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