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:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2009-04-19 17:37:59 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2009-04-19 17:37:59 +0400
commitadff6aeb1c749183921c0facd373972bbeb874b4 (patch)
tree07987d408713eee8a3dd8bb5cb4ecf3c112de654 /source/blender/python
parentd880257d165888638b7c924fb6ef7071343b783e (diff)
RNA: Generic Type Registration
The Python API to define Panels and Operators is based on subclassing, this makes that system more generic, and based on RNA. Hopefully that will make it easy to make various parts of Blender more extensible. * The system simply uses RNA properties and functions and marks them with REGISTER to make them part of the type registration process. Additionally, the struct must provide a register/unregister callback to create/free the PanelType or similar. * From the python side there were some small changes, mainly that registration now goes trough bpy.types.register instead of bpy.ui.addPanel. * Only Panels have been wrapped this way now. Check rna_ui.c to see how this code works. There's still some rough edges and possibilities to make it cleaner, though it works without any manual python code. * Started some docs here: http://wiki.blender.org/index.php/BlenderDev/Blender2.5/RNATypeRegistration * Also changed some RNA_property and RNA_struct functions to not require a PointerRNA anymore, where they were not required (which is actually the cause of most changed files).
Diffstat (limited to 'source/blender/python')
-rw-r--r--source/blender/python/intern/bpy_operator.c16
-rw-r--r--source/blender/python/intern/bpy_operator_wrap.c4
-rw-r--r--source/blender/python/intern/bpy_panel_wrap.c252
-rw-r--r--source/blender/python/intern/bpy_panel_wrap.h36
-rw-r--r--source/blender/python/intern/bpy_rna.c479
-rw-r--r--source/blender/python/intern/bpy_rna.h3
-rw-r--r--source/blender/python/intern/bpy_ui.c4
-rw-r--r--source/blender/python/intern/bpy_util.c20
-rw-r--r--source/blender/python/intern/bpy_util.h4
9 files changed, 454 insertions, 364 deletions
diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c
index 660e1d01b6c..f8dcb1f43a1 100644
--- a/source/blender/python/intern/bpy_operator.c
+++ b/source/blender/python/intern/bpy_operator.c
@@ -27,6 +27,7 @@
#include "bpy_operator_wrap.h"
#include "bpy_rna.h" /* for setting arg props only - pyrna_py_to_prop() */
#include "bpy_compat.h"
+#include "bpy_util.h"
//#include "blendef.h"
#include "BLI_dynstr.h"
@@ -54,7 +55,7 @@ int PYOP_props_from_dict(PointerRNA *ptr, PyObject *kw)
PropertyRNA *prop, *iterprop;
CollectionPropertyIterator iter;
- iterprop= RNA_struct_iterator_property(ptr);
+ iterprop= RNA_struct_iterator_property(ptr->type);
RNA_property_collection_begin(ptr, iterprop, &iter);
totkw = kw ? PyDict_Size(kw):0;
@@ -62,7 +63,7 @@ int PYOP_props_from_dict(PointerRNA *ptr, PyObject *kw)
for(; iter.valid; RNA_property_collection_next(&iter)) {
prop= iter.ptr.data;
- arg_name= RNA_property_identifier(&iter.ptr, prop);
+ arg_name= RNA_property_identifier(prop);
if (strcmp(arg_name, "rna_type")==0) continue;
@@ -128,7 +129,6 @@ static PyObject *pyop_base_call( PyObject * self, PyObject * args, PyObject * k
bContext *C = (bContext *)PyCObject_AsVoidPtr(PyDict_GetItemString(PyEval_GetGlobals(), "__bpy_context__"));
char *opname = _PyUnicode_AsString(self);
- char *report_str= NULL;
if (PyTuple_Size(args)) {
PyErr_SetString( PyExc_AttributeError, "All operator args must be keywords");
@@ -157,16 +157,10 @@ static PyObject *pyop_base_call( PyObject * self, PyObject * args, PyObject * k
WM_operator_call_py(C, ot, &ptr, &reports);
- report_str= BKE_reports_string(&reports, RPT_ERROR);
-
- if (report_str) {
- PyErr_SetString(PyExc_SystemError, report_str);
- MEM_freeN(report_str);
+ if(BPy_reports_to_error(&reports))
error_val = -1;
- }
- if (reports.list.first)
- BKE_reports_clear(&reports);
+ BKE_reports_clear(&reports);
}
WM_operator_properties_free(&ptr);
diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c
index 02a87450a06..4fa72fe18bc 100644
--- a/source/blender/python/intern/bpy_operator_wrap.c
+++ b/source/blender/python/intern/bpy_operator_wrap.c
@@ -208,12 +208,12 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
CollectionPropertyIterator iter;
const char *arg_name;
- iterprop= RNA_struct_iterator_property(op->ptr);
+ iterprop= RNA_struct_iterator_property(op->ptr->type);
RNA_property_collection_begin(op->ptr, iterprop, &iter);
for(; iter.valid; RNA_property_collection_next(&iter)) {
prop= iter.ptr.data;
- arg_name= RNA_property_identifier(&iter.ptr, prop);
+ arg_name= RNA_property_identifier(prop);
if (strcmp(arg_name, "rna_type")==0) continue;
diff --git a/source/blender/python/intern/bpy_panel_wrap.c b/source/blender/python/intern/bpy_panel_wrap.c
deleted file mode 100644
index a8409d44553..00000000000
--- a/source/blender/python/intern/bpy_panel_wrap.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/**
- * $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_panel_wrap.h"
-#include "bpy_rna.h"
-#include "bpy_util.h"
-#include "bpy_compat.h"
-
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
-#include "BLI_listbase.h"
-#include "BKE_context.h"
-#include "BKE_screen.h"
-#include "DNA_screen_types.h"
-#include "MEM_guardedalloc.h"
-#include "ED_screen.h"
-#include "WM_api.h"
-#include "WM_types.h"
-
-#define PYPANEL_ATTR_UINAME "__label__"
-#define PYPANEL_ATTR_IDNAME "__name__" /* use pythons class name */
-#define PYPANEL_ATTR_CONTEXT "__context__"
-
-#define PYPANEL_DRAW 1
-#define PYPANEL_POLL 2
-
-extern void BPY_update_modules( void ); //XXX temp solution
-
-static int PyPanel_generic(int mode, const bContext *C, Panel *pnl)
-{
- PyObject *py_class= (PyObject *)(pnl->type->py_data);
-
- PyObject *args;
- PyObject *ret= NULL, *py_class_instance, *item;
- PointerRNA panelptr;
- int ret_flag= 0;
-
- PyGILState_STATE gilstate = PyGILState_Ensure();
-
- BPY_update_modules(); // XXX - the RNA pointers can change so update before running, would like a nicer solutuon for this.
-
- args = PyTuple_New(1);
- RNA_pointer_create(&CTX_wm_screen(C)->id, pnl->type->srna, pnl, &panelptr);
- PyTuple_SET_ITEM(args, 0, pyrna_struct_CreatePyObject(&panelptr));
- py_class_instance = PyObject_Call(py_class, args, NULL);
- Py_DECREF(args);
-
- if (py_class_instance) { /* Initializing the class worked, now run its invoke function */
- PointerRNA context_ptr;
-
- if (mode==PYPANEL_DRAW) {
- item= PyObject_GetAttrString(py_class, "draw");
- }
- else if (mode==PYPANEL_POLL) {
- item= PyObject_GetAttrString(py_class, "poll");
- }
- args = PyTuple_New(2);
- PyTuple_SET_ITEM(args, 0, py_class_instance);
-
- RNA_pointer_create(NULL, &RNA_Context, (void *)C, &context_ptr);
-
- PyTuple_SET_ITEM(args, 1, pyrna_struct_CreatePyObject(&context_ptr));
-
- ret = PyObject_Call(item, args, NULL);
-
- /* args is decref'd from item */
- Py_DECREF(item);
- }
-
- if (ret == NULL) { /* covers py_class_instance failing too */
- PyErr_Print(); /* XXX use reporting api? */
- }
- else {
- if (mode==PYPANEL_POLL) {
- if (PyBool_Check(ret) == 0) {
- PyErr_SetString(PyExc_ValueError, "Python poll function return value ");
- PyErr_Print(); /* XXX use reporting api? */
- }
- else {
- ret_flag= ret==Py_True ? 1:0;
- }
- }
- else {
- //XXX - draw stuff
- }
-
- Py_DECREF(ret);
- }
- PyGILState_Release(gilstate);
-
- return ret_flag;
-}
-
-static void PyPanel_draw(const bContext *C, Panel *pnl)
-{
- PyPanel_generic(PYPANEL_DRAW, C, pnl);
-}
-
-static int PyPanel_poll(const bContext *C)
-{
- //return PyPanel_generic(PYPANEL_POLL, C, NULL);
- return 1; // XXX we need the panel type to access the PyObject grr!
-}
-
-/* pyOperators - Operators defined IN Python */
-PyObject *PyPanel_wrap_add(PyObject *self, PyObject *args)
-{
- bContext *C;
- PyObject *item;
- PyObject *py_class;
- PyObject *base_class;
- char *space_identifier;
- char *region_identifier;
- char *idname;
- int space_value;
- int region_value;
-
- PanelType *pt;
- SpaceType *st;
- ARegionType *art;
-
- static struct BPY_class_attr_check pypnl_class_attr_values[]= {
- {PYPANEL_ATTR_IDNAME, 's', 0, 0},
- {PYPANEL_ATTR_UINAME, 's', 0, 0},
- {PYPANEL_ATTR_CONTEXT, 's', 0, 0},
- {"draw", 'f', 2, 0}, /* Do we need the Panel struct?, could be an extra arg */
- {"poll", 'f', 2, BPY_CLASS_ATTR_OPTIONAL},
- {NULL, 0, 0, 0}};
-
- enum {
- PYPANEL_ATTR_IDNAME_IDX=0,
- PYPANEL_ATTR_UINAME_IDX,
- PYPANEL_ATTR_CONTEXT_IDX,
- PYPANEL_ATTR_DRAW_IDX,
- PYPANEL_ATTR_POLL_IDX
- };
-
- PyObject *pypnl_class_attrs[6]= {NULL, NULL, NULL, NULL, NULL, NULL};
-
- if( !PyArg_ParseTuple( args, "Oss:addPanel", &py_class, &space_identifier, &region_identifier))
- return NULL;
-
- base_class = PyObject_GetAttrStringArgs(PyDict_GetItemString(PyEval_GetGlobals(), "bpy"), 2, "types", "Panel");
- Py_DECREF(base_class);
-
- /* Should this use a base class? */
- if (BPY_class_validate("Panel", py_class, base_class, pypnl_class_attr_values, pypnl_class_attrs) < 0) {
- return NULL; /* BPY_class_validate sets the error */
- }
-
- if (RNA_enum_value_from_id(space_type_items, space_identifier, &space_value)==0) {
- char *cstring= BPy_enum_as_string(space_type_items);
- PyErr_Format( PyExc_AttributeError, "SpaceType \"%s\" is not one of [%s]", space_identifier, cstring);
- MEM_freeN(cstring);
- return NULL;
- }
-
- if (RNA_enum_value_from_id(region_type_items, region_identifier, &region_value)==0) {
- char *cstring= BPy_enum_as_string(region_type_items);
- PyErr_Format( PyExc_AttributeError, "RegionType \"%s\" is not one of [%s]", region_identifier, cstring);
- MEM_freeN(cstring);
- return NULL;
- }
-
- st= BKE_spacetype_from_id(space_value);
-
-#if 0
- // for printing what panels we have
- for(art= st->regiontypes.first; art; art= art->next) {
-
- printf("REG %d\n", art->regionid);
-
- for(pt= art->paneltypes.first; pt; pt= pt->next) {
- printf("\tREG %s %s - %s\n", pt->idname, pt->name, pt->context);
- }
- }
-#endif
-
- for(art= st->regiontypes.first; art; art= art->next) {
- if (art->regionid==region_value)
- break;
- }
-
- if (art==NULL) {
- PyErr_Format( PyExc_AttributeError, "SpaceType \"%s\" does not have a UI region '%s'", space_identifier, region_identifier);
- return NULL;
- }
-
- idname= _PyUnicode_AsString(pypnl_class_attrs[PYPANEL_ATTR_IDNAME_IDX]);
-
- for(pt=art->paneltypes.first; pt; pt=pt->next)
- if(strcmp(pt->idname, idname) == 0)
- break;
-
- if(!pt) {
- pt= MEM_callocN(sizeof(PanelType), "python buttons panel");
- pt->srna= RNA_def_struct(&BLENDER_RNA, pt->idname, "Panel");
- BLI_addtail(&art->paneltypes, pt);
- }
-
- pt->idname= idname;
-
- item= pypnl_class_attrs[PYPANEL_ATTR_UINAME_IDX];
- pt->name= item? _PyUnicode_AsString(item): pt->idname;
- pt->context= _PyUnicode_AsString(pypnl_class_attrs[PYPANEL_ATTR_CONTEXT_IDX]);
-
- if (pypnl_class_attrs[PYPANEL_ATTR_POLL_IDX])
- pt->poll= PyPanel_poll;
- else
- pt->poll= NULL;
-
- pt->draw= PyPanel_draw;
-
- Py_INCREF(py_class);
- pt->py_data= (void *)py_class;
- RNA_struct_py_type_set(pt->srna, py_class);
-
- item= PyDict_GetItemString(PyEval_GetGlobals(), "__bpy_context__");
- if(item && (C=(bContext *)PyCObject_AsVoidPtr(item)))
- WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
-
- Py_RETURN_NONE;
-}
-
-PyObject *PyPanel_wrap_remove(PyObject *self, PyObject *args)
-{
- // XXX - todo
- Py_RETURN_NONE;
-}
-
diff --git a/source/blender/python/intern/bpy_panel_wrap.h b/source/blender/python/intern/bpy_panel_wrap.h
deleted file mode 100644
index 42b24703d00..00000000000
--- a/source/blender/python/intern/bpy_panel_wrap.h
+++ /dev/null
@@ -1,36 +0,0 @@
-
-/**
- * $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_PANEL_WRAP_H
-#define BPY_PANEL_WRAP_H
-
-#include <Python.h>
-
-/* these are used for operator methods, used by bpy_operator.c */
-
-PyObject *PyPanel_wrap_add(PyObject *self, PyObject *args);
-PyObject *PyPanel_wrap_remove(PyObject *self, PyObject *args);
-
-#endif
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 87ce11b76d9..627b240c65d 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -28,13 +28,16 @@
//#include "blendef.h"
#include "BLI_dynstr.h"
#include "BLI_listbase.h"
+#include "BLI_string.h"
#include "float.h" /* FLT_MIN/MAX */
+#include "RNA_access.h"
#include "RNA_define.h" /* for defining our own rna */
#include "MEM_guardedalloc.h"
#include "BKE_context.h"
#include "BKE_global.h" /* evil G.* */
+#include "BKE_report.h"
static int pyrna_struct_compare( BPy_StructRNA * a, BPy_StructRNA * b )
{
@@ -74,13 +77,13 @@ static PyObject *pyrna_struct_repr( BPy_StructRNA * self )
char str[512];
/* print name if available */
- prop= RNA_struct_name_property(&self->ptr);
+ prop= RNA_struct_name_property(self->ptr.type);
if(prop) {
RNA_property_string_get(&self->ptr, prop, str);
- return PyUnicode_FromFormat( "[BPy_StructRNA \"%s\" -> \"%s\"]", RNA_struct_identifier(&self->ptr), str);
+ return PyUnicode_FromFormat( "[BPy_StructRNA \"%s\" -> \"%s\"]", RNA_struct_identifier(self->ptr.type), str);
}
- return PyUnicode_FromFormat( "[BPy_StructRNA \"%s\"]", RNA_struct_identifier(&self->ptr));
+ return PyUnicode_FromFormat( "[BPy_StructRNA \"%s\"]", RNA_struct_identifier(self->ptr.type));
}
static PyObject *pyrna_prop_repr( BPy_PropertyRNA * self )
@@ -90,19 +93,19 @@ static PyObject *pyrna_prop_repr( BPy_PropertyRNA * self )
char str[512];
/* if a pointer, try to print name of pointer target too */
- if(RNA_property_type(&self->ptr, self->prop) == PROP_POINTER) {
+ if(RNA_property_type(self->prop) == PROP_POINTER) {
ptr= RNA_property_pointer_get(&self->ptr, self->prop);
if(ptr.data) {
- prop= RNA_struct_name_property(&ptr);
+ prop= RNA_struct_name_property(ptr.type);
if(prop) {
RNA_property_string_get(&ptr, prop, str);
- return PyUnicode_FromFormat( "[BPy_PropertyRNA \"%s\" -> \"%s\" -> \"%s\" ]", RNA_struct_identifier(&self->ptr), RNA_property_identifier(&self->ptr, self->prop), str);
+ return PyUnicode_FromFormat( "[BPy_PropertyRNA \"%s\" -> \"%s\" -> \"%s\" ]", RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop), str);
}
}
}
- return PyUnicode_FromFormat( "[BPy_PropertyRNA \"%s\" -> \"%s\"]", RNA_struct_identifier(&self->ptr), RNA_property_identifier(&self->ptr, self->prop));
+ return PyUnicode_FromFormat( "[BPy_PropertyRNA \"%s\" -> \"%s\"]", RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop));
}
static long pyrna_struct_hash( BPy_StructRNA * self )
@@ -136,8 +139,8 @@ static char *pyrna_enum_as_string(PointerRNA *ptr, PropertyRNA *prop)
PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop)
{
PyObject *ret;
- int type = RNA_property_type(ptr, prop);
- int len = RNA_property_array_length(ptr, prop);
+ int type = RNA_property_type(prop);
+ int len = RNA_property_array_length(prop);
if (len > 0) {
/* resolve the array from a new pytype */
@@ -221,8 +224,8 @@ PyObject *pyrna_func_to_py(PointerRNA *ptr, FunctionRNA *func)
int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *value)
{
/* XXX hard limits should be checked here */
- int type = RNA_property_type(ptr, prop);
- int len = RNA_property_array_length(ptr, prop);
+ int type = RNA_property_type(prop);
+ int len = RNA_property_array_length(prop);
if (len > 0) {
PyObject *item;
@@ -402,12 +405,12 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
}
case PROP_POINTER:
{
- StructRNA *ptype= RNA_property_pointer_type(ptr, prop);
+ StructRNA *ptype= RNA_property_pointer_type(prop);
if(!BPy_StructRNA_Check(value)) {
PointerRNA tmp;
RNA_pointer_create(NULL, ptype, NULL, &tmp);
- PyErr_Format(PyExc_TypeError, "expected a %s type", RNA_struct_identifier(&tmp));
+ PyErr_Format(PyExc_TypeError, "expected a %s type", RNA_struct_identifier(tmp.type));
return -1;
} else {
BPy_StructRNA *param= (BPy_StructRNA*)value;
@@ -416,7 +419,7 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
if(ptype == &RNA_AnyType) {
*((PointerRNA*)data)= param->ptr;
}
- else if(RNA_struct_is_a(&param->ptr, ptype)) {
+ else if(RNA_struct_is_a(param->ptr.type, ptype)) {
*((void**)data)= param->ptr.data;
} else {
raise_error= 1;
@@ -424,12 +427,12 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
}
else {
/* data==NULL, assign to RNA */
- if(RNA_struct_is_a(&param->ptr, ptype)) {
+ if(RNA_struct_is_a(param->ptr.type, ptype)) {
RNA_property_pointer_set(ptr, prop, param->ptr);
} else {
PointerRNA tmp;
RNA_pointer_create(NULL, ptype, NULL, &tmp);
- PyErr_Format(PyExc_TypeError, "expected a %s type", RNA_struct_identifier(&tmp));
+ PyErr_Format(PyExc_TypeError, "expected a %s type", RNA_struct_identifier(tmp.type));
return -1;
}
}
@@ -437,7 +440,7 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
if(raise_error) {
PointerRNA tmp;
RNA_pointer_create(NULL, ptype, NULL, &tmp);
- PyErr_Format(PyExc_TypeError, "expected a %s type", RNA_struct_identifier(&tmp));
+ PyErr_Format(PyExc_TypeError, "expected a %s type", RNA_struct_identifier(tmp.type));
return -1;
}
}
@@ -460,7 +463,7 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
static PyObject * pyrna_prop_to_py_index(PointerRNA *ptr, PropertyRNA *prop, int index)
{
PyObject *ret;
- int type = RNA_property_type(ptr, prop);
+ int type = RNA_property_type(prop);
/* see if we can coorce into a python type - PropertyType */
switch (type) {
@@ -485,7 +488,7 @@ static PyObject * pyrna_prop_to_py_index(PointerRNA *ptr, PropertyRNA *prop, int
static int pyrna_py_to_prop_index(PointerRNA *ptr, PropertyRNA *prop, int index, PyObject *value)
{
int ret = 0;
- int type = RNA_property_type(ptr, prop);
+ int type = RNA_property_type(prop);
/* see if we can coorce into a python type - PropertyType */
switch (type) {
@@ -537,10 +540,10 @@ static Py_ssize_t pyrna_prop_len( BPy_PropertyRNA * self )
{
Py_ssize_t len;
- if (RNA_property_type(&self->ptr, self->prop) == PROP_COLLECTION) {
+ if (RNA_property_type(self->prop) == PROP_COLLECTION) {
len = RNA_property_collection_length(&self->ptr, self->prop);
} else {
- len = RNA_property_array_length(&self->ptr, self->prop);
+ len = RNA_property_array_length(self->prop);
if (len==0) { /* not an array*/
PyErr_SetString(PyExc_AttributeError, "len() only available for collection RNA types");
@@ -567,7 +570,7 @@ static PyObject *pyrna_prop_subscript( BPy_PropertyRNA * self, PyObject *key )
return NULL;
}
- if (RNA_property_type(&self->ptr, self->prop) == PROP_COLLECTION) {
+ if (RNA_property_type(self->prop) == PROP_COLLECTION) {
int ok;
if (keyname) ok = RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr);
else ok = RNA_property_collection_lookup_int(&self->ptr, self->prop, keynum, &newptr);
@@ -583,7 +586,7 @@ static PyObject *pyrna_prop_subscript( BPy_PropertyRNA * self, PyObject *key )
PyErr_SetString(PyExc_AttributeError, "string keys are only supported for collections");
ret = NULL;
} else {
- int len = RNA_property_array_length(&self->ptr, self->prop);
+ int len = RNA_property_array_length(self->prop);
if (len==0) { /* not an array*/
PyErr_Format(PyExc_AttributeError, "not an array or collection %d", keynum);
@@ -609,7 +612,7 @@ static int pyrna_prop_assign_subscript( BPy_PropertyRNA * self, PyObject *key, P
char *keyname = NULL;
if (!RNA_property_editable(&self->ptr, self->prop)) {
- PyErr_Format( PyExc_AttributeError, "PropertyRNA - attribute \"%s\" from \"%s\" is read-only", RNA_property_identifier(&self->ptr, self->prop), RNA_struct_identifier(&self->ptr) );
+ PyErr_Format( PyExc_AttributeError, "PropertyRNA - attribute \"%s\" from \"%s\" is read-only", RNA_property_identifier(self->prop), RNA_struct_identifier(self->ptr.type) );
return -1;
}
@@ -622,14 +625,14 @@ static int pyrna_prop_assign_subscript( BPy_PropertyRNA * self, PyObject *key, P
return -1;
}
- if (RNA_property_type(&self->ptr, self->prop) == PROP_COLLECTION) {
+ if (RNA_property_type(self->prop) == PROP_COLLECTION) {
PyErr_SetString(PyExc_AttributeError, "PropertyRNA - assignment is not supported for collections (yet)");
ret = -1;
} else if (keyname) {
PyErr_SetString(PyExc_AttributeError, "PropertyRNA - string keys are only supported for collections");
ret = -1;
} else {
- int len = RNA_property_array_length(&self->ptr, self->prop);
+ int len = RNA_property_array_length(self->prop);
if (len==0) { /* not an array*/
PyErr_Format(PyExc_AttributeError, "PropertyRNA - not an array or collection %d", keynum);
@@ -693,11 +696,11 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA * self)
PropertyRNA *nameprop;
char name[256], *nameptr;
- iterprop= RNA_struct_iterator_property(&self->ptr);
+ iterprop= RNA_struct_iterator_property(self->ptr.type);
RNA_property_collection_begin(&self->ptr, iterprop, &iter);
for(; iter.valid; RNA_property_collection_next(&iter)) {
- if(iter.ptr.data && (nameprop = RNA_struct_name_property(&iter.ptr))) {
+ if(iter.ptr.data && (nameprop = RNA_struct_name_property(iter.ptr.type))) {
nameptr= RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name));
pystring = PyUnicode_FromString(nameptr);
@@ -725,7 +728,7 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA * self)
RNA_property_collection_begin(&tptr, iterprop, &iter);
for(; iter.valid; RNA_property_collection_next(&iter)) {
- pystring = PyUnicode_FromString(RNA_function_identifier(&tptr, iter.ptr.data));
+ pystring = PyUnicode_FromString(RNA_function_identifier(iter.ptr.data));
PyList_Append(ret, pystring);
Py_DECREF(pystring);
}
@@ -814,7 +817,7 @@ static int pyrna_struct_setattro( BPy_StructRNA * self, PyObject *pyname, PyObje
}
if (!RNA_property_editable(&self->ptr, prop)) {
- PyErr_Format( PyExc_AttributeError, "StructRNA - Attribute \"%s\" from \"%s\" is read-only", RNA_property_identifier(&self->ptr, prop), RNA_struct_identifier(&self->ptr) );
+ PyErr_Format( PyExc_AttributeError, "StructRNA - Attribute \"%s\" from \"%s\" is read-only", RNA_property_identifier(prop), RNA_struct_identifier(self->ptr.type) );
return -1;
}
@@ -825,7 +828,7 @@ static int pyrna_struct_setattro( BPy_StructRNA * self, PyObject *pyname, PyObje
PyObject *pyrna_prop_keys(BPy_PropertyRNA *self)
{
PyObject *ret;
- if (RNA_property_type(&self->ptr, self->prop) != PROP_COLLECTION) {
+ if (RNA_property_type(self->prop) != PROP_COLLECTION) {
PyErr_SetString( PyExc_TypeError, "keys() is only valid for collection types" );
ret = NULL;
} else {
@@ -838,7 +841,7 @@ PyObject *pyrna_prop_keys(BPy_PropertyRNA *self)
RNA_property_collection_begin(&self->ptr, self->prop, &iter);
for(; iter.valid; RNA_property_collection_next(&iter)) {
- if(iter.ptr.data && (nameprop = RNA_struct_name_property(&iter.ptr))) {
+ if(iter.ptr.data && (nameprop = RNA_struct_name_property(iter.ptr.type))) {
nameptr= RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name));
/* add to python list */
@@ -860,7 +863,7 @@ PyObject *pyrna_prop_keys(BPy_PropertyRNA *self)
PyObject *pyrna_prop_items(BPy_PropertyRNA *self)
{
PyObject *ret;
- if (RNA_property_type(&self->ptr, self->prop) != PROP_COLLECTION) {
+ if (RNA_property_type(self->prop) != PROP_COLLECTION) {
PyErr_SetString( PyExc_TypeError, "items() is only valid for collection types" );
ret = NULL;
} else {
@@ -873,7 +876,7 @@ PyObject *pyrna_prop_items(BPy_PropertyRNA *self)
RNA_property_collection_begin(&self->ptr, self->prop, &iter);
for(; iter.valid; RNA_property_collection_next(&iter)) {
- if(iter.ptr.data && (nameprop = RNA_struct_name_property(&iter.ptr))) {
+ if(iter.ptr.data && (nameprop = RNA_struct_name_property(iter.ptr.type))) {
nameptr= RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name));
/* add to python list */
@@ -896,7 +899,7 @@ PyObject *pyrna_prop_items(BPy_PropertyRNA *self)
PyObject *pyrna_prop_values(BPy_PropertyRNA *self)
{
PyObject *ret;
- if (RNA_property_type(&self->ptr, self->prop) != PROP_COLLECTION) {
+ if (RNA_property_type(self->prop) != PROP_COLLECTION) {
PyErr_SetString( PyExc_TypeError, "values() is only valid for collection types" );
ret = NULL;
} else {
@@ -908,7 +911,7 @@ PyObject *pyrna_prop_values(BPy_PropertyRNA *self)
RNA_property_collection_begin(&self->ptr, self->prop, &iter);
for(; iter.valid; RNA_property_collection_next(&iter)) {
- if(iter.ptr.data && (nameprop = RNA_struct_name_property(&iter.ptr))) {
+ if(iter.ptr.data && (nameprop = RNA_struct_name_property(iter.ptr.type))) {
item = pyrna_struct_CreatePyObject(&iter.ptr);
PyList_Append(ret, item);
Py_DECREF(item);
@@ -929,7 +932,7 @@ PyObject *pyrna_prop_iter(BPy_PropertyRNA *self)
if (ret==NULL) {
/* collection did not work, try array */
- int len = RNA_property_array_length(&self->ptr, self->prop);
+ int len = RNA_property_array_length(self->prop);
if (len) {
int i;
@@ -1005,8 +1008,8 @@ static PyObject * pyrna_prop_new(PyTypeObject *type, PyObject *args, PyObject *k
PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data)
{
PyObject *ret;
- int type = RNA_property_type(ptr, prop);
- int len = RNA_property_array_length(ptr, prop);
+ int type = RNA_property_type(prop);
+ int len = RNA_property_array_length(prop);
int a;
if(len > 0) {
@@ -1066,7 +1069,7 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data)
case PROP_POINTER:
{
PointerRNA newptr;
- StructRNA *type= RNA_property_pointer_type(ptr, prop);
+ StructRNA *type= RNA_property_pointer_type(prop);
if(type == &RNA_AnyType) {
/* in this case we get the full ptr */
@@ -1116,7 +1119,7 @@ static PyObject * pyrna_func_call(PyObject * self, PyObject *args, PyObject *kw)
/* setup */
RNA_pointer_create(NULL, &RNA_Function, self_func, &funcptr);
- pret= RNA_function_return(self_ptr, self_func);
+ pret= RNA_function_return(self_func);
tlen= PyTuple_GET_SIZE(args);
parms= RNA_parameter_list_create(self_ptr, self_func);
@@ -1131,8 +1134,8 @@ static PyObject * pyrna_func_call(PyObject * self, PyObject *args, PyObject *kw)
continue;
}
- pid= RNA_property_identifier(&funcptr, parm);
- flag= RNA_property_flag(&funcptr, parm);
+ pid= RNA_property_identifier(parm);
+ flag= RNA_property_flag(parm);
item= NULL;
if ((i < tlen) && (flag & PROP_REQUIRED)) {
@@ -1144,8 +1147,8 @@ static PyObject * pyrna_func_call(PyObject * self, PyObject *args, PyObject *kw)
if (item==NULL) {
if(flag & PROP_REQUIRED) {
- tid= RNA_struct_identifier(self_ptr);
- fid= RNA_function_identifier(self_ptr, self_func);
+ tid= RNA_struct_identifier(self_ptr->type);
+ fid= RNA_function_identifier(self_func);
PyErr_Format(PyExc_AttributeError, "%s.%s(): required parameter \"%s\" not specified", tid, fid, pid);
err= -1;
@@ -1355,6 +1358,21 @@ PyTypeObject pyrna_prop_Type = {
NULL
};
+static void pyrna_subtype_set_rna(PyObject *newclass, StructRNA *srna)
+{
+ PointerRNA ptr;
+ PyObject *item;
+
+ RNA_struct_py_type_set(srna, (void *)newclass); /* Store for later use */
+
+ /* Not 100% needed but useful,
+ * having an instance within a type looks wrong however this instance IS an rna type */
+ RNA_pointer_create(NULL, &RNA_Struct, srna, &ptr);
+ item = pyrna_struct_CreatePyObject(&ptr);
+ PyDict_SetItemString(((PyTypeObject *)newclass)->tp_dict, "__rna__", item);
+ Py_DECREF(item);
+ /* done with rna instance */
+}
PyObject* pyrna_struct_Subtype(PointerRNA *ptr)
{
@@ -1365,7 +1383,7 @@ PyObject* pyrna_struct_Subtype(PointerRNA *ptr)
newclass= NULL; /* Nothing to do */
} else if ((newclass= RNA_struct_py_type_get(ptr->data))) {
Py_INCREF(newclass);
- } else if ((nameprop = RNA_struct_name_property(ptr))) {
+ } else if ((nameprop = RNA_struct_name_property(ptr->type))) {
/* for now, return the base RNA type rather then a real module */
/* Assume RNA_struct_py_type_get(ptr->data) was alredy checked */
@@ -1376,7 +1394,7 @@ PyObject* pyrna_struct_Subtype(PointerRNA *ptr)
- myClass = type(name='myClass', bases=(myBase,), dict={'some':'value'})
*/
char name[256], *nameptr;
- const char *descr= RNA_struct_ui_description(ptr);
+ const char *descr= RNA_struct_ui_description(ptr->type);
PyObject *args = PyTuple_New(3);
PyObject *bases = PyTuple_New(1);
@@ -1413,16 +1431,8 @@ PyObject* pyrna_struct_Subtype(PointerRNA *ptr)
newclass = PyObject_CallObject((PyObject *)&PyType_Type, args);
Py_DECREF(args);
- if (newclass) {
- RNA_struct_py_type_set(ptr->data, (void *)newclass); /* Store for later use */
-
- /* Not 100% needed but useful,
- * having an instance within a type looks wrong however this instance IS an rna type */
- item = pyrna_struct_CreatePyObject(ptr);
- PyDict_SetItemString(((PyTypeObject *)newclass)->tp_dict, "__rna__", item);
- Py_DECREF(item);
- /* done with rna instance */
- }
+ if (newclass)
+ pyrna_subtype_set_rna(newclass, ptr->data);
if (name != nameptr)
MEM_freeN(nameptr);
@@ -1545,6 +1555,8 @@ static PyObject *pyrna_basetype_getattro( BPy_BaseTypeRNA * self, PyObject *pyna
static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self);
static struct PyMethodDef pyrna_basetype_methods[] = {
{"__dir__", (PyCFunction)pyrna_basetype_dir, METH_NOARGS, ""},
+ {"register", (PyCFunction)pyrna_basetype_register, METH_VARARGS, ""},
+ {"unregister", (PyCFunction)pyrna_basetype_unregister, METH_VARARGS, ""},
{NULL, NULL, 0, NULL}
};
@@ -1676,3 +1688,356 @@ PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw)
return ret;
}
}
+
+/*-------------------- Type Registration ------------------------*/
+
+static int rna_function_arg_count(FunctionRNA *func)
+{
+ const ListBase *lb= RNA_function_defined_parameters(func);
+ PropertyRNA *parm;
+ Link *link;
+ int count= 1;
+
+ for(link=lb->first; link; link=link->next) {
+ parm= (PropertyRNA*)link;
+ if(!(RNA_property_flag(parm) & PROP_RETURN))
+ count++;
+ }
+
+ return count;
+}
+
+static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_function)
+{
+ const ListBase *lb;
+ Link *link;
+ FunctionRNA *func;
+ PropertyRNA *prop;
+ StructRNA *srna= dummyptr->type;
+ const char *class_type= RNA_struct_identifier(srna);
+ PyObject *py_class= (PyObject*)py_data;
+ PyObject *base_class= RNA_struct_py_type_get(srna);
+ PyObject *item, *fitem;
+ PyObject *py_arg_count;
+ int i, flag, arg_count, func_arg_count;
+ char identifier[128];
+
+ if (base_class) {
+ if (!PyObject_IsSubclass(py_class, base_class)) {
+ PyObject *name= PyObject_GetAttrString(base_class, "__name__");
+ PyErr_Format( PyExc_AttributeError, "expected %s subclass of class \"%s\"", class_type, name ? _PyUnicode_AsString(name):"<UNKNOWN>");
+ Py_XDECREF(name);
+ return -1;
+ }
+ }
+
+ /* verify callback functions */
+ lb= RNA_struct_defined_functions(srna);
+ i= 0;
+ for(link=lb->first; link; link=link->next) {
+ func= (FunctionRNA*)link;
+ flag= RNA_function_flag(func);
+
+ if(!(flag & FUNC_REGISTER))
+ continue;
+
+ item = PyObject_GetAttrString(py_class, RNA_function_identifier(func));
+
+ have_function[i]= (item != NULL);
+ i++;
+
+ if (item==NULL) {
+ if ((flag & FUNC_REGISTER_OPTIONAL)==0) {
+ PyErr_Format( PyExc_AttributeError, "expected %s class to have an \"%s\" attribute", class_type, RNA_function_identifier(func));
+ return -1;
+ }
+
+ PyErr_Clear();
+ }
+ else {
+ Py_DECREF(item); /* no need to keep a ref, the class owns it */
+
+ if (PyMethod_Check(item))
+ fitem= PyMethod_Function(item); /* py 2.x */
+ else
+ fitem= item; /* py 3.x */
+
+ if (PyFunction_Check(fitem)==0) {
+ PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute to be a function", class_type, RNA_function_identifier(func));
+ return -1;
+ }
+
+ func_arg_count= rna_function_arg_count(func);
+
+ if (func_arg_count >= 0) { /* -1 if we dont care*/
+ py_arg_count = PyObject_GetAttrString(PyFunction_GET_CODE(fitem), "co_argcount");
+ arg_count = PyLong_AsSsize_t(py_arg_count);
+ Py_DECREF(py_arg_count);
+
+ if (arg_count != func_arg_count) {
+ PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" function to have %d args", class_type, RNA_function_identifier(func), func_arg_count);
+ return -1;
+ }
+ }
+ }
+ }
+
+ /* verify properties */
+ lb= RNA_struct_defined_properties(srna);
+ for(link=lb->first; link; link=link->next) {
+ prop= (PropertyRNA*)link;
+ flag= RNA_property_flag(prop);
+
+ if(!(flag & PROP_REGISTER))
+ continue;
+
+ BLI_snprintf(identifier, sizeof(identifier), "__%s__", RNA_property_identifier(prop));
+ item = PyObject_GetAttrString(py_class, identifier);
+
+ if (item==NULL) {
+ if(strcmp(identifier, "__idname__") == 0) {
+ item= PyObject_GetAttrString(py_class, "__name__");
+
+ if(item) {
+ Py_DECREF(item); /* no need to keep a ref, the class owns it */
+
+ if(pyrna_py_to_prop(dummyptr, prop, NULL, item) != 0)
+ return -1;
+ }
+ }
+
+ if (item==NULL && (flag & PROP_REGISTER_OPTIONAL)==0) {
+ PyErr_Format( PyExc_AttributeError, "expected %s class to have an \"%s\" attribute", class_type, identifier);
+ return -1;
+ }
+
+ PyErr_Clear();
+ }
+ else {
+ Py_DECREF(item); /* no need to keep a ref, the class owns it */
+
+ if(pyrna_py_to_prop(dummyptr, prop, NULL, item) != 0)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+extern void BPY_update_modules( void ); //XXX temp solution
+
+static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *parms)
+{
+ PyObject *args;
+ PyObject *ret= NULL, *py_class, *py_class_instance, *item, *parmitem;
+ PropertyRNA *pret= NULL, *parm;
+ ParameterIterator iter;
+ PointerRNA funcptr;
+ void *retdata= NULL;
+ int err= 0, i, flag;
+
+ PyGILState_STATE gilstate = PyGILState_Ensure();
+
+ BPY_update_modules(); // XXX - the RNA pointers can change so update before running, would like a nicer solution for this.
+
+ py_class= RNA_struct_py_type_get(ptr->type);
+
+ args = PyTuple_New(1);
+ PyTuple_SET_ITEM(args, 0, pyrna_struct_CreatePyObject(ptr));
+ py_class_instance = PyObject_Call(py_class, args, NULL);
+ Py_DECREF(args);
+
+ if (py_class_instance) { /* Initializing the class worked, now run its invoke function */
+ item= PyObject_GetAttrString(py_class, RNA_function_identifier(func));
+ flag= RNA_function_flag(func);
+
+ if(item) {
+ pret= RNA_function_return(func);
+ RNA_pointer_create(NULL, &RNA_Function, func, &funcptr);
+
+ args = PyTuple_New(rna_function_arg_count(func));
+ PyTuple_SET_ITEM(args, 0, py_class_instance);
+
+ RNA_parameter_list_begin(parms, &iter);
+
+ /* parse function parameters */
+ for (i= 1; iter.valid; RNA_parameter_list_next(&iter)) {
+ parm= iter.parm;
+
+ if (parm==pret) {
+ retdata= iter.data;
+ continue;
+ }
+
+ parmitem= pyrna_param_to_py(&funcptr, parm, iter.data);
+ PyTuple_SET_ITEM(args, i, parmitem);
+ i++;
+ }
+
+ ret = PyObject_Call(item, args, NULL);
+
+ /* args is decref'd from item */
+ Py_DECREF(item);
+ }
+ else {
+ Py_DECREF(py_class_instance);
+ PyErr_Format(PyExc_AttributeError, "could not find function %s in %s to execute callback.", RNA_function_identifier(func), RNA_struct_identifier(ptr->type));
+ err= -1;
+ }
+ }
+ else {
+ PyErr_Format(PyExc_AttributeError, "could not create instance of %s to call callback function %s.", RNA_struct_identifier(ptr->type), RNA_function_identifier(func));
+ err= -1;
+ }
+
+ if (ret == NULL) { /* covers py_class_instance failing too */
+ PyErr_Print(); /* XXX use reporting api? */
+ err= -1;
+ }
+ else {
+ if(retdata)
+ err= pyrna_py_to_prop(&funcptr, pret, retdata, ret);
+ Py_DECREF(ret);
+ }
+
+ PyGILState_Release(gilstate);
+
+ return err;
+}
+
+static void bpy_class_free(void *pyob_ptr)
+{
+ Py_DECREF((PyObject *)pyob_ptr);
+}
+
+PyObject *pyrna_basetype_register(PyObject *self, PyObject *args)
+{
+ bContext *C= NULL;
+ PyObject *py_class, *item;
+ ReportList reports;
+ StructRegisterFunc reg;
+ BPy_StructRNA *py_srna;
+ StructRNA *srna;
+
+ if(!PyArg_ParseTuple(args, "O:register", &py_class))
+ return NULL;
+
+ if(!PyType_Check(py_class)) {
+ PyErr_SetString(PyExc_AttributeError, "expected a Type subclassed from a registerable rna type (no a Type object).");
+ return NULL;
+ }
+
+ /* check we got an __rna__ attribute */
+ item= PyObject_GetAttrString(py_class, "__rna__");
+
+ if(!item || !BPy_StructRNA_Check(item)) {
+ if(item) {
+ Py_DECREF(item);
+ }
+ PyErr_SetString(PyExc_AttributeError, "expected a Type subclassed from a registerable rna type (no __rna__ property).");
+ return NULL;
+ }
+
+ /* check the __rna__ attribute has the right type */
+ Py_DECREF(item);
+ py_srna= (BPy_StructRNA*)item;
+
+ if(py_srna->ptr.type != &RNA_Struct) {
+ PyErr_SetString(PyExc_AttributeError, "expected a Type subclassed from a registerable rna type (not a Struct).");
+ return NULL;
+ }
+
+ /* check that we have a register callback for this type */
+ reg= RNA_struct_register(py_srna->ptr.data);
+
+ if(!reg) {
+ PyErr_SetString(PyExc_AttributeError, "expected a Type subclassed from a registerable rna type (no register supported).");
+ return NULL;
+ }
+
+ /* get the context, so register callback can do necessary refreshes */
+ item= PyDict_GetItemString(PyEval_GetGlobals(), "__bpy_context__");
+
+ if(item) {
+ C= (bContext*)PyCObject_AsVoidPtr(item);
+ Py_DECREF(item);
+ }
+
+ /* call the register callback */
+ BKE_reports_init(&reports, RPT_PRINT);
+ srna= reg(C, &reports, py_class, bpy_class_validate, bpy_class_call, bpy_class_free);
+
+ if(!srna) {
+ BPy_reports_to_error(&reports);
+ BKE_reports_clear(&reports);
+ return NULL;
+ }
+
+ BKE_reports_clear(&reports);
+
+ pyrna_subtype_set_rna(py_class, srna);
+ Py_INCREF(py_class);
+
+ Py_RETURN_NONE;
+}
+
+PyObject *pyrna_basetype_unregister(PyObject *self, PyObject *args)
+{
+ bContext *C= NULL;
+ PyObject *py_class, *item;
+ BPy_StructRNA *py_srna;
+ StructUnregisterFunc unreg;
+
+ if(!PyArg_ParseTuple(args, "O:register", &py_class))
+ return NULL;
+
+ if(!PyType_Check(py_class)) {
+ PyErr_SetString(PyExc_AttributeError, "expected a Type subclassed from a registerable rna type (no a Type object).");
+ return NULL;
+ }
+
+ /* check we got an __rna__ attribute */
+ item= PyDict_GetItemString(((PyTypeObject*)py_class)->tp_dict, "__rna__");
+
+ if(!item || !BPy_StructRNA_Check(item)) {
+ if(item) {
+ Py_DECREF(item);
+ }
+ PyErr_SetString(PyExc_AttributeError, "expected a Type subclassed from a registerable rna type (no __rna__ property).");
+ return NULL;
+ }
+
+ /* check the __rna__ attribute has the right type */
+ Py_DECREF(item);
+ py_srna= (BPy_StructRNA*)item;
+
+ if(py_srna->ptr.type != &RNA_Struct) {
+ PyErr_SetString(PyExc_AttributeError, "expected a Type subclassed from a registerable rna type (not a Struct).");
+ return NULL;
+ }
+
+ /* check that we have a unregister callback for this type */
+ unreg= RNA_struct_unregister(py_srna->ptr.data);
+
+ if(!unreg) {
+ PyErr_SetString(PyExc_AttributeError, "expected a Type subclassed from a registerable rna type (no unregister supported).");
+ return NULL;
+ }
+
+ /* get the context, so register callback can do necessary refreshes */
+ item= PyDict_GetItemString(PyEval_GetGlobals(), "__bpy_context__");
+
+ if(item) {
+ C= (bContext*)PyCObject_AsVoidPtr(item);
+ Py_DECREF(item);
+ }
+
+ /* call unregister */
+ unreg(C, py_srna->ptr.data);
+
+ /* remove reference to old type */
+ Py_DECREF(py_class);
+
+ Py_RETURN_NONE;
+}
+
diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h
index 5ddaf991a51..a97d450fb2f 100644
--- a/source/blender/python/intern/bpy_rna.h
+++ b/source/blender/python/intern/bpy_rna.h
@@ -76,5 +76,8 @@ PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_BoolProperty(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);
#endif
diff --git a/source/blender/python/intern/bpy_ui.c b/source/blender/python/intern/bpy_ui.c
index b53cc523f05..e7143e8f84c 100644
--- a/source/blender/python/intern/bpy_ui.c
+++ b/source/blender/python/intern/bpy_ui.c
@@ -27,7 +27,6 @@
#include "bpy_rna.h" /* for rna buttons */
#include "bpy_operator.h" /* for setting button operator properties */
#include "bpy_compat.h"
-#include "bpy_panel_wrap.h" /* for setting button operator properties */
#include "WM_types.h" /* for WM_OP_INVOKE_DEFAULT & friends */
@@ -431,9 +430,6 @@ static struct PyMethodDef ui_methods[] = {
{"getSpacePtr", (PyCFunction)Method_getSpacePtr, METH_NOARGS, ""},
{"getWindowPtr", (PyCFunction)Method_getWindowPtr, METH_NOARGS, ""},
- /* Adding panels should be moved, at the moment there is no obvious place as there is with operators */
- {"addPanel", (PyCFunction)PyPanel_wrap_add, METH_VARARGS, ""},
- {"removePanel", (PyCFunction)PyPanel_wrap_remove, METH_VARARGS, ""},
{NULL, NULL, 0, NULL}
};
diff --git a/source/blender/python/intern/bpy_util.c b/source/blender/python/intern/bpy_util.c
index 0623124009c..66cf244e3bd 100644
--- a/source/blender/python/intern/bpy_util.c
+++ b/source/blender/python/intern/bpy_util.c
@@ -22,10 +22,12 @@
* ***** END GPL LICENSE BLOCK *****
*/
-
+#include "DNA_listBase.h"
+#include "RNA_access.h"
#include "bpy_util.h"
#include "BLI_dynstr.h"
#include "MEM_guardedalloc.h"
+#include "BKE_report.h"
PyObject *BPY_flag_to_list(struct BPY_flag_def *flagdef, int flag)
{
@@ -241,7 +243,6 @@ PyObject *PyObject_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...)
return item;
}
-
int BPY_class_validate(const char *class_type, PyObject *class, PyObject *base_class, BPY_class_attr_check* class_attrs, PyObject **py_class_attrs)
{
PyObject *item, *fitem;
@@ -333,3 +334,18 @@ char *BPy_enum_as_string(EnumPropertyItem *item)
BLI_dynstr_free(dynstr);
return cstring;
}
+
+int BPy_reports_to_error(ReportList *reports)
+{
+ char *report_str;
+
+ report_str= BKE_reports_string(reports, RPT_ERROR);
+
+ if(report_str) {
+ PyErr_SetString(PyExc_SystemError, report_str);
+ MEM_freeN(report_str);
+ }
+
+ return (report_str != NULL);
+}
+
diff --git a/source/blender/python/intern/bpy_util.h b/source/blender/python/intern/bpy_util.h
index 9ce7a17b9e3..db31f403714 100644
--- a/source/blender/python/intern/bpy_util.h
+++ b/source/blender/python/intern/bpy_util.h
@@ -31,6 +31,7 @@
#include "RNA_types.h" /* for EnumPropertyItem only */
struct EnumPropertyItem;
+struct ReportList;
/* for internal use only, so python can interchange a sequence of strings with flags */
typedef struct BPY_flag_def {
@@ -70,4 +71,7 @@ char *BPy_enum_as_string(struct EnumPropertyItem *item);
#define BLANK_PYTHON_TYPE {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
+/* error reporting */
+int BPy_reports_to_error(struct ReportList *reports);
+
#endif