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