Blender文档翻译-Blender库数据的通用属性

 Blender库数据的通用属性

引言

Blender现在支持在所有库数据中存储自定义数据(如对象、材料、纹理、几何体,如网格、曲线,元球,场景和更多)。现在渲染导出、游戏导出和需要它的任何脚本类型都可以将数据存储到.blend附加到库数据中。

称之为ID属性系统,因为所有的属性存储在所有库数据都有的唯一ID结构中。

它是如何工作的

属性由以下基本类型组成:

  • Array:简单一维float或int型数组 a simple one-dimensional array of either floats or ints
  • String: 字符串
  • Group: 一组属性
  • Float: 浮点数
  • Int: 整数

另外,属性都有(明显地)一个名字。

标准

有一个专用的ID属性标准页在BlenderDev/PropertyStandards这里。请与其他作者一起工作形成自己脚本标准,这个想法是为了避免每个脚本都有一套独特的属性。

 Python教程

从python的角度看使用ID属性是很容易的。下面示例代码展示了它的简单性:

 1 import Blender
 2 from Blender import Material
 3 mat = Material.Get("Material")
 4  
 5 # get a property
 6 try:
 7     TranslucencyFactor = mat.properties['SomeRenderer']['TransFac']
 8 except:
 9     TranslucencyFactor = 0.0
10     mat.properties['SomeRenderer']={}
11     mat.properties['SomeRenderer']['TransFac'] = 0.0
12  
13 # some more code to demonstrate how to make groups, arrays, etc.
14 mat.properties['a float array'] = [0.0, 1.0, 2.0]
15 mat.properties['a group'] = {"IntArray": [1, 2, 3], "AnotherGroup": {"int": 1}}
16 mat.properties['a string'] = "Sdfdsfsd"
17 mat.properties['a float'] = 0.0
18 mat.properties['an int'] = 0
19  
20 # to get a properties type, use type()
21 if type(mat.properties['a float array']) is Blender.Types.IDArrayType:
22     print "It's an array!"
23 if type(mat.properties['an int']) is int:
24     print "It's an int!"
25  
26 # iterate over a group
27 for property in mat.properties['a group']:
28     print property
29     print type(property)
30  
31 theint = mat.properties['an int']
32 thestring = mat.properties['a string']

正如您所看到的,属性可以通过简单的python类型创建,比如int、float、dict和List。从属性中获取数据就像访问它的.data成员一样简单。

C API

ID属性的C API是在头文件原文source/Blender/makesdna/DNA_ID.h中原型化的。与使用pythonAPI相比,使用C API有很大不同;它的级别很低。最终会建立一种类似于XML的ID验证系统。现在,还只是低级别的函数。

下面是IDProperty结构和ID结构(译者:以下代码摘自Blender2.8)

 1 typedef struct IDPropertyData {
 2     void *pointer;
 3     ListBase group;
 4     int val, val2;  /* note, we actually fit a double into these two ints */
 5 } IDPropertyData;
 6 
 7 typedef struct IDProperty {
 8     struct IDProperty *next, *prev;
 9     char type, subtype;
10     short flag;
11     char name[64];  /* MAX_IDPROP_NAME */
12 
13     /* saved is used to indicate if this struct has been saved yet.
14      * seemed like a good idea as a pad var was needed anyway :) */
15     int saved;
16     IDPropertyData data;  /* note, alignment for 64 bits */
17 
18     /* array length, also (this is important!) string length + 1.
19      * the idea is to be able to reuse array realloc functions on strings.*/
20     int len;
21 
22     /* Strings and arrays are both buffered, though the buffer isn't saved. */
23     /* totallen is total length of allocated array/string, including a buffer.
24      * Note that the buffering is mild; the code comes from python's list implementation. */
25     int totallen;
26 } IDProperty;
27 
28 typedef struct ID {
29     void *next, *prev;
30     struct ID *newid;
31     struct Library *lib;
32     char name[66]; /* MAX_ID_NAME */
33     /**
34      * LIB_... flags report on status of the datablock this ID belongs to (persistent, saved to and read from .blend).
35      */
36     short flag;
37     /**
38      * LIB_TAG_... tags (runtime only, cleared at read time).
39      */
40     int tag;
41     int us;
42     int icon_id;
43     int recalc;
44     int pad;
45     IDProperty *properties;
46 
47     IDOverrideStatic *override_static;  /* Reference linked ID which this one overrides. */
48     void *pad1;
49 
50     void *py_instance;
51 } ID;

由ID获取ID属性

由ID获取ID属性(具体说,是一个连接于ID的Group类型属性)用下面的函数:

 struct IDProperty *IDP_GetProperties(struct ID *id, int create_if_needed); 

 如果传入值为1的create_if_needed,将会自动创建并连接Group类型的IDProperty到ID,否则若ID中没有Group类型属性结构时将返回NULL。

创建一个ID属性

创建ID属性很容易;首先创建IDPropertyTemplate并设置适当的值。IDPropertyTemplate是一个联合体,这非常容易。若要设置float属性的数据,只需设置.f为浮点数;.i为整数;.str为字符串;数组的.array.len和.array.type(IDP_Float或IDP_int);对于新建group属性什么都不需要。

一旦你创建了模板联合体,就可以将它与ID属性类型及其名称一起提供给IDP_New函数。下面是一个例子:

 1 IDPropertyTemplate val;
 2 IDProperty *group, *idgroup, *color;
 3 group = IDP_New(IDP_GROUP, val, "group1"); //groups don't need a template.
 4  
 5 val.array.len = 4
 6 val.array.type = IDP_FLOAT;
 7 color = IDP_New(IDP_ARRAY, val, "color1");
 8  
 9 idgroup = IDP_GetProperties(some_id, 1);
10 IDP_AddToGroup(group, color);
11 IDP_AddToGroup(idgroup, group);

在组中查找ID属性

查找ID属性使用下面的函数:

 IDProperty *IDP_GetPropertyFromGroup(struct IDProperty *prop, char *name); 

下面这部分内容在Blender2.8版中已不存在了

迭代组中的ID属性

若要迭代组属性中的id属性,请分配一个void*指针,并使用此函数将其设置为迭代器:

 void *IDP_GetGroupIterator(struct IDProperty *prop); 

然后你可用下面函数迭代:

 void *IDP_GroupIterNext(void *vself); 

注意迭代器在迭代结束时自动释放,但如果停止迭代初期就可以释放它:

 void IDP_FreeIterBeforeEnd(void *vself); 

使用它的一个例子:

1 IDProperty *prop;
2 void *iter = IDP_GetGroupIterator(some_group);
3 for (prop=GroupIterNext(iter);prop;prop=GroupIterNext(iter)) {
4    . . .
5 }

原文(Blender官方文档):https://wiki.blender.org/index.php/Dev:Source/Data_System/ID_Property,由于原文是基于Blender2.5的,译者结合2.8版代码作了修改。

posted @ 2017-12-30 18:00  平凡人  阅读(...)  评论(...编辑  收藏