diff options
-rw-r--r-- | pixel-client/src/main.rs | 19 | ||||
-rw-r--r-- | pixel-client/src/menu.rs | 29 | ||||
-rw-r--r-- | pixel-client/src/ui.rs | 107 |
3 files changed, 144 insertions, 11 deletions
diff --git a/pixel-client/src/main.rs b/pixel-client/src/main.rs index b072a7e0..247cd636 100644 --- a/pixel-client/src/main.rs +++ b/pixel-client/src/main.rs @@ -25,6 +25,7 @@ use render::Renderer; use sdl2::{ event::Event, keyboard::{KeyboardState, Keycode}, + mouse::MouseState, pixels::Color, }; use std::time::{Duration, Instant}; @@ -106,10 +107,12 @@ fn main() { renderer.size = Vec2::new(width as f32, height as f32); let keyboard = KeyboardState::new(&events); + let mouse = MouseState::new(&events); + let dt = last_tick.elapsed().min(Duration::from_secs_f32(1. / 30.)); match &mut state { State::Ingame(x) => x.tick(dt.as_secs_f32(), &keyboard, renderer.atlas_layout()), - State::Menu(x) => x.tick(dt.as_secs_f32(), &keyboard, renderer.atlas_layout()), + State::Menu(x) => x.tick(dt.as_secs_f32(), &keyboard, &mouse, renderer.atlas_layout()), } last_tick += dt; @@ -132,6 +135,20 @@ fn main() { keycode: Option::Some(Keycode::Escape), .. } => break 'mainloop, + Event::KeyUp { + keycode: Some(keycode), + .. + } => match &mut state { + State::Ingame(_) => (), + State::Menu(menu) => menu.keyboard_event(keycode, false), + }, + Event::KeyDown { + keycode: Some(keycode), + .. + } => match &mut state { + State::Ingame(_) => (), + State::Menu(menu) => menu.keyboard_event(keycode, true), + }, _ => {} } } diff --git a/pixel-client/src/menu.rs b/pixel-client/src/menu.rs index 0d63d4e7..6c382331 100644 --- a/pixel-client/src/menu.rs +++ b/pixel-client/src/menu.rs @@ -8,7 +8,10 @@ use hurrycurry_protocol::{ TileIndex, }; use rand::{random, seq::IndexedRandom, thread_rng}; -use sdl2::keyboard::KeyboardState; +use sdl2::{ + keyboard::{KeyboardState, Keycode}, + mouse::MouseState, +}; #[derive(Debug)] pub struct Menu { @@ -55,9 +58,19 @@ impl Menu { background: Vec2::ZERO, } } - pub fn tick(&mut self, dt: f32, _keyboard: &KeyboardState, _layout: &AtlasLayout) { + pub fn tick( + &mut self, + dt: f32, + keyboard: &KeyboardState, + mouse: &MouseState, + _layout: &AtlasLayout, + ) { self.fade_in = (self.fade_in + dt).min(1.); self.background += Vec2::new(2., 3.) * dt; + self.ui_state.update(keyboard, mouse, dt); + } + pub fn keyboard_event(&mut self, keycode: Keycode, down: bool) { + self.ui_state.keyboard_event(keycode, down); } pub fn draw(&mut self, ctx: &mut Renderer) { ctx.set_world_view( @@ -85,9 +98,15 @@ impl Menu { self.map.draw(ctx); self.ui_state.draw(ctx, |ui| { - ui.button("Join"); - ui.button("Settings"); - ui.button("Quit"); + if ui.button("Join") { + eprintln!("join button") + } + if ui.button("Settings") { + eprintln!("settings button") + } + if ui.button("Quit") { + eprintln!("quit button") + } }); ctx.draw_ui(SpriteDraw::overlay( diff --git a/pixel-client/src/ui.rs b/pixel-client/src/ui.rs index 557800aa..5ac1a79f 100644 --- a/pixel-client/src/ui.rs +++ b/pixel-client/src/ui.rs @@ -1,29 +1,91 @@ -use crate::render::Renderer; -use hurrycurry_protocol::glam::Vec2; +use crate::render::{sprite::SpriteDraw, Renderer}; +use hurrycurry_protocol::glam::{IVec2, Vec2}; +use sdl2::{ + keyboard::{KeyboardState, Keycode, Scancode}, + mouse::MouseState, +}; + +#[derive(Debug, Default)] +pub struct FocusDevice { + focus: usize, + pressing: Option<usize>, + interact_just_pressed: bool, + interact_just_released: bool, + interact_down: bool, +} #[derive(Default, Debug)] pub struct UiState { - focus: usize, + mouse_position: Vec2, + ui_scale: Vec2, + + keyboard_focus: FocusDevice, + mouse_focus: FocusDevice, } pub struct Ui<'a, 'b> { cursor: Vec2, cross_height: f32, + index: usize, direction_horizontal: bool, renderer: &'a mut Renderer<'b>, state: &'a mut UiState, } impl UiState { + pub fn update(&mut self, keyboard: &KeyboardState, mouse: &MouseState, _dt: f32) { + self.mouse_position = IVec2::new(mouse.x(), mouse.y()).as_vec2() / self.ui_scale; + + self.mouse_focus.update(mouse.left()); + self.keyboard_focus + .update(keyboard.is_scancode_pressed(Scancode::Space)); + } + pub fn keyboard_event(&mut self, keycode: Keycode, down: bool) { + if down { + match keycode { + Keycode::DOWN => self.keyboard_focus.focus += 1, + Keycode::UP if self.keyboard_focus.focus > 0 => self.keyboard_focus.focus -= 1, + _ => (), + } + } + } + pub fn draw(&mut self, renderer: &mut Renderer, ui: impl FnOnce(&mut Ui)) { + self.ui_scale = renderer.ui_scale; + self.mouse_focus.focus = usize::MAX; let mut u = Ui { cursor: Vec2::ZERO, direction_horizontal: false, renderer, state: self, cross_height: 0., + index: 0, }; ui(&mut u); + + if self.mouse_focus.interact_just_released { + self.mouse_focus.pressing = None; + } + if self.keyboard_focus.interact_just_released { + self.keyboard_focus.pressing = None; + } + } +} + +impl FocusDevice { + pub fn update(&mut self, interact: bool) { + self.interact_just_pressed = interact && !self.interact_down; + self.interact_just_released = !interact && self.interact_down; + self.interact_down = interact; + } + pub fn element(&mut self, index: usize) -> (bool, bool, bool) { + let focus = self.focus == index; + if focus && self.interact_just_pressed { + self.pressing = Some(index) + }; + let pressing = self.pressing == Some(index); + let released = self.interact_just_released && pressing && focus; + (focus, pressing, released) } } @@ -33,9 +95,44 @@ impl<'a, 'b> Ui<'a, 'b> { self.advance(size); } pub fn button(&mut self, label: &str) -> bool { - let size = self.renderer.draw_text(self.cursor, label); + let c = self.cursor; + let margin = Vec2::splat(2.); + let size = self.renderer.draw_text(self.cursor + margin, label) + margin + margin; + + self.index += 1; + + let mouse_rel = self.state.mouse_position - c; + if mouse_rel.x >= 0. && mouse_rel.y >= 0. && mouse_rel.x < size.x && mouse_rel.y < size.y { + self.state.mouse_focus.focus = self.index; + } + + let (focus, pressing, released) = { + let (mfocus, mpressing, mreleased) = self.state.mouse_focus.element(self.index); + let (kfocus, kpressing, kreleased) = self.state.keyboard_focus.element(self.index); + ( + mfocus || kfocus, + mpressing || kpressing, + mreleased || kreleased, + ) + }; + + let l = if pressing { + 100 + } else if focus { + 50 + } else { + 30 + }; + self.renderer.draw_ui(SpriteDraw::screen( + self.renderer.misc_textures.solid, + i32::MAX - 1, + c, + size, + Some([l, l, l, 200]), + )); + self.advance(size); - false + released } pub fn advance(&mut self, size: Vec2) { |