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/pose_transform.c')
-rw-r--r--source/blender/editors/armature/pose_transform.c280
1 files changed, 159 insertions, 121 deletions
diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c
index 43dfa2f13d7..22c710dcda5 100644
--- a/source/blender/editors/armature/pose_transform.c
+++ b/source/blender/editors/armature/pose_transform.c
@@ -45,13 +45,16 @@
#include "BKE_blender_copybuffer.h"
#include "BKE_context.h"
#include "BKE_deform.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_main.h"
#include "BKE_object.h"
+#include "BKE_layer.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
@@ -70,8 +73,10 @@
/* Pose Apply */
/* helper for apply_armature_pose2bones - fixes parenting of objects that are bone-parented to armature */
-static void applyarmature_fix_boneparents(Main *bmain, Scene *scene, Object *armob)
+static void applyarmature_fix_boneparents(const bContext *C, Scene *scene, Object *armob)
{
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Main *bmain = CTX_data_main(C);
Object workob, *ob;
/* go through all objects in database */
@@ -83,7 +88,7 @@ static void applyarmature_fix_boneparents(Main *bmain, Scene *scene, Object *arm
*/
BKE_object_apply_mat4(ob, ob->obmat, false, false);
- BKE_object_workob_calc_parent(scene, ob, &workob);
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
invert_m4_m4(ob->parentinv, workob.obmat);
}
}
@@ -93,8 +98,10 @@ static void applyarmature_fix_boneparents(Main *bmain, Scene *scene, Object *arm
static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
Scene *scene = CTX_data_scene(C);
Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); // must be active object, not edit-object
+ const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
bArmature *arm = BKE_armature_from_object(ob);
bPose *pose;
bPoseChannel *pchan;
@@ -122,11 +129,12 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
pose = ob->pose;
for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
+ const bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
curbone = ED_armature_ebone_find_name(arm->edbo, pchan->name);
/* simply copy the head/tail values from pchan over to curbone */
- copy_v3_v3(curbone->head, pchan->pose_head);
- copy_v3_v3(curbone->tail, pchan->pose_tail);
+ copy_v3_v3(curbone->head, pchan_eval->pose_head);
+ copy_v3_v3(curbone->tail, pchan_eval->pose_tail);
/* fix roll:
* 1. find auto-calculated roll value for this bone now
@@ -142,7 +150,7 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
invert_m3_m3(imat, premat);
/* get pchan 'visual' matrix */
- copy_m3_m4(pmat, pchan->pose_mat);
+ copy_m3_m4(pmat, pchan_eval->pose_mat);
/* remove auto from visual and get euler rotation */
mul_m3_m3m3(tmat, imat, pmat);
@@ -156,17 +164,19 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
* then clear the pchan values (so we don't get a double-up)
*/
if (pchan->bone->segments > 1) {
- curbone->curveInX += pchan->curveInX;
- curbone->curveInY += pchan->curveInY;
- curbone->curveOutX += pchan->curveOutX;
- curbone->curveOutY += pchan->curveOutY;
- curbone->roll1 += pchan->roll1;
- curbone->roll2 += pchan->roll2;
- curbone->ease1 += pchan->ease1;
- curbone->ease2 += pchan->ease2;
- curbone->scaleIn += pchan->scaleIn;
- curbone->scaleOut += pchan->scaleOut;
-
+ /* combine rest/pose values */
+ curbone->curveInX += pchan_eval->curveInX;
+ curbone->curveInY += pchan_eval->curveInY;
+ curbone->curveOutX += pchan_eval->curveOutX;
+ curbone->curveOutY += pchan_eval->curveOutY;
+ curbone->roll1 += pchan_eval->roll1;
+ curbone->roll2 += pchan_eval->roll2;
+ curbone->ease1 += pchan_eval->ease1;
+ curbone->ease2 += pchan_eval->ease2;
+ curbone->scaleIn += pchan_eval->scaleIn;
+ curbone->scaleOut += pchan_eval->scaleOut;
+
+ /* reset pose values */
pchan->curveInX = pchan->curveOutX = 0.0f;
pchan->curveInY = pchan->curveOutY = 0.0f;
pchan->roll1 = pchan->roll2 = 0.0f;
@@ -190,13 +200,14 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
ED_armature_edit_free(arm);
/* flush positions of posebones */
- BKE_pose_where_is(scene, ob);
+ BKE_pose_where_is(depsgraph, scene, ob);
/* fix parenting of objects which are bone-parented */
- applyarmature_fix_boneparents(bmain, scene, ob);
+ applyarmature_fix_boneparents(C, scene, ob);
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
return OPERATOR_FINISHED;
}
@@ -220,38 +231,41 @@ void POSE_OT_armature_apply(wmOperatorType *ot)
/* set the current pose as the restpose */
static int pose_visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); // must be active object, not edit-object
-
- /* don't check if editmode (should be done by caller) */
- if (ob->type != OB_ARMATURE)
- return OPERATOR_CANCELLED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
- /* loop over all selected pchans
- *
- * TODO, loop over children before parents if multiple bones
- * at once are to be predictable*/
- CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pose_bones)
+ FOREACH_OBJECT_IN_MODE_BEGIN(view_layer, OB_MODE_POSE, ob)
{
- float delta_mat[4][4];
-
- /* 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, pchan->pose_mat, delta_mat);
+ /* loop over all selected pchans
+ *
+ * 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];
+
+ /* 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);
- BKE_pchan_apply_mat4(pchan, delta_mat, true);
- }
- CTX_DATA_END;
+ BKE_pchan_apply_mat4(pchan, delta_mat, true);
+ }
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ }
+ FOREACH_OBJECT_IN_MODE_END;
return OPERATOR_FINISHED;
}
@@ -502,7 +516,6 @@ void POSE_OT_copy(wmOperatorType *ot)
static int pose_paste_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
Scene *scene = CTX_data_scene(C);
bPoseChannel *chan;
@@ -567,11 +580,11 @@ static int pose_paste_exec(bContext *C, wmOperator *op)
BKE_main_free(tmp_bmain);
/* Update event for pose and deformation children. */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
/* Recalculate paths if any of the bones have paths... */
if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) {
- ED_pose_recalculate_paths(bmain, scene, ob);
+ ED_pose_recalculate_paths(C, scene, ob);
}
/* Notifiers for updates, */
@@ -755,10 +768,8 @@ static void pchan_clear_transforms(bPoseChannel *pchan)
static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op,
void (*clear_func)(bPoseChannel *), const char default_ksName[])
{
- Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- short autokey = 0;
+ bool changed_multi = false;
/* sanity checks */
if (ELEM(NULL, clear_func, default_ksName)) {
@@ -767,47 +778,70 @@ static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op,
}
/* only clear relevant transforms for selected bones */
- CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pose_bones)
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, OB_MODE_POSE, ob_iter)
{
- /* run provided clearing function */
- clear_func(pchan);
+ Object *ob_eval = DEG_get_evaluated_object(CTX_data_depsgraph(C), ob_iter); // XXX: UGLY HACK (for autokey + clear transforms)
+ ListBase dsources = {NULL, NULL};
+ bool changed = false;
- /* do auto-keyframing as appropriate */
- if (autokeyframe_cfra_can_key(scene, &ob->id)) {
- /* clear any unkeyed tags */
- if (pchan->bone)
- pchan->bone->flag &= ~BONE_UNKEYED;
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob_iter, pchan)
+ {
+ /* run provided clearing function */
+ clear_func(pchan);
+ changed = true;
+
+ /* do auto-keyframing as appropriate */
+ if (autokeyframe_cfra_can_key(scene, &ob_iter->id)) {
+ /* clear any unkeyed tags */
+ if (pchan->bone) {
+ pchan->bone->flag &= ~BONE_UNKEYED;
+ }
+ /* tag for autokeying later */
+ ANIM_relative_keyingset_add_source(&dsources, &ob_iter->id, &RNA_PoseBone, pchan);
- /* tag for autokeying later */
- autokey = 1;
- }
- else {
- /* add unkeyed tags */
- if (pchan->bone)
- pchan->bone->flag |= BONE_UNKEYED;
+#if 1 /* XXX: Ugly Hack - Run clearing function on evaluated copy of pchan */
+ bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
+ clear_func(pchan_eval);
+#endif
+ }
+ else {
+ /* add unkeyed tags */
+ if (pchan->bone) {
+ pchan->bone->flag |= BONE_UNKEYED;
+ }
+ }
}
- }
- CTX_DATA_END;
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
- /* perform autokeying on the bones if needed */
- if (autokey) {
- /* get KeyingSet to use */
- KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, default_ksName);
+ if (changed) {
+ changed_multi = true;
- /* insert keyframes */
- ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+ /* perform autokeying on the bones if needed */
+ if (!BLI_listbase_is_empty(&dsources)) {
+ /* get KeyingSet to use */
+ KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, default_ksName);
- /* now recalculate paths */
- if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS))
- ED_pose_recalculate_paths(bmain, scene, ob);
- }
+ /* insert keyframes */
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ /* now recalculate paths */
+ if ((ob_iter->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) {
+ ED_pose_recalculate_paths(C, scene, ob_iter);
+ }
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
+ BLI_freelistN(&dsources);
+ }
- return OPERATOR_FINISHED;
+ DEG_id_tag_update(&ob_iter->id, OB_RECALC_DATA);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob_iter);
+ }
+ }
+ FOREACH_OBJECT_IN_MODE_END;
+
+ return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
/* --------------- */
@@ -900,57 +934,61 @@ void POSE_OT_transforms_clear(wmOperatorType *ot)
static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op)
{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Scene *scene = CTX_data_scene(C);
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
float cframe = (float)CFRA;
const bool only_select = RNA_boolean_get(op->ptr, "only_selected");
- if ((ob->adt) && (ob->adt->action)) {
- /* XXX: this is just like this to avoid contaminating anything else;
- * just pose values should change, so this should be fine
- */
- bPose *dummyPose = NULL;
- Object workob = {{NULL}};
- bPoseChannel *pchan;
+ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, OB_MODE_POSE, ob)
+ {
+ if ((ob->adt) && (ob->adt->action)) {
+ /* XXX: this is just like this to avoid contaminating anything else;
+ * just pose values should change, so this should be fine
+ */
+ bPose *dummyPose = NULL;
+ Object workob = {{NULL}};
+ bPoseChannel *pchan;
- /* execute animation step for current frame using a dummy copy of the pose */
- BKE_pose_copy_data(&dummyPose, ob->pose, 0);
+ /* execute animation step for current frame using a dummy copy of the pose */
+ BKE_pose_copy_data(&dummyPose, ob->pose, 0);
- BLI_strncpy(workob.id.name, "OB<ClearTfmWorkOb>", sizeof(workob.id.name));
- workob.type = OB_ARMATURE;
- workob.data = ob->data;
- workob.adt = ob->adt;
- workob.pose = dummyPose;
+ BLI_strncpy(workob.id.name, "OB<ClearTfmWorkOb>", sizeof(workob.id.name));
+ workob.type = OB_ARMATURE;
+ workob.data = ob->data;
+ workob.adt = ob->adt;
+ workob.pose = dummyPose;
- BKE_animsys_evaluate_animdata(scene, &workob.id, workob.adt, cframe, ADT_RECALC_ANIM);
+ BKE_animsys_evaluate_animdata(NULL, scene, &workob.id, workob.adt, cframe, ADT_RECALC_ANIM);
- /* copy back values, but on selected bones only */
- for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
- pose_bone_do_paste(ob, pchan, only_select, 0);
- }
+ /* copy back values, but on selected bones only */
+ for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
+ pose_bone_do_paste(ob, pchan, only_select, 0);
+ }
- /* free temp data - free manually as was copied without constraints */
- for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->prop) {
- IDP_FreeProperty(pchan->prop);
- MEM_freeN(pchan->prop);
+ /* free temp data - free manually as was copied without constraints */
+ for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->prop) {
+ IDP_FreeProperty(pchan->prop);
+ MEM_freeN(pchan->prop);
+ }
}
+
+ /* was copied without constraints */
+ BLI_freelistN(&dummyPose->chanbase);
+ MEM_freeN(dummyPose);
+ }
+ else {
+ /* no animation, so just reset whole pose to rest pose
+ * (cannot just restore for selected though)
+ */
+ BKE_pose_rest(ob->pose);
}
- /* was copied without constraints */
- BLI_freelistN(&dummyPose->chanbase);
- MEM_freeN(dummyPose);
+ /* notifiers and updates */
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
}
- else {
- /* no animation, so just reset whole pose to rest pose
- * (cannot just restore for selected though)
- */
- BKE_pose_rest(ob->pose);
- }
-
- /* notifiers and updates */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
+ FOREACH_OBJECT_IN_MODE_END;
return OPERATOR_FINISHED;
}