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/editors/armature')
-rw-r--r--source/blender/editors/armature/BIF_retarget.h1
-rw-r--r--source/blender/editors/armature/armature_add.c344
-rw-r--r--source/blender/editors/armature/armature_edit.c100
-rw-r--r--source/blender/editors/armature/armature_intern.h1
-rw-r--r--source/blender/editors/armature/armature_naming.c4
-rw-r--r--source/blender/editors/armature/armature_ops.c4
-rw-r--r--source/blender/editors/armature/armature_relations.c16
-rw-r--r--source/blender/editors/armature/armature_select.c173
-rw-r--r--source/blender/editors/armature/armature_utils.c22
-rw-r--r--source/blender/editors/armature/editarmature_retarget.c4
-rw-r--r--source/blender/editors/armature/meshlaplacian.c8
-rw-r--r--source/blender/editors/armature/meshlaplacian.h2
-rw-r--r--source/blender/editors/armature/pose_edit.c9
-rw-r--r--source/blender/editors/armature/pose_group.c12
-rw-r--r--source/blender/editors/armature/pose_select.c106
-rw-r--r--source/blender/editors/armature/pose_slide.c152
-rw-r--r--source/blender/editors/armature/pose_transform.c2
17 files changed, 617 insertions, 343 deletions
diff --git a/source/blender/editors/armature/BIF_retarget.h b/source/blender/editors/armature/BIF_retarget.h
index 21e85b6fe89..aa56f847f00 100644
--- a/source/blender/editors/armature/BIF_retarget.h
+++ b/source/blender/editors/armature/BIF_retarget.h
@@ -40,7 +40,6 @@ struct bContext;
struct EditBone;
-struct RigJoint;
struct RigGraph;
struct RigNode;
struct RigArc;
diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c
index 22aaeccc4a8..e3a69a89a57 100644
--- a/source/blender/editors/armature/armature_add.c
+++ b/source/blender/editors/armature/armature_add.c
@@ -43,6 +43,7 @@
#include "BKE_constraint.h"
#include "BKE_context.h"
#include "BKE_idprop.h"
+#include "BKE_deform.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -89,7 +90,7 @@ EditBone *ED_armature_edit_bone_add_primitive(Object *obedit_arm, float length,
bArmature *arm = obedit_arm->data;
EditBone *bone;
- ED_armature_deselect_all(obedit_arm, 0);
+ ED_armature_deselect_all(obedit_arm);
/* Create a bone */
bone = ED_armature_edit_bone_add(arm, "Bone");
@@ -144,7 +145,7 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op))
to_root = 1;
}
- ED_armature_deselect_all(obedit, 0);
+ ED_armature_deselect_all(obedit);
/* we re-use code for mirror editing... */
flipbone = NULL;
@@ -282,12 +283,8 @@ static EditBone *get_named_editbone(ListBase *edbo, const char *name)
* */
void preEditBoneDuplicate(ListBase *editbones)
{
- EditBone *eBone;
-
/* clear temp */
- for (eBone = editbones->first; eBone; eBone = eBone->next) {
- eBone->temp = NULL;
- }
+ ED_armature_ebone_listbase_temp_clear(editbones);
}
/*
@@ -311,7 +308,7 @@ void updateDuplicateSubtargetObjects(EditBone *dupBone, ListBase *editbones, Obj
/* does this constraint have a subtarget in
* this armature?
*/
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -327,8 +324,8 @@ void updateDuplicateSubtargetObjects(EditBone *dupBone, ListBase *editbones, Obj
* so, update the constraint to point at the
* duplicate of the old subtarget.
*/
- if (oldtarget->temp) {
- newtarget = (EditBone *) oldtarget->temp;
+ if (oldtarget->temp.ebone) {
+ newtarget = oldtarget->temp.ebone;
BLI_strncpy(ct->subtarget, newtarget->name, sizeof(ct->subtarget));
}
}
@@ -357,8 +354,8 @@ EditBone *duplicateEditBoneObjects(EditBone *curBone, const char *name, ListBase
/* Copy data from old bone to new bone */
memcpy(eBone, curBone, sizeof(EditBone));
- curBone->temp = eBone;
- eBone->temp = curBone;
+ curBone->temp.ebone = eBone;
+ eBone->temp.ebone = curBone;
if (name != NULL) {
BLI_strncpy(eBone->name, name, sizeof(eBone->name));
@@ -398,13 +395,11 @@ EditBone *duplicateEditBone(EditBone *curBone, const char *name, ListBase *editb
return duplicateEditBoneObjects(curBone, name, editbones, ob, ob);
}
-/* previously adduplicate_armature */
static int armature_duplicate_selected_exec(bContext *C, wmOperator *UNUSED(op))
{
bArmature *arm;
- EditBone *eBone = NULL;
- EditBone *curBone;
- EditBone *firstDup = NULL; /* The beginning of the duplicated bones in the edbo list */
+ EditBone *ebone_iter;
+ EditBone *ebone_first_dupe = NULL; /* The beginning of the duplicated bones in the edbo list */
Object *obedit = CTX_data_edit_object(C);
arm = obedit->data;
@@ -419,77 +414,80 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *UNUSED(op))
/* Select mirrored bones */
if (arm->flag & ARM_MIRROR_EDIT) {
- for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
- if (EBONE_VISIBLE(arm, curBone)) {
- if (curBone->flag & BONE_SELECTED) {
- eBone = ED_armature_bone_get_mirrored(arm->edbo, curBone);
- if (eBone)
- eBone->flag |= BONE_SELECTED;
+ for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
+ if (EBONE_VISIBLE(arm, ebone_iter) &&
+ (ebone_iter->flag & BONE_SELECTED))
+ {
+ EditBone *ebone;
+
+ ebone = ED_armature_bone_get_mirrored(arm->edbo, ebone_iter);
+ if (ebone) {
+ ebone->flag |= BONE_SELECTED;
}
}
}
}
- /* Find the selected bones and duplicate them as needed */
- for (curBone = arm->edbo->first; curBone && curBone != firstDup; curBone = curBone->next) {
- if (EBONE_VISIBLE(arm, curBone)) {
- if (curBone->flag & BONE_SELECTED) {
-
- eBone = duplicateEditBone(curBone, curBone->name, arm->edbo, obedit);
-
- if (!firstDup)
- firstDup = eBone;
+ /* Find the selected bones and duplicate them as needed */
+ for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) {
+ if (EBONE_VISIBLE(arm, ebone_iter) &&
+ (ebone_iter->flag & BONE_SELECTED))
+ {
+ EditBone *ebone;
+ ebone = duplicateEditBone(ebone_iter, ebone_iter->name, arm->edbo, obedit);
+
+ if (!ebone_first_dupe) {
+ ebone_first_dupe = ebone;
}
}
}
- /* Run though the list and fix the pointers */
- for (curBone = arm->edbo->first; curBone && curBone != firstDup; curBone = curBone->next) {
- if (EBONE_VISIBLE(arm, curBone)) {
- if (curBone->flag & BONE_SELECTED) {
- eBone = (EditBone *) curBone->temp;
-
- if (!curBone->parent) {
- /* If this bone has no parent,
- * Set the duplicate->parent to NULL
- */
- eBone->parent = NULL;
- }
- else if (curBone->parent->temp) {
- /* If this bone has a parent that was duplicated,
- * Set the duplicate->parent to the curBone->parent->temp
- */
- eBone->parent = (EditBone *)curBone->parent->temp;
- }
- else {
- /* If this bone has a parent that IS not selected,
- * Set the duplicate->parent to the curBone->parent
- */
- eBone->parent = (EditBone *) curBone->parent;
- eBone->flag &= ~BONE_CONNECTED;
- }
-
- /* Lets try to fix any constraint subtargets that might
- * have been duplicated
+ /* Run though the list and fix the pointers */
+ for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) {
+ if (EBONE_VISIBLE(arm, ebone_iter) &&
+ (ebone_iter->flag & BONE_SELECTED))
+ {
+ EditBone *ebone = ebone_iter->temp.ebone;
+
+ if (!ebone_iter->parent) {
+ /* If this bone has no parent,
+ * Set the duplicate->parent to NULL
+ */
+ ebone->parent = NULL;
+ }
+ else if (ebone_iter->parent->temp.ebone) {
+ /* If this bone has a parent that was duplicated,
+ * Set the duplicate->parent to the curBone->parent->temp
+ */
+ ebone->parent = ebone_iter->parent->temp.ebone;
+ }
+ else {
+ /* If this bone has a parent that IS not selected,
+ * Set the duplicate->parent to the curBone->parent
*/
- updateDuplicateSubtarget(eBone, arm->edbo, obedit);
+ ebone->parent = (EditBone *) ebone_iter->parent;
+ ebone->flag &= ~BONE_CONNECTED;
}
+
+ /* Lets try to fix any constraint subtargets that might
+ * have been duplicated
+ */
+ updateDuplicateSubtarget(ebone, arm->edbo, obedit);
}
}
/* correct the active bone */
- if (arm->act_edbone) {
- eBone = arm->act_edbone;
- if (eBone->temp)
- arm->act_edbone = eBone->temp;
+ if (arm->act_edbone && arm->act_edbone->temp.ebone) {
+ arm->act_edbone = arm->act_edbone->temp.ebone;
}
- /* Deselect the old bones and select the new ones */
- for (curBone = arm->edbo->first; curBone && curBone != firstDup; curBone = curBone->next) {
- if (EBONE_VISIBLE(arm, curBone))
- curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ /* Deselect the old bones and select the new ones */
+ for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) {
+ if (EBONE_VISIBLE(arm, ebone_iter)) {
+ ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
}
ED_armature_validate_active(arm);
@@ -515,6 +513,214 @@ void ARMATURE_OT_duplicate(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/**
+ * near duplicate of #armature_duplicate_selected_exec,
+ * except for parenting part (keep in sync)
+ */
+static int armature_symmetrize_exec(bContext *C, wmOperator *op)
+{
+ bArmature *arm;
+ EditBone *ebone_iter;
+ EditBone *ebone_first_dupe = NULL; /* The beginning of the duplicated mirrored bones in the edbo list */
+
+ Object *obedit = CTX_data_edit_object(C);
+ const int direction = RNA_enum_get(op->ptr, "direction");
+ const int axis = 0;
+
+ arm = obedit->data;
+
+ /* cancel if nothing selected */
+ if (CTX_DATA_COUNT(C, selected_bones) == 0)
+ return OPERATOR_CANCELLED;
+
+ ED_armature_sync_selection(arm->edbo); // XXX why is this needed?
+
+ preEditBoneDuplicate(arm->edbo);
+
+ /* Select mirrored bones */
+ for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
+ if (EBONE_VISIBLE(arm, ebone_iter) &&
+ (ebone_iter->flag & BONE_SELECTED))
+ {
+ char name_flip[MAX_VGROUP_NAME];
+
+ BKE_deform_flip_side_name(name_flip, ebone_iter->name, false);
+
+ if (STREQ(name_flip, ebone_iter->name)) {
+ /* if the name matches, we don't have the potential to be mirrored, just skip */
+ ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else {
+ EditBone *ebone = ED_armature_bone_find_name(arm->edbo, name_flip);
+
+ if (ebone) {
+ if ((ebone->flag & BONE_SELECTED) == 0) {
+ /* simple case, we're selected, the other bone isn't! */
+ ebone_iter->temp.ebone = ebone;
+ }
+ else {
+ /* complicated - choose which direction to copy */
+ float axis_delta;
+
+ axis_delta = ebone->head[axis] - ebone_iter->head[axis];
+ if (axis_delta == 0.0f) {
+ axis_delta = ebone->tail[axis] - ebone_iter->tail[axis];
+ }
+
+ if (axis_delta == 0.0f) {
+ /* both mirrored bones exist and point to eachother and overlap exactly.
+ *
+ * in this case theres no well defined solution, so de-select both and skip.
+ */
+ ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else {
+ EditBone *ebone_src, *ebone_dst;
+ if (((axis_delta < 0.0f) ? -1 : 1) == direction) {
+ ebone_src = ebone;
+ ebone_dst = ebone_iter;
+ }
+ else {
+ ebone_src = ebone_iter;
+ ebone_dst = ebone;
+ }
+
+ ebone_src->temp.ebone = ebone_dst;
+ ebone_dst->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Find the selected bones and duplicate them as needed, with mirrored name */
+ for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) {
+ if (EBONE_VISIBLE(arm, ebone_iter) &&
+ (ebone_iter->flag & BONE_SELECTED) &&
+ /* will be set if the mirror bone already exists (no need to make a new one) */
+ (ebone_iter->temp.ebone == NULL))
+ {
+ char name_flip[MAX_VGROUP_NAME];
+
+ BKE_deform_flip_side_name(name_flip, ebone_iter->name, false);
+
+ /* bones must have a side-suffix */
+ if (!STREQ(name_flip, ebone_iter->name)) {
+ EditBone *ebone;
+
+ ebone = duplicateEditBone(ebone_iter, name_flip, arm->edbo, obedit);
+
+ if (!ebone_first_dupe) {
+ ebone_first_dupe = ebone;
+ }
+ }
+ }
+ }
+
+ /* Run though the list and fix the pointers */
+ for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) {
+ if (ebone_iter->temp.ebone) {
+ /* copy all flags except for ... */
+ const int flag_copy = ((int)~0) & ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
+
+ EditBone *ebone = ebone_iter->temp.ebone;
+
+ /* copy flags incase bone is pre-existing data */
+ ebone->flag = (ebone->flag & ~flag_copy) | (ebone_iter->flag & flag_copy);
+
+ if (ebone_iter->parent == NULL) {
+ /* If this bone has no parent,
+ * Set the duplicate->parent to NULL
+ */
+ ebone->parent = NULL;
+ ebone->flag &= ~BONE_CONNECTED;
+ }
+ else {
+ /* the parent may have been duplicated, if not lookup the mirror parent */
+ EditBone *ebone_parent =
+ (ebone_iter->parent->temp.ebone ?
+ ebone_iter->parent->temp.ebone : ED_armature_bone_get_mirrored(arm->edbo, ebone_iter->parent));
+
+ if (ebone_parent == NULL) {
+ /* If the mirror lookup failed, (but the current bone has a parent)
+ * then we can assume the parent has no L/R but is a center bone.
+ * So just use the same parent for both.
+ */
+ ebone_parent = ebone_iter->parent;
+ ebone->flag &= ~BONE_CONNECTED;
+ }
+
+ ebone->parent = ebone_parent;
+ }
+
+ /* Lets try to fix any constraint subtargets that might
+ * have been duplicated
+ */
+ updateDuplicateSubtarget(ebone, arm->edbo, obedit);
+ }
+ }
+
+ transform_armature_mirror_update(obedit);
+
+ /* Selected bones now have their 'temp' pointer set,
+ * so we don't need this anymore */
+
+ /* Deselect the old bones and select the new ones */
+ for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) {
+ if (EBONE_VISIBLE(arm, ebone_iter)) {
+ ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ }
+
+ /* New bones will be selected, but some of the bones may already exist */
+ for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) {
+ EditBone *ebone = ebone_iter->temp.ebone;
+ if (ebone && EBONE_SELECTABLE(arm, ebone)) {
+ ED_armature_ebone_select_set(ebone, true);
+ }
+ }
+
+ /* correct the active bone */
+ if (arm->act_edbone && arm->act_edbone->temp.ebone) {
+ arm->act_edbone = arm->act_edbone->temp.ebone;
+ }
+
+ ED_armature_validate_active(arm);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+/* following conventions from #MESH_OT_symmetrize */
+void ARMATURE_OT_symmetrize(wmOperatorType *ot)
+{
+ /* subset of 'symmetrize_direction_items' */
+ static EnumPropertyItem arm_symmetrize_direction_items[] = {
+ {-1, "NEGATIVE_X", 0, "-X to +X", ""},
+ {+1, "POSITIVE_X", 0, "+X to -X", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "Symmetrize";
+ ot->idname = "ARMATURE_OT_symmetrize";
+ ot->description = "Enforce symmetry, make copies of the selection or use existing";
+
+ /* api callbacks */
+ ot->exec = armature_symmetrize_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(
+ ot->srna, "direction", arm_symmetrize_direction_items, -1,
+ "Direction", "Which sides to copy from and to (when both are selected)");
+}
+
/* ------------------------------------------ */
/* previously extrude_armature */
@@ -704,7 +910,7 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op)
mul_m3_m3m3(totmat, obmat, viewmat);
invert_m3_m3(imat, totmat);
- ED_armature_deselect_all(obedit, 0);
+ ED_armature_deselect_all(obedit);
/* Create a bone */
bone = ED_armature_edit_bone_add(obedit->data, name);
diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c
index 88c52989c07..d4df77753eb 100644
--- a/source/blender/editors/armature/armature_edit.c
+++ b/source/blender/editors/armature/armature_edit.c
@@ -578,6 +578,7 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
ListBase points = {NULL, NULL};
+ EditBone *newbone = NULL;
int count;
/* sanity checks */
@@ -610,94 +611,97 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op)
float curs[3];
/* Get Points - selected joint */
- ebp = (EditBonePoint *)points.first;
+ ebp = points.first;
/* Get points - cursor (tail) */
invert_m4_m4(obedit->imat, obedit->obmat);
mul_v3_m4v3(curs, obedit->imat, ED_view3d_cursor3d_get(scene, v3d));
/* Create a bone */
- /* newbone = */ add_points_bone(obedit, ebp->vec, curs);
+ newbone = add_points_bone(obedit, ebp->vec, curs);
}
else if (count == 2) {
- EditBonePoint *ebp, *ebp2;
+ EditBonePoint *ebp_a, *ebp_b;
float head[3], tail[3];
short headtail = 0;
/* check that the points don't belong to the same bone */
- ebp = (EditBonePoint *)points.first;
- ebp2 = ebp->next;
+ ebp_a = (EditBonePoint *)points.first;
+ ebp_b = ebp_a->next;
- if ((ebp->head_owner == ebp2->tail_owner) && (ebp->head_owner != NULL)) {
- BKE_report(op->reports, RPT_ERROR, "Same bone selected...");
- BLI_freelistN(&points);
- return OPERATOR_CANCELLED;
- }
- if ((ebp->tail_owner == ebp2->head_owner) && (ebp->tail_owner != NULL)) {
+ if (((ebp_a->head_owner == ebp_b->tail_owner) && (ebp_a->head_owner != NULL)) ||
+ ((ebp_a->tail_owner == ebp_b->head_owner) && (ebp_a->tail_owner != NULL)))
+ {
BKE_report(op->reports, RPT_ERROR, "Same bone selected...");
BLI_freelistN(&points);
return OPERATOR_CANCELLED;
}
/* 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 */
- invert_m4_m4(obedit->imat, obedit->obmat);
- mul_v3_m4v3(curs, obedit->imat, ED_view3d_cursor3d_get(scene, v3d));
-
- /* get distances */
- sub_v3_v3v3(vecA, ebp->vec, curs);
- sub_v3_v3v3(vecB, ebp2->vec, curs);
- distA = len_v3(vecA);
- distB = len_v3(vecB);
-
- /* compare distances - closer one therefore acts as direction for bone to go */
- headtail = (distA < distB) ? 2 : 1;
+ if ((ebp_a->head_owner && ebp_b->head_owner) || (ebp_a->tail_owner && ebp_b->tail_owner)) {
+ /* use active, nice predictable */
+ if (arm->act_edbone && ELEM(arm->act_edbone, ebp_a->head_owner, ebp_a->tail_owner)) {
+ headtail = 1;
+ }
+ else if (arm->act_edbone && ELEM(arm->act_edbone, ebp_b->head_owner, ebp_b->tail_owner)) {
+ headtail = 2;
+ }
+ else {
+ /* rule: whichever one is closer to 3d-cursor */
+ float curs[3];
+ float dist_sq_a, dist_sq_b;
+
+ /* get cursor location */
+ invert_m4_m4(obedit->imat, obedit->obmat);
+ mul_v3_m4v3(curs, obedit->imat, ED_view3d_cursor3d_get(scene, v3d));
+
+ /* get distances */
+ dist_sq_a = len_squared_v3v3(ebp_a->vec, curs);
+ dist_sq_b = len_squared_v3v3(ebp_b->vec, curs);
+
+ /* compare distances - closer one therefore acts as direction for bone to go */
+ headtail = (dist_sq_a < dist_sq_b) ? 2 : 1;
+ }
}
- else if (ebp->head_owner) {
+ else if (ebp_a->head_owner) {
headtail = 1;
}
- else if (ebp2->head_owner) {
+ else if (ebp_b->head_owner) {
headtail = 2;
}
/* assign head/tail combinations */
if (headtail == 2) {
- copy_v3_v3(head, ebp->vec);
- copy_v3_v3(tail, ebp2->vec);
+ copy_v3_v3(head, ebp_a->vec);
+ copy_v3_v3(tail, ebp_b->vec);
}
else if (headtail == 1) {
- copy_v3_v3(head, ebp2->vec);
- copy_v3_v3(tail, ebp->vec);
+ copy_v3_v3(head, ebp_b->vec);
+ copy_v3_v3(tail, ebp_a->vec);
}
/* add new bone and parent it to the appropriate end */
if (headtail) {
- EditBone *newbone = add_points_bone(obedit, head, tail);
+ newbone = add_points_bone(obedit, head, tail);
/* do parenting (will need to set connected flag too) */
if (headtail == 2) {
/* ebp tail or head - tail gets priority */
- if (ebp->tail_owner)
- newbone->parent = ebp->tail_owner;
+ if (ebp_a->tail_owner)
+ newbone->parent = ebp_a->tail_owner;
else
- newbone->parent = ebp->head_owner;
+ newbone->parent = ebp_a->head_owner;
}
else {
- /* ebp2 tail or head - tail gets priority */
- if (ebp2->tail_owner)
- newbone->parent = ebp2->tail_owner;
+ /* ebp_b tail or head - tail gets priority */
+ if (ebp_b->tail_owner)
+ newbone->parent = ebp_b->tail_owner;
else
- newbone->parent = ebp2->head_owner;
+ newbone->parent = ebp_b->head_owner;
}
/* don't set for bone connecting two head points of bones */
- if (ebp->tail_owner || ebp2->tail_owner) {
+ if (ebp_a->tail_owner || ebp_b->tail_owner) {
newbone->flag |= BONE_CONNECTED;
}
}
@@ -708,6 +712,12 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op)
BLI_freelistN(&points);
return OPERATOR_CANCELLED;
}
+
+ if (newbone) {
+ ED_armature_deselect_all(obedit);
+ arm->act_edbone = newbone;
+ newbone->flag |= BONE_TIPSEL;
+ }
/* updates */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
@@ -1254,7 +1264,7 @@ static int armature_delete_selected_exec(bContext *C, wmOperator *UNUSED(op))
}
else {
for (con = pchan->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h
index 2c64c9aa345..0607bc49515 100644
--- a/source/blender/editors/armature/armature_intern.h
+++ b/source/blender/editors/armature/armature_intern.h
@@ -72,6 +72,7 @@ void ARMATURE_OT_shortest_path_pick(struct wmOperatorType *ot);
void ARMATURE_OT_delete(struct wmOperatorType *ot);
void ARMATURE_OT_duplicate(struct wmOperatorType *ot);
+void ARMATURE_OT_symmetrize(struct wmOperatorType *ot);
void ARMATURE_OT_extrude(struct wmOperatorType *ot);
void ARMATURE_OT_hide(struct wmOperatorType *ot);
void ARMATURE_OT_reveal(struct wmOperatorType *ot);
diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c
index a8b5f888597..eedff896315 100644
--- a/source/blender/editors/armature/armature_naming.c
+++ b/source/blender/editors/armature/armature_naming.c
@@ -104,7 +104,7 @@ static void constraint_bone_name_fix(Object *ob, ListBase *conlist, const char *
bConstraintTarget *ct;
for (curcon = conlist->first; curcon; curcon = curcon->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon);
ListBase targets = {NULL, NULL};
/* constraint targets */
@@ -270,7 +270,7 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n
// XXX: the ID here is for armatures, but most bone drivers are actually on the object instead...
{
- BKE_all_animdata_fix_paths_rename(&arm->id, "pose.bones", oldname, newname);
+ BKE_animdata_fix_paths_rename_all(&arm->id, "pose.bones", oldname, newname);
}
/* correct view locking */
diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c
index c80953d6737..ea435e3e4fa 100644
--- a/source/blender/editors/armature/armature_ops.c
+++ b/source/blender/editors/armature/armature_ops.c
@@ -66,6 +66,7 @@ void ED_operatortypes_armature(void)
WM_operatortype_append(ARMATURE_OT_delete);
WM_operatortype_append(ARMATURE_OT_duplicate);
+ WM_operatortype_append(ARMATURE_OT_symmetrize);
WM_operatortype_append(ARMATURE_OT_extrude);
WM_operatortype_append(ARMATURE_OT_hide);
WM_operatortype_append(ARMATURE_OT_reveal);
@@ -275,7 +276,7 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "ARMATURE_OT_merge", MKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "ARMATURE_OT_split", YKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "ARMATURE_OT_separate", PKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
+ WM_keymap_add_item(keymap, "ARMATURE_OT_separate", PKEY, KM_PRESS, 0, 0);
/* set flags */
WM_keymap_add_menu(keymap, "VIEW3D_MT_bone_options_toggle", WKEY, KM_PRESS, KM_SHIFT, 0);
@@ -411,5 +412,6 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
/* menus */
WM_keymap_add_menu(keymap, "VIEW3D_MT_pose_specials", WKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_menu(keymap, "VIEW3D_MT_pose_propagate", PKEY, KM_PRESS, KM_ALT, 0);
}
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index 53989dd783c..8cda6f6db77 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -78,7 +78,7 @@ static void joined_armature_fix_links_constraints(
bConstraint *con;
for (con = lb->first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -380,7 +380,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
if (base->object->adt) {
if (ob->adt == NULL) {
/* no animdata, so just use a copy of the whole thing */
- ob->adt = BKE_copy_animdata(base->object->adt, false);
+ ob->adt = BKE_animdata_copy(base->object->adt, false);
}
else {
/* merge in data - we'll fix the drivers manually */
@@ -391,7 +391,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
if (curarm->adt) {
if (arm->adt == NULL) {
/* no animdata, so just use a copy of the whole thing */
- arm->adt = BKE_copy_animdata(curarm->adt, false);
+ arm->adt = BKE_animdata_copy(curarm->adt, false);
}
else {
/* merge in data - we'll fix the drivers manually */
@@ -435,7 +435,7 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm)
if (ob->type == OB_ARMATURE) {
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
for (con = pchan->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -473,7 +473,7 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm)
/* fix object-level constraints */
if (ob != origArm) {
for (con = ob->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -548,7 +548,7 @@ static void separate_armature_bones(Object *ob, short sel)
for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
if (ebo->parent == curbone) {
ebo->parent = NULL;
- ebo->temp = NULL; /* this is needed to prevent random crashes with in ED_armature_from_edit */
+ ebo->temp.p = NULL; /* this is needed to prevent random crashes with in ED_armature_from_edit */
ebo->flag &= ~BONE_CONNECTED;
}
}
@@ -641,6 +641,9 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
ED_armature_to_edit(obedit->data);
+ /* parents tips remain selected when connected children are removed. */
+ ED_armature_deselect_all(obedit);
+
BKE_report(op->reports, RPT_INFO, "Separated bones");
/* note, notifier might evolve */
@@ -660,6 +663,7 @@ void ARMATURE_OT_separate(wmOperatorType *ot)
ot->description = "Isolate selected bones into a separate armature";
/* callbacks */
+ ot->invoke = WM_operator_confirm;
ot->exec = separate_armature_exec;
ot->poll = ED_operator_editarmature;
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index 581dd00e285..5aa2c628252 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -54,9 +54,9 @@
#include "armature_intern.h"
-/* utility macros fro storing a temp int in the bone (selection flag) */
-#define EBONE_PREV_FLAG_GET(ebone) ((void)0, (GET_INT_FROM_POINTER((ebone)->temp)))
-#define EBONE_PREV_FLAG_SET(ebone, val) ((ebone)->temp = SET_INT_IN_POINTER(val))
+/* utility macros for storing a temp int in the bone (selection flag) */
+#define EBONE_PREV_FLAG_GET(ebone) ((void)0, (ebone)->temp.i)
+#define EBONE_PREV_FLAG_SET(ebone, val) ((ebone)->temp.i = val)
/* **************** PoseMode & EditMode Selection Buffer Queries *************************** */
@@ -388,61 +388,14 @@ static EditBone *get_nearest_editbonepoint(ViewContext *vc, const int mval[2],
return NULL;
}
-
-
-/* toggle==0: deselect
- * toggle==1: swap (based on test)
- * toggle==2: swap (no test), CURRENTLY UNUSED
- */
-void ED_armature_deselect_all(Object *obedit, int toggle)
+void ED_armature_deselect_all(Object *obedit)
{
bArmature *arm = obedit->data;
- EditBone *eBone;
- int sel = 1;
-
- if (toggle == 1) {
- /* Determine if there are any selected bones
- * and therefore whether we are selecting or deselecting */
- for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
- // if (arm->layer & eBone->layer) {
- if (eBone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
- sel = 0;
- break;
- }
- // }
- }
- }
- else {
- sel = toggle;
- }
+ EditBone *ebone;
- /* Set the flags */
- for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
- if (sel == 2) {
- /* invert selection of bone */
- if (EBONE_VISIBLE(arm, eBone)) {
- eBone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- if (arm->act_edbone == eBone)
- arm->act_edbone = NULL;
- }
- }
- else if (sel == 1) {
- /* select bone */
- if (EBONE_VISIBLE(arm, eBone)) {
- eBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- if (eBone->parent)
- eBone->parent->flag |= (BONE_TIPSEL);
- }
- }
- else {
- /* deselect bone */
- eBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- if (arm->act_edbone == eBone)
- arm->act_edbone = NULL;
- }
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
}
-
- ED_armature_sync_selection(arm->edbo);
}
void ED_armature_deselect_all_visible(Object *obedit)
@@ -489,8 +442,9 @@ bool mouse_armature(bContext *C, const int mval[2], bool extend, bool deselect,
nearBone = get_nearest_editbonepoint(&vc, mval, arm->edbo, 1, &selmask);
if (nearBone) {
- if (!extend && !deselect && !toggle)
- ED_armature_deselect_all(obedit, 0);
+ if (!extend && !deselect && !toggle) {
+ ED_armature_deselect_all(obedit);
+ }
/* by definition the non-root connected bones have no root point drawn,
* so a root selection needs to be delivered to the parent tip */
@@ -731,7 +685,7 @@ static void armature_select_more_less(Object *ob, bool more)
}
}
}
- ebone->temp = NULL;
+ ebone->temp.p = NULL;
}
ED_armature_sync_selection(arm->edbo);
@@ -962,75 +916,78 @@ void ARMATURE_OT_select_similar(wmOperatorType *ot)
/* ********************* select hierarchy operator ************** */
-/* Get the first available child of an editbone */
-static EditBone *editbone_get_child(bArmature *arm, EditBone *pabone, short use_visibility)
-{
- EditBone *curbone, *chbone = NULL;
-
- for (curbone = arm->edbo->first; curbone; curbone = curbone->next) {
- if (curbone->parent == pabone) {
- if (use_visibility) {
- if ((arm->layer & curbone->layer) && !(pabone->flag & BONE_HIDDEN_A)) {
- chbone = curbone;
- }
- }
- else
- chbone = curbone;
- }
- }
-
- return chbone;
-}
-
static int armature_select_hierarchy_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
Object *ob;
bArmature *arm;
- EditBone *curbone, *pabone, *chbone;
+ EditBone *ebone_active;
int direction = RNA_enum_get(op->ptr, "direction");
const bool add_to_sel = RNA_boolean_get(op->ptr, "extend");
+ bool changed = false;
ob = obedit;
arm = (bArmature *)ob->data;
-
- for (curbone = arm->edbo->first; curbone; curbone = curbone->next) {
- /* only work on bone if it is visible and its selection can change */
- if (EBONE_SELECTABLE(arm, curbone)) {
- if (curbone == arm->act_edbone) {
- if (direction == BONE_SELECT_PARENT) {
- if (curbone->parent == NULL) continue;
- else pabone = curbone->parent;
-
- if (EBONE_VISIBLE(arm, pabone)) {
- pabone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- arm->act_edbone = pabone;
- if (pabone->parent) pabone->parent->flag |= BONE_TIPSEL;
-
- if (!add_to_sel) curbone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- break;
- }
-
+
+ ebone_active = arm->act_edbone;
+ if (ebone_active == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (direction == BONE_SELECT_PARENT) {
+ if (ebone_active->parent) {
+ EditBone *ebone_parent;
+
+ ebone_parent = ebone_active->parent;
+
+ if (EBONE_SELECTABLE(arm, ebone_parent)) {
+ arm->act_edbone = ebone_parent;
+
+ if (!add_to_sel) {
+ ED_armature_ebone_select_set(ebone_active, false);
}
- else { // BONE_SELECT_CHILD
- chbone = editbone_get_child(arm, curbone, 1);
- if (chbone == NULL) continue;
-
- if (EBONE_SELECTABLE(arm, chbone)) {
- chbone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- arm->act_edbone = chbone;
-
- if (!add_to_sel) {
- curbone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL);
- if (curbone->parent) curbone->parent->flag &= ~BONE_TIPSEL;
+ ED_armature_ebone_select_set(ebone_parent, true);
+
+ changed = true;
+ }
+ }
+
+ }
+ else { /* BONE_SELECT_CHILD */
+ EditBone *ebone_iter, *ebone_child = NULL;
+ int pass;
+
+ /* first pass, only connected bones (the logical direct child) */
+ for (pass = 0; pass < 2 && (ebone_child == NULL); pass++) {
+ for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
+ /* possible we have multiple children, some invisible */
+ if (EBONE_SELECTABLE(arm, ebone_iter)) {
+ if (ebone_iter->parent == ebone_active) {
+ if ((pass == 1) || (ebone_iter->flag & BONE_CONNECTED)) {
+ ebone_child = ebone_iter;
+ break;
}
- break;
}
}
}
}
+
+ if (ebone_child) {
+ arm->act_edbone = ebone_child;
+
+ if (!add_to_sel) {
+ ED_armature_ebone_select_set(ebone_active, false);
+ }
+ ED_armature_ebone_select_set(ebone_child, true);
+
+ changed = true;
+ }
}
+ if (changed == false) {
+ return OPERATOR_CANCELLED;
+ }
+
ED_armature_sync_selection(arm->edbo);
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c
index 97f69d86aee..eebdd706ab2 100644
--- a/source/blender/editors/armature/armature_utils.c
+++ b/source/blender/editors/armature/armature_utils.c
@@ -488,7 +488,7 @@ static void fix_bonelist_roll(ListBase *bonelist, ListBase *editbonelist)
/* Find the associated editbone */
for (ebone = editbonelist->first; ebone; ebone = ebone->next)
- if ((Bone *)ebone->temp == curBone)
+ if (ebone->temp.bone == curBone)
break;
if (ebone) {
@@ -548,7 +548,7 @@ void ED_armature_from_edit(bArmature *arm)
/* Copy the bones from the editData into the armature */
for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
newBone = MEM_callocN(sizeof(Bone), "bone");
- eBone->temp = newBone; /* Associate the real Bones with the EditBones */
+ eBone->temp.bone = newBone; /* Associate the real Bones with the EditBones */
BLI_strncpy(newBone->name, eBone->name, sizeof(newBone->name));
copy_v3_v3(newBone->arm_head, eBone->head);
@@ -584,9 +584,9 @@ void ED_armature_from_edit(bArmature *arm)
/* Fix parenting in a separate pass to ensure ebone->bone connections
* are valid at this point */
for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
- newBone = (Bone *)eBone->temp;
+ newBone = eBone->temp.bone;
if (eBone->parent) {
- newBone->parent = (Bone *)eBone->parent->temp;
+ newBone->parent = eBone->parent->temp.bone;
BLI_addtail(&newBone->parent->childbase, newBone);
{
@@ -695,24 +695,24 @@ static void ED_armature_ebone_listbase_copy(ListBase *lb_dst, ListBase *lb_src)
if (ebone_dst->prop) {
ebone_dst->prop = IDP_CopyProperty(ebone_dst->prop);
}
- ebone_src->temp = ebone_dst;
+ ebone_src->temp.ebone = ebone_dst;
BLI_addtail(lb_dst, ebone_dst);
}
/* set pointers */
for (ebone_dst = lb_dst->first; ebone_dst; ebone_dst = ebone_dst->next) {
if (ebone_dst->parent) {
- ebone_dst->parent = ebone_dst->parent->temp;
+ ebone_dst->parent = ebone_dst->parent->temp.ebone;
}
}
}
-static void ED_armature_ebone_listbase_temp_clear(ListBase *lb)
+void ED_armature_ebone_listbase_temp_clear(ListBase *lb)
{
EditBone *ebone;
/* be sure they don't hang ever */
for (ebone = lb->first; ebone; ebone = ebone->next) {
- ebone->temp = NULL;
+ ebone->temp.p = NULL;
}
}
@@ -733,7 +733,7 @@ static void undoBones_to_editBones(void *uarmv, void *armv, void *UNUSED(data))
/* active bone */
if (uarm->act_edbone) {
ebone = uarm->act_edbone;
- arm->act_edbone = ebone->temp;
+ arm->act_edbone = ebone->temp.ebone;
}
else {
arm->act_edbone = NULL;
@@ -755,7 +755,7 @@ static void *editBones_to_undoBones(void *armv, void *UNUSED(obdata))
/* active bone */
if (arm->act_edbone) {
ebone = arm->act_edbone;
- uarm->act_edbone = ebone->temp;
+ uarm->act_edbone = ebone->temp.ebone;
}
ED_armature_ebone_listbase_temp_clear(&uarm->lb);
@@ -785,7 +785,7 @@ static void *get_armature_edit(bContext *C)
void undo_push_armature(bContext *C, const char *name)
{
// XXX solve getdata()
- undo_editmode_push(C, name, get_armature_edit, free_undoBones, undoBones_to_editBones, editBones_to_undoBones, NULL);
+ undo_editmode_push(C, name, CTX_data_edit_object, get_armature_edit, free_undoBones, undoBones_to_editBones, editBones_to_undoBones, NULL);
}
/* *************************************************************** */
diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c
index 5376fc8c79b..2235f9f92cc 100644
--- a/source/blender/editors/armature/editarmature_retarget.c
+++ b/source/blender/editors/armature/editarmature_retarget.c
@@ -707,7 +707,7 @@ static void RIG_reconnectControlBones(RigGraph *rg)
/* DO SOME MAGIC HERE */
for (pchan = rg->ob->pose->chanbase.first; pchan; pchan = pchan->next) {
for (con = pchan->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -832,7 +832,7 @@ static void RIG_reconnectControlBones(RigGraph *rg)
/* DO SOME MAGIC HERE */
for (pchan = rg->ob->pose->chanbase.first; pchan; pchan = pchan->next) {
for (con = pchan->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index b7d14e089cf..c630ea6478a 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -127,12 +127,12 @@ struct LaplacianSystem {
static void laplacian_increase_edge_count(EdgeHash *edgehash, int v1, int v2)
{
- void **p = BLI_edgehash_lookup_p(edgehash, v1, v2);
+ void **p;
- if (p)
+ if (BLI_edgehash_ensure_p(edgehash, v1, v2, &p))
*p = (void *)((intptr_t)*p + (intptr_t)1);
else
- BLI_edgehash_insert(edgehash, v1, v2, (void *)(intptr_t)1);
+ *p = (void *)((intptr_t)1);
}
static int laplacian_edge_count(EdgeHash *edgehash, int v1, int v2)
@@ -1719,7 +1719,7 @@ static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind
/* sanity check */
for (b = 0; b < mdb->size3; b++)
if (mdb->tag[b] != MESHDEFORM_TAG_EXTERIOR)
- if (fabs(mdb->totalphi[b] - 1.0f) > 1e-4)
+ if (fabsf(mdb->totalphi[b] - 1.0f) > 1e-4f)
printf("totalphi deficiency [%s|%d] %d: %.10f\n",
(mdb->tag[b] == MESHDEFORM_TAG_INTERIOR) ? "interior" : "boundary", mdb->semibound[b], mdb->varidx[b], mdb->totalphi[b]);
#endif
diff --git a/source/blender/editors/armature/meshlaplacian.h b/source/blender/editors/armature/meshlaplacian.h
index 820aedc5467..1412136c1a8 100644
--- a/source/blender/editors/armature/meshlaplacian.h
+++ b/source/blender/editors/armature/meshlaplacian.h
@@ -29,11 +29,9 @@
//#define RIGID_DEFORM
-struct Scene;
struct Object;
struct Mesh;
struct bDeformGroup;
-struct MeshDeformModifierData;
#ifdef RIGID_DEFORM
struct EditMesh;
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index 549a3854bac..e87c324d7ec 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -436,7 +436,7 @@ static void pose_copy_menu(Scene *scene)
pchan->constflag |= pchanact->constflag;
if (ob->pose)
- ob->pose->flag |= POSE_RECALC;
+ BKE_pose_tag_recalc(bmain, ob->pose);
}
break;
case 6: /* Transform Locks */
@@ -550,7 +550,7 @@ static void pose_copy_menu(Scene *scene)
BKE_pose_update_constraint_flags(ob->pose); /* we could work out the flags but its simpler to do this */
if (ob->pose)
- ob->pose->flag |= POSE_RECALC;
+ BKE_pose_tag_recalc(bmain, ob->pose);
}
DAG_id_tag_update(&ob->id, OB_RECALC_DATA); // and all its relations
@@ -862,7 +862,7 @@ static int pose_bone_layers_invoke(bContext *C, wmOperator *op, const wmEvent *e
/* loop over the bits for this pchan's layers, adding layers where they're needed */
for (bit = 0; bit < 32; bit++) {
- layers[bit] = (pchan->bone->layer & (1 << bit)) != 0;
+ layers[bit] = (pchan->bone->layer & (1u << bit)) != 0;
}
}
CTX_DATA_END;
@@ -936,8 +936,9 @@ static int armature_bone_layers_invoke(bContext *C, wmOperator *op, const wmEven
/* loop over the bits for this pchan's layers, adding layers where they're needed */
for (bit = 0; bit < 32; bit++) {
- if (ebone->layer & (1 << bit))
+ if (ebone->layer & (1u << bit)) {
layers[bit] = 1;
+ }
}
}
CTX_DATA_END;
diff --git a/source/blender/editors/armature/pose_group.c b/source/blender/editors/armature/pose_group.c
index 413a74d24b5..4d9df06f33f 100644
--- a/source/blender/editors/armature/pose_group.c
+++ b/source/blender/editors/armature/pose_group.c
@@ -130,6 +130,7 @@ static int pose_groups_menu_invoke(bContext *C, wmOperator *op, const wmEvent *U
{
Object *ob = ED_pose_object_from_context(C);
bPose *pose;
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "type");
uiPopupMenu *pup;
uiLayout *layout;
@@ -140,6 +141,17 @@ static int pose_groups_menu_invoke(bContext *C, wmOperator *op, const wmEvent *U
if (ELEM(NULL, ob, ob->pose))
return OPERATOR_CANCELLED;
pose = ob->pose;
+
+ /* If group index is set, try to use it! */
+ if (RNA_property_is_set(op->ptr, prop)) {
+ const int num_groups = BLI_listbase_count(&pose->agroups);
+ const int group = RNA_property_int_get(op->ptr, prop);
+
+ /* just use the active group index, and call the exec callback for the calling operator */
+ if (group > 0 && group <= num_groups) {
+ return op->type->exec(C, op);
+ }
+ }
/* if there's no active group (or active is invalid), create a new menu to find it */
if (pose->active_group <= 0) {
diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c
index 5d5a9bf363c..3bac50ef3ed 100644
--- a/source/blender/editors/armature/pose_select.c
+++ b/source/blender/editors/armature/pose_select.c
@@ -62,7 +62,7 @@
#include "armature_intern.h"
-/* utility macros fro storing a temp int in the bone (selection flag) */
+/* utility macros for storing a temp int in the bone (selection flag) */
#define PBONE_PREV_FLAG_GET(pchan) ((void)0, (GET_INT_FROM_POINTER((pchan)->temp)))
#define PBONE_PREV_FLAG_SET(pchan, val) ((pchan)->temp = SET_INT_IN_POINTER(val))
@@ -458,7 +458,7 @@ static int pose_select_constraint_target_exec(bContext *C, wmOperator *UNUSED(op
{
if (pchan->bone->flag & BONE_SELECTED) {
for (con = pchan->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -518,71 +518,67 @@ static int pose_select_hierarchy_exec(bContext *C, wmOperator *op)
{
Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
bArmature *arm = ob->data;
- Bone *curbone, *pabone, *chbone;
+ bPoseChannel *pchan_act;
int direction = RNA_enum_get(op->ptr, "direction");
const bool add_to_sel = RNA_boolean_get(op->ptr, "extend");
- bool found = false;
+ bool changed = false;
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
- {
- curbone = pchan->bone;
-
- if ((curbone->flag & BONE_UNSELECTABLE) == 0) {
- if (curbone == arm->act_bone) {
- if (direction == BONE_SELECT_PARENT) {
- if (pchan->parent == NULL) continue;
- else pabone = pchan->parent->bone;
-
- if (PBONE_SELECTABLE(arm, pabone)) {
- if (!add_to_sel) curbone->flag &= ~BONE_SELECTED;
- pabone->flag |= BONE_SELECTED;
- arm->act_bone = pabone;
-
- found = 1;
- break;
- }
+ pchan_act = BKE_pose_channel_active(ob);
+ if (pchan_act == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (direction == BONE_SELECT_PARENT) {
+ if (pchan_act->parent) {
+ Bone *bone_parent;
+ bone_parent = pchan_act->parent->bone;
+
+ if (PBONE_SELECTABLE(arm, bone_parent)) {
+ if (!add_to_sel) {
+ pchan_act->bone->flag &= ~BONE_SELECTED;
}
- else { /* direction == BONE_SELECT_CHILD */
- /* the child member is only assigned to connected bones, see [#30340] */
-#if 0
- if (pchan->child == NULL) continue;
- else chbone = pchan->child->bone;
-#else
- /* instead. find _any_ visible child bone, using the first one is a little arbitrary - campbell */
- chbone = pchan->child ? pchan->child->bone : NULL;
- if (chbone == NULL) {
- bPoseChannel *pchan_child;
-
- for (pchan_child = ob->pose->chanbase.first; pchan_child; pchan_child = pchan_child->next) {
- /* possible we have multiple children, some invisible */
- if (PBONE_SELECTABLE(arm, pchan_child->bone)) {
- if (pchan_child->parent == pchan) {
- chbone = pchan_child->bone;
- break;
- }
- }
- }
- }
+ bone_parent->flag |= BONE_SELECTED;
+ arm->act_bone = bone_parent;
- if (chbone == NULL) continue;
-#endif
-
- if (PBONE_SELECTABLE(arm, chbone)) {
- if (!add_to_sel) curbone->flag &= ~BONE_SELECTED;
- chbone->flag |= BONE_SELECTED;
- arm->act_bone = chbone;
-
- found = 1;
- break;
+ changed = true;
+ }
+ }
+ }
+ else { /* direction == BONE_SELECT_CHILD */
+ bPoseChannel *pchan_iter;
+ Bone *bone_child = NULL;
+ int pass;
+
+ /* first pass, only connected bones (the logical direct child) */
+ for (pass = 0; pass < 2 && (bone_child == NULL); pass++) {
+ for (pchan_iter = ob->pose->chanbase.first; pchan_iter; pchan_iter = pchan_iter->next) {
+ /* possible we have multiple children, some invisible */
+ if (PBONE_SELECTABLE(arm, pchan_iter->bone)) {
+ if (pchan_iter->parent == pchan_act) {
+ if ((pass == 1) || (pchan_iter->bone->flag & BONE_CONNECTED)) {
+ bone_child = pchan_iter->bone;
+ break;
+ }
}
}
}
}
+
+ if (bone_child) {
+ arm->act_bone = bone_child;
+
+ if (!add_to_sel) {
+ pchan_act->bone->flag &= ~BONE_SELECTED;
+ }
+ bone_child->flag |= BONE_SELECTED;
+
+ changed = true;
+ }
}
- CTX_DATA_END;
- if (found == 0)
+ if (changed == false) {
return OPERATOR_CANCELLED;
+ }
/* updates */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c
index 5f9f24d23a4..1a1108a2b1c 100644
--- a/source/blender/editors/armature/pose_slide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -43,6 +43,7 @@
#include "BKE_context.h"
#include "BKE_object.h"
#include "BKE_report.h"
+#include "BKE_unit.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -53,6 +54,7 @@
#include "ED_armature.h"
#include "ED_keyframes_draw.h"
#include "ED_markers.h"
+#include "ED_numinput.h"
#include "ED_screen.h"
#include "armature_intern.h"
@@ -98,6 +100,8 @@ typedef struct tPoseSlideOp {
int flag; /* unused for now, but can later get used for storing runtime settings.... */
float percentage; /* 0-1 value for determining the influence of whatever is relevant */
+
+ NumInput num; /* numeric input */
} tPoseSlideOp;
/* Pose Sliding Modes */
@@ -154,6 +158,12 @@ static int pose_slide_init(bContext *C, wmOperator *op, short mode)
*/
BLI_dlrbTree_init(&pso->keys);
+ /* initialise numeric input */
+ initNumInput(&pso->num);
+ pso->num.idx_max = 0; /* one axis */
+ pso->num.val_flag[0] |= NUM_NO_NEGATIVE;
+ pso->num.unit_type[0] = B_UNIT_NONE; /* percentages don't have any units... */
+
/* return status is whether we've got all the data we were requested to get */
return 1;
}
@@ -201,6 +211,12 @@ static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, float *val)
/* next/end */
eVal = evaluate_fcurve(fcu, (float)pso->nextFrame);
+ /* if both values are equal, don't do anything */
+ if (IS_EQF(sVal, eVal)) {
+ (*val) = sVal;
+ return;
+ }
+
/* calculate the relative weights of the endpoints */
if (pso->mode == POSESLIDE_BREAKDOWN) {
/* get weights from the percentage control */
@@ -234,7 +250,7 @@ static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, float *val)
* - perform this weighting a number of times given by the percentage...
*/
int iters = (int)ceil(10.0f * pso->percentage); /* TODO: maybe a sensitivity ctrl on top of this is needed */
-
+
while (iters-- > 0) {
(*val) = (-((sVal * w2) + (eVal * w1)) + ((*val) * 6.0f) ) / 5.0f;
}
@@ -247,7 +263,7 @@ static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, float *val)
* - perform this weighting a number of times given by the percentage...
*/
int iters = (int)ceil(10.0f * pso->percentage); /* TODO: maybe a sensitivity ctrl on top of this is needed */
-
+
while (iters-- > 0) {
(*val) = ( ((sVal * w2) + (eVal * w1)) + ((*val) * 5.0f) ) / 6.0f;
}
@@ -320,6 +336,7 @@ static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
if (prop) {
switch (RNA_property_type(prop)) {
+ /* continuous values that can be smoothly interpolated... */
case PROP_FLOAT:
{
float tval = RNA_property_float_get(&ptr, prop);
@@ -327,8 +344,6 @@ static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
RNA_property_float_set(&ptr, prop, tval);
break;
}
- case PROP_BOOLEAN:
- case PROP_ENUM:
case PROP_INT:
{
float tval = (float)RNA_property_int_get(&ptr, prop);
@@ -336,6 +351,23 @@ static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
RNA_property_int_set(&ptr, prop, (int)tval);
break;
}
+
+ /* values which can only take discrete values */
+ case PROP_BOOLEAN:
+ {
+ float tval = (float)RNA_property_boolean_get(&ptr, prop);
+ pose_slide_apply_val(pso, fcu, &tval);
+ RNA_property_boolean_set(&ptr, prop, (int)tval); // XXX: do we need threshold clamping here?
+ break;
+ }
+ case PROP_ENUM:
+ {
+ /* don't handle this case - these don't usually represent interchangeable
+ * set of values which should be interpolated between
+ */
+ break;
+ }
+
default:
/* cannot handle */
//printf("Cannot Pose Slide non-numerical property\n");
@@ -404,11 +436,11 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
}
else if (pso->mode == POSESLIDE_PUSH) {
float quat_diff[4], quat_orig[4];
-
+
/* calculate the delta transform from the previous to the current */
/* TODO: investigate ways to favour one transform more? */
sub_qt_qtqt(quat_diff, pchan->quat, quat_prev);
-
+
/* make a copy of the original rotation */
copy_qt_qt(quat_orig, pchan->quat);
@@ -418,7 +450,7 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
else {
float quat_interp[4], quat_orig[4];
int iters = (int)ceil(10.0f * pso->percentage); /* TODO: maybe a sensitivity ctrl on top of this is needed */
-
+
/* perform this blending several times until a satisfactory result is reached */
while (iters-- > 0) {
/* calculate the interpolation between the endpoints */
@@ -512,7 +544,7 @@ static void pose_slide_reset(tPoseSlideOp *pso)
/* draw percentage indicator in header */
static void pose_slide_draw_status(tPoseSlideOp *pso)
{
- char status_str[32];
+ char status_str[256];
char mode_str[32];
switch (pso->mode) {
@@ -532,7 +564,18 @@ static void pose_slide_draw_status(tPoseSlideOp *pso)
break;
}
- BLI_snprintf(status_str, sizeof(status_str), "%s: %d %%", mode_str, (int)(pso->percentage * 100.0f));
+ if (hasNumInput(&pso->num)) {
+ Scene *scene = pso->scene;
+ char str_offs[NUM_STR_REP_LEN];
+
+ outputNumInput(&pso->num, str_offs, &scene->unit);
+
+ BLI_snprintf(status_str, sizeof(status_str), "%s: %s", mode_str, str_offs);
+ }
+ else {
+ BLI_snprintf(status_str, sizeof(status_str), "%s: %d %%", mode_str, (int)(pso->percentage * 100.0f));
+ }
+
ED_area_headerprint(pso->sa, status_str);
}
@@ -617,6 +660,7 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
tPoseSlideOp *pso = op->customdata;
wmWindow *win = CTX_wm_window(C);
+ const bool has_numinput = hasNumInput(&pso->num);
switch (event->type) {
case LEFTMOUSE: /* confirm */
@@ -656,25 +700,54 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
case MOUSEMOVE: /* calculate new position */
{
- /* calculate percentage based on position of mouse (we only use x-axis for now.
- * since this is more convenient for users to do), and store new percentage value
- */
- pso->percentage = (event->x - pso->ar->winrct.xmin) / ((float)pso->ar->winx);
- RNA_float_set(op->ptr, "percentage", pso->percentage);
-
- /* update percentage indicator in header */
- pose_slide_draw_status(pso);
-
- /* reset transforms (to avoid accumulation errors) */
- pose_slide_reset(pso);
-
- /* apply... */
- pose_slide_apply(C, pso);
+ /* only handle mousemove if not doing numinput */
+ if (has_numinput == false) {
+ /* calculate percentage based on position of mouse (we only use x-axis for now.
+ * since this is more convenient for users to do), and store new percentage value
+ */
+ pso->percentage = (event->x - pso->ar->winrct.xmin) / ((float)pso->ar->winx);
+ RNA_float_set(op->ptr, "percentage", pso->percentage);
+
+ /* update percentage indicator in header */
+ pose_slide_draw_status(pso);
+
+ /* reset transforms (to avoid accumulation errors) */
+ pose_slide_reset(pso);
+
+ /* apply... */
+ pose_slide_apply(C, pso);
+ }
break;
}
- default: /* unhandled event (maybe it was some view manip? */
- /* allow to pass through */
- return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH;
+ default:
+ if ((event->val == KM_PRESS) && handleNumInput(C, &pso->num, event)) {
+ float value;
+
+ /* Grab percentage from numeric input, and store this new value for redo
+ * NOTE: users see ints, while internally we use a 0-1 float
+ */
+ value = pso->percentage * 100.0f;
+ applyNumInput(&pso->num, &value);
+
+ pso->percentage = value / 100.0f;
+ CLAMP(pso->percentage, 0.0f, 1.0f);
+ RNA_float_set(op->ptr, "percentage", pso->percentage);
+
+ /* update percentage indicator in header */
+ pose_slide_draw_status(pso);
+
+ /* reset transforms (to avoid accumulation errors) */
+ pose_slide_reset(pso);
+
+ /* apply... */
+ pose_slide_apply(C, pso);
+ break;
+ }
+ else {
+ /* unhandled event - maybe it was some view manip? */
+ /* allow to pass through */
+ return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH;
+ }
}
/* still running... */
@@ -898,6 +971,8 @@ typedef enum ePosePropagate_Termination {
/* stop when we run out of keyframes */
POSE_PROPAGATE_BEFORE_END,
+ /* only do on keyframes that are selected */
+ POSE_PROPAGATE_SELECTED_KEYS,
/* only do on the frames where markers are selected */
POSE_PROPAGATE_SELECTED_MARKERS
} ePosePropagate_Termination;
@@ -1137,6 +1212,11 @@ static void pose_propagate_fcurve(wmOperator *op, Object *ob, FCurve *fcu,
if (ce == NULL)
continue;
}
+ else if (mode == POSE_PROPAGATE_SELECTED_KEYS) {
+ /* only allow if this keyframe is already selected - skip otherwise */
+ if (BEZSELECTED(bezt) == 0)
+ continue;
+ }
/* just flatten handles, since values will now be the same either side... */
/* TODO: perhaps a fade-out modulation of the value is required here (optional once again)? */
@@ -1219,12 +1299,20 @@ static int pose_propagate_exec(bContext *C, wmOperator *op)
void POSE_OT_propagate(wmOperatorType *ot)
{
static EnumPropertyItem terminate_items[] = {
- {POSE_PROPAGATE_SMART_HOLDS, "WHILE_HELD", 0, "While Held", "Propagate pose to all keyframes after current frame that don't change (Default behavior)"},
- {POSE_PROPAGATE_NEXT_KEY, "NEXT_KEY", 0, "To Next Keyframe", "Propagate pose to first keyframe following the current frame only"},
- {POSE_PROPAGATE_LAST_KEY, "LAST_KEY", 0, "To Last Keyframe", "Propagate pose to the last keyframe only (i.e. making action cyclic)"},
- {POSE_PROPAGATE_BEFORE_FRAME, "BEFORE_FRAME", 0, "Before Frame", "Propagate pose to all keyframes between current frame and 'Frame' property"},
- {POSE_PROPAGATE_BEFORE_END, "BEFORE_END", 0, "Before Last Keyframe", "Propagate pose to all keyframes from current frame until no more are found"},
- {POSE_PROPAGATE_SELECTED_MARKERS, "SELECTED_MARKERS", 0, "On Selected Markers", "Propagate pose to all keyframes occurring on frames with Scene Markers after the current frame"},
+ {POSE_PROPAGATE_SMART_HOLDS, "WHILE_HELD", 0, "While Held",
+ "Propagate pose to all keyframes after current frame that don't change (Default behavior)"},
+ {POSE_PROPAGATE_NEXT_KEY, "NEXT_KEY", 0, "To Next Keyframe",
+ "Propagate pose to first keyframe following the current frame only"},
+ {POSE_PROPAGATE_LAST_KEY, "LAST_KEY", 0, "To Last Keyframe",
+ "Propagate pose to the last keyframe only (i.e. making action cyclic)"},
+ {POSE_PROPAGATE_BEFORE_FRAME, "BEFORE_FRAME", 0, "Before Frame",
+ "Propagate pose to all keyframes between current frame and 'Frame' property"},
+ {POSE_PROPAGATE_BEFORE_END, "BEFORE_END", 0, "Before Last Keyframe",
+ "Propagate pose to all keyframes from current frame until no more are found"},
+ {POSE_PROPAGATE_SELECTED_KEYS, "SELECTED_KEYS", 0, "On Selected Keyframes",
+ "Propagate pose to all selected keyframes"},
+ {POSE_PROPAGATE_SELECTED_MARKERS, "SELECTED_MARKERS", 0, "On Selected Markers",
+ "Propagate pose to all keyframes occurring on frames with Scene Markers after the current frame"},
{0, NULL, 0, NULL, NULL}};
/* identifiers */
diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c
index fbf6dccdb38..01e16df9f08 100644
--- a/source/blender/editors/armature/pose_transform.c
+++ b/source/blender/editors/armature/pose_transform.c
@@ -320,7 +320,7 @@ static bPoseChannel *pose_bone_do_paste(Object *ob, bPoseChannel *chan, const bo
if (selOnly)
paste_ok = ((pchan) && (pchan->bone->flag & BONE_SELECTED));
else
- paste_ok = ((pchan != NULL));
+ paste_ok = (pchan != NULL);
/* continue? */
if (paste_ok) {