/* * * ***** 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 #include #include #include #include #include #include /*****************************************************************************/ /* 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); 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_NOARGS, "Returns list of materials assigned to the object"}, {"getMatrix", (PyCFunction)Object_getMatrix, METH_VARARGS, "Returns the object matrix - worlspace or localspace (default)"}, {"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) 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); } 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); } 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) { return (EXPP_PyList_fromMaterialList (self->object->mat, self->object->totcol)); } 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 */ where_is_object(self->object); Mat4CpyMat4(*((MatrixObject*)matrix)->matrix, self->object->obmat); } else if (BLI_streq(space, "localspace")) { /* Localspace matrix*/ object_to_mat4(self->object, *((MatrixObject*)matrix)->matrix); } else { return (EXPP_ReturnPyObjError (PyExc_RuntimeError, "correct spaces are 'worldspace' and 'localspace', none defaults to localespace")); } 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); } 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 ; iobject; 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, "illegal material index!")); } if (self->object->mat) { EXPP_releaseMaterialList (self->object->mat, len); } /* Increase the user count on all materials */ for (i=0 ; iobject->mat = matlist; self->object->totcol = len; self->object->actcol = -1; 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, self->object->data); 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_AttributeError, "expected an object argument"); } if (!Object_CheckPyObject ((PyObject*)object)) { return EXPP_ReturnPyObjError (PyExc_TypeError, "argument 1 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); } 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; 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)){ /* uppper 2 bytes 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; if( base->object == obj->object ){ local = base->lay &= 0xFF000000; base->lay = local | newLayer; object->lay = base->lay; } countall(); } else{ return EXPP_ReturnIntError(PyExc_AttributeError, "expected int as bitmask"); } 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); }