From fe6a6dee0bd91c59c774e2feb8886a8a4b4f0806 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 14 Sep 2018 13:59:58 +0200 Subject: Motion Paths: only update once when transforming multiple bones or objects. --- source/blender/editors/transform/transform.h | 10 ++- .../editors/transform/transform_conversions.c | 83 +++++++++++++--------- .../blender/editors/transform/transform_generics.c | 26 +++++-- 3 files changed, 79 insertions(+), 40 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 20512a18ae3..3b19618405a 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -730,12 +730,16 @@ bool transdata_check_local_islands(TransInfo *t, short around); int count_set_pose_transflags(struct Object *ob, const int mode, const short around, bool has_translate_rotate[2]); -/* auto-keying stuff used by special_aftertrans_update */ -void autokeyframe_ob_cb_func( +/* Auto-keyframe applied after transform, returns true if motion paths need to be updated. */ +void autokeyframe_object( struct bContext *C, struct Scene *scene, struct ViewLayer *view_layer, struct Object *ob, int tmode); -void autokeyframe_pose_cb_func( +void autokeyframe_pose( struct bContext *C, struct Scene *scene, struct Object *ob, int tmode, short targetless_ik); +/* Test if we need to update motion paths for a given object. */ +bool motionpath_need_update_object(struct Scene *scene, struct Object *ob); +bool motionpath_need_update_pose(struct Scene *scene, struct Object *ob); + /*********************** Constraints *****************************/ void drawConstraint(TransInfo *t); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 244f6f061af..26c853e8d0a 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5916,7 +5916,7 @@ static void clear_trans_object_base_flags(TransInfo *t) * tmode: should be a transform mode */ // NOTE: context may not always be available, so must check before using it as it's a luxury for a few cases -void autokeyframe_ob_cb_func(bContext *C, Scene *scene, ViewLayer *view_layer, Object *ob, int tmode) +void autokeyframe_object(bContext *C, Scene *scene, ViewLayer *view_layer, Object *ob, int tmode) { Main *bmain = CTX_data_main(C); ID *id = &ob->id; @@ -6012,33 +6012,33 @@ void autokeyframe_ob_cb_func(bContext *C, Scene *scene, ViewLayer *view_layer, O ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); } - /* only calculate paths if there are paths to be recalculated, - * assuming that since we've autokeyed the transforms this is - * now safe to apply... - * - * NOTE: only do this when there's context info - */ - if (C && (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) { - //ED_objects_clear_paths(C); // XXX for now, don't need to clear - ED_objects_recalculate_paths(C, scene); - - /* XXX: there's potential here for problems with unkeyed rotations/scale, - * but for now (until proper data-locality for baking operations), - * this should be a better fix for T24451 and T37755 - */ - } - /* free temp info */ BLI_freelistN(&dsources); } } +/* Return if we need to update motion paths, only if they already exist, + * and we will insert a keyframe at the end of transform. */ +bool motionpath_need_update_object(Scene *scene, Object *ob) +{ + /* XXX: there's potential here for problems with unkeyed rotations/scale, + * but for now (until proper data-locality for baking operations), + * this should be a better fix for T24451 and T37755 + */ + + if (autokeyframe_cfra_can_key(scene, &ob->id)) { + return (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0; + } + + return false; +} + /* auto-keyframing feature - for poses/pose-channels * tmode: should be a transform mode * targetless_ik: has targetless ik been done on any channels? */ // NOTE: context may not always be available, so must check before using it as it's a luxury for a few cases -void autokeyframe_pose_cb_func(bContext *C, Scene *scene, Object *ob, int tmode, short targetless_ik) +void autokeyframe_pose(bContext *C, Scene *scene, Object *ob, int tmode, short targetless_ik) { Main *bmain = CTX_data_main(C); ID *id = &ob->id; @@ -6158,16 +6158,6 @@ void autokeyframe_pose_cb_func(bContext *C, Scene *scene, Object *ob, int tmode, BLI_freelistN(&dsources); } } - - /* do the bone paths - * - only do this when there is context info, since we need that to resolve - * how to do the updates and so on... - * - do not calculate unless there are paths already to update... - */ - if (C && (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) { - //ED_pose_clear_paths(C, ob); // XXX for now, don't need to clear - ED_pose_recalculate_paths(C, scene, ob); - } } else { /* tag channels that should have unkeyed data */ @@ -6180,6 +6170,17 @@ void autokeyframe_pose_cb_func(bContext *C, Scene *scene, Object *ob, int tmode, } } +/* Return if we need to update motion paths, only if they already exist, + * and we will insert a keyframe at the end of transform. */ +bool motionpath_need_update_pose(Scene *scene, Object *ob) +{ + if (autokeyframe_cfra_can_key(scene, &ob->id)) { + return (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0; + } + + return false; +} + static void special_aftertrans_update__movieclip(bContext *C, TransInfo *t) { SpaceClip *sc = t->sa->spacedata.first; @@ -6665,6 +6666,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t) } } else if (t->flag & T_POSE) { + GSet *motionpath_updates = BLI_gset_ptr_new("motionpath updates"); FOREACH_TRANS_DATA_CONTAINER (t, tc) { @@ -6704,7 +6706,10 @@ void special_aftertrans_update(bContext *C, TransInfo *t) /* automatic inserting of keys and unkeyed tagging - only if transform wasn't canceled (or TFM_DUMMY) */ if (!canceled && (t->mode != TFM_DUMMY)) { - autokeyframe_pose_cb_func(C, t->scene, ob, t->mode, targetless_ik); + autokeyframe_pose(C, t->scene, ob, t->mode, targetless_ik); + if (motionpath_need_update_pose(t->scene, ob)) { + BLI_gset_insert(motionpath_updates, ob); + } DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } else if (arm->flag & ARM_DELAYDEFORM) { @@ -6719,6 +6724,13 @@ void special_aftertrans_update(bContext *C, TransInfo *t) DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } } + + /* Update motion paths once for all transformed bones in an object. */ + GSetIterator gs_iter; + GSET_ITER (gs_iter, motionpath_updates) { + ob = BLI_gsetIterator_getKey(&gs_iter); + ED_pose_recalculate_paths(C, t->scene, ob); + } } else if (t->options & CTX_PAINT_CURVE) { /* pass */ @@ -6734,13 +6746,12 @@ void special_aftertrans_update(bContext *C, TransInfo *t) /* do nothing */ } else { /* Objects */ - int i; - BLI_assert(t->flag & (T_OBJECT | T_TEXTURE)); TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); + bool motionpath_update = false; - for (i = 0; i < tc->data_len; i++) { + for (int i = 0; i < tc->data_len; i++) { TransData *td = tc->data + i; ListBase pidlist; PTCacheID *pid; @@ -6772,7 +6783,8 @@ void special_aftertrans_update(bContext *C, TransInfo *t) /* Set autokey if necessary */ if (!canceled) { - autokeyframe_ob_cb_func(C, t->scene, t->view_layer, ob, t->mode); + autokeyframe_object(C, t->scene, t->view_layer, ob, t->mode); + motionpath_update |= motionpath_need_update_object(t->scene, ob); } /* restore rigid body transform */ @@ -6782,6 +6794,11 @@ void special_aftertrans_update(bContext *C, TransInfo *t) BKE_rigidbody_aftertrans_update(ob, td->ext->oloc, td->ext->orot, td->ext->oquat, td->ext->orotAxis, td->ext->orotAngle); } } + + if (motionpath_update) { + /* Update motion paths once for all transformed objects. */ + ED_objects_recalculate_paths(C, t->scene); + } } clear_trans_object_base_flags(t); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index a2377166dff..925b4e8dd3e 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -937,6 +937,8 @@ static void recalcData_objects(TransInfo *t) } else if (t->flag & T_POSE) { + GSet *motionpath_updates = BLI_gset_ptr_new("motionpath updates"); + FOREACH_TRANS_DATA_CONTAINER (t, tc) { Object *ob = tc->poseobj; bArmature *arm = ob->data; @@ -952,7 +954,10 @@ static void recalcData_objects(TransInfo *t) int targetless_ik = (t->flag & T_AUTOIK); // XXX this currently doesn't work, since flags aren't set yet! animrecord_check_state(t->scene, &ob->id, t->animtimer); - autokeyframe_pose_cb_func(t->context, t->scene, ob, t->mode, targetless_ik); + autokeyframe_pose(t->context, t->scene, ob, t->mode, targetless_ik); + if (motionpath_need_update_pose(t->scene, ob)) { + BLI_gset_insert(motionpath_updates, ob); + } } /* old optimize trick... this enforces to bypass the depgraph */ @@ -965,6 +970,13 @@ static void recalcData_objects(TransInfo *t) BKE_pose_where_is(t->depsgraph, t->scene, ob); } } + + /* Update motion paths once for all transformed bones in an object. */ + GSetIterator gs_iter; + GSET_ITER (gs_iter, motionpath_updates) { + Object *ob = BLI_gsetIterator_getKey(&gs_iter); + ED_pose_recalculate_paths(t->context, t->scene, ob); + } } else if (base && (base->object->mode & OB_MODE_PARTICLE_EDIT) && PE_get_current(t->scene, base->object)) @@ -975,7 +987,7 @@ static void recalcData_objects(TransInfo *t) flushTransParticles(t); } else { - int i; + bool motionpath_update = false; if (t->state != TRANS_CANCEL) { applyProject(t); @@ -984,7 +996,7 @@ static void recalcData_objects(TransInfo *t) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { + for (int i = 0; i < tc->data_len; i++, td++) { Object *ob = td->ob; if (td->flag & TD_NOACTION) @@ -1000,7 +1012,8 @@ static void recalcData_objects(TransInfo *t) // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes? if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) { animrecord_check_state(t->scene, &ob->id, t->animtimer); - autokeyframe_ob_cb_func(t->context, t->scene, t->view_layer, ob, t->mode); + autokeyframe_object(t->context, t->scene, t->view_layer, ob, t->mode); + motionpath_update |= motionpath_need_update_object(t->scene, ob); } /* sets recalc flags fully, instead of flushing existing ones @@ -1012,6 +1025,11 @@ static void recalcData_objects(TransInfo *t) DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } } + + if (motionpath_update) { + /* Update motion paths once for all transformed objects. */ + ED_objects_recalculate_paths(t->context, t->scene); + } } } -- cgit v1.2.3