288 信号卡顿根治 + 中心轴面板重做 + 标签页默认状态
一、卡顿真因(实测 29.8ms/帧 → 6.6ms/帧) 1. 中心轴面板高度没有上限:288 个信号时面板高 9996px(绘图区只有 1141px) ⇒ PanelRectInsideLayer 恒为假 ⇒ 面板像素缓存一次都存不进去 ⇒ 每帧全量重画。 2. PanelGlobalKey 混入鼠标驱动状态(m_hoverSignal / m_hoverLane / m_hoverCursor / CursorTime / EdgeRangeMin/Max)⇒ 鼠标一动键就变 ⇒ 所有面板每帧重画; PanelSlotKey 里还会为每个信号调一次 EdgeCenterCountsFor(单帧 288 次查询)。 3. 缓存命中路径的投影(与面板同大的半透明抗锯齿圆角矩形)每帧重画,GDI+ 实测 > 20ms。 修法: * 新增 PlotView::InputIsInteractive()(拖拽中 / 鼠标 140ms 内移动过)。交互期间冻结 全部鼠标驱动项与统计数字、跳过投影、统计预算降到 8 万(静止时 40 万)。 m_meanRowHoverLane/Ref 例外 —— 它直接改面板像素且只在进出某行时变化。 * kEdgeScanPairsPerFrame 由 1,200,000 降为 400,000。 * 中心轴面板重做为可滚动列表 ⇒ 面板高度被绘图区夹住、缓存可用、只画可见行。 二、「中心轴边沿计数」面板重做(与「均值滤波」同风格) 条目栏为信号色叠底的可折叠栏 + 右端复选框;栏下同一行显示「上升沿 / 下降沿」; 再下面两行滑块(均值点数 / 迭代次数,标签不带 X/N),数值可点击输入上限、 右侧复位按钮;整个面板可滚动;未勾选时条目栏不可展开。 新增 Lane::edgeCenterScroll + SetLaneEdgeCenterScroll;交互复用 MEAN_* 拖拽模式 + m_meanDragCenter / m_editMeanCenter 标志分派;光标形状与均值滤波一致。 三、标签页 * 唯一标签页点 ✕ 不再弹警告:直接 erase 后 NewTab(true),名字必然为「视图 1」。 * 新建标签页(含手动新建)默认:组全部折起、无选中信号(清空全局 Selected)、 样式区无目标。 四、验证 .preflight/bugcheck.exe 59/59(A1 空闲 0.7ms、A2 平移 2.5ms、A3 双光标 2.4ms、 A4 自由标记 5.2ms、A5 中心轴拖动 6.6ms;B3 真实 WM_TIMER+WM_PAINT 路径; B5 快速连点与动画反向;C 中心轴面板交互;D 标签页默认状态) panelcheck 71/71、markercheck 13/13、ringcheck 6/6 make release / make debug 零 warning
This commit is contained in:
1 parent
8271879ede
commit
944c074ab3
11 files changed
+618
-122
No files matched your search
@@ -1097,6 +1097,12 @@ namespace jdi
|
||||
*/
|
||||
bool SetLaneMeanFilterScroll(int laneIndex, float scroll);
|
||||
|
||||
/**
|
||||
* @brief 设置某网格「中心轴边沿计数」面板内容的滚动偏移(客户区像素,0 = 顶部)。
|
||||
* @return 偏移真的发生变化返回 true。
|
||||
*/
|
||||
bool SetLaneEdgeCenterScroll(int laneIndex, float scroll);
|
||||
|
||||
/**
|
||||
* @brief 切换某网格「自由标记」面板里某个信号分组的收起状态。
|
||||
* @return 切换后为「已收起」返回 true。
|
||||
@@ -2807,12 +2813,28 @@ namespace jdi
|
||||
SignalRef m_peakDragRef; /**< 正在拖动弱峰滑块的**信号**(每个信号一套参数)。 */
|
||||
int m_meanDragLane = -1; /**< 正在拖动「均值滤波」参数滑块的面板所属网格。 */
|
||||
SignalRef m_meanDragRef; /**< 正在拖动「均值滤波」参数滑块的信号(每信号一套参数)。 */
|
||||
/**
|
||||
* @brief 当前参数滑块拖拽的目标是**中心轴边沿计数**面板(而不是均值滤波)。
|
||||
*
|
||||
* 「中心轴边沿计数」自 2026-11-02 起与「均值滤波」共用同一套可滚动列表与滑块交互,
|
||||
* 因此复用 `MEAN_POINTS` / `MEAN_ITERATIONS` / `MEAN_SCROLL` 三个拖拽模式;
|
||||
* 这个标志说明它们的写入目标是 `Lane::edgeCenterItems` 还是 `Lane::meanFilterItems`。
|
||||
*/
|
||||
bool m_meanDragCenter = false;
|
||||
/**
|
||||
* @brief 正在编辑「均值滤波」某个滑块上限时,输入框内灰色提示用的**当前上限值**。
|
||||
*
|
||||
* 与 `m_peakEditCurrentMax` 同一语义(输入框以空内容开始,空内容时显示当前上限)。
|
||||
*/
|
||||
int m_meanEditCurrentMax = 0;
|
||||
|
||||
/**
|
||||
* @brief 正在编辑「滑块上限」的是**中心轴边沿计数**面板(而不是均值滤波)。
|
||||
*
|
||||
* 与 `m_meanDragCenter` 同一思路:两者共用 `MEAN_POINTS_MAX` / `MEAN_ITERATIONS_MAX`
|
||||
* 两个编辑目标,这个标志说明提交时要写到 `Lane::edgeCenterItems` 还是 `meanFilterItems`。
|
||||
*/
|
||||
bool m_editMeanCenter = false;
|
||||
/**
|
||||
* @brief 正在编辑「迭代次数 N 上限」时,输入框内灰色提示用的**当前上限值**。
|
||||
*
|
||||
@@ -2867,6 +2889,32 @@ namespace jdi
|
||||
/** 「弱峰调整」每行滑块右侧的复位控件是否处于悬停态(用于“进入/离开”时只提示一次)。 */
|
||||
bool m_peakResetHover = false;
|
||||
|
||||
/**
|
||||
* @brief 最近一次鼠标活动(移动 / 按下 / 滚轮)的时间戳(`GetTickCount64()`)。
|
||||
*
|
||||
* 用途:**边沿统计的每帧预算**要区分“交互中”和“静止”两种状态(见
|
||||
* `kEdgeScanPairsPerFrameInteractive`)。交互期间压小预算保住跟手;鼠标停下
|
||||
* `kEdgeScanInteractiveIdleMs` 之后自动恢复高预算,把统计快速补齐。
|
||||
* 初值 0 ⇒ 启动后第一帧就算作“静止”(可以全速推进统计)。
|
||||
*/
|
||||
std::uint64_t m_lastInputActivityMs = 0;
|
||||
|
||||
/**
|
||||
* @brief 当前是否处于「交互中」(正在拖拽,或鼠标刚刚移动过)。
|
||||
*
|
||||
* 两个用途(都用它保证同一个判定口径):
|
||||
* * `Paint` 决定边沿统计本帧的扫描预算(交互 ⇒ 小预算,保住跟手);
|
||||
* * `PanelGlobalKey` / `PanelSlotKey` 决定**是否把边沿统计数字与光标时间计入面板像素缓存键**:
|
||||
* 交互期间不计入 ⇒ 键保持稳定 ⇒ 面板直接复用上一帧像素、**不做**每帧数百次统计查询
|
||||
* 与整块重绘。
|
||||
*
|
||||
* ⚠️ 用户 2026-11-02 报告:288 个信号合并到同一网格、开启中心轴边沿计数后,
|
||||
* 拖动横向光标/移动鼠标每帧要 30ms。根因正是「每帧 × 每个信号 × 一次
|
||||
* `EdgeCenterCountsFor` 区间汇总」被塞进了缓存键计算里,且结果每帧都让键变化
|
||||
* ⇒ 面板缓存永远不命中、每帧重画整块面板。
|
||||
*/
|
||||
bool InputIsInteractive() const;
|
||||
|
||||
/**
|
||||
* @brief 上一帧鼠标悬停在「均值滤波 / 弱峰调整」面板的哪个**条目栏**上。
|
||||
*
|
||||
|
||||
@@ -625,8 +625,26 @@ namespace jdi
|
||||
* 而系统时钟粒度约 15.6ms —— 当帧率高于它时(`PostMessage` 自持重绘会把帧率拉高),
|
||||
* 同一 tick 内的多帧**完全不推进**(用户报告:“按住横向光标不动时统计卡在统计中”,
|
||||
* “回车确认参数后不移动鼠标就一直停在部分值”)。
|
||||
*
|
||||
* ⚠️⚠️ **这是「非交互帧」的预算**:用户 2026-11-02 报告——288 个信号合并到同一网格、
|
||||
* 开启中心轴边沿计数后,拖动横向光标每帧要 30ms(实测),界面完全跟不上手。
|
||||
* 原因就是本预算太大:中心轴每个采样对还要按“均值点数 × 迭代次数”算一次均值窗口,
|
||||
* 1200000 对 × 11 次浮点运算 ≈ 3 位千万级运算/帧。
|
||||
* 现在交互期间改用 `kEdgeScanPairsPerFrameInteractive`(见 `Paint` 开头)。
|
||||
*/
|
||||
inline const std::size_t kEdgeScanPairsPerFrame = 1200000;
|
||||
inline const std::size_t kEdgeScanPairsPerFrame = 400000;
|
||||
/**
|
||||
* @brief **交互帧**(正在拖动 / 鼠标刚移动过)允许的边沿统计预算。
|
||||
*
|
||||
* 交互时首要目标是跟手:把预算压到非交互帧的 1/5(实测单帧统计开销 ≈6ms 以内),
|
||||
* 鼠标停下 `kEdgeScanInteractiveIdleMs` 之后自动恢复高预算、快速把统计补齐。
|
||||
* ⚠️ 不能降到 0 —— 那样“按住横向光标不动”时统计会停在“统计中…”。
|
||||
*/
|
||||
inline const std::size_t kEdgeScanPairsPerFrameInteractive = 80000;
|
||||
/**
|
||||
* @brief 鼠标停止移动多久之后恢复高统计预算(毫秒)。
|
||||
*/
|
||||
inline const std::uint64_t kEdgeScanInteractiveIdleMs = 140;
|
||||
/**
|
||||
* @brief 每个累积状态每帧的扫描配额下限(防止多个状态时前面的把预算吃光)。
|
||||
*
|
||||
|
||||
Reference in new issue
Block a user