| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- using System;
- using System.Collections.Generic;
- using TeamAAS.Vision;
- using TeamAAS.FlowEditor.Plugins;
- using Plugins.Halcon.Views;
- namespace Plugins.Halcon
- {
- /// <summary>
- /// 编辑器内嵌预览的挂接点 + 视觉图层发布桥。
- ///
- /// 两条显示通路(互不干扰):
- /// 1) 图层通路(新):<see cref="Show(TeamAAS.FlowEditor.Plugins.BasePluginModel, object, object, string)"/>
- /// 把节点运行结果按「节点 → 图层集」发布到 <see cref="VisionLayerStore"/>,
- /// HalconFlowEditorView 的大显示窗按选中节点/图层筛选渲染 —— 类 VisionMaster 的图层体验;
- /// 2) 经典通路(兼容保留):<see cref="Current"/> 静态窗体直接推图(主页引擎画面、旧调用方不受影响)。
- ///
- /// 内存策略:每轮运行开始(<see cref="BeginRunCycle"/>)换新 RunStamp;同名节点再次发布=整体替换,
- /// 跨批次发布时由 VisionLayerStore 释放上一批次自有对象(GenImage 副本等),图层永不无限叠加。
- /// </summary>
- public static class HalconEditorPreview
- {
- static HalconEditorPreview()
- {
- // 图层库释放自有对象时走 HALCON 安全释放(吞异常)
- VisionLayerStore.Disposer = obj =>
- {
- var h = obj as HalconDotNet.HObject;
- if (h != null) { HalconRuntime.Dispose(h); return; }
- var d = obj as IDisposable;
- if (d != null) { try { d.Dispose(); } catch { } }
- };
- }
- /// <summary>当前 HALCON 流程编辑器内嵌的预览窗体(无编辑器打开时为 null)——经典通路。</summary>
- public static HalconWindow Current { get; set; }
- private static string _runStamp = "0";
- /// <summary>当前运行批次号(每轮容器运行开始时更新)。</summary>
- public static string RunStamp => _runStamp;
- private static long _runSeq = 0;
- /// <summary>
- /// 一轮运行开始:更新 RunStamp 并清掉上一轮遗留图层(防跨轮叠加)。
- /// 由 HalconFlowPlugin.PluginRun 在执行子流程前调用。
- /// </summary>
- public static void BeginRunCycle()
- {
- _runSeq++;
- _runStamp = _runSeq.ToString();
- VisionLayerStore.Instance.ClearAll();
- }
- /// <summary>
- /// 【图层通路】节点运行结果发布:写 VisionLayerStore(驱动编辑器大显示窗/图层筛选),
- /// 同时保持经典通路(Current 窗体直接推图)行为不变。
- /// 后台线程调用安全(内部切 UI 线程);无消费方时零开销。
- /// </summary>
- /// <param name="model">节点模型(取 FlowId/NodeName/NodeName 定位图层归属)</param>
- /// <param name="image">底图(HObject/GenImage),null=只叠加</param>
- /// <param name="overlay">叠加对象(区域/XLD),null=无</param>
- /// <param name="color">叠加颜色(如 "green"),null 用默认</param>
- public static void Show(BasePluginModel model, object image, object overlay = null, string color = null)
- {
- string flowId = model?.FlowId;
- string nodeName = model?.NodeName;
- bool hasContext = !string.IsNullOrEmpty(flowId) && !string.IsNullOrEmpty(nodeName);
- // 1) 图层发布(有节点上下文才发布)
- if (hasContext)
- {
- var args = new LayerPublishArgs
- {
- FlowId = flowId,
- NodeName = nodeName,
- RunStamp = _runStamp,
- };
- if (image != null)
- args.Layers.Add(new LayerItem("图像", LayerKind.Image, image,
- owned: !(image is HalconDotNet.HObject)));
- if (overlay != null)
- args.Layers.Add(new LayerItem("区域", LayerKind.Region, overlay,
- owned: !(overlay is HalconDotNet.HObject), color: color ?? "red"));
- if (args.Layers.Count > 0)
- VisionLayerStore.Instance.Publish(args);
- }
- // 2) 经典通路:编辑器内嵌窗体直接推图(行为不变)
- Show(image, overlay);
- }
- /// <summary>
- /// 【经典通路】把结果推到编辑器内嵌预览窗体(若已打开)。
- /// image 可为 null(只更新叠加区域、保留底图,供只产出区域的节点用)。
- /// 在后台线程调用也安全(内部切 UI 线程);无预览窗体时静默跳过(生产运行零开销)。
- /// </summary>
- public static void Show(object image, object overlay = null)
- {
- var w = Current;
- if (w == null) return;
- try
- {
- System.Windows.Application.Current?.Dispatcher.Invoke(() => w.RefreshImage(image, overlay));
- }
- catch { }
- }
- }
- }
|