1+ package flixel .tweens .misc ;
2+
3+ import flixel .tweens .FlxTween ;
4+
5+ /**
6+ * Tweens multiple numeric properties of an object simultaneously.
7+ */
8+ class VarTween extends FlxTween
9+ {
10+ var _object : Dynamic ;
11+ var _properties : Dynamic ;
12+ var _propertyInfos : Array <VarTweenProperty >;
13+
14+ function new (options : TweenOptions , ? manager : FlxTweenManager )
15+ {
16+ super (options , manager );
17+ }
18+
19+ /**
20+ * Tweens multiple numeric public properties.
21+ *
22+ * @param object The object containing the properties.
23+ * @param properties An object containing key/value pairs of properties and target values.
24+ * @param duration Duration of the tween.
25+ */
26+ public function tween (object : Dynamic , properties : Dynamic , duration : Float ): VarTween
27+ {
28+ #if FLX_DEBUG
29+ if (object == null )
30+ throw " Cannot tween variables of an object that is null." ;
31+ else if (properties == null )
32+ throw " Cannot tween null properties." ;
33+ #end
34+
35+ _object = object ;
36+ _properties = properties ;
37+ _propertyInfos = [];
38+ this .duration = duration ;
39+ start ();
40+ initializeVars ();
41+ return this ;
42+ }
43+
44+ override function update (elapsed : Float ): Void
45+ {
46+ var delay : Float = (executions > 0 ) ? loopDelay : startDelay ;
47+
48+ // Leave properties alone until delay is over
49+ if (_secondsSinceStart < delay )
50+ super .update (elapsed );
51+ else
52+ {
53+ // Wait until the delay is done to set the starting values of tweens
54+ if (Math .isNaN (_propertyInfos [0 ].startValue ))
55+ setStartValues ();
56+
57+ super .update (elapsed );
58+
59+ if (active )
60+ for (info in _propertyInfos )
61+ Reflect .setProperty (info .object , info .field , info .startValue + info .range * scale );
62+ }
63+ }
64+
65+ function initializeVars (): Void
66+ {
67+ var fieldPaths : Array <String >;
68+ if (Reflect .isObject (_properties ))
69+ fieldPaths = Reflect .fields (_properties );
70+ else
71+ throw " Unsupported properties container - use an object containing key/value pairs." ;
72+
73+ for (fieldPath in fieldPaths )
74+ {
75+ var target = _object ;
76+ var path = fieldPath .split (" ." );
77+ var field = path .pop ();
78+ for (component in path )
79+ {
80+ target = Reflect .getProperty (target , component );
81+ if (! Reflect .isObject (target ))
82+ throw ' The object does not have the property " $component " in " $fieldPath "' ;
83+ }
84+
85+ _propertyInfos .push ({
86+ object : target ,
87+ field : field ,
88+ startValue : Math . NaN , // gets set after delay
89+ range : Reflect .getProperty (_properties , fieldPath )
90+ });
91+ }
92+ }
93+
94+ function setStartValues ()
95+ {
96+ for (info in _propertyInfos )
97+ {
98+ if (Reflect .getProperty (info .object , info .field ) == null )
99+ throw ' The object does not have the property " ${info .field }"' ;
100+
101+ var value : Dynamic = Reflect .getProperty (info .object , info .field );
102+ if (Math .isNaN (value ))
103+ throw ' The property " ${info .field }" is not numeric.' ;
104+
105+ info .startValue = value ;
106+ info .range = info .range - value ;
107+ }
108+ }
109+
110+ override public function destroy (): Void
111+ {
112+ super .destroy ();
113+ _object = null ;
114+ _properties = null ;
115+ _propertyInfos = null ;
116+ }
117+
118+ override function isTweenOf (object : Dynamic , ? field : String ): Bool
119+ {
120+ if (object == _object && field == null )
121+ return true ;
122+
123+ for (property in _propertyInfos )
124+ {
125+ if (object == property .object && (field == property .field || field == null ))
126+ return true ;
127+ }
128+
129+ return false ;
130+ }
131+ }
132+
133+ private typedef VarTweenProperty =
134+ {
135+ object : Dynamic ,
136+ field : String ,
137+ startValue : Float ,
138+ range : Float
139+ }
0 commit comments