Fix snapping pose mode bugs
- Object/pose checks were performed in same loop, so selected pose bones were moved instead of the object. - Snap selected to cursor/active incorrectly used unique object-data.
This commit is contained in:
@@ -70,7 +70,7 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
|
||||
Object *obedit = CTX_data_edit_object(C);
|
||||
Object *obact = CTX_data_active_object(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
RegionView3D *rv3d = CTX_wm_region_data(C);
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
@@ -81,13 +81,13 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
|
||||
gridf = ED_view3d_grid_view_scale(scene, v3d, rv3d, NULL);
|
||||
|
||||
if (obedit) {
|
||||
if (OBEDIT_FROM_OBACT(obact)) {
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
uint objects_len = 0;
|
||||
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
||||
view_layer, CTX_wm_view3d(C), &objects_len);
|
||||
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||
obedit = objects[ob_index];
|
||||
Object *obedit = objects[ob_index];
|
||||
|
||||
if (obedit->type == OB_MESH) {
|
||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||
@@ -124,89 +124,96 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
}
|
||||
MEM_freeN(objects);
|
||||
}
|
||||
else if (OBPOSE_FROM_OBACT(obact)) {
|
||||
struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
|
||||
uint objects_len = 0;
|
||||
Object **objects_eval = BKE_object_pose_array_get(view_layer_eval, v3d, &objects_len);
|
||||
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||
Object *ob_eval = objects_eval[ob_index];
|
||||
Object *ob = DEG_get_original_object(ob_eval);
|
||||
bPoseChannel *pchan_eval;
|
||||
bArmature *arm_eval = ob_eval->data;
|
||||
|
||||
invert_m4_m4(ob_eval->imat, ob_eval->obmat);
|
||||
|
||||
for (pchan_eval = ob_eval->pose->chanbase.first; pchan_eval; pchan_eval = pchan_eval->next) {
|
||||
if (pchan_eval->bone->flag & BONE_SELECTED) {
|
||||
if (pchan_eval->bone->layer & arm_eval->layer) {
|
||||
if ((pchan_eval->bone->flag & BONE_CONNECTED) == 0) {
|
||||
float nLoc[3];
|
||||
|
||||
/* get nearest grid point to snap to */
|
||||
copy_v3_v3(nLoc, pchan_eval->pose_mat[3]);
|
||||
/* We must operate in world space! */
|
||||
mul_m4_v3(ob_eval->obmat, nLoc);
|
||||
vec[0] = gridf * floorf(0.5f + nLoc[0] / gridf);
|
||||
vec[1] = gridf * floorf(0.5f + nLoc[1] / gridf);
|
||||
vec[2] = gridf * floorf(0.5f + nLoc[2] / gridf);
|
||||
/* Back in object space... */
|
||||
mul_m4_v3(ob_eval->imat, vec);
|
||||
|
||||
/* Get location of grid point in pose space. */
|
||||
BKE_armature_loc_pose_to_bone(pchan_eval, vec, vec);
|
||||
|
||||
/* adjust location on the original pchan*/
|
||||
bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, pchan_eval->name);
|
||||
if ((pchan->protectflag & OB_LOCK_LOCX) == 0) {
|
||||
pchan->loc[0] = vec[0];
|
||||
}
|
||||
if ((pchan->protectflag & OB_LOCK_LOCY) == 0) {
|
||||
pchan->loc[1] = vec[1];
|
||||
}
|
||||
if ((pchan->protectflag & OB_LOCK_LOCZ) == 0) {
|
||||
pchan->loc[2] = vec[2];
|
||||
}
|
||||
|
||||
/* auto-keyframing */
|
||||
ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
|
||||
}
|
||||
/* if the bone has a parent and is connected to the parent,
|
||||
* don't do anything - will break chain unless we do auto-ik.
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
|
||||
|
||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
||||
}
|
||||
MEM_freeN(objects_eval);
|
||||
}
|
||||
else {
|
||||
/* Object mode. */
|
||||
|
||||
struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
|
||||
|
||||
FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN (view_layer_eval, v3d, ob_eval) {
|
||||
Object *ob = DEG_get_original_object(ob_eval);
|
||||
if (ob->mode & OB_MODE_POSE) {
|
||||
bPoseChannel *pchan_eval;
|
||||
bArmature *arm_eval = ob_eval->data;
|
||||
vec[0] = -ob_eval->obmat[3][0] + gridf * floorf(0.5f + ob_eval->obmat[3][0] / gridf);
|
||||
vec[1] = -ob_eval->obmat[3][1] + gridf * floorf(0.5f + ob_eval->obmat[3][1] / gridf);
|
||||
vec[2] = -ob_eval->obmat[3][2] + gridf * floorf(0.5f + ob_eval->obmat[3][2] / gridf);
|
||||
|
||||
invert_m4_m4(ob_eval->imat, ob_eval->obmat);
|
||||
if (ob->parent) {
|
||||
float originmat[3][3];
|
||||
BKE_object_where_is_calc_ex(depsgraph, scene, NULL, ob, originmat);
|
||||
|
||||
for (pchan_eval = ob_eval->pose->chanbase.first; pchan_eval;
|
||||
pchan_eval = pchan_eval->next) {
|
||||
if (pchan_eval->bone->flag & BONE_SELECTED) {
|
||||
if (pchan_eval->bone->layer & arm_eval->layer) {
|
||||
if ((pchan_eval->bone->flag & BONE_CONNECTED) == 0) {
|
||||
float nLoc[3];
|
||||
|
||||
/* get nearest grid point to snap to */
|
||||
copy_v3_v3(nLoc, pchan_eval->pose_mat[3]);
|
||||
/* We must operate in world space! */
|
||||
mul_m4_v3(ob_eval->obmat, nLoc);
|
||||
vec[0] = gridf * floorf(0.5f + nLoc[0] / gridf);
|
||||
vec[1] = gridf * floorf(0.5f + nLoc[1] / gridf);
|
||||
vec[2] = gridf * floorf(0.5f + nLoc[2] / gridf);
|
||||
/* Back in object space... */
|
||||
mul_m4_v3(ob_eval->imat, vec);
|
||||
|
||||
/* Get location of grid point in pose space. */
|
||||
BKE_armature_loc_pose_to_bone(pchan_eval, vec, vec);
|
||||
|
||||
/* adjust location on the original pchan*/
|
||||
bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, pchan_eval->name);
|
||||
if ((pchan->protectflag & OB_LOCK_LOCX) == 0) {
|
||||
pchan->loc[0] = vec[0];
|
||||
}
|
||||
if ((pchan->protectflag & OB_LOCK_LOCY) == 0) {
|
||||
pchan->loc[1] = vec[1];
|
||||
}
|
||||
if ((pchan->protectflag & OB_LOCK_LOCZ) == 0) {
|
||||
pchan->loc[2] = vec[2];
|
||||
}
|
||||
|
||||
/* auto-keyframing */
|
||||
ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
|
||||
}
|
||||
/* if the bone has a parent and is connected to the parent,
|
||||
* don't do anything - will break chain unless we do auto-ik.
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
|
||||
|
||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
||||
invert_m3_m3(imat, originmat);
|
||||
mul_m3_v3(imat, vec);
|
||||
}
|
||||
else {
|
||||
vec[0] = -ob_eval->obmat[3][0] + gridf * floorf(0.5f + ob_eval->obmat[3][0] / gridf);
|
||||
vec[1] = -ob_eval->obmat[3][1] + gridf * floorf(0.5f + ob_eval->obmat[3][1] / gridf);
|
||||
vec[2] = -ob_eval->obmat[3][2] + gridf * floorf(0.5f + ob_eval->obmat[3][2] / gridf);
|
||||
|
||||
if (ob->parent) {
|
||||
float originmat[3][3];
|
||||
BKE_object_where_is_calc_ex(depsgraph, scene, NULL, ob, originmat);
|
||||
|
||||
invert_m3_m3(imat, originmat);
|
||||
mul_m3_v3(imat, vec);
|
||||
}
|
||||
if ((ob->protectflag & OB_LOCK_LOCX) == 0) {
|
||||
ob->loc[0] = ob_eval->loc[0] + vec[0];
|
||||
}
|
||||
if ((ob->protectflag & OB_LOCK_LOCY) == 0) {
|
||||
ob->loc[1] = ob_eval->loc[1] + vec[1];
|
||||
}
|
||||
if ((ob->protectflag & OB_LOCK_LOCZ) == 0) {
|
||||
ob->loc[2] = ob_eval->loc[2] + vec[2];
|
||||
}
|
||||
|
||||
/* auto-keyframing */
|
||||
ED_autokeyframe_object(C, scene, ob, ks);
|
||||
|
||||
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
|
||||
if ((ob->protectflag & OB_LOCK_LOCX) == 0) {
|
||||
ob->loc[0] = ob_eval->loc[0] + vec[0];
|
||||
}
|
||||
if ((ob->protectflag & OB_LOCK_LOCY) == 0) {
|
||||
ob->loc[1] = ob_eval->loc[1] + vec[1];
|
||||
}
|
||||
if ((ob->protectflag & OB_LOCK_LOCZ) == 0) {
|
||||
ob->loc[2] = ob_eval->loc[2] + vec[2];
|
||||
}
|
||||
|
||||
/* auto-keyframing */
|
||||
ED_autokeyframe_object(C, scene, ob, ks);
|
||||
|
||||
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
|
||||
}
|
||||
FOREACH_SELECTED_EDITABLE_OBJECT_END;
|
||||
}
|
||||
@@ -323,12 +330,12 @@ static int snap_selected_to_location(bContext *C,
|
||||
}
|
||||
MEM_freeN(objects);
|
||||
}
|
||||
else if (obact && (obact->mode & OB_MODE_POSE)) {
|
||||
else if (OBPOSE_FROM_OBACT(obact)) {
|
||||
struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
uint objects_len = 0;
|
||||
Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(
|
||||
view_layer, CTX_wm_view3d(C), &objects_len, OB_MODE_POSE);
|
||||
Object **objects = BKE_object_pose_array_get(view_layer, v3d, &objects_len);
|
||||
|
||||
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||
Object *ob = objects[ob_index];
|
||||
bPoseChannel *pchan;
|
||||
|
||||
Reference in New Issue
Block a user