zoukankan      html  css  js  c++  java
  • 让pv3d(papervision3D)支持单帧前进、后退(nextFrame)。

    下载最新的源码,找到animationController.

    修改如下:

    package org.papervision3d.core.controller 
    {
    	import flash.events.EventDispatcher;
    	import flash.utils.getTimer;
    	
    	import org.papervision3d.core.animation.IAnimatable;
    	import org.papervision3d.core.animation.channel.Channel3D;
    	import org.papervision3d.core.animation.clip.AnimationClip3D;
    	import org.papervision3d.events.AnimationEvent;
    	
    	/**
    	 * The AnimationController class controls an animation.
    	 * 
    	 * @author Tim Knip / floorplanner.com
    	 */
    	public class AnimationController extends EventDispatcher implements IObjectController, IAnimatable
    	{
    		/**
    		 * Start time of animation in seconds. 
    		 */
    		public var startTime : Number;
    		
    		/**
    		 * End time of animation in seconds. 
    		 */
    		public var endTime : Number;
    		
    		/**
    		 * 
    		 */
    		private var _channels : Array;
    		
    		/**
    		 * 
    		 */
    		private var _isPlaying : Boolean;
    		
    		/**
    		 * 
    		 */
    		private var _isPaused : Boolean;
    		
    		/**
    		 * 
    		 */
    		private var _isStepping : Boolean = false;
    		
    		/**
    		 * 
    		 */
    		private var _currentTime : Number;
    		
    		/**
    		 * 
    		 */
    		private var _currentTimeStamp : int;
    		
    		/**
    		 * 
    		 */
    		private var _pauseTime : Number;
    		
    		/**
    		 * 
    		 */
    		private var _loop : Boolean;
    		
    		/** */
    		private var _clip : AnimationClip3D;
    		
    		/** */
    		private var _clips : Array;
    		
    		/** */
    		private var _clipByName : Object;
    		
    		/** */
    		private var _dispatchEvents : Boolean;
    		
    		/** 帧计算 */
    		private var _frameIndex:int = 0;
    		
    		/**
    		 * Constructor.
    		 */
    		public function AnimationController(dispatchEvents:Boolean=true) 
    		{
    			super();
    			
    			_dispatchEvents = dispatchEvents;
    			
    			init();			
    		}
    
    		/**
    		 * 
    		 */
    		public function addChannel(channel : Channel3D) : Channel3D 
    		{
    			if(_channels.indexOf(channel) == -1)
    			{
    				_channels.push(channel);
    				updateStartAndEndTime();
    				return channel;
    			}
    			return null;
    		}
    
    		/**
    		 * 
    		 */
    		public function addClip(clip : AnimationClip3D) : AnimationClip3D
    		{
    			if(_clips.indexOf(clip) == -1)
    			{
    				_clips.push(clip);
    				_clipByName[clip.name] = clip;
    				return clip;
    			}
    			return null;	
    		}
    
    		/**
    		 * 
    		 */
    		public function clone() : AnimationController
    		{
    			var controller : AnimationController = new AnimationController();
    			var channel : Channel3D;
    			var cloned : Channel3D;
    			var i : int;
    			
    			for(i = 0; i < _channels.length; i++)
    			{
    				channel = _channels[i];
    				cloned = channel.clone();
    				controller.addChannel(cloned);
    			}
    			return controller;
    		}
    
    		/**
    		 * Initialize.
    		 */
    		protected function init() : void
    		{
    			_channels = new Array();
    			_clips = new Array();
    			_clipByName = new Object();
    			_isPlaying = false;
    			_isPaused = false;
    			_currentTime = 0;
    			_loop = false;
    			updateStartAndEndTime();
    		}
    		
    		/**
    		 * Pause the animation.
    		 */
    		public function pause() : void
    		{
    			_pauseTime = _currentTime;
    			_isPaused = true;
    			_isPlaying = false;
    			
    			if (_dispatchEvents)
    			{
    				var clipName :String = _clip ? _clip.name : "all";
    
    				dispatchEvent(new AnimationEvent(AnimationEvent.PAUSE, _pauseTime, clipName));
    			}
    		}
    		/**
    		 * Plays the animation.
    		 * 
    		 * @param 	clip	Clip to play. Default is "all"
    		 * @param 	loop	Whether the animation should loop. Default is true.
    		 */ 
    		public function play(clip:String="all", loop:Boolean=true) : void 
    		{
    			if(clip && clip.length && _clipByName[clip] is AnimationClip3D) 
    			{	
    				_clip = _clipByName[clip];
    			}
    			else
    			{
    				_clip = null;
    			}
    			
    			if(_channels.length)
    			{
    				_loop = loop;
    				_currentTimeStamp = getTimer();
    				if(_clip)
    				{
    					_currentTimeStamp -= (_clip.startTime * 1000);	
    				}
    				_isPlaying = true;
    				_isPaused = false;
    			}
    			
    			if (_dispatchEvents)
    			{
    				var clipName :String = _clip ? _clip.name : "all";
    				var time :Number = _clip ? _clip.startTime : 0;
    				
    				dispatchEvent(new AnimationEvent(AnimationEvent.START, time, clipName));
    			}
    		}
    
    		/**
    		 * 显示下一帧
    		 */
    		public function next():void{
    			_frameIndex++;
    			if(_frameIndex >= totalFrames)
    			{
    				_frameIndex = 0;
    			}
    			_currentTime =  endTime / totalFrames * _frameIndex;
    			this._isStepping = true;
    		}
    		
    		public function get totalFrames():int{
    			var count:int = 0;
    			if(!this._channels)
    				return count;
    			for each(var _channel:Channel3D in this._channels)
    			{
    				if(_channel.output == null)
    					continue;
    				count = Math.max(_channel.output.length, count);
    			}
    			return count;
    		}
    		
    		/**
    		 * 
    		 */
    		public function removeAllChannels() : void
    		{
    			while(_channels.length)
    			{
    				_channels.pop();
    			}
    			updateStartAndEndTime();
    		}
    		
    		/**
    		 * 
    		 */
    		public function removeChannel(channel : Channel3D) : Channel3D
    		{
    			var pos : int = _channels.indexOf(channel);
    			if(pos >= 0)
    			{
    				_channels.splice(pos, 1);
    				updateStartAndEndTime();
    				return channel;
    			}
    			return null;
    		}
    		
    		/**
    		 * Removes a clip.
    		 * 
    		 * @param clip
    		 * 
    		 * @return	The removed clip or null on failure.
    		 */
    		public function removeClip(clip : AnimationClip3D) : AnimationClip3D
    		{
    			var pos : int = _clips.indexOf(clip);
    			if(pos >= 0)
    			{
    				_clips.splice(pos, 1);
    				_clipByName[clip.name] = null;
    				return clip;
    			}
    			return null;
    		}
    		
    		/**
    		 * Resumes the animation.
    		 * 
    		 *  @param loop	Whether the animation should loop. Defaults to true;
    		 */
    		public function resume(loop:Boolean=true) : void
    		{
    			if(_channels.length)
    			{
    				_loop = loop;
    				_currentTimeStamp = getTimer();
    				if(_isPaused)
    				{
    					_currentTimeStamp = getTimer() - _pauseTime * 1000;	
    				}
    				_isPlaying = true;
    				_isPaused = false;
    				
    				if (_dispatchEvents)
    				{
    					var clipName :String = _clip ? _clip.name : "all";
    
    					dispatchEvent(new AnimationEvent(AnimationEvent.RESUME, _pauseTime, clipName));
    				}
    			}
    		}
    
    		/**
    		 * Stops the animation.
    		 */
    		public function stop() : void
    		{	
    			_isPlaying = false;
    			
    			if (_dispatchEvents)
    			{
    				var endTime :Number = _clip ? _clip.endTime : this.endTime;
    				var clipName :String = _clip ? _clip.name : "all";
    			
    				dispatchEvent(new AnimationEvent(AnimationEvent.STOP, endTime, clipName));
    			}
    		}
    		
    		/**
    		 * Update.
    		 */
    		public function update() : void 
    		{
    			if(_isStepping)
    			{
    				stepping();
    				_isStepping = false;
    				return;	
    			}
    			
    			if(!_isPlaying || _isPaused || !_channels.length)
    			{
    				return;
    			}
    			
    			var t : int = getTimer();
    			var elapsed : int = t - _currentTimeStamp;
    			var channel : Channel3D;
    			var et : Number = _clip ? _clip.endTime : endTime;
    			var clipName :String = _clip ? _clip.name : "all";
    			
    			_currentTime =  (elapsed * 0.001);
    
    			if(_currentTime > et) 
    			{
    				if (_dispatchEvents)
    				{
    					dispatchEvent(new AnimationEvent(AnimationEvent.COMPLETE, et, clipName));
    				}
    					
    				if(!_loop)
    				{
    					stop();
    					return;
    				}
    				_currentTimeStamp = t;
    				if(_clip)
    				{
    					_currentTimeStamp -= (_clip.startTime * 1000);
    				}
    				_currentTime = _clip ? _clip.startTime : startTime;
    			}
    			
    			for each(channel in _channels)
    			{
    				channel.update(_currentTime);
    			}
    			
    			if (_isPlaying && _dispatchEvents)
    			{
    				dispatchEvent(new AnimationEvent(AnimationEvent.NEXT_FRAME, _currentTime, clipName));
    			}
    		}
    		
    		private function stepping():void
    		{
    			var channel : Channel3D;
    			var et : Number = _clip ? _clip.endTime : endTime;
    			var clipName :String = _clip ? _clip.name : "all";
    			
    			if(_currentTime > et) 
    			{
    				if (_dispatchEvents)
    				{
    					dispatchEvent(new AnimationEvent(AnimationEvent.COMPLETE, et, clipName));
    				}
    				
    				if(!_loop)
    				{
    					stop();
    					return;
    				}
    				if(_clip)
    				{
    					_currentTimeStamp -= (_clip.startTime * 1000);
    				}
    				_currentTime = _clip ? _clip.startTime : startTime;
    			}
    			
    			for each(channel in _channels)
    			{
    				channel.update(_currentTime);
    			}
    			
    			if (_isPlaying && _dispatchEvents)
    			{
    				dispatchEvent(new AnimationEvent(AnimationEvent.NEXT_FRAME, _currentTime, clipName));
    			}
    		}
    		
    		/**
    		 * Updates the startTime and endTime of this animation controller.
    		 */
    		protected function updateStartAndEndTime() : void
    		{
    			var channel : Channel3D;
    			
    			if(_channels.length == 0)
    			{
    				startTime = endTime = 0;
    				return;
    			}
    			
    			startTime = Number.MAX_VALUE;
    			endTime = -startTime;
    		
    			for each(channel in _channels)
    			{
    				startTime = Math.min(startTime, channel.startTime);
    				endTime = Math.max(endTime, channel.endTime);
    			}
    		}
    		
    		/**
    		 * 
    		 */
    		override public function toString() : String
    		{
    			return "[AnimationController] #channels: " + _channels.length + " startTime: " + startTime + " endTime: " + endTime;
    		}
    		
    		public function set channels(value : Array) : void
    		{
    			_channels = value;	
    		}
    		
    		public function get channels() : Array
    		{
    			return _channels;
    		}
    		
    		public function get currentTime():Number
    		{
    			return _currentTime;	
    		}
    
    		/**
    		 * Gets all defined clip names. This property is read-only.
    		 * 
    		 * @return Array containing clip names.
    		 */
    		public function get clipNames() : Array
    		{
    			var names : Array = new Array();	
    			var clip : AnimationClip3D;
    			
    			for each(clip in _clips)
    			{
    				names.push(clip.name);
    			}
    			return names;
    		}
    		
    		/**
    		 * Gets all defined clips. This property is read-only.
    		 * 
    		 * @return Array containing clips.
    		 * 
    		 * @see org.papervision3d.core.animation.clip.AnimationClip3D
    		 */
    		public function get clips() : Array
    		{
    			return _clips;
    		}
    		
    		/**
    		 * 
    		 */
    		public function get dispatchEvents():Boolean
    		{
    			return _dispatchEvents;
    		} 
    		
    		/**
    		 * 
    		 */
    		public function set dispatchEvents(value:Boolean):void
    		{
    			_dispatchEvents = value;	
    		}
    		
    		/**
    		 * Number of channels.
    		 */
    		public function get numChannels() : uint
    		{
    			return _channels.length;
    		}
    		
    		/**
    		 * Whether the animation is playing. This property is read-only.
    		 */
    		public function get playing() : Boolean
    		{
    			return _isPlaying;
    		}
    	}
    }
    

      

    增加了next方法。每次调用,就会进入下一帧。然后调用 onRenderTick即可。

  • 相关阅读:
    739. Daily Temperatures
    556. Next Greater Element III
    1078. Occurrences After Bigram
    1053. Previous Permutation With One Swap
    565. Array Nesting
    1052. Grumpy Bookstore Owner
    1051. Height Checker
    数据库入门及SQL基本语法
    ISCSI的概念
    配置一个IP SAN 存储服务器
  • 原文地址:https://www.cnblogs.com/zc22/p/3488278.html
Copyright © 2011-2022 走看看