New Bpy type Text3d for accessing Blender's Font objects.
[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 <BKE_font.h>
49 #include <BIF_editview.h>
50
51 #include "Ipo.h"
52 #include "Lattice.h"
53 #include "modules.h"
54
55 /* only used for oops location get/set at the moment */
56 #include "DNA_oops_types.h" 
57 #include "DNA_space_types.h"
58
59 /*****************************************************************************/
60 /* Python API function prototypes for the Blender module.                */
61 /*****************************************************************************/
62 static PyObject *M_Object_New( PyObject * self, PyObject * args );
63 PyObject *M_Object_Get( PyObject * self, PyObject * args );
64 static PyObject *M_Object_GetSelected( PyObject * self, PyObject * args );
65
66 /*****************************************************************************/
67 /* The following string definitions are used for documentation strings.  */
68 /* In Python these will be written to the console when doing a           */
69 /* Blender.Object.__doc__                                                */
70 /*****************************************************************************/
71 char M_Object_doc[] = "The Blender Object module\n\n\
72 This module provides access to **Object Data** in Blender.\n";
73
74 char M_Object_New_doc[] =
75         "(type) - Add a new object of type 'type' in the current scene";
76
77 char M_Object_Get_doc[] =
78         "(name) - return the object with the name 'name', returns None if not\
79         found.\n\
80         If 'name' is not specified, it returns a list of all objects in the\n\
81         current scene.";
82
83 char M_Object_GetSelected_doc[] =
84         "() - Returns a list of selected Objects in the active layer(s)\n\
85 The active object is the first in the list, if visible";
86
87 /*****************************************************************************/
88 /* Python method structure definition for Blender.Object module:         */
89 /*****************************************************************************/
90 struct PyMethodDef M_Object_methods[] = {
91         {"New", ( PyCFunction ) M_Object_New, METH_VARARGS,
92          M_Object_New_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         {NULL, NULL, 0, NULL}
98 };
99
100 /*****************************************************************************/
101 /* Python BPy_Object methods declarations:                                 */
102 /*****************************************************************************/
103 static PyObject *Object_buildParts( BPy_Object * self );
104 static PyObject *Object_clearIpo( BPy_Object * self );
105 static PyObject *Object_clrParent( BPy_Object * self, PyObject * args );
106 static PyObject *Object_clearTrack( BPy_Object * self, PyObject * args );
107 static PyObject *Object_getData(BPy_Object *self, PyObject *a, PyObject *kwd);
108 static PyObject *Object_getDeltaLocation( BPy_Object * self );
109 static PyObject *Object_getDrawMode( BPy_Object * self );
110 static PyObject *Object_getDrawType( BPy_Object * self );
111 static PyObject *Object_getEuler( BPy_Object * self );
112 static PyObject *Object_getInverseMatrix( BPy_Object * self );
113 static PyObject *Object_getIpo( BPy_Object * self );
114 static PyObject *Object_getLocation( BPy_Object * self, PyObject * args );
115 static PyObject *Object_getMaterials( BPy_Object * self, PyObject * args );
116 static PyObject *Object_getMatrix( BPy_Object * self, PyObject * args );
117 static PyObject *Object_getName( BPy_Object * self );
118 static PyObject *Object_getParent( BPy_Object * self );
119 static PyObject *Object_getSize( BPy_Object * self, PyObject * args );
120 static PyObject *Object_getTimeOffset( BPy_Object * self );
121 static PyObject *Object_getTracked( BPy_Object * self );
122 static PyObject *Object_getType( BPy_Object * self );
123 static PyObject *Object_getBoundBox( BPy_Object * self );
124 static PyObject *Object_getAction( BPy_Object * self );
125 static PyObject *Object_isSelected( BPy_Object * self );
126 static PyObject *Object_makeDisplayList( BPy_Object * self );
127 static PyObject *Object_link( BPy_Object * self, PyObject * args );
128 static PyObject *Object_makeParent( BPy_Object * self, PyObject * args );
129 static PyObject *Object_materialUsage( BPy_Object * self, PyObject * args );
130 static PyObject *Object_setDeltaLocation( BPy_Object * self, PyObject * args );
131 static PyObject *Object_setDrawMode( BPy_Object * self, PyObject * args );
132 static PyObject *Object_setDrawType( BPy_Object * self, PyObject * args );
133 static PyObject *Object_setEuler( BPy_Object * self, PyObject * args );
134 static PyObject *Object_setMatrix( BPy_Object * self, PyObject * args );
135 static PyObject *Object_setIpo( BPy_Object * self, PyObject * args );
136 static PyObject *Object_setLocation( BPy_Object * self, PyObject * args );
137 static PyObject *Object_setMaterials( BPy_Object * self, PyObject * args );
138 static PyObject *Object_setName( BPy_Object * self, PyObject * args );
139 static PyObject *Object_setSize( BPy_Object * self, PyObject * args );
140 static PyObject *Object_setTimeOffset( BPy_Object * self, PyObject * args );
141 static PyObject *Object_makeTrack( BPy_Object * self, PyObject * args );
142 static PyObject *Object_shareFrom( BPy_Object * self, PyObject * args );
143 static PyObject *Object_Select( BPy_Object * self, PyObject * args );
144 static PyObject *Object_getAllProperties( BPy_Object * self );
145 static PyObject *Object_addProperty( BPy_Object * self, PyObject * args );
146 static PyObject *Object_removeProperty( BPy_Object * self, PyObject * args );
147 static PyObject *Object_getProperty( BPy_Object * self, PyObject * args );
148 static PyObject *Object_removeAllProperties( BPy_Object * self );
149 static PyObject *Object_copyAllPropertiesTo( BPy_Object * self,
150                                              PyObject * args );
151 static PyObject *Object_getScriptLinks( BPy_Object * self, PyObject * args );
152 static PyObject *Object_addScriptLink( BPy_Object * self, PyObject * args );
153 static PyObject *Object_clearScriptLinks( BPy_Object * self );
154 /* fixme: save for separate commit. 06-mar-05
155 static PyObject *Object_setDupliVerts ( 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_VARARGS | METH_KEYWORDS,
175          "(name_only = 0) - Returns the datablock object containing the object's \
176 data, e.g. Mesh.\n\
177 If 'name_only' is nonzero or True, only the name of the datablock is returned"},
178         {"getDeltaLocation", ( PyCFunction ) Object_getDeltaLocation,
179          METH_NOARGS,
180          "Returns the object's delta location (x, y, z)"},
181         {"getDrawMode", ( PyCFunction ) Object_getDrawMode, METH_NOARGS,
182          "Returns the object draw modes"},
183         {"getDrawType", ( PyCFunction ) Object_getDrawType, METH_NOARGS,
184          "Returns the object draw type"},
185         {"getAction", ( PyCFunction ) Object_getAction, METH_NOARGS,
186          "Returns the active action for this object"},
187         {"isSelected", ( PyCFunction ) Object_isSelected, METH_NOARGS,
188          "Return a 1 or 0 depending on whether the object is selected"},
189         {"getEuler", ( PyCFunction ) Object_getEuler, METH_NOARGS,
190          "Returns the object's rotation as Euler rotation vector\n\
191 (rotX, rotY, rotZ)"},
192         {"getInverseMatrix", ( PyCFunction ) Object_getInverseMatrix,
193          METH_NOARGS,
194          "Returns the object's inverse matrix"},
195         {"getLocation", ( PyCFunction ) Object_getLocation, METH_VARARGS,
196          "Returns the object's location (x, y, z)"},
197         {"getMaterials", ( PyCFunction ) Object_getMaterials, METH_VARARGS,
198          "(i = 0) - Returns list of materials assigned to the object.\n\
199 if i is nonzero, empty slots are not ignored: they are returned as None's."},
200         {"getMatrix", ( PyCFunction ) Object_getMatrix, METH_VARARGS,
201          "(str = 'worldspace') - Returns the object matrix.\n\
202 (str = 'worldspace') - the wanted matrix: worldspace (default), localspace\n\
203 or old_worldspace.\n\
204 \n\
205 'old_worldspace' was the only behavior before Blender 2.34.  With it the\n\
206 matrix is not updated for changes made by the script itself\n\
207 (like obj.LocX = 10) until a redraw happens, either called by the script or\n\
208 automatic when the script finishes."},
209         {"getName", ( PyCFunction ) Object_getName, METH_NOARGS,
210          "Returns the name of the object"},
211         {"getParent", ( PyCFunction ) Object_getParent, METH_NOARGS,
212          "Returns the object's parent object"},
213         {"getSize", ( PyCFunction ) Object_getSize, METH_VARARGS,
214          "Returns the object's size (x, y, z)"},
215         {"getTimeOffset", ( PyCFunction ) Object_getTimeOffset, METH_NOARGS,
216          "Returns the object's time offset"},
217         {"getTracked", ( PyCFunction ) Object_getTracked, METH_NOARGS,
218          "Returns the object's tracked object"},
219         {"getType", ( PyCFunction ) Object_getType, METH_NOARGS,
220          "Returns type of string of Object"},
221         {"getBoundBox", ( PyCFunction ) Object_getBoundBox, METH_NOARGS,
222          "Returns the object's bounding box"},
223         {"makeDisplayList", ( PyCFunction ) Object_makeDisplayList,
224          METH_NOARGS,
225          "Update this object's Display List. Some changes like turning \n\
226 'SubSurf' on for a mesh need this method (followed by a Redraw) to \n\
227 show the changes on the 3d window."},
228         {"link", ( PyCFunction ) Object_link, METH_VARARGS,
229          "Links Object with data provided in the argument. The data must \n\
230 match the Object's type, so you cannot link a Lamp to a Mesh type object."},
231         {"makeParent", ( PyCFunction ) Object_makeParent, METH_VARARGS,
232          "Makes the object the parent of the objects provided in the \n\
233 argument which must be a list of valid Objects. Optional extra arguments:\n\
234 mode:\n\t0: make parent with inverse\n\t1: without inverse\n\
235 fast:\n\t0: update scene hierarchy automatically\n\t\
236 don't update scene hierarchy (faster). In this case, you must\n\t\
237 explicitely update the Scene hierarchy."},
238         {"materialUsage", ( PyCFunction ) Object_materialUsage, METH_VARARGS,
239          "Determines the way the material is used and returns status.\n\
240 Possible arguments (provide as strings):\n\
241 \tData:   Materials assigned to the object's data are shown. (default)\n\
242 \tObject: Materials assigned to the object are shown."},
243         {"setDeltaLocation", ( PyCFunction ) Object_setDeltaLocation,
244          METH_VARARGS,
245          "Sets the object's delta location which must be a vector triple."},
246         {"setDrawMode", ( PyCFunction ) Object_setDrawMode, METH_VARARGS,
247          "Sets the object's drawing mode. The argument can be a sum of:\n\
248 2:      axis\n4:  texspace\n8:  drawname\n16: drawimage\n32: drawwire"},
249         {"setDrawType", ( PyCFunction ) Object_setDrawType, METH_VARARGS,
250          "Sets the object's drawing type. The argument must be one of:\n\
251 1: Bounding box\n2: Wire\n3: Solid\n4: Shaded\n5: Textured"},
252         {"setEuler", ( PyCFunction ) Object_setEuler, METH_VARARGS,
253          "Set the object's rotation according to the specified Euler\n\
254 angles. The argument must be a vector triple"},
255         {"setMatrix", ( PyCFunction ) Object_setMatrix, METH_VARARGS,
256          "Set and apply a new matrix for the object"},
257         {"setLocation", ( PyCFunction ) Object_setLocation, METH_VARARGS,
258          "Set the object's location. The first argument must be a vector\n\
259 triple."},
260         {"setMaterials", ( PyCFunction ) Object_setMaterials, METH_VARARGS,
261          "Sets materials. The argument must be a list of valid material\n\
262 objects."},
263         {"setName", ( PyCFunction ) Object_setName, METH_VARARGS,
264          "Sets the name of the object"},
265         {"setSize", ( PyCFunction ) Object_setSize, METH_VARARGS,
266          "Set the object's size. The first argument must be a vector\n\
267 triple."},
268         {"setTimeOffset", ( PyCFunction ) Object_setTimeOffset, METH_VARARGS,
269          "Set the object's time offset."},
270         {"makeTrack", ( PyCFunction ) Object_makeTrack, METH_VARARGS,
271          "(trackedobj, fast = 0) - Make this object track another.\n\
272          (trackedobj) - the object that will be tracked.\n\
273          (fast = 0) - if 0: update the scene hierarchy automatically.  If you\n\
274          set 'fast' to a nonzero value, don't forget to update the scene yourself\n\
275          (see scene.update())."},
276         {"shareFrom", ( PyCFunction ) Object_shareFrom, METH_VARARGS,
277          "Link data of self with object specified in the argument. This\n\
278 works only if self and the object specified are of the same type."},
279         {"select", ( PyCFunction ) Object_Select, METH_VARARGS,
280          "( 1 or 0 )  - Set the selected state of the object.\n\
281    1 is selected, 0 not selected "},
282         {"setIpo", ( PyCFunction ) Object_setIpo, METH_VARARGS,
283          "(Blender Ipo) - Sets the object's ipo"},
284         {"clearIpo", ( PyCFunction ) Object_clearIpo, METH_NOARGS,
285          "() - Unlink ipo from this object"},
286         {"getAllProperties", ( PyCFunction ) Object_getAllProperties,
287          METH_NOARGS,
288          "() - Get all the properties from this object"},
289         {"addProperty", ( PyCFunction ) Object_addProperty, METH_VARARGS,
290          "() - Add a property to this object"},
291         {"removeProperty", ( PyCFunction ) Object_removeProperty, METH_VARARGS,
292          "() - Remove a property from  this object"},
293         {"getProperty", ( PyCFunction ) Object_getProperty, METH_VARARGS,
294          "() - Get a property from this object by name"},
295         {"removeAllProperties", ( PyCFunction ) Object_removeAllProperties,
296          METH_NOARGS,
297          "() - removeAll a properties from this object"},
298         {"copyAllPropertiesTo", ( PyCFunction ) Object_copyAllPropertiesTo,
299          METH_VARARGS,
300          "() - copy all properties from this object to another object"},
301         {"getScriptLinks", ( PyCFunction ) Object_getScriptLinks, METH_VARARGS,
302          "(eventname) - Get a list of this object's scriptlinks (Text names) "
303          "of the given type\n"
304          "(eventname) - string: FrameChanged or Redraw."},
305         {"addScriptLink", ( PyCFunction ) Object_addScriptLink, METH_VARARGS,
306          "(text, evt) - Add a new object scriptlink.\n"
307          "(text) - string: an existing Blender Text name;\n"
308          "(evt) string: FrameChanged or Redraw."},
309         {"clearScriptLinks", ( PyCFunction ) Object_clearScriptLinks,
310          METH_NOARGS,
311          "() - Delete all scriptlinks from this object."},
312 #if 0
313 /* fixme:save for separate commit. 6-mar-05 stivs */
314         {"setDupliVerts", ( PyCFunction ) Object_setDupliVerts,
315          METH_NOARGS,
316          "() - setDupliVerts."},
317 #endif
318         {NULL, NULL, 0, NULL}
319 };
320
321 /*****************************************************************************/
322 /* PythonTypeObject callback function prototypes                         */
323 /*****************************************************************************/
324 static void Object_dealloc( BPy_Object * obj );
325 static PyObject *Object_getAttr( BPy_Object * obj, char *name );
326 static int Object_setAttr( BPy_Object * obj, char *name, PyObject * v );
327 static PyObject *Object_repr( BPy_Object * obj );
328 static int Object_compare( BPy_Object * a, BPy_Object * b );
329
330 /*****************************************************************************/
331 /* Python TypeObject structure definition.                               */
332 /*****************************************************************************/
333 PyTypeObject Object_Type = {
334         PyObject_HEAD_INIT( NULL ) /* requred macro */
335         0,      /* ob_size */
336         "Blender Object",       /* tp_name */
337         sizeof( BPy_Object ),   /* tp_basicsize */
338         0,                      /* tp_itemsize */
339         /* methods */
340         ( destructor ) Object_dealloc,  /* tp_dealloc */
341         0,                      /* tp_print */
342         ( getattrfunc ) Object_getAttr, /* tp_getattr */
343         ( setattrfunc ) Object_setAttr, /* tp_setattr */
344         ( cmpfunc ) Object_compare,     /* tp_compare */
345         ( reprfunc ) Object_repr,       /* tp_repr */
346         0,                      /* tp_as_number */
347         0,                      /* tp_as_sequence */
348         0,                      /* tp_as_mapping */
349         0,                      /* tp_as_hash */
350         0, 0, 0, 0, 0, 0,
351         0,                      /* tp_doc */
352         0, 0, 0, 0, 0, 0,
353         BPy_Object_methods,     /* tp_methods */
354         0,                      /* tp_members */
355         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
356 };
357
358 /*****************************************************************************/
359 /* Function:                      M_Object_New                           */
360 /* Python equivalent:     Blender.Object.New                             */
361 /*****************************************************************************/
362 PyObject *M_Object_New( PyObject * self, PyObject * args )
363 {
364         struct Object *object;
365         BPy_Object *blen_object;
366         int type;
367         char *str_type;
368         char *name = NULL;
369
370         if( !PyArg_ParseTuple( args, "s|s", &str_type, &name ) ) {
371                 EXPP_ReturnPyObjError( PyExc_TypeError,
372                                        "string expected as argument" );
373                 return ( NULL );
374         }
375
376         if( strcmp( str_type, "Armature" ) == 0 )
377                 type = OB_ARMATURE;
378         else if( strcmp( str_type, "Camera" ) == 0 )
379                 type = OB_CAMERA;
380         else if( strcmp( str_type, "Curve" ) == 0 )
381                 type = OB_CURVE;
382         else if (strcmp (str_type, "Text") == 0)        
383                 type = OB_FONT;
384 /*      else if (strcmp (str_type, "Ika") == 0)         type = OB_IKA; */
385         else if( strcmp( str_type, "Lamp" ) == 0 )
386                 type = OB_LAMP;
387         else if( strcmp( str_type, "Lattice" ) == 0 )
388                 type = OB_LATTICE;
389         else if( strcmp( str_type, "Mball" ) == 0 )
390                 type = OB_MBALL;
391         else if( strcmp( str_type, "Mesh" ) == 0 )
392                 type = OB_MESH;
393         else if( strcmp( str_type, "Surf" ) == 0 )
394                 type = OB_SURF;
395 /*      else if (strcmp (str_type, "Wave") == 0)        type = OB_WAVE; */
396         else if( strcmp( str_type, "Empty" ) == 0 )
397                 type = OB_EMPTY;
398         else {
399                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
400                                                 "Unknown type specified" ) );
401         }
402
403         /* Create a new object. */
404         if( name == NULL ) {
405         /* No name is specified, set the name to the type of the object. */
406                 name = str_type;
407         }
408         object = alloc_libblock( &( G.main->object ), ID_OB, name );
409
410         object->id.us = 0;
411         object->flag = 0;
412         object->type = type;
413
414
415         /* transforms */
416         QuatOne( object->quat );
417         QuatOne( object->dquat );
418
419         object->col[3] = 1.0;   // alpha 
420
421         object->size[0] = object->size[1] = object->size[2] = 1.0;
422         object->loc[0] = object->loc[1] = object->loc[2] = 0.0;
423         Mat4One( object->parentinv );
424         Mat4One( object->obmat );
425         object->dt = OB_SHADED; // drawtype
426
427         if( U.flag & USER_MAT_ON_OB ) {
428                 object->colbits = -1;
429         }
430         switch ( object->type ) {
431         case OB_CAMERA: /* fall through. */
432         case OB_LAMP:
433                 object->trackflag = OB_NEGZ;
434                 object->upflag = OB_POSY;
435                 break;
436         default:
437                 object->trackflag = OB_POSY;
438                 object->upflag = OB_POSZ;
439         }
440         object->ipoflag = OB_OFFS_OB + OB_OFFS_PARENT;
441
442         /* duplivert settings */
443         object->dupon = 1;
444         object->dupoff = 0;
445         object->dupsta = 1;
446         object->dupend = 100;
447
448         /* Gameengine defaults */
449         object->mass = 1.0;
450         object->inertia = 1.0;
451         object->formfactor = 0.4;
452         object->damping = 0.04;
453         object->rdamping = 0.1;
454         object->anisotropicFriction[0] = 1.0;
455         object->anisotropicFriction[1] = 1.0;
456         object->anisotropicFriction[2] = 1.0;
457         object->gameflag = OB_PROP;
458
459         object->lay = 1;        // Layer, by default visible
460         G.totobj++;
461
462         object->data = NULL;
463
464         /* Create a Python object from it. */
465         blen_object =
466                 ( BPy_Object * ) PyObject_NEW( BPy_Object, &Object_Type );
467         blen_object->object = object;
468
469         return ( ( PyObject * ) blen_object );
470 }
471
472 /*****************************************************************************/
473 /* Function:      M_Object_Get                                          */
474 /* Python equivalent:     Blender.Object.Get                            */
475 /*****************************************************************************/
476 PyObject *M_Object_Get( PyObject * self, PyObject * args )
477 {
478         struct Object *object;
479         BPy_Object *blen_object;
480         char *name = NULL;
481
482         PyArg_ParseTuple( args, "|s", &name );
483
484         if( name != NULL ) {
485                 object = GetObjectByName( name );
486
487                 if( object == NULL ) {
488                         /* No object exists with the name specified in the argument name. */
489                         return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
490                                                         "Unknown object specified." ) );
491                 }
492                 blen_object =
493                         ( BPy_Object * ) PyObject_NEW( BPy_Object,
494                                                        &Object_Type );
495                 blen_object->object = object;
496
497                 return ( ( PyObject * ) blen_object );
498         } else {
499                 /* No argument has been given. Return a list of all objects. */
500                 PyObject *obj_list;
501                 Link *link;
502                 int index;
503
504                 obj_list = PyList_New( BLI_countlist( &( G.main->object ) ) );
505
506                 if( obj_list == NULL ) {
507                         return ( EXPP_ReturnPyObjError( PyExc_SystemError,
508                                                         "List creation failed." ) );
509                 }
510
511                 link = G.main->object.first;
512                 index = 0;
513                 while( link ) {
514                         object = ( Object * ) link;
515                         blen_object =
516                                 ( BPy_Object * ) PyObject_NEW( BPy_Object,
517                                                                &Object_Type );
518                         blen_object->object = object;
519
520                         PyList_SetItem( obj_list, index,
521                                         ( PyObject * ) blen_object );
522                         index++;
523                         link = link->next;
524                 }
525                 return ( obj_list );
526         }
527 }
528
529 /*****************************************************************************/
530 /* Function:      M_Object_GetSelected                          */
531 /* Python equivalent:     Blender.Object.GetSelected            */
532 /*****************************************************************************/
533 static PyObject *M_Object_GetSelected( PyObject * self, PyObject * args )
534 {
535         BPy_Object *blen_object;
536         PyObject *list;
537         Base *base_iter;
538
539         if( G.vd == NULL ) {
540                 // No 3d view has been initialized yet, simply return None
541                 Py_INCREF( Py_None );
542                 return Py_None;
543         }
544         list = PyList_New( 0 );
545         if( ( G.scene->basact ) &&
546             ( ( G.scene->basact->flag & SELECT ) &&
547               ( G.scene->basact->lay & G.vd->lay ) ) ) {
548                 /* Active object is first in the list. */
549                 blen_object =
550                         ( BPy_Object * ) PyObject_NEW( BPy_Object,
551                                                        &Object_Type );
552                 if( blen_object == NULL ) {
553                         Py_DECREF( list );
554                         Py_INCREF( Py_None );
555                         return ( Py_None );
556                 }
557                 blen_object->object = G.scene->basact->object;
558                 PyList_Append( list, ( PyObject * ) blen_object );
559                 Py_DECREF( blen_object );
560         }
561
562         base_iter = G.scene->base.first;
563         while( base_iter ) {
564                 if( ( ( base_iter->flag & SELECT ) &&
565                       ( base_iter->lay & G.vd->lay ) ) &&
566                     ( base_iter != G.scene->basact ) ) {
567                         blen_object =
568                                 ( BPy_Object * ) PyObject_NEW( BPy_Object,
569                                                                &Object_Type );
570                         if( blen_object == NULL ) {
571                                 Py_DECREF( list );
572                                 Py_INCREF( Py_None );
573                                 return ( Py_None );
574                         }
575                         blen_object->object = base_iter->object;
576                         PyList_Append( list, ( PyObject * ) blen_object );
577                         Py_DECREF( blen_object );
578                 }
579                 base_iter = base_iter->next;
580         }
581         return ( list );
582 }
583
584 /*****************************************************************************/
585 /* Function:     initObject                                             */
586 /*****************************************************************************/
587 PyObject *Object_Init( void )
588 {
589         PyObject *module;
590
591         Object_Type.ob_type = &PyType_Type;
592
593         module = Py_InitModule3( "Blender.Object", M_Object_methods,
594                                  M_Object_doc );
595
596         return ( module );
597 }
598
599 /*****************************************************************************/
600 /* Python BPy_Object methods:                                   */
601 /*****************************************************************************/
602
603 static PyObject *Object_buildParts( BPy_Object * self )
604 {
605         void build_particle_system( Object * ob );
606         struct Object *obj = self->object;
607
608         build_particle_system( obj );
609
610         Py_INCREF( Py_None );
611         return ( Py_None );
612 }
613
614 static PyObject *Object_clearIpo( BPy_Object * self )
615 {
616         Object *ob = self->object;
617         Ipo *ipo = ( Ipo * ) ob->ipo;
618
619         if( ipo ) {
620                 ID *id = &ipo->id;
621                 if( id->us > 0 )
622                         id->us--;
623                 ob->ipo = NULL;
624
625                 return EXPP_incr_ret_True();
626         }
627
628         return EXPP_incr_ret_False(); /* no ipo found */
629 }
630
631 static PyObject *Object_clrParent( BPy_Object * self, PyObject * args )
632 {
633         int mode = 0;
634         int fast = 0;
635
636         if( !PyArg_ParseTuple( args, "|ii", &mode, &fast ) ) {
637                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
638                                                 "expected one or two integers as arguments" ) );
639         }
640
641         /* Remove the link only, the object is still in the scene. */
642         self->object->parent = NULL;
643
644         if( mode == 2 ) {
645                 /* Keep transform */
646                 apply_obmat( self->object );
647         }
648
649         if( !fast ) {
650                 sort_baselist( G.scene );
651         }
652
653         Py_INCREF( Py_None );
654         return ( Py_None );
655 }
656
657 static PyObject *Object_clearTrack( BPy_Object * self, PyObject * args )
658 {
659         int mode = 0;
660         int fast = 0;
661
662         if( !PyArg_ParseTuple( args, "|ii", &mode, &fast ) ) {
663                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
664                                                 "expected one or two integers as arguments" ) );
665         }
666
667         /* Remove the link only, the object is still in the scene. */
668         self->object->track = NULL;
669
670         if( mode ) {
671                 /* Keep transform */
672                 apply_obmat( self->object );
673         }
674
675         if( !fast ) {
676                 sort_baselist( G.scene );
677         }
678
679         Py_INCREF( Py_None );
680         return ( Py_None );
681 }
682
683 /* adds object data to a Blender object, if object->data = NULL */
684 int EXPP_add_obdata( struct Object *object )
685 {
686         if( object->data != NULL )
687                 return -1;
688
689         switch ( object->type ) {
690         case OB_ARMATURE:
691                 /* TODO: Do we need to add something to G? (see the OB_LAMP case) */
692                 object->data = add_armature(  );
693                 break;
694         case OB_CAMERA:
695                 /* TODO: Do we need to add something to G? (see the OB_LAMP case) */
696                 object->data = add_camera(  );
697                 break;
698         case OB_CURVE:
699                 object->data = add_curve( OB_CURVE );
700                 G.totcurve++;
701                 break;
702         case OB_LAMP:
703                 object->data = add_lamp(  );
704                 G.totlamp++;
705                 break;
706         case OB_MESH:
707                 object->data = add_mesh(  );
708                 G.totmesh++;
709                 break;
710         case OB_LATTICE:
711                 object->data = ( void * ) add_lattice(  );
712                 object->dt = OB_WIRE;
713                 break;
714         case OB_MBALL:
715                 object->data = add_mball(  );
716                 break;
717
718                 /* TODO the following types will be supported later
719                    case OB_SURF:
720                    object->data = add_curve(OB_SURF);
721                    G.totcurve++;
722                    break;
723                    case OB_FONT:
724                    object->data = add_curve(OB_FONT);
725                    break;
726                    case OB_IKA:
727                    object->data = add_ika();
728                    object->dt = OB_WIRE;
729                    break;
730                    case OB_WAVE:
731                    object->data = add_wave();
732                    break;
733                  */
734         default:
735                 break;
736         }
737
738         if( !object->data )
739                 return -1;
740
741         return 0;
742 }
743
744
745 static PyObject *Object_getData( BPy_Object *self, PyObject *a, PyObject *kwd )
746 {
747         PyObject *data_object;
748         Object *object = self->object;
749         int name_only = 0;
750         static char *kwlist[] = {"name_only", NULL};
751
752         if (!PyArg_ParseTupleAndKeywords(a, kwd, "|i", kwlist, &name_only))
753                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
754                         "expected nothing or an int (keyword 'name_only') as argument" );
755
756         /* if there's no obdata, try to create it */
757         if( object->data == NULL ) {
758                 if( EXPP_add_obdata( object ) != 0 ) {  /* couldn't create obdata */
759                         Py_INCREF( Py_None );
760                         return ( Py_None );
761                 }
762         }
763
764         /* user wants only the name of the data object */
765         if (name_only) {
766                 ID *id = object->data;
767                 data_object = Py_BuildValue("s", id->name+2);
768
769                 if (data_object) return data_object;
770                 return EXPP_ReturnPyObjError (PyExc_MemoryError,
771                         "could not create a string pyobject!");
772         }
773
774         /* user wants the data object wrapper */
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                                 return EXPP_incr_ret_True();
872                         } else {
873                                 return EXPP_incr_ret_False();
874                         }
875                 }
876                 base = base->next;
877         }
878         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
879                                         "Internal error: could not find objects selection state" ) );
880 }
881
882
883 static PyObject *Object_getDrawType( BPy_Object * self )
884 {
885         PyObject *attr = Py_BuildValue( "b", self->object->dt );
886
887         if( attr )
888                 return ( attr );
889
890         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
891                                         "couldn't get Object.drawType attribute" ) );
892 }
893
894 static PyObject *Object_getEuler( BPy_Object * self )
895 {
896         EulerObject *eul;
897
898         eul = ( EulerObject * ) newEulerObject( NULL );
899         eul->eul[0] = self->object->rot[0];
900         eul->eul[1] = self->object->rot[1];
901         eul->eul[2] = self->object->rot[2];
902
903         return ( PyObject * ) eul;
904
905 }
906
907 static PyObject *Object_getInverseMatrix( BPy_Object * self )
908 {
909         MatrixObject *inverse =
910                 ( MatrixObject * ) newMatrixObject( NULL, 4, 4 );
911         Mat4Invert( *inverse->matrix, self->object->obmat );
912
913         return ( ( PyObject * ) inverse );
914 }
915
916 static PyObject *Object_getIpo( BPy_Object * self )
917 {
918         struct Ipo *ipo = self->object->ipo;
919
920         if( !ipo ) {
921                 Py_INCREF( Py_None );
922                 return Py_None;
923         }
924
925         return Ipo_CreatePyObject( ipo );
926 }
927
928 static PyObject *Object_getLocation( BPy_Object * self, PyObject * args )
929 {
930         PyObject *attr = Py_BuildValue( "fff",
931                                         self->object->loc[0],
932                                         self->object->loc[1],
933                                         self->object->loc[2] );
934
935         if( attr )
936                 return ( attr );
937
938         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
939                                         "couldn't get Object.loc attributes" ) );
940 }
941
942 static PyObject *Object_getMaterials( BPy_Object * self, PyObject * args )
943 {
944         int all = 0;
945
946         if( !PyArg_ParseTuple( args, "|i", &all ) ) {
947                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
948                                                 "expected an int or nothing" ) );
949         }
950
951         return ( EXPP_PyList_fromMaterialList( self->object->mat,
952                                                self->object->totcol, all ) );
953 }
954
955 static PyObject *Object_getMatrix( BPy_Object * self, PyObject * args )
956 {
957         PyObject *matrix;
958         char *space = "worldspace";     /* default to world */
959
960         if( !PyArg_ParseTuple( args, "|s", &space ) ) {
961                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
962                                                 "expected a string or nothing" ) );
963         }
964         //new matrix
965         matrix = newMatrixObject( NULL, 4, 4 );
966
967         if( BLI_streq( space, "worldspace" ) ) {        /* Worldspace matrix */
968                 disable_where_script( 1 );
969                 where_is_object( self->object );
970                 disable_where_script( 0 );
971                 Mat4CpyMat4( *( ( MatrixObject * ) matrix )->matrix,
972                              self->object->obmat );
973         } else if( BLI_streq( space, "localspace" ) ) { /* Localspace matrix */
974                 object_to_mat4( self->object,
975                                 *( ( MatrixObject * ) matrix )->matrix );
976                 /* old behavior, prior to 2.34, check this method's doc string: */
977         } else if( BLI_streq( space, "old_worldspace" ) ) {
978                 Mat4CpyMat4( *( ( MatrixObject * ) matrix )->matrix,
979                              self->object->obmat );
980         } else {
981                 return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
982                                 "wrong parameter, expected nothing or either 'worldspace' (default),\n\
983 'localspace' or 'old_worldspace'" ) );
984         }
985         return matrix;
986 }
987
988 static PyObject *Object_getName( BPy_Object * self )
989 {
990         PyObject *attr = Py_BuildValue( "s", self->object->id.name + 2 );
991
992         if( attr )
993                 return ( attr );
994
995         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
996                                         "couldn't get the name of the Object" ) );
997 }
998
999 static PyObject *Object_getParent( BPy_Object * self )
1000 {
1001         PyObject *attr;
1002
1003         if( self->object->parent == NULL )
1004                 return EXPP_incr_ret( Py_None );
1005
1006         attr = Object_CreatePyObject( self->object->parent );
1007
1008         if( attr ) {
1009                 return ( attr );
1010         }
1011
1012         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
1013                                         "couldn't get Object.parent attribute" ) );
1014 }
1015
1016 static PyObject *Object_getSize( BPy_Object * self, PyObject * args )
1017 {
1018         PyObject *attr = Py_BuildValue( "fff",
1019                                         self->object->size[0],
1020                                         self->object->size[1],
1021                                         self->object->size[2] );
1022
1023         if( attr )
1024                 return ( attr );
1025
1026         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
1027                                         "couldn't get Object.size attributes" ) );
1028 }
1029
1030 static PyObject *Object_getTimeOffset( BPy_Object * self )
1031 {
1032         PyObject *attr = Py_BuildValue( "f", self->object->sf );
1033
1034         if( attr )
1035                 return ( attr );
1036
1037         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
1038                                         "couldn't get Object.sf attributes" ) );
1039 }
1040
1041
1042 static PyObject *Object_getTracked( BPy_Object * self )
1043 {
1044         PyObject *attr;
1045
1046         if( self->object->track == NULL )
1047                 return EXPP_incr_ret( Py_None );
1048
1049         attr = Object_CreatePyObject( self->object->track );
1050
1051         if( attr ) {
1052                 return ( attr );
1053         }
1054
1055         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
1056                                         "couldn't get Object.track attribute" ) );
1057 }
1058
1059 static PyObject *Object_getType( BPy_Object * self )
1060 {
1061         switch ( self->object->type ) {
1062         case OB_ARMATURE:
1063                 return ( Py_BuildValue( "s", "Armature" ) );
1064         case OB_CAMERA:
1065                 return ( Py_BuildValue( "s", "Camera" ) );
1066         case OB_CURVE:
1067                 return ( Py_BuildValue( "s", "Curve" ) );
1068         case OB_EMPTY:
1069                 return ( Py_BuildValue( "s", "Empty" ) );
1070         case OB_FONT:
1071                 return ( Py_BuildValue( "s", "Text" ) );
1072         case OB_IKA:
1073                 return ( Py_BuildValue( "s", "Ika" ) );
1074         case OB_LAMP:
1075                 return ( Py_BuildValue( "s", "Lamp" ) );
1076         case OB_LATTICE:
1077                 return ( Py_BuildValue( "s", "Lattice" ) );
1078         case OB_MBALL:
1079                 return ( Py_BuildValue( "s", "MBall" ) );
1080         case OB_MESH:
1081                 return ( Py_BuildValue( "s", "Mesh" ) );
1082         case OB_SURF:
1083                 return ( Py_BuildValue( "s", "Surf" ) );
1084         case OB_WAVE:
1085                 return ( Py_BuildValue( "s", "Wave" ) );
1086         default:
1087                 return ( Py_BuildValue( "s", "unknown" ) );
1088         }
1089 }
1090
1091
1092 static PyObject *Object_getBoundBox( BPy_Object * self )
1093 {
1094         int i;
1095         float *vec = NULL;
1096         PyObject *vector, *bbox;
1097
1098         if( !self->object->data )
1099                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
1100                                               "This object isn't linked to any object data (mesh, curve, etc) yet" );
1101
1102         if( !self->object->bb ) {       /* if no ob bbox, we look in obdata */
1103                 Mesh *me;
1104                 Curve *curve;
1105                 switch ( self->object->type ) {
1106                 case OB_MESH:
1107                         me = self->object->data;
1108                         if( !me->bb )
1109                                 tex_space_mesh( me );
1110                         vec = ( float * ) me->bb->vec;
1111                         break;
1112                 case OB_CURVE:
1113                 case OB_FONT:
1114                 case OB_SURF:
1115                         curve = self->object->data;
1116                         if( !curve->bb )
1117                                 tex_space_curve( curve );
1118                         vec = ( float * ) curve->bb->vec;
1119                         break;
1120                 default:
1121                         Py_INCREF( Py_None );
1122                         return Py_None;
1123                 }
1124
1125                 {               /* transform our obdata bbox by the obmat.
1126                                    the obmat is 4x4 homogeneous coords matrix.
1127                                    each bbox coord is xyz, so we make it homogenous
1128                                    by padding it with w=1.0 and doing the matrix mult.
1129                                    afterwards we divide by w to get back to xyz.
1130                                  */
1131                         /* printmatrix4( "obmat", self->object->obmat); */
1132
1133                         float tmpvec[4];        /* tmp vector for homogenous coords math */
1134                         int i;
1135                         float *from;
1136
1137                         bbox = PyList_New( 8 );
1138                         if( !bbox )
1139                                 return EXPP_ReturnPyObjError
1140                                         ( PyExc_MemoryError,
1141                                           "couldn't create pylist" );
1142                         for( i = 0, from = vec; i < 8; i++, from += 3 ) {
1143                                 memcpy( tmpvec, from, 3 * sizeof( float ) );
1144                                 tmpvec[3] = 1.0f;       /* set w coord */
1145                                 Mat4MulVec4fl( self->object->obmat, tmpvec );
1146                                 /* divide x,y,z by w */
1147                                 tmpvec[0] /= tmpvec[3];
1148                                 tmpvec[1] /= tmpvec[3];
1149                                 tmpvec[2] /= tmpvec[3];
1150
1151 #if 0
1152                                 {       /* debug print stuff */
1153                                         int i;
1154
1155                                         printf( "\nobj bbox transformed\n" );
1156                                         for( i = 0; i < 4; ++i )
1157                                                 printf( "%f ", tmpvec[i] );
1158
1159                                         printf( "\n" );
1160                                 }
1161 #endif
1162
1163                                 /* because our bounding box is calculated and
1164                                    does not have its own memory,
1165                                    we must create vectors that allocate space */
1166
1167                                 vector = newVectorObject( NULL, 3 );
1168                                 memcpy( ( ( VectorObject * ) vector )->vec,
1169                                         tmpvec, 3 * sizeof( float ) );
1170                                 PyList_SET_ITEM( bbox, i, vector );
1171                         }
1172                 }
1173         } else {                /* the ob bbox exists */
1174                 vec = ( float * ) self->object->bb->vec;
1175
1176                 if( !vec )
1177                         return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1178                                                       "couldn't retrieve bounding box data" );
1179
1180                 bbox = PyList_New( 8 );
1181
1182                 if( !bbox )
1183                         return EXPP_ReturnPyObjError( PyExc_MemoryError,
1184                                                       "couldn't create pylist" );
1185
1186                 /* create vectors referencing object bounding box coords */
1187                 for( i = 0; i < 8; i++ ) {
1188                         vector = newVectorObject( vec, 3 );
1189                         PyList_SET_ITEM( bbox, i, vector );
1190                         vec += 3;
1191                 }
1192         }
1193
1194         return bbox;
1195 }
1196
1197
1198 static PyObject *Object_makeDisplayList( BPy_Object * self )
1199 {
1200         Object *ob = self->object;
1201
1202         if( ob->type == OB_FONT )
1203                 text_to_curve( ob, 0 );
1204
1205         makeDispList( ob );
1206
1207         Py_INCREF( Py_None );
1208         return Py_None;
1209 }
1210
1211 static PyObject *Object_link( BPy_Object * self, PyObject * args )
1212 {
1213         PyObject *py_data;
1214         ID *id;
1215         ID *oldid;
1216         int obj_id;
1217         void *data = NULL;
1218
1219         if( !PyArg_ParseTuple( args, "O", &py_data ) ) {
1220                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1221                                                 "expected an object as argument" ) );
1222         }
1223         if( Armature_CheckPyObject( py_data ) )
1224                 data = ( void * ) Armature_FromPyObject( py_data );
1225         if( Camera_CheckPyObject( py_data ) )
1226                 data = ( void * ) Camera_FromPyObject( py_data );
1227         if( Lamp_CheckPyObject( py_data ) )
1228                 data = ( void * ) Lamp_FromPyObject( py_data );
1229         if( Curve_CheckPyObject( py_data ) )
1230                 data = ( void * ) Curve_FromPyObject( py_data );
1231         if( NMesh_CheckPyObject( py_data ) )
1232                 data = ( void * ) Mesh_FromPyObject( py_data, self->object );
1233         if( Lattice_CheckPyObject( py_data ) )
1234                 data = ( void * ) Lattice_FromPyObject( py_data );
1235         if( Metaball_CheckPyObject( py_data ) )
1236                 data = ( void * ) Metaball_FromPyObject( py_data );
1237         if( Text3d_CheckPyObject( py_data ) )
1238                 data = ( void * ) Text3d_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 && self->object->type != OB_FONT ) {
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         int argslen = PyObject_Length( args );
1834
1835         if( argslen == 3 || argslen == 2 ) {
1836                 if( !PyArg_ParseTuple
1837                     ( args, "sO|s", &prop_name, &prop_data, &prop_type ) ) {
1838                         return ( EXPP_ReturnPyObjError
1839                                  ( PyExc_AttributeError,
1840                                    "unable to get string, data, and optional string" ) );
1841                 }
1842         } else if( argslen == 1 ) {
1843                 if( !PyArg_ParseTuple( args, "O!", &property_Type, &py_prop ) ) {
1844                         return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1845                                                         "unable to get Property" ) );
1846                 }
1847                 if( py_prop->property != NULL ) {
1848                         return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1849                                                         "Property is already added to an object" ) );
1850                 }
1851         } else {
1852                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1853                                                 "expected 1,2 or 3 arguments" ) );
1854         }
1855
1856         //parse property type
1857         if( !py_prop ) {
1858                 if( prop_type ) {
1859                         if( BLI_streq( prop_type, "BOOL" ) )
1860                                 type = PROP_BOOL;
1861                         else if( BLI_streq( prop_type, "INT" ) )
1862                                 type = PROP_INT;
1863                         else if( BLI_streq( prop_type, "FLOAT" ) )
1864                                 type = PROP_FLOAT;
1865                         else if( BLI_streq( prop_type, "TIME" ) )
1866                                 type = PROP_TIME;
1867                         else if( BLI_streq( prop_type, "STRING" ) )
1868                                 type = PROP_STRING;
1869                         else
1870                                 return ( EXPP_ReturnPyObjError
1871                                          ( PyExc_RuntimeError,
1872                                            "BOOL, INT, FLOAT, TIME or STRING expected" ) );
1873                 } else {
1874                         //use the default
1875                         if( PyInt_Check( prop_data ) )
1876                                 type = PROP_INT;
1877                         else if( PyFloat_Check( prop_data ) )
1878                                 type = PROP_FLOAT;
1879                         else if( PyString_Check( prop_data ) )
1880                                 type = PROP_STRING;
1881                 }
1882         } else {
1883                 type = py_prop->type;
1884         }
1885
1886         //initialize a new bProperty of the specified type
1887         prop = new_property( type );
1888
1889         //parse data
1890         if( !py_prop ) {
1891                 BLI_strncpy( prop->name, prop_name, 32 );
1892                 if( PyInt_Check( prop_data ) ) {
1893                         *( ( int * ) &prop->data ) =
1894                                 ( int ) PyInt_AsLong( prop_data );
1895                 } else if( PyFloat_Check( prop_data ) ) {
1896                         *( ( float * ) &prop->data ) =
1897                                 ( float ) PyFloat_AsDouble( prop_data );
1898                 } else if( PyString_Check( prop_data ) ) {
1899                         BLI_strncpy( prop->poin,
1900                                      PyString_AsString( prop_data ),
1901                                      MAX_PROPSTRING );
1902                 }
1903         } else {
1904                 py_prop->property = prop;
1905                 if( !updateProperyData( py_prop ) ) {
1906                         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
1907                                                         "Could not update property data - error" ) );
1908                 }
1909         }
1910
1911         //add to property listbase for the object
1912         BLI_addtail( &self->object->prop, prop );
1913
1914         return EXPP_incr_ret( Py_None );
1915 }
1916
1917 static PyObject *Object_removeProperty( BPy_Object * self, PyObject * args )
1918 {
1919         char *prop_name = NULL;
1920         BPy_Property *py_prop = NULL;
1921         bProperty *prop = NULL;
1922
1923         // we have property and no optional arg
1924         if( !PyArg_ParseTuple( args, "O!", &property_Type, &py_prop ) ) {
1925                 if( !PyArg_ParseTuple( args, "s", &prop_name ) ) {
1926                         return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1927                                                         "expected a Property or a string" ) );
1928                 }
1929         }
1930         //remove the link, free the data, and update the py struct
1931         if( py_prop ) {
1932                 BLI_remlink( &self->object->prop, py_prop->property );
1933                 if( updatePyProperty( py_prop ) ) {
1934                         free_property( py_prop->property );
1935                         py_prop->property = NULL;
1936                 }
1937         } else {
1938                 prop = get_property( self->object, prop_name );
1939                 if( prop ) {
1940                         BLI_remlink( &self->object->prop, prop );
1941                         free_property( prop );
1942                 }
1943         }
1944         return EXPP_incr_ret( Py_None );
1945 }
1946
1947 static PyObject *Object_removeAllProperties( BPy_Object * self )
1948 {
1949         free_properties( &self->object->prop );
1950         return EXPP_incr_ret( Py_None );
1951 }
1952
1953 static PyObject *Object_copyAllPropertiesTo( BPy_Object * self,
1954                                              PyObject * args )
1955 {
1956         PyObject *dest = Py_None;
1957         bProperty *prop = NULL;
1958         bProperty *propn = NULL;
1959
1960         if( !PyArg_ParseTuple( args, "O!", &Object_Type, &dest ) ) {
1961                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1962                                                 "expected an Object" ) );
1963         }
1964         //make a copy of all it's properties
1965         prop = self->object->prop.first;
1966         while( prop ) {
1967                 propn = copy_property( prop );
1968                 BLI_addtail( &( ( BPy_Object * ) dest )->object->prop, propn );
1969                 prop = prop->next;
1970         }
1971
1972         return EXPP_incr_ret( Py_None );
1973 }
1974
1975 /* obj.addScriptLink */
1976 static PyObject *Object_addScriptLink( BPy_Object * self, PyObject * args )
1977 {
1978         Object *obj = self->object;
1979         ScriptLink *slink = NULL;
1980
1981         slink = &( obj )->scriptlink;
1982
1983         if( !EXPP_addScriptLink( slink, args, 0 ) )
1984                 return EXPP_incr_ret( Py_None );
1985         else
1986                 return NULL;
1987 }
1988
1989 /* obj.clearScriptLinks */
1990 static PyObject *Object_clearScriptLinks( BPy_Object * self )
1991 {
1992         Object *obj = self->object;
1993         ScriptLink *slink = NULL;
1994
1995         slink = &( obj )->scriptlink;
1996
1997         return EXPP_incr_ret( Py_BuildValue
1998                               ( "i", EXPP_clearScriptLinks( slink ) ) );
1999 }
2000
2001 /* obj.getScriptLinks */
2002 static PyObject *Object_getScriptLinks( BPy_Object * self, PyObject * args )
2003 {
2004         Object *obj = self->object;
2005         ScriptLink *slink = NULL;
2006         PyObject *ret = NULL;
2007
2008         slink = &( obj )->scriptlink;
2009
2010         ret = EXPP_getScriptLinks( slink, args, 0 );
2011
2012         if( ret )
2013                 return ret;
2014         else
2015                 return NULL;
2016 }
2017
2018 #if 0
2019
2020 /* fixme: save this for next commit 6-mar-05 stivs */
2021
2022 /****
2023  * Set dupliverts 
2024  * 
2025  ***/
2026
2027 static PyObject *Object_setDupliVerts ( BPy_Object * self ) {
2028         Object *obj = self->object;
2029         if (obj) {
2030                 obj->transflag|= (char)16;
2031         }
2032         return Py_None;
2033 }
2034 #endif
2035
2036 /*****************************************************************************/
2037 /* Function:    Object_CreatePyObject                                    */
2038 /* Description: This function will create a new BlenObject from an existing  */
2039 /*              Object structure.                                        */
2040 /*****************************************************************************/
2041 PyObject *Object_CreatePyObject( struct Object * obj )
2042 {
2043         BPy_Object *blen_object;
2044
2045         if( !obj )
2046                 return EXPP_incr_ret( Py_None );
2047
2048         blen_object =
2049                 ( BPy_Object * ) PyObject_NEW( BPy_Object, &Object_Type );
2050
2051         if( blen_object == NULL ) {
2052                 return ( NULL );
2053         }
2054         blen_object->object = obj;
2055         return ( ( PyObject * ) blen_object );
2056 }
2057
2058 /*****************************************************************************/
2059 /* Function:    Object_CheckPyObject                                     */
2060 /* Description: This function returns true when the given PyObject is of the */
2061 /*              type Object. Otherwise it will return false.             */
2062 /*****************************************************************************/
2063 int Object_CheckPyObject( PyObject * py_obj )
2064 {
2065         return ( py_obj->ob_type == &Object_Type );
2066 }
2067
2068 /*****************************************************************************/
2069 /* Function:    Object_FromPyObject                                      */
2070 /* Description: This function returns the Blender object from the given  */
2071 /*              PyObject.                                                */
2072 /*****************************************************************************/
2073 struct Object *Object_FromPyObject( PyObject * py_obj )
2074 {
2075         BPy_Object *blen_obj;
2076
2077         blen_obj = ( BPy_Object * ) py_obj;
2078         return ( blen_obj->object );
2079 }
2080
2081 /*****************************************************************************/
2082 /* Description: Returns the object with the name specified by the argument  */
2083 /*              name. Note that the calling function has to remove the first */
2084 /*              two characters of the object name. These two characters    */
2085 /*              specify the type of the object (OB, ME, WO, ...)         */
2086 /*              The function will return NULL when no object with the given  */
2087 /*              name is found.                                           */
2088 /*****************************************************************************/
2089 Object *GetObjectByName( char *name )
2090 {
2091         Object *obj_iter;
2092
2093         obj_iter = G.main->object.first;
2094         while( obj_iter ) {
2095                 if( StringEqual( name, GetIdName( &( obj_iter->id ) ) ) ) {
2096                         return ( obj_iter );
2097                 }
2098                 obj_iter = obj_iter->id.next;
2099         }
2100
2101         /* There is no object with the given name */
2102         return ( NULL );
2103 }
2104
2105 /*****************************************************************************/
2106 /* Function:    Object_dealloc                                           */
2107 /* Description: This is a callback function for the BlenObject type. It is  */
2108 /*              the destructor function.                                 */
2109 /*****************************************************************************/
2110 static void Object_dealloc( BPy_Object * obj )
2111 {
2112         PyObject_DEL( obj );
2113 }
2114
2115 /*****************************************************************************/
2116 /* Function:    Object_getAttr                                           */
2117 /* Description: This is a callback function for the BlenObject type. It is  */
2118 /*              the function that retrieves any value from Blender and   */
2119 /*              passes it to Python.                                     */
2120 /*****************************************************************************/
2121 static PyObject *Object_getAttr( BPy_Object * obj, char *name )
2122 {
2123         struct Object *object;
2124         struct Ika *ika;
2125
2126         object = obj->object;
2127         if( StringEqual( name, "LocX" ) )
2128                 return ( PyFloat_FromDouble( object->loc[0] ) );
2129         if( StringEqual( name, "LocY" ) )
2130                 return ( PyFloat_FromDouble( object->loc[1] ) );
2131         if( StringEqual( name, "LocZ" ) )
2132                 return ( PyFloat_FromDouble( object->loc[2] ) );
2133         if( StringEqual( name, "loc" ) )
2134                 return ( Py_BuildValue( "fff", object->loc[0], object->loc[1],
2135                                         object->loc[2] ) );
2136         if( StringEqual( name, "dLocX" ) )
2137                 return ( PyFloat_FromDouble( object->dloc[0] ) );
2138         if( StringEqual( name, "dLocY" ) )
2139                 return ( PyFloat_FromDouble( object->dloc[1] ) );
2140         if( StringEqual( name, "dLocZ" ) )
2141                 return ( PyFloat_FromDouble( object->dloc[2] ) );
2142         if( StringEqual( name, "dloc" ) )
2143                 return ( Py_BuildValue
2144                          ( "fff", object->dloc[0], object->dloc[1],
2145                            object->dloc[2] ) );
2146         if( StringEqual( name, "RotX" ) )
2147                 return ( PyFloat_FromDouble( object->rot[0] ) );
2148         if( StringEqual( name, "RotY" ) )
2149                 return ( PyFloat_FromDouble( object->rot[1] ) );
2150         if( StringEqual( name, "RotZ" ) )
2151                 return ( PyFloat_FromDouble( object->rot[2] ) );
2152         if( StringEqual( name, "rot" ) )
2153                 return ( Py_BuildValue( "fff", object->rot[0], object->rot[1],
2154                                         object->rot[2] ) );
2155         if( StringEqual( name, "dRotX" ) )
2156                 return ( PyFloat_FromDouble( object->drot[0] ) );
2157         if( StringEqual( name, "dRotY" ) )
2158                 return ( PyFloat_FromDouble( object->drot[1] ) );
2159         if( StringEqual( name, "dRotZ" ) )
2160                 return ( PyFloat_FromDouble( object->drot[2] ) );
2161         if( StringEqual( name, "drot" ) )
2162                 return ( Py_BuildValue
2163                          ( "fff", object->drot[0], object->drot[1],
2164                            object->drot[2] ) );
2165         if( StringEqual( name, "SizeX" ) )
2166                 return ( PyFloat_FromDouble( object->size[0] ) );
2167         if( StringEqual( name, "SizeY" ) )
2168                 return ( PyFloat_FromDouble( object->size[1] ) );
2169         if( StringEqual( name, "SizeZ" ) )
2170                 return ( PyFloat_FromDouble( object->size[2] ) );
2171         if( StringEqual( name, "size" ) )
2172                 return ( Py_BuildValue
2173                          ( "fff", object->size[0], object->size[1],
2174                            object->size[2] ) );
2175         if( StringEqual( name, "dSizeX" ) )
2176                 return ( PyFloat_FromDouble( object->dsize[0] ) );
2177         if( StringEqual( name, "dSizeY" ) )
2178                 return ( PyFloat_FromDouble( object->dsize[1] ) );
2179         if( StringEqual( name, "dSizeZ" ) )
2180                 return ( PyFloat_FromDouble( object->dsize[2] ) );
2181         if( StringEqual( name, "dsize" ) )
2182                 return ( Py_BuildValue
2183                          ( "fff", object->dsize[0], object->dsize[1],
2184                            object->dsize[2] ) );
2185         if( strncmp( name, "Eff", 3 ) == 0 ) {
2186                 if( ( object->type == OB_IKA ) && ( object->data != NULL ) ) {
2187                         ika = object->data;
2188                         switch ( name[3] ) {
2189                         case 'X':
2190                                 return ( PyFloat_FromDouble( ika->effg[0] ) );
2191                         case 'Y':
2192                                 return ( PyFloat_FromDouble( ika->effg[1] ) );
2193                         case 'Z':
2194                                 return ( PyFloat_FromDouble( ika->effg[2] ) );
2195                         default:
2196                                 /* Do we need to display a sensible error message here? */
2197                                 return ( NULL );
2198                         }
2199                 }
2200                 return ( NULL );
2201         }
2202         if( StringEqual( name, "Layer" ) )
2203                 return ( PyInt_FromLong( object->lay ) );
2204         if( StringEqual( name, "parent" ) ) {
2205                 if( object->parent )
2206                         return ( Object_CreatePyObject( object->parent ) );
2207                 else {
2208                         Py_INCREF( Py_None );
2209                         return ( Py_None );
2210                 }
2211         }
2212
2213         if( StringEqual( name, "track" ) )
2214                 return ( Object_CreatePyObject( object->track ) );
2215         if( StringEqual( name, "data" ) ) {
2216                 PyObject *getdata, *tuple = PyTuple_New(0);
2217
2218                 if (!tuple)
2219                         return EXPP_ReturnPyObjError (PyExc_MemoryError,
2220                                 "couldn't create an empty tuple!");
2221
2222                 getdata = Object_getData( obj, tuple, NULL );
2223
2224                 Py_DECREF(tuple);
2225                 return getdata;
2226         }
2227         if( StringEqual( name, "ipo" ) ) {
2228                 if( object->ipo == NULL ) {
2229                         /* There's no ipo linked to the object, return Py_None. */
2230                         Py_INCREF( Py_None );
2231                         return ( Py_None );
2232                 }
2233                 return ( Ipo_CreatePyObject( object->ipo ) );
2234         }
2235         if( StringEqual( name, "mat" ) || StringEqual( name, "matrix" ) )
2236                 return ( Object_getMatrix
2237                          ( obj, Py_BuildValue( "(s)", "worldspace" ) ) );
2238         if( StringEqual( name, "matrixWorld" ) )
2239                 return ( Object_getMatrix
2240                          ( obj, Py_BuildValue( "(s)", "worldspace" ) ) );
2241         if( StringEqual( name, "matrixLocal" ) )
2242                 return ( Object_getMatrix
2243                          ( obj, Py_BuildValue( "(s)", "localspace" ) ) );
2244         if( StringEqual( name, "colbits" ) )
2245                 return ( Py_BuildValue( "h", object->colbits ) );
2246         if( StringEqual( name, "drawType" ) )
2247                 return ( Py_BuildValue( "b", object->dt ) );
2248         if( StringEqual( name, "drawMode" ) )
2249                 return ( Py_BuildValue( "b", object->dtx ) );
2250         if( StringEqual( name, "name" ) )
2251                 return ( Py_BuildValue( "s", object->id.name + 2 ) );
2252         if( StringEqual( name, "sel" ) )
2253                 return ( Object_isSelected( obj ) );
2254         if (StringEqual (name, "oopsLoc")) {
2255                 if (G.soops) {
2256       Oops *oops= G.soops->oops.first;
2257       while(oops) {
2258         if(oops->type==ID_OB) {
2259           if ((Object *)oops->id == object) {
2260             return (Py_BuildValue ("ff", oops->x, oops->y));
2261           }
2262         }
2263         oops= oops->next;
2264       }
2265     }
2266                 return EXPP_incr_ret( Py_None );
2267         }
2268
2269         /* not an attribute, search the methods table */
2270         return Py_FindMethod( BPy_Object_methods, ( PyObject * ) obj, name );
2271 }
2272
2273 /*****************************************************************************/
2274 /* Function:    Object_setAttr                                           */
2275 /* Description: This is a callback function for the BlenObject type. It is  */
2276 /*              the function that retrieves any value from Python and sets  */
2277 /*              it accordingly in Blender.                               */
2278 /*****************************************************************************/
2279 static int Object_setAttr( BPy_Object * obj, char *name, PyObject * value )
2280 {
2281         PyObject *valtuple;
2282         struct Object *object;
2283         struct Ika *ika;
2284
2285         /* First put the value(s) in a tuple. For some variables, we want to */
2286         /* pass the values to a function, and these functions only accept */
2287         /* PyTuples. */
2288         valtuple = Py_BuildValue( "(O)", value );
2289         if( !valtuple ) {
2290                 return EXPP_ReturnIntError( PyExc_MemoryError,
2291                                             "Object_setAttr: couldn't create PyTuple" );
2292         }
2293
2294         object = obj->object;
2295         if( StringEqual( name, "LocX" ) )
2296                 return ( !PyArg_Parse( value, "f", &( object->loc[0] ) ) );
2297         if( StringEqual( name, "LocY" ) )
2298                 return ( !PyArg_Parse( value, "f", &( object->loc[1] ) ) );
2299         if( StringEqual( name, "LocZ" ) )
2300                 return ( !PyArg_Parse( value, "f", &( object->loc[2] ) ) );
2301         if( StringEqual( name, "loc" ) ) {
2302                 if( Object_setLocation( obj, valtuple ) != Py_None )
2303                         return ( -1 );
2304                 else
2305                         return ( 0 );
2306         }
2307         if( StringEqual( name, "dLocX" ) )
2308                 return ( !PyArg_Parse( value, "f", &( object->dloc[0] ) ) );
2309         if( StringEqual( name, "dLocY" ) )
2310                 return ( !PyArg_Parse( value, "f", &( object->dloc[1] ) ) );
2311         if( StringEqual( name, "dLocZ" ) )
2312                 return ( !PyArg_Parse( value, "f", &( object->dloc[2] ) ) );
2313         if( StringEqual( name, "dloc" ) ) {
2314                 if( Object_setDeltaLocation( obj, valtuple ) != Py_None )
2315                         return ( -1 );
2316                 else
2317                         return ( 0 );
2318         }
2319         if( StringEqual( name, "RotX" ) )
2320                 return ( !PyArg_Parse( value, "f", &( object->rot[0] ) ) );
2321         if( StringEqual( name, "RotY" ) )
2322                 return ( !PyArg_Parse( value, "f", &( object->rot[1] ) ) );
2323         if( StringEqual( name, "RotZ" ) )
2324                 return ( !PyArg_Parse( value, "f", &( object->rot[2] ) ) );
2325         if( StringEqual( name, "rot" ) ) {
2326                 if( Object_setEuler( obj, valtuple ) != Py_None )
2327                         return ( -1 );
2328                 else
2329                         return ( 0 );
2330         }
2331         if( StringEqual( name, "dRotX" ) )
2332                 return ( !PyArg_Parse( value, "f", &( object->drot[0] ) ) );
2333         if( StringEqual( name, "dRotY" ) )
2334                 return ( !PyArg_Parse( value, "f", &( object->drot[1] ) ) );
2335         if( StringEqual( name, "dRotZ" ) )
2336                 return ( !PyArg_Parse( value, "f", &( object->drot[2] ) ) );
2337         if( StringEqual( name, "drot" ) )
2338                 return ( !PyArg_ParseTuple( value, "fff", &( object->drot[0] ),
2339                                             &( object->drot[1] ),
2340                                             &( object->drot[2] ) ) );
2341         if( StringEqual( name, "SizeX" ) )
2342                 return ( !PyArg_Parse( value, "f", &( object->size[0] ) ) );
2343         if( StringEqual( name, "SizeY" ) )
2344                 return ( !PyArg_Parse( value, "f", &( object->size[1] ) ) );
2345         if( StringEqual( name, "SizeZ" ) )
2346                 return ( !PyArg_Parse( value, "f", &( object->size[2] ) ) );
2347         if( StringEqual( name, "size" ) )
2348                 return ( !PyArg_ParseTuple( value, "fff", &( object->size[0] ),
2349                                             &( object->size[1] ),
2350                                             &( object->size[2] ) ) );
2351         if( StringEqual( name, "dSizeX" ) )
2352                 return ( !PyArg_Parse( value, "f", &( object->dsize[0] ) ) );
2353         if( StringEqual( name, "dSizeY" ) )
2354                 return ( !PyArg_Parse( value, "f", &( object->dsize[1] ) ) );
2355         if( StringEqual( name, "dSizeZ" ) )
2356                 return ( !PyArg_Parse( value, "f", &( object->dsize[2] ) ) );
2357         if( StringEqual( name, "dsize" ) )
2358                 return ( !PyArg_ParseTuple
2359                          ( value, "fff", &( object->dsize[0] ),
2360                            &( object->dsize[1] ), &( object->dsize[2] ) ) );
2361         if( strncmp( name, "Eff", 3 ) == 0 ) {
2362                 if( ( object->type == OB_IKA ) && ( object->data != NULL ) ) {
2363                         ika = object->data;
2364                         switch ( name[3] ) {
2365                         case 'X':
2366                                 return ( !PyArg_Parse
2367                                          ( value, "f", &( ika->effg[0] ) ) );
2368                         case 'Y':
2369                                 return ( !PyArg_Parse
2370                                          ( value, "f", &( ika->effg[1] ) ) );
2371                         case 'Z':
2372                                 return ( !PyArg_Parse
2373                                          ( value, "f", &( ika->effg[2] ) ) );
2374                         default:
2375                                 /* Do we need to display a sensible error message here? */
2376                                 return ( 0 );
2377                         }
2378                 }
2379                 return ( 0 );
2380         }
2381         if( StringEqual( name, "Layer" ) ) {
2382                 /*  usage note: caller of this func needs to do a 
2383                    Blender.Redraw(-1) to update and redraw the interface */
2384
2385                 Base *base;
2386                 int newLayer;
2387                 int local;
2388
2389                 if( ! PyArg_Parse( value, "i", &newLayer ) ) {
2390                         return EXPP_ReturnIntError( PyExc_AttributeError,
2391                                                     "expected int as bitmask" );
2392                 }
2393
2394                 /* uppper 2 nibbles are for local view */
2395                 newLayer &= 0x00FFFFFF;
2396                 if( newLayer == 0 )     /* bail if nothing to do */
2397                         return ( 0 );
2398                 
2399                 /* update any bases pointing to our object */
2400                 base = FIRSTBASE;  /* first base in current scene */
2401                 while( base ){
2402                         if( base->object == obj->object ) {
2403                                 local = base->lay &= 0xFF000000;
2404                                 base->lay = local | newLayer;
2405                                 object->lay = base->lay;
2406                         }
2407                         base = base->next;
2408                 }
2409                 countall(  );
2410                 
2411                 return ( 0 );
2412         }
2413         if( StringEqual( name, "parent" ) ) {
2414                 /* This is not allowed. */
2415                 EXPP_ReturnPyObjError( PyExc_AttributeError,
2416                                        "Setting the parent is not allowed." );
2417                 return ( 0 );
2418         }
2419         if( StringEqual( name, "track" ) ) {
2420                 if( Object_makeTrack( obj, valtuple ) != Py_None )
2421                         return ( -1 );
2422                 else
2423                         return ( 0 );
2424         }
2425         if( StringEqual( name, "data" ) ) {
2426                 /* This is not allowed. */
2427                 EXPP_ReturnPyObjError( PyExc_AttributeError,
2428                                        "Setting the data is not allowed." );
2429                 return ( 0 );
2430         }
2431         if( StringEqual( name, "ipo" ) ) {
2432                 /* This is not allowed. */
2433                 EXPP_ReturnPyObjError( PyExc_AttributeError,
2434                                        "Setting the ipo is not allowed." );
2435                 return ( 0 );
2436         }
2437         if( StringEqual( name, "mat" ) ) {
2438                 /* This is not allowed. */
2439                 EXPP_ReturnPyObjError( PyExc_AttributeError,
2440                                        "Setting the matrix is not allowed." );
2441                 return ( 0 );
2442         }
2443         if( StringEqual( name, "matrix" ) ) {
2444                 /* This is not allowed. */
2445                 EXPP_ReturnPyObjError( PyExc_AttributeError,
2446                                        "Please use .setMatrix(matrix)" );
2447                 return ( 0 );
2448         }
2449         if( StringEqual( name, "colbits" ) )
2450                 return ( !PyArg_Parse( value, "h", &( object->colbits ) ) );
2451         if( StringEqual( name, "drawType" ) ) {
2452                 if( Object_setDrawType( obj, valtuple ) != Py_None )
2453                         return ( -1 );
2454                 else
2455                         return ( 0 );
2456         }
2457         if( StringEqual( name, "drawMode" ) ) {
2458                 if( Object_setDrawMode( obj, valtuple ) != Py_None )
2459                         return ( -1 );
2460                 else
2461                         return ( 0 );
2462         }
2463         if( StringEqual( name, "name" ) ) {
2464                 if( Object_setName( obj, valtuple ) != Py_None )
2465                         return ( -1 );
2466                 else
2467                         return ( 0 );
2468         }
2469         if( StringEqual( name, "sel" ) ) {
2470                 if( Object_Select( obj, valtuple ) != Py_None )
2471                         return ( -1 );
2472                 else
2473                         return ( 0 );
2474         }
2475         if (StringEqual (name, "oopsLoc")) {
2476                 if (G.soops) {
2477                         Oops *oops= G.soops->oops.first;
2478                         while(oops) {
2479                                 if(oops->type==ID_OB) {
2480                                         if ((Object *)oops->id == object) {
2481                                                 return (!PyArg_ParseTuple  (value, "ff", &(oops->x),&(oops->y)));
2482                                         }
2483                                 }
2484                                 oops= oops->next;
2485                         }
2486                 }
2487                 return 0;
2488         }
2489
2490         return EXPP_ReturnIntError( PyExc_KeyError, "attribute not found" );
2491 }
2492
2493 /*****************************************************************************/
2494 /* Function:    Object_compare                                           */
2495 /* Description: This is a callback function for the BPy_Object type. It  */
2496 /*              compares two Object_Type objects. Only the "==" and "!="  */
2497 /*              comparisons are meaninful. Returns 0 for equality and -1 if  */
2498 /*              they don't point to the same Blender Object struct.      */
2499 /*              In Python it becomes 1 if they are equal, 0 otherwise.   */
2500 /*****************************************************************************/
2501 static int Object_compare( BPy_Object * a, BPy_Object * b )
2502 {
2503         Object *pa = a->object, *pb = b->object;
2504         return ( pa == pb ) ? 0 : -1;
2505 }
2506
2507 /*****************************************************************************/
2508 /* Function:    Object_repr                                              */
2509 /* Description: This is a callback function for the BPy_Object type. It  */
2510 /*              builds a meaninful string to represent object objects.   */
2511 /*****************************************************************************/
2512 static PyObject *Object_repr( BPy_Object * self )
2513 {
2514         return PyString_FromFormat( "[Object \"%s\"]",
2515                                     self->object->id.name + 2 );
2516 }