Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/python')
-rw-r--r--source/blender/python/BPY_interface.c3
-rw-r--r--source/blender/python/SConscript1
-rw-r--r--source/blender/python/api2_2x/Armature.c25
-rw-r--r--source/blender/python/api2_2x/Armature.h4
-rw-r--r--source/blender/python/api2_2x/BezTriple.c32
-rw-r--r--source/blender/python/api2_2x/Bone.c144
-rw-r--r--source/blender/python/api2_2x/Bone.h4
-rw-r--r--source/blender/python/api2_2x/Key.c141
-rw-r--r--source/blender/python/api2_2x/Mesh.c478
-rw-r--r--source/blender/python/api2_2x/NLA.c8
-rw-r--r--source/blender/python/api2_2x/NLA.h2
-rw-r--r--source/blender/python/api2_2x/NMesh.c86
-rw-r--r--source/blender/python/api2_2x/Object.c40
-rw-r--r--source/blender/python/api2_2x/Pose.c1033
-rw-r--r--source/blender/python/api2_2x/Pose.h72
-rw-r--r--source/blender/python/api2_2x/Window.c15
-rw-r--r--source/blender/python/api2_2x/constant.c2
-rw-r--r--source/blender/python/api2_2x/doc/API_intro.py1
-rw-r--r--source/blender/python/api2_2x/doc/Armature.py11
-rw-r--r--source/blender/python/api2_2x/doc/Ipo.py10
-rw-r--r--source/blender/python/api2_2x/doc/Key.py9
-rw-r--r--source/blender/python/api2_2x/doc/Mathutils.py1
-rw-r--r--source/blender/python/api2_2x/doc/Mesh.py57
-rw-r--r--source/blender/python/api2_2x/doc/Object.py13
-rw-r--r--source/blender/python/api2_2x/doc/Theme.py4
-rw-r--r--source/blender/python/api2_2x/doc/Window.py5
-rw-r--r--source/blender/python/api2_2x/matrix.c2
-rw-r--r--source/blender/python/api2_2x/vector.c4
-rw-r--r--source/blender/python/api2_2x/windowTheme.c13
29 files changed, 1735 insertions, 485 deletions
diff --git a/source/blender/python/BPY_interface.c b/source/blender/python/BPY_interface.c
index 3cdc0de4f52..529d428692b 100644
--- a/source/blender/python/BPY_interface.c
+++ b/source/blender/python/BPY_interface.c
@@ -1706,8 +1706,9 @@ static PyObject *reimportText( PyObject *module )
/* if previously compiled, free the object */
/* (can't see how could be NULL, but check just in case) */
- if( text->compiled )
+ if( text->compiled ){
Py_DECREF( (PyObject *)text->compiled );
+ }
/* compile the buffer */
buf = txt_to_buf( text );
diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript
index c7a597c62c9..aedafd84e96 100644
--- a/source/blender/python/SConscript
+++ b/source/blender/python/SConscript
@@ -43,6 +43,7 @@ source_files = ['BPY_interface.c',
'api2_2x/Types.c',
'api2_2x/Window.c',
'api2_2x/World.c',
+ 'api2_2x/Pose.c',
'api2_2x/Image.c',
'api2_2x/Text.c',
'api2_2x/Text3d.c',
diff --git a/source/blender/python/api2_2x/Armature.c b/source/blender/python/api2_2x/Armature.c
index 743956a1f61..28ae3eadcc7 100644
--- a/source/blender/python/api2_2x/Armature.c
+++ b/source/blender/python/api2_2x/Armature.c
@@ -44,8 +44,7 @@
#include "DNA_object_types.h" //This must come before BIF_editarmature.h...
#include "BIF_editarmature.h"
-//------------------UNDECLARED EXTERNAL PROTOTYPES--------------------
-//These are evil 'extern' declarations for functions with no anywhere
+//------------------EXTERNAL PROTOTYPES--------------------
extern void free_editArmature(void);
extern void make_boneList(ListBase* list, ListBase *bones, EditBone *parent);
extern void editbones_to_armature (ListBase *list, Object *ob);
@@ -112,7 +111,7 @@ static PyMethodDef BPy_BonesDict_methods[] = {
"() - Returns the keys the dictionary"},
{"values", (PyCFunction) BonesDict_values, METH_NOARGS,
"() - Returns the values from the dictionary"},
- {NULL}
+ {NULL, NULL, 0, NULL}
};
//-----------------(internal)
static int BoneMapping_Init(PyObject *dictionary, ListBase *bones){
@@ -225,8 +224,18 @@ PyObject *BonesDict_GetItem(BPy_BonesDict *self, PyObject* key)
}else{
value = PyDict_GetItem(self->bonesMap, key);
}
- if(value == NULL){
- return EXPP_incr_ret(Py_None);
+ if(value == NULL){ /* item not found in dict. throw exception */
+ char buffer[128];
+ char* key_str;
+ key_str = PyString_AsString( key );
+ if( !key_str ){ /* key not a py string */
+ key_str = ""; /* use empty string for printing */
+ }
+
+ PyOS_snprintf( buffer, sizeof(buffer),
+ "bone %s not found", key_str);
+
+ return EXPP_ReturnPyObjError(PyExc_KeyError, buffer );
}
return EXPP_incr_ret(value);
}
@@ -335,7 +344,7 @@ AttributeError3:
return EXPP_intError(PyExc_AttributeError, "%s%s",
sBoneDictBadArgs, "The 'connected' flag is set but the bone has no parent!");
}
-//------------------TYPE_OBECT DEFINITION--------------------------
+//------------------TYPE_OBJECT DEFINITION--------------------------
//Mapping Protocol
static PyMappingMethods BonesDict_MapMethods = {
(inquiry) BonesDict_len, //mp_length
@@ -929,7 +938,7 @@ static PyMethodDef BPy_Armature_methods[] = {
"() - Unlocks the ability to modify armature bones"},
{"update", (PyCFunction) Armature_update, METH_NOARGS,
"() - Rebuilds the armature based on changes to bones since the last call to makeEditable"},
- {NULL}
+ {NULL, NULL, 0, NULL}
};
//------------------------tp_getset
//This contains methods for attributes that require checking
@@ -1218,7 +1227,7 @@ static char M_Armature_Get_doc[] = "(name) - return the armature with the name '
struct PyMethodDef M_Armature_methods[] = {
{"Get", M_Armature_Get, METH_VARARGS, M_Armature_Get_doc},
- {NULL}
+ {NULL, NULL, 0, NULL}
};
//------------------VISIBLE PROTOTYPE IMPLEMENTATION-----------------------
//-----------------(internal)
diff --git a/source/blender/python/api2_2x/Armature.h b/source/blender/python/api2_2x/Armature.h
index 4d14b41fdc8..dbf21d1e5a5 100644
--- a/source/blender/python/api2_2x/Armature.h
+++ b/source/blender/python/api2_2x/Armature.h
@@ -40,8 +40,8 @@
//-------------------MODULE INIT---------------------------------
PyObject *Armature_Init( void );
//-------------------TYPEOBJECT----------------------------------
-PyTypeObject Armature_Type;
-PyTypeObject BonesDict_Type;
+extern PyTypeObject Armature_Type;
+extern PyTypeObject BonesDict_Type;
//-------------------STRUCT DEFINITION---------------------------
typedef struct {
PyObject_HEAD
diff --git a/source/blender/python/api2_2x/BezTriple.c b/source/blender/python/api2_2x/BezTriple.c
index 3d610e38fd6..c8b82d16a88 100644
--- a/source/blender/python/api2_2x/BezTriple.c
+++ b/source/blender/python/api2_2x/BezTriple.c
@@ -256,39 +256,20 @@ static PyObject *BezTriple_getTriple( BPy_BezTriple * self )
static PyObject *BezTriple_setPoints( BPy_BezTriple * self, PyObject * args )
{
-
int i;
struct BezTriple *bezt = self->beztriple;
PyObject *popo = 0;
- if( !PyArg_ParseTuple( args, "O", &popo ) )
- return ( EXPP_ReturnPyObjError
- ( PyExc_TypeError, "expected sequence argument" ) );
-
- if( PySequence_Check( popo ) == 0 ) {
- puts( "error in BezTriple_setPoints - expected sequence" );
- Py_INCREF( Py_None );
- return Py_None;
- }
-
- {
- /*
- some debug stuff
- this will become an overloaded args check
- */
- int size = PySequence_Size( popo );
- printf( "\n dbg: sequence size is %d\n", size );
- }
+ if( !PyArg_ParseTuple( args, "O", &popo ) || !PySequence_Check( popo ) )
+ return EXPP_ReturnPyObjError( PyExc_TypeError,
+ "expected sequence argument" );
for( i = 0; i < 2; i++ ) {
- PyObject *o = PySequence_GetItem( popo, i );
- if( !o )
- printf( "\n bad o. o no!\n" );
-
- /* bezt->vec[1][i] = PyFloat_AsDouble (PyTuple_GetItem (popo, i)); */
+ PyObject *o = PySequence_ITEM( popo, i );
bezt->vec[1][i] = (float)PyFloat_AsDouble( o );
bezt->vec[0][i] = bezt->vec[1][i] - 1;
bezt->vec[2][i] = bezt->vec[1][i] + 1;
+ Py_DECREF( o );
}
/* experimental fussing with handles - ipo.c: calchandles_ipocurve */
@@ -298,8 +279,7 @@ static PyObject *BezTriple_setPoints( BPy_BezTriple * self, PyObject * args )
if( bezt->vec[2][0] < bezt->vec[1][0] )
bezt->vec[2][0] = bezt->vec[1][0];
- Py_INCREF( Py_None );
- return Py_None;
+ Py_RETURN_NONE;
}
diff --git a/source/blender/python/api2_2x/Bone.c b/source/blender/python/api2_2x/Bone.c
index b4f8af4fe12..7e233e5f647 100644
--- a/source/blender/python/api2_2x/Bone.c
+++ b/source/blender/python/api2_2x/Bone.c
@@ -42,14 +42,15 @@
#include "DNA_object_types.h" //1
#include "BIF_editarmature.h" //2
+//------------------UNDECLARED EXTERNAL PROTOTYPES--------------------
+extern void mat3_to_vec_roll(float mat[][3], float *vec, float *roll);
+
//------------------------ERROR CODES---------------------------------
//This is here just to make me happy and to have more consistant error strings :)
-static const char sEditBoneError[] = "EditBone (internal) - Error: ";
-static const char sEditBoneBadArgs[] = "EditBone (internal) - Bad Arguments: ";
+static const char sEditBoneError[] = "EditBone - Error: ";
+static const char sEditBoneBadArgs[] = "EditBone - Bad Arguments: ";
static const char sBoneError[] = "Bone - Error: ";
static const char sBoneBadArgs[] = "Bone - Bad Arguments: ";
-static const char sConstListError[] = "ConstantList - Error: ";
-static const char sConstListBadArgs[] = "ConstantList - Bad Arguments: ";
//----------------------(internal)
//gets the bone->roll (which is a localspace roll) and puts it in parentspace
@@ -541,7 +542,6 @@ static int EditBone_setParent(BPy_EditBone *self, PyObject *value, void *closure
AttributeError:
return EXPP_intError(PyExc_AttributeError, "%s%s%s",
sEditBoneError, ".parent: ", "expects a EditBone Object");
-
AttributeError2:
return EXPP_intError(PyExc_AttributeError, "%s%s%s",
sEditBoneError, ".parent: ", "This object is not in the armature's bone list!");
@@ -565,8 +565,53 @@ static PyObject *EditBone_getMatrix(BPy_EditBone *self, void *closure)
//------------------------EditBone.matrix (set)
static int EditBone_setMatrix(BPy_EditBone *self, PyObject *value, void *closure)
{
- printf("Sorry this isn't implemented yet.... :/");
- return 1;
+ PyObject *matrix;
+ float roll, length, vec[3], axis[3], mat3[3][3];
+
+ if (!PyArg_Parse(value, "O!", &matrix_Type, &matrix))
+ goto AttributeError;
+
+ //make sure we have the right sizes
+ if (((MatrixObject*)matrix)->rowSize != 3 && ((MatrixObject*)matrix)->colSize != 3){
+ if(((MatrixObject*)matrix)->rowSize != 4 && ((MatrixObject*)matrix)->colSize != 4){
+ goto AttributeError;
+ }
+ }
+
+ /*vec will be a normalized directional vector
+ * together with the length of the old bone vec*length = the new vector*/
+ /*The default rotation is 0,1,0 on the Y axis (see mat3_to_vec_roll)*/
+ if (((MatrixObject*)matrix)->rowSize == 4){
+ Mat3CpyMat4(mat3, ((float (*)[4])*((MatrixObject*)matrix)->matrix));
+ }else{
+ Mat3CpyMat3(mat3, ((float (*)[3])*((MatrixObject*)matrix)->matrix));
+ }
+ mat3_to_vec_roll(mat3, vec, &roll);
+
+ //if a 4x4 matrix was passed we'll translate the vector otherwise not
+ if (self->editbone){
+ self->editbone->roll = roll;
+ VecSubf(axis, self->editbone->tail, self->editbone->head);
+ length = VecLength(axis);
+ VecMulf(vec, length);
+ if (((MatrixObject*)matrix)->rowSize == 4)
+ VecCopyf(self->editbone->head, ((MatrixObject*)matrix)->matrix[3]);
+ VecAddf(self->editbone->tail, self->editbone->head, vec);
+ return 0;
+ }else{
+ self->roll = roll;
+ VecSubf(axis, self->tail, self->head);
+ length = VecLength(axis);
+ VecMulf(vec, length);
+ if (((MatrixObject*)matrix)->rowSize == 4)
+ VecCopyf(self->head, ((MatrixObject*)matrix)->matrix[3]);
+ VecAddf(self->tail, self->head, vec);
+ return 0;
+ }
+
+AttributeError:
+ return EXPP_intError(PyExc_AttributeError, "%s%s%s",
+ sEditBoneError, ".matrix: ", "expects a 3x3 or 4x4 Matrix Object");
}
//------------------------Bone.length (get)
static PyObject *EditBone_getLength(BPy_EditBone *self, void *closure)
@@ -603,7 +648,7 @@ static PyMethodDef BPy_EditBone_methods[] = {
"() - True/False - Bone has a parent"},
{"clearParent", (PyCFunction) EditBone_clearParent, METH_NOARGS,
"() - sets the parent to None"},
- {NULL}
+ {NULL, NULL, 0, NULL}
};
///------------------------tp_getset
//This contains methods for attributes that require checking
@@ -630,7 +675,7 @@ static PyGetSetDef BPy_EditBone_getset[] = {
"The parent bone of this bone", NULL},
{"length", (getter)EditBone_getLength, (setter)EditBone_setLength,
"The length of this bone", NULL},
- {NULL}
+ {NULL, NULL, NULL, NULL,NULL}
};
//------------------------tp_repr
@@ -751,6 +796,28 @@ PyTypeObject EditBone_Type = {
};
//------------------METHOD IMPLEMENTATIONS--------------------------------
+//------------------------(internal) PyBone_ChildrenAsList
+static int PyBone_ChildrenAsList(PyObject *list, ListBase *bones){
+ Bone *bone = NULL;
+ PyObject *py_bone = NULL;
+
+ for (bone = bones->first; bone; bone = bone->next){
+ py_bone = PyBone_FromBone(bone);
+ if (py_bone == NULL)
+ return 0;
+
+ if(PyList_Append(list, py_bone) == -1){
+ goto RuntimeError;
+ }
+ if (bone->childbase.first)
+ PyBone_ChildrenAsList(list, &bone->childbase);
+ }
+ return 1;
+
+RuntimeError:
+ return EXPP_intError(PyExc_RuntimeError, "%s%s",
+ sBoneError, "Internal error trying to wrap blender bones!");
+}
//-------------------------Bone.hasParent()
PyObject *Bone_hasParent(BPy_Bone *self)
{
@@ -767,6 +834,20 @@ PyObject *Bone_hasChildren(BPy_Bone *self)
else
return EXPP_incr_ret(Py_False);
}
+//-------------------------Bone.getAllChildren()
+PyObject *Bone_getAllChildren(BPy_Bone *self)
+{
+ PyObject *list = NULL;
+
+ if (self->bone->childbase.first){
+ list = PyList_New(0);
+ if (!PyBone_ChildrenAsList(list, &self->bone->childbase))
+ return NULL;
+ return EXPP_incr_ret(list);
+ }else{
+ return EXPP_incr_ret(Py_None);
+ }
+}
//------------------ATTRIBUTE IMPLEMENTATIONS-----------------------------
//------------------------Bone.name (get)
static PyObject *Bone_getName(BPy_Bone *self, void *closure)
@@ -920,42 +1001,31 @@ static int Bone_setParent(BPy_Bone *self, PyObject *value, void *closure)
return EXPP_intError(PyExc_ValueError, "%s%s",
sBoneError, "You must first call .makeEditable() to edit the armature");
}
-//------------------------(internal) PyBone_ChildrenAsList
-static int PyBone_ChildrenAsList(PyObject *list, ListBase *bones){
- Bone *bone = NULL;
- PyObject *py_bone = NULL;
-
- for (bone = bones->first; bone; bone = bone->next){
- py_bone = PyBone_FromBone(bone);
- if (py_bone == NULL)
- return 0;
-
- if(PyList_Append(list, py_bone) == -1){
- goto RuntimeError;
- }
- if (bone->childbase.first)
- PyBone_ChildrenAsList(list, &bone->childbase);
- }
- return 1;
-
-RuntimeError:
- return EXPP_intError(PyExc_RuntimeError, "%s%s",
- sBoneError, "Internal error trying to wrap blender bones!");
-}
-
//------------------------Bone.children (get)
static PyObject *Bone_getChildren(BPy_Bone *self, void *closure)
{
PyObject *list = NULL;
+ Bone *bone = NULL;
+ PyObject *py_bone = NULL;
if (self->bone->childbase.first){
list = PyList_New(0);
- if (!PyBone_ChildrenAsList(list, &self->bone->childbase))
- return NULL;
+ for (bone = self->bone->childbase.first; bone; bone = bone->next){
+ py_bone = PyBone_FromBone(bone);
+ if (py_bone == NULL)
+ return 0;
+ if(PyList_Append(list, py_bone) == -1){
+ goto RuntimeError;
+ }
+ }
return EXPP_incr_ret(list);
}else{
return EXPP_incr_ret(Py_None);
}
+
+RuntimeError:
+ return EXPP_objError(PyExc_RuntimeError, "%s%s",
+ sBoneError, "Internal error trying to wrap blender bones!");
}
//------------------------Bone.children (set)
static int Bone_setChildren(BPy_Bone *self, PyObject *value, void *closure)
@@ -995,7 +1065,9 @@ static PyMethodDef BPy_Bone_methods[] = {
"() - True/False - Bone has a parent"},
{"hasChildren", (PyCFunction) Bone_hasChildren, METH_NOARGS,
"() - True/False - Bone has 1 or more children"},
- {NULL}
+ {"getAllChildren", (PyCFunction) Bone_getAllChildren, METH_NOARGS,
+ "() - All the children for this bone - including children's children"},
+ {NULL, NULL, 0, NULL}
};
//------------------------tp_getset
//This contains methods for attributes that require checking
@@ -1024,7 +1096,7 @@ static PyGetSetDef BPy_Bone_getset[] = {
"The child bones of this bone", NULL},
{"length", (getter)Bone_getLength, (setter)Bone_setLength,
"The length of this bone", NULL},
- {NULL}
+ {NULL, NULL, NULL, NULL,NULL}
};
//------------------------tp_repr
//This is the string representation of the object
diff --git a/source/blender/python/api2_2x/Bone.h b/source/blender/python/api2_2x/Bone.h
index aa095733d05..8c10aeb3075 100644
--- a/source/blender/python/api2_2x/Bone.h
+++ b/source/blender/python/api2_2x/Bone.h
@@ -38,8 +38,8 @@
#define BoneObject_Check(v) ((v)->ob_type == &Bone_Type)
#define EditBoneObject_Check(v) ((v)->ob_type == &EditBone_Type)
//-------------------TYPEOBJECT----------------------------------
-PyTypeObject EditBone_Type;
-PyTypeObject Bone_Type;
+extern PyTypeObject EditBone_Type;
+extern PyTypeObject Bone_Type;
//-------------------STRUCT DEFINITION----------------------------
typedef struct {
diff --git a/source/blender/python/api2_2x/Key.c b/source/blender/python/api2_2x/Key.c
index e71602ad6b4..32d7bc26191 100644
--- a/source/blender/python/api2_2x/Key.c
+++ b/source/blender/python/api2_2x/Key.c
@@ -25,7 +25,8 @@
*
* This is a new part of Blender.
*
- * Contributor(s): Pontus Lidman, Johnny Matthews, Ken Hughes
+ * Contributor(s): Pontus Lidman, Johnny Matthews, Ken Hughes,
+ * Michael Reimpell
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
@@ -36,6 +37,7 @@
#include <BKE_global.h>
#include <BKE_main.h>
#include <BKE_curve.h>
+#include "BIF_space.h"
#include "Ipocurve.h"
#include "Key.h"
@@ -62,10 +64,12 @@ static void KeyBlock_dealloc( PyObject * self );
static PyObject *Key_repr( BPy_Key * self );
static PyObject *Key_getBlocks( PyObject * self );
-static PyObject *Key_getType( PyObject * self );
+static PyObject *Key_getType( BPy_Key * self );
+static PyObject *Key_getRelative( BPy_Key * self );
static PyObject *Key_getIpo( PyObject * self );
static int Key_setIpo( PyObject * self, PyObject * args );
static PyObject *Key_getValue( PyObject * self );
+static int Key_setRelative( BPy_Key * self, PyObject * value );
static struct PyMethodDef Key_methods[] = {
{ "getBlocks", (PyCFunction) Key_getBlocks, METH_NOARGS, "Get key blocks" },
@@ -74,21 +78,21 @@ static struct PyMethodDef Key_methods[] = {
};
static PyGetSetDef BPy_Key_getsetters[] = {
- {"type",(getter)Key_getType, (setter)NULL,
- "Key Type",NULL},
- {"value",(getter)Key_getValue, (setter)NULL,
- "Key value",NULL},
- {"ipo",(getter)Key_getIpo, (setter)Key_setIpo,
- "ipo linked to key",NULL},
- {"blocks",(getter)Key_getBlocks, (setter)NULL,
- "blocks linked to the key",NULL},
- {NULL,NULL,NULL,NULL,NULL} /* Sentinel */
- };
-
-
+ {"type",(getter)Key_getType, (setter)NULL,
+ "Key Type",NULL},
+ {"value",(getter)Key_getValue, (setter)NULL,
+ "Key value",NULL},
+ {"ipo",(getter)Key_getIpo, (setter)Key_setIpo,
+ "Ipo linked to key",NULL},
+ {"blocks",(getter)Key_getBlocks, (setter)NULL,
+ "Blocks linked to the key",NULL},
+ {"relative",(getter)Key_getRelative, (setter)Key_setRelative,
+ "Non-zero is key is relative",NULL},
+ {NULL,NULL,NULL,NULL,NULL} /* Sentinel */
+};
static PyObject *KeyBlock_getData( PyObject * self );
-
+static PyObject *KeyBlock_getCurval( BPy_KeyBlock * self );
static PyObject *KeyBlock_getName( BPy_KeyBlock * self );
static PyObject *KeyBlock_getPos( BPy_KeyBlock * self );
static PyObject *KeyBlock_getSlidermin( BPy_KeyBlock * self );
@@ -107,6 +111,8 @@ static struct PyMethodDef KeyBlock_methods[] = {
};
static PyGetSetDef BPy_KeyBlock_getsetters[] = {
+ {"curval",(getter)KeyBlock_getCurval, (setter)NULL,
+ "Current value of the corresponding IpoCurve",NULL},
{"name",(getter)KeyBlock_getName, (setter)KeyBlock_setName,
"Keyblock Name",NULL},
{"pos",(getter)KeyBlock_getPos, (setter)NULL,
@@ -362,13 +368,32 @@ static int Key_setIpo( PyObject * self, PyObject * value )
return 0;
}
-static PyObject *Key_getType( PyObject * self )
+static PyObject *Key_getRelative( BPy_Key * self )
+{
+ if( self->key->type == KEY_RELATIVE )
+ return EXPP_incr_ret(Py_True);
+ else
+ return EXPP_incr_ret(Py_False);
+}
+
+static int Key_setRelative( BPy_Key * self, PyObject * value )
+{
+ if( PyObject_IsTrue( value ) )
+ self->key->type = KEY_RELATIVE;
+ else
+ self->key->type = KEY_NORMAL;
+ allqueue(REDRAWIPO, 0);
+ allspace(REMAKEIPO, 0);
+
+ return 0;
+}
+
+static PyObject *Key_getType( BPy_Key * self )
{
- BPy_Key *k = ( BPy_Key * ) self;
int idcode;
int type = -1;
- idcode = GS( k->key->from->name );
+ idcode = GS( self->key->from->name );
switch( idcode ) {
case ID_ME:
@@ -437,55 +462,51 @@ PyObject *KeyBlock_CreatePyObject( KeyBlock * kb, Key *parentKey )
return ( PyObject * ) keyBlock;
}
+static PyObject *KeyBlock_getCurval( BPy_KeyBlock * self ) {
+ return PyFloat_FromDouble( self->keyblock->curval );
+}
+
static PyObject *KeyBlock_getName( BPy_KeyBlock * self ) {
- BPy_KeyBlock *kb = ( BPy_KeyBlock * ) self;
- PyObject *name = Py_BuildValue( "s", kb->keyblock->name);
+ PyObject *name = Py_BuildValue( "s", self->keyblock->name);
return name;
}
static PyObject *KeyBlock_getPos( BPy_KeyBlock * self ){
- BPy_KeyBlock *kb = ( BPy_KeyBlock * ) self;
- return PyFloat_FromDouble( kb->keyblock->pos );
+ return PyFloat_FromDouble( self->keyblock->pos );
}
static PyObject *KeyBlock_getSlidermin( BPy_KeyBlock * self ){
- BPy_KeyBlock *kb = ( BPy_KeyBlock * ) self;
- return PyFloat_FromDouble( kb->keyblock->slidermin );
+ return PyFloat_FromDouble( self->keyblock->slidermin );
}
static PyObject *KeyBlock_getSlidermax( BPy_KeyBlock * self ){
- BPy_KeyBlock *kb = ( BPy_KeyBlock * ) self;
- return PyFloat_FromDouble( kb->keyblock->slidermax );
+ return PyFloat_FromDouble( self->keyblock->slidermax );
}
static PyObject *KeyBlock_getVgroup( BPy_KeyBlock * self ){
- BPy_KeyBlock *kb = ( BPy_KeyBlock * ) self;
- PyObject *name = Py_BuildValue( "s", kb->keyblock->vgroup);
- return name;
+ return Py_BuildValue( "s", self->keyblock->vgroup);
}
static int KeyBlock_setName( BPy_KeyBlock * self, PyObject * args ){
char* text = NULL;
- BPy_KeyBlock *kb = ( BPy_KeyBlock * ) self;
-
+
text = PyString_AsString ( args );
if( !text )
return EXPP_ReturnIntError( PyExc_TypeError,
"expected string argument" );
- strncpy( kb->keyblock->name, text , 32);
+ strncpy( self->keyblock->name, text , 32);
return 0;
}
static int KeyBlock_setVgroup( BPy_KeyBlock * self, PyObject * args ){
char* text = NULL;
- BPy_KeyBlock *kb = ( BPy_KeyBlock * ) self;
-
+
text = PyString_AsString ( args );
if( !text )
return EXPP_ReturnIntError( PyExc_TypeError,
"expected string argument" );
- strncpy( kb->keyblock->vgroup, text , 32);
+ strncpy( self->keyblock->vgroup, text , 32);
return 0;
}
@@ -635,7 +656,8 @@ static PyObject *M_Key_Get( PyObject * self, PyObject * args )
"expected string argument (or nothing)" ) );
if ( name ) {
- for (key_iter = G.main->key.first; key_iter; key_iter=key_iter->id.next) {
+ for (key_iter = G.main->key.first; key_iter;
+ key_iter=key_iter->id.next) {
if (strcmp ( key_iter->id.name + 2, name ) == 0 ) {
return Key_CreatePyObject( key_iter );
}
@@ -643,17 +665,16 @@ static PyObject *M_Key_Get( PyObject * self, PyObject * args )
PyOS_snprintf( error_msg, sizeof( error_msg ),
"Key \"%s\" not found", name );
- return ( EXPP_ReturnPyObjError ( PyExc_NameError, error_msg ) );
+ return EXPP_ReturnPyObjError ( PyExc_NameError, error_msg );
- }
-
- else {
+ } else {
PyObject *keylist;
keylist = PyList_New( BLI_countlist( &( G.main->key ) ) );
- for ( i=0, key_iter = G.main->key.first; key_iter; key_iter=key_iter->id.next, i++ ) {
+ for ( i=0, key_iter = G.main->key.first; key_iter;
+ key_iter=key_iter->id.next, i++ ) {
PyList_SetItem(keylist, i, Key_CreatePyObject(key_iter));
}
return keylist;
@@ -665,32 +686,36 @@ struct PyMethodDef M_Key_methods[] = {
{NULL, NULL, 0, NULL}
};
+static PyObject *M_Key_TypesDict( void )
+{
+ PyObject *T = PyConstant_New( );
+
+ if( T ) {
+ BPy_constant *d = ( BPy_constant * ) T;
+
+ PyConstant_Insert( d, "MESH", PyInt_FromLong( KEY_TYPE_MESH ) );
+ PyConstant_Insert( d, "CURVE", PyInt_FromLong( KEY_TYPE_CURVE ) );
+ PyConstant_Insert( d, "LATTICE", PyInt_FromLong( KEY_TYPE_LATTICE ) );
+ }
+
+ return T;
+}
+
PyObject *Key_Init( void )
{
- PyObject *submodule, *KeyTypes;
+ PyObject *submodule;
+ PyObject *Types = NULL;
- if( PyType_Ready( &Key_Type ) < 0)
+ if( PyType_Ready( &Key_Type ) < 0 || PyType_Ready( &KeyBlock_Type ) < 0 )
return NULL;
- Key_Type.ob_type = &PyType_Type;
- PyType_Ready( &KeyBlock_Type );
-
submodule =
Py_InitModule3( "Blender.Key", M_Key_methods, "Key module" );
- KeyTypes = PyConstant_New( );
-
- PyConstant_Insert(( BPy_constant * ) KeyTypes, "MESH", PyInt_FromLong(KEY_TYPE_MESH));
- PyConstant_Insert(( BPy_constant * ) KeyTypes, "CURVE", PyInt_FromLong(KEY_TYPE_CURVE));
- PyConstant_Insert(( BPy_constant * ) KeyTypes, "LATTICE", PyInt_FromLong(KEY_TYPE_LATTICE));
-
- PyModule_AddObject( submodule, "Types", KeyTypes);
+ Types = M_Key_TypesDict( );
+ if( Types )
+ PyModule_AddObject( submodule, "Types", Types );
- /*
- PyModule_AddIntConstant( submodule, "TYPE_MESH", KEY_TYPE_MESH );
- PyModule_AddIntConstant( submodule, "TYPE_CURVE", KEY_TYPE_CURVE );
- PyModule_AddIntConstant( submodule, "TYPE_LATTICE", KEY_TYPE_LATTICE );
- */
return submodule;
}
diff --git a/source/blender/python/api2_2x/Mesh.c b/source/blender/python/api2_2x/Mesh.c
index 0bb882a046c..91b86947a83 100644
--- a/source/blender/python/api2_2x/Mesh.c
+++ b/source/blender/python/api2_2x/Mesh.c
@@ -82,8 +82,6 @@
#include "constant.h"
#include "gen_utils.h"
-#define MESH_TOOLS /* add access to mesh tools */
-
/* EXPP Mesh defines */
#define MESH_SMOOTHRESH 30
@@ -126,6 +124,7 @@ typedef struct SrchEdges {
typedef struct SrchFaces {
unsigned int v[4]; /* indices for verts */
+ unsigned int index; /* index in original param list of this edge */
unsigned char order; /* order of original verts, bitpacked */
} SrchFaces;
@@ -156,6 +155,22 @@ int medge_comp( const void *va, const void *vb )
}
/*
+ * compare edges by insert list indices
+ */
+
+int medge_index_comp( const void *va, const void *vb )
+{
+ const SrchEdges *a = (SrchEdges *)va;
+ const SrchEdges *b = (SrchEdges *)vb;
+
+ /* compare list indices for differences */
+
+ if (a->index < b->index) return -1;
+ else return (a->index > b->index);
+}
+
+
+/*
* compare faces by vertex indices
*/
@@ -191,6 +206,23 @@ int mface_comp( const void *va, const void *vb )
}
/*
+ * compare faces by insert list indices
+ */
+
+int mface_index_comp( const void *va, const void *vb )
+{
+ const SrchFaces *a = va;
+ const SrchFaces *b = vb;
+
+ /* compare indices, first to last, for differences */
+ if( a->index < b->index )
+ return -1;
+ if( a->index > b->index )
+ return 1;
+ return 0;
+}
+
+/*
* compare edges by vertex indices
*/
@@ -1386,7 +1418,7 @@ static PyObject *MVertSeq_item( BPy_MVertSeq * self, int i )
"array index out of range" );
return MVert_CreatePyObject( self->mesh, i );
-};
+}
/*
* retrieve a slice of the vertex list (as a Python list)
@@ -1453,7 +1485,7 @@ static int MVertSeq_assign_item( BPy_MVertSeq * self, int i,
memcpy( dst, src, sizeof(MVert) );
// mesh_update( self->mesh );
return 0;
-};
+}
static int MVertSeq_assign_slice( BPy_MVertSeq *self, int low, int high,
PyObject *args )
@@ -1566,39 +1598,42 @@ static PyObject *MVertSeq_extend( BPy_MVertSeq * self, PyObject *args )
Mesh *mesh = self->mesh;
/* make sure we get a sequence of tuples of something */
- switch( PySequence_Size ( args ) ) {
+ switch( PySequence_Size( args ) ) {
case 1: /* better be a list or a tuple */
tmp = PyTuple_GET_ITEM( args, 0 );
if( !VectorObject_Check ( tmp ) ) {
if( !PySequence_Check ( tmp ) )
return EXPP_ReturnPyObjError( PyExc_TypeError,
- "expected a sequence of tuple triplets" );
+ "expected a sequence of sequence triplets" );
args = tmp;
}
Py_INCREF( args ); /* so we can safely DECREF later */
break;
- case 3: /* take any three args and put into a tuple */
+ case 3:
tmp = PyTuple_GET_ITEM( args, 0 );
- if( PyTuple_Check( tmp ) ) {
- Py_INCREF( args );
- break;
- }
+ /* if first item is not a number, it's wrong */
+ if( !PyNumber_Check( tmp ) )
+ return EXPP_ReturnPyObjError( PyExc_TypeError,
+ "expected a sequence of sequence triplets" );
+
+ /* otherwise, put into a new tuple */
args = Py_BuildValue( "((OOO))", tmp,
PyTuple_GET_ITEM( args, 1 ), PyTuple_GET_ITEM( args, 2 ) );
if( !args )
return EXPP_ReturnPyObjError( PyExc_RuntimeError,
"Py_BuildValue() failed" );
break;
+
default: /* anything else is definitely wrong */
return EXPP_ReturnPyObjError( PyExc_TypeError,
- "expected a sequence of tuple triplets" );
+ "expected a sequence of sequence triplets" );
}
+ /* if no verts given, return quietly */
len = PySequence_Size( args );
if( len == 0 ) {
Py_DECREF ( args );
- return EXPP_ReturnPyObjError( PyExc_ValueError,
- "expected at least one tuple" );
+ Py_RETURN_NONE;
}
newlen = mesh->totvert + len;
@@ -1620,18 +1655,19 @@ static PyObject *MVertSeq_extend( BPy_MVertSeq * self, PyObject *args )
}
for( j = 0; j < 3; ++j )
co[j] = ((VectorObject *)tmp)->vec[j];
- } else if( PyTuple_Check( tmp ) ) {
+ } else if( PySequence_Check( tmp ) ) {
int ok=1;
PyObject *flt;
- if( PyTuple_Size( tmp ) != 3 )
+ if( PySequence_Size( tmp ) != 3 )
ok = 0;
else
for( j = 0; ok && j < 3; ++j ) {
- flt = PyTuple_GET_ITEM( tmp, j );
+ flt = PySequence_ITEM( tmp, j );
if( !PyNumber_Check ( flt ) )
ok = 0;
else
co[j] = (float)PyFloat_AsDouble( flt );
+ Py_DECREF( flt );
}
if( !ok ) {
@@ -1639,9 +1675,16 @@ static PyObject *MVertSeq_extend( BPy_MVertSeq * self, PyObject *args )
Py_DECREF ( args );
Py_DECREF ( tmp );
return EXPP_ReturnPyObjError( PyExc_ValueError,
- "expected tuple triplet of floats" );
+ "expected sequence triplet of floats" );
}
+ } else {
+ MEM_freeN( newvert );
+ Py_DECREF ( args );
+ Py_DECREF ( tmp );
+ return EXPP_ReturnPyObjError( PyExc_ValueError,
+ "expected sequence triplet of floats" );
}
+
Py_DECREF ( tmp );
/* add the coordinate to the new list */
@@ -1714,7 +1757,7 @@ static PyObject *MVertSeq_extend( BPy_MVertSeq * self, PyObject *args )
mesh_update( mesh );
Py_DECREF ( args );
- return EXPP_incr_ret( Py_None );
+ Py_RETURN_NONE;
}
static PyObject *MVertSeq_delete( BPy_MVertSeq * self, PyObject *args )
@@ -1725,15 +1768,20 @@ static PyObject *MVertSeq_delete( BPy_MVertSeq * self, PyObject *args )
Mesh *mesh = self->mesh;
MFace *tmpface;
- Py_INCREF( args ); /* so we can safely DECREF later */
-
- /* accept a sequence (lists or tuples) also */
+ /*
+ * if input tuple contains a single sequence, use it as input instead;
+ * otherwise use the sequence as-is and check later that it contains
+ * one or more integers or MVerts
+ */
if( PySequence_Size( args ) == 1 ) {
PyObject *tmp = PyTuple_GET_ITEM( args, 0 );
- if( PySequence_Check ( tmp ) ) {
- Py_DECREF( args ); /* release previous reference */
- args = tmp; /* PyTuple_GET_ITEM returns new ref */
- }
+ if( PySequence_Check( tmp ) )
+ args = tmp;
+ }
+
+ /* if sequence is empty, do nothing */
+ if( PySequence_Size( args ) == 0 ) {
+ Py_RETURN_NONE;
}
/* allocate vertex lookup table */
@@ -1747,18 +1795,15 @@ static PyObject *MVertSeq_delete( BPy_MVertSeq * self, PyObject *args )
if( BPy_MVert_Check( tmp ) ) {
if( (void *)self->mesh != ((BPy_MVert*)tmp)->data ) {
MEM_freeN( vert_table );
- Py_DECREF( args );
Py_DECREF( tmp );
return EXPP_ReturnPyObjError( PyExc_ValueError,
"MVert belongs to a different mesh" );
}
index = ((BPy_MVert*)tmp)->index;
- }
- else if( PyInt_CheckExact( tmp ) )
+ } else if( PyInt_CheckExact( tmp ) ) {
index = PyInt_AsLong ( tmp );
- else {
+ } else {
MEM_freeN( vert_table );
- Py_DECREF( args );
Py_DECREF( tmp );
return EXPP_ReturnPyObjError( PyExc_TypeError,
"expected a sequence of ints or MVerts" );
@@ -1766,8 +1811,7 @@ static PyObject *MVertSeq_delete( BPy_MVertSeq * self, PyObject *args )
Py_DECREF( tmp );
if( index < 0 || index >= mesh->totvert ) {
MEM_freeN( vert_table );
- Py_DECREF( args );
- return EXPP_ReturnPyObjError( PyExc_ValueError,
+ return EXPP_ReturnPyObjError( PyExc_IndexError,
"array index out of range" );
}
vert_table[index] = UINT_MAX;
@@ -1802,8 +1846,7 @@ static PyObject *MVertSeq_delete( BPy_MVertSeq * self, PyObject *args )
/* clean up and exit */
MEM_freeN( vert_table );
mesh_update ( mesh );
- Py_DECREF( args );
- return EXPP_incr_ret( Py_None );
+ Py_RETURN_NONE;
}
static PyObject *MVertSeq_selected( BPy_MVertSeq * self )
@@ -2413,40 +2456,52 @@ static PyObject *MEdgeSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
MEdge *tmpedge;
Mesh *mesh = self->mesh;
- /* make sure we get a sequence of tuples of something */
-
- switch( PySequence_Size ( args ) ) {
- case 1: /* better be a list or a tuple */
- args = PyTuple_GET_ITEM( args, 0 );
- if( !PySequence_Check ( args ) )
+ /* make sure we get a tuple of sequences of something */
+ switch( PySequence_Size( args ) ) {
+ case 1:
+ /* if a sequence... */
+ tmp = PyTuple_GET_ITEM( args, 0 );
+ if( PySequence_Check( tmp ) ) {
+ /* if another sequence, use it */
+ PyObject *tmp2 = PySequence_ITEM( tmp, 0 );
+ if( PySequence_Check( tmp2 ) )
+ args = tmp;
+ Py_INCREF( args );
+ Py_DECREF( tmp2 );
+ } else
return EXPP_ReturnPyObjError( PyExc_TypeError,
- "expected a sequence of tuple pairs" );
- Py_INCREF( args ); /* so we can safely DECREF later */
+ "expected a sequence of sequence pairs" );
break;
case 2:
case 3:
case 4: /* two to four args may be individual verts */
tmp = PyTuple_GET_ITEM( args, 0 );
- if( PyTuple_Check( tmp ) ) {/* maybe just tuples, so use args as-is */
+ /*
+ * if first item isn't a sequence, then assume it's a bunch of MVerts
+ * and wrap inside a tuple
+ */
+ if( !PySequence_Check( tmp ) ) {
+ args = Py_BuildValue( "(O)", args );
+ if( !args )
+ return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+ "Py_BuildValue() failed" );
+ /*
+ * otherwise, assume it already a bunch of sequences so use as-is
+ */
+ } else {
Py_INCREF( args ); /* so we can safely DECREF later */
- break;
}
- args = Py_BuildValue( "(O)", args );
- if( !args )
- return EXPP_ReturnPyObjError( PyExc_RuntimeError,
- "Py_BuildValue() failed" );
break;
default: /* anything else is definitely wrong */
return EXPP_ReturnPyObjError( PyExc_TypeError,
- "expected a sequence of tuple pairs" );
+ "expected a sequence of sequence pairs" );
}
/* make sure there is something to add */
len = PySequence_Size( args );
if( len == 0 ) {
- Py_DECREF( args );
- return EXPP_ReturnPyObjError( PyExc_ValueError,
- "expected at least one tuple" );
+ Py_DECREF ( args );
+ Py_RETURN_NONE;
}
/* verify the param list and get a total count of number of edges */
@@ -2455,21 +2510,21 @@ static PyObject *MEdgeSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
tmp = PySequence_GetItem( args, i );
/* not a tuple of MVerts... error */
- if( !PyTuple_Check( tmp ) ||
+ if( !PySequence_Check( tmp ) ||
EXPP_check_sequence_consistency( tmp, &MVert_Type ) != 1 ) {
Py_DECREF( tmp );
Py_DECREF( args );
return EXPP_ReturnPyObjError( PyExc_ValueError,
- "expected sequence of MVert tuples" );
+ "expected sequence of MVert sequences" );
}
/* not the right number of MVerts... error */
- nverts = PyTuple_Size( tmp );
+ nverts = PySequence_Size( tmp );
if( nverts < 2 || nverts > 4 ) {
Py_DECREF( tmp );
Py_DECREF( args );
return EXPP_ReturnPyObjError( PyExc_ValueError,
- "expected 2 to 4 MVerts per tuple" );
+ "expected 2 to 4 MVerts per sequence" );
}
Py_DECREF( tmp );
@@ -2486,14 +2541,15 @@ static PyObject *MEdgeSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
/* scan the input list and build the new edge pair list */
len = PySequence_Size( args );
tmppair = newpair;
+ new_edge_count = 0;
for( i = 0; i < len; ++i ) {
int edge_count;
tmp = PySequence_GetItem( args, i );
- nverts = PyTuple_Size( tmp );
+ nverts = PySequence_Size( tmp );
- /* get copies of vertices */
+ /* get new references for the vertices */
for(j = 0; j < nverts; ++j )
- e[j] = (BPy_MVert *)PyTuple_GET_ITEM( tmp, j );
+ e[j] = (BPy_MVert *)PySequence_GetItem( tmp, j );
Py_DECREF( tmp );
if( nverts == 2 )
@@ -2518,12 +2574,20 @@ static PyObject *MEdgeSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
tmppair->swap = 1;
} else {
MEM_freeN( newpair );
+ for(j = 0; j < nverts; ++j )
+ Py_DECREF( e[j] );
Py_DECREF( args );
return EXPP_ReturnPyObjError( PyExc_ValueError,
"tuple contains duplicate vertices" );
}
+ tmppair->index = new_edge_count;
+ ++new_edge_count;
tmppair++;
}
+
+ /* free the new references */
+ for( j = 0; j < nverts; ++j )
+ Py_DECREF( e[j] );
}
/* sort the new edge pairs */
@@ -2605,6 +2669,9 @@ static PyObject *MEdgeSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
}
mesh->medge = tmpedge; /* point to the new edge list */
+ /* resort edges into original order */
+ qsort( newpair, new_edge_count, sizeof(SrchEdges), medge_index_comp );
+
/* point to the first edge we're going to add */
tmpedge = &mesh->medge[mesh->totedge];
tmppair = newpair;
@@ -2632,7 +2699,7 @@ static PyObject *MEdgeSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
mesh_update( mesh );
MEM_freeN( newpair );
Py_DECREF ( args );
- return EXPP_incr_ret( Py_None );
+ Py_RETURN_NONE;
}
static PyObject *MEdgeSeq_delete( BPy_MEdgeSeq * self, PyObject *args )
@@ -2644,19 +2711,23 @@ static PyObject *MEdgeSeq_delete( BPy_MEdgeSeq * self, PyObject *args )
int i, len;
int face_count, edge_count, vert_count;
- Py_INCREF( args ); /* so we can safely DECREF later */
-
- /* accept a sequence (lists or tuples) also */
+ /*
+ * if input tuple contains a single sequence, use it as input instead;
+ * otherwise use the sequence as-is and check later that it contains
+ * one or more integers or MVerts
+ */
if( PySequence_Size( args ) == 1 ) {
PyObject *tmp = PyTuple_GET_ITEM( args, 0 );
- if( PySequence_Check ( tmp ) ) {
- Py_DECREF( args ); /* release previous reference */
- args = tmp; /* PyTuple_GET_ITEM returns new ref */
- }
+ if( PySequence_Check( tmp ) )
+ args = tmp;
}
- /* see how many args we need to parse */
+ /* if sequence is empty, do nothing */
len = PySequence_Size( args );
+ if( len == 0 ) {
+ Py_RETURN_NONE;
+ }
+
edge_table = (unsigned int *)MEM_callocN( len*sizeof( unsigned int ),
"edge_table" );
@@ -2670,7 +2741,6 @@ static PyObject *MEdgeSeq_delete( BPy_MEdgeSeq * self, PyObject *args )
else {
MEM_freeN( edge_table );
Py_DECREF( tmp );
- Py_DECREF( args );
return EXPP_ReturnPyObjError( PyExc_TypeError,
"expected a sequence of ints or MEdges" );
}
@@ -2679,7 +2749,6 @@ static PyObject *MEdgeSeq_delete( BPy_MEdgeSeq * self, PyObject *args )
/* if index out-of-range, throw exception */
if( edge_table[i] >= (unsigned int)mesh->totedge ) {
MEM_freeN( edge_table );
- Py_DECREF( args );
return EXPP_ReturnPyObjError( PyExc_ValueError,
"array index out of range" );
}
@@ -2773,9 +2842,8 @@ static PyObject *MEdgeSeq_delete( BPy_MEdgeSeq * self, PyObject *args )
MEM_freeN( del_table );
MEM_freeN( vert_table );
MEM_freeN( edge_table );
- Py_DECREF( args );
mesh_update ( mesh );
- return EXPP_incr_ret( Py_None );
+ Py_RETURN_NONE;
}
static PyObject *MEdgeSeq_selected( BPy_MEdgeSeq * self )
@@ -3388,21 +3456,22 @@ static int MFace_setUV( BPy_MFace * self, PyObject * value )
if( !MFace_get_pointer( self ) )
return -1;
- if( !PyTuple_Check( value ) ||
+ if( !PySequence_Check( value ) ||
EXPP_check_sequence_consistency( value, &vector_Type ) != 1 )
return EXPP_ReturnIntError( PyExc_TypeError,
- "expected tuple of vectors" );
+ "expected sequence of vectors" );
length = self->mesh->mface[self->index].v4 ? 4 : 3;
- if( length != PyTuple_Size( value ) )
+ if( length != PySequence_Size( value ) )
return EXPP_ReturnIntError( PyExc_TypeError,
- "size of vertex and UV lists differ" );
+ "size of vertex and UV sequences differ" );
face = &self->mesh->tface[self->index];
for( i=0; i<length; ++i ) {
- VectorObject *vector = (VectorObject *)PyTuple_GET_ITEM( value, i );
+ VectorObject *vector = (VectorObject *)PySequence_ITEM( value, i );
face->uv[i][0] = vector->vec[0];
face->uv[i][1] = vector->vec[1];
+ Py_DECREF( vector );
}
return 0;
}
@@ -3531,6 +3600,54 @@ static PyObject *MFace_getCol( BPy_MFace * self )
return attr;
}
+/*
+ * set a face's vertex colors
+ */
+
+static int MFace_setCol( BPy_MFace * self, PyObject *value )
+{
+ int length, i;
+ MCol * mcol;
+
+ /* if there's no mesh color vectors or texture faces, nothing to do */
+
+ if( !self->mesh->mcol && !self->mesh->tface )
+ return EXPP_ReturnIntError( PyExc_ValueError,
+ "face has no vertex colors" );
+
+ if( !MFace_get_pointer( self ) )
+ return -1;
+
+ if( self->mesh->tface )
+ mcol = (MCol *) self->mesh->tface[self->index].col;
+ else
+ mcol = &self->mesh->mcol[self->index*4];
+
+ length = self->mesh->mface[self->index].v4 ? 4 : 3;
+
+ if( !PyList_Check( value ) && !PyTuple_Check( value ) )
+ return EXPP_ReturnIntError( PyExc_TypeError,
+ "expected a sequence of MCols" );
+
+ if( EXPP_check_sequence_consistency( value, &MCol_Type ) != 1 )
+ return EXPP_ReturnIntError( PyExc_TypeError,
+ "expected a sequence of MCols" );
+
+ if( PySequence_Size( value ) != length )
+ return EXPP_ReturnIntError( PyExc_ValueError,
+ "incorrect number of colors for this face" );
+
+ for( i=0; i<length; ++i ) {
+ BPy_MCol *obj = (BPy_MCol *)PySequence_ITEM( value, i );
+ mcol[i].r = obj->color->r;
+ mcol[i].g = obj->color->g;
+ mcol[i].b = obj->color->b;
+ mcol[i].a = obj->color->a;
+ Py_DECREF( obj );
+ }
+ return 0;
+}
+
/************************************************************************
*
* Python MFace_Type attributes get/set structure
@@ -3575,7 +3692,7 @@ static PyGetSetDef BPy_MFace_getseters[] = {
/* attributes for texture faces (mostly, I think) */
{"col",
- (getter)MFace_getCol, (setter)NULL,
+ (getter)MFace_getCol, (setter)MFace_setCol,
"face's vertex colors",
NULL},
{"flag",
@@ -3888,43 +4005,56 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
tmp = MEdgeSeq_extend( self, args );
if( !tmp )
return NULL;
-
+
Py_DECREF( tmp );
- /* make sure we get a sequence of tuples of something */
+ /* make sure we get a tuple of sequences of something */
- switch( PySequence_Size ( args ) ) {
- case 1: /* better be a list or a tuple */
- args = PyTuple_GET_ITEM( args, 0 );
- if( !PySequence_Check ( args ) )
+ switch( PySequence_Size( args ) ) {
+ case 1: /* better be a sequence or a tuple */
+ /* if a sequence... */
+ tmp = PyTuple_GET_ITEM( args, 0 );
+ if( PySequence_Check( tmp ) ) {
+ /* if another sequence, use it */
+ PyObject *tmp2 = PySequence_ITEM( tmp, 0 );
+ if( PySequence_Check( tmp2 ) )
+ args = tmp;
+ Py_INCREF( args );
+ Py_DECREF( tmp2 );
+ } else
return EXPP_ReturnPyObjError( PyExc_TypeError,
- "expected a sequence of tuple pairs" );
- Py_INCREF( args ); /* so we can safely DECREF later */
+ "expected a sequence of sequence pairs" );
break;
case 2:
case 3:
case 4: /* two to four args may be individual verts */
tmp = PyTuple_GET_ITEM( args, 0 );
- if( PyTuple_Check( tmp ) ) {/* maybe just tuples, so use args as-is */
+ /*
+ * if first item isn't a sequence, then assume it's a bunch of MVerts
+ * and wrap inside a tuple
+ */
+ if( !PySequence_Check( tmp ) ) {
+ args = Py_BuildValue( "(O)", args );
+ if( !args )
+ return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+ "Py_BuildValue() failed" );
+ /*
+ * otherwise, assume it already a bunch of sequences so use as-is
+ */
+ } else {
Py_INCREF( args ); /* so we can safely DECREF later */
- break;
}
- args = Py_BuildValue( "(O)", args );
- if( !args )
- return EXPP_ReturnPyObjError( PyExc_RuntimeError,
- "Py_BuildValue() failed" );
break;
default: /* anything else is definitely wrong */
return EXPP_ReturnPyObjError( PyExc_TypeError,
- "expected a sequence of tuple pairs" );
+ "expected a sequence of sequence pairs" );
}
- /* make sure there is something to add */
+ /* if nothing to add, just exit */
len = PySequence_Size( args );
if( len == 0 ) {
Py_DECREF( args );
- return EXPP_ReturnPyObjError( PyExc_ValueError,
- "expected at least one tuple" );
+ Py_RETURN_NONE;
}
/* verify the param list and get a total count of number of edges */
@@ -3933,19 +4063,19 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
tmp = PySequence_GetItem( args, i );
/* not a tuple of MVerts... error */
- if( !PyTuple_Check( tmp ) ||
+ if( !PySequence_Check( tmp ) ||
EXPP_check_sequence_consistency( tmp, &MVert_Type ) != 1 ) {
Py_DECREF( args );
return EXPP_ReturnPyObjError( PyExc_ValueError,
- "expected sequence of MVert tuples" );
+ "expected sequence of MVert sequences" );
}
/* not the right number of MVerts... error */
- nverts = PyTuple_Size( tmp );
+ nverts = PySequence_Size( tmp );
if( nverts < 2 || nverts > 4 ) {
Py_DECREF( args );
return EXPP_ReturnPyObjError( PyExc_ValueError,
- "expected 2 to 4 MVerts per tuple" );
+ "expected 2 to 4 MVerts per sequence" );
}
if( nverts != 2 ) /* new faces cannot have only 2 verts */
@@ -3965,7 +4095,7 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
unsigned int vert[4]={0,0,0,0};
unsigned char order[4]={0,1,2,3};
tmp = PySequence_GetItem( args, i );
- nverts = PyTuple_Size( tmp );
+ nverts = PySequence_Size( tmp );
if( nverts == 2 ) /* again, ignore 2-vert tuples */
break;
@@ -3975,15 +4105,19 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
* vertices are not index 0
*/
- e = (BPy_MVert *)PyTuple_GET_ITEM( tmp, 0 );
+ e = (BPy_MVert *)PySequence_ITEM( tmp, 0 );
tmpface.v1 = e->index;
- e = (BPy_MVert *)PyTuple_GET_ITEM( tmp, 1 );
+ Py_DECREF( e );
+ e = (BPy_MVert *)PySequence_ITEM( tmp, 1 );
tmpface.v2 = e->index;
- e = (BPy_MVert *)PyTuple_GET_ITEM( tmp, 2 );
+ Py_DECREF( e );
+ e = (BPy_MVert *)PySequence_ITEM( tmp, 2 );
tmpface.v3 = e->index;
+ Py_DECREF( e );
if( nverts == 4 ) {
- e = (BPy_MVert *)PyTuple_GET_ITEM( tmp, 3 );
+ e = (BPy_MVert *)PySequence_ITEM( tmp, 3 );
tmpface.v4 = e->index;
+ Py_DECREF( e );
}
Py_DECREF( tmp );
@@ -4016,6 +4150,7 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
}
tmppair->v[j] = vert[j];
}
+ tmppair->index = i;
/* pack order into a byte */
tmppair->order = order[0]|(order[1]<<2)|(order[2]<<4)|(order[3]<<6);
@@ -4111,6 +4246,9 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
mesh->tface = tmptface;
}
+ /* sort the faces back into their original input list order */
+ qsort( newpair, new_face_count, sizeof(SrchFaces), mface_index_comp );
+
/* allocate new face list */
tmpface = MEM_callocN(totface*sizeof(MFace), "Mesh_addFaces");
@@ -4157,7 +4295,7 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
mesh_update( mesh );
Py_DECREF ( args );
MEM_freeN( newpair );
- return EXPP_incr_ret( Py_None );
+ Py_RETURN_NONE;
}
struct fourEdges
@@ -4196,7 +4334,7 @@ static PyObject *MFaceSeq_delete( BPy_MFaceSeq * self, PyObject *args )
if( BPy_MFace_Check( tmp ) )
face_table[i] = ((BPy_MFace *)tmp)->index;
else if( PyInt_CheckExact( tmp ) )
- face_table[i] = PyInt_AsLong ( tmp );
+ face_table[i] = PyInt_AsLong( tmp );
else {
MEM_freeN( face_table );
Py_DECREF( tmp );
@@ -4276,7 +4414,7 @@ static PyObject *MFaceSeq_delete( BPy_MFaceSeq * self, PyObject *args )
verts[0] = tmpface->v1;
verts[1] = tmpface->v2;
verts[2] = tmpface->v3;
- if(len == 4)
+ if( len == 4 )
verts[3] = tmpface->v4;
for( j = 0; j < len; ++j ) {
k = (j+1) % len;
@@ -5373,7 +5511,53 @@ static PyObject *Mesh_getVertGroupNames( BPy_Mesh * self )
return list;
}
-#ifdef MESH_TOOLS
+static PyObject *Mesh_getVertexInfluences( BPy_Mesh * self, PyObject * args )
+{
+ int index;
+ PyObject *influence_list = NULL;
+ Object *object = self->object;
+ Mesh *me = self->mesh;
+
+ /* Get a reference to the mesh object wrapped in here. */
+ if( !object )
+ return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+ "This mesh must be linked to an object" );
+
+ /* Parse the parameters: only on integer (vertex index) */
+ if( !PyArg_ParseTuple( args, "i", &index ) )
+ return EXPP_ReturnPyObjError( PyExc_TypeError,
+ "expected int argument (index of the vertex)" );
+
+ /* check for valid index */
+ if( index < 0 || index >= me->totvert )
+ return EXPP_ReturnPyObjError( PyExc_IndexError,
+ "vertex index out of range" );
+
+ influence_list = PyList_New( 0 );
+
+ /* Proceed only if we have vertex deformation information */
+ if( me->dvert ) {
+ int i;
+ MDeformWeight *sweight = NULL;
+
+ /* Number of bones influencing the vertex */
+ int totinfluences = me->dvert[index].totweight;
+
+ /* Get the reference of the first weight structure */
+ sweight = me->dvert[index].dw;
+
+ /* Build the list only with weights and names of the influent bones */
+ for( i = 0; i < totinfluences; i++, sweight++ ) {
+ bDeformGroup *defgroup = BLI_findlink( &object->defbase,
+ sweight->def_nr );
+ if( defgroup )
+ PyList_Append( influence_list, Py_BuildValue( "[sf]",
+ defgroup->name, sweight->weight ) );
+ }
+ }
+
+ return influence_list;
+}
static PyObject *Mesh_Tools( BPy_Mesh * self, int type, void **args )
{
@@ -5575,8 +5759,6 @@ static PyObject *Mesh_fill( BPy_Mesh * self )
return Mesh_Tools( self, MESH_TOOL_FILL, NULL );
}
-#endif
-
static struct PyMethodDef BPy_Mesh_methods[] = {
{"calcNormals", (PyCFunction)Mesh_calcNormals, METH_NOARGS,
"all recalculate vertex normals"},
@@ -5604,10 +5786,10 @@ static struct PyMethodDef BPy_Mesh_methods[] = {
"Rename an existing vertex group"},
{"getVertGroupNames", (PyCFunction)Mesh_getVertGroupNames, METH_NOARGS,
"Get names of vertex groups"},
+ {"getVertexInfluences", (PyCFunction)Mesh_getVertexInfluences, METH_VARARGS,
+ "Get list of the influences of bones for a given mesh vertex"},
-
-
-#ifdef MESH_TOOLS
+ /* Mesh tools */
{"smooth", (PyCFunction)Mesh_smooth, METH_NOARGS,
"Flattens angle of selected faces (experimental)"},
{"flipNormals", (PyCFunction)Mesh_flipNormals, METH_NOARGS,
@@ -5626,7 +5808,6 @@ static struct PyMethodDef BPy_Mesh_methods[] = {
"Removes duplicates from selected vertices (experimental)"},
{"recalcNormals", (PyCFunction)Mesh_recalcNormals, METH_VARARGS,
"Recalculates inside or outside normals (experimental)"},
-#endif
{NULL, NULL, 0, NULL}
};
@@ -5906,8 +6087,12 @@ static int Mesh_setFlag( BPy_Mesh * self, PyObject *value, void *type )
MEM_freeN( mesh->tface );
mesh->tface = NULL;
}
- } else if( !mesh->tface )
+ } else if( !mesh->tface ) {
+ if( !mesh->totface )
+ return EXPP_ReturnIntError( PyExc_RuntimeError,
+ "mesh has no faces" );
make_tfaces( mesh );
+ }
return 0;
case MESH_HASMCOL:
if( !param ) {
@@ -6098,8 +6283,6 @@ static PyGetSetDef BPy_Mesh_getseters[] = {
(getter)Mesh_getMode, (setter)Mesh_setMode,
"The mesh's mode bitfield",
NULL},
-
-
{"faceUV",
(getter)Mesh_getFlag, (setter)Mesh_setFlag,
"UV-mapped textured faces enabled",
@@ -6125,11 +6308,6 @@ static PyGetSetDef BPy_Mesh_getseters[] = {
};
/*****************************************************************************/
-/* Python Mesh_Type callback function prototypes: */
-/*****************************************************************************/
-static void Mesh_dealloc( BPy_Mesh * object );
-
-/*****************************************************************************/
/* Python Mesh_Type structure definition: */
/*****************************************************************************/
PyTypeObject Mesh_Type = {
@@ -6329,6 +6507,28 @@ static PyObject *M_Mesh_MVert( PyObject * self, PyObject * args )
return PVert_CreatePyObject( &vert );
}
+static PyObject *M_Mesh_Modes( PyObject * self, PyObject * args )
+{
+ int modes = 0;
+
+ if( !G.scene ) {
+ Py_RETURN_NONE;
+ }
+
+ if( !PyArg_ParseTuple( args, "|i", &modes ) )
+ return EXPP_ReturnPyObjError( PyExc_TypeError,
+ "expected optional int as argument" );
+
+ if( modes > ( SCE_SELECT_VERTEX | SCE_SELECT_EDGE | SCE_SELECT_FACE ) )
+ return EXPP_ReturnPyObjError( PyExc_ValueError,
+ "value out of range" );
+
+ if( modes > 0 )
+ G.scene->selectmode = modes;
+
+ return PyInt_FromLong( G.scene->selectmode );
+}
+
static struct PyMethodDef M_Mesh_methods[] = {
{"New", (PyCFunction)M_Mesh_New, METH_VARARGS,
"Create a new mesh"},
@@ -6336,10 +6536,12 @@ static struct PyMethodDef M_Mesh_methods[] = {
"Get a mesh by name"},
{"MVert", (PyCFunction)M_Mesh_MVert, METH_VARARGS,
"Create a new MVert"},
+ {"Mode", (PyCFunction)M_Mesh_Modes, METH_VARARGS,
+ "Get/set edit selection mode(s)"},
{NULL, NULL, 0, NULL},
};
-static PyObject *M_Mesh_Modes( void )
+static PyObject *M_Mesh_ModesDict( void )
{
PyObject *Modes = PyConstant_New( );
@@ -6444,18 +6646,32 @@ static PyObject *M_Mesh_VertAssignDict( void )
return Vert;
}
+
+static PyObject *M_Mesh_SelectModeDict( void )
+{
+ PyObject *Mode = PyConstant_New( );
+ if( Mode ) {
+ BPy_constant *d = ( BPy_constant * ) Mode;
+ PyConstant_Insert(d, "VERTEX", PyInt_FromLong(SCE_SELECT_VERTEX));
+ PyConstant_Insert(d, "EDGE", PyInt_FromLong(SCE_SELECT_EDGE));
+ PyConstant_Insert(d, "FACE", PyInt_FromLong(SCE_SELECT_FACE));
+ }
+ return Mode;
+}
+
static char M_Mesh_doc[] = "The Blender.Mesh submodule";
PyObject *Mesh_Init( void )
{
PyObject *submodule;
- PyObject *Modes = M_Mesh_Modes( );
- PyObject *FaceFlags = M_Mesh_FaceFlagsDict( );
- PyObject *FaceModes = M_Mesh_FaceModesDict( );
- PyObject *FaceTranspModes = M_Mesh_FaceTranspModesDict( );
+ PyObject *Modes = M_Mesh_ModesDict( );
+ PyObject *FaceFlags = M_Mesh_FaceFlagsDict( );
+ PyObject *FaceModes = M_Mesh_FaceModesDict( );
+ PyObject *FaceTranspModes = M_Mesh_FaceTranspModesDict( );
PyObject *EdgeFlags = M_Mesh_EdgeFlagsDict( );
- PyObject *AssignModes = M_Mesh_VertAssignDict( );
+ PyObject *AssignModes = M_Mesh_VertAssignDict( );
+ PyObject *SelectModes = M_Mesh_SelectModeDict( );
if( PyType_Ready( &MCol_Type ) < 0 )
return NULL;
@@ -6491,6 +6707,8 @@ PyObject *Mesh_Init( void )
PyModule_AddObject( submodule, "EdgeFlags", EdgeFlags );
if( AssignModes )
PyModule_AddObject( submodule, "AssignModes", AssignModes );
+ if( SelectModes )
+ PyModule_AddObject( submodule, "SelectModes", SelectModes );
return submodule;
diff --git a/source/blender/python/api2_2x/NLA.c b/source/blender/python/api2_2x/NLA.c
index c1ed37bfe43..dd891472155 100644
--- a/source/blender/python/api2_2x/NLA.c
+++ b/source/blender/python/api2_2x/NLA.c
@@ -471,11 +471,15 @@ PyObject *Action_CreatePyObject( struct bAction * act )
{
BPy_Action *blen_action;
+ if(!act)
+ return EXPP_incr_ret(Py_None);
+
blen_action =
( BPy_Action * ) PyObject_NEW( BPy_Action, &Action_Type );
- if( blen_action == NULL ) {
- return ( NULL );
+ if( !blen_action) {
+ return ( EXPP_ReturnPyObjError
+ ( PyExc_RuntimeError, "failure to create object!" ) );
}
blen_action->action = act;
return ( ( PyObject * ) blen_action );
diff --git a/source/blender/python/api2_2x/NLA.h b/source/blender/python/api2_2x/NLA.h
index 11b44f2401b..07632124bba 100644
--- a/source/blender/python/api2_2x/NLA.h
+++ b/source/blender/python/api2_2x/NLA.h
@@ -39,6 +39,8 @@
/** NLA module initialization function. */
PyObject *NLA_Init( void );
+extern PyTypeObject Action_Type;
+
/** Python BPy_NLA structure definition. */
typedef struct {
PyObject_HEAD
diff --git a/source/blender/python/api2_2x/NMesh.c b/source/blender/python/api2_2x/NMesh.c
index f285557d5ee..293b9a2f3f4 100644
--- a/source/blender/python/api2_2x/NMesh.c
+++ b/source/blender/python/api2_2x/NMesh.c
@@ -1466,71 +1466,55 @@ static PyObject *NMesh_update( PyObject *self, PyObject *a, PyObject *kwd )
* influences that this vertex receives.
* @author Jordi Rovira i Bonet
*/
+
static PyObject *NMesh_getVertexInfluences( PyObject * self, PyObject * args )
{
int index;
PyObject *influence_list = NULL;
-
- /* Get a reference to the mesh object wrapped in here. */
+ Object *object = ( ( BPy_NMesh * ) self )->object;
Mesh *me = ( ( BPy_NMesh * ) self )->mesh;
+ /* Get a reference to the mesh object wrapped in here. */
if( !me )
return EXPP_ReturnPyObjError( PyExc_RuntimeError,
- "unlinked nmesh: call its .update() method first" );
+ "unlinked nmesh: call its .update() method first" );
+
+ if( !object )
+ return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+ "This mesh must be linked to an object" );
/* Parse the parameters: only on integer (vertex index) */
if( !PyArg_ParseTuple( args, "i", &index ) )
return EXPP_ReturnPyObjError( PyExc_TypeError,
- "expected int argument (index of the vertex)" );
+ "expected int argument (index of the vertex)" );
+
+ /* check for valid index */
+ if( index < 0 || index >= me->totvert )
+ return EXPP_ReturnPyObjError( PyExc_IndexError,
+ "vertex index out of range" );
+
+ influence_list = PyList_New( 0 );
- /* Proceed only if we have vertex deformation information and index is valid */
+ /* Proceed only if we have vertex deformation information */
if( me->dvert ) {
- if( ( index >= 0 ) && ( index < me->totvert ) ) {
-
- int i;
- MDeformWeight *sweight = NULL;
-
- /* Number of bones influencing the vertex */
- int totinfluences = me->dvert[index].totweight;
-
- /* Build the list only with weights and names of the influent bones */
- /*influence_list = PyList_New(totinfluences); */
- influence_list = PyList_New( 0 );
-
- /* Get the reference of the first weight structure */
- sweight = me->dvert[index].dw;
-
- for( i = 0; i < totinfluences; i++ ) {
- /*Add the weight and the name of the bone, which is used to identify it */
-
- /* Disabled this code, it couldn't be correct!
- * sweight->data was being set to a posechannel not a bone
- * for one thing, and it is not always set for another.
- * The only thing safe here is to return the defgroup number. -zr
- */
-// if( sweight->data )
- /* valid bone: return its name */
- /* PyList_SetItem(influence_list, i,
- Py_BuildValue("[sf]", sweight->data->name, sweight->weight));
- else // NULL bone: return Py_None instead
- PyList_SetItem(influence_list, i,
- Py_BuildValue("[Of]", Py_None, sweight->weight)); */
-// PyList_Append( influence_list,
-// Py_BuildValue( "[sf]",
-// sweight->
-// data->
-// name,
-// sweight->
-// weight ) );
-
- /* Next weight */
- sweight++;
- }
- } else //influence_list = PyList_New(0);
- return EXPP_ReturnPyObjError( PyExc_IndexError,
- "vertex index out of range" );
- } else
- influence_list = PyList_New( 0 );
+ int i;
+ MDeformWeight *sweight = NULL;
+
+ /* Number of bones influencing the vertex */
+ int totinfluences = me->dvert[index].totweight;
+
+ /* Get the reference of the first weight structure */
+ sweight = me->dvert[index].dw;
+
+ /* Build the list only with weights and names of the influent bones */
+ for( i = 0; i < totinfluences; i++, sweight++ ) {
+ bDeformGroup *defgroup = (bDeformGroup *) BLI_findlink( &object->defbase,
+ sweight->def_nr );
+ if( defgroup )
+ PyList_Append( influence_list, Py_BuildValue( "[sf]",
+ defgroup->name, sweight->weight ) );
+ }
+ }
return influence_list;
}
diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c
index 77179aad819..89ad6f36576 100644
--- a/source/blender/python/api2_2x/Object.c
+++ b/source/blender/python/api2_2x/Object.c
@@ -100,7 +100,9 @@ struct rctf;
#include "NLA.h"
#include "logic.h"
#include "Effect.h"
+#include "Pose.h"
#include "gen_utils.h"
+#include "BIF_editkey.h"
/* Defines for insertIpoKey */
@@ -291,6 +293,7 @@ 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 );
+static PyObject *Object_insertShapeKey(BPy_Object * self);
/*****************************************************************************/
/* Python BPy_Object methods table: */
/*****************************************************************************/
@@ -322,7 +325,7 @@ If 'name_only' is nonzero or True, only the name of the datablock is returned"},
{"getAction", ( PyCFunction ) Object_getAction, METH_NOARGS,
"Returns the active action for this object"},
{"getPose", ( PyCFunction ) Object_getPose, METH_NOARGS,
- "Returns the pose for this object"},
+ "() - returns the pose from an object if it exists, else None"},
{"isSelected", ( PyCFunction ) Object_isSelected, METH_NOARGS,
"Return a 1 or 0 depending on whether the object is selected"},
{"getEuler", ( PyCFunction ) Object_getEuler, METH_NOARGS,
@@ -585,7 +588,8 @@ works only if self and the object specified are of the same type."},
"([s1<,s2,s3...>]) - Delete specified scriptlinks from this object."},
{"setDupliVerts", ( PyCFunction ) Object_setDupliVerts,
METH_VARARGS, "() - set or reset duplicate child objects on all vertices"},
-
+ {"insertShapeKey", ( PyCFunction ) Object_insertShapeKey,
+ METH_NOARGS, "() - Insert a Shape Key in the current object"},
{NULL, NULL, 0, NULL}
};
@@ -750,9 +754,13 @@ PyObject *M_Object_Get( PyObject * self, PyObject * args )
object = GetObjectByName( name );
/* No object exists with the name specified in the argument name. */
- if( !object )
- return EXPP_ReturnPyObjError( PyExc_AttributeError,
- "Unknown object specified." );
+ if( !object ){
+ char buffer[128];
+ PyOS_snprintf( buffer, sizeof(buffer),
+ "object \"%s\" not found", name);
+ return EXPP_ReturnPyObjError( PyExc_ValueError,
+ buffer );
+ }
return Object_CreatePyObject( object );
} else {
@@ -883,7 +891,7 @@ static PyObject *M_Object_Duplicate( PyObject * self, PyObject * args, PyObject
/*****************************************************************************/
PyObject *Object_Init( void )
{
- PyObject *module;
+ PyObject *module, *dict;
Object_Type.ob_type = &PyType_Type;
@@ -908,6 +916,11 @@ PyObject *Object_Init( void )
PyModule_AddIntConstant( module, "MAGNET",PFIELD_MAGNET );
PyModule_AddIntConstant( module, "WIND",PFIELD_WIND );
+ //Add SUBMODULES to the module
+ dict = PyModule_GetDict( module ); //borrowed
+ PyDict_SetItemString(dict, "Pose", Pose_Init()); //creates a *new* module
+ //PyDict_SetItemString(dict, "Constraint", Constraint_Init()); //creates a *new* module
+
return ( module );
}
@@ -1178,6 +1191,7 @@ static PyObject *Object_getAction( BPy_Object * self )
}
}
+#if 0
static PyObject *Object_getPose( BPy_Object * self )
{
/*BPy_Action *py_action = NULL; */
@@ -1190,6 +1204,14 @@ static PyObject *Object_getPose( BPy_Object * self )
return Pose_CreatePyObject( self->object->pose );
}
+#endif
+
+static PyObject * Object_getPose(BPy_Object *self)
+{
+ //if there is no pose will return PyNone
+ return PyPose_FromPose(self->object->pose, self->object->id.name+2);
+}
+
static PyObject *Object_isSelected( BPy_Object * self )
{
Base *base;
@@ -3011,6 +3033,12 @@ static PyObject *Object_getEffects( BPy_Object * self )
return effect_list;
}
+static PyObject *Object_insertShapeKey(BPy_Object * self)
+{
+ insert_shapekey(self->object);
+ return Py_None;
+}
+
/*****************************************************************************/
/* Function: Object_CreatePyObject */
/* Description: This function will create a new BlenObject from an existing */
diff --git a/source/blender/python/api2_2x/Pose.c b/source/blender/python/api2_2x/Pose.c
index 42fe8c516e7..577eb1029a3 100644
--- a/source/blender/python/api2_2x/Pose.c
+++ b/source/blender/python/api2_2x/Pose.c
@@ -1,143 +1,940 @@
+/*
+ * $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.
+ *
+ * Contributor(s): Joseph Gilbert
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+*/
+
#include "Pose.h"
-#include "NLA.h"
-//Action is still there, may move to Action.h
-// Action_Type used for typechecking
-#include "Types.h"
-#include <Python.h>
-//#include <DNA_action_types.h>
-#include "gen_utils.h"
+
+
+#include "mydevice.h"
+#include "BKE_armature.h"
+#include "BKE_main.h"
+#include "BKE_global.h"
#include "BKE_action.h"
+#include "BKE_utildefines.h"
+#include "BIF_editaction.h"
+#include "BIF_space.h"
+#include "BKE_depsgraph.h"
+#include "DNA_object_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h" //1 - this order
+#include "BSE_editipo.h" //2
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "Mathutils.h"
+#include "Object.h"
+#include "NLA.h"
+#include "gen_utils.h"
-static void Pose_dealloc( PyObject *self );
-static PyObject *Pose_repr( BPy_Pose *self );
-static PyObject *Pose_fromAction( BPy_Pose *self, PyObject *args);
+extern void chan_calc_mat(bPoseChannel *chan);
+
+//------------------------ERROR CODES---------------------------------
+//This is here just to make me happy and to have more consistant error strings :)
+static const char sPoseError[] = "Pose - Error: ";
+static const char sPoseBadArgs[] = "Pose - Bad Arguments: ";
+static const char sPoseBoneError[] = "PoseBone - Error: ";
+static const char sPoseBoneBadArgs[] = "PoseBone - Bad Arguments: ";
+static const char sPoseBonesDictError[] = "PoseBone - Error: ";
+static const char sPoseBonesDictBadArgs[] = "PoseBone - Bad Arguments: ";
+
+//################## PoseBonesDict_Type (internal) ########################
+/*This is an internal psuedo-dictionary type that allows for manipulation
+* of posechannels inside of a pose structure. It is a subobject of pose.
+* i.e. Pose.bones['key']*/
+//################################################################
+
+//------------------METHOD IMPLEMENTATIONS-----------------------------
+//------------------------Pose.bones.items()
+//Returns a list of key:value pairs like dict.items()
+PyObject* PoseBonesDict_items(BPy_PoseBonesDict *self)
+{
+ return PyDict_Items(self->bonesMap);
+}
+//------------------------Pose.bones.keys()
+//Returns a list of keys like dict.keys()
+PyObject* PoseBonesDict_keys(BPy_PoseBonesDict *self)
+{
+ return PyDict_Keys(self->bonesMap);
+}
+//------------------------Armature.bones.values()
+//Returns a list of values like dict.values()
+PyObject* PoseBonesDict_values(BPy_PoseBonesDict *self)
+{
+ return PyDict_Values(self->bonesMap);
+}
+//------------------ATTRIBUTE IMPLEMENTATION---------------------------
+//------------------TYPE_OBECT IMPLEMENTATION-----------------------
+//------------------------tp_doc
+//The __doc__ string for this object
+static char BPy_PoseBonesDict_doc[] = "This is an internal subobject of pose\
+designed to act as a Py_PoseBone dictionary.";
-static struct PyMethodDef Pose_methods[] = {
- {"fromAction", ( PyCFunction ) Pose_fromAction,
- METH_VARARGS, "() - sets the pose based on an action and given time in it."},
- {0, 0, 0, 0}
+//------------------------tp_methods
+//This contains a list of all methods the object contains
+static PyMethodDef BPy_PoseBonesDict_methods[] = {
+ {"items", (PyCFunction) PoseBonesDict_items, METH_NOARGS,
+ "() - Returns the key:value pairs from the dictionary"},
+ {"keys", (PyCFunction) PoseBonesDict_keys, METH_NOARGS,
+ "() - Returns the keys the dictionary"},
+ {"values", (PyCFunction) PoseBonesDict_values, METH_NOARGS,
+ "() - Returns the values from the dictionary"},
+ {NULL, NULL, 0, NULL}
};
+//-----------------(internal)
+static int PoseBoneMapping_Init(PyObject *dictionary, ListBase *posechannels){
+ bPoseChannel *pchan = NULL;
+ PyObject *py_posechannel = NULL;
-static PyGetSetDef BPy_Pose_getsetters[] = {
-// {"type",(getter)Key_getType, (setter)NULL,
- {NULL,NULL,NULL,NULL,NULL} /* Sentinel */
- };
+ for (pchan = posechannels->first; pchan; pchan = pchan->next){
+ py_posechannel = PyPoseBone_FromPosechannel(pchan);
+ if (!py_posechannel)
+ return -1;
-PyTypeObject Pose_Type = {
- PyObject_HEAD_INIT( NULL ) 0, /*ob_size */
- "Blender Pose", /*tp_name */
- sizeof( BPy_Pose ), /*tp_basicsize */
- 0, /*tp_itemsize */
- /* methods */
- ( destructor ) Pose_dealloc, /*tp_dealloc */
- ( printfunc ) 0, /*tp_print */
- ( getattrfunc ) 0, /*tp_getattr */
- ( setattrfunc ) 0, /*tp_setattr */
- 0, /*tp_compare*/
- ( reprfunc ) Pose_repr, /* tp_repr */
- /* Method suites for standard classes */
-
- NULL, /* PyNumberMethods *tp_as_number; */
- NULL, /* PySequenceMethods *tp_as_sequence; */
- NULL, /* PyMappingMethods *tp_as_mapping; */
-
- /* More standard operations (here for binary compatibility) */
-
- NULL, /* hashfunc tp_hash; */
- NULL, /* ternaryfunc tp_call; */
- NULL, /* reprfunc tp_str; */
- NULL, /* getattrofunc tp_getattro; */
- NULL, /* setattrofunc tp_setattro; */
-
- /* Functions to access object as input/output buffer */
- NULL, /* PyBufferProcs *tp_as_buffer; */
-
- /*** Flags to define presence of optional/expanded features ***/
- Py_TPFLAGS_DEFAULT, /* long tp_flags; */
-
- NULL, /* char *tp_doc; Documentation string */
- /*** Assigned meaning in release 2.0 ***/
- /* call function for all accessible objects */
- NULL, /* traverseproc tp_traverse; */
-
- /* delete references to contained objects */
- NULL, /* inquiry tp_clear; */
-
- /*** Assigned meaning in release 2.1 ***/
- /*** rich comparisons ***/
- NULL, /* richcmpfunc tp_richcompare; */
-
- /*** weak reference enabler ***/
- 0, /* long tp_weaklistoffset; */
-
- /*** Added in release 2.2 ***/
- /* Iterators */
- NULL, /* getiterfunc tp_iter; */
- NULL, /* iternextfunc tp_iternext; */
-
- /*** Attribute descriptor and subclassing stuff ***/
- Pose_methods, /* struct PyMethodDef *tp_methods; */
- NULL, /* struct PyMemberDef *tp_members; */
- BPy_Pose_getsetters, /* struct PyGetSetDef *tp_getset; */
- NULL, /* struct _typeobject *tp_base; */
- NULL, /* PyObject *tp_dict; */
- NULL, /* descrgetfunc tp_descr_get; */
- NULL, /* descrsetfunc tp_descr_set; */
- 0, /* long tp_dictoffset; */
- NULL, /* initproc tp_init; */
- NULL, /* allocfunc tp_alloc; */
- NULL, /* newfunc tp_new; */
- /* Low-level free-memory routine */
- NULL, /* freefunc tp_free; */
- /* For PyObject_IS_GC */
- NULL, /* inquiry tp_is_gc; */
- NULL, /* PyObject *tp_bases; */
- /* method resolution order */
- NULL, /* PyObject *tp_mro; */
- NULL, /* PyObject *tp_cache; */
- NULL, /* PyObject *tp_subclasses; */
- NULL, /* PyObject *tp_weaklist; */
- NULL
+ if(PyDict_SetItem(dictionary,
+ PyString_FromString(pchan->name), py_posechannel) == -1){
+ return -1;
+ }
+ Py_DECREF(py_posechannel);
+ }
+ return 0;
+}
+
+//----------------- BonesDict_InitBones
+static int PoseBonesDict_InitBones(BPy_PoseBonesDict *self)
+{
+ PyDict_Clear(self->bonesMap);
+ if (PoseBoneMapping_Init(self->bonesMap, self->bones) == -1)
+ return 0;
+ return 1;
+}
+
+//------------------------tp_repr
+//This is the string representation of the object
+static PyObject *PoseBonesDict_repr(BPy_PoseBonesDict *self)
+{
+ char buffer[128], str[4096];
+ PyObject *key, *value;
+ int pos = 0;
+
+ BLI_strncpy(str,"",4096);
+ sprintf(buffer, "[Pose Bone Dict: {");
+ strcat(str,buffer);
+ while (PyDict_Next(self->bonesMap, &pos, &key, &value)) {
+ sprintf(buffer, "%s : %s, ", PyString_AsString(key),
+ PyString_AsString(value->ob_type->tp_repr(value)));
+ strcat(str,buffer);
+ }
+ sprintf(buffer, "}]\n");
+ strcat(str,buffer);
+ return PyString_FromString(str);
+}
+
+//------------------------tp_dealloc
+//This tells how to 'tear-down' our object when ref count hits 0
+static void PoseBonesDict_dealloc(BPy_PoseBonesDict * self)
+{
+ Py_DECREF(self->bonesMap);
+ PoseBonesDict_Type.tp_free(self);
+ return;
+}
+//------------------------mp_length
+//This gets the size of the dictionary
+int PoseBonesDict_len(BPy_PoseBonesDict *self)
+{
+ return BLI_countlist(self->bones);
+}
+//-----------------------mp_subscript
+//This defines getting a bone from the dictionary - x = Bones['key']
+PyObject *PoseBonesDict_GetItem(BPy_PoseBonesDict *self, PyObject* key)
+{
+ PyObject *value = NULL;
+
+ value = PyDict_GetItem(self->bonesMap, key);
+ if(value == NULL){
+ return EXPP_incr_ret(Py_None);
+ }
+ return EXPP_incr_ret(value);
+}
+//------------------TYPE_OBECT DEFINITION--------------------------
+//Mapping Protocol
+static PyMappingMethods PoseBonesDict_MapMethods = {
+ (inquiry) PoseBonesDict_len, //mp_length
+ (binaryfunc)PoseBonesDict_GetItem, //mp_subscript
+ 0, //mp_ass_subscript
+};
+//PoseBonesDict TypeObject
+PyTypeObject PoseBonesDict_Type = {
+ PyObject_HEAD_INIT(NULL) //tp_head
+ 0, //tp_internal
+ "PoseBonesDict", //tp_name
+ sizeof(BPy_PoseBonesDict), //tp_basicsize
+ 0, //tp_itemsize
+ (destructor)PoseBonesDict_dealloc, //tp_dealloc
+ 0, //tp_print
+ 0, //tp_getattr
+ 0, //tp_setattr
+ 0, //tp_compare
+ (reprfunc) PoseBonesDict_repr, //tp_repr
+ 0, //tp_as_number
+ 0, //tp_as_sequence
+ &PoseBonesDict_MapMethods, //tp_as_mapping
+ 0, //tp_hash
+ 0, //tp_call
+ 0, //tp_str
+ 0, //tp_getattro
+ 0, //tp_setattro
+ 0, //tp_as_buffer
+ Py_TPFLAGS_DEFAULT, //tp_flags
+ BPy_PoseBonesDict_doc, //tp_doc
+ 0, //tp_traverse
+ 0, //tp_clear
+ 0, //tp_richcompare
+ 0, //tp_weaklistoffset
+ 0, //tp_iter
+ 0, //tp_iternext
+ BPy_PoseBonesDict_methods, //tp_methods
+ 0, //tp_members
+ 0, //tp_getset
+ 0, //tp_base
+ 0, //tp_dict
+ 0, //tp_descr_get
+ 0, //tp_descr_set
+ 0, //tp_dictoffset
+ 0, //tp_init
+ 0, //tp_alloc
+ 0, //tp_new
+ 0, //tp_free
+ 0, //tp_is_gc
+ 0, //tp_bases
+ 0, //tp_mro
+ 0, //tp_cache
+ 0, //tp_subclasses
+ 0, //tp_weaklist
+ 0 //tp_del
};
+//-----------------------PyPoseBonesDict_FromPyPose
+static PyObject *PyPoseBonesDict_FromPyPose(BPy_Pose *py_pose)
+{
+ BPy_PoseBonesDict *py_posebonesdict = NULL;
+
+ //create py object
+ py_posebonesdict = (BPy_PoseBonesDict *)PoseBonesDict_Type.tp_alloc(&PoseBonesDict_Type, 0);
+ if (!py_posebonesdict)
+ goto RuntimeError;
-static void Pose_dealloc( PyObject * self )
+ //create internal dictionaries
+ py_posebonesdict->bonesMap = PyDict_New();
+ if (!py_posebonesdict->bonesMap)
+ goto RuntimeError;
+
+ //set listbase pointer
+ py_posebonesdict->bones = &py_pose->pose->chanbase;
+
+ //now that everything is setup - init the mappings
+ if (!PoseBonesDict_InitBones(py_posebonesdict))
+ goto RuntimeError;
+
+ return (PyObject*)py_posebonesdict;
+
+RuntimeError:
+ return EXPP_objError(PyExc_RuntimeError, "%s%s",
+ sPoseBonesDictError, "Failed to create class");
+}
+
+//################## Pose_Type ##########################
+/*This type is a wrapper for a pose*/
+//####################################################
+//------------------METHOD IMPLEMENTATIONS------------------------------
+static PyObject *Pose_update(BPy_Pose *self)
+{
+ Object *daddy = NULL;
+
+ self->pose->flag |= POSE_RECALC;
+
+ for (daddy = G.main->object.first; daddy; daddy = daddy->id.next){
+ if (daddy->pose == self->pose){
+ break;
+ }
+ }
+
+ if(daddy)
+ where_is_pose(daddy);
+
+ return EXPP_incr_ret(Py_None);
+}
+//------------------------tp_methods
+//This contains a list of all methods the object contains
+static PyMethodDef BPy_Pose_methods[] = {
+ {"update", (PyCFunction) Pose_update, METH_NOARGS,
+ "() - Rebuilds the pose with new values"},
+ {NULL, NULL, 0, NULL}
+};
+//------------------ATTRIBUTE IMPLEMENTATIONS---------------------------
+//------------------------Pose.bones (getter)
+//Gets the bones attribute
+static PyObject *Pose_getBoneDict(BPy_Pose *self, void *closure)
+{
+ return EXPP_incr_ret((PyObject*)self->Bones);
+}
+//------------------------Pose.bones (setter)
+//Sets the bones attribute
+static int Pose_setBoneDict(BPy_Pose *self, PyObject *value, void *closure)
+{
+ goto AttributeError;
+
+AttributeError:
+ return EXPP_intError(PyExc_AttributeError, "%s%s",
+ sPoseError, "You are not allowed to change the .bones attribute");
+}
+//------------------TYPE_OBECT IMPLEMENTATION---------------------------
+//------------------------tp_getset
+//This contains methods for attributes that require checking
+static PyGetSetDef BPy_Pose_getset[] = {
+ {"bones", (getter)Pose_getBoneDict, (setter)Pose_setBoneDict,
+ "The pose's Bone dictionary", NULL},
+ {NULL, NULL, NULL, NULL, NULL}
+};
+//------------------------tp_dealloc
+//This tells how to 'tear-down' our object when ref count hits 0
+static void Pose_dealloc(BPy_Pose *self)
{
- PyObject_DEL( self );
+ Py_DECREF(self->Bones);
+ Pose_Type.tp_free(self);
+ return;
}
+//------------------------tp_repr
+//This is the string representation of the object
+static PyObject *Pose_repr(BPy_Pose *self)
+{
+ return PyString_FromFormat( "[Pose \"%s\"]", self->name);
+}
+//------------------------tp_doc
+//The __doc__ string for this object
+static char BPy_Pose_doc[] = "This object wraps a Blender Pose object.";
-PyObject *Pose_CreatePyObject( struct bPose * pose )
- {
- BPy_Pose *pypose;
-
- pypose =
- ( BPy_Pose * ) PyObject_NEW( BPy_Pose, &Pose_Type );
+//------------------TYPE_OBECT DEFINITION--------------------------
+PyTypeObject Pose_Type = {
+ PyObject_HEAD_INIT(NULL) //tp_head
+ 0, //tp_internal
+ "Pose", //tp_name
+ sizeof(BPy_Pose), //tp_basicsize
+ 0, //tp_itemsize
+ (destructor)Pose_dealloc, //tp_dealloc
+ 0, //tp_print
+ 0, //tp_getattr
+ 0, //tp_setattr
+ 0, //tp_compare
+ (reprfunc)Pose_repr, //tp_repr
+ 0, //tp_as_number
+ 0, //tp_as_sequence
+ 0, //tp_as_mapping
+ 0, //tp_hash
+ 0, //tp_call
+ 0, //tp_str
+ 0, //tp_getattro
+ 0, //tp_setattro
+ 0, //tp_as_buffer
+ Py_TPFLAGS_DEFAULT, //tp_flags
+ BPy_Pose_doc, //tp_doc
+ 0, //tp_traverse
+ 0, //tp_clear
+ 0, //tp_richcompare
+ 0, //tp_weaklistoffset
+ 0, //tp_iter
+ 0, //tp_iternext
+ BPy_Pose_methods, //tp_methods
+ 0, //tp_members
+ BPy_Pose_getset, //tp_getset
+ 0, //tp_base
+ 0, //tp_dict
+ 0, //tp_descr_get
+ 0, //tp_descr_set
+ 0, //tp_dictoffset
+ 0, //tp_init
+ 0, //tp_alloc
+ 0, //tp_new
+ 0, //tp_free
+ 0, //tp_is_gc
+ 0, //tp_bases
+ 0, //tp_mro
+ 0, //tp_cache
+ 0, //tp_subclasses
+ 0, //tp_weaklist
+ 0 //tp_del
+};
+//################## PoseBone_Type #####################
+/*This type is a wrapper for a posechannel*/
+//####################################################
+//------------------METHOD IMPLEMENTATIONS------------------------------
+//------------------------------PoseBone.insertKey()
+static PyObject *PoseBone_insertKey(BPy_PoseBone *self, PyObject *args)
+{
+ PyObject *parent_object = NULL;
+ PyObject *constants = NULL, *item = NULL;
+ int frame = 1, oldframe, length, x, numeric_value = 0, oldflag;
+ bPoseChannel *pchan = NULL;
- if( !pypose )
- return EXPP_ReturnPyObjError( PyExc_MemoryError,
- "couldn't create BPy_Pose object" );
- PyType_Ready(&Pose_Type);
+ if (!PyArg_ParseTuple(args, "O!i|O", &Object_Type, &parent_object, &frame, &constants ))
+ goto AttributeError;
+
+ //verify that this pchannel is part of the object->pose
+ for (pchan = ((BPy_Object*)parent_object)->object->pose->chanbase.first;
+ pchan; pchan = pchan->next){
+ if (pchan == self->posechannel)
+ break;
+ }
+ if (!pchan)
+ goto AttributeError2;
+
+ //verify that there is an action bound to this object
+ if (!((BPy_Object*)parent_object)->object->action){
+ goto AttributeError5;
+ }
- pypose->pose = pose;
- return ( ( PyObject * ) pypose );
+ oldflag = self->posechannel->flag;
+ self->posechannel->flag = 0;
+ //set the flags for this posechannel
+ if (constants){
+ if(PySequence_Check(constants)){
+ length = PySequence_Length(constants);
+ for (x = 0; x < length; x++){
+ item = PySequence_GetItem(constants, x);
+ if (item == EXPP_GetModuleConstant("Blender.Object.Pose", "ROT")){
+ numeric_value |= POSE_ROT;
+ }else if (item == EXPP_GetModuleConstant("Blender.Object.Pose", "LOC")){
+ numeric_value |= POSE_LOC;
+ }else if (item == EXPP_GetModuleConstant("Blender.Object.Pose", "SIZE")){
+ numeric_value |= POSE_SIZE;
+ }else{
+ Py_DECREF(item);
+ self->posechannel->flag = (short)oldflag;
+ goto AttributeError4;
+ }
+ Py_DECREF(item);
+ }
+ self->posechannel->flag = (short)numeric_value;
+ }else if (BPy_Constant_Check(constants)){
+ if (constants == EXPP_GetModuleConstant("Blender.Object.Pose", "ROT")){
+ numeric_value |= POSE_ROT;
+ }else if (constants == EXPP_GetModuleConstant("Blender.Object.Pose", "LOC")){
+ numeric_value |= POSE_LOC;
+ }else if (constants == EXPP_GetModuleConstant("Blender.Object.Pose", "SIZE")){
+ numeric_value |= POSE_SIZE;
+ }else{
+ self->posechannel->flag = (short)oldflag;
+ goto AttributeError4;
+ }
+ self->posechannel->flag = (short)numeric_value;
+ }else{
+ goto AttributeError3;
+ }
+ }else{ //nothing passed so set them all
+ self->posechannel->flag |= POSE_ROT;
+ self->posechannel->flag |= POSE_LOC;
+ self->posechannel->flag |= POSE_SIZE;
}
-static PyObject *Pose_fromAction( BPy_Pose *self, PyObject *args) {
- BPy_Action *action;
- float time;
- float factor = 1.0;
+ //set the frame we want insertion on
+ oldframe = G.scene->r.cfra;
+ G.scene->r.cfra = (short)frame;
+
+ //add the action channel if it's not there
+ verify_action_channel(((BPy_Object*)parent_object)->object->action,
+ self->posechannel->name);
+
+ //insert the pose keys
+ if (self->posechannel->flag & POSE_ROT){
+ insertkey(&((BPy_Object*)parent_object)->object->id,
+ ID_PO, self->posechannel->name, NULL, AC_QUAT_X);
+ insertkey(&((BPy_Object*)parent_object)->object->id,
+ ID_PO, self->posechannel->name, NULL, AC_QUAT_Y);
+ insertkey(&((BPy_Object*)parent_object)->object->id,
+ ID_PO, self->posechannel->name, NULL, AC_QUAT_Z);
+ insertkey(&((BPy_Object*)parent_object)->object->id,
+ ID_PO, self->posechannel->name, NULL, AC_QUAT_W);
+ }
+ if (self->posechannel->flag & POSE_LOC){
+ insertkey(&((BPy_Object*)parent_object)->object->id,
+ ID_PO, self->posechannel->name, NULL, AC_LOC_X);
+ insertkey(&((BPy_Object*)parent_object)->object->id,
+ ID_PO, self->posechannel->name, NULL, AC_LOC_Y);
+ insertkey(&((BPy_Object*)parent_object)->object->id,
+ ID_PO, self->posechannel->name, NULL, AC_LOC_Z);
+ }
+ if (self->posechannel->flag & POSE_SIZE){
+ insertkey(&((BPy_Object*)parent_object)->object->id,
+ ID_PO, self->posechannel->name, NULL, AC_SIZE_X);
+ insertkey(&((BPy_Object*)parent_object)->object->id,
+ ID_PO, self->posechannel->name, NULL, AC_SIZE_Y);
+ insertkey(&((BPy_Object*)parent_object)->object->id,
+ ID_PO, self->posechannel->name, NULL, AC_SIZE_Z);
+ }
- if (!PyArg_ParseTuple(args, "O!f|f", &Action_Type, &action, &time, &factor))
- return EXPP_ReturnPyObjError(PyExc_AttributeError, "An action and a time (as number) required as arguments.");
+ //flip the frame back
+ G.scene->r.cfra = (short)oldframe;
- //todo: range check for time
+ //update the IPOs
+ remake_action_ipos (((BPy_Object*)parent_object)->object->action);
- extract_pose_from_action(self->pose, action->action, time);
+ return EXPP_incr_ret(Py_None);
- Py_RETURN_NONE;
+AttributeError:
+ return EXPP_objError(PyExc_AttributeError, "%s%s%s",
+ sPoseBoneError, ".insertKey: ", "expects an Object, int, (optional) constants");
+AttributeError2:
+ return EXPP_objError(PyExc_AttributeError, "%s%s%s",
+ sPoseBoneError, ".insertKey: ", "wrong object detected. \
+ Use the object this pose came from");
+AttributeError3:
+ return EXPP_objError(PyExc_AttributeError, "%s%s%s",
+ sPoseBoneError, ".insertKey: ", "Expects a constant or list of constants");
+AttributeError4:
+ return EXPP_objError(PyExc_AttributeError, "%s%s%s",
+ sPoseBoneError, ".insertKey: ", "Please use a constant defined in the Pose module");
+AttributeError5:
+ return EXPP_objError(PyExc_AttributeError, "%s%s%s",
+ sPoseBoneError, ".insertKey: ", "You must set up and link an Action to this object first");
}
+//------------------------tp_methods
+//This contains a list of all methods the object contains
+static PyMethodDef BPy_PoseBone_methods[] = {
+ {"insertKey", (PyCFunction) PoseBone_insertKey, METH_VARARGS,
+ "() - insert a key for this pose into an action"},
+ {NULL, NULL, 0, NULL}
+};
+//------------------ATTRIBUTE IMPLEMENTATIONS---------------------------
+//------------------------PoseBone.name (getter)
+//Gets the name attribute
+static PyObject *PoseBone_getName(BPy_PoseBone *self, void *closure)
+{
+ return PyString_FromString(self->posechannel->name);
+}
+//------------------------PoseBone.name (setter)
+//Sets the name attribute
+static int PoseBone_setName(BPy_PoseBone *self, PyObject *value, void *closure)
+{
+ char *name = "";
+
+ if (!PyArg_Parse(value, "s", &name))
+ goto AttributeError;
-static PyObject *Pose_repr( BPy_Pose * self )
+ BLI_strncpy(self->posechannel->name, name, 32);
+ return 0;
+
+AttributeError:
+ return EXPP_intError(PyExc_AttributeError, "%s%s%s",
+ sPoseBoneError, ".name: ", "expects a string");
+}
+//------------------------PoseBone.loc (getter)
+//Gets the loc attribute
+static PyObject *PoseBone_getLoc(BPy_PoseBone *self, void *closure)
+{
+ return newVectorObject(self->posechannel->loc, 3, Py_WRAP);
+}
+//------------------------PoseBone.loc (setter)
+//Sets the loc attribute
+static int PoseBone_setLoc(BPy_PoseBone *self, PyObject *value, void *closure)
{
- return PyString_FromFormat( "[Pose]"); // \"%s\"]", self->key->id.name + 2 );
+ VectorObject *vec = NULL;
+ int x;
+
+ if (!PyArg_Parse(value, "O!", &vector_Type, &vec))
+ goto AttributeError;
+ if (vec->size != 3)
+ goto AttributeError;
+
+ for (x = 0; x < 3; x++){
+ self->posechannel->loc[x] = vec->vec[x];
+ }
+ return 0;
+
+AttributeError:
+ return EXPP_intError(PyExc_AttributeError, "%s%s%s",
+ sPoseBoneError, ".loc: ", "expects a 3d vector object");
+}
+//------------------------PoseBone.size (getter)
+//Gets the size attribute
+static PyObject *PoseBone_getSize(BPy_PoseBone *self, void *closure)
+{
+ return newVectorObject(self->posechannel->size, 3, Py_WRAP);
+}
+//------------------------PoseBone.size (setter)
+//Sets the size attribute
+static int PoseBone_setSize(BPy_PoseBone *self, PyObject *value, void *closure)
+{
+ VectorObject *vec = NULL;
+ int x;
+
+ if (!PyArg_Parse(value, "O!", &vector_Type, &vec))
+ goto AttributeError;
+ if (vec->size != 3)
+ goto AttributeError;
+
+ for (x = 0; x < 3; x++){
+ self->posechannel->size[x] = vec->vec[x];
+ }
+ return 0;
+
+AttributeError:
+ return EXPP_intError(PyExc_AttributeError, "%s%s%s",
+ sPoseBoneError, ".size: ", "expects a 3d vector object");
+}
+//------------------------PoseBone.quat (getter)
+//Gets the quat attribute
+static PyObject *PoseBone_getQuat(BPy_PoseBone *self, void *closure)
+{
+ return newQuaternionObject(self->posechannel->quat, Py_WRAP);
+}
+//------------------------PoseBone.quat (setter)
+//Sets the quat attribute
+static int PoseBone_setQuat(BPy_PoseBone *self, PyObject *value, void *closure)
+{
+ QuaternionObject *quat = NULL;
+ int x;
+
+ if (!PyArg_Parse(value, "O!", &quaternion_Type, &quat))
+ goto AttributeError;
+
+ for (x = 0; x < 4; x++){
+ self->posechannel->quat[x] = quat->quat[x];
+ }
+ return 0;
+
+AttributeError:
+ return EXPP_intError(PyExc_AttributeError, "%s%s%s",
+ sPoseBoneError, ".quat: ", "expects a quaternion object");
+}
+//------------------------PoseBone.localMatrix (getter)
+//Gets the chan_mat
+static PyObject *PoseBone_getLocalMatrix(BPy_PoseBone *self, void *closure)
+{
+ return newMatrixObject((float*)self->posechannel->chan_mat, 4, 4, Py_WRAP);
+}
+//------------------------PoseBone.localMatrix (setter)
+//Sets the chan_mat
+static int PoseBone_setLocalMatrix(BPy_PoseBone *self, PyObject *value, void *closure)
+{
+ MatrixObject *matrix = NULL;
+ float size[3], quat[4], loc[3];
+ float mat3[3][3], mat4[4][4];
+ int matsize = 0;
+
+ if (!PyArg_Parse(value, "O!", &matrix_Type, &matrix))
+ goto AttributeError;
+
+ if (matrix->rowSize == 3 && matrix->colSize == 3){
+ matsize = 3;
+ Mat3CpyMat3(mat3, (float(*)[3])*matrix->matrix);
+ }else if (matrix->rowSize == 4 && matrix->colSize == 4){
+ matsize = 4;
+ Mat4CpyMat4(mat4, (float(*)[4])*matrix->matrix);
+ }
+
+ if (matsize != 3 && matsize != 4){
+ goto AttributeError;
+ }
+
+ //get size and rotation
+ if (matsize == 3){
+ Mat3ToSize(mat3, size);
+ Mat3Ortho(mat3);
+ Mat3ToQuat(mat3, quat);
+ }else if (matsize == 4){
+ Mat4ToSize(mat4, size);
+ Mat4Ortho(mat4);
+ Mat4ToQuat(mat4, quat);
+ }
+
+ //get loc
+ if (matsize == 4){
+ VECCOPY(loc, matrix->matrix[3]);
+ }
+
+ //copy new attributes
+ VECCOPY(self->posechannel->size, size);
+ QUATCOPY(self->posechannel->quat, quat);
+ if (matsize == 4){
+ VECCOPY(self->posechannel->loc, loc);
+ }
+
+ //rebuild matrix
+ chan_calc_mat(self->posechannel);
+ return 0;
+
+AttributeError:
+ return EXPP_intError(PyExc_AttributeError, "%s%s%s",
+ sPoseBoneError, ".localMatrix: ", "expects a 3x3 or 4x4 matrix object");
+}
+//------------------------PoseBone.poseMatrix (getter)
+//Gets the pose_mat
+static PyObject *PoseBone_getPoseMatrix(BPy_PoseBone *self, void *closure)
+{
+ return newMatrixObject((float*)self->posechannel->pose_mat, 4, 4, Py_WRAP);
+}
+//------------------------PoseBone.poseMatrix (setter)
+//Sets the pose_mat
+static int PoseBone_setPoseMatrix(BPy_PoseBone *self, PyObject *value, void *closure)
+{
+ return EXPP_intError(PyExc_AttributeError, "%s%s%s",
+ sPoseBoneError, ".poseMatrix: ", "not able to set this property");
+}
+////------------------------PoseBone.constraints (getter)
+////Gets the constraints list
+//static PyObject *PoseBone_getConstraints(BPy_PoseBone *self, void *closure)
+//{
+// PyObject *list = NULL, *py_constraint = NULL;
+// bConstraint *constraint = NULL;
+//
+// list = PyList_New(0);
+// for (constraint = self->posechannel->constraints.first; constraint; constraint = constraint->next){
+// py_constraint = PyConstraint_FromConstraint(constraint);
+// if (!py_constraint)
+// return NULL;
+// if (PyList_Append(list, py_constraint) == -1){
+// Py_DECREF(py_constraint);
+// goto RuntimeError;
+// }
+// Py_DECREF(py_constraint);
+// }
+// return list;
+//
+//RuntimeError:
+// return EXPP_objError(PyExc_RuntimeError, "%s%s%s",
+// sPoseBoneError, ".constraints: ", "unable to build constraint list");
+//}
+////------------------------PoseBone.constraints (setter)
+////Sets the constraints list
+//static int PoseBone_setConstraints(BPy_PoseBone *self, PyObject *value, void *closure)
+//{
+// printf("This is not implemented yet...");
+// return 1;
+//}
+//------------------------PoseBone.head (getter)
+//Gets the pose head position
+static PyObject *PoseBone_getHead(BPy_PoseBone *self, void *closure)
+{
+ return newVectorObject(self->posechannel->pose_head, 3, Py_NEW);
+}
+//------------------------PoseBone.head (setter)
+//Sets the pose head position
+static int PoseBone_setHead(BPy_PoseBone *self, PyObject *value, void *closure)
+{
+ return EXPP_intError(PyExc_AttributeError, "%s%s%s",
+ sPoseBoneError, ".head: ", "not able to set this property");
+}
+//------------------------PoseBone.tail (getter)
+//Gets the pose tail position
+static PyObject *PoseBone_getTail(BPy_PoseBone *self, void *closure)
+{
+ return newVectorObject(self->posechannel->pose_tail, 3, Py_NEW);
+}
+//------------------------PoseBone.tail (setter)
+//Sets the pose tail position
+static int PoseBone_setTail(BPy_PoseBone *self, PyObject *value, void *closure)
+{
+ return EXPP_intError(PyExc_AttributeError, "%s%s%s",
+ sPoseBoneError, ".tail: ", "not able to set this property");
+}
+//------------------TYPE_OBECT IMPLEMENTATION---------------------------
+//------------------------tp_getset
+//This contains methods for attributes that require checking
+static PyGetSetDef BPy_PoseBone_getset[] = {
+ {"name", (getter)PoseBone_getName, (setter)PoseBone_setName,
+ "The pose bone's name", NULL},
+ {"loc", (getter)PoseBone_getLoc, (setter)PoseBone_setLoc,
+ "The pose bone's change in location as a vector", NULL},
+ {"size", (getter)PoseBone_getSize, (setter)PoseBone_setSize,
+ "The pose bone's change in size as a vector", NULL},
+ {"quat", (getter)PoseBone_getQuat, (setter)PoseBone_setQuat,
+ "The pose bone's change in rotation as a quat", NULL},
+ {"localMatrix", (getter)PoseBone_getLocalMatrix, (setter)PoseBone_setLocalMatrix,
+ "The pose bone's change matrix built from the quat, loc, and size", NULL},
+ {"poseMatrix", (getter)PoseBone_getPoseMatrix, (setter)PoseBone_setPoseMatrix,
+ "The pose bone's matrix", NULL},
+ {"head", (getter)PoseBone_getHead, (setter)PoseBone_setHead,
+ "The pose bone's head positon", NULL},
+ {"tail", (getter)PoseBone_getTail, (setter)PoseBone_setTail,
+ "The pose bone's tail positon", NULL},
+ //{"constraints", (getter)PoseBone_getConstraints, (setter)PoseBone_setConstraints,
+ // "The list of contraints that pertain to this pose bone", NULL},
+ {NULL, NULL, NULL, NULL, NULL}
+};
+//------------------------tp_dealloc
+//This tells how to 'tear-down' our object when ref count hits 0
+static void PoseBone_dealloc(BPy_PoseBone *self)
+{
+ PoseBone_Type.tp_free(self);
+ return;
+}
+//------------------------tp_repr
+//This is the string representation of the object
+static PyObject *PoseBone_repr(BPy_PoseBone *self)
+{
+ return PyString_FromFormat( "[PoseBone \"%s\"]", self->posechannel->name);
+}
+//------------------------tp_doc
+//The __doc__ string for this object
+static char BPy_PoseBone_doc[] = "This object wraps a Blender PoseBone object.";
+
+//------------------TYPE_OBECT DEFINITION--------------------------
+PyTypeObject PoseBone_Type = {
+ PyObject_HEAD_INIT(NULL) //tp_head
+ 0, //tp_internal
+ "PoseBone", //tp_name
+ sizeof(BPy_PoseBone), //tp_basicsize
+ 0, //tp_itemsize
+ (destructor)PoseBone_dealloc, //tp_dealloc
+ 0, //tp_print
+ 0, //tp_getattr
+ 0, //tp_setattr
+ 0, //tp_compare
+ (reprfunc)PoseBone_repr, //tp_repr
+ 0, //tp_as_number
+ 0, //tp_as_sequence
+ 0, //tp_as_mapping
+ 0, //tp_hash
+ 0, //tp_call
+ 0, //tp_str
+ 0, //tp_getattro
+ 0, //tp_setattro
+ 0, //tp_as_buffer
+ Py_TPFLAGS_DEFAULT, //tp_flags
+ BPy_PoseBone_doc, //tp_doc
+ 0, //tp_traverse
+ 0, //tp_clear
+ 0, //tp_richcompare
+ 0, //tp_weaklistoffset
+ 0, //tp_iter
+ 0, //tp_iternext
+ BPy_PoseBone_methods, //tp_methods
+ 0, //tp_members
+ BPy_PoseBone_getset, //tp_getset
+ 0, //tp_base
+ 0, //tp_dict
+ 0, //tp_descr_get
+ 0, //tp_descr_set
+ 0, //tp_dictoffset
+ 0, //tp_init
+ 0, //tp_alloc
+ 0, //tp_new
+ 0, //tp_free
+ 0, //tp_is_gc
+ 0, //tp_bases
+ 0, //tp_mro
+ 0, //tp_cache
+ 0, //tp_subclasses
+ 0, //tp_weaklist
+ 0 //tp_del
+};
+//-------------------MODULE METHODS IMPLEMENTATION------------------------
+//-------------------MODULE METHODS DEFINITION-----------------------------
+struct PyMethodDef M_Pose_methods[] = {
+ {NULL, NULL, 0, NULL}
+};
+//-------------------MODULE INITIALIZATION--------------------------------
+PyObject *Pose_Init(void)
+{
+ PyObject *module;
+
+ //Initializes TypeObject.ob_type
+ if (PyType_Ready(&Pose_Type) < 0 || PyType_Ready(&PoseBone_Type) < 0 ||
+ PyType_Ready(&PoseBonesDict_Type) < 0) {
+ return EXPP_incr_ret(Py_None);
+ }
+
+ //Register the module
+ module = Py_InitModule3("Blender.Object.Pose", M_Pose_methods,
+ "The Blender Pose module");
+
+ //Add TYPEOBJECTS to the module
+ PyModule_AddObject(module, "Pose",
+ EXPP_incr_ret((PyObject *)&Pose_Type)); //*steals*
+ PyModule_AddObject(module, "PoseBone",
+ EXPP_incr_ret((PyObject *)&PoseBone_Type)); //*steals*
+
+ //Add CONSTANTS to the module
+ PyModule_AddObject(module, "ROT",
+ EXPP_incr_ret(PyConstant_NewInt("ROT", POSE_ROT)));
+ PyModule_AddObject(module, "LOC",
+ EXPP_incr_ret(PyConstant_NewInt("LOC", POSE_LOC)));
+ PyModule_AddObject(module, "SIZE",
+ EXPP_incr_ret(PyConstant_NewInt("SIZE", POSE_SIZE)));
+
+ return module;
+}
+//------------------VISIBLE PROTOTYPE IMPLEMENTATION-----------------------
+//------------------------------PyPose_FromPose (internal)
+//Returns a PyPose from a bPose - return PyNone if bPose is NULL
+PyObject *PyPose_FromPose(bPose *pose, char *name)
+{
+ BPy_Pose *py_pose = NULL;
+
+ if (pose){
+ py_pose = (BPy_Pose*)Pose_Type.tp_alloc(&Pose_Type, 0);
+ if (!py_pose)
+ goto RuntimeError;
+
+ py_pose->pose = pose;
+ BLI_strncpy(py_pose->name, name, 24);
+
+ //create armature.bones
+ py_pose->Bones = (BPy_PoseBonesDict*)PyPoseBonesDict_FromPyPose(py_pose);
+ if (!py_pose->Bones)
+ goto RuntimeError;
+
+ return (PyObject*)py_pose;
+ }else{
+ return EXPP_incr_ret(Py_None);
+ }
+
+RuntimeError:
+ return EXPP_objError(PyExc_RuntimeError, "%s%s%s",
+ sPoseError, "PyPose_FromPose: ", "Internal Error Ocurred");
+}
+//------------------------------PyPoseBone_FromPosechannel (internal)
+//Returns a PyPoseBone from a bPoseChannel - return PyNone if bPoseChannel is NULL
+PyObject *PyPoseBone_FromPosechannel(bPoseChannel *pchan)
+{
+ BPy_PoseBone *py_posechannel = NULL;
+
+ if (pchan){
+ py_posechannel = (BPy_PoseBone*)PoseBone_Type.tp_alloc(&PoseBone_Type, 0);
+ if (!py_posechannel)
+ goto RuntimeError;
+ py_posechannel->posechannel = pchan;
+ return (PyObject*)py_posechannel;
+ }else{
+ return EXPP_incr_ret(Py_None);
+ }
+
+RuntimeError:
+ return EXPP_objError(PyExc_RuntimeError, "%s%s%s",
+ sPoseBoneError, "PyPoseBone_FromPosechannel: ", "Internal Error Ocurred");
}
diff --git a/source/blender/python/api2_2x/Pose.h b/source/blender/python/api2_2x/Pose.h
index c1735d1ebd4..dc90c8820f0 100644
--- a/source/blender/python/api2_2x/Pose.h
+++ b/source/blender/python/api2_2x/Pose.h
@@ -1,24 +1,68 @@
+/*
+ * $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.
+ *
+ * Contributor(s): Joseph Gilbert
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+*/
+
#ifndef EXPP_POSE_H
#define EXPP_POSE_H
#include <Python.h>
+#include "DNA_action_types.h"
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <DNA_action_types.h>
-
-/* EXPP PyType Objects */
+//-------------------TYPE CHECKS---------------------------------
+#define PoseObject_Check(v) ((v)->ob_type == &Pose_Type)
+#define PoseBoneObject_Check(v) ((v)->ob_type == &PoseBone_Type)
+#define PoseBonesDictObject_Check(v) ((v)->ob_type == &PoseBonesDict_Type)
+//-------------------TYPEOBJECT----------------------------------
extern PyTypeObject Pose_Type;
-
-struct BPy_Pose;
+extern PyTypeObject PoseBone_Type;
+extern PyTypeObject PoseBonesDict_Type;
+//-------------------STRUCT DEFINITION----------------------------
+typedef struct {
+ PyObject_HEAD
+ PyObject *bonesMap;
+ ListBase *bones;
+} BPy_PoseBonesDict;
typedef struct {
- PyObject_HEAD /* required python macro */
- bPose * pose;
-} BPy_Pose; /* a pose */
+ PyObject_HEAD
+ bPose *pose;
+ char name[24]; //because poses have not names :(
+ BPy_PoseBonesDict *Bones;
+} BPy_Pose;
-PyObject *Pose_CreatePyObject( bPose * p );
+typedef struct {
+ PyObject_HEAD
+ bPoseChannel *posechannel;
+} BPy_PoseBone;
-#endif /* EXPP_KEY_H */
+//-------------------VISIBLE PROTOTYPES-------------------------
+PyObject *Pose_Init(void);
+PyObject *PyPose_FromPose(bPose *pose, char *name);
+PyObject *PyPoseBone_FromPosechannel(bPoseChannel *pchan);
+#endif
diff --git a/source/blender/python/api2_2x/Window.c b/source/blender/python/api2_2x/Window.c
index 8b89296dcde..a7ad2581f45 100644
--- a/source/blender/python/api2_2x/Window.c
+++ b/source/blender/python/api2_2x/Window.c
@@ -889,20 +889,23 @@ static PyObject *M_Window_EditMode( PyObject * self, PyObject * args )
short status = -1;
char *undo_str = "From script";
int undo_str_len = 11;
+ int do_undo = 1;
- if( !PyArg_ParseTuple
- ( args, "|hs#", &status, &undo_str, &undo_str_len ) )
+ if( !PyArg_ParseTuple( args,
+ "|hs#i", &status, &undo_str, &undo_str_len, &do_undo ) )
return EXPP_ReturnPyObjError( PyExc_TypeError,
- "expected nothing or an int (bool) and a string as arguments" );
+ "expected optional int (bool), string and int (bool) as arguments" );
if( status >= 0 ) {
if( status ) {
if( !G.obedit )
enter_editmode( );
} else if( G.obedit ) {
- if( undo_str_len > 63 )
- undo_str[63] = '\0'; /* 64 is max */
- undo_push_mesh( undo_str ); /* use better solution after 2.34 */
+ if( do_undo && U.undosteps != 0 ) {
+ if( undo_str_len > 63 )
+ undo_str[63] = '\0'; /* 64 is max */
+ undo_push_mesh( undo_str ); /* use better solution after 2.34 */
+ }
exit_editmode( 1 );
}
}
diff --git a/source/blender/python/api2_2x/constant.c b/source/blender/python/api2_2x/constant.c
index 1ebf50ffa55..f28af8efad6 100644
--- a/source/blender/python/api2_2x/constant.c
+++ b/source/blender/python/api2_2x/constant.c
@@ -90,7 +90,7 @@ static PyMethodDef BPy_constant_methods[] = {
"() - Returns the keys the dictionary"},
{"values", (PyCFunction) constant_values, METH_NOARGS,
"() - Returns the values from the dictionary"},
- {NULL}
+ {NULL, NULL, 0, NULL}
};
//------------------------mp_length
static int constantLength(BPy_constant *self)
diff --git a/source/blender/python/api2_2x/doc/API_intro.py b/source/blender/python/api2_2x/doc/API_intro.py
index 9a7c16d5168..a23999f4a0e 100644
--- a/source/blender/python/api2_2x/doc/API_intro.py
+++ b/source/blender/python/api2_2x/doc/API_intro.py
@@ -33,6 +33,7 @@ The Blender Python API Reference
- L{NMesh} (*)
- L{Noise}
- L{Object} (*)
+ - L{Pose}
- L{Registry}
- L{Scene}
- L{Radio}
diff --git a/source/blender/python/api2_2x/doc/Armature.py b/source/blender/python/api2_2x/doc/Armature.py
index 79f9481192d..a8ce2e3c1eb 100644
--- a/source/blender/python/api2_2x/doc/Armature.py
+++ b/source/blender/python/api2_2x/doc/Armature.py
@@ -212,7 +212,7 @@ class Bone:
@type matrix: Matrix Object
@ivar parent: The parent Bone.
@type parent: Bone Object
- @ivar children: The children bones.
+ @ivar children: The children directly attached to this bone.
@type children: List of Bone Objects
@ivar weight: The bone's weight.
@type weight: Float
@@ -246,6 +246,13 @@ class Bone:
@rtype: Bool
"""
+ def getAllChildren():
+ """
+ Gets all the children under this bone including the children's children.
+ @rtype: List of Bone object
+ @return: all bones under this one
+ """
+
class Editbone:
"""
The Editbone Object
@@ -260,7 +267,7 @@ class Editbone:
@type head: Vector Object
@ivar tail: This Bone's "tail" ending position when in rest state (armaturespace).
@type tail: Vector Object
- @ivar matrix: This Bone's matrix. (armaturespace) This cannot be set.
+ @ivar matrix: This Bone's matrix. (armaturespace)
@type matrix: Matrix Object
@ivar parent: The parent Bone.
@type parent: Editbone Object
diff --git a/source/blender/python/api2_2x/doc/Ipo.py b/source/blender/python/api2_2x/doc/Ipo.py
index 8621bd18ca0..01abef7e430 100644
--- a/source/blender/python/api2_2x/doc/Ipo.py
+++ b/source/blender/python/api2_2x/doc/Ipo.py
@@ -297,6 +297,16 @@ class IpoCurve:
Can be Constant, Extrapolation, Cyclic or Cyclic_extrapolation.
@rtype: None
@return: None
+ @note: Cyclic Ipo curves never reach the end value. If the first and
+ last bezier points do not have the same y coordinate, the value of the
+ curve when it "cycles" is that of the first point. If a user wants to
+ get the value of the final curve point, read the final point from the
+ curve's L{bezierPoints} attribute::
+
+ ipo = Blender.Object.Get('Cube').ipo
+ icu = ipo.getCurves('LocX')
+ endtime,endvalue = icu.bezierPoints[-1].pt
+
"""
def getExtrapolation():
diff --git a/source/blender/python/api2_2x/doc/Key.py b/source/blender/python/api2_2x/doc/Key.py
index 6d3c8316a0e..795346491a1 100644
--- a/source/blender/python/api2_2x/doc/Key.py
+++ b/source/blender/python/api2_2x/doc/Key.py
@@ -6,7 +6,7 @@ The Blender.Key submodule.
This module provides access to B{Key} objects in Blender.
@type Types: readonly dictionary
-@var Types: The type of a key, indicating the type of data in the
+@var Types: The type of a key owner, indicating the type of data in the
data blocks.
- MESH - the key is a Mesh key; data blocks contain
L{NMVert<NMesh.NMVert>} vertices.
@@ -15,7 +15,6 @@ data blocks.
3 floating point numbers).
- LATTICE - the key is a Lattice key; data blocks contain
BPoints, each point represented by a list of 3 floating point numbers.
-
"""
def Get(name = None):
@@ -38,7 +37,7 @@ class Key:
keyframe data.
@ivar ipo: Key Ipo. Contains the Ipo if one is assigned to the
- object, B{None} otherwise. Setting to B{None} clears the current Ipo..
+ object, B{None} otherwise. Setting to B{None} clears the current Ipo.
@type ipo: Blender Ipo
@ivar value: The value of the key. Read-only.
@type value: float
@@ -47,6 +46,8 @@ class Key:
@type type: int
@ivar blocks: A list of KeyBlocks for the key. Read-only.
@type blocks: Blender KeyBlock.
+ @ivar relative: Indicates whether the key is relative(=True) or normal.
+ @type relative: bool
"""
def getIpo():
@@ -66,6 +67,8 @@ class KeyBlock:
Each Key object has a list of KeyBlocks attached, each KeyBlock
representing a keyframe.
+ @ivar curval: Current value of the corresponding IpoCurve. Read-only.
+ @type curval: float
@ivar name: The name of the Keyblock. Truncated to 32 characters.
@type name: string
@ivar pos: The position of the keyframe.
diff --git a/source/blender/python/api2_2x/doc/Mathutils.py b/source/blender/python/api2_2x/doc/Mathutils.py
index 2d4e0a0c092..b1a8839110e 100644
--- a/source/blender/python/api2_2x/doc/Mathutils.py
+++ b/source/blender/python/api2_2x/doc/Mathutils.py
@@ -493,6 +493,7 @@ class Vector:
def resize4D():
"""
Resize the vector to 4d. New axis will be 0.0.
+ The last component will be 1.0, to make multiplying 3d vectors by 4x4 matrices easier.
@return: a copy of itself
"""
diff --git a/source/blender/python/api2_2x/doc/Mesh.py b/source/blender/python/api2_2x/doc/Mesh.py
index f60d84ff02a..54fd5d59cf0 100644
--- a/source/blender/python/api2_2x/doc/Mesh.py
+++ b/source/blender/python/api2_2x/doc/Mesh.py
@@ -112,6 +112,11 @@ Example::
already associated with a group, else it does nothing.\n
- REPLACE: attempts to replace a weight with the new weight value
for an already associated vertex/group, else it does nothing.
+@type SelectModes: readonly dictionary.
+@var SelectModes: The available edit select modes.
+ - VERTEX: vertex select mode.
+ - EDGE: edge select mode.
+ - FACE: face select mode.
"""
AssignModes = {'REPLACE':1}
@@ -135,6 +140,19 @@ def New(name='Mesh'):
@return: a new Blender mesh.
"""
+def Mode(mode=0):
+ """
+ Get and/or set the selection modes for mesh editing. These are the modes
+ visible in the 3D window when a mesh is in Edit Mode.
+ @type mode: int
+ @param mode: The name of the mesh data object. See L{SelectModes} for values.
+ Modes can be combined. If omitted, the selection mode is not changed.
+ @rtype: int
+ @return: the current selection mode.
+ @note: The selection mode is an attribute of the current scene. If the
+ scene is changed, the selection mode may not be the same.
+ """
+
class MCol:
"""
The MCol object
@@ -273,9 +291,9 @@ class MVertSeq:
l=[(.1,.1,.1),Vector([2,2,.5])]
me.verts.extend(l) # add multiple vertices
- @type coords: tuple(s) of floats or vectors
+ @type coords: sequences(s) of floats or vectors
@param coords: coords can be
- - a tuple of three floats,
+ - a sequence of three floats,
- a 3D vector, or
- a sequence (list or tuple) of either of the above.
"""
@@ -348,12 +366,12 @@ class MEdgeSeq:
v = me.verts # get vertices
if len(v) >= 6: # if there are enough vertices...
me.edges.extend(v[0],v[1]) # add a single edge
- l=[(v[1],v[2],v[3]),(v[0],v[2],v[4],v[5])]
+ l=[(v[1],v[2],v[3]),[v[0],v[2],v[4],v[5]]]
me.edges.extend(l) # add multiple edges
- @type vertseq: tuple(s) of MVerts
+ @type vertseq: sequence(s) of MVerts
@param vertseq: either two to four MVerts, or sequence (list or tuple)
- of tuples each containing two to four MVerts.
+ of sequences each containing two to four MVerts.
"""
def delete(edges):
@@ -442,7 +460,7 @@ class MFace:
colors; use L{Mesh.faceUV} and L{Mesh.vertexColors} to test. B{Note}:
if a mesh has i{both} UV faces and vertex colors, the colors stored in
the UV faces will be used here.
- @type col: list of MCols
+ @type col: sequence of MCols
@ivar mat: The face's index into the mesh's materials
list. It is in the range [0,15].
@type mat: int
@@ -520,7 +538,7 @@ class MFaceSeq:
def extend(vertseq):
"""
Add one or more faces to the mesh. Faces which already exist in the
- mesh are ignored. Tuples of two vertices are accepted, but no face
+ mesh are ignored. Sequences of two vertices are accepted, but no face
will be created.
Example::
@@ -531,12 +549,12 @@ class MFaceSeq:
v = me.verts # get vertices
if len(v) >= 6: # if there are enough vertices...
me.faces.extend(v[1],v[2],v[3]) # add a single edge
- l=[(v[0],v[1]),(v[0],v[2],v[4],v[5])]
+ l=[(v[0],v[1]),[v[0],v[2],v[4],v[5]]]
me.faces.extend(l) # add another face
- @type vertseq: tuple(s) of MVerts
+ @type vertseq: sequence(s) of MVerts
@param vertseq: either two to four MVerts, or sequence (list or tuple)
- of tuples each containing two to four MVerts.
+ of sequences each containing two to four MVerts.
"""
def delete(deledges, faces):
@@ -608,6 +626,9 @@ class Mesh:
be set. Furthermore, if vertexColors is already set when faceUV is set,
vertexColors is cleared. This is because the vertex color information
is stored with UV faces, so enabling faceUV implies enabling vertexColors.
+ In addition, faceUV cannot be set when the mesh has no faces defined
+ (this is the same behavior as the UI). Attempting to do so will throw
+ a RuntimeError exception.
@type faceUV: bool
@ivar vertexColors: The mesh contains vertex colors. See L{faceUV} for the
use of vertex colors when UV-mapped texture faces are enabled.
@@ -706,11 +727,11 @@ class Mesh:
def findEdges(edges):
"""
- Quickly search for the location of an edge.
- @type edges: tuple(s) of ints or MVerts
+ Quickly search for the location of an edges.
+ @type edges: sequence(s) of ints or MVerts
@param edges: can be tuples of MVerts or integer indexes (B{note:} will
not work with PVerts) or a sequence (list or tuple) containing two or
- more tuples.
+ more sequences.
@rtype: int, None or list
@return: if an edge is found, its index is returned; otherwise None is
returned. If a sequence of edges is passed, a list is returned.
@@ -825,6 +846,16 @@ class Mesh:
associated with the mesh's object
"""
+ def getVertexInfluences(index):
+ """
+ Get the bone influences for a specific vertex.
+ @type index: int
+ @param index: The index of a vertex.
+ @rtype: list of lists
+ @return: List of pairs [name, weight], where name is the bone name (string)
+ and weight is a float value.
+ """
+
def smooth():
"""
Flattens angle of selected faces. Experimental mesh tool.
diff --git a/source/blender/python/api2_2x/doc/Object.py b/source/blender/python/api2_2x/doc/Object.py
index 45d3fb9c90d..f51a31e85f2 100644
--- a/source/blender/python/api2_2x/doc/Object.py
+++ b/source/blender/python/api2_2x/doc/Object.py
@@ -269,6 +269,19 @@ class Object:
the type Effect.
"""
+ def insertShapeKey():
+ """
+ Insert a Shape Key in the current object. It applies to Objects of
+ the type Mesh, Lattice, or Curve.
+ """
+
+ def getPose():
+ """
+ Gets the current Pose of the object.
+ @rtype: Pose object
+ @return: the current pose object
+ """
+
def clearIpo():
"""
Unlinks the ipo from this object.
diff --git a/source/blender/python/api2_2x/doc/Theme.py b/source/blender/python/api2_2x/doc/Theme.py
index cd5ea2c3036..16bdf3f4d84 100644
--- a/source/blender/python/api2_2x/doc/Theme.py
+++ b/source/blender/python/api2_2x/doc/Theme.py
@@ -184,6 +184,10 @@ class ThemeSpace:
@ivar face_select: theme rgba var.
@ivar face_dot: theme rgba var.
@ivar normal: theme rgba var.
+ @ivar bone_solid: theme rgba var.
+ @ivar bon_pose: theme rgba var.
+ @ivar strip: theme rgba var.
+ @ivar strip_select: theme rgba var.
@ivar syntaxl: theme rgba var.
@ivar syntaxn: theme rgba var.
@ivar syntaxb: theme rgba var.
diff --git a/source/blender/python/api2_2x/doc/Window.py b/source/blender/python/api2_2x/doc/Window.py
index 64775654054..061ae696f6a 100644
--- a/source/blender/python/api2_2x/doc/Window.py
+++ b/source/blender/python/api2_2x/doc/Window.py
@@ -232,7 +232,7 @@ def GetPerspMatrix ():
@return: the current matrix.
"""
-def EditMode(enable = -1, undo_msg = 'From script'):
+def EditMode(enable = -1, undo_msg = 'From script', undo = 1):
"""
Get and optionally set the current edit mode status: in or out.
@@ -258,6 +258,9 @@ def EditMode(enable = -1, undo_msg = 'From script'):
string is used as the undo message in the Mesh->Undo History submenu in
the 3d view header. Max length is 63, strings longer than that get
clamped.
+ @param undo: don't save Undo information (only needed when exiting edit
+ mode).
+ @type undo: int
@rtype: int (bool)
@return: 0 if Blender is not in edit mode right now, 1 otherwise.
@warn: this is an important function. NMesh operates on normal Blender
diff --git a/source/blender/python/api2_2x/matrix.c b/source/blender/python/api2_2x/matrix.c
index c66482eab1c..fcf0616b874 100644
--- a/source/blender/python/api2_2x/matrix.c
+++ b/source/blender/python/api2_2x/matrix.c
@@ -458,7 +458,7 @@ static int Matrix_ass_item(MatrixObject * self, int i, PyObject * ob)
float vec[4];
PyObject *m, *f;
- if(i > self->rowSize || i < 0){
+ if(i >= self->rowSize || i < 0){
return EXPP_ReturnIntError(PyExc_TypeError,
"matrix[attribute] = x: bad row\n");
}
diff --git a/source/blender/python/api2_2x/vector.c b/source/blender/python/api2_2x/vector.c
index bb862fe42f7..d9b656be61f 100644
--- a/source/blender/python/api2_2x/vector.c
+++ b/source/blender/python/api2_2x/vector.c
@@ -160,9 +160,9 @@ PyObject *Vector_Resize4D(VectorObject * self)
self->vec = self->data.py_data; //force
if(self->size == 2){
self->data.py_data[2] = 0.0f;
- self->data.py_data[3] = 0.0f;
+ self->data.py_data[3] = 1.0f;
}else if(self->size == 3){
- self->data.py_data[3] = 0.0f;
+ self->data.py_data[3] = 1.0f;
}
self->size = 4;
return EXPP_incr_ret((PyObject*)self);
diff --git a/source/blender/python/api2_2x/windowTheme.c b/source/blender/python/api2_2x/windowTheme.c
index d07323d0ccd..4043c9e0faf 100644
--- a/source/blender/python/api2_2x/windowTheme.c
+++ b/source/blender/python/api2_2x/windowTheme.c
@@ -170,6 +170,10 @@ static PyObject *ThemeSpace_getAttr( BPy_ThemeSpace * self, char *name )
ELSEIF_TSP_RGBA( face_select )
ELSEIF_TSP_RGBA( face_dot )
ELSEIF_TSP_RGBA( normal )
+ ELSEIF_TSP_RGBA( bone_solid )
+ ELSEIF_TSP_RGBA( bone_pose )
+ ELSEIF_TSP_RGBA( strip )
+ ELSEIF_TSP_RGBA( strip_select )
ELSEIF_TSP_RGBA( syntaxl )
ELSEIF_TSP_RGBA( syntaxn )
ELSEIF_TSP_RGBA( syntaxb )
@@ -180,14 +184,15 @@ static PyObject *ThemeSpace_getAttr( BPy_ThemeSpace * self, char *name )
else if( !strcmp( name, "facedot_size" ) )
attrib = Py_BuildValue( "i", tsp->facedot_size );
else if( !strcmp( name, "__members__" ) )
- attrib = Py_BuildValue( "[sssssssssssssssssssssssssssssss]", "theme",
+ attrib = Py_BuildValue("[sssssssssssssssssssssssssssssssssss]", "theme",
"back", "text", "text_hi", "header",
"panel", "shade1", "shade2", "hilite",
"grid", "wire", "lamp", "select", "active",
"transform", "vertex", "vertex_select",
"edge", "edge_select", "edge_seam",
"edge_facesel", "face", "face_select",
- "face_dot", "normal",
+ "face_dot", "normal", "bone_solid", "bone_pose",
+ "strip", "strip_select",
"syntaxl", "syntaxn", "syntaxb", "syntaxv", "syntaxc",
"vertex_size", "facedot_size" );
@@ -230,6 +235,10 @@ static int ThemeSpace_setAttr( BPy_ThemeSpace * self, char *name,
ELSEIF_TSP_RGBA( face_select )
ELSEIF_TSP_RGBA( face_dot )
ELSEIF_TSP_RGBA( normal )
+ ELSEIF_TSP_RGBA( bone_solid )
+ ELSEIF_TSP_RGBA( bone_pose )
+ ELSEIF_TSP_RGBA( strip )
+ ELSEIF_TSP_RGBA( strip_select )
ELSEIF_TSP_RGBA( syntaxl )
ELSEIF_TSP_RGBA( syntaxn )
ELSEIF_TSP_RGBA( syntaxb )