-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
switch.rs
77 lines (66 loc) · 2.18 KB
/
switch.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
use std::marker::PhantomData;
use bevy::{prelude::*, reflect::GetTypeRegistration};
#[macro_export]
macro_rules! switchable_impl {
($($button:ident [$root:ident, $event:ident]),* $(,)?) => {
$(
#[derive(Event)]
pub struct $event(pub u8);
#[derive(Component, Default, Reflect)]
#[reflect(Component)]
pub struct $root;
#[derive(Component, Default, Reflect)]
#[reflect(Component)]
pub struct $button(pub u8);
impl $crate::Switchable for $button { type Event = $event; type Marker = $root; }
$crate::switchable_impl! {@getindex $event, $button }
)*
};
(@getindex $($impls:ident),* $(,)?) => {
$(impl $crate::switch::GetIndex for $impls { fn index(&self) -> u8 { self.0 } })*
};
}
pub trait GetIndex {
fn index(&self) -> u8;
}
pub trait Switchable: Component + GetIndex + Reflect + GetTypeRegistration {
type Event: Event + GetIndex;
type Marker: Component + Reflect + GetTypeRegistration + Default;
}
fn switch_tab<T: Switchable>(
mut tab_requests: EventReader<T::Event>,
mut vis: Query<&mut Visibility>,
tab_menu: Query<&Children, With<T::Marker>>,
) {
// ANCHOR: system
use Visibility::{Hidden, Inherited};
for req in tab_requests.read() {
let Ok(menu_children) = tab_menu.get_single() else {
continue;
};
let mut i = 0;
let mut iter = vis.iter_many_mut(menu_children);
while let Some(mut vis) = iter.fetch_next() {
*vis = if i == req.index() { Inherited } else { Hidden };
i += 1;
}
}
// ANCHOR_END: system
}
pub struct SwitchPlugin<T>(PhantomData<T>);
#[rustfmt::skip]
impl<T: Switchable> Default for SwitchPlugin<T> {
fn default() -> Self { Self::new() }
}
#[rustfmt::skip]
impl<T: Switchable> SwitchPlugin<T> {
#[must_use] pub fn new() -> Self { Self(PhantomData) }
}
impl<T: Switchable> Plugin for SwitchPlugin<T> {
fn build(&self, app: &mut App) {
app.add_event::<T::Event>()
.register_type::<T::Marker>()
.register_type::<T>()
.add_systems(Update, switch_tab::<T>);
}
}