summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-07-25 14:34:18 +0200
committermetamuffin <metamuffin@disroot.org>2024-07-25 14:34:18 +0200
commit16dbbba23e3534105707fbb861a1dce5d9ef2f0e (patch)
tree44b2f81349e22ff12ad9e36db1893a02455548c8
parentecb6ff15c24841dc08ab8f5c3b347c8080720ac4 (diff)
downloadhurrycurry-16dbbba23e3534105707fbb861a1dce5d9ef2f0e.tar
hurrycurry-16dbbba23e3534105707fbb861a1dce5d9ef2f0e.tar.bz2
hurrycurry-16dbbba23e3534105707fbb861a1dce5d9ef2f0e.tar.zst
button interact behavior
-rw-r--r--pixel-client/src/main.rs19
-rw-r--r--pixel-client/src/menu.rs29
-rw-r--r--pixel-client/src/ui.rs107
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) {