@@ -87,14 +87,19 @@ pub enum AnimationSystem {
87
87
/// attached to the same entity, and tick the animator to animate the component.
88
88
pub fn component_animator_system < T : Component > (
89
89
time : Res < Time > ,
90
- mut query : Query < ( Entity , & mut T , & mut Animator < T > ) > ,
90
+ mut animator_query : Query < ( Entity , & mut Animator < T > ) > ,
91
+ mut target_query : Query < & mut T > ,
91
92
events : ResMut < Events < TweenCompleted > > ,
92
93
mut commands : Commands ,
93
94
) {
94
95
let mut events: Mut < Events < TweenCompleted > > = events. into ( ) ;
95
- for ( entity , target , mut animator) in query . iter_mut ( ) {
96
+ for ( animator_entity , mut animator) in animator_query . iter_mut ( ) {
96
97
if animator. state != AnimatorState :: Paused {
97
98
let speed = animator. speed ( ) ;
99
+ let entity = animator. target . unwrap_or ( animator_entity) ;
100
+ let Ok ( target) = target_query. get_mut ( entity) else {
101
+ continue ;
102
+ } ;
98
103
let mut target = ComponentTarget :: new ( target) ;
99
104
animator. tweenable_mut ( ) . tick (
100
105
time. delta ( ) . mul_f32 ( speed) ,
@@ -164,7 +169,8 @@ mod tests {
164
169
/// [`Entity`] in it.
165
170
struct TestEnv < T : Component > {
166
171
world : World ,
167
- entity : Entity ,
172
+ animator_entity : Entity ,
173
+ target_entity : Option < Entity > ,
168
174
_phantom : PhantomData < T > ,
169
175
}
170
176
@@ -180,7 +186,25 @@ mod tests {
180
186
181
187
Self {
182
188
world,
183
- entity,
189
+ animator_entity : entity,
190
+ target_entity : None ,
191
+ _phantom : PhantomData ,
192
+ }
193
+ }
194
+
195
+ /// Like [`TestEnv::new`], but the component is placed on a separate entity.
196
+ pub fn new_separated ( animator : Animator < T > ) -> Self {
197
+ let mut world = World :: new ( ) ;
198
+ world. init_resource :: < Events < TweenCompleted > > ( ) ;
199
+ world. init_resource :: < Time > ( ) ;
200
+
201
+ let target = world. spawn ( T :: default ( ) ) . id ( ) ;
202
+ let entity = world. spawn ( animator. with_target ( target) ) . id ( ) ;
203
+
204
+ Self {
205
+ world,
206
+ animator_entity : entity,
207
+ target_entity : Some ( target) ,
184
208
_phantom : PhantomData ,
185
209
}
186
210
}
@@ -215,12 +239,17 @@ mod tests {
215
239
216
240
/// Get the animator for the component.
217
241
pub fn animator ( & self ) -> & Animator < T > {
218
- self . world . entity ( self . entity ) . get :: < Animator < T > > ( ) . unwrap ( )
242
+ self . world
243
+ . entity ( self . animator_entity )
244
+ . get :: < Animator < T > > ( )
245
+ . unwrap ( )
219
246
}
220
247
221
248
/// Get the component.
222
249
pub fn component_mut ( & mut self ) -> Mut < T > {
223
- self . world . get_mut :: < T > ( self . entity ) . unwrap ( )
250
+ self . world
251
+ . get_mut :: < T > ( self . target_entity . unwrap_or ( self . animator_entity ) )
252
+ . unwrap ( )
224
253
}
225
254
226
255
/// Get the emitted event count since last tick.
@@ -230,6 +259,30 @@ mod tests {
230
259
}
231
260
}
232
261
262
+ #[ test]
263
+ fn custom_target_entity ( ) {
264
+ let tween = Tween :: new (
265
+ EaseMethod :: Linear ,
266
+ Duration :: from_secs ( 1 ) ,
267
+ TransformPositionLens {
268
+ start : Vec3 :: ZERO ,
269
+ end : Vec3 :: ONE ,
270
+ } ,
271
+ )
272
+ . with_completed_event ( 0 ) ;
273
+ let mut env = TestEnv :: new_separated ( Animator :: new ( tween) ) ;
274
+ let mut system = IntoSystem :: into_system ( component_animator_system :: < Transform > ) ;
275
+ system. initialize ( env. world_mut ( ) ) ;
276
+
277
+ env. tick ( Duration :: ZERO , & mut system) ;
278
+ let transform = env. component_mut ( ) ;
279
+ assert ! ( transform. translation. abs_diff_eq( Vec3 :: ZERO , 1e-5 ) ) ;
280
+
281
+ env. tick ( Duration :: from_millis ( 500 ) , & mut system) ;
282
+ let transform = env. component_mut ( ) ;
283
+ assert ! ( transform. translation. abs_diff_eq( Vec3 :: splat( 0.5 ) , 1e-5 ) ) ;
284
+ }
285
+
233
286
#[ test]
234
287
fn change_detect_component ( ) {
235
288
let tween = Tween :: new (
0 commit comments