Cleanup: minor changes to pose-mode apply visual transform
- Remove use of evaluated poses, instead calculate transformations into an array which is applied afterwards. - Only update ID's for poses that have been changed.
This commit is contained in:
parent
36deb8a48e
commit
74609bfd51
|
@ -512,37 +512,60 @@ static int pose_visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op))
|
|||
{
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
|
||||
/* Needed to ensure #bPoseChannel.pose_mat are up to date. */
|
||||
CTX_data_ensure_evaluated_depsgraph(C);
|
||||
|
||||
FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) {
|
||||
/* Loop over all selected pchan's.
|
||||
*
|
||||
* TODO, loop over children before parents if multiple bones
|
||||
* at once are to be predictable*/
|
||||
FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob, pchan) {
|
||||
const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
|
||||
bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
|
||||
float delta_mat[4][4];
|
||||
const bArmature *arm = ob->data;
|
||||
|
||||
/* chan_mat already contains the delta transform from rest pose to pose-mode pose
|
||||
int chanbase_len = BLI_listbase_count(&ob->pose->chanbase);
|
||||
/* Storage for the calculated matrices to prevent reading from modified values.
|
||||
* NOTE: this could be avoided if children were always calculated before parents
|
||||
* however ensuring this is involved and doesn't give any significant advantage. */
|
||||
struct {
|
||||
float matrix[4][4];
|
||||
bool is_set;
|
||||
} *pchan_xform_array = MEM_mallocN(sizeof(*pchan_xform_array) * chanbase_len, __func__);
|
||||
bool changed = false;
|
||||
|
||||
int i;
|
||||
LISTBASE_FOREACH_INDEX (bPoseChannel *, pchan, &ob->pose->chanbase, i) {
|
||||
if (!((pchan->bone->flag & BONE_SELECTED) && PBONE_VISIBLE(arm, pchan->bone))) {
|
||||
pchan_xform_array[i].is_set = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* `chan_mat` already contains the delta transform from rest pose to pose-mode pose
|
||||
* as that is baked into there so that B-Bones will work. Once we've set this as the
|
||||
* new raw-transform components, don't recalc the poses yet, otherwise IK result will
|
||||
* change, thus changing the result we may be trying to record.
|
||||
*/
|
||||
/* XXX For some reason, we can't use pchan->chan_mat here, gives odd rotation/offset
|
||||
* (see T38251).
|
||||
* Using pchan->pose_mat and bringing it back in bone space seems to work as expected!
|
||||
*/
|
||||
BKE_armature_mat_pose_to_bone(pchan_eval, pchan_eval->pose_mat, delta_mat);
|
||||
* new raw-transform components, don't recalculate the poses yet, otherwise IK result will
|
||||
* change, thus changing the result we may be trying to record. */
|
||||
|
||||
BKE_pchan_apply_mat4(pchan, delta_mat, true);
|
||||
/* NOTE: For some reason `pchan->chan_mat` can't be used here as it gives odd
|
||||
* rotation/offset, see T38251.
|
||||
* Using `pchan->pose_mat` and bringing it back in bone space seems to work as expected!
|
||||
* This matches how visual key-framing works. */
|
||||
BKE_armature_mat_pose_to_bone(pchan, pchan->pose_mat, pchan_xform_array[i].matrix);
|
||||
pchan_xform_array[i].is_set = true;
|
||||
changed = true;
|
||||
}
|
||||
FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
|
||||
|
||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
||||
if (changed) {
|
||||
/* Perform separately to prevent feedback loop. */
|
||||
LISTBASE_FOREACH_INDEX (bPoseChannel *, pchan, &ob->pose->chanbase, i) {
|
||||
if (!pchan_xform_array[i].is_set) {
|
||||
continue;
|
||||
}
|
||||
BKE_pchan_apply_mat4(pchan, pchan_xform_array[i].matrix, true);
|
||||
}
|
||||
|
||||
/* note, notifier might evolve */
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
|
||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
||||
|
||||
/* note, notifier might evolve */
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
|
||||
}
|
||||
|
||||
MEM_freeN(pchan_xform_array);
|
||||
}
|
||||
FOREACH_OBJECT_IN_MODE_END;
|
||||
|
||||
|
|
|
@ -287,7 +287,10 @@ typedef struct bPoseChannel {
|
|||
short rotmode;
|
||||
char _pad[2];
|
||||
|
||||
/** Matrix result of loc/quat/size, and where we put deform in, see next line */
|
||||
/**
|
||||
* Matrix result of location/rotation/scale components & constraints.
|
||||
* This is the dynamic component of `pose_mat` (without #Bone.arm_mat).
|
||||
*/
|
||||
float chan_mat[4][4];
|
||||
/**
|
||||
* Constraints accumulate here. in the end, `pose_mat = bone->arm_mat * chan_mat`
|
||||
|
|
Loading…
Reference in New Issue