diff options
-rw-r--r-- | source/blender/blenkernel/BKE_anim.h | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/anim.c | 71 | ||||
-rw-r--r-- | source/blender/editors/armature/pose_edit.c | 24 | ||||
-rw-r--r-- | source/blender/editors/armature/pose_transform.c | 4 | ||||
-rw-r--r-- | source/blender/editors/armature/pose_utils.c | 2 | ||||
-rw-r--r-- | source/blender/editors/include/ED_armature.h | 2 | ||||
-rw-r--r-- | source/blender/editors/include/ED_object.h | 2 | ||||
-rw-r--r-- | source/blender/editors/object/object_edit.c | 30 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 17 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_generics.c | 15 |
10 files changed, 114 insertions, 56 deletions
diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h index 91f936c6eca..0d8a50c5325 100644 --- a/source/blender/blenkernel/BKE_anim.h +++ b/source/blender/blenkernel/BKE_anim.h @@ -61,7 +61,8 @@ void animviz_calc_motionpaths(struct Depsgraph *depsgraph, struct Main *bmain, struct Scene *scene, ListBase *targets, - bool restore); + bool restore, + bool current_frame_only); /* ---------------------------------------------------- */ /* Curve Paths */ diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 02f871e6ccf..deafe631290 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -347,7 +347,6 @@ static void motionpaths_calc_bake_targets(ListBase *targets, int cframe) /* for each target, check if it can be baked on the current frame */ for (mpt = targets->first; mpt; mpt = mpt->next) { bMotionPath *mpath = mpt->mpath; - bMotionPathVert *mpv; /* current frame must be within the range the cache works for * - is inclusive of the first frame, but not the last otherwise we get buffer overruns @@ -357,7 +356,7 @@ static void motionpaths_calc_bake_targets(ListBase *targets, int cframe) } /* get the relevant cache vert to write to */ - mpv = mpath->points + (cframe - mpath->start_frame); + bMotionPathVert *mpv = mpath->points + (cframe - mpath->start_frame); Object *ob_eval = mpt->ob_eval; @@ -392,6 +391,25 @@ static void motionpaths_calc_bake_targets(ListBase *targets, int cframe) if (BLI_dlrbTree_search_exact(&mpt->keys, compare_ak_cfraPtr, &mframe)) { mpv->flag |= MOTIONPATH_VERT_KEY; } + + /* Incremental update on evaluated object if possible, for fast updating + * while dragging in transform. */ + bMotionPath *mpath_eval = NULL; + if (mpt->pchan) { + mpath_eval = (pchan_eval) ? pchan_eval->mpath : NULL; + } + else { + mpath_eval = ob_eval->mpath; + } + + if (mpath_eval && mpath_eval->length == mpath->length) { + bMotionPathVert *mpv_eval = mpath_eval->points + (cframe - mpath_eval->start_frame); + *mpv_eval = *mpv; + + GPU_VERTBUF_DISCARD_SAFE(mpath_eval->points_vbo); + GPU_BATCH_DISCARD_SAFE(mpath_eval->batch_line); + GPU_BATCH_DISCARD_SAFE(mpath_eval->batch_points); + } } } @@ -405,36 +423,45 @@ void animviz_calc_motionpaths(Depsgraph *depsgraph, Main *bmain, Scene *scene, ListBase *targets, - bool restore) + bool restore, + bool current_frame_only) { - MPathTarget *mpt; - int sfra, efra; - int cfra; - /* sanity check */ if (ELEM(NULL, targets, targets->first)) return; - /* set frame values */ - cfra = CFRA; - sfra = efra = cfra; - - /* TODO: this method could be improved... + /* Compute frame range to bake within. + * TODO: this method could be improved... * 1) max range for standard baking * 2) minimum range for recalc baking (i.e. between keyframes, but how?) */ - for (mpt = targets->first; mpt; mpt = mpt->next) { + int sfra = INT_MAX; + int efra = INT_MIN; + + for (MPathTarget *mpt = targets->first; mpt; mpt = mpt->next) { /* try to increase area to do (only as much as needed) */ sfra = MIN2(sfra, mpt->mpath->start_frame); efra = MAX2(efra, mpt->mpath->end_frame); } - if (efra <= sfra) return; + if (efra <= sfra) { + return; + } + + /* Limit frame range if we are updating just the current frame. */ + /* set frame values */ + int cfra = CFRA; + if (current_frame_only) { + if (cfra < sfra || cfra > efra) { + return; + } + sfra = efra = cfra; + } /* get copies of objects/bones to get the calculated results from * (for copy-on-write evaluation), so that we actually get some results */ // TODO: Create a copy of background depsgraph that only contain these entities, and only evaluates them.. - for (mpt = targets->first; mpt; mpt = mpt->next) { + for (MPathTarget *mpt = targets->first; mpt; mpt = mpt->next) { mpt->ob_eval = DEG_get_evaluated_object(depsgraph, mpt->ob); AnimData *adt = BKE_animdata_from_id(&mpt->ob_eval->id); @@ -472,8 +499,14 @@ void animviz_calc_motionpaths(Depsgraph *depsgraph, /* calculate path over requested range */ printf("Calculating MotionPaths between frames %d - %d (%d frames)\n", sfra, efra, efra - sfra + 1); for (CFRA = sfra; CFRA <= efra; CFRA++) { - /* update relevant data for new frame */ - motionpaths_calc_update_scene(bmain, depsgraph); + if (current_frame_only) { + /* For current frame, only update tagged. */ + BKE_scene_graph_update_tagged(depsgraph, bmain); + } + else { + /* Update relevant data for new frame. */ + motionpaths_calc_update_scene(bmain, depsgraph); + } /* perform baking for targets */ motionpaths_calc_bake_targets(targets, CFRA); @@ -484,12 +517,12 @@ void animviz_calc_motionpaths(Depsgraph *depsgraph, * may be a temporary one that works on a subset of the data. We always have * to resoture the current frame though. */ CFRA = cfra; - if (restore) { + if (!current_frame_only && restore) { motionpaths_calc_update_scene(bmain, depsgraph); } /* clear recalc flags from targets */ - for (mpt = targets->first; mpt; mpt = mpt->next) { + for (MPathTarget *mpt = targets->first; mpt; mpt = mpt->next) { bAnimVizSettings *avs; bMotionPath *mpath = mpt->mpath; diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c index d0ca809f196..15b8c3eb8de 100644 --- a/source/blender/editors/armature/pose_edit.c +++ b/source/blender/editors/armature/pose_edit.c @@ -193,15 +193,20 @@ 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(bContext *C, Scene *scene, Object *ob) +void ED_pose_recalculate_paths(bContext *C, Scene *scene, Object *ob, bool current_frame_only) { - struct Main *bmain = CTX_data_main(C); + /* Transform doesn't always have context avaialble to do update. */ + if (C == NULL) { + return; + } + + Main *bmain = CTX_data_main(C); Depsgraph *depsgraph = CTX_data_depsgraph(C); ListBase targets = {NULL, NULL}; bool free_depsgraph = false; /* Override depsgraph with a filtered, simpler copy */ - if (G.debug_value != -1) { + if (!current_frame_only && G.debug_value != -1) { TIMEIT_START(filter_pose_depsgraph); DEG_FilterQuery query = {0}; @@ -226,13 +231,16 @@ void ED_pose_recalculate_paths(bContext *C, Scene *scene, Object *ob) /* recalculate paths, then free */ TIMEIT_START(pose_path_calc); - animviz_calc_motionpaths(depsgraph, bmain, scene, &targets, false); + animviz_calc_motionpaths(depsgraph, bmain, scene, &targets, !free_depsgraph, current_frame_only); TIMEIT_END(pose_path_calc); 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); + if (!current_frame_only) { + /* Tag armature object for copy on write - so paths will draw/redraw. + * For currently frame only we update evaluated object directly. */ + DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE); + } /* Free temporary depsgraph instance */ if (free_depsgraph) { @@ -303,7 +311,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(C, scene, ob); + ED_pose_recalculate_paths(C, scene, ob, false); #ifdef DEBUG_TIME TIMEIT_END(recalc_pose_paths); @@ -364,7 +372,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(C, scene, ob); + ED_pose_recalculate_paths(C, scene, ob, false); /* notifiers for updates */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index 22c710dcda5..b492cfacddb 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -584,7 +584,7 @@ static int pose_paste_exec(bContext *C, wmOperator *op) /* Recalculate paths if any of the bones have paths... */ if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) { - ED_pose_recalculate_paths(C, scene, ob); + ED_pose_recalculate_paths(C, scene, ob, false); } /* Notifiers for updates, */ @@ -827,7 +827,7 @@ static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op, /* now recalculate paths */ if ((ob_iter->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) { - ED_pose_recalculate_paths(C, scene, ob_iter); + ED_pose_recalculate_paths(C, scene, ob_iter, false); } BLI_freelistN(&dsources); diff --git a/source/blender/editors/armature/pose_utils.c b/source/blender/editors/armature/pose_utils.c index e280284a9ce..8b0a60c0f97 100644 --- a/source/blender/editors/armature/pose_utils.c +++ b/source/blender/editors/armature/pose_utils.c @@ -269,7 +269,7 @@ void poseAnim_mapping_autoKeyframe(bContext *C, Scene *scene, Object *ob, ListBa */ if (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); + ED_pose_recalculate_paths(C, scene, ob, false); } } } diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index 5c193392052..3044543795c 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -225,7 +225,7 @@ bool ED_pose_deselect_all(struct Object *ob, int select_mode, const bool ignore_ void ED_pose_deselect_all_multi(struct Object **objects, uint objects_len, int select_mode, const bool ignore_visibility); void ED_pose_bone_select_tag_update(struct Object *ob); void ED_pose_bone_select(struct Object *ob, struct bPoseChannel *pchan, bool select); -void ED_pose_recalculate_paths(struct bContext *C, struct Scene *scene, struct Object *ob); +void ED_pose_recalculate_paths(struct bContext *C, struct Scene *scene, struct Object *ob, bool current_frame_only); struct Object *ED_pose_object_from_context(struct bContext *C); /* meshlaplacian.c */ diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 3fd520810ea..1f58a6508b2 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -196,7 +196,7 @@ void ED_object_single_user(struct Main *bmain, struct Scene *scene, struct Objec /* object motion paths */ void ED_objects_clear_paths(struct bContext *C, bool only_selected); -void ED_objects_recalculate_paths(struct bContext *C, struct Scene *scene); +void ED_objects_recalculate_paths(struct bContext *C, struct Scene *scene, bool current_frame_only); /* constraints */ struct ListBase *get_active_constraints(struct Object *ob); diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index cd572c9e93f..43d287590e6 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -1223,9 +1223,14 @@ void OBJECT_OT_forcefield_toggle(wmOperatorType *ot) * * To be called from various tools that do incremental updates */ -void ED_objects_recalculate_paths(bContext *C, Scene *scene) +void ED_objects_recalculate_paths(bContext *C, Scene *scene, bool current_frame_only) { - struct Main *bmain = CTX_data_main(C); + /* Transform doesn't always have context avaialble to do update. */ + if (C == NULL) { + return; + } + + Main *bmain = CTX_data_main(C); Depsgraph *depsgraph = CTX_data_depsgraph(C); ListBase targets = {NULL, NULL}; @@ -1239,17 +1244,20 @@ void ED_objects_recalculate_paths(bContext *C, Scene *scene) CTX_DATA_END; /* recalculate paths, then free */ - animviz_calc_motionpaths(depsgraph, bmain, scene, &targets, true); + animviz_calc_motionpaths(depsgraph, bmain, scene, &targets, true, current_frame_only); BLI_freelistN(&targets); - /* tag objects for copy on write - so paths will draw/redraw */ - CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects) - { - if (ob->mpath) { - DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE); + if (!current_frame_only) { + /* Tag objects for copy on write - so paths will draw/redraw + * For currently frame only we update evaluated object directly. */ + CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects) + { + if (ob->mpath) { + DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE); + } } + CTX_DATA_END; } - CTX_DATA_END; } @@ -1296,7 +1304,7 @@ static int object_calculate_paths_exec(bContext *C, wmOperator *op) CTX_DATA_END; /* calculate the paths for objects that have them (and are tagged to get refreshed) */ - ED_objects_recalculate_paths(C, scene); + ED_objects_recalculate_paths(C, scene, false); /* notifiers for updates */ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); @@ -1346,7 +1354,7 @@ static int object_update_paths_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; /* calculate the paths for objects that have them (and are tagged to get refreshed) */ - ED_objects_recalculate_paths(C, scene); + ED_objects_recalculate_paths(C, scene, false); /* notifiers for updates */ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 26c853e8d0a..ae3ad145c31 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -6707,9 +6707,6 @@ 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(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) { @@ -6723,14 +6720,20 @@ void special_aftertrans_update(bContext *C, TransInfo *t) else { DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } + + if (t->mode != TFM_DUMMY && motionpath_need_update_pose(t->scene, ob)) { + BLI_gset_insert(motionpath_updates, ob); + } } /* Update motion paths once for all transformed bones in an object. */ GSetIterator gs_iter; GSET_ITER (gs_iter, motionpath_updates) { + bool current_frame_only = canceled; ob = BLI_gsetIterator_getKey(&gs_iter); - ED_pose_recalculate_paths(C, t->scene, ob); + ED_pose_recalculate_paths(C, t->scene, ob, current_frame_only); } + BLI_gset_free(motionpath_updates, NULL); } else if (t->options & CTX_PAINT_CURVE) { /* pass */ @@ -6784,9 +6787,10 @@ void special_aftertrans_update(bContext *C, TransInfo *t) /* Set autokey if necessary */ if (!canceled) { autokeyframe_object(C, t->scene, t->view_layer, ob, t->mode); - motionpath_update |= motionpath_need_update_object(t->scene, ob); } + motionpath_update |= motionpath_need_update_object(t->scene, ob); + /* restore rigid body transform */ if (ob->rigidbody_object && canceled) { float ctime = BKE_scene_frame_get(t->scene); @@ -6797,7 +6801,8 @@ void special_aftertrans_update(bContext *C, TransInfo *t) if (motionpath_update) { /* Update motion paths once for all transformed objects. */ - ED_objects_recalculate_paths(C, t->scene); + bool current_frame_only = canceled; + ED_objects_recalculate_paths(C, t->scene, current_frame_only); } } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 925b4e8dd3e..87ce40546aa 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -955,9 +955,10 @@ static void recalcData_objects(TransInfo *t) animrecord_check_state(t->scene, &ob->id, t->animtimer); 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); - } + } + + if (motionpath_need_update_pose(t->scene, ob)) { + BLI_gset_insert(motionpath_updates, ob); } /* old optimize trick... this enforces to bypass the depgraph */ @@ -975,8 +976,9 @@ static void recalcData_objects(TransInfo *t) 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); + ED_pose_recalculate_paths(t->context, t->scene, ob, true); } + BLI_gset_free(motionpath_updates, NULL); } else if (base && (base->object->mode & OB_MODE_PARTICLE_EDIT) && PE_get_current(t->scene, base->object)) @@ -1013,9 +1015,10 @@ static void recalcData_objects(TransInfo *t) if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) { animrecord_check_state(t->scene, &ob->id, t->animtimer); autokeyframe_object(t->context, t->scene, t->view_layer, ob, t->mode); - motionpath_update |= motionpath_need_update_object(t->scene, ob); } + motionpath_update |= motionpath_need_update_object(t->scene, ob); + /* sets recalc flags fully, instead of flushing existing ones * otherwise proxies don't function correctly */ @@ -1028,7 +1031,7 @@ static void recalcData_objects(TransInfo *t) if (motionpath_update) { /* Update motion paths once for all transformed objects. */ - ED_objects_recalculate_paths(t->context, t->scene); + ED_objects_recalculate_paths(t->context, t->scene, true); } } } |