aura_anim_core/
presence.rs1use crate::{
4 runtime::{Motion, MotionError, MotionEvent, MotionRuntime, PlaybackId},
5 timing::Timing,
6 traits::{Animatable, IntoMotionAnimation},
7};
8
9pub struct Presence<T: Animatable> {
31 motion: Motion<T>,
32 visible: T,
33 hidden: T,
34 mounted: bool,
35 shown: bool,
36 exit_playback: Option<PlaybackId>,
37}
38
39impl<T: Animatable> Presence<T> {
40 #[must_use]
42 pub fn new(runtime: &mut MotionRuntime, hidden: T, visible: T, timing: Timing) -> Self {
43 Self {
44 motion: runtime.motion_with(hidden.clone(), timing),
45 visible,
46 hidden,
47 mounted: false,
48 shown: false,
49 exit_playback: None,
50 }
51 }
52
53 pub fn motion(&self) -> Motion<T> {
55 self.motion
56 }
57
58 pub fn value<'a>(&self, runtime: &'a MotionRuntime) -> Result<&'a T, MotionError> {
60 self.motion.value_ref(runtime)
61 }
62
63 #[must_use]
65 pub const fn is_mounted(&self) -> bool {
66 self.mounted
67 }
68
69 #[must_use]
71 pub const fn is_visible(&self) -> bool {
72 self.shown
73 }
74
75 pub fn set_visible(
80 &mut self,
81 visible: bool,
82 runtime: &mut MotionRuntime,
83 ) -> Result<bool, MotionError> {
84 if self.shown == visible {
85 #[cfg(feature = "tracing")]
86 tracing::trace!(
87 target: "aura_anim::presence",
88 value_type = std::any::type_name::<T>(),
89 mounted = self.mounted,
90 shown = self.shown,
91 "presence visibility is unchanged"
92 );
93 return Ok(false);
94 }
95
96 if visible {
97 self.show(runtime)?;
98 } else {
99 self.hide(runtime)?;
100 }
101 Ok(true)
102 }
103
104 pub fn toggle(&mut self, runtime: &mut MotionRuntime) -> Result<bool, MotionError> {
106 self.set_visible(!self.shown, runtime)
107 }
108
109 pub fn show(&mut self, runtime: &mut MotionRuntime) -> Result<(), MotionError> {
111 self.motion
112 .transition_to_tracked(self.visible.clone(), runtime)?;
113 self.mounted = true;
114 self.shown = true;
115 self.exit_playback = None;
116 #[cfg(feature = "tracing")]
117 tracing::debug!(
118 target: "aura_anim::presence",
119 value_type = std::any::type_name::<T>(),
120 mounted = self.mounted,
121 shown = self.shown,
122 "showing presence"
123 );
124 Ok(())
125 }
126
127 pub fn hide(&mut self, runtime: &mut MotionRuntime) -> Result<(), MotionError> {
129 let playback = self
130 .motion
131 .transition_to_tracked(self.hidden.clone(), runtime)?;
132 self.shown = false;
133 self.exit_playback = Some(playback);
134 #[cfg(feature = "tracing")]
135 tracing::debug!(
136 target: "aura_anim::presence",
137 value_type = std::any::type_name::<T>(),
138 mounted = self.mounted,
139 shown = self.shown,
140 "hiding presence"
141 );
142 Ok(())
143 }
144
145 pub fn show_with<P, Kind>(
147 &mut self,
148 animation: P,
149 runtime: &mut MotionRuntime,
150 ) -> Result<(), MotionError>
151 where
152 P: IntoMotionAnimation<T, Kind>,
153 {
154 self.motion.play_tracked(animation, runtime)?;
155 self.mounted = true;
156 self.shown = true;
157 self.exit_playback = None;
158 #[cfg(feature = "tracing")]
159 tracing::debug!(
160 target: "aura_anim::presence",
161 value_type = std::any::type_name::<T>(),
162 mounted = self.mounted,
163 shown = self.shown,
164 "showing presence with custom animation"
165 );
166 Ok(())
167 }
168
169 pub fn hide_with<P, Kind>(
171 &mut self,
172 animation: P,
173 runtime: &mut MotionRuntime,
174 ) -> Result<(), MotionError>
175 where
176 P: IntoMotionAnimation<T, Kind>,
177 {
178 let playback = self.motion.play_tracked(animation, runtime)?;
179 self.shown = false;
180 self.exit_playback = Some(playback);
181 #[cfg(feature = "tracing")]
182 tracing::debug!(
183 target: "aura_anim::presence",
184 value_type = std::any::type_name::<T>(),
185 mounted = self.mounted,
186 shown = self.shown,
187 "hiding presence with custom animation"
188 );
189 Ok(())
190 }
191
192 pub fn handle_event(&mut self, event: &MotionEvent) -> bool {
197 let Some(exit_playback) = self.exit_playback else {
198 return false;
199 };
200 if self.shown || !event.is_completed_for(exit_playback) {
201 return false;
202 }
203
204 let changed = self.mounted;
205 self.mounted = false;
206 self.exit_playback = None;
207 #[cfg(feature = "tracing")]
208 tracing::debug!(
209 target: "aura_anim::presence",
210 value_type = std::any::type_name::<T>(),
211 "unmounted completed hidden presence from runtime event"
212 );
213 changed
214 }
215
216 pub fn sync(&mut self, runtime: &MotionRuntime) -> Result<(), MotionError> {
218 if !self.shown && self.motion.is_completed(runtime)? {
219 self.mounted = false;
220 self.exit_playback = None;
221 #[cfg(feature = "tracing")]
222 tracing::debug!(
223 target: "aura_anim::presence",
224 value_type = std::any::type_name::<T>(),
225 "unmounted completed hidden presence"
226 );
227 }
228 Ok(())
229 }
230}