From f9d67150563c9a2f81454db3cd472ee2c7190fd8 Mon Sep 17 00:00:00 2001 From: architeur Date: Mon, 29 Dec 2025 21:19:27 +0100 Subject: [PATCH] Fix build errors for .NET 7.0 / Rhino 9 WIP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Target .NET 7.0 for Rhino 9 WIP compatibility - Fix Sphere volume calculation (manual formula) - Fix BooleanDifference API signature - Replace IGH_BakeAwareObject with IGH_GeometricGoo for baking - Fix anonymous type declarations in GrasshopperHandler 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/rhino-plugin/RhinoMCP/CommandHandler.cs | 5 +- .../RhinoMCP/GrasshopperHandler.cs | 104 ++++++++---------- src/rhino-plugin/RhinoMCP/RhinoMCP.csproj | 3 +- 3 files changed, 52 insertions(+), 60 deletions(-) diff --git a/src/rhino-plugin/RhinoMCP/CommandHandler.cs b/src/rhino-plugin/RhinoMCP/CommandHandler.cs index 41cf147..eba01b1 100644 --- a/src/rhino-plugin/RhinoMCP/CommandHandler.cs +++ b/src/rhino-plugin/RhinoMCP/CommandHandler.cs @@ -221,7 +221,8 @@ namespace RhinoMCP var id = doc.Objects.AddSphere(sphere); doc.Views.Redraw(); - return new { success = true, id = id.ToString(), radius, volume = sphere.Volume() }; + var volume = (4.0 / 3.0) * Math.PI * radius * radius * radius; + return new { success = true, id = id.ToString(), radius, volume }; } private static object CreateBox(RhinoDoc doc, JObject p) @@ -548,7 +549,7 @@ namespace RhinoMCP .Where(b => b != null) .ToList(); - var result = Brep.CreateBooleanDifference(baseBrep, subtractBreps!, doc.ModelAbsoluteTolerance); + var result = Brep.CreateBooleanDifference(new[] { baseBrep }, subtractBreps!, doc.ModelAbsoluteTolerance); if (result == null || result.Length == 0) return new { error = "Boolean difference failed" }; diff --git a/src/rhino-plugin/RhinoMCP/GrasshopperHandler.cs b/src/rhino-plugin/RhinoMCP/GrasshopperHandler.cs index 239cda3..5fac49b 100644 --- a/src/rhino-plugin/RhinoMCP/GrasshopperHandler.cs +++ b/src/rhino-plugin/RhinoMCP/GrasshopperHandler.cs @@ -37,8 +37,7 @@ namespace RhinoMCP private static GH_Document? GetActiveDocument() { - var editor = Instances.ActiveCanvas?.Document; - return editor; + return Instances.ActiveCanvas?.Document; } private static object OpenDefinition(JObject p) @@ -53,7 +52,7 @@ namespace RhinoMCP if (Instances.ActiveCanvas == null) { RhinoApp.RunScript("_Grasshopper", false); - System.Threading.Thread.Sleep(1000); // Wait for GH to open + System.Threading.Thread.Sleep(1000); } var io = new GH_DocumentIO(); @@ -94,23 +93,21 @@ namespace RhinoMCP foreach (var obj in doc.Objects) { - var info = new Dictionary - { - ["instance_guid"] = obj.InstanceGuid.ToString(), - ["name"] = obj.Name ?? "", - ["nickname"] = obj.NickName ?? "", - ["category"] = obj.Category ?? "", - ["subcategory"] = obj.SubCategory ?? "", - ["position"] = new { x = obj.Attributes.Pivot.X, y = obj.Attributes.Pivot.Y } - }; + var instanceGuid = obj.InstanceGuid.ToString(); + var name = obj.Name ?? ""; + var nickname = obj.NickName ?? ""; + var category = obj.Category ?? ""; + var subcategory = obj.SubCategory ?? ""; + var posX = obj.Attributes.Pivot.X; + var posY = obj.Attributes.Pivot.Y; if (obj is GH_NumberSlider slider) { sliders.Add(new { - info["instance_guid"], - info["nickname"], - info["position"], + instance_guid = instanceGuid, + nickname = nickname, + position = new { x = posX, y = posY }, current_value = slider.CurrentValue, min_value = (double)slider.Slider.Minimum, max_value = (double)slider.Slider.Maximum, @@ -121,9 +118,9 @@ namespace RhinoMCP { toggles.Add(new { - info["instance_guid"], - info["nickname"], - info["position"], + instance_guid = instanceGuid, + nickname = nickname, + position = new { x = posX, y = posY }, value = toggle.Value }); } @@ -131,38 +128,38 @@ namespace RhinoMCP { panels.Add(new { - info["instance_guid"], - info["nickname"], - info["position"], + instance_guid = instanceGuid, + nickname = nickname, + position = new { x = posX, y = posY }, text = panel.UserText }); } else if (obj is IGH_Component component) { - var inputs = component.Params.Input.Select(p => new + var inputs = component.Params.Input.Select(param => new { - name = p.Name, - nickname = p.NickName, - type = p.TypeName, - source_count = p.SourceCount + name = param.Name, + nickname = param.NickName, + type = param.TypeName, + source_count = param.SourceCount }).ToList(); - var outputs = component.Params.Output.Select(p => new + var outputs = component.Params.Output.Select(param => new { - name = p.Name, - nickname = p.NickName, - type = p.TypeName, - recipient_count = p.Recipients.Count + name = param.Name, + nickname = param.NickName, + type = param.TypeName, + recipient_count = param.Recipients.Count }).ToList(); components.Add(new { - info["instance_guid"], - info["name"], - info["nickname"], - info["category"], - info["subcategory"], - info["position"], + instance_guid = instanceGuid, + name = name, + nickname = nickname, + category = category, + subcategory = subcategory, + position = new { x = posX, y = posY }, inputs, outputs }); @@ -197,7 +194,6 @@ namespace RhinoMCP if (slider == null) return new { error = $"Slider '{sliderName}' not found" }; - // Clamp value to slider range var min = (double)slider.Slider.Minimum; var max = (double)slider.Slider.Maximum; value = Math.Max(min, Math.Min(max, value)); @@ -257,7 +253,6 @@ namespace RhinoMCP var doc = GetActiveDocument(); if (doc == null) { - // Try to open Grasshopper RhinoApp.RunScript("_Grasshopper", false); System.Threading.Thread.Sleep(1000); doc = GetActiveDocument(); @@ -270,7 +265,6 @@ namespace RhinoMCP var x = position?["x"]?.Value() ?? 0; var y = position?["y"]?.Value() ?? 0; - // Find component by name in the component server var proxy = Instances.ComponentServer.FindObjectByName(componentName, true, true); if (proxy == null) return new { error = $"Component '{componentName}' not found" }; @@ -312,17 +306,14 @@ namespace RhinoMCP var targetId = p["target_component"]?.ToString() ?? ""; var targetInput = p["target_input"]?.ToString() ?? ""; - // Find source component var sourceObj = FindComponent(doc, sourceId); if (sourceObj == null) return new { error = $"Source component '{sourceId}' not found" }; - // Find target component var targetObj = FindComponent(doc, targetId); if (targetObj == null) return new { error = $"Target component '{targetId}' not found" }; - // Get output parameter IGH_Param? outputParam = null; if (sourceObj is IGH_Component sourceComp) { @@ -337,7 +328,6 @@ namespace RhinoMCP if (outputParam == null) return new { error = $"Output '{sourceOutput}' not found on source component" }; - // Get input parameter IGH_Param? inputParam = null; if (targetObj is IGH_Component targetComp) { @@ -352,7 +342,6 @@ namespace RhinoMCP if (inputParam == null) return new { error = $"Input '{targetInput}' not found on target component" }; - // Create connection inputParam.AddSource(outputParam); doc.NewSolution(true); Instances.ActiveCanvas?.Refresh(); @@ -370,13 +359,11 @@ namespace RhinoMCP private static IGH_DocumentObject? FindComponent(GH_Document doc, string identifier) { - // Try to find by GUID if (Guid.TryParse(identifier, out var guid)) { return doc.Objects.FirstOrDefault(o => o.InstanceGuid == guid); } - // Try to find by name or nickname return doc.Objects.FirstOrDefault(o => o.Name == identifier || o.NickName == identifier); } @@ -436,7 +423,6 @@ namespace RhinoMCP if (rhinoDoc == null) return new { error = "No active Rhino document" }; - // Ensure layer exists var layerIndex = rhinoDoc.Layers.FindByFullPath(layerName, -1); if (layerIndex < 0) layerIndex = rhinoDoc.Layers.Add(layerName, Color.Black); @@ -447,7 +433,6 @@ namespace RhinoMCP { if (obj is IGH_Component component) { - // Skip if we're looking for a specific component if (!string.IsNullOrEmpty(componentName) && component.Name != componentName && component.NickName != componentName) @@ -457,16 +442,20 @@ namespace RhinoMCP { foreach (var item in output.VolatileData.AllData(true)) { - if (item is Grasshopper.Kernel.Types.IGH_BakeAwareData bakeAware) + if (item is Grasshopper.Kernel.Types.IGH_GeometricGoo goo && goo.IsValid) { - var attributes = new Rhino.DocObjects.ObjectAttributes + var geo = goo.ScriptVariable() as Rhino.Geometry.GeometryBase; + if (geo != null) { - LayerIndex = layerIndex - }; + var attributes = new Rhino.DocObjects.ObjectAttributes + { + LayerIndex = layerIndex + }; - Guid objId; - if (bakeAware.BakeGeometry(rhinoDoc, attributes, out objId)) - bakedCount++; + var objId = rhinoDoc.Objects.Add(geo, attributes); + if (objId != Guid.Empty) + bakedCount++; + } } } } @@ -501,7 +490,8 @@ namespace RhinoMCP } else { - success = io.SaveAs(filePath); + doc.FilePath = filePath; + success = io.Save(); } return new { success, file_path = filePath }; diff --git a/src/rhino-plugin/RhinoMCP/RhinoMCP.csproj b/src/rhino-plugin/RhinoMCP/RhinoMCP.csproj index 0955c2f..f217593 100644 --- a/src/rhino-plugin/RhinoMCP/RhinoMCP.csproj +++ b/src/rhino-plugin/RhinoMCP/RhinoMCP.csproj @@ -2,9 +2,10 @@ net7.0-windows + latest enable enable - latest + true true