The issue was that my last set of changes were causing the animations to
restart, causing the animation to keep being extended to another 150ms.
I think the only way for this to work is to switch to an event
mechanism to notify widgets once they've been invalidated. This event
could include a parameter stating whether it was a direct invalidation
or an invalidation due to another widget in the hierarchy. Button
doesn't really care about the rest of the hierarchy, it only cares about
its own state, and the cache key was including too many changes.
This also fixes some inconsistencies that arose when the focus widget
was "stuck" on a removed widget. Button previously handled it hackily in
a redraw function, but now Gooey handles it automatically without
needing to wait for a repaint.
Given the goal of this function, I'm not sure it can get more optimal
than this even with specialized data structures like KD-trees. The
problem is that we want all widgets that are hovered, not just some, and
that makes nearest neighbor useless.
The main optimizations here are simple:
- Group up all the render data we need in a single vec to help cache.
- Precompute the rect's extents to make the contains check at most 4
comparisons.
This had a noticable effect on the "wiggle the mouse frantically"
performance, where Gooey isn't actually repainting but is routing mouse
events.
measure() now is layout(). LayoutContext can either persist layout
information or be used temporarily for measurement. While this caching
is constantly thrown out currently, this is a step towards being able to
only re-layout widgets if they've been invalidated.