From fd362c73414feb0ed394c1985b730d6f4ed4d71e Mon Sep 17 00:00:00 2001 From: Togglebit Date: Tue, 14 Nov 2023 08:06:08 +0100 Subject: [PATCH 1/5] world coords and hover state for tilemap (this is very much debug) --- Cargo.lock | 52 +++++++++++++++++------------------------- Cargo.toml | 2 +- examples/tilemap.rs | 15 ++++++++---- src/widgets/tilemap.rs | 32 ++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 52bf4e2..e03d92d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -96,7 +96,7 @@ dependencies = [ [[package]] name = "appit" version = "0.1.0" -source = "git+https://github.com/khonsulabs/appit#043bfe2c78524d6a06ed159289ea1cd7a62b0fec" +source = "git+https://github.com/khonsulabs/appit#5ed0d923ded6520950d14b3b869cbcac89452f5c" dependencies = [ "raw-window-handle 0.5.2", "winit", @@ -262,11 +262,10 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.0.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "0f8e7c90afad890484a21653d08b6e209ae34770fb5ee298f9c699fcc1e5c856" dependencies = [ - "jobserver", "libc", ] @@ -437,9 +436,9 @@ dependencies = [ [[package]] name = "etagere" -version = "0.2.9" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf70b9ea3a235a7432b4f481854815e2d4fb2fe824c1f5fb09b8985dd06b3e9" +checksum = "fcf22f748754352918e082e0039335ee92454a5d62bcaf69b5e8daf5907d9644" dependencies = [ "euclid", "svg_fmt", @@ -457,7 +456,7 @@ dependencies = [ [[package]] name = "figures" version = "0.1.0" -source = "git+https://github.com/khonsulabs/figures#f5b9ca5cf181b748897b269ad47d7a9f2d1f3eac" +source = "git+https://github.com/khonsulabs/figures#7b41393c44d4def606790e340c98450b603010b4" dependencies = [ "bytemuck", "euclid", @@ -811,15 +810,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" -[[package]] -name = "jobserver" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" -dependencies = [ - "libc", -] - [[package]] name = "js-sys" version = "0.3.65" @@ -855,7 +845,7 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" [[package]] name = "kludgine" version = "0.1.0" -source = "git+https://github.com/khonsulabs/kludgine#fd2078efb7212db0f07120b80440699b00ec2a2b" +source = "git+https://github.com/khonsulabs/kludgine#09790aafb5a9c3b0da034387adead9960eb06bc7" dependencies = [ "ahash", "alot", @@ -923,9 +913,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" [[package]] name = "lock_api" @@ -1464,9 +1454,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.38.21" +version = "0.38.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +checksum = "80109a168d9bc0c7f483083244543a6eb0dba02295d33ca268145e6190d6df0c" dependencies = [ "bitflags 2.4.1", "errno", @@ -1528,9 +1518,9 @@ dependencies = [ [[package]] name = "self_cell" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c309e515543e67811222dbc9e3dd7e1056279b782e1dacffe4242b718734fb6" +checksum = "e388332cd64eb80cd595a00941baf513caffae8dce9cfd0467fc9c66397dade6" [[package]] name = "serde" @@ -1572,9 +1562,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "smithay-client-toolkit" @@ -1676,9 +1666,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" dependencies = [ "winapi-util", ] @@ -1804,9 +1794,9 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.4" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ "log", "once_cell", @@ -1815,9 +1805,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "nu-ansi-term", "sharded-slab", diff --git a/Cargo.toml b/Cargo.toml index 784adb7..4ab496e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ tracing-subscriber = { version = "0.3", optional = true } # [patch."https://github.com/khonsulabs/kludgine"] -# kludgine = { path = "../kludgine2" } +# kludgine = { path = "../kludgine" } # [patch."https://github.com/khonsulabs/appit"] # appit = { path = "../appit" } # [patch."https://github.com/khonsulabs/figures"] diff --git a/examples/tilemap.rs b/examples/tilemap.rs index 54f7ad7..79a5ee4 100644 --- a/examples/tilemap.rs +++ b/examples/tilemap.rs @@ -6,7 +6,8 @@ use gooey::kludgine::shapes::Shape; use gooey::kludgine::tilemap::{Object, ObjectLayer, TileKind, TileMapFocus, Tiles, TILE_SIZE}; use gooey::kludgine::Color; use gooey::value::Dynamic; -use gooey::widgets::TileMap; +use gooey::widget::MakeWidget; +use gooey::widgets::{TileMap, Label, Stack}; use gooey::{Run, Tick}; const PLAYER_SIZE: Px = Px(16); @@ -37,12 +38,17 @@ fn main() -> gooey::Result { let layers = Dynamic::new((Tiles::new(8, 8, TILES), characters)); - TileMap::dynamic(layers.clone()) + let debug_message = Dynamic::new(String::new()); + + let tilemap = TileMap::dynamic(layers.clone()) .focus_on(TileMapFocus::Object { layer: 1, id: myself, }) .tick(Tick::times_per_second(60, move |elapsed, input| { + // get mouse cursor position and subsequently get the object under + // the mouse + let mut direction = Point::new(0., 0.); if input.keys.contains(&Key::ArrowDown) { direction.y += 1.0; @@ -65,8 +71,9 @@ fn main() -> gooey::Result { one_second_movement.y * elapsed.as_secs_f32(), ) }); - })) - .run() + })); + + Stack::rows(tilemap.debug_output(debug_message.clone()).expand().and(Label::new(debug_message))).run() } #[derive(Debug)] diff --git a/src/widgets/tilemap.rs b/src/widgets/tilemap.rs index 9d60893..ed1e393 100644 --- a/src/widgets/tilemap.rs +++ b/src/widgets/tilemap.rs @@ -1,6 +1,8 @@ use std::fmt::Debug; use intentional::Cast; +use kludgine::figures::units::Px; +use kludgine::figures::Point; use crate::context::{EventContext, GraphicsContext, LayoutContext}; use crate::kludgine::app::winit::event::{DeviceId, KeyEvent, MouseScrollDelta, TouchPhase}; @@ -21,6 +23,7 @@ pub struct TileMap { focus: Value, zoom: f32, tick: Option, + debug_output: Option>, } impl TileMap { @@ -30,9 +33,15 @@ impl TileMap { focus: Value::default(), zoom: 1., tick: None, + debug_output: None, } } + pub fn debug_output(mut self, message: Dynamic) -> Self { + self.debug_output = Some(message); + self + } + /// Returns a new tilemap that contains dynamic layers. pub fn dynamic(layers: Dynamic) -> Self { Self::construct(Value::Dynamic(layers)) @@ -104,6 +113,29 @@ where HANDLED } + fn hover(&mut self, local: Point, context: &mut EventContext<'_, '_>) { + // translate location to local location + // * effective zoom + + 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); + + self.debug_output.as_ref().unwrap().set(format!("world: {world:?} | local: {local:?}")); + } + + fn hit_test(&mut self, _: Point, _: &mut EventContext<'_, '_>) -> bool { + true + } + + fn accept_focus(&mut self, context: &mut EventContext<'_, '_>) -> bool { + true + } + fn keyboard_input( &mut self, _device_id: DeviceId, From 36895c38972fc9fd020e62a054842c0ec1164988 Mon Sep 17 00:00:00 2001 From: Togglebit Date: Tue, 14 Nov 2023 08:21:29 +0100 Subject: [PATCH 2/5] removed dep as we only needed it in the lock file --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 2e39955..f8dbfa8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,6 @@ interner = "0.2.1" kempt = "0.2.1" intentional = "0.1.0" tracing = "0.1.40" -rustix = "=0.38.21" tracing-subscriber = { version = "0.3", optional = true, features = [ "env-filter", From 1d80f8467cc2ee78ac00d7547316c0a0c8954c84 Mon Sep 17 00:00:00 2001 From: Togglebit Date: Tue, 14 Nov 2023 08:23:09 +0100 Subject: [PATCH 3/5] removed comment --- Cargo.lock | 1 - src/widgets/tilemap.rs | 3 --- 2 files changed, 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6f21fcc..8ac28ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -728,7 +728,6 @@ dependencies = [ "kludgine", "palette", "pollster", - "rustix", "tracing", "tracing-subscriber", ] diff --git a/src/widgets/tilemap.rs b/src/widgets/tilemap.rs index 8d51816..adf75af 100644 --- a/src/widgets/tilemap.rs +++ b/src/widgets/tilemap.rs @@ -127,9 +127,6 @@ where } fn hover(&mut self, local: Point, context: &mut EventContext<'_, '_>) { - // translate location to local location - // * effective zoom - let Some(size) = context.last_layout().map(|rect| rect.size) else { return }; let offset = self.layers.map(|layers| self.focus.get().world_coordinate(layers)); From fa56922594cc25689dea58234dbc30b36c351cae Mon Sep 17 00:00:00 2001 From: Togglebit Date: Tue, 14 Nov 2023 08:51:57 +0100 Subject: [PATCH 4/5] try to update the player colour based on mouse position (currently not working) --- examples/tilemap.rs | 16 ++++++++++++---- src/tick.rs | 16 ++++++++++++++++ src/widgets/tilemap.rs | 4 ++++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/examples/tilemap.rs b/examples/tilemap.rs index 79a5ee4..7dbfec1 100644 --- a/examples/tilemap.rs +++ b/examples/tilemap.rs @@ -46,8 +46,7 @@ fn main() -> gooey::Result { id: myself, }) .tick(Tick::times_per_second(60, move |elapsed, input| { - // get mouse cursor position and subsequently get the object under - // the mouse + // get mouse cursor position and subsequently get the object under the cursor let mut direction = Point::new(0., 0.); if input.keys.contains(&Key::ArrowDown) { @@ -65,11 +64,20 @@ fn main() -> gooey::Result { let one_second_movement = direction * TILE_SIZE.0 as f32; + let cursor_pos = input.mouse.pos; + layers.map_mut(|layers| { - layers.1[myself].position += Point::new( + let pos = &mut layers.1[myself].position; + *pos += Point::new( one_second_movement.x * elapsed.as_secs_f32(), 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, + }; }); })); diff --git a/src/tick.rs b/src/tick.rs index d57ed02..b1978da 100644 --- a/src/tick.rs +++ b/src/tick.rs @@ -5,6 +5,8 @@ use std::time::{Duration, Instant}; use kludgine::app::winit::event::KeyEvent; use kludgine::app::winit::keyboard::Key; +use kludgine::figures::Point; +use kludgine::figures::units::Px; use crate::context::WidgetContext; use crate::value::Dynamic; @@ -48,6 +50,11 @@ impl Tick { } } + pub fn set_cursor_position(&self, pos: Point) { + let mut state = self.data.state(); + state.input.mouse.pos = pos; + } + /// Returns a new tick that invokes `tick`, aiming to repeat at the given /// duration. pub fn new(tick_every: Duration, tick: F) -> Self @@ -62,6 +69,7 @@ impl Tick { keep_running: true, frame: 0, input: InputState::default(), + mouse: None, }), period: tick_every, sync: Condvar::new(), @@ -110,8 +118,15 @@ impl Tick { pub struct InputState { /// A collection of all keys currently pressed. pub keys: HashSet, + pub mouse: Mouse, } +#[derive(Debug, Default)] +pub struct Mouse { + pub pos: Point, +} + + #[derive(Debug)] struct TickData { state: Mutex, @@ -136,6 +151,7 @@ struct TickState { keep_running: bool, frame: usize, input: InputState, + mouse: Option, } fn tick_loop(data: &TickData, mut tick: F) diff --git a/src/widgets/tilemap.rs b/src/widgets/tilemap.rs index adf75af..f662e7d 100644 --- a/src/widgets/tilemap.rs +++ b/src/widgets/tilemap.rs @@ -135,6 +135,10 @@ where let zoom = self.zoom; let world = tilemap::translate_coordinates(local, offset, scale, zoom, size); + if let Some(tick) = &self.tick { + tick.set_cursor_position(world); + } + self.debug_output.as_ref().unwrap().set(format!("world: {world:?} | local: {local:?}")); } From 66fd9ba7667ea6fdb3b0c588239ad1253ba8aad7 Mon Sep 17 00:00:00 2001 From: Jonathan Johnson Date: Sun, 26 Nov 2023 19:31:03 -0800 Subject: [PATCH 5/5] Finished mouse handling for tile map --- examples/tilemap.rs | 21 +++++-------- src/tick.rs | 47 ++++++++++++++++++++++------ src/widgets/tilemap.rs | 70 +++++++++++++++++++++++++++++++----------- 3 files changed, 98 insertions(+), 40 deletions(-) diff --git a/examples/tilemap.rs b/examples/tilemap.rs index f00f928..28938f5 100644 --- a/examples/tilemap.rs +++ b/examples/tilemap.rs @@ -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)] diff --git a/src/tick.rs b/src/tick.rs index 6a16be2..e910c9e 100644 --- a/src/tick.rs +++ b/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) { + /// Sets the cursor position. + pub fn set_cursor_position(&self, pos: Option>) { 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, - pub mouse: Mouse, + /// The state of the mouse cursor and any buttons pressed. + pub mouse: Option, } #[derive(Debug, Default)] pub struct Mouse { - pub pos: Point, + pub position: Point, + pub buttons: HashSet, } - #[derive(Debug)] struct TickData { state: Mutex, @@ -150,7 +180,6 @@ struct TickState { keep_running: bool, frame: usize, input: InputState, - mouse: Option, } fn tick_loop(data: &TickData, mut tick: F) diff --git a/src/widgets/tilemap.rs b/src/widgets/tilemap.rs index f662e7d..3a75e72 100644 --- a/src/widgets/tilemap.rs +++ b/src/widgets/tilemap.rs @@ -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 { focus: Value, zoom: f32, tick: Option, - debug_output: Option>, } impl TileMap { @@ -33,15 +34,9 @@ impl TileMap { focus: Value::default(), zoom: 1., tick: None, - debug_output: None, } } - pub fn debug_output(mut self, message: Dynamic) -> Self { - self.debug_output = Some(message); - self - } - /// Returns a new tilemap that contains dynamic layers. pub fn dynamic(layers: Dynamic) -> Self { Self::construct(Value::Dynamic(layers)) @@ -126,20 +121,32 @@ where HANDLED } - fn hover(&mut self, local: Point, 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, + context: &mut EventContext<'_, '_>, + ) -> Option { 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, + _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>, + _device_id: DeviceId, + button: kludgine::app::winit::event::MouseButton, + _context: &mut EventContext<'_, '_>, + ) { + if let Some(tick) = &self.tick { + tick.mouse_button(button, ElementState::Released); + } + } }