使用序列化的属性编辑处理方法和装置、设备及介质与流程

未命名 07-23 阅读:93 评论:0


1.本技术涉及软件技术领域,尤其涉及一种使用序列化的属性编辑处理方法和装置、电子设备及存储介质。


背景技术:

2.3d(三维)图形引擎是一种用于渲染三维图形的软件工具,通常可以用于游戏开发、虚拟现实和计算机辅助设计等领域。通常一款3d图形引擎无法完全覆盖所有用户的需求,因此用户需要根据自己的用途对引擎进行二次开发,二次开发中最常见的就是添加自定义功能的组件。在开发了自己的组件之后,还需要考虑在编辑器界面如何对组件进行显示和编辑,以方便策划和美术等工作更方便地使用组件。
3.例如,组件中包含一个字符串类型的变量,如果使用默认的编辑方式,则界面会给出一个输入框,用户手动输入所需信息,但当字符串表达的含义是一个文件路径时,用户通常希望可以直接在界面上选取文件,甚至是将文件拖动到输入框处进行赋值,从而避免了找到文件位置、复制文件路径、粘贴到输入框的复杂操作路径,也避免了误输入的问题。再例如,组件中的一个整数类型的成员变量的值只允许以10为单位移动,且一次只能移动10,如果用户使用默认的编辑方式手动输入值则需要每位编辑人员都了解并遵守这一规则,但如果用户可以在界面上开发一个按钮,点击一次按钮就移动10,即保证了规则的可维护性,又方便了编辑人员的使用。诸如这样的例子还有很多,因此在开发引擎时需要设计出合理的接口,使得二次开发的人员可以用简单高效的方式实现上述需求。
4.现有的技术方案是实现一个editor(编辑)类,将这个类绑定到组件上,成为该组件的编辑类。在编辑类中可以重载一个绘制接口,通过调用create(创建)函数并传入需要编辑的变量名和希望显示出的样式类型实现绘制的定制。同时在editor类中保存了被编辑的对象,可以直接通过指针获取对象的数据并进行编辑。现有方案的主要缺点是:通过变量名传递变量信息存在限制,即,只能编辑直接存在于当前对象中的变量,无法将多重包含的变量进行打散并组合编辑;对数组元素无法进行定制编辑;灵活性较低,无法同时编辑包含在其他类型中的变量。因此,亟需解决这一技术问题。


技术实现要素:

