diff options
-rw-r--r-- | release/scripts/op/object_randomize_transform.py | 134 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_interface.c | 1 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_operator_wrap.c | 1 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_props.c | 463 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_props.h | 44 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 370 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.h | 10 |
7 files changed, 646 insertions, 377 deletions
diff --git a/release/scripts/op/object_randomize_transform.py b/release/scripts/op/object_randomize_transform.py new file mode 100644 index 00000000000..bbec7546514 --- /dev/null +++ b/release/scripts/op/object_randomize_transform.py @@ -0,0 +1,134 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +import bpy + +def randomize_selected(seed, loc, rot, scale, scale_even, scale_min): + + import random + from random import uniform + from Mathutils import Vector + + random.seed(seed) + + def rand_vec(vec_range): + return Vector([uniform(-val, val) for val in vec_range]) + + + for obj in bpy.context.selected_objects: + + if loc: + obj.location += rand_vec(loc) + + if rot: # TODO, non euler's + vec = rand_vec(rot) + obj.rotation_euler[0] += vec[0] + obj.rotation_euler[1] += vec[1] + obj.rotation_euler[2] += vec[2] + + if scale: + org_sca_x, org_sca_y, org_sca_z = obj.scale + + if scale_even: + sca_x = sca_y = sca_z = uniform(scale[0], -scale[0]) + else: + sca_x, sca_y, sca_z = rand_vec(scale) + + aX = sca_x + org_sca_x + bX = org_sca_x * scale_min / 100.0 + + aY = sca_y + org_sca_y + bY = org_sca_y * scale_min / 100.0 + + aZ = sca_z + org_sca_z + bZ = org_sca_z * scale_min / 100.0 + + if aX < bX: aX = bX + if aY < bY: aY = bY + if aZ < bZ: aZ = bZ + + obj.scale = aX, aY, aZ + +from bpy.props import * + + +class RandomizeLocRotSize(bpy.types.Operator): + '''Randomize objects loc/rot/scale.''' + bl_idname = "object.randomize_locrotsize" + bl_label = "Randomize Loc Rot Size" + bl_register = True + bl_undo = True + + random_seed = IntProperty(name="Random Seed", + description="Seed value for the random generator", + default=0, min=0, max=1000) + + use_loc = BoolProperty(name="Randomize Location", + description="Randomize the scale values", default=True) + + loc = FloatVectorProperty(name="Location", + description="Maximun distance the objects can spread over each axis", + default=(0.0, 0.0, 0.0), min=-100.0, max=100.0) + + use_rot = BoolProperty(name="Randomize Rotation", + description="Randomize the rotation values", default=True) + + rot = FloatVectorProperty(name="Rotation", + description="Maximun rotation over each axis", + default=(0.0, 0.0, 0.0), min=-180.0, max=180.0) + + use_scale = BoolProperty(name="Randomize Scale", + description="Randomize the scale values", default=True) + + scale_even = BoolProperty(name="Scale Even", + description="Use the same scale value for all axis", default=False) + + scale_min = FloatProperty(name="Minimun Scale Factor", + description="Lowest scale percentage possible", + default=15.0, min=-100.0, max=100.0) + + scale = FloatVectorProperty(name="Scale", + description="Maximum scale randomization over each axis", + default=(0.0, 0.0, 0.0), min=-100.0, max=100.0) + + def execute(self, context): + from math import radians + seed = self.properties.random_seed + + loc = self.properties.loc if self.properties.use_loc else None + rot = self.properties.rot if self.properties.use_rot else None + scale = [radians(val) for val in self.properties.scale] if self.properties.use_scale else None + + scale_even = self.properties.scale_even + scale_min= self.properties.scale_min + + randomize_selected(seed, loc, rot, scale, scale_even, scale_min) + + return {'FINISHED'} + + +# Register the operator +bpy.types.register(RandomizeLocRotSize) + +# Add to the menu +def menu_func(self, context): + if context.mode == 'OBJECT': + self.layout.operator(RandomizeLocRotSize.bl_idname, + text="Randomize Loc Rot Size") + +bpy.types.VIEW3D_MT_transform.append(menu_func) diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 611521073ef..1591f491944 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -39,6 +39,7 @@ #include "eval.h" /* for PyEval_EvalCode */ #include "bpy_rna.h" +#include "bpy_props.h" #include "bpy_operator.h" #include "bpy_ui.h" #include "bpy_util.h" diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c index ebe063b7c6f..08ccadf141d 100644 --- a/source/blender/python/intern/bpy_operator_wrap.c +++ b/source/blender/python/intern/bpy_operator_wrap.c @@ -31,6 +31,7 @@ #include "RNA_define.h" #include "bpy_rna.h" +#include "bpy_props.h" #include "bpy_util.h" static void operator_properties_init(wmOperatorType *ot) diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c new file mode 100644 index 00000000000..9c3e4ea18eb --- /dev/null +++ b/source/blender/python/intern/bpy_props.c @@ -0,0 +1,463 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "bpy_props.h" +#include "bpy_rna.h" + +#include "RNA_access.h" +#include "RNA_define.h" /* for defining our own rna */ + +#include "MEM_guardedalloc.h" + +#include "float.h" /* FLT_MIN/MAX */ + +/* operators use this so it can store the args given but defer running + * it until the operator runs where these values are used to setup the + * default args for that operator instance */ +static PyObject *bpy_prop_deferred_return(void *func, PyObject *kw) +{ + PyObject *ret = PyTuple_New(2); + PyTuple_SET_ITEM(ret, 0, PyCObject_FromVoidPtr(func, NULL)); + PyTuple_SET_ITEM(ret, 1, kw); + Py_INCREF(kw); + return ret; +} + +/* Function that sets RNA, NOTE - self is NULL when called from python, but being abused from C so we can pass the srna allong + * This isnt incorrect since its a python object - but be careful */ + +PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw) +{ + StructRNA *srna; + + if (PyTuple_Size(args) > 0) { + PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this. + return NULL; + } + + srna= srna_from_self(self); + if(srna==NULL && PyErr_Occurred()) { + return NULL; /* self's type was compatible but error getting the srna */ + } + else if(srna) { + static char *kwlist[] = {"attr", "name", "description", "default", "hidden", NULL}; + char *id=NULL, *name="", *description=""; + int def=0, hidden=0; + PropertyRNA *prop; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssii:BoolProperty", kwlist, &id, &name, &description, &def, &hidden)) + return NULL; + + prop= RNA_def_boolean(srna, id, def, name, description); + if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN); + RNA_def_property_duplicate_pointers(prop); + Py_RETURN_NONE; + } + else { /* operators defer running this function */ + return bpy_prop_deferred_return((void *)BPy_BoolProperty, kw); + } +} + +PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw) +{ + StructRNA *srna; + + if (PyTuple_Size(args) > 0) { + PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this. + return NULL; + } + + srna= srna_from_self(self); + if(srna==NULL && PyErr_Occurred()) { + return NULL; /* self's type was compatible but error getting the srna */ + } + else if(srna) { + static char *kwlist[] = {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "hidden", NULL}; + char *id=NULL, *name="", *description=""; + int min=INT_MIN, max=INT_MAX, soft_min=INT_MIN, soft_max=INT_MAX, step=1, def=0; + int hidden=0; + PropertyRNA *prop; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssiiiiiii:IntProperty", kwlist, &id, &name, &description, &def, &min, &max, &soft_min, &soft_max, &step, &hidden)) + return NULL; + + prop= RNA_def_int(srna, id, def, min, max, name, description, soft_min, soft_max); + RNA_def_property_ui_range(prop, min, max, step, 0); + if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN); + RNA_def_property_duplicate_pointers(prop); + Py_RETURN_NONE; + } + else { /* operators defer running this function */ + return bpy_prop_deferred_return((void *)BPy_IntProperty, kw); + } +} + +PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw) +{ + StructRNA *srna; + + if (PyTuple_Size(args) > 0) { + PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this. + return NULL; + } + + srna= srna_from_self(self); + if(srna==NULL && PyErr_Occurred()) { + return NULL; /* self's type was compatible but error getting the srna */ + } + else if(srna) { + static char *kwlist[] = {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "precision", "hidden", NULL}; + char *id=NULL, *name="", *description=""; + float min=-FLT_MAX, max=FLT_MAX, soft_min=-FLT_MAX, soft_max=FLT_MAX, step=3, def=0.0f; + int precision= 1, hidden=0; + PropertyRNA *prop; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssffffffii:FloatProperty", kwlist, &id, &name, &description, &def, &min, &max, &soft_min, &soft_max, &step, &precision, &hidden)) + return NULL; + + prop= RNA_def_float(srna, id, def, min, max, name, description, soft_min, soft_max); + RNA_def_property_ui_range(prop, min, max, step, precision); + if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN); + RNA_def_property_duplicate_pointers(prop); + Py_RETURN_NONE; + } + else { /* operators defer running this function */ + return bpy_prop_deferred_return((void *)BPy_FloatProperty, kw); + } +} + +PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObject *kw) +{ + StructRNA *srna; + + if (PyTuple_Size(args) > 0) { + PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this. + return NULL; + } + + srna= srna_from_self(self); + if(srna==NULL && PyErr_Occurred()) { + return NULL; /* self's type was compatible but error getting the srna */ + } + else if(srna) { + static char *kwlist[] = {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "precision", "hidden", "size", NULL}; + char *id=NULL, *name="", *description=""; + float min=-FLT_MAX, max=FLT_MAX, soft_min=-FLT_MAX, soft_max=FLT_MAX, step=3, def[PYRNA_STACK_ARRAY]={0.0f}; + int precision= 1, hidden=0, size=3; + PropertyRNA *prop; + PyObject *pydef= NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssOfffffiii:FloatVectorProperty", kwlist, &id, &name, &description, &pydef, &min, &max, &soft_min, &soft_max, &step, &precision, &hidden, &size)) + return NULL; + + if(size < 0 || size > PYRNA_STACK_ARRAY) { + PyErr_Format(PyExc_TypeError, "FloatVectorProperty(): size must be between 0 and %d, given %d.", PYRNA_STACK_ARRAY, size); + return NULL; + } + + if(pydef) { + int i; + + if(!PySequence_Check(pydef)) { + PyErr_Format(PyExc_TypeError, "FloatVectorProperty(): default value is not a sequence of size: %d.", size); + return NULL; + } + + if(size != PySequence_Size(pydef)) { + PyErr_Format(PyExc_TypeError, "FloatVectorProperty(): size: %d, does not default: %d.", size, PySequence_Size(pydef)); + return NULL; + } + + for(i=0; i<size; i++) { + PyObject *item= PySequence_GetItem(pydef, i); + if(item) { + def[i]= PyFloat_AsDouble(item); + Py_DECREF(item); + } + } + + if(PyErr_Occurred()) { /* error set above */ + return NULL; + } + } + + prop= RNA_def_float_vector(srna, id, size, pydef ? def:NULL, min, max, name, description, soft_min, soft_max); + RNA_def_property_ui_range(prop, min, max, step, precision); + if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN); + RNA_def_property_duplicate_pointers(prop); + Py_RETURN_NONE; + } + else { /* operators defer running this function */ + return bpy_prop_deferred_return((void *)BPy_FloatVectorProperty, kw); + } +} + +PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw) +{ + StructRNA *srna; + + if (PyTuple_Size(args) > 0) { + PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this. + return NULL; + } + + srna= srna_from_self(self); + if(srna==NULL && PyErr_Occurred()) { + return NULL; /* self's type was compatible but error getting the srna */ + } + else if(srna) { + static char *kwlist[] = {"attr", "name", "description", "default", "maxlen", "hidden", NULL}; + char *id=NULL, *name="", *description="", *def=""; + int maxlen=0, hidden=0; + PropertyRNA *prop; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "s|sssii:StringProperty", kwlist, &id, &name, &description, &def, &maxlen, &hidden)) + return NULL; + + prop= RNA_def_string(srna, id, def, maxlen, name, description); + if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN); + RNA_def_property_duplicate_pointers(prop); + Py_RETURN_NONE; + } + else { /* operators defer running this function */ + return bpy_prop_deferred_return((void *)BPy_StringProperty, kw); + } +} + +static EnumPropertyItem *enum_items_from_py(PyObject *value, const char *def, int *defvalue) +{ + EnumPropertyItem *items= NULL; + PyObject *item; + int seq_len, i, totitem= 0; + + if(!PySequence_Check(value)) { + PyErr_SetString(PyExc_TypeError, "expected a sequence of tuples for the enum items"); + return NULL; + } + + seq_len = PySequence_Length(value); + 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"); + 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"); + Py_DECREF(item); + return NULL; + } + + tmp.value= i; + RNA_enum_item_add(&items, &totitem, &tmp); + + if(def[0] && strcmp(def, tmp.identifier) == 0) + *defvalue= tmp.value; + + Py_DECREF(item); + } + + if(!def[0]) + *defvalue= 0; + + RNA_enum_item_end(&items, &totitem); + + return items; +} + +PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw) +{ + StructRNA *srna; + + if (PyTuple_Size(args) > 0) { + PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this. + return NULL; + } + + srna= srna_from_self(self); + if(srna==NULL && PyErr_Occurred()) { + return NULL; /* self's type was compatible but error getting the srna */ + } + else if(srna) { + static char *kwlist[] = {"attr", "items", "name", "description", "default", "hidden", NULL}; + char *id=NULL, *name="", *description="", *def=""; + int defvalue=0, hidden=0; + PyObject *items= Py_None; + EnumPropertyItem *eitems; + PropertyRNA *prop; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|sssi:EnumProperty", kwlist, &id, &items, &name, &description, &def, &hidden)) + return NULL; + + eitems= enum_items_from_py(items, def, &defvalue); + if(!eitems) + return NULL; + + prop= RNA_def_enum(srna, id, eitems, defvalue, name, description); + if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN); + RNA_def_property_duplicate_pointers(prop); + MEM_freeN(eitems); + + Py_RETURN_NONE; + } + else { /* operators defer running this function */ + return bpy_prop_deferred_return((void *)BPy_EnumProperty, kw); + } +} + +static StructRNA *pointer_type_from_py(PyObject *value) +{ + StructRNA *srna; + + srna= srna_from_self(value); + if(!srna) { + PyErr_SetString(PyExc_SystemError, "expected an RNA type derived from IDPropertyGroup"); + return NULL; + } + + if(!RNA_struct_is_a(srna, &RNA_IDPropertyGroup)) { + PyErr_SetString(PyExc_SystemError, "expected an RNA type derived from IDPropertyGroup"); + return NULL; + } + + return srna; +} + +PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw) +{ + StructRNA *srna; + + if (PyTuple_Size(args) > 0) { + PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this. + return NULL; + } + + srna= srna_from_self(self); + if(srna==NULL && PyErr_Occurred()) { + return NULL; /* self's type was compatible but error getting the srna */ + } + else if(srna) { + static char *kwlist[] = {"attr", "type", "name", "description", "hidden", NULL}; + char *id=NULL, *name="", *description=""; + int hidden= 0; + PropertyRNA *prop; + StructRNA *ptype; + PyObject *type= Py_None; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|ssi:PointerProperty", kwlist, &id, &type, &name, &description, &hidden)) + return NULL; + + ptype= pointer_type_from_py(type); + if(!ptype) + return NULL; + + prop= RNA_def_pointer_runtime(srna, id, ptype, name, description); + if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN); + RNA_def_property_duplicate_pointers(prop); + Py_RETURN_NONE; + } + else { /* operators defer running this function */ + return bpy_prop_deferred_return((void *)BPy_PointerProperty, kw); + } + return NULL; +} + +PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw) +{ + StructRNA *srna; + + if (PyTuple_Size(args) > 0) { + PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this. + return NULL; + } + + srna= srna_from_self(self); + if(srna==NULL && PyErr_Occurred()) { + return NULL; /* self's type was compatible but error getting the srna */ + } + else if(srna) { + static char *kwlist[] = {"attr", "type", "name", "description", "hidden", NULL}; + char *id=NULL, *name="", *description=""; + int hidden= 0; + PropertyRNA *prop; + StructRNA *ptype; + PyObject *type= Py_None; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|ssi:CollectionProperty", kwlist, &id, &type, &name, &description, &hidden)) + return NULL; + + ptype= pointer_type_from_py(type); + if(!ptype) + return NULL; + + prop= RNA_def_collection_runtime(srna, id, ptype, name, description); + if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN); + RNA_def_property_duplicate_pointers(prop); + Py_RETURN_NONE; + } + else { /* operators defer running this function */ + return bpy_prop_deferred_return((void *)BPy_CollectionProperty, kw); + } + return NULL; +} + +static struct PyMethodDef props_methods[] = { + {"BoolProperty", (PyCFunction)BPy_BoolProperty, METH_VARARGS|METH_KEYWORDS, ""}, + {"IntProperty", (PyCFunction)BPy_IntProperty, METH_VARARGS|METH_KEYWORDS, ""}, + {"FloatProperty", (PyCFunction)BPy_FloatProperty, METH_VARARGS|METH_KEYWORDS, ""}, + {"FloatVectorProperty", (PyCFunction)BPy_FloatVectorProperty, METH_VARARGS|METH_KEYWORDS, ""}, + {"StringProperty", (PyCFunction)BPy_StringProperty, METH_VARARGS|METH_KEYWORDS, ""}, + {"EnumProperty", (PyCFunction)BPy_EnumProperty, METH_VARARGS|METH_KEYWORDS, ""}, + {"PointerProperty", (PyCFunction)BPy_PointerProperty, METH_VARARGS|METH_KEYWORDS, ""}, + {"CollectionProperty", (PyCFunction)BPy_CollectionProperty, METH_VARARGS|METH_KEYWORDS, ""}, + {NULL, NULL, 0, NULL} +}; + +static struct PyModuleDef props_module = { + PyModuleDef_HEAD_INIT, + "bpy.props", + "", + -1,/* multiple "initialization" just copies the module dict. */ + props_methods, + NULL, NULL, NULL, NULL +}; + +PyObject *BPY_rna_props( void ) +{ + PyObject *submodule; + submodule= PyModule_Create(&props_module); + PyDict_SetItemString(PySys_GetObject("modules"), props_module.m_name, submodule); + + /* INCREF since its its assumed that all these functions return the + * module with a new ref like PyDict_New, since they are passed to + * PyModule_AddObject which steals a ref */ + Py_INCREF(submodule); + + return submodule; +} diff --git a/source/blender/python/intern/bpy_props.h b/source/blender/python/intern/bpy_props.h new file mode 100644 index 00000000000..23ed142d7b8 --- /dev/null +++ b/source/blender/python/intern/bpy_props.h @@ -0,0 +1,44 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef BPY_PROPS_H +#define BPY_PROPS_H + +#include <Python.h> + +PyObject *BPY_rna_props( void ); + +/* functions for setting up new props - experemental */ +PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw); +PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw); +PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw); +PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObject *kw); +PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw); +PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw); +PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw); +PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw); + +#define PYRNA_STACK_ARRAY 32 + +#endif diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index bee6c4f70da..722968c9b31 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -24,6 +24,7 @@ */ #include "bpy_rna.h" +#include "bpy_props.h" #include "bpy_util.h" //#include "blendef.h" #include "BLI_dynstr.h" @@ -1034,7 +1035,6 @@ static PyObject *prop_subscript_collection_slice(PointerRNA *ptr, PropertyRNA *p * note: could also use pyrna_prop_to_py_index(self, count) in a loop but its a lot slower * since at the moment it reads (and even allocates) the entire array for each index. */ -#define PYRNA_STACK_ARRAY 32 static PyObject *prop_subscript_array_slice(PointerRNA *ptr, PropertyRNA *prop, int start, int stop, int length) { PyObject *list = PyList_New(stop - start); @@ -3140,6 +3140,7 @@ static struct PyMethodDef pyrna_struct_subtype_methods[] = { {"BoolProperty", (PyCFunction)BPy_BoolProperty, METH_VARARGS|METH_KEYWORDS, ""}, {"IntProperty", (PyCFunction)BPy_IntProperty, METH_VARARGS|METH_KEYWORDS, ""}, {"FloatProperty", (PyCFunction)BPy_FloatProperty, METH_VARARGS|METH_KEYWORDS, ""}, + {"FloatVectorProperty", (PyCFunction)BPy_FloatVectorProperty, METH_VARARGS|METH_KEYWORDS, ""}, {"StringProperty", (PyCFunction)BPy_StringProperty, METH_VARARGS|METH_KEYWORDS, ""}, {"EnumProperty", (PyCFunction)BPy_EnumProperty, METH_VARARGS|METH_KEYWORDS, ""}, {"PointerProperty", (PyCFunction)BPy_PointerProperty, METH_VARARGS|METH_KEYWORDS, ""}, @@ -3531,40 +3532,6 @@ PyObject *BPY_rna_types(void) return (PyObject *)self; } -static struct PyMethodDef props_methods[] = { - {"BoolProperty", (PyCFunction)BPy_BoolProperty, METH_VARARGS|METH_KEYWORDS, ""}, - {"IntProperty", (PyCFunction)BPy_IntProperty, METH_VARARGS|METH_KEYWORDS, ""}, - {"FloatProperty", (PyCFunction)BPy_FloatProperty, METH_VARARGS|METH_KEYWORDS, ""}, - {"StringProperty", (PyCFunction)BPy_StringProperty, METH_VARARGS|METH_KEYWORDS, ""}, - {"EnumProperty", (PyCFunction)BPy_EnumProperty, METH_VARARGS|METH_KEYWORDS, ""}, - {"PointerProperty", (PyCFunction)BPy_PointerProperty, METH_VARARGS|METH_KEYWORDS, ""}, - {"CollectionProperty", (PyCFunction)BPy_CollectionProperty, METH_VARARGS|METH_KEYWORDS, ""}, - {NULL, NULL, 0, NULL} -}; - -static struct PyModuleDef props_module = { - PyModuleDef_HEAD_INIT, - "bpy.props", - "", - -1,/* multiple "initialization" just copies the module dict. */ - props_methods, - NULL, NULL, NULL, NULL -}; - -PyObject *BPY_rna_props( void ) -{ - PyObject *submodule; - submodule= PyModule_Create(&props_module); - PyDict_SetItemString(PySys_GetObject("modules"), props_module.m_name, submodule); - - /* INCREF since its its assumed that all these functions return the - * module with a new ref like PyDict_New, since they are passed to - * PyModule_AddObject which steals a ref */ - Py_INCREF(submodule); - - return submodule; -} - StructRNA *pyrna_struct_as_srna(PyObject *self) { BPy_StructRNA *py_srna = NULL; @@ -3602,7 +3569,6 @@ StructRNA *pyrna_struct_as_srna(PyObject *self) return srna; } - /* Orphan functions, not sure where they should go */ /* get the srna for methods attached to types */ /* */ @@ -3611,7 +3577,7 @@ StructRNA *srna_from_self(PyObject *self) /* a bit sloppy but would cause a very confusing bug if * an error happened to be set here */ PyErr_Clear(); - + if(self==NULL) { return NULL; } @@ -3627,336 +3593,6 @@ StructRNA *srna_from_self(PyObject *self) return pyrna_struct_as_srna(self); } -/* operators use this so it can store the args given but defer running - * it until the operator runs where these values are used to setup the - * default args for that operator instance */ -static PyObject *bpy_prop_deferred_return(void *func, PyObject *kw) -{ - PyObject *ret = PyTuple_New(2); - PyTuple_SET_ITEM(ret, 0, PyCObject_FromVoidPtr(func, NULL)); - PyTuple_SET_ITEM(ret, 1, kw); - Py_INCREF(kw); - return ret; -} - -/* Function that sets RNA, NOTE - self is NULL when called from python, but being abused from C so we can pass the srna allong - * This isnt incorrect since its a python object - but be careful */ - -PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw) -{ - StructRNA *srna; - - if (PyTuple_Size(args) > 0) { - PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this. - return NULL; - } - - srna= srna_from_self(self); - if(srna==NULL && PyErr_Occurred()) { - return NULL; /* self's type was compatible but error getting the srna */ - } - else if(srna) { - static char *kwlist[] = {"attr", "name", "description", "default", "hidden", NULL}; - char *id=NULL, *name="", *description=""; - int def=0, hidden=0; - PropertyRNA *prop; - - if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssii:BoolProperty", kwlist, &id, &name, &description, &def, &hidden)) - return NULL; - - prop= RNA_def_boolean(srna, id, def, name, description); - if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN); - RNA_def_property_duplicate_pointers(prop); - Py_RETURN_NONE; - } - else { /* operators defer running this function */ - return bpy_prop_deferred_return((void *)BPy_BoolProperty, kw); - } -} - -PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw) -{ - StructRNA *srna; - - if (PyTuple_Size(args) > 0) { - PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this. - return NULL; - } - - srna= srna_from_self(self); - if(srna==NULL && PyErr_Occurred()) { - return NULL; /* self's type was compatible but error getting the srna */ - } - else if(srna) { - static char *kwlist[] = {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "hidden", NULL}; - char *id=NULL, *name="", *description=""; - int min=INT_MIN, max=INT_MAX, soft_min=INT_MIN, soft_max=INT_MAX, step=1, def=0; - int hidden=0; - PropertyRNA *prop; - - if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssiiiiiii:IntProperty", kwlist, &id, &name, &description, &def, &min, &max, &soft_min, &soft_max, &step, &hidden)) - return NULL; - - prop= RNA_def_int(srna, id, def, min, max, name, description, soft_min, soft_max); - RNA_def_property_ui_range(prop, min, max, step, 0); - if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN); - RNA_def_property_duplicate_pointers(prop); - Py_RETURN_NONE; - } - else { /* operators defer running this function */ - return bpy_prop_deferred_return((void *)BPy_IntProperty, kw); - } -} - -PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw) -{ - StructRNA *srna; - - if (PyTuple_Size(args) > 0) { - PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this. - return NULL; - } - - srna= srna_from_self(self); - if(srna==NULL && PyErr_Occurred()) { - return NULL; /* self's type was compatible but error getting the srna */ - } - else if(srna) { - static char *kwlist[] = {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "precision", "hidden", NULL}; - char *id=NULL, *name="", *description=""; - float min=-FLT_MAX, max=FLT_MAX, soft_min=-FLT_MAX, soft_max=FLT_MAX, step=3, def=0.0f; - int precision= 1, hidden=0; - PropertyRNA *prop; - - if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssffffffii:FloatProperty", kwlist, &id, &name, &description, &def, &min, &max, &soft_min, &soft_max, &step, &precision, &hidden)) - return NULL; - - prop= RNA_def_float(srna, id, def, min, max, name, description, soft_min, soft_max); - RNA_def_property_ui_range(prop, min, max, step, precision); - if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN); - RNA_def_property_duplicate_pointers(prop); - Py_RETURN_NONE; - } - else { /* operators defer running this function */ - return bpy_prop_deferred_return((void *)BPy_FloatProperty, kw); - } -} - -PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw) -{ - StructRNA *srna; - - if (PyTuple_Size(args) > 0) { - PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this. - return NULL; - } - - srna= srna_from_self(self); - if(srna==NULL && PyErr_Occurred()) { - return NULL; /* self's type was compatible but error getting the srna */ - } - else if(srna) { - static char *kwlist[] = {"attr", "name", "description", "default", "maxlen", "hidden", NULL}; - char *id=NULL, *name="", *description="", *def=""; - int maxlen=0, hidden=0; - PropertyRNA *prop; - - if (!PyArg_ParseTupleAndKeywords(args, kw, "s|sssii:StringProperty", kwlist, &id, &name, &description, &def, &maxlen, &hidden)) - return NULL; - - prop= RNA_def_string(srna, id, def, maxlen, name, description); - if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN); - RNA_def_property_duplicate_pointers(prop); - Py_RETURN_NONE; - } - else { /* operators defer running this function */ - return bpy_prop_deferred_return((void *)BPy_StringProperty, kw); - } -} - -static EnumPropertyItem *enum_items_from_py(PyObject *value, const char *def, int *defvalue) -{ - EnumPropertyItem *items= NULL; - PyObject *item; - int seq_len, i, totitem= 0; - - if(!PySequence_Check(value)) { - PyErr_SetString(PyExc_TypeError, "expected a sequence of tuples for the enum items"); - return NULL; - } - - seq_len = PySequence_Length(value); - 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"); - 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"); - Py_DECREF(item); - return NULL; - } - - tmp.value= i; - RNA_enum_item_add(&items, &totitem, &tmp); - - if(def[0] && strcmp(def, tmp.identifier) == 0) - *defvalue= tmp.value; - - Py_DECREF(item); - } - - if(!def[0]) - *defvalue= 0; - - RNA_enum_item_end(&items, &totitem); - - return items; -} - -PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw) -{ - StructRNA *srna; - - if (PyTuple_Size(args) > 0) { - PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this. - return NULL; - } - - srna= srna_from_self(self); - if(srna==NULL && PyErr_Occurred()) { - return NULL; /* self's type was compatible but error getting the srna */ - } - else if(srna) { - static char *kwlist[] = {"attr", "items", "name", "description", "default", "hidden", NULL}; - char *id=NULL, *name="", *description="", *def=""; - int defvalue=0, hidden=0; - PyObject *items= Py_None; - EnumPropertyItem *eitems; - PropertyRNA *prop; - - if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|sssi:EnumProperty", kwlist, &id, &items, &name, &description, &def, &hidden)) - return NULL; - - eitems= enum_items_from_py(items, def, &defvalue); - if(!eitems) - return NULL; - - prop= RNA_def_enum(srna, id, eitems, defvalue, name, description); - if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN); - RNA_def_property_duplicate_pointers(prop); - MEM_freeN(eitems); - - Py_RETURN_NONE; - } - else { /* operators defer running this function */ - return bpy_prop_deferred_return((void *)BPy_EnumProperty, kw); - } -} - -static StructRNA *pointer_type_from_py(PyObject *value) -{ - StructRNA *srna; - - srna= srna_from_self(value); - if(!srna) { - PyErr_SetString(PyExc_SystemError, "expected an RNA type derived from IDPropertyGroup"); - return NULL; - } - - if(!RNA_struct_is_a(srna, &RNA_IDPropertyGroup)) { - PyErr_SetString(PyExc_SystemError, "expected an RNA type derived from IDPropertyGroup"); - return NULL; - } - - return srna; -} - -PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw) -{ - StructRNA *srna; - - if (PyTuple_Size(args) > 0) { - PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this. - return NULL; - } - - srna= srna_from_self(self); - if(srna==NULL && PyErr_Occurred()) { - return NULL; /* self's type was compatible but error getting the srna */ - } - else if(srna) { - static char *kwlist[] = {"attr", "type", "name", "description", "hidden", NULL}; - char *id=NULL, *name="", *description=""; - int hidden= 0; - PropertyRNA *prop; - StructRNA *ptype; - PyObject *type= Py_None; - - if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|ssi:PointerProperty", kwlist, &id, &type, &name, &description, &hidden)) - return NULL; - - ptype= pointer_type_from_py(type); - if(!ptype) - return NULL; - - prop= RNA_def_pointer_runtime(srna, id, ptype, name, description); - if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN); - RNA_def_property_duplicate_pointers(prop); - Py_RETURN_NONE; - } - else { /* operators defer running this function */ - return bpy_prop_deferred_return((void *)BPy_PointerProperty, kw); - } - return NULL; -} - -PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw) -{ - StructRNA *srna; - - if (PyTuple_Size(args) > 0) { - PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this. - return NULL; - } - - srna= srna_from_self(self); - if(srna==NULL && PyErr_Occurred()) { - return NULL; /* self's type was compatible but error getting the srna */ - } - else if(srna) { - static char *kwlist[] = {"attr", "type", "name", "description", "hidden", NULL}; - char *id=NULL, *name="", *description=""; - int hidden= 0; - PropertyRNA *prop; - StructRNA *ptype; - PyObject *type= Py_None; - - if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|ssi:CollectionProperty", kwlist, &id, &type, &name, &description, &hidden)) - return NULL; - - ptype= pointer_type_from_py(type); - if(!ptype) - return NULL; - - prop= RNA_def_collection_runtime(srna, id, ptype, name, description); - if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN); - RNA_def_property_duplicate_pointers(prop); - Py_RETURN_NONE; - } - else { /* operators defer running this function */ - return bpy_prop_deferred_return((void *)BPy_CollectionProperty, kw); - } - return NULL; -} - - static int deferred_register_prop(StructRNA *srna, PyObject *item, PyObject *key, PyObject *dummy_args) { /* We only care about results from C which diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index 74a16b43dc1..01602c5a863 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -70,7 +70,6 @@ PyObject *BPY_rna_module( void ); void BPY_update_rna_module( void ); /*PyObject *BPY_rna_doc( void );*/ PyObject *BPY_rna_types( void ); -PyObject *BPY_rna_props( void ); PyObject *pyrna_struct_CreatePyObject( PointerRNA *ptr ); PyObject *pyrna_prop_CreatePyObject( PointerRNA *ptr, PropertyRNA *prop ); @@ -80,15 +79,6 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, int all_args, const char *error_prefix); PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop); -/* functions for setting up new props - experemental */ -PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw); -PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw); -PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw); -PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw); -PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw); -PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw); -PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw); - /* function for registering types */ PyObject *pyrna_basetype_register(PyObject *self, PyObject *args); PyObject *pyrna_basetype_unregister(PyObject *self, PyObject *args); |