using HalconDotNet;
using LB_VisionControls;
using LB_VisionControls.Forms;
using LB_VisionProcesses;
using LB_VisionProcesses.Cameras;
using LB_VisionProcesses.Communicators;
using LB_VisionProcesses.Processes;
using OpenCvSharp;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Collections.Concurrent;
using LB_SmartVision.Tool;
using LB_SmartVision.ProcessRun;
namespace LB_SmartVision.Forms.Pages.ProcessPage
{
public partial class ProcessPage : UserControl
{
///
/// 运行步骤(object为IProces或者object为ICamera)
///
public ProcessRunBll ProcessRunBll { get; set; }
public Action LogInfo;
private UserHSmartWindowControl UserHSmartWindowControl = new UserHSmartWindowControl();
public ProcessPage()
{
InitializeComponent();
}
public ProcessPage(string Name, ProcessRunBll ProcessRunBll)
{
InitializeComponent();
this.Text = "ProcessPage";
this.Name = Name;
this.ProcessRunBll = ProcessRunBll;
Name = ProcessRunBll.Name;
Text = ProcessRunBll.Name;
this.splitContainer1.Panel1.Controls.Add(UserHSmartWindowControl);
UserHSmartWindowControl.Dock = DockStyle.Fill;
this.panel1.Controls.Add(ProcessRunBll.nodesControl);
ProcessRunBll.nodesControl.Location = new System.Drawing.Point(0, 0);
ProcessRunBll.nodesControl.Size = new System.Drawing.Size(5000, 5000);
RemoveAllHandler();
ProcessRunBll.nodesControl.AddNodeAction += AddProcess;
ProcessRunBll.nodesControl.CopyNodeAction += CopyProcess;
ProcessRunBll.nodesControl.RenameNodeAction += RenameProcess;
ProcessRunBll.nodesControl.InAndOutNodeAction += InAndOutProcess;
ProcessRunBll.nodesControl.DeleteNodeAction += DeleteProcess;
ProcessRunBll.nodesControl.EditNodeAction += EditProcess;
ProcessRunBll.nodesControl.AddBranchAction += AddBranch;
ProcessRunBll.nodesControl.DeleteBranchAction += DeleteBranch;
}
private void ProcessPage_Paint(object sender, PaintEventArgs e)
{
if (ProcessRunBll.Result)
uiButtonRun.ButtonType = ReaLTaiizor.Util.HopeButtonType.Success;
else
uiButtonRun.ButtonType = ReaLTaiizor.Util.HopeButtonType.Danger;
if (ProcessRunBll.GetImage(out _, out HObject RecordImage))
UserHSmartWindowControl.ShowHoImage(RecordImage);
}
public void RemoveAllHandler()
{
ProcessRunBll.nodesControl.AddNodeAction -= AddProcess;
ProcessRunBll.nodesControl.RenameNodeAction -= RenameProcess;
ProcessRunBll.nodesControl.InAndOutNodeAction -= InAndOutProcess;
ProcessRunBll.nodesControl.DeleteNodeAction -= DeleteProcess;
ProcessRunBll.nodesControl.EditNodeAction -= EditProcess;
ProcessRunBll.nodesControl.AddBranchAction -= AddBranch;
ProcessRunBll.nodesControl.DeleteBranchAction -= DeleteBranch;
}
private void uiButtonRun_Click(object sender, EventArgs e)
{
this.BeginInvoke(new Action(() =>
{
UserHSmartWindowControl.ClearObj();
LogInfo?.Invoke(string.Format("流程[{0}]开始运行", this.ProcessRunBll.Name), LogInfoType.INFO);
bool result = this.ProcessRunBll.Run();
string msg = ProcessRunBll.Msg;
LogInfo?.Invoke(string.Format("流程[{0}]运行完成,结果:{1}", this.ProcessRunBll.Name, msg)
, result ? LogInfoType.PASS : LogInfoType.ERROR);
if (ProcessRunBll.GetImage(out _, out HObject RecordImage))
UserHSmartWindowControl.ShowHoImage(RecordImage);
if (result)
uiButtonRun.ButtonType = ReaLTaiizor.Util.HopeButtonType.Success;
else
uiButtonRun.ButtonType = ReaLTaiizor.Util.HopeButtonType.Danger;
}));
}
public void AddProcess(string ProcessName, string Descript)
{
string ClassName = ProcessRunBll.Node2ToolClassName(Descript);
string ProcessPath = GlobalVar.allProcessPath + ProcessRunBll.Name + "\\" + ProcessName + ".json";
if (ProcessRunBll.AddStep(ProcessRunBll.Name, ProcessName, ClassName, ProcessPath))
{
ProcessRunBll.SaveInputs();
ProcessRunBll.SaveOutputs();
ProcessRunBll.CompileMappings();
}
else
LogInfo?.Invoke(string.Format("流程[{0}]添加步骤\"{1}\"失败", this.Text, ProcessName), LogInfoType.ERROR);
}
public void CopyProcess(string oriProcessName, string newProcessName, string Descript)
{
var dicSteps = ProcessRunBll.GetSteps();
if (!dicSteps.ContainsKey(oriProcessName))
return;
string ClassName = ProcessRunBll.Node2ToolClassName(Descript);
string oriProcessPath = GlobalVar.allProcessPath + ProcessRunBll.Name + "\\" + oriProcessName + ".json";
string newProcessPath = GlobalVar.allProcessPath + ProcessRunBll.Name + "\\" + newProcessName + ".json";
// 把新的步骤文件复制一份
if (File.Exists(oriProcessPath))
File.Copy(oriProcessPath, newProcessPath, true);
else
{
string oriProcessDirectory = GlobalVar.allProcessPath + ProcessRunBll.Name + "\\" + oriProcessName;
string newProcessDirectory = GlobalVar.allProcessPath + ProcessRunBll.Name + "\\" + newProcessName;
if (Directory.Exists(oriProcessDirectory))
{
if (Directory.Exists(newProcessDirectory))
Directory.Delete(newProcessDirectory, true);
LB_SmartVision.Tool.Tool.CopyDirectory(oriProcessDirectory, newProcessDirectory);
string[] Files = Directory.GetFiles(newProcessDirectory);
foreach (var file in Files)
{
string fileName = Path.GetFileName(file);
if (fileName.StartsWith(oriProcessName))
{
string newFileName = fileName.Replace(oriProcessName, newProcessName);
string newFilePath = Path.Combine(newProcessDirectory, newFileName);
File.Move(file, newFilePath);
}
}
}
}
if (ProcessRunBll.AddStep(ProcessRunBll.Name, newProcessName, ClassName, newProcessPath))
{
ProcessRunBll.SaveInputs();
ProcessRunBll.SaveOutputs();
ProcessRunBll.CompileMappings();
}
else
LogInfo?.Invoke(string.Format("流程[{0}]复制步骤\"{1}\"为\"{2}\"失败", this.Text, oriProcessName, newProcessName), LogInfoType.ERROR);
}
private void InAndOutProcess(string ProcessName)
{
var dicSteps = ProcessRunBll.GetSteps();
if (!dicSteps.ContainsKey(ProcessName))
return;
ProcessInputsSelectForm inputsSelectForm = new ProcessInputsSelectForm(ProcessName, ProcessRunBll);
inputsSelectForm.Text = ProcessName;
inputsSelectForm.ShowDialog();
ProcessRunBll.SaveInputs();
ProcessRunBll.SaveOutputs();
ProcessRunBll.CompileMappings();
//string ProcessPath = GlobalVar.allProcessPath + ProcessRunBll.Name + "\\" + ProcessName + ".json";
//((IProcess)dicSteps[ProcessName]).Load(ProcessPath);
}
public void DeleteProcess(string ProcessName)
{
try
{
var dicSteps = ProcessRunBll.GetSteps();
if (!dicSteps.ContainsKey(ProcessName))
return;
string ProcessPath = GlobalVar.allProcessPath + ProcessRunBll.Name + "\\" + ProcessName + ".json";
if (string.IsNullOrEmpty(ProcessName) || string.IsNullOrEmpty(ProcessPath))
return;
// 获取所有文件(不管后缀名是什么)并进行遍历
string directoryPath = Path.GetDirectoryName(ProcessPath);
string[] files = Directory.GetFiles(directoryPath, ProcessName + ".*"); // 匹配所有名称为aa的文件,后缀不限
foreach (var file in files)
{
try
{
if (File.Exists(file))
File.Delete(file);
}
catch (Exception ex)
{
Debug.WriteLine($"删除文件 {file} 时出错: {ex.Message}");
LogInfo?.Invoke(string.Format("流程[{0}]移除步骤\"{1}\"失败,原因是{2}", this.Text, ProcessName, ex.Message), LogInfoType.ERROR);
return;
}
}
if (Directory.Exists(directoryPath + "\\" + ProcessName))
Directory.Delete(directoryPath + "\\" + ProcessName, true);
if (!ProcessRunBll.Remove(ProcessName))
LogInfo?.Invoke(string.Format("流程[{0}]移除步骤\"{1}\"失败", this.Text, ProcessName), LogInfoType.ERROR);
}
catch (Exception ex) { Debug.WriteLine(ex.Message); }
}
private void RenameProcess(string ProcessName, string newProcessName)
{
ConcurrentDictionary dicSteps = ProcessRunBll.GetSteps();
if (!dicSteps.ContainsKey(ProcessName))
return;
ProcessRenameEvent(ProcessName, newProcessName);
}
private void ProcessRenameEvent(string oriName, string newName)
{
ConcurrentDictionary dicSteps = ProcessRunBll.GetSteps();
//更新后的步骤名仍然需要是唯一
if (dicSteps.ContainsKey(newName))
{
MessageBox.Show(string.Format("重命名失败,步骤名称[{0}]已存在!", newName), "异常");
return;
}
if (dicSteps.ContainsKey(oriName))
{
string oriPath = GlobalVar.allProcessPath + this.Text + "\\" + oriName + ".json";
string newPath = GlobalVar.allProcessPath + this.Text + "\\" + newName + ".json";
string directoryPath = Path.GetDirectoryName(oriPath);
string[] files = new string[] { };
// 重命名当前文件夹
files = Directory.GetFiles(directoryPath, oriName + ".*"); // 匹配所有名称为oriName的文件,后缀不限
foreach (var file in files)
{
try
{
// 获取文件的扩展名
string extension = Path.GetExtension(file);
// 构造新文件名
string newFileName = Path.Combine(directoryPath, newName + extension);
if (!File.Exists(newFileName))
{
// 重命名文件
File.Move(file, newFileName);
Debug.WriteLine($"文件已重命名: {file} -> {newFileName}");
}
else
{
LogInfo?.Invoke(string.Format("流程[{0}]重命名步骤\"{1}\"为\"{2}\"失败,原因是{3}", this.Text, oriName, newName, "命名重复"), LogInfoType.ERROR);
return;
}
}
catch (Exception ex)
{
Debug.WriteLine($"重命名文件 {file} 时出错: {ex.Message}");
LogInfo?.Invoke(string.Format("流程[{0}]重命名步骤\"{1}\"为\"{2}\"失败,原因是{3}", this.Text, oriName, newName, ex.Message), LogInfoType.ERROR);
return;
}
}
// 重命名当前文件夹
if (Directory.Exists(directoryPath + "\\" + oriName))
{
Directory.Move(directoryPath + "\\" + oriName, directoryPath + "\\" + newName);
// 重命名子文件夹
string newParentDirectory = Path.GetDirectoryName(GlobalVar.allProcessPath + this.Text + "\\" + newName + "\\" + oriName + ".json");
files = Directory.GetFiles(newParentDirectory, oriName + ".*"); // 匹配子文件夹内所有名称为oriName的文件,后缀不限(一般只有一个)
foreach (var file in files)
{
try
{
// 获取文件的扩展名
string extension = Path.GetExtension(file);
// 构造新文件名
string newFileName = Path.Combine(newParentDirectory, newName + extension);
if (!File.Exists(newFileName))
{
if (!Directory.Exists(newParentDirectory))
Directory.CreateDirectory(newParentDirectory);
// 重命名文件
File.Move(file, newFileName);
Debug.WriteLine($"文件已重命名: {file} -> {newFileName}");
}
else
{
LogInfo?.Invoke(string.Format("流程[{0}]重命名步骤\"{1}\"为\"{2}\"失败,原因是{3}", this.Text, oriName, newName, "命名重复"), LogInfoType.ERROR);
return;
}
}
catch (Exception ex)
{
Debug.WriteLine($"重命名文件 {file} 时出错: {ex.Message}");
LogInfo?.Invoke(string.Format("流程[{0}]重命名步骤\"{1}\"为\"{2}\"失败,原因是{3}", this.Text, oriName, newName, ex.Message), LogInfoType.ERROR);
return;
}
}
}
ProcessRunBll.Rename(oriName, newName);
LogInfo?.Invoke(string.Format("流程[{0}]重命名步骤\"{1}\"为\"{2}\"成功", this.Text, oriName, newName), LogInfoType.PASS);
//if (dicSteps[newName] is VisionProTool && Tool.ContainsChinese(newName))
// MessageBox.Show($"VisionPro工具不支持命名为中文:{newName}", "异常");
}
}
private void EditProcess(string ProcessName)
{
try
{
ConcurrentDictionary dicSteps = ProcessRunBll.GetSteps();
if (!dicSteps.ContainsKey(ProcessName))
return;
string ClassName = dicSteps[ProcessName].GetType().ToString();
string ProcessPath = GlobalVar.allProcessPath + ProcessRunBll.Name + "\\" + ProcessName + ".json";
if (string.IsNullOrEmpty(ProcessName) || string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(ProcessPath))
return;
//利用反射创建实例
Type type = IProcess.GetExecutingAssembly().GetType(ClassName);
if (type == null)
{
LogInfo?.Invoke(string.Format("流程[{0}]步骤\"{1}\"打开失败了,类[{2}]不存在", this.Text, ProcessName, ClassName), LogInfoType.ERROR);
return;
}
((IProcess)dicSteps[ProcessName]).Save(Path.GetDirectoryName(ProcessPath));
IProcess process = ((IProcess)dicSteps[ProcessName]).Clone() as IProcess;
Object InputImage = new Object();
if (process.InputImage != null)
{
if (process.InputImage is HObject ho_image && ho_image.IsInitialized())
InputImage = ho_image.CopyObj(1, -1);
else if (process.InputImage is Mat mat && !mat.Empty())
InputImage = mat.Clone();
else if (process.InputImage is Bitmap bitmap)
InputImage = bitmap.Clone();
}
if (ClassName.Contains("CameraConfig") && process is CameraConfig)
{
LB_VisionProcesses.Cameras.CameraForm cameraForm
= new LB_VisionProcesses.Cameras.CameraForm(GlobalVar.dicCameras.Items, (CameraConfig)process, ProcessPath);
cameraForm.ShowDialog();
if (!(process.Load(ProcessPath)))
LogInfo?.Invoke(string.Format("流程[{0}]步骤\"{1}\"加载失败了", this.Text, ProcessName), LogInfoType.ERROR);
process.strProcessName = ProcessName;
}
else if (ClassName.Contains("Communicators") && process is CommunicatorConfig)
{
LB_VisionProcesses.Communicators.CommunicatorForm communicatorForm
= new LB_VisionProcesses.Communicators.CommunicatorForm(GlobalVar.dicCommunicators.Items, (CommunicatorConfig)process, ProcessPath);
communicatorForm.ShowDialog();
if (!(process.Load(ProcessPath)))
LogInfo?.Invoke(string.Format("流程[{0}]步骤\"{1}\"加载失败了", this.Text, ProcessName), LogInfoType.ERROR);
process.strProcessName = ProcessName;
}
else
{
ProcessEditForm processEditForm = new ProcessEditForm(process, ProcessPath);
processEditForm.ShowDialog();
//重新加载更新后的步骤
if (processEditForm.hasChanged)
LogInfo?.Invoke(string.Format("流程[{0}]步骤\"{1}\"更新了", this.Text, ProcessName), LogInfoType.WARN);
if (!(process.Load(ProcessPath)))
LogInfo?.Invoke(string.Format("流程[{0}]步骤\"{1}\"加载失败了", this.Text, ProcessName), LogInfoType.ERROR);
process.strProcessName = ProcessName;
}
if (InputImage != null)
{
if (InputImage is HObject ho_image && ho_image.IsInitialized())
process.InputImage = ho_image.CopyObj(1, -1);
else if (InputImage is Mat mat && !mat.Empty())
process.InputImage = mat.Clone();
else if (InputImage is Bitmap bitmap)
process.InputImage = bitmap.Clone();
}
dicSteps[ProcessName] = process;
ProcessRunBll.UpdataInputsAndOutputs(ProcessName, process);
}
catch (Exception ex) { Debug.WriteLine(ex.Message); }
}
private void AddBranch(string ProcessName)
{
var dicSteps = ProcessRunBll.GetSteps();
if (!dicSteps.ContainsKey(ProcessName))
return;
// 多分支的本质为脚本工具,根据branchIndex来走对应的分支
if (dicSteps[ProcessName] is ScriptTool ScriptTool)
{
ScriptTool.Params.Outputs.Add($"Branch{ScriptTool.Params.Outputs.Count}", false);
Debug.WriteLine($"脚本工具[{ProcessName}]增加了Branch{ScriptTool.Params.Outputs.Count - 1}");
}
}
private void DeleteBranch(string ProcessName)
{
var dicSteps = ProcessRunBll.GetSteps();
if (!dicSteps.ContainsKey(ProcessName))
return;
// 多分支的本质为脚本工具,根据branchIndex来走对应的分支
if (dicSteps[ProcessName] is ScriptTool ScriptTool
&& ScriptTool.Params.Outputs.Remove($"Branch{ScriptTool.Params.Outputs.Count}"))
{
Debug.WriteLine($"脚本工具[{ProcessName}]移除了Branch{ScriptTool.Params.Outputs.Count + 1}");
}
}
}
}