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