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