Delta3D中的可扩展做的非常好,包括在STAGE中的一个控制属性面板,里面的一些小零件都是可以按自己需要添加删减或者重新映射的。如图:
其实,里面的一个小条目(被称为一个dynamiccontrol)和一个actor类似,BasePropertyEditor中有一个DynamicControlFactory,负责dynamiccontrol类型的注册(系统自带的如DynamicStringControl、DynamicFloatControl等)
void RegisterControlForDataType(dtCore::DataType& dataType) { mControlFactory->RemoveType(&dataType); mControlFactory->RegisterType<DynControlType>(&dataType); }
DynamicAbstractControl* DynamicControlFactory::CreateDynamicControl(const dtCore::ActorProperty& prop) { return mControlFactory->CreateObject(&prop.GetPropertyType()); }
其中,每一个继承于AbstractParameter的属性(如StringActorProperty、NamedIntParameter、Vec3dActorProperty等)都会关联一个DataType,如下所示:
class AbstractParameter : public osg::Referenced { public: AbstractParameter(DataType& dataType, const dtUtil::RefString& name): mDataType(dataType), mName(name) {}
其中在基类BasePropertyEditor中有成员变量dtCore::RefPtr<DynamicControlFactory> mControlFactory,负责dynamiccontrol的注册和创建。
在dynamiccontrolfactory中的构造函数中有一些系统自带的dynamiccontrol的注册,如:
DynamicControlFactory::DynamicControlFactory() : mControlFactory(new dtUtil::ObjectFactory<dtCore::DataType*, DynamicAbstractControl>) { // register all the data types with the dynamic control factory RegisterControlForDataType<DynamicStringControl>(dtCore::DataType::STRING); RegisterControlForDataType<DynamicFloatControl>(dtCore::DataType::FLOAT); RegisterControlForDataType<DynamicDoubleControl>(dtCore::DataType::DOUBLE); RegisterControlForDataType<DynamicIntControl>(dtCore::DataType::INT); RegisterControlForDataType<DynamicLongControl>(dtCore::DataType::LONGINT); RegisterControlForDataType<DynamicBoolControl>(dtCore::DataType::BOOLEAN); RegisterControlForDataType<DynamicVecNControl<dtCore::Vec2ActorProperty> >(dtCore::DataType::VEC2); RegisterControlForDataType<DynamicVecNControl<dtCore::Vec2fActorProperty> >(dtCore::DataType::VEC2F); RegisterControlForDataType<DynamicVecNControl<dtCore::Vec2dActorProperty> >(dtCore::DataType::VEC2D); RegisterControlForDataType<DynamicVecNControl<dtCore::Vec3ActorProperty> >(dtCore::DataType::VEC3); RegisterControlForDataType<DynamicVecNControl<dtCore::Vec3fActorProperty> >(dtCore::DataType::VEC3F); RegisterControlForDataType<DynamicVecNControl<dtCore::Vec3dActorProperty> >(dtCore::DataType::VEC3D); RegisterControlForDataType<DynamicVecNControl<dtCore::Vec4ActorProperty> >(dtCore::DataType::VEC4); RegisterControlForDataType<DynamicVecNControl<dtCore::Vec4fActorProperty> >(dtCore::DataType::VEC4F); RegisterControlForDataType<DynamicVecNControl<dtCore::Vec4dActorProperty> >(dtCore::DataType::VEC4D); RegisterControlForDataType<DynamicEnumControl>(dtCore::DataType::ENUMERATION); RegisterControlForDataType<DynamicColorRGBAControl>(dtCore::DataType::RGBACOLOR); RegisterControlForDataType<DynamicArrayControl>(dtCore::DataType::ARRAY); RegisterControlForDataType<DynamicContainerControl>(dtCore::DataType::CONTAINER); RegisterControlForDataType<DynamicContainerSelectorControl>(dtCore::DataType::CONTAINER_SELECTOR); RegisterControlForDataType<DynamicPropertyContainerControl>(dtCore::DataType::PROPERTY_CONTAINER); RegisterControlForDataType<DynamicActorControl>(dtCore::DataType::ACTOR); RegisterControlForDataType<DynamicGameEventControl>(dtCore::DataType::GAME_EVENT); RegisterControlForDataType<DynamicBitMaskControl>(dtCore::DataType::BIT_MASK); size_t datatypeCount = dtCore::DataType::EnumerateType().size(); for (size_t i = 0; i < datatypeCount; ++i) { dtCore::DataType* dt = dtCore::DataType::EnumerateType()[i]; if (dt->IsResource()) { RegisterControlForDataType<DynamicResourceControl>(*dt); } } }