203 lines
9.6 KiB
GDScript
203 lines
9.6 KiB
GDScript
extends HBoxContainer
|
||
## 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).
|
||
##
|
||
## NACHBESSERUNG 20.10. (Operator, Sly-Befund „Damit kann man nicht mehr
|
||
## arbeiten"): Diese Leiste erbte von EditorPanel (= VBoxContainer) und wurde
|
||
## dadurch SELBST senkrecht — jeder Knopf bekam eine eigene, fensterbreite
|
||
## Zeile, die Leiste wuchs auf ~11×40 px und drückte das 3D-Fenster auf einen
|
||
## Briefmarken-Streifen. Eine Leiste braucht eine WAAGERECHTE Zeile: extends
|
||
## HBoxContainer. Die Helfer der Basis (main-Zeiger, Label-Bauer) braucht nur
|
||
## die senkrechte Spalte; hier genügt der main-Zeiger.
|
||
|
||
var main # src/ui/main.gd (script-erweitert → untypisiert)
|
||
|
||
|
||
func setup(p_main) -> void:
|
||
main = p_main
|
||
# Eine Leiste darf NIE in die Höhe wachsen (sie würde dem 3D-Fenster die
|
||
# Fläche wegnehmen): genau eine Knopfzeile, oben ausgerichtet.
|
||
size_flags_vertical = Control.SIZE_SHRINK_BEGIN
|
||
size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||
|
||
|
||
func panel_title() -> String:
|
||
return "Werkzeuge"
|
||
|
||
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(8)) # U7-Raster (4/8)
|
||
|
||
var file_menu := MenuButton.new()
|
||
file_menu.text = "Datei"
|
||
file_menu.flat = false
|
||
file_menu.custom_minimum_size = UIScale.v2(90, 40)
|
||
# U7: Klartext-Tooltip am Datei-Menü (alle Map-Aktionen an einem Ort).
|
||
file_menu.tooltip_text = "Map-Aktionen: neu, öffnen, speichern, testen, Updates"
|
||
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)
|
||
# FIX 20.10. (Sly-Befund „Kartengröße ändern tut nichts“): id_pressed sendet
|
||
# die Menü-ID. main.call.bind("_on_menu_action") hängt die ID aber ALS
|
||
# ARGUMENT an call() → effektiv call(6, "_on_menu_action") →
|
||
# „Cannot convert argument 1 from int to StringName“ (map-builder.log
|
||
# 20.10.) — das GESAMTE Datei-Menü verpufft, kein Eintrag tut etwas.
|
||
# Lambda macht die Reihenfolge (Name zuerst, ID als Argument) explizit,
|
||
# Stil wie grid_btn/contours_btn oben.
|
||
popup.id_pressed.connect(func(id: int) -> void: main.call("_on_menu_action", id))
|
||
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"])))
|
||
# Test-Start ist ein Umschalter: main liest/setzt seinen Zustand
|
||
# (Prüfsuite test_playtest_spawn.gd erwartet main.test_start_btn).
|
||
if str(entry["id"]) == "teststart":
|
||
btn.toggle_mode = true
|
||
main.set("test_start_btn", btn)
|
||
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)
|
||
|
||
var help_btn := Button.new()
|
||
help_btn.text = "❓ Hilfe"
|
||
help_btn.name = "hilfe"
|
||
help_btn.custom_minimum_size = UIScale.v2(110, 40)
|
||
help_btn.tooltip_text = "Werkzeuge, Steuerung und Tastenkürzel (H)"
|
||
help_btn.pressed.connect(func() -> void: main.call("_toggle_help_overlay"))
|
||
add_child(help_btn)
|
||
|
||
title_label = Label.new()
|
||
title_label.text = " %s" % main.APP_TITLE
|
||
title_label.add_theme_font_size_override("font_size", UIScale.heading_font_size())
|
||
# 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 = ""
|
||
# U7: Farbe über Theme (Editor/colors/title) statt modulate-Wert im Code.
|
||
file_label.add_theme_color_override("font_color",
|
||
main.theme.get_color("title", "Editor"))
|
||
# 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)
|