merged changes to revision 24271
This commit is contained in:
@@ -63,6 +63,7 @@
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_text.h"
|
||||
#include "BKE_context.h"
|
||||
|
||||
#include "BPY_extern.h"
|
||||
|
||||
@@ -202,6 +203,7 @@ static void bpy_init_modules( void )
|
||||
|
||||
bpy_import_test("bpy_ops"); /* adds its self to bpy.ops */
|
||||
bpy_import_test("bpy_sys"); /* adds its self to bpy.sys */
|
||||
bpy_import_test("bpy_ext"); /* extensions to our existing types */
|
||||
}
|
||||
|
||||
/* stand alone utility modules not related to blender directly */
|
||||
@@ -950,3 +952,65 @@ int BPY_button_eval(bContext *C, char *expr, double *value)
|
||||
return error_ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int bpy_context_get(bContext *C, const char *member, bContextDataResult *result)
|
||||
{
|
||||
PyObject *pyctx= (PyObject *)CTX_py_dict_get(C);
|
||||
PyObject *item= PyDict_GetItemString(pyctx, member);
|
||||
PointerRNA *ptr= NULL;
|
||||
int done= 0;
|
||||
|
||||
if(item==NULL) {
|
||||
/* pass */
|
||||
}
|
||||
else if(item==Py_None) {
|
||||
/* pass */
|
||||
}
|
||||
else if(BPy_StructRNA_Check(item)) {
|
||||
ptr= &(((BPy_StructRNA *)item)->ptr);
|
||||
|
||||
//result->ptr= ((BPy_StructRNA *)item)->ptr;
|
||||
CTX_data_pointer_set(result, ptr->id.data, ptr->type, ptr->data);
|
||||
done= 1;
|
||||
}
|
||||
else if (PySequence_Check(item)) {
|
||||
PyObject *seq_fast= PySequence_Fast(item, "bpy_context_get sequence conversion");
|
||||
if (seq_fast==NULL) {
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
else {
|
||||
int len= PySequence_Fast_GET_SIZE(seq_fast);
|
||||
int i;
|
||||
for(i = 0; i < len; i++) {
|
||||
PyObject *list_item= PySequence_Fast_GET_ITEM(seq_fast, i);
|
||||
|
||||
if(BPy_StructRNA_Check(list_item)) {
|
||||
/*
|
||||
CollectionPointerLink *link= MEM_callocN(sizeof(CollectionPointerLink), "bpy_context_get");
|
||||
link->ptr= ((BPy_StructRNA *)item)->ptr;
|
||||
BLI_addtail(&result->list, link);
|
||||
*/
|
||||
ptr= &(((BPy_StructRNA *)list_item)->ptr);
|
||||
CTX_data_list_add(result, ptr->id.data, ptr->type, ptr->data);
|
||||
}
|
||||
else {
|
||||
printf("List item not a valid type\n");
|
||||
}
|
||||
|
||||
}
|
||||
Py_DECREF(seq_fast);
|
||||
|
||||
done= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(done==0) {
|
||||
if (item) printf("Context '%s' not found\n", member);
|
||||
else printf("Context '%s' not a valid type\n", member);
|
||||
}
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,8 @@ static PyObject *pyop_call( PyObject * self, PyObject * args)
|
||||
|
||||
char *opname;
|
||||
PyObject *kw= NULL; /* optional args */
|
||||
PyObject *context_dict= NULL; /* optional args */
|
||||
PyObject *context_dict_back;
|
||||
|
||||
/* note that context is an int, python does the conversion in this case */
|
||||
int context= WM_OP_EXEC_DEFAULT;
|
||||
@@ -55,7 +57,7 @@ static PyObject *pyop_call( PyObject * self, PyObject * args)
|
||||
// XXX Todo, work out a better solution for passing on context, could make a tuple from self and pack the name and Context into it...
|
||||
bContext *C = BPy_GetContext();
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s|O!i:bpy.__ops__.call", &opname, &PyDict_Type, &kw, &context))
|
||||
if (!PyArg_ParseTuple(args, "sO|O!i:bpy.__ops__.call", &opname, &context_dict, &PyDict_Type, &kw, &context))
|
||||
return NULL;
|
||||
|
||||
ot= WM_operatortype_find(opname, TRUE);
|
||||
@@ -65,61 +67,74 @@ static PyObject *pyop_call( PyObject * self, PyObject * args)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!PyDict_Check(context_dict))
|
||||
context_dict= NULL;
|
||||
|
||||
context_dict_back= CTX_py_dict_get(C);
|
||||
|
||||
CTX_py_dict_set(C, (void *)context_dict);
|
||||
Py_XINCREF(context_dict); /* so we done loose it */
|
||||
|
||||
if(WM_operator_poll((bContext*)C, ot) == FALSE) {
|
||||
PyErr_SetString( PyExc_SystemError, "bpy.__ops__.call: operator poll() function failed, context is incorrect");
|
||||
return NULL;
|
||||
error_val= -1;
|
||||
}
|
||||
else {
|
||||
/* WM_operator_properties_create(&ptr, opname); */
|
||||
/* Save another lookup */
|
||||
RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
|
||||
|
||||
/* WM_operator_properties_create(&ptr, opname); */
|
||||
/* Save another lookup */
|
||||
RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
|
||||
if(kw && PyDict_Size(kw))
|
||||
error_val= pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: ");
|
||||
|
||||
|
||||
if (error_val==0) {
|
||||
ReportList *reports;
|
||||
|
||||
reports= MEM_mallocN(sizeof(ReportList), "wmOperatorReportList");
|
||||
BKE_reports_init(reports, RPT_STORE);
|
||||
|
||||
WM_operator_call_py(C, ot, context, &ptr, reports);
|
||||
|
||||
if(BPy_reports_to_error(reports))
|
||||
error_val = -1;
|
||||
|
||||
/* operator output is nice to have in the terminal/console too */
|
||||
if(reports->list.first) {
|
||||
char *report_str= BKE_reports_string(reports, 0); /* all reports */
|
||||
|
||||
if(kw && PyDict_Size(kw))
|
||||
error_val= pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: ");
|
||||
|
||||
if(report_str) {
|
||||
PySys_WriteStdout("%s\n", report_str);
|
||||
MEM_freeN(report_str);
|
||||
}
|
||||
}
|
||||
|
||||
if (error_val==0) {
|
||||
ReportList *reports;
|
||||
|
||||
reports= MEM_mallocN(sizeof(ReportList), "wmOperatorReportList");
|
||||
BKE_reports_init(reports, RPT_STORE);
|
||||
|
||||
WM_operator_call_py(C, ot, context, &ptr, reports);
|
||||
|
||||
if(BPy_reports_to_error(reports))
|
||||
error_val = -1;
|
||||
|
||||
/* operator output is nice to have in the terminal/console too */
|
||||
if(reports->list.first) {
|
||||
char *report_str= BKE_reports_string(reports, 0); /* all reports */
|
||||
|
||||
if(report_str) {
|
||||
PySys_WriteStdout("%s\n", report_str);
|
||||
MEM_freeN(report_str);
|
||||
BKE_reports_clear(reports);
|
||||
if ((reports->flag & RPT_FREE) == 0)
|
||||
{
|
||||
MEM_freeN(reports);
|
||||
}
|
||||
}
|
||||
|
||||
BKE_reports_clear(reports);
|
||||
if ((reports->flag & RPT_FREE) == 0)
|
||||
{
|
||||
MEM_freeN(reports);
|
||||
}
|
||||
}
|
||||
|
||||
WM_operator_properties_free(&ptr);
|
||||
WM_operator_properties_free(&ptr);
|
||||
|
||||
#if 0
|
||||
/* if there is some way to know an operator takes args we should use this */
|
||||
{
|
||||
/* no props */
|
||||
if (kw != NULL) {
|
||||
PyErr_Format(PyExc_AttributeError, "Operator \"%s\" does not take any args", opname);
|
||||
return NULL;
|
||||
}
|
||||
/* if there is some way to know an operator takes args we should use this */
|
||||
{
|
||||
/* no props */
|
||||
if (kw != NULL) {
|
||||
PyErr_Format(PyExc_AttributeError, "Operator \"%s\" does not take any args", opname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL);
|
||||
}
|
||||
WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* restore with original context dict, probably NULL but need this for nested operator calls */
|
||||
Py_XDECREF(context_dict);
|
||||
CTX_py_dict_set(C, (void *)context_dict_back);
|
||||
|
||||
if (error_val==-1) {
|
||||
return NULL;
|
||||
|
||||
@@ -41,13 +41,12 @@
|
||||
|
||||
#include "../generic/bpy_internal_import.h" // our own imports
|
||||
|
||||
#define PYOP_ATTR_PROP "__props__"
|
||||
#define PYOP_ATTR_UINAME "__label__"
|
||||
#define PYOP_ATTR_IDNAME "__idname__" /* the name given by python */
|
||||
#define PYOP_ATTR_IDNAME_BL "__idname_bl__" /* our own name converted into blender syntax, users wont see this */
|
||||
#define PYOP_ATTR_DESCRIPTION "__doc__" /* use pythons docstring */
|
||||
#define PYOP_ATTR_REGISTER "__register__" /* True/False. if this python operator should be registered */
|
||||
#define PYOP_ATTR_UNDO "__undo__" /* True/False. if this python operator should be undone */
|
||||
#define PYOP_ATTR_UINAME "bl_label"
|
||||
#define PYOP_ATTR_IDNAME "bl_idname" /* the name given by python */
|
||||
#define PYOP_ATTR_IDNAME_BL "_bl_idname" /* our own name converted into blender syntax, users wont see this */
|
||||
#define PYOP_ATTR_DESCRIPTION "__doc__" /* use pythons docstring */
|
||||
#define PYOP_ATTR_REGISTER "bl_register" /* True/False. if this python operator should be registered */
|
||||
#define PYOP_ATTR_UNDO "bl_undo" /* True/False. if this python operator should be undone */
|
||||
|
||||
static struct BPY_flag_def pyop_ret_flags[] = {
|
||||
{"RUNNING_MODAL", OPERATOR_RUNNING_MODAL},
|
||||
@@ -91,19 +90,23 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperatorType *ot, wmOperat
|
||||
PointerRNA ptr_context;
|
||||
PointerRNA ptr_operator;
|
||||
PointerRNA ptr_event;
|
||||
PyObject *py_operator;
|
||||
|
||||
PyGILState_STATE gilstate;
|
||||
|
||||
bpy_context_set(C, &gilstate);
|
||||
|
||||
args = PyTuple_New(1);
|
||||
PyTuple_SET_ITEM(args, 0, PyObject_GetAttrString(py_class, "__rna__")); // need to use an rna instance as the first arg
|
||||
|
||||
/* poll has no 'op', should be ok still */
|
||||
/* use an rna instance as the first arg */
|
||||
RNA_pointer_create(NULL, &RNA_Operator, op, &ptr_operator);
|
||||
PyTuple_SET_ITEM(args, 0, pyrna_struct_CreatePyObject(&ptr_operator));
|
||||
|
||||
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 */
|
||||
|
||||
PyObject *class_dict= PyObject_GetAttrString(py_class_instance, "__dict__");
|
||||
|
||||
/* Assign instance attributes from operator properties */
|
||||
if(op) {
|
||||
@@ -115,20 +118,12 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperatorType *ot, wmOperat
|
||||
if (strcmp(arg_name, "rna_type")==0) continue;
|
||||
|
||||
item = pyrna_prop_to_py(op->ptr, prop);
|
||||
PyObject_SetAttrString(py_class_instance, arg_name, item);
|
||||
PyDict_SetItemString(class_dict, arg_name, item);
|
||||
Py_DECREF(item);
|
||||
}
|
||||
RNA_STRUCT_END;
|
||||
}
|
||||
|
||||
/* set operator pointer RNA as instance "__operator__" attribute */
|
||||
if(op) {
|
||||
RNA_pointer_create(NULL, &RNA_Operator, op, &ptr_operator);
|
||||
py_operator= pyrna_struct_CreatePyObject(&ptr_operator);
|
||||
PyObject_SetAttrString(py_class_instance, "__operator__", py_operator);
|
||||
Py_DECREF(py_operator);
|
||||
}
|
||||
|
||||
RNA_pointer_create(NULL, &RNA_Context, C, &ptr_context);
|
||||
|
||||
if (mode==PYOP_INVOKE) {
|
||||
@@ -159,6 +154,11 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperatorType *ot, wmOperat
|
||||
|
||||
Py_DECREF(args);
|
||||
Py_DECREF(item);
|
||||
Py_DECREF(class_dict);
|
||||
}
|
||||
else {
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
if (ret == NULL) { /* covers py_class_instance failing too */
|
||||
@@ -246,7 +246,7 @@ static int PYTHON_OT_poll(bContext *C, wmOperatorType *ot)
|
||||
void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata)
|
||||
{
|
||||
PyObject *py_class = (PyObject *)userdata;
|
||||
PyObject *props, *item;
|
||||
PyObject *item;
|
||||
|
||||
/* identifiers */
|
||||
item= PyObject_GetAttrString(py_class, PYOP_ATTR_IDNAME_BL);
|
||||
@@ -300,46 +300,18 @@ void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata)
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
props= PyObject_GetAttrString(py_class, PYOP_ATTR_PROP);
|
||||
|
||||
if (props) {
|
||||
PyObject *dummy_args = PyTuple_New(0);
|
||||
int i;
|
||||
|
||||
for(i=0; i<PyList_Size(props); i++) {
|
||||
PyObject *py_func_ptr, *py_kw, *py_srna_cobject, *py_ret;
|
||||
item = PyList_GET_ITEM(props, i);
|
||||
|
||||
if (PyArg_ParseTuple(item, "O!O!:PYTHON_OT_wrapper", &PyCObject_Type, &py_func_ptr, &PyDict_Type, &py_kw)) {
|
||||
|
||||
PyObject *(*pyfunc)(PyObject *, PyObject *, PyObject *);
|
||||
pyfunc = PyCObject_AsVoidPtr(py_func_ptr);
|
||||
py_srna_cobject = PyCObject_FromVoidPtr(ot->srna, NULL);
|
||||
|
||||
py_ret = pyfunc(py_srna_cobject, dummy_args, py_kw);
|
||||
if (py_ret) {
|
||||
Py_DECREF(py_ret);
|
||||
} else {
|
||||
fprintf(stderr, "BPy Operator \"%s\" registration error: %s item %d could not run\n", ot->idname, PYOP_ATTR_PROP, i);
|
||||
PyLineSpit();
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
Py_DECREF(py_srna_cobject);
|
||||
|
||||
} else {
|
||||
/* cant return NULL from here */ // XXX a bit ugly
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
// expect a tuple with a CObject and a dict
|
||||
/* Can't use this because it returns a dict proxy
|
||||
*
|
||||
* item= PyObject_GetAttrString(py_class, "__dict__");
|
||||
*/
|
||||
item= ((PyTypeObject*)py_class)->tp_dict;
|
||||
if(item) {
|
||||
if(pyrna_deferred_register_props(ot->srna, item)!=0) {
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
Py_DECREF(dummy_args);
|
||||
Py_DECREF(props);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
PyErr_Clear();
|
||||
}
|
||||
}
|
||||
@@ -354,12 +326,10 @@ PyObject *PYOP_wrap_add(PyObject *self, PyObject *py_class)
|
||||
|
||||
char *idname= NULL;
|
||||
char idname_bl[OP_MAX_TYPENAME]; /* converted to blender syntax */
|
||||
int i;
|
||||
|
||||
static struct BPY_class_attr_check pyop_class_attr_values[]= {
|
||||
{PYOP_ATTR_IDNAME, 's', -1, OP_MAX_TYPENAME-3, 0}, /* -3 because a.b -> A_OT_b */
|
||||
{PYOP_ATTR_UINAME, 's', -1,-1, BPY_CLASS_ATTR_OPTIONAL},
|
||||
{PYOP_ATTR_PROP, 'l', -1,-1, BPY_CLASS_ATTR_OPTIONAL},
|
||||
{PYOP_ATTR_DESCRIPTION, 's', -1,-1, BPY_CLASS_ATTR_NONE_OK},
|
||||
{"execute", 'f', 2, -1, BPY_CLASS_ATTR_OPTIONAL},
|
||||
{"invoke", 'f', 3, -1, BPY_CLASS_ATTR_OPTIONAL},
|
||||
@@ -400,24 +370,6 @@ PyObject *PYOP_wrap_add(PyObject *self, PyObject *py_class)
|
||||
WM_operatortype_remove(idname);
|
||||
}
|
||||
|
||||
/* If we have properties set, check its a list of dicts */
|
||||
item= PyObject_GetAttrString(py_class, PYOP_ATTR_PROP);
|
||||
if (item) {
|
||||
for(i=0; i<PyList_Size(item); i++) {
|
||||
PyObject *py_args = PyList_GET_ITEM(item, i);
|
||||
PyObject *py_func_ptr, *py_kw; /* place holders */
|
||||
|
||||
if (!PyArg_ParseTuple(py_args, "O!O!", &PyCObject_Type, &py_func_ptr, &PyDict_Type, &py_kw)) {
|
||||
PyErr_Format(PyExc_ValueError, "Cant register operator class - %s.properties must contain values from FloatProperty", idname);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
Py_DECREF(item);
|
||||
}
|
||||
else {
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
Py_INCREF(py_class);
|
||||
WM_operatortype_append_ptr(PYTHON_OT_wrapper, py_class);
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@ static int mathutils_rna_vector_set(BPy_PropertyRNA *self, int subtype, float *v
|
||||
return 0;
|
||||
|
||||
RNA_property_float_set_array(&self->ptr, self->prop, vec_to);
|
||||
RNA_property_update(BPy_GetContext(), &self->ptr, self->prop);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -89,6 +90,7 @@ static int mathutils_rna_vector_set_index(BPy_PropertyRNA *self, int subtype, fl
|
||||
return 0;
|
||||
|
||||
RNA_property_float_set_index(&self->ptr, self->prop, index, vec_to[index]);
|
||||
RNA_property_update(BPy_GetContext(), &self->ptr, self->prop);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -119,6 +121,7 @@ static int mathutils_rna_matrix_set(BPy_PropertyRNA *self, int subtype, float *m
|
||||
return 0;
|
||||
|
||||
RNA_property_float_set_array(&self->ptr, self->prop, mat_to);
|
||||
RNA_property_update(BPy_GetContext(), &self->ptr, self->prop);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1124,11 +1127,24 @@ static int pyrna_prop_contains(BPy_PropertyRNA * self, PyObject *value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *pyrna_prop_item(BPy_PropertyRNA * self, Py_ssize_t index)
|
||||
{
|
||||
/* reuse subscript functions */
|
||||
if (RNA_property_type(self->prop) == PROP_COLLECTION) {
|
||||
return prop_subscript_collection_int(self, index);
|
||||
} else if (RNA_property_array_check(&self->ptr, self->prop)) {
|
||||
return prop_subscript_array_int(self, index);
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_TypeError, "rna type is not an array or a collection");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PySequenceMethods pyrna_prop_as_sequence = {
|
||||
NULL, /* Cant set the len otherwise it can evaluate as false */
|
||||
NULL, /* sq_concat */
|
||||
NULL, /* sq_repeat */
|
||||
NULL, /* sq_item */
|
||||
(ssizeargfunc)pyrna_prop_item, /* sq_item */ /* Only set this so PySequence_Check() returns True */
|
||||
NULL, /* sq_slice */
|
||||
NULL, /* sq_ass_item */
|
||||
NULL, /* sq_ass_slice */
|
||||
@@ -1138,19 +1154,43 @@ static PySequenceMethods pyrna_prop_as_sequence = {
|
||||
|
||||
static PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA * self, PyObject *args)
|
||||
{
|
||||
char *path;
|
||||
char *path, *path_full;
|
||||
int index= 0;
|
||||
float cfra = CTX_data_scene(BPy_GetContext())->r.cfra;
|
||||
|
||||
if(!RNA_struct_is_ID(self->ptr.type)) {
|
||||
PyErr_SetString( PyExc_TypeError, "StructRNA - keyframe_insert only for ID type");
|
||||
return NULL;
|
||||
}
|
||||
PropertyRNA *prop;
|
||||
PyObject *result;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s|if:keyframe_insert", &path, &index, &cfra))
|
||||
return NULL;
|
||||
|
||||
return PyBool_FromLong( insert_keyframe((ID *)self->ptr.data, NULL, NULL, path, index, cfra, 0));
|
||||
if (self->ptr.data==NULL) {
|
||||
PyErr_Format( PyExc_TypeError, "keyframe_insert, this struct has no data, cant be animated", path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
prop = RNA_struct_find_property(&self->ptr, path);
|
||||
|
||||
if (prop==NULL) {
|
||||
PyErr_Format( PyExc_TypeError, "keyframe_insert, property \"%s\" not found", path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!RNA_property_animateable(&self->ptr, prop)) {
|
||||
PyErr_Format( PyExc_TypeError, "keyframe_insert, property \"%s\" not animatable", path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
path_full= RNA_path_from_ID_to_property(&self->ptr, prop);
|
||||
|
||||
if (path_full==NULL) {
|
||||
PyErr_Format( PyExc_TypeError, "keyframe_insert, could not make path to \"%s\"", path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result= PyBool_FromLong( insert_keyframe((ID *)self->ptr.id.data, NULL, NULL, path_full, index, cfra, 0));
|
||||
MEM_freeN(path_full);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static PyObject *pyrna_struct_is_property_set(BPy_StructRNA * self, PyObject *args)
|
||||
@@ -1178,7 +1218,6 @@ static PyObject *pyrna_struct_is_property_hidden(BPy_StructRNA * self, PyObject
|
||||
return PyBool_FromLong(hidden);
|
||||
}
|
||||
|
||||
|
||||
static PyObject *pyrna_struct_dir(BPy_StructRNA * self)
|
||||
{
|
||||
PyObject *ret, *dict;
|
||||
@@ -1263,6 +1302,13 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA * self)
|
||||
BLI_freelistN(&lb);
|
||||
}
|
||||
|
||||
/* Hard coded names */
|
||||
{
|
||||
pystring = PyUnicode_FromString("id_data");
|
||||
PyList_Append(ret, pystring);
|
||||
Py_DECREF(pystring);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1319,6 +1365,16 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA * self, PyObject *pyname )
|
||||
|
||||
BLI_freelistN(&newlb);
|
||||
}
|
||||
else if (strcmp(name, "id_data")==0) { /* XXX - hard coded */
|
||||
if(self->ptr.id.data) {
|
||||
PointerRNA id_ptr;
|
||||
RNA_id_pointer_create((ID *)self->ptr.id.data, &id_ptr);
|
||||
return pyrna_struct_CreatePyObject(&id_ptr);
|
||||
}
|
||||
else {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
PyErr_Format( PyExc_AttributeError, "StructRNA - Attribute \"%.200s\" not found", name);
|
||||
ret = NULL;
|
||||
@@ -1334,10 +1390,14 @@ static int pyrna_struct_setattro( BPy_StructRNA * self, PyObject *pyname, PyObje
|
||||
PropertyRNA *prop = RNA_struct_find_property(&self->ptr, name);
|
||||
|
||||
if (prop==NULL) {
|
||||
// XXX - This currently allows anything to be assigned to an rna prop, need to see how this should be used
|
||||
// but for now it makes porting scripts confusing since it fails silently.
|
||||
#if 0
|
||||
if (!BPy_StructRNA_CheckExact(self) && PyObject_GenericSetAttr((PyObject *)self, pyname, value) >= 0) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
PyErr_Format( PyExc_AttributeError, "StructRNA - Attribute \"%.200s\" not found", name);
|
||||
return -1;
|
||||
}
|
||||
@@ -2350,7 +2410,7 @@ static void pyrna_subtype_set_rna(PyObject *newclass, StructRNA *srna)
|
||||
item = pyrna_struct_CreatePyObject(&ptr);
|
||||
|
||||
//item = PyCObject_FromVoidPtr(srna, NULL);
|
||||
PyDict_SetItemString(((PyTypeObject *)newclass)->tp_dict, "__rna__", item);
|
||||
PyDict_SetItemString(((PyTypeObject *)newclass)->tp_dict, "bl_rna", item);
|
||||
Py_DECREF(item);
|
||||
/* done with rna instance */
|
||||
|
||||
@@ -2666,6 +2726,7 @@ 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
|
||||
@@ -2682,26 +2743,26 @@ static StructRNA *pyrna_struct_as_srna(PyObject *self)
|
||||
|
||||
/* ack, PyObject_GetAttrString wont look up this types tp_dict first :/ */
|
||||
if(PyType_Check(self)) {
|
||||
py_srna = (BPy_StructRNA *)PyDict_GetItemString(((PyTypeObject *)self)->tp_dict, "__rna__");
|
||||
py_srna = (BPy_StructRNA *)PyDict_GetItemString(((PyTypeObject *)self)->tp_dict, "bl_rna");
|
||||
Py_XINCREF(py_srna);
|
||||
}
|
||||
|
||||
if(py_srna==NULL)
|
||||
py_srna = (BPy_StructRNA*)PyObject_GetAttrString(self, "__rna__");
|
||||
py_srna = (BPy_StructRNA*)PyObject_GetAttrString(self, "bl_rna");
|
||||
|
||||
if(py_srna==NULL) {
|
||||
PyErr_SetString(PyExc_SystemError, "internal error, self had no __rna__ attribute, should never happen.");
|
||||
PyErr_SetString(PyExc_SystemError, "internal error, self had no bl_rna attribute, should never happen.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BPy_StructRNA_Check(py_srna)) {
|
||||
PyErr_Format(PyExc_SystemError, "internal error, __rna__ was of type %.200s, instead of %.200s instance.", Py_TYPE(py_srna)->tp_name, pyrna_struct_Type.tp_name);
|
||||
PyErr_Format(PyExc_SystemError, "internal error, bl_rna was of type %.200s, instead of %.200s instance.", Py_TYPE(py_srna)->tp_name, pyrna_struct_Type.tp_name);
|
||||
Py_DECREF(py_srna);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(py_srna->ptr.type != &RNA_Struct) {
|
||||
PyErr_SetString(PyExc_SystemError, "internal error, __rna__ was not a RNA_Struct type of rna struct.");
|
||||
PyErr_SetString(PyExc_SystemError, "internal error, bl_rna was not a RNA_Struct type of rna struct.");
|
||||
Py_DECREF(py_srna);
|
||||
return NULL;
|
||||
}
|
||||
@@ -2755,13 +2816,10 @@ static PyObject *bpy_prop_deferred_return(void *func, PyObject *kw)
|
||||
PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
static char *kwlist[] = {"attr", "name", "description", "default", NULL};
|
||||
char *id, *name="", *description="";
|
||||
char *id=NULL, *name="", *description="";
|
||||
int def=0;
|
||||
PropertyRNA *prop;
|
||||
StructRNA *srna;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssi:BoolProperty", kwlist, &id, &name, &description, &def))
|
||||
return NULL;
|
||||
|
||||
if (PyTuple_Size(args) > 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
|
||||
@@ -2773,6 +2831,10 @@ PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
return NULL; /* self's type was compatible but error getting the srna */
|
||||
}
|
||||
else if(srna) {
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssi:BoolProperty", kwlist, &id, &name, &description, &def))
|
||||
return NULL;
|
||||
|
||||
prop= RNA_def_boolean(srna, id, def, name, description);
|
||||
RNA_def_property_duplicate_pointers(prop);
|
||||
Py_RETURN_NONE;
|
||||
@@ -2785,13 +2847,10 @@ PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
static char *kwlist[] = {"attr", "name", "description", "min", "max", "soft_min", "soft_max", "default", NULL};
|
||||
char *id, *name="", *description="";
|
||||
char *id=NULL, *name="", *description="";
|
||||
int min=INT_MIN, max=INT_MAX, soft_min=INT_MIN, soft_max=INT_MAX, def=0;
|
||||
PropertyRNA *prop;
|
||||
StructRNA *srna;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssiiiii:IntProperty", kwlist, &id, &name, &description, &min, &max, &soft_min, &soft_max, &def))
|
||||
return NULL;
|
||||
|
||||
if (PyTuple_Size(args) > 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
|
||||
@@ -2803,6 +2862,10 @@ PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
return NULL; /* self's type was compatible but error getting the srna */
|
||||
}
|
||||
else if(srna) {
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssiiiii:IntProperty", kwlist, &id, &name, &description, &min, &max, &soft_min, &soft_max, &def))
|
||||
return NULL;
|
||||
|
||||
prop= RNA_def_int(srna, id, def, min, max, name, description, soft_min, soft_max);
|
||||
RNA_def_property_duplicate_pointers(prop);
|
||||
Py_RETURN_NONE;
|
||||
@@ -2815,13 +2878,10 @@ PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
static char *kwlist[] = {"attr", "name", "description", "min", "max", "soft_min", "soft_max", "default", NULL};
|
||||
char *id, *name="", *description="";
|
||||
char *id=NULL, *name="", *description="";
|
||||
float min=-FLT_MAX, max=FLT_MAX, soft_min=-FLT_MAX, soft_max=FLT_MAX, def=0.0f;
|
||||
PropertyRNA *prop;
|
||||
StructRNA *srna;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssfffff:FloatProperty", kwlist, &id, &name, &description, &min, &max, &soft_min, &soft_max, &def))
|
||||
return NULL;
|
||||
|
||||
if (PyTuple_Size(args) > 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
|
||||
@@ -2833,6 +2893,10 @@ PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
return NULL; /* self's type was compatible but error getting the srna */
|
||||
}
|
||||
else if(srna) {
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssfffff:FloatProperty", kwlist, &id, &name, &description, &min, &max, &soft_min, &soft_max, &def))
|
||||
return NULL;
|
||||
|
||||
prop= RNA_def_float(srna, id, def, min, max, name, description, soft_min, soft_max);
|
||||
RNA_def_property_duplicate_pointers(prop);
|
||||
Py_RETURN_NONE;
|
||||
@@ -2845,13 +2909,10 @@ PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
static char *kwlist[] = {"attr", "name", "description", "maxlen", "default", NULL};
|
||||
char *id, *name="", *description="", *def="";
|
||||
char *id=NULL, *name="", *description="", *def="";
|
||||
int maxlen=0;
|
||||
PropertyRNA *prop;
|
||||
StructRNA *srna;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssis:StringProperty", kwlist, &id, &name, &description, &maxlen, &def))
|
||||
return NULL;
|
||||
|
||||
if (PyTuple_Size(args) > 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
|
||||
@@ -2863,6 +2924,10 @@ PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
return NULL; /* self's type was compatible but error getting the srna */
|
||||
}
|
||||
else if(srna) {
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssis:StringProperty", kwlist, &id, &name, &description, &maxlen, &def))
|
||||
return NULL;
|
||||
|
||||
prop= RNA_def_string(srna, id, def, maxlen, name, description);
|
||||
RNA_def_property_duplicate_pointers(prop);
|
||||
Py_RETURN_NONE;
|
||||
@@ -2921,15 +2986,12 @@ static EnumPropertyItem *enum_items_from_py(PyObject *value, const char *def, in
|
||||
PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
static char *kwlist[] = {"attr", "items", "name", "description", "default", NULL};
|
||||
char *id, *name="", *description="", *def="";
|
||||
char *id=NULL, *name="", *description="", *def="";
|
||||
int defvalue=0;
|
||||
PyObject *items= Py_None;
|
||||
EnumPropertyItem *eitems;
|
||||
PropertyRNA *prop;
|
||||
StructRNA *srna;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|sss:EnumProperty", kwlist, &id, &items, &name, &description, &def))
|
||||
return NULL;
|
||||
|
||||
if (PyTuple_Size(args) > 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
|
||||
@@ -2941,6 +3003,10 @@ PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
return NULL; /* self's type was compatible but error getting the srna */
|
||||
}
|
||||
else if(srna) {
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|sss:EnumProperty", kwlist, &id, &items, &name, &description, &def))
|
||||
return NULL;
|
||||
|
||||
eitems= enum_items_from_py(items, def, &defvalue);
|
||||
if(!eitems)
|
||||
return NULL;
|
||||
@@ -2977,13 +3043,10 @@ static StructRNA *pointer_type_from_py(PyObject *value)
|
||||
PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
static char *kwlist[] = {"attr", "type", "name", "description", NULL};
|
||||
char *id, *name="", *description="";
|
||||
char *id=NULL, *name="", *description="";
|
||||
PropertyRNA *prop;
|
||||
StructRNA *srna, *ptype;
|
||||
PyObject *type= Py_None;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|ss:PointerProperty", kwlist, &id, &type, &name, &description))
|
||||
return NULL;
|
||||
|
||||
if (PyTuple_Size(args) > 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
|
||||
@@ -2995,6 +3058,10 @@ PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
return NULL; /* self's type was compatible but error getting the srna */
|
||||
}
|
||||
else if(srna) {
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|ss:PointerProperty", kwlist, &id, &type, &name, &description))
|
||||
return NULL;
|
||||
|
||||
ptype= pointer_type_from_py(type);
|
||||
if(!ptype)
|
||||
return NULL;
|
||||
@@ -3012,13 +3079,10 @@ PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
static char *kwlist[] = {"attr", "type", "name", "description", NULL};
|
||||
char *id, *name="", *description="";
|
||||
char *id=NULL, *name="", *description="";
|
||||
PropertyRNA *prop;
|
||||
StructRNA *srna, *ptype;
|
||||
PyObject *type= Py_None;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|ss:CollectionProperty", kwlist, &id, &type, &name, &description))
|
||||
return NULL;
|
||||
|
||||
if (PyTuple_Size(args) > 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
|
||||
@@ -3030,6 +3094,10 @@ PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
return NULL; /* self's type was compatible but error getting the srna */
|
||||
}
|
||||
else if(srna) {
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|ss:CollectionProperty", kwlist, &id, &type, &name, &description))
|
||||
return NULL;
|
||||
|
||||
ptype= pointer_type_from_py(type);
|
||||
if(!ptype)
|
||||
return NULL;
|
||||
@@ -3044,50 +3112,58 @@ PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int deferred_register_props(PyObject *py_class, StructRNA *srna)
|
||||
int pyrna_deferred_register_props(StructRNA *srna, PyObject *class_dict)
|
||||
{
|
||||
PyObject *props, *dummy_args, *item;
|
||||
int i;
|
||||
|
||||
props= PyObject_GetAttrString(py_class, "__props__");
|
||||
|
||||
if(!props) {
|
||||
PyErr_Clear();
|
||||
return 1;
|
||||
}
|
||||
PyObject *dummy_args, *item, *key;
|
||||
Py_ssize_t pos = 0;
|
||||
|
||||
dummy_args = PyTuple_New(0);
|
||||
|
||||
for(i=0; i<PyList_Size(props); i++) {
|
||||
|
||||
while (PyDict_Next(class_dict, &pos, &key, &item)) {
|
||||
PyObject *py_func_ptr, *py_kw, *py_srna_cobject, *py_ret;
|
||||
item = PyList_GET_ITEM(props, i);
|
||||
|
||||
if(PyArg_ParseTuple(item, "O!O!", &PyCObject_Type, &py_func_ptr, &PyDict_Type, &py_kw)) {
|
||||
PyObject *(*pyfunc)(PyObject *, PyObject *, PyObject *);
|
||||
pyfunc = PyCObject_AsVoidPtr(py_func_ptr);
|
||||
py_srna_cobject = PyCObject_FromVoidPtr(srna, NULL);
|
||||
|
||||
py_ret = pyfunc(py_srna_cobject, dummy_args, py_kw);
|
||||
Py_DECREF(py_srna_cobject);
|
||||
/* We only care about results from C which
|
||||
* are for sure types, save some time with error */
|
||||
if(PyTuple_CheckExact(item)) {
|
||||
if(PyArg_ParseTuple(item, "O!O!", &PyCObject_Type, &py_func_ptr, &PyDict_Type, &py_kw)) {
|
||||
|
||||
if(py_ret) {
|
||||
Py_DECREF(py_ret);
|
||||
PyObject *(*pyfunc)(PyObject *, PyObject *, PyObject *);
|
||||
pyfunc = PyCObject_AsVoidPtr(py_func_ptr);
|
||||
py_srna_cobject = PyCObject_FromVoidPtr(srna, NULL);
|
||||
|
||||
/* not 100% nice :/, modifies the dict passed, should be ok */
|
||||
PyDict_SetItemString(py_kw, "attr", key);
|
||||
|
||||
py_ret = pyfunc(py_srna_cobject, dummy_args, py_kw);
|
||||
Py_DECREF(py_srna_cobject);
|
||||
|
||||
if(py_ret) {
|
||||
Py_DECREF(py_ret);
|
||||
}
|
||||
else {
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
|
||||
PyLineSpit();
|
||||
|
||||
PyErr_Format(PyExc_ValueError, "StructRNA \"%.200s\" registration error: %.200s could not run\n", RNA_struct_identifier(srna), _PyUnicode_AsString(key));
|
||||
Py_DECREF(dummy_args);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Py_DECREF(dummy_args);
|
||||
return 0;
|
||||
/* Since this is a class dict, ignore args that can't be passed */
|
||||
|
||||
/* for testing only */
|
||||
/* PyObSpit("Why doesn't this work??", item);
|
||||
PyErr_Print(); */
|
||||
PyErr_Clear();
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
PyErr_Clear();
|
||||
PyErr_SetString(PyExc_AttributeError, "expected list of dicts for __props__.");
|
||||
Py_DECREF(dummy_args);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Py_DECREF(dummy_args);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------- Type Registration ------------------------*/
|
||||
@@ -3121,7 +3197,7 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun
|
||||
PyObject *item, *fitem;
|
||||
PyObject *py_arg_count;
|
||||
int i, flag, arg_count, func_arg_count;
|
||||
char identifier[128];
|
||||
const char *identifier;
|
||||
|
||||
if (base_class) {
|
||||
if (!PyObject_IsSubclass(py_class, base_class)) {
|
||||
@@ -3192,11 +3268,13 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun
|
||||
if(!(flag & PROP_REGISTER))
|
||||
continue;
|
||||
|
||||
BLI_snprintf(identifier, sizeof(identifier), "__%s__", RNA_property_identifier(prop));
|
||||
identifier= RNA_property_identifier(prop);
|
||||
item = PyObject_GetAttrString(py_class, identifier);
|
||||
|
||||
if (item==NULL) {
|
||||
if(strcmp(identifier, "__idname__") == 0) {
|
||||
|
||||
/* Sneaky workaround to use the class name as the bl_idname */
|
||||
if(strcmp(identifier, "bl_idname") == 0) {
|
||||
item= PyObject_GetAttrString(py_class, "__name__");
|
||||
|
||||
if(item) {
|
||||
@@ -3207,7 +3285,8 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun
|
||||
}
|
||||
}
|
||||
|
||||
if (item==NULL && (flag & PROP_REGISTER_OPTIONAL)==0) {
|
||||
|
||||
if (item == NULL && (((flag & PROP_REGISTER_OPTIONAL) != PROP_REGISTER_OPTIONAL))) {
|
||||
PyErr_Format( PyExc_AttributeError, "expected %.200s class to have an \"%.200s\" attribute", class_type, identifier);
|
||||
return -1;
|
||||
}
|
||||
@@ -3450,8 +3529,19 @@ PyObject *pyrna_basetype_register(PyObject *self, PyObject *py_class)
|
||||
// Py_DECREF(py_class); // shuld be able to do this XXX since the old rna adds a new ref.
|
||||
}
|
||||
|
||||
if(!deferred_register_props(py_class, srna_new))
|
||||
return NULL;
|
||||
/* Can't use this because it returns a dict proxy
|
||||
*
|
||||
* item= PyObject_GetAttrString(py_class, "__dict__");
|
||||
*/
|
||||
item= ((PyTypeObject*)py_class)->tp_dict;
|
||||
if(item) {
|
||||
if(pyrna_deferred_register_props(srna_new, item)!=0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
@@ -91,6 +91,8 @@ PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw);
|
||||
PyObject *pyrna_basetype_register(PyObject *self, PyObject *args);
|
||||
PyObject *pyrna_basetype_unregister(PyObject *self, PyObject *args);
|
||||
|
||||
int pyrna_deferred_register_props(struct StructRNA *srna, PyObject *class_dict);
|
||||
|
||||
/* called before stopping python */
|
||||
void pyrna_alloc_types(void);
|
||||
void pyrna_free_types(void);
|
||||
|
||||
Reference in New Issue
Block a user