- parenting checks for bone additions to armature

- update to addBone parenting transform code
- hide/unhide bones
- draw axes/draw names
- clear parenting and clear children from bones - removes childbase links from bone and set as root or remove parenting and set as root
This commit is contained in:
Joseph Gilbert 2004-04-14 23:42:58 +00:00
parent 837da93f19
commit e2bed35011
2 changed files with 271 additions and 27 deletions

@ -24,7 +24,7 @@
*
* This is a new part of Blender.
*
* Contributor(s): Jordi Rovira i Bonet
* Contributor(s): Jordi Rovira i Bonet, Joseph Gilbert
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
@ -94,7 +94,8 @@ 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); */
static PyObject *Armature_drawAxes (BPy_Armature * self, PyObject * args);
static PyObject *Armature_drawNames (BPy_Armature * self, PyObject * args);
/*****************************************************************************/
/* Python BPy_Armature methods table: */
@ -109,9 +110,10 @@ static PyMethodDef BPy_Armature_methods[] = {
"(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"},
*/
{"drawAxes", (PyCFunction)Armature_drawAxes, METH_VARARGS,
"will draw the axis of each bone in armature"},
{"drawNames", (PyCFunction)Armature_drawNames, METH_VARARGS,
"will draw the names of each bone in armature"},
{NULL, NULL, 0, NULL}
};
@ -389,16 +391,25 @@ doesBoneName_exist(char *name, bArmature* arm)
return 0;
}
static int
testBoneInArmature(bArmature *arm, Bone *test)
{
Bone *root;
for(root = arm->bonebase.first; root; root = root->next){
if(root == test){
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,
@ -414,29 +425,19 @@ static PyObject *Armature_addBone(BPy_Armature *self, PyObject *args)
//if bone has a parent....
if(py_bone->bone->parent){
//then check to see if parent has been added to the armature - bone loop test
if(!testBoneInArmature(self->armature, py_bone->bone->parent))
return (EXPP_ReturnPyObjError (PyExc_TypeError,
"cannot parent to a bone not yet added to armature!"));
//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);
Mat4Invert (iM_parentRest, M_boneObjectspace);
//transformation of local bone
Mat4MulVecfl(iM_parentRest, py_bone->bone->head);
@ -469,6 +470,42 @@ Armature_setName (BPy_Armature * self, PyObject * args)
return Py_None;
}
static PyObject *
Armature_drawAxes (BPy_Armature * self, PyObject * args)
{
int toggle;
if (!PyArg_ParseTuple (args, "i", &toggle))
return (EXPP_ReturnPyObjError (PyExc_AttributeError,
"expected 1 or 0 as integer"));
if(toggle)
self->armature->flag |= ARM_DRAWAXES;
else
self->armature->flag &= ~ARM_DRAWAXES;
Py_INCREF (Py_None);
return Py_None;
}
static PyObject *
Armature_drawNames (BPy_Armature * self, PyObject * args)
{
int toggle;
if (!PyArg_ParseTuple (args, "i", &toggle))
return (EXPP_ReturnPyObjError (PyExc_AttributeError,
"expected 1 or 0 as integer"));
if(toggle)
self->armature->flag |= ARM_DRAWNAMES;
else
self->armature->flag &= ~ARM_DRAWNAMES;
Py_INCREF (Py_None);
return Py_None;
}
/*****************************************************************************/
/* Function: Armature_dealloc */
/* Description: This is a callback function for the BPy_Armature type. It is */

@ -24,7 +24,7 @@
*
* This is a new part of Blender.
*
* Contributor(s): Jordi Rovira i Bonet
* Contributor(s): Jordi Rovira i Bonet, Joseph Gilbert
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
@ -37,6 +37,7 @@
#include <BKE_armature.h>
#include <BKE_library.h>
#include <MEM_guardedalloc.h>
#include <BLI_blenlib.h>
#include "constant.h"
#include "gen_utils.h"
@ -88,6 +89,10 @@ static PyObject *Bone_getParent (BPy_Bone * self);
static PyObject *Bone_hasParent (BPy_Bone * self);
static PyObject *Bone_getWeight (BPy_Bone * self);
static PyObject *Bone_getChildren (BPy_Bone * self);
static PyObject *Bone_clearParent (BPy_Bone * self);
static PyObject *Bone_clearChildren (BPy_Bone * self);
static PyObject *Bone_hide (BPy_Bone * self);
static PyObject *Bone_unhide (BPy_Bone * self);
static PyObject *Bone_setName (BPy_Bone * self, PyObject * args);
static PyObject *Bone_setRoll (BPy_Bone * self, PyObject * args);
static PyObject *Bone_setHead (BPy_Bone * self, PyObject * args);
@ -116,6 +121,10 @@ static PyMethodDef BPy_Bone_methods[] = {
"() - return Bone size"},
{"getQuat", (PyCFunction) Bone_getQuat, METH_NOARGS,
"() - return Bone quat"},
{"hide", (PyCFunction) Bone_hide, METH_NOARGS,
"() - hides the bone"},
{"unhide", (PyCFunction) Bone_unhide, METH_NOARGS,
"() - unhides the bone"},
{"getWeight", (PyCFunction) Bone_getWeight, METH_NOARGS,
"() - return Bone weight"},
{"getParent", (PyCFunction) Bone_getParent, METH_NOARGS,
@ -126,6 +135,10 @@ static PyMethodDef BPy_Bone_methods[] = {
"() - return true if bone has a parent"},
{"getChildren", (PyCFunction) Bone_getChildren, METH_NOARGS,
"() - return Bone children list"},
{"clearParent", (PyCFunction) Bone_clearParent, METH_NOARGS,
"() - clears the bone's parent in the armature and makes it root"},
{"clearChildren", (PyCFunction) Bone_clearChildren, METH_NOARGS,
"() - remove the children associated with this bone"},
{"setName", (PyCFunction) Bone_setName, METH_VARARGS,
"(str) - rename Bone"},
{"setRoll", (PyCFunction) Bone_setRoll, METH_VARARGS,
@ -665,6 +678,22 @@ Bone_setQuat (BPy_Bone * self, PyObject * args)
return Py_None;
}
static int
testChildbase(Bone *bone, Bone *test)
{
Bone *child;
for(child = bone->childbase.first; child; child = child->next){
if(child == test){
return 1;
}
if(child->childbase.first != NULL)
testChildbase(child, test);
}
return 0;
}
static PyObject *
Bone_setParent(BPy_Bone *self, PyObject *args)
{
@ -679,6 +708,13 @@ Bone_setParent(BPy_Bone *self, PyObject *args)
if(!py_bone->bone)
return (EXPP_ReturnPyObjError (PyExc_TypeError, "bone contains no data!"));
if(py_bone->bone == self->bone)
return (EXPP_ReturnPyObjError (PyExc_AttributeError, "Cannot parent to self"));
//test to see if were creating an illegal loop by parenting to child
if(testChildbase(self->bone, py_bone->bone))
return (EXPP_ReturnPyObjError (PyExc_AttributeError, "Cannot parent to child"));
//set the parent of self
self->bone->parent = py_bone->bone;
@ -705,6 +741,177 @@ Bone_setWeight(BPy_Bone *self, PyObject *args)
return Py_None;
}
static PyObject *
Bone_clearParent(BPy_Bone *self)
{
bArmature *arm = NULL;
Bone *bone = NULL;
Bone *parent = NULL;
Bone *child = NULL;
Bone *childPrev = NULL;
int firstChild;
float M_boneObjectspace[4][4];
if (!self->bone)
(EXPP_ReturnPyObjError (PyExc_RuntimeError, "bone contains no data!"));
if(self->bone->parent == NULL)
return EXPP_incr_ret(Py_None);
//get parent and remove link
parent = self->bone->parent;
self->bone->parent = NULL;
//remove the childbase link from the parent bone
firstChild = 1;
for(child = parent->childbase.first; child; child = child->next){
if(child == self->bone && firstChild){
parent->childbase.first = child->next;
child->next = NULL;
break;
}
if(child == self->bone && !firstChild){
childPrev->next = child->next;
child->next = NULL;
break;
}
firstChild = 0;
childPrev = child;
}
//now get rid of the parent transformation
get_objectspace_bone_matrix(parent, M_boneObjectspace, 0,0);
//transformation of local bone
Mat4MulVecfl(M_boneObjectspace, self->bone->head);
Mat4MulVecfl(M_boneObjectspace, self->bone->tail);
//get the root bone
while(parent->parent != NULL){
parent = parent->parent;
}
//add unlinked bone to the bonebase of the armature
for (arm = G.main->armature.first; arm; arm= arm->id.next) {
for(bone = arm->bonebase.first; bone; bone = bone->next){
if(parent == bone){
//we found the correct armature - now add it as root bone
BLI_addtail (&arm->bonebase, self->bone);
break;
}
}
}
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
Bone_clearChildren(BPy_Bone *self)
{
Bone *child = NULL;
bArmature *arm = NULL;
Bone *bone = NULL;
Bone *parent = NULL;
Bone *prev = NULL;
Bone *next = NULL;
float M_boneObjectspace[4][4];
int first;
if (!self->bone)
(EXPP_ReturnPyObjError (PyExc_RuntimeError, "bone contains no data!"));
if(self->bone->childbase.first == NULL)
return EXPP_incr_ret(Py_None);
//get the root bone
parent = bone->parent;
if(parent != NULL){
while(parent->parent != NULL){
parent = parent->parent;
}
}else{
parent = bone;
}
//get the armature
for (arm = G.main->armature.first; arm; arm = arm->id.next) {
for(bone = arm->bonebase.first; bone; bone = bone->next){
if(parent == bone){
//we found the correct armature
goto gotArmature;
}
}
}
gotArmature:
if(arm == NULL)
(EXPP_ReturnPyObjError (PyExc_RuntimeError, "couldn't find armature that contains this bone"));
//now get rid of the parent transformation
get_objectspace_bone_matrix(self->bone, M_boneObjectspace, 0,0);
//set children as root
first = 1;
for(child = self->bone->childbase.first; child; child = next){
//undo transformation of local bone
Mat4MulVecfl(M_boneObjectspace, child->head);
Mat4MulVecfl(M_boneObjectspace, child->tail);
//set next pointers to NULL
if(first){
prev = child;
first = 0;
}else{
prev->next = NULL;
prev = child;
}
next = child->next;
//remove parenting and linking
child->parent = NULL;
BLI_remlink(&self->bone->childbase, child);
//add as root
BLI_addtail (&arm->bonebase, child);
}
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
Bone_hide(BPy_Bone *self)
{
if (!self->bone)
(EXPP_ReturnPyObjError (PyExc_RuntimeError, "bone contains no data!"));
if(!(self->bone->flag & BONE_HIDDEN))
self->bone->flag |= BONE_HIDDEN;
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
Bone_unhide(BPy_Bone *self)
{
if (!self->bone)
(EXPP_ReturnPyObjError (PyExc_RuntimeError, "bone contains no data!"));
if(self->bone->flag & BONE_HIDDEN)
self->bone->flag &= ~BONE_HIDDEN;
Py_INCREF(Py_None);
return Py_None;
}
/*****************************************************************************/
/* Function: Bone_dealloc */