1package aurelienribon.tweenengine;
2
3import java.util.ArrayList;
4import java.util.Collections;
5import java.util.List;
6
7/**
8 * A TweenManager updates all your tweens and timelines at once.
9 * Its main interest is that it handles the tween/timeline life-cycles for you,
10 * as well as the pooling constraints (if object pooling is enabled).
11 * <p/>
12 *
13 * Just give it a bunch of tweens or timelines and call update() periodically,
14 * you don't need to care for anything else! Relax and enjoy your animations.
15 *
16 * @see Tween
17 * @see Timeline
18 * @author Aurelien Ribon | http://www.aurelienribon.com/
19 */
20public class TweenManager {
21	// -------------------------------------------------------------------------
22	// Static API
23	// -------------------------------------------------------------------------
24
25	/**
26	 * Disables or enables the "auto remove" mode of any tween manager for a
27	 * particular tween or timeline. This mode is activated by default. The
28	 * interest of desactivating it is to prevent some tweens or timelines from
29	 * being automatically removed from a manager once they are finished.
30	 * Therefore, if you update a manager backwards, the tweens or timelines
31	 * will be played again, even if they were finished.
32	 */
33	public static void setAutoRemove(BaseTween<?> object, boolean value) {
34		object.isAutoRemoveEnabled = value;
35	}
36
37	/**
38	 * Disables or enables the "auto start" mode of any tween manager for a
39	 * particular tween or timeline. This mode is activated by default. If it
40	 * is not enabled, add a tween or timeline to any manager won't start it
41	 * automatically, and you'll need to call .start() manually on your object.
42	 */
43	public static void setAutoStart(BaseTween<?> object, boolean value) {
44		object.isAutoStartEnabled = value;
45	}
46
47	// -------------------------------------------------------------------------
48	// Public API
49	// -------------------------------------------------------------------------
50
51	private final ArrayList<BaseTween<?>> objects = new ArrayList<BaseTween<?>>(20);
52	private boolean isPaused = false;
53
54	/**
55	 * Adds a tween or timeline to the manager and starts or restarts it.
56	 *
57	 * @return The manager, for instruction chaining.
58	 */
59	public TweenManager add(BaseTween<?> object) {
60		if (!objects.contains(object)) objects.add(object);
61		if (object.isAutoStartEnabled) object.start();
62		return this;
63	}
64
65	/**
66	 * Returns true if the manager contains any valid interpolation associated
67	 * to the given target object.
68	 */
69	public boolean containsTarget(Object target) {
70		for (int i=0, n=objects.size(); i<n; i++) {
71			BaseTween<?> obj = objects.get(i);
72			if (obj.containsTarget(target)) return true;
73		}
74		return false;
75	}
76
77	/**
78	 * Returns true if the manager contains any valid interpolation associated
79	 * to the given target object and to the given tween type.
80	 */
81	public boolean containsTarget(Object target, int tweenType) {
82		for (int i=0, n=objects.size(); i<n; i++) {
83			BaseTween<?> obj = objects.get(i);
84			if (obj.containsTarget(target, tweenType)) return true;
85		}
86		return false;
87	}
88
89	/**
90	 * Kills every managed tweens and timelines.
91	 */
92	public void killAll() {
93		for (int i=0, n=objects.size(); i<n; i++) {
94			BaseTween<?> obj = objects.get(i);
95			obj.kill();
96		}
97	}
98
99	/**
100	 * Kills every tweens associated to the given target. Will also kill every
101	 * timelines containing a tween associated to the given target.
102	 */
103	public void killTarget(Object target) {
104		for (int i=0, n=objects.size(); i<n; i++) {
105			BaseTween<?> obj = objects.get(i);
106			obj.killTarget(target);
107		}
108	}
109
110	/**
111	 * Kills every tweens associated to the given target and tween type. Will
112	 * also kill every timelines containing a tween associated to the given
113	 * target and tween type.
114	 */
115	public void killTarget(Object target, int tweenType) {
116		for (int i=0, n=objects.size(); i<n; i++) {
117			BaseTween<?> obj = objects.get(i);
118			obj.killTarget(target, tweenType);
119		}
120	}
121
122	/**
123	 * Increases the minimum capacity of the manager. Defaults to 20.
124	 */
125	public void ensureCapacity(int minCapacity) {
126		objects.ensureCapacity(minCapacity);
127	}
128
129	/**
130	 * Pauses the manager. Further update calls won't have any effect.
131	 */
132	public void pause() {
133		isPaused = true;
134	}
135
136	/**
137	 * Resumes the manager, if paused.
138	 */
139	public void resume() {
140		isPaused = false;
141	}
142
143	/**
144	 * Updates every tweens with a delta time ang handles the tween life-cycles
145	 * automatically. If a tween is finished, it will be removed from the
146	 * manager. The delta time represents the elapsed time between now and the
147	 * last update call. Each tween or timeline manages its local time, and adds
148	 * this delta to its local time to update itself.
149	 * <p/>
150	 *
151	 * Slow motion, fast motion and backward play can be easily achieved by
152	 * tweaking this delta time. Multiply it by -1 to play the animation
153	 * backward, or by 0.5 to play it twice slower than its normal speed.
154	 */
155	public void update(float delta) {
156		for (int i=objects.size()-1; i>=0; i--) {
157			BaseTween<?> obj = objects.get(i);
158			if (obj.isFinished() && obj.isAutoRemoveEnabled) {
159				objects.remove(i);
160				obj.free();
161			}
162		}
163
164		if (!isPaused) {
165			if (delta >= 0) {
166				for (int i=0, n=objects.size(); i<n; i++) objects.get(i).update(delta);
167			} else {
168				for (int i=objects.size()-1; i>=0; i--) objects.get(i).update(delta);
169			}
170		}
171	}
172
173	/**
174	 * Gets the number of managed objects. An object may be a tween or a
175	 * timeline. Note that a timeline only counts for 1 object, since it
176	 * manages its children itself.
177	 * <p/>
178	 * To get the count of running tweens, see {@link #getRunningTweensCount()}.
179	 */
180	public int size() {
181		return objects.size();
182	}
183
184	/**
185	 * Gets the number of running tweens. This number includes the tweens
186	 * located inside timelines (and nested timelines).
187	 * <p/>
188	 * <b>Provided for debug purpose only.</b>
189	 */
190	public int getRunningTweensCount() {
191		return getTweensCount(objects);
192	}
193
194	/**
195	 * Gets the number of running timelines. This number includes the timelines
196	 * nested inside other timelines.
197	 * <p/>
198	 * <b>Provided for debug purpose only.</b>
199	 */
200	public int getRunningTimelinesCount() {
201		return getTimelinesCount(objects);
202	}
203
204	/**
205	 * Gets an immutable list of every managed object.
206	 * <p/>
207	 * <b>Provided for debug purpose only.</b>
208	 */
209	public List<BaseTween<?>> getObjects() {
210		return Collections.unmodifiableList(objects);
211	}
212
213	// -------------------------------------------------------------------------
214	// Helpers
215	// -------------------------------------------------------------------------
216
217	private static int getTweensCount(List<BaseTween<?>> objs) {
218		int cnt = 0;
219		for (int i=0, n=objs.size(); i<n; i++) {
220			BaseTween<?> obj = objs.get(i);
221			if (obj instanceof Tween) cnt += 1;
222			else cnt += getTweensCount(((Timeline)obj).getChildren());
223		}
224		return cnt;
225	}
226
227	private static int getTimelinesCount(List<BaseTween<?>> objs) {
228		int cnt = 0;
229		for (int i=0, n=objs.size(); i<n; i++) {
230			BaseTween<?> obj = objs.get(i);
231			if (obj instanceof Timeline) {
232				cnt += 1 + getTimelinesCount(((Timeline)obj).getChildren());
233			}
234		}
235		return cnt;
236	}
237}
238