- remove calls to showkeypos from exit editmode functions, should be
[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, Johnny Matthews,
33  * Ken Hughes
34  *
35  * ***** END GPL/BL DUAL LICENSE BLOCK *****
36 */
37
38 #include "Object.h"
39 #include "NLA.h"
40 #include "logic.h"
41 #include "blendef.h"
42
43 #include "DNA_scene_types.h"
44 #include "DNA_mesh_types.h"
45 #include "DNA_curve_types.h"
46 #include "DNA_object_force.h"
47 #include "DNA_property_types.h"
48
49 #include "BKE_depsgraph.h"
50 #include "BKE_font.h"
51 #include "BKE_property.h"
52 #include "BKE_mball.h"
53 #include "BKE_softbody.h"
54 #include "BKE_utildefines.h"
55
56 #include "BIF_editview.h"
57 #include "BSE_editipo.h"
58 #include "BSE_edit.h"
59
60 #include "Ipo.h"
61 #include "Lattice.h"
62 #include "modules.h"
63 #include "Mathutils.h"
64 #include "constant.h"
65 /* only used for oops location get/set at the moment */
66 #include "DNA_oops_types.h" 
67 #include "DNA_space_types.h"
68
69 #include <string.h>
70
71 /* Defines for insertIpoKey */
72
73 #define IPOKEY_LOC              0
74 #define IPOKEY_ROT              1
75 #define IPOKEY_SIZE             2
76 #define IPOKEY_LOCROT           3
77 #define IPOKEY_LOCROTSIZE       4
78 #define IPOKEY_PI_STRENGTH      5
79 #define IPOKEY_PI_FALLOFF       6
80 #define IPOKEY_PI_MAXDIST       7 /*Not Ready Yet*/
81 #define IPOKEY_PI_SURFACEDAMP   8
82 #define IPOKEY_PI_RANDOMDAMP    9
83 #define IPOKEY_PI_PERM          10
84
85 #define PFIELD_FORCE    1
86 #define PFIELD_VORTEX   2
87 #define PFIELD_MAGNET   3
88 #define PFIELD_WIND             4
89
90 /*****************************************************************************/
91 /* Python API function prototypes for the Blender module.                */
92 /*****************************************************************************/
93 static PyObject *M_Object_New( PyObject * self, PyObject * args );
94 PyObject *M_Object_Get( PyObject * self, PyObject * args );
95 static PyObject *M_Object_GetSelected( PyObject * self, PyObject * args );
96
97 /* HELPER FUNCTION FOR PARENTING */
98 static PyObject *internal_makeParent(Object *parent, PyObject *py_child, int partype, int noninverse, int fast, int v1, int v2, int v3);
99
100 extern int Text3d_CheckPyObject( PyObject * py_obj );
101 extern struct Text3d *Text3d_FromPyObject( PyObject * py_obj );
102
103
104 /*****************************************************************************/
105 /* The following string definitions are used for documentation strings.  */
106 /* In Python these will be written to the console when doing a           */
107 /* Blender.Object.__doc__                                                */
108 /*****************************************************************************/
109 char M_Object_doc[] = "The Blender Object module\n\n\
110 This module provides access to **Object Data** in Blender.\n";
111
112 char M_Object_New_doc[] =
113         "(type) - Add a new object of type 'type' in the current scene";
114
115 char M_Object_Get_doc[] =
116         "(name) - return the object with the name 'name', returns None if not\
117         found.\n\
118         If 'name' is not specified, it returns a list of all objects in the\n\
119         current scene.";
120
121 char M_Object_GetSelected_doc[] =
122         "() - Returns a list of selected Objects in the active layer(s)\n\
123 The active object is the first in the list, if visible";
124
125 /*****************************************************************************/
126 /* Python method structure definition for Blender.Object module:         */
127 /*****************************************************************************/
128 struct PyMethodDef M_Object_methods[] = {
129         {"New", ( PyCFunction ) M_Object_New, METH_VARARGS,
130          M_Object_New_doc},
131         {"Get", ( PyCFunction ) M_Object_Get, METH_VARARGS,
132          M_Object_Get_doc},
133         {"GetSelected", ( PyCFunction ) M_Object_GetSelected, METH_VARARGS,
134          M_Object_GetSelected_doc},
135         {NULL, NULL, 0, NULL}
136 };
137
138 /*****************************************************************************/
139 /* Python BPy_Object methods declarations:                                 */
140 /*****************************************************************************/
141 int setupSB(Object* ob); /*Make sure Softbody Pointer is initialized */
142 int setupPI(Object* ob);
143
144 static PyObject *Object_buildParts( BPy_Object * self );
145 static PyObject *Object_clearIpo( BPy_Object * self );
146 static PyObject *Object_clrParent( BPy_Object * self, PyObject * args );
147 static PyObject *Object_clearTrack( BPy_Object * self, PyObject * args );
148 static PyObject *Object_getData(BPy_Object *self, PyObject *args, PyObject *kwd);
149 static PyObject *Object_getDeltaLocation( BPy_Object * self );
150 static PyObject *Object_getDrawMode( BPy_Object * self );
151 static PyObject *Object_getDrawType( BPy_Object * self );
152 static PyObject *Object_getEuler( BPy_Object * self );
153 static PyObject *Object_getInverseMatrix( BPy_Object * self );
154 static PyObject *Object_getIpo( BPy_Object * self );
155 static PyObject *Object_getLocation( BPy_Object * self, PyObject * args );
156 static PyObject *Object_getMaterials( BPy_Object * self, PyObject * args );
157 static PyObject *Object_getMatrix( BPy_Object * self, PyObject * args );
158 static PyObject *Object_getName( BPy_Object * self );
159 static PyObject *Object_getParent( BPy_Object * self );
160 static PyObject *Object_getSize( BPy_Object * self, PyObject * args );
161 static PyObject *Object_getTimeOffset( BPy_Object * self );
162 static PyObject *Object_getTracked( BPy_Object * self );
163 static PyObject *Object_getType( BPy_Object * self );
164 static PyObject *Object_getBoundBox( BPy_Object * self );
165 static PyObject *Object_getAction( BPy_Object * self );
166 static PyObject *Object_isSelected( BPy_Object * self );
167 static PyObject *Object_makeDisplayList( BPy_Object * self );
168 static PyObject *Object_link( BPy_Object * self, PyObject * args );
169 static PyObject *Object_makeParent( BPy_Object * self, PyObject * args );
170 static PyObject *Object_makeParentDeform( BPy_Object * self, PyObject * args );
171 static PyObject *Object_makeParentVertex( BPy_Object * self, PyObject * args );
172 static PyObject *Object_materialUsage( BPy_Object * self, PyObject * args );
173 static PyObject *Object_getDupliVerts ( BPy_Object * self );
174
175 static PyObject *Object_setDeltaLocation( BPy_Object * self, PyObject * args );
176 static PyObject *Object_setDrawMode( BPy_Object * self, PyObject * args );
177 static PyObject *Object_setDrawType( BPy_Object * self, PyObject * args );
178 static PyObject *Object_setEuler( BPy_Object * self, PyObject * args );
179 static PyObject *Object_setMatrix( BPy_Object * self, PyObject * args );
180 static PyObject *Object_setIpo( BPy_Object * self, PyObject * args );
181 static PyObject *Object_insertIpoKey( BPy_Object * self, PyObject * args );
182 static PyObject *Object_setLocation( BPy_Object * self, PyObject * args );
183 static PyObject *Object_setMaterials( BPy_Object * self, PyObject * args );
184 static PyObject *Object_setName( BPy_Object * self, PyObject * args );
185 static PyObject *Object_setSize( BPy_Object * self, PyObject * args );
186 static PyObject *Object_setTimeOffset( BPy_Object * self, PyObject * args );
187 static PyObject *Object_makeTrack( BPy_Object * self, PyObject * args );
188 static PyObject *Object_shareFrom( BPy_Object * self, PyObject * args );
189 static PyObject *Object_Select( BPy_Object * self, PyObject * args );
190 static PyObject *Object_getAllProperties( BPy_Object * self );
191 static PyObject *Object_addProperty( BPy_Object * self, PyObject * args );
192 static PyObject *Object_removeProperty( BPy_Object * self, PyObject * args );
193 static PyObject *Object_getProperty( BPy_Object * self, PyObject * args );
194 static PyObject *Object_removeAllProperties( BPy_Object * self );
195 static PyObject *Object_copyAllPropertiesTo( BPy_Object * self,
196                                              PyObject * args );
197 static PyObject *Object_getScriptLinks( BPy_Object * self, PyObject * args );
198 static PyObject *Object_addScriptLink( BPy_Object * self, PyObject * args );
199 static PyObject *Object_clearScriptLinks( BPy_Object * self, PyObject *args );
200 static PyObject *Object_setDupliVerts ( BPy_Object * self, PyObject * args );
201 static PyObject *Object_getPIStrength( BPy_Object * self );
202 static PyObject *Object_setPIStrength( BPy_Object * self, PyObject * args );
203 static PyObject *Object_getPIFalloff( BPy_Object * self );
204 static PyObject *Object_setPIFalloff( BPy_Object * self, PyObject * args );
205 static PyObject *Object_getPIMaxDist( BPy_Object * self );
206 static PyObject *Object_setPIMaxDist( BPy_Object * self, PyObject * args );
207 static PyObject *Object_getPIUseMaxDist( BPy_Object * self );
208 static PyObject *Object_setPIUseMaxDist( BPy_Object * self, PyObject * args );
209 static PyObject *Object_getPIType( BPy_Object * self );
210 static PyObject *Object_setPIType( BPy_Object * self, PyObject * args );
211 static PyObject *Object_getPIPerm( BPy_Object * self );
212 static PyObject *Object_setPIPerm( BPy_Object * self, PyObject * args );
213 static PyObject *Object_getPIRandomDamp( BPy_Object * self );
214 static PyObject *Object_setPIRandomDamp( BPy_Object * self, PyObject * args );
215 static PyObject *Object_getPISurfaceDamp( BPy_Object * self );
216 static PyObject *Object_setPISurfaceDamp( BPy_Object * self, PyObject * args );
217 static PyObject *Object_getPIDeflection( BPy_Object * self );
218 static PyObject *Object_setPIDeflection( BPy_Object * self, PyObject * args );
219
220 static PyObject *Object_isSB( BPy_Object * self );
221 static PyObject *Object_getSBMass( BPy_Object * self );
222 static PyObject *Object_setSBMass( BPy_Object * self, PyObject * args );
223 static PyObject *Object_getSBGravity( BPy_Object * self );
224 static PyObject *Object_setSBGravity( BPy_Object * self, PyObject * args );
225 static PyObject *Object_getSBFriction( BPy_Object * self );
226 static PyObject *Object_setSBFriction( BPy_Object * self, PyObject * args );
227 static PyObject *Object_getSBErrorLimit( BPy_Object * self );
228 static PyObject *Object_setSBErrorLimit( BPy_Object * self, PyObject * args );
229 static PyObject *Object_getSBGoalSpring( BPy_Object * self );
230 static PyObject *Object_setSBGoalSpring( BPy_Object * self, PyObject * args );
231 static PyObject *Object_getSBGoalFriction( BPy_Object * self );
232 static PyObject *Object_setSBGoalFriction( BPy_Object * self, PyObject * args );
233 static PyObject *Object_getSBMinGoal( BPy_Object * self );
234 static PyObject *Object_setSBMinGoal( BPy_Object * self, PyObject * args );
235 static PyObject *Object_getSBMaxGoal( BPy_Object * self );
236 static PyObject *Object_setSBMaxGoal( BPy_Object * self, PyObject * args );
237 static PyObject *Object_getSBInnerSpring( BPy_Object * self );
238 static PyObject *Object_setSBInnerSpring( BPy_Object * self, PyObject * args );
239 static PyObject *Object_getSBInnerSpringFriction( BPy_Object * self );
240 static PyObject *Object_setSBInnerSpringFriction( BPy_Object * self, PyObject * args );
241 static PyObject *Object_getSBDefaultGoal( BPy_Object * self );
242 static PyObject *Object_setSBDefaultGoal( BPy_Object * self, PyObject * args );
243 static PyObject *Object_getSBEnable( BPy_Object * self );
244 static PyObject *Object_setSBEnable( BPy_Object * self, PyObject * args );
245 static PyObject *Object_getSBPostDef( BPy_Object * self );
246 static PyObject *Object_setSBPostDef( BPy_Object * self, PyObject * args );
247 static PyObject *Object_getSBUseGoal( BPy_Object * self );
248 static PyObject *Object_setSBUseGoal( BPy_Object * self, PyObject * args );
249 static PyObject *Object_getSBUseEdges( BPy_Object * self );
250 static PyObject *Object_setSBUseEdges( BPy_Object * self, PyObject * args );
251 static PyObject *Object_getSBStiffQuads( BPy_Object * self );
252 static PyObject *Object_setSBStiffQuads( BPy_Object * self, PyObject * args );
253 /*****************************************************************************/
254 /* Python BPy_Object methods table:                                        */
255 /*****************************************************************************/
256 static PyMethodDef BPy_Object_methods[] = {
257         /* name, method, flags, doc */
258         {"buildParts", ( PyCFunction ) Object_buildParts, METH_NOARGS,
259          "Recalcs particle system (if any) "},
260         {"getIpo", ( PyCFunction ) Object_getIpo, METH_NOARGS,
261          "Returns the ipo of this object (if any) "},
262         {"clrParent", ( PyCFunction ) Object_clrParent, METH_VARARGS,
263          "Clears parent object. Optionally specify:\n\
264 mode\n\tnonzero: Keep object transform\nfast\n\t>0: Don't update scene \
265 hierarchy (faster)"},
266         {"clearTrack", ( PyCFunction ) Object_clearTrack, METH_VARARGS,
267          "Make this object not track another anymore. Optionally specify:\n\
268 mode\n\t2: Keep object transform\nfast\n\t>0: Don't update scene \
269 hierarchy (faster)"},
270         {"getData", ( PyCFunction ) Object_getData, METH_VARARGS | METH_KEYWORDS,
271          "(name_only = 0) - Returns the datablock object containing the object's \
272 data, e.g. Mesh.\n\
273 If 'name_only' is nonzero or True, only the name of the datablock is returned"},
274         {"getDeltaLocation", ( PyCFunction ) Object_getDeltaLocation,
275          METH_NOARGS,
276          "Returns the object's delta location (x, y, z)"},
277         {"getDrawMode", ( PyCFunction ) Object_getDrawMode, METH_NOARGS,
278          "Returns the object draw modes"},
279         {"getDrawType", ( PyCFunction ) Object_getDrawType, METH_NOARGS,
280          "Returns the object draw type"},
281         {"getAction", ( PyCFunction ) Object_getAction, METH_NOARGS,
282          "Returns the active action for this object"},
283         {"isSelected", ( PyCFunction ) Object_isSelected, METH_NOARGS,
284          "Return a 1 or 0 depending on whether the object is selected"},
285         {"getEuler", ( PyCFunction ) Object_getEuler, METH_NOARGS,
286          "Returns the object's rotation as Euler rotation vector\n\
287 (rotX, rotY, rotZ)"},
288         {"getInverseMatrix", ( PyCFunction ) Object_getInverseMatrix,
289          METH_NOARGS,
290          "Returns the object's inverse matrix"},
291         {"getLocation", ( PyCFunction ) Object_getLocation, METH_VARARGS,
292          "Returns the object's location (x, y, z)"},
293         {"getMaterials", ( PyCFunction ) Object_getMaterials, METH_VARARGS,
294          "(i = 0) - Returns list of materials assigned to the object.\n\
295 if i is nonzero, empty slots are not ignored: they are returned as None's."},
296         {"getMatrix", ( PyCFunction ) Object_getMatrix, METH_VARARGS,
297          "(str = 'worldspace') - Returns the object matrix.\n\
298 (str = 'worldspace') - the wanted matrix: worldspace (default), localspace\n\
299 or old_worldspace.\n\
300 \n\
301 'old_worldspace' was the only behavior before Blender 2.34.  With it the\n\
302 matrix is not updated for changes made by the script itself\n\
303 (like obj.LocX = 10) until a redraw happens, either called by the script or\n\
304 automatic when the script finishes."},
305         {"getName", ( PyCFunction ) Object_getName, METH_NOARGS,
306          "Returns the name of the object"},
307         {"getParent", ( PyCFunction ) Object_getParent, METH_NOARGS,
308          "Returns the object's parent object"},
309         {"getSize", ( PyCFunction ) Object_getSize, METH_VARARGS,
310          "Returns the object's size (x, y, z)"},
311         {"getTimeOffset", ( PyCFunction ) Object_getTimeOffset, METH_NOARGS,
312          "Returns the object's time offset"},
313         {"getTracked", ( PyCFunction ) Object_getTracked, METH_NOARGS,
314          "Returns the object's tracked object"},
315         {"getType", ( PyCFunction ) Object_getType, METH_NOARGS,
316          "Returns type of string of Object"},
317 /* Particle Interaction */
318          
319         {"getPIStrength", ( PyCFunction ) Object_getPIStrength, METH_NOARGS,
320          "Returns Particle Interaction Strength"},
321         {"setPIStrength", ( PyCFunction ) Object_setPIStrength, METH_VARARGS,
322          "Sets Particle Interaction Strength"},
323         {"getPIFalloff", ( PyCFunction ) Object_getPIFalloff, METH_NOARGS,
324          "Returns Particle Interaction Falloff"},
325         {"setPIFalloff", ( PyCFunction ) Object_setPIFalloff, METH_VARARGS,
326          "Sets Particle Interaction Falloff"},
327         {"getPIMaxDist", ( PyCFunction ) Object_getPIMaxDist, METH_NOARGS,
328          "Returns Particle Interaction Max Distance"},
329         {"setPIMaxDist", ( PyCFunction ) Object_setPIMaxDist, METH_VARARGS,
330          "Sets Particle Interaction Max Distance"},
331         {"getPIUseMaxDist", ( PyCFunction ) Object_getPIUseMaxDist, METH_NOARGS,
332          "Returns bool for Use Max Distace in Particle Interaction "},
333         {"setPIUseMaxDist", ( PyCFunction ) Object_setPIUseMaxDist, METH_VARARGS,
334          "Sets if Max Distance should be used in Particle Interaction"},
335         {"getPIType", ( PyCFunction ) Object_getPIType, METH_NOARGS,
336          "Returns Particle Interaction Type"},
337         {"setPIType", ( PyCFunction ) Object_setPIType, METH_VARARGS,
338          "sets Particle Interaction Type"},
339         {"getPIPerm", ( PyCFunction ) Object_getPIPerm, METH_NOARGS,
340          "Returns Particle Interaction Permiability"},
341         {"setPIPerm", ( PyCFunction ) Object_setPIPerm, METH_VARARGS,
342          "Sets Particle Interaction  Permiability"},
343         {"getPISurfaceDamp", ( PyCFunction ) Object_getPISurfaceDamp, METH_NOARGS,
344          "Returns Particle Interaction Surface Damping"},
345         {"setPISurfaceDamp", ( PyCFunction ) Object_setPISurfaceDamp, METH_VARARGS,
346          "Sets Particle Interaction Surface Damping"},
347         {"getPIRandomDamp", ( PyCFunction ) Object_getPIRandomDamp, METH_NOARGS,
348          "Returns Particle Interaction Random Damping"},
349         {"setPIRandomDamp", ( PyCFunction ) Object_setPIRandomDamp, METH_VARARGS,
350          "Sets Particle Interaction Random Damping"},
351         {"getPIDeflection", ( PyCFunction ) Object_getPIDeflection, METH_NOARGS,
352          "Returns Particle Interaction Deflection"},
353         {"setPIDeflection", ( PyCFunction ) Object_setPIDeflection, METH_VARARGS,
354          "Sets Particle Interaction Deflection"},  
355      
356 /* Softbody */
357
358         {"isSB", ( PyCFunction ) Object_isSB, METH_NOARGS,
359          "True if object is a soft body"},
360         {"getSBMass", ( PyCFunction ) Object_getSBMass, METH_NOARGS,
361          "Returns SB Mass"},
362         {"setSBMass", ( PyCFunction ) Object_setSBMass, METH_VARARGS,
363          "Sets SB Mass"}, 
364         {"getSBGravity", ( PyCFunction ) Object_getSBGravity, METH_NOARGS,
365          "Returns SB Gravity"},
366         {"setSBGravity", ( PyCFunction ) Object_setSBGravity, METH_VARARGS,
367          "Sets SB Gravity"}, 
368         {"getSBFriction", ( PyCFunction ) Object_getSBFriction, METH_NOARGS,
369          "Returns SB Friction"},
370         {"setSBFriction", ( PyCFunction ) Object_setSBFriction, METH_VARARGS,
371          "Sets SB Friction"}, 
372         {"getSBErrorLimit", ( PyCFunction ) Object_getSBErrorLimit, METH_NOARGS,
373          "Returns SB ErrorLimit"},
374         {"setSBErrorLimit", ( PyCFunction ) Object_setSBErrorLimit, METH_VARARGS,
375          "Sets SB ErrorLimit"}, 
376         {"getSBGoalSpring", ( PyCFunction ) Object_getSBGoalSpring, METH_NOARGS,
377          "Returns SB GoalSpring"},
378         {"setSBGoalSpring", ( PyCFunction ) Object_setSBGoalSpring, METH_VARARGS,
379          "Sets SB GoalSpring"}, 
380         {"getSBGoalFriction", ( PyCFunction ) Object_getSBGoalFriction, METH_NOARGS,
381          "Returns SB GoalFriction"},
382         {"setSBGoalFriction", ( PyCFunction ) Object_setSBGoalFriction, METH_VARARGS,
383          "Sets SB GoalFriction"}, 
384         {"getSBMinGoal", ( PyCFunction ) Object_getSBMinGoal, METH_NOARGS,
385          "Returns SB MinGoal"},
386         {"setSBMinGoal", ( PyCFunction ) Object_setSBMinGoal, METH_VARARGS,
387          "Sets SB MinGoal "}, 
388         {"getSBMaxGoal", ( PyCFunction ) Object_getSBMaxGoal, METH_NOARGS,
389          "Returns SB MaxGoal"},
390         {"setSBMaxGoal", ( PyCFunction ) Object_setSBMaxGoal, METH_VARARGS,
391          "Sets SB MaxGoal"},  
392         {"getSBInnerSpring", ( PyCFunction ) Object_getSBInnerSpring, METH_NOARGS,
393          "Returns SB InnerSpring"},
394         {"setSBInnerSpring", ( PyCFunction ) Object_setSBInnerSpring, METH_VARARGS,
395          "Sets SB InnerSpring"},         
396         {"getSBInnerSpringFriction", ( PyCFunction ) Object_getSBInnerSpringFriction, METH_NOARGS,
397          "Returns SB InnerSpringFriction"},
398         {"setSBInnerSpringFriction", ( PyCFunction ) Object_setSBInnerSpringFriction, METH_VARARGS,
399          "Sets SB InnerSpringFriction"},        
400         {"getSBDefaultGoal", ( PyCFunction ) Object_getSBDefaultGoal, METH_NOARGS,
401          "Returns SB DefaultGoal"},
402         {"setSBDefaultGoal", ( PyCFunction ) Object_setSBDefaultGoal, METH_VARARGS,
403          "Sets SB DefaultGoal"},                 
404         {"getSBEnable", ( PyCFunction ) Object_getSBEnable, METH_NOARGS,
405          "Returns SB Enable"},
406         {"setSBEnable", ( PyCFunction ) Object_setSBEnable, METH_VARARGS,
407          "Sets SB Enable"},              
408         {"getSBPostDef", ( PyCFunction ) Object_getSBPostDef, METH_NOARGS,
409          "Returns SB PostDef"},
410         {"setSBPostDef", ( PyCFunction ) Object_setSBPostDef, METH_VARARGS,
411          "Sets SB PostDef"}, 
412         {"getSBUseGoal", ( PyCFunction ) Object_getSBUseGoal, METH_NOARGS,
413          "Returns SB UseGoal"},
414         {"setSBUseGoal", ( PyCFunction ) Object_setSBUseGoal, METH_VARARGS,
415          "Sets SB UseGoal"}, 
416         {"getSBUseEdges", ( PyCFunction ) Object_getSBUseEdges, METH_NOARGS,
417          "Returns SB UseEdges"},
418         {"setSBUseEdges", ( PyCFunction ) Object_setSBUseEdges, METH_VARARGS,
419          "Sets SB UseEdges"}, 
420         {"getSBStiffQuads", ( PyCFunction ) Object_getSBStiffQuads, METH_NOARGS,
421          "Returns SB StiffQuads"},
422         {"setSBStiffQuads", ( PyCFunction ) Object_setSBStiffQuads, METH_VARARGS,
423          "Sets SB StiffQuads"},          
424
425                                  
426         {"getBoundBox", ( PyCFunction ) Object_getBoundBox, METH_NOARGS,
427          "Returns the object's bounding box"},
428         {"getDupliVerts", ( PyCFunction ) Object_getDupliVerts,
429          METH_NOARGS, "Returns state of duplicates propertie"},
430         {"makeDisplayList", ( PyCFunction ) Object_makeDisplayList,
431          METH_NOARGS,
432          "Update this object's Display List. Some changes like turning \n\
433 'SubSurf' on for a mesh need this method (followed by a Redraw) to \n\
434 show the changes on the 3d window."},
435         {"link", ( PyCFunction ) Object_link, METH_VARARGS,
436          "Links Object with data provided in the argument. The data must \n\
437 match the Object's type, so you cannot link a Lamp to a Mesh type object."},
438         {"makeParent", ( PyCFunction ) Object_makeParent, METH_VARARGS,
439          "Makes the object the parent of the objects provided in the \n\
440 argument which must be a list of valid Objects. Optional extra arguments:\n\
441 mode:\n\t0: make parent with inverse\n\t1: without inverse\n\
442 fast:\n\t0: update scene hierarchy automatically\n\t\
443 don't update scene hierarchy (faster). In this case, you must\n\t\
444 explicitely update the Scene hierarchy."},
445         {"makeParentDeform", ( PyCFunction ) Object_makeParentDeform, METH_VARARGS,
446          "Makes the object the deformation parent of the objects provided in the \n\
447 argument which must be a list of valid Objects. Optional extra arguments:\n\
448 mode:\n\t0: make parent with inverse\n\t1: without inverse\n\
449 fast:\n\t0: update scene hierarchy automatically\n\t\
450 don't update scene hierarchy (faster). In this case, you must\n\t\
451 explicitely update the Scene hierarchy."},
452         {"makeParentVertex", ( PyCFunction ) Object_makeParentVertex, METH_VARARGS,
453          "Makes the object the vertex parent of the objects provided in the \n\
454 argument which must be a list of valid Objects. \n\
455 The second argument is a tuple of 1 or 3 positive integers which corresponds \
456 to the index of the vertex you are parenting to.\n\
457 Optional extra arguments:\n\
458 mode:\n\t0: make parent with inverse\n\t1: without inverse\n\
459 fast:\n\t0: update scene hierarchy automatically\n\t\
460 don't update scene hierarchy (faster). In this case, you must\n\t\
461 explicitely update the Scene hierarchy."},
462         {"materialUsage", ( PyCFunction ) Object_materialUsage, METH_VARARGS,
463          "Determines the way the material is used and returns status.\n\
464 Possible arguments (provide as strings):\n\
465 \tData:   Materials assigned to the object's data are shown. (default)\n\
466 \tObject: Materials assigned to the object are shown."},
467         {"setDeltaLocation", ( PyCFunction ) Object_setDeltaLocation,
468          METH_VARARGS,
469          "Sets the object's delta location which must be a vector triple."},
470         {"setDrawMode", ( PyCFunction ) Object_setDrawMode, METH_VARARGS,
471          "Sets the object's drawing mode. The argument can be a sum of:\n\
472 2:      axis\n4:  texspace\n8:  drawname\n16: drawimage\n32: drawwire"},
473         {"setDrawType", ( PyCFunction ) Object_setDrawType, METH_VARARGS,
474          "Sets the object's drawing type. The argument must be one of:\n\
475 1: Bounding box\n2: Wire\n3: Solid\n4: Shaded\n5: Textured"},
476         {"setEuler", ( PyCFunction ) Object_setEuler, METH_VARARGS,
477          "Set the object's rotation according to the specified Euler\n\
478 angles. The argument must be a vector triple"},
479         {"setMatrix", ( PyCFunction ) Object_setMatrix, METH_VARARGS,
480          "Set and apply a new matrix for the object"},
481         {"setLocation", ( PyCFunction ) Object_setLocation, METH_VARARGS,
482          "Set the object's location. The first argument must be a vector\n\
483 triple."},
484         {"setMaterials", ( PyCFunction ) Object_setMaterials, METH_VARARGS,
485          "Sets materials. The argument must be a list of valid material\n\
486 objects."},
487         {"setName", ( PyCFunction ) Object_setName, METH_VARARGS,
488          "Sets the name of the object"},
489         {"setSize", ( PyCFunction ) Object_setSize, METH_VARARGS,
490          "Set the object's size. The first argument must be a vector\n\
491 triple."},
492         {"setTimeOffset", ( PyCFunction ) Object_setTimeOffset, METH_VARARGS,
493          "Set the object's time offset."},
494         {"makeTrack", ( PyCFunction ) Object_makeTrack, METH_VARARGS,
495          "(trackedobj, fast = 0) - Make this object track another.\n\
496          (trackedobj) - the object that will be tracked.\n\
497          (fast = 0) - if 0: update the scene hierarchy automatically.  If you\n\
498          set 'fast' to a nonzero value, don't forget to update the scene yourself\n\
499          (see scene.update())."},
500         {"shareFrom", ( PyCFunction ) Object_shareFrom, METH_VARARGS,
501          "Link data of self with object specified in the argument. This\n\
502 works only if self and the object specified are of the same type."},
503         {"select", ( PyCFunction ) Object_Select, METH_VARARGS,
504          "( 1 or 0 )  - Set the selected state of the object.\n\
505    1 is selected, 0 not selected "},
506         {"setIpo", ( PyCFunction ) Object_setIpo, METH_VARARGS,
507          "(Blender Ipo) - Sets the object's ipo"},
508         {"clearIpo", ( PyCFunction ) Object_clearIpo, METH_NOARGS,
509          "() - Unlink ipo from this object"},
510          {"insertIpoKey", ( PyCFunction ) Object_insertIpoKey, METH_VARARGS,
511          "( Object IPO type ) - Inserts a key into IPO"},
512         {"getAllProperties", ( PyCFunction ) Object_getAllProperties,
513          METH_NOARGS,
514          "() - Get all the properties from this object"},
515         {"addProperty", ( PyCFunction ) Object_addProperty, METH_VARARGS,
516          "() - Add a property to this object"},
517         {"removeProperty", ( PyCFunction ) Object_removeProperty, METH_VARARGS,
518          "() - Remove a property from  this object"},
519         {"getProperty", ( PyCFunction ) Object_getProperty, METH_VARARGS,
520          "() - Get a property from this object by name"},
521         {"removeAllProperties", ( PyCFunction ) Object_removeAllProperties,
522          METH_NOARGS,
523          "() - removeAll a properties from this object"},
524         {"copyAllPropertiesTo", ( PyCFunction ) Object_copyAllPropertiesTo,
525          METH_VARARGS,
526          "() - copy all properties from this object to another object"},
527         {"getScriptLinks", ( PyCFunction ) Object_getScriptLinks, METH_VARARGS,
528          "(eventname) - Get a list of this object's scriptlinks (Text names) "
529          "of the given type\n"
530          "(eventname) - string: FrameChanged, Redraw or Render."},
531         {"addScriptLink", ( PyCFunction ) Object_addScriptLink, METH_VARARGS,
532          "(text, evt) - Add a new object scriptlink.\n"
533          "(text) - string: an existing Blender Text name;\n"
534          "(evt) string: FrameChanged, Redraw or Render."},
535         {"clearScriptLinks", ( PyCFunction ) Object_clearScriptLinks,
536          METH_VARARGS,
537          "() - Delete all scriptlinks from this object.\n"
538          "([s1<,s2,s3...>]) - Delete specified scriptlinks from this object."},
539         {"setDupliVerts", ( PyCFunction ) Object_setDupliVerts,
540          METH_VARARGS, "() - set or reset duplicate child objects on all vertices"},
541         {NULL, NULL, 0, NULL}
542 };
543
544 /*****************************************************************************/
545 /* PythonTypeObject callback function prototypes                         */
546 /*****************************************************************************/
547 static void Object_dealloc( BPy_Object * obj );
548 static PyObject *Object_getAttr( BPy_Object * obj, char *name );
549 static int Object_setAttr( BPy_Object * obj, char *name, PyObject * v );
550 static PyObject *Object_repr( BPy_Object * obj );
551 static int Object_compare( BPy_Object * a, BPy_Object * b );
552
553 /*****************************************************************************/
554 /* Python TypeObject structure definition.                               */
555 /*****************************************************************************/
556 PyTypeObject Object_Type = {
557         PyObject_HEAD_INIT( NULL ) /* requred macro */
558         0,      /* ob_size */
559         "Blender Object",       /* tp_name */
560         sizeof( BPy_Object ),   /* tp_basicsize */
561         0,                      /* tp_itemsize */
562         /* methods */
563         ( destructor ) Object_dealloc,  /* tp_dealloc */
564         0,                      /* tp_print */
565         ( getattrfunc ) Object_getAttr, /* tp_getattr */
566         ( setattrfunc ) Object_setAttr, /* tp_setattr */
567         ( cmpfunc ) Object_compare,     /* tp_compare */
568         ( reprfunc ) Object_repr,       /* tp_repr */
569         0,                      /* tp_as_number */
570         0,                      /* tp_as_sequence */
571         0,                      /* tp_as_mapping */
572         0,                      /* tp_as_hash */
573         0, 0, 0, 0, 0, 0,
574         0,                      /* tp_doc */
575         0, 0, 0, 0, 0, 0,
576         BPy_Object_methods,     /* tp_methods */
577         0,                      /* tp_members */
578         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
579 };
580
581 /*****************************************************************************/
582 /* Function:                      M_Object_New                           */
583 /* Python equivalent:     Blender.Object.New                             */
584 /*****************************************************************************/
585 PyObject *M_Object_New( PyObject * self, PyObject * args )
586 {
587         struct Object *object;
588         BPy_Object *blen_object;
589         int type;
590         char *str_type;
591         char *name = NULL;
592
593         if( !PyArg_ParseTuple( args, "s|s", &str_type, &name ) ) {
594                 EXPP_ReturnPyObjError( PyExc_TypeError,
595                                        "string expected as argument" );
596                 return ( NULL );
597         }
598
599         if( strcmp( str_type, "Armature" ) == 0 )
600                 type = OB_ARMATURE;
601         else if( strcmp( str_type, "Camera" ) == 0 )
602                 type = OB_CAMERA;
603         else if( strcmp( str_type, "Curve" ) == 0 )
604                 type = OB_CURVE;
605         else if (strcmp (str_type, "Text") == 0)        
606                 type = OB_FONT;
607         else if( strcmp( str_type, "Lamp" ) == 0 )
608                 type = OB_LAMP;
609         else if( strcmp( str_type, "Lattice" ) == 0 )
610                 type = OB_LATTICE;
611         else if( strcmp( str_type, "Mball" ) == 0 )
612                 type = OB_MBALL;
613         else if( strcmp( str_type, "Mesh" ) == 0 )
614                 type = OB_MESH;
615         else if( strcmp( str_type, "Surf" ) == 0 )
616                 type = OB_SURF;
617 /*      else if (strcmp (str_type, "Wave") == 0)        type = OB_WAVE; */
618         else if( strcmp( str_type, "Empty" ) == 0 )
619                 type = OB_EMPTY;
620         else {
621                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
622                                                 "Unknown type specified" ) );
623         }
624
625         /* Create a new object. */
626         if( name == NULL ) {
627         /* No name is specified, set the name to the type of the object. */
628                 name = str_type;
629         }
630         object = alloc_libblock( &( G.main->object ), ID_OB, name );
631
632         object->id.us = 0;
633         object->flag = 0;
634         object->type = type;
635
636
637         /* transforms */
638         QuatOne( object->quat );
639         QuatOne( object->dquat );
640
641         object->col[3] = 1.0;   // alpha 
642
643         object->size[0] = object->size[1] = object->size[2] = 1.0;
644         object->loc[0] = object->loc[1] = object->loc[2] = 0.0;
645         Mat4One( object->parentinv );
646         Mat4One( object->obmat );
647         object->dt = OB_SHADED; // drawtype
648
649         if( U.flag & USER_MAT_ON_OB ) {
650                 object->colbits = -1;
651         }
652         switch ( object->type ) {
653         case OB_CAMERA: /* fall through. */
654         case OB_LAMP:
655                 object->trackflag = OB_NEGZ;
656                 object->upflag = OB_POSY;
657                 break;
658         default:
659                 object->trackflag = OB_POSY;
660                 object->upflag = OB_POSZ;
661         }
662         object->ipoflag = OB_OFFS_OB + OB_OFFS_PARENT;
663
664         /* duplivert settings */
665         object->dupon = 1;
666         object->dupoff = 0;
667         object->dupsta = 1;
668         object->dupend = 100;
669
670         /* Gameengine defaults */
671         object->mass = 1.0;
672         object->inertia = 1.0;
673         object->formfactor = 0.4;
674         object->damping = 0.04;
675         object->rdamping = 0.1;
676         object->anisotropicFriction[0] = 1.0;
677         object->anisotropicFriction[1] = 1.0;
678         object->anisotropicFriction[2] = 1.0;
679         object->gameflag = OB_PROP;
680
681         object->lay = 1;        // Layer, by default visible
682         G.totobj++;
683
684         object->data = NULL;
685
686         /* Create a Python object from it. */
687         blen_object =
688                 ( BPy_Object * ) PyObject_NEW( BPy_Object, &Object_Type );
689         blen_object->object = object;
690
691         return ( ( PyObject * ) blen_object );
692 }
693
694 /*****************************************************************************/
695 /* Function:      M_Object_Get                                          */
696 /* Python equivalent:     Blender.Object.Get                            */
697 /*****************************************************************************/
698 PyObject *M_Object_Get( PyObject * self, PyObject * args )
699 {
700         struct Object *object;
701         BPy_Object *blen_object;
702         char *name = NULL;
703
704         PyArg_ParseTuple( args, "|s", &name );
705
706         if( name != NULL ) {
707                 object = GetObjectByName( name );
708
709                 if( object == NULL ) {
710                         /* No object exists with the name specified in the argument name. */
711                         return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
712                                                         "Unknown object specified." ) );
713                 }
714                 blen_object =
715                         ( BPy_Object * ) PyObject_NEW( BPy_Object,
716                                                        &Object_Type );
717                 blen_object->object = object;
718
719                 return ( ( PyObject * ) blen_object );
720         } else {
721                 /* No argument has been given. Return a list of all objects. */
722                 PyObject *obj_list;
723                 Link *link;
724                 int index;
725
726                 obj_list = PyList_New( BLI_countlist( &( G.main->object ) ) );
727
728                 if( obj_list == NULL ) {
729                         return ( EXPP_ReturnPyObjError( PyExc_SystemError,
730                                                         "List creation failed." ) );
731                 }
732
733                 link = G.main->object.first;
734                 index = 0;
735                 while( link ) {
736                         object = ( Object * ) link;
737                         blen_object =
738                                 ( BPy_Object * ) PyObject_NEW( BPy_Object,
739                                                                &Object_Type );
740                         blen_object->object = object;
741
742                         PyList_SetItem( obj_list, index,
743                                         ( PyObject * ) blen_object );
744                         index++;
745                         link = link->next;
746                 }
747                 return ( obj_list );
748         }
749 }
750
751 /*****************************************************************************/
752 /* Function:      M_Object_GetSelected                          */
753 /* Python equivalent:     Blender.Object.GetSelected            */
754 /*****************************************************************************/
755 static PyObject *M_Object_GetSelected( PyObject * self, PyObject * args )
756 {
757         BPy_Object *blen_object;
758         PyObject *list;
759         Base *base_iter;
760
761         if( G.vd == NULL ) {
762                 // No 3d view has been initialized yet, simply return None
763                 Py_INCREF( Py_None );
764                 return Py_None;
765         }
766         list = PyList_New( 0 );
767         if( ( G.scene->basact ) &&
768             ( ( G.scene->basact->flag & SELECT ) &&
769               ( G.scene->basact->lay & G.vd->lay ) ) ) {
770                 /* Active object is first in the list. */
771                 blen_object =
772                         ( BPy_Object * ) PyObject_NEW( BPy_Object,
773                                                        &Object_Type );
774                 if( blen_object == NULL ) {
775                         Py_DECREF( list );
776                         Py_INCREF( Py_None );
777                         return ( Py_None );
778                 }
779                 blen_object->object = G.scene->basact->object;
780                 PyList_Append( list, ( PyObject * ) blen_object );
781                 Py_DECREF( blen_object );
782         }
783
784         base_iter = G.scene->base.first;
785         while( base_iter ) {
786                 if( ( ( base_iter->flag & SELECT ) &&
787                       ( base_iter->lay & G.vd->lay ) ) &&
788                     ( base_iter != G.scene->basact ) ) {
789                         blen_object =
790                                 ( BPy_Object * ) PyObject_NEW( BPy_Object,
791                                                                &Object_Type );
792                         if( blen_object == NULL ) {
793                                 Py_DECREF( list );
794                                 Py_INCREF( Py_None );
795                                 return ( Py_None );
796                         }
797                         blen_object->object = base_iter->object;
798                         PyList_Append( list, ( PyObject * ) blen_object );
799                         Py_DECREF( blen_object );
800                 }
801                 base_iter = base_iter->next;
802         }
803         return ( list );
804 }
805
806 /*****************************************************************************/
807 /* Function:     initObject                                             */
808 /*****************************************************************************/
809 PyObject *Object_Init( void )
810 {
811         PyObject *module;
812
813         Object_Type.ob_type = &PyType_Type;
814
815         module = Py_InitModule3( "Blender.Object", M_Object_methods,
816                                  M_Object_doc );
817
818         PyModule_AddIntConstant( module, "LOC", IPOKEY_LOC );
819         PyModule_AddIntConstant( module, "ROT", IPOKEY_ROT );
820         PyModule_AddIntConstant( module, "SIZE", IPOKEY_SIZE );
821         PyModule_AddIntConstant( module, "LOCROT", IPOKEY_LOCROT );
822         PyModule_AddIntConstant( module, "LOCROTSIZE", IPOKEY_LOCROTSIZE );
823
824         PyModule_AddIntConstant( module, "PI_STRENGTH", IPOKEY_PI_STRENGTH );
825         PyModule_AddIntConstant( module, "PI_FALLOFF", IPOKEY_PI_FALLOFF );
826         PyModule_AddIntConstant( module, "PI_SURFACEDAMP", IPOKEY_PI_SURFACEDAMP );
827         PyModule_AddIntConstant( module, "PI_RANDOMDAMP", IPOKEY_PI_RANDOMDAMP );
828         PyModule_AddIntConstant( module, "PI_PERM", IPOKEY_PI_PERM );
829
830         PyModule_AddIntConstant( module, "NONE",0 );
831         PyModule_AddIntConstant( module, "FORCE",PFIELD_FORCE );
832         PyModule_AddIntConstant( module, "VORTEX",PFIELD_VORTEX );
833         PyModule_AddIntConstant( module, "MAGNET",PFIELD_MAGNET );
834         PyModule_AddIntConstant( module, "WIND",PFIELD_WIND );
835
836         return ( module );
837 }
838
839 /*****************************************************************************/
840 /* Python BPy_Object methods:                                   */
841 /*****************************************************************************/
842
843 static PyObject *Object_buildParts( BPy_Object * self )
844 {
845         void build_particle_system( Object * ob );
846         struct Object *obj = self->object;
847
848         build_particle_system( obj );
849
850         Py_INCREF( Py_None );
851         return ( Py_None );
852 }
853
854 static PyObject *Object_clearIpo( BPy_Object * self )
855 {
856         Object *ob = self->object;
857         Ipo *ipo = ( Ipo * ) ob->ipo;
858
859         if( ipo ) {
860                 ID *id = &ipo->id;
861                 if( id->us > 0 )
862                         id->us--;
863                 ob->ipo = NULL;
864
865                 return EXPP_incr_ret_True();
866         }
867
868         return EXPP_incr_ret_False(); /* no ipo found */
869 }
870
871 static PyObject *Object_clrParent( BPy_Object * self, PyObject * args )
872 {
873         int mode = 0;
874         int fast = 0;
875
876         if( !PyArg_ParseTuple( args, "|ii", &mode, &fast ) ) {
877                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
878                                                 "expected one or two integers as arguments" ) );
879         }
880
881         /* Remove the link only, the object is still in the scene. */
882         self->object->parent = NULL;
883
884         if( mode == 2 ) {
885                 /* Keep transform */
886                 apply_obmat( self->object );
887         }
888
889         if( !fast ) {
890                 DAG_scene_sort( G.scene );
891         }
892
893         Py_INCREF( Py_None );
894         return ( Py_None );
895 }
896
897 static PyObject *Object_clearTrack( BPy_Object * self, PyObject * args )
898 {
899         int mode = 0;
900         int fast = 0;
901
902         if( !PyArg_ParseTuple( args, "|ii", &mode, &fast ) ) {
903                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
904                                                 "expected one or two integers as arguments" ) );
905         }
906
907         /* Remove the link only, the object is still in the scene. */
908         self->object->track = NULL;
909
910         if( mode ) {
911                 /* Keep transform */
912                 apply_obmat( self->object );
913         }
914
915         if( !fast ) {
916                 DAG_scene_sort( G.scene );
917         }
918
919         Py_INCREF( Py_None );
920         return ( Py_None );
921 }
922
923 /* adds object data to a Blender object, if object->data = NULL */
924 int EXPP_add_obdata( struct Object *object )
925 {
926         if( object->data != NULL )
927                 return -1;
928
929         switch ( object->type ) {
930         case OB_ARMATURE:
931                 /* TODO: Do we need to add something to G? (see the OB_LAMP case) */
932                 object->data = add_armature(  );
933                 break;
934         case OB_CAMERA:
935                 /* TODO: Do we need to add something to G? (see the OB_LAMP case) */
936                 object->data = add_camera(  );
937                 break;
938         case OB_CURVE:
939                 object->data = add_curve( OB_CURVE );
940                 G.totcurve++;
941                 break;
942         case OB_LAMP:
943                 object->data = add_lamp(  );
944                 G.totlamp++;
945                 break;
946         case OB_MESH:
947                 object->data = add_mesh(  );
948                 G.totmesh++;
949                 break;
950         case OB_LATTICE:
951                 object->data = ( void * ) add_lattice(  );
952                 object->dt = OB_WIRE;
953                 break;
954         case OB_MBALL:
955                 object->data = add_mball(  );
956                 break;
957
958                 /* TODO the following types will be supported later
959                    case OB_SURF:
960                    object->data = add_curve(OB_SURF);
961                    G.totcurve++;
962                    break;
963                    case OB_FONT:
964                    object->data = add_curve(OB_FONT);
965                    break;
966                    case OB_WAVE:
967                    object->data = add_wave();
968                    break;
969                  */
970         default:
971                 break;
972         }
973
974         if( !object->data )
975                 return -1;
976
977         return 0;
978 }
979
980
981 static PyObject *Object_getData( BPy_Object *self, PyObject *args, PyObject *kwd )
982 {
983         PyObject *data_object;
984         Object *object = self->object;
985         int name_only = 0;
986         static char *kwlist[] = {"name_only", NULL};
987
988         if (!PyArg_ParseTupleAndKeywords(args, kwd, "|i", kwlist, &name_only))
989                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
990                         "expected nothing or bool keyword 'name_only' as argument" );
991
992         /* if there's no obdata, try to create it */
993         if( object->data == NULL ) {
994                 if( EXPP_add_obdata( object ) != 0 ) {  /* couldn't create obdata */
995                         Py_INCREF( Py_None );
996                         return ( Py_None );
997                 }
998         }
999
1000         /* user wants only the name of the data object */
1001         if (name_only) {
1002                 ID *id = object->data;
1003                 data_object = Py_BuildValue("s", id->name+2);
1004
1005                 if (data_object) return data_object;
1006                 return EXPP_ReturnPyObjError (PyExc_MemoryError,
1007                         "could not create a string pyobject!");
1008         }
1009
1010         /* user wants the data object wrapper */
1011         data_object = NULL;
1012
1013         switch ( object->type ) {
1014         case OB_ARMATURE:
1015                 data_object = Armature_CreatePyObject( object->data );
1016                 break;
1017         case OB_CAMERA:
1018                 data_object = Camera_CreatePyObject( object->data );
1019                 break;
1020         case OB_CURVE:
1021                 data_object = Curve_CreatePyObject( object->data );
1022                 break;
1023         case ID_IM:
1024                 data_object = Image_CreatePyObject( object->data );
1025                 break;
1026         case ID_IP:
1027                 data_object = Ipo_CreatePyObject( object->data );
1028                 break;
1029         case OB_LAMP:
1030                 data_object = Lamp_CreatePyObject( object->data );
1031                 break;
1032         case OB_LATTICE:
1033                 data_object = Lattice_CreatePyObject( object->data );
1034                 break;
1035         case ID_MA:
1036                 break;
1037         case OB_MESH:
1038                 data_object = NMesh_CreatePyObject( object->data, object );
1039                 break;
1040         case ID_OB:
1041                 data_object = Object_CreatePyObject( object->data );
1042                 break;
1043         case ID_SCE:
1044                 break;
1045         case ID_TXT:
1046                 data_object = Text_CreatePyObject( object->data );
1047                 break;
1048         case OB_FONT:
1049                 data_object = Text3d_CreatePyObject( object->data );
1050                 break;          
1051         case ID_WO:
1052                 break;
1053         default:
1054                 break;
1055         }
1056         if( data_object == NULL ) {
1057                 Py_INCREF( Py_None );
1058                 return ( Py_None );
1059         } else {
1060                 return ( data_object );
1061         }
1062 }
1063
1064 static PyObject *Object_getDeltaLocation( BPy_Object * self )
1065 {
1066         PyObject *attr = Py_BuildValue( "fff",
1067                                         self->object->dloc[0],
1068                                         self->object->dloc[1],
1069                                         self->object->dloc[2] );
1070
1071         if( attr )
1072                 return ( attr );
1073
1074         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
1075                                         "couldn't get Object.dloc attributes" ) );
1076 }
1077
1078 static PyObject *Object_getDrawMode( BPy_Object * self )
1079 {
1080         PyObject *attr = Py_BuildValue( "b", self->object->dtx );
1081
1082         if( attr )
1083                 return ( attr );
1084
1085         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
1086                                         "couldn't get Object.drawMode attribute" ) );
1087 }
1088
1089 static PyObject *Object_getAction( BPy_Object * self )
1090 {
1091         /*BPy_Action *py_action = NULL; */
1092
1093         if( !self->object->action ) {
1094                 Py_INCREF( Py_None );
1095                 return ( Py_None );
1096         } else {
1097                 return Action_CreatePyObject( self->object->action );
1098         }
1099 }
1100
1101
1102 static PyObject *Object_isSelected( BPy_Object * self )
1103 {
1104         Base *base;
1105
1106         base = FIRSTBASE;
1107         while( base ) {
1108                 if( base->object == self->object ) {
1109                         if( base->flag & SELECT ) {
1110                                 return EXPP_incr_ret_True();
1111                         } else {
1112                                 return EXPP_incr_ret_False();
1113                         }
1114                 }
1115                 base = base->next;
1116         }
1117         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
1118                                         "Internal error: could not find objects selection state" ) );
1119 }
1120
1121
1122 static PyObject *Object_getDrawType( BPy_Object * self )
1123 {
1124         PyObject *attr = Py_BuildValue( "b", self->object->dt );
1125
1126         if( attr )
1127                 return ( attr );
1128
1129         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
1130                                         "couldn't get Object.drawType attribute" ) );
1131 }
1132
1133 static PyObject *Object_getEuler( BPy_Object * self )
1134 {
1135         float eul[3];
1136
1137         eul[0] = self->object->rot[0];
1138         eul[1] = self->object->rot[1];
1139         eul[2] = self->object->rot[2];
1140
1141         return ( PyObject * ) newEulerObject( eul, Py_WRAP );
1142
1143 }
1144
1145 static PyObject *Object_getInverseMatrix( BPy_Object * self )
1146 {
1147         MatrixObject *inverse =
1148                 ( MatrixObject * ) newMatrixObject( NULL, 4, 4, Py_NEW);
1149         Mat4Invert( (float ( * )[4])*inverse->matrix, self->object->obmat );
1150
1151         return ( ( PyObject * ) inverse );
1152 }
1153
1154 static PyObject *Object_getIpo( BPy_Object * self )
1155 {
1156         struct Ipo *ipo = self->object->ipo;
1157
1158         if( !ipo ) {
1159                 Py_INCREF( Py_None );
1160                 return Py_None;
1161         }
1162
1163         return Ipo_CreatePyObject( ipo );
1164 }
1165
1166 static PyObject *Object_getLocation( BPy_Object * self, PyObject * args )
1167 {
1168         PyObject *attr = Py_BuildValue( "fff",
1169                                         self->object->loc[0],
1170                                         self->object->loc[1],
1171                                         self->object->loc[2] );
1172
1173         if( attr )
1174                 return ( attr );
1175
1176         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
1177                                         "couldn't get Object.loc attributes" ) );
1178 }
1179
1180 static PyObject *Object_getMaterials( BPy_Object * self, PyObject * args )
1181 {
1182         int all = 0;
1183
1184         if( !PyArg_ParseTuple( args, "|i", &all ) ) {
1185                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1186                                                 "expected an int or nothing" ) );
1187         }
1188
1189         return ( EXPP_PyList_fromMaterialList( self->object->mat,
1190                                                self->object->totcol, all ) );
1191 }
1192
1193 static PyObject *Object_getMatrix( BPy_Object * self, PyObject * args )
1194 {
1195         float matrix[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
1196                          0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
1197         char *space = "worldspace";     /* default to world */
1198
1199         if( !PyArg_ParseTuple( args, "|s", &space ) ) {
1200                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1201                                                 "expected a string or nothing" ) );
1202         }
1203
1204         if( BLI_streq( space, "worldspace" ) ) {        /* Worldspace matrix */
1205                 disable_where_script( 1 );
1206                 where_is_object( self->object );
1207                 disable_where_script( 0 );
1208         } else if( BLI_streq( space, "localspace" ) ) { /* Localspace matrix */
1209                 object_to_mat4( self->object, (float (*)[4])matrix );
1210                 return newMatrixObject(matrix,4,4,Py_NEW);
1211         } else if( BLI_streq( space, "old_worldspace" ) ) {
1212                 /* old behavior, prior to 2.34, check this method's doc string: */
1213         } else {
1214                 return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
1215                                 "wrong parameter, expected nothing or either 'worldspace' (default),\n\
1216 'localspace' or 'old_worldspace'" ) );
1217         }
1218         return newMatrixObject((float*)self->object->obmat,4,4,Py_WRAP);
1219 }
1220
1221 static PyObject *Object_getName( BPy_Object * self )
1222 {
1223         PyObject *attr = Py_BuildValue( "s", self->object->id.name + 2 );
1224
1225         if( attr )
1226                 return ( attr );
1227
1228         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
1229                                         "couldn't get the name of the Object" ) );
1230 }
1231
1232 static PyObject *Object_getParent( BPy_Object * self )
1233 {
1234         PyObject *attr;
1235
1236         if( self->object->parent == NULL )
1237                 return EXPP_incr_ret( Py_None );
1238
1239         attr = Object_CreatePyObject( self->object->parent );
1240
1241         if( attr ) {
1242                 return ( attr );
1243         }
1244
1245         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
1246                                         "couldn't get Object.parent attribute" ) );
1247 }
1248
1249 static PyObject *Object_getSize( BPy_Object * self, PyObject * args )
1250 {
1251         PyObject *attr = Py_BuildValue( "fff",
1252                                         self->object->size[0],
1253                                         self->object->size[1],
1254                                         self->object->size[2] );
1255
1256         if( attr )
1257                 return ( attr );
1258
1259         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
1260                                         "couldn't get Object.size attributes" ) );
1261 }
1262
1263 static PyObject *Object_getTimeOffset( BPy_Object * self )
1264 {
1265         PyObject *attr = Py_BuildValue( "f", self->object->sf );
1266
1267         if( attr )
1268                 return ( attr );
1269
1270         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
1271                                         "couldn't get Object.sf attributes" ) );
1272 }
1273
1274
1275 static PyObject *Object_getTracked( BPy_Object * self )
1276 {
1277         PyObject *attr;
1278
1279         if( self->object->track == NULL )
1280                 return EXPP_incr_ret( Py_None );
1281
1282         attr = Object_CreatePyObject( self->object->track );
1283
1284         if( attr ) {
1285                 return ( attr );
1286         }
1287
1288         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
1289                                         "couldn't get Object.track attribute" ) );
1290 }
1291
1292 static PyObject *Object_getType( BPy_Object * self )
1293 {
1294         switch ( self->object->type ) {
1295         case OB_ARMATURE:
1296                 return ( Py_BuildValue( "s", "Armature" ) );
1297         case OB_CAMERA:
1298                 return ( Py_BuildValue( "s", "Camera" ) );
1299         case OB_CURVE:
1300                 return ( Py_BuildValue( "s", "Curve" ) );
1301         case OB_EMPTY:
1302                 return ( Py_BuildValue( "s", "Empty" ) );
1303         case OB_FONT:
1304                 return ( Py_BuildValue( "s", "Text" ) );
1305         case OB_LAMP:
1306                 return ( Py_BuildValue( "s", "Lamp" ) );
1307         case OB_LATTICE:
1308                 return ( Py_BuildValue( "s", "Lattice" ) );
1309         case OB_MBALL:
1310                 return ( Py_BuildValue( "s", "MBall" ) );
1311         case OB_MESH:
1312                 return ( Py_BuildValue( "s", "Mesh" ) );
1313         case OB_SURF:
1314                 return ( Py_BuildValue( "s", "Surf" ) );
1315         case OB_WAVE:
1316                 return ( Py_BuildValue( "s", "Wave" ) );
1317         default:
1318                 return ( Py_BuildValue( "s", "unknown" ) );
1319         }
1320 }
1321
1322
1323 static PyObject *Object_getBoundBox( BPy_Object * self )
1324 {
1325         int i;
1326         float *vec = NULL;
1327         PyObject *vector, *bbox;
1328
1329         if( !self->object->data )
1330                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
1331                                               "This object isn't linked to any object data (mesh, curve, etc) yet" );
1332
1333         if( !self->object->bb ) {       /* if no ob bbox, we look in obdata */
1334                 Mesh *me;
1335                 Curve *curve;
1336                 switch ( self->object->type ) {
1337                 case OB_MESH:
1338                         me = self->object->data;
1339                         vec = (float*) mesh_get_bb(me)->vec;
1340                         break;
1341                 case OB_CURVE:
1342                 case OB_FONT:
1343                 case OB_SURF:
1344                         curve = self->object->data;
1345                         if( !curve->bb )
1346                                 tex_space_curve( curve );
1347                         vec = ( float * ) curve->bb->vec;
1348                         break;
1349                 default:
1350                         Py_INCREF( Py_None );
1351                         return Py_None;
1352                 }
1353
1354                 {               /* transform our obdata bbox by the obmat.
1355                                    the obmat is 4x4 homogeneous coords matrix.
1356                                    each bbox coord is xyz, so we make it homogenous
1357                                    by padding it with w=1.0 and doing the matrix mult.
1358                                    afterwards we divide by w to get back to xyz.
1359                                  */
1360                         /* printmatrix4( "obmat", self->object->obmat); */
1361
1362                         float tmpvec[4];        /* tmp vector for homogenous coords math */
1363                         int i;
1364                         float *from;
1365
1366                         bbox = PyList_New( 8 );
1367                         if( !bbox )
1368                                 return EXPP_ReturnPyObjError
1369                                         ( PyExc_MemoryError,
1370                                           "couldn't create pylist" );
1371                         for( i = 0, from = vec; i < 8; i++, from += 3 ) {
1372                                 memcpy( tmpvec, from, 3 * sizeof( float ) );
1373                                 tmpvec[3] = 1.0f;       /* set w coord */
1374                                 Mat4MulVec4fl( self->object->obmat, tmpvec );
1375                                 /* divide x,y,z by w */
1376                                 tmpvec[0] /= tmpvec[3];
1377                                 tmpvec[1] /= tmpvec[3];
1378                                 tmpvec[2] /= tmpvec[3];
1379
1380 #if 0
1381                                 {       /* debug print stuff */
1382                                         int i;
1383
1384                                         printf( "\nobj bbox transformed\n" );
1385                                         for( i = 0; i < 4; ++i )
1386                                                 printf( "%f ", tmpvec[i] );
1387
1388                                         printf( "\n" );
1389                                 }
1390 #endif
1391
1392                                 /* because our bounding box is calculated and
1393                                    does not have its own memory,
1394                                    we must create vectors that allocate space */
1395
1396                                 vector = newVectorObject( NULL, 3, Py_NEW);
1397                                 memcpy( ( ( VectorObject * ) vector )->vec,
1398                                         tmpvec, 3 * sizeof( float ) );
1399                                 PyList_SET_ITEM( bbox, i, vector );
1400                         }
1401                 }
1402         } else {                /* the ob bbox exists */
1403                 vec = ( float * ) self->object->bb->vec;
1404
1405                 if( !vec )
1406                         return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1407                                                       "couldn't retrieve bounding box data" );
1408
1409                 bbox = PyList_New( 8 );
1410
1411                 if( !bbox )
1412                         return EXPP_ReturnPyObjError( PyExc_MemoryError,
1413                                                       "couldn't create pylist" );
1414
1415                 /* create vectors referencing object bounding box coords */
1416                 for( i = 0; i < 8; i++ ) {
1417                         vector = newVectorObject( vec, 3, Py_WRAP );
1418                         PyList_SET_ITEM( bbox, i, vector );
1419                         vec += 3;
1420                 }
1421         }
1422
1423         return bbox;
1424 }
1425
1426
1427 static PyObject *Object_makeDisplayList( BPy_Object * self )
1428 {
1429         Object *ob = self->object;
1430
1431         if( ob->type == OB_FONT )
1432                 text_to_curve( ob, 0 );
1433
1434         makeDispList( ob );
1435
1436         Py_INCREF( Py_None );
1437         return Py_None;
1438 }
1439
1440 static PyObject *Object_link( BPy_Object * self, PyObject * args )
1441 {
1442         PyObject *py_data;
1443         ID *id;
1444         ID *oldid;
1445         int obj_id;
1446         void *data = NULL;
1447
1448         if( !PyArg_ParseTuple( args, "O", &py_data ) ) {
1449                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1450                                                 "expected an object as argument" ) );
1451         }
1452         if( Armature_CheckPyObject( py_data ) )
1453                 data = ( void * ) Armature_FromPyObject( py_data );
1454         if( Camera_CheckPyObject( py_data ) )
1455                 data = ( void * ) Camera_FromPyObject( py_data );
1456         if( Lamp_CheckPyObject( py_data ) )
1457                 data = ( void * ) Lamp_FromPyObject( py_data );
1458         if( Curve_CheckPyObject( py_data ) )
1459                 data = ( void * ) Curve_FromPyObject( py_data );
1460         if( NMesh_CheckPyObject( py_data ) )
1461                 data = ( void * ) Mesh_FromPyObject( py_data, self->object );
1462         if( Lattice_CheckPyObject( py_data ) )
1463                 data = ( void * ) Lattice_FromPyObject( py_data );
1464         if( Metaball_CheckPyObject( py_data ) )
1465                 data = ( void * ) Metaball_FromPyObject( py_data );
1466         if( Text3d_CheckPyObject( py_data ) )
1467                 data = ( void * ) Text3d_FromPyObject( py_data );
1468
1469         /* have we set data to something good? */
1470         if( !data ) {
1471                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1472                                                 "link argument type is not supported " ) );
1473         }
1474
1475         oldid = ( ID * ) self->object->data;
1476         id = ( ID * ) data;
1477         obj_id = MAKE_ID2( id->name[0], id->name[1] );
1478
1479         switch ( obj_id ) {
1480         case ID_AR:
1481                 if( self->object->type != OB_ARMATURE ) {
1482                         return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1483                                                         "The 'link' object is incompatible with the base object" ) );
1484                 }
1485                 break;
1486         case ID_CA:
1487                 if( self->object->type != OB_CAMERA ) {
1488                         return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1489                                                         "The 'link' object is incompatible with the base object" ) );
1490                 }
1491                 break;
1492         case ID_LA:
1493                 if( self->object->type != OB_LAMP ) {
1494                         return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1495                                                         "The 'link' object is incompatible with the base object" ) );
1496                 }
1497                 break;
1498         case ID_ME:
1499                 if( self->object->type != OB_MESH ) {
1500                         return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1501                                                         "The 'link' object is incompatible with the base object" ) );
1502                 }
1503                 break;
1504         case ID_CU:
1505                 if( self->object->type != OB_CURVE && self->object->type != OB_FONT ) {
1506                         return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1507                                                         "The 'link' object is incompatible with the base object" ) );
1508                 }
1509                 break;
1510         case ID_LT:
1511                 if( self->object->type != OB_LATTICE ) {
1512                         return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1513                                                         "The 'link' object is incompatible with the base object" ) );
1514                 }
1515                 break;
1516         case ID_MB:
1517                 if( self->object->type != OB_MBALL ) {
1518                         return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1519                                                         "The 'link' object is incompatible with the base object" ) );
1520                 }
1521                 break;
1522         default:
1523                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1524                                                 "Linking this object type is not supported" ) );
1525         }
1526         self->object->data = data;
1527
1528         if( self->object->type == OB_MESH ) {
1529                 self->object->totcol = 0;
1530                 EXPP_synchronizeMaterialLists( self->object );
1531         }
1532
1533         //creates the curve for the text object
1534         if (self->object->type == OB_FONT) 
1535                 text_to_curve(self->object, 0);
1536
1537         id_us_plus( id );
1538         if( oldid ) {
1539                 if( oldid->us > 0 ) {
1540                         oldid->us--;
1541                 } else {
1542                         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
1543                                                         "old object reference count below 0" ) );
1544                 }
1545         }
1546         return EXPP_incr_ret( Py_None );
1547 }
1548
1549 static PyObject *Object_makeParentVertex( BPy_Object * self, PyObject * args )
1550 {
1551         PyObject *list;
1552         PyObject *vlist;
1553         PyObject *py_child;
1554         PyObject *ret_val;
1555         Object *parent;
1556         int noninverse = 0;
1557         int fast = 0;
1558         int partype;
1559         int v1, v2=0, v3=0;
1560         int i, vlen;
1561
1562         /* Check if the arguments passed to makeParent are valid. */
1563         if( !PyArg_ParseTuple( args, "OO|ii", &list, &vlist, &noninverse, &fast ) ) {
1564                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1565                                                 "expected a list of objects, a tuple of integers and one or two integers as arguments" ) );
1566         }
1567         if( !PySequence_Check( list ) ) {
1568                 return ( EXPP_ReturnPyObjError( PyExc_TypeError,
1569                                                 "expected a list of objects" ) );
1570         }
1571
1572         if (!PyTuple_Check( vlist ))
1573                 return ( EXPP_ReturnPyObjError( PyExc_TypeError,
1574                                                 "expected a tuple of integers" ) );
1575
1576         vlen = PyTuple_Size( vlist );
1577         switch (vlen) {
1578         case 1:
1579                 if( !PyArg_ParseTuple( vlist, "i", &v1 ) )
1580                         return ( EXPP_ReturnPyObjError( PyExc_TypeError,
1581                                                         "expected a tuple of 1 or 3 integers" ) );
1582
1583                 if ( v1 < 0 )
1584                         return ( EXPP_ReturnPyObjError( PyExc_ValueError,
1585                                                         "indices must be strictly positive" ) );
1586
1587                 partype = PARVERT1;
1588                 break;
1589         case 3:
1590                 if( !PyArg_ParseTuple( vlist, "iii", &v1, &v2, &v3 ) )
1591                         return ( EXPP_ReturnPyObjError( PyExc_TypeError,
1592                                                         "expected a tuple of 1 or 3 integers" ) );
1593
1594                 if ( v1 < 0 || v2 < 0 || v3 < 0)
1595                         return ( EXPP_ReturnPyObjError( PyExc_ValueError,
1596                                                         "indices must be strictly positive" ) );
1597                 partype = PARVERT3;
1598                 break;
1599         default:
1600                 return ( EXPP_ReturnPyObjError( PyExc_TypeError,
1601                                                 "expected a tuple of 1 or 3 integers" ) );
1602         }
1603
1604         parent = ( Object * ) self->object;
1605
1606         if (!ELEM3(parent->type, OB_MESH, OB_CURVE, OB_SURF))
1607                 return ( EXPP_ReturnPyObjError( PyExc_TypeError,
1608                                                 "Parent Vertex only applies to curve, mesh or surface objects" ) );
1609
1610         if (parent->id.us == 0)
1611                 return EXPP_ReturnPyObjError (PyExc_RuntimeError,
1612                         "object must be linked to a scene before it can become a parent");
1613
1614         /* Check if the PyObject passed in list is a Blender object. */
1615         for( i = 0; i < PySequence_Length( list ); i++ ) {
1616                 py_child = PySequence_GetItem( list, i );
1617
1618                 ret_val = internal_makeParent(parent, py_child, partype, noninverse, fast, v1, v2, v3);
1619                 Py_DECREF (py_child);
1620
1621                 if (ret_val)
1622                         Py_DECREF(ret_val);
1623                 else {
1624                         if (!fast)      /* need to sort when interupting in the middle of the list */
1625                                 DAG_scene_sort( G.scene );
1626                         return NULL; /* error has been set already */
1627                 }
1628         }
1629
1630         if (!fast) /* otherwise, only sort at the end */
1631                 DAG_scene_sort( G.scene );
1632
1633         return EXPP_incr_ret( Py_None );
1634 }
1635
1636 static PyObject *Object_makeParentDeform( BPy_Object * self, PyObject * args )
1637 {
1638         PyObject *list;
1639         PyObject *py_child;
1640         PyObject *ret_val;
1641         Object *parent;
1642         int noninverse = 0;
1643         int fast = 0;
1644         int i;
1645
1646         /* Check if the arguments passed to makeParent are valid. */
1647         if( !PyArg_ParseTuple( args, "O|ii", &list, &noninverse, &fast ) ) {
1648                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1649                                                 "expected a list of objects and one or two integers as arguments" ) );
1650         }
1651         if( !PySequence_Check( list ) ) {
1652                 return ( EXPP_ReturnPyObjError( PyExc_TypeError,
1653                                                 "expected a list of objects" ) );
1654         }
1655
1656         parent = ( Object * ) self->object;
1657
1658         if (parent->type != OB_CURVE && parent->type != OB_ARMATURE)
1659                 return ( EXPP_ReturnPyObjError( PyExc_ValueError,
1660                                                 "Parent Deform only applies to curve or armature objects" ) );
1661
1662         if (parent->id.us == 0)
1663                 return EXPP_ReturnPyObjError (PyExc_RuntimeError,
1664                         "object must be linked to a scene before it can become a parent");
1665
1666         /* Check if the PyObject passed in list is a Blender object. */
1667         for( i = 0; i < PySequence_Length( list ); i++ ) {
1668                 py_child = PySequence_GetItem( list, i );
1669
1670                 ret_val = internal_makeParent(parent, py_child, PARSKEL, noninverse, fast, 0, 0, 0);
1671                 Py_DECREF (py_child);
1672
1673                 if (ret_val)
1674                         Py_DECREF(ret_val);
1675                 else {
1676                         if (!fast)      /* need to sort when interupting in the middle of the list */
1677                                 DAG_scene_sort( G.scene );
1678                         return NULL; /* error has been set already */
1679                 }
1680         }
1681
1682         if (!fast) /* otherwise, only sort at the end */
1683                 DAG_scene_sort( G.scene );
1684
1685         return EXPP_incr_ret( Py_None );
1686 }
1687
1688 static PyObject *Object_makeParent( BPy_Object * self, PyObject * args )
1689 {
1690         PyObject *list;
1691         PyObject *py_child;
1692         PyObject *ret_val;
1693         Object *parent;
1694         int noninverse = 0;
1695         int fast = 0;
1696         int i;
1697
1698         /* Check if the arguments passed to makeParent are valid. */
1699         if( !PyArg_ParseTuple( args, "O|ii", &list, &noninverse, &fast ) ) {
1700                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1701                                                 "expected a list of objects and one or two integers as arguments" ) );
1702         }
1703         if( !PySequence_Check( list ) ) {
1704                 return ( EXPP_ReturnPyObjError( PyExc_TypeError,
1705                                                 "expected a list of objects" ) );
1706         }
1707
1708         parent = ( Object * ) self->object;
1709
1710         if (parent->id.us == 0)
1711                 return EXPP_ReturnPyObjError (PyExc_RuntimeError,
1712                         "object must be linked to a scene before it can become a parent");
1713
1714         /* Check if the PyObject passed in list is a Blender object. */
1715         for( i = 0; i < PySequence_Length( list ); i++ ) {
1716                 py_child = PySequence_GetItem( list, i );
1717
1718                 ret_val = internal_makeParent(parent, py_child, PAROBJECT, noninverse, fast, 0, 0, 0);
1719                 Py_DECREF (py_child);
1720
1721                 if (ret_val)
1722                         Py_DECREF(ret_val);
1723                 else {
1724                         if (!fast)      /* need to sort when interupting in the middle of the list */
1725                                 DAG_scene_sort( G.scene );
1726                         return NULL; /* error has been set already */
1727                 }
1728         }
1729
1730         if (!fast) /* otherwise, only sort at the end */
1731                 DAG_scene_sort( G.scene );
1732
1733         return EXPP_incr_ret( Py_None );
1734 }
1735
1736 static PyObject *internal_makeParent(Object *parent, PyObject *py_child,
1737                                                                          int partype,   /* parenting type */
1738                                                                          int noninverse, int fast,      /* parenting arguments */
1739                                                                          int v1, int v2, int v3 /* for vertex parent */
1740                                                                          )
1741 {
1742         Object *child = NULL;
1743
1744         if( Object_CheckPyObject( py_child ) )
1745                 child = ( Object * ) Object_FromPyObject( py_child );
1746
1747         if( child == NULL ) {
1748                 return ( EXPP_ReturnPyObjError( PyExc_TypeError,
1749                                                 "Object Type expected" ) );
1750         }
1751
1752         if( test_parent_loop( parent, child ) ) {
1753                 return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
1754                                                 "parenting loop detected - parenting failed" ) );
1755         }
1756
1757         if (partype == PARSKEL && child->type != OB_MESH)
1758                 child->partype = PAROBJECT;
1759         else
1760                 child->partype = partype;
1761
1762         if (partype == PARVERT3) {
1763                 child->par1 = v1;
1764                 child->par2 = v2;
1765                 child->par3 = v3;
1766         }
1767         else if (partype == PARVERT1) {
1768                 child->par1 = v1;
1769         }
1770
1771         child->parent = parent;
1772         //py_obj_child = (BPy_Object *) py_child;
1773         if( noninverse == 1 ) {
1774                 /* Parent inverse = unity */
1775                 child->loc[0] = 0.0;
1776                 child->loc[1] = 0.0;
1777                 child->loc[2] = 0.0;
1778         } else {
1779                 what_does_parent( child );
1780                 Mat4Invert( child->parentinv, workob.obmat );
1781                 clear_workob();
1782         }
1783
1784         if( !fast ) {
1785                 child->recalc |= OB_RECALC_OB;
1786         }
1787
1788         return EXPP_incr_ret( Py_None );
1789 }
1790
1791 static PyObject *Object_materialUsage( BPy_Object * self, PyObject * args )
1792 {
1793         return ( EXPP_ReturnPyObjError( PyExc_NotImplementedError,
1794                                         "materialUsage: not yet implemented" ) );
1795 }
1796
1797 static PyObject *Object_setDeltaLocation( BPy_Object * self, PyObject * args )
1798 {
1799         float dloc1;
1800         float dloc2;
1801         float dloc3;
1802         int status;
1803
1804         if( PyObject_Length( args ) == 3 )
1805                 status = PyArg_ParseTuple( args, "fff", &dloc1, &dloc2,
1806                                            &dloc3 );
1807         else
1808                 status = PyArg_ParseTuple( args, "(fff)", &dloc1, &dloc2,
1809                                            &dloc3 );
1810
1811         if( !status )
1812                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
1813                                               "expected list argument of 3 floats" );
1814
1815         self->object->dloc[0] = dloc1;
1816         self->object->dloc[1] = dloc2;
1817         self->object->dloc[2] = dloc3;
1818
1819         Py_INCREF( Py_None );
1820         return ( Py_None );
1821 }
1822
1823 static PyObject *Object_setDrawMode( BPy_Object * self, PyObject * args )
1824 {
1825         char dtx;
1826
1827         if( !PyArg_ParseTuple( args, "b", &dtx ) ) {
1828                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1829                                                 "expected an integer as argument" ) );
1830         }
1831         self->object->dtx = dtx;
1832
1833         Py_INCREF( Py_None );
1834         return ( Py_None );
1835 }
1836
1837 static PyObject *Object_setDrawType( BPy_Object * self, PyObject * args )
1838 {
1839         char dt;
1840
1841         if( !PyArg_ParseTuple( args, "b", &dt ) ) {
1842                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1843                                                 "expected an integer as argument" ) );
1844         }
1845         self->object->dt = dt;
1846
1847         Py_INCREF( Py_None );
1848         return ( Py_None );
1849 }
1850
1851 static PyObject *Object_setEuler( BPy_Object * self, PyObject * args )
1852 {
1853         float rot1;
1854         float rot2;
1855         float rot3;
1856         int status = 0;         /* failure */
1857         PyObject *ob;
1858
1859         /* 
1860            args is either a tuple/list of floats or an euler.
1861            for backward compatibility, we also accept 3 floats.
1862          */
1863
1864         /* do we have 3 floats? */
1865         if( PyObject_Length( args ) == 3 ) {
1866                 status = PyArg_ParseTuple( args, "fff", &rot1, &rot2, &rot3 );
1867         } else {                //test to see if it's a list or a euler
1868                 if( PyArg_ParseTuple( args, "O", &ob ) ) {
1869                         if( EulerObject_Check( ob ) ) {
1870                                 rot1 = ( ( EulerObject * ) ob )->eul[0];
1871                                 rot2 = ( ( EulerObject * ) ob )->eul[1];
1872                                 rot3 = ( ( EulerObject * ) ob )->eul[2];
1873                                 status = 1;     /* success! */
1874                         } else if( PySequence_Check( ob ) )
1875                                 status = PyArg_ParseTuple( args, "(fff)",
1876                                                            &rot1, &rot2,
1877                                                            &rot3 );
1878                         else {  /* not an euler or tuple */
1879
1880                                 /* python C api doc says don't decref this */
1881                                 /*Py_DECREF (ob); */
1882
1883                                 status = 0;     /* false */
1884                         }
1885                 } else {        /* arg parsing failed */
1886                         status = 0;
1887                 }
1888         }
1889
1890         if( !status )           /* parsing args failed */
1891                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1892                                                 "expected euler or list/tuple of 3 floats " ) );
1893
1894         self->object->rot[0] = rot1;
1895         self->object->rot[1] = rot2;
1896         self->object->rot[2] = rot3;
1897
1898         Py_INCREF( Py_None );
1899         return ( Py_None );
1900 }
1901
1902
1903 static PyObject *Object_setMatrix( BPy_Object * self, PyObject * args )
1904 {
1905         MatrixObject *mat;
1906         int x, y;
1907
1908         if( !PyArg_ParseTuple( args, "O!", &matrix_Type, &mat ) )
1909                 return EXPP_ReturnPyObjError
1910                         ( PyExc_TypeError,
1911                           "expected matrix object as argument" );
1912
1913         for( x = 0; x < 4; x++ ) {
1914                 for( y = 0; y < 4; y++ ) {
1915                         self->object->obmat[x][y] = mat->matrix[x][y];
1916                 }
1917         }
1918         apply_obmat( self->object );
1919
1920         Py_INCREF( Py_None );
1921         return ( Py_None );
1922 }
1923
1924
1925 static PyObject *Object_setIpo( BPy_Object * self, PyObject * args )
1926 {
1927         PyObject *pyipo = 0;
1928         Ipo *ipo = NULL;
1929         Ipo *oldipo;
1930
1931         if( !PyArg_ParseTuple( args, "O!", &Ipo_Type, &pyipo ) )
1932                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1933                                               "expected Ipo as argument" );
1934
1935         ipo = Ipo_FromPyObject( pyipo );
1936
1937         if( !ipo )
1938                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1939                                               "null ipo!" );
1940
1941         if( ipo->blocktype != ID_OB )
1942                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1943                                               "this ipo is not an object ipo" );
1944
1945         oldipo = self->object->ipo;
1946         if( oldipo ) {
1947                 ID *id = &oldipo->id;
1948                 if( id->us > 0 )
1949                         id->us--;
1950         }
1951
1952         ( ( ID * ) & ipo->id )->us++;
1953
1954         self->object->ipo = ipo;
1955
1956         Py_INCREF( Py_None );
1957         return Py_None;
1958 }
1959
1960 /*
1961  * Object_insertIpoKey()
1962  *  inserts Object IPO key for LOC, ROT, SIZE, LOCROT, or LOCROTSIZE
1963  */
1964
1965 static PyObject *Object_insertIpoKey( BPy_Object * self, PyObject * args )
1966 {
1967     int key = 0;
1968     
1969         if( !PyArg_ParseTuple( args, "i", &( key ) ) )
1970                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
1971                                                                                 "expected int argument" ) );
1972
1973         if (key == IPOKEY_LOC || key == IPOKEY_LOCROT || key == IPOKEY_LOCROTSIZE){
1974                 insertkey((ID *)self->object,OB_LOC_X);
1975                 insertkey((ID *)self->object,OB_LOC_Y);
1976                 insertkey((ID *)self->object,OB_LOC_Z);      
1977         }
1978     if (key == IPOKEY_ROT || key == IPOKEY_LOCROT || key == IPOKEY_LOCROTSIZE){
1979                 insertkey((ID *)self->object,OB_ROT_X);
1980                 insertkey((ID *)self->object,OB_ROT_Y);
1981                 insertkey((ID *)self->object,OB_ROT_Z);      
1982         }
1983     if (key == IPOKEY_SIZE || key == IPOKEY_LOCROTSIZE ){
1984                 insertkey((ID *)self->object,OB_SIZE_X);
1985                 insertkey((ID *)self->object,OB_SIZE_Y);
1986                 insertkey((ID *)self->object,OB_SIZE_Z);      
1987         }
1988
1989     if (key == IPOKEY_PI_STRENGTH ){
1990         insertkey((ID *)self->object, OB_PD_FSTR);   
1991         }
1992
1993     if (key == IPOKEY_PI_FALLOFF ){
1994         insertkey((ID *)self->object, OB_PD_FFALL);   
1995         }
1996         
1997     if (key == IPOKEY_PI_SURFACEDAMP ){
1998         insertkey((ID *)self->object, OB_PD_SDAMP);   
1999         }
2000
2001     if (key == IPOKEY_PI_RANDOMDAMP ){
2002         insertkey((ID *)self->object, OB_PD_RDAMP);   
2003         }
2004
2005     if (key == IPOKEY_PI_PERM ){
2006         insertkey((ID *)self->object, OB_PD_PERM);   
2007         }
2008
2009
2010         allspace(REMAKEIPO, 0);
2011         EXPP_allqueue(REDRAWIPO, 0);
2012         EXPP_allqueue(REDRAWVIEW3D, 0);
2013         EXPP_allqueue(REDRAWACTION, 0);
2014         EXPP_allqueue(REDRAWNLA, 0);
2015
2016         return EXPP_incr_ret( Py_None );
2017 }
2018
2019
2020
2021 static PyObject *Object_setLocation( BPy_Object * self, PyObject * args )
2022 {
2023         float loc1;
2024         float loc2;
2025         float loc3;
2026         int status;
2027
2028         if( PyObject_Length( args ) == 3 )
2029                 status = PyArg_ParseTuple( args, "fff", &loc1, &loc2, &loc3 );
2030         else
2031                 status = PyArg_ParseTuple( args, "(fff)", &loc1, &loc2,
2032                                            &loc3 );
2033
2034         if( !status )
2035                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
2036                                               "expected list argument of 3 floats" );
2037
2038         self->object->loc[0] = loc1;
2039         self->object->loc[1] = loc2;
2040         self->object->loc[2] = loc3;
2041
2042         Py_INCREF( Py_None );
2043         return ( Py_None );
2044 }
2045
2046 static PyObject *Object_setMaterials( BPy_Object * self, PyObject * args )
2047 {
2048         PyObject *list;
2049         int len;
2050         int i;
2051         Material **matlist;
2052
2053         if( !PyArg_ParseTuple( args, "O", &list ) ) {
2054                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
2055                                                 "expected a list of materials as argument" ) );
2056         }
2057
2058         len = PySequence_Length( list );
2059         if( len > 0 ) {
2060                 matlist = EXPP_newMaterialList_fromPyList( list );
2061                 if( !matlist ) {
2062                         return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
2063                                                         "material list must be a list of valid materials!" ) );
2064                 }
2065                 if( ( len < 0 ) || ( len > MAXMAT ) ) {
2066                         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
2067                                                         "material list should have at least 1, at most 16 entries" ) );
2068                 }
2069
2070                 if( self->object->mat ) {
2071                         EXPP_releaseMaterialList( self->object->mat,
2072                                                   self->object->totcol );
2073                 }
2074                 /* Increase the user count on all materials */
2075                 for( i = 0; i < len; i++ ) {
2076                         if( matlist[i] )
2077                                 id_us_plus( ( ID * ) matlist[i] );
2078                 }
2079                 self->object->mat = matlist;
2080                 self->object->totcol = len;
2081                 self->object->actcol = len;
2082
2083                 switch ( self->object->type ) {
2084                 case OB_CURVE:  /* fall through */
2085                 case OB_FONT:   /* fall through */
2086                 case OB_MESH:   /* fall through */
2087                 case OB_MBALL:  /* fall through */
2088                 case OB_SURF:
2089                         EXPP_synchronizeMaterialLists( self->object );
2090                         break;
2091                 default:
2092                         break;
2093                 }
2094         }
2095         return EXPP_incr_ret( Py_None );
2096 }
2097
2098 static PyObject *Object_setName( BPy_Object * self, PyObject * args )
2099 {
2100         char *name;
2101         char buf[21];
2102
2103         if( !PyArg_ParseTuple( args, "s", &name ) ) {
2104                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
2105                                                 "expected a String as argument" ) );
2106         }
2107
2108         PyOS_snprintf( buf, sizeof( buf ), "%s", name );
2109
2110         rename_id( &self->object->id, buf );
2111
2112         Py_INCREF( Py_None );
2113         return ( Py_None );
2114 }
2115
2116 static PyObject *Object_setSize( BPy_Object * self, PyObject * args )
2117 {
2118         float sizex;
2119         float sizey;
2120         float sizez;
2121         int status;
2122
2123         if( PyObject_Length( args ) == 3 )
2124                 status = PyArg_ParseTuple( args, "fff", &sizex, &sizey,
2125                                            &sizez );
2126         else
2127                 status = PyArg_ParseTuple( args, "(fff)", &sizex, &sizey,
2128                                            &sizez );
2129
2130         if( !status )
2131                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
2132                                               "expected list argument of 3 floats" );
2133
2134         self->object->size[0] = sizex;
2135         self->object->size[1] = sizey;
2136         self->object->size[2] = sizez;
2137
2138         Py_INCREF( Py_None );
2139         return ( Py_None );
2140 }
2141
2142 static PyObject *Object_setTimeOffset( BPy_Object * self, PyObject * args )
2143 {
2144         float newTimeOffset;
2145
2146         if( !PyArg_ParseTuple( args, "f", &newTimeOffset ) ) {
2147                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
2148                                                 "expected a float as argument" ) );
2149         }
2150
2151         self->object->sf = newTimeOffset;
2152
2153         Py_INCREF( Py_None );
2154         return ( Py_None );
2155 }
2156
2157 static PyObject *Object_makeTrack( BPy_Object * self, PyObject * args )
2158 {
2159         BPy_Object *tracked = NULL;
2160         Object *ob = self->object;
2161         int fast = 0;
2162
2163         if( !PyArg_ParseTuple( args, "O!|i", &Object_Type, &tracked, &fast ) )
2164                 return EXPP_ReturnPyObjError( PyExc_TypeError,
2165                                               "expected an object and optionally also an int as arguments." );
2166
2167         ob->track = tracked->object;
2168
2169         if( !fast )
2170                 DAG_scene_sort( G.scene );
2171
2172         return EXPP_incr_ret( Py_None );
2173 }
2174
2175 static PyObject *Object_shareFrom( BPy_Object * self, PyObject * args )
2176 {
2177         BPy_Object *object;
2178         ID *id;
2179         ID *oldid;
2180
2181         if( !PyArg_ParseTuple( args, "O", &object ) ) {
2182                 return EXPP_ReturnPyObjError( PyExc_TypeError,
2183                                               "expected an object argument" );
2184         }
2185         if( !Object_CheckPyObject( ( PyObject * ) object ) ) {
2186                 return EXPP_ReturnPyObjError( PyExc_TypeError,
2187                                               "first argument is not of type 'Object'" );
2188         }
2189
2190         if( self->object->type != object->object->type ) {
2191                 return EXPP_ReturnPyObjError( PyExc_TypeError,
2192                                               "objects are not of same data type" );
2193         }
2194         switch ( self->object->type ) {
2195         case OB_MESH:
2196         case OB_LAMP:
2197         case OB_CAMERA: /* we can probably add the other types, too */
2198         case OB_ARMATURE:
2199         case OB_CURVE:
2200         case OB_SURF:
2201         case OB_LATTICE:
2202                 oldid = ( ID * ) self->object->data;
2203                 id = ( ID * ) object->object->data;
2204                 self->object->data = object->object->data;
2205
2206                 if( self->object->type == OB_MESH && id ) {
2207                         self->object->totcol = 0;
2208                         EXPP_synchronizeMaterialLists( self->object );
2209                 }
2210
2211                 id_us_plus( id );
2212                 if( oldid ) {
2213                         if( oldid->us > 0 ) {
2214                                 oldid->us--;
2215                         } else {
2216                                 return ( EXPP_ReturnPyObjError
2217                                          ( PyExc_RuntimeError,
2218                                            "old object reference count below 0" ) );
2219                         }
2220                 }
2221                 Py_INCREF( Py_None );
2222                 return ( Py_None );
2223         default:
2224                 return EXPP_ReturnPyObjError( PyExc_TypeError,
2225                                               "type not supported" );
2226         }
2227
2228         Py_INCREF( Py_None );
2229         return ( Py_None );
2230 }
2231
2232
2233
2234 static PyObject *Object_Select( BPy_Object * self, PyObject * args )
2235 {
2236         Base *base;
2237         int sel;
2238
2239         base = FIRSTBASE;
2240         if( !PyArg_ParseTuple( args, "i", &sel ) )
2241                 return EXPP_ReturnPyObjError
2242                         ( PyExc_TypeError, "expected an integer, 0 or 1" );
2243
2244         while( base ) {
2245                 if( base->object == self->object ) {
2246                         if( sel == 1 ) {
2247                                 base->flag |= SELECT;
2248                                 self->object->flag = base->flag;
2249                                 set_active_base( base );
2250                         } else {
2251                                 base->flag &= ~SELECT;
2252                                 self->object->flag = base->flag;
2253                         }
2254                         break;
2255                 }
2256                 base = base->next;
2257         }
2258
2259         countall(  );
2260
2261         Py_INCREF( Py_None );
2262         return ( Py_None );
2263 }
2264
2265 static PyObject *Object_getAllProperties( BPy_Object * self )
2266 {
2267         PyObject *prop_list;
2268         bProperty *prop = NULL;
2269
2270         prop_list = PyList_New( 0 );
2271
2272         prop = self->object->prop.first;
2273         while( prop ) {
2274                 PyList_Append( prop_list, Property_CreatePyObject( prop ) );
2275                 prop = prop->next;
2276         }
2277         return prop_list;
2278 }
2279
2280 static PyObject *Object_getProperty( BPy_Object * self, PyObject * args )
2281 {
2282         char *prop_name = NULL;
2283         bProperty *prop = NULL;
2284         PyObject *py_prop = Py_None;
2285
2286         if( !PyArg_ParseTuple( args, "s", &prop_name ) ) {
2287                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
2288                                                 "expected a string" ) );
2289         }
2290
2291         prop = get_property( self->object, prop_name );
2292         if( prop ) {
2293                 py_prop = Property_CreatePyObject( prop );
2294         } else {
2295                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
2296                                                 "couldn't find the property...." ) );
2297         }
2298         return py_prop;
2299 }
2300
2301 static PyObject *Object_addProperty( BPy_Object * self, PyObject * args )
2302 {
2303         bProperty *prop = NULL;
2304         char *prop_name = NULL;
2305         PyObject *prop_data = Py_None;
2306         char *prop_type = NULL;
2307         short type = -1;
2308         BPy_Property *py_prop = NULL;
2309         int argslen = PyObject_Length( args );
2310
2311         if( argslen == 3 || argslen == 2 ) {
2312                 if( !PyArg_ParseTuple
2313                     ( args, "sO|s", &prop_name, &prop_data, &prop_type ) ) {
2314                         return ( EXPP_ReturnPyObjError
2315                                  ( PyExc_AttributeError,
2316                                    "unable to get string, data, and optional string" ) );
2317                 }
2318         } else if( argslen == 1 ) {
2319                 if( !PyArg_ParseTuple( args, "O!", &property_Type, &py_prop ) ) {
2320                         return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
2321                                                         "unable to get Property" ) );
2322                 }
2323                 if( py_prop->property != NULL ) {
2324                         return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
2325                                                         "Property is already added to an object" ) );
2326                 }
2327         } else {
2328                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
2329                                                 "expected 1,2 or 3 arguments" ) );
2330         }
2331
2332         //parse property type
2333         if( !py_prop ) {
2334                 if( prop_type ) {
2335                         if( BLI_streq( prop_type, "BOOL" ) )
2336                                 type = PROP_BOOL;
2337                         else if( BLI_streq( prop_type, "INT" ) )
2338                                 type = PROP_INT;
2339                         else if( BLI_streq( prop_type, "FLOAT" ) )
2340                                 type = PROP_FLOAT;
2341                         else if( BLI_streq( prop_type, "TIME" ) )
2342                                 type = PROP_TIME;
2343                         else if( BLI_streq( prop_type, "STRING" ) )
2344                                 type = PROP_STRING;
2345                         else
2346                                 return ( EXPP_ReturnPyObjError
2347                                          ( PyExc_RuntimeError,
2348                                            "BOOL, INT, FLOAT, TIME or STRING expected" ) );
2349                 } else {
2350                         //use the default
2351                         if( PyInt_Check( prop_data ) )
2352                                 type = PROP_INT;
2353                         else if( PyFloat_Check( prop_data ) )
2354                                 type = PROP_FLOAT;
2355                         else if( PyString_Check( prop_data ) )
2356                                 type = PROP_STRING;
2357                 }
2358         } else {
2359                 type = py_prop->type;
2360         }
2361
2362         //initialize a new bProperty of the specified type
2363         prop = new_property( type );
2364
2365         //parse data
2366         if( !py_prop ) {
2367                 BLI_strncpy( prop->name, prop_name, 32 );
2368                 if( PyInt_Check( prop_data ) ) {
2369                         *( ( int * ) &prop->data ) =
2370                                 ( int ) PyInt_AsLong( prop_data );
2371                 } else if( PyFloat_Check( prop_data ) ) {
2372                         *( ( float * ) &prop->data ) =
2373                                 ( float ) PyFloat_AsDouble( prop_data );
2374                 } else if( PyString_Check( prop_data ) ) {
2375                         BLI_strncpy( prop->poin,
2376                                      PyString_AsString( prop_data ),
2377                                      MAX_PROPSTRING );
2378                 }
2379         } else {
2380                 py_prop->property = prop;
2381                 if( !updateProperyData( py_prop ) ) {
2382                         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
2383                                                         "Could not update property data - error" ) );
2384                 }
2385         }
2386
2387         //add to property listbase for the object
2388         BLI_addtail( &self->object->prop, prop );
2389
2390         return EXPP_incr_ret( Py_None );
2391 }
2392
2393 static PyObject *Object_removeProperty( BPy_Object * self, PyObject * args )
2394 {
2395         char *prop_name = NULL;
2396         BPy_Property *py_prop = NULL;
2397         bProperty *prop = NULL;
2398
2399         // we have property and no optional arg
2400         if( !PyArg_ParseTuple( args, "O!", &property_Type, &py_prop ) ) {
2401                 if( !PyArg_ParseTuple( args, "s", &prop_name ) ) {
2402                         return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
2403                                                         "expected a Property or a string" ) );
2404                 }
2405         }
2406         //remove the link, free the data, and update the py struct
2407         if( py_prop ) {
2408                 BLI_remlink( &self->object->prop, py_prop->property );
2409                 if( updatePyProperty( py_prop ) ) {
2410                         free_property( py_prop->property );
2411                         py_prop->property = NULL;
2412                 }
2413         } else {
2414                 prop = get_property( self->object, prop_name );
2415                 if( prop ) {
2416                         BLI_remlink( &self->object->prop, prop );
2417                         free_property( prop );
2418                 }
2419         }
2420         return EXPP_incr_ret( Py_None );
2421 }
2422
2423 static PyObject *Object_removeAllProperties( BPy_Object * self )
2424 {
2425         free_properties( &self->object->prop );
2426         return EXPP_incr_ret( Py_None );
2427 }
2428
2429 static PyObject *Object_copyAllPropertiesTo( BPy_Object * self,
2430                                              PyObject * args )
2431 {
2432         PyObject *dest = Py_None;
2433         bProperty *prop = NULL;
2434         bProperty *propn = NULL;
2435
2436         if( !PyArg_ParseTuple( args, "O!", &Object_Type, &dest ) ) {
2437                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
2438                                                 "expected an Object" ) );
2439         }
2440         //make a copy of all it's properties
2441         prop = self->object->prop.first;
2442         while( prop ) {
2443                 propn = copy_property( prop );
2444                 BLI_addtail( &( ( BPy_Object * ) dest )->object->prop, propn );
2445                 prop = prop->next;
2446         }
2447
2448         return EXPP_incr_ret( Py_None );
2449 }
2450
2451 /* obj.addScriptLink */
2452 static PyObject *Object_addScriptLink( BPy_Object * self, PyObject * args )
2453 {
2454         Object *obj = self->object;
2455         ScriptLink *slink = NULL;
2456
2457         slink = &( obj )->scriptlink;
2458
2459         return EXPP_addScriptLink( slink, args, 0 );
2460 }
2461
2462 /* obj.clearScriptLinks */
2463 static PyObject *Object_clearScriptLinks( BPy_Object * self, PyObject * args )
2464 {
2465         Object *obj = self->object;
2466         ScriptLink *slink = NULL;
2467
2468         slink = &( obj )->scriptlink;
2469
2470         return EXPP_clearScriptLinks( slink, args );
2471 }
2472
2473 /* obj.getScriptLinks */
2474 static PyObject *Object_getScriptLinks( BPy_Object * self, PyObject * args )
2475 {
2476         Object *obj = self->object;
2477         ScriptLink *slink = NULL;
2478         PyObject *ret = NULL;
2479
2480         slink = &( obj )->scriptlink;
2481
2482         ret = EXPP_getScriptLinks( slink, args, 0 );
2483
2484         if( ret )
2485                 return ret;
2486         else
2487                 return NULL;
2488 }
2489
2490 static PyObject *Object_getDupliVerts ( BPy_Object * self ) {
2491         if (self->object->transflag & OB_DUPLIVERTS)
2492                 return EXPP_incr_ret_True ();
2493         else
2494                 return EXPP_incr_ret_False();
2495 }
2496
2497 static PyObject *Object_setDupliVerts ( BPy_Object * self, PyObject * args ) {
2498         int setting= 0;
2499         if( !PyArg_ParseTuple( args, "i", &setting ) ) {
2500                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
2501                                                 "expected a string") );
2502         }
2503         if (self && self->object) {
2504                 if (setting)
2505                         self->object->transflag |= OB_DUPLIVERTS;
2506                 else 
2507                         self->object->transflag &= ~OB_DUPLIVERTS;
2508         }
2509         return Py_None;
2510 }
2511
2512 /*****************************************************************************/
2513 /* Function:    Object_CreatePyObject                                    */
2514 /* Description: This function will create a new BlenObject from an existing  */
2515 /*              Object structure.                                        */
2516 /*****************************************************************************/
2517 PyObject *Object_CreatePyObject( struct Object * obj )
2518 {
2519         BPy_Object *blen_object;
2520
2521         if( !obj )
2522                 return EXPP_incr_ret( Py_None );
2523
2524         blen_object =
2525                 ( BPy_Object * ) PyObject_NEW( BPy_Object, &Object_Type );
2526
2527         if( blen_object == NULL ) {
2528                 return ( NULL );
2529         }
2530         blen_object->object = obj;
2531         return ( ( PyObject * ) blen_object );
2532 }
2533
2534 /*****************************************************************************/
2535 /* Function:    Object_CheckPyObject                                     */
2536 /* Description: This function returns true when the given PyObject is of the */
2537 /*              type Object. Otherwise it will return false.             */
2538 /*****************************************************************************/
2539 int Object_CheckPyObject( PyObject * py_obj )
2540 {
2541         return ( py_obj->ob_type == &Object_Type );
2542 }
2543
2544 /*****************************************************************************/
2545 /* Function:    Object_FromPyObject                                      */
2546 /* Description: This function returns the Blender object from the given  */
2547 /*              PyObject.                                                */
2548 /*****************************************************************************/
2549 struct Object *Object_FromPyObject( PyObject * py_obj )
2550 {
2551         BPy_Object *blen_obj;
2552
2553         blen_obj = ( BPy_Object * ) py_obj;
2554         return ( blen_obj->object );
2555 }
2556
2557 /*****************************************************************************/
2558 /* Description: Returns the object with the name specified by the argument  */
2559 /*              name. Note that the calling function has to remove the first */
2560 /*              two characters of the object name. These two characters    */
2561 /*              specify the type of the object (OB, ME, WO, ...)         */
2562 /*              The function will return NULL when no object with the given  */
2563 /*              name is found.                                           */
2564 /*****************************************************************************/
2565 Object *GetObjectByName( char *name )
2566 {
2567         Object *obj_iter;
2568
2569         obj_iter = G.main->object.first;
2570         while( obj_iter ) {
2571                 if( StringEqual( name, GetIdName( &( obj_iter->id ) ) ) ) {
2572                         return ( obj_iter );
2573                 }
2574                 obj_iter = obj_iter->id.next;
2575         }
2576
2577         /* There is no object with the given name */
2578         return ( NULL );
2579 }
2580
2581 /*****************************************************************************/
2582 /* Function:    Object_dealloc                                           */
2583 /* Description: This is a callback function for the BlenObject type. It is  */
2584 /*              the destructor function.                                 */
2585 /*****************************************************************************/
2586 static void Object_dealloc( BPy_Object * obj )
2587 {
2588         PyObject_DEL( obj );
2589 }
2590
2591 /*****************************************************************************/
2592 /* Function:    Object_getAttr                                           */
2593 /* Description: This is a callback function for the BlenObject type. It is  */
2594 /*              the function that retrieves any value from Blender and   */
2595 /*              passes it to Python.                                     */
2596 /*****************************************************************************/
2597 static PyObject *Object_getAttr( BPy_Object * obj, char *name )
2598 {
2599         struct Object *object;
2600
2601         object = obj->object;
2602         if( StringEqual( name, "LocX" ) )
2603                 return ( PyFloat_FromDouble( object->loc[0] ) );
2604         if( StringEqual( name, "LocY" ) )
2605                 return ( PyFloat_FromDouble( object->loc[1] ) );
2606         if( StringEqual( name, "LocZ" ) )
2607                 return ( PyFloat_FromDouble( object->loc[2] ) );
2608         if( StringEqual( name, "loc" ) )
2609                 return ( Py_BuildValue( "fff", object->loc[0], object->loc[1],
2610                                         object->loc[2] ) );
2611         if( StringEqual( name, "dLocX" ) )
2612                 return ( PyFloat_FromDouble( object->dloc[0] ) );
2613         if( StringEqual( name, "dLocY" ) )
2614                 return ( PyFloat_FromDouble( object->dloc[1] ) );
2615         if( StringEqual( name, "dLocZ" ) )
2616                 return ( PyFloat_FromDouble( object->dloc[2] ) );
2617         if( StringEqual( name, "dloc" ) )
2618                 return ( Py_BuildValue
2619                          ( "fff", object->dloc[0], object->dloc[1],
2620                            object->dloc[2] ) );
2621         if( StringEqual( name, "RotX" ) )
2622                 return ( PyFloat_FromDouble( object->rot[0] ) );
2623         if( StringEqual( name, "RotY" ) )
2624                 return ( PyFloat_FromDouble( object->rot[1] ) );
2625         if( StringEqual( name, "RotZ" ) )
2626                 return ( PyFloat_FromDouble( object->rot[2] ) );
2627         if( StringEqual( name, "rot" ) )
2628                 return ( Py_BuildValue( "fff", object->rot[0], object->rot[1],
2629                                         object->rot[2] ) );
2630         if( StringEqual( name, "dRotX" ) )
2631                 return ( PyFloat_FromDouble( object->drot[0] ) );
2632         if( StringEqual( name, "dRotY" ) )
2633                 return ( PyFloat_FromDouble( object->drot[1] ) );
2634         if( StringEqual( name, "dRotZ" ) )
2635                 return ( PyFloat_FromDouble( object->drot[2] ) );
2636         if( StringEqual( name, "drot" ) )
2637                 return ( Py_BuildValue
2638                          ( "fff", object->drot[0], object->drot[1],
2639                            object->drot[2] ) );
2640         if( StringEqual( name, "SizeX" ) )
2641                 return ( PyFloat_FromDouble( object->size[0] ) );
2642         if( StringEqual( name, "SizeY" ) )
2643                 return ( PyFloat_FromDouble( object->size[1] ) );
2644         if( StringEqual( name, "SizeZ" ) )
2645                 return ( PyFloat_FromDouble( object->size[2] ) );
2646         if( StringEqual( name, "size" ) )
2647                 return ( Py_BuildValue
2648                          ( "fff", object->size[0], object->size[1],
2649                            object->size[2] ) );
2650         if( StringEqual( name, "dSizeX" ) )
2651                 return ( PyFloat_FromDouble( object->dsize[0] ) );
2652         if( StringEqual( name, "dSizeY" ) )
2653                 return ( PyFloat_FromDouble( object->dsize[1] ) );
2654         if( StringEqual( name, "dSizeZ" ) )
2655                 return ( PyFloat_FromDouble( object->dsize[2] ) );
2656         if( StringEqual( name, "dsize" ) )
2657                 return ( Py_BuildValue
2658                          ( "fff", object->dsize[0], object->dsize[1],
2659                            object->dsize[2] ) );
2660
2661         /* accept both Layer (old, for compatibility) and Layers */
2662         if( strncmp( name, "Layer", 5 ) == 0)
2663                 return ( PyInt_FromLong( object->lay ) );
2664         /* Layers returns a bitmask, layers returns a list of integers */
2665         if( StringEqual( name, "layers" ) ) {
2666                 int layers, bit = 0, val = 0;
2667                 PyObject *item = NULL, *laylist = PyList_New( 0 );
2668
2669                 if( !laylist )
2670                         return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
2671                                 "couldn't create pylist!" ) );
2672
2673                 layers = object->lay;
2674
2675                 while( bit < 20 ) {
2676                         val = 1 << bit;
2677                         if( layers & val ) {
2678                                 item = Py_BuildValue( "i", bit + 1 );
2679                                 PyList_Append( laylist, item );
2680                                 Py_DECREF( item );
2681                         }
2682                         bit++;
2683                 }
2684                 return laylist;
2685         }
2686         if( StringEqual( name, "parent" ) ) {
2687                 if( object->parent )
2688                         return ( Object_CreatePyObject( object->parent ) );
2689                 else {
2690                         Py_INCREF( Py_None );
2691                         return ( Py_None );
2692                 }
2693         }
2694
2695         if( StringEqual( name, "track" ) )
2696                 return ( Object_CreatePyObject( object->track ) );
2697         if( StringEqual( name, "data" ) ) {
2698                 PyObject *getdata, *tuple = PyTuple_New(0);
2699
2700                 if (!tuple)
2701                         return EXPP_ReturnPyObjError (PyExc_MemoryError,
2702                                 "couldn't create an empty tuple!");
2703
2704                 getdata = Object_getData( obj, tuple, NULL );
2705
2706                 Py_DECREF(tuple);
2707                 return getdata;
2708         }
2709         if( StringEqual( name, "ipo" ) ) {
2710                 if( object->ipo == NULL ) {
2711                         /* There's no ipo linked to the object, return Py_None. */
2712                         Py_INCREF( Py_None );
2713                         return ( Py_None );
2714                 }
2715                 return ( Ipo_CreatePyObject( object->ipo ) );
2716         }
2717         if( StringEqual( name, "mat" ) || StringEqual( name, "matrix" ) )
2718                 return ( Object_getMatrix
2719                          ( obj, Py_BuildValue( "(s)", "worldspace" ) ) );
2720         if( StringEqual( name, "matrixWorld" ) )
2721                 return ( Object_getMatrix
2722                          ( obj, Py_BuildValue( "(s)", "worldspace" ) ) );
2723         if( StringEqual( name, "matrixLocal" ) )
2724                 return ( Object_getMatrix
2725                          ( obj, Py_BuildValue( "(s)", "localspace" ) ) );
2726         if( StringEqual( name, "colbits" ) )
2727                 return ( Py_BuildValue( "h", object->colbits ) );
2728         if( StringEqual( name, "drawType" ) )
2729                 return ( Py_BuildValue( "b", object->dt ) );
2730         if( StringEqual( name, "drawMode" ) )
2731                 return ( Py_BuildValue( "b", object->dtx ) );
2732         if( StringEqual( name, "name" ) )
2733                 return ( Py_BuildValue( "s", object->id.name + 2 ) );
2734         if( StringEqual( name, "sel" ) )
2735                 return ( Object_isSelected( obj ) );
2736         if( StringEqual( name, "DupSta" ) )
2737                 return PyInt_FromLong( obj->object->dupsta );
2738         if( StringEqual( name, "DupEnd" ) )
2739                 return PyInt_FromLong( obj->object->dupend );
2740         if( StringEqual( name, "DupOn" ) )
2741                 return PyInt_FromLong( obj->object->dupon );
2742         if( StringEqual( name, "DupOff" ) )
2743                 return PyInt_FromLong( obj->object->dupoff );
2744         if( StringEqual( name, "Dupliframes" ) ){
2745                 if (obj->object->transflag & OB_DUPLIFRAMES)
2746                         return EXPP_incr_ret_True();
2747                 else
2748                         return EXPP_incr_ret_False();
2749         }
2750         if (StringEqual (name, "oopsLoc")) {
2751                 if (G.soops) {
2752       Oops *oops= G.soops->oops.first;
2753       while(oops) {
2754         if(oops->type==ID_OB) {
2755           if ((Object *)oops->id == object) {
2756             return (Py_BuildValue ("ff", oops->x, oops->y));
2757           }
2758         }
2759         oops= oops->next;
2760       }
2761     }
2762                 return EXPP_incr_ret( Py_None );
2763         }
2764
2765         /* not an attribute, search the methods table */
2766         return Py_FindMethod( BPy_Object_methods, ( PyObject * ) obj, name );
2767 }
2768
2769 /*****************************************************************************/
2770 /* Function:    Object_setAttr                                           */
2771 /* Description: This is a callback function for the BlenObject type. It is  */
2772 /*              the function that retrieves any value from Python and sets  */
2773 /*              it accordingly in Blender.                               */
2774 /*****************************************************************************/
2775 static int Object_setAttr( BPy_Object * obj, char *name, PyObject * value )
2776 {
2777         PyObject *valtuple, *result=NULL;
2778         struct Object *object;
2779
2780         object = obj->object;
2781
2782         /* Handle all properties which are Read Only */
2783         if( StringEqual( name, "parent" ) )
2784                 return EXPP_ReturnIntError( PyExc_AttributeError,
2785                                        "Setting the parent is not allowed." );
2786         if( StringEqual( name, "data" ) )
2787                 return EXPP_ReturnIntError( PyExc_AttributeError,
2788                                        "Setting the data is not allowed." );
2789         if( StringEqual( name, "ipo" ) )
2790                 return EXPP_ReturnIntError( PyExc_AttributeError,
2791                                        "Setting the ipo is not allowed." );
2792         if( StringEqual( name, "mat" ) )
2793                 return EXPP_ReturnIntError( PyExc_AttributeError,
2794                                        "Not allowed. Please use .setMatrix(matrix)" );
2795         if( StringEqual( name, "matrix" ) )
2796                 return EXPP_ReturnIntError( PyExc_AttributeError,
2797                                        "Not allowed. Please use .setMatrix(matrix)" );
2798
2799         /* FIRST, do attributes that are diretly changed */
2800         if( StringEqual( name, "LocX" ) )
2801                 return ( !PyArg_Parse( value, "f", &( object->loc[0] ) ) );
2802         if( StringEqual( name, "LocY" ) )
2803                 return ( !PyArg_Parse( value, "f", &( object->loc[1] ) ) );
2804         if( StringEqual( name, "LocZ" ) )
2805                 return ( !PyArg_Parse( value, "f", &( object->loc[2] ) ) );
2806         if( StringEqual( name, "dLocX" ) )
2807                 return ( !PyArg_Parse( value, "f", &( object->dloc[0] ) ) );
2808         if( StringEqual( name, "dLocY" ) )
2809                 return ( !PyArg_Parse( value, "f", &( object->dloc[1] ) ) );
2810         if( StringEqual( name, "dLocZ" ) )
2811                 return ( !PyArg_Parse( value, "f", &( object->dloc[2] ) ) );
2812         if( StringEqual( name, "RotX" ) )
2813                 return ( !PyArg_Parse( value, "f", &( object->rot[0] ) ) );
2814         if( StringEqual( name, "RotY" ) )
2815                 return ( !PyArg_Parse( value, "f", &( object->rot[1] ) ) );
2816         if( StringEqual( name, "RotZ" ) )
2817                 return ( !PyArg_Parse( value, "f", &( object->rot[2] ) ) );
2818         if( StringEqual( name, "dRotX" ) )
2819                 return ( !PyArg_Parse( value, "f", &( object->drot[0] ) ) );
2820         if( StringEqual( name, "dRotY" ) )
2821                 return ( !PyArg_Parse( value, "f", &( object->drot[1] ) ) );
2822         if( StringEqual( name, "dRotZ" ) )
2823                 return ( !PyArg_Parse( value, "f", &( object->drot[2] ) ) );
2824         if( StringEqual( name, "drot" ) )
2825                 return ( !PyArg_ParseTuple( value, "fff", &( object->drot[0] ),
2826                                             &( object->drot[1] ),
2827                                             &( object->drot[2] ) ) );
2828         if( StringEqual( name, "SizeX" ) )
2829                 return ( !PyArg_Parse( value, "f", &( object->size[0] ) ) );
2830         if( StringEqual( name, "SizeY" ) )
2831                 return ( !PyArg_Parse( value, "f", &( object->size[1] ) ) );
2832         if( StringEqual( name, "SizeZ" ) )
2833                 return ( !PyArg_Parse( value, "f", &( object->size[2] ) ) );
2834         if( StringEqual( name, "size" ) )
2835                 return ( !PyArg_ParseTuple( value, "fff", &( object->size[0] ),
2836                                             &( object->size[1] ),
2837                                             &( object->size[2] ) ) );
2838         if( StringEqual( name, "dSizeX" ) )
2839                 return ( !PyArg_Parse( value, "f", &( object->dsize[0] ) ) );
2840         if( StringEqual( name, "dSizeY" ) )
2841                 return ( !PyArg_Parse( value, "f", &( object->dsize[1] ) ) );
2842         if( StringEqual( name, "dSizeZ" ) )
2843                 return ( !PyArg_Parse( value, "f", &( object->dsize[2] ) ) );
2844         if( StringEqual( name, "dsize" ) )
2845                 return ( !PyArg_ParseTuple
2846                          ( value, "fff", &( object->dsize[0] ),
2847                            &( object->dsize[1] ), &( object->dsize[2] ) ) );
2848         
2849         if( StringEqual( name, "DupSta" ) )
2850                 return ( !PyArg_Parse( value, "h", &( object->dupsta ) ) );
2851
2852         if( StringEqual( name, "DupEnd" ) )
2853                 return ( !PyArg_Parse( value, "h", &( object->dupend ) ) );
2854
2855         if( StringEqual( name, "DupOn" ) )
2856                 return ( !PyArg_Parse( value, "h", &( object->dupon ) ) );
2857
2858         if( StringEqual( name, "DupOff" ) )
2859                 return ( !PyArg_Parse( value, "h", &( object->dupoff ) ) );
2860
2861         if( StringEqual( name, "Dupliframes" ) ) {
2862                 short dupli;
2863                 if ( !PyArg_Parse( value, "h", &dupli ) )
2864                         return -1;
2865
2866                 if (dupli)
2867                         obj->object->transflag |= OB_DUPLIFRAMES;
2868                 else
2869                         obj->object->transflag &= ~OB_DUPLIFRAMES;
2870
2871                 return 0;
2872         }
2873         if( StringEqual( name, "colbits" ) )
2874                 return ( !PyArg_Parse( value, "h", &( object->colbits ) ) );
2875
2876         /* accept both Layer (for compatibility) and Layers */
2877         if( strncmp( name, "Layer", 5 ) == 0 ) {
2878                 /*  usage note: caller of this func needs to do a 
2879                    Blender.Redraw(-1) to update and redraw the interface */
2880
2881                 Base *base;
2882                 int newLayer;
2883                 int local;
2884
2885                 if( ! PyArg_Parse( value, "i", &newLayer ) ) {
2886                         return EXPP_ReturnIntError( PyExc_AttributeError,
2887                                                     "expected int as bitmask" );
2888                 }
2889
2890                 /* uppper 2 nibbles are for local view */
2891                 newLayer &= 0x00FFFFFF;
2892                 if( newLayer == 0 ) {
2893                         return EXPP_ReturnIntError( PyExc_AttributeError,
2894                                 "bitmask must have from 1 up to 20 bits set");
2895                 }
2896
2897                 /* update any bases pointing to our object */
2898                 base = FIRSTBASE;  /* first base in current scene */
2899                 while( base ){
2900                         if( base->object == obj->object ) {
2901                                 local = base->lay &= 0xFF000000;
2902                                 base->lay = local | newLayer;
2903                                 object->lay = base->lay;
2904                         }
2905                         base = base->next;
2906                 }
2907                 countall(  );
2908                 
2909                 return ( 0 );
2910         }
2911         if( StringEqual( name, "layers" ) ) {
2912                 /*  usage note: caller of this func needs to do a 
2913                    Blender.Redraw(-1) to update and redraw the interface */
2914
2915                 Base *base;
2916                 int layers = 0, len_list = 0;
2917                 int local, i, val;
2918                 PyObject *list = NULL, *item = NULL;
2919
2920                 if( !PyArg_Parse( value, "O!", &PyList_Type, &list ) )
2921                         return EXPP_ReturnIntError( PyExc_TypeError,
2922                           "expected a list of integers" );
2923
2924                 len_list = PyList_Size(list);
2925
2926                 if (len_list == 0)
2927                         return EXPP_ReturnIntError( PyExc_AttributeError,
2928                           "list can't be empty, at least one layer must be set" );
2929
2930                 for( i = 0; i < len_list; i++ ) {
2931                         item = PyList_GetItem( list, i );
2932                         if( !PyInt_Check( item ) )
2933                                 return EXPP_ReturnIntError
2934                                         ( PyExc_AttributeError,
2935                                           "list must contain only integer numbers" );
2936
2937                         val = ( int ) PyInt_AsLong( item );
2938                         if( val < 1 || val > 20 )
2939                                 return EXPP_ReturnIntError
2940                                         ( PyExc_AttributeError,
2941                                           "layer values must be in the range [1, 20]" );
2942
2943                         layers |= 1 << ( val - 1 );
2944                 }
2945
2946                 /* update any bases pointing to our object */
2947                 base = FIRSTBASE;  /* first base in current scene */
2948                 while( base ){
2949                         if( base->object == obj->object ) {
2950                                 local = base->lay &= 0xFF000000;
2951                                 base->lay = local | layers;
2952                                 object->lay = base->lay;
2953                         }
2954                         base = base->next;
2955                 }
2956                 countall();
2957
2958                 return ( 0 );
2959         }
2960         if (StringEqual (name, "oopsLoc")) {
2961                 if (G.soops) {
2962                         Oops *oops= G.soops->oops.first;
2963                         while(oops) {
2964                                 if(oops->type==ID_OB) {
2965                                         if ((Object *)oops->id == object) {
2966                                                 return (!PyArg_ParseTuple  (value, "ff", &(oops->x),&(oops->y)));
2967                                         }
2968                                 }
2969                                 oops= oops->next;
2970                         }
2971                 }
2972                 return 0;
2973         }
2974         /*
2975         IKA isn't even in Blender anymore, I think we can remove this... (theeth)
2976         if( strncmp( name, "Eff", 3 ) == 0 ) {
2977                 if( ( object->type == OB_IKA ) && ( object->data != NULL ) ) {
2978                         ika = object->data;
2979                         switch ( name[3] ) {
2980                         case 'X':
2981                                 return ( !PyArg_Parse
2982                                          ( value, "f", &( ika->effg[0] ) ) );
2983                         case 'Y':
2984                                 return ( !PyArg_Parse
2985                                          ( value, "f", &( ika->effg[1] ) ) );
2986                         case 'Z':
2987                                 return ( !PyArg_Parse
2988                                          ( value, "f", &( ika->effg[2] ) ) );
2989                         default:
2990                                 // Do we need to display a sensible error message here?
2991                                 return ( 0 );
2992                         }
2993                 }
2994                 return ( 0 );
2995         }
2996         */
2997
2998         /* SECOND, handle all the attributes that passes the value as a tuple to another function */
2999
3000         /* Put the value(s) in a tuple. For some variables, we want to */
3001         /* pass the values to a function, and these functions only accept */
3002         /* PyTuples. */
3003         valtuple = Py_BuildValue( "(O)", value );
3004         if( !valtuple ) {
3005                 return EXPP_ReturnIntError( PyExc_MemoryError,
3006                                             "Object_setAttr: couldn't create PyTuple" );
3007         }
3008         /* Call the setFunctions to handle it */
3009         if( StringEqual( name, "loc" ) )
3010                 result = Object_setLocation( obj, valtuple );
3011         else if( StringEqual( name, "dloc" ) )
3012                 result = Object_setDeltaLocation( obj, valtuple );
3013         else if( StringEqual( name, "rot" ) )
3014                 result = Object_setEuler( obj, valtuple );
3015         else if( StringEqual( name, "track" ) )
3016                 result = Object_makeTrack( obj, valtuple );
3017         else if( StringEqual( name, "drawType" ) )
3018                 result = Object_setDrawType( obj, valtuple );
3019         else if( StringEqual( name, "drawMode" ) )
3020                 result = Object_setDrawMode( obj, valtuple );
3021         else if( StringEqual( name, "name" ) )
3022                 result = Object_setName( obj, valtuple );
3023         else if( StringEqual( name, "sel" ) )
3024                 result = Object_Select( obj, valtuple );
3025         else { /* if it turns out here, it's not an attribute*/
3026                 Py_DECREF(valtuple);
3027                 return EXPP_ReturnIntError( PyExc_KeyError, "attribute not found" );
3028         }
3029
3030 /* valtuple won't be returned to the caller, so we need to DECREF it */
3031         Py_DECREF(valtuple);
3032
3033         if( result != Py_None )
3034                 return -1;      /* error return */
3035
3036 /* Py_None was incref'ed by the called Scene_set* function. We probably
3037  * don't need to decref Py_None (!), but since Python/C API manual tells us
3038  * to treat it like any other PyObject regarding ref counting ... */
3039         Py_DECREF( Py_None );
3040         return 0;               /* normal return */
3041 }
3042
3043 /*****************************************************************************/
3044 /* Function:    Object_compare                                           */
3045 /* Description: This is a callback function for the BPy_Object type. It  */
3046 /*              compares two Object_Type objects. Only the "==" and "!="  */
3047 /*              comparisons are meaninful. Returns 0 for equality and -1 if  */
3048 /*              they don't point to the same Blender Object struct.      */
3049 /*              In Python it becomes 1 if they are equal, 0 otherwise.   */
3050 /*****************************************************************************/
3051 static int Object_compare( BPy_Object * a, BPy_Object * b )
3052 {
3053         Object *pa = a->object, *pb = b->object;
3054         return ( pa == pb ) ? 0 : -1;
3055 }
3056
3057 /*****************************************************************************/
3058 /* Function:    Object_repr                                              */
3059 /* Description: This is a callback function for the BPy_Object type. It  */
3060 /*              builds a meaninful string to represent object objects.   */
3061 /*****************************************************************************/
3062 static PyObject *Object_repr( BPy_Object * self )
3063 {
3064         return PyString_FromFormat( "[Object \"%s\"]",
3065                                     self->object->id.name + 2 );
3066 }
3067
3068
3069 PyObject *Object_getPIStrength( BPy_Object * self )
3070 {
3071     PyObject *attr;
3072
3073     if(!self->object->pd){
3074            if(!setupPI(self->object))
3075            return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
3076                                         "particle deflection could not be accessed (null pointer)" ) );    
3077     }
3078     
3079          attr = PyFloat_FromDouble( ( double ) self->object->pd->f_strength );
3080
3081         if( attr )
3082                 return attr;
3083
3084         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
3085                                         "couldn't get Object->pd->f_strength attribute" ) );    
3086 }
3087 PyObject *Object_setPIStrength( BPy_Object * self, PyObject * args )
3088 {
3089     float value;
3090
3091     if(!self->object->pd){
3092            if(!setupPI(self->object))
3093            return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
3094                                         "particle deflection could not be accessed (null pointer)" ) );    
3095     }
3096
3097         if( !PyArg_ParseTuple( args, "f", &value ) )
3098                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
3099                         "expected float argument" ) );
3100
3101         if(value > 1000.0f || value < -1000.0f)
3102                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
3103                         "acceptable values are between 1000.0 and -1000.0" ) );
3104         self->object->pd->f_strength = value;
3105
3106         return EXPP_incr_ret( Py_None );
3107 }
3108
3109 PyObject *Object_getPIFalloff( BPy_Object * self )
3110 {
3111         PyObject *attr;
3112     
3113     if(!self->object->pd){
3114            if(!setupPI(self->object))
3115            return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
3116                                         "particle deflection could not be accessed (null pointer)" ) );    
3117     }    
3118     
3119     attr = PyFloat_FromDouble( ( double ) self->object->pd->f_power );
3120
3121         if( attr )
3122                 return attr;
3123
3124         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
3125                                         "couldn't get Object->pd->f_power attribute" ) );
3126 }
3127 PyObject *Object_setPIFalloff( BPy_Object * self, PyObject * args )
3128 {
3129     float value;
3130
3131     if(!self->object->pd){
3132            if(!setupPI(self->object))
3133            return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
3134                                         "particle deflection could not be accessed (null pointer)" ) );    
3135     }
3136
3137         if( !PyArg_ParseTuple( args, "f", &value ) )
3138                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
3139                         "expected float argument" ) );
3140
3141         if(value > 10.0f || value < 0.0f)
3142                 return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
3143                         "acceptable values are between 10.0 and 0.0" ) );
3144         self->object->pd->f_power = value;
3145
3146         return EXPP_incr_ret( Py_None );
3147 }
3148
3149 PyObject *Object_getPIMaxDist( BPy_Object * self )
3150 {
3151         PyObject *attr;
3152
3153     if(!self->object->pd){
3154            if(!setupPI(self->object))
3155            return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
3156                                         "particle deflection could not be accessed (null pointer)" ) );    
3157     }    
3158     
3159     attr = PyFloat_FromDouble( ( double ) self->object->pd->maxdist );
3160
3161         if( attr )
3162                 return attr;
3163
3164         return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
3165                                         "couldn't get Object->pd->f_maxdist attribute" ) );
3166 }
3167 PyObject *Object_setPIMaxDist( BPy_Object * self, PyObject * args )
3168 {