Fix #145525: Scene switch should not affect viewport perspective mode

The existing behaviour traces back from pre-2.5 era. It seems like a
general sanitization technique for any operator which may change the
view transformation.

While it still makes sense to switch to PERSPECTIVE mode when actively
calling a view operator, I don't think the same should be said by simply
switching the active scene.

This PR makes it so a temporary flag is set when switching to a scene that
has no camera. This flag is kept around until we deliberately change
perspective mode. We can eventually make it so the flag is reset again in
more occasions. But the patch is good as it is.

Ref: !146364
This commit is contained in:
Dalai Felinto
2025-09-23 18:53:20 +02:00
parent ec4db5825d
commit e8deba14c3
4 changed files with 30 additions and 20 deletions

View File

@@ -1453,33 +1453,41 @@ static void screen_set_3dview_camera(Scene *scene,
ScrArea *area,
View3D *v3d)
{
/* fix any cameras that are used in the 3d view but not in the scene */
/* Fix any cameras that are used in the 3d view but not in the scene. */
BKE_screen_view3d_sync(v3d, scene);
BKE_view_layer_synced_ensure(scene, view_layer);
if (!v3d->camera || !BKE_view_layer_base_find(view_layer, v3d->camera)) {
v3d->camera = BKE_view_layer_camera_find(scene, view_layer);
// XXX if (screen == curscreen) handle_view3d_lock();
}
ListBase *regionbase;
/* regionbase is in different place depending if space is active. */
if (v3d == area->spacedata.first) {
regionbase = &area->regionbase;
}
else {
regionbase = &v3d->regionbase;
}
LISTBASE_FOREACH (ARegion *, region, regionbase) {
if (region->regiontype != RGN_TYPE_WINDOW) {
continue;
}
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
/* Keep the information about RV3D_CAMOB even when no camera can be found.
* This prevents jumping off the camera view while scrubbing through the
* Sequencer with some Scene strips without scene. */
if (!v3d->camera) {
ListBase *regionbase;
/* regionbase is in different place depending if space is active */
if (v3d == area->spacedata.first) {
regionbase = &area->regionbase;
}
else {
regionbase = &v3d->regionbase;
}
LISTBASE_FOREACH (ARegion *, region, regionbase) {
if (region->regiontype == RGN_TYPE_WINDOW) {
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
if (rv3d->persp == RV3D_CAMOB) {
rv3d->persp = RV3D_PERSP;
}
}
if (rv3d->persp == RV3D_CAMOB) {
rv3d->persp = RV3D_PERSP;
rv3d->rflag |= RV3D_WAS_CAMOB;
}
}
else if ((rv3d->rflag & RV3D_WAS_CAMOB) != 0) {
rv3d->persp = RV3D_CAMOB;
rv3d->rflag &= ~RV3D_WAS_CAMOB;
}
}
}

View File

@@ -5020,6 +5020,7 @@ static void region_quadview_init_rv3d(
ScrArea *area, ARegion *region, const char viewlock, const char view, const char persp)
{
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
rv3d->rflag &= ~RV3D_WAS_CAMOB;
if (persp == RV3D_CAMOB) {
ED_view3d_lastview_store(rv3d);

View File

@@ -498,6 +498,7 @@ static wmOperatorStatus viewpersportho_exec(bContext *C, wmOperator * /*op*/)
else {
rv3d->persp = RV3D_PERSP;
}
rv3d->rflag &= ~RV3D_WAS_CAMOB;
ED_region_tag_redraw(region);
}

View File

@@ -445,12 +445,12 @@ enum {
RV3D_NAVIGATING = 1 << 3,
RV3D_GPULIGHT_UPDATE = 1 << 4,
RV3D_PAINTING = 1 << 5,
// RV3D_IS_GAME_ENGINE = 1 << 5, /* UNUSED */
/**
* Disable Z-buffer offset, skip calls to #ED_view3d_polygon_offset.
* Use when precise surface depth is needed and picking bias isn't, see #45434).
*/
RV3D_ZOFFSET_DISABLED = 1 << 6,
RV3D_WAS_CAMOB = 1 << 7,
};
/** #RegionView3D.viewlock */