fix(iced/feedback): 逐环改固定窗判据 + 贴顶边距 + Dialog 下限单测(复审 r3 P2-3/P2-1/P2-2)
D45 封顶轮的最后一改,只动这三条: - **P2-3 逐环断言(假绿)**:环本来就在固定 x 栅格(24 + 56·i、宽 40),判据从「主色连通簇数 非空」改成**六个窗逐个测**「窗内墨迹(轨道 ∪ 激活并集)外接成 40(±2)×40(±2)、且不越窗」, 外加「1..5 号窗必须有激活色弧」。簇数只打印不再当判据。G18-i 从「欠账」改成**已收口**, 并删掉模块文档里「要么把 6 个环摆成固定 x 栅格」那句错话(它们本来就在栅格上)。 环带定位也换过两版(「每行墨点 4..20」会把 40 切成 32;「首行..末行」在深色档扩到 274 行), 最终用「第一个窗里连续有墨、高度≈40 的行组」。 变异:涂掉 4 个环 → `第 1 个窗里没有任何环墨迹:环丢了` 红;25% 环缩成 20×20 → `第 1 个窗里的环应 40×40(±2),实测 20×20` 红。 - **P2-1 贴顶边距**:新增「框顶行 → 条顶行 = 36±1」与「取景框高 = 96±1」两条。 变异(`HOST_SHORT` 96 → 72,重编重拍):`D:贴底 ⇒ 框顶到条顶应为 36(96 − 48 − 12),实测 12` 红; 还原后绿。—— 之前只量「条底距框底」,宿高回退成 72 时确实抓不住。 顺带修了取景框判据本身:条自身(深色)比画布更接近框色,会把条自己认成框(实测差值 1), 现在要求「框色连续段比条本身更宽」。 - **P2-2 Dialog 下限**:补单测 `effective_width(200.0) == 280.0`(360/800 两点一并钉住), 并把「不低于官方 280」写进 `Dialog::width` 的文档。 - 欠账登记(只写表、不改代码):G18-j(动作色用全图合计,单卡漂移可能被别卡盖住)、 G18-k(再 4 处文档残留,不为凑数扩大 diff)、G18-l(取景框判据会把条的抗锯齿底行算成框, 余量 0.0008,方向是误报;加了「框高 96」后触发概率下降)。
This commit is contained in:
1 parent
11d7b64a5e
commit
d4e73aacdd
5 files changed
+198
-48
No files matched your search
@@ -275,8 +275,9 @@ fn check_snackbar(shot: &Shot, ui: &Ui) {
|
||||
if !(near(width, 300) || near(width, 344)) {
|
||||
continue;
|
||||
}
|
||||
// 1px 描边常落在半像素上(两行各 ~50% 覆盖),精确色匹配抓不住;
|
||||
// 用「更靠近框色而不是画布」判(这一带除了框没有别的灰线)。
|
||||
// 1px 描边常落在半像素上(两行各 ~50% 覆盖),精确色匹配抓不住 ⇒ 用「更靠近框色
|
||||
// 而不是画布」判。但条自身(深色)比画布**更接近**框色,所以还要一条:这一行的
|
||||
// 框色连续段必须**比条本身更宽**(框横贯整个宿主),否则会认成条自己(实测过:差值 1)。
|
||||
let distance = |pixel: [u8; 3], target: [u8; 3]| -> u32 {
|
||||
pixel
|
||||
.iter()
|
||||
@@ -284,19 +285,44 @@ fn check_snackbar(shot: &Shot, ui: &Ui) {
|
||||
.map(|(a, b)| u32::from(a.abs_diff(b)))
|
||||
.sum()
|
||||
};
|
||||
let surface_rgb = rgb(surface);
|
||||
let frame_run = |y: usize| -> usize {
|
||||
let mut longest = 0;
|
||||
let mut current = 0;
|
||||
for x in 0..shot.width {
|
||||
let pixel = shot.at(x, y);
|
||||
if distance(pixel, frame) < distance(pixel, surface_rgb) {
|
||||
current += 1;
|
||||
longest = longest.max(current);
|
||||
} else {
|
||||
current = 0;
|
||||
}
|
||||
}
|
||||
longest
|
||||
};
|
||||
// 框的横贯长度 > 条宽 + 10 ⇒ 只有框那一两行满足
|
||||
let is_frame_row = |y: usize| frame_run(y) >= width + 10;
|
||||
|
||||
let frame_row = ((bottom + 1)..shot.height)
|
||||
.find(|y| {
|
||||
(0..shot.width)
|
||||
.filter(|x| {
|
||||
let pixel = shot.at(*x, *y);
|
||||
distance(pixel, frame) < distance(pixel, rgb(surface))
|
||||
})
|
||||
.count()
|
||||
>= 200
|
||||
})
|
||||
.find(|y| is_frame_row(*y))
|
||||
.unwrap_or_else(|| {
|
||||
panic!("D:窄条下方没找到宿主取景框(条 y {top}..{bottom},宽 {width})")
|
||||
});
|
||||
let frame_top_row = (0..*top)
|
||||
.rev()
|
||||
.find(|y| is_frame_row(*y))
|
||||
.unwrap_or_else(|| panic!("D:窄条上方没找到宿主取景框(条顶 y {top})"));
|
||||
// 复审 P2-1:宿高回退到 72(上下留白相等)时这条会红。
|
||||
assert!(
|
||||
(*top as i64 - frame_top_row as i64 - 36).abs() <= 1,
|
||||
"D:贴底 ⇒ 框顶到条顶应为 36(96 − 48 − 12),实测 {}",
|
||||
*top as i64 - frame_top_row as i64
|
||||
);
|
||||
let frame_height = frame_row - frame_top_row + 1;
|
||||
assert!(
|
||||
frame_height.abs_diff(96) <= 1,
|
||||
"D:取景框高应 96(宿主高),实测 {frame_height}"
|
||||
);
|
||||
margins.push(frame_row - bottom);
|
||||
}
|
||||
assert!(
|
||||
|
||||
Reference in new issue
Block a user