下载最新的源码,找到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即可。

让pv3d(papervision3D)支持单帧前进、后退(nextFrame)。的更多相关文章

  1. Laya 使list渲染支持分帧的思路

    Laya 使list渲染支持分帧的思路 @author ixenos 2019-09-06 1.由于Laya的list渲染时没有做分帧处理,只做了延迟帧处理,所以当单页元素较多时,会有大量运算卡帧的情 ...

  2. SQL Server利用RowNumber()内置函数与Over关键字实现通用分页存储过程(支持单表或多表结查集分页)

    SQL Server利用RowNumber()内置函数与Over关键字实现通用分页存储过程,支持单表或多表结查集分页,存储过程如下: /******************/ --Author:梦在旅 ...

  3. JS编写日历控件(支持单日历 双日历 甚至多日历等)

    前言: 最近几天都在研究日历控件编写,当然前提我要说明下,当然看过别人写的源码 所以脑子一热 就想用自己的编码方式 来写一套可扩展性 可维护性 性能高点的代码控件出来,就算练习练习下,所以前几天晚上下 ...

  4. 【转】Android单帧动画Rotate旋转

    项目有一个需求,有一个刷新按钮,上面放着一个常见的静止的刷新圆圈,如下图: 一旦用户按了刷新按钮,需要让这个刷新圆圈转动起来,让用户感觉到程序还在运行着,而不是卡死了. 有两个思路,一是将这个图按照旋 ...

  5. K8S-OVS使用Openvswitch为提供SDN功能支持单租户模式和多租户模式

    k8s-ovs ============================== 最近在寻求一些工作机会,如果有kubernetes相关研发招聘的朋友,欢迎随时联系我.我的个人简历可以通过百度网盘:htt ...

  6. 单页应用后退不刷新方案(vue & react)

    引言 前进刷新,后退不刷新,是一个类似app页面的特点,要在单页web应用中做后退不刷新,却并非一件易事. 为什么麻烦 spa的渲染原理(以vue为例):url的更改触发onHashChange/pu ...

  7. [原][spark]帧序列的纹理UV索引,修改spark源码,改变纹理索引方式,支持常规帧序列

    spark的纹理索引方式是左下为最小值0 右上为最大值k ,遍历顺序为横向即: 3 4 5 0 1 2 而常规的纹理帧序列是这样的: 0 1 2 3 4 5 所以,为了让spark的纹理遍历顺序能按照 ...

  8. Android:控件布局(单帧布局)FrameLayout

    FrameLayout:所有控件位于左上角,并且直接覆盖前面的子元素. 在最上方显示的层加上: android:clickable="true" 可以避免点击上层触发底层. 实例: ...

  9. Android FrameLayout单帧布局

    FrameLayout:所有控件位于左上角,并且直接覆盖前面的子元素. 在最上方显示的层加上: android:clickable="true" 可以避免点击上层触发底层. 实例: ...

随机推荐

  1. IMEI串号

    IMEI串号就是国际移动设备身份码,是电子设备的唯一身份证,由于它的唯一性,它可以用来查询电子设备的保修期还有产地,可以说用处直逼人民的身份证啊! 在拨号键盘页面  输入[*#06#]五个字符

  2. Fiddler问题 - creation of the root certificate was not successful

    打开cmd执行命令. d: cd D:\soft\Fiddler2 makecert.exe -r -ss my -n "CN=DO_NOT_TRUST_FiddlerRoot, O=DO_ ...

  3. ViewPager 简单实现左右无限滑动.

    只需在在适配器中将getCount 给一个较大的值, 然后将currentItem 设为值的一半 就可以伪实现 无限循环. private static final int PAGE_COUNT = ...

  4. 安卓智能POS开单神器-成为零售批发商亲睐的生意帮手-pda销售扫描开单 现场结算打印凭据

    pda销售开单主要有盘点.出库.入库.销售等操作. 主要功能: 出库作业(销售开单.销售退货.销售赠品).入库作业(进货开单.进货退货.进货赠品).盘点作业(能盘盈盘亏)等操作,带蓝牙打印功能 3.仓 ...

  5. 转:Delphi2010新发现-类的构造和析构函数功能

    Delphi2010发布了. 虽然凭着对Delphi的热爱第一时间就安装了,但是现在可能是年纪大了,对新事物缺乏兴趣了.一直都没有仔细研究. 今天有点时间试了一下新功能. 本来C#和Delphi.NE ...

  6. d-规则

    [问题描述]对任意给定的m(m∈N+)和n(n∈N+),满足m<n,构造一初始集合:P={x|m≤x≤n,x∈N+} (m,n≤100).现定义一种d规则如下:若存在a∈P,且存在K∈N+ ,K ...

  7. ajax返回json数据,对其中日期的解析

    JS 对其格式化 方法如下 function ChangeDateFormat(d){ //将时间戳转为int类型,构造Date类型 var date = new Date(parseInt(d.ti ...

  8. Codeforces Round #259 (Div. 2)

    A. Little Pony and Crystal Mine 水题,每行D的个数为1,3.......n-2,n,n-2,.....3,1,然后打印即可 #include <iostream& ...

  9. tomcat在linux下自启动

    Linux下设置tomcat开机自启动  一.以root用户登录系统: 二.进入init.d文件夹 cd /etc/init.d/ 三.创建并打开tomcat文件 vi tomcat 四.tomcat ...

  10. ubuntu 16.04 安装完QQ后,更新或apt-get报错

    apt-get install python-pip正在读取软件包列表... 完成正在分析软件包的依赖关系树 正在读取状态信息... 完成 您可能需要运行“apt-get -f install”来纠正 ...