diff --git a/FemDesign.Core/Properties/GlobalAssemblyInfo.cs b/FemDesign.Core/Properties/GlobalAssemblyInfo.cs index a395682f7..1c658be6c 100644 --- a/FemDesign.Core/Properties/GlobalAssemblyInfo.cs +++ b/FemDesign.Core/Properties/GlobalAssemblyInfo.cs @@ -23,5 +23,5 @@ // Revision // -[assembly: AssemblyVersion("25.0.0")] -[assembly: AssemblyFileVersion("25.0.0")] +[assembly: AssemblyVersion("25.1.0")] +[assembly: AssemblyFileVersion("25.1.0")] diff --git a/FemDesign.Grasshopper/FemDesign.Grasshopper.csproj b/FemDesign.Grasshopper/FemDesign.Grasshopper.csproj index 99fff21f6..10d2a486e 100644 --- a/FemDesign.Grasshopper/FemDesign.Grasshopper.csproj +++ b/FemDesign.Grasshopper/FemDesign.Grasshopper.csproj @@ -9,6 +9,7 @@ v4.8 512 + true @@ -61,6 +62,9 @@ + + ..\packages\System.Resources.Extensions.8.0.0\lib\net462\System.Resources.Extensions.dll + @@ -232,6 +236,7 @@ + diff --git a/FemDesign.Grasshopper/Helpers/FemDesignConnectionHub.cs b/FemDesign.Grasshopper/Helpers/FemDesignConnectionHub.cs index a2683bde4..69f10368b 100644 --- a/FemDesign.Grasshopper/Helpers/FemDesignConnectionHub.cs +++ b/FemDesign.Grasshopper/Helpers/FemDesignConnectionHub.cs @@ -1,6 +1,7 @@ // https://strusoft.com/ using System; using System.Collections.Concurrent; +using System.Runtime.ExceptionServices; using System.Threading; using System.Threading.Tasks; @@ -28,9 +29,30 @@ public static Guid Create(string fdDir, bool minimized, string outputDir = null, { var id = Guid.NewGuid(); var inst = new Instance(); + var initialized = new ManualResetEventSlim(false); + Exception startupException = null; + inst.WorkerThread = new Thread(() => { - inst.Connection = new FemDesign.FemDesignConnection(fdDir, minimized, outputDir: outputDir, tempOutputDir: deleteOutput); + try + { + inst.Connection = new FemDesign.FemDesignConnection(fdDir, minimized, outputDir: outputDir, tempOutputDir: deleteOutput); + } + catch (Exception ex) + { + startupException = ex; + } + finally + { + initialized.Set(); + } + + if (inst.Connection == null) + { + inst.Queue.CompleteAdding(); + return; + } + foreach (var action in inst.Queue.GetConsumingEnumerable()) { try { action(); } @@ -45,6 +67,15 @@ public static Guid Create(string fdDir, bool minimized, string outputDir = null, throw new InvalidOperationException("Failed to create FemDesign connection instance."); inst.WorkerThread.Start(); + initialized.Wait(); + + if (startupException != null) + { + _instances.TryRemove(id, out _); + inst.Queue.Dispose(); + ExceptionDispatchInfo.Capture(startupException).Throw(); + } + return id; } diff --git a/FemDesign.Grasshopper/Pipe/FemDesignConnectionComponent.cs b/FemDesign.Grasshopper/Pipe/FemDesignConnectionComponent.cs index 43ae9d596..f2b754aa3 100644 --- a/FemDesign.Grasshopper/Pipe/FemDesignConnectionComponent.cs +++ b/FemDesign.Grasshopper/Pipe/FemDesignConnectionComponent.cs @@ -74,11 +74,20 @@ protected override void SolveInstance(IGH_DataAccess DA) System.IO.Directory.SetCurrentDirectory(currentDir); } - CloseConnection(); - _handle = FemDesignConnectionHub.Create(fdDir, minimized, outputDir, deleteOutput); + try + { + CloseConnection(); + _handle = FemDesignConnectionHub.Create(fdDir, minimized, outputDir, deleteOutput); - // Emit a handle object to wire downstream - DA.SetData("Connection", new FemDesign.Grasshopper.FemDesignHubHandle(_handle)); + // Emit a handle object to wire downstream + DA.SetData("Connection", new FemDesign.Grasshopper.FemDesignHubHandle(_handle)); + } + catch (Exception ex) + { + _handle = Guid.Empty; + AddRuntimeMessage(GH_RuntimeMessageLevel.Error, ex.Message); + DA.SetData("Connection", null); + } } private void CloseConnection() @@ -102,7 +111,7 @@ public override void RemovedFromDocument(GH_Document document) } protected override System.Drawing.Bitmap Icon => FemDesign.Properties.Resources.FEM_Connection; - public override Guid ComponentGuid => new Guid("{CBDD03EE-9F56-42FC-AA8D-7C45C152EF1C}"); + public override Guid ComponentGuid => new Guid("{A3F7B2D1-E4C8-4A6F-9D3E-1B5C7F8A2E09}"); public override GH_Exposure Exposure => GH_Exposure.primary; } } diff --git a/FemDesign.Grasshopper/Pipe/OBSOLETE/FemDesignConnectionComponent_OBSOLETE2500.cs b/FemDesign.Grasshopper/Pipe/OBSOLETE/FemDesignConnectionComponent_OBSOLETE2500.cs new file mode 100644 index 000000000..f909a56ff --- /dev/null +++ b/FemDesign.Grasshopper/Pipe/OBSOLETE/FemDesignConnectionComponent_OBSOLETE2500.cs @@ -0,0 +1,109 @@ +// https://strusoft.com/ +using System; +using System.Collections.Generic; +using Grasshopper; +using Grasshopper.Kernel; + +namespace FemDesign.Grasshopper +{ + /// + /// Configures the shared FemDesignConnectionHub and exposes a lightweight handle. + /// + public class FemDesignConnectionComponent_OBSOLETE2500: FEM_Design_API_Component + { + private Guid _handle = Guid.Empty; + public FemDesignConnectionComponent_OBSOLETE2500() : base("FEM-Design.Connection", "Connection", "Create or configure a shared FEM-Design connection. Use it to specify the 'Connection' for the LiveLink components.\n\n" + + "Note: Removing this component will automatically close the FEM-Design window. To keep FEM-Design open after closing the connection, use the 'Disconnect' component.", CategoryName.Name(), SubCategoryName.Cat8()) + { + ObjectChanged += FemDesignConnectionComponent_ObjectChanged; + } + + private void FemDesignConnectionComponent_ObjectChanged(object sender, GH_ObjectChangedEventArgs e) + { + if (e.Type is GH_ObjectEventType.Enabled) + { + CloseConnection(); + } + } + + protected override void RegisterInputParams(GH_InputParamManager pManager) + { + pManager.AddTextParameter("FEM-Design dir", "FEM-Design dir", "Path to the FEM-Design installation directory.", GH_ParamAccess.item, @"C:\\Program Files\\StruSoft\\FEM-Design 25\\"); + pManager[pManager.ParamCount - 1].Optional = true; + + pManager.AddBooleanParameter("Minimized", "Minimized", "If true, FEM-Design window will open in a minimised mode.", GH_ParamAccess.item, false); + pManager[pManager.ParamCount - 1].Optional = true; + + pManager.AddTextParameter("OutputDir", "OutputDir", "The directory where the script, log and result files will be saved. By default, the files will be written to the same directory as your .gh script.", GH_ParamAccess.item); + pManager[pManager.ParamCount - 1].Optional = true; + + pManager.AddBooleanParameter("DeleteOutputFolder", "DeleteOutputFolder", "Delete output directory on disconnect.", GH_ParamAccess.item, false); + pManager[pManager.ParamCount - 1].Optional = true; + } + + protected override void RegisterOutputParams(GH_OutputParamManager pManager) + { + pManager.AddGenericParameter("Connection", "Connection", "Shared FEM-Design connection handle.", GH_ParamAccess.item); + } + + protected override void SolveInstance(IGH_DataAccess DA) + { + string fdDir = @"C:\\Program Files\\StruSoft\\FEM-Design 25\\"; + DA.GetData("FEM-Design dir", ref fdDir); + + bool minimized = false; + DA.GetData("Minimized", ref minimized); + + string outputDir = null; + DA.GetData("OutputDir", ref outputDir); + + bool deleteOutput = false; + DA.GetData("DeleteOutputFolder", ref deleteOutput); + + // Set working directory similarly to existing component behavior + bool fileExist = OnPingDocument().IsFilePathDefined; + if (!fileExist) + { + string tempPath = System.IO.Path.GetTempPath(); + System.IO.Directory.SetCurrentDirectory(tempPath); + } + else + { + var filePath = OnPingDocument().FilePath; + var currentDir = System.IO.Path.GetDirectoryName(filePath); + System.IO.Directory.SetCurrentDirectory(currentDir); + } + + CloseConnection(); + _handle = FemDesignConnectionHub.Create(fdDir, minimized, outputDir, deleteOutput); + + // Emit a handle object to wire downstream + DA.SetData("Connection", new FemDesign.Grasshopper.FemDesignHubHandle(_handle)); + } + + private void CloseConnection() + { + if (_handle != Guid.Empty) + { + FemDesignConnectionHub.DisposeAsync(_handle).GetAwaiter().GetResult(); + _handle = Guid.Empty; + } + } + + public override void RemovedFromDocument(GH_Document document) + { + try + { + CloseConnection(); + } + catch { } + + base.RemovedFromDocument(document); + } + + protected override System.Drawing.Bitmap Icon => FemDesign.Properties.Resources.FEM_Connection; + public override Guid ComponentGuid => new Guid("{CBDD03EE-9F56-42FC-AA8D-7C45C152EF1C}"); + public override GH_Exposure Exposure => GH_Exposure.hidden; + } +} + diff --git a/FemDesign.Grasshopper/packages.config b/FemDesign.Grasshopper/packages.config index 8f67b3d0e..78e746087 100644 --- a/FemDesign.Grasshopper/packages.config +++ b/FemDesign.Grasshopper/packages.config @@ -3,4 +3,5 @@ + \ No newline at end of file diff --git a/FemDesign.Tests/Results/Assets/General.str b/FemDesign.Tests/Results/Assets/General.str index f5696b058..568b15aa0 100644 Binary files a/FemDesign.Tests/Results/Assets/General.str and b/FemDesign.Tests/Results/Assets/General.str differ diff --git a/FemDesign.Tests/Results/Assets/General.strFEM b/FemDesign.Tests/Results/Assets/General.strFEM index dae27badc..871e5bde9 100644 Binary files a/FemDesign.Tests/Results/Assets/General.strFEM and b/FemDesign.Tests/Results/Assets/General.strFEM differ diff --git a/FemDesign.Tests/Sections/SectionDatabaseTests.cs b/FemDesign.Tests/Sections/SectionDatabaseTests.cs index 66c666514..4bffb0cfb 100644 --- a/FemDesign.Tests/Sections/SectionDatabaseTests.cs +++ b/FemDesign.Tests/Sections/SectionDatabaseTests.cs @@ -34,9 +34,8 @@ public void GetDefaultTest() } - [TestMethod("SectionDatabase - Fuzzy search")] [TestCategory("FEM-Design required")] - + [TestMethod("Fuzzy Search")] public void TestFuzzySearch() { var db = SectionDatabase.GetDefault();