├── LICENSE ├── lib ├── InstantMeshes.exe └── InstantMeshes LICENSE.txt ├── Resources └── InstantMeshes.ico ├── Properties └── AssemblyInfo.cs ├── InstantMeshesInfo.cs ├── InstantMeshes.sln ├── README.md ├── InstantMeshes.csproj ├── FileObj.cs └── InstantMeshesComponent.cs /LICENSE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dalefugier/InstantMeshes/HEAD/LICENSE -------------------------------------------------------------------------------- /lib/InstantMeshes.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dalefugier/InstantMeshes/HEAD/lib/InstantMeshes.exe -------------------------------------------------------------------------------- /Resources/InstantMeshes.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dalefugier/InstantMeshes/HEAD/Resources/InstantMeshes.ico -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | [assembly: AssemblyTrademark("")] 5 | [assembly: AssemblyCulture("")] 6 | [assembly: ComVisible(false)] 7 | [assembly: Guid("416e37e9-85bf-439c-992f-6bac1ab72ebe")] 8 | -------------------------------------------------------------------------------- /InstantMeshesInfo.cs: -------------------------------------------------------------------------------- 1 | using Grasshopper.Kernel; 2 | using System; 3 | using System.Drawing; 4 | using System.Reflection; 5 | 6 | namespace InstantMeshes 7 | { 8 | public class InstantMeshesInfo : GH_AssemblyInfo 9 | { 10 | public override string Name => "InstantMeshes"; 11 | public override Bitmap Icon 12 | { 13 | get 14 | { 15 | const string resource = "InstantMeshes.Resources.InstantMeshes.ico"; 16 | Size size = new Size(24, 24); 17 | Assembly assembly = Assembly.GetExecutingAssembly(); 18 | Icon icon = Rhino.UI.DrawingUtilities.IconFromResource(resource, size, assembly); 19 | return icon.ToBitmap(); 20 | } 21 | } 22 | public override string Description => "Field-aligned mesh generator for Grasshopper®"; 23 | public override Guid Id => new Guid("06cbea6f-9c7a-46e1-b0e2-fc0f114ecfd0"); 24 | public override string AuthorName => "Robert McNeel & Associates"; 25 | public override string AuthorContact => "https://github.com/dalefugier/InstantMeshes"; 26 | public override string Version => "8.19.25132.1001"; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /InstantMeshes.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.779 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InstantMeshes", "InstantMeshes.csproj", "{416E37E9-85BF-439C-992F-6BAC1AB72EBE}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {416E37E9-85BF-439C-992F-6BAC1AB72EBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {416E37E9-85BF-439C-992F-6BAC1AB72EBE}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {416E37E9-85BF-439C-992F-6BAC1AB72EBE}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {416E37E9-85BF-439C-992F-6BAC1AB72EBE}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {094541CE-66EB-4D21-A58A-B2CE5C9DC3F3} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # InstantMeshes 2 | 3 | [](https://github.com/wjakob/instant-meshes) 4 | 5 | Grasshopper for Windows plug-in that uses the [Instant Meshes](https://github.com/wjakob/instant-meshes) open source meshing utility. 6 | 7 | InstantMeshes is available in Rhino via the [PackageManager](https://www.rhino3d.com/features/package-manager/). 8 | 9 | ## Prerequisites 10 | 11 | The following tools are required to build InstantMeshes: 12 | 13 | - [Microsoft Visual Studio](https://visualstudio.microsoft.com/) 14 | - [Rhino 8 for Windows](https://www.rhino3d.com/) 15 | 16 | ## Compiling 17 | 18 | 1. Clone the repository. At a command prompt, enter the following command: 19 | ``` 20 | git clone https://github.com/dalefugier/InstantMeshes 21 | ``` 22 | 2. Open the `InstantMeshes.sln` solution file in Visual Studio. 23 | 4. Press F7, or click *Build > Build Solution* to build the solution. 24 | 25 | ## License 26 | This source code is licensed under the [MIT License](https://github.com/dalefugier/InstantMeshes/blob/master/LICENSE). 27 | 28 | [Instant Meshes](https://github.com/wjakob/instant-meshes/blob/master/LICENSE.txt) has its own separate license agreement. 29 | 30 | -------------------------------------------------------------------------------- /lib/InstantMeshes LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Wenzel Jakob, Daniele Panozzo, Marco Tarini, 2 | and Olga Sorkine-Hornung. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors 15 | may be used to endorse or promote products derived from this software 16 | without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | You are under no obligation whatsoever to provide any bug fixes, patches, or 30 | upgrades to the features, functionality or performance of the source code 31 | ("Enhancements") to anyone; however, if you choose to make your Enhancements 32 | available either publicly, or directly to the authors of this software, without 33 | imposing a separate written license agreement for such Enhancements, then you 34 | hereby grant the following license: a non-exclusive, royalty-free perpetual 35 | license to install, use, modify, prepare derivative works, incorporate into 36 | other computer software, distribute, and sublicense such enhancements or 37 | derivative works thereof, in binary and source code form. 38 | -------------------------------------------------------------------------------- /InstantMeshes.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net7.0;net48 4 | true 5 | NU1701 6 | .gha 7 | .\bin\ 8 | Library 9 | 10 | 11 | 12 | Robert McNeel & Associates 13 | Copyright © 2013-2025, Robert McNeel & Associates 14 | InstantMeshes 15 | Field-aligned mesh generator for Grasshopper® 16 | 8.19.25132.1001 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | PreserveNewest 28 | InstantMeshes.exe 29 | 30 | 31 | 32 | 33 | 34 | 35 | PreserveNewest 36 | InstantMeshes LICENSE.txt 37 | 38 | 39 | 40 | 41 | 42 | 43 | C:\Program Files\Rhino 8\System\Yak.exe 44 | True 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /FileObj.cs: -------------------------------------------------------------------------------- 1 | using Rhino; 2 | using Rhino.Geometry; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Globalization; 6 | using System.IO; 7 | using System.Text.RegularExpressions; 8 | 9 | namespace InstantMeshes 10 | { 11 | internal static class FileObj 12 | { 13 | public static void Write(IEnumerable meshes, string filename) 14 | { 15 | try 16 | { 17 | StreamWriter sw = new StreamWriter(filename); 18 | // Write header 19 | sw.WriteLine("#OBJ"); 20 | // Write mesh geometry 21 | long vert_counter = 1; 22 | foreach (Mesh m in meshes) 23 | { 24 | // Write all Verticies: v 1 2 3 25 | int vc = m.Vertices.Count; 26 | for (int i = 0; i < vc; i++) 27 | sw.WriteLine($"v {m.Vertices[i].X.ToString(CultureInfo.InvariantCulture)} {m.Vertices[i].Y.ToString(CultureInfo.InvariantCulture)} {m.Vertices[i].Z.ToString(CultureInfo.InvariantCulture)}"); 28 | // Write All vertex normals: vn 1 2 3 29 | int nc = m.Normals.Count; 30 | m.Normals.UnitizeNormals(); 31 | for (int i = 0; i < nc; i++) 32 | sw.WriteLine($"vn {m.Normals[i].X.ToString(CultureInfo.InvariantCulture)} {m.Normals[i].Y.ToString(CultureInfo.InvariantCulture)} {m.Normals[i].Z.ToString(CultureInfo.InvariantCulture)}"); 33 | // Write All Faces: f 1 2 3 / 4 34 | int fc = m.Faces.Count; 35 | for (int i = 0; i < fc; i++) 36 | { 37 | if (m.Faces[i].IsTriangle) 38 | sw.WriteLine( 39 | $"f {m.Faces[i].A + vert_counter} {m.Faces[i].B + vert_counter} {m.Faces[i].C + vert_counter}"); 40 | if (m.Faces[i].IsQuad) 41 | sw.WriteLine( 42 | $"f {m.Faces[i].A + vert_counter} {m.Faces[i].B + vert_counter} {m.Faces[i].C + vert_counter} {m.Faces[i].D + vert_counter}"); 43 | } 44 | vert_counter += m.Vertices.Count; 45 | } 46 | sw.Close(); 47 | } 48 | catch (Exception e) 49 | { 50 | RhinoApp.WriteLine(e.Message); 51 | } 52 | } 53 | 54 | public static Mesh Read(string filename) 55 | { 56 | try 57 | { 58 | using (StreamReader sr = new StreamReader(filename)) 59 | { 60 | string obj_file = sr.ReadToEnd(); 61 | Mesh obj = new Mesh(); 62 | 63 | #region ADD NORMALS 64 | //n vector normals 65 | const string normal_reg = @"vn( +[\d|\.|\+|\-|e]+)( [\d|\.|\+|\-|e]+)( [\d|\.|\+|\-|e]+)"; 66 | foreach (Match m in Regex.Matches(obj_file, normal_reg)) 67 | { 68 | Vector3d n = new Vector3d(double.Parse(m.Groups[1].Value, CultureInfo.InvariantCulture), double.Parse(m.Groups[2].Value, CultureInfo.InvariantCulture), 69 | double.Parse(m.Groups[3].Value, CultureInfo.InvariantCulture)); 70 | if (n.IsValid) 71 | obj.Normals.Add(n); 72 | } 73 | #endregion 74 | 75 | #region ADD VERTS 76 | //v add verts 77 | const string vertex_reg = @"v( +[\d|\.|\+|\-|e]+)( [\d|\.|\+|\-|e]+)( [\d|\.|\+|\-|e]+)"; 78 | MatchCollection verts = Regex.Matches(obj_file, vertex_reg); 79 | if (verts.Count > 0) 80 | { 81 | foreach (Match m in verts) 82 | { 83 | int vc = obj.Vertices.Count; 84 | Point3d p = new Point3d(double.Parse(m.Groups[1].Value, CultureInfo.InvariantCulture), 85 | double.Parse(m.Groups[2].Value, CultureInfo.InvariantCulture), 86 | double.Parse(m.Groups[3].Value, CultureInfo.InvariantCulture)); 87 | if (p.IsValid) 88 | obj.Vertices.SetVertex(vc, p.X, p.Y, p.Z); 89 | 90 | } 91 | //obj.Vertices.CombineIdentical(true, true); 92 | 93 | } 94 | #endregion 95 | 96 | #region ADD FACES 97 | // HUNT FOR FACES 98 | 99 | // f vertex vertex vertex eg f 1 2 3 100 | const string fvvv_reg = @"f( +[\d]+)( [\d]+)( [\d]+)( [\d]+)?"; 101 | MatchCollection fvvv = Regex.Matches(obj_file, fvvv_reg); 102 | 103 | if (fvvv.Count > 0) 104 | { 105 | foreach (Match m in fvvv) 106 | { 107 | MeshFace mf = new MeshFace 108 | { 109 | A = int.Parse(m.Groups[1].Value, CultureInfo.InvariantCulture) - 1, 110 | B = int.Parse(m.Groups[2].Value, CultureInfo.InvariantCulture) - 1, 111 | C = int.Parse(m.Groups[3].Value, CultureInfo.InvariantCulture) - 1 112 | }; 113 | if (m.Groups.Count == 5) 114 | mf.D = int.Parse(m.Groups[4].Value, CultureInfo.InvariantCulture) - 1; 115 | obj.Faces.AddFace(mf); 116 | } 117 | } 118 | else 119 | { 120 | //f quad based face structure v//n v//n v//n v//n 121 | const string fvnq_reg = @"(^f )[\d].+"; 122 | const RegexOptions options = RegexOptions.Multiline; 123 | MatchCollection fvnq = Regex.Matches(obj_file, fvnq_reg, options); 124 | if (fvnq.Count > 0) 125 | { 126 | foreach (Match m in fvnq) 127 | { 128 | const string faces_req = @" [\d]+"; 129 | MatchCollection faces = Regex.Matches(m.Value, faces_req); 130 | 131 | if (faces.Count <= 0) 132 | continue; 133 | 134 | MeshFace mf = new MeshFace 135 | { 136 | A = int.Parse(faces[0].Value, CultureInfo.InvariantCulture) - 1, 137 | B = int.Parse(faces[1].Value, CultureInfo.InvariantCulture) - 1, 138 | C = int.Parse(faces[2].Value, CultureInfo.InvariantCulture) - 1 139 | }; 140 | 141 | if (faces.Count == 4) 142 | { 143 | mf.D = int.Parse(faces[3].Value, CultureInfo.InvariantCulture) - 1; 144 | } 145 | else 146 | { 147 | mf.D = mf.C; 148 | } 149 | 150 | obj.Faces.AddFace(mf); 151 | 152 | } 153 | 154 | } 155 | } 156 | #endregion 157 | 158 | 159 | sr.Close(); 160 | 161 | obj.Faces.CullDegenerateFaces(); 162 | obj.Compact(); 163 | 164 | 165 | if (obj.Normals.Count == 0) 166 | obj.Normals.ComputeNormals(); 167 | 168 | if (obj.IsValid) 169 | obj.Weld(22.5); 170 | 171 | return obj; 172 | } 173 | } 174 | catch 175 | { 176 | return null; 177 | } 178 | } 179 | } 180 | } 181 | 182 | 183 | -------------------------------------------------------------------------------- /InstantMeshesComponent.cs: -------------------------------------------------------------------------------- 1 | using Grasshopper; 2 | using Grasshopper.Kernel; 3 | using Rhino.Geometry; 4 | using System; 5 | using System.Diagnostics; 6 | using System.Drawing; 7 | using System.IO; 8 | using System.Reflection; 9 | using System.Threading; 10 | 11 | namespace InstantMeshes 12 | { 13 | public class InstantMeshesComponent : GH_Component 14 | { 15 | public InstantMeshesComponent() 16 | : base("InstantMeshes", "IM", "Construct a field-aligned mesh.", "Mesh", "Triangulation") 17 | { 18 | } 19 | 20 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager args) 21 | { 22 | args.AddMeshParameter("Mesh", "M", "Mesh", GH_ParamAccess.item); 23 | args.AddIntegerParameter("Faces", "F", "Target face count", GH_ParamAccess.item, 1000); 24 | args.AddIntegerParameter("Smooth", "S", "Smoothing steps", GH_ParamAccess.item, 2); 25 | args.AddIntegerParameter("Format", "F", "Mesh format: 0 = Triangles (6-RoSy, 6-PoSy), 1 = Quads (2-RoSy, 4-PoSy), 2 = Quads (4-RoSy,4-PoSy)", GH_ParamAccess.item, 2); 26 | args.AddBooleanParameter("Extrinsic", "E", "Extrinsic or intrinsic", GH_ParamAccess.item, true); 27 | args.AddBooleanParameter("Align", "A", "Align to boundaries", GH_ParamAccess.item, true); 28 | args.AddBooleanParameter("Creases", "C", "Sharp creases", GH_ParamAccess.item, true); 29 | args.AddNumberParameter("Angle", "A", "Crease angle in degrees", GH_ParamAccess.item, 90.0); 30 | 31 | //args[7].Optional = true; 32 | } 33 | 34 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager args) 35 | { 36 | args.AddMeshParameter("Mesh", "M", "Instant mesh", GH_ParamAccess.item); 37 | } 38 | 39 | protected override void SolveInstance(IGH_DataAccess access) 40 | { 41 | #region Process input 42 | 43 | Mesh mesh = new Mesh(); 44 | int target_face_count = 1000; 45 | int smooth_iterations = 2; 46 | int mesh_format = 2; 47 | bool extrinsic = true; 48 | bool align_boundaries = true; 49 | bool sharp_creases = true; 50 | double crease_angle = 90.0; 51 | 52 | if (!access.GetData(0, ref mesh)) return; 53 | if (!access.GetData(1, ref target_face_count)) return; 54 | if (!access.GetData(2, ref smooth_iterations)) return; 55 | if (!access.GetData(3, ref mesh_format)) return; 56 | if (!access.GetData(4, ref extrinsic)) return; 57 | if (!access.GetData(5, ref align_boundaries)) return; 58 | if (!access.GetData(6, ref sharp_creases)) return; 59 | if (!access.GetData(7, ref crease_angle)) return; 60 | 61 | if (!mesh.IsValid) 62 | { 63 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Input mesh is invalid"); 64 | return; 65 | } 66 | if (mesh_format < 0 || mesh_format > 2) 67 | { 68 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Mesh format must be: 0 <= Format <= 2"); 69 | return; 70 | } 71 | if (crease_angle < 0.0 || crease_angle > 180.0) 72 | { 73 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Crease angle must be: 0 < Angle < 180.0"); 74 | return; 75 | } 76 | 77 | #endregion 78 | 79 | 80 | #region Setup paths 81 | 82 | 83 | string gha_path = AssemblyDirectory; 84 | string im_path = Path.Combine(gha_path, "InstantMeshes.exe"); 85 | if (!File.Exists(im_path)) 86 | { 87 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "InstantMeshes.exe not found"); 88 | return; 89 | } 90 | 91 | string tmp_path = Path.GetTempPath(); 92 | Guid guid = Guid.NewGuid(); 93 | 94 | string temp_obj = Path.Combine(tmp_path, $"input{guid}.obj"); 95 | if (File.Exists(temp_obj)) 96 | File.Delete(temp_obj); 97 | 98 | string temp_output_obj = Path.Combine(tmp_path, $"output{guid}.obj"); 99 | if (File.Exists(temp_output_obj)) 100 | File.Delete(temp_output_obj); 101 | 102 | FileObj.Write(new[] { mesh }, temp_obj); 103 | 104 | #endregion 105 | 106 | 107 | #region Configure and run InstantMeshes 108 | 109 | int mx = 2; 110 | if (mesh_format == 0) 111 | mx = 6; 112 | else if (mesh_format == 1) 113 | mx = 2; 114 | else if (mesh_format == 2) 115 | mx = 4; 116 | 117 | int my = 4; 118 | if (mesh_format == 0) 119 | my = 6; 120 | else if (mesh_format == 1 || mesh_format == 2) 121 | my = 4; 122 | 123 | string b = align_boundaries == true ? "-b" : string.Empty; 124 | string i = extrinsic == true ? string.Empty : "-i"; 125 | string c = sharp_creases == true ? $"-c {crease_angle}" : string.Empty; 126 | 127 | string args = $"\"{temp_obj}\" -f {target_face_count} -p {my} -r {mx} {i} {c} {b} -S {smooth_iterations} -o \"{temp_output_obj}\""; 128 | 129 | ProcessStartInfo start_info = new ProcessStartInfo() 130 | { 131 | FileName = im_path, 132 | Arguments = args, 133 | UseShellExecute = false, 134 | RedirectStandardOutput = true, 135 | RedirectStandardError = true, 136 | WindowStyle = ProcessWindowStyle.Hidden, 137 | CreateNoWindow = true 138 | }; 139 | 140 | Process process = new Process 141 | { 142 | StartInfo = start_info, 143 | EnableRaisingEvents = true 144 | }; 145 | try 146 | { 147 | process.Start(); 148 | } 149 | catch 150 | { 151 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Failed to start InstantMeshes process"); 152 | return; 153 | 154 | } 155 | 156 | StreamReader s_out = process.StandardOutput; 157 | StreamReader s_err = process.StandardError; 158 | try 159 | { 160 | string str; 161 | while ((str = s_out.ReadLine()) != null && !s_out.EndOfStream) 162 | { 163 | s_out.BaseStream.Flush(); 164 | } 165 | while ((str = s_err.ReadLine()) != null && !s_err.EndOfStream) 166 | { 167 | s_err.BaseStream.Flush(); 168 | } 169 | 170 | } 171 | finally 172 | { 173 | s_out.Close(); 174 | s_err.Close(); 175 | } 176 | 177 | #endregion 178 | 179 | 180 | #region Return meshes from InstantMeshes 181 | 182 | if (!File.Exists(temp_output_obj)) 183 | { 184 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Mesh creation failed"); 185 | return; 186 | } 187 | 188 | int retries = 0; 189 | while (IsFileLocked(new FileInfo(temp_output_obj)) || retries >= 4) 190 | { 191 | Thread.Sleep(500); 192 | retries++; 193 | } 194 | 195 | Mesh imported_mesh = FileObj.Read(temp_output_obj); 196 | if (imported_mesh == null) 197 | { 198 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "An invalid mesh was returned from InstantMeshes"); 199 | return; 200 | } 201 | 202 | if (imported_mesh.SolidOrientation() == -1) 203 | imported_mesh.Flip(true, true, true); 204 | 205 | #endregion 206 | 207 | 208 | if (File.Exists(temp_output_obj)) 209 | File.Delete(temp_output_obj); 210 | 211 | if (File.Exists(temp_obj)) 212 | File.Delete(temp_obj); 213 | 214 | access.SetData(0, imported_mesh); 215 | } 216 | 217 | /// 218 | /// Returns the path to this assembly 219 | /// 220 | private string AssemblyDirectory 221 | { 222 | get 223 | { 224 | GH_AssemblyInfo info = Instances.ComponentServer.FindAssemblyByObject(ComponentGuid); 225 | return (null != info) ? Path.GetDirectoryName(info.Location) : null; 226 | } 227 | } 228 | 229 | /// 230 | /// Returns true if the specified file is locked by another process 231 | /// 232 | private bool IsFileLocked(FileInfo file) 233 | { 234 | FileStream stream = null; 235 | try 236 | { 237 | stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None); 238 | } 239 | catch (IOException) 240 | { 241 | return true; 242 | } 243 | finally 244 | { 245 | stream?.Close(); 246 | } 247 | return false; 248 | } 249 | 250 | 251 | public override GH_Exposure Exposure => GH_Exposure.quarternary; 252 | 253 | protected override Bitmap Icon 254 | { 255 | get 256 | { 257 | const string resource = "InstantMeshes.Resources.InstantMeshes.ico"; 258 | Size size = new Size(24, 24); 259 | Assembly assembly = Assembly.GetExecutingAssembly(); 260 | Icon icon = Rhino.UI.DrawingUtilities.IconFromResource(resource, size, assembly); 261 | return icon.ToBitmap(); 262 | } 263 | } 264 | 265 | public override Guid ComponentGuid => new Guid("30392475-f7c9-4317-b8e8-4480cd13cdfd"); 266 | } 267 | } 268 | --------------------------------------------------------------------------------