Fix local view toggle setting the view to "User"

Activating local view could set an axis view to "User"
when activated before the previous action had completed.
This commit is contained in:
Campbell Barton
2024-09-10 17:31:04 +10:00
parent 62dbebc18e
commit 9d6ecd0ed6
3 changed files with 105 additions and 13 deletions

View File

@@ -360,6 +360,19 @@ void ED_view3d_smooth_view_undo_end(bContext *C,
*/
void ED_view3d_smooth_view_force_finish(bContext *C, View3D *v3d, ARegion *region);
/**
* A version of #ED_view3d_smooth_view_force_finish
* that doesn't support camera locking or auto-keying.
* Use for viewport actions that don't control the camera,
* entering/exiting the local-view for example (see code-comments for details).
*/
void ED_view3d_smooth_view_force_finish_no_camera_lock(const Depsgraph *depsgraph,
wmWindowManager *wm,
wmWindow *win,
const Scene *scene,
View3D *v3d,
ARegion *region);
void VIEW3D_OT_smoothview(wmOperatorType *ot);
/* view3d_navigate_view_all.cc */

View File

@@ -426,25 +426,27 @@ static void view3d_smoothview_apply_with_interp(
/**
* Apply the view-port transformation & free smooth-view related data.
*/
static void view3d_smoothview_apply_and_finish(bContext *C, View3D *v3d, RegionView3D *rv3d)
static void view3d_smoothview_apply_and_finish_ex(wmWindowManager *wm,
wmWindow *win,
View3D *v3d,
RegionView3D *rv3d,
bContext *C_for_camera_lock)
{
wmWindowManager *wm = CTX_wm_manager(C);
SmoothView3DStore *sms = rv3d->sms;
wmWindow *win = CTX_wm_window(C);
/* if we went to camera, store the original */
if (sms->to_camera) {
rv3d->persp = RV3D_CAMOB;
view3d_smooth_view_state_restore(&sms->org, v3d, rv3d);
}
else {
const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
view3d_smooth_view_state_restore(&sms->dst, v3d, rv3d);
if (ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d)) {
ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true);
if (C_for_camera_lock) {
const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C_for_camera_lock);
if (ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d)) {
ED_view3d_camera_lock_autokey(v3d, rv3d, C_for_camera_lock, true, true);
}
}
}
@@ -467,7 +469,14 @@ static void view3d_smoothview_apply_and_finish(bContext *C, View3D *v3d, RegionV
*
* For now only redraw all regions when smooth-view finishes.
*/
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, v3d);
}
static void view3d_smoothview_apply_and_finish(bContext *C, View3D *v3d, RegionView3D *rv3d)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
view3d_smoothview_apply_and_finish_ex(wm, win, v3d, rv3d, C);
}
/* only meant for timer usage */
@@ -518,17 +527,64 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator * /*op*/, const wmEv
return OPERATOR_FINISHED;
}
static void view3d_smooth_view_force_finish_ex(const Depsgraph *depsgraph,
wmWindowManager *wm,
wmWindow *win,
const Scene *scene,
View3D *v3d,
ARegion *region,
bContext *C_for_camera_lock)
{
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
BLI_assert(rv3d && rv3d->sms);
view3d_smoothview_apply_and_finish_ex(wm, win, v3d, rv3d, C_for_camera_lock);
if (depsgraph) {
/* Force update of view matrix so tools that run immediately after
* can use them without redrawing first. */
ED_view3d_update_viewmat(depsgraph, scene, v3d, region, nullptr, nullptr, nullptr, false);
}
}
void ED_view3d_smooth_view_force_finish(bContext *C, View3D *v3d, ARegion *region)
{
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
if (rv3d && rv3d->sms) {
view3d_smoothview_apply_and_finish(C, v3d, rv3d);
/* Force update of view matrix so tools that run immediately after
* can use them without redrawing first */
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Scene *scene = CTX_data_scene(C);
ED_view3d_update_viewmat(depsgraph, scene, v3d, region, nullptr, nullptr, nullptr, false);
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
view3d_smooth_view_force_finish_ex(depsgraph, wm, win, scene, v3d, region, C);
}
}
void ED_view3d_smooth_view_force_finish_no_camera_lock(const Depsgraph *depsgraph,
wmWindowManager *wm,
wmWindow *win,
const Scene *scene,
View3D *v3d,
ARegion *region)
{
/* NOTE(@ideasman42): Ideally we would *always* apply the camera lock.
* Failing to do so results in incorrect behavior when a user performs
* a camera-locked view-port manipulation & immediately enters enters local-view
* before the operation is completed.
* In this case the camera isn't key-framed when it should be.
*
* A generic solution that supports forcing modal operators to finish their
* work may be best, but needs to be investigated.
*
* It's worth noting this *is* a corner case, while not ideal,
* rarely happens unless a motivated users is trying to cause it to fail.
* Even when it does occur, it simply misses completing & auto-keying the action. */
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
if (rv3d && rv3d->sms) {
view3d_smooth_view_force_finish_ex(depsgraph, wm, win, scene, v3d, region, nullptr);
}
}

View File

@@ -873,6 +873,16 @@ static bool view3d_localview_init(const Depsgraph *depsgraph,
return false;
}
/* Apply any running smooth-view values before reading from the viewport. */
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
if (region->regiontype == RGN_TYPE_WINDOW) {
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
if (rv3d->sms) {
ED_view3d_smooth_view_force_finish_no_camera_lock(depsgraph, wm, win, scene, v3d, region);
}
}
}
v3d->localvd = static_cast<View3D *>(MEM_mallocN(sizeof(View3D), "localview"));
*v3d->localvd = blender::dna::shallow_copy(*v3d);
v3d->local_view_uid = local_view_bit;
@@ -955,6 +965,19 @@ static void view3d_localview_exit(const Depsgraph *depsgraph,
}
}
/* Apply any running smooth-view values before reading from the viewport. */
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
if (region->regiontype == RGN_TYPE_WINDOW) {
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
if (rv3d->localvd == nullptr) {
continue;
}
if (rv3d->sms) {
ED_view3d_smooth_view_force_finish_no_camera_lock(depsgraph, wm, win, scene, v3d, region);
}
}
}
Object *camera_old = v3d->camera;
Object *camera_new = v3d->localvd->camera;