diff options
author | Campbell Barton <ideasman42@gmail.com> | 2011-03-02 07:51:43 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2011-03-02 07:51:43 +0300 |
commit | e2304a4dbbf320d268581536cdc9c3e8f66cc7c3 (patch) | |
tree | f84c7b417e42580fbc69b7e8e4c36695844fb0f8 /source/blender/python/intern | |
parent | 21067886aaa9607f0ab345c8f52dbdb9c2818033 (diff) |
move anim functions out of bpy_rna.c, its getting too big.
Diffstat (limited to 'source/blender/python/intern')
-rw-r--r-- | source/blender/python/intern/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/python/intern/bpy.c | 2 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_interface.c | 2 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_operator.c | 3 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_operator_wrap.c | 1 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_props.c | 5 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 334 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.h | 40 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna_anim.c | 353 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna_anim.h | 37 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna_array.c | 4 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna_callback.c | 4 |
12 files changed, 452 insertions, 335 deletions
diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt index 123c8e5b3e0..bf91fd90744 100644 --- a/source/blender/python/intern/CMakeLists.txt +++ b/source/blender/python/intern/CMakeLists.txt @@ -46,6 +46,7 @@ set(SRC bpy_operator_wrap.c bpy_props.c bpy_rna.c + bpy_rna_anim.c bpy_rna_array.c bpy_rna_callback.c bpy_traceback.c @@ -59,6 +60,7 @@ set(SRC bpy_operator_wrap.h bpy_props.h bpy_rna.h + bpy_rna_anim.h bpy_rna_callback.h bpy_traceback.h bpy_util.h diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index 1f66e106374..589da5b3cb7 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -48,6 +48,8 @@ #include "BKE_global.h" /* XXX, G.main only */ +#include "RNA_access.h" + #include "MEM_guardedalloc.h" /* external util modules */ diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index ade7ff62519..03d5f528670 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -37,6 +37,8 @@ #include "MEM_guardedalloc.h" +#include "RNA_types.h" + #include "bpy.h" #include "bpy_rna.h" #include "bpy_util.h" diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index e4df94cfbc0..73a8deb1b97 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -34,6 +34,8 @@ #include <Python.h> +#include "RNA_types.h" + #include "bpy_operator.h" #include "bpy_operator_wrap.h" #include "bpy_rna.h" /* for setting arg props only - pyrna_py_to_prop() */ @@ -41,6 +43,7 @@ #include "BLI_utildefines.h" +#include "RNA_access.h" #include "RNA_enum_types.h" #include "WM_api.h" diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c index 78b731fdde1..0269625d906 100644 --- a/source/blender/python/intern/bpy_operator_wrap.c +++ b/source/blender/python/intern/bpy_operator_wrap.c @@ -36,6 +36,7 @@ #include "BLI_utildefines.h" +#include "RNA_access.h" #include "RNA_define.h" #include "bpy_rna.h" diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index bae32090529..09c62f8b2c8 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -29,12 +29,17 @@ #include <Python.h> +#include "RNA_types.h" + #include "bpy_props.h" #include "bpy_rna.h" #include "bpy_util.h" #include "BLI_utildefines.h" +#include "BKE_idprop.h" + +#include "RNA_access.h" #include "RNA_define.h" /* for defining our own rna */ #include "RNA_enum_types.h" diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index b1338f3b82d..32a1f387103 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -32,7 +32,10 @@ #include <stddef.h> #include <float.h> /* FLT_MIN/MAX */ +#include "RNA_types.h" + #include "bpy_rna.h" +#include "bpy_rna_anim.h" #include "bpy_props.h" #include "bpy_util.h" #include "bpy_rna_callback.h" @@ -44,6 +47,7 @@ #include "BLI_dynstr.h" #include "BLI_string.h" #include "BLI_listbase.h" +#include "BLI_math_rotation.h" #include "BLI_utildefines.h" #ifdef USE_PYRNA_INVALIDATE_GC @@ -52,6 +56,7 @@ #include "RNA_enum_types.h" #include "RNA_define.h" /* RNA_def_property_free_identifier */ +#include "RNA_access.h" #include "MEM_guardedalloc.h" @@ -59,15 +64,11 @@ #include "BKE_context.h" #include "BKE_global.h" /* evil G.* */ #include "BKE_report.h" +#include "BKE_idprop.h" #include "BKE_animsys.h" #include "BKE_fcurve.h" -/* only for keyframing */ -#include "DNA_scene_types.h" -#include "DNA_anim_types.h" -#include "ED_keyframing.h" - #include "../generic/IDProp.h" /* for IDprop lookups */ #include "../generic/py_capi_utils.h" @@ -77,16 +78,7 @@ static PyObject *pyrna_prop_collection_values(BPy_PropertyRNA *self); -#define PYRNA_STRUCT_CHECK_OBJ(obj) if(pyrna_struct_validity_check(obj) == -1) { return NULL; } -#define PYRNA_STRUCT_CHECK_INT(obj) if(pyrna_struct_validity_check(obj) == -1) { return -1; } - -#define PYRNA_PROP_CHECK_OBJ(obj) if(pyrna_prop_validity_check(obj) == -1) { return NULL; } -#define PYRNA_PROP_CHECK_INT(obj) if(pyrna_prop_validity_check(obj) == -1) { return -1; } - -#define PYRNA_STRUCT_IS_VALID(pysrna) (((BPy_StructRNA *)(pysrna))->ptr.type != NULL) -#define PYRNA_PROP_IS_VALID(pysrna) (((BPy_PropertyRNA *)(pysrna))->ptr.type != NULL) - -static int pyrna_struct_validity_check(BPy_StructRNA *pysrna) +int pyrna_struct_validity_check(BPy_StructRNA *pysrna) { if(pysrna->ptr.type) return 0; @@ -94,7 +86,7 @@ static int pyrna_struct_validity_check(BPy_StructRNA *pysrna) return -1; } -static int pyrna_prop_validity_check(BPy_PropertyRNA *self) +int pyrna_prop_validity_check(BPy_PropertyRNA *self) { if(self->ptr.type) return 0; @@ -527,7 +519,7 @@ static short pyrna_rotation_euler_order_get(PointerRNA *ptr, PropertyRNA **prop_ if(*prop_eul_order) { short order= RNA_property_enum_get(ptr, *prop_eul_order); - if (order >= ROT_MODE_XYZ && order <= ROT_MODE_ZYX) /* could be quat or axisangle */ + if (order >= EULER_ORDER_XYZ && order <= EULER_ORDER_ZYX) /* could be quat or axisangle */ return order; } @@ -606,14 +598,14 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) if(is_thick) { /* attempt to get order, only needed for thick types since wrapped with update via callbacks */ PropertyRNA *prop_eul_order= NULL; - short order= pyrna_rotation_euler_order_get(ptr, &prop_eul_order, ROT_MODE_XYZ); + short order= pyrna_rotation_euler_order_get(ptr, &prop_eul_order, EULER_ORDER_XYZ); ret= newEulerObject(NULL, order, Py_NEW, NULL); // TODO, get order from RNA RNA_property_float_get_array(ptr, prop, ((EulerObject *)ret)->eul); } else { /* order will be updated from callback on use */ - PyObject *eul_cb= newEulerObject_cb(ret, ROT_MODE_XYZ, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_EUL); // TODO, get order from RNA + PyObject *eul_cb= newEulerObject_cb(ret, EULER_ORDER_XYZ, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_EUL); // TODO, get order from RNA Py_DECREF(ret); /* the euler owns now */ ret= eul_cb; /* return the euler instead */ } @@ -2436,308 +2428,6 @@ static PyObject *pyrna_struct_values(BPy_PropertyRNA *self) return BPy_Wrap_GetValues(self->ptr.id.data, group); } -/* for keyframes and drivers */ -static int pyrna_struct_anim_args_parse(PointerRNA *ptr, const char *error_prefix, const char *path, - const char **path_full, int *index) -{ - const int is_idbase= RNA_struct_is_ID(ptr->type); - PropertyRNA *prop; - PointerRNA r_ptr; - - if (ptr->data==NULL) { - PyErr_Format(PyExc_TypeError, "%.200s this struct has no data, can't be animated", error_prefix); - return -1; - } - - /* full paths can only be given from ID base */ - if(is_idbase) { - int r_index= -1; - if(RNA_path_resolve_full(ptr, path, &r_ptr, &prop, &r_index)==0) { - prop= NULL; - } - else if(r_index != -1) { - PyErr_Format(PyExc_ValueError, "%.200s path includes index, must be a separate argument", error_prefix, path); - return -1; - } - else if(ptr->id.data != r_ptr.id.data) { - PyErr_Format(PyExc_ValueError, "%.200s path spans ID blocks", error_prefix, path); - return -1; - } - } - else { - prop = RNA_struct_find_property(ptr, path); - r_ptr= *ptr; - } - - if (prop==NULL) { - PyErr_Format(PyExc_TypeError, "%.200s property \"%s\" not found", error_prefix, path); - return -1; - } - - if (!RNA_property_animateable(&r_ptr, prop)) { - PyErr_Format(PyExc_TypeError, "%.200s property \"%s\" not animatable", error_prefix, path); - return -1; - } - - if(RNA_property_array_check(&r_ptr, prop) == 0) { - if((*index) == -1) { - *index= 0; - } - else { - PyErr_Format(PyExc_TypeError, "%.200s index %d was given while property \"%s\" is not an array", error_prefix, *index, path); - return -1; - } - } - else { - int array_len= RNA_property_array_length(&r_ptr, prop); - if((*index) < -1 || (*index) >= array_len) { - PyErr_Format(PyExc_TypeError, "%.200s index out of range \"%s\", given %d, array length is %d", error_prefix, path, *index, array_len); - return -1; - } - } - - if(is_idbase) { - *path_full= BLI_strdup(path); - } - else { - *path_full= RNA_path_from_ID_to_property(&r_ptr, prop); - - if (*path_full==NULL) { - PyErr_Format(PyExc_TypeError, "%.200s could not make path to \"%s\"", error_prefix, path); - return -1; - } - } - - return 0; -} - -/* internal use for insert and delete */ -static int pyrna_struct_keyframe_parse(PointerRNA *ptr, PyObject *args, PyObject *kw, const char *parse_str, const char *error_prefix, - const char **path_full, int *index, float *cfra, const char **group_name) /* return values */ -{ - static const char *kwlist[] = {"data_path", "index", "frame", "group", NULL}; - const char *path; - - /* note, parse_str MUST start with 's|ifs' */ - if (!PyArg_ParseTupleAndKeywords(args, kw, parse_str, (char **)kwlist, &path, index, cfra, group_name)) - return -1; - - if(pyrna_struct_anim_args_parse(ptr, error_prefix, path, path_full, index) < 0) - return -1; - - if(*cfra==FLT_MAX) - *cfra= CTX_data_scene(BPy_GetContext())->r.cfra; - - return 0; /* success */ -} - -static char pyrna_struct_keyframe_insert_doc[] = -".. method:: keyframe_insert(data_path, index=-1, frame=bpy.context.scene.frame_current, group=\"\")\n" -"\n" -" Insert a keyframe on the property given, adding fcurves and animation data when necessary.\n" -"\n" -" :arg data_path: path to the property to key, analogous to the fcurve's data path.\n" -" :type data_path: string\n" -" :arg index: array index of the property to key. Defaults to -1 which will key all indices or a single channel if the property is not an array.\n" -" :type index: int\n" -" :arg frame: The frame on which the keyframe is inserted, defaulting to the current frame.\n" -" :type frame: float\n" -" :arg group: The name of the group the F-Curve should be added to if it doesn't exist yet.\n" -" :type group: str\n" -" :return: Success of keyframe insertion.\n" -" :rtype: boolean\n" -; -static PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyObject *kw) -{ - /* args, pyrna_struct_keyframe_parse handles these */ - const char *path_full= NULL; - int index= -1; - float cfra= FLT_MAX; - const char *group_name= NULL; - - PYRNA_STRUCT_CHECK_OBJ(self) - - if(pyrna_struct_keyframe_parse(&self->ptr, args, kw, "s|ifs:bpy_struct.keyframe_insert()", "bpy_struct.keyframe_insert()", &path_full, &index, &cfra, &group_name) == -1) { - return NULL; - } - else { - short result; - ReportList reports; - - BKE_reports_init(&reports, RPT_STORE); - - result= insert_keyframe(&reports, (ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0); - MEM_freeN((void *)path_full); - - if(BPy_reports_to_error(&reports, TRUE)) - return NULL; - - return PyBool_FromLong(result); - } -} - -static char pyrna_struct_keyframe_delete_doc[] = -".. method:: keyframe_delete(data_path, index=-1, frame=bpy.context.scene.frame_current, group=\"\")\n" -"\n" -" Remove a keyframe from this properties fcurve.\n" -"\n" -" :arg data_path: path to the property to remove a key, analogous to the fcurve's data path.\n" -" :type data_path: string\n" -" :arg index: array index of the property to remove a key. Defaults to -1 removing all indices or a single channel if the property is not an array.\n" -" :type index: int\n" -" :arg frame: The frame on which the keyframe is deleted, defaulting to the current frame.\n" -" :type frame: float\n" -" :arg group: The name of the group the F-Curve should be added to if it doesn't exist yet.\n" -" :type group: str\n" -" :return: Success of keyframe deleation.\n" -" :rtype: boolean\n" -; -static PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyObject *kw) -{ - /* args, pyrna_struct_keyframe_parse handles these */ - const char *path_full= NULL; - int index= -1; - float cfra= FLT_MAX; - const char *group_name= NULL; - - PYRNA_STRUCT_CHECK_OBJ(self) - - if(pyrna_struct_keyframe_parse(&self->ptr, args, kw, "s|ifs:bpy_struct.keyframe_delete()", "bpy_struct.keyframe_insert()", &path_full, &index, &cfra, &group_name) == -1) { - return NULL; - } - else { - short result; - ReportList reports; - - BKE_reports_init(&reports, RPT_STORE); - - result= delete_keyframe(&reports, (ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0); - MEM_freeN((void *)path_full); - - if(BPy_reports_to_error(&reports, TRUE)) - return NULL; - - return PyBool_FromLong(result); - } - -} - -static char pyrna_struct_driver_add_doc[] = -".. method:: driver_add(path, index=-1)\n" -"\n" -" Adds driver(s) to the given property\n" -"\n" -" :arg path: path to the property to drive, analogous to the fcurve's data path.\n" -" :type path: string\n" -" :arg index: array index of the property drive. Defaults to -1 for all indices or a single channel if the property is not an array.\n" -" :type index: int\n" -" :return: The driver(s) added.\n" -" :rtype: :class:`FCurve` or list if index is -1 with an array property.\n" -; -static PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args) -{ - const char *path, *path_full; - int index= -1; - - PYRNA_STRUCT_CHECK_OBJ(self) - - if (!PyArg_ParseTuple(args, "s|i:driver_add", &path, &index)) - return NULL; - - if(pyrna_struct_anim_args_parse(&self->ptr, "bpy_struct.driver_add():", path, &path_full, &index) < 0) { - return NULL; - } - else { - PyObject *ret= NULL; - ReportList reports; - int result; - - BKE_reports_init(&reports, RPT_STORE); - - result= ANIM_add_driver(&reports, (ID *)self->ptr.id.data, path_full, index, 0, DRIVER_TYPE_PYTHON); - - if(BPy_reports_to_error(&reports, TRUE)) - return NULL; - - if(result) { - ID *id= self->ptr.id.data; - AnimData *adt= BKE_animdata_from_id(id); - FCurve *fcu; - - PointerRNA tptr; - PyObject *item; - - if(index == -1) { /* all, use a list */ - int i= 0; - ret= PyList_New(0); - while((fcu= list_find_fcurve(&adt->drivers, path_full, i++))) { - RNA_pointer_create(id, &RNA_FCurve, fcu, &tptr); - item= pyrna_struct_CreatePyObject(&tptr); - PyList_Append(ret, item); - Py_DECREF(item); - } - } - else { - fcu= list_find_fcurve(&adt->drivers, path_full, index); - RNA_pointer_create(id, &RNA_FCurve, fcu, &tptr); - ret= pyrna_struct_CreatePyObject(&tptr); - } - } - else { - /* XXX, should be handled by reports, */ - PyErr_SetString(PyExc_TypeError, "bpy_struct.driver_add(): failed because of an internal error"); - return NULL; - } - - MEM_freeN((void *)path_full); - - return ret; - } -} - - -static char pyrna_struct_driver_remove_doc[] = -".. method:: driver_remove(path, index=-1)\n" -"\n" -" Remove driver(s) from the given property\n" -"\n" -" :arg path: path to the property to drive, analogous to the fcurve's data path.\n" -" :type path: string\n" -" :arg index: array index of the property drive. Defaults to -1 for all indices or a single channel if the property is not an array.\n" -" :type index: int\n" -" :return: Success of driver removal.\n" -" :rtype: boolean\n" -; -static PyObject *pyrna_struct_driver_remove(BPy_StructRNA *self, PyObject *args) -{ - const char *path, *path_full; - int index= -1; - - PYRNA_STRUCT_CHECK_OBJ(self) - - if (!PyArg_ParseTuple(args, "s|i:driver_remove", &path, &index)) - return NULL; - - if(pyrna_struct_anim_args_parse(&self->ptr, "bpy_struct.driver_remove():", path, &path_full, &index) < 0) { - return NULL; - } - else { - short result; - ReportList reports; - - BKE_reports_init(&reports, RPT_STORE); - - result= ANIM_remove_driver(&reports, (ID *)self->ptr.id.data, path_full, index, 0); - - MEM_freeN((void *)path_full); - - if(BPy_reports_to_error(&reports, TRUE)) - return NULL; - - return PyBool_FromLong(result); - } -} - static char pyrna_struct_is_property_set_doc[] = ".. method:: is_property_set(property)\n" @@ -3969,10 +3659,12 @@ static struct PyMethodDef pyrna_struct_methods[] = { {"as_pointer", (PyCFunction)pyrna_struct_as_pointer, METH_NOARGS, pyrna_struct_as_pointer_doc}, + /* bpy_rna_anim.c */ {"keyframe_insert", (PyCFunction)pyrna_struct_keyframe_insert, METH_VARARGS|METH_KEYWORDS, pyrna_struct_keyframe_insert_doc}, {"keyframe_delete", (PyCFunction)pyrna_struct_keyframe_delete, METH_VARARGS|METH_KEYWORDS, pyrna_struct_keyframe_delete_doc}, {"driver_add", (PyCFunction)pyrna_struct_driver_add, METH_VARARGS, pyrna_struct_driver_add_doc}, {"driver_remove", (PyCFunction)pyrna_struct_driver_remove, METH_VARARGS, pyrna_struct_driver_remove_doc}, + {"is_property_set", (PyCFunction)pyrna_struct_is_property_set, METH_VARARGS, pyrna_struct_is_property_set_doc}, {"is_property_hidden", (PyCFunction)pyrna_struct_is_property_hidden, METH_VARARGS, pyrna_struct_is_property_hidden_doc}, {"path_resolve", (PyCFunction)pyrna_struct_path_resolve, METH_VARARGS, pyrna_struct_path_resolve_doc}, diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index be877344c48..77f1fa3b336 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -29,21 +29,8 @@ #ifndef BPY_RNA_H #define BPY_RNA_H -#include "RNA_access.h" -#include "RNA_types.h" -#include "BKE_idprop.h" - -extern PyTypeObject pyrna_struct_meta_idprop_Type; -extern PyTypeObject pyrna_struct_Type; -extern PyTypeObject pyrna_prop_Type; -extern PyTypeObject pyrna_prop_array_Type; -extern PyTypeObject pyrna_prop_collection_Type; - -#define BPy_StructRNA_Check(v) (PyObject_TypeCheck(v, &pyrna_struct_Type)) -#define BPy_StructRNA_CheckExact(v) (Py_TYPE(v) == &pyrna_struct_Type) -#define BPy_PropertyRNA_Check(v) (PyObject_TypeCheck(v, &pyrna_prop_Type)) -#define BPy_PropertyRNA_CheckExact(v) (Py_TYPE(v) == &pyrna_prop_Type) +/* --- bpy build options --- */ /* play it safe and keep optional for now, need to test further now this affects looping on 10000's of verts for eg. */ // #define USE_WEAKREFS @@ -62,6 +49,28 @@ extern PyTypeObject pyrna_prop_collection_Type; #if defined(USE_PYRNA_INVALIDATE_GC) && defined(USE_PYRNA_INVALIDATE_WEAKREF) #error "Only 1 reference check method at a time!" #endif +/* --- end bpy build options --- */ + + +extern PyTypeObject pyrna_struct_meta_idprop_Type; +extern PyTypeObject pyrna_struct_Type; +extern PyTypeObject pyrna_prop_Type; +extern PyTypeObject pyrna_prop_array_Type; +extern PyTypeObject pyrna_prop_collection_Type; + +#define BPy_StructRNA_Check(v) (PyObject_TypeCheck(v, &pyrna_struct_Type)) +#define BPy_StructRNA_CheckExact(v) (Py_TYPE(v) == &pyrna_struct_Type) +#define BPy_PropertyRNA_Check(v) (PyObject_TypeCheck(v, &pyrna_prop_Type)) +#define BPy_PropertyRNA_CheckExact(v) (Py_TYPE(v) == &pyrna_prop_Type) + +#define PYRNA_STRUCT_CHECK_OBJ(obj) if(pyrna_struct_validity_check(obj) == -1) { return NULL; } +#define PYRNA_STRUCT_CHECK_INT(obj) if(pyrna_struct_validity_check(obj) == -1) { return -1; } + +#define PYRNA_PROP_CHECK_OBJ(obj) if(pyrna_prop_validity_check(obj) == -1) { return NULL; } +#define PYRNA_PROP_CHECK_INT(obj) if(pyrna_prop_validity_check(obj) == -1) { return -1; } + +#define PYRNA_STRUCT_IS_VALID(pysrna) (((BPy_StructRNA *)(pysrna))->ptr.type != NULL) +#define PYRNA_PROP_IS_VALID(pysrna) (((BPy_PropertyRNA *)(pysrna))->ptr.type != NULL) typedef struct { PyObject_HEAD /* required python macro */ @@ -141,6 +150,9 @@ int pyrna_array_contains_py(PointerRNA *ptr, PropertyRNA *prop, PyObject *value) int pyrna_write_check(void); +int pyrna_struct_validity_check(BPy_StructRNA *pysrna); +int pyrna_prop_validity_check(BPy_PropertyRNA *self); + void BPY_modules_update(struct bContext *C); //XXX temp solution /* bpy.utils.(un)register_class */ diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c new file mode 100644 index 00000000000..d85710bf388 --- /dev/null +++ b/source/blender/python/intern/bpy_rna_anim.c @@ -0,0 +1,353 @@ +/* + * $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/python/intern/bpy_rna_anim.c + * \ingroup pythonintern + */ + +#include <Python.h> +#include <float.h> /* FLT_MIN/MAX */ + +#include "MEM_guardedalloc.h" + +#include "BLI_string.h" + +#include "DNA_scene_types.h" +#include "DNA_anim_types.h" +#include "ED_keyframing.h" + +#include "BKE_report.h" +#include "BKE_context.h" +#include "BKE_animsys.h" +#include "BKE_fcurve.h" + +#include "ED_keyframing.h" + +#include "bpy_rna.h" +#include "bpy_util.h" + +#define TRUE 1 +#define FALSE 0 + +/* for keyframes and drivers */ +static int pyrna_struct_anim_args_parse(PointerRNA *ptr, const char *error_prefix, const char *path, + const char **path_full, int *index) +{ + const int is_idbase= RNA_struct_is_ID(ptr->type); + PropertyRNA *prop; + PointerRNA r_ptr; + + if (ptr->data==NULL) { + PyErr_Format(PyExc_TypeError, "%.200s this struct has no data, can't be animated", error_prefix); + return -1; + } + + /* full paths can only be given from ID base */ + if(is_idbase) { + int r_index= -1; + if(RNA_path_resolve_full(ptr, path, &r_ptr, &prop, &r_index)==0) { + prop= NULL; + } + else if(r_index != -1) { + PyErr_Format(PyExc_ValueError, "%.200s path includes index, must be a separate argument", error_prefix, path); + return -1; + } + else if(ptr->id.data != r_ptr.id.data) { + PyErr_Format(PyExc_ValueError, "%.200s path spans ID blocks", error_prefix, path); + return -1; + } + } + else { + prop = RNA_struct_find_property(ptr, path); + r_ptr= *ptr; + } + + if (prop==NULL) { + PyErr_Format(PyExc_TypeError, "%.200s property \"%s\" not found", error_prefix, path); + return -1; + } + + if (!RNA_property_animateable(&r_ptr, prop)) { + PyErr_Format(PyExc_TypeError, "%.200s property \"%s\" not animatable", error_prefix, path); + return -1; + } + + if(RNA_property_array_check(&r_ptr, prop) == 0) { + if((*index) == -1) { + *index= 0; + } + else { + PyErr_Format(PyExc_TypeError, "%.200s index %d was given while property \"%s\" is not an array", error_prefix, *index, path); + return -1; + } + } + else { + int array_len= RNA_property_array_length(&r_ptr, prop); + if((*index) < -1 || (*index) >= array_len) { + PyErr_Format(PyExc_TypeError, "%.200s index out of range \"%s\", given %d, array length is %d", error_prefix, path, *index, array_len); + return -1; + } + } + + if(is_idbase) { + *path_full= BLI_strdup(path); + } + else { + *path_full= RNA_path_from_ID_to_property(&r_ptr, prop); + + if (*path_full==NULL) { + PyErr_Format(PyExc_TypeError, "%.200s could not make path to \"%s\"", error_prefix, path); + return -1; + } + } + + return 0; +} + +/* internal use for insert and delete */ +static int pyrna_struct_keyframe_parse(PointerRNA *ptr, PyObject *args, PyObject *kw, const char *parse_str, const char *error_prefix, + const char **path_full, int *index, float *cfra, const char **group_name) /* return values */ +{ + static const char *kwlist[] = {"data_path", "index", "frame", "group", NULL}; + const char *path; + + /* note, parse_str MUST start with 's|ifs' */ + if (!PyArg_ParseTupleAndKeywords(args, kw, parse_str, (char **)kwlist, &path, index, cfra, group_name)) + return -1; + + if(pyrna_struct_anim_args_parse(ptr, error_prefix, path, path_full, index) < 0) + return -1; + + if(*cfra==FLT_MAX) + *cfra= CTX_data_scene(BPy_GetContext())->r.cfra; + + return 0; /* success */ +} + +char pyrna_struct_keyframe_insert_doc[] = +".. method:: keyframe_insert(data_path, index=-1, frame=bpy.context.scene.frame_current, group=\"\")\n" +"\n" +" Insert a keyframe on the property given, adding fcurves and animation data when necessary.\n" +"\n" +" :arg data_path: path to the property to key, analogous to the fcurve's data path.\n" +" :type data_path: string\n" +" :arg index: array index of the property to key. Defaults to -1 which will key all indices or a single channel if the property is not an array.\n" +" :type index: int\n" +" :arg frame: The frame on which the keyframe is inserted, defaulting to the current frame.\n" +" :type frame: float\n" +" :arg group: The name of the group the F-Curve should be added to if it doesn't exist yet.\n" +" :type group: str\n" +" :return: Success of keyframe insertion.\n" +" :rtype: boolean\n" +; +PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyObject *kw) +{ + /* args, pyrna_struct_keyframe_parse handles these */ + const char *path_full= NULL; + int index= -1; + float cfra= FLT_MAX; + const char *group_name= NULL; + + PYRNA_STRUCT_CHECK_OBJ(self) + + if(pyrna_struct_keyframe_parse(&self->ptr, args, kw, "s|ifs:bpy_struct.keyframe_insert()", "bpy_struct.keyframe_insert()", &path_full, &index, &cfra, &group_name) == -1) { + return NULL; + } + else { + short result; + ReportList reports; + + BKE_reports_init(&reports, RPT_STORE); + + result= insert_keyframe(&reports, (ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0); + MEM_freeN((void *)path_full); + + if(BPy_reports_to_error(&reports, TRUE)) + return NULL; + + return PyBool_FromLong(result); + } +} + +char pyrna_struct_keyframe_delete_doc[] = +".. method:: keyframe_delete(data_path, index=-1, frame=bpy.context.scene.frame_current, group=\"\")\n" +"\n" +" Remove a keyframe from this properties fcurve.\n" +"\n" +" :arg data_path: path to the property to remove a key, analogous to the fcurve's data path.\n" +" :type data_path: string\n" +" :arg index: array index of the property to remove a key. Defaults to -1 removing all indices or a single channel if the property is not an array.\n" +" :type index: int\n" +" :arg frame: The frame on which the keyframe is deleted, defaulting to the current frame.\n" +" :type frame: float\n" +" :arg group: The name of the group the F-Curve should be added to if it doesn't exist yet.\n" +" :type group: str\n" +" :return: Success of keyframe deleation.\n" +" :rtype: boolean\n" +; +PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyObject *kw) +{ + /* args, pyrna_struct_keyframe_parse handles these */ + const char *path_full= NULL; + int index= -1; + float cfra= FLT_MAX; + const char *group_name= NULL; + + PYRNA_STRUCT_CHECK_OBJ(self) + + if(pyrna_struct_keyframe_parse(&self->ptr, args, kw, "s|ifs:bpy_struct.keyframe_delete()", "bpy_struct.keyframe_insert()", &path_full, &index, &cfra, &group_name) == -1) { + return NULL; + } + else { + short result; + ReportList reports; + + BKE_reports_init(&reports, RPT_STORE); + + result= delete_keyframe(&reports, (ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0); + MEM_freeN((void *)path_full); + + if(BPy_reports_to_error(&reports, TRUE)) + return NULL; + + return PyBool_FromLong(result); + } + +} + +char pyrna_struct_driver_add_doc[] = +".. method:: driver_add(path, index=-1)\n" +"\n" +" Adds driver(s) to the given property\n" +"\n" +" :arg path: path to the property to drive, analogous to the fcurve's data path.\n" +" :type path: string\n" +" :arg index: array index of the property drive. Defaults to -1 for all indices or a single channel if the property is not an array.\n" +" :type index: int\n" +" :return: The driver(s) added.\n" +" :rtype: :class:`FCurve` or list if index is -1 with an array property.\n" +; +PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args) +{ + const char *path, *path_full; + int index= -1; + + PYRNA_STRUCT_CHECK_OBJ(self) + + if (!PyArg_ParseTuple(args, "s|i:driver_add", &path, &index)) + return NULL; + + if(pyrna_struct_anim_args_parse(&self->ptr, "bpy_struct.driver_add():", path, &path_full, &index) < 0) { + return NULL; + } + else { + PyObject *ret= NULL; + ReportList reports; + int result; + + BKE_reports_init(&reports, RPT_STORE); + + result= ANIM_add_driver(&reports, (ID *)self->ptr.id.data, path_full, index, 0, DRIVER_TYPE_PYTHON); + + if(BPy_reports_to_error(&reports, TRUE)) + return NULL; + + if(result) { + ID *id= self->ptr.id.data; + AnimData *adt= BKE_animdata_from_id(id); + FCurve *fcu; + + PointerRNA tptr; + PyObject *item; + + if(index == -1) { /* all, use a list */ + int i= 0; + ret= PyList_New(0); + while((fcu= list_find_fcurve(&adt->drivers, path_full, i++))) { + RNA_pointer_create(id, &RNA_FCurve, fcu, &tptr); + item= pyrna_struct_CreatePyObject(&tptr); + PyList_Append(ret, item); + Py_DECREF(item); + } + } + else { + fcu= list_find_fcurve(&adt->drivers, path_full, index); + RNA_pointer_create(id, &RNA_FCurve, fcu, &tptr); + ret= pyrna_struct_CreatePyObject(&tptr); + } + } + else { + /* XXX, should be handled by reports, */ + PyErr_SetString(PyExc_TypeError, "bpy_struct.driver_add(): failed because of an internal error"); + return NULL; + } + + MEM_freeN((void *)path_full); + + return ret; + } +} + + +char pyrna_struct_driver_remove_doc[] = +".. method:: driver_remove(path, index=-1)\n" +"\n" +" Remove driver(s) from the given property\n" +"\n" +" :arg path: path to the property to drive, analogous to the fcurve's data path.\n" +" :type path: string\n" +" :arg index: array index of the property drive. Defaults to -1 for all indices or a single channel if the property is not an array.\n" +" :type index: int\n" +" :return: Success of driver removal.\n" +" :rtype: boolean\n" +; +PyObject *pyrna_struct_driver_remove(BPy_StructRNA *self, PyObject *args) +{ + const char *path, *path_full; + int index= -1; + + PYRNA_STRUCT_CHECK_OBJ(self) + + if (!PyArg_ParseTuple(args, "s|i:driver_remove", &path, &index)) + return NULL; + + if(pyrna_struct_anim_args_parse(&self->ptr, "bpy_struct.driver_remove():", path, &path_full, &index) < 0) { + return NULL; + } + else { + short result; + ReportList reports; + + BKE_reports_init(&reports, RPT_STORE); + + result= ANIM_remove_driver(&reports, (ID *)self->ptr.id.data, path_full, index, 0); + + MEM_freeN((void *)path_full); + + if(BPy_reports_to_error(&reports, TRUE)) + return NULL; + + return PyBool_FromLong(result); + } +} diff --git a/source/blender/python/intern/bpy_rna_anim.h b/source/blender/python/intern/bpy_rna_anim.h new file mode 100644 index 00000000000..bd50a1805a2 --- /dev/null +++ b/source/blender/python/intern/bpy_rna_anim.h @@ -0,0 +1,37 @@ +/* + * $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/python/intern/bpy_rna_anim.h + * \ingroup pythonintern + */ + +extern char pyrna_struct_keyframe_insert_doc[]; +extern char pyrna_struct_keyframe_delete_doc[]; +extern char pyrna_struct_driver_add_doc[]; +extern char pyrna_struct_driver_remove_doc[]; + +PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyObject *kw); +PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyObject *kw); +PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args); +PyObject *pyrna_struct_driver_remove(BPy_StructRNA *self, PyObject *args); diff --git a/source/blender/python/intern/bpy_rna_array.c b/source/blender/python/intern/bpy_rna_array.c index dc2f56fea99..8e7aba42a99 100644 --- a/source/blender/python/intern/bpy_rna_array.c +++ b/source/blender/python/intern/bpy_rna_array.c @@ -28,10 +28,14 @@ #include <Python.h> +#include "RNA_types.h" + #include "bpy_rna.h" #include "BKE_global.h" #include "MEM_guardedalloc.h" +#include "RNA_access.h" + #define MAX_ARRAY_DIMENSION 10 typedef void (*ItemConvertFunc)(PyObject *, char *); diff --git a/source/blender/python/intern/bpy_rna_callback.c b/source/blender/python/intern/bpy_rna_callback.c index 81ec955300a..7581eb16a9d 100644 --- a/source/blender/python/intern/bpy_rna_callback.c +++ b/source/blender/python/intern/bpy_rna_callback.c @@ -29,6 +29,8 @@ #include <Python.h> +#include "RNA_types.h" + #include "bpy_rna.h" #include "bpy_rna_callback.h" #include "bpy_util.h" @@ -37,6 +39,8 @@ #include "DNA_screen_types.h" +#include "RNA_access.h" + #include "BKE_context.h" #include "ED_space_api.h" |