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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//! Actions that can be performed by the buttons in the settings menu.

use bevy::prelude::*;

use game_library::state::{AppState, Overlay, Settings};

use super::events::{ChangeSetting, IndividualSetting};

/// All of the various "buttons" that can be clicked in any of the main menu screens
#[derive(Component, Debug, Eq, PartialEq, Hash, Clone, Copy)]
pub(super) enum ButtonAction {
    /// Close the menu.
    CloseMenu,
    /// Go back to the "main" settings menu.
    BackToMenu,
    /// Go to the audio menu
    SettingsAudio,
    /// Go to the display menu
    SettingsDisplay,
    /// Go to the controls menu
    SettingsControls,
    /// Go to the gameplay menu
    SettingsGameplay,
    /// Go to the accessibility menu
    SettingsAccessibility,
    /// Toggle Auto-Cast
    ToggleAutoCast,
    /// Toggle Auto-Aim
    ToggleAutoAim,
    /// Change the font family
    RotateFontFamily,
    /// Increment the main volume
    IncrementMainVolume,
    /// Increment the music volume
    IncrementMusicVolume,
    /// Increment the sound effects volume
    IncrementSoundEffectsVolume,
    /// Go to the Main Menu of the game
    GoToMainGameMenu,
}

#[derive(Component, Debug, Clone, PartialEq, Eq, Hash)]
pub(super) struct SettingsMenuButton;

/// System to handle the main menu button actions
///
/// * `interaction_query`: grabs all the buttons that have been interacted with, with the components
///    Interaction and `ButtonAction` that have a changed interaction value (i.e. the button has been
///   pressed)
/// * `app_exit_events`: can be used to send an `AppExit` event to exit the game
/// * `menu_state(next)`: lets us change the menu state for the next frame
/// * `game_state(next)`: lets us change the game state for the next frame
#[allow(clippy::type_complexity)]
pub fn menu_actions(
    interaction_query: Query<
        (&Interaction, &ButtonAction),
        (Changed<Interaction>, With<Button>, With<SettingsMenuButton>),
    >,
    mut menu_state: ResMut<NextState<Settings>>,
    mut game_state: ResMut<NextState<AppState>>,
    mut overlay_state: ResMut<NextState<Overlay>>,
    mut ew_change_setting: EventWriter<ChangeSetting>,
) {
    // Loop through all the buttons that have been interacted with
    for (interaction, menu_button_action) in &interaction_query {
        // If the button has been pressed, match the button action
        if *interaction == Interaction::Pressed {
            // Check which button action has been pressed (i.e. what action we attached to the button)
            match menu_button_action {
                ButtonAction::CloseMenu => {
                    menu_state.set(Settings::Disabled);
                    overlay_state.set(Overlay::None);
                }
                ButtonAction::GoToMainGameMenu => {
                    menu_state.set(Settings::Disabled);
                    game_state.set(AppState::MainMenu);
                }
                ButtonAction::BackToMenu => menu_state.set(Settings::Main),
                ButtonAction::SettingsAudio => menu_state.set(Settings::Audio),
                ButtonAction::SettingsDisplay => menu_state.set(Settings::Display),
                ButtonAction::SettingsControls => menu_state.set(Settings::Controls),
                ButtonAction::SettingsGameplay => menu_state.set(Settings::Gameplay),
                ButtonAction::SettingsAccessibility => menu_state.set(Settings::Accessibility),
                ButtonAction::ToggleAutoCast => {
                    ew_change_setting.send(ChangeSetting {
                        setting: IndividualSetting::AutoCast,
                    });
                }
                ButtonAction::ToggleAutoAim => {
                    ew_change_setting.send(ChangeSetting {
                        setting: IndividualSetting::AutoAim,
                    });
                }
                ButtonAction::RotateFontFamily => {
                    ew_change_setting.send(ChangeSetting {
                        setting: IndividualSetting::FontFamily,
                    });
                }
                ButtonAction::IncrementMainVolume => {
                    ew_change_setting.send(ChangeSetting {
                        setting: IndividualSetting::MainVolume,
                    });
                }
                ButtonAction::IncrementMusicVolume => {
                    ew_change_setting.send(ChangeSetting {
                        setting: IndividualSetting::MusicVolume,
                    });
                }
                ButtonAction::IncrementSoundEffectsVolume => {
                    ew_change_setting.send(ChangeSetting {
                        setting: IndividualSetting::SoundEffectsVolume,
                    });
                }
            }
        }
    }
}