14、Kanzi插件——通过Kanzi Engine插件创建自定义属性类型及其元数据+代码解析
一、创建自定义属性类型及代码分析
向插件的构造函数中添加一些代码,其中,第5-23行为新添加代码
class PLUGINDEMO_API Plugindemo : public kanzi::Node3D
{
public://字符串属性static kanzi::PropertyType<kanzi::string> StringProperty;//引用节点的字符串static kanzi::PropertyType<kanzi::string> NodeRefByStringProperty;//引用预设件的字符串static kanzi::PropertyType<kanzi::string> PrefabRefByStringProperty;//引用预设件的共享指针static kanzi::PropertyType<kanzi::ResourceSharedPtr> PrefabRefBySharedPtrProperty;//引用材质的共享指针static kanzi::PropertyType<kanzi::ResourceSharedPtr> MaterialRefBySharedPtrProperty;KZ_METACLASS_BEGIN(Plugindemo, Node3D, "MyNode")//将属性类型添加到类元数据。KZ_METACLASS_PROPERTY_TYPE(StringProperty)KZ_METACLASS_PROPERTY_TYPE(NodeRefByStringProperty)KZ_METACLASS_PROPERTY_TYPE(PrefabRefByStringProperty)KZ_METACLASS_PROPERTY_TYPE(PrefabRefBySharedPtrProperty)KZ_METACLASS_PROPERTY_TYPE(MaterialRefBySharedPtrProperty)KZ_METACLASS_END()static kanzi::PropertyTypeEditorInfoSharedPtr makeEditorInfo();// Creates a Plugindemo.static PlugindemoSharedPtr create(kanzi::Domain* domain, kanzi::string_view name);protected:// Constructor.explicit Plugindemo(kanzi::Domain* domain, kanzi::string_view name):kanzi::Node3D(domain, name){}// Initializes the created Kanzi Engine plugin.// Kanzi node classes typically have a static create() member function, which creates the instance of a node,// initializes it, and returns a shared pointer to the instance. To initialize the instance, the initialize()// function is called on it. You must initialize a node in the initialize() function, not in the constructor.void initialize();
};
上述代码中PropertyType是一个模板类,利用该模板类声明了五个属性对象。在
KZ_METACLASS_BEGIN(Plugindemo, Node3D, "MyNode")
KZ_METACLASS_END()
中间添加了五个宏,宏展开的代码如下
#define KZ_METACLASS_PROPERTY_TYPE(propertyType)\metaclass.addPropertyType(propertyType);addPropertyType实现如下void addPropertyType(AbstractPropertyType propertyType)
{kzAssert(propertyType);checkSealed();m_propertyTypes.push_back(propertyType);
}
其中m_propertyTypes的类型是一个容器
PropertyTypeContainer m_propertyTypes;
typedef vector<AbstractPropertyType> PropertyTypeContainer;
这个类型实质就是vector<AbstractPropertyType>的别名,当把各个属性添加到容器中时,会调用PropertyType中的类型转换运算符将各个属性统一成AbstractPropertyType对象
operator AbstractPropertyType() const
{return AbstractPropertyType(m_propertyType);
}
所以,这五个宏的作用就是将这五个属性添加到元类对象中
之后,在类外对这五个static成员进行初始化,初始化的代码如下
PropertyType<string> Plugindemo::StringProperty(kzMakeFixedString("Plugindemo.String"), "", 0, false,KZ_DECLARE_EDITOR_METADATA(metadata.displayName = "String";
));PropertyType<string> Plugindemo::NodeRefByStringProperty(kzMakeFixedString("Plugindemo.NodeRefByString"), "", 0, false,KZ_DECLARE_EDITOR_METADATA(metadata.displayName = "Node Reference by String";metadata.valueProvider = "ProjectObject:Node3D";
));PropertyType<string> Plugindemo::PrefabRefByStringProperty(kzMakeFixedString("Plugindemo.PrefabRefByString"), "", 0, false,KZ_DECLARE_EDITOR_METADATA(metadata.displayName = "Prefab Reference by String"; metadata.valueProvider = "ProjectObject:PrefabTemplate";
));PropertyType<ResourceSharedPtr> Plugindemo::PrefabRefBySharedPtrProperty(kzMakeFixedString("Plugindemo.PrefabRefBySharedPtr"), ResourceSharedPtr(), 0, false,KZ_DECLARE_EDITOR_METADATA(metadata.displayName = "Prefab Reference by Shared Pointer"; metadata.valueProvider = "ProjectObject:PrefabTemplate";
));PropertyType<ResourceSharedPtr> Plugindemo::MaterialRefBySharedPtrProperty(kzMakeFixedString("Plugindemo.MaterialRefBySharedPtr"), ResourceSharedPtr(), 0, false,KZ_DECLARE_EDITOR_METADATA(metadata.displayName = "Material Reference by Shared Pointer";metadata.valueProvider = "ProjectObject:Material";
));
上述五个属性的初始化分别调用了PropertyType的构造函数,其中被调用到的构造函数实现如下
explicit PropertyType(FixedString name, DataType defaultValue, uint32_t changeFlags, bool inheritable, PropertyTypeEditorInfo* editorInfo) :m_propertyType(create(name, defaultValue, changeFlags, inheritable, PropertyTypeEditorInfoSharedPtr(editorInfo)))
{
}
其中第一个参数的实参是宏kzMakeFixedString展开的结果,kzMakeFixedString的展开如下
#define kzMakeFixedString(x) x ## _kzfixed
这个展开结果会直接调用operator"" _kzfixed,operator"" _kzfixed的实现如下,可见,最终通过字面值操作符返回的是一个FixedString的临时对象
inline FixedString operator"" _kzfixed(const char* s, std::size_t)
{return FixedString(s);
}
所以,通过上述流程,PropertyType构造函数的第一个参数的实参是一个FixedString的临时对象,其中,FixedString构造函数中的实参是传入宏kzMakeFixedString的参数(也就是Plugindemo.String, Plugindemo.NodeRefByString等等)
第二个参数的类型是一个模板参数类型的别名,如果模板参数类型是一个string,那么直接传入空字符串,如果模板参数类型是一个ResourceSharedPtr,直接传入一个临时对象。
最后一个参数是PropertyTypeEditorInfo的指针,其定义见上一篇,这里通过宏KZ_DECLARE_EDITOR_METADATA展开对PropertyTypeEditorInfo的指针进行初始化
#define KZ_DECLARE_EDITOR_METADATA(x) new kanzi::PropertyTypeEditorInfo(
[]() -> kanzi::PropertyTypeEditorInfo::AttributeDictionary { kanzi::PropertyTypeEditorInfo::AttributeDictionary metadata; x return metadata; }()
)
可见,通过该宏展开,最终new了一个PropertyTypeEditorInfo的对象,这个对象是通过一个lambda表达式返回的meta数据进行初始化的
PropertyType的成员m_propertyType的类型定义如下
Descriptor* m_propertyType;
该成员的初始化是靠create函数和传给PropertyType构造函数的参数共同进行初始化
create的实现如下
Descriptor* create(FixedString name, DataType defaultValue, uint32_t changeFlags, bool inherited, PropertyTypeEditorInfoSharedPtr editorInfo)
{return new Descriptor(name, defaultValue, changeFlags, inherited, editorInfo);
}
其中Descriptor的定义如下
typedef PropertyTypeDescriptor<Type> Descriptor;
PropertyTypeDescriptor的部分定义如下
template <typename T>
class PropertyTypeDescriptor : public AbstractPropertyTypeDescriptor
{
public:explicit PropertyTypeDescriptor(FixedString name, typename Traits::ParameterType defaultValue, uint32_t changeFlags, bool inherited, PropertyTypeEditorInfoSharedPtr editorInfo) :AbstractPropertyTypeDescriptor(name, changeFlags, inherited, editorInfo){Traits::write(m_defaultValue, defaultValue);}
};
可见,最终在构造函数执行了一个写入的操作。
Trait的实现如下
typedef PropertyDataTypeTraits<T> Traits;
PropertyDataTypeTraits的特化了多个模板类,其中string和ResourceSharedPtr的特化版本实现如下
template <>
struct PropertyDataTypeTraits<ResourceSharedPtr> : public detail::ComplexDataTypeTraits<ResourceSharedPtr>
{static const PropertyDataType dataType = PropertyDataTypeResource;
};template <>
struct PropertyDataTypeTraits<string>
{typedef string StorageType;typedef string_view ParameterType;typedef string ReturnType;static const PropertyDataType dataType = PropertyDataTypeString;static inline void write(StorageType& storage, ParameterType parameter){storage.assign(cbegin(parameter), cend(parameter));}static inline const string& read(const StorageType& storage){return storage;}
};
ResourceSharedPtr的特化版本没有write,会调用父类中的write,其实现如下
template <typename T>
struct ComplexDataTypeTraits
{typedef T StorageType;typedef const T& ParameterType;typedef T ReturnType;static inline void write(StorageType& storage, ParameterType value){storage = value;}
};
上述两个函数的本质就是一个枚举的初始化和一个赋值,调用完之后,StringProperty就初始化完成了
二、效果
编译插件工程,并更新插件
至此,可以为自定义的节点设置自定义的属性
参考
《Kanzi官方文档》
14、Kanzi插件——通过Kanzi Engine插件创建自定义属性类型及其元数据+代码解析相关推荐
- 12、Kanzi插件——创建Kanzi Engine插件的方法
可以使用模板自动创建Kanzi Engine插件 模板选为含有Kanzi Engine插件的应用 注意:工程名不能叫plugin,因为VS工程会根据该工程名设置定义具体的类,如果命名为plugin,那 ...
- 15、Kanzi插件——通过Kanzi Engine插件创建自定义消息类型+代码解析
一.创建trigger中的自定义消息 比如,想创建一个当汽车燃油量发生变化时对应的消息,可以进行如下操作 首先,在插件工程中的头文件中定义一个嵌套类,下面代码中的第23行和29-44行为新添加代码 # ...
- 13、Kanzi插件——通过Kanzi Engine插件创建自定义节点+代码解析
一.通过插件创建自定义类型的节点 在类Plugindemo 中添加一行 static kanzi::PropertyTypeEditorInfoSharedPtr makeEditorInfo(); ...
- 16、Kanzi插件——通过Kanzi Engine插件创建自定义动作+代码解析
一.创建自定义动作 当收到燃油变化的消息时,相应动作代码整体如下 class PLUGINDEMO_API Plugindemo : public kanzi::Node3D { public://字 ...
- 【Flutter】开发 Flutter 包和插件 ( Flutter 包和插件简介 | 创建 Flutter 插件 | 创建 Dart 包 )
文章目录 一.Flutter 包和插件简介 二.创建 Flutter 插件 1.Android Studio 中可视化创建 2.命令行创建 三.创建 Dart 包 1.Android Studio 中 ...
- 【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | 主线程创建 Activity 实例之前使用插件 Activity 类替换占位的组件 )
Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...
- 【Android 插件化】Hook 插件化框架 ( 创建插件应用 | 拷贝插件 APK | 初始化插件包 | 测试插件 DEX 字节码 )
Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...
- 【Android 插件化】“ 插桩式 “ 插件化框架 ( 类加载器创建 | 资源加载 )
Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...
- 从零开始实现ASP.NET Core MVC的插件式开发(二) - 如何创建项目模板
标题:从零开始实现ASP.NET Core MVC的插件式开发(二) - 如何创建项目模板 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/11155 ...
最新文章
- java map 红黑树_Java集合-TreeMap和红黑树
- springMVC之Interceptor拦截器
- 解析rtcm32报文工具_RTCM32编解码中的一些概念及相关文献阅读
- java中Object.equals()简单用法
- springcloud Feign工程熔断器Hystrix
- 军事医学研究院应晓敏组招聘博士后
- 【ES6(2015)】Map
- webug第十二关:我系统密码忘记了!
- jsp a标签传值到action中,action接收不到传值
- 在Github上搭建你的博客
- (ubuntu 下)tensorflow 的安装及版本升级
- python医药数据,PostgreSQL+Python实现药品规格数值与单位拆分
- 迅捷cad_迅捷泛型
- 10x程序员是如何思考的?
- 此笔记只作为自身笔记,结构比较混乱,不建议参考,如有需要请访问其他文献,servlet的基础知识和使用
- ios dat 文件读写_玩转你的iphone, IOS 13 NFC标签读写详细步骤
- 数据分析统计工具有哪些?
- winpe进入linux系统,制作U盘Linux 与WinPE启动
- ifconfig 命令使用
- python清洗数据去除停用词_python之NLP数据清洗