2456 lines
		
	
	
		
			73 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2456 lines
		
	
	
		
			73 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* 
 | |
|  * $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
 | |
|  *
 | |
|  * ***** END GPL/BL DUAL LICENSE BLOCK *****
 | |
| */
 | |
| 
 | |
| #include "Object.h"
 | |
| #include "NLA.h"
 | |
| #include "logic.h"
 | |
| #include <blendef.h>
 | |
| #include <DNA_scene_types.h>
 | |
| #include <DNA_mesh_types.h>
 | |
| #include <DNA_curve_types.h>
 | |
| #include <DNA_property_types.h>
 | |
| #include <BSE_edit.h>
 | |
| #include <BKE_property.h>
 | |
| #include <BKE_mball.h>
 | |
| #include <BIF_editview.h>
 | |
| 
 | |
| #include "Ipo.h"
 | |
| #include "Lattice.h"
 | |
| #include "modules.h"
 | |
| 
 | |
| 
 | |
| /*****************************************************************************/
 | |
| /* 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 );
 | |
| PyObject *M_Object_get( PyObject * self, PyObject * args );
 | |
| static PyObject *M_Object_GetSelected( PyObject * self, PyObject * args );
 | |
| static PyObject *M_Object_getSelected( PyObject * self, PyObject * args );
 | |
| 
 | |
| /*****************************************************************************/
 | |
| /* 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},
 | |
| 	{"get", ( PyCFunction ) M_Object_get, METH_VARARGS,
 | |
| 	 M_Object_Get_doc},
 | |
| 	{"GetSelected", ( PyCFunction ) M_Object_GetSelected, METH_VARARGS,
 | |
| 	 M_Object_GetSelected_doc},
 | |
| 	{"getSelected", ( PyCFunction ) M_Object_getSelected, METH_VARARGS,
 | |
| 	 M_Object_GetSelected_doc},
 | |
| 	{NULL, NULL, 0, NULL}
 | |
| };
 | |
| 
 | |
| /*****************************************************************************/
 | |
| /* Python BPy_Object methods declarations:				   */
 | |
| /*****************************************************************************/
 | |
| 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 );
 | |
| 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_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_materialUsage( BPy_Object * self, PyObject * args );
 | |
| 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_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 );
 | |
| 
 | |
| /*****************************************************************************/
 | |
| /* 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_NOARGS,
 | |
| 	 "Returns the datablock object containing the object's data, e.g. Mesh"},
 | |
| 	{"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 = 'localspace') - Returns the object matrix.\n\
 | |
| (str = 'localspace') - the wanted matrix: worldspace, localspace (default)\n\
 | |
| or oldlocal (not updated, it was the only choice before Blender 2.34)."},
 | |
| 	{"getName", ( PyCFunction ) Object_getName, METH_NOARGS,
 | |
| 	 "Returns the name of the object"},
 | |
| 	{"getParent", ( PyCFunction ) Object_getParent, METH_NOARGS,
 | |
| 	 "Returns the object's parent object"},
 | |
| 	{"getSize", ( PyCFunction ) Object_getSize, METH_VARARGS,
 | |
| 	 "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"},
 | |
| 	{"getBoundBox", ( PyCFunction ) Object_getBoundBox, METH_NOARGS,
 | |
| 	 "Returns the object's bounding box"},
 | |
| 	{"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."},
 | |
| 	{"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"},
 | |
| 	{"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 or Redraw."},
 | |
| 	{"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 or Redraw."},
 | |
| 	{"clearScriptLinks", ( PyCFunction ) Object_clearScriptLinks,
 | |
| 	 METH_NOARGS,
 | |
| 	 "() - Delete all scriptlinks from this object."},
 | |
| 	{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 */
 | |
| };
 | |
| 
 | |
| /*****************************************************************************/
 | |
| /* 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, "Ika") == 0)		type = OB_IKA; */
 | |
| 	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 = 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.4;
 | |
| 	object->damping = 0.04;
 | |
| 	object->rdamping = 0.1;
 | |
| 	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_get					*/
 | |
| /* Python equivalent:	  Blender.Object.get			*/
 | |
| /*****************************************************************************/
 | |
| PyObject *M_Object_get( PyObject * self, PyObject * args )
 | |
