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_edit.c')
-rw-r--r--source/blender/editors/armature/pose_edit.c224
1 files changed, 129 insertions, 95 deletions
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index 389a8423f23..3ae578279ca 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -31,6 +31,8 @@
* \ingroup edarmature
*/
+#include "MEM_guardedalloc.h"
+
#include "BLI_math.h"
#include "BLI_blenlib.h"
@@ -39,14 +41,17 @@
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
+#include "BKE_action.h"
#include "BKE_anim.h"
#include "BKE_armature.h"
#include "BKE_context.h"
#include "BKE_deform.h"
-#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_report.h"
+#include "BKE_layer.h"
+
+#include "DEG_depsgraph.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -59,6 +64,7 @@
#include "ED_keyframing.h"
#include "ED_screen.h"
#include "ED_object.h"
+#include "ED_view3d.h"
#include "UI_interface.h"
@@ -82,7 +88,7 @@ Object *ED_pose_object_from_context(bContext *C)
}
/* This function is used to process the necessary updates for */
-bool ED_object_posemode_enter_ex(Object *ob)
+bool ED_object_posemode_enter_ex(struct Main *bmain, Object *ob)
{
BLI_assert(!ID_IS_LINKED(ob));
bool ok = false;
@@ -91,6 +97,8 @@ bool ED_object_posemode_enter_ex(Object *ob)
case OB_ARMATURE:
ob->restore_mode = ob->mode;
ob->mode |= OB_MODE_POSE;
+ /* Inform all CoW versions that we changed the mode. */
+ DEG_id_tag_update_ex(bmain, &ob->id, DEG_TAG_COPY_ON_WRITE);
ok = true;
break;
@@ -107,26 +115,31 @@ bool ED_object_posemode_enter(bContext *C, Object *ob)
BKE_report(reports, RPT_WARNING, "Cannot pose libdata");
return false;
}
- bool ok = ED_object_posemode_enter_ex(ob);
+ struct Main *bmain = CTX_data_main(C);
+ bool ok = ED_object_posemode_enter_ex(bmain, ob);
if (ok) {
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_POSE, NULL);
}
return ok;
}
-bool ED_object_posemode_exit_ex(Object *ob)
+bool ED_object_posemode_exit_ex(struct Main *bmain, Object *ob)
{
bool ok = false;
if (ob) {
ob->restore_mode = ob->mode;
ob->mode &= ~OB_MODE_POSE;
+
+ /* Inform all CoW versions that we changed the mode. */
+ DEG_id_tag_update_ex(bmain, &ob->id, DEG_TAG_COPY_ON_WRITE);
ok = true;
}
return ok;
}
bool ED_object_posemode_exit(bContext *C, Object *ob)
{
- bool ok = ED_object_posemode_exit_ex(ob);
+ struct Main *bmain = CTX_data_main(C);
+ bool ok = ED_object_posemode_exit_ex(bmain, ob);
if (ok) {
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
}
@@ -168,8 +181,10 @@ static bool pose_has_protected_selected(Object *ob, short warn)
*
* To be called from various tools that do incremental updates
*/
-void ED_pose_recalculate_paths(Main *bmain, Scene *scene, Object *ob)
+void ED_pose_recalculate_paths(bContext *C, Scene *scene, Object *ob)
{
+ struct Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
ListBase targets = {NULL, NULL};
/* set flag to force recalc, then grab the relevant bones to target */
@@ -177,8 +192,11 @@ void ED_pose_recalculate_paths(Main *bmain, Scene *scene, Object *ob)
animviz_get_object_motionpaths(ob, &targets);
/* recalculate paths, then free */
- animviz_calc_motionpaths(bmain, scene, &targets);
+ animviz_calc_motionpaths(depsgraph, bmain, scene, &targets);
BLI_freelistN(&targets);
+
+ /* tag armature object for copy on write - so paths will draw/redraw */
+ DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
}
@@ -212,7 +230,6 @@ static int pose_calculate_paths_invoke(bContext *C, wmOperator *op, const wmEven
*/
static int pose_calculate_paths_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);
@@ -241,7 +258,7 @@ static int pose_calculate_paths_exec(bContext *C, wmOperator *op)
/* calculate the bones that now have motionpaths... */
/* TODO: only make for the selected bones? */
- ED_pose_recalculate_paths(bmain, scene, ob);
+ ED_pose_recalculate_paths(C, scene, ob);
/* notifiers for updates */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
@@ -270,7 +287,8 @@ void POSE_OT_paths_calculate(wmOperatorType *ot)
RNA_def_int(ot->srna, "end_frame", 250, MINAFRAME, MAXFRAME, "End",
"Last frame to calculate bone paths on", MINFRAME, MAXFRAME / 2.0);
- RNA_def_enum(ot->srna, "bake_location", rna_enum_motionpath_bake_location_items, 0,
+ RNA_def_enum(ot->srna, "bake_location", rna_enum_motionpath_bake_location_items,
+ MOTIONPATH_BAKE_HEADS,
"Bake Location",
"Which point on the bones is used when calculating paths");
}
@@ -289,7 +307,6 @@ static bool pose_update_paths_poll(bContext *C)
static int pose_update_paths_exec(bContext *C, wmOperator *UNUSED(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);
@@ -298,7 +315,7 @@ static int pose_update_paths_exec(bContext *C, wmOperator *UNUSED(op))
/* calculate the bones that now have motionpaths... */
/* TODO: only make for the selected bones? */
- ED_pose_recalculate_paths(bmain, scene, ob);
+ ED_pose_recalculate_paths(C, scene, ob);
/* notifiers for updates */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
@@ -596,7 +613,7 @@ static void pose_copy_menu(Scene *scene)
BKE_pose_tag_recalc(bmain, ob->pose);
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA); // and all its relations
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA); // and all its relations
BIF_undo_push("Copy Pose Attributes");
@@ -608,34 +625,31 @@ static void pose_copy_menu(Scene *scene)
static int pose_flip_names_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- bArmature *arm;
-
- /* paranoia checks */
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
-
+ ViewLayer *view_layer = CTX_data_view_layer(C);
const bool do_strip_numbers = RNA_boolean_get(op->ptr, "do_strip_numbers");
- arm = ob->data;
-
- ListBase bones_names = {NULL};
-
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
+ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, OB_MODE_POSE, ob)
{
- BLI_addtail(&bones_names, BLI_genericNodeN(pchan->name));
- }
- CTX_DATA_END;
+ bArmature *arm = ob->data;
+ ListBase bones_names = {NULL};
- ED_armature_bones_flip_names(bmain, arm, &bones_names, do_strip_numbers);
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob, pchan)
+ {
+ BLI_addtail(&bones_names, BLI_genericNodeN(pchan->name));
+ }
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
- BLI_freelistN(&bones_names);
+ ED_armature_bones_flip_names(bmain, arm, &bones_names, do_strip_numbers);
- /* since we renamed stuff... */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ BLI_freelistN(&bones_names);
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ /* since we renamed stuff... */
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ }
+ FOREACH_OBJECT_IN_MODE_END;
return OPERATOR_FINISHED;
}
@@ -684,7 +698,7 @@ static int pose_autoside_names_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
/* since we renamed stuff... */
- 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);
@@ -733,7 +747,7 @@ static int pose_bone_rotmode_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
/* notifiers and updates */
- DAG_id_tag_update((ID *)ob, OB_RECALC_DATA);
+ DEG_id_tag_update((ID *)ob, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
return OPERATOR_FINISHED;
@@ -813,6 +827,7 @@ static int pose_armature_layers_showall_exec(bContext *C, wmOperator *op)
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
/* done */
return OPERATOR_FINISHED;
@@ -880,6 +895,7 @@ static int armature_layers_exec(bContext *C, wmOperator *op)
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
return OPERATOR_FINISHED;
}
@@ -908,7 +924,7 @@ void ARMATURE_OT_armature_layers(wmOperatorType *ot)
/* Present a popup to get the layers that should be used */
static int pose_bone_layers_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- bool layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
+ bool layers[32] = {0}; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
/* get layers that are active already */
CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
@@ -954,6 +970,7 @@ static int pose_bone_layers_exec(bContext *C, wmOperator *op)
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ DEG_id_tag_update((ID *)ob->data, DEG_TAG_COPY_ON_WRITE);
return OPERATOR_FINISHED;
}
@@ -1009,7 +1026,6 @@ static int armature_bone_layers_invoke(bContext *C, wmOperator *op, const wmEven
static int armature_bone_layers_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_edit_object(C);
- bArmature *arm = (ob) ? ob->data : NULL;
PointerRNA ptr;
bool layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
@@ -1017,7 +1033,7 @@ static int armature_bone_layers_exec(bContext *C, wmOperator *op)
RNA_boolean_get_array(op->ptr, "layers", layers);
/* set layers of pchans based on the values set in the operator props */
- CTX_DATA_BEGIN (C, EditBone *, ebone, selected_editable_bones)
+ CTX_DATA_BEGIN_WITH_ID (C, EditBone *, ebone, selected_editable_bones, bArmature *, arm)
{
/* get pointer for pchan, and write flags this way */
RNA_pointer_create((ID *)arm, &RNA_EditBone, ebone, &ptr);
@@ -1053,55 +1069,54 @@ void ARMATURE_OT_bone_layers(wmOperatorType *ot)
/* ********************************************** */
/* Show/Hide Bones */
-static int hide_selected_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
+static int hide_pose_bone_fn(Object *ob, Bone *bone, void *ptr)
{
bArmature *arm = ob->data;
-
+ const bool hide_select = (bool)GET_INT_FROM_POINTER(ptr);
+ int count = 0;
if (arm->layer & bone->layer) {
- if (bone->flag & BONE_SELECTED) {
+ if (((bone->flag & BONE_SELECTED) != 0) == hide_select) {
bone->flag |= BONE_HIDDEN_P;
+ /* only needed when 'hide_select' is true, but harmless. */
bone->flag &= ~BONE_SELECTED;
- if (arm->act_bone == bone)
- arm->act_bone = NULL;
- }
- }
- return 0;
-}
-
-static int hide_unselected_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
-{
- bArmature *arm = ob->data;
-
- if (arm->layer & bone->layer) {
- /* hrm... typo here? */
- if ((bone->flag & BONE_SELECTED) == 0) {
- bone->flag |= BONE_HIDDEN_P;
- if (arm->act_bone == bone)
+ if (arm->act_bone == bone) {
arm->act_bone = NULL;
+ }
+ count += 1;
}
}
- return 0;
+ return count;
}
/* active object is armature in posemode, poll checked */
static int pose_hide_exec(bContext *C, wmOperator *op)
{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- bArmature *arm = ob->data;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len;
+ Object **objects = BKE_object_pose_array_get_unique(view_layer, &objects_len);
+ bool changed_multi = false;
- if (ob->proxy != NULL) {
- BKE_report(op->reports, RPT_INFO, "Undo of hiding can only be done with Reveal Selected");
- }
+ const int hide_select = !RNA_boolean_get(op->ptr, "unselected");
+ void *hide_select_p = SET_INT_IN_POINTER(hide_select);
- if (RNA_boolean_get(op->ptr, "unselected"))
- bone_looper(ob, arm->bonebase.first, NULL, hide_unselected_pose_bone_cb);
- else
- bone_looper(ob, arm->bonebase.first, NULL, hide_selected_pose_bone_cb);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob_iter = objects[ob_index];
+ bArmature *arm = ob_iter->data;
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ if (ob_iter->proxy != NULL) {
+ BKE_report(op->reports, RPT_INFO, "Undo of hiding can only be done with Reveal Selected");
+ }
- return OPERATOR_FINISHED;
+ bool changed = bone_looper(ob_iter, arm->bonebase.first, hide_select_p, hide_pose_bone_fn) != 0;
+ if (changed) {
+ changed_multi = true;
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob_iter);
+ DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
+ }
+ }
+ MEM_freeN(objects);
+
+ return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void POSE_OT_hide(wmOperatorType *ot)
@@ -1127,32 +1142,44 @@ static int show_pose_bone_cb(Object *ob, Bone *bone, void *data)
const bool select = GET_INT_FROM_POINTER(data);
bArmature *arm = ob->data;
-
+ int count = 0;
if (arm->layer & bone->layer) {
if (bone->flag & BONE_HIDDEN_P) {
if (!(bone->flag & BONE_UNSELECTABLE)) {
SET_FLAG_FROM_TEST(bone->flag, select, BONE_SELECTED);
}
bone->flag &= ~BONE_HIDDEN_P;
+ count += 1;
}
}
- return 0;
+ return count;
}
/* active object is armature in posemode, poll checked */
static int pose_reveal_exec(bContext *C, wmOperator *op)
{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- bArmature *arm = ob->data;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len;
+ Object **objects = BKE_object_pose_array_get_unique(view_layer, &objects_len);
+ bool changed_multi = false;
const bool select = RNA_boolean_get(op->ptr, "select");
+ void *select_p = SET_INT_IN_POINTER(select);
- bone_looper(ob, arm->bonebase.first, SET_INT_IN_POINTER(select), show_pose_bone_cb);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob_iter = objects[ob_index];
+ bArmature *arm = ob_iter->data;
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ bool changed = bone_looper(ob_iter, arm->bonebase.first, select_p, show_pose_bone_cb);
+ if (changed) {
+ changed_multi = true;
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob_iter);
+ DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
+ }
+ }
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void POSE_OT_reveal(wmOperatorType *ot)
@@ -1178,27 +1205,34 @@ void POSE_OT_reveal(wmOperatorType *ot)
static int pose_flip_quats_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID);
- /* loop through all selected pchans, flipping and keying (as needed) */
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
- {
- /* only if bone is using quaternion rotation */
- if (pchan->rotmode == ROT_MODE_QUAT) {
- /* quaternions have 720 degree range */
- negate_v4(pchan->quat);
+ bool changed_multi = false;
- ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
- }
- }
- CTX_DATA_END;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, OB_MODE_POSE, ob_iter) {
+ bool changed = false;
+ /* loop through all selected pchans, flipping and keying (as needed) */
+ FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob_iter, pchan) {
+ /* only if bone is using quaternion rotation */
+ if (pchan->rotmode == ROT_MODE_QUAT) {
+ changed = true;
+ /* quaternions have 720 degree range */
+ negate_v4(pchan->quat);
- /* notifiers and updates */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
+ ED_autokeyframe_pchan(C, scene, ob_iter, pchan, ks);
+ }
+ } FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
- return OPERATOR_FINISHED;
+ if (changed) {
+ changed_multi = true;
+ /* notifiers and updates */
+ DEG_id_tag_update(&ob_iter->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob_iter);
+ }
+ } FOREACH_OBJECT_IN_MODE_END;
+
+ return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void POSE_OT_quaternions_flip(wmOperatorType *ot)