From 7db11e9065753d60ed590230213692dfeaf6b5ce Mon Sep 17 00:00:00 2001 From: demenik Date: Sat, 29 Nov 2025 16:08:51 +0100 Subject: [PATCH] fix: Fix #52 (Move/interaction click outside grid) and fix move/interaction click through popups --- src/features/grid/utils.rs | 50 ++++++++++++++++++++------ src/features/hud/ui/settings.rs | 1 + src/features/input/mod.rs | 23 ++++++++++-- src/features/inventory/ui/inventory.rs | 1 + src/features/savegame/ui/load.rs | 1 + 5 files changed, 63 insertions(+), 13 deletions(-) diff --git a/src/features/grid/utils.rs b/src/features/grid/utils.rs index 3c032da..4165d82 100644 --- a/src/features/grid/utils.rs +++ b/src/features/grid/utils.rs @@ -1,3 +1,6 @@ +use bevy::window::PrimaryWindow; + +use super::errors::GridError; use crate::prelude::*; pub fn grid_start_x(grid_width: u32) -> f32 { @@ -8,24 +11,25 @@ pub fn grid_start_y(grid_height: u32) -> f32 { -(grid_height as f32 * TILE_SIZE) / 2.0 + TILE_SIZE / 2.0 } -pub fn world_to_grid_coords(world_pos: Vec3, grid_width: u32, grid_height: u32) -> (u32, u32) { +pub fn world_to_grid_coords( + world_pos: Vec3, + grid_width: u32, + grid_height: u32, +) -> Result<(u32, u32), GridError> { let start_x = grid_start_x(grid_width); let start_y = grid_start_y(grid_height); let x = ((world_pos.x - start_x + TILE_SIZE / 2.0) / TILE_SIZE).floor(); let y = ((world_pos.y - start_y + TILE_SIZE / 2.0) / TILE_SIZE).floor(); - let mut x_u32 = x as u32; - let mut y_u32 = y as u32; - - if x_u32 >= grid_width { - x_u32 = grid_width - 1; - } - if y_u32 >= grid_height { - y_u32 = grid_height - 1; + if x >= grid_width as f32 || y >= grid_height as f32 || x < 0.0 || y < 0.0 { + return Err(GridError::OutOfBounds { + x: x as i32, + y: x as i32, + }); } - (x_u32, y_u32) + Ok((x as u32, y as u32)) } pub fn grid_to_world_coords( @@ -41,3 +45,29 @@ pub fn grid_to_world_coords( z.unwrap_or(0.0), ) } + +pub fn ui_blocks( + window: Single<&Window, With>, + cursor_pos: Vec2, + ui_query: Query<(&ComputedNode, &GlobalTransform), With>, +) -> bool { + let ui_point = Vec2::new( + cursor_pos.x - window.width() / 2.0, + (window.height() / 2.0) - cursor_pos.y, + ); + + dbg!(ui_point); + + ui_query.iter().any(|(node, global_transform)| { + dbg!(node, global_transform); + + let size = node.size(); + let center = global_transform.translation().truncate(); + let half_size = size / 2.0; + + let min = center - half_size; + let max = center + half_size; + + ui_point.x >= min.x && ui_point.x <= max.x && ui_point.y >= min.y && ui_point.y <= max.y + }) +} diff --git a/src/features/hud/ui/settings.rs b/src/features/hud/ui/settings.rs index dd8868d..f2b16f5 100644 --- a/src/features/hud/ui/settings.rs +++ b/src/features/hud/ui/settings.rs @@ -14,6 +14,7 @@ pub fn open_settings(commands: &mut Commands) { }, ZIndex(1), BackgroundColor(Color::srgba(0.0, 0.0, 0.0, 0.8)), + GlobalTransform::default(), )) .with_children(|parent| { parent diff --git a/src/features/input/mod.rs b/src/features/input/mod.rs index ce12444..9b95b8a 100644 --- a/src/features/input/mod.rs +++ b/src/features/input/mod.rs @@ -1,4 +1,5 @@ use crate::features::{ + grid::utils::ui_blocks, phase::messages::{NextPhaseMessage, PhaseTimerPauseMessage}, pom::messages::InvalidMoveMessage, }; @@ -38,6 +39,7 @@ fn move_click( camera: Single<(&Camera, &GlobalTransform), With>, config: Res, phase: Res, + ui_query: Query<(&ComputedNode, &GlobalTransform), With>, ) { match phase.0 { Phase::Focus { .. } => return, @@ -50,10 +52,17 @@ fn move_click( let Some(cursor_pos) = window.cursor_position() else { return; }; + if ui_blocks(window, cursor_pos, ui_query) { + return; + } let Ok(world_pos) = cam.viewport_to_world(cam_transform, cursor_pos) else { return; }; - let (x, y) = world_to_grid_coords(world_pos.origin, config.grid_width, config.grid_height); + let Ok((x, y)) = + world_to_grid_coords(world_pos.origin, config.grid_width, config.grid_height) + else { + return; + }; println!("Move Click: ({}, {})", x, y); move_messages.write(MoveMessage { x, y }); @@ -67,6 +76,7 @@ fn interact_click( camera: Single<(&Camera, &GlobalTransform), With>, config: Res, phase: Res, + ui_query: Query<(&ComputedNode, &GlobalTransform), With>, // for debug grid: ResMut, tile_query: Query<&mut TileState>, @@ -82,10 +92,17 @@ fn interact_click( let Some(cursor_pos) = window.cursor_position() else { return; }; + if ui_blocks(window, cursor_pos, ui_query) { + return; + } let Ok(world_pos) = cam.viewport_to_world(cam_transform, cursor_pos) else { return; }; - let (x, y) = world_to_grid_coords(world_pos.origin, config.grid_width, config.grid_height); + let Ok((x, y)) = + world_to_grid_coords(world_pos.origin, config.grid_width, config.grid_height) + else { + return; + }; println!("Interact Click: ({}, {})", x, y); interact_messages.write(InteractStartMessage { x, y }); @@ -100,7 +117,7 @@ fn interact_click( }, tile_query, ) - .unwrap(); + .unwrap_or_else(|_| ()); } } } diff --git a/src/features/inventory/ui/inventory.rs b/src/features/inventory/ui/inventory.rs index e77d9cc..769307a 100644 --- a/src/features/inventory/ui/inventory.rs +++ b/src/features/inventory/ui/inventory.rs @@ -13,6 +13,7 @@ pub fn open_inventory(commands: &mut Commands, items: Query<&ItemStack>) { }, ZIndex(1), BackgroundColor(Color::srgba(0.0, 0.0, 0.0, 0.8)), + GlobalTransform::default(), )) .with_children(|parent| { parent diff --git a/src/features/savegame/ui/load.rs b/src/features/savegame/ui/load.rs index 80b405e..2df621b 100644 --- a/src/features/savegame/ui/load.rs +++ b/src/features/savegame/ui/load.rs @@ -13,6 +13,7 @@ pub fn spawn_load_popup(commands: &mut Commands) { }, ZIndex(1), BackgroundColor(Color::srgba(0.0, 0.0, 0.0, 0.8)), + GlobalTransform::default(), )) .with_children(|parent| { parent