2.5 Python
Merging changes made by Arystanbek in the soc-2009-kazanbas branch, plus some things modified and added by me. * Operator exec is called execute in python now, due to conflicts with python exec keyword. * Operator invoke/execute now get context argument. * Fix crash executing operators due to bpy_import_main_set not being set with Main pointer. * The bpy.props module now has the FloatProperty/IntProperty/ StringProperty/BoolProperty functions to define RNA properties for operators. * Operators now have an __operator__ property to get the actual RNA operator pointers, this is only temporary though. * bpy.ops.add now allows the operator to be already registered, it will simply overwrite the existing one. * Both the ui and io directories are now scanned and run on startup.
This commit is contained in:
@@ -40,6 +40,8 @@
|
||||
#include "bpy_compat.h"
|
||||
#include "bpy_util.h"
|
||||
|
||||
#include "../generic/bpy_internal_import.h" // our own imports
|
||||
|
||||
#define PYOP_ATTR_PROP "__props__"
|
||||
#define PYOP_ATTR_UINAME "__label__"
|
||||
#define PYOP_ATTR_IDNAME "__name__" /* use pythons class name */
|
||||
@@ -177,9 +179,12 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
|
||||
PyObject *ret= NULL, *py_class_instance, *item= NULL;
|
||||
int ret_flag= (mode==PYOP_POLL ? 0:OPERATOR_CANCELLED);
|
||||
PointerRNA ptr_context;
|
||||
PyObject *py_context;
|
||||
PointerRNA ptr_operator;
|
||||
PyObject *py_operator;
|
||||
|
||||
PyGILState_STATE gilstate = PyGILState_Ensure();
|
||||
|
||||
bpy_import_main_set(CTX_data_main(C));
|
||||
|
||||
BPY_update_modules(); // XXX - the RNA pointers can change so update before running, would like a nicer solutuon for this.
|
||||
|
||||
@@ -213,20 +218,29 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
|
||||
|
||||
RNA_property_collection_end(&iter);
|
||||
}
|
||||
|
||||
|
||||
/* set operator pointer RNA as instance "__operator__" attribute */
|
||||
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) {
|
||||
item= PyObject_GetAttrString(py_class, "invoke");
|
||||
args = PyTuple_New(2);
|
||||
PyTuple_SET_ITEM(args, 1, pyop_dict_from_event(event));
|
||||
args = PyTuple_New(3);
|
||||
|
||||
// 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, pyop_dict_from_event(event));
|
||||
}
|
||||
else if (mode==PYOP_EXEC) {
|
||||
item= PyObject_GetAttrString(py_class, "exec");
|
||||
item= PyObject_GetAttrString(py_class, "execute");
|
||||
args = PyTuple_New(2);
|
||||
|
||||
RNA_pointer_create(NULL, &RNA_Context, C, &ptr_context);
|
||||
py_context = pyrna_struct_CreatePyObject(&ptr_context);
|
||||
PyTuple_SET_ITEM(args, 1, py_context);
|
||||
PyTuple_SET_ITEM(args, 1, pyrna_struct_CreatePyObject(&ptr_context));
|
||||
}
|
||||
else if (mode==PYOP_POLL) {
|
||||
item= PyObject_GetAttrString(py_class, "poll");
|
||||
@@ -258,7 +272,8 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
|
||||
} else if (BPY_flag_from_seq(pyop_ret_flags, ret, &ret_flag) == -1) {
|
||||
/* the returned value could not be converted into a flag */
|
||||
BPy_errors_to_report(op->reports);
|
||||
|
||||
|
||||
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
|
||||
@@ -271,7 +286,34 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
Py_DECREF(item);
|
||||
strcpy(class_name, _PyUnicode_AsString(item));
|
||||
|
||||
fprintf(stderr, "%s's %s returned %s\n", class_name, mode == PYOP_EXEC ? "execute" : "invoke", flag_str);
|
||||
}
|
||||
|
||||
PyGILState_Release(gilstate);
|
||||
bpy_import_main_set(NULL);
|
||||
|
||||
return ret_flag;
|
||||
}
|
||||
@@ -321,7 +363,7 @@ void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata)
|
||||
/* api callbacks, detailed checks dont on adding */
|
||||
if (PyObject_HasAttrString(py_class, "invoke"))
|
||||
ot->invoke= PYTHON_OT_invoke;
|
||||
if (PyObject_HasAttrString(py_class, "exec"))
|
||||
if (PyObject_HasAttrString(py_class, "execute"))
|
||||
ot->exec= PYTHON_OT_exec;
|
||||
if (PyObject_HasAttrString(py_class, "poll"))
|
||||
ot->poll= PYTHON_OT_poll;
|
||||
@@ -374,6 +416,7 @@ void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata)
|
||||
PyObject *PYOP_wrap_add(PyObject *self, PyObject *py_class)
|
||||
{
|
||||
PyObject *base_class, *item;
|
||||
wmOperatorType *ot;
|
||||
|
||||
|
||||
char *idname= NULL;
|
||||
@@ -384,8 +427,8 @@ PyObject *PYOP_wrap_add(PyObject *self, PyObject *py_class)
|
||||
{PYOP_ATTR_UINAME, 's', 0, BPY_CLASS_ATTR_OPTIONAL},
|
||||
{PYOP_ATTR_PROP, 'l', 0, BPY_CLASS_ATTR_OPTIONAL},
|
||||
{PYOP_ATTR_DESCRIPTION, 's', 0, BPY_CLASS_ATTR_NONE_OK},
|
||||
{"exec", 'f', 2, BPY_CLASS_ATTR_OPTIONAL},
|
||||
{"invoke", 'f', 2, BPY_CLASS_ATTR_OPTIONAL},
|
||||
{"execute", 'f', 2, BPY_CLASS_ATTR_OPTIONAL},
|
||||
{"invoke", 'f', 3, BPY_CLASS_ATTR_OPTIONAL},
|
||||
{"poll", 'f', 2, BPY_CLASS_ATTR_OPTIONAL},
|
||||
{NULL, 0, 0, 0}
|
||||
};
|
||||
@@ -404,9 +447,10 @@ PyObject *PYOP_wrap_add(PyObject *self, PyObject *py_class)
|
||||
Py_DECREF(item);
|
||||
idname = _PyUnicode_AsString(item);
|
||||
|
||||
if (WM_operatortype_find(idname)) {
|
||||
PyErr_Format( PyExc_AttributeError, "Operator alredy exists with this name \"%s\"", idname);
|
||||
return NULL;
|
||||
/* remove if it already exists */
|
||||
if ((ot=WM_operatortype_find(idname))) {
|
||||
Py_XDECREF((PyObject*)ot->pyop_data);
|
||||
WM_operatortype_remove(idname);
|
||||
}
|
||||
|
||||
/* If we have properties set, check its a list of dicts */
|
||||
|
||||
Reference in New Issue
Block a user