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