1674413afa7af061810e95dff8c27b156d0132dd
[blender-staging.git] / source / blender / python / api2_2x / Object.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  *
26  * The Object module provides generic access to Objects of various types via
27  * the Python interface.
28  *
29  *
30  * Contributor(s): Michel Selten, Willian Germano, Jacques Guignot,
31  * Joseph Gilbert, Stephen Swaney, Bala Gi
32  *
33  * ***** END GPL/BL DUAL LICENSE BLOCK *****
34 */
35
36 #include "Object.h"
37
38 /*****************************************************************************/
39 /* Python API function prototypes for the Blender module.                                        */
40 /*****************************************************************************/
41 static PyObject *M_Object_New(PyObject *self, PyObject *args);
42 PyObject *M_Object_Get(PyObject *self, PyObject *args);
43 PyObject *M_Object_get(PyObject *self, PyObject *args);
44 static PyObject *M_Object_GetSelected (PyObject *self, PyObject *args);
45 static PyObject *M_Object_getSelected (PyObject *self, PyObject *args);
46
47 /*****************************************************************************/
48 /* The following string definitions are used for documentation strings.          */
49 /* In Python these will be written to the console when doing a                           */
50 /* Blender.Object.__doc__                                                                                                        */
51 /*****************************************************************************/
52 char M_Object_doc[] =
53 "The Blender Object module\n\n\
54 This module provides access to **Object Data** in Blender.\n";
55
56 char M_Object_New_doc[] =
57 "(type) - Add a new object of type 'type' in the current scene";
58
59 char M_Object_Get_doc[] =
60 "(name) - return the object with the name 'name', returns None if not\
61         found.\n\
62         If 'name' is not specified, it returns a list of all objects in the\n\
63         current scene.";
64
65 char M_Object_GetSelected_doc[] =
66 "() - Returns a list of selected Objects in the active layer(s)\n\
67 The active object is the first in the list, if visible";
68
69 /*****************************************************************************/
70 /* Python method structure definition for Blender.Object module:                         */
71 /*****************************************************************************/
72 struct PyMethodDef M_Object_methods[] = {
73         {"New",                 (PyCFunction)M_Object_New,                 METH_VARARGS,
74                                         M_Object_New_doc},
75         {"Get",                 (PyCFunction)M_Object_Get,                 METH_VARARGS,
76                                         M_Object_Get_doc},
77         {"get",                 (PyCFunction)M_Object_get,                 METH_VARARGS,
78                                         M_Object_Get_doc},
79         {"GetSelected", (PyCFunction)M_Object_GetSelected, METH_VARARGS,
80                                         M_Object_GetSelected_doc},
81         {"getSelected", (PyCFunction)M_Object_getSelected, METH_VARARGS,
82                                         M_Object_GetSelected_doc},
83         {NULL, NULL, 0, NULL}
84 };
85
86 /*****************************************************************************/
87 /* Python BPy_Object methods declarations:                                                                         */
88 /*****************************************************************************/
89 static PyObject *Object_buildParts (BPy_Object *self);
90 static PyObject *Object_clearIpo (BPy_Object *self);
91 static PyObject *Object_clrParent (BPy_Object *self, PyObject *args);
92 static PyObject *Object_getData (BPy_Object *self);
93 static PyObject *Object_getDeltaLocation (BPy_Object *self);
94 static PyObject *Object_getDrawMode (BPy_Object *self);
95 static PyObject *Object_getDrawType (BPy_Object *self);
96 static PyObject *Object_getEuler (BPy_Object *self);
97 static PyObject *Object_getInverseMatrix (BPy_Object *self);
98 static PyObject *Object_getIpo (BPy_Object *self);
99 static PyObject *Object_getLocation (BPy_Object *self, PyObject *args);
100 static PyObject *Object_getMaterials (BPy_Object *self);
101 static PyObject *Object_getMatrix (BPy_Object *self);
102 static PyObject *Object_getName (BPy_Object *self);
103 static PyObject *Object_getParent (BPy_Object *self);
104 static PyObject *Object_getSize (BPy_Object *self, PyObject *args);
105 static PyObject *Object_getTimeOffset (BPy_Object *self);
106 static PyObject *Object_getTracked (BPy_Object *self);
107 static PyObject *Object_getType (BPy_Object *self);
108 static PyObject *Object_getBoundBox (BPy_Object *self);
109 static PyObject *Object_makeDisplayList (BPy_Object *self);
110 static PyObject *Object_link (BPy_Object *self, PyObject *args);
111 static PyObject *Object_makeParent (BPy_Object *self, PyObject *args);
112 static PyObject *Object_materialUsage (BPy_Object *self, PyObject *args);
113 static PyObject *Object_setDeltaLocation (BPy_Object *self, PyObject *args);
114 static PyObject *Object_setDrawMode (BPy_Object *self, PyObject *args);
115 static PyObject *Object_setDrawType (BPy_Object *self, PyObject *args);
116 static PyObject *Object_setEuler (BPy_Object *self, PyObject *args);\
117 static PyObject *Object_setMatrix (BPy_Object *self, PyObject *args);
118 static PyObject *Object_setIpo (BPy_Object *self, PyObject *args);
119 static PyObject *Object_setLocation (BPy_Object *self, PyObject *args);
120 static PyObject *Object_setMaterials (BPy_Object *self, PyObject *args);
121 static PyObject *Object_setName (BPy_Object *self, PyObject *args);
122 static PyObject *Object_setSize (BPy_Object *self, PyObject *args);
123 static PyObject *Object_setTimeOffset (BPy_Object *self, PyObject *args);
124 static PyObject *Object_shareFrom (BPy_Object *self, PyObject *args);
125
126 /*****************************************************************************/
127 /* Python BPy_Object methods table:                                                                                        */
128 /*****************************************************************************/
129 static PyMethodDef BPy_Object_methods[] = {
130         /* name, method, flags, doc */
131   {"buildParts", (PyCFunction)Object_buildParts, METH_NOARGS,
132         "Recalcs particle system (if any) "},
133   {"getIpo", (PyCFunction)Object_getIpo, METH_NOARGS,
134                 "Returns the ipo of this object (if any) "},   
135   {"clrParent", (PyCFunction)Object_clrParent, METH_VARARGS,
136         "Clears parent object. Optionally specify:\n\
137 mode\n\t2: Keep object transform\nfast\n\t>0: Don't update scene \
138 hierarchy (faster)"},
139   {"getData", (PyCFunction)Object_getData, METH_NOARGS,
140         "Returns the datablock object containing the object's data, e.g. Mesh"},
141   {"getDeltaLocation", (PyCFunction)Object_getDeltaLocation, METH_NOARGS,
142         "Returns the object's delta location (x, y, z)"},
143   {"getDrawMode", (PyCFunction)Object_getDrawMode, METH_NOARGS,
144         "Returns the object draw modes"},
145   {"getDrawType", (PyCFunction)Object_getDrawType, METH_NOARGS,
146         "Returns the object draw type"},
147   {"getEuler", (PyCFunction)Object_getEuler, METH_NOARGS,
148         "Returns the object's rotation as Euler rotation vector\n\
149 (rotX, rotY, rotZ)"},
150   {"getInverseMatrix", (PyCFunction)Object_getInverseMatrix, METH_NOARGS,
151         "Returns the object's inverse matrix"},
152   {"getLocation", (PyCFunction)Object_getLocation, METH_VARARGS,
153         "Returns the object's location (x, y, z)"},
154   {"getMaterials", (PyCFunction)Object_getMaterials, METH_NOARGS,
155         "Returns list of materials assigned to the object"},
156   {"getMatrix", (PyCFunction)Object_getMatrix, METH_NOARGS,
157         "Returns the object matrix"},
158   {"getName", (PyCFunction)Object_getName, METH_NOARGS,
159         "Returns the name of the object"},
160   {"getParent", (PyCFunction)Object_getParent, METH_NOARGS,
161         "Returns the object's parent object"},
162   {"getSize", (PyCFunction)Object_getSize, METH_VARARGS,
163         "Returns the object's size (x, y, z)"},
164   {"getTimeOffset", (PyCFunction)Object_getTimeOffset, METH_NOARGS,
165         "Returns the object's time offset"},
166   {"getTracked", (PyCFunction)Object_getTracked, METH_NOARGS,
167         "Returns the object's tracked object"},
168   {"getType", (PyCFunction)Object_getType, METH_NOARGS,
169         "Returns type of string of Object"},
170   {"getBoundBox", (PyCFunction)Object_getBoundBox, METH_NOARGS,
171         "Returns the object's bounding box"},
172   {"makeDisplayList", (PyCFunction)Object_makeDisplayList, METH_NOARGS,
173         "Update this object's Display List. Some changes like turning \n\
174 'SubSurf' on for a mesh need this method (followed by a Redraw) to \n\
175 show the changes on the 3d window."},
176   {"link", (PyCFunction)Object_link, METH_VARARGS,
177         "Links Object with data provided in the argument. The data must \n\
178 match the Object's type, so you cannot link a Lamp to a Mesh type object."},
179   {"makeParent", (PyCFunction)Object_makeParent, METH_VARARGS,
180         "Makes the object the parent of the objects provided in the \n\
181 argument which must be a list of valid Objects. Optional extra arguments:\n\
182 mode:\n\t0: make parent with inverse\n\t1: without inverse\n\
183 fase:\n\t0: update scene hierarchy automatically\n\t\
184 don't update scene hierarchy (faster). In this case, you must\n\t\
185 explicitely update the Scene hierarchy."},
186   {"materialUsage", (PyCFunction)Object_materialUsage, METH_VARARGS,
187         "Determines the way the material is used and returns status.\n\
188 Possible arguments (provide as strings):\n\
189 \tData:   Materials assigned to the object's data are shown. (default)\n\
190 \tObject: Materials assigned to the object are shown."},
191   {"setDeltaLocation", (PyCFunction)Object_setDeltaLocation, METH_VARARGS,
192         "Sets the object's delta location which must be a vector triple."},
193   {"setDrawMode", (PyCFunction)Object_setDrawMode, METH_VARARGS,
194         "Sets the object's drawing mode. The argument can be a sum of:\n\
195 2:      axis\n4:  texspace\n8:  drawname\n16: drawimage\n32: drawwire"},
196   {"setDrawType", (PyCFunction)Object_setDrawType, METH_VARARGS,
197         "Sets the object's drawing type. The argument must be one of:\n\
198 1: Bounding box\n2: Wire\n3: Solid\n4: Shaded\n5: Textured"},
199   {"setEuler", (PyCFunction)Object_setEuler, METH_VARARGS,
200         "Set the object's rotation according to the specified Euler\n\
201 angles. The argument must be a vector triple"},
202   {"setMatrix", (PyCFunction)Object_setMatrix, METH_VARARGS,
203         "Set and apply a new matrix for the object"},
204   {"setLocation", (PyCFunction)Object_setLocation, METH_VARARGS,
205         "Set the object's location. The first argument must be a vector\n\
206 triple."},
207   {"setMaterials", (PyCFunction)Object_setMaterials, METH_VARARGS,
208         "Sets materials. The argument must be a list of valid material\n\
209 objects."},
210   {"setName", (PyCFunction)Object_setName, METH_VARARGS,
211         "Sets the name of the object"},
212   {"setSize", (PyCFunction)Object_setSize, METH_VARARGS,
213         "Set the object's size. The first argument must be a vector\n\
214 triple."},
215   {"setTimeOffset", (PyCFunction)Object_setTimeOffset, METH_VARARGS,
216         "Set the object's time offset."},
217   {"shareFrom", (PyCFunction)Object_shareFrom, METH_VARARGS,
218         "Link data of self with object specified in the argument. This\n\
219 works only if self and the object specified are of the same type."},
220   {"setIpo", (PyCFunction)Object_setIpo, METH_VARARGS,
221         "(Blender Ipo) - Sets the object's ipo"},
222   {"clearIpo", (PyCFunction)Object_clearIpo, METH_NOARGS,
223         "() - Unlink ipo from this object"},
224   {0}
225 };
226
227 /*****************************************************************************/
228 /* PythonTypeObject callback function prototypes                                                         */
229 /*****************************************************************************/
230 static void              Object_dealloc (BPy_Object *obj);
231 static PyObject* Object_getAttr (BPy_Object *obj, char *name);
232 static int               Object_setAttr (BPy_Object *obj, char *name, PyObject *v);
233 static PyObject* Object_repr    (BPy_Object *obj);
234 static int               Object_compare (BPy_Object *a, BPy_Object *b);
235
236 /*****************************************************************************/
237 /* Python TypeObject structure definition.                                                                       */
238 /*****************************************************************************/
239 PyTypeObject Object_Type =
240 {
241   PyObject_HEAD_INIT(NULL)
242   0,                                                            /* ob_size */
243   "Blender Object",                                     /* tp_name */
244   sizeof (BPy_Object),                          /* tp_basicsize */
245   0,                                                            /* tp_itemsize */
246   /* methods */
247   (destructor)Object_dealloc,           /* tp_dealloc */
248   0,                                                            /* tp_print */
249   (getattrfunc)Object_getAttr,          /* tp_getattr */
250   (setattrfunc)Object_setAttr,          /* tp_setattr */
251   (cmpfunc)Object_compare,                      /* tp_compare */
252   (reprfunc)Object_repr,                        /* tp_repr */
253   0,                                                            /* tp_as_number */
254   0,                                                            /* tp_as_sequence */
255   0,                                                            /* tp_as_mapping */
256   0,                                                            /* tp_as_hash */
257   0,0,0,0,0,0,
258   0,                                                            /* tp_doc */ 
259   0,0,0,0,0,0,
260   BPy_Object_methods,                           /* tp_methods */
261   0,                                                            /* tp_members */
262 };
263
264 /*****************************************************************************/
265 /* Function:                      M_Object_New                                                                           */
266 /* Python equivalent:     Blender.Object.New                                                             */
267 /*****************************************************************************/
268 PyObject *M_Object_New(PyObject *self, PyObject *args)
269 {
270   struct Object * object;
271   BPy_Object      * blen_object;
272   int           type;
273   char  * str_type;
274   char  * name = NULL;
275
276   if (!PyArg_ParseTuple(args, "s|s", &str_type, &name))
277   {
278                 PythonReturnErrorObject (PyExc_TypeError, "string expected as argument");
279                 return (NULL);
280   }
281
282   if (strcmp (str_type, "Armature") == 0)         type = OB_ARMATURE;
283   else if (strcmp (str_type, "Camera") == 0)  type = OB_CAMERA;
284   else if (strcmp (str_type, "Curve") == 0)   type = OB_CURVE;
285 /*      else if (strcmp (str_type, "Text") == 0)        type = OB_FONT; */
286 /*      else if (strcmp (str_type, "Ika") == 0)         type = OB_IKA; */
287   else if (strcmp (str_type, "Lamp") == 0)        type = OB_LAMP;
288   else if (strcmp (str_type, "Lattice") == 0) type = OB_LATTICE;
289 /*      else if (strcmp (str_type, "Mball") == 0)       type = OB_MBALL; */
290   else if (strcmp (str_type, "Mesh") == 0)        type = OB_MESH;
291   else if (strcmp (str_type, "Surf") == 0)        type = OB_SURF;
292 /*      else if (strcmp (str_type, "Wave") == 0)        type = OB_WAVE; */
293   else if (strcmp (str_type, "Empty") == 0)   type = OB_EMPTY;
294   else
295   {
296                 return (PythonReturnErrorObject (PyExc_AttributeError,
297                 "Unknown type specified"));
298   }
299
300   /* Create a new object. */
301   if (name == NULL)
302   {
303           /* No name is specified, set the name to the type of the object. */
304                 name = str_type;
305   }
306   object = alloc_libblock (&(G.main->object), ID_OB, name);
307
308   object->id.us = 0;
309   object->flag = 0;
310   object->type = type;
311   
312
313   /* transforms */
314   QuatOne(object->quat);
315   QuatOne(object->dquat);
316
317   object->col[3]= 1.0;    // alpha 
318
319   object->size[0] = object->size[1] = object->size[2] = 1.0;
320   object->loc[0] = object->loc[1] = object->loc[2] = 0.0;
321   Mat4One(object->parentinv);
322   Mat4One(object->obmat);
323   object->dt = OB_SHADED; // drawtype
324
325   if (U.flag & USER_MAT_ON_OB)
326   {
327                 object->colbits = -1;
328   }
329   switch (object->type)
330   {
331                 case OB_CAMERA: /* fall through. */
332                 case OB_LAMP:
333                   object->trackflag = OB_NEGZ;
334                   object->upflag = OB_POSY;
335                 break;
336                 default:
337                   object->trackflag = OB_POSY;
338                  object->upflag = OB_POSZ;
339   }
340   object->ipoflag = OB_OFFS_OB + OB_OFFS_PARENT;
341
342   /* duplivert settings */
343   object->dupon = 1;
344   object->dupoff = 0;
345   object->dupsta = 1;
346   object->dupend = 100;
347
348   /* Gameengine defaults*/
349   object->mass = 1.0;
350   object->inertia = 1.0;
351   object->formfactor = 0.4;
352   object->damping = 0.04;
353   object->rdamping = 0.1;
354   object->anisotropicFriction[0] = 1.0;
355   object->anisotropicFriction[1] = 1.0;
356   object->anisotropicFriction[2] = 1.0;
357   object->gameflag = OB_PROP;
358
359   object->lay = 1; // Layer, by default visible
360   G.totobj++;
361
362   object->data = NULL;
363
364   /* Create a Python object from it. */
365   blen_object = (BPy_Object*)PyObject_NEW (BPy_Object, &Object_Type); 
366   blen_object->object = object;
367
368   return ((PyObject*)blen_object);
369 }
370
371 /*****************************************************************************/
372 /* Function:                      M_Object_Get                                                                           */
373 /* Python equivalent:     Blender.Object.Get                                                             */
374 /*****************************************************************************/
375 PyObject *M_Object_Get(PyObject *self, PyObject *args)
376 {
377         struct Object   * object;
378         BPy_Object              * blen_object;
379         char                    * name = NULL;
380
381         PyArg_ParseTuple(args, "|s", &name);
382
383         if (name != NULL)
384         {
385                 object = GetObjectByName (name);
386
387                 if (object == NULL)
388                 {
389                         /* No object exists with the name specified in the argument name. */
390                         return (PythonReturnErrorObject (PyExc_AttributeError,
391                                                 "Unknown object specified."));
392                 }
393                 blen_object = (BPy_Object*)PyObject_NEW (BPy_Object, &Object_Type); 
394                 blen_object->object = object;
395
396                 return ((PyObject*)blen_object);
397         }
398         else
399         {
400                 /* No argument has been given. Return a list of all objects. */
401                 PyObject        * obj_list;
402                 Link            * link;
403                 int                       index;
404
405                 obj_list = PyList_New (BLI_countlist (&(G.main->object)));
406
407                 if (obj_list == NULL)
408                 {
409                         return (PythonReturnErrorObject (PyExc_SystemError,
410                                         "List creation failed."));
411                 }
412
413                 link = G.main->object.first;
414                 index = 0;
415                 while (link)
416                 {
417                         object = (Object*)link;
418                         blen_object = (BPy_Object*)PyObject_NEW (BPy_Object, &Object_Type);
419                         blen_object->object = object;
420
421                         PyList_SetItem (obj_list, index, (PyObject*)blen_object);
422                         index++;
423                         link = link->next;
424                 }
425                 return (obj_list);
426         }
427 }
428
429 /*****************************************************************************/
430 /* Function:                      M_Object_get                                                                           */
431 /* Python equivalent:     Blender.Object.get                                                             */
432 /*****************************************************************************/
433 PyObject *M_Object_get(PyObject *self, PyObject *args)
434 {
435         PyErr_Warn (PyExc_DeprecationWarning,
436                 "The Object.get() function will be removed in Blender 2.29\n" \
437                 "Please update the script to use Object.Get");
438         return (M_Object_Get (self, args));
439 }
440
441 /*****************************************************************************/
442 /* Function:                      M_Object_GetSelected                                                           */
443 /* Python equivalent:     Blender.Object.getSelected                                             */
444 /*****************************************************************************/
445 static PyObject *M_Object_GetSelected (PyObject *self, PyObject *args)
446 {
447         BPy_Object                * blen_object;
448         PyObject                * list;
449         Base                    * base_iter;
450
451     if (G.vd == NULL)
452     {
453         // No 3d view has been initialized yet, simply return None
454         Py_INCREF (Py_None);
455         return Py_None;
456     }
457         list = PyList_New (0);
458         if ((G.scene->basact) &&
459                 ((G.scene->basact->flag & SELECT) &&
460                  (G.scene->basact->lay & G.vd->lay)))
461         {
462                 /* Active object is first in the list. */
463                 blen_object = (BPy_Object*)PyObject_NEW (BPy_Object, &Object_Type); 
464                 if (blen_object == NULL)
465                 {
466                         Py_DECREF (list);
467                         Py_INCREF (Py_None);
468                         return (Py_None);
469                 }
470                 blen_object->object = G.scene->basact->object;
471                 PyList_Append (list, (PyObject*)blen_object);
472         }
473
474         base_iter = G.scene->base.first;
475         while (base_iter)
476         {
477                 if (((base_iter->flag & SELECT) &&
478                          (base_iter->lay & G.vd->lay)) &&
479                         (base_iter != G.scene->basact))
480                 {
481                         blen_object = (BPy_Object*)PyObject_NEW (BPy_Object, &Object_Type); 
482                         if (blen_object == NULL)
483                         {
484                                 Py_DECREF (list);
485                                 Py_INCREF (Py_None);
486                                 return (Py_None);
487                         }
488                         blen_object->object = base_iter->object;
489                         PyList_Append (list, (PyObject*)blen_object);
490                 }
491                 base_iter = base_iter->next;
492         }
493         return (list);
494 }
495
496 /*****************************************************************************/
497 /* Function:                      M_Object_getSelected                                                           */
498 /* Python equivalent:     Blender.Object.getSelected                                             */
499 /*****************************************************************************/
500 static PyObject *M_Object_getSelected (PyObject *self, PyObject *args)
501 {
502         PyErr_Warn (PyExc_DeprecationWarning,
503                                 "The Object.getSelected() function will be removed in "\
504                                 "Blender 2.29\n" \
505                                 "Please update the script to use Object.GetSelected");
506         return (M_Object_GetSelected (self, args));
507 }
508
509 /*****************************************************************************/
510 /* Function:                      initObject                                                                             */
511 /*****************************************************************************/
512 PyObject *Object_Init (void)
513 {
514         PyObject        * module;
515
516         Object_Type.ob_type = &PyType_Type;
517
518         module = Py_InitModule3("Blender.Object", M_Object_methods, M_Object_doc);
519
520         return (module);
521 }
522
523 /*****************************************************************************/
524 /* Python BPy_Object methods:                                                                                              */
525 /*****************************************************************************/
526
527 static PyObject *Object_buildParts (BPy_Object *self)
528 {
529   void build_particle_system(Object *ob);
530   struct Object *obj = self->object;
531
532   build_particle_system(obj);
533
534   Py_INCREF (Py_None);
535   return (Py_None);
536 }
537
538 static PyObject *Object_clearIpo(BPy_Object *self)
539 {
540         Object *ob = self->object;
541         Ipo *ipo = (Ipo *)ob->ipo;
542
543         if (ipo) {
544                 ID *id = &ipo->id;
545                 if (id->us > 0) id->us--;
546                 ob->ipo = NULL;
547
548                 Py_INCREF (Py_True);
549                 return Py_True;
550         }
551
552         Py_INCREF (Py_False); /* no ipo found */
553         return Py_False;
554 }
555
556 static PyObject *Object_clrParent (BPy_Object *self, PyObject *args)
557 {
558   int mode=0;
559   int fast=0;
560
561   if (!PyArg_ParseTuple (args, "|ii", &mode, &fast))
562   {
563                 return (PythonReturnErrorObject (PyExc_AttributeError,
564                   "expected one or two integers as arguments"));
565   }
566
567   /* Remove the link only, the object is still in the scene. */
568   self->object->parent = NULL;
569
570   if (mode == 2)
571   {
572                 /* Keep transform */
573                 apply_obmat (self->object);
574   }
575
576   if (!fast)
577   {
578                 sort_baselist (G.scene);
579   }
580
581   Py_INCREF (Py_None);
582   return (Py_None);
583 }
584
585 /* adds object data to a Blender object, if object->data = NULL */
586 int EXPP_add_obdata(struct Object *object)
587 {
588   if (object->data != NULL) return -1;
589
590   switch(object->type)
591   {
592         case OB_ARMATURE:
593         /* TODO: Do we need to add something to G? (see the OB_LAMP case) */
594           object->data = add_armature();
595           break;
596         case OB_CAMERA:
597           /* TODO: Do we need to add something to G? (see the OB_LAMP case) */
598           object->data = add_camera();
599           break;
600         case OB_CURVE:
601           object->data = add_curve(OB_CURVE);
602           G.totcurve++;
603           break;
604         case OB_LAMP:
605           object->data = add_lamp();
606           G.totlamp++;
607           break;
608         case OB_MESH:
609           object->data = add_mesh();
610           G.totmesh++;
611           break;
612         case OB_LATTICE:
613       object->data = (void *)add_lattice();
614           object->dt = OB_WIRE;
615           break;
616
617         /* TODO the following types will be supported later
618         case OB_SURF:
619           object->data = add_curve(OB_SURF);
620           G.totcurve++;
621           break;
622         case OB_FONT:
623           object->data = add_curve(OB_FONT);
624           break;
625         case OB_MBALL:
626           object->data = add_mball();
627           break;
628         case OB_IKA:
629           object->data = add_ika();
630           object->dt = OB_WIRE;
631           break;
632         case OB_WAVE:
633           object->data = add_wave();
634           break;
635         */
636         default:
637           break;
638   }
639
640   if (!object->data) return -1;
641
642   return 0;
643 }
644
645 static PyObject *Object_getData (BPy_Object *self)
646 {
647         PyObject  * data_object;
648         Object * object = self->object;
649
650         /* if there's no obdata, try to create it */
651         if (object->data == NULL)
652         {
653           if (EXPP_add_obdata(object) != 0)
654           { /* couldn't create obdata */
655                 Py_INCREF (Py_None);
656                 return (Py_None);
657           }
658         }
659
660         data_object = NULL;
661
662         switch (object->type)
663         {
664                 case OB_ARMATURE:
665                         data_object = Armature_CreatePyObject (object->data);
666                         break;
667                 case OB_CAMERA:
668                         data_object = Camera_CreatePyObject (object->data);
669                         break;
670                 case OB_CURVE:
671                         data_object = Curve_CreatePyObject (object->data);
672                         break;
673                 case ID_IM:
674                         data_object = Image_CreatePyObject (object->data);
675                         break;
676                 case ID_IP:
677                         data_object = Ipo_CreatePyObject (object->data);
678                         break;
679                 case OB_LAMP:
680                         data_object = Lamp_CreatePyObject (object->data);
681                         break;
682                 case OB_LATTICE:
683                         data_object = Lattice_CreatePyObject (object->data);
684                         break;
685                 case ID_MA:
686                         break;
687                 case OB_MESH:
688                         data_object = NMesh_CreatePyObject (object->data, object);
689                         break;
690                 case ID_OB:
691                         data_object = Object_CreatePyObject (object->data);
692                         break;
693                 case ID_SCE:
694                         break;
695                 case ID_TXT:
696                         data_object = Text_CreatePyObject (object->data);
697                         break;
698                 case ID_WO:
699                         break;
700                 default:
701                         break;
702         }
703         if (data_object == NULL)
704         {
705                 Py_INCREF (Py_None);
706                 return (Py_None);
707         }
708         else
709         {
710                 return (data_object);
711         }
712 }
713
714 static PyObject *Object_getDeltaLocation (BPy_Object *self)
715 {
716         PyObject *attr = Py_BuildValue ("fff",
717                                                                         self->object->dloc[0],
718                                                                         self->object->dloc[1],
719                                                                         self->object->dloc[2]);
720
721         if (attr) return (attr);
722
723         return (PythonReturnErrorObject (PyExc_RuntimeError,
724                         "couldn't get Object.dloc attributes"));
725 }
726
727 static PyObject *Object_getDrawMode (BPy_Object *self)
728 {
729         PyObject *attr = Py_BuildValue ("b", self->object->dtx);
730
731         if (attr) return (attr);
732
733         return (PythonReturnErrorObject (PyExc_RuntimeError,
734                         "couldn't get Object.drawMode attribute"));
735 }
736
737 static PyObject *Object_getDrawType (BPy_Object *self)
738 {
739         PyObject *attr = Py_BuildValue ("b", self->object->dt);
740
741         if (attr) return (attr);
742
743         return (PythonReturnErrorObject (PyExc_RuntimeError,
744                         "couldn't get Object.drawType attribute"));
745 }
746
747 static PyObject *Object_getEuler (BPy_Object *self)
748 {  
749         EulerObject *eul;
750
751         eul = (EulerObject*)newEulerObject(NULL);
752         eul->eul[0] = self->object->rot[0];
753         eul->eul[1] = self->object->rot[1];
754         eul->eul[2] = self->object->rot[2];
755
756         return (PyObject*)eul; 
757
758 }
759
760 static PyObject *Object_getInverseMatrix (BPy_Object *self)
761 {
762         MatrixObject *inverse = (MatrixObject *)newMatrixObject(NULL, 4, 4);
763         
764         Mat4Invert (*inverse->matrix, self->object->obmat);
765
766         return ((PyObject *)inverse);
767
768 }
769
770 static PyObject *Object_getIpo(BPy_Object *self)
771 {
772   struct Ipo *ipo = self->object->ipo;
773
774   if (!ipo)
775         {
776                 Py_INCREF (Py_None);
777                 return Py_None;
778   }
779
780   return Ipo_CreatePyObject (ipo);
781 }
782
783 static PyObject *Object_getLocation (BPy_Object *self, PyObject *args)
784 {
785         PyObject *attr = Py_BuildValue ("fff",
786                                                                         self->object->loc[0],
787                                                                         self->object->loc[1],
788                                                                         self->object->loc[2]);
789
790         if (attr) return (attr);
791
792         return (PythonReturnErrorObject (PyExc_RuntimeError,
793                         "couldn't get Object.loc attributes"));
794 }
795
796 static PyObject *Object_getMaterials (BPy_Object *self)
797 {
798         return (EXPP_PyList_fromMaterialList (self->object->mat,
799                                                                                   self->object->totcol));
800 }
801
802 static PyObject *Object_getMatrix (BPy_Object *self)
803 {
804         Object  * ob;
805
806         ob = self->object;
807
808         return (PyObject*)newMatrixObject((float*)ob->obmat, 4, 4);
809 }
810
811 static PyObject *Object_getName (BPy_Object *self)
812 {
813         PyObject *attr = Py_BuildValue ("s", self->object->id.name+2);
814
815         if (attr) return (attr);
816
817         return (PythonReturnErrorObject (PyExc_RuntimeError,
818                         "couldn't get the name of the Object"));
819 }
820
821 static PyObject *Object_getParent (BPy_Object *self)
822 {
823         PyObject *attr;
824
825         if (self->object->parent == NULL)
826                 return EXPP_incr_ret (Py_None);
827
828         attr = Object_CreatePyObject (self->object->parent);
829
830         if (attr)
831         {
832                 return (attr);
833         }
834
835         return (PythonReturnErrorObject (PyExc_RuntimeError,
836                         "couldn't get Object.parent attribute"));
837 }
838
839 static PyObject *Object_getSize (BPy_Object *self, PyObject *args)
840 {
841         PyObject *attr = Py_BuildValue ("fff",
842                                                                         self->object->size[0],
843                                                                         self->object->size[1],
844                                                                         self->object->size[2]);
845
846         if (attr) return (attr);
847
848         return (PythonReturnErrorObject (PyExc_RuntimeError,
849                         "couldn't get Object.size attributes"));
850 }
851
852 static PyObject *Object_getTimeOffset (BPy_Object *self)
853 {
854         PyObject *attr = Py_BuildValue ("f", self->object->sf);
855
856         if (attr) return (attr);
857
858         return (PythonReturnErrorObject (PyExc_RuntimeError,
859                         "couldn't get Object.sf attributes"));
860 }
861
862
863 static PyObject *Object_getTracked (BPy_Object *self)
864 {
865         PyObject        *attr;
866
867         if (self->object->track == NULL)
868                 return EXPP_incr_ret (Py_None);
869         
870         attr = Object_CreatePyObject (self->object->track);
871
872         if (attr)
873         {
874                 return (attr);
875         }
876
877         return (PythonReturnErrorObject (PyExc_RuntimeError,
878                         "couldn't get Object.track attribute"));
879 }
880
881 static PyObject *Object_getType (BPy_Object *self)
882 {
883         switch (self->object->type)
884         {
885                 case OB_ARMATURE:       return (Py_BuildValue ("s", "Armature"));
886                 case OB_CAMERA:         return (Py_BuildValue ("s", "Camera"));
887                 case OB_CURVE:          return (Py_BuildValue ("s", "Curve"));
888                 case OB_EMPTY:          return (Py_BuildValue ("s", "Empty"));
889                 case OB_FONT:           return (Py_BuildValue ("s", "Text"));
890                 case OB_IKA:            return (Py_BuildValue ("s", "Ika"));
891                 case OB_LAMP:           return (Py_BuildValue ("s", "Lamp"));
892                 case OB_LATTICE:        return (Py_BuildValue ("s", "Lattice"));
893                 case OB_MBALL:          return (Py_BuildValue ("s", "MBall"));
894                 case OB_MESH:           return (Py_BuildValue ("s", "Mesh"));
895                 case OB_SURF:           return (Py_BuildValue ("s", "Surf"));
896                 case OB_WAVE:           return (Py_BuildValue ("s", "Wave"));
897                 default:                        return (Py_BuildValue ("s", "unknown"));
898         }
899 }
900
901 static PyObject *Object_getBoundBox (BPy_Object *self)
902 {
903   int i;
904   float *vec = NULL;
905   PyObject *vector, *bbox;
906
907   if (!self->object->data)
908         return EXPP_ReturnPyObjError (PyExc_AttributeError,
909           "This object isn't linked to any object data (mesh, curve, etc) yet");
910
911   if (!self->object->bb) {
912         Mesh *me;
913         Curve *curve;
914         switch (self->object->type) {
915           case OB_MESH:
916                 me = self->object->data;
917                 if (!me->bb) tex_space_mesh(me);
918                 vec = (float *)me->bb->vec;
919                 break;
920           case OB_CURVE:
921           case OB_FONT:
922           case OB_SURF:
923                 curve = self->object->data;
924                 if (!curve->bb) tex_space_curve(curve);
925                 vec = (float *)curve->bb->vec;
926                 break;
927           default:
928                 Py_INCREF (Py_None);
929                 return Py_None;
930         }
931   }
932   else vec = (float *)self->object->bb->vec;
933
934   if (!vec)
935         return EXPP_ReturnPyObjError (PyExc_RuntimeError,
936                   "couldn't retrieve bounding box data");
937
938   bbox = PyList_New(8);
939
940   if (!bbox)
941         return EXPP_ReturnPyObjError (PyExc_MemoryError,
942                   "couldn't create pylist");
943
944   for (i = 0; i < 8; i++) {
945         vector = newVectorObject(vec, 3);
946         PyList_SET_ITEM(bbox, i, vector);
947         vec += 3;
948   }
949
950   return bbox;
951 }
952
953 static PyObject *Object_makeDisplayList (BPy_Object *self)
954 {
955   Object *ob = self->object;
956
957   if (ob->type == OB_FONT) text_to_curve(ob, 0);
958
959   makeDispList(ob);
960
961   Py_INCREF (Py_None);
962   return Py_None;
963 }
964
965 static PyObject *Object_link (BPy_Object *self, PyObject *args)
966 {
967         PyObject        * py_data;
968         ID                      * id;
969         ID                      * oldid;
970         int                       obj_id;
971         void            * data = NULL;
972
973         if (!PyArg_ParseTuple (args, "O", &py_data))
974         {
975                 return (PythonReturnErrorObject (PyExc_AttributeError,
976                         "expected an object as argument"));
977         }
978         if (Camera_CheckPyObject (py_data))
979                 data = (void *)Camera_FromPyObject (py_data);
980         if (Lamp_CheckPyObject (py_data))
981                 data = (void *)Lamp_FromPyObject (py_data);
982         if (Curve_CheckPyObject (py_data))
983                 data = (void *)Curve_FromPyObject (py_data);
984         if (NMesh_CheckPyObject (py_data))
985                 data = (void *)Mesh_FromPyObject (py_data, self->object);
986         if (Lattice_CheckPyObject (py_data))
987                 data = (void *)Lattice_FromPyObject (py_data);
988
989         /* have we set data to something good? */
990         if( !data )
991         {
992                 return (PythonReturnErrorObject (PyExc_AttributeError,
993                         "link argument type is not supported "));
994         }
995
996         oldid = (ID*) self->object->data;
997         id = (ID*) data;
998         obj_id = MAKE_ID2 (id->name[0], id->name[1]);
999
1000         switch (obj_id)
1001         {
1002                 case ID_CA:
1003                         if (self->object->type != OB_CAMERA)
1004                         {
1005                                 return (PythonReturnErrorObject (PyExc_AttributeError,
1006                                         "The 'link' object is incompatible with the base object"));
1007                         }
1008                         break;
1009                 case ID_LA:
1010                         if (self->object->type != OB_LAMP)
1011                         {
1012                                 return (PythonReturnErrorObject (PyExc_AttributeError,
1013                                         "The 'link' object is incompatible with the base object"));
1014                         }
1015                         break;
1016                 case ID_ME:
1017                         if (self->object->type != OB_MESH)
1018                         {
1019                                 return (PythonReturnErrorObject (PyExc_AttributeError,
1020                                         "The 'link' object is incompatible with the base object"));
1021                         }
1022                         break;
1023                 case ID_CU:
1024                         if (self->object->type != OB_CURVE)
1025                         {
1026                                 return (PythonReturnErrorObject (PyExc_AttributeError,
1027                                         "The 'link' object is incompatible with the base object"));
1028                         }
1029                         break;
1030                 case ID_LT:
1031                         if (self->object->type != OB_LATTICE)
1032                         {
1033                                         return (PythonReturnErrorObject (PyExc_AttributeError,
1034                                                         "The 'link' object is incompatible with the base object"));
1035                         }
1036                         break;
1037                 default:
1038                         return (PythonReturnErrorObject (PyExc_AttributeError,
1039                                 "Linking this object type is not supported"));
1040         }
1041         self->object->data = data;
1042
1043         if ( self->object->type == OB_MESH)
1044         {
1045                 self->object->totcol = 0;
1046                 EXPP_synchronizeMaterialLists(self->object, id);
1047         }
1048
1049         id_us_plus (id);
1050         if (oldid)
1051         {
1052                 if (oldid->us > 0)
1053                 {
1054                         oldid->us--;
1055                 }
1056                 else
1057                 {
1058                         return (PythonReturnErrorObject (PyExc_RuntimeError,
1059                                 "old object reference count below 0"));
1060                 }
1061         }
1062         return EXPP_incr_ret (Py_None);
1063 }
1064
1065 static PyObject *Object_makeParent (BPy_Object *self, PyObject *args)
1066 {
1067         PyObject        * list;
1068         PyObject        * py_child;
1069         //BPy_Object      * py_obj_child; unused
1070         Object          * child;
1071         Object          * parent;
1072         int                       noninverse = 0;
1073         int                       fast = 0;
1074         int                       i;
1075
1076         /* Check if the arguments passed to makeParent are valid. */
1077         if (!PyArg_ParseTuple (args, "O|ii", &list, &noninverse, &fast))
1078         {
1079                 return (PythonReturnErrorObject (PyExc_AttributeError,
1080                         "expected a list of objects and one or two integers as arguments"));
1081         }
1082         if (!PySequence_Check (list))
1083         {
1084                 return (PythonReturnErrorObject (PyExc_TypeError,
1085                         "expected a list of objects"));
1086         }
1087
1088         /* Check if the PyObject passed in list is a Blender object. */
1089         for (i=0 ; i<PySequence_Length (list) ; i++)
1090         {
1091                 child = NULL;
1092                 py_child = PySequence_GetItem (list, i);
1093                 if (Object_CheckPyObject (py_child))
1094                         child = (Object*) Object_FromPyObject (py_child);
1095
1096                 if (child == NULL)
1097                 {
1098                         return (PythonReturnErrorObject (PyExc_TypeError,
1099                                 "Object Type expected"));
1100                 }
1101
1102                 parent = (Object*)self->object;
1103                 if (test_parent_loop (parent, child))
1104                 {
1105                         return (PythonReturnErrorObject (PyExc_RuntimeError,
1106                                 "parenting loop detected - parenting failed"));
1107                 }
1108                 child->partype = PAROBJECT;
1109                 child->parent = parent;
1110                 //py_obj_child = (BPy_Object *) py_child;
1111                 if (noninverse == 1)
1112                 {
1113                         /* Parent inverse = unity */
1114                         child->loc[0] = 0.0;
1115                         child->loc[1] = 0.0;
1116                         child->loc[2] = 0.0;
1117                 }
1118                 else
1119                 {
1120                         what_does_parent (child);
1121                         Mat4Invert (child->parentinv, parent->obmat);
1122                 }
1123
1124                 if (!fast)
1125                 {
1126                         sort_baselist (G.scene);
1127                 }
1128
1129                 // We don't need the child object anymore.
1130                 //Py_DECREF ((PyObject *) child);
1131         }
1132         return EXPP_incr_ret (Py_None);
1133 }
1134
1135 static PyObject *Object_materialUsage (BPy_Object *self, PyObject *args)
1136 {
1137         return (PythonReturnErrorObject (PyExc_NotImplementedError,
1138                         "materialUsage: not yet implemented"));
1139 }
1140
1141 static PyObject *Object_setDeltaLocation (BPy_Object *self, PyObject *args)
1142 {
1143         float   dloc1;
1144         float   dloc2;
1145         float   dloc3;
1146         int             status;
1147
1148         if (PyObject_Length (args) == 3)
1149                 status = PyArg_ParseTuple (args, "fff", &dloc1, &dloc2, &dloc3);
1150         else
1151                 status = PyArg_ParseTuple (args, "(fff)", &dloc1, &dloc2, &dloc3);
1152
1153         if (!status)
1154                 return EXPP_ReturnPyObjError (PyExc_AttributeError,
1155                                 "expected list argument of 3 floats");
1156
1157         self->object->dloc[0] = dloc1;
1158         self->object->dloc[1] = dloc2;
1159         self->object->dloc[2] = dloc3;
1160
1161         Py_INCREF (Py_None);
1162         return (Py_None);
1163 }
1164
1165 static PyObject *Object_setDrawMode (BPy_Object *self, PyObject *args)
1166 {
1167         char    dtx;
1168
1169         if (!PyArg_ParseTuple (args, "b", &dtx))
1170         {
1171                 return (PythonReturnErrorObject (PyExc_AttributeError,
1172                                 "expected an integer as argument"));
1173         }
1174         self->object->dtx = dtx;
1175
1176         Py_INCREF (Py_None);
1177         return (Py_None);
1178 }
1179
1180 static PyObject *Object_setDrawType (BPy_Object *self, PyObject *args)
1181
1182         char    dt;
1183
1184         if (!PyArg_ParseTuple (args, "b", &dt))
1185         {
1186                 return (PythonReturnErrorObject (PyExc_AttributeError,
1187                                 "expected an integer as argument"));
1188         }
1189         self->object->dt = dt;
1190
1191         Py_INCREF (Py_None);
1192         return (Py_None);
1193 }
1194
1195 static PyObject *Object_setEuler (BPy_Object *self, PyObject *args)
1196 {
1197         float   rot1;
1198         float   rot2;
1199         float   rot3;
1200         int             status;
1201         PyObject* ob;
1202
1203         if (!PyArg_ParseTuple (args, "O", &ob))
1204                 return (PythonReturnErrorObject (PyExc_AttributeError,
1205                                 "unknown type passed to function (setEuler)"));
1206
1207         //test to see if it's a list or a euler
1208         if(PyList_Check(ob)){
1209                 if (PyObject_Length (args) == 3)
1210                         status = PyArg_ParseTuple (args, "fff", &rot1, &rot2, &rot3);
1211                 else
1212                         status = PyArg_ParseTuple (args, "(fff)", &rot1, &rot2, &rot3);
1213                 if (!status)
1214                         return EXPP_ReturnPyObjError (PyExc_AttributeError,
1215                                         "expected list argument of 3 floats");
1216         }else if(EulerObject_Check(ob)){
1217                 rot1 = ((EulerObject*)ob)->eul[0];
1218                 rot2 = ((EulerObject*)ob)->eul[1];
1219                 rot3 = ((EulerObject*)ob)->eul[2];
1220         }else{
1221                 Py_DECREF (ob);
1222                 return (PythonReturnErrorObject (PyExc_AttributeError,
1223                                 "expected list of floats or euler"));
1224         }
1225
1226         self->object->rot[0] = rot1;
1227         self->object->rot[1] = rot2;
1228         self->object->rot[2] = rot3;
1229
1230         Py_INCREF (Py_None);
1231         return (Py_None);
1232 }
1233
1234 static PyObject *Object_setMatrix (BPy_Object *self, PyObject *args)
1235 {
1236         MatrixObject* mat;
1237         int x,y;
1238
1239         if (!PyArg_ParseTuple(args, "O!", &matrix_Type, &mat))
1240                 return EXPP_ReturnPyObjError 
1241                    (PyExc_TypeError, "expected matrix object as argument");
1242
1243         for(x = 0; x < 4; x++){
1244                 for(y = 0; y < 4; y++){
1245                         self->object->obmat[x][y] = mat->matrix[x][y];
1246                 }
1247         }
1248         apply_obmat(self->object);
1249
1250         Py_INCREF (Py_None);
1251         return (Py_None);
1252 }
1253
1254 static PyObject *Object_setIpo(BPy_Object *self, PyObject *args)
1255 {
1256         PyObject *pyipo = 0;
1257         Ipo *ipo = NULL;
1258         Ipo *oldipo;
1259
1260         if (!PyArg_ParseTuple(args, "O!", &Ipo_Type, &pyipo))
1261                 return EXPP_ReturnPyObjError (PyExc_TypeError, "expected Ipo as argument");
1262
1263         ipo = Ipo_FromPyObject(pyipo);
1264
1265         if (!ipo) return EXPP_ReturnPyObjError (PyExc_RuntimeError, "null ipo!");
1266
1267         if (ipo->blocktype != ID_OB)
1268                 return EXPP_ReturnPyObjError (PyExc_TypeError,
1269                         "this ipo is not an object ipo");
1270
1271         oldipo = self->object->ipo;
1272         if (oldipo) {
1273                 ID *id = &oldipo->id;
1274                 if (id->us > 0) id->us--;
1275         }
1276
1277         ((ID *)&ipo->id)->us++;
1278
1279         self->object->ipo = ipo;
1280
1281         Py_INCREF(Py_None);
1282         return Py_None;
1283 }
1284
1285 static PyObject *Object_setLocation (BPy_Object *self, PyObject *args)
1286 {
1287         float   loc1;
1288         float   loc2;
1289         float   loc3;
1290         int             status;
1291
1292         if (PyObject_Length (args) == 3)
1293                 status = PyArg_ParseTuple (args, "fff", &loc1, &loc2, &loc3);
1294         else
1295                 status = PyArg_ParseTuple (args, "(fff)", &loc1, &loc2, &loc3);
1296
1297         if (!status)
1298                 return EXPP_ReturnPyObjError (PyExc_AttributeError,
1299                                 "expected list argument of 3 floats");
1300
1301         self->object->loc[0] = loc1;
1302         self->object->loc[1] = loc2;
1303         self->object->loc[2] = loc3;
1304
1305         Py_INCREF (Py_None);
1306         return (Py_None);
1307 }
1308
1309 static PyObject *Object_setMaterials (BPy_Object *self, PyObject *args)
1310 {
1311         PyObject         * list;
1312         int                        len;
1313         int                        i;
1314         Material        ** matlist;
1315
1316         if (!PyArg_ParseTuple (args, "O", &list))
1317         {
1318                 return (PythonReturnErrorObject (PyExc_AttributeError,
1319                                 "expected a list of materials as argument"));
1320         }
1321
1322         len = PySequence_Length (list);
1323         if (len > 0)
1324         {
1325                 matlist = EXPP_newMaterialList_fromPyList (list);
1326                 if (!matlist)
1327                 {
1328                         return (PythonReturnErrorObject (PyExc_AttributeError,
1329                                 "material list must be a list of valid materials!"));
1330                 }
1331                 if ((len < 0) || (len > MAXMAT))
1332                 {
1333                         return (PythonReturnErrorObject (PyExc_RuntimeError,
1334                                 "illegal material index!"));
1335                 }
1336
1337                 if (self->object->mat)
1338                 {
1339                         EXPP_releaseMaterialList (self->object->mat, len);
1340                 }
1341                 /* Increase the user count on all materials */
1342                 for (i=0 ; i<len ; i++)
1343                 {
1344                         id_us_plus ((ID *) matlist[i]);
1345                 }
1346                 self->object->mat = matlist;
1347                 self->object->totcol = len;
1348                 self->object->actcol = -1;
1349
1350                 switch (self->object->type)
1351                 {
1352                         case OB_CURVE:  /* fall through */
1353                         case OB_FONT:   /* fall through */
1354                         case OB_MESH:   /* fall through */
1355                         case OB_MBALL:  /* fall through */
1356                         case OB_SURF:
1357                                 EXPP_synchronizeMaterialLists (self->object,
1358                                                                                            self->object->data);
1359                                 break;
1360                         default:
1361                                 break;
1362                 }
1363         }
1364         return EXPP_incr_ret (Py_None);
1365 }
1366
1367 static PyObject *Object_setName (BPy_Object *self, PyObject *args)
1368 {
1369         char  * name;
1370         char    buf[21];
1371
1372         if (!PyArg_ParseTuple (args, "s", &name))
1373         {
1374                 return (PythonReturnErrorObject (PyExc_AttributeError,
1375                                 "expected a String as argument"));
1376         }
1377
1378         PyOS_snprintf(buf, sizeof(buf), "%s", name);
1379
1380         rename_id(&self->object->id, buf);
1381
1382         Py_INCREF (Py_None);
1383         return (Py_None);
1384 }
1385
1386 static PyObject *Object_setSize (BPy_Object *self, PyObject *args)
1387 {
1388         float   sizex;
1389         float   sizey;
1390         float   sizez;
1391         int             status;
1392
1393         if (PyObject_Length (args) == 3)
1394                 status = PyArg_ParseTuple (args, "fff", &sizex, &sizey, &sizez);
1395         else
1396                 status = PyArg_ParseTuple (args, "(fff)", &sizex, &sizey, &sizez);
1397
1398         if (!status)
1399                 return EXPP_ReturnPyObjError (PyExc_AttributeError,
1400                                 "expected list argument of 3 floats");
1401
1402         self->object->size[0] = sizex;
1403         self->object->size[1] = sizey;
1404         self->object->size[2] = sizez;
1405
1406         Py_INCREF (Py_None);
1407         return (Py_None);
1408 }
1409
1410 static PyObject *Object_setTimeOffset (BPy_Object *self, PyObject *args)
1411 {
1412         float newTimeOffset;
1413
1414         if (!PyArg_ParseTuple (args, "f", &newTimeOffset))
1415         {
1416                 return (PythonReturnErrorObject (PyExc_AttributeError,
1417                                 "expected a float as argument"));
1418         }
1419
1420         self->object->sf=newTimeOffset;
1421
1422         Py_INCREF (Py_None);
1423         return (Py_None);
1424 }
1425
1426 static PyObject *Object_shareFrom (BPy_Object *self, PyObject *args)
1427 {
1428         BPy_Object              * object;
1429         ID                              * id;
1430         ID                              * oldid;
1431
1432         if (!PyArg_ParseTuple (args, "O", &object))
1433         {
1434                 PythonReturnErrorObject (PyExc_AttributeError,
1435                                 "expected an object argument");
1436                 return (NULL);
1437         }
1438         if (!Object_CheckPyObject ((PyObject*)object))
1439         {
1440                 PythonReturnErrorObject (PyExc_TypeError,
1441                                 "argument 1 is not of type 'Object'");
1442                 return (NULL);
1443         }
1444
1445         if (self->object->type != object->object->type)
1446         {
1447                 PythonReturnErrorObject (PyExc_TypeError,
1448                                 "objects are not of same data type");
1449                 return (NULL);
1450         }
1451         switch (self->object->type)
1452         {
1453                 case OB_MESH:
1454                 case OB_LAMP:
1455                 case OB_CAMERA: /* we can probably add the other types, too */
1456                 case OB_ARMATURE:
1457                 case OB_CURVE:
1458                 case OB_SURF:
1459                 case OB_LATTICE:
1460                         oldid = (ID*) self->object->data;
1461                         id = (ID*) object->object->data;
1462                         self->object->data = object->object->data;
1463
1464                         if ( self->object->type == OB_MESH && id ){
1465                                 self->object->totcol = 0;
1466                                 EXPP_synchronizeMaterialLists(self->object, id);
1467                         }
1468                         
1469                         id_us_plus (id);
1470                         if (oldid)
1471                         {
1472                                 if (oldid->us > 0)
1473                                 {
1474                                         oldid->us--;
1475                                 }
1476                                 else
1477                                 {
1478                                         return (PythonReturnErrorObject (PyExc_RuntimeError,
1479                                                         "old object reference count below 0"));
1480                                 }
1481                         }
1482                         Py_INCREF (Py_None);
1483                         return (Py_None);
1484                 default:
1485                         PythonReturnErrorObject (PyExc_TypeError,
1486                                         "type not supported");
1487                         return (NULL);
1488         }
1489
1490         Py_INCREF (Py_None);
1491         return (Py_None);
1492 }
1493
1494 /*****************************************************************************/
1495 /* Function:    Object_CreatePyObject                                                                            */
1496 /* Description: This function will create a new BlenObject from an existing  */
1497 /*                              Object structure.                                                                                        */
1498 /*****************************************************************************/
1499 PyObject* Object_CreatePyObject (struct Object *obj)
1500 {
1501         BPy_Object        * blen_object;
1502
1503         blen_object = (BPy_Object*)PyObject_NEW (BPy_Object, &Object_Type);
1504
1505         if (blen_object == NULL)
1506         {
1507                 return (NULL);
1508         }
1509         blen_object->object = obj;
1510         return ((PyObject*)blen_object);
1511 }
1512
1513 /*****************************************************************************/
1514 /* Function:    Object_CheckPyObject                                                                             */
1515 /* Description: This function returns true when the given PyObject is of the */
1516 /*                              type Object. Otherwise it will return false.                             */
1517 /*****************************************************************************/
1518 int Object_CheckPyObject (PyObject *py_obj)
1519 {
1520         return (py_obj->ob_type == &Object_Type);
1521 }
1522
1523 /*****************************************************************************/
1524 /* Function:    Object_FromPyObject                                                                                      */
1525 /* Description: This function returns the Blender object from the given          */
1526 /*                              PyObject.                                                                                                        */
1527 /*****************************************************************************/
1528 struct Object* Object_FromPyObject (PyObject *py_obj)
1529 {
1530         BPy_Object        * blen_obj;
1531
1532         blen_obj = (BPy_Object*)py_obj;
1533         return (blen_obj->object);
1534 }
1535
1536 /*****************************************************************************/
1537 /* Description: Returns the object with the name specified by the argument       */
1538 /*                              name. Note that the calling function has to remove the first */
1539 /*                              two characters of the object name. These two characters          */
1540 /*                              specify the type of the object (OB, ME, WO, ...)                         */
1541 /*                              The function will return NULL when no object with the given  */
1542 /*                              name is found.                                                                                           */
1543 /*****************************************************************************/
1544 Object * GetObjectByName (char * name)
1545 {
1546   Object  * obj_iter;
1547
1548   obj_iter = G.main->object.first;
1549   while (obj_iter)
1550   {
1551         if (StringEqual (name, GetIdName (&(obj_iter->id))))
1552         {
1553           return (obj_iter);
1554         }
1555         obj_iter = obj_iter->id.next;
1556   }
1557
1558   /* There is no object with the given name */
1559   return (NULL);
1560 }
1561
1562 /*****************************************************************************/
1563 /* Function:    Object_dealloc                                                                                           */
1564 /* Description: This is a callback function for the BlenObject type. It is       */
1565 /*                              the destructor function.                                                                         */
1566 /*****************************************************************************/
1567 static void Object_dealloc (BPy_Object *obj)
1568 {
1569         PyObject_DEL (obj);
1570 }
1571
1572 /*****************************************************************************/
1573 /* Function:    Object_getAttr                                                                                           */
1574 /* Description: This is a callback function for the BlenObject type. It is       */
1575 /*                              the function that retrieves any value from Blender and           */
1576 /*                              passes it to Python.                                                                             */
1577 /*****************************************************************************/
1578 static PyObject* Object_getAttr (BPy_Object *obj, char *name)
1579 {
1580         struct Object   * object;
1581         struct Ika              * ika;
1582
1583         object = obj->object;
1584         if (StringEqual (name, "LocX"))
1585                 return (PyFloat_FromDouble(object->loc[0]));
1586         if (StringEqual (name, "LocY"))
1587                 return (PyFloat_FromDouble(object->loc[1]));
1588         if (StringEqual (name, "LocZ"))
1589                 return (PyFloat_FromDouble(object->loc[2]));
1590         if (StringEqual (name, "loc"))
1591                 return (Py_BuildValue ("fff", object->loc[0], object->loc[1],
1592                                                            object->loc[2]));
1593         if (StringEqual (name, "dLocX"))
1594                 return (PyFloat_FromDouble(object->dloc[0]));
1595         if (StringEqual (name, "dLocY"))
1596                 return (PyFloat_FromDouble(object->dloc[1]));
1597         if (StringEqual (name, "dLocZ"))
1598                 return (PyFloat_FromDouble(object->dloc[2]));
1599         if (StringEqual (name, "dloc"))
1600                 return (Py_BuildValue ("fff", object->dloc[0], object->dloc[1],
1601                                                            object->dloc[2]));
1602         if (StringEqual (name, "RotX"))
1603                 return (PyFloat_FromDouble(object->rot[0]));
1604         if (StringEqual (name, "RotY"))
1605                 return (PyFloat_FromDouble(object->rot[1]));
1606         if (StringEqual (name, "RotZ"))
1607                 return (PyFloat_FromDouble(object->rot[2]));
1608         if (StringEqual (name, "rot"))
1609                 return (Py_BuildValue ("fff", object->rot[0], object->rot[1],
1610                                                            object->rot[2]));
1611         if (StringEqual (name, "dRotX"))
1612                 return (PyFloat_FromDouble(object->drot[0]));
1613         if (StringEqual (name, "dRotY"))
1614                 return (PyFloat_FromDouble(object->drot[1]));
1615         if (StringEqual (name, "dRotZ"))
1616                 return (PyFloat_FromDouble(object->drot[2]));
1617         if (StringEqual (name, "drot"))
1618                 return (Py_BuildValue ("fff", object->drot[0], object->drot[1],
1619                                                            object->drot[2]));
1620         if (StringEqual (name, "SizeX"))
1621                 return (PyFloat_FromDouble(object->size[0]));
1622         if (StringEqual (name, "SizeY"))
1623                 return (PyFloat_FromDouble(object->size[1]));
1624         if (StringEqual (name, "SizeZ"))
1625                 return (PyFloat_FromDouble(object->size[2]));
1626         if (StringEqual (name, "size"))
1627                 return (Py_BuildValue ("fff", object->size[0], object->size[1],
1628                                                            object->size[2]));
1629         if (StringEqual (name, "dSizeX"))
1630                 return (PyFloat_FromDouble(object->dsize[0]));
1631         if (StringEqual (name, "dSizeY"))
1632                 return (PyFloat_FromDouble(object->dsize[1]));
1633         if (StringEqual (name, "dSizeZ"))
1634                 return (PyFloat_FromDouble(object->dsize[2]));
1635         if (StringEqual (name, "dsize"))
1636                 return (Py_BuildValue ("fff", object->dsize[0], object->dsize[1],
1637                                                            object->dsize[2]));
1638         if (strncmp (name,"Eff", 3) == 0)
1639         {
1640                 if ( (object->type == OB_IKA) && (object->data != NULL) )
1641                 {
1642                         ika = object->data;
1643                         switch (name[3])
1644                         {
1645                                 case 'X':
1646                                         return (PyFloat_FromDouble (ika->effg[0]));
1647                                 case 'Y':
1648                                         return (PyFloat_FromDouble (ika->effg[1]));
1649                                 case 'Z':
1650                                         return (PyFloat_FromDouble (ika->effg[2]));
1651                                 default:
1652                                 /* Do we need to display a sensible error message here? */
1653                                         return (NULL);
1654                         }
1655                 }
1656                 return (NULL);
1657         }
1658         if (StringEqual (name, "Layer"))
1659           return (PyInt_FromLong(object->lay));
1660         if (StringEqual (name, "parent"))
1661         {
1662                 if (object->parent)
1663                         return (Object_CreatePyObject (object->parent));
1664                 else 
1665         {
1666           Py_INCREF (Py_None);
1667           return (Py_None);
1668         }
1669         }
1670
1671         if (StringEqual (name, "track"))
1672           return (Object_CreatePyObject (object->track));
1673         if (StringEqual (name, "data"))
1674           return (Object_getData (obj));
1675         if (StringEqual (name, "ipo"))
1676         {
1677                 if (object->ipo == NULL)
1678                 {
1679                         /* There's no ipo linked to the object, return Py_None. */
1680                         Py_INCREF (Py_None);
1681                         return (Py_None);
1682                 }
1683                 return (Ipo_CreatePyObject (object->ipo));
1684         }
1685         if (StringEqual (name, "mat"))
1686                 return (Object_getMatrix (obj));
1687         if (StringEqual (name, "matrix"))
1688                 return (Object_getMatrix (obj));
1689         if (StringEqual (name, "colbits"))
1690                 return (Py_BuildValue ("h", object->colbits));
1691         if (StringEqual (name, "drawType"))
1692                 return (Py_BuildValue ("b", object->dt));
1693         if (StringEqual (name, "drawMode"))
1694                 return (Py_BuildValue ("b", object->dtx));
1695         if (StringEqual (name, "name"))
1696                 return (Py_BuildValue ("s", object->id.name+2));
1697
1698         /* not an attribute, search the methods table */
1699         return Py_FindMethod(BPy_Object_methods, (PyObject *)obj, name);
1700 }
1701
1702 /*****************************************************************************/
1703 /* Function:    Object_setAttr                                                                                           */
1704 /* Description: This is a callback function for the BlenObject type. It is       */
1705 /*                              the function that retrieves any value from Python and sets       */
1706 /*                              it accordingly in Blender.                                                                       */
1707 /*****************************************************************************/
1708 static int Object_setAttr (BPy_Object *obj, char *name, PyObject *value)
1709 {
1710         PyObject                * valtuple;
1711         struct Object   * object;
1712         struct Ika              * ika;
1713
1714         /* First put the value(s) in a tuple. For some variables, we want to */
1715         /* pass the values to a function, and these functions only accept */
1716         /* PyTuples. */
1717         valtuple = Py_BuildValue ("(O)", value);
1718         if (!valtuple)
1719         {
1720                 return EXPP_ReturnIntError(PyExc_MemoryError,
1721                                                  "Object_setAttr: couldn't create PyTuple");
1722         }
1723
1724         object = obj->object;
1725         if (StringEqual (name, "LocX"))
1726                 return (!PyArg_Parse (value, "f", &(object->loc[0])));
1727         if (StringEqual (name, "LocY"))
1728                 return (!PyArg_Parse (value, "f", &(object->loc[1])));
1729         if (StringEqual (name, "LocZ"))
1730                 return (!PyArg_Parse (value, "f", &(object->loc[2])));
1731         if (StringEqual (name, "loc"))
1732         {
1733                 if (Object_setLocation (obj, valtuple) != Py_None)
1734                         return (-1);
1735                 else
1736                         return (0);
1737         }
1738         if (StringEqual (name, "dLocX"))
1739                 return (!PyArg_Parse (value, "f", &(object->dloc[0])));
1740         if (StringEqual (name, "dLocY"))
1741                 return (!PyArg_Parse (value, "f", &(object->dloc[1])));
1742         if (StringEqual (name, "dLocZ"))
1743                 return (!PyArg_Parse (value, "f", &(object->dloc[2])));
1744         if (StringEqual (name, "dloc"))
1745         {
1746                 if (Object_setDeltaLocation (obj, valtuple) != Py_None)
1747                         return (-1);
1748                 else
1749                         return (0);
1750         }
1751         if (StringEqual (name, "RotX"))
1752                 return (!PyArg_Parse (value, "f", &(object->rot[0])));
1753         if (StringEqual (name, "RotY"))
1754                 return (!PyArg_Parse (value, "f", &(object->rot[1])));
1755         if (StringEqual (name, "RotZ"))
1756                 return (!PyArg_Parse (value, "f", &(object->rot[2])));
1757         if (StringEqual (name, "rot"))
1758         {
1759                 if (Object_setEuler (obj, valtuple) != Py_None)
1760                         return (-1);
1761                 else
1762                         return (0);
1763         }
1764         if (StringEqual (name, "dRotX"))
1765                 return (!PyArg_Parse (value, "f", &(object->drot[0])));
1766         if (StringEqual (name, "dRotY"))
1767                 return (!PyArg_Parse (value, "f", &(object->drot[1])));
1768         if (StringEqual (name, "dRotZ"))
1769                 return (!PyArg_Parse (value, "f", &(object->drot[2])));
1770         if (StringEqual (name, "drot"))
1771                 return (!PyArg_ParseTuple (value, "fff", &(object->drot[0]),
1772                                                           &(object->drot[1]), &(object->drot[2])));
1773         if (StringEqual (name, "SizeX"))
1774                 return (!PyArg_Parse (value, "f", &(object->size[0])));
1775         if (StringEqual (name, "SizeY"))
1776                 return (!PyArg_Parse (value, "f", &(object->size[1])));
1777         if (StringEqual (name, "SizeZ"))
1778                 return (!PyArg_Parse (value, "f", &(object->size[2])));
1779         if (StringEqual (name, "size"))
1780                 return (!PyArg_ParseTuple  (value, "fff", &(object->size[0]),
1781                                                           &(object->size[1]), &(object->size[2])));
1782         if (StringEqual (name, "dSizeX"))
1783                 return (!PyArg_Parse (value, "f", &(object->dsize[0])));
1784         if (StringEqual (name, "dSizeY"))
1785                 return (!PyArg_Parse (value, "f", &(object->dsize[1])));
1786         if (StringEqual (name, "dSizeZ"))
1787                 return (!PyArg_Parse (value, "f", &(object->dsize[2])));
1788         if (StringEqual (name, "dsize"))
1789                 return (!PyArg_ParseTuple  (value, "fff", &(object->dsize[0]),
1790                                                           &(object->dsize[1]), &(object->dsize[2])));
1791         if (strncmp (name,"Eff", 3) == 0)
1792         {
1793                 if ( (object->type == OB_IKA) && (object->data != NULL) )
1794                 {
1795                         ika = object->data;
1796                         switch (name[3])
1797                         {
1798                                 case 'X':
1799                                         return (!PyArg_Parse (value, "f", &(ika->effg[0])));
1800                                 case 'Y':
1801                                         return (!PyArg_Parse (value, "f", &(ika->effg[1])));
1802                                 case 'Z':
1803                                         return (!PyArg_Parse (value, "f", &(ika->effg[2])));
1804                                 default:
1805                                         /* Do we need to display a sensible error message here? */
1806                                         return (0);
1807                         }
1808                 }
1809                 return (0);
1810         }
1811         if (StringEqual (name, "Layer"))
1812                 return (!PyArg_Parse (value, "i", &(object->lay)));
1813         if (StringEqual (name, "parent"))
1814         {
1815                 /* This is not allowed. */
1816                 PythonReturnErrorObject (PyExc_AttributeError,
1817                                         "Setting the parent is not allowed.");
1818                 return (0);
1819         }
1820         if (StringEqual (name, "track"))
1821         {
1822                 /* This is not allowed. */
1823                 PythonReturnErrorObject (PyExc_AttributeError,
1824                                         "Setting the track is not allowed.");
1825                 return (0);
1826         }
1827         if (StringEqual (name, "data"))
1828         {
1829                 /* This is not allowed. */
1830                 PythonReturnErrorObject (PyExc_AttributeError,
1831                                         "Setting the data is not allowed.");
1832                 return (0);
1833         }
1834         if (StringEqual (name, "ipo"))
1835         {
1836                 /* This is not allowed. */
1837                 PythonReturnErrorObject (PyExc_AttributeError,
1838                                         "Setting the ipo is not allowed.");
1839                 return (0);
1840         }
1841         if (StringEqual (name, "mat"))
1842         {
1843                 /* This is not allowed. */
1844                 PythonReturnErrorObject (PyExc_AttributeError,
1845                                         "Setting the matrix is not allowed.");
1846                 return (0);
1847         }
1848         if (StringEqual (name, "matrix"))
1849         {
1850                 /* This is not allowed. */
1851                 PythonReturnErrorObject (PyExc_AttributeError,
1852                                         "Please use .setMatrix(matrix)");
1853                 return (0);
1854         }
1855         if (StringEqual (name, "colbits"))
1856                 return (!PyArg_Parse (value, "h", &(object->colbits)));
1857         if (StringEqual (name, "drawType"))
1858         {
1859                 if (Object_setDrawType (obj, valtuple) != Py_None)
1860                         return (-1);
1861                 else
1862                         return (0);
1863         }
1864         if (StringEqual (name, "drawMode"))
1865         {
1866                 if (Object_setDrawMode (obj, valtuple) != Py_None)
1867                         return (-1);
1868                 else
1869                         return (0);
1870         }
1871         if (StringEqual (name, "name"))
1872         {
1873                 if (Object_setName (obj, valtuple) != Py_None)
1874                         return (-1);
1875                 else
1876                         return (0);
1877         }
1878
1879         printf ("Unknown variable.\n");
1880         return (0);
1881 }
1882
1883 /*****************************************************************************/
1884 /* Function:    Object_compare                                                                                           */
1885 /* Description: This is a callback function for the BPy_Object type. It          */
1886 /*                              compares two Object_Type objects. Only the "==" and "!="         */
1887 /*                              comparisons are meaninful. Returns 0 for equality and -1 if  */
1888 /*                              they don't point to the same Blender Object struct.                      */
1889 /*                              In Python it becomes 1 if they are equal, 0 otherwise.           */
1890 /*****************************************************************************/
1891 static int Object_compare (BPy_Object *a, BPy_Object *b)
1892 {
1893   Object *pa = a->object, *pb = b->object;
1894   return (pa == pb) ? 0:-1;
1895 }
1896
1897 /*****************************************************************************/
1898 /* Function:    Object_repr                                                                                                      */
1899 /* Description: This is a callback function for the BPy_Object type. It          */
1900 /*                              builds a meaninful string to represent object objects.           */
1901 /*****************************************************************************/
1902 static PyObject *Object_repr (BPy_Object *self)
1903 {
1904   return PyString_FromFormat("[Object \"%s\"]", self->object->id.name+2);
1905 }
1906