f2cfbfb23e3bcd22acf38388685e2d02c424139f
[blender.git] / source / blender / python / api2_2x / Material.c
1 /* 
2  *
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA        02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * This is a new part of Blender.
26  *
27  * Contributor(s): Willian P. Germano, Michel Selten, Alex Mole
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30 */
31
32 #include <BKE_main.h>
33 #include <BKE_global.h>
34 #include <BKE_library.h>
35 #include <MEM_guardedalloc.h>
36 #include <DNA_ID.h>
37 #include <BLI_blenlib.h>
38
39 #include "constant.h"
40 #include "gen_utils.h"
41 #include "bpy_types.h"
42 #include "modules.h"
43
44 #include "MTex.h"
45 #include "Texture.h"
46
47 #include "Material.h"
48
49 /*****************************************************************************/
50 /* Python BPy_Material defaults:                                                                                                                                                                                 */
51 /*****************************************************************************/
52 #define EXPP_MAT_MODE_TRACEABLE                                         MA_TRACEBLE
53 #define EXPP_MAT_MODE_SHADOW                                                    MA_SHADOW
54 #define EXPP_MAT_MODE_SHADELESS                                         MA_SHLESS
55 #define EXPP_MAT_MODE_WIRE                                                              MA_WIRE
56 #define EXPP_MAT_MODE_VCOL_LIGHT                                        MA_VERTEXCOL
57 #define EXPP_MAT_MODE_HALO                                                              MA_HALO
58 #define EXPP_MAT_MODE_ZTRANSP                                                   MA_ZTRA
59 #define EXPP_MAT_MODE_VCOL_PAINT                                        MA_VERTEXCOLP
60 #define EXPP_MAT_MODE_ZINVERT                                                   MA_ZINV
61 #define EXPP_MAT_MODE_HALORINGS                                         MA_HALO_RINGS
62 #define EXPP_MAT_MODE_ENV                                                                       MA_ENV
63 #define EXPP_MAT_MODE_HALOLINES                                         MA_HALO_LINES
64 #define EXPP_MAT_MODE_ONLYSHADOW                                        MA_ONLYSHADOW
65 #define EXPP_MAT_MODE_HALOXALPHA                                        MA_HALO_XALPHA
66 #define EXPP_MAT_MODE_HALOSTAR                                          MA_STAR
67 #define EXPP_MAT_MODE_TEXFACE                                                   MA_FACETEXTURE
68 #define EXPP_MAT_MODE_HALOTEX                                                   MA_HALOTEX
69 #define EXPP_MAT_MODE_HALOPUNO                                          MA_HALOPUNO
70 #define EXPP_MAT_MODE_NOMIST                                                    MA_NOMIST
71 #define EXPP_MAT_MODE_HALOSHADE                                         MA_HALO_SHADE
72 #define EXPP_MAT_MODE_HALOFLARE                                         MA_HALO_FLARE
73 #define EXPP_MAT_MODE_RADIO                                                             MA_RADIO
74
75 /* Material MIN, MAX values */
76 #define EXPP_MAT_ADD_MIN                                         0.0
77 #define EXPP_MAT_ADD_MAX                                         1.0
78 #define EXPP_MAT_ALPHA_MIN                               0.0
79 #define EXPP_MAT_ALPHA_MAX                               1.0
80 #define EXPP_MAT_AMB_MIN                                         0.0
81 #define EXPP_MAT_AMB_MAX                                         1.0
82 #define EXPP_MAT_COL_MIN                                         0.0 /* min/max for all ... */
83 #define EXPP_MAT_COL_MAX                                         1.0 /* ... color triplets      */
84 #define EXPP_MAT_EMIT_MIN                                        0.0
85 #define EXPP_MAT_EMIT_MAX                                        1.0
86 #define EXPP_MAT_REF_MIN                                         0.0
87 #define EXPP_MAT_REF_MAX                                         1.0
88 #define EXPP_MAT_SPEC_MIN                                        0.0
89 #define EXPP_MAT_SPEC_MAX                                        2.0
90 #define EXPP_MAT_SPECTRA_MIN                     0.0
91 #define EXPP_MAT_SPECTRA_MAX                     1.0
92 #define EXPP_MAT_ZOFFS_MIN                               0.0
93 #define EXPP_MAT_ZOFFS_MAX                              10.0
94 #define EXPP_MAT_HALOSIZE_MIN                    0.0
95 #define EXPP_MAT_HALOSIZE_MAX            100.0
96 #define EXPP_MAT_FLARESIZE_MIN           0.1
97 #define EXPP_MAT_FLARESIZE_MAX          25.0
98 #define EXPP_MAT_FLAREBOOST_MIN          0.1
99 #define EXPP_MAT_FLAREBOOST_MAX         10.0
100 #define EXPP_MAT_SUBSIZE_MIN                     0.1
101 #define EXPP_MAT_SUBSIZE_MAX                    25.0
102
103 #define EXPP_MAT_HARD_MIN                                1
104 #define EXPP_MAT_HARD_MAX                        255    /* 127 with MODE HALO ON */
105 #define EXPP_MAT_HALOSEED_MIN            1
106 #define EXPP_MAT_HALOSEED_MAX  255
107 #define EXPP_MAT_NFLARES_MIN             1
108 #define EXPP_MAT_NFLARES_MAX            32
109 #define EXPP_MAT_FLARESEED_MIN   1
110 #define EXPP_MAT_FLARESEED_MAX 255
111 #define EXPP_MAT_NSTARS_MIN                      3
112 #define EXPP_MAT_NSTARS_MAX                     50
113 #define EXPP_MAT_NLINES_MIN                      0
114 #define EXPP_MAT_NLINES_MAX              250
115 #define EXPP_MAT_NRINGS_MIN                      0
116 #define EXPP_MAT_NRINGS_MAX                     24
117
118 /*****************************************************************************/
119 /* Python API function prototypes for the Material module.                                                                       */
120 /*****************************************************************************/
121 static PyObject *M_Material_New (PyObject *self, PyObject *args,
122                                                                                                                          PyObject *keywords);
123 static PyObject *M_Material_Get (PyObject *self, PyObject *args);
124
125 /*****************************************************************************/
126 /* The following string definitions are used for documentation strings.                  */
127 /* In Python these will be written to the console when doing a                                                   */
128 /* Blender.Material.__doc__                                                                                                                                                                                                      */
129 /*****************************************************************************/
130 static char M_Material_doc[] =
131 "The Blender Material module";
132
133 static char M_Material_New_doc[] =
134 "(name) - return a new material called 'name'\n\
135 () - return a new material called 'Mat'";
136
137 static char M_Material_Get_doc[] =
138 "(name) - return the material called 'name', None if not found.\n\
139 () - return a list of all materials in the current scene.";
140
141 /*****************************************************************************/
142 /* Python method structure definition for Blender.Material module:                                       */
143 /*****************************************************************************/
144 struct PyMethodDef M_Material_methods[] = {
145         {"New",(PyCFunction)M_Material_New, METH_VARARGS|METH_KEYWORDS,
146                                         M_Material_New_doc},
147         {"Get",                                 M_Material_Get,                                 METH_VARARGS, M_Material_Get_doc},
148         {"get",                                 M_Material_Get,                                 METH_VARARGS, M_Material_Get_doc},
149         {NULL, NULL, 0, NULL}
150 };
151
152 /*****************************************************************************/
153 /* Function:                                                    M_Material_New                                                                                                                                           */
154 /* Python equivalent:                   Blender.Material.New                                                                                                                     */
155 /*****************************************************************************/
156 static PyObject *M_Material_New(PyObject *self, PyObject *args,
157                                                                 PyObject *keywords)
158 {
159         char *name = "Mat";
160         static char *kwlist[] = {"name", NULL};
161         BPy_Material *pymat; /* for Material Data object wrapper in Python */
162         Material *blmat; /* for actual Material Data we create in Blender */
163         char buf[21];
164
165         if (!PyArg_ParseTupleAndKeywords(args, keywords, "|s", kwlist, &name))
166                 return (EXPP_ReturnPyObjError (PyExc_AttributeError,
167                                                 "expected string or nothing as argument"));
168
169         if (strcmp(name, "Mat") != 0) /* use gave us a name ?*/
170                 PyOS_snprintf(buf, sizeof(buf), "%s", name);
171
172         blmat = add_material(name); /* first create the Material Data in Blender */
173
174         if (blmat) /* now create the wrapper obj in Python */
175                 pymat = (BPy_Material *)Material_CreatePyObject (blmat);
176         else
177                 return (EXPP_ReturnPyObjError (PyExc_RuntimeError,
178                                                                                                                 "couldn't create Material Data in Blender"));
179
180         blmat->id.us = 0; /* was incref'ed by add_material() above */
181
182         if (pymat == NULL)
183                 return (EXPP_ReturnPyObjError (PyExc_MemoryError,
184                                                                                                                 "couldn't create Material Data object"));
185
186         return (PyObject *)pymat;
187 }
188
189 /*****************************************************************************/
190 /* Function:                                                    M_Material_Get                                                                                                                                           */
191 /* Python equivalent:                   Blender.Material.Get                                                                                                                     */
192 /* Description:                                         Receives a string and returns the material whose         */
193 /*                                                                                              name matches the string.        If no argument is                                */
194 /*                                                                                              passed in, a list with all materials in the                              */
195 /*                                                                                              current scene is returned.                                                                                               */
196 /*****************************************************************************/
197 static PyObject *M_Material_Get(PyObject *self, PyObject *args)
198 {
199         char     *name = NULL;
200         Material *mat_iter;
201
202         if (!PyArg_ParseTuple(args, "|s", &name))
203                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
204                                                 "expected string argument (or nothing)"));
205
206         mat_iter = G.main->mat.first;
207
208         if (name) { /* (name) - Search material by name */
209
210                 BPy_Material *wanted_mat = NULL;
211
212                 while ((mat_iter) && (wanted_mat == NULL)) {
213
214                         if (strcmp (name, mat_iter->id.name+2) == 0)
215                                 wanted_mat = (BPy_Material *)Material_CreatePyObject (mat_iter);
216
217                         mat_iter = mat_iter->id.next;
218                 }
219
220                 if (wanted_mat == NULL) { /* Requested material doesn't exist */
221                         char error_msg[64];
222                         PyOS_snprintf(error_msg, sizeof(error_msg),
223                                                                                         "Material \"%s\" not found", name);
224                         return (EXPP_ReturnPyObjError (PyExc_NameError, error_msg));
225                 }
226
227                 return (PyObject *)wanted_mat;
228         }
229
230         else { /* () - return a list with all materials in the scene */
231                 int index = 0;
232                 PyObject *matlist, *pyobj;
233
234                 matlist = PyList_New (BLI_countlist (&(G.main->mat)));
235
236                 if (!matlist)
237                         return (EXPP_ReturnPyObjError (PyExc_MemoryError,
238                                                         "couldn't create PyList"));
239
240                 while (mat_iter) {
241                         pyobj = Material_CreatePyObject (mat_iter);
242
243                         if (!pyobj)
244                                 return (EXPP_ReturnPyObjError (PyExc_MemoryError,
245                                                                         "couldn't create PyObject"));
246
247                         PyList_SET_ITEM (matlist, index, pyobj);
248
249                         mat_iter = mat_iter->id.next;
250                         index++;
251                 }
252
253                 return matlist;
254         }
255 }
256
257 static PyObject *Lamp_ModesDict (void)
258 {
259         PyObject *Modes = M_constant_New();
260
261 #undef EXPP_ADDCONST
262 #define EXPP_ADDCONST(name) \
263         constant_insert(c, #name, PyInt_FromLong(EXPP_MAT_MODE_##name))
264
265 /* So that:
266  * EXPP_ADDCONST(TRACEABLE) becomes:
267  * constant_insert(c, "TRACEABLE", PyInt_FromLong(EXPP_MAT_MODE_TRACEABLE))
268  */
269
270         if (Modes) {
271                 BPy_constant *c = (BPy_constant *)Modes;
272                 
273                 EXPP_ADDCONST(TRACEABLE);
274                 EXPP_ADDCONST(SHADOW);
275                 EXPP_ADDCONST(SHADELESS);
276                 EXPP_ADDCONST(WIRE);
277                 EXPP_ADDCONST(VCOL_LIGHT);
278                 EXPP_ADDCONST(HALO);
279                 EXPP_ADDCONST(ZTRANSP);
280                 EXPP_ADDCONST(VCOL_PAINT);
281                 EXPP_ADDCONST(ZINVERT);
282                 EXPP_ADDCONST(HALORINGS);
283                 EXPP_ADDCONST(ENV);
284                 EXPP_ADDCONST(HALOLINES);
285                 EXPP_ADDCONST(ONLYSHADOW);
286                 EXPP_ADDCONST(HALOXALPHA);
287                 EXPP_ADDCONST(HALOSTAR);
288                 EXPP_ADDCONST(TEXFACE);
289                 EXPP_ADDCONST(HALOTEX);
290                 EXPP_ADDCONST(HALOPUNO);
291                 EXPP_ADDCONST(NOMIST);
292                 EXPP_ADDCONST(HALOSHADE);
293                 EXPP_ADDCONST(HALOFLARE);
294                 EXPP_ADDCONST(RADIO);
295         }
296
297         return Modes;
298 }
299
300 /*****************************************************************************/
301 /* Function:                                                    Material_Init                                                                                                                                                    */
302 /*****************************************************************************/
303 PyObject *Material_Init (void)
304 {
305         PyObject        *submodule, *Modes;
306
307         Material_Type.ob_type = &PyType_Type;
308
309         Modes = Lamp_ModesDict ();
310
311         submodule = Py_InitModule3("Blender.Material",
312                                                                         M_Material_methods, M_Material_doc);
313
314         if (Modes) PyModule_AddObject(submodule, "Modes", Modes);
315         return (submodule);
316 }
317
318 /***************************/
319 /*** The Material PyType ***/
320 /***************************/
321
322 /*****************************************************************************/
323 /* Python BPy_Material methods declarations:                                                                                                                             */
324 /*****************************************************************************/
325 static PyObject *Material_getIpo(BPy_Material *self);
326 static PyObject *Material_getName(BPy_Material *self);
327 static PyObject *Material_getMode(BPy_Material *self);
328 static PyObject *Material_getRGBCol(BPy_Material *self);
329 /*static PyObject *Material_getAmbCol(BPy_Material *self);*/
330 static PyObject *Material_getSpecCol(BPy_Material *self);
331 static PyObject *Material_getMirCol(BPy_Material *self);
332 static PyObject *Material_getAmb(BPy_Material *self);
333 static PyObject *Material_getEmit(BPy_Material *self);
334 static PyObject *Material_getAlpha(BPy_Material *self);
335 static PyObject *Material_getRef(BPy_Material *self);
336 static PyObject *Material_getSpec(BPy_Material *self);
337 static PyObject *Material_getSpecTransp(BPy_Material *self);
338 static PyObject *Material_getAdd(BPy_Material *self);
339 static PyObject *Material_getZOffset(BPy_Material *self);
340 static PyObject *Material_getHaloSize(BPy_Material *self);
341 static PyObject *Material_getHaloSeed(BPy_Material *self);
342 static PyObject *Material_getFlareSize(BPy_Material *self);
343 static PyObject *Material_getFlareSeed(BPy_Material *self);
344 static PyObject *Material_getFlareBoost(BPy_Material *self);
345 static PyObject *Material_getSubSize(BPy_Material *self);
346 static PyObject *Material_getHardness(BPy_Material *self);
347 static PyObject *Material_getNFlares(BPy_Material *self);
348 static PyObject *Material_getNStars(BPy_Material *self);
349 static PyObject *Material_getNLines(BPy_Material *self);
350 static PyObject *Material_getNRings(BPy_Material *self);
351 static PyObject *Material_getTextures(BPy_Material *self);
352 static PyObject *Material_setIpo(BPy_Material *self, PyObject *args);
353 static PyObject *Material_clearIpo(BPy_Material *self);
354 static PyObject *Material_setName(BPy_Material *self, PyObject *args);
355 static PyObject *Material_setMode(BPy_Material *self, PyObject *args);
356 static PyObject *Material_setIntMode(BPy_Material *self, PyObject *args);
357 static PyObject *Material_setRGBCol(BPy_Material *self, PyObject *args);
358 /*static PyObject *Material_setAmbCol(BPy_Material *self, PyObject *args);*/
359 static PyObject *Material_setSpecCol(BPy_Material *self, PyObject *args);
360 static PyObject *Material_setMirCol(BPy_Material *self, PyObject *args);
361 static PyObject *Material_setAmb(BPy_Material *self, PyObject *args);
362 static PyObject *Material_setEmit(BPy_Material *self, PyObject *args);
363 static PyObject *Material_setAlpha(BPy_Material *self, PyObject *args);
364 static PyObject *Material_setRef(BPy_Material *self, PyObject *args);
365 static PyObject *Material_setSpec(BPy_Material *self, PyObject *args);
366 static PyObject *Material_setSpecTransp(BPy_Material *self, PyObject *args);
367 static PyObject *Material_setAdd(BPy_Material *self, PyObject *args);
368 static PyObject *Material_setZOffset(BPy_Material *self, PyObject *args);
369 static PyObject *Material_setHaloSize(BPy_Material *self, PyObject *args);
370 static PyObject *Material_setHaloSeed(BPy_Material *self, PyObject *args);
371 static PyObject *Material_setFlareSize(BPy_Material *self, PyObject *args);
372 static PyObject *Material_setFlareSeed(BPy_Material *self, PyObject *args);
373 static PyObject *Material_setFlareBoost(BPy_Material *self, PyObject *args);
374 static PyObject *Material_setSubSize(BPy_Material *self, PyObject *args);
375 static PyObject *Material_setHardness(BPy_Material *self, PyObject *args);
376 static PyObject *Material_setNFlares(BPy_Material *self, PyObject *args);
377 static PyObject *Material_setNStars(BPy_Material *self, PyObject *args);
378 static PyObject *Material_setNLines(BPy_Material *self, PyObject *args);
379 static PyObject *Material_setNRings(BPy_Material *self, PyObject *args);
380 static PyObject *Material_setTexture(BPy_Material *self, PyObject *args);
381 static PyObject *Material_clearTexture(BPy_Material *self, PyObject *args);
382
383 static PyObject *Material_setColorComponent(BPy_Material *self, char *key,
384                                                                 PyObject *args);
385
386 /*****************************************************************************/
387 /* Python BPy_Material methods table:                                                                                                                                                            */
388 /*****************************************************************************/
389 static PyMethodDef BPy_Material_methods[] = {
390  /* name, method, flags, doc */
391         {"getName", (PyCFunction)Material_getName, METH_NOARGS,
392                         "() - Return Material's name"},
393         {"getIpo", (PyCFunction)Material_getIpo, METH_NOARGS,
394                         "() - Return Material's ipo or None if not found"},
395         {"getMode", (PyCFunction)Material_getMode, METH_NOARGS,
396                         "() - Return Material's mode flags"},
397         {"getRGBCol", (PyCFunction)Material_getRGBCol, METH_NOARGS,
398                         "() - Return Material's rgb color triplet"},
399 /*      {"getAmbCol", (PyCFunction)Material_getAmbCol, METH_NOARGS,
400                         "() - Return Material's ambient color"},*/
401         {"getSpecCol", (PyCFunction)Material_getSpecCol, METH_NOARGS,
402                         "() - Return Material's specular color"},
403         {"getMirCol", (PyCFunction)Material_getMirCol, METH_NOARGS,
404                         "() - Return Material's mirror color"},
405         {"getAmb", (PyCFunction)Material_getAmb, METH_NOARGS,
406                         "() - Return Material's ambient color blend factor"},
407         {"getEmit", (PyCFunction)Material_getEmit, METH_NOARGS,
408                         "() - Return Material's emitting light intensity"},
409         {"getAlpha", (PyCFunction)Material_getAlpha, METH_NOARGS,
410                         "() - Return Material's alpha (transparency) value"},
411         {"getRef", (PyCFunction)Material_getRef, METH_NOARGS,
412                         "() - Return Material's reflectivity"},
413         {"getSpec", (PyCFunction)Material_getSpec, METH_NOARGS,
414                         "() - Return Material's specularity"},
415         {"getSpecTransp", (PyCFunction)Material_getSpecTransp, METH_NOARGS,
416                         "() - Return Material's specular transparency"},
417         {"getAdd", (PyCFunction)Material_getAdd, METH_NOARGS,
418                         "() - Return Material's glow factor"},
419         {"getZOffset", (PyCFunction)Material_getZOffset, METH_NOARGS,
420                         "() - Return Material's artificial offset for faces"},
421         {"getHaloSize", (PyCFunction)Material_getHaloSize, METH_NOARGS,
422                         "() - Return Material's halo size"},
423         {"getHaloSeed", (PyCFunction)Material_getHaloSeed, METH_NOARGS,
424                         "() - Return Material's seed for random ring dimension and line "
425                         "location in halos"},
426         {"getFlareSize", (PyCFunction)Material_getFlareSize, METH_NOARGS,
427                         "() - Return Material's (flare size)/(halo size) factor"},
428         {"getFlareSeed", (PyCFunction)Material_getFlareSeed, METH_NOARGS,
429                         "() - Return Material's flare offset in the seed table"},
430         {"getFlareBoost", (PyCFunction)Material_getFlareBoost, METH_NOARGS,
431                         "() - Return Material's flare boost"},
432         {"getSubSize", (PyCFunction)Material_getSubSize, METH_NOARGS,
433                         "() - Return Material's dimension of subflare, dots and circles"},
434         {"getHardness", (PyCFunction)Material_getHardness, METH_NOARGS,
435                         "() - Return Material's specular hardness"},
436         {"getNFlares", (PyCFunction)Material_getNFlares, METH_NOARGS,
437                         "() - Return Material's number of flares in halo"},
438         {"getNStars", (PyCFunction)Material_getNStars, METH_NOARGS,
439                         "() - Return Material's number of points in the halo stars"},
440         {"getNLines", (PyCFunction)Material_getNLines, METH_NOARGS,
441                         "() - Return Material's number of lines in halo"},
442         {"getNRings", (PyCFunction)Material_getNRings, METH_NOARGS,
443                         "() - Return Material's number of rings in halo"},
444         {"getTextures", (PyCFunction)Material_getTextures, METH_NOARGS,
445                         "() - Return Material's texture list as a tuple"},
446         {"setName", (PyCFunction)Material_setName, METH_VARARGS,
447                         "(s) - Change Material's name"},
448         {"setIpo", (PyCFunction)Material_setIpo, METH_VARARGS,
449                         "(Blender Ipo) - Change Material's Ipo"},
450         {"clearIpo", (PyCFunction)Material_clearIpo, METH_NOARGS,
451                         "(Blender Ipo) - Unlink Ipo from this Material"},
452         {"setMode", (PyCFunction)Material_setMode, METH_VARARGS,
453                         "([s[,s]]) - Set Material's mode flag(s)"},
454         {"setRGBCol", (PyCFunction)Material_setRGBCol, METH_VARARGS,
455                         "(f,f,f or [f,f,f]) - Set Material's rgb color triplet"},
456 /*      {"setAmbCol", (PyCFunction)Material_setAmbCol, METH_VARARGS,
457                         "(f,f,f or [f,f,f]) - Set Material's ambient color"},*/
458         {"setSpecCol", (PyCFunction)Material_setSpecCol, METH_VARARGS,
459                         "(f,f,f or [f,f,f]) - Set Material's specular color"},
460         {"setMirCol", (PyCFunction)Material_setMirCol, METH_VARARGS,
461                         "(f,f,f or [f,f,f]) - Set Material's mirror color"},
462         {"setAmb", (PyCFunction)Material_setAmb, METH_VARARGS,
463                         "(f) - Set how much the Material's color is affected"
464                                                         " by \nthe global ambient colors - [0.0, 1.0]"},
465         {"setEmit", (PyCFunction)Material_setEmit, METH_VARARGS,
466                         "(f) - Set Material's emitting light intensity - [0.0, 1.0]"},
467         {"setAlpha", (PyCFunction)Material_setAlpha, METH_VARARGS,
468                         "(f) - Set Material's alpha (transparency) - [0.0, 1.0]"},
469         {"setRef", (PyCFunction)Material_setRef, METH_VARARGS,
470                         "(f) - Set Material's reflectivity - [0.0, 1.0]"},
471         {"setSpec", (PyCFunction)Material_setSpec, METH_VARARGS,
472                         "(f) - Set Material's specularity - [0.0, 2.0]"},
473         {"setSpecTransp", (PyCFunction)Material_setSpecTransp, METH_VARARGS,
474                         "(f) - Set Material's specular transparency - [0.0, 1.0]"},
475         {"setAdd", (PyCFunction)Material_setAdd, METH_VARARGS,
476                         "(f) - Set Material's glow factor - [0.0, 1.0]"},
477         {"setZOffset", (PyCFunction)Material_setZOffset, METH_VARARGS,
478                         "(f) - Set Material's artificial offset - [0.0, 10.0]"},
479         {"setHaloSize", (PyCFunction)Material_setHaloSize, METH_VARARGS,
480                         "(f) - Set Material's halo size - [0.0, 100.0]"},
481         {"setHaloSeed", (PyCFunction)Material_setHaloSeed, METH_VARARGS,
482                         "(i) - Set Material's halo seed - [0, 255]"},
483         {"setFlareSize", (PyCFunction)Material_setFlareSize, METH_VARARGS,
484                         "(f) - Set Material's factor: (flare size)/(halo size) - [0.1, 25.0]"},
485         {"setFlareSeed", (PyCFunction)Material_setFlareSeed, METH_VARARGS,
486                         "(i) - Set Material's flare seed - [0, 255]"},
487         {"setFlareBoost", (PyCFunction)Material_setFlareBoost, METH_VARARGS,
488                         "(f) - Set Material's flare boost - [0.1, 10.0]"},
489         {"setSubSize", (PyCFunction)Material_setSubSize, METH_VARARGS,
490                         "(f) - Set Material's dimension of subflare,"
491                                                         " dots and circles - [0.1, 25.0]"},
492         {"setHardness", (PyCFunction)Material_setHardness, METH_VARARGS,
493                         "(i) - Set Material's hardness - [1, 255 (127 if halo mode is ON)]"},
494         {"setNFlares", (PyCFunction)Material_setNFlares, METH_VARARGS,
495                         "(i) - Set Material's number of flares in halo - [1, 32]"},
496         {"setNStars", (PyCFunction)Material_setNStars, METH_VARARGS,
497                         "(i) - Set Material's number of stars in halo - [3, 50]"},
498         {"setNLines", (PyCFunction)Material_setNLines, METH_VARARGS,
499                         "(i) - Set Material's number of lines in halo - [0, 250]"},
500         {"setNRings", (PyCFunction)Material_setNRings, METH_VARARGS,
501                         "(i) - Set Material's number of rings in halo - [0, 24]"},
502         {"setTexture", (PyCFunction)Material_setTexture, METH_VARARGS,
503                    "(n,tex,texco=0,mapto=0) - Set numbered texture to tex"},
504         {"clearTexture", (PyCFunction)Material_clearTexture, METH_VARARGS,
505                         "(n) - Remove texture from numbered slot"},
506         {NULL, NULL, 0, NULL}
507 };
508
509 /*****************************************************************************/
510 /* Python Material_Type callback function prototypes:                                                                                            */
511 /*****************************************************************************/
512 static void Material_dealloc (BPy_Material *self);
513 static int Material_setAttr (BPy_Material *self, char *name, PyObject *v);
514 static PyObject *Material_getAttr (BPy_Material *self, char *name);
515 static PyObject *Material_repr (BPy_Material *self);
516
517 /*****************************************************************************/
518 /* Python Material_Type structure definition:                                                                                                                            */
519 /*****************************************************************************/
520 PyTypeObject Material_Type =
521 {
522         PyObject_HEAD_INIT(NULL)
523         0,                                                                                                                                                      /* ob_size */
524         "Blender Material",                                                                                     /* tp_name */
525         sizeof (BPy_Material),                                                                  /* tp_basicsize */
526         0,                                                                                                                                                      /* tp_itemsize */
527         /* methods */
528         (destructor)Material_dealloc,                                           /* tp_dealloc */
529         0,                                                                                                                                                      /* tp_print */
530         (getattrfunc)Material_getAttr,                                  /* tp_getattr */
531         (setattrfunc)Material_setAttr,                                  /* tp_setattr */
532         0,                                                                                                                                                      /* tp_compare */
533         (reprfunc)Material_repr,                                                                /* tp_repr */
534         0,                                                                                                                                                      /* tp_as_number */
535         0,                                                                                                                                                      /* tp_as_sequence */
536         0,                                                                                                                                                      /* tp_as_mapping */
537         0,                                                                                                                                                      /* tp_as_hash */
538         0,0,0,0,0,0,
539         0,                                                                                                                                                      /* tp_doc */ 
540         0,0,0,0,0,0,
541         BPy_Material_methods,                                                                                   /* tp_methods */
542         0,                                                                                                                                                      /* tp_members */
543 };
544
545 /*****************************************************************************/
546 /* Function:            Material_dealloc                                                                                                                                                                                 */
547 /* Description: This is a callback function for the BPy_Material type. It is */
548 /*                                                      the destructor function.                                                                                                                                                 */
549 /*****************************************************************************/
550 static void Material_dealloc (BPy_Material *self)
551 {
552         Py_DECREF (self->col);
553         Py_DECREF (self->amb);
554         Py_DECREF (self->spec);
555         Py_DECREF (self->mir);
556         PyObject_DEL (self);
557 }
558
559 /*****************************************************************************/
560 /* Function:            Material_CreatePyObject                                                                                                                                                  */
561 /* Description: This function will create a new BPy_Material from an existing*/
562 /*                                                      Blender material structure.                                                                                                                                      */
563 /*****************************************************************************/
564 PyObject *Material_CreatePyObject (struct Material *mat)
565 {
566         BPy_Material *pymat;
567         float *col[3], *amb[3], *spec[3], *mir[3];
568
569         pymat = (BPy_Material *)PyObject_NEW (BPy_Material, &Material_Type);
570
571         if (!pymat)
572                 return EXPP_ReturnPyObjError (PyExc_MemoryError,
573                                                 "couldn't create BPy_Material object");
574
575         pymat->material = mat;
576
577         col[0] = &mat->r;
578         col[1] = &mat->g;
579         col[2] = &mat->b;
580
581         amb[0] = &mat->ambr;
582         amb[1] = &mat->ambg;
583         amb[2] = &mat->ambb;
584
585         spec[0] = &mat->specr;
586         spec[1] = &mat->specg;
587         spec[2] = &mat->specb;
588
589         mir[0] = &mat->mirr;
590         mir[1] = &mat->mirg;
591         mir[2] = &mat->mirb;
592
593         pymat->col      = (BPy_rgbTuple *)rgbTuple_New(col);
594         pymat->amb      = (BPy_rgbTuple *)rgbTuple_New(amb);
595         pymat->spec = (BPy_rgbTuple *)rgbTuple_New(spec);
596         pymat->mir      = (BPy_rgbTuple *)rgbTuple_New(mir);
597
598         return (PyObject *)pymat;
599 }
600
601 /*****************************************************************************/
602 /* Function:            Material_CheckPyObject                                                                                                                                                   */
603 /* Description: This function returns true when the given PyObject is of the */
604 /*                                                      type Material. Otherwise it will return false.                                                   */
605 /*****************************************************************************/
606 int Material_CheckPyObject (PyObject *pyobj)
607 {
608         return (pyobj->ob_type == &Material_Type);
609 }
610
611 /*****************************************************************************/
612 /* Function:            Material_FromPyObject                                                                                                                                                            */
613 /* Description: This function returns the Blender material from the given                */
614 /*                                                      PyObject.                                                                                                                                                                                                                */
615 /*****************************************************************************/
616 Material *Material_FromPyObject (PyObject *pyobj)
617 {
618         return ((BPy_Material *)pyobj)->material;
619 }
620
621 /*****************************************************************************/
622 /* Description: Returns the object with the name specified by the argument       */
623 /*                                                      name. Note that the calling function has to remove the first */
624 /*                                                      two characters of the object name. These two characters                  */
625 /*                                                      specify the type of the object (OB, ME, WO, ...)                                                 */
626 /*                                                      The function will return NULL when no object with the given  */
627 /*                                                      name is found.                                                                                                                                                                                   */
628 /*****************************************************************************/
629 Material * GetMaterialByName (char * name)
630 {
631         Material        * mat_iter;
632
633         mat_iter = G.main->mat.first;
634         while (mat_iter)
635         {
636                 if (StringEqual (name, GetIdName (&(mat_iter->id))))
637                 {
638                         return (mat_iter);
639                 }
640                 mat_iter = mat_iter->id.next;
641         }
642
643         /* There is no material with the given name */
644         return (NULL);
645 }
646
647 /*****************************************************************************/
648 /* Python BPy_Material methods:                                                                                                                                                                                          */
649 /*****************************************************************************/
650
651 static PyObject *Material_getIpo(BPy_Material *self)
652 {
653         Ipo *ipo = self->material->ipo;
654
655         if (!ipo) {
656                 Py_INCREF(Py_None);
657                 return Py_None;
658         }
659         
660         return Ipo_CreatePyObject (ipo);
661 }
662
663 static PyObject *Material_getName(BPy_Material *self)
664 {
665         PyObject *attr = PyString_FromString(self->material->id.name+2);
666
667         if (attr) return attr;
668
669         return (EXPP_ReturnPyObjError (PyExc_RuntimeError,
670                                                                                                                                          "couldn't get Material.name attribute"));
671 }
672
673 static PyObject *Material_getMode(BPy_Material *self)
674 {
675         PyObject *attr = PyInt_FromLong((long)self->material->mode);
676
677         if (attr) return attr;
678
679         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
680                                                                                                                                          "couldn't get Material.Mode attribute");
681 }
682
683 static PyObject *Material_getRGBCol(BPy_Material *self)
684 {
685         return rgbTuple_getCol(self->col);
686 }
687 /*
688 static PyObject *Material_getAmbCol(BPy_Material *self)
689 {
690         return rgbTuple_getCol(self->amb);
691 }
692 */
693 static PyObject *Material_getSpecCol(BPy_Material *self)
694 {
695         return rgbTuple_getCol(self->spec);
696 }
697
698 static PyObject *Material_getMirCol(BPy_Material *self)
699 {
700         return rgbTuple_getCol(self->mir);
701 }
702
703 static PyObject *Material_getAmb(BPy_Material *self)
704 {
705         PyObject *attr = PyFloat_FromDouble((double)self->material->amb);
706
707         if (attr) return attr;
708
709         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
710                                                                                                                                          "couldn't get Material.amb attribute");
711 }
712
713 static PyObject *Material_getEmit(BPy_Material *self)
714 {
715         PyObject *attr = PyFloat_FromDouble((double)self->material->emit);
716
717         if (attr) return attr;
718
719         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
720                                                                                                                                          "couldn't get Material.emit attribute");
721 }
722
723 static PyObject *Material_getAlpha(BPy_Material *self)
724 {
725         PyObject *attr = PyFloat_FromDouble((double)self->material->alpha);
726
727         if (attr) return attr;
728
729         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
730                                                                                                                                          "couldn't get Material.alpha attribute");
731 }
732
733 static PyObject *Material_getRef(BPy_Material *self)
734 {
735         PyObject *attr = PyFloat_FromDouble((double)self->material->ref);
736
737         if (attr) return attr;
738
739         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
740                                                                                                                                          "couldn't get Material.ref attribute");
741 }
742
743 static PyObject *Material_getSpec(BPy_Material *self)
744 {
745         PyObject *attr = PyFloat_FromDouble((double)self->material->spec);
746
747         if (attr) return attr;
748
749         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
750                                                                                                                                          "couldn't get Material.spec attribute");
751 }
752
753 static PyObject *Material_getSpecTransp(BPy_Material *self)
754 {
755         PyObject *attr = PyFloat_FromDouble((double)self->material->spectra);
756
757         if (attr) return attr;
758
759         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
760                                                         "couldn't get Material.specTransp attribute");
761 }
762
763 static PyObject *Material_getAdd(BPy_Material *self)
764 {
765         PyObject *attr = PyFloat_FromDouble((double)self->material->add);
766
767         if (attr) return attr;
768
769         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
770                                                                                                                                          "couldn't get Material.add attribute");
771 }
772
773 static PyObject *Material_getZOffset(BPy_Material *self)
774 {
775         PyObject *attr = PyFloat_FromDouble((double)self->material->zoffs);
776
777         if (attr) return attr;
778
779         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
780                                                                                                 "couldn't get Material.zOffset attribute");
781 }
782
783 static PyObject *Material_getHaloSize(BPy_Material *self)
784 {
785         PyObject *attr = PyFloat_FromDouble((double)self->material->hasize);
786
787         if (attr) return attr;
788
789         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
790                                                                          "couldn't get Material.haloSize attribute");
791 }
792
793 static PyObject *Material_getFlareSize(BPy_Material *self)
794 {
795         PyObject *attr = PyFloat_FromDouble((double)self->material->flaresize);
796
797         if (attr) return attr;
798
799         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
800                                                                                  "couldn't get Material.flareSize attribute");
801 }
802
803 static PyObject *Material_getFlareBoost(BPy_Material *self)
804 {
805         PyObject *attr = PyFloat_FromDouble((double)self->material->flareboost);
806
807         if (attr) return attr;
808
809         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
810                                                                                  "couldn't get Material.flareBoost attribute");
811 }
812
813 static PyObject *Material_getSubSize(BPy_Material *self)
814 {
815         PyObject *attr = PyFloat_FromDouble((double)self->material->subsize);
816
817         if (attr) return attr;
818
819         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
820                                                          "couldn't get Material.subSize attribute");
821 }
822
823 static PyObject *Material_getHaloSeed(BPy_Material *self)
824 {
825         PyObject *attr = PyInt_FromLong((long)self->material->seed1);
826
827         if (attr) return attr;
828
829         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
830                                                                                          "couldn't get Material.haloSeed attribute");
831 }
832
833 static PyObject *Material_getFlareSeed(BPy_Material *self)
834 {
835         PyObject *attr = PyInt_FromLong((long)self->material->seed2);
836
837         if (attr) return attr;
838
839         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
840                                                                                          "couldn't get Material.flareSeed attribute");
841 }
842
843 static PyObject *Material_getHardness(BPy_Material *self)
844 {
845         PyObject *attr = PyInt_FromLong((long)self->material->har);
846
847         if (attr) return attr;
848
849         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
850                                                                                          "couldn't get Material.hard attribute");
851 }
852
853 static PyObject *Material_getNFlares(BPy_Material *self)
854 {
855         PyObject *attr = PyInt_FromLong((long)self->material->flarec);
856
857         if (attr) return attr;
858
859         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
860                                                                                          "couldn't get Material.nFlares attribute");
861 }
862
863 static PyObject *Material_getNStars(BPy_Material *self)
864 {
865         PyObject *attr = PyInt_FromLong((long)self->material->starc);
866
867         if (attr) return attr;
868
869         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
870                                                                                          "couldn't get Material.nStars attribute");
871 }
872
873 static PyObject *Material_getNLines(BPy_Material *self)
874 {
875         PyObject *attr = PyInt_FromLong((long)self->material->linec);
876
877         if (attr) return attr;
878
879         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
880                                                                                          "couldn't get Material.nLines attribute");
881 }
882
883 static PyObject *Material_getNRings(BPy_Material *self)
884 {
885         PyObject *attr = PyInt_FromLong((long)self->material->ringc);
886
887         if (attr) return attr;
888
889         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
890                                                                                          "couldn't get Material.nRings attribute");
891 }
892
893 static PyObject *Material_getTextures(BPy_Material *self)
894 {
895   int i;
896   struct MTex *mtex;
897   PyObject *t[8];
898   PyObject *tuple;
899   
900   /* build a texture list */
901   for (i=0; i<8; ++i) {
902     mtex = self->material->mtex[i];
903     
904     if (mtex) {
905       t[i] = MTex_CreatePyObject (mtex);
906     }
907     else {
908       Py_INCREF (Py_None);
909       t[i] = Py_None;
910     }
911   }
912
913   /* turn the array into a tuple */
914   tuple = Py_BuildValue ("NNNNNNNN", t[0], t[1], t[2], t[3], 
915                                      t[4], t[5], t[6], t[7]);
916         if (!tuple) 
917                 return EXPP_ReturnPyObjError(PyExc_MemoryError,
918                                                                                                  "Material_getTextures: couldn't create PyTuple");
919
920   return tuple;
921 }
922
923 static PyObject *Material_setIpo(BPy_Material *self, PyObject *args)
924 {
925         PyObject *pyipo = 0;
926         Ipo *ipo = NULL;
927         Ipo *oldipo;
928
929         if (!PyArg_ParseTuple(args, "O!", &Ipo_Type, &pyipo))
930                 return EXPP_ReturnPyObjError (PyExc_TypeError, "expected Ipo as argument");
931
932         ipo = Ipo_FromPyObject(pyipo);
933
934         if (!ipo) return EXPP_ReturnPyObjError (PyExc_RuntimeError, "null ipo!");
935
936         if (ipo->blocktype != ID_MA)
937                 return EXPP_ReturnPyObjError (PyExc_TypeError,
938                         "this ipo is not a Material type ipo");
939
940         oldipo = self->material->ipo;
941         if (oldipo) {
942                 ID *id = &oldipo->id;
943                 if (id->us > 0) id->us--;
944         }
945
946         ((ID *)&ipo->id)->us++;
947
948         self->material->ipo = ipo;
949
950         Py_INCREF(Py_None);
951         return Py_None;
952 }
953
954 static PyObject *Material_clearIpo(BPy_Material *self)
955 {
956         Material *mat = self->material;
957         Ipo *ipo = (Ipo *)mat->ipo;
958
959         if (ipo) {
960                 ID *id = &ipo->id;
961                 if (id->us > 0) id->us--;
962                 mat->ipo = NULL;
963
964                 Py_INCREF (Py_True);
965                 return Py_True;
966         }
967
968         Py_INCREF (Py_False); /* no ipo found */
969         return Py_False;
970 }
971
972 static PyObject *Material_setName(BPy_Material *self, PyObject *args)
973 {
974         char *name;
975         char buf[21];
976
977         if (!PyArg_ParseTuple(args, "s", &name))
978                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
979                                                                                                                                                  "expected string argument"));
980
981         PyOS_snprintf(buf, sizeof(buf), "%s", name);
982
983         rename_id(&self->material->id, buf);
984
985         Py_INCREF(Py_None);
986         return Py_None;
987 }
988
989 /* Possible modes are traceable, shadow, shadeless, wire, vcolLight,
990  * vcolPaint, halo, ztransp, zinvert, haloRings, env, haloLines,
991  * onlyShadow, xalpha, star, faceTexture, haloTex, haloPuno, noMist,
992  * haloShaded, haloFlare */
993 static PyObject *Material_setMode(BPy_Material *self, PyObject *args)
994 {
995         int i, flag = 0;
996         char *m[22] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL,
997                                                                  NULL, NULL, NULL, NULL, NULL, NULL, NULL,
998                                                                  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
999
1000         if (!PyArg_ParseTuple(args, "|ssssssssssssssssssssss",
1001                                         &m[0], &m[1], &m[2], &m[3],  &m[4],  &m[5],  &m[6],
1002                                         &m[7], &m[8], &m[9], &m[10], &m[11], &m[12], &m[13],
1003                                         &m[14], &m[15], &m[16], &m[17], &m[18], &m[19], &m[20], &m[21]))
1004         {
1005                 return (EXPP_ReturnPyObjError (PyExc_AttributeError,
1006                                                 "expected from none to 22 string argument(s)"));
1007         }
1008
1009         for (i = 0; i < 22; i++) {
1010                 if (m[i] == NULL) break;
1011                 if (strcmp(m[i], "Traceable") == 0)
1012                         flag |= EXPP_MAT_MODE_TRACEABLE;
1013                 else if (strcmp(m[i], "Shadow") == 0)
1014                         flag |= EXPP_MAT_MODE_SHADOW;
1015                 else if (strcmp(m[i], "Shadeless") == 0)
1016                         flag |= EXPP_MAT_MODE_SHADELESS;
1017                 else if (strcmp(m[i], "Wire") == 0)
1018                         flag |= EXPP_MAT_MODE_WIRE;
1019                 else if (strcmp(m[i], "VColLight") == 0)
1020                         flag |= EXPP_MAT_MODE_VCOL_LIGHT;
1021                 else if (strcmp(m[i], "VColPaint") == 0)
1022                         flag |= EXPP_MAT_MODE_VCOL_PAINT;
1023                 else if (strcmp(m[i], "Halo") == 0)
1024                         flag |= EXPP_MAT_MODE_HALO;
1025                 else if (strcmp(m[i], "ZTransp") == 0)
1026                         flag |= EXPP_MAT_MODE_ZTRANSP;
1027                 else if (strcmp(m[i], "ZInvert") == 0)
1028                         flag |= EXPP_MAT_MODE_ZINVERT;
1029                 else if (strcmp(m[i], "HaloRings") == 0)
1030                         flag |= EXPP_MAT_MODE_HALORINGS;
1031                 else if (strcmp(m[i], "Env") == 0)
1032                         flag |= EXPP_MAT_MODE_ENV;
1033                 else if (strcmp(m[i], "HaloLines") == 0)
1034                         flag |= EXPP_MAT_MODE_HALOLINES;
1035                 else if (strcmp(m[i], "OnlyShadow") == 0)
1036                         flag |= EXPP_MAT_MODE_ONLYSHADOW;
1037                 else if (strcmp(m[i], "HaloXAlpha") == 0)
1038                         flag |= EXPP_MAT_MODE_HALOXALPHA;
1039                 else if (strcmp(m[i], "HaloStar") == 0)
1040                         flag |= EXPP_MAT_MODE_HALOSTAR;
1041                 else if (strcmp(m[i], "TexFace") == 0)
1042                         flag |= EXPP_MAT_MODE_TEXFACE;
1043                 else if (strcmp(m[i], "HaloTex") == 0)
1044                         flag |= EXPP_MAT_MODE_HALOTEX;
1045                 else if (strcmp(m[i], "HaloPuno") == 0)
1046                         flag |= EXPP_MAT_MODE_HALOPUNO;
1047                 else if (strcmp(m[i], "NoMist") == 0)
1048                         flag |= EXPP_MAT_MODE_NOMIST;
1049                 else if (strcmp(m[i], "HaloShaded") == 0)
1050                         flag |= EXPP_MAT_MODE_HALOSHADE;
1051                 else if (strcmp(m[i], "HaloFlare") == 0)
1052                         flag |= EXPP_MAT_MODE_HALOFLARE;
1053                 else if (strcmp(m[i], "Radio") == 0)
1054                         flag |= EXPP_MAT_MODE_RADIO;
1055                 else
1056                         return (EXPP_ReturnPyObjError (PyExc_AttributeError,
1057                                                         "unknown Material mode argument"));
1058         }
1059
1060         self->material->mode = flag;
1061
1062         Py_INCREF(Py_None);
1063         return Py_None;
1064 }
1065
1066 /* Another helper function, for the same reason.
1067  * (See comment before Material_setIntType above). */
1068 static PyObject *Material_setIntMode(BPy_Material *self, PyObject *args)
1069 {
1070         int value;
1071
1072         if (!PyArg_ParseTuple(args, "i", &value))
1073                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1074                                                                                                                                                  "expected int argument"));
1075
1076         self->material->mode = value;
1077
1078         Py_INCREF(Py_None);
1079         return Py_None;
1080 }
1081
1082 static PyObject *Material_setRGBCol (BPy_Material *self, PyObject *args)
1083 {
1084         return rgbTuple_setCol(self->col, args);
1085 }
1086 /*
1087 static PyObject *Material_setAmbCol (BPy_Material *self, PyObject *args)
1088 {
1089         return rgbTuple_setCol(self->amb, args);
1090 }
1091 */
1092 static PyObject *Material_setSpecCol (BPy_Material *self, PyObject *args)
1093 {
1094         return rgbTuple_setCol(self->spec, args);
1095 }
1096
1097 static PyObject *Material_setMirCol (BPy_Material *self, PyObject *args)
1098 {
1099         return rgbTuple_setCol(self->mir, args);
1100 }
1101
1102 static PyObject *Material_setColorComponent(BPy_Material *self, char *key,
1103                                                                 PyObject *args)
1104 { /* for compatibility with old bpython */
1105         float value;
1106
1107         if (!PyArg_ParseTuple(args, "f", &value))
1108                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1109                                                 "expected float argument in [0.0, 1.0]"));
1110
1111         value = EXPP_ClampFloat (value, EXPP_MAT_COL_MIN,
1112                                                                         EXPP_MAT_COL_MAX);
1113
1114         if (!strcmp(key, "R"))
1115                 self->material->r = value;
1116         else if (!strcmp(key, "G"))
1117                 self->material->g = value;
1118         else if (!strcmp(key, "B"))
1119                 self->material->b = value;
1120         else if (!strcmp(key, "specR"))
1121                 self->material->specr = value;
1122         else if (!strcmp(key, "specG"))
1123                 self->material->specg = value;
1124         else if (!strcmp(key, "specB"))
1125                 self->material->specb = value;
1126
1127         return EXPP_incr_ret (Py_None);
1128 }
1129
1130 static PyObject *Material_setAmb(BPy_Material *self, PyObject *args)
1131 {
1132         float value;
1133
1134         if (!PyArg_ParseTuple(args, "f", &value))
1135                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1136                                                 "expected float argument in [0.0, 1.0]"));
1137
1138         self->material->amb = EXPP_ClampFloat (value, EXPP_MAT_AMB_MIN,
1139                                                                         EXPP_MAT_AMB_MAX);
1140
1141         return EXPP_incr_ret (Py_None);
1142 }
1143
1144 static PyObject *Material_setEmit(BPy_Material *self, PyObject *args)
1145 {
1146         float value;
1147
1148         if (!PyArg_ParseTuple(args, "f", &value))
1149                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1150                                                 "expected float argument in [0.0, 1.0]"));
1151
1152         self->material->emit = EXPP_ClampFloat (value, EXPP_MAT_EMIT_MIN,
1153                                                                         EXPP_MAT_EMIT_MAX);
1154
1155         return EXPP_incr_ret (Py_None);
1156 }
1157
1158 static PyObject *Material_setSpecTransp(BPy_Material *self, PyObject *args)
1159 {
1160         float value;
1161
1162         if (!PyArg_ParseTuple(args, "f", &value))
1163                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1164                                                 "expected float argument in [0.0, 1.0]"));
1165
1166         self->material->spectra = EXPP_ClampFloat (value, EXPP_MAT_SPECTRA_MIN,
1167                                                                         EXPP_MAT_SPECTRA_MAX);
1168
1169         return EXPP_incr_ret (Py_None);
1170 }
1171
1172 static PyObject *Material_setAlpha(BPy_Material *self, PyObject *args)
1173 {
1174         float value;
1175
1176         if (!PyArg_ParseTuple(args, "f", &value))
1177                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1178                                                 "expected float argument in [0.0, 1.0]"));
1179
1180         self->material->alpha = EXPP_ClampFloat (value, EXPP_MAT_ALPHA_MIN,
1181                                                                         EXPP_MAT_ALPHA_MAX);
1182
1183         return EXPP_incr_ret (Py_None);
1184 }
1185
1186 static PyObject *Material_setRef(BPy_Material *self, PyObject *args)
1187 {
1188         float value;
1189
1190         if (!PyArg_ParseTuple(args, "f", &value))
1191                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1192                                                 "expected float argument in [0.0, 1.0]"));
1193
1194         self->material->ref = EXPP_ClampFloat (value, EXPP_MAT_REF_MIN,
1195                                                                         EXPP_MAT_REF_MAX);
1196
1197         return EXPP_incr_ret (Py_None);
1198 }
1199
1200 static PyObject *Material_setSpec(BPy_Material *self, PyObject *args)
1201 {
1202         float value;
1203
1204         if (!PyArg_ParseTuple(args, "f", &value))
1205                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1206                                                 "expected float argument in [0.0, 1.0]"));
1207
1208         self->material->spec = EXPP_ClampFloat (value, EXPP_MAT_SPEC_MIN,
1209                                                                         EXPP_MAT_SPEC_MAX);
1210
1211         return EXPP_incr_ret (Py_None);
1212 }
1213
1214 static PyObject *Material_setZOffset(BPy_Material *self, PyObject *args)
1215 {
1216         float value;
1217
1218         if (!PyArg_ParseTuple(args, "f", &value))
1219                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1220                                                 "expected float argument in [0.0, 10.0]"));
1221
1222         self->material->zoffs = EXPP_ClampFloat (value, EXPP_MAT_ZOFFS_MIN,
1223                                                                         EXPP_MAT_ZOFFS_MAX);
1224
1225         return EXPP_incr_ret (Py_None);
1226 }
1227
1228 static PyObject *Material_setAdd(BPy_Material *self, PyObject *args)
1229 {
1230         float value;
1231
1232         if (!PyArg_ParseTuple(args, "f", &value))
1233                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1234                                                 "expected float argument in [0.0, 1.0]"));
1235
1236         self->material->add = EXPP_ClampFloat (value, EXPP_MAT_ADD_MIN,
1237                                                                         EXPP_MAT_ADD_MAX);
1238
1239         return EXPP_incr_ret (Py_None);
1240 }
1241
1242 static PyObject *Material_setHaloSize(BPy_Material *self, PyObject *args)
1243 {
1244         float value;
1245
1246         if (!PyArg_ParseTuple(args, "f", &value))
1247                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1248                                                 "expected float argument in [0.0, 100.0]"));
1249
1250         self->material->hasize = EXPP_ClampFloat (value, EXPP_MAT_HALOSIZE_MIN,
1251                                                                         EXPP_MAT_HALOSIZE_MAX);
1252
1253         return EXPP_incr_ret (Py_None);
1254 }
1255
1256 static PyObject *Material_setFlareSize(BPy_Material *self, PyObject *args)
1257 {
1258          float value;
1259
1260         if (!PyArg_ParseTuple(args, "f", &value))
1261                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1262                                                 "expected float argument in [0.1, 25.0]"));
1263
1264         self->material->flaresize = EXPP_ClampFloat (value, EXPP_MAT_FLARESIZE_MIN,
1265                                                                         EXPP_MAT_FLARESIZE_MAX);
1266
1267         return EXPP_incr_ret (Py_None);
1268 }
1269
1270 static PyObject *Material_setFlareBoost(BPy_Material *self, PyObject *args)
1271 {
1272          float value;
1273
1274         if (!PyArg_ParseTuple(args, "f", &value))
1275                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1276                                                 "expected float argument in [0.1, 10.0]"));
1277
1278         self->material->flareboost = EXPP_ClampFloat(value, EXPP_MAT_FLAREBOOST_MIN,
1279                                                                         EXPP_MAT_FLAREBOOST_MAX);
1280
1281         return EXPP_incr_ret (Py_None);
1282 }
1283
1284 static PyObject *Material_setSubSize(BPy_Material *self, PyObject *args)
1285 {
1286          float value;
1287
1288         if (!PyArg_ParseTuple(args, "f", &value))
1289                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1290                                                 "expected float argument in [0.1, 25.0]"));
1291
1292         self->material->subsize = EXPP_ClampFloat (value, EXPP_MAT_SUBSIZE_MIN,
1293                                                                         EXPP_MAT_SUBSIZE_MAX);
1294
1295         return EXPP_incr_ret (Py_None);
1296 }
1297
1298 static PyObject *Material_setHaloSeed(BPy_Material *self, PyObject *args)
1299 {
1300         short value;
1301
1302         if (!PyArg_ParseTuple(args, "h", &value))                        
1303                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1304                                                 "expected int argument in [1, 255]"));
1305
1306         self->material->seed1 = EXPP_ClampInt (value, EXPP_MAT_HALOSEED_MIN,
1307                                                                         EXPP_MAT_HALOSEED_MAX);
1308
1309         return EXPP_incr_ret (Py_None);
1310 }
1311
1312 static PyObject *Material_setFlareSeed(BPy_Material *self, PyObject *args)
1313 {
1314         short value;
1315
1316         if (!PyArg_ParseTuple(args, "h", &value))                        
1317                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1318                                                 "expected int argument in [1, 255]"));
1319
1320         self->material->seed2 = EXPP_ClampInt (value, EXPP_MAT_FLARESEED_MIN,
1321                                                                         EXPP_MAT_FLARESEED_MAX);
1322
1323         return EXPP_incr_ret (Py_None);
1324 }
1325
1326
1327 static PyObject *Material_setHardness(BPy_Material *self, PyObject *args)
1328 {
1329         short value;
1330
1331         if (!PyArg_ParseTuple(args, "h", &value))                        
1332                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1333                                                 "expected int argument in [1, 255]"));
1334
1335         self->material->har = EXPP_ClampInt (value, EXPP_MAT_HARD_MIN,
1336                                                                         EXPP_MAT_HARD_MAX);
1337
1338         return EXPP_incr_ret (Py_None);
1339 }
1340
1341 static PyObject *Material_setNFlares(BPy_Material *self, PyObject *args)
1342 {
1343         short value;
1344
1345         if (!PyArg_ParseTuple(args, "h", &value))                        
1346                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1347                                                 "expected int argument in [1, 32]"));
1348
1349         self->material->flarec = EXPP_ClampInt (value, EXPP_MAT_NFLARES_MIN,
1350                                                                         EXPP_MAT_NFLARES_MAX);
1351
1352         return EXPP_incr_ret (Py_None);
1353 }
1354
1355 static PyObject *Material_setNStars(BPy_Material *self, PyObject *args)
1356 {
1357         short value;
1358
1359         if (!PyArg_ParseTuple(args, "h", &value))                        
1360                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1361                                                 "expected int argument in [3, 50]"));
1362
1363         self->material->starc = EXPP_ClampInt (value, EXPP_MAT_NSTARS_MIN,
1364                                                                         EXPP_MAT_NSTARS_MAX);
1365
1366         return EXPP_incr_ret (Py_None);
1367 }
1368
1369 static PyObject *Material_setNLines(BPy_Material *self, PyObject *args)
1370 {
1371         short value;
1372
1373         if (!PyArg_ParseTuple(args, "h", &value))                        
1374                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1375                                                 "expected int argument in [0, 250]"));
1376
1377         self->material->linec = EXPP_ClampInt (value, EXPP_MAT_NLINES_MIN,
1378                                                                         EXPP_MAT_NLINES_MAX);
1379
1380         return EXPP_incr_ret (Py_None);
1381 }
1382
1383 static PyObject *Material_setNRings(BPy_Material *self, PyObject *args)
1384 {
1385         short value;
1386
1387         if (!PyArg_ParseTuple(args, "h", &value))                        
1388                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1389                                                 "expected int argument in [0, 24]"));
1390
1391         self->material->ringc = EXPP_ClampInt (value, EXPP_MAT_NRINGS_MIN,
1392                                                                         EXPP_MAT_NRINGS_MAX);
1393
1394         return EXPP_incr_ret (Py_None);
1395 }
1396
1397 static PyObject *Material_setTexture(BPy_Material *self, PyObject *args)
1398 {
1399   int texnum;
1400   PyObject *pytex;
1401   Tex *bltex;
1402   int texco=TEXCO_ORCO, mapto=MAP_COL;
1403
1404   if (!PyArg_ParseTuple(args, "iO!|ii", &texnum, &Texture_Type, &pytex,
1405                                         &texco, &mapto))
1406     return EXPP_ReturnPyObjError (PyExc_TypeError,
1407                     "expected int in [0,7] and Texture");
1408   if ((texnum<0) || (texnum>=8))
1409     return EXPP_ReturnPyObjError (PyExc_TypeError,
1410                     "expected int in [0,7] and Texture");
1411   
1412   bltex = Texture_FromPyObject (pytex);
1413   
1414   if (!self->material->mtex[texnum]) {
1415     /* there isn't an mtex for this slot so we need to make one */
1416     self->material->mtex[texnum] = add_mtex ();
1417   }
1418   else {
1419     /* we already had a texture here so deal with the old one first */
1420     self->material->mtex[texnum]->tex->id.us--;
1421   }
1422   
1423   self->material->mtex[texnum]->tex = bltex;
1424   id_us_plus (&bltex->id);
1425   self->material->mtex[texnum]->texco = texco;
1426   self->material->mtex[texnum]->mapto = mapto;
1427
1428   Py_INCREF(Py_None);
1429   return Py_None;
1430 }
1431
1432 static PyObject *Material_clearTexture(BPy_Material *self, PyObject *args)
1433 {
1434   int texnum;
1435   struct MTex *mtex;
1436
1437   if (!PyArg_ParseTuple(args, "i", &texnum))
1438     return EXPP_ReturnPyObjError (PyExc_TypeError,
1439                     "expected int in [0,7]");
1440   if ((texnum<0) || (texnum>=8))
1441     return EXPP_ReturnPyObjError (PyExc_TypeError,
1442                     "expected int in [0,7]");
1443   
1444   mtex = self->material->mtex[texnum];
1445   if (mtex) {
1446     if (mtex->tex)
1447       mtex->tex->id.us--;
1448     MEM_freeN (mtex);    
1449     self->material->mtex[texnum] = NULL;
1450   }
1451   
1452   Py_INCREF(Py_None);
1453   return Py_None;
1454 }
1455
1456 /*****************************************************************************/
1457 /* Function:            Material_getAttr                                                                                                                                                                                 */
1458 /* Description: This is a callback function for the BPy_Material type. It is */
1459 /*                                                      the function that accesses BPy_Material "member variables"       */
1460 /*                                                      and methods.                                                                                                                                                                                             */
1461 /*****************************************************************************/
1462 static PyObject *Material_getAttr (BPy_Material *self, char *name)
1463 {
1464         PyObject *attr = Py_None;
1465
1466         if (strcmp(name, "name") == 0)
1467                 attr = PyString_FromString(self->material->id.name+2);
1468         else if (strcmp(name, "mode") == 0)
1469                 attr = PyInt_FromLong(self->material->mode);
1470         else if (strcmp(name, "rgbCol") == 0)
1471                 attr = Material_getRGBCol(self);
1472 /*      else if (strcmp(name, "ambCol") == 0)
1473                 attr = Material_getAmbCol(self);*/
1474         else if (strcmp(name, "specCol") == 0)
1475                 attr = Material_getSpecCol(self);
1476         else if (strcmp(name, "mirCol") == 0)
1477                 attr = Material_getMirCol(self);
1478         else if (strcmp(name, "R") == 0)
1479                 attr = PyFloat_FromDouble((double)self->material->r);
1480         else if (strcmp(name, "G") == 0)
1481                 attr = PyFloat_FromDouble((double)self->material->g);
1482         else if (strcmp(name, "B") == 0)
1483                 attr = PyFloat_FromDouble((double)self->material->b);
1484         else if (strcmp(name, "specR") == 0)
1485                 attr = PyFloat_FromDouble((double)self->material->specr);
1486         else if (strcmp(name, "specG") == 0)
1487                 attr = PyFloat_FromDouble((double)self->material->specg);
1488         else if (strcmp(name, "specB") == 0)
1489                 attr = PyFloat_FromDouble((double)self->material->specb);
1490         else if (strcmp(name, "amb") == 0)
1491                 attr = PyFloat_FromDouble((double)self->material->amb);
1492         else if (strcmp(name, "emit") == 0)
1493                 attr = PyFloat_FromDouble((double)self->material->emit);
1494         else if (strcmp(name, "alpha") == 0)
1495                 attr = PyFloat_FromDouble((double)self->material->alpha);
1496         else if (strcmp(name, "ref") == 0)
1497                 attr = PyFloat_FromDouble((double)self->material->ref);
1498         else if (strcmp(name, "spec") == 0)
1499                 attr = PyFloat_FromDouble((double)self->material->spec);
1500         else if (strcmp(name, "specTransp") == 0)
1501                 attr = PyFloat_FromDouble((double)self->material->spectra);
1502         else if (strcmp(name, "add") == 0)
1503                 attr = PyFloat_FromDouble((double)self->material->add);
1504         else if (strcmp(name, "zOffset") == 0)
1505                 attr = PyFloat_FromDouble((double)self->material->zoffs);
1506         else if (strcmp(name, "haloSize") == 0)
1507                 attr = PyFloat_FromDouble((double)self->material->hasize);
1508         else if (strcmp(name, "haloSeed") == 0)
1509                 attr = PyInt_FromLong((double)self->material->seed1);
1510         else if (strcmp(name, "flareSize") == 0)
1511                 attr = PyFloat_FromDouble((double)self->material->flaresize);
1512         else if (strcmp(name, "flareBoost") == 0)
1513                 attr = PyFloat_FromDouble((double)self->material->flareboost);
1514         else if (strcmp(name, "flareSeed") == 0)
1515                 attr = PyInt_FromLong((double)self->material->seed2);
1516         else if (strcmp(name, "subSize") == 0)
1517                 attr = PyFloat_FromDouble((double)self->material->subsize);
1518         else if (strcmp(name, "hard") == 0)
1519                 attr = PyInt_FromLong((long)self->material->har);
1520         else if (strcmp(name, "nFlares") == 0)
1521                 attr = PyInt_FromLong((long)self->material->flarec);
1522         else if (strcmp(name, "nStars") == 0)
1523                 attr = PyInt_FromLong((long)self->material->starc);
1524         else if (strcmp(name, "nLines") == 0)
1525                 attr = PyInt_FromLong((long)self->material->linec);
1526         else if (strcmp(name, "nRings") == 0)
1527                 attr = PyInt_FromLong((long)self->material->ringc);
1528
1529         else if (strcmp(name, "__members__") == 0) {
1530                 attr = /* 27 items */
1531                         Py_BuildValue("[s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s]",
1532                                 "name", "mode", "rgbCol", "specCol", "mirCol",
1533                                 "R", "G", "B", "alpha", "amb", "emit", "ref", "spec",
1534                                 "specTransp", "add", "zOffset", "haloSize", "haloSeed",
1535                                 "flareSize", "flareBoost", "flareSeed", "subSize", "hard",
1536                                 "nFlares", "nStars", "nLines", "nRings");
1537         }
1538
1539         if (!attr)
1540                 return (EXPP_ReturnPyObjError (PyExc_MemoryError,
1541                                                                                         "couldn't create PyObject"));
1542
1543         if (attr != Py_None) return attr; /* member attribute found, return it */
1544
1545         /* not an attribute, search the methods table */
1546         return Py_FindMethod(BPy_Material_methods, (PyObject *)self, name);
1547 }
1548
1549 /****************************************************************************/
1550 /* Function:            Material_setAttr                                                                                                                                                                                */
1551 /* Description: This is a callback function for the BPy_Material type.                  */
1552 /*                                                      It is the function that sets Material attributes (member                */
1553 /*                                                      variables).                                                                                                                                                                                                     */
1554 /****************************************************************************/
1555 static int Material_setAttr (BPy_Material *self, char *name, PyObject *value)
1556 {
1557         PyObject *valtuple; 
1558         PyObject *error = NULL;
1559
1560 /* We're playing a trick on the Python API users here.  Even if they use
1561  * Material.member = val instead of Material.setMember(val), we end up using the
1562  * function anyway, since it already has error checking, clamps to the right
1563  * interval and updates the Blender Material structure when necessary. */
1564
1565 /* First we put "value" in a tuple, because we want to pass it to functions
1566  * that only accept PyTuples. */
1567         valtuple = Py_BuildValue("(O)", value);
1568
1569         if (!valtuple) /* everything OK with our PyObject? */
1570                 return EXPP_ReturnIntError(PyExc_MemoryError,
1571                                                                                                  "MaterialSetAttr: couldn't create PyTuple");
1572
1573 /* Now we just compare "name" with all possible BPy_Material member variables */
1574         if (strcmp (name, "name") == 0)
1575                 error = Material_setName (self, valtuple);
1576         else if (strcmp (name, "mode") == 0)
1577                 error = Material_setIntMode (self, valtuple); /* special case */
1578         else if (strcmp (name, "rgbCol") == 0)
1579                 error = Material_setRGBCol (self, valtuple);
1580 /*      else if (strcmp (name, "ambCol") == 0)
1581                 error = Material_setAmbCol (self, valtuple);*/
1582         else if (strcmp (name, "specCol") == 0)
1583                 error = Material_setSpecCol (self, valtuple);
1584         else if (strcmp (name, "mirCol") == 0)
1585                 error = Material_setMirCol (self, valtuple);
1586         else if (strcmp (name, "R") == 0)
1587                 error = Material_setColorComponent (self, "R", valtuple);
1588         else if (strcmp (name, "G") == 0)
1589                 error = Material_setColorComponent (self, "G", valtuple);
1590         else if (strcmp (name, "B") == 0)
1591                 error = Material_setColorComponent (self, "B", valtuple);
1592         else if (strcmp (name, "specR") == 0)
1593                 error = Material_setColorComponent (self, "specR", valtuple);
1594         else if (strcmp (name, "specG") == 0)
1595                 error = Material_setColorComponent (self, "specG", valtuple);
1596         else if (strcmp (name, "specB") == 0)
1597                 error = Material_setColorComponent (self, "specB", valtuple);
1598         else if (strcmp (name, "amb") == 0)
1599                 error = Material_setAmb (self, valtuple);
1600         else if (strcmp (name, "emit") == 0)
1601                 error = Material_setEmit (self, valtuple);
1602         else if (strcmp (name, "alpha") == 0)
1603                 error = Material_setAlpha (self, valtuple);
1604         else if (strcmp (name, "ref") == 0)
1605                 error = Material_setRef (self, valtuple);
1606         else if (strcmp (name, "spec") == 0)
1607                 error = Material_setSpec (self, valtuple);
1608         else if (strcmp (name, "specTransp") == 0)
1609                 error = Material_setSpecTransp (self, valtuple);
1610         else if (strcmp (name, "add") == 0)
1611                 error = Material_setAdd (self, valtuple);
1612         else if (strcmp (name, "zOffset") == 0)
1613                 error = Material_setZOffset (self, valtuple);
1614         else if (strcmp (name, "haloSize") == 0)
1615                 error = Material_setHaloSize (self, valtuple);
1616         else if (strcmp (name, "haloSeed") == 0)
1617                 error = Material_setHaloSeed (self, valtuple);
1618         else if (strcmp (name, "flareSize") == 0)
1619                 error = Material_setFlareSize (self, valtuple);
1620         else if (strcmp (name, "flareBoost") == 0)
1621                 error = Material_setFlareBoost (self, valtuple);
1622         else if (strcmp (name, "flareSeed") == 0)
1623                 error = Material_setFlareSeed (self, valtuple);
1624         else if (strcmp (name, "subSize") == 0)
1625                 error = Material_setSubSize (self, valtuple);
1626         else if (strcmp (name, "hard") == 0)
1627                 error = Material_setHardness (self, valtuple);
1628         else if (strcmp (name, "nFlares") == 0)
1629                 error = Material_setNFlares (self, valtuple);
1630         else if (strcmp (name, "nStars") == 0)
1631                 error = Material_setNStars (self, valtuple);
1632         else if (strcmp (name, "nLines") == 0)
1633                 error = Material_setNLines (self, valtuple);
1634         else if (strcmp (name, "nRings") == 0)
1635                 error = Material_setNRings (self, valtuple);
1636
1637         else { /* Error */
1638                 Py_DECREF(valtuple);
1639                 return (EXPP_ReturnIntError (PyExc_AttributeError, name));
1640         }
1641
1642 /* valtuple won't be returned to the caller, so we need to DECREF it */
1643         Py_DECREF(valtuple);
1644
1645         if (error != Py_None) return -1;
1646
1647 /* Py_None was incref'ed by the called Material_set* function. We probably
1648  * don't need to decref Py_None (!), but since Python/C API manual tells us
1649  * to treat it like any other PyObject regarding ref counting ... */
1650         Py_DECREF(Py_None);
1651         return 0; /* normal exit */
1652 }
1653
1654 /*****************************************************************************/
1655 /* Function:            Material_repr                                                                                                                                                                                            */
1656 /* Description: This is a callback function for the BPy_Material type. It                */
1657 /*                                                      builds a meaninful string to represent material objects.                 */
1658 /*****************************************************************************/
1659 static PyObject *Material_repr (BPy_Material *self)
1660 {
1661         return PyString_FromFormat ("[Material \"%s\"]", self->material->id.name+2);
1662 }
1663
1664
1665 /*****************************************************************************/
1666 /* These functions are used in NMesh.c and Object.c                                                                                                      */
1667 /*****************************************************************************/
1668 PyObject *EXPP_PyList_fromMaterialList (Material **matlist, int len)
1669 {
1670         PyObject *list;
1671         int i;
1672
1673         list = PyList_New(0);
1674         if (!matlist) return list;
1675
1676         for (i = 0; i < len; i++) {
1677                 Material *mat = matlist[i];
1678                 PyObject *ob;
1679
1680                 if (mat) {
1681                         ob = Material_CreatePyObject (mat);
1682                         PyList_Append (list, ob);
1683                         Py_DECREF (ob); /* because Append increfs */
1684                 }
1685         }
1686
1687         return list;
1688 }
1689
1690 Material **EXPP_newMaterialList_fromPyList (PyObject *list)
1691 {
1692         int i, len;
1693         BPy_Material *pymat = 0;
1694         Material *mat;
1695         Material **matlist;
1696
1697         len = PySequence_Length (list);
1698         if (len > 16) len = 16;
1699
1700         matlist = EXPP_newMaterialList (len);
1701
1702         for (i= 0; i < len; i++) {
1703
1704                 pymat = (BPy_Material *)PySequence_GetItem (list, i);
1705
1706                 if (Material_CheckPyObject ((PyObject *)pymat)) {
1707                         mat = pymat->material;
1708                         matlist[i] = mat;
1709                 }
1710
1711                 else { /* error; illegal type in material list */
1712                         Py_DECREF(pymat);
1713                         MEM_freeN(matlist);
1714                         return NULL;
1715                 }
1716
1717                 Py_DECREF(pymat);
1718         }
1719
1720         return matlist;
1721 }
1722
1723 Material **EXPP_newMaterialList(int len)
1724 {
1725         Material **matlist =
1726                 (Material **)MEM_mallocN(len * sizeof(Material *), "MaterialList");
1727
1728         return matlist;
1729 }
1730
1731 int EXPP_releaseMaterialList (Material **matlist, int len)
1732 {
1733                 int                                             i;
1734                 Material                * mat;
1735
1736                 if ((len < 0) || (len > MAXMAT)) {
1737                                 printf ("illegal matindex!\n");
1738                                 return 0;
1739                 }
1740
1741                 for (i=0 ; i<len ; i++) {
1742                                 mat = matlist[i];
1743                                 if (mat != NULL) {
1744                                                 if (((ID *)mat)->us > 0)
1745                                                                 ((ID *)mat)->us--;
1746                                                 else
1747                                                                 printf ("FATAL: material usage=0: %s", ((ID *)mat)->name);
1748                                 }
1749                 }
1750                 MEM_freeN (matlist);
1751
1752                 return 1;
1753 }
1754
1755 /** expands pointer array of length 'oldsize' to length 'newsize'.
1756         * A pointer to the (void *) array must be passed as first argument 
1757         * The array pointer content can be NULL, in this case a new array of length
1758         * 'newsize' is created.
1759         */
1760
1761 static int expandPtrArray(void **p, int oldsize, int newsize)
1762 {
1763         void *newarray;
1764
1765         if (newsize < oldsize) {
1766                 return 0;
1767         }       
1768         newarray = MEM_callocN(newsize * sizeof(void *), "PtrArray");
1769         if (*p) {
1770                 memcpy(newarray, *p, oldsize);
1771                 MEM_freeN(*p);
1772         }       
1773         *p = newarray;
1774         return 1;
1775 }
1776
1777 int EXPP_synchronizeMaterialLists (Object *object, void *data)
1778 {
1779                 Material        *** p_dataMaterials = give_matarar (object);
1780                 short                           * nmaterials = give_totcolp (object);
1781
1782                 if (object->totcol > *nmaterials) {
1783                                 /* More object mats than data mats */
1784                                 *nmaterials = object->totcol;
1785                                 return expandPtrArray ((void *) p_dataMaterials,
1786                                                                                                                          *nmaterials,
1787                                                                                                                          object->totcol);
1788                 }
1789                 else {
1790                                 if (object->totcol < *nmaterials) {
1791                                                 /* More data mats than object mats */
1792                                                 object->totcol = *nmaterials;
1793                                                 return expandPtrArray ((void *) &object->mat,
1794                                                                                                                                          object->totcol,
1795                                                                                                                                          *nmaterials);
1796                                 }
1797                 }
1798
1799                 /* No synchronization is needed; they're of equal length */
1800                 return 1;
1801 }
1802
1803 void EXPP_incr_mats_us (Material **matlist, int len)
1804 {
1805         int i;
1806         Material *mat;
1807
1808         if (len <= 0) return;
1809
1810         for (i = 0; i < len; i++) {
1811                 mat = matlist[i];
1812                 if (mat) mat->id.us++;
1813         }
1814
1815         return;
1816 }
1817