Logo Search packages:      
Sourcecode: blender version File versions

Object.c

/* 
 * $Id: Object.c,v 1.94 2004/12/05 04:01:56 ianwill Exp $
 *
 * ***** 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 );
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},
      {"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 = '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"},
      {"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_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 );

      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 = "worldspace";   /* default to world */

      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 );
            /* old behavior, prior to 2.34, check this method's doc string: */
      } else if( BLI_streq( space, "old_worldspace" ) ) {
            Mat4CpyMat4( *( ( MatrixObject * ) matrix )->matrix,
                       self->object->obmat );
      } else {
            return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
                        "wrong parameter, expected nothing or either 'worldspace' (default),\n\
'localspace' or 'old_worldspace'" ) );
      }
      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;
      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;

      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)", "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 ) );

      /* 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 );
}

Generated by  Doxygen 1.6.0   Back to index