From 5317b575963ffc44baeece496dc3016b405c5b3b Mon Sep 17 00:00:00 2001 From: Paris DOUADY Date: Thu, 8 Feb 2024 00:51:54 +0100 Subject: [PATCH] move windows to layer system instead of custom --- goryak/src/window.rs | 78 ++- native_app/src/init.rs | 2 - native_app/src/newgui/hud/menu.rs | 71 ++- native_app/src/newgui/hud/mod.rs | 8 +- native_app/src/newgui/hud/window_display.rs | 52 -- native_app/src/newgui/hud/windows/economy.rs | 526 +++++++++--------- native_app/src/newgui/hud/windows/mod.rs | 9 +- native_app/src/newgui/hud/windows/settings.rs | 446 ++++++++------- native_app/src/uiworld.rs | 12 - 9 files changed, 547 insertions(+), 657 deletions(-) delete mode 100644 native_app/src/newgui/hud/window_display.rs diff --git a/goryak/src/window.rs b/goryak/src/window.rs index 2657fe8e..1d2eabaf 100644 --- a/goryak/src/window.rs +++ b/goryak/src/window.rs @@ -1,5 +1,5 @@ use std::borrow::Cow; -use std::cell::{Cell, RefCell}; +use std::cell::Cell; use std::rc::Rc; use yakui_core::geometry::{Color, Constraints, Dim2, Vec2}; @@ -12,57 +12,54 @@ use crate::{ blur_bg, icon_button, mincolumn, on_primary_container, outline, primary_container, textc, }; -thread_local! { - /// Remember which windows were drawn. That what we can put them at the bottom of the widget tree to be drawn on top of the rest. - /// We can also have a way to remember which windows are active, so they can be on top too. - static WINDOWS: RefCell> = Default::default(); -} - -pub struct Window { +pub struct Window<'a> { pub title: &'static str, pub pad: Pad, pub radius: f32, + pub opened: &'a mut bool, } -impl Window { - pub fn show(self, children: impl FnOnce(), on_close: impl FnOnce()) { +impl<'a> Window<'a> { + pub fn show(self, children: impl FnOnce()) { let dom = context::dom(); let response = dom.begin_widget::(()); let off = draggable(|| { - blur_bg(primary_container().with_alpha(0.5), self.radius, || { - self.pad.show(|| { - mincolumn(|| { - reflow(Alignment::TOP_RIGHT, Dim2::ZERO, || { - offset(Vec2::new(-25.0, -15.0), || { - constrained(Constraints::tight(Vec2::splat(40.0)), || { - center(|| { - let mut b = Button::unstyled("close"); - b.padding = Pad::balanced(4.0, 2.0); - b.border_radius = 10.0; - b.style.fill = Color::CLEAR; - b.style.text.font_size = 20.0; - b.style.text.color = on_primary_container().adjust(0.5); - b.down_style.fill = Color::CLEAR; - b.down_style.text = b.style.text.clone(); - b.hover_style.fill = Color::CLEAR; - b.hover_style.text = b.style.text.clone(); - b.hover_style.text.font_size = 25.0; - b.hover_style.text.color = on_primary_container(); - - if icon_button(b).show().clicked { - on_close(); - } + if *self.opened { + blur_bg(primary_container().with_alpha(0.5), self.radius, || { + self.pad.show(|| { + mincolumn(|| { + reflow(Alignment::TOP_RIGHT, Dim2::ZERO, || { + offset(Vec2::new(-25.0, -15.0), || { + constrained(Constraints::tight(Vec2::splat(40.0)), || { + center(|| { + let mut b = Button::unstyled("close"); + b.padding = Pad::balanced(4.0, 2.0); + b.border_radius = 10.0; + b.style.fill = Color::CLEAR; + b.style.text.font_size = 20.0; + b.style.text.color = on_primary_container().adjust(0.5); + b.down_style.fill = Color::CLEAR; + b.down_style.text = b.style.text.clone(); + b.hover_style.fill = Color::CLEAR; + b.hover_style.text = b.style.text.clone(); + b.hover_style.text.font_size = 25.0; + b.hover_style.text.color = on_primary_container(); + + if icon_button(b).show().clicked { + *self.opened = false; + } + }); }); }); }); + textc(on_primary_container(), Cow::Borrowed(self.title)); + divider(outline(), 10.0, 1.0); + children(); }); - textc(on_primary_container(), Cow::Borrowed(self.title)); - divider(outline(), 10.0, 1.0); - children(); }); }); - }); + } }); response.confirm.set(off.dragging.is_none()); @@ -78,18 +75,18 @@ impl Window { struct WindowBase { props: (), off: Vec2, - resp: Rc, + resp: Rc, } #[derive(Default, Debug)] -struct WindowResp { +struct WindowBaseResponse { off: Cell, confirm: Cell, } impl Widget for WindowBase { type Props<'a> = (); - type Response = Rc; + type Response = Rc; fn new() -> Self { Self::default() @@ -112,6 +109,7 @@ impl Widget for WindowBase { } fn layout(&self, mut ctx: LayoutContext<'_>, _: Constraints) -> Vec2 { + ctx.layout.new_layer(ctx.dom); let node = ctx.dom.get_current(); if node.children.len() > 1 { panic!("Window can only have one child"); diff --git a/native_app/src/init.rs b/native_app/src/init.rs index ab2df434..98a7a00c 100644 --- a/native_app/src/init.rs +++ b/native_app/src/init.rs @@ -10,7 +10,6 @@ use crate::newgui::roadbuild::RoadBuildResource; use crate::newgui::roadeditor::RoadEditorResource; use crate::newgui::specialbuilding::SpecialBuildingResource; use crate::newgui::terraforming::TerraformingResource; -use crate::newgui::window_display::WindowDisplay; use crate::newgui::windows::economy::EconomyState; use crate::newgui::windows::settings::{Settings, SettingsState}; use crate::newgui::zoneedit::ZoneEditState; @@ -62,7 +61,6 @@ pub fn init() { register_resource_noserialize::(); register_resource_noserialize::(); register_resource_noserialize::(); - register_resource_noserialize::(); register_resource_noserialize::(); register_resource_noserialize::(); } diff --git a/native_app/src/newgui/hud/menu.rs b/native_app/src/newgui/hud/menu.rs index ca273089..37fdd73a 100644 --- a/native_app/src/newgui/hud/menu.rs +++ b/native_app/src/newgui/hud/menu.rs @@ -60,46 +60,43 @@ fn save_window(gui: &mut GuiState, uiw: &UiWorld) { match *estate { ExitState::NoExit => {} ExitState::ExitAsk | ExitState::Saving => { - uiw.window( - Window { - title: "Exit Menu", - pad: Pad::all(15.0), - radius: 10.0, - }, - |uiw| { - let mut estate = uiw.write::(); - *estate = ExitState::NoExit; - }, - |uiw, _sim| { - let mut slstate = uiw.write::(); - let mut estate = uiw.write::(); - let mut l = List::column(); - l.item_spacing = 5.0; - l.main_axis_size = MainAxisSize::Min; - l.show(|| { - if let ExitState::Saving = *estate { - textc(on_secondary_container(), "Saving..."); - if !slstate.please_save && !slstate.saving_status.load(Ordering::SeqCst) - { - std::process::exit(0); - } - return; - } - if button_secondary("Save and exit").show().clicked { - if let ExitState::ExitAsk = *estate { - slstate.please_save = true; - *estate = ExitState::Saving; - } - } - if button_secondary("Exit without saving").show().clicked { + let mut opened = true; + Window { + title: "Exit Menu", + pad: Pad::all(15.0), + radius: 10.0, + opened: &mut opened, + } + .show(|| { + let mut l = List::column(); + l.item_spacing = 5.0; + l.main_axis_size = MainAxisSize::Min; + l.show(|| { + if let ExitState::Saving = *estate { + textc(on_secondary_container(), "Saving..."); + if !slstate.please_save && !slstate.saving_status.load(Ordering::SeqCst) { std::process::exit(0); } - if button_secondary("Cancel").show().clicked { - *estate = ExitState::NoExit; + return; + } + if button_secondary("Save and exit").show().clicked { + if let ExitState::ExitAsk = *estate { + slstate.please_save = true; + *estate = ExitState::Saving; } - }); - }, - ); + } + if button_secondary("Exit without saving").show().clicked { + std::process::exit(0); + } + if button_secondary("Cancel").show().clicked { + *estate = ExitState::NoExit; + } + }); + }); + + if !opened { + *estate = ExitState::NoExit; + } if uiw .read::() diff --git a/native_app/src/newgui/hud/mod.rs b/native_app/src/newgui/hud/mod.rs index 7c85c09f..21ee0aaa 100644 --- a/native_app/src/newgui/hud/mod.rs +++ b/native_app/src/newgui/hud/mod.rs @@ -1,4 +1,3 @@ -use goryak::debug_layout; use ordered_float::OrderedFloat; use std::time::Instant; use yakui::{reflow, Alignment, Color, Dim2, Vec2}; @@ -10,14 +9,12 @@ use crate::gui::{GuiState, UiTextures}; use crate::newgui::hud::menu::menu_bar; use crate::newgui::hud::time_controls::time_controls; use crate::newgui::hud::toolbox::new_toolbox; -use crate::newgui::window_display::WindowDisplay; use crate::newgui::windows::settings::Settings; use crate::uiworld::{SaveLoadState, UiWorld}; mod menu; mod time_controls; mod toolbox; -pub mod window_display; pub mod windows; /// Root GUI entrypoint @@ -35,11 +32,8 @@ pub fn render_newgui(uiworld: &UiWorld, sim: &Simulation) { menu_bar(uiworld, sim); uiworld.write::().windows.render(uiworld, sim); time_controls(uiworld, sim); - WindowDisplay::finish(uiworld, sim); }); - if tweak!(false) { - debug_layout(); - } + //goryak::debug_layout(); } fn auto_save(uiworld: &UiWorld) { diff --git a/native_app/src/newgui/hud/window_display.rs b/native_app/src/newgui/hud/window_display.rs deleted file mode 100644 index 8ccb0457..00000000 --- a/native_app/src/newgui/hud/window_display.rs +++ /dev/null @@ -1,52 +0,0 @@ -use crate::uiworld::UiWorld; -use goryak::Window; -use simulation::Simulation; - -#[derive(Default)] -pub struct WindowDisplay { - windows: Vec, -} - -struct WindowDisplayHolder { - window: Window, - children: Box, - on_close: Box, -} - -impl WindowDisplay { - pub fn show( - &mut self, - window: Window, - children: impl FnOnce(&UiWorld, &Simulation) + 'static, - on_close: impl FnOnce(&UiWorld) + 'static, - ) { - self.windows.push(WindowDisplayHolder { - window, - children: Box::new(children), - on_close: Box::new(on_close), - }); - } - - pub fn finish(uiw: &UiWorld, sim: &Simulation) { - let mut window_state = uiw.write::(); - let windows = std::mem::take(&mut window_state.windows); - window_state.windows = Vec::with_capacity(windows.len()); - drop(window_state); - - for WindowDisplayHolder { - window, - children, - on_close, - } in windows - { - window.show( - || { - children(uiw, sim); - }, - || { - on_close(uiw); - }, - ); - } - } -} diff --git a/native_app/src/newgui/hud/windows/economy.rs b/native_app/src/newgui/hud/windows/economy.rs index 90464bc0..b9f425aa 100644 --- a/native_app/src/newgui/hud/windows/economy.rs +++ b/native_app/src/newgui/hud/windows/economy.rs @@ -19,7 +19,6 @@ use simulation::economy::{ }; use simulation::Simulation; -use crate::gui::GuiState; use crate::uiworld::UiWorld; #[derive(Copy, Clone, Default, PartialEq, Eq)] @@ -46,310 +45,291 @@ pub struct EconomyState { /// Economy window /// Shows the economy stats -pub fn economy(uiw: &UiWorld, _: &Simulation) { - uiw.window( - Window { - title: "Economy", - pad: Pad::all(10.0), - radius: 10.0, - }, - |uiw| { - uiw.write::().windows.economy_open = false; - }, - |uiw, sim| { - let mut state = uiw.write::(); - let ecostats = sim.read::(); - pady(10.0, || { - let mut l = List::row(); - l.main_axis_size = MainAxisSize::Min; - l.item_spacing = 10.0; - l.show(|| { - let tabs = &[ - ("Import/Exports", EconomyTab::ImportExports), - ("Internal Trade", EconomyTab::InternalTrade), - ("Market Prices", EconomyTab::MarketPrices), - ]; - - for (label, tab) in tabs { - if selectable_label_primary(state.tab == *tab, label).clicked { - state.tab = *tab; - } +pub fn economy(uiw: &UiWorld, sim: &Simulation, opened: &mut bool) { + Window { + title: "Economy", + pad: Pad::all(10.0), + radius: 10.0, + opened, + } + .show(|| { + let mut state = uiw.write::(); + let ecostats = sim.read::(); + pady(10.0, || { + let mut l = List::row(); + l.main_axis_size = MainAxisSize::Min; + l.item_spacing = 10.0; + l.show(|| { + let tabs = &[ + ("Import/Exports", EconomyTab::ImportExports), + ("Internal Trade", EconomyTab::InternalTrade), + ("Market Prices", EconomyTab::MarketPrices), + ]; + + for (label, tab) in tabs { + if selectable_label_primary(state.tab == *tab, label).clicked { + state.tab = *tab; } - }); + } }); + }); - pady(10.0, || { - let mut l = List::row(); - l.main_axis_size = MainAxisSize::Min; - l.item_spacing = 10.0; - l.show(|| { - for (i, level_name) in LEVEL_NAMES.iter().enumerate() { - if selectable_label_primary(state.curlevel == i, *level_name).clicked { - state.curlevel = i; - } + pady(10.0, || { + let mut l = List::row(); + l.main_axis_size = MainAxisSize::Min; + l.item_spacing = 10.0; + l.show(|| { + for (i, level_name) in LEVEL_NAMES.iter().enumerate() { + if selectable_label_primary(state.curlevel == i, *level_name).clicked { + state.curlevel = i; } + } - if state.tab == EconomyTab::ImportExports { - if selectable_label_primary(state.hist_type == HistoryType::Money, "Money") - .clicked - { - state.hist_type = HistoryType::Money; - } - if selectable_label_primary(state.hist_type == HistoryType::Items, "Items") - .clicked - { - state.hist_type = HistoryType::Items; - } + if state.tab == EconomyTab::ImportExports { + if selectable_label_primary(state.hist_type == HistoryType::Money, "Money") + .clicked + { + state.hist_type = HistoryType::Money; } - }); + if selectable_label_primary(state.hist_type == HistoryType::Items, "Items") + .clicked + { + state.hist_type = HistoryType::Items; + } + } }); - let seconds_per_step = LEVEL_FREQS[state.curlevel] as f64 * DELTA_F64; - let xs: Vec = (0..HISTORY_SIZE) - .map(|i| i as f64 * seconds_per_step) - .collect(); - let EconomyState { - curlevel, - ref tab, - hist_type, - } = *state; - - let render_history = |history: &ItemHistories, hist_type: HistoryType| { - padxy(5.0, 5.0, || { - mincolumn(|| { - let plot_size_x: f32 = 300.0; - let plot_size_y: f32 = 200.0; - - let filterid = use_state(|| HashSet::::new()); - - let mut vertices = Vec::new(); - let mut indices = Vec::new(); - - let cull_rect = - AABB::new_ll_size([0.0, 0.0].into(), [plot_size_x, plot_size_y].into()); - let mut tess = - Tesselator::new(&mut vertices, &mut indices, Some(cull_rect), 15.0); - tess.set_color([1.0f32, 1.0, 1.0, 1.0]); - - let mut overallmax = 0; - let cursor = history.cursors()[curlevel]; - - let mut positions = Vec::with_capacity(xs.len()); - - let filterid_b = filterid.borrow(); - for (id, history) in history.iter_histories(curlevel) { - if !filterid_b.is_empty() && !filterid_b.contains(&id) { - continue; + }); + let seconds_per_step = LEVEL_FREQS[state.curlevel] as f64 * DELTA_F64; + let xs: Vec = (0..HISTORY_SIZE) + .map(|i| i as f64 * seconds_per_step) + .collect(); + let EconomyState { + curlevel, + ref tab, + hist_type, + } = *state; + + let render_history = |history: &ItemHistories, hist_type: HistoryType| { + padxy(5.0, 5.0, || { + mincolumn(|| { + let plot_size_x: f32 = 300.0; + let plot_size_y: f32 = 200.0; + + let filterid = use_state(|| HashSet::::new()); + + let mut vertices = Vec::new(); + let mut indices = Vec::new(); + + let cull_rect = + AABB::new_ll_size([0.0, 0.0].into(), [plot_size_x, plot_size_y].into()); + let mut tess = + Tesselator::new(&mut vertices, &mut indices, Some(cull_rect), 15.0); + tess.set_color([1.0f32, 1.0, 1.0, 1.0]); + + let mut overallmax = 0; + let cursor = history.cursors()[curlevel]; + + let mut positions = Vec::with_capacity(xs.len()); + + let filterid_b = filterid.borrow(); + for (id, history) in history.iter_histories(curlevel) { + if !filterid_b.is_empty() && !filterid_b.contains(&id) { + continue; + } + let holder; + let ring = match hist_type { + HistoryType::Items => &history.past_ring_items, + HistoryType::Money => { + holder = history.past_ring_money.map(|x| x.bucks().abs()); + &holder } - let holder; - let ring = match hist_type { - HistoryType::Items => &history.past_ring_items, - HistoryType::Money => { - holder = history.past_ring_money.map(|x| x.bucks().abs()); - &holder - } - }; + }; - let maxval = *ring.iter().max().unwrap(); - if maxval > overallmax { - overallmax = maxval; - } + let maxval = *ring.iter().max().unwrap(); + if maxval > overallmax { + overallmax = maxval; } + } - let rescaler = AABB::new_ll_ur( - [0.0, 0.0].into(), - [ - HISTORY_SIZE as f32 * seconds_per_step as f32, - 1.0 + 1.25 * overallmax as f32, - ] - .into(), - ) - .make_rescaler(AABB::new_ll_ur( - [0.0, 0.0].into(), - [plot_size_x, plot_size_y].into(), - )); - - for (id, history) in history.iter_histories(curlevel) { - if !filterid_b.is_empty() && !filterid_b.contains(&id) { - continue; + let rescaler = AABB::new_ll_ur( + [0.0, 0.0].into(), + [ + HISTORY_SIZE as f32 * seconds_per_step as f32, + 1.0 + 1.25 * overallmax as f32, + ] + .into(), + ) + .make_rescaler(AABB::new_ll_ur( + [0.0, 0.0].into(), + [plot_size_x, plot_size_y].into(), + )); + + for (id, history) in history.iter_histories(curlevel) { + if !filterid_b.is_empty() && !filterid_b.contains(&id) { + continue; + } + let holder; + let ring = match hist_type { + HistoryType::Items => &history.past_ring_items, + HistoryType::Money => { + holder = history.past_ring_money.map(|x| x.bucks().abs()); + &holder } - let holder; - let ring = match hist_type { - HistoryType::Items => &history.past_ring_items, - HistoryType::Money => { - holder = history.past_ring_money.map(|x| x.bucks().abs()); - &holder - } - }; + }; - let maxval = *ring.iter().max().unwrap(); - if maxval == 0 { - continue; - } + let maxval = *ring.iter().max().unwrap(); + if maxval == 0 { + continue; + } - let h = id.hash(); - let random_col = geom::Color::new( - 0.5 + 0.5 * common::rand::rand2(h as f32, 0.0), - 0.5 + 0.5 * common::rand::rand2(h as f32, 1.0), - 0.5 + 0.5 * common::rand::rand2(h as f32, 2.0), - 1.0, - ); - - let c_next = (cursor + 1) % HISTORY_SIZE; - - tess.set_color([ - random_col.r, - random_col.g, - random_col.b, - random_col.a, - ]); - - let mut first_zeros = false; - - for (x, y) in xs.iter().zip( - ring[c_next..HISTORY_SIZE] - .iter() - .chain(ring[0..c_next].iter()) - .copied(), - ) { - if !first_zeros && y > 0 { - first_zeros = true; - } - if !first_zeros { - continue; - } + let h = id.hash(); + let random_col = geom::Color::new( + 0.5 + 0.5 * common::rand::rand2(h as f32, 0.0), + 0.5 + 0.5 * common::rand::rand2(h as f32, 1.0), + 0.5 + 0.5 * common::rand::rand2(h as f32, 2.0), + 1.0, + ); + + let c_next = (cursor + 1) % HISTORY_SIZE; - let rescaled = rescaler([*x as f32, y as f32].into()); + tess.set_color([random_col.r, random_col.g, random_col.b, random_col.a]); - positions.push(rescaled.z(0.0)); + let mut first_zeros = false; + + for (x, y) in xs.iter().zip( + ring[c_next..HISTORY_SIZE] + .iter() + .chain(ring[0..c_next].iter()) + .copied(), + ) { + if !first_zeros && y > 0 { + first_zeros = true; + } + if !first_zeros { + continue; } - tess.draw_polyline(&positions, 2.0, false); + let rescaled = rescaler([*x as f32, y as f32].into()); + + positions.push(rescaled.z(0.0)); } - drop(filterid_b); - - padxy(5.0, 5.0, || { - sized_canvas( - Vec2::new(plot_size_x, 200.0), - Color::BLACK, - move |paint| { - let rect = paint.layout.get(paint.dom.current()).unwrap().rect; - - let [x, y]: [f32; 2] = rect.pos().into(); - let [_sx, sy]: [f32; 2] = rect.size().into(); - - paint.paint.add_mesh(PaintMesh::new( - vertices.into_iter().map(|v| { - yakui::paint::Vertex::new( - [x + v.position[0], y + sy - v.position[1]], - v.uv, - v.color, - ) - }), - indices.into_iter().map(|x| x as _), - )); - }, - ); + tess.draw_polyline(&positions, 2.0, false); + } + + drop(filterid_b); + + padxy(5.0, 5.0, || { + sized_canvas(Vec2::new(plot_size_x, 200.0), Color::BLACK, move |paint| { + let rect = paint.layout.get(paint.dom.current()).unwrap().rect; + + let [x, y]: [f32; 2] = rect.pos().into(); + let [_sx, sy]: [f32; 2] = rect.size().into(); + + paint.paint.add_mesh(PaintMesh::new( + vertices.into_iter().map(|v| { + yakui::paint::Vertex::new( + [x + v.position[0], y + sy - v.position[1]], + v.uv, + v.color, + ) + }), + indices.into_iter().map(|x| x as _), + )); }); + }); - VertScroll::Fixed(300.0).show(|| { - constrained(Constraints::loose(Vec2::new(300.0, 1000000.0)), || { - let mut overall_total = 0; - let mut g = CountGrid::col(2); - g.cross_axis_alignment = CrossAxisAlignment::Stretch; - g.main_axis_size = MainAxisSize::Min; - g.main_axis_align_items = MainAxisAlignItems::Center; - g.show(|| { - let mut histories: Vec<_> = history - .iter_histories(curlevel) - .map(|(id, level)| { - (id, { - match hist_type { - HistoryType::Items => { - level.past_ring_items.iter().sum::() - } - HistoryType::Money => level - .past_ring_money - .iter() - .map(|x| x.bucks().abs()) - .sum::(), + VertScroll::Fixed(300.0).show(|| { + constrained(Constraints::loose(Vec2::new(300.0, 1000000.0)), || { + let mut overall_total = 0; + let mut g = CountGrid::col(2); + g.cross_axis_alignment = CrossAxisAlignment::Stretch; + g.main_axis_size = MainAxisSize::Min; + g.main_axis_align_items = MainAxisAlignItems::Center; + g.show(|| { + let mut histories: Vec<_> = history + .iter_histories(curlevel) + .map(|(id, level)| { + (id, { + match hist_type { + HistoryType::Items => { + level.past_ring_items.iter().sum::() } - }) + HistoryType::Money => level + .past_ring_money + .iter() + .map(|x| x.bucks().abs()) + .sum::(), + } }) - .filter(|(_, x)| *x != 0) - .collect(); - histories.sort_by_key(|(_, sum)| *sum); - - for (id, sum) in histories { - let enabled = filterid.borrow().contains(&id); - - minrow(0.0, || { - if selectable_label_primary( - enabled, - &id.prototype().name, - ) + }) + .filter(|(_, x)| *x != 0) + .collect(); + histories.sort_by_key(|(_, sum)| *sum); + + for (id, sum) in histories { + let enabled = filterid.borrow().contains(&id); + + minrow(0.0, || { + if selectable_label_primary(enabled, &id.prototype().name) .clicked - { - if !enabled { - filterid.borrow_mut().insert(id); - } else { - filterid.borrow_mut().remove(&id); - } + { + if !enabled { + filterid.borrow_mut().insert(id); + } else { + filterid.borrow_mut().remove(&id); } - }); - let suffix = match hist_type { - HistoryType::Items => "", - HistoryType::Money => "$", - }; - padxy(5.0, 5.0, || { - textc( - on_primary_container(), - format!("{}{}", sum, suffix), - ); - }); - overall_total += sum; - } - if matches!(hist_type, HistoryType::Money) { - textc( - on_primary_container(), - format!("Total: {}$", overall_total), - ); - } - }); + } + }); + let suffix = match hist_type { + HistoryType::Items => "", + HistoryType::Money => "$", + }; + padxy(5.0, 5.0, || { + textc(on_primary_container(), format!("{}{}", sum, suffix)); + }); + overall_total += sum; + } + if matches!(hist_type, HistoryType::Money) { + textc( + on_primary_container(), + format!("Total: {}$", overall_total), + ); + } }); }); }); }); - }; - - match tab { - EconomyTab::ImportExports => { - let (label_left, label_right) = match hist_type { - HistoryType::Items => ("Imports", "Exports"), - HistoryType::Money => ("Expenses", "Income"), - }; - - constrained_viewport(|| { - let mut grid = CountGrid::col(2); - grid.main_axis_size = MainAxisSize::Min; - grid.show(|| { - padxy(5.0, 5.0, || textc(on_primary_container(), label_left)); - padxy(5.0, 5.0, || textc(on_primary_container(), label_right)); - - render_history(&ecostats.imports, hist_type); - render_history(&ecostats.exports, hist_type); - }); + }); + }; + + match tab { + EconomyTab::ImportExports => { + let (label_left, label_right) = match hist_type { + HistoryType::Items => ("Imports", "Exports"), + HistoryType::Money => ("Expenses", "Income"), + }; + + constrained_viewport(|| { + let mut grid = CountGrid::col(2); + grid.main_axis_size = MainAxisSize::Min; + grid.show(|| { + padxy(5.0, 5.0, || textc(on_primary_container(), label_left)); + padxy(5.0, 5.0, || textc(on_primary_container(), label_right)); + + render_history(&ecostats.imports, hist_type); + render_history(&ecostats.exports, hist_type); }); - } - EconomyTab::InternalTrade => { - render_history(&ecostats.internal_trade, HistoryType::Items); - } - EconomyTab::MarketPrices => { - render_market_prices(sim); - } + }); } - }, - ); + EconomyTab::InternalTrade => { + render_history(&ecostats.internal_trade, HistoryType::Items); + } + EconomyTab::MarketPrices => { + render_market_prices(sim); + } + } + }); } fn render_market_prices(sim: &Simulation) { diff --git a/native_app/src/newgui/hud/windows/mod.rs b/native_app/src/newgui/hud/windows/mod.rs index e8d471b3..5868ba24 100644 --- a/native_app/src/newgui/hud/windows/mod.rs +++ b/native_app/src/newgui/hud/windows/mod.rs @@ -33,12 +33,7 @@ impl GUIWindows { self.economy_open ^= true; } - if self.economy_open { - economy::economy(uiworld, sim); - } - - if self.settings_open { - settings::settings(uiworld, sim); - } + economy::economy(uiworld, sim, &mut self.economy_open); + settings::settings(uiworld, sim, &mut self.settings_open); } } diff --git a/native_app/src/newgui/hud/windows/settings.rs b/native_app/src/newgui/hud/windows/settings.rs index ce4a474a..8507f298 100644 --- a/native_app/src/newgui/hud/windows/settings.rs +++ b/native_app/src/newgui/hud/windows/settings.rs @@ -15,7 +15,6 @@ use goryak::{ use simulation::Simulation; use crate::game_loop::Timings; -use crate::gui::GuiState; use crate::inputmap::{Bindings, InputMap}; use crate::uiworld::UiWorld; @@ -119,249 +118,242 @@ impl Default for SettingsState { /// Settings window /// This window is used to change the settings of the game -pub fn settings(uiw: &UiWorld, _: &Simulation) { - uiw.window( - Window { - title: "Settings", - pad: Pad::all(10.0), - radius: 10.0, - }, - |uiw| { - uiw.write::().windows.settings_open = false; - }, - |uiw, _sim| { - profiling::scope!("gui::window::settings"); - - VertScroll::Percent(0.8).show(|| { - let mut l = List::column(); - l.item_spacing = 5.0; - l.main_axis_size = MainAxisSize::Min; - l.show(|| { - let mut settings = uiw.write::(); - let mut state = uiw.write::(); - let before = *settings; - - textc(on_secondary_container(), "Gameplay"); - minrow(5.0, || { - textc(on_secondary_container(), "Auto save every"); - let mut id = settings.auto_save_every as u8 as usize; - if combo_box( - &mut id, - &[ - AutoSaveEvery::Never.as_ref(), - AutoSaveEvery::OneMinute.as_ref(), - AutoSaveEvery::FiveMinutes.as_ref(), - ], - 200.0, - ) { - settings.auto_save_every = AutoSaveEvery::from(id as u8); - } - }); - - divider(outline(), 10.0, 1.0); - textc(on_secondary_container(), "Input"); - checkbox_value( - &mut settings.camera_border_move, - on_secondary_container(), - "Border screen camera movement", - ); - checkbox_value( - &mut settings.camera_smooth, - on_secondary_container(), - "Camera smooth", - ); - - if settings.camera_smooth { - minrow(5.0, || { - dragvalue() - .min(0.1) - .max(2.0) - .step(0.1) - .show(&mut settings.camera_smooth_tightness); - textc(on_secondary_container(), "Camera smoothing tightness"); - }); +pub fn settings(uiw: &UiWorld, _: &Simulation, opened: &mut bool) { + Window { + title: "Settings", + pad: Pad::all(10.0), + radius: 10.0, + opened, + } + .show(|| { + profiling::scope!("gui::window::settings"); + + VertScroll::Percent(0.8).show(|| { + let mut l = List::column(); + l.item_spacing = 5.0; + l.main_axis_size = MainAxisSize::Min; + l.show(|| { + let mut settings = uiw.write::(); + let mut state = uiw.write::(); + let before = *settings; + + textc(on_secondary_container(), "Gameplay"); + minrow(5.0, || { + textc(on_secondary_container(), "Auto save every"); + let mut id = settings.auto_save_every as u8 as usize; + if combo_box( + &mut id, + &[ + AutoSaveEvery::Never.as_ref(), + AutoSaveEvery::OneMinute.as_ref(), + AutoSaveEvery::FiveMinutes.as_ref(), + ], + 200.0, + ) { + settings.auto_save_every = AutoSaveEvery::from(id as u8); } + }); + divider(outline(), 10.0, 1.0); + textc(on_secondary_container(), "Input"); + checkbox_value( + &mut settings.camera_border_move, + on_secondary_container(), + "Border screen camera movement", + ); + checkbox_value( + &mut settings.camera_smooth, + on_secondary_container(), + "Camera smooth", + ); + + if settings.camera_smooth { minrow(5.0, || { dragvalue() - .min(2.0) - .max(179.0) - .step(1.0) - .show(&mut settings.camera_fov); - textc(on_secondary_container(), "Camera Field of View (FOV)"); + .min(0.1) + .max(2.0) + .step(0.1) + .show(&mut settings.camera_smooth_tightness); + textc(on_secondary_container(), "Camera smoothing tightness"); }); + } + + minrow(5.0, || { + dragvalue() + .min(2.0) + .max(179.0) + .step(1.0) + .show(&mut settings.camera_fov); + textc(on_secondary_container(), "Camera Field of View (FOV)"); + }); - // only update the fps every 300ms to avoid flickering - if state.fps == 0.0 || state.instant.elapsed() > Duration::from_millis(300) { - state.ms = uiw.read::().all.avg(); - state.fps = 1.0 / state.ms; - state.instant = Instant::now(); + // only update the fps every 300ms to avoid flickering + if state.fps == 0.0 || state.instant.elapsed() > Duration::from_millis(300) { + state.ms = uiw.read::().all.avg(); + state.fps = 1.0 / state.ms; + state.instant = Instant::now(); + } + + divider(outline(), 10.0, 1.0); + #[cfg(debug_assertions)] + textc( + on_secondary_container(), + "shouldn't be looking at FPS in debug mode! use --release", + ); + textc( + on_secondary_container(), + format!( + "Graphics - {:.1}FPS - {:.1}ms", + state.fps, + 1000.0 * state.ms + ), + ); + checkbox_value( + &mut settings.gfx.fullscreen, + on_secondary_container(), + "Fullscreen", + ); + checkbox_value( + &mut settings.gfx.terrain_grid, + on_secondary_container(), + "Terrain Grid", + ); + checkbox_value(&mut settings.gfx.fog, on_secondary_container(), "Fog"); + checkbox_value( + &mut settings.gfx.ssao, + on_secondary_container(), + "Ambient Occlusion (SSAO)", + ); + checkbox_value(&mut settings.gfx.vsync, on_secondary_container(), "VSync"); + + minrow(5.0, || { + let mut id = settings.gfx.shadows as u8 as usize; + if combo_box( + &mut id, + &[ + ShadowQuality::NoShadows.as_ref(), + ShadowQuality::Low.as_ref(), + ShadowQuality::Medium.as_ref(), + ShadowQuality::High.as_ref(), + ShadowQuality::Ultra.as_ref(), + ], + 200.0, + ) { + settings.gfx.shadows = ShadowQuality::from(id as u8); } + textc(on_secondary_container(), "Shadow Quality"); + }); - divider(outline(), 10.0, 1.0); - #[cfg(debug_assertions)] - textc( - on_secondary_container(), - "shouldn't be looking at FPS in debug mode! use --release", - ); - textc( - on_secondary_container(), - format!( - "Graphics - {:.1}FPS - {:.1}ms", - state.fps, - 1000.0 * state.ms - ), - ); - checkbox_value( - &mut settings.gfx.fullscreen, - on_secondary_container(), - "Fullscreen", - ); - checkbox_value( - &mut settings.gfx.terrain_grid, - on_secondary_container(), - "Terrain Grid", - ); - checkbox_value(&mut settings.gfx.fog, on_secondary_container(), "Fog"); - checkbox_value( - &mut settings.gfx.ssao, - on_secondary_container(), - "Ambient Occlusion (SSAO)", - ); - checkbox_value(&mut settings.gfx.vsync, on_secondary_container(), "VSync"); - - minrow(5.0, || { - let mut id = settings.gfx.shadows as u8 as usize; - if combo_box( - &mut id, - &[ - ShadowQuality::NoShadows.as_ref(), - ShadowQuality::Low.as_ref(), - ShadowQuality::Medium.as_ref(), - ShadowQuality::High.as_ref(), - ShadowQuality::Ultra.as_ref(), - ], - 200.0, - ) { - settings.gfx.shadows = ShadowQuality::from(id as u8); - } - textc(on_secondary_container(), "Shadow Quality"); - }); - - divider(outline(), 10.0, 1.0); - textc(on_secondary_container(), "GUI"); - minrow(5.0, || { - dragvalue().min(0.5).max(2.0).show(&mut settings.gui_scale); - textc(on_secondary_container(), "GUI Scale"); - }); - - divider(outline(), 10.0, 1.0); - textc(on_secondary_container(), "Audio"); - minrow(5.0, || { - dragvalue() - .min(0.0) - .max(100.0) - .step(1.0) - .show(&mut settings.master_volume_percent); - textc(on_secondary_container(), "Master volume"); - }); + divider(outline(), 10.0, 1.0); + textc(on_secondary_container(), "GUI"); + minrow(5.0, || { + dragvalue().min(0.5).max(2.0).show(&mut settings.gui_scale); + textc(on_secondary_container(), "GUI Scale"); + }); - minrow(5.0, || { - dragvalue() - .min(0.0) - .max(100.0) - .step(1.0) - .show(&mut settings.music_volume_percent); - textc(on_secondary_container(), "Music volume"); - }); + divider(outline(), 10.0, 1.0); + textc(on_secondary_container(), "Audio"); + minrow(5.0, || { + dragvalue() + .min(0.0) + .max(100.0) + .step(1.0) + .show(&mut settings.master_volume_percent); + textc(on_secondary_container(), "Master volume"); + }); - minrow(5.0, || { - dragvalue() - .min(0.0) - .max(100.0) - .step(1.0) - .show(&mut settings.effects_volume_percent); - textc(on_secondary_container(), "Effects volume"); - }); + minrow(5.0, || { + dragvalue() + .min(0.0) + .max(100.0) + .step(1.0) + .show(&mut settings.music_volume_percent); + textc(on_secondary_container(), "Music volume"); + }); - minrow(5.0, || { - dragvalue() - .min(0.0) - .max(100.0) - .step(1.0) - .show(&mut settings.ui_volume_percent); - textc(on_secondary_container(), "Ui volume"); - }); + minrow(5.0, || { + dragvalue() + .min(0.0) + .max(100.0) + .step(1.0) + .show(&mut settings.effects_volume_percent); + textc(on_secondary_container(), "Effects volume"); + }); - divider(outline(), 10.0, 1.0); - textc(on_secondary_container(), "Keybinds"); - let mut bindings = uiw.write::(); - if button_primary("Reset").show().clicked { - *bindings = Bindings::default(); - uiw.write::().build_input_tree(&mut bindings); - } + minrow(5.0, || { + dragvalue() + .min(0.0) + .max(100.0) + .step(1.0) + .show(&mut settings.ui_volume_percent); + textc(on_secondary_container(), "Ui volume"); + }); - let mut sorted_inps = bindings.0.keys().cloned().collect::>(); - sorted_inps.sort(); - - constrained( - Constraints::loose(Vec2::new(f32::INFINITY, 100000.0)), - || { - CountGrid::col(4) - .main_axis_size(MainAxisSize::Min) - .cross_axis_aligment(CrossAxisAlignment::Start) - .main_axis_align_items(MainAxisAlignItems::Center) - .show(|| { - for i in 0..sorted_inps.len() { - let action = &sorted_inps[i]; - let comb = bindings.0.get_mut(action).unwrap(); - padx(2.0, || { - textc(on_secondary_container(), action.to_string()); - }); - padx(2.0, || { - minrow(0.0, || { - if !comb.0.is_empty() { - button_primary(format!("{}", comb.0[0])).show(); - } else { - button_primary("").show(); - } - }); + divider(outline(), 10.0, 1.0); + textc(on_secondary_container(), "Keybinds"); + let mut bindings = uiw.write::(); + if button_primary("Reset").show().clicked { + *bindings = Bindings::default(); + uiw.write::().build_input_tree(&mut bindings); + } + + let mut sorted_inps = bindings.0.keys().cloned().collect::>(); + sorted_inps.sort(); + + constrained( + Constraints::loose(Vec2::new(f32::INFINITY, 100000.0)), + || { + CountGrid::col(4) + .main_axis_size(MainAxisSize::Min) + .cross_axis_aligment(CrossAxisAlignment::Start) + .main_axis_align_items(MainAxisAlignItems::Center) + .show(|| { + for i in 0..sorted_inps.len() { + let action = &sorted_inps[i]; + let comb = bindings.0.get_mut(action).unwrap(); + padx(2.0, || { + textc(on_secondary_container(), action.to_string()); + }); + padx(2.0, || { + minrow(0.0, || { + if !comb.0.is_empty() { + button_primary(format!("{}", comb.0[0])).show(); + } else { + button_primary("").show(); + } }); - padx(2.0, || { - minrow(0.0, || { - if comb.0.len() > 1 { - button_primary(format!("{}", comb.0[1])).show(); - } else { - button_primary("").show(); - } - }); + }); + padx(2.0, || { + minrow(0.0, || { + if comb.0.len() > 1 { + button_primary(format!("{}", comb.0[1])).show(); + } else { + button_primary("").show(); + } }); - padxy(8.0, 2.0, || { - minrow(0.0, || { - if icon_button(button_primary("arrows-rotate")) - .show() - .clicked - { - comb.0 = Bindings::default() - .0 - .remove(action) - .unwrap() - .0; - } - }); + }); + padxy(8.0, 2.0, || { + minrow(0.0, || { + if icon_button(button_primary("arrows-rotate")) + .show() + .clicked + { + comb.0 = + Bindings::default().0.remove(action).unwrap().0; + } }); - } - }); - }, - ); - - if *settings != before { - common::saveload::JSONPretty::save_silent(&*settings, SETTINGS_SAVE_NAME); - } - }); + }); + } + }); + }, + ); + + if *settings != before { + common::saveload::JSONPretty::save_silent(&*settings, SETTINGS_SAVE_NAME); + } }); - }, - ); + }); + }) } pub fn manage_settings(ctx: &mut engine::Context, settings: &Settings) { diff --git a/native_app/src/uiworld.rs b/native_app/src/uiworld.rs index d413d49d..c13a56cf 100644 --- a/native_app/src/uiworld.rs +++ b/native_app/src/uiworld.rs @@ -1,7 +1,5 @@ use crate::init::{INIT_FUNCS, SAVELOAD_FUNCS}; -use crate::newgui::window_display::WindowDisplay; use crate::newgui::TimeAlways; -use goryak::Window; use simulation::utils::resources::{RefMutSingle, RefSingle, ResourcesSingleThread}; use simulation::world_command::{WorldCommand, WorldCommands}; use simulation::{Simulation, SimulationReplayLoader}; @@ -72,16 +70,6 @@ impl UiWorld { self.write::() } - pub fn window( - &self, - window: Window, - on_close: impl FnOnce(&UiWorld) + 'static, - children: impl FnOnce(&UiWorld, &Simulation) + 'static, - ) { - let mut window_state = self.write::(); - window_state.show(window, children, on_close); - } - pub fn check_present(&mut self, res: fn() -> T) { self.resources.write_or_insert_with(res); }