修复垂直中键拖拽后再平移的网格纵向跳变/绘制错误

症状:对某网格做一次纵向中键拖拽(幅值窗口上下平移)后,不松开中键、只做一点点
水平(或垂直)位移,该网格波形整体纵向错位(最多 15px),看起来像"纵向跳帧/抽搐"。
松开后再按下中键做同样的微小水平移动同样复现,且与缩放等级无关。

根因:RenderLaneLayerRegion 结束时无条件把 layer.anchorYMax 重置为"当前 yMax"。
该赋值只对"整块重画 / 纵向补条(整宽)"成立(那两种情况整块像素都对齐到当前映射),
对"横向补细条(整高)"不成立 —— 横向滚动只改一条竖带,其余像素仍在原锚点上。
纵向拖动以 kLayerRollQuantum = 16px 量化:|vOffset| < 16px 时不滚动、交给贴图偏移,
因此拖动停下时图层会残留一个 <16px 的纵向偏移且 anchorYMax != 当前 yMax。第一次水平
微移(哪怕只有 3px)就把该残余偏移静默清零(vOffset 变成 0),而像素并未上移 →
整个网格的波形相对正确位置纵向错位,错位量恰好等于那个残余量。

修法:RenderLaneLayerRegion 新增形参 double anchorYMax(本次渲染像素所对应的纵向锚点),
内部以它作为幅值映射基准(yMin = anchorYMax - laneSpan)渲染,并写回
layer.anchorYMax = anchorYMax。各调用点:
  * 整块重画 / 纵向补条 / 待重画补齐:传当前 yMax(纵向补条传滚动后的 layer.anchorYMax,
    与已滚动像素同一映射);
  * 横向补细条:传 layer.anchorYMax(保持不变),细条因此与其余像素纵向同源,
    残余偏移继续由贴图偏移承担。
vOffset == 0 时新逻辑与旧逻辑完全等价,故既有"仅水平/仅纵向平移"的像素结果不变。

验证:新增离屏探针 .preflight/perf/pancheck(窗口 SW_HIDE + 直接注入消息 + 读图层内部
anchorYMax/当前 yMax/vOffset + 把持按钮帧与释放后的整幅全质量帧做纵向互相关)。
修复前 A 场景 H step 1 起 vOff 从 -15.00 被清零为 +0.00、lane0 best dy=+15px(差异 39245);
修复后全程保持 -15.00、best dy=0(差异 1220,仅已知 <=0.5px 列相位残差)。
对照/中间网格/长距水平/斜向/松开重按共 7 个场景在缩放 0/8/26 步下全部 dy=0
(中间网格 +1px 为整像素量化残差)。make clean && make all 零警告。
This commit is contained in:
DeepSeek V4.1 Flash committed 2026-10-12 22:58:27 +08:00
1 parent 7344bbe9c4
commit de27d9b94f
3 files changed
+93 -12

No files matched your search

+9 -1
View File
@@ -2319,10 +2319,18 @@ namespace jdi
* @param [IN] wideMin 位图 `x=0` 对应的时间。
* **必须与调用方的意图一致**:整块重画传 `LayerDefaultWideMin()`(以当前视界居中);
* 滚动补细条则传 `layer.wideMin`(与该图层已有像素同一映射,否则会留下接缝)。
* @param [IN] anchorYMax 本次渲染的像素所对应的**纵向锚点**(= 该网格的 `yMax`)。
* ⚠️ **必须与"本次改动的那部分像素"一致**:
* - 整块重画 / 纵向补条(整宽):整块图层都对齐到锚点 → 传**当前** `yMax`
* (纵向补条则传 `layer.anchorYMax` 滚动后的值,与已滚动的像素同一映射);
* - **横向补细条(整高)**:只改一条竖带,其余像素仍在**原锚点**上,
* 因此必须传 `layer.anchorYMax`(**绝不能传当前 `yMax`**)—— 否则贴图偏移被
* 静默清零、而像素并未上移,整个网格的波形会纵向错位(用户报告的
* "垂直拖动后再横向平移出现纵向跳变/绘制错误")。
* @return 渲染成功返回 true。
*/
bool RenderLaneLayerRegion(int laneIndex, LaneLayer& layer, int stripX, int stripW, int stripY,
int stripH, double wideMin);
int stripH, double wideMin, double anchorYMax);
/**
* @brief 前台补画各网格的**分界线**(网格顶部那条较重的横线)。
*