0c57488a2664cb629e551cde0f5cd69cece7c59a
[blender.git] / source / blender / python / api2_2x / World.c
1 /* 
2  * $Id$
3  *
4  * ***** BEGIN GPL 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.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA        02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * This is a new part of Blender.
24  *
25  * Contributor(s): Jacques Guignot, Johnny Matthews
26  *
27  * ***** END GPL LICENSE BLOCK *****
28 */
29
30 /**
31  * \file World.c
32  * \ingroup scripts
33  * \brief Blender.World Module and World Data PyObject implementation.
34  *
35  * Note: Parameters between "<" and ">" are optional.  But if one of them is
36  * given, all preceding ones must be given, too.  Of course, this only relates
37  * to the Python functions and methods described here and only inside Python
38  * code. [ This will go to another file later, probably the main exppython
39  * doc file].  XXX Better: put optional args with their default value:
40  * (self, name = "MyName")
41  */
42
43 #include "World.h"  /*This must come first*/
44
45 #include "DNA_scene_types.h"  /* for G.scene */
46 #include "BKE_global.h"
47 #include "BKE_world.h"
48 #include "BKE_main.h"
49 #include "BKE_library.h"
50 #include "BKE_texture.h"
51 #include "BLI_blenlib.h"
52 #include "BSE_editipo.h"
53 #include "BIF_keyframing.h"
54 #include "BIF_space.h"
55 #include "mydevice.h"
56 #include "Ipo.h"
57 #include "MTex.h"
58 #include "gen_utils.h"
59 #include "gen_library.h"
60 #include "MEM_guardedalloc.h"
61
62 #define IPOKEY_ZENITH   0
63 #define IPOKEY_HORIZON  1
64 #define IPOKEY_MIST     2
65 #define IPOKEY_STARS    3
66 #define IPOKEY_OFFSET   4
67 #define IPOKEY_SIZE     5
68 /*****************************************************************************/
69 /* Python BPy_World methods declarations:                                   */
70 /*****************************************************************************/
71 static PyObject *World_getRange( BPy_World * self );
72 static PyObject *World_setRange( BPy_World * self, PyObject * args );
73 static PyObject *World_getIpo( BPy_World * self );
74 static PyObject *World_oldsetIpo( BPy_World * self, PyObject * args );
75 static int       World_setIpo( BPy_World * self, PyObject * args );
76 static PyObject *World_clearIpo( BPy_World * self );
77 static PyObject *World_insertIpoKey( BPy_World * self, PyObject * args );
78 static PyObject *World_getMode( BPy_World * self );
79 static PyObject *World_oldsetMode( BPy_World * self, PyObject * args );
80 static int       World_setMode( BPy_World * self, PyObject * args );
81 static PyObject *World_getSkytype( BPy_World * self );
82 static PyObject *World_oldsetSkytype( BPy_World * self, PyObject * args );
83 static int       World_setSkytype( BPy_World * self, PyObject * args );
84 static PyObject *World_getMistype( BPy_World * self );
85 static PyObject *World_oldsetMistype( BPy_World * self, PyObject * args );
86 static int       World_setMistype( BPy_World * self, PyObject * args );
87 static PyObject *World_getHor( BPy_World * self );
88 static PyObject *World_oldsetHor( BPy_World * self, PyObject * args );
89 static int       World_setHor( BPy_World * self, PyObject * args );
90 static PyObject *World_getZen( BPy_World * self );
91 static PyObject *World_oldsetZen( BPy_World * self, PyObject * args );
92 static int       World_setZen( BPy_World * self, PyObject * args );
93 static PyObject *World_getAmb( BPy_World * self );
94 static PyObject *World_oldsetAmb( BPy_World * self, PyObject * args );
95 static int       World_setAmb( BPy_World * self, PyObject * args );
96 static PyObject *World_getStar( BPy_World * self );
97 static PyObject *World_oldsetStar( BPy_World * self, PyObject * args );
98 static int       World_setStar( BPy_World * self, PyObject * args );
99 static PyObject *World_getMist( BPy_World * self );
100 static PyObject *World_oldsetMist( BPy_World * self, PyObject * args );
101 static int       World_setMist( BPy_World * self, PyObject * args );
102 static PyObject *World_getScriptLinks( BPy_World * self, PyObject * value );
103 static PyObject *World_addScriptLink( BPy_World * self, PyObject * args );
104 static PyObject *World_clearScriptLinks( BPy_World * self, PyObject * args );
105 static PyObject *World_setCurrent( BPy_World * self );
106 static PyObject *World_getTextures( BPy_World * self );
107 static int               World_setTextures( BPy_World * self, PyObject * value );
108 static PyObject *World_copy( BPy_World * self );
109
110
111 /*****************************************************************************/
112 /* Python API function prototypes for the World module.                     */
113 /*****************************************************************************/
114 static PyObject *M_World_New( PyObject * self, PyObject * args,
115                               PyObject * keywords );
116 static PyObject *M_World_Get( PyObject * self, PyObject * args );
117 static PyObject *M_World_GetCurrent( PyObject * self );
118
119
120 /*****************************************************************************/
121 /* Python World_Type callback function prototypes:                      */
122 /*****************************************************************************/
123 //static int World_Print (BPy_World *self, FILE *fp, int flags);
124 static int World_Compare( BPy_World * a, BPy_World * b );
125 static PyObject *World_Repr( BPy_World * self );
126
127
128
129 /*****************************************************************************/
130 /* The following string definitions are used for documentation strings.      */
131 /* In Python these will be written to the console when doing a               */
132 /* Blender.World.__doc__                                                     */
133 /*****************************************************************************/
134 static char M_World_doc[] = "The Blender World module\n\n\
135 This module provides access to **World Data** objects in Blender\n\n";
136
137 static char M_World_New_doc[] = "() - return a new World object";
138
139 static char M_World_Get_doc[] =
140         "(name) - return the world with the name 'name', \
141 returns None if not found.\n If 'name' is not specified, \
142 it returns a list of all worlds in the\ncurrent scene.";
143 static char M_World_GetCurrent_doc[] = "() - returns the current world, or \
144 None if the Scene has no world";
145
146
147
148 /*****************************************************************************/
149 /* Python method structure definition for Blender.World module:              */
150 /*****************************************************************************/
151 struct PyMethodDef M_World_methods[] = {
152         {"New", ( PyCFunction ) M_World_New, METH_VARARGS | METH_KEYWORDS,
153          M_World_New_doc},
154         {"Get", M_World_Get, METH_VARARGS, M_World_Get_doc},
155         {"GetActive", ( PyCFunction ) M_World_GetCurrent, METH_NOARGS,
156          M_World_GetCurrent_doc},
157         {"GetCurrent", ( PyCFunction ) M_World_GetCurrent, METH_NOARGS,
158          M_World_GetCurrent_doc},
159         {"get", M_World_Get, METH_VARARGS, M_World_Get_doc},
160         {NULL, NULL, 0, NULL}
161 };
162
163
164
165 /*****************************************************************************/
166 /* Python BPy_World methods table:                                          */
167 /*****************************************************************************/
168 static PyMethodDef BPy_World_methods[] = {
169         {"getRange", ( PyCFunction ) World_getRange, METH_NOARGS,
170          "() - Return World Range"},
171         {"setRange", ( PyCFunction ) World_setRange, METH_VARARGS,
172          "() - Change this World's range"},
173         {"getIpo", ( PyCFunction ) World_getIpo, METH_NOARGS,
174          "() - Return World Ipo"},
175         {"setIpo", ( PyCFunction ) World_oldsetIpo, METH_VARARGS,
176          "() - Change this World's ipo"},
177         {"clearIpo", ( PyCFunction ) World_clearIpo, METH_VARARGS,
178          "() - Unlink Ipo from this World"},
179         {"getName", ( PyCFunction ) GenericLib_getName, METH_NOARGS,
180          "() - Return World Data name"},
181         {"setName", ( PyCFunction ) GenericLib_setName_with_method, METH_VARARGS,
182          "() - Set World Data name"},
183         {"getMode", ( PyCFunction ) World_getMode, METH_NOARGS,
184          "() - Return World Data mode"},
185         {"setMode", ( PyCFunction ) World_oldsetMode, METH_VARARGS,
186          "(i) - Set World Data mode"},
187         {"getSkytype", ( PyCFunction ) World_getSkytype, METH_NOARGS,
188          "() - Return World Data skytype"},
189         {"setSkytype", ( PyCFunction ) World_oldsetSkytype, METH_VARARGS,
190          "() - Return World Data skytype"},
191         {"getMistype", ( PyCFunction ) World_getMistype, METH_NOARGS,
192          "() - Return World Data mistype"},
193         {"setMistype", ( PyCFunction ) World_oldsetMistype, METH_VARARGS,
194          "() - Return World Data mistype"},
195         {"getHor", ( PyCFunction ) World_getHor, METH_NOARGS,
196          "() - Return World Data hor"},
197         {"setHor", ( PyCFunction ) World_oldsetHor, METH_VARARGS,
198          "() - Return World Data hor"},
199         {"getZen", ( PyCFunction ) World_getZen, METH_NOARGS,
200          "() - Return World Data zen"},
201         {"setZen", ( PyCFunction ) World_oldsetZen, METH_VARARGS,
202          "() - Return World Data zen"},
203         {"getAmb", ( PyCFunction ) World_getAmb, METH_NOARGS,
204          "() - Return World Data amb"},
205         {"setAmb", ( PyCFunction ) World_oldsetAmb, METH_VARARGS,
206          "() - Return World Data amb"},
207         {"getStar", ( PyCFunction ) World_getStar, METH_NOARGS,
208          "() - Return World Data star"},
209         {"setStar", ( PyCFunction ) World_oldsetStar, METH_VARARGS,
210          "() - Return World Data star"},
211         {"getMist", ( PyCFunction ) World_getMist, METH_NOARGS,
212          "() - Return World Data mist"},
213         {"setMist", ( PyCFunction ) World_oldsetMist, METH_VARARGS,
214          "() - Return World Data mist"},
215         {"getScriptLinks", ( PyCFunction ) World_getScriptLinks, METH_O,
216          "(eventname) - Get a list of this world's scriptlinks (Text names) "
217          "of the given type\n"
218          "(eventname) - string: FrameChanged, Redraw or Render."},
219         {"addScriptLink", ( PyCFunction ) World_addScriptLink, METH_VARARGS,
220          "(text, evt) - Add a new world scriptlink.\n"
221          "(text) - string: an existing Blender Text name;\n"
222          "(evt) string: FrameChanged, Redraw or Render."},
223         {"clearScriptLinks", ( PyCFunction ) World_clearScriptLinks,
224          METH_VARARGS,
225          "() - Delete all scriptlinks from this world.\n"
226          "([s1<,s2,s3...>]) - Delete specified scriptlinks from this world."},
227         {"setCurrent", ( PyCFunction ) World_setCurrent, METH_NOARGS,
228          "() - Makes this world the active world for the current scene."},
229         {"makeActive", ( PyCFunction ) World_setCurrent, METH_NOARGS,
230          "please use setCurrent instead, this alias will be removed."},
231         {"insertIpoKey", ( PyCFunction ) World_insertIpoKey, METH_VARARGS,
232          "( World IPO type ) - Inserts a key into the IPO"},
233         {"__copy__", ( PyCFunction ) World_copy, METH_NOARGS,
234          "() - Makes a copy of this world."},
235         {"copy", ( PyCFunction ) World_copy, METH_NOARGS,
236          "() - Makes a copy of this world."},
237         {NULL, NULL, 0, NULL}
238 };
239
240 /*****************************************************************************/
241 /* Python attributes get/set structure:                                      */
242 /*****************************************************************************/
243 static PyGetSetDef BPy_World_getseters[] = {
244         GENERIC_LIB_GETSETATTR,
245         {"skytype", (getter)World_getSkytype, (setter)World_setSkytype,
246          "sky settings as a list", NULL},
247         {"mode", (getter)World_getMode, (setter)World_setMode,
248          "world mode", NULL},
249         {"mistype", (getter)World_getMistype, (setter)World_setMistype,
250          "world mist type", NULL},
251         {"hor", (getter)World_getHor, (setter)World_setHor,
252          "world horizon color", NULL},
253         {"amb", (getter)World_getAmb, (setter)World_setAmb,
254          "world ambient color", NULL},
255         {"mist", (getter)World_getMist, (setter)World_setMist,
256          "world mist settings", NULL},
257         {"ipo", (getter)World_getIpo, (setter)World_setIpo,
258          "world ipo", NULL},
259     {"textures", (getter)World_getTextures, (setter)World_setTextures,
260      "The World's texture list as a tuple",
261      NULL},
262         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
263 };
264
265 /*****************************************************************************/
266 /* Python World_Type structure definition:                                */
267 /*****************************************************************************/
268 PyTypeObject World_Type = {
269         PyObject_HEAD_INIT( NULL ) 
270         0,      /* ob_size */
271         "World",                /* tp_name */
272         sizeof( BPy_World ),    /* tp_basicsize */
273         0,                      /* tp_itemsize */
274         /* methods */
275         NULL,   /* tp_dealloc */
276         0,              /* tp_print */
277         NULL,   /* tp_getattr */
278         NULL,   /* tp_setattr */
279         ( cmpfunc ) World_Compare,      /* tp_compare */
280         ( reprfunc ) World_Repr,        /* tp_repr */
281
282         /* Method suites for standard classes */
283
284         NULL,                       /* PyNumberMethods *tp_as_number; */
285         NULL,                       /* PySequenceMethods *tp_as_sequence; */
286         NULL,                       /* PyMappingMethods *tp_as_mapping; */
287
288         /* More standard operations (here for binary compatibility) */
289
290         ( hashfunc ) GenericLib_hash,   /* hashfunc tp_hash; */
291         NULL,                       /* ternaryfunc tp_call; */
292         NULL,                       /* reprfunc tp_str; */
293         NULL,                       /* getattrofunc tp_getattro; */
294         NULL,                       /* setattrofunc tp_setattro; */
295
296         /* Functions to access object as input/output buffer */
297         NULL,                       /* PyBufferProcs *tp_as_buffer; */
298
299   /*** Flags to define presence of optional/expanded features ***/
300         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
301
302         NULL,                       /*  char *tp_doc;  Documentation string */
303   /*** Assigned meaning in release 2.0 ***/
304         /* call function for all accessible objects */
305         NULL,                       /* traverseproc tp_traverse; */
306
307         /* delete references to contained objects */
308         NULL,                       /* inquiry tp_clear; */
309
310   /***  Assigned meaning in release 2.1 ***/
311   /*** rich comparisons ***/
312         NULL,                       /* richcmpfunc tp_richcompare; */
313
314   /***  weak reference enabler ***/
315         0,                          /* long tp_weaklistoffset; */
316
317   /*** Added in release 2.2 ***/
318         /*   Iterators */
319         NULL,                       /* getiterfunc tp_iter; */
320         NULL,                       /* iternextfunc tp_iternext; */
321
322   /*** Attribute descriptor and subclassing stuff ***/
323         BPy_World_methods,           /* struct PyMethodDef *tp_methods; */
324         NULL,                       /* struct PyMemberDef *tp_members; */
325         BPy_World_getseters,         /* struct PyGetSetDef *tp_getset; */
326         NULL,                       /* struct _typeobject *tp_base; */
327         NULL,                       /* PyObject *tp_dict; */
328         NULL,                       /* descrgetfunc tp_descr_get; */
329         NULL,                       /* descrsetfunc tp_descr_set; */
330         0,                          /* long tp_dictoffset; */
331         NULL,                       /* initproc tp_init; */
332         NULL,                       /* allocfunc tp_alloc; */
333         NULL,                       /* newfunc tp_new; */
334         /*  Low-level free-memory routine */
335         NULL,                       /* freefunc tp_free;  */
336         /* For PyObject_IS_GC */
337         NULL,                       /* inquiry tp_is_gc;  */
338         NULL,                       /* PyObject *tp_bases; */
339         /* method resolution order */
340         NULL,                       /* PyObject *tp_mro;  */
341         NULL,                       /* PyObject *tp_cache; */
342         NULL,                       /* PyObject *tp_subclasses; */
343         NULL,                       /* PyObject *tp_weaklist; */
344         NULL
345 };
346
347 /**
348  * \defgroup World_Module Blender.World module functions
349  *
350  */
351
352 /*@{*/
353
354 /**
355  * \brief Python module function: Blender.World.New()
356  *
357  * This is the .New() function of the Blender.World submodule. It creates
358  * new World Data in Blender and returns its Python wrapper object.  The
359  * name parameter is mandatory.
360  * \param <name> - string: The World Data name.
361  * \return A new World PyObject.
362  */
363
364 static PyObject *M_World_New( PyObject * self, PyObject * args,
365                               PyObject * kwords )
366 {
367         char *name = NULL;
368         BPy_World *pyworld;
369         World *blworld;
370
371         if( !PyArg_ParseTuple( args, "s", &name ) )
372                 return ( EXPP_ReturnPyObjError( PyExc_TypeError,
373                                                 "expected       int argument" ) );
374
375
376         blworld = add_world( name );
377
378         if( blworld ) {
379                 /* return user count to zero because add_world() inc'd it */
380                 blworld->id.us = 0;
381                 /* create python wrapper obj */
382                 pyworld =
383                         ( BPy_World * ) PyObject_NEW( BPy_World, &World_Type );
384         } else
385                 return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
386                                                 "couldn't create World Data in Blender" ) );
387
388         if( pyworld == NULL )
389                 return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
390                                                 "couldn't create World Data object" ) );
391
392         pyworld->world = blworld;
393
394         return ( PyObject * ) pyworld;
395 }
396
397 /**
398  * \brief Python module function: Blender.World.Get()
399  *
400  * This is the .Get() function of the Blender.World submodule.  It searches
401  * the list of current World Data objects and returns a Python wrapper for
402  * the one with the name provided by the user.  If called with no arguments,
403  * it returns a list of all current World Data object names in Blender.
404  * \param <name> - string: The name of an existing Blender World Data object.
405  * \return () - A list with the names of all current World Data objects;\n
406  * \return (name) - A Python wrapper for the World Data called 'name'
407  * in Blender.
408  */
409
410 static PyObject *M_World_Get( PyObject * self, PyObject * args )
411 {
412
413         char *name = NULL;
414         World *world_iter;
415         PyObject *worldlist;
416         char error_msg[64];
417
418         if( !PyArg_ParseTuple( args, "|s", &name ) )
419                 return ( EXPP_ReturnPyObjError( PyExc_TypeError,
420                                                 "expected string argument (or nothing)" ) );
421
422         if( name ) {            /* (name) - Search world by name */
423                 world_iter = ( World * ) GetIdFromList( &( G.main->world ), name );
424                 
425                 if( world_iter == NULL ) {      /* Requested world doesn't exist */
426                         PyOS_snprintf( error_msg, sizeof( error_msg ),
427                                        "World \"%s\" not found", name );
428                         return ( EXPP_ReturnPyObjError
429                                  ( PyExc_NameError, error_msg ) );
430                 }
431
432                 return ( PyObject * ) World_CreatePyObject(world_iter);
433         }
434
435         else {                  /* return a list of all worlds in the scene */
436                 world_iter = G.main->world.first;
437                 worldlist = PyList_New( 0 );
438                 if( worldlist == NULL )
439                         return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
440                                                         "couldn't create PyList" ) );
441
442                 while( world_iter ) {
443                         BPy_World *found_world =
444                                 ( BPy_World * ) PyObject_NEW( BPy_World,
445                                                               &World_Type );
446                         found_world->world = world_iter;
447                         PyList_Append( worldlist, ( PyObject * ) found_world );
448                         Py_DECREF(found_world);
449                         
450                         world_iter = world_iter->id.next;
451                 }
452                 return ( worldlist );
453         }
454
455 }
456
457 static PyObject *M_World_GetCurrent( PyObject * self )
458 {
459         BPy_World *w = NULL;
460 #if 0   /* add back in when bpy becomes "official" */
461         static char warning = 1;
462         if( warning ) {
463                 printf("Blender.World.GetCurrent() deprecated!\n\tuse bpy.scenes.world instead\n");
464                 --warning;
465         }
466 #endif
467
468         if( !G.scene->world )
469                 Py_RETURN_NONE;
470         
471         w = ( BPy_World * ) PyObject_NEW( BPy_World, &World_Type );
472         w->world = G.scene->world;
473         return ( PyObject * ) w;
474 }
475
476 /*@}*/
477
478 /**
479  * \brief Initializes the Blender.World submodule
480  *
481  * This function is used by Blender_Init() in Blender.c to register the
482  * Blender.World submodule in the main Blender module.
483  * \return PyObject*: The initialized submodule.
484  */
485
486 PyObject *World_Init( void )
487 {
488         PyObject *submodule;
489
490         if( PyType_Ready( &World_Type ) < 0 )
491                 return NULL;
492
493         submodule = Py_InitModule3( "Blender.World",
494                                     M_World_methods, M_World_doc );
495
496         PyModule_AddIntConstant( submodule, "ZENITH",      IPOKEY_ZENITH );
497         PyModule_AddIntConstant( submodule, "HORIZON",     IPOKEY_HORIZON );
498         PyModule_AddIntConstant( submodule, "MIST",        IPOKEY_MIST );
499         PyModule_AddIntConstant( submodule, "STARS",       IPOKEY_STARS );
500         PyModule_AddIntConstant( submodule, "OFFSET",      IPOKEY_OFFSET );
501         PyModule_AddIntConstant( submodule, "SIZE",        IPOKEY_SIZE );
502
503         return ( submodule );
504 }
505
506 /*****************************************************************************/
507 /* Python BPy_World methods:                                            */
508 /*****************************************************************************/
509 static PyObject *World_getRange( BPy_World * self )
510 {
511         return PyFloat_FromDouble( self->world->range );
512 }
513
514 static PyObject *World_setRange( BPy_World * self, PyObject * args )
515 {
516         float range = 0.f;
517         if( !PyArg_ParseTuple( args, "f", &range ) )
518                 return ( EXPP_ReturnPyObjError
519                          ( PyExc_TypeError, "expected a float argument" ) );
520         self->world->range = range;
521         Py_RETURN_NONE;
522 }
523
524
525 static PyObject *World_getIpo( BPy_World * self )
526 {
527         struct Ipo *ipo = self->world->ipo;
528
529         if( !ipo )
530                 Py_RETURN_NONE;
531
532         return Ipo_CreatePyObject( ipo );
533 }
534
535 static int World_setIpo( BPy_World * self, PyObject * value )
536 {
537         return GenericLib_assignData(value, (void **) &self->world->ipo, 0, 1, ID_IP, ID_WO);
538 }
539
540 static PyObject *World_oldsetIpo( BPy_World * self, PyObject * args )
541 {
542         return EXPP_setterWrapper( (void *)self, args, (setter)World_setIpo );
543 }
544
545 static PyObject *World_clearIpo( BPy_World * self )
546 {
547         World *world = self->world;
548         Ipo *ipo = ( Ipo * ) world->ipo;
549
550         if( ipo ) {
551                 ID *id = &ipo->id;
552                 if( id->us > 0 )
553                         id->us--;
554                 world->ipo = NULL;
555
556                 return EXPP_incr_ret_True();
557         }
558
559         return EXPP_incr_ret_False(); /* no ipo found */
560 }
561
562 /**
563  * \brief World PyMethod getSkytype
564  *
565  * \return int : The World Data skytype.
566  */
567
568 static PyObject *World_getSkytype( BPy_World * self )
569 {
570         return PyInt_FromLong( ( long ) self->world->skytype );
571 }
572
573
574 /**
575  * \brief World PyMethod setSkytype
576  *
577  * \return int : The World Data skytype.
578  */
579
580 static int World_setSkytype( BPy_World * self, PyObject * value )
581 {
582         if( !PyInt_Check(value) )
583                 return ( EXPP_ReturnIntError( PyExc_TypeError,
584                                                 "expected int argument" ) );
585         self->world->skytype = (short)PyInt_AsLong(value);
586         return 0;
587 }
588
589 static PyObject *World_oldsetSkytype( BPy_World * self, PyObject * args )
590 {
591         return EXPP_setterWrapper( (void *)self, args, (setter)World_setSkytype );
592 }
593
594
595 /**
596  * \brief World PyMethod getMode
597  *
598  * \return int : The World Data mode.
599  */
600
601 static PyObject *World_getMode( BPy_World * self )
602 {
603         return PyInt_FromLong( ( long ) self->world->mode );
604 }
605
606
607 /**
608  * \brief World PyMethod setMode
609  *
610  * \return int : The World Data mode.
611  */
612
613 static int World_setMode( BPy_World * self, PyObject * value )
614 {
615         if( !PyInt_Check(value) )
616                 return ( EXPP_ReturnIntError( PyExc_TypeError,
617                                                 "expected int argument" ) );
618         self->world->mode = (short)PyInt_AsLong(value);
619         return 0;
620 }
621
622 static PyObject *World_oldsetMode( BPy_World * self, PyObject * args )
623 {
624         return EXPP_setterWrapper( (void *)self, args, (setter)World_setMode );
625 }
626
627
628
629 /**
630  * \brief World PyMethod getMistype
631  *
632  * \return int : The World Data mistype.
633  */
634
635 static PyObject *World_getMistype( BPy_World * self )
636 {
637         return PyInt_FromLong( ( long ) self->world->mistype );
638 }
639
640
641 /**
642  * \brief World PyMethod setMistype
643  *
644  * \return int : The World Data mistype.
645  */
646
647 static int World_setMistype( BPy_World * self, PyObject * value )
648 {
649         if( !PyInt_Check(value) )
650                 return ( EXPP_ReturnIntError( PyExc_TypeError,
651                                                 "expected int argument" ) );
652         self->world->mistype = (short)PyInt_AsLong(value);
653         return 0;
654 }
655
656 static PyObject *World_oldsetMistype( BPy_World * self, PyObject * args )
657 {
658         return EXPP_setterWrapper( (void *)self, args, (setter)World_setMistype );
659 }
660
661
662
663 static PyObject *World_getHor( BPy_World * self )
664 {
665         PyObject *attr = PyList_New( 3 );
666         if( !attr )
667                 return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
668                                                 "couldn't create list" ) );
669         PyList_SET_ITEM( attr, 0, PyFloat_FromDouble( self->world->horr ) );
670         PyList_SET_ITEM( attr, 1, PyFloat_FromDouble( self->world->horg ) );
671         PyList_SET_ITEM( attr, 2, PyFloat_FromDouble( self->world->horb ) );
672         return attr;
673 }
674
675
676 static int World_setHor( BPy_World * self, PyObject * value )
677 {
678         if( !PyList_Check( value ) )
679                 return ( EXPP_ReturnIntError( PyExc_TypeError,
680                                                 "expected list argument" ) );
681         if( PyList_Size( value ) != 3 )
682                 return ( EXPP_ReturnIntError
683                          ( PyExc_TypeError, "list size must be 3" ) );
684         self->world->horr = (float)PyFloat_AsDouble( PyList_GetItem( value, 0 ) );
685         self->world->horg = (float)PyFloat_AsDouble( PyList_GetItem( value, 1 ) );
686         self->world->horb = (float)PyFloat_AsDouble( PyList_GetItem( value, 2 ) );
687         return 0;
688 }
689
690 static PyObject *World_oldsetHor( BPy_World * self, PyObject * args )
691 {
692         return EXPP_setterWrapper( (void *)self, args, (setter)World_setHor );
693 }
694
695 static PyObject *World_getZen( BPy_World * self )
696 {
697         PyObject *attr = PyList_New( 3 );
698         if( !attr )
699                 return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
700                                                 "couldn't create list" ) );
701         PyList_SET_ITEM( attr, 0, PyFloat_FromDouble( self->world->zenr ) );
702         PyList_SET_ITEM( attr, 1, PyFloat_FromDouble( self->world->zeng ) );
703         PyList_SET_ITEM( attr, 2, PyFloat_FromDouble( self->world->zenb ) );
704         return attr;
705 }
706
707
708 static int World_setZen( BPy_World * self, PyObject * value )
709 {
710         if( !PyList_Check( value ) )
711                 return ( EXPP_ReturnIntError( PyExc_TypeError,
712                                                 "expected list argument" ) );
713         if( PyList_Size( value ) != 3 )
714                 return ( EXPP_ReturnIntError
715                          ( PyExc_TypeError, "list size must be 3" ) );
716         self->world->zenr = (float)PyFloat_AsDouble( PyList_GetItem( value, 0 ) );
717         self->world->zeng = (float)PyFloat_AsDouble( PyList_GetItem( value, 1 ) );
718         self->world->zenb = (float)PyFloat_AsDouble( PyList_GetItem( value, 2 ) );
719         return 0;
720 }
721
722 static PyObject *World_oldsetZen( BPy_World * self, PyObject * args )
723 {
724         return EXPP_setterWrapper( (void *)self, args, (setter)World_setZen );
725 }
726
727
728 static PyObject *World_getAmb( BPy_World * self )
729 {
730         PyObject *attr = PyList_New( 3 );
731         if( !attr )
732                 return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
733                                                 "couldn't create list" ) );
734         PyList_SET_ITEM( attr, 0, PyFloat_FromDouble( self->world->ambr ) );
735         PyList_SET_ITEM( attr, 1, PyFloat_FromDouble( self->world->ambg ) );
736         PyList_SET_ITEM( attr, 2, PyFloat_FromDouble( self->world->ambb ) );
737         return attr;
738 }
739
740
741 static int World_setAmb( BPy_World * self, PyObject * value )
742 {
743         if( !PyList_Check( value ) )
744                 return ( EXPP_ReturnIntError( PyExc_TypeError,
745                                                 "expected list argument" ) );
746         if( PyList_Size( value ) != 3 )
747                 return ( EXPP_ReturnIntError
748                          ( PyExc_TypeError, "wrong list size" ) );
749         self->world->ambr = (float)PyFloat_AsDouble( PyList_GetItem( value, 0 ) );
750         self->world->ambg = (float)PyFloat_AsDouble( PyList_GetItem( value, 1 ) );
751         self->world->ambb = (float)PyFloat_AsDouble( PyList_GetItem( value, 2 ) );
752         return 0;
753 }
754
755 static PyObject *World_oldsetAmb( BPy_World * self, PyObject * args )
756 {
757         return EXPP_setterWrapper( (void *)self, args, (setter)World_setAmb );
758 }
759
760 static PyObject *World_getStar( BPy_World * self )
761 {
762         PyObject *attr = PyList_New( 7 );
763         if( !attr )
764                 return ( EXPP_ReturnPyObjError
765                          ( PyExc_RuntimeError, "couldn't create list" ) );
766         PyList_SET_ITEM( attr, 0, PyFloat_FromDouble( self->world->starr ) );
767         PyList_SET_ITEM( attr, 1, PyFloat_FromDouble( self->world->starg ) );
768         PyList_SET_ITEM( attr, 2, PyFloat_FromDouble( self->world->starb ) );
769         PyList_SET_ITEM( attr, 3, PyFloat_FromDouble( self->world->starsize ) );
770         PyList_SET_ITEM( attr, 4, PyFloat_FromDouble( self->world->starmindist ) );
771         PyList_SET_ITEM( attr, 5, PyFloat_FromDouble( self->world->stardist ) );
772         PyList_SET_ITEM( attr, 6, PyFloat_FromDouble( self->world->starcolnoise ) );
773         return attr;
774 }
775
776
777 static int World_setStar( BPy_World * self, PyObject * value )
778 {
779         if( !PyList_Check( value ) )
780                 return ( EXPP_ReturnIntError
781                          ( PyExc_TypeError, "expected list argument" ) );
782         if( PyList_Size( value ) != 7 )
783                 return ( EXPP_ReturnIntError
784                          ( PyExc_TypeError, "wrong list size" ) );
785         self->world->starr = (float)PyFloat_AsDouble( PyList_GetItem( value, 0 ) );
786         self->world->starg = (float)PyFloat_AsDouble( PyList_GetItem( value, 1 ) );
787         self->world->starb = (float)PyFloat_AsDouble( PyList_GetItem( value, 2 ) );
788         self->world->starsize =
789                 (float)PyFloat_AsDouble( PyList_GetItem( value, 3 ) );
790         self->world->starmindist =
791                 (float)PyFloat_AsDouble( PyList_GetItem( value, 4 ) );
792         self->world->stardist =
793                 (float)PyFloat_AsDouble( PyList_GetItem( value, 5 ) );
794         self->world->starcolnoise =
795                 (float)PyFloat_AsDouble( PyList_GetItem( value, 6 ) );
796         return 0;
797 }
798
799 static PyObject *World_oldsetStar( BPy_World * self, PyObject * args )
800 {
801         return EXPP_setterWrapper( (void *)self, args, (setter)World_setStar );
802 }
803
804
805 static PyObject *World_getMist( BPy_World * self )
806 {
807         PyObject *attr = PyList_New( 4 );
808         if( !attr )
809                 return ( EXPP_ReturnPyObjError
810                          ( PyExc_RuntimeError, "couldn't create list" ) );
811         PyList_SET_ITEM( attr, 0, PyFloat_FromDouble( self->world->misi ) );
812         PyList_SET_ITEM( attr, 1, PyFloat_FromDouble( self->world->miststa ) );
813         PyList_SET_ITEM( attr, 2, PyFloat_FromDouble( self->world->mistdist ) );
814         PyList_SET_ITEM( attr, 3, PyFloat_FromDouble( self->world->misthi ) );
815         return attr;
816 }
817
818 static int World_setMist( BPy_World * self, PyObject * value )
819 {
820         if( !PyList_Check( value ) )
821                 return ( EXPP_ReturnIntError
822                          ( PyExc_TypeError, "expected list argument" ) );
823         if( PyList_Size( value ) != 4 )
824                 return ( EXPP_ReturnIntError
825                          ( PyExc_TypeError, "wrong list size" ) );
826         self->world->misi = (float)PyFloat_AsDouble( PyList_GetItem( value, 0 ) );
827         self->world->miststa =
828                 (float)PyFloat_AsDouble( PyList_GetItem( value, 1 ) );
829         self->world->mistdist =
830                 (float)PyFloat_AsDouble( PyList_GetItem( value, 2 ) );
831         self->world->misthi =
832                 (float)PyFloat_AsDouble( PyList_GetItem( value, 3 ) );
833         return 0;
834 }
835
836 static PyObject *World_oldsetMist( BPy_World * self, PyObject * args )
837 {
838         return EXPP_setterWrapper( (void *)self, args, (setter)World_setMist );
839 }
840
841
842 /* world.addScriptLink */
843 static PyObject *World_addScriptLink( BPy_World * self, PyObject * args )
844 {
845         World *world = self->world;
846         ScriptLink *slink = NULL;
847
848         slink = &( world )->scriptlink;
849
850         return EXPP_addScriptLink( slink, args, 0 );
851 }
852
853 /* world.clearScriptLinks */
854 static PyObject *World_clearScriptLinks( BPy_World * self, PyObject * args )
855 {
856         World *world = self->world;
857         ScriptLink *slink = NULL;
858
859         slink = &( world )->scriptlink;
860
861         return EXPP_clearScriptLinks( slink, args );
862 }
863
864 /* world.getScriptLinks */
865 static PyObject *World_getScriptLinks( BPy_World * self, PyObject * value )
866 {
867         World *world = self->world;
868         ScriptLink *slink = NULL;
869         PyObject *ret = NULL;
870
871         slink = &( world )->scriptlink;
872
873         ret = EXPP_getScriptLinks( slink, value, 0 );
874
875         if( ret )
876                 return ret;
877         else
878                 return NULL;
879 }
880
881
882 /* world.setCurrent */
883 static PyObject *World_setCurrent( BPy_World * self )
884 {
885         World *world = self->world;
886 #if 0   /* add back in when bpy becomes "official" */
887         static char warning = 1;
888         if( warning ) {
889                 printf("world.setCurrent() deprecated!\n\tuse bpy.scenes.world=world instead\n");
890                 --warning;
891         }
892 #endif
893
894         /* If there is a world then it now has one less user */
895         if( G.scene->world )
896                 G.scene->world->id.us--;
897         world->id.us++;
898         G.scene->world = world;
899         Py_RETURN_NONE;
900 }
901
902 /* world.__copy__ */
903 static PyObject *World_copy( BPy_World * self )
904 {
905         World *world = copy_world(self->world );
906         world->id.us = 0;
907         return World_CreatePyObject(world);
908 }
909
910 /**
911  * \brief The World PyType compare function
912  *
913  * This function compares two given World PyObjects, returning 0 for equality
914  * and -1 otherwise.    In Python it becomes 1 if they are equal and 0 case not.
915  * The comparison is done with their pointers to Blender World Data objects,
916  * so any two wrappers pointing to the same Blender World Data will be
917  * considered the same World PyObject.  Currently, only the "==" and "!="
918  * comparisons are meaninful -- the "<", "<=", ">" or ">=" are not.
919  */
920
921 static int World_Compare( BPy_World * a, BPy_World * b )
922 {
923         return ( a->world == b->world ) ? 0 : -1;
924 }
925
926 /**
927  * \brief The World PyType print callback
928  *
929  * This function is called when the user tries to print a PyObject of type
930  * World.  It builds a string with the name of the wrapped Blender World.
931  */
932
933 /*
934 static int World_Print(BPy_World *self, FILE *fp, int flags)
935
936         fprintf(fp, "[World \"%s\"]", self->world->id.name+2);
937         return 0;
938 }
939 */
940
941 /**
942  * \brief The World PyType repr callback
943  *
944  * This function is called when the statement "repr(myworld)" is executed in
945  * Python.      Repr gives a string representation of a PyObject.
946  */
947
948 static PyObject *World_Repr( BPy_World * self )
949 {
950         return PyString_FromFormat( "[World \"%s\"]",
951                                     self->world->id.name + 2 );
952 }
953
954 /*@}*/
955 /*
956 static int World_compare (BPy_World *a, BPy_World *b)
957 {
958         World *pa = a->world, *pb = b->world;
959         return (pa == pb) ? 0:-1;
960 }
961 */
962 PyObject *World_CreatePyObject( struct World * world )
963 {
964         BPy_World *blen_object;
965
966         blen_object = ( BPy_World * ) PyObject_NEW( BPy_World, &World_Type );
967
968         if( blen_object == NULL ) {
969                 return ( NULL );
970         }
971         blen_object->world = world;
972         return ( ( PyObject * ) blen_object );
973 }
974
975 World *World_FromPyObject( PyObject * py_obj )
976 {
977         BPy_World *blen_obj;
978
979         blen_obj = ( BPy_World * ) py_obj;
980         return ( blen_obj->world );
981
982 }
983
984 /*
985  * World_insertIpoKey()
986  *  inserts World IPO key for ZENITH,HORIZON,MIST,STARS,OFFSET,SIZE
987  */
988
989 static PyObject *World_insertIpoKey( BPy_World * self, PyObject * args )
990 {
991         int key = 0, map;
992
993         if( !PyArg_ParseTuple( args, "i", &( key ) ) )
994                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
995                                                                                 "expected int argument" ) );
996
997         map = texchannel_to_adrcode(self->world->texact);
998
999         if(key == IPOKEY_ZENITH) {
1000                 insertkey((ID *)self->world, ID_WO, NULL, NULL, WO_ZEN_R, 0);
1001                 insertkey((ID *)self->world, ID_WO, NULL, NULL, WO_ZEN_G, 0);
1002                 insertkey((ID *)self->world, ID_WO, NULL, NULL, WO_ZEN_B, 0);
1003         }
1004         if(key == IPOKEY_HORIZON) {
1005                 insertkey((ID *)self->world, ID_WO, NULL, NULL, WO_HOR_R, 0);
1006                 insertkey((ID *)self->world, ID_WO, NULL, NULL, WO_HOR_G, 0);
1007                 insertkey((ID *)self->world, ID_WO, NULL, NULL, WO_HOR_B, 0);
1008         }
1009         if(key == IPOKEY_MIST) {
1010                 insertkey((ID *)self->world, ID_WO, NULL, NULL, WO_MISI, 0);
1011                 insertkey((ID *)self->world, ID_WO, NULL, NULL, WO_MISTDI, 0);
1012                 insertkey((ID *)self->world, ID_WO, NULL, NULL, WO_MISTSTA, 0);
1013                 insertkey((ID *)self->world, ID_WO, NULL, NULL, WO_MISTHI, 0);
1014         }
1015         if(key == IPOKEY_STARS) {
1016                 insertkey((ID *)self->world, ID_WO, NULL, NULL, WO_STAR_R, 0);
1017                 insertkey((ID *)self->world, ID_WO, NULL, NULL, WO_STAR_G, 0);
1018                 insertkey((ID *)self->world, ID_WO, NULL, NULL, WO_STAR_B, 0);
1019                 insertkey((ID *)self->world, ID_WO, NULL, NULL, WO_STARDIST, 0);
1020                 insertkey((ID *)self->world, ID_WO, NULL, NULL, WO_STARSIZE, 0);
1021         }
1022         if(key == IPOKEY_OFFSET) {
1023                 insertkey((ID *)self->world, ID_WO, NULL, NULL, map+MAP_OFS_X, 0);
1024                 insertkey((ID *)self->world, ID_WO, NULL, NULL, map+MAP_OFS_Y, 0);
1025                 insertkey((ID *)self->world, ID_WO, NULL, NULL, map+MAP_OFS_Z, 0);
1026         }
1027         if(key == IPOKEY_SIZE) {
1028                 insertkey((ID *)self->world, ID_WO, NULL, NULL, map+MAP_SIZE_X, 0);
1029                 insertkey((ID *)self->world, ID_WO, NULL, NULL, map+MAP_SIZE_Y, 0);
1030                 insertkey((ID *)self->world, ID_WO, NULL, NULL, map+MAP_SIZE_Z, 0);
1031         }
1032
1033         allspace(REMAKEIPO, 0);
1034         EXPP_allqueue(REDRAWIPO, 0);
1035         EXPP_allqueue(REDRAWVIEW3D, 0);
1036         EXPP_allqueue(REDRAWACTION, 0);
1037         EXPP_allqueue(REDRAWNLA, 0);
1038
1039         Py_RETURN_NONE;
1040 }
1041
1042 static PyObject *World_getTextures( BPy_World * self )
1043 {
1044         int i;
1045         PyObject *tuple;
1046
1047         /* build a texture list */
1048         tuple = PyTuple_New( MAX_MTEX );
1049         if( !tuple )
1050                 return EXPP_ReturnPyObjError( PyExc_MemoryError,
1051                                               "couldn't create PyTuple" );
1052
1053         for( i = 0; i < MAX_MTEX; ++i ) {
1054                 struct MTex *mtex = self->world->mtex[i];
1055                 if( mtex ) {
1056                         PyTuple_SET_ITEM( tuple, i, MTex_CreatePyObject( mtex, ID_WO ) );
1057                 } else {
1058                         Py_INCREF( Py_None );
1059                         PyTuple_SET_ITEM( tuple, i, Py_None );
1060                 }
1061         }
1062
1063         return tuple;
1064 }
1065
1066 static int World_setTextures( BPy_World * self, PyObject * value )
1067 {
1068         int i;
1069
1070         if( !PyList_Check( value ) && !PyTuple_Check( value ) )
1071                 return EXPP_ReturnIntError( PyExc_TypeError,
1072                                                 "expected tuple or list of integers" );
1073
1074         /* don't allow more than MAX_MTEX items */
1075         if( PySequence_Size(value) > MAX_MTEX )
1076                 return EXPP_ReturnIntError( PyExc_AttributeError,
1077                                                 "size of sequence greater than number of allowed textures" );
1078
1079         /* get a fast sequence; in Python 2.5, this just return the original
1080          * list or tuple and INCREFs it, so we must DECREF */
1081         value = PySequence_Fast( value, "" );
1082
1083         /* check the list for valid entries */
1084         for( i= 0; i < PySequence_Size(value) ; ++i ) {
1085                 PyObject *item = PySequence_Fast_GET_ITEM( value, i );
1086                 if( item == Py_None || ( BPy_MTex_Check( item ) &&
1087                                                 ((BPy_MTex *)item)->type == ID_WO ) ) {
1088                         continue;
1089                 } else {
1090                         Py_DECREF(value);
1091                         return EXPP_ReturnIntError( PyExc_TypeError,
1092                                         "expected tuple or list containing world MTex objects and NONE" );
1093                 }
1094         }
1095
1096         /* for each MTex object, copy to this structure */
1097         for( i= 0; i < PySequence_Size(value) ; ++i ) {
1098                 PyObject *item = PySequence_Fast_GET_ITEM( value, i );
1099                 struct MTex *mtex = self->world->mtex[i];
1100                 if( item != Py_None ) {
1101                         BPy_MTex *obj = (BPy_MTex *)item;
1102
1103                         /* if MTex is already at this location, just skip it */
1104                         if( obj->mtex == mtex ) continue;
1105
1106                         /* create a new entry if needed, otherwise update reference count
1107                          * for texture that is being replaced */
1108                         if( !mtex )
1109                                 mtex = self->world->mtex[i] = add_mtex(  );
1110                         else
1111                                 mtex->tex->id.us--;
1112
1113                         /* copy the data */
1114                         mtex->tex = obj->mtex->tex;
1115                         id_us_plus( &mtex->tex->id );
1116                         mtex->texco = obj->mtex->texco;
1117                         mtex->mapto = obj->mtex->mapto;
1118                 }
1119         }
1120
1121         /* now go back and free any entries now marked as None */
1122         for( i= 0; i < PySequence_Size(value) ; ++i ) {
1123                 PyObject *item = PySequence_Fast_GET_ITEM( value, i );
1124                 struct MTex *mtex = self->world->mtex[i];
1125                 if( item == Py_None && mtex ) {
1126                         mtex->tex->id.us--;
1127                         MEM_freeN( mtex );
1128                         self->world->mtex[i] = NULL;
1129                 } 
1130         }
1131
1132         Py_DECREF(value);
1133         return 0;
1134 }