## Core(法杖)编辑器标签 — 槽位/拓扑/CPU/施法间隔/特性/矩阵·电路结构 @tool extends VBoxContainer const UI = preload("res://addons/game_designer/designer_ui.gd") const PATH = "res://data/cores.json" const TOPO = ["LINEAR 线性", "MATRIX 矩阵", "CIRCUIT 电路"] const FEAT = ["无", "PERSISTENT_MEMORY 记忆", "DUAL_STREAM 双流", "ALWAYS_CAST_LAST", "SHUFFLE_DECK", "INFINITE_SPELLS"] var _data: Dictionary = {} var _cur: String = "" var _list: ItemList var _id: LineEdit var _name: LineEdit var _slots: SpinBox var _topo: OptionButton var _cpu: SpinBox var _interval: SpinBox var _mana_max: SpinBox var _mana_regen: SpinBox var _feat: OptionButton var _rows: SpinBox var _cols: SpinBox var _edges: TextEdit var _status: Label func _ready() -> void: add_child(UI.header("🪄 Core 编辑器 — 法杖拓扑与特性")) _load() _list = ItemList.new() _list.custom_minimum_size = Vector2(0, 90) _list.item_selected.connect(_on_select) add_child(_list) var brow := HBoxContainer.new(); add_child(brow) brow.add_child(UI.btn("➕新增", _on_new)) brow.add_child(UI.btn("🗑删除", _on_delete)) add_child(HSeparator.new()) _id = _row("ID", UI.line("")) _name = _row("显示名", UI.line("", "tr 键或文本")) _slots = _row("槽位数", UI.spin(1, 20, 1, 5)) _topo = _row("拓扑", UI.opt(TOPO, 0)) _cpu = _row("CPU 上限", UI.spin(1, 40, 1, 5)) _interval = _row("施法间隔(s)", UI.spin(0.05, 5, 0.05, 0.5)) _mana_max = _row("蓝上限(Mana Max)", UI.spin(0, 1000, 5, 100)) _mana_regen = _row("回蓝/秒(Mana Regen)", UI.spin(0, 100, 0.5, 5)) _feat = _row("特性", UI.opt(FEAT, 0)) _rows = _row("矩阵行(MATRIX)", UI.spin(1, 8, 1, 1)) _cols = _row("矩阵列(MATRIX)", UI.spin(1, 16, 1, 5)) add_child(Label.new()) var el := Label.new(); el.text = "电路边(CIRCUIT,JSON)"; add_child(el) _edges = TextEdit.new(); _edges.custom_minimum_size = Vector2(0, 50) _edges.placeholder_text = '[{"from":0,"to":1},{"from":0,"to":2}]' add_child(_edges) add_child(HSeparator.new()) var srow := HBoxContainer.new(); add_child(srow) srow.add_child(UI.btn("✓应用", _on_apply)) srow.add_child(UI.btn("💾保存 cores.json", _save)) _status = UI.status_label(); add_child(_status) _refresh() func _row(label: String, ctrl: Control) -> Control: var h := HBoxContainer.new() h.add_child(UI.cell_label(label)) h.add_child(ctrl) add_child(h) return ctrl func _load() -> void: var d = UI.load_json(PATH) _data = d if d is Dictionary else {} func _refresh() -> void: _list.clear() var ids: Array = _data.keys(); ids.sort() for cid in ids: _list.add_item("%s(%s)" % [cid, _data[cid].get("display_name", "")]) _list.set_item_metadata(_list.item_count - 1, cid) func _on_select(idx: int) -> void: _cur = String(_list.get_item_metadata(idx)) var d: Dictionary = _data.get(_cur, {}) _id.text = _cur _name.text = String(d.get("display_name", "")) _slots.value = float(d.get("slot_count", 5)) _topo.selected = int(d.get("topology", 0)) _cpu.value = float(d.get("cpu_limit", 5)) _interval.value = float(d.get("cast_interval", 0.5)) _mana_max.value = float(d.get("mana_max", 100)) _mana_regen.value = float(d.get("mana_regen", 5)) _feat.selected = int(d.get("feature_tags", 0)) _rows.value = float(d.get("grid_rows", 1)) _cols.value = float(d.get("grid_cols", 5)) _edges.text = JSON.stringify(d.get("edges", [])) func _on_apply() -> void: var cid: String = _id.text.strip_edges() if cid == "": UI.set_status(_status, "✗ ID 不能为空", true); return var edges = JSON.parse_string(_edges.text) if _edges.text.strip_edges() != "" else [] if not (edges is Array): edges = [] if _cur != "" and _cur != cid and _data.has(_cur): _data.erase(_cur) _data[cid] = { "display_name": _name.text, "slot_count": int(_slots.value), "topology": _topo.selected, "cpu_limit": int(_cpu.value), "cast_interval": _interval.value, "feature_tags": _feat.selected, "mana_max": int(_mana_max.value), "mana_regen": _mana_regen.value, "grid_rows": int(_rows.value), "grid_cols": int(_cols.value), "edges": edges, } _cur = cid _refresh() UI.set_status(_status, "✓ 已应用『%s』(记得保存)" % cid) func _on_new() -> void: var cid := "new_core" var i := 1 while _data.has(cid): cid = "new_core_%d" % i; i += 1 _data[cid] = {"display_name": cid, "slot_count": 5, "topology": 0, "cpu_limit": 5, "cast_interval": 0.5, "feature_tags": 0, "mana_max": 100, "mana_regen": 5, "edges": []} _refresh() func _on_delete() -> void: if _cur != "" and _data.has(_cur): _data.erase(_cur); _cur = ""; _refresh() UI.set_status(_status, "已删除(记得保存)") func _save() -> void: if UI.save_json(PATH, _data): UI.set_status(_status, "💾 已保存 %d 个 Core(重启 F5 生效)" % _data.size()) else: UI.set_status(_status, "✗ 保存失败", true)