[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [25140] trunk/blender: Support for the C Macro system in Python.

Martin Poirier theeth at yahoo.com
Sat Dec 5 20:27:26 CET 2009


Revision: 25140
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=25140
Author:   theeth
Date:     2009-12-05 20:27:26 +0100 (Sat, 05 Dec 2009)

Log Message:
-----------
Support for the C Macro system in Python.

Basic definition works like a python operator but you derive from "bpy.types.Macro" instead.
Operators are added to the macro after it has been added with "bpy.ops.add_macro" through the class method "define" which takes an operator id and returns an OperatorMacroType (new RNA type) for which properties can then be defined to be passed to the operator when run.

Example: http://blenderartists.org/~theeth/bf/macro.py

Using this system, it should be easy to add an operator to the console that converts selected lines into a macro or even a more generic record macro system.

Modified Paths:
--------------
    trunk/blender/release/scripts/modules/bpy/ops.py
    trunk/blender/release/scripts/modules/bpy_types.py
    trunk/blender/source/blender/makesrna/RNA_access.h
    trunk/blender/source/blender/makesrna/intern/rna_wm.c
    trunk/blender/source/blender/python/intern/bpy_operator.c
    trunk/blender/source/blender/python/intern/bpy_operator_wrap.c
    trunk/blender/source/blender/python/intern/bpy_operator_wrap.h
    trunk/blender/source/blender/windowmanager/WM_api.h
    trunk/blender/source/blender/windowmanager/intern/wm_operators.c
    trunk/blender/source/blenderplayer/bad_level_call_stubs/stubs.c

Modified: trunk/blender/release/scripts/modules/bpy/ops.py
===================================================================
--- trunk/blender/release/scripts/modules/bpy/ops.py	2009-12-05 19:26:28 UTC (rev 25139)
+++ trunk/blender/release/scripts/modules/bpy/ops.py	2009-12-05 19:27:26 UTC (rev 25140)
@@ -23,6 +23,7 @@
 
 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
@@ -58,6 +59,9 @@
 
     def add(self, pyop):
         op_add(pyop)
+    
+    def add_macro(self, pyop):
+        op_add_macro(pyop)
 
     def remove(self, pyop):
         op_remove(pyop)

Modified: trunk/blender/release/scripts/modules/bpy_types.py
===================================================================
--- trunk/blender/release/scripts/modules/bpy_types.py	2009-12-05 19:26:28 UTC (rev 25139)
+++ trunk/blender/release/scripts/modules/bpy_types.py	2009-12-05 19:27:26 UTC (rev 25140)
@@ -252,6 +252,13 @@
 class Operator(StructRNA, metaclass=OrderedMeta):
     pass
 
+class Macro(StructRNA, metaclass=OrderedMeta):
+    # bpy_types is imported before ops is defined
+    # so we have to do a local import on each run
+    @classmethod
+    def define(self, opname):
+        from _bpy import ops
+        return ops.macro_define(self, opname)
 
 class Menu(StructRNA):
     

Modified: trunk/blender/source/blender/makesrna/RNA_access.h
===================================================================
--- trunk/blender/source/blender/makesrna/RNA_access.h	2009-12-05 19:26:28 UTC (rev 25139)
+++ trunk/blender/source/blender/makesrna/RNA_access.h	2009-12-05 19:27:26 UTC (rev 25140)
@@ -323,6 +323,7 @@
 extern StructRNA RNA_OperatorMousePath;
 extern StructRNA RNA_OperatorProperties;
 extern StructRNA RNA_OperatorStrokeElement;
+extern StructRNA RNA_OperatorTypeMacro;
 extern StructRNA RNA_OrController;
 extern StructRNA RNA_OutflowFluidSettings;
 extern StructRNA RNA_PackedFile;

Modified: trunk/blender/source/blender/makesrna/intern/rna_wm.c
===================================================================
--- trunk/blender/source/blender/makesrna/intern/rna_wm.c	2009-12-05 19:26:28 UTC (rev 25139)
+++ trunk/blender/source/blender/makesrna/intern/rna_wm.c	2009-12-05 19:27:26 UTC (rev 25140)
@@ -309,6 +309,12 @@
 	return rna_pointer_inherit_refine(ptr, op->type->srna, op->properties);
 }
 