5.鉴于上述问题,提出了本技术以便提供一种克服上述问题或者至少部分地解决上述问题的使用序列化的属性编辑处理方法和装置、电子设备及存储介质。所述技术方案如下:
6.第一方面,提供了一种使用序列化的属性编辑处理方法,包括:
7.通过对象,生成所述对象的中间对象;其中所述对象的属性待被编辑,且所述对象的属性通过所述对象中的一个或多个变量来表示,在所述中间对象中所述对象的实例的变量被序列化为连续空间存储;
8.通过所述对象中的一个或多个变量,创建生成各个变量的中间属性;
9.根据所述对象中待被编辑的变量的路径,在创建生成的各个变量的中间属性中查找到对应的目标中间属性;
10.通过所述目标中间属性的访问接口和修改接口,根据所述对象中待被编辑的变量的修改信息对所述中间对象中的连续空间存储进行修改,并将连续空间存储的修改应用到所述对象上。
11.在一种可能的实现方式中,通过对象,生成所述对象的中间对象,包括:
12.遍历对象的类型信息,生成所述对象对应的类型信息结构;
13.以生成所述对象对应的类型信息结构相同的顺序,对所述对象的实例的变量进行遍历,将所述对象的实例的变量序列化为连续空间存储,从而生成包括成员变量类型信息结构和连续空间存储的中间对象。
14.在一种可能的实现方式中,所述方法还包括:
15.实现序列化管理类,用于维护从所述对象的指针到连续空间存储的映射;每次在同一帧内需要将所述对象的实例的变量序列化为连续空间存储时,调用序列化管理类的对象到连续空间存储接口,从映射中查询是否已经存在被序列化过的连续空间存储,若存在则直接赋值,否则调用序列化接口生产连续空间存储并存储在映射中。
16.在一种可能的实现方式中,所述各个变量的中间属性中的多个成员变量,分别以指针的形式指向所述中间对象中的成员变量。
17.在一种可能的实现方式中,所述将连续空间存储的修改应用到所述对象上,包括:
18.调用所述对象的中间对象中的申请修改接口,根据所述对象对应的类型信息结构,将修改后的连续空间存储反序列化为变量,从而将连续空间存储的修改应用到所述对象上。
19.在一种可能的实现方式中,在将连续空间存储的修改应用到所述对象上之后,所述方法还包括:
20.通过所述申请修改接口调用属性命令,实现属性修改的撤销或重做功能,其中所述属性命令存储了被修改的对象的指针、修改前的连续空间存储、修改后的连续空间存储和修改路径的数组。
21.在一种可能的实现方式中,所述方法还包括:
22.在属性编辑面板的编辑类里,以成员变量的形式保存所述对象的中间对象;
23.对于待显示在属性编辑面板上的属性,调用所述中间对象的获取属性接口获取中间属性,将中间属性传入对应类型的属性编辑条目,创建出一条属性编辑空间。
24.第二方面,提供了一种使用序列化的属性编辑处理装置,包括:
25.生成模块,用于通过对象,生成所述对象的中间对象;其中所述对象的属性待被编辑,且所述对象的属性通过所述对象中的一个或多个变量来表示,在所述中间对象中所述对象的实例的变量被序列化为连续空间存储;通过所述对象中的一个或多个变量,创建生成各个变量的中间属性;
26.查找模块,用于根据所述对象中待被编辑的变量的路径,在创建生成的各个变量的中间属性中查找到对应的目标中间属性;
27.处理模块,用于通过所述目标中间属性的访问接口和修改接口,根据所述对象中待被编辑的变量的修改信息对所述中间对象中的连续空间存储进行修改,并将连续空间存
储的修改应用到所述对象上。
28.在一种可能的实现方式中,所述生成模块还用于:
29.遍历对象的类型信息,生成所述对象对应的类型信息结构;
30.以生成所述对象对应的类型信息结构相同的顺序,对所述对象的实例的变量进行遍历,将所述对象的实例的变量序列化为连续空间存储,从而生成包括成员变量类型信息结构和连续空间存储的中间对象。
31.在一种可能的实现方式中,所述处理模块还用于:
32.实现序列化管理类,用于维护从所述对象的指针到连续空间存储的映射;每次在同一帧内需要将所述对象的实例的变量序列化为连续空间存储时,调用序列化管理类的对象到连续空间存储接口,从映射中查询是否已经存在被序列化过的连续空间存储,若存在则直接赋值,否则调用序列化接口生产连续空间存储并存储在映射中。
33.在一种可能的实现方式中,所述各个变量的中间属性中的多个成员变量,分别以指针的形式指向所述中间对象中的成员变量。
34.在一种可能的实现方式中,所述处理模块还用于:
35.调用所述对象的中间对象中的申请修改接口,根据所述对象对应的类型信息结构,将修改后的连续空间存储反序列化为变量,从而将连续空间存储的修改应用到所述对象上。
36.在一种可能的实现方式中,所述处理模块还用于:
37.在将连续空间存储的修改应用到所述对象上之后,通过所述申请修改接口调用属性命令,实现属性修改的撤销或重做功能,其中所述属性命令存储了被修改的对象的指针、修改前的连续空间存储、修改后的连续空间存储和修改路径的数组。
38.在一种可能的实现方式中,所述装置还包括:
39.创建模块,用于在属性编辑面板的编辑类里,以成员变量的形式保存所述对象的中间对象;对于待显示在属性编辑面板上的属性,调用所述中间对象的获取属性接口获取中间属性,将中间属性传入对应类型的属性编辑条目,创建出一条属性编辑空间。
40.第三方面,提供了一种电子设备,该电子设备包括处理器和存储器,其中,所述存储器中存储有计算机程序,所述处理器被配置为运行所述计算机程序以执行上述任一项所述的使用序列化的属性编辑处理方法。
41.第四方面,提供了一种存储介质,所述存储介质存储有计算机程序,其中,所述计算机程序被配置为运行时执行上述任一项所述的使用序列化的属性编辑处理方法。
42.借由上述技术方案,本技术实施例提供的使用序列化的属性编辑处理方法和装置、电子设备及存储介质,该方法可以通过对象,生成对象的中间对象;其中对象的属性待被编辑,且对象的属性通过对象中的一个或多个变量来表示,在中间对象中对象的实例的变量被序列化为连续空间存储;通过对象中的一个或多个变量,创建生成各个变量的中间属性;根据对象中待被编辑的变量的路径,在创建生成的各个变量的中间属性中查找到对应的目标中间属性;通过目标中间属性的访问接口和修改接口,根据对象中待被编辑的变量的修改信息对中间对象中的连续空间存储进行修改,并将连续空间存储的修改应用到对象上。可以看到,本技术实施例采用中间属性类型代替变量名传递变量信息,只要是对象中的变量,中间属性都可以进行表示和修改,对数组元素和多重包含的变量也可直接进行编
辑操作;同时,中间属性封装了访问接口和修改接口,使得二次开发人员可以在编辑器类中安全、便捷地对变量进行编辑操作,实现对对象的属性的编辑。
附图说明
43.为了更清楚地说明本技术实施例的技术方案,下面将对本技术实施例描述中所需要使用的附图作简单地介绍。
44.图1是本技术实施例提供的使用序列化的属性编辑处理方法的流程图;
45.图2是本技术另一实施例提供的使用序列化的属性编辑处理的示意图;
46.图3是本技术实施例提供的类型信息结构的示意图;
47.图4是本技术实施例提供的树状结构顺序转化为数组的示意图;
48.图5是本技术实施例提供的由类作为对象生成类型信息结构的示意图;
49.图6是本技术实施例提供的对象的实例的变量被序列化为连续空间存储的示意图;
50.图7是本技术实施例提供的对连续空间存储的部分内容进行修改的示意图;
51.图8是本技术另一实施例提供的对连续空间存储的部分内容进行修改的示意图;
52.图9示出了本技术实施例提供的使用序列化的属性编辑处理装置的结构图;
53.图10示出了本技术另一实施例提供的使用序列化的属性编辑处理装置的结构图;
54.图11示出了本技术实施例提供的一种电子设备的结构图。
具体实施方式
55.下面将参照附图更详细地描述本技术的示例性实施例。虽然附图中显示了本技术的示例性实施例,然而应当理解,可以以各种形式实现本技术而不应被这里阐述的实施例所限制。相反,提供这些实施例是为了能够更透彻地理解本技术,并且能够将本技术的范围完整的传达给本领域的技术人员。
56.需要说明的是,本技术的说明书和权利要求书及上述附图中的术语“第一”、“第二”等是用于区别类似的对象,而不必用于描述特定的顺序或先后次序。应该理解这样使用在适当情况下可以互换,以便这里描述的本技术的实施例能够以除了在这里图示或描述的那些以外的顺序实施。此外,术语“包括”及其变体要被解读为意味着“包括但不限于”的开放式术语。
57.为了解决上述技术问题,本技术实施例提供了一种使用序列化的属性编辑处理方法,如图1所示,该使用序列化的属性编辑处理方法可以包括以下步骤s101至s104:
58.步骤s101,通过对象,生成对象的中间对象;其中对象的属性待被编辑,且对象的属性通过对象中的一个或多个变量来表示,在中间对象中对象的实例的变量被序列化为连续空间存储。
59.该步骤中,对象可以是组件或类等,本实施例对此不作限制。
60.步骤s102,通过对象中的一个或多个变量,创建生成各个变量的中间属性。
61.步骤s103,根据对象中待被编辑的变量的路径,在创建生成的各个变量的中间属性中查找到对应的目标中间属性。
62.步骤s104,通过目标中间属性的访问接口和修改接口,根据对象中待被编辑的变
量的修改信息对中间对象中的连续空间存储进行修改,并将连续空间存储的修改应用到对象上。
63.本技术实施例采用中间属性类型代替变量名传递变量信息,只要是对象中的变量,中间属性都可以进行表示和修改,对数组元素和多重包含的变量也可直接进行编辑操作;同时,中间属性封装了访问接口和修改接口,使得二次开发人员可以在编辑器类中安全、便捷地对变量进行编辑操作,实现对对象的属性的编辑。
64.本技术实施例中提供了一种可能的实现方式,上面步骤s101通过对象,生成对象的中间对象,具体可以包括以下步骤a1和a2:
65.步骤a1,遍历对象的类型信息,生成对象对应的类型信息结构。
66.该步骤中,类型信息结构可以是描述一个对象的类型信息的树,用于在中间对象中保存对象的类型信息,以便将其序列化为连续空间存储和解析连续空间存储内容。类型信息结构包括类型信息结构节点,每个类型信息结构节点对应类型中的一个变量。当变量的类型为类、结构体或数组时,该变量对应的类型信息结构节点可以进一步展开,从而形成整个类型信息结构的树。
67.步骤a2,以生成对象对应的类型信息结构相同的顺序,对对象的实例的变量进行遍历,将对象的实例的变量序列化为连续空间存储,从而生成包括成员变量类型信息结构和连续空间存储的中间对象。
68.本实施例可以准确、快速生成包括成员变量类型信息结构和连续空间存储的中间对象。
69.本技术实施例中提供了一种可能的实现方式,为了避免同一个对象在同一帧之内被多次序列化造成效率降低,实现了一个单例来维护从对象指针到连续连续空间存储的映射,具体可以包括以下步骤b1:
70.步骤b1,实现序列化管理类,用于维护从对象的指针到连续空间存储的映射;每次在同一帧内需要将对象的实例的变量序列化为连续空间存储时,调用序列化管理类的对象到连续空间存储接口,从映射中查询是否已经存在被序列化过的连续空间存储,若存在则直接赋值,否则调用序列化接口生产连续空间存储并存储在映射中。
71.该步骤中,每帧开始时清空映射中所有内容,保证数据的准确性。
72.本技术实施例中提供了一种可能的实现方式,中间属性是对中间对象中指定位置存储的值进行读写操作的类,上面步骤s102中创建的各个变量的中间属性中的多个成员变量,分别以指针的形式指向中间对象中的成员变量。
73.本技术实施例中提供了一种可能的实现方式,上面步骤s104将连续空间存储的修改应用到对象上,具体可以包括以下步骤c1:
74.步骤c1,调用对象的中间对象中的申请修改接口,根据对象对应的类型信息结构,将修改后的连续空间存储反序列化为变量,从而将连续空间存储的修改应用到对象上。
75.本实施例可以准确地将连续空间存储的修改应用到对象上,且灵活性高。
76.本技术实施例中提供了一种可能的实现方式,上面步骤s104将连续空间存储的修改应用到对象上之后,还可以包括以下步骤d1:
77.步骤d1,通过申请修改接口调用属性命令,实现属性修改的撤销或重做功能,其中属性命令存储了被修改的对象的指针、修改前的连续空间存储、修改后的连续空间存储和
修改路径的数组。
78.本实施例将撤销或重做等功能实现在接口内部,从而满足了属性修改的需求,解决了现有技术通过指针直接获取对象数据进行编辑无法满足在编辑器进行撤销或重做的问题,且无需二次开发的人员手动添加响应的代码,效率高且安全性高。
79.本技术实施例中提供了一种可能的实现方式,3d图形引擎许多功能的编辑器拓展都需要用到自定义的属性编辑面板,此时可以使用中间对象配合属性编辑条目实现属性编辑功能,具体可以包括以下步骤e1和e2:
80.步骤e1,在属性编辑面板的编辑类里,以成员变量的形式保存对象的中间对象。
81.该步骤中,在属性编辑面板初始化或者需要显示的对象发生修改时调用中间对象的init(初始化)函数,通常每种类型的对象对应一个中间对象。对于多选的情况,同一类型的对象多选时可以对应同一个中间对象。
82.步骤e2,对于待显示在属性编辑面板上的属性,调用中间对象的获取属性接口获取中间属性,将中间属性传入对应类型的属性编辑条目,创建出一条属性编辑空间。
83.本实施例可以将中间属性类直接传递给界面层满足了编辑器界面属性编辑方式定制的需求。
84.以上介绍了图1所示实施例的各个环节的多种实现方式,下面将通过具体实施例对本技术实施例的使用序列化的属性编辑处理方法做进一步说明。
85.3d图形引擎经常需要程序员在编辑器模块中对自己开发的新的类型和组件进行编辑器相关拓展的二次开发,二次开发中最常实现的功能就是属性修改和编辑器界面属性编辑方式定制。
86.编辑器模块中的属性修改,不同于运行期只需直接赋值,在编辑器中需要考虑到这次属性修改是否支持撤销或重做,是否可以被预制体系统记录下修改信息等,如果只进行赋值操作而不考虑上述两点,则在使用二次开发的编辑器模块时会发生无法保存和使用不便等问题。
87.编辑器界面属性编辑方式定制,需要解决的痛点是如何将需要编辑的对象的指定属性所有相关的反射信息通过一种简单的方式获取和传递给界面。
88.在下面的实施例中,object即对象,intermediateobject即中间对象,buffer即连续空间存储,intermediateproperty即中间属性,typeinfostructure即类型信息结构,typeinfostructurenode即类型信息结构节点,map即映射,typeinfostructureiterator即类型信息结构迭代器,serializedbuffermanager即序列化管理,objecttobuffer即对象到连续空间存储,applytoobject即申请修改,propertycommand即属性命令,propertyeditentry即属性编辑条目,getproperty即获取属性,propetypath即变量的路径。
89.这里,object是3d图形引擎中绝大部分类的基类,该类定义了引擎对象的一些基本功能,如创建、销毁序列化、类型转换、安全引用等。object作为基类,所有继承自这个基类的都可以用本实施例提供的方法进行修改。
90.本实施例实现了一种使用序列化的属性编辑封装方案,将被编辑的对象(如组件或类型等)封装成intermediateobject类,对象的属性封装成intermediateproperty类,并实现了get(访问)接口和set(修改)接口,将撤销或重做、记录typeinfostructure预制体修
改信息等功能实现在接口内部,从而满足了属性修改的需求;将intermediateproperty类直接传递给界面层满足了编辑器界面属性编辑方式定制的需求。
91.intermediateobject和intermediateproperty的设计目的是为了提供一个在编辑器模块中方便地修改某个object中指定路径的值的通用方法。
92.图2是本技术另一实施例提供的使用序列化的属性编辑处理的示意图,在图2中,通过object生成intermediateobject;然后通过intermediateobject的getproperty接口,根据object中待被编辑的变量的路径propetypath,在创建生成的各个变量的intermediateproperty中查找到对应的目标intermediateproperty;再通过intermediateproperty的get接口和set接口对intermediateobject中的buffer进行修改,最后将buffer的修改应用到object上。在编辑器中所有的变量赋值操作都可以通过intermediateobject和intermediateproperty的相关接口进行,使用这套接口进行赋值操作可以自动帮助用户实现调用set(设置)函数和markprefabmodification(记录预制体修改信息)等功能,同时还支持undo(撤销)和redo(重做),省去写赋值操作需要考虑各种情况的问题。
93.下面将分几个部分介绍这套系统的设计。
94.1.typeinfostructure、typeinfostructurenode和typeinfostructureiteratortypeinfostructure是描述一个object类型信息的树,可以用于在intermediateobject中保存object的类型信息,以便将其序列化为buffer和解析buffer内容。typeinfostructure的节点为typeinfostructurenode,每个typeinfostructurenode对应类型中的一个变量。当变量的类型为类、结构体或数组时,该变量对应的typeinfostructurenode可以进一步展开,从而形成整个类型信息结构的树,如图3中简化示意了typeinfostructurenode依树状结构顺序组成typeinfostructure。
95.typeinfostructurenode在typeinfostructure中以数组的形式存储。typeinfostructurenode在typeinfostructure中依据树状结构以深度优先的遍历顺序形成一个数组,由节点在数组中的位置和节点中成员变量level(水平)的值可以确定节点在树状结构中的位置和父、子、兄弟节点等,图4是一个树状结构顺序转化为数组的例子。
96.继续参见图3,typeinfostructureiterator是用于访问typeinfostructure内容的类型,一个typeinfostructureiterator和一个typeinfostructurenode一一对应。typeinfostructureiterator的成员变量由typeinfostructure指针和index(索引)组成,index为其对应的typeinfostructurenode在typeinfostructure的数组中的位置。typeinfostructure一旦生成不允许进行再次修改,所有对typeinfostructure的访问都应通过typeinfostructureiterator进行。typeinfostructureiterator的常用接口有两类,第一类是father()、children()、next()、last()等用于遍历typeinfostructure的接口,第二类是typename()、name()、datamember()等用于访问typeinfostructurenode内容的接口。
97.2.序列化
98.与intermediateobject有关的序列化主要分为四类,全部以静态函数的形式定义在typeinfostructureserialization(类型信息结构序列化)中。
99.2.1由object生成typeinfostructure
100.通过遍历object的类型信息生成该object对应的typeinfostructure,图5是由类example(例子)定义生成typeinfostructure的一个示例。
101.若当前处理的变量为指针、简单类型、字符串、objectreference(对象引用)时,只需根据类型信息给当前节点的type(类型)、ispointer(是否指针)和bytesize(字节大小)赋值即可,其中字符串由于不确定大小,bytesize为-1。这里的简单类型中,classdescriptor(反射类描述符)为空。
102.若为其他情况,即类或结构体时,需遍历所有成员变量依次对其调用生成typeinfostructure的函数,并在生成完毕后对节点的datamember(数据成员)和isarraymember(是否数组成员)赋值。
103.需要注意的是,由于对数组信息的记录比较特殊(例如数组内元素不存在自己的datamember),生成typeinfostructure的函数没有对数组类型的变量直接进行处理,对数组的处理包含在类或结构体遍历成员变量的部分。当成员变量是数组元素时,首先创建一个对应整个数组的节点,该节点的datamember即数组变量的datamember,isarraymember为0。然后以该数组节点为父节点创建一个数组大小节点,该节点的datamember依然是数组变量的datamember,isarraymember为1,type为uint32。最后以数组节点为父节点创建第二个子节点,为数组元素节点,该节点的datamember依然是数组变量的datamember(因为数组内元素没有自己的datamember),isarraymember为2,对数组元素调用生成typeinfostructure的函数继续向下遍历类型信息。无论实际的数组大小是多少,这里都生成且仅生成一个数组元素节点。
104.依上述规则对类型信息进行深度优先的遍历,从而生成出完整的typeinfostructure。
105.生成出的typeinfostructure默认的根节点,即level=0的节点为一个空节点,level=1的节点有且仅有一个,对应整个object,从level=2层开始对object依次进行展开,注意此处生成时一定要遵守深度优先的顺序进行,否则typeinfostructure的addchild(添加子项)接口无法正确添加子节点。
106.2.2变量被序列化为连续buffer
107.将变量序列化为连续buffer又分为两个接口,objecttobuffer和partobjecttobuffer(部分对象到连续空间存储)。这两个接口的实现是相同的,区别只在于一个接受的参数是object指针,一个是blockpointer(区块指针),因此后者即使只传入一个int(整数)类型的变量也可以序列化为连续buffer,而前者必须保证被序列化的变量类型继承自object。
108.将变量序列化为连续buffer时不需要依赖typeinfostructure,但需要以和生成typeinfostructure相同的顺序对变量的进行遍历,否则序列化产生的连续buffer无法在后续依靠typeinfostructure进行解析和修改,图6是由对象为类的实例生成连续buffer“35hellopres2guid1guid2111.52”的一个例子。
109.若变量为指针类型,则直接在buffer中记录指针的值,大小为指针长度。
110.若变量为简单类型(classdescriptor为空),则直接记录变量的值,大小为类型长度。
111.若变量为objectreference或safegameobjectpointer(安全指针)类型,则记录其
对应的guid(全局唯一标识符)的值,大小为guid长度。
112.若变量为cxstring(字符串)类型,先用一个uint32的大小记录字符串长度,再记录字符串的值。
113.若变量为数组类型,先用一个uint32大小记录数组长度,在依次记录每个数组元素的值。
114.若变量为类或结构体,遍历记录其成员变量的值。注意此处成员变量的遍历顺序依然是先子类后父类,与typeinfostructure节点顺序保持一致。
115.2.3连续buffer反序列化为变量
116.将连续buffer反序列化为变量时也分为两个接口,分别是buffertoobject(连续空间存储到对象)和buffertopartobject(连续空间存储到部分对象)。两者的实现有所不同,第一个接口需传入一个object指针作为参数,方法会将buffer上的修改应用到传入的object上。而第二个接口无需传入已有的变量,方法会创建一个该类型的变量并以返回值的形式返回给调用者,但调用者需注意在使用完毕后应手动delete(删除)被创建的变量,否则将造成内存泄漏。
117.buffertoobject一共有五个参数,分别是待修改的object指针,被修改过的buffer,object和buffer对应的typeinfostructure,包含object所有修改条目的modifypath(修改路径)和控制是否在修改发生时调用set函数(如果有)的布尔值。方法将根据typeinfostructure同时遍历object的所有变量和其对应的buffer值,如果发现当前变量的变量名路径在modifypath数组中且控制是否调用set函数的布尔值为true且变量绑定了set函数,则调用set函数;如果发现当前变量名路径在modifypath数组中,但不满足上述条件,则比较内存值是否相同来决定是否修改;如果发现当前变量名路径不在modifypath中,则不进行修改。
118.buffertopartobject一共有四个参数,分别是被修改过的buffer,变量对应的值在buffer中的pos(位置),变量的路径和变量对应的typeinfostructureiterator。方法先根据typeinfostructureiterator指示的类型创建相应大小的内存空间。然后对这段内存空间以和上个方法相似的方式进行遍历并应用buffer上的修改,在修改的过程中无需考虑modifypath和控制set函数的布尔值,因为这次修改默认对全部内容都应用修改且总是调用set函数。
119.2.4对连续buffer的部分内容进行修改
120.对连续buffer的部分内容进行修改的方法为modifytobuffer(修改连续空间存储),接受三个输入参数:被修改的变量对应的typeinfostructureiterator,修改到的新值newvaluebuffer(新值连续空间存储)和被修改的buffer。
121.对长度确定的buffer进行修改时,只需找到变量在buffer中的起始位置,然后将newvaluebuffer替换进去即可,如图7所示。
122.当被修改的是字符串或数组等不定长度的变量时,还需找到在原本的buffer中变量结束的位置,将这段buffer从整体中移除,再插入新的buffer,如图8所示。
123.3.intermediateobject和intermediateproperty
124.intermediateobject和intermediateproperty是外部对这个方案进行调用的主要接口,接下来将分别介绍这两个类的内容。
125.3.1intermediateobject
126.intermediateobject是存储了object的序列化信息和外部修改信息的类,通过这些信息可以承担起将编辑器对object的修改相关操作封装起来,并应用到object上的作用。
127.intermediateobject包含的变量包括uint32 intermediateobject version(版本)、vector《safeobjectpointer》objects、typeinfostructure、buffer、ismodify(是否修改)、modifypath等等,这些变量一方面存储了单个object所需的全部信息,还存储了多选时的一些额外信息,以便处理多选赋值的情况:
128.1)version在每次buffer更新时同步更新,以便核对intermediateproperty是否同步到了最新版的intermediateobject。
129.2)objects数组存储了被序列化的对象的指针。
130.3)typeinfostructure为objects数组第一个对象生成的typeinfostructure。
131.4)buffer为objects数组第一个对象序列化产生的连续buffer,和typeinfostructure都可以通过上面序列化一节中的相关接口生成。
132.5)ismodify记录buffer是否被修改。
133.6)modifypath记录修改路径。
134.7)parentintermediateobject(父中间属性)处理当前intermediateobject为被展开的指针类型的情况,记录了该指针类型所属的intermediateobject,以便用户获取和使用。
135.8)isdifferentcachedirty(是否隐藏不同)和isdifferent(是否不同)记录了多选情况下其余object和objects数组第一个object的不同之处。
136.9)maxarraysize(最大数组大小)和minarraysizes(最小数组大小)记录了多选情况下数组大小的不同之处。
137.10)multitypeinfostructures(多类型信息结构)记录了多选情况下其余object生成的typeinfostructure。
138.intermediateobject的常用接口为init,update(更新),getproperty,modifyproperty(修改属性)和applymodification。
139.(1)init接受参数为object数组,用于初始化intermediateobject状态。首先将所有变量的值设为初始值,然后用传参数给objects数组赋值,接着将typeinfostructure设为objects第一个元素生成的typeinfostructure,最后执行一次update即完成了init过程。
140.(2)update通常用于每帧更新buffer,有时也会在需要使用指针内容等地方强行调用以确保正确性。update时首先清空modify(修改)列表,然后从objects数组第一个元素更新buffer,更新version的值,最后处理多选情况下的额外信息。
141.(3)getproperty用于根据propetypath给出对应的intermediateproperty,使用时需注意进行返回值判断,若返回false(错误的),则未找到对应路径下的intermediateproperty。
142.(4)modifyproperty用于记录buffer中受到的变量修改,输入参数为修改路径。首先将ismodify置为true,然后再modifypath中添加修改路径,接着将isdifferent中修改路
径对应的值置为false,最后更新version。
143.(5)applymodification用于将buffer上的修改应用到objects上,其中又分为applymodification和applymodificationwithoutundo两个接口,后者只进行赋值操作,不处理加入undo(撤销)或redo(重做)队列等逻辑,前者自动将修改加入undo或redo队列并markmodify(标记修改)和调用inspector检查器函数等。在函数实现中,首先调用反序列化接口将buffer修改应用到objects数组第一个元素上,然后处理多选情况,对其余object依次生成typeinfostructure和buffer,遍历modifypath,对每条modifypath将第一个object的buffer上的修改应用到当前object的buffer上,并调用反序列化接口将buffer修改应用到当前object上,最后将ismodify设为true并清空modifypath数组即可。
144.3.2intermediateproperty
145.intermediateproperty是对intermediateobject中指定位置存储的值进行读写操作的类。常用方法是getvalue和setvalue,用来访问和修改buffer内容。
146.intermediateproperty中包含的变量有intermediateobject、isvalid、intermediateobjectversion、object等,许多信息是以指针的形式指向intermediateobject中成员变量的,因此需保证当使用intermediateproperty时,其指向的intermediateobject不能被释放,即intermediateobject的生命周期需大于等于所有使用它的intermediateproperty。下面介绍一下变量的含义:
147.1)intermediateobject是指向使用的intermediateobject的指针。
148.2)isvalid记录getproperty是否成功,若失败则byteoffset的值不可靠,进行访问和修改等操作。
149.3)intermediateobjectversion在被intermediateobject更新时同步,当需要访问或修改时,需要校验version是否一致。若不一致则应先同步再访问,否则byteoffset的值可能不对。
150.4)object记录intermediateobject的objects数组中第一个元素。
151.5)typeinfostructureiterator为当前property在intermediateobject的typeinfostructure中对应的类型节点。
152.6)buffer为指向intermediateobject中buffer的指针。
153.7)propertypath为当前intermediateproperty的路径,类型展开用'.'连接,数组元素用'[]'表示。
[0154]
8)byteoffset为当前变量对应的内存块在buffer数组中的起始位置。
[0155]
9)stack是记录了当前变量向上找自己所属的父级类型的堆栈,除typeinfostructureiterator外还额外记录了一些数组信息。
[0156]
10)materialshadervartype(材料着色变量类型)是专门用于记录material(材料)的shadervar(着色变量)类型信息的变量,非material的shadervar时值为unknown。后续可将material的shadervar的存储方式优化为variable(变量)之类的通用容器,从而避免此处的特殊处理。
[0157]
下面介绍几个intermediateproperty的常用接口及其实现:
[0158]
(1)syncintermediateobjectversion用于同步version,若当前version一致则不执行,否则重新执行一次getproperty。若getproperty失败则将propertypath的值保留,
isvalid置为false。
[0159]
(2)getproperty只允许intermediateobject调用,在调用之前需保证当前intermediateproperty的值为初始值,若不是初始值则只能在typeinfostructure中处于当前变量之后的变量中查询。每次从当前变量向后找一个,如果找到的路径属于目标路径的一部分,则继续向子节点寻找;否则跳过当前变量的所有子节点,直接从下一个兄弟节点(若没有就找父节点的兄弟节点,以此类推)向后寻找。若成功找到路径相同的变量则返回true,若全部遍历完毕也没找到则返回false。
[0160]
(3)clear将所有成员变量赋为初始值,isvalid置为false。
[0161]
(4)getvalue是一个模板函数,调用时需要显式传入value的类型。首先同步version;然后校验模板类型和typeinfostructureiterator记录的类型是否一致;接着调用反序列化接口,以byteoffset在buffer中指向的位置为连续buffer的起始地址,根据类型将这段连续buffer反序列化为该类型的变量,这里会进行一次变量的拷贝,拷贝后将buffertopartobject返回的内存删除,避免内存泄漏;最后将序列化得到的变量返回。
[0162]
(5)setvalue是一个模板函数,模板类型可以通过函数参数的类型隐式传入。首先同步version;然后对数值类型处理valuerange语义;接着校验类型,若是数组大小则调resizearray,否则调用partobjecttobuffer将传入的参数序列化为连续buffer;最后将这段连续buffer替换掉buffer中原有位置并调用markpropertymodified即可。
[0163]
(6)resizearray接受一个参数为新的数组大小。首先校验当前type是否是数组类型;然后对于数组大小增加的情况,默认复制数组最后一个元素的值,若后续反射系统支持了默认值的绑定此处可进行修改,对于数组大小减小的情况直接计算出新数组大小对应的buffer大小即可;接着对bufffer进行相应的增或删操作并修改buffer中记录的数组大小;最后调用markpropertymodified并维护intermediateobject中minarraysizes的值即可。
[0164]
(7)removearrayelementatindex接受一个参数为被移除的元素的下标,该函数固定将数组大小减小1。实现与resizearray很相似,唯一的区别是在校验类型之后需将被移除的元素对应的buffer移动到数组最后一位,原本在其后的元素的buffer依次前移一位。
[0165]
(8)movearrayelement接受两个参数,需要移动的元素下标和移动到的目标位置下标。首先还是校验type是否是数组类型,然后计算出需要移动的元素的位置和大小,将其移动到目标位置,并将两者之间的其余元素依次前移或后移一位。
[0166]
(9)markpropertymodified(标记属性已修改)调用intermediateobject的markpropertymodified,若调用之前version处于同步状态则继续同步,否则不同步。该函数一般在intermediateproperty内部自动调用,不需要外部调用。
[0167]
3.3serializedbuffermanager
[0168]
为避免同一个object在同一帧之内被多次序列化造成效率降低,实现了一个单例来维护从object指针到连续buffer的map映射。
[0169]
每次需要将object序列化为连续buffer时,应调用serializedbuffermanager的objecttobuffer接口,从map中查询是否已经存在被序列化过的连续buffer,若存在则直接赋值,否则调用序列化接口生产并存在map中。
[0170]
每帧开始时清空map中所有内容。
[0171]
4.propertycommand
[0172]
propertycommand实现了属性修改的撤销和重做功能。内部存储了被修改的object的指针,修改前的buffer,修改后的buffer和修改路径的数组。
[0173]
撤销和重做时首先使用object生成typeinfostructure,根据buffer、typeinfostructure和修改路径将修改应用到object上;然后调用oninspector和onchanged函数;最后markmodify即可。
[0174]
这个command目前仅在intermediateobject的applymodification内部调用,使用时只需调intermediateobject接口即可自动创建命令,无需手动创建。
[0175]
5.使用方式
[0176]
5.1赋值
[0177]
当不使用intermediateobject时,在editor类里修改属性的代码如下所示,虽然也可以成功进行属性修改,但是无法撤销,也无法保存对typeinfostructure预制体实例的修改。
[0178][0179]
使用intermediateobject修改属性的代码如下所示,只需知道变量路径,即可对任意绑定的变量进行取值和赋值。在applymodification中自动实现了支持撤销和重做、记录预制体实例修改、调用set函数和oninspector函数等功能。
[0180][0181]
调用applymodification之前如果调用了多次setvalue则会被合并进一次撤销操作中,若希望分次撤销可在每次setvalue后立即调用applymodification。applymodification也接受basecommand*类型的参数,若参数不为空,则本次赋值操作将成为传入参数的子操作,用户可自行决定如何处理本次操作。
[0182]
applymodification的另一个版本的接口applymodificationwithoutundo,若调用该接口则只执行赋值和调用set函数两项操作,其余均不执行。
[0183]
5.2创建属性编辑控件
[0184]
引擎许多功能的编辑器拓展都需要用到自定义的属性编辑面板,此时可以使用intermediateobject配合propertyeditentry实现属性编辑功能。
[0185]
intermediateobject通常在面板的编辑类里以成员变量的形式保存下来。在面板初始化或者需要显示的object发生修改时调用intermediateobject的init函数,通常每种类型的object对应一个intermediateobject,此处注意考虑如何处理多选情况,同一类型的object多选时对应同一个intermediateobject。
[0186]
对于希望显示在面板上的属性,可以调用getproperty函数获取intermediateproperty,然后将intermediateproperty传入对应类型的propertyeditentry即可创建出一条属性编辑空间,下面是一个简单的例子。
[0187]
intermediateproperty*localposprop=new intermediateproperty;
[0188]
m_intermediateobject.getproperty("m_localposition",*localposprop);
[0189]
layout()-》addwidget(new propertyeditentryvector3(localposprop,"local position"));
[0190]
事实上,对于不同类型的变量通常需要创建不同类型的propertyeditentry进行显示,因此在上面的例子中还需要调用intermediateproperty的gettypeinfostructureiterator().type()接口获取属性,根据属性创建对应的样式。本实施例提供了一种默认的根据类型创建控件的方法,如果有特殊需求也可自行判断,默认
方法的使用方式如下所示。
[0191][0192][0193]
通过反射拿到类型所有的成员变量名后即可通过上面的for循环将所有绑定的变量的编辑控件显示在面板上。
[0194]
面板的编辑类应每帧调用intermediateobject的update函数,保证界面显示的属性和object的实际属性同步。
[0195]
关闭时调用clear函数清空intermediateobject数据。
[0196]
本实施例实现的是对现有方案的升级,主要有以下两项优点:
[0197]
1)用intermediateproperty类型代替变量名传递变量信息,大大增加了自定义绘制的灵活性,对数组元素和多重包含的变量也可直接进行编辑操作。
[0198]
2)同时intermediateproperty封装了get和set接口,使得二次开发人员可以在编辑器类中安全地对变量进行编辑操作的同时自动化完成了撤销和重做以及记录typeinfostructure预制体信息的功能。
[0199]
需要说明的是,上述实施例中各步骤的序号的大小并不意味着执行顺序的先后,各过程的执行顺序应以其功能和内在逻辑确定,而不应对本技术实施例的实施过程构成任何限定。实际应用中,上述所有可能的实施方式可以采用结合的方式任意组合,形成本技术的可能的实施例,在此不再一一赘述。
[0200]
基于上文各个实施例提供的使用序列化的属性编辑处理方法,基于同一发明构思,本技术实施例还提供了一种使用序列化的属性编辑处理装置。
[0201]
图9是本技术实施例提供的使用序列化的属性编辑处理装置的结构图。如图9所示,该使用序列化的属性编辑处理装置具体可以包括生成模块910、查找模块920以及处理模块930。
[0202]
生成模块910,用于通过对象,生成所述对象的中间对象;其中所述对象的属性待被编辑,且所述对象的属性通过所述对象中的一个或多个变量来表示,在所述中间对象中所述对象的实例的变量被序列化为连续空间存储;通过所述对象中的一个或多个变量,创建生成各个变量的中间属性;
[0203]
查找模块920,用于根据所述对象中待被编辑的变量的路径,在创建生成的各个变量的中间属性中查找到对应的目标中间属性;
[0204]
处理模块930,用于通过所述目标中间属性的访问接口和修改接口,根据所述对象中待被编辑的变量的修改信息对所述中间对象中的连续空间存储进行修改,并将连续空间存储的修改应用到所述对象上。
[0205]
本技术实施例中提供了一种可能的实现方式,所述生成模块910还用于:
industry standard architecture,扩展工业标准结构)总线等。总线1102可以分为地址总线、数据总线、控制总线等。为便于表示,图11中仅用一条粗线表示,但并不表示仅有一根总线或一种类型的总线。
[0220]
存储器1103可以是rom(read only memory,只读存储器)或可存储静态信息和指令的其他类型的静态存储设备,ram(random access memory,随机存取存储器)或者可存储信息和指令的其他类型的动态存储设备,也可以是eeprom(electrically erasable programmable read only memory,电可擦可编程只读存储器)、cd-rom(compact disc read only memory,只读光盘)或其他光盘存储、光碟存储(包括压缩光碟、激光碟、光碟、数字通用光碟、蓝光光碟等)、磁盘存储介质或者其他磁存储设备、或者能够用于携带或存储具有指令或数据结构形式的期望的程序代码并能够由计算机存取的任何其他介质,但不限于此。
[0221]
存储器1103用于存储执行本技术方案的计算机程序代码,并由处理器1101来控制执行。处理器1101用于执行存储器1103中存储的计算机程序代码,以实现前述方法实施例所示的内容。
[0222]
其中,电子设备包括但不限于:移动电话、笔记本电脑、数字广播接收器、pda(个人数字助理)、pad(平板电脑)、pmp(便携式多媒体播放器)、车载终端(例如车载导航终端)等等的移动终端以及诸如数字tv、台式计算机等等的固定终端。图11示出的电子设备仅仅是一个示例,不应对本技术实施例的功能和使用范围带来任何限制。
[0223]
基于同一发明构思,本技术实施例还提供了一种存储介质,该存储介质中存储有计算机程序,其中,计算机程序被设置为运行时执行上述任意一个实施例的使用序列化的属性编辑处理方法。
[0224]
所属领域的技术人员可以清楚地了解到,上述描述的系统、装置、模块的具体工作过程,可以参考前述方法实施例中的对应过程,为简洁起见,在此不另赘述。
[0225]
本领域普通技术人员可以理解:本技术的技术方案本质上或者该技术方案的全部或部分可以以软件产品的形式体现出来,该计算机软件产品存储在一个存储介质中,其包括若干程序指令,用以使得一电子设备(例如个人计算机,服务器,或者网络设备等)在运行所述程序指令时执行本技术各实施例所述方法的全部或部分步骤。而前述的存储介质包括:u盘、移动硬盘、只读存储器(rom)、随机存取存储器(ram)、磁碟或者光盘等各种可以存储程序代码的介质。
[0226]
或者,实现前述方法实施例的全部或部分步骤可以通过程序指令相关的硬件(诸如个人计算机,服务器,或者网络设备等的电子设备)来完成,所述程序指令可以存储于一计算机可读取存储介质中,当所述程序指令被电子设备的处理器执行时,所述电子设备执行本技术各实施例所述方法的全部或部分步骤。
[0227]
以上各实施例仅用以说明本技术的技术方案,而非对其限制;尽管参照前述各实施例对本技术进行了详细的说明,本领域的普通技术人员应当理解:在本技术的精神和原则之内,其依然可以对前述各实施例所记载的技术方案进行修改,或者对其中部分或者全部技术特征进行等同替换;而这些修改或者替换,并不使相应技术方案脱离本技术的保护范围。

