Merged changes in the trunk up to revision 25863.
This commit is contained in:
@@ -541,7 +541,7 @@ static PyGetSetDef Euler_getseters[] = {
|
||||
{"z", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Z axis", (void *)2},
|
||||
|
||||
{"wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, "True when this wraps blenders internal data", NULL},
|
||||
{"__owner__", (getter)BaseMathObject_getOwner, (setter)NULL, "Read only owner for vectors that depend on another object", NULL},
|
||||
{"_owner", (getter)BaseMathObject_getOwner, (setter)NULL, "Read only owner for vectors that depend on another object", NULL},
|
||||
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
|
||||
@@ -1129,12 +1129,33 @@ static PyObject *Matrix_getColSize( MatrixObject * self, void *type )
|
||||
return PyLong_FromLong((long) self->colSize);
|
||||
}
|
||||
|
||||
static PyObject *Matrix_getMedianScale( MatrixObject * self, void *type )
|
||||
{
|
||||
float mat[3][3];
|
||||
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
/*must be 3-4 cols, 3-4 rows, square matrix*/
|
||||
if(self->colSize == 4 && self->rowSize == 4)
|
||||
copy_m3_m4(mat, (float (*)[4])*self->matrix);
|
||||
else if(self->colSize == 3 && self->rowSize == 3)
|
||||
copy_m3_m3(mat, (float (*)[3])*self->matrix);
|
||||
else {
|
||||
PyErr_SetString(PyExc_AttributeError, "Matrix.median_scale: inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return PyFloat_FromDouble(mat3_to_scale(mat));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Python attributes get/set structure: */
|
||||
/*****************************************************************************/
|
||||
static PyGetSetDef Matrix_getseters[] = {
|
||||
{"rowSize", (getter)Matrix_getRowSize, (setter)NULL, "", NULL},
|
||||
{"colSize", (getter)Matrix_getColSize, (setter)NULL, "", NULL},
|
||||
{"row_size", (getter)Matrix_getRowSize, (setter)NULL, "", NULL},
|
||||
{"col_size", (getter)Matrix_getColSize, (setter)NULL, "", NULL},
|
||||
{"median_scale", (getter)Matrix_getMedianScale, (setter)NULL, "", NULL},
|
||||
{"wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, "", NULL},
|
||||
{"_owner",(getter)BaseMathObject_getOwner, (setter)NULL, "",
|
||||
NULL},
|
||||
|
||||
@@ -739,7 +739,7 @@ static PyGetSetDef Quaternion_getseters[] = {
|
||||
(getter)BaseMathObject_getWrapped, (setter)NULL,
|
||||
"True when this wraps blenders internal data",
|
||||
NULL},
|
||||
{"__owner__",
|
||||
{"_owner",
|
||||
(getter)BaseMathObject_getOwner, (setter)NULL,
|
||||
"Read only owner for vectors that depend on another object",
|
||||
NULL},
|
||||
|
||||
@@ -1421,7 +1421,7 @@ static PyGetSetDef Vector_getseters[] = {
|
||||
(getter)BaseMathObject_getWrapped, (setter)NULL,
|
||||
"True when this wraps blenders internal data",
|
||||
NULL},
|
||||
{"__owner__",
|
||||
{"_owner",
|
||||
(getter)BaseMathObject_getOwner, (setter)NULL,
|
||||
"Read only owner for vectors that depend on another object",
|
||||
NULL},
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
|
||||
#include "BPY_extern.h"
|
||||
#include "BKE_fcurve.h"
|
||||
|
||||
@@ -145,12 +147,15 @@ float BPY_pydriver_eval (ChannelDriver *driver)
|
||||
{
|
||||
PyObject *driver_vars=NULL;
|
||||
PyObject *retval= NULL;
|
||||
PyObject *expr_vars; /* speed up by pre-hashing string & avoids re-converting unicode strings for every execution */
|
||||
PyObject *expr_code;
|
||||
PyGILState_STATE gilstate;
|
||||
|
||||
DriverTarget *dtar;
|
||||
DriverVar *dvar;
|
||||
float result = 0.0f; /* default return */
|
||||
char *expr = NULL;
|
||||
short targets_ok= 1;
|
||||
int i;
|
||||
|
||||
/* sanity checks - should driver be executed? */
|
||||
if ((driver == NULL) /*|| (G.f & G_DOSCRIPTLINKS)==0*/)
|
||||
@@ -172,43 +177,75 @@ float BPY_pydriver_eval (ChannelDriver *driver)
|
||||
}
|
||||
}
|
||||
|
||||
if(driver->expr_comp==NULL)
|
||||
driver->flag |= DRIVER_FLAG_RECOMPILE;
|
||||
|
||||
/* compile the expression first if it hasn't been compiled or needs to be rebuilt */
|
||||
if(driver->flag & DRIVER_FLAG_RECOMPILE) {
|
||||
Py_XDECREF(driver->expr_comp);
|
||||
driver->expr_comp= PyTuple_New(2);
|
||||
|
||||
expr_code= Py_CompileString(expr, "<bpy driver>", Py_eval_input);
|
||||
PyTuple_SET_ITEM(((PyObject *)driver->expr_comp), 0, expr_code);
|
||||
|
||||
driver->flag &= ~DRIVER_FLAG_RECOMPILE;
|
||||
driver->flag |= DRIVER_FLAG_RENAMEVAR; /* maybe this can be removed but for now best keep until were sure */
|
||||
}
|
||||
else {
|
||||
expr_code= PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 0);
|
||||
}
|
||||
|
||||
if(driver->flag & DRIVER_FLAG_RENAMEVAR) {
|
||||
/* may not be set */
|
||||
expr_vars= PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 1);
|
||||
Py_XDECREF(expr_vars);
|
||||
|
||||
/* intern the arg names so creating the namespace for every run is faster */
|
||||
expr_vars= PyTuple_New(BLI_countlist(&driver->variables));
|
||||
PyTuple_SET_ITEM(((PyObject *)driver->expr_comp), 1, expr_vars);
|
||||
|
||||
for (dvar= driver->variables.first, i=0; dvar; dvar= dvar->next) {
|
||||
PyTuple_SET_ITEM(expr_vars, i++, PyUnicode_InternFromString(dvar->name));
|
||||
}
|
||||
}
|
||||
else {
|
||||
expr_vars= PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 1);
|
||||
}
|
||||
|
||||
/* add target values to a dict that will be used as '__locals__' dict */
|
||||
driver_vars = PyDict_New(); // XXX do we need to decref this?
|
||||
for (dtar= driver->targets.first; dtar; dtar= dtar->next) {
|
||||
for (dvar= driver->variables.first, i=0; dvar; dvar= dvar->next) {
|
||||
PyObject *driver_arg = NULL;
|
||||
float tval = 0.0f;
|
||||
|
||||
|
||||
/* try to get variable value */
|
||||
tval= driver_get_target_value(driver, dtar);
|
||||
tval= driver_get_variable_value(driver, dvar);
|
||||
driver_arg= PyFloat_FromDouble((double)tval);
|
||||
|
||||
|
||||
/* try to add to dictionary */
|
||||
if (PyDict_SetItemString(driver_vars, dtar->name, driver_arg)) {
|
||||
/* if (PyDict_SetItemString(driver_vars, dvar->name, driver_arg)) { */
|
||||
if (PyDict_SetItem(driver_vars, PyTuple_GET_ITEM(expr_vars, i++), driver_arg)) { /* use string interning for faster namespace creation */
|
||||
/* this target failed - bad name */
|
||||
if (targets_ok) {
|
||||
/* first one - print some extra info for easier identification */
|
||||
fprintf(stderr, "\nBPY_pydriver_eval() - Error while evaluating PyDriver:\n");
|
||||
targets_ok= 0;
|
||||
}
|
||||
|
||||
fprintf(stderr, "\tBPY_pydriver_eval() - couldn't add variable '%s' to namespace \n", dtar->name);
|
||||
|
||||
fprintf(stderr, "\tBPY_pydriver_eval() - couldn't add variable '%s' to namespace \n", dvar->name);
|
||||
// BPy_errors_to_report(NULL); // TODO - reports
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 // slow
|
||||
#if 0 // slow, with this can avoid all Py_CompileString above.
|
||||
/* execute expression to get a value */
|
||||
retval = PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict, driver_vars);
|
||||
#else
|
||||
if(driver->flag & DRIVER_FLAG_RECOMPILE || driver->expr_comp==NULL) {
|
||||
Py_XDECREF(driver->expr_comp);
|
||||
driver->expr_comp= Py_CompileString(expr, "<bpy driver>", Py_eval_input);
|
||||
driver->flag &= ~DRIVER_FLAG_RECOMPILE;
|
||||
}
|
||||
if(driver->expr_comp)
|
||||
retval= PyEval_EvalCode(driver->expr_comp, bpy_pydriver_Dict, driver_vars);
|
||||
/* evaluate the compiled expression */
|
||||
if (expr_code)
|
||||
retval= PyEval_EvalCode((PyCodeObject *)expr_code, bpy_pydriver_Dict, driver_vars);
|
||||
#endif
|
||||
|
||||
/* decref the driver vars first... */
|
||||
|
||||
@@ -226,12 +226,15 @@ static void bpy_init_modules( void )
|
||||
|
||||
/* blender info that wont change at runtime, add into _bpy */
|
||||
{
|
||||
extern char bprogname[]; /* argv[0] from creator.c */
|
||||
|
||||
PyObject *mod_dict= PyModule_GetDict(mod);
|
||||
char tmpstr[256];
|
||||
PyModule_AddStringConstant(mod, "_HOME", BLI_gethome());
|
||||
PyDict_SetItemString(mod_dict, "_VERSION", Py_BuildValue("(iii)", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION));
|
||||
sprintf(tmpstr, "%d.%02d (sub %d)", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION);
|
||||
PyModule_AddStringConstant(mod, "_VERSION_STR", tmpstr);
|
||||
PyModule_AddStringConstant(mod, "_BINPATH", bprogname);
|
||||
}
|
||||
|
||||
/* add our own modules dir, this is a python package */
|
||||
|
||||
@@ -244,10 +244,7 @@ PyObject *BPY_operator_module( void )
|
||||
static PyMethodDef pyop_as_string_meth ={"as_string", (PyCFunction) pyop_as_string, METH_VARARGS, NULL};
|
||||
static PyMethodDef pyop_dir_meth = {"dir", (PyCFunction) pyop_dir, METH_NOARGS, NULL};
|
||||
static PyMethodDef pyop_getrna_meth = {"get_rna", (PyCFunction) pyop_getrna, METH_O, NULL};
|
||||
// static PyMethodDef pyop_add_meth = {"add", (PyCFunction) PYOP_wrap_add, METH_O, NULL};
|
||||
static PyMethodDef pyop_add_macro_meth ={"add_macro", (PyCFunction) PYOP_wrap_add_macro, METH_O, NULL};
|
||||
static PyMethodDef pyop_macro_def_meth ={"macro_define", (PyCFunction) PYOP_wrap_macro_define, METH_VARARGS, NULL};
|
||||
static PyMethodDef pyop_remove_meth = {"remove", (PyCFunction) PYOP_wrap_remove, METH_O, NULL};
|
||||
|
||||
PyObject *submodule = PyModule_New("_bpy.ops");
|
||||
PyDict_SetItemString(PySys_GetObject("modules"), "_bpy.ops", submodule);
|
||||
@@ -256,10 +253,7 @@ PyObject *BPY_operator_module( void )
|
||||
PyModule_AddObject( submodule, "as_string",PyCFunction_New(&pyop_as_string_meth,NULL) );
|
||||
PyModule_AddObject( submodule, "dir", PyCFunction_New(&pyop_dir_meth, NULL) );
|
||||
PyModule_AddObject( submodule, "get_rna", PyCFunction_New(&pyop_getrna_meth, NULL) );
|
||||
// PyModule_AddObject( submodule, "add", PyCFunction_New(&pyop_add_meth, NULL) );
|
||||
PyModule_AddObject( submodule, "add_macro", PyCFunction_New(&pyop_add_macro_meth, NULL) );
|
||||
PyModule_AddObject( submodule, "macro_define",PyCFunction_New(&pyop_macro_def_meth, NULL) );
|
||||
PyModule_AddObject( submodule, "remove", PyCFunction_New(&pyop_remove_meth, NULL) );
|
||||
|
||||
return submodule;
|
||||
}
|
||||
|
||||
@@ -42,226 +42,6 @@
|
||||
|
||||
#include "../generic/bpy_internal_import.h" // our own imports
|
||||
|
||||
#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},
|
||||
{"CANCELLED", OPERATOR_CANCELLED},
|
||||
{"FINISHED", OPERATOR_FINISHED},
|
||||
{"PASS_THROUGH", OPERATOR_PASS_THROUGH},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
/* This invoke function can take events and
|
||||
*
|
||||
* It is up to the pyot->py_invoke() python func to run pyot->py_exec()
|
||||
* the invoke function gets the keyword props as a dict, but can parse them
|
||||
* to py_exec like this...
|
||||
*
|
||||
* def op_exec(x=-1, y=-1, text=""):
|
||||
* ...
|
||||
*
|
||||
* def op_invoke(event, prop_defs):
|
||||
* prop_defs['x'] = event['x']
|
||||
* ...
|
||||
* op_exec(**prop_defs)
|
||||
*
|
||||
* when there is no invoke function, C calls exec and sets the props.
|
||||
* python class instance is stored in op->customdata so exec() can access
|
||||
*/
|
||||
|
||||
|
||||
#define PYOP_EXEC 1
|
||||
#define PYOP_INVOKE 2
|
||||
#define PYOP_POLL 3
|
||||
#define PYOP_DRAW 4
|
||||
|
||||
extern void BPY_update_modules( void ); //XXX temp solution
|
||||
|
||||
static int PYTHON_OT_generic(int mode, bContext *C, wmOperatorType *ot, wmOperator *op, wmEvent *event, uiLayout *layout)
|
||||
{
|
||||
PyObject *py_class = ot->pyop_data;
|
||||
PyObject *args;
|
||||
PyObject *ret= NULL, *py_class_instance, *item= NULL;
|
||||
int ret_flag= (mode==PYOP_POLL ? 0:OPERATOR_CANCELLED);
|
||||
PointerRNA ptr_context;
|
||||
PointerRNA ptr_operator;
|
||||
|
||||
PyGILState_STATE gilstate;
|
||||
|
||||
bpy_context_set(C, &gilstate);
|
||||
|
||||
args = PyTuple_New(1);
|
||||
|
||||
/* 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==NULL) { /* Initializing the class worked, now run its invoke function */
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
else {
|
||||
RNA_pointer_create(NULL, &RNA_Context, C, &ptr_context);
|
||||
|
||||
if (mode==PYOP_INVOKE) {
|
||||
PointerRNA ptr_event;
|
||||
item= PyObject_GetAttrString(py_class, "invoke");
|
||||
args = PyTuple_New(3);
|
||||
|
||||
RNA_pointer_create(NULL, &RNA_Event, event, &ptr_event);
|
||||
|
||||
// PyTuple_SET_ITEM "steals" object reference, it is
|
||||
// an object passed shouldn't be DECREF'ed
|
||||
PyTuple_SET_ITEM(args, 1, pyrna_struct_CreatePyObject(&ptr_context));
|
||||
PyTuple_SET_ITEM(args, 2, pyrna_struct_CreatePyObject(&ptr_event));
|
||||
}
|
||||
else if (mode==PYOP_EXEC) {
|
||||
item= PyObject_GetAttrString(py_class, "execute");
|
||||
args = PyTuple_New(2);
|
||||
|
||||
PyTuple_SET_ITEM(args, 1, pyrna_struct_CreatePyObject(&ptr_context));
|
||||
}
|
||||
else if (mode==PYOP_POLL) {
|
||||
item= PyObject_GetAttrString(py_class, "poll");
|
||||
args = PyTuple_New(2);
|
||||
PyTuple_SET_ITEM(args, 1, pyrna_struct_CreatePyObject(&ptr_context));
|
||||
}
|
||||
else if (mode==PYOP_DRAW) {
|
||||
PointerRNA ptr_layout;
|
||||
item= PyObject_GetAttrString(py_class, "draw");
|
||||
args = PyTuple_New(2);
|
||||
|
||||
RNA_pointer_create(NULL, &RNA_UILayout, layout, &ptr_layout);
|
||||
|
||||
// PyTuple_SET_ITEM "steals" object reference, it is
|
||||
// an object passed shouldn't be DECREF'ed
|
||||
PyTuple_SET_ITEM(args, 1, pyrna_struct_CreatePyObject(&ptr_context));
|
||||
#if 0
|
||||
PyTuple_SET_ITEM(args, 2, pyrna_struct_CreatePyObject(&ptr_layout));
|
||||
#else
|
||||
{
|
||||
/* mimic panels */
|
||||
PyObject *py_layout= pyrna_struct_CreatePyObject(&ptr_layout);
|
||||
PyObject *pyname= PyUnicode_FromString("layout");
|
||||
|
||||
if(PyObject_GenericSetAttr(py_class_instance, pyname, py_layout)) {
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
else {
|
||||
Py_DECREF(py_layout);
|
||||
}
|
||||
|
||||
Py_DECREF(pyname);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
PyTuple_SET_ITEM(args, 0, py_class_instance);
|
||||
|
||||
ret = PyObject_Call(item, args, NULL);
|
||||
|
||||
Py_DECREF(args);
|
||||
Py_DECREF(item);
|
||||
}
|
||||
|
||||
if (ret == NULL) { /* covers py_class_instance failing too */
|
||||
if(op)
|
||||
BPy_errors_to_report(op->reports);
|
||||
}
|
||||
else {
|
||||
if (mode==PYOP_POLL) {
|
||||
if (PyBool_Check(ret) == 0) {
|
||||
PyErr_Format(PyExc_ValueError, "Python operator '%s.poll', did not return a bool value", ot->idname);
|
||||
BPy_errors_to_report(op ? op->reports:NULL); /* prints and clears if NULL given */
|
||||
}
|
||||
else {
|
||||
ret_flag= ret==Py_True ? 1:0;
|
||||
}
|
||||
} else if(mode==PYOP_DRAW) {
|
||||
/* pass */
|
||||
} else if (BPY_flag_from_seq(pyop_ret_flags, ret, &ret_flag) == -1) {
|
||||
/* the returned value could not be converted into a flag */
|
||||
PyErr_Format(PyExc_ValueError, "Python operator, error using return value from \"%s\"\n", ot->idname);
|
||||
BPy_errors_to_report(op ? op->reports:NULL);
|
||||
ret_flag = OPERATOR_CANCELLED;
|
||||
}
|
||||
/* there is no need to copy the py keyword dict modified by
|
||||
* pyot->py_invoke(), back to the operator props since they are just
|
||||
* thrown away anyway
|
||||
*
|
||||
* If we ever want to do this and use the props again,
|
||||
* it can be done with - pyrna_pydict_to_props(op->ptr, kw, "")
|
||||
*/
|
||||
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
#if 0 /* only for testing */
|
||||
|
||||
/* print operator return value */
|
||||
if (mode != PYOP_POLL) {
|
||||
char flag_str[100];
|
||||
char class_name[100];
|
||||
BPY_flag_def *flag_def = pyop_ret_flags;
|
||||
|
||||
strcpy(flag_str, "");
|
||||
|
||||
while(flag_def->name) {
|
||||
if (ret_flag & flag_def->flag) {
|
||||
if(flag_str[1])
|
||||
sprintf(flag_str, "%s | %s", flag_str, flag_def->name);
|
||||
else
|
||||
strcpy(flag_str, flag_def->name);
|
||||
}
|
||||
flag_def++;
|
||||
}
|
||||
|
||||
/* get class name */
|
||||
item= PyObject_GetAttrString(py_class, PYOP_ATTR_IDNAME);
|
||||
strcpy(class_name, _PyUnicode_AsString(item));
|
||||
Py_DECREF(item);
|
||||
|
||||
fprintf(stderr, "%s's %s returned %s\n", class_name, mode == PYOP_EXEC ? "execute" : "invoke", flag_str);
|
||||
}
|
||||
#endif
|
||||
|
||||
bpy_context_clear(C, &gilstate);
|
||||
|
||||
return ret_flag;
|
||||
}
|
||||
|
||||
static int PYTHON_OT_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
return PYTHON_OT_generic(PYOP_INVOKE, C, op->type, op, event, NULL);
|
||||
}
|
||||
|
||||
static int PYTHON_OT_execute(bContext *C, wmOperator *op)
|
||||
{
|
||||
return PYTHON_OT_generic(PYOP_EXEC, C, op->type, op, NULL, NULL);
|
||||
}
|
||||
|
||||
static int PYTHON_OT_poll(bContext *C, wmOperatorType *ot)
|
||||
{
|
||||
return PYTHON_OT_generic(PYOP_POLL, C, ot, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static void PYTHON_OT_draw(bContext *C, wmOperator *op, uiLayout *layout)
|
||||
{
|
||||
PYTHON_OT_generic(PYOP_DRAW, C, op->type, op, NULL, layout);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void operator_wrapper(wmOperatorType *ot, void *userdata)
|
||||
{
|
||||
/* take care not to overwrite anything set in
|
||||
@@ -299,288 +79,46 @@ void operator_wrapper(wmOperatorType *ot, void *userdata)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata)
|
||||
void macro_wrapper(wmOperatorType *ot, void *userdata)
|
||||
{
|
||||
PyObject *py_class = (PyObject *)userdata;
|
||||
PyObject *item;
|
||||
wmOperatorType *data = (wmOperatorType *)userdata;
|
||||
|
||||
/* identifiers */
|
||||
item= PyObject_GetAttrString(py_class, PYOP_ATTR_IDNAME_BL);
|
||||
ot->idname= _PyUnicode_AsString(item);
|
||||
Py_DECREF(item);
|
||||
/* only copy a couple of things, the rest is set by the macro registration */
|
||||
ot->name = data->name;
|
||||
ot->idname = data->idname;
|
||||
ot->description = data->description;
|
||||
ot->flag |= data->flag; /* append flags to the one set by registration */
|
||||
ot->pyop_poll = data->pyop_poll;
|
||||
ot->ui = data->ui;
|
||||
ot->ext = data->ext;
|
||||
|
||||
item= PyObject_GetAttrString(py_class, PYOP_ATTR_UINAME);
|
||||
if (item) {
|
||||
ot->name= _PyUnicode_AsString(item);
|
||||
Py_DECREF(item);
|
||||
}
|
||||
else {
|
||||
ot->name= ot->idname;
|
||||
PyErr_Clear();
|
||||
}
|
||||
RNA_struct_blender_type_set(ot->ext.srna, ot);
|
||||
|
||||
item= PyObject_GetAttrString(py_class, PYOP_ATTR_DESCRIPTION);
|
||||
ot->description= (item && PyUnicode_Check(item)) ? _PyUnicode_AsString(item):"undocumented python operator";
|
||||
Py_XDECREF(item);
|
||||
|
||||
/* api callbacks, detailed checks dont on adding */
|
||||
if (PyObject_HasAttrString(py_class, "invoke"))
|
||||
ot->invoke= PYTHON_OT_invoke;
|
||||
//else
|
||||
// ot->invoke= WM_operator_props_popup; /* could have an option for standard invokes */
|
||||
|
||||
if (PyObject_HasAttrString(py_class, "execute"))
|
||||
ot->exec= PYTHON_OT_execute;
|
||||
if (PyObject_HasAttrString(py_class, "poll"))
|
||||
ot->pyop_poll= PYTHON_OT_poll;
|
||||
if (PyObject_HasAttrString(py_class, "draw"))
|
||||
ot->ui= PYTHON_OT_draw;
|
||||
|
||||
ot->pyop_data= userdata;
|
||||
|
||||
/* flags */
|
||||
ot->flag= 0;
|
||||
|
||||
item= PyObject_GetAttrString(py_class, PYOP_ATTR_REGISTER);
|
||||
if (item) {
|
||||
ot->flag |= PyObject_IsTrue(item)!=0 ? OPTYPE_REGISTER:0;
|
||||
Py_DECREF(item);
|
||||
}
|
||||
else {
|
||||
PyErr_Clear();
|
||||
}
|
||||
item= PyObject_GetAttrString(py_class, PYOP_ATTR_UNDO);
|
||||
if (item) {
|
||||
ot->flag |= PyObject_IsTrue(item)!=0 ? OPTYPE_UNDO:0;
|
||||
Py_DECREF(item);
|
||||
}
|
||||
else {
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
/* Can't use this because it returns a dict proxy
|
||||
*
|
||||
* item= PyObject_GetAttrString(py_class, "__dict__");
|
||||
*/
|
||||
item= ((PyTypeObject*)py_class)->tp_dict;
|
||||
if(item) {
|
||||
/* only call this so pyrna_deferred_register_props gives a useful error
|
||||
* WM_operatortype_append_ptr will call RNA_def_struct_identifier
|
||||
* later */
|
||||
RNA_def_struct_identifier(ot->srna, ot->idname);
|
||||
{
|
||||
PyObject *py_class = ot->ext.data;
|
||||
PyObject *item= ((PyTypeObject*)py_class)->tp_dict;
|
||||
if(item) {
|
||||
/* only call this so pyrna_deferred_register_props gives a useful error
|
||||
* WM_operatortype_append_ptr will call RNA_def_struct_identifier
|
||||
* later */
|
||||
RNA_def_struct_identifier(ot->srna, ot->idname);
|
||||
|
||||
if(pyrna_deferred_register_props(ot->srna, item)!=0) {
|
||||
/* failed to register operator props */
|
||||
PyErr_Print();
|
||||
if(pyrna_deferred_register_props(ot->srna, item)!=0) {
|
||||
/* failed to register operator props */
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
PyErr_Clear();
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
PyErr_Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void PYTHON_OT_MACRO_wrapper(wmOperatorType *ot, void *userdata)
|
||||
{
|
||||
PyObject *py_class = (PyObject *)userdata;
|
||||
PyObject *item;
|
||||
|
||||
/* identifiers */
|
||||
item= PyObject_GetAttrString(py_class, PYOP_ATTR_IDNAME_BL);
|
||||
ot->idname= _PyUnicode_AsString(item);
|
||||
Py_DECREF(item);
|
||||
|
||||
item= PyObject_GetAttrString(py_class, PYOP_ATTR_UINAME);
|
||||
if (item) {
|
||||
ot->name= _PyUnicode_AsString(item);
|
||||
Py_DECREF(item);
|
||||
}
|
||||
else {
|
||||
ot->name= ot->idname;
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
item= PyObject_GetAttrString(py_class, PYOP_ATTR_DESCRIPTION);
|
||||
ot->description= (item && PyUnicode_Check(item)) ? _PyUnicode_AsString(item):"undocumented python operator";
|
||||
Py_XDECREF(item);
|
||||
|
||||
if (PyObject_HasAttrString(py_class, "poll"))
|
||||
ot->pyop_poll= PYTHON_OT_poll;
|
||||
if (PyObject_HasAttrString(py_class, "draw"))
|
||||
ot->ui= PYTHON_OT_draw;
|
||||
|
||||
ot->pyop_data= userdata;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_MACRO; /* macro at least */
|
||||
|
||||
item= PyObject_GetAttrString(py_class, PYOP_ATTR_REGISTER);
|
||||
if (item) {
|
||||
ot->flag |= PyObject_IsTrue(item)!=0 ? OPTYPE_REGISTER:0;
|
||||
Py_DECREF(item);
|
||||
}
|
||||
else {
|
||||
PyErr_Clear();
|
||||
}
|
||||
item= PyObject_GetAttrString(py_class, PYOP_ATTR_UNDO);
|
||||
if (item) {
|
||||
ot->flag |= PyObject_IsTrue(item)!=0 ? OPTYPE_UNDO:0;
|
||||
Py_DECREF(item);
|
||||
}
|
||||
else {
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
/* Can't use this because it returns a dict proxy
|
||||
*
|
||||
* item= PyObject_GetAttrString(py_class, "__dict__");
|
||||
*/
|
||||
item= ((PyTypeObject*)py_class)->tp_dict;
|
||||
if(item) {
|
||||
/* only call this so pyrna_deferred_register_props gives a useful error
|
||||
* WM_operatortype_append_macro_ptr will call RNA_def_struct_identifier
|
||||
* later */
|
||||
RNA_def_struct_identifier(ot->srna, ot->idname);
|
||||
|
||||
if(pyrna_deferred_register_props(ot->srna, item)!=0) {
|
||||
/* failed to register operator props */
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
PyErr_Clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* pyOperators - Operators defined IN Python */
|
||||
PyObject *PYOP_wrap_add(PyObject *self, PyObject *py_class)
|
||||
{
|
||||
PyObject *base_class, *item;
|
||||
wmOperatorType *ot;
|
||||
|
||||
|
||||
char *idname= NULL;
|
||||
char idname_bl[OP_MAX_TYPENAME]; /* converted to blender syntax */
|
||||
|
||||
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_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},
|
||||
{"poll", 'f', 2, -1, BPY_CLASS_ATTR_OPTIONAL},
|
||||
{"draw", 'f', 2, -1, BPY_CLASS_ATTR_OPTIONAL},
|
||||
{NULL, 0, 0, 0}
|
||||
};
|
||||
|
||||
// in python would be...
|
||||
//PyObject *optype = PyObject_GetAttrString(PyObject_GetAttrString(PyDict_GetItemString(PyEval_GetGlobals(), "bpy"), "types"), "Operator");
|
||||
|
||||
//PyObject bpy_mod= PyDict_GetItemString(PyEval_GetGlobals(), "bpy");
|
||||
PyObject *bpy_mod= PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0);
|
||||
base_class = PyObject_GetAttrStringArgs(bpy_mod, 2, "types", "Operator");
|
||||
Py_DECREF(bpy_mod);
|
||||
|
||||
if(BPY_class_validate("Operator", py_class, base_class, pyop_class_attr_values, NULL) < 0) {
|
||||
return NULL; /* BPY_class_validate sets the error */
|
||||
}
|
||||
Py_DECREF(base_class);
|
||||
|
||||
/* class name is used for operator ID - this can be changed later if we want */
|
||||
item= PyObject_GetAttrString(py_class, PYOP_ATTR_IDNAME);
|
||||
idname = _PyUnicode_AsString(item);
|
||||
|
||||
|
||||
/* annoying conversion! */
|
||||
WM_operator_bl_idname(idname_bl, idname);
|
||||
Py_DECREF(item);
|
||||
|
||||
item= PyUnicode_FromString(idname_bl);
|
||||
PyObject_SetAttrString(py_class, PYOP_ATTR_IDNAME_BL, item);
|
||||
idname = _PyUnicode_AsString(item);
|
||||
Py_DECREF(item);
|
||||
/* end annoying conversion! */
|
||||
|
||||
|
||||
/* remove if it already exists */
|
||||
if ((ot=WM_operatortype_exists(idname))) {
|
||||
if(ot->pyop_data) {
|
||||
Py_XDECREF((PyObject*)ot->pyop_data);
|
||||
}
|
||||
WM_operatortype_remove(idname);
|
||||
}
|
||||
|
||||
Py_INCREF(py_class);
|
||||
WM_operatortype_append_ptr(PYTHON_OT_wrapper, py_class);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
/* pyOperators - Macro Operators defined IN Python */
|
||||
PyObject *PYOP_wrap_add_macro(PyObject *self, PyObject *py_class)
|
||||
{
|
||||
PyObject *base_class, *item;
|
||||
wmOperatorType *ot;
|
||||
|
||||
|
||||
char *idname= NULL;
|
||||
char idname_bl[OP_MAX_TYPENAME]; /* converted to blender syntax */
|
||||
|
||||
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_DESCRIPTION, 's', -1,-1, BPY_CLASS_ATTR_NONE_OK},
|
||||
{"poll", 'f', 2, -1, BPY_CLASS_ATTR_OPTIONAL},
|
||||
{"draw", 'f', 2, -1, BPY_CLASS_ATTR_OPTIONAL},
|
||||
{NULL, 0, 0, 0}
|
||||
};
|
||||
|
||||
//PyObject bpy_mod= PyDict_GetItemString(PyEval_GetGlobals(), "bpy");
|
||||
PyObject *bpy_mod= PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0);
|
||||
base_class = PyObject_GetAttrStringArgs(bpy_mod, 2, "types", "Macro");
|
||||
Py_DECREF(bpy_mod);
|
||||
|
||||
if(BPY_class_validate("Macro", py_class, base_class, pyop_class_attr_values, NULL) < 0) {
|
||||
return NULL; /* BPY_class_validate sets the error */
|
||||
}
|
||||
Py_DECREF(base_class);
|
||||
|
||||
/* class name is used for operator ID - this can be changed later if we want */
|
||||
item= PyObject_GetAttrString(py_class, PYOP_ATTR_IDNAME);
|
||||
idname = _PyUnicode_AsString(item);
|
||||
|
||||
|
||||
/* annoying conversion! */
|
||||
WM_operator_bl_idname(idname_bl, idname);
|
||||
Py_DECREF(item);
|
||||
|
||||
item= PyUnicode_FromString(idname_bl);
|
||||
PyObject_SetAttrString(py_class, PYOP_ATTR_IDNAME_BL, item);
|
||||
idname = _PyUnicode_AsString(item);
|
||||
Py_DECREF(item);
|
||||
/* end annoying conversion! */
|
||||
|
||||
|
||||
/* remove if it already exists */
|
||||
if ((ot=WM_operatortype_exists(idname))) {
|
||||
if(ot->pyop_data) {
|
||||
Py_XDECREF((PyObject*)ot->pyop_data);
|
||||
}
|
||||
WM_operatortype_remove(idname);
|
||||
}
|
||||
|
||||
Py_INCREF(py_class);
|
||||
WM_operatortype_append_macro_ptr(PYTHON_OT_MACRO_wrapper, py_class);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyObject *PYOP_wrap_macro_define(PyObject *self, PyObject *args)
|
||||
@@ -588,11 +126,11 @@ PyObject *PYOP_wrap_macro_define(PyObject *self, PyObject *args)
|
||||
wmOperatorType *ot;
|
||||
wmOperatorTypeMacro *otmacro;
|
||||
PyObject *macro;
|
||||
PyObject *item;
|
||||
PointerRNA ptr_otmacro;
|
||||
StructRNA *srna;
|
||||
|
||||
char *opname;
|
||||
char *macroname;
|
||||
const char *macroname;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "Os:_bpy.ops.macro_define", ¯o, &opname))
|
||||
return NULL;
|
||||
@@ -603,21 +141,8 @@ PyObject *PYOP_wrap_macro_define(PyObject *self, PyObject *args)
|
||||
}
|
||||
|
||||
/* identifiers */
|
||||
item= PyObject_GetAttrString(macro, PYOP_ATTR_IDNAME_BL);
|
||||
|
||||
if (!item) {
|
||||
item= PyObject_GetAttrString(macro, PYOP_ATTR_IDNAME);
|
||||
|
||||
if (!item) {
|
||||
PyErr_Format(PyExc_ValueError, "Macro Define: not a valid Macro class");
|
||||
} else {
|
||||
macroname= _PyUnicode_AsString(item);
|
||||
PyErr_Format(PyExc_ValueError, "Macro Define: '%s' hasn't been registered yet", macroname);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
macroname= _PyUnicode_AsString(item);
|
||||
srna= srna_from_self(macro);
|
||||
macroname = RNA_struct_identifier(srna);
|
||||
|
||||
ot = WM_operatortype_exists(macroname);
|
||||
|
||||
@@ -633,40 +158,3 @@ PyObject *PYOP_wrap_macro_define(PyObject *self, PyObject *args)
|
||||
return pyrna_struct_CreatePyObject(&ptr_otmacro);
|
||||
}
|
||||
|
||||
|
||||
PyObject *PYOP_wrap_remove(PyObject *self, PyObject *value)
|
||||
{
|
||||
PyObject *py_class;
|
||||
char *idname= NULL;
|
||||
wmOperatorType *ot;
|
||||
|
||||
|
||||
if (PyUnicode_Check(value))
|
||||
idname = _PyUnicode_AsString(value);
|
||||
else if (PyCFunction_Check(value)) {
|
||||
PyObject *cfunc_self = PyCFunction_GetSelf(value);
|
||||
if (cfunc_self)
|
||||
idname = _PyUnicode_AsString(cfunc_self);
|
||||
}
|
||||
|
||||
if (idname==NULL) {
|
||||
PyErr_SetString( PyExc_ValueError, "Expected the operator name as a string or the operator function");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(ot= WM_operatortype_exists(idname))) {
|
||||
PyErr_Format( PyExc_AttributeError, "Operator \"%s\" does not exists, cant remove", idname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(py_class= (PyObject *)ot->pyop_data)) {
|
||||
PyErr_Format( PyExc_AttributeError, "Operator \"%s\" was not created by python", idname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_XDECREF(py_class);
|
||||
|
||||
WM_operatortype_remove(idname);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
@@ -28,9 +28,5 @@
|
||||
#include <Python.h>
|
||||
|
||||
/* these are used for operator methods, used by bpy_operator.c */
|
||||
PyObject *PYOP_wrap_add(PyObject *self, PyObject *args);
|
||||
PyObject *PYOP_wrap_add_macro(PyObject *self, PyObject *args);
|
||||
PyObject *PYOP_wrap_macro_define(PyObject *self, PyObject *args);
|
||||
PyObject *PYOP_wrap_remove(PyObject *self, PyObject *args);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
@@ -53,6 +54,8 @@
|
||||
#include "../generic/Mathutils.h" /* so we can have mathutils callbacks */
|
||||
#include "../generic/IDProp.h" /* for IDprop lookups */
|
||||
|
||||
static PyObject *prop_subscript_array_slice(PointerRNA *ptr, PropertyRNA *prop, int start, int stop, int length);
|
||||
|
||||
/* bpyrna vector/euler/quat callbacks */
|
||||
static int mathutils_rna_array_cb_index= -1; /* index for our callbacks */
|
||||
|
||||
@@ -138,6 +141,8 @@ Mathutils_Callback mathutils_rna_matrix_cb = {
|
||||
(BaseMathSetIndexFunc) NULL
|
||||
};
|
||||
|
||||
#define PROP_ALL_VECTOR_SUBTYPES PROP_TRANSLATION: case PROP_DIRECTION: case PROP_VELOCITY: case PROP_ACCELERATION: case PROP_XYZ: case PROP_XYZ|PROP_UNIT_LENGTH
|
||||
|
||||
PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
|
||||
{
|
||||
PyObject *ret= NULL;
|
||||
@@ -146,28 +151,24 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
|
||||
int subtype, totdim;
|
||||
int len;
|
||||
int is_thick;
|
||||
int flag= RNA_property_flag(prop);
|
||||
|
||||
/* disallow dynamic sized arrays to be wrapped since the size could change
|
||||
* to a size mathutils does not support */
|
||||
if ((RNA_property_type(prop) != PROP_FLOAT) || (RNA_property_flag(prop) & PROP_DYNAMIC))
|
||||
if ((RNA_property_type(prop) != PROP_FLOAT) || (flag & PROP_DYNAMIC))
|
||||
return NULL;
|
||||
|
||||
len= RNA_property_array_length(ptr, prop);
|
||||
subtype= RNA_property_subtype(prop);
|
||||
totdim= RNA_property_array_dimension(ptr, prop, NULL);
|
||||
is_thick = (RNA_property_flag(prop) & PROP_THICK_WRAP);
|
||||
is_thick = (flag & PROP_THICK_WRAP);
|
||||
|
||||
if (totdim == 1 || (totdim == 2 && subtype == PROP_MATRIX)) {
|
||||
if(!is_thick)
|
||||
ret = pyrna_prop_CreatePyObject(ptr, prop); /* owned by the Mathutils PyObject */
|
||||
|
||||
switch(RNA_property_subtype(prop)) {
|
||||
case PROP_TRANSLATION:
|
||||
case PROP_DIRECTION:
|
||||
case PROP_VELOCITY:
|
||||
case PROP_ACCELERATION:
|
||||
case PROP_XYZ:
|
||||
case PROP_XYZ|PROP_UNIT_LENGTH:
|
||||
case PROP_ALL_VECTOR_SUBTYPES:
|
||||
if(len>=2 && len <= 4) {
|
||||
if(is_thick) {
|
||||
ret= newVectorObject(NULL, len, Py_NEW, NULL);
|
||||
@@ -234,8 +235,15 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
|
||||
}
|
||||
}
|
||||
|
||||
if(ret==NULL)
|
||||
ret = pyrna_prop_CreatePyObject(ptr, prop); /* TODO, convert to a python list */
|
||||
if(ret==NULL) {
|
||||
if(is_thick) {
|
||||
/* this is an array we cant reference (since its not thin wrappable)
|
||||
* and cannot be coerced into a mathutils type, so return as a list */
|
||||
ret = prop_subscript_array_slice(ptr, prop, 0, len, len);
|
||||
} else {
|
||||
ret = pyrna_prop_CreatePyObject(ptr, prop); /* owned by the Mathutils PyObject */
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -244,8 +252,6 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
|
||||
|
||||
#endif
|
||||
|
||||
static StructRNA *pyrna_struct_as_srna(PyObject *self);
|
||||
|
||||
static int pyrna_struct_compare( BPy_StructRNA * a, BPy_StructRNA * b )
|
||||
{
|
||||
return (a->ptr.data==b->ptr.data) ? 0 : -1;
|
||||
@@ -1001,7 +1007,7 @@ static PyObject *prop_subscript_collection_str(BPy_PropertyRNA *self, char *keyn
|
||||
}
|
||||
/* static PyObject *prop_subscript_array_str(BPy_PropertyRNA *self, char *keyname) */
|
||||
|
||||
static PyObject *prop_subscript_collection_slice(BPy_PropertyRNA *self, int start, int stop)
|
||||
static PyObject *prop_subscript_collection_slice(PointerRNA *ptr, PropertyRNA *prop, int start, int stop, int length)
|
||||
{
|
||||
PointerRNA newptr;
|
||||
PyObject *list = PyList_New(stop - start);
|
||||
@@ -1010,8 +1016,8 @@ static PyObject *prop_subscript_collection_slice(BPy_PropertyRNA *self, int star
|
||||
start = MIN2(start,stop); /* values are clamped from */
|
||||
|
||||
for(count = start; count < stop; count++) {
|
||||
if(RNA_property_collection_lookup_int(&self->ptr, self->prop, count - start, &newptr)) {
|
||||
PyList_SetItem(list, count - start, pyrna_struct_CreatePyObject(&newptr));
|
||||
if(RNA_property_collection_lookup_int(ptr, prop, count - start, &newptr)) {
|
||||
PyList_SET_ITEM(list, count - start, pyrna_struct_CreatePyObject(&newptr));
|
||||
}
|
||||
else {
|
||||
Py_DECREF(list);
|
||||
@@ -1023,16 +1029,72 @@ static PyObject *prop_subscript_collection_slice(BPy_PropertyRNA *self, int star
|
||||
|
||||
return list;
|
||||
}
|
||||
static PyObject *prop_subscript_array_slice(BPy_PropertyRNA *self, int start, int stop)
|
||||
|
||||
/* TODO - dimensions
|
||||
* note: could also use pyrna_prop_to_py_index(self, count) in a loop but its a lot slower
|
||||
* since at the moment it reads (and even allocates) the entire array for each index.
|
||||
*/
|
||||
#define PYRNA_STACK_ARRAY 32
|
||||
static PyObject *prop_subscript_array_slice(PointerRNA *ptr, PropertyRNA *prop, int start, int stop, int length)
|
||||
{
|
||||
PyObject *list = PyList_New(stop - start);
|
||||
int count;
|
||||
|
||||
start = MIN2(start,stop); /* values are clamped from PySlice_GetIndicesEx */
|
||||
switch (RNA_property_type(prop)) {
|
||||
case PROP_FLOAT:
|
||||
{
|
||||
float values_stack[PYRNA_STACK_ARRAY];
|
||||
float *values;
|
||||
if(length > PYRNA_STACK_ARRAY) { values= PyMem_MALLOC(sizeof(float) * length); }
|
||||
else { values= values_stack; }
|
||||
RNA_property_float_get_array(ptr, prop, values);
|
||||
|
||||
for(count=start; count<stop; count++)
|
||||
PyList_SET_ITEM(list, count-start, PyFloat_FromDouble(values[count]));
|
||||
|
||||
for(count = start; count < stop; count++)
|
||||
PyList_SetItem(list, count - start, pyrna_prop_to_py_index(self, count));
|
||||
if(values != values_stack) {
|
||||
PyMem_FREE(values);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PROP_BOOLEAN:
|
||||
{
|
||||
int values_stack[PYRNA_STACK_ARRAY];
|
||||
int *values;
|
||||
if(length > PYRNA_STACK_ARRAY) { values= PyMem_MALLOC(sizeof(int) * length); }
|
||||
else { values= values_stack; }
|
||||
|
||||
RNA_property_boolean_get_array(ptr, prop, values);
|
||||
for(count=start; count<stop; count++)
|
||||
PyList_SET_ITEM(list, count-start, PyBool_FromLong(values[count]));
|
||||
|
||||
if(values != values_stack) {
|
||||
PyMem_FREE(values);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PROP_INT:
|
||||
{
|
||||
int values_stack[PYRNA_STACK_ARRAY];
|
||||
int *values;
|
||||
if(length > PYRNA_STACK_ARRAY) { values= PyMem_MALLOC(sizeof(int) * length); }
|
||||
else { values= values_stack; }
|
||||
|
||||
RNA_property_int_get_array(ptr, prop, values);
|
||||
for(count=start; count<stop; count++)
|
||||
PyList_SET_ITEM(list, count-start, PyLong_FromSsize_t(values[count]));
|
||||
|
||||
if(values != values_stack) {
|
||||
PyMem_FREE(values);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* probably will never happen */
|
||||
PyErr_SetString(PyExc_TypeError, "not an array type");
|
||||
Py_DECREF(list);
|
||||
list= NULL;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -1059,7 +1121,7 @@ static PyObject *prop_subscript_collection(BPy_PropertyRNA *self, PyObject *key)
|
||||
return PyList_New(0);
|
||||
}
|
||||
else if (step == 1) {
|
||||
return prop_subscript_collection_slice(self, start, stop);
|
||||
return prop_subscript_collection_slice(&self->ptr, self->prop, start, stop, len);
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna");
|
||||
@@ -1094,7 +1156,7 @@ static PyObject *prop_subscript_array(BPy_PropertyRNA *self, PyObject *key)
|
||||
return PyList_New(0);
|
||||
}
|
||||
else if (step == 1) {
|
||||
return prop_subscript_array_slice(self, start, stop);
|
||||
return prop_subscript_array_slice(&self->ptr, self->prop, start, stop, len);
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna");
|
||||
@@ -1119,21 +1181,93 @@ static PyObject *pyrna_prop_subscript( BPy_PropertyRNA *self, PyObject *key )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int prop_subscript_ass_array_slice(BPy_PropertyRNA *self, int begin, int end, PyObject *value)
|
||||
/* could call (pyrna_py_to_prop_index(self, i, value) in a loop but it is slow */
|
||||
static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop, int start, int stop, int length, PyObject *value_orig)
|
||||
{
|
||||
PyObject *value;
|
||||
int count;
|
||||
void *values_alloc= NULL;
|
||||
int ret= 0;
|
||||
|
||||
/* values are clamped from */
|
||||
begin = MIN2(begin,end);
|
||||
|
||||
for(count = begin; count < end; count++) {
|
||||
if(pyrna_py_to_prop_index(self, count - begin, value) == -1) {
|
||||
/* TODO - this is wrong since some values have been assigned... will need to fix that */
|
||||
return -1; /* pyrna_struct_CreatePyObject should set the error */
|
||||
}
|
||||
if(value_orig == NULL) {
|
||||
PyErr_SetString(PyExc_TypeError, "invalid slice assignment, deleting with list types is not supported by StructRNA.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if(!(value=PySequence_Fast(value_orig, "invalid slice assignment, type is not a sequence"))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(PySequence_Fast_GET_SIZE(value) != stop-start) {
|
||||
Py_DECREF(value);
|
||||
PyErr_SetString(PyExc_TypeError, "invalid slice assignment, resizing StructRNA arrays isn't supported.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (RNA_property_type(prop)) {
|
||||
case PROP_FLOAT:
|
||||
{
|
||||
float values_stack[PYRNA_STACK_ARRAY];
|
||||
float *values;
|
||||
if(length > PYRNA_STACK_ARRAY) { values= values_alloc= PyMem_MALLOC(sizeof(float) * length); }
|
||||
else { values= values_stack; }
|
||||
if(start != 0 || stop != length) /* partial assignment? - need to get the array */
|
||||
RNA_property_float_get_array(ptr, prop, values);
|
||||
|
||||
for(count=start; count<stop; count++)
|
||||
values[count] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, count-start));
|
||||
|
||||
if(PyErr_Occurred()) ret= -1;
|
||||
else RNA_property_float_set_array(ptr, prop, values);
|
||||
break;
|
||||
}
|
||||
case PROP_BOOLEAN:
|
||||
{
|
||||
int values_stack[PYRNA_STACK_ARRAY];
|
||||
int *values;
|
||||
if(length > PYRNA_STACK_ARRAY) { values= values_alloc= PyMem_MALLOC(sizeof(int) * length); }
|
||||
else { values= values_stack; }
|
||||
|
||||
if(start != 0 || stop != length) /* partial assignment? - need to get the array */
|
||||
RNA_property_boolean_get_array(ptr, prop, values);
|
||||
|
||||
for(count=start; count<stop; count++)
|
||||
values[count] = PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, count-start));
|
||||
|
||||
if(PyErr_Occurred()) ret= -1;
|
||||
else RNA_property_boolean_set_array(ptr, prop, values);
|
||||
break;
|
||||
}
|
||||
case PROP_INT:
|
||||
{
|
||||
int values_stack[PYRNA_STACK_ARRAY];
|
||||
int *values;
|
||||
if(length > PYRNA_STACK_ARRAY) { values= values_alloc= PyMem_MALLOC(sizeof(int) * length); }
|
||||
else { values= values_stack; }
|
||||
|
||||
if(start != 0 || stop != length) /* partial assignment? - need to get the array */
|
||||
RNA_property_int_get_array(ptr, prop, values);
|
||||
|
||||
for(count=start; count<stop; count++)
|
||||
values[count] = PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, count-start));
|
||||
|
||||
if(PyErr_Occurred()) ret= -1;
|
||||
else RNA_property_int_set_array(ptr, prop, values);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
PyErr_SetString(PyExc_TypeError, "not an array type");
|
||||
ret= -1;
|
||||
}
|
||||
|
||||
Py_DECREF(value);
|
||||
|
||||
if(values_alloc) {
|
||||
PyMem_FREE(values_alloc);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static int prop_subscript_ass_array_int(BPy_PropertyRNA *self, int keynum, PyObject *value)
|
||||
@@ -1182,7 +1316,7 @@ static int pyrna_prop_ass_subscript( BPy_PropertyRNA *self, PyObject *key, PyObj
|
||||
return 0;
|
||||
}
|
||||
else if (step == 1) {
|
||||
return prop_subscript_ass_array_slice(self, start, stop, value);
|
||||
return prop_subscript_ass_array_slice(&self->ptr, self->prop, start, stop, len, value);
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna");
|
||||
@@ -1872,6 +2006,16 @@ static PyObject *pyrna_prop_getattro( BPy_PropertyRNA *self, PyObject *pyname )
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* annoying exception, maybe we need to have different types for this... */
|
||||
if((strcmp(name, "__getitem__")==0 || strcmp(name, "__setitem__")==0) &&
|
||||
(RNA_property_type(self->prop) != PROP_COLLECTION) &&
|
||||
RNA_property_array_check(&self->ptr, self->prop)==0
|
||||
) {
|
||||
PyErr_SetString(PyExc_AttributeError, "PropertyRNA - no __getitem__ support for this type");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* The error raised here will be displayed */
|
||||
return PyObject_GenericGetAttr((PyObject *)self, pyname);
|
||||
@@ -2104,10 +2248,11 @@ static void foreach_attr_type( BPy_PropertyRNA *self, char *attr,
|
||||
RawPropertyType *raw_type, int *attr_tot, int *attr_signed )
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
*raw_type= -1;
|
||||
*raw_type= PROP_RAW_UNSET;
|
||||
*attr_tot= 0;
|
||||
*attr_signed= FALSE;
|
||||
|
||||
/* note: this is fail with zero length lists, so dont let this get caled in that case */
|
||||
RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) {
|
||||
prop = RNA_struct_find_property(&itemptr, attr);
|
||||
*raw_type= RNA_property_raw_type(prop);
|
||||
@@ -2130,7 +2275,8 @@ static int foreach_parse_args(
|
||||
int target_tot;
|
||||
#endif
|
||||
|
||||
*size= *raw_type= *attr_tot= *attr_signed= FALSE;
|
||||
*size= *attr_tot= *attr_signed= FALSE;
|
||||
*raw_type= PROP_RAW_UNSET;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "sO", attr, seq) || (!PySequence_Check(*seq) && PyObject_CheckBuffer(*seq))) {
|
||||
PyErr_SetString( PyExc_TypeError, "foreach_get(attr, sequence) expects a string and a sequence" );
|
||||
@@ -2163,6 +2309,12 @@ static int foreach_parse_args(
|
||||
#endif
|
||||
}
|
||||
|
||||
/* check 'attr_tot' otherwise we dont know if any values were set
|
||||
* this isnt ideal because it means running on an empty list may fail silently when its not compatible. */
|
||||
if (*size == 0 && *attr_tot != 0) {
|
||||
PyErr_SetString( PyExc_AttributeError, "attribute does not support foreach method" );
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2184,6 +2336,8 @@ static int foreach_compat_buffer(RawPropertyType raw_type, int attr_signed, cons
|
||||
return (f=='f') ? 1:0;
|
||||
case PROP_RAW_DOUBLE:
|
||||
return (f=='d') ? 1:0;
|
||||
case PROP_RAW_UNSET:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -2248,6 +2402,9 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set)
|
||||
case PROP_RAW_DOUBLE:
|
||||
((double *)array)[i]= (double)PyFloat_AsDouble(item);
|
||||
break;
|
||||
case PROP_RAW_UNSET:
|
||||
/* should never happen */
|
||||
break;
|
||||
}
|
||||
|
||||
Py_DECREF(item);
|
||||
@@ -2299,6 +2456,9 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set)
|
||||
case PROP_RAW_DOUBLE:
|
||||
item= PyFloat_FromDouble( (double) ((double *)array)[i] );
|
||||
break;
|
||||
case PROP_RAW_UNSET:
|
||||
/* should never happen */
|
||||
break;
|
||||
}
|
||||
|
||||
PySequence_SetItem(seq, i, item);
|
||||
@@ -2343,14 +2503,8 @@ PyObject *pyrna_prop_iter(BPy_PropertyRNA *self)
|
||||
PyObject *iter;
|
||||
|
||||
if(RNA_property_array_check(&self->ptr, self->prop)) {
|
||||
int len = pyrna_prop_array_length(self);
|
||||
int i;
|
||||
PyErr_Clear();
|
||||
ret = PyList_New(len);
|
||||
|
||||
for (i=0; i < len; i++) {
|
||||
PyList_SET_ITEM(ret, i, pyrna_prop_to_py_index(self, i));
|
||||
}
|
||||
int len= pyrna_prop_array_length(self);
|
||||
ret = prop_subscript_array_slice(&self->ptr, self->prop, 0, len, len);
|
||||
}
|
||||
else if ((ret = pyrna_prop_values(self))) {
|
||||
/* do nothing */
|
||||
@@ -2449,29 +2603,48 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data)
|
||||
{
|
||||
PyObject *ret;
|
||||
int type = RNA_property_type(prop);
|
||||
|
||||
int flag = RNA_property_flag(prop);
|
||||
int a;
|
||||
|
||||
if(RNA_property_array_check(ptr, prop)) {
|
||||
int len = RNA_property_array_length(ptr, prop);
|
||||
|
||||
/* resolve the array from a new pytype */
|
||||
ret = PyTuple_New(len);
|
||||
|
||||
/* kazanbas: TODO make multidim sequences here */
|
||||
|
||||
switch (type) {
|
||||
case PROP_BOOLEAN:
|
||||
ret = PyTuple_New(len);
|
||||
for(a=0; a<len; a++)
|
||||
PyTuple_SET_ITEM(ret, a, PyBool_FromLong( ((int*)data)[a] ));
|
||||
break;
|
||||
case PROP_INT:
|
||||
ret = PyTuple_New(len);
|
||||
for(a=0; a<len; a++)
|
||||
PyTuple_SET_ITEM(ret, a, PyLong_FromSsize_t( (Py_ssize_t)((int*)data)[a] ));
|
||||
break;
|
||||
case PROP_FLOAT:
|
||||
for(a=0; a<len; a++)
|
||||
PyTuple_SET_ITEM(ret, a, PyFloat_FromDouble( ((float*)data)[a] ));
|
||||
switch(RNA_property_subtype(prop)) {
|
||||
case PROP_ALL_VECTOR_SUBTYPES:
|
||||
ret= newVectorObject(data, len, Py_NEW, NULL);
|
||||
break;
|
||||
case PROP_MATRIX:
|
||||
if(len==16) {
|
||||
ret= newMatrixObject(data, 4, 4, Py_NEW, NULL);
|
||||
break;
|
||||
}
|
||||
else if (len==9) {
|
||||
ret= newMatrixObject(data, 3, 3, Py_NEW, NULL);
|
||||
break;
|
||||
}
|
||||
/* pass through */
|
||||
default:
|
||||
ret = PyTuple_New(len);
|
||||
for(a=0; a<len; a++)
|
||||
PyTuple_SET_ITEM(ret, a, PyFloat_FromDouble( ((float*)data)[a] ));
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
PyErr_Format(PyExc_TypeError, "RNA Error: unknown array type \"%d\" (pyrna_param_to_py)", type);
|
||||
@@ -2493,7 +2666,10 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data)
|
||||
break;
|
||||
case PROP_STRING:
|
||||
{
|
||||
ret = PyUnicode_FromString( *(char**)data );
|
||||
if(flag & PROP_THICK_WRAP)
|
||||
ret = PyUnicode_FromString( (char*)data );
|
||||
else
|
||||
ret = PyUnicode_FromString( *(char**)data );
|
||||
break;
|
||||
}
|
||||
case PROP_ENUM:
|
||||
@@ -2505,7 +2681,6 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data)
|
||||
{
|
||||
PointerRNA newptr;
|
||||
StructRNA *type= RNA_property_pointer_type(ptr, prop);
|
||||
int flag = RNA_property_flag(prop);
|
||||
|
||||
if(flag & PROP_RNAPTR) {
|
||||
/* in this case we get the full ptr */
|
||||
@@ -2566,11 +2741,13 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw)
|
||||
PointerRNA funcptr;
|
||||
ParameterList parms;
|
||||
ParameterIterator iter;
|
||||
PropertyRNA *pret, *parm;
|
||||
PropertyRNA *parm;
|
||||
PyObject *ret, *item;
|
||||
int i, args_len, parms_len, flag, err= 0, kw_tot= 0, kw_arg;
|
||||
int i, args_len, parms_len, ret_len, flag, err= 0, kw_tot= 0, kw_arg;
|
||||
const char *parm_id;
|
||||
void *retdata= NULL;
|
||||
|
||||
PropertyRNA *pret_single= NULL;
|
||||
void *retdata_single= NULL;
|
||||
|
||||
/* Should never happen but it does in rare cases */
|
||||
if(self_ptr==NULL) {
|
||||
@@ -2588,14 +2765,15 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw)
|
||||
* the same ID as the functions. */
|
||||
RNA_pointer_create(self_ptr->id.data, &RNA_Function, self_func, &funcptr);
|
||||
|
||||
pret= RNA_function_return(self_func);
|
||||
args_len= PyTuple_GET_SIZE(args);
|
||||
|
||||
RNA_parameter_list_create(&parms, self_ptr, self_func);
|
||||
RNA_parameter_list_begin(&parms, &iter);
|
||||
parms_len = RNA_parameter_list_size(&parms);
|
||||
parms_len= RNA_parameter_list_size(&parms);
|
||||
ret_len= 0;
|
||||
|
||||
if(args_len + (kw ? PyDict_Size(kw):0) > parms_len) {
|
||||
RNA_parameter_list_end(&iter);
|
||||
PyErr_Format(PyExc_TypeError, "%.200s.%.200s(): takes at most %d arguments, got %d", RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), parms_len, args_len);
|
||||
err= -1;
|
||||
}
|
||||
@@ -2603,14 +2781,20 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw)
|
||||
/* parse function parameters */
|
||||
for (i= 0; iter.valid && err==0; RNA_parameter_list_next(&iter)) {
|
||||
parm= iter.parm;
|
||||
flag= RNA_property_flag(parm);
|
||||
|
||||
/* only useful for single argument returns, we'll need another list loop for multiple */
|
||||
if (flag & PROP_RETURN) {
|
||||
ret_len++;
|
||||
if (pret_single==NULL) {
|
||||
pret_single= parm;
|
||||
retdata_single= iter.data;
|
||||
}
|
||||
|
||||
if (parm==pret) {
|
||||
retdata= iter.data;
|
||||
continue;
|
||||
}
|
||||
|
||||
parm_id= RNA_property_identifier(parm);
|
||||
flag= RNA_property_flag(parm);
|
||||
item= NULL;
|
||||
|
||||
if ((i < args_len) && (flag & PROP_REQUIRED)) {
|
||||
@@ -2655,6 +2839,8 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RNA_parameter_list_end(&iter);
|
||||
|
||||
|
||||
/* Check if we gave args that dont exist in the function
|
||||
@@ -2742,8 +2928,25 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw)
|
||||
|
||||
/* return value */
|
||||
if(err==0) {
|
||||
if(pret) {
|
||||
ret= pyrna_param_to_py(&funcptr, pret, retdata);
|
||||
if (ret_len > 0) {
|
||||
if (ret_len > 1) {
|
||||
ret= PyTuple_New(ret_len);
|
||||
i= 0; /* arg index */
|
||||
|
||||
RNA_parameter_list_begin(&parms, &iter);
|
||||
|
||||
for(; iter.valid; RNA_parameter_list_next(&iter)) {
|
||||
parm= iter.parm;
|
||||
flag= RNA_property_flag(parm);
|
||||
|
||||
if (flag & PROP_RETURN)
|
||||
PyTuple_SET_ITEM(ret, i++, pyrna_param_to_py(&funcptr, parm, iter.data));
|
||||
}
|
||||
|
||||
RNA_parameter_list_end(&iter);
|
||||
}
|
||||
else
|
||||
ret= pyrna_param_to_py(&funcptr, pret_single, retdata_single);
|
||||
|
||||
/* possible there is an error in conversion */
|
||||
if(ret==NULL)
|
||||
@@ -3354,7 +3557,7 @@ PyObject *BPY_rna_props( void )
|
||||
return submodule;
|
||||
}
|
||||
|
||||
static StructRNA *pyrna_struct_as_srna(PyObject *self)
|
||||
StructRNA *pyrna_struct_as_srna(PyObject *self)
|
||||
{
|
||||
BPy_StructRNA *py_srna = NULL;
|
||||
StructRNA *srna;
|
||||
@@ -3395,7 +3598,7 @@ static StructRNA *pyrna_struct_as_srna(PyObject *self)
|
||||
/* Orphan functions, not sure where they should go */
|
||||
/* get the srna for methods attached to types */
|
||||
/* */
|
||||
static StructRNA *srna_from_self(PyObject *self)
|
||||
StructRNA *srna_from_self(PyObject *self)
|
||||
{
|
||||
/* a bit sloppy but would cause a very confusing bug if
|
||||
* an error happened to be set here */
|
||||
@@ -3937,31 +4140,26 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun
|
||||
item = PyObject_GetAttrString(py_class, identifier);
|
||||
|
||||
if (item==NULL) {
|
||||
|
||||
/* 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) {
|
||||
Py_DECREF(item); /* no need to keep a ref, the class owns it */
|
||||
#define BPY_REPLACEMENT_STRING(rna_attr, py_attr) \
|
||||
if(strcmp(identifier, rna_attr) == 0) { \
|
||||
item= PyObject_GetAttrString(py_class, py_attr); \
|
||||
if(item && item != Py_None) { \
|
||||
if(pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class error:") != 0) { \
|
||||
Py_DECREF(item); \
|
||||
return -1; \
|
||||
} \
|
||||
} \
|
||||
Py_XDECREF(item); \
|
||||
} \
|
||||
|
||||
if(pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class error:") != 0)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if(strcmp(identifier, "bl_label") == 0) {
|
||||
item= PyObject_GetAttrString(py_class, "__doc__");
|
||||
BPY_REPLACEMENT_STRING("bl_idname", "__name__");
|
||||
BPY_REPLACEMENT_STRING("bl_description", "__doc__");
|
||||
|
||||
if(item) {
|
||||
Py_DECREF(item); /* no need to keep a ref, the class owns it */
|
||||
#undef BPY_REPLACEMENT_STRING
|
||||
|
||||
if(pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class error:") != 0)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (item == NULL && (((flag & PROP_REGISTER_OPTIONAL) != PROP_REGISTER_OPTIONAL))) {
|
||||
PyErr_Format( PyExc_AttributeError, "expected %.200s, %.200s class to have an \"%.200s\" attribute", class_type, py_class_name, identifier);
|
||||
return -1;
|
||||
@@ -3982,15 +4180,18 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun
|
||||
|
||||
extern void BPY_update_modules( void ); //XXX temp solution
|
||||
|
||||
/* TODO - multiple return values like with rna functions */
|
||||
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;
|
||||
PropertyRNA *parm;
|
||||
ParameterIterator iter;
|
||||
PointerRNA funcptr;
|
||||
void *retdata= NULL;
|
||||
int err= 0, i, flag;
|
||||
int err= 0, i, flag, ret_len=0;
|
||||
|
||||
PropertyRNA *pret_single= NULL;
|
||||
void *retdata_single= NULL;
|
||||
|
||||
PyGILState_STATE gilstate;
|
||||
|
||||
@@ -4016,10 +4217,9 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
|
||||
|
||||
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);
|
||||
// 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)); /* first arg is included in 'item' */
|
||||
@@ -4030,9 +4230,16 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
|
||||
/* parse function parameters */
|
||||
for (i= 1; iter.valid; RNA_parameter_list_next(&iter)) {
|
||||
parm= iter.parm;
|
||||
flag= RNA_property_flag(parm);
|
||||
|
||||
/* only useful for single argument returns, we'll need another list loop for multiple */
|
||||
if (flag & PROP_RETURN) {
|
||||
ret_len++;
|
||||
if (pret_single==NULL) {
|
||||
pret_single= parm;
|
||||
retdata_single= iter.data;
|
||||
}
|
||||
|
||||
if (parm==pret) {
|
||||
retdata= iter.data;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -4043,6 +4250,7 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
|
||||
|
||||
ret = PyObject_Call(item, args, NULL);
|
||||
|
||||
RNA_parameter_list_end(&iter);
|
||||
Py_DECREF(item);
|
||||
Py_DECREF(args);
|
||||
}
|
||||
@@ -4062,8 +4270,39 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
|
||||
err= -1;
|
||||
}
|
||||
else {
|
||||
if(retdata)
|
||||
err= pyrna_py_to_prop(&funcptr, pret, retdata, ret, "calling class function:");
|
||||
if(ret_len==1) {
|
||||
err= pyrna_py_to_prop(&funcptr, pret_single, retdata_single, ret, "calling class function:");
|
||||
}
|
||||
else if (ret_len > 1) {
|
||||
|
||||
if(PyTuple_Check(ret)==0) {
|
||||
PyErr_Format(PyExc_RuntimeError, "expected class %.200s, function %.200s to return a tuple of size %d.", RNA_struct_identifier(ptr->type), RNA_function_identifier(func), ret_len);
|
||||
err= -1;
|
||||
}
|
||||
else if (PyTuple_GET_SIZE(ret) != ret_len) {
|
||||
PyErr_Format(PyExc_RuntimeError, "class %.200s, function %.200s to returned %d items, expected %d.", RNA_struct_identifier(ptr->type), RNA_function_identifier(func), PyTuple_GET_SIZE(ret), ret_len);
|
||||
err= -1;
|
||||
}
|
||||
else {
|
||||
|
||||
RNA_parameter_list_begin(parms, &iter);
|
||||
|
||||
/* parse function parameters */
|
||||
for (i= 0; iter.valid; RNA_parameter_list_next(&iter)) {
|
||||
parm= iter.parm;
|
||||
flag= RNA_property_flag(parm);
|
||||
|
||||
/* only useful for single argument returns, we'll need another list loop for multiple */
|
||||
if (flag & PROP_RETURN) {
|
||||
err= pyrna_py_to_prop(&funcptr, parm, iter.data, PyTuple_GET_ITEM(ret, i++), "calling class function:");
|
||||
if(err)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RNA_parameter_list_end(&iter);
|
||||
}
|
||||
}
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,9 @@ typedef struct {
|
||||
/* cheap trick */
|
||||
#define BPy_BaseTypeRNA BPy_PropertyRNA
|
||||
|
||||
StructRNA *srna_from_self(PyObject *self);
|
||||
StructRNA *pyrna_struct_as_srna(PyObject *self);
|
||||
|
||||
void BPY_rna_init( void );
|
||||
PyObject *BPY_rna_module( void );
|
||||
void BPY_update_rna_module( void );
|
||||
|
||||
@@ -35,95 +35,6 @@ bContext* __py_context = NULL;
|
||||
bContext* BPy_GetContext(void) { return __py_context; };
|
||||
void BPy_SetContext(bContext *C) { __py_context= C; };
|
||||
|
||||
|
||||
PyObject *BPY_flag_to_list(struct BPY_flag_def *flagdef, int flag)
|
||||
{
|
||||
PyObject *list = PyList_New(0);
|
||||
|
||||
PyObject *item;
|
||||
BPY_flag_def *fd;
|
||||
|
||||
fd= flagdef;
|
||||
while(fd->name) {
|
||||
if (fd->flag & flag) {
|
||||
item = PyUnicode_FromString(fd->name);
|
||||
PyList_Append(list, item);
|
||||
Py_DECREF(item);
|
||||
}
|
||||
fd++;
|
||||
}
|
||||
|
||||
return list;
|
||||
|
||||
}
|
||||
|
||||
static char *bpy_flag_error_str(BPY_flag_def *flagdef)
|
||||
{
|
||||
BPY_flag_def *fd= flagdef;
|
||||
DynStr *dynstr= BLI_dynstr_new();
|
||||
char *cstring;
|
||||
|
||||
BLI_dynstr_append(dynstr, "Error converting a sequence of strings into a flag.\n\tExpected only these strings...\n\t");
|
||||
|
||||
while(fd->name) {
|
||||
BLI_dynstr_appendf(dynstr, fd!=flagdef?", '%s'":"'%s'", fd->name);
|
||||
fd++;
|
||||
}
|
||||
|
||||
cstring = BLI_dynstr_get_cstring(dynstr);
|
||||
BLI_dynstr_free(dynstr);
|
||||
return cstring;
|
||||
}
|
||||
|
||||
int BPY_flag_from_seq(BPY_flag_def *flagdef, PyObject *seq, int *flag)
|
||||
{
|
||||
int i, error_val= 0;
|
||||
char *cstring;
|
||||
PyObject *item;
|
||||
BPY_flag_def *fd;
|
||||
*flag = 0;
|
||||
|
||||
if (PySequence_Check(seq)) {
|
||||
i= PySequence_Length(seq);
|
||||
|
||||
while(i--) {
|
||||
item = PySequence_ITEM(seq, i);
|
||||
cstring= _PyUnicode_AsString(item);
|
||||
if(cstring) {
|
||||
fd= flagdef;
|
||||
while(fd->name) {
|
||||
if (strcmp(cstring, fd->name) == 0) {
|
||||
(*flag) |= fd->flag;
|
||||
break;
|
||||
}
|
||||
fd++;
|
||||
}
|
||||
if (fd->name==NULL) { /* could not find a match */
|
||||
error_val= 1;
|
||||
}
|
||||
} else {
|
||||
error_val= 1;
|
||||
}
|
||||
Py_DECREF(item);
|
||||
}
|
||||
}
|
||||
else {
|
||||
error_val= 1;
|
||||
}
|
||||
|
||||
if (*flag == 0)
|
||||
error_val = 1;
|
||||
|
||||
if (error_val) {
|
||||
char *buf = bpy_flag_error_str(flagdef);
|
||||
PyErr_SetString(PyExc_AttributeError, buf);
|
||||
MEM_freeN(buf);
|
||||
return -1; /* error value */
|
||||
}
|
||||
|
||||
return 0; /* ok */
|
||||
}
|
||||
|
||||
/* for debugging */
|
||||
void PyObSpit(char *name, PyObject *var) {
|
||||
fprintf(stderr, "<%s> : ", name);
|
||||
|
||||
@@ -36,16 +36,6 @@
|
||||
struct EnumPropertyItem;
|
||||
struct ReportList;
|
||||
|
||||
/* for internal use only, so python can interchange a sequence of strings with flags */
|
||||
typedef struct BPY_flag_def {
|
||||
const char *name;
|
||||
int flag;
|
||||
} BPY_flag_def;
|
||||
|
||||
|
||||
PyObject *BPY_flag_to_list(BPY_flag_def *flagdef, int flag);
|
||||
int BPY_flag_from_seq(BPY_flag_def *flagdef, PyObject *seq, int *flag);
|
||||
|
||||
void PyObSpit(char *name, PyObject *var);
|
||||
void PyLineSpit(void);
|
||||
void BPY_getFileAndNum(char **filename, int *lineno);
|
||||
|
||||
@@ -23,10 +23,10 @@ Usage,
|
||||
run this script from blenders root path once you have compiled blender
|
||||
./blender.bin -b -P /b/source/blender/python/sphinx_doc_gen.py
|
||||
|
||||
This will generate python files in "./source/blender/python/doc/bpy/sphinx-in"
|
||||
This will generate python files in "./source/blender/python/doc/sphinx-in"
|
||||
Generate html docs by running...
|
||||
|
||||
sphinx-build source/blender/python/doc/bpy/sphinx-in source/blender/python/doc/bpy/sphinx-out
|
||||
sphinx-build source/blender/python/doc/sphinx-in source/blender/python/doc/sphinx-out
|
||||
'''
|
||||
|
||||
# if you dont have graphvis installed ommit the --graph arg.
|
||||
@@ -115,7 +115,7 @@ def rna2sphinx(BASEPATH):
|
||||
#if not struct.identifier.startswith("Sc") and not struct.identifier.startswith("I"):
|
||||
# return
|
||||
|
||||
#if not struct.identifier.startswith("Bone"):
|
||||
#if not struct.identifier == "Object":
|
||||
# return
|
||||
|
||||
filepath = os.path.join(BASEPATH, "bpy.types.%s.rst" % struct.identifier)
|
||||
@@ -182,8 +182,17 @@ def rna2sphinx(BASEPATH):
|
||||
for prop in func.args:
|
||||
write_param(" ", fw, prop)
|
||||
|
||||
if func.return_value:
|
||||
write_param(" ", fw, func.return_value, is_return=True)
|
||||
if len(func.return_values) == 1:
|
||||
write_param(" ", fw, func.return_values[0], is_return=True)
|
||||
else: # multiple return values
|
||||
fw(" :return (%s):\n" % ", ".join([prop.identifier for prop in func.return_values]))
|
||||
for prop in func.return_values:
|
||||
type_descr = prop.get_type_description(as_arg=True, class_fmt=":class:`%s`")
|
||||
descr = prop.description
|
||||
if not descr:
|
||||
descr = prop.name
|
||||
fw(" `%s`, %s, %s\n\n" % (prop.identifier, descr, type_descr))
|
||||
|
||||
fw("\n")
|
||||
|
||||
|
||||
@@ -265,9 +274,9 @@ if __name__ == '__main__':
|
||||
print("\nError, this script must run from inside blender2.5")
|
||||
print(script_help_msg)
|
||||
else:
|
||||
# os.system("rm source/blender/python/doc/bpy/sphinx-in/*.rst")
|
||||
# os.system("rm -rf source/blender/python/doc/bpy/sphinx-out/*")
|
||||
rna2sphinx('source/blender/python/doc/bpy/sphinx-in')
|
||||
# os.system("rm source/blender/python/doc/sphinx-in/*.rst")
|
||||
# os.system("rm -rf source/blender/python/doc/sphinx-out/*")
|
||||
rna2sphinx('source/blender/python/doc/sphinx-in')
|
||||
|
||||
import sys
|
||||
sys.exit()
|
||||
|
||||
Reference in New Issue
Block a user