vizia_core/systems/
animation.rs

1use morphorm::Node;
2
3use crate::{layout::node::SubLayout, prelude::*};
4
5macro_rules! process_auto_animations {
6    ($cx:expr, $property:expr, $height:expr) => {
7        if let Some(animations) = $property.get_active_animations() {
8            let mut entities = vec![];
9
10            for animation in animations {
11                if animation.keyframes.iter().any(|keyframe| keyframe.value == Units::Auto) {
12                    for entity in animation.entities.iter() {
13                        entities.push((*entity, animation.clone()));
14                    }
15                }
16            }
17
18            for (entity, mut animation) in entities {
19                $property.stop_animation(entity, animation.id);
20                $property.insert(entity, Units::Auto);
21
22                let size = entity.layout(
23                    &mut $cx.cache,
24                    &$cx.tree,
25                    &$cx.style,
26                    &mut SubLayout {
27                        text_context: &mut $cx.text_context,
28                        resource_manager: &$cx.resource_manager,
29                    },
30                );
31
32                $property.remove(entity);
33                animation.keyframes.iter_mut().for_each(|keyframe| {
34                    if keyframe.value == Units::Auto {
35                        let parent = $cx.tree.get_parent(entity).unwrap_or(Entity::root());
36                        let parent_layout_type =
37                            $cx.style.layout_type.get(parent).copied().unwrap_or_default();
38                        let value = if (parent_layout_type == LayoutType::Row) == $height {
39                            size.cross
40                        } else {
41                            size.main
42                        };
43                        keyframe.value = Units::Pixels(value);
44                    }
45                });
46
47                let id = $cx.style.animation_manager.create();
48                $property.insert_animation(id, animation.clone());
49                $property.play_animation(
50                    entity,
51                    id,
52                    animation.start_time,
53                    animation.duration,
54                    animation.delay,
55                );
56            }
57        }
58    };
59}
60
61pub(crate) fn animation_system(cx: &mut Context) -> bool {
62    cx.style.play_pending_animations();
63
64    process_auto_animations!(cx, cx.style.max_height, true);
65    process_auto_animations!(cx, cx.style.max_width, false);
66    process_auto_animations!(cx, cx.style.height, true);
67    process_auto_animations!(cx, cx.style.width, false);
68
69    // if let Some(animations) = cx.style.max_height.get_active_animations() {
70    //     let mut entities = vec![];
71
72    //     for animation in animations {
73    //         if animation.keyframes.iter().any(|keyframe| keyframe.value == Units::Auto) {
74    //             for entity in animation.entities.iter() {
75    //                 entities.push((*entity, animation.clone()));
76    //             }
77    //         }
78    //     }
79
80    //     for (entity, mut animation) in entities {
81    //         cx.style.max_height.stop_animation(entity, animation.id);
82    //         cx.style.max_height.insert(entity, Units::Auto);
83
84    //         let size = entity.layout(
85    //             &mut cx.cache,
86    //             &cx.tree,
87    //             &cx.style,
88    //             &mut SubLayout {
89    //                 text_context: &mut cx.text_context,
90    //                 resource_manager: &cx.resource_manager,
91    //             },
92    //         );
93
94    //         cx.style.max_height.remove(entity);
95    //         animation.keyframes.iter_mut().for_each(|keyframe| {
96    //             if keyframe.value == Units::Auto {
97    //                 keyframe.value = Units::Pixels(size.main);
98    //             }
99    //         });
100
101    //         let id = cx.style.animation_manager.create();
102    //         cx.style.max_height.insert_animation(id, animation.clone());
103    //         cx.style.max_height.play_animation(
104    //             entity,
105    //             id,
106    //             animation.start_time,
107    //             animation.duration,
108    //             animation.delay,
109    //         );
110    //     }
111    // }
112
113    // Tick all animations
114
115    let time = Instant::now();
116
117    let mut redraw_entities = Vec::new();
118    let mut reflow_entities = Vec::new();
119    let mut relayout_entities = Vec::new();
120
121    // Properties which affect rendering
122    // Opacity
123    redraw_entities.extend(cx.style.opacity.tick(time));
124    // Corner Colour
125    redraw_entities.extend(cx.style.border_color.tick(time));
126    // Corner Radius
127    redraw_entities.extend(cx.style.corner_top_left_radius.tick(time));
128    redraw_entities.extend(cx.style.corner_top_right_radius.tick(time));
129    redraw_entities.extend(cx.style.corner_bottom_left_radius.tick(time));
130    redraw_entities.extend(cx.style.corner_bottom_right_radius.tick(time));
131    // Background
132    redraw_entities.extend(cx.style.background_color.tick(time));
133    redraw_entities.extend(cx.style.background_image.tick(time));
134    redraw_entities.extend(cx.style.background_size.tick(time));
135    // Box Shadow
136    redraw_entities.extend(cx.style.shadow.tick(time));
137    // Transform
138    redraw_entities.extend(cx.style.transform.tick(time));
139    redraw_entities.extend(cx.style.transform_origin.tick(time));
140    redraw_entities.extend(cx.style.translate.tick(time));
141    redraw_entities.extend(cx.style.rotate.tick(time));
142    redraw_entities.extend(cx.style.scale.tick(time));
143    // Outline
144    redraw_entities.extend(cx.style.outline_color.tick(time));
145    redraw_entities.extend(cx.style.outline_offset.tick(time));
146    redraw_entities.extend(cx.style.outline_width.tick(time));
147    // Clip Path
148    redraw_entities.extend(cx.style.clip_path.tick(time));
149
150    redraw_entities.extend(cx.style.fill.tick(time));
151
152    // Font Color
153    reflow_entities.extend(cx.style.font_color.tick(time));
154    // Font Size
155    reflow_entities.extend(cx.style.font_size.tick(time));
156
157    // Properties which affect layout
158    relayout_entities.extend(cx.style.display.tick(time));
159    // Border Width
160    relayout_entities.extend(cx.style.border_width.tick(time));
161    // Space
162    relayout_entities.extend(cx.style.left.tick(time));
163    relayout_entities.extend(cx.style.right.tick(time));
164    relayout_entities.extend(cx.style.top.tick(time));
165    relayout_entities.extend(cx.style.bottom.tick(time));
166    // Size
167    relayout_entities.extend(cx.style.width.tick(time));
168    relayout_entities.extend(cx.style.height.tick(time));
169    // Min/Max Size
170    relayout_entities.extend(cx.style.max_width.tick(time));
171    relayout_entities.extend(cx.style.max_height.tick(time));
172    relayout_entities.extend(cx.style.min_width.tick(time));
173    relayout_entities.extend(cx.style.min_height.tick(time));
174    // Min/Max Gap
175    relayout_entities.extend(cx.style.max_horizontal_gap.tick(time));
176    relayout_entities.extend(cx.style.max_vertical_gap.tick(time));
177    relayout_entities.extend(cx.style.min_horizontal_gap.tick(time));
178    relayout_entities.extend(cx.style.min_vertical_gap.tick(time));
179    // Row/Col Between
180    relayout_entities.extend(cx.style.vertical_gap.tick(time));
181    relayout_entities.extend(cx.style.horizontal_gap.tick(time));
182    // Child Space
183    relayout_entities.extend(cx.style.padding_left.tick(time));
184    relayout_entities.extend(cx.style.padding_right.tick(time));
185    relayout_entities.extend(cx.style.padding_top.tick(time));
186    relayout_entities.extend(cx.style.padding_bottom.tick(time));
187
188    if !relayout_entities.is_empty() {
189        cx.style.system_flags.set(SystemFlags::RELAYOUT, true);
190    }
191
192    for entity in redraw_entities.iter() {
193        cx.needs_redraw(*entity);
194    }
195
196    for entity in reflow_entities.iter() {
197        cx.style.text_construction.insert(*entity).unwrap();
198    }
199
200    !redraw_entities.is_empty() | !relayout_entities.is_empty() | !reflow_entities.is_empty()
201}