技术特征:
1.一种使用序列化的属性编辑处理方法,其特征在于,包括:通过对象,生成所述对象的中间对象;其中所述对象的属性待被编辑,且所述对象的属性通过所述对象中的一个或多个变量来表示,在所述中间对象中所述对象的实例的变量被序列化为连续空间存储;通过所述对象中的一个或多个变量,创建生成各个变量的中间属性;根据所述对象中待被编辑的变量的路径,在创建生成的各个变量的中间属性中查找到对应的目标中间属性;通过所述目标中间属性的访问接口和修改接口,根据所述对象中待被编辑的变量的修改信息对所述中间对象中的连续空间存储进行修改,并将连续空间存储的修改应用到所述对象上。2.根据权利要求1所述的方法,其特征在于,通过对象,生成所述对象的中间对象,包括:遍历对象的类型信息,生成所述对象对应的类型信息结构;以生成所述对象对应的类型信息结构相同的顺序,对所述对象的实例的变量进行遍历,将所述对象的实例的变量序列化为连续空间存储,从而生成包括成员变量类型信息结构和连续空间存储的中间对象。3.根据权利要求2所述的方法,其特征在于,所述方法还包括:实现序列化管理类,用于维护从所述对象的指针到连续空间存储的映射;每次在同一帧内需要将所述对象的实例的变量序列化为连续空间存储时,调用序列化管理类的对象到连续空间存储接口,从映射中查询是否已经存在被序列化过的连续空间存储,若存在则直接赋值,否则调用序列化接口生产连续空间存储并存储在映射中。4.根据权利要求1至3中任一项所述的方法,其特征在于,所述各个变量的中间属性中的多个成员变量,分别以指针的形式指向所述中间对象中的成员变量。5.根据权利要求2所述的方法,其特征在于,所述将连续空间存储的修改应用到所述对象上,包括:调用所述对象的中间对象中的申请修改接口,根据所述对象对应的类型信息结构,将修改后的连续空间存储反序列化为变量,从而将连续空间存储的修改应用到所述对象上。6.根据权利要求5所述的方法,其特征在于,在将连续空间存储的修改应用到所述对象上之后,所述方法还包括:通过所述申请修改接口调用属性命令,实现属性修改的撤销或重做功能,其中所述属性命令存储了被修改的对象的指针、修改前的连续空间存储、修改后的连续空间存储和修改路径的数组。7.根据权利要求1所述的方法,其特征在于,所述方法还包括:在属性编辑面板的编辑类里,以成员变量的形式保存所述对象的中间对象;对于待显示在属性编辑面板上的属性,调用所述中间对象的获取属性接口获取中间属性,将中间属性传入对应类型的属性编辑条目,创建出一条属性编辑空间。8.一种使用序列化的属性编辑处理装置,其特征在于,包括:生成模块,用于通过对象,生成所述对象的中间对象;其中所述对象的属性待被编辑,且所述对象的属性通过所述对象中的一个或多个变量来表示,在所述中间对象中所述对象
的实例的变量被序列化为连续空间存储;通过所述对象中的一个或多个变量,创建生成各个变量的中间属性;查找模块,用于根据所述对象中待被编辑的变量的路径,在创建生成的各个变量的中间属性中查找到对应的目标中间属性;处理模块,用于通过所述目标中间属性的访问接口和修改接口,根据所述对象中待被编辑的变量的修改信息对所述中间对象中的连续空间存储进行修改,并将连续空间存储的修改应用到所述对象上。9.一种电子设备,其特征在于,包括处理器和存储器,其中,所述存储器中存储有计算机程序,所述处理器被配置为运行所述计算机程序以执行权利要求1至7中任一项所述的使用序列化的属性编辑处理方法。10.一种存储介质,其特征在于,所述存储介质中存储有计算机程序,其中,所述计算机程序被配置为运行时执行权利要求1至7中任一项所述的使用序列化的属性编辑处理方法。

