using Hawkeye.VisionBuilder.Workflow.Datatypes; using Hawkeye.VisionBuilder.Workflow.Links; using Hawkeye.VisionBuilder.Workflow.Operations.Attributes; using Microsoft.Scripting.Hosting; using Ninject.Infrastructure.Language; using OpenCvSharp; using System.Diagnostics; using System.Reflection; using System.Runtime; using System.Runtime.CompilerServices; using System.Text.RegularExpressions; using System.Xml; using System.Xml.Linq; using RectangleElement = Hawkeye.VisionBuilder.Workflow.Datatypes.Elements.Rectangle.RectangleElement; namespace Hawkeye.VisionBuilder.Workflow { public abstract class BaseOperation { private static readonly ScriptScope _scope; private static readonly ScriptEngine _engine; static BaseOperation() { _engine = IronPython.Hosting.Python.CreateEngine(); _scope = _engine.CreateScope(); } protected BaseOperation() { TypeName = MakeOperationName(this.GetType().Name); Label = MakeOperationName(this.GetType().Name,false); } public static void SetScriptValue(string name, T value) { _scope.SetVariable(name,value); } public static T GetScriptValue(ScriptValue scriptValue) { return _engine.Execute(scriptValue.Script,_scope); } [NotForTool] public bool CanHaveProcessingError { get; set; } = true; [NotForTool] public string Status { get; set; } protected bool CheckImageExists(Context context) { if (context.ActiveImage == null) { Status = "No image available"; Result = false; return false; } return true; } protected bool CheckColorful(Context context) { if (context.ActiveImage.ImageData.Type() != MatType.CV_8UC3) { Status="Image is not colorful"; Result = false; return false; } return true; } protected bool CheckGrayscale(Context context) { if (context.ActiveImage.ImageData.Type() != MatType.CV_8UC1) { Status="Image is not grayscale"; Result = false; return false; } return true; } [NotForTool] public bool NeedsUpdate { get; set; } = true; [NotForTool] public Guid Id { get; protected set; }= Guid.NewGuid(); public static string MakeOperationName(string typeName,bool useSpaces=true) { return Regex.Replace(typeName.Replace("Operation", ""), "(\\B[A-Z]+?(?=[A-Z][^A-Z])|\\B[A-Z]+?(?=[^A-Z]))", (useSpaces?" ":"")+"$1"); } public bool Result { get; set; } = true; public string ResultString { get { return this.ToString(); } } [NotForTool] public string TypeName { get; private set; } [NotForTool] public string Label { get; set; } public TimeSpan ExecutionTime { get; set; } public string ExecutionTimeString { get { return ((int)ExecutionTime.TotalMilliseconds) + " ms"; } } public void Interpret(Context context) { Result = true; Status = ""; Stopwatch sw = Stopwatch.StartNew(); InterpretInternal(context); sw.Stop(); ExecutionTime = sw.Elapsed; _scope.SetVariable(Label,this); } protected abstract void InterpretInternal(Context context); public Dictionary GetParameters() { var props = this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) .Where(x=>!x.HasAttribute(typeof(NotForToolAttribute))); return props.ToDictionary(x => x.Name, x => x.GetValue(this)!); } public virtual void SetParameters(Dictionary parameters) { foreach (KeyValuePair pair in parameters) { this.GetType().GetProperty(pair.Key, BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) ?.SetValue(this,pair.Value); } } public virtual void SaveXML(XmlWriter writer) { writer.WriteAttributeString("Id", Id.ToString()); writer.WriteAttributeString("Label", Label); // Save all public properties that are not marked with NotForTool var properties = GetParameters(); foreach (var property in properties) { if (property.Value != null) { writer.WriteStartElement("Property"); writer.WriteAttributeString("Name", property.Key); writer.WriteAttributeString("Type", property.Value.GetType().FullName); // Handle different types appropriately if (property.Value is string || property.Value.GetType().IsPrimitive || property.Value.GetType().IsEnum) { writer.WriteString(property.Value.ToString()); } else if (property.Value is Guid guid) { writer.WriteString(guid.ToString()); } else { // For complex types, convert to string representation writer.WriteString(property.Value.ToString()); } writer.WriteEndElement(); } } } public virtual void LoadXML(XmlReader reader) { if (reader.GetAttribute("Id") != null) Id = new Guid(reader.GetAttribute("Id")); if (reader.GetAttribute("Label") != null) Label = reader.GetAttribute("Label"); var properties = new Dictionary(); while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element && reader.Name == "Property") { string propertyName = reader.GetAttribute("Name"); string propertyType = reader.GetAttribute("Type"); string propertyValue = reader.ReadElementContentAsString(); if (!string.IsNullOrEmpty(propertyName) && !string.IsNullOrEmpty(propertyValue)) { // Convert string value back to appropriate type object convertedValue = ConvertFromString(propertyValue, propertyType); if (convertedValue != null) { properties[propertyName] = convertedValue; } } } else if (reader.NodeType == XmlNodeType.EndElement && reader.Name == GetOperationElementName()) { break; } } if (properties.Count > 0) { SetParameters(properties); } } private string GetOperationElementName() { return this.GetType().Name; } private object ConvertFromString(string value, string typeName) { try { var type = Type.GetType(typeName); if (type == null) return value; if (type == typeof(string)) return value; else if (type == typeof(int)) return int.Parse(value); else if (type == typeof(double)) return double.Parse(value); else if (type == typeof(float)) return float.Parse(value); else if (type == typeof(bool)) return bool.Parse(value); else if (type == typeof(Guid)) return new Guid(value); else if (type.IsEnum) return Enum.Parse(type, value); else return value; // Fallback to string } catch { return value; // Fallback to string if conversion fails } } public override string ToString() { return Status; } public virtual void Save(BinaryWriter bw) { bw.Write(Id.ToString()); bw.Write(Label); } public virtual void Load(BinaryReader br) { Id = new Guid(br.ReadString()); Label = br.ReadString(); } public void SetError(string eMessage) { Status=eMessage; Result = false; } } }