docs(designer): UI 优化设计(布局撑满 + 元素复选框 + 双语标签)
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
# 游戏设计器 UI 优化(布局撑满 + 元素复选框 + 双语标签)— 设计
|
||||
|
||||
- 日期:2026-07-22
|
||||
- 状态:设计已确认,待实现
|
||||
- 范围:编辑器工具层 `addons/game_designer/`,**游戏运行时代码与数据文件格式零改动**
|
||||
|
||||
---
|
||||
|
||||
## 1. 背景与问题
|
||||
|
||||
用户反馈游戏设计器三点待优化:
|
||||
|
||||
1. **输入框无法完整显示内容** —— `designer_ui.gd` 的 `line()`/`opt()`/`spin()` 只设固定最小宽度、无 `SIZE_EXPAND_FILL`,控件不随面板拉伸,长文本(显示名/描述/VFX/JSON/长中文选项)被截断。
|
||||
2. **法术元素标签用逗号文本易错** —— 应改可视化控件。元素标签是**多值**(如 `plasma_storm` = `["tag:water","tag:lightning"]`)。
|
||||
3. **部分显示仍为纯英文** —— `spell_tab.TYPE_NAMES`/`LOGIC_OPS`、`wave_tab.TYPE_NAMES`、`resonance_tab.MATCH` 等为纯英文。要求统一**双语(中文 English)**显示,含 spell_tab(其 `DMG_LABELS`/`ST_LABELS` 现为纯中文,也改双语)。
|
||||
|
||||
### 词表事实
|
||||
|
||||
- 元素标签词表(全数据仅这 5 个):`tag:fire 火` / `tag:ice 冰` / `tag:lightning 雷` / `tag:water 水` / `tag:poison 毒`。
|
||||
- 枚举整数来源:`DamageType`(0物理/1火/2冰/3雷/4毒/5奥术)、`StatusID`(0无/1燃烧/2冻结/3中毒/4潮湿/5沾油/6眩晕/7连击/8易伤)。
|
||||
|
||||
---
|
||||
|
||||
## 2. 布局修复(全 7 页,中央改动)
|
||||
|
||||
`addons/game_designer/designer_ui.gd`:`line()` / `opt()` / `spin()` 三个工厂各追加:
|
||||
```gdscript
|
||||
ctrl.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
```
|
||||
效果:行内 `cell_label`(70px,autosize,不变)之后,输入控件吃掉剩余宽度;表格页(敌人/波次)各列随之填满面板宽度。零数据改动,全 7 页受益。
|
||||
|
||||
---
|
||||
|
||||
## 3. 共享元素词表(`designer_ui.gd` 新增常量)
|
||||
|
||||
```gdscript
|
||||
const ELEM_LABELS := ["火 Fire", "冰 Ice", "雷 Lightning", "水 Water", "毒 Poison"] # 显示(双语)
|
||||
const ELEM_TAGS := ["tag:fire", "tag:ice", "tag:lightning", "tag:water", "tag:poison"] # 存储,index 对齐
|
||||
```
|
||||
spell_tab(复选框)与 resonance_tab(元素下拉)共用,单一事实源。通过 `UI.ELEM_LABELS` / `UI.ELEM_TAGS` 访问(`const UI = preload(designer_ui.gd)`,常量可跨脚本访问)。
|
||||
|
||||
---
|
||||
|
||||
## 4. spell_tab —— 元素复选框 + 双语标签
|
||||
|
||||
### 4.1 元素标签复选框(替代 `_tags` 单行文本)
|
||||
- UI:一行「元素标签」标签 + 5 个 CheckBox(文本取 `UI.ELEM_LABELS`);下方一行「自定义标签」+ 小 LineEdit(收纳非元素 tag,防丢)。
|
||||
- 新增成员:`var _elem_checks: Array = []`(5 个 CheckBox)、`var _custom_tags: LineEdit`。
|
||||
- 加载(`_on_select`):
|
||||
```gdscript
|
||||
var etags: Array = d.get("element_tags", [])
|
||||
for i in _elem_checks.size():
|
||||
_elem_checks[i].button_pressed = UI.ELEM_TAGS[i] in etags
|
||||
var custom := []
|
||||
for t in etags:
|
||||
if not (t in UI.ELEM_TAGS): custom.append(String(t))
|
||||
_custom_tags.text = ",".join(custom)
|
||||
```
|
||||
- 应用(`_on_apply`,替换原 `_tags` 解析块):
|
||||
```gdscript
|
||||
var tags: Array = []
|
||||
for i in _elem_checks.size():
|
||||
if _elem_checks[i].button_pressed: tags.append(UI.ELEM_TAGS[i])
|
||||
for t in _custom_tags.text.split(",", false):
|
||||
var s := t.strip_edges()
|
||||
if s != "" and not (s in tags): tags.append(s)
|
||||
```
|
||||
- ⚠️ 多元素法术会被规整为**固定元素顺序**(火冰雷水毒),`element_tags` 语义为集合、顺序无意义——属预期简化(回读比较按集合)。
|
||||
|
||||
### 4.2 双语标签(仅显示;存储 index/key 不变)
|
||||
```gdscript
|
||||
const TYPE_NAMES := ["动作 ACTION", "修饰 MODIFIER", "触发 TRIGGER", "逻辑 LOGIC"]
|
||||
const ACTION_KINDS := ["弹道 Projectile", "毒池 Zone", "召唤 Summon"]
|
||||
const LOGIC_OPS := ["every_n_shots", "if_hp_below", "if_enemy_nearby", "loop"] # 存储 key,不变
|
||||
const LOGIC_OP_LABELS := ["每 N 次 every_n_shots", "生命低于 if_hp_below", "附近有敌 if_enemy_nearby", "循环 loop"] # 新增,供下拉显示
|
||||
const DMG_LABELS := ["物理 Physical", "火 Fire", "冰 Ice", "雷 Lightning", "毒 Poison", "奥术 Arcane"]
|
||||
const ST_LABELS := ["无 None", "燃烧 Burn", "冻结 Freeze", "中毒 Poison", "潮湿 Wet", "沾油 Oily", "眩晕 Stun", "连击 Combo", "易伤 Vuln"]
|
||||
```
|
||||
- `_lop` 下拉改用 `UI.opt(LOGIC_OP_LABELS, 0)`;`_read_meta` 仍 `meta["logic_op"] = LOGIC_OPS[_lop.selected]`,`_on_select` 仍 `_lop.selected = LOGIC_OPS.find(...)`(index↔key 逻辑不变,只换显示数组)。
|
||||
- 列表前缀 `"[%s] %s" % [TYPE_NAMES[...], sid]` 变为 `"[动作 ACTION] action_spark_bolt"`(可接受)。
|
||||
|
||||
---
|
||||
|
||||
## 5. wave_tab —— 双语标签
|
||||
|
||||
```gdscript
|
||||
const TYPE_NAMES = ["杂兵 Basic", "快速 Fast", "护甲 Armored", "精英 Elite", "首领 MiniBoss", "终焉 Boss"]
|
||||
const BOSS_NAMES = ["无 None", "首领 MiniBoss", "终焉 Boss"] # 存储走 BOSS_VALS,不变
|
||||
```
|
||||
(存储均为 index / BOSS_VALS,改标签零数据影响。)
|
||||
|
||||
---
|
||||
|
||||
## 6. resonance_tab —— 双语标签 + 元素下拉
|
||||
|
||||
- 匹配方式:`MATCH`(存储 key `adjacent`/`anywhere_in_deck`)不变;新增 `const MATCH_LABELS = ["相邻 adjacent", "卡组内任意 anywhere_in_deck"]` 供下拉显示。`_match = _row("匹配方式", UI.opt(MATCH_LABELS, 0))`;`_on_apply` 仍 `"match": MATCH[_match.selected]`;`_on_select` 仍 `_match.selected = max(0, MATCH.find(...))`。
|
||||
- 元素 A / B:`_p0`/`_p1` 由 LineEdit → `UI.opt(UI.ELEM_LABELS, 0)`。
|
||||
- 加载:`_p0.selected = max(0, UI.ELEM_TAGS.find(String(p0)))`(非元素值回退第 0 项)。
|
||||
- 应用:`"pattern": [UI.ELEM_TAGS[_p0.selected], UI.ELEM_TAGS[_p1.selected]]`。
|
||||
- 列表显示 `_refresh` 用 pattern 原值(tag 串),不变。
|
||||
- ⚠️ 若某配方 pattern 含非元素值(现数据无),会被下拉回退丢失——现 `resonance.json` 全为元素,风险为零;如未来需要非元素 pattern 再扩展。
|
||||
|
||||
---
|
||||
|
||||
## 7. 已双语的页(enemy / core / status)
|
||||
|
||||
`enemy_tab.NAMES`("杂兵 Basic")、`core_tab.TOPO/FEAT`("MATRIX 矩阵")、`status_tab.STACK`("REFRESH 刷新")已是双语,**本次不改文案**(其中 enemy `name` 是持久化字段,改动会写入 enemies.json),仅受益于第 2 点布局撑满。
|
||||
|
||||
> 注:core/status 现为「英文 中文」序,新加的为「中文 英文」序,序不统一但均双语、均含中文,本次不做归一化以免无谓改动持久化/工作正常的部分。
|
||||
|
||||
---
|
||||
|
||||
## 8. 组件边界与改动清单
|
||||
|
||||
| 文件 | 改动 |
|
||||
|---|---|
|
||||
| `designer_ui.gd` | line/opt/spin 加 `SIZE_EXPAND_FILL`;新增 `ELEM_LABELS`/`ELEM_TAGS` 常量 |
|
||||
| `spell_tab.gd` | 元素复选框 + 自定义框替换 `_tags`;`TYPE_NAMES`/`ACTION_KINDS`/`DMG_LABELS`/`ST_LABELS` 改双语;新增 `LOGIC_OP_LABELS` 并用于 `_lop` 下拉 |
|
||||
| `wave_tab.gd` | `TYPE_NAMES`/`BOSS_NAMES` 改双语 |
|
||||
| `resonance_tab.gd` | `MATCH_LABELS` 新增用于下拉;元素 A/B 改元素下拉 |
|
||||
|
||||
其它运行时脚本、数据文件、其它 tab 逻辑不动。
|
||||
|
||||
---
|
||||
|
||||
## 9. 验证
|
||||
|
||||
1. `validate_script` 四个改动文件全绿;`reload_project` + `get_editor_errors` 无报错。
|
||||
2. 回读往返测试(`execute_editor_script`):
|
||||
- **spell**:逐条 `_on_select`→`_read_meta` meta 一致(同上一特性);`element_tags` 作为**集合**与原一致;含非元素自定义 tag 的情形自定义框保留。
|
||||
- **resonance**:逐条 `_on_select`→ 重建 record,`pattern`(两元素)与 `match` 与原一致。
|
||||
3. `get_editor_screenshot` 目测:各页输入框撑满面板宽、下拉显示双语、法术页元素为复选框。
|
||||
|
||||
## 10. 范围外(YAGNI)
|
||||
|
||||
- 不改游戏运行时代码 / 数据文件格式 / 数据内容。
|
||||
- 不归一化 enemy/core/status 既有双语文案。
|
||||
- 不做元素标签之外的 tag 下拉词表(自定义框已覆盖)。
|
||||
- resonance pattern 仍限两元素(现结构),不扩展多元素配方。
|
||||
|
||||
## 11. 验收标准
|
||||
|
||||
1. 打开游戏设计器,各页输入框/下拉框随面板宽度撑满,长文本不再截断。
|
||||
2. 法术页「元素标签」为 5 个元素复选框 + 自定义框;`plasma_storm` 正确勾选 水+雷;保存后 `element_tags` 集合不变。
|
||||
3. 法术页 类型/动作种类/logic_op/伤害类型/施加状态 均双语显示,保存的 `type`/`logic_op`/`damage_type` 等值不变。
|
||||
4. 波次页 类型/Boss、共鸣页 匹配方式 均双语;共鸣页 元素 A/B 为元素下拉,`resonance.json` 回读往返一致。
|
||||
5. `validate_script`/`reload_project` 无报错;spell 与 resonance 回读往返测试 FAILS=0。
|
||||
Reference in New Issue
Block a user