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")))