Pack-Kaserne/-Checkpoint/-Container sind innen geschlossen; die Vorlagen sind begehbare Gebäude aus bau_*-Teilen. Test beweist per Strahl durch die echte Kollision. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
107 lines
4.7 KiB
GDScript
107 lines
4.7 KiB
GDScript
extends "res://src/ui/panels/editor_panel.gd"
|
|
## Bauen-Tab: Bauteile für eigene Gebäude (Fundament, Wände, Dach, Treppe). Fertige
|
|
## Pack-Objekte (Container, Hangar-Tore, Sperren …) gehören in die Objekt-Bibliothek
|
|
## unten, NICHT hierher. Ein Klick auf ein Teil startet
|
|
## das Platzieren (Vorschau rastet an Zelle/Kante/Ebene, siehe build_snap.gd); jedes
|
|
## gesetzte Teil ist ein normales Objekt und gehört zum laufenden Gebäude (Gruppe).
|
|
## Gebäude kopieren/löschen/auswählen läuft über die Knöpfe unten — alles Undo-fähig.
|
|
|
|
var bau_buttons: Dictionary = {} # oid → Button
|
|
var info_label: Label
|
|
var _group: ButtonGroup
|
|
|
|
|
|
static func spec() -> Dictionary:
|
|
return {"titel": "Bauen", "gruppe": "rechts", "order": 47}
|
|
|
|
|
|
func panel_title() -> String:
|
|
return "Bauen"
|
|
|
|
|
|
func build() -> void:
|
|
_group = ButtonGroup.new()
|
|
_group.allow_unpress = true
|
|
add_child(_muted_label("Wähle ein Teil und klicke in die Karte. Wände rasten an die nächste Zellkante, Böden und Dächer in die Zellmitte (Raster 2 m). Klick auf die Oberkante einer Wand stapelt das nächste Geschoss, Klick auf die Seite ersetzt das Teil (z. B. Wand → Tür). R dreht, Esc beendet."))
|
|
for gruppe in BauKatalog.GRUPPEN:
|
|
add_child(_field_label(str(gruppe["label"])))
|
|
add_child(_knopf_raster(gruppe["oids"] as Array))
|
|
add_child(_separator())
|
|
add_child(_header_label("Begehbare Vorlagen"))
|
|
add_child(_muted_label("Pack-Kaserne, -Checkpoint und -Container sind innen geschlossen. Diese Vorlagen setzen ein begehbares Gebäude mit einem Klick in die Bildmitte (Tür, Fenster, Dach, Strg+Z nimmt alles zurück)."))
|
|
for key in BauVorlagen.schluessel():
|
|
add_child(_aktion("🏠 %s" % BauVorlagen.label(key), str(BauVorlagen.VORLAGEN[key]["info"]),
|
|
func() -> void: main.call("_bau_vorlage_setzen", key)))
|
|
add_child(_separator())
|
|
add_child(_header_label("Gebäude"))
|
|
info_label = _muted_label("")
|
|
add_child(info_label)
|
|
add_child(_aktion("🏠 Neues Gebäude beginnen", "Das nächste Teil gehört zu einem neuen Gebäude (neue Gruppe).",
|
|
func() -> void: main.call("_bau_neues_gebaeude")))
|
|
add_child(_aktion("🔲 Ganzes Gebäude auswählen", "Wählt alle Teile des Gebäudes, zu dem das markierte Teil gehört — zum Verschieben, Drehen, Kopieren.",
|
|
func() -> void: main.call("_bau_gebaeude_waehlen")))
|
|
add_child(_aktion("📄 Gebäude kopieren", "Kopiert das ganze Gebäude als neues Gebäude (Strg+Z nimmt es zurück).",
|
|
func() -> void: main.call("_bau_gebaeude_kopieren")))
|
|
add_child(_aktion("🗑 Gebäude löschen", "Löscht alle Teile des Gebäudes (Strg+Z holt es zurück).",
|
|
func() -> void: main.call("_bau_gebaeude_loeschen")))
|
|
refresh_info()
|
|
wrap_in_scroll()
|
|
|
|
|
|
func _knopf_raster(oids: Array) -> GridContainer:
|
|
var grid := GridContainer.new()
|
|
grid.columns = 2
|
|
grid.add_theme_constant_override("h_separation", UIScale.px(8))
|
|
grid.add_theme_constant_override("v_separation", UIScale.px(8))
|
|
var lib: Dictionary = main.manifest.get("objects", {})
|
|
for oid in oids:
|
|
var btn := Button.new()
|
|
btn.toggle_mode = true
|
|
btn.button_group = _group
|
|
btn.custom_minimum_size = UIScale.v2(148, 44)
|
|
btn.clip_text = true
|
|
var poly := int((lib.get(oid, {}) as Dictionary).get("poly", 0))
|
|
btn.text = BauKatalog.label(oid)
|
|
btn.tooltip_text = "%s — %s\n%d Dreiecke" % [BauKatalog.label(oid),
|
|
str((BauKatalog.KINDS[oid] as Dictionary).get("info", "")), poly]
|
|
btn.pressed.connect(_on_teil_gedrueckt.bind(str(oid), btn))
|
|
bau_buttons[str(oid)] = btn
|
|
grid.add_child(btn)
|
|
return grid
|
|
|
|
|
|
func _aktion(text: String, tip: String, cb: Callable) -> Button:
|
|
var b := Button.new()
|
|
b.text = text
|
|
b.tooltip_text = tip
|
|
b.custom_minimum_size = UIScale.v2(0, 44)
|
|
b.pressed.connect(cb)
|
|
return b
|
|
|
|
|
|
func _on_teil_gedrueckt(oid: String, btn: Button) -> void:
|
|
if not btn.button_pressed:
|
|
main.interaction.call("cancel_placement")
|
|
return
|
|
main.call("_on_bauteil_gewaehlt", oid)
|
|
|
|
|
|
## Teil-Markierung an den laufenden Platzier-Zustand koppeln (Esc/Abbruch löst sie).
|
|
func sync_platzierung() -> void:
|
|
var aktiv := str(main.interaction.get("place_oid")) if bool(main.interaction.get("placing")) else ""
|
|
for oid in bau_buttons:
|
|
(bau_buttons[oid] as Button).set_pressed_no_signal(oid == aktiv)
|
|
|
|
|
|
## Info-Zeile: aktuelles Gebäude (Name, Teile, Dreiecke) bzw. Gesamtzahl.
|
|
func refresh_info() -> void:
|
|
if info_label == null or main == null or main.doc.is_empty():
|
|
return
|
|
var gebaeude := BauOps.gebaeude_gruppen(main.doc)
|
|
var text := "%d Gebäude, %d Bauteile in der Map." % [gebaeude.size(), BauOps.teile_zahl(main.doc)]
|
|
var gid := int(main.interaction.get("build_group_id"))
|
|
for g in gebaeude:
|
|
if int(g["gid"]) == gid:
|
|
text = "Aktuell: %s — %d Teile, %d Dreiecke.\n%s" % [g["name"], (g["indizes"] as Array).size(), int(g["dreiecke"]), text]
|
|
break
|
|
info_label.text = text
|