Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rework how clipping rects are calculated. fixes #149 #210

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

msparkles
Copy link
Contributor

No description provided.

@msparkles msparkles requested a review from LPGhatguy as a code owner February 25, 2025 14:34
@LPGhatguy
Copy link
Member

Thanks for taking a look at this! I know you've been fighting clipping for a bit.

It's a great idea to allow widgets to break out of the clip stack. Tooltips and dropdowns are a good case of when that's appropriate. I like that this PR enables a good escape hatch for that.

It looks like this PR also makes every widget always clip its children by default though! I don't think that behavior is desirable; the vast majority of widgets don't draw outside of their parent container anyways. This is kind of like overflow: visible vs overflow: hidden in CSS — visible is the default, probably for debuggability. I'd like clipping your children to stay a conscious choice.

Maybe more interestingly, clipping every widget also breaks yakui's draw call batching because we need to insert a set_scissor_rect whenever changing the clip region right now. I think the "right" solution to that problem is to clip the geometry ourselves, like in a compute shader, and then blast everything out in one go.

Do you think we can preserve the push/pop nature of the "clip stack" while also letting widgets break out?

Could we accomplish the same result by just changing the clip stack to hold an enum similar to the one you made, like this?

enum ClipEntry {
    Rect(Rect),
    FullViewport,
}

@msparkles
Copy link
Contributor Author

Yeah that should be easily doable! We weren't sure your opinion on that behaviour, so we went with what we found was easy.

Didn't know about the batching! We'll try to unbork that.

We think that something like this would work perfectly:

enum ClipEntry {
    InheritParent, // default behaviour
    WithLayoutRect,
    FullViewport,
    Resolved(Rect),
}

Naming is a WIP, but ultimately, we intentionally reworked the clipping resolution to be flexible, the logic of resolving clip rects at every widget will remain the same, but you can choose between:

  • InheritParent: just inherit the parent's clipping. this will effectively mean that unless something explicitly uses WithLayoutRect, everything will be clipped to viewport instead, effectively nullifying the "everything always clips its children" issue by rephrasing the problem- everything still does clip its children always, it's just that in the clipping resolution it'll just use whatever the parent's clip already was.
    • Though, how would hit_test be changed in accordance to this, we're not sure.
  • WithLayoutRect: constrains the layout rect with the parent's clipping, so effectively the behaviour of clipping its children
  • FullViewport: what it says on the tin
  • we think we'll keep Resolved around? do you think we should keep a separate list of resolved clipping rects? the idea is that if there ever comes a time someone needs it, we can also allow widgets to completely override the clipping rect, and Resolved would still be fitting because it means you've already "resolved" the clipping rect elsewhere yourself by setting an override.

Let us know what you think

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants