@@ -67,7 +67,7 @@ use bevy_ecs::{
6767 system:: SystemParam ,
6868} ;
6969use bevy_math:: { CompassOctant , Dir2 , Vec2 } ;
70- use bevy_ui:: { ComputedNode , UiGlobalTransform } ;
70+ use bevy_ui:: { ComputedNode , ComputedUiTargetCamera , UiGlobalTransform } ;
7171use thiserror:: Error ;
7272
7373use crate :: InputFocus ;
@@ -418,17 +418,23 @@ pub struct DirectionalNavigation<'w, 's> {
418418 ' s ,
419419 (
420420 Entity ,
421+ & ' static ComputedUiTargetCamera ,
421422 & ' static ComputedNode ,
422423 & ' static UiGlobalTransform ,
423424 & ' static InheritedVisibility ,
424425 ) ,
425426 With < AutoDirectionalNavigation > ,
426427 > ,
427- /// A query used to get the [`FocusableArea`] for a given entity to be used in automatic navigation.
428- focusable_area_query : Query <
428+ /// A query used to get the target camera and the [`FocusableArea`] for a given entity to be used in automatic navigation.
429+ camera_and_focusable_area_query : Query <
429430 ' w ,
430431 ' s ,
431- ( Entity , & ' static ComputedNode , & ' static UiGlobalTransform ) ,
432+ (
433+ Entity ,
434+ & ' static ComputedUiTargetCamera ,
435+ & ' static ComputedNode ,
436+ & ' static UiGlobalTransform ,
437+ ) ,
432438 With < AutoDirectionalNavigation > ,
433439 > ,
434440}
@@ -449,11 +455,12 @@ impl<'w, 's> DirectionalNavigation<'w, 's> {
449455 if let Some ( new_focus) = self . map . get_neighbor ( current_focus, direction) {
450456 self . focus . set ( new_focus) ;
451457 Ok ( new_focus)
452- } else if let Some ( origin) = self . entity_to_focusable_area ( current_focus)
458+ } else if let Some ( ( target_camera, origin) ) =
459+ self . entity_to_camera_and_focusable_area ( current_focus)
453460 && let Some ( new_focus) = find_best_candidate (
454461 & origin,
455462 direction,
456- & self . get_navigable_nodes ( ) ,
463+ & self . get_navigable_nodes ( target_camera ) ,
457464 & self . config ,
458465 )
459466 {
@@ -471,39 +478,62 @@ impl<'w, 's> DirectionalNavigation<'w, 's> {
471478 }
472479
473480 /// Returns a vec of [`FocusableArea`] representing nodes that are eligible to be automatically navigated to.
474- fn get_navigable_nodes ( & self ) -> Vec < FocusableArea > {
481+ /// The camera of any navigable nodes will equal the desired `target_camera`.
482+ fn get_navigable_nodes ( & self , target_camera : Entity ) -> Vec < FocusableArea > {
475483 self . navigable_entities_query
476484 . iter ( )
477- . filter_map ( |( entity, computed, transform, inherited_visibility) | {
478- // Skip hidden or zero-size nodes
479- if computed. is_empty ( ) || !inherited_visibility. get ( ) {
480- return None ;
481- }
482-
483- let ( _scale, _rotation, translation) = transform. to_scale_angle_translation ( ) ;
484- Some ( FocusableArea {
485- entity,
486- position : translation,
487- size : computed. size ( ) ,
488- } )
489- } )
485+ . filter_map (
486+ |( entity, computed_target_camera, computed, transform, inherited_visibility) | {
487+ // Skip hidden or zero-size nodes
488+ if computed. is_empty ( ) || !inherited_visibility. get ( ) {
489+ return None ;
490+ }
491+ // Accept nodes that have the same target camera as the desired target camera
492+ if let Some ( tc) = computed_target_camera. get ( )
493+ && tc == target_camera
494+ {
495+ let ( _scale, _rotation, translation) =
496+ transform. to_scale_angle_translation ( ) ;
497+ Some ( FocusableArea {
498+ entity,
499+ position : translation,
500+ size : computed. size ( ) ,
501+ } )
502+ } else {
503+ // The node either does not have a target camera or it is not the same as the desired one.
504+ None
505+ }
506+ } ,
507+ )
490508 . collect ( )
491509 }
492510
493- /// Gets the [`FocusableArea`] of the provided entity, if it exists.
511+ /// Gets the target camera and the [`FocusableArea`] of the provided entity, if it exists.
494512 ///
495- /// Returns None if there was a [`QueryEntityError`](bevy_ecs::query::QueryEntityError).
496- fn entity_to_focusable_area ( & self , entity : Entity ) -> Option < FocusableArea > {
497- self . focusable_area_query
498- . get ( entity)
499- . map_or ( None , |( entity, computed, transform) | {
500- let ( _scale, _rotation, translation) = transform. to_scale_angle_translation ( ) ;
501- Some ( FocusableArea {
502- entity,
503- position : translation,
504- size : computed. size ( ) ,
505- } )
506- } )
513+ /// Returns None if there was a [`QueryEntityError`](bevy_ecs::query::QueryEntityError) or
514+ /// if the entity does not have a target camera.
515+ fn entity_to_camera_and_focusable_area (
516+ & self ,
517+ entity : Entity ,
518+ ) -> Option < ( Entity , FocusableArea ) > {
519+ self . camera_and_focusable_area_query . get ( entity) . map_or (
520+ None ,
521+ |( entity, computed_target_camera, computed, transform) | {
522+ if let Some ( target_camera) = computed_target_camera. get ( ) {
523+ let ( _scale, _rotation, translation) = transform. to_scale_angle_translation ( ) ;
524+ Some ( (
525+ target_camera,
526+ FocusableArea {
527+ entity,
528+ position : translation,
529+ size : computed. size ( ) ,
530+ } ,
531+ ) )
532+ } else {
533+ None
534+ }
535+ } ,
536+ )
507537 }
508538}
509539
0 commit comments