BPython:
[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 static PyObject *Material_getScriptLinks(BPy_Material *self, PyObject *args);
387 static PyObject *Material_addScriptLink(BPy_Material *self, PyObject *args);
388 static PyObject *Material_clearScriptLinks(BPy_Material *self);
389
390 /*****************************************************************************/
391 /* Python BPy_Material methods table:                                                                                                                                                            */
392 /*****************************************************************************/
393 static PyMethodDef BPy_Material_methods[] = {
394  /* name, method, flags, doc */
395         {"getName", (PyCFunction)Material_getName, METH_NOARGS,
396                         "() - Return Material's name"},
397         {"getIpo", (PyCFunction)Material_getIpo, METH_NOARGS,
398                         "() - Return Material's ipo or None if not found"},
399         {"getMode", (PyCFunction)Material_getMode, METH_NOARGS,
400                         "() - Return Material's mode flags"},
401         {"getRGBCol", (PyCFunction)Material_getRGBCol, METH_NOARGS,
402                         "() - Return Material's rgb color triplet"},
403 /*      {"getAmbCol", (PyCFunction)Material_getAmbCol, METH_NOARGS,
404                         "() - Return Material's ambient color"},*/
405         {"getSpecCol", (PyCFunction)Material_getSpecCol, METH_NOARGS,
406                         "() - Return Material's specular color"},
407         {"getMirCol", (PyCFunction)Material_getMirCol, METH_NOARGS,
408                         "() - Return Material's mirror color"},
409         {"getAmb", (PyCFunction)Material_getAmb, METH_NOARGS,
410                         "() - Return Material's ambient color blend factor"},
411         {"getEmit", (PyCFunction)Material_getEmit, METH_NOARGS,
412                         "() - Return Material's emitting light intensity"},
413         {"getAlpha", (PyCFunction)Material_getAlpha, METH_NOARGS,
414                         "() - Return Material's alpha (transparency) value"},
415         {"getRef", (PyCFunction)Material_getRef, METH_NOARGS,
416                         "() - Return Material's reflectivity"},
417         {"getSpec", (PyCFunction)Material_getSpec, METH_NOARGS,
418                         "() - Return Material's specularity"},
419         {"getSpecTransp", (PyCFunction)Material_getSpecTransp, METH_NOARGS,
420                         "() - Return Material's specular transparency"},
421         {"getAdd", (PyCFunction)Material_getAdd, METH_NOARGS,
422                         "() - Return Material's glow factor"},
423         {"getZOffset", (PyCFunction)Material_getZOffset, METH_NOARGS,
424                         "() - Return Material's artificial offset for faces"},
425         {"getHaloSize", (PyCFunction)Material_getHaloSize, METH_NOARGS,
426                         "() - Return Material's halo size"},
427         {"getHaloSeed", (PyCFunction)Material_getHaloSeed, METH_NOARGS,
428                         "() - Return Material's seed for random ring dimension and line "
429                         "location in halos"},
430         {"getFlareSize", (PyCFunction)Material_getFlareSize, METH_NOARGS,
431                         "() - Return Material's (flare size)/(halo size) factor"},
432         {"getFlareSeed", (PyCFunction)Material_getFlareSeed, METH_NOARGS,
433                         "() - Return Material's flare offset in the seed table"},
434         {"getFlareBoost", (PyCFunction)Material_getFlareBoost, METH_NOARGS,
435                         "() - Return Material's flare boost"},
436         {"getSubSize", (PyCFunction)Material_getSubSize, METH_NOARGS,
437                         "() - Return Material's dimension of subflare, dots and circles"},
438         {"getHardness", (PyCFunction)Material_getHardness, METH_NOARGS,
439                         "() - Return Material's specular hardness"},
440         {"getNFlares", (PyCFunction)Material_getNFlares, METH_NOARGS,
441                         "() - Return Material's number of flares in halo"},
442         {"getNStars", (PyCFunction)Material_getNStars, METH_NOARGS,
443                         "() - Return Material's number of points in the halo stars"},
444         {"getNLines", (PyCFunction)Material_getNLines, METH_NOARGS,
445                         "() - Return Material's number of lines in halo"},
446         {"getNRings", (PyCFunction)Material_getNRings, METH_NOARGS,
447                         "() - Return Material's number of rings in halo"},
448         {"getTextures", (PyCFunction)Material_getTextures, METH_NOARGS,
449                         "() - Return Material's texture list as a tuple"},
450         {"setName", (PyCFunction)Material_setName, METH_VARARGS,
451                         "(s) - Change Material's name"},
452         {"setIpo", (PyCFunction)Material_setIpo, METH_VARARGS,
453                         "(Blender Ipo) - Change Material's Ipo"},
454         {"clearIpo", (PyCFunction)Material_clearIpo, METH_NOARGS,
455                         "(Blender Ipo) - Unlink Ipo from this Material"},
456         {"setMode", (PyCFunction)Material_setMode, METH_VARARGS,
457                         "([s[,s]]) - Set Material's mode flag(s)"},
458         {"setRGBCol", (PyCFunction)Material_setRGBCol, METH_VARARGS,
459                         "(f,f,f or [f,f,f]) - Set Material's rgb color triplet"},
460 /*      {"setAmbCol", (PyCFunction)Material_setAmbCol, METH_VARARGS,
461                         "(f,f,f or [f,f,f]) - Set Material's ambient color"},*/
462         {"setSpecCol", (PyCFunction)Material_setSpecCol, METH_VARARGS,
463                         "(f,f,f or [f,f,f]) - Set Material's specular color"},
464         {"setMirCol", (PyCFunction)Material_setMirCol, METH_VARARGS,
465                         "(f,f,f or [f,f,f]) - Set Material's mirror color"},
466         {"setAmb", (PyCFunction)Material_setAmb, METH_VARARGS,
467                         "(f) - Set how much the Material's color is affected"
468                                                         " by \nthe global ambient colors - [0.0, 1.0]"},
469         {"setEmit", (PyCFunction)Material_setEmit, METH_VARARGS,
470                         "(f) - Set Material's emitting light intensity - [0.0, 1.0]"},
471         {"setAlpha", (PyCFunction)Material_setAlpha, METH_VARARGS,
472                         "(f) - Set Material's alpha (transparency) - [0.0, 1.0]"},
473         {"setRef", (PyCFunction)Material_setRef, METH_VARARGS,
474                         "(f) - Set Material's reflectivity - [0.0, 1.0]"},
475         {"setSpec", (PyCFunction)Material_setSpec, METH_VARARGS,
476                         "(f) - Set Material's specularity - [0.0, 2.0]"},
477         {"setSpecTransp", (PyCFunction)Material_setSpecTransp, METH_VARARGS,
478                         "(f) - Set Material's specular transparency - [0.0, 1.0]"},
479         {"setAdd", (PyCFunction)Material_setAdd, METH_VARARGS,
480                         "(f) - Set Material's glow factor - [0.0, 1.0]"},
481         {"setZOffset", (PyCFunction)Material_setZOffset, METH_VARARGS,
482                         "(f) - Set Material's artificial offset - [0.0, 10.0]"},
483         {"setHaloSize", (PyCFunction)Material_setHaloSize, METH_VARARGS,
484                         "(f) - Set Material's halo size - [0.0, 100.0]"},
485         {"setHaloSeed", (PyCFunction)Material_setHaloSeed, METH_VARARGS,
486                         "(i) - Set Material's halo seed - [0, 255]"},
487         {"setFlareSize", (PyCFunction)Material_setFlareSize, METH_VARARGS,
488                         "(f) - Set Material's factor: (flare size)/(halo size) - [0.1, 25.0]"},
489         {"setFlareSeed", (PyCFunction)Material_setFlareSeed, METH_VARARGS,
490                         "(i) - Set Material's flare seed - [0, 255]"},
491         {"setFlareBoost", (PyCFunction)Material_setFlareBoost, METH_VARARGS,
492                         "(f) - Set Material's flare boost - [0.1, 10.0]"},
493         {"setSubSize", (PyCFunction)Material_setSubSize, METH_VARARGS,
494                         "(f) - Set Material's dimension of subflare,"
495                                                         " dots and circles - [0.1, 25.0]"},
496         {"setHardness", (PyCFunction)Material_setHardness, METH_VARARGS,
497                         "(i) - Set Material's hardness - [1, 255 (127 if halo mode is ON)]"},
498         {"setNFlares", (PyCFunction)Material_setNFlares, METH_VARARGS,
499                         "(i) - Set Material's number of flares in halo - [1, 32]"},
500         {"setNStars", (PyCFunction)Material_setNStars, METH_VARARGS,
501                         "(i) - Set Material's number of stars in halo - [3, 50]"},
502         {"setNLines", (PyCFunction)Material_setNLines, METH_VARARGS,
503                         "(i) - Set Material's number of lines in halo - [0, 250]"},
504         {"setNRings", (PyCFunction)Material_setNRings, METH_VARARGS,
505                         "(i) - Set Material's number of rings in halo - [0, 24]"},
506         {"setTexture", (PyCFunction)Material_setTexture, METH_VARARGS,
507                          "(n,tex,texco=0,mapto=0) - Set numbered texture to tex"},
508         {"clearTexture", (PyCFunction)Material_clearTexture, METH_VARARGS,
509                         "(n) - Remove texture from numbered slot"},
510         {"getScriptLinks", (PyCFunction)Material_getScriptLinks, METH_VARARGS,
511                         "(eventname) - Get a list of this material's scriptlinks (Text names) "
512                         "of the given type\n"
513         "(eventname) - string: FrameChanged or Redraw."},
514         {"addScriptLink", (PyCFunction)Material_addScriptLink, METH_VARARGS,
515                         "(text, evt) - Add a new material scriptlink.\n"
516         "(text) - string: an existing Blender Text name;\n"
517         "(evt) string: FrameChanged or Redraw."},
518         {"clearScriptLinks", (PyCFunction)Material_clearScriptLinks, METH_NOARGS,
519                         "() - Delete all scriptlinks from this material."},
520         {NULL, NULL, 0, NULL}
521 };
522
523 /*****************************************************************************/
524 /* Python Material_Type callback function prototypes:                                                                                            */
525 /*****************************************************************************/
526 static void Material_dealloc (BPy_Material *self);
527 static int Material_setAttr (BPy_Material *self, char *name, PyObject *v);
528 static PyObject *Material_getAttr (BPy_Material *self, char *name);
529 static PyObject *Material_repr (BPy_Material *self);
530
531 /*****************************************************************************/
532 /* Python Material_Type structure definition:                                                                                                                            */
533 /*****************************************************************************/
534 PyTypeObject Material_Type =
535 {
536         PyObject_HEAD_INIT(NULL)
537         0,                                                                                                                                                      /* ob_size */
538         "Blender Material",                                                                                     /* tp_name */
539         sizeof (BPy_Material),                                                                  /* tp_basicsize */
540         0,                                                                                                                                                      /* tp_itemsize */
541         /* methods */
542         (destructor)Material_dealloc,                                           /* tp_dealloc */
543         0,                                                                                                                                                      /* tp_print */
544         (getattrfunc)Material_getAttr,                                  /* tp_getattr */
545         (setattrfunc)Material_setAttr,                                  /* tp_setattr */
546         0,                                                                                                                                                      /* tp_compare */
547         (reprfunc)Material_repr,                                                                /* tp_repr */
548         0,                                                                                                                                                      /* tp_as_number */
549         0,                                                                                                                                                      /* tp_as_sequence */
550         0,                                                                                                                                                      /* tp_as_mapping */
551         0,                                                                                                                                                      /* tp_as_hash */
552         0,0,0,0,0,0,
553         0,                                                                                                                                                      /* tp_doc */ 
554         0,0,0,0,0,0,
555         BPy_Material_methods,                                                                                   /* tp_methods */
556         0,                                                                                                                                                      /* tp_members */
557 };
558
559 /*****************************************************************************/
560 /* Function:            Material_dealloc                                                                                                                                                                                 */
561 /* Description: This is a callback function for the BPy_Material type. It is */
562 /*                                                      the destructor function.                                                                                                                                                 */
563 /*****************************************************************************/
564 static void Material_dealloc (BPy_Material *self)
565 {
566         Py_DECREF (self->col);
567         Py_DECREF (self->amb);
568         Py_DECREF (self->spec);
569         Py_DECREF (self->mir);
570         PyObject_DEL (self);
571 }
572
573 /*****************************************************************************/
574 /* Function:            Material_CreatePyObject                                                                                                                                                  */
575 /* Description: This function will create a new BPy_Material from an existing*/
576 /*                                                      Blender material structure.                                                                                                                                      */
577 /*****************************************************************************/
578 PyObject *Material_CreatePyObject (struct Material *mat)
579 {
580         BPy_Material *pymat;
581         float *col[3], *amb[3], *spec[3], *mir[3];
582
583         pymat = (BPy_Material *)PyObject_NEW (BPy_Material, &Material_Type);
584
585         if (!pymat)
586                 return EXPP_ReturnPyObjError (PyExc_MemoryError,
587                                                 "couldn't create BPy_Material object");
588
589         pymat->material = mat;
590
591         col[0] = &mat->r;
592         col[1] = &mat->g;
593         col[2] = &mat->b;
594
595         amb[0] = &mat->ambr;
596         amb[1] = &mat->ambg;
597         amb[2] = &mat->ambb;
598
599         spec[0] = &mat->specr;
600         spec[1] = &mat->specg;
601         spec[2] = &mat->specb;
602
603         mir[0] = &mat->mirr;
604         mir[1] = &mat->mirg;
605         mir[2] = &mat->mirb;
606
607         pymat->col      = (BPy_rgbTuple *)rgbTuple_New(col);
608         pymat->amb      = (BPy_rgbTuple *)rgbTuple_New(amb);
609         pymat->spec = (BPy_rgbTuple *)rgbTuple_New(spec);
610         pymat->mir      = (BPy_rgbTuple *)rgbTuple_New(mir);
611
612         return (PyObject *)pymat;
613 }
614
615 /*****************************************************************************/
616 /* Function:            Material_CheckPyObject                                                                                                                                                   */
617 /* Description: This function returns true when the given PyObject is of the */
618 /*                                                      type Material. Otherwise it will return false.                                                   */
619 /*****************************************************************************/
620 int Material_CheckPyObject (PyObject *pyobj)
621 {
622         return (pyobj->ob_type == &Material_Type);
623 }
624
625 /*****************************************************************************/
626 /* Function:            Material_FromPyObject                                                                                                                                                            */
627 /* Description: This function returns the Blender material from the given                */
628 /*                                                      PyObject.                                                                                                                                                                                                                */
629 /*****************************************************************************/
630 Material *Material_FromPyObject (PyObject *pyobj)
631 {
632         return ((BPy_Material *)pyobj)->material;
633 }
634
635 /*****************************************************************************/
636 /* Description: Returns the object with the name specified by the argument       */
637 /*                                                      name. Note that the calling function has to remove the first */
638 /*                                                      two characters of the object name. These two characters                  */
639 /*                                                      specify the type of the object (OB, ME, WO, ...)                                                 */
640 /*                                                      The function will return NULL when no object with the given  */
641 /*                                                      name is found.                                                                                                                                                                                   */
642 /*****************************************************************************/
643 Material * GetMaterialByName (char * name)
644 {
645         Material        * mat_iter;
646
647         mat_iter = G.main->mat.first;
648         while (mat_iter)
649         {
650                 if (StringEqual (name, GetIdName (&(mat_iter->id))))
651                 {
652                         return (mat_iter);
653                 }
654                 mat_iter = mat_iter->id.next;
655         }
656
657         /* There is no material with the given name */
658         return (NULL);
659 }
660
661 /*****************************************************************************/
662 /* Python BPy_Material methods:                                                                                                                                                                                          */
663 /*****************************************************************************/
664
665 static PyObject *Material_getIpo(BPy_Material *self)
666 {
667         Ipo *ipo = self->material->ipo;
668
669         if (!ipo) {
670                 Py_INCREF(Py_None);
671                 return Py_None;
672         }
673         
674         return Ipo_CreatePyObject (ipo);
675 }
676
677 static PyObject *Material_getName(BPy_Material *self)
678 {
679         PyObject *attr = PyString_FromString(self->material->id.name+2);
680
681         if (attr) return attr;
682
683         return (EXPP_ReturnPyObjError (PyExc_RuntimeError,
684                                                                                                                                          "couldn't get Material.name attribute"));
685 }
686
687 static PyObject *Material_getMode(BPy_Material *self)
688 {
689         PyObject *attr = PyInt_FromLong((long)self->material->mode);
690
691         if (attr) return attr;
692
693         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
694                                                                                                                                          "couldn't get Material.Mode attribute");
695 }
696
697 static PyObject *Material_getRGBCol(BPy_Material *self)
698 {
699         return rgbTuple_getCol(self->col);
700 }
701 /*
702 static PyObject *Material_getAmbCol(BPy_Material *self)
703 {
704         return rgbTuple_getCol(self->amb);
705 }
706 */
707 static PyObject *Material_getSpecCol(BPy_Material *self)
708 {
709         return rgbTuple_getCol(self->spec);
710 }
711
712 static PyObject *Material_getMirCol(BPy_Material *self)
713 {
714         return rgbTuple_getCol(self->mir);
715 }
716
717 static PyObject *Material_getAmb(BPy_Material *self)
718 {
719         PyObject *attr = PyFloat_FromDouble((double)self->material->amb);
720
721         if (attr) return attr;
722
723         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
724                                                                                                                                          "couldn't get Material.amb attribute");
725 }
726
727 static PyObject *Material_getEmit(BPy_Material *self)
728 {
729         PyObject *attr = PyFloat_FromDouble((double)self->material->emit);
730
731         if (attr) return attr;
732
733         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
734                                                                                                                                          "couldn't get Material.emit attribute");
735 }
736
737 static PyObject *Material_getAlpha(BPy_Material *self)
738 {
739         PyObject *attr = PyFloat_FromDouble((double)self->material->alpha);
740
741         if (attr) return attr;
742
743         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
744                                                                                                                                          "couldn't get Material.alpha attribute");
745 }
746
747 static PyObject *Material_getRef(BPy_Material *self)
748 {
749         PyObject *attr = PyFloat_FromDouble((double)self->material->ref);
750
751         if (attr) return attr;
752
753         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
754                                                                                                                                          "couldn't get Material.ref attribute");
755 }
756
757 static PyObject *Material_getSpec(BPy_Material *self)
758 {
759         PyObject *attr = PyFloat_FromDouble((double)self->material->spec);
760
761         if (attr) return attr;
762
763         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
764                                                                                                                                          "couldn't get Material.spec attribute");
765 }
766
767 static PyObject *Material_getSpecTransp(BPy_Material *self)
768 {
769         PyObject *attr = PyFloat_FromDouble((double)self->material->spectra);
770
771         if (attr) return attr;
772
773         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
774                                                         "couldn't get Material.specTransp attribute");
775 }
776
777 static PyObject *Material_getAdd(BPy_Material *self)
778 {
779         PyObject *attr = PyFloat_FromDouble((double)self->material->add);
780
781         if (attr) return attr;
782
783         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
784                                                                                                                                          "couldn't get Material.add attribute");
785 }
786
787 static PyObject *Material_getZOffset(BPy_Material *self)
788 {
789         PyObject *attr = PyFloat_FromDouble((double)self->material->zoffs);
790
791         if (attr) return attr;
792
793         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
794                                                                                                 "couldn't get Material.zOffset attribute");
795 }
796
797 static PyObject *Material_getHaloSize(BPy_Material *self)
798 {
799         PyObject *attr = PyFloat_FromDouble((double)self->material->hasize);
800
801         if (attr) return attr;
802
803         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
804                                                                          "couldn't get Material.haloSize attribute");
805 }
806
807 static PyObject *Material_getFlareSize(BPy_Material *self)
808 {
809         PyObject *attr = PyFloat_FromDouble((double)self->material->flaresize);
810
811         if (attr) return attr;
812
813         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
814                                                                                  "couldn't get Material.flareSize attribute");
815 }
816
817 static PyObject *Material_getFlareBoost(BPy_Material *self)
818 {
819         PyObject *attr = PyFloat_FromDouble((double)self->material->flareboost);
820
821         if (attr) return attr;
822
823         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
824                                                                                  "couldn't get Material.flareBoost attribute");
825 }
826
827 static PyObject *Material_getSubSize(BPy_Material *self)
828 {
829         PyObject *attr = PyFloat_FromDouble((double)self->material->subsize);
830
831         if (attr) return attr;
832
833         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
834                                                          "couldn't get Material.subSize attribute");
835 }
836
837 static PyObject *Material_getHaloSeed(BPy_Material *self)
838 {
839         PyObject *attr = PyInt_FromLong((long)self->material->seed1);
840
841         if (attr) return attr;
842
843         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
844                                                                                          "couldn't get Material.haloSeed attribute");
845 }
846
847 static PyObject *Material_getFlareSeed(BPy_Material *self)
848 {
849         PyObject *attr = PyInt_FromLong((long)self->material->seed2);
850
851         if (attr) return attr;
852
853         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
854                                                                                          "couldn't get Material.flareSeed attribute");
855 }
856
857 static PyObject *Material_getHardness(BPy_Material *self)
858 {
859         PyObject *attr = PyInt_FromLong((long)self->material->har);
860
861         if (attr) return attr;
862
863         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
864                                                                                          "couldn't get Material.hard attribute");
865 }
866
867 static PyObject *Material_getNFlares(BPy_Material *self)
868 {
869         PyObject *attr = PyInt_FromLong((long)self->material->flarec);
870
871         if (attr) return attr;
872
873         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
874                                                                                          "couldn't get Material.nFlares attribute");
875 }
876
877 static PyObject *Material_getNStars(BPy_Material *self)
878 {
879         PyObject *attr = PyInt_FromLong((long)self->material->starc);
880
881         if (attr) return attr;
882
883         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
884                                                                                          "couldn't get Material.nStars attribute");
885 }
886
887 static PyObject *Material_getNLines(BPy_Material *self)
888 {
889         PyObject *attr = PyInt_FromLong((long)self->material->linec);
890
891         if (attr) return attr;
892
893         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
894                                                                                          "couldn't get Material.nLines attribute");
895 }
896
897 static PyObject *Material_getNRings(BPy_Material *self)
898 {
899         PyObject *attr = PyInt_FromLong((long)self->material->ringc);
900
901         if (attr) return attr;
902
903         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
904                                                                                          "couldn't get Material.nRings attribute");
905 }
906
907 static PyObject *Material_getTextures(BPy_Material *self)
908 {
909         int i;
910         struct MTex *mtex;
911         PyObject *t[8];
912         PyObject *tuple;
913         
914         /* build a texture list */
915         for (i=0; i<8; ++i) {
916                 mtex = self->material->mtex[i];
917                 
918                 if (mtex) {
919                         t[i] = MTex_CreatePyObject (mtex);
920                 }
921                 else {
922                         Py_INCREF (Py_None);
923                         t[i] = Py_None;
924                 }
925         }
926
927         /* turn the array into a tuple */
928         tuple = Py_BuildValue ("NNNNNNNN", t[0], t[1], t[2], t[3], 
929                                                                                                                                                  t[4], t[5], t[6], t[7]);
930         if (!tuple) 
931                 return EXPP_ReturnPyObjError(PyExc_MemoryError,
932                                                                                                  "Material_getTextures: couldn't create PyTuple");
933
934         return tuple;
935 }
936
937 static PyObject *Material_setIpo(BPy_Material *self, PyObject *args)
938 {
939         PyObject *pyipo = 0;
940         Ipo *ipo = NULL;
941         Ipo *oldipo;
942
943         if (!PyArg_ParseTuple(args, "O!", &Ipo_Type, &pyipo))
944                 return EXPP_ReturnPyObjError (PyExc_TypeError, "expected Ipo as argument");
945
946         ipo = Ipo_FromPyObject(pyipo);
947
948         if (!ipo) return EXPP_ReturnPyObjError (PyExc_RuntimeError, "null ipo!");
949
950         if (ipo->blocktype != ID_MA)
951                 return EXPP_ReturnPyObjError (PyExc_TypeError,
952                         "this ipo is not a Material type ipo");
953
954         oldipo = self->material->ipo;
955         if (oldipo) {
956                 ID *id = &oldipo->id;
957                 if (id->us > 0) id->us--;
958         }
959
960         ((ID *)&ipo->id)->us++;
961
962         self->material->ipo = ipo;
963
964         Py_INCREF(Py_None);
965         return Py_None;
966 }
967
968 static PyObject *Material_clearIpo(BPy_Material *self)
969 {
970         Material *mat = self->material;
971         Ipo *ipo = (Ipo *)mat->ipo;
972
973         if (ipo) {
974                 ID *id = &ipo->id;
975                 if (id->us > 0) id->us--;
976                 mat->ipo = NULL;
977
978                 Py_INCREF (Py_True);
979                 return Py_True;
980         }
981
982         Py_INCREF (Py_False); /* no ipo found */
983         return Py_False;
984 }
985
986 static PyObject *Material_setName(BPy_Material *self, PyObject *args)
987 {
988         char *name;
989         char buf[21];
990
991         if (!PyArg_ParseTuple(args, "s", &name))
992                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
993                                                                                                                                                  "expected string argument"));
994
995         PyOS_snprintf(buf, sizeof(buf), "%s", name);
996
997         rename_id(&self->material->id, buf);
998
999         Py_INCREF(Py_None);
1000         return Py_None;
1001 }
1002
1003 /* Possible modes are traceable, shadow, shadeless, wire, vcolLight,
1004  * vcolPaint, halo, ztransp, zinvert, haloRings, env, haloLines,
1005  * onlyShadow, xalpha, star, faceTexture, haloTex, haloPuno, noMist,
1006  * haloShaded, haloFlare */
1007 static PyObject *Material_setMode(BPy_Material *self, PyObject *args)
1008 {
1009         int i, flag = 0;
1010         char *m[22] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1011                                                                  NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1012                                                                  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
1013
1014         if (!PyArg_ParseTuple(args, "|ssssssssssssssssssssss",
1015                                         &m[0], &m[1], &m[2], &m[3],  &m[4],  &m[5],  &m[6],
1016                                         &m[7], &m[8], &m[9], &m[10], &m[11], &m[12], &m[13],
1017                                         &m[14], &m[15], &m[16], &m[17], &m[18], &m[19], &m[20], &m[21]))
1018         {
1019                 return (EXPP_ReturnPyObjError (PyExc_AttributeError,
1020                                                 "expected from none to 22 string argument(s)"));
1021         }
1022
1023         for (i = 0; i < 22; i++) {
1024                 if (m[i] == NULL) break;
1025                 if (strcmp(m[i], "Traceable") == 0)
1026                         flag |= EXPP_MAT_MODE_TRACEABLE;
1027                 else if (strcmp(m[i], "Shadow") == 0)
1028                         flag |= EXPP_MAT_MODE_SHADOW;
1029                 else if (strcmp(m[i], "Shadeless") == 0)
1030                         flag |= EXPP_MAT_MODE_SHADELESS;
1031                 else if (strcmp(m[i], "Wire") == 0)
1032                         flag |= EXPP_MAT_MODE_WIRE;
1033                 else if (strcmp(m[i], "VColLight") == 0)
1034                         flag |= EXPP_MAT_MODE_VCOL_LIGHT;
1035                 else if (strcmp(m[i], "VColPaint") == 0)
1036                         flag |= EXPP_MAT_MODE_VCOL_PAINT;
1037                 else if (strcmp(m[i], "Halo") == 0)
1038                         flag |= EXPP_MAT_MODE_HALO;
1039                 else if (strcmp(m[i], "ZTransp") == 0)
1040                         flag |= EXPP_MAT_MODE_ZTRANSP;
1041                 else if (strcmp(m[i], "ZInvert") == 0)
1042                         flag |= EXPP_MAT_MODE_ZINVERT;
1043                 else if (strcmp(m[i], "HaloRings") == 0)
1044                         flag |= EXPP_MAT_MODE_HALORINGS;
1045                 else if (strcmp(m[i], "Env") == 0)
1046                         flag |= EXPP_MAT_MODE_ENV;
1047                 else if (strcmp(m[i], "HaloLines") == 0)
1048                         flag |= EXPP_MAT_MODE_HALOLINES;
1049                 else if (strcmp(m[i], "OnlyShadow") == 0)
1050                         flag |= EXPP_MAT_MODE_ONLYSHADOW;
1051                 else if (strcmp(m[i], "HaloXAlpha") == 0)
1052                         flag |= EXPP_MAT_MODE_HALOXALPHA;
1053                 else if (strcmp(m[i], "HaloStar") == 0)
1054                         flag |= EXPP_MAT_MODE_HALOSTAR;
1055                 else if (strcmp(m[i], "TexFace") == 0)
1056                         flag |= EXPP_MAT_MODE_TEXFACE;
1057                 else if (strcmp(m[i], "HaloTex") == 0)
1058                         flag |= EXPP_MAT_MODE_HALOTEX;
1059                 else if (strcmp(m[i], "HaloPuno") == 0)
1060                         flag |= EXPP_MAT_MODE_HALOPUNO;
1061                 else if (strcmp(m[i], "NoMist") == 0)
1062                         flag |= EXPP_MAT_MODE_NOMIST;
1063                 else if (strcmp(m[i], "HaloShaded") == 0)
1064                         flag |= EXPP_MAT_MODE_HALOSHADE;
1065                 else if (strcmp(m[i], "HaloFlare") == 0)
1066                         flag |= EXPP_MAT_MODE_HALOFLARE;
1067                 else if (strcmp(m[i], "Radio") == 0)
1068                         flag |= EXPP_MAT_MODE_RADIO;
1069                 else
1070                         return (EXPP_ReturnPyObjError (PyExc_AttributeError,
1071                                                         "unknown Material mode argument"));
1072         }
1073
1074         self->material->mode = flag;
1075
1076         Py_INCREF(Py_None);
1077         return Py_None;
1078 }
1079
1080 /* Another helper function, for the same reason.
1081  * (See comment before Material_setIntType above). */
1082 static PyObject *Material_setIntMode(BPy_Material *self, PyObject *args)
1083 {
1084         int value;
1085
1086         if (!PyArg_ParseTuple(args, "i", &value))
1087                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1088                                                                                                                                                  "expected int argument"));
1089
1090         self->material->mode = value;
1091
1092         Py_INCREF(Py_None);
1093         return Py_None;
1094 }
1095
1096 static PyObject *Material_setRGBCol (BPy_Material *self, PyObject *args)
1097 {
1098         return rgbTuple_setCol(self->col, args);
1099 }
1100 /*
1101 static PyObject *Material_setAmbCol (BPy_Material *self, PyObject *args)
1102 {
1103         return rgbTuple_setCol(self->amb, args);
1104 }
1105 */
1106 static PyObject *Material_setSpecCol (BPy_Material *self, PyObject *args)
1107 {
1108         return rgbTuple_setCol(self->spec, args);
1109 }
1110
1111 static PyObject *Material_setMirCol (BPy_Material *self, PyObject *args)
1112 {
1113         return rgbTuple_setCol(self->mir, args);
1114 }
1115
1116 static PyObject *Material_setColorComponent(BPy_Material *self, char *key,
1117                                                                 PyObject *args)
1118 { /* for compatibility with old bpython */
1119         float value;
1120
1121         if (!PyArg_ParseTuple(args, "f", &value))
1122                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1123                                                 "expected float argument in [0.0, 1.0]"));
1124
1125         value = EXPP_ClampFloat (value, EXPP_MAT_COL_MIN,
1126                                                                         EXPP_MAT_COL_MAX);
1127
1128         if (!strcmp(key, "R"))
1129                 self->material->r = value;
1130         else if (!strcmp(key, "G"))
1131                 self->material->g = value;
1132         else if (!strcmp(key, "B"))
1133                 self->material->b = value;
1134         else if (!strcmp(key, "specR"))
1135                 self->material->specr = value;
1136         else if (!strcmp(key, "specG"))
1137                 self->material->specg = value;
1138         else if (!strcmp(key, "specB"))
1139                 self->material->specb = value;
1140
1141         return EXPP_incr_ret (Py_None);
1142 }
1143
1144 static PyObject *Material_setAmb(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->amb = EXPP_ClampFloat (value, EXPP_MAT_AMB_MIN,
1153                                                                         EXPP_MAT_AMB_MAX);
1154
1155         return EXPP_incr_ret (Py_None);
1156 }
1157
1158 static PyObject *Material_setEmit(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->emit = EXPP_ClampFloat (value, EXPP_MAT_EMIT_MIN,
1167                                                                         EXPP_MAT_EMIT_MAX);
1168
1169         return EXPP_incr_ret (Py_None);
1170 }
1171
1172 static PyObject *Material_setSpecTransp(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->spectra = EXPP_ClampFloat (value, EXPP_MAT_SPECTRA_MIN,
1181                                                                         EXPP_MAT_SPECTRA_MAX);
1182
1183         return EXPP_incr_ret (Py_None);
1184 }
1185
1186 static PyObject *Material_setAlpha(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->alpha = EXPP_ClampFloat (value, EXPP_MAT_ALPHA_MIN,
1195                                                                         EXPP_MAT_ALPHA_MAX);
1196
1197         return EXPP_incr_ret (Py_None);
1198 }
1199
1200 static PyObject *Material_setRef(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->ref = EXPP_ClampFloat (value, EXPP_MAT_REF_MIN,
1209                                                                         EXPP_MAT_REF_MAX);
1210
1211         return EXPP_incr_ret (Py_None);
1212 }
1213
1214 static PyObject *Material_setSpec(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, 1.0]"));
1221
1222         self->material->spec = EXPP_ClampFloat (value, EXPP_MAT_SPEC_MIN,
1223                                                                         EXPP_MAT_SPEC_MAX);
1224
1225         return EXPP_incr_ret (Py_None);
1226 }
1227
1228 static PyObject *Material_setZOffset(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, 10.0]"));
1235
1236         self->material->zoffs = EXPP_ClampFloat (value, EXPP_MAT_ZOFFS_MIN,
1237                                                                         EXPP_MAT_ZOFFS_MAX);
1238
1239         return EXPP_incr_ret (Py_None);
1240 }
1241
1242 static PyObject *Material_setAdd(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, 1.0]"));
1249
1250         self->material->add = EXPP_ClampFloat (value, EXPP_MAT_ADD_MIN,
1251                                                                         EXPP_MAT_ADD_MAX);
1252
1253         return EXPP_incr_ret (Py_None);
1254 }
1255
1256 static PyObject *Material_setHaloSize(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.0, 100.0]"));
1263
1264         self->material->hasize = EXPP_ClampFloat (value, EXPP_MAT_HALOSIZE_MIN,
1265                                                                         EXPP_MAT_HALOSIZE_MAX);
1266
1267         return EXPP_incr_ret (Py_None);
1268 }
1269
1270 static PyObject *Material_setFlareSize(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, 25.0]"));
1277
1278         self->material->flaresize = EXPP_ClampFloat (value, EXPP_MAT_FLARESIZE_MIN,
1279                                                                         EXPP_MAT_FLARESIZE_MAX);
1280
1281         return EXPP_incr_ret (Py_None);
1282 }
1283
1284 static PyObject *Material_setFlareBoost(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, 10.0]"));
1291
1292         self->material->flareboost = EXPP_ClampFloat(value, EXPP_MAT_FLAREBOOST_MIN,
1293                                                                         EXPP_MAT_FLAREBOOST_MAX);
1294
1295         return EXPP_incr_ret (Py_None);
1296 }
1297
1298 static PyObject *Material_setSubSize(BPy_Material *self, PyObject *args)
1299 {
1300          float value;
1301
1302         if (!PyArg_ParseTuple(args, "f", &value))
1303                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1304                                                 "expected float argument in [0.1, 25.0]"));
1305
1306         self->material->subsize = EXPP_ClampFloat (value, EXPP_MAT_SUBSIZE_MIN,
1307                                                                         EXPP_MAT_SUBSIZE_MAX);
1308
1309         return EXPP_incr_ret (Py_None);
1310 }
1311
1312 static PyObject *Material_setHaloSeed(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->seed1 = EXPP_ClampInt (value, EXPP_MAT_HALOSEED_MIN,
1321                                                                         EXPP_MAT_HALOSEED_MAX);
1322
1323         return EXPP_incr_ret (Py_None);
1324 }
1325
1326 static PyObject *Material_setFlareSeed(BPy_Material *self, PyObject *args)
1327 {
1328         short value;
1329
1330         if (!PyArg_ParseTuple(args, "h", &value))                        
1331                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1332                                                 "expected int argument in [1, 255]"));
1333
1334         self->material->seed2 = EXPP_ClampInt (value, EXPP_MAT_FLARESEED_MIN,
1335                                                                         EXPP_MAT_FLARESEED_MAX);
1336
1337         return EXPP_incr_ret (Py_None);
1338 }
1339
1340
1341 static PyObject *Material_setHardness(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, 255]"));
1348
1349         self->material->har = EXPP_ClampInt (value, EXPP_MAT_HARD_MIN,
1350                                                                         EXPP_MAT_HARD_MAX);
1351
1352         return EXPP_incr_ret (Py_None);
1353 }
1354
1355 static PyObject *Material_setNFlares(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 [1, 32]"));
1362
1363         self->material->flarec = EXPP_ClampInt (value, EXPP_MAT_NFLARES_MIN,
1364                                                                         EXPP_MAT_NFLARES_MAX);
1365
1366         return EXPP_incr_ret (Py_None);
1367 }
1368
1369 static PyObject *Material_setNStars(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 [3, 50]"));
1376
1377         self->material->starc = EXPP_ClampInt (value, EXPP_MAT_NSTARS_MIN,
1378                                                                         EXPP_MAT_NSTARS_MAX);
1379
1380         return EXPP_incr_ret (Py_None);
1381 }
1382
1383 static PyObject *Material_setNLines(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, 250]"));
1390
1391         self->material->linec = EXPP_ClampInt (value, EXPP_MAT_NLINES_MIN,
1392                                                                         EXPP_MAT_NLINES_MAX);
1393
1394         return EXPP_incr_ret (Py_None);
1395 }
1396
1397 static PyObject *Material_setNRings(BPy_Material *self, PyObject *args)
1398 {
1399         short value;
1400
1401         if (!PyArg_ParseTuple(args, "h", &value))                        
1402                 return (EXPP_ReturnPyObjError (PyExc_TypeError,
1403                                                 "expected int argument in [0, 24]"));
1404
1405         self->material->ringc = EXPP_ClampInt (value, EXPP_MAT_NRINGS_MIN,
1406                                                                         EXPP_MAT_NRINGS_MAX);
1407
1408         return EXPP_incr_ret (Py_None);
1409 }
1410
1411 static PyObject *Material_setTexture(BPy_Material *self, PyObject *args)
1412 {
1413         int texnum;
1414         PyObject *pytex;
1415         Tex *bltex;
1416         int texco=TEXCO_ORCO, mapto=MAP_COL;
1417
1418         if (!PyArg_ParseTuple(args, "iO!|ii", &texnum, &Texture_Type, &pytex,
1419                                                                                                                                                                 &texco, &mapto))
1420                 return EXPP_ReturnPyObjError (PyExc_TypeError,
1421                                                                                 "expected int in [0,7] and Texture");
1422         if ((texnum<0) || (texnum>=8))
1423                 return EXPP_ReturnPyObjError (PyExc_TypeError,
1424                                                                                 "expected int in [0,7] and Texture");
1425         
1426         bltex = Texture_FromPyObject (pytex);
1427         
1428         if (!self->material->mtex[texnum]) {
1429                 /* there isn't an mtex for this slot so we need to make one */
1430                 self->material->mtex[texnum] = add_mtex ();
1431         }
1432         else {
1433                 /* we already had a texture here so deal with the old one first */
1434                 self->material->mtex[texnum]->tex->id.us--;
1435         }
1436         
1437         self->material->mtex[texnum]->tex = bltex;
1438         id_us_plus (&bltex->id);
1439         self->material->mtex[texnum]->texco = texco;
1440         self->material->mtex[texnum]->mapto = mapto;
1441
1442         Py_INCREF(Py_None);
1443         return Py_None;
1444 }
1445
1446 static PyObject *Material_clearTexture(BPy_Material *self, PyObject *args)
1447 {
1448         int texnum;
1449         struct MTex *mtex;
1450
1451         if (!PyArg_ParseTuple(args, "i", &texnum))
1452                 return EXPP_ReturnPyObjError (PyExc_TypeError,
1453                                                                                 "expected int in [0,7]");
1454         if ((texnum<0) || (texnum>=8))
1455                 return EXPP_ReturnPyObjError (PyExc_TypeError,
1456                                                                                 "expected int in [0,7]");
1457         
1458         mtex = self->material->mtex[texnum];
1459         if (mtex) {
1460                 if (mtex->tex)
1461                         mtex->tex->id.us--;
1462                 MEM_freeN (mtex);                
1463                 self->material->mtex[texnum] = NULL;
1464         }
1465         
1466         Py_INCREF(Py_None);
1467         return Py_None;
1468 }
1469
1470 /* mat.addScriptLink */
1471 static PyObject *Material_addScriptLink (BPy_Material *self, PyObject *args)
1472 {
1473         Material *mat = self->material;
1474         ScriptLink *slink = NULL;
1475
1476         slink = &(mat)->scriptlink;
1477
1478         if (!EXPP_addScriptLink(slink, args, 0))
1479                 return EXPP_incr_ret (Py_None);
1480         else return NULL;
1481 }
1482
1483 /* mat.clearScriptLinks */
1484 static PyObject *Material_clearScriptLinks (BPy_Material *self)
1485 {
1486         Material *mat = self->material;
1487         ScriptLink *slink = NULL;
1488
1489         slink = &(mat)->scriptlink;
1490
1491         return EXPP_incr_ret(Py_BuildValue("i", EXPP_clearScriptLinks (slink)));
1492 }
1493
1494 /* mat.getScriptLinks */
1495 static PyObject *Material_getScriptLinks (BPy_Material *self, PyObject *args)
1496 {
1497         Material *mat = self->material;
1498         ScriptLink *slink = NULL;
1499         PyObject *ret = NULL;
1500
1501         slink = &(mat)->scriptlink;
1502
1503         ret = EXPP_getScriptLinks(slink, args, 0);
1504
1505         if (ret) return ret;
1506         else return NULL;
1507 }
1508
1509 /*****************************************************************************/
1510 /* Function:            Material_getAttr                                                                                                                                                                                 */
1511 /* Description: This is a callback function for the BPy_Material type. It is */
1512 /*                                                      the function that accesses BPy_Material "member variables"       */
1513 /*                                                      and methods.                                                                                                                                                                                             */
1514 /*****************************************************************************/
1515 static PyObject *Material_getAttr (BPy_Material *self, char *name)
1516 {
1517         PyObject *attr = Py_None;
1518
1519         if (strcmp(name, "name") == 0)
1520                 attr = PyString_FromString(self->material->id.name+2);
1521         else if (strcmp(name, "mode") == 0)
1522                 attr = PyInt_FromLong(self->material->mode);
1523         else if (strcmp(name, "rgbCol") == 0)
1524                 attr = Material_getRGBCol(self);
1525 /*      else if (strcmp(name, "ambCol") == 0)
1526                 attr = Material_getAmbCol(self);*/
1527         else if (strcmp(name, "specCol") == 0)
1528                 attr = Material_getSpecCol(self);
1529         else if (strcmp(name, "mirCol") == 0)
1530                 attr = Material_getMirCol(self);
1531         else if (strcmp(name, "R") == 0)
1532                 attr = PyFloat_FromDouble((double)self->material->r);
1533         else if (strcmp(name, "G") == 0)
1534                 attr = PyFloat_FromDouble((double)self->material->g);
1535         else if (strcmp(name, "B") == 0)
1536                 attr = PyFloat_FromDouble((double)self->material->b);
1537         else if (strcmp(name, "specR") == 0)
1538                 attr = PyFloat_FromDouble((double)self->material->specr);
1539         else if (strcmp(name, "specG") == 0)
1540                 attr = PyFloat_FromDouble((double)self->material->specg);
1541         else if (strcmp(name, "specB") == 0)
1542                 attr = PyFloat_FromDouble((double)self->material->specb);
1543         else if (strcmp(name, "amb") == 0)
1544                 attr = PyFloat_FromDouble((double)self->material->amb);
1545         else if (strcmp(name, "emit") == 0)
1546                 attr = PyFloat_FromDouble((double)self->material->emit);
1547         else if (strcmp(name, "alpha") == 0)
1548                 attr = PyFloat_FromDouble((double)self->material->alpha);
1549         else if (strcmp(name, "ref") == 0)
1550                 attr = PyFloat_FromDouble((double)self->material->ref);
1551         else if (strcmp(name, "spec") == 0)
1552                 attr = PyFloat_FromDouble((double)self->material->spec);
1553         else if (strcmp(name, "specTransp") == 0)
1554                 attr = PyFloat_FromDouble((double)self->material->spectra);
1555         else if (strcmp(name, "add") == 0)
1556                 attr = PyFloat_FromDouble((double)self->material->add);
1557         else if (strcmp(name, "zOffset") == 0)
1558                 attr = PyFloat_FromDouble((double)self->material->zoffs);
1559         else if (strcmp(name, "haloSize") == 0)
1560                 attr = PyFloat_FromDouble((double)self->material->hasize);
1561         else if (strcmp(name, "haloSeed") == 0)
1562                 attr = PyInt_FromLong((double)self->material->seed1);
1563         else if (strcmp(name, "flareSize") == 0)
1564                 attr = PyFloat_FromDouble((double)self->material->flaresize);
1565         else if (strcmp(name, "flareBoost") == 0)
1566                 attr = PyFloat_FromDouble((double)self->material->flareboost);
1567         else if (strcmp(name, "flareSeed") == 0)
1568                 attr = PyInt_FromLong((double)self->material->seed2);
1569         else if (strcmp(name, "subSize") == 0)
1570                 attr = PyFloat_FromDouble((double)self->material->subsize);
1571         else if (strcmp(name, "hard") == 0)
1572                 attr = PyInt_FromLong((long)self->material->har);
1573         else if (strcmp(name, "nFlares") == 0)
1574                 attr = PyInt_FromLong((long)self->material->flarec);
1575         else if (strcmp(name, "nStars") == 0)
1576                 attr = PyInt_FromLong((long)self->material->starc);
1577         else if (strcmp(name, "nLines") == 0)
1578                 attr = PyInt_FromLong((long)self->material->linec);
1579         else if (strcmp(name, "nRings") == 0)
1580                 attr = PyInt_FromLong((long)self->material->ringc);
1581
1582         else if (strcmp(name, "__members__") == 0) {
1583                 attr = /* 27 items */
1584                         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]",
1585                                 "name", "mode", "rgbCol", "specCol", "mirCol",
1586                                 "R", "G", "B", "alpha", "amb", "emit", "ref", "spec",
1587                                 "specTransp", "add", "zOffset", "haloSize", "haloSeed",
1588                                 "flareSize", "flareBoost", "flareSeed", "subSize", "hard",
1589                                 "nFlares", "nStars", "nLines", "nRings");
1590         }
1591
1592         if (!attr)
1593                 return (EXPP_ReturnPyObjError (PyExc_MemoryError,
1594                                                                                         "couldn't create PyObject"));
1595
1596         if (attr != Py_None) return attr; /* member attribute found, return it */
1597
1598         /* not an attribute, search the methods table */
1599         return Py_FindMethod(BPy_Material_methods, (PyObject *)self, name);
1600 }
1601
1602 /****************************************************************************/
1603 /* Function:            Material_setAttr                                                                                                                                                                                */
1604 /* Description: This is a callback function for the BPy_Material type.                  */
1605 /*                                                      It is the function that sets Material attributes (member                */
1606 /*                                                      variables).                                                                                                                                                                                                     */
1607 /****************************************************************************/
1608 static int Material_setAttr (BPy_Material *self, char *name, PyObject *value)
1609 {
1610         PyObject *valtuple; 
1611         PyObject *error = NULL;
1612
1613 /* We're playing a trick on the Python API users here.  Even if they use
1614  * Material.member = val instead of Material.setMember(val), we end up using the
1615  * function anyway, since it already has error checking, clamps to the right
1616  * interval and updates the Blender Material structure when necessary. */
1617
1618 /* First we put "value" in a tuple, because we want to pass it to functions
1619  * that only accept PyTuples. */
1620         valtuple = Py_BuildValue("(O)", value);
1621
1622         if (!valtuple) /* everything OK with our PyObject? */
1623                 return EXPP_ReturnIntError(PyExc_MemoryError,
1624                                                                                                  "MaterialSetAttr: couldn't create PyTuple");
1625
1626 /* Now we just compare "name" with all possible BPy_Material member variables */
1627         if (strcmp (name, "name") == 0)
1628                 error = Material_setName (self, valtuple);
1629         else if (strcmp (name, "mode") == 0)
1630                 error = Material_setIntMode (self, valtuple); /* special case */
1631         else if (strcmp (name, "rgbCol") == 0)
1632                 error = Material_setRGBCol (self, valtuple);
1633 /*      else if (strcmp (name, "ambCol") == 0)
1634                 error = Material_setAmbCol (self, valtuple);*/
1635         else if (strcmp (name, "specCol") == 0)
1636                 error = Material_setSpecCol (self, valtuple);
1637         else if (strcmp (name, "mirCol") == 0)
1638                 error = Material_setMirCol (self, valtuple);
1639         else if (strcmp (name, "R") == 0)
1640                 error = Material_setColorComponent (self, "R", valtuple);
1641         else if (strcmp (name, "G") == 0)
1642                 error = Material_setColorComponent (self, "G", valtuple);
1643         else if (strcmp (name, "B") == 0)
1644                 error = Material_setColorComponent (self, "B", valtuple);
1645         else if (strcmp (name, "specR") == 0)
1646                 error = Material_setColorComponent (self, "specR", valtuple);
1647         else if (strcmp (name, "specG") == 0)
1648                 error = Material_setColorComponent (self, "specG", valtuple);
1649         else if (strcmp (name, "specB") == 0)
1650                 error = Material_setColorComponent (self, "specB", valtuple);
1651         else if (strcmp (name, "amb") == 0)
1652                 error = Material_setAmb (self, valtuple);
1653         else if (strcmp (name, "emit") == 0)
1654                 error = Material_setEmit (self, valtuple);
1655         else if (strcmp (name, "alpha") == 0)
1656                 error = Material_setAlpha (self, valtuple);
1657         else if (strcmp (name, "ref") == 0)
1658                 error = Material_setRef (self, valtuple);
1659         else if (strcmp (name, "spec") == 0)
1660                 error = Material_setSpec (self, valtuple);
1661         else if (strcmp (name, "specTransp") == 0)
1662                 error = Material_setSpecTransp (self, valtuple);
1663         else if (strcmp (name, "add") == 0)
1664                 error = Material_setAdd (self, valtuple);
1665         else if (strcmp (name, "zOffset") == 0)
1666                 error = Material_setZOffset (self, valtuple);
1667         else if (strcmp (name, "haloSize") == 0)
1668                 error = Material_setHaloSize (self, valtuple);
1669         else if (strcmp (name, "haloSeed") == 0)
1670                 error = Material_setHaloSeed (self, valtuple);
1671         else if (strcmp (name, "flareSize") == 0)
1672                 error = Material_setFlareSize (self, valtuple);
1673         else if (strcmp (name, "flareBoost") == 0)
1674                 error = Material_setFlareBoost (self, valtuple);
1675         else if (strcmp (name, "flareSeed") == 0)
1676                 error = Material_setFlareSeed (self, valtuple);
1677         else if (strcmp (name, "subSize") == 0)
1678                 error = Material_setSubSize (self, valtuple);
1679         else if (strcmp (name, "hard") == 0)
1680                 error = Material_setHardness (self, valtuple);
1681         else if (strcmp (name, "nFlares") == 0)
1682                 error = Material_setNFlares (self, valtuple);
1683         else if (strcmp (name, "nStars") == 0)
1684                 error = Material_setNStars (self, valtuple);
1685         else if (strcmp (name, "nLines") == 0)
1686                 error = Material_setNLines (self, valtuple);
1687         else if (strcmp (name, "nRings") == 0)
1688                 error = Material_setNRings (self, valtuple);
1689
1690         else { /* Error */
1691                 Py_DECREF(valtuple);
1692                 return (EXPP_ReturnIntError (PyExc_AttributeError, name));
1693         }
1694
1695 /* valtuple won't be returned to the caller, so we need to DECREF it */
1696         Py_DECREF(valtuple);
1697
1698         if (error != Py_None) return -1;
1699
1700 /* Py_None was incref'ed by the called Material_set* function. We probably
1701  * don't need to decref Py_None (!), but since Python/C API manual tells us
1702  * to treat it like any other PyObject regarding ref counting ... */
1703         Py_DECREF(Py_None);
1704         return 0; /* normal exit */
1705 }
1706
1707 /*****************************************************************************/
1708 /* Function:            Material_repr                                                                                                                                                                                            */
1709 /* Description: This is a callback function for the BPy_Material type. It                */
1710 /*                                                      builds a meaninful string to represent material objects.                 */
1711 /*****************************************************************************/
1712 static PyObject *Material_repr (BPy_Material *self)
1713 {
1714         return PyString_FromFormat ("[Material \"%s\"]", self->material->id.name+2);
1715 }
1716
1717
1718 /*****************************************************************************/
1719 /* These functions are used in NMesh.c and Object.c                                                                                                      */
1720 /*****************************************************************************/
1721 PyObject *EXPP_PyList_fromMaterialList (Material **matlist, int len)
1722 {
1723         PyObject *list;
1724         int i;
1725
1726         list = PyList_New(0);
1727         if (!matlist) return list;
1728
1729         for (i = 0; i < len; i++) {
1730                 Material *mat = matlist[i];
1731                 PyObject *ob;
1732
1733                 if (mat) {
1734                         ob = Material_CreatePyObject (mat);
1735                         PyList_Append (list, ob);
1736                         Py_DECREF (ob); /* because Append increfs */
1737                 }
1738         }
1739
1740         return list;
1741 }
1742
1743 Material **EXPP_newMaterialList_fromPyList (PyObject *list)
1744 {
1745         int i, len;
1746         BPy_Material *pymat = 0;
1747         Material *mat;
1748         Material **matlist;
1749
1750         len = PySequence_Length (list);
1751         if (len > 16) len = 16;
1752
1753         matlist = EXPP_newMaterialList (len);
1754
1755         for (i= 0; i < len; i++) {
1756
1757                 pymat = (BPy_Material *)PySequence_GetItem (list, i);
1758
1759                 if (Material_CheckPyObject ((PyObject *)pymat)) {
1760                         mat = pymat->material;
1761                         matlist[i] = mat;
1762                 }
1763
1764                 else { /* error; illegal type in material list */
1765                         Py_DECREF(pymat);
1766                         MEM_freeN(matlist);
1767                         return NULL;
1768                 }
1769
1770                 Py_DECREF(pymat);
1771         }
1772
1773         return matlist;
1774 }
1775
1776 Material **EXPP_newMaterialList(int len)
1777 {
1778         Material **matlist =
1779                 (Material **)MEM_mallocN(len * sizeof(Material *), "MaterialList");
1780
1781         return matlist;
1782 }
1783
1784 int EXPP_releaseMaterialList (Material **matlist, int len)
1785 {
1786                 int                                             i;
1787                 Material                * mat;
1788
1789                 if ((len < 0) || (len > MAXMAT)) {
1790                                 printf ("illegal matindex!\n");
1791                                 return 0;
1792                 }
1793
1794                 for (i=0 ; i<len ; i++) {
1795                                 mat = matlist[i];
1796                                 if (mat != NULL) {
1797                                                 if (((ID *)mat)->us > 0)
1798                                                                 ((ID *)mat)->us--;
1799                                                 else
1800                                                                 printf ("FATAL: material usage=0: %s", ((ID *)mat)->name);
1801                                 }
1802                 }
1803                 MEM_freeN (matlist);
1804
1805                 return 1;
1806 }
1807
1808 /** expands pointer array of length 'oldsize' to length 'newsize'.
1809         * A pointer to the (void *) array must be passed as first argument 
1810         * The array pointer content can be NULL, in this case a new array of length
1811         * 'newsize' is created.
1812         */
1813
1814 static int expandPtrArray(void **p, int oldsize, int newsize)
1815 {
1816         void *newarray;
1817
1818         if (newsize < oldsize) {
1819                 return 0;
1820         }       
1821         newarray = MEM_callocN(newsize * sizeof(void *), "PtrArray");
1822         if (*p) {
1823                 memcpy(newarray, *p, oldsize);
1824                 MEM_freeN(*p);
1825         }       
1826         *p = newarray;
1827         return 1;
1828 }
1829
1830 int EXPP_synchronizeMaterialLists (Object *object, void *data)
1831 {
1832                 Material        *** p_dataMaterials = give_matarar (object);
1833                 short                           * nmaterials = give_totcolp (object);
1834
1835                 if (object->totcol > *nmaterials) {
1836                                 /* More object mats than data mats */
1837                                 *nmaterials = object->totcol;
1838                                 return expandPtrArray ((void *) p_dataMaterials,
1839                                                                                                                          *nmaterials,
1840                                                                                                                          object->totcol);
1841                 }
1842                 else {
1843                                 if (object->totcol < *nmaterials) {
1844                                                 /* More data mats than object mats */
1845                                                 object->totcol = *nmaterials;
1846                                                 return expandPtrArray ((void *) &object->mat,
1847                                                                                                                                          object->totcol,
1848                                                                                                                                          *nmaterials);
1849                                 }
1850                 }
1851
1852                 /* No synchronization is needed; they're of equal length */
1853                 return 1;
1854 }
1855
1856 void EXPP_incr_mats_us (Material **matlist, int len)
1857 {
1858         int i;
1859         Material *mat;
1860
1861         if (len <= 0) return;
1862
1863         for (i = 0; i < len; i++) {
1864                 mat = matlist[i];
1865                 if (mat) mat->id.us++;
1866         }
1867
1868         return;
1869 }
1870