| {
 | |
| 	PyErr_Warn( PyExc_DeprecationWarning,
 | |
| 		    "The Object.get() function will be removed in Blender 2.29\n"
 | |
| 		    "Please update the script to use Object.Get" );
 | |
| 	return ( M_Object_Get( self, args ) );
 | |
| }
 | |
| 
 | |
| /*****************************************************************************/
 | |
| /* 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:	  M_Object_getSelected					*/
 | |
| /* Python equivalent:	  Blender.Object.getSelected	       	        */
 | |
| /*****************************************************************************/
 | |
| static PyObject *M_Object_getSelected( PyObject * self, PyObject * args )
 | |
| {
 | |
| 	PyErr_Warn( PyExc_DeprecationWarning,
 | |
| 		    "The Object.getSelected() function will be removed in "
 | |
| 		    "Blender 2.29\n"
 | |
| 		    "Please update the script to use Object.GetSelected" );
 | |
| 	return ( M_Object_GetSelected( self, args ) );
 | |
| }
 | |
| 
 | |
| /*****************************************************************************/
 | |
| /* 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 );
 | |
| 
 | |
| 	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;
 | |
| 
 | |
| 		Py_INCREF( Py_True );
 | |
| 		return Py_True;
 | |
| 	}
 | |
| 
 | |
| 	Py_INCREF( Py_False );	/* no ipo found */
 | |
| 	return Py_False;
 | |
| }
 | |
| 
 | |
| 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 ) {
 | |
| 		sort_baselist( 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 ) {
 | |
| 		sort_baselist( 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_IKA:
 | |
| 		   object->data = add_ika();
 | |
| 		   object->dt = OB_WIRE;
 | |
| 		   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 *data_object;
 | |
| 	Object *object = self->object;
 | |
| 
 | |
| 	/* 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 );
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	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:
 | |
| 		data_object = NMesh_CreatePyObject( object->data, object );
 | |
| 		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 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 ) {
 | |
| 				Py_INCREF( Py_True );
 | |
| 				return Py_True;
 | |
| 			} else {
 | |
| 				Py_INCREF( Py_False );
 | |
| 				return Py_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 )
 | |
| {
 | |
| 	EulerObject *eul;
 | |
| 
 | |
| 	eul = ( EulerObject * ) newEulerObject( NULL );
 | |
| 	eul->eul[0] = self->object->rot[0];
 | |
| 	eul->eul[1] = self->object->rot[1];
 | |
| 	eul->eul[2] = self->object->rot[2];
 | |
| 
 | |
| 	return ( PyObject * ) eul;
 | |
| 
 | |
| }
 | |
| 
 | |
| static PyObject *Object_getInverseMatrix( BPy_Object * self )
 | |
| {
 | |
| 	MatrixObject *inverse =
 | |
| 		( MatrixObject * ) newMatrixObject( NULL, 4, 4 );
 | |
| 	Mat4Invert( *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 )
 | |
| {
 | |
| 	PyObject *matrix;
 | |
| 	char *space = "localspace";	/* default to local */
 | |
| 
 | |
| 	if( !PyArg_ParseTuple( args, "|s", &space ) ) {
 | |
| 		return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
 | |
| 						"expected a string or nothing" ) );
 | |
| 	}
 | |
| 	//new matrix
 | |
| 	matrix = newMatrixObject( NULL, 4, 4 );
 | |
| 
 | |
| 	if( BLI_streq( space, "worldspace" ) ) {	/* Worldspace matrix */
 | |
| 		disable_where_script( 1 );
 | |
| 		where_is_object( self->object );
 | |
| 		disable_where_script( 0 );
 | |
| 		Mat4CpyMat4( *( ( MatrixObject * ) matrix )->matrix,
 | |
| 			     self->object->obmat );
 | |
| 	} else if( BLI_streq( space, "localspace" ) ) {	/* Localspace matrix */
 | |
| 		object_to_mat4( self->object,
 | |
| 				*( ( MatrixObject * ) matrix )->matrix );
 | |
| 	} else if( BLI_streq( space, "oldlocal" ) ) {	/* old behavior, prior to 2.34 */
 | |
| 		Mat4CpyMat4( *( ( MatrixObject * ) matrix )->matrix,
 | |
| 			     self->object->obmat );
 | |
| 	} else {
 | |
| 		return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
 | |
| 						"wrong parameter, expected nothing or either 'localspace' (default),\n\
 | |
| 'worldspace' or 'oldlocal'" ) );
 | |
| 	}
 | |
| 	return matrix;
 | |
| }
 | |
