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

Changing the data on every frame #1060

Closed
jneem opened this issue Jun 25, 2020 · 9 comments · Fixed by #1155
Closed

Changing the data on every frame #1060

jneem opened this issue Jun 25, 2020 · 9 comments · Fixed by #1155
Labels
discussion needs feedback and ideas enhancement adds or requests a new feature

Comments

@jneem
Copy link
Collaborator

jneem commented Jun 25, 2020

I'm working on an animation program, and I'm keeping the current time of the animation in my Data. While playing back the animation, I want to update the data on every frame, but I can't find a good way to do this right now.

Originally, I was firing a timer every 16ms, but the druid-shell docs (the druid docs is missing this warning, but I'll submit a PR) suggest that it isn't a good idea. Empirically, it works well on GTK but poorly on windows.

I switched to using AnimFrame, but since lifecycle can't modify the data directly I had to (as suggested in the docs) change the data indirectly through a command. Unfortunately, the change to the data doesn't happen until the following frame (and sometimes not even until the one after -- I've recorded delays of up to 30ms). This method works better than the timer method on Windows, but is noticeably worse on GTK.

Could there be a reliable way to change the data just before drawing the frame?

@raphlinus
Copy link
Contributor

It's a good question. Originally AnimFrame was an event, which can modify the data. Definitely firing a timer is the wrong thing to do.

The general approach to not being able to mutate the data is to send a Command. Would this work for you? It seems strictly less hacky than the timer idea.

@jneem
Copy link
Collaborator Author

jneem commented Jun 25, 2020 via email

@raphlinus
Copy link
Contributor

I'm not sure why a command would have smoothness problems, I think that might be worth investigating. It's supposed to basically be synchronous wrt the runloop.

@jneem
Copy link
Collaborator Author

jneem commented Jun 25, 2020

It turns out that 90% of the jank was caused by update failing to run after the command -- I'll send a PR. I'm still occasionally dropping frames, though: I sometimes see two paint calls in a row, with no command delivered in between. Wild guess: because I'm getting lots of events, GTK doesn't manage to schedule the idle handler in between every pair of frames. I haven't managed to reproduce this on a minimal example yet, though.

@cmyr
Copy link
Member

cmyr commented Jun 25, 2020

This is currently an intentional design decision; Data should not include display-specific state. If you think this is a misstep, I would be happy to discuss it. :)

@jneem
Copy link
Collaborator Author

jneem commented Jun 25, 2020

I don't disagree with the design decision, but I don't think that the current time in my animation is display-specific state. For example, if I draw an extra line in my animation, it should appear, in the animation, at the time that is currently being displayed. Therefore, I think the current time is an integral part of my application state.

Just to be clear, by "current time" I don't mean the wall clock time, but rather something like "1.78 seconds since the start of the animation"

@cmyr
Copy link
Member

cmyr commented Jun 25, 2020

So the eventual next API for animations will work more like this, where you schedule an animation with a given duration and you have access to that duration when the animation ticks. I think for now though it would make more sense to stash this duration in your widget?

@jneem
Copy link
Collaborator Author

jneem commented Jun 25, 2020

To be clear, this is a program for creating animations, so when I say "animation", I don't mean a transient animation displayed by the UI. Maybe it would be clearer to pretend I'm making a video-editing program, because "video" is less overloaded in this context.

Now that I'm talking about videos, I can't easily store the current video position in my widget because it's needed all over the widget tree. For example, I have a little clock at the bottom-left telling me what the current position is, and I have a timeline with a cursor indicating the current position. Also, many of the commands that cause changes to the video need to know what the current position is. I really think that the current position is a natural part of the application state. It's like saying that the cursor location is part of the application state for a text editor.

@cmyr
Copy link
Member

cmyr commented Jun 26, 2020

Okay, that's interesting.

@luleyleo luleyleo added discussion needs feedback and ideas enhancement adds or requests a new feature labels Jun 28, 2020
jneem added a commit that referenced this issue Sep 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion needs feedback and ideas enhancement adds or requests a new feature
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants