diff --git a/active.md b/active.md index 948e7baa..c5aa7eff 100644 --- a/active.md +++ b/active.md @@ -17,19 +17,19 @@ ## 当前状态快照(收口批先更新本节,再追加状态记录;≤10 行) -- **更新于**:2026-10-13(迭代 24 敌人表内容修批总收口——单会话 /goal+iter U0 交付)。 -- **批末闸全绿**:冒烟 949/0(基线 938+本批 11 断言)+run_all 25 套+probe --click/--full+render_gate golden 0.00%+doc 三闸/熵增对基线零新增;MC 同种子配对 40 局×both(seed0=9000)三组读数在带(perfect L2 +25pp/全通 +20pp 低于二档判读带,L2 记录不回调)。 -- **迭代 24 交付**:N1 (1,2) 降档 hp22/ac2(敌种 bugbear 保留)+N2 毒吐/盾击两行六池(首遇位 (2,4) 不动)+N3 敌方 attack_type 轴 20 行全填 normal+敌方结算克制消费点(卡片 §2 漏项补点待追认=报告 §四#6);06 三条销号+08 v1.2+07 ㉓+registry 三处;实现报告=design/qa/iter24-实现报告-2026-10-13.md。 -- **迭代 24 待用户**:实机目检三观测(07 ㉓,登记不阻塞)+代拍板追认单三项+GDD 反哺点五条(06 专条)——迭代位仍预留后续追加卡。 -- **现行文档事实源**:秘宝.md v2.9+奇物.md v3.16+天赋树.md v0.10+锻造工坊.md v0.8+元进度.md v1.20+术语表 v1.10+**08-Alpha版本标准 v1.2(本批随批入库转正)**。 -- **各批残留人闸不变**:迭代 20 实机目检五件+V20/V21/V22 人工核对半;21 营地四柜台〔07 ⑳〕+22 秘宝解锁装配〔07 ㉑〕+23 锻造工作间〔07 ㉒〕+**24 敌人表三观测〔07 ㉓〕**。 -- **已裁在册**:M4 数值批顺延迭代 25+ 未排期(本批与锻造批 provisional 终值归其统一标定)。 -- **界面美化三层已登记**(85e2d2a/08 v1.1):先动第一层,待 U0 发令后写需求卡片。 +- **更新于**:2026-10-13(迭代 25 UI 全局主题批总收口——单会话 /goal+iter U0 交付)。 +- **批末闸全绿**:冒烟 987/0(基线 949+本批 38 断言)+run_all 25 套+probe --click/--full+render_gate golden 0.00%+doc 三闸/熵增对基线零新增;MC 零跑(零数值零行为=纯呈现)。 +- **迭代 25 交付**:全局主题 `game/assets/theme/main_theme.tres` 挂 `gui/theme/custom`(15 类型全覆盖+预盖 CheckBox/CheckButton/OptionButton/PopupMenu 弹层+`default_font` 中文字形防御);`tooltip_theme()`/`styled_slider()` 两处局部做法同批退役(settings_overlay 几何内联+debug_overlay 双轨消隐);冒烟 V1-V6 断言 38 条;06「UI 全局主题资源缺失」条移除+「UI 元素细节修」①销号;08 v1.3;07 ㉔;roadmap 行换代;实现报告=design/qa/iter25-实现报告-2026-10-13.md。 +- **迭代 25 待用户**:实机目检全屏巡检+专项观察点二(07 ㉔,登记不阻塞)+代拍板追认单八项(位图不入 git 政策口径/CheckButton 词条名订正/Slider 无 pressed 槽等=报告 §四)+GDD 反哺点五条(报告 §五)。 +- **现行文档事实源**:秘宝.md v2.9+奇物.md v3.16+天赋树.md v0.10+锻造工坊.md v0.8+元进度.md v1.20+术语表 v1.10+**08-Alpha版本标准 v1.3**。 +- **各批残留人闸不变**:迭代 20 实机目检五件+V20/V21/V22 人工核对半;21 营地四柜台〔07 ⑳〕+22 秘宝解锁装配〔07 ㉑〕+23 锻造工作间〔07 ㉒〕+24 敌人表三观测〔07 ㉓〕+**25 全屏巡检〔07 ㉔〕**。 +- **已裁在册**:M4 数值批顺延迭代 26+ 未排期(各批 provisional 终值归其统一标定)。 +- **界面美化三层已登记**(85e2d2a/08 v1.1):第一层第一条(全局主题)已交付;余二条(按钮状态矩阵/全局纹理过滤)待立项。 ## 项目当前位置(2026-10-12 刷新;实时细节以根目录 `roadmap.md` 与 06-待办清单 为准) - **里程碑**:M3=Alpha 版本的完整实现(2026-10-09 立规:用户未明令宣布 M3 完成前停留 M3,迭代只排 M3 需求,M4 一律不排期) -- **迭代**:迭代 19 五卡已入库(2026-10-08);迭代 20 专长实装批已入库(2026-10-11 总收口);迭代 21 天赋树实装批已入库(2026-10-12);迭代 22 秘宝体系实现重构落地批已入库(2026-10-12);迭代 23 锻造工坊实装批已入库(2026-10-12);**迭代 24 敌人表内容修批已入库(2026-10-13,单会话交付;迭代位预留追加卡)**;M4=迭代 25+ 未排期 -- **近期主战场**:迭代 20/21/22/23 四批残留人闸(实机目检:专长五件 / 营地四柜台〔07 ⑳〕/ 秘宝解锁-装配〔07 ㉑〕/ 锻造工坊工作间〔07 ㉒〕)——各批追认单与反哺点全部出清;**下一前沿=M4 数值批,待 U0 发令** +- **迭代**:迭代 19 五卡已入库(2026-10-08);迭代 20 专长实装批已入库(2026-10-11 总收口);迭代 21 天赋树实装批已入库(2026-10-12);迭代 22 秘宝体系实现重构落地批已入库(2026-10-12);迭代 23 锻造工坊实装批已入库(2026-10-12);迭代 24 敌人表内容修批已入库(2026-10-13,单会话交付;迭代位预留追加卡);**迭代 25 UI 全局主题批已入库(2026-10-13,单会话交付)**;M4=迭代 26+ 未排期 +- **近期主战场**:迭代 20/21/22/23/24 五批残留人闸(实机目检:专长五件 / 营地四柜台〔07 ⑳〕/ 秘宝解锁-装配〔07 ㉑〕/ 锻造工坊工作间〔07 ㉒〕/ 敌人表三观测〔07 ㉓〕/ **UI 全屏巡检〔07 ㉔〕**)——各批追认单与反哺点全部出清;**下一前沿=M4 数值批,待 U0 发令** ## 未决面(进行中/待人闸/待裁点指针;现行事实源登记处=`design/gdd/06-待办清单.md`) - 待用户裁决:美术审计两项 P0(art-bible 死样张指涉+主角像素管线重产;06 在册);去毒残留词扫否(魔法道具约 30 处/罕见约 18 处,呈报在案);喂雷流 R5 甲重启条件回落文(一句话件);「通关 vs 通过第 N 关」全库口径统一 273 处(待裁是否补登记 06);迭代 20 实机目检五件+V20/V21/V22 人工核对半(07 在册) @@ -85,3 +85,7 @@ - **487(2026-10-13,迭代 24 敌人表内容修批(三关)开工——U0 单会话交付)**:定义入库 0c083bb(主区守卫拦 commit 坑再证——b89c3fe worktree 提交 --no-ff 合回舞步);开工门=需求卡片 v1.1 零待裁点(Q1-Q9 全裁用户令「按推荐方式」)。基线复读:冒烟 938/0 + run_all **25 套**(卡片/roadmap 记 24 系 485 R1 批加套前旧基线,随批换代呈报)+ probe --click 全绿;改前 MC 锚落盘 sim-data/runsum_iter24_pre_n40both_20261013.jsonl(二档 N=20×both·seed0=9000 沿用迭代 23 配对种子:normal L1 通关 3/20·taken 中位 29.5;perfect L1 19/20·L2 8/20·全通 6/20·taken 中位 76.5)。T1 N1 落地=enemy.tres (1,2) hp 50→22·ac 3→2+表尾批注(阶名化解方案实机未达预期重裁沿革)+V1 两断言(降档锚定+相邻总量比≤2.5 护栏);T2 N2 落地=skills.tres 12→14 行(venom_spit 毒吐 ×1.6/CD2·shield_bash 盾击 ×1.7/CD3 均无 rider)+六池投放(蜘蛛 (2,5)-(2,7)+毒吐 2、灰矮人 (3,0)/(3,5)/(3,7)+盾击 2、首遇位 (2,4) 不动)+expect_pools 六键同步+旧「技能表十二行」断言换代十四行+V3/V4 五断言(两行字段域/两投放面/逐池增益妨害纪律)。冒烟 945/0+probe 全绿。T3 N3 进行中。(worktree g-plan2-iter24-enemy) - **488(2026-10-13,迭代 24 敌人表内容修批(三关)总收口——单会话 /goal+iter U0 全量交付)**:三提交全量入库(worktree g-plan2-iter24-enemy;26d669f N1+N2 / ab3ba4f N3 / 5f2ef77 文档同步面+收口笔)。**N1**:enemy.tres (1,2) hp 50→22·ac 3→2(敌种 bugbear/池/数量/atk 零动;表尾批注载 2026-09-24 阶名化解方案实机未达预期重裁沿革)+V1 两断言(锚定+相邻总量比≤2.5 护栏)。**N2**:skills.tres 12→14 行(venom_spit 毒吐 ×1.6/CD2、shield_bash 盾击 ×1.7/CD3 均无 rider——damage_floor 兜底与 0.75 档等效)+六池投放(蜘蛛 (2,5)-(2,7)/灰矮人 (3,0)(3,5)(3,7);首遇位 (2,4) 不动)+expect_pools 六键同步+旧「十二行」断言换代+V3/V4 五断言。**N3**:20 行 attack_type 全填 normal+enemy_table ATTACK_TYPES 枚举校验(缺省 normal 向后兼容)+unit_container 敌方快照+battle_orchestrator 开单第 9 参传值+**damage_controller._resolve_enemy_skill 克制消费点补一行**(卡片 §2 事实漏项——敌方兑付路径原硬编码 delta 0,2026-09-24 批注释在案;不改则 V5 矩阵命中证词物理不可达,属验收闸强制最小补点待用户追认=报告 §四#6)+单据载荷 attack_type 键+V5 四断言(矩阵证词同种子三甲型实测 heavy 2==light 3−1·ward 4==light 3+1)。**读数**:MC 同种子配对 seed0=9000 N=20×both 改前/改后各 40 局(锚落 sim-data/runsum_iter24_{pre,post}_n40both_20261013.jsonl);三组读数=N1 perfect L1 19→20/20、N2 perfect L2 8→13/20 全通 6→10/20(方向符合预期低于二档判读带,L2 记录不回调,倍率归 M4)、N3 单发恒 ±1(V5 钉死)全局中位位移系构成效应;二档会话累计 ~8 分钟。**文档同步面**:06 三条销号(第一关遭遇表数值异常/第二关技能池与投放/锻造迁移面⑥)+卡片条收口+反哺点五条专条;08 敌种池行注摘除升 v1.2(untracked 件随批转正入库);07 ㉓ 三目检登记;registry 三处(enemy.attack_type 字段/skill 十四行/hero 甲轴休眠注退役);Alpha未完成事项梳理三注订正(A2 已修+附.3 缺行疑云解销=L2/L3 缺 2/3/8 系奖励/休整/商店节正常缺省)。**闸**:冒烟 949/0+run_all 25 套+probe click/full+render_gate golden 0.00%(首跑 SKIP 抓出 worktree 漏拷 art 实体——初拷链因 .godot 路径错误短路,补拷后全绿)+doc 三闸/熵增对基线零新增(死链3/拔旗1/雾格1/lint 3件FAIL 均存量)。**待用户**:实机目检三观测(07 ㉓,登记不阻塞)+追认单三项(消费点补行/旧断言换代/两 untracked 件转正)+GDD 反哺五条。基线漂移记档=run_all 24→25(485 批)。合并=321e6c9(roadmap 与并行迭代 25 编入批 7e0f519d union 解——迭代 24 行已入库门列+迭代 25 UI 批行+26+ M4 行并存);合并后主区 --import 重刷+冒烟 949/0+run_all 25 套+probe --click 兜底绿。(worktree g-plan2-iter24-enemy;编号顺延 488——487 系本会话开工条) + +- **489(2026-10-13,迭代 25 UI 全局主题批开工——/goal+iter U0)**:开工检查全过:需求卡片 v1.2 零待裁点(三范围裁点+三 grilling 裁点+同日审核六点全落文);验收清单 V1-V6 三要素齐(V1-V6 自动闸机+V6 中文字体防御 v1.2 新增)。自洽扫描事实抽查全符(project.godot 仅 custom_font 无 gui/theme/custom/ui_kit:735 styled_slider 与 :753 tooltip_theme 在役/ui_assembler:105 挂载行/consumers=settings_overlay:59+debug_overlay:277 裸 HSlider 双轨/HSeparator 15 处/tooltip_text 11 文件/theme 目录不存在/art/ui 无滚动条滑轨勾选贴图);一处事实 drift 记录继续(有利方向)=卡片 §5 称 08-Alpha版本标准 系 git 未跟踪文件,实际已于 5f2ef77(迭代 24 文档批)转正入库——手工搬运条款 moot,worktree 直接可见。定义面四件(roadmap 迭代 25 行/需求卡片/06/08)均已跟踪且干净(迭代 24 收口批 7e0f519d union 解带入),T0 无需新定义入库提交;主区脏件全属他批遗产零碰(.gitignore/.zcode/02/playnote/四 untracked/三 .uid)。基线复读全绿=冒烟 949/0(V5 基线按卡片「开工日实测为准」口径订正为 949/0,卡片记 938/0 系迭代 23 时代数)+run_all 25 套+probe --click 全绿残留 0(ui_input 17 断言/ui_struct/ui_contrast 38 对/click 行为走查问题 0)。worktree g-plan2-iter25-theme(分支 iter25-theme-20261013,基点 5f8acd0)已建,冷检出三件套(art 主区绝对路径拷贝+字体 .import 拷贝+--import 刷导入件)完毕,T0 主题资源起。 + +- **490(2026-10-13,迭代 25 UI 全局主题批总收口——单会话 /goal+iter U0 全量交付)**:T0-T2 三卡全落(worktree g-plan2-iter25-theme,两提交)。**T0 主题资源**:`game/assets/theme/main_theme.tres`(15 类型=V/HScrollBar·ScrollContainer·H/VSlider·TooltipPanel/Label·LineEdit·SpinBox·H/VSeparator+预盖 CheckBox/CheckButton/OptionButton/PopupMenu)挂 project.godot `gui/theme/custom`;位图生成脚本 `tools/gen_theme_icons.py`(PIL,幂等)产 9 张纯色/几何小位图落 `game/assets/art/ui/gen/`;色值溯源表 `game/assets/theme/README.md`;`default_font` 显式指现役同字体文件(V6 中文字形防御)。**T1 换代退役**:ui_kit.gd 删 `tooltip_theme()`/`_tip_theme` 与 `styled_slider()` 整函数、ui_assembler.gd 删挂载行(旧实现同批删除);settings_overlay 音量滑轨几何内联(裸 HSlider+200×24)、debug_overlay `_slider_row` 补注释(双轨消隐=两处均走全局主题)。**T2 断言与文档闸**:冒烟新增 `_smoke_global_theme()` 38 断言(V1 类型覆盖+Button/focus 双红线+V2 冻结值锚定+5.49:1+V3 预盖证词+V4 退役零残留+V6 字体防御双断言);06「UI 全局主题资源缺失」条移除+「UI 元素细节修」①销号;08 v1.3(三·界面主题行→在役+五·表现细节修行注;余五行本批零触碰已逐行核对);07 ㉔ 全屏巡检登记;roadmap 迭代 25 行换代。**引擎事实三证**(4.7.2 源码+默认主题链双查,探针实证):①CheckButton 与 CheckBox 同套 checked/unchecked 图标名(卡片 v1.2 注③「on/off」不成立——按引擎事实落位否则预盖静默空转,订正随报告呈报);②Slider 无 grabber_pressed 图标槽(冻结表「柄·按」GOLD_DEEP 留档未落位);③ScrollBar 柄=StyleBox 非 Icon(滚动条无位图,increment/decrement 箭头默认主题未定义=无箭头按钮);另证 4.7 导入参数无逐贴图 filter 标志(位图原生尺寸消费无滤波伪影,全局设置红线未触)。**位图不入 git**:.gitignore:52 `game/assets/art/**`(注释明文「运行时资源本地生成不入库」)——卡片 T0「.import 侧车随批入库」与政策冲突,按政策执行(脚本入库可再生+README 溯源+主区随批拷贝 gen/),例外强制入库与否呈报追认。**闸**:冒烟 987/0(基线 949+38)+run_all 25 套+probe click/full+render_gate golden 0.00%(3 屏)+doc 三闸/熵增对基线零新增(死链 3/词命中 2/lint 3 FAIL 均存量);MC 零跑(零数值零行为=纯呈现)。**待用户**:实机目检全屏巡检+专项观察点二(07 ㉔)+代拍板追认单八项+GDD 反哺点五条(design/qa/iter25-实现报告-2026-10-13.md §四/§五)。合并=见 git(主区 merge --no-ff;合并后 --import 重刷+gen/ 位图拷贝+全量复跑留痕)。 diff --git a/design/gdd/06-待办清单.md b/design/gdd/06-待办清单.md index a651657f..28e53ced 100644 --- a/design/gdd/06-待办清单.md +++ b/design/gdd/06-待办清单.md @@ -2,16 +2,6 @@ 本清单是全项目待办事项的**唯一登记处**:各系统文档不再自建「待办」条目节,只留一行指路存根;新增待办事项一律直接登记本清单。条目按四个循环分组,组内按系统分节;每条事项一个四级标题,其下用粗体属性名成段——**现状**(现状与失义原因,自各系统文档原样搬运、措辞不改;跨文档重复条目合并为一条,登记在建议归属主责方名下,其余来源在现状中注明出处;相关但不同面的条目各自保留,现状末尾互相指认;搬运时仅将原文中的「本文 / 本系统」替换为对应系统名,并把相对链接改写为本文件位置可用的路径)、**归属**、**状态**。事项解决后**从本清单移除**(2026-09-18 用户拍板改口径,原"改状态留痕"废止):去向与依据登记当批台账与 active.md 快照,git 历史即留痕。 -#### UI 全局主题资源缺失——引擎原生控件没有接管皮肤(2026-10-13 登记,UI 美化三层诊断 · 第一层) - -**现状**:整个游戏工程没有任何主题资源(全库搜主题文件零命中),`game/project.godot` 里跟界面样式有关的只有一行全局字体设置。于是凡是没有被呈现层逐个手工盖上样式的引擎自带控件,全部显示为引擎默认的灰色圆角现代风,跟游戏的像素木石风格不搭——实机截图里能直接看到的就有营地右侧那条浅灰圆角滚动条(容器在 `camp_overlay_view.gd` 第 101 行起的三处滚动容器),此外设置面的音量滑轨、几乎所有界面的悬停提示气泡、任何下拉框与勾选框都是同一批默认皮肤。**这条为什么会存在**:游戏现行的界面样式做法是"逐个控件手工盖皮肤",而不是"一套主题统一管"——优点是色值与样式已全部单点收拢在 `ui_kit.gd`(这是很好的地基,四十四个消费方里只有两个文件各有两处裸色常量),缺点是没有被点到名的控件就等于没有皮肤。 - -**来源**:2026-10-13 用户提出对当前游戏界面做美化并要求先做分析;本条是分析中**此前未在任何登记处在册**的三项之一(另两项见下方两条)。 - -**归属**:呈现层表现批(纯工程改动,不动任何美术素材,也不改动 [美术圣经](../art/art-bible.md) §7 的定稿规格) - -**状态**:待办(**Alpha 阶段需完成**)——UI 美化三层诊断分三层推进,本条属第一层「系统性缺口」;**用户 2026-10-13 已指定最先动这一层**。**需求卡片=[需求卡片-UI全局主题批-2026-10-13.md](../research/需求卡片-UI全局主题批-2026-10-13.md)(v1.2,零待裁点,开工门=U0),2026-10-13 用户令编入 roadmap 迭代 25(该迭代卡①)**,卡片状态=已编入。**需求卡片已写**:[需求卡片-UI全局主题批-2026-10-13](../research/需求卡片-UI全局主题批-2026-10-13.md) **v1.1 成立**(2026-10-13 三裁点+grilling 三裁点全落:载体=.tres 主题文件 / 未在役控件预盖(含 PopupMenu 弹层)/ 滑轨对比度顺手修 / focus 族词条零定义 / 色值冻结;零待裁点,开工门=U0)。 - #### UI 按钮状态矩阵缺档——悬停没有反馈、危险钮按下没有反馈、键盘焦点全站空白(2026-10-13 登记,UI 美化三层诊断 · 第一层) **现状**:按钮至少应当具备常态 / 悬停 / 按下 / 禁用 / 键盘焦点五种状态,目前全站五种状态的覆盖数量很不齐(`ui_kit.gd` 里常态四处、悬停四处、按下三处、禁用一处、**键盘焦点零处**),具体三处缺档:①普通按钮的贴皮函数(第 541 到 555 行)把悬停态填的是**常态那张图**,等于鼠标移上去外观纹丝不动,同时它把悬停文字色也填成了同常态一样的墨色,两个通道一起失效;②危险钮(第 591 行起)只填了常态与悬停,**没有按下态也没有禁用态**,按下去没有下沉反馈;③全站没有任何键盘焦点样式,走的是引擎默认的灰色描边——这一点正好卡在本清单「棋盘战斗键盘/手柄输入」那条 Beta 待办的连带裁决点③(弹层界面的焦点导航要不要同批做)前面,**焦点态是它的前置件**。**影响**:这些不是纸面问题,玩家在实机上会直接感觉到"点了没反应"。 @@ -66,7 +56,7 @@ **归属**:呈现层表现批 -**状态**:待办(**Alpha 阶段需完成**)——①②③是观感改动,④只需关闭或移进调试浮窗,成本很低,可以顺手带上。**①已由「UI 全局主题批」认领顺手修**(2026-10-13 用户裁「顺手修掉」,随该批滑轨词条迁主题时重配两段对比度,销号随该批收口;另:代码面两段色实为暖石/深棕两值,与诊断「同一深棕」描述不符,实机复核随批目检——见该批卡片 §2 疑点披露)。 +**状态**:待办(**Alpha 阶段需完成**)——①②③是观感改动,④只需关闭或移进调试浮窗,成本很低,可以顺手带上。**①已销号**(2026-10-13 迭代 25「UI 全局主题批」收口——滑轨词条迁全局主题时两段对比度重配:已填充段 BG_ROOT #3A2E22 对槽暖石 #B8A582 ≈5.5:1,「拖到中点一眼可辨」;实机目检随 07 登记项归用户。另:代码面两段色实为暖石/深棕两值,与诊断「同一深棕」描述不符,已随批呈报)。余②③④保留待立项。 #### 旧行为 MC 行为锚全数作废——重锚归数值批(2026-10-06 登记) diff --git a/design/gdd/07-体验验证清单.md b/design/gdd/07-体验验证清单.md index 63009601..bcdb8686 100644 --- a/design/gdd/07-体验验证清单.md +++ b/design/gdd/07-体验验证清单.md @@ -225,6 +225,15 @@ - **第一关节奏**:第一关第三个节点(熊地精 22 血)不再是「打不动的一堵墙」,推进节奏顺畅。 - 验证方式:用户实机目检(登记不阻塞——2026-10-12 真人检测立规;能力验证半已由自动化闸覆盖=V1-V7)。 +### ㉔ UI 全局主题批全屏巡检(迭代 25 UI 全局主题批随批登记——2026-10-13) + +- **引擎默认灰清零巡检**:营地三处滚动容器(含右侧竖滚条)、战斗日志/结算回看的自动滚动条、设置面音量滑轨、各屏悬停气泡(含标题屏深底气泡承旧观感)、调试浮窗种子输入框/批量模拟数/输出区、全屏 15 处分隔线——逐屏看过,应无引擎默认灰色圆角现代风残留。 +- **音量滑轨两段可辨**:把主音量拖到中点,已填充段(深棕)与未填充段(暖石)是否一眼可辨(本批销号 06 第三层①的实机判据)。 +- **专项观察点 1·滑轨柄是否抢焦点**:设置屏上滑轨柄(烛光黄方柄)是否比「关闭」按钮还抢眼——若是,走 L2 微调(候选降档 STONE 灰石系;色值已冻结,目检前不改)。 +- **专项观察点 2·滚动条槽是否看得见**:滚得动的内容里,能否一眼看出滚动条在哪(槽=BG_OVERLAY α0.35)——若否,走 L2 微调(候选提不透明度或改取 SLOT_BACKDROP)。 +- **预盖件无实役(登记注记)**:CheckBox / CheckButton / OptionButton 及其弹层 PopupMenu 游戏零使用,本批仅预盖(冒烟 V3 已有运行时证词)——无需目检,备案待未来批次启用时复查。 +- 验证方式:用户实机目检(登记不阻塞——2026-10-12 真人检测立规;能力验证半已由自动化闸覆盖=冒烟 V1-V6)。 + ## 验收读数重测义务(履行留痕 + 现行义务) **已履行**(按序换代,旧读数各随其批作废留痕不入本单):①验收读数重测批(2026-09-19——Boss 单独出列/承伤带/通关率基线全量重测,硬化翻倍期·乏力死效果期·充能期旧读数作废);②迭代 5 基线重测(统一随机流后 MC+verifier 双窗);③**数值修复批新尺重测(2026-10-01)**——模拟档位重构后全量重测,新锚 `sim-data/runsum_numfix_final_n200_20261001.jsonl`,全旧带作废只测不判(numfix 报告(已退役,git 历史可查));④**迭代 10 奖励重构批重锚(2026-10-01)**——四代锚 77000/78000/79000/80000(改前/重构后/共享池后/掷定前置后,各 400 局),普通 L1 41.8%/L2 10.2% 带内(迭代10通关率读数(已退役,git 历史可查));⑤**T19 真人标定局收口(2026-10-03 用户裁)**——有效局 2(1 通关 1 死于 L3 首战,T19真人试玩读数(已退役,git 历史可查)),用户裁定**佐证级收口不再补局**;k 预期带同日立(**正常 >0.5、预警 <0.3**),字段随 81000 重锚入库后补算终值。 @@ -244,3 +253,4 @@ | v0.5 | 2026-10-10 | 生涯页呈现行柜台名扫改(2026-10-10 天赋树设计会话裁「道具工坊」改名「秘宝匣」):「道具工坊已解锁 X/6 件」改「秘宝匣已解锁 X/6 件」;计数语义(旧六件→新目录)随实装批换代,见 06「天赋树结构重构批」改名连带面 | | v0.6 | 2026-10-12 | 新增 ㉒ 锻造工坊工作间形态与购买交互目检节(迭代 23 锻造工坊实装批随批登记——V13 人闸观测项:门与形态/购买/解锁双通道/选中与锁死/注入抽查) | | v0.7 | 2026-10-13 | 新增 ㉓ 敌人表内容修批三观测目检节(迭代 24 卡①随批登记:新招可见性/甲型体感/第一关节奏——登记不阻塞按 2026-10-12 真人检测立规) | +| v0.8 | 2026-10-13 | 新增 ㉔ UI 全局主题批全屏巡检目检节(迭代 25 卡①随批登记:引擎默认灰清零巡检/音量滑轨两段可辨/专项观察点二(滑轨柄抢焦点·滚动条槽可见性)/预盖件无实役注记——登记不阻塞;能力验证半=冒烟 V1-V6) | diff --git a/design/gdd/08-Alpha版本标准.md b/design/gdd/08-Alpha版本标准.md index 828caa10..f57a5cb4 100644 --- a/design/gdd/08-Alpha版本标准.md +++ b/design/gdd/08-Alpha版本标准.md @@ -114,7 +114,7 @@ | 图例面板 | —— | 在役 | | 设置面 | [设置与本地化](systems/表现与支撑/设置与本地化.md) | 在役 | | 调试浮窗 | —— | 在役 | -| UI 全局主题资源(引擎原生控件接管皮肤) | [06-待办清单](06-待办清单.md) | 待做 | +| UI 全局主题资源(引擎原生控件接管皮肤) | —— | 在役(迭代 25 · 2026-10-13 入库:game/assets/theme/main_theme.tres 挂 gui/theme/custom) | | UI 按钮状态矩阵(悬停 / 按下 / 禁用 / 键盘焦点补齐) | [06-待办清单](06-待办清单.md) | 待做 | --- @@ -158,7 +158,7 @@ | UI 字体补完(拉丁像素字专件 + 字重两档) | [美术圣经](../art/art-bible.md) §7.4 | 待做 | | 战斗一屏样张(界面美术的终稿闸) | [美术圣经](../art/art-bible.md) §1.4 | 待做 | | UI 氛围层与九宫格切片观感修 | [06-待办清单](06-待办清单.md) | 待做 | -| UI 元素细节修(滑轨填充 / 图标垫块 / 留白 / 开发件外泄) | [06-待办清单](06-待办清单.md) | 待做 | +| UI 元素细节修(滑轨填充 / 图标垫块 / 留白 / 开发件外泄) | [06-待办清单](06-待办清单.md) | 待做(①滑轨填充已销号=迭代 25 全局主题批两段对比度重配;余②③④) | --- @@ -222,3 +222,4 @@ | v1.0 | 2026-10-13 | **定稿(用户令)**:① **与游戏内容无关的三项移出 Alpha**——音频 / 教学引导(含教学引导面)/ 多语言本地化一律排 Beta,自「一 · 表现与支撑」「三 · 界面」「五 · 表现」三表摘除,移入「六 · Alpha 不含」并单列为一组;判据 = 缺了照样能联调、能通关,属打磨层;② 未决项十一项减为**八项**(删音频 / 教学引导 / 本地化三条,余项重编号);③ 文首加状态行 = **已定稿**,Alpha 内容范围自此冻结,增删须经用户裁决并记版本历史 | | v1.1 | 2026-10-13 | **界面美化三层诊断入 Alpha 标准(用户令)**:用户同日提出界面美化需求并要求先作现状分析,随后下令「把分析出的三层全部作为独立待办事项登记、且一律列为 Alpha 阶段必须完成」。据此新增八行——「三 · 界面」表两行(UI 全局主题资源、UI 按钮状态矩阵),「五 · 表现」表六行(全局纹理过滤、UI 贴图重构批、UI 字体补完、战斗一屏样张、UI 氛围层与九宫格切片观感修、UI 元素细节修)。八行的登记事实源统一为 [06-待办清单](06-待办清单.md) 同批新增的八条专条;其中「UI 贴图重构批」「UI 字体补完」「战斗一屏样张」三条原先只登记在美术侧的资产清单与素材状态清单里,本次转立本清单以免两处各写一份内容。用户同时指定**先动第一层**,即主题资源 / 按钮状态矩阵 / 全局纹理过滤三项(均属纯工程补齐、不依赖美术素材)。本次改动未触碰既有的未决项八项与「六 · Alpha 不含」清单 | | v1.2 | 2026-10-13 | **敌种池行注摘除(迭代 24 卡①机械面随批)**:「二 · 内容量」敌种池行的「第一关遭遇表数值待修」注摘除——该异常已随迭代 24 N1 修复((1,2) 降档 hp 22/ac 2,06 对应条已销号),本行回归「在役」净态;条目集合零增删,未决项与「六 · Alpha 不含」零触碰 | +| v1.3 | 2026-10-13 | **UI 全局主题批收口回填(迭代 25 卡①机械面随批)**:「三 · 界面」表「UI 全局主题资源(引擎原生控件接管皮肤)」行 待做→在役(主题资源已入库:game/assets/theme/main_theme.tres 挂 project.godot gui/theme/custom,06 对应条销号);「五 · 表现」表「UI 元素细节修」行状态注记①销号(滑轨两段难辨已随主题批重配=已填充段 BG_ROOT 对暖石 ≈5.5:1,余②③④保留)。「五 · 表现」表余零改动——逐行核对六条 06 指向行中仅「UI 元素细节修」事实变化,其余(棋盘观感/站桩帧动画/素材升档重产/全局纹理过滤/UI 氛围层)本批零触碰;条目集合零增删,未决项与「六 · Alpha 不含」零触碰 | diff --git a/design/qa/iter25-实现报告-2026-10-13.md b/design/qa/iter25-实现报告-2026-10-13.md new file mode 100644 index 00000000..ea9deb95 --- /dev/null +++ b/design/qa/iter25-实现报告-2026-10-13.md @@ -0,0 +1,90 @@ +# 迭代 25 实现报告——UI 全局主题批(引擎原生控件接管皮肤) + +- 日期:2026-10-13(单会话 /goal+iter U0 开工令交付) +- 需求卡片:`design/research/需求卡片-UI全局主题批-2026-10-13.md` v1.2(零待裁点,开工门=U0) +- worktree:`g-plan2-iter25-theme`(分支 `iter25-theme-20261013`,基点 master 5f8acd0) +- 基线复读(主区 T0):冒烟 949/0 + run_all 25 套 + probe --click 全绿残留 0 +- 批末闸:冒烟 **987/0**(基线 949 + 本批 38 断言)+ run_all 25 套 + probe click/full + render_gate golden 0.00% + doc 三闸/熵增对基线零新增(详见 §三) + +## 一、交付总览 + +| 卡 | 内容 | 状态 | +|---|---|---| +| T0 | 主题资源与词条:`game/assets/theme/main_theme.tres`(15 类型全覆盖 + 预盖件)挂 `project.godot` `gui/theme/custom`;位图生成脚本 `tools/gen_theme_icons.py`(9 张纯色/几何小位图 → `game/assets/art/ui/gen/`);色值溯源表 `game/assets/theme/README.md` | ✅ | +| T1 | 换代退役:`ui_kit.gd` `tooltip_theme()`/`_tip_theme` 与 `styled_slider()` 样式段、`ui_assembler.gd` 挂载行同批删除;settings_overlay 音量滑轨几何内联;debug_overlay `_slider_row` 双轨消隐(两消费方均改裸 HSlider+几何,皮肤统一走全局主题) | ✅ | +| T2 | 断言与文档同步闸:冒烟新增 `_smoke_global_theme()`(V1-V6 共 38 断言);06 两条销号/①销号;08 升 v1.3;07 ㉔ 登记;roadmap 行换代 | ✅ | + +**契约遵守**:🔴 Button 类型词条零接触(冒烟断言在闸)· 🔴 focus 族词条零定义(全主题自有条目扫描断言)· 🔴 零新增美术素材(位图=脚本生成)· 🔴 全局纹理过滤未动。**camp_overlay_view.gd 零改动**——营地滚动条由 VScrollBar/HScrollBar 类型词条全局接管,无需逐实例改码(roadmap 编入批文件清单里的该文件系预估,实际未触)。 + +## 二、落位明细 + +### 主题词条(main_theme.tres) + +- **滚动条**:V/HScrollBar 的 scroll(BG_OVERLAY #362B20 α0.35 直角槽)+ grabber/grabber_highlight/grabber_pressed(PANEL_BORDER/STONE_FAINT/STONE_DEEP 纯色 StyleBoxFlat,content margin 4 = 8px 粗细、柄最小 8px)。**引擎实证:Godot 4 ScrollBar 的 grabber 是 StyleBox 非 Icon**(scroll_bar.cpp BIND_THEME_ITEM 双查),故滚动条柄不走位图;increment/decrement 箭头图标默认主题未定义(0×0 空图不渲染),滚动条无箭头按钮,与冻结表一致。 +- **滑轨**:HSlider/VSlider 的 slider(暖石 #B8A582 + PANEL_BORDER 边 + (0,6,0,6) margins 承 styled_slider 现值)/ grabber_area(+highlight)(**BG_ROOT #3A2E22 换色**——顺手修 06 第三层①,实测对比 5.49:1)/ grabber 三态位图(CANDLE 方柄+PANEL_BORDER 描边 / 提亮档 / STONE_DEEP 废态)。 +- **Tooltip**:TooltipPanel/TooltipLabel 承 `tooltip_theme()` 现值原样迁入(深底 0.96 + 边 #5A5044 + WARM 字 14)——标题屏观感零变化,其余各屏气泡由引擎默认灰转正。 +- **输入件**:LineEdit normal(PANEL_DATA + PANEL_BORDER + RADIUS_OBJECT 圆角,同数据框惯例)+ 占位色 `font_placeholder_color`=STONE_DEEP(**词条名经 4.7.2 实证**,`font_color_placeholder` 不存在);SpinBox updown 合并箭头位图(INK ▲▼)+ 箭头底 hover/pressed 覆盖(默认主题该两态有可见 Flat 高亮)。 +- **分隔线**:HSeparator/VSeparator = StyleBoxLine PANEL_BORDER α0.6 单线 1px(默认灰 #808080 实证在位)。 +- **预盖件**(零实役):CheckBox/CheckButton 共用 `checked`/`unchecked`(+_disabled) 四态 14×14 位图;OptionButton normal/hover/pressed/disabled = button_stone 九宫格(8px 边距同 `_apply_button_skin` 观感)+ INK 字系 + INK 箭头位图;PopupMenu panel(PANEL_DATA+PANEL_BORDER)/ hover(GOLD_LIT 底 + INK_ON_GOLD 字)/ 字色 INK / 字号 16。 +- **default_font**:显式指向 `res://assets/fonts/ui_font_fusion_pixel_zh_hans.ttf`(与 project.godot `theme/custom_font` 同文件)——V6 中文字形防御:冒烟断言主题 default_font 非空 + Label 实取字体非空双闸。**未设 default_font_size**(全站字号走 UiKit.FS_* 逐实例 override)。 + +### 退役(T1,旧实现同批删除) + +- `ui_kit.gd`:删 `tooltip_theme()` 函数 + `_tip_theme` 缓存 + `styled_slider()` 整函数(样式段随删,几何/量程按白名单#3 内联两消费方)。 +- `ui_assembler.gd`:删 `overlay.theme = UiKit.tooltip_theme()` 挂载行及注释引用。 +- `settings_overlay.gd`:音量滑轨改裸 `HSlider.new()` + min/max/value/custom_minimum_size(200,24) 内联。 +- `debug_overlay.gd`:`_slider_row` 原即裸构建,补注释标明与设置屏同一构建方式(双轨消隐=两处都不再走局部样式,统一全局主题)。 +- V4 断言:四文件剥注释后扫 `styled_slider`/`tooltip_theme`/`_tip_theme`/`overlay.theme` 零残留(编译期+断言双闸)。 + +### 断言(T2,冒烟 949 → 987,+38) + +`_smoke_global_theme()`:V1 挂载与类型覆盖(15 类型逐一 + Button 红线 + focus 族全扫描红线 + scroll_focus 红线 + 关键词条抽查)/ V2 冻结值锚定 + 两段对比 5.49:1 ≥4.5:1 / V3 预盖件运行时证词(CheckBox/CheckButton 四态图标 + PopupMenu + OptionButton)/ V4 退役零残留(四文件源码剥注释扫)/ V6 中文字体防御双断言。V5 回归=冒烟全绿(按钮/面板逐实例 override 优先级保证存量观感零变化,存量断言即回归网)。 + +## 三、批末重闸结果 + +| 闸 | 结果 | +|---|---| +| 冒烟(run_smoke 三闸) | **987 项检查 0 项失败**(基线 949 + 38 新断言) | +| run_all 单元全套 | 25 套全绿 | +| probe_gate --click | 全绿,残留 Godot=0 | +| probe_gate --full | 全绿(四探针收编段) | +| render_gate | golden 0.00%(棋盘逐像素基线零漂移) | +| doc 三闸(gdd_lint/doc_link/doc_term --strict) | 对基线零新增(存量红项不变) | +| 熵增闸(repo_structure_audit) | PASS(新增 theme/ 与 gen/ 均命中 CLAUDE.md Project Layout) | +| MC | **零跑**(零数值零行为=纯呈现批,按触发细则不发起) | + +## 四、代拍板追认单(白名单内执行项 + 事实订正,请用户追认) + +**白名单内执行**: +1. 位图微观值:滑轨柄 12×12(常/悬/废三态位图)、勾选框 14×14 四态、SpinBox updown 16×16、OptionButton 箭头 8×8;滚动条柄按引擎事实走 StyleBox(无位图);脚本=`tools/gen_theme_icons.py`(PIL,幂等可重跑,色值常量集中在头部)。 +2. `styled_slider` 退役形态=删函数+几何内联两消费方(settings_overlay/debug_overlay,两处为上限)。 +3. 词条内字号沿用既有档(tooltip 14 / 输入件与 PopupMenu 16)。 +4. 未列尽同族微观词条按冻结表同源常量(白名单#5):HSlider/VSlider `grabber_disabled` 图标(STONE_DEEP 方柄);SpinBox `up/down_background_hovered`(STONE_FAINT α0.6)/`pressed`(STONE_DEEP);OptionButton `arrow`(INK 位图);OptionButton `disabled`(button_stone_pressed 九宫格,同 `_apply_button_skin` 惯例);ScrollContainer `panel`(全透明——默认即 StyleBoxEmpty 不可见,显式接管);PopupMenu/LineEdit 边距与圆角微观值;VSlider 边距为 HSlider 旋转换位((6,0,6,0))。 + +**卡片措辞与政策/引擎事实的偏差(呈报追认)**: +5. **位图与 .import 侧车未入 git**(卡片 T0 写「.import 侧车随批入库」):`.gitignore:52` `game/assets/art/**` 全量忽略(注释明文「运行时资源本地生成不入库」——本批位图恰属本地生成件),全库既无任何 art 位图入库先例。处置=生成脚本入库(可再生)+ 位图随批拷贝回主区 `game/assets/art/ui/gen/`(已执行)+ README 溯源表载明出处。**若用户要求主题位图作为例外强制入库(theme 的 ext_resource 缺失时加载报错,与 UiKit 的缺位回退不同),一句话可补(git add -f)——请裁**。 +6. **CheckButton 图标词条名订正**(卡片 v1.2 注③称「CheckButton 用 on/off,不可与 CheckBox 共用」):Godot 4.7.2 源码(check_button.cpp BIND_THEME_ITEM)+ 默认主题链双查实证=**CheckButton 与 CheckBox 同套 `checked`/`unchecked`(+_disabled)**,`on`/`off` 在 4.7 不存在(has_theme_icon=false)。按引擎事实落位(两类共用一套位图),否则预盖静默空转——正是卡片警告的失效形态。需求卡片已归档不修订,订正随本报告呈报。 +7. **Slider 无 `grabber_pressed` 图标槽**(4.7.2 slider.cpp + 默认主题链双查):冻结表「滑轨柄·按」值 GOLD_DEEP #B07A14 无槽可落,README 留档;常/悬两态位图在位。若未来引擎开槽再补。 +8. **Godot 4.7 导入参数已无逐贴图 filter 标志**(现存 art/ui/*.import 实证):卡片「小位图各自单点设邻近采样」在 4.7.2 不可表达(filter 归全局 project setting=红线未触);位图均为原生尺寸消费(12×12/14×14/16×16/8×8),无滤波伪影。全局纹理过滤条目(06 第一层第三条)不受影响。 + +## 五、GDD 反哺点(设计权威文档不随批改,待用户逐点裁) + +1. **art-bible §7 组件规格立条款**:滚动条/滑轨/悬停气泡/输入件的组件规格(尺寸档、圆角、对比度底线)目前无条款,本批色值=临时权威——是否立条款入 §7,待用户裁。 +2. **第三层①诊断描述与代码面不符**:诊断称音量滑轨两段「同一个深棕色」,实为 #B8A582/#7A5232(2.84:1,低于 3:1 图形参考线)——「偏难辨」成立、「同色」不成立;已在 06 条目状态注记呈报,是否需回改诊断源文待用户裁。 +3. **需求卡片 v1.2 注③事实订正**(见追认单 6)——卡片已退役归档,订正只随本报告留痕。 +4. **主题色值双处存在**:.tres 字面量与 ui_kit 常量双源(卡片立项时已知代价,README 溯源表缓解)——长期是否将主题色值收敛回代码单点(程序化 Theme 生成)待用户裁。 +5. **专项观察点二**(v1.2 增补):滑轨柄 CANDLE 色是否违反焦点预算(比「关闭」按钮抢眼?)、滚动条槽 α0.35 是否可见——归用户目检,L2 微调候选已在 README 列明(STONE 灰石系 / SLOT_BACKDROP #3E362C)。 + +## 六、实机目检总清单(归用户,07 ㉔ 登记不阻塞) + +1. 引擎默认灰清零巡检:营地三处滚动容器、战斗日志/结算回看自动滚动条、设置音量滑轨、各屏悬停气泡、调试浮窗输入件、全屏 15 处分隔线——无引擎默认灰色圆角现代风残留。 +2. 音量滑轨拖到中点:已填充段(深棕)与未填充段(暖石)一眼可辨。 +3. 专项观察点:滑轨柄是否比「关闭」按钮抢眼;滚动条槽是否看得见。 +4. 预盖件无实役(CheckBox/CheckButton/OptionButton/PopupMenu 游戏零使用,备案待启用时复查)。 + +## 七、遗留与风险 + +- 位图不入 git(追认单 5)——主区已拷贝;新克隆环境需先跑 `python tools/gen_theme_icons.py`(D 盘 gamedev venv 的 PIL)或从主区拷贝。 +- Slider 柄·按无槽(追认单 7)——观感缺口限「按下滑轨柄」一瞬,调试/音量滑轨均非常态操作。 +- 遗留人闸不变:迭代 20 实机目检五件 + 21 营地四柜台〔07 ⑳〕+ 22 秘宝解锁装配〔07 ㉑〕+ 23 锻造工作间〔07 ㉒〕+ 24 敌人表三观测〔07 ㉓〕+ **25 全屏巡检〔07 ㉔〕**。 +- 本迭代位仍预留后续追加卡(roadmap 注记维持)。 diff --git a/game/assets/theme/README.md b/game/assets/theme/README.md new file mode 100644 index 00000000..31386817 --- /dev/null +++ b/game/assets/theme/README.md @@ -0,0 +1,59 @@ +# game/assets/theme/ —— UI 全局主题资源(迭代 25 · UI 全局主题批) + +- 主文件:`main_theme.tres`(Godot 4 Theme 资源,挂 `project.godot` 的 `gui/theme/custom`) +- 生成脚本:`tools/gen_theme_icons.py`(可重跑,幂等)→ 小位图落 `../art/ui/gen/` +- 依据:需求卡片 `design/research/需求卡片-UI全局主题批-2026-10-13.md` v1.2(2026-10-13) + +本目录不含内联注释(.tres 注释语法不赌),全部溯源信息以本表为准。**色值一律取自 +`game/presentation/views/ui_kit.gd` 既有常量,零新增色值**(迭代 25 契约:不新增美术素材)。 + +## 色值溯源表(字面量 ↔ ui_kit 常量) + +| ui_kit 常量 | 值 | 本主题用途 | +|---|---|---| +| BG_OVERLAY | #362B20 α0.35 | 滚动条槽(V/H) | +| PANEL_BORDER | #786E58 | 滚动条柄·常、滑轨槽描边、LineEdit/PopupMenu 边、分隔线 α0.6、勾选框边、滑轨柄描边、SpinBox 箭头底系 | +| STONE_FAINT | #8C7C64 | 滚动条柄·悬、SpinBox 箭头底·悬(α0.6,白名单#5) | +| STONE_DEEP | #554D41 | 滚动条柄·按、滑轨柄·废、勾选框·废、SpinBox 箭头底·按、LineEdit 占位字色 | +| BG_ROOT | #3A2E22 | 滑轨已填充段 grabber_area(+highlight) | +| 暖石(无常量,ui_kit.gd:743 字面量) | #B8A582 | 滑轨槽 slider(承 styled_slider 现值) | +| CANDLE | #F6C667 | 滑轨柄·常 | +| CANDLE 提亮档(lightened≈12%,≈#F7E08C) | — | 滑轨柄·悬(白名单#5;Godot lightened 同式) | +| GOLD_DEEP | #B07A14 | 滑轨柄·按——**Godot 4.7 Slider 无 grabber_pressed 图标槽**(实证:引擎源码+默认主题链双查),值留档未落位 | +| WARM | #F0E2C8 | TooltipLabel 字色(承 tooltip_theme() 现值) | +| tooltip 面板底/边(ui_kit.gd:757-759 现值) | Color(0.09,0.07,0.05,0.96) / #5A5044 | TooltipPanel | +| PANEL_DATA | #E9D9B8 | LineEdit 底、勾选框空框底、PopupMenu 面板底 | +| INK | #33261B | LineEdit/PopupMenu/OptionButton 字色、SpinBox 箭头、勾选框对勾 | +| INK α0.45 | — | OptionButton 废字色(同 _apply_button_skin 惯例) | +| GOLD_LIT | #E6BE5A | PopupMenu 条目 hover 底 | +| INK_ON_GOLD | #3C2C14 | PopupMenu 条目 hover 字色 | +| RADIUS_OBJECT | 5 | LineEdit 圆角(同数据框惯例 ui_kit.gd:476) | +| 默认字体 | res://assets/fonts/ui_font_fusion_pixel_zh_hans.ttf | 主题 `default_font`(与 project.godot `theme/custom_font` 同文件——v1.2 防御条款,防挂主题后中文字形缺失) | + +## 词条落位总览 + +| 类型 | 词条 | 载体 | +|---|---|---| +| VScrollBar / HScrollBar | scroll / grabber / grabber_highlight / grabber_pressed | StyleBoxFlat 纯色(**Godot 4 滚动条柄是 StyleBox 非 Icon**,无需位图;content margin 4 = 8px 粗细,柄最小 8px) | +| ScrollContainer | panel | StyleBoxFlat 全透明(默认即 Empty 不可见,显式接管) | +| HSlider / VSlider | slider / grabber_area / grabber_area_highlight / grabber / grabber_highlight / grabber_disabled | StyleBoxFlat + 生成位图(12×12 方柄;VSlider 边距为 H 的旋转换位) | +| TooltipPanel / TooltipLabel | panel / font_color / font_size | 承 tooltip_theme() 现值原样迁入 | +| LineEdit | normal / font_color / font_placeholder_color | StyleBoxFlat + 色词条(**占位色词条名 = `font_placeholder_color`**,4.7.2 实证;`font_color_placeholder` 不存在) | +| SpinBox | updown / up·down_background_hovered·pressed | **Godot 4 SpinBox 走 `updown` 合并图标槽**(定义了它就不再画 up/down 分件,引擎源码实证);hover/pressed 箭头底默认主题可见,按白名单#5 覆盖 | +| HSeparator / VSeparator | separator | StyleBoxLine(PANEL_BORDER α0.6 单线,1px) | +| CheckBox / CheckButton | unchecked / checked / unchecked_disabled / checked_disabled | **两类共用同一套图标名**(checked/unchecked,4.7.2 源码实证——卡片 v1.2 注③「CheckButton 用 on/off」不成立,已按引擎事实落位并呈报追认) | +| OptionButton | normal / hover / pressed / disabled / font_* / arrow | button_stone 九宫格(8px 边距,同 _apply_button_skin 观感)+ INK 字 + 生成箭头 | +| PopupMenu | panel / hover / font_color / font_hover_color / font_size | StyleBoxFlat(预盖件,含弹层) | + +## 红线遵守记录 + +- Button 类型词条**零接触**(五态矩阵归 06 第一层第二条);OptionButton 为独立主题类型(预盖件)。 +- focus 族词条**零定义**(scroll_focus / LineEdit focus / font_focus_color 等一律不写)。 +- 全局纹理过滤未动(`rendering/textures/canvas_textures/default_texture_filter` 归 06 第一层第三条); + Godot 4.7.2 导入参数已无逐贴图 filter 标志(现存 art/ui/*.import 实证),小位图均为原生尺寸消费,无滤波伪影。 +- default_font_size **未设**(全站字号走 UiKit.FS_* 逐实例 override)。 + +## 专项观察点(v1.2 增补,归用户目检) + +1. 滑轨柄 CANDLE 色是否比「关闭」按钮抢眼(违反焦点预算嫌疑)——若是走 L2 微调(候选 STONE 灰石系)。 +2. 滚动条槽 BG_OVERLAY α0.35 叠 BG_ROOT 上是否可见——若否走 L2 微调(候选提不透明度或 SLOT_BACKDROP #3E362C)。 diff --git a/game/assets/theme/main_theme.tres b/game/assets/theme/main_theme.tres new file mode 100644 index 00000000..558372d7 --- /dev/null +++ b/game/assets/theme/main_theme.tres @@ -0,0 +1,222 @@ +[gd_resource type="Theme" format=3] + +[ext_resource type="FontFile" path="res://assets/fonts/ui_font_fusion_pixel_zh_hans.ttf" id="1_font"] +[ext_resource type="Texture2D" path="res://assets/art/ui/button_stone.png" id="2_btn"] +[ext_resource type="Texture2D" path="res://assets/art/ui/button_stone_pressed.png" id="3_btnp"] +[ext_resource type="Texture2D" path="res://assets/art/ui/gen/slider_grabber.png" id="4_sg"] +[ext_resource type="Texture2D" path="res://assets/art/ui/gen/slider_grabber_highlight.png" id="5_sgh"] +[ext_resource type="Texture2D" path="res://assets/art/ui/gen/slider_grabber_disabled.png" id="6_sgd"] +[ext_resource type="Texture2D" path="res://assets/art/ui/gen/spinbox_updown.png" id="7_spu"] +[ext_resource type="Texture2D" path="res://assets/art/ui/gen/option_arrow.png" id="8_oa"] +[ext_resource type="Texture2D" path="res://assets/art/ui/gen/checkbox_unchecked.png" id="9_cbu"] +[ext_resource type="Texture2D" path="res://assets/art/ui/gen/checkbox_checked.png" id="10_cbc"] +[ext_resource type="Texture2D" path="res://assets/art/ui/gen/checkbox_unchecked_disabled.png" id="11_cbud"] +[ext_resource type="Texture2D" path="res://assets/art/ui/gen/checkbox_checked_disabled.png" id="12_cbcd"] + +[sub_resource type="StyleBoxFlat" id="SBF_vscroll_track"] +content_margin_left = 4.0 +content_margin_right = 4.0 +bg_color = Color(0.211765, 0.168627, 0.12549, 0.35) + +[sub_resource type="StyleBoxFlat" id="SBF_vscroll_grab"] +content_margin_top = 4.0 +content_margin_bottom = 4.0 +bg_color = Color(0.470588, 0.431373, 0.345098, 1) + +[sub_resource type="StyleBoxFlat" id="SBF_vscroll_grab_h"] +content_margin_top = 4.0 +content_margin_bottom = 4.0 +bg_color = Color(0.54902, 0.486275, 0.392157, 1) + +[sub_resource type="StyleBoxFlat" id="SBF_vscroll_grab_p"] +content_margin_top = 4.0 +content_margin_bottom = 4.0 +bg_color = Color(0.333333, 0.301961, 0.254902, 1) + +[sub_resource type="StyleBoxFlat" id="SBF_hscroll_track"] +content_margin_top = 4.0 +content_margin_bottom = 4.0 +bg_color = Color(0.211765, 0.168627, 0.12549, 0.35) + +[sub_resource type="StyleBoxFlat" id="SBF_hscroll_grab"] +content_margin_left = 4.0 +content_margin_right = 4.0 +bg_color = Color(0.470588, 0.431373, 0.345098, 1) + +[sub_resource type="StyleBoxFlat" id="SBF_hscroll_grab_h"] +content_margin_left = 4.0 +content_margin_right = 4.0 +bg_color = Color(0.54902, 0.486275, 0.392157, 1) + +[sub_resource type="StyleBoxFlat" id="SBF_hscroll_grab_p"] +content_margin_left = 4.0 +content_margin_right = 4.0 +bg_color = Color(0.333333, 0.301961, 0.254902, 1) + +[sub_resource type="StyleBoxFlat" id="SBF_sc_panel"] +bg_color = Color(0, 0, 0, 0) + +[sub_resource type="StyleBoxFlat" id="SBF_hslider_track"] +content_margin_top = 6.0 +content_margin_bottom = 6.0 +bg_color = Color(0.721569, 0.647059, 0.509804, 1) +border_color = Color(0.470588, 0.431373, 0.345098, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 + +[sub_resource type="StyleBoxFlat" id="SBF_hslider_fill"] +content_margin_top = 6.0 +content_margin_bottom = 6.0 +bg_color = Color(0.227451, 0.180392, 0.133333, 1) + +[sub_resource type="StyleBoxFlat" id="SBF_vslider_track"] +content_margin_left = 6.0 +content_margin_right = 6.0 +bg_color = Color(0.721569, 0.647059, 0.509804, 1) +border_color = Color(0.470588, 0.431373, 0.345098, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 + +[sub_resource type="StyleBoxFlat" id="SBF_vslider_fill"] +content_margin_left = 6.0 +content_margin_right = 6.0 +bg_color = Color(0.227451, 0.180392, 0.133333, 1) + +[sub_resource type="StyleBoxFlat" id="SBF_tooltip"] +content_margin_left = 8.0 +content_margin_top = 6.0 +content_margin_right = 8.0 +content_margin_bottom = 6.0 +bg_color = Color(0.09, 0.07, 0.05, 0.96) +border_color = Color(0.352941, 0.313725, 0.266667, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 + +[sub_resource type="StyleBoxFlat" id="SBF_lineedit"] +content_margin_left = 6.0 +content_margin_top = 3.0 +content_margin_right = 6.0 +content_margin_bottom = 3.0 +bg_color = Color(0.913725, 0.85098, 0.721569, 1) +border_color = Color(0.470588, 0.431373, 0.345098, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 + +[sub_resource type="StyleBoxFlat" id="SBF_spin_btn_h"] +bg_color = Color(0.54902, 0.486275, 0.392157, 0.6) + +[sub_resource type="StyleBoxFlat" id="SBF_spin_btn_p"] +bg_color = Color(0.333333, 0.301961, 0.254902, 1) + +[sub_resource type="StyleBoxLine" id="SBLine_hsep"] +color = Color(0.470588, 0.431373, 0.345098, 0.6) +thickness = 1 + +[sub_resource type="StyleBoxLine" id="SBLine_vsep"] +color = Color(0.470588, 0.431373, 0.345098, 0.6) +thickness = 1 +vertical = true + +[sub_resource type="StyleBoxTexture" id="SBTex_btn"] +texture = ExtResource("2_btn") +texture_margin_left = 8.0 +texture_margin_top = 8.0 +texture_margin_right = 8.0 +texture_margin_bottom = 8.0 + +[sub_resource type="StyleBoxTexture" id="SBTex_btnp"] +texture = ExtResource("3_btnp") +texture_margin_left = 8.0 +texture_margin_top = 8.0 +texture_margin_right = 8.0 +texture_margin_bottom = 8.0 + +[sub_resource type="StyleBoxFlat" id="SBF_popup_panel"] +content_margin_left = 8.0 +content_margin_top = 6.0 +content_margin_right = 8.0 +content_margin_bottom = 6.0 +bg_color = Color(0.913725, 0.85098, 0.721569, 1) +border_color = Color(0.470588, 0.431373, 0.345098, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 + +[sub_resource type="StyleBoxFlat" id="SBF_popup_hover"] +content_margin_left = 6.0 +content_margin_top = 2.0 +content_margin_right = 6.0 +content_margin_bottom = 2.0 +bg_color = Color(0.901961, 0.745098, 0.352941, 1) + +[resource] +default_font = ExtResource("1_font") +VScrollBar/styles/scroll = SubResource("SBF_vscroll_track") +VScrollBar/styles/grabber = SubResource("SBF_vscroll_grab") +VScrollBar/styles/grabber_highlight = SubResource("SBF_vscroll_grab_h") +VScrollBar/styles/grabber_pressed = SubResource("SBF_vscroll_grab_p") +HScrollBar/styles/scroll = SubResource("SBF_hscroll_track") +HScrollBar/styles/grabber = SubResource("SBF_hscroll_grab") +HScrollBar/styles/grabber_highlight = SubResource("SBF_hscroll_grab_h") +HScrollBar/styles/grabber_pressed = SubResource("SBF_hscroll_grab_p") +ScrollContainer/styles/panel = SubResource("SBF_sc_panel") +HSlider/styles/slider = SubResource("SBF_hslider_track") +HSlider/styles/grabber_area = SubResource("SBF_hslider_fill") +HSlider/styles/grabber_area_highlight = SubResource("SBF_hslider_fill") +HSlider/icons/grabber = ExtResource("4_sg") +HSlider/icons/grabber_highlight = ExtResource("5_sgh") +HSlider/icons/grabber_disabled = ExtResource("6_sgd") +VSlider/styles/slider = SubResource("SBF_vslider_track") +VSlider/styles/grabber_area = SubResource("SBF_vslider_fill") +VSlider/styles/grabber_area_highlight = SubResource("SBF_vslider_fill") +VSlider/icons/grabber = ExtResource("4_sg") +VSlider/icons/grabber_highlight = ExtResource("5_sgh") +VSlider/icons/grabber_disabled = ExtResource("6_sgd") +TooltipPanel/styles/panel = SubResource("SBF_tooltip") +TooltipLabel/colors/font_color = Color(0.941176, 0.886275, 0.784314, 1) +TooltipLabel/font_sizes/font_size = 14 +LineEdit/styles/normal = SubResource("SBF_lineedit") +LineEdit/colors/font_color = Color(0.2, 0.14902, 0.105882, 1) +LineEdit/colors/font_placeholder_color = Color(0.333333, 0.301961, 0.254902, 1) +SpinBox/icons/updown = ExtResource("7_spu") +SpinBox/styles/up_background_hovered = SubResource("SBF_spin_btn_h") +SpinBox/styles/up_background_pressed = SubResource("SBF_spin_btn_p") +SpinBox/styles/down_background_hovered = SubResource("SBF_spin_btn_h") +SpinBox/styles/down_background_pressed = SubResource("SBF_spin_btn_p") +HSeparator/styles/separator = SubResource("SBLine_hsep") +VSeparator/styles/separator = SubResource("SBLine_vsep") +CheckBox/icons/unchecked = ExtResource("9_cbu") +CheckBox/icons/checked = ExtResource("10_cbc") +CheckBox/icons/unchecked_disabled = ExtResource("11_cbud") +CheckBox/icons/checked_disabled = ExtResource("12_cbcd") +CheckButton/icons/unchecked = ExtResource("9_cbu") +CheckButton/icons/checked = ExtResource("10_cbc") +CheckButton/icons/unchecked_disabled = ExtResource("11_cbud") +CheckButton/icons/checked_disabled = ExtResource("12_cbcd") +OptionButton/styles/normal = SubResource("SBTex_btn") +OptionButton/styles/hover = SubResource("SBTex_btn") +OptionButton/styles/pressed = SubResource("SBTex_btnp") +OptionButton/styles/disabled = SubResource("SBTex_btnp") +OptionButton/colors/font_color = Color(0.2, 0.14902, 0.105882, 1) +OptionButton/colors/font_hover_color = Color(0.2, 0.14902, 0.105882, 1) +OptionButton/colors/font_pressed_color = Color(0.2, 0.14902, 0.105882, 1) +OptionButton/colors/font_disabled_color = Color(0.2, 0.14902, 0.105882, 0.45) +OptionButton/icons/arrow = ExtResource("8_oa") +PopupMenu/styles/panel = SubResource("SBF_popup_panel") +PopupMenu/styles/hover = SubResource("SBF_popup_hover") +PopupMenu/colors/font_color = Color(0.2, 0.14902, 0.105882, 1) +PopupMenu/colors/font_hover_color = Color(0.235294, 0.172549, 0.078431, 1) +PopupMenu/font_sizes/font_size = 16 diff --git a/game/presentation/ui_assembler.gd b/game/presentation/ui_assembler.gd index d4cb9e3e..d6e11dcd 100644 --- a/game/presentation/ui_assembler.gd +++ b/game/presentation/ui_assembler.gd @@ -99,10 +99,10 @@ static func build_overlays(host: Control, db) -> Dictionary: # UI 落码批 M2(2026-10-04):单列 VBox→双列(左操作 56% + 右舞台);按钮动词化+悬停解释 #(解释全迁 tooltip,G5);lvbtn 升主操作钮(烛光黄 CANDLE);右列=立绘看台。**玩法速览牌已退役 #(2026-10-06 用户令:界面禁玩法文字墙——教学内容归 Beta 帮助手册〔教学引导定稿批 P4 丙〕,历史文案在 git)**; -# root 挂 UiKit.tooltip_theme() 全树生效。返回键集不变,组合根接线零改) +# tooltip 主题归全局主题单点(迭代 25 2026-10-13——旧 root 挂程序化 tooltip 主题的做法退役)。 +# 返回键集不变,组合根接线零改) static func build_start_overlay(host: Control, db = null) -> Dictionary: var overlay := overlay_bg(host, UiKit.BG_BRIGHT) - overlay.theme = UiKit.tooltip_theme() # 石纹弱质感+斜光带+暗角(UI 对齐批 T5 2026-10-06——demo .tilebg 0.14/.beams/.vignette 三层; # 旧满铺石纹不透退役。缺位不挂即回退平色) var bd := UiKit.backdrop_tile() diff --git a/game/presentation/views/debug_overlay.gd b/game/presentation/views/debug_overlay.gd index 1a1b51b4..3800013f 100644 --- a/game/presentation/views/debug_overlay.gd +++ b/game/presentation/views/debug_overlay.gd @@ -278,7 +278,7 @@ func _slider_row(box: VBoxContainer, title: String) -> Dictionary: s.min_value = 0 s.max_value = 300 s.step = 5 - s.custom_minimum_size = Vector2(320, 24) + s.custom_minimum_size = Vector2(320, 24) # 皮肤走全局主题(迭代 25:与设置屏音量滑轨同一构建方式,消双轨) row.add_child(s) var v := UiKit.label("+0%",UiKit.FS_BODY, true) v.custom_minimum_size = Vector2(70, 0) diff --git a/game/presentation/views/settings_overlay.gd b/game/presentation/views/settings_overlay.gd index 96733f8a..f44918a4 100644 --- a/game/presentation/views/settings_overlay.gd +++ b/game/presentation/views/settings_overlay.gd @@ -56,7 +56,11 @@ func _build() -> void: var vol_lab := UiKit.label("主音量",UiKit.FS_BODY, false, UiKit.INK_LABEL) vol_lab.custom_minimum_size = Vector2(140, 0) # T8 label 列定宽(两列对齐) vol_row.add_child(vol_lab) - _volume = UiKit.styled_slider(100.0, 0.0, 100.0) + _volume = HSlider.new() + _volume.min_value = 0.0 + _volume.max_value = 100.0 + _volume.value = 100.0 + _volume.custom_minimum_size = Vector2(200, 24) # 几何/量程内联(迭代 25:样式滑杆工厂退役,皮肤走全局主题) _volume.step = 1 _volume.size_flags_horizontal = Control.SIZE_EXPAND_FILL _volume.value_changed.connect(_on_volume_changed) diff --git a/game/presentation/views/ui_kit.gd b/game/presentation/views/ui_kit.gd index 42680f90..2b63f6c1 100644 --- a/game/presentation/views/ui_kit.gd +++ b/game/presentation/views/ui_kit.gd @@ -731,32 +731,7 @@ static func switch_toggle(initial: bool) -> SwitchToggle: return SwitchToggle.new(initial) -# 样式滑杆(设置屏音量——轨道暖石+默认柄;范围/读数由消费方接) -static func styled_slider(value: float, minv := 0.0, maxv := 100.0) -> HSlider: - var s := HSlider.new() - s.min_value = minv - s.max_value = maxv - s.value = value - s.custom_minimum_size = Vector2(200, 24) - # 槽轨/填充实高(2026-10-06 判官实checkpoint:HSlider 槽=按 stylebox min 高绘制——零 margin - # StyleBoxFlat min 高 0-2px=轨道整条不可见;6px 上下 content margin=12px 实高) - s.add_theme_stylebox_override("slider", - panel_flat(Color8(184, 165, 130), PANEL_BORDER, 0, 1, Vector4(0, 6, 0, 6))) - s.add_theme_stylebox_override("grabber_area", - panel_flat(Color8(122, 82, 50), Color8(0, 0, 0, 0), 0, 0, Vector4(0, 6, 0, 6))) - return s - - -# tooltip 全站主题(深底多行素牌——§7.2 文字可读硬指标;消费方=任一祖先 Control.theme 挂一次全树生效) -static var _tip_theme: Theme = null - -static func tooltip_theme() -> Theme: - if _tip_theme != null: - return _tip_theme - var th := Theme.new() - th.set_stylebox("panel", "TooltipPanel", - panel_flat(Color(0.09, 0.07, 0.05, 0.96), Color8(90, 80, 68), 0, 1, Vector4(8, 6, 8, 6))) - th.set_color("font_color", "TooltipLabel", WARM) - th.set_font_size("font_size", "TooltipLabel", 14) - _tip_theme = th - return _tip_theme +# 样式滑杆/tooltip 主题两处局部做法已退役(迭代 25 UI 全局主题批 2026-10-13——词条迁 +# game/assets/theme/main_theme.tres 全局主题单点:滑轨 slider/grabber_area/grabber、 +# TooltipPanel/TooltipLabel;旧实现同批删除,禁新旧并存。消费方几何内联: +# settings_overlay 音量滑轨 / debug_overlay _slider_row) diff --git a/game/project.godot b/game/project.godot index 488ca4bd..c3d1b8bc 100644 --- a/game/project.godot +++ b/game/project.godot @@ -28,6 +28,7 @@ window/stretch/mode="canvas_items" [gui] theme/custom_font="res://assets/fonts/ui_font_fusion_pixel_zh_hans.ttf" +theme/custom="res://assets/theme/main_theme.tres" [rendering] diff --git a/game/smoke/smoke_all.gd b/game/smoke/smoke_all.gd index 1dc37529..c023dcd0 100644 --- a/game/smoke/smoke_all.gd +++ b/game/smoke/smoke_all.gd @@ -25,6 +25,19 @@ func check(cond: bool, label: String, quiet: bool = false) -> void: print(" [FAIL] " + label) +# WCAG 相对亮度/对比度(迭代 25 UI 全局主题批 V2——滑轨两段对比度断言用) +func _theme_rel_luminance(c: Color) -> float: + var lin := func(ch: float) -> float: + return ch / 12.92 if ch <= 0.03928 else pow((ch + 0.055) / 1.055, 2.4) + return 0.2126 * lin.call(c.r) + 0.7152 * lin.call(c.g) + 0.0722 * lin.call(c.b) + + +func _theme_contrast(a: Color, b: Color) -> float: + var la := _theme_rel_luminance(a) + var lb := _theme_rel_luminance(b) + return (maxf(la, lb) + 0.05) / (minf(la, lb) + 0.05) + + func _initialize() -> void: print("=== Dungeon Sweeper 垂直切片冒烟 ===") var db = ConfigDBScript.new() @@ -93,6 +106,7 @@ func _run_core_smoke(db, rng) -> void: _smoke_damage_types() _smoke_playtest_logger() _smoke_battle_log_view() + _smoke_global_theme() _smoke_encounter_roll() _smoke_attack_chain_fresh_pool() _smoke_clear_reward_chain() @@ -5343,6 +5357,105 @@ func _smoke_battle_log_view() -> void: check(view.parsed_text().length() > before, "行型 %s 格式化落地(解析文本增长)" % String(row_type)) +# ---- UI 全局主题冒烟(迭代 25 UI 全局主题批 2026-10-13——需求卡片 §7 验收清单 V1-V6)---- +# V1 挂载覆盖 / V2 滑轨两段修复 / V3 预盖件运行时证词 / V4 换代退役零残留 / +# V5 回归(本冒烟全绿即回归网)/ V6 中文字体防御(挂主题后 default_font 顶掉 custom_font 也不丢字形) +func _smoke_global_theme() -> void: + print("--- UI 全局主题(main_theme.tres 挂载与词条断言)---") + var th := ThemeDB.get_project_theme() + check(th != null, "V1 项目主题挂载(project.godot gui/theme/custom → main_theme.tres)") + if th == null: + return + # V1:类型集覆盖 §4「做」清单全部类型(含 PopupMenu 弹层预盖) + var need_types := ["VScrollBar", "HScrollBar", "ScrollContainer", "HSlider", "VSlider", + "TooltipPanel", "TooltipLabel", "LineEdit", "SpinBox", "HSeparator", "VSeparator", + "CheckBox", "CheckButton", "OptionButton", "PopupMenu"] + var type_set := th.get_type_list() + for t in need_types: + check(type_set.has(t), "V1 主题类型覆盖 %s" % t) + # V1 红线:Button 类型词条零接触(五态矩阵归 06 第一层第二条) + check(not type_set.has("Button"), "V1 红线 Button 类型词条零接触") + # V1 红线:focus 族词条一律零定义(扫本主题自有条目,不走默认主题链) + var focus_hits := "" + for t in type_set: + for n in (th.get_stylebox_list(t) + th.get_icon_list(t) + th.get_color_list(t) + + th.get_font_list(t) + th.get_font_size_list(t) + th.get_constant_list(t)): + if "focus" in String(n): + focus_hits += "%s/%s " % [t, n] + check(focus_hits == "", "V1 红线 focus 族词条零定义%s" % ("" if focus_hits == "" else "(违例:" + focus_hits + ")")) + # V1:关键词条抽查在位(实例走主题链解析) + var vsb := VScrollBar.new() + check(vsb.has_theme_stylebox("scroll") and vsb.has_theme_stylebox("grabber") + and vsb.has_theme_stylebox("grabber_highlight") and vsb.has_theme_stylebox("grabber_pressed"), + "V1 滚动条槽/柄三态词条在位") + check(not th.has_stylebox("scroll_focus", "VScrollBar") and not th.has_stylebox("scroll_focus", "HScrollBar"), + "V1 滚动条 scroll_focus 未定义(红线)") + var hsl := HSlider.new() + check(hsl.has_theme_stylebox("slider") and hsl.has_theme_stylebox("grabber_area") + and hsl.has_theme_stylebox("grabber_area_highlight") + and hsl.has_theme_icon("grabber") and hsl.has_theme_icon("grabber_highlight") + and hsl.has_theme_icon("grabber_disabled"), "V1 滑轨槽/填充/柄词条在位") + var le := LineEdit.new() + check(le.has_theme_stylebox("normal") and le.has_theme_color("font_color") + and le.has_theme_color("font_placeholder_color"), "V1 LineEdit 词条在位(含占位色 font_placeholder_color)") + var sp := SpinBox.new() + check(sp.has_theme_icon("updown"), "V1 SpinBox 箭头词条在位(updown 合并槽)") + var hsep := HSeparator.new() + var vsep := VSeparator.new() + check(hsep.has_theme_stylebox("separator") and vsep.has_theme_stylebox("separator"), "V1 分隔线词条在位") + var tpanel := PanelContainer.new() + var tlabel := Label.new() + check(tpanel.has_theme_stylebox("panel"), "V1 TooltipPanel 词条在位") + check(tlabel.has_theme_color("font_color") and tlabel.has_theme_font_size("font_size"), "V1 TooltipLabel 词条在位") + # V2:滑轨修复——已填充段 BG_ROOT 对槽暖石 ≈5.5:1(冻结值锚定) + var fill_sb: StyleBox = hsl.get_theme_stylebox("grabber_area") + var track_sb: StyleBox = hsl.get_theme_stylebox("slider") + if fill_sb is StyleBoxFlat and track_sb is StyleBoxFlat: + var fill_c: Color = (fill_sb as StyleBoxFlat).bg_color + var track_c: Color = (track_sb as StyleBoxFlat).bg_color + check(fill_c.is_equal_approx(Color8(58, 46, 34)) and track_c.is_equal_approx(Color8(184, 165, 130)), + "V2 冻结值锚定(已填充段=BG_ROOT #3A2E22,槽=暖石 #B8A582)") + var ratio := _theme_contrast(fill_c, track_c) + check(ratio >= 4.5, "V2 滑轨两段对比 %.2f:1 ≥4.5:1(拖到中点一眼可辨)" % ratio) + else: + check(false, "V2 滑轨 stylebox 类型均为 StyleBoxFlat") + # V3:预盖件运行时证词(临时实例化读词条——无实役控件的在役证据) + var cbx := CheckBox.new() + check(cbx.get_theme_icon("checked") != null and cbx.get_theme_icon("unchecked") != null + and cbx.get_theme_icon("checked_disabled") != null and cbx.get_theme_icon("unchecked_disabled") != null, + "V3 CheckBox 四态图标非空") + var cbt := CheckButton.new() + check(cbt.get_theme_icon("checked") != null and cbt.get_theme_icon("unchecked") != null + and cbt.get_theme_icon("checked_disabled") != null and cbt.get_theme_icon("unchecked_disabled") != null, + "V3 CheckButton 四态图标非空(与 CheckBox 同套 checked/unchecked 名,4.7 源码实证)") + var pm := PopupMenu.new() + check(pm.has_theme_stylebox("panel") and pm.has_theme_stylebox("hover") + and pm.has_theme_font_size("font_size"), "V3 PopupMenu 词条存在(弹层预盖)") + var ob := OptionButton.new() + check(ob.has_theme_stylebox("normal") and ob.has_theme_stylebox("hover") + and ob.has_theme_stylebox("pressed") and ob.has_theme_color("font_color"), + "V3 OptionButton 词条存在(预盖)") + # V4:换代退役——源码零残留(剥注释行后扫;ui_kit 两函数+挂载行+滑轨工厂) + for path in ["res://presentation/views/ui_kit.gd", "res://presentation/ui_assembler.gd", + "res://presentation/views/settings_overlay.gd", "res://presentation/views/debug_overlay.gd"]: + var src: String = FileAccess.get_file_as_string(path) + var bad := "" + for ln in src.split("\n", false): + var s := ln.strip_edges() + if s.begins_with("#"): + continue + if "styled_slider" in s or "tooltip_theme" in s or "_tip_theme" in s or "overlay.theme" in s: + bad += s + " " + check(bad == "", "V4 退役实现零残留(%s)%s" % [path, "" if bad == "" else "违例:" + bad]) + # V6:中文字体防御——default_font 非空且 Label 实取字体非空 + check(th.default_font != null, "V6 主题 default_font 非空(挂主题顶掉 custom_font 也不丢中文字形)") + var lbl := Label.new() + lbl.text = "测试" + check(lbl.get_theme_font("font") != null, "V6 Label 实取字体非空(中文字形防御实证)") + vsb.free(); hsl.free(); le.free(); sp.free(); hsep.free(); vsep.free() + tpanel.free(); tlabel.free(); cbx.free(); cbt.free(); pm.free(); ob.free(); lbl.free() + + # ---- 存档序列化冒烟(SaveManager——读写往返/新档合法/余额拒花/锻造出域拒/高版本拒读禁写/ # 损坏兜底/迁移链/域界干净/摘要 cap/摘要集成/生涯终身计数域 v6)。测试文件统一 user://smoke_save_*.json 隔离, # 段首清场+段尾清理——绝不碰 user://save.json(红线)。 diff --git a/roadmap.md b/roadmap.md index 57120ed2..f268e0da 100644 --- a/roadmap.md +++ b/roadmap.md @@ -24,7 +24,7 @@ ## 当前位置(2026-10-11 刷新) - **里程碑语义(2026-10-09 立规换代,详见下方里程碑表的换代注)**:现行里程碑 = **M3「Alpha 版本的完整实现」**——用户未明令宣布完成前停留 M3,迭代只排 M3 需求;M4=Beta 版本的完整实现,一律不排期。下文里程碑表的旧编号(M-3/M-4)保留作历史序列,语义以本节为准。 -- **迭代进度**:迭代 19 五卡全部已入库(2026-10-08);**迭代 20=专长实装批 ✅ 已入库**(2026-10-11,出口闸全绿;残留人闸=实机目检五件+V20/V21/V22 人工核对半,07 在册);**迭代 21=天赋树实装批 ✅ 已入库(2026-10-12 U0 开工单会话交付,T0-T7 全绿;残留人闸=实机目检四柜台)**;**迭代 22=秘宝体系实现重构落地批 ✅ 已入库(2026-10-12 单会话交付,T1-T7 全绿;残留人闸=实机目检秘宝解锁-装配流程)**;**迭代 23=锻造工坊实装批 ✅ 已入库(2026-10-12 单会话交付,T0-T7 全绿;残留人闸=实机目检工作间形态与购买交互)**;**迭代 24=敌人表内容修批(三关)✅ 已入库(2026-10-13 /goal+iter U0 开工单会话交付——N1 (1,2) 降档 hp22/ac2·N2 毒吐盾击两行六池·N3 敌方 attack_type 轴全填 normal+敌方结算克制消费点;冒烟 949/0+run_all 25 套+重闸全绿+MC 同种子配对 40 局×both 位移在带;实现报告=design/qa/iter24-实现报告-2026-10-13.md;残留人闸=实机目检三观测〔07 ㉓〕;代拍板追认单+GDD 反哺点五条待用户;**本迭代位仍预留后续追加卡——用户将把其他需求陆续编入本迭代**);;**迭代 25=UI 全局主题批 ✅ 已编入**(2026-10-13 用户令编入,卡①;需求卡片 v1.2 零待裁点,开工门=U0;**`game/` 代码面与迭代 24 零重叠,可并行开发**——共享文档四处重叠见迭代 25 表行注记);**迭代 26+**=M4 数值批(Beta 位·未排期——用户令 2026-10-07:后续新迭代一律不先做 M4;迭代 24 与 25 占位后本批顺延)。 +- **迭代进度**:迭代 19 五卡全部已入库(2026-10-08);**迭代 20=专长实装批 ✅ 已入库**(2026-10-11,出口闸全绿;残留人闸=实机目检五件+V20/V21/V22 人工核对半,07 在册);**迭代 21=天赋树实装批 ✅ 已入库(2026-10-12 U0 开工单会话交付,T0-T7 全绿;残留人闸=实机目检四柜台)**;**迭代 22=秘宝体系实现重构落地批 ✅ 已入库(2026-10-12 单会话交付,T1-T7 全绿;残留人闸=实机目检秘宝解锁-装配流程)**;**迭代 23=锻造工坊实装批 ✅ 已入库(2026-10-12 单会话交付,T0-T7 全绿;残留人闸=实机目检工作间形态与购买交互)**;**迭代 24=敌人表内容修批(三关)✅ 已入库(2026-10-13 /goal+iter U0 开工单会话交付——N1 (1,2) 降档 hp22/ac2·N2 毒吐盾击两行六池·N3 敌方 attack_type 轴全填 normal+敌方结算克制消费点;冒烟 949/0+run_all 25 套+重闸全绿+MC 同种子配对 40 局×both 位移在带;实现报告=design/qa/iter24-实现报告-2026-10-13.md;残留人闸=实机目检三观测〔07 ㉓〕;代拍板追认单+GDD 反哺点五条待用户;**本迭代位仍预留后续追加卡——用户将把其他需求陆续编入本迭代**);;**迭代 25=UI 全局主题批 ✅ 已入库**(2026-10-13 用户令编入,/goal+iter U0 单会话交付:全局主题资源 main_theme.tres 挂载+两处局部做法退役+冒烟 V1-V6 断言 38 条,冒烟 987/0+重闸全绿;实现报告=design/qa/iter25-实现报告-2026-10-13.md;残留人闸=实机目检全屏巡检〔07 ㉔〕);**迭代 26+**=M4 数值批(Beta 位·未排期——用户令 2026-10-07:后续新迭代一律不先做 M4;迭代 24 与 25 占位后本批顺延)。 - **近期主战场**:迭代 20/21/22/23 残留人闸(实机目检四批:专长五件+营地四柜台+秘宝解锁装配+锻造工作间,07 在册);**下一前沿=M4 数值批,待 U0 发令**(锻造工坊批 provisional 数值终值归其统一标定)。 - **实时状态**:以根目录 [active.md](active.md) 顶部「当前状态快照」节为准(`stage.txt` 已定性为旧阶段开关,仅存档)。 @@ -81,7 +81,7 @@ | 迭代 23+ | **M4 数值批(**原 22+;迭代 21 已编入天赋树实装批、迭代 22 已编入秘宝实装批,均 2026-10-11 用户令**——**Alpha 收官位·未排期**〔2026-10-09 语义换代:M4=Beta 阶段、非 Alpha 收官位,M3 未由用户明令关闭前不排期维持〕——2026-10-05 用户令编入迭代 17 卡②;2026-10-06 用户令移出独立成批并定序「Alpha 阶段最后——内容补全先行、统一数值调整殿后」〔当日曾被编入迭代 18 为收官卡,2026-10-07 用户令撤回〕;**2026-10-07 用户令二次后移:后续新迭代(迭代 20 起)一律不先做 M4,除非用户明确要求启动 M4 批次**)**:四件数值欠账合一批——①削弱档位终值(weaken 现值 −65/duration 2/refresh 考证在册;叠层改续时语义已定案,差 duration 终值+当量锚复算)②调参批数值点评(06 条目现行登记五条——任务口径「八条」与条目五条不符,需求卡片 §2.2 已呈报差异以条目为准)③迭代 10 奖励重构联动欠账①②(钥石产出重标 boss_keystone 首杀 3/3/3·复杀 2/2/3 provisional + 通关率带重扫〔通关回血 20%+AP 件首轮 +1〕)④元进度定价剩余面(forge base 20/比 150 考证在册——06 条目文本「base 10」滞后于 2026-09-22 对齿批已呈报;Boss 两档终值)。读数义务随批=迭代 14 两件后置复算(T6 MC 四带复算+T7 技能池节奏重测,均挂 07);顺路修复 damage_probe A1 改前既有红灯(判式换代批出口报告 §四.7 在册)。**硬约束:一切 MC/verifier 跑批发起前须用户批准;调参联动禁独立调参网络(β 带 [1.2,2.5] 逐 u 检算)**。需求卡片=`design/research/需求卡片-M4数值批-2026-10-05.md`(**v1.2 2026-10-06 案C 增补+联审修订**:v1.1 三事实与第五推算件照旧;联审=P3 转正顺延至重扫读数后/检算工具 WEAKEN_PCT 入同步面/F11 两句死文本全刷/T3·T5 四带复算并账一次跑批双认账/R5 改前锚=本批新立案C 锚/估时段一勘误 4.25d;案C 增补内容照旧=§2.6 三事实〔行为换代/锚全作废/难度预判〕+T0 推算稿第五件=对拍锚按新序重推导+T6 四带复算按案C 新行为首采;T0-T8≈6.25d,天然切分点 T4 末;🔴 契约 5 条含跑批批准制;**✅ 裁点全裁(2026-10-06 用户令:P1甲=维持 2 场·magnitude [60,85] 带内当量锚复算、具体值随出口 provisional 追认/P2甲 不对称有意/P3甲 3-3-3·2-2-3 维持、转正顺延至重扫读数到账且带内(Q4 二裁)/P4甲 不立直购价);开工=U0**) | 迭代 18 全部内容卡(③④⑤⑦)出口+全部内容批行为变更落定+**用户发令(未排期)**——重锚窗口须收尽全部内容批行为变更 | T0-T8≈6.25d(超软盒预挂,段一 T0-T4≈4.25d〔v1.2 勘误,原 4.5 系加总错误〕/段二 T5-T8≈2.0d) | | 迭代 23 | **锻造工坊实装批(2026-10-12 用户令编入——设计面 v0.6 就绪)**:按 [锻造工坊](design/gdd/systems/跨局循环/锻造工坊.md) **v0.6** 设计权威文档实装——迁移面:①新建锻造路线行族(现役 `meta.tres` forge_products 已随迭代 21 T5 退役、无改造对象;钥石定价历史考古 20/150%、投值归 M4)②两根类型轴所有权移交(默认值归锻造工坊配置常驻持有、hero.tres 静态表两轴删除、选中态写存档域+冒险开始参数面注入)③存档域 forge_routes(已预登记存档序列化.md v7 计划行)④满级特效本期不实装(只留扩展位)⑤敌方 attack_type 填值归敌人系统/战斗结算侧(非本批——敌方定义数据、与名字血量同时读写、无独立时序)⑥术语登记(v0.6 已做完:术语表+registry)⑦数值验证义务=改前/改后同种子配对读数。解锁通道=并联双通道;一次冒险=一武器类型+一甲型。**✅ 已全批入库(2026-10-12,/goal+iter U0 开工单会话交付——worktree g-plan2-iter23-forge 七提交;T1 行族+T2 两轴移交+T3 写口族+T5 存档 v7(序调先行)+T4 注入链+T6 工作间 UI+T7 收口;冒烟 938/0+run_all 24 套+probe click/full+render_gate+doc 三闸/熵增对基线零新增+MC 同种子配对零漂移;实现报告=design/qa/iter23-实现报告-2026-10-12.md;残留人闸=实机目检工作间形态与购买交互〔07 在册〕;代拍板追认单+GDD 反哺点待用户)** | ✅ 已入库(出口闸全绿+实机目检归用户 07 在册) | 估时随需求卡片立项(实际单会话) | | 迭代 24 | **①敌人表内容修批(三关)(2026-10-13 用户令编入;**本迭代位预留后续追加卡**——用户将把其他需求陆续编入本迭代)**:需求卡片=`design/research/需求卡片-敌人表内容修批-2026-10-13.md`(**v1.1**——grilling 复核九问 Q1-Q9 已全裁、零待裁点、开工门=U0)。三件事合一:**N1** 第一关 (1,2) 降档(`enemy.tres:48` 改两值:`hp` 50→22、`armor_class` 3→2;**敌种 `bugbear` 不动**——`enemy.tres:594-600` 注释载明该行 50 血系 2026-09-24 用户裁决的设计而非填错,且 `hobgoblin` 无立绘,故「改敌种」案已否决;本批定性=阶名化解方案实机未达预期按 2026-10-13 体验反馈重裁)· **N2** 第二/三关普通敌技能投放(`skills.tres` 12→14 行:新增 `venom_spit` 毒吐 damage 1.6/CD2 挂 (2,5)/(2,6)/(2,7) 巨蜘蛛族、`shield_bash` 盾击 damage 1.7/CD3 挂 (3,0)/(3,5)/(3,7) 灰矮人族;**首遇教学位 (2,4) 池不动**,venom_spit 自 (2,5) 起投;两新行均不带 `rider_mult`——低 atk 下恒被 `damage_floor` 兜成 1 与 0.75 档等效)· **N3** 敌方 `attack_type` 加列并全填 `normal`(挂**敌种行**、20 行同值,不做差异化;`enemy_table.gd` 加枚举校验 + `unit_container.gd:119` 加单位快照 + `battle_orchestrator.gd:1406` 第 9 参由 `""` 改传值;全局平移=穿重甲受伤 −1 / 魔法护甲 +1 / 轻甲 0,使锻造甲路线首次具备战斗意义)。**契约要点**:池与敌种键属**契约级**,改必同步 `smoke_all.gd:3211` `expect_pools`(N1 因键值不变零改动、N2 同步 6 键);节点图拓扑零触碰(A1 关卡节点图重构的地盘);(1,1) 地精一伙不在本批范围(「第二个节点」字面偏差已登记 06)。**收口去向**:06「第一关遭遇表数值异常」「第二关技能池与投放」与锻造工坊条迁移面⑥ 三条一并销号;08「二·内容量」敌种池行注摘除 | ✅ 已入库(2026-10-13 单会话交付,出口闸全绿:冒烟 949/0+run_all 25 套〔485 批基线漂移 24→25 在案〕+探针 click/full+render_gate golden 0.00%+doc 三闸/熵增对基线零新增+MC 配对三组读数;实现报告=design/qa/iter24-实现报告-2026-10-13.md;残留人闸=实机目检三观测 07 ㉓) | -| 迭代 25 | **①UI 全局主题批(引擎原生控件接管皮肤)(2026-10-13 用户令编入;UI 美化三层诊断 · 第一层第一条)**:需求卡片=`design/research/需求卡片-UI全局主题批-2026-10-13.md`(**v1.2**——grilling 三裁点全裁+同日审核六点补充落文、零待裁点、开工门=U0)。三件事合一:**T0** 新建 `game/assets/theme/main_theme.tres` 并挂 `project.godot` 的 `gui/theme/custom`,覆盖滚动条 / 滑轨 / 悬停气泡 / 输入件 / 分隔线等引擎原生控件,并预盖 CheckBox / CheckButton / OptionButton 及其弹层 PopupMenu(**须在新主题内显式设 `default_font`=现役同一字体文件**,防挂主题后中文字形缺失;新增小位图落 `game/assets/art/ui/gen/`,色值溯源表落 `game/assets/theme/README.md`)· **T1** 退役 `ui_kit.gd` 的 `tooltip_theme()` 与 `styled_slider()` 两处局部做法、消 `debug_overlay._slider_row` 双轨(🔴 旧实现同批删除,禁新旧并存)· **T2** 断言与文档同步闸。**顺手销号**=06 第三层「UI 元素细节修」之①(音量滑轨两段对比度重配,以「拖到中点一眼可辨」为准绳)。**契约要点**:🔴 Button 类型词条零接触(五态矩阵归 06 第一层第二条「UI 按钮状态矩阵缺档」,其悬停态有未裁点)· 🔴 focus 族词条零定义(归按钮批与「棋盘战斗键盘/手柄输入」连带裁决点③)· 🔴 不新增美术素材、不改美术圣经 §7 · 🔴 全局纹理过滤不动(归 06 第一层第三条)。**收口去向**:06「UI 全局主题资源缺失」与「UI 元素细节修」之①两条销号;08「三·界面」同名行与「五·表现」六行回填 | **无迭代前置**(卡片零待裁点,发令即开工)。**可与迭代 24 并行开发**:两者 `game/` 代码面零重叠(本批改 ui_kit / ui_assembler / debug_overlay / settings_overlay / camp_overlay_view / project.godot 与新增 assets/theme/;迭代 24 改 enemy.tres / skills.tres / enemy_table.gd / unit_container.gd / battle_orchestrator.gd)——**但共享文档面有四处确定重叠**:`smoke_all.gd`(两边都新增断言)、`06-待办清单.md`(两边都销号)、`roadmap.md`(两边都改迭代行)、`08-Alpha版本标准.md`(两边都回填,且它**至今是未跟踪文件**=无冲突检测、并发改会静默丢失)。**后合入的一方须先 merge master 解冲突,再跑四闸** | T0-T2≈0.5–1d(闸=冒烟基线以开工日实测为准〔最近记录 938/0〕+run_all+探针+新增主题词条断言 V1-V6;08 系未跟踪文件,改前须手工搬运进 worktree) | +| 迭代 25 | **①UI 全局主题批(引擎原生控件接管皮肤)(2026-10-13 用户令编入;UI 美化三层诊断 · 第一层第一条)**:**✅ 已全批入库(2026-10-13 /goal+iter U0 开工单会话交付,worktree g-plan2-iter25-theme 分支 iter25-theme-20261013)**——**T0 主题资源**:新建 `game/assets/theme/main_theme.tres` 挂 `project.godot` `gui/theme/custom`(15 类型全覆盖:V/HScrollBar·ScrollContainer·H/VSlider·TooltipPanel/Label·LineEdit·SpinBox·H/VSeparator + 预盖 CheckBox/CheckButton/OptionButton/PopupMenu 弹层;`default_font` 显式指向现役同字体文件=V6 中文字形防御;位图由 `tools/gen_theme_icons.py` 一次性生成落 `game/assets/art/ui/gen/`,色值溯源表落 `game/assets/theme/README.md`)· **T1 换代退役**:`ui_kit.gd` 的 `tooltip_theme()`/`_tip_theme` 与 `styled_slider()` 样式段、`ui_assembler.gd` 挂载行同批删除(禁新旧并存),settings_overlay 几何内联+debug_overlay `_slider_row` 双轨消隐· **T2 断言与文档同步闸**:冒烟新增 V1-V6 主题词条断言 38 条。**顺手销号**=06 第三层「UI 元素细节修」之①(音量滑轨两段对比度重配=已填充段 BG_ROOT #3A2E22 对暖石 #B8A582 实测 5.49:1)。**契约遵守**:🔴 Button 类型词条零接触(冒烟断言在闸)· 🔴 focus 族词条零定义(全主题扫描断言)· 🔴 零新增美术素材(位图=脚本生成纯色/几何)· 🔴 全局纹理过滤未动。**引擎事实订正(呈报追认)**:Godot 4.7.2 源码+默认主题链双查实证——①CheckButton 图标词条名与 CheckBox 同套 `checked`/`unchecked`(卡片 v1.2 注③「CheckButton 用 on/off」不成立,按引擎事实落位)②Slider 无 `grabber_pressed` 图标槽(冻结表「柄·按」值 GOLD_DEEP 留档未落位)③ScrollBar 柄是 StyleBox 非 Icon(无需位图)④4.7 导入参数已无逐贴图 filter 标志(位图原生尺寸消费无滤波伪影)。**闸**:冒烟 987/0(基线 949+本批 38 断言)+run_all 25 套+probe click/full+render_gate golden 0.00%+doc 三闸/熵增对基线零新增;MC 零跑(零数值零行为=纯呈现)。**收口去向**:06「UI 全局主题资源缺失」条移除+「UI 元素细节修」①销号;08 升 v1.3(三·界面主题行→在役、五·表现细节修行注①销号);07 ㉔ 全屏巡检登记;实现报告=design/qa/iter25-实现报告-2026-10-13.md。**待用户**:实机目检全屏巡检+专项观察点二(07 ㉔,登记不阻塞)+代拍板追认单(位图不入 git 政策口径/CheckButton 词条名订正等)+GDD 反哺点(组件规格是否立条款入 art-bible §7 等)。↓ 原任务登记:三件事合一——**T0** 新建 `game/assets/theme/main_theme.tres` 并挂 `project.godot` 的 `gui/theme/custom`,覆盖滚动条 / 滑轨 / 悬停气泡 / 输入件 / 分隔线等引擎原生控件,并预盖 CheckBox / CheckButton / OptionButton 及其弹层 PopupMenu(须在新主题内显式设 `default_font`=现役同一字体文件;新增小位图落 `game/assets/art/ui/gen/`,色值溯源表落 `game/assets/theme/README.md`)· **T1** 退役 `ui_kit.gd` 的 `tooltip_theme()` 与 `styled_slider()` 两处局部做法、消 `debug_overlay._slider_row` 双轨(🔴 旧实现同批删除)· **T2** 断言与文档同步闸。契约要点:🔴 Button 类型词条零接触 · 🔴 focus 族词条零定义 · 🔴 不新增美术素材、不改美术圣经 §7 · 🔴 全局纹理过滤不动 | ✅ 已入库(出口闸全绿+实机目检归用户 07 ㉔ 在册) | T0-T2≈0.5–1d(实际单会话) | | 迭代 26+ | **M4 数值批(**原 22+;迭代 21 已编入天赋树实装批、迭代 22 已编入秘宝实装批(均 2026-10-11 用户令)、迭代 23 已编入锻造工坊实装批(2026-10-12 用户令)**;迭代 24 已由用户令编入敌人表内容修批、迭代 25 已由用户令编入 UI 全局主题批(2026-10-13),本批顺延 26+**——**Alpha 收官位·未排期**〔2026-10-09 语义换代:M4=Beta 阶段、非 Alpha 收官位,M3 未由用户明令关闭前不排期维持〕——2026-10-05 用户令编入迭代 17 卡②;2026-10-06 用户令移出独立成批并定序「Alpha 阶段最后——内容补全先行、统一数值调整殿后」〔当日曾被编入迭代 18 为收官卡,2026-10-07 用户令撤回〕;**2026-10-07 用户令二次后移:后续新迭代(迭代 20 起)一律不先做 M4,除非用户明确要求启动 M4 批次**)**:四件数值欠账合一批——①削弱档位终值(weaken 现值 −65/duration 2/refresh 考证在册;叠层改续时语义已定案,差 duration 终值+当量锚复算)②调参批数值点评(06 条目现行登记五条——任务口径「八条」与条目五条不符,需求卡片 §2.2 已呈报差异以条目为准)③迭代 10 奖励重构联动欠账①②(钥石产出重标 boss_keystone 首杀 3/3/3·复杀 2/2/3 provisional + 通关率带重扫〔通关回血 20%+AP 件首轮 +1〕)④元进度定价剩余面(forge base 20/比 150 考证在册——06 条目文本「base 10」滞后于 2026-09-22 对齿批已呈报;Boss 两档终值)。读数义务随批=迭代 14 两件后置复算(T6 MC 四带复算+T7 技能池节奏重测,均挂 07);顺路修复 damage_probe A1 改前既有红灯(判式换代批出口报告 §四.7 在册)。**硬约束:一切 MC/verifier 跑批发起前须用户批准;调参联动禁独立调参网络(β 带 [1.2,2.5] 逐 u 检算)**。需求卡片=`design/research/需求卡片-M4数值批-2026-10-05.md`(**v1.2 2026-10-06 案C 增补+联审修订**:v1.1 三事实与第五推算件照旧;联审=P3 转正顺延至重扫读数后/检算工具 WEAKEN_PCT 入同步面/F11 两句死文本全刷/T3·T5 四带复算并账一次跑批双认账/R5 改前锚=本批新立案C 锚/估时段一勘误 4.25d;案C 增补内容照旧=§2.6 三事实〔行为换代/锚全作废/难度预判〕+T0 推算稿第五件=对拍锚按新序重推导+T6 四带复算按案C 新行为首采;T0-T8≈6.25d,天然切分点 T4 末;🔴 契约 5 条含跑批批准制;**✅ 裁点全裁(2026-10-06 用户令:P1甲=维持 2 场·magnitude [60,85] 带内当量锚复算、具体值随出口 provisional 追认/P2甲 不对称有意/P3甲 3-3-3·2-2-3 维持、转正顺延至重扫读数到账且带内(Q4 二裁)/P4甲 不立直购价);开工=U0**) | 迭代 18 全部内容卡(③④⑤⑦)出口+全部内容批行为变更落定+**用户发令(未排期)**——重锚窗口须收尽全部内容批行为变更 | T0-T8≈6.25d(超软盒预挂,段一 T0-T4≈4.25d〔v1.2 勘误,原 4.5 系加总错误〕/段二 T5-T8≈2.0d) | ## 执行纪律(2026-09-27 用户立规) diff --git a/tools/gen_theme_icons.py b/tools/gen_theme_icons.py new file mode 100644 index 00000000..b5ff694c --- /dev/null +++ b/tools/gen_theme_icons.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +"""UI 全局主题批小位图生成脚本(迭代 25 T0,2026-10-13)。 + +产出(→ game/assets/art/ui/gen/,纯色/几何、像素风): + slider_grabber.png 滑轨柄·常 12×12 CANDLE #F6C667 + PANEL_BORDER #786E58 1px 描边 + slider_grabber_highlight.png 滑轨柄·悬 12×12 CANDLE 提亮档(lightened≈12%) + 同描边 + slider_grabber_disabled.png 滑轨柄·废 12×12 STONE_DEEP #554D41 + 同描边 + spinbox_updown.png SpinBox 箭头 16×16 INK #33261B ▲▼ 合一(Godot 4 SpinBox 走 updown 合并图标槽) + option_arrow.png OptionButton 箭头 8×8 INK 向下三角 + checkbox_unchecked.png 勾选框·空 14×14 PANEL_DATA #E9D9B8 + PANEL_BORDER 边 + checkbox_checked.png 勾选框·选 14×14 同底边 + INK 对勾 + checkbox_unchecked_disabled.png 勾选框·空·废 14×14 同底 + STONE_DEEP 边 + checkbox_checked_disabled.png 勾选框·选·废 14×14 同底边 + STONE_DEEP 对勾 + +色值全部取自 game/presentation/views/ui_kit.gd 既有常量(溯源表见 game/assets/theme/README.md)—— +不新增美术素材、不动美术圣经 §7(迭代 25 契约)。滚动条柄不走位图:Godot 4 ScrollBar 的 +grabber 是 StyleBox(非 Icon),纯色 StyleBoxFlat 直接承载(见 main_theme.tres)。 + +♻ 可重跑:本脚本幂等,重复执行覆盖产出;改色值只改本脚本顶部常量后重跑 + 重导。 +用法: python tools/gen_theme_icons.py +""" +import os + +from PIL import Image + +ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +OUT = os.path.join(ROOT, "game", "assets", "art", "ui", "gen") + +# ── 色值(↔ ui_kit.gd 常量,冻结)──────────────────────────────────────────── +INK = (51, 38, 27) # INK #33261B +PANEL_DATA = (233, 217, 184) # PANEL_DATA #E9D9B8 +PANEL_BORDER = (120, 110, 88) # PANEL_BORDER #786E58 +STONE_DEEP = (85, 77, 65) # STONE_DEEP #554D41 +CANDLE = (246, 198, 103) # CANDLE #F6C667 + + +def lighten(c, amount=0.12): + """复刻 Godot Color.lightened:每通道 + (255-通道)×amount(sRGB 存储值域)""" + return tuple(min(255, round(v + (255 - v) * amount)) for v in c) + + +def save(img, name): + path = os.path.join(OUT, name) + img.save(path) + print("wrote %s (%dx%d)" % (name, img.width, img.height)) + + +def slider_grabber(fill): + """12×12 方柄:fill 实心 + PANEL_BORDER 1px 描边""" + img = Image.new("RGBA", (12, 12), (0, 0, 0, 0)) + for x in range(12): + for y in range(12): + edge = x in (0, 11) or y in (0, 11) + img.putpixel((x, y), PANEL_BORDER + (255,) if edge else fill + (255,)) + return img + + +def spinbox_updown(): + """16×16 ▲▼ 合一:上三角 y2-7、下三角 y9-14,各宽 12(INK)""" + img = Image.new("RGBA", (16, 16), (0, 0, 0, 0)) + # 上三角:顶行中心 2px(x7-8),第 6 行满宽 x2-13 + for row in range(6): + half = 1 + row # 第 row 行左右各扩 1 + for x in range(8 - half, 8 + half): + img.putpixel((x, 2 + row), INK + (255,)) + # 下三角:镜像(第 row 行满宽在底) + for row in range(6): + half = 6 - row + for x in range(8 - half, 8 + half): + img.putpixel((x, 9 + row), INK + (255,)) + return img + + +def option_arrow(): + """8×8 向下三角(OptionButton 箭头)""" + img = Image.new("RGBA", (8, 8), (0, 0, 0, 0)) + for row in range(5): + half = row + 1 + for x in range(4 - half, 4 + half - 1): + img.putpixel((x, 1 + row), INK + (255,)) + return img + + +def checkbox(border, mark): + """14×14 勾选框:PANEL_DATA 底 + 1px 边;mark 非 None 时画 2px 对勾""" + img = Image.new("RGBA", (14, 14), (0, 0, 0, 0)) + for x in range(14): + for y in range(14): + edge = x in (0, 13) or y in (0, 13) + img.putpixel((x, y), border + (255,) if edge else PANEL_DATA + (255,)) + if mark is not None: + # 对勾:(3,7)→(6,10)→(11,3),2px 粗(内区 1..12) + seg = [(3, 7), (4, 7), (4, 8), (5, 8), (5, 9), (6, 9), + (6, 10), (7, 10), (7, 11), (8, 11), (8, 10), (9, 10), + (9, 9), (10, 9), (10, 8), (11, 8), + (11, 7), (10, 7), (10, 6), (9, 6), (9, 5), (8, 5), + (8, 4), (7, 4), (7, 3), (6, 3)] + for (x, y) in seg: + if 1 <= x <= 12 and 1 <= y <= 12: + img.putpixel((x, y), mark + (255,)) + return img + + +def main(): + os.makedirs(OUT, exist_ok=True) + save(slider_grabber(CANDLE), "slider_grabber.png") + save(slider_grabber(lighten(CANDLE)), "slider_grabber_highlight.png") + save(slider_grabber(STONE_DEEP), "slider_grabber_disabled.png") + save(spinbox_updown(), "spinbox_updown.png") + save(option_arrow(), "option_arrow.png") + save(checkbox(PANEL_BORDER, None), "checkbox_unchecked.png") + save(checkbox(PANEL_BORDER, INK), "checkbox_checked.png") + save(checkbox(STONE_DEEP, None), "checkbox_unchecked_disabled.png") + save(checkbox(STONE_DEEP, STONE_DEEP), "checkbox_checked_disabled.png") + print("done → %s" % OUT) + + +if __name__ == "__main__": + main()