PageRenderTime 316ms CodeModel.GetById 131ms app.highlight 15ms RepoModel.GetById 95ms app.codeStats 1ms

/src/away3d/animators/AnimatorBase.as

http://github.com/away3d/away3d-core-fp11
ActionScript | 349 lines | 184 code | 52 blank | 113 comment | 18 complexity | 8ace496f54a36ed9ce84173a87300e75 MD5 | raw file
  1package away3d.animators
  2{
  3	import flash.display.Sprite;
  4	import flash.events.Event;
  5	import flash.geom.Vector3D;
  6	import flash.utils.Dictionary;
  7	import flash.utils.getTimer;
  8	
  9	import away3d.arcane;
 10	import away3d.animators.nodes.AnimationNodeBase;
 11	import away3d.animators.states.AnimationStateBase;
 12	import away3d.animators.states.IAnimationState;
 13	import away3d.entities.Mesh;
 14	import away3d.events.AnimatorEvent;
 15	import away3d.library.assets.AssetType;
 16	import away3d.library.assets.IAsset;
 17	import away3d.library.assets.NamedAssetBase;
 18	
 19	use namespace arcane;
 20	
 21	/**
 22	 * Dispatched when playback of an animation inside the animator object starts.
 23	 *
 24	 * @eventType away3d.events.AnimatorEvent
 25	 */
 26	[Event(name="start", type="away3d.events.AnimatorEvent")]
 27	
 28	/**
 29	 * Dispatched when playback of an animation inside the animator object stops.
 30	 *
 31	 * @eventType away3d.events.AnimatorEvent
 32	 */
 33	[Event(name="stop", type="away3d.events.AnimatorEvent")]
 34	
 35	/**
 36	 * Dispatched when playback of an animation reaches the end of an animation.
 37	 *
 38	 * @eventType away3d.events.AnimatorEvent
 39	 */
 40	[Event(name="cycle_complete", type="away3d.events.AnimatorEvent")]
 41	
 42	/**
 43	 * Provides an abstract base class for animator classes that control animation output from a data set subtype of <code>AnimationSetBase</code>.
 44	 *
 45	 * @see away3d.animators.AnimationSetBase
 46	 */
 47	public class AnimatorBase extends NamedAssetBase implements IAsset
 48	{
 49		private var _broadcaster:Sprite = new Sprite();
 50		private var _isPlaying:Boolean;
 51		private var _autoUpdate:Boolean = true;
 52		private var _startEvent:AnimatorEvent;
 53		private var _stopEvent:AnimatorEvent;
 54		private var _cycleEvent:AnimatorEvent;
 55		private var _time:int;
 56		private var _playbackSpeed:Number = 1;
 57		
 58		protected var _animationSet:IAnimationSet;
 59		protected var _owners:Vector.<Mesh> = new Vector.<Mesh>();
 60		protected var _activeNode:AnimationNodeBase;
 61		protected var _activeState:IAnimationState;
 62		protected var _activeAnimationName:String;
 63		protected var _absoluteTime:Number = 0;
 64		private var _animationStates:Dictionary = new Dictionary(true);
 65		
 66		/**
 67		 * Enables translation of the animated mesh from data returned per frame via the positionDelta property of the active animation node. Defaults to true.
 68		 *
 69		 * @see away3d.animators.states.IAnimationState#positionDelta
 70		 */
 71		public var updatePosition:Boolean = true;
 72		
 73		public function getAnimationState(node:AnimationNodeBase):AnimationStateBase
 74		{
 75			var className:Class = node.stateClass;
 76			
 77			return _animationStates[node] ||= new className(this, node);
 78		}
 79		
 80		public function getAnimationStateByName(name:String):AnimationStateBase
 81		{
 82			return getAnimationState(_animationSet.getAnimation(name));
 83		}
 84		
 85		/**
 86		 * Returns the internal absolute time of the animator, calculated by the current time and the playback speed.
 87		 *
 88		 * @see #time
 89		 * @see #playbackSpeed
 90		 */
 91		public function get absoluteTime():Number
 92		{
 93			return _absoluteTime;
 94		}
 95		
 96		/**
 97		 * Returns the animation data set in use by the animator.
 98		 */
 99		public function get animationSet():IAnimationSet
100		{
101			return _animationSet;
102		}
103		
104		/**
105		 * Returns the current active animation state.
106		 */
107		public function get activeState():IAnimationState
108		{
109			return _activeState;
110		}
111		
112		/**
113		 * Returns the current active animation node.
114		 */
115		public function get activeAnimation():AnimationNodeBase
116		{
117			return _animationSet.getAnimation(_activeAnimationName);
118		}
119		
120		/**
121		 * Returns the current active animation node.
122		 */
123		public function get activeAnimationName():String
124		{
125			return _activeAnimationName;
126		}
127		
128		/**
129		 * Determines whether the animators internal update mechanisms are active. Used in cases
130		 * where manual updates are required either via the <code>time</code> property or <code>update()</code> method.
131		 * Defaults to true.
132		 *
133		 * @see #time
134		 * @see #update()
135		 */
136		public function get autoUpdate():Boolean
137		{
138			return _autoUpdate;
139		}
140		
141		public function set autoUpdate(value:Boolean):void
142		{
143			if (_autoUpdate == value)
144				return;
145			
146			_autoUpdate = value;
147			
148			if (_autoUpdate)
149				start();
150			else
151				stop();
152		}
153		
154		/**
155		 * Gets and sets the internal time clock of the animator.
156		 */
157		public function get time():int
158		{
159			return _time;
160		}
161		
162		public function set time(value:int):void
163		{
164			if (_time == value)
165				return;
166			
167			update(value);
168		}
169		
170		/**
171		 * Sets the animation phase of the current active state's animation clip(s).
172		 *
173		 * @param value The phase value to use. 0 represents the beginning of an animation clip, 1 represents the end.
174		 */
175		public function phase(value:Number):void
176		{
177			_activeState.phase(value);
178		}
179		
180		/**
181		 * Creates a new <code>AnimatorBase</code> object.
182		 *
183		 * @param animationSet The animation data set to be used by the animator object.
184		 */
185		public function AnimatorBase(animationSet:IAnimationSet)
186		{
187			_animationSet = animationSet;
188		}
189		
190		/**
191		 * The amount by which passed time should be scaled. Used to slow down or speed up animations. Defaults to 1.
192		 */
193		public function get playbackSpeed():Number
194		{
195			return _playbackSpeed;
196		}
197		
198		public function set playbackSpeed(value:Number):void
199		{
200			_playbackSpeed = value;
201		}
202		
203		/**
204		 * Resumes the automatic playback clock controling the active state of the animator.
205		 */
206		public function start():void
207		{
208			if (_isPlaying || !_autoUpdate)
209				return;
210			
211			_time = _absoluteTime = getTimer();
212			
213			_isPlaying = true;
214			
215			if (!_broadcaster.hasEventListener(Event.ENTER_FRAME))
216				_broadcaster.addEventListener(Event.ENTER_FRAME, onEnterFrame);
217			
218			if (!hasEventListener(AnimatorEvent.START))
219				return;
220			
221			dispatchEvent(_startEvent ||= new AnimatorEvent(AnimatorEvent.START, this));
222		}
223		
224		/**
225		 * Pauses the automatic playback clock of the animator, in case manual updates are required via the
226		 * <code>time</code> property or <code>update()</code> method.
227		 *
228		 * @see #time
229		 * @see #update()
230		 */
231		public function stop():void
232		{
233			if (!_isPlaying)
234				return;
235			
236			_isPlaying = false;
237			
238			if (_broadcaster.hasEventListener(Event.ENTER_FRAME))
239				_broadcaster.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
240			
241			if (!hasEventListener(AnimatorEvent.STOP))
242				return;
243			
244			dispatchEvent(_stopEvent || (_stopEvent = new AnimatorEvent(AnimatorEvent.STOP, this)));
245		}
246		
247		/**
248		 * Provides a way to manually update the active state of the animator when automatic
249		 * updates are disabled.
250		 *
251		 * @see #stop()
252		 * @see #autoUpdate
253		 */
254		public function update(time:int):void
255		{
256			var dt:Number = (time - _time)*playbackSpeed;
257			
258			updateDeltaTime(dt);
259			
260			_time = time;
261		}
262		
263		public function reset(name:String, offset:Number = 0):void
264		{
265			getAnimationState(_animationSet.getAnimation(name)).offset(offset + _absoluteTime);
266		}
267		
268		/**
269		 * Used by the mesh object to which the animator is applied, registers the owner for internal use.
270		 *
271		 * @private
272		 */
273		public function addOwner(mesh:Mesh):void
274		{
275			_owners.push(mesh);
276		}
277		
278		/**
279		 * Used by the mesh object from which the animator is removed, unregisters the owner for internal use.
280		 *
281		 * @private
282		 */
283		public function removeOwner(mesh:Mesh):void
284		{
285			_owners.splice(_owners.indexOf(mesh), 1);
286		}
287		
288		/**
289		 * Internal abstract method called when the time delta property of the animator's contents requires updating.
290		 *
291		 * @private
292		 */
293		protected function updateDeltaTime(dt:Number):void
294		{
295			_absoluteTime += dt;
296			
297			_activeState.update(_absoluteTime);
298			
299			if (updatePosition)
300				applyPositionDelta();
301		}
302		
303		/**
304		 * Enter frame event handler for automatically updating the active state of the animator.
305		 */
306		private function onEnterFrame(event:Event = null):void
307		{
308			update(getTimer());
309		}
310		
311		private function applyPositionDelta():void
312		{
313			var delta:Vector3D = _activeState.positionDelta;
314			var dist:Number = delta.length;
315			var len:uint;
316			if (dist > 0) {
317				len = _owners.length;
318				for (var i:uint = 0; i < len; ++i)
319					_owners[i].translateLocal(delta, dist);
320			}
321		}
322		
323		/**
324		 *  for internal use.
325		 *
326		 * @private
327		 */
328		public function dispatchCycleEvent():void
329		{
330			if (hasEventListener(AnimatorEvent.CYCLE_COMPLETE))
331				dispatchEvent(_cycleEvent || (_cycleEvent = new AnimatorEvent(AnimatorEvent.CYCLE_COMPLETE, this)));
332		}
333		
334		/**
335		 * @inheritDoc
336		 */
337		public function dispose():void
338		{
339		}
340		
341		/**
342		 * @inheritDoc
343		 */
344		public function get assetType():String
345		{
346			return AssetType.ANIMATOR;
347		}
348	}
349}