[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [18112] branches/blender2.5/blender/source /blender/python/intern: PyOperator invoke function now receives the wmEvent and default properties as 2 python dictionary args .

Campbell Barton ideasman42 at gmail.com
Sun Dec 28 09:41:52 CET 2008


Revision: 18112
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=18112
Author:   campbellbarton
Date:     2008-12-28 09:41:49 +0100 (Sun, 28 Dec 2008)

Log Message:
-----------
PyOperator invoke function now receives the wmEvent and default properties as 2 python dictionary args.
the Python invoke function can then edit the properties based on the event, once its finished the properties are copied back to the operator.

python exec and invoke functions can now return RUNNING_MODAL, CANCELLED, FINISHED, PASS_THROUGH flags

Still need to look into how python operators can make use of invoke/exec for a practical case. (Need to bring back the popup menu's)

Modified Paths:
--------------
    branches/blender2.5/blender/source/blender/python/intern/bpy_operator.c
    branches/blender2.5/blender/source/blender/python/intern/bpy_operator.h
    branches/blender2.5/blender/source/blender/python/intern/bpy_opwrapper.c

Added Paths:
-----------
    branches/blender2.5/blender/source/blender/python/intern/bpy_util.c
    branches/blender2.5/blender/source/blender/python/intern/bpy_util.h

Modified: branches/blender2.5/blender/source/blender/python/intern/bpy_operator.c
===================================================================
--- branches/blender2.5/blender/source/blender/python/intern/bpy_operator.c	2008-12-28 08:15:29 UTC (rev 18111)
+++ branches/blender2.5/blender/source/blender/python/intern/bpy_operator.c	2008-12-28 08:41:49 UTC (rev 18112)
@@ -39,22 +39,75 @@
 
 extern ListBase global_ops; /* evil, temp use */
 
-/* floats bigger then this are displayed as inf in the docstrings */
-#define MAXFLOAT_DOC 10000000
 
-#if 0
-void PyObSpit(char *name, PyObject *var) {
-	fprintf(stderr, "<%s> : ", name);
-	if (var==NULL) {
-		fprintf(stderr, "<NIL>");
+
+/* This function is only used by operators right now
+ * Its used for taking keyword args and filling in property values */
+int PYOP_props_from_dict(PointerRNA *ptr, PyObject *kw)
+{
+	int error_val = 0;
+	int totkw;
+	const char *arg_name= NULL;
+	PyObject *item;
+
+	PropertyRNA *prop, *iterprop;
+	CollectionPropertyIterator iter;
+
+	iterprop= RNA_struct_iterator_property(ptr);
+	RNA_property_collection_begin(ptr, iterprop, &iter);
+
+	totkw = kw ? PyDict_Size(kw):0;
+
+	for(; iter.valid; RNA_property_collection_next(&iter)) {
+		prop= iter.ptr.data;
+
+		arg_name= RNA_property_identifier(&iter.ptr, prop);
+
+		if (strcmp(arg_name, "rna_type")==0) continue;
+
+		if (kw==NULL) {
+			PyErr_Format( PyExc_AttributeError, "no args, expected \"%s\"", arg_name ? arg_name : "<UNKNOWN>");
+			error_val= -1;
+			break;
+		}
+
+		item= PyDict_GetItemString(kw, arg_name);
+
+		if (item == NULL) {
+			PyErr_Format( PyExc_AttributeError, "argument \"%s\" missing", arg_name ? arg_name : "<UNKNOWN>");
+			error_val = -1; /* pyrna_py_to_prop sets the error */
+			break;
+		}
+
+		if (pyrna_py_to_prop(ptr, prop, item)) {
+			error_val= -1;
+			break;
+		}
+
+		totkw--;
 	}
-	else {
-		PyObject_Print(var, stderr, 0);
+
+	RNA_property_collection_end(&iter);
+
+	if (error_val==0 && totkw > 0) { /* some keywords were given that were not used :/ */
+		PyObject *key, *value;
+		Py_ssize_t pos = 0;
+
+		while (PyDict_Next(kw, &pos, &key, &value)) {
+			arg_name= _PyUnicode_AsString(key);
+			if (RNA_struct_find_property(ptr, arg_name) == NULL) break;
+			arg_name= NULL;
+		}
+
+		PyErr_Format( PyExc_AttributeError, "argument \"%s\" unrecognized", arg_name ? arg_name : "<UNKNOWN>");
+		error_val = -1;
 	}
-	fprintf(stderr, "\n");
+
+	return error_val;
 }
-#endif
 
+/* floats bigger then this are displayed as inf in the docstrings */
+#define MAXFLOAT_DOC 10000000
 
 static int pyop_func_compare( BPy_OperatorFunc * a, BPy_OperatorFunc * b )
 {
@@ -120,14 +173,8 @@
 	wmOperatorType *ot;
 
 	int error_val = 0;
-	int totkw;
-	const char *arg_name= NULL;
-	PyObject *item;
-	
 	PointerRNA ptr;
-	PropertyRNA *prop, *iterprop;
-	CollectionPropertyIterator iter;
-
+	
 	if (PyTuple_Size(args)) {
 		PyErr_SetString( PyExc_AttributeError, "All operator args must be keywords");
 		return NULL;
@@ -140,59 +187,11 @@
 	}
 	
 	RNA_pointer_create(NULL, NULL, ot->srna, &properties, &ptr);
-
-
-	iterprop= RNA_struct_iterator_property(&ptr);
-	RNA_property_collection_begin(&ptr, iterprop, &iter);
-
-	totkw = kw ? PyDict_Size(kw):0;
-
-	for(; iter.valid; RNA_property_collection_next(&iter)) {
-		prop= iter.ptr.data;
-
-		arg_name= RNA_property_identifier(&iter.ptr, prop);
-
-		if (strcmp(arg_name, "rna_type")==0) continue;
-
-		if (kw==NULL) {
-			PyErr_Format( PyExc_AttributeError, "no args, expected \"%s\"", arg_name ? arg_name : "<UNKNOWN>");
-			error_val= 1;
-			break;
-		}
-		
-		item= PyDict_GetItemString(kw, arg_name);
-
-		if (item == NULL) {
-			PyErr_Format( PyExc_AttributeError, "argument \"%s\" missing", arg_name ? arg_name : "<UNKNOWN>");
-			error_val = 1; /* pyrna_py_to_prop sets the error */
-			break;
-		}
-		
-		if (pyrna_py_to_prop(&ptr, prop, item)) {
-			error_val= 1;
-			break;
-		}
-
-		totkw--;
-	}
-
-	RNA_property_collection_end(&iter);
-
-	if (error_val==0 && totkw > 0) { /* some keywords were given that were not used :/ */
-		PyObject *key, *value;
-		Py_ssize_t pos = 0;
-
-		while (PyDict_Next(kw, &pos, &key, &value)) {
-			arg_name= _PyUnicode_AsString(key);
-			if (RNA_struct_find_property(&ptr, arg_name) == NULL) break;
-			arg_name= NULL;
-		}
-
-		PyErr_Format( PyExc_AttributeError, "argument \"%s\" unrecognized", arg_name ? arg_name : "<UNKNOWN>");
-		error_val = 1;
-	}
-
+	
+	PYOP_props_from_dict(&ptr, kw);
+	
 	if (error_val==0) {
+		//WM_operator_name_call(self->C, self->name, WM_OP_INVOKE_DEFAULT, properties);
 		WM_operator_name_call(self->C, self->name, WM_OP_EXEC_DEFAULT, properties);
 	}
 

Modified: branches/blender2.5/blender/source/blender/python/intern/bpy_operator.h
===================================================================
--- branches/blender2.5/blender/source/blender/python/intern/bpy_operator.h	2008-12-28 08:15:29 UTC (rev 18111)
+++ branches/blender2.5/blender/source/blender/python/intern/bpy_operator.h	2008-12-28 08:41:49 UTC (rev 18112)
@@ -51,4 +51,7 @@
 PyObject *pyop_base_CreatePyObject(bContext *C );
 PyObject *pyop_func_CreatePyObject(bContext *C, char *name );
 
+/* fill in properties from a python dict */
+int PYOP_props_from_dict(PointerRNA *ptr, PyObject *kw);
+
 #endif

Modified: branches/blender2.5/blender/source/blender/python/intern/bpy_opwrapper.c
===================================================================
--- branches/blender2.5/blender/source/blender/python/intern/bpy_opwrapper.c	2008-12-28 08:15:29 UTC (rev 18111)
+++ branches/blender2.5/blender/source/blender/python/intern/bpy_opwrapper.c	2008-12-28 08:41:49 UTC (rev 18112)
@@ -37,6 +37,8 @@
 
 #include "bpy_rna.h"
 #include "bpy_compat.h"
+#include "bpy_util.h"
+#include "bpy_operator.h" /* for PYOP_props_from_dict() */
 
 typedef struct PyOperatorType {
 	void *next, *prev;
@@ -46,8 +48,9 @@
 	PyObject *py_exec;
 } PyOperatorType;
 
-static void pyop_kwargs_from_operator(PyObject *dict, wmOperator *op)
+static PyObject *pyop_kwargs_from_operator(wmOperator *op)
 {
+	PyObject *dict = PyDict_New();
 	PyObject *item;
 	PropertyRNA *prop, *iterprop;
 	CollectionPropertyIterator iter;
@@ -70,17 +73,130 @@
 
 	RNA_property_collection_end(&iter);
 
+	return dict;
 }
 
+
+static PyObject *pyop_dict_from_event(wmEvent *event)
+{
+	PyObject *dict= PyDict_New();
+	PyObject *item;
+	char *cstring, ascii[2];
+
+	/* type */
+	item= PyUnicode_FromString(WM_key_event_string(event->type));
+	PyDict_SetItemString(dict, "type", item);	Py_DECREF(item);
+
+	/* val */
+	switch(event->val) {
+	case KM_ANY:
+		cstring = "ANY";
+		break;
+	case KM_RELEASE:
+		cstring = "RELEASE";
+		break;
+	case KM_PRESS:
+		cstring = "PRESS";
+		break;
+	default:
+		cstring = "UNKNOWN";
+		break;
+	}
+
+	item= PyUnicode_FromString(cstring);
+	PyDict_SetItemString(dict, "val", item);	Py_DECREF(item);
+
+	/* x, y (mouse) */
+	item= PyLong_FromLong(event->x);
+	PyDict_SetItemString(dict, "x", item);		Py_DECREF(item);
+
+	item= PyLong_FromLong(event->y);
+	PyDict_SetItemString(dict, "y", item);		Py_DECREF(item);
+
+	item= PyLong_FromLong(event->prevx);
+	PyDict_SetItemString(dict, "prevx", item);	Py_DECREF(item);
+
+	item= PyLong_FromLong(event->prevy);
+	PyDict_SetItemString(dict, "prevy", item);	Py_DECREF(item);
+
+	/* ascii */
+	ascii[0]= event->ascii;
+	ascii[1]= '\0';
+	item= PyUnicode_FromString(ascii);
+	PyDict_SetItemString(dict, "ascii", item);	Py_DECREF(item);
+
+	/* modifier keys */
+	item= PyLong_FromLong(event->shift);
+	PyDict_SetItemString(dict, "shift", item);	Py_DECREF(item);
+
+	item= PyLong_FromLong(event->ctrl);
+	PyDict_SetItemString(dict, "ctrl", item);	Py_DECREF(item);
+
+	item= PyLong_FromLong(event->alt);
+	PyDict_SetItemString(dict, "alt", item);	Py_DECREF(item);
+
+	item= PyLong_FromLong(event->oskey);
+	PyDict_SetItemString(dict, "oskey", item);	Py_DECREF(item);
+
+
+
+	/* modifier */
+#if 0
+	item= PyTuple_New(0);
+	if(event->keymodifier & KM_SHIFT) {
+		_PyTuple_Resize(&item, size+1);
+		PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("SHIFT"));
+		size++;
+	}
+	if(event->keymodifier & KM_CTRL) {
+		_PyTuple_Resize(&item, size+1);
+		PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("CTRL"));
+		size++;
+	}
+	if(event->keymodifier & KM_ALT) {
+		_PyTuple_Resize(&item, size+1);
+		PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("ALT"));
+		size++;
+	}
+	if(event->keymodifier & KM_OSKEY) {
+		_PyTuple_Resize(&item, size+1);
+		PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("OSKEY"));
+		size++;
+	}
+	PyDict_SetItemString(dict, "keymodifier", item);	Py_DECREF(item);
+#endif
+
+	return dict;
+}
+
+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}
+};
+
 static int PYTHON_OT_exec(bContext *C, wmOperator *op)
 {
 	PyOperatorType *pyot = op->type->pyop_data;
-	PyObject *ret, *args= PyTuple_New(0), *kw= PyDict_New();
+	PyObject *args= PyTuple_New(0);
+	PyObject *kw= pyop_kwargs_from_operator(op);
+	PyObject *ret;
+	int ret_flag;
 
-	pyop_kwargs_from_operator(kw, op);
+	ret = PyObject_Call(pyot->py_exec, args, kw);
 
-	ret = PyObject_Call(pyot->py_exec, args, kw);
-	
+	if (ret == NULL) {
+		PyErr_Print();
+	}
+	else {
+		if (BPY_flag_from_seq(pyop_ret_flags, ret, &ret_flag) == -1) {
+			 /* the returned value could not be converted into a flag */
+			PyErr_Print();
+		}
+	}
+
 	Py_DECREF(args);
 	Py_DECREF(kw);
 
@@ -90,16 +206,38 @@
 static int PYTHON_OT_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
 	PyOperatorType *pyot = op->type->pyop_data;
-	PyObject *ret, *args= PyTuple_New(0), *kw= PyDict_New();
+	PyObject *args= PyTuple_New(2);
+	PyObject *kw= pyop_kwargs_from_operator(op);
+	PyObject *ret;
+	int ret_flag;
 
-	pyop_kwargs_from_operator(kw, op);
+	PyTuple_SET_ITEM(args, 0, pyop_dict_from_event(event));
+	PyTuple_SET_ITEM(args, 1, kw);
 
-	ret = PyObject_Call(pyot->py_invoke, args, kw);
+	ret = PyObject_Call(pyot->py_invoke, args, NULL);
 
-	Py_DECREF(args);
-	Py_DECREF(kw);
+	if (ret == NULL) {
+		PyErr_Print();
+	}
+	else {
+		if (BPY_flag_from_seq(pyop_ret_flags, ret, &ret_flag) == -1) {
+			 /* the returned value could not be converted into a flag */
+			PyErr_Print();
+		}
+		else {
+			/* copy the args back to the prop */
+			if (PYOP_props_from_dict(op->ptr, kw) == -1) {
+				/* one of the dict items didnt convert back to the prop */
+				PyErr_Print();
+			}
+		}
+	}
 
-	return OPERATOR_FINISHED;
+	
+
+	Py_DECREF(args); /* also decref's kw */
+
+	return ret_flag;
 }
 

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list