Compare commits

...

9 Commits

Author SHA1 Message Date
Björn Steinhagen 3090b5f5bb Merge pull request #1207 from specklesystems/dev
.NET Build and Publish / build-connectors (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
merge dev -> main
2025-12-03 12:31:27 +02:00
Björn Steinhagen 7c609c93ae fix(grasshopper): syncing GeometryBase to Base for re-publish workflows (#1205) 2025-12-01 15:46:23 +03:00
Jedd Morgan 36a6572483 Merge pull request #1204 from specklesystems/main
back merge Main -> dev
2025-12-01 10:56:30 +00:00
Jedd Morgan ce04d2fd55 Merge pull request #1203 from specklesystems/dev
Back merge dev -> main
2025-12-01 10:53:36 +00:00
Jedd Morgan 4dbe4dd9a0 fix(rhino-importer): Ensure non-zero exit code is propagated (#1199)
* Ensure background service exit codes are properly propagated

* detail log

* fail fast

* log

* env exit works just as well

* add comment

* Use central management for importer version
2025-12-01 10:51:29 +00:00
Björn Steinhagen 6f72402b76 fix(revit): rebar and area reinforcement transforms with reference points (#1202)
* fix: rebar transforms

* fix: area reinf.
2025-11-28 17:25:37 +02:00
Björn Steinhagen a7b3ae8780 refactor(grasshopper): appending "with Token" to "Speckle Model URL" component name (#1201) 2025-11-28 11:41:47 +00:00
Björn Steinhagen 5da534aeb7 refactor(grasshopper): renaming component naming for automatic loading (#1200) 2025-11-28 13:37:26 +02:00
Oğuzhan Koral 0b246cf95c Merge pull request #1193 from specklesystems/dev
.NET Build and Publish / build-connectors (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
Update dev into main
2025-11-18 15:50:22 +03:00
17 changed files with 116 additions and 76 deletions
@@ -29,8 +29,8 @@
<ItemGroup>
<PackageReference Include="GrasshopperAsyncComponent" />
<PackageReference Include="RhinoCommon" IncludeAssets="compile; build" PrivateAssets="all" />
<PackageReference Include="Grasshopper" IncludeAssets="compile; build" PrivateAssets="all" />
<PackageReference Include="RhinoCommon" IncludeAssets="compile; build" PrivateAssets="all" VersionOverride="8.9.24194.18121"/>
<PackageReference Include="Grasshopper" IncludeAssets="compile; build" PrivateAssets="all" VersionOverride="8.9.24194.18121"/>
<PackageReference Include="System.Resources.Extensions" />
</ItemGroup>
@@ -15,7 +15,7 @@ public class TokenUrlComponent : GH_Component
{
public TokenUrlComponent()
: base(
"Speckle Model URL",
"Speckle Model URL with Token",
"URL",
"Create a Speckle model link using URL and developer token",
ComponentCategories.PRIMARY_RIBBON,
@@ -130,7 +130,7 @@ public class ReceiveAsyncComponent : GH_AsyncComponent<ReceiveAsyncComponent>
{
var autoReceiveMi = Menu_AppendItem(
menu,
"Load automatically",
"Load new versions automatically",
(s, e) =>
{
AutoReceive = !AutoReceive;
@@ -3,7 +3,9 @@ using Rhino.Geometry;
using Speckle.Connectors.Common.Operations.Receive;
using Speckle.Connectors.GrasshopperShared.HostApp;
using Speckle.Connectors.GrasshopperShared.Parameters;
using Speckle.Converters.Common;
using Speckle.Converters.Common.ToHost;
using Speckle.Converters.Rhino;
using Speckle.Sdk;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;
@@ -29,6 +31,7 @@ internal sealed class LocalToGlobalMapHandler
// injected via constructor (DI-managed)
private readonly IDataObjectInstanceRegistry _dataObjectInstanceRegistry;
private readonly ILogger<LocalToGlobalMapHandler> _logger;
private readonly IConverterSettingsStore<RhinoConversionSettings> _settingsStore;
// set via Initialize() method (per-operation data)
private TraversalContextUnpacker _traversalContextUnpacker = null!;
@@ -41,11 +44,13 @@ internal sealed class LocalToGlobalMapHandler
public LocalToGlobalMapHandler(
IDataObjectInstanceRegistry dataObjectInstanceRegistry,
ILogger<LocalToGlobalMapHandler> logger
ILogger<LocalToGlobalMapHandler> logger,
IConverterSettingsStore<RhinoConversionSettings> settingsStore
)
{
_dataObjectInstanceRegistry = dataObjectInstanceRegistry;
_logger = logger;
_settingsStore = settingsStore;
}
/// <summary>
@@ -368,7 +373,17 @@ internal sealed class LocalToGlobalMapHandler
{
// deep copy and transform the geometry
var transformedWrapper = definitionObject.DeepCopy();
// transform the GeometryBase
transformedWrapper.GeometryBase.NotNull().Transform(transform);
// keep Base and GeometryBase in sync (fixed as of CNX-2847)
transformedWrapper.Base = SpeckleConversionContext.Current.ConvertToSpeckle(transformedWrapper.GeometryBase);
// preserve metadata from original Base
transformedWrapper.Base.applicationId = definitionObject.Base.applicationId;
transformedWrapper.Base["units"] = _settingsStore.Current.SpeckleUnits;
resolvedGeometries.Add(transformedWrapper);
}
}
@@ -161,12 +161,7 @@ public partial class SpecklePropertyGroupGoo : GH_Goo<Dictionary<string, ISpeckl
else
{
SpecklePropertyGoo entry = new();
if (!entry.CastFrom(kvp.Value))
{
throw new ArgumentException(
$"Property '{kvp.Key}' has unsupported type '{kvp.Value?.GetType().Name ?? "null"}'"
);
}
entry.CastFrom(kvp.Value);
val = entry;
}
@@ -8,6 +8,7 @@
<StartProgram>$(ProgramFiles)\Rhino $(RhinoVersion)\System\Rhino.exe</StartProgram>
<EnableWindowsTargeting>true</EnableWindowsTargeting>
<UseWpf>true</UseWpf>
<PlatformTarget>x64</PlatformTarget>
<UseWindowsForms>true</UseWindowsForms>
<GenerateResourceUsePreserializedResources>true</GenerateResourceUsePreserializedResources>
</PropertyGroup>
@@ -7,14 +7,15 @@
<TargetExt>.rhp</TargetExt>
<StartProgram>$(ProgramFiles)\Rhino $(RhinoVersion)\System\Rhino.exe</StartProgram>
<EnableWindowsTargeting>true</EnableWindowsTargeting>
<PlatformTarget>x64</PlatformTarget>
<UseWpf>true</UseWpf>
<UseWindowsForms>true</UseWindowsForms>
<GenerateResourceUsePreserializedResources>true</GenerateResourceUsePreserializedResources>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="RhinoCommon" IncludeAssets="compile; build" PrivateAssets="all" />
<PackageReference Include="RhinoWindows" IncludeAssets="compile; build" PrivateAssets="all" />
<PackageReference Include="RhinoCommon" IncludeAssets="compile; build" PrivateAssets="all" VersionOverride="8.9.24194.18121"/>
<PackageReference Include="RhinoWindows" IncludeAssets="compile; build" PrivateAssets="all" VersionOverride="8.9.24194.18121"/>
</ItemGroup>
<ItemGroup>
@@ -19,8 +19,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="RhinoCommon" IncludeAssets="compile; build" PrivateAssets="all" VersionOverride="8.21.25188.17001"/>
<PackageReference Include="RhinoWindows" IncludeAssets="compile; build" PrivateAssets="all" VersionOverride="8.21.25188.17001"/>
<PackageReference Include="RhinoCommon" IncludeAssets="compile; build" PrivateAssets="all"/>
<PackageReference Include="RhinoWindows" IncludeAssets="compile; build" PrivateAssets="all"/>
</ItemGroup>
<ItemGroup>
@@ -29,20 +29,20 @@
},
"RhinoCommon": {
"type": "Direct",
"requested": "[8.21.25188.17001, )",
"resolved": "8.21.25188.17001",
"contentHash": "Wo6JXheyDBvilyIwDY6xZCQJC4170jzAlTSlMgh8yokUY+vYyCl4KJVXZofIOynNt/xx5wLqb2On5gZZekXR6w==",
"requested": "[8.25.25328.11001, )",
"resolved": "8.25.25328.11001",
"contentHash": "PDKR9GwqyUXUkTulV4J0dzDIf/aWqSJkL7nkS8ReAx8xhnt/+RQpE8gTjOSCmkSU2tjG6WzclowbTxwMTU7VAA==",
"dependencies": {
"System.Drawing.Common": "7.0.0"
}
},
"RhinoWindows": {
"type": "Direct",
"requested": "[8.21.25188.17001, )",
"resolved": "8.21.25188.17001",
"contentHash": "9zqCorcLRBeiW/j1RTwUS4E7bnZetAdA9WDdtd/AQccjOpxdtw76wdN+ciyQ6qslseWkwZ9qSBeh7QaM800Ntw==",
"requested": "[8.25.25328.11001, )",
"resolved": "8.25.25328.11001",
"contentHash": "I/+++piwtYTue+iAAQqcMF5QlontqwNnC7Leyhiv2FiF8JpAl6K44ZsJqB7ZEUC6ns0LDfa3mbFzQwUfHwYumQ==",
"dependencies": {
"RhinoCommon": "[8.21.25188.17001]"
"RhinoCommon": "[8.25.25328.11001]"
}
},
"Speckle.InterfaceGenerator": {
@@ -74,15 +74,18 @@ public sealed class DisplayValueExtractor
}
return areaDisplay;
// NOTE: this is only for Rebar and not AreaReinforcement, RebarInSystem
// AreaReinforcement and RebarInSystem pass through GetGeometryDisplayValue which get DisplayValues as per hostApp
// Rebar elements need special handling as get_Geometry() doesn't work properly
// We either represent them as centerlines or as solids based on settings
// Rebar: get_Geometry() returns null, use GetTransformedCenterlineCurves/GetFullGeometryForView + apply reference point transform
case DB.Structure.Rebar rebar:
return _converterSettings.Current.SendRebarsAsVolumetric
? GetRebarVolumetricDisplayValue(rebar)
: GetRebarCenterlineDisplayValue(rebar);
// AreaReinforcement/PathReinforcement get_Geometry() returns curves in document coordinates
// unlike Rebar which needs reference point transform applied, these are already correct
case DB.Structure.AreaReinforcement:
case DB.Structure.PathReinforcement:
return GetAreaReinforcementDisplayValue(element);
// handle specific types of objects with multiple parts or children
// curtain and stacked walls should have their display values in their children
case DB.Wall wall:
@@ -107,7 +110,7 @@ public sealed class DisplayValueExtractor
using DB.Transform? compoundTransform =
localToDocument is not null && documentToWorld is not null
? documentToWorld.Multiply(localToDocument)
: localToDocument; // don't want to accidentally dispose of the ReferencePointTransform
: localToDocument;
DB.Transform? localToWorld = compoundTransform ?? documentToWorld;
@@ -423,7 +426,7 @@ public sealed class DisplayValueExtractor
return false; // exit fast on a potential hot path
}
DB.GraphicsStyle? bjk = null; // ask ogu why this variable is named like this
DB.GraphicsStyle? bjk; // ask ogu why this variable is named like this
if (!_graphicStyleCache.ContainsKey(geomObj.GraphicsStyleId.ToString().NotNull()))
{
@@ -547,8 +550,9 @@ public sealed class DisplayValueExtractor
if (geometryElements != null)
{
DB.Transform? documentToWorld = _converterSettings.Current.ReferencePointTransform?.Inverse;
SortGeometry(rebar, collections, geometryElements, null);
return ProcessGeometryCollections(rebar, collections, null);
return ProcessGeometryCollections(rebar, collections, documentToWorld);
}
// Return empty list if no geometry is found - imo not critical
@@ -589,16 +593,40 @@ public sealed class DisplayValueExtractor
)
);
}
DB.Transform? documentToWorld = _converterSettings.Current.ReferencePointTransform?.Inverse;
List<DisplayValueResult> displayValue = new();
foreach (var curve in curves)
{
displayValue.Add(DisplayValueResult.WithoutTransform(GetCurveDisplayValue(curve)));
if (documentToWorld is not null)
{
using var transformedCurve = curve.CreateTransformed(documentToWorld);
displayValue.Add(DisplayValueResult.WithoutTransform(GetCurveDisplayValue(transformedCurve)));
}
else
{
displayValue.Add(DisplayValueResult.WithoutTransform(GetCurveDisplayValue(curve)));
}
}
return displayValue;
}
/// <summary>
/// Gets display value for AreaReinforcement and PathReinforcement.
/// </summary>
/// <remarks>
/// These elements' get_Geometry() returns curves already in document coordinates.
/// Unlike Rebar.GetTransformedCenterlineCurves() which requires reference point transform,
/// these curves should not be transformed - they're already in the correct space.
/// </remarks>
private List<DisplayValueResult> GetAreaReinforcementDisplayValue(DB.Element element)
{
var collections = GetSortedGeometryFromElement(element, null, null);
// pass null for transform - curves are already in correct document coordinates
return ProcessGeometryCollections(element, collections, null);
}
/// <summary>
/// Represents sorted collections of different geometry types extracted from an element.
/// Used to pass multiple geometry collections as a single parameter to improve code readability
@@ -7,11 +7,11 @@
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net48'">
<PackageReference Include="RhinoCommon" IncludeAssets="compile; build" PrivateAssets="all" />
<PackageReference Include="RhinoCommon" IncludeAssets="compile; build" PrivateAssets="all" VersionOverride="8.9.24194.18121"/>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' != 'net48'">
<PackageReference Include="RhinoCommon" IncludeAssets="compile; build" PrivateAssets="all" VersionOverride="8.21.25188.17001"/>
<PackageReference Include="RhinoCommon" IncludeAssets="compile; build" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
@@ -346,9 +346,9 @@
},
"RhinoCommon": {
"type": "Direct",
"requested": "[8.21.25188.17001, )",
"resolved": "8.21.25188.17001",
"contentHash": "Wo6JXheyDBvilyIwDY6xZCQJC4170jzAlTSlMgh8yokUY+vYyCl4KJVXZofIOynNt/xx5wLqb2On5gZZekXR6w==",
"requested": "[8.25.25328.11001, )",
"resolved": "8.25.25328.11001",
"contentHash": "PDKR9GwqyUXUkTulV4J0dzDIf/aWqSJkL7nkS8ReAx8xhnt/+RQpE8gTjOSCmkSU2tjG6WzclowbTxwMTU7VAA==",
"dependencies": {
"System.Drawing.Common": "7.0.0"
}
+2 -2
View File
@@ -28,10 +28,10 @@
<PackageVersion Include="NUnit.Analyzers" Version="4.2.0" />
<PackageVersion Include="NUnit3TestAdapter" version="4.6.0" />
<PackageVersion Include="Revit.Async" Version="2.1.1" />
<PackageVersion Include="RhinoCommon" Version="8.9.24194.18121" />
<PackageVersion Include="RhinoCommon" Version="8.25.25328.11001" />
<PackageVersion Include="Rhino.Inside" Version="8.0.7-beta" />
<PackageVersion Include="Grasshopper" Version="8.9.24194.18121" />
<PackageVersion Include="RhinoWindows" Version="8.9.24194.18121" />
<PackageVersion Include="RhinoWindows" Version="8.25.25328.11001" />
<PackageVersion Include="Semver" Version="3.0.0" />
<PackageVersion Include="Serilog.Formatting.Compact" Version="3.0.0" />
<PackageVersion Include="Speckle.CSI.API" Version="2.4.0" />
@@ -8,6 +8,7 @@ using Speckle.Connectors.Logging;
using Speckle.Importers.JobProcessor.Domain;
using Speckle.Importers.JobProcessor.JobHandlers;
using Speckle.Importers.JobProcessor.JobQueue;
using Speckle.Sdk;
using Speckle.Sdk.Api;
using Speckle.Sdk.Api.GraphQL.Inputs;
using Speckle.Sdk.Common;
@@ -29,6 +30,24 @@ internal sealed class JobProcessorInstance(
private static readonly TimeSpan s_idleTimeout = TimeSpan.FromSeconds(1);
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
{
try
{
await RunJobProcessorLoop(cancellationToken);
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
logger.LogError(ex, "Job Processor crashed");
Environment.Exit(1); //This is the only reliable way I've managed to figure out how to get windows services retry policy to actually kick in (see https://github.com/dotnet/runtime/issues/67146)
throw;
}
}
private async Task RunJobProcessorLoop(CancellationToken cancellationToken)
{
await using var connection = await repository.SetupConnection(cancellationToken).ConfigureAwait(false);
@@ -180,6 +199,11 @@ internal sealed class JobProcessorInstance(
{
logger.LogError(new AggregateException(ex, ex2), "Failed to report failure status");
await repository.ReturnJobToQueued(connection, job.Id, cancellationToken);
if (ex2.IsFatal())
{
throw;
}
}
}
finally
@@ -10,27 +10,14 @@ namespace Speckle.Importers.JobProcessor;
public static class Program
{
public static async Task<int> Main(string[] args)
public static async Task Main(string[] args)
{
// Dapper doesn't understand how to handle JSON deserialization, so we need to tell it what types can be deserialzied
SqlMapper.AddTypeHandler(new JsonHandler<FileimportPayload>());
var host = ConfigureAppHost(args);
var backgroundServiceTasks = host
.Services.GetServices<IHostedService>()
.OfType<BackgroundService>()
.Select(s => s.ExecuteTask);
await host.RunAsync();
if (backgroundServiceTasks.Any(t => t?.IsFaulted == true))
{
//https://github.com/dotnet/runtime/issues/67146
return -1;
}
return 0;
}
private static IHost ConfigureAppHost(string[] args)
@@ -50,15 +37,4 @@ public static class Program
return builder.Build();
}
private static void ConfigureTopLevelLogs(ILogger logger)
{
TaskScheduler.UnobservedTaskException += (_, eventArgs) =>
logger.LogCritical(eventArgs.Exception, "Unobserved Task Exception");
AppDomain.CurrentDomain.UnhandledException += (sender, eventArgs) =>
{
logger.LogCritical(eventArgs.ExceptionObject as Exception, "Unhandled exception occurred in the AppDomain");
};
}
}
@@ -8,9 +8,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="RhinoCommon" IncludeAssets="compile; build" PrivateAssets="all" VersionOverride="8.24.25281.15001"/>
<PackageReference Include="Grasshopper" IncludeAssets="compile; build" PrivateAssets="all" VersionOverride="8.24.25281.15001"/>
<PackageReference Include="RhinoWindows" IncludeAssets="compile; build" PrivateAssets="all" VersionOverride="8.24.25281.15001"/>
<PackageReference Include="RhinoCommon" IncludeAssets="compile; build" PrivateAssets="all" VersionOverride="8.25.25328.11001"/>
<PackageReference Include="Grasshopper" IncludeAssets="compile; build" PrivateAssets="all" VersionOverride="8.25.25328.11001"/>
<PackageReference Include="RhinoWindows" IncludeAssets="compile; build" PrivateAssets="all" VersionOverride="8.25.25328.11001"/>
<PackageReference Include="Rhino.Inside" />
</ItemGroup>
@@ -4,11 +4,11 @@
"net8.0-windows7.0": {
"Grasshopper": {
"type": "Direct",
"requested": "[8.24.25281.15001, )",
"resolved": "8.24.25281.15001",
"contentHash": "TEtB8nElTvhMJctLhv8UC1v6jscYdTgsoRQIr31ewGZr6cpgGtQTBmUk26/9ZvQxXCgOp7Y4EZdcEZkmqCm1SQ==",
"requested": "[8.25.25328.11001, )",
"resolved": "8.25.25328.11001",
"contentHash": "1uFL9pmgCEbYFd1b3JFGHaLEjQuRgFsiRHmP5u73mdEMdO6+5F/pNV1dQZr3YGLDovUmgrc+jmpsme7wr/J01A==",
"dependencies": {
"RhinoCommon": "[8.24.25281.15001]"
"RhinoCommon": "[8.25.25328.11001]"
}
},
"Microsoft.NETFramework.ReferenceAssemblies": {
@@ -48,20 +48,20 @@
},
"RhinoCommon": {
"type": "Direct",
"requested": "[8.24.25281.15001, )",
"resolved": "8.24.25281.15001",
"contentHash": "K8dd7DJvEUUYHpwkyyxr/ojK3e8swlE0STeyG+ulVWkWNHK6gIRDxMYCwB7kNyHHMgpr/vpQlMgR3SVD1GoMTA==",
"requested": "[8.25.25328.11001, )",
"resolved": "8.25.25328.11001",
"contentHash": "PDKR9GwqyUXUkTulV4J0dzDIf/aWqSJkL7nkS8ReAx8xhnt/+RQpE8gTjOSCmkSU2tjG6WzclowbTxwMTU7VAA==",
"dependencies": {
"System.Drawing.Common": "7.0.0"
}
},
"RhinoWindows": {
"type": "Direct",
"requested": "[8.24.25281.15001, )",
"resolved": "8.24.25281.15001",
"contentHash": "JbG98P80Hskpomzx1xhqFoz2WmVnhjda0noQyZE+dE678ZKmw+O3i/iIjaN5jydXvTu/fZXRzQmEDL7M7Ura8g==",
"requested": "[8.25.25328.11001, )",
"resolved": "8.25.25328.11001",
"contentHash": "I/+++piwtYTue+iAAQqcMF5QlontqwNnC7Leyhiv2FiF8JpAl6K44ZsJqB7ZEUC6ns0LDfa3mbFzQwUfHwYumQ==",
"dependencies": {
"RhinoCommon": "[8.24.25281.15001]"
"RhinoCommon": "[8.25.25328.11001]"
}
},
"Speckle.InterfaceGenerator": {