Menu als state im Mode-System

This commit is contained in:
2026-06-13 19:24:28 +02:00
parent a41d39cc78
commit d584e418f5
4 changed files with 165 additions and 43 deletions
+32 -5
View File
@@ -20,9 +20,12 @@ pub enum Mode {
/// Freie Welt — das Fenster rendert die Szene, die Konsole nimmt
/// Engine-Befehle.
Free,
/// Ein Dialog läuft — das Fenster pausiert die Welt und zeigt (sobald
/// Text-Rendering existiert) Panels; Eingaben treiben den Dialog statt
/// Befehle.
/// Menü offen — wie der Dialog pausiert das Fenster die Welt und gibt die
/// Maus frei; Eingaben sind weiter Engine-Befehle (das Menü ist nur eine
/// andere Darstellung). Per `menu`-Befehl getoggelt.
Menu,
/// Ein Dialog läuft — das Fenster pausiert die Welt und zeigt Panels;
/// Eingaben treiben den Dialog statt Befehle.
Dialog(Dialog),
}
@@ -73,8 +76,8 @@ impl Session {
/// Klick denselben Dialog ohne Sonderpfad.
pub fn exec(&mut self, line: &str) -> ExecResult {
match self.mode {
Mode::Dialog(_) => self.dialog_input(line),
Mode::Free => self.command(line),
Mode::Dialog(_) => self.dialog_input(line),
Mode::Free | Mode::Menu => self.command(line),
}
}
@@ -83,6 +86,15 @@ impl Session {
match line {
"" => ExecResult::empty(),
"quit" | "exit" => ExecResult { output: Vec::new(), quit: true },
"menu" => {
// Free ↔ Menu umschalten (erreichbar nur aus diesen beiden,
// da Dialog anders geroutet wird).
self.mode = match self.mode {
Mode::Menu => Mode::Free,
_ => Mode::Menu,
};
ExecResult::empty()
}
"help" => ExecResult::lines(help()),
"kv" => ExecResult::lines(self.dump_kv()),
"reload" => {
@@ -189,6 +201,7 @@ fn help() -> Vec<String> {
" use <instance> Objekt-Interaktion simulieren — `use Mushroom.005`".into(),
" feuert Signal `Mushroom` mit $self = Mushroom.005".into(),
" kv KV-Store anzeigen".into(),
" menu Menü öffnen/schließen".into(),
" reload signals.toml neu laden".into(),
" quit beenden".into(),
]
@@ -218,6 +231,20 @@ mod tests {
assert!(matches!(s.mode, Mode::Free));
}
#[test]
fn menu_command_toggles_free_and_menu() {
let mut s = empty_session();
assert!(matches!(s.mode, Mode::Free));
s.exec("menu");
assert!(matches!(s.mode, Mode::Menu));
s.exec("menu");
assert!(matches!(s.mode, Mode::Free));
// Im Menü laufen Engine-Befehle weiter (gleiche Route wie Free).
s.exec("menu");
s.exec("signal set in_menu true");
assert!(s.game.kv["in_menu"].coerce_to_bool().unwrap());
}
#[test]
fn unknown_command_reports_and_stays_free() {
let mut s = empty_session();