edit: dynamic gui scale
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
use std::{cell::RefCell, rc::Rc};
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
use button::setup_custom_button;
|
use button::setup_custom_button;
|
||||||
use glam::{vec2, Affine2, Vec2};
|
use glam::{Affine2, Vec2, vec2};
|
||||||
use label::setup_custom_label;
|
use label::setup_custom_label;
|
||||||
use wgui::{
|
use wgui::{
|
||||||
assets::AssetPath,
|
assets::AssetPath,
|
||||||
@@ -15,14 +15,14 @@ use wgui::{
|
|||||||
layout::{Layout, LayoutParams, WidgetID},
|
layout::{Layout, LayoutParams, WidgetID},
|
||||||
parser::ParserState,
|
parser::ParserState,
|
||||||
renderer_vk::context::Context as WguiContext,
|
renderer_vk::context::Context as WguiContext,
|
||||||
widget::{label::WidgetLabel, rectangle::WidgetRectangle, EventResult},
|
widget::{EventResult, label::WidgetLabel, rectangle::WidgetRectangle},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::input::{Haptics, HoverResult, PointerHit, PointerMode},
|
backend::input::{Haptics, HoverResult, PointerHit, PointerMode},
|
||||||
state::AppState,
|
state::AppState,
|
||||||
subsystem::hid::WheelDelta,
|
subsystem::hid::WheelDelta,
|
||||||
windowing::backend::{ui_transform, FrameMeta, OverlayBackend, RenderResources, ShouldRender},
|
windowing::backend::{FrameMeta, OverlayBackend, RenderResources, ShouldRender, ui_transform},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{timer::GuiTimer, timestep::Timestep};
|
use super::{timer::GuiTimer, timestep::Timestep};
|
||||||
@@ -41,6 +41,7 @@ pub struct GuiPanel<S> {
|
|||||||
pub timers: Vec<GuiTimer>,
|
pub timers: Vec<GuiTimer>,
|
||||||
pub parser_state: ParserState,
|
pub parser_state: ParserState,
|
||||||
pub max_size: Vec2,
|
pub max_size: Vec2,
|
||||||
|
pub gui_scale: f32,
|
||||||
interaction_transform: Option<Affine2>,
|
interaction_transform: Option<Affine2>,
|
||||||
context: WguiContext,
|
context: WguiContext,
|
||||||
timestep: Timestep,
|
timestep: Timestep,
|
||||||
@@ -56,13 +57,28 @@ pub type OnCustomIdFunc = Box<
|
|||||||
) -> anyhow::Result<()>,
|
) -> anyhow::Result<()>,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
pub struct NewGuiPanelParams {
|
||||||
|
pub on_custom_id: Option<OnCustomIdFunc>, // used only in `new_from_template`
|
||||||
|
pub resize_to_parent: bool,
|
||||||
|
pub gui_scale: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for NewGuiPanelParams {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
on_custom_id: None,
|
||||||
|
resize_to_parent: false,
|
||||||
|
gui_scale: 1.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<S: 'static> GuiPanel<S> {
|
impl<S: 'static> GuiPanel<S> {
|
||||||
pub fn new_from_template(
|
pub fn new_from_template(
|
||||||
app: &mut AppState,
|
app: &mut AppState,
|
||||||
path: &str,
|
path: &str,
|
||||||
state: S,
|
state: S,
|
||||||
on_custom_id: Option<OnCustomIdFunc>,
|
params: NewGuiPanelParams,
|
||||||
resize_to_parent: bool,
|
|
||||||
) -> anyhow::Result<Self> {
|
) -> anyhow::Result<Self> {
|
||||||
let custom_elems = Rc::new(RefCell::new(vec![]));
|
let custom_elems = Rc::new(RefCell::new(vec![]));
|
||||||
|
|
||||||
@@ -80,10 +96,14 @@ impl<S: 'static> GuiPanel<S> {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let (mut layout, mut parser_state) =
|
let (mut layout, mut parser_state) = wgui::parser::new_layout_from_assets(
|
||||||
wgui::parser::new_layout_from_assets(&doc_params, &LayoutParams { resize_to_parent })?;
|
&doc_params,
|
||||||
|
&LayoutParams {
|
||||||
|
resize_to_parent: params.resize_to_parent,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
if let Some(on_element_id) = on_custom_id {
|
if let Some(on_element_id) = params.on_custom_id {
|
||||||
let ids = parser_state.data.ids.clone(); // FIXME: copying all ids?
|
let ids = parser_state.data.ids.clone(); // FIXME: copying all ids?
|
||||||
|
|
||||||
for (id, widget) in ids {
|
for (id, widget) in ids {
|
||||||
@@ -128,11 +148,21 @@ impl<S: 'static> GuiPanel<S> {
|
|||||||
max_size: vec2(DEFAULT_MAX_SIZE as _, DEFAULT_MAX_SIZE as _),
|
max_size: vec2(DEFAULT_MAX_SIZE as _, DEFAULT_MAX_SIZE as _),
|
||||||
timers: vec![],
|
timers: vec![],
|
||||||
interaction_transform: None,
|
interaction_transform: None,
|
||||||
|
gui_scale: params.gui_scale,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_blank(app: &mut AppState, state: S, resize_to_parent: bool) -> anyhow::Result<Self> {
|
pub fn new_blank(
|
||||||
let layout = Layout::new(app.wgui_globals.clone(), &LayoutParams { resize_to_parent })?;
|
app: &mut AppState,
|
||||||
|
state: S,
|
||||||
|
params: NewGuiPanelParams,
|
||||||
|
) -> anyhow::Result<Self> {
|
||||||
|
let layout = Layout::new(
|
||||||
|
app.wgui_globals.clone(),
|
||||||
|
&LayoutParams {
|
||||||
|
resize_to_parent: params.resize_to_parent,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
let context = WguiContext::new(&mut app.wgui_shared, 1.0)?;
|
let context = WguiContext::new(&mut app.wgui_shared, 1.0)?;
|
||||||
let mut timestep = Timestep::new();
|
let mut timestep = Timestep::new();
|
||||||
timestep.set_tps(60.0);
|
timestep.set_tps(60.0);
|
||||||
@@ -146,6 +176,7 @@ impl<S: 'static> GuiPanel<S> {
|
|||||||
max_size: vec2(DEFAULT_MAX_SIZE as _, DEFAULT_MAX_SIZE as _),
|
max_size: vec2(DEFAULT_MAX_SIZE as _, DEFAULT_MAX_SIZE as _),
|
||||||
timers: vec![],
|
timers: vec![],
|
||||||
interaction_transform: None,
|
interaction_transform: None,
|
||||||
|
gui_scale: params.gui_scale,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,8 +253,9 @@ impl<S: 'static> OverlayBackend for GuiPanel<S> {
|
|||||||
|
|
||||||
fn render(&mut self, app: &mut AppState, rdr: &mut RenderResources) -> anyhow::Result<()> {
|
fn render(&mut self, app: &mut AppState, rdr: &mut RenderResources) -> anyhow::Result<()> {
|
||||||
self.context
|
self.context
|
||||||
.update_viewport(&mut app.wgui_shared, rdr.extent, 1.0)?;
|
.update_viewport(&mut app.wgui_shared, rdr.extent, self.gui_scale)?;
|
||||||
self.layout.update(self.max_size, self.timestep.alpha)?;
|
self.layout
|
||||||
|
.update(self.max_size / self.gui_scale, self.timestep.alpha)?;
|
||||||
|
|
||||||
let globals = self.layout.state.globals.clone(); // sorry
|
let globals = self.layout.state.globals.clone(); // sorry
|
||||||
let mut globals = globals.get();
|
let mut globals = globals.get();
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ use std::sync::{Arc, LazyLock};
|
|||||||
|
|
||||||
use crate::gui::panel::GuiPanel;
|
use crate::gui::panel::GuiPanel;
|
||||||
use crate::state::AppState;
|
use crate::state::AppState;
|
||||||
use crate::windowing::window::{OverlayWindowConfig, OverlayWindowState, Positioning};
|
|
||||||
use crate::windowing::Z_ORDER_ANCHOR;
|
use crate::windowing::Z_ORDER_ANCHOR;
|
||||||
|
use crate::windowing::window::{OverlayWindowConfig, OverlayWindowState, Positioning};
|
||||||
|
|
||||||
pub static ANCHOR_NAME: LazyLock<Arc<str>> = LazyLock::new(|| Arc::from("anchor"));
|
pub static ANCHOR_NAME: LazyLock<Arc<str>> = LazyLock::new(|| Arc::from("anchor"));
|
||||||
|
|
||||||
pub fn create_anchor(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
|
pub fn create_anchor(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
|
||||||
let mut panel = GuiPanel::new_from_template(app, "gui/anchor.xml", (), None, false)?;
|
let mut panel = GuiPanel::new_from_template(app, "gui/anchor.xml", (), Default::default())?;
|
||||||
panel.update_layout()?;
|
panel.update_layout()?;
|
||||||
|
|
||||||
Ok(OverlayWindowConfig {
|
Ok(OverlayWindowConfig {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ struct BarState {}
|
|||||||
#[allow(clippy::match_same_arms)] // TODO: remove later
|
#[allow(clippy::match_same_arms)] // TODO: remove later
|
||||||
pub fn create_bar(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
|
pub fn create_bar(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
|
||||||
let state = BarState {};
|
let state = BarState {};
|
||||||
let mut panel = GuiPanel::new_from_template(app, "gui/bar.xml", state, None, false)?;
|
let mut panel = GuiPanel::new_from_template(app, "gui/bar.xml", state, Default::default())?;
|
||||||
|
|
||||||
for (id, _widget_id) in &panel.parser_state.data.ids {
|
for (id, _widget_id) in &panel.parser_state.data.ids {
|
||||||
match id.as_ref() {
|
match id.as_ref() {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use glam::{vec3, Affine3A, Quat, Vec3};
|
use glam::{Affine3A, Quat, Vec3, vec3};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
gui::panel::GuiPanel,
|
gui::panel::GuiPanel,
|
||||||
@@ -18,7 +18,7 @@ pub fn create_custom(app: &mut AppState, name: Arc<str>) -> Option<OverlayWindow
|
|||||||
|
|
||||||
unreachable!();
|
unreachable!();
|
||||||
|
|
||||||
let panel = GuiPanel::new_blank(app, (), false).ok()?;
|
let panel = GuiPanel::new_blank(app, (), Default::default()).ok()?;
|
||||||
panel.update_layout().ok()?;
|
panel.update_layout().ok()?;
|
||||||
|
|
||||||
Some(OverlayWindowConfig {
|
Some(OverlayWindowConfig {
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ use std::{
|
|||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use glam::vec2;
|
use glam::{UVec2, vec2};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::input::HoverResult,
|
backend::input::HoverResult,
|
||||||
gui::panel::GuiPanel,
|
gui::panel::{GuiPanel, NewGuiPanelParams},
|
||||||
state::AppState,
|
state::AppState,
|
||||||
subsystem::hid::WheelDelta,
|
subsystem::hid::WheelDelta,
|
||||||
windowing::{
|
windowing::{
|
||||||
@@ -35,11 +35,19 @@ impl EditWrapperManager {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let Some(meta) = owc.backend.frame_meta() else {
|
||||||
|
log::error!("META NULL");
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
log::debug!("EditMode wrap on {}", owc.name);
|
log::debug!("EditMode wrap on {}", owc.name);
|
||||||
let inner = mem::replace(&mut owc.backend, Box::new(DummyBackend {}));
|
let inner = mem::replace(&mut owc.backend, Box::new(DummyBackend {}));
|
||||||
let mut panel = self.panel_pool.pop();
|
let mut panel = self.panel_pool.pop();
|
||||||
if panel.is_none() {
|
if panel.is_none() {
|
||||||
panel = Some(make_edit_panel(app)?);
|
panel = Some(make_edit_panel(
|
||||||
|
app,
|
||||||
|
UVec2::new(meta.extent[0], meta.extent[1]),
|
||||||
|
)?);
|
||||||
}
|
}
|
||||||
let mut panel = panel.unwrap();
|
let mut panel = panel.unwrap();
|
||||||
panel.state = owc.name.clone();
|
panel.state = owc.name.clone();
|
||||||
@@ -99,10 +107,15 @@ impl OverlayBackend for EditModeBackendWrapper {
|
|||||||
if !matches!(i, ShouldRender::Unable)
|
if !matches!(i, ShouldRender::Unable)
|
||||||
&& let Some(ref frame_meta) = self.inner.frame_meta()
|
&& let Some(ref frame_meta) = self.inner.frame_meta()
|
||||||
{
|
{
|
||||||
let new_size = vec2(frame_meta.extent[0] as _, frame_meta.extent[1] as _);
|
let (width_px, height_px) = (frame_meta.extent[0], frame_meta.extent[1]);
|
||||||
|
|
||||||
|
let new_size = vec2(width_px as _, height_px as _);
|
||||||
if self.panel.max_size != new_size {
|
if self.panel.max_size != new_size {
|
||||||
log::debug!("EditWrapperGui size {} → {new_size}", self.panel.max_size);
|
log::debug!("EditWrapperGui size {} → {new_size}", self.panel.max_size);
|
||||||
self.panel.max_size = new_size;
|
self.panel.max_size = new_size;
|
||||||
|
|
||||||
|
let gui_scale = width_px.min(height_px) as f32 / 550.0;
|
||||||
|
self.panel.gui_scale = gui_scale;
|
||||||
self.panel.update_layout()?;
|
self.panel.update_layout()?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -165,8 +178,25 @@ impl OverlayBackend for EditModeBackendWrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_edit_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
|
fn make_edit_panel(
|
||||||
let panel = GuiPanel::new_from_template(app, "gui/edit.xml", "".into(), None, true)?;
|
app: &mut AppState,
|
||||||
|
overlay_resolution: UVec2,
|
||||||
|
) -> anyhow::Result<EditModeWrapPanel> {
|
||||||
|
log::error!(
|
||||||
|
"overlay res {} {}",
|
||||||
|
overlay_resolution.x,
|
||||||
|
overlay_resolution.y
|
||||||
|
);
|
||||||
|
|
||||||
|
let panel = GuiPanel::new_from_template(
|
||||||
|
app,
|
||||||
|
"gui/edit.xml",
|
||||||
|
"".into(),
|
||||||
|
NewGuiPanelParams {
|
||||||
|
resize_to_parent: true,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
Ok(panel)
|
Ok(panel)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ pub fn create_keyboard(
|
|||||||
processes: vec![],
|
processes: vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut panel = GuiPanel::new_blank(app, state, false)?;
|
let mut panel = GuiPanel::new_blank(app, state, Default::default())?;
|
||||||
|
|
||||||
let globals = app.wgui_globals.clone();
|
let globals = app.wgui_globals.clone();
|
||||||
let accent_color = globals.get().defaults.accent_color;
|
let accent_color = globals.get().defaults.accent_color;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use std::{
|
|||||||
time::Instant,
|
time::Instant,
|
||||||
};
|
};
|
||||||
|
|
||||||
use glam::{vec3, Affine3A, Quat, Vec3};
|
use glam::{Affine3A, Quat, Vec3, vec3};
|
||||||
use idmap_derive::IntegerId;
|
use idmap_derive::IntegerId;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use wgui::{
|
use wgui::{
|
||||||
@@ -28,8 +28,8 @@ use crate::{
|
|||||||
gui::panel::GuiPanel,
|
gui::panel::GuiPanel,
|
||||||
state::{AppState, LeftRight},
|
state::{AppState, LeftRight},
|
||||||
windowing::{
|
windowing::{
|
||||||
window::{OverlayWindowConfig, OverlayWindowState, Positioning},
|
|
||||||
OverlaySelector, Z_ORDER_TOAST,
|
OverlaySelector, Z_ORDER_TOAST,
|
||||||
|
window::{OverlayWindowConfig, OverlayWindowState, Positioning},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -170,7 +170,7 @@ fn new_toast(toast: Toast, app: &mut AppState) -> Option<OverlayWindowConfig> {
|
|||||||
toast.title
|
toast.title
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut panel = GuiPanel::new_blank(app, (), false).ok()?;
|
let mut panel = GuiPanel::new_blank(app, (), Default::default()).ok()?;
|
||||||
|
|
||||||
let globals = panel.layout.state.globals.clone();
|
let globals = panel.layout.state.globals.clone();
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,14 @@ use std::{collections::HashMap, rc::Rc, time::Duration};
|
|||||||
use glam::{Affine3A, Vec3, Vec3A};
|
use glam::{Affine3A, Vec3, Vec3A};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
gui::{panel::GuiPanel, timer::GuiTimer},
|
gui::{
|
||||||
|
panel::{GuiPanel, NewGuiPanelParams},
|
||||||
|
timer::GuiTimer,
|
||||||
|
},
|
||||||
state::AppState,
|
state::AppState,
|
||||||
windowing::{
|
windowing::{
|
||||||
window::{OverlayWindowConfig, OverlayWindowData, OverlayWindowState, Positioning},
|
|
||||||
Z_ORDER_WATCH,
|
Z_ORDER_WATCH,
|
||||||
|
window::{OverlayWindowConfig, OverlayWindowData, OverlayWindowState, Positioning},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -22,7 +25,8 @@ pub fn create_watch(app: &mut AppState, num_sets: usize) -> anyhow::Result<Overl
|
|||||||
app,
|
app,
|
||||||
"gui/watch.xml",
|
"gui/watch.xml",
|
||||||
state,
|
state,
|
||||||
Some(Box::new(
|
NewGuiPanelParams {
|
||||||
|
on_custom_id: Some(Box::new(
|
||||||
move |id, widget, doc_params, layout, parser_state| {
|
move |id, widget, doc_params, layout, parser_state| {
|
||||||
if &*id != "sets" {
|
if &*id != "sets" {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -32,12 +36,14 @@ pub fn create_watch(app: &mut AppState, num_sets: usize) -> anyhow::Result<Overl
|
|||||||
let mut params: HashMap<Rc<str>, Rc<str>> = HashMap::new();
|
let mut params: HashMap<Rc<str>, Rc<str>> = HashMap::new();
|
||||||
params.insert("display".into(), (idx + 1).to_string().into());
|
params.insert("display".into(), (idx + 1).to_string().into());
|
||||||
params.insert("handle".into(), idx.to_string().into());
|
params.insert("handle".into(), idx.to_string().into());
|
||||||
parser_state.instantiate_template(doc_params, "Set", layout, widget, params)?;
|
parser_state
|
||||||
|
.instantiate_template(doc_params, "Set", layout, widget, params)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
false,
|
..Default::default()
|
||||||
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
panel
|
panel
|
||||||
|
|||||||
Reference in New Issue
Block a user