现在的位置: 首页 > 综合 > 正文

CEGUI-AnimationSystem

2018年01月16日 ⁄ 综合 ⁄ 共 2770字 ⁄ 字号 评论关闭

CEGUI的动画系统实现了以下的功能:

1.通过属性系统驱动,即在每一帧通过将某种属性设为不同的值,实现该属性的动画;

2.驱动方式分为直接设值,在原有值上加一个值,和在原有值上乘一个值;

3.动画曲线通过关键帧控制,关键帧包含时间点和值,值可以是直接设置的,也可以是动画开始时,从驱动目标上取的属性值,该属性可以与被驱动的属性不同;

4.由一帧到另一帧的移动方式分为匀速、加速、减速和离散;

5.当时间点在两帧之间时,进行线性插值

6.动画可以设置播放一次的时长;

7.播放方式分为一次性播放、重复播放、往返重复播放;

8.动画能对某个外部对象发送事件,例如当动画开始时,能向它发送动画开始事件;

9.动画能监听某个外部对象,当它的某个事件发生时,能执行某个动作,例如监听一个按钮,当按钮按下时,动画启动;

10.动画能够执行的动作分为启动、结束、暂停、解除暂停和切换暂停。

 

动画系统的类图如下:

 

我觉得这个系统最大的特点是把动画的定义和实例进行了分离,动画的定义对应类图中的AniDef,动画的实例对应类图中的AniInstance。一个AniDef可以对应多个AniInstance,但一个AniInstance只能对应一个AniDef。

 

下面介绍每个类的核心字段和方法:

1.KeyFrame——对应需求中的关键帧

-position:关键帧所在的时间点;

-value:如果关键帧的值不是动画开始时从驱动目标上取的属性值,则存于该字段;

-sourceProperty:如果关键帧的值是动画开始时从驱动目标上取的属性值,则该属性的名字存于该字段;

-progression:由上一帧到这一帧的移动方式,有匀速、加速、减速和离散四种(具体解释见该类方法alterInterpolationPosition());

-savePropertyValue():从驱动目标上取属性值,并保存到相应的AniInstance对象中。这个方法是一个调用链,从AniInstance开始,经过AniDef、Affector,最后到KeyFrame;

-getValueForAnimation():返回该关键帧里面的值,如果不是动画开始时从驱动目标上取属性值,则返回value,否则返回取的值;

-alterInterpolationPostion():在动画更新流程中,会将当前时间点映射到[0,1]区间(0表示左关键帧,1表示右关键帧),将该映射值传人右关键帧的该方法,获得处理后的映射值。处理方法为:匀速直接返回,加速进行平方,减速进行开方,离散为输入值为1时才返回1其余时候返回0;

 

2.Interpolator——线性插值器,它是一个接口,具体的插值工作由它的实现类完成。插值参数都是以字符串的形式传人,在实现类的方法中转换为对应类型的数值,然后插值,插值结果还要经过一道处理才返回,处理的方式根据驱动方式而定:

-interpolateAbsolute():对应直接设值方式,直接返回插值结果;

-interpolateRelative():对应在原有值上加一个值的方式,原有值也是以参数的形式传人,加上插值结果后返回;

-interpolateMultiply():对应在原有值上乘一个值的方式,原有值也是以参数的形式传人,乘上插值结果后返回;

将驱动方式的不同处理放在Interpolator里面是因为,如果直接返回插值结果,那么因为它是以字符串的形式返回的,要和原有值进行加或者乘,就又要转换一次,这个一是效率会低一些,二是逻辑分散了,在Interpolator里面做是知道应该转换成那种类型的值的,如果在外面做就需要根据目标属性进转换,这会形成一个巨大的switch,以后加入一种新的属性值类型时,还要在这个switch里面加代码,非常不好。

 

3.Affector——一个动画定义可以包含多个属性驱动,而单一的属性驱动就封装在Affector这一层

-keyFrameList:关键帧的序列;

-applicationMethod:驱动方式,即直接设值,在原有值上加一个值,和在原有值上乘一个值;

-targetProperty:被驱动的属性的名字;

-interpolator:插值器;

-savePropertyValues():从驱动目标上取属性值,并保存到相应的AniInstance对象中,除了保存关键帧需要的值以为,如果驱动方式是在原有值上加一个值或在原有值上乘一个值,则还保存了被驱动的属性的原有值;

-apply():根据动画实例的当前位置,设置被驱动属性的值。apply()方法是一个调用链,由AniInstance类开始,结果AniDef类,最后到Affector类。

 

4.AniDef——动画定义

-affectorList:Affector对象的集合;

-replayMode:播放方式,分为一次性播放、重复播放、往返重复播放;

-duration:播放一次的时长;

-autoSubscriptions:事件和处理函数映射表,注册监听对象时会用到;

-savePropertyValues():从驱动目标上取属性值,并保存到相应的AniInstance对象中;

-apply():根据动画实例的当前位置,设置被驱动属性的值。

 

5.AniInstance——动画实例

-postion:当前时间点;

-savedPropertyValueMap:动画开始时,从驱动目标上取属性值保存在该字段;

-aniDef:对应的动画定义;

-target:驱动目标;

-eventReceiver:发射事件的目标,例如动画开始时,向它发送动画开始事件;

-eventSender:监听对象,例如它是一个按钮,当它被按下时,动画启动;

-step():更新当前时间点;

-apply():根据当前位置,设置被驱动属性的值。

-savePropertyValues():从驱动目标上取属性值,并保存到savedPropertyValueMap中;

-getSavedPropertyValue():获取保存的属性值;

-handleXXX():事件响应函数,共有响应启动、结束、暂停、解除暂停和切换暂停五种事件的函数;

-XXX():启动、结束、暂停、解除暂停和切换暂停的实际执行函数;

 

6.PropertySet——属性集合体,即被驱动的对象

 

7.EventSet——事件集合体,即监听的对象和发送事件的目标

 

8.AniManager——动画管理器

-aniDefList:动画定义列表;

-aniDefAndInstanceMap:动画定义和实例映射表;

-interpolatorList:插值器列表;

-stepInstances():驱动所有动画实例。

 

动画系统的时序图如下:

初始化

 

 

事件处理

 

 

驱动流程

 

抱歉!评论已关闭.