diff options
Diffstat (limited to 'pixel-client/src/ui.rs')
-rw-r--r-- | pixel-client/src/ui.rs | 107 |
1 files changed, 102 insertions, 5 deletions
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) { |