From f0210e07972995550c2e4b71267e5f82eec0d6dd Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Wed, 24 Jul 2024 14:43:30 -0700 Subject: [PATCH] ui: Move view transform calculation into `PageLayout`. This makes sense to have in this module next to `UiSize`, and will eventually actually depend on the layout. --- all-is-cubes-ui/src/ui_content/vui_manager.rs | 40 ++++++------------- all-is-cubes-ui/src/vui/page.rs | 31 +++++++++++++- 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/all-is-cubes-ui/src/ui_content/vui_manager.rs b/all-is-cubes-ui/src/ui_content/vui_manager.rs index 779b9ea5d..48b51b48f 100644 --- a/all-is-cubes-ui/src/ui_content/vui_manager.rs +++ b/all-is-cubes-ui/src/ui_content/vui_manager.rs @@ -7,8 +7,7 @@ use all_is_cubes::arcstr::ArcStr; use all_is_cubes::character::{Character, Cursor}; use all_is_cubes::inv::{EphemeralOpaque, Tool, ToolError, ToolInput}; use all_is_cubes::listen::{DirtyFlag, ListenableCell, ListenableSource, Notifier}; -use all_is_cubes::math::FreeCoordinate; -use all_is_cubes::math::{FreeVector, NotNan}; +use all_is_cubes::math::NotNan; use all_is_cubes::space::Space; use all_is_cubes::time; use all_is_cubes::transaction::{self, Transaction}; @@ -237,10 +236,14 @@ impl Vui { } => &mut self.dump_page, }; let next_space: Handle = next_page.get_or_create_space(size, universe); + let layout = next_page.page().layout; if Some(&next_space) != Option::as_ref(&self.current_view.get().space) { - self.current_view - .set(Self::view_state_for(Some(next_space), &self.hud_inputs)); + self.current_view.set(Self::view_state_for( + layout, + Some(next_space), + &self.hud_inputs, + )); self.current_focus_on_ui = next_page.page().focus_on_ui; log::trace!( "UI switched to {:?} ({:?})", @@ -250,13 +253,17 @@ impl Vui { } } - fn view_state_for(space: Option>, inputs: &HudInputs) -> UiViewState { + fn view_state_for( + page_layout: vui::PageLayout, + space: Option>, + inputs: &HudInputs, + ) -> UiViewState { // TODO: compute the derived graphics options only once let graphics_options = Self::graphics_options(inputs.graphics_options.snapshot()); UiViewState { view_transform: match space.as_ref() { - Some(space) => Self::view_transform( + Some(space) => page_layout.view_transform( &space.read().unwrap(), // TODO: eliminate this unwrap graphics_options.fov_y.into_inner(), ), @@ -267,27 +274,6 @@ impl Vui { } } - /// Computes a [`ViewTransform`] that should be used to view the [`Vui::current_space`]. - /// - /// It does not need to be rechecked other than on aspect ratio changes. - /// - /// TODO: used to be public before [`UiViewState`]; refactor in light of - fn view_transform(space: &Space, fov_y_degrees: FreeCoordinate) -> ViewTransform { - let bounds = space.bounds(); - let mut ui_center = bounds.center(); - - // Arrange a view distance which will place the Z=0 plane sized to fill the viewport - // (at least vertically, as we don't have aspect ratio support yet). - ui_center.z = 0.0; - - let view_distance = FreeCoordinate::from(bounds.size().height) - / (fov_y_degrees / 2.).to_radians().tan() - / 2.; - ViewTransform::from_translation( - ui_center.to_vector() + FreeVector::new(0., 0., view_distance), - ) - } - /// Compute graphics options to render the VUI space given the user's regular options. fn graphics_options(mut options: GraphicsOptions) -> GraphicsOptions { // Set FOV to give a predictable, not-too-wide-angle perspective. diff --git a/all-is-cubes-ui/src/vui/page.rs b/all-is-cubes-ui/src/vui/page.rs index 6bcd2a144..190688905 100644 --- a/all-is-cubes-ui/src/vui/page.rs +++ b/all-is-cubes-ui/src/vui/page.rs @@ -7,12 +7,12 @@ use all_is_cubes::color_block; use all_is_cubes::content::palette; use all_is_cubes::euclid::{size2, Size2D}; use all_is_cubes::math::{ - Cube, Face6, FreeCoordinate, GridAab, GridCoordinate, GridSize, GridSizeCoord, Rgba, + Cube, Face6, FreeCoordinate, FreeVector, GridAab, GridCoordinate, GridSize, GridSizeCoord, Rgba, }; use all_is_cubes::space::{self, Space, SpaceBuilder, SpacePhysics}; use all_is_cubes::time; use all_is_cubes::universe::{Handle, Universe}; -use all_is_cubes_render::camera; +use all_is_cubes_render::camera::{self, ViewTransform}; use crate::vui::{ self, install_widgets, widgets, Align, Gravity, InstallVuiError, LayoutGrant, LayoutRequest, @@ -160,6 +160,33 @@ pub(crate) enum PageLayout { Hud, } +impl PageLayout { + /// Calculate the camera view transform that should be used for a page with this layout. + pub(crate) fn view_transform( + self, + space: &Space, + fov_y_degrees: FreeCoordinate, + ) -> ViewTransform { + let bounds = space.bounds(); + let mut ui_center = bounds.center(); + + match self { + PageLayout::Hud => { + // Arrange a view distance which will place the Z=0 plane sized to fill the viewport + // vertically. + ui_center.z = 0.0; + + let view_distance = FreeCoordinate::from(bounds.size().height) + / (fov_y_degrees / 2.).to_radians().tan() + / 2.; + ViewTransform::from_translation( + ui_center.to_vector() + FreeVector::new(0., 0., view_distance), + ) + } + } + } +} + /// Pair of a [`Page`] and a cached space that is an instantiation of its widgets, /// which can be recreated with a different size as needed by viewport size changes. ///