mirror of
https://github.com/danbulant/cushy
synced 2026-06-18 22:11:34 +00:00
Finished mouse handling for tile map
This commit is contained in:
parent
273aac65bb
commit
66fd9ba766
3 changed files with 98 additions and 40 deletions
|
|
@ -67,7 +67,7 @@ fn main() -> gooey::Result {
|
|||
|
||||
let one_second_movement = direction * TILE_SIZE.into_float();
|
||||
|
||||
let cursor_pos = input.mouse.pos;
|
||||
let cursor_pos = input.mouse.as_ref().map(|mouse| mouse.position);
|
||||
|
||||
layers.map_mut(|layers| {
|
||||
let pos = &mut layers.1[myself].position;
|
||||
|
|
@ -76,21 +76,16 @@ fn main() -> gooey::Result {
|
|||
one_second_movement.y * elapsed.as_secs_f32(),
|
||||
);
|
||||
|
||||
let rect = Rect::new(*pos, Size::new(16., 16.));
|
||||
let color = match rect.cast().contains(cursor_pos) {
|
||||
true => Color::RED,
|
||||
false => Color::BLUE,
|
||||
};
|
||||
let rect = Rect::new(*pos - Size::squared(8.), Size::squared(16.));
|
||||
layers.1[myself].color =
|
||||
match cursor_pos.map_or(false, |cursor_pos| rect.cast().contains(cursor_pos)) {
|
||||
true => Color::RED,
|
||||
false => Color::BLUE,
|
||||
};
|
||||
});
|
||||
}));
|
||||
|
||||
Stack::rows(
|
||||
tilemap
|
||||
.debug_output(debug_message.clone())
|
||||
.expand()
|
||||
.and(Label::new(debug_message)),
|
||||
)
|
||||
.run()
|
||||
Stack::rows(tilemap.expand().and(Label::new(debug_message))).run()
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
|||
47
src/tick.rs
47
src/tick.rs
|
|
@ -3,10 +3,11 @@ use std::sync::atomic::{AtomicUsize, Ordering};
|
|||
use std::sync::{Arc, Mutex, MutexGuard};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use kludgine::app::winit::event::KeyEvent;
|
||||
use intentional::Assert;
|
||||
use kludgine::app::winit::event::{ElementState, KeyEvent, MouseButton};
|
||||
use kludgine::app::winit::keyboard::Key;
|
||||
use kludgine::figures::Point;
|
||||
use kludgine::figures::units::Px;
|
||||
use kludgine::figures::Point;
|
||||
|
||||
use crate::context::WidgetContext;
|
||||
use crate::utils::{IgnorePoison, UnwindsafeCondvar};
|
||||
|
|
@ -51,9 +52,38 @@ impl Tick {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn set_cursor_position(&self, pos: Point<Px>) {
|
||||
/// Sets the cursor position.
|
||||
pub fn set_cursor_position(&self, pos: Option<Point<Px>>) {
|
||||
let mut state = self.data.state();
|
||||
state.input.mouse.pos = pos;
|
||||
match pos {
|
||||
Some(pos) => {
|
||||
if state.input.mouse.is_none() {
|
||||
state.input.mouse = Some(Mouse::default());
|
||||
}
|
||||
|
||||
state
|
||||
.input
|
||||
.mouse
|
||||
.as_mut()
|
||||
.assert("always initialized")
|
||||
.position = pos;
|
||||
}
|
||||
None => {
|
||||
state.input.mouse = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Processes a mouse button event.
|
||||
pub fn mouse_button(&self, button: MouseButton, button_state: ElementState) {
|
||||
let mut state = self.data.state();
|
||||
if let Some(mouse) = &mut state.input.mouse {
|
||||
if button_state.is_pressed() {
|
||||
mouse.buttons.insert(button);
|
||||
} else {
|
||||
mouse.buttons.remove(&button);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a new tick that invokes `tick`, aiming to repeat at the given
|
||||
|
|
@ -70,7 +100,6 @@ impl Tick {
|
|||
keep_running: true,
|
||||
frame: 0,
|
||||
input: InputState::default(),
|
||||
mouse: None,
|
||||
}),
|
||||
period: tick_every,
|
||||
sync: UnwindsafeCondvar::new(),
|
||||
|
|
@ -119,15 +148,16 @@ impl Tick {
|
|||
pub struct InputState {
|
||||
/// A collection of all keys currently pressed.
|
||||
pub keys: HashSet<Key>,
|
||||
pub mouse: Mouse,
|
||||
/// The state of the mouse cursor and any buttons pressed.
|
||||
pub mouse: Option<Mouse>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Mouse {
|
||||
pub pos: Point<Px>,
|
||||
pub position: Point<Px>,
|
||||
pub buttons: HashSet<MouseButton>,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TickData {
|
||||
state: Mutex<TickState>,
|
||||
|
|
@ -150,7 +180,6 @@ struct TickState {
|
|||
keep_running: bool,
|
||||
frame: usize,
|
||||
input: InputState,
|
||||
mouse: Option<Mouse>,
|
||||
}
|
||||
|
||||
fn tick_loop<F>(data: &TickData, mut tick: F)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
use std::fmt::Debug;
|
||||
|
||||
use intentional::Cast;
|
||||
use kludgine::app::winit::event::ElementState;
|
||||
use kludgine::app::winit::window::CursorIcon;
|
||||
use kludgine::figures::units::Px;
|
||||
use kludgine::figures::Point;
|
||||
|
||||
|
|
@ -23,7 +25,6 @@ pub struct TileMap<Layers> {
|
|||
focus: Value<TileMapFocus>,
|
||||
zoom: f32,
|
||||
tick: Option<Tick>,
|
||||
debug_output: Option<Dynamic<String>>,
|
||||
}
|
||||
|
||||
impl<Layers> TileMap<Layers> {
|
||||
|
|
@ -33,15 +34,9 @@ impl<Layers> TileMap<Layers> {
|
|||
focus: Value::default(),
|
||||
zoom: 1.,
|
||||
tick: None,
|
||||
debug_output: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn debug_output(mut self, message: Dynamic<String>) -> Self {
|
||||
self.debug_output = Some(message);
|
||||
self
|
||||
}
|
||||
|
||||
/// Returns a new tilemap that contains dynamic layers.
|
||||
pub fn dynamic(layers: Dynamic<Layers>) -> Self {
|
||||
Self::construct(Value::Dynamic(layers))
|
||||
|
|
@ -126,20 +121,32 @@ where
|
|||
HANDLED
|
||||
}
|
||||
|
||||
fn hover(&mut self, local: Point<Px>, context: &mut EventContext<'_, '_>) {
|
||||
let Some(size) = context.last_layout().map(|rect| rect.size) else { return };
|
||||
|
||||
let offset = self.layers.map(|layers| self.focus.get().world_coordinate(layers));
|
||||
|
||||
let scale = context.kludgine.scale();
|
||||
let zoom = self.zoom;
|
||||
let world = tilemap::translate_coordinates(local, offset, scale, zoom, size);
|
||||
|
||||
fn hover(
|
||||
&mut self,
|
||||
local: Point<Px>,
|
||||
context: &mut EventContext<'_, '_>,
|
||||
) -> Option<CursorIcon> {
|
||||
if let Some(tick) = &self.tick {
|
||||
tick.set_cursor_position(world);
|
||||
let Some(size) = context.last_layout().map(|rect| rect.size) else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let world =
|
||||
tilemap::translate_coordinates(local, context.kludgine.scale(), self.zoom, size);
|
||||
let offset = self
|
||||
.layers
|
||||
.map(|layers| self.focus.get().world_coordinate(layers));
|
||||
|
||||
tick.set_cursor_position(Some(world + offset));
|
||||
}
|
||||
|
||||
self.debug_output.as_ref().unwrap().set(format!("world: {world:?} | local: {local:?}"));
|
||||
None
|
||||
}
|
||||
|
||||
fn unhover(&mut self, _context: &mut EventContext<'_, '_>) {
|
||||
if let Some(tick) = &self.tick {
|
||||
tick.set_cursor_position(None);
|
||||
}
|
||||
}
|
||||
|
||||
fn keyboard_input(
|
||||
|
|
@ -155,4 +162,31 @@ where
|
|||
|
||||
IGNORED
|
||||
}
|
||||
|
||||
fn mouse_down(
|
||||
&mut self,
|
||||
_location: Point<Px>,
|
||||
_device_id: DeviceId,
|
||||
button: kludgine::app::winit::event::MouseButton,
|
||||
_context: &mut EventContext<'_, '_>,
|
||||
) -> EventHandling {
|
||||
if let Some(tick) = &self.tick {
|
||||
tick.mouse_button(button, ElementState::Pressed);
|
||||
HANDLED
|
||||
} else {
|
||||
IGNORED
|
||||
}
|
||||
}
|
||||
|
||||
fn mouse_up(
|
||||
&mut self,
|
||||
_location: Option<Point<Px>>,
|
||||
_device_id: DeviceId,
|
||||
button: kludgine::app::winit::event::MouseButton,
|
||||
_context: &mut EventContext<'_, '_>,
|
||||
) {
|
||||
if let Some(tick) = &self.tick {
|
||||
tick.mouse_button(button, ElementState::Released);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue