Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2010-12-13 12:10:16 +0300
committerCampbell Barton <ideasman42@gmail.com>2010-12-13 12:10:16 +0300
commita4b410af3d67c44a35c9cbf6f09c33a3c41a50af (patch)
tree8eccf50b13bdfb6cd63bd953965d4555a6154caf /source/blender/python
parent25bf9e38f3fbeb1e36f29b1296f0bbc2dd61f9d2 (diff)
Expose access to PROP_ENUM_FLAG from bpy.props.EnumProperty(), this is exposed as a python set(). The default value is also a python set() so multiple booleans can be used in the 1 property.
Also added PROP_ENUM_FLAG support to operator printouts.
Diffstat (limited to 'source/blender/python')
-rw-r--r--source/blender/python/intern/bpy_props.c123
1 files changed, 93 insertions, 30 deletions
diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c
index b7192f7395b..1148b9e5e2b 100644
--- a/source/blender/python/intern/bpy_props.c
+++ b/source/blender/python/intern/bpy_props.c
@@ -40,6 +40,12 @@ EnumPropertyItem property_flag_items[] = {
{PROP_ANIMATABLE, "ANIMATABLE", 0, "Animateable", ""},
{0, NULL, 0, NULL, NULL}};
+EnumPropertyItem property_flag_enum_items[] = {
+ {PROP_HIDDEN, "HIDDEN", 0, "Hidden", ""},
+ {PROP_ANIMATABLE, "ANIMATABLE", 0, "Animateable", ""},
+ {PROP_ENUM_FLAG, "ENUM_FLAG", 0, "Enum Flag", ""},
+ {0, NULL, 0, NULL, NULL}};
+
/* subtypes */
EnumPropertyItem property_subtype_string_items[] = {
{PROP_FILEPATH, "FILE_PATH", 0, "File Path", ""},
@@ -134,7 +140,7 @@ static PyObject *bpy_prop_deferred_return(PyObject *func, PyObject *kw)
/* terse macros for error checks shared between all funcs cant use function
* calls because of static strins passed to pyrna_set_to_enum_bitfield */
-#define BPY_PROPDEF_CHECK(_func) \
+#define BPY_PROPDEF_CHECK(_func, _property_flag_items) \
if(id_len >= MAX_IDPROP_NAME) { \
PyErr_Format(PyExc_TypeError, #_func"(): '%.200s' too long, max length is %d", id, MAX_IDPROP_NAME-1); \
return NULL; \
@@ -143,11 +149,11 @@ static PyObject *bpy_prop_deferred_return(PyObject *func, PyObject *kw)
PyErr_Format(PyExc_TypeError, #_func"(): '%s' is defined as a non-dynamic type", id); \
return NULL; \
} \
- if(pyopts && pyrna_set_to_enum_bitfield(property_flag_items, pyopts, &opts, #_func"(options={...}):")) \
+ if(pyopts && pyrna_set_to_enum_bitfield(_property_flag_items, pyopts, &opts, #_func"(options={...}):")) \
return NULL; \
-#define BPY_PROPDEF_SUBTYPE_CHECK(_func, _subtype) \
- BPY_PROPDEF_CHECK(_func) \
+#define BPY_PROPDEF_SUBTYPE_CHECK(_func, _property_flag_items, _subtype) \
+ BPY_PROPDEF_CHECK(_func, _property_flag_items) \
if(pysubtype && RNA_enum_value_from_id(_subtype, pysubtype, &subtype)==0) { \
PyErr_Format(PyExc_TypeError, #_func"(subtype='%s'): invalid subtype", pysubtype); \
return NULL; \
@@ -196,7 +202,7 @@ static PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw)
if (!PyArg_ParseTupleAndKeywords(args, kw, "s#|ssiO!s:BoolProperty", (char **)kwlist, &id, &id_len, &name, &description, &def, &PySet_Type, &pyopts, &pysubtype))
return NULL;
- BPY_PROPDEF_SUBTYPE_CHECK(BoolProperty, property_subtype_number_items)
+ BPY_PROPDEF_SUBTYPE_CHECK(BoolProperty, property_flag_items, property_subtype_number_items)
prop= RNA_def_property(srna, id, PROP_BOOLEAN, subtype);
RNA_def_property_boolean_default(prop, def);
@@ -243,7 +249,7 @@ static PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject
if (!PyArg_ParseTupleAndKeywords(args, kw, "s#|ssOO!si:BoolVectorProperty", (char **)kwlist, &id, &id_len, &name, &description, &pydef, &PySet_Type, &pyopts, &pysubtype, &size))
return NULL;
- BPY_PROPDEF_SUBTYPE_CHECK(BoolVectorProperty, property_subtype_array_items)
+ BPY_PROPDEF_SUBTYPE_CHECK(BoolVectorProperty, property_flag_items, property_subtype_array_items)
if(size < 1 || size > PYRNA_STACK_ARRAY) {
PyErr_Format(PyExc_TypeError, "BoolVectorProperty(size=%d): size must be between 0 and " STRINGIFY(PYRNA_STACK_ARRAY), size);
@@ -298,7 +304,7 @@ static PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw)
if (!PyArg_ParseTupleAndKeywords(args, kw, "s#|ssiiiiiiO!s:IntProperty", (char **)kwlist, &id, &id_len, &name, &description, &def, &min, &max, &soft_min, &soft_max, &step, &PySet_Type, &pyopts, &pysubtype))
return NULL;
- BPY_PROPDEF_SUBTYPE_CHECK(IntProperty, property_subtype_number_items)
+ BPY_PROPDEF_SUBTYPE_CHECK(IntProperty, property_flag_items, property_subtype_number_items)
prop= RNA_def_property(srna, id, PROP_INT, subtype);
RNA_def_property_int_default(prop, def);
@@ -346,7 +352,7 @@ static PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject
if (!PyArg_ParseTupleAndKeywords(args, kw, "s#|ssOiiiiiO!si:IntVectorProperty", (char **)kwlist, &id, &id_len, &name, &description, &pydef, &min, &max, &soft_min, &soft_max, &step, &PySet_Type, &pyopts, &pysubtype, &size))
return NULL;
- BPY_PROPDEF_SUBTYPE_CHECK(IntVectorProperty, property_subtype_array_items)
+ BPY_PROPDEF_SUBTYPE_CHECK(IntVectorProperty, property_flag_items, property_subtype_array_items)
if(size < 1 || size > PYRNA_STACK_ARRAY) {
PyErr_Format(PyExc_TypeError, "IntVectorProperty(size=%d): size must be between 0 and " STRINGIFY(PYRNA_STACK_ARRAY), size);
@@ -407,7 +413,7 @@ static PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw)
if (!PyArg_ParseTupleAndKeywords(args, kw, "s#|ssffffffiO!ss:FloatProperty", (char **)kwlist, &id, &id_len, &name, &description, &def, &min, &max, &soft_min, &soft_max, &step, &precision, &PySet_Type, &pyopts, &pysubtype, &pyunit))
return NULL;
- BPY_PROPDEF_SUBTYPE_CHECK(FloatProperty, property_subtype_number_items)
+ BPY_PROPDEF_SUBTYPE_CHECK(FloatProperty, property_flag_items, property_subtype_number_items)
if(pyunit && RNA_enum_value_from_id(property_unit_items, pyunit, &unit)==0) {
PyErr_Format(PyExc_TypeError, "FloatProperty(unit='%s'): invalid unit");
@@ -460,7 +466,7 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec
if (!PyArg_ParseTupleAndKeywords(args, kw, "s#|ssOfffffiO!si:FloatVectorProperty", (char **)kwlist, &id, &id_len, &name, &description, &pydef, &min, &max, &soft_min, &soft_max, &step, &precision, &PySet_Type, &pyopts, &pysubtype, &size))
return NULL;
- BPY_PROPDEF_SUBTYPE_CHECK(FloatVectorProperty, property_subtype_array_items)
+ BPY_PROPDEF_SUBTYPE_CHECK(FloatVectorProperty, property_flag_items, property_subtype_array_items)
if(size < 1 || size > PYRNA_STACK_ARRAY) {
PyErr_Format(PyExc_TypeError, "FloatVectorProperty(size=%d): size must be between 0 and " STRINGIFY(PYRNA_STACK_ARRAY), size);
@@ -515,7 +521,7 @@ static PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw
if (!PyArg_ParseTupleAndKeywords(args, kw, "s#|sssiO!s:StringProperty", (char **)kwlist, &id, &id_len, &name, &description, &def, &maxlen, &PySet_Type, &pyopts, &pysubtype))
return NULL;
- BPY_PROPDEF_SUBTYPE_CHECK(StringProperty, property_subtype_string_items)
+ BPY_PROPDEF_SUBTYPE_CHECK(StringProperty, property_flag_items, property_subtype_string_items)
prop= RNA_def_property(srna, id, PROP_STRING, subtype);
if(maxlen != 0) RNA_def_property_string_maxlength(prop, maxlen + 1); /* +1 since it includes null terminator */
@@ -531,49 +537,102 @@ static PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw
Py_RETURN_NONE;
}
-static EnumPropertyItem *enum_items_from_py(PyObject *value, const char *def, int *defvalue)
+static EnumPropertyItem *enum_items_from_py(PyObject *value, PyObject *def, int *defvalue, const short is_enum_flag)
{
EnumPropertyItem *items= NULL;
PyObject *item;
int seq_len, i, totitem= 0;
+ short def_used= 0;
+ const char *def_cmp= NULL;
if(!PySequence_Check(value)) {
- PyErr_SetString(PyExc_TypeError, "expected a sequence of tuples for the enum items");
+ PyErr_SetString(PyExc_TypeError, "EnumProperty(...): expected a sequence of tuples for the enum items");
return NULL;
}
- seq_len = PySequence_Length(value);
+ seq_len= PySequence_Length(value);
+
+ if(is_enum_flag) {
+ if(seq_len > RNA_ENUM_BITFLAG_SIZE) {
+ PyErr_SetString(PyExc_TypeError, "EnumProperty(...): maximum " STRINGIFY(RNA_ENUM_BITFLAG_SIZE) " members for a ENUM_FLAG type property");
+ return NULL;
+ }
+ if(def && !PySet_Check(def)) {
+ PyErr_Format(PyExc_TypeError, "EnumProperty(...): default option must be a 'set' type when ENUM_FLAG is enabled, not a '%.200s'", Py_TYPE(def)->tp_name);
+ return NULL;
+ }
+ }
+ else {
+ if(def) {
+ def_cmp= _PyUnicode_AsString(def);
+ if(def_cmp==NULL) {
+ PyErr_Format(PyExc_TypeError, "EnumProperty(...): default option must be a 'str' type when ENUM_FLAG is disabled, not a '%.200s'", Py_TYPE(def)->tp_name);
+ return NULL;
+ }
+ }
+ }
+
+ /* blank value */
+ *defvalue= 0;
+
for(i=0; i<seq_len; i++) {
EnumPropertyItem tmp= {0, "", 0, "", ""};
item= PySequence_GetItem(value, i);
if(item==NULL || PyTuple_Check(item)==0) {
- PyErr_SetString(PyExc_TypeError, "expected a sequence of tuples for the enum items");
+ PyErr_SetString(PyExc_TypeError, "EnumProperty(...): expected a sequence of tuples for the enum items");
if(items) MEM_freeN(items);
Py_XDECREF(item);
return NULL;
}
if(!PyArg_ParseTuple(item, "sss", &tmp.identifier, &tmp.name, &tmp.description)) {
- PyErr_SetString(PyExc_TypeError, "expected an identifier, name and description in the tuple");
+ PyErr_SetString(PyExc_TypeError, "EnumProperty(...): expected an identifier, name and description in the tuple");
Py_DECREF(item);
return NULL;
}
- tmp.value= i;
- RNA_enum_item_add(&items, &totitem, &tmp);
+ if(is_enum_flag) {
+ tmp.value= 1<<i;
+
+ if(def && PySet_Contains(def, PyTuple_GET_ITEM(item, 0))) {
+ *defvalue |= tmp.value;
+ def_used++;
+ }
+ }
+ else {
+ tmp.value= i;
- if(def[0] && strcmp(def, tmp.identifier) == 0)
- *defvalue= tmp.value;
+ if(def && def_used == 0 && strcmp(def_cmp, tmp.identifier)==0) {
+ *defvalue= tmp.value;
+ def_used++; /* only ever 1 */
+ }
+ }
+
+ RNA_enum_item_add(&items, &totitem, &tmp);
Py_DECREF(item);
}
- if(!def[0])
- *defvalue= 0;
-
RNA_enum_item_end(&items, &totitem);
+ if(is_enum_flag) {
+ /* strict check that all set members were used */
+ if(def && def_used != PySet_GET_SIZE(def)) {
+ MEM_freeN(items);
+
+ PyErr_Format(PyExc_TypeError, "EnumProperty(..., default={...}): set has %d unused member(s)", PySet_GET_SIZE(def) - def_used);
+ return NULL;
+ }
+ }
+ else {
+ if(def && def_used == 0) {
+ MEM_freeN(items);
+
+ PyErr_Format(PyExc_TypeError, "EnumProperty(..., default=\'%s\'): not found in enum members", def);
+ return NULL;
+ }
+ }
return items;
}
@@ -582,7 +641,9 @@ static char BPy_EnumProperty_doc[] =
"\n"
" Returns a new enumerator property definition.\n"
"\n"
-" :arg options: Enumerator in ['HIDDEN', 'ANIMATABLE'].\n"
+" :arg default: The default value for this enum, A string when *ENUM_FLAG* is disabled otherwise a set which may only contain string identifiers used in *items*.\n"
+" :type default: string or set\n"
+" :arg options: Enumerator in ['HIDDEN', 'ANIMATABLE', 'ENUM_FLAG'].\n"
" :type options: set\n"
" :arg items: The items that make up this enumerator.\n"
" :type items: sequence of string triplets";
@@ -594,7 +655,8 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw)
if(srna) {
static const char *kwlist[] = {"attr", "items", "name", "description", "default", "options", NULL};
- const char *id=NULL, *name="", *description="", *def="";
+ const char *id=NULL, *name="", *description="";
+ PyObject *def= NULL;
int id_len;
int defvalue=0;
PyObject *items= Py_None;
@@ -603,12 +665,12 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw)
PyObject *pyopts= NULL;
int opts=0;
- if (!PyArg_ParseTupleAndKeywords(args, kw, "s#O|sssO!:EnumProperty", (char **)kwlist, &id, &id_len, &items, &name, &description, &def, &PySet_Type, &pyopts))
+ if (!PyArg_ParseTupleAndKeywords(args, kw, "s#O|ssOO!:EnumProperty", (char **)kwlist, &id, &id_len, &items, &name, &description, &def, &PySet_Type, &pyopts))
return NULL;
- BPY_PROPDEF_CHECK(EnumProperty)
+ BPY_PROPDEF_CHECK(EnumProperty, property_flag_enum_items)
- eitems= enum_items_from_py(items, def, &defvalue);
+ eitems= enum_items_from_py(items, def, &defvalue, (opts & PROP_ENUM_FLAG)!=0);
if(!eitems)
return NULL;
@@ -616,6 +678,7 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw)
if(pyopts) {
if(opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN);
if((opts & PROP_ANIMATABLE)==0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ if(opts & PROP_ENUM_FLAG) RNA_def_property_flag(prop, PROP_ENUM_FLAG);
}
RNA_def_property_duplicate_pointers(srna, prop);
MEM_freeN(eitems);
@@ -673,7 +736,7 @@ static PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *k
if (!PyArg_ParseTupleAndKeywords(args, kw, "s#O|ssO!:PointerProperty", (char **)kwlist, &id, &id_len, &type, &name, &description, &PySet_Type, &pyopts))
return NULL;
- BPY_PROPDEF_CHECK(PointerProperty)
+ BPY_PROPDEF_CHECK(PointerProperty, property_flag_items)
ptype= pointer_type_from_py(type, "PointerProperty(...):");
if(!ptype)
@@ -717,7 +780,7 @@ static PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject
if (!PyArg_ParseTupleAndKeywords(args, kw, "s#O|ssO!:CollectionProperty", (char **)kwlist, &id, &id_len, &type, &name, &description, &PySet_Type, &pyopts))
return NULL;
- BPY_PROPDEF_CHECK(CollectionProperty)
+ BPY_PROPDEF_CHECK(CollectionProperty, property_flag_items)
ptype= pointer_type_from_py(type, "CollectionProperty(...):");
if(!ptype)