| 
 | |
| 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_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_IKA:
 | |
| 		return ( Py_BuildValue( "s", "Ika" ) );
 | |
| 	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;
 | |
| 			if( !me->bb )
 | |
| 				tex_space_mesh( me );
 | |
| 			vec = ( float * ) me->bb->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 );
 | |
| 				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 );
 | |
| 			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 );
 | |
| 
 | |
| 	makeDispList( ob );
 | |
| 
 | |
| 	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 );
 | |
| 	if( Camera_CheckPyObject( py_data ) )
 | |
| 		data = ( void * ) Camera_FromPyObject( py_data );
 | |
| 	if( Lamp_CheckPyObject( py_data ) )
 | |
| 		data = ( void * ) Lamp_FromPyObject( py_data );
 | |
| 	if( Curve_CheckPyObject( py_data ) )
 | |
| 		data = ( void * ) Curve_FromPyObject( py_data );
 | |
| 	if( NMesh_CheckPyObject( py_data ) )
 | |
| 		data = ( void * ) Mesh_FromPyObject( py_data, self->object );
 | |
| 	if( Lattice_CheckPyObject( py_data ) )
 | |
| 		data = ( void * ) Lattice_FromPyObject( py_data );
 | |
| 	if( Metaball_CheckPyObject( py_data ) )
 | |
| 		data = ( void * ) Metaball_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 ) {
 | |
| 			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 );
 | |
| 	}
 | |
| 
 | |
| 	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_makeParent( BPy_Object * self, PyObject * args )
 | |
| {
 | |
| 	PyObject *list;
 | |
| 	PyObject *py_child;
 | |
| 	//BPy_Object      * py_obj_child; unused
 | |
| 	Object *child;
 | |
| 	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" ) );
 | |
| 	}
 | |
| 
 | |
| 	/* Check if the PyObject passed in list is a Blender object. */
 | |
| 	for( i = 0; i < PySequence_Length( list ); i++ ) {
 | |
| 		child = NULL;
 | |
| 		py_child = PySequence_GetItem( list, i );
 | |
| 		if( Object_CheckPyObject( py_child ) )
 | |
| 			child = ( Object * ) Object_FromPyObject( py_child );
 | |
| 
 | |
| 		if( child == NULL ) {
 | |
| 			return ( EXPP_ReturnPyObjError( PyExc_TypeError,
 | |
| 							"Object Type expected" ) );
 | |
| 		}
 | |
| 
 | |
| 		parent = ( Object * ) self->object;
 | |
| 		if( test_parent_loop( parent, child ) ) {
 | |
| 			return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
 | |
| 							"parenting loop detected - parenting failed" ) );
 | |
| 		}
 | |
| 		child->partype = PAROBJECT;
 | |
| 		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, parent->obmat );
 | |
| 		}
 | |
| 
 | |
| 		if( !fast ) {
 | |
| 			sort_baselist( G.scene );
 | |
| 		}
 | |
| 		// We don't need the child object anymore.
 | |
| 		//Py_DECREF ((PyObject *) child);
 | |
| 	}
 | |
| 	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;
 | |
| 	float rot2;
 | |
| 	float rot3;
 | |
| 	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;
 | |
| }
 | |
| 
 | |
| 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;
 | |
| 
 | |
| 	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", &list ) ) {
 | |
| 		return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
 | |
| 						"expected a list of materials as argument" ) );
 | |
| 	}
 | |
| 
 | |
| 	len = PySequence_Length( list );
 | |
| 	if( len > 0 ) {
 | |
| 		matlist = EXPP_newMaterialList_fromPyList( list );
 | |
| 		if( !matlist ) {
 | |
| 			return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
 | |
| 							"material list must be a list of valid materials!" ) );
 | |
| 		}
 | |
| 		if( ( len < 0 ) || ( len > MAXMAT ) ) {
 | |
| 			return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
 | |
| 							"material list should have at least 1, at most 16 entries" ) );
 | |
| 		}
 | |
| 
 | |
| 		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 = len;
 | |
| 		self->object->actcol = 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 )
 | |
| 		sort_baselist( 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" );
 | |
| 	}
 | |
| 
 | |
