extends "res://src/ui/panels/editor_panel.gd" ## Map-Inhalt-Baum (aus main.gd ausgezogen, Karte t_eaccbfed U1 — Logik ## unverändert). U2 baut hier den hierarchischen Szenen-Baum aus; diese Karte ## zieht nur um: Der Baum lebt jetzt im LINKEN TabContainer (Registry-Gruppe ## "links"), Zustand/Signale wie vorher. var content_tree: Tree var _tree_select_lock := false # verhindert Rückkopplung Auswahl ↔ Baum static func spec() -> Dictionary: return {"titel": "Map-Inhalt", "gruppe": "links", "order": 10} func build() -> void: add_child(_header_label("Map-Inhalt")) content_tree = Tree.new() content_tree.size_flags_vertical = Control.SIZE_EXPAND_FILL content_tree.custom_minimum_size = UIScale.v2(0, 160) content_tree.allow_reselect = true content_tree.select_mode = Tree.SELECT_MULTI # Strg+Klick im Baum = Mehrfachauswahl (t_c46d31c2) content_tree.hide_root = true content_tree.item_selected.connect(_on_tree_selected) add_child(content_tree) ## Der Baum ruft zurück, wenn der Nutzer dort ein Objekt auswählt. ## SELECT_MULTI (Karte t_c46d31c2): einfacher Klick = Ersatz-Auswahl, ## Strg+Klick addiert/entfernt nativ — ALLE markierten Objekt-Zeilen spiegeln ## sich in die Viewport-Auswahl (Baum und Szene sind immer synchron). func _on_tree_selected() -> void: if _tree_select_lock: return var item := content_tree.get_selected() if item == null: return if item.has_meta("gebaeude_index"): _on_tree_selected_gebaeude(int(item.get_meta("gebaeude_index"))) return var indices: Array = [] var walk := content_tree.get_next_selected(null) while walk != null: if walk.has_meta("obj_index"): indices.append(int(walk.get_meta("obj_index"))) walk = content_tree.get_next_selected(walk) if indices.is_empty(): return var objects: Array = main.doc.get("objects", []) var valid: Array = [] for idx in indices: if idx >= 0 and idx < objects.size(): valid.append(idx) if valid.is_empty(): return if valid.size() == 1: main.interaction.select_object(valid[0], true) main.call("_set_status", "%s ausgewählt — ziehen zum Verschieben, R/Mausrad zum Drehen, Entf zum Löschen. Strg+Klick markiert weitere dazu." % main.object_label(str(objects[valid[0]].get("id", "")))) else: main.interaction.select_many(valid) main.call("_set_status", "%d Objekte im Baum markiert — Entf löscht ALLE, Strg+D dupliziert ALLE (jeweils EIN Undo-Schritt)." % valid.size()) ## Baum: Bauteil-Klick → Bauen-Modus + Teil anwählen (Karte t_97ea59c5). func _on_tree_selected_gebaeude(gi: int) -> void: if str(main.get("tool_mode")) != "bauen": main.call("_set_tool_mode", "bauen") main.build_tool.call("select_index", gi) func mark_tree_selection(idx: int) -> void: mark_tree_selection_multi([idx]) func mark_tree_selection_multi(indices: Array) -> void: _tree_select_lock = true var wanted := {} for i in indices: wanted[int(i)] = true _mark_tree_selection_walk(content_tree.get_root(), wanted) var primary: Variant = main.interaction.get("selected_index") if main.interaction != null else -1 if primary is int and primary >= 0: _ensure_tree_visible(content_tree.get_root(), primary) _tree_select_lock = false func _mark_tree_selection_walk(item: TreeItem, wanted: Dictionary) -> void: if item == null: return if item.has_meta("obj_index"): var idx := int(item.get_meta("obj_index")) if wanted.has(idx): item.select(0) elif item.is_selected(0): item.deselect(0) for child in item.get_children(): _mark_tree_selection_walk(child, wanted) func _ensure_tree_visible(item: TreeItem, idx: int) -> void: if item == null: return if item.has_meta("obj_index") and int(item.get_meta("obj_index")) == idx: # Fix (beim Inspektor-Einbau gefunden, Vorbestand t_f6f29d86): Tree # und TreeItem haben KEIN ensure_visible — die Godot-4-API heißt # Tree.scroll_to_item. Der alte Ruf warf bei JEDER Auswahl einen # SCRIPT ERROR und scrollte den Baum nie zur Auswahl. content_tree.scroll_to_item(item) return for child in item.get_children(): _ensure_tree_visible(child, idx) func refresh_tree() -> void: content_tree.clear() var root := content_tree.create_item() var objects: Array = main.doc.get("objects", []) var obj_item := content_tree.create_item(root) obj_item.set_text(0, "Objekte (%d)" % objects.size()) for i in objects.size(): var obj = objects[i] var item := content_tree.create_item(obj_item) if obj is Dictionary: item.set_text(0, "%s #%d" % [main.object_label(str(obj.get("id", "?"))), i + 1]) item.set_meta("obj_index", i) else: item.set_text(0, "ungültig #%d" % (i + 1)) var zones: Dictionary = main.doc.get("spawn_zones", {}) var spawn_item := content_tree.create_item(root) spawn_item.set_text(0, "Spawn-Zonen") for team_key in ["0", "1"]: if not zones.has(team_key): continue var zone: Dictionary = zones[team_key] var team_item := content_tree.create_item(spawn_item) var team_name := "Team Blau" if team_key == "0" else "Team Rot" team_item.set_text(0, "%s (%d Punkte)" % [team_name, (zone.get("points", []) as Array).size()]) for p in (zone.get("points", []) as Array): if p is Dictionary: var point_item := content_tree.create_item(team_item) point_item.set_text(0, "%s (%.0f, %.0f)" % [ str(p.get("id", "?")), float(p.get("pos", [0, 0, 0])[0]), float(p.get("pos", [0, 0, 0])[2])]) # Gebäude (Karte t_97ea59c5): Bauteile im Baum — Klick wählt das Teil an. var geb_list: Array = BuildOps.pieces(main.doc) if not geb_list.is_empty(): var geb_item := content_tree.create_item(root) geb_item.set_text(0, "Gebäude (%d Bauteile)" % geb_list.size()) for i in geb_list.size(): var teil: Dictionary = geb_list[i] var g_child := content_tree.create_item(geb_item) g_child.set_text(0, "%s #%d" % [BuildOps.kind_label(str(teil.get("id", "?"))), i + 1]) g_child.set_meta("gebaeude_index", i)