forked from bartvdbraak/blender
- added support for adding/parenting bones to armatures
- fixed getArmatureIpo compiling error
This commit is contained in:
parent
3b680da036
commit
32b0677d96
@ -40,10 +40,12 @@
|
||||
#include <BKE_armature.h>
|
||||
#include <BKE_library.h>
|
||||
#include <BLI_blenlib.h>
|
||||
#include <BLI_arithb.h>
|
||||
|
||||
#include "constant.h"
|
||||
#include "gen_utils.h"
|
||||
#include "modules.h"
|
||||
#include "Types.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Python API function prototypes for the Armature module. */
|
||||
@ -90,6 +92,7 @@ struct PyMethodDef M_Armature_methods[] = {
|
||||
/*****************************************************************************/
|
||||
static PyObject *Armature_getName (BPy_Armature * self);
|
||||
static PyObject *Armature_getBones (BPy_Armature * self);
|
||||
static PyObject *Armature_addBone(BPy_Armature *self, PyObject *args);
|
||||
static PyObject *Armature_setName (BPy_Armature * self, PyObject * args);
|
||||
/* static PyObject *Armature_setBones(BPy_Armature *self, PyObject *args); */
|
||||
|
||||
@ -104,6 +107,8 @@ static PyMethodDef BPy_Armature_methods[] = {
|
||||
"() - return Armature root bones"},
|
||||
{"setName", (PyCFunction) Armature_setName, METH_VARARGS,
|
||||
"(str) - rename Armature"},
|
||||
{"addBone", (PyCFunction)Armature_addBone, METH_VARARGS,
|
||||
"(bone)-add bone"},
|
||||
/* {"setBones", (PyCFunction)Armature_setBones, METH_VARARGS,
|
||||
"(list of bones) - replace the whole bone list of the armature"},
|
||||
*/
|
||||
@ -120,6 +125,7 @@ static int Armature_setAttr (BPy_Armature * armature, char *name,
|
||||
static int Armature_compare (BPy_Armature * a1, BPy_Armature * a2);
|
||||
static PyObject *Armature_repr (BPy_Armature * armature);
|
||||
|
||||
static int doesBoneName_exist(char *name, bArmature* arm);
|
||||
/*****************************************************************************/
|
||||
/* Python TypeArmature structure definition: */
|
||||
/*****************************************************************************/
|
||||
@ -154,47 +160,42 @@ PyTypeObject Armature_Type = {
|
||||
static PyObject *
|
||||
M_Armature_New (PyObject * self, PyObject * args, PyObject * keywords)
|
||||
{
|
||||
char *type_str = "Armature";
|
||||
char *name_str = "ArmatureData";
|
||||
static char *kwlist[] = { "type_str", "name_str", NULL };
|
||||
BPy_Armature *py_armature; /* for Armature Data object wrapper in Python */
|
||||
bArmature *bl_armature; /* for actual Armature Data we create in Blender */
|
||||
char buf[21];
|
||||
char *name_str = "ArmatureData";
|
||||
BPy_Armature *py_armature; /* for Armature Data object wrapper in Python */
|
||||
bArmature *bl_armature; /* for actual Armature Data we create in Blender */
|
||||
char buf[21];
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords (args, keywords, "|ss", kwlist,
|
||||
&type_str, &name_str))
|
||||
if (!PyArg_ParseTuple(args, "|s", &name_str))
|
||||
return (EXPP_ReturnPyObjError (PyExc_AttributeError,
|
||||
"expected string(s) or empty argument"));
|
||||
"expected string or empty argument"));
|
||||
|
||||
bl_armature = add_armature (); /* first create in Blender */
|
||||
if (bl_armature)
|
||||
{
|
||||
/* return user count to zero because add_armature() inc'd it */
|
||||
bl_armature->id.us = 0;
|
||||
/* now create the wrapper obj in Python */
|
||||
py_armature =
|
||||
(BPy_Armature *) PyObject_NEW (BPy_Armature, &Armature_Type);
|
||||
}
|
||||
bl_armature = add_armature(); /* first create in Blender */
|
||||
|
||||
if (bl_armature){
|
||||
/* return user count to zero because add_armature() inc'd it */
|
||||
bl_armature->id.us = 0;
|
||||
/* now create the wrapper obj in Python */
|
||||
py_armature = (BPy_Armature *)PyObject_NEW(BPy_Armature, &Armature_Type);
|
||||
}
|
||||
else
|
||||
return (EXPP_ReturnPyObjError (PyExc_RuntimeError,
|
||||
"couldn't create Armature Data in Blender"));
|
||||
"couldn't create Armature Data in Blender"));
|
||||
|
||||
if (py_armature == NULL)
|
||||
return (EXPP_ReturnPyObjError (PyExc_MemoryError,
|
||||
"couldn't create Armature Data object"));
|
||||
"couldn't create ArmaturePyObject"));
|
||||
|
||||
/* link Python armature wrapper with Blender Armature: */
|
||||
py_armature->armature = bl_armature;
|
||||
|
||||
if (strcmp (name_str, "ArmatureData") == 0)
|
||||
return (PyObject *) py_armature;
|
||||
else
|
||||
{ /* user gave us a name for the armature, use it */
|
||||
PyOS_snprintf (buf, sizeof (buf), "%s", name_str);
|
||||
rename_id (&bl_armature->id, buf);
|
||||
}
|
||||
if (strcmp(name_str, "ArmatureData") == 0)
|
||||
return (PyObject *)py_armature;
|
||||
else { /* user gave us a name for the armature, use it */
|
||||
PyOS_snprintf(buf, sizeof(buf), "%s", name_str);
|
||||
rename_id(&bl_armature->id, buf);
|
||||
}
|
||||
|
||||
return (PyObject *) py_armature;
|
||||
return (PyObject *)py_armature;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -340,6 +341,107 @@ Armature_getBones (BPy_Armature * self)
|
||||
return listbones;
|
||||
}
|
||||
|
||||
static void
|
||||
unique_BoneName(char *name, bArmature* arm)
|
||||
{
|
||||
char tempname[64];
|
||||
int number;
|
||||
char *dot;
|
||||
|
||||
if (doesBoneName_exist(name, arm)){
|
||||
/* Strip off the suffix */
|
||||
dot=strchr(name, '.');
|
||||
if (dot)
|
||||
*dot=0;
|
||||
|
||||
for (number = 1; number <=999; number++){
|
||||
sprintf (tempname, "%s.%03d", name, number);
|
||||
if (!doesBoneName_exist(tempname, arm)){
|
||||
strcpy (name, tempname);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
doesBoneName_exist(char *name, bArmature* arm)
|
||||
{
|
||||
Bone *parent = NULL;
|
||||
Bone *child = NULL;
|
||||
|
||||
for (parent = arm->bonebase.first; parent; parent = parent->next){
|
||||
if (!strcmp (name, parent->name))
|
||||
return 1;
|
||||
for (child = parent->childbase.first; child; child = child->next){
|
||||
if (!strcmp (name, child->name))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *Armature_addBone(BPy_Armature *self, PyObject *args)
|
||||
{
|
||||
BPy_Bone* py_bone = NULL;
|
||||
float M_boneObjectspace[4][4];
|
||||
float M_parentRest[4][4];
|
||||
float iM_parentRest[4][4];
|
||||
float delta[3];
|
||||
float rootHead[3];
|
||||
float rootTail[3];
|
||||
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O!", &Bone_Type, &py_bone))
|
||||
return (EXPP_ReturnPyObjError (PyExc_TypeError,
|
||||
"expected bone object argument (or nothing)"));
|
||||
|
||||
if(py_bone != NULL)
|
||||
if(!py_bone->bone)
|
||||
return (EXPP_ReturnPyObjError (PyExc_TypeError, "bone contains no data!"));
|
||||
|
||||
//make sure the name is unique for this armature
|
||||
unique_BoneName(py_bone->bone->name, self->armature);
|
||||
|
||||
//if bone has a parent....
|
||||
if(py_bone->bone->parent){
|
||||
|
||||
//add to parent's childbase
|
||||
BLI_addtail (&py_bone->bone->parent->childbase, py_bone->bone);
|
||||
|
||||
//get the worldspace coords for the parent
|
||||
get_objectspace_bone_matrix(py_bone->bone->parent, M_boneObjectspace, 1,0);
|
||||
rootHead[0] = M_boneObjectspace[3][0];
|
||||
rootHead[1] = M_boneObjectspace[3][1];
|
||||
rootHead[2] = M_boneObjectspace[3][2];
|
||||
get_objectspace_bone_matrix(py_bone->bone->parent, M_boneObjectspace, 0,0);
|
||||
rootTail[0] = M_boneObjectspace[3][0];
|
||||
rootTail[1] = M_boneObjectspace[3][1];
|
||||
rootTail[2] = M_boneObjectspace[3][2];
|
||||
|
||||
//rest matrix of parent
|
||||
VecSubf (delta, rootTail, rootHead);
|
||||
make_boneMatrixvr(M_parentRest, delta, py_bone->bone->parent->roll);
|
||||
|
||||
// Invert the parent rest matrix
|
||||
Mat4Invert (iM_parentRest, M_parentRest);
|
||||
|
||||
// Get the new head and tail
|
||||
VecSubf (py_bone->bone->head, py_bone->bone->head, rootTail);
|
||||
VecSubf (py_bone->bone->tail, py_bone->bone->tail, rootTail);
|
||||
|
||||
//transformation of local bone
|
||||
Mat4MulVecfl(iM_parentRest, py_bone->bone->head);
|
||||
Mat4MulVecfl(iM_parentRest, py_bone->bone->tail);
|
||||
|
||||
}else //no parent....
|
||||
BLI_addtail (&self->armature->bonebase,py_bone->bone);
|
||||
|
||||
precalc_bonelist_irestmats(&self->armature->bonebase);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
Armature_setName (BPy_Armature * self, PyObject * args)
|
||||
@ -359,19 +461,6 @@ Armature_setName (BPy_Armature * self, PyObject * args)
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static PyObject *
|
||||
Armature_setBones (BPy_Armature * self, PyObject * args)
|
||||
{
|
||||
/* TODO: Implement me! */
|
||||
printf ("ERROR: Armature_setBones NOT implemented yet!\n");
|
||||
Py_INCREF (Py_None);
|
||||
return Py_None;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Function: Armature_dealloc */
|
||||
/* Description: This is a callback function for the BPy_Armature type. It is */
|
||||
@ -498,6 +587,7 @@ Armature_CreatePyObject (struct bArmature * obj)
|
||||
return (NULL);
|
||||
}
|
||||
blen_armature->armature = obj;
|
||||
|
||||
return ((PyObject *) blen_armature);
|
||||
}
|
||||
|
||||
|
@ -39,10 +39,9 @@
|
||||
/* Python BPy_Armature structure definition: */
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PyObject_HEAD bArmature * armature;
|
||||
}
|
||||
BPy_Armature;
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
bArmature *armature;
|
||||
} BPy_Armature;
|
||||
|
||||
#endif /* EXPP_ARMATURE_H */
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <BKE_object.h>
|
||||
#include <BKE_armature.h>
|
||||
#include <BKE_library.h>
|
||||
#include <MEM_guardedalloc.h>
|
||||
|
||||
#include "constant.h"
|
||||
#include "gen_utils.h"
|
||||
@ -92,8 +93,7 @@ static PyObject *Bone_setTail (BPy_Bone * self, PyObject * args);
|
||||
static PyObject *Bone_setLoc (BPy_Bone * self, PyObject * args);
|
||||
static PyObject *Bone_setSize (BPy_Bone * self, PyObject * args);
|
||||
static PyObject *Bone_setQuat (BPy_Bone * self, PyObject * args);
|
||||
/* static PyObject *Bone_setParent(BPy_Bone *self, PyObject *args); */
|
||||
/* static PyObject *Bone_setChildren(BPy_Bone *self, PyObject *args); */
|
||||
static PyObject *Bone_setParent(BPy_Bone *self, PyObject *args);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Python BPy_Bone methods table: */
|
||||
@ -135,12 +135,8 @@ static PyMethodDef BPy_Bone_methods[] = {
|
||||
"(float,float,float) - set Bone size"},
|
||||
{"setQuat", (PyCFunction) Bone_setQuat, METH_VARARGS,
|
||||
"(float,float,float,float) - set Bone quat"},
|
||||
#if 0
|
||||
{"setParent", (PyCFunction) Bone_setParent, METH_NOARGS,
|
||||
{"setParent", (PyCFunction)Bone_setParent, METH_VARARGS,
|
||||
"() - set the Bone parent of this one."},
|
||||
{"setChildren", (PyCFunction) Bone_setChildren, METH_NOARGS,
|
||||
"() - replace the children list of the bone."},
|
||||
#endif
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
@ -184,6 +180,7 @@ PyTypeObject Bone_Type = {
|
||||
/* Function: M_Bone_New */
|
||||
/* Python equivalent: Blender.Armature.Bone.New */
|
||||
/*****************************************************************************/
|
||||
|
||||
static PyObject *
|
||||
M_Bone_New (PyObject * self, PyObject * args, PyObject * keywords)
|
||||
{
|
||||
@ -196,10 +193,17 @@ M_Bone_New (PyObject * self, PyObject * args, PyObject * keywords)
|
||||
"expected string or empty argument"));
|
||||
|
||||
/* Create the C structure for the newq bone */
|
||||
bl_bone = (Bone *) malloc (sizeof (Bone));
|
||||
bl_bone = (Bone *) MEM_callocN(sizeof (Bone), "bone");
|
||||
strncpy (bl_bone->name, name_str, sizeof (bl_bone->name));
|
||||
|
||||
if (bl_bone) /* now create the wrapper obj in Python */
|
||||
bl_bone->dist=1.0;
|
||||
bl_bone->weight=1.0;
|
||||
bl_bone->flag=32;
|
||||
bl_bone->parent = NULL;
|
||||
bl_bone->roll = 0.0;
|
||||
|
||||
// now create the wrapper obj in Python
|
||||
if (bl_bone)
|
||||
py_bone = (BPy_Bone *) PyObject_NEW (BPy_Bone, &Bone_Type);
|
||||
else
|
||||
return (EXPP_ReturnPyObjError (PyExc_RuntimeError,
|
||||
@ -209,16 +213,9 @@ M_Bone_New (PyObject * self, PyObject * args, PyObject * keywords)
|
||||
return (EXPP_ReturnPyObjError (PyExc_MemoryError,
|
||||
"couldn't create Bone Data object"));
|
||||
|
||||
py_bone->bone = bl_bone; /* link Python bone wrapper with Blender Bone */
|
||||
|
||||
if (strcmp (name_str, "BoneData") == 0)
|
||||
return (PyObject *) py_bone;
|
||||
else
|
||||
{ /* user gave us a name for the bone, use it */
|
||||
/* TODO: check that name is not already in use? */
|
||||
PyOS_snprintf (bl_bone->name, sizeof (bl_bone->name), "%s", name_str);
|
||||
}
|
||||
|
||||
py_bone->bone = bl_bone; // link Python bone wrapper with Blender Bone
|
||||
|
||||
Py_INCREF(py_bone);
|
||||
return (PyObject *) py_bone;
|
||||
}
|
||||
|
||||
@ -379,7 +376,6 @@ Bone_getQuat (BPy_Bone * self)
|
||||
"couldn't get Bone.tail attribute"));
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
Bone_hasParent (BPy_Bone * self)
|
||||
{
|
||||
@ -495,7 +491,6 @@ Bone_setRoll (BPy_Bone * self, PyObject * args)
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
Bone_setHead (BPy_Bone * self, PyObject * args)
|
||||
{
|
||||
@ -636,6 +631,27 @@ Bone_setQuat (BPy_Bone * self, PyObject * args)
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
Bone_setParent(BPy_Bone *self, PyObject *args)
|
||||
{
|
||||
BPy_Bone* py_bone;
|
||||
|
||||
if (!self->bone)
|
||||
(EXPP_ReturnPyObjError (PyExc_RuntimeError, "bone contains no data!"));
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O", &py_bone))
|
||||
return (EXPP_ReturnPyObjError (PyExc_TypeError, "expected bone object argument"));
|
||||
|
||||
if(!py_bone->bone)
|
||||
return (EXPP_ReturnPyObjError (PyExc_TypeError, "bone contains no data!"));
|
||||
|
||||
//set the parent of self
|
||||
self->bone->parent = py_bone->bone;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Function: Bone_dealloc */
|
||||
/* Description: This is a callback function for the BPy_Bone type. It is */
|
||||
@ -644,7 +660,8 @@ Bone_setQuat (BPy_Bone * self, PyObject * args)
|
||||
static void
|
||||
Bone_dealloc (BPy_Bone * self)
|
||||
{
|
||||
PyObject_DEL (self);
|
||||
MEM_freeN(self->bone);
|
||||
PyObject_DEL (self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -649,13 +649,15 @@ static PyObject *Object_getActionIpos (BPy_Object *self)
|
||||
{
|
||||
Object *obj=self->object;
|
||||
PyObject *dict=PyDict_New ();
|
||||
bAction *action = NULL;
|
||||
bActionChannel *bone = NULL;
|
||||
|
||||
if (obj->type==OB_ARMATURE) {
|
||||
|
||||
if (obj->action!=0) {
|
||||
|
||||
bAction *action=obj->action;
|
||||
bActionChannel *bone=(bActionChannel*)(action->chanbase.first);
|
||||
action = obj->action;
|
||||
bone = (bActionChannel*)(action->chanbase.first);
|
||||
|
||||
// Go through the list of bones
|
||||
while (bone!=0) {
|
||||
@ -1030,6 +1032,8 @@ static PyObject *Object_link (BPy_Object *self, PyObject *args)
|
||||
return (PythonReturnErrorObject (PyExc_AttributeError,
|
||||
"expected an object as argument"));
|
||||
}
|
||||
if (Armature_CheckPyObject (py_data))
|
||||
data = (void *)Armature_FromPyObject (py_data);
|
||||
if (Camera_CheckPyObject (py_data))
|
||||
data = (void *)Camera_FromPyObject (py_data);
|
||||
if (Lamp_CheckPyObject (py_data))
|
||||
@ -1054,6 +1058,13 @@ static PyObject *Object_link (BPy_Object *self, PyObject *args)
|
||||
|
||||
switch (obj_id)
|
||||
{
|
||||
case ID_AR:
|
||||
if (self->object->type != OB_ARMATURE)
|
||||
{
|
||||
return (PythonReturnErrorObject (PyExc_AttributeError,
|
||||
"The 'link' object is incompatible with the base object"));
|
||||
}
|
||||
break;
|
||||
case ID_CA:
|
||||
if (self->object->type != OB_CAMERA)
|
||||
{
|
||||
|
@ -56,6 +56,7 @@
|
||||
#include <DNA_scene_types.h>
|
||||
#include <DNA_userdef_types.h>
|
||||
#include <DNA_view3d_types.h>
|
||||
#include <DNA_action_types.h>
|
||||
|
||||
#include "bpy_types.h"
|
||||
#include "gen_utils.h"
|
||||
|
Loading…
Reference in New Issue
Block a user