scopedvr-map-core/ui/panels/settings_panel.gd
2026-11-01 19:31:33 +01:00

160 lines
7.2 KiB
GDScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

extends "res://core/ui/panels/editor_panel.gd"
## Einstellungen (Fenster „⚙ Einstellungen“ in der Kopfleiste — Karte
## t_aaff5dcc, T3 Komfort; 25.10. Test-Befund: Gitter, Höhenlinien, Symmetrie-
## Modus, UI-Größe, Raster-Snap, Gizmo-Schrittweite und „Karte prüfen“ ziehen
## aus Kopfleiste/Objekt-Werkzeugen hierher).
##
## Registry-Weg (Operator-Vorgabe 20.10.): main.gd bleibt unangetastet, das
## Modul meldet sich nur über core/ui/panels/registry.gd an. Der ZUSTAND lebt
## in core/editor/playtest/playtest_settings.gd (PlaytestSettings, user://-cfg) —
## dieses Panel zeigt/anpasst nur. Läuft gerade ein Testlauf, wird die neue
## Maus-Empfindlichkeit SOFORT über main.playtest.apply_sensitivity wirksam.
var sens_box: SpinBox
## Perspektive im Testlauf (Karte t_17a35c59): Erste/Dritte Person, derselbe
## Eintrag wie Taste V (PlaytestSettings, persistiert).
var perspektive_box: OptionButton
# Ansicht / Platzieren (vorher Kopfleiste und Tab „Objekt-Werkzeuge“). main
# hält dieselben Namen als Referenzen (grid_btn, contours_btn, size_menu, …).
var grid_btn: CheckButton
var contours_btn: CheckButton
var size_menu: OptionButton
var sym_menu: OptionButton
var raster_snap_check: CheckButton
var gizmo_step_box: SpinBox
var check_btn: Button
static func spec() -> Dictionary:
return {"titel": "Einstellungen", "gruppe": "dialog", "order": 10}
func panel_title() -> String:
return "Einstellungen"
func build() -> void:
add_child(_header_label("Ansicht"))
grid_btn = CheckButton.new()
grid_btn.text = "⊞ Maßstabsgitter (100-m-Raster)"
grid_btn.custom_minimum_size = UIScale.v2(0, 36)
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)
contours_btn = CheckButton.new()
contours_btn.text = "≈ Höhenlinien fixieren"
contours_btn.custom_minimum_size = UIScale.v2(0, 36)
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)
add_child(_field_label("UI-Größe"))
size_menu = OptionButton.new()
for i in UIScale.step_count():
size_menu.add_item(UIScale.step_label(i), i)
size_menu.custom_minimum_size = UIScale.v2(0, 36)
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."
size_menu.item_selected.connect(func(index: int) -> void: main.call("_on_ui_size_selected", index))
add_child(size_menu)
add_child(_separator())
add_child(_header_label("Bauen & Platzieren"))
raster_snap_check = CheckButton.new()
raster_snap_check.text = "Raster-Snap (1 m)"
raster_snap_check.custom_minimum_size = UIScale.v2(0, 36)
raster_snap_check.tooltip_text = "Neue und verschobene Objekte rasten auf ein 1-Meter-Raster ein (Strg gedrückt halten geht immer)"
raster_snap_check.toggled.connect(func(pressed: bool) -> void: main.call("_on_grid_snap_changed", pressed))
add_child(raster_snap_check)
add_child(_field_label("Gizmo-Schrittweite (m)"))
gizmo_step_box = SpinBox.new()
gizmo_step_box.min_value = 0.01
gizmo_step_box.max_value = 10.0
gizmo_step_box.step = 0.01
gizmo_step_box.value = main.gizmo_step_m
gizmo_step_box.custom_minimum_size = UIScale.v2(0, 36)
gizmo_step_box.tooltip_text = "Wie weit bewegt sich das Objekt am Achsen-Gizmo pro Schritt (in Metern). Mausrad WÄHREND des Ziehens wechselt zwischen fein (0.1) / normal (0.5) / grob (2.0)."
gizmo_step_box.value_changed.connect(func(v: float) -> void:
main.gizmo_step_m = v
if main.gizmo != null and is_instance_valid(main.gizmo):
main.gizmo.set_step_m(v))
add_child(gizmo_step_box)
add_child(_separator())
add_child(_header_label("Symmetrie & Prüfen"))
add_child(_field_label("Symmetrie-Modus"))
sym_menu = OptionButton.new()
for i in SymmetryCore.MODE_LABELS.size():
sym_menu.add_item("Symmetrie: %s" % SymmetryCore.MODE_LABELS[i], i)
sym_menu.custom_minimum_size = UIScale.v2(0, 36)
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."
sym_menu.item_selected.connect(func(index: int) -> void: main.call("_on_sym_mode_selected", index))
add_child(sym_menu)
check_btn = Button.new()
check_btn.text = "✅ Karte prüfen"
check_btn.custom_minimum_size = UIScale.v2(0, 40)
check_btn.tooltip_text = "Prüft, ob die Map bereit für den Export ist — sagt VORHER, was fehlt"
check_btn.pressed.connect(func() -> void: main.call("_on_check_map"))
add_child(check_btn)
add_child(_separator())
add_child(_header_label("Testlauf-Einstellungen"))
add_child(_field_label("Maus-Empfindlichkeit (0,1 – 5,0)"))
sens_box = SpinBox.new()
sens_box.min_value = PlaytestSettings.MIN_SENS
sens_box.max_value = PlaytestSettings.MAX_SENS
sens_box.step = 0.1
sens_box.value = PlaytestSettings.load_sens()
sens_box.custom_minimum_size = UIScale.v2(0, 36)
sens_box.tooltip_text = "Multiplikator auf die Blick-Geschwindigkeit im Testlauf. 1,0 = Standard; kleine Werte = feinfühlig, große Werte = schnell."
sens_box.value_changed.connect(_on_sens_changed)
add_child(sens_box)
add_child(_field_label("Perspektive im Testlauf"))
perspektive_box = OptionButton.new()
perspektive_box.add_item("Erste Person (Standard)")
perspektive_box.add_item("Dritte Person (Bot-Avatar)")
perspektive_box.selected = 1 if PlaytestSettings.load_third() else 0
perspektive_box.custom_minimum_size = UIScale.v2(0, 36)
perspektive_box.tooltip_text = "Dritte Person zeigt denselben Avatar wie die Bots im Spiel (Taste V schaltet im Testlauf ebenfalls). Dritte Person braucht die Avatar-Modelle aus dem Client-Klon."
perspektive_box.item_selected.connect(_on_perspektive_changed)
add_child(perspektive_box)
add_child(_separator())
func _on_sens_changed(value: float) -> void:
PlaytestSettings.save_sens(value)
var pt: Variant = main.get("playtest")
if pt != null and pt.has_method("apply_sensitivity"):
pt.call("apply_sensitivity", value)
func _on_perspektive_changed(index: int) -> void:
var dritte := index == 1
PlaytestSettings.save_third(dritte)
# Live anwenden, falls der Testlauf gerade läuft. Ohne Avatar-Modelle
# bleibt First Person aktiv (set_perspektive lehnt Third ab) — der
# Klartext-Grund steht beim Start/V-Druck im HUD.
var pt: Variant = main.get("playtest")
if pt == null:
return
var body: Variant = pt.get("body")
if body != null:
body.call("set_perspektive", dritte)
## Schalter aus dem Editor-Zustand nachziehen (beim Öffnen des Fensters).
func refresh() -> void:
if main == null:
return
grid_btn.set_pressed_no_signal(bool(main.get("_grid_on")))
contours_btn.set_pressed_no_signal(bool(main.get("_contours_on")))
raster_snap_check.set_pressed_no_signal(bool(main.get("grid_snap")))
gizmo_step_box.set_value_no_signal(float(main.gizmo_step_m))
size_menu.select(UIScale.step_index())
sym_menu.select(int(main.get("sym_mode")))