merge(designer): edges/aether_thresholds 改整数元组行编辑器(去 JSON)
This commit is contained in:
@@ -12,7 +12,7 @@ var _data: Dictionary = {}
|
||||
var _mult_spins: Dictionary = {} # key → [SpinBox ×3]
|
||||
var _miniboss: SpinBox
|
||||
var _boss: SpinBox
|
||||
var _aether: TextEdit
|
||||
var _aether
|
||||
var _status: Label
|
||||
|
||||
func _ready() -> void:
|
||||
@@ -46,10 +46,13 @@ func _ready() -> void:
|
||||
_boss = UI.spin(1, 999999, 10, float(bhp.get("5", 1800)))
|
||||
h2.add_child(_boss)
|
||||
add_child(HSeparator.new())
|
||||
var al := Label.new(); al.text = "碎片奖励阈值 aether_thresholds(JSON [[波次,碎片],...])"; add_child(al)
|
||||
_aether = TextEdit.new(); _aether.custom_minimum_size = Vector2(0, 50)
|
||||
_aether.text = JSON.stringify(_data.get("aether_thresholds", [[1, 0], [5, 3], [10, 8], [15, 14], [20, 20]]))
|
||||
var al := Label.new(); al.text = "碎片奖励阈值 aether_thresholds(波次 → 碎片)"; add_child(al)
|
||||
_aether = preload("res://addons/game_designer/tuple_list_editor.gd").new()
|
||||
_aether.setup([
|
||||
{"label": "波次", "min": 1, "max": 9999, "step": 1, "int": true},
|
||||
{"label": "碎片", "min": 0, "max": 9999, "step": 1, "int": true}], "➕ 加行")
|
||||
add_child(_aether)
|
||||
_aether.set_values(_data.get("aether_thresholds", [[1, 0], [5, 3], [10, 8], [15, 14], [20, 20]]))
|
||||
add_child(UI.btn("💾 保存 balance.json", _save))
|
||||
_status = UI.status_label(); add_child(_status)
|
||||
|
||||
@@ -62,9 +65,7 @@ func _save() -> void:
|
||||
for key in MULT_KEYS:
|
||||
var spins: Array = _mult_spins[key]
|
||||
mults[key] = [spins[0].value, spins[1].value, spins[2].value]
|
||||
var thresholds = JSON.parse_string(_aether.text) if _aether.text.strip_edges() != "" else []
|
||||
if not (thresholds is Array):
|
||||
thresholds = []
|
||||
var thresholds = _aether.get_values()
|
||||
var out := {
|
||||
"difficulty_mults": mults,
|
||||
"boss_hp": {"4": _miniboss.value, "5": _boss.value},
|
||||
|
||||
@@ -22,7 +22,7 @@ var _mana_leech: SpinBox
|
||||
var _feat: OptionButton
|
||||
var _rows: SpinBox
|
||||
var _cols: SpinBox
|
||||
var _edges: TextEdit
|
||||
var _edges
|
||||
var _status: Label
|
||||
|
||||
func _ready() -> void:
|
||||
@@ -49,9 +49,11 @@ func _ready() -> void:
|
||||
_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}]'
|
||||
var el := Label.new(); el.text = "电路边(CIRCUIT,from → to)"; add_child(el)
|
||||
_edges = preload("res://addons/game_designer/tuple_list_editor.gd").new()
|
||||
_edges.setup([
|
||||
{"label": "from", "min": 0, "max": 63, "step": 1, "int": true},
|
||||
{"label": "→ to", "min": 0, "max": 63, "step": 1, "int": true}], "➕ 加边")
|
||||
add_child(_edges)
|
||||
add_child(HSeparator.new())
|
||||
var srow := HBoxContainer.new(); add_child(srow)
|
||||
@@ -93,15 +95,18 @@ func _on_select(idx: int) -> void:
|
||||
_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", []))
|
||||
var erows := []
|
||||
for e in d.get("edges", []):
|
||||
erows.append([int(e.get("from", 0)), int(e.get("to", 0))])
|
||||
_edges.set_values(erows)
|
||||
|
||||
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 = []
|
||||
var edges := []
|
||||
for r in _edges.get_values():
|
||||
edges.append({"from": r[0], "to": r[1]})
|
||||
if _cur != "" and _cur != cid and _data.has(_cur):
|
||||
_data.erase(_cur)
|
||||
_data[cid] = {
|
||||
|
||||
@@ -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)
|
||||
@@ -0,0 +1 @@
|
||||
uid://c2bkt1s3rrk24
|
||||
@@ -114,7 +114,7 @@ git commit -m "feat(designer): 新增整数元组列表行编辑器组件"
|
||||
|
||||
(4 处 Edit,精确匹配,保留 TAB 缩进。)
|
||||
|
||||
- [ ] **Step 1: 成员变量类型**
|
||||
- [ ] **Step 1: 成员变量类型(改为不标注,动态派发 setup/get_values)**
|
||||
|
||||
old:
|
||||
```gdscript
|
||||
@@ -122,7 +122,7 @@ var _edges: TextEdit
|
||||
```
|
||||
new:
|
||||
```gdscript
|
||||
var _edges: Control
|
||||
var _edges
|
||||
```
|
||||
|
||||
- [ ] **Step 2: `_ready()` —— edges 文本框换行编辑器**
|
||||
@@ -191,7 +191,7 @@ git commit -m "feat(designer): Core 电路边改行编辑器(去 JSON)"
|
||||
**Files:**
|
||||
- Modify: `addons/game_designer/balance_tab.gd`
|
||||
|
||||
- [ ] **Step 1: 成员变量类型**
|
||||
- [ ] **Step 1: 成员变量类型(改为不标注,动态派发 setup/get_values)**
|
||||
|
||||
old:
|
||||
```gdscript
|
||||
@@ -199,10 +199,10 @@ old:
|
||||
```
|
||||
new:
|
||||
```gdscript
|
||||
var _aether: Control
|
||||
var _aether
|
||||
```
|
||||
|
||||
(注意:该 `var` 声明位于文件顶部成员区,缩进为单 TAB;按文件实际缩进匹配。)
|
||||
(注意:`_aether` 成员声明在文件顶部成员区,无前导缩进;`balance_tab.gd` 的 `var _aether: TextEdit` 在第 15 行左右,顶格。)
|
||||
|
||||
- [ ] **Step 2: `_ready()` —— aether 文本框换行编辑器**
|
||||
|
||||
@@ -331,6 +331,6 @@ Expected: `BALANCE FAILS=0 []`(5 行 [[1,0],[5,3],[10,8],[15,14],[20,20]])
|
||||
|
||||
**占位符扫描:** 无 TBD/TODO;每步含完整代码或精确命令。✅
|
||||
|
||||
**类型/命名一致性:** `_edges`/`_aether` 由 TextEdit→Control(Task 2/3 定义,Task 4 回读用 `tab._edges`/`tab._aether`);`setup`/`set_values`/`get_values`(Task 1 定义,Task 2/3/4 调用一致);行数据模型 `Array[Array]` 全程一致。✅
|
||||
**类型/命名一致性:** `_edges`/`_aether` 由 `TextEdit` 改为**不标注**(动态派发 setup/get_values,避免 Control 无此方法的编译错;Task 4 回读用 `tab._edges`/`tab._aether`);`setup`/`set_values`/`get_values`(Task 1 定义,Task 2/3/4 调用一致);行数据模型 `Array[Array]` 全程一致。✅
|
||||
|
||||
**已知取舍:** LINEAR/MATRIX 法杖应用后仍会写 `edges:[]`(既有行为,非本次引入);回读把「空数组 == 缺 edges 键」按 size 0 视为等价。
|
||||
|
||||
Reference in New Issue
Block a user