BPython:
[blender.git] / source / blender / python / api2_2x / gen_utils.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): Michel Selten, Willian P. Germano
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30 */
31
32 #include "gen_utils.h"
33 #include "constant.h"
34
35 #include <DNA_text_types.h>
36 #include <MEM_guardedalloc.h>
37
38 /*****************************************************************************/
39 /* Description: This function clamps an int to the given interval                                                */
40 /*                                                      [min, max].                                                                                                                                                                                                      */
41 /*****************************************************************************/
42 int EXPP_ClampInt (int value, int min, int max)
43 {
44         if (value < min) return min;
45         else if (value > max) return max;
46         return value;
47 }
48
49 /*****************************************************************************/
50 /* Description: This function clamps a float to the given interval                                       */
51 /*                                                      [min, max].                                                                                                                                                                                                      */
52 /*****************************************************************************/
53 float EXPP_ClampFloat (float value, float min, float max)
54 {
55         if (value < min) return min;
56         else if (value > max) return max;
57         return value;
58 }
59
60 /*****************************************************************************/
61 /* Description: This function returns true if both given strings are equal,  */
62 /*                                                      otherwise it returns false.                                                                                                                                      */
63 /*****************************************************************************/
64 int StringEqual (const char * string1, const char * string2)
65 {
66         return (strcmp(string1, string2)==0);
67 }
68
69 /*****************************************************************************/
70 /* Description: This function returns the name of the given ID struct                            */
71 /*                                                      without the Object type identifying characters prepended.                */
72 /*****************************************************************************/
73 char * GetIdName (ID *id)
74 {
75         return ((id->name)+2);
76 }
77
78 /*****************************************************************************/
79 /* Description: This function returns the ID of the object with given name       */
80 /*                                                      from a given list.                                                                                                                                                                       */
81 /*****************************************************************************/
82 ID *GetIdFromList(ListBase *list, char *name)
83 {
84         ID *id = list->first;
85
86         while (id) {
87                 if(strcmp(name, id->name+2) == 0) break;
88                         id= id->next;
89         }
90
91         return id;
92 }
93
94 /*****************************************************************************/
95 /* Description: These functions set an internal string with the given type       */
96 /*                                                      and error_msg arguments.                                                                                                                                                 */
97 /*****************************************************************************/
98
99 PyObject *EXPP_ReturnPyObjError (PyObject * type, char * error_msg)
100 { /* same as above, just to change its name smoothly */
101         PyErr_SetString (type, error_msg);
102         return NULL;
103 }
104
105 int EXPP_ReturnIntError (PyObject *type, char *error_msg)
106 {
107         PyErr_SetString (type, error_msg);
108         return -1;
109 }
110
111 /*****************************************************************************/
112 /* Description: This function increments the reference count of the given                */
113 /*                                                      Python object (usually Py_None) and returns it.                                                  */
114 /*****************************************************************************/
115
116 PyObject *EXPP_incr_ret (PyObject *object)
117 {
118         Py_INCREF (object);
119         return (object);
120 }
121
122 /*****************************************************************************/
123 /* Description: This function maps the event identifier to a string.                             */
124 /*****************************************************************************/
125 char * event_to_name(short event)
126 {
127         switch (event)
128         {
129                 case SCRIPT_FRAMECHANGED:
130                         return "FrameChanged";
131                 case SCRIPT_ONLOAD:
132                         return "OnLoad";
133                 case SCRIPT_REDRAW:
134                         return "Redraw";
135                 default:
136                         return "Unknown";
137         }
138 }       
139
140 /*****************************************************************************/
141 /* Description: Checks whether all objects in a PySequence are of a same                 */
142 /*                                                      given type.  Returns 0 if not, 1 on success.                                                             */
143 /*****************************************************************************/
144 int EXPP_check_sequence_consistency(PyObject *seq, PyTypeObject *against)
145 {
146         PyObject *ob;
147         int len = PySequence_Length(seq);
148         int i;
149
150         for (i = 0; i < len; i++) {
151                 ob = PySequence_GetItem(seq, i);
152                 if (ob->ob_type != against) {
153                         Py_DECREF(ob);
154                         return 0;
155                 }
156                 Py_DECREF(ob);
157         }
158         return 1;
159 }
160
161 PyObject *EXPP_tuple_repr(PyObject *self, int size)
162 {
163         PyObject *repr, *item;
164         int i;
165
166 /*@     note: a value must be built because the list is decrefed!
167  * otherwise we have nirvana pointers inside python.. */
168
169         repr = PyString_FromString("");
170         if (!repr) return 0;
171
172         item = PySequence_GetItem(self, 0); 
173         PyString_ConcatAndDel(&repr, PyObject_Repr(item));
174         Py_DECREF(item);
175
176         for (i = 1; i < size; i++) {
177                 item = PySequence_GetItem(self, i);
178                 PyString_ConcatAndDel(&repr, PyObject_Repr(item));
179                 Py_DECREF(item);
180         }
181
182         return repr;
183 }
184
185 /****************************************************************************/
186 /* Description: searches through a map for a pair with a given name. If the */
187 /*                                                      pair is present, its ival is stored in *ival and nonzero is */
188 /*                                                      returned. If the pair is absent, zero is returned.                                      */
189 /****************************************************************************/
190 int EXPP_map_getIntVal (const EXPP_map_pair *map, const char *sval, int *ival)
191 {
192                 while (map->sval)
193                 {
194                                 if (StringEqual(sval, map->sval))
195                                 {
196                                                 *ival = map->ival;
197                                                 return 1;
198                                 }
199                                 ++map;
200                 }
201                 return 0;
202 }
203
204 /****************************************************************************/
205 /* Description: searches through a map for a pair with a given name. If the */
206 /*                                                      pair is present, its ival is stored in *ival and nonzero is */
207 /*                                                      returned. If the pair is absent, zero is returned.                                      */
208 /* note: this function is identical to EXPP_map_getIntVal except that the               */
209 /*                       output is stored in a short value.                                                                                                                                     */
210 /****************************************************************************/
211 int EXPP_map_getShortVal (const EXPP_map_pair *map, 
212                                                                                                                                                                 const char *sval, short *ival)
213 {
214                 while (map->sval)
215                 {
216                                 if (StringEqual(sval, map->sval))
217                                 {
218                                                 *ival = map->ival;
219                                                 return 1;
220                                 }
221                                 ++map;
222                 }
223                 return 0;
224 }
225
226 /****************************************************************************/
227 /* Description: searches through a map for a pair with a given ival. If the */
228 /*                                                      pair is present, a pointer to its name is stored in *sval               */
229 /*                                                      and nonzero is returned. If the pair is absent, zero is                 */
230 /*                                                      returned.                                                                                                                                                                                                               */
231 /****************************************************************************/
232 int EXPP_map_getStrVal (const EXPP_map_pair *map, int ival, const char **sval)
233 {
234         while (map->sval)
235         {
236                 if (ival == map->ival)
237                 {
238                         *sval = map->sval;
239                         return 1;
240                 }
241                 ++map;
242         }
243         return 0;
244 }
245
246 /************************************************************************/
247 /* Scriptlink-related functions, used by scene, object, etc. bpyobjects */
248 /************************************************************************/
249 PyObject *EXPP_getScriptLinks (ScriptLink *slink, PyObject *args, int is_scene)
250 {
251         PyObject *list = NULL;
252         char *eventname = NULL;
253         int i, event = 0;
254
255         /* actually !scriptlink shouldn't happen ... */
256         if (!slink || !slink->totscript)
257                 return EXPP_incr_ret (Py_None);
258
259         if (!PyArg_ParseTuple(args, "s", &eventname))
260                 return EXPP_ReturnPyObjError (PyExc_TypeError,
261                         "expected event name (string) as argument");
262
263         list = PyList_New(0);
264         if (!list)
265                 return EXPP_ReturnPyObjError (PyExc_MemoryError,
266                         "couldn't create PyList!");
267
268         if (!strcmp(eventname, "FrameChanged"))
269                 event = SCRIPT_FRAMECHANGED;
270         else if (!strcmp(eventname, "Redraw"))
271                 event = SCRIPT_REDRAW;
272         else if (is_scene && !strcmp(eventname, "OnLoad"))
273                 event = SCRIPT_ONLOAD;
274         else
275                 return EXPP_ReturnPyObjError (PyExc_AttributeError,
276                                                 "invalid event name.");
277
278         for (i = 0; i < slink->totscript; i++) {
279                 if ((slink->flag[i] == event) && slink->scripts[i])
280                         PyList_Append(list, PyString_FromString(slink->scripts[i]->name+2));
281         }
282
283         return list;
284 }
285
286 int EXPP_clearScriptLinks (ScriptLink *slink)
287 {
288         /* actually !scriptlink shouldn't happen ... */
289         if (!slink || !slink->totscript) return -1;
290
291         if (slink->scripts) MEM_freeN(slink->scripts);
292         if (slink->flag) MEM_freeN(slink->flag);
293
294         slink->scripts = NULL;
295         slink->flag = NULL;
296         slink->totscript = slink->actscript = 0;
297
298         return 0; /* normal return */
299 }
300
301 int EXPP_addScriptLink (ScriptLink *slink, PyObject *args, int is_scene)
302 {
303         int event = 0, found_txt = 0;
304         void *stmp = NULL, *ftmp = NULL;
305         Text *bltxt = G.main->text.first;
306         char *textname = NULL;
307         char *eventname = NULL;
308
309         /* !scriptlink shouldn't happen ... */
310         if (!slink) {
311                 return EXPP_ReturnIntError (PyExc_RuntimeError,
312                         "internal error: no scriptlink!");
313         }
314
315         if (!PyArg_ParseTuple(args, "ss", &textname, &eventname))
316                 return EXPP_ReturnIntError (PyExc_TypeError,
317                         "expected two strings as arguments");
318
319         while (bltxt) {
320                 if (!strcmp(bltxt->id.name+2, textname)) {
321                         found_txt = 1;
322                         break;
323                 }
324                 bltxt = bltxt->id.next;
325         }
326
327         if (!found_txt)
328                 return EXPP_ReturnIntError (PyExc_AttributeError,
329                         "no such Blender Text.");
330
331         if (!strcmp(eventname, "FrameChanged"))
332                 event = SCRIPT_FRAMECHANGED;
333         else if (!strcmp(eventname, "Redraw"))
334                 event = SCRIPT_REDRAW;
335         else if (is_scene && !strcmp(eventname, "OnLoad"))
336                 event = SCRIPT_ONLOAD;
337         else
338                 return EXPP_ReturnIntError (PyExc_AttributeError,
339                                                 "invalid event name.");
340
341         stmp= slink->scripts;
342         slink->scripts= MEM_mallocN(sizeof(ID*)*(slink->totscript+1), "bpySlinkL");
343
344         ftmp= slink->flag;
345         slink->flag= MEM_mallocN(sizeof(short*)*(slink->totscript+1), "bpySlinkF");
346         
347         if (slink->totscript) {
348                 memcpy(slink->scripts, stmp, sizeof(ID*)*(slink->totscript));
349                 MEM_freeN(stmp);
350
351                 memcpy(slink->flag, ftmp, sizeof(short)*(slink->totscript));
352                 MEM_freeN(ftmp);
353         }
354
355         slink->scripts[slink->totscript] = (ID*)bltxt;
356         slink->flag[slink->totscript]= event;
357
358         slink->totscript++;
359                                 
360         if (slink->actscript < 1) slink->actscript = 1;
361
362         return 0; /* normal exit */
363 }