Scripts:
[blender.git] / source / blender / python / api2_2x / Window.c
1 /* 
2  *
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA        02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * This is a new part of Blender.
26  *
27  * Contributor(s): Willian P. Germano
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30 */
31
32 #include <Python.h>
33 #include <stdio.h>
34
35 #include <blendef.h> /* OBACT */
36 #include <BDR_editobject.h> /* enter / leave editmode */
37 #include <BKE_global.h>
38 #include <BKE_library.h>
39 #include <BKE_object.h> /* for during_script() */
40 #include <BKE_scene.h> /* scene_find_camera() */
41 #include <BIF_usiblender.h>
42 #include <BIF_mywindow.h>
43 #include <BSE_headerbuttons.h>
44 #include <BSE_filesel.h>
45 #include <BIF_editmesh.h> /* for undo_push_mesh() */
46 #include <BIF_screen.h>
47 #include <BIF_space.h>
48 #include <BIF_drawtext.h>
49 #include <BIF_spacetypes.h>
50 #include <mydevice.h>
51 #include <DNA_view3d_types.h>
52 #include <DNA_screen_types.h>
53 #include <DNA_space_types.h>
54 #include <DNA_text_types.h>
55 #include <DNA_vec_types.h> /* for rcti struct */
56
57 #include "gen_utils.h"
58 #include "modules.h"
59 #include "matrix.h"
60 #include "vector.h"
61 #include "constant.h"
62
63
64 /* See Draw.c */
65 extern int EXPP_disable_force_draw;
66
67 /* Callback used by the file and image selector access functions */
68 static PyObject *(*EXPP_FS_PyCallback)(PyObject *arg) = NULL;
69
70 /*****************************************************************************/
71 /* Python API function prototypes for the Window module.                                                                                 */
72 /*****************************************************************************/
73 PyObject *M_Window_Redraw (PyObject *self, PyObject *args);
74 static PyObject *M_Window_RedrawAll (PyObject *self, PyObject *args);
75 static PyObject *M_Window_QRedrawAll (PyObject *self, PyObject *args);
76 static PyObject *M_Window_DrawProgressBar (PyObject *self, PyObject *args);
77 static PyObject *M_Window_GetCursorPos (PyObject *self);
78 static PyObject *M_Window_SetCursorPos (PyObject *self, PyObject *args);
79 static PyObject *M_Window_WaitCursor (PyObject *self, PyObject *args);
80 static PyObject *M_Window_GetViewVector (PyObject *self);
81 static PyObject *M_Window_GetViewQuat (PyObject *self);
82 static PyObject *M_Window_SetViewQuat (PyObject *self, PyObject *args);
83 static PyObject *M_Window_GetViewOffset (PyObject *self);
84 static PyObject *M_Window_SetViewOffset (PyObject *self, PyObject *args);
85 static PyObject *M_Window_GetViewMatrix (PyObject *self);
86 static PyObject *M_Window_FileSelector (PyObject *self, PyObject *args);
87 static PyObject *M_Window_ImageSelector (PyObject *self, PyObject *args);
88 static PyObject *M_Window_EditMode (PyObject *self, PyObject *args);
89 static PyObject *M_Window_ViewLayer (PyObject *self, PyObject *args);
90 static PyObject *M_Window_CameraView (PyObject *self, PyObject *args);
91 static PyObject *M_Window_QTest (PyObject *self);
92 static PyObject *M_Window_QRead (PyObject *self);
93 static PyObject *M_Window_QAdd (PyObject *self, PyObject *args);
94 static PyObject *M_Window_QHandle (PyObject *self, PyObject *args);
95 static PyObject *M_Window_GetMouseCoords (PyObject *self);
96 static PyObject *M_Window_SetMouseCoords (PyObject *self, PyObject *args);
97 static PyObject *M_Window_GetMouseButtons (PyObject *self);
98 static PyObject *M_Window_GetKeyQualifiers (PyObject *self);
99 static PyObject *M_Window_SetKeyQualifiers (PyObject *self, PyObject *args);
100 static PyObject *M_Window_GetAreaSize (PyObject *self);
101 static PyObject *M_Window_GetAreaID (PyObject *self);
102 static PyObject *M_Window_GetScreenSize (PyObject *self);
103 static PyObject *M_Window_GetScreens (PyObject *self);
104 static PyObject *M_Window_SetScreen (PyObject *self, PyObject *args);
105 static PyObject *M_Window_GetScreenInfo (PyObject *self, PyObject *args,
106         PyObject *kwords);
107
108 /*****************************************************************************/
109 /* The following string definitions are used for documentation strings.                  */
110 /* In Python these will be written to the console when doing a                                                   */
111 /* Blender.Window.__doc__                                                                                                                                                                                                                */
112 /*****************************************************************************/
113 static char M_Window_doc[] =
114 "The Blender Window module\n\n";
115
116 static char M_Window_Redraw_doc[] =
117 "() - Force a redraw of a specific Window Type (see Window.Types)";
118
119 static char M_Window_RedrawAll_doc[] =
120 "() - Redraw all windows";
121
122 static char M_Window_QRedrawAll_doc[] =
123 "() - Redraw all windows by queue event";
124
125 static char M_Window_FileSelector_doc[] =
126 "(callback [, title, filename]) - Open a file selector window.\n\
127 The selected file name is used as argument to a function callback f(name)\n\
128 that you must provide. 'title' is optional and defaults to 'SELECT FILE'.\n\
129 'filename' is optional and defaults to Blender.Get('filename').\n\n\
130 Example:\n\n\
131 import Blender\n\n\
132 def my_function(filename):\n\
133         print 'The selected file was: ', filename\n\n\
134 Blender.Window.FileSelector(my_function, 'SAVE FILE')\n";
135
136 static char M_Window_ImageSelector_doc[] =
137 "(callback [, title, filename]) - Open an image selector window.\n\
138 The selected file name is used as argument to a function callback f(name)\n\
139 that you must provide. 'title' is optional and defaults to 'SELECT IMAGE'.\n\
140 'filename' is optional and defaults to Blender.Get('filename').\n\n\
141 Example:\n\n\
142 import Blender\n\n\
143 def my_function(filename):\n\
144         print 'The selected image file was: ', filename\n\n\
145 Blender.Window.ImageSelector(my_function, 'LOAD IMAGE')\n";
146
147 static char M_Window_DrawProgressBar_doc[] =
148 "(done, text) - Draw a progress bar.\n\
149 'done' is a float value <= 1.0, 'text' contains info about what is\n\
150 currently being done.";
151
152 static char M_Window_GetCursorPos_doc[] =
153 "() - Get the current 3d cursor position as a list of three floats.";
154
155 static char M_Window_SetCursorPos_doc[] =
156 "([f,f,f]) - Set the current 3d cursor position from a list of three floats.";
157
158 static char M_Window_WaitCursor_doc[] =
159 "(bool) - Set cursor to wait mode (nonzero bool) or normal mode (0).";
160
161 static char M_Window_GetViewVector_doc[] =
162 "() - Get the current 3d view vector as a list of three floats [x,y,z].";
163
164 static char M_Window_GetViewMatrix_doc[] =
165 "() - Get the current 3d view matrix.";
166
167 static char M_Window_EditMode_doc[] =
168 "() - Get the current status -- 0: not in edit mode; 1: in edit mode.\n\
169 (status) - if 1: enter edit mode; if 0: leave edit mode.\n\
170 Returns the current status.  This function is mostly useful to leave\n\
171 edit mode before applying changes to a mesh (otherwise the changes will\n\
172 be lost) and then returning to it upon leaving.";
173
174 static char M_Window_ViewLayer_doc[] =
175 "(layers = []) - Get/set active layers in all 3d View windows.\n\
176 () - Make no changes, only return currently visible layers.\n\
177 (layers = []) - a list of integers, each in the range [1, 20].\n\
178 This function returns the currently visible layers as a list of ints.";
179
180 static char M_Window_GetViewQuat_doc[] =
181 "() - Get the current VIEW3D view quaternion values.";
182
183 static char M_Window_SetViewQuat_doc[] =
184 "(quat) - Set the current VIEW3D view quaternion values.\n\
185 (quat) - [f,f,f,f] or f,f,f,f: the new float values.";
186
187 static char M_Window_GetViewOffset_doc[] =
188 "() - Get the current VIEW3D view offset values.";
189
190 static char M_Window_SetViewOffset_doc[] =
191 "(ofs) - Set the current VIEW3D view offset values.\n\
192 (ofs) - [f,f,f] or f,f,f: the new float values.";
193
194 static char M_Window_CameraView_doc[] =
195 "(camtov3d = 0) - Set the current VIEW3D view to the active camera's view.\n\
196 (camtov3d = 0) - bool: if nonzero it's the camera that gets positioned at the\n\
197 current view, instead of the view being changed to that of the camera.\n\n\
198 If no camera is the active object, the active camera for the current scene\n\
199 is used.";
200
201 static char M_Window_QTest_doc[] =
202 "() - Check if there are pending events in the event queue.";
203
204 static char M_Window_QRead_doc[] =
205 "() - Get the next pending event from the event queue.\n\
206 This function returns a list [event, val], where:\n\
207 event - int: the key or mouse event (see Blender.Draw module);\n\
208 val - int: if 1 it's a key or mouse button press, if 0 a release.  For\n\
209         mouse movement events 'val' returns the new coordinates in x or y.";
210
211 static char M_Window_QAdd_doc[] =
212 "(win, evt, val, after = 0) - Add an event to some window's event queue.\n\
213 (win) - int: the win id, see Blender.Window.GetScreenInfo();\n\
214 (evt) - int: the event number, see events in Blender.Draw;\n\
215 (val) - bool: 1 for a key press, 0 for a release;\n\
216 (after) - bool: if 1 the event is put after the current queue and added later.";
217
218 static char M_Window_QHandle_doc[] =
219 "(win) - Process all events for the given window (area) now.\n\
220 (win) - int: the window id, see Blender.Window.GetScreenInfo().\n\n\
221 See Blender.Window.QAdd() for how to send events to a particular window.";
222
223 static char M_Window_GetMouseCoords_doc[] =
224 "() - Get mouse pointer's current screen coordinates.";
225
226 static char M_Window_SetMouseCoords_doc[] =
227 "(x, y) - Set mouse pointer's current screen coordinates.\n\
228 (x,y) - ints ([x, y] also accepted): the new x, y coordinates.";
229
230 static char M_Window_GetMouseButtons_doc[] =
231 "() - Get the current mouse button state (see Blender.Draw.LEFTMOUSE, etc).";
232
233 static char M_Window_GetKeyQualifiers_doc[] =
234 "() - Get the current qualifier keys state.\n\
235 An int is returned: or'ed combination of values in Blender.Window.Qual's dict.";
236
237 static char M_Window_SetKeyQualifiers_doc[] =
238 "(qual) - Fake qualifier keys state.\n\
239 (qual) - int: an or'ed combination of the values in Blender.Window.Qual dict.\n\
240 Note: remember to reset to 0 after handling the related event (see QAdd()).";
241
242 static char M_Window_GetAreaID_doc[] =
243 "() - Get the current window's (area) ID.";
244
245 static char M_Window_GetAreaSize_doc[] =
246 "() - Get the current window's (area) size as [width, height].";
247
248 static char M_Window_GetScreenSize_doc[] =
249 "() - Get the screen's size as [width, height].";
250
251 static char M_Window_GetScreens_doc[] =
252 "() - Get a list with the names of all available screens.";
253
254 static char M_Window_SetScreen_doc[] =
255 "(name) - Set current screen to the one with the given 'name'.";
256
257 static char M_Window_GetScreenInfo_doc[] =
258 "(type = -1, rect = 'win', screen = None)\n\
259 - Get info about the the areas in the current screen setup.\n\
260 (type = -1) - int: the space type (Blender.Window.Types) to restrict the\n\
261         results to, all if -1;\n\
262 (rect = 'win') - str: the rectangle of interest.  This defines if the corner\n\
263         coordinates returned will refer to:\n\
264         - the whole area: 'total';\n\
265         - only the header: 'header';\n\
266         - only the window content (default): 'win'.\n\
267 (screen = None) - str: the screen name, current if not given.\n\n\
268 A list of dictionaries (one for each area) is returned.\n\
269 Each dictionary has keys:\n\
270 'vertices': [xmin, ymin, xmax, ymax] area corners;\n\
271 'win': window type, see Blender.Window.Types dict;\n\
272 'id': area's id.";
273
274 /*****************************************************************************/
275 /* Python method structure definition for Blender.Window module:                                                 */
276 /*****************************************************************************/
277 struct PyMethodDef M_Window_methods[] = {
278         {"Redraw",               M_Window_Redraw,                       METH_VARARGS, M_Window_Redraw_doc},
279         {"RedrawAll",  M_Window_RedrawAll,      METH_VARARGS, M_Window_RedrawAll_doc},
280         {"QRedrawAll", M_Window_QRedrawAll, METH_VARARGS, M_Window_QRedrawAll_doc},
281         {"FileSelector", M_Window_FileSelector, METH_VARARGS,
282                 M_Window_FileSelector_doc},
283         {"ImageSelector", (PyCFunction)M_Window_ImageSelector, METH_VARARGS,
284                 M_Window_ImageSelector_doc},
285         {"DrawProgressBar", M_Window_DrawProgressBar,  METH_VARARGS,
286                 M_Window_DrawProgressBar_doc},
287         {"drawProgressBar", M_Window_DrawProgressBar,  METH_VARARGS,
288                 M_Window_DrawProgressBar_doc},
289         {"GetCursorPos", (PyCFunction)M_Window_GetCursorPos,    METH_NOARGS,
290                 M_Window_GetCursorPos_doc},
291         {"SetCursorPos", M_Window_SetCursorPos,  METH_VARARGS,
292                 M_Window_SetCursorPos_doc},
293         {"WaitCursor", M_Window_WaitCursor,  METH_VARARGS,
294                 M_Window_WaitCursor_doc},
295         {"GetViewVector", (PyCFunction)M_Window_GetViewVector,  METH_NOARGS,
296                 M_Window_GetViewVector_doc},
297         {"GetViewQuat", (PyCFunction)M_Window_GetViewQuat,      METH_NOARGS,
298                 M_Window_GetViewQuat_doc},
299         {"SetViewQuat", (PyCFunction)M_Window_SetViewQuat,      METH_VARARGS,
300                 M_Window_SetViewQuat_doc},
301         {"GetViewOffset", (PyCFunction)M_Window_GetViewOffset,  METH_NOARGS,
302                 M_Window_GetViewOffset_doc},
303         {"SetViewOffset", (PyCFunction)M_Window_SetViewOffset,  METH_VARARGS,
304                 M_Window_SetViewOffset_doc},
305         {"GetViewMatrix", (PyCFunction)M_Window_GetViewMatrix,  METH_NOARGS,
306                 M_Window_GetViewMatrix_doc},
307         {"EditMode", (PyCFunction)M_Window_EditMode,    METH_VARARGS,
308                 M_Window_EditMode_doc},
309         {"ViewLayer", (PyCFunction)M_Window_ViewLayer,  METH_VARARGS,
310                 M_Window_ViewLayer_doc},
311         {"CameraView", (PyCFunction)M_Window_CameraView,        METH_VARARGS,
312                 M_Window_CameraView_doc},
313         {"QTest", (PyCFunction)M_Window_QTest,  METH_NOARGS,
314                 M_Window_QTest_doc},
315         {"QRead", (PyCFunction)M_Window_QRead,  METH_NOARGS,
316                 M_Window_QRead_doc},
317         {"QAdd", (PyCFunction)M_Window_QAdd,    METH_VARARGS,
318                 M_Window_QAdd_doc},
319         {"QHandle", (PyCFunction)M_Window_QHandle,      METH_VARARGS,
320                 M_Window_QHandle_doc},
321         {"GetMouseCoords", (PyCFunction)M_Window_GetMouseCoords, METH_NOARGS,
322                 M_Window_GetMouseCoords_doc},
323         {"SetMouseCoords", (PyCFunction)M_Window_SetMouseCoords, METH_VARARGS,
324                 M_Window_SetMouseCoords_doc},
325         {"GetMouseButtons", (PyCFunction)M_Window_GetMouseButtons, METH_NOARGS,
326                 M_Window_GetMouseButtons_doc},
327         {"GetKeyQualifiers", (PyCFunction)M_Window_GetKeyQualifiers, METH_NOARGS,
328                 M_Window_GetKeyQualifiers_doc},
329         {"SetKeyQualifiers", (PyCFunction)M_Window_SetKeyQualifiers, METH_VARARGS,
330                 M_Window_SetKeyQualifiers_doc},
331         {"GetAreaSize", (PyCFunction)M_Window_GetAreaSize, METH_NOARGS,
332                 M_Window_GetAreaSize_doc},
333         {"GetAreaID", (PyCFunction)M_Window_GetAreaID, METH_NOARGS,
334                 M_Window_GetAreaID_doc},
335         {"GetScreenSize", (PyCFunction)M_Window_GetScreenSize, METH_NOARGS,
336                 M_Window_GetScreenSize_doc},
337         {"GetScreens", (PyCFunction)M_Window_GetScreens, METH_NOARGS,
338                 M_Window_GetScreens_doc},
339         {"SetScreen", (PyCFunction)M_Window_SetScreen, METH_VARARGS,
340                 M_Window_SetScreen_doc},
341         {"GetScreenInfo", (PyCFunction)M_Window_GetScreenInfo,
342                 METH_VARARGS | METH_KEYWORDS, M_Window_GetScreenInfo_doc},
343         {NULL, NULL, 0, NULL}
344 };
345
346 /*****************************************************************************/
347 /* Function:                                                    M_Window_Redraw                                                                                                                                          */
348 /* Python equivalent:                   Blender.Window.Redraw                                                                                                                    */
349 /*****************************************************************************/
350 /* not static so py_slider_update in Draw.[ch] can use it */
351 PyObject *M_Window_Redraw(PyObject *self, PyObject *args)
352
353         ScrArea *tempsa, *sa;
354         SpaceText *st;
355         int wintype = SPACE_VIEW3D;
356         short redraw_all = 0;
357
358         if (!PyArg_ParseTuple(args, "|i", &wintype))
359                 return (EXPP_ReturnPyObjError (PyExc_AttributeError,
360                                                 "expected int argument (or nothing)"));
361
362         if (wintype < 0)
363                 redraw_all = 1;
364
365         if (!during_script()) {
366                 tempsa= curarea;
367                 sa = G.curscreen->areabase.first;
368
369                 while (sa) {
370
371                         if (sa->spacetype == wintype || redraw_all) {
372                                 if (sa->spacetype == SPACE_TEXT) {
373                                         st = sa->spacedata.first;
374                                         if (st->text->flags & TXT_FOLLOW) /* follow cursor display */
375                                                 pop_space_text(st);
376
377                                         // XXX making a test: Jul 07, 2004.
378                                         // we don't need to prevent text win redraws anymore,
379                                         // since now there's a scripts space instead.
380                                         //if (EXPP_disable_force_draw) { /* defined in Draw.[ch] ... */
381                                         //      scrarea_queue_redraw(sa);
382                                         }
383
384                                 //} else {
385                                         scrarea_do_windraw(sa);
386                                         if (sa->headwin) scrarea_do_headdraw(sa);
387                                 //}
388                         }
389
390                         sa= sa->next;
391                 }
392
393                 if (curarea != tempsa) areawinset (tempsa->win);
394
395                 if (curarea) { /* is null if Blender is in bg mode */
396                         if (curarea->headwin) scrarea_do_headdraw (curarea);
397                         screen_swapbuffers();
398                 }
399         }
400
401         Py_INCREF(Py_None);
402         return Py_None;
403 }
404
405 /*****************************************************************************/
406 /* Function:                                                    M_Window_RedrawAll                                                                                                                               */
407 /* Python equivalent:                   Blender.Window.RedrawAll                                                                                                         */
408 /*****************************************************************************/
409 static PyObject *M_Window_RedrawAll(PyObject *self, PyObject *args)
410 {
411         return M_Window_Redraw(self, Py_BuildValue("(i)", -1));
412 }
413
414 /*****************************************************************************/
415 /* Function:                                                    M_Window_QRedrawAll                                                                                                                              */
416 /* Python equivalent:                   Blender.Window.QRedrawAll                                                                                                        */
417 /*****************************************************************************/
418 static PyObject *M_Window_QRedrawAll(PyObject *self, PyObject *args)
419 {
420         allqueue(REDRAWALL, 0);
421
422         Py_INCREF(Py_None);
423         return Py_None;
424 }
425
426 /*****************************************************************************/
427 /* Function:                                                    M_Window_FileSelector                                                                                                                    */
428 /* Python equivalent:                   Blender.Window.FileSelector                                                                                              */
429 /*****************************************************************************/
430
431 /* This is the callback to "activate_fileselect" below.  It receives the
432  * selected filename and (using it as argument) calls the Python callback
433  * provided by the script writer and stored in EXPP_FS_PyCallback. */
434
435 static void getSelectedFile(char *name)
436 {
437         if (!EXPP_FS_PyCallback) return;
438
439         PyObject_CallFunction((PyObject *)EXPP_FS_PyCallback, "s", name);
440
441         EXPP_FS_PyCallback = NULL;
442
443         return;
444 }
445
446 static PyObject *M_Window_FileSelector(PyObject *self, PyObject *args)
447 {
448         char *title = "SELECT FILE";
449         char *filename = G.sce;
450         SpaceScript *sc;
451         Script *script = G.main->script.last;
452         int startspace = 0;
453
454         if (!PyArg_ParseTuple(args, "O!|ss",
455                         &PyFunction_Type, &EXPP_FS_PyCallback, &title, &filename))
456                 return EXPP_ReturnPyObjError (PyExc_AttributeError,
457                 "\nexpected a callback function (and optionally one or two strings) "
458                 "as argument(s)");
459
460 /* trick: we move to a spacescript because then the fileselector will properly
461  * unset our SCRIPT_FILESEL flag when the user chooses a file or cancels the
462  * selection.  This is necessary because when a user cancels, the
463  * getSelectedFile function above doesn't get called and so couldn't unset the
464  * flag. */
465         startspace = curarea->spacetype;
466         if (startspace != SPACE_SCRIPT) newspace (curarea, SPACE_SCRIPT);
467
468         sc = curarea->spacedata.first;
469
470         /* did we get the right script? */
471         if (!(script->flags & SCRIPT_RUNNING)) {
472                 /* if not running, then we were already on a SpaceScript space, executing
473                  * a registered callback -- aka: this script has a gui */
474                 script = sc->script; /* this is the right script */
475         }
476         else { /* still running, use the trick */
477                 script->lastspace = startspace;
478                 sc->script = script;
479         }
480
481         script->flags |= SCRIPT_FILESEL;
482
483         activate_fileselect(FILE_BLENDER, title, filename, getSelectedFile);
484
485         Py_INCREF(Py_None);
486         return Py_None;
487 }
488
489 static PyObject *M_Window_ImageSelector(PyObject *self, PyObject *args)
490 {
491         char *title = "SELECT IMAGE";
492         char *filename = G.sce;
493         SpaceScript *sc;
494         Script *script = G.main->script.last;
495         int startspace = 0;
496
497         if (!PyArg_ParseTuple(args, "O!|ss",
498                         &PyFunction_Type, &EXPP_FS_PyCallback, &title, &filename))
499                 return (EXPP_ReturnPyObjError (PyExc_AttributeError,
500                 "\nexpected a callback function (and optionally one or two strings) "
501                 "as argument(s)"));
502
503 /* trick: we move to a spacescript because then the fileselector will properly
504  * unset our SCRIPT_FILESEL flag when the user chooses a file or cancels the
505  * selection.  This is necessary because when a user cancels, the
506  * getSelectedFile function above doesn't get called and so couldn't unset the
507  * flag. */
508         startspace = curarea->spacetype;
509         if (startspace != SPACE_SCRIPT) newspace (curarea, SPACE_SCRIPT);
510
511         sc = curarea->spacedata.first;
512
513         /* did we get the right script? */
514         if (!(script->flags & SCRIPT_RUNNING)) {
515                 /* if not running, then we're on a SpaceScript space, executing a
516                  * registered callback -- aka: this script has a gui */
517                 SpaceScript *sc = curarea->spacedata.first;
518                 script = sc->script; /* this is the right script */
519         }
520         else { /* still running, use the trick */
521                 script->lastspace = startspace;
522                 sc->script = script;
523         }
524
525         script->flags |= SCRIPT_FILESEL; /* same flag as filesel */
526
527         activate_imageselect(FILE_BLENDER, title, filename, getSelectedFile);
528
529         Py_INCREF(Py_None);
530         return Py_None;
531 }
532
533 /*****************************************************************************/
534 /* Function:                                                    M_Window_DrawProgressBar                                                                                                         */
535 /* Python equivalent:                   Blender.Window.DrawProgressBar                                                                           */
536 /*****************************************************************************/
537 static PyObject *M_Window_DrawProgressBar(PyObject *self, PyObject *args)
538 {
539         float done;
540         char *info = NULL;
541         int retval = 0;
542
543         if(!PyArg_ParseTuple(args, "fs", &done, &info))
544                 return (EXPP_ReturnPyObjError (PyExc_AttributeError,
545                                                 "expected a float and a string as arguments"));
546
547         if (!G.background) retval = progress_bar(done, info);
548
549         return Py_BuildValue("i", retval);
550 }
551
552 /*****************************************************************************/
553 /* Function:                                                    M_Window_GetCursorPos                                                                                                                    */
554 /* Python equivalent:                   Blender.Window.GetCursorPos                                                                                              */
555 /*****************************************************************************/
556 static PyObject *M_Window_GetCursorPos(PyObject *self)
557 {
558         float *cursor = NULL;
559         PyObject *pylist;
560
561         if (G.vd && G.vd->localview)
562                 cursor = G.vd->cursor;
563         else cursor = G.scene->cursor;
564
565         pylist = Py_BuildValue("[fff]", cursor[0], cursor[1], cursor[2]);
566
567         if (!pylist)
568                 return (EXPP_ReturnPyObjError (PyExc_MemoryError,
569                                                 "GetCursorPos: couldn't create pylist"));
570
571         return pylist;
572 }
573
574 /*****************************************************************************/
575 /* Function:                                                    M_Window_SetCursorPos                                                                                                                    */
576 /* Python equivalent:                   Blender.Window.SetCursorPos                                                                                              */
577 /*****************************************************************************/
578 static PyObject *M_Window_SetCursorPos(PyObject *self, PyObject *args)
579 {
580         int ok = 0;
581         float val[3];
582
583         if (PyObject_Length (args) == 3)
584                 ok = PyArg_ParseTuple (args, "fff", &val[0], &val[1], &val[2]);
585         else
586                 ok = PyArg_ParseTuple(args, "(fff)", &val[0], &val[1], &val[2]);
587
588         if (!ok)
589                 return EXPP_ReturnPyObjError (PyExc_TypeError,
590                                                                         "expected [f,f,f] or f,f,f as arguments");
591
592         if (G.vd && G.vd->localview) {
593                 G.vd->cursor[0] = val[0];
594                 G.vd->cursor[1] = val[1];
595                 G.vd->cursor[2] = val[2];
596         }
597         else {
598                 G.scene->cursor[0] = val[0];
599                 G.scene->cursor[1] = val[1];
600                 G.scene->cursor[2] = val[2];
601         }
602
603         Py_INCREF (Py_None);
604         return Py_None;
605 }
606
607 static PyObject *M_Window_WaitCursor(PyObject *self, PyObject *args)
608 {
609         int bool;
610
611         if (!PyArg_ParseTuple(args, "i", &bool))
612                 return EXPP_ReturnPyObjError (PyExc_TypeError,
613                         "expected bool (0 or 1) or nothing as argument");
614
615         waitcursor(bool); /* nonzero bool sets, zero unsets */
616
617         return EXPP_incr_ret(Py_None);
618 }
619
620 /*****************************************************************************/
621 /* Function:                                                    M_Window_GetViewVector                                                                                                           */
622 /* Python equivalent:                   Blender.Window.GetViewVector                                                                                     */
623 /*****************************************************************************/
624 static PyObject *M_Window_GetViewVector(PyObject *self)
625 {
626         float *vec = NULL;
627         PyObject *pylist;
628
629         if (!G.vd) {
630                 Py_INCREF (Py_None);
631                 return Py_None;
632         }
633
634         vec = G.vd->viewinv[2];
635
636         pylist = Py_BuildValue("[fff]", vec[0], vec[1], vec[2]);
637
638         if (!pylist)
639                 return (EXPP_ReturnPyObjError (PyExc_MemoryError,
640                                                 "GetViewVector: couldn't create pylist"));
641
642         return pylist;
643 }
644
645 static PyObject *M_Window_GetViewQuat(PyObject *self)
646 {
647         float *vec = NULL;
648         PyObject *pylist;
649
650         if (!G.vd) {
651                 Py_INCREF (Py_None);
652                 return Py_None;
653         }
654
655         vec = G.vd->viewquat;
656
657         pylist = Py_BuildValue("[ffff]", vec[0], vec[1], vec[2], vec[3]);
658
659         if (!pylist)
660                 return (EXPP_ReturnPyObjError (PyExc_MemoryError,
661                                                 "GetViewQuat: couldn't create pylist"));
662
663         return pylist;
664 }
665
666 static PyObject *M_Window_SetViewQuat(PyObject *self, PyObject *args)
667 {
668         int ok = 0;
669         float val[4];
670
671         if (!G.vd) {
672                 Py_INCREF (Py_None);
673                 return Py_None;
674         }
675
676         if (PyObject_Length (args) == 4)
677                 ok = PyArg_ParseTuple (args, "ffff", &val[0], &val[1], &val[2], &val[3]);
678         else
679                 ok = PyArg_ParseTuple(args, "(ffff)", &val[0], &val[1], &val[2], &val[3]);
680
681         if (!ok)
682                 return EXPP_ReturnPyObjError (PyExc_TypeError,
683                                                                         "expected [f,f,f,f] or f,f,f,f as arguments");
684
685         G.vd->viewquat[0] = val[0];
686         G.vd->viewquat[1] = val[1];
687         G.vd->viewquat[2] = val[2];
688         G.vd->viewquat[3] = val[3];
689
690         return EXPP_incr_ret (Py_None);
691 }
692
693 static PyObject *M_Window_GetViewOffset(PyObject *self)
694 {
695         float *vec = NULL;
696         PyObject *pylist;
697
698         if (!G.vd) {
699                 Py_INCREF (Py_None);
700                 return Py_None;
701         }
702
703         vec = G.vd->ofs;
704
705         pylist = Py_BuildValue("[fff]", vec[0], vec[1], vec[2]);
706
707         if (!pylist)
708                 return (EXPP_ReturnPyObjError (PyExc_MemoryError,
709                                                 "GetViewQuat: couldn't create pylist"));
710
711         return pylist;
712 }
713
714 static PyObject *M_Window_SetViewOffset(PyObject *self, PyObject *args)
715 {
716         int ok = 0;
717         float val[3];
718
719         if (!G.vd) {
720                 Py_INCREF (Py_None);
721                 return Py_None;
722         }
723
724         if (PyObject_Length (args) == 3)
725                 ok = PyArg_ParseTuple (args, "fff", &val[0], &val[1], &val[2]);
726         else
727                 ok = PyArg_ParseTuple(args, "(fff)", &val[0], &val[1], &val[2]);
728
729         if (!ok)
730                 return EXPP_ReturnPyObjError (PyExc_TypeError,
731                                                                         "expected [f,f,f] or f,f,f as arguments");
732
733         G.vd->ofs[0] = val[0];
734         G.vd->ofs[1] = val[1];
735         G.vd->ofs[2] = val[2];
736
737         return EXPP_incr_ret (Py_None);
738 }
739
740
741 /*****************************************************************************/
742 /* Function:                                                    M_Window_GetViewMatrix                                                                                                           */
743 /* Python equivalent:                   Blender.Window.GetViewMatrix                                                                                     */
744 /*****************************************************************************/
745 static PyObject *M_Window_GetViewMatrix(PyObject *self)
746 {
747         PyObject *viewmat;
748
749         if (!G.vd) {
750                 Py_INCREF (Py_None);
751                 return Py_None;
752         }
753
754         viewmat = (PyObject*)newMatrixObject((float*)G.vd->viewmat, 4, 4);
755
756         if (!viewmat)
757                 return EXPP_ReturnPyObjError (PyExc_MemoryError,
758                                                 "GetViewMatrix: couldn't create matrix pyobject");
759
760         return viewmat;
761 }
762
763 static PyObject *M_Window_EditMode(PyObject *self, PyObject *args)
764 {
765         short status = -1;
766
767         if (!PyArg_ParseTuple(args, "|h", &status))
768                 return EXPP_ReturnPyObjError (PyExc_TypeError,
769                         "expected nothing or an int (bool) as argument");
770
771         if (status >= 0) {
772                 if (status) {
773                                 if (!G.obedit) enter_editmode();
774                 }
775                 else if (G.obedit) {
776                         undo_push_mesh("From script"); /* use better solution after 2.34 */
777                         exit_editmode(1);
778                 }
779         }
780
781         return Py_BuildValue("h", G.obedit?1:0);
782 }
783
784 static PyObject *M_Window_ViewLayer(PyObject *self, PyObject *args)
785 {
786         PyObject *item = NULL;
787         PyObject *list = NULL, *resl = NULL;
788         int val, i, bit = 0, layer = 0;
789
790         if (!PyArg_ParseTuple(args, "|O!", &PyList_Type, &list))
791                 return EXPP_ReturnPyObjError (PyExc_TypeError,
792                         "expected nothing or a list of ints as argument");
793
794         if (list) {
795                 for (i = 0; i < PyList_Size(list); i++) {
796                         item = PyList_GetItem(list, i);
797                         if (!PyInt_Check(item))
798                                 return EXPP_ReturnPyObjError (PyExc_AttributeError,
799                                         "list must contain only integer numbers");
800
801                         val = (int)PyInt_AsLong(item);
802                         if (val < 1 || val > 20)
803                                 return EXPP_ReturnPyObjError (PyExc_AttributeError,
804                                         "layer values must be in the range [1, 20]");
805
806                         layer |= 1<<(val-1);
807                 }
808                 G.vd->lay = layer;
809
810                 while (bit < 20) {
811                         val = 1<<bit;
812                         if (layer & val) {
813                                 G.vd->layact = val;
814                                 break;
815                         }
816                         bit++;
817                 }
818         }
819                 
820         resl = PyList_New(0);
821         if (!resl)
822                 return (EXPP_ReturnPyObjError (PyExc_MemoryError,
823                         "couldn't create pylist!"));
824
825         layer = G.vd->lay;
826
827         bit = 0;
828         while (bit < 20) {
829                 val = 1<<bit;
830                 if (layer & val) {
831                         item = Py_BuildValue("i", bit + 1);
832                         PyList_Append(resl, item);
833                         Py_DECREF(item);
834                 }
835                 bit++;
836         }
837
838         return resl;
839 }
840
841 static PyObject *M_Window_CameraView(PyObject *self, PyObject *args)
842 {
843         short camtov3d = 0;
844         void setcameratoview3d(void); /* view.c, used in toets.c */
845
846         if (!PyArg_ParseTuple(args, "|i", &camtov3d))
847                 return EXPP_ReturnPyObjError (PyExc_TypeError,
848                         "expected an int (from Window.Views) as argument");
849
850         if (!G.vd)
851                 return EXPP_ReturnPyObjError (PyExc_RuntimeError,
852                         "View3d not available!");
853
854         if (!G.vd->camera) {
855                 if (BASACT && OBACT->type == OB_CAMERA) G.vd->camera = OBACT;
856                 else G.vd->camera = scene_find_camera(G.scene);
857                 handle_view3d_lock();
858         }
859
860         G.vd->persp = 2;
861         G.vd->view = 0;
862
863         if (camtov3d) setcameratoview3d();
864
865         return EXPP_incr_ret(Py_None);
866 }
867
868 static PyObject *M_Window_QTest(PyObject *self)
869 {
870         return Py_BuildValue("h", qtest());
871 }
872
873 static PyObject *M_Window_QRead(PyObject *self)
874 {
875         short val = 0;
876         unsigned short event;
877
878         event = extern_qread(&val);
879
880         return Py_BuildValue("ii", event, val);
881 }
882
883 static PyObject *M_Window_QAdd(PyObject *self, PyObject *args)
884 {
885         short win;
886         short evt; /* unsigned, we check below */
887         short val;
888         short after = 0;
889
890         if (!PyArg_ParseTuple(args, "hhh|h", &win, &evt, &val, &after))
891                 return EXPP_ReturnPyObjError (PyExc_TypeError,
892                         "expected three or four ints as arguments");
893
894         if (evt < 0) /* evt is unsigned short */
895                 return EXPP_ReturnPyObjError (PyExc_AttributeError,
896                         "event value must be a positive int, check events in Blender.Draw");
897
898         if (after) addafterqueue(win, evt, val);
899         else addqueue(win, evt, val);
900
901         return EXPP_incr_ret(Py_None);
902 }
903
904 static PyObject *M_Window_QHandle(PyObject *self, PyObject *args)
905 {
906         short win;
907         ScrArea *sa = curarea;
908         ScrArea *oldsa = NULL;
909
910         if (!PyArg_ParseTuple(args, "h", &win))
911                 return EXPP_ReturnPyObjError (PyExc_TypeError,
912                         "expected an int as argument");
913
914         while (sa) {
915                 if (sa->win == win) break;
916                 sa = sa->next;
917         }
918
919         if (sa) {
920                 BWinEvent evt;
921                 short do_redraw = 0, do_change = 0;
922
923                 if(sa != curarea || sa->win != mywinget()) {
924                         oldsa = curarea;
925                         areawinset(sa->win);
926                         set_g_activearea(sa);
927                 }
928                 while(bwin_qread(sa->win, &evt)) {
929                         if(evt.event == REDRAW) {
930                                 do_redraw = 1;
931                         }
932                         else if(evt.event == CHANGED) {
933                                 sa->win_swap = 0;
934                                 do_change = 1;
935                                 do_redraw = 1;
936                         }
937                         else {
938                                 scrarea_do_winhandle(sa, &evt);
939                         }
940                 }
941         }
942
943         if (oldsa) {
944                 areawinset(oldsa->win);
945                 set_g_activearea(oldsa);
946         }
947
948         return EXPP_incr_ret(Py_None);
949 }
950
951 static PyObject *M_Window_GetMouseCoords(PyObject *self)
952 {
953         short mval[2];
954
955         getmouse(mval);
956         
957         return Py_BuildValue("hh", mval[0], mval[1]);
958 }
959
960 static PyObject *M_Window_SetMouseCoords(PyObject *self, PyObject *args)
961 {
962         int ok, x, y;
963
964         if (!G.curscreen)
965                 return EXPP_ReturnPyObjError (PyExc_RuntimeError,
966                         "no current screen to retrieve info from!");
967         
968         x = G.curscreen->sizex / 2;
969         y = G.curscreen->sizey / 2;
970
971         if (PyObject_Length(args) == 2)
972                 ok = PyArg_ParseTuple(args, "hh", &x, &y);
973         else
974                 ok = PyArg_ParseTuple(args, "|(hh)", &x, &y);
975
976         if (!ok)
977                 return EXPP_ReturnPyObjError (PyExc_TypeError,
978                         "expected [i, i] or i,i as arguments (or nothing).");
979
980         warp_pointer(x, y);
981
982         return EXPP_incr_ret(Py_None);
983 }
984
985 static PyObject *M_Window_GetMouseButtons(PyObject *self)
986 {
987         short mbut = get_mbut();
988         
989         return Py_BuildValue("h", mbut);
990 }
991
992 static PyObject *M_Window_GetKeyQualifiers(PyObject *self)
993 {
994         short qual = get_qual();
995
996         return Py_BuildValue("h", qual);
997 }
998
999 static PyObject *M_Window_SetKeyQualifiers(PyObject *self, PyObject *args)
1000 {
1001         short qual = 0;
1002
1003         if (!PyArg_ParseTuple(args, "|h", &qual))
1004                 return EXPP_ReturnPyObjError (PyExc_TypeError,
1005                         "expected nothing or an int (or'ed flags) as argument");
1006
1007         if (qual < 0)
1008                 return EXPP_ReturnPyObjError (PyExc_AttributeError,
1009                         "value must be a positive int, check Blender.Window.Qual");
1010
1011         G.qual = qual;
1012
1013         return Py_BuildValue("h", qual);        
1014 }
1015
1016 static PyObject *M_Window_GetAreaSize(PyObject *self)
1017 {
1018         ScrArea *sa = curarea;
1019
1020         if (!sa) return EXPP_incr_ret(Py_None);
1021
1022         return Py_BuildValue("hh", sa->winx, sa->winy);
1023 }
1024
1025 static PyObject *M_Window_GetAreaID(PyObject *self)
1026 {
1027         ScrArea *sa = curarea;
1028
1029         if (!sa) return EXPP_incr_ret(Py_None);
1030
1031         return Py_BuildValue("h", sa->win);
1032 }
1033
1034 static PyObject *M_Window_GetScreenSize(PyObject *self)
1035 {
1036         bScreen *scr = G.curscreen;
1037
1038         if (!scr) return EXPP_incr_ret(Py_None);
1039
1040         return Py_BuildValue("hh", scr->sizex, scr->sizey);
1041 }
1042
1043
1044 static PyObject *M_Window_SetScreen(PyObject *self, PyObject *args)
1045 {
1046         bScreen *scr = G.main->screen.first;
1047         char *name = NULL;
1048
1049         if (!PyArg_ParseTuple(args, "s", &name))
1050                 return EXPP_ReturnPyObjError (PyExc_TypeError,
1051                         "expected string as argument");
1052
1053         while (scr) {
1054                 if (!strcmp(scr->id.name+2, name)) {
1055                         setscreen(scr);
1056                         break;
1057                 }
1058                 scr = scr->id.next;
1059         }
1060
1061         if (!scr)
1062                 return EXPP_ReturnPyObjError (PyExc_AttributeError,
1063                         "no such screen, check Window.GetScreens() for valid names.");
1064
1065         return EXPP_incr_ret(Py_None);
1066 }
1067
1068 static PyObject *M_Window_GetScreens(PyObject *self)
1069 {
1070         bScreen *scr = G.main->screen.first;
1071         PyObject *list = PyList_New(0);
1072         PyObject *str = NULL;
1073
1074         if (!list)
1075                 return EXPP_ReturnPyObjError (PyExc_MemoryError,
1076                         "couldn't create py list!");
1077
1078         while (scr) {
1079                 str = PyString_FromString(scr->id.name+2);
1080
1081                 if (!str) {
1082                         Py_DECREF(list);
1083                         return EXPP_ReturnPyObjError (PyExc_MemoryError,
1084                                 "couldn't create py string!");
1085                 }
1086
1087                 PyList_Append(list, str); /* incref's str */
1088                 Py_DECREF(str);
1089
1090                 scr = scr->id.next;
1091         }
1092
1093         return list;    
1094 }
1095
1096 static PyObject *M_Window_GetScreenInfo(PyObject *self, PyObject *args,
1097         PyObject *kwords)
1098 {
1099         ScrArea *sa = G.curscreen->areabase.first;
1100         bScreen *scr = G.main->screen.first;
1101         PyObject *item, *list;
1102         rcti *rct;
1103         int type = -1;
1104         char *rect = "win";
1105         char *screen = "";
1106         static char *kwlist[] = {"type", "rect", "screen", NULL};
1107         int rctype = 0;
1108
1109         if (!PyArg_ParseTupleAndKeywords(args, kwords, "|iss", kwlist, &type,
1110                         &rect, &screen))
1111                 return EXPP_ReturnPyObjError (PyExc_TypeError,
1112                         "expected nothing or an int and two strings as arguments");
1113
1114         if (!strcmp(rect, "win"))
1115                 rctype = 0;
1116         else if (!strcmp(rect, "total"))
1117                 rctype = 1;
1118         else if (!strcmp(rect, "header"))
1119                 rctype = 2;
1120         else
1121                 return EXPP_ReturnPyObjError (PyExc_AttributeError,
1122                         "requested invalid type for area rectangle coordinates.");
1123
1124         list = PyList_New(0);
1125
1126         if (screen && screen[0] != '\0') {
1127                 while (scr) {
1128                         if (!strcmp(scr->id.name+2, screen)) {
1129                                 sa = scr->areabase.first;
1130                                 break;
1131                         }
1132                         scr = scr->id.next;
1133                 }
1134         }
1135
1136         if (!scr) {
1137                 Py_DECREF(list);
1138                 return EXPP_ReturnPyObjError (PyExc_AttributeError,
1139                         "no such screen, see existing ones with Window.GetScreens.");
1140         }
1141         
1142         while (sa) {
1143                 if (type != -1 && sa->spacetype != type) {
1144                         sa = sa->next;
1145                         continue;
1146                 }
1147
1148                 switch (rctype) {
1149                         case 0:
1150                                 rct = &sa->winrct;
1151                                 break;
1152                         case 1:
1153                                 rct = &sa->totrct;
1154                                 break;
1155                         case 2:
1156                         default:
1157                                 rct = &sa->headrct;
1158                 }
1159
1160                 item = Py_BuildValue("{s:[h,h,h,h],s:h,s:h}",
1161                         "vertices", rct->xmin, rct->ymin, rct->xmax, rct->ymax,
1162                         "type", (short)sa->spacetype, "id", (short)sa->win);
1163                 PyList_Append(list, item);
1164                 Py_DECREF(item);
1165
1166                 sa = sa->next;
1167         }
1168
1169         return list;
1170 }
1171
1172 /*****************************************************************************/
1173 /* Function:                                                    Window_Init                                                                                                                                                              */
1174 /*****************************************************************************/
1175 PyObject *Window_Init (void)
1176 {
1177         PyObject        *submodule, *Types, *Qual;
1178
1179         submodule = Py_InitModule3("Blender.Window", M_Window_methods, M_Window_doc);
1180
1181         Types = M_constant_New();
1182         Qual = M_constant_New();
1183
1184         if (Types) {
1185                 BPy_constant *d = (BPy_constant *)Types;
1186
1187                 constant_insert(d, "VIEW3D", PyInt_FromLong(SPACE_VIEW3D));
1188                 constant_insert(d, "IPO", PyInt_FromLong(SPACE_IPO));
1189                 constant_insert(d, "OOPS", PyInt_FromLong(SPACE_OOPS));
1190                 constant_insert(d, "BUTS", PyInt_FromLong(SPACE_BUTS));
1191                 constant_insert(d, "FILE", PyInt_FromLong(SPACE_FILE));
1192                 constant_insert(d, "IMAGE", PyInt_FromLong(SPACE_IMAGE));
1193                 constant_insert(d, "INFO", PyInt_FromLong(SPACE_INFO));
1194                 constant_insert(d, "SEQ", PyInt_FromLong(SPACE_SEQ));
1195                 constant_insert(d, "IMASEL", PyInt_FromLong(SPACE_IMASEL));
1196                 constant_insert(d, "SOUND", PyInt_FromLong(SPACE_SOUND));
1197                 constant_insert(d, "ACTION", PyInt_FromLong(SPACE_ACTION));
1198                 constant_insert(d, "TEXT", PyInt_FromLong(SPACE_TEXT));
1199                 constant_insert(d, "NLA", PyInt_FromLong(SPACE_NLA));
1200                 constant_insert(d, "SCRIPT", PyInt_FromLong(SPACE_SCRIPT));
1201
1202                 PyModule_AddObject(submodule, "Types", Types);
1203         }
1204
1205         if (Qual) {
1206                 BPy_constant *d = (BPy_constant *)Qual;
1207
1208                 constant_insert(d, "LALT", PyInt_FromLong(L_ALTKEY));
1209                 constant_insert(d, "RALT", PyInt_FromLong(R_ALTKEY));
1210                 constant_insert(d, "ALT", PyInt_FromLong(LR_ALTKEY));
1211                 constant_insert(d, "LCTRL", PyInt_FromLong(L_CTRLKEY));
1212                 constant_insert(d, "RCTRL", PyInt_FromLong(R_CTRLKEY));
1213                 constant_insert(d, "CTRL", PyInt_FromLong(LR_CTRLKEY));
1214                 constant_insert(d, "LSHIFT", PyInt_FromLong(L_SHIFTKEY));
1215                 constant_insert(d, "RSHIFT", PyInt_FromLong(R_SHIFTKEY));
1216                 constant_insert(d, "SHIFT", PyInt_FromLong(LR_SHIFTKEY));
1217
1218                 PyModule_AddObject(submodule, "Qual", Qual);
1219         }
1220
1221         return submodule;
1222 }
1223