修复自适应/首帧卡顿回归 + 派生信号烘值 + 图例交互与托底重做
一、性能(详见 agent_mem §9.19) - AutoRangeLaneToView:把 DataSet::Style(ref) 从逐采样循环里提出来(远端新增的「调整」 功能让它每个采样点解析两次,实测 147ms 劣化到 1200ms),并在「视界覆盖整条信号且 无任何数值变换」时直接取信号已缓存的 min/max(O(1))。工具栏「Y 轴自适应」在全视图下 1200ms → 0.02ms,结果与逐点扫描逐位一致;有变换时仍逐点套用与绘制相同的变换。 - 新增 WarmLaneLayersStep():加载后宽基底图层从未分配,用户第一次平移/选区放大时 Paint 会在那一帧同步重建全部网格图层(首帧 64.3ms)。现在改为在「命中静态场景缓存」 (视界未变、非拖拽)时用既有预算机制每帧至多补 1 个网格,把整批重建摊到静止帧; 选区放大首帧 64.3ms → 13.0ms。 二、派生信号 - 「构建为新信号」把源信号的「调整」变换(系数 → 绝对值 → 垂直镜像 → Y 偏移,以及 水平镜像=数据反序)烘进派生采样值,新信号样式一律保持默认(不再是"继承的指纹"); 仅时间轴偏移 offsetTime 因派生信号与源信号共用同一个文件时间轴仍需继承。 三、交互 - 网格 GX 拖拽让位判据改为「鼠标指针」:指针越过相邻网格的中心水平线即让位并出现吸附 提示(原先按"被拖网格的中心",要求把整个网格拖过去一格才吸附)。 - GX 徽标悬停高亮:徽标本体在装饰缓存里被冻结,高亮改为贴图之后的叠加层,并新增 m_hoverBadge 状态驱动重绘/取消;QueryCursor 在徽标上返回 IDC_HAND —— 与左侧信号列表 里同一个 GX 徽标一致。 - 修复「中键平移过视界之后图例悬停/点击/双击改名全部失效」:整幅重绘路径会清空 m_legendHits,而装饰缓存命中时 PaintLaneLegend 提前 return 导致永不重建。现在把该函数 拆成「几何 → 命中/装饰矩形 → 绘制」三段,任何路径都先重建命中矩形。 四、绘制 - 每个信号图例单独加圆角托底(配色/圆角风格与 GX 徽标一致);装饰矩形改为逐块 (徽标一块 + 每个条目一块 + 每个 Y 轴胶囊一块),不再覆盖整条图例带;每块托底先用 不透明底色铺满「外接整数像素再外扩 1px」的矩形再画圆角 —— 消除「GX/图例周边旧波形 像素残留」(逐像素验证:装饰矩形内 0 差异)。 - 图例悬停高亮改为不透明托底并在其上重绘色块与文字(否则不透明托底会把图例内容盖住), 同时保留对应信号的曲线光晕;Y 轴刻度胶囊补不透明外接底色,消除同类残留。 验证:离屏 Application harness(窗口 SW_HIDE + 直接注入鼠标消息 + 从后备缓冲区截图, 不占用鼠标/键盘/屏幕)40/40 通过;zoomcheck 新增 mode 20-26 量化;make release 零警告。
This commit is contained in:
1 parent
940b8e67e6
commit
7c32eca004
4 files changed
+590
-183
No files matched your search
@@ -1528,23 +1528,26 @@ namespace jdi
|
||||
// 0. 先把源信号的「调整」变换快照下来(下面 `InsertDerivedSignal` 会移动信号存储,
|
||||
// 之后再取 `source` 会悬垂)。
|
||||
//
|
||||
// ⚠️ **新信号必须继承这套变换**,否则会出现“预览是调整后的波形、构建出来的却按原始状态绘制”
|
||||
//(用户报告的不一致):网格里的预览曲线绘制的是 `变换(滤波结果)`,而构建出的信号只存了
|
||||
// `滤波结果`;把变换一并继承后,两者绘制完全相同。
|
||||
// 另外**时间轴偏移只能靠继承**:派生信号与源信号共用同一个文件时间轴,无法把时间平移烘进数据。
|
||||
SignalStyle inheritedTransform;
|
||||
// ⚠️ **变换要"烘进数据",而不是让新信号继承这套指纹**(用户明确要求):
|
||||
// 网格里的预览曲线画的是 `变换(滤波结果)`。若新信号只存 `滤波结果` 再**继承变换**,
|
||||
// 它的「调整」面板里就会莫名其妙带着一整套系数 / 镜像 / 偏移 —— 用户看到的是
|
||||
// "新信号只是继承了原信号的指纹,数据本身没变"。现在改为:
|
||||
// * 数值域变换(系数 → 绝对值 → 垂直镜像 → Y 偏移)**与**水平镜像(数据反序)
|
||||
// 全部作用在派生采样值上;
|
||||
// * 于是新信号**用默认外观**绘制出来就与预览曲线逐位一致。
|
||||
// * ⚠️ **时间轴偏移是唯一的例外**:它改变的是"绘制在哪个时刻",而派生信号与源信号
|
||||
// 共用同一个文件时间轴,无法把时间平移烘进采样数据,因此仍由新信号的样式携带
|
||||
// (否则新信号会相对预览整体横向错位)。
|
||||
SignalStyle sourceTransform;
|
||||
bool hasSourceStyle = false;
|
||||
{
|
||||
SignalRef sourceRef;
|
||||
sourceRef.fileIndex = request.fileIndex;
|
||||
sourceRef.signalIndex = request.signalIndex;
|
||||
if (const SignalStyle* sourceStyle = m_dataSet.Style(sourceRef))
|
||||
{
|
||||
inheritedTransform.gain = sourceStyle->gain;
|
||||
inheritedTransform.absolute = sourceStyle->absolute;
|
||||
inheritedTransform.mirrorVertical = sourceStyle->mirrorVertical;
|
||||
inheritedTransform.mirrorHorizontal = sourceStyle->mirrorHorizontal;
|
||||
inheritedTransform.offsetY = sourceStyle->offsetY;
|
||||
inheritedTransform.offsetTime = sourceStyle->offsetTime;
|
||||
sourceTransform = *sourceStyle;
|
||||
hasSourceStyle = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1567,11 +1570,33 @@ namespace jdi
|
||||
std::to_wstring(request.iterations) + L"次迭代)";
|
||||
}
|
||||
|
||||
// 2. 组装新信号(外观先沿用默认值,插入后再继承源信号的「调整」变换)。
|
||||
// 2. 组装新信号(外观一律用默认值:变换已经烘进采样数据,不再是"继承的指纹")。
|
||||
derived.rawHeader = derived.name;
|
||||
derived.unit = source.unit;
|
||||
derived.values.assign(derived_values.begin(), derived_values.end());
|
||||
|
||||
// 2b. 把源信号的「调整」变换**烘进派生采样值**:
|
||||
// * 数值域(系数 → 绝对值 → 垂直镜像 → Y 偏移)逐点套用 `ApplyDrawTransform`;
|
||||
// * 水平镜像 = 数据反序,等价于把采样数组整体反转。
|
||||
// ⚠️ `ApplyDrawTransform` 是逐点函数,因此"先变换再反转"与"先反转再变换"等价。
|
||||
if (hasSourceStyle)
|
||||
{
|
||||
const bool valueTransform =
|
||||
(sourceTransform.gain != 1.0f || sourceTransform.absolute ||
|
||||
sourceTransform.mirrorVertical || sourceTransform.offsetY != 0.0f);
|
||||
if (valueTransform)
|
||||
{
|
||||
for (double& value : derived.values)
|
||||
{
|
||||
value = ApplyDrawTransform(sourceTransform, value);
|
||||
}
|
||||
}
|
||||
if (sourceTransform.mirrorHorizontal)
|
||||
{
|
||||
std::reverse(derived.values.begin(), derived.values.end());
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 插入到原信号的下方(数据层 + 各标签页引用重映射)。
|
||||
int newIndex = -1;
|
||||
// 插入派生信号会移动该文件的信号存储:先暂停后台计算,避免其读取已移动的数据。
|
||||
@@ -1586,16 +1611,15 @@ namespace jdi
|
||||
tab.RemapAfterSignalInsert(request.fileIndex, newIndex);
|
||||
}
|
||||
|
||||
// 3b. 新信号继承源信号的「调整」变换(系数 / 绝对值 / 镜像 / 偏移),
|
||||
// 使其绘制结果与网格里的预览曲线**完全一致**。
|
||||
if (SignalStyle* derivedStyle = m_dataSet.Style(SignalRef{request.fileIndex, newIndex}))
|
||||
// 3b. 仅把**时间轴偏移**带到新信号上(唯一无法烘进数据的一项,见上面第 0 步说明)。
|
||||
// 其余「调整」项(系数 / 绝对值 / 镜像 / Y 偏移)保持在默认值 —— 它们已经
|
||||
// 烘进了采样数据,因此新信号不经过任何"调整"就与预览曲线完全一致。
|
||||
if (hasSourceStyle && sourceTransform.offsetTime != 0.0)
|
||||
{
|
||||
derivedStyle->gain = inheritedTransform.gain;
|
||||
derivedStyle->absolute = inheritedTransform.absolute;
|
||||
derivedStyle->mirrorVertical = inheritedTransform.mirrorVertical;
|
||||
derivedStyle->mirrorHorizontal = inheritedTransform.mirrorHorizontal;
|
||||
derivedStyle->offsetY = inheritedTransform.offsetY;
|
||||
derivedStyle->offsetTime = inheritedTransform.offsetTime;
|
||||
if (SignalStyle* derivedStyle = m_dataSet.Style(SignalRef{request.fileIndex, newIndex}))
|
||||
{
|
||||
derivedStyle->offsetTime = sourceTransform.offsetTime;
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 在当前标签页中勾选新信号,并把它所在的网格移到原信号网格的下方。
|
||||
|
||||
Reference in new issue
Block a user