extends "res://src/ui/panels/editor_panel.gd" ## Toolbar (aus main.gd ausgezogen, Karte t_eaccbfed U1 — Logik unverändert): ## Menü Datei + Undo/Redo + Gitter/Höhenlinien + Symmetrie + Toolbar-Aktionen ## aus der Registry (Karte prüfen, ▶ Karte testen). Neue Aktionen melden sich ## künftig in registry.gd an (U2–U7, T1-F5 bleibt unverändert erreichbar). var undo_btn: Button var redo_btn: Button var grid_btn: Button # „⊞ Gitter“ (Karte t_7ac70014) var contours_btn: Button # „≈ Höhenlinien“ (Karte t_3ebe4086) var sym_menu: MenuButton var size_menu: MenuButton # „UI-Größe“ (Karte t_297221b5) var title_label: Label var file_label: Label static func spec() -> Dictionary: return {"titel": "Toolbar", "gruppe": "toolbar", "order": 0} func build() -> void: add_theme_constant_override("separation", UIScale.px(10)) var file_menu := MenuButton.new() file_menu.text = "Datei" file_menu.flat = false file_menu.custom_minimum_size = UIScale.v2(90, 40) var popup := file_menu.get_popup() popup.add_item("Neue Map…", 0) popup.add_item("Öffnen…", 1) popup.add_item("Kartengröße ändern…", 6) popup.add_separator() popup.add_item("Speichern (Strg+S)", 2) popup.add_item("Speichern unter…", 3) popup.add_separator() popup.add_item("▶ Karte testen", 5) popup.add_separator() popup.add_item("🔄 Updates prüfen", 7) popup.add_item("Beenden", 4) popup.id_pressed.connect(main.call.bind("_on_menu_action")) add_child(file_menu) undo_btn = Button.new() undo_btn.text = "↩ Rückgängig" undo_btn.custom_minimum_size = UIScale.v2(140, 40) undo_btn.tooltip_text = "Letzte Aktion zurücknehmen (Strg+Z)" undo_btn.pressed.connect(main.call.bind("_do_undo")) add_child(undo_btn) redo_btn = Button.new() redo_btn.text = "↪ Wiederholen" redo_btn.custom_minimum_size = UIScale.v2(150, 40) redo_btn.tooltip_text = "Zurückgenommene Aktion wiederherstellen (Strg+Y)" redo_btn.pressed.connect(main.call.bind("_do_redo")) add_child(redo_btn) # Maßstabsgitter-Toggle (Karte t_7ac70014): über sichtbarem Terrain ist das # Gitter standardmäßig AUS (das Terrain ist die Bodendarstellung); wer das # 100-m-Raster als Planungshilfe will, schaltet es hier ohne Rebuild zu. grid_btn = Button.new() grid_btn.text = "⊞ Gitter" grid_btn.toggle_mode = true grid_btn.button_pressed = false grid_btn.custom_minimum_size = UIScale.v2(120, 40) grid_btn.tooltip_text = "Maßstabsgitter (100-m-Raster) im Viewport ein-/ausblenden. Über sichtbarem Terrain ist es standardmäßig aus." grid_btn.toggled.connect(func(pressed: bool) -> void: main.call("_on_grid_toggled", pressed)) add_child(grid_btn) # Höhenlinien-Button (Karte t_3ebe4086, Kopplung t_89c0ec95): drücken = # LINIEN FIXIEREN (immer sichtbar, in jedem Werkzeug). Ohne Fix sind die # Linien NUR im Terrain-Werkzeug (F1) sichtbar; auf flachen Maps (< 2 m # Gesamtrelief) schaltet das Terrain-Mesh zusätzlich selbst auf aus. contours_btn = Button.new() contours_btn.text = "≈ Höhenlinien" contours_btn.toggle_mode = true contours_btn.button_pressed = false contours_btn.custom_minimum_size = UIScale.v2(150, 40) contours_btn.tooltip_text = "Höhenlinien (1 m, alle 5 m kräftiger) FIXIERT an/aus. Ohne Fixierung erscheinen sie nur im Terrain-Werkzeug (F1). Taste L schaltet ebenfalls. Bei flachem Terrain (< 2 m) sind sie automatisch aus." contours_btn.toggled.connect(func(pressed: bool) -> void: main.call("_on_contours_toggled", pressed)) add_child(contours_btn) # Symmetrie-Schalter (Karte t_f5935023, M1): Aus / Punkt / Achse X / Achse Z. # Standard = Punktspiegelung (Sly 20.10.). M1 setzt nur Modus + Anzeige; # das gespiegelte Bauen selbst kommt mit M2–M4. sym_menu = MenuButton.new() sym_menu.text = "Symmetrie: Punkt" sym_menu.flat = false sym_menu.custom_minimum_size = UIScale.v2(160, 40) sym_menu.tooltip_text = "Gespiegeltes Bauen: Änderungen werden automatisch auf die andere Kartenseite übertragen. Aus / Punkt (180° um die Kartenmitte) / Achse X / Achse Z. Standard: Punkt." var sym_popup := sym_menu.get_popup() for i in SymmetryCore.MODE_LABELS.size(): sym_popup.add_check_item(SymmetryCore.MODE_LABELS[i], i) sym_popup.index_pressed.connect(func(index: int) -> void: main.call("_on_sym_mode_selected", index)) add_child(sym_menu) # Toolbar-Aktionen DATENGETRIEBEN aus der Registry (Operator-Vorgabe # 20.10.): Karte prüfen, ▶ Karte testen — künftige Karten melden sich # hier an, ohne main.gd anzufassen. Die Buttons bekommen den Registry-Namen # als Node-Namen (main kann sie per get_node/find_child ansprechen, z. B. # der Shake-Effekt beim fehlgeschlagenen Map-Check). for entry in PanelRegistry.toolbar_actions(): var btn := Button.new() btn.text = str(entry["titel"]) btn.name = str(entry["id"]) if str(entry["id"]) == "karte_pruefen": btn.custom_minimum_size = UIScale.v2(170, 40) btn.tooltip_text = "Prüft, ob die Map bereit für den Export ist — sagen wir VORHER, was fehlt" else: btn.custom_minimum_size = UIScale.v2(190, 40) btn.tooltip_text = "Startet die Map SOFORT als Spiel zum Durchlaufen — eigenes Fenster, der Editor bleibt offen. ESC im Spiel = zurück zum Editor." btn.pressed.connect(main.call.bind(str(entry["action"]))) add_child(btn) # UI-Größe (Karte t_297221b5): Klein/Mittel/Groß — Sly stellt das selbst um, # es wirkt SOFORT (kompletter UI-Neuaufbau mit dem neuen Faktor) und bleibt # in user://scopedvr_editor.cfg gespeichert. size_menu = MenuButton.new() size_menu.text = "UI-Größe" size_menu.flat = false size_menu.custom_minimum_size = UIScale.v2(120, 40) size_menu.tooltip_text = "Größe der Oberfläche: Klein (wie bisher), Mittel (1,25-fach), Groß (1,5-fach). Wirkt sofort und bleibt gespeichert." var size_popup := size_menu.get_popup() for i in UIScale.step_count(): size_popup.add_check_item(UIScale.step_label(i), i) # Häkchen-Sync macht der KOORDINATOR nach _pull_toolbar_refs (hier ist # main.size_menu noch null — alter Reihenfolge-Bug, Karte t_eaccbfed). size_popup.index_pressed.connect(func(index: int) -> void: main.call("_on_ui_size_selected", index)) add_child(size_menu) title_label = Label.new() title_label.text = " %s" % main.APP_TITLE title_label.add_theme_font_size_override("font_size", UIScale.f(20)) # Karte t_297221b5: bei großer Stufe darf der Titel EGALISIEREN statt die # Top-Bar aus dem Fenster zu drücken (Mindestbreite der Schrift skaliert mit). # Mindestbreite, damit er nicht KOMPLETT verschwindet (Ellipsis macht "Scop…"). # Expand: bei Platz bekommt er seine VOLLSTÄNDIGE natürliche Breite (wie # Vorher bei „Klein“), erst bei knappem Fenster egalisiert er mit "…". title_label.custom_minimum_size = UIScale.v2(180, 0) title_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL title_label.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS title_label.clip_text = true add_child(title_label) var spacer := Control.new() spacer.size_flags_horizontal = Control.SIZE_EXPAND_FILL add_child(spacer) file_label = Label.new() file_label.text = "" file_label.modulate = Color(1, 1, 1, 0.6) # Karte t_297221b5: Map-Pfad darf bei großer Stufe egalisiert werden # (Voller Name im Tooltip, sonst drückt die Zeile die Top-Bar aus dem Fenster). # Expand: bekommt zusammen mit dem Spacer seinen Anteil, egalisiert mit "…". file_label.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS file_label.clip_text = true file_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL add_child(file_label)