平移不再阻塞前台刷新;弱峰增强逐信号参数;浮动面板加入层序
一、平移:前台刷新线程永不阻塞(解决"按住键拖拽时质量下降/断线/周期性卡顿")
- RollWideBuffer 不再整块重画:逐网格整数像素平移 + 只补细条;内容指纹过期或锚点离视界
过远的网格只登记到 m_layerRebuildPending 并仍按现有像素平移(位置照样跟随视界)。
- 新增 RenderPendingLaneRebuilds(budget):Paint 每帧最多重画 1 个网格,其余留到后续帧;
队列非空时 PostMessage(kMessagePlotDerivedReady) 请宿主再送一帧,直到补齐。
- BlitWideBuffer 改为局部贴图:把 BitBlt 夹到图层可用区间,图层没覆盖到的部分留空由底色
填充(旧实现直接跳过整块,导致网格瞬间变空 = "断线")。
- "结算"(整幅全质量精确帧)触发条件收紧为三者同时成立:内容与视界同上一条快路径帧、
m_dragMode == NONE、全部图层就绪。拖拽期间不再结算,消除"宽基底快路径 / 整幅重绘(关AA)"
每两帧振荡造成的质量下降与周期性卡顿。
- 新增 LaneLayerReady(i) / LanesAllReadyForView();原 LayersReadyForView() 更名
LayersStructurallyReady()(只看结构,用于"跨度/布局变化必须整批重建一次")。
- 实测(.preflight/panperf,VERY_BIG_DATA 5 网格深放大,每帧平移 60px):平移 40 帧
中位 6.2ms / p90 7.2ms / max 7.6ms;按住键且视界停在边界 12 帧中位 0.29ms(无整幅重绘)。
二、弱峰增强:改为逐信号参数(对齐均值滤波)
- Lane::WeakPeakItem 由 using = MeanFilterItem 改为独立结构体
{ ref, levelPercent(0-200, 默认 150), iterations(1-10, 默认 1) };删除网格级
Lane::weakPeakLevel / weakPeakIterations。
- 面板改为与均值滤波完全同构:每个被勾选信号一行"名称 + 复选框",第二排两个输入框
(增强等级 % / 迭代次数 N),底部"构建为新信号";删除网格级两个滑块及其常量、
WeakPeakSliderHit、PlotDragMode::PEAK_LEVEL/PEAK_ITERATIONS、m_peakDragLane、
EdgePanelLayout::slider/sliderIterations。
- 新增 PlotEditTarget::PEAK_LEVEL_PERCENT / PEAK_ITERATIONS,EndEdit 中分别夹到 0-200 / 1-10。
- 指纹/快照/预览曲线/光标胶囊/构建新信号全部改为逐信号参数(同一网格内不同信号可用不同强度,
且"预览"与"构建"逐位一致);WeakPeakItem 不再是 MeanFilterItem,purgeRefs 改为泛型 lambda。
三、浮动面板:层序(z-order)与命中修复
- 新增 m_panelOrder(队尾 = 最上层):SyncPanelOrder 保留已有序、新面板追加到最上层;
TopPanelAtPoint 从最上层往下取第一个命中;BringPanelToFront 在点击面板时把它置顶。
- 绘制改为按 m_panelOrder 自下而上;PanelGlobalKey 混合层序(层序变化即整层重画);
QueryCursor / OnMouseMove 的"是否在面板上"也走 TopPanelAtPoint。
- 修复"上层面板的 ✕ / 标题栏被下层参数输入框抢走,导致上层面板关不掉/拖不动"。
四、测试
- uitest 新增 [AG]:层预算(每帧只重画 1 个网格、剩余排队、最终补齐并全部就绪)、
局部贴图(只覆盖视界一半时左侧被贴、右侧保持哨兵色)、面板层序(上层 ✕ 命中上层、
下层不受影响、点击下层置顶、TopPanelAtPoint 随之改变、新开面板在最上层)。
- [X] 改为逐信号参数(含两个输入框就地编辑:写入该信号自己的条目、越界夹取),
移除已不存在的滑块断言。
- 新增离屏探针 .preflight/panperf(平移帧耗时 + 按住键静止帧耗时)。
- make all 零警告;uitest 388/388 通过;panperf PASS;layercheck 保持像素一致。
This commit is contained in:
1 parent
da83dc2987
commit
1ddbc37b78
5 files changed
+706
-544
No files matched your search
+15
-23
@@ -374,13 +374,17 @@ namespace jdi
|
||||
using EdgeCenterItem = MeanFilterItem;
|
||||
|
||||
/**
|
||||
* @brief 「弱峰增强」中某个信号自己的条目。
|
||||
* @brief 「弱峰增强」中某个信号自己的参数条目。
|
||||
*
|
||||
* 目前只用到 `ref`(增强等级属于整个网格,统一保存在 `weakPeakLevel` 中);
|
||||
* 复用 `MeanFilterItem` 结构是为了与均值滤波/中心轴共享
|
||||
* 「条目查找 + 信号插入/删除时的引用重映射」等既有实现。
|
||||
* 与「均值滤波」完全一致:**每个被勾选的信号各自持有参数**
|
||||
*(增强等级 0–200% + 迭代次数 N),因此同一网格内不同信号可以使用不同强度。
|
||||
*/
|
||||
using WeakPeakItem = MeanFilterItem;
|
||||
struct WeakPeakItem
|
||||
{
|
||||
SignalRef ref; /**< 目标信号。 */
|
||||
int levelPercent = 150; /**< 增强等级(0–200;100% = 到达较温和的一侧,200% = 完全拉平)。 */
|
||||
int iterations = 1; /**< 迭代次数 N(1–10)。 */
|
||||
};
|
||||
|
||||
std::wstring name; /**< 网格名称。 */
|
||||
std::vector<SignalRef> signals; /**< 该网格包含的信号(按加入顺序)。 */
|
||||
@@ -505,35 +509,23 @@ namespace jdi
|
||||
*
|
||||
* 开启后为本网格内**被勾选**的信号额外绘制一条「弱峰增强」曲线:
|
||||
* 识别纹波的波峰/波谷,把“比左右同类极值更弱”的波峰上拉、波谷下拉,
|
||||
* 并按「弱峰增强等级」在左右两个同类极值之间取目标值,使其恢复与周边一致的振幅。
|
||||
* 并按各信号自己的「增强等级」在左右两个同类极值之间取目标值,使其恢复与周边振幅。
|
||||
* 这条曲线只是叠加显示,不会作为信号加入左侧列表。
|
||||
*/
|
||||
bool weakPeak = false;
|
||||
|
||||
/**
|
||||
* @brief 弱峰增强等级(0–2,面板上显示为 0%–200%)。
|
||||
* @brief 参与弱峰增强预览的信号及其**各自的参数**(只包含被勾选的信号)。
|
||||
*
|
||||
* 0 = 目标就是当前值(完全不动);1 = 拉到较温和的一侧(波峰取较低的左/右波峰,
|
||||
* 波谷取较高的左/右波谷);2 = 拉到另一侧(完全拉平)。默认 1.5,等价于旧版的 50%。
|
||||
* 参数(等级 0–200% + 迭代次数 N)按信号保存,与「均值滤波」的实现方式一致:
|
||||
* 同一网格内不同信号可以使用不同的增强强度,也可以分别「构建为新信号」。
|
||||
*/
|
||||
double weakPeakLevel = 1.5;
|
||||
|
||||
/**
|
||||
* @brief 弱峰增强的迭代次数 N(1–10)。
|
||||
*
|
||||
* 与「均值滤波」的迭代次数 N 一样表示“把同一处理重复应用 N 次”(每一阶以上一阶为输入):
|
||||
* 一阶时改定量就已严格等于「等级」对应的目标值;多阶会把相邻弱峰互相抬高
|
||||
* 彼此的基准,从而把较宽的弱峰区逐步恢复。
|
||||
*/
|
||||
int weakPeakIterations = 1;
|
||||
|
||||
/** 参与弱峰增强预览的信号条目(只包含被勾选的信号)。 */
|
||||
std::vector<WeakPeakItem> weakPeakItems;
|
||||
|
||||
/** 取某个信号的弱峰增强条目(未勾选时返回空指针)。 */
|
||||
/** 取某个信号的弱峰增强参数(未勾选时返回空指针)。 */
|
||||
const WeakPeakItem* FindWeakPeakItem(const SignalRef& ref) const;
|
||||
|
||||
/** 取得或创建某信号的弱峰增强条目(用于勾选)。 */
|
||||
/** 取得或创建某信号的弱峰增强参数(用于勾选)。 */
|
||||
WeakPeakItem& EnsureWeakPeakItem(const SignalRef& ref);
|
||||
|
||||
/** 取消某信号的弱峰增强勾选。 */
|
||||
|
||||
@@ -136,8 +136,6 @@ namespace jdi
|
||||
double meanFilterPanelY = -1.0;
|
||||
bool weakPeak = false;
|
||||
std::vector<Lane::WeakPeakItem> weakPeakItems;
|
||||
double weakPeakLevel = 1.5;
|
||||
int weakPeakIterations = 1;
|
||||
bool weakPeakPanelOpen = true;
|
||||
double weakPeakPanelX = -1.0;
|
||||
double weakPeakPanelY = -1.0;
|
||||
@@ -168,8 +166,6 @@ namespace jdi
|
||||
carry.meanFilterPanelY = lane.meanFilterPanelY;
|
||||
carry.weakPeak = lane.weakPeak;
|
||||
carry.weakPeakItems = lane.weakPeakItems;
|
||||
carry.weakPeakLevel = lane.weakPeakLevel;
|
||||
carry.weakPeakIterations = lane.weakPeakIterations;
|
||||
carry.weakPeakPanelOpen = lane.weakPeakPanelOpen;
|
||||
carry.weakPeakPanelX = lane.weakPeakPanelX;
|
||||
carry.weakPeakPanelY = lane.weakPeakPanelY;
|
||||
@@ -211,8 +207,6 @@ namespace jdi
|
||||
lane.meanFilterPanelY = carry.meanFilterPanelY;
|
||||
lane.weakPeak = carry.weakPeak;
|
||||
lane.weakPeakItems = carry.weakPeakItems;
|
||||
lane.weakPeakLevel = carry.weakPeakLevel;
|
||||
lane.weakPeakIterations = carry.weakPeakIterations;
|
||||
lane.weakPeakPanelOpen = carry.weakPeakPanelOpen;
|
||||
lane.weakPeakPanelX = carry.weakPeakPanelX;
|
||||
lane.weakPeakPanelY = carry.weakPeakPanelY;
|
||||
@@ -1618,17 +1612,20 @@ namespace jdi
|
||||
}
|
||||
}
|
||||
|
||||
// 均值滤波 / 中心轴边沿计数的条目同样持有信号引用,必须一起删除/前移。
|
||||
const auto purgeRefs = [fileIndex, signalIndex](std::vector<Lane::MeanFilterItem>& items)
|
||||
// 均值滤波 / 中心轴边沿计数 / 弱峰增强的条目同样持有信号引用,必须一起删除/前移。
|
||||
// 三类条目都是「带 `ref` 的结构体」,因此用泛型 lambda 统一处理
|
||||
//(弱峰增强的参数与均值滤波不同,不能再共用同一个具体类型)。
|
||||
const auto purgeRefs = [fileIndex, signalIndex](auto& items)
|
||||
{
|
||||
using ItemType = typename std::decay_t<decltype(items)>::value_type;
|
||||
items.erase(std::remove_if(items.begin(), items.end(),
|
||||
[fileIndex, signalIndex](const Lane::MeanFilterItem& item)
|
||||
[fileIndex, signalIndex](const ItemType& item)
|
||||
{
|
||||
return item.ref.fileIndex == fileIndex &&
|
||||
item.ref.signalIndex == signalIndex;
|
||||
}),
|
||||
items.end());
|
||||
for (Lane::MeanFilterItem& item : items)
|
||||
for (ItemType& item : items)
|
||||
{
|
||||
if (item.ref.fileIndex == fileIndex && item.ref.signalIndex > signalIndex)
|
||||
{
|
||||
@@ -1931,8 +1928,6 @@ namespace jdi
|
||||
lane.edgeCenterPanelX = source.edgeCenterPanelX;
|
||||
lane.edgeCenterPanelY = source.edgeCenterPanelY;
|
||||
lane.weakPeak = source.weakPeak;
|
||||
lane.weakPeakLevel = source.weakPeakLevel;
|
||||
lane.weakPeakIterations = source.weakPeakIterations;
|
||||
lane.weakPeakPanelOpen = source.weakPeakPanelOpen;
|
||||
lane.weakPeakPanelX = source.weakPeakPanelX;
|
||||
lane.weakPeakPanelY = source.weakPeakPanelY;
|
||||
|
||||
Reference in new issue
Block a user