1.CEGUI的属性系统非常方便非常强大,只需向PropertySet::setProperty函数中传人属性名和属性值,就可以设置了。方便的代价是效率,无论何种类型的属性值都是以字符串的形式传人的,在调用真正的属性设置函数进行设置时,再把字符串转化为真正的类型值。如果只是在初始化时,或者界面响应用户操作时,以这种形式进行设置,那也没什么大不了,但如果是在每帧里面都这样设,我感觉效率上有点吃不消。
CEGUI的动画系统就是基于它的属性系统的,所以动画系统可以动画所有属性,这一点非常强大,但就像上面说的,因为属性系统是基于字符串的,而动画每帧都要设置属性,这个效率,我表示怀疑。
不过动画系统设计的还是非常好的,代码很有美感。设计的总体思路除了上面说的以属性为基础外,还有就是动画的定义和动画实例分离。
动画的定义记录静态信息:该动画操控那些属性,每种操控的关键帧的时间位置是什么、值是什么。动画的实例记录动态信息,其实就是一个:该实例播放到什么时间点了。
在每一帧绘制的时候,将流失的时间传人动画实例中,计算当前播到什么时间点了,然后再把时间点传人动画定义中,找到时间点两边的关键帧,进行线性插值,获取该时间点对应的属性值,然后设置该属性就可以了。有些关键帧的值被设置为某些属性的值,动画开始时,会把这些关键帧值刷一遍,以同步到当时的那些属性的值,这些值也记录在动画实例中。
具体的动画系统还有很多小细节,想下次画一下UML图,详细的剖析一下,不过我现在有时想,这样详细研究剖析代码的收益和付出到底是否划得来。
2.ChainedXMLHandler
在CEGUI中有两种处理XML的思路,分歧在于如何处理嵌套节点
<A>
<B>
<C/>
</B>
</A>
其中一种方式是在handler里面设置一些变量和栈,用它们来追踪解析的过程,GuiLayoutHandler就是这么做的,还有一种方式是使用ChainedXMLHandler,这种方式,会为每一种节点,从ChainedXMLHandler基类派生出一个类,这种节点的解析就被局部到这个类里面。ChainedXMLHandler类中有一个指向ChainedXMLHandler对象的指针,通过该指针就会形成一个Handler链,上述的嵌套节点的解析过程,就通过这个链来完成。每个类的elementStartLocal方法其实不是解析该类对应的节点,而是解析该类的下一级节点,解析的方法就是生成一个下级节点对应的handler对象,该对象的实例化函数需要对应节点的属性对,即handler实例的过程其实就节点解析的过程,而handler的elementStartLocal方法却是解析下一级节点的过程。
这两种方法的区别就是递归调用和把递归调用展成循环的区别,第二种方法刚开始看的时候会别扭一些,但其实是要好写一些的(递归和展开递归哪种好写,大家都知道),但从效率上讲,第二种比第一种要低,与递归和展开递归同理,只不过此处与“函数入栈出栈”变成了handler的构造和析构。
3.xsd文件
该文件定义某种xml文件应该具有的形式,例如有哪些节点,节点之间的关系如何。例如CEGUi的动画文件对应的xsd文件就是Animation.xsd。XMLParser::parseXMLFile函数中就需要传人该文件,检查解析的XML文件是否符合要求。
我现在感觉自己层次比较低,剖析代码的时候,感觉自己其实已经看懂了看全了,但没法说好说全,描述方式有大问题,层次不分明,应该是因为没用UML和设计模式参与描述造成的。