diff --git a/addons/game_designer/tuple_list_editor.gd b/addons/game_designer/tuple_list_editor.gd new file mode 100644 index 0000000..88e7245 --- /dev/null +++ b/addons/game_designer/tuple_list_editor.gd @@ -0,0 +1,68 @@ +## 整数元组列表编辑器(@tool)— 每行 N 个 SpinBox + 🗑 删行,底部 ➕ 加行。 +## 用于 Core edges(from/to)、balance aether_thresholds(波次/碎片)等可变长小整数元组列表。 +## 数据模型:Array[Array](行数组);调用方负责与自身 JSON 结构互转。 +@tool +extends VBoxContainer + +var _cols: Array = [] # [{label,min,max,step,int,default}] +var _rows_box: VBoxContainer +var _add_label: String = "➕ 加行" + +func setup(col_specs: Array, add_label: String = "➕ 加行") -> void: + _cols = col_specs + _add_label = add_label + _rows_box = VBoxContainer.new() + add_child(_rows_box) + var add_btn := Button.new() + add_btn.text = _add_label + add_btn.pressed.connect(_on_add) + add_child(add_btn) + +func set_values(rows: Array) -> void: + if _rows_box == null: + return + for c in _rows_box.get_children(): + _rows_box.remove_child(c) + c.free() + for r in rows: + _add_row(r) + +func get_values() -> Array: + var out: Array = [] + if _rows_box == null: + return out + for h in _rows_box.get_children(): + var row: Array = [] + var ci := 0 + for ch in h.get_children(): + if ch is SpinBox: + var v: float = (ch as SpinBox).value + var is_int: bool = bool(_cols[ci].get("int", true)) if ci < _cols.size() else true + row.append(int(v) if is_int else v) + ci += 1 + out.append(row) + return out + +func _on_add() -> void: + _add_row([]) + +func _add_row(vals: Array) -> void: + var h := HBoxContainer.new() + for i in _cols.size(): + var c: Dictionary = _cols[i] + var lbl := String(c.get("label", "")) + if lbl != "": + var l := Label.new(); l.text = lbl + h.add_child(l) + var sp := SpinBox.new() + sp.min_value = c.get("min", 0) + sp.max_value = c.get("max", 100000) + sp.step = c.get("step", 1) + sp.value = float(vals[i]) if i < vals.size() else float(c.get("default", c.get("min", 0))) + sp.size_flags_horizontal = Control.SIZE_EXPAND_FILL + h.add_child(sp) + var del := Button.new() + del.text = "🗑" + del.pressed.connect(func(): _rows_box.remove_child(h); h.queue_free()) + h.add_child(del) + _rows_box.add_child(h)