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