Initial revision
[blender.git] / source / blender / bpython / intern / opy_datablock.c
1 /* Datablock handling code. This handles the generic low level access to Blender
2    Datablocks. */
3
4 /*
5  * $Id$
6  *
7  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version. The Blender
13  * Foundation also sells licenses for use in proprietary software under
14  * the Blender License.  See http://www.blender.org/BL/ for information
15  * about this.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software Foundation,
24  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  *
26  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
27  * All rights reserved.
28  *
29  * The Original Code is: all of this file.
30  *
31  * Contributor(s): none yet.
32  *
33  * ***** END GPL/BL DUAL LICENSE BLOCK *****
34  */
35
36 /**************************************************************************
37  * This code provides low level, generalized access to the Blender Datablock 
38  * objects. It basically creates a descriptor Python Object of type 'DataBlock'
39  * for each requested Blender datablock.
40  * This introduces the question of synchronization, for example:
41  *  What happens if an Object is deleted?
42  * 
43  * Blender Objects have their own 'reference counting', e.g. a Mesh datablock
44  * used by two Objects has a user count of 2. Datablocks with user count of 0
45  * are not saved to Disk -- this is the current way Blender does
46  * 'garbage collection'
47  * Therefore, an object should normally not be deleted by Python, but rather
48  * unlinked from its parent object.
49  * Still, for other objects like Scene or Text objects, deletion from 'Main'
50  * is desired.
51  * The current workaround:
52  
53  * Some objects can be explicitely deleted (not recommended, but possible) --
54  * they have a user count of 1, even if they are used by objects in some way,
55  * for example Text objects which are used by any other Blender object
56  * through a ScriptLink.
57  * 
58  * Objects that are deleted through Python end up with a 'dead' descriptor;
59  * accessing the descriptor after deletion causes a Python exception.
60  * 
61  * NASTY UGLY DIRTY, VUILE, DRECKIGES AND STILL REMAINING PROBLEM:
62  * 
63  * It is (in the current API) possible to construct the case, that an
64  * Object is deleted in Blender, but the Python descriptor does not know
65  * about this. Accessing the descriptor (which simply contains a pointer to
66  * the raw datablock struct) will most probably end in colourful joy.
67  * 
68  * TODO:
69  * possible solutions:
70  * - rewrite datablock handling that way, that the descriptor uses an id 
71  *   tag to retrieve that pointer through a getPointerbyID() function 
72  *   (if the object exists!) on each access. Slow.
73  * - make sure that deletion always happends by the descriptor and never
74  *   delete the raw datastructure. This solution would imply a major
75  *   redesign of user action handling (GUI actions calling python).
76  *   Not likely to happen...better fusion raw and python object in this case.
77  *   After all, still somewhat dirty.
78  * - make sure that no deletion can happen in Blender while a script
79  *   still accesses the raw data - i.e. implement user counting of raw
80  *   objects with descriptors. This would need an implementation of
81  *   garbage collection in Blender. This might sound like the most feasible
82  *   solution...
83  */
84
85
86 #include "Python.h"
87 #include "BPY_macros.h"
88
89 #include "opy_datablock.h"
90 #include "opy_nmesh.h"
91
92 #include "opy_vector.h" /* matrix datatypes */
93
94 #include "BPY_tools.h"
95 #include "BPY_types.h"
96 #include "BPY_main.h"
97
98 #include "MEM_guardedalloc.h"
99
100 #include "b_interface.h" /* needed for most of the DNA datatypes */
101
102
103 /* ---------------------------------------------------------------------- */
104
105 /*********************/
106 /* Camera Datablocks */
107
108 DATABLOCK_GET(Cameramodule, camera, getCameraList())
109
110 static char Cameramodule_New_doc[] = 
111 "() - returns new Camera object"; 
112  
113 PyObject *Cameramodule_New (PyObject *self, PyObject *args) 
114
115         Camera *obj; 
116         obj = camera_new(); 
117         return DataBlock_fromData(obj); 
118
119
120 #ifdef FUTURE_PYTHON_API
121
122 DataBlockProperty Camera_Properties[]= {
123         {"lens",        "lens",         DBP_TYPE_FLO, 0, 1.0,    250.0}, 
124         {"clipStart","clipsta", DBP_TYPE_FLO, 0, 0.0,    100.0}, 
125         {"clipEnd",     "clipend",      DBP_TYPE_FLO, 0, 1.0,   5000.0}, 
126         {"type", "type",        DBP_TYPE_SHO, 0, 0.0,      0.0},
127         {"mode", "flag",        DBP_TYPE_SHO, 0, 0.0,      0.0},
128
129         {"ipo",         "*ipo",         DBP_TYPE_FUN, 0, 0.0,   0.0, {0}, {0}, 0, 0, get_DataBlock_func}, 
130         
131         {NULL}
132 };
133
134 #else
135
136 DataBlockProperty Camera_Properties[]= {
137         {"Lens",        "lens",         DBP_TYPE_FLO, 0, 1.0,   250.0}, 
138         {"ClSta",       "clipsta",      DBP_TYPE_FLO, 0, 0.0,   100.0}, 
139         {"ClEnd",       "clipend",      DBP_TYPE_FLO, 0, 1.0,   5000.0}, 
140
141         {"ipo",         "*ipo",         DBP_TYPE_FUN, 0, 0.0,   0.0, {0}, {0}, 0, 0, get_DataBlock_func}, 
142         
143         {NULL}
144 };
145
146 #endif
147
148 static struct PyMethodDef Cameramodule_methods[] = {
149         {"New", Cameramodule_New, METH_VARARGS, Cameramodule_New_doc},
150         {"get", Cameramodule_get, METH_VARARGS, Cameramodule_get_doc},
151         {NULL, NULL}
152 };
153
154 DATABLOCK_ASSIGN_IPO(Camera, camera) // defines Camera_assignIpo
155
156 static struct PyMethodDef Camera_methods[] = {
157         {"clrIpo", Camera_clrIpo, METH_VARARGS, Camera_clrIpo_doc},
158         {"assignIpo", Camera_assignIpo, METH_VARARGS, Camera_assignIpo_doc},
159         {NULL, NULL}
160 };
161
162 /***********************/
163 /* Material Datablocks */
164
165
166 /** returns a pointer to a new (malloced) material list created from
167   * a Python material list
168   */
169
170 Material **newMaterialList_fromPyList(PyObject *list)
171 {
172         int i, len;
173         DataBlock *block = 0;
174         Material *mat;
175         Material **matlist;
176
177         len = PySequence_Length(list);
178         if (len > 16) len = 16;
179
180         matlist = newMaterialList(len);
181         
182         for (i= 0; i < len; i++) {
183                 
184                 block= (DataBlock *) PySequence_GetItem(list, i);
185                 
186                 if (DataBlock_isType(block, ID_MA)) {
187                         mat = (Material *) block->data;
188                         matlist[i] = mat;
189                 } else { 
190                         // error; illegal type in material list
191                         Py_DECREF(block);
192                         MEM_freeN(matlist);
193                         return NULL;
194                 }       
195                 Py_DECREF(block);
196         }
197         return matlist;
198 }
199
200 /** Return Python List from material pointer list 'matlist' with length
201   * 'len'
202   *
203   */
204
205 PyObject *PyList_fromMaterialList(Material **matlist, int len)
206 {
207         PyObject *list;
208         int i;
209
210         list = PyList_New(0);
211         if (!matlist) return list;
212
213         for (i = 0; i < len; i++) {
214                 Material *mat= matlist[i];
215                 PyObject *ob;
216                 
217                 if (mat) {
218                         ob = DataBlock_fromData(mat);
219                         PyList_Append(list, ob);
220                         Py_DECREF(ob); // because Append increfs!
221                 }                       
222         }
223         return list;
224 }
225
226 DATABLOCK_GET(Materialmodule, material, getMaterialList())
227
228 DATABLOCK_NEW(Materialmodule, Material, material_new())
229
230 static struct PyMethodDef Materialmodule_methods[] = {
231         {"get", Materialmodule_get, METH_VARARGS, Materialmodule_get_doc},
232         {"New", Materialmodule_New, METH_VARARGS, Materialmodule_New_doc},
233         {NULL, NULL}
234 };
235
236 DATABLOCK_ASSIGN_IPO(Material, material)   
237
238 static struct PyMethodDef Material_methods[] = {
239         {"clrIpo", Material_clrIpo, METH_VARARGS, Material_clrIpo_doc},
240         {"assignIpo", Material_assignIpo, METH_VARARGS, Material_assignIpo_doc},
241         {NULL, NULL}
242 };
243
244 #ifdef FUTURE_PYTHON_API
245
246 DataBlockProperty Material_Properties[]= {
247         {"R",           "r",            DBP_TYPE_FLO, 0, 0.0,   1.0}, 
248         {"G",           "g",            DBP_TYPE_FLO, 0, 0.0,   1.0}, 
249         {"B",           "b",            DBP_TYPE_FLO, 0, 0.0,   1.0}, 
250         {"specR",       "specr",        DBP_TYPE_FLO, 0, 0.0,   1.0}, 
251         {"specG",       "specg",        DBP_TYPE_FLO, 0, 0.0,   1.0}, 
252         {"specB",       "specb",        DBP_TYPE_FLO, 0, 0.0,   1.0}, 
253         {"mirR",        "mirr",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
254         {"mirG",        "mirg",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
255         {"mirB",        "mirb",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
256         {"ref",         "ref",          DBP_TYPE_FLO, 0, 0.0,   1.0}, 
257         {"alpha",       "alpha",        DBP_TYPE_FLO, 0, 0.0,   1.0}, 
258         {"emit",        "emit",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
259         {"amb",         "amb",          DBP_TYPE_FLO, 0, 0.0,   1.0}, 
260         {"spec",        "spec",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
261         {"specTransp",  "spectra",      DBP_TYPE_FLO, 0, 0.0,   1.0}, 
262         {"haloSize",    "hasize",       DBP_TYPE_FLO, 0, 0.0,   10000.0}, 
263
264         {"mode",        "mode",         DBP_TYPE_INT, 0, 0.0,   0.0},    
265         {"hard",        "har",          DBP_TYPE_SHO, 0, 1.0,   128.0},  
266
267         {"ipo",         "*ipo",         DBP_TYPE_FUN, 0, 0.0,   0.0, {0}, {0}, 0, 0, get_DataBlock_func}, 
268
269         {NULL} 
270 };
271
272 #else
273
274 DataBlockProperty Material_Properties[]= {
275         {"R",           "r",            DBP_TYPE_FLO, 0, 0.0,   1.0}, 
276         {"G",           "g",            DBP_TYPE_FLO, 0, 0.0,   1.0}, 
277         {"B",           "b",            DBP_TYPE_FLO, 0, 0.0,   1.0}, 
278         {"SpecR",       "specr",        DBP_TYPE_FLO, 0, 0.0,   1.0}, 
279         {"SpecG",       "specg",        DBP_TYPE_FLO, 0, 0.0,   1.0}, 
280         {"SpecB",       "specb",        DBP_TYPE_FLO, 0, 0.0,   1.0}, 
281         {"MirR",        "mirr",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
282         {"MirG",        "mirg",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
283         {"MirB",        "mirb",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
284         {"Ref",         "ref",          DBP_TYPE_FLO, 0, 0.0,   1.0}, 
285         {"Alpha",       "alpha",        DBP_TYPE_FLO, 0, 0.0,   1.0}, 
286         {"Emit",        "emit",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
287         {"Amb",         "amb",          DBP_TYPE_FLO, 0, 0.0,   1.0}, 
288         {"Spec",        "spec",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
289         {"SpTra",       "spectra",      DBP_TYPE_FLO, 0, 0.0,   1.0}, 
290         {"HaSize",      "hasize",       DBP_TYPE_FLO, 0, 0.0,   10000.0}, 
291
292         {"Mode",        "mode",         DBP_TYPE_INT, 0, 0.0,   0.0},  
293         {"Hard",        "har",          DBP_TYPE_SHO, 0, 1.0,   128.0},  
294
295         {"ipo",         "*ipo",         DBP_TYPE_FUN, 0, 0.0,   0.0, {0}, {0}, 0, 0, get_DataBlock_func}, 
296
297         {NULL} 
298 };
299
300 #endif
301
302 /*******************/
303 /* Lamp Datablocks */
304
305 DATABLOCK_GET(Lampmodule, lamp, getLampList())
306
307 // DATABLOCK_NEW(Lampmodule, Lamp, lamp_new())
308
309 static char Lampmodule_New_doc[] = 
310 "() - returns new Lamp object"; 
311  
312 PyObject *Lampmodule_New (PyObject *self, PyObject *args) 
313
314         Lamp *obj; 
315         obj = lamp_new(); 
316         return DataBlock_fromData(obj); 
317
318
319 #ifdef FUTURE_PYTHON_API
320
321 DataBlockProperty Lamp_Properties[]= {
322         {"mode",        "mode",                 DBP_TYPE_SHO, 0, 0.0,   0.0}, 
323         {"type",        "type",                 DBP_TYPE_SHO, 0, 0.0,   0.0}, 
324         {"R",           "r",                    DBP_TYPE_FLO, 0, 0.0,   1.0}, 
325         {"G",           "g",                    DBP_TYPE_FLO, 0, 0.0,   1.0}, 
326         {"B",           "b",                    DBP_TYPE_FLO, 0, 0.0,   1.0}, 
327         {"energy",      "energy",               DBP_TYPE_FLO, 0, 0.0,   10.0}, 
328         {"dist",        "dist",                 DBP_TYPE_FLO, 0, 0.01,  5000.0}, 
329         {"spotSize",    "spotsize",             DBP_TYPE_FLO, 0, 1.0,   180.0}, 
330         {"spotBlend",   "spotblend",    DBP_TYPE_FLO, 0, 0.0,   1.0}, 
331         {"haloInt",     "haint",                DBP_TYPE_FLO, 0, 0.0,   5.0}, 
332         {"quad1",       "att1",                 DBP_TYPE_FLO, 0, 0.0,   1.0}, 
333         {"quad2",       "att2",                 DBP_TYPE_FLO, 0, 0.0,   1.0}, 
334         {"bufferSize",  "bufsize",      DBP_TYPE_SHO, 0, 0.0,   0.0}, 
335         {"samples",     "samp", DBP_TYPE_SHO, 0, 1.0,   16.0}, 
336         {"haloStep",    "shadhalostep", DBP_TYPE_SHO, 0, 0.0,   12.0}, 
337         {"clipStart",   "clipsta",      DBP_TYPE_FLO, 0, 0.1,   5000.0}, 
338         {"clipEnd",     "clipend",      DBP_TYPE_FLO, 0, 0.1,   5000.0}, 
339         {"bias",        "bias", DBP_TYPE_FLO, 0, 0.01,  5.0}, 
340         {"softness",    "soft", DBP_TYPE_FLO, 0, 1.00,  100.0}, 
341
342         {"ipo",         "*ipo",         DBP_TYPE_FUN, 0, 0.0,   0.0, {0}, {0}, 0, 0, get_DataBlock_func}, 
343         
344         {NULL}
345 };
346 #else
347
348 DataBlockProperty Lamp_Properties[]= {
349         {"mode",        "mode",                 DBP_TYPE_SHO, 0, 0.0,   0.0}, 
350         {"type",        "type",                 DBP_TYPE_SHO, 0, 0.0,   0.0}, 
351         {"R",           "r",                    DBP_TYPE_FLO, 0, 0.0,   1.0}, 
352         {"G",           "g",                    DBP_TYPE_FLO, 0, 0.0,   1.0}, 
353         {"B",           "b",                    DBP_TYPE_FLO, 0, 0.0,   1.0}, 
354         {"Energ",       "energy",               DBP_TYPE_FLO, 0, 0.0,   10.0}, 
355         {"Dist",        "dist",                 DBP_TYPE_FLO, 0, 0.01,  5000.0}, 
356         {"SpotSi",      "spotsize",             DBP_TYPE_FLO, 0, 1.0,   180.0}, 
357         {"SpotBl",      "spotblend",    DBP_TYPE_FLO, 0, 0.0,   1.0}, 
358         {"HaloInt",     "haint",                DBP_TYPE_FLO, 0, 1.0,   5.0}, 
359         {"Quad1",       "att1",                 DBP_TYPE_FLO, 0, 0.0,   1.0}, 
360         {"Quad2",       "att2",                 DBP_TYPE_FLO, 0, 0.0,   1.0}, 
361
362         {"ipo",         "*ipo",         DBP_TYPE_FUN, 0, 0.0,   0.0, {0}, {0}, 0, 0, get_DataBlock_func}, 
363         
364         {NULL}
365 };
366
367 #endif
368
369
370 static struct PyMethodDef Lampmodule_methods[] = {
371         {"New", Lampmodule_New, METH_VARARGS, Lampmodule_New_doc},
372         {"get", Lampmodule_get, METH_VARARGS, Lampmodule_get_doc},
373 #ifdef CURRENT_PYTHON_API
374         {"Get", Lampmodule_get, METH_VARARGS, Lampmodule_get_doc},
375 #endif
376         {NULL, NULL}
377 };
378
379 DATABLOCK_ASSIGN_IPO(Lamp, lamp) // defines Lamp_assignIpo
380
381 static struct PyMethodDef Lamp_methods[] = {
382         {"clrIpo", Lamp_clrIpo, METH_VARARGS, Lamp_clrIpo_doc},
383         {"assignIpo", Lamp_assignIpo, METH_VARARGS, Lamp_assignIpo_doc},
384         {NULL, NULL}
385 };
386
387 /********************/
388 /* World Datablocks */
389
390 DATABLOCK_GET(Worldmodule, world, getWorldList() )
391
392 #ifdef FUTURE_PYTHON_API
393
394 DataBlockProperty World_Properties[]= {
395
396         {"mode", "mode", DBP_TYPE_SHO, 0, 0.0,  0.0},
397         {"skyType", "skytype", DBP_TYPE_SHO, 0, 0.0,  0.0},
398         {"mistType", "mistype", DBP_TYPE_SHO, 0, 0.0,  0.0},
399         {"horR",        "horr",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
400         {"horG",        "horg",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
401         {"horB",        "horb",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
402         {"ambR",        "ambr",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
403         {"ambG",        "ambg",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
404         {"ambB",        "ambb",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
405         {"zenR",        "zenr",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
406         {"zenG",        "zeng",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
407         {"zenB",        "zenb",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
408         {"exposure",    "exposure",     DBP_TYPE_FLO, 0, 0.0,   5.0}, 
409         {"mistStart",   "miststa",      DBP_TYPE_FLO, 0, 0.0,   1000.0}, 
410         {"mistDepth",   "mistdist",     DBP_TYPE_FLO, 0, 0.0,   1000.0}, 
411         {"mistHeight",  "misthi",       DBP_TYPE_FLO, 0, 0.0,   100.0}, 
412         {"starDensity", "stardist",     DBP_TYPE_FLO, 0, 2.0,   1000.0}, 
413         {"starMinDist", "starmindist",  DBP_TYPE_FLO, 0, 0.0,   1000.0}, 
414         {"starSize",    "starsize",     DBP_TYPE_FLO, 0, 0.0,   10.0}, 
415         {"starColNoise",        "starcolsize",  DBP_TYPE_FLO, 0, 0.0,   1.0}, 
416         {"gravity",     "gravity",      DBP_TYPE_FLO, 0, 0.0,   25.0}, 
417
418         {"ipo",         "*ipo",         DBP_TYPE_FUN, 0, 0.0,   0.0, {0}, {0}, 0, 0, get_DataBlock_func}, 
419         
420         {NULL}
421 };
422
423 #else
424
425 DataBlockProperty World_Properties[]= {
426         {"HorR",        "horr",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
427         {"HorG",        "horg",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
428         {"HorB",        "horb",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
429         {"ZenR",        "zenr",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
430         {"ZenG",        "zeng",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
431         {"ZenB",        "zenb",         DBP_TYPE_FLO, 0, 0.0,   1.0}, 
432         {"Expos",       "exposure",     DBP_TYPE_FLO, 0, 0.0,   5.0}, 
433         {"MisSta",      "miststa",      DBP_TYPE_FLO, 0, 0.0,   1000.0}, 
434         {"MisDi",       "mistdist",     DBP_TYPE_FLO, 0, 0.0,   1000.0}, 
435         {"MisHi",       "misthi",       DBP_TYPE_FLO, 0, 0.0,   100.0}, 
436         {"StarDi",      "stardist",     DBP_TYPE_FLO, 0, 2.0,   1000.0}, 
437         {"StarSi",      "starsize",     DBP_TYPE_FLO, 0, 0.0,   10.0}, 
438
439         {"ipo",         "*ipo",         DBP_TYPE_FUN, 0, 0.0,   0.0, {0}, {0}, 0, 0, get_DataBlock_func}, 
440         
441         {NULL}
442 };
443
444 #endif
445
446 static char Worldmodule_getActive_doc[]="() - Returns the active world";
447 static PyObject *Worldmodule_getActive (PyObject *self, PyObject *args)
448 {
449         if (scene_getCurrent()->world) 
450                 return DataBlock_fromData(scene_getCurrent()->world);
451         else
452                 return BPY_incr_ret(Py_None);   
453 }
454
455 static struct PyMethodDef Worldmodule_methods[] = {
456         // these for compatibility...
457         {"get",                 Worldmodule_get,                        METH_VARARGS, Worldmodule_get_doc},
458 #ifdef CURRENT_PYTHON_API
459         {"Get",                 Worldmodule_get,                        METH_VARARGS, Worldmodule_get_doc},
460 #endif
461         {"getCurrent",  Worldmodule_getActive,  METH_VARARGS, Worldmodule_getActive_doc},
462         {NULL, NULL}
463 };
464
465
466
467 /* XXX these should go elsewhere */
468
469 PyObject *BPY_PyList_FromIDList(ListBase *list, DBConvertfunc convertfunc)
470 {
471         PyObject *pylist= PyList_New(BLI_countlist(list));
472         ID *id = list->first;
473
474         int i=0;
475
476         while (id) {
477                 PyObject *ob= convertfunc(id);
478                 
479                 if (!ob) {
480                         Py_DECREF(pylist);
481                         return NULL;
482                 }
483                 PyList_SetItem(pylist, i, ob);  
484                 id = id->next; i++;
485         }
486         return pylist;
487 }
488
489
490 PyObject *py_find_from_list(ListBase *list, PyObject *args) {
491         char *name= NULL;
492         ID *id = list->first;
493         BPY_TRY(PyArg_ParseTuple(args, "|s", &name));
494         
495         if (name) {
496                 while (id) {
497                         if (strcmp(name, getIDName(id))==0) 
498                                 return DataBlock_fromData(id);
499
500                         id= id->next;
501                 }
502                 return BPY_incr_ret(Py_None);
503                 
504         } else 
505                 return BPY_PyList_FromIDList(list, DataBlock_fromData);
506 }
507
508 PyObject *named_enum_get(int val, NamedEnum *enums) {
509         while (enums->name) {
510                 if (enums->num == val) return PyString_FromString(enums->name);
511                 enums++;
512         }       
513         PyErr_SetString(PyExc_AttributeError, "Internal error, Unknown enumerated type");
514         return NULL;
515 }
516
517 int named_enum_set(char *name, NamedEnum *enums) {
518         while (enums->name) {
519                 if (STREQ(enums->name, name)) 
520                         return enums->num;
521                 enums++;
522         }       
523         
524         return -1;
525 }
526
527 static int calc_offset_subsize(int *dlist, int *idx, int *subsize) {
528         int n= *dlist;
529         
530         if (n<=0) {
531                 *subsize= -n;
532                 return 0;
533         } else {
534                 int ss;
535                 int off= calc_offset_subsize(dlist+1, idx+1, &ss);
536                         
537                 *subsize= n*ss;
538                 return off + (*idx)*ss;
539         }
540 }
541
542 static int calc_offset(int *dlist, int *idx) {
543         int subsize;
544         return calc_offset_subsize(dlist, idx, &subsize);
545 }
546
547 static void *get_db_ptr(DataBlockProperty *prop, char *structname, void *struct_ptr) {
548         int offset= BLO_findstruct_offset(structname, prop->struct_name);
549         void *ptr= struct_ptr;
550         
551         if (offset==-1) {
552                 BPY_warn(("Internal error, Invalid prop entry\n"));
553                 return NULL;
554         }
555
556         ptr= (void *) (((char *)ptr) + offset);
557         
558         offset= calc_offset(prop->dlist, prop->idx);    
559         ptr= (void *) (((char *)ptr) + offset);
560         
561         return ptr;
562 }
563
564 PyObject *datablock_getattr(DataBlockProperty *props, char *structname, char *name, void *struct_ptr) { 
565         if (STREQ(name, "properties") || STREQ(name, "__members__")) {
566                 PyObject *l= PyList_New(0);
567                 DataBlockProperty *p= props;
568                 
569                 while (p->public_name) {
570                         PyList_Append(l, PyString_FromString(p->public_name));
571                         p++;
572                 }
573                 
574                 return l;
575         }
576         
577         while (props->public_name) {
578                 if (STREQ(name, props->public_name)) {
579                         void *ptr = struct_ptr;
580                         int val;
581                         DBPtrToObFP conv_fp;
582
583                         if (props->handling==DBP_HANDLING_NONE || 
584                                         props->handling==DBP_HANDLING_NENM) {
585                                 ptr= get_db_ptr(props, structname, struct_ptr);
586                                 if (!ptr) return NULL;
587                                 
588                         } else if (props->handling==DBP_HANDLING_FUNC) {
589                                 DBGetPtrFP fp= (DBGetPtrFP) props->extra1;
590                                 ptr= fp(struct_ptr, props->struct_name, 0);
591                                 if (!ptr) return NULL;
592                         }                       
593
594                         switch(props->type) {
595                         case DBP_TYPE_CHA:
596                                 val= *((char    *)ptr);
597                                 if (props->handling==DBP_HANDLING_NENM) 
598                                         return named_enum_get(val, props->extra1);                              
599                                 else
600                                         return PyInt_FromLong(val);
601                         case DBP_TYPE_SHO:
602                                 val= *((short   *)ptr);
603                                 if (props->handling==DBP_HANDLING_NENM) 
604                                         return named_enum_get(val, props->extra1);                              
605                                 else
606                                         return PyInt_FromLong(val);
607                         case DBP_TYPE_INT:
608                                 val= *((int     *)ptr);
609                                 if (props->handling==DBP_HANDLING_NENM) 
610                                         return named_enum_get(val, props->extra1);                              
611                                 else
612                                         return PyInt_FromLong(val);
613                         case DBP_TYPE_FLO:
614                                 return PyFloat_FromDouble       ( *((float      *)ptr) );
615                         case DBP_TYPE_VEC:
616                                 return newVectorObject          ( ((float       *)ptr), (int) props->min );
617                         case DBP_TYPE_FUN:
618                                 conv_fp= (DBPtrToObFP) props->extra2;
619                                 return conv_fp( ptr );
620                         default:
621                                 PyErr_SetString(PyExc_AttributeError, "Internal error, Unknown prop type");
622                                 return NULL;
623                         }
624                 }
625                 
626                 props++;
627         }
628         
629         PyErr_SetString(PyExc_AttributeError, name);
630         return NULL;            
631 }
632
633 int datablock_setattr(DataBlockProperty *props, char *structname, char *name, void *struct_ptr, PyObject *setto) {
634
635         while (props->public_name) {
636                 if (STREQ(props->public_name, name)) {
637                         void *ptr = NULL;
638                         int type;
639                         DBSetPtrFP conv_fp;
640                         int clamp= props->min!=props->max;
641
642                         int enum_val= -1;
643                         char    cha_data;
644                         short   sho_data;
645                         int             int_data;
646                         float   flo_data;
647
648                         type= props->stype;
649                         if (type==DBP_TYPE_NON) type= props->type;
650
651                         if (props->handling==DBP_HANDLING_NONE) {
652                                 ptr= get_db_ptr(props, structname, struct_ptr);
653                                 if (!ptr) return 0;
654                                 
655                         } else if (props->handling==DBP_HANDLING_FUNC) {
656                                 if (type!=DBP_TYPE_FUN) {
657                                         DBGetPtrFP fp= (DBGetPtrFP) props->extra1;
658                                         ptr= fp(struct_ptr, props->struct_name, 1);
659                                         if (!ptr) return 0;
660                                 }
661                         } else if (props->handling==DBP_HANDLING_NENM) {
662                                 char *str;
663                                 if (!PyArg_Parse(setto, "s", &str)) return -1;
664
665                                 ptr= get_db_ptr(props, structname, struct_ptr);
666                                 if (!ptr) return 0;
667                                 
668                                 enum_val= named_enum_set(str, props->extra1);
669                                 if (enum_val==-1)
670                                         return py_err_ret_int(PyExc_AttributeError, "invalid setting for field");
671                         }
672
673                         switch(type) {
674                         case DBP_TYPE_CHA:
675                                 if (enum_val==-1) {
676                                         if (!PyArg_Parse(setto, "b", &cha_data)) return -1;
677                                 } else cha_data= (char) enum_val;
678                                 
679                                 if (clamp) {
680                                         CLAMP(cha_data, (char) props->min, (char) props->max);
681                                 }       
682                                 *((char         *)ptr)= cha_data;
683                                 return 0;
684                         case DBP_TYPE_SHO:
685                                 if (enum_val==-1) {
686                                         if (!PyArg_Parse(setto, "h", &sho_data)) return -1;
687                                 } else sho_data= (short) enum_val;
688
689                                 if (clamp) {
690                                         CLAMP(sho_data, (short) props->min, (short) props->max);
691                                 }
692                                 *((short        *)ptr)= sho_data;
693                                 return 0;
694                         case DBP_TYPE_INT:
695                                 if (enum_val==-1) {
696                                         if (!PyArg_Parse(setto, "i", &int_data)) return -1;
697                                 } else int_data= (int) enum_val;
698
699                                 if (clamp) {
700                                         CLAMP(int_data, (int) props->min, (int) props->max);
701                                 }       
702                                 *((int          *)ptr)= int_data;
703                                 return 0;
704                         case DBP_TYPE_FLO:
705                                 if (!PyArg_Parse(setto, "f", &flo_data)) return -1;
706                                 if (clamp) {
707                                         CLAMP(flo_data, (float) props->min, (float) props->max);
708                                 }               
709                                 *((float        *)ptr)= flo_data;
710                                 return 0;
711                         case DBP_TYPE_VEC:
712                         /* this is very dangerous!! TYPE_VEC also can contain non floats; see
713                          * ipo curve attribute h1t, etc. */
714                                 if (props->min == 3.0 ) {  // vector triple
715                                         return BPY_parsefloatvector(setto, (float *) ptr, 3);
716                                 } else {
717                                         return py_err_ret_int(PyExc_AttributeError, "cannot directly assign, use slice assignment instead");
718                                 }
719                                 return 0;
720                                         
721                         case DBP_TYPE_FUN:
722                                 conv_fp= (DBSetPtrFP) props->extra3;
723                                 if (conv_fp)
724                                         return conv_fp( struct_ptr, props->struct_name, setto );
725                                 else
726                                         return py_err_ret_int(PyExc_AttributeError, "cannot directly assign to item");
727                         default:
728                                 PyErr_SetString(PyExc_AttributeError, "Internal error, Unknown prop type");
729                                 return -1;
730                         }
731                 }
732                 
733                 props++;
734         }
735
736         PyErr_SetString(PyExc_AttributeError, name);
737         return -1;
738 }
739
740 PyObject *datablock_assignIpo(DataBlock *block, DataBlock *ipoblock)
741 {
742         Ipo **ipoptr;
743         Ipo *ipo;
744
745         if (!DataBlock_isType(ipoblock, ID_IP)) {
746                 PyErr_SetString(PyExc_TypeError, "expects Ipo object");
747                 return 0;
748         }
749
750         ipo = PYBLOCK_AS_IPO(ipoblock);
751
752         if (DataBlock_type(block) != ipo->blocktype) {
753                 PyErr_SetString(PyExc_TypeError, "Ipo type does not match object type!");
754                 return 0;
755         }
756
757         ipoptr = get_db_ptr(block->properties, "ipo", block->data);
758         if (!ipoptr) {
759                 PyErr_SetString(PyExc_RuntimeError, "Object does not have an ipo!");
760                 return 0;
761         }
762
763         *ipoptr = ipo;
764         Py_INCREF(Py_None);
765         return Py_None; 
766 }
767
768 /* deallocates a Python Datablock object */
769 void DataBlock_dealloc(DataBlock *self) 
770 {
771 #ifdef REF_USERCOUNT
772         BOB_XDECUSER(DATABLOCK_ID(self)); // XXX abuse for ref count
773 #endif
774         PyMem_DEL(self);
775 }
776
777 PyObject *DataBlock_repr(DataBlock *self) 
778 {
779         static char s[256];
780         if (self->data) 
781                 sprintf (s, "[%.32s %.32s]", self->type, getIDName((ID*)self->data));
782         else
783                 sprintf (s, "[%.32s %.32s]", self->type, "<deleted>");
784         return Py_BuildValue("s", s);
785 }
786
787 /* ************************************************************************* */
788 /* datablock linking */
789
790 /** Link data to Object */
791
792 static PyObject *link_Data_toObject(DataBlock *objectblk, DataBlock *datablk)
793 {
794         Object *object = PYBLOCK_AS_OBJECT(objectblk);
795
796         void *data = datablk->data;
797         if (!object_linkdata(object, data))
798         {
799                 PyErr_SetString(PyExc_TypeError,
800                 "Object type different from Data type or linking for this type\
801  not supported");
802                 return NULL;
803         }       
804         Py_INCREF(Py_None);     
805         return Py_None;
806 }
807
808
809 #ifdef USE_NMESH
810 /** Special function to link NMesh data to an Object */
811 static PyObject *link_NMesh_toObject(DataBlock *objectblk, NMesh *nmesh)
812 {
813         int retval;
814         Mesh *mesh = nmesh->mesh;
815         Object *obj = PYBLOCK_AS_OBJECT(objectblk);
816
817         // if mesh was not created yet (mesh == 0), then do so:
818         if (!mesh) {
819                 mesh = Mesh_fromNMesh(nmesh); // create and convert data
820                 nmesh->mesh = mesh;
821                 nmesh_updateMaterials(nmesh);
822         }
823
824         retval = object_linkdata(obj, mesh);
825         if (!retval) {
826                 PyErr_SetString(PyExc_RuntimeError, "failed to link NMesh data");
827                 if (!mesh)
828                         printf("mesh data was null\n"); // XXX
829                 return NULL;
830         }
831         synchronizeMaterialLists(obj, obj->data);
832         return Py_BuildValue("i", retval);
833 }
834
835 #endif
836
837 /** This is the generic function for linking objects with each other.
838   * It can be called on any DataBlock, as long as this makes sense.
839   * Example:
840   * 
841   * from Blender import Object, Scene, NMesh
842   * ob = Object.get("Plane")
843   * scene = Scene.get("2")
844   * ob.link(scene)
845   *
846   *    or
847   *
848   *     nmesh = NMesh.GetRaw('Mesh')
849   * ob.link(nmesh)  # instanciate mesh
850   *
851   */
852
853 static char DataBlock_link_doc[]=
854 "(object) - Links 'self' with the specified object.\n\
855 Only the following object types can be linked to each other:\n\
856         Scene  -> Object\n\
857     Object -> Data (Mesh, Curve, etc.)\n\
858     Object -> Materials: [Material1, Material2, ...]\n\
859 \n\
860 The order of linking does not matter, i.e. the following both expressions\n\
861 are valid:\n\
862 \n\
863     scene.link(object)\n\
864 \n\
865     object.link(scene)\n\
866 ";
867         
868 PyObject *DataBlock_link(PyObject *self, PyObject *args)
869 {
870         DataBlock *blockA= (DataBlock*) self;
871         PyObject *with;
872         DataBlock *blockB;
873
874 #ifdef USE_NMESH
875         BPY_TRY(PyArg_ParseTuple(args, "O", &with));
876         
877         blockB = (DataBlock *) with;
878 #else   
879         BPY_TRY(PyArg_ParseTuple(args, "O!", &DataBlock_Type, &blockB));
880 #endif  
881
882         switch (DataBlock_type(blockA)) {
883                 case ID_OB:
884         // NMesh is no datablock object, so needs special treatment:
885 #ifdef USE_NMESH
886                         if (NMesh_Check(with)) {
887                                 return link_NMesh_toObject(blockA, (NMesh *) with);
888                         }       
889 #endif  
890                         if (!DataBlock_Check(blockB)) {
891                                 PyErr_SetString(PyExc_TypeError, "Argument must be a DataBlock object!");
892                                 return NULL;
893                         }       
894                         return link_Data_toObject(blockA, blockB);
895
896                 default:
897                         PyErr_SetString(PyExc_TypeError, "FATAL: implementation error, illegal link method");
898                         return NULL;
899         }
900 }
901
902 /* unlinking currently disabled, but might me needed later
903    for other object types...
904
905 static char DataBlock_unlink_doc[]=
906 "(object) - unlinks 'self' from the specified object.\n\
907 See documentation for link() for valid object types.";
908
909 static PyObject *DataBlock_unlink(PyObject *self, PyObject *args)
910 {
911         DataBlock *blockA= (DataBlock*) self;
912         DataBlock *blockB;
913
914         BPY_TRY(PyArg_ParseTuple(args, "O!", &DataBlock_Type, &blockB));
915         switch (DataBlock_type(blockA)) {
916                 case ID_SCE:
917                         switch(DataBlock_type(blockB)) {
918                                 case ID_OB:
919                                         return unlink_Object_fromScene(blockA, blockB);
920                                 default:
921                                         PyErr_SetString(PyExc_TypeError, "Scene unlink: invalid Object type");
922                                         return NULL;
923                         }
924                 default:
925                         PyErr_SetString(PyExc_TypeError, "cannot unlink: invalid object type");
926                         return NULL;
927
928         }
929
930 }
931 */
932
933 /** These are the methods common to each datablock */
934
935 static struct PyMethodDef commonDataBlock_methods[] = {
936         {"link", DataBlock_link, METH_VARARGS, DataBlock_link_doc},
937 //      {"unlink", DataBlock_unlink, METH_VARARGS, DataBlock_unlink_doc},
938         {NULL}
939 };
940
941 PyObject *DataBlock_getattr(PyObject *self, char *name) {
942         DataBlock *block= (DataBlock*) self;
943         PyObject *ret = NULL;
944         CHECK_VALIDDATA(block, "block was deleted!")
945
946         // Check for common attributes: 
947         if (STREQ(name, "name"))
948                 return PyString_FromString((((ID*)block->data)->name)+2);
949         else if (STREQ(name, "block_type"))
950                 return PyString_FromString(block->type);
951         else if (STREQ(name, "users"))
952                 return PyInt_FromLong(((ID*)block->data)->us);
953         
954         //
955         // the following datablock types have methods:
956         switch (DataBlock_type(block)) {
957         case ID_OB:
958                 ret = Py_FindMethod(Object_methods, self, name);
959                 break;
960         case ID_IP:
961                 ret = Py_FindMethod(Ipo_methods, self, name);
962                 break;
963         case ID_CA:
964                 ret = Py_FindMethod(Camera_methods, self, name);
965                 break;
966         case ID_MA:
967                 ret = Py_FindMethod(Material_methods, self, name);
968                 break;
969         case ID_LA:
970                 ret = Py_FindMethod(Lamp_methods, self, name);
971                 break;
972         case ID_TXT:
973                 ret = Py_FindMethod(Text_methods, self, name);
974                 break;
975         }       
976         if (ret) return ret;
977         PyErr_Clear(); // no method found, clear error
978
979         // try common datablock methods
980         ret = Py_FindMethod(commonDataBlock_methods, (PyObject*)self, name);
981         if (ret) return ret;
982
983         PyErr_Clear();
984
985         // try attributes from property list
986         ret = datablock_getattr(block->properties, block->type, name, block->data);
987         return ret;
988 }
989
990 int DataBlock_setattr(PyObject *self, char *name, PyObject *ob) {
991         DataBlock *block= (DataBlock*) self;
992
993         CHECK_VALIDDATA(block, "block was deleted!")
994
995         if (STREQ(name, "name")) {
996                 if (!PyArg_Parse(ob, "s", &name)) return -1;
997
998                 new_id(block->type_list, (ID*)block->data, name);
999                 
1000                 return 0;
1001         }
1002         return datablock_setattr(block->properties, block->type, name, block->data, ob);
1003 }
1004
1005
1006 PyTypeObject DataBlock_Type = {
1007         PyObject_HEAD_INIT(NULL)
1008         0,                                                                      /*ob_size*/
1009         "Block",                                                        /*tp_name*/
1010         sizeof(DataBlock),                                      /*tp_basicsize*/
1011         0,                                                                      /*tp_itemsize*/
1012         (destructor)    DataBlock_dealloc,      /*tp_dealloc*/
1013         (printfunc)             0,              /*tp_print*/
1014         (getattrfunc)   DataBlock_getattr,      /*tp_getattr*/
1015         (setattrfunc)   DataBlock_setattr,      /*tp_setattr*/
1016         (cmpfunc) 0,    /*tp_compare*/
1017         (reprfunc)      DataBlock_repr,         /*tp_repr*/
1018 };
1019
1020 /**************************************************************************/
1021
1022 /**********************/
1023 /* Texture Datablocks */
1024 /*
1025 DATABLOCK_GET(Texturemodule, texture, getTextureList())
1026
1027 static struct PyMethodDef Texture_methods[] = {
1028         {"Get", Texture_Get, 1, Texture_Get_doc},
1029         {NULL, NULL}
1030 };
1031 */
1032
1033
1034
1035 /* ---------------------------------------------------------------------- */
1036
1037 int DataBlock_type(DataBlock *block)
1038 {
1039         return (GET_ID_TYPE((ID *) block->data));
1040 }
1041
1042 int ObjectDataIDType(DataBlock *block)
1043 {
1044         Object *ob;
1045         if (!DataBlock_isType(block, ID_OB))
1046                 return -1;
1047
1048         ob = (Object *) block->data;
1049         return GET_ID_TYPE((ID *) ob->data);
1050 }
1051
1052 int DataBlock_isType(DataBlock *block, int type)
1053 {
1054         ID *id;
1055
1056         if (!DataBlock_Check(block)) return 0;
1057         id= (ID *) block->data;
1058         return (GET_ID_TYPE(id))==type;
1059 }
1060
1061 /** This function creates a Python datablock descriptor object from
1062   * the specified data pointer. This pointer must point to a structure
1063   * with a valid ID header.
1064   */
1065
1066 PyObject *DataBlock_fromData(void *data) {
1067         DataBlock *newb;
1068         ID *id= (ID *) data;
1069         int idn;
1070         
1071         if (!data) return BPY_incr_ret(Py_None);
1072
1073         idn = GET_ID_TYPE(id);
1074         
1075         if (idn==ID_OB) {
1076                 newb= PyObject_NEW(DataBlock, &DataBlock_Type);
1077                 newb->type= "Object";
1078                 newb->type_list= getObjectList();
1079                 newb->properties= Object_Properties;
1080
1081         } else if (idn==ID_ME) {
1082 #ifdef USE_NMESH        
1083                 return newNMesh(data);
1084 #else
1085                 newb= PyObject_NEW(DataBlock, &DataBlock_Type);
1086                 newb->type= "Mesh";
1087                 newb->type_list= getMeshList();
1088                 newb->properties= Mesh_Properties;
1089 #endif
1090
1091 //      } else if (idn==ID_CU) {
1092                 /* Special case, should be fixed
1093                  * by proper high-level NURBS access.
1094                  * 
1095                  * Later.
1096                  */
1097                  
1098 //              return newNCurveObject(data);                   
1099
1100         } else if (idn==ID_LA) {
1101                 newb= PyObject_NEW(DataBlock, &DataBlock_Type);
1102                 newb->type= "Lamp";
1103                 newb->type_list= getLampList();
1104                 newb->properties= Lamp_Properties;
1105
1106         } else if (idn==ID_CA) {
1107                 newb= PyObject_NEW(DataBlock, &DataBlock_Type);
1108                 newb->type= "Camera";
1109                 newb->type_list= getCameraList();
1110                 newb->properties= Camera_Properties;
1111
1112         } else if (idn==ID_MA) {
1113                 newb= PyObject_NEW(DataBlock, &DataBlock_Type);
1114                 newb->type= "Material";
1115                 newb->type_list= getMaterialList();
1116                 newb->properties= Material_Properties;
1117                 
1118         } else if (idn==ID_WO) {
1119                 newb= PyObject_NEW(DataBlock, &DataBlock_Type);
1120                 newb->type= "World";
1121                 newb->type_list= getWorldList();
1122                 newb->properties= World_Properties;
1123
1124         } else if (idn==ID_IP) {
1125                 newb= PyObject_NEW(DataBlock, &DataBlock_Type);
1126                 newb->type= "Ipo";
1127                 newb->type_list= getIpoList();
1128                 newb->properties= Ipo_Properties;               
1129
1130 #ifdef EXPERIMENTAL
1131         } else if (idn==ID_TE) {
1132                 newb= PyObject_NEW(DataBlock, &DataBlock_Type);
1133                 newb->type= "Tex";
1134                 newb->type_list= getTextureList();
1135                 newb->properties= Texture_Properties;           
1136 #endif
1137
1138         } else if (idn==ID_IM) {
1139                 newb= PyObject_NEW(DataBlock, &DataBlock_Type);
1140                 newb->type= "Image";
1141                 newb->type_list= getImageList();
1142                 newb->properties= Image_Properties;             
1143
1144         } else if (idn==ID_TXT) {
1145                 newb= PyObject_NEW(DataBlock, &DataBlock_Type);
1146                 newb->type= "Text";
1147                 newb->type_list= getTextList();
1148                 newb->properties= Text_Properties;              
1149         } else return BPY_err_ret_ob(PyExc_SystemError, "unable to create Block for data");
1150         
1151         newb->data= data;
1152 #ifdef REF_USERCOUNT
1153         BOB_INCUSER(id); // XXX abuse for refcount
1154 #endif
1155         
1156         return (PyObject *) newb;
1157 }
1158
1159 PyObject *get_DataBlock_func(void **ptr) {
1160         ID *id= (ID*) *ptr;
1161         return DataBlock_fromData(id);
1162 }
1163
1164 /* ---------------------------------------------------------------------- */
1165 /* INIT ROUTINE */
1166
1167
1168 void init_types(PyObject *dict)
1169 {
1170         PyObject *tmod, *tdict;
1171
1172         tmod= Py_InitModule("Blender.Types", Null_methods);
1173         PyDict_SetItemString(dict, "Types", tmod);
1174         
1175         tdict= PyModule_GetDict(tmod);
1176
1177         PyDict_SetItemString(tdict, "IpoCurve", (PyObject *)&PyIpoCurve_Type);
1178         PyDict_SetItemString(tdict, "BezTriple", (PyObject *)&PyBezTriple_Type);
1179
1180         PyDict_SetItemString(tdict, "ButtonType", (PyObject *)&Button_Type);
1181         PyDict_SetItemString(tdict, "BufferType", (PyObject *)&Buffer_Type);
1182         PyDict_SetItemString(tdict, "NMeshType", (PyObject *)&NMesh_Type);
1183         PyDict_SetItemString(tdict, "NMFaceType", (PyObject *)&NMFace_Type);
1184         PyDict_SetItemString(tdict, "NMVertType", (PyObject *)&NMVert_Type);
1185         PyDict_SetItemString(tdict, "NMColType", (PyObject *)&NMCol_Type);
1186
1187         PyDict_SetItemString(tdict, "BlockType", (PyObject *)&DataBlock_Type);
1188         
1189         /* Setup external types */
1190         PyDict_SetItemString(tdict, "VectorType", (PyObject *)&Vector_Type);
1191         PyDict_SetItemString(tdict, "MatrixType", (PyObject *)&Matrix_Type);
1192 }
1193
1194 #undef BPY_ADDCONST
1195 #define BPY_ADDCONST(dict, name) insertConst(dict, #name, PyInt_FromLong(LA_##name))
1196
1197 PyObject *initLamp(void)
1198 {
1199         PyObject *mod, *dict, *d;
1200
1201         mod= Py_InitModule(MODNAME(BLENDERMODULE) ".Lamp", Lampmodule_methods);
1202         dict= PyModule_GetDict(mod);
1203         d = ConstObject_New();
1204         PyDict_SetItemString(dict, "Types", d);
1205
1206         /* type */
1207         BPY_ADDCONST(d, LOCAL);
1208         BPY_ADDCONST(d, SUN);
1209         BPY_ADDCONST(d, SPOT);
1210         BPY_ADDCONST(d, HEMI);
1211
1212         d = ConstObject_New();
1213         PyDict_SetItemString(dict, "Modes", d);
1214
1215         /* mode */
1216         BPY_ADDCONST(d, SHAD);
1217         BPY_ADDCONST(d, HALO);
1218         BPY_ADDCONST(d, LAYER);
1219         BPY_ADDCONST(d, QUAD);
1220         BPY_ADDCONST(d, NEG);
1221         BPY_ADDCONST(d, ONLYSHADOW);
1222         BPY_ADDCONST(d, SPHERE);
1223         BPY_ADDCONST(d, SQUARE);
1224         BPY_ADDCONST(d, TEXTURE);
1225         BPY_ADDCONST(d, OSATEX);
1226         BPY_ADDCONST(d, DEEP_SHADOW);
1227
1228         return mod;
1229 }
1230
1231 PyObject *initMaterial(void)
1232 {
1233         PyObject *mod, *dict, *d;
1234
1235         mod= Py_InitModule(MODNAME(BLENDERMODULE) ".Material", 
1236                            Materialmodule_methods);
1237         dict= PyModule_GetDict(mod);
1238         d = ConstObject_New();
1239         PyDict_SetItemString(dict, "Modes", d);
1240
1241         /* MATERIAL MODES 
1242          * ...some of these have really cryptic defines :-) 
1243          * We try to match them to the GUI descriptions...  */
1244
1245 #undef BPY_ADDCONST
1246 #define BPY_ADDCONST(dict, name) \
1247         insertConst(dict, #name, PyInt_FromLong(MA_##name))
1248
1249         insertConst(d, "TRACEABLE", PyInt_FromLong(MA_TRACEBLE));
1250         BPY_ADDCONST(d, SHADOW);
1251         insertConst(d, "SHADELESS", PyInt_FromLong(MA_SHLESS));
1252         BPY_ADDCONST(d, WIRE);
1253         insertConst(d, "VCOL_LIGHT", PyInt_FromLong(MA_VERTEXCOL));
1254         BPY_ADDCONST(d, HALO);
1255         insertConst(d, "ZTRANSP", PyInt_FromLong(MA_ZTRA));
1256         insertConst(d, "VCOL_PAINT", PyInt_FromLong(MA_VERTEXCOLP));
1257         insertConst(d, "ZINVERT", PyInt_FromLong(MA_ZINV));
1258         BPY_ADDCONST(d, ONLYSHADOW);
1259         BPY_ADDCONST(d, STAR);
1260         insertConst(d, "TEXFACE", PyInt_FromLong(MA_FACETEXTURE));
1261         BPY_ADDCONST(d, NOMIST);
1262
1263         /* HALO MODES */
1264         d = ConstObject_New();
1265         PyDict_SetItemString(dict, "HaloModes", d);
1266
1267 #undef BPY_ADDCONST
1268 #define BPY_ADDCONST(dict, name) \
1269         insertConst(dict, #name, PyInt_FromLong(MA_HALO_##name))
1270
1271         BPY_ADDCONST(d, RINGS);
1272         BPY_ADDCONST(d, LINES);
1273         insertConst(d, "TEX", PyInt_FromLong(MA_HALOTEX));
1274         insertConst(d, "PUNO", PyInt_FromLong(MA_HALOPUNO));
1275         BPY_ADDCONST(d, SHADE);
1276         BPY_ADDCONST(d, FLARE);
1277
1278         return mod;
1279 }
1280
1281 void init_Datablockmodules(PyObject *dict) {
1282 #define MODLOAD(name)   PyDict_SetItemString(dict, #name, Py_InitModule(MODNAME(BLENDERMODULE) "." #name, name##module_methods))
1283
1284         DataBlock_Type.ob_type = &PyType_Type;
1285         PyIpoCurve_Type.ob_type= &PyType_Type;
1286         PyBezTriple_Type.ob_type= &PyType_Type;
1287
1288         PyDict_SetItemString(dict, "Object", initObject());
1289         PyDict_SetItemString(dict, "Lamp", initLamp());
1290         PyDict_SetItemString(dict, "Material", initMaterial());
1291         PyDict_SetItemString(dict, "Ipo", initIpo());
1292         PyDict_SetItemString(dict, "Scene", initScene());
1293         MODLOAD(Text);
1294 //      MODLOAD(Mesh);
1295         MODLOAD(Camera);
1296         MODLOAD(World);
1297         MODLOAD(Image);
1298 /*      MODLOAD(Texture); */
1299 }