| 	Py_INCREF( Py_None );
 | |
| 	return ( Py_None );
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 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 = base->flag;
 | |
| 				set_active_base( base );
 | |
| 			} else {
 | |
| 				base->flag &= ~SELECT;
 | |
| 				self->object->flag = 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;
 | |
| 
 | |
| 	if( PyObject_Length( args ) == 3 || PyObject_Length( args ) == 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( PyObject_Length( args ) == 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;
 | |
| 
 | |
| 	if( !EXPP_addScriptLink( slink, args, 0 ) )
 | |
| 		return EXPP_incr_ret( Py_None );
 | |
| 	else
 | |
| 		return NULL;
 | |
| }
 | |
| 
 | |
| /* obj.clearScriptLinks */
 | |
| static PyObject *Object_clearScriptLinks( BPy_Object * self )
 | |
| {
 | |
| 	Object *obj = self->object;
 | |
| 	ScriptLink *slink = NULL;
 | |
| 
 | |
| 	slink = &( obj )->scriptlink;
 | |
| 
 | |
| 	return EXPP_incr_ret( Py_BuildValue
 | |
| 			      ( "i", EXPP_clearScriptLinks( slink ) ) );
 | |
| }
 | |
| 
 | |
| /* 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;
 | |
| }
 | |
| 
 | |
| /*****************************************************************************/
 | |
| /* 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;
 | |
| 	struct Ika *ika;
 | |
| 
 | |
| 	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] ) );
 | |
| 	if( strncmp( name, "Eff", 3 ) == 0 ) {
 | |
| 		if( ( object->type == OB_IKA ) && ( object->data != NULL ) ) {
 | |
| 			ika = object->data;
 | |
| 			switch ( name[3] ) {
 | |
| 			case 'X':
 | |
| 				return ( PyFloat_FromDouble( ika->effg[0] ) );
 | |
| 			case 'Y':
 | |
| 				return ( PyFloat_FromDouble( ika->effg[1] ) );
 | |
| 			case 'Z':
 | |
| 				return ( PyFloat_FromDouble( ika->effg[2] ) );
 | |
| 			default:
 | |
| 				/* Do we need to display a sensible error message here? */
 | |
| 				return ( NULL );
 | |
| 			}
 | |
| 		}
 | |
| 		return ( NULL );
 | |
| 	}
 | |
| 	if( StringEqual( name, "Layer" ) )
 | |
| 		return ( PyInt_FromLong( object->lay ) );
 | |
| 	if( StringEqual( name, "parent" ) ) {
 | |
| 		if( object->parent )
 | |
| 			return ( Object_CreatePyObject( object->parent ) );
 | |
| 		else {
 | |
| 			Py_INCREF( Py_None );
 | |
| 			return ( Py_None );
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if( StringEqual( name, "track" ) )
 | |
| 		return ( Object_CreatePyObject( object->track ) );
 | |
| 	if( StringEqual( name, "data" ) )
 | |
| 		return ( Object_getData( obj ) );
 | |
| 	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)", "localspace" ) ) );
 | |
| 	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 ) );
 | |
| 
 | |
| 	/* 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;
 | |
| 	struct Object *object;
 | |
| 	struct Ika *ika;
 | |
| 
 | |
| 	/* First 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" );
 | |
| 	}
 | |
| 
 | |
| 	object = obj->object;
 | |
| 	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, "loc" ) ) {
 | |
| 		if( Object_setLocation( obj, valtuple ) != Py_None )
 | |
| 			return ( -1 );
 | |
| 		else
 | |
| 			return ( 0 );
 | |
| 	}
 | |
| 	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, "dloc" ) ) {
 | |
| 		if( Object_setDeltaLocation( obj, valtuple ) != Py_None )
 | |
| 			return ( -1 );
 | |
| 		else
 | |
| 			return ( 0 );
 | |
| 	}
 | |
| 	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, "rot" ) ) {
 | |
| 		if( Object_setEuler( obj, valtuple ) != Py_None )
 | |
| 			return ( -1 );
 | |
| 		else
 | |
| 			return ( 0 );
 | |
| 	}
 | |
| 	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( strncmp( name, "Eff", 3 ) == 0 ) {
 | |
| 		if( ( object->type == OB_IKA ) && ( object->data != NULL ) ) {
 | |
| 			ika = object->data;
 | |
| 			switch ( name[3] ) {
 | |
| 			case 'X':
 | |
| 				return ( !PyArg_Parse
 | |
| 					 ( value, "f", &( ika->effg[0] ) ) );
 | |
| 			case 'Y':
 | |
| 				return ( !PyArg_Parse
 | |
| 					 ( value, "f", &( ika->effg[1] ) ) );
 | |
| 			case 'Z':
 | |
| 				return ( !PyArg_Parse
 | |
| 					 ( value, "f", &( ika->effg[2] ) ) );
 | |
| 			default:
 | |
| 				/* Do we need to display a sensible error message here? */
 | |
