}
}
+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)
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)
+{
+ wmOperatorType *ot;
+ wmOperatorTypeMacro *otmacro;
+ PyObject *macro;
+ PyObject *item;
+ PointerRNA ptr_otmacro;
+
+ char *opname;
+ char *macroname;
+
+ if (!PyArg_ParseTuple(args, "Os:_bpy.ops.macro_define", ¯o, &opname))
+ return NULL;
+
+ if (WM_operatortype_exists(opname) == NULL) {
+ PyErr_Format(PyExc_ValueError, "Macro Define: '%s' is not a valid operator id", opname);
+ return NULL;
+ }
+
+ /* 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);
+
+ ot = WM_operatortype_exists(macroname);
+
+ if (!ot) {
+ PyErr_Format(PyExc_ValueError, "Macro Define: '%s' is not a valid macro or hasn't been registered yet", macroname);
+ return NULL;
+ }
+
+ otmacro = WM_operatortype_macro_define(ot, opname);
+
+ RNA_pointer_create(NULL, &RNA_OperatorTypeMacro, otmacro, &ptr_otmacro);
+
+ return pyrna_struct_CreatePyObject(&ptr_otmacro);
+}
+
+
PyObject *PYOP_wrap_remove(PyObject *self, PyObject *value)
{
PyObject *py_class;