Macro registration using the normal rna registration methods (like operators).
authorMartin Poirier <theeth@yahoo.com>
Wed, 30 Dec 2009 22:14:32 +0000 (22:14 +0000)
committerMartin Poirier <theeth@yahoo.com>
Wed, 30 Dec 2009 22:14:32 +0000 (22:14 +0000)
bpy.types.register(MacroClass)

instead of

bpy.ops.add_macro(MacroClass)

The rest is unchanged.

Also remove some now unused code for the old registration methods (there's still some remaining).

release/scripts/modules/bpy/ops.py
source/blender/makesrna/RNA_access.h
source/blender/makesrna/intern/rna_internal.h
source/blender/makesrna/intern/rna_wm.c
source/blender/makesrna/intern/rna_wm_api.c
source/blender/python/intern/bpy_operator.c
source/blender/python/intern/bpy_operator_wrap.c
source/blender/python/intern/bpy_rna.c
source/blender/python/intern/bpy_rna.h
source/blender/windowmanager/intern/wm_operators.c

index 268189b2db49b1bd80bccd83a5ca3ee997235d9c..ba5eeff7a0e03d1254037fca887f36f8911c85de 100644 (file)
@@ -23,7 +23,6 @@ from _bpy import ops as ops_module
 
 # op_add = ops_module.add
 op_remove = ops_module.remove
-op_add_macro = ops_module.add_macro
 op_dir = ops_module.dir
 op_call = ops_module.call
 op_as_string = ops_module.as_string
@@ -57,12 +56,6 @@ class bpy_ops(object):
             raise AttributeError(module)
         return bpy_ops_submodule(module)
 
-    def add(self, pyop):
-        op_add(pyop)
-
-    def add_macro(self, pyop):
-        op_add_macro(pyop)
-
     def remove(self, pyop):
         op_remove(pyop)
 
index 2528af6b57aa1047978d52bb8f488400ec398004..908d832daf17aa732708e06a3093b2c9134f288d 100644 (file)
@@ -319,6 +319,7 @@ extern StructRNA RNA_Object;
 extern StructRNA RNA_ObjectBase;
 extern StructRNA RNA_ObstacleFluidSettings;
 extern StructRNA RNA_Operator;
+extern StructRNA RNA_Macro;
 extern StructRNA RNA_OperatorFileListElement;
 extern StructRNA RNA_OperatorMousePath;
 extern StructRNA RNA_OperatorProperties;
index 5bb3c82395daadb848e6eb3c4c25f4ddff91dd3d..22b8388f6931c42f9c409923387b768f8c88cfd6 100644 (file)
@@ -211,6 +211,7 @@ void RNA_api_armature_edit_bone(StructRNA *srna);
 void RNA_api_drivers(StructRNA *srna);
 void RNA_api_image(struct StructRNA *srna);
 void RNA_api_operator(struct StructRNA *srna);
+void RNA_api_macro(struct StructRNA *srna);
 void RNA_api_keyconfig(struct StructRNA *srna);
 void RNA_api_keyingset(struct StructRNA *srna);
 void RNA_api_keymap(struct StructRNA *srna);
index 7abba3c004a535d1aa1475d136011d8b442e7525..e68681919eb4cef52d749b1406ef8af4a6e22637 100644 (file)
@@ -692,6 +692,7 @@ static void operator_draw(bContext *C, wmOperator *op)
 }
 
 void operator_wrapper(wmOperatorType *ot, void *userdata);
+void macro_wrapper(wmOperatorType *ot, void *userdata);
 
 static char _operator_idname[OP_MAX_TYPENAME];
 static char _operator_name[OP_MAX_TYPENAME];
@@ -763,12 +764,84 @@ static StructRNA *rna_Operator_register(const bContext *C, ReportList *reports,
        return dummyot.ext.srna;
 }
 
