138 lines
5.0 KiB
GDScript
138 lines
5.0 KiB
GDScript
## 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 _mana_leech: 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))
|
||
_mana_leech = _row("击杀回蓝(Mana Leech)", UI.spin(0, 100, 0.5, 0))
|
||
_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))
|
||
_mana_leech.value = float(d.get("mana_leech", 0))
|
||
_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,
|
||
"mana_leech": _mana_leech.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, "mana_leech": 0, "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)
|