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

Wrong transition animation when values indirectly updated right before start #5426

Open
Justyna-JustCode opened this issue Jun 18, 2024 · 4 comments
Labels
a:tool classes & property system runtime core classes (SharedVector,SharedString) and property system (mO,bS) bug Something isn't working priority:low Lowest priority. The issue is kept open for tracking purpose, but noone is actively working on this

Comments

@Justyna-JustCode
Copy link

Slint 1.6 + Rust

I noticed that values used for a transition animation are wrong if the property value is indirectly updated right before the transition is triggered.

Example code:

    Rectangle {
        property <bool> expanded: false;
        property <length> start-y: 70% * parent.height;

        background: red;
        height: 30%;
        y: self.start-y;

        states [
            expanded when self.expanded: {
                height: 100%;
                y: 0;

                in { animate y, height { duration: 1s; } }
                out { animate y, height { duration: 300ms; } }
            }
        ]

        TouchArea {
            clicked => {
                parent.start-y = 30% * parent.height;
                // parent.y; // <- required for the animation to work properly
                parent.expanded = !parent.expanded;
            }
        }
    }

Initially, the red rectangle is placed at the very bottom of the window. However, when clicked, the position is updated, and the expanded state is enabled (with the transition triggered).

My expectation for the code is that after clicking on the rectangle, it is firstly moved to the proper position (30% * parent.height) and then expanded. In reality, the rectangle is expanded from the initial bottom position.

It seems like the value of y will not yet be updated when the transition starts. If the y property is set directly (not via the start-y property), the problem is gone. Another workaround is to access the y property before triggering state change (see the commented line).

Actual: Expected:
expand-bug-actual expand-bug-expected
@ogoffart
Copy link
Member

Thanks for filling a bug.

The thing is that the binding evaluation is lazy, and the animation starts from the last evaluated value.

So in summary, the binding for your property is (pseudo-code):

y: !self.expanded ? self.start-y : 'state-animation-to'(0);

when you change the value of start-y, the value of y is marked as dirty but not re-evaluated yet.
If you don't query the value before changing the state, the state animation will start at the last computed value of the property.

You found the work around which is to query that property before the animation start.
One change we could do is re-evaluate the property of the previous state before as the start of the animation. But that also might not be correct :-/

Slightly related is #4811 in which animation restarts with an outdated value.

@ogoffart ogoffart added bug Something isn't working a:tool classes & property system runtime core classes (SharedVector,SharedString) and property system (mO,bS) priority:low Lowest priority. The issue is kept open for tracking purpose, but noone is actively working on this labels Jun 24, 2024
@Justyna-JustCode
Copy link
Author

Thanks for your reply!

One change we could do is re-evaluate the property of the previous state before as the start of the animation. But that also might not be correct :-/

This is precisely what I would expect. Could you elaborate on why you think it might not be correct? I can't think of any example. If the property is already marked dirty when the transition starts, it was changed before the transition was triggered. In my opinion, the order here implies that the transition should use the updated value.

When I access (query) the value, it gets updated. But the animation also (well, conceptually) queries the value to know what to start from. So, the behavior should be the same.

Am I missing something? 😉

@ogoffart
Copy link
Member

ogoffart commented Jun 24, 2024

The case i'm thinking about is this:

states [
  A when ...: { p: 0; in => { animate p { duration 1s } }
  B when ...: { p: 100; in => { animate p { duration 1s } }
]
  • state A is active, p is 0.
  • state B becomes active, p is set to animate from 0 to 100 in 1s. animations start
  • after 0.5s, state A becomes active again and want to set the property back to 0.

When we change back from B to A, the property p is dirty because the time changes. But we don't want to re-evaluate the start position of state B either.

@Justyna-JustCode
Copy link
Author

I might be missing or misunderstanding something, and I don't know the implementation details.
But:

When we change back from B to A, the property p is dirty because the time changes.

The p property is dirty because it was updated by the B-state transition (which seems good). When we switch back to state A, we should use the latest property value as a start position (right?). So, the dirty state should be taken into consideration, and the property value should be evaluated before the A-state transition starts.

But we don't want to re-evaluate the start position of state B either.

Why do we consider B at all? Shouldn't the B-state animation just stop (be aborted) when we switch back to state A?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a:tool classes & property system runtime core classes (SharedVector,SharedString) and property system (mO,bS) bug Something isn't working priority:low Lowest priority. The issue is kept open for tracking purpose, but noone is actively working on this
Projects
None yet
Development

No branches or pull requests

2 participants