b8e8f92b83ed4c1cb3fa5e9e81251496542b5e76
[blender-staging.git] / source / blender / python / api2_2x / gen_utils.c
1 /* 
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA        02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * This is a new part of Blender.
27  *
28  * Contributor(s): Michel Selten, Willian P. Germano, Alex Mole
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31 */
32
33 #if defined(__WIN32__) || defined(WIN32) || defined(_WIN32)
34         #include <string.h>             
35 #else
36         #include <strings.h>    /*for strcasecmp */
37 #endif
38 #include <DNA_text_types.h>
39 #include <MEM_guardedalloc.h>
40
41 #include "gen_utils.h"
42 #include "constant.h"
43
44 /*****************************************************************************/
45 /* Description: This function clamps an int to the given interval         */
46 /*                                                      [min, max].        */
47 /*****************************************************************************/
48 int EXPP_ClampInt( int value, int min, int max )
49 {
50         if( value < min )
51                 return min;
52         else if( value > max )
53                 return max;
54         return value;
55 }
56
57 /*****************************************************************************/
58 /* Description: This function clamps a float to the given interval       */
59 /*                                                      [min, max].      */
60 /*****************************************************************************/
61 float EXPP_ClampFloat( float value, float min, float max )
62 {
63         if( value < min )
64                 return min;
65         else if( value > max )
66                 return max;
67         return value;
68 }
69
70 /*****************************************************************************/
71 /* Description: This function returns true if both given strings are equal,  */
72 /*              otherwise it returns false.                             */
73 /*****************************************************************************/
74 int StringEqual( const char *string1, const char *string2 )
75 {
76         return ( strcmp( string1, string2 ) == 0 );
77 }
78
79 /*****************************************************************************/
80 /* Description: This function returns the name of the given ID struct    */
81 /*               without the Object type identifying characters prepended.   */
82 /*****************************************************************************/
83 char *GetIdName( ID * id )
84 {
85         return ( ( id->name ) + 2 );
86 }
87
88 /*****************************************************************************/
89 /* Description: This function returns the ID of the object with given name   */
90 /*              from a given list.                                          */
91 /*****************************************************************************/
92 ID *GetIdFromList( ListBase * list, char *name )
93 {
94         ID *id = list->first;
95
96         while( id ) {
97                 if( strcmp( name, id->name + 2 ) == 0 )
98                         break;
99                 id = id->next;
100         }
101
102         return id;
103 }
104
105 /*****************************************************************************/
106 /* Description: These functions set an internal string with the given type   */
107 /*                and error_msg arguments.                                   */
108 /*****************************************************************************/
109
110 PyObject *EXPP_ReturnPyObjError( PyObject * type, char *error_msg )
111 {                               /* same as above, just to change its name smoothly */
112         PyErr_SetString( type, error_msg );
113         return NULL;
114 }
115
116 int EXPP_ReturnIntError( PyObject * type, char *error_msg )
117 {
118         PyErr_SetString( type, error_msg );
119         return -1;
120 }
121
122 /*****************************************************************************/
123 /* Description: This function increments the reference count of the given   */
124 /*                       Python object (usually Py_None) and returns it.    */
125 /*****************************************************************************/
126
127 PyObject *EXPP_incr_ret( PyObject * object )
128 {
129         Py_INCREF( object );
130         return ( object );
131 }
132
133 /* return Py_False - to avoid warnings, we use the fact that
134  * 0 == False in Python: */
135 PyObject *EXPP_incr_ret_False()
136 {
137         return Py_BuildValue("i", 0);
138 }
139
140 /* return Py_True - to avoid warnings, we use the fact that
141  * 1 == True in Python: */
142 PyObject *EXPP_incr_ret_True()
143 {
144         return Py_BuildValue("i", 1);
145 }
146
147 /*****************************************************************************/
148 /* Description: This function maps the event identifier to a string.      */
149 /*****************************************************************************/
150 char *event_to_name( short event )
151 {
152         switch ( event ) {
153         case SCRIPT_FRAMECHANGED:
154                 return "FrameChanged";
155         case SCRIPT_ONLOAD:
156                 return "OnLoad";
157         case SCRIPT_ONSAVE:
158                 return "OnSave";
159         case SCRIPT_REDRAW:
160                 return "Redraw";
161         default:
162                 return "Unknown";
163         }
164 }
165
166 /*****************************************************************************/
167 /* Description: Checks whether all objects in a PySequence are of a same  */
168 /*              given type.  Returns 0 if not, 1 on success.             */
169 /*****************************************************************************/
170 int EXPP_check_sequence_consistency( PyObject * seq, PyTypeObject * against )
171 {
172         PyObject *ob;
173         int len = PySequence_Length( seq );
174         int i, result = 1;
175
176         for( i = 0; i < len; i++ ) {
177                 ob = PySequence_GetItem( seq, i );
178                 if( ob == Py_None )
179                         result = 2;
180                 else if( ob->ob_type != against ) {
181                         Py_DECREF( ob );
182                         return 0;
183                 }
184                 Py_DECREF( ob );
185         }
186         return result;          /* 1 if all of 'against' type, 2 if there are (also) Nones */
187 }
188
189 PyObject *EXPP_tuple_repr( PyObject * self, int size )
190 {
191         PyObject *repr, *item;
192         int i;
193
194 /*@     note: a value must be built because the list is decrefed!
195  * otherwise we have nirvana pointers inside python.. */
196
197         repr = PyString_FromString( "" );
198         if( !repr )
199                 return 0;
200
201         item = PySequence_GetItem( self, 0 );
202         PyString_ConcatAndDel( &repr, PyObject_Repr( item ) );
203         Py_DECREF( item );
204
205         for( i = 1; i < size; i++ ) {
206                 item = PySequence_GetItem( self, i );
207                 PyString_ConcatAndDel( &repr, PyObject_Repr( item ) );
208                 Py_DECREF( item );
209         }
210
211         return repr;
212 }
213
214 /****************************************************************************/
215 /* Description: searches through a map for a pair with a given name. If the */
216 /*               pair is present, its ival is stored in *ival and nonzero is */
217 /*               returned. If the pair is absent, zero is returned.     */
218 /****************************************************************************/
219 int EXPP_map_getIntVal( const EXPP_map_pair * map, const char *sval,
220                         int *ival )
221 {
222         while( map->sval ) {
223                 if( StringEqual( sval, map->sval ) ) {
224                         *ival = map->ival;
225                         return 1;
226                 }
227                 ++map;
228         }
229         return 0;
230 }
231
232 /* same as above, but string case is ignored */
233 int EXPP_map_case_getIntVal( const EXPP_map_pair * map, const char *sval,
234                              int *ival )
235 {
236         while( map->sval ) {
237                 if( !strcasecmp( sval, map->sval ) ) {
238                         *ival = map->ival;
239                         return 1;
240                 }
241                 ++map;
242         }
243         return 0;
244 }
245
246 /****************************************************************************/
247 /* Description: searches through a map for a pair with a given name. If the */
248 /*               pair is present, its ival is stored in *ival and nonzero is */
249 /*              returned. If the pair is absent, zero is returned.           */
250 /* note: this function is identical to EXPP_map_getIntVal except that the  */
251 /*              output is stored in a short value.                         */
252 /****************************************************************************/
253 int EXPP_map_getShortVal( const EXPP_map_pair * map,
254                           const char *sval, short *ival )
255 {
256         while( map->sval ) {
257                 if( StringEqual( sval, map->sval ) ) {
258                         *ival = map->ival;
259                         return 1;
260                 }
261                 ++map;
262         }
263         return 0;
264 }
265
266 /****************************************************************************/
267 /* Description: searches through a map for a pair with a given ival. If the */
268 /*              pair is present, a pointer to its name is stored in *sval */
269 /*              and nonzero is returned. If the pair is absent, zero is */
270 /*              returned.                                               */
271 /****************************************************************************/
272 int EXPP_map_getStrVal( const EXPP_map_pair * map, int ival,
273                         const char **sval )
274 {
275         while( map->sval ) {
276                 if( ival == map->ival ) {
277                         *sval = map->sval;
278                         return 1;
279                 }
280                 ++map;
281         }
282         return 0;
283 }
284
285 /* Redraw wrappers */
286
287 /* this queues redraws if we're not in background mode: */
288 void EXPP_allqueue(unsigned short event, short val)
289 {
290         if (!G.background) allqueue(event, val);
291 }
292
293 /************************************************************************/
294 /* Scriptlink-related functions, used by scene, object, etc. bpyobjects */
295 /************************************************************************/
296 PyObject *EXPP_getScriptLinks( ScriptLink * slink, PyObject * args,
297                                int is_scene )
298 {
299         PyObject *list = NULL;
300         char *eventname = NULL;
301         int i, event = 0;
302
303         /* actually !scriptlink shouldn't happen ... */
304         if( !slink || !slink->totscript )
305                 return EXPP_incr_ret( Py_None );
306
307         if( !PyArg_ParseTuple( args, "s", &eventname ) )
308                 return EXPP_ReturnPyObjError( PyExc_TypeError,
309                                               "expected event name (string) as argument" );
310
311         list = PyList_New( 0 );
312         if( !list )
313                 return EXPP_ReturnPyObjError( PyExc_MemoryError,
314                                               "couldn't create PyList!" );
315
316         if( !strcmp( eventname, "FrameChanged" ) )
317                 event = SCRIPT_FRAMECHANGED;
318         else if( !strcmp( eventname, "Redraw" ) )
319                 event = SCRIPT_REDRAW;
320         else if( is_scene && !strcmp( eventname, "OnLoad" ) )
321                 event = SCRIPT_ONLOAD;
322         else if( is_scene && !strcmp( eventname, "OnSave" ) )
323                 event = SCRIPT_ONSAVE;
324         else
325                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
326                                               "invalid event name" );
327
328         for( i = 0; i < slink->totscript; i++ ) {
329                 if( ( slink->flag[i] == event ) && slink->scripts[i] )
330                         PyList_Append( list,
331                                        PyString_FromString( slink->scripts[i]->
332                                                             name + 2 ) );
333         }
334
335         return list;
336 }
337
338 int EXPP_clearScriptLinks( ScriptLink * slink )
339 {
340         /* actually !scriptlink shouldn't happen ... */
341         if( !slink || !slink->totscript )
342                 return -1;
343
344         if( slink->scripts )
345                 MEM_freeN( slink->scripts );
346         if( slink->flag )
347                 MEM_freeN( slink->flag );
348
349         slink->scripts = NULL;
350         slink->flag = NULL;
351         slink->totscript = slink->actscript = 0;
352
353         return 0;               /* normal return */
354 }
355
356 int EXPP_addScriptLink( ScriptLink * slink, PyObject * args, int is_scene )
357 {
358         int event = 0, found_txt = 0;
359         void *stmp = NULL, *ftmp = NULL;
360         Text *bltxt = G.main->text.first;
361         char *textname = NULL;
362         char *eventname = NULL;
363
364         /* !scriptlink shouldn't happen ... */
365         if( !slink ) {
366                 return EXPP_ReturnIntError( PyExc_RuntimeError,
367                                             "internal error: no scriptlink!" );
368         }
369
370         if( !PyArg_ParseTuple( args, "ss", &textname, &eventname ) )
371                 return EXPP_ReturnIntError( PyExc_TypeError,
372                                             "expected two strings as arguments" );
373
374         while( bltxt ) {
375                 if( !strcmp( bltxt->id.name + 2, textname ) ) {
376                         found_txt = 1;
377                         break;
378                 }
379                 bltxt = bltxt->id.next;
380         }
381
382         if( !found_txt )
383                 return EXPP_ReturnIntError( PyExc_AttributeError,
384                                             "no such Blender Text." );
385
386         if( !strcmp( eventname, "FrameChanged" ) )
387                 event = SCRIPT_FRAMECHANGED;
388         else if( !strcmp( eventname, "Redraw" ) )
389                 event = SCRIPT_REDRAW;
390         else if( is_scene && !strcmp( eventname, "OnLoad" ) )
391                 event = SCRIPT_ONLOAD;
392         else if( is_scene && !strcmp( eventname, "OnSave" ) )
393                 event = SCRIPT_ONSAVE;
394         else
395                 return EXPP_ReturnIntError( PyExc_AttributeError,
396                                             "invalid event name." );
397
398         stmp = slink->scripts;
399         slink->scripts =
400                 MEM_mallocN( sizeof( ID * ) * ( slink->totscript + 1 ),
401                              "bpySlinkL" );
402
403         ftmp = slink->flag;
404         slink->flag =
405                 MEM_mallocN( sizeof( short * ) * ( slink->totscript + 1 ),
406                              "bpySlinkF" );
407
408         if( slink->totscript ) {
409                 memcpy( slink->scripts, stmp,
410                         sizeof( ID * ) * ( slink->totscript ) );
411                 MEM_freeN( stmp );
412
413                 memcpy( slink->flag, ftmp,
414                         sizeof( short ) * ( slink->totscript ) );
415                 MEM_freeN( ftmp );
416         }
417
418         slink->scripts[slink->totscript] = ( ID * ) bltxt;
419         slink->flag[slink->totscript] = event;
420
421         slink->totscript++;
422
423         if( slink->actscript < 1 )
424                 slink->actscript = 1;
425
426         return 0;               /* normal exit */
427 }