+
+static StructRNA *rna_MacroOperator_register(const bContext *C, ReportList *reports, void *data, const char *identifier, StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+       wmOperatorType dummyot = {0};
+       wmOperator dummyop= {0};
+       PointerRNA dummyotr;
+       int have_function[4];
+
+       /* setup dummy operator & operator type to store static properties in */
+       dummyop.type= &dummyot;
+       dummyot.idname= _operator_idname; /* only assigne the pointer, string is NULL'd */
+       dummyot.name= _operator_name; /* only assigne the pointer, string is NULL'd */
+       dummyot.description= _operator_descr; /* only assigne the pointer, string is NULL'd */
+       RNA_pointer_create(NULL, &RNA_Macro, &dummyop, &dummyotr);
+
+       /* validate the python class */
+       if(validate(&dummyotr, data, have_function) != 0)
+               return NULL;
+
+       {       /* convert foo.bar to FOO_OT_bar
+                * allocate the description and the idname in 1 go */
+               int idlen = strlen(_operator_idname) + 4;
+               int namelen = strlen(_operator_name) + 1;
+               int desclen = strlen(_operator_descr) + 1;
+               char *ch, *ch_arr;
+               ch_arr= ch= MEM_callocN(sizeof(char) * (idlen + namelen + desclen), "_operator_idname"); /* 2 terminators and 3 to convert a.b -> A_OT_b */
+               WM_operator_bl_idname(ch, _operator_idname); /* convert the idname from python */
+               dummyot.idname= ch;
+               ch += idlen;
+               strcpy(ch, _operator_name);
+               dummyot.name = ch;
+               ch += namelen;
+               strcpy(ch, _operator_descr);
+               dummyot.description = ch;
+       }
+
+       if(strlen(identifier) >= sizeof(dummyop.idname)) {
+               BKE_reportf(reports, RPT_ERROR, "registering operator class: '%s' is too long, maximum length is %d.", identifier, sizeof(dummyop.idname));
+               return NULL;
+       }
+
+       /* check if we have registered this operator type before, and remove it */
+       {
+               wmOperatorType *ot= WM_operatortype_exists(dummyot.idname);
+               if(ot && ot->ext.srna)
+                       rna_Operator_unregister(C, ot->ext.srna);
+       }
+
+       /* create a new menu type */
+       dummyot.ext.srna= RNA_def_struct(&BLENDER_RNA, dummyot.idname, "Operator");
+       dummyot.ext.data= data;
+       dummyot.ext.call= call;
+       dummyot.ext.free= free;
+
+       dummyot.pyop_poll=      (have_function[0])? operator_poll: NULL;
+       dummyot.ui=                     (have_function[3])? operator_draw: NULL;
+
+       WM_operatortype_append_macro_ptr(macro_wrapper, (void *)&dummyot);
+
+       /* update while blender is running */
+       if(C)
+               WM_main_add_notifier(NC_SCREEN|NA_EDITED, NULL);
+
+       return dummyot.ext.srna;
+}
+
 static StructRNA* rna_Operator_refine(PointerRNA *opr)
 {
        wmOperator *op= (wmOperator*)opr->data;
        return (op->type && op->type->ext.srna)? op->type->ext.srna: &RNA_Operator;
 }
 
+static StructRNA* rna_MacroOperator_refine(PointerRNA *opr)
+{
+       wmOperator *op= (wmOperator*)opr->data;
+       return (op->type && op->type->ext.srna)? op->type->ext.srna: &RNA_Macro;
+}
+
 #else
 
 static void rna_def_operator(BlenderRNA *brna)
@@ -832,6 +905,8 @@ static void rna_def_macro_operator(BlenderRNA *brna)
        srna= RNA_def_struct(brna, "Macro", NULL);
        RNA_def_struct_ui_text(srna, "Macro Operator", "Storage of a macro operator being executed, or registered after execution.");
        RNA_def_struct_sdna(srna, "wmOperator");
+       RNA_def_struct_refine_func(srna, "rna_MacroOperator_refine");
+       RNA_def_struct_register_funcs(srna, "rna_MacroOperator_register", "rna_Operator_unregister");
 
        prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
        RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@ -844,6 +919,27 @@ static void rna_def_macro_operator(BlenderRNA *brna)
        RNA_def_property_struct_type(prop, "OperatorProperties");
        RNA_def_property_ui_text(prop, "Properties", "");
        RNA_def_property_pointer_funcs(prop, "rna_Operator_properties_get", NULL, NULL);
+
+       /* Registration */
+       prop= RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
+       RNA_def_property_string_sdna(prop, NULL, "type->idname");
+       RNA_def_property_string_maxlength(prop, OP_MAX_TYPENAME); /* else it uses the pointer size! */
+       RNA_def_property_flag(prop, PROP_REGISTER);
+
+       prop= RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
+       RNA_def_property_string_sdna(prop, NULL, "type->name");
+       RNA_def_property_string_maxlength(prop, 1024); /* else it uses the pointer size! */
+       RNA_def_property_flag(prop, PROP_REGISTER);
+
+       prop= RNA_def_property(srna, "bl_register", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "type->flag", OPTYPE_REGISTER);
+       RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+
+       prop= RNA_def_property(srna, "bl_undo", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "type->flag", OPTYPE_UNDO);
+       RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+
+       RNA_api_macro(srna);
 }
 
 static void rna_def_operator_type_macro(BlenderRNA *brna)
