Fix build errors for .NET 7.0 / Rhino 9 WIP
- 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 <noreply@anthropic.com>
This commit is contained in:
@@ -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" };
|
||||
|
||||
|
||||
@@ -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<string, object>
|
||||
{
|
||||
["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<float>() ?? 0;
|
||||
var y = position?["y"]?.Value<float>() ?? 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,21 +442,25 @@ 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 geo = goo.ScriptVariable() as Rhino.Geometry.GeometryBase;
|
||||
if (geo != null)
|
||||
{
|
||||
var attributes = new Rhino.DocObjects.ObjectAttributes
|
||||
{
|
||||
LayerIndex = layerIndex
|
||||
};
|
||||
|
||||
Guid objId;
|
||||
if (bakeAware.BakeGeometry(rhinoDoc, attributes, out objId))
|
||||
var objId = rhinoDoc.Objects.Add(geo, attributes);
|
||||
if (objId != Guid.Empty)
|
||||
bakedCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rhinoDoc.Views.Redraw();
|
||||
|
||||
@@ -501,7 +490,8 @@ namespace RhinoMCP
|
||||
}
|
||||
else
|
||||
{
|
||||
success = io.SaveAs(filePath);
|
||||
doc.FilePath = filePath;
|
||||
success = io.Save();
|
||||
}
|
||||
|
||||
return new { success, file_path = filePath };
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0-windows</TargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
|
||||
<!-- Rhino Plugin Settings -->
|
||||
<EnableDynamicLoading>true</EnableDynamicLoading>
|
||||
|
||||
Reference in New Issue
Block a user