- parenting checks for bone additions to armature
authorJoseph Gilbert <ascotan@gmail.com>
Wed, 14 Apr 2004 23:42:58 +0000 (23:42 +0000)
committerJoseph Gilbert <ascotan@gmail.com>
Wed, 14 Apr 2004 23:42:58 +0000 (23:42 +0000)
- 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

source/blender/python/api2_2x/Armature.c
source/blender/python/api2_2x/Bone.c

index b10fb6574d09115aa3887f33f4b3de8325dc22d0..c8ae99fd67b1f4e26413c638aa32841191356248 100644 (file)
@@ -24,7 +24,7 @@
  *
  * This is a new part of Blender.
  *
  *
  * 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 *****
  */
  *
  * ***** 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_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:                                        */
 
 /*****************************************************************************/
 /* 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"},
    "(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}
 };
 
   {NULL, NULL, 0, NULL}
 };
 
@@ -389,16 +391,25 @@ doesBoneName_exist(char *name, bArmature* arm)
   return 0;
 }
 
   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];
 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 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, 
        
        if (!PyArg_ParseTuple(args, "O!", &Bone_Type, &py_bone))
                return (EXPP_ReturnPyObjError (PyExc_TypeError, 
@@ -413,30 +424,20 @@ static PyObject *Armature_addBone(BPy_Armature *self, PyObject *args)
 
        //if bone has a parent....      
        if(py_bone->bone->parent){
 
        //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
                
                //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);
                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
 
                // 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);
 
                //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;
 }
 
   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 */
 /*****************************************************************************/
 /* Function:    Armature_dealloc                                             */
 /* Description: This is a callback function for the BPy_Armature type. It is */
index 80d4136832b7cfcf78380f57d3e694524f8129c4..4a86e0c5c5b55b91e933213b953befbadd5cf022 100644 (file)
@@ -24,7 +24,7 @@
  *
  * This is a new part of Blender.
  *
  *
  * 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 *****
 */
  *
  * ***** END GPL/BL DUAL LICENSE BLOCK *****
 */
@@ -37,6 +37,7 @@
 #include <BKE_armature.h>
 #include <BKE_library.h>
 #include <MEM_guardedalloc.h>
 #include <BKE_armature.h>
 #include <BKE_library.h>
 #include <MEM_guardedalloc.h>
+#include <BLI_blenlib.h>
 
 #include "constant.h"
 #include "gen_utils.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_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);
 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"},
    "() - 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,
   {"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"},
    "() - 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,
   {"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;
 }
 
   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)
 {
 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)
        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;
 
   //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;
 }
 
   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                                                                                            */
 
 /*****************************************************************************/
 /* Function:   Bone_dealloc                                                                                            */