+static PointerRNA rna_OperatorTypeMacro_properties_get(PointerRNA *ptr)
+{
+	wmOperatorTypeMacro *otmacro= (wmOperatorTypeMacro*)ptr->data;
+	wmOperatorType *ot = WM_operatortype_exists(otmacro->idname);
+	return rna_pointer_inherit_refine(ptr, ot->srna, otmacro->properties);
+}
 
 static void rna_Event_ascii_get(PointerRNA *ptr, char *value)
 {
@@ -593,6 +599,50 @@
 	RNA_def_struct_idproperties_func(srna, "rna_OperatorProperties_idproperties");
 }
 
+static void rna_def_macro_operator(BlenderRNA *brna)
+{
+	StructRNA *srna;
+	PropertyRNA *prop;
+
+	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");
+
+	prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+	RNA_def_property_string_funcs(prop, "rna_Operator_name_get", "rna_Operator_name_length", NULL);
+	RNA_def_property_ui_text(prop, "Name", "");
+	RNA_def_struct_name_property(srna, prop);
+
+	prop= RNA_def_property(srna, "properties", PROP_POINTER, PROP_NONE);
+	RNA_def_property_flag(prop, PROP_NEVER_NULL);
+	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);
+}
+
+static void rna_def_operator_type_macro(BlenderRNA *brna)
+{
+	StructRNA *srna;
+	PropertyRNA *prop;
+
+	srna= RNA_def_struct(brna, "OperatorTypeMacro", NULL);
+	RNA_def_struct_ui_text(srna, "OperatorTypeMacro", "Storage of a sub operator in a macro after it has been added.");
+	RNA_def_struct_sdna(srna, "wmOperatorTypeMacro");
+
+//	prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+//	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+//	RNA_def_property_string_sdna(prop, NULL, "idname");
+//	RNA_def_property_ui_text(prop, "Name", "Name of the sub operator.");
+//	RNA_def_struct_name_property(srna, prop);
+
+	prop= RNA_def_property(srna, "properties", PROP_POINTER, PROP_NONE);
+	RNA_def_property_flag(prop, PROP_NEVER_NULL);
+	RNA_def_property_struct_type(prop, "OperatorProperties");
+	RNA_def_property_ui_text(prop, "Properties", "");
+	RNA_def_property_pointer_funcs(prop, "rna_OperatorTypeMacro_properties_get", NULL, NULL);
+}
+
 static void rna_def_operator_utils(BlenderRNA *brna)
 {
 	StructRNA *srna;
@@ -911,6 +961,8 @@
 	rna_def_operator(brna);
 	rna_def_operator_utils(brna);
 	rna_def_operator_filelist_element(brna);
+	rna_def_macro_operator(brna);
+	rna_def_operator_type_macro(brna);
 	rna_def_event(brna);
 	rna_def_window(brna);
 	rna_def_windowmanager(brna);

Modified: trunk/blender/source/blender/python/intern/bpy_operator.c
===================================================================
--- trunk/blender/source/blender/python/intern/bpy_operator.c	2009-12-05 19:26:28 UTC (rev 25139)
+++ trunk/blender/source/blender/python/intern/bpy_operator.c	2009-12-05 19:27:26 UTC (rev 25140)
@@ -60,7 +60,7 @@
 	if (!PyArg_ParseTuple(args, "sO|O!i:_bpy.ops.call", &opname, &context_dict, &PyDict_Type, &kw, &context))
 		return NULL;
 
-	ot= WM_operatortype_find(opname, TRUE);
+	ot= WM_operatortype_exists(opname);
 
 	if (ot == NULL) {
 		PyErr_Format( PyExc_SystemError, "_bpy.ops.call: operator \"%s\"could not be found", opname);
@@ -245,6 +245,8 @@
 	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");
@@ -255,6 +257,8 @@
 	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;

Modified: trunk/blender/source/blender/python/intern/bpy_operator_wrap.c
===================================================================
--- trunk/blender/source/blender/python/intern/bpy_operator_wrap.c	2009-12-05 19:26:28 UTC (rev 25139)
+++ trunk/blender/source/blender/python/intern/bpy_operator_wrap.c	2009-12-05 19:27:26 UTC (rev 25140)
@@ -342,7 +342,81 @@
 	}
 }
 
+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)
 {	
@@ -407,6 +481,116 @@
 	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) {

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list