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版代码作了修改。