BPython - first step for better integration of Python in Blender:
[blender-staging.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 "Window.h"
33 #include "vector.h"
34 #include <BKE_library.h>
35
36 /* Many parts of the code here come from the older bpython implementation
37  * (file opy_window.c) */
38
39 /*****************************************************************************/
40 /* Function:                                                    M_Window_Redraw                                                                                                                                          */
41 /* Python equivalent:                   Blender.Window.Redraw                                                                                                                    */
42 /*****************************************************************************/
43 PyObject *M_Window_Redraw(PyObject *self, PyObject *args)
44 { /* not static so py_slider_update in Draw.[ch] can use it */
45         ScrArea *tempsa, *sa;
46         SpaceText *st;
47         int wintype = SPACE_VIEW3D;
48         short redraw_all = 0;
49
50         if (!PyArg_ParseTuple(args, "|i", &wintype))
51                 return (EXPP_ReturnPyObjError (PyExc_AttributeError,
52                                                 "expected int argument (or nothing)"));
53
54         if (wintype < 0)
55                 redraw_all = 1;
56
57         if (!during_script()) { /* XXX check this */
58                 tempsa= curarea;
59                 sa = G.curscreen->areabase.first;
60
61                 while (sa) {
62
63                         if (sa->spacetype == wintype || redraw_all) {
64                                 /* don't force-redraw Text window (Python GUI) when
65                                          redraw is called out of a slider update */
66                                 if (sa->spacetype == SPACE_TEXT) {
67                                         st = sa->spacedata.first;
68                                         if (st->text->flags & TXT_FOLLOW) /* follow cursor display */
69                                                 pop_space_text(st);
70                                         if (EXPP_disable_force_draw) { /* defined in Draw.[ch] ... */
71                                                 scrarea_queue_redraw(sa);
72                                         }
73
74                                 } else {
75                                         scrarea_do_windraw(sa);
76                                         if (sa->headwin) scrarea_do_headdraw(sa);
77                                 }
78                         }
79
80                         sa= sa->next;
81                 }
82
83                 if (curarea != tempsa) areawinset (tempsa->win);
84
85                 if (curarea->headwin) scrarea_do_headdraw (curarea);
86
87                 screen_swapbuffers();
88         }
89
90         Py_INCREF(Py_None);
91         return Py_None;
92 }
93
94 /*****************************************************************************/
95 /* Function:                                                    M_Window_RedrawAll                                                                                                                               */
96 /* Python equivalent:                   Blender.Window.RedrawAll                                                                                                         */
97 /*****************************************************************************/
98 static PyObject *M_Window_RedrawAll(PyObject *self, PyObject *args)
99 {
100         return M_Window_Redraw(self, Py_BuildValue("(i)", -1));
101 }
102
103 /*****************************************************************************/
104 /* Function:                                                    M_Window_QRedrawAll                                                                                                                              */
105 /* Python equivalent:                   Blender.Window.QRedrawAll                                                                                                        */
106 /*****************************************************************************/
107 static PyObject *M_Window_QRedrawAll(PyObject *self, PyObject *args)
108 {
109         allqueue(REDRAWALL, 0);
110
111         Py_INCREF(Py_None);
112         return Py_None;
113 }
114
115 /*****************************************************************************/
116 /* Function:                                                    M_Window_FileSelector                                                                                                                    */
117 /* Python equivalent:                   Blender.Window.FileSelector                                                                                              */
118 /*****************************************************************************/
119
120 /* This is the callback to "activate_fileselect" below.  It receives the
121  * selected filename and (using it as argument) calls the Python callback
122  * provided by the script writer and stored in EXPP_FS_PyCallback. */
123
124 static void getSelectedFile(char *name)
125 {
126         if (!EXPP_FS_PyCallback) return;
127
128         PyObject_CallFunction((PyObject *)EXPP_FS_PyCallback, "s", name);
129
130         EXPP_FS_PyCallback = NULL;
131
132         return;
133 }
134
135 static PyObject *M_Window_FileSelector(PyObject *self, PyObject *args)
136 {
137         char *title = "SELECT FILE";
138         SpaceScript *sc;
139         Script *script = G.main->script.last;
140         int startspace = 0;
141
142         if (!PyArg_ParseTuple(args, "O!|s", &PyFunction_Type, &EXPP_FS_PyCallback,
143                                 &title))
144                 return (EXPP_ReturnPyObjError (PyExc_AttributeError,
145                 "\nexpected a callback function (and optionally a string) as argument(s)"));
146
147 /* trick: we move to a spacescript because then the fileselector will properly
148  * unset our SCRIPT_FILESEL flag when the user chooses a file or cancels the
149  * selection.  This is necessary because when a user cancels, the
150  * getSelectedFile function above doesn't get called and so couldn't unset the
151  * flag. */
152         startspace = curarea->spacetype;
153         if (startspace != SPACE_SCRIPT) newspace (curarea, SPACE_SCRIPT);
154
155         sc = curarea->spacedata.first;
156
157         /* did we get the right script? */
158         if (!(script->flags & SCRIPT_RUNNING)) {
159                 /* if not running, then we were already on a SpaceScript space, executing
160                  * a registered callback -- aka: this script has a gui */
161                 script = sc->script; /* this is the right script */
162         }
163         else { /* still running, use the trick */
164                 script->lastspace = startspace;
165                 sc->script = script;
166         }
167
168         script->flags |= SCRIPT_FILESEL;
169
170         activate_fileselect(FILE_BLENDER, title, G.sce, getSelectedFile);
171
172         Py_INCREF(Py_None);
173         return Py_None;
174 }
175
176 static PyObject *M_Window_ImageSelector(PyObject *self, PyObject *args)
177 {
178         char *title = "SELECT IMAGE";
179         SpaceScript *sc;
180         Script *script = G.main->script.last;
181         int startspace = 0;
182
183         if (!PyArg_ParseTuple(args, "O!|s", &PyFunction_Type, &EXPP_FS_PyCallback,
184                                 &title))
185                 return (EXPP_ReturnPyObjError (PyExc_AttributeError,
186                 "\nexpected a callback function (and optionally a string) as argument(s)"));
187
188 /* trick: we move to a spacescript because then the fileselector will properly
189  * unset our SCRIPT_FILESEL flag when the user chooses a file or cancels the
190  * selection.  This is necessary because when a user cancels, the
191  * getSelectedFile function above doesn't get called and so couldn't unset the
192  * flag. */
193         startspace = curarea->spacetype;
194         if (startspace != SPACE_SCRIPT) newspace (curarea, SPACE_SCRIPT);
195
196         sc = curarea->spacedata.first;
197
198         /* did we get the right script? */
199         if (!(script->flags & SCRIPT_RUNNING)) {
200                 /* if not running, then we're on a SpaceScript space, executing a
201                  * registered callback -- aka: this script has a gui */
202                 SpaceScript *sc = curarea->spacedata.first;
203                 script = sc->script; /* this is the right script */
204         }
205         else { /* still running, use the trick */
206                 script->lastspace = startspace;
207                 sc->script = script;
208         }
209
210         script->flags |= SCRIPT_FILESEL; /* same flag as filesel */
211
212         activate_imageselect(FILE_BLENDER, title, G.sce, getSelectedFile);
213
214         Py_INCREF(Py_None);
215         return Py_None;
216 }
217
218 /*****************************************************************************/
219 /* Function:                                                    M_Window_DrawProgressBar                                                                                                         */
220 /* Python equivalent:                   Blender.Window.DrawProgressBar                                                                           */
221 /*****************************************************************************/
222 static PyObject *M_Window_DrawProgressBar(PyObject *self, PyObject *args)
223 {
224         float done;
225         char *info = NULL;
226         int retval;
227
228         if(!PyArg_ParseTuple(args, "fs", &done, &info))
229                 return (EXPP_ReturnPyObjError (PyExc_AttributeError,
230                                                 "expected a float and a string as arguments"));
231
232         retval = progress_bar(done, info);
233
234         return Py_BuildValue("i", retval);
235 }
236
237 /*****************************************************************************/
238 /* Function:                                                    M_Window_GetCursorPos                                                                                                                    */
239 /* Python equivalent:                   Blender.Window.GetCursorPos                                                                                              */
240 /*****************************************************************************/
241 static PyObject *M_Window_GetCursorPos(PyObject *self)
242 {
243         float *cursor = NULL;
244         PyObject *pylist;
245
246         if (G.vd && G.vd->localview)
247                 cursor = G.vd->cursor;
248         else cursor = G.scene->cursor;
249
250         pylist = Py_BuildValue("[fff]", cursor[0], cursor[1], cursor[2]);
251
252         if (!pylist)
253                 return (EXPP_ReturnPyObjError (PyExc_MemoryError,
254                                                 "GetCursorPos: couldn't create pylist"));
255
256         return pylist;
257 }
258
259 /*****************************************************************************/
260 /* Function:                                                    M_Window_SetCursorPos                                                                                                                    */
261 /* Python equivalent:                   Blender.Window.SetCursorPos                                                                                              */
262 /*****************************************************************************/
263 static PyObject *M_Window_SetCursorPos(PyObject *self, PyObject *args)
264 {
265         int ok = 0;
266         float val[3];
267
268         if (PyObject_Length (args) == 3)
269                 ok = PyArg_ParseTuple (args, "fff", &val[0], &val[1], &val[2]);
270         else
271                 ok = PyArg_ParseTuple(args, "(fff)", &val[0], &val[1], &val[2]);
272
273         if (!ok)
274                 return EXPP_ReturnPyObjError (PyExc_TypeError,
275                                                                         "expected [f,f,f] or f,f,f as arguments");
276
277         if (G.vd && G.vd->localview) {
278                 G.vd->cursor[0] = val[0];
279                 G.vd->cursor[1] = val[1];
280                 G.vd->cursor[2] = val[2];
281         }
282         else {
283                 G.scene->cursor[0] = val[0];
284                 G.scene->cursor[1] = val[1];
285                 G.scene->cursor[2] = val[2];
286         }
287
288         Py_INCREF (Py_None);
289         return Py_None;
290 }
291
292 /*****************************************************************************/
293 /* Function:                                                    M_Window_GetViewVector                                                                                                           */
294 /* Python equivalent:                   Blender.Window.GetViewVector                                                                                     */
295 /*****************************************************************************/
296 static PyObject *M_Window_GetViewVector(PyObject *self)
297 {
298         float *vec = NULL;
299         PyObject *pylist;
300
301         if (!G.vd) {
302                 Py_INCREF (Py_None);
303                 return Py_None;
304         }
305
306         vec = G.vd->viewinv[2];
307
308         pylist = Py_BuildValue("[fff]", vec[0], vec[1], vec[2]);
309
310         if (!pylist)
311                 return (EXPP_ReturnPyObjError (PyExc_MemoryError,
312                                                 "GetViewVector: couldn't create pylist"));
313
314         return pylist;
315 }
316
317 /*****************************************************************************/
318 /* Function:                                                    M_Window_GetViewMatrix                                                                                                           */
319 /* Python equivalent:                   Blender.Window.GetViewMatrix                                                                                     */
320 /*****************************************************************************/
321 static PyObject *M_Window_GetViewMatrix(PyObject *self)
322 {
323         PyObject *viewmat;
324
325         if (!G.vd) {
326                 Py_INCREF (Py_None);
327                 return Py_None;
328         }
329
330         viewmat = newMatrixObject (G.vd->viewmat);
331
332         if (!viewmat)
333                 return (EXPP_ReturnPyObjError (PyExc_MemoryError,
334                                                 "GetViewMatrix: couldn't create matrix pyobject"));
335
336         return viewmat;
337 }
338
339 /*****************************************************************************/
340 /* Function:                                                    Window_Init                                                                                                                                                              */
341 /*****************************************************************************/
342 PyObject *Window_Init (void)
343 {
344         PyObject        *submodule, *Types;
345
346         submodule = Py_InitModule3("Blender.Window", M_Window_methods, M_Window_doc);
347
348         Types = Py_BuildValue("{s:h,s:h,s:h,s:h,s:h,s:h,s:h,s:h,s:h,s:h,s:h,s:h,s:h,s:h}",
349                 "VIEW3D", SPACE_VIEW3D, "IPO", SPACE_IPO, "OOPS", SPACE_OOPS,
350                 "BUTS", SPACE_BUTS, "FILE", SPACE_FILE, "IMAGE", SPACE_IMAGE,
351                 "INFO", SPACE_INFO, "SEQ", SPACE_SEQ, "IMASEL", SPACE_IMASEL,
352                 "SOUND", SPACE_SOUND, "ACTION", SPACE_ACTION,
353                 "TEXT", SPACE_TEXT, "NLA", SPACE_NLA, "SCRIPT", SPACE_SCRIPT);
354
355         if (Types) PyModule_AddObject(submodule, "Types", Types);
356
357         return submodule;
358 }
359