index 1afedf1c6a637b3aa5ecc4a6eab012ea76bd2dd6..9ed6046ecd06c67fa4c14c7f0fe448f7a2cf766a 100644 (file)
@@ -237,6 +237,35 @@ void RNA_api_operator(StructRNA *srna)
        RNA_def_pointer(func, "context", "Context", "", "");
 }
 
+void RNA_api_macro(StructRNA *srna)
+{
+       FunctionRNA *func;
+       PropertyRNA *parm;
+
+       /* utility, not for registering */
+       func= RNA_def_function(srna, "report", "rna_Operator_report");
+       parm= RNA_def_enum(func, "type", wm_report_items, 0, "Type", "");
+       RNA_def_property_flag(parm, PROP_REQUIRED|PROP_ENUM_FLAG);
+       parm= RNA_def_string(func, "message", "", 0, "Report Message", "");
+       RNA_def_property_flag(parm, PROP_REQUIRED);
+
+
+       /* Registration */
+
+       /* poll */
+       func= RNA_def_function(srna, "poll", NULL);
+       RNA_def_function_ui_description(func, "Test if the operator can be called or not.");
+       RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+       RNA_def_function_return(func, RNA_def_boolean(func, "visible", 1, "", ""));
+       RNA_def_pointer(func, "context", "Context", "", "");
+
+       /* draw */
+       func= RNA_def_function(srna, "draw", NULL);
+       RNA_def_function_ui_description(func, "Draw function for the operator.");
+       RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+       RNA_def_pointer(func, "context", "Context", "", "");
+}
+
 void RNA_api_keyconfig(StructRNA *srna)
 {
        FunctionRNA *func;
index 101f3619da4fb8e9575aee36ce89b2c5950c451d..e7cce8e781271488b87b6c11c51b4e5c5fcea962 100644 (file)
@@ -245,7 +245,7 @@ PyObject *BPY_operator_module( void )
        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_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};
 
@@ -257,7 +257,7 @@ PyObject *BPY_operator_module( void )
        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, "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) );
 
index b3f281b4b3fccf9701021e32a5b9e711cb2a2bd8..0a468f2de735c4fa27df118e9446d55354362ef9 100644 (file)
@@ -299,7 +299,47 @@ void operator_wrapper(wmOperatorType *ot, void *userdata)
        }
 }
 
+void macro_wrapper(wmOperatorType *ot, void *userdata)
+{
+       wmOperatorType *data = (wmOperatorType *)userdata;
 
+       /* 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;
+
+       RNA_struct_blender_type_set(ot->ext.srna, ot);
+
+
+       /* Can't use this because it returns a dict proxy
+        *
+        * item= PyObject_GetAttrString(py_class, "__dict__");
+        */
+       {
+               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();
+                               PyErr_Clear();
+
+                       }
+               }
+               else {
+                       PyErr_Clear();
+               }
+       }
+}
 
 
 
@@ -588,11 +628,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", &macro, &opname))
                return NULL;
@@ -603,21 +643,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);
 
index 7c4e49e93e301cbd9ce0b89772a94c31c0ee459c..c8f0a29ca64e6e161ab2de8723edcdc75a11e58f 100644 (file)
@@ -244,8 +244,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;
@@ -3354,7 +3352,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 +3393,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 */
index 37f6af367268e24e1f60f9cee523c0c1c8dfc111..74a16b43dc1a9d48feba49f39a7f2af93623ad60 100644 (file)
@@ -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 );
index f7054af944349391efeb687bf1015f821ec55b19..e9bf1be5861a1bb0040a1ec3daaa6dbf2fdb0a17 100644 (file)
@@ -360,6 +360,7 @@ void WM_operatortype_append_macro_ptr(void (*opfunc)(wmOperatorType*, void*), vo
        ot= MEM_callocN(sizeof(wmOperatorType), "operatortype");
        ot->srna= RNA_def_struct(&BLENDER_RNA, "", "OperatorProperties");
 
+       ot->flag= OPTYPE_MACRO;
        ot->exec= wm_macro_exec;
        ot->invoke= wm_macro_invoke;
        ot->modal= wm_macro_modal;