diff --git a/crates/bevy_input_focus/src/directional_navigation.rs b/crates/bevy_input_focus/src/directional_navigation.rs index 17114ef11a..fd64cd41a7 100644 --- a/crates/bevy_input_focus/src/directional_navigation.rs +++ b/crates/bevy_input_focus/src/directional_navigation.rs @@ -186,10 +186,11 @@ impl DirectionalNavigationMap { /// /// This is useful for creating a circular navigation path between a set of entities, such as a menu. pub fn add_looping_edges(&mut self, entities: &[Entity], direction: CompassOctant) { - for i in 0..entities.len() { - let a = entities[i]; - let b = entities[(i + 1) % entities.len()]; - self.add_symmetrical_edge(a, b, direction); + self.add_edges(entities, direction); + if let Some((first_entity, rest)) = entities.split_first() { + if let Some(last_entity) = rest.last() { + self.add_symmetrical_edge(*last_entity, *first_entity, direction); + } } } @@ -227,14 +228,17 @@ impl DirectionalNavigation<'_> { /// If the result was `Ok`, the [`InputFocus`] resource is updated to the new focus as part of this method call. pub fn navigate( &mut self, - octant: CompassOctant, + direction: CompassOctant, ) -> Result { if let Some(current_focus) = self.focus.0 { - if let Some(new_focus) = self.map.get_neighbor(current_focus, octant) { + if let Some(new_focus) = self.map.get_neighbor(current_focus, direction) { self.focus.set(new_focus); Ok(new_focus) } else { - Err(DirectionalNavigationError::NoNeighborInDirection) + Err(DirectionalNavigationError::NoNeighborInDirection { + current_focus, + direction, + }) } } else { Err(DirectionalNavigationError::NoFocus) @@ -249,8 +253,13 @@ pub enum DirectionalNavigationError { #[error("No focusable entity is currently set.")] NoFocus, /// No neighbor in the requested direction. - #[error("No neighbor in the requested direction.")] - NoNeighborInDirection, + #[error("No neighbor from {current_focus} in the {direction:?} direction.")] + NoNeighborInDirection { + /// The entity that was the focus when the error occurred. + current_focus: Entity, + /// The direction in which the navigation was attempted. + direction: CompassOctant, + }, } #[cfg(test)] diff --git a/examples/ui/directional_navigation.rs b/examples/ui/directional_navigation.rs index b62c2875c5..b228df6dd4 100644 --- a/examples/ui/directional_navigation.rs +++ b/examples/ui/directional_navigation.rs @@ -5,6 +5,8 @@ //! //! In this example, we will set up a simple UI with a grid of buttons that can be navigated using the arrow keys or gamepad input. +use std::time::Duration; + use bevy::{ input_focus::{ directional_navigation::{ @@ -65,9 +67,7 @@ const FOCUSED_BORDER: Srgba = bevy::color::palettes::tailwind::BLUE_50; // In a real project, each button would also have its own unique behavior, // to capture the actual intent of the user fn universal_button_click_behavior( - // We're using an on-mouse-down trigger to improve responsiveness; - // Clicked is better when you want roll-off cancellation - mut trigger: Trigger>, + mut trigger: Trigger>, mut button_query: Query<(&mut BackgroundColor, &mut ResetTimer)>, ) { let button_entity = trigger.target(); @@ -368,7 +368,7 @@ fn highlight_focused_element( } } -// By sending a Pointer trigger rather than directly handling button-like interactions, +// By sending a Pointer trigger rather than directly handling button-like interactions, // we can unify our handling of pointer and keyboard/gamepad interactions fn interact_with_focused_button( action_state: Res, @@ -381,7 +381,7 @@ fn interact_with_focused_button( { if let Some(focused_entity) = input_focus.0 { commands.trigger_targets( - Pointer:: { + Pointer:: { target: focused_entity, // We're pretending that we're a mouse pointer_id: PointerId::Mouse, @@ -395,7 +395,7 @@ fn interact_with_focused_button( ), position: Vec2::ZERO, }, - event: Pressed { + event: Click { button: PointerButton::Primary, // This field isn't used, so we're just setting it to a placeholder value hit: HitData { @@ -404,6 +404,7 @@ fn interact_with_focused_button( position: None, normal: None, }, + duration: Duration::from_secs_f32(0.1), }, }, focused_entity,