1.CEGUI中的Property
CEGUI中Property可以分为三类,标准Property,UserDataProperty,和LinkProperty。
标准Property是就是之前讲过的那一种,他们都有自己的实体类,派生自Property,而且每个实体类,全局只有一个实例,他们的get/set函数一般都会进行一些内部操作,例如设置窗口可见性。
UserDataProperty都是PropertyDefinition类的对象,PropertyDefinition是Property的子类,UserDataProperty的get/set函数仅仅只是存取Window类的d_userStrings成员,所以它们只是以字符串的形式存取某些数据,并没有内部操作。
LinkProperty都是PropertyLinkDefinition类的对象,PropertyLinkDefinition是Property的子类,他本身并不进行任何直接操作,它里面保存有其他Property以及该Property作用的Window的信息对,它的get/set方法就是遍历这些信息对,根据信息对中的Window对象名,找到window对象,对其执行信息对里的Property。
标准Property的注册必须在代码中完成,一般每个Window的派生类,都会有一个方法注册该派生类的属性,该方法在构造函数中调用,例如FrameWindow的addFrameWindowProperties()。在配置文件中,<Property>节点就是用来对这些标标准Property进行设置的,该节点在layout文件中会直接引发Window对象的PropertySet::set方法,在looknfeel文件却不是,因为解析looknfeel并没有生产Window对象,自然无法调用Window对象的PropertySet::set,所以需要一种方法把属性名和属性值记录下来,在Window对象实例化出来后,取得这些信息,进行属性设置,用于记录的类就是PropertyInitialiser。
UserDataProperty通过looknfeel文件中的<PropertyDefinition>节点定义,它的注册是在WidgetLookFeel::initialiseWidget里面完成的,当然用户在代码里面手工添加UserDataProperty也是可以的。
LinkProperty通过looknfeel文件中的<PropertyLinkDefinition>节点定义,它的注册是在WidgetLookFeel::initialiseWidget里面完成的,当然用户在代码里面手工添加LinkProperty也是可以的。
任何Property在注册的时候,都会调用Property类的虚方法initialisePropertyReceiver进行属性的初始设置。
发现一个有点奇怪的地方--Property::set不是const方法。这造成了WidgetLookFeel::d_propertyDefinitions必须是mutable,因为WidgetLookFeel::initialiseWIdgte是const方法(从逻辑上它应该是),而该方法中会取出d_propertyDefinitions的元素调用Window::addProperty,而该方法中又会调用Property::set,因为set不是const,所以d_propertyDefinitions的元素不能是const,所以只能mutable。
在我的理解中,mutable应该是只出现在lazy-evaluation功能中,例如面片有一个世界变换矩阵,通过getMatrix取得,这个矩阵会因为很多因素改变,如果每次这些因素改变的时候,都去重新计算这个矩阵,那么会很浪费,所以一种比较好的方法,是使用一个变量记录这个矩阵是否需要更新,每次这些因素改变的时候,就把标志置为true,在getMatrix里面检测这个标志,如果为true就更新世界矩阵变量,并把标志置为false,因为getMatrix这个方法从逻辑上讲是获得对象的一个字段,所以应该是const,但获得的时候,内部变量又有可能变化,所以这些变量就是mutable,这就是lazy-evaluation。
d_propertyDefinitions用mutable不是因为这个,所以我觉得设计有问题。
Property相当于是工具对象,它只是进行转调,它不应该有可变的状态,所以set应该是const的。不过这个也可能是为了放宽限制,说不定什么时候就会有一个Property需要状态可变,例如进行调用计数。