我正在用C ++编写一个材料脚本解释器,这实际上并不特别。一个简单的材料可能看起来像这样:
Material "SimpleMaterial"
{
CastShadows true
Transparent false
Technique
{
...
}
...
}
与任何其他材料一样,它有多种技术,传递,纹理单元,每个都有自己的设置。但是材料也会支持我有点困难的变量。材质脚本中的变量如下所示:
Material "SimpleMaterial2"
{
Boolean SomeVariable true
CastShadows SomeVariable
Transparent SomeVariable
...
}
现在我想要了解的是为材质制作变量类的最佳方法。变量必须包含分配给它的所有属性的列表。因此,如果我现在将SomeVariable更改为false,则必须将SimpleMaterial2的CastShadows和Transparent值都设置为false。而且材料本身必须包含影响其属性的变量列表。例如,如果我有这些材料:
Material "SimpleParent"
{
Boolean SomeVariable true
...
}
Material "SimpleDerived" : "SimpleParent"
{
CastShadows SomeVariable
...
}
如果我现在更改派生材料中的CastShadows,它必须通知SomeVariable从分配或其他东西中删除此属性。目前我有一个看起来像这样的变量类:
class Variable
{
public:
enum Assignment
{
CastShadows,
Transparent,
Pass_Diffuse,
...
}
.
enum ValueType
{
Boolean,
Enum,
Vec3,
...
}
.
private:
map<void*, std::vector<Assignment>> _Assignments;
ValueType _Type;
void* _Value;
}
_Value void指针实际上存储了不同类型的值,具体取决于此变量的类型(bool,int,Vector2 ...)。 _Assignments map实际上是一种列表,用于存储分配此变量的所有信息。 Void指针可以是指向材质的指针,材质技术,技术的通道,纹理单元,以及存储在键下的向量存储此值“指向”的所有赋值。因此,当变量的值发生变化时,它会调用更新方法。此更新方法首先遍历map并从map获取每个向量。然后它遍历向量并检查哪个赋值。因此,如果赋值是CastShadow,则它会转换:
((SL_Material*)(*map_iterator).first)->CastShadows = (bool*)_Value;
只要我确保(void *)指针正确返回到其原始对象,此方法就可以正常工作。但我很确定所有这一切都可以以更干净的方式完成。也许使用一些模板?欢迎任何想法:)