use console; use render; use ui; use settings; use std::sync::{Arc, Mutex}; pub fn new_submenu_button(text: &str, renderer: &mut render::Renderer, ui_container: &mut ui::Container, x: f64, y: f64) -> (ui::ElementRef, ui::ElementRef) { let (mut btn, mut txt) = super::new_button_text(renderer, text, x, y, 300.0, 40.0); btn.set_v_attach(ui::VAttach::Middle); btn.set_h_attach(ui::HAttach::Center); let ui_btn = ui_container.add(btn); txt.set_parent(&ui_btn); (ui_btn, ui_container.add(txt)) } pub fn new_centered_button(text: &str, renderer: &mut render::Renderer, ui_container: &mut ui::Container, y: f64, vertical_attach: ui::VAttach) -> (ui::ElementRef, ui::ElementRef) { let (mut btn, mut txt) = super::new_button_text(renderer, text, 0.0, y, 400.0, 40.0); btn.set_v_attach(vertical_attach); btn.set_h_attach(ui::HAttach::Center); let ui_btn = ui_container.add(btn); txt.set_parent(&ui_btn); (ui_btn, ui_container.add(txt)) } macro_rules! get_bool_str { ($fmt:expr, $val:expr, $val_true:expr, $val_false:expr) => (format!($fmt, if $val { $val_true } else { $val_false }).as_ref()); ($fmt:expr, $val:expr) => (get_bool_string!($fmt, $val, "true", "false")); } macro_rules! get_matched_str { ($fmt:expr, $val:expr, $($to_match:expr => $result:expr),*) => ( format!($fmt, match $val { $($to_match => $result.to_owned(), )* _ => $val.to_string(), }).as_ref() ) } pub struct UIElements { elements: ui::Collection, background: ui::ElementRef, } pub struct SettingsMenu { console: Arc>, elements: Option, show_disconnect_button: bool } impl SettingsMenu { pub fn new(console: Arc>, show_disconnect_button: bool) -> SettingsMenu { SettingsMenu { console: console, elements: None, show_disconnect_button: show_disconnect_button } } } impl super::Screen for SettingsMenu { fn on_active(&mut self, renderer: &mut render::Renderer, ui_container: &mut ui::Container) { let mut elements = ui::Collection::new(); let mut background = ui::Image::new( render::Renderer::get_texture(renderer.get_textures_ref(), "steven:solid"), 0.0, 0.0, 854.0, 480.0, 0.0, 0.0, 1.0, 1.0, 0, 0, 0 ); background.set_a(100); let background = elements.add(ui_container.add(background)); // From top and down let (btn_audio_settings, txt_audio_settings) = new_submenu_button("Audio settings...", renderer, ui_container, -160.0, -50.0); super::button_action(ui_container, btn_audio_settings.clone(), Some(txt_audio_settings.clone()), move |game, _| { game.screen_sys.add_screen(Box::new(AudioSettingsMenu::new(game.console.clone()))); }); elements.add(btn_audio_settings); elements.add(txt_audio_settings); let (btn_video_settings, txt_video_settings) = new_submenu_button("Video settings...", renderer, ui_container, 160.0, -50.0); super::button_action(ui_container, btn_video_settings.clone(), Some(txt_video_settings.clone()), move |game, _| { game.screen_sys.add_screen(Box::new(VideoSettingsMenu::new(game.console.clone()))); }); elements.add(btn_video_settings); elements.add(txt_video_settings); let (btn_controls_settings, txt_controls_settings) = new_submenu_button("Controls...", renderer, ui_container, 160.0, 0.0); super::button_action(ui_container, btn_controls_settings.clone(), Some(txt_controls_settings.clone()), move |_, _| { // TODO: Implement this... }); elements.add(btn_controls_settings); elements.add(txt_controls_settings); let (btn_locale_settings, txt_locale_settings) = new_submenu_button("Language...", renderer, ui_container, -160.0, 0.0); super::button_action(ui_container, btn_locale_settings.clone(), Some(txt_locale_settings.clone()), move |_, _| { // TODO: Implement this... }); elements.add(btn_locale_settings); elements.add(txt_locale_settings); // Center bottom items let (btn_back_to_game, txt_back_to_game) = new_centered_button("Done", renderer, ui_container, 50.0, ui::VAttach::Bottom); super::button_action(ui_container, btn_back_to_game.clone(), Some(txt_back_to_game.clone()), move |game, _| { game.screen_sys.pop_screen(); game.focused = true; }); elements.add(btn_back_to_game); elements.add(txt_back_to_game); if self.show_disconnect_button { let (btn_exit_game, txt_exit_game) = new_centered_button("Disconnect", renderer, ui_container, 100.0, ui::VAttach::Bottom); super::button_action(ui_container, btn_exit_game.clone(), Some(txt_exit_game.clone()), move |game, _| { game.server.disconnect(None); game.screen_sys.replace_screen(Box::new(super::ServerList::new(None))); }); elements.add(btn_exit_game); elements.add(txt_exit_game); } self.elements = Some(UIElements { elements: elements, background: background, }); } fn on_deactive(&mut self, _renderer: &mut render::Renderer, ui_container: &mut ui::Container) { { let elements = self.elements.as_mut().unwrap(); elements.elements.remove_all(ui_container); } self.elements = None; } // Called every frame the screen is active fn tick(&mut self, _delta: f64, renderer: &mut render::Renderer, ui_container: &mut ui::Container) -> Option> { let elements = self.elements.as_mut().unwrap(); { let mode = ui_container.mode; let background = ui_container.get_mut(&elements.background); background.set_width(match mode { ui::Mode::Unscaled(scale) => 854.0 / scale, ui::Mode::Scaled => renderer.width as f64, }); background.set_height(match mode { ui::Mode::Unscaled(scale) => 480.0 / scale, ui::Mode::Scaled => renderer.height as f64, }); } None } // Events fn on_scroll(&mut self, _x: f64, _y: f64) { } fn is_closable(&self) -> bool { true } } pub struct VideoSettingsMenu { console: Arc>, elements: Option, } impl VideoSettingsMenu { pub fn new(console: Arc>) -> VideoSettingsMenu { VideoSettingsMenu { console: console, elements: None, } } } impl super::Screen for VideoSettingsMenu { fn on_active(&mut self, renderer: &mut render::Renderer, ui_container: &mut ui::Container) { let mut elements = ui::Collection::new(); let mut background = ui::Image::new( render::Renderer::get_texture(renderer.get_textures_ref(), "steven:solid"), 0.0, 0.0, 854.0, 480.0, 0.0, 0.0, 1.0, 1.0, 0, 0, 0 ); background.set_a(100); let background = elements.add(ui_container.add(background)); // Load defaults let (r_max_fps, r_fov, r_vsync) = { let console = self.console.lock().unwrap(); ( console.get(settings::R_MAX_FPS).clone(), console.get(settings::R_FOV).clone(), console.get(settings::R_VSYNC).clone() ) }; // Setting buttons // TODO: Slider let (btn_fov, txt_fov) = new_submenu_button(get_matched_str!("FOV: {}", r_fov, 90 => "Normal", 110 => "Quake pro"), renderer, ui_container, -160.0, -50.0); elements.add(btn_fov); elements.add(txt_fov); let (btn_vsync, txt_vsync) = new_submenu_button(get_bool_str!("VSync: {}", r_vsync, "Enabled", "Disabled"), renderer, ui_container, -160.0, 0.0); elements.add(txt_vsync.clone()); super::button_action(ui_container, btn_vsync.clone(), Some(txt_vsync.clone()), move | game, ui_container | { let mut console = game.console.lock().unwrap(); let r_vsync = !console.get(settings::R_VSYNC); let txt_vsync = ui_container.get_mut(&txt_vsync); txt_vsync.set_text(&game.renderer, get_bool_str!("VSync: {}", r_vsync, "Enabled", "Disabled")); console.set(settings::R_VSYNC, r_vsync); }); elements.add(btn_vsync); // TODO: Slider let (btn_fps_cap, txt_fps_cap) = new_submenu_button(get_matched_str!("FPS cap: {}", r_max_fps, 0 => "Unlimited", 15 => "Potato"), renderer, ui_container, 160.0, 0.0); elements.add(btn_fps_cap); elements.add(txt_fps_cap); let (btn_done, txt_done) = new_centered_button("Done", renderer, ui_container, 50.0, ui::VAttach::Bottom); super::button_action(ui_container, btn_done.clone(), Some(txt_done.clone()), move | game, _ | { game.screen_sys.pop_screen(); }); elements.add(btn_done); elements.add(txt_done); self.elements = Some(UIElements { elements: elements, background: background, }); } fn on_deactive(&mut self, _renderer: &mut render::Renderer, ui_container: &mut ui::Container) { { let elements = self.elements.as_mut().unwrap(); elements.elements.remove_all(ui_container); } self.elements = None; } // Called every frame the screen is active fn tick(&mut self, _delta: f64, renderer: &mut render::Renderer, ui_container: &mut ui::Container) -> Option> { let elements = self.elements.as_mut().unwrap(); { let mode = ui_container.mode; let background = ui_container.get_mut(&elements.background); background.set_width(match mode { ui::Mode::Unscaled(scale) => 854.0 / scale, ui::Mode::Scaled => renderer.width as f64, }); background.set_height(match mode { ui::Mode::Unscaled(scale) => 480.0 / scale, ui::Mode::Scaled => renderer.height as f64, }); } None } // Events fn on_scroll(&mut self, _x: f64, _y: f64) { } fn is_closable(&self) -> bool { true } } pub struct AudioSettingsMenu { console: Arc>, elements: Option } impl AudioSettingsMenu { pub fn new(console: Arc>) -> AudioSettingsMenu { AudioSettingsMenu { console: console, elements: None } } } impl super::Screen for AudioSettingsMenu { fn on_active(&mut self, renderer: &mut render::Renderer, ui_container: &mut ui::Container) { let mut elements = ui::Collection::new(); let mut background = ui::Image::new( render::Renderer::get_texture(renderer.get_textures_ref(), "steven:solid"), 0.0, 0.0, 854.0, 480.0, 0.0, 0.0, 1.0, 1.0, 0, 0, 0 ); background.set_a(100); let background = elements.add(ui_container.add(background)); let master_volume = { let console = self.console.lock().unwrap(); (console.get(settings::CL_MASTER_VOLUME).clone()) }; let (btn_master_volume, txt_master_volume) = new_centered_button(master_volume.to_string().as_ref(), renderer, ui_container, -150.0, ui::VAttach::Middle); elements.add(btn_master_volume); elements.add(txt_master_volume); let (btn_done, txt_done) = new_centered_button("Done", renderer, ui_container, 50.0, ui::VAttach::Bottom); super::button_action(ui_container, btn_done.clone(), Some(txt_done.clone()), move | game, _ | { game.screen_sys.pop_screen(); }); elements.add(btn_done); elements.add(txt_done); self.elements = Some(UIElements { elements: elements, background: background, }); } fn on_deactive(&mut self, _renderer: &mut render::Renderer, ui_container: &mut ui::Container) { { let elements = self.elements.as_mut().unwrap(); elements.elements.remove_all(ui_container); } self.elements = None; } // Called every frame the screen is active fn tick(&mut self, _delta: f64, renderer: &mut render::Renderer, ui_container: &mut ui::Container) -> Option> { let elements = self.elements.as_mut().unwrap(); { let mode = ui_container.mode; let background = ui_container.get_mut(&elements.background); background.set_width(match mode { ui::Mode::Unscaled(scale) => 854.0 / scale, ui::Mode::Scaled => renderer.width as f64, }); background.set_height(match mode { ui::Mode::Unscaled(scale) => 480.0 / scale, ui::Mode::Scaled => renderer.height as f64, }); } None } // Events fn on_scroll(&mut self, _x: f64, _y: f64) { } fn is_closable(&self) -> bool { true } }