| 				return ( 0 );
 | |
| 			}
 | |
| 		}
 | |
| 		return ( 0 );
 | |
| 	}
 | |
| 	if( StringEqual( name, "Layer" ) ) {
 | |
| 		/*  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 )	/* bail if nothing to do */
 | |
| 			return ( 0 );
 | |
| 		
 | |
| 		/* 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, "parent" ) ) {
 | |
| 		/* This is not allowed. */
 | |
| 		EXPP_ReturnPyObjError( PyExc_AttributeError,
 | |
| 				       "Setting the parent is not allowed." );
 | |
| 		return ( 0 );
 | |
| 	}
 | |
| 	if( StringEqual( name, "track" ) ) {
 | |
| 		if( Object_makeTrack( obj, valtuple ) != Py_None )
 | |
| 			return ( -1 );
 | |
| 		else
 | |
| 			return ( 0 );
 | |
| 	}
 | |
| 	if( StringEqual( name, "data" ) ) {
 | |
| 		/* This is not allowed. */
 | |
| 		EXPP_ReturnPyObjError( PyExc_AttributeError,
 | |
| 				       "Setting the data is not allowed." );
 | |
| 		return ( 0 );
 | |
| 	}
 | |
| 	if( StringEqual( name, "ipo" ) ) {
 | |
| 		/* This is not allowed. */
 | |
| 		EXPP_ReturnPyObjError( PyExc_AttributeError,
 | |
| 				       "Setting the ipo is not allowed." );
 | |
| 		return ( 0 );
 | |
| 	}
 | |
| 	if( StringEqual( name, "mat" ) ) {
 | |
| 		/* This is not allowed. */
 | |
| 		EXPP_ReturnPyObjError( PyExc_AttributeError,
 | |
| 				       "Setting the matrix is not allowed." );
 | |
| 		return ( 0 );
 | |
| 	}
 | |
| 	if( StringEqual( name, "matrix" ) ) {
 | |
| 		/* This is not allowed. */
 | |
| 		EXPP_ReturnPyObjError( PyExc_AttributeError,
 | |
| 				       "Please use .setMatrix(matrix)" );
 | |
| 		return ( 0 );
 | |
| 	}
 | |
| 	if( StringEqual( name, "colbits" ) )
 | |
| 		return ( !PyArg_Parse( value, "h", &( object->colbits ) ) );
 | |
| 	if( StringEqual( name, "drawType" ) ) {
 | |
| 		if( Object_setDrawType( obj, valtuple ) != Py_None )
 | |
| 			return ( -1 );
 | |
| 		else
 | |
| 			return ( 0 );
 | |
| 	}
 | |
| 	if( StringEqual( name, "drawMode" ) ) {
 | |
| 		if( Object_setDrawMode( obj, valtuple ) != Py_None )
 | |
| 			return ( -1 );
 | |
| 		else
 | |
| 			return ( 0 );
 | |
| 	}
 | |
| 	if( StringEqual( name, "name" ) ) {
 | |
| 		if( Object_setName( obj, valtuple ) != Py_None )
 | |
| 			return ( -1 );
 | |
| 		else
 | |
| 			return ( 0 );
 | |
| 	}
 | |
| 
 | |
| 	if( StringEqual( name, "sel" ) ) {
 | |
| 		if( Object_Select( obj, valtuple ) != Py_None )
 | |
| 			return ( -1 );
 | |
| 		else
 | |
| 			return ( 0 );
 | |
| 	}
 | |
| 
 | |
| 	printf( "Unknown variable.\n" );
 | |
| 	return ( 0 );
 | |
| }
 | |
| 
 | |
| /*****************************************************************************/
 | |
| /* 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 );
 | |
| }
 | 
