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