求解器(ui/LayoutSolver.js): - 按方向校验 anchor:竖排只收 top/bottom/center、横排只收 left/right/center, 未知 direction 一并拒绝。框架 AlignmentUtils 的 switch 对写错方向的 anchor 落到 default(居中),笔误会被静默吞掉——ROOM_CATEGORY_COLUMN 就是这么把前两行摆到画布外的。 - grid 校验合并 ctx 后的 cols/rows 必须是数字:缺 rows 时 capacity=NaN 让超载守卫失效、 循环一次不跑,静默返回空数组(一个矩形都不产出)。 - line/fan/grid 要求 anchorX/anchorY 必须是数字(框架的 anchorY||0 会把缺失变成 0); point 要求 x/y 必须是数字。 - apply() 精灵数与矩形数不等时抛错,不再静默截断:截断会让多余精灵停在上一手牌的旧坐标上。 - 统一运行时注入:ctx 里的 INJECT_KEYS(target/x/y/w/h/anchorX/anchorY/rows/ itemWidth/itemHeight)覆盖配置同名字段,优先级 ctx > bySeat > base。 - line + items 竖排显式拒绝(只实现了水平)。 配置: - ROOM_CATEGORY_COLUMN anchor 由 'left' 改为 'top'(竖排语义)。 - ROOM_OPTION_OVERFLOW_GRID 补 rows(runtime)、槽尺寸与 anchor 沿用 ROOM_OPTION_ROW, cols 直接引用 ROOM_OPTION_MAX_PER_ROW;ROOM_OPTION_ROW 补上注释里已声明的 itemHeight。 - 所有依赖运行时注入的节点加 runtime 声明,所有 attach 节点加 targetKind (sprite / layout / platform),显式区分「忘了写」与「故意延后到运行时」。 守卫(tests/test_constants.js): - 求解冒烟改为只对 runtime 声明过的键注入假值,没声明却缺字段的照常抛错变红。 - 补矩形数量断言(line/fan/grid 按项数、point/attach 恒 1)——此前只查数组与坐标类型, 空数组照样通过,「少画了几张牌」对守卫完全不可见。 - attach.target 改为只在 targetKind 指定的那一个命名空间里校验存在。 - 补 runtime 声明自身的合法性检查与布局节点总数(62)钉死。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
66 lines
2.4 KiB
JavaScript
66 lines
2.4 KiB
JavaScript
///////////////////////////////////////////////////////////////
|
||
////////// EQW_Layout: 结算区配置(清单 §6.9)//////////////////
|
||
///////////////////////////////////////////////////////////////
|
||
// 【纯数据文件】无函数、无副作用;依赖 LayoutConstants.js 先加载
|
||
// (引用其 EQW_Layout.TEXT_STYLE.*,属 EQW_Layout 内部自引用)。
|
||
var EQW_Layout = EQW_Layout || {};
|
||
|
||
EQW_Layout.RESULT_BOTTOM_PANEL = { kind: 'point', x: 430, y: 140, w: 420, h: 148 };
|
||
|
||
//底牌说明文字:贴面板底部,纯文字,清单未给宽高
|
||
EQW_Layout.RESULT_BOTTOM_TEXT = {
|
||
kind: 'attach', targetKind: 'layout', target: 'RESULT_BOTTOM_PANEL',
|
||
hAlign: 'center', vAlign: 'bottom', offsetY: -14,
|
||
runtime: ['w', 'h']
|
||
};
|
||
|
||
//三家分数光晕
|
||
EQW_Layout.RESULT_GLOW = {
|
||
kind: 'point', w: 225, h: 100,
|
||
bySeat: {
|
||
LEFT: { x: 175, y: 150 },
|
||
RIGHT: { x: 865, y: 150 },
|
||
SELF: { x: 490, y: 340 }
|
||
}
|
||
};
|
||
|
||
//三家总分大字:贴对应光晕居中。target 直接指向光晕精灵键(固定,非动态)
|
||
EQW_Layout.RESULT_SCORE_TEXT = {
|
||
kind: 'attach', targetKind: 'sprite', hAlign: 'center', vAlign: 'middle',
|
||
textStyle: EQW_Layout.TEXT_STYLE.SCORE_BIG, runtime: ['w', 'h'],
|
||
bySeat: {
|
||
LEFT: { target: 'RESULT_GLOW_LEFT' },
|
||
RIGHT: { target: 'RESULT_GLOW_RIGHT' },
|
||
SELF: { target: 'RESULT_GLOW_SELF' }
|
||
}
|
||
};
|
||
|
||
//三家『牌局分』:贴对应光晕左下
|
||
EQW_Layout.RESULT_JF_TEXT = {
|
||
kind: 'attach', targetKind: 'sprite', hAlign: 'left', vAlign: 'bottom', offsetX: -15, offsetY: 24,
|
||
runtime: ['w', 'h'],
|
||
bySeat: {
|
||
LEFT: { target: 'RESULT_GLOW_LEFT' },
|
||
RIGHT: { target: 'RESULT_GLOW_RIGHT' },
|
||
SELF: { target: 'RESULT_GLOW_SELF' }
|
||
}
|
||
};
|
||
|
||
//三家『冲关分』:贴对应光晕右下
|
||
EQW_Layout.RESULT_AW_TEXT = {
|
||
kind: 'attach', targetKind: 'sprite', hAlign: 'right', vAlign: 'bottom', offsetX: 15, offsetY: 24,
|
||
runtime: ['w', 'h'],
|
||
bySeat: {
|
||
LEFT: { target: 'RESULT_GLOW_LEFT' },
|
||
RIGHT: { target: 'RESULT_GLOW_RIGHT' },
|
||
SELF: { target: 'RESULT_GLOW_SELF' }
|
||
}
|
||
};
|
||
|
||
EQW_Layout.RESULT_BTN_CG = { kind: 'point', x: 535, y: 515, w: 183, h: 63 };
|
||
|
||
EQW_Layout.RESULT_BTN_NEXT = { kind: 'point', x: 835, y: 518, w: 180, h: 65 };
|
||
|
||
//冲关遮罩:透明度也是配置项
|
||
EQW_Layout.CG_MASK = { kind: 'point', x: 0, y: 0, w: 1280, h: 720, opacity: 0.72 };
|