bluecadet / Cinder-BluecadetViews

Scene graph Cinder block with touch management and various tools for UI dev
MIT License
11 stars 3 forks source link

Add fine grain control over view's timelines "current time" #144

Open monsieurgustav opened 4 years ago

monsieurgustav commented 4 years ago

(First of all: I've just found out your framework, it is great!)

Cinder timelines have precision issues after few hours, because the current time is stored as a float. (going double would add days but would not solve the inner issue) To mitigate the issue, reset the current time regularly (when no animation is playing) works.

Views have their own local timeline to manage property animation, but they are all slaves (generally of the app timeline) because they all use the same absoluteTime. One cannot reset timelines lying in some part of the scene graph.

It's not even trivial to do so on the complete scene graph: one need to copy the BaseApp::update() implementation to pass another absoluteTime value. Or just don't use RootView completly.

How do you handle long-run applications?

benjaminbojko commented 4 years ago

@monsieurgustav thanks for the suggestion!

It shouldn't be too hard to expose a central value and there could be a way to already accomplish what you need w/o any modifications.

Currently, all views get the same FrameInfo value passed through via BaseView::updateScene() which contains the time used for all timelines: https://github.com/bluecadet/Cinder-BluecadetViews/blob/develop/src/bluecadet/core/BaseApp.cpp#L70-L85

It's possible to override this value for a subtree in your scene graph by overriding updateScene():

//(untested code off the top of my head)
MyView::updateScene(const FrameInfo & info) {
    FrameInfo customInfo(info);
    customInfo.absoluteTime = 0.0f; // reset here
    BaseView::updateScene(customInfo);
}

Since the default value comes from BaseApp at a central location, we could add an optional override for that value. What do you think would be most helpful?

FWIW: Generally, we've been considering moving to a multi-scene model, where your app can have scenes with their own scene graphs, and each scene would handle that kind of logic more explicitly rather than it being tucked within BaseApp.

As a safety measure, most of our permanent installations are programmed to reboot nightly to prevent issues like these and to account for any OS-related pileup, but that's not always an option, so we'd be happy to formalize something like this in this block.

monsieurgustav commented 4 years ago

Having a dedicated view to handle this is an interesting suggestion! It's a little weird to have a "view" to handle time issues, but it's also very practical.

Another way of thinking it, maybe: use relative time instead of absolute. (ie: use Timeline::step() instead of stepTo) Then, some timelines could be reset while others would continue normally. But that's probably some more work!

monsieurgustav commented 4 years ago

Hi Benjamin, I'm about to implement my "TimelineScopeView" as you suggest. I stumble upon the BaseView::getTimeline(bool stepToNow) function.

As the argument suggests, this function may call advanceTimeline, using again the app timeline current time. It obviously obliterate my attempt to control the current time in a subtree. :)

I previously had another issue with this function: I called it in a "finish" function of an animation, to clean some stuff. It resulted in seg fault because

I plan to remove the advanceTimeline call from getTimeline, because it causes painful issues and I don't see why it's there in the first place... Can you tell me if it may break something ?

Cheers,

Guillaume