/* * $Id$ * * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. The Blender * Foundation also sells licenses for use in proprietary software under * the Blender License. See http://www.blender.org/BL/ for information * about this. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * * * The Object module provides generic access to Objects of various types via * the Python interface. * * * Contributor(s): Michel Selten, Willian Germano, Jacques Guignot, * Joseph Gilbert, Stephen Swaney, Bala Gi, Campbell Barton, Johnny Matthews, * Ken Hughes, Alex Mole * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ struct SpaceIpo; struct rctf; #include "Object.h" /*This must come first */ #include "DNA_object_types.h" #include "DNA_view3d_types.h" #include "DNA_object_force.h" #include "DNA_userdef_types.h" #include "BKE_depsgraph.h" #include "BKE_effect.h" #include "BKE_font.h" #include "BKE_property.h" #include "BKE_mball.h" #include "BKE_softbody.h" #include "BKE_utildefines.h" #include "BKE_armature.h" #include "BKE_lattice.h" #include "BKE_mesh.h" #include "BKE_library.h" #include "BKE_object.h" #include "BKE_curve.h" #include "BKE_global.h" #include "BKE_main.h" #include "BIF_editview.h" #include "BSE_editipo.h" #include "BSE_edit.h" #include "BIF_space.h" #include "DNA_oops_types.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" #include "BDR_editobject.h" #include "MEM_guardedalloc.h" #include "mydevice.h" #include "blendef.h" #include "Scene.h" #include "Mathutils.h" #include "Mesh.h" #include "NMesh.h" #include "Curve.h" #include "Ipo.h" #include "Armature.h" #include "Camera.h" #include "Lamp.h" #include "Lattice.h" #include "Text.h" #include "Text3d.h" #include "Metaball.h" #include "Draw.h" #include "NLA.h" #include "logic.h" #include "gen_utils.h" /* Defines for insertIpoKey */ #define IPOKEY_LOC 0 #define IPOKEY_ROT 1 #define IPOKEY_SIZE 2 #define IPOKEY_LOCROT 3 #define IPOKEY_LOCROTSIZE 4 #define IPOKEY_PI_STRENGTH 5 #define IPOKEY_PI_FALLOFF 6 #define IPOKEY_PI_MAXDIST 7 /*Not Ready Yet*/ #define IPOKEY_PI_SURFACEDAMP 8 #define IPOKEY_PI_RANDOMDAMP 9 #define IPOKEY_PI_PERM 10 #define PFIELD_FORCE 1 #define PFIELD_VORTEX 2 #define PFIELD_MAGNET 3 #define PFIELD_WIND 4 /*****************************************************************************/ /* Python API function prototypes for the Blender module. */ /*****************************************************************************/ static PyObject *M_Object_New( PyObject * self, PyObject * args ); PyObject *M_Object_Get( PyObject * self, PyObject * args ); static PyObject *M_Object_GetSelected( PyObject * self, PyObject * args ); /* HELPER FUNCTION FOR PARENTING */ static PyObject *internal_makeParent(Object *parent, PyObject *py_child, int partype, int noninverse, int fast, int v1, int v2, int v3); /*****************************************************************************/ /* The following string definitions are used for documentation strings. */ /* In Python these will be written to the console when doing a */ /* Blender.Object.__doc__ */ /*****************************************************************************/ char M_Object_doc[] = "The Blender Object module\n\n\ This module provides access to **Object Data** in Blender.\n"; char M_Object_New_doc[] = "(type) - Add a new object of type 'type' in the current scene"; char M_Object_Get_doc[] = "(name) - return the object with the name 'name', returns None if not\ found.\n\ If 'name' is not specified, it returns a list of all objects in the\n\ current scene."; char M_Object_GetSelected_doc[] = "() - Returns a list of selected Objects in the active layer(s)\n\ The active object is the first in the list, if visible"; /*****************************************************************************/ /* Python method structure definition for Blender.Object module: */ /*****************************************************************************/ struct PyMethodDef M_Object_methods[] = { {"New", ( PyCFunction ) M_Object_New, METH_VARARGS, M_Object_New_doc}, {"Get", ( PyCFunction ) M_Object_Get, METH_VARARGS, M_Object_Get_doc}, {"GetSelected", ( PyCFunction ) M_Object_GetSelected, METH_VARARGS, M_Object_GetSelected_doc}, {NULL, NULL, 0, NULL} }; /*****************************************************************************/ /* Python BPy_Object methods declarations: */ /*****************************************************************************/ int setupSB(Object* ob); /*Make sure Softbody Pointer is initialized */ int setupPI(Object* ob); static PyObject *Object_buildParts( BPy_Object * self ); static PyObject *Object_clearIpo( BPy_Object * self ); static PyObject *Object_clrParent( BPy_Object * self, PyObject * args ); static PyObject *Object_clearTrack( BPy_Object * self, PyObject * args ); static PyObject *Object_getData(BPy_Object *self, PyObject *args, PyObject *kwd); static PyObject *Object_getDeltaLocation( BPy_Object * self ); static PyObject *Object_getDrawMode( BPy_Object * self ); static PyObject *Object_getDrawType( BPy_Object * self ); static PyObject *Object_getEuler( BPy_Object * self ); static PyObject *Object_getInverseMatrix( BPy_Object * self ); static PyObject *Object_getIpo( BPy_Object * self ); static PyObject *Object_getLocation( BPy_Object * self, PyObject * args ); static PyObject *Object_getMaterials( BPy_Object * self, PyObject * args ); static PyObject *Object_getMatrix( BPy_Object * self, PyObject * args ); static PyObject *Object_getName( BPy_Object * self ); static PyObject *Object_getParent( BPy_Object * self ); static PyObject *Object_getParentBoneName( BPy_Object * self ); static PyObject *Object_getSize( BPy_Object * self, PyObject * args ); static PyObject *Object_getTimeOffset( BPy_Object * self ); static PyObject *Object_getTracked( BPy_Object * self ); static PyObject *Object_getType( BPy_Object * self ); static PyObject *Object_getBoundBox( BPy_Object * self ); static PyObject *Object_getAction( BPy_Object * self ); static PyObject *Object_isSelected( BPy_Object * self ); static PyObject *Object_makeDisplayList( BPy_Object * self ); static PyObject *Object_link( BPy_Object * self, PyObject * args ); static PyObject *Object_makeParent( BPy_Object * self, PyObject * args ); static PyObject *Object_makeParentDeform( BPy_Object * self, PyObject * args ); static PyObject *Object_makeParentVertex( BPy_Object * self, PyObject * args ); static PyObject *Object_materialUsage( BPy_Object * self, PyObject * args ); static PyObject *Object_getDupliVerts ( BPy_Object * self ); static PyObject *Object_setDeltaLocation( BPy_Object * self, PyObject * args ); static PyObject *Object_setDrawMode( BPy_Object * self, PyObject * args ); static PyObject *Object_setDrawType( BPy_Object * self, PyObject * args ); static PyObject *Object_setEuler( BPy_Object * self, PyObject * args ); static PyObject *Object_setMatrix( BPy_Object * self, PyObject * args ); static PyObject *Object_setIpo( BPy_Object * self, PyObject * args ); static PyObject *Object_insertIpoKey( BPy_Object * self, PyObject * args ); static PyObject *Object_setLocation( BPy_Object * self, PyObject * args ); static PyObject *Object_setMaterials( BPy_Object * self, PyObject * args ); static PyObject *Object_setName( BPy_Object * self, PyObject * args ); static PyObject *Object_setSize( BPy_Object * self, PyObject * args ); static PyObject *Object_setTimeOffset( BPy_Object * self, PyObject * args ); static PyObject *Object_makeTrack( BPy_Object * self, PyObject * args ); static PyObject *Object_shareFrom( BPy_Object * self, PyObject * args ); static PyObject *Object_Select( BPy_Object * self, PyObject * args ); static PyObject *Object_getAllProperties( BPy_Object * self ); static PyObject *Object_addProperty( BPy_Object * self, PyObject * args ); static PyObject *Object_removeProperty( BPy_Object * self, PyObject * args ); static PyObject *Object_getProperty( BPy_Object * self, PyObject * args ); static PyObject *Object_removeAllProperties( BPy_Object * self ); static PyObject *Object_copyAllPropertiesTo( BPy_Object * self, PyObject * args ); static PyObject *Object_getScriptLinks( BPy_Object * self, PyObject * args ); static PyObject *Object_addScriptLink( BPy_Object * self, PyObject * args ); static PyObject *Object_clearScriptLinks( BPy_Object * self, PyObject *args ); static PyObject *Object_setDupliVerts ( BPy_Object * self, PyObject * args ); static PyObject *Object_getPIStrength( BPy_Object * self ); static PyObject *Object_setPIStrength( BPy_Object * self, PyObject * args ); static PyObject *Object_getPIFalloff( BPy_Object * self ); static PyObject *Object_setPIFalloff( BPy_Object * self, PyObject * args ); static PyObject *Object_getPIMaxDist( BPy_Object * self ); static PyObject *Object_setPIMaxDist( BPy_Object * self, PyObject * args ); static PyObject *Object_getPIUseMaxDist( BPy_Object * self ); static PyObject *Object_setPIUseMaxDist( BPy_Object * self, PyObject * args ); static PyObject *Object_getPIType( BPy_Object * self ); static PyObject *Object_setPIType( BPy_Object * self, PyObject * args ); static PyObject *Object_getPIPerm( BPy_Object * self ); static PyObject *Object_setPIPerm( BPy_Object * self, PyObject * args ); static PyObject *Object_getPIRandomDamp( BPy_Object * self ); static PyObject *Object_setPIRandomDamp( BPy_Object * self, PyObject * args ); static PyObject *Object_getPISurfaceDamp( BPy_Object * self ); static PyObject *Object_setPISurfaceDamp( BPy_Object * self, PyObject * args ); static PyObject *Object_getPIDeflection( BPy_Object * self ); static PyObject *Object_setPIDeflection( BPy_Object * self, PyObject * args ); static PyObject *Object_isSB( BPy_Object * self ); static PyObject *Object_getSBMass( BPy_Object * self ); static PyObject *Object_setSBMass( BPy_Object * self, PyObject * args ); static PyObject *Object_getSBGravity( BPy_Object * self ); static PyObject *Object_setSBGravity( BPy_Object * self, PyObject * args ); static PyObject *Object_getSBFriction( BPy_Object * self ); static PyObject *Object_setSBFriction( BPy_Object * self, PyObject * args ); static PyObject *Object_getSBErrorLimit( BPy_Object * self ); static PyObject *Object_setSBErrorLimit( BPy_Object * self, PyObject * args ); static PyObject *Object_getSBGoalSpring( BPy_Object * self ); static PyObject *Object_setSBGoalSpring( BPy_Object * self, PyObject * args ); static PyObject *Object_getSBGoalFriction( BPy_Object * self ); static PyObject *Object_setSBGoalFriction( BPy_Object * self, PyObject * args ); static PyObject *Object_getSBMinGoal( BPy_Object * self ); static PyObject *Object_setSBMinGoal( BPy_Object * self, PyObject * args ); static PyObject *Object_getSBMaxGoal( BPy_Object * self ); static PyObject *Object_setSBMaxGoal( BPy_Object * self, PyObject * args ); static PyObject *Object_getSBInnerSpring( BPy_Object * self ); static PyObject *Object_setSBInnerSpring( BPy_Object * self, PyObject * args ); static PyObject *Object_getSBInnerSpringFriction( BPy_Object * self ); static PyObject *Object_setSBInnerSpringFriction( BPy_Object * self, PyObject * args ); static PyObject *Object_getSBDefaultGoal( BPy_Object * self ); static PyObject *Object_setSBDefaultGoal( BPy_Object * self, PyObject * args ); static PyObject *Object_getSBUseGoal( BPy_Object * self ); static PyObject *Object_setSBUseGoal( BPy_Object * self, PyObject * args ); static PyObject *Object_getSBUseEdges( BPy_Object * self ); static PyObject *Object_setSBUseEdges( BPy_Object * self, PyObject * args ); static PyObject *Object_getSBStiffQuads( BPy_Object * self ); static PyObject *Object_setSBStiffQuads( BPy_Object * self, PyObject * args ); /*****************************************************************************/ /* Python BPy_Object methods table: */ /*****************************************************************************/ static PyMethodDef BPy_Object_methods[] = { /* name, method, flags, doc */ {"buildParts", ( PyCFunction ) Object_buildParts, METH_NOARGS, "Recalcs particle system (if any) "}, {"getIpo", ( PyCFunction ) Object_getIpo, METH_NOARGS, "Returns the ipo of this object (if any) "}, {"clrParent", ( PyCFunction ) Object_clrParent, METH_VARARGS, "Clears parent object. Optionally specify:\n\ mode\n\tnonzero: Keep object transform\nfast\n\t>0: Don't update scene \ hierarchy (faster)"}, {"clearTrack", ( PyCFunction ) Object_clearTrack, METH_VARARGS, "Make this object not track another anymore. Optionally specify:\n\ mode\n\t2: Keep object transform\nfast\n\t>0: Don't update scene \ hierarchy (faster)"}, {"getData", ( PyCFunction ) Object_getData, METH_VARARGS | METH_KEYWORDS, "(name_only = 0, mesh = 0) - Returns the datablock object containing the object's \ data, e.g. Mesh.\n\ If 'name_only' is nonzero or True, only the name of the datablock is returned"}, {"getDeltaLocation", ( PyCFunction ) Object_getDeltaLocation, METH_NOARGS, "Returns the object's delta location (x, y, z)"}, {"getDrawMode", ( PyCFunction ) Object_getDrawMode, METH_NOARGS, "Returns the object draw modes"}, {"getDrawType", ( PyCFunction ) Object_getDrawType, METH_NOARGS, "Returns the object draw type"}, {"getAction", ( PyCFunction ) Object_getAction, METH_NOARGS, "Returns the active action for this object"}, {"isSelected", ( PyCFunction ) Object_isSelected, METH_NOARGS, "Return a 1 or 0 depending on whether the object is selected"}, {"getEuler", ( PyCFunction ) Object_getEuler, METH_NOARGS, "Returns the object's rotation as Euler rotation vector\n\ (rotX, rotY, rotZ)"}, {"getInverseMatrix", ( PyCFunction ) Object_getInverseMatrix, METH_NOARGS, "Returns the object's inverse matrix"}, {"getLocation", ( PyCFunction ) Object_getLocation, METH_VARARGS, "Returns the object's location (x, y, z)"}, {"getMaterials", ( PyCFunction ) Object_getMaterials, METH_VARARGS, "(i = 0) - Returns list of materials assigned to the object.\n\ if i is nonzero, empty slots are not ignored: they are returned as None's."}, {"getMatrix", ( PyCFunction ) Object_getMatrix, METH_VARARGS, "(str = 'worldspace') - Returns the object matrix.\n\ (str = 'worldspace') - the wanted matrix: worldspace (default), localspace\n\ or old_worldspace.\n\ \n\ 'old_worldspace' was the only behavior before Blender 2.34. With it the\n\ matrix is not updated for changes made by the script itself\n\ (like obj.LocX = 10) until a redraw happens, either called by the script or\n\ automatic when the script finishes."}, {"getName", ( PyCFunction ) Object_getName, METH_NOARGS, "Returns the name of the object"}, {"getParent", ( PyCFunction ) Object_getParent, METH_NOARGS, "Returns the object's parent object"}, {"getParentBoneName", ( PyCFunction ) Object_getParentBoneName, METH_NOARGS, "Returns None, or the 'sub-name' of the parent (eg. Bone name)"}, {"getSize", ( PyCFunction ) Object_getSize, METH_NOARGS, "Returns the object's size (x, y, z)"}, {"getTimeOffset", ( PyCFunction ) Object_getTimeOffset, METH_NOARGS, "Returns the object's time offset"}, {"getTracked", ( PyCFunction ) Object_getTracked, METH_NOARGS, "Returns the object's tracked object"}, {"getType", ( PyCFunction ) Object_getType, METH_NOARGS, "Returns type of string of Object"}, /* Particle Interaction */ {"getPIStrength", ( PyCFunction ) Object_getPIStrength, METH_NOARGS, "Returns Particle Interaction Strength"}, {"setPIStrength", ( PyCFunction ) Object_setPIStrength, METH_VARARGS, "Sets Particle Interaction Strength"}, {"getPIFalloff", ( PyCFunction ) Object_getPIFalloff, METH_NOARGS, "Returns Particle Interaction Falloff"}, {"setPIFalloff", ( PyCFunction ) Object_setPIFalloff, METH_VARARGS, "Sets Particle Interaction Falloff"}, {"getPIMaxDist", ( PyCFunction ) Object_getPIMaxDist, METH_NOARGS, "Returns Particle Interaction Max Distance"}, {"setPIMaxDist", ( PyCFunction ) Object_setPIMaxDist, METH_VARARGS, "Sets Particle Interaction Max Distance"}, {"getPIUseMaxDist", ( PyCFunction ) Object_getPIUseMaxDist, METH_NOARGS, "Returns bool for Use Max Distace in Particle Interaction "}, {"setPIUseMaxDist", ( PyCFunction ) Object_setPIUseMaxDist, METH_VARARGS, "Sets if Max Distance should be used in Particle Interaction"}, {"getPIType", ( PyCFunction ) Object_getPIType, METH_NOARGS, "Returns Particle Interaction Type"}, {"setPIType", ( PyCFunction ) Object_setPIType, METH_VARARGS, "sets Particle Interaction Type"}, {"getPIPerm", ( PyCFunction ) Object_getPIPerm, METH_NOARGS, "Returns Particle Interaction Permiability"}, {"setPIPerm", ( PyCFunction ) Object_setPIPerm, METH_VARARGS, "Sets Particle Interaction Permiability"}, {"getPISurfaceDamp", ( PyCFunction ) Object_getPISurfaceDamp, METH_NOARGS, "Returns Particle Interaction Surface Damping"}, {"setPISurfaceDamp", ( PyCFunction ) Object_setPISurfaceDamp, METH_VARARGS, "Sets Particle Interaction Surface Damping"}, {"getPIRandomDamp", ( PyCFunction ) Object_getPIRandomDamp, METH_NOARGS, "Returns Particle Interaction Random Damping"}, {"setPIRandomDamp", ( PyCFunction ) Object_setPIRandomDamp, METH_VARARGS, "Sets Particle Interaction Random Damping"}, {"getPIDeflection", ( PyCFunction ) Object_getPIDeflection, METH_NOARGS, "Returns Particle Interaction Deflection"}, {"setPIDeflection", ( PyCFunction ) Object_setPIDeflection, METH_VARARGS, "Sets Particle Interaction Deflection"}, /* Softbody */ {"isSB", ( PyCFunction ) Object_isSB, METH_NOARGS, "True if object is a soft body"}, {"getSBMass", ( PyCFunction ) Object_getSBMass, METH_NOARGS, "Returns SB Mass"}, {"setSBMass", ( PyCFunction ) Object_setSBMass, METH_VARARGS, "Sets SB Mass"}, {"getSBGravity", ( PyCFunction ) Object_getSBGravity, METH_NOARGS, "Returns SB Gravity"}, {"setSBGravity", ( PyCFunction ) Object_setSBGravity, METH_VARARGS, "Sets SB Gravity"}, {"getSBFriction", ( PyCFunction ) Object_getSBFriction, METH_NOARGS, "Returns SB Friction"}, {"setSBFriction", ( PyCFunction ) Object_setSBFriction, METH_VARARGS, "Sets SB Friction"}, {"getSBErrorLimit", ( PyCFunction ) Object_getSBErrorLimit, METH_NOARGS, "Returns SB ErrorLimit"}, {"setSBErrorLimit", ( PyCFunction ) Object_setSBErrorLimit, METH_VARARGS, "Sets SB ErrorLimit"}, {"getSBGoalSpring", ( PyCFunction ) Object_getSBGoalSpring, METH_NOARGS, "Returns SB GoalSpring"}, {"setSBGoalSpring", ( PyCFunction ) Object_setSBGoalSpring, METH_VARARGS, "Sets SB GoalSpring"}, {"getSBGoalFriction", ( PyCFunction ) Object_getSBGoalFriction, METH_NOARGS, "Returns SB GoalFriction"}, {"setSBGoalFriction", ( PyCFunction ) Object_setSBGoalFriction, METH_VARARGS, "Sets SB GoalFriction"}, {"getSBMinGoal", ( PyCFunction ) Object_getSBMinGoal, METH_NOARGS, "Returns SB MinGoal"}, {"setSBMinGoal", ( PyCFunction ) Object_setSBMinGoal, METH_VARARGS, "Sets SB MinGoal "}, {"getSBMaxGoal", ( PyCFunction ) Object_getSBMaxGoal, METH_NOARGS, "Returns SB MaxGoal"}, {"setSBMaxGoal", ( PyCFunction ) Object_setSBMaxGoal, METH_VARARGS, "Sets SB MaxGoal"}, {"getSBInnerSpring", ( PyCFunction ) Object_getSBInnerSpring, METH_NOARGS, "Returns SB InnerSpring"}, {"setSBInnerSpring", ( PyCFunction ) Object_setSBInnerSpring, METH_VARARGS, "Sets SB InnerSpring"}, {"getSBInnerSpringFriction", ( PyCFunction ) Object_getSBInnerSpringFriction, METH_NOARGS, "Returns SB InnerSpringFriction"}, {"setSBInnerSpringFriction", ( PyCFunction ) Object_setSBInnerSpringFriction, METH_VARARGS, "Sets SB InnerSpringFriction"}, {"getSBDefaultGoal", ( PyCFunction ) Object_getSBDefaultGoal, METH_NOARGS, "Returns SB DefaultGoal"}, {"setSBDefaultGoal", ( PyCFunction ) Object_setSBDefaultGoal, METH_VARARGS, "Sets SB DefaultGoal"}, {"getSBUseGoal", ( PyCFunction ) Object_getSBUseGoal, METH_NOARGS, "Returns SB UseGoal"}, {"setSBUseGoal", ( PyCFunction ) Object_setSBUseGoal, METH_VARARGS, "Sets SB UseGoal"}, {"getSBUseEdges", ( PyCFunction ) Object_getSBUseEdges, METH_NOARGS, "Returns SB UseEdges"}, {"setSBUseEdges", ( PyCFunction ) Object_setSBUseEdges, METH_VARARGS, "Sets SB UseEdges"}, {"getSBStiffQuads", ( PyCFunction ) Object_getSBStiffQuads, METH_NOARGS, "Returns SB StiffQuads"}, {"setSBStiffQuads", ( PyCFunction ) Object_setSBStiffQuads, METH_VARARGS, "Sets SB StiffQuads"}, {"getBoundBox", ( PyCFunction ) Object_getBoundBox, METH_NOARGS, "Returns the object's bounding box"}, {"getDupliVerts", ( PyCFunction ) Object_getDupliVerts, METH_NOARGS, "Returns state of duplicates propertie"}, {"makeDisplayList", ( PyCFunction ) Object_makeDisplayList, METH_NOARGS, "Update this object's Display List. Some changes like turning \n\ 'SubSurf' on for a mesh need this method (followed by a Redraw) to \n\ show the changes on the 3d window."}, {"link", ( PyCFunction ) Object_link, METH_VARARGS, "Links Object with data provided in the argument. The data must \n\ match the Object's type, so you cannot link a Lamp to a Mesh type object."}, {"makeParent", ( PyCFunction ) Object_makeParent, METH_VARARGS, "Makes the object the parent of the objects provided in the \n\ argument which must be a list of valid Objects. Optional extra arguments:\n\ mode:\n\t0: make parent with inverse\n\t1: without inverse\n\ fast:\n\t0: update scene hierarchy automatically\n\t\ don't update scene hierarchy (faster). In this case, you must\n\t\ explicitely update the Scene hierarchy."}, {"makeParentDeform", ( PyCFunction ) Object_makeParentDeform, METH_VARARGS, "Makes the object the deformation parent of the objects provided in the \n\ argument which must be a list of valid Objects. Optional extra arguments:\n\ mode:\n\t0: make parent with inverse\n\t1: without inverse\n\ fast:\n\t0: update scene hierarchy automatically\n\t\ don't update scene hierarchy (faster). In this case, you must\n\t\ explicitely update the Scene hierarchy."}, {"makeParentVertex", ( PyCFunction ) Object_makeParentVertex, METH_VARARGS, "Makes the object the vertex parent of the objects provided in the \n\ argument which must be a list of valid Objects. \n\ The second argument is a tuple of 1 or 3 positive integers which corresponds \ to the index of the vertex you are parenting to.\n\ Optional extra arguments:\n\ mode:\n\t0: make parent with inverse\n\t1: without inverse\n\ fast:\n\t0: update scene hierarchy automatically\n\t\ don't update scene hierarchy (faster). In this case, you must\n\t\ explicitely update the Scene hierarchy."}, {"materialUsage", ( PyCFunction ) Object_materialUsage, METH_VARARGS, "Determines the way the material is used and returns status.\n\ Possible arguments (provide as strings):\n\ \tData: Materials assigned to the object's data are shown. (default)\n\ \tObject: Materials assigned to the object are shown."}, {"setDeltaLocation", ( PyCFunction ) Object_setDeltaLocation, METH_VARARGS, "Sets the object's delta location which must be a vector triple."}, {"setDrawMode", ( PyCFunction ) Object_setDrawMode, METH_VARARGS, "Sets the object's drawing mode. The argument can be a sum of:\n\ 2: axis\n4: texspace\n8: drawname\n16: drawimage\n32: drawwire"}, {"setDrawType", ( PyCFunction ) Object_setDrawType, METH_VARARGS, "Sets the object's drawing type. The argument must be one of:\n\ 1: Bounding box\n2: Wire\n3: Solid\n4: Shaded\n5: Textured"}, {"setEuler", ( PyCFunction ) Object_setEuler, METH_VARARGS, "Set the object's rotation according to the specified Euler\n\ angles. The argument must be a vector triple"}, {"setMatrix", ( PyCFunction ) Object_setMatrix, METH_VARARGS, "Set and apply a new matrix for the object"}, {"setLocation", ( PyCFunction ) Object_setLocation, METH_VARARGS, "Set the object's location. The first argument must be a vector\n\ triple."}, {"setMaterials", ( PyCFunction ) Object_setMaterials, METH_VARARGS, "Sets materials. The argument must be a list of valid material\n\ objects."}, {"setName", ( PyCFunction ) Object_setName, METH_VARARGS, "Sets the name of the object"}, {"setSize", ( PyCFunction ) Object_setSize, METH_VARARGS, "Set the object's size. The first argument must be a vector\n\ triple."}, {"setTimeOffset", ( PyCFunction ) Object_setTimeOffset, METH_VARARGS, "Set the object's time offset."}, {"makeTrack", ( PyCFunction ) Object_makeTrack, METH_VARARGS, "(trackedobj, fast = 0) - Make this object track another.\n\ (trackedobj) - the object that will be tracked.\n\ (fast = 0) - if 0: update the scene hierarchy automatically. If you\n\ set 'fast' to a nonzero value, don't forget to update the scene yourself\n\ (see scene.update())."}, {"shareFrom", ( PyCFunction ) Object_shareFrom, METH_VARARGS, "Link data of self with object specified in the argument. This\n\ works only if self and the object specified are of the same type."}, {"select", ( PyCFunction ) Object_Select, METH_VARARGS, "( 1 or 0 ) - Set the selected state of the object.\n\ 1 is selected, 0 not selected "}, {"setIpo", ( PyCFunction ) Object_setIpo, METH_VARARGS, "(Blender Ipo) - Sets the object's ipo"}, {"clearIpo", ( PyCFunction ) Object_clearIpo, METH_NOARGS, "() - Unlink ipo from this object"}, {"insertIpoKey", ( PyCFunction ) Object_insertIpoKey, METH_VARARGS, "( Object IPO type ) - Inserts a key into IPO"}, {"getAllProperties", ( PyCFunction ) Object_getAllProperties, METH_NOARGS, "() - Get all the properties from this object"}, {"addProperty", ( PyCFunction ) Object_addProperty, METH_VARARGS, "() - Add a property to this object"}, {"removeProperty", ( PyCFunction ) Object_removeProperty, METH_VARARGS, "() - Remove a property from this object"}, {"getProperty", ( PyCFunction ) Object_getProperty, METH_VARARGS, "() - Get a property from this object by name"}, {"removeAllProperties", ( PyCFunction ) Object_removeAllProperties, METH_NOARGS, "() - removeAll a properties from this object"}, {"copyAllPropertiesTo", ( PyCFunction ) Object_copyAllPropertiesTo, METH_VARARGS, "() - copy all properties from this object to another object"}, {"getScriptLinks", ( PyCFunction ) Object_getScriptLinks, METH_VARARGS, "(eventname) - Get a list of this object's scriptlinks (Text names) " "of the given type\n" "(eventname) - string: FrameChanged, Redraw or Render."}, {"addScriptLink", ( PyCFunction ) Object_addScriptLink, METH_VARARGS, "(text, evt) - Add a new object scriptlink.\n" "(text) - string: an existing Blender Text name;\n" "(evt) string: FrameChanged, Redraw or Render."}, {"clearScriptLinks", ( PyCFunction ) Object_clearScriptLinks, METH_VARARGS, "() - Delete all scriptlinks from this object.\n" "([s1<,s2,s3...>]) - Delete specified scriptlinks from this object."}, {"setDupliVerts", ( PyCFunction ) Object_setDupliVerts, METH_VARARGS, "() - set or reset duplicate child objects on all vertices"}, {NULL, NULL, 0, NULL} }; /*****************************************************************************/ /* PythonTypeObject callback function prototypes */ /*****************************************************************************/ static void Object_dealloc( BPy_Object * obj ); static PyObject *Object_getAttr( BPy_Object * obj, char *name ); static int Object_setAttr( BPy_Object * obj, char *name, PyObject * v ); static PyObject *Object_repr( BPy_Object * obj ); static int Object_compare( BPy_Object * a, BPy_Object * b ); /*****************************************************************************/ /* Python TypeObject structure definition. */ /*****************************************************************************/ PyTypeObject Object_Type = { PyObject_HEAD_INIT( NULL ) /* requred macro */ 0, /* ob_size */ "Blender Object", /* tp_name */ sizeof( BPy_Object ), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ ( destructor ) Object_dealloc, /* tp_dealloc */ 0, /* tp_print */ ( getattrfunc ) Object_getAttr, /* tp_getattr */ ( setattrfunc ) Object_setAttr, /* tp_setattr */ ( cmpfunc ) Object_compare, /* tp_compare */ ( reprfunc ) Object_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_as_hash */ 0, 0, 0, 0, 0, 0, 0, /* tp_doc */ 0, 0, 0, 0, 0, 0, BPy_Object_methods, /* tp_methods */ 0, /* tp_members */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, }; /*****************************************************************************/ /* Function: M_Object_New */ /* Python equivalent: Blender.Object.New */ /*****************************************************************************/ PyObject *M_Object_New( PyObject * self, PyObject * args ) { struct Object *object; BPy_Object *blen_object; int type; char *str_type; char *name = NULL; if( !PyArg_ParseTuple( args, "s|s", &str_type, &name ) ) { EXPP_ReturnPyObjError( PyExc_TypeError, "string expected as argument" ); return ( NULL ); } if( strcmp( str_type, "Armature" ) == 0 ) type = OB_ARMATURE; else if( strcmp( str_type, "Camera" ) == 0 ) type = OB_CAMERA; else if( strcmp( str_type, "Curve" ) == 0 ) type = OB_CURVE; else if (strcmp (str_type, "Text") == 0) type = OB_FONT; else if( strcmp( str_type, "Lamp" ) == 0 ) type = OB_LAMP; else if( strcmp( str_type, "Lattice" ) == 0 ) type = OB_LATTICE; else if( strcmp( str_type, "Mball" ) == 0 ) type = OB_MBALL; else if( strcmp( str_type, "Mesh" ) == 0 ) type = OB_MESH; else if( strcmp( str_type, "Surf" ) == 0 ) type = OB_SURF; /* else if (strcmp (str_type, "Wave") == 0) type = OB_WAVE; */ else if( strcmp( str_type, "Empty" ) == 0 ) type = OB_EMPTY; else { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "Unknown type specified" ) ); } /* Create a new object. */ if( name == NULL ) { /* No name is specified, set the name to the type of the object. */ name = str_type; } object = alloc_libblock( &( G.main->object ), ID_OB, name ); object->id.us = 0; object->flag = 0; object->type = (short)type; /* transforms */ QuatOne( object->quat ); QuatOne( object->dquat ); object->col[3] = 1.0; // alpha object->size[0] = object->size[1] = object->size[2] = 1.0; object->loc[0] = object->loc[1] = object->loc[2] = 0.0; Mat4One( object->parentinv ); Mat4One( object->obmat ); object->dt = OB_SHADED; // drawtype if( U.flag & USER_MAT_ON_OB ) { object->colbits = -1; } switch ( object->type ) { case OB_CAMERA: /* fall through. */ case OB_LAMP: object->trackflag = OB_NEGZ; object->upflag = OB_POSY; break; default: object->trackflag = OB_POSY; object->upflag = OB_POSZ; } object->ipoflag = OB_OFFS_OB + OB_OFFS_PARENT; /* duplivert settings */ object->dupon = 1; object->dupoff = 0; object->dupsta = 1; object->dupend = 100; /* Gameengine defaults */ object->mass = 1.0; object->inertia = 1.0; object->formfactor = 0.4f; object->damping = 0.04f; object->rdamping = 0.1f; object->anisotropicFriction[0] = 1.0; object->anisotropicFriction[1] = 1.0; object->anisotropicFriction[2] = 1.0; object->gameflag = OB_PROP; object->lay = 1; // Layer, by default visible G.totobj++; object->data = NULL; /* Create a Python object from it. */ blen_object = ( BPy_Object * ) PyObject_NEW( BPy_Object, &Object_Type ); blen_object->object = object; return ( ( PyObject * ) blen_object ); } /*****************************************************************************/ /* Function: M_Object_Get */ /* Python equivalent: Blender.Object.Get */ /*****************************************************************************/ PyObject *M_Object_Get( PyObject * self, PyObject * args ) { struct Object *object; BPy_Object *blen_object; char *name = NULL; PyArg_ParseTuple( args, "|s", &name ); if( name != NULL ) { object = GetObjectByName( name ); if( object == NULL ) { /* No object exists with the name specified in the argument name. */ return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "Unknown object specified." ) ); } blen_object = ( BPy_Object * ) PyObject_NEW( BPy_Object, &Object_Type ); blen_object->object = object; return ( ( PyObject * ) blen_object ); } else { /* No argument has been given. Return a list of all objects. */ PyObject *obj_list; Link *link; int index; obj_list = PyList_New( BLI_countlist( &( G.main->object ) ) ); if( obj_list == NULL ) { return ( EXPP_ReturnPyObjError( PyExc_SystemError, "List creation failed." ) ); } link = G.main->object.first; index = 0; while( link ) { object = ( Object * ) link; blen_object = ( BPy_Object * ) PyObject_NEW( BPy_Object, &Object_Type ); blen_object->object = object; PyList_SetItem( obj_list, index, ( PyObject * ) blen_object ); index++; link = link->next; } return ( obj_list ); } } /*****************************************************************************/ /* Function: M_Object_GetSelected */ /* Python equivalent: Blender.Object.GetSelected */ /*****************************************************************************/ static PyObject *M_Object_GetSelected( PyObject * self, PyObject * args ) { BPy_Object *blen_object; PyObject *list; Base *base_iter; if( G.vd == NULL ) { // No 3d view has been initialized yet, simply return None Py_INCREF( Py_None ); return Py_None; } list = PyList_New( 0 ); if( ( G.scene->basact ) && ( ( G.scene->basact->flag & SELECT ) && ( G.scene->basact->lay & G.vd->lay ) ) ) { /* Active object is first in the list. */ blen_object = ( BPy_Object * ) PyObject_NEW( BPy_Object, &Object_Type ); if( blen_object == NULL ) { Py_DECREF( list ); Py_INCREF( Py_None ); return ( Py_None ); } blen_object->object = G.scene->basact->object; PyList_Append( list, ( PyObject * ) blen_object ); Py_DECREF( blen_object ); } base_iter = G.scene->base.first; while( base_iter ) { if( ( ( base_iter->flag & SELECT ) && ( base_iter->lay & G.vd->lay ) ) && ( base_iter != G.scene->basact ) ) { blen_object = ( BPy_Object * ) PyObject_NEW( BPy_Object, &Object_Type ); if( blen_object == NULL ) { Py_DECREF( list ); Py_INCREF( Py_None ); return ( Py_None ); } blen_object->object = base_iter->object; PyList_Append( list, ( PyObject * ) blen_object ); Py_DECREF( blen_object ); } base_iter = base_iter->next; } return ( list ); } /*****************************************************************************/ /* Function: initObject */ /*****************************************************************************/ PyObject *Object_Init( void ) { PyObject *module; Object_Type.ob_type = &PyType_Type; module = Py_InitModule3( "Blender.Object", M_Object_methods, M_Object_doc ); PyModule_AddIntConstant( module, "LOC", IPOKEY_LOC ); PyModule_AddIntConstant( module, "ROT", IPOKEY_ROT ); PyModule_AddIntConstant( module, "SIZE", IPOKEY_SIZE ); PyModule_AddIntConstant( module, "LOCROT", IPOKEY_LOCROT ); PyModule_AddIntConstant( module, "LOCROTSIZE", IPOKEY_LOCROTSIZE ); PyModule_AddIntConstant( module, "PI_STRENGTH", IPOKEY_PI_STRENGTH ); PyModule_AddIntConstant( module, "PI_FALLOFF", IPOKEY_PI_FALLOFF ); PyModule_AddIntConstant( module, "PI_SURFACEDAMP", IPOKEY_PI_SURFACEDAMP ); PyModule_AddIntConstant( module, "PI_RANDOMDAMP", IPOKEY_PI_RANDOMDAMP ); PyModule_AddIntConstant( module, "PI_PERM", IPOKEY_PI_PERM ); PyModule_AddIntConstant( module, "NONE",0 ); PyModule_AddIntConstant( module, "FORCE",PFIELD_FORCE ); PyModule_AddIntConstant( module, "VORTEX",PFIELD_VORTEX ); PyModule_AddIntConstant( module, "MAGNET",PFIELD_MAGNET ); PyModule_AddIntConstant( module, "WIND",PFIELD_WIND ); return ( module ); } /*****************************************************************************/ /* Python BPy_Object methods: */ /*****************************************************************************/ static PyObject *Object_buildParts( BPy_Object * self ) { void build_particle_system( Object * ob ); struct Object *obj = self->object; build_particle_system( obj ); Py_INCREF( Py_None ); return ( Py_None ); } static PyObject *Object_clearIpo( BPy_Object * self ) { Object *ob = self->object; Ipo *ipo = ( Ipo * ) ob->ipo; if( ipo ) { ID *id = &ipo->id; if( id->us > 0 ) id->us--; ob->ipo = NULL; return EXPP_incr_ret_True(); } return EXPP_incr_ret_False(); /* no ipo found */ } static PyObject *Object_clrParent( BPy_Object * self, PyObject * args ) { int mode = 0; int fast = 0; if( !PyArg_ParseTuple( args, "|ii", &mode, &fast ) ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected one or two integers as arguments" ) ); } /* Remove the link only, the object is still in the scene. */ self->object->parent = NULL; if( mode == 2 ) { /* Keep transform */ apply_obmat( self->object ); } if( !fast ) { DAG_scene_sort( G.scene ); } Py_INCREF( Py_None ); return ( Py_None ); } static PyObject *Object_clearTrack( BPy_Object * self, PyObject * args ) { int mode = 0; int fast = 0; if( !PyArg_ParseTuple( args, "|ii", &mode, &fast ) ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected one or two integers as arguments" ) ); } /* Remove the link only, the object is still in the scene. */ self->object->track = NULL; if( mode ) { /* Keep transform */ apply_obmat( self->object ); } if( !fast ) { DAG_scene_sort( G.scene ); } Py_INCREF( Py_None ); return ( Py_None ); } /* adds object data to a Blender object, if object->data = NULL */ int EXPP_add_obdata( struct Object *object ) { if( object->data != NULL ) return -1; switch ( object->type ) { case OB_ARMATURE: /* TODO: Do we need to add something to G? (see the OB_LAMP case) */ object->data = add_armature( ); break; case OB_CAMERA: /* TODO: Do we need to add something to G? (see the OB_LAMP case) */ object->data = add_camera( ); break; case OB_CURVE: object->data = add_curve( OB_CURVE ); G.totcurve++; break; case OB_LAMP: object->data = add_lamp( ); G.totlamp++; break; case OB_MESH: object->data = add_mesh( ); G.totmesh++; break; case OB_LATTICE: object->data = ( void * ) add_lattice( ); object->dt = OB_WIRE; break; case OB_MBALL: object->data = add_mball( ); break; /* TODO the following types will be supported later case OB_SURF: object->data = add_curve(OB_SURF); G.totcurve++; break; case OB_FONT: object->data = add_curve(OB_FONT); break; case OB_WAVE: object->data = add_wave(); break; */ default: break; } if( !object->data ) return -1; return 0; } static PyObject *Object_getData( BPy_Object *self, PyObject *args, PyObject *kwd ) { PyObject *data_object; Object *object = self->object; int name_only = 0; int mesh = 0; /* default mesh type = NMesh */ static char *kwlist[] = {"name_only", "mesh", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwd, "|ii", kwlist, &name_only, &mesh)) return EXPP_ReturnPyObjError( PyExc_AttributeError, "expected nothing or bool keyword 'name_only' as argument" ); /* if there's no obdata, try to create it */ if( object->data == NULL ) { if( EXPP_add_obdata( object ) != 0 ) { /* couldn't create obdata */ Py_INCREF( Py_None ); return ( Py_None ); } } /* user wants only the name of the data object */ if (name_only) { ID *id = object->data; data_object = Py_BuildValue("s", id->name+2); if (data_object) return data_object; return EXPP_ReturnPyObjError (PyExc_MemoryError, "could not create a string pyobject!"); } /* user wants the data object wrapper */ data_object = NULL; switch ( object->type ) { case OB_ARMATURE: data_object = Armature_CreatePyObject( object->data ); break; case OB_CAMERA: data_object = Camera_CreatePyObject( object->data ); break; case OB_CURVE: data_object = Curve_CreatePyObject( object->data ); break; case ID_IM: data_object = Image_CreatePyObject( object->data ); break; case ID_IP: data_object = Ipo_CreatePyObject( object->data ); break; case OB_LAMP: data_object = Lamp_CreatePyObject( object->data ); break; case OB_LATTICE: data_object = Lattice_CreatePyObject( object->data ); break; case ID_MA: break; case OB_MESH: if( !mesh ) /* get as NMesh (default) */ data_object = NMesh_CreatePyObject( object->data, object ); else /* else get as Mesh */ data_object = Mesh_CreatePyObject( object->data ); break; case ID_OB: data_object = Object_CreatePyObject( object->data ); break; case ID_SCE: break; case ID_TXT: data_object = Text_CreatePyObject( object->data ); break; case OB_FONT: data_object = Text3d_CreatePyObject( object->data ); break; case ID_WO: break; default: break; } if( data_object == NULL ) { Py_INCREF( Py_None ); return ( Py_None ); } else { return ( data_object ); } } static PyObject *Object_getDeltaLocation( BPy_Object * self ) { PyObject *attr = Py_BuildValue( "fff", self->object->dloc[0], self->object->dloc[1], self->object->dloc[2] ); if( attr ) return ( attr ); return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object.dloc attributes" ) ); } static PyObject *Object_getDrawMode( BPy_Object * self ) { PyObject *attr = Py_BuildValue( "b", self->object->dtx ); if( attr ) return ( attr ); return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object.drawMode attribute" ) ); } static PyObject *Object_getAction( BPy_Object * self ) { /*BPy_Action *py_action = NULL; */ if( !self->object->action ) { Py_INCREF( Py_None ); return ( Py_None ); } else { return Action_CreatePyObject( self->object->action ); } } static PyObject *Object_isSelected( BPy_Object * self ) { Base *base; base = FIRSTBASE; while( base ) { if( base->object == self->object ) { if( base->flag & SELECT ) { return EXPP_incr_ret_True(); } else { return EXPP_incr_ret_False(); } } base = base->next; } return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "Internal error: could not find objects selection state" ) ); } static PyObject *Object_getDrawType( BPy_Object * self ) { PyObject *attr = Py_BuildValue( "b", self->object->dt ); if( attr ) return ( attr ); return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object.drawType attribute" ) ); } static PyObject *Object_getEuler( BPy_Object * self ) { float eul[3]; eul[0] = self->object->rot[0]; eul[1] = self->object->rot[1]; eul[2] = self->object->rot[2]; return ( PyObject * ) newEulerObject( eul, Py_WRAP ); } static PyObject *Object_getInverseMatrix( BPy_Object * self ) { MatrixObject *inverse = ( MatrixObject * ) newMatrixObject( NULL, 4, 4, Py_NEW); Mat4Invert( (float ( * )[4])*inverse->matrix, self->object->obmat ); return ( ( PyObject * ) inverse ); } static PyObject *Object_getIpo( BPy_Object * self ) { struct Ipo *ipo = self->object->ipo; if( !ipo ) { Py_INCREF( Py_None ); return Py_None; } return Ipo_CreatePyObject( ipo ); } static PyObject *Object_getLocation( BPy_Object * self, PyObject * args ) { PyObject *attr = Py_BuildValue( "fff", self->object->loc[0], self->object->loc[1], self->object->loc[2] ); if( attr ) return ( attr ); return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object.loc attributes" ) ); } static PyObject *Object_getMaterials( BPy_Object * self, PyObject * args ) { int all = 0; if( !PyArg_ParseTuple( args, "|i", &all ) ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected an int or nothing" ) ); } return ( EXPP_PyList_fromMaterialList( self->object->mat, self->object->totcol, all ) ); } static PyObject *Object_getMatrix( BPy_Object * self, PyObject * args ) { float matrix[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; char *space = "worldspace"; /* default to world */ if( !PyArg_ParseTuple( args, "|s", &space ) ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected a string or nothing" ) ); } if( BLI_streq( space, "worldspace" ) ) { /* Worldspace matrix */ disable_where_script( 1 ); where_is_object( self->object ); disable_where_script( 0 ); } else if( BLI_streq( space, "localspace" ) ) { /* Localspace matrix */ object_to_mat4( self->object, (float (*)[4])matrix ); return newMatrixObject(matrix,4,4,Py_NEW); } else if( BLI_streq( space, "old_worldspace" ) ) { /* old behavior, prior to 2.34, check this method's doc string: */ } else { return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "wrong parameter, expected nothing or either 'worldspace' (default),\n\ 'localspace' or 'old_worldspace'" ) ); } return newMatrixObject((float*)self->object->obmat,4,4,Py_WRAP); } static PyObject *Object_getName( BPy_Object * self ) { PyObject *attr = Py_BuildValue( "s", self->object->id.name + 2 ); if( attr ) return ( attr ); return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get the name of the Object" ) ); } static PyObject *Object_getParent( BPy_Object * self ) { PyObject *attr; if( self->object->parent == NULL ) return EXPP_incr_ret( Py_None ); attr = Object_CreatePyObject( self->object->parent ); if( attr ) { return ( attr ); } return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object.parent attribute" ) ); } static PyObject *Object_getParentBoneName( BPy_Object * self ) { PyObject *attr; if( self->object->parent == NULL ) return EXPP_incr_ret( Py_None ); if( self->object->parsubstr[0] == '\0' ) return EXPP_incr_ret( Py_None ); attr = Py_BuildValue( "s", self->object->parsubstr ); if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "Failed to get parent bone name" ) ); } static PyObject *Object_getSize( BPy_Object * self, PyObject * args ) { PyObject *attr = Py_BuildValue( "fff", self->object->size[0], self->object->size[1], self->object->size[2] ); if( attr ) return ( attr ); return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object.size attributes" ) ); } static PyObject *Object_getTimeOffset( BPy_Object * self ) { PyObject *attr = Py_BuildValue( "f", self->object->sf ); if( attr ) return ( attr ); return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object.sf attributes" ) ); } static PyObject *Object_getTracked( BPy_Object * self ) { PyObject *attr; if( self->object->track == NULL ) return EXPP_incr_ret( Py_None ); attr = Object_CreatePyObject( self->object->track ); if( attr ) { return ( attr ); } return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object.track attribute" ) ); } static PyObject *Object_getType( BPy_Object * self ) { switch ( self->object->type ) { case OB_ARMATURE: return ( Py_BuildValue( "s", "Armature" ) ); case OB_CAMERA: return ( Py_BuildValue( "s", "Camera" ) ); case OB_CURVE: return ( Py_BuildValue( "s", "Curve" ) ); case OB_EMPTY: return ( Py_BuildValue( "s", "Empty" ) ); case OB_FONT: return ( Py_BuildValue( "s", "Text" ) ); case OB_LAMP: return ( Py_BuildValue( "s", "Lamp" ) ); case OB_LATTICE: return ( Py_BuildValue( "s", "Lattice" ) ); case OB_MBALL: return ( Py_BuildValue( "s", "MBall" ) ); case OB_MESH: return ( Py_BuildValue( "s", "Mesh" ) ); case OB_SURF: return ( Py_BuildValue( "s", "Surf" ) ); case OB_WAVE: return ( Py_BuildValue( "s", "Wave" ) ); default: return ( Py_BuildValue( "s", "unknown" ) ); } } static PyObject *Object_getBoundBox( BPy_Object * self ) { int i; float *vec = NULL; PyObject *vector, *bbox; if( !self->object->data ) return EXPP_ReturnPyObjError( PyExc_AttributeError, "This object isn't linked to any object data (mesh, curve, etc) yet" ); if( !self->object->bb ) { /* if no ob bbox, we look in obdata */ Mesh *me; Curve *curve; switch ( self->object->type ) { case OB_MESH: me = self->object->data; vec = (float*) mesh_get_bb(me)->vec; break; case OB_CURVE: case OB_FONT: case OB_SURF: curve = self->object->data; if( !curve->bb ) tex_space_curve( curve ); vec = ( float * ) curve->bb->vec; break; default: Py_INCREF( Py_None ); return Py_None; } { /* transform our obdata bbox by the obmat. the obmat is 4x4 homogeneous coords matrix. each bbox coord is xyz, so we make it homogenous by padding it with w=1.0 and doing the matrix mult. afterwards we divide by w to get back to xyz. */ /* printmatrix4( "obmat", self->object->obmat); */ float tmpvec[4]; /* tmp vector for homogenous coords math */ int i; float *from; bbox = PyList_New( 8 ); if( !bbox ) return EXPP_ReturnPyObjError ( PyExc_MemoryError, "couldn't create pylist" ); for( i = 0, from = vec; i < 8; i++, from += 3 ) { memcpy( tmpvec, from, 3 * sizeof( float ) ); tmpvec[3] = 1.0f; /* set w coord */ Mat4MulVec4fl( self->object->obmat, tmpvec ); /* divide x,y,z by w */ tmpvec[0] /= tmpvec[3]; tmpvec[1] /= tmpvec[3]; tmpvec[2] /= tmpvec[3]; #if 0 { /* debug print stuff */ int i; printf( "\nobj bbox transformed\n" ); for( i = 0; i < 4; ++i ) printf( "%f ", tmpvec[i] ); printf( "\n" ); } #endif /* because our bounding box is calculated and does not have its own memory, we must create vectors that allocate space */ vector = newVectorObject( NULL, 3, Py_NEW); memcpy( ( ( VectorObject * ) vector )->vec, tmpvec, 3 * sizeof( float ) ); PyList_SET_ITEM( bbox, i, vector ); } } } else { /* the ob bbox exists */ vec = ( float * ) self->object->bb->vec; if( !vec ) return EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't retrieve bounding box data" ); bbox = PyList_New( 8 ); if( !bbox ) return EXPP_ReturnPyObjError( PyExc_MemoryError, "couldn't create pylist" ); /* create vectors referencing object bounding box coords */ for( i = 0; i < 8; i++ ) { vector = newVectorObject( vec, 3, Py_WRAP ); PyList_SET_ITEM( bbox, i, vector ); vec += 3; } } return bbox; } static PyObject *Object_makeDisplayList( BPy_Object * self ) { Object *ob = self->object; if( ob->type == OB_FONT ) text_to_curve( ob, 0 ); DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); Py_INCREF( Py_None ); return Py_None; } static PyObject *Object_link( BPy_Object * self, PyObject * args ) { PyObject *py_data; ID *id; ID *oldid; int obj_id; void *data = NULL; if( !PyArg_ParseTuple( args, "O", &py_data ) ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected an object as argument" ) ); } if( Armature_CheckPyObject( py_data ) ) data = ( void * ) Armature_FromPyObject( py_data ); else if( Camera_CheckPyObject( py_data ) ) data = ( void * ) Camera_FromPyObject( py_data ); else if( Lamp_CheckPyObject( py_data ) ) data = ( void * ) Lamp_FromPyObject( py_data ); else if( Curve_CheckPyObject( py_data ) ) data = ( void * ) Curve_FromPyObject( py_data ); else if( NMesh_CheckPyObject( py_data ) ) data = ( void * ) NMesh_FromPyObject( py_data, self->object ); else if( Mesh_CheckPyObject( py_data ) ) data = ( void * ) Mesh_FromPyObject( py_data ); else if( Lattice_CheckPyObject( py_data ) ) data = ( void * ) Lattice_FromPyObject( py_data ); else if( Metaball_CheckPyObject( py_data ) ) data = ( void * ) Metaball_FromPyObject( py_data ); else if( Text3d_CheckPyObject( py_data ) ) data = ( void * ) Text3d_FromPyObject( py_data ); /* have we set data to something good? */ if( !data ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "link argument type is not supported " ) ); } oldid = ( ID * ) self->object->data; id = ( ID * ) data; obj_id = MAKE_ID2( id->name[0], id->name[1] ); switch ( obj_id ) { case ID_AR: if( self->object->type != OB_ARMATURE ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "The 'link' object is incompatible with the base object" ) ); } break; case ID_CA: if( self->object->type != OB_CAMERA ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "The 'link' object is incompatible with the base object" ) ); } break; case ID_LA: if( self->object->type != OB_LAMP ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "The 'link' object is incompatible with the base object" ) ); } break; case ID_ME: if( self->object->type != OB_MESH ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "The 'link' object is incompatible with the base object" ) ); } break; case ID_CU: if( self->object->type != OB_CURVE && self->object->type != OB_FONT ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "The 'link' object is incompatible with the base object" ) ); } break; case ID_LT: if( self->object->type != OB_LATTICE ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "The 'link' object is incompatible with the base object" ) ); } break; case ID_MB: if( self->object->type != OB_MBALL ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "The 'link' object is incompatible with the base object" ) ); } break; default: return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "Linking this object type is not supported" ) ); } self->object->data = data; if( self->object->type == OB_MESH ) { self->object->totcol = 0; EXPP_synchronizeMaterialLists( self->object ); } //creates the curve for the text object if (self->object->type == OB_FONT) text_to_curve(self->object, 0); id_us_plus( id ); if( oldid ) { if( oldid->us > 0 ) { oldid->us--; } else { return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "old object reference count below 0" ) ); } } return EXPP_incr_ret( Py_None ); } static PyObject *Object_makeParentVertex( BPy_Object * self, PyObject * args ) { PyObject *list; PyObject *vlist; PyObject *py_child; PyObject *ret_val; Object *parent; int noninverse = 0; int fast = 0; int partype; int v1, v2=0, v3=0; int i, vlen; /* Check if the arguments passed to makeParent are valid. */ if( !PyArg_ParseTuple( args, "OO|ii", &list, &vlist, &noninverse, &fast ) ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected a list of objects, a tuple of integers and one or two integers as arguments" ) ); } if( !PySequence_Check( list ) ) { return ( EXPP_ReturnPyObjError( PyExc_TypeError, "expected a list of objects" ) ); } if (!PyTuple_Check( vlist )) return ( EXPP_ReturnPyObjError( PyExc_TypeError, "expected a tuple of integers" ) ); vlen = PyTuple_Size( vlist ); switch (vlen) { case 1: if( !PyArg_ParseTuple( vlist, "i", &v1 ) ) return ( EXPP_ReturnPyObjError( PyExc_TypeError, "expected a tuple of 1 or 3 integers" ) ); if ( v1 < 0 ) return ( EXPP_ReturnPyObjError( PyExc_ValueError, "indices must be strictly positive" ) ); partype = PARVERT1; break; case 3: if( !PyArg_ParseTuple( vlist, "iii", &v1, &v2, &v3 ) ) return ( EXPP_ReturnPyObjError( PyExc_TypeError, "expected a tuple of 1 or 3 integers" ) ); if ( v1 < 0 || v2 < 0 || v3 < 0) return ( EXPP_ReturnPyObjError( PyExc_ValueError, "indices must be strictly positive" ) ); partype = PARVERT3; break; default: return ( EXPP_ReturnPyObjError( PyExc_TypeError, "expected a tuple of 1 or 3 integers" ) ); } parent = ( Object * ) self->object; if (!ELEM3(parent->type, OB_MESH, OB_CURVE, OB_SURF)) return ( EXPP_ReturnPyObjError( PyExc_TypeError, "Parent Vertex only applies to curve, mesh or surface objects" ) ); if (parent->id.us == 0) return EXPP_ReturnPyObjError (PyExc_RuntimeError, "object must be linked to a scene before it can become a parent"); /* Check if the PyObject passed in list is a Blender object. */ for( i = 0; i < PySequence_Length( list ); i++ ) { py_child = PySequence_GetItem( list, i ); ret_val = internal_makeParent(parent, py_child, partype, noninverse, fast, v1, v2, v3); Py_DECREF (py_child); if (ret_val) Py_DECREF(ret_val); else { if (!fast) /* need to sort when interupting in the middle of the list */ DAG_scene_sort( G.scene ); return NULL; /* error has been set already */ } } if (!fast) /* otherwise, only sort at the end */ DAG_scene_sort( G.scene ); return EXPP_incr_ret( Py_None ); } static PyObject *Object_makeParentDeform( BPy_Object * self, PyObject * args ) { PyObject *list; PyObject *py_child; PyObject *ret_val; Object *parent; int noninverse = 0; int fast = 0; int i; /* Check if the arguments passed to makeParent are valid. */ if( !PyArg_ParseTuple( args, "O|ii", &list, &noninverse, &fast ) ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected a list of objects and one or two integers as arguments" ) ); } if( !PySequence_Check( list ) ) { return ( EXPP_ReturnPyObjError( PyExc_TypeError, "expected a list of objects" ) ); } parent = ( Object * ) self->object; if (parent->type != OB_CURVE && parent->type != OB_ARMATURE) return ( EXPP_ReturnPyObjError( PyExc_ValueError, "Parent Deform only applies to curve or armature objects" ) ); if (parent->id.us == 0) return EXPP_ReturnPyObjError (PyExc_RuntimeError, "object must be linked to a scene before it can become a parent"); /* Check if the PyObject passed in list is a Blender object. */ for( i = 0; i < PySequence_Length( list ); i++ ) { py_child = PySequence_GetItem( list, i ); ret_val = internal_makeParent(parent, py_child, PARSKEL, noninverse, fast, 0, 0, 0); Py_DECREF (py_child); if (ret_val) Py_DECREF(ret_val); else { if (!fast) /* need to sort when interupting in the middle of the list */ DAG_scene_sort( G.scene ); return NULL; /* error has been set already */ } } if (!fast) /* otherwise, only sort at the end */ DAG_scene_sort( G.scene ); return EXPP_incr_ret( Py_None ); } static PyObject *Object_makeParent( BPy_Object * self, PyObject * args ) { PyObject *list; PyObject *py_child; PyObject *ret_val; Object *parent; int noninverse = 0; int fast = 0; int i; /* Check if the arguments passed to makeParent are valid. */ if( !PyArg_ParseTuple( args, "O|ii", &list, &noninverse, &fast ) ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected a list of objects and one or two integers as arguments" ) ); } if( !PySequence_Check( list ) ) { return ( EXPP_ReturnPyObjError( PyExc_TypeError, "expected a list of objects" ) ); } parent = ( Object * ) self->object; if (parent->id.us == 0) return EXPP_ReturnPyObjError (PyExc_RuntimeError, "object must be linked to a scene before it can become a parent"); /* Check if the PyObject passed in list is a Blender object. */ for( i = 0; i < PySequence_Length( list ); i++ ) { py_child = PySequence_GetItem( list, i ); ret_val = internal_makeParent(parent, py_child, PAROBJECT, noninverse, fast, 0, 0, 0); Py_DECREF (py_child); if (ret_val) Py_DECREF(ret_val); else { if (!fast) /* need to sort when interupting in the middle of the list */ DAG_scene_sort( G.scene ); return NULL; /* error has been set already */ } } if (!fast) /* otherwise, only sort at the end */ DAG_scene_sort( G.scene ); return EXPP_incr_ret( Py_None ); } static PyObject *internal_makeParent(Object *parent, PyObject *py_child, int partype, /* parenting type */ int noninverse, int fast, /* parenting arguments */ int v1, int v2, int v3 /* for vertex parent */ ) { Object *child = NULL; if( Object_CheckPyObject( py_child ) ) child = ( Object * ) Object_FromPyObject( py_child ); if( child == NULL ) { return ( EXPP_ReturnPyObjError( PyExc_TypeError, "Object Type expected" ) ); } if( test_parent_loop( parent, child ) ) { return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "parenting loop detected - parenting failed" ) ); } if (partype == PARSKEL && child->type != OB_MESH) child->partype = PAROBJECT; else child->partype = (short)partype; if (partype == PARVERT3) { child->par1 = v1; child->par2 = v2; child->par3 = v3; } else if (partype == PARVERT1) { child->par1 = v1; } child->parent = parent; //py_obj_child = (BPy_Object *) py_child; if( noninverse == 1 ) { /* Parent inverse = unity */ child->loc[0] = 0.0; child->loc[1] = 0.0; child->loc[2] = 0.0; } else { what_does_parent( child ); Mat4Invert( child->parentinv, workob.obmat ); clear_workob(); } if( !fast ) { child->recalc |= OB_RECALC_OB; } return EXPP_incr_ret( Py_None ); } static PyObject *Object_materialUsage( BPy_Object * self, PyObject * args ) { return ( EXPP_ReturnPyObjError( PyExc_NotImplementedError, "materialUsage: not yet implemented" ) ); } static PyObject *Object_setDeltaLocation( BPy_Object * self, PyObject * args ) { float dloc1; float dloc2; float dloc3; int status; if( PyObject_Length( args ) == 3 ) status = PyArg_ParseTuple( args, "fff", &dloc1, &dloc2, &dloc3 ); else status = PyArg_ParseTuple( args, "(fff)", &dloc1, &dloc2, &dloc3 ); if( !status ) return EXPP_ReturnPyObjError( PyExc_AttributeError, "expected list argument of 3 floats" ); self->object->dloc[0] = dloc1; self->object->dloc[1] = dloc2; self->object->dloc[2] = dloc3; Py_INCREF( Py_None ); return ( Py_None ); } static PyObject *Object_setDrawMode( BPy_Object * self, PyObject * args ) { char dtx; if( !PyArg_ParseTuple( args, "b", &dtx ) ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected an integer as argument" ) ); } self->object->dtx = dtx; Py_INCREF( Py_None ); return ( Py_None ); } static PyObject *Object_setDrawType( BPy_Object * self, PyObject * args ) { char dt; if( !PyArg_ParseTuple( args, "b", &dt ) ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected an integer as argument" ) ); } self->object->dt = dt; Py_INCREF( Py_None ); return ( Py_None ); } static PyObject *Object_setEuler( BPy_Object * self, PyObject * args ) { float rot1 = 0.0f; float rot2 = 0.0f; float rot3 = 0.0f; int status = 0; /* failure */ PyObject *ob; /* args is either a tuple/list of floats or an euler. for backward compatibility, we also accept 3 floats. */ /* do we have 3 floats? */ if( PyObject_Length( args ) == 3 ) { status = PyArg_ParseTuple( args, "fff", &rot1, &rot2, &rot3 ); } else { //test to see if it's a list or a euler if( PyArg_ParseTuple( args, "O", &ob ) ) { if( EulerObject_Check( ob ) ) { rot1 = ( ( EulerObject * ) ob )->eul[0]; rot2 = ( ( EulerObject * ) ob )->eul[1]; rot3 = ( ( EulerObject * ) ob )->eul[2]; status = 1; /* success! */ } else if( PySequence_Check( ob ) ) status = PyArg_ParseTuple( args, "(fff)", &rot1, &rot2, &rot3 ); else { /* not an euler or tuple */ /* python C api doc says don't decref this */ /*Py_DECREF (ob); */ status = 0; /* false */ } } else { /* arg parsing failed */ status = 0; } } if( !status ) /* parsing args failed */ return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected euler or list/tuple of 3 floats " ) ); self->object->rot[0] = rot1; self->object->rot[1] = rot2; self->object->rot[2] = rot3; Py_INCREF( Py_None ); return ( Py_None ); } static PyObject *Object_setMatrix( BPy_Object * self, PyObject * args ) { MatrixObject *mat; int x, y; if( !PyArg_ParseTuple( args, "O!", &matrix_Type, &mat ) ) return EXPP_ReturnPyObjError ( PyExc_TypeError, "expected matrix object as argument" ); for( x = 0; x < 4; x++ ) { for( y = 0; y < 4; y++ ) { self->object->obmat[x][y] = mat->matrix[x][y]; } } apply_obmat( self->object ); Py_INCREF( Py_None ); return ( Py_None ); } static PyObject *Object_setIpo( BPy_Object * self, PyObject * args ) { PyObject *pyipo = 0; Ipo *ipo = NULL; Ipo *oldipo; if( !PyArg_ParseTuple( args, "O!", &Ipo_Type, &pyipo ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected Ipo as argument" ); ipo = Ipo_FromPyObject( pyipo ); if( !ipo ) return EXPP_ReturnPyObjError( PyExc_RuntimeError, "null ipo!" ); if( ipo->blocktype != ID_OB ) return EXPP_ReturnPyObjError( PyExc_TypeError, "this ipo is not an object ipo" ); oldipo = self->object->ipo; if( oldipo ) { ID *id = &oldipo->id; if( id->us > 0 ) id->us--; } ( ( ID * ) & ipo->id )->us++; self->object->ipo = ipo; Py_INCREF( Py_None ); return Py_None; } /* * Object_insertIpoKey() * inserts Object IPO key for LOC, ROT, SIZE, LOCROT, or LOCROTSIZE * Note it also inserts actions! */ static PyObject *Object_insertIpoKey( BPy_Object * self, PyObject * args ) { Object *ob= self->object; int key = 0; char *actname= NULL; if( !PyArg_ParseTuple( args, "i", &( key ) ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected int argument" ) ); if(ob->ipoflag & OB_ACTION_OB) actname= "Object"; if (key == IPOKEY_LOC || key == IPOKEY_LOCROT || key == IPOKEY_LOCROTSIZE){ insertkey((ID *)ob, ID_OB, actname, NULL,OB_LOC_X); insertkey((ID *)ob, ID_OB, actname, NULL,OB_LOC_Y); insertkey((ID *)ob, ID_OB, actname, NULL,OB_LOC_Z); } if (key == IPOKEY_ROT || key == IPOKEY_LOCROT || key == IPOKEY_LOCROTSIZE){ insertkey((ID *)ob, ID_OB, actname, NULL,OB_ROT_X); insertkey((ID *)ob, ID_OB, actname, NULL,OB_ROT_Y); insertkey((ID *)ob, ID_OB, actname, NULL,OB_ROT_Z); } if (key == IPOKEY_SIZE || key == IPOKEY_LOCROTSIZE ){ insertkey((ID *)ob, ID_OB, actname, NULL,OB_SIZE_X); insertkey((ID *)ob, ID_OB, actname, NULL,OB_SIZE_Y); insertkey((ID *)ob, ID_OB, actname, NULL,OB_SIZE_Z); } if (key == IPOKEY_PI_STRENGTH ){ insertkey((ID *)ob, ID_OB, actname, NULL, OB_PD_FSTR); } if (key == IPOKEY_PI_FALLOFF ){ insertkey((ID *)ob, ID_OB, actname, NULL, OB_PD_FFALL); } if (key == IPOKEY_PI_SURFACEDAMP ){ insertkey((ID *)ob, ID_OB, actname, NULL, OB_PD_SDAMP); } if (key == IPOKEY_PI_RANDOMDAMP ){ insertkey((ID *)ob, ID_OB, actname, NULL, OB_PD_RDAMP); } if (key == IPOKEY_PI_PERM ){ insertkey((ID *)ob, ID_OB, actname, NULL, OB_PD_PERM); } allspace(REMAKEIPO, 0); EXPP_allqueue(REDRAWIPO, 0); EXPP_allqueue(REDRAWVIEW3D, 0); EXPP_allqueue(REDRAWACTION, 0); EXPP_allqueue(REDRAWNLA, 0); return EXPP_incr_ret( Py_None ); } static PyObject *Object_setLocation( BPy_Object * self, PyObject * args ) { float loc1; float loc2; float loc3; int status; if( PyObject_Length( args ) == 3 ) status = PyArg_ParseTuple( args, "fff", &loc1, &loc2, &loc3 ); else status = PyArg_ParseTuple( args, "(fff)", &loc1, &loc2, &loc3 ); if( !status ) return EXPP_ReturnPyObjError( PyExc_AttributeError, "expected list argument of 3 floats" ); self->object->loc[0] = loc1; self->object->loc[1] = loc2; self->object->loc[2] = loc3; /* since we have messed with object, we need to flag for DAG recalc */ self->object->recalc |= OB_RECALC_OB; Py_INCREF( Py_None ); return ( Py_None ); } static PyObject *Object_setMaterials( BPy_Object * self, PyObject * args ) { PyObject *list; int len; int i; Material **matlist; if( !PyArg_ParseTuple( args, "O!", &PyList_Type, &list ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a list of materials (None's also accepted) as argument" ); len = PyList_Size(list); if( len > MAXMAT ) return EXPP_ReturnPyObjError( PyExc_TypeError, "list must have from 1 up to 16 materials" ); matlist = EXPP_newMaterialList_fromPyList( list ); if( !matlist ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "material list must be a list of valid materials!" ) ); } if( self->object->mat ) EXPP_releaseMaterialList( self->object->mat, self->object->totcol ); /* Increase the user count on all materials */ for( i = 0; i < len; i++ ) { if( matlist[i] ) id_us_plus( ( ID * ) matlist[i] ); } self->object->mat = matlist; self->object->totcol = (char)len; self->object->actcol = (char)len; switch ( self->object->type ) { case OB_CURVE: /* fall through */ case OB_FONT: /* fall through */ case OB_MESH: /* fall through */ case OB_MBALL: /* fall through */ case OB_SURF: EXPP_synchronizeMaterialLists( self->object ); break; default: break; } return EXPP_incr_ret( Py_None ); } static PyObject *Object_setName( BPy_Object * self, PyObject * args ) { char *name; char buf[21]; if( !PyArg_ParseTuple( args, "s", &name ) ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected a String as argument" ) ); } PyOS_snprintf( buf, sizeof( buf ), "%s", name ); rename_id( &self->object->id, buf ); Py_INCREF( Py_None ); return ( Py_None ); } static PyObject *Object_setSize( BPy_Object * self, PyObject * args ) { float sizex; float sizey; float sizez; int status; if( PyObject_Length( args ) == 3 ) status = PyArg_ParseTuple( args, "fff", &sizex, &sizey, &sizez ); else status = PyArg_ParseTuple( args, "(fff)", &sizex, &sizey, &sizez ); if( !status ) return EXPP_ReturnPyObjError( PyExc_AttributeError, "expected list argument of 3 floats" ); self->object->size[0] = sizex; self->object->size[1] = sizey; self->object->size[2] = sizez; Py_INCREF( Py_None ); return ( Py_None ); } static PyObject *Object_setTimeOffset( BPy_Object * self, PyObject * args ) { float newTimeOffset; if( !PyArg_ParseTuple( args, "f", &newTimeOffset ) ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected a float as argument" ) ); } self->object->sf = newTimeOffset; Py_INCREF( Py_None ); return ( Py_None ); } static PyObject *Object_makeTrack( BPy_Object * self, PyObject * args ) { BPy_Object *tracked = NULL; Object *ob = self->object; int fast = 0; if( !PyArg_ParseTuple( args, "O!|i", &Object_Type, &tracked, &fast ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected an object and optionally also an int as arguments." ); ob->track = tracked->object; if( !fast ) DAG_scene_sort( G.scene ); return EXPP_incr_ret( Py_None ); } static PyObject *Object_shareFrom( BPy_Object * self, PyObject * args ) { BPy_Object *object; ID *id; ID *oldid; if( !PyArg_ParseTuple( args, "O", &object ) ) { return EXPP_ReturnPyObjError( PyExc_TypeError, "expected an object argument" ); } if( !Object_CheckPyObject( ( PyObject * ) object ) ) { return EXPP_ReturnPyObjError( PyExc_TypeError, "first argument is not of type 'Object'" ); } if( self->object->type != object->object->type ) { return EXPP_ReturnPyObjError( PyExc_TypeError, "objects are not of same data type" ); } switch ( self->object->type ) { case OB_MESH: case OB_LAMP: case OB_CAMERA: /* we can probably add the other types, too */ case OB_ARMATURE: case OB_CURVE: case OB_SURF: case OB_LATTICE: oldid = ( ID * ) self->object->data; id = ( ID * ) object->object->data; self->object->data = object->object->data; if( self->object->type == OB_MESH && id ) { self->object->totcol = 0; EXPP_synchronizeMaterialLists( self->object ); } id_us_plus( id ); if( oldid ) { if( oldid->us > 0 ) { oldid->us--; } else { return ( EXPP_ReturnPyObjError ( PyExc_RuntimeError, "old object reference count below 0" ) ); } } Py_INCREF( Py_None ); return ( Py_None ); default: return EXPP_ReturnPyObjError( PyExc_TypeError, "type not supported" ); } } static PyObject *Object_Select( BPy_Object * self, PyObject * args ) { Base *base; int sel; base = FIRSTBASE; if( !PyArg_ParseTuple( args, "i", &sel ) ) return EXPP_ReturnPyObjError ( PyExc_TypeError, "expected an integer, 0 or 1" ); while( base ) { if( base->object == self->object ) { if( sel == 1 ) { base->flag |= SELECT; self->object->flag = (short)base->flag; set_active_base( base ); } else { base->flag &= ~SELECT; self->object->flag = (short)base->flag; } break; } base = base->next; } countall( ); Py_INCREF( Py_None ); return ( Py_None ); } static PyObject *Object_getAllProperties( BPy_Object * self ) { PyObject *prop_list; bProperty *prop = NULL; prop_list = PyList_New( 0 ); prop = self->object->prop.first; while( prop ) { PyList_Append( prop_list, Property_CreatePyObject( prop ) ); prop = prop->next; } return prop_list; } static PyObject *Object_getProperty( BPy_Object * self, PyObject * args ) { char *prop_name = NULL; bProperty *prop = NULL; PyObject *py_prop = Py_None; if( !PyArg_ParseTuple( args, "s", &prop_name ) ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected a string" ) ); } prop = get_property( self->object, prop_name ); if( prop ) { py_prop = Property_CreatePyObject( prop ); } else { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "couldn't find the property...." ) ); } return py_prop; } static PyObject *Object_addProperty( BPy_Object * self, PyObject * args ) { bProperty *prop = NULL; char *prop_name = NULL; PyObject *prop_data = Py_None; char *prop_type = NULL; short type = -1; BPy_Property *py_prop = NULL; int argslen = PyObject_Length( args ); if( argslen == 3 || argslen == 2 ) { if( !PyArg_ParseTuple ( args, "sO|s", &prop_name, &prop_data, &prop_type ) ) { return ( EXPP_ReturnPyObjError ( PyExc_AttributeError, "unable to get string, data, and optional string" ) ); } } else if( argslen == 1 ) { if( !PyArg_ParseTuple( args, "O!", &property_Type, &py_prop ) ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "unable to get Property" ) ); } if( py_prop->property != NULL ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "Property is already added to an object" ) ); } } else { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected 1,2 or 3 arguments" ) ); } //parse property type if( !py_prop ) { if( prop_type ) { if( BLI_streq( prop_type, "BOOL" ) ) type = PROP_BOOL; else if( BLI_streq( prop_type, "INT" ) ) type = PROP_INT; else if( BLI_streq( prop_type, "FLOAT" ) ) type = PROP_FLOAT; else if( BLI_streq( prop_type, "TIME" ) ) type = PROP_TIME; else if( BLI_streq( prop_type, "STRING" ) ) type = PROP_STRING; else return ( EXPP_ReturnPyObjError ( PyExc_RuntimeError, "BOOL, INT, FLOAT, TIME or STRING expected" ) ); } else { //use the default if( PyInt_Check( prop_data ) ) type = PROP_INT; else if( PyFloat_Check( prop_data ) ) type = PROP_FLOAT; else if( PyString_Check( prop_data ) ) type = PROP_STRING; } } else { type = py_prop->type; } //initialize a new bProperty of the specified type prop = new_property( type ); //parse data if( !py_prop ) { BLI_strncpy( prop->name, prop_name, 32 ); if( PyInt_Check( prop_data ) ) { *( ( int * ) &prop->data ) = ( int ) PyInt_AsLong( prop_data ); } else if( PyFloat_Check( prop_data ) ) { *( ( float * ) &prop->data ) = ( float ) PyFloat_AsDouble( prop_data ); } else if( PyString_Check( prop_data ) ) { BLI_strncpy( prop->poin, PyString_AsString( prop_data ), MAX_PROPSTRING ); } } else { py_prop->property = prop; if( !updateProperyData( py_prop ) ) { return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "Could not update property data - error" ) ); } } //add to property listbase for the object BLI_addtail( &self->object->prop, prop ); return EXPP_incr_ret( Py_None ); } static PyObject *Object_removeProperty( BPy_Object * self, PyObject * args ) { char *prop_name = NULL; BPy_Property *py_prop = NULL; bProperty *prop = NULL; // we have property and no optional arg if( !PyArg_ParseTuple( args, "O!", &property_Type, &py_prop ) ) { if( !PyArg_ParseTuple( args, "s", &prop_name ) ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected a Property or a string" ) ); } } //remove the link, free the data, and update the py struct if( py_prop ) { BLI_remlink( &self->object->prop, py_prop->property ); if( updatePyProperty( py_prop ) ) { free_property( py_prop->property ); py_prop->property = NULL; } } else { prop = get_property( self->object, prop_name ); if( prop ) { BLI_remlink( &self->object->prop, prop ); free_property( prop ); } } return EXPP_incr_ret( Py_None ); } static PyObject *Object_removeAllProperties( BPy_Object * self ) { free_properties( &self->object->prop ); return EXPP_incr_ret( Py_None ); } static PyObject *Object_copyAllPropertiesTo( BPy_Object * self, PyObject * args ) { PyObject *dest = Py_None; bProperty *prop = NULL; bProperty *propn = NULL; if( !PyArg_ParseTuple( args, "O!", &Object_Type, &dest ) ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected an Object" ) ); } //make a copy of all it's properties prop = self->object->prop.first; while( prop ) { propn = copy_property( prop ); BLI_addtail( &( ( BPy_Object * ) dest )->object->prop, propn ); prop = prop->next; } return EXPP_incr_ret( Py_None ); } /* obj.addScriptLink */ static PyObject *Object_addScriptLink( BPy_Object * self, PyObject * args ) { Object *obj = self->object; ScriptLink *slink = NULL; slink = &( obj )->scriptlink; return EXPP_addScriptLink( slink, args, 0 ); } /* obj.clearScriptLinks */ static PyObject *Object_clearScriptLinks( BPy_Object * self, PyObject * args ) { Object *obj = self->object; ScriptLink *slink = NULL; slink = &( obj )->scriptlink; return EXPP_clearScriptLinks( slink, args ); } /* obj.getScriptLinks */ static PyObject *Object_getScriptLinks( BPy_Object * self, PyObject * args ) { Object *obj = self->object; ScriptLink *slink = NULL; PyObject *ret = NULL; slink = &( obj )->scriptlink; ret = EXPP_getScriptLinks( slink, args, 0 ); if( ret ) return ret; else return NULL; } static PyObject *Object_getDupliVerts ( BPy_Object * self ) { if (self->object->transflag & OB_DUPLIVERTS) return EXPP_incr_ret_True (); else return EXPP_incr_ret_False(); } static PyObject *Object_setDupliVerts ( BPy_Object * self, PyObject * args ) { int setting= 0; if( !PyArg_ParseTuple( args, "i", &setting ) ) { return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected a string") ); } if (self && self->object) { if (setting) self->object->transflag |= OB_DUPLIVERTS; else self->object->transflag &= ~OB_DUPLIVERTS; } return Py_None; } /*****************************************************************************/ /* Function: Object_CreatePyObject */ /* Description: This function will create a new BlenObject from an existing */ /* Object structure. */ /*****************************************************************************/ PyObject *Object_CreatePyObject( struct Object * obj ) { BPy_Object *blen_object; if( !obj ) return EXPP_incr_ret( Py_None ); blen_object = ( BPy_Object * ) PyObject_NEW( BPy_Object, &Object_Type ); if( blen_object == NULL ) { return ( NULL ); } blen_object->object = obj; return ( ( PyObject * ) blen_object ); } /*****************************************************************************/ /* Function: Object_CheckPyObject */ /* Description: This function returns true when the given PyObject is of the */ /* type Object. Otherwise it will return false. */ /*****************************************************************************/ int Object_CheckPyObject( PyObject * py_obj ) { return ( py_obj->ob_type == &Object_Type ); } /*****************************************************************************/ /* Function: Object_FromPyObject */ /* Description: This function returns the Blender object from the given */ /* PyObject. */ /*****************************************************************************/ struct Object *Object_FromPyObject( PyObject * py_obj ) { BPy_Object *blen_obj; blen_obj = ( BPy_Object * ) py_obj; return ( blen_obj->object ); } /*****************************************************************************/ /* Description: Returns the object with the name specified by the argument */ /* name. Note that the calling function has to remove the first */ /* two characters of the object name. These two characters */ /* specify the type of the object (OB, ME, WO, ...) */ /* The function will return NULL when no object with the given */ /* name is found. */ /*****************************************************************************/ Object *GetObjectByName( char *name ) { Object *obj_iter; obj_iter = G.main->object.first; while( obj_iter ) { if( StringEqual( name, GetIdName( &( obj_iter->id ) ) ) ) { return ( obj_iter ); } obj_iter = obj_iter->id.next; } /* There is no object with the given name */ return ( NULL ); } /*****************************************************************************/ /* Function: Object_dealloc */ /* Description: This is a callback function for the BlenObject type. It is */ /* the destructor function. */ /*****************************************************************************/ static void Object_dealloc( BPy_Object * obj ) { PyObject_DEL( obj ); } /*****************************************************************************/ /* Function: Object_getAttr */ /* Description: This is a callback function for the BlenObject type. It is */ /* the function that retrieves any value from Blender and */ /* passes it to Python. */ /*****************************************************************************/ static PyObject *Object_getAttr( BPy_Object * obj, char *name ) { struct Object *object; object = obj->object; if( StringEqual( name, "LocX" ) ) return ( PyFloat_FromDouble( object->loc[0] ) ); if( StringEqual( name, "LocY" ) ) return ( PyFloat_FromDouble( object->loc[1] ) ); if( StringEqual( name, "LocZ" ) ) return ( PyFloat_FromDouble( object->loc[2] ) ); if( StringEqual( name, "loc" ) ) return ( Py_BuildValue( "fff", object->loc[0], object->loc[1], object->loc[2] ) ); if( StringEqual( name, "dLocX" ) ) return ( PyFloat_FromDouble( object->dloc[0] ) ); if( StringEqual( name, "dLocY" ) ) return ( PyFloat_FromDouble( object->dloc[1] ) ); if( StringEqual( name, "dLocZ" ) ) return ( PyFloat_FromDouble( object->dloc[2] ) ); if( StringEqual( name, "dloc" ) ) return ( Py_BuildValue ( "fff", object->dloc[0], object->dloc[1], object->dloc[2] ) ); if( StringEqual( name, "RotX" ) ) return ( PyFloat_FromDouble( object->rot[0] ) ); if( StringEqual( name, "RotY" ) ) return ( PyFloat_FromDouble( object->rot[1] ) ); if( StringEqual( name, "RotZ" ) ) return ( PyFloat_FromDouble( object->rot[2] ) ); if( StringEqual( name, "rot" ) ) return ( Py_BuildValue( "fff", object->rot[0], object->rot[1], object->rot[2] ) ); if( StringEqual( name, "dRotX" ) ) return ( PyFloat_FromDouble( object->drot[0] ) ); if( StringEqual( name, "dRotY" ) ) return ( PyFloat_FromDouble( object->drot[1] ) ); if( StringEqual( name, "dRotZ" ) ) return ( PyFloat_FromDouble( object->drot[2] ) ); if( StringEqual( name, "drot" ) ) return ( Py_BuildValue ( "fff", object->drot[0], object->drot[1], object->drot[2] ) ); if( StringEqual( name, "SizeX" ) ) return ( PyFloat_FromDouble( object->size[0] ) ); if( StringEqual( name, "SizeY" ) ) return ( PyFloat_FromDouble( object->size[1] ) ); if( StringEqual( name, "SizeZ" ) ) return ( PyFloat_FromDouble( object->size[2] ) ); if( StringEqual( name, "size" ) ) return ( Py_BuildValue ( "fff", object->size[0], object->size[1], object->size[2] ) ); if( StringEqual( name, "dSizeX" ) ) return ( PyFloat_FromDouble( object->dsize[0] ) ); if( StringEqual( name, "dSizeY" ) ) return ( PyFloat_FromDouble( object->dsize[1] ) ); if( StringEqual( name, "dSizeZ" ) ) return ( PyFloat_FromDouble( object->dsize[2] ) ); if( StringEqual( name, "dsize" ) ) return ( Py_BuildValue ( "fff", object->dsize[0], object->dsize[1], object->dsize[2] ) ); /* accept both Layer (old, for compatibility) and Layers */ if( strncmp( name, "Layer", 5 ) == 0) return ( PyInt_FromLong( object->lay ) ); /* Layers returns a bitmask, layers returns a list of integers */ if( StringEqual( name, "layers" ) ) { int layers, bit = 0, val = 0; PyObject *item = NULL, *laylist = PyList_New( 0 ); if( !laylist ) return ( EXPP_ReturnPyObjError( PyExc_MemoryError, "couldn't create pylist!" ) ); layers = object->lay; while( bit < 20 ) { val = 1 << bit; if( layers & val ) { item = Py_BuildValue( "i", bit + 1 ); PyList_Append( laylist, item ); Py_DECREF( item ); } bit++; } return laylist; } if( StringEqual( name, "parent" ) ) { if( object->parent ) return ( Object_CreatePyObject( object->parent ) ); else { Py_INCREF( Py_None ); return ( Py_None ); } } if( StringEqual( name, "parentbonename" ) ) { if( object->parent && object->parsubstr[0] ) return ( Py_BuildValue("s", object->parsubstr) ); else { Py_INCREF( Py_None ); return ( Py_None ); } } if( StringEqual( name, "track" ) ) return ( Object_CreatePyObject( object->track ) ); if( StringEqual( name, "data" ) ) { PyObject *getdata, *tuple = PyTuple_New(0); if (!tuple) return EXPP_ReturnPyObjError (PyExc_MemoryError, "couldn't create an empty tuple!"); getdata = Object_getData( obj, tuple, NULL ); Py_DECREF(tuple); return getdata; } if( StringEqual( name, "ipo" ) ) { if( object->ipo == NULL ) { /* There's no ipo linked to the object, return Py_None. */ Py_INCREF( Py_None ); return ( Py_None ); } return ( Ipo_CreatePyObject( object->ipo ) ); } if( StringEqual( name, "mat" ) || StringEqual( name, "matrix" ) ) return ( Object_getMatrix ( obj, Py_BuildValue( "(s)", "worldspace" ) ) ); if( StringEqual( name, "matrixWorld" ) ) return ( Object_getMatrix ( obj, Py_BuildValue( "(s)", "worldspace" ) ) ); if( StringEqual( name, "matrixLocal" ) ) return ( Object_getMatrix ( obj, Py_BuildValue( "(s)", "localspace" ) ) ); if( StringEqual( name, "colbits" ) ) return ( Py_BuildValue( "h", object->colbits ) ); if( StringEqual( name, "drawType" ) ) return ( Py_BuildValue( "b", object->dt ) ); if( StringEqual( name, "drawMode" ) ) return ( Py_BuildValue( "b", object->dtx ) ); if( StringEqual( name, "name" ) ) return ( Py_BuildValue( "s", object->id.name + 2 ) ); if( StringEqual( name, "sel" ) ) return ( Object_isSelected( obj ) ); if( StringEqual( name, "DupSta" ) ) return PyInt_FromLong( obj->object->dupsta ); if( StringEqual( name, "DupEnd" ) ) return PyInt_FromLong( obj->object->dupend ); if( StringEqual( name, "DupOn" ) ) return PyInt_FromLong( obj->object->dupon ); if( StringEqual( name, "DupOff" ) ) return PyInt_FromLong( obj->object->dupoff ); if( StringEqual( name, "Dupliframes" ) ){ if (obj->object->transflag & OB_DUPLIFRAMES) return EXPP_incr_ret_True(); else return EXPP_incr_ret_False(); } if (StringEqual (name, "oopsLoc")) { if (G.soops) { Oops *oops= G.soops->oops.first; while(oops) { if(oops->type==ID_OB) { if ((Object *)oops->id == object) { return (Py_BuildValue ("ff", oops->x, oops->y)); } } oops= oops->next; } } return EXPP_incr_ret( Py_None ); } /* not an attribute, search the methods table */ return Py_FindMethod( BPy_Object_methods, ( PyObject * ) obj, name ); } /*****************************************************************************/ /* Function: Object_setAttr */ /* Description: This is a callback function for the BlenObject type. It is */ /* the function that retrieves any value from Python and sets */ /* it accordingly in Blender. */ /*****************************************************************************/ static int Object_setAttr( BPy_Object * obj, char *name, PyObject * value ) { PyObject *valtuple, *result=NULL; struct Object *object; object = obj->object; /* Handle all properties which are Read Only */ if( StringEqual( name, "parent" ) ) return EXPP_ReturnIntError( PyExc_AttributeError, "Setting the parent is not allowed." ); if( StringEqual( name, "data" ) ) return EXPP_ReturnIntError( PyExc_AttributeError, "Setting the data is not allowed." ); if( StringEqual( name, "ipo" ) ) return EXPP_ReturnIntError( PyExc_AttributeError, "Setting the ipo is not allowed." ); if( StringEqual( name, "mat" ) ) return EXPP_ReturnIntError( PyExc_AttributeError, "Not allowed. Please use .setMatrix(matrix)" ); if( StringEqual( name, "matrix" ) ) return EXPP_ReturnIntError( PyExc_AttributeError, "Not allowed. Please use .setMatrix(matrix)" ); /* FIRST, do attributes that are diretly changed */ /* All the methods below modify the object so we set the recalc flag here. When we move to tp_getset, the individual settors will need to set the flag. */ object->recalc |= OB_RECALC_OB; if( StringEqual( name, "LocX" ) ) return ( !PyArg_Parse( value, "f", &( object->loc[0] ) ) ); if( StringEqual( name, "LocY" ) ) return ( !PyArg_Parse( value, "f", &( object->loc[1] ) ) ); if( StringEqual( name, "LocZ" ) ) return ( !PyArg_Parse( value, "f", &( object->loc[2] ) ) ); if( StringEqual( name, "dLocX" ) ) return ( !PyArg_Parse( value, "f", &( object->dloc[0] ) ) ); if( StringEqual( name, "dLocY" ) ) return ( !PyArg_Parse( value, "f", &( object->dloc[1] ) ) ); if( StringEqual( name, "dLocZ" ) ) return ( !PyArg_Parse( value, "f", &( object->dloc[2] ) ) ); if( StringEqual( name, "RotX" ) ) return ( !PyArg_Parse( value, "f", &( object->rot[0] ) ) ); if( StringEqual( name, "RotY" ) ) return ( !PyArg_Parse( value, "f", &( object->rot[1] ) ) ); if( StringEqual( name, "RotZ" ) ) return ( !PyArg_Parse( value, "f", &( object->rot[2] ) ) ); if( StringEqual( name, "dRotX" ) ) return ( !PyArg_Parse( value, "f", &( object->drot[0] ) ) ); if( StringEqual( name, "dRotY" ) ) return ( !PyArg_Parse( value, "f", &( object->drot[1] ) ) ); if( StringEqual( name, "dRotZ" ) ) return ( !PyArg_Parse( value, "f", &( object->drot[2] ) ) ); if( StringEqual( name, "drot" ) ) return ( !PyArg_ParseTuple( value, "fff", &( object->drot[0] ), &( object->drot[1] ), &( object->drot[2] ) ) ); if( StringEqual( name, "SizeX" ) ) return ( !PyArg_Parse( value, "f", &( object->size[0] ) ) ); if( StringEqual( name, "SizeY" ) ) return ( !PyArg_Parse( value, "f", &( object->size[1] ) ) ); if( StringEqual( name, "SizeZ" ) ) return ( !PyArg_Parse( value, "f", &( object->size[2] ) ) ); if( StringEqual( name, "size" ) ) return ( !PyArg_ParseTuple( value, "fff", &( object->size[0] ), &( object->size[1] ), &( object->size[2] ) ) ); if( StringEqual( name, "dSizeX" ) ) return ( !PyArg_Parse( value, "f", &( object->dsize[0] ) ) ); if( StringEqual( name, "dSizeY" ) ) return ( !PyArg_Parse( value, "f", &( object->dsize[1] ) ) ); if( StringEqual( name, "dSizeZ" ) ) return ( !PyArg_Parse( value, "f", &( object->dsize[2] ) ) ); if( StringEqual( name, "dsize" ) ) return ( !PyArg_ParseTuple ( value, "fff", &( object->dsize[0] ), &( object->dsize[1] ), &( object->dsize[2] ) ) ); if( StringEqual( name, "DupSta" ) ) return ( !PyArg_Parse( value, "h", &( object->dupsta ) ) ); if( StringEqual( name, "DupEnd" ) ) return ( !PyArg_Parse( value, "h", &( object->dupend ) ) ); if( StringEqual( name, "DupOn" ) ) return ( !PyArg_Parse( value, "h", &( object->dupon ) ) ); if( StringEqual( name, "DupOff" ) ) return ( !PyArg_Parse( value, "h", &( object->dupoff ) ) ); if( StringEqual( name, "Dupliframes" ) ) { short dupli; if ( !PyArg_Parse( value, "h", &dupli ) ) return -1; if (dupli) obj->object->transflag |= OB_DUPLIFRAMES; else obj->object->transflag &= ~OB_DUPLIFRAMES; return 0; } if( StringEqual( name, "colbits" ) ) return ( !PyArg_Parse( value, "h", &( object->colbits ) ) ); /* accept both Layer (for compatibility) and Layers */ if( strncmp( name, "Layer", 5 ) == 0 ) { /* usage note: caller of this func needs to do a Blender.Redraw(-1) to update and redraw the interface */ Base *base; int newLayer; int local; if( ! PyArg_Parse( value, "i", &newLayer ) ) { return EXPP_ReturnIntError( PyExc_AttributeError, "expected int as bitmask" ); } /* uppper 2 nibbles are for local view */ newLayer &= 0x00FFFFFF; if( newLayer == 0 ) { return EXPP_ReturnIntError( PyExc_AttributeError, "bitmask must have from 1 up to 20 bits set"); } /* update any bases pointing to our object */ base = FIRSTBASE; /* first base in current scene */ while( base ){ if( base->object == obj->object ) { local = base->lay &= 0xFF000000; base->lay = local | newLayer; object->lay = base->lay; } base = base->next; } countall( ); return ( 0 ); } if( StringEqual( name, "layers" ) ) { /* usage note: caller of this func needs to do a Blender.Redraw(-1) to update and redraw the interface */ Base *base; int layers = 0, len_list = 0; int local, i, val; PyObject *list = NULL, *item = NULL; if( !PyArg_Parse( value, "O!", &PyList_Type, &list ) ) return EXPP_ReturnIntError( PyExc_TypeError, "expected a list of integers" ); len_list = PyList_Size(list); if (len_list == 0) return EXPP_ReturnIntError( PyExc_AttributeError, "list can't be empty, at least one layer must be set" ); for( i = 0; i < len_list; i++ ) { item = PyList_GetItem( list, i ); if( !PyInt_Check( item ) ) return EXPP_ReturnIntError ( PyExc_AttributeError, "list must contain only integer numbers" ); val = ( int ) PyInt_AsLong( item ); if( val < 1 || val > 20 ) return EXPP_ReturnIntError ( PyExc_AttributeError, "layer values must be in the range [1, 20]" ); layers |= 1 << ( val - 1 ); } /* update any bases pointing to our object */ base = FIRSTBASE; /* first base in current scene */ while( base ){ if( base->object == obj->object ) { local = base->lay &= 0xFF000000; base->lay = local | layers; object->lay = base->lay; } base = base->next; } countall(); return ( 0 ); } if (StringEqual (name, "oopsLoc")) { if (G.soops) { Oops *oops= G.soops->oops.first; while(oops) { if(oops->type==ID_OB) { if ((Object *)oops->id == object) { return (!PyArg_ParseTuple (value, "ff", &(oops->x),&(oops->y))); } } oops= oops->next; } } return 0; } /* SECOND, handle all the attributes that passes the value as a tuple to another function */ /* Put the value(s) in a tuple. For some variables, we want to */ /* pass the values to a function, and these functions only accept */ /* PyTuples. */ valtuple = Py_BuildValue( "(O)", value ); if( !valtuple ) { return EXPP_ReturnIntError( PyExc_MemoryError, "Object_setAttr: couldn't create PyTuple" ); } /* Call the setFunctions to handle it */ if( StringEqual( name, "loc" ) ) result = Object_setLocation( obj, valtuple ); else if( StringEqual( name, "dloc" ) ) result = Object_setDeltaLocation( obj, valtuple ); else if( StringEqual( name, "rot" ) ) result = Object_setEuler( obj, valtuple ); else if( StringEqual( name, "track" ) ) result = Object_makeTrack( obj, valtuple ); else if( StringEqual( name, "drawType" ) ) result = Object_setDrawType( obj, valtuple ); else if( StringEqual( name, "drawMode" ) ) result = Object_setDrawMode( obj, valtuple ); else if( StringEqual( name, "name" ) ) result = Object_setName( obj, valtuple ); else if( StringEqual( name, "sel" ) ) result = Object_Select( obj, valtuple ); else { /* if it turns out here, it's not an attribute*/ Py_DECREF(valtuple); return EXPP_ReturnIntError( PyExc_KeyError, "attribute not found" ); } /* valtuple won't be returned to the caller, so we need to DECREF it */ Py_DECREF(valtuple); if( result != Py_None ) return -1; /* error return */ /* Py_None was incref'ed by the called Scene_set* function. We probably * don't need to decref Py_None (!), but since Python/C API manual tells us * to treat it like any other PyObject regarding ref counting ... */ Py_DECREF( Py_None ); return 0; /* normal return */ } /*****************************************************************************/ /* Function: Object_compare */ /* Description: This is a callback function for the BPy_Object type. It */ /* compares two Object_Type objects. Only the "==" and "!=" */ /* comparisons are meaninful. Returns 0 for equality and -1 if */ /* they don't point to the same Blender Object struct. */ /* In Python it becomes 1 if they are equal, 0 otherwise. */ /*****************************************************************************/ static int Object_compare( BPy_Object * a, BPy_Object * b ) { Object *pa = a->object, *pb = b->object; return ( pa == pb ) ? 0 : -1; } /*****************************************************************************/ /* Function: Object_repr */ /* Description: This is a callback function for the BPy_Object type. It */ /* builds a meaninful string to represent object objects. */ /*****************************************************************************/ static PyObject *Object_repr( BPy_Object * self ) { return PyString_FromFormat( "[Object \"%s\"]", self->object->id.name + 2 ); } PyObject *Object_getPIStrength( BPy_Object * self ) { PyObject *attr; if(!self->object->pd){ if(!setupPI(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "particle deflection could not be accessed (null pointer)" ) ); } attr = PyFloat_FromDouble( ( double ) self->object->pd->f_strength ); if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object->pd->f_strength attribute" ) ); } PyObject *Object_setPIStrength( BPy_Object * self, PyObject * args ) { float value; if(!self->object->pd){ if(!setupPI(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "particle deflection could not be accessed (null pointer)" ) ); } if( !PyArg_ParseTuple( args, "f", &value ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected float argument" ) ); if(value > 1000.0f || value < -1000.0f) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "acceptable values are between 1000.0 and -1000.0" ) ); self->object->pd->f_strength = value; return EXPP_incr_ret( Py_None ); } PyObject *Object_getPIFalloff( BPy_Object * self ) { PyObject *attr; if(!self->object->pd){ if(!setupPI(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "particle deflection could not be accessed (null pointer)" ) ); } attr = PyFloat_FromDouble( ( double ) self->object->pd->f_power ); if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object->pd->f_power attribute" ) ); } PyObject *Object_setPIFalloff( BPy_Object * self, PyObject * args ) { float value; if(!self->object->pd){ if(!setupPI(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "particle deflection could not be accessed (null pointer)" ) ); } if( !PyArg_ParseTuple( args, "f", &value ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected float argument" ) ); if(value > 10.0f || value < 0.0f) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "acceptable values are between 10.0 and 0.0" ) ); self->object->pd->f_power = value; return EXPP_incr_ret( Py_None ); } PyObject *Object_getPIMaxDist( BPy_Object * self ) { PyObject *attr; if(!self->object->pd){ if(!setupPI(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "particle deflection could not be accessed (null pointer)" ) ); } attr = PyFloat_FromDouble( ( double ) self->object->pd->maxdist ); if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object->pd->f_maxdist attribute" ) ); } PyObject *Object_setPIMaxDist( BPy_Object * self, PyObject * args ) { float value; if(!self->object->pd){ if(!setupPI(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "particle deflection could not be accessed (null pointer)" ) ); } if( !PyArg_ParseTuple( args, "f", &value ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected float argument" ) ); if(value > 1000.0f || value < 0.0f) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "acceptable values are between 1000.0 and 0.0" ) ); self->object->pd->maxdist = value; return EXPP_incr_ret( Py_None ); } PyObject *Object_getPIUseMaxDist( BPy_Object * self ) { PyObject *attr; if(!self->object->pd){ if(!setupPI(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "particle deflection could not be accessed (null pointer)" ) ); } attr = PyInt_FromLong( ( long ) self->object->pd->flag ); if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object->pd->flag attribute" ) ); } PyObject *Object_setPIUseMaxDist( BPy_Object * self, PyObject * args ) { int value; if(!self->object->pd){ if(!setupPI(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "particle deflection could not be accessed (null pointer)" ) ); } if( !PyArg_ParseTuple( args, "i", &( value ) ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected int argument" ) ); self->object->pd->flag = (short)value; return EXPP_incr_ret( Py_None ); } PyObject *Object_getPIType( BPy_Object * self ) { PyObject *attr; if(!self->object->pd){ if(!setupPI(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "particle deflection could not be accessed (null pointer)" ) ); } attr = PyInt_FromLong( ( long ) self->object->pd->forcefield ); if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object->pd->forcefield attribute" ) ); } PyObject *Object_setPIType( BPy_Object * self, PyObject * args ) { int value; if(!self->object->pd){ if(!setupPI(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "particle deflection could not be accessed (null pointer)" ) ); } if( !PyArg_ParseTuple( args, "i", &( value ) ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected int argument" ) ); self->object->pd->forcefield = (short)value; return EXPP_incr_ret( Py_None ); } PyObject *Object_getPIPerm( BPy_Object * self ) { PyObject *attr; if(!self->object->pd){ if(!setupPI(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "particle deflection could not be accessed (null pointer)" ) ); } attr = PyFloat_FromDouble( ( double ) self->object->pd->pdef_perm ); if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object->pd->pdef_perm attribute" ) ); } PyObject *Object_setPIPerm( BPy_Object * self, PyObject * args ) { float value; if(!self->object->pd){ if(!setupPI(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "particle deflection could not be accessed (null pointer)" ) ); } if( !PyArg_ParseTuple( args, "f", &value ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected float argument" ) ); if(value > 1.0f || value < 0.0f) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "acceptable values are between 1.0 and 0.0" ) ); self->object->pd->pdef_perm = value; return EXPP_incr_ret( Py_None ); } PyObject *Object_getPIRandomDamp( BPy_Object * self ) { PyObject *attr; if(!self->object->pd){ if(!setupPI(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "particle deflection could not be accessed (null pointer)" ) ); } attr = PyFloat_FromDouble( ( double ) self->object->pd->pdef_rdamp ); if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object->pd->pdef_rdamp attribute" ) ); } PyObject *Object_setPIRandomDamp( BPy_Object * self, PyObject * args ) { float value; if(!self->object->pd){ if(!setupPI(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "particle deflection could not be accessed (null pointer)" ) ); } if( !PyArg_ParseTuple( args, "f", &value ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected float argument" ) ); if(value > 1.0f || value < 0.0f) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "acceptable values are between 1.0 and 0.0" ) ); self->object->pd->pdef_rdamp = value; return EXPP_incr_ret( Py_None ); } PyObject *Object_getPISurfaceDamp( BPy_Object * self ) { PyObject *attr; if(!self->object->pd){ if(!setupPI(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "particle deflection could not be accessed (null pointer)" ) ); } attr = PyFloat_FromDouble( ( double ) self->object->pd->pdef_damp ); if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object->pd->pdef_rdamp attribute" ) ); } PyObject *Object_setPISurfaceDamp( BPy_Object * self, PyObject * args ) { float value; if(!self->object->pd){ if(!setupPI(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "particle deflection could not be accessed (null pointer)" ) ); } if( !PyArg_ParseTuple( args, "f", &value ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected float argument" ) ); if(value > 1.0f || value < 0.0f) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "acceptable values are between 1.0 and 0.0" ) ); self->object->pd->pdef_damp = value; return EXPP_incr_ret( Py_None ); } PyObject *Object_getPIDeflection( BPy_Object * self ) { PyObject *attr; if(!self->object->pd){ if(!setupPI(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "particle deflection could not be accessed (null pointer)" ) ); } attr = PyInt_FromLong( ( long ) self->object->pd->deflect ); if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object->pd->deflect attribute" ) ); } PyObject *Object_setPIDeflection( BPy_Object * self, PyObject * args ) { int value; if(!self->object->pd){ if(!setupPI(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "particle deflection could not be accessed (null pointer)" ) ); } if( !PyArg_ParseTuple( args, "i", &( value ) ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected int argument" ) ); self->object->pd->deflect = (short)value; return EXPP_incr_ret( Py_None ); } /* SOFTBODY FUNCTIONS */ PyObject *Object_isSB(BPy_Object *self) { if (self->object->soft) return EXPP_incr_ret_True(); else return EXPP_incr_ret_False(); } PyObject *Object_getSBMass( BPy_Object * self ) { PyObject *attr; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } attr = PyFloat_FromDouble( ( double ) self->object->soft->nodemass ); if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object->soft->nodemass attribute" ) ); } PyObject *Object_setSBMass( BPy_Object * self, PyObject * args ) { float value; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } if( !PyArg_ParseTuple( args, "f", &value ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected float argument" ) ); if(value > 50.0f || value < 0.0f) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "acceptable values are between 0.0 and 50.0" ) ); self->object->soft->nodemass = value; return EXPP_incr_ret( Py_None ); } PyObject *Object_getSBGravity( BPy_Object * self ) { PyObject *attr; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } attr = PyFloat_FromDouble( ( double ) self->object->soft->grav ); if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object->soft->grav attribute" ) ); } PyObject *Object_setSBGravity( BPy_Object * self, PyObject * args ) { float value; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } if( !PyArg_ParseTuple( args, "f", &value ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected float argument" ) ); if(value > 10.0f || value < 0.0f) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "acceptable values are between 0.0 and 10.0" ) ); self->object->soft->grav = value; return EXPP_incr_ret( Py_None ); } PyObject *Object_getSBFriction( BPy_Object * self ) { PyObject *attr; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } attr = PyFloat_FromDouble( ( double ) self->object->soft->mediafrict ); if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object->soft->mediafrict attribute" ) ); } PyObject *Object_setSBFriction( BPy_Object * self, PyObject * args ) { float value; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } if( !PyArg_ParseTuple( args, "f", &value ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected float argument" ) ); if(value > 10.0f || value < 0.0f) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "acceptable values are between 0.0 and 10.0" ) ); self->object->soft->mediafrict = value; return EXPP_incr_ret( Py_None ); } PyObject *Object_getSBErrorLimit( BPy_Object * self ) { PyObject *attr; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } attr = PyFloat_FromDouble( ( double ) self->object->soft->rklimit ); if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object->soft->rklimit attribute" ) ); } PyObject *Object_setSBErrorLimit( BPy_Object * self, PyObject * args ) { float value; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } if( !PyArg_ParseTuple( args, "f", &value ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected float argument" ) ); if(value > 1.0f || value < 0.01f) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "acceptable values are between 0.01 and 1.0" ) ); self->object->soft->rklimit = value; return EXPP_incr_ret( Py_None ); } PyObject *Object_getSBGoalSpring( BPy_Object * self ) { PyObject *attr; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } attr = PyFloat_FromDouble( ( double ) self->object->soft->goalspring ); if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object->soft->goalspring attribute" ) ); } PyObject *Object_setSBGoalSpring( BPy_Object * self, PyObject * args ) { float value; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer) " ) ); } if( !PyArg_ParseTuple( args, "f", &value ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected float argument" ) ); if(value > 0.999f || value < 0.00f) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "acceptable values are between 0.00 and 0.999" ) ); self->object->soft->goalspring = value; return EXPP_incr_ret( Py_None ); } PyObject *Object_getSBGoalFriction( BPy_Object * self ) { PyObject *attr; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } attr = PyFloat_FromDouble( ( double ) self->object->soft->goalfrict ); if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object->soft->goalfrict attribute" ) ); } PyObject *Object_setSBGoalFriction( BPy_Object * self, PyObject * args ) { float value; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } if( !PyArg_ParseTuple( args, "f", &value ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected float argument" ) ); if(value > 10.0f || value < 0.00f) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "acceptable values are between 0.00 and 10.0" ) ); self->object->soft->goalfrict = value; return EXPP_incr_ret( Py_None ); } PyObject *Object_getSBMinGoal( BPy_Object * self ) { PyObject *attr; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } attr = PyFloat_FromDouble( ( double ) self->object->soft->mingoal ); if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object->soft->mingoal attribute" ) ); } PyObject *Object_setSBMinGoal( BPy_Object * self, PyObject * args ) { float value; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } if( !PyArg_ParseTuple( args, "f", &value ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected float argument" ) ); if(value > 1.0f || value < 0.00f) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "acceptable values are between 0.00 and 1.0" ) ); self->object->soft->mingoal = value; return EXPP_incr_ret( Py_None ); } PyObject *Object_getSBMaxGoal( BPy_Object * self ) { PyObject *attr; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } attr = PyFloat_FromDouble( ( double ) self->object->soft->maxgoal ); if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object->soft->maxgoal attribute" ) ); } PyObject *Object_setSBMaxGoal( BPy_Object * self, PyObject * args ) { float value; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } if( !PyArg_ParseTuple( args, "f", &value ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected float argument" ) ); if(value > 1.0f || value < 0.00f) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "acceptable values are between 0.00 and 1.0" ) ); self->object->soft->maxgoal = value; return EXPP_incr_ret( Py_None ); } PyObject *Object_getSBInnerSpring( BPy_Object * self ) { PyObject *attr; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } attr = PyFloat_FromDouble( ( double ) self->object->soft->inspring ); if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object->soft->inspring attribute" ) ); } PyObject *Object_setSBInnerSpring( BPy_Object * self, PyObject * args ) { float value; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } if( !PyArg_ParseTuple( args, "f", &value ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected float argument" ) ); if(value > 0.999f || value < 0.00f) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "acceptable values are between 0.00 and 0.999" ) ); self->object->soft->inspring = value; return EXPP_incr_ret( Py_None ); } PyObject *Object_getSBInnerSpringFriction( BPy_Object * self ) { PyObject *attr; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } attr = PyFloat_FromDouble( ( double ) self->object->soft->infrict ); if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object->soft->infrict attribute" ) ); } PyObject *Object_setSBInnerSpringFriction( BPy_Object * self, PyObject * args ) { float value; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } if( !PyArg_ParseTuple( args, "f", &value ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected float argument" ) ); if(value > 10.0f || value < 0.00f) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "acceptable values are between 0.00 and 10.0" ) ); self->object->soft->infrict = value; return EXPP_incr_ret( Py_None ); } PyObject *Object_getSBDefaultGoal( BPy_Object * self ) { PyObject *attr; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } attr = PyFloat_FromDouble( ( double ) self->object->soft->defgoal ); if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object->soft->defgoal attribute" ) ); } PyObject *Object_setSBDefaultGoal( BPy_Object * self, PyObject * args ) { float value; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } if( !PyArg_ParseTuple( args, "f", &value ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected float argument" ) ); if(value > 1.0f || value < 0.00f) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "acceptable values are between 0.00 and 1.0" ) ); self->object->soft->defgoal = value; return EXPP_incr_ret( Py_None ); } PyObject *Object_getSBUseGoal( BPy_Object * self ) { /*short flag = self->object->softflag;*/ PyObject *attr = NULL; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } if(self->object->softflag & OB_SB_GOAL){ attr = PyInt_FromLong(1); } else{ attr = PyInt_FromLong(0); } if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object->softflag attribute" ) ); } PyObject *Object_setSBUseGoal( BPy_Object * self, PyObject * args ) { short value; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } if( !PyArg_ParseTuple( args, "h", &value ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected integer argument" ) ); if(value){ self->object->softflag |= OB_SB_GOAL; } else{ self->object->softflag &= ~OB_SB_GOAL; } return EXPP_incr_ret( Py_None ); } PyObject *Object_getSBUseEdges( BPy_Object * self ) { /*short flag = self->object->softflag;*/ PyObject *attr = NULL; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } if(self->object->softflag & OB_SB_EDGES){ attr = PyInt_FromLong(1); } else{ attr = PyInt_FromLong(0); } if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object->softflag attribute" ) ); } PyObject *Object_setSBUseEdges( BPy_Object * self, PyObject * args ) { short value; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } if( !PyArg_ParseTuple( args, "h", &value ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected integer argument" ) ); if(value){ self->object->softflag |= OB_SB_EDGES; } else{ self->object->softflag &= ~OB_SB_EDGES; } return EXPP_incr_ret( Py_None ); } PyObject *Object_getSBStiffQuads( BPy_Object * self ) { /*short flag = self->object->softflag;*/ PyObject *attr = NULL; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } if(self->object->softflag & OB_SB_QUADS){ attr = PyInt_FromLong(1); } else{ attr = PyInt_FromLong(0); } if( attr ) return attr; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Object->softflag attribute" ) ); } PyObject *Object_setSBStiffQuads( BPy_Object * self, PyObject * args ) { short value; if(!self->object->soft){ if(!setupSB(self->object)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "softbody could not be accessed (null pointer)" ) ); } if( !PyArg_ParseTuple( args, "h", &value ) ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected integer argument" ) ); if(value){ self->object->softflag |= OB_SB_QUADS; } else{ self->object->softflag &= ~OB_SB_QUADS; } return EXPP_incr_ret( Py_None ); } int setupSB(Object* ob){ ob->soft= sbNew(); ob->softflag |= OB_SB_GOAL|OB_SB_EDGES; if(ob->soft){ ob->soft->nodemass = 1.0f; ob->soft->grav = 0.0f; ob->soft->mediafrict = 0.5f; ob->soft->rklimit = 0.1f; ob->soft->goalspring = 0.5f; ob->soft->goalfrict = 0.0f; ob->soft->mingoal = 0.0f; ob->soft->maxgoal = 1.0f; ob->soft->inspring = 0.5f; ob->soft->infrict = 0.5f; ob->soft->defgoal = 0.7f; return 1; } else { return 0; } } int setupPI(Object* ob){ if(ob->pd==NULL) { ob->pd= MEM_callocN(sizeof(PartDeflect), "PartDeflect"); /* and if needed, init here */ } if(ob->pd){ ob->pd->deflect =0; ob->pd->forcefield =0; ob->pd->flag =0; ob->pd->pdef_damp =0; ob->pd->pdef_rdamp =0; ob->pd->pdef_perm =0; ob->pd->f_strength =0; ob->pd->f_power =0; ob->pd->maxdist =0; return 1; } else{ return 0; } } /* * scan list of Objects looking for matching obdata. * if found, set OB_RECALC_DATA flag. * call this from a bpy type update() method. */ void Object_updateDag( void *data ) { Object *ob; if( !data) return; for( ob= G.main->object.first; ob; ob= ob->id.next){ if( ob->data == data){ ob->recalc |= OB_RECALC_DATA; } } }