diff --git a/src/textual/_animator.py b/src/textual/_animator.py index 08620bcd9..d0fc2aa80 100644 --- a/src/textual/_animator.py +++ b/src/textual/_animator.py @@ -51,37 +51,35 @@ class SimpleAnimation(Animation): def __call__(self, time: float) -> bool: if self.duration == 0: - value = self.final_value - else: - factor = min(1.0, (time - self.start_time) / self.duration) - eased_factor = self.easing(factor) + setattr(self.obj, self.attribute, self.final_value) + return True - if factor == 1.0: - value = self.final_value - elif isinstance(self.start_value, Animatable): - assert isinstance( - self.end_value, Animatable - ), "end_value must be animatable" - value = self.start_value.blend(self.end_value, eased_factor) + factor = min(1.0, (time - self.start_time) / self.duration) + eased_factor = self.easing(factor) + + if factor == 1.0: + value = self.final_value + elif isinstance(self.start_value, Animatable): + assert isinstance( + self.end_value, Animatable + ), "end_value must be animatable" + value = self.start_value.blend(self.end_value, eased_factor) + else: + assert isinstance(self.start_value, float), "`start_value` must be float" + assert isinstance(self.end_value, float), "`end_value` must be float" + if self.end_value > self.start_value: + eased_factor = self.easing(factor) + value = ( + self.start_value + + (self.end_value - self.start_value) * eased_factor + ) else: - assert isinstance( - self.start_value, float - ), "`start_value` must be float" - assert isinstance(self.end_value, float), "`end_value` must be float" - if self.end_value > self.start_value: - eased_factor = self.easing(factor) - value = ( - self.start_value - + (self.end_value - self.start_value) * eased_factor - ) - else: - eased_factor = 1 - self.easing(factor) - value = ( - self.end_value - + (self.start_value - self.end_value) * eased_factor - ) + eased_factor = 1 - self.easing(factor) + value = ( + self.end_value + (self.start_value - self.end_value) * eased_factor + ) setattr(self.obj, self.attribute, value) - return value == self.final_value + return factor >= 1 class BoundAnimator: diff --git a/tests/test_animator.py b/tests/test_animator.py index 2814c048f..e64a50ae5 100644 --- a/tests/test_animator.py +++ b/tests/test_animator.py @@ -22,7 +22,7 @@ class Animatable: @dataclass class AnimateTest: - """An object to animate.""" + """An object with animatable properties.""" foo: float | None = 0 # Plain float that may be set to None on final_value bar: Animatable = Animatable(0) # A mock object supporting the animatable protocol @@ -49,6 +49,8 @@ def test_simple_animation(): easing=lambda x: x, ) + assert animatable.foo == 0.0 + assert animation(time) is False assert animatable.foo == 20.0 @@ -58,7 +60,7 @@ def test_simple_animation(): assert animation(time + 2.0) is False assert animatable.foo == 40.0 - assert animation(time + 2.9) is False + assert animation(time + 2.9) is False # Not quite final value assert pytest.approx(animatable.foo, 49.0) assert animation(time + 3.0) is True # True to indicate animation is complete @@ -89,7 +91,7 @@ def test_simple_animation_duration_zero(): easing=lambda x: x, ) - assert animation(time) is True + assert animation(time) is True # Duration is 0, so this is last value assert animatable.foo == 50.0 assert animation(time + 1.0) is True