让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即可。
让pv3d(papervision3D)支持单帧前进、后退(nextFrame)。的更多相关文章
- Laya 使list渲染支持分帧的思路
Laya 使list渲染支持分帧的思路 @author ixenos 2019-09-06 1.由于Laya的list渲染时没有做分帧处理,只做了延迟帧处理,所以当单页元素较多时,会有大量运算卡帧的情 ...
- SQL Server利用RowNumber()内置函数与Over关键字实现通用分页存储过程(支持单表或多表结查集分页)
SQL Server利用RowNumber()内置函数与Over关键字实现通用分页存储过程,支持单表或多表结查集分页,存储过程如下: /******************/ --Author:梦在旅 ...
- JS编写日历控件(支持单日历 双日历 甚至多日历等)
前言: 最近几天都在研究日历控件编写,当然前提我要说明下,当然看过别人写的源码 所以脑子一热 就想用自己的编码方式 来写一套可扩展性 可维护性 性能高点的代码控件出来,就算练习练习下,所以前几天晚上下 ...
- 【转】Android单帧动画Rotate旋转
项目有一个需求,有一个刷新按钮,上面放着一个常见的静止的刷新圆圈,如下图: 一旦用户按了刷新按钮,需要让这个刷新圆圈转动起来,让用户感觉到程序还在运行着,而不是卡死了. 有两个思路,一是将这个图按照旋 ...
- K8S-OVS使用Openvswitch为提供SDN功能支持单租户模式和多租户模式
k8s-ovs ============================== 最近在寻求一些工作机会,如果有kubernetes相关研发招聘的朋友,欢迎随时联系我.我的个人简历可以通过百度网盘:htt ...
- 单页应用后退不刷新方案(vue & react)
引言 前进刷新,后退不刷新,是一个类似app页面的特点,要在单页web应用中做后退不刷新,却并非一件易事. 为什么麻烦 spa的渲染原理(以vue为例):url的更改触发onHashChange/pu ...
- [原][spark]帧序列的纹理UV索引,修改spark源码,改变纹理索引方式,支持常规帧序列
spark的纹理索引方式是左下为最小值0 右上为最大值k ,遍历顺序为横向即: 3 4 5 0 1 2 而常规的纹理帧序列是这样的: 0 1 2 3 4 5 所以,为了让spark的纹理遍历顺序能按照 ...
- Android:控件布局(单帧布局)FrameLayout
FrameLayout:所有控件位于左上角,并且直接覆盖前面的子元素. 在最上方显示的层加上: android:clickable="true" 可以避免点击上层触发底层. 实例: ...
- Android FrameLayout单帧布局
FrameLayout:所有控件位于左上角,并且直接覆盖前面的子元素. 在最上方显示的层加上: android:clickable="true" 可以避免点击上层触发底层. 实例: ...
随机推荐
- 转:Delphi2010新发现-类的构造和析构函数功能
Delphi2010发布了. 虽然凭着对Delphi的热爱第一时间就安装了,但是现在可能是年纪大了,对新事物缺乏兴趣了.一直都没有仔细研究. 今天有点时间试了一下新功能. 本来C#和Delphi.NE ...
- asp.net mvc自定义JsonResult类来防止MaxJsonLength超过限制
前不久在做一个项目的时候,我用到了mvc的webapi返回了一个大数据,结果报了500错误,如下图所示: Server Error in ‘/’ Application. Error during s ...
- [资料分享]SQL Server 2016/2014/2012/2008简体中文企业版下载+对应补丁
为什么只提供企业版下载呢?因为不管你是学生还是工作研究人员,企业版都是功能最为齐全的一个版本,比如企业版都集成了SQL Server Management Studio管理界面(俗称企业管理器的可视化 ...
- 洛谷 P1201 [USACO1.1]贪婪的送礼者Greedy Gift Givers Label:ExWater
题目描述 对于一群(NP个)要互送礼物的朋友,GY要确定每个人送出的钱比收到的多多少.在这一个问题中,每个人都准备了一些钱来送礼物,而这些钱将会被平均分给那些将收到他的礼物的人.然而,在任何一群朋友中 ...
- requirejs 打包 添加版本号收集资料 待测试
https://www.npmjs.org/package/rjs-optimhttps://www.npmjs.org/package/grunt-requirejs-md5指定js版本号 但不是M ...
- 试用avalon2.0
一直从事后端开发,对于前端的html+css+js,不熟不熟的.前面写了一个比较复杂的操作界面,我只能说,误工费时.花了一周研究avalonjs2,大神的确就是大神,解决了我很多的问题, 请参考htt ...
- Meta标签介绍
Meta标签写法与作用 meta标签是在HTML网页源代码中一个重要的html标签.meta位于head区的辅助性标签,提供用户不可用的信息. META标签用来描述一个HTML网页文档的属性,例 ...
- Tomcat7安装配置 for Ubuntu
一.环境说明: 操作系统:Ubuntu 12.04.2 LTS Tomcat:apache-tomcat-7.0.52 二.下载 下载地址:http://tomcat.apache.org/ 这里下载 ...
- (转)windows系统下Python环境的搭建
原博文地址:http://www.cnblogs.com/windinsky/archive/2012/09/20/2695520.html 这段时间在做python,觉得这个配置环境的帖子还不错,分 ...
- [WPF] 我的WPF自学日记1,无标题窗体拖动
学习WPF的第一天,尝试写比较常用的功能,无标题窗体拖动. 先在设计界面给它加上MouseDown事件 <Window x:Class="MyFirstWPFAPP.MainWindo ...