新增实验性功能「自由标记」:网格内跟随鼠标的纵向光标 + 单击固定数据点 + 浮动面板
需求(用户):网格右键菜单「实验性功能」里新增带 √ 的「自由标记」。开启后网格内跟随鼠标
出现一条仅限本网格的纵向光标(上下各一个把手、不显示时间值),穿过信号时只标注离鼠标
最近的数据点;左键单击把该点固定(带 ✕ 可移除,鼠标移开仍显示、超出视界直接不显示),
后续固定点显示为相对前一个的增量;面板按信号分组列出「值(±增量) = 枚举」+「t:… Δt:…」
(两列右对齐、可双击按秒编辑并自动换位);命中自动点线判据的信号要有吸附提示;
两级 ✕ 都要悬停提示;与选区放大共存时原地单击 = 固定、按下拖动 = 框选。
一、数据层
- Lane 新增 freeMarker 开关、freeMarkerItems(FreeMarkerItem{ref, time})、freeMarkerPanel。
time 是「显示时刻」(画在 TimeToX(time) 处),与光标同一口径;取值必须走
SampleDisplayedSignalAt(内部处理时间偏移与水平镜像)。
- 新增 AddFreeMarker / RemoveFreeMarker / RemoveFreeMarkerAt / RemoveFreeMarkersOf /
FindFreeMarker / HasFreeMarkers。同一信号同一时刻不重复加入(相对容差 1e-12);
freeMarkerItems 保持插入顺序,显示顺序与「前一个固定点」一律由 SortedFreeMarkerIndices
按时间排序得出(删除某项不打乱其它项下标)。
- LaneCarry 同步携带,勾选/取消勾选信号导致网格重建时不会丢掉已固定的点。
二、网格内交互
- ProbeFreeMarker:仅当鼠标所在网格开启该功能时有效;在网格内全部可见信号里挑屏幕纵向
距离鼠标最近的数据点。MinorCellSparse 成立时经 SnapTimeToSample 吸附到真实采样时刻,
绘制侧画一圈圆环作为吸附提示。吸附只看判据,不看当前绘制方式。
- PaintFreeMarker(接在 paintOverlays 里、浮动面板之前):纵向线只在本网格内,上把手尖端
朝下(与常规光标顶部把手一致)、下把手尖端朝上,不画时间读数;已固定点画低透明度细线 +
圆点 + 「值(±增量) = 枚举」胶囊 + 行尾 ✕(悬停高亮 + 提示气泡);
超出视界直接不显示(不复用常规数据点的贴边定格 + 方向三角)。
- 网格内固定点 ✕ 的命中矩形由绘制时登记(m_freeMarkerHits),因为它的位置取决于取值文本宽度。
- OnMouseLeave 清跟随光标与三处悬停态(已固定的点保留)。
三、单击 vs 框选
- OnLButtonDown 在开启该功能的网格上只登记 m_freeMarkerPendingFix,并把拖拽模式设为
「选区放大 ? RUBBER_SELECT : PAN」;OnLButtonUp 里只有「整段操作没有拖动且选区轴向未定」
才 AddFreeMarker,否则照旧框选/平移。
四、浮动面板(EdgePanelKind::MARK / PLOT_CMD_LANE_FREE_MARKER = 12)
- 每个可见信号一行名称(右侧带清除该信号全部固定点的 ✕),名称行下方按时间升序列出该信号的
固定点;没有任何固定点时第一行给灰色提示。
- 行 = 左侧「值(±增量) = 枚举文本」(无尖头括号、首项无增量)+ 右侧两列各自右对齐的
「t:<时刻>s」与「Δt:+<复合单位>」(自动单位匹配)+ 行尾 ✕。
两列右边界存进 EdgePanelLayout(markerTimeRight / markerDeltaRight),保证所有条目纵向对齐。
- 双击行:左半编辑自身时刻(FREE_MARKER_TIME),右半编辑相对前一固定点的间隔
(FREE_MARKER_DELTA,最左边的点没有前一项所以不进入编辑)。提交后只改 time,
顺序由排序函数自动重排(越过后续点即交换条目位置)。
- PanelSlotKey 把每个固定点的信号 + 时刻、全部 marker 行矩形与两列边界一起 mix。
五、一并修掉的两个自伤
1. EdgePanelWidth 的 MARK 分支原本逐行取采样值算文本宽度 —— 它被 EdgePanelLayoutFor 调用,
而后者在 TopPanelAtPoint / SyncPanelOrder 里每次鼠标移动调用数次,等于「鼠标一动就做几十次
采样查询」。改为固定宽度 kFreeMarkerPanelWidth(340 逻辑像素)+ 绘制侧 UiEllipsize。
2. PaintFreeMarker 与跟随光标的胶囊绘制原本是两份重复代码,抽 PaintFreeMarkerCapsule 共用;
FreeMarkerLabelRects 增加 text 出参,避免绘制侧重复求解一次取值。
验证(全离屏,不占用鼠标/键盘/屏幕)
- 新增 .preflight/markcheck 31/31:探测有效与就近选择、原地单击恰好新增 1 个固定点、
选区放大共存(单击固定不缩放 / 拖动缩放不固定)、面板行数与时间升序、首项无增量、
后续项增量与 Δt 正确、两列右对齐、行尾 ✕ 只删 1 项、信号名 ✕ 清空该信号、
编辑 Δt 后移动并重排、深放大时吸附且时刻精确等于采样时刻、视界外固定点不绘制。
- 回归:editcheck 20/20、round3check 31/31、round4check 34/34、round5check 5/5、
convcheck 18/18;check 136/137(唯一失败项是本轮之前就存在的不稳定项,上一轮已用
git stash 在基线复现同一数值);真实 MF4 仍 283/8/18/24 个信号。
- make release / make debug 零警告。
- TargetCheck.exe 833,536 字节(814.0 KiB)—— 比上一轮 +24 KB,首次超出旧的 800 KiB
红线约 14 KB。已做的瘦身见上;剩余为新功能的真实代码量,若要回到 800 KiB 以内需要
改变取舍(动态 CRT / UPX / 砍其它功能),本轮按「实现功能优先」未动。
文档:Documents/agent_mem.md 同步 §10 变更日志、§11.2 第 181-188 条硬约束
与文末本轮小节。
This commit is contained in:
1 parent
53b981a2a9
commit
dd8f63aa0e
10 files changed
+1735
-16
No files matched your search
@@ -3009,6 +3009,8 @@ else if (panelOnly) { /* 只回送“本帧重绘过的区域并集” */ }
|
||||
|
||||
| 2026-10-20 | DeepSeek-V4.1-Flash(**本机**) | **全项目大检查(性能 / BUG / 过期注释 / 错误命名)+ 修复(详见 §12 末尾「2026-10-20 第六轮」与 §11.2 第 171–180 条)**。① **数据层 BUG**:`MatH5` 的 `U8/U16/U32/U64` 用「逐字节 `Cached()`」拼装,而 `Cached` 只服务同一 64KB 块内的请求 ⇒ **跨块标量静默读成 0**(分块 B-tree 的 chunk 偏移/子节点地址被破坏,无任何报错);改为 `ScalarLE()`(命中缓存用缓存,否则一次 `ReadAt`)。`Mf4Loader::IsBlock` 未校验链接表是否落在块内 ⇒ `DataOffset` 越界后 `block_len - (data-offset)` **uint64 下溢**,下游 `vector(usable+1)` 直接 `bad_alloc`;`ReadAt`/`IsBlock` 的 `offset + bytes > size` 也回绕。非字节对齐的 **64 位整数**用「先拼 64 位再右移」会丢掉最高字节(32/8 位宽度组合受影响);`cg_cycle_count` 无上限(损坏文件可让程序申请几十 GB);`CsvLoader` 表头分支不跳过 `#`/`%` 注释行(整份文件解析失败);`MatLoader` 把文件里的 double 直接 `static_cast<int>`(NaN 越界 = UB)、普通对象递归无深度上限;`Utf8Util::BuildTicks` 的 `double→long long` 越界转换。② **UI BUG**:工具栏按钮**永远不显示悬停高亮**(`Paint` 读的 `Button::hover` 全仓从未赋值);菜单打开时**每个消息**都无条件取消底层拖拽 ⇒ 菜单自己的内联输入框无法拖拽框选(`Target::EDIT_FIELD` 被误清);`GdiplusShutdown` 前未释放 `PlotView` 的 GDI+ 位图(`Application` 是进程单例,退出时访问违例);`WM_KILLFOCUS` 不提交标签页/绘图区编辑;`WM_LBUTTONUP` 无条件 `ReleaseCapture` 抢走中键平移的捕获;`TextEdit` 字符被过滤器拒绝却返回 `true`、无选区时 `Ctrl+X` **清空整段文本**;`InvalidateRows()` 不作废 `m_editRow` ⇒ 行集合变化后回车把新名字写到**另一条**信号;`EndFilterEdit` 不调 `ApplyFilterText`(空格+回车后列表仍处于筛选态);`SignalBadgeVisible` 三处判据不一致(未绘制处仍可点出菜单);折起动画结束后不夹取滚动量(列表底部空白 + 滑块画出轨道);快速双击分组名改名后**折起动画仍在播**。③ **PlotView 缓存/正确性**:`FindStyleOnlyLanes` 只比 4 个外观字段,而 `SceneGeometryHash` 还排除了系数/镜像/偏移 ⇒ 两个网格同时改不同属性时有一个带着旧像素被当成“最新”;拖拽光晕被烘进宽基底图层(`LaneLayerHash` 不含它);`m_legendHits` 半可见时提前返回导致点中“看不见的图例”;面板主体 96% → **不透明**(消除平移后 4% 透出的旧波形);PAN / Shift+滚轮绕过 `SetTimeView`(自动点线不随平移重判);内联输入框命中用 `uiSmall` 而绘制用 `monoSmall`;派生曲线取值未按 `SourceIndexFor` 映射(水平镜像时读到镜像另一端);`EdgePanelWidth` 缺 `style/axis` 空指针守卫;`MinorCellSparse`/`AutoRangeLaneToView` 的二分结果未夹到 `count`(时间轴比 values 长时越界)。④ **清理**:删除死接口 `Toolbar::ActionLabel`、`Theme::statusBg`、`PopupMenu::editResult` 死机制、`Toolbar::Layout` 的重复 `clear()`、`HitRow` 的恒假分支、`OnDoubleClick` 的重复命中判定;修正一批过期/错误注释(`EmitEnvelopeBand` “不做加宽”、`LaneLayerHash` 的图例说法、`MeanFilterCurve` 的窗口说法、样式区行数与「调整」按钮顺序、`FIT_ALL` 退出缩放模式、`RemoveSignal` 的 ✕ 位置、`.mat`/`.dat` 格式文档、`MatH5` “映射视图”等)。⑤ **体积评估(未做修改)**:release **809,472 B**;`objdump` 分节 `.text 652KB / .xdata 43KB / .pdata 32KB / .rdata 42KB / .rsrc 20KB / .idata 11KB`;**去掉 `-ld3d11 -ldwmapi -ld3dcompiler` 实测 0 字节收益**(静态库只拉引用到的对象);仓内已无 `<iostream>/<sstream>/<filesystem>` 等体积炸弹。验证:全部离屏探针(`check`/`editcheck`/`round3check`/`round4check`/`round5check`/`convcheck`/`loadcheck`)与 4 个 MF4 + 3 个 `.mat`(含 1.29GB `BIG_MAT.mat`)回归通过;`make release`/`make debug` 零警告。 |
|
||||
|
||||
| 2026-10-20 | DeepSeek-V4.1-Flash(**本机**) | **新增实验性功能「自由标记」(网格内跟随鼠标的纵向光标 + 单击固定数据点 + 面板)**(详见 §12 末尾「2026-10-20 第七轮」与 §11.2 第 181–188 条)。① **数据层**:`Lane` 新增 `freeMarker` 开关、`FreeMarkerItem{ref, time}` 列表(`time` 存**显示时刻**,与光标同一口径)与 `freeMarkerPanel`;新增 `AddFreeMarker/RemoveFreeMarker/RemoveFreeMarkerAt/RemoveFreeMarkersOf/FindFreeMarker/HasFreeMarkers`(同一信号同一时刻不重复加入,容差 1e-12 相对量);`LaneCarry` 一并携带(重建网格不丢)。② **网格内交互**:`ProbeFreeMarker` 在「开启该功能的网格」内挑**离鼠标最近**的那个数据点(`MinorCellSparse` 成立时经 `SnapTimeToSample` 吸附到采样时刻并画圆环提示);`PaintFreeMarker` 画**仅限本网格**的纵向光标(上把手尖端朝下、下把手尖端朝上,**不显示时间读数**)+ 就近取值胶囊;已固定点画细线 + 圆点 + `值(±增量) = 枚举` 胶囊 + 行尾 ✕(悬停高亮 + 提示气泡)。**超出视界直接不显示**(不像常规数据点那样贴边定格 + 三角)。③ **单击 vs 框选**:`OnLButtonDown` 只登记 `m_freeMarkerPendingFix`,`OnLButtonUp` 里**原地未拖动**才真正 `AddFreeMarker`;选区放大模式下「按下后拖动」照旧进入框选并缩放。④ **面板**:新 `EdgePanelKind::MARK`(`PLOT_CMD_LANE_FREE_MARKER = 12`),按「网格内信号顺序 → 该信号内时间升序」展开;每行 `值(±增量) = 枚举` + 两列**右对齐**的 `t:<时刻>s` / `Δt:+<复合单位>`;信号名右侧 ✕ 清除该信号全部固定点、行尾 ✕ 移除单个;双击行编辑「自身时刻」或「相对前一固定点的间隔」(秒),提交后 `SortedFreeMarkerIndices` 自动重排(越过后续点即交换条目位置)。⑤ **两处修正**:`EdgePanelWidth` 的 MARK 分支**不做采样查询**(它被 `TopPanelAtPoint`/`SyncPanelOrder` 高频调用,逐行取值会拖慢鼠标),改用固定宽度 `kFreeMarkerPanelWidth` + 绘制侧省略号;`PaintFreeMarker` 与跟随光标共用 `PaintFreeMarkerCapsule`(避免两份重复绘制)。验证:新增离屏 `.preflight/markcheck` **31/31**(探测/就近选择/单击固定/三处✕/增量与时间列对齐/选区放大共存/吸附/越界不显示/间隔编辑后重排);回归 `check` 136/137(唯一失败项为既有不稳定项,基线同样失败)、`editcheck` 20/20、`round3check` 31/31、`round4check` 34/34、`round5check` 5/5、`convcheck` 18/18,真实 MF4 仍 283/8/18/24;`make release`/`make debug` 零警告;`TargetCheck.exe` **833,536 字节(814.0 KiB)** —— 比上一轮 **+24 KB**,**首次超出 800 KiB 的旧红线约 14 KB**。 |
|
||||
|
||||
## 11. 跨设备协作须知(起源设备视角)
|
||||
|
||||
> **本文件是唯一权威记忆**。所有设备 / Agent 共用它,**不要再新建 `agent_mem_origin.md` 等旁支记忆文件**。
|
||||
@@ -3868,6 +3870,36 @@ else if (panelOnly) { /* 只回送“本帧重绘过的区域并集” */ }
|
||||
180. ⚠️ **二分得到的可见下标必须夹到 `count = min(时间轴长度, values 长度)`**:分组时间轴可能比
|
||||
某条信号长(多信号共轴、有的信号短),`lower_bound` 在**整条** `axis.time` 上进行时
|
||||
`begin/end` 会超出 `values` 范围 ⇒ 逐点扫描越界读。
|
||||
181. ⚠️⚠️ **新增实验性功能必须同时改这 6 处,缺一个就会出现"开关点了没反应/面板不出现"**:
|
||||
① `EdgePanelKind` 加枚举;② `PlotViewInternal.hpp` 的 `kEdgePanelKinds[]`(绘制与命中共用的
|
||||
遍历表);③ `EdgePanelWidth` 与 `EdgePanelLayoutFor` 的 `enabled/open` 三元表达式与
|
||||
`shown` lambda + `kOrder[]`;④ `PaintEdgeCursor` 里该面板的绘制分支;
|
||||
⑤ `PanelSlotKey`(面板像素缓存的键,**凡影响面板文字的都要 mix**);
|
||||
⑥ `PlotMenuCommand` + `ApplicationCommands` 的菜单项与派发。
|
||||
⚠️ `EdgePanelLayoutFor` 里那些 `x ? ... : (y ? ... : ...)` 链很容易漏一个分支——
|
||||
漏掉的后果是该功能的 `enabled/open` 恒为 false ⇒ 面板永远不显示。
|
||||
182. ⚠️⚠️ **`EdgePanelWidth` 里绝不能查采样值**:它被 `EdgePanelLayoutFor` 调用,而后者在
|
||||
`TopPanelAtPoint` / `SyncPanelOrder` 里被**每次鼠标移动调用数次**。若在那里逐行
|
||||
`SampleDisplayedSignalAt` 算文本宽度,就变成"鼠标一动几十次采样查询",交互立刻变卡。
|
||||
需要宽度时用固定常量 + 绘制侧 `UiEllipsize` 截断。
|
||||
183. ⚠️⚠️ **「自由标记」的 `FreeMarkerItem::time` 是「显示时刻」**(= 画在 `TimeToX(time)` 处),
|
||||
与 `TabConfig::CursorTime()` 同一口径;取值必须用 `SampleDisplayedSignalAt`
|
||||
(内部减 `style.offsetTime`、处理水平镜像),**不要**直接用 `time` 索引 `axis.time`。
|
||||
184. ⚠️⚠️ **「自由标记」的条目顺序只能由 `SortedFreeMarkerIndices` 决定**:
|
||||
`Lane::freeMarkerItems` 保持**插入顺序**(删除某项不会打乱其它项的下标),
|
||||
面板显示顺序、"前一个固定点"(增量与 Δt 的基准)都由那个函数按时间排序后得到。
|
||||
绘制、命中、增量计算三处必须共用它,否则会各自排一次序而错位。
|
||||
185. ⚠️ **「自由标记」超出视界的固定点直接不显示**(用户明确要求):不要复用常规数据点
|
||||
那套"贴边定格 + 方向三角"的处理(`MakeDataMarker`),否则会被误认为该点在视界内。
|
||||
186. ⚠️ **「自由标记」与选区放大共存的单击语义**:按下时**只登记意图**
|
||||
(`m_freeMarkerPendingFix`),抬起时若"整段操作没有拖动且选区轴向未定"才固定数据点;
|
||||
否则照旧进入框选。⚠️ 不能在 `OnLButtonDown` 里直接固定 —— 那样用户想框选时每按一次都会
|
||||
多一个固定点。
|
||||
187. ⚠️ **网格内固定点的 ✕ 命中矩形由绘制时登记**(`m_freeMarkerHits`):它依赖取值文本宽度
|
||||
(而文本取决于数值),命中测试无法重新推算。与 `m_legendHits` 同一套路:
|
||||
绘制时重建、`OnMouseMove`/`OnLButtonDown` 读取。
|
||||
188. ⚠️ **`PaintFreeMarker` 必须画在 `PaintEdgeCursor`(浮动面板)之前**:面板在最上层,
|
||||
自由标记的胶囊/✕ 不得盖住面板;接入点是 `paintOverlays()`(三个绘制分支共用)。
|
||||
|
||||
### 11.3 离屏验证方法学(本机偏好,强烈建议沿用)
|
||||
|
||||
@@ -7084,5 +7116,89 @@ DG3 data=0 cycle=0 (空组,一个字符串通道)
|
||||
`带无障碍对照-防夹力曲线数据 Group1 x2.mat` 4 组 8 信号、**`BIG_MAT.mat` 5 信号(私有内存 +741MB)**。
|
||||
- `make release` / `make debug` **零警告**。
|
||||
|
||||
---
|
||||
|
||||
## 本轮(2026-10-20 第七轮,本机):实验性功能「自由标记」
|
||||
|
||||
> 用户需求:在网格右键菜单的「实验性功能」里新增带 √ 的「自由标记」。
|
||||
> 开启后网格内跟随鼠标出现一条**仅限本网格**的纵向光标(上下各一个把手、不显示时间值),
|
||||
> 光标穿过信号时只标注**离鼠标最近**的数据点;左键单击把该点固定下来(带 ✕ 可单独移除,
|
||||
> 固定点在鼠标移开后仍显示、超出视界直接不显示),后续固定点显示为相对前一个的增量;
|
||||
> 浮动面板按信号分组列出 `值(±增量) = 枚举文本` + `t:… Δt:…`(两列右对齐,可双击按秒编辑,
|
||||
> 编辑后位置移动并在越过后续点时自动换位);命中「自动点线」判据的信号要给出吸附提示;
|
||||
> 面板两级 ✕(信号名清空该信号 / 行尾移除单项)都必须有悬停提示;
|
||||
> 与「选区放大」共存时**原地单击 = 固定数据点、按下后拖动 = 框选**。
|
||||
|
||||
### A. 数据层(`Utilities`)
|
||||
|
||||
- `Lane` 新增:`bool freeMarker`、`std::vector<FreeMarkerItem> freeMarkerItems`、`LanePanelState freeMarkerPanel`。
|
||||
`FreeMarkerItem{ SignalRef ref; double time; }` —— **`time` 是显示时刻**(= 画在 `TimeToX(time)` 处),
|
||||
与 `TabConfig::CursorTime()` 同一口径;取值用 `SampleDisplayedSignalAt`(内部处理时间偏移与水平镜像)。
|
||||
- 新增 `AddFreeMarker / RemoveFreeMarker / RemoveFreeMarkerAt / RemoveFreeMarkersOf / FindFreeMarker /
|
||||
HasFreeMarkers`。同一信号同一时刻**不重复加入**(相对容差 1e-12);`freeMarkerItems` **保持插入顺序**
|
||||
(删除某项不打乱其它项的下标),显示顺序一律由 `SortedFreeMarkerIndices` 按时间排序得出。
|
||||
- `LaneCarry` 同步携带三件套 ⇒ 勾选/取消勾选信号导致网格重建时**不会丢掉已固定的点**。
|
||||
|
||||
### B. 网格内:跟随光标 + 固定点
|
||||
|
||||
- `ProbeFreeMarker(mouseX, mouseY)`:仅当鼠标所在网格开启了该功能时有效;在网格内**全部可见信号**里
|
||||
挑屏幕纵向距离鼠标最近的那个数据点。判据 `MinorCellSparse` 成立时经 `SnapTimeToSample` **吸附**到
|
||||
真实采样时刻(并置 `snapped`,绘制侧画一圈圆环作为吸附提示)。
|
||||
⚠️ 吸附与否**只看判据**,不管当前是散点/线段、也不管用户是否手动改过样式(用户明确要求)。
|
||||
- `PaintFreeMarker`(在 `paintOverlays` 里、`PaintEdgeCursor` **之前**调用):
|
||||
* 跟随光标:纵向线**只在本网格内**(`clipTop..clipBottom`),上把手尖端朝下(与常规光标顶部把手一致)、
|
||||
**下把手尖端朝上**(用户明确要求),**不画时间读数**;只画最近点的取值胶囊;
|
||||
* 已固定点:低透明度细线 + 圆点 + `值(±增量) = 枚举` 胶囊 + 行尾 ✕(悬停高亮 + 提示气泡);
|
||||
* **超出视界直接不显示**(不复用常规数据点的"贴边定格 + 方向三角")。
|
||||
- 两处 ✕ 的命中:网格内固定点 ✕ 的矩形**由绘制时登记**(`m_freeMarkerHits`,与 `m_legendHits` 同套路),
|
||||
因为它的位置取决于取值文本宽度;面板内 ✕ 直接取布局矩形。
|
||||
- `OnMouseLeave` 清 `m_freeMarker` 与三处悬停态(已固定的点保留)。
|
||||
|
||||
### C. 单击 vs 框选(与「选区放大」共存)
|
||||
|
||||
`OnLButtonDown` 在绘图区内、开启该功能的网格上**只登记** `m_freeMarkerPendingFix`,
|
||||
并把 `m_dragMode` 设为「选区放大模式 ? RUBBER_SELECT : PAN」;`OnLButtonUp` 里只有
|
||||
**整段操作没有拖动且选区轴向未定**时才 `AddFreeMarker`,否则照旧走框选/平移。
|
||||
⚠️ 不能在按下时就固定 —— 那样用户想框选时每按一次都会多一个固定点。
|
||||
|
||||
### D. 浮动面板(`EdgePanelKind::MARK`)
|
||||
|
||||
- 布局:标题「自由标记」;每个**可见信号**一行名称(右侧带「清除该信号全部固定点」✕),
|
||||
名称行下方按 `SortedFreeMarkerIndices` 的顺序逐行列出该信号的固定点(从左到右 == 从上到下);
|
||||
没有任何固定点时第一行给灰色提示「在网格内单击可固定数据点」。
|
||||
- 行内容:左侧 `值(±增量) = 枚举文本`(**没有尖头括号**;首项无增量),右侧两列**各自右对齐**:
|
||||
`t:<时刻>s`(与光标时间读数同格式)与 `Δt:+<复合单位>`(与双光标差值同格式,自动单位匹配),
|
||||
再右侧是行尾 ✕。两列右边界存在 `EdgePanelLayout::markerTimeRight/markerDeltaRight`,
|
||||
⇒ 所有条目的时间尾缀纵向对齐。
|
||||
- 双击行:左半 → `PlotEditTarget::FREE_MARKER_TIME`(编辑自身时刻,秒);
|
||||
右半 → `FREE_MARKER_DELTA`(编辑相对前一固定点的间隔,秒;最左边的点没有前一项 ⇒ 不进入编辑)。
|
||||
提交后只改 `time`,顺序由排序函数自动重排(**越过后续点即交换条目位置**)。
|
||||
- `PanelSlotKey` 把每个固定点的「信号 + 时刻」与全部 marker 行矩形、两列边界一起 mix
|
||||
(否则增删固定点后会贴回旧像素)。
|
||||
|
||||
### E. 一并修掉的两个自伤
|
||||
|
||||
1. **`EdgePanelWidth` 的 MARK 分支原本逐行取采样值算文本宽度** —— 它被 `EdgePanelLayoutFor` 调用,
|
||||
而后者在 `TopPanelAtPoint` / `SyncPanelOrder` 里**每次鼠标移动调用数次** ⇒ 变成"鼠标一动就几十次
|
||||
采样查询"。改为固定宽度 `kFreeMarkerPanelWidth`(340 逻辑像素)+ 绘制侧 `UiEllipsize`。
|
||||
2. `PaintFreeMarker` 与跟随光标的胶囊绘制原本是两份重复代码 ⇒ 抽 `PaintFreeMarkerCapsule` 共用;
|
||||
`FreeMarkerLabelRects` 增加 `text` 出参,避免绘制侧重复求解一次取值。
|
||||
|
||||
### F. 验证
|
||||
|
||||
- 新增离屏 `.preflight/markcheck` **31/31**:
|
||||
[A] 探测有效/就近选择随鼠标纵向变化;[B] 原地单击恰好新增 1 个固定点;
|
||||
[C] 选区放大模式下原地单击 = 固定且不缩放、拖动 = 缩放且不固定;
|
||||
[D] 面板行数 == 固定点数、组内按时间升序、首项无增量、后续项增量与 Δt 正确、两列右对齐;
|
||||
[E] 行尾 ✕ 只删 1 项、信号名 ✕ 清空该信号全部;[F] 编辑 Δt 后该点移动到「前一点 + 间隔」并在越过后续点时变成最右项;
|
||||
[G] 深度放大时 `snapped == true` 且时刻精确等于某个采样时刻;视界外的固定点 `FreeMarkerLabelRects` 返回 false。
|
||||
- 回归:`editcheck` 20/20、`round3check` 31/31、`round4check` 34/34、`round5check` 5/5、
|
||||
`convcheck` 18/18;`check` **136/137**(唯一失败项是本轮之前就已存在的不稳定项,上一轮已用 `git stash`
|
||||
在基线复现同一数值);真实 MF4 仍 283/8/18/24。
|
||||
- `make release` / `make debug` **零警告**;`TargetCheck.exe` **833,536 字节(814.0 KiB)**。
|
||||
⚠️ **体积超出旧的 800 KiB 红线约 14 KB**(本轮 +24 KB)。已做的瘦身:面板宽度不测文本、
|
||||
胶囊绘制去重。剩余体积是新功能的真实代码量(~800 行新代码 / ~30 B 每行)——
|
||||
若必须回到 800 KiB 以内,需要用户决策(动态 CRT / UPX / 砍其它功能),本轮按"实现功能优先"未动。
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user