Python Panels WIP
[blender.git] / source / blender / python / intern / bpy_operator_wrap.c
1
2 /**
3  * $Id$
4  *
5  * ***** BEGIN GPL LICENSE BLOCK *****
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software Foundation,
19  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20  *
21  * Contributor(s): Campbell Barton
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26
27 #include "bpy_operator_wrap.h"
28 #include "BLI_listbase.h"
29 #include "BKE_context.h"
30 #include "BKE_report.h"
31 #include "DNA_windowmanager_types.h"
32 #include "MEM_guardedalloc.h"
33 #include "WM_api.h"
34 #include "WM_types.h"
35 #include "ED_screen.h"
36
37 #include "RNA_define.h"
38
39 #include "bpy_rna.h"
40 #include "bpy_compat.h"
41 #include "bpy_util.h"
42
43 #define PYOP_ATTR_PROP                  "__props__"
44 #define PYOP_ATTR_UINAME                "__label__"
45 #define PYOP_ATTR_IDNAME                "__name__"      /* use pythons class name */
46 #define PYOP_ATTR_DESCRIPTION   "__doc__"       /* use pythons docstring */
47
48 static PyObject *pyop_dict_from_event(wmEvent *event)
49 {
50         PyObject *dict= PyDict_New();
51         PyObject *item;
52         char *cstring, ascii[2];
53
54         /* type */
55         item= PyUnicode_FromString(WM_key_event_string(event->type));
56         PyDict_SetItemString(dict, "type", item);       Py_DECREF(item);
57
58         /* val */
59         switch(event->val) {
60         case KM_ANY:
61                 cstring = "ANY";
62                 break;
63         case KM_RELEASE:
64                 cstring = "RELEASE";
65                 break;
66         case KM_PRESS:
67                 cstring = "PRESS";
68                 break;
69         default:
70                 cstring = "UNKNOWN";
71                 break;
72         }
73
74         item= PyUnicode_FromString(cstring);
75         PyDict_SetItemString(dict, "val", item);        Py_DECREF(item);
76
77         /* x, y (mouse) */
78         item= PyLong_FromLong(event->x);
79         PyDict_SetItemString(dict, "x", item);          Py_DECREF(item);
80
81         item= PyLong_FromLong(event->y);
82         PyDict_SetItemString(dict, "y", item);          Py_DECREF(item);
83
84         item= PyLong_FromLong(event->prevx);
85         PyDict_SetItemString(dict, "prevx", item);      Py_DECREF(item);
86
87         item= PyLong_FromLong(event->prevy);
88         PyDict_SetItemString(dict, "prevy", item);      Py_DECREF(item);
89
90         /* ascii */
91         ascii[0]= event->ascii;
92         ascii[1]= '\0';
93         item= PyUnicode_FromString(ascii);
94         PyDict_SetItemString(dict, "ascii", item);      Py_DECREF(item);
95
96         /* modifier keys */
97         item= PyLong_FromLong(event->shift);
98         PyDict_SetItemString(dict, "shift", item);      Py_DECREF(item);
99
100         item= PyLong_FromLong(event->ctrl);
101         PyDict_SetItemString(dict, "ctrl", item);       Py_DECREF(item);
102
103         item= PyLong_FromLong(event->alt);
104         PyDict_SetItemString(dict, "alt", item);        Py_DECREF(item);
105
106         item= PyLong_FromLong(event->oskey);
107         PyDict_SetItemString(dict, "oskey", item);      Py_DECREF(item);
108
109
110
111         /* modifier */
112 #if 0
113         item= PyTuple_New(0);
114         if(event->keymodifier & KM_SHIFT) {
115                 _PyTuple_Resize(&item, size+1);
116                 PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("SHIFT"));
117                 size++;
118         }
119         if(event->keymodifier & KM_CTRL) {
120                 _PyTuple_Resize(&item, size+1);
121                 PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("CTRL"));
122                 size++;
123         }
124         if(event->keymodifier & KM_ALT) {
125                 _PyTuple_Resize(&item, size+1);
126                 PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("ALT"));
127                 size++;
128         }
129         if(event->keymodifier & KM_OSKEY) {
130                 _PyTuple_Resize(&item, size+1);
131                 PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("OSKEY"));
132                 size++;
133         }
134         PyDict_SetItemString(dict, "keymodifier", item);        Py_DECREF(item);
135 #endif
136
137         return dict;
138 }
139
140 /* TODO - a whole traceback would be ideal */
141 static void pyop_error_report(ReportList *reports)
142 {
143         PyObject *exception, *v, *tb;
144         PyErr_Fetch(&exception, &v, &tb);
145         if (exception == NULL)
146                 return;
147         /* Now we know v != NULL too */
148         BKE_report(reports, RPT_ERROR, _PyUnicode_AsString(v));
149         
150         PyErr_Print();
151 }
152
153 static struct BPY_flag_def pyop_ret_flags[] = {
154         {"RUNNING_MODAL", OPERATOR_RUNNING_MODAL},
155         {"CANCELLED", OPERATOR_CANCELLED},
156         {"FINISHED", OPERATOR_FINISHED},
157         {"PASS_THROUGH", OPERATOR_PASS_THROUGH},
158         {NULL, 0}
159 };
160
161 /* This invoke function can take events and
162  *
163  * It is up to the pyot->py_invoke() python func to run pyot->py_exec()
164  * the invoke function gets the keyword props as a dict, but can parse them
165  * to py_exec like this...
166  *
167  * def op_exec(x=-1, y=-1, text=""):
168  *     ...
169  *
170  * def op_invoke(event, prop_defs):
171  *     prop_defs['x'] = event['x']
172  *     ...
173  *     op_exec(**prop_defs)
174  *
175  * when there is no invoke function, C calls exec and sets the props.
176  * python class instance is stored in op->customdata so exec() can access
177  */
178
179
180 #define PYOP_EXEC 1
181 #define PYOP_INVOKE 2
182 #define PYOP_POLL 3
183         
184 static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *event)
185 {
186         PyObject *py_class = op->type->pyop_data;
187         PyObject *args;
188         PyObject *ret= NULL, *py_class_instance, *item;
189         int ret_flag= (mode==PYOP_POLL ? 0:OPERATOR_CANCELLED);
190
191         PyGILState_STATE gilstate = PyGILState_Ensure();
192
193         args = PyTuple_New(1);
194         PyTuple_SET_ITEM(args, 0, PyObject_GetAttrString(py_class, "__rna__")); // need to use an rna instance as the first arg
195         py_class_instance = PyObject_Call(py_class, args, NULL);
196         Py_DECREF(args);
197         
198         if (py_class_instance) { /* Initializing the class worked, now run its invoke function */
199                 
200                 
201                 /* Assign instance attributes from operator properties */
202                 {
203                         PropertyRNA *prop, *iterprop;
204                         CollectionPropertyIterator iter;
205                         const char *arg_name;
206
207                         iterprop= RNA_struct_iterator_property(op->ptr);
208                         RNA_property_collection_begin(op->ptr, iterprop, &iter);
209
210                         for(; iter.valid; RNA_property_collection_next(&iter)) {
211                                 prop= iter.ptr.data;
212                                 arg_name= RNA_property_identifier(&iter.ptr, prop);
213
214                                 if (strcmp(arg_name, "rna_type")==0) continue;
215
216                                 item = pyrna_prop_to_py(op->ptr, prop);
217                                 PyObject_SetAttrString(py_class_instance, arg_name, item);
218                                 Py_DECREF(item);
219                         }
220
221                         RNA_property_collection_end(&iter);
222                 }
223                 
224                 
225                 if (mode==PYOP_INVOKE) {
226                         item= PyObject_GetAttrString(py_class, "invoke");
227                         args = PyTuple_New(2);
228                         PyTuple_SET_ITEM(args, 1, pyop_dict_from_event(event));
229                 }
230                 else if (mode==PYOP_EXEC) {
231                         item= PyObject_GetAttrString(py_class, "exec");
232                         args = PyTuple_New(1);
233                 }
234                 else if (mode==PYOP_POLL) {
235                         item= PyObject_GetAttrString(py_class, "poll");
236                         args = PyTuple_New(2);
237                         //XXX  Todo - wrap context in a useful way, None for now.
238                         PyTuple_SET_ITEM(args, 1, Py_None);
239                 }
240                 PyTuple_SET_ITEM(args, 0, py_class_instance);
241         
242                 ret = PyObject_Call(item, args, NULL);
243                 
244                 Py_DECREF(args);
245                 Py_DECREF(item);
246         }
247         
248         if (ret == NULL) { /* covers py_class_instance failing too */
249                 pyop_error_report(op->reports);
250         }
251         else {
252                 if (mode==PYOP_POLL) {
253                         if (PyBool_Check(ret) == 0) {
254                                 PyErr_SetString(PyExc_ValueError, "Python poll function return value ");
255                                 pyop_error_report(op->reports);
256                         }
257                         else {
258                                 ret_flag= ret==Py_True ? 1:0;
259                         }
260                         
261                 } else if (BPY_flag_from_seq(pyop_ret_flags, ret, &ret_flag) == -1) {
262                          /* the returned value could not be converted into a flag */
263                         pyop_error_report(op->reports);
264                         
265                 }
266                 /* there is no need to copy the py keyword dict modified by
267                  * pyot->py_invoke(), back to the operator props since they are just
268                  * thrown away anyway
269                  *
270                  * If we ever want to do this and use the props again,
271                  * it can be done with - PYOP_props_from_dict(op->ptr, kw)
272                  */
273                 
274                 Py_DECREF(ret);
275         }
276
277         PyGILState_Release(gilstate);
278
279         return ret_flag;
280 }
281
282 static int PYTHON_OT_invoke(bContext *C, wmOperator *op, wmEvent *event)
283 {
284         return PYTHON_OT_generic(PYOP_INVOKE, C, op, event);    
285 }
286
287 static int PYTHON_OT_exec(bContext *C, wmOperator *op)
288 {
289         return PYTHON_OT_generic(PYOP_EXEC, C, op, NULL);
290 }
291
292 static int PYTHON_OT_poll(bContext *C)
293 {
294         // XXX TODO - no way to get the operator type (and therefor class) from the poll function.
295         //return PYTHON_OT_generic(PYOP_POLL, C, NULL, NULL);
296         return 1;
297 }
298
299 void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata)
300 {
301         PyObject *py_class = (PyObject *)userdata;
302         PyObject *props, *item;
303
304         /* identifiers */
305         item= PyObject_GetAttrString(py_class, PYOP_ATTR_IDNAME);
306         Py_DECREF(item);
307         ot->idname= _PyUnicode_AsString(item);
308         
309
310         item= PyObject_GetAttrString(py_class, PYOP_ATTR_UINAME);
311         if (item) {
312                 Py_DECREF(item);
313                 ot->name= _PyUnicode_AsString(item);
314         }
315         else {
316                 ot->name= ot->idname;
317                 PyErr_Clear();
318         }
319
320         item= PyObject_GetAttrString(py_class, PYOP_ATTR_DESCRIPTION);
321         Py_DECREF(item);
322         ot->description= (item && PyUnicode_Check(item)) ? _PyUnicode_AsString(item):"";
323         
324         /* api callbacks, detailed checks dont on adding */ 
325         if (PyObject_HasAttrString(py_class, "invoke"))
326                 ot->invoke= PYTHON_OT_invoke;
327         if (PyObject_HasAttrString(py_class, "exec"))
328                 ot->exec= PYTHON_OT_exec;
329         if (PyObject_HasAttrString(py_class, "poll"))
330                 ot->poll= PYTHON_OT_poll;
331         
332         ot->pyop_data= userdata;
333         
334         props= PyObject_GetAttrString(py_class, PYOP_ATTR_PROP);
335         
336         if (props) {
337                 PyObject *dummy_args = PyTuple_New(0);
338                 int i;
339                 
340                 Py_DECREF(props);
341
342                 for(i=0; i<PyList_Size(props); i++) {
343                         PyObject *py_func_ptr, *py_kw, *py_srna_cobject, *py_ret;
344                         item = PyList_GET_ITEM(props, i);
345                         
346                         if (PyArg_ParseTuple(item, "O!O!", &PyCObject_Type, &py_func_ptr, &PyDict_Type, &py_kw)) {
347                                 
348                                 PyObject *(*pyfunc)(PyObject *, PyObject *, PyObject *);
349                                 pyfunc = PyCObject_AsVoidPtr(py_func_ptr);
350                                 py_srna_cobject = PyCObject_FromVoidPtr(ot->srna, NULL);
351                                 
352                                 py_ret = pyfunc(py_srna_cobject, dummy_args, py_kw);
353                                 if (py_ret) {
354                                         Py_DECREF(py_ret);
355                                 } else {
356                                         PyErr_Print();
357                                         PyErr_Clear();
358                                 }
359                                 Py_DECREF(py_srna_cobject);
360                                 
361                         } else {
362                                 /* cant return NULL from here */ // XXX a bit ugly
363                                 PyErr_Print();
364                                 PyErr_Clear();
365                         }
366                         
367                         // expect a tuple with a CObject and a dict
368                 }
369                 Py_DECREF(dummy_args);
370         } else {
371                 PyErr_Clear();
372         }
373 }
374
375
376 /* pyOperators - Operators defined IN Python */
377 PyObject *PYOP_wrap_add(PyObject *self, PyObject *py_class)
378 {       
379         PyObject *base_class, *item;
380         
381         
382         char *idname= NULL;
383         int i;
384
385         static struct BPY_class_attr_check pyop_class_attr_values[]= {
386                 {PYOP_ATTR_IDNAME,              's', 0, 0},
387                 {PYOP_ATTR_UINAME,              's', 0, BPY_CLASS_ATTR_OPTIONAL},
388                 {PYOP_ATTR_PROP,                'l', 0, BPY_CLASS_ATTR_OPTIONAL},
389                 {PYOP_ATTR_DESCRIPTION, 's', 0, BPY_CLASS_ATTR_NONE_OK},
390                 {"exec",        'f', 1, BPY_CLASS_ATTR_OPTIONAL},
391                 {"invoke",      'f', 2, BPY_CLASS_ATTR_OPTIONAL},
392                 {"poll",        'f', 2, BPY_CLASS_ATTR_OPTIONAL},
393                 {NULL, 0, 0, 0}
394         };
395
396         // in python would be...
397         //PyObject *optype = PyObject_GetAttrString(PyObject_GetAttrString(PyDict_GetItemString(PyEval_GetGlobals(), "bpy"), "types"), "Operator");
398         base_class = PyObject_GetAttrStringArgs(PyDict_GetItemString(PyEval_GetGlobals(), "bpy"), 2, "types", "Operator");
399         Py_DECREF(base_class);
400
401         if(BPY_class_validate("Operator", py_class, base_class, pyop_class_attr_values, NULL) < 0) {
402                 return NULL; /* BPY_class_validate sets the error */
403         }
404
405         /* class name is used for operator ID - this can be changed later if we want */
406         item= PyObject_GetAttrString(py_class, PYOP_ATTR_IDNAME);
407         Py_DECREF(item);
408         idname =  _PyUnicode_AsString(item);
409         
410         if (WM_operatortype_find(idname)) {
411                 PyErr_Format( PyExc_AttributeError, "Operator alredy exists with this name \"%s\"", idname);
412                 return NULL;
413         }
414         
415         /* If we have properties set, check its a list of dicts */
416         item= PyObject_GetAttrString(py_class, PYOP_ATTR_PROP);
417         if (item) {
418                 Py_DECREF(item);
419                 for(i=0; i<PyList_Size(item); i++) {
420                         PyObject *py_args = PyList_GET_ITEM(item, i);
421                         PyObject *py_func_ptr, *py_kw; /* place holders */
422                         
423                         if (!PyArg_ParseTuple(py_args, "O!O!", &PyCObject_Type, &py_func_ptr, &PyDict_Type, &py_kw)) {
424                                 PyErr_Format(PyExc_ValueError, "Cant register operator class - %s.properties must contain values from FloatProperty", idname);
425                                 return NULL;                            
426                         }
427                 }
428         }
429         else {
430                 PyErr_Clear();
431         }
432         
433         Py_INCREF(py_class);
434         WM_operatortype_append_ptr(PYTHON_OT_wrapper, py_class);
435
436         Py_RETURN_NONE;
437 }
438
439 PyObject *PYOP_wrap_remove(PyObject *self, PyObject *value)
440 {
441         PyObject *py_class;
442         char *idname= NULL;
443         wmOperatorType *ot;
444         
445
446         if (PyUnicode_Check(value))
447                 idname = _PyUnicode_AsString(value);
448         else if (PyCFunction_Check(value)) {
449                 PyObject *cfunc_self = PyCFunction_GetSelf(value);
450                 if (cfunc_self)
451                         idname = _PyUnicode_AsString(cfunc_self);
452         }
453         
454         if (idname==NULL) {
455                 PyErr_SetString( PyExc_ValueError, "Expected the operator name as a string or the operator function");
456                 return NULL;
457         }
458
459         if (!(ot= WM_operatortype_find(idname))) {
460                 PyErr_Format( PyExc_AttributeError, "Operator \"%s\" does not exists, cant remove", idname);
461                 return NULL;
462         }
463         
464         if (!(py_class= (PyObject *)ot->pyop_data)) {
465                 PyErr_Format( PyExc_AttributeError, "Operator \"%s\" was not created by python", idname);
466                 return NULL;
467         }
468         
469         Py_XDECREF(py_class);
470
471         WM_operatortype_remove(idname);
472
473         Py_RETURN_NONE;
474 }
475
476
477