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:
authorJoshua Leung <aligorith@gmail.com>2007-12-14 03:09:07 +0300
committerJoshua Leung <aligorith@gmail.com>2007-12-14 03:09:07 +0300
commit1aa225e9535a4228ad577697290e313a1bac685b (patch)
treea990229f0cf62708db7d10257cf01736a13bc1f3 /source/blender/src
parent960ace98dbf5d9cc9b77672d9b47474a9bd801fd (diff)
== Fill Bones ==
This commit fixes/implements this feature. It is restricted to using 1-2 joints selected joints only.
Diffstat (limited to 'source/blender/src')
-rw-r--r--source/blender/src/editarmature.c145
1 files changed, 124 insertions, 21 deletions
diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c
index 51acac45b3f..923d7638495 100644
--- a/source/blender/src/editarmature.c
+++ b/source/blender/src/editarmature.c
@@ -1930,24 +1930,69 @@ static void chains_find_tips (ListBase *list)
}
}
+
+static void fill_add_joint (EditBone *ebo, short eb_tail, ListBase *points)
+{
+ EditBonePoint *ebp;
+ float vec[3];
+ short found= 0;
+
+ if (eb_tail) {
+ VECCOPY(vec, ebo->tail);
+ }
+ else {
+ VECCOPY(vec, ebo->head);
+ }
+
+ for (ebp= points->first; ebp; ebp= ebp->next) {
+ if (VecEqual(ebp->vec, vec)) {
+ if (eb_tail) {
+ if ((ebp->head_owner) && (ebp->head_owner->parent == ebo)) {
+ /* so this bone's tail owner is this bone*/
+ ebp->tail_owner= ebo;
+ found= 1;
+ break;
+ }
+ }
+ else {
+ if ((ebp->tail_owner) && (ebp->tail_owner->parent == ebo)) {
+ /* so this bone's head owner is this bone */
+ ebp->head_owner= ebo;
+ found = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ /* allocate a new point if no existing point was related */
+ if (found == 0) {
+ ebp= MEM_callocN(sizeof(EditBonePoint), "EditBonePoint");
+
+ if (eb_tail) {
+ VECCOPY(ebp->vec, ebo->tail);
+ ebp->tail_owner= ebo;
+ }
+ else {
+ VECCOPY(ebp->vec, ebo->head);
+ ebp->head_owner= ebo;
+ }
+
+ BLI_addtail(points, ebp);
+ }
+}
+
/* bone adding between selected joints */
void fill_bones_armature(void)
{
- bArmature *arm= G.obedit->data;
+ EditBone *ebo, *newbone=NULL;
ListBase chains = {NULL, NULL};
LinkData *chain;
ListBase points = {NULL, NULL};
- EditBonePoint *ebp;
int count;
- EditBone *ebo, *newbone=NULL;
-
-
- // temp... warning about this not being coded (will be fixed)
- error("This tool hasn't been coded!");
- return;
/* get chains */
chains_find_tips(&chains);
@@ -1956,18 +2001,16 @@ void fill_bones_armature(void)
/* traverse chains to find selected joints */
for (chain= chains.first; chain; chain= chain->next) {
for (ebo= chain->data; ebo; ebo= ebo->parent) {
- if (ebo->flag & (BONE_SELECTED|BONE_ACTIVE)) {
-
- }
- else if (ebo->flag & BONE_ROOTSEL) {
-
- }
- else if (ebo->flag & BONE_TIPSEL) {
-
- }
+ if (ebo->flag & BONE_ROOTSEL)
+ fill_add_joint(ebo, 0, &points);
+ if (ebo->flag & BONE_TIPSEL)
+ fill_add_joint(ebo, 1, &points);
}
}
+ /* free chains - not needed anymore */
+ BLI_freelistN(&chains);
+
/* the number of joints determines how we fill:
* 1) between joint and cursor (joint=head, cursor=tail)
* 2) between the two joints (order is dependent on active-bone/hierachy)
@@ -1976,6 +2019,7 @@ void fill_bones_armature(void)
count= BLI_countlist(&points);
if (count == 1) {
+ EditBonePoint *ebp;
float curs[3];
/* Get Points - selected joint */
@@ -1991,19 +2035,78 @@ void fill_bones_armature(void)
newbone= add_points_bone(ebp->vec, curs);
}
else if (count == 2) {
+ EditBonePoint *ebp, *ebp2;
+ float head[3], tail[3];
+
+ /* check that the points don't belong to the same bone */
+ ebp= (EditBonePoint *)points.first;
+ ebp2= ebp->next;
+ if ((ebp->head_owner==ebp2->tail_owner) && (ebp->head_owner!=NULL)) {
+ error("Same bone selected...");
+ BLI_freelistN(&points);
+ return;
+ }
+ if ((ebp->tail_owner==ebp2->head_owner) && (ebp->tail_owner!=NULL)) {
+ error("Same bone selected...");
+ BLI_freelistN(&points);
+ return;
+ }
+
+ /* find which one should be the 'head' */
+ if ((ebp->head_owner && ebp2->head_owner) || (ebp->tail_owner && ebp2->tail_owner)) {
+ /* rule: whichever one is closer to 3d-cursor */
+ float curs[3];
+ float vecA[3], vecB[3];
+ float distA, distB;
+
+ /* get cursor location */
+ VECCOPY (curs, give_cursor());
+
+ Mat4Invert(G.obedit->imat, G.obedit->obmat);
+ Mat4MulVecfl(G.obedit->imat, curs);
+
+ /* get distances */
+ VecSubf(vecA, ebp->vec, curs);
+ VecSubf(vecB, ebp2->vec, curs);
+ distA= VecLength(vecA);
+ distB= VecLength(vecB);
+
+ /* compare distances - closer one therefore acts as direction for bone to go */
+ if (distA < distB) {
+ VECCOPY(head, ebp2->vec);
+ VECCOPY(tail, ebp->vec);
+ }
+ else {
+ VECCOPY(head, ebp->vec);
+ VECCOPY(tail, ebp2->vec);
+ }
+ }
+ else if (ebp->head_owner) {
+ VECCOPY(head, ebp->vec);
+ VECCOPY(tail, ebp2->vec);
+ }
+ else if (ebp2->head_owner) {
+ VECCOPY(head, ebp2->vec);
+ VECCOPY(tail, ebp->vec);
+ }
+
+ /* add new bone */
+ newbone= add_points_bone(head, tail);
}
else {
- error("Too many points selected"); // FIXME..
+ // FIXME.. figure out a method for multiple bones
+ error("Too many points selected");
+ return;
}
- /* free chains */
- BLI_freelistN(&chains);
+ /* free points */
+ BLI_freelistN(&points);
/* undo + updates */
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWBUTSEDIT, 0);
- BIF_undo_push("Merge Bones");
+ BIF_undo_push("Fill Bones");
}
/* this function merges between two bones, removes them and those in-between,