Skip to content

Commit

Permalink
Property Animations (vizia#76)
Browse files Browse the repository at this point in the history
* Make bindings the parent of their contents and remove children when updating

Rename perf test to a permanent fixture

Hack around textbox expecting bindings to not be parents

Incredibly low-effort implementation of attribute bindings

Make lenses fallible, again!

fix captured widget being destroyed but not releasing its status as captured

Make bindings ignored by layout

* Remove Display::Contents; only use tree.is_ignored()

* Final fixes for determining layout ancestry; add test for layout iter

* Fix warnings

* Allow prop setters to take a lens and generate a binding

* Fix slider, knob, and label

* Fix popup and dropdown

* Fmt and fix warnings

* Add some more safeguards for fallible lenses

* Allow deriving Lens on enums!

* fmt

* Remove debug print

* Add `TreeDepthIterator` for debugging + Fix `overflow` not being removed when entity is removed

* Fix warnings

* Quick fix for text autosize glitch

* Fix property bindings replacing first child of view

* Fix textbox_list

* Add concept of 'duplicated' and 'deduplicated' lenses

* Remove observer from stored lenses when entity is removed. Remove stored lenses when they have no observers.

+ fmt and warnings fix

* Quick fix for panic when removing list items in crud example

* Start adding style transitions

* Apply animations after styling

* Make opacity animatable and update default style for popups

* fmt

* Add transitions to default theme

* Animate all animatable properties

* Clean up style module and rename theme.rs to parser.rs

* Update context.rs

* Add animation builder

* Small style changes

* Fix animations to reset unless persistent

* Fmt

* Fix warnings

* Actually fix the warnings this time

* Changes to radiobutton widget. Fixes transitions when animation is already playing.

* fmt+ fix warnings

Co-authored-by: Audrey Dutcher <[email protected]>
  • Loading branch information
geom3trik and rhelmot authored Mar 18, 2022
1 parent 519818d commit 4c60371
Show file tree
Hide file tree
Showing 33 changed files with 819 additions and 1,443 deletions.
20 changes: 20 additions & 0 deletions baseview/src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,26 @@ impl ApplicationRunner {
}

self.context.process_data_updates();
self.context.process_style_updates();

// if self.context.has_animations() {
// if let Some(window_event_handler) = self.context.views.remove(&Entity::root()) {
// if let Some(window) = window_event_handler.downcast_ref::<Window>() {
// window.handle.window().request_redraw();
// }

// context.views.insert(Entity::root(), window_event_handler);
// }
// } else {
// if should_poll {
// *control_flow = ControlFlow::Poll;
// } else {
// *control_flow = ControlFlow::Wait;
// }
// }

self.context.apply_animations();

self.context.process_visual_updates();

if self.context.style.needs_redraw {
Expand Down
97 changes: 46 additions & 51 deletions core/src/animation/anim_ext.rs
Original file line number Diff line number Diff line change
@@ -1,92 +1,87 @@
use crate::{Animation, AsEntity, State};
use crate::{Animation, AsEntity, Context};

/// Trait which provides methods for entities to manipulate linked animations
pub trait AnimExt: AsEntity + Sized {

/// Play an animation on the entity.
///
/// Internally this generates an active animation and links the entity to it for each animated property.
///
/// # Example
/// Create an animation which animates the `left` property from 0 to 100 pixels in 5 seconds
/// Create an animation which animates the `left` property from 0 to 100 pixels in 5 seconds
/// and play the animation on an entity:
/// ```
/// let animation_id = state.create_animation(instant::Duration::from_secs(5))
/// ```ignore
/// let animation_id = cx.create_animation(instant::Duration::from_secs(5))
/// .add_keyframe(0.0, |keyframe| keyframe.set_left(Pixels(0.0)))
/// .add_keyframe(1.0, |keyframe| keyframe.set_left(Pixels(100.0)))
/// .build();
/// .build();
///
/// entity.play_animation(state, animation_id);
/// entity.play_animation(cx, animation_id);
/// ```
fn play_animation(self, state: &mut State, animation: Animation) -> Self {

fn play_animation(self, cx: &mut Context, animation: Animation) -> Self {
// Background
state.style.background_color.play_animation(self.entity(), animation);
cx.style.background_color.play_animation(self.entity(), animation);

// Space
state.style.left.play_animation(self.entity(), animation);
state.style.right.play_animation(self.entity(), animation);
state.style.top.play_animation(self.entity(), animation);
state.style.bottom.play_animation(self.entity(), animation);
cx.style.left.play_animation(self.entity(), animation);
cx.style.right.play_animation(self.entity(), animation);
cx.style.top.play_animation(self.entity(), animation);
cx.style.bottom.play_animation(self.entity(), animation);

// Min/Max Space
state.style.min_left.play_animation(self.entity(), animation);
state.style.min_right.play_animation(self.entity(), animation);
state.style.min_top.play_animation(self.entity(), animation);
state.style.min_bottom.play_animation(self.entity(), animation);
state.style.max_left.play_animation(self.entity(), animation);
state.style.max_right.play_animation(self.entity(), animation);
state.style.max_top.play_animation(self.entity(), animation);
state.style.max_bottom.play_animation(self.entity(), animation);
cx.style.min_left.play_animation(self.entity(), animation);
cx.style.min_right.play_animation(self.entity(), animation);
cx.style.min_top.play_animation(self.entity(), animation);
cx.style.min_bottom.play_animation(self.entity(), animation);
cx.style.max_left.play_animation(self.entity(), animation);
cx.style.max_right.play_animation(self.entity(), animation);
cx.style.max_top.play_animation(self.entity(), animation);
cx.style.max_bottom.play_animation(self.entity(), animation);

// Child Space
state.style.child_left.play_animation(self.entity(), animation);
state.style.child_right.play_animation(self.entity(), animation);
state.style.child_top.play_animation(self.entity(), animation);
state.style.child_bottom.play_animation(self.entity(), animation);
cx.style.child_left.play_animation(self.entity(), animation);
cx.style.child_right.play_animation(self.entity(), animation);
cx.style.child_top.play_animation(self.entity(), animation);
cx.style.child_bottom.play_animation(self.entity(), animation);

// Size
state.style.width.play_animation(self.entity(), animation);
state.style.height.play_animation(self.entity(), animation);
cx.style.width.play_animation(self.entity(), animation);
cx.style.height.play_animation(self.entity(), animation);

// Min/Max Size
state.style.min_width.play_animation(self.entity(), animation);
state.style.min_height.play_animation(self.entity(), animation);
state.style.max_width.play_animation(self.entity(), animation);
state.style.max_height.play_animation(self.entity(), animation);
cx.style.min_width.play_animation(self.entity(), animation);
cx.style.min_height.play_animation(self.entity(), animation);
cx.style.max_width.play_animation(self.entity(), animation);
cx.style.max_height.play_animation(self.entity(), animation);

// Border
state.style.border_color.play_animation(self.entity(), animation);
state.style.border_width.play_animation(self.entity(), animation);
state.style.border_radius_bottom_left.play_animation(self.entity(), animation);
state.style.border_radius_top_left.play_animation(self.entity(), animation);
state.style.border_radius_bottom_right.play_animation(self.entity(), animation);
state.style.border_radius_top_right.play_animation(self.entity(), animation);
cx.style.border_color.play_animation(self.entity(), animation);
cx.style.border_width.play_animation(self.entity(), animation);
cx.style.border_radius_bottom_left.play_animation(self.entity(), animation);
cx.style.border_radius_top_left.play_animation(self.entity(), animation);
cx.style.border_radius_bottom_right.play_animation(self.entity(), animation);
cx.style.border_radius_top_right.play_animation(self.entity(), animation);

// Transform
state.style.rotate.play_animation(self.entity(), animation);
// state.style.translate.play_animation(self.entity(), animation);
state.style.scale.play_animation(self.entity(), animation);
cx.style.rotate.play_animation(self.entity(), animation);
// cx.style.translate.play_animation(self.entity(), animation);
cx.style.scale.play_animation(self.entity(), animation);

// Display
state.style.opacity.play_animation(self.entity(), animation);

cx.style.opacity.play_animation(self.entity(), animation);

self
}

/// Returns true if there is an active animation with the given id.
///
///
/// # Example
/// ```
/// ```ignore
/// let test = entity.is_animation(animation_id);
/// ```
fn is_animating(self, state: &mut State, animation: Animation) -> bool {
state.style.height.is_animating(self.entity(), animation) ||
state.style.width.is_animating(self.entity(), animation)
fn is_animating(self, cx: &mut Context, animation: Animation) -> bool {
cx.style.height.is_animating(self.entity(), animation)
|| cx.style.width.is_animating(self.entity(), animation)
}
}

impl<T: AsEntity> AnimExt for T {

}
impl<T: AsEntity> AnimExt for T {}
Loading

0 comments on commit 4c60371

Please sign in to comment.