让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" 可以避免点击上层触发底层. 实例: ...
随机推荐
- git使用
1.权限校验 首先,您的数据保存在远端服务器一份,服务器需要对您的身份进行识别,一段RAS加密字串, 启动GUI,step1:创建秘钥,generate SSHkey. step2:添加密钥:去你的代 ...
- keycode
<script type="text/javascript" language=JavaScript charset="UTF-8"> docume ...
- JavaScript高级程序设计-(1)html中使用JavaScript
html中使用JavaScript 1.延迟脚本 script标签定义了defer属性,脚本会被延迟到整个页面都解析完毕后运行 详细内容如下: 2.异步脚本 script标签定义了async属性,as ...
- 【刷题笔记】火车购票-----java方案
问题描述请实现一个铁路购票系统的简单座位分配算法,来处理一节车厢的座位分配. 假设一节车厢有20排.每一排5个座位.为方便起见,我们用1到100来给所有的座位编号,第一排是1到5号,第二排是6到10号 ...
- IIS最大连接数优化
错误信息:Error Summary:HTTP Error 503.2 - Service UnavailableThe serverRuntime@appConcurrentRequestLimit ...
- 2015 ACM/ICPC EC-Final
A. Boxes and Balls 二分找到最大的不超过$n$的$\frac{x(x+1)}{2}$形式的数即可. #include <bits/stdc++.h> using name ...
- 【BZOJ1497】[NOI2006]最大获利 最小割
裸的最小割,很经典的模型. 建图:要求总收益-总成本最大,那么将每条弧与源点相连,流量为成本,每个收益与汇点相连,流量为收益,然后每条弧与它所能到达的收益相连,流量为inf. 与源点相连的是未被选中的 ...
- 线程的Alertable与User APC
在使用插User APC注入DLL时,经常面临一个问题,那就是线程必须是处于Alertable模式才能注入成功.但一直对这个Alertable的含义不甚清楚,今天总算是把这个梗消化了. 微软对Aler ...
- Ubuntu环境变量(.profile)加载顺序
Ubuntu下启动的时候的的加载环境变量的过程大致为: /etc/enviroment /etc/profile -->/etc/bash.bashrc --> /etc/prof ...
- linux终端 字符界面 显示乱码
方法一:配置SSH工具 SecureCRT中文版配置 [全局选项]→[默认会话]→[编辑默认设置]→[终端]→[外观]→[字体]→[新宋体 10pt CHINESE_GB2312]→[字符编码 UTF ...