1use alloc::vec::Vec;
28use bevy_app::{App, Plugin, Startup};
29use bevy_camera::visibility::InheritedVisibility;
30use bevy_ecs::{
31 component::Component,
32 entity::Entity,
33 hierarchy::{ChildOf, Children},
34 observer::On,
35 query::{With, Without},
36 system::{Commands, Query, Res, ResMut, SystemParam},
37};
38use bevy_input::{
39 keyboard::{KeyCode, KeyboardInput},
40 ButtonInput, ButtonState,
41};
42use bevy_window::{PrimaryWindow, Window};
43use log::warn;
44use thiserror::Error;
45
46use crate::{AcquireFocus, FocusCause, FocusedInput, InputFocus, InputFocusVisible};
47
48#[cfg(feature = "bevy_reflect")]
49use {
50 bevy_ecs::prelude::ReflectComponent,
51 bevy_reflect::{prelude::*, Reflect},
52};
53
54#[derive(#[automatically_derived]impl ::core::fmt::Debug for TabIndex {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f, "TabIndex",
&&self.0)
}
}Debug, #[automatically_derived]impl ::core::default::Default for TabIndex {
#[inline]
fn default() -> Self { TabIndex(::core::default::Default::default()) }
}Default, impl bevy_ecs::component::Component for TabIndex where
Self: ::core::marker::Send + ::core::marker::Sync + 'static {
const STORAGE_TYPE: bevy_ecs::component::StorageType =
bevy_ecs::component::StorageType::Table;
type Mutability = bevy_ecs::component::Mutable;
fn register_required_components(_requiree:
bevy_ecs::component::ComponentId,
required_components:
&mut bevy_ecs::component::RequiredComponentsRegistrator) {}
fn clone_behavior() -> bevy_ecs::component::ComponentCloneBehavior {
use bevy_ecs::component::{
DefaultCloneBehaviorBase, DefaultCloneBehaviorViaClone,
};
(&&&bevy_ecs::component::DefaultCloneBehaviorSpecialization::<Self>::default()).default_clone_behavior()
}
fn relationship_accessor()
->
::core::option::Option<bevy_ecs::relationship::ComponentRelationshipAccessor<Self>> {
::core::option::Option::None
}
}Component, #[automatically_derived]impl ::core::marker::Copy for TabIndex { }Copy, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
for TabIndex {
}
#[automatically_derived]impl ::core::clone::Clone for TabIndex {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<i32>;
*self
}
}Clone, #[automatically_derived]impl ::core::marker::StructuralPartialEq for TabIndex
{
}
#[automatically_derived]impl ::core::cmp::PartialEq for TabIndex {
#[inline]
fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for TabIndex {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<i32>;
}
}Eq, #[automatically_derived]impl ::core::cmp::PartialOrd for TabIndex {
#[inline]
fn partial_cmp(&self, other: &Self)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
}
}PartialOrd, #[automatically_derived]impl ::core::cmp::Ord for TabIndex {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}Ord)]
59#[cfg_attr(
60 feature = "bevy_reflect",
61 derive(const _: () =
{
impl bevy_reflect::GetTypeRegistration for TabIndex where {
fn get_type_registration() -> bevy_reflect::TypeRegistration {
let mut registration =
bevy_reflect::TypeRegistration::of::<Self>();
registration.insert(<bevy_reflect::ReflectFromPtr as
bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
registration.insert(<bevy_reflect::ReflectFromReflect as
bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
registration.register_type_data_with::<ReflectDefault, Self,
_>(());
registration.register_type_data_with::<ReflectComponent, Self,
_>(());
registration
}
#[inline(never)]
fn register_type_dependencies(registry:
&mut bevy_reflect::TypeRegistry) {
<i32 as
bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
}
}
impl bevy_reflect::Typed for TabIndex where {
#[inline(never)]
fn type_info() -> &'static bevy_reflect::TypeInfo {
static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
bevy_reflect::utility::NonGenericTypeInfoCell::new();
CELL.get_or_set(#[inline(never)] ||
{
bevy_reflect::TypeInfo::TupleStruct(bevy_reflect::tuple_struct::TupleStructInfo::new::<Self>(&[bevy_reflect::UnnamedField::new::<i32>(0usize)]))
})
}
}
#[allow(deprecated, reason =
"derives on a deprecated type shouldn't be considered a usage")]
impl bevy_reflect::TypePath for TabIndex where {
fn type_path() -> &'static str {
"bevy_input_focus::tab_navigation::TabIndex"
}
fn short_type_path() -> &'static str { "TabIndex" }
fn type_ident() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("TabIndex")
}
fn crate_name() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_input_focus::tab_navigation".split(':').next().unwrap())
}
fn module_path() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_input_focus::tab_navigation")
}
}
impl bevy_reflect::Reflect for TabIndex where {
#[inline]
fn into_any(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
self
}
#[inline]
fn as_any(&self) -> &dyn ::core::any::Any { self }
#[inline]
fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
#[inline]
fn into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
self
}
#[inline]
fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
#[inline]
fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
self
}
#[inline]
fn set(&mut self,
value:
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
->
::core::result::Result<(),
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
*self = <dyn bevy_reflect::Reflect>::take(value)?;
::core::result::Result::Ok(())
}
}
#[allow(non_upper_case_globals)]
const _: () =
{
static __INVENTORY: ::inventory::Node =
::inventory::Node {
value: &{
bevy_reflect::__macro_exports::auto_register::AutomaticReflectRegistrations(<TabIndex
as
bevy_reflect::__macro_exports::auto_register::RegisterForReflection>::__register)
},
next: ::inventory::__private::UnsafeCell::new(::inventory::__private::Option::None),
};
#[link_section = ".text.startup"]
unsafe extern "C" fn __ctor() {
unsafe {
::inventory::ErasedNode::submit(__INVENTORY.value,
&__INVENTORY)
}
}
#[used]
#[link_section = ".init_array"]
static __CTOR: unsafe extern "C" fn() = __ctor;
};
impl bevy_reflect::tuple_struct::TupleStruct for TabIndex where {
fn field(&self, index: usize)
-> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
match index {
0usize => ::core::option::Option::Some(&self.0),
_ => ::core::option::Option::None,
}
}
fn field_mut(&mut self, index: usize)
->
::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
match index {
0usize => ::core::option::Option::Some(&mut self.0),
_ => ::core::option::Option::None,
}
}
#[inline]
fn field_len(&self) -> usize { 1usize }
#[inline]
fn iter_fields(&self)
-> bevy_reflect::tuple_struct::TupleStructFieldIter {
bevy_reflect::tuple_struct::TupleStructFieldIter::new(self)
}
fn to_dynamic_tuple_struct(&self)
->
::core::result::Result<bevy_reflect::tuple_struct::DynamicTupleStruct,
bevy_reflect::ReflectCloneError> {
let mut dynamic:
bevy_reflect::tuple_struct::DynamicTupleStruct =
::core::default::Default::default();
dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
dynamic.insert_boxed(bevy_reflect::PartialReflect::to_dynamic(&self.0)?);
::core::result::Result::Ok(dynamic)
}
}
impl bevy_reflect::PartialReflect for TabIndex where {
#[inline]
fn get_represented_type_info(&self)
-> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
::core::option::Option::Some(<Self as
bevy_reflect::Typed>::type_info())
}
#[inline]
fn try_apply(&mut self, value: &dyn bevy_reflect::PartialReflect)
-> ::core::result::Result<(), bevy_reflect::ApplyError> {
if let bevy_reflect::ReflectRef::TupleStruct(struct_value) =
bevy_reflect::PartialReflect::reflect_ref(value) {
for (i, value) in
::core::iter::Iterator::enumerate(bevy_reflect::tuple_struct::TupleStruct::iter_fields(struct_value))
{
if let ::core::option::Option::Some(v) =
bevy_reflect::tuple_struct::TupleStruct::field_mut(self, i)
{
bevy_reflect::PartialReflect::try_apply(v, value)?;
}
}
} else {
return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
from_kind: bevy_reflect::PartialReflect::reflect_kind(value),
to_kind: bevy_reflect::ReflectKind::TupleStruct,
});
}
::core::result::Result::Ok(())
}
#[inline]
fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
bevy_reflect::ReflectKind::TupleStruct
}
#[inline]
fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
bevy_reflect::ReflectRef::TupleStruct(self)
}
#[inline]
fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
bevy_reflect::ReflectMut::TupleStruct(self)
}
#[inline]
fn reflect_owned(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
-> bevy_reflect::ReflectOwned {
bevy_reflect::ReflectOwned::TupleStruct(self)
}
#[inline]
fn try_into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
::core::result::Result::Ok(self)
}
#[inline]
fn try_as_reflect(&self)
-> ::core::option::Option<&dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn try_as_reflect_mut(&mut self)
-> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn into_partial_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
self
}
#[inline]
fn as_partial_reflect(&self)
-> &dyn bevy_reflect::PartialReflect {
self
}
#[inline]
fn as_partial_reflect_mut(&mut self)
-> &mut dyn bevy_reflect::PartialReflect {
self
}
fn reflect_partial_eq(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<bool> {
let value =
<dyn bevy_reflect::PartialReflect>::try_downcast_ref::<Self>(value);
if let ::core::option::Option::Some(value) = value {
::core::option::Option::Some(::core::cmp::PartialEq::eq(self,
value))
} else { ::core::option::Option::Some(false) }
}
fn reflect_partial_cmp(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<::core::cmp::Ordering> {
(bevy_reflect::tuple_struct::tuple_struct_partial_cmp)(self,
value)
}
fn debug(&self, f: &mut ::core::fmt::Formatter<'_>)
-> ::core::fmt::Result {
::core::fmt::Debug::fmt(self, f)
}
#[inline]
fn reflect_clone(&self)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::ReflectCloneError> {
::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(::core::clone::Clone::clone(self)))
}
}
impl bevy_reflect::FromReflect for TabIndex where {
fn from_reflect(reflect: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<Self> {
if let bevy_reflect::ReflectRef::TupleStruct(__ref_struct) =
bevy_reflect::PartialReflect::reflect_ref(reflect) {
let mut __this =
<Self as ::core::default::Default>::default();
if let ::core::option::Option::Some(__field) =
(||
<i32 as
bevy_reflect::FromReflect>::from_reflect(bevy_reflect::tuple_struct::TupleStruct::field(__ref_struct,
0)?))() {
__this.0 = __field;
}
::core::option::Option::Some(__this)
} else { ::core::option::Option::None }
}
}
};Reflect),
62 reflect(Debug, Default, Component, PartialEq, Clone)
63)]
64pub struct TabIndex(pub i32);
65
66#[derive(#[automatically_derived]impl ::core::fmt::Debug for TabGroup {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "TabGroup",
"order", &self.order, "modal", &&self.modal)
}
}Debug, #[automatically_derived]impl ::core::default::Default for TabGroup {
#[inline]
fn default() -> Self {
TabGroup {
order: ::core::default::Default::default(),
modal: ::core::default::Default::default(),
}
}
}Default, impl bevy_ecs::component::Component for TabGroup where
Self: ::core::marker::Send + ::core::marker::Sync + 'static {
const STORAGE_TYPE: bevy_ecs::component::StorageType =
bevy_ecs::component::StorageType::Table;
type Mutability = bevy_ecs::component::Mutable;
fn register_required_components(_requiree:
bevy_ecs::component::ComponentId,
required_components:
&mut bevy_ecs::component::RequiredComponentsRegistrator) {}
fn clone_behavior() -> bevy_ecs::component::ComponentCloneBehavior {
use bevy_ecs::component::{
DefaultCloneBehaviorBase, DefaultCloneBehaviorViaClone,
};
(&&&bevy_ecs::component::DefaultCloneBehaviorSpecialization::<Self>::default()).default_clone_behavior()
}
fn relationship_accessor()
->
::core::option::Option<bevy_ecs::relationship::ComponentRelationshipAccessor<Self>> {
::core::option::Option::None
}
}Component, #[automatically_derived]impl ::core::marker::Copy for TabGroup { }Copy, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
for TabGroup {
}
#[automatically_derived]impl ::core::clone::Clone for TabGroup {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<i32>;
let _: ::core::clone::AssertParamIsClone<bool>;
*self
}
}Clone)]
68#[cfg_attr(
69 feature = "bevy_reflect",
70 derive(const _: () =
{
impl bevy_reflect::GetTypeRegistration for TabGroup where {
fn get_type_registration() -> bevy_reflect::TypeRegistration {
let mut registration =
bevy_reflect::TypeRegistration::of::<Self>();
registration.insert(<bevy_reflect::ReflectFromPtr as
bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
registration.insert(<bevy_reflect::ReflectFromReflect as
bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
registration.register_type_data_with::<ReflectDefault, Self,
_>(());
registration.register_type_data_with::<ReflectComponent, Self,
_>(());
registration
}
#[inline(never)]
fn register_type_dependencies(registry:
&mut bevy_reflect::TypeRegistry) {
<i32 as
bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
<bool as
bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
}
}
impl bevy_reflect::Typed for TabGroup where {
#[inline(never)]
fn type_info() -> &'static bevy_reflect::TypeInfo {
static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
bevy_reflect::utility::NonGenericTypeInfoCell::new();
CELL.get_or_set(#[inline(never)] ||
{
bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[bevy_reflect::NamedField::new::<i32>("order"),
bevy_reflect::NamedField::new::<bool>("modal")]))
})
}
}
#[allow(deprecated, reason =
"derives on a deprecated type shouldn't be considered a usage")]
impl bevy_reflect::TypePath for TabGroup where {
fn type_path() -> &'static str {
"bevy_input_focus::tab_navigation::TabGroup"
}
fn short_type_path() -> &'static str { "TabGroup" }
fn type_ident() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("TabGroup")
}
fn crate_name() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_input_focus::tab_navigation".split(':').next().unwrap())
}
fn module_path() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_input_focus::tab_navigation")
}
}
impl bevy_reflect::Reflect for TabGroup where {
#[inline]
fn into_any(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
self
}
#[inline]
fn as_any(&self) -> &dyn ::core::any::Any { self }
#[inline]
fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
#[inline]
fn into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
self
}
#[inline]
fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
#[inline]
fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
self
}
#[inline]
fn set(&mut self,
value:
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
->
::core::result::Result<(),
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
*self = <dyn bevy_reflect::Reflect>::take(value)?;
::core::result::Result::Ok(())
}
}
#[allow(non_upper_case_globals)]
const _: () =
{
static __INVENTORY: ::inventory::Node =
::inventory::Node {
value: &{
bevy_reflect::__macro_exports::auto_register::AutomaticReflectRegistrations(<TabGroup
as
bevy_reflect::__macro_exports::auto_register::RegisterForReflection>::__register)
},
next: ::inventory::__private::UnsafeCell::new(::inventory::__private::Option::None),
};
#[link_section = ".text.startup"]
unsafe extern "C" fn __ctor() {
unsafe {
::inventory::ErasedNode::submit(__INVENTORY.value,
&__INVENTORY)
}
}
#[used]
#[link_section = ".init_array"]
static __CTOR: unsafe extern "C" fn() = __ctor;
};
impl bevy_reflect::structs::Struct for TabGroup where {
fn field(&self, name: &str)
-> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
match name {
"order" => ::core::option::Option::Some(&self.order),
"modal" => ::core::option::Option::Some(&self.modal),
_ => ::core::option::Option::None,
}
}
fn field_mut(&mut self, name: &str)
->
::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
match name {
"order" => ::core::option::Option::Some(&mut self.order),
"modal" => ::core::option::Option::Some(&mut self.modal),
_ => ::core::option::Option::None,
}
}
fn field_at(&self, index: usize)
-> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
match index {
0usize => ::core::option::Option::Some(&self.order),
1usize => ::core::option::Option::Some(&self.modal),
_ => ::core::option::Option::None,
}
}
fn field_at_mut(&mut self, index: usize)
->
::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
match index {
0usize => ::core::option::Option::Some(&mut self.order),
1usize => ::core::option::Option::Some(&mut self.modal),
_ => ::core::option::Option::None,
}
}
fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
match index {
0usize => ::core::option::Option::Some("order"),
1usize => ::core::option::Option::Some("modal"),
_ => ::core::option::Option::None,
}
}
fn index_of_name(&self, name: &str)
-> ::core::option::Option<usize> {
match name {
"order" => ::core::option::Option::Some(0usize),
"modal" => ::core::option::Option::Some(1usize),
_ => ::core::option::Option::None,
}
}
fn field_len(&self) -> usize { 2usize }
fn iter_fields(&self) -> bevy_reflect::structs::FieldIter {
bevy_reflect::structs::FieldIter::new(self)
}
fn to_dynamic_struct(&self)
->
::core::result::Result<bevy_reflect::structs::DynamicStruct,
bevy_reflect::ReflectCloneError> {
let mut dynamic: bevy_reflect::structs::DynamicStruct =
::core::default::Default::default();
dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
dynamic.insert_boxed("order",
bevy_reflect::PartialReflect::to_dynamic(&self.order)?);
dynamic.insert_boxed("modal",
bevy_reflect::PartialReflect::to_dynamic(&self.modal)?);
::core::result::Result::Ok(dynamic)
}
}
impl bevy_reflect::PartialReflect for TabGroup where {
#[inline]
fn get_represented_type_info(&self)
-> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
::core::option::Option::Some(<Self as
bevy_reflect::Typed>::type_info())
}
#[inline]
fn try_apply(&mut self, value: &dyn bevy_reflect::PartialReflect)
-> ::core::result::Result<(), bevy_reflect::ApplyError> {
if let bevy_reflect::ReflectRef::Struct(struct_value) =
bevy_reflect::PartialReflect::reflect_ref(value) {
for (name, value) in
bevy_reflect::structs::Struct::iter_fields(struct_value) {
if let ::core::option::Option::Some(v) =
bevy_reflect::structs::Struct::field_mut(self, name) {
bevy_reflect::PartialReflect::try_apply(v, value)?;
}
}
} else {
return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
from_kind: bevy_reflect::PartialReflect::reflect_kind(value),
to_kind: bevy_reflect::ReflectKind::Struct,
});
}
::core::result::Result::Ok(())
}
#[inline]
fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
bevy_reflect::ReflectKind::Struct
}
#[inline]
fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
bevy_reflect::ReflectRef::Struct(self)
}
#[inline]
fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
bevy_reflect::ReflectMut::Struct(self)
}
#[inline]
fn reflect_owned(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
-> bevy_reflect::ReflectOwned {
bevy_reflect::ReflectOwned::Struct(self)
}
#[inline]
fn try_into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
::core::result::Result::Ok(self)
}
#[inline]
fn try_as_reflect(&self)
-> ::core::option::Option<&dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn try_as_reflect_mut(&mut self)
-> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn into_partial_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
self
}
#[inline]
fn as_partial_reflect(&self)
-> &dyn bevy_reflect::PartialReflect {
self
}
#[inline]
fn as_partial_reflect_mut(&mut self)
-> &mut dyn bevy_reflect::PartialReflect {
self
}
fn reflect_partial_eq(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<bool> {
(bevy_reflect::structs::struct_partial_eq)(self, value)
}
fn reflect_partial_cmp(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<::core::cmp::Ordering> {
(bevy_reflect::structs::struct_partial_cmp)(self, value)
}
fn debug(&self, f: &mut ::core::fmt::Formatter<'_>)
-> ::core::fmt::Result {
::core::fmt::Debug::fmt(self, f)
}
#[inline]
fn reflect_clone(&self)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::ReflectCloneError> {
::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(::core::clone::Clone::clone(self)))
}
}
impl bevy_reflect::FromReflect for TabGroup where {
fn from_reflect(reflect: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<Self> {
if let bevy_reflect::ReflectRef::Struct(__ref_struct) =
bevy_reflect::PartialReflect::reflect_ref(reflect) {
let mut __this =
<Self as ::core::default::Default>::default();
if let ::core::option::Option::Some(__field) =
(||
<i32 as
bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
"order")?))() {
__this.order = __field;
}
if let ::core::option::Option::Some(__field) =
(||
<bool as
bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
"modal")?))() {
__this.modal = __field;
}
::core::option::Option::Some(__this)
} else { ::core::option::Option::None }
}
}
};Reflect),
71 reflect(Debug, Default, Component, Clone)
72)]
73pub struct TabGroup {
74 pub order: i32,
76
77 pub modal: bool,
82}
83
84impl TabGroup {
85 pub fn new(order: i32) -> Self {
87 Self {
88 order,
89 modal: false,
90 }
91 }
92
93 pub fn modal() -> Self {
95 Self {
96 order: 0,
97 modal: true,
98 }
99 }
100}
101
102#[derive(#[automatically_derived]impl ::core::default::Default for NavAction {
#[inline]
fn default() -> Self { Self::Next }
}Default, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
for NavAction {
}
#[automatically_derived]impl ::core::clone::Clone for NavAction {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]impl ::core::marker::Copy for NavAction { }Copy, #[automatically_derived]impl ::core::fmt::Debug for NavAction {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
NavAction::Next => "Next",
NavAction::Previous => "Previous",
NavAction::First => "First",
NavAction::Last => "Last",
})
}
}Debug, #[automatically_derived]impl ::core::marker::StructuralPartialEq for NavAction
{
}
#[automatically_derived]impl ::core::cmp::PartialEq for NavAction {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other)
}
}PartialEq)]
106#[cfg_attr(
107 feature = "bevy_reflect",
108 derive(const _: () =
{
impl bevy_reflect::GetTypeRegistration for NavAction where {
fn get_type_registration() -> bevy_reflect::TypeRegistration {
let mut registration =
bevy_reflect::TypeRegistration::of::<Self>();
registration.insert(<bevy_reflect::ReflectFromPtr as
bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
registration.insert(<bevy_reflect::ReflectFromReflect as
bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
registration
}
#[inline(never)]
fn register_type_dependencies(registry:
&mut bevy_reflect::TypeRegistry) {}
}
impl bevy_reflect::Typed for NavAction where {
#[inline(never)]
fn type_info() -> &'static bevy_reflect::TypeInfo {
static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
bevy_reflect::utility::NonGenericTypeInfoCell::new();
CELL.get_or_set(#[inline(never)] ||
{
bevy_reflect::TypeInfo::Enum(bevy_reflect::enums::EnumInfo::new::<Self>(&[bevy_reflect::enums::VariantInfo::Unit(bevy_reflect::enums::UnitVariantInfo::new("Next")),
bevy_reflect::enums::VariantInfo::Unit(bevy_reflect::enums::UnitVariantInfo::new("Previous")),
bevy_reflect::enums::VariantInfo::Unit(bevy_reflect::enums::UnitVariantInfo::new("First")),
bevy_reflect::enums::VariantInfo::Unit(bevy_reflect::enums::UnitVariantInfo::new("Last"))]))
})
}
}
#[allow(deprecated, reason =
"derives on a deprecated type shouldn't be considered a usage")]
impl bevy_reflect::TypePath for NavAction where {
fn type_path() -> &'static str {
"bevy_input_focus::tab_navigation::NavAction"
}
fn short_type_path() -> &'static str { "NavAction" }
fn type_ident() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("NavAction")
}
fn crate_name() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_input_focus::tab_navigation".split(':').next().unwrap())
}
fn module_path() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_input_focus::tab_navigation")
}
}
impl bevy_reflect::Reflect for NavAction where {
#[inline]
fn into_any(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
self
}
#[inline]
fn as_any(&self) -> &dyn ::core::any::Any { self }
#[inline]
fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
#[inline]
fn into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
self
}
#[inline]
fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
#[inline]
fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
self
}
#[inline]
fn set(&mut self,
value:
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
->
::core::result::Result<(),
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
*self = <dyn bevy_reflect::Reflect>::take(value)?;
::core::result::Result::Ok(())
}
}
#[allow(non_upper_case_globals)]
const _: () =
{
static __INVENTORY: ::inventory::Node =
::inventory::Node {
value: &{
bevy_reflect::__macro_exports::auto_register::AutomaticReflectRegistrations(<NavAction
as
bevy_reflect::__macro_exports::auto_register::RegisterForReflection>::__register)
},
next: ::inventory::__private::UnsafeCell::new(::inventory::__private::Option::None),
};
#[link_section = ".text.startup"]
unsafe extern "C" fn __ctor() {
unsafe {
::inventory::ErasedNode::submit(__INVENTORY.value,
&__INVENTORY)
}
}
#[used]
#[link_section = ".init_array"]
static __CTOR: unsafe extern "C" fn() = __ctor;
};
impl bevy_reflect::enums::Enum for NavAction where {
fn field(&self, __name_param: &str)
-> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
match self { _ => ::core::option::Option::None, }
}
fn field_at(&self, __index_param: usize)
-> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
match self { _ => ::core::option::Option::None, }
}
fn field_mut(&mut self, __name_param: &str)
->
::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
match self { _ => ::core::option::Option::None, }
}
fn field_at_mut(&mut self, __index_param: usize)
->
::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
match self { _ => ::core::option::Option::None, }
}
fn index_of(&self, __name_param: &str)
-> ::core::option::Option<usize> {
match self { _ => ::core::option::Option::None, }
}
fn name_at(&self, __index_param: usize)
-> ::core::option::Option<&str> {
match self { _ => ::core::option::Option::None, }
}
fn iter_fields(&self) -> bevy_reflect::enums::VariantFieldIter {
bevy_reflect::enums::VariantFieldIter::new(self)
}
#[inline]
fn field_len(&self) -> usize {
match self {
NavAction::Next { .. } => 0usize,
NavAction::Previous { .. } => 0usize,
NavAction::First { .. } => 0usize,
NavAction::Last { .. } => 0usize,
_ => 0,
}
}
#[inline]
fn variant_name(&self) -> &str {
match self {
NavAction::Next { .. } => "Next",
NavAction::Previous { .. } => "Previous",
NavAction::First { .. } => "First",
NavAction::Last { .. } => "Last",
_ => ::core::panicking::unreachable_default_msg(),
}
}
#[inline]
fn variant_index(&self) -> usize {
match self {
NavAction::Next { .. } => 0usize,
NavAction::Previous { .. } => 1usize,
NavAction::First { .. } => 2usize,
NavAction::Last { .. } => 3usize,
_ => ::core::panicking::unreachable_default_msg(),
}
}
#[inline]
fn variant_type(&self) -> bevy_reflect::enums::VariantType {
match self {
NavAction::Next { .. } =>
bevy_reflect::enums::VariantType::Unit,
NavAction::Previous { .. } =>
bevy_reflect::enums::VariantType::Unit,
NavAction::First { .. } =>
bevy_reflect::enums::VariantType::Unit,
NavAction::Last { .. } =>
bevy_reflect::enums::VariantType::Unit,
_ => ::core::panicking::unreachable_default_msg(),
}
}
fn to_dynamic_enum(&self)
->
::core::result::Result<bevy_reflect::enums::DynamicEnum,
bevy_reflect::ReflectCloneError> {
bevy_reflect::enums::DynamicEnum::try_from_ref::<Self>(self)
}
}
impl bevy_reflect::PartialReflect for NavAction where {
#[inline]
fn get_represented_type_info(&self)
-> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
::core::option::Option::Some(<Self as
bevy_reflect::Typed>::type_info())
}
#[inline]
fn try_apply(&mut self,
__value_param: &dyn bevy_reflect::PartialReflect)
-> ::core::result::Result<(), bevy_reflect::ApplyError> {
if let bevy_reflect::ReflectRef::Enum(__value_param) =
bevy_reflect::PartialReflect::reflect_ref(__value_param) {
if bevy_reflect::enums::Enum::variant_name(self) ==
bevy_reflect::enums::Enum::variant_name(__value_param) {
match bevy_reflect::enums::Enum::variant_type(__value_param)
{
bevy_reflect::enums::VariantType::Struct => {
for field in
bevy_reflect::enums::Enum::iter_fields(__value_param) {
let name = field.name().unwrap();
if let ::core::option::Option::Some(v) =
bevy_reflect::enums::Enum::field_mut(self, name) {
bevy_reflect::PartialReflect::try_apply(v, field.value())?;
}
}
}
bevy_reflect::enums::VariantType::Tuple => {
for (index, field) in
::core::iter::Iterator::enumerate(bevy_reflect::enums::Enum::iter_fields(__value_param))
{
if let ::core::option::Option::Some(v) =
bevy_reflect::enums::Enum::field_at_mut(self, index) {
bevy_reflect::PartialReflect::try_apply(v, field.value())?;
}
}
}
_ => {}
}
} else {
match bevy_reflect::enums::Enum::variant_name(__value_param)
{
"Next" => { *self = NavAction::Next {} }
"Previous" => { *self = NavAction::Previous {} }
"First" => { *self = NavAction::First {} }
"Last" => { *self = NavAction::Last {} }
name => {
return ::core::result::Result::Err(bevy_reflect::ApplyError::UnknownVariant {
enum_name: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(self)),
variant_name: ::core::convert::Into::into(name),
});
}
}
}
} else {
return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
from_kind: bevy_reflect::PartialReflect::reflect_kind(__value_param),
to_kind: bevy_reflect::ReflectKind::Enum,
});
}
::core::result::Result::Ok(())
}
fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
bevy_reflect::ReflectKind::Enum
}
fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
bevy_reflect::ReflectRef::Enum(self)
}
fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
bevy_reflect::ReflectMut::Enum(self)
}
fn reflect_owned(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
-> bevy_reflect::ReflectOwned {
bevy_reflect::ReflectOwned::Enum(self)
}
#[inline]
fn try_into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
::core::result::Result::Ok(self)
}
#[inline]
fn try_as_reflect(&self)
-> ::core::option::Option<&dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn try_as_reflect_mut(&mut self)
-> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn into_partial_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
self
}
#[inline]
fn as_partial_reflect(&self)
-> &dyn bevy_reflect::PartialReflect {
self
}
#[inline]
fn as_partial_reflect_mut(&mut self)
-> &mut dyn bevy_reflect::PartialReflect {
self
}
fn reflect_hash(&self) -> ::core::option::Option<u64> {
(bevy_reflect::enums::enum_hash)(self)
}
fn reflect_partial_eq(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<bool> {
let value =
<dyn bevy_reflect::PartialReflect>::try_downcast_ref::<Self>(value);
if let ::core::option::Option::Some(value) = value {
::core::option::Option::Some(::core::cmp::PartialEq::eq(self,
value))
} else { ::core::option::Option::Some(false) }
}
fn reflect_partial_cmp(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<::core::cmp::Ordering> {
(bevy_reflect::enums::enum_partial_cmp)(self, value)
}
fn debug(&self, f: &mut ::core::fmt::Formatter<'_>)
-> ::core::fmt::Result {
::core::fmt::Debug::fmt(self, f)
}
#[inline]
fn reflect_clone(&self)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::ReflectCloneError> {
::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(::core::clone::Clone::clone(self)))
}
}
impl bevy_reflect::FromReflect for NavAction where {
fn from_reflect(__param0: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<Self> {
if let bevy_reflect::ReflectRef::Enum(__param0) =
bevy_reflect::PartialReflect::reflect_ref(__param0) {
match bevy_reflect::enums::Enum::variant_name(__param0) {
"Next" => ::core::option::Option::Some(NavAction::Next {}),
"Previous" =>
::core::option::Option::Some(NavAction::Previous {}),
"First" =>
::core::option::Option::Some(NavAction::First {}),
"Last" => ::core::option::Option::Some(NavAction::Last {}),
name => ::core::option::Option::None,
}
} else { ::core::option::Option::None }
}
}
};Reflect),
109 reflect(Debug, Clone, PartialEq)
110)]
111pub enum NavAction {
112 #[default]
116 Next,
117 Previous,
121 First,
125 Last,
129}
130
131#[derive(#[automatically_derived]impl ::core::fmt::Debug for TabNavigationError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::NoTabGroups =>
::core::fmt::Formatter::write_str(f, "NoTabGroups"),
Self::NoFocusableEntities =>
::core::fmt::Formatter::write_str(f, "NoFocusableEntities"),
Self::FailedToNavigateToNextFocusableEntity =>
::core::fmt::Formatter::write_str(f,
"FailedToNavigateToNextFocusableEntity"),
Self::NoTabGroupForCurrentFocus {
previous_focus: __self_0, new_focus: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"NoTabGroupForCurrentFocus", "previous_focus", __self_0,
"new_focus", &__self_1),
}
}
}Debug, #[allow(unused_qualifications)]
#[automatically_derived]
impl ::thiserror::__private21::Error for TabNavigationError { }
#[allow(unused_qualifications)]
#[automatically_derived]
impl ::core::fmt::Display for TabNavigationError {
fn fmt(&self, __formatter: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
use ::thiserror::__private21::AsDisplay as _;
#[allow(unused_variables, deprecated, clippy ::
used_underscore_binding)]
match self {
TabNavigationError::NoTabGroups {} =>
__formatter.write_str("No tab groups found"),
TabNavigationError::NoFocusableEntities {} =>
__formatter.write_str("No focusable entities found"),
TabNavigationError::FailedToNavigateToNextFocusableEntity {} =>
__formatter.write_str("Failed to navigate to next focusable entity"),
TabNavigationError::NoTabGroupForCurrentFocus {
previous_focus, new_focus } =>
match (previous_focus.as_display(),) {
(__display_previous_focus,) =>
__formatter.write_fmt(format_args!("No tab group found for currently focused entity {0}. Users will not be able to navigate back to this entity.",
__display_previous_focus)),
},
}
}
}Error, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
TabNavigationError {
}
#[automatically_derived]impl ::core::cmp::PartialEq for TabNavigationError {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other) &&
match (self, other) {
(Self::NoTabGroupForCurrentFocus {
previous_focus: __self_0, new_focus: __self_1 },
Self::NoTabGroupForCurrentFocus {
previous_focus: __arg1_0, new_focus: __arg1_1 }) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1,
_ => true,
}
}
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for TabNavigationError {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Entity>;
}
}Eq, #[automatically_derived]impl ::core::clone::Clone for TabNavigationError {
#[inline]
fn clone(&self) -> Self {
match self {
Self::NoTabGroups => TabNavigationError::NoTabGroups,
Self::NoFocusableEntities =>
TabNavigationError::NoFocusableEntities,
Self::FailedToNavigateToNextFocusableEntity =>
TabNavigationError::FailedToNavigateToNextFocusableEntity,
Self::NoTabGroupForCurrentFocus {
previous_focus: __self_0, new_focus: __self_1 } =>
TabNavigationError::NoTabGroupForCurrentFocus {
previous_focus: ::core::clone::Clone::clone(__self_0),
new_focus: ::core::clone::Clone::clone(__self_1),
},
}
}
}Clone)]
133pub enum TabNavigationError {
134 #[error("No tab groups found")]
136 NoTabGroups,
137 #[error("No focusable entities found")]
139 NoFocusableEntities,
140 #[error("Failed to navigate to next focusable entity")]
144 FailedToNavigateToNextFocusableEntity,
145 #[error("No tab group found for currently focused entity {previous_focus}. Users will not be able to navigate back to this entity.")]
147 NoTabGroupForCurrentFocus {
148 previous_focus: Entity,
151 new_focus: Entity,
155 },
156}
157
158#[doc(hidden)]
160#[derive(const _: () =
{
type __StructFieldsAlias<'w, 's> =
(Query<'w, 's, (Entity, &'static TabGroup, &'static Children)>,
Query<'w, 's,
(Entity, Option<&'static TabIndex>, Option<&'static Children>,
Option<&'static InheritedVisibility>), Without<TabGroup>>,
Query<'w, 's, &'static ChildOf>);
#[doc(hidden)]
pub struct FetchState {
state: <__StructFieldsAlias<'static, 'static> as
bevy_ecs::system::SystemParam>::State,
}
unsafe impl bevy_ecs::system::SystemParam for TabNavigation<'_, '_> {
type State = FetchState<>;
type Item<'w, 's> = TabNavigation<'w, 's>;
fn init_state(world: &mut bevy_ecs::world::World) -> Self::State {
FetchState {
state: <__StructFieldsAlias<'_, '_> as
bevy_ecs::system::SystemParam>::init_state(world),
}
}
fn init_access(state: &Self::State,
system_meta: &mut bevy_ecs::system::SystemMeta,
system_access: &mut bevy_ecs::system::SystemAccess,
world: &mut bevy_ecs::world::World) {
<__StructFieldsAlias<'_, '_> as
bevy_ecs::system::SystemParam>::init_access(&state.state,
system_meta, system_access, world);
}
fn apply(state: &mut Self::State,
system_meta: &bevy_ecs::system::SystemMeta,
world: &mut bevy_ecs::world::World) {
<__StructFieldsAlias<'_, '_> as
bevy_ecs::system::SystemParam>::apply(&mut state.state,
system_meta, world);
}
fn queue(state: &mut Self::State,
system_meta: &bevy_ecs::system::SystemMeta,
world: bevy_ecs::world::DeferredWorld) {
<__StructFieldsAlias<'_, '_> as
bevy_ecs::system::SystemParam>::queue(&mut state.state,
system_meta, world);
}
#[inline]
unsafe fn get_param<'w,
's>(state: &'s mut Self::State,
system_meta: &bevy_ecs::system::SystemMeta,
world:
bevy_ecs::world::unsafe_world_cell::UnsafeWorldCell<'w>,
change_tick: bevy_ecs::change_detection::Tick)
->
::core::result::Result<Self::Item<'w, 's>,
bevy_ecs::system::SystemParamValidationError> {
let (fieldtabgroup_query, fieldtabindex_query,
fieldparent_query) = &mut state.state;
let fieldtabgroup_query =
unsafe {
<Query<'w, 's,
(Entity, &'static TabGroup, &'static Children)> as
bevy_ecs::system::SystemParam>::get_param(fieldtabgroup_query,
system_meta, world, change_tick)
}.map_err(|err|
bevy_ecs::system::SystemParamValidationError::new::<Self>(err.skipped,
err.message, "::tabgroup_query"))?;
let fieldtabindex_query =
unsafe {
<Query<'w, 's,
(Entity, Option<&'static TabIndex>,
Option<&'static Children>,
Option<&'static InheritedVisibility>), Without<TabGroup>> as
bevy_ecs::system::SystemParam>::get_param(fieldtabindex_query,
system_meta, world, change_tick)
}.map_err(|err|
bevy_ecs::system::SystemParamValidationError::new::<Self>(err.skipped,
err.message, "::tabindex_query"))?;
let fieldparent_query =
unsafe {
<Query<'w, 's, &'static ChildOf> as
bevy_ecs::system::SystemParam>::get_param(fieldparent_query,
system_meta, world, change_tick)
}.map_err(|err|
bevy_ecs::system::SystemParamValidationError::new::<Self>(err.skipped,
err.message, "::parent_query"))?;
::core::result::Result::Ok(TabNavigation {
tabgroup_query: fieldtabgroup_query,
tabindex_query: fieldtabindex_query,
parent_query: fieldparent_query,
})
}
}
unsafe impl<'w, 's> bevy_ecs::system::ReadOnlySystemParam for
TabNavigation<'w, 's> where
Query<'w, 's,
(Entity, &'static TabGroup,
&'static Children)>: bevy_ecs::system::ReadOnlySystemParam,
Query<'w, 's,
(Entity, Option<&'static TabIndex>, Option<&'static Children>,
Option<&'static InheritedVisibility>),
Without<TabGroup>>: bevy_ecs::system::ReadOnlySystemParam,
Query<'w, 's,
&'static ChildOf>: bevy_ecs::system::ReadOnlySystemParam {}
};SystemParam)]
161pub struct TabNavigation<'w, 's> {
162 tabgroup_query: Query<'w, 's, (Entity, &'static TabGroup, &'static Children)>,
164 tabindex_query: Query<
166 'w,
167 's,
168 (
169 Entity,
170 Option<&'static TabIndex>,
171 Option<&'static Children>,
172 Option<&'static InheritedVisibility>,
173 ),
174 Without<TabGroup>,
175 >,
176 parent_query: Query<'w, 's, &'static ChildOf>,
178}
179
180impl TabNavigation<'_, '_> {
181 pub fn navigate(
191 &self,
192 focus: &InputFocus,
193 action: NavAction,
194 ) -> Result<Entity, TabNavigationError> {
195 if self.tabgroup_query.is_empty() {
197 return Err(TabNavigationError::NoTabGroups);
198 }
199
200 let tabgroup = focus.get().and_then(|focus_ent| {
203 self.parent_query
204 .iter_ancestors(focus_ent)
205 .find_map(|entity| {
206 self.tabgroup_query
207 .get(entity)
208 .ok()
209 .map(|(_, tg, _)| (entity, tg))
210 })
211 });
212
213 self.navigate_internal(focus.get(), action, tabgroup)
214 }
215
216 pub fn initialize(
222 &self,
223 parent: Entity,
224 action: NavAction,
225 ) -> Result<Entity, TabNavigationError> {
226 if self.tabgroup_query.is_empty() {
228 return Err(TabNavigationError::NoTabGroups);
229 }
230
231 match self.tabgroup_query.get(parent) {
233 Ok(tabgroup) => self.navigate_internal(None, action, Some((parent, tabgroup.1))),
234 Err(_) => Err(TabNavigationError::NoTabGroups),
235 }
236 }
237
238 pub fn navigate_internal(
239 &self,
240 focus: Option<Entity>,
241 action: NavAction,
242 tabgroup: Option<(Entity, &TabGroup)>,
243 ) -> Result<Entity, TabNavigationError> {
244 let navigation_result = self.navigate_in_group(tabgroup, focus, action);
245
246 match navigation_result {
247 Ok(entity) => {
248 if let Some(previous_focus) = focus
249 && tabgroup.is_none()
250 {
251 Err(TabNavigationError::NoTabGroupForCurrentFocus {
252 previous_focus,
253 new_focus: entity,
254 })
255 } else {
256 Ok(entity)
257 }
258 }
259 Err(e) => Err(e),
260 }
261 }
262
263 fn navigate_in_group(
264 &self,
265 tabgroup: Option<(Entity, &TabGroup)>,
266 focus: Option<Entity>,
267 action: NavAction,
268 ) -> Result<Entity, TabNavigationError> {
269 let mut focusable: Vec<(Entity, TabIndex, usize)> =
271 Vec::with_capacity(self.tabindex_query.iter().len());
272
273 match tabgroup {
274 Some((tg_entity, tg)) if tg.modal => {
275 if let Ok((_, _, children)) = self.tabgroup_query.get(tg_entity) {
277 for child in children.iter() {
278 self.gather_focusable(&mut focusable, *child, 0);
279 }
280 }
281 }
282 _ => {
283 let mut tab_groups: Vec<(Entity, TabGroup)> = self
285 .tabgroup_query
286 .iter()
287 .filter(|(_, tg, _)| !tg.modal)
288 .map(|(e, tg, _)| (e, *tg))
289 .collect();
290 tab_groups.sort_by_key(|(_, tg)| tg.order);
292
293 tab_groups
295 .iter()
296 .enumerate()
297 .for_each(|(idx, (tg_entity, _))| {
298 self.gather_focusable(&mut focusable, *tg_entity, idx);
299 });
300 }
301 }
302
303 if focusable.is_empty() {
304 return Err(TabNavigationError::NoFocusableEntities);
305 }
306
307 focusable.sort_by(|(_, a_tab_idx, a_group), (_, b_tab_idx, b_group)| {
309 if a_group == b_group {
310 a_tab_idx.cmp(b_tab_idx)
311 } else {
312 a_group.cmp(b_group)
313 }
314 });
315
316 let index = focusable.iter().position(|e| Some(e.0) == focus);
317 let count = focusable.len();
318 let next = match (index, action) {
319 (Some(idx), NavAction::Next) => (idx + 1).rem_euclid(count),
320 (Some(idx), NavAction::Previous) => (idx + count - 1).rem_euclid(count),
321 (None, NavAction::Next) | (_, NavAction::First) => 0,
322 (None, NavAction::Previous) | (_, NavAction::Last) => count - 1,
323 };
324 match focusable.get(next) {
325 Some((entity, _, _)) => Ok(*entity),
326 None => Err(TabNavigationError::FailedToNavigateToNextFocusableEntity),
327 }
328 }
329
330 fn gather_focusable(
332 &self,
333 out: &mut Vec<(Entity, TabIndex, usize)>,
334 parent: Entity,
335 tab_group_idx: usize,
336 ) {
337 if let Ok((entity, tabindex, children, inherited_visibility)) =
338 self.tabindex_query.get(parent)
339 {
340 if inherited_visibility.is_none_or(|v| v.get()) {
343 if let Some(tabindex) = tabindex
344 && tabindex.0 >= 0
345 {
346 out.push((entity, *tabindex, tab_group_idx));
347 }
348 if let Some(children) = children {
349 for child in children.iter() {
350 if self.tabgroup_query.get(*child).is_err() {
352 self.gather_focusable(out, *child, tab_group_idx);
353 }
354 }
355 }
356 }
357 } else if let Ok((_, tabgroup, children)) = self.tabgroup_query.get(parent)
358 && !tabgroup.modal
359 {
360 for child in children.iter() {
361 self.gather_focusable(out, *child, tab_group_idx);
362 }
363 }
364 }
365}
366
367#[cfg_attr(
382 feature = "bevy_picking",
383 doc = "This observer is also registered by
384[`PointerFocusPlugin`](crate::pointer_focus::PointerFocusPlugin) as a temporary bridge so pointer
385clicks can acquire focus without [`TabNavigationPlugin`]. Because `add_observer` does not
386deduplicate, it may therefore run twice per request when both plugins are present; keep it
387idempotent (stop propagation, only mutate focus on a real change) so the second run is a no-op."
388)]
389pub fn acquire_focus_tab_index(
390 mut acquire_focus: On<AcquireFocus>,
391 focusable: Query<(), (With<TabIndex>, Without<Window>)>,
392 mut focus: ResMut<InputFocus>,
393) {
394 if focusable.contains(acquire_focus.focused_entity) {
396 acquire_focus.propagate(false);
398 if focus.get() != Some(acquire_focus.focused_entity) {
400 focus.set(acquire_focus.focused_entity, FocusCause::Navigated);
401 }
402 }
403}
404
405pub struct TabNavigationPlugin;
407
408impl Plugin for TabNavigationPlugin {
409 fn build(&self, app: &mut App) {
410 app.add_systems(Startup, setup_tab_navigation);
411 app.add_observer(acquire_focus_tab_index);
412 }
413}
414
415fn setup_tab_navigation(mut commands: Commands, window: Query<Entity, With<PrimaryWindow>>) {
416 for window in window.iter() {
417 commands.entity(window).observe(handle_tab_navigation);
418 }
419}
420
421pub fn handle_tab_navigation(
428 mut event: On<FocusedInput<KeyboardInput>>,
429 nav: TabNavigation,
430 mut focus: ResMut<InputFocus>,
431 mut visible: ResMut<InputFocusVisible>,
432 keys: Res<ButtonInput<KeyCode>>,
433) {
434 let key_event = &event.input;
436 if key_event.key_code == KeyCode::Tab
437 && key_event.state == ButtonState::Pressed
438 && !key_event.repeat
439 {
440 let maybe_next = nav.navigate(
441 &focus,
442 if keys.pressed(KeyCode::ShiftLeft) || keys.pressed(KeyCode::ShiftRight) {
443 NavAction::Previous
444 } else {
445 NavAction::Next
446 },
447 );
448
449 match maybe_next {
450 Ok(next) => {
451 event.propagate(false);
452 focus.set(next, FocusCause::Navigated);
453 visible.0 = true;
454 }
455 Err(e) => {
456 {
{
let lvl = ::log::Level::Warn;
if lvl <= ::log::STATIC_MAX_LEVEL && lvl <= ::log::max_level() {
::log::__private_api::log({ ::log::__private_api::GlobalLogger },
format_args!("Tab navigation error: {0}", e), lvl,
&("bevy_input_focus::tab_navigation",
"bevy_input_focus::tab_navigation",
::log::__private_api::loc()), ());
}
}
};warn!("Tab navigation error: {e}");
457 if let TabNavigationError::NoTabGroupForCurrentFocus { new_focus, .. } = e {
459 event.propagate(false);
460 focus.set(new_focus, FocusCause::Navigated);
461 visible.0 = true;
462 }
463 }
464 }
465 }
466}
467
468#[cfg(test)]
469mod tests {
470 use bevy_ecs::system::SystemState;
471
472 use super::*;
473
474 #[test]
475 fn test_tab_navigation() {
476 let mut app = App::new();
477 let world = app.world_mut();
478
479 let tab_group_entity = world.spawn(TabGroup::new(0)).id();
480 let tab_entity_1 = world.spawn((TabIndex(0), ChildOf(tab_group_entity))).id();
481 let tab_entity_2 = world.spawn((TabIndex(1), ChildOf(tab_group_entity))).id();
482
483 let mut system_state: SystemState<TabNavigation> = SystemState::new(world);
484 let tab_navigation = system_state.get(world).unwrap();
485 assert_eq!(tab_navigation.tabgroup_query.iter().count(), 1);
486 assert!(tab_navigation.tabindex_query.iter().count() >= 2);
487
488 let next_entity =
489 tab_navigation.navigate(&InputFocus::from_entity(tab_entity_1), NavAction::Next);
490 assert_eq!(next_entity, Ok(tab_entity_2));
491
492 let prev_entity =
493 tab_navigation.navigate(&InputFocus::from_entity(tab_entity_2), NavAction::Previous);
494 assert_eq!(prev_entity, Ok(tab_entity_1));
495
496 let first_entity = tab_navigation.navigate(&InputFocus::default(), NavAction::First);
497 assert_eq!(first_entity, Ok(tab_entity_1));
498
499 let last_entity = tab_navigation.navigate(&InputFocus::default(), NavAction::Last);
500 assert_eq!(last_entity, Ok(tab_entity_2));
501 }
502
503 #[test]
504 fn test_tab_navigation_between_groups_is_sorted_by_group() {
505 let mut app = App::new();
506 let world = app.world_mut();
507
508 let tab_group_1 = world.spawn(TabGroup::new(0)).id();
509 let tab_entity_1 = world.spawn((TabIndex(0), ChildOf(tab_group_1))).id();
510 let tab_entity_2 = world.spawn((TabIndex(1), ChildOf(tab_group_1))).id();
511
512 let tab_group_2 = world.spawn(TabGroup::new(1)).id();
513 let tab_entity_3 = world.spawn((TabIndex(0), ChildOf(tab_group_2))).id();
514 let tab_entity_4 = world.spawn((TabIndex(1), ChildOf(tab_group_2))).id();
515
516 let mut system_state: SystemState<TabNavigation> = SystemState::new(world);
517 let tab_navigation = system_state.get(world).unwrap();
518 assert_eq!(tab_navigation.tabgroup_query.iter().count(), 2);
519 assert!(tab_navigation.tabindex_query.iter().count() >= 4);
520
521 let next_entity =
522 tab_navigation.navigate(&InputFocus::from_entity(tab_entity_1), NavAction::Next);
523 assert_eq!(next_entity, Ok(tab_entity_2));
524
525 let prev_entity =
526 tab_navigation.navigate(&InputFocus::from_entity(tab_entity_2), NavAction::Previous);
527 assert_eq!(prev_entity, Ok(tab_entity_1));
528
529 let first_entity = tab_navigation.navigate(&InputFocus::default(), NavAction::First);
530 assert_eq!(first_entity, Ok(tab_entity_1));
531
532 let last_entity = tab_navigation.navigate(&InputFocus::default(), NavAction::Last);
533 assert_eq!(last_entity, Ok(tab_entity_4));
534
535 let next_from_end_of_group_entity =
536 tab_navigation.navigate(&InputFocus::from_entity(tab_entity_2), NavAction::Next);
537 assert_eq!(next_from_end_of_group_entity, Ok(tab_entity_3));
538
539 let prev_entity_from_start_of_group =
540 tab_navigation.navigate(&InputFocus::from_entity(tab_entity_3), NavAction::Previous);
541 assert_eq!(prev_entity_from_start_of_group, Ok(tab_entity_2));
542 }
543
544 fn acquire_focus_app() -> (App, Entity) {
548 use crate::InputFocusPlugin;
549 use bevy_input::InputPlugin;
550
551 let mut app = App::new();
552 app.add_plugins((InputPlugin, InputFocusPlugin, TabNavigationPlugin));
553 let window = app
554 .world_mut()
555 .spawn((Window::default(), PrimaryWindow))
556 .id();
557 app.update();
559 (app, window)
560 }
561
562 #[test]
563 fn acquire_focus_focuses_entity_with_tab_index() {
564 let (mut app, window) = acquire_focus_app();
565
566 let focusable = app.world_mut().spawn(TabIndex(0)).id();
567
568 app.world_mut().trigger(AcquireFocus {
569 focused_entity: focusable,
570 window,
571 });
572 app.update();
573
574 assert_eq!(app.world().resource::<InputFocus>().get(), Some(focusable));
575 }
576
577 #[test]
578 fn acquire_focus_does_not_focus_entity_without_tab_index() {
579 let (mut app, window) = acquire_focus_app();
580
581 let non_focusable = app.world_mut().spawn(ChildOf(window)).id();
586 app.world_mut().trigger(AcquireFocus {
587 focused_entity: non_focusable,
588 window,
589 });
590 app.update();
591
592 assert_ne!(
593 app.world().resource::<InputFocus>().get(),
594 Some(non_focusable)
595 );
596 assert_eq!(app.world().resource::<InputFocus>().get(), None);
597 }
598}