This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/python/api2_2x/Object.c

4197 lines
126 KiB
C
Raw Normal View History

/*
* $Id$
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
*
* The Object module provides generic access to Objects of various types via
* the Python interface.
*
*
* Contributor(s): Michel Selten, Willian Germano, Jacques Guignot,
* Joseph Gilbert, Stephen Swaney, Bala Gi, Campbell Barton, Johnny Matthews,
* Ken Hughes, Alex Mole
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
struct SpaceIpo;
struct rctf;
#include "Object.h" /*This must come first */
#include "DNA_view3d_types.h"
#include "DNA_object_force.h"
#include "DNA_userdef_types.h"
Mathutils update - also included is some fixes for preprocessor inclues and some clean up of the previous commit -rewrite and bugfixes ---------------------------------- Here's my changelog: -fixed Rand() so that it doesn't seed everytime and should generate better random numbers - changed a few error return types to something more appropriate - clean up of uninitialized variables & removal of unneccessary objects - NMesh returns wrapped vectors now - World returns wrapped matrices now - Object.getEuler() and Object.getBoundingBox() return Wrapped data when data is present - Object.getMatrix() returns wrapped data if it's worldspace, 'localspace' returns a new matrix - Vector, Euler, Mat, Quat, call all now internally wrap object without destroying internal datablocks - Removed memory allocation (unneeded) from all methods - Vector's resize methods are only applicable to new vectors not wrapped data. - Matrix(), Quat(), Euler(), Vector() now accepts ANY sequence list, including tuples, list, or a self object to copy - matrices accept multiple sequences - Fixed Slerp() so that it now works correctly values are clamped between 0 and 1 - Euler.rotate does internal rotation now - Slice assignment now works better for all types - Vector * Vector and Quat * Quat are defined and return the DOT product - Mat * Vec and Vec * Mat are defined now - Moved #includes to .c file from headers. Also fixed prototypes in mathutils - Added new helper functions for incref'ing to genutils - Major cleanup of header files includes - include Mathutils.h for access to math types - matrix.toQuat() and .toEuler() now fixed take appropriate matrix sizes - Matrix() with no parameters now returns an identity matrix by default not a zero matrix - printf() now prints with 6 digits instead of 4 - printf() now prints output with object descriptor - Matrices now support [x][y] assignment (e.g. matrix[x][y] = 5.4) - Matrix[index] = value now expectes a sequence not an integer. This will now set a ROW of the matrix through a sequence. index cannot go above the row size of the matrix. - slice operations on matrices work with sequences now (rows of the matrix) example: mymatrix[0:2] returns a list of 2 wrapped vectors with access to the matrix data. - slice assignment will no longer modify the data if the assignment operation fails - fixed error in matrix * scalar multiplication - euler.toMatrix(), toQuat() no longer causes "creep" from repeated use - Wrapped data will generate wrapped objects when toEuler(), toQuat(), toMatrix() is used - Quats can be created with angle/axis, axis/angle - 4x4 matrices can be multiplied by 3D vectors (by popular demand :)) - vec *quat / quat * vec is now defined - vec.magnitude alias for vec.length - all self, internal methods return a pointer to self now so you can do print vector.internalmethod() or vector.internalmethod().nextmethod() (no more print matrix.inverse() returning 'none') - these methods have been deprecated (still functioning but suggested to use the corrected functionality): * CopyVec() - replaced by Vector() functionality * CopyMat() - replaced by Matrix() functionality * CopyQuat() - replace by Quaternion() functionality * CopyEuler() - replaced by Euler() functionality * RotateEuler() - replaced by Euler.rotate() funtionality * MatMultVec() - replaced by matrix * vector * VecMultMat() - replaced by vector * matrix - New struct containers references to python object data or internally allocated blender data for wrapping * Explaination here: math structs now function as a 'simple wrapper' or a 'py_object' - data that is created on the fly will now be a 'py_object' with its memory managed by python * otherwise if the data is returned by blender's G.main then the math object is a 'simple wrapper' and data can be accessed directly from the struct just like other python objects.
2005-07-14 03:34:56 +00:00
#include "BKE_depsgraph.h"
#include "BKE_effect.h"
Mathutils update - also included is some fixes for preprocessor inclues and some clean up of the previous commit -rewrite and bugfixes ---------------------------------- Here's my changelog: -fixed Rand() so that it doesn't seed everytime and should generate better random numbers - changed a few error return types to something more appropriate - clean up of uninitialized variables & removal of unneccessary objects - NMesh returns wrapped vectors now - World returns wrapped matrices now - Object.getEuler() and Object.getBoundingBox() return Wrapped data when data is present - Object.getMatrix() returns wrapped data if it's worldspace, 'localspace' returns a new matrix - Vector, Euler, Mat, Quat, call all now internally wrap object without destroying internal datablocks - Removed memory allocation (unneeded) from all methods - Vector's resize methods are only applicable to new vectors not wrapped data. - Matrix(), Quat(), Euler(), Vector() now accepts ANY sequence list, including tuples, list, or a self object to copy - matrices accept multiple sequences - Fixed Slerp() so that it now works correctly values are clamped between 0 and 1 - Euler.rotate does internal rotation now - Slice assignment now works better for all types - Vector * Vector and Quat * Quat are defined and return the DOT product - Mat * Vec and Vec * Mat are defined now - Moved #includes to .c file from headers. Also fixed prototypes in mathutils - Added new helper functions for incref'ing to genutils - Major cleanup of header files includes - include Mathutils.h for access to math types - matrix.toQuat() and .toEuler() now fixed take appropriate matrix sizes - Matrix() with no parameters now returns an identity matrix by default not a zero matrix - printf() now prints with 6 digits instead of 4 - printf() now prints output with object descriptor - Matrices now support [x][y] assignment (e.g. matrix[x][y] = 5.4) - Matrix[index] = value now expectes a sequence not an integer. This will now set a ROW of the matrix through a sequence. index cannot go above the row size of the matrix. - slice operations on matrices work with sequences now (rows of the matrix) example: mymatrix[0:2] returns a list of 2 wrapped vectors with access to the matrix data. - slice assignment will no longer modify the data if the assignment operation fails - fixed error in matrix * scalar multiplication - euler.toMatrix(), toQuat() no longer causes "creep" from repeated use - Wrapped data will generate wrapped objects when toEuler(), toQuat(), toMatrix() is used - Quats can be created with angle/axis, axis/angle - 4x4 matrices can be multiplied by 3D vectors (by popular demand :)) - vec *quat / quat * vec is now defined - vec.magnitude alias for vec.length - all self, internal methods return a pointer to self now so you can do print vector.internalmethod() or vector.internalmethod().nextmethod() (no more print matrix.inverse() returning 'none') - these methods have been deprecated (still functioning but suggested to use the corrected functionality): * CopyVec() - replaced by Vector() functionality * CopyMat() - replaced by Matrix() functionality * CopyQuat() - replace by Quaternion() functionality * CopyEuler() - replaced by Euler() functionality * RotateEuler() - replaced by Euler.rotate() funtionality * MatMultVec() - replaced by matrix * vector * VecMultMat() - replaced by vector * matrix - New struct containers references to python object data or internally allocated blender data for wrapping * Explaination here: math structs now function as a 'simple wrapper' or a 'py_object' - data that is created on the fly will now be a 'py_object' with its memory managed by python * otherwise if the data is returned by blender's G.main then the math object is a 'simple wrapper' and data can be accessed directly from the struct just like other python objects.
2005-07-14 03:34:56 +00:00
#include "BKE_font.h"
#include "BKE_property.h"
#include "BKE_mball.h"
#include "BKE_softbody.h"
#include "BKE_utildefines.h"
#include "BKE_armature.h"
#include "BKE_lattice.h"
#include "BKE_mesh.h"
#include "BKE_library.h"
#include "BKE_object.h"
#include "BKE_curve.h"
#include "BKE_global.h"
#include "BKE_main.h"
Mathutils update - also included is some fixes for preprocessor inclues and some clean up of the previous commit -rewrite and bugfixes ---------------------------------- Here's my changelog: -fixed Rand() so that it doesn't seed everytime and should generate better random numbers - changed a few error return types to something more appropriate - clean up of uninitialized variables & removal of unneccessary objects - NMesh returns wrapped vectors now - World returns wrapped matrices now - Object.getEuler() and Object.getBoundingBox() return Wrapped data when data is present - Object.getMatrix() returns wrapped data if it's worldspace, 'localspace' returns a new matrix - Vector, Euler, Mat, Quat, call all now internally wrap object without destroying internal datablocks - Removed memory allocation (unneeded) from all methods - Vector's resize methods are only applicable to new vectors not wrapped data. - Matrix(), Quat(), Euler(), Vector() now accepts ANY sequence list, including tuples, list, or a self object to copy - matrices accept multiple sequences - Fixed Slerp() so that it now works correctly values are clamped between 0 and 1 - Euler.rotate does internal rotation now - Slice assignment now works better for all types - Vector * Vector and Quat * Quat are defined and return the DOT product - Mat * Vec and Vec * Mat are defined now - Moved #includes to .c file from headers. Also fixed prototypes in mathutils - Added new helper functions for incref'ing to genutils - Major cleanup of header files includes - include Mathutils.h for access to math types - matrix.toQuat() and .toEuler() now fixed take appropriate matrix sizes - Matrix() with no parameters now returns an identity matrix by default not a zero matrix - printf() now prints with 6 digits instead of 4 - printf() now prints output with object descriptor - Matrices now support [x][y] assignment (e.g. matrix[x][y] = 5.4) - Matrix[index] = value now expectes a sequence not an integer. This will now set a ROW of the matrix through a sequence. index cannot go above the row size of the matrix. - slice operations on matrices work with sequences now (rows of the matrix) example: mymatrix[0:2] returns a list of 2 wrapped vectors with access to the matrix data. - slice assignment will no longer modify the data if the assignment operation fails - fixed error in matrix * scalar multiplication - euler.toMatrix(), toQuat() no longer causes "creep" from repeated use - Wrapped data will generate wrapped objects when toEuler(), toQuat(), toMatrix() is used - Quats can be created with angle/axis, axis/angle - 4x4 matrices can be multiplied by 3D vectors (by popular demand :)) - vec *quat / quat * vec is now defined - vec.magnitude alias for vec.length - all self, internal methods return a pointer to self now so you can do print vector.internalmethod() or vector.internalmethod().nextmethod() (no more print matrix.inverse() returning 'none') - these methods have been deprecated (still functioning but suggested to use the corrected functionality): * CopyVec() - replaced by Vector() functionality * CopyMat() - replaced by Matrix() functionality * CopyQuat() - replace by Quaternion() functionality * CopyEuler() - replaced by Euler() functionality * RotateEuler() - replaced by Euler.rotate() funtionality * MatMultVec() - replaced by matrix * vector * VecMultMat() - replaced by vector * matrix - New struct containers references to python object data or internally allocated blender data for wrapping * Explaination here: math structs now function as a 'simple wrapper' or a 'py_object' - data that is created on the fly will now be a 'py_object' with its memory managed by python * otherwise if the data is returned by blender's G.main then the math object is a 'simple wrapper' and data can be accessed directly from the struct just like other python objects.
2005-07-14 03:34:56 +00:00
#include "BIF_editview.h"
#include "BSE_editipo.h"
#include "BSE_edit.h"
#include "BIF_space.h"
#include "DNA_oops_types.h"
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
#include "BDR_editobject.h"
#include "MEM_guardedalloc.h"
#include "mydevice.h"
#include "blendef.h"
#include "Scene.h"
#include "Mathutils.h"
#include "NMesh.h"
#include "Curve.h"
#include "Ipo.h"
#include "Armature.h"
#include "Camera.h"
#include "Lamp.h"
#include "Lattice.h"
#include "Text.h"
#include "Text3d.h"
#include "Metaball.h"
#include "Draw.h"
#include "NLA.h"
#include "logic.h"
#include "gen_utils.h"
/* Defines for insertIpoKey */
#define IPOKEY_LOC 0
#define IPOKEY_ROT 1
#define IPOKEY_SIZE 2
#define IPOKEY_LOCROT 3
#define IPOKEY_LOCROTSIZE 4
#define IPOKEY_PI_STRENGTH 5
#define IPOKEY_PI_FALLOFF 6
#define IPOKEY_PI_MAXDIST 7 /*Not Ready Yet*/
#define IPOKEY_PI_SURFACEDAMP 8
#define IPOKEY_PI_RANDOMDAMP 9
#define IPOKEY_PI_PERM 10
#define PFIELD_FORCE 1
#define PFIELD_VORTEX 2
#define PFIELD_MAGNET 3
#define PFIELD_WIND 4
/*****************************************************************************/
/* Python API function prototypes for the Blender module. */
/*****************************************************************************/
static PyObject *M_Object_New( PyObject * self, PyObject * args );
PyObject *M_Object_Get( PyObject * self, PyObject * args );
static PyObject *M_Object_GetSelected( PyObject * self, PyObject * args );
/* HELPER FUNCTION FOR PARENTING */
static PyObject *internal_makeParent(Object *parent, PyObject *py_child, int partype, int noninverse, int fast, int v1, int v2, int v3);
extern int Text3d_CheckPyObject( PyObject * py_obj );
extern struct Text3d *Text3d_FromPyObject( PyObject * py_obj );
/*****************************************************************************/
/* The following string definitions are used for documentation strings. */
/* In Python these will be written to the console when doing a */
/* Blender.Object.__doc__ */
/*****************************************************************************/
char M_Object_doc[] = "The Blender Object module\n\n\
This module provides access to **Object Data** in Blender.\n";
char M_Object_New_doc[] =
"(type) - Add a new object of type 'type' in the current scene";
char M_Object_Get_doc[] =
"(name) - return the object with the name 'name', returns None if not\
found.\n\
If 'name' is not specified, it returns a list of all objects in the\n\
current scene.";
char M_Object_GetSelected_doc[] =
"() - Returns a list of selected Objects in the active layer(s)\n\
The active object is the first in the list, if visible";
/*****************************************************************************/
/* Python method structure definition for Blender.Object module: */
/*****************************************************************************/
struct PyMethodDef M_Object_methods[] = {
{"New", ( PyCFunction ) M_Object_New, METH_VARARGS,
M_Object_New_doc},
{"Get", ( PyCFunction ) M_Object_Get, METH_VARARGS,
M_Object_Get_doc},
{"GetSelected", ( PyCFunction ) M_Object_GetSelected, METH_VARARGS,
M_Object_GetSelected_doc},
{NULL, NULL, 0, NULL}
};
/*****************************************************************************/
/* Python BPy_Object methods declarations: */
/*****************************************************************************/
int setupSB(Object* ob); /*Make sure Softbody Pointer is initialized */
int setupPI(Object* ob);
static PyObject *Object_buildParts( BPy_Object * self );
static PyObject *Object_clearIpo( BPy_Object * self );
static PyObject *Object_clrParent( BPy_Object * self, PyObject * args );
static PyObject *Object_clearTrack( BPy_Object * self, PyObject * args );
static PyObject *Object_getData(BPy_Object *self, PyObject *args, PyObject *kwd);
static PyObject *Object_getDeltaLocation( BPy_Object * self );
static PyObject *Object_getDrawMode( BPy_Object * self );
static PyObject *Object_getDrawType( BPy_Object * self );
static PyObject *Object_getEuler( BPy_Object * self );
static PyObject *Object_getInverseMatrix( BPy_Object * self );
static PyObject *Object_getIpo( BPy_Object * self );
static PyObject *Object_getLocation( BPy_Object * self, PyObject * args );
static PyObject *Object_getMaterials( BPy_Object * self, PyObject * args );
static PyObject *Object_getMatrix( BPy_Object * self, PyObject * args );
static PyObject *Object_getName( BPy_Object * self );
static PyObject *Object_getParent( BPy_Object * self );
static PyObject *Object_getParentBoneName( BPy_Object * self );
static PyObject *Object_getSize( BPy_Object * self, PyObject * args );
static PyObject *Object_getTimeOffset( BPy_Object * self );
static PyObject *Object_getTracked( BPy_Object * self );
static PyObject *Object_getType( BPy_Object * self );
static PyObject *Object_getBoundBox( BPy_Object * self );
static PyObject *Object_getAction( BPy_Object * self );
static PyObject *Object_isSelected( BPy_Object * self );
static PyObject *Object_makeDisplayList( BPy_Object * self );
static PyObject *Object_link( BPy_Object * self, PyObject * args );
static PyObject *Object_makeParent( BPy_Object * self, PyObject * args );
static PyObject *Object_makeParentDeform( BPy_Object * self, PyObject * args );
static PyObject *Object_makeParentVertex( BPy_Object * self, PyObject * args );
static PyObject *Object_materialUsage( BPy_Object * self, PyObject * args );
static PyObject *Object_getDupliVerts ( BPy_Object * self );
static PyObject *Object_setDeltaLocation( BPy_Object * self, PyObject * args );
static PyObject *Object_setDrawMode( BPy_Object * self, PyObject * args );
static PyObject *Object_setDrawType( BPy_Object * self, PyObject * args );
static PyObject *Object_setEuler( BPy_Object * self, PyObject * args );
static PyObject *Object_setMatrix( BPy_Object * self, PyObject * args );
static PyObject *Object_setIpo( BPy_Object * self, PyObject * args );
static PyObject *Object_insertIpoKey( BPy_Object * self, PyObject * args );
static PyObject *Object_setLocation( BPy_Object * self, PyObject * args );
static PyObject *Object_setMaterials( BPy_Object * self, PyObject * args );
static PyObject *Object_setName( BPy_Object * self, PyObject * args );
static PyObject *Object_setSize( BPy_Object * self, PyObject * args );
static PyObject *Object_setTimeOffset( BPy_Object * self, PyObject * args );
static PyObject *Object_makeTrack( BPy_Object * self, PyObject * args );
static PyObject *Object_shareFrom( BPy_Object * self, PyObject * args );
static PyObject *Object_Select( BPy_Object * self, PyObject * args );
static PyObject *Object_getAllProperties( BPy_Object * self );
static PyObject *Object_addProperty( BPy_Object * self, PyObject * args );
static PyObject *Object_removeProperty( BPy_Object * self, PyObject * args );
static PyObject *Object_getProperty( BPy_Object * self, PyObject * args );
static PyObject *Object_removeAllProperties( BPy_Object * self );
static PyObject *Object_copyAllPropertiesTo( BPy_Object * self,
PyObject * args );
static PyObject *Object_getScriptLinks( BPy_Object * self, PyObject * args );
static PyObject *Object_addScriptLink( BPy_Object * self, PyObject * args );
static PyObject *Object_clearScriptLinks( BPy_Object * self, PyObject *args );
static PyObject *Object_setDupliVerts ( BPy_Object * self, PyObject * args );
static PyObject *Object_getPIStrength( BPy_Object * self );
static PyObject *Object_setPIStrength( BPy_Object * self, PyObject * args );
static PyObject *Object_getPIFalloff( BPy_Object * self );
static PyObject *Object_setPIFalloff( BPy_Object * self, PyObject * args );
static PyObject *Object_getPIMaxDist( BPy_Object * self );
static PyObject *Object_setPIMaxDist( BPy_Object * self, PyObject * args );
static PyObject *Object_getPIUseMaxDist( BPy_Object * self );
static PyObject *Object_setPIUseMaxDist( BPy_Object * self, PyObject * args );
static PyObject *Object_getPIType( BPy_Object * self );
static PyObject *Object_setPIType( BPy_Object * self, PyObject * args );
static PyObject *Object_getPIPerm( BPy_Object * self );
static PyObject *Object_setPIPerm( BPy_Object * self, PyObject * args );
static PyObject *Object_getPIRandomDamp( BPy_Object * self );
static PyObject *Object_setPIRandomDamp( BPy_Object * self, PyObject * args );
static PyObject *Object_getPISurfaceDamp( BPy_Object * self );
static PyObject *Object_setPISurfaceDamp( BPy_Object * self, PyObject * args );
static PyObject *Object_getPIDeflection( BPy_Object * self );
static PyObject *Object_setPIDeflection( BPy_Object * self, PyObject * args );
static PyObject *Object_isSB( BPy_Object * self );
static PyObject *Object_getSBMass( BPy_Object * self );
static PyObject *Object_setSBMass( BPy_Object * self, PyObject * args );
static PyObject *Object_getSBGravity( BPy_Object * self );
static PyObject *Object_setSBGravity( BPy_Object * self, PyObject * args );
static PyObject *Object_getSBFriction( BPy_Object * self );
static PyObject *Object_setSBFriction( BPy_Object * self, PyObject * args );
static PyObject *Object_getSBErrorLimit( BPy_Object * self );
static PyObject *Object_setSBErrorLimit( BPy_Object * self, PyObject * args );
static PyObject *Object_getSBGoalSpring( BPy_Object * self );
static PyObject *Object_setSBGoalSpring( BPy_Object * self, PyObject * args );
static PyObject *Object_getSBGoalFriction( BPy_Object * self );
static PyObject *Object_setSBGoalFriction( BPy_Object * self, PyObject * args );
static PyObject *Object_getSBMinGoal( BPy_Object * self );
static PyObject *Object_setSBMinGoal( BPy_Object * self, PyObject * args );
static PyObject *Object_getSBMaxGoal( BPy_Object * self );
static PyObject *Object_setSBMaxGoal( BPy_Object * self, PyObject * args );
static PyObject *Object_getSBInnerSpring( BPy_Object * self );
static PyObject *Object_setSBInnerSpring( BPy_Object * self, PyObject * args );
static PyObject *Object_getSBInnerSpringFriction( BPy_Object * self );
static PyObject *Object_setSBInnerSpringFriction( BPy_Object * self, PyObject * args );
static PyObject *Object_getSBDefaultGoal( BPy_Object * self );
static PyObject *Object_setSBDefaultGoal( BPy_Object * self, PyObject * args );
static PyObject *Object_getSBEnable( BPy_Object * self );
static PyObject *Object_setSBEnable( BPy_Object * self, PyObject * args );
static PyObject *Object_getSBPostDef( BPy_Object * self );
static PyObject *Object_setSBPostDef( BPy_Object * self, PyObject * args );
static PyObject *Object_getSBUseGoal( BPy_Object * self );
static PyObject *Object_setSBUseGoal( BPy_Object * self, PyObject * args );
static PyObject *Object_getSBUseEdges( BPy_Object * self );
static PyObject *Object_setSBUseEdges( BPy_Object * self, PyObject * args );
static PyObject *Object_getSBStiffQuads( BPy_Object * self );
static PyObject *Object_setSBStiffQuads( BPy_Object * self, PyObject * args );
/*****************************************************************************/
/* Python BPy_Object methods table: */
/*****************************************************************************/
static PyMethodDef BPy_Object_methods[] = {
/* name, method, flags, doc */
{"buildParts", ( PyCFunction ) Object_buildParts, METH_NOARGS,
"Recalcs particle system (if any) "},
{"getIpo", ( PyCFunction ) Object_getIpo, METH_NOARGS,
"Returns the ipo of this object (if any) "},
{"clrParent", ( PyCFunction ) Object_clrParent, METH_VARARGS,
"Clears parent object. Optionally specify:\n\
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
mode\n\tnonzero: Keep object transform\nfast\n\t>0: Don't update scene \
hierarchy (faster)"},
{"clearTrack", ( PyCFunction ) Object_clearTrack, METH_VARARGS,
"Make this object not track another anymore. Optionally specify:\n\
mode\n\t2: Keep object transform\nfast\n\t>0: Don't update scene \
hierarchy (faster)"},
{"getData", ( PyCFunction ) Object_getData, METH_VARARGS | METH_KEYWORDS,
"(name_only = 0) - Returns the datablock object containing the object's \
data, e.g. Mesh.\n\
If 'name_only' is nonzero or True, only the name of the datablock is returned"},
{"getDeltaLocation", ( PyCFunction ) Object_getDeltaLocation,
METH_NOARGS,
"Returns the object's delta location (x, y, z)"},
{"getDrawMode", ( PyCFunction ) Object_getDrawMode, METH_NOARGS,
"Returns the object draw modes"},
{"getDrawType", ( PyCFunction ) Object_getDrawType, METH_NOARGS,
"Returns the object draw type"},
{"getAction", ( PyCFunction ) Object_getAction, METH_NOARGS,
"Returns the active action for this object"},
{"isSelected", ( PyCFunction ) Object_isSelected, METH_NOARGS,
"Return a 1 or 0 depending on whether the object is selected"},
{"getEuler", ( PyCFunction ) Object_getEuler, METH_NOARGS,
"Returns the object's rotation as Euler rotation vector\n\
(rotX, rotY, rotZ)"},
{"getInverseMatrix", ( PyCFunction ) Object_getInverseMatrix,
METH_NOARGS,
"Returns the object's inverse matrix"},
{"getLocation", ( PyCFunction ) Object_getLocation, METH_VARARGS,
"Returns the object's location (x, y, z)"},
{"getMaterials", ( PyCFunction ) Object_getMaterials, METH_VARARGS,
"(i = 0) - Returns list of materials assigned to the object.\n\
if i is nonzero, empty slots are not ignored: they are returned as None's."},
{"getMatrix", ( PyCFunction ) Object_getMatrix, METH_VARARGS,
"(str = 'worldspace') - Returns the object matrix.\n\
(str = 'worldspace') - the wanted matrix: worldspace (default), localspace\n\
or old_worldspace.\n\
\n\
'old_worldspace' was the only behavior before Blender 2.34. With it the\n\
matrix is not updated for changes made by the script itself\n\
(like obj.LocX = 10) until a redraw happens, either called by the script or\n\
automatic when the script finishes."},
{"getName", ( PyCFunction ) Object_getName, METH_NOARGS,
"Returns the name of the object"},
{"getParent", ( PyCFunction ) Object_getParent, METH_NOARGS,
"Returns the object's parent object"},
{"getParentBoneName", ( PyCFunction ) Object_getParentBoneName, METH_NOARGS,
"Returns None, or the 'sub-name' of the parent (eg. Bone name)"},
{"getSize", ( PyCFunction ) Object_getSize, METH_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"},
/* Particle Interaction */
{"getPIStrength", ( PyCFunction ) Object_getPIStrength, METH_NOARGS,
"Returns Particle Interaction Strength"},
{"setPIStrength", ( PyCFunction ) Object_setPIStrength, METH_VARARGS,
"Sets Particle Interaction Strength"},
{"getPIFalloff", ( PyCFunction ) Object_getPIFalloff, METH_NOARGS,
"Returns Particle Interaction Falloff"},
{"setPIFalloff", ( PyCFunction ) Object_setPIFalloff, METH_VARARGS,
"Sets Particle Interaction Falloff"},
{"getPIMaxDist", ( PyCFunction ) Object_getPIMaxDist, METH_NOARGS,
"Returns Particle Interaction Max Distance"},
{"setPIMaxDist", ( PyCFunction ) Object_setPIMaxDist, METH_VARARGS,
"Sets Particle Interaction Max Distance"},
{"getPIUseMaxDist", ( PyCFunction ) Object_getPIUseMaxDist, METH_NOARGS,
"Returns bool for Use Max Distace in Particle Interaction "},
{"setPIUseMaxDist", ( PyCFunction ) Object_setPIUseMaxDist, METH_VARARGS,
"Sets if Max Distance should be used in Particle Interaction"},
{"getPIType", ( PyCFunction ) Object_getPIType, METH_NOARGS,
"Returns Particle Interaction Type"},
{"setPIType", ( PyCFunction ) Object_setPIType, METH_VARARGS,
"sets Particle Interaction Type"},
{"getPIPerm", ( PyCFunction ) Object_getPIPerm, METH_NOARGS,
"Returns Particle Interaction Permiability"},
{"setPIPerm", ( PyCFunction ) Object_setPIPerm, METH_VARARGS,
"Sets Particle Interaction Permiability"},
{"getPISurfaceDamp", ( PyCFunction ) Object_getPISurfaceDamp, METH_NOARGS,
"Returns Particle Interaction Surface Damping"},
{"setPISurfaceDamp", ( PyCFunction ) Object_setPISurfaceDamp, METH_VARARGS,
"Sets Particle Interaction Surface Damping"},
{"getPIRandomDamp", ( PyCFunction ) Object_getPIRandomDamp, METH_NOARGS,
"Returns Particle Interaction Random Damping"},
{"setPIRandomDamp", ( PyCFunction ) Object_setPIRandomDamp, METH_VARARGS,
"Sets Particle Interaction Random Damping"},
{"getPIDeflection", ( PyCFunction ) Object_getPIDeflection, METH_NOARGS,
"Returns Particle Interaction Deflection"},
{"setPIDeflection", ( PyCFunction ) Object_setPIDeflection, METH_VARARGS,
"Sets Particle Interaction Deflection"},
/* Softbody */
{"isSB", ( PyCFunction ) Object_isSB, METH_NOARGS,
"True if object is a soft body"},
{"getSBMass", ( PyCFunction ) Object_getSBMass, METH_NOARGS,
"Returns SB Mass"},
{"setSBMass", ( PyCFunction ) Object_setSBMass, METH_VARARGS,
"Sets SB Mass"},
{"getSBGravity", ( PyCFunction ) Object_getSBGravity, METH_NOARGS,
"Returns SB Gravity"},
{"setSBGravity", ( PyCFunction ) Object_setSBGravity, METH_VARARGS,
"Sets SB Gravity"},
{"getSBFriction", ( PyCFunction ) Object_getSBFriction, METH_NOARGS,
"Returns SB Friction"},
{"setSBFriction", ( PyCFunction ) Object_setSBFriction, METH_VARARGS,
"Sets SB Friction"},
{"getSBErrorLimit", ( PyCFunction ) Object_getSBErrorLimit, METH_NOARGS,
"Returns SB ErrorLimit"},
{"setSBErrorLimit", ( PyCFunction ) Object_setSBErrorLimit, METH_VARARGS,
"Sets SB ErrorLimit"},
{"getSBGoalSpring", ( PyCFunction ) Object_getSBGoalSpring, METH_NOARGS,
"Returns SB GoalSpring"},
{"setSBGoalSpring", ( PyCFunction ) Object_setSBGoalSpring, METH_VARARGS,
"Sets SB GoalSpring"},
{"getSBGoalFriction", ( PyCFunction ) Object_getSBGoalFriction, METH_NOARGS,
"Returns SB GoalFriction"},
{"setSBGoalFriction", ( PyCFunction ) Object_setSBGoalFriction, METH_VARARGS,
"Sets SB GoalFriction"},
{"getSBMinGoal", ( PyCFunction ) Object_getSBMinGoal, METH_NOARGS,
"Returns SB MinGoal"},
{"setSBMinGoal", ( PyCFunction ) Object_setSBMinGoal, METH_VARARGS,
"Sets SB MinGoal "},
{"getSBMaxGoal", ( PyCFunction ) Object_getSBMaxGoal, METH_NOARGS,
"Returns SB MaxGoal"},
{"setSBMaxGoal", ( PyCFunction ) Object_setSBMaxGoal, METH_VARARGS,
"Sets SB MaxGoal"},
{"getSBInnerSpring", ( PyCFunction ) Object_getSBInnerSpring, METH_NOARGS,
"Returns SB InnerSpring"},
{"setSBInnerSpring", ( PyCFunction ) Object_setSBInnerSpring, METH_VARARGS,
"Sets SB InnerSpring"},
{"getSBInnerSpringFriction", ( PyCFunction ) Object_getSBInnerSpringFriction, METH_NOARGS,
"Returns SB InnerSpringFriction"},
{"setSBInnerSpringFriction", ( PyCFunction ) Object_setSBInnerSpringFriction, METH_VARARGS,
"Sets SB InnerSpringFriction"},
{"getSBDefaultGoal", ( PyCFunction ) Object_getSBDefaultGoal, METH_NOARGS,
"Returns SB DefaultGoal"},
{"setSBDefaultGoal", ( PyCFunction ) Object_setSBDefaultGoal, METH_VARARGS,
"Sets SB DefaultGoal"},
{"getSBEnable", ( PyCFunction ) Object_getSBEnable, METH_NOARGS,
"Returns SB Enable"},
{"setSBEnable", ( PyCFunction ) Object_setSBEnable, METH_VARARGS,
"Sets SB Enable"},
{"getSBPostDef", ( PyCFunction ) Object_getSBPostDef, METH_NOARGS,
"Returns SB PostDef"},
{"setSBPostDef", ( PyCFunction ) Object_setSBPostDef, METH_VARARGS,
"Sets SB PostDef"},
{"getSBUseGoal", ( PyCFunction ) Object_getSBUseGoal, METH_NOARGS,
"Returns SB UseGoal"},
{"setSBUseGoal", ( PyCFunction ) Object_setSBUseGoal, METH_VARARGS,
"Sets SB UseGoal"},
{"getSBUseEdges", ( PyCFunction ) Object_getSBUseEdges, METH_NOARGS,
"Returns SB UseEdges"},
{"setSBUseEdges", ( PyCFunction ) Object_setSBUseEdges, METH_VARARGS,
"Sets SB UseEdges"},
{"getSBStiffQuads", ( PyCFunction ) Object_getSBStiffQuads, METH_NOARGS,
"Returns SB StiffQuads"},
{"setSBStiffQuads", ( PyCFunction ) Object_setSBStiffQuads, METH_VARARGS,
"Sets SB StiffQuads"},
{"getBoundBox", ( PyCFunction ) Object_getBoundBox, METH_NOARGS,
"Returns the object's bounding box"},
{"getDupliVerts", ( PyCFunction ) Object_getDupliVerts,
METH_NOARGS, "Returns state of duplicates propertie"},
{"makeDisplayList", ( PyCFunction ) Object_makeDisplayList,
METH_NOARGS,
"Update this object's Display List. Some changes like turning \n\
'SubSurf' on for a mesh need this method (followed by a Redraw) to \n\
show the changes on the 3d window."},
{"link", ( PyCFunction ) Object_link, METH_VARARGS,
"Links Object with data provided in the argument. The data must \n\
match the Object's type, so you cannot link a Lamp to a Mesh type object."},
{"makeParent", ( PyCFunction ) Object_makeParent, METH_VARARGS,
"Makes the object the parent of the objects provided in the \n\
argument which must be a list of valid Objects. Optional extra arguments:\n\
mode:\n\t0: make parent with inverse\n\t1: without inverse\n\
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
fast:\n\t0: update scene hierarchy automatically\n\t\
don't update scene hierarchy (faster). In this case, you must\n\t\
explicitely update the Scene hierarchy."},
{"makeParentDeform", ( PyCFunction ) Object_makeParentDeform, METH_VARARGS,
"Makes the object the deformation parent of the objects provided in the \n\
argument which must be a list of valid Objects. Optional extra arguments:\n\
mode:\n\t0: make parent with inverse\n\t1: without inverse\n\
fast:\n\t0: update scene hierarchy automatically\n\t\
don't update scene hierarchy (faster). In this case, you must\n\t\
explicitely update the Scene hierarchy."},
{"makeParentVertex", ( PyCFunction ) Object_makeParentVertex, METH_VARARGS,
"Makes the object the vertex parent of the objects provided in the \n\
argument which must be a list of valid Objects. \n\
The second argument is a tuple of 1 or 3 positive integers which corresponds \
to the index of the vertex you are parenting to.\n\
Optional extra arguments:\n\
mode:\n\t0: make parent with inverse\n\t1: without inverse\n\
fast:\n\t0: update scene hierarchy automatically\n\t\
don't update scene hierarchy (faster). In this case, you must\n\t\
explicitely update the Scene hierarchy."},
{"materialUsage", ( PyCFunction ) Object_materialUsage, METH_VARARGS,
"Determines the way the material is used and returns status.\n\
Possible arguments (provide as strings):\n\
\tData: Materials assigned to the object's data are shown. (default)\n\
\tObject: Materials assigned to the object are shown."},
{"setDeltaLocation", ( PyCFunction ) Object_setDeltaLocation,
METH_VARARGS,
"Sets the object's delta location which must be a vector triple."},
{"setDrawMode", ( PyCFunction ) Object_setDrawMode, METH_VARARGS,
"Sets the object's drawing mode. The argument can be a sum of:\n\
2: axis\n4: texspace\n8: drawname\n16: drawimage\n32: drawwire"},
{"setDrawType", ( PyCFunction ) Object_setDrawType, METH_VARARGS,
"Sets the object's drawing type. The argument must be one of:\n\
1: Bounding box\n2: Wire\n3: Solid\n4: Shaded\n5: Textured"},
{"setEuler", ( PyCFunction ) Object_setEuler, METH_VARARGS,
"Set the object's rotation according to the specified Euler\n\
angles. The argument must be a vector triple"},
{"setMatrix", ( PyCFunction ) Object_setMatrix, METH_VARARGS,
"Set and apply a new matrix for the object"},
{"setLocation", ( PyCFunction ) Object_setLocation, METH_VARARGS,
"Set the object's location. The first argument must be a vector\n\
triple."},
{"setMaterials", ( PyCFunction ) Object_setMaterials, METH_VARARGS,
"Sets materials. The argument must be a list of valid material\n\
objects."},
{"setName", ( PyCFunction ) Object_setName, METH_VARARGS,
"Sets the name of the object"},
{"setSize", ( PyCFunction ) Object_setSize, METH_VARARGS,
"Set the object's size. The first argument must be a vector\n\
triple."},
{"setTimeOffset", ( PyCFunction ) Object_setTimeOffset, METH_VARARGS,
"Set the object's time offset."},
{"makeTrack", ( PyCFunction ) Object_makeTrack, METH_VARARGS,
"(trackedobj, fast = 0) - Make this object track another.\n\
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
(trackedobj) - the object that will be tracked.\n\
(fast = 0) - if 0: update the scene hierarchy automatically. If you\n\
set 'fast' to a nonzero value, don't forget to update the scene yourself\n\
(see scene.update())."},
{"shareFrom", ( PyCFunction ) Object_shareFrom, METH_VARARGS,
"Link data of self with object specified in the argument. This\n\
works only if self and the object specified are of the same type."},
{"select", ( PyCFunction ) Object_Select, METH_VARARGS,
"( 1 or 0 ) - Set the selected state of the object.\n\
1 is selected, 0 not selected "},
{"setIpo", ( PyCFunction ) Object_setIpo, METH_VARARGS,
"(Blender Ipo) - Sets the object's ipo"},
{"clearIpo", ( PyCFunction ) Object_clearIpo, METH_NOARGS,
"() - Unlink ipo from this object"},
{"insertIpoKey", ( PyCFunction ) Object_insertIpoKey, METH_VARARGS,
"( Object IPO type ) - Inserts a key into IPO"},
{"getAllProperties", ( PyCFunction ) Object_getAllProperties,
METH_NOARGS,
"() - Get all the properties from this object"},
{"addProperty", ( PyCFunction ) Object_addProperty, METH_VARARGS,
"() - Add a property to this object"},
{"removeProperty", ( PyCFunction ) Object_removeProperty, METH_VARARGS,
"() - Remove a property from this object"},
{"getProperty", ( PyCFunction ) Object_getProperty, METH_VARARGS,
"() - Get a property from this object by name"},
{"removeAllProperties", ( PyCFunction ) Object_removeAllProperties,
METH_NOARGS,
"() - removeAll a properties from this object"},
{"copyAllPropertiesTo", ( PyCFunction ) Object_copyAllPropertiesTo,
METH_VARARGS,
"() - copy all properties from this object to another object"},
{"getScriptLinks", ( PyCFunction ) Object_getScriptLinks, METH_VARARGS,
"(eventname) - Get a list of this object's scriptlinks (Text names) "
"of the given type\n"
"(eventname) - string: FrameChanged, Redraw or Render."},
{"addScriptLink", ( PyCFunction ) Object_addScriptLink, METH_VARARGS,
"(text, evt) - Add a new object scriptlink.\n"
"(text) - string: an existing Blender Text name;\n"
"(evt) string: FrameChanged, Redraw or Render."},
{"clearScriptLinks", ( PyCFunction ) Object_clearScriptLinks,
METH_VARARGS,
"() - Delete all scriptlinks from this object.\n"
"([s1<,s2,s3...>]) - Delete specified scriptlinks from this object."},
{"setDupliVerts", ( PyCFunction ) Object_setDupliVerts,
METH_VARARGS, "() - set or reset duplicate child objects on all vertices"},
{NULL, NULL, 0, NULL}
};
/*****************************************************************************/
/* PythonTypeObject callback function prototypes */
/*****************************************************************************/
static void Object_dealloc( BPy_Object * obj );
static PyObject *Object_getAttr( BPy_Object * obj, char *name );
static int Object_setAttr( BPy_Object * obj, char *name, PyObject * v );
static PyObject *Object_repr( BPy_Object * obj );
static int Object_compare( BPy_Object * a, BPy_Object * b );
/*****************************************************************************/
/* Python TypeObject structure definition. */
/*****************************************************************************/
PyTypeObject Object_Type = {
PyObject_HEAD_INIT( NULL ) /* requred macro */
0, /* ob_size */
"Blender Object", /* tp_name */
sizeof( BPy_Object ), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
( destructor ) Object_dealloc, /* tp_dealloc */
0, /* tp_print */
( getattrfunc ) Object_getAttr, /* tp_getattr */
( setattrfunc ) Object_setAttr, /* tp_setattr */
( cmpfunc ) Object_compare, /* tp_compare */
( reprfunc ) Object_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_as_hash */
0, 0, 0, 0, 0, 0,
0, /* tp_doc */
0, 0, 0, 0, 0, 0,
BPy_Object_methods, /* tp_methods */
0, /* tp_members */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};
/*****************************************************************************/
/* Function: M_Object_New */
/* Python equivalent: Blender.Object.New */
/*****************************************************************************/
PyObject *M_Object_New( PyObject * self, PyObject * args )
{
struct Object *object;
BPy_Object *blen_object;
int type;
char *str_type;
char *name = NULL;
if( !PyArg_ParseTuple( args, "s|s", &str_type, &name ) ) {
EXPP_ReturnPyObjError( PyExc_TypeError,
"string expected as argument" );
return ( NULL );
}
if( strcmp( str_type, "Armature" ) == 0 )
type = OB_ARMATURE;
else if( strcmp( str_type, "Camera" ) == 0 )
type = OB_CAMERA;
else if( strcmp( str_type, "Curve" ) == 0 )
type = OB_CURVE;
else if (strcmp (str_type, "Text") == 0)
type = OB_FONT;
else if( strcmp( str_type, "Lamp" ) == 0 )
type = OB_LAMP;
else if( strcmp( str_type, "Lattice" ) == 0 )
type = OB_LATTICE;
else if( strcmp( str_type, "Mball" ) == 0 )
type = OB_MBALL;
else if( strcmp( str_type, "Mesh" ) == 0 )
type = OB_MESH;
else if( strcmp( str_type, "Surf" ) == 0 )
type = OB_SURF;
/* else if (strcmp (str_type, "Wave") == 0) type = OB_WAVE; */
else if( strcmp( str_type, "Empty" ) == 0 )
type = OB_EMPTY;
else {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"Unknown type specified" ) );
}
/* Create a new object. */
if( name == NULL ) {
/* No name is specified, set the name to the type of the object. */
name = str_type;
}
object = alloc_libblock( &( G.main->object ), ID_OB, name );
object->id.us = 0;
object->flag = 0;
object->type = (short)type;
/* transforms */
QuatOne( object->quat );
QuatOne( object->dquat );
object->col[3] = 1.0; // alpha
object->size[0] = object->size[1] = object->size[2] = 1.0;
object->loc[0] = object->loc[1] = object->loc[2] = 0.0;
Mat4One( object->parentinv );
Mat4One( object->obmat );
object->dt = OB_SHADED; // drawtype
if( U.flag & USER_MAT_ON_OB ) {
object->colbits = -1;
}
switch ( object->type ) {
case OB_CAMERA: /* fall through. */
case OB_LAMP:
object->trackflag = OB_NEGZ;
object->upflag = OB_POSY;
break;
default:
object->trackflag = OB_POSY;
object->upflag = OB_POSZ;
}
object->ipoflag = OB_OFFS_OB + OB_OFFS_PARENT;
/* duplivert settings */
object->dupon = 1;
object->dupoff = 0;
object->dupsta = 1;
object->dupend = 100;
/* Gameengine defaults */
object->mass = 1.0;
object->inertia = 1.0;
object->formfactor = 0.4f;
object->damping = 0.04f;
object->rdamping = 0.1f;
object->anisotropicFriction[0] = 1.0;
object->anisotropicFriction[1] = 1.0;
object->anisotropicFriction[2] = 1.0;
object->gameflag = OB_PROP;
object->lay = 1; // Layer, by default visible
G.totobj++;
object->data = NULL;
/* Create a Python object from it. */
blen_object =
( BPy_Object * ) PyObject_NEW( BPy_Object, &Object_Type );
blen_object->object = object;
return ( ( PyObject * ) blen_object );
}
/*****************************************************************************/
/* Function: M_Object_Get */
/* Python equivalent: Blender.Object.Get */
/*****************************************************************************/
PyObject *M_Object_Get( PyObject * self, PyObject * args )
{
struct Object *object;
BPy_Object *blen_object;
char *name = NULL;
PyArg_ParseTuple( args, "|s", &name );
if( name != NULL ) {
object = GetObjectByName( name );
if( object == NULL ) {
/* No object exists with the name specified in the argument name. */
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"Unknown object specified." ) );
}
blen_object =
( BPy_Object * ) PyObject_NEW( BPy_Object,
&Object_Type );
blen_object->object = object;
return ( ( PyObject * ) blen_object );
} else {
/* No argument has been given. Return a list of all objects. */
PyObject *obj_list;
Link *link;
int index;
obj_list = PyList_New( BLI_countlist( &( G.main->object ) ) );
if( obj_list == NULL ) {
return ( EXPP_ReturnPyObjError( PyExc_SystemError,
"List creation failed." ) );
}
link = G.main->object.first;
index = 0;
while( link ) {
object = ( Object * ) link;
blen_object =
( BPy_Object * ) PyObject_NEW( BPy_Object,
&Object_Type );
blen_object->object = object;
PyList_SetItem( obj_list, index,
( PyObject * ) blen_object );
index++;
link = link->next;
}
return ( obj_list );
}
}
/*****************************************************************************/
/* Function: M_Object_GetSelected */
/* Python equivalent: Blender.Object.GetSelected */
/*****************************************************************************/
static PyObject *M_Object_GetSelected( PyObject * self, PyObject * args )
{
BPy_Object *blen_object;
PyObject *list;
Base *base_iter;
if( G.vd == NULL ) {
// No 3d view has been initialized yet, simply return None
Py_INCREF( Py_None );
return Py_None;
}
list = PyList_New( 0 );
if( ( G.scene->basact ) &&
( ( G.scene->basact->flag & SELECT ) &&
( G.scene->basact->lay & G.vd->lay ) ) ) {
/* Active object is first in the list. */
blen_object =
( BPy_Object * ) PyObject_NEW( BPy_Object,
&Object_Type );
if( blen_object == NULL ) {
Py_DECREF( list );
Py_INCREF( Py_None );
return ( Py_None );
}
blen_object->object = G.scene->basact->object;
PyList_Append( list, ( PyObject * ) blen_object );
Py_DECREF( blen_object );
}
base_iter = G.scene->base.first;
while( base_iter ) {
if( ( ( base_iter->flag & SELECT ) &&
( base_iter->lay & G.vd->lay ) ) &&
( base_iter != G.scene->basact ) ) {
blen_object =
( BPy_Object * ) PyObject_NEW( BPy_Object,
&Object_Type );
if( blen_object == NULL ) {
Py_DECREF( list );
Py_INCREF( Py_None );
return ( Py_None );
}
blen_object->object = base_iter->object;
PyList_Append( list, ( PyObject * ) blen_object );
Py_DECREF( blen_object );
}
base_iter = base_iter->next;
}
return ( list );
}
/*****************************************************************************/
/* Function: initObject */
/*****************************************************************************/
PyObject *Object_Init( void )
{
PyObject *module;
Object_Type.ob_type = &PyType_Type;
module = Py_InitModule3( "Blender.Object", M_Object_methods,
M_Object_doc );
PyModule_AddIntConstant( module, "LOC", IPOKEY_LOC );
PyModule_AddIntConstant( module, "ROT", IPOKEY_ROT );
PyModule_AddIntConstant( module, "SIZE", IPOKEY_SIZE );
PyModule_AddIntConstant( module, "LOCROT", IPOKEY_LOCROT );
PyModule_AddIntConstant( module, "LOCROTSIZE", IPOKEY_LOCROTSIZE );
PyModule_AddIntConstant( module, "PI_STRENGTH", IPOKEY_PI_STRENGTH );
PyModule_AddIntConstant( module, "PI_FALLOFF", IPOKEY_PI_FALLOFF );
PyModule_AddIntConstant( module, "PI_SURFACEDAMP", IPOKEY_PI_SURFACEDAMP );
PyModule_AddIntConstant( module, "PI_RANDOMDAMP", IPOKEY_PI_RANDOMDAMP );
PyModule_AddIntConstant( module, "PI_PERM", IPOKEY_PI_PERM );
PyModule_AddIntConstant( module, "NONE",0 );
PyModule_AddIntConstant( module, "FORCE",PFIELD_FORCE );
PyModule_AddIntConstant( module, "VORTEX",PFIELD_VORTEX );
PyModule_AddIntConstant( module, "MAGNET",PFIELD_MAGNET );
PyModule_AddIntConstant( module, "WIND",PFIELD_WIND );
return ( module );
}
/*****************************************************************************/
/* Python BPy_Object methods: */
/*****************************************************************************/
static PyObject *Object_buildParts( BPy_Object * self )
2003-10-28 23:23:30 +00:00
{
void build_particle_system( Object * ob );
struct Object *obj = self->object;
2003-10-28 23:23:30 +00:00
build_particle_system( obj );
Py_INCREF( Py_None );
return ( Py_None );
}
static PyObject *Object_clearIpo( BPy_Object * self )
{
Object *ob = self->object;
Ipo *ipo = ( Ipo * ) ob->ipo;
if( ipo ) {
ID *id = &ipo->id;
if( id->us > 0 )
id->us--;
ob->ipo = NULL;
return EXPP_incr_ret_True();
}
return EXPP_incr_ret_False(); /* no ipo found */
}
static PyObject *Object_clrParent( BPy_Object * self, PyObject * args )
{
int mode = 0;
int fast = 0;
if( !PyArg_ParseTuple( args, "|ii", &mode, &fast ) ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected one or two integers as arguments" ) );
}
/* Remove the link only, the object is still in the scene. */
self->object->parent = NULL;
if( mode == 2 ) {
/* Keep transform */
apply_obmat( self->object );
}
if( !fast ) {
Result of 2 weeks of quiet coding work in Greece :) Aim was to get a total refresh of the animation system. This is needed because; - we need to upgrade it with 21st century features - current code is spaghetti/hack combo, and hides good design - it should become lag-free with using dependency graphs A full log, with complete code API/structure/design explanation will follow, that's a load of work... so here below the list with hot changes; - The entire object update system (matrices, geometry) is now centralized. Calls to where_is_object and makeDispList are forbidden, instead we tag objects 'changed' and let the depgraph code sort it out - Removed all old "Ika" code - Depgraph is aware of all relationships, including meta balls, constraints, bevelcurve, and so on. - Made depgraph aware of relation types and layers, to do smart flushing of 'changed' events. Nothing gets calculated too often! - Transform uses depgraph to detect changes - On frame-advance, depgraph flushes animated changes Armatures; Almost all armature related code has been fully built from scratch. It now reveils the original design much better, with a very clean implementation, lag free without even calculating each Bone more than once. Result is quite a speedup yes! Important to note is; 1) Armature is data containing the 'rest position' 2) Pose is the changes of rest position, and always on object level. That way more Objects can use same Pose. Also constraints are in Pose 3) Actions only contain the Ipos to change values in Poses. - Bones draw unrotated now - Drawing bones speedup enormously (10-20 times) - Bone selecting in EditMode, selection state is saved for PoseMode, and vice-versa - Undo in editmode - Bone renaming does vertexgroups, constraints, posechannels, actions, for all users of Armature in entire file - Added Bone renaming in NKey panel - Nkey PoseMode shows eulers now - EditMode and PoseMode now have 'active' bone too (last clicked) - Parenting in EditMode' CTRL+P, ALT+P, with nice options! - Pose is added in Outliner now, with showing that constraints are in the Pose, not Armature - Disconnected IK solving from constraints. It's a separate phase now, on top of the full Pose calculations - Pose itself has a dependency graph too, so evaluation order is lag free. TODO NOW; - Rotating in Posemode has incorrect inverse transform (Martin will fix) - Python Bone/Armature/Pose API disabled... needs full recode too (wait for my doc!) - Game engine will need upgrade too - Depgraph code needs revision, cleanup, can be much faster! (But, compliments for Jean-Luc, it works like a charm!) - IK changed, it now doesnt use previous position to advance to next position anymore. That system looks nice (no flips) but is not well suited for NLA and background render. TODO LATER; We now can do loadsa new nifty features as well; like: - Kill PoseMode (can be option for armatures itself) - Make B-Bones (Bezier, Bspline, like for spines) - Move all silly button level edit to 3d window (like CTRL+I = add IK) - Much better & informative drawing - Fix action/nla editors - Put all ipos in Actions (object, mesh key, lamp color) - Add hooks - Null bones - Much more advanced constraints... Bugfixes; - OGL render (view3d header) had wrong first frame on anim render - Ipo 'recording' mode had wrong playback speed - Vertex-key mode now sticks to show 'active key', until frame change -Ton-
2005-07-03 17:35:38 +00:00
DAG_scene_sort( G.scene );
}
Py_INCREF( Py_None );
return ( Py_None );
}
static PyObject *Object_clearTrack( BPy_Object * self, PyObject * args )
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
{
int mode = 0;
int fast = 0;
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
if( !PyArg_ParseTuple( args, "|ii", &mode, &fast ) ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected one or two integers as arguments" ) );
}
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
/* Remove the link only, the object is still in the scene. */
self->object->track = NULL;
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
if( mode ) {
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
/* Keep transform */
apply_obmat( self->object );
}
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
if( !fast ) {
Result of 2 weeks of quiet coding work in Greece :) Aim was to get a total refresh of the animation system. This is needed because; - we need to upgrade it with 21st century features - current code is spaghetti/hack combo, and hides good design - it should become lag-free with using dependency graphs A full log, with complete code API/structure/design explanation will follow, that's a load of work... so here below the list with hot changes; - The entire object update system (matrices, geometry) is now centralized. Calls to where_is_object and makeDispList are forbidden, instead we tag objects 'changed' and let the depgraph code sort it out - Removed all old "Ika" code - Depgraph is aware of all relationships, including meta balls, constraints, bevelcurve, and so on. - Made depgraph aware of relation types and layers, to do smart flushing of 'changed' events. Nothing gets calculated too often! - Transform uses depgraph to detect changes - On frame-advance, depgraph flushes animated changes Armatures; Almost all armature related code has been fully built from scratch. It now reveils the original design much better, with a very clean implementation, lag free without even calculating each Bone more than once. Result is quite a speedup yes! Important to note is; 1) Armature is data containing the 'rest position' 2) Pose is the changes of rest position, and always on object level. That way more Objects can use same Pose. Also constraints are in Pose 3) Actions only contain the Ipos to change values in Poses. - Bones draw unrotated now - Drawing bones speedup enormously (10-20 times) - Bone selecting in EditMode, selection state is saved for PoseMode, and vice-versa - Undo in editmode - Bone renaming does vertexgroups, constraints, posechannels, actions, for all users of Armature in entire file - Added Bone renaming in NKey panel - Nkey PoseMode shows eulers now - EditMode and PoseMode now have 'active' bone too (last clicked) - Parenting in EditMode' CTRL+P, ALT+P, with nice options! - Pose is added in Outliner now, with showing that constraints are in the Pose, not Armature - Disconnected IK solving from constraints. It's a separate phase now, on top of the full Pose calculations - Pose itself has a dependency graph too, so evaluation order is lag free. TODO NOW; - Rotating in Posemode has incorrect inverse transform (Martin will fix) - Python Bone/Armature/Pose API disabled... needs full recode too (wait for my doc!) - Game engine will need upgrade too - Depgraph code needs revision, cleanup, can be much faster! (But, compliments for Jean-Luc, it works like a charm!) - IK changed, it now doesnt use previous position to advance to next position anymore. That system looks nice (no flips) but is not well suited for NLA and background render. TODO LATER; We now can do loadsa new nifty features as well; like: - Kill PoseMode (can be option for armatures itself) - Make B-Bones (Bezier, Bspline, like for spines) - Move all silly button level edit to 3d window (like CTRL+I = add IK) - Much better & informative drawing - Fix action/nla editors - Put all ipos in Actions (object, mesh key, lamp color) - Add hooks - Null bones - Much more advanced constraints... Bugfixes; - OGL render (view3d header) had wrong first frame on anim render - Ipo 'recording' mode had wrong playback speed - Vertex-key mode now sticks to show 'active key', until frame change -Ton-
2005-07-03 17:35:38 +00:00
DAG_scene_sort( G.scene );
}
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
Py_INCREF( Py_None );
return ( Py_None );
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
}
/* adds object data to a Blender object, if object->data = NULL */
int EXPP_add_obdata( struct Object *object )
{
if( object->data != NULL )
return -1;
switch ( object->type ) {
case OB_ARMATURE:
/* TODO: Do we need to add something to G? (see the OB_LAMP case) */
object->data = add_armature( );
break;
case OB_CAMERA:
/* TODO: Do we need to add something to G? (see the OB_LAMP case) */
object->data = add_camera( );
break;
case OB_CURVE:
object->data = add_curve( OB_CURVE );
G.totcurve++;
break;
case OB_LAMP:
object->data = add_lamp( );
G.totlamp++;
break;
case OB_MESH:
object->data = add_mesh( );
G.totmesh++;
break;
case OB_LATTICE:
object->data = ( void * ) add_lattice( );
object->dt = OB_WIRE;
break;
case OB_MBALL:
object->data = add_mball( );
break;
/* TODO the following types will be supported later
case OB_SURF:
object->data = add_curve(OB_SURF);
G.totcurve++;
break;
case OB_FONT:
object->data = add_curve(OB_FONT);
break;
case OB_WAVE:
object->data = add_wave();
break;
*/
default:
break;
}
if( !object->data )
return -1;
return 0;
}
static PyObject *Object_getData( BPy_Object *self, PyObject *args, PyObject *kwd )
{
PyObject *data_object;
Object *object = self->object;
int name_only = 0;
static char *kwlist[] = {"name_only", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwd, "|i", kwlist, &name_only))
return EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected nothing or bool keyword 'name_only' as argument" );
/* if there's no obdata, try to create it */
if( object->data == NULL ) {
if( EXPP_add_obdata( object ) != 0 ) { /* couldn't create obdata */
Py_INCREF( Py_None );
return ( Py_None );
}
}
/* user wants only the name of the data object */
if (name_only) {
ID *id = object->data;
data_object = Py_BuildValue("s", id->name+2);
if (data_object) return data_object;
return EXPP_ReturnPyObjError (PyExc_MemoryError,
"could not create a string pyobject!");
}
/* user wants the data object wrapper */
data_object = NULL;
switch ( object->type ) {
case OB_ARMATURE:
data_object = Armature_CreatePyObject( object->data );
break;
case OB_CAMERA:
data_object = Camera_CreatePyObject( object->data );
break;
case OB_CURVE:
data_object = Curve_CreatePyObject( object->data );
break;
case ID_IM:
data_object = Image_CreatePyObject( object->data );
break;
case ID_IP:
data_object = Ipo_CreatePyObject( object->data );
break;
case OB_LAMP:
data_object = Lamp_CreatePyObject( object->data );
break;
case OB_LATTICE:
data_object = Lattice_CreatePyObject( object->data );
break;
case ID_MA:
break;
case OB_MESH:
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 OB_FONT:
data_object = Text3d_CreatePyObject( object->data );
break;
case ID_WO:
break;
default:
break;
}
if( data_object == NULL ) {
Py_INCREF( Py_None );
return ( Py_None );
} else {
return ( data_object );
}
}
static PyObject *Object_getDeltaLocation( BPy_Object * self )
{
PyObject *attr = Py_BuildValue( "fff",
self->object->dloc[0],
self->object->dloc[1],
self->object->dloc[2] );
if( attr )
return ( attr );
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object.dloc attributes" ) );
}
static PyObject *Object_getDrawMode( BPy_Object * self )
{
PyObject *attr = Py_BuildValue( "b", self->object->dtx );
if( attr )
return ( attr );
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object.drawMode attribute" ) );
}
static PyObject *Object_getAction( BPy_Object * self )
{
/*BPy_Action *py_action = NULL; */
if( !self->object->action ) {
Py_INCREF( Py_None );
return ( Py_None );
} else {
return Action_CreatePyObject( self->object->action );
}
}
static PyObject *Object_isSelected( BPy_Object * self )
{
Base *base;
base = FIRSTBASE;
while( base ) {
if( base->object == self->object ) {
if( base->flag & SELECT ) {
return EXPP_incr_ret_True();
} else {
return EXPP_incr_ret_False();
}
}
base = base->next;
}
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"Internal error: could not find objects selection state" ) );
}
static PyObject *Object_getDrawType( BPy_Object * self )
{
PyObject *attr = Py_BuildValue( "b", self->object->dt );
if( attr )
return ( attr );
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object.drawType attribute" ) );
}
static PyObject *Object_getEuler( BPy_Object * self )
{
Mathutils update - also included is some fixes for preprocessor inclues and some clean up of the previous commit -rewrite and bugfixes ---------------------------------- Here's my changelog: -fixed Rand() so that it doesn't seed everytime and should generate better random numbers - changed a few error return types to something more appropriate - clean up of uninitialized variables & removal of unneccessary objects - NMesh returns wrapped vectors now - World returns wrapped matrices now - Object.getEuler() and Object.getBoundingBox() return Wrapped data when data is present - Object.getMatrix() returns wrapped data if it's worldspace, 'localspace' returns a new matrix - Vector, Euler, Mat, Quat, call all now internally wrap object without destroying internal datablocks - Removed memory allocation (unneeded) from all methods - Vector's resize methods are only applicable to new vectors not wrapped data. - Matrix(), Quat(), Euler(), Vector() now accepts ANY sequence list, including tuples, list, or a self object to copy - matrices accept multiple sequences - Fixed Slerp() so that it now works correctly values are clamped between 0 and 1 - Euler.rotate does internal rotation now - Slice assignment now works better for all types - Vector * Vector and Quat * Quat are defined and return the DOT product - Mat * Vec and Vec * Mat are defined now - Moved #includes to .c file from headers. Also fixed prototypes in mathutils - Added new helper functions for incref'ing to genutils - Major cleanup of header files includes - include Mathutils.h for access to math types - matrix.toQuat() and .toEuler() now fixed take appropriate matrix sizes - Matrix() with no parameters now returns an identity matrix by default not a zero matrix - printf() now prints with 6 digits instead of 4 - printf() now prints output with object descriptor - Matrices now support [x][y] assignment (e.g. matrix[x][y] = 5.4) - Matrix[index] = value now expectes a sequence not an integer. This will now set a ROW of the matrix through a sequence. index cannot go above the row size of the matrix. - slice operations on matrices work with sequences now (rows of the matrix) example: mymatrix[0:2] returns a list of 2 wrapped vectors with access to the matrix data. - slice assignment will no longer modify the data if the assignment operation fails - fixed error in matrix * scalar multiplication - euler.toMatrix(), toQuat() no longer causes "creep" from repeated use - Wrapped data will generate wrapped objects when toEuler(), toQuat(), toMatrix() is used - Quats can be created with angle/axis, axis/angle - 4x4 matrices can be multiplied by 3D vectors (by popular demand :)) - vec *quat / quat * vec is now defined - vec.magnitude alias for vec.length - all self, internal methods return a pointer to self now so you can do print vector.internalmethod() or vector.internalmethod().nextmethod() (no more print matrix.inverse() returning 'none') - these methods have been deprecated (still functioning but suggested to use the corrected functionality): * CopyVec() - replaced by Vector() functionality * CopyMat() - replaced by Matrix() functionality * CopyQuat() - replace by Quaternion() functionality * CopyEuler() - replaced by Euler() functionality * RotateEuler() - replaced by Euler.rotate() funtionality * MatMultVec() - replaced by matrix * vector * VecMultMat() - replaced by vector * matrix - New struct containers references to python object data or internally allocated blender data for wrapping * Explaination here: math structs now function as a 'simple wrapper' or a 'py_object' - data that is created on the fly will now be a 'py_object' with its memory managed by python * otherwise if the data is returned by blender's G.main then the math object is a 'simple wrapper' and data can be accessed directly from the struct just like other python objects.
2005-07-14 03:34:56 +00:00
float eul[3];
Mathutils update - also included is some fixes for preprocessor inclues and some clean up of the previous commit -rewrite and bugfixes ---------------------------------- Here's my changelog: -fixed Rand() so that it doesn't seed everytime and should generate better random numbers - changed a few error return types to something more appropriate - clean up of uninitialized variables & removal of unneccessary objects - NMesh returns wrapped vectors now - World returns wrapped matrices now - Object.getEuler() and Object.getBoundingBox() return Wrapped data when data is present - Object.getMatrix() returns wrapped data if it's worldspace, 'localspace' returns a new matrix - Vector, Euler, Mat, Quat, call all now internally wrap object without destroying internal datablocks - Removed memory allocation (unneeded) from all methods - Vector's resize methods are only applicable to new vectors not wrapped data. - Matrix(), Quat(), Euler(), Vector() now accepts ANY sequence list, including tuples, list, or a self object to copy - matrices accept multiple sequences - Fixed Slerp() so that it now works correctly values are clamped between 0 and 1 - Euler.rotate does internal rotation now - Slice assignment now works better for all types - Vector * Vector and Quat * Quat are defined and return the DOT product - Mat * Vec and Vec * Mat are defined now - Moved #includes to .c file from headers. Also fixed prototypes in mathutils - Added new helper functions for incref'ing to genutils - Major cleanup of header files includes - include Mathutils.h for access to math types - matrix.toQuat() and .toEuler() now fixed take appropriate matrix sizes - Matrix() with no parameters now returns an identity matrix by default not a zero matrix - printf() now prints with 6 digits instead of 4 - printf() now prints output with object descriptor - Matrices now support [x][y] assignment (e.g. matrix[x][y] = 5.4) - Matrix[index] = value now expectes a sequence not an integer. This will now set a ROW of the matrix through a sequence. index cannot go above the row size of the matrix. - slice operations on matrices work with sequences now (rows of the matrix) example: mymatrix[0:2] returns a list of 2 wrapped vectors with access to the matrix data. - slice assignment will no longer modify the data if the assignment operation fails - fixed error in matrix * scalar multiplication - euler.toMatrix(), toQuat() no longer causes "creep" from repeated use - Wrapped data will generate wrapped objects when toEuler(), toQuat(), toMatrix() is used - Quats can be created with angle/axis, axis/angle - 4x4 matrices can be multiplied by 3D vectors (by popular demand :)) - vec *quat / quat * vec is now defined - vec.magnitude alias for vec.length - all self, internal methods return a pointer to self now so you can do print vector.internalmethod() or vector.internalmethod().nextmethod() (no more print matrix.inverse() returning 'none') - these methods have been deprecated (still functioning but suggested to use the corrected functionality): * CopyVec() - replaced by Vector() functionality * CopyMat() - replaced by Matrix() functionality * CopyQuat() - replace by Quaternion() functionality * CopyEuler() - replaced by Euler() functionality * RotateEuler() - replaced by Euler.rotate() funtionality * MatMultVec() - replaced by matrix * vector * VecMultMat() - replaced by vector * matrix - New struct containers references to python object data or internally allocated blender data for wrapping * Explaination here: math structs now function as a 'simple wrapper' or a 'py_object' - data that is created on the fly will now be a 'py_object' with its memory managed by python * otherwise if the data is returned by blender's G.main then the math object is a 'simple wrapper' and data can be accessed directly from the struct just like other python objects.
2005-07-14 03:34:56 +00:00
eul[0] = self->object->rot[0];
eul[1] = self->object->rot[1];
eul[2] = self->object->rot[2];
Mathutils update - also included is some fixes for preprocessor inclues and some clean up of the previous commit -rewrite and bugfixes ---------------------------------- Here's my changelog: -fixed Rand() so that it doesn't seed everytime and should generate better random numbers - changed a few error return types to something more appropriate - clean up of uninitialized variables & removal of unneccessary objects - NMesh returns wrapped vectors now - World returns wrapped matrices now - Object.getEuler() and Object.getBoundingBox() return Wrapped data when data is present - Object.getMatrix() returns wrapped data if it's worldspace, 'localspace' returns a new matrix - Vector, Euler, Mat, Quat, call all now internally wrap object without destroying internal datablocks - Removed memory allocation (unneeded) from all methods - Vector's resize methods are only applicable to new vectors not wrapped data. - Matrix(), Quat(), Euler(), Vector() now accepts ANY sequence list, including tuples, list, or a self object to copy - matrices accept multiple sequences - Fixed Slerp() so that it now works correctly values are clamped between 0 and 1 - Euler.rotate does internal rotation now - Slice assignment now works better for all types - Vector * Vector and Quat * Quat are defined and return the DOT product - Mat * Vec and Vec * Mat are defined now - Moved #includes to .c file from headers. Also fixed prototypes in mathutils - Added new helper functions for incref'ing to genutils - Major cleanup of header files includes - include Mathutils.h for access to math types - matrix.toQuat() and .toEuler() now fixed take appropriate matrix sizes - Matrix() with no parameters now returns an identity matrix by default not a zero matrix - printf() now prints with 6 digits instead of 4 - printf() now prints output with object descriptor - Matrices now support [x][y] assignment (e.g. matrix[x][y] = 5.4) - Matrix[index] = value now expectes a sequence not an integer. This will now set a ROW of the matrix through a sequence. index cannot go above the row size of the matrix. - slice operations on matrices work with sequences now (rows of the matrix) example: mymatrix[0:2] returns a list of 2 wrapped vectors with access to the matrix data. - slice assignment will no longer modify the data if the assignment operation fails - fixed error in matrix * scalar multiplication - euler.toMatrix(), toQuat() no longer causes "creep" from repeated use - Wrapped data will generate wrapped objects when toEuler(), toQuat(), toMatrix() is used - Quats can be created with angle/axis, axis/angle - 4x4 matrices can be multiplied by 3D vectors (by popular demand :)) - vec *quat / quat * vec is now defined - vec.magnitude alias for vec.length - all self, internal methods return a pointer to self now so you can do print vector.internalmethod() or vector.internalmethod().nextmethod() (no more print matrix.inverse() returning 'none') - these methods have been deprecated (still functioning but suggested to use the corrected functionality): * CopyVec() - replaced by Vector() functionality * CopyMat() - replaced by Matrix() functionality * CopyQuat() - replace by Quaternion() functionality * CopyEuler() - replaced by Euler() functionality * RotateEuler() - replaced by Euler.rotate() funtionality * MatMultVec() - replaced by matrix * vector * VecMultMat() - replaced by vector * matrix - New struct containers references to python object data or internally allocated blender data for wrapping * Explaination here: math structs now function as a 'simple wrapper' or a 'py_object' - data that is created on the fly will now be a 'py_object' with its memory managed by python * otherwise if the data is returned by blender's G.main then the math object is a 'simple wrapper' and data can be accessed directly from the struct just like other python objects.
2005-07-14 03:34:56 +00:00
return ( PyObject * ) newEulerObject( eul, Py_WRAP );
}
static PyObject *Object_getInverseMatrix( BPy_Object * self )
{
MatrixObject *inverse =
Mathutils update - also included is some fixes for preprocessor inclues and some clean up of the previous commit -rewrite and bugfixes ---------------------------------- Here's my changelog: -fixed Rand() so that it doesn't seed everytime and should generate better random numbers - changed a few error return types to something more appropriate - clean up of uninitialized variables & removal of unneccessary objects - NMesh returns wrapped vectors now - World returns wrapped matrices now - Object.getEuler() and Object.getBoundingBox() return Wrapped data when data is present - Object.getMatrix() returns wrapped data if it's worldspace, 'localspace' returns a new matrix - Vector, Euler, Mat, Quat, call all now internally wrap object without destroying internal datablocks - Removed memory allocation (unneeded) from all methods - Vector's resize methods are only applicable to new vectors not wrapped data. - Matrix(), Quat(), Euler(), Vector() now accepts ANY sequence list, including tuples, list, or a self object to copy - matrices accept multiple sequences - Fixed Slerp() so that it now works correctly values are clamped between 0 and 1 - Euler.rotate does internal rotation now - Slice assignment now works better for all types - Vector * Vector and Quat * Quat are defined and return the DOT product - Mat * Vec and Vec * Mat are defined now - Moved #includes to .c file from headers. Also fixed prototypes in mathutils - Added new helper functions for incref'ing to genutils - Major cleanup of header files includes - include Mathutils.h for access to math types - matrix.toQuat() and .toEuler() now fixed take appropriate matrix sizes - Matrix() with no parameters now returns an identity matrix by default not a zero matrix - printf() now prints with 6 digits instead of 4 - printf() now prints output with object descriptor - Matrices now support [x][y] assignment (e.g. matrix[x][y] = 5.4) - Matrix[index] = value now expectes a sequence not an integer. This will now set a ROW of the matrix through a sequence. index cannot go above the row size of the matrix. - slice operations on matrices work with sequences now (rows of the matrix) example: mymatrix[0:2] returns a list of 2 wrapped vectors with access to the matrix data. - slice assignment will no longer modify the data if the assignment operation fails - fixed error in matrix * scalar multiplication - euler.toMatrix(), toQuat() no longer causes "creep" from repeated use - Wrapped data will generate wrapped objects when toEuler(), toQuat(), toMatrix() is used - Quats can be created with angle/axis, axis/angle - 4x4 matrices can be multiplied by 3D vectors (by popular demand :)) - vec *quat / quat * vec is now defined - vec.magnitude alias for vec.length - all self, internal methods return a pointer to self now so you can do print vector.internalmethod() or vector.internalmethod().nextmethod() (no more print matrix.inverse() returning 'none') - these methods have been deprecated (still functioning but suggested to use the corrected functionality): * CopyVec() - replaced by Vector() functionality * CopyMat() - replaced by Matrix() functionality * CopyQuat() - replace by Quaternion() functionality * CopyEuler() - replaced by Euler() functionality * RotateEuler() - replaced by Euler.rotate() funtionality * MatMultVec() - replaced by matrix * vector * VecMultMat() - replaced by vector * matrix - New struct containers references to python object data or internally allocated blender data for wrapping * Explaination here: math structs now function as a 'simple wrapper' or a 'py_object' - data that is created on the fly will now be a 'py_object' with its memory managed by python * otherwise if the data is returned by blender's G.main then the math object is a 'simple wrapper' and data can be accessed directly from the struct just like other python objects.
2005-07-14 03:34:56 +00:00
( MatrixObject * ) newMatrixObject( NULL, 4, 4, Py_NEW);
Mat4Invert( (float ( * )[4])*inverse->matrix, self->object->obmat );
return ( ( PyObject * ) inverse );
}
static PyObject *Object_getIpo( BPy_Object * self )
{
struct Ipo *ipo = self->object->ipo;
if( !ipo ) {
Py_INCREF( Py_None );
return Py_None;
}
return Ipo_CreatePyObject( ipo );
}
static PyObject *Object_getLocation( BPy_Object * self, PyObject * args )
{
PyObject *attr = Py_BuildValue( "fff",
self->object->loc[0],
self->object->loc[1],
self->object->loc[2] );
if( attr )
return ( attr );
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object.loc attributes" ) );
}
static PyObject *Object_getMaterials( BPy_Object * self, PyObject * args )
{
int all = 0;
if( !PyArg_ParseTuple( args, "|i", &all ) ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected an int or nothing" ) );
}
return ( EXPP_PyList_fromMaterialList( self->object->mat,
self->object->totcol, all ) );
}
static PyObject *Object_getMatrix( BPy_Object * self, PyObject * args )
{
Mathutils update - also included is some fixes for preprocessor inclues and some clean up of the previous commit -rewrite and bugfixes ---------------------------------- Here's my changelog: -fixed Rand() so that it doesn't seed everytime and should generate better random numbers - changed a few error return types to something more appropriate - clean up of uninitialized variables & removal of unneccessary objects - NMesh returns wrapped vectors now - World returns wrapped matrices now - Object.getEuler() and Object.getBoundingBox() return Wrapped data when data is present - Object.getMatrix() returns wrapped data if it's worldspace, 'localspace' returns a new matrix - Vector, Euler, Mat, Quat, call all now internally wrap object without destroying internal datablocks - Removed memory allocation (unneeded) from all methods - Vector's resize methods are only applicable to new vectors not wrapped data. - Matrix(), Quat(), Euler(), Vector() now accepts ANY sequence list, including tuples, list, or a self object to copy - matrices accept multiple sequences - Fixed Slerp() so that it now works correctly values are clamped between 0 and 1 - Euler.rotate does internal rotation now - Slice assignment now works better for all types - Vector * Vector and Quat * Quat are defined and return the DOT product - Mat * Vec and Vec * Mat are defined now - Moved #includes to .c file from headers. Also fixed prototypes in mathutils - Added new helper functions for incref'ing to genutils - Major cleanup of header files includes - include Mathutils.h for access to math types - matrix.toQuat() and .toEuler() now fixed take appropriate matrix sizes - Matrix() with no parameters now returns an identity matrix by default not a zero matrix - printf() now prints with 6 digits instead of 4 - printf() now prints output with object descriptor - Matrices now support [x][y] assignment (e.g. matrix[x][y] = 5.4) - Matrix[index] = value now expectes a sequence not an integer. This will now set a ROW of the matrix through a sequence. index cannot go above the row size of the matrix. - slice operations on matrices work with sequences now (rows of the matrix) example: mymatrix[0:2] returns a list of 2 wrapped vectors with access to the matrix data. - slice assignment will no longer modify the data if the assignment operation fails - fixed error in matrix * scalar multiplication - euler.toMatrix(), toQuat() no longer causes "creep" from repeated use - Wrapped data will generate wrapped objects when toEuler(), toQuat(), toMatrix() is used - Quats can be created with angle/axis, axis/angle - 4x4 matrices can be multiplied by 3D vectors (by popular demand :)) - vec *quat / quat * vec is now defined - vec.magnitude alias for vec.length - all self, internal methods return a pointer to self now so you can do print vector.internalmethod() or vector.internalmethod().nextmethod() (no more print matrix.inverse() returning 'none') - these methods have been deprecated (still functioning but suggested to use the corrected functionality): * CopyVec() - replaced by Vector() functionality * CopyMat() - replaced by Matrix() functionality * CopyQuat() - replace by Quaternion() functionality * CopyEuler() - replaced by Euler() functionality * RotateEuler() - replaced by Euler.rotate() funtionality * MatMultVec() - replaced by matrix * vector * VecMultMat() - replaced by vector * matrix - New struct containers references to python object data or internally allocated blender data for wrapping * Explaination here: math structs now function as a 'simple wrapper' or a 'py_object' - data that is created on the fly will now be a 'py_object' with its memory managed by python * otherwise if the data is returned by blender's G.main then the math object is a 'simple wrapper' and data can be accessed directly from the struct just like other python objects.
2005-07-14 03:34:56 +00:00
float matrix[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
char *space = "worldspace"; /* default to world */
if( !PyArg_ParseTuple( args, "|s", &space ) ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected a string or nothing" ) );
}
if( BLI_streq( space, "worldspace" ) ) { /* Worldspace matrix */
disable_where_script( 1 );
where_is_object( self->object );
disable_where_script( 0 );
} else if( BLI_streq( space, "localspace" ) ) { /* Localspace matrix */
Mathutils update - also included is some fixes for preprocessor inclues and some clean up of the previous commit -rewrite and bugfixes ---------------------------------- Here's my changelog: -fixed Rand() so that it doesn't seed everytime and should generate better random numbers - changed a few error return types to something more appropriate - clean up of uninitialized variables & removal of unneccessary objects - NMesh returns wrapped vectors now - World returns wrapped matrices now - Object.getEuler() and Object.getBoundingBox() return Wrapped data when data is present - Object.getMatrix() returns wrapped data if it's worldspace, 'localspace' returns a new matrix - Vector, Euler, Mat, Quat, call all now internally wrap object without destroying internal datablocks - Removed memory allocation (unneeded) from all methods - Vector's resize methods are only applicable to new vectors not wrapped data. - Matrix(), Quat(), Euler(), Vector() now accepts ANY sequence list, including tuples, list, or a self object to copy - matrices accept multiple sequences - Fixed Slerp() so that it now works correctly values are clamped between 0 and 1 - Euler.rotate does internal rotation now - Slice assignment now works better for all types - Vector * Vector and Quat * Quat are defined and return the DOT product - Mat * Vec and Vec * Mat are defined now - Moved #includes to .c file from headers. Also fixed prototypes in mathutils - Added new helper functions for incref'ing to genutils - Major cleanup of header files includes - include Mathutils.h for access to math types - matrix.toQuat() and .toEuler() now fixed take appropriate matrix sizes - Matrix() with no parameters now returns an identity matrix by default not a zero matrix - printf() now prints with 6 digits instead of 4 - printf() now prints output with object descriptor - Matrices now support [x][y] assignment (e.g. matrix[x][y] = 5.4) - Matrix[index] = value now expectes a sequence not an integer. This will now set a ROW of the matrix through a sequence. index cannot go above the row size of the matrix. - slice operations on matrices work with sequences now (rows of the matrix) example: mymatrix[0:2] returns a list of 2 wrapped vectors with access to the matrix data. - slice assignment will no longer modify the data if the assignment operation fails - fixed error in matrix * scalar multiplication - euler.toMatrix(), toQuat() no longer causes "creep" from repeated use - Wrapped data will generate wrapped objects when toEuler(), toQuat(), toMatrix() is used - Quats can be created with angle/axis, axis/angle - 4x4 matrices can be multiplied by 3D vectors (by popular demand :)) - vec *quat / quat * vec is now defined - vec.magnitude alias for vec.length - all self, internal methods return a pointer to self now so you can do print vector.internalmethod() or vector.internalmethod().nextmethod() (no more print matrix.inverse() returning 'none') - these methods have been deprecated (still functioning but suggested to use the corrected functionality): * CopyVec() - replaced by Vector() functionality * CopyMat() - replaced by Matrix() functionality * CopyQuat() - replace by Quaternion() functionality * CopyEuler() - replaced by Euler() functionality * RotateEuler() - replaced by Euler.rotate() funtionality * MatMultVec() - replaced by matrix * vector * VecMultMat() - replaced by vector * matrix - New struct containers references to python object data or internally allocated blender data for wrapping * Explaination here: math structs now function as a 'simple wrapper' or a 'py_object' - data that is created on the fly will now be a 'py_object' with its memory managed by python * otherwise if the data is returned by blender's G.main then the math object is a 'simple wrapper' and data can be accessed directly from the struct just like other python objects.
2005-07-14 03:34:56 +00:00
object_to_mat4( self->object, (float (*)[4])matrix );
return newMatrixObject(matrix,4,4,Py_NEW);
} else if( BLI_streq( space, "old_worldspace" ) ) {
Mathutils update - also included is some fixes for preprocessor inclues and some clean up of the previous commit -rewrite and bugfixes ---------------------------------- Here's my changelog: -fixed Rand() so that it doesn't seed everytime and should generate better random numbers - changed a few error return types to something more appropriate - clean up of uninitialized variables & removal of unneccessary objects - NMesh returns wrapped vectors now - World returns wrapped matrices now - Object.getEuler() and Object.getBoundingBox() return Wrapped data when data is present - Object.getMatrix() returns wrapped data if it's worldspace, 'localspace' returns a new matrix - Vector, Euler, Mat, Quat, call all now internally wrap object without destroying internal datablocks - Removed memory allocation (unneeded) from all methods - Vector's resize methods are only applicable to new vectors not wrapped data. - Matrix(), Quat(), Euler(), Vector() now accepts ANY sequence list, including tuples, list, or a self object to copy - matrices accept multiple sequences - Fixed Slerp() so that it now works correctly values are clamped between 0 and 1 - Euler.rotate does internal rotation now - Slice assignment now works better for all types - Vector * Vector and Quat * Quat are defined and return the DOT product - Mat * Vec and Vec * Mat are defined now - Moved #includes to .c file from headers. Also fixed prototypes in mathutils - Added new helper functions for incref'ing to genutils - Major cleanup of header files includes - include Mathutils.h for access to math types - matrix.toQuat() and .toEuler() now fixed take appropriate matrix sizes - Matrix() with no parameters now returns an identity matrix by default not a zero matrix - printf() now prints with 6 digits instead of 4 - printf() now prints output with object descriptor - Matrices now support [x][y] assignment (e.g. matrix[x][y] = 5.4) - Matrix[index] = value now expectes a sequence not an integer. This will now set a ROW of the matrix through a sequence. index cannot go above the row size of the matrix. - slice operations on matrices work with sequences now (rows of the matrix) example: mymatrix[0:2] returns a list of 2 wrapped vectors with access to the matrix data. - slice assignment will no longer modify the data if the assignment operation fails - fixed error in matrix * scalar multiplication - euler.toMatrix(), toQuat() no longer causes "creep" from repeated use - Wrapped data will generate wrapped objects when toEuler(), toQuat(), toMatrix() is used - Quats can be created with angle/axis, axis/angle - 4x4 matrices can be multiplied by 3D vectors (by popular demand :)) - vec *quat / quat * vec is now defined - vec.magnitude alias for vec.length - all self, internal methods return a pointer to self now so you can do print vector.internalmethod() or vector.internalmethod().nextmethod() (no more print matrix.inverse() returning 'none') - these methods have been deprecated (still functioning but suggested to use the corrected functionality): * CopyVec() - replaced by Vector() functionality * CopyMat() - replaced by Matrix() functionality * CopyQuat() - replace by Quaternion() functionality * CopyEuler() - replaced by Euler() functionality * RotateEuler() - replaced by Euler.rotate() funtionality * MatMultVec() - replaced by matrix * vector * VecMultMat() - replaced by vector * matrix - New struct containers references to python object data or internally allocated blender data for wrapping * Explaination here: math structs now function as a 'simple wrapper' or a 'py_object' - data that is created on the fly will now be a 'py_object' with its memory managed by python * otherwise if the data is returned by blender's G.main then the math object is a 'simple wrapper' and data can be accessed directly from the struct just like other python objects.
2005-07-14 03:34:56 +00:00
/* old behavior, prior to 2.34, check this method's doc string: */
} else {
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"wrong parameter, expected nothing or either 'worldspace' (default),\n\
'localspace' or 'old_worldspace'" ) );
}
Mathutils update - also included is some fixes for preprocessor inclues and some clean up of the previous commit -rewrite and bugfixes ---------------------------------- Here's my changelog: -fixed Rand() so that it doesn't seed everytime and should generate better random numbers - changed a few error return types to something more appropriate - clean up of uninitialized variables & removal of unneccessary objects - NMesh returns wrapped vectors now - World returns wrapped matrices now - Object.getEuler() and Object.getBoundingBox() return Wrapped data when data is present - Object.getMatrix() returns wrapped data if it's worldspace, 'localspace' returns a new matrix - Vector, Euler, Mat, Quat, call all now internally wrap object without destroying internal datablocks - Removed memory allocation (unneeded) from all methods - Vector's resize methods are only applicable to new vectors not wrapped data. - Matrix(), Quat(), Euler(), Vector() now accepts ANY sequence list, including tuples, list, or a self object to copy - matrices accept multiple sequences - Fixed Slerp() so that it now works correctly values are clamped between 0 and 1 - Euler.rotate does internal rotation now - Slice assignment now works better for all types - Vector * Vector and Quat * Quat are defined and return the DOT product - Mat * Vec and Vec * Mat are defined now - Moved #includes to .c file from headers. Also fixed prototypes in mathutils - Added new helper functions for incref'ing to genutils - Major cleanup of header files includes - include Mathutils.h for access to math types - matrix.toQuat() and .toEuler() now fixed take appropriate matrix sizes - Matrix() with no parameters now returns an identity matrix by default not a zero matrix - printf() now prints with 6 digits instead of 4 - printf() now prints output with object descriptor - Matrices now support [x][y] assignment (e.g. matrix[x][y] = 5.4) - Matrix[index] = value now expectes a sequence not an integer. This will now set a ROW of the matrix through a sequence. index cannot go above the row size of the matrix. - slice operations on matrices work with sequences now (rows of the matrix) example: mymatrix[0:2] returns a list of 2 wrapped vectors with access to the matrix data. - slice assignment will no longer modify the data if the assignment operation fails - fixed error in matrix * scalar multiplication - euler.toMatrix(), toQuat() no longer causes "creep" from repeated use - Wrapped data will generate wrapped objects when toEuler(), toQuat(), toMatrix() is used - Quats can be created with angle/axis, axis/angle - 4x4 matrices can be multiplied by 3D vectors (by popular demand :)) - vec *quat / quat * vec is now defined - vec.magnitude alias for vec.length - all self, internal methods return a pointer to self now so you can do print vector.internalmethod() or vector.internalmethod().nextmethod() (no more print matrix.inverse() returning 'none') - these methods have been deprecated (still functioning but suggested to use the corrected functionality): * CopyVec() - replaced by Vector() functionality * CopyMat() - replaced by Matrix() functionality * CopyQuat() - replace by Quaternion() functionality * CopyEuler() - replaced by Euler() functionality * RotateEuler() - replaced by Euler.rotate() funtionality * MatMultVec() - replaced by matrix * vector * VecMultMat() - replaced by vector * matrix - New struct containers references to python object data or internally allocated blender data for wrapping * Explaination here: math structs now function as a 'simple wrapper' or a 'py_object' - data that is created on the fly will now be a 'py_object' with its memory managed by python * otherwise if the data is returned by blender's G.main then the math object is a 'simple wrapper' and data can be accessed directly from the struct just like other python objects.
2005-07-14 03:34:56 +00:00
return newMatrixObject((float*)self->object->obmat,4,4,Py_WRAP);
}
static PyObject *Object_getName( BPy_Object * self )
{
PyObject *attr = Py_BuildValue( "s", self->object->id.name + 2 );
if( attr )
return ( attr );
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get the name of the Object" ) );
}
static PyObject *Object_getParent( BPy_Object * self )
{
PyObject *attr;
if( self->object->parent == NULL )
return EXPP_incr_ret( Py_None );
attr = Object_CreatePyObject( self->object->parent );
if( attr ) {
return ( attr );
}
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object.parent attribute" ) );
}
static PyObject *Object_getParentBoneName( BPy_Object * self )
{
PyObject *attr;
if( self->object->parent == NULL )
return EXPP_incr_ret( Py_None );
if( self->object->parsubstr[0] == '\0' )
return EXPP_incr_ret( Py_None );
attr = Py_BuildValue( "s", self->object->parsubstr );
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"Failed to get parent bone name" ) );
}
static PyObject *Object_getSize( BPy_Object * self, PyObject * args )
{
PyObject *attr = Py_BuildValue( "fff",
self->object->size[0],
self->object->size[1],
self->object->size[2] );
if( attr )
return ( attr );
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object.size attributes" ) );
}
static PyObject *Object_getTimeOffset( BPy_Object * self )
{
PyObject *attr = Py_BuildValue( "f", self->object->sf );
if( attr )
return ( attr );
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object.sf attributes" ) );
}
static PyObject *Object_getTracked( BPy_Object * self )
{
PyObject *attr;
if( self->object->track == NULL )
return EXPP_incr_ret( Py_None );
attr = Object_CreatePyObject( self->object->track );
if( attr ) {
return ( attr );
}
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object.track attribute" ) );
}
static PyObject *Object_getType( BPy_Object * self )
{
switch ( self->object->type ) {
case OB_ARMATURE:
return ( Py_BuildValue( "s", "Armature" ) );
case OB_CAMERA:
return ( Py_BuildValue( "s", "Camera" ) );
case OB_CURVE:
return ( Py_BuildValue( "s", "Curve" ) );
case OB_EMPTY:
return ( Py_BuildValue( "s", "Empty" ) );
case OB_FONT:
return ( Py_BuildValue( "s", "Text" ) );
case OB_LAMP:
return ( Py_BuildValue( "s", "Lamp" ) );
case OB_LATTICE:
return ( Py_BuildValue( "s", "Lattice" ) );
case OB_MBALL:
return ( Py_BuildValue( "s", "MBall" ) );
case OB_MESH:
return ( Py_BuildValue( "s", "Mesh" ) );
case OB_SURF:
return ( Py_BuildValue( "s", "Surf" ) );
case OB_WAVE:
return ( Py_BuildValue( "s", "Wave" ) );
default:
return ( Py_BuildValue( "s", "unknown" ) );
}
}
static PyObject *Object_getBoundBox( BPy_Object * self )
{
int i;
float *vec = NULL;
PyObject *vector, *bbox;
if( !self->object->data )
return EXPP_ReturnPyObjError( PyExc_AttributeError,
"This object isn't linked to any object data (mesh, curve, etc) yet" );
if( !self->object->bb ) { /* if no ob bbox, we look in obdata */
Mesh *me;
Curve *curve;
switch ( self->object->type ) {
case OB_MESH:
me = self->object->data;
vec = (float*) mesh_get_bb(me)->vec;
break;
case OB_CURVE:
case OB_FONT:
case OB_SURF:
curve = self->object->data;
if( !curve->bb )
tex_space_curve( curve );
vec = ( float * ) curve->bb->vec;
break;
default:
Py_INCREF( Py_None );
return Py_None;
}
{ /* transform our obdata bbox by the obmat.
the obmat is 4x4 homogeneous coords matrix.
each bbox coord is xyz, so we make it homogenous
by padding it with w=1.0 and doing the matrix mult.
afterwards we divide by w to get back to xyz.
*/
/* printmatrix4( "obmat", self->object->obmat); */
float tmpvec[4]; /* tmp vector for homogenous coords math */
int i;
float *from;
bbox = PyList_New( 8 );
if( !bbox )
return EXPP_ReturnPyObjError
( PyExc_MemoryError,
"couldn't create pylist" );
for( i = 0, from = vec; i < 8; i++, from += 3 ) {
memcpy( tmpvec, from, 3 * sizeof( float ) );
tmpvec[3] = 1.0f; /* set w coord */
Mat4MulVec4fl( self->object->obmat, tmpvec );
/* divide x,y,z by w */
tmpvec[0] /= tmpvec[3];
tmpvec[1] /= tmpvec[3];
tmpvec[2] /= tmpvec[3];
#if 0
{ /* debug print stuff */
int i;
printf( "\nobj bbox transformed\n" );
for( i = 0; i < 4; ++i )
printf( "%f ", tmpvec[i] );
printf( "\n" );
}
#endif
/* because our bounding box is calculated and
does not have its own memory,
we must create vectors that allocate space */
Mathutils update - also included is some fixes for preprocessor inclues and some clean up of the previous commit -rewrite and bugfixes ---------------------------------- Here's my changelog: -fixed Rand() so that it doesn't seed everytime and should generate better random numbers - changed a few error return types to something more appropriate - clean up of uninitialized variables & removal of unneccessary objects - NMesh returns wrapped vectors now - World returns wrapped matrices now - Object.getEuler() and Object.getBoundingBox() return Wrapped data when data is present - Object.getMatrix() returns wrapped data if it's worldspace, 'localspace' returns a new matrix - Vector, Euler, Mat, Quat, call all now internally wrap object without destroying internal datablocks - Removed memory allocation (unneeded) from all methods - Vector's resize methods are only applicable to new vectors not wrapped data. - Matrix(), Quat(), Euler(), Vector() now accepts ANY sequence list, including tuples, list, or a self object to copy - matrices accept multiple sequences - Fixed Slerp() so that it now works correctly values are clamped between 0 and 1 - Euler.rotate does internal rotation now - Slice assignment now works better for all types - Vector * Vector and Quat * Quat are defined and return the DOT product - Mat * Vec and Vec * Mat are defined now - Moved #includes to .c file from headers. Also fixed prototypes in mathutils - Added new helper functions for incref'ing to genutils - Major cleanup of header files includes - include Mathutils.h for access to math types - matrix.toQuat() and .toEuler() now fixed take appropriate matrix sizes - Matrix() with no parameters now returns an identity matrix by default not a zero matrix - printf() now prints with 6 digits instead of 4 - printf() now prints output with object descriptor - Matrices now support [x][y] assignment (e.g. matrix[x][y] = 5.4) - Matrix[index] = value now expectes a sequence not an integer. This will now set a ROW of the matrix through a sequence. index cannot go above the row size of the matrix. - slice operations on matrices work with sequences now (rows of the matrix) example: mymatrix[0:2] returns a list of 2 wrapped vectors with access to the matrix data. - slice assignment will no longer modify the data if the assignment operation fails - fixed error in matrix * scalar multiplication - euler.toMatrix(), toQuat() no longer causes "creep" from repeated use - Wrapped data will generate wrapped objects when toEuler(), toQuat(), toMatrix() is used - Quats can be created with angle/axis, axis/angle - 4x4 matrices can be multiplied by 3D vectors (by popular demand :)) - vec *quat / quat * vec is now defined - vec.magnitude alias for vec.length - all self, internal methods return a pointer to self now so you can do print vector.internalmethod() or vector.internalmethod().nextmethod() (no more print matrix.inverse() returning 'none') - these methods have been deprecated (still functioning but suggested to use the corrected functionality): * CopyVec() - replaced by Vector() functionality * CopyMat() - replaced by Matrix() functionality * CopyQuat() - replace by Quaternion() functionality * CopyEuler() - replaced by Euler() functionality * RotateEuler() - replaced by Euler.rotate() funtionality * MatMultVec() - replaced by matrix * vector * VecMultMat() - replaced by vector * matrix - New struct containers references to python object data or internally allocated blender data for wrapping * Explaination here: math structs now function as a 'simple wrapper' or a 'py_object' - data that is created on the fly will now be a 'py_object' with its memory managed by python * otherwise if the data is returned by blender's G.main then the math object is a 'simple wrapper' and data can be accessed directly from the struct just like other python objects.
2005-07-14 03:34:56 +00:00
vector = newVectorObject( NULL, 3, Py_NEW);
memcpy( ( ( VectorObject * ) vector )->vec,
tmpvec, 3 * sizeof( float ) );
PyList_SET_ITEM( bbox, i, vector );
}
}
} else { /* the ob bbox exists */
vec = ( float * ) self->object->bb->vec;
if( !vec )
return EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't retrieve bounding box data" );
bbox = PyList_New( 8 );
if( !bbox )
return EXPP_ReturnPyObjError( PyExc_MemoryError,
"couldn't create pylist" );
/* create vectors referencing object bounding box coords */
for( i = 0; i < 8; i++ ) {
Mathutils update - also included is some fixes for preprocessor inclues and some clean up of the previous commit -rewrite and bugfixes ---------------------------------- Here's my changelog: -fixed Rand() so that it doesn't seed everytime and should generate better random numbers - changed a few error return types to something more appropriate - clean up of uninitialized variables & removal of unneccessary objects - NMesh returns wrapped vectors now - World returns wrapped matrices now - Object.getEuler() and Object.getBoundingBox() return Wrapped data when data is present - Object.getMatrix() returns wrapped data if it's worldspace, 'localspace' returns a new matrix - Vector, Euler, Mat, Quat, call all now internally wrap object without destroying internal datablocks - Removed memory allocation (unneeded) from all methods - Vector's resize methods are only applicable to new vectors not wrapped data. - Matrix(), Quat(), Euler(), Vector() now accepts ANY sequence list, including tuples, list, or a self object to copy - matrices accept multiple sequences - Fixed Slerp() so that it now works correctly values are clamped between 0 and 1 - Euler.rotate does internal rotation now - Slice assignment now works better for all types - Vector * Vector and Quat * Quat are defined and return the DOT product - Mat * Vec and Vec * Mat are defined now - Moved #includes to .c file from headers. Also fixed prototypes in mathutils - Added new helper functions for incref'ing to genutils - Major cleanup of header files includes - include Mathutils.h for access to math types - matrix.toQuat() and .toEuler() now fixed take appropriate matrix sizes - Matrix() with no parameters now returns an identity matrix by default not a zero matrix - printf() now prints with 6 digits instead of 4 - printf() now prints output with object descriptor - Matrices now support [x][y] assignment (e.g. matrix[x][y] = 5.4) - Matrix[index] = value now expectes a sequence not an integer. This will now set a ROW of the matrix through a sequence. index cannot go above the row size of the matrix. - slice operations on matrices work with sequences now (rows of the matrix) example: mymatrix[0:2] returns a list of 2 wrapped vectors with access to the matrix data. - slice assignment will no longer modify the data if the assignment operation fails - fixed error in matrix * scalar multiplication - euler.toMatrix(), toQuat() no longer causes "creep" from repeated use - Wrapped data will generate wrapped objects when toEuler(), toQuat(), toMatrix() is used - Quats can be created with angle/axis, axis/angle - 4x4 matrices can be multiplied by 3D vectors (by popular demand :)) - vec *quat / quat * vec is now defined - vec.magnitude alias for vec.length - all self, internal methods return a pointer to self now so you can do print vector.internalmethod() or vector.internalmethod().nextmethod() (no more print matrix.inverse() returning 'none') - these methods have been deprecated (still functioning but suggested to use the corrected functionality): * CopyVec() - replaced by Vector() functionality * CopyMat() - replaced by Matrix() functionality * CopyQuat() - replace by Quaternion() functionality * CopyEuler() - replaced by Euler() functionality * RotateEuler() - replaced by Euler.rotate() funtionality * MatMultVec() - replaced by matrix * vector * VecMultMat() - replaced by vector * matrix - New struct containers references to python object data or internally allocated blender data for wrapping * Explaination here: math structs now function as a 'simple wrapper' or a 'py_object' - data that is created on the fly will now be a 'py_object' with its memory managed by python * otherwise if the data is returned by blender's G.main then the math object is a 'simple wrapper' and data can be accessed directly from the struct just like other python objects.
2005-07-14 03:34:56 +00:00
vector = newVectorObject( vec, 3, Py_WRAP );
PyList_SET_ITEM( bbox, i, vector );
vec += 3;
}
}
return bbox;
}
static PyObject *Object_makeDisplayList( BPy_Object * self )
{
Object *ob = self->object;
if( ob->type == OB_FONT )
text_to_curve( ob, 0 );
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
Py_INCREF( Py_None );
return Py_None;
}
static PyObject *Object_link( BPy_Object * self, PyObject * args )
{
PyObject *py_data;
ID *id;
ID *oldid;
int obj_id;
void *data = NULL;
if( !PyArg_ParseTuple( args, "O", &py_data ) ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected an object as argument" ) );
}
if( Armature_CheckPyObject( py_data ) )
data = ( void * ) Armature_FromPyObject( py_data );
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 );
if( Text3d_CheckPyObject( py_data ) )
data = ( void * ) Text3d_FromPyObject( py_data );
/* have we set data to something good? */
if( !data ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"link argument type is not supported " ) );
}
oldid = ( ID * ) self->object->data;
id = ( ID * ) data;
obj_id = MAKE_ID2( id->name[0], id->name[1] );
switch ( obj_id ) {
case ID_AR:
if( self->object->type != OB_ARMATURE ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"The 'link' object is incompatible with the base object" ) );
}
break;
case ID_CA:
if( self->object->type != OB_CAMERA ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"The 'link' object is incompatible with the base object" ) );
}
break;
case ID_LA:
if( self->object->type != OB_LAMP ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"The 'link' object is incompatible with the base object" ) );
}
break;
case ID_ME:
if( self->object->type != OB_MESH ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"The 'link' object is incompatible with the base object" ) );
}
break;
case ID_CU:
if( self->object->type != OB_CURVE && self->object->type != OB_FONT ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"The 'link' object is incompatible with the base object" ) );
}
break;
case ID_LT:
if( self->object->type != OB_LATTICE ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"The 'link' object is incompatible with the base object" ) );
}
break;
case ID_MB:
if( self->object->type != OB_MBALL ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"The 'link' object is incompatible with the base object" ) );
}
break;
default:
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"Linking this object type is not supported" ) );
}
self->object->data = data;
if( self->object->type == OB_MESH ) {
self->object->totcol = 0;
EXPP_synchronizeMaterialLists( self->object );
}
//creates the curve for the text object
if (self->object->type == OB_FONT)
text_to_curve(self->object, 0);
id_us_plus( id );
if( oldid ) {
if( oldid->us > 0 ) {
oldid->us--;
} else {
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"old object reference count below 0" ) );
}
}
return EXPP_incr_ret( Py_None );
}
static PyObject *Object_makeParentVertex( BPy_Object * self, PyObject * args )
{
PyObject *list;
PyObject *vlist;
PyObject *py_child;
PyObject *ret_val;
Object *parent;
int noninverse = 0;
int fast = 0;
int partype;
int v1, v2=0, v3=0;
int i, vlen;
/* Check if the arguments passed to makeParent are valid. */
if( !PyArg_ParseTuple( args, "OO|ii", &list, &vlist, &noninverse, &fast ) ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected a list of objects, a tuple of integers and one or two integers as arguments" ) );
}
if( !PySequence_Check( list ) ) {
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
"expected a list of objects" ) );
}
if (!PyTuple_Check( vlist ))
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
"expected a tuple of integers" ) );
vlen = PyTuple_Size( vlist );
switch (vlen) {
case 1:
if( !PyArg_ParseTuple( vlist, "i", &v1 ) )
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
"expected a tuple of 1 or 3 integers" ) );
if ( v1 < 0 )
return ( EXPP_ReturnPyObjError( PyExc_ValueError,
"indices must be strictly positive" ) );
partype = PARVERT1;
break;
case 3:
if( !PyArg_ParseTuple( vlist, "iii", &v1, &v2, &v3 ) )
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
"expected a tuple of 1 or 3 integers" ) );
if ( v1 < 0 || v2 < 0 || v3 < 0)
return ( EXPP_ReturnPyObjError( PyExc_ValueError,
"indices must be strictly positive" ) );
partype = PARVERT3;
break;
default:
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
"expected a tuple of 1 or 3 integers" ) );
}
parent = ( Object * ) self->object;
if (!ELEM3(parent->type, OB_MESH, OB_CURVE, OB_SURF))
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
"Parent Vertex only applies to curve, mesh or surface objects" ) );
if (parent->id.us == 0)
return EXPP_ReturnPyObjError (PyExc_RuntimeError,
"object must be linked to a scene before it can become a parent");
/* Check if the PyObject passed in list is a Blender object. */
for( i = 0; i < PySequence_Length( list ); i++ ) {
py_child = PySequence_GetItem( list, i );
ret_val = internal_makeParent(parent, py_child, partype, noninverse, fast, v1, v2, v3);
Py_DECREF (py_child);
if (ret_val)
Py_DECREF(ret_val);
else {
if (!fast) /* need to sort when interupting in the middle of the list */
DAG_scene_sort( G.scene );
return NULL; /* error has been set already */
}
}
if (!fast) /* otherwise, only sort at the end */
DAG_scene_sort( G.scene );
return EXPP_incr_ret( Py_None );
}
static PyObject *Object_makeParentDeform( BPy_Object * self, PyObject * args )
{
PyObject *list;
PyObject *py_child;
PyObject *ret_val;
Object *parent;
int noninverse = 0;
int fast = 0;
int i;
/* Check if the arguments passed to makeParent are valid. */
if( !PyArg_ParseTuple( args, "O|ii", &list, &noninverse, &fast ) ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected a list of objects and one or two integers as arguments" ) );
}
if( !PySequence_Check( list ) ) {
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
"expected a list of objects" ) );
}
parent = ( Object * ) self->object;
if (parent->type != OB_CURVE && parent->type != OB_ARMATURE)
return ( EXPP_ReturnPyObjError( PyExc_ValueError,
"Parent Deform only applies to curve or armature objects" ) );
if (parent->id.us == 0)
return EXPP_ReturnPyObjError (PyExc_RuntimeError,
"object must be linked to a scene before it can become a parent");
/* Check if the PyObject passed in list is a Blender object. */
for( i = 0; i < PySequence_Length( list ); i++ ) {
py_child = PySequence_GetItem( list, i );
ret_val = internal_makeParent(parent, py_child, PARSKEL, noninverse, fast, 0, 0, 0);
Py_DECREF (py_child);
if (ret_val)
Py_DECREF(ret_val);
else {
if (!fast) /* need to sort when interupting in the middle of the list */
DAG_scene_sort( G.scene );
return NULL; /* error has been set already */
}
}
if (!fast) /* otherwise, only sort at the end */
DAG_scene_sort( G.scene );
return EXPP_incr_ret( Py_None );
}
static PyObject *Object_makeParent( BPy_Object * self, PyObject * args )
{
PyObject *list;
PyObject *py_child;
PyObject *ret_val;
Object *parent;
int noninverse = 0;
int fast = 0;
int i;
/* Check if the arguments passed to makeParent are valid. */
if( !PyArg_ParseTuple( args, "O|ii", &list, &noninverse, &fast ) ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected a list of objects and one or two integers as arguments" ) );
}
if( !PySequence_Check( list ) ) {
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
"expected a list of objects" ) );
}
parent = ( Object * ) self->object;
if (parent->id.us == 0)
return EXPP_ReturnPyObjError (PyExc_RuntimeError,
"object must be linked to a scene before it can become a parent");
/* Check if the PyObject passed in list is a Blender object. */
for( i = 0; i < PySequence_Length( list ); i++ ) {
py_child = PySequence_GetItem( list, i );
ret_val = internal_makeParent(parent, py_child, PAROBJECT, noninverse, fast, 0, 0, 0);
Py_DECREF (py_child);
if (ret_val)
Py_DECREF(ret_val);
else {
if (!fast) /* need to sort when interupting in the middle of the list */
DAG_scene_sort( G.scene );
return NULL; /* error has been set already */
}
}
if (!fast) /* otherwise, only sort at the end */
DAG_scene_sort( G.scene );
return EXPP_incr_ret( Py_None );
}
static PyObject *internal_makeParent(Object *parent, PyObject *py_child,
int partype, /* parenting type */
int noninverse, int fast, /* parenting arguments */
int v1, int v2, int v3 /* for vertex parent */
)
{
Object *child = NULL;
if( Object_CheckPyObject( py_child ) )
child = ( Object * ) Object_FromPyObject( py_child );
if( child == NULL ) {
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
"Object Type expected" ) );
}
if( test_parent_loop( parent, child ) ) {
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"parenting loop detected - parenting failed" ) );
}
if (partype == PARSKEL && child->type != OB_MESH)
child->partype = PAROBJECT;
else
child->partype = (short)partype;
if (partype == PARVERT3) {
child->par1 = v1;
child->par2 = v2;
child->par3 = v3;
}
else if (partype == PARVERT1) {
child->par1 = v1;
}
child->parent = parent;
//py_obj_child = (BPy_Object *) py_child;
if( noninverse == 1 ) {
/* Parent inverse = unity */
child->loc[0] = 0.0;
child->loc[1] = 0.0;
child->loc[2] = 0.0;
} else {
what_does_parent( child );
Mat4Invert( child->parentinv, workob.obmat );
clear_workob();
}
if( !fast ) {
child->recalc |= OB_RECALC_OB;
}
return EXPP_incr_ret( Py_None );
}
static PyObject *Object_materialUsage( BPy_Object * self, PyObject * args )
{
return ( EXPP_ReturnPyObjError( PyExc_NotImplementedError,
"materialUsage: not yet implemented" ) );
}
static PyObject *Object_setDeltaLocation( BPy_Object * self, PyObject * args )
{
float dloc1;
float dloc2;
float dloc3;
int status;
if( PyObject_Length( args ) == 3 )
status = PyArg_ParseTuple( args, "fff", &dloc1, &dloc2,
&dloc3 );
else
status = PyArg_ParseTuple( args, "(fff)", &dloc1, &dloc2,
&dloc3 );
if( !status )
return EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected list argument of 3 floats" );
self->object->dloc[0] = dloc1;
self->object->dloc[1] = dloc2;
self->object->dloc[2] = dloc3;
Py_INCREF( Py_None );
return ( Py_None );
}
static PyObject *Object_setDrawMode( BPy_Object * self, PyObject * args )
{
char dtx;
if( !PyArg_ParseTuple( args, "b", &dtx ) ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected an integer as argument" ) );
}
self->object->dtx = dtx;
Py_INCREF( Py_None );
return ( Py_None );
}
static PyObject *Object_setDrawType( BPy_Object * self, PyObject * args )
{
char dt;
if( !PyArg_ParseTuple( args, "b", &dt ) ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected an integer as argument" ) );
}
self->object->dt = dt;
Py_INCREF( Py_None );
return ( Py_None );
}
static PyObject *Object_setEuler( BPy_Object * self, PyObject * args )
{
float rot1 = 0.0f;
float rot2 = 0.0f;
float rot3 = 0.0f;
int status = 0; /* failure */
PyObject *ob;
/*
args is either a tuple/list of floats or an euler.
for backward compatibility, we also accept 3 floats.
*/
/* do we have 3 floats? */
if( PyObject_Length( args ) == 3 ) {
status = PyArg_ParseTuple( args, "fff", &rot1, &rot2, &rot3 );
} else { //test to see if it's a list or a euler
if( PyArg_ParseTuple( args, "O", &ob ) ) {
if( EulerObject_Check( ob ) ) {
rot1 = ( ( EulerObject * ) ob )->eul[0];
rot2 = ( ( EulerObject * ) ob )->eul[1];
rot3 = ( ( EulerObject * ) ob )->eul[2];
status = 1; /* success! */
} else if( PySequence_Check( ob ) )
status = PyArg_ParseTuple( args, "(fff)",
&rot1, &rot2,
&rot3 );
else { /* not an euler or tuple */
/* python C api doc says don't decref this */
/*Py_DECREF (ob); */
status = 0; /* false */
}
} else { /* arg parsing failed */
status = 0;
}
}
if( !status ) /* parsing args failed */
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected euler or list/tuple of 3 floats " ) );
self->object->rot[0] = rot1;
self->object->rot[1] = rot2;
self->object->rot[2] = rot3;
Py_INCREF( Py_None );
return ( Py_None );
}
static PyObject *Object_setMatrix( BPy_Object * self, PyObject * args )
{
MatrixObject *mat;
int x, y;
if( !PyArg_ParseTuple( args, "O!", &matrix_Type, &mat ) )
return EXPP_ReturnPyObjError
( PyExc_TypeError,
"expected matrix object as argument" );
for( x = 0; x < 4; x++ ) {
for( y = 0; y < 4; y++ ) {
self->object->obmat[x][y] = mat->matrix[x][y];
}
}
apply_obmat( self->object );
Py_INCREF( Py_None );
return ( Py_None );
}
static PyObject *Object_setIpo( BPy_Object * self, PyObject * args )
{
PyObject *pyipo = 0;
Ipo *ipo = NULL;
Ipo *oldipo;
if( !PyArg_ParseTuple( args, "O!", &Ipo_Type, &pyipo ) )
return EXPP_ReturnPyObjError( PyExc_TypeError,
"expected Ipo as argument" );
ipo = Ipo_FromPyObject( pyipo );
if( !ipo )
return EXPP_ReturnPyObjError( PyExc_RuntimeError,
"null ipo!" );
if( ipo->blocktype != ID_OB )
return EXPP_ReturnPyObjError( PyExc_TypeError,
"this ipo is not an object ipo" );
oldipo = self->object->ipo;
if( oldipo ) {
ID *id = &oldipo->id;
if( id->us > 0 )
id->us--;
}
( ( ID * ) & ipo->id )->us++;
self->object->ipo = ipo;
Py_INCREF( Py_None );
return Py_None;
}
/*
* Object_insertIpoKey()
* inserts Object IPO key for LOC, ROT, SIZE, LOCROT, or LOCROTSIZE
*/
static PyObject *Object_insertIpoKey( BPy_Object * self, PyObject * args )
{
int key = 0;
if( !PyArg_ParseTuple( args, "i", &( key ) ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected int argument" ) );
if (key == IPOKEY_LOC || key == IPOKEY_LOCROT || key == IPOKEY_LOCROTSIZE){
insertkey((ID *)self->object,OB_LOC_X);
insertkey((ID *)self->object,OB_LOC_Y);
insertkey((ID *)self->object,OB_LOC_Z);
}
if (key == IPOKEY_ROT || key == IPOKEY_LOCROT || key == IPOKEY_LOCROTSIZE){
insertkey((ID *)self->object,OB_ROT_X);
insertkey((ID *)self->object,OB_ROT_Y);
insertkey((ID *)self->object,OB_ROT_Z);
}
if (key == IPOKEY_SIZE || key == IPOKEY_LOCROTSIZE ){
insertkey((ID *)self->object,OB_SIZE_X);
insertkey((ID *)self->object,OB_SIZE_Y);
insertkey((ID *)self->object,OB_SIZE_Z);
}
if (key == IPOKEY_PI_STRENGTH ){
insertkey((ID *)self->object, OB_PD_FSTR);
}
if (key == IPOKEY_PI_FALLOFF ){
insertkey((ID *)self->object, OB_PD_FFALL);
}
if (key == IPOKEY_PI_SURFACEDAMP ){
insertkey((ID *)self->object, OB_PD_SDAMP);
}
if (key == IPOKEY_PI_RANDOMDAMP ){
insertkey((ID *)self->object, OB_PD_RDAMP);
}
if (key == IPOKEY_PI_PERM ){
insertkey((ID *)self->object, OB_PD_PERM);
}
allspace(REMAKEIPO, 0);
EXPP_allqueue(REDRAWIPO, 0);
EXPP_allqueue(REDRAWVIEW3D, 0);
EXPP_allqueue(REDRAWACTION, 0);
EXPP_allqueue(REDRAWNLA, 0);
return EXPP_incr_ret( Py_None );
}
static PyObject *Object_setLocation( BPy_Object * self, PyObject * args )
{
float loc1;
float loc2;
float loc3;
int status;
if( PyObject_Length( args ) == 3 )
status = PyArg_ParseTuple( args, "fff", &loc1, &loc2, &loc3 );
else
status = PyArg_ParseTuple( args, "(fff)", &loc1, &loc2,
&loc3 );
if( !status )
return EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected list argument of 3 floats" );
self->object->loc[0] = loc1;
self->object->loc[1] = loc2;
self->object->loc[2] = loc3;
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 = (char)len;
self->object->actcol = (char)len;
switch ( self->object->type ) {
case OB_CURVE: /* fall through */
case OB_FONT: /* fall through */
case OB_MESH: /* fall through */
case OB_MBALL: /* fall through */
case OB_SURF:
EXPP_synchronizeMaterialLists( self->object );
break;
default:
break;
}
}
return EXPP_incr_ret( Py_None );
}
static PyObject *Object_setName( BPy_Object * self, PyObject * args )
{
char *name;
char buf[21];
if( !PyArg_ParseTuple( args, "s", &name ) ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected a String as argument" ) );
}
PyOS_snprintf( buf, sizeof( buf ), "%s", name );
rename_id( &self->object->id, buf );
Py_INCREF( Py_None );
return ( Py_None );
}
static PyObject *Object_setSize( BPy_Object * self, PyObject * args )
{
float sizex;
float sizey;
float sizez;
int status;
if( PyObject_Length( args ) == 3 )
status = PyArg_ParseTuple( args, "fff", &sizex, &sizey,
&sizez );
else
status = PyArg_ParseTuple( args, "(fff)", &sizex, &sizey,
&sizez );
if( !status )
return EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected list argument of 3 floats" );
self->object->size[0] = sizex;
self->object->size[1] = sizey;
self->object->size[2] = sizez;
Py_INCREF( Py_None );
return ( Py_None );
}
static PyObject *Object_setTimeOffset( BPy_Object * self, PyObject * args )
{
float newTimeOffset;
if( !PyArg_ParseTuple( args, "f", &newTimeOffset ) ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected a float as argument" ) );
}
self->object->sf = newTimeOffset;
Py_INCREF( Py_None );
return ( Py_None );
}
static PyObject *Object_makeTrack( BPy_Object * self, PyObject * args )
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
{
BPy_Object *tracked = NULL;
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
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." );
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
ob->track = tracked->object;
if( !fast )
Result of 2 weeks of quiet coding work in Greece :) Aim was to get a total refresh of the animation system. This is needed because; - we need to upgrade it with 21st century features - current code is spaghetti/hack combo, and hides good design - it should become lag-free with using dependency graphs A full log, with complete code API/structure/design explanation will follow, that's a load of work... so here below the list with hot changes; - The entire object update system (matrices, geometry) is now centralized. Calls to where_is_object and makeDispList are forbidden, instead we tag objects 'changed' and let the depgraph code sort it out - Removed all old "Ika" code - Depgraph is aware of all relationships, including meta balls, constraints, bevelcurve, and so on. - Made depgraph aware of relation types and layers, to do smart flushing of 'changed' events. Nothing gets calculated too often! - Transform uses depgraph to detect changes - On frame-advance, depgraph flushes animated changes Armatures; Almost all armature related code has been fully built from scratch. It now reveils the original design much better, with a very clean implementation, lag free without even calculating each Bone more than once. Result is quite a speedup yes! Important to note is; 1) Armature is data containing the 'rest position' 2) Pose is the changes of rest position, and always on object level. That way more Objects can use same Pose. Also constraints are in Pose 3) Actions only contain the Ipos to change values in Poses. - Bones draw unrotated now - Drawing bones speedup enormously (10-20 times) - Bone selecting in EditMode, selection state is saved for PoseMode, and vice-versa - Undo in editmode - Bone renaming does vertexgroups, constraints, posechannels, actions, for all users of Armature in entire file - Added Bone renaming in NKey panel - Nkey PoseMode shows eulers now - EditMode and PoseMode now have 'active' bone too (last clicked) - Parenting in EditMode' CTRL+P, ALT+P, with nice options! - Pose is added in Outliner now, with showing that constraints are in the Pose, not Armature - Disconnected IK solving from constraints. It's a separate phase now, on top of the full Pose calculations - Pose itself has a dependency graph too, so evaluation order is lag free. TODO NOW; - Rotating in Posemode has incorrect inverse transform (Martin will fix) - Python Bone/Armature/Pose API disabled... needs full recode too (wait for my doc!) - Game engine will need upgrade too - Depgraph code needs revision, cleanup, can be much faster! (But, compliments for Jean-Luc, it works like a charm!) - IK changed, it now doesnt use previous position to advance to next position anymore. That system looks nice (no flips) but is not well suited for NLA and background render. TODO LATER; We now can do loadsa new nifty features as well; like: - Kill PoseMode (can be option for armatures itself) - Make B-Bones (Bezier, Bspline, like for spines) - Move all silly button level edit to 3d window (like CTRL+I = add IK) - Much better & informative drawing - Fix action/nla editors - Put all ipos in Actions (object, mesh key, lamp color) - Add hooks - Null bones - Much more advanced constraints... Bugfixes; - OGL render (view3d header) had wrong first frame on anim render - Ipo 'recording' mode had wrong playback speed - Vertex-key mode now sticks to show 'active key', until frame change -Ton-
2005-07-03 17:35:38 +00:00
DAG_scene_sort( G.scene );
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
return EXPP_incr_ret( Py_None );
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
}
static PyObject *Object_shareFrom( BPy_Object * self, PyObject * args )
{
BPy_Object *object;
ID *id;
ID *oldid;
if( !PyArg_ParseTuple( args, "O", &object ) ) {
return EXPP_ReturnPyObjError( PyExc_TypeError,
"expected an object argument" );
}
if( !Object_CheckPyObject( ( PyObject * ) object ) ) {
return EXPP_ReturnPyObjError( PyExc_TypeError,
"first argument is not of type 'Object'" );
}
if( self->object->type != object->object->type ) {
return EXPP_ReturnPyObjError( PyExc_TypeError,
"objects are not of same data type" );
}
switch ( self->object->type ) {
case OB_MESH:
case OB_LAMP:
case OB_CAMERA: /* we can probably add the other types, too */
case OB_ARMATURE:
case OB_CURVE:
case OB_SURF:
case OB_LATTICE:
oldid = ( ID * ) self->object->data;
id = ( ID * ) object->object->data;
self->object->data = object->object->data;
if( self->object->type == OB_MESH && id ) {
self->object->totcol = 0;
EXPP_synchronizeMaterialLists( self->object );
}
id_us_plus( id );
if( oldid ) {
if( oldid->us > 0 ) {
oldid->us--;
} else {
return ( EXPP_ReturnPyObjError
( PyExc_RuntimeError,
"old object reference count below 0" ) );
}
}
Py_INCREF( Py_None );
return ( Py_None );
default:
return EXPP_ReturnPyObjError( PyExc_TypeError,
"type not supported" );
}
}
static PyObject *Object_Select( BPy_Object * self, PyObject * args )
{
Base *base;
int sel;
base = FIRSTBASE;
if( !PyArg_ParseTuple( args, "i", &sel ) )
return EXPP_ReturnPyObjError
( PyExc_TypeError, "expected an integer, 0 or 1" );
while( base ) {
if( base->object == self->object ) {
if( sel == 1 ) {
base->flag |= SELECT;
self->object->flag = (short)base->flag;
set_active_base( base );
} else {
base->flag &= ~SELECT;
self->object->flag = (short)base->flag;
}
break;
}
base = base->next;
}
countall( );
Py_INCREF( Py_None );
return ( Py_None );
}
static PyObject *Object_getAllProperties( BPy_Object * self )
{
PyObject *prop_list;
bProperty *prop = NULL;
prop_list = PyList_New( 0 );
prop = self->object->prop.first;
while( prop ) {
PyList_Append( prop_list, Property_CreatePyObject( prop ) );
prop = prop->next;
}
return prop_list;
}
static PyObject *Object_getProperty( BPy_Object * self, PyObject * args )
{
char *prop_name = NULL;
bProperty *prop = NULL;
PyObject *py_prop = Py_None;
if( !PyArg_ParseTuple( args, "s", &prop_name ) ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected a string" ) );
}
prop = get_property( self->object, prop_name );
if( prop ) {
py_prop = Property_CreatePyObject( prop );
} else {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"couldn't find the property...." ) );
}
return py_prop;
}
static PyObject *Object_addProperty( BPy_Object * self, PyObject * args )
{
bProperty *prop = NULL;
char *prop_name = NULL;
PyObject *prop_data = Py_None;
char *prop_type = NULL;
short type = -1;
BPy_Property *py_prop = NULL;
int argslen = PyObject_Length( args );
if( argslen == 3 || argslen == 2 ) {
if( !PyArg_ParseTuple
( args, "sO|s", &prop_name, &prop_data, &prop_type ) ) {
return ( EXPP_ReturnPyObjError
( PyExc_AttributeError,
"unable to get string, data, and optional string" ) );
}
} else if( argslen == 1 ) {
if( !PyArg_ParseTuple( args, "O!", &property_Type, &py_prop ) ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"unable to get Property" ) );
}
if( py_prop->property != NULL ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"Property is already added to an object" ) );
}
} else {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected 1,2 or 3 arguments" ) );
}
//parse property type
if( !py_prop ) {
if( prop_type ) {
if( BLI_streq( prop_type, "BOOL" ) )
type = PROP_BOOL;
else if( BLI_streq( prop_type, "INT" ) )
type = PROP_INT;
else if( BLI_streq( prop_type, "FLOAT" ) )
type = PROP_FLOAT;
else if( BLI_streq( prop_type, "TIME" ) )
type = PROP_TIME;
else if( BLI_streq( prop_type, "STRING" ) )
type = PROP_STRING;
else
return ( EXPP_ReturnPyObjError
( PyExc_RuntimeError,
"BOOL, INT, FLOAT, TIME or STRING expected" ) );
} else {
//use the default
if( PyInt_Check( prop_data ) )
type = PROP_INT;
else if( PyFloat_Check( prop_data ) )
type = PROP_FLOAT;
else if( PyString_Check( prop_data ) )
type = PROP_STRING;
}
} else {
type = py_prop->type;
}
//initialize a new bProperty of the specified type
prop = new_property( type );
//parse data
if( !py_prop ) {
BLI_strncpy( prop->name, prop_name, 32 );
if( PyInt_Check( prop_data ) ) {
*( ( int * ) &prop->data ) =
( int ) PyInt_AsLong( prop_data );
} else if( PyFloat_Check( prop_data ) ) {
*( ( float * ) &prop->data ) =
( float ) PyFloat_AsDouble( prop_data );
} else if( PyString_Check( prop_data ) ) {
BLI_strncpy( prop->poin,
PyString_AsString( prop_data ),
MAX_PROPSTRING );
}
} else {
py_prop->property = prop;
if( !updateProperyData( py_prop ) ) {
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"Could not update property data - error" ) );
}
}
//add to property listbase for the object
BLI_addtail( &self->object->prop, prop );
return EXPP_incr_ret( Py_None );
}
static PyObject *Object_removeProperty( BPy_Object * self, PyObject * args )
{
char *prop_name = NULL;
BPy_Property *py_prop = NULL;
bProperty *prop = NULL;
// we have property and no optional arg
if( !PyArg_ParseTuple( args, "O!", &property_Type, &py_prop ) ) {
if( !PyArg_ParseTuple( args, "s", &prop_name ) ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected a Property or a string" ) );
}
}
//remove the link, free the data, and update the py struct
if( py_prop ) {
BLI_remlink( &self->object->prop, py_prop->property );
if( updatePyProperty( py_prop ) ) {
free_property( py_prop->property );
py_prop->property = NULL;
}
} else {
prop = get_property( self->object, prop_name );
if( prop ) {
BLI_remlink( &self->object->prop, prop );
free_property( prop );
}
}
return EXPP_incr_ret( Py_None );
}
static PyObject *Object_removeAllProperties( BPy_Object * self )
{
free_properties( &self->object->prop );
return EXPP_incr_ret( Py_None );
}
static PyObject *Object_copyAllPropertiesTo( BPy_Object * self,
PyObject * args )
{
PyObject *dest = Py_None;
bProperty *prop = NULL;
bProperty *propn = NULL;
if( !PyArg_ParseTuple( args, "O!", &Object_Type, &dest ) ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected an Object" ) );
}
//make a copy of all it's properties
prop = self->object->prop.first;
while( prop ) {
propn = copy_property( prop );
BLI_addtail( &( ( BPy_Object * ) dest )->object->prop, propn );
prop = prop->next;
}
return EXPP_incr_ret( Py_None );
}
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
/* obj.addScriptLink */
static PyObject *Object_addScriptLink( BPy_Object * self, PyObject * args )
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
{
Object *obj = self->object;
ScriptLink *slink = NULL;
slink = &( obj )->scriptlink;
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
return EXPP_addScriptLink( slink, args, 0 );
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
}
/* obj.clearScriptLinks */
static PyObject *Object_clearScriptLinks( BPy_Object * self, PyObject * args )
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
{
Object *obj = self->object;
ScriptLink *slink = NULL;
slink = &( obj )->scriptlink;
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
return EXPP_clearScriptLinks( slink, args );
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
}
/* obj.getScriptLinks */
static PyObject *Object_getScriptLinks( BPy_Object * self, PyObject * args )
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
{
Object *obj = self->object;
ScriptLink *slink = NULL;
PyObject *ret = NULL;
slink = &( obj )->scriptlink;
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
ret = EXPP_getScriptLinks( slink, args, 0 );
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
if( ret )
return ret;
else
return NULL;
New scripts: - hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms); - bevel_center by Loic Berthe, suggested for inclusion by jms; - doc_browser, by Daniel Dunbar (Zr) Thanks to them for the new contributions! (I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?) BPython related: - Added scriptlink methods to object, lamp, camera and world. - Object: added object.makeTrack and object.clearTrack (old track method). - sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither. - doc updates and fixes. - made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data. - Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...) - Draw: added mouse wheel events. - Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate". The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
}
static PyObject *Object_getDupliVerts ( BPy_Object * self ) {
if (self->object->transflag & OB_DUPLIVERTS)
return EXPP_incr_ret_True ();
else
return EXPP_incr_ret_False();
}
static PyObject *Object_setDupliVerts ( BPy_Object * self, PyObject * args ) {
int setting= 0;
if( !PyArg_ParseTuple( args, "i", &setting ) ) {
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected a string") );
}
if (self && self->object) {
if (setting)
self->object->transflag |= OB_DUPLIVERTS;
else
self->object->transflag &= ~OB_DUPLIVERTS;
}
return Py_None;
}
/*****************************************************************************/
/* Function: Object_CreatePyObject */
/* Description: This function will create a new BlenObject from an existing */
/* Object structure. */
/*****************************************************************************/
PyObject *Object_CreatePyObject( struct Object * obj )
{
BPy_Object *blen_object;
if( !obj )
return EXPP_incr_ret( Py_None );
blen_object =
( BPy_Object * ) PyObject_NEW( BPy_Object, &Object_Type );
if( blen_object == NULL ) {
return ( NULL );
}
blen_object->object = obj;
return ( ( PyObject * ) blen_object );
}
/*****************************************************************************/
/* Function: Object_CheckPyObject */
/* Description: This function returns true when the given PyObject is of the */
/* type Object. Otherwise it will return false. */
/*****************************************************************************/
int Object_CheckPyObject( PyObject * py_obj )
{
return ( py_obj->ob_type == &Object_Type );
}
/*****************************************************************************/
/* Function: Object_FromPyObject */
/* Description: This function returns the Blender object from the given */
/* PyObject. */
/*****************************************************************************/
struct Object *Object_FromPyObject( PyObject * py_obj )
{
BPy_Object *blen_obj;
blen_obj = ( BPy_Object * ) py_obj;
return ( blen_obj->object );
}
/*****************************************************************************/
/* Description: Returns the object with the name specified by the argument */
/* name. Note that the calling function has to remove the first */
/* two characters of the object name. These two characters */
/* specify the type of the object (OB, ME, WO, ...) */
/* The function will return NULL when no object with the given */
/* name is found. */
/*****************************************************************************/
Object *GetObjectByName( char *name )
{
Object *obj_iter;
obj_iter = G.main->object.first;
while( obj_iter ) {
if( StringEqual( name, GetIdName( &( obj_iter->id ) ) ) ) {
return ( obj_iter );
}
obj_iter = obj_iter->id.next;
}
/* There is no object with the given name */
return ( NULL );
}
/*****************************************************************************/
/* Function: Object_dealloc */
/* Description: This is a callback function for the BlenObject type. It is */
/* the destructor function. */
/*****************************************************************************/
static void Object_dealloc( BPy_Object * obj )
{
PyObject_DEL( obj );
}
/*****************************************************************************/
/* Function: Object_getAttr */
/* Description: This is a callback function for the BlenObject type. It is */
/* the function that retrieves any value from Blender and */
/* passes it to Python. */
/*****************************************************************************/
static PyObject *Object_getAttr( BPy_Object * obj, char *name )
{
struct Object *object;
object = obj->object;
if( StringEqual( name, "LocX" ) )
return ( PyFloat_FromDouble( object->loc[0] ) );
if( StringEqual( name, "LocY" ) )
return ( PyFloat_FromDouble( object->loc[1] ) );
if( StringEqual( name, "LocZ" ) )
return ( PyFloat_FromDouble( object->loc[2] ) );
if( StringEqual( name, "loc" ) )
return ( Py_BuildValue( "fff", object->loc[0], object->loc[1],
object->loc[2] ) );
if( StringEqual( name, "dLocX" ) )
return ( PyFloat_FromDouble( object->dloc[0] ) );
if( StringEqual( name, "dLocY" ) )
return ( PyFloat_FromDouble( object->dloc[1] ) );
if( StringEqual( name, "dLocZ" ) )
return ( PyFloat_FromDouble( object->dloc[2] ) );
if( StringEqual( name, "dloc" ) )
return ( Py_BuildValue
( "fff", object->dloc[0], object->dloc[1],
object->dloc[2] ) );
if( StringEqual( name, "RotX" ) )
return ( PyFloat_FromDouble( object->rot[0] ) );
if( StringEqual( name, "RotY" ) )
return ( PyFloat_FromDouble( object->rot[1] ) );
if( StringEqual( name, "RotZ" ) )
return ( PyFloat_FromDouble( object->rot[2] ) );
if( StringEqual( name, "rot" ) )
return ( Py_BuildValue( "fff", object->rot[0], object->rot[1],
object->rot[2] ) );
if( StringEqual( name, "dRotX" ) )
return ( PyFloat_FromDouble( object->drot[0] ) );
if( StringEqual( name, "dRotY" ) )
return ( PyFloat_FromDouble( object->drot[1] ) );
if( StringEqual( name, "dRotZ" ) )
return ( PyFloat_FromDouble( object->drot[2] ) );
if( StringEqual( name, "drot" ) )
return ( Py_BuildValue
( "fff", object->drot[0], object->drot[1],
object->drot[2] ) );
if( StringEqual( name, "SizeX" ) )
return ( PyFloat_FromDouble( object->size[0] ) );
if( StringEqual( name, "SizeY" ) )
return ( PyFloat_FromDouble( object->size[1] ) );
if( StringEqual( name, "SizeZ" ) )
return ( PyFloat_FromDouble( object->size[2] ) );
if( StringEqual( name, "size" ) )
return ( Py_BuildValue
( "fff", object->size[0], object->size[1],
object->size[2] ) );
if( StringEqual( name, "dSizeX" ) )
return ( PyFloat_FromDouble( object->dsize[0] ) );
if( StringEqual( name, "dSizeY" ) )
return ( PyFloat_FromDouble( object->dsize[1] ) );
if( StringEqual( name, "dSizeZ" ) )
return ( PyFloat_FromDouble( object->dsize[2] ) );
if( StringEqual( name, "dsize" ) )
return ( Py_BuildValue
( "fff", object->dsize[0], object->dsize[1],
object->dsize[2] ) );
Result of 2 weeks of quiet coding work in Greece :) Aim was to get a total refresh of the animation system. This is needed because; - we need to upgrade it with 21st century features - current code is spaghetti/hack combo, and hides good design - it should become lag-free with using dependency graphs A full log, with complete code API/structure/design explanation will follow, that's a load of work... so here below the list with hot changes; - The entire object update system (matrices, geometry) is now centralized. Calls to where_is_object and makeDispList are forbidden, instead we tag objects 'changed' and let the depgraph code sort it out - Removed all old "Ika" code - Depgraph is aware of all relationships, including meta balls, constraints, bevelcurve, and so on. - Made depgraph aware of relation types and layers, to do smart flushing of 'changed' events. Nothing gets calculated too often! - Transform uses depgraph to detect changes - On frame-advance, depgraph flushes animated changes Armatures; Almost all armature related code has been fully built from scratch. It now reveils the original design much better, with a very clean implementation, lag free without even calculating each Bone more than once. Result is quite a speedup yes! Important to note is; 1) Armature is data containing the 'rest position' 2) Pose is the changes of rest position, and always on object level. That way more Objects can use same Pose. Also constraints are in Pose 3) Actions only contain the Ipos to change values in Poses. - Bones draw unrotated now - Drawing bones speedup enormously (10-20 times) - Bone selecting in EditMode, selection state is saved for PoseMode, and vice-versa - Undo in editmode - Bone renaming does vertexgroups, constraints, posechannels, actions, for all users of Armature in entire file - Added Bone renaming in NKey panel - Nkey PoseMode shows eulers now - EditMode and PoseMode now have 'active' bone too (last clicked) - Parenting in EditMode' CTRL+P, ALT+P, with nice options! - Pose is added in Outliner now, with showing that constraints are in the Pose, not Armature - Disconnected IK solving from constraints. It's a separate phase now, on top of the full Pose calculations - Pose itself has a dependency graph too, so evaluation order is lag free. TODO NOW; - Rotating in Posemode has incorrect inverse transform (Martin will fix) - Python Bone/Armature/Pose API disabled... needs full recode too (wait for my doc!) - Game engine will need upgrade too - Depgraph code needs revision, cleanup, can be much faster! (But, compliments for Jean-Luc, it works like a charm!) - IK changed, it now doesnt use previous position to advance to next position anymore. That system looks nice (no flips) but is not well suited for NLA and background render. TODO LATER; We now can do loadsa new nifty features as well; like: - Kill PoseMode (can be option for armatures itself) - Make B-Bones (Bezier, Bspline, like for spines) - Move all silly button level edit to 3d window (like CTRL+I = add IK) - Much better & informative drawing - Fix action/nla editors - Put all ipos in Actions (object, mesh key, lamp color) - Add hooks - Null bones - Much more advanced constraints... Bugfixes; - OGL render (view3d header) had wrong first frame on anim render - Ipo 'recording' mode had wrong playback speed - Vertex-key mode now sticks to show 'active key', until frame change -Ton-
2005-07-03 17:35:38 +00:00
/* accept both Layer (old, for compatibility) and Layers */
if( strncmp( name, "Layer", 5 ) == 0)
return ( PyInt_FromLong( object->lay ) );
/* Layers returns a bitmask, layers returns a list of integers */
if( StringEqual( name, "layers" ) ) {
int layers, bit = 0, val = 0;
PyObject *item = NULL, *laylist = PyList_New( 0 );
if( !laylist )
return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
"couldn't create pylist!" ) );
layers = object->lay;
while( bit < 20 ) {
val = 1 << bit;
if( layers & val ) {
item = Py_BuildValue( "i", bit + 1 );
PyList_Append( laylist, item );
Py_DECREF( item );
}
bit++;
}
return laylist;
}
if( StringEqual( name, "parent" ) ) {
if( object->parent )
return ( Object_CreatePyObject( object->parent ) );
else {
Py_INCREF( Py_None );
return ( Py_None );
}
}
if( StringEqual( name, "parentbonename" ) ) {
if( object->parent && object->parsubstr[0] )
return ( Py_BuildValue("s", object->parsubstr) );
else {
Py_INCREF( Py_None );
return ( Py_None );
}
}
if( StringEqual( name, "track" ) )
return ( Object_CreatePyObject( object->track ) );
if( StringEqual( name, "data" ) ) {
PyObject *getdata, *tuple = PyTuple_New(0);
if (!tuple)
return EXPP_ReturnPyObjError (PyExc_MemoryError,
"couldn't create an empty tuple!");
getdata = Object_getData( obj, tuple, NULL );
Py_DECREF(tuple);
return getdata;
}
if( StringEqual( name, "ipo" ) ) {
if( object->ipo == NULL ) {
/* There's no ipo linked to the object, return Py_None. */
Py_INCREF( Py_None );
return ( Py_None );
}
return ( Ipo_CreatePyObject( object->ipo ) );
}
if( StringEqual( name, "mat" ) || StringEqual( name, "matrix" ) )
return ( Object_getMatrix
( obj, Py_BuildValue( "(s)", "worldspace" ) ) );
if( StringEqual( name, "matrixWorld" ) )
return ( Object_getMatrix
( obj, Py_BuildValue( "(s)", "worldspace" ) ) );
if( StringEqual( name, "matrixLocal" ) )
return ( Object_getMatrix
( obj, Py_BuildValue( "(s)", "localspace" ) ) );
if( StringEqual( name, "colbits" ) )
return ( Py_BuildValue( "h", object->colbits ) );
if( StringEqual( name, "drawType" ) )
return ( Py_BuildValue( "b", object->dt ) );
if( StringEqual( name, "drawMode" ) )
return ( Py_BuildValue( "b", object->dtx ) );
if( StringEqual( name, "name" ) )
return ( Py_BuildValue( "s", object->id.name + 2 ) );
if( StringEqual( name, "sel" ) )
return ( Object_isSelected( obj ) );
if( StringEqual( name, "DupSta" ) )
return PyInt_FromLong( obj->object->dupsta );
if( StringEqual( name, "DupEnd" ) )
return PyInt_FromLong( obj->object->dupend );
if( StringEqual( name, "DupOn" ) )
return PyInt_FromLong( obj->object->dupon );
if( StringEqual( name, "DupOff" ) )
return PyInt_FromLong( obj->object->dupoff );
if( StringEqual( name, "Dupliframes" ) ){
if (obj->object->transflag & OB_DUPLIFRAMES)
return EXPP_incr_ret_True();
else
return EXPP_incr_ret_False();
}
if (StringEqual (name, "oopsLoc")) {
if (G.soops) {
Oops *oops= G.soops->oops.first;
while(oops) {
if(oops->type==ID_OB) {
if ((Object *)oops->id == object) {
return (Py_BuildValue ("ff", oops->x, oops->y));
}
}
oops= oops->next;
}
}
return EXPP_incr_ret( Py_None );
}
/* not an attribute, search the methods table */
return Py_FindMethod( BPy_Object_methods, ( PyObject * ) obj, name );
}
/*****************************************************************************/
/* Function: Object_setAttr */
/* Description: This is a callback function for the BlenObject type. It is */
/* the function that retrieves any value from Python and sets */
/* it accordingly in Blender. */
/*****************************************************************************/
static int Object_setAttr( BPy_Object * obj, char *name, PyObject * value )
{
PyObject *valtuple, *result=NULL;
struct Object *object;
object = obj->object;
/* Handle all properties which are Read Only */
if( StringEqual( name, "parent" ) )
return EXPP_ReturnIntError( PyExc_AttributeError,
"Setting the parent is not allowed." );
if( StringEqual( name, "data" ) )
return EXPP_ReturnIntError( PyExc_AttributeError,
"Setting the data is not allowed." );
if( StringEqual( name, "ipo" ) )
return EXPP_ReturnIntError( PyExc_AttributeError,
"Setting the ipo is not allowed." );
if( StringEqual( name, "mat" ) )
return EXPP_ReturnIntError( PyExc_AttributeError,
"Not allowed. Please use .setMatrix(matrix)" );
if( StringEqual( name, "matrix" ) )
return EXPP_ReturnIntError( PyExc_AttributeError,
"Not allowed. Please use .setMatrix(matrix)" );
/* FIRST, do attributes that are diretly changed */
if( StringEqual( name, "LocX" ) )
return ( !PyArg_Parse( value, "f", &( object->loc[0] ) ) );
if( StringEqual( name, "LocY" ) )
return ( !PyArg_Parse( value, "f", &( object->loc[1] ) ) );
if( StringEqual( name, "LocZ" ) )
return ( !PyArg_Parse( value, "f", &( object->loc[2] ) ) );
if( StringEqual( name, "dLocX" ) )
return ( !PyArg_Parse( value, "f", &( object->dloc[0] ) ) );
if( StringEqual( name, "dLocY" ) )
return ( !PyArg_Parse( value, "f", &( object->dloc[1] ) ) );
if( StringEqual( name, "dLocZ" ) )
return ( !PyArg_Parse( value, "f", &( object->dloc[2] ) ) );
if( StringEqual( name, "RotX" ) )
return ( !PyArg_Parse( value, "f", &( object->rot[0] ) ) );
if( StringEqual( name, "RotY" ) )
return ( !PyArg_Parse( value, "f", &( object->rot[1] ) ) );
if( StringEqual( name, "RotZ" ) )
return ( !PyArg_Parse( value, "f", &( object->rot[2] ) ) );
if( StringEqual( name, "dRotX" ) )
return ( !PyArg_Parse( value, "f", &( object->drot[0] ) ) );
if( StringEqual( name, "dRotY" ) )
return ( !PyArg_Parse( value, "f", &( object->drot[1] ) ) );
if( StringEqual( name, "dRotZ" ) )
return ( !PyArg_Parse( value, "f", &( object->drot[2] ) ) );
if( StringEqual( name, "drot" ) )
return ( !PyArg_ParseTuple( value, "fff", &( object->drot[0] ),
&( object->drot[1] ),
&( object->drot[2] ) ) );
if( StringEqual( name, "SizeX" ) )
return ( !PyArg_Parse( value, "f", &( object->size[0] ) ) );
if( StringEqual( name, "SizeY" ) )
return ( !PyArg_Parse( value, "f", &( object->size[1] ) ) );
if( StringEqual( name, "SizeZ" ) )
return ( !PyArg_Parse( value, "f", &( object->size[2] ) ) );
if( StringEqual( name, "size" ) )
return ( !PyArg_ParseTuple( value, "fff", &( object->size[0] ),
&( object->size[1] ),
&( object->size[2] ) ) );
if( StringEqual( name, "dSizeX" ) )
return ( !PyArg_Parse( value, "f", &( object->dsize[0] ) ) );
if( StringEqual( name, "dSizeY" ) )
return ( !PyArg_Parse( value, "f", &( object->dsize[1] ) ) );
if( StringEqual( name, "dSizeZ" ) )
return ( !PyArg_Parse( value, "f", &( object->dsize[2] ) ) );
if( StringEqual( name, "dsize" ) )
return ( !PyArg_ParseTuple
( value, "fff", &( object->dsize[0] ),
&( object->dsize[1] ), &( object->dsize[2] ) ) );
Result of 2 weeks of quiet coding work in Greece :) Aim was to get a total refresh of the animation system. This is needed because; - we need to upgrade it with 21st century features - current code is spaghetti/hack combo, and hides good design - it should become lag-free with using dependency graphs A full log, with complete code API/structure/design explanation will follow, that's a load of work... so here below the list with hot changes; - The entire object update system (matrices, geometry) is now centralized. Calls to where_is_object and makeDispList are forbidden, instead we tag objects 'changed' and let the depgraph code sort it out - Removed all old "Ika" code - Depgraph is aware of all relationships, including meta balls, constraints, bevelcurve, and so on. - Made depgraph aware of relation types and layers, to do smart flushing of 'changed' events. Nothing gets calculated too often! - Transform uses depgraph to detect changes - On frame-advance, depgraph flushes animated changes Armatures; Almost all armature related code has been fully built from scratch. It now reveils the original design much better, with a very clean implementation, lag free without even calculating each Bone more than once. Result is quite a speedup yes! Important to note is; 1) Armature is data containing the 'rest position' 2) Pose is the changes of rest position, and always on object level. That way more Objects can use same Pose. Also constraints are in Pose 3) Actions only contain the Ipos to change values in Poses. - Bones draw unrotated now - Drawing bones speedup enormously (10-20 times) - Bone selecting in EditMode, selection state is saved for PoseMode, and vice-versa - Undo in editmode - Bone renaming does vertexgroups, constraints, posechannels, actions, for all users of Armature in entire file - Added Bone renaming in NKey panel - Nkey PoseMode shows eulers now - EditMode and PoseMode now have 'active' bone too (last clicked) - Parenting in EditMode' CTRL+P, ALT+P, with nice options! - Pose is added in Outliner now, with showing that constraints are in the Pose, not Armature - Disconnected IK solving from constraints. It's a separate phase now, on top of the full Pose calculations - Pose itself has a dependency graph too, so evaluation order is lag free. TODO NOW; - Rotating in Posemode has incorrect inverse transform (Martin will fix) - Python Bone/Armature/Pose API disabled... needs full recode too (wait for my doc!) - Game engine will need upgrade too - Depgraph code needs revision, cleanup, can be much faster! (But, compliments for Jean-Luc, it works like a charm!) - IK changed, it now doesnt use previous position to advance to next position anymore. That system looks nice (no flips) but is not well suited for NLA and background render. TODO LATER; We now can do loadsa new nifty features as well; like: - Kill PoseMode (can be option for armatures itself) - Make B-Bones (Bezier, Bspline, like for spines) - Move all silly button level edit to 3d window (like CTRL+I = add IK) - Much better & informative drawing - Fix action/nla editors - Put all ipos in Actions (object, mesh key, lamp color) - Add hooks - Null bones - Much more advanced constraints... Bugfixes; - OGL render (view3d header) had wrong first frame on anim render - Ipo 'recording' mode had wrong playback speed - Vertex-key mode now sticks to show 'active key', until frame change -Ton-
2005-07-03 17:35:38 +00:00
if( StringEqual( name, "DupSta" ) )
return ( !PyArg_Parse( value, "h", &( object->dupsta ) ) );
if( StringEqual( name, "DupEnd" ) )
return ( !PyArg_Parse( value, "h", &( object->dupend ) ) );
if( StringEqual( name, "DupOn" ) )
return ( !PyArg_Parse( value, "h", &( object->dupon ) ) );
if( StringEqual( name, "DupOff" ) )
return ( !PyArg_Parse( value, "h", &( object->dupoff ) ) );
if( StringEqual( name, "Dupliframes" ) ) {
short dupli;
if ( !PyArg_Parse( value, "h", &dupli ) )
return -1;
if (dupli)
obj->object->transflag |= OB_DUPLIFRAMES;
else
obj->object->transflag &= ~OB_DUPLIFRAMES;
return 0;
}
if( StringEqual( name, "colbits" ) )
return ( !PyArg_Parse( value, "h", &( object->colbits ) ) );
/* accept both Layer (for compatibility) and Layers */
if( strncmp( name, "Layer", 5 ) == 0 ) {
/* usage note: caller of this func needs to do a
Blender.Redraw(-1) to update and redraw the interface */
Base *base;
int newLayer;
int local;
if( ! PyArg_Parse( value, "i", &newLayer ) ) {
return EXPP_ReturnIntError( PyExc_AttributeError,
"expected int as bitmask" );
}
/* uppper 2 nibbles are for local view */
newLayer &= 0x00FFFFFF;
if( newLayer == 0 ) {
return EXPP_ReturnIntError( PyExc_AttributeError,
"bitmask must have from 1 up to 20 bits set");
}
/* update any bases pointing to our object */
base = FIRSTBASE; /* first base in current scene */
while( base ){
if( base->object == obj->object ) {
local = base->lay &= 0xFF000000;
base->lay = local | newLayer;
object->lay = base->lay;
}
base = base->next;
}
countall( );
return ( 0 );
}
if( StringEqual( name, "layers" ) ) {
/* usage note: caller of this func needs to do a
Blender.Redraw(-1) to update and redraw the interface */
Base *base;
int layers = 0, len_list = 0;
int local, i, val;
PyObject *list = NULL, *item = NULL;
if( !PyArg_Parse( value, "O!", &PyList_Type, &list ) )
return EXPP_ReturnIntError( PyExc_TypeError,
"expected a list of integers" );
len_list = PyList_Size(list);
if (len_list == 0)
return EXPP_ReturnIntError( PyExc_AttributeError,
"list can't be empty, at least one layer must be set" );
for( i = 0; i < len_list; i++ ) {
item = PyList_GetItem( list, i );
if( !PyInt_Check( item ) )
return EXPP_ReturnIntError
( PyExc_AttributeError,
"list must contain only integer numbers" );
val = ( int ) PyInt_AsLong( item );
if( val < 1 || val > 20 )
return EXPP_ReturnIntError
( PyExc_AttributeError,
"layer values must be in the range [1, 20]" );
layers |= 1 << ( val - 1 );
}
/* update any bases pointing to our object */
base = FIRSTBASE; /* first base in current scene */
while( base ){
if( base->object == obj->object ) {
local = base->lay &= 0xFF000000;
base->lay = local | layers;
object->lay = base->lay;
}
base = base->next;
}
countall();
return ( 0 );
}
if (StringEqual (name, "oopsLoc")) {
if (G.soops) {
Oops *oops= G.soops->oops.first;
while(oops) {
if(oops->type==ID_OB) {
if ((Object *)oops->id == object) {
return (!PyArg_ParseTuple (value, "ff", &(oops->x),&(oops->y)));
}
}
oops= oops->next;
}
}
return 0;
}
/*
IKA isn't even in Blender anymore, I think we can remove this... (theeth)
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 );
}
*/
/* SECOND, handle all the attributes that passes the value as a tuple to another function */
/* Put the value(s) in a tuple. For some variables, we want to */
/* pass the values to a function, and these functions only accept */
/* PyTuples. */
valtuple = Py_BuildValue( "(O)", value );
if( !valtuple ) {
return EXPP_ReturnIntError( PyExc_MemoryError,
"Object_setAttr: couldn't create PyTuple" );
}
/* Call the setFunctions to handle it */
if( StringEqual( name, "loc" ) )
result = Object_setLocation( obj, valtuple );
else if( StringEqual( name, "dloc" ) )
result = Object_setDeltaLocation( obj, valtuple );
else if( StringEqual( name, "rot" ) )
result = Object_setEuler( obj, valtuple );
else if( StringEqual( name, "track" ) )
result = Object_makeTrack( obj, valtuple );
else if( StringEqual( name, "drawType" ) )
result = Object_setDrawType( obj, valtuple );
else if( StringEqual( name, "drawMode" ) )
result = Object_setDrawMode( obj, valtuple );
else if( StringEqual( name, "name" ) )
result = Object_setName( obj, valtuple );
else if( StringEqual( name, "sel" ) )
result = Object_Select( obj, valtuple );
else { /* if it turns out here, it's not an attribute*/
Py_DECREF(valtuple);
return EXPP_ReturnIntError( PyExc_KeyError, "attribute not found" );
}
/* valtuple won't be returned to the caller, so we need to DECREF it */
Py_DECREF(valtuple);
if( result != Py_None )
return -1; /* error return */
/* Py_None was incref'ed by the called Scene_set* function. We probably
* don't need to decref Py_None (!), but since Python/C API manual tells us
* to treat it like any other PyObject regarding ref counting ... */
Py_DECREF( Py_None );
return 0; /* normal return */
}
/*****************************************************************************/
/* Function: Object_compare */
/* Description: This is a callback function for the BPy_Object type. It */
/* compares two Object_Type objects. Only the "==" and "!=" */
/* comparisons are meaninful. Returns 0 for equality and -1 if */
/* they don't point to the same Blender Object struct. */
/* In Python it becomes 1 if they are equal, 0 otherwise. */
/*****************************************************************************/
static int Object_compare( BPy_Object * a, BPy_Object * b )
{
Object *pa = a->object, *pb = b->object;
return ( pa == pb ) ? 0 : -1;
}
/*****************************************************************************/
/* Function: Object_repr */
/* Description: This is a callback function for the BPy_Object type. It */
/* builds a meaninful string to represent object objects. */
/*****************************************************************************/
static PyObject *Object_repr( BPy_Object * self )
{
return PyString_FromFormat( "[Object \"%s\"]",
self->object->id.name + 2 );
}
PyObject *Object_getPIStrength( BPy_Object * self )
{
PyObject *attr;
if(!self->object->pd){
if(!setupPI(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"particle deflection could not be accessed (null pointer)" ) );
}
attr = PyFloat_FromDouble( ( double ) self->object->pd->f_strength );
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->pd->f_strength attribute" ) );
}
PyObject *Object_setPIStrength( BPy_Object * self, PyObject * args )
{
float value;
if(!self->object->pd){
if(!setupPI(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"particle deflection could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "f", &value ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected float argument" ) );
if(value > 1000.0f || value < -1000.0f)
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"acceptable values are between 1000.0 and -1000.0" ) );
self->object->pd->f_strength = value;
return EXPP_incr_ret( Py_None );
}
PyObject *Object_getPIFalloff( BPy_Object * self )
{
PyObject *attr;
if(!self->object->pd){
if(!setupPI(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"particle deflection could not be accessed (null pointer)" ) );
}
attr = PyFloat_FromDouble( ( double ) self->object->pd->f_power );
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->pd->f_power attribute" ) );
}
PyObject *Object_setPIFalloff( BPy_Object * self, PyObject * args )
{
float value;
if(!self->object->pd){
if(!setupPI(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"particle deflection could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "f", &value ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected float argument" ) );
if(value > 10.0f || value < 0.0f)
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"acceptable values are between 10.0 and 0.0" ) );
self->object->pd->f_power = value;
return EXPP_incr_ret( Py_None );
}
PyObject *Object_getPIMaxDist( BPy_Object * self )
{
PyObject *attr;
if(!self->object->pd){
if(!setupPI(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"particle deflection could not be accessed (null pointer)" ) );
}
attr = PyFloat_FromDouble( ( double ) self->object->pd->maxdist );
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->pd->f_maxdist attribute" ) );
}
PyObject *Object_setPIMaxDist( BPy_Object * self, PyObject * args )
{
float value;
if(!self->object->pd){
if(!setupPI(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"particle deflection could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "f", &value ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected float argument" ) );
if(value > 1000.0f || value < 0.0f)
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"acceptable values are between 1000.0 and 0.0" ) );
self->object->pd->maxdist = value;
return EXPP_incr_ret( Py_None );
}
PyObject *Object_getPIUseMaxDist( BPy_Object * self )
{
PyObject *attr;
if(!self->object->pd){
if(!setupPI(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"particle deflection could not be accessed (null pointer)" ) );
}
attr = PyInt_FromLong( ( long ) self->object->pd->flag );
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->pd->flag attribute" ) );
}
PyObject *Object_setPIUseMaxDist( BPy_Object * self, PyObject * args )
{
int value;
if(!self->object->pd){
if(!setupPI(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"particle deflection could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "i", &( value ) ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected int argument" ) );
self->object->pd->flag = (short)value;
return EXPP_incr_ret( Py_None );
}
PyObject *Object_getPIType( BPy_Object * self )
{
PyObject *attr;
if(!self->object->pd){
if(!setupPI(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"particle deflection could not be accessed (null pointer)" ) );
}
attr = PyInt_FromLong( ( long ) self->object->pd->forcefield );
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->pd->forcefield attribute" ) );
}
PyObject *Object_setPIType( BPy_Object * self, PyObject * args )
{
int value;
if(!self->object->pd){
if(!setupPI(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"particle deflection could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "i", &( value ) ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected int argument" ) );
self->object->pd->forcefield = (short)value;
return EXPP_incr_ret( Py_None );
}
PyObject *Object_getPIPerm( BPy_Object * self )
{
PyObject *attr;
if(!self->object->pd){
if(!setupPI(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"particle deflection could not be accessed (null pointer)" ) );
}
attr = PyFloat_FromDouble( ( double ) self->object->pd->pdef_perm );
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->pd->pdef_perm attribute" ) );
}
PyObject *Object_setPIPerm( BPy_Object * self, PyObject * args )
{
float value;
if(!self->object->pd){
if(!setupPI(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"particle deflection could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "f", &value ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected float argument" ) );
if(value > 1.0f || value < 0.0f)
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"acceptable values are between 1.0 and 0.0" ) );
self->object->pd->pdef_perm = value;
return EXPP_incr_ret( Py_None );
}
PyObject *Object_getPIRandomDamp( BPy_Object * self )
{
PyObject *attr;
if(!self->object->pd){
if(!setupPI(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"particle deflection could not be accessed (null pointer)" ) );
}
attr = PyFloat_FromDouble( ( double ) self->object->pd->pdef_rdamp );
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->pd->pdef_rdamp attribute" ) );
}
PyObject *Object_setPIRandomDamp( BPy_Object * self, PyObject * args )
{
float value;
if(!self->object->pd){
if(!setupPI(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"particle deflection could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "f", &value ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected float argument" ) );
if(value > 1.0f || value < 0.0f)
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"acceptable values are between 1.0 and 0.0" ) );
self->object->pd->pdef_rdamp = value;
return EXPP_incr_ret( Py_None );
}
PyObject *Object_getPISurfaceDamp( BPy_Object * self )
{
PyObject *attr;
if(!self->object->pd){
if(!setupPI(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"particle deflection could not be accessed (null pointer)" ) );
}
attr = PyFloat_FromDouble( ( double ) self->object->pd->pdef_damp );
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->pd->pdef_rdamp attribute" ) );
}
PyObject *Object_setPISurfaceDamp( BPy_Object * self, PyObject * args )
{
float value;
if(!self->object->pd){
if(!setupPI(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"particle deflection could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "f", &value ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected float argument" ) );
if(value > 1.0f || value < 0.0f)
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"acceptable values are between 1.0 and 0.0" ) );
self->object->pd->pdef_damp = value;
return EXPP_incr_ret( Py_None );
}
PyObject *Object_getPIDeflection( BPy_Object * self )
{
PyObject *attr;
if(!self->object->pd){
if(!setupPI(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"particle deflection could not be accessed (null pointer)" ) );
}
attr = PyInt_FromLong( ( long ) self->object->pd->deflect );
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->pd->deflect attribute" ) );
}
PyObject *Object_setPIDeflection( BPy_Object * self, PyObject * args )
{
int value;
if(!self->object->pd){
if(!setupPI(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"particle deflection could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "i", &( value ) ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected int argument" ) );
self->object->pd->deflect = (short)value;
return EXPP_incr_ret( Py_None );
}
/* SOFTBODY FUNCTIONS */
PyObject *Object_isSB(BPy_Object *self)
{
if (self->object->soft)
return EXPP_incr_ret_True();
else return EXPP_incr_ret_False();
}
PyObject *Object_getSBMass( BPy_Object * self )
{
PyObject *attr;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
attr = PyFloat_FromDouble( ( double ) self->object->soft->nodemass );
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->soft->nodemass attribute" ) );
}
PyObject *Object_setSBMass( BPy_Object * self, PyObject * args )
{
float value;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "f", &value ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected float argument" ) );
if(value > 50.0f || value < 0.0f)
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"acceptable values are between 0.0 and 50.0" ) );
self->object->soft->nodemass = value;
return EXPP_incr_ret( Py_None );
}
PyObject *Object_getSBGravity( BPy_Object * self )
{
PyObject *attr;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
attr = PyFloat_FromDouble( ( double ) self->object->soft->grav );
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->soft->grav attribute" ) );
}
PyObject *Object_setSBGravity( BPy_Object * self, PyObject * args )
{
float value;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "f", &value ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected float argument" ) );
if(value > 10.0f || value < 0.0f)
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"acceptable values are between 0.0 and 10.0" ) );
self->object->soft->grav = value;
return EXPP_incr_ret( Py_None );
}
PyObject *Object_getSBFriction( BPy_Object * self )
{
PyObject *attr;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
attr = PyFloat_FromDouble( ( double ) self->object->soft->mediafrict );
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->soft->mediafrict attribute" ) );
}
PyObject *Object_setSBFriction( BPy_Object * self, PyObject * args )
{
float value;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "f", &value ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected float argument" ) );
if(value > 10.0f || value < 0.0f)
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"acceptable values are between 0.0 and 10.0" ) );
self->object->soft->mediafrict = value;
return EXPP_incr_ret( Py_None );
}
PyObject *Object_getSBErrorLimit( BPy_Object * self )
{
PyObject *attr;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
attr = PyFloat_FromDouble( ( double ) self->object->soft->rklimit );
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->soft->rklimit attribute" ) );
}
PyObject *Object_setSBErrorLimit( BPy_Object * self, PyObject * args )
{
float value;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "f", &value ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected float argument" ) );
if(value > 1.0f || value < 0.01f)
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"acceptable values are between 0.01 and 1.0" ) );
self->object->soft->rklimit = value;
return EXPP_incr_ret( Py_None );
}
PyObject *Object_getSBGoalSpring( BPy_Object * self )
{
PyObject *attr;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
attr = PyFloat_FromDouble( ( double ) self->object->soft->goalspring );
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->soft->goalspring attribute" ) );
}
PyObject *Object_setSBGoalSpring( BPy_Object * self, PyObject * args )
{
float value;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer) " ) );
}
if( !PyArg_ParseTuple( args, "f", &value ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected float argument" ) );
if(value > 0.999f || value < 0.00f)
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"acceptable values are between 0.00 and 0.999" ) );
self->object->soft->goalspring = value;
return EXPP_incr_ret( Py_None );
}
PyObject *Object_getSBGoalFriction( BPy_Object * self )
{
PyObject *attr;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
attr = PyFloat_FromDouble( ( double ) self->object->soft->goalfrict );
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->soft->goalfrict attribute" ) );
}
PyObject *Object_setSBGoalFriction( BPy_Object * self, PyObject * args )
{
float value;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "f", &value ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected float argument" ) );
if(value > 10.0f || value < 0.00f)
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"acceptable values are between 0.00 and 10.0" ) );
self->object->soft->goalfrict = value;
return EXPP_incr_ret( Py_None );
}
PyObject *Object_getSBMinGoal( BPy_Object * self )
{
PyObject *attr;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
attr = PyFloat_FromDouble( ( double ) self->object->soft->mingoal );
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->soft->mingoal attribute" ) );
}
PyObject *Object_setSBMinGoal( BPy_Object * self, PyObject * args )
{
float value;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "f", &value ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected float argument" ) );
if(value > 1.0f || value < 0.00f)
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"acceptable values are between 0.00 and 1.0" ) );
self->object->soft->mingoal = value;
return EXPP_incr_ret( Py_None );
}
PyObject *Object_getSBMaxGoal( BPy_Object * self )
{
PyObject *attr;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
attr = PyFloat_FromDouble( ( double ) self->object->soft->maxgoal );
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->soft->maxgoal attribute" ) );
}
PyObject *Object_setSBMaxGoal( BPy_Object * self, PyObject * args )
{
float value;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "f", &value ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected float argument" ) );
if(value > 1.0f || value < 0.00f)
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"acceptable values are between 0.00 and 1.0" ) );
self->object->soft->maxgoal = value;
return EXPP_incr_ret( Py_None );
}
PyObject *Object_getSBInnerSpring( BPy_Object * self )
{
PyObject *attr;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
attr = PyFloat_FromDouble( ( double ) self->object->soft->inspring );
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->soft->inspring attribute" ) );
}
PyObject *Object_setSBInnerSpring( BPy_Object * self, PyObject * args )
{
float value;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "f", &value ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected float argument" ) );
if(value > 0.999f || value < 0.00f)
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"acceptable values are between 0.00 and 0.999" ) );
self->object->soft->inspring = value;
return EXPP_incr_ret( Py_None );
}
PyObject *Object_getSBInnerSpringFriction( BPy_Object * self )
{
PyObject *attr;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
attr = PyFloat_FromDouble( ( double ) self->object->soft->infrict );
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->soft->infrict attribute" ) );
}
PyObject *Object_setSBInnerSpringFriction( BPy_Object * self, PyObject * args )
{
float value;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "f", &value ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected float argument" ) );
if(value > 10.0f || value < 0.00f)
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"acceptable values are between 0.00 and 10.0" ) );
self->object->soft->infrict = value;
return EXPP_incr_ret( Py_None );
}
PyObject *Object_getSBDefaultGoal( BPy_Object * self )
{
PyObject *attr;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
attr = PyFloat_FromDouble( ( double ) self->object->soft->defgoal );
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->soft->defgoal attribute" ) );
}
PyObject *Object_setSBDefaultGoal( BPy_Object * self, PyObject * args )
{
float value;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "f", &value ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected float argument" ) );
if(value > 1.0f || value < 0.00f)
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"acceptable values are between 0.00 and 1.0" ) );
self->object->soft->defgoal = value;
return EXPP_incr_ret( Py_None );
}
PyObject *Object_getSBEnable( BPy_Object * self )
{
/*short flag = self->object->softflag;*/
PyObject *attr = NULL;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
if(self->object->softflag & OB_SB_ENABLE){
attr = PyInt_FromLong(1);
}
else{ attr = PyInt_FromLong(0); }
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->softflag attribute" ) );
}
PyObject *Object_setSBEnable( BPy_Object * self, PyObject * args )
{
short value;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "h", &value ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected integer argument" ) );
if(value > 0){
self->object->softflag |= OB_SB_ENABLE;
}
else{
self->object->softflag &= ~OB_SB_ENABLE;
}
return EXPP_incr_ret( Py_None );
}
PyObject *Object_getSBPostDef( BPy_Object * self )
{
/*short flag = self->object->softflag;*/
PyObject *attr = NULL;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
if(self->object->softflag & OB_SB_POSTDEF){
attr = PyInt_FromLong(1);
}
else{ attr = PyInt_FromLong(0); }
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->softflag attribute" ) );
}
PyObject *Object_setSBPostDef( BPy_Object * self, PyObject * args )
{
short value;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "h", &value ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected integer argument" ) );
if(value){ self->object->softflag |= OB_SB_POSTDEF; }
else{ self->object->softflag &= ~OB_SB_POSTDEF; }
return EXPP_incr_ret( Py_None );
}
PyObject *Object_getSBUseGoal( BPy_Object * self )
{
/*short flag = self->object->softflag;*/
PyObject *attr = NULL;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
if(self->object->softflag & OB_SB_GOAL){
attr = PyInt_FromLong(1);
}
else{ attr = PyInt_FromLong(0); }
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->softflag attribute" ) );
}
PyObject *Object_setSBUseGoal( BPy_Object * self, PyObject * args )
{
short value;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "h", &value ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected integer argument" ) );
if(value){ self->object->softflag |= OB_SB_GOAL; }
else{ self->object->softflag &= ~OB_SB_GOAL; }
return EXPP_incr_ret( Py_None );
}
PyObject *Object_getSBUseEdges( BPy_Object * self )
{
/*short flag = self->object->softflag;*/
PyObject *attr = NULL;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
if(self->object->softflag & OB_SB_EDGES){
attr = PyInt_FromLong(1);
}
else{ attr = PyInt_FromLong(0); }
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->softflag attribute" ) );
}
PyObject *Object_setSBUseEdges( BPy_Object * self, PyObject * args )
{
short value;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "h", &value ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected integer argument" ) );
if(value){ self->object->softflag |= OB_SB_EDGES; }
else{ self->object->softflag &= ~OB_SB_EDGES; }
return EXPP_incr_ret( Py_None );
}
PyObject *Object_getSBStiffQuads( BPy_Object * self )
{
/*short flag = self->object->softflag;*/
PyObject *attr = NULL;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
if(self->object->softflag & OB_SB_QUADS){
attr = PyInt_FromLong(1);
}
else{ attr = PyInt_FromLong(0); }
if( attr )
return attr;
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"couldn't get Object->softflag attribute" ) );
}
PyObject *Object_setSBStiffQuads( BPy_Object * self, PyObject * args )
{
short value;
if(!self->object->soft){
if(!setupSB(self->object))
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"softbody could not be accessed (null pointer)" ) );
}
if( !PyArg_ParseTuple( args, "h", &value ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected integer argument" ) );
if(value){ self->object->softflag |= OB_SB_QUADS; }
else{ self->object->softflag &= ~OB_SB_QUADS; }
return EXPP_incr_ret( Py_None );
}
int setupSB(Object* ob){
ob->soft= sbNew();
ob->softflag |= OB_SB_GOAL|OB_SB_EDGES;
// default add edges for softbody
if(ob->type==OB_MESH) {
Mesh *me= ob->data;
if(me->medge==NULL) make_edges(me);
}
if(ob->soft){
ob->soft->nodemass = 1.0f;
ob->soft->grav = 0.0f;
ob->soft->mediafrict = 0.5f;
ob->soft->rklimit = 0.1f;
ob->soft->goalspring = 0.5f;
ob->soft->goalfrict = 0.0f;
ob->soft->mingoal = 0.0f;
ob->soft->maxgoal = 1.0f;
ob->soft->inspring = 0.5f;
ob->soft->infrict = 0.5f;
ob->soft->defgoal = 0.7f;
return 1;
}
else {
return 0;
}
}
int setupPI(Object* ob){
if(ob->pd==NULL) {
ob->pd= MEM_callocN(sizeof(PartDeflect), "PartDeflect");
/* and if needed, init here */
}
if(ob->pd){
ob->pd->deflect =0;
ob->pd->forcefield =0;
ob->pd->flag =0;
ob->pd->pdef_damp =0;
ob->pd->pdef_rdamp =0;
ob->pd->pdef_perm =0;
ob->pd->f_strength =0;
ob->pd->f_power =0;
ob->pd->maxdist =0;
return 1;
}
else{
return 0;
}
}