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

Style updates causing Transition restart without re-render() #24

Closed
ChristopherBiscardi opened this issue Jul 26, 2024 · 1 comment
Closed

Comments

@ChristopherBiscardi
Copy link
Collaborator

Repo

I've extracted a custom TransitionTimer and Button widget to a repo for reproduction: https://github.com/ChristopherBiscardi/woodpecker_buttons_repro

Behavior

By default in the repo, because there is a mutation of WoodpeckerStyle from the main_menu_interaction system, the Transitions re-occur constantly, seemingly due to re-initializing the values which in turn causes the timers to run, etc.

screenshot-2024-07-26-at-13.24.24.mp4

commenting that single line out shows a different behavior, that only re-starts the Transition when the window resizes.

screenshot-2024-07-26-at-13.25.49.mp4

From an implementation point of view, this style update is unrelated to the Transition behavior and should not cause the TransitionTimer to re-start.

Desired Behavior

I want to animated two solid color bars across the area the button will show in, spawning in the button behind these bars during the animation similar to a "stinger" transition. Once the Transition is over, I never want it to happen again.

Additionally, I want to have hover states affect the styles on the button after the Transition is over. Implementing these hover states is where I started to run into issues (specifically, the style mutation).

More details

The goal of the button is to play two solid color bars across the button surface area the first time it renders, revealing the content underneath. It currently achieves this through a custom TransitionTimer component that accepts a vec of styles and a vec of timers. Each element in the widget is then animated multiple times using these timers, lerp, and a mutation of the WoodpeckerStyle (basically the same logic as the current built-in Transition).

In a future implementation, I'd like this "Stinger" entrance behavior to be its own encapsulated behavior that I can add to a variety of widgets. I'm probably also going to try to take advantage of clipping so that the reveal is all left-to-right whereas currently it is first block left->right, second block left->right, second block right->left.

Questions

In React (and some other UI frameworks), the render function re-runs any time there are props or state updates. This is not the case when the WoodpeckerStyle component is updated, so there is clearly a "second render function" to think about (ie: vello) from that perspective. What is the mental model for the Widget::render function given these additional rendering updates, and in conjunction with the new hooks/state functionality?

I think answers to that then follow on with "should TransitionTimer and PickingInteraction drive widget state" and "how do arbitrary Component values on the entity relate to props/state/etc and when should each be used".

@ChristopherBiscardi
Copy link
Collaborator Author

The fix is in this commit: ChristopherBiscardi/woodpecker_buttons_repro@d102e4b

screenshot-2024-07-26-at-15.43.57.mp4

It ended up that I was updating the inner container of the widget, which caused all children to re-render, re-creating the TransitionTimers. Note that this re-render never caused MainMenuButtonWidget::render to be called, which is fine (it doesn't need to).

If anyone stumbles across this in the future, first: enable trace-level logging for woodpecker and see what you can find.

RUST_LOG=woodpecker_ui=trace cargo run

I ended up figuring this out by adding names to all of the components, and logging out those names in association with layout behavior in the runner. Specifically runner::update_widgets and the built-in Element's own update.

I think there's some interesting opportunity for debug systems that expose this kind of data in the future, but Woodpecker is behaving correctly. It was my own code in the end that had the bug.

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

No branches or pull requests

1 participant