Skip to main content

traaains/ui/track/segment/signals_list/item/data/
main_state_select.rs

1use bevy::{
2    ecs::{
3        entity::Entity, event::EntityEvent, hierarchy::ChildOf, observer::On, query::With,
4        system::Query,
5    },
6    feathers::controls::{FeathersSelect, OptionIndex, list_rows_from_strings},
7    log::tracing,
8    scene::{Scene, bsn, on},
9    ui_widgets::ValueChange,
10};
11use strum::IntoEnumIterator;
12
13use crate::{
14    sim::signal::{
15        Signals,
16        main::{MainSignalState, MainSignalStateDiscriminants},
17    },
18    ui::{
19        Target,
20        segment::signals_list::item::{SignalListItem, find_root_with_target},
21    },
22};
23
24fn on_value_change(
25    e: On<ValueChange<Entity>>,
26    options: Query<&OptionIndex>,
27    target: Query<(Entity, &Target), With<SignalListItem>>,
28    children: Query<&ChildOf>,
29    mut signals: Query<&mut Signals>,
30) {
31    let Some((_, target_signal)) = find_root_with_target(e.event_target(), &target, &children)
32    else {
33        tracing::error!(
34            "Could not find parent UI entity with a target component pointing to a signal!"
35        );
36        return;
37    };
38
39    // TODO: Add a check to not switch between same states?
40    if let Ok(option) = options.get(e.value)
41        && let Ok(mut signal) = signals.get_mut(target_signal)
42    {
43        match &mut *signal {
44            Signals::Main(main_signal) => {
45                match MainSignalStateDiscriminants::try_from(option.0).unwrap() {
46                    MainSignalStateDiscriminants::Stop => {
47                        main_signal.state = MainSignalState::Stop { summon: false }
48                    }
49                    MainSignalStateDiscriminants::Warning => {
50                        main_signal.state = MainSignalState::Warning {
51                            max_speed: None,
52                            next_speed: None,
53                        }
54                    }
55                    MainSignalStateDiscriminants::Free => {
56                        main_signal.state = MainSignalState::Free { max_speed: None }
57                    }
58                }
59            }
60            _ => panic!("Invalid signal"),
61        }
62    }
63}
64
65pub fn main_state_select(curr_state: MainSignalStateDiscriminants) -> impl Scene {
66    bsn! {
67        @FeathersSelect {
68            @options: list_rows_from_strings(MainSignalStateDiscriminants::iter().map(|s| s.to_string()), MainSignalStateDiscriminants::iter().enumerate().find_map(|(i, v)| {
69                if v == curr_state {
70                    return Some(i);
71                }
72
73                None
74            })),
75        }
76        on(on_value_change)
77    }
78}