diff --git a/Cargo.lock b/Cargo.lock index fbb5f19..aeb35db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -782,9 +782,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "gl_generator" @@ -845,7 +845,7 @@ version = "0.1.0" dependencies = [ "attribute-derive", "insta", - "manyhow 0.10.2", + "manyhow 0.10.4", "prettyplease", "proc-macro2", "quote", @@ -908,9 +908,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ "ahash", "allocator-api2", @@ -1226,11 +1226,11 @@ dependencies = [ [[package]] name = "manyhow" -version = "0.10.2" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69c6f16c208a6c61edc7b44896fc49b674af4b6b0d66a548770b9518f6aea41a" +checksum = "f91ea592d76c0b6471965708ccff7e6a5d277f676b90ab31f4d3f3fc77fade64" dependencies = [ - "manyhow-macros 0.10.2", + "manyhow-macros 0.10.4", "proc-macro2", "quote", "syn", @@ -1249,9 +1249,9 @@ dependencies = [ [[package]] name = "manyhow-macros" -version = "0.10.2" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f44d5b16145f87728fcf137729f1959252619ec4d7d1f19eacb3f558bc5567a" +checksum = "c64621e2c08f2576e4194ea8be11daf24ac01249a4f53cd8befcbb7077120ead" dependencies = [ "proc-macro-utils", "proc-macro2", @@ -1620,9 +1620,9 @@ checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "phf" @@ -1693,16 +1693,16 @@ dependencies = [ [[package]] name = "polling" -version = "3.3.0" +version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e53b6af1f60f36f8c2ac2aad5459d75a5a9b4be1e8cdd40264f315d78193e531" +checksum = "cf63fa624ab313c11656b4cda960bfc46c410187ad493c41f6ba2d8c1e991c9e" dependencies = [ "cfg-if", "concurrent-queue", "pin-project-lite", "rustix", "tracing", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1749,9 +1749,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" dependencies = [ "unicode-ident", ] @@ -2654,9 +2654,9 @@ dependencies = [ [[package]] name = "wgpu-hal" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e30b9a8155c83868e82a8c5d3ce899de6c3961d2ef595de8fc168a1677fc2d8" +checksum = "b84ecc802da3eb67b4cf3dd9ea6fe45bbb47ef13e6c49c5c3240868a9cc6cdd9" dependencies = [ "android_system_properties", "arrayvec", @@ -2789,6 +2789,15 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -2819,6 +2828,21 @@ dependencies = [ "windows_x86_64_msvc 0.48.5", ] +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -2831,6 +2855,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -2843,6 +2873,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -2855,6 +2891,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -2867,6 +2909,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -2879,6 +2927,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -2891,6 +2945,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -2904,10 +2964,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] -name = "winit" -version = "0.29.3" +name = "windows_x86_64_msvc" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "161598019a9da35ab6c34dc46cd13546cba9dbf9816475d4dd9a639455016563" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "winit" +version = "0.29.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25d662bb83b511acd839534bb2d88521b0bbc81440969cb077d23c4db9e62c7" dependencies = [ "ahash", "android-activity", diff --git a/examples/tilemap.rs b/examples/tilemap.rs index dc5d4d6..28938f5 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::{Label, Stack, TileMap}; use gooey::{Run, Tick}; use kludgine::app::winit::keyboard::NamedKey; use kludgine::figures::FloatConversion; @@ -40,12 +41,16 @@ 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 cursor + let mut direction = Point::new(0., 0.); if input.keys.contains(&Key::Named(NamedKey::ArrowDown)) { direction.y += 1.0; @@ -62,15 +67,25 @@ fn main() -> gooey::Result { let one_second_movement = direction * TILE_SIZE.into_float(); + let cursor_pos = input.mouse.as_ref().map(|mouse| mouse.position); + layers.map_mut(|layers| { - layers.1[myself].position += Point::new( - // TODO fix this in figures + 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::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, + }; }); - })) - .run() + })); + + Stack::rows(tilemap.expand().and(Label::new(debug_message))).run() } #[derive(Debug)] diff --git a/src/tick.rs b/src/tick.rs index 84db645..e910c9e 100644 --- a/src/tick.rs +++ b/src/tick.rs @@ -3,8 +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::units::Px; +use kludgine::figures::Point; use crate::context::WidgetContext; use crate::utils::{IgnorePoison, UnwindsafeCondvar}; @@ -49,6 +52,40 @@ impl Tick { } } + /// Sets the cursor position. + pub fn set_cursor_position(&self, pos: Option>) { + let mut state = self.data.state(); + 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 /// duration. pub fn new(tick_every: Duration, tick: F) -> Self @@ -111,6 +148,14 @@ impl Tick { pub struct InputState { /// A collection of all keys currently pressed. pub keys: HashSet, + /// The state of the mouse cursor and any buttons pressed. + pub mouse: Option, +} + +#[derive(Debug, Default)] +pub struct Mouse { + pub position: Point, + pub buttons: HashSet, } #[derive(Debug)] diff --git a/src/widgets/tilemap.rs b/src/widgets/tilemap.rs index 7d5bb88..3a75e72 100644 --- a/src/widgets/tilemap.rs +++ b/src/widgets/tilemap.rs @@ -1,6 +1,10 @@ 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; use crate::context::{EventContext, GraphicsContext, LayoutContext}; use crate::kludgine::app::winit::event::{DeviceId, KeyEvent, MouseScrollDelta, TouchPhase}; @@ -117,6 +121,34 @@ where HANDLED } + fn hover( + &mut self, + local: Point, + context: &mut EventContext<'_, '_>, + ) -> Option { + if let Some(tick) = &self.tick { + 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)); + } + + None + } + + fn unhover(&mut self, _context: &mut EventContext<'_, '_>) { + if let Some(tick) = &self.tick { + tick.set_cursor_position(None); + } + } + fn keyboard_input( &mut self, _device_id: DeviceId, @@ -130,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); + } + } }