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