技术总结
本申请提供了一种使用序列化的属性编辑处理方法和装置、设备及介质,涉及软件技术领域。该方法通过对象,生成对象的中间对象;通过对象中的一个或多个变量,创建生成各个变量的中间属性;本申请实施例采用中间属性类型代替变量名传递变量信息,只要是对象中的变量,中间属性都可以进行表示和修改;同时,封装了访问接口和修改接口,使得二次开发人员可以在编辑器类中安全、便捷地对变量进行编辑操作,实现对对象的属性的编辑。现对对象的属性的编辑。现对对象的属性的编辑。


技术研发人员:崔铭 池婧雯 傅晨阳 冯星 李荣华 方顺
受保护的技术使用者:北京渲光科技有限公司
技术研发日:2023.04.07
技术公布日:2023/7/21
版权声明

本文仅代表作者观点,不代表航空之家立场。
本文系作者授权航家号发表,未经原创作者书面授权,任何单位或个人不得引用、复制、转载、摘编、链接或以其他任何方式复制发表。任何单位或个人在获得书面授权使用航空之家内容时,须注明作者及来源 “航空之家”。如非法使用航空之家的部分或全部内容的,航空之家将依法追究其法律责任。(航空之家官方QQ:2926969996)

飞行汽车 https://www.autovtol.com/

分享:

扫一扫在手机阅读、分享本文

相关推荐