1- use bevy:: prelude:: * ;
21use std:: time:: Duration ;
32
3+ use bevy:: prelude:: * ;
4+
45use crate :: { EaseMethod , Lens , TweeningDirection , TweeningType } ;
56
7+ /// The dynamic tweenable type.
8+ ///
9+ /// When creating lists of tweenables, you will need to box them to create a homogeneous
10+ /// array like so:
11+ /// ```no_run
12+ /// # use bevy::prelude::Transform;
13+ /// # use bevy_tweening::{BoxedTweenable, Delay, Sequence, Tween};
14+ /// #
15+ /// # let delay: Delay = unimplemented!();
16+ /// # let tween: Tween<Transform> = unimplemented!();
17+ ///
18+ /// Sequence::new([Box::new(delay) as BoxedTweenable<Transform>, tween.into()]);
19+ /// ```
20+ ///
21+ /// When using your own [`Tweenable`] types, APIs will be easier to use if you implement [`From`]:
22+ /// ```no_run
23+ /// # use std::time::Duration;
24+ /// # use bevy::prelude::{Entity, EventWriter, Transform};
25+ /// # use bevy_tweening::{BoxedTweenable, Sequence, Tweenable, TweenCompleted, TweenState};
26+ /// #
27+ /// # struct MyTweenable;
28+ /// # impl Tweenable<Transform> for MyTweenable {
29+ /// # fn duration(&self) -> Duration { unimplemented!() }
30+ /// # fn is_looping(&self) -> bool { unimplemented!() }
31+ /// # fn set_progress(&mut self, progress: f32) { unimplemented!() }
32+ /// # fn progress(&self) -> f32 { unimplemented!() }
33+ /// # fn tick(&mut self, delta: Duration, target: &mut Transform, entity: Entity, event_writer: &mut EventWriter<TweenCompleted>) -> TweenState { unimplemented!() }
34+ /// # fn times_completed(&self) -> u32 { unimplemented!() }
35+ /// # fn rewind(&mut self) { unimplemented!() }
36+ /// # }
37+ ///
38+ /// Sequence::new([Box::new(MyTweenable) as BoxedTweenable<_>]);
39+ ///
40+ /// // OR
41+ ///
42+ /// Sequence::new([MyTweenable]);
43+ ///
44+ /// impl From<MyTweenable> for BoxedTweenable<Transform> {
45+ /// fn from(t: MyTweenable) -> Self {
46+ /// Box::new(t)
47+ /// }
48+ /// }
49+ /// ```
50+ pub type BoxedTweenable < T > = Box < dyn Tweenable < T > + Send + Sync + ' static > ;
51+
652/// Playback state of a [`Tweenable`].
753///
854/// This is returned by [`Tweenable::tick()`] to allow the caller to execute some logic based on the
@@ -169,45 +215,27 @@ pub trait Tweenable<T>: Send + Sync {
169215 fn rewind ( & mut self ) ;
170216}
171217
172- impl < T > Tweenable < T > for Box < dyn Tweenable < T > + Send + Sync + ' static > {
173- fn duration ( & self ) -> Duration {
174- self . as_ref ( ) . duration ( )
175- }
176- fn is_looping ( & self ) -> bool {
177- self . as_ref ( ) . is_looping ( )
178- }
179- fn set_progress ( & mut self , progress : f32 ) {
180- self . as_mut ( ) . set_progress ( progress) ;
218+ impl < T > From < Delay > for BoxedTweenable < T > {
219+ fn from ( d : Delay ) -> Self {
220+ Box :: new ( d)
181221 }
182- fn progress ( & self ) -> f32 {
183- self . as_ref ( ) . progress ( )
184- }
185- fn tick (
186- & mut self ,
187- delta : Duration ,
188- target : & mut T ,
189- entity : Entity ,
190- event_writer : & mut EventWriter < TweenCompleted > ,
191- ) -> TweenState {
192- self . as_mut ( ) . tick ( delta, target, entity, event_writer)
193- }
194- fn times_completed ( & self ) -> u32 {
195- self . as_ref ( ) . times_completed ( )
196- }
197- fn rewind ( & mut self ) {
198- self . as_mut ( ) . rewind ( ) ;
222+ }
223+
224+ impl < T : ' static > From < Sequence < T > > for BoxedTweenable < T > {
225+ fn from ( s : Sequence < T > ) -> Self {
226+ Box :: new ( s)
199227 }
200228}
201229
202- /// Trait for boxing a [`Tweenable`] trait object.
203- pub trait IntoBoxDynTweenable < T > {
204- /// Convert the current object into a boxed [`Tweenable`].
205- fn into_box_dyn ( this : Self ) -> Box < dyn Tweenable < T > + Send + Sync + ' static > ;
230+ impl < T : ' static > From < Tracks < T > > for BoxedTweenable < T > {
231+ fn from ( t : Tracks < T > ) -> Self {
232+ Box :: new ( t )
233+ }
206234}
207235
208- impl < T , U : Tweenable < T > + Send + Sync + ' static > IntoBoxDynTweenable < T > for U {
209- fn into_box_dyn ( this : U ) -> Box < dyn Tweenable < T > + Send + Sync + ' static > {
210- Box :: new ( this )
236+ impl < T : ' static > From < Tween < T > > for BoxedTweenable < T > {
237+ fn from ( t : Tween < T > ) -> Self {
238+ Box :: new ( t )
211239 }
212240}
213241
@@ -480,7 +508,7 @@ impl<T> Tweenable<T> for Tween<T> {
480508
481509/// A sequence of tweens played back in order one after the other.
482510pub struct Sequence < T > {
483- tweens : Vec < Box < dyn Tweenable < T > + Send + Sync + ' static > > ,
511+ tweens : Vec < BoxedTweenable < T > > ,
484512 index : usize ,
485513 duration : Duration ,
486514 time : Duration ,
@@ -492,13 +520,14 @@ impl<T> Sequence<T> {
492520 ///
493521 /// This method panics if the input collection is empty.
494522 #[ must_use]
495- pub fn new ( items : impl IntoIterator < Item = impl IntoBoxDynTweenable < T > > ) -> Self {
496- let tweens: Vec < _ > = items
497- . into_iter ( )
498- . map ( IntoBoxDynTweenable :: into_box_dyn)
499- . collect ( ) ;
523+ pub fn new ( items : impl IntoIterator < Item = impl Into < BoxedTweenable < T > > > ) -> Self {
524+ let tweens: Vec < _ > = items. into_iter ( ) . map ( Into :: into) . collect ( ) ;
500525 assert ! ( !tweens. is_empty( ) ) ;
501- let duration = tweens. iter ( ) . map ( Tweenable :: duration) . sum ( ) ;
526+ let duration = tweens
527+ . iter ( )
528+ . map ( AsRef :: as_ref)
529+ . map ( Tweenable :: duration)
530+ . sum ( ) ;
502531 Self {
503532 tweens,
504533 index : 0 ,
@@ -512,8 +541,9 @@ impl<T> Sequence<T> {
512541 #[ must_use]
513542 pub fn from_single ( tween : impl Tweenable < T > + Send + Sync + ' static ) -> Self {
514543 let duration = tween. duration ( ) ;
544+ let boxed: BoxedTweenable < T > = Box :: new ( tween) ;
515545 Self {
516- tweens : vec ! [ Box :: new ( tween ) ] ,
546+ tweens : vec ! [ boxed ] ,
517547 index : 0 ,
518548 duration,
519549 time : Duration :: ZERO ,
@@ -637,7 +667,7 @@ impl<T> Tweenable<T> for Sequence<T> {
637667
638668/// A collection of [`Tweenable`] executing in parallel.
639669pub struct Tracks < T > {
640- tracks : Vec < Box < dyn Tweenable < T > + Send + Sync + ' static > > ,
670+ tracks : Vec < BoxedTweenable < T > > ,
641671 duration : Duration ,
642672 time : Duration ,
643673 times_completed : u32 ,
@@ -646,12 +676,14 @@ pub struct Tracks<T> {
646676impl < T > Tracks < T > {
647677 /// Create a new [`Tracks`] from an iterator over a collection of [`Tweenable`].
648678 #[ must_use]
649- pub fn new ( items : impl IntoIterator < Item = impl IntoBoxDynTweenable < T > > ) -> Self {
650- let tracks: Vec < _ > = items
651- . into_iter ( )
652- . map ( IntoBoxDynTweenable :: into_box_dyn)
653- . collect ( ) ;
654- let duration = tracks. iter ( ) . map ( Tweenable :: duration) . max ( ) . unwrap ( ) ;
679+ pub fn new ( items : impl IntoIterator < Item = impl Into < BoxedTweenable < T > > > ) -> Self {
680+ let tracks: Vec < _ > = items. into_iter ( ) . map ( Into :: into) . collect ( ) ;
681+ let duration = tracks
682+ . iter ( )
683+ . map ( AsRef :: as_ref)
684+ . map ( Tweenable :: duration)
685+ . max ( )
686+ . unwrap ( ) ;
655687 Self {
656688 tracks,
657689 duration,
@@ -797,12 +829,15 @@ impl<T> Tweenable<T> for Delay {
797829
798830#[ cfg( test) ]
799831mod tests {
800- use super :: * ;
801- use crate :: lens:: * ;
802- use bevy:: ecs:: { event:: Events , system:: SystemState } ;
803832 use std:: sync:: { Arc , Mutex } ;
804833 use std:: time:: Duration ;
805834
835+ use bevy:: ecs:: { event:: Events , system:: SystemState } ;
836+
837+ use crate :: lens:: * ;
838+
839+ use super :: * ;
840+
806841 /// Utility to compare floating-point values with a tolerance.
807842 fn abs_diff_eq ( a : f32 , b : f32 , tol : f32 ) -> bool {
808843 ( a - b) . abs ( ) < tol
0 commit comments