diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
index 822d8977c..9a0678092 100644
--- a/.github/workflows/pr.yml
+++ b/.github/workflows/pr.yml
@@ -29,7 +29,7 @@ jobs:
run: ./build.sh test-and-pack
- name: Upload coverage reports to Codecov with GitHub Action
- uses: codecov/codecov-action@v5
+ uses: codecov/codecov-action@v6
with:
files: Converters/**/coverage.xml
token: ${{ secrets.CODECOV_TOKEN }}
diff --git a/.gitignore b/.gitignore
index 2646b24de..af18aab41 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,5 @@ tools
coverage.xml
output/
Images/Thumbs.db
+
+.claude/
diff --git a/Build/Consts.cs b/Build/Consts.cs
index 3e0b119c5..614c69717 100644
--- a/Build/Consts.cs
+++ b/Build/Consts.cs
@@ -43,6 +43,7 @@ public static class Consts
new("Connectors/Autocad/Speckle.Connectors.Civil3d2026", "net8.0-windows")
]
),
+ new("plant3d", [new("Connectors/Autocad/Speckle.Connectors.Plant3d2026", "net8.0-windows")]),
new(
"navisworks",
[
diff --git a/CodeMetricsConfig.txt b/CodeMetricsConfig.txt
index e69bf2348..898cf21de 100644
--- a/CodeMetricsConfig.txt
+++ b/CodeMetricsConfig.txt
@@ -1,4 +1,4 @@
CA1502: 25
CA1501: 5
-CA1506(Method): 50
+CA1506(Method): 60
CA1506(Type): 95
diff --git a/Connectors/Autocad/Directory.Build.targets b/Connectors/Autocad/Directory.Build.targets
index 5d93d9f50..36e48644e 100644
--- a/Connectors/Autocad/Directory.Build.targets
+++ b/Connectors/Autocad/Directory.Build.targets
@@ -35,4 +35,23 @@
$(ProgramW6432)\Autodesk\AutoCAD $(Civil3DVersion)\acad.exe
/product C3D
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Program
+ $(ProgramW6432)\Autodesk\AutoCAD $(Plant3DVersion)\acad.exe
+ /product PLNT3D
+
diff --git a/Connectors/Autocad/Speckle.Connectors.Autocad2022/packages.lock.json b/Connectors/Autocad/Speckle.Connectors.Autocad2022/packages.lock.json
index 8bb684f74..946d549ab 100644
--- a/Connectors/Autocad/Speckle.Connectors.Autocad2022/packages.lock.json
+++ b/Connectors/Autocad/Speckle.Connectors.Autocad2022/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -283,7 +283,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -314,7 +314,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -358,11 +358,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Connectors/Autocad/Speckle.Connectors.Autocad2023/packages.lock.json b/Connectors/Autocad/Speckle.Connectors.Autocad2023/packages.lock.json
index 0890cd151..72d9dd051 100644
--- a/Connectors/Autocad/Speckle.Connectors.Autocad2023/packages.lock.json
+++ b/Connectors/Autocad/Speckle.Connectors.Autocad2023/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -283,7 +283,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -314,7 +314,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -358,11 +358,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Connectors/Autocad/Speckle.Connectors.Autocad2024/packages.lock.json b/Connectors/Autocad/Speckle.Connectors.Autocad2024/packages.lock.json
index 1e9fd7977..a5fee056d 100644
--- a/Connectors/Autocad/Speckle.Connectors.Autocad2024/packages.lock.json
+++ b/Connectors/Autocad/Speckle.Connectors.Autocad2024/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -283,7 +283,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -315,7 +315,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -359,11 +359,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Connectors/Autocad/Speckle.Connectors.Autocad2025/packages.lock.json b/Connectors/Autocad/Speckle.Connectors.Autocad2025/packages.lock.json
index 9220739d9..d5e91a1ec 100644
--- a/Connectors/Autocad/Speckle.Connectors.Autocad2025/packages.lock.json
+++ b/Connectors/Autocad/Speckle.Connectors.Autocad2025/packages.lock.json
@@ -157,8 +157,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -166,13 +166,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -230,7 +230,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -262,7 +262,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -306,11 +306,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
},
diff --git a/Connectors/Autocad/Speckle.Connectors.Autocad2026/packages.lock.json b/Connectors/Autocad/Speckle.Connectors.Autocad2026/packages.lock.json
index 988203688..ce0bd002d 100644
--- a/Connectors/Autocad/Speckle.Connectors.Autocad2026/packages.lock.json
+++ b/Connectors/Autocad/Speckle.Connectors.Autocad2026/packages.lock.json
@@ -157,8 +157,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -166,13 +166,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -230,7 +230,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -262,7 +262,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -306,11 +306,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
},
diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/DependencyInjection/AutocadConnectorModule.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/DependencyInjection/AutocadConnectorModule.cs
index 6e199726f..656e65b96 100644
--- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/DependencyInjection/AutocadConnectorModule.cs
+++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/DependencyInjection/AutocadConnectorModule.cs
@@ -18,6 +18,10 @@ public static class AutocadConnectorModule
// Send
serviceCollection.LoadSend();
serviceCollection.AddScoped, AutocadRootObjectBuilder>();
+ serviceCollection.AddScoped<
+ IRootContinuousTraversalBuilder,
+ AutocadContinuousTraversalBuilder
+ >();
// Receive
serviceCollection.LoadReceive();
diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/HostApp/AutocadColorBaker.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/HostApp/AutocadColorBaker.cs
index c02e1d839..4c74c1194 100644
--- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/HostApp/AutocadColorBaker.cs
+++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/HostApp/AutocadColorBaker.cs
@@ -1,9 +1,9 @@
using Autodesk.AutoCAD.Colors;
using Microsoft.Extensions.Logging;
-using Speckle.Connectors.Common.Operations;
using Speckle.InterfaceGenerator;
using Speckle.Sdk;
using Speckle.Sdk.Models.Proxies;
+using Speckle.Sdk.Pipelines.Progress;
using AutocadColor = Autodesk.AutoCAD.Colors.Color;
namespace Speckle.Connectors.Autocad.HostApp;
diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/HostApp/AutocadInstanceBaker.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/HostApp/AutocadInstanceBaker.cs
index e1373f54f..3d7782c99 100644
--- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/HostApp/AutocadInstanceBaker.cs
+++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/HostApp/AutocadInstanceBaker.cs
@@ -5,7 +5,6 @@ using Microsoft.Extensions.Logging;
using Speckle.Connectors.Autocad.HostApp.Extensions;
using Speckle.Connectors.Common.Conversion;
using Speckle.Connectors.Common.Instances;
-using Speckle.Connectors.Common.Operations;
using Speckle.Converters.Autocad;
using Speckle.Converters.Common;
using Speckle.DoubleNumerics;
@@ -16,6 +15,7 @@ using Speckle.Sdk.Dependencies;
using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Collections;
using Speckle.Sdk.Models.Instances;
+using Speckle.Sdk.Pipelines.Progress;
using AutocadColor = Autodesk.AutoCAD.Colors.Color;
namespace Speckle.Connectors.Autocad.HostApp;
diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/HostApp/AutocadMaterialBaker.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/HostApp/AutocadMaterialBaker.cs
index 1e09a7f2b..1265ee081 100644
--- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/HostApp/AutocadMaterialBaker.cs
+++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/HostApp/AutocadMaterialBaker.cs
@@ -3,12 +3,12 @@ using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.GraphicsInterface;
using Microsoft.Extensions.Logging;
using Speckle.Connectors.Common.Conversion;
-using Speckle.Connectors.Common.Operations;
using Speckle.InterfaceGenerator;
using Speckle.Objects.Other;
using Speckle.Sdk;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;
+using Speckle.Sdk.Pipelines.Progress;
using Material = Autodesk.AutoCAD.DatabaseServices.Material;
using RenderMaterial = Speckle.Objects.Other.RenderMaterial;
diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Receive/AutocadHostObjectBaseBuilder.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Receive/AutocadHostObjectBaseBuilder.cs
index fab625077..b06fa98e2 100644
--- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Receive/AutocadHostObjectBaseBuilder.cs
+++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Receive/AutocadHostObjectBaseBuilder.cs
@@ -12,6 +12,7 @@ using Speckle.Sdk.Dependencies;
using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Collections;
using Speckle.Sdk.Models.Instances;
+using Speckle.Sdk.Pipelines.Progress;
using AutocadColor = Autodesk.AutoCAD.Colors.Color;
namespace Speckle.Connectors.Autocad.Operations.Receive;
diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadContinuousTraversalBaseBuilder.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadContinuousTraversalBaseBuilder.cs
new file mode 100644
index 000000000..67ae43e14
--- /dev/null
+++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadContinuousTraversalBaseBuilder.cs
@@ -0,0 +1,197 @@
+using System.Diagnostics.CodeAnalysis;
+using Autodesk.AutoCAD.DatabaseServices;
+using Microsoft.Extensions.Logging;
+using Speckle.Connectors.Autocad.HostApp;
+using Speckle.Connectors.Common.Builders;
+using Speckle.Connectors.Common.Caching;
+using Speckle.Connectors.Common.Conversion;
+using Speckle.Connectors.Common.Extensions;
+using Speckle.Connectors.Common.Operations;
+using Speckle.Converters.Common;
+using Speckle.Sdk;
+using Speckle.Sdk.Logging;
+using Speckle.Sdk.Models;
+using Speckle.Sdk.Models.Collections;
+using Speckle.Sdk.Models.Instances;
+using Speckle.Sdk.Pipelines.Progress;
+using Speckle.Sdk.Pipelines.Send;
+
+namespace Speckle.Connectors.Autocad.Operations.Send;
+
+///
+/// Abstract base class for AutoCAD continuous traversal builders that stream objects through a
+/// for packfile-based uploads. Same conversion logic as
+/// , but processes elements through the pipeline.
+///
+public abstract class AutocadContinuousTraversalBaseBuilder : IRootContinuousTraversalBuilder
+{
+ private readonly IRootToSpeckleConverter _converter;
+ private readonly string[] _documentPathSeparator = ["\\"];
+ private readonly ISendConversionCache _sendConversionCache;
+ private readonly AutocadInstanceUnpacker _instanceUnpacker;
+ private readonly AutocadMaterialUnpacker _materialUnpacker;
+ private readonly AutocadColorUnpacker _colorUnpacker;
+ private readonly AutocadGroupUnpacker _groupUnpacker;
+ private readonly ILogger _logger;
+ private readonly ISdkActivityFactory _activityFactory;
+
+ protected AutocadContinuousTraversalBaseBuilder(
+ IRootToSpeckleConverter converter,
+ ISendConversionCache sendConversionCache,
+ AutocadInstanceUnpacker instanceObjectManager,
+ AutocadMaterialUnpacker materialUnpacker,
+ AutocadColorUnpacker colorUnpacker,
+ AutocadGroupUnpacker groupUnpacker,
+ ILogger logger,
+ ISdkActivityFactory activityFactory
+ )
+ {
+ _converter = converter;
+ _sendConversionCache = sendConversionCache;
+ _instanceUnpacker = instanceObjectManager;
+ _materialUnpacker = materialUnpacker;
+ _colorUnpacker = colorUnpacker;
+ _groupUnpacker = groupUnpacker;
+ _logger = logger;
+ _activityFactory = activityFactory;
+ }
+
+ [SuppressMessage(
+ "Maintainability",
+ "CA1506:Avoid excessive class coupling",
+ Justification = """
+ It is already simplified but has many different references since it is a builder. Do not know can we simplify it now.
+ Later we might consider to refactor proxies from one proxy manager? but we do not know the shape of it all potential
+ proxy classes yet. So I'm supressing this one now!!!
+ """
+ )]
+ public async Task Build(
+ IReadOnlyList objects,
+ string projectId,
+ SendPipeline sendPipeline,
+ IProgress onOperationProgressed,
+ CancellationToken cancellationToken
+ )
+ {
+ // 0 - Init the root
+ Collection root =
+ new()
+ {
+ name = Application
+ .DocumentManager.CurrentDocument.Name.Split(_documentPathSeparator, StringSplitOptions.None)
+ .Reverse()
+ .First()
+ };
+
+ Document doc = Application.DocumentManager.CurrentDocument;
+ using Transaction tr = doc.Database.TransactionManager.StartTransaction();
+
+ // 1 - Unpack the instances
+ var (atomicObjects, _, instanceProxies, instanceDefinitionProxies) = _instanceUnpacker.UnpackSelection(objects);
+ root[ProxyKeys.INSTANCE_DEFINITION] = instanceDefinitionProxies;
+
+ // 2 - Unpack the groups
+ root[ProxyKeys.GROUP] = _groupUnpacker.UnpackGroups(atomicObjects);
+ using (var _ = _activityFactory.Start("Converting objects"))
+ {
+ // 3 - Convert atomic objects and process through pipeline
+ List usedAcadLayers = new();
+ List results = new();
+ int count = 0;
+ foreach (var (entity, applicationId) in atomicObjects)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ (Collection objectCollection, LayerTableRecord? autocadLayer) = CreateObjectCollection(entity, tr);
+
+ if (autocadLayer is not null)
+ {
+ usedAcadLayers.Add(autocadLayer);
+ root.elements.Add(objectCollection);
+ }
+
+ var result = await ConvertAutocadEntity(
+ entity,
+ applicationId,
+ objectCollection,
+ instanceProxies,
+ projectId,
+ sendPipeline
+ );
+ results.Add(result);
+
+ onOperationProgressed.Report(
+ new($"Converting objects... ({count:N0} / {atomicObjects.Count:N0})", (double)++count / atomicObjects.Count)
+ );
+ }
+
+ if (results.All(x => x.Status == Status.ERROR))
+ {
+ throw new SpeckleException("Failed to convert all objects.");
+ }
+
+ // 4 - Unpack the render material proxies
+ root[ProxyKeys.RENDER_MATERIAL] = _materialUnpacker.UnpackMaterials(atomicObjects, usedAcadLayers);
+
+ // 5 - Unpack the color proxies
+ root[ProxyKeys.COLOR] = _colorUnpacker.UnpackColors(atomicObjects, usedAcadLayers);
+
+ // add any additional properties (most likely from verticals)
+ AddAdditionalProxiesToRoot(root);
+
+ // Process root collection and wait for all uploads
+ await sendPipeline.Process(root);
+ await sendPipeline.WaitForUpload();
+
+ return new RootObjectBuilderResult(root, results);
+ }
+ }
+
+ public virtual (Collection, LayerTableRecord?) CreateObjectCollection(Entity entity, Transaction tr)
+ {
+ return (new(), null);
+ }
+
+ public virtual void AddAdditionalProxiesToRoot(Collection rootCollection)
+ {
+ return;
+ }
+
+ private async Task ConvertAutocadEntity(
+ Entity entity,
+ string applicationId,
+ Collection collectionHost,
+ IReadOnlyDictionary instanceProxies,
+ string projectId,
+ SendPipeline sendPipeline
+ )
+ {
+ string sourceType = entity.GetType().ToString();
+ try
+ {
+ Base converted;
+ if (entity is BlockReference && instanceProxies.TryGetValue(applicationId, out InstanceProxy? instanceProxy))
+ {
+ converted = instanceProxy;
+ }
+ else if (_sendConversionCache.TryGetValue(projectId, applicationId, out ObjectReference? value))
+ {
+ converted = value;
+ }
+ else
+ {
+ converted = _converter.Convert(entity);
+ converted.applicationId = applicationId;
+ }
+
+ // NOTE: this is the main part that differentiate from the main root object builder
+ var reference = await sendPipeline.Process(converted).ConfigureAwait(false);
+ collectionHost.elements.Add(reference);
+ return new(Status.SUCCESS, applicationId, sourceType, reference);
+ }
+ catch (Exception ex) when (!ex.IsFatal())
+ {
+ _logger.LogSendConversionError(ex, sourceType);
+ return new(Status.ERROR, applicationId, sourceType, null, ex);
+ }
+ }
+}
diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadContinuousTraversalBuilder.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadContinuousTraversalBuilder.cs
new file mode 100644
index 000000000..eb7e6b893
--- /dev/null
+++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadContinuousTraversalBuilder.cs
@@ -0,0 +1,46 @@
+using Autodesk.AutoCAD.DatabaseServices;
+using Microsoft.Extensions.Logging;
+using Speckle.Connectors.Autocad.HostApp;
+using Speckle.Connectors.Common.Caching;
+using Speckle.Converters.Common;
+using Speckle.Sdk.Logging;
+using Speckle.Sdk.Models.Collections;
+
+namespace Speckle.Connectors.Autocad.Operations.Send;
+
+public sealed class AutocadContinuousTraversalBuilder : AutocadContinuousTraversalBaseBuilder
+{
+ private readonly AutocadLayerUnpacker _layerUnpacker;
+
+ public AutocadContinuousTraversalBuilder(
+ AutocadLayerUnpacker layerUnpacker,
+ IRootToSpeckleConverter converter,
+ ISendConversionCache sendConversionCache,
+ AutocadInstanceUnpacker instanceObjectManager,
+ AutocadMaterialUnpacker materialUnpacker,
+ AutocadColorUnpacker colorUnpacker,
+ AutocadGroupUnpacker groupUnpacker,
+ ILogger logger,
+ ISdkActivityFactory activityFactory
+ )
+ : base(
+ converter,
+ sendConversionCache,
+ instanceObjectManager,
+ materialUnpacker,
+ colorUnpacker,
+ groupUnpacker,
+ logger,
+ activityFactory
+ )
+ {
+ _layerUnpacker = layerUnpacker;
+ }
+
+ public override (Collection, LayerTableRecord?) CreateObjectCollection(Entity entity, Transaction tr)
+ {
+ Layer layer = _layerUnpacker.GetOrCreateSpeckleLayer(entity, tr, out LayerTableRecord? autocadLayer);
+
+ return (layer, autocadLayer);
+ }
+}
diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBaseBuilder.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBaseBuilder.cs
index 20b5660d2..ba3befb4c 100644
--- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBaseBuilder.cs
+++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBaseBuilder.cs
@@ -16,6 +16,7 @@ using Speckle.Sdk.Logging;
using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Collections;
using Speckle.Sdk.Models.Instances;
+using Speckle.Sdk.Pipelines.Progress;
namespace Speckle.Connectors.Autocad.Operations.Send;
diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Plugin/AppUtils.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Plugin/AppUtils.cs
index f50818580..100f488c7 100644
--- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Plugin/AppUtils.cs
+++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Plugin/AppUtils.cs
@@ -7,6 +7,8 @@ public static class AppUtils
public static Speckle.Sdk.Application App =>
#if CIVIL3D
HostApplications.Civil3D;
+#elif PLANT3D
+ HostApplications.Plant3D;
#elif AUTOCAD
HostApplications.AutoCAD;
#else
@@ -14,11 +16,11 @@ public static class AppUtils
#endif
public static HostAppVersion Version =>
-#if AUTOCAD2026 || CIVIL3D2026
+#if AUTOCAD2026 || CIVIL3D2026 || PLANT3D2026
HostAppVersion.v2026;
-#elif AUTOCAD2025 || CIVIL3D2025
+#elif AUTOCAD2025 || CIVIL3D2025 || PLANT3D2025
HostAppVersion.v2025;
-#elif AUTOCAD2024 || CIVIL3D2024
+#elif AUTOCAD2024 || CIVIL3D2024 || PLANT3D2024
HostAppVersion.v2024;
#elif AUTOCAD2023|| CIVIL3D2023
HostAppVersion.v2023;
diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Plugin/AutocadCommand.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Plugin/AutocadCommand.cs
index c8ad7ad2a..1b2ade7fc 100644
--- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Plugin/AutocadCommand.cs
+++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Plugin/AutocadCommand.cs
@@ -11,6 +11,9 @@ using Speckle.Converters.Autocad;
#elif CIVIL3D
using Speckle.Converters.Civil3dShared;
using Speckle.Connectors.Civil3dShared.DependencyInjection;
+#elif PLANT3D
+using Speckle.Connectors.Plant3dShared.DependencyInjection;
+using Speckle.Converters.Plant3dShared;
#endif
namespace Speckle.Connectors.Autocad.Plugin;
@@ -39,13 +42,18 @@ public class AutocadCommand
// init DI
var services = new ServiceCollection();
+
_disposableLogger = services.Initialize(AppUtils.App, AppUtils.Version);
+
#if AUTOCAD
services.AddAutocad();
services.AddAutocadConverters();
#elif CIVIL3D
services.AddCivil3d();
services.AddCivil3dConverters();
+#elif PLANT3D
+ services.AddPlant3d();
+ services.AddPlant3dConverters();
#endif
Container = services.BuildServiceProvider();
Container.UseDUI();
diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Plugin/AutocadRibbon.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Plugin/AutocadRibbon.cs
index f20b15fa0..6d773f330 100644
--- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Plugin/AutocadRibbon.cs
+++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Plugin/AutocadRibbon.cs
@@ -3,7 +3,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using Autodesk.Windows;
using Speckle.Sdk;
-#if !AUTOCAD2025_OR_GREATER && !CIVIL3D2025_OR_GREATER
+#if !AUTOCAD2025_OR_GREATER && !CIVIL3D2025_OR_GREATER && !PLANT3D2025_OR_GREATER
using System.IO;
#endif
diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Plugin/BundlePlant3D/PackageContents.xml b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Plugin/BundlePlant3D/PackageContents.xml
new file mode 100644
index 000000000..4f12bdf61
--- /dev/null
+++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Plugin/BundlePlant3D/PackageContents.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Speckle.Connectors.AutocadShared.projitems b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Speckle.Connectors.AutocadShared.projitems
index 1c3a680cd..bac2b770e 100644
--- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Speckle.Connectors.AutocadShared.projitems
+++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Speckle.Connectors.AutocadShared.projitems
@@ -41,6 +41,8 @@
+
+
@@ -60,5 +62,8 @@
Always
+
+ Always
+
\ No newline at end of file
diff --git a/Connectors/Autocad/Speckle.Connectors.Civil3d2022/packages.lock.json b/Connectors/Autocad/Speckle.Connectors.Civil3d2022/packages.lock.json
index 8d0109286..c4dc9d4b3 100644
--- a/Connectors/Autocad/Speckle.Connectors.Civil3d2022/packages.lock.json
+++ b/Connectors/Autocad/Speckle.Connectors.Civil3d2022/packages.lock.json
@@ -180,8 +180,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -190,13 +190,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -292,7 +292,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -324,7 +324,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -368,11 +368,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Connectors/Autocad/Speckle.Connectors.Civil3d2023/packages.lock.json b/Connectors/Autocad/Speckle.Connectors.Civil3d2023/packages.lock.json
index 22c078aa6..efd0cd943 100644
--- a/Connectors/Autocad/Speckle.Connectors.Civil3d2023/packages.lock.json
+++ b/Connectors/Autocad/Speckle.Connectors.Civil3d2023/packages.lock.json
@@ -180,8 +180,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -190,13 +190,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -292,7 +292,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -324,7 +324,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -368,11 +368,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Connectors/Autocad/Speckle.Connectors.Civil3d2024/packages.lock.json b/Connectors/Autocad/Speckle.Connectors.Civil3d2024/packages.lock.json
index 16abbf491..0957e11f1 100644
--- a/Connectors/Autocad/Speckle.Connectors.Civil3d2024/packages.lock.json
+++ b/Connectors/Autocad/Speckle.Connectors.Civil3d2024/packages.lock.json
@@ -180,8 +180,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -190,13 +190,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -292,7 +292,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -324,7 +324,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -368,11 +368,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Connectors/Autocad/Speckle.Connectors.Civil3d2025/packages.lock.json b/Connectors/Autocad/Speckle.Connectors.Civil3d2025/packages.lock.json
index 15613abcb..a6f81fcb4 100644
--- a/Connectors/Autocad/Speckle.Connectors.Civil3d2025/packages.lock.json
+++ b/Connectors/Autocad/Speckle.Connectors.Civil3d2025/packages.lock.json
@@ -166,8 +166,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -175,13 +175,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -239,7 +239,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -272,7 +272,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -316,11 +316,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
},
diff --git a/Connectors/Autocad/Speckle.Connectors.Civil3d2026/packages.lock.json b/Connectors/Autocad/Speckle.Connectors.Civil3d2026/packages.lock.json
index 03babfe1b..cfde9e946 100644
--- a/Connectors/Autocad/Speckle.Connectors.Civil3d2026/packages.lock.json
+++ b/Connectors/Autocad/Speckle.Connectors.Civil3d2026/packages.lock.json
@@ -166,8 +166,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -175,13 +175,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -239,7 +239,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -272,7 +272,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -316,11 +316,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
},
diff --git a/Connectors/Autocad/Speckle.Connectors.Civil3dShared/DependencyInjection/Civil3dConnectorModule.cs b/Connectors/Autocad/Speckle.Connectors.Civil3dShared/DependencyInjection/Civil3dConnectorModule.cs
index 4ac057e8d..4cc3ae659 100644
--- a/Connectors/Autocad/Speckle.Connectors.Civil3dShared/DependencyInjection/Civil3dConnectorModule.cs
+++ b/Connectors/Autocad/Speckle.Connectors.Civil3dShared/DependencyInjection/Civil3dConnectorModule.cs
@@ -22,6 +22,10 @@ public static class Civil3dConnectorModule
// add send
serviceCollection.LoadSend();
serviceCollection.AddScoped, Civil3dRootObjectBuilder>();
+ serviceCollection.AddScoped<
+ IRootContinuousTraversalBuilder,
+ Civil3dContinuousTraversalBuilder
+ >();
serviceCollection.AddSingleton();
// add receive
diff --git a/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Operations/Send/Civil3dContinuousTraversalBuilder.cs b/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Operations/Send/Civil3dContinuousTraversalBuilder.cs
new file mode 100644
index 000000000..cc3379a15
--- /dev/null
+++ b/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Operations/Send/Civil3dContinuousTraversalBuilder.cs
@@ -0,0 +1,57 @@
+using Autodesk.AutoCAD.DatabaseServices;
+using Microsoft.Extensions.Logging;
+using Speckle.Connectors.Autocad.HostApp;
+using Speckle.Connectors.Autocad.Operations.Send;
+using Speckle.Connectors.Common.Caching;
+using Speckle.Connectors.Common.Operations;
+using Speckle.Converters.Civil3dShared.ToSpeckle;
+using Speckle.Converters.Common;
+using Speckle.Sdk.Logging;
+using Speckle.Sdk.Models.Collections;
+
+namespace Speckle.Connectors.Civil3dShared.Operations.Send;
+
+public sealed class Civil3dContinuousTraversalBuilder : AutocadContinuousTraversalBaseBuilder
+{
+ private readonly AutocadLayerUnpacker _layerUnpacker;
+ private readonly PropertySetDefinitionHandler _propertySetDefinitionHandler;
+
+ public Civil3dContinuousTraversalBuilder(
+ AutocadLayerUnpacker layerUnpacker,
+ PropertySetDefinitionHandler propertySetDefinitionHandler,
+ IRootToSpeckleConverter converter,
+ ISendConversionCache sendConversionCache,
+ AutocadInstanceUnpacker instanceObjectManager,
+ AutocadMaterialUnpacker materialUnpacker,
+ AutocadColorUnpacker colorUnpacker,
+ AutocadGroupUnpacker groupUnpacker,
+ ILogger logger,
+ ISdkActivityFactory activityFactory
+ )
+ : base(
+ converter,
+ sendConversionCache,
+ instanceObjectManager,
+ materialUnpacker,
+ colorUnpacker,
+ groupUnpacker,
+ logger,
+ activityFactory
+ )
+ {
+ _layerUnpacker = layerUnpacker;
+ _propertySetDefinitionHandler = propertySetDefinitionHandler;
+ }
+
+ public override (Collection, LayerTableRecord?) CreateObjectCollection(Entity entity, Transaction tr)
+ {
+ Layer layer = _layerUnpacker.GetOrCreateSpeckleLayer(entity, tr, out LayerTableRecord? autocadLayer);
+
+ return (layer, autocadLayer);
+ }
+
+ public override void AddAdditionalProxiesToRoot(Collection rootObject)
+ {
+ rootObject[ProxyKeys.PROPERTYSET_DEFINITIONS] = _propertySetDefinitionHandler.Definitions;
+ }
+}
diff --git a/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Speckle.Connectors.Civil3dShared.projitems b/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Speckle.Connectors.Civil3dShared.projitems
index 578a9fad0..ed43904aa 100644
--- a/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Speckle.Connectors.Civil3dShared.projitems
+++ b/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Speckle.Connectors.Civil3dShared.projitems
@@ -13,6 +13,7 @@
+
diff --git a/Connectors/Autocad/Speckle.Connectors.Plant3d2026/Speckle.Connectors.Plant3d2026.csproj b/Connectors/Autocad/Speckle.Connectors.Plant3d2026/Speckle.Connectors.Plant3d2026.csproj
new file mode 100644
index 000000000..a4f8ff6eb
--- /dev/null
+++ b/Connectors/Autocad/Speckle.Connectors.Plant3d2026/Speckle.Connectors.Plant3d2026.csproj
@@ -0,0 +1,30 @@
+
+
+ net8.0-windows
+ 2026
+ $(DefineConstants);PLANT3D2026;PLANT3D;PLANT3D2024_OR_GREATER;PLANT3D2025_OR_GREATER;PLANT3D2026_OR_GREATER
+ Debug;Release;Local
+
+
+
+
+ win-x64
+ true
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Connectors/Autocad/Speckle.Connectors.Plant3d2026/packages.lock.json b/Connectors/Autocad/Speckle.Connectors.Plant3d2026/packages.lock.json
new file mode 100644
index 000000000..6d82dde10
--- /dev/null
+++ b/Connectors/Autocad/Speckle.Connectors.Plant3d2026/packages.lock.json
@@ -0,0 +1,341 @@
+{
+ "version": 2,
+ "dependencies": {
+ "net8.0-windows7.0": {
+ "Microsoft.NETFramework.ReferenceAssemblies": {
+ "type": "Direct",
+ "requested": "[1.0.3, )",
+ "resolved": "1.0.3",
+ "contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
+ "dependencies": {
+ "Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.3"
+ }
+ },
+ "Microsoft.SourceLink.GitHub": {
+ "type": "Direct",
+ "requested": "[8.0.0, )",
+ "resolved": "8.0.0",
+ "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
+ "dependencies": {
+ "Microsoft.Build.Tasks.Git": "8.0.0",
+ "Microsoft.SourceLink.Common": "8.0.0"
+ }
+ },
+ "PolySharp": {
+ "type": "Direct",
+ "requested": "[1.14.1, )",
+ "resolved": "1.14.1",
+ "contentHash": "mOOmFYwad3MIOL14VCjj02LljyF1GNw1wP0YVlxtcPvqdxjGGMNdNJJxHptlry3MOd8b40Flm8RPOM8JOlN2sQ=="
+ },
+ "Speckle.AutoCAD.API": {
+ "type": "Direct",
+ "requested": "[2026.0.0, )",
+ "resolved": "2026.0.0",
+ "contentHash": "WlkV81PmbK/ftoM7aGpU6LGosKbePBQej9MO/m63rFMozX89tsitEhE12o58wu7K/4FmRUdAMolYtdK20EDBnw=="
+ },
+ "Speckle.InterfaceGenerator": {
+ "type": "Direct",
+ "requested": "[0.9.6, )",
+ "resolved": "0.9.6",
+ "contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
+ },
+ "Speckle.Plant3D.API": {
+ "type": "Direct",
+ "requested": "[2026.0.0, )",
+ "resolved": "2026.0.0",
+ "contentHash": "VT8M6CGQl1mk3/5Ro3AEAOVrOs/cX58YRwYZnu+6xeHvsazK07Et/6kMJsde4Y7Xrpox7eBLKgYeOspiRVvX5g==",
+ "dependencies": {
+ "Speckle.AutoCAD.API": "2026.0.0"
+ }
+ },
+ "GraphQL.Client": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "8yPNBbuVBpTptivyAlak4GZvbwbUcjeQTL4vN1HKHRuOykZ4r7l5fcLS6vpyPyLn0x8FsL31xbOIKyxbmR9rbA==",
+ "dependencies": {
+ "GraphQL.Client.Abstractions": "6.0.0",
+ "GraphQL.Client.Abstractions.Websocket": "6.0.0",
+ "System.Reactive": "5.0.0"
+ }
+ },
+ "GraphQL.Client.Abstractions": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "h7uzWFORHZ+CCjwr/ThAyXMr0DPpzEANDa4Uo54wqCQ+j7qUKwqYTgOrb1W40sqbvNaZm9v/X7It31SUw0maHA==",
+ "dependencies": {
+ "GraphQL.Primitives": "6.0.0"
+ }
+ },
+ "GraphQL.Client.Abstractions.Websocket": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "Nr9bPf8gIOvLuXpqEpqr9z9jslYFJOvd0feHth3/kPqeR3uMbjF5pjiwh4jxyMcxHdr8Pb6QiXkV3hsSyt0v7A==",
+ "dependencies": {
+ "GraphQL.Client.Abstractions": "6.0.0"
+ }
+ },
+ "GraphQL.Primitives": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "yg72rrYDapfsIUrul7aF6wwNnTJBOFvuA9VdDTQpPa8AlAriHbufeXYLBcodKjfUdkCnaiggX1U/nEP08Zb5GA=="
+ },
+ "Microsoft.Build.Tasks.Git": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
+ },
+ "Microsoft.Data.Sqlite": {
+ "type": "Transitive",
+ "resolved": "7.0.5",
+ "contentHash": "KGxbPeWsQMnmQy43DSBxAFtHz3l2JX8EWBSGUCvT3CuZ8KsuzbkqMIJMDOxWtG8eZSoCDI04aiVQjWuuV8HmSw==",
+ "dependencies": {
+ "Microsoft.Data.Sqlite.Core": "7.0.5",
+ "SQLitePCLRaw.bundle_e_sqlite3": "2.1.4"
+ }
+ },
+ "Microsoft.Data.Sqlite.Core": {
+ "type": "Transitive",
+ "resolved": "7.0.5",
+ "contentHash": "FTerRmQPqHrCrnoUzhBu+E+1DNGwyrAMLqHkAqOOOu5pGfyMOj8qQUBxI/gDtWtG11p49UxSfWmBzRNlwZqfUg==",
+ "dependencies": {
+ "SQLitePCLRaw.core": "2.1.4"
+ }
+ },
+ "Microsoft.Extensions.Configuration": {
+ "type": "Transitive",
+ "resolved": "2.2.0",
+ "contentHash": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "2.2.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration.Abstractions": {
+ "type": "Transitive",
+ "resolved": "2.2.0",
+ "contentHash": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "2.2.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration.Binder": {
+ "type": "Transitive",
+ "resolved": "2.2.0",
+ "contentHash": "vJ9xvOZCnUAIHcGC3SU35r3HKmHTVIeHzo6u/qzlHAqD8m6xv92MLin4oJntTvkpKxVX3vI1GFFkIQtU3AdlsQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "2.2.0"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection.Abstractions": {
+ "type": "Transitive",
+ "resolved": "2.2.0",
+ "contentHash": "f9hstgjVmr6rmrfGSpfsVOl2irKAgr1QjrSi3FgnS7kulxband50f2brRLwySAQTADPZeTdow0mpSMcoAdadCw=="
+ },
+ "Microsoft.Extensions.Options": {
+ "type": "Transitive",
+ "resolved": "2.2.0",
+ "contentHash": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
+ "Microsoft.Extensions.Primitives": "2.2.0",
+ "System.ComponentModel.Annotations": "4.5.0"
+ }
+ },
+ "Microsoft.Extensions.Primitives": {
+ "type": "Transitive",
+ "resolved": "2.2.0",
+ "contentHash": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==",
+ "dependencies": {
+ "System.Memory": "4.5.1",
+ "System.Runtime.CompilerServices.Unsafe": "4.5.1"
+ }
+ },
+ "Microsoft.NETFramework.ReferenceAssemblies.net461": {
+ "type": "Transitive",
+ "resolved": "1.0.3",
+ "contentHash": "AmOJZwCqnOCNp6PPcf9joyogScWLtwy0M1WkqfEQ0M9nYwyDD7EX9ZjscKS5iYnyvteX7kzSKFCKt9I9dXA6mA=="
+ },
+ "Microsoft.SourceLink.Common": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
+ },
+ "Speckle.Newtonsoft.Json": {
+ "type": "Transitive",
+ "resolved": "13.0.2",
+ "contentHash": "g1BejUZwax5PRfL6xHgLEK23sqHWOgOj9hE7RvfRRlN00AGt8GnPYt8HedSK7UB3HiRW8zCA9Pn0iiYxCK24BA=="
+ },
+ "Speckle.Sdk": {
+ "type": "Transitive",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
+ "dependencies": {
+ "GraphQL.Client": "6.0.0",
+ "Microsoft.Data.Sqlite": "7.0.5",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
+ "Microsoft.Extensions.Logging": "2.2.0",
+ "Speckle.DoubleNumerics": "4.1.0",
+ "Speckle.Newtonsoft.Json": "13.0.2",
+ "Speckle.Sdk.Dependencies": "3.15.3"
+ }
+ },
+ "Speckle.Sdk.Dependencies": {
+ "type": "Transitive",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
+ },
+ "SQLitePCLRaw.bundle_e_sqlite3": {
+ "type": "Transitive",
+ "resolved": "2.1.4",
+ "contentHash": "EWI1olKDjFEBMJu0+3wuxwziIAdWDVMYLhuZ3Qs84rrz+DHwD00RzWPZCa+bLnHCf3oJwuFZIRsHT5p236QXww==",
+ "dependencies": {
+ "SQLitePCLRaw.lib.e_sqlite3": "2.1.4",
+ "SQLitePCLRaw.provider.e_sqlite3": "2.1.4"
+ }
+ },
+ "SQLitePCLRaw.core": {
+ "type": "Transitive",
+ "resolved": "2.1.4",
+ "contentHash": "inBjvSHo9UDKneGNzfUfDjK08JzlcIhn1+SP5Y3m6cgXpCxXKCJDy6Mka7LpgSV+UZmKSnC8rTwB0SQ0xKu5pA==",
+ "dependencies": {
+ "System.Memory": "4.5.3"
+ }
+ },
+ "SQLitePCLRaw.lib.e_sqlite3": {
+ "type": "Transitive",
+ "resolved": "2.1.4",
+ "contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
+ },
+ "SQLitePCLRaw.provider.e_sqlite3": {
+ "type": "Transitive",
+ "resolved": "2.1.4",
+ "contentHash": "CSlb5dUp1FMIkez9Iv5EXzpeq7rHryVNqwJMWnpq87j9zWZexaEMdisDktMsnnrzKM6ahNrsTkjqNodTBPBxtQ==",
+ "dependencies": {
+ "SQLitePCLRaw.core": "2.1.4"
+ }
+ },
+ "System.ComponentModel.Annotations": {
+ "type": "Transitive",
+ "resolved": "4.5.0",
+ "contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
+ },
+ "System.Memory": {
+ "type": "Transitive",
+ "resolved": "4.5.3",
+ "contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA=="
+ },
+ "System.Reactive": {
+ "type": "Transitive",
+ "resolved": "5.0.0",
+ "contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ=="
+ },
+ "System.Runtime.CompilerServices.Unsafe": {
+ "type": "Transitive",
+ "resolved": "4.5.1",
+ "contentHash": "Zh8t8oqolRaFa9vmOZfdQm/qKejdqz0J9kr7o2Fu0vPeoH3BL1EOXipKWwkWtLT1JPzjByrF19fGuFlNbmPpiw=="
+ },
+ "speckle.connectors.common": {
+ "type": "Project",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
+ "Speckle.Connectors.Logging": "[1.0.0, )",
+ "Speckle.Converters.Common": "[1.0.0, )",
+ "Speckle.Objects": "[3.15.3, )"
+ }
+ },
+ "speckle.connectors.dui": {
+ "type": "Project",
+ "dependencies": {
+ "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
+ "Speckle.Connectors.Common": "[1.0.0, )"
+ }
+ },
+ "speckle.connectors.dui.webview": {
+ "type": "Project",
+ "dependencies": {
+ "Microsoft.Web.WebView2": "[1.0.1938.49, )",
+ "Speckle.Connectors.DUI": "[1.0.0, )"
+ }
+ },
+ "speckle.connectors.logging": {
+ "type": "Project"
+ },
+ "speckle.converters.common": {
+ "type": "Project",
+ "dependencies": {
+ "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
+ "Speckle.Objects": "[3.15.3, )"
+ }
+ },
+ "speckle.converters.plant3d2026": {
+ "type": "Project",
+ "dependencies": {
+ "Speckle.AutoCAD.API": "[2026.0.0, )",
+ "Speckle.Connectors.DUI.WebView": "[1.0.0, )",
+ "Speckle.Converters.Common": "[1.0.0, )",
+ "Speckle.Plant3D.API": "[2026.0.0, )"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection": {
+ "type": "CentralTransitive",
+ "requested": "[2.2.0, )",
+ "resolved": "2.2.0",
+ "contentHash": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0"
+ }
+ },
+ "Microsoft.Extensions.Logging": {
+ "type": "CentralTransitive",
+ "requested": "[2.2.0, )",
+ "resolved": "2.2.0",
+ "contentHash": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Binder": "2.2.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
+ "Microsoft.Extensions.Logging.Abstractions": "2.2.0",
+ "Microsoft.Extensions.Options": "2.2.0"
+ }
+ },
+ "Microsoft.Extensions.Logging.Abstractions": {
+ "type": "CentralTransitive",
+ "requested": "[2.2.0, )",
+ "resolved": "2.2.0",
+ "contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
+ },
+ "Microsoft.Web.WebView2": {
+ "type": "CentralTransitive",
+ "requested": "[1.0.1938.49, )",
+ "resolved": "1.0.1938.49",
+ "contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
+ },
+ "Speckle.DoubleNumerics": {
+ "type": "CentralTransitive",
+ "requested": "[4.1.0, )",
+ "resolved": "4.1.0",
+ "contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
+ },
+ "Speckle.Objects": {
+ "type": "CentralTransitive",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
+ "dependencies": {
+ "Speckle.Sdk": "3.15.3"
+ }
+ }
+ },
+ "net8.0-windows7.0/win-x64": {
+ "SQLitePCLRaw.lib.e_sqlite3": {
+ "type": "Transitive",
+ "resolved": "2.1.4",
+ "contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
+ },
+ "Microsoft.Web.WebView2": {
+ "type": "CentralTransitive",
+ "requested": "[1.0.1938.49, )",
+ "resolved": "1.0.1938.49",
+ "contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Connectors/Autocad/Speckle.Connectors.Plant3dShared/Bindings/Plant3dSendBinding.cs b/Connectors/Autocad/Speckle.Connectors.Plant3dShared/Bindings/Plant3dSendBinding.cs
new file mode 100644
index 000000000..c0853b96d
--- /dev/null
+++ b/Connectors/Autocad/Speckle.Connectors.Plant3dShared/Bindings/Plant3dSendBinding.cs
@@ -0,0 +1,61 @@
+using Microsoft.Extensions.DependencyInjection;
+using Speckle.Connectors.Autocad.Bindings;
+using Speckle.Connectors.Common.Caching;
+using Speckle.Connectors.Common.Cancellation;
+using Speckle.Connectors.Common.Threading;
+using Speckle.Connectors.DUI.Bindings;
+using Speckle.Connectors.DUI.Bridge;
+using Speckle.Connectors.DUI.Models;
+using Speckle.Connectors.DUI.Models.Card.SendFilter;
+using Speckle.Converters.Autocad;
+using Speckle.Converters.Common;
+using Speckle.Converters.Plant3dShared;
+
+namespace Speckle.Connectors.Plant3dShared.Bindings;
+
+public sealed class Plant3dSendBinding : AutocadSendBaseBinding
+{
+ private readonly IPlant3dConversionSettingsFactory _plant3dConversionSettingsFactory;
+ private readonly IAutocadConversionSettingsFactory _autocadConversionSettingsFactory;
+
+ public Plant3dSendBinding(
+ DocumentModelStore store,
+ IBrowserBridge parent,
+ IEnumerable sendFilters,
+ ICancellationManager cancellationManager,
+ ISendConversionCache sendConversionCache,
+ IPlant3dConversionSettingsFactory plant3dConversionSettingsFactory,
+ IAutocadConversionSettingsFactory autocadConversionSettingsFactory,
+ IThreadContext threadContext,
+ ITopLevelExceptionHandler topLevelExceptionHandler,
+ IAppIdleManager appIdleManager,
+ ISendOperationManagerFactory sendOperationManagerFactory
+ )
+ : base(
+ store,
+ parent,
+ sendFilters,
+ cancellationManager,
+ sendConversionCache,
+ threadContext,
+ topLevelExceptionHandler,
+ appIdleManager,
+ sendOperationManagerFactory
+ )
+ {
+ _plant3dConversionSettingsFactory = plant3dConversionSettingsFactory;
+ _autocadConversionSettingsFactory = autocadConversionSettingsFactory;
+ }
+
+ // We need a separate send binding for Plant 3D due to using a different unit converter (needed for conversion settings construction)
+ protected override void InitializeSettings(IServiceProvider serviceProvider)
+ {
+ serviceProvider
+ .GetRequiredService>()
+ .Initialize(_plant3dConversionSettingsFactory.Create(Application.DocumentManager.CurrentDocument));
+
+ serviceProvider
+ .GetRequiredService>()
+ .Initialize(_autocadConversionSettingsFactory.Create(Application.DocumentManager.CurrentDocument));
+ }
+}
diff --git a/Connectors/Autocad/Speckle.Connectors.Plant3dShared/DependencyInjection/Plant3dConnectorModule.cs b/Connectors/Autocad/Speckle.Connectors.Plant3dShared/DependencyInjection/Plant3dConnectorModule.cs
new file mode 100644
index 000000000..9b11f1abb
--- /dev/null
+++ b/Connectors/Autocad/Speckle.Connectors.Plant3dShared/DependencyInjection/Plant3dConnectorModule.cs
@@ -0,0 +1,27 @@
+using System.Reflection;
+using Microsoft.Extensions.DependencyInjection;
+using Speckle.Connectors.Autocad.DependencyInjection;
+using Speckle.Connectors.Autocad.Operations.Send;
+using Speckle.Connectors.Common.Builders;
+using Speckle.Connectors.DUI.Bindings;
+using Speckle.Connectors.Plant3dShared.Bindings;
+using Speckle.Connectors.Plant3dShared.Operations.Send;
+using Speckle.Sdk;
+
+namespace Speckle.Connectors.Plant3dShared.DependencyInjection;
+
+public static class Plant3dConnectorModule
+{
+ public static void AddPlant3d(this IServiceCollection serviceCollection)
+ {
+ serviceCollection.AddAutocadBase();
+
+ // add send
+ serviceCollection.LoadSend();
+ serviceCollection.AddScoped, Plant3dRootObjectBuilder>();
+ serviceCollection.AddSingleton();
+
+ // automatically detects the Class:IClass interface pattern to register all generated interfaces
+ serviceCollection.AddMatchingInterfacesAsTransient(Assembly.GetExecutingAssembly());
+ }
+}
diff --git a/Connectors/Autocad/Speckle.Connectors.Plant3dShared/Operations/Send/Plant3dRootObjectBuilder.cs b/Connectors/Autocad/Speckle.Connectors.Plant3dShared/Operations/Send/Plant3dRootObjectBuilder.cs
new file mode 100644
index 000000000..b2cc81fac
--- /dev/null
+++ b/Connectors/Autocad/Speckle.Connectors.Plant3dShared/Operations/Send/Plant3dRootObjectBuilder.cs
@@ -0,0 +1,50 @@
+using Autodesk.AutoCAD.DatabaseServices;
+using Microsoft.Extensions.Logging;
+using Speckle.Connectors.Autocad.HostApp;
+using Speckle.Connectors.Autocad.Operations.Send;
+using Speckle.Connectors.Common.Caching;
+using Speckle.Converters.Autocad;
+using Speckle.Converters.Common;
+using Speckle.Sdk.Logging;
+using Speckle.Sdk.Models.Collections;
+
+namespace Speckle.Connectors.Plant3dShared.Operations.Send;
+
+public sealed class Plant3dRootObjectBuilder : AutocadRootObjectBaseBuilder
+{
+ private readonly AutocadLayerUnpacker _layerUnpacker;
+
+ public Plant3dRootObjectBuilder(
+ AutocadLayerUnpacker layerUnpacker,
+ IRootToSpeckleConverter converter,
+ IConverterSettingsStore converterSettings,
+ ISendConversionCache sendConversionCache,
+ AutocadInstanceUnpacker instanceObjectManager,
+ AutocadMaterialUnpacker materialUnpacker,
+ AutocadColorUnpacker colorUnpacker,
+ AutocadGroupUnpacker groupUnpacker,
+ ILogger logger,
+ ISdkActivityFactory activityFactory
+ )
+ : base(
+ converter,
+ converterSettings,
+ sendConversionCache,
+ instanceObjectManager,
+ materialUnpacker,
+ colorUnpacker,
+ groupUnpacker,
+ logger,
+ activityFactory
+ )
+ {
+ _layerUnpacker = layerUnpacker;
+ }
+
+ public override (Collection, LayerTableRecord?) CreateObjectCollection(Entity entity, Transaction tr)
+ {
+ Layer layer = _layerUnpacker.GetOrCreateSpeckleLayer(entity, tr, out LayerTableRecord? autocadLayer);
+
+ return (layer, autocadLayer);
+ }
+}
diff --git a/Connectors/Autocad/Speckle.Connectors.Plant3dShared/Speckle.Connectors.Plant3dShared.projitems b/Connectors/Autocad/Speckle.Connectors.Plant3dShared/Speckle.Connectors.Plant3dShared.projitems
new file mode 100644
index 000000000..915ec726d
--- /dev/null
+++ b/Connectors/Autocad/Speckle.Connectors.Plant3dShared/Speckle.Connectors.Plant3dShared.projitems
@@ -0,0 +1,20 @@
+
+
+
+ $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
+ true
+ B1C4A14C-2F4E-4C3D-9B71-A3F5D8E6C912
+
+
+ Speckle.Connectors.Plant3dShared
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Connectors/Autocad/Speckle.Connectors.Plant3dShared/Speckle.Connectors.Plant3dShared.shproj b/Connectors/Autocad/Speckle.Connectors.Plant3dShared/Speckle.Connectors.Plant3dShared.shproj
new file mode 100644
index 000000000..9724f8108
--- /dev/null
+++ b/Connectors/Autocad/Speckle.Connectors.Plant3dShared/Speckle.Connectors.Plant3dShared.shproj
@@ -0,0 +1,11 @@
+
+
+
+ {B1C4A14C-2F4E-4C3D-9B71-A3F5D8E6C912}
+
+
+
+
+
+
+
diff --git a/Connectors/CSi/Speckle.Connectors.CSiShared/Operations/Send/CsiContinuousTraversalBuilder.cs b/Connectors/CSi/Speckle.Connectors.CSiShared/Operations/Send/CsiContinuousTraversalBuilder.cs
new file mode 100644
index 000000000..01a320058
--- /dev/null
+++ b/Connectors/CSi/Speckle.Connectors.CSiShared/Operations/Send/CsiContinuousTraversalBuilder.cs
@@ -0,0 +1,211 @@
+using Microsoft.Extensions.Logging;
+using Speckle.Connectors.Common.Builders;
+using Speckle.Connectors.Common.Conversion;
+using Speckle.Connectors.Common.Operations;
+using Speckle.Connectors.CSiShared.HostApp;
+using Speckle.Connectors.CSiShared.HostApp.Helpers;
+using Speckle.Connectors.CSiShared.Utils;
+using Speckle.Converters.Common;
+using Speckle.Converters.CSiShared;
+using Speckle.Converters.CSiShared.Extensions;
+using Speckle.Converters.CSiShared.Utils;
+using Speckle.Sdk;
+using Speckle.Sdk.Logging;
+using Speckle.Sdk.Models;
+using Speckle.Sdk.Models.Collections;
+using Speckle.Sdk.Pipelines.Progress;
+using Speckle.Sdk.Pipelines.Send;
+
+namespace Speckle.Connectors.CSiShared.Builders;
+
+///
+/// Continuous traversal builder for CSi that streams objects through a
+/// for packfile-based uploads. Same conversion logic as .
+///
+public class CsiContinuousTraversalBuilder : IRootContinuousTraversalBuilder
+{
+ private readonly IRootToSpeckleConverter _rootToSpeckleConverter;
+ private readonly IConverterSettingsStore _converterSettings;
+ private readonly CsiSendCollectionManager _sendCollectionManager;
+ private readonly IMaterialUnpacker _materialUnpacker;
+ private readonly ISectionUnpacker _sectionUnpacker;
+ private readonly ILogger _logger;
+ private readonly ISdkActivityFactory _activityFactory;
+ private readonly ICsiApplicationService _csiApplicationService;
+ private readonly AnalysisResultsExtractor _analysisResultsExtractor;
+
+ public CsiContinuousTraversalBuilder(
+ IRootToSpeckleConverter rootToSpeckleConverter,
+ IConverterSettingsStore converterSettings,
+ CsiSendCollectionManager sendCollectionManager,
+ IMaterialUnpacker materialUnpacker,
+ ISectionUnpacker sectionUnpacker,
+ ILogger logger,
+ ISdkActivityFactory activityFactory,
+ ICsiApplicationService csiApplicationService,
+ AnalysisResultsExtractor analysisResultsExtractor
+ )
+ {
+ _converterSettings = converterSettings;
+ _sendCollectionManager = sendCollectionManager;
+ _materialUnpacker = materialUnpacker;
+ _sectionUnpacker = sectionUnpacker;
+ _rootToSpeckleConverter = rootToSpeckleConverter;
+ _logger = logger;
+ _activityFactory = activityFactory;
+ _csiApplicationService = csiApplicationService;
+ _analysisResultsExtractor = analysisResultsExtractor;
+ }
+
+ public async Task Build(
+ IReadOnlyList csiObjects,
+ string projectId,
+ SendPipeline sendPipeline,
+ IProgress onOperationProgressed,
+ CancellationToken cancellationToken
+ )
+ {
+ using var activity = _activityFactory.Start("Build");
+
+ string modelFileName = _csiApplicationService.SapModel.GetModelFilename(false) ?? "Unnamed model";
+ (string forceUnit, string tempUnit) = GetForceAndTemperatureUnits();
+
+ Collection rootObjectCollection =
+ new()
+ {
+ name = modelFileName,
+ ["units"] = _converterSettings.Current.SpeckleUnits,
+ ["forceUnits"] = forceUnit,
+ ["temperatureUnits"] = tempUnit
+ };
+
+ List results = new(csiObjects.Count);
+ int count = 0;
+
+ using (var _ = _activityFactory.Start("Convert all"))
+ {
+ foreach (ICsiWrapper csiObject in csiObjects)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ var result = await ConvertCsiObject(csiObject, rootObjectCollection, sendPipeline);
+ results.Add(result);
+
+ count++;
+ onOperationProgressed.Report(
+ new($"Converting objects... ({count:N0} / {csiObjects.Count:N0})", (double)count / csiObjects.Count)
+ );
+ await Task.Yield();
+ }
+ }
+
+ if (results.All(x => x.Status == Status.ERROR))
+ {
+ throw new SpeckleException("Failed to convert all objects");
+ }
+
+ using (var _ = _activityFactory.Start("Process Proxies"))
+ {
+ rootObjectCollection[ProxyKeys.MATERIAL] = _materialUnpacker.UnpackMaterials().ToList();
+ rootObjectCollection[ProxyKeys.SECTION] = _sectionUnpacker.UnpackSections().ToList();
+ }
+
+ // Extract analysis results (if applicable)
+ var objectSelectionSummary = GetObjectSummary(csiObjects);
+ var selectedCasesAndCombinations = _converterSettings.Current.SelectedLoadCasesAndCombinations;
+ var requestedResultTypes = _converterSettings.Current.SelectedResultTypes;
+
+ if (selectedCasesAndCombinations?.Count > 0)
+ {
+ if (requestedResultTypes == null || requestedResultTypes.Count == 0)
+ {
+ throw new SpeckleException(
+ "Adjust publish settings - no result type input for the requested load cases and combinations"
+ );
+ }
+
+ if (!_csiApplicationService.SapModel.GetModelIsLocked())
+ {
+ throw new SpeckleException("Model unlocked, no access to analysis results");
+ }
+
+ try
+ {
+ var analysisResults = _analysisResultsExtractor.ExtractAnalysisResults(
+ selectedCasesAndCombinations,
+ requestedResultTypes,
+ objectSelectionSummary
+ );
+ rootObjectCollection[RootKeys.ANALYSIS_RESULTS] = analysisResults;
+ }
+ catch (Exception ex)
+ {
+ throw new SpeckleException("Analysis result extraction failed", ex);
+ }
+ }
+
+ // Process root collection and wait for all uploads
+ await sendPipeline.Process(rootObjectCollection);
+ await sendPipeline.WaitForUpload();
+
+ return new RootObjectBuilderResult(rootObjectCollection, results);
+ }
+
+ private async Task ConvertCsiObject(
+ ICsiWrapper csiObject,
+ Collection typeCollection,
+ SendPipeline sendPipeline
+ )
+ {
+ string sourceType = csiObject.ObjectName;
+ string applicationId = csiObject switch
+ {
+ CsiJointWrapper jointWrapper => jointWrapper.GetSpeckleApplicationId(_csiApplicationService.SapModel),
+ CsiFrameWrapper frameWrapper => frameWrapper.GetSpeckleApplicationId(_csiApplicationService.SapModel),
+ CsiCableWrapper cableWrapper => cableWrapper.GetSpeckleApplicationId(_csiApplicationService.SapModel),
+ CsiTendonWrapper tendonWrapper => tendonWrapper.ObjectName,
+ CsiShellWrapper shellWrapper => shellWrapper.GetSpeckleApplicationId(_csiApplicationService.SapModel),
+ CsiSolidWrapper solidWrapper => solidWrapper.GetSpeckleApplicationId(_csiApplicationService.SapModel),
+ CsiLinkWrapper linkWrapper => linkWrapper.GetSpeckleApplicationId(_csiApplicationService.SapModel),
+ _ => throw new ArgumentException($"Unsupported wrapper type: {csiObject.GetType()}", nameof(csiObject))
+ };
+
+ try
+ {
+ Base converted = _rootToSpeckleConverter.Convert(csiObject);
+
+ var collection = _sendCollectionManager.AddObjectCollectionToRoot(converted, typeCollection);
+
+ // NOTE: this is the main part that differentiate from the main root object builder
+ var reference = await sendPipeline.Process(converted).ConfigureAwait(false);
+ collection.elements.Add(reference);
+
+ return new(Status.SUCCESS, applicationId, sourceType, reference);
+ }
+ catch (NotImplementedException ex)
+ {
+ _logger.LogError(ex, "Failed to convert object {sourceType}", sourceType);
+ return new(Status.WARNING, applicationId, sourceType, null, ex);
+ }
+ catch (Exception ex) when (!ex.IsFatal())
+ {
+ _logger.LogError(ex, "Failed to convert object {sourceType}", sourceType);
+ return new(Status.ERROR, applicationId, sourceType, null, ex);
+ }
+ }
+
+ private Dictionary> GetObjectSummary(IReadOnlyList csiObjects) =>
+ csiObjects
+ .GroupBy(csiObject => csiObject.ObjectType)
+ .ToDictionary(group => group.Key, group => group.Select(obj => obj.Name).ToList());
+
+ private (string, string) GetForceAndTemperatureUnits()
+ {
+ var forceUnit = eForce.NotApplicable;
+ var lengthUnit = eLength.NotApplicable;
+ var temperatureUnit = eTemperature.NotApplicable;
+
+ _converterSettings.Current.SapModel.GetDatabaseUnits_2(ref forceUnit, ref lengthUnit, ref temperatureUnit);
+
+ return (forceUnit.ToString(), temperatureUnit.ToString());
+ }
+}
diff --git a/Connectors/CSi/Speckle.Connectors.CSiShared/Operations/Send/CsiRootObjectBuilder.cs b/Connectors/CSi/Speckle.Connectors.CSiShared/Operations/Send/CsiRootObjectBuilder.cs
index 0df394a30..00c110ba3 100644
--- a/Connectors/CSi/Speckle.Connectors.CSiShared/Operations/Send/CsiRootObjectBuilder.cs
+++ b/Connectors/CSi/Speckle.Connectors.CSiShared/Operations/Send/CsiRootObjectBuilder.cs
@@ -13,6 +13,7 @@ using Speckle.Sdk;
using Speckle.Sdk.Logging;
using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Collections;
+using Speckle.Sdk.Pipelines.Progress;
namespace Speckle.Connectors.CSiShared.Builders;
diff --git a/Connectors/CSi/Speckle.Connectors.CSiShared/ServiceRegistration.cs b/Connectors/CSi/Speckle.Connectors.CSiShared/ServiceRegistration.cs
index 0a3942caf..c0b224cd6 100644
--- a/Connectors/CSi/Speckle.Connectors.CSiShared/ServiceRegistration.cs
+++ b/Connectors/CSi/Speckle.Connectors.CSiShared/ServiceRegistration.cs
@@ -43,6 +43,7 @@ public static class ServiceRegistration
services.AddScoped();
services.AddScoped();
services.AddScoped, CsiRootObjectBuilder>();
+ services.AddScoped, CsiContinuousTraversalBuilder>();
services.AddScoped>();
services.AddScoped();
diff --git a/Connectors/CSi/Speckle.Connectors.CSiShared/Speckle.Connectors.CSiShared.projitems b/Connectors/CSi/Speckle.Connectors.CSiShared/Speckle.Connectors.CSiShared.projitems
index 7dd388f54..9e9dca126 100644
--- a/Connectors/CSi/Speckle.Connectors.CSiShared/Speckle.Connectors.CSiShared.projitems
+++ b/Connectors/CSi/Speckle.Connectors.CSiShared/Speckle.Connectors.CSiShared.projitems
@@ -29,6 +29,7 @@
+
diff --git a/Connectors/CSi/Speckle.Connectors.ETABS21/packages.lock.json b/Connectors/CSi/Speckle.Connectors.ETABS21/packages.lock.json
index 870303dab..78b0d61f3 100644
--- a/Connectors/CSi/Speckle.Connectors.ETABS21/packages.lock.json
+++ b/Connectors/CSi/Speckle.Connectors.ETABS21/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -283,7 +283,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -307,7 +307,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.converters.etabs21": {
@@ -357,11 +357,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Connectors/CSi/Speckle.Connectors.ETABS22/packages.lock.json b/Connectors/CSi/Speckle.Connectors.ETABS22/packages.lock.json
index e10dfb30e..4717e26e4 100644
--- a/Connectors/CSi/Speckle.Connectors.ETABS22/packages.lock.json
+++ b/Connectors/CSi/Speckle.Connectors.ETABS22/packages.lock.json
@@ -157,8 +157,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -166,13 +166,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -230,7 +230,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -254,7 +254,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.converters.etabs22": {
@@ -304,11 +304,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Connectors/Navisworks/Speckle.Connectors.Navisworks2020/packages.lock.json b/Connectors/Navisworks/Speckle.Connectors.Navisworks2020/packages.lock.json
index de58fe45b..471d73e7e 100644
--- a/Connectors/Navisworks/Speckle.Connectors.Navisworks2020/packages.lock.json
+++ b/Connectors/Navisworks/Speckle.Connectors.Navisworks2020/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -283,7 +283,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -307,7 +307,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.converters.navisworks2020": {
@@ -359,11 +359,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
},
diff --git a/Connectors/Navisworks/Speckle.Connectors.Navisworks2021/packages.lock.json b/Connectors/Navisworks/Speckle.Connectors.Navisworks2021/packages.lock.json
index 9ed66984b..ab67486bf 100644
--- a/Connectors/Navisworks/Speckle.Connectors.Navisworks2021/packages.lock.json
+++ b/Connectors/Navisworks/Speckle.Connectors.Navisworks2021/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -283,7 +283,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -307,7 +307,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.converters.navisworks2021": {
@@ -359,11 +359,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
},
diff --git a/Connectors/Navisworks/Speckle.Connectors.Navisworks2022/packages.lock.json b/Connectors/Navisworks/Speckle.Connectors.Navisworks2022/packages.lock.json
index c53fe6df9..922c92f11 100644
--- a/Connectors/Navisworks/Speckle.Connectors.Navisworks2022/packages.lock.json
+++ b/Connectors/Navisworks/Speckle.Connectors.Navisworks2022/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -283,7 +283,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -307,7 +307,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.converters.navisworks2022": {
@@ -359,11 +359,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
},
diff --git a/Connectors/Navisworks/Speckle.Connectors.Navisworks2023/packages.lock.json b/Connectors/Navisworks/Speckle.Connectors.Navisworks2023/packages.lock.json
index ae2c353b1..7d3e3dd54 100644
--- a/Connectors/Navisworks/Speckle.Connectors.Navisworks2023/packages.lock.json
+++ b/Connectors/Navisworks/Speckle.Connectors.Navisworks2023/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -283,7 +283,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -307,7 +307,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.converters.navisworks2023": {
@@ -359,11 +359,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
},
diff --git a/Connectors/Navisworks/Speckle.Connectors.Navisworks2024/packages.lock.json b/Connectors/Navisworks/Speckle.Connectors.Navisworks2024/packages.lock.json
index d6ac82b0a..71d333976 100644
--- a/Connectors/Navisworks/Speckle.Connectors.Navisworks2024/packages.lock.json
+++ b/Connectors/Navisworks/Speckle.Connectors.Navisworks2024/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -283,7 +283,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -307,7 +307,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.converters.navisworks2024": {
@@ -359,11 +359,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
},
diff --git a/Connectors/Navisworks/Speckle.Connectors.Navisworks2025/packages.lock.json b/Connectors/Navisworks/Speckle.Connectors.Navisworks2025/packages.lock.json
index 256f44310..29950e6b4 100644
--- a/Connectors/Navisworks/Speckle.Connectors.Navisworks2025/packages.lock.json
+++ b/Connectors/Navisworks/Speckle.Connectors.Navisworks2025/packages.lock.json
@@ -177,8 +177,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -187,13 +187,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -289,7 +289,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -313,7 +313,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.converters.navisworks2025": {
@@ -359,11 +359,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
},
diff --git a/Connectors/Navisworks/Speckle.Connectors.Navisworks2026/packages.lock.json b/Connectors/Navisworks/Speckle.Connectors.Navisworks2026/packages.lock.json
index 3b4fe261d..5be4576d0 100644
--- a/Connectors/Navisworks/Speckle.Connectors.Navisworks2026/packages.lock.json
+++ b/Connectors/Navisworks/Speckle.Connectors.Navisworks2026/packages.lock.json
@@ -186,8 +186,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -196,13 +196,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -290,7 +290,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -314,7 +314,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.converters.navisworks2026": {
@@ -361,11 +361,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
},
diff --git a/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Bindings/NavisworksSendBinding.cs b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Bindings/NavisworksSendBinding.cs
index e5afddd40..a76394d72 100644
--- a/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Bindings/NavisworksSendBinding.cs
+++ b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Bindings/NavisworksSendBinding.cs
@@ -5,7 +5,6 @@ using Speckle.Connector.Navisworks.Operations.Send.Filters;
using Speckle.Connector.Navisworks.Operations.Send.Settings;
using Speckle.Connector.Navisworks.Services;
using Speckle.Connectors.Common.Cancellation;
-using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
@@ -18,6 +17,7 @@ using Speckle.Converter.Navisworks.Services;
using Speckle.Converter.Navisworks.Settings;
using Speckle.Converters.Common;
using Speckle.Sdk.Common;
+using Speckle.Sdk.Pipelines.Progress;
namespace Speckle.Connector.Navisworks.Bindings;
diff --git a/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/DependencyInjection/NavisworksConnectorServiceRegistration.cs b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/DependencyInjection/NavisworksConnectorServiceRegistration.cs
index 845b6ed62..cb9ab254e 100644
--- a/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/DependencyInjection/NavisworksConnectorServiceRegistration.cs
+++ b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/DependencyInjection/NavisworksConnectorServiceRegistration.cs
@@ -57,6 +57,7 @@ public static class NavisworksConnectorServiceRegistration
// Sending operations
serviceCollection.AddScoped, NavisworksRootObjectBuilder>();
+ serviceCollection.AddScoped, NavisworksContinuousTraversalBuilder>();
serviceCollection.AddScoped>();
serviceCollection.AddSingleton(DefaultTraversal.CreateTraversalFunc());
serviceCollection.AddSingleton();
diff --git a/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Operations/Send/NavisworksContinuousTraversalBuilder.cs b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Operations/Send/NavisworksContinuousTraversalBuilder.cs
new file mode 100644
index 000000000..ab1563a46
--- /dev/null
+++ b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Operations/Send/NavisworksContinuousTraversalBuilder.cs
@@ -0,0 +1,400 @@
+using Microsoft.Extensions.Logging;
+using Speckle.Connector.Navisworks.HostApp;
+using Speckle.Connectors.Common.Builders;
+using Speckle.Connectors.Common.Conversion;
+using Speckle.Converter.Navisworks.Helpers;
+using Speckle.Converter.Navisworks.Services;
+using Speckle.Converter.Navisworks.Settings;
+using Speckle.Converters.Common;
+using Speckle.Objects.Data;
+using Speckle.Sdk;
+using Speckle.Sdk.Logging;
+using Speckle.Sdk.Models;
+using Speckle.Sdk.Models.Collections;
+using Speckle.Sdk.Models.Instances;
+using Speckle.Sdk.Pipelines.Progress;
+using Speckle.Sdk.Pipelines.Send;
+using static Speckle.Connector.Navisworks.Operations.Send.GeometryNodeMerger;
+using static Speckle.Connectors.Common.Operations.ProxyKeys;
+using static Speckle.Converter.Navisworks.Constants.InstanceConstants;
+
+namespace Speckle.Connector.Navisworks.Operations.Send;
+
+///
+/// Continuous traversal builder for Navisworks that streams objects through a
+/// for packfile-based uploads. Same conversion/grouping logic as ,
+/// but processes final elements through the pipeline after all post-processing is complete.
+///
+public class NavisworksContinuousTraversalBuilder(
+ IRootToSpeckleConverter rootToSpeckleConverter,
+ IConverterSettingsStore converterSettings,
+ ILogger logger,
+ ISdkActivityFactory activityFactory,
+ NavisworksMaterialUnpacker materialUnpacker,
+ NavisworksColorUnpacker colorUnpacker,
+ Speckle.Converter.Navisworks.Constants.Registers.IInstanceFragmentRegistry instanceRegistry,
+ IElementSelectionService elementSelectionService,
+ IUiUnitsCache uiUnitsCache
+) : IRootContinuousTraversalBuilder
+{
+ private bool SkipNodeMerging { get; set; }
+ private bool DisableGroupingForInstanceTesting { get; set; }
+
+ public async Task Build(
+ IReadOnlyList navisworksModelItems,
+ string projectId,
+ SendPipeline sendPipeline,
+ IProgress onOperationProgressed,
+ CancellationToken cancellationToken
+ )
+ {
+#if DEBUG
+ SkipNodeMerging = false;
+ DisableGroupingForInstanceTesting = false;
+#endif
+ using var activity = activityFactory.Start("Build");
+
+ ValidateInputs(navisworksModelItems, projectId, onOperationProgressed);
+
+ var rootCollection = InitializeRootCollection();
+ (Dictionary convertedElements, List conversionResults) =
+ await ConvertModelItemsAsync(navisworksModelItems, onOperationProgressed, cancellationToken);
+
+ ValidateConversionResults(conversionResults);
+
+ var groupedNodes = SkipNodeMerging ? [] : GroupSiblingGeometryNodes(navisworksModelItems);
+ var finalElements = BuildFinalElements(convertedElements, groupedNodes);
+
+ await AddProxiesToCollection(rootCollection, navisworksModelItems, groupedNodes);
+
+ AddInstanceDefinitionsToCollection(rootCollection, ref finalElements);
+
+ // Process each final element through the send pipeline
+ var processedElements = new List(finalElements.Count);
+ foreach (var element in finalElements)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ // NOTE: this is the main part that differentiate from the main root object builder
+ var reference = await sendPipeline.Process(element).ConfigureAwait(false);
+ processedElements.Add(reference);
+ }
+
+ rootCollection.elements = processedElements;
+
+ // Process the root collection and wait for all uploads to complete
+ await sendPipeline.Process(rootCollection);
+ await sendPipeline.WaitForUpload();
+
+ return new RootObjectBuilderResult(rootCollection, conversionResults);
+ }
+
+ private static void ValidateInputs(
+ IReadOnlyList navisworksModelItems,
+ string projectId,
+ IProgress onOperationProgressed
+ )
+ {
+ if (!navisworksModelItems.Any())
+ {
+ throw new SpeckleException("No objects to convert");
+ }
+
+ if (navisworksModelItems == null)
+ {
+ throw new ArgumentNullException(nameof(navisworksModelItems));
+ }
+
+ if (onOperationProgressed == null || projectId == null)
+ {
+ throw new ArgumentNullException(
+ onOperationProgressed == null ? nameof(onOperationProgressed) : nameof(projectId)
+ );
+ }
+ }
+
+ private Collection InitializeRootCollection() =>
+ new()
+ {
+ name = NavisworksApp.ActiveDocument.Title ?? "Unnamed model",
+ ["units"] = converterSettings.Current.Derived.SpeckleUnits
+ };
+
+ private Task<(Dictionary converted, List results)> ConvertModelItemsAsync(
+ IReadOnlyList navisworksModelItems,
+ IProgress onOperationProgressed,
+ CancellationToken cancellationToken
+ )
+ {
+ var results = new List(navisworksModelItems.Count);
+ var convertedBases = new Dictionary();
+ int processedCount = 0;
+ int totalCount = navisworksModelItems.Count;
+
+ foreach (var item in navisworksModelItems)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ var converted = ConvertNavisworksItem(item, convertedBases);
+ results.Add(converted);
+
+ processedCount++;
+ onOperationProgressed.Report(new CardProgress("Converting", (double)processedCount / totalCount));
+ }
+
+ return Task.FromResult((convertedBases, results));
+ }
+
+ private static void ValidateConversionResults(List results)
+ {
+ if (results.All(x => x.Status == Status.ERROR))
+ {
+ throw new SpeckleException("Failed to convert all objects.");
+ }
+ }
+
+ private List BuildFinalElements(
+ Dictionary convertedBases,
+ Dictionary> groupedNodes
+ )
+ {
+ var finalElements = new List();
+ var processedPaths = new HashSet();
+
+ if (!DisableGroupingForInstanceTesting)
+ {
+ AddGroupedElements(finalElements, convertedBases, groupedNodes, processedPaths);
+ logger.LogInformation(
+ "After grouping: {grouped} paths processed, {elements} elements in collection",
+ processedPaths.Count,
+ finalElements.Count
+ );
+ }
+ else
+ {
+ logger.LogInformation("Grouping disabled for instance testing");
+ }
+
+ if (converterSettings.Current.User.PreserveModelHierarchy)
+ {
+ logger.LogInformation("Building hierarchy (PreserveModelHierarchy=true)");
+ var hierarchyBuilder = new NavisworksHierarchyBuilder(
+ convertedBases,
+ rootToSpeckleConverter,
+ elementSelectionService
+ );
+
+ return hierarchyBuilder.BuildHierarchy();
+ }
+
+ logger.LogInformation("Adding remaining elements (flat mode)");
+ AddRemainingElements(finalElements, convertedBases, processedPaths);
+
+ logger.LogInformation("Final elements count: {count}", finalElements.Count);
+ return finalElements;
+ }
+
+ private void AddGroupedElements(
+ List finalElements,
+ Dictionary convertedBases,
+ Dictionary> groupedNodes,
+ HashSet processedPaths
+ )
+ {
+ foreach (var group in groupedNodes)
+ {
+ var siblingBases = new List(group.Value.Count);
+ foreach (var itemPath in group.Value.Select(elementSelectionService.GetModelItemPath))
+ {
+ processedPaths.Add(itemPath);
+ if (convertedBases.TryGetValue(itemPath, out var convertedBase) && convertedBase != null)
+ {
+ siblingBases.Add(convertedBase);
+ }
+ }
+
+ if (siblingBases.Count > 0)
+ {
+ finalElements.Add(CreateNavisworksObject(group.Key, siblingBases));
+ }
+ }
+ }
+
+ private void AddRemainingElements(
+ List finalElements,
+ Dictionary convertedBases,
+ HashSet processedPaths
+ )
+ {
+ foreach (var kvp in convertedBases.Where(kvp => !processedPaths.Contains(kvp.Key)))
+ {
+ switch (kvp.Value)
+ {
+ case null:
+ continue;
+ case Collection collection:
+ finalElements.Add(collection);
+ break;
+ default:
+ if (CreateNavisworksObject(kvp.Value) is { } navisworksObject)
+ {
+ finalElements.Add(navisworksObject);
+ }
+
+ break;
+ }
+ }
+ }
+
+ private (string name, string path) GetElementNameAndPath(string applicationId)
+ {
+ var modelItem = elementSelectionService.GetModelItemFromPath(applicationId);
+ var context = HierarchyHelper.ExtractContext(modelItem);
+ return (context.Name, context.Path);
+ }
+
+ private NavisworksObject CreateNavisworksObject(string groupKey, List siblingBases)
+ {
+ string cleanParentPath = ElementSelectionHelper.GetCleanPath(groupKey);
+ (string name, string path) = GetElementNameAndPath(cleanParentPath);
+
+ int estimatedCapacity = siblingBases.Sum(b => (b["displayValue"] as List)?.Count ?? 0);
+ var displayValues = new List(estimatedCapacity);
+ displayValues.AddRange(
+ siblingBases
+ .Where(sibling => sibling["displayValue"] is List)
+ .SelectMany(sibling => (List)sibling["displayValue"]!)
+ );
+
+ return new NavisworksObject
+ {
+ name = name,
+ displayValue = displayValues,
+ properties = siblingBases.First()["properties"] as Dictionary ?? [],
+ units = converterSettings.Current.Derived.SpeckleUnits,
+ applicationId = groupKey,
+ ["path"] = path
+ };
+ }
+
+ private NavisworksObject? CreateNavisworksObject(Base convertedBase)
+ {
+ if (convertedBase.applicationId == null)
+ {
+ return null;
+ }
+
+ (string name, string path) = GetElementNameAndPath(convertedBase.applicationId);
+
+ var units = uiUnitsCache.Ensure();
+
+ return new NavisworksObject
+ {
+ name = name,
+ displayValue = convertedBase["displayValue"] as List ?? [],
+ properties = convertedBase["properties"] as Dictionary ?? [],
+ units = units.ToString(),
+ applicationId = convertedBase.applicationId,
+ ["path"] = path
+ };
+ }
+
+ private Task AddProxiesToCollection(
+ Collection rootCollection,
+ IReadOnlyList navisworksModelItems,
+ Dictionary> groupedNodes
+ )
+ {
+ using var _ = activityFactory.Start("UnpackProxies");
+
+ var renderMaterials = materialUnpacker.UnpackRenderMaterial(navisworksModelItems, groupedNodes);
+ if (renderMaterials.Count > 0)
+ {
+ rootCollection[RENDER_MATERIAL] = renderMaterials;
+ }
+
+ var colors = colorUnpacker.UnpackColor(navisworksModelItems, groupedNodes);
+ if (colors.Count > 0)
+ {
+ rootCollection[COLOR] = colors;
+ }
+
+ return Task.CompletedTask;
+ }
+
+ private void AddInstanceDefinitionsToCollection(Collection rootCollection, ref List finalElements)
+ {
+ using var _ = activityFactory.Start("BuildInstanceDefinitions");
+
+ var allDefinitions = instanceRegistry.GetAllDefinitionGeometries();
+
+ if (allDefinitions.Count == 0)
+ {
+ logger.LogInformation("No instance definitions found - instancing may be disabled");
+ return;
+ }
+
+ logger.LogInformation("Building instance structure for {count} definition groups", allDefinitions.Count);
+
+ var instanceDefinitionProxies = new List(allDefinitions.Count);
+
+ int estimatedGeometryCount = allDefinitions.Sum(kvp => kvp.Value.Count);
+ var allDefinitionGeometries = new List(estimatedGeometryCount);
+
+ foreach (var kvp in allDefinitions)
+ {
+ var groupKey = kvp.Key;
+ var geometries = kvp.Value;
+ var groupKeyPath = groupKey.ToPathString();
+
+ var defProxy = new InstanceDefinitionProxy
+ {
+ name = $"Shared Geometry {groupKeyPath}",
+ objects = geometries.Select(g => g.applicationId ?? "").Where(id => !string.IsNullOrEmpty(id)).ToList(),
+ applicationId = $"{DEFINITION_ID_PREFIX}{groupKeyPath}",
+ maxDepth = 0
+ };
+
+ instanceDefinitionProxies.Add(defProxy);
+ allDefinitionGeometries.AddRange(geometries);
+ }
+
+ rootCollection[INSTANCE_DEFINITION] = instanceDefinitionProxies;
+ var geometryDefinitionsCollection = new Collection
+ {
+ name = "Geometry Definitions",
+ elements = allDefinitionGeometries
+ };
+
+ var objectCollection = new Collection { name = "", elements = finalElements };
+
+ finalElements = [geometryDefinitionsCollection, objectCollection];
+
+ logger.LogInformation(
+ "Added {proxyCount} instance definition proxies and {geomCount} definition geometries",
+ instanceDefinitionProxies.Count,
+ allDefinitionGeometries.Count
+ );
+ }
+
+ private SendConversionResult ConvertNavisworksItem(
+ NAV.ModelItem navisworksItem,
+ Dictionary convertedBases
+ )
+ {
+ string applicationId = elementSelectionService.GetModelItemPath(navisworksItem);
+ string sourceType = navisworksItem.GetType().Name;
+
+ try
+ {
+ Base converted = rootToSpeckleConverter.Convert(navisworksItem);
+
+ convertedBases[applicationId] = converted;
+
+ return new SendConversionResult(Status.SUCCESS, applicationId, sourceType, converted);
+ }
+ catch (Exception ex) when (!ex.IsFatal())
+ {
+ logger.LogError(ex, "Failed to convert model item {id}", applicationId);
+ return new SendConversionResult(Status.ERROR, applicationId, "ModelItem", null, ex);
+ }
+ }
+}
diff --git a/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Operations/Send/NavisworksRootObjectBuilder.cs b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Operations/Send/NavisworksRootObjectBuilder.cs
index 9297b38af..45185cf43 100644
--- a/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Operations/Send/NavisworksRootObjectBuilder.cs
+++ b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Operations/Send/NavisworksRootObjectBuilder.cs
@@ -3,7 +3,6 @@ using Speckle.Connector.Navisworks.HostApp;
using Speckle.Connectors.Common.Builders;
using Speckle.Connectors.Common.Caching;
using Speckle.Connectors.Common.Conversion;
-using Speckle.Connectors.Common.Operations;
using Speckle.Converter.Navisworks.Helpers;
using Speckle.Converter.Navisworks.Services;
using Speckle.Converter.Navisworks.Settings;
@@ -14,6 +13,7 @@ using Speckle.Sdk.Logging;
using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Collections;
using Speckle.Sdk.Models.Instances;
+using Speckle.Sdk.Pipelines.Progress;
using static Speckle.Connector.Navisworks.Operations.Send.GeometryNodeMerger;
using static Speckle.Connectors.Common.Operations.ProxyKeys;
using static Speckle.Converter.Navisworks.Constants.InstanceConstants;
diff --git a/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Speckle.Connectors.NavisworksShared.projitems b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Speckle.Connectors.NavisworksShared.projitems
index 9e2fd10e7..7581669d9 100644
--- a/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Speckle.Connectors.NavisworksShared.projitems
+++ b/Connectors/Navisworks/Speckle.Connectors.NavisworksShared/Speckle.Connectors.NavisworksShared.projitems
@@ -24,6 +24,7 @@
+
diff --git a/Connectors/Revit/Speckle.Connectors.Revit2022/packages.lock.json b/Connectors/Revit/Speckle.Connectors.Revit2022/packages.lock.json
index 5e9ea6995..728d609f6 100644
--- a/Connectors/Revit/Speckle.Connectors.Revit2022/packages.lock.json
+++ b/Connectors/Revit/Speckle.Connectors.Revit2022/packages.lock.json
@@ -193,8 +193,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -203,13 +203,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -312,7 +312,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -335,7 +335,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.converters.revit2022": {
@@ -387,11 +387,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
},
"Speckle.Revit.API": {
diff --git a/Connectors/Revit/Speckle.Connectors.Revit2023/packages.lock.json b/Connectors/Revit/Speckle.Connectors.Revit2023/packages.lock.json
index 71d13d333..f69fc3cbb 100644
--- a/Connectors/Revit/Speckle.Connectors.Revit2023/packages.lock.json
+++ b/Connectors/Revit/Speckle.Connectors.Revit2023/packages.lock.json
@@ -193,8 +193,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -203,13 +203,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -312,7 +312,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -335,7 +335,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.converters.revit2023": {
@@ -387,11 +387,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
},
"Speckle.Revit.API": {
diff --git a/Connectors/Revit/Speckle.Connectors.Revit2024/packages.lock.json b/Connectors/Revit/Speckle.Connectors.Revit2024/packages.lock.json
index e82afd090..6086a184f 100644
--- a/Connectors/Revit/Speckle.Connectors.Revit2024/packages.lock.json
+++ b/Connectors/Revit/Speckle.Connectors.Revit2024/packages.lock.json
@@ -193,8 +193,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -203,13 +203,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -312,7 +312,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -335,7 +335,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.converters.revit2024": {
@@ -387,11 +387,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
},
"Speckle.Revit.API": {
diff --git a/Connectors/Revit/Speckle.Connectors.Revit2025/packages.lock.json b/Connectors/Revit/Speckle.Connectors.Revit2025/packages.lock.json
index 36807b2cf..bb2bd99b9 100644
--- a/Connectors/Revit/Speckle.Connectors.Revit2025/packages.lock.json
+++ b/Connectors/Revit/Speckle.Connectors.Revit2025/packages.lock.json
@@ -173,8 +173,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -182,13 +182,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -253,7 +253,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -276,7 +276,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.converters.revit2025": {
@@ -328,11 +328,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
},
"Speckle.Revit.API": {
diff --git a/Connectors/Revit/Speckle.Connectors.Revit2026/packages.lock.json b/Connectors/Revit/Speckle.Connectors.Revit2026/packages.lock.json
index a9988c7a6..dd881eeb2 100644
--- a/Connectors/Revit/Speckle.Connectors.Revit2026/packages.lock.json
+++ b/Connectors/Revit/Speckle.Connectors.Revit2026/packages.lock.json
@@ -166,8 +166,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -175,13 +175,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -246,7 +246,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -269,7 +269,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.converters.revit2026": {
@@ -312,11 +312,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
},
"Speckle.Revit.API": {
diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/RevitParametersBinding.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/RevitParametersBinding.cs
index 6f618ff75..48a33d0bb 100644
--- a/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/RevitParametersBinding.cs
+++ b/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/RevitParametersBinding.cs
@@ -1,4 +1,5 @@
using Autodesk.Revit.DB;
+using Microsoft.Extensions.Logging;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Utils;
@@ -34,6 +35,7 @@ internal sealed class RevitParametersBinding : IParametersBinding
private readonly ParameterUpdater _parameterUpdater;
private readonly IJsonSerializer _jsonSerializer;
private readonly IBasicConnectorBinding _baseBinding;
+ private readonly ILogger _logger;
public RevitParametersBinding(
IBrowserBridge parent,
@@ -42,7 +44,8 @@ internal sealed class RevitParametersBinding : IParametersBinding
IRevitTask revitTask,
ParameterUpdater parameterUpdater,
IJsonSerializer jsonSerializer,
- IBasicConnectorBinding baseBinding
+ IBasicConnectorBinding baseBinding,
+ ILogger logger
)
{
Parent = parent;
@@ -52,6 +55,7 @@ internal sealed class RevitParametersBinding : IParametersBinding
_parameterUpdater = parameterUpdater;
_jsonSerializer = jsonSerializer;
_baseBinding = baseBinding;
+ _logger = logger;
}
public async Task Update(string payload)
@@ -123,19 +127,36 @@ internal sealed class RevitParametersBinding : IParametersBinding
if (errors.Count > 0)
{
- var groupedErrors = errors.GroupBy(e => e).Select(g => g.Count() > 1 ? $"{g.Count()} x {g.Key}" : g.Key);
- await _baseBinding.Commands.SetGlobalNotification(
- ToastNotificationType.WARNING,
- "Update Completed with Issues",
- $"Applied {successCount} updates. Encountered {errors.Count} errors: {string.Join(" | ", groupedErrors)}",
- autoClose: false
- );
+ var groupedErrors = errors.GroupBy(e => e).Select(g => $"{g.Count()} x {g.Key}");
+ var errorString = string.Join(", ", groupedErrors);
+
+ if (successCount > 0)
+ {
+ // Partial Success (Some worked, some failed)
+ await _baseBinding.Commands.SetGlobalNotification(
+ ToastNotificationType.WARNING,
+ "Parameters updated with errors",
+ $"Applied {successCount} updates. Encountered {errors.Count} errors: {errorString}",
+ autoClose: false
+ );
+ }
+ else
+ {
+ // Total Failure (None worked)
+ await _baseBinding.Commands.SetGlobalNotification(
+ ToastNotificationType.DANGER,
+ "No parameters updated",
+ $"All {errors.Count} updates failed: {errorString}",
+ autoClose: false
+ );
+ }
}
- else
+ else if (successCount > 0)
{
+ // Total Success
await _baseBinding.Commands.SetGlobalNotification(
ToastNotificationType.SUCCESS,
- "Parameters Updated",
+ "All parameters updated",
$"Successfully applied {successCount} updates."
);
}
@@ -162,28 +183,35 @@ internal sealed class RevitParametersBinding : IParametersBinding
if (string.IsNullOrEmpty(request.ApplicationId))
{
- errorMessage = "Missing ApplicationId.";
+ errorMessage = "Missing ApplicationId";
+ return false;
+ }
+
+ if (ContainsLinkedModelTransformHash(request.ApplicationId))
+ {
+ errorMessage = "Cannot modify elements from a linked model";
return false;
}
var elementId = ElementIdHelper.GetElementIdFromUniqueId(doc, request.ApplicationId);
if (elementId == null)
{
- errorMessage = $"Element UniqueId not found: {request.ApplicationId}";
+ errorMessage = "Element(s) not found in document";
return false;
}
element = doc.GetElement(elementId);
if (element == null)
{
- errorMessage = $"Element is null for Id: {elementId}";
+ errorMessage = "Element(s) not found in document";
return false;
}
var rawPath = request.Path;
if (string.IsNullOrEmpty(rawPath))
{
- errorMessage = "Path is missing.";
+ _logger.LogError("Widget / DUI payload error: parameter path missing");
+ errorMessage = "Parameter path is missing";
return false;
}
@@ -200,13 +228,21 @@ internal sealed class RevitParametersBinding : IParametersBinding
var pathParts = rawPath.Split(['.'], 3);
if (pathParts.Length != 3)
{
- errorMessage = $"Path must have 3 parts. Got: '{rawPath}'";
+ _logger.LogError(
+ "Path format error: Expected exactly 3 parts (Scope.Category.Name) but received '{RawPath}' for element",
+ rawPath
+ );
+ errorMessage = "Parameter path is incorrectly formatted";
return false;
}
parsedPath = new ParsedParameterPath(pathParts[0], pathParts[1], pathParts[2]);
return true;
}
+
+ private static bool ContainsLinkedModelTransformHash(string applicationId) =>
+ // Evaluates if the ID contains the standard transform hash for linked elements
+ System.Text.RegularExpressions.Regex.IsMatch(applicationId, @"_t[a-f0-9]+$");
}
public class ParameterChangesWrapper
diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/DependencyInjection/RevitConnectorModule.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/DependencyInjection/RevitConnectorModule.cs
index 7971cbb99..b496f4e1c 100644
--- a/Connectors/Revit/Speckle.Connectors.RevitShared/DependencyInjection/RevitConnectorModule.cs
+++ b/Connectors/Revit/Speckle.Connectors.RevitShared/DependencyInjection/RevitConnectorModule.cs
@@ -65,6 +65,7 @@ public static class ServiceRegistration
serviceCollection.AddScoped();
serviceCollection.AddScoped();
serviceCollection.AddScoped, RevitRootObjectBuilder>();
+ serviceCollection.AddScoped, RevitContinuousTraversalBuilder>();
serviceCollection.AddSingleton();
serviceCollection.AddSingleton();
serviceCollection.AddSingleton();
diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/HostApp/RevitFamilyBaker.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/HostApp/RevitFamilyBaker.cs
index b8c3d71da..85d6704fd 100644
--- a/Connectors/Revit/Speckle.Connectors.RevitShared/HostApp/RevitFamilyBaker.cs
+++ b/Connectors/Revit/Speckle.Connectors.RevitShared/HostApp/RevitFamilyBaker.cs
@@ -4,7 +4,6 @@ using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Structure;
using Microsoft.Extensions.Logging;
using Speckle.Connectors.Common.Conversion;
-using Speckle.Connectors.Common.Operations;
using Speckle.Converters.Common;
using Speckle.Converters.Common.Objects;
using Speckle.Converters.RevitShared.Helpers;
@@ -18,6 +17,7 @@ using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Collections;
using Speckle.Sdk.Models.GraphTraversal;
using Speckle.Sdk.Models.Instances;
+using Speckle.Sdk.Pipelines.Progress;
using DB = Autodesk.Revit.DB;
using Document = Autodesk.Revit.DB.Document;
diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Receive/RevitHostObjectBuilder.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Receive/RevitHostObjectBuilder.cs
index dc598a92e..054a31959 100644
--- a/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Receive/RevitHostObjectBuilder.cs
+++ b/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Receive/RevitHostObjectBuilder.cs
@@ -24,6 +24,7 @@ using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Collections;
using Speckle.Sdk.Models.GraphTraversal;
using Speckle.Sdk.Models.Instances;
+using Speckle.Sdk.Pipelines.Progress;
namespace Speckle.Connectors.Revit.Operations.Receive;
diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/RevitContinuousTraversalBuilder.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/RevitContinuousTraversalBuilder.cs
new file mode 100644
index 000000000..9cdf309f7
--- /dev/null
+++ b/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/RevitContinuousTraversalBuilder.cs
@@ -0,0 +1,318 @@
+using System.Diagnostics.CodeAnalysis;
+using Autodesk.Revit.DB;
+using Microsoft.Extensions.Logging;
+using Speckle.Connectors.Common.Builders;
+using Speckle.Connectors.Common.Caching;
+using Speckle.Connectors.Common.Conversion;
+using Speckle.Connectors.Common.Extensions;
+using Speckle.Connectors.Common.Operations;
+using Speckle.Connectors.Common.Threading;
+using Speckle.Connectors.DUI.Exceptions;
+using Speckle.Connectors.DUI.Settings;
+using Speckle.Connectors.Revit.HostApp;
+using Speckle.Converters.Common;
+using Speckle.Converters.RevitShared.Helpers;
+using Speckle.Converters.RevitShared.Settings;
+using Speckle.Sdk;
+using Speckle.Sdk.Common;
+using Speckle.Sdk.Models;
+using Speckle.Sdk.Models.Collections;
+using Speckle.Sdk.Pipelines.Progress;
+using Speckle.Sdk.Pipelines.Send;
+
+namespace Speckle.Connectors.Revit.Operations.Send;
+
+public class RevitContinuousTraversalBuilder(
+ IRootToSpeckleConverter converter,
+ IConverterSettingsStore converterSettings,
+ ISendConversionCache sendConversionCache,
+ ElementUnpacker elementUnpacker,
+ LevelUnpacker levelUnpacker,
+ ViewUnpacker viewUnpacker,
+ IThreadContext threadContext,
+ SendCollectionManager sendCollectionManager,
+ ILogger logger,
+ RevitToSpeckleCacheSingleton revitToSpeckleCacheSingleton,
+ LinkedModelHandler linkedModelHandler,
+ IConfigStore configStore
+) : IRootContinuousTraversalBuilder
+{
+ public async Task Build(
+ IReadOnlyList documentElementContexts,
+ string projectId,
+ SendPipeline sendPipeline,
+ IProgress onOperationProgressed,
+ CancellationToken cancellationToken
+ )
+ {
+ return await threadContext.RunOnMainAsync(
+ async () =>
+ await BuildMainThread(
+ documentElementContexts,
+ projectId,
+ sendPipeline,
+ onOperationProgressed,
+ cancellationToken
+ )
+ );
+ }
+
+ [SuppressMessage("Maintainability", "CA1502:Avoid excessive class coupling")]
+ [SuppressMessage("Maintainability", "CA1506:Avoid excessive class coupling")]
+ private async Task BuildMainThread(
+ IReadOnlyList documentElementContexts,
+ string projectId,
+ SendPipeline sendPipeline,
+ IProgress onOperationProgressed,
+ CancellationToken cancellationToken
+ )
+ {
+ var doc = converterSettings.Current.Document;
+
+ if (doc.IsFamilyDocument)
+ {
+ throw new SpeckleException("Family Environment documents are not supported.");
+ }
+
+ // init the root
+ Collection rootObject =
+ new() { name = converterSettings.Current.Document.PathName.Split('\\').Last().Split('.').First() };
+ rootObject["units"] = converterSettings.Current.SpeckleUnits;
+
+ var filteredDocumentsToConvert = new List();
+ bool sendWithLinkedModels = converterSettings.Current.SendLinkedModels;
+ List results = new();
+
+ // Prepare linked model display names if needed
+ if (sendWithLinkedModels)
+ {
+ linkedModelHandler.PrepareLinkedModelNames(documentElementContexts);
+ }
+
+ foreach (var documentElementContext in documentElementContexts)
+ {
+ // add appropriate warnings for linked documents
+ if (documentElementContext.Doc.IsLinked && !sendWithLinkedModels)
+ {
+ results.Add(
+ new(
+ Status.WARNING,
+ documentElementContext.Doc.PathName,
+ typeof(RevitLinkInstance).ToString(),
+ null,
+ new SpeckleException("Enable linked model support from the settings to send this object")
+ )
+ );
+ continue;
+ }
+
+ // filter for valid elements
+ // if send linked models setting is disabled List will be empty, and we won't enter foreach loop
+ var elementsInTransform = new List();
+ foreach (var el in documentElementContext.Elements)
+ {
+ if (el == null || el.Category == null)
+ {
+ continue;
+ }
+ elementsInTransform.Add(el);
+ }
+
+ // only add contexts with elements
+ if (elementsInTransform.Count > 0)
+ {
+ filteredDocumentsToConvert.Add(documentElementContext with { Elements = elementsInTransform });
+ }
+ }
+
+ // TODO: check the exception!!!!
+ if (filteredDocumentsToConvert.Count == 0)
+ {
+ throw new SpeckleSendFilterException("No objects were found. Please update your publish filter!");
+ }
+
+ // Unpack groups (& other complex data structures)
+ var atomicObjectsByDocumentAndTransform = new List();
+ var atomicObjectCount = 0;
+ foreach (var filteredDocumentToConvert in filteredDocumentsToConvert)
+ {
+ using (
+ converterSettings.Push(currentSettings => currentSettings with { Document = filteredDocumentToConvert.Doc })
+ )
+ {
+ var atomicObjects = elementUnpacker
+ .UnpackSelectionForConversion(filteredDocumentToConvert.Elements, filteredDocumentToConvert.Doc)
+ .ToList();
+ atomicObjectsByDocumentAndTransform.Add(filteredDocumentToConvert with { Elements = atomicObjects });
+ atomicObjectCount += atomicObjects.Count;
+ }
+ }
+
+ var count = 0;
+ var cacheHitCount = 0;
+ var skippedObjectCount = 0;
+
+ var config = configStore.GetConnectorConfig();
+
+ foreach (var atomicObjectByDocumentAndTransform in atomicObjectsByDocumentAndTransform)
+ {
+ string? modelDisplayName = null;
+ if (atomicObjectByDocumentAndTransform.Doc.IsLinked)
+ {
+ string id = linkedModelHandler.GetIdFromDocumentToConvert(atomicObjectByDocumentAndTransform);
+ linkedModelHandler.LinkedModelDisplayNames.TryGetValue(id, out modelDisplayName);
+ }
+
+ // here we do magic for changing the transform and the related document according to model. first one is always the main model.
+ using (
+ converterSettings.Push(currentSettings =>
+ currentSettings with
+ {
+ ReferencePointTransform = atomicObjectByDocumentAndTransform.Transform,
+ Document = atomicObjectByDocumentAndTransform.Doc,
+ }
+ )
+ )
+ {
+ var atomicObjects = atomicObjectByDocumentAndTransform.Elements;
+ foreach (Element revitElement in atomicObjects)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ string applicationId = revitElement.UniqueId;
+ string sourceType = revitElement.GetType().Name;
+ try
+ {
+ if (!SupportedCategoriesUtils.IsSupportedCategory(revitElement.Category))
+ {
+ var cat = revitElement.Category != null ? revitElement.Category.Name : "No category";
+ results.Add(
+ new(
+ Status.WARNING,
+ revitElement.UniqueId,
+ cat,
+ null,
+ new SpeckleException($"Category {cat} is not supported.")
+ )
+ );
+ skippedObjectCount++;
+ continue;
+ }
+
+ Base converted;
+ bool hasTransform = atomicObjectByDocumentAndTransform.Transform != null;
+
+ // non-transformed elements can safely rely on cache
+ // TODO: Potential here to transform cached objects and NOT reconvert,
+ // TODO: we wont do !hasTransform here, and re-set application id before this
+
+ if (
+ !hasTransform
+ && !config.DocumentChangeListeningDisabled //This is experimental
+ && sendConversionCache.TryGetValue(projectId, applicationId, out ObjectReference? value)
+ )
+ {
+ converted = value;
+ cacheHitCount++;
+ }
+ // not in cache means we convert
+ else
+ {
+ // if it has a transform we append transform hash to the applicationId to distinguish the elements from other instances
+ if (hasTransform)
+ {
+ string transformHash = linkedModelHandler.GetTransformHash(
+ atomicObjectByDocumentAndTransform.Transform.NotNull()
+ );
+ applicationId = $"{applicationId}_t{transformHash}";
+ }
+ // normal conversions
+ converted = converter.Convert(revitElement);
+ converted.applicationId = applicationId;
+ }
+
+ // NOTE: this is the main part that differentiate from the main root object builder
+ var reference = await sendPipeline.Process(converted).ConfigureAwait(true);
+
+ var collection = sendCollectionManager.GetAndCreateObjectHostCollection(
+ revitElement,
+ rootObject,
+ sendWithLinkedModels,
+ modelDisplayName
+ );
+
+ collection.elements.Add(reference);
+ results.Add(new(Status.SUCCESS, applicationId, sourceType, reference));
+ }
+ catch (Exception ex) when (!ex.IsFatal())
+ {
+ logger.LogSendConversionError(ex, sourceType);
+ results.Add(new(Status.ERROR, applicationId, sourceType, null, ex));
+ }
+
+ count++;
+ onOperationProgressed.Report(
+ new($"Converting objects... ({count:N0} / {atomicObjectCount:N0})", (double)count / atomicObjectCount)
+ );
+ }
+ }
+ }
+
+ // if we ended up skipping everything, there is a reason for this, that users can diagnose themselves
+ // this can occur if a published view contains only unsupported objects or if user trying to ONLY send linked model
+ // docs but the setting is disabled
+ if (skippedObjectCount == atomicObjectCount)
+ {
+ throw new SpeckleException("No supported objects visible. Update publish filter or check publish settings.");
+ }
+
+ // this is, I suppose, fully on us?
+ if (results.All(x => x.Status == Status.ERROR))
+ {
+ throw new SpeckleException("Failed to convert all objects.");
+ }
+
+ // STEP 5: Unpack proxies to attach to root collection
+ var flatElements = atomicObjectsByDocumentAndTransform.SelectMany(t => t.Elements).ToList();
+ var idsAndSubElementIds = elementUnpacker.GetElementsAndSubelementIdsFromAtomicObjects(flatElements);
+
+ var renderMaterialProxies = revitToSpeckleCacheSingleton.GetRenderMaterialProxyListForObjects(idsAndSubElementIds);
+ rootObject[ProxyKeys.RENDER_MATERIAL] = renderMaterialProxies;
+
+ var levelProxies = levelUnpacker.Unpack(flatElements);
+ rootObject[ProxyKeys.LEVEL] = levelProxies;
+
+ rootObject[ProxyKeys.INSTANCE_DEFINITION] = revitToSpeckleCacheSingleton.GetInstanceDefinitionProxiesForObjects(
+ idsAndSubElementIds
+ );
+ rootObject.elements.Add(
+ new Collection()
+ {
+ elements = revitToSpeckleCacheSingleton.GetBaseObjectsForObjects(idsAndSubElementIds),
+ name = "definitionGeometry"
+ }
+ );
+
+ // STEP 6: Unpack all other objects to attach to root collection
+ List views = viewUnpacker.Unpack(converterSettings.Current.Document);
+
+ if (views.Count > 0)
+ {
+ rootObject[RootKeys.VIEW] = views;
+ }
+
+ // NOTE: these are currently not used anywhere, we'll skip them until someone calls for it back
+ // rootObject[ProxyKeys.PARAMETER_DEFINITIONS] = _parameterDefinitionHandler.Definitions;
+
+ // we want to store transform data for chosen reference point setting
+ if (converterSettings.Current.ReferencePointTransform is Transform transform)
+ {
+ var transformMatrix = ReferencePointHelper.CreateTransformDataForRootObject(transform);
+ rootObject[RootKeys.REFERENCE_POINT_TRANSFORM] = transformMatrix;
+ }
+
+ await sendPipeline.Process(rootObject);
+ await sendPipeline.WaitForUpload();
+
+ return new RootObjectBuilderResult(rootObject, results);
+ }
+}
diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/RevitRootObjectBuilder.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/RevitRootObjectBuilder.cs
index d10c99190..7b3e58a9d 100644
--- a/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/RevitRootObjectBuilder.cs
+++ b/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/RevitRootObjectBuilder.cs
@@ -17,6 +17,7 @@ using Speckle.Sdk;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Collections;
+using Speckle.Sdk.Pipelines.Progress;
namespace Speckle.Connectors.Revit.Operations.Send;
@@ -39,7 +40,7 @@ public class RevitRootObjectBuilder(
IReadOnlyList documentElementContexts,
string projectId,
IProgress onOperationProgressed,
- CancellationToken ct = default
+ CancellationToken ct
) =>
threadContext.RunOnMainAsync(
() => Task.FromResult(BuildSync(documentElementContexts, projectId, onOperationProgressed, ct))
diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/Speckle.Connectors.RevitShared.projitems b/Connectors/Revit/Speckle.Connectors.RevitShared/Speckle.Connectors.RevitShared.projitems
index 0730a2580..f8431209c 100644
--- a/Connectors/Revit/Speckle.Connectors.RevitShared/Speckle.Connectors.RevitShared.projitems
+++ b/Connectors/Revit/Speckle.Connectors.RevitShared/Speckle.Connectors.RevitShared.projitems
@@ -60,6 +60,7 @@
+
diff --git a/Connectors/Rhino/Speckle.Connectors.Grasshopper7/packages.lock.json b/Connectors/Rhino/Speckle.Connectors.Grasshopper7/packages.lock.json
index 090b834bb..c88695c83 100644
--- a/Connectors/Rhino/Speckle.Connectors.Grasshopper7/packages.lock.json
+++ b/Connectors/Rhino/Speckle.Connectors.Grasshopper7/packages.lock.json
@@ -204,8 +204,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -214,13 +214,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -349,7 +349,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.logging": {
@@ -359,7 +359,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.converters.rhino7": {
@@ -404,11 +404,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Connectors/Rhino/Speckle.Connectors.Grasshopper8/packages.lock.json b/Connectors/Rhino/Speckle.Connectors.Grasshopper8/packages.lock.json
index dcc18d6a6..84587b574 100644
--- a/Connectors/Rhino/Speckle.Connectors.Grasshopper8/packages.lock.json
+++ b/Connectors/Rhino/Speckle.Connectors.Grasshopper8/packages.lock.json
@@ -204,8 +204,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -214,13 +214,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -349,7 +349,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.logging": {
@@ -359,7 +359,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.converters.rhino8": {
@@ -403,11 +403,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Receive/ReceiveAsyncComponent.cs b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Receive/ReceiveAsyncComponent.cs
index 2aa2573f9..75d9a9e88 100644
--- a/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Receive/ReceiveAsyncComponent.cs
+++ b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Receive/ReceiveAsyncComponent.cs
@@ -8,7 +8,6 @@ using GrasshopperAsyncComponent;
using Rhino;
using Speckle.Connectors.Common;
using Speckle.Connectors.Common.Analytics;
-using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Common.Operations.Receive;
using Speckle.Connectors.GrasshopperShared.HostApp;
using Speckle.Connectors.GrasshopperShared.Operations.Receive;
@@ -22,6 +21,7 @@ using Speckle.Sdk.Credentials;
using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Collections;
using Speckle.Sdk.Models.Extensions;
+using Speckle.Sdk.Pipelines.Progress;
namespace Speckle.Connectors.GrasshopperShared.Components.Operations.Receive;
diff --git a/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Receive/ReceiveComponent.cs b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Receive/ReceiveComponent.cs
index 015913adc..1f27dfa66 100644
--- a/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Receive/ReceiveComponent.cs
+++ b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Receive/ReceiveComponent.cs
@@ -3,7 +3,6 @@ using Microsoft.Extensions.DependencyInjection;
using Rhino;
using Speckle.Connectors.Common;
using Speckle.Connectors.Common.Analytics;
-using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Common.Operations.Receive;
using Speckle.Connectors.GrasshopperShared.Components.BaseComponents;
using Speckle.Connectors.GrasshopperShared.HostApp;
@@ -16,6 +15,7 @@ using Speckle.Sdk.Api;
using Speckle.Sdk.Api.GraphQL.Models;
using Speckle.Sdk.Credentials;
using Speckle.Sdk.Models.Collections;
+using Speckle.Sdk.Pipelines.Progress;
namespace Speckle.Connectors.GrasshopperShared.Components.Operations.Receive;
diff --git a/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Send/IngestionTracker.cs b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Send/IngestionTracker.cs
new file mode 100644
index 000000000..6238a5662
--- /dev/null
+++ b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Send/IngestionTracker.cs
@@ -0,0 +1,56 @@
+using Speckle.Sdk;
+using Speckle.Sdk.Api;
+using Speckle.Sdk.Api.GraphQL.Enums;
+using Speckle.Sdk.Common;
+
+namespace Speckle.Connectors.GrasshopperShared.Components.Operations.Send;
+
+///
+/// Polls ingestion status via the SDK's GraphQL query API
+/// and blocks until the ingestion reaches a terminal state (success/failed/cancelled).
+///
+///
+/// We use polling instead of subscriptions because GH components call WaitForIngestionCompletion
+/// after SendViaPackfile returns — by that point the server may have already completed
+/// the ingestion. Setting up a new WebSocket subscription is too slow to catch fast completions.
+/// Polling with Ingestion.Get() is reliable regardless of timing.
+///
+public class IngestionTracker
+{
+ private static readonly TimeSpan s_pollInterval = TimeSpan.FromSeconds(1);
+
+ public async Task WaitForIngestionCompletion(
+ IClient client,
+ string projectId,
+ string ingestionId,
+ Action? reportProgress,
+ string? reportProgressId,
+ CancellationToken cancellationToken
+ )
+ {
+ // NOTE: before start hating from this - read the class description
+ while (true)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ var ingestion = await client.Ingestion.Get(ingestionId, projectId, cancellationToken).ConfigureAwait(false);
+ var status = ingestion.statusData.status;
+
+ switch (status)
+ {
+ case ModelIngestionStatus.success:
+ return ingestion.statusData.versionId.NotNull();
+ case ModelIngestionStatus.failed:
+ throw new SpeckleException($"Server processing failed: {ingestion.statusData.progressMessage}");
+ case ModelIngestionStatus.cancelled:
+ throw new OperationCanceledException("Ingestion was cancelled by the server");
+ case ModelIngestionStatus.processing:
+ case ModelIngestionStatus.queued:
+ reportProgress?.Invoke(reportProgressId ?? "Server", 0);
+ break;
+ }
+
+ await Task.Delay(s_pollInterval, cancellationToken).ConfigureAwait(false);
+ }
+ }
+}
diff --git a/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Send/SendAsyncComponent.cs b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Send/SendAsyncComponent.cs
index 9f25e9676..bd45a382c 100644
--- a/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Send/SendAsyncComponent.cs
+++ b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Send/SendAsyncComponent.cs
@@ -20,6 +20,7 @@ using Speckle.Sdk.Api;
using Speckle.Sdk.Common;
using Speckle.Sdk.Credentials;
using Speckle.Sdk.Models.Extensions;
+using Speckle.Sdk.Pipelines.Progress;
namespace Speckle.Connectors.GrasshopperShared.Components.Operations.Send;
@@ -503,10 +504,26 @@ public class SendComponentWorker : WorkerInstance
});
using var scope = PriorityLoader.CreateScopeForActiveDocument();
var sendOperation = scope.ServiceProvider.GetRequiredService>();
- (SendOperationResult result, string versionId) = await sendOperation
+ (SendOperationResult result, string versionId, string? ingestionId) = await sendOperation
.Send([rootCollectionWrapper], sendInfo, fileName, fileBytes, Parent.VersionMessage, progress, CancellationToken)
.ConfigureAwait(false);
+ if (ingestionId != null)
+ {
+ Parent.Message = "Remote processing";
+ var ingestionTracker = scope.ServiceProvider.GetRequiredService();
+ versionId = await ingestionTracker
+ .WaitForIngestionCompletion(
+ Parent.ApiClient,
+ sendInfo.ProjectId,
+ ingestionId,
+ reportProgress,
+ Id,
+ CancellationToken
+ )
+ .ConfigureAwait(false);
+ }
+
// TODO: If we have NodeRun events later, better to have `ComponentTracker` to use across components
var customProperties = new Dictionary() { { "isAsync", true }, { "auto", Parent.AutoSend } };
if (sendInfo.WorkspaceId != null)
diff --git a/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Send/SendComponent.cs b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Send/SendComponent.cs
index 985df6ef8..e4ebd5077 100644
--- a/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Send/SendComponent.cs
+++ b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Send/SendComponent.cs
@@ -15,6 +15,7 @@ using Speckle.Sdk.Api;
using Speckle.Sdk.Common;
using Speckle.Sdk.Credentials;
using Speckle.Sdk.Models.Collections;
+using Speckle.Sdk.Pipelines.Progress;
namespace Speckle.Connectors.GrasshopperShared.Components.Operations.Send;
@@ -281,10 +282,26 @@ public class SendComponent : SpeckleTaskCapableComponent();
+ versionId = await ingestionTracker
+ .WaitForIngestionCompletion(
+ client,
+ sendInfo.ProjectId,
+ ingestionId,
+ reportProgress: null,
+ reportProgressId: null,
+ cancellationToken
+ )
+ .ConfigureAwait(false);
+ }
+
// TODO: If we have NodeRun events later, better to have `ComponentTracker` to use across components
var customProperties = new Dictionary { { "isAsync", false } };
if (sendInfo.WorkspaceId != null)
@@ -295,12 +312,13 @@ public class SendComponent : SpeckleTaskCapableComponent();
await mixpanel.TrackEvent(MixPanelEvents.Send, account, customProperties);
- SpeckleUrlLatestModelVersionResource createdVersionResource =
+ SpeckleUrlModelVersionResource createdVersionResource =
new(
new(sendInfo.Account.id, null, sendInfo.Account.serverInfo.url),
sendInfo.WorkspaceId,
sendInfo.ProjectId,
- sendInfo.ModelId
+ sendInfo.ModelId,
+ versionId
);
Url = $"{sendInfo.Account.serverInfo.url}/projects/{sendInfo.ProjectId}/models/{sendInfo.ModelId}";
return new SendComponentOutput(createdVersionResource, versionId);
diff --git a/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Operations/Receive/GrasshopperReceiveOperation.cs b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Operations/Receive/GrasshopperReceiveOperation.cs
index b8f9d0af8..6ce8d6e7a 100644
--- a/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Operations/Receive/GrasshopperReceiveOperation.cs
+++ b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Operations/Receive/GrasshopperReceiveOperation.cs
@@ -3,6 +3,7 @@ using Speckle.Connectors.Common.Operations;
using Speckle.Sdk.Api;
using Speckle.Sdk.Logging;
using Speckle.Sdk.Models;
+using Speckle.Sdk.Pipelines.Progress;
using Speckle.Sdk.Transports;
namespace Speckle.Connectors.GrasshopperShared.Operations.Receive;
diff --git a/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Operations/Send/GrasshopperContinuousTraversalBuilder.cs b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Operations/Send/GrasshopperContinuousTraversalBuilder.cs
new file mode 100644
index 000000000..75c6811a1
--- /dev/null
+++ b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Operations/Send/GrasshopperContinuousTraversalBuilder.cs
@@ -0,0 +1,221 @@
+using Speckle.Connectors.Common.Builders;
+using Speckle.Connectors.Common.Instances;
+using Speckle.Connectors.Common.Operations;
+using Speckle.Connectors.GrasshopperShared.HostApp;
+using Speckle.Connectors.GrasshopperShared.Parameters;
+using Speckle.Sdk.Models;
+using Speckle.Sdk.Models.Collections;
+using Speckle.Sdk.Pipelines.Progress;
+using Speckle.Sdk.Pipelines.Send;
+using DataObject = Speckle.Objects.Data.DataObject;
+
+namespace Speckle.Connectors.GrasshopperShared.Operations.Send;
+
+///
+/// Continuous traversal builder for Grasshopper that processes each object through the
+/// as it unwraps. This enables the packfile send path (streaming objects to S3 during build).
+///
+public class GrasshopperContinuousTraversalBuilder(
+ IInstanceObjectsManager> instanceObjectsManager
+) : IRootContinuousTraversalBuilder
+{
+ public async Task Build(
+ IReadOnlyList objects,
+ string projectId,
+ SendPipeline sendPipeline,
+ IProgress onOperationProgressed,
+ CancellationToken cancellationToken
+ )
+ {
+ // create root collection
+ var rootCollectionGoo = (SpeckleRootCollectionWrapperGoo)objects[0].Duplicate();
+ rootCollectionGoo.Value.Name = "Grasshopper Model";
+ RootCollection rootCollection =
+ new(rootCollectionGoo.Value.Name)
+ {
+ applicationId = rootCollectionGoo.Value.ApplicationId,
+ properties = rootCollectionGoo.Value.Properties ?? new()
+ };
+
+ // create packers for colors and render materials
+ GrasshopperColorPacker colorPacker = new();
+ GrasshopperMaterialPacker materialPacker = new();
+ GrasshopperBlockPacker blockPacker = new(instanceObjectsManager);
+
+ // unwrap the input collection, processing each object through the send pipeline
+ await Unwrap(
+ rootCollectionGoo.Value,
+ rootCollection,
+ colorPacker,
+ materialPacker,
+ blockPacker,
+ sendPipeline,
+ cancellationToken
+ )
+ .ConfigureAwait(false);
+
+ // add proxies
+ rootCollection[ProxyKeys.COLOR] = colorPacker.ColorProxies.Values.ToList();
+ rootCollection[ProxyKeys.RENDER_MATERIAL] = materialPacker.RenderMaterialProxies.Values.ToList();
+ rootCollection[ProxyKeys.INSTANCE_DEFINITION] = blockPacker.InstanceDefinitionProxies.Values.ToList();
+
+ // process the root collection through the pipeline and wait for all uploads
+ await sendPipeline.Process(rootCollection).ConfigureAwait(false);
+ await sendPipeline.WaitForUpload().ConfigureAwait(false);
+
+ // TODO: Not getting any conversion results yet
+ return new RootObjectBuilderResult(rootCollection, []);
+ }
+
+ private async Task Unwrap(
+ SpeckleCollectionWrapper wrapper,
+ Collection targetCollection,
+ GrasshopperColorPacker colorPacker,
+ GrasshopperMaterialPacker materialPacker,
+ GrasshopperBlockPacker blockPacker,
+ SendPipeline sendPipeline,
+ CancellationToken cancellationToken
+ )
+ {
+ colorPacker.ProcessColor(wrapper.ApplicationId, wrapper.Color);
+ materialPacker.ProcessMaterial(wrapper.ApplicationId, wrapper.Material);
+
+ int skippedNulls = 0;
+
+ foreach (ISpeckleCollectionObject? element in wrapper.Elements)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ switch (element)
+ {
+ case null:
+ skippedNulls++;
+ continue;
+
+ case SpeckleCollectionWrapper collWrapper:
+ collWrapper.ApplicationId ??= collWrapper.GetSpeckleApplicationId();
+ targetCollection.elements.Add(collWrapper.Collection);
+ await Unwrap(
+ collWrapper,
+ collWrapper.Collection,
+ colorPacker,
+ materialPacker,
+ blockPacker,
+ sendPipeline,
+ cancellationToken
+ )
+ .ConfigureAwait(false);
+ break;
+
+ case SpeckleGeometryWrapper so:
+ Base objectBase = UnwrapGeometry(so);
+ string applicationId = objectBase.applicationId!;
+
+ // NOTE: This is how it differentiate from 'GrasshopperSendOperation'
+ // It process through send pipeline before adding to collection
+ var reference = await sendPipeline.Process(objectBase).ConfigureAwait(false);
+ targetCollection.elements.Add(reference);
+
+ if (so is SpeckleBlockInstanceWrapper blockInstance)
+ {
+ await ProcessBlockInstanceDefinition(
+ blockInstance,
+ colorPacker,
+ materialPacker,
+ blockPacker,
+ targetCollection,
+ sendPipeline,
+ cancellationToken
+ )
+ .ConfigureAwait(false);
+ }
+
+ colorPacker.ProcessColor(applicationId, so.Color);
+ materialPacker.ProcessMaterial(applicationId, so.Material);
+ break;
+
+ case SpeckleDataObjectWrapper dataObjectWrapper:
+ DataObject dataObject = UnwrapDataObject(dataObjectWrapper, colorPacker, materialPacker);
+
+ // process data object through send pipeline
+ var dataRef = await sendPipeline.Process(dataObject).ConfigureAwait(false);
+ targetCollection.elements.Add(dataRef);
+ break;
+ }
+ }
+
+ // clear topology when nulls are present (CNX-2855)
+ if (skippedNulls > 0)
+ {
+ targetCollection[Constants.TOPOLOGY_PROP] = null;
+ }
+ }
+
+ private Base UnwrapGeometry(SpeckleGeometryWrapper wrapper)
+ {
+ Dictionary props = [];
+ Base baseObject = wrapper.Base;
+ if (wrapper.Properties.CastTo(ref props))
+ {
+ baseObject["properties"] = props;
+ }
+
+ return baseObject;
+ }
+
+ private async Task ProcessBlockInstanceDefinition(
+ SpeckleBlockInstanceWrapper blockInstance,
+ GrasshopperColorPacker colorPacker,
+ GrasshopperMaterialPacker materialPacker,
+ GrasshopperBlockPacker blockPacker,
+ Collection currentColl,
+ SendPipeline sendPipeline,
+ CancellationToken cancellationToken
+ )
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ var definitionObjects = blockPacker.ProcessInstance(blockInstance);
+
+ if (definitionObjects != null)
+ {
+ foreach (var definitionObject in definitionObjects)
+ {
+ Base defObjectBase = UnwrapGeometry(definitionObject);
+ string applicationId = defObjectBase.applicationId!;
+
+ var reference = await sendPipeline.Process(defObjectBase).ConfigureAwait(false);
+ currentColl.elements.Add(reference);
+
+ colorPacker.ProcessColor(applicationId, definitionObject.Color);
+ materialPacker.ProcessMaterial(applicationId, definitionObject.Material);
+ }
+ }
+ }
+
+ private DataObject UnwrapDataObject(
+ SpeckleDataObjectWrapper wrapper,
+ GrasshopperColorPacker colorPacker,
+ GrasshopperMaterialPacker materialPacker
+ )
+ {
+ DataObject dataObject = wrapper.DataObject;
+
+ var displayValue = new List();
+ foreach (var geometryWrapper in wrapper.Geometries)
+ {
+ Base geometryBase = UnwrapGeometry(geometryWrapper);
+ displayValue.Add(geometryBase);
+
+ if (geometryWrapper.ApplicationId != null)
+ {
+ colorPacker.ProcessColor(geometryWrapper.ApplicationId, geometryWrapper.Color);
+ materialPacker.ProcessMaterial(geometryWrapper.ApplicationId, geometryWrapper.Material);
+ }
+ }
+
+ dataObject.displayValue = displayValue;
+
+ return dataObject;
+ }
+}
diff --git a/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Operations/Send/GrasshopperSendOperation.cs b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Operations/Send/GrasshopperSendOperation.cs
index 8450fc871..37692db3a 100644
--- a/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Operations/Send/GrasshopperSendOperation.cs
+++ b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Operations/Send/GrasshopperSendOperation.cs
@@ -5,6 +5,7 @@ using Speckle.Connectors.GrasshopperShared.HostApp;
using Speckle.Connectors.GrasshopperShared.Parameters;
using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Collections;
+using Speckle.Sdk.Pipelines.Progress;
using DataObject = Speckle.Objects.Data.DataObject;
namespace Speckle.Connectors.GrasshopperShared.Operations.Send;
diff --git a/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Registration/PriorityLoader.cs b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Registration/PriorityLoader.cs
index bd1fec8b7..0d7c9532b 100644
--- a/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Registration/PriorityLoader.cs
+++ b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Registration/PriorityLoader.cs
@@ -9,6 +9,7 @@ using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Common.Operations.Receive;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.GrasshopperShared.Components;
+using Speckle.Connectors.GrasshopperShared.Components.Operations.Send;
using Speckle.Connectors.GrasshopperShared.HostApp;
using Speckle.Connectors.GrasshopperShared.Operations.Receive;
using Speckle.Connectors.GrasshopperShared.Operations.Send;
@@ -61,9 +62,14 @@ public class PriorityLoader : GH_AssemblyPriority
services.AddTransient();
services.AddScoped();
services.AddTransient();
+ services.AddTransient();
// send
services.AddTransient, GrasshopperRootObjectBuilder>();
+ services.AddTransient<
+ IRootContinuousTraversalBuilder,
+ GrasshopperContinuousTraversalBuilder
+ >();
services.AddTransient>();
services.AddSingleton(new DefaultThreadContext());
services.AddScoped<
diff --git a/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Speckle.Connectors.GrasshopperShared.projitems b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Speckle.Connectors.GrasshopperShared.projitems
index 11c8a8743..169d58a67 100644
--- a/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Speckle.Connectors.GrasshopperShared.projitems
+++ b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Speckle.Connectors.GrasshopperShared.projitems
@@ -58,7 +58,9 @@
+
+
diff --git a/Connectors/Rhino/Speckle.Connectors.Rhino7/packages.lock.json b/Connectors/Rhino/Speckle.Connectors.Rhino7/packages.lock.json
index e586c4f04..cc9a55eb6 100644
--- a/Connectors/Rhino/Speckle.Connectors.Rhino7/packages.lock.json
+++ b/Connectors/Rhino/Speckle.Connectors.Rhino7/packages.lock.json
@@ -185,8 +185,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -195,13 +195,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -330,7 +330,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -363,7 +363,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.converters.rhino7": {
@@ -423,11 +423,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
},
"System.Resources.Extensions": {
diff --git a/Connectors/Rhino/Speckle.Connectors.Rhino8/packages.lock.json b/Connectors/Rhino/Speckle.Connectors.Rhino8/packages.lock.json
index bb22cd074..15edfd5df 100644
--- a/Connectors/Rhino/Speckle.Connectors.Rhino8/packages.lock.json
+++ b/Connectors/Rhino/Speckle.Connectors.Rhino8/packages.lock.json
@@ -185,8 +185,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -195,13 +195,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -330,7 +330,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -363,7 +363,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.converters.rhino8": {
@@ -422,11 +422,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
},
"System.Resources.Extensions": {
diff --git a/Connectors/Rhino/Speckle.Connectors.RhinoImporter/packages.lock.json b/Connectors/Rhino/Speckle.Connectors.RhinoImporter/packages.lock.json
index e03e3af77..2db534724 100644
--- a/Connectors/Rhino/Speckle.Connectors.RhinoImporter/packages.lock.json
+++ b/Connectors/Rhino/Speckle.Connectors.RhinoImporter/packages.lock.json
@@ -29,20 +29,20 @@
},
"RhinoCommon": {
"type": "Direct",
- "requested": "[8.25.25328.11001, )",
- "resolved": "8.25.25328.11001",
- "contentHash": "PDKR9GwqyUXUkTulV4J0dzDIf/aWqSJkL7nkS8ReAx8xhnt/+RQpE8gTjOSCmkSU2tjG6WzclowbTxwMTU7VAA==",
+ "requested": "[8.28.26041.11001, )",
+ "resolved": "8.28.26041.11001",
+ "contentHash": "5mByZF+IdHvRLbYvr6Ek95Pwam6otewAyVHIGSC0sUE1+OscSpd9gbrFWnzo1arfCYmUJcUdsGhf7VayW09fQA==",
"dependencies": {
"System.Drawing.Common": "7.0.0"
}
},
"RhinoWindows": {
"type": "Direct",
- "requested": "[8.25.25328.11001, )",
- "resolved": "8.25.25328.11001",
- "contentHash": "I/+++piwtYTue+iAAQqcMF5QlontqwNnC7Leyhiv2FiF8JpAl6K44ZsJqB7ZEUC6ns0LDfa3mbFzQwUfHwYumQ==",
+ "requested": "[8.28.26041.11001, )",
+ "resolved": "8.28.26041.11001",
+ "contentHash": "7MBG231k5c0/V/USTzbXpaTCiZCECQOuB80DnpgEvvEA3r//IQQDTbrqawDYmN9BEw/FHiFn82bsf6tV+SS5Iw==",
"dependencies": {
- "RhinoCommon": "[8.25.25328.11001]"
+ "RhinoCommon": "[8.28.26041.11001]"
}
},
"Speckle.InterfaceGenerator": {
@@ -174,8 +174,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -183,13 +183,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -255,7 +255,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -279,7 +279,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.converters.rhino8": {
@@ -329,11 +329,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
},
diff --git a/Connectors/Rhino/Speckle.Connectors.RhinoShared/HostApp/RhinoInstanceBaker.cs b/Connectors/Rhino/Speckle.Connectors.RhinoShared/HostApp/RhinoInstanceBaker.cs
index 7ab39e1d6..77920b99b 100644
--- a/Connectors/Rhino/Speckle.Connectors.RhinoShared/HostApp/RhinoInstanceBaker.cs
+++ b/Connectors/Rhino/Speckle.Connectors.RhinoShared/HostApp/RhinoInstanceBaker.cs
@@ -2,9 +2,9 @@ using Microsoft.Extensions.Logging;
using Rhino;
using Rhino.DocObjects;
using Rhino.Geometry;
+using Rhino.Render;
using Speckle.Connectors.Common.Conversion;
using Speckle.Connectors.Common.Instances;
-using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Rhino.Extensions;
using Speckle.Converters.Common.ToHost;
using Speckle.DoubleNumerics;
@@ -14,6 +14,7 @@ using Speckle.Sdk.Common.Exceptions;
using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Collections;
using Speckle.Sdk.Models.Instances;
+using Speckle.Sdk.Pipelines.Progress;
namespace Speckle.Connectors.Rhino.HostApp;
@@ -137,9 +138,11 @@ public class RhinoInstanceBaker : IInstanceBaker>
// create attributes
ObjectAttributes atts = instanceProxy.GetAttributes();
atts.LayerIndex = layerIndex;
- if (_materialBaker.ObjectIdAndMaterialIndexMap.TryGetValue(instanceProxyId, out int mIndex))
+
+ // set material using Guid
+ if (_materialBaker.ObjectIdAndMaterialIdMap.TryGetValue(instanceProxyId, out Guid materialGuid))
{
- atts.MaterialIndex = mIndex;
+ atts.RenderMaterial = RenderContent.FromId(doc, materialGuid) as RenderMaterial;
atts.MaterialSource = ObjectMaterialSource.MaterialFromObject;
}
diff --git a/Connectors/Rhino/Speckle.Connectors.RhinoShared/HostApp/RhinoLayerBaker.cs b/Connectors/Rhino/Speckle.Connectors.RhinoShared/HostApp/RhinoLayerBaker.cs
index 61f443f93..351e4e415 100644
--- a/Connectors/Rhino/Speckle.Connectors.RhinoShared/HostApp/RhinoLayerBaker.cs
+++ b/Connectors/Rhino/Speckle.Connectors.RhinoShared/HostApp/RhinoLayerBaker.cs
@@ -1,5 +1,6 @@
using Rhino;
using Rhino.DocObjects;
+using Rhino.Render;
using Speckle.Connectors.Common.Operations.Receive;
using Speckle.Sdk;
using Speckle.Sdk.Common;
@@ -104,8 +105,7 @@ public class RhinoLayerBaker : TraversalContextUnpacker
///
/// An array of Collection objects representing the path to create the layer.
/// The base layer name to start creating the new layer.
- /// The index of the last created layer.
- private int CreateLayerFromPath(Collection[] collectionPath, string baseLayerName)
+ private void CreateLayerFromPath(Collection[] collectionPath, string baseLayerName)
{
var currentLayerName = baseLayerName;
var currentDocument = RhinoDoc.ActiveDoc; // POC: too much effort right now to wrap around the interfaced layers
@@ -135,13 +135,17 @@ public class RhinoLayerBaker : TraversalContextUnpacker
// set material
if (
- _materialBaker.ObjectIdAndMaterialIndexMap.TryGetValue(
+ _materialBaker.ObjectIdAndMaterialIdMap.TryGetValue(
collection.applicationId ?? collection.id.NotNull(),
- out int mIndex
+ out Guid materialGuid
)
)
{
- newLayer.RenderMaterialIndex = mIndex;
+ var rc = RenderContent.FromId(currentDocument, materialGuid);
+ if (rc is RenderMaterial rm)
+ {
+ newLayer.RenderMaterialIndex = rm.DocumentAssoc.Materials.CurrentMaterialIndex;
+ }
}
// set color
@@ -164,7 +168,5 @@ public class RhinoLayerBaker : TraversalContextUnpacker
_hostLayerCache.Add(currentLayerName, index);
previousLayer = currentDocument.Layers.FindIndex(index); // note we need to get the correct id out, hence why we're double calling this
}
-
- return previousLayer.Index;
}
}
diff --git a/Connectors/Rhino/Speckle.Connectors.RhinoShared/HostApp/RhinoMaterialBaker.cs b/Connectors/Rhino/Speckle.Connectors.RhinoShared/HostApp/RhinoMaterialBaker.cs
index c65a6d75f..caca41c0b 100644
--- a/Connectors/Rhino/Speckle.Connectors.RhinoShared/HostApp/RhinoMaterialBaker.cs
+++ b/Connectors/Rhino/Speckle.Connectors.RhinoShared/HostApp/RhinoMaterialBaker.cs
@@ -3,9 +3,9 @@ using Speckle.Converters.Common;
using Speckle.Converters.Rhino;
using Speckle.Objects.Other;
using Speckle.Sdk;
-using Speckle.Sdk.Common;
using Speckle.Sdk.Common.Exceptions;
using Material = Rhino.DocObjects.Material;
+using RenderMaterial = Rhino.Render.RenderMaterial;
namespace Speckle.Connectors.Rhino.HostApp;
@@ -24,11 +24,12 @@ public class RhinoMaterialBaker
}
///
- /// A map keeping track of ids, either layer id or object id, and their material index. It's generated from the material proxy list as we bake materials; must be called in advance for this to be populated with the correct data.
+ /// A map keeping track of ids, either layer id or object id, and their Render Material Guid.
+ /// It's generated from the material proxy list as we .
///
- public Dictionary ObjectIdAndMaterialIndexMap { get; } = new();
+ public Dictionary ObjectIdAndMaterialIdMap { get; } = [];
- public void BakeMaterials(IReadOnlyCollection speckleRenderMaterialProxies, string baseLayerName)
+ public void BakeMaterials(IReadOnlyCollection speckleRenderMaterialProxies)
{
var doc = _converterSettings.Current.Document; // POC: too much right now to interface around
// List conversionResults = new(); // TODO: return this guy
@@ -40,15 +41,14 @@ public class RhinoMaterialBaker
try
{
// POC: Currently we're relying on the render material name for identification if it's coming from speckle and from which model; could we do something else?
- string materialId = speckleRenderMaterial.applicationId ?? speckleRenderMaterial.id.NotNull();
- string matName = $"{speckleRenderMaterial.name}-({materialId})-{baseLayerName}";
+ string matName = speckleRenderMaterial.name;
matName = matName.Replace("[", "").Replace("]", ""); // "Material" doesn't like square brackets if we create from here. Once they created from Rhino UI, all good..
// Check if material with this name already exists in the document
- int matIndex = doc.Materials.Find(matName, ignoreDeletedMaterials: true);
+ var existingRenderMaterial = doc.RenderMaterials.FirstOrDefault(m => m.Name == matName);
+ Guid materialGuid;
- // If material doesn't exist, create it
- if (matIndex == -1)
+ if (existingRenderMaterial == null)
{
Color diffuse = Color.FromArgb(speckleRenderMaterial.diffuse);
Color emissive = Color.FromArgb(speckleRenderMaterial.emissive);
@@ -73,24 +73,32 @@ public class RhinoMaterialBaker
rhinoMaterial.Shine = shine;
}
- matIndex = doc.Materials.Add(rhinoMaterial);
+ // create RenderMaterial wrapper (CNX-2896)
+ var renderMaterial = RenderMaterial.CreateBasicMaterial(rhinoMaterial, doc);
- // POC: check on matIndex -1, means we haven't created anything - this is most likely an recoverable error at this stage
- if (matIndex == -1)
- {
- throw new ConversionException($"Failed to add a material to the document: '{matName}' (ID: {materialId})");
- }
+ // add to RenderMaterial table. From my understanding, this internally manages the legacy Material table entry
+ doc.RenderMaterials.Add(renderMaterial);
+ materialGuid = renderMaterial.Id;
+ }
+ else
+ {
+ materialGuid = existingRenderMaterial.Id;
}
- // Create the object <> material index map
+ if (materialGuid == Guid.Empty)
+ {
+ throw new ConversionException($"Failed to create or retrieve RenderMaterial Guid for: '{matName}'");
+ }
+
+ // map object ID to Material Guid
foreach (var objectId in proxy.objects)
{
- ObjectIdAndMaterialIndexMap[objectId] = matIndex;
+ ObjectIdAndMaterialIdMap[objectId] = materialGuid;
}
}
catch (Exception ex) when (!ex.IsFatal())
{
- _logger.LogError(ex, "Failed to add a material to the document");
+ _logger.LogError(ex, "Failed to add a modern RenderMaterial to the document");
}
}
}
diff --git a/Connectors/Rhino/Speckle.Connectors.RhinoShared/Operations/Receive/RhinoHostObjectBuilder.cs b/Connectors/Rhino/Speckle.Connectors.RhinoShared/Operations/Receive/RhinoHostObjectBuilder.cs
index 50900c856..2874f7aed 100644
--- a/Connectors/Rhino/Speckle.Connectors.RhinoShared/Operations/Receive/RhinoHostObjectBuilder.cs
+++ b/Connectors/Rhino/Speckle.Connectors.RhinoShared/Operations/Receive/RhinoHostObjectBuilder.cs
@@ -1,6 +1,7 @@
using Rhino;
using Rhino.DocObjects;
using Rhino.Geometry;
+using Rhino.Render;
using Speckle.Connectors.Common.Builders;
using Speckle.Connectors.Common.Conversion;
using Speckle.Connectors.Common.Extensions;
@@ -18,6 +19,7 @@ using Speckle.Sdk.Logging;
using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Collections;
using Speckle.Sdk.Models.Instances;
+using Speckle.Sdk.Pipelines.Progress;
namespace Speckle.Connectors.Rhino.Operations.Receive;
@@ -119,7 +121,7 @@ public class RhinoHostObjectBuilder : IHostObjectBuilder
using var _ = _activityFactory.Start("Render Materials");
_threadContext.RunOnMain(() =>
{
- _materialBaker.BakeMaterials(unpackedRoot.RenderMaterialProxies, baseLayerName);
+ _materialBaker.BakeMaterials(unpackedRoot.RenderMaterialProxies);
});
}
@@ -330,17 +332,17 @@ public class RhinoHostObjectBuilder : IHostObjectBuilder
{
var objectId = originalObject.applicationId ?? originalObject.id.NotNull();
- if (_materialBaker.ObjectIdAndMaterialIndexMap.TryGetValue(objectId, out int mIndex))
+ if (_materialBaker.ObjectIdAndMaterialIdMap.TryGetValue(objectId, out Guid materialGuid))
{
- atts.MaterialIndex = mIndex;
+ atts.RenderMaterial = RenderContent.FromId(_converterSettings.Current.Document, materialGuid) as RenderMaterial;
atts.MaterialSource = ObjectMaterialSource.MaterialFromObject;
}
else if (
parentObjectId is not null
- && (_materialBaker.ObjectIdAndMaterialIndexMap.TryGetValue(parentObjectId, out int mIndexSpeckleObj))
+ && (_materialBaker.ObjectIdAndMaterialIdMap.TryGetValue(parentObjectId, out Guid parentGuid))
)
{
- atts.MaterialIndex = mIndexSpeckleObj;
+ atts.RenderMaterial = RenderContent.FromId(_converterSettings.Current.Document, parentGuid) as RenderMaterial;
atts.MaterialSource = ObjectMaterialSource.MaterialFromObject;
}
diff --git a/Connectors/Rhino/Speckle.Connectors.RhinoShared/Operations/Send/RhinoContinousTraversalBuilder.cs b/Connectors/Rhino/Speckle.Connectors.RhinoShared/Operations/Send/RhinoContinousTraversalBuilder.cs
new file mode 100644
index 000000000..5aa87a06c
--- /dev/null
+++ b/Connectors/Rhino/Speckle.Connectors.RhinoShared/Operations/Send/RhinoContinousTraversalBuilder.cs
@@ -0,0 +1,220 @@
+using Microsoft.Extensions.Logging;
+using Rhino.DocObjects;
+using Speckle.Connectors.Common.Builders;
+using Speckle.Connectors.Common.Caching;
+using Speckle.Connectors.Common.Conversion;
+using Speckle.Connectors.Common.Extensions;
+using Speckle.Connectors.Common.Instances;
+using Speckle.Connectors.Common.Operations;
+using Speckle.Connectors.DUI.Models.Card.SendFilter;
+using Speckle.Connectors.Rhino.HostApp;
+using Speckle.Connectors.Rhino.HostApp.Properties;
+using Speckle.Converters.Common;
+using Speckle.Converters.Rhino;
+using Speckle.Sdk;
+using Speckle.Sdk.Logging;
+using Speckle.Sdk.Models;
+using Speckle.Sdk.Models.Collections;
+using Speckle.Sdk.Models.Instances;
+using Speckle.Sdk.Pipelines.Progress;
+using Speckle.Sdk.Pipelines.Send;
+using Layer = Rhino.DocObjects.Layer;
+
+namespace Speckle.Connectors.Rhino.Operations.Send;
+
+///
+/// NOTE: I am not happy this is a mostly copy paste of the Root object builder, but i'm also not too worried. The main (hot) path
+/// should be this one going forward, so we should not touch the og root object builder besides to delete it.
+/// Stateless builder object to turn an into a object
+///
+public class RhinoContinuousTraversalBuilder : IRootContinuousTraversalBuilder
+{
+ private readonly IRootToSpeckleConverter _rootToSpeckleConverter;
+ private readonly ISendConversionCache _sendConversionCache;
+ private readonly IConverterSettingsStore _converterSettings;
+ private readonly RhinoLayerUnpacker _layerUnpacker;
+ private readonly RhinoInstanceUnpacker _instanceUnpacker;
+ private readonly RhinoGroupUnpacker _groupUnpacker;
+ private readonly RhinoMaterialUnpacker _materialUnpacker;
+ private readonly RhinoColorUnpacker _colorUnpacker;
+ private readonly RhinoViewUnpacker _viewUnpacker;
+ private readonly PropertiesExtractor _propertiesExtractor;
+ private readonly ILogger _logger;
+ private readonly ISdkActivityFactory _activityFactory;
+
+ public RhinoContinuousTraversalBuilder(
+ IRootToSpeckleConverter rootToSpeckleConverter,
+ ISendConversionCache sendConversionCache,
+ IConverterSettingsStore converterSettings,
+ RhinoLayerUnpacker layerUnpacker,
+ RhinoInstanceUnpacker instanceUnpacker,
+ RhinoGroupUnpacker groupUnpacker,
+ RhinoMaterialUnpacker materialUnpacker,
+ RhinoColorUnpacker colorUnpacker,
+ RhinoViewUnpacker viewUnpacker,
+ PropertiesExtractor propertiesExtractor,
+ ILogger logger,
+ ISdkActivityFactory activityFactory
+ )
+ {
+ _sendConversionCache = sendConversionCache;
+ _converterSettings = converterSettings;
+ _layerUnpacker = layerUnpacker;
+ _instanceUnpacker = instanceUnpacker;
+ _groupUnpacker = groupUnpacker;
+ _rootToSpeckleConverter = rootToSpeckleConverter;
+ _materialUnpacker = materialUnpacker;
+ _colorUnpacker = colorUnpacker;
+ _viewUnpacker = viewUnpacker;
+ _propertiesExtractor = propertiesExtractor;
+ _logger = logger;
+ _activityFactory = activityFactory;
+ }
+
+ public async Task Build(
+ IReadOnlyList rhinoObjects,
+ string projectId,
+ SendPipeline sendPipeline,
+ IProgress onOperationProgressed,
+ CancellationToken cancellationToken
+ )
+ {
+ using var activity = _activityFactory.Start("Build");
+ // 0 - Init the root
+ Collection rootObjectCollection = new() { name = _converterSettings.Current.Document.Name ?? "Unnamed document" };
+ rootObjectCollection["units"] = _converterSettings.Current.SpeckleUnits;
+
+ // 1 - Unpack the instances
+ UnpackResult unpackResults;
+ using (var _ = _activityFactory.Start("UnpackSelection"))
+ {
+ unpackResults = _instanceUnpacker.UnpackSelection(rhinoObjects);
+ }
+
+ var (atomicObjects, _, instanceProxies, instanceDefinitionProxies) = unpackResults;
+ // POC: we should formalise this, sooner or later - or somehow fix it a bit more
+ rootObjectCollection[ProxyKeys.INSTANCE_DEFINITION] = instanceDefinitionProxies; // this won't work re traversal on receive
+
+ // 2 - Unpack the groups
+ using (var _ = _activityFactory.Start("Unpack Groups"))
+ {
+ _groupUnpacker.UnpackGroups(rhinoObjects);
+ }
+ rootObjectCollection[ProxyKeys.GROUP] = _groupUnpacker.GroupProxies.Values;
+
+ // 3 - Convert atomic objects
+ List results = new(atomicObjects.Count);
+ int count = 0;
+ using (var _ = _activityFactory.Start("Convert all"))
+ {
+ foreach (RhinoObject rhinoObject in atomicObjects)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ // handle layer and store object layer *and all layer parents* to the version layers
+ // this is important because we need to unpack colors and materials on intermediate layers that do not have objects as well.
+ Layer layer = _converterSettings.Current.Document.Layers[rhinoObject.Attributes.LayerIndex];
+ Collection collectionHost = _layerUnpacker.GetHostObjectCollection(layer, rootObjectCollection);
+
+ var result = await ConvertRhinoObject(rhinoObject, collectionHost, instanceProxies, projectId, sendPipeline);
+ results.Add(result);
+
+ count++;
+ onOperationProgressed.Report(
+ new($"Converting objects... ({count:N0} / {atomicObjects.Count:N0})", (double)count / atomicObjects.Count)
+ );
+ }
+ }
+
+ if (results.All(x => x.Status == Status.ERROR))
+ {
+ throw new SpeckleException("Failed to convert all objects."); // fail fast instead creating empty commit! It will appear as model card error with red color.
+ }
+
+ // 4 - Unpack all proxies for the root
+ // Get all layers from the created collections on the root object commit for proxy processing
+ List layers = _layerUnpacker.GetUsedLayers().ToList();
+
+ using (var _ = _activityFactory.Start("UnpackRenderMaterials"))
+ {
+ rootObjectCollection[ProxyKeys.RENDER_MATERIAL] = _materialUnpacker.UnpackRenderMaterials(atomicObjects, layers);
+ }
+
+ using (var _ = _activityFactory.Start("UnpackColors"))
+ {
+ rootObjectCollection[ProxyKeys.COLOR] = _colorUnpacker.UnpackColors(atomicObjects, layers);
+ }
+
+ // 5 - Unpack all other objects for the root
+ using (var _ = _activityFactory.Start("UnpackViews"))
+ {
+ List views = _viewUnpacker.UnpackViews(_converterSettings.Current.Document.NamedViews);
+ if (views.Count > 0)
+ {
+ rootObjectCollection[RootKeys.VIEW] = views;
+ }
+ }
+
+ await sendPipeline.Process(rootObjectCollection);
+ await sendPipeline.WaitForUpload();
+ return new RootObjectBuilderResult(rootObjectCollection, results);
+ }
+
+ private async Task ConvertRhinoObject(
+ RhinoObject rhinoObject,
+ Collection collectionHost,
+ IReadOnlyDictionary instanceProxies,
+ string projectId,
+ SendPipeline sendPipeline
+ )
+ {
+ string applicationId = rhinoObject.Id.ToString();
+ string sourceType = rhinoObject.ObjectType.ToString();
+ try
+ {
+ // get from cache or convert:
+ // What we actually do here is check if the object has been previously converted AND has not changed.
+ // If that's the case, we insert in the host collection just its object reference which has been saved from the prior conversion.
+ Base converted;
+ if (rhinoObject is InstanceObject)
+ {
+ converted = instanceProxies[applicationId];
+ }
+ else if (_sendConversionCache.TryGetValue(projectId, applicationId, out ObjectReference? value))
+ {
+ converted = value;
+ }
+ else
+ {
+ converted = _rootToSpeckleConverter.Convert(rhinoObject);
+ converted.applicationId = applicationId;
+ }
+
+ // add name and properties
+ // POC: this is NOT done in the converter because we don't have a RootToSpeckle converter that captures all top level converters
+ if (!string.IsNullOrEmpty(rhinoObject.Attributes.Name))
+ {
+ converted["name"] = rhinoObject.Attributes.Name;
+ }
+
+ var properties = _propertiesExtractor.GetProperties(rhinoObject);
+ if (properties.Count > 0)
+ {
+ converted["properties"] = properties;
+ }
+
+ // NOTE: this is the main part that differentiate from the main root object builder
+ var reference = await sendPipeline.Process(converted).ConfigureAwait(false);
+
+ // add to host
+ collectionHost.elements.Add(reference);
+
+ return new(Status.SUCCESS, applicationId, sourceType, reference);
+ }
+ catch (Exception ex) when (!ex.IsFatal())
+ {
+ _logger.LogSendConversionError(ex, sourceType);
+ return new(Status.ERROR, applicationId, sourceType, null, ex);
+ }
+ }
+}
diff --git a/Connectors/Rhino/Speckle.Connectors.RhinoShared/Operations/Send/RhinoRootObjectBuilder.cs b/Connectors/Rhino/Speckle.Connectors.RhinoShared/Operations/Send/RhinoRootObjectBuilder.cs
index 8394ec6c5..938b5c91c 100644
--- a/Connectors/Rhino/Speckle.Connectors.RhinoShared/Operations/Send/RhinoRootObjectBuilder.cs
+++ b/Connectors/Rhino/Speckle.Connectors.RhinoShared/Operations/Send/RhinoRootObjectBuilder.cs
@@ -16,6 +16,7 @@ using Speckle.Sdk.Logging;
using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Collections;
using Speckle.Sdk.Models.Instances;
+using Speckle.Sdk.Pipelines.Progress;
using Layer = Rhino.DocObjects.Layer;
namespace Speckle.Connectors.Rhino.Operations.Send;
diff --git a/Connectors/Rhino/Speckle.Connectors.RhinoShared/Registration/ServiceRegistration.cs b/Connectors/Rhino/Speckle.Connectors.RhinoShared/Registration/ServiceRegistration.cs
index 6369b4b29..e202defd5 100644
--- a/Connectors/Rhino/Speckle.Connectors.RhinoShared/Registration/ServiceRegistration.cs
+++ b/Connectors/Rhino/Speckle.Connectors.RhinoShared/Registration/ServiceRegistration.cs
@@ -71,6 +71,7 @@ public static class ServiceRegistration
serviceCollection.AddSingleton(DefaultTraversal.CreateTraversalFunc());
serviceCollection.AddScoped, RhinoRootObjectBuilder>();
+ serviceCollection.AddScoped, RhinoContinuousTraversalBuilder>();
serviceCollection.AddScoped<
IInstanceObjectsManager>,
InstanceObjectsManager>
diff --git a/Connectors/Rhino/Speckle.Connectors.RhinoShared/Speckle.Connectors.RhinoShared.projitems b/Connectors/Rhino/Speckle.Connectors.RhinoShared/Speckle.Connectors.RhinoShared.projitems
index 8da708e54..ed833bdb9 100644
--- a/Connectors/Rhino/Speckle.Connectors.RhinoShared/Speckle.Connectors.RhinoShared.projitems
+++ b/Connectors/Rhino/Speckle.Connectors.RhinoShared/Speckle.Connectors.RhinoShared.projitems
@@ -38,6 +38,7 @@
+
diff --git a/Connectors/Tekla/Speckle.Connector.Tekla2023/packages.lock.json b/Connectors/Tekla/Speckle.Connector.Tekla2023/packages.lock.json
index 817aaf4f5..3a4c4eaa1 100644
--- a/Connectors/Tekla/Speckle.Connector.Tekla2023/packages.lock.json
+++ b/Connectors/Tekla/Speckle.Connector.Tekla2023/packages.lock.json
@@ -210,8 +210,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -220,13 +220,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -349,7 +349,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -382,7 +382,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"LibTessDotNet": {
@@ -432,11 +432,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Connectors/Tekla/Speckle.Connector.Tekla2024/packages.lock.json b/Connectors/Tekla/Speckle.Connector.Tekla2024/packages.lock.json
index 108c6632c..4815b7770 100644
--- a/Connectors/Tekla/Speckle.Connector.Tekla2024/packages.lock.json
+++ b/Connectors/Tekla/Speckle.Connector.Tekla2024/packages.lock.json
@@ -229,8 +229,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -239,13 +239,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -430,7 +430,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -463,7 +463,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"LibTessDotNet": {
@@ -513,11 +513,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Connectors/Tekla/Speckle.Connector.Tekla2025/packages.lock.json b/Connectors/Tekla/Speckle.Connector.Tekla2025/packages.lock.json
index 89a66c3c5..ed67c066d 100644
--- a/Connectors/Tekla/Speckle.Connector.Tekla2025/packages.lock.json
+++ b/Connectors/Tekla/Speckle.Connector.Tekla2025/packages.lock.json
@@ -229,8 +229,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -239,13 +239,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -430,7 +430,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -463,7 +463,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"LibTessDotNet": {
@@ -513,11 +513,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Connectors/Tekla/Speckle.Connector.TeklaShared/Operations/Send/TeklaContinuousTraversalBuilder.cs b/Connectors/Tekla/Speckle.Connector.TeklaShared/Operations/Send/TeklaContinuousTraversalBuilder.cs
new file mode 100644
index 000000000..180e5d99e
--- /dev/null
+++ b/Connectors/Tekla/Speckle.Connector.TeklaShared/Operations/Send/TeklaContinuousTraversalBuilder.cs
@@ -0,0 +1,141 @@
+using Microsoft.Extensions.Logging;
+using Speckle.Connectors.Common.Builders;
+using Speckle.Connectors.Common.Caching;
+using Speckle.Connectors.Common.Conversion;
+using Speckle.Connectors.Common.Operations;
+using Speckle.Connectors.TeklaShared.Extensions;
+using Speckle.Connectors.TeklaShared.HostApp;
+using Speckle.Converters.Common;
+using Speckle.Converters.TeklaShared;
+using Speckle.Sdk;
+using Speckle.Sdk.Logging;
+using Speckle.Sdk.Models;
+using Speckle.Sdk.Models.Collections;
+using Speckle.Sdk.Pipelines.Progress;
+using Speckle.Sdk.Pipelines.Send;
+
+namespace Speckle.Connectors.TeklaShared.Operations.Send;
+
+///
+/// Continuous traversal builder for Tekla that streams objects through a
+/// for packfile-based uploads. Same conversion logic as .
+///
+public class TeklaContinuousTraversalBuilder : IRootContinuousTraversalBuilder
+{
+ private readonly IRootToSpeckleConverter _rootToSpeckleConverter;
+ private readonly ISendConversionCache _sendConversionCache;
+ private readonly IConverterSettingsStore _converterSettings;
+ private readonly SendCollectionManager _sendCollectionManager;
+ private readonly ILogger _logger;
+ private readonly ISdkActivityFactory _activityFactory;
+ private readonly TeklaMaterialUnpacker _materialUnpacker;
+
+ public TeklaContinuousTraversalBuilder(
+ IRootToSpeckleConverter rootToSpeckleConverter,
+ ISendConversionCache sendConversionCache,
+ IConverterSettingsStore converterSettings,
+ SendCollectionManager sendCollectionManager,
+ ILogger logger,
+ ISdkActivityFactory activityFactory,
+ TeklaMaterialUnpacker materialUnpacker
+ )
+ {
+ _sendConversionCache = sendConversionCache;
+ _converterSettings = converterSettings;
+ _sendCollectionManager = sendCollectionManager;
+ _rootToSpeckleConverter = rootToSpeckleConverter;
+ _logger = logger;
+ _activityFactory = activityFactory;
+ _materialUnpacker = materialUnpacker;
+ }
+
+ public async Task Build(
+ IReadOnlyList teklaObjects,
+ string projectId,
+ SendPipeline sendPipeline,
+ IProgress onOperationProgressed,
+ CancellationToken cancellationToken
+ )
+ {
+ using var activity = _activityFactory.Start("Build");
+
+ var model = new TSM.Model();
+ string modelName = model.GetInfo().ModelName ?? "Unnamed model";
+
+ Collection rootObjectCollection = new() { name = modelName };
+ rootObjectCollection["units"] = _converterSettings.Current.SpeckleUnits;
+
+ List results = new(teklaObjects.Count);
+ int count = 0;
+
+ using (var _ = _activityFactory.Start("Convert all"))
+ {
+ foreach (TSM.ModelObject teklaObject in teklaObjects)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ var result = await ConvertTeklaObject(teklaObject, rootObjectCollection, projectId, sendPipeline);
+ results.Add(result);
+
+ ++count;
+ onOperationProgressed.Report(
+ new($"Converting objects... ({count:N0} / {teklaObjects.Count:N0})", (double)count / teklaObjects.Count)
+ );
+ await Task.Yield();
+ }
+ }
+
+ if (results.All(x => x.Status == Status.ERROR))
+ {
+ throw new SpeckleException("Failed to convert all objects.");
+ }
+
+ var renderMaterialProxies = _materialUnpacker.UnpackRenderMaterial(teklaObjects.ToList());
+ if (renderMaterialProxies.Count > 0)
+ {
+ rootObjectCollection[ProxyKeys.RENDER_MATERIAL] = renderMaterialProxies;
+ }
+
+ // Process root collection and wait for all uploads
+ await sendPipeline.Process(rootObjectCollection);
+ await sendPipeline.WaitForUpload();
+
+ return new RootObjectBuilderResult(rootObjectCollection, results);
+ }
+
+ private async Task ConvertTeklaObject(
+ TSM.ModelObject teklaObject,
+ Collection collectionHost,
+ string projectId,
+ SendPipeline sendPipeline
+ )
+ {
+ string applicationId = teklaObject.GetSpeckleApplicationId();
+ string sourceType = teklaObject.GetType().Name;
+
+ try
+ {
+ Base converted;
+ if (_sendConversionCache.TryGetValue(projectId, applicationId, out ObjectReference? value))
+ {
+ converted = value;
+ }
+ else
+ {
+ converted = _rootToSpeckleConverter.Convert(teklaObject);
+ }
+
+ var collection = _sendCollectionManager.GetAndCreateObjectHostCollection(teklaObject, collectionHost);
+
+ // NOTE: this is the main part that differentiate from the main root object builder
+ var reference = await sendPipeline.Process(converted).ConfigureAwait(false);
+ collection.elements.Add(reference);
+
+ return new(Status.SUCCESS, applicationId, sourceType, reference);
+ }
+ catch (Exception ex) when (!ex.IsFatal())
+ {
+ _logger.LogError(ex, "Failed to convert object {SourceType}", sourceType);
+ return new(Status.ERROR, applicationId, sourceType, null, ex);
+ }
+ }
+}
diff --git a/Connectors/Tekla/Speckle.Connector.TeklaShared/Operations/Send/TeklaRootObjectBuilder.cs b/Connectors/Tekla/Speckle.Connector.TeklaShared/Operations/Send/TeklaRootObjectBuilder.cs
index e41216c3b..d1aeb2550 100644
--- a/Connectors/Tekla/Speckle.Connector.TeklaShared/Operations/Send/TeklaRootObjectBuilder.cs
+++ b/Connectors/Tekla/Speckle.Connector.TeklaShared/Operations/Send/TeklaRootObjectBuilder.cs
@@ -11,6 +11,7 @@ using Speckle.Sdk;
using Speckle.Sdk.Logging;
using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Collections;
+using Speckle.Sdk.Pipelines.Progress;
namespace Speckle.Connectors.TeklaShared.Operations.Send;
diff --git a/Connectors/Tekla/Speckle.Connector.TeklaShared/ServiceRegistration.cs b/Connectors/Tekla/Speckle.Connector.TeklaShared/ServiceRegistration.cs
index a4a4a389f..2398982f5 100644
--- a/Connectors/Tekla/Speckle.Connector.TeklaShared/ServiceRegistration.cs
+++ b/Connectors/Tekla/Speckle.Connector.TeklaShared/ServiceRegistration.cs
@@ -54,6 +54,7 @@ public static class ServiceRegistration
services.AddSingleton(DefaultTraversal.CreateTraversalFunc());
services.AddScoped();
services.AddScoped, TeklaRootObjectBuilder>();
+ services.AddScoped, TeklaContinuousTraversalBuilder>();
services.AddScoped>();
services.AddSingleton();
diff --git a/Connectors/Tekla/Speckle.Connector.TeklaShared/Speckle.Connectors.TeklaShared.projitems b/Connectors/Tekla/Speckle.Connector.TeklaShared/Speckle.Connectors.TeklaShared.projitems
index 86a8ddc2d..bdf99d4f4 100644
--- a/Connectors/Tekla/Speckle.Connector.TeklaShared/Speckle.Connectors.TeklaShared.projitems
+++ b/Connectors/Tekla/Speckle.Connector.TeklaShared/Speckle.Connectors.TeklaShared.projitems
@@ -37,6 +37,7 @@
+
diff --git a/Converters/Autocad/Speckle.Converters.Autocad2022/packages.lock.json b/Converters/Autocad/Speckle.Converters.Autocad2022/packages.lock.json
index dc20eab6b..c439890bb 100644
--- a/Converters/Autocad/Speckle.Converters.Autocad2022/packages.lock.json
+++ b/Converters/Autocad/Speckle.Converters.Autocad2022/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -281,7 +281,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.Logging": {
@@ -310,11 +310,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Autocad/Speckle.Converters.Autocad2023/packages.lock.json b/Converters/Autocad/Speckle.Converters.Autocad2023/packages.lock.json
index b52d335de..1db27db32 100644
--- a/Converters/Autocad/Speckle.Converters.Autocad2023/packages.lock.json
+++ b/Converters/Autocad/Speckle.Converters.Autocad2023/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -281,7 +281,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.Logging": {
@@ -310,11 +310,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Autocad/Speckle.Converters.Autocad2024/packages.lock.json b/Converters/Autocad/Speckle.Converters.Autocad2024/packages.lock.json
index 167b6fdb2..1b2fd5abd 100644
--- a/Converters/Autocad/Speckle.Converters.Autocad2024/packages.lock.json
+++ b/Converters/Autocad/Speckle.Converters.Autocad2024/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -283,7 +283,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -307,7 +307,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -351,11 +351,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Autocad/Speckle.Converters.Autocad2025/packages.lock.json b/Converters/Autocad/Speckle.Converters.Autocad2025/packages.lock.json
index 18240640c..f5cb73519 100644
--- a/Converters/Autocad/Speckle.Converters.Autocad2025/packages.lock.json
+++ b/Converters/Autocad/Speckle.Converters.Autocad2025/packages.lock.json
@@ -157,8 +157,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -166,13 +166,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -230,7 +230,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -254,7 +254,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -298,11 +298,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Autocad/Speckle.Converters.Autocad2026/packages.lock.json b/Converters/Autocad/Speckle.Converters.Autocad2026/packages.lock.json
index 453037a94..9afefd60d 100644
--- a/Converters/Autocad/Speckle.Converters.Autocad2026/packages.lock.json
+++ b/Converters/Autocad/Speckle.Converters.Autocad2026/packages.lock.json
@@ -157,8 +157,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -166,13 +166,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -230,7 +230,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -254,7 +254,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -298,11 +298,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/AutocadRootToSpeckleConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/AutocadRootToSpeckleConverter.cs
index b8b3236bd..02b753fcb 100644
--- a/Converters/Autocad/Speckle.Converters.AutocadShared/AutocadRootToSpeckleConverter.cs
+++ b/Converters/Autocad/Speckle.Converters.AutocadShared/AutocadRootToSpeckleConverter.cs
@@ -36,24 +36,20 @@ public class AutocadRootToSpeckleConverter : IRootToSpeckleConverter
Type type = dbObject.GetType();
- using (var l = _settingsStore.Current.Document.LockDocument())
+ using var l = _settingsStore.Current.Document.LockDocument();
+ using var tr = _settingsStore.Current.Document.Database.TransactionManager.StartTransaction();
+ var objectConverter = _toSpeckle.ResolveConverter(type);
+
+ var convertedObject = objectConverter.Convert(dbObject);
+
+ // add properties
+ Dictionary properties = _propertiesExtractor.GetProperties((Entity)dbObject);
+ if (properties.Count > 0)
{
- using (var tr = _settingsStore.Current.Document.Database.TransactionManager.StartTransaction())
- {
- var objectConverter = _toSpeckle.ResolveConverter(type);
-
- var convertedObject = objectConverter.Convert(dbObject);
-
- // add properties
- Dictionary properties = _propertiesExtractor.GetProperties((Entity)dbObject);
- if (properties.Count > 0)
- {
- convertedObject["properties"] = properties;
- }
-
- tr.Commit();
- return convertedObject;
- }
+ convertedObject["properties"] = properties;
}
+
+ tr.Commit();
+ return convertedObject;
}
}
diff --git a/Converters/CSi/Speckle.Converters.ETABS21/packages.lock.json b/Converters/CSi/Speckle.Converters.ETABS21/packages.lock.json
index bdd7f4a36..61c4d726b 100644
--- a/Converters/CSi/Speckle.Converters.ETABS21/packages.lock.json
+++ b/Converters/CSi/Speckle.Converters.ETABS21/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -281,7 +281,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.Logging": {
@@ -310,11 +310,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/CSi/Speckle.Converters.ETABS22/packages.lock.json b/Converters/CSi/Speckle.Converters.ETABS22/packages.lock.json
index 8c08f8fbc..390e5c2fe 100644
--- a/Converters/CSi/Speckle.Converters.ETABS22/packages.lock.json
+++ b/Converters/CSi/Speckle.Converters.ETABS22/packages.lock.json
@@ -157,8 +157,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -166,13 +166,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -228,7 +228,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.Logging": {
@@ -257,11 +257,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Civil3d/Speckle.Converters.Civil3d2022/packages.lock.json b/Converters/Civil3d/Speckle.Converters.Civil3d2022/packages.lock.json
index 2616b26f7..df96ad208 100644
--- a/Converters/Civil3d/Speckle.Converters.Civil3d2022/packages.lock.json
+++ b/Converters/Civil3d/Speckle.Converters.Civil3d2022/packages.lock.json
@@ -180,8 +180,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -190,13 +190,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -290,7 +290,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.Logging": {
@@ -319,11 +319,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Civil3d/Speckle.Converters.Civil3d2023/packages.lock.json b/Converters/Civil3d/Speckle.Converters.Civil3d2023/packages.lock.json
index 7cf858e45..147483115 100644
--- a/Converters/Civil3d/Speckle.Converters.Civil3d2023/packages.lock.json
+++ b/Converters/Civil3d/Speckle.Converters.Civil3d2023/packages.lock.json
@@ -180,8 +180,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -190,13 +190,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -290,7 +290,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.Logging": {
@@ -319,11 +319,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Civil3d/Speckle.Converters.Civil3d2024/packages.lock.json b/Converters/Civil3d/Speckle.Converters.Civil3d2024/packages.lock.json
index 94cf31a1c..3e823c5cb 100644
--- a/Converters/Civil3d/Speckle.Converters.Civil3d2024/packages.lock.json
+++ b/Converters/Civil3d/Speckle.Converters.Civil3d2024/packages.lock.json
@@ -180,8 +180,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -190,13 +190,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -290,7 +290,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.Logging": {
@@ -319,11 +319,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Civil3d/Speckle.Converters.Civil3d2025/packages.lock.json b/Converters/Civil3d/Speckle.Converters.Civil3d2025/packages.lock.json
index 168630fc7..1e19f16d0 100644
--- a/Converters/Civil3d/Speckle.Converters.Civil3d2025/packages.lock.json
+++ b/Converters/Civil3d/Speckle.Converters.Civil3d2025/packages.lock.json
@@ -166,8 +166,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -175,13 +175,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -239,7 +239,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -263,7 +263,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -307,11 +307,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Civil3d/Speckle.Converters.Civil3d2026/packages.lock.json b/Converters/Civil3d/Speckle.Converters.Civil3d2026/packages.lock.json
index e844107cc..53ae32162 100644
--- a/Converters/Civil3d/Speckle.Converters.Civil3d2026/packages.lock.json
+++ b/Converters/Civil3d/Speckle.Converters.Civil3d2026/packages.lock.json
@@ -166,8 +166,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -175,13 +175,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -239,7 +239,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -263,7 +263,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -307,11 +307,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dRootToSpeckleConverter.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dRootToSpeckleConverter.cs
index 980e0daab..f725c07f7 100644
--- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dRootToSpeckleConverter.cs
+++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dRootToSpeckleConverter.cs
@@ -2,7 +2,6 @@ using System.ComponentModel.DataAnnotations;
using Speckle.Converters.Common;
using Speckle.Converters.Common.Objects;
using Speckle.Converters.Common.Registration;
-using Speckle.Sdk;
using Speckle.Sdk.Models;
namespace Speckle.Converters.Civil3dShared;
@@ -50,34 +49,22 @@ public class Civil3dRootToSpeckleConverter : IRootToSpeckleConverter
var objectConverter = _toSpeckle.ResolveConverter(type);
- try
+ using var l = _settingsStore.Current.Document.LockDocument();
+ using var tr = _settingsStore.Current.Document.Database.TransactionManager.StartTransaction();
+ var result = objectConverter.Convert(target);
+
+ // This is needed to retrieve property sets on solids
+ // Civil entity properties are retrieved in the CivilEntityToSpeckleTopLevelConverter
+ if (target is not CDB.Entity && target is ADB.Entity autocadEntity)
{
- using (var l = _settingsStore.Current.Document.LockDocument())
+ var properties = _propertiesExtractor.GetProperties(autocadEntity);
+ if (properties.Count > 0)
{
- using (var tr = _settingsStore.Current.Document.Database.TransactionManager.StartTransaction())
- {
- var result = objectConverter.Convert(target);
-
- // This is needed to retrieve property sets on solids
- // Civil entity properties are retrieved in the CivilEntityToSpeckleTopLevelConverter
- if (target is not CDB.Entity && target is ADB.Entity autocadEntity)
- {
- var properties = _propertiesExtractor.GetProperties(autocadEntity);
- if (properties.Count > 0)
- {
- result["properties"] = properties;
- }
- }
-
- tr.Commit();
- return result;
- }
+ result["properties"] = properties;
}
}
- catch (SpeckleException e)
- {
- Console.WriteLine(e);
- throw; // Just rethrowing for now, Logs may be needed here.
- }
+
+ tr.Commit();
+ return result;
}
}
diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/PropertyHandler.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/PropertyHandler.cs
index 84ae9d987..2397e885c 100644
--- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/PropertyHandler.cs
+++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/PropertyHandler.cs
@@ -1,5 +1,3 @@
-using Speckle.Sdk;
-
namespace Speckle.Converters.Civil3dShared.Helpers;
///
@@ -16,9 +14,9 @@ public sealed class PropertyHandler
}
catch (Exception e)
when (e is InvalidOperationException
- || e is ArgumentException argEx && !argEx.IsFatal()
- || e is Autodesk.AutoCAD.Runtime.Exception acEx && !acEx.IsFatal() // eNotApplicable
- || e is Autodesk.Civil.CivilException civilEx && !civilEx.IsFatal()
+ || e is ArgumentException
+ || e is Autodesk.AutoCAD.Runtime.Exception // eNotApplicable
+ || e is Autodesk.Civil.CivilException
)
{
value = default;
diff --git a/Converters/Navisworks/Speckle.Converters.Navisworks2020/packages.lock.json b/Converters/Navisworks/Speckle.Converters.Navisworks2020/packages.lock.json
index 237788fda..a650e7a31 100644
--- a/Converters/Navisworks/Speckle.Converters.Navisworks2020/packages.lock.json
+++ b/Converters/Navisworks/Speckle.Converters.Navisworks2020/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -283,7 +283,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -300,7 +300,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -338,11 +338,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Navisworks/Speckle.Converters.Navisworks2021/packages.lock.json b/Converters/Navisworks/Speckle.Converters.Navisworks2021/packages.lock.json
index a96568a5e..51adfda12 100644
--- a/Converters/Navisworks/Speckle.Converters.Navisworks2021/packages.lock.json
+++ b/Converters/Navisworks/Speckle.Converters.Navisworks2021/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -283,7 +283,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -300,7 +300,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -338,11 +338,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Navisworks/Speckle.Converters.Navisworks2022/packages.lock.json b/Converters/Navisworks/Speckle.Converters.Navisworks2022/packages.lock.json
index 357570037..ab1e1d6f4 100644
--- a/Converters/Navisworks/Speckle.Converters.Navisworks2022/packages.lock.json
+++ b/Converters/Navisworks/Speckle.Converters.Navisworks2022/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -283,7 +283,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -300,7 +300,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -338,11 +338,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Navisworks/Speckle.Converters.Navisworks2023/packages.lock.json b/Converters/Navisworks/Speckle.Converters.Navisworks2023/packages.lock.json
index 3417ca242..ad9ef7f48 100644
--- a/Converters/Navisworks/Speckle.Converters.Navisworks2023/packages.lock.json
+++ b/Converters/Navisworks/Speckle.Converters.Navisworks2023/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -283,7 +283,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -300,7 +300,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -338,11 +338,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Navisworks/Speckle.Converters.Navisworks2024/packages.lock.json b/Converters/Navisworks/Speckle.Converters.Navisworks2024/packages.lock.json
index 8486d3493..fb0531f4e 100644
--- a/Converters/Navisworks/Speckle.Converters.Navisworks2024/packages.lock.json
+++ b/Converters/Navisworks/Speckle.Converters.Navisworks2024/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -283,7 +283,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -300,7 +300,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -338,11 +338,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Navisworks/Speckle.Converters.Navisworks2025/packages.lock.json b/Converters/Navisworks/Speckle.Converters.Navisworks2025/packages.lock.json
index 22b77d46b..0cae6b9cd 100644
--- a/Converters/Navisworks/Speckle.Converters.Navisworks2025/packages.lock.json
+++ b/Converters/Navisworks/Speckle.Converters.Navisworks2025/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -283,7 +283,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -300,7 +300,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -338,11 +338,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Navisworks/Speckle.Converters.Navisworks2026/packages.lock.json b/Converters/Navisworks/Speckle.Converters.Navisworks2026/packages.lock.json
index 3dccc1ff6..c3f5ad4a5 100644
--- a/Converters/Navisworks/Speckle.Converters.Navisworks2026/packages.lock.json
+++ b/Converters/Navisworks/Speckle.Converters.Navisworks2026/packages.lock.json
@@ -180,8 +180,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -190,13 +190,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -284,7 +284,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -301,7 +301,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -339,11 +339,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Plant3d/Speckle.Converters.Plant3d2026/Speckle.Converters.Plant3d2026.csproj b/Converters/Plant3d/Speckle.Converters.Plant3d2026/Speckle.Converters.Plant3d2026.csproj
new file mode 100644
index 000000000..3e1f87c35
--- /dev/null
+++ b/Converters/Plant3d/Speckle.Converters.Plant3d2026/Speckle.Converters.Plant3d2026.csproj
@@ -0,0 +1,23 @@
+
+
+ net8.0-windows
+ x64
+ 2026
+ $(DefineConstants);PLANT3D2026;PLANT3D;PLANT3D2024_OR_GREATER;PLANT3D2025_OR_GREATER;PLANT3D2026_OR_GREATER
+ Debug;Release;Local
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Converters/Plant3d/Speckle.Converters.Plant3d2026/packages.lock.json b/Converters/Plant3d/Speckle.Converters.Plant3d2026/packages.lock.json
new file mode 100644
index 000000000..230d71b38
--- /dev/null
+++ b/Converters/Plant3d/Speckle.Converters.Plant3d2026/packages.lock.json
@@ -0,0 +1,319 @@
+{
+ "version": 2,
+ "dependencies": {
+ "net8.0-windows7.0": {
+ "Microsoft.NETFramework.ReferenceAssemblies": {
+ "type": "Direct",
+ "requested": "[1.0.3, )",
+ "resolved": "1.0.3",
+ "contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
+ "dependencies": {
+ "Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.3"
+ }
+ },
+ "Microsoft.SourceLink.GitHub": {
+ "type": "Direct",
+ "requested": "[8.0.0, )",
+ "resolved": "8.0.0",
+ "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
+ "dependencies": {
+ "Microsoft.Build.Tasks.Git": "8.0.0",
+ "Microsoft.SourceLink.Common": "8.0.0"
+ }
+ },
+ "PolySharp": {
+ "type": "Direct",
+ "requested": "[1.14.1, )",
+ "resolved": "1.14.1",
+ "contentHash": "mOOmFYwad3MIOL14VCjj02LljyF1GNw1wP0YVlxtcPvqdxjGGMNdNJJxHptlry3MOd8b40Flm8RPOM8JOlN2sQ=="
+ },
+ "Speckle.AutoCAD.API": {
+ "type": "Direct",
+ "requested": "[2026.0.0, )",
+ "resolved": "2026.0.0",
+ "contentHash": "WlkV81PmbK/ftoM7aGpU6LGosKbePBQej9MO/m63rFMozX89tsitEhE12o58wu7K/4FmRUdAMolYtdK20EDBnw=="
+ },
+ "Speckle.InterfaceGenerator": {
+ "type": "Direct",
+ "requested": "[0.9.6, )",
+ "resolved": "0.9.6",
+ "contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
+ },
+ "Speckle.Plant3D.API": {
+ "type": "Direct",
+ "requested": "[2026.0.0, )",
+ "resolved": "2026.0.0",
+ "contentHash": "VT8M6CGQl1mk3/5Ro3AEAOVrOs/cX58YRwYZnu+6xeHvsazK07Et/6kMJsde4Y7Xrpox7eBLKgYeOspiRVvX5g==",
+ "dependencies": {
+ "Speckle.AutoCAD.API": "2026.0.0"
+ }
+ },
+ "GraphQL.Client": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "8yPNBbuVBpTptivyAlak4GZvbwbUcjeQTL4vN1HKHRuOykZ4r7l5fcLS6vpyPyLn0x8FsL31xbOIKyxbmR9rbA==",
+ "dependencies": {
+ "GraphQL.Client.Abstractions": "6.0.0",
+ "GraphQL.Client.Abstractions.Websocket": "6.0.0",
+ "System.Reactive": "5.0.0"
+ }
+ },
+ "GraphQL.Client.Abstractions": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "h7uzWFORHZ+CCjwr/ThAyXMr0DPpzEANDa4Uo54wqCQ+j7qUKwqYTgOrb1W40sqbvNaZm9v/X7It31SUw0maHA==",
+ "dependencies": {
+ "GraphQL.Primitives": "6.0.0"
+ }
+ },
+ "GraphQL.Client.Abstractions.Websocket": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "Nr9bPf8gIOvLuXpqEpqr9z9jslYFJOvd0feHth3/kPqeR3uMbjF5pjiwh4jxyMcxHdr8Pb6QiXkV3hsSyt0v7A==",
+ "dependencies": {
+ "GraphQL.Client.Abstractions": "6.0.0"
+ }
+ },
+ "GraphQL.Primitives": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "yg72rrYDapfsIUrul7aF6wwNnTJBOFvuA9VdDTQpPa8AlAriHbufeXYLBcodKjfUdkCnaiggX1U/nEP08Zb5GA=="
+ },
+ "Microsoft.Build.Tasks.Git": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
+ },
+ "Microsoft.Data.Sqlite": {
+ "type": "Transitive",
+ "resolved": "7.0.5",
+ "contentHash": "KGxbPeWsQMnmQy43DSBxAFtHz3l2JX8EWBSGUCvT3CuZ8KsuzbkqMIJMDOxWtG8eZSoCDI04aiVQjWuuV8HmSw==",
+ "dependencies": {
+ "Microsoft.Data.Sqlite.Core": "7.0.5",
+ "SQLitePCLRaw.bundle_e_sqlite3": "2.1.4"
+ }
+ },
+ "Microsoft.Data.Sqlite.Core": {
+ "type": "Transitive",
+ "resolved": "7.0.5",
+ "contentHash": "FTerRmQPqHrCrnoUzhBu+E+1DNGwyrAMLqHkAqOOOu5pGfyMOj8qQUBxI/gDtWtG11p49UxSfWmBzRNlwZqfUg==",
+ "dependencies": {
+ "SQLitePCLRaw.core": "2.1.4"
+ }
+ },
+ "Microsoft.Extensions.Configuration": {
+ "type": "Transitive",
+ "resolved": "2.2.0",
+ "contentHash": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "2.2.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration.Abstractions": {
+ "type": "Transitive",
+ "resolved": "2.2.0",
+ "contentHash": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "2.2.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration.Binder": {
+ "type": "Transitive",
+ "resolved": "2.2.0",
+ "contentHash": "vJ9xvOZCnUAIHcGC3SU35r3HKmHTVIeHzo6u/qzlHAqD8m6xv92MLin4oJntTvkpKxVX3vI1GFFkIQtU3AdlsQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "2.2.0"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection.Abstractions": {
+ "type": "Transitive",
+ "resolved": "2.2.0",
+ "contentHash": "f9hstgjVmr6rmrfGSpfsVOl2irKAgr1QjrSi3FgnS7kulxband50f2brRLwySAQTADPZeTdow0mpSMcoAdadCw=="
+ },
+ "Microsoft.Extensions.Options": {
+ "type": "Transitive",
+ "resolved": "2.2.0",
+ "contentHash": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
+ "Microsoft.Extensions.Primitives": "2.2.0",
+ "System.ComponentModel.Annotations": "4.5.0"
+ }
+ },
+ "Microsoft.Extensions.Primitives": {
+ "type": "Transitive",
+ "resolved": "2.2.0",
+ "contentHash": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==",
+ "dependencies": {
+ "System.Memory": "4.5.1",
+ "System.Runtime.CompilerServices.Unsafe": "4.5.1"
+ }
+ },
+ "Microsoft.NETFramework.ReferenceAssemblies.net461": {
+ "type": "Transitive",
+ "resolved": "1.0.3",
+ "contentHash": "AmOJZwCqnOCNp6PPcf9joyogScWLtwy0M1WkqfEQ0M9nYwyDD7EX9ZjscKS5iYnyvteX7kzSKFCKt9I9dXA6mA=="
+ },
+ "Microsoft.SourceLink.Common": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
+ },
+ "Speckle.Newtonsoft.Json": {
+ "type": "Transitive",
+ "resolved": "13.0.2",
+ "contentHash": "g1BejUZwax5PRfL6xHgLEK23sqHWOgOj9hE7RvfRRlN00AGt8GnPYt8HedSK7UB3HiRW8zCA9Pn0iiYxCK24BA=="
+ },
+ "Speckle.Sdk": {
+ "type": "Transitive",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
+ "dependencies": {
+ "GraphQL.Client": "6.0.0",
+ "Microsoft.Data.Sqlite": "7.0.5",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
+ "Microsoft.Extensions.Logging": "2.2.0",
+ "Speckle.DoubleNumerics": "4.1.0",
+ "Speckle.Newtonsoft.Json": "13.0.2",
+ "Speckle.Sdk.Dependencies": "3.15.3"
+ }
+ },
+ "Speckle.Sdk.Dependencies": {
+ "type": "Transitive",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
+ },
+ "SQLitePCLRaw.bundle_e_sqlite3": {
+ "type": "Transitive",
+ "resolved": "2.1.4",
+ "contentHash": "EWI1olKDjFEBMJu0+3wuxwziIAdWDVMYLhuZ3Qs84rrz+DHwD00RzWPZCa+bLnHCf3oJwuFZIRsHT5p236QXww==",
+ "dependencies": {
+ "SQLitePCLRaw.lib.e_sqlite3": "2.1.4",
+ "SQLitePCLRaw.provider.e_sqlite3": "2.1.4"
+ }
+ },
+ "SQLitePCLRaw.core": {
+ "type": "Transitive",
+ "resolved": "2.1.4",
+ "contentHash": "inBjvSHo9UDKneGNzfUfDjK08JzlcIhn1+SP5Y3m6cgXpCxXKCJDy6Mka7LpgSV+UZmKSnC8rTwB0SQ0xKu5pA==",
+ "dependencies": {
+ "System.Memory": "4.5.3"
+ }
+ },
+ "SQLitePCLRaw.lib.e_sqlite3": {
+ "type": "Transitive",
+ "resolved": "2.1.4",
+ "contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
+ },
+ "SQLitePCLRaw.provider.e_sqlite3": {
+ "type": "Transitive",
+ "resolved": "2.1.4",
+ "contentHash": "CSlb5dUp1FMIkez9Iv5EXzpeq7rHryVNqwJMWnpq87j9zWZexaEMdisDktMsnnrzKM6ahNrsTkjqNodTBPBxtQ==",
+ "dependencies": {
+ "SQLitePCLRaw.core": "2.1.4"
+ }
+ },
+ "System.ComponentModel.Annotations": {
+ "type": "Transitive",
+ "resolved": "4.5.0",
+ "contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
+ },
+ "System.Memory": {
+ "type": "Transitive",
+ "resolved": "4.5.3",
+ "contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA=="
+ },
+ "System.Reactive": {
+ "type": "Transitive",
+ "resolved": "5.0.0",
+ "contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ=="
+ },
+ "System.Runtime.CompilerServices.Unsafe": {
+ "type": "Transitive",
+ "resolved": "4.5.1",
+ "contentHash": "Zh8t8oqolRaFa9vmOZfdQm/qKejdqz0J9kr7o2Fu0vPeoH3BL1EOXipKWwkWtLT1JPzjByrF19fGuFlNbmPpiw=="
+ },
+ "speckle.connectors.common": {
+ "type": "Project",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
+ "Speckle.Connectors.Logging": "[1.0.0, )",
+ "Speckle.Converters.Common": "[1.0.0, )",
+ "Speckle.Objects": "[3.15.3, )"
+ }
+ },
+ "speckle.connectors.dui": {
+ "type": "Project",
+ "dependencies": {
+ "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
+ "Speckle.Connectors.Common": "[1.0.0, )"
+ }
+ },
+ "speckle.connectors.dui.webview": {
+ "type": "Project",
+ "dependencies": {
+ "Microsoft.Web.WebView2": "[1.0.1938.49, )",
+ "Speckle.Connectors.DUI": "[1.0.0, )"
+ }
+ },
+ "speckle.connectors.logging": {
+ "type": "Project"
+ },
+ "speckle.converters.common": {
+ "type": "Project",
+ "dependencies": {
+ "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
+ "Speckle.Objects": "[3.15.3, )"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection": {
+ "type": "CentralTransitive",
+ "requested": "[2.2.0, )",
+ "resolved": "2.2.0",
+ "contentHash": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0"
+ }
+ },
+ "Microsoft.Extensions.Logging": {
+ "type": "CentralTransitive",
+ "requested": "[2.2.0, )",
+ "resolved": "2.2.0",
+ "contentHash": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Binder": "2.2.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
+ "Microsoft.Extensions.Logging.Abstractions": "2.2.0",
+ "Microsoft.Extensions.Options": "2.2.0"
+ }
+ },
+ "Microsoft.Extensions.Logging.Abstractions": {
+ "type": "CentralTransitive",
+ "requested": "[2.2.0, )",
+ "resolved": "2.2.0",
+ "contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
+ },
+ "Microsoft.Web.WebView2": {
+ "type": "CentralTransitive",
+ "requested": "[1.0.1938.49, )",
+ "resolved": "1.0.1938.49",
+ "contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
+ },
+ "Speckle.DoubleNumerics": {
+ "type": "CentralTransitive",
+ "requested": "[4.1.0, )",
+ "resolved": "4.1.0",
+ "contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
+ },
+ "Speckle.Objects": {
+ "type": "CentralTransitive",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
+ "dependencies": {
+ "Speckle.Sdk": "3.15.3"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Converters/Plant3d/Speckle.Converters.Plant3dShared/GlobalUsings.cs b/Converters/Plant3d/Speckle.Converters.Plant3dShared/GlobalUsings.cs
new file mode 100644
index 000000000..edabdb007
--- /dev/null
+++ b/Converters/Plant3d/Speckle.Converters.Plant3dShared/GlobalUsings.cs
@@ -0,0 +1,2 @@
+global using PP = Autodesk.ProcessPower;
+global using PPDL = Autodesk.ProcessPower.DataLinks;
diff --git a/Converters/Plant3d/Speckle.Converters.Plant3dShared/Helpers/PropertyHandler.cs b/Converters/Plant3d/Speckle.Converters.Plant3dShared/Helpers/PropertyHandler.cs
new file mode 100644
index 000000000..c30c00e97
--- /dev/null
+++ b/Converters/Plant3d/Speckle.Converters.Plant3dShared/Helpers/PropertyHandler.cs
@@ -0,0 +1,43 @@
+using Speckle.Sdk;
+
+namespace Speckle.Converters.Plant3dShared.Helpers;
+
+///
+/// Used to help with properties on classes that may throw exceptions when accessed
+///
+public sealed class PropertyHandler
+{
+ public bool TryGetValue(Func getValue, out T? value)
+ {
+ try
+ {
+ value = getValue();
+ return true;
+ }
+ catch (Exception e)
+ when (e is InvalidOperationException
+ || e is ArgumentException argEx && !argEx.IsFatal()
+ || e is Autodesk.AutoCAD.Runtime.Exception acEx && !acEx.IsFatal()
+ )
+ {
+ value = default;
+ return false;
+ }
+ }
+
+ public bool TryAddToDictionary(Dictionary dict, string key, Func getValue)
+ {
+ if (dict.ContainsKey(key))
+ {
+ return false;
+ }
+
+ if (TryGetValue(getValue, out var value))
+ {
+ dict.Add(key, value);
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/Converters/Plant3d/Speckle.Converters.Plant3dShared/Plant3dConversionSettings.cs b/Converters/Plant3d/Speckle.Converters.Plant3dShared/Plant3dConversionSettings.cs
new file mode 100644
index 000000000..a9f7a12a6
--- /dev/null
+++ b/Converters/Plant3d/Speckle.Converters.Plant3dShared/Plant3dConversionSettings.cs
@@ -0,0 +1,3 @@
+namespace Speckle.Converters.Plant3dShared;
+
+public record Plant3dConversionSettings(Document Document, string SpeckleUnits);
diff --git a/Converters/Plant3d/Speckle.Converters.Plant3dShared/Plant3dConversionSettingsFactory.cs b/Converters/Plant3d/Speckle.Converters.Plant3dShared/Plant3dConversionSettingsFactory.cs
new file mode 100644
index 000000000..08215668b
--- /dev/null
+++ b/Converters/Plant3d/Speckle.Converters.Plant3dShared/Plant3dConversionSettingsFactory.cs
@@ -0,0 +1,13 @@
+using Autodesk.AutoCAD.DatabaseServices;
+using Speckle.Converters.Common;
+using Speckle.InterfaceGenerator;
+
+namespace Speckle.Converters.Plant3dShared;
+
+[GenerateAutoInterface]
+public class Plant3dConversionSettingsFactory(IHostToSpeckleUnitConverter unitsConverter)
+ : IPlant3dConversionSettingsFactory
+{
+ public Plant3dConversionSettings Create(Document document) =>
+ new(document, unitsConverter.ConvertOrThrow(document.Database.Insunits));
+}
diff --git a/Converters/Plant3d/Speckle.Converters.Plant3dShared/Plant3dRootToSpeckleConverter.cs b/Converters/Plant3d/Speckle.Converters.Plant3dShared/Plant3dRootToSpeckleConverter.cs
new file mode 100644
index 000000000..9e0cb21cd
--- /dev/null
+++ b/Converters/Plant3d/Speckle.Converters.Plant3dShared/Plant3dRootToSpeckleConverter.cs
@@ -0,0 +1,72 @@
+using System.ComponentModel.DataAnnotations;
+using Speckle.Converters.Common;
+using Speckle.Converters.Common.Objects;
+using Speckle.Converters.Common.Registration;
+using Speckle.Objects.Data;
+using Speckle.Sdk.Models;
+
+namespace Speckle.Converters.Plant3dShared;
+
+public class Plant3dRootToSpeckleConverter(
+ IConverterManager toSpeckle,
+ IConverterSettingsStore settingsStore,
+ ToSpeckle.PropertiesExtractor propertiesExtractor,
+ ToSpeckle.Plant3dDataExtractor dataExtractor
+) : IRootToSpeckleConverter
+{
+ public Base Convert(object target)
+ {
+ if (target is not ADB.DBObject dbObject)
+ {
+ throw new ValidationException(
+ $"Conversion of {target.GetType().Name} to Speckle is not supported. Only objects that inherit from DBObject are."
+ );
+ }
+
+ Type type = dbObject.GetType();
+
+ var objectConverter = toSpeckle.ResolveConverter(type);
+
+ using var l = settingsStore.Current.Document.LockDocument();
+ using var tr = settingsStore.Current.Document.Database.TransactionManager.StartTransaction();
+ Base result = objectConverter.Convert(target);
+
+ if (target is ADB.Entity autocadEntity)
+ {
+ // Extract AEC property sets and extension dictionaries
+ var properties = propertiesExtractor.GetProperties(autocadEntity);
+
+ // Extract Plant3D project database properties (Tag, NominalDiameter, etc.)
+ var dataProperties = dataExtractor.GetDataProperties(autocadEntity);
+
+ if (result is DataObject dataObject)
+ {
+ // Merge AEC properties
+ foreach (var kvp in properties)
+ {
+ dataObject.properties[kvp.Key] = kvp.Value;
+ }
+
+ // Merge Plant3D data under "P&ID" key
+ if (dataProperties.Count > 0)
+ {
+ dataObject.properties["P&ID"] = dataProperties;
+ }
+ }
+ else
+ {
+ if (properties.Count > 0)
+ {
+ result["properties"] = properties;
+ }
+ if (dataProperties.Count > 0)
+ {
+ result["Plant3D Data"] = dataProperties;
+ }
+ }
+ }
+
+ tr.Commit();
+ return result;
+ }
+}
diff --git a/Converters/Plant3d/Speckle.Converters.Plant3dShared/Plant3dToSpeckleUnitConverter.cs b/Converters/Plant3d/Speckle.Converters.Plant3dShared/Plant3dToSpeckleUnitConverter.cs
new file mode 100644
index 000000000..b7c2a7501
--- /dev/null
+++ b/Converters/Plant3d/Speckle.Converters.Plant3dShared/Plant3dToSpeckleUnitConverter.cs
@@ -0,0 +1,37 @@
+using Autodesk.AutoCAD.DatabaseServices;
+using Speckle.Converters.Common;
+using Speckle.Sdk.Common;
+using Speckle.Sdk.Common.Exceptions;
+
+namespace Speckle.Converters.Plant3dShared;
+
+public class Plant3dToSpeckleUnitConverter : IHostToSpeckleUnitConverter
+{
+ private static readonly IReadOnlyDictionary s_unitsMapping = Create();
+
+ private static IReadOnlyDictionary Create()
+ {
+ var dict = new Dictionary();
+
+ dict[UnitsValue.Undefined] = Units.Meters;
+ dict[UnitsValue.Millimeters] = Units.Millimeters;
+ dict[UnitsValue.Centimeters] = Units.Centimeters;
+ dict[UnitsValue.Meters] = Units.Meters;
+ dict[UnitsValue.Kilometers] = Units.Kilometers;
+ dict[UnitsValue.Inches] = Units.Inches;
+ dict[UnitsValue.Feet] = Units.Feet;
+ dict[UnitsValue.Yards] = Units.Yards;
+ dict[UnitsValue.Miles] = Units.Miles;
+ return dict;
+ }
+
+ public string ConvertOrThrow(UnitsValue hostUnit)
+ {
+ if (s_unitsMapping.TryGetValue(hostUnit, out string? value))
+ {
+ return value;
+ }
+
+ throw new UnitNotSupportedException($"The Unit System \"{hostUnit}\" is unsupported.");
+ }
+}
diff --git a/Converters/Plant3d/Speckle.Converters.Plant3dShared/ServiceRegistration.cs b/Converters/Plant3d/Speckle.Converters.Plant3dShared/ServiceRegistration.cs
new file mode 100644
index 000000000..afa28fd8a
--- /dev/null
+++ b/Converters/Plant3d/Speckle.Converters.Plant3dShared/ServiceRegistration.cs
@@ -0,0 +1,43 @@
+using Microsoft.Extensions.DependencyInjection;
+using Speckle.Converters.Autocad;
+using Speckle.Converters.Autocad.ToHost.Helpers;
+using Speckle.Converters.Common;
+using Speckle.Converters.Common.Registration;
+using Speckle.Converters.Plant3dShared.ToSpeckle;
+using Speckle.Sdk;
+
+namespace Speckle.Converters.Plant3dShared;
+
+public static class ServiceRegistration
+{
+ public static void AddPlant3dConverters(this IServiceCollection serviceCollection)
+ {
+ var plant3dAssembly = typeof(Plant3dConversionSettings).Assembly;
+ var autocadAssembly = typeof(AutocadConversionSettings).Assembly;
+ // register types by default
+ serviceCollection.AddMatchingInterfacesAsTransient(plant3dAssembly);
+ serviceCollection.AddMatchingInterfacesAsTransient(autocadAssembly);
+ // Register single root
+ serviceCollection.AddRootCommon(plant3dAssembly);
+
+ // register all application converters
+ serviceCollection.AddApplicationConverters(plant3dAssembly);
+ // serviceCollection.AddApplicationConverters(autocadAssembly);
+ serviceCollection.AddScoped<
+ IConverterSettingsStore,
+ ConverterSettingsStore
+ >();
+ serviceCollection.AddScoped<
+ IConverterSettingsStore,
+ ConverterSettingsStore
+ >();
+ serviceCollection.AddScoped();
+
+ // add other classes
+ serviceCollection.AddScoped(); // for plant3d
+ serviceCollection.AddScoped();
+ serviceCollection.AddScoped();
+ serviceCollection.AddScoped();
+ serviceCollection.AddScoped();
+ }
+}
diff --git a/Converters/Plant3d/Speckle.Converters.Plant3dShared/Speckle.Converters.Plant3dShared.projitems b/Converters/Plant3d/Speckle.Converters.Plant3dShared/Speckle.Converters.Plant3dShared.projitems
new file mode 100644
index 000000000..aa9193041
--- /dev/null
+++ b/Converters/Plant3d/Speckle.Converters.Plant3dShared/Speckle.Converters.Plant3dShared.projitems
@@ -0,0 +1,29 @@
+
+
+
+ $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
+ true
+ C7E3A28D-5F91-4B6E-A8D2-3F1C9E7B4D56
+
+
+ Speckle.Converters.Plant3dShared
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Converters/Plant3d/Speckle.Converters.Plant3dShared/Speckle.Converters.Plant3dShared.shproj b/Converters/Plant3d/Speckle.Converters.Plant3dShared/Speckle.Converters.Plant3dShared.shproj
new file mode 100644
index 000000000..292cf8614
--- /dev/null
+++ b/Converters/Plant3d/Speckle.Converters.Plant3dShared/Speckle.Converters.Plant3dShared.shproj
@@ -0,0 +1,13 @@
+
+
+
+ C7E3A28D-5F91-4B6E-A8D2-3F1C9E7B4D56
+ 14.0
+
+
+
+
+
+
+
+
diff --git a/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Geometry/EquipmentToSpeckleConverter.cs b/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Geometry/EquipmentToSpeckleConverter.cs
new file mode 100644
index 000000000..9dd935920
--- /dev/null
+++ b/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Geometry/EquipmentToSpeckleConverter.cs
@@ -0,0 +1,11 @@
+using Speckle.Converters.Common;
+using Speckle.Converters.Common.Objects;
+using Speckle.Converters.Common.Registration;
+
+namespace Speckle.Converters.Plant3dShared.ToSpeckle.Geometry;
+
+[NameAndRankValue(typeof(PP.PnP3dObjects.Equipment), NameAndRankValueAttribute.SPECKLE_DEFAULT_RANK)]
+public class EquipmentToSpeckleConverter(
+ IConverterManager converterManager,
+ IConverterSettingsStore settingsStore
+) : Plant3dEntityToSpeckleConverter(converterManager, settingsStore);
diff --git a/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Geometry/FallbackEntityToSpeckleConverter.cs b/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Geometry/FallbackEntityToSpeckleConverter.cs
new file mode 100644
index 000000000..a7607cfef
--- /dev/null
+++ b/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Geometry/FallbackEntityToSpeckleConverter.cs
@@ -0,0 +1,18 @@
+using Speckle.Converters.Common;
+using Speckle.Converters.Common.Objects;
+using Speckle.Converters.Common.Registration;
+
+//using Speckle.Objects.Data;
+//using Speckle.Sdk.Models;
+
+namespace Speckle.Converters.Plant3dShared.ToSpeckle.Geometry;
+
+///
+/// Fallback converter for any ADB.Entity that doesn't have a specific Plant3D converter.
+/// Uses a rank lower than SPECKLE_DEFAULT_RANK so specific converters always win.
+///
+[NameAndRankValue(typeof(ADB.Entity), NameAndRankValueAttribute.SPECKLE_DEFAULT_RANK - 1)]
+public class FallbackEntityToSpeckleConverter(
+ IConverterManager converterManager,
+ IConverterSettingsStore settingsStore
+) : Plant3dEntityToSpeckleConverter(converterManager, settingsStore);
diff --git a/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Geometry/LineSegmentToSpeckleConverter.cs b/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Geometry/LineSegmentToSpeckleConverter.cs
new file mode 100644
index 000000000..45f6fb396
--- /dev/null
+++ b/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Geometry/LineSegmentToSpeckleConverter.cs
@@ -0,0 +1,66 @@
+using Speckle.Converters.Autocad;
+using Speckle.Converters.Common;
+using Speckle.Converters.Common.Objects;
+using Speckle.Objects.Data;
+using Speckle.Sdk.Models;
+
+namespace Speckle.Converters.Plant3dShared.ToSpeckle.Geometry;
+
+///
+/// Converts P&ID LineSegment (SLINE) entities to Speckle.
+/// Unlike 3D Plant objects (Pipe, Equipment) which are block references needing Explode(),
+/// LineSegment is a Curve-based entity. We read its Vertices directly and produce a Polyline,
+/// applying the same coordinate transforms as the AutoCAD converters.
+///
+[NameAndRankValue(typeof(PP.PnIDObjects.LineSegment), NameAndRankValueAttribute.SPECKLE_DEFAULT_RANK)]
+public class LineSegmentToSpeckleConverter : IToSpeckleTopLevelConverter
+{
+ private readonly IConverterSettingsStore _settingsStore;
+ private readonly IReferencePointConverter _referencePointConverter;
+
+ public LineSegmentToSpeckleConverter(
+ IConverterSettingsStore settingsStore,
+ IReferencePointConverter referencePointConverter
+ )
+ {
+ _settingsStore = settingsStore;
+ _referencePointConverter = referencePointConverter;
+ }
+
+ public Base Convert(object target)
+ {
+ var lineSegment = (PP.PnIDObjects.LineSegment)target;
+
+ // Build a flat list of xyz coordinates from the Vertices collection
+ var vertices = lineSegment.Vertices;
+ List value = new(vertices.Count * 3);
+ foreach (AG.Point3d pt in vertices)
+ {
+ value.Add(pt.X);
+ value.Add(pt.Y);
+ value.Add(pt.Z);
+ }
+
+ // Apply the same WCS → external coordinate transform that all AutoCAD converters use
+ value = _referencePointConverter.ConvertWCSDoublesToExternalCoordinates(value);
+
+ SOG.Polyline polyline =
+ new()
+ {
+ value = value,
+ closed = lineSegment.Closed,
+ units = _settingsStore.Current.SpeckleUnits
+ };
+
+ DataObject dataObject =
+ new()
+ {
+ name = lineSegment.TagValue is { Length: > 0 } tag ? tag : lineSegment.GetType().Name,
+ displayValue = new List { polyline },
+ properties = new Dictionary(),
+ applicationId = lineSegment.Handle.Value.ToString()
+ };
+
+ return dataObject;
+ }
+}
diff --git a/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Geometry/PipeInlineAssetToSpeckleConverter.cs b/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Geometry/PipeInlineAssetToSpeckleConverter.cs
new file mode 100644
index 000000000..a73c593b0
--- /dev/null
+++ b/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Geometry/PipeInlineAssetToSpeckleConverter.cs
@@ -0,0 +1,14 @@
+using Speckle.Converters.Common;
+using Speckle.Converters.Common.Objects;
+using Speckle.Converters.Common.Registration;
+
+namespace Speckle.Converters.Plant3dShared.ToSpeckle.Geometry;
+
+///
+/// Converts inline pipe assets (valves, instruments, etc.) to Speckle.
+///
+[NameAndRankValue(typeof(PP.PnP3dObjects.PipeInlineAsset), NameAndRankValueAttribute.SPECKLE_DEFAULT_RANK)]
+public class PipeInlineAssetToSpeckleConverter(
+ IConverterManager converterManager,
+ IConverterSettingsStore settingsStore
+) : Plant3dEntityToSpeckleConverter(converterManager, settingsStore);
diff --git a/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Geometry/PipeToSpeckleConverter.cs b/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Geometry/PipeToSpeckleConverter.cs
new file mode 100644
index 000000000..70e6278d9
--- /dev/null
+++ b/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Geometry/PipeToSpeckleConverter.cs
@@ -0,0 +1,11 @@
+using Speckle.Converters.Common;
+using Speckle.Converters.Common.Objects;
+using Speckle.Converters.Common.Registration;
+
+namespace Speckle.Converters.Plant3dShared.ToSpeckle.Geometry;
+
+[NameAndRankValue(typeof(PP.PnP3dObjects.Pipe), NameAndRankValueAttribute.SPECKLE_DEFAULT_RANK)]
+public class PipeToSpeckleConverter(
+ IConverterManager converterManager,
+ IConverterSettingsStore settingsStore
+) : Plant3dEntityToSpeckleConverter(converterManager, settingsStore);
diff --git a/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Geometry/Plant3dEntityToSpeckleConverter.cs b/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Geometry/Plant3dEntityToSpeckleConverter.cs
new file mode 100644
index 000000000..ba4759532
--- /dev/null
+++ b/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Geometry/Plant3dEntityToSpeckleConverter.cs
@@ -0,0 +1,119 @@
+using Speckle.Converters.Common;
+using Speckle.Converters.Common.Objects;
+using Speckle.Converters.Common.Registration;
+using Speckle.Objects.Data;
+using Speckle.Sdk.Models;
+
+namespace Speckle.Converters.Plant3dShared.ToSpeckle.Geometry;
+
+///
+/// Generic converter for Plant3D entity types.
+/// Plant3D entities are internally block references (often nested).
+/// Uses Explode() to decompose into world-coordinate geometry, then converts each
+/// sub-entity using the existing AutoCAD converters (Line, Arc, Solid3d, etc.).
+///
+public abstract class Plant3dEntityToSpeckleConverter : IToSpeckleTopLevelConverter
+{
+ private readonly IConverterManager _converterManager;
+ private readonly IConverterSettingsStore _settingsStore;
+
+ private const int MAX_DEPTH = 5;
+
+ protected Plant3dEntityToSpeckleConverter(
+ IConverterManager converterManager,
+ IConverterSettingsStore settingsStore
+ )
+ {
+ _converterManager = converterManager;
+ _settingsStore = settingsStore;
+ }
+
+ public Base Convert(object target) => ConvertEntity((ADB.Entity)target);
+
+ private DataObject ConvertEntity(ADB.Entity entity)
+ {
+ List displayValue = ExtractDisplayValue(entity);
+
+ // Plant3D P&ID types (Asset, LineSegment, EndLineObject, etc.) each have a TagValue property
+ // that provides a unique, human-readable identifier (e.g. "T-0001", "1 1/2"-CIPS-Util1049-...").
+ // These types all inherit directly from ADB.Entity — there is no shared P&ID base class
+ // that declares TagValue, so we use reflection to read it regardless of the concrete type.
+ // I don't like this but its a good tradeoff since Plant3d API does not have common class to find TagValue
+ string name = entity.GetType().Name;
+ if (entity.GetType().GetProperty("TagValue")?.GetValue(entity) is string tagValue && tagValue.Length > 0)
+ {
+ name = tagValue;
+ }
+
+ DataObject dataObject =
+ new()
+ {
+ name = name,
+ displayValue = displayValue,
+ properties = new Dictionary(),
+ applicationId = entity.Handle.Value.ToString()
+ };
+
+ return dataObject;
+ }
+
+#pragma warning disable CA1031 // Autodesk APIs throw various exception types
+ private List ExtractDisplayValue(ADB.Entity entity)
+ {
+ List results = new();
+ CollectDisplayObjects(entity, results, 0);
+ return results;
+ }
+
+ ///
+ /// Recursively explodes the entity to reach leaf geometry, then converts
+ /// each piece using the registered AutoCAD converters.
+ /// Explode() produces entities in world coordinates (transforms are applied),
+ /// unlike opening the BlockTableRecord directly which gives local coordinates.
+ ///
+ private void CollectDisplayObjects(ADB.Entity entity, List results, int depth)
+ {
+ // If this is NOT a block reference, try converting it directly
+ // (Line, Arc, Circle, Polyline, Solid3d, etc.)
+ if (entity is not ADB.BlockReference)
+ {
+ try
+ {
+ var converter = _converterManager.ResolveConverter(entity.GetType(), false);
+
+ var converted = converter.Convert(entity);
+ results.Add(converted);
+ return;
+ }
+ catch (System.Exception)
+ {
+ // Fall through to explode on ConversionNotSupportedException or failed
+ }
+ }
+
+ // For BlockReferences or unconvertible entities, explode to get sub-entities
+ // Explode produces world-coordinate geometry (block transform is applied)
+ if (depth >= MAX_DEPTH)
+ {
+ return;
+ }
+
+ try
+ {
+ using ADB.DBObjectCollection exploded = new();
+ entity.Explode(exploded);
+ foreach (ADB.DBObject obj in exploded)
+ {
+ if (obj is ADB.Entity subEntity)
+ {
+ CollectDisplayObjects(subEntity, results, depth + 1);
+ }
+ }
+ }
+ catch (System.Exception)
+ {
+ // Can't explode — no display value from this entity
+ }
+ }
+#pragma warning restore CA1031
+}
diff --git a/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Properties/ExtensionDictionaryExtractor.cs b/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Properties/ExtensionDictionaryExtractor.cs
new file mode 100644
index 000000000..7844b8b96
--- /dev/null
+++ b/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Properties/ExtensionDictionaryExtractor.cs
@@ -0,0 +1,55 @@
+using Speckle.Converters.Common;
+
+namespace Speckle.Converters.Plant3dShared.ToSpeckle;
+
+///
+/// Extracts extension dictionaries out from an element. Expects to be scoped per operation.
+///
+public class ExtensionDictionaryExtractor
+{
+ private readonly IConverterSettingsStore _settingsStore;
+
+ public ExtensionDictionaryExtractor(IConverterSettingsStore settingsStore)
+ {
+ _settingsStore = settingsStore;
+ }
+
+ ///
+ /// Extracts extension dictionary out from an entity. Expects to be scoped per operation.
+ ///
+ public Dictionary? GetExtensionDictionary(ADB.Entity entity)
+ {
+ if (entity is null || entity.ExtensionDictionary == ADB.ObjectId.Null)
+ {
+ return null;
+ }
+
+ Dictionary extensionDictionaryDict = new();
+
+ using (ADB.Transaction tr = _settingsStore.Current.Document.TransactionManager.StartTransaction())
+ {
+ var extensionDictionary = (ADB.DBDictionary)tr.GetObject(entity.ExtensionDictionary, ADB.OpenMode.ForRead, false);
+
+ foreach (ADB.DBDictionaryEntry entry in extensionDictionary)
+ {
+ if (tr.GetObject(entry.Value, ADB.OpenMode.ForRead) is ADB.Xrecord xRecord)
+ {
+ Dictionary entryDict = new();
+ foreach (ADB.TypedValue xEntry in xRecord.Data)
+ {
+ entryDict[xEntry.TypeCode.ToString()] = xEntry.Value;
+ }
+
+ if (entryDict.Count > 0)
+ {
+ extensionDictionaryDict[$"{entry.Key}"] = entryDict;
+ }
+ }
+ }
+
+ tr.Commit();
+ }
+
+ return extensionDictionaryDict.Count > 0 ? extensionDictionaryDict : null;
+ }
+}
diff --git a/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Properties/Plant3dDataExtractor.cs b/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Properties/Plant3dDataExtractor.cs
new file mode 100644
index 000000000..af8095022
--- /dev/null
+++ b/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Properties/Plant3dDataExtractor.cs
@@ -0,0 +1,67 @@
+using Speckle.Converters.Common;
+
+namespace Speckle.Converters.Plant3dShared.ToSpeckle;
+
+///
+/// Extracts Plant3D project database properties for entities.
+/// Uses the PnPDataLinks API to find the data row linked to a DWG entity,
+/// then reads all properties from that row in the project database (DCF files).
+///
+public class Plant3dDataExtractor
+{
+ private readonly IConverterSettingsStore _settingsStore;
+
+ public Plant3dDataExtractor(IConverterSettingsStore settingsStore)
+ {
+ _settingsStore = settingsStore;
+ }
+
+ ///
+ /// Gets Plant3D database properties for the given entity.
+ /// Returns a dictionary of property name → value pairs from the project database.
+ ///
+#pragma warning disable CA1031 // Plant3D data APIs can throw various exceptions
+ public Dictionary GetDataProperties(ADB.Entity entity)
+ {
+ var result = new Dictionary();
+
+ try
+ {
+ var database = _settingsStore.Current.Document.Database;
+
+ // Get the DataLinksManager for this database
+ var dlm = PPDL.DataLinksManager.GetManager(database);
+ if (dlm is null)
+ {
+ return result;
+ }
+
+ // Find the data row linked to this entity (returns single int row ID)
+ int rowId = dlm.FindAcPpRowId(entity.ObjectId);
+ if (rowId <= 0)
+ {
+ return result;
+ }
+
+ // Read all properties from the linked row
+ var allProps = dlm.GetAllProperties(rowId, true);
+ if (allProps is not null)
+ {
+ foreach (var kvp in allProps)
+ {
+ string key = kvp.Key ?? "unknown";
+
+ result[key] = kvp.Value;
+ }
+ }
+ }
+ catch (PPDL.DLException)
+ {
+ // DataLinksManager not available or other API failure
+ }
+
+ return result;
+ }
+
+#pragma warning restore CA1031
+}
diff --git a/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Properties/PropertiesExtractor.cs b/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Properties/PropertiesExtractor.cs
new file mode 100644
index 000000000..3bfe539a0
--- /dev/null
+++ b/Converters/Plant3d/Speckle.Converters.Plant3dShared/ToSpeckle/Properties/PropertiesExtractor.cs
@@ -0,0 +1,43 @@
+namespace Speckle.Converters.Plant3dShared.ToSpeckle;
+
+///
+/// Extracts properties for Plant3D objects.
+///
+public class PropertiesExtractor : Speckle.Converters.AutocadShared.ToSpeckle.IPropertiesExtractor
+{
+ private readonly ExtensionDictionaryExtractor _extensionDictionaryExtractor;
+
+ public PropertiesExtractor(ExtensionDictionaryExtractor extensionDictionaryExtractor)
+ {
+ _extensionDictionaryExtractor = extensionDictionaryExtractor;
+ }
+
+ public Dictionary GetProperties(ADB.Entity entity)
+ {
+ Dictionary properties = new();
+
+ // TODO: Add Plant3D class-specific property extraction here
+ // For example, extract pipe spec data, equipment data, etc.
+
+ // add property sets and extension dictionaries to the properties dict
+ AddDictionaryToPropertyDictionary(
+ _extensionDictionaryExtractor.GetExtensionDictionary(entity),
+ "Extension Dictionary",
+ properties
+ );
+
+ return properties;
+ }
+
+ private void AddDictionaryToPropertyDictionary(
+ Dictionary? entryDictionary,
+ string entryName,
+ Dictionary propertyDictionary
+ )
+ {
+ if (entryDictionary is not null && entryDictionary.Count > 0)
+ {
+ propertyDictionary.Add(entryName, entryDictionary);
+ }
+ }
+}
diff --git a/Converters/Revit/Speckle.Converters.Revit2022/packages.lock.json b/Converters/Revit/Speckle.Converters.Revit2022/packages.lock.json
index a90eab9c8..3d1476d98 100644
--- a/Converters/Revit/Speckle.Converters.Revit2022/packages.lock.json
+++ b/Converters/Revit/Speckle.Converters.Revit2022/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -288,7 +288,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"LibTessDotNet": {
@@ -323,11 +323,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Revit/Speckle.Converters.Revit2023/packages.lock.json b/Converters/Revit/Speckle.Converters.Revit2023/packages.lock.json
index e7faee8fd..8bfc35af5 100644
--- a/Converters/Revit/Speckle.Converters.Revit2023/packages.lock.json
+++ b/Converters/Revit/Speckle.Converters.Revit2023/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -288,7 +288,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"LibTessDotNet": {
@@ -323,11 +323,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Revit/Speckle.Converters.Revit2024/packages.lock.json b/Converters/Revit/Speckle.Converters.Revit2024/packages.lock.json
index a6c4fbdb6..88727938a 100644
--- a/Converters/Revit/Speckle.Converters.Revit2024/packages.lock.json
+++ b/Converters/Revit/Speckle.Converters.Revit2024/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -288,7 +288,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"LibTessDotNet": {
@@ -323,11 +323,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Revit/Speckle.Converters.Revit2025/packages.lock.json b/Converters/Revit/Speckle.Converters.Revit2025/packages.lock.json
index b1482d1a3..6e540ab7f 100644
--- a/Converters/Revit/Speckle.Converters.Revit2025/packages.lock.json
+++ b/Converters/Revit/Speckle.Converters.Revit2025/packages.lock.json
@@ -157,8 +157,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -166,13 +166,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -235,7 +235,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"LibTessDotNet": {
@@ -270,11 +270,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Revit/Speckle.Converters.Revit2026/packages.lock.json b/Converters/Revit/Speckle.Converters.Revit2026/packages.lock.json
index 9429f96f1..ccdc748fc 100644
--- a/Converters/Revit/Speckle.Converters.Revit2026/packages.lock.json
+++ b/Converters/Revit/Speckle.Converters.Revit2026/packages.lock.json
@@ -157,8 +157,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -166,13 +166,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -235,7 +235,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"LibTessDotNet": {
@@ -270,11 +270,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Rhino/Speckle.Converters.Rhino7/packages.lock.json b/Converters/Rhino/Speckle.Converters.Rhino7/packages.lock.json
index 490b1c858..d0e86234a 100644
--- a/Converters/Rhino/Speckle.Converters.Rhino7/packages.lock.json
+++ b/Converters/Rhino/Speckle.Converters.Rhino7/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -281,7 +281,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.Logging": {
@@ -310,11 +310,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Rhino/Speckle.Converters.Rhino8/packages.lock.json b/Converters/Rhino/Speckle.Converters.Rhino8/packages.lock.json
index 37413da81..bedaabff4 100644
--- a/Converters/Rhino/Speckle.Converters.Rhino8/packages.lock.json
+++ b/Converters/Rhino/Speckle.Converters.Rhino8/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -281,7 +281,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.Logging": {
@@ -310,11 +310,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
},
@@ -346,9 +346,9 @@
},
"RhinoCommon": {
"type": "Direct",
- "requested": "[8.25.25328.11001, )",
- "resolved": "8.25.25328.11001",
- "contentHash": "PDKR9GwqyUXUkTulV4J0dzDIf/aWqSJkL7nkS8ReAx8xhnt/+RQpE8gTjOSCmkSU2tjG6WzclowbTxwMTU7VAA==",
+ "requested": "[8.28.26041.11001, )",
+ "resolved": "8.28.26041.11001",
+ "contentHash": "5mByZF+IdHvRLbYvr6Ek95Pwam6otewAyVHIGSC0sUE1+OscSpd9gbrFWnzo1arfCYmUJcUdsGhf7VayW09fQA==",
"dependencies": {
"System.Drawing.Common": "7.0.0"
}
@@ -482,8 +482,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -491,13 +491,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -561,7 +561,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.Logging": {
@@ -590,11 +590,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Converters/Tekla/Speckle.Converter.Tekla2023/packages.lock.json b/Converters/Tekla/Speckle.Converter.Tekla2023/packages.lock.json
index 106e1760a..3b901eead 100644
--- a/Converters/Tekla/Speckle.Converter.Tekla2023/packages.lock.json
+++ b/Converters/Tekla/Speckle.Converter.Tekla2023/packages.lock.json
@@ -188,8 +188,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -198,13 +198,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -325,7 +325,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"LibTessDotNet": {
@@ -360,11 +360,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
},
"Tekla.Structures.Dialog": {
diff --git a/Converters/Tekla/Speckle.Converter.Tekla2024/packages.lock.json b/Converters/Tekla/Speckle.Converter.Tekla2024/packages.lock.json
index 325e1b28a..b526d0ab2 100644
--- a/Converters/Tekla/Speckle.Converter.Tekla2024/packages.lock.json
+++ b/Converters/Tekla/Speckle.Converter.Tekla2024/packages.lock.json
@@ -198,8 +198,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -208,13 +208,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -366,7 +366,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"LibTessDotNet": {
@@ -401,11 +401,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
},
"Tekla.Structures.Plugins": {
diff --git a/Converters/Tekla/Speckle.Converter.Tekla2025/packages.lock.json b/Converters/Tekla/Speckle.Converter.Tekla2025/packages.lock.json
index 325e1b28a..b526d0ab2 100644
--- a/Converters/Tekla/Speckle.Converter.Tekla2025/packages.lock.json
+++ b/Converters/Tekla/Speckle.Converter.Tekla2025/packages.lock.json
@@ -198,8 +198,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -208,13 +208,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -366,7 +366,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"LibTessDotNet": {
@@ -401,11 +401,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
},
"Tekla.Structures.Plugins": {
diff --git a/DUI3/Speckle.Connectors.DUI.Tests/ReceiveOperationManagerTests.cs b/DUI3/Speckle.Connectors.DUI.Tests/ReceiveOperationManagerTests.cs
index 3112474f2..311fbe12f 100644
--- a/DUI3/Speckle.Connectors.DUI.Tests/ReceiveOperationManagerTests.cs
+++ b/DUI3/Speckle.Connectors.DUI.Tests/ReceiveOperationManagerTests.cs
@@ -12,6 +12,7 @@ using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Models.Card;
using Speckle.Sdk;
using Speckle.Sdk.Credentials;
+using Speckle.Sdk.Pipelines.Progress;
using Speckle.Testing;
namespace Speckle.Connectors.DUI.Tests;
diff --git a/DUI3/Speckle.Connectors.DUI.Tests/packages.lock.json b/DUI3/Speckle.Connectors.DUI.Tests/packages.lock.json
index 22da2186f..414680b2a 100644
--- a/DUI3/Speckle.Connectors.DUI.Tests/packages.lock.json
+++ b/DUI3/Speckle.Connectors.DUI.Tests/packages.lock.json
@@ -238,8 +238,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -247,13 +247,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -334,7 +334,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -351,7 +351,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.testing": {
@@ -360,7 +360,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Moq": "[4.20.70, )",
"NUnit": "[4.1.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -398,11 +398,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/DUI3/Speckle.Connectors.DUI.WebView/packages.lock.json b/DUI3/Speckle.Connectors.DUI.WebView/packages.lock.json
index f8eec91b8..89496050d 100644
--- a/DUI3/Speckle.Connectors.DUI.WebView/packages.lock.json
+++ b/DUI3/Speckle.Connectors.DUI.WebView/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -283,7 +283,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -300,7 +300,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -338,11 +338,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
},
@@ -502,8 +502,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -511,13 +511,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -575,7 +575,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -592,7 +592,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -630,11 +630,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/DUI3/Speckle.Connectors.DUI/Bindings/ISendBindingUICommands.cs b/DUI3/Speckle.Connectors.DUI/Bindings/ISendBindingUICommands.cs
index 0fb6ddc10..f732aa369 100644
--- a/DUI3/Speckle.Connectors.DUI/Bindings/ISendBindingUICommands.cs
+++ b/DUI3/Speckle.Connectors.DUI/Bindings/ISendBindingUICommands.cs
@@ -13,7 +13,8 @@ public interface ISendBindingUICommands
Task SetModelSendResult(
string modelCardId,
string versionId,
- IEnumerable sendConversionResults
+ IEnumerable sendConversionResults,
+ string? ingestionId = null
);
IBrowserBridge Bridge { get; }
diff --git a/DUI3/Speckle.Connectors.DUI/Bindings/OperationProgressManager.cs b/DUI3/Speckle.Connectors.DUI/Bindings/OperationProgressManager.cs
index c8dd08700..ccc047dac 100644
--- a/DUI3/Speckle.Connectors.DUI/Bindings/OperationProgressManager.cs
+++ b/DUI3/Speckle.Connectors.DUI/Bindings/OperationProgressManager.cs
@@ -1,8 +1,8 @@
using System.Collections.Concurrent;
-using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Models.Card;
using Speckle.InterfaceGenerator;
+using Speckle.Sdk.Pipelines.Progress;
namespace Speckle.Connectors.DUI.Bindings;
@@ -21,7 +21,7 @@ public class OperationProgressManager : IOperationProgressManager
private const string SET_MODEL_PROGRESS_UI_COMMAND_NAME = "setModelProgress";
private static readonly ConcurrentDictionary s_lastProgressValues =
new();
- private const int THROTTLE_INTERVAL_MS = 200;
+ private const int THROTTLE_INTERVAL_MS = 400;
public IProgress CreateOperationProgressEventHandler(
IBrowserBridge bridge,
@@ -65,11 +65,10 @@ public class OperationProgressManager : IOperationProgressManager
var currentTime = DateTime.Now;
var elapsedMs = (currentTime - t.Item1).Milliseconds;
- if (elapsedMs < THROTTLE_INTERVAL_MS && t.Item2 == progress.Status)
+ if (elapsedMs < THROTTLE_INTERVAL_MS)
{
return;
}
- Console.WriteLine($"Progress: {progress.Status} - {progress.Progress}");
s_lastProgressValues[modelCardId] = (currentTime, progress.Status);
SendProgress(bridge, modelCardId, progress);
}
diff --git a/DUI3/Speckle.Connectors.DUI/Bindings/SendBindingUICommands.cs b/DUI3/Speckle.Connectors.DUI/Bindings/SendBindingUICommands.cs
index eeafee7b3..8c0bc944c 100644
--- a/DUI3/Speckle.Connectors.DUI/Bindings/SendBindingUICommands.cs
+++ b/DUI3/Speckle.Connectors.DUI/Bindings/SendBindingUICommands.cs
@@ -37,7 +37,8 @@ public class SendBindingUICommands(IBrowserBridge bridge)
public async Task SetModelSendResult(
string modelCardId,
string versionId,
- IEnumerable sendConversionResults
+ IEnumerable sendConversionResults,
+ string? ingestionId = null
) =>
await Bridge.Send(
SET_MODEL_SEND_RESULT_UI_COMMAND_NAME,
@@ -45,7 +46,8 @@ public class SendBindingUICommands(IBrowserBridge bridge)
{
modelCardId,
versionId,
- sendConversionResults
+ sendConversionResults,
+ ingestionId
}
);
}
diff --git a/DUI3/Speckle.Connectors.DUI/Bindings/SendOperationManager.cs b/DUI3/Speckle.Connectors.DUI/Bindings/SendOperationManager.cs
index 069b661a3..c7216dd7d 100644
--- a/DUI3/Speckle.Connectors.DUI/Bindings/SendOperationManager.cs
+++ b/DUI3/Speckle.Connectors.DUI/Bindings/SendOperationManager.cs
@@ -13,6 +13,7 @@ using Speckle.Sdk.Api;
using Speckle.Sdk.Common;
using Speckle.Sdk.Credentials;
using Speckle.Sdk.Logging;
+using Speckle.Sdk.Pipelines.Progress;
namespace Speckle.Connectors.DUI.Bindings;
@@ -98,7 +99,7 @@ public sealed class SendOperationManager(
cancellationItem.Token
);
- var objects = await gatherObjects(modelCard, progress);
+ var objects = await gatherObjects.Invoke(modelCard, progress);
if (objects.Count == 0)
{
@@ -108,7 +109,7 @@ public sealed class SendOperationManager(
var sendOperation = serviceScope.ServiceProvider.GetRequiredService>();
- var (result, versionId) = await sendOperation.Send(
+ var (result, versionId, ingestionId) = await sendOperation.Send(
objects,
sendInfo,
fileName,
@@ -118,7 +119,7 @@ public sealed class SendOperationManager(
cancellationItem.Token
);
- await commands.SetModelSendResult(modelCardId, versionId, result.ConversionResults);
+ await commands.SetModelSendResult(modelCardId, versionId, result.ConversionResults, ingestionId);
}
catch (OperationCanceledException)
{
diff --git a/DUI3/Speckle.Connectors.DUI/Models/Card/ModelCardProgress.cs b/DUI3/Speckle.Connectors.DUI/Models/Card/ModelCardProgress.cs
index aff002bd2..4827bdfa0 100644
--- a/DUI3/Speckle.Connectors.DUI/Models/Card/ModelCardProgress.cs
+++ b/DUI3/Speckle.Connectors.DUI/Models/Card/ModelCardProgress.cs
@@ -4,7 +4,7 @@
/// Progress value between 0 and 1 to calculate UI progress bar width.
/// If it is null it will swooshing on UI.
///
-public record ModelCardProgress(string ModelCardId, string Status, double? Progress)
+public readonly record struct ModelCardProgress(string ModelCardId, string Status, double? Progress)
{
public override string ToString() => $"{ModelCardId} - {Status} - {Progress}";
}
diff --git a/DUI3/Speckle.Connectors.DUI/packages.lock.json b/DUI3/Speckle.Connectors.DUI/packages.lock.json
index d2e5a5c63..2f6d69744 100644
--- a/DUI3/Speckle.Connectors.DUI/packages.lock.json
+++ b/DUI3/Speckle.Connectors.DUI/packages.lock.json
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -181,13 +181,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -283,7 +283,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.logging": {
@@ -293,7 +293,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -325,11 +325,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
},
@@ -489,8 +489,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -498,13 +498,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -562,7 +562,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.logging": {
@@ -572,7 +572,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -604,11 +604,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 6c8bf8f1a..b31fd4e18 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -18,7 +18,7 @@
-
+
@@ -28,10 +28,10 @@
-
+
-
-
+
+
@@ -43,8 +43,8 @@
-
-
+
+
@@ -54,7 +54,7 @@
-
+
diff --git a/Importers/Rhino/Speckle.Importers.JobProcessor/Blobs/ImportJobFileFactory.cs b/Importers/Rhino/Speckle.Importers.JobProcessor/Blobs/ImportJobFileFactory.cs
index ea6f9d077..cd583a9b0 100644
--- a/Importers/Rhino/Speckle.Importers.JobProcessor/Blobs/ImportJobFileFactory.cs
+++ b/Importers/Rhino/Speckle.Importers.JobProcessor/Blobs/ImportJobFileFactory.cs
@@ -1,22 +1,35 @@
using Microsoft.Extensions.Logging;
using Speckle.Importers.JobProcessor.Domain;
using Speckle.Sdk.Api;
+using Speckle.Sdk.Logging;
namespace Speckle.Importers.JobProcessor.Blobs;
-internal sealed class ImportJobFileDownloader(ILogger logger)
+internal sealed class ImportJobFileDownloader(ILogger logger, ISdkActivityFactory activityFactory)
{
public async Task DownloadFile(FileimportJob job, IClient client, CancellationToken cancellationToken)
{
- var directory = Directory.CreateTempSubdirectory("speckle-file-import");
- string targetFilePath = $"{directory.FullName}/{job.Payload.BlobId}.{job.Payload.FileType}";
- await client.FileImport.DownloadFile(
- job.Payload.ProjectId,
- job.Payload.BlobId,
- targetFilePath,
- null,
- cancellationToken
- );
- return new ImportJobFile(logger, new FileInfo(targetFilePath));
+ using var activity = activityFactory.Start();
+ try
+ {
+ var directory = Directory.CreateTempSubdirectory("speckle-file-import");
+ string targetFilePath = $"{directory.FullName}/{job.Payload.BlobId}.{job.Payload.FileType}";
+ await client.FileImport.DownloadFile(
+ job.Payload.ProjectId,
+ job.Payload.BlobId,
+ targetFilePath,
+ null,
+ cancellationToken
+ );
+ var ret = new ImportJobFile(logger, new FileInfo(targetFilePath));
+ activity?.SetStatus(SdkActivityStatusCode.Ok);
+ return ret;
+ }
+ catch (Exception ex)
+ {
+ activity?.RecordException(ex);
+ activity?.SetStatus(SdkActivityStatusCode.Error);
+ throw;
+ }
}
}
diff --git a/Importers/Rhino/Speckle.Importers.JobProcessor/Domain/FileimportPayload.cs b/Importers/Rhino/Speckle.Importers.JobProcessor/Domain/FileimportPayload.cs
index b347b1d4a..58b41eaf5 100644
--- a/Importers/Rhino/Speckle.Importers.JobProcessor/Domain/FileimportPayload.cs
+++ b/Importers/Rhino/Speckle.Importers.JobProcessor/Domain/FileimportPayload.cs
@@ -1,4 +1,6 @@
-namespace Speckle.Importers.JobProcessor.Domain;
+using System.Text.Json.Serialization;
+
+namespace Speckle.Importers.JobProcessor.Domain;
///
/// Payload for the fileimport job
@@ -17,4 +19,13 @@ internal sealed class FileimportPayload
public required Uri ServerUrl { get; init; }
public required int PayloadVersion { get; init; }
public required int TimeOutSeconds { get; init; }
+
+ [JsonPropertyName("_traceContext")]
+ public TraceContext? TraceContext { get; init; }
+}
+
+public sealed class TraceContext
+{
+ [JsonPropertyName("traceparent")]
+ public string? TraceParent { get; init; }
}
diff --git a/Importers/Rhino/Speckle.Importers.JobProcessor/JobHandlers/IPCModels.cs b/Importers/Rhino/Speckle.Importers.JobProcessor/JobHandlers/IPCModels.cs
index 0aa777426..2f93f65f6 100644
--- a/Importers/Rhino/Speckle.Importers.JobProcessor/JobHandlers/IPCModels.cs
+++ b/Importers/Rhino/Speckle.Importers.JobProcessor/JobHandlers/IPCModels.cs
@@ -12,6 +12,7 @@ internal readonly struct ImporterArgs
public required string BlobId { get; init; }
public required int Attempt { get; init; }
public required string ResultsPath { get; init; }
+ public required string? TraceContext { get; init; }
public required Project Project { get; init; }
public required ModelIngestion Ingestion { get; init; }
public required Account Account { get; init; }
diff --git a/Importers/Rhino/Speckle.Importers.JobProcessor/JobHandlers/RhinoJobHandler.cs b/Importers/Rhino/Speckle.Importers.JobProcessor/JobHandlers/RhinoJobHandler.cs
index 995e1634b..30eaf02da 100644
--- a/Importers/Rhino/Speckle.Importers.JobProcessor/JobHandlers/RhinoJobHandler.cs
+++ b/Importers/Rhino/Speckle.Importers.JobProcessor/JobHandlers/RhinoJobHandler.cs
@@ -10,6 +10,7 @@ using Speckle.Sdk.Api;
using Speckle.Sdk.Api.GraphQL.Inputs;
using Speckle.Sdk.Api.GraphQL.Models;
using Speckle.Sdk.Common;
+using Speckle.Sdk.Logging;
using JsonSerializer = System.Text.Json.JsonSerializer;
namespace Speckle.Importers.JobProcessor.JobHandlers;
@@ -17,7 +18,8 @@ namespace Speckle.Importers.JobProcessor.JobHandlers;
internal sealed class RhinoJobHandler(
ILogger logger,
ImportJobFileDownloader fileDownloader,
- ISpeckleApplication application
+ ISpeckleApplication application,
+ ISdkActivityFactory activityFactory
) : IJobHandler
{
private readonly JsonSerializerSettings _settings =
@@ -50,21 +52,27 @@ internal sealed class RhinoJobHandler(
),
cancellationToken
);
+ string resultsPath = $"{file.FileInfo.DirectoryName}/results.json";
- var importerArgs = new ImporterArgs
+ using (var activity = activityFactory.Start("Await sub-process"))
{
- FilePath = file.FileInfo.FullName,
- ResultsPath = $"{file.FileInfo.DirectoryName}/results.json",
- Account = client.Account,
- Project = project,
- Ingestion = ingestion,
- JobId = job.Id,
- BlobId = job.Payload.BlobId,
- Attempt = job.Attempt,
- HostApplication = handlerApplication,
- };
- await RunSubProcess(importerArgs, cancellationToken);
- var response = await DeserializeResponse(importerArgs.ResultsPath, cancellationToken);
+ var importerArgs = new ImporterArgs
+ {
+ FilePath = file.FileInfo.FullName,
+ ResultsPath = resultsPath,
+ TraceContext = $"00-{activity?.TraceId}-{activity?.SpanId}-01",
+ Account = client.Account,
+ Project = project,
+ Ingestion = ingestion,
+ JobId = job.Id,
+ BlobId = job.Payload.BlobId,
+ Attempt = job.Attempt,
+ HostApplication = handlerApplication,
+ };
+ await RunSubProcess(importerArgs, cancellationToken);
+ }
+
+ var response = await DeserializeResponse(resultsPath, cancellationToken);
if (response.RootObjectId is null)
{
@@ -94,7 +102,12 @@ internal sealed class RhinoJobHandler(
var processStart = new ProcessStartInfo()
{
FileName = $"{path}/Speckle.Importers.Rhino.exe",
- Environment = { },
+ Environment =
+ {
+ ["DOTNET_ENVIRONMENT"] = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT"),
+ ["SEQ_API_KEY"] = Environment.GetEnvironmentVariable("SEQ_API_KEY"),
+ ["SPECKLE_COLLECTOR_API_TOKEN"] = Environment.GetEnvironmentVariable("SPECKLE_COLLECTOR_API_TOKEN"),
+ },
RedirectStandardError = true,
RedirectStandardOutput = true,
UseShellExecute = false,
diff --git a/Importers/Rhino/Speckle.Importers.JobProcessor/JobProcessor.cs b/Importers/Rhino/Speckle.Importers.JobProcessor/JobProcessor.cs
index 2c31992d7..453ec4d4a 100644
--- a/Importers/Rhino/Speckle.Importers.JobProcessor/JobProcessor.cs
+++ b/Importers/Rhino/Speckle.Importers.JobProcessor/JobProcessor.cs
@@ -71,13 +71,16 @@ internal sealed class JobProcessorInstance(
job.RemainingComputeBudgetSeconds
);
- using var activity = activityFactory.Start();
+ using var activity = job.Payload.TraceContext?.TraceParent is not null
+ ? activityFactory.StartRemote(job.Payload.TraceContext.TraceParent, SdkActivityKind.Consumer, "Picked up a job")
+ : activityFactory.Start("Picked up a job", SdkActivityKind.Consumer);
+
using var scopeJobId = ActivityScope.SetTag("jobId", job.Id);
using var scopeJobType = ActivityScope.SetTag("jobType", job.Payload.JobType);
using var scopeAttempt = ActivityScope.SetTag("job.attempt", job.Attempt.ToString());
using var scopeServerUrl = ActivityScope.SetTag("serverUrl", job.Payload.ServerUrl.ToString());
using var scopeProjectId = ActivityScope.SetTag("projectId", job.Payload.ProjectId);
- using var scopeModelIngestionId = ActivityScope.SetTag("modelIngestionId", job.Payload.ModelIngestionId);
+ using var scopeModelIngestionId = ActivityScope.SetTag("modelIngestion.Id", job.Payload.ModelIngestionId);
using var scopeBlobId = ActivityScope.SetTag("blobId", job.Payload.BlobId);
using var scopeFileType = ActivityScope.SetTag("fileType", job.Payload.FileType);
@@ -96,27 +99,6 @@ internal sealed class JobProcessorInstance(
}
}
- private async Task ReportSuccess(
- FileimportJob job,
- string rootObjectId,
- IClient client,
- double elapsedSeconds,
- CancellationToken cancellationToken
- )
- {
- string versionId = await client.Ingestion.Complete(
- new(job.Payload.ModelIngestionId, job.Payload.ProjectId, rootObjectId, null),
- cancellationToken
- );
- logger.LogInformation(
- "Attempt {Attempt} of {JobId} has succeeded creating {VersionId} after {ElapsedSeconds}",
- job.Attempt,
- job.Id,
- versionId,
- elapsedSeconds
- );
- }
-
private async Task ReportCancelled(FileimportJob job, IClient client, Exception ex, double elapsedSeconds)
{
await client.Ingestion.FailWithCancel(
@@ -186,11 +168,9 @@ internal sealed class JobProcessorInstance(
throw new MaxAttemptsExceededException("Unhandled error silently failed the job multiple times");
}
- string rootObjectId = await ExecuteJobWithTimeout(job, speckleClient, serviceCancellationToken);
+ await ExecuteJobWithTimeout(job, speckleClient, serviceCancellationToken);
totalElapsedSeconds = stopwatch.Elapsed.TotalSeconds;
- await ReportSuccess(job, rootObjectId, speckleClient, totalElapsedSeconds, serviceCancellationToken);
-
activity?.SetStatus(SdkActivityStatusCode.Ok);
}
catch (Exception ex)
diff --git a/Importers/Rhino/Speckle.Importers.JobProcessor/Program.cs b/Importers/Rhino/Speckle.Importers.JobProcessor/Program.cs
index 49cb6ffc5..a5ca899f7 100644
--- a/Importers/Rhino/Speckle.Importers.JobProcessor/Program.cs
+++ b/Importers/Rhino/Speckle.Importers.JobProcessor/Program.cs
@@ -15,17 +15,17 @@ public static class Program
// Dapper doesn't understand how to handle JSON deserialization, so we need to tell it what types can be deserialzied
SqlMapper.AddTypeHandler(new JsonHandler());
- var host = ConfigureAppHost(args);
+ using var loggerDisposable = ConfigureAppHost(args, out IHost host);
await host.RunAsync();
}
- private static IHost ConfigureAppHost(string[] args)
+ private static IDisposable ConfigureAppHost(string[] args, out IHost host)
{
// DI setup
var builder = Host.CreateApplicationBuilder(args);
- builder.Services.AddJobProcessor();
+ var loggingDisposable = builder.Services.AddJobProcessor();
builder.Services.AddWindowsService();
builder.Services.AddTransient();
@@ -35,6 +35,7 @@ public static class Program
settings.Filter = (_, level) => level >= LogLevel.Information;
});
- return builder.Build();
+ host = builder.Build();
+ return loggingDisposable;
}
}
diff --git a/Importers/Rhino/Speckle.Importers.JobProcessor/ServiceRegistration.cs b/Importers/Rhino/Speckle.Importers.JobProcessor/ServiceRegistration.cs
index c4e4cadd0..2dd154e4b 100644
--- a/Importers/Rhino/Speckle.Importers.JobProcessor/ServiceRegistration.cs
+++ b/Importers/Rhino/Speckle.Importers.JobProcessor/ServiceRegistration.cs
@@ -7,6 +7,9 @@ using Speckle.Importers.JobProcessor.Blobs;
using Speckle.Importers.JobProcessor.JobQueue;
using Speckle.Objects.Geometry;
using Speckle.Sdk;
+#if !DEBUG && !LOCAL
+using Speckle.Sdk.Common;
+#endif
namespace Speckle.Importers.JobProcessor;
@@ -15,7 +18,7 @@ internal static class ServiceRegistration
private static readonly Application s_application = new(".NET File Import Job Processor", "jobprocessor");
private const HostAppVersion HOST_APP_VERSION = HostAppVersion.v3;
- public static IServiceCollection AddJobProcessor(this IServiceCollection serviceCollection)
+ public static IDisposable AddJobProcessor(this IServiceCollection serviceCollection)
{
var assemblyVersion = Assembly.GetExecutingAssembly().GetVersion();
@@ -26,17 +29,18 @@ internal static class ServiceRegistration
typeof(Point).Assembly
);
- serviceCollection.AddLoggingConfig();
+ var loggingDisposable = serviceCollection.AddLoggingConfig();
serviceCollection.AddTransient();
serviceCollection.AddTransient();
serviceCollection.AddHostedService();
- return serviceCollection;
+ return loggingDisposable;
}
- private static void AddLoggingConfig(this IServiceCollection serviceCollection)
+ private static IDisposable AddLoggingConfig(this IServiceCollection serviceCollection)
{
- serviceCollection.AddSeqLogging(
+ return serviceCollection.AddOpenTelemetry(
+ "Speckle.Importers.JobProcessor",
s_application,
HOST_APP_VERSION,
#if DEBUG || LOCAL
@@ -51,7 +55,23 @@ internal static class ServiceRegistration
[
new(
Endpoint: new Uri("https://seq.speckle.systems/ingest/otlp/v1/logs"),
- Headers: new() { { "X-Seq-ApiKey", "zG4cU1MbOhMD699iGlAq" } }
+ Headers: new()
+ {
+ // We're using a different token than connectors for seq because we want to beable to
+ // trust the client's timestamps (rather than use the server's timestamps) for better tracing
+ // This setting has more opportunity for abuse, so we're keeping it secret, unlike the connectors token.
+ { "X-Seq-ApiKey", Environment.GetEnvironmentVariable("SEQ_API_KEY").NotNullOrWhiteSpace() }
+ }
+ ),
+ new(
+ Endpoint: new Uri("https://collector.speckle.dev/v1/logs"),
+ Headers: new()
+ {
+ {
+ "authorization",
+ Environment.GetEnvironmentVariable("SPECKLE_COLLECTOR_API_TOKEN").NotNullOrWhiteSpace()
+ }
+ }
)
],
MinimumLevel: SpeckleLogLevel.Information
@@ -62,7 +82,20 @@ internal static class ServiceRegistration
[
new(
Endpoint: new Uri("https://seq.speckle.systems/ingest/otlp/v1/traces"),
- Headers: new() { { "X-Seq-ApiKey", "zG4cU1MbOhMD699iGlAq" } }
+ Headers: new()
+ {
+ { "X-Seq-ApiKey", Environment.GetEnvironmentVariable("SEQ_API_KEY").NotNullOrWhiteSpace() }
+ }
+ ),
+ new(
+ Endpoint: new Uri("https://collector.speckle.dev/v1/traces"),
+ Headers: new()
+ {
+ {
+ "authorization",
+ Environment.GetEnvironmentVariable("SPECKLE_COLLECTOR_API_TOKEN").NotNullOrWhiteSpace()
+ }
+ }
)
]
),
diff --git a/Importers/Rhino/Speckle.Importers.JobProcessor/packages.lock.json b/Importers/Rhino/Speckle.Importers.JobProcessor/packages.lock.json
index f76013a38..a5cc59d02 100644
--- a/Importers/Rhino/Speckle.Importers.JobProcessor/packages.lock.json
+++ b/Importers/Rhino/Speckle.Importers.JobProcessor/packages.lock.json
@@ -40,9 +40,9 @@
},
"Npgsql": {
"type": "Direct",
- "requested": "[9.0.3, )",
- "resolved": "9.0.3",
- "contentHash": "tPvY61CxOAWxNsKLEBg+oR646X4Bc8UmyQ/tJszL/7mEmIXQnnBhVJZrZEEUv0Bstu0mEsHZD5At3EO8zQRAYw==",
+ "requested": "[9.0.4, )",
+ "resolved": "9.0.4",
+ "contentHash": "68BASXH0FAEuL/J4J0eRfYC8/3vzqQTmoW8zDzNf0JgaVxc7LZeEkS6jaG0ib3voFLxY5ZiCwJG+uQM+mzuu0Q==",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "8.0.2"
}
@@ -413,8 +413,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -422,13 +422,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -513,7 +513,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -545,7 +545,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.converters.rhino8": {
@@ -622,11 +622,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Importers/Rhino/Speckle.Importers.Rhino/Internal/FileTypeConfig/DwgConfig.cs b/Importers/Rhino/Speckle.Importers.Rhino/Internal/FileTypeConfig/DwgConfig.cs
new file mode 100644
index 000000000..45e8b4337
--- /dev/null
+++ b/Importers/Rhino/Speckle.Importers.Rhino/Internal/FileTypeConfig/DwgConfig.cs
@@ -0,0 +1,22 @@
+using Rhino;
+using Rhino.FileIO;
+using Speckle.Sdk;
+
+namespace Speckle.Importers.Rhino.Internal.FileTypeConfig;
+
+internal sealed class DwgConfig : IFileTypeConfig
+{
+ private readonly FileDwgReadOptions _readOptions = new() { SetLayerMaterialToLayerColor = true };
+
+ public RhinoDoc OpenInHeadlessDocument(string filePath)
+ {
+ RhinoDoc? doc = RhinoDoc.OpenHeadless(filePath, _readOptions.ToDictionary());
+ if (doc is null)
+ {
+ throw new SpeckleException("Rhino could not open this file");
+ }
+ return doc;
+ }
+
+ public void Dispose() { }
+}
diff --git a/Importers/Rhino/Speckle.Importers.Rhino/Internal/IPCModels.cs b/Importers/Rhino/Speckle.Importers.Rhino/Internal/IPCModels.cs
index 91e3bce1e..82c792521 100644
--- a/Importers/Rhino/Speckle.Importers.Rhino/Internal/IPCModels.cs
+++ b/Importers/Rhino/Speckle.Importers.Rhino/Internal/IPCModels.cs
@@ -12,6 +12,7 @@ internal readonly struct ImporterArgs
public required string BlobId { get; init; }
public required int Attempt { get; init; }
public required string ResultsPath { get; init; }
+ public required string? TraceContext { get; init; }
public required Project Project { get; init; }
public required ModelIngestion Ingestion { get; init; }
public required Account Account { get; init; }
diff --git a/Importers/Rhino/Speckle.Importers.Rhino/Internal/ImporterInstance.cs b/Importers/Rhino/Speckle.Importers.Rhino/Internal/ImporterInstance.cs
index 547b27bff..ef826299e 100644
--- a/Importers/Rhino/Speckle.Importers.Rhino/Internal/ImporterInstance.cs
+++ b/Importers/Rhino/Speckle.Importers.Rhino/Internal/ImporterInstance.cs
@@ -2,60 +2,99 @@ using System.Diagnostics.Contracts;
using Microsoft.Extensions.Logging;
using Rhino;
using Rhino.Runtime.InProcess;
+using Speckle.Connectors.Common.Builders;
using Speckle.Connectors.Common.Extensions;
using Speckle.Connectors.Logging;
using Speckle.Importers.Rhino.Internal.FileTypeConfig;
using Speckle.Sdk.Api;
-using Speckle.Sdk.Serialisation.V2.Send;
+using Speckle.Sdk.Logging;
namespace Speckle.Importers.Rhino.Internal;
-internal sealed class ImporterInstance(
- ImporterArgs args,
- Sender sender,
- IClient speckleClient,
- ILogger logger
-) : IDisposable
+internal sealed class ImporterInstance : IDisposable
{
private readonly RhinoCore _rhinoInstance = new(["/netcore-8"], WindowStyle.NoWindow);
- private readonly RhinoDoc _rhinoDoc = OpenDocument(args, logger);
+ private readonly RhinoDoc _rhinoDoc;
- private readonly IReadOnlyList _scopes =
- [
- ActivityScope.SetTag("jobId", args.JobId),
- ActivityScope.SetTag("job.attempt", args.Attempt.ToString()),
- // ActivityScope.SetTag("jobType", args.JobType),
- ActivityScope.SetTag("serverUrl", args.Account.serverInfo.url),
- ActivityScope.SetTag("projectId", args.Project.id),
- ActivityScope.SetTag("ingestionId", args.Ingestion.id),
- ActivityScope.SetTag("modelId", args.Ingestion.modelId),
- ActivityScope.SetTag("blobId", args.BlobId),
- ActivityScope.SetTag("fileType", Path.GetExtension(args.FilePath).TrimStart('.')),
- UserActivityScope.AddUserScope(args.Account),
- ];
+ private readonly IReadOnlyList _scopes;
- public async Task RunRhinoImport(CancellationToken cancellationToken)
+ private readonly ImporterArgs _args;
+ private readonly Sender _sender;
+ private readonly IClient _speckleClient;
+ private readonly ILogger _logger;
+ private readonly ISdkActivityFactory _activityFactory;
+
+ public ImporterInstance(
+ ImporterArgs args,
+ Sender sender,
+ IClient speckleClient,
+ ILogger logger,
+ ISdkActivityFactory activityFactory
+ )
{
+ _args = args;
+ _sender = sender;
+ _speckleClient = speckleClient;
+ _logger = logger;
+ _activityFactory = activityFactory;
+ _rhinoDoc = OpenDocument();
+ _scopes =
+ [
+ ActivityScope.SetTag("jobId", args.JobId),
+ ActivityScope.SetTag("job.attempt", args.Attempt.ToString()),
+ // ActivityScope.SetTag("jobType", args.JobType),
+ ActivityScope.SetTag("serverUrl", new Uri(args.Account.serverInfo.url).ToString()),
+ ActivityScope.SetTag("projectId", args.Project.id),
+ ActivityScope.SetTag("modelIngestion.id", args.Ingestion.id),
+ ActivityScope.SetTag("modelId", args.Ingestion.modelId),
+ ActivityScope.SetTag("blobId", args.BlobId),
+ ActivityScope.SetTag("fileType", Path.GetExtension(args.FilePath).TrimStart('.')),
+ UserActivityScope.AddUserScope(args.Account),
+ ];
+ }
+
+ public async Task RunRhinoImport(CancellationToken cancellationToken)
+ {
+ using var activity = _activityFactory.Start();
try
{
RhinoDoc.ActiveDoc = _rhinoDoc;
- var results = await sender
- .Send(args.Project, args.Ingestion, speckleClient, cancellationToken)
+ var results = await _sender
+ .Send(_args.Project, _args.Ingestion, _speckleClient, cancellationToken)
.ConfigureAwait(false);
+ activity?.SetStatus(SdkActivityStatusCode.Ok);
return results;
}
+ catch (Exception ex)
+ {
+ activity?.RecordException(ex);
+ activity?.SetStatus(SdkActivityStatusCode.Error);
+ throw;
+ }
finally
{
RhinoDoc.ActiveDoc = null;
}
}
- private static RhinoDoc OpenDocument(ImporterArgs args, ILogger logger)
+ private RhinoDoc OpenDocument()
{
- using var config = GetConfig(Path.GetExtension(args.FilePath));
- logger.LogInformation("Opening file {FilePath}", args.FilePath);
- return config.OpenInHeadlessDocument(args.FilePath);
+ using var activity = _activityFactory.Start();
+ try
+ {
+ using var config = GetConfig(Path.GetExtension(_args.FilePath));
+ RhinoDoc openedDoc = config.OpenInHeadlessDocument(_args.FilePath);
+
+ activity?.SetStatus(SdkActivityStatusCode.Ok);
+ return openedDoc;
+ }
+ catch (Exception ex)
+ {
+ activity?.RecordException(ex);
+ activity?.SetStatus(SdkActivityStatusCode.Error);
+ throw;
+ }
}
[Pure]
@@ -66,6 +105,8 @@ internal sealed class ImporterInstance(
".obj" => new ObjConfig(),
".dgn" => new DgnConfig(),
".fbx" => new FbxConfig(),
+ ".dwg" => new DwgConfig(),
+ ".dxf" => new DwgConfig(),
_ => new DefaultConfig(),
};
@@ -80,6 +121,6 @@ internal sealed class ImporterInstance(
{
scope.Dispose();
}
- speckleClient.Dispose();
+ _speckleClient.Dispose();
}
}
diff --git a/Importers/Rhino/Speckle.Importers.Rhino/Internal/ImporterInstanceFactory.cs b/Importers/Rhino/Speckle.Importers.Rhino/Internal/ImporterInstanceFactory.cs
index e5d2aa600..59ffd2619 100644
--- a/Importers/Rhino/Speckle.Importers.Rhino/Internal/ImporterInstanceFactory.cs
+++ b/Importers/Rhino/Speckle.Importers.Rhino/Internal/ImporterInstanceFactory.cs
@@ -1,17 +1,19 @@
using Microsoft.Extensions.Logging;
using Speckle.Sdk.Api;
+using Speckle.Sdk.Logging;
namespace Speckle.Importers.Rhino.Internal;
internal sealed class ImporterInstanceFactory(
Sender sender,
IClientFactory clientFactory,
- ILogger logger
+ ILogger logger,
+ ISdkActivityFactory activityFactory
)
{
public ImporterInstance Create(ImporterArgs args)
{
var speckleClient = clientFactory.Create(args.Account);
- return new(args, sender, speckleClient, logger);
+ return new(args, sender, speckleClient, logger, activityFactory);
}
}
diff --git a/Importers/Rhino/Speckle.Importers.Rhino/Internal/Sender.cs b/Importers/Rhino/Speckle.Importers.Rhino/Internal/Sender.cs
index 136c711d3..638ff513f 100644
--- a/Importers/Rhino/Speckle.Importers.Rhino/Internal/Sender.cs
+++ b/Importers/Rhino/Speckle.Importers.Rhino/Internal/Sender.cs
@@ -3,8 +3,7 @@ using Microsoft.Extensions.Logging;
using Rhino;
using Rhino.DocObjects;
using Speckle.Connectors.Common.Analytics;
-using Speckle.Connectors.Common.Operations;
-using Speckle.Connectors.Common.Operations.Send;
+using Speckle.Connectors.Common.Builders;
using Speckle.Converters.Common;
using Speckle.Converters.Rhino;
using Speckle.Sdk;
@@ -12,7 +11,8 @@ using Speckle.Sdk.Api;
using Speckle.Sdk.Api.GraphQL.Models;
using Speckle.Sdk.Credentials;
using Speckle.Sdk.Logging;
-using Speckle.Sdk.Serialisation.V2.Send;
+using Speckle.Sdk.Pipelines.Progress;
+using Speckle.Sdk.Pipelines.Send;
namespace Speckle.Importers.Rhino.Internal;
@@ -22,10 +22,11 @@ internal sealed class Sender(
IRhinoConversionSettingsFactory rhinoConversionSettingsFactory,
IMixPanelManager mixpanel,
IIngestionProgressManagerFactory progressManagerFactory,
+ ISendPipelineFactory sendPipelineFactory,
ILogger logger
)
{
- public async Task Send(
+ public async Task Send(
Project project,
ModelIngestion ingestion,
IClient speckleClient,
@@ -35,7 +36,6 @@ internal sealed class Sender(
var progressManager = progressManagerFactory.CreateInstance(
speckleClient,
ingestion,
- project.id,
TimeSpan.FromSeconds(1.5),
cancellationToken
);
@@ -56,20 +56,30 @@ internal sealed class Sender(
throw new SpeckleException("There are no objects found in the file");
}
- var operation = scope.ServiceProvider.GetRequiredService>();
- var buildResults = await operation.Build(rhinoObjects, project.id, progressManager, cancellationToken);
- var results = await operation.SendObjects(
- buildResults.RootObject,
+ var rootContinuousTraversalBuilder = scope.ServiceProvider.GetRequiredService<
+ IRootContinuousTraversalBuilder
+ >();
+
+ var sendPipeline = sendPipelineFactory.CreateInstance(
project.id,
+ ingestion.id,
speckleClient.Account,
+ new RenderedStreamProgress(progressManager),
+ cancellationToken
+ );
+ var buildResult = await rootContinuousTraversalBuilder.Build(
+ rhinoObjects,
+ project.id,
+ sendPipeline,
progressManager,
cancellationToken
);
+ buildResult.RootObject["version"] = 3;
await TrackSendMetrics(project, speckleClient.Account);
- logger.LogInformation("Root: {RootId}", results.RootId);
- return results;
+ logger.LogInformation("Root: {RootId}", buildResult.RootObject.id);
+ return buildResult;
}
private async Task TrackSendMetrics(Project project, Account account)
diff --git a/Importers/Rhino/Speckle.Importers.Rhino/Internal/ServiceRegistration.cs b/Importers/Rhino/Speckle.Importers.Rhino/Internal/ServiceRegistration.cs
index 7f99d6aa6..00b47ce2c 100644
--- a/Importers/Rhino/Speckle.Importers.Rhino/Internal/ServiceRegistration.cs
+++ b/Importers/Rhino/Speckle.Importers.Rhino/Internal/ServiceRegistration.cs
@@ -1,35 +1,120 @@
-using Microsoft.Extensions.DependencyInjection;
+using System.Reflection;
+using Microsoft.Extensions.DependencyInjection;
using Speckle.Connectors.Common;
-using Speckle.Connectors.Common.Operations.Send;
+using Speckle.Connectors.Common.Common;
using Speckle.Connectors.Common.Threading;
+using Speckle.Connectors.Logging;
using Speckle.Connectors.Rhino.DependencyInjection;
using Speckle.Converters.Rhino;
+using Speckle.Objects.Geometry;
using Speckle.Sdk;
using Speckle.Sdk.SQLite;
+#if !DEBUG && !LOCAL
+using Speckle.Sdk.Common;
+#endif
namespace Speckle.Importers.Rhino.Internal;
internal static class ServiceRegistration
{
- public static IServiceCollection AddRhinoImporter(this IServiceCollection services, Application applicationInfo)
- {
- services.Initialize(applicationInfo, HostAppVersion.v8);
- services.AddSingleton(applicationInfo);
+ private const HostAppVersion HOST_APP_VERSION = HostAppVersion.v3;
- services.AddRhino(false);
- services.AddRhinoConverters();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
+ public static IServiceCollection AddRhinoImporter(
+ this IServiceCollection serviceCollection,
+ Application applicationInfo
+ )
+ {
+ var assemblyVersion = Assembly.GetExecutingAssembly().GetVersion();
+
+ serviceCollection.AddSpeckleSdk(
+ applicationInfo,
+ HostApplications.GetVersion(HOST_APP_VERSION),
+ assemblyVersion,
+ typeof(Point).Assembly
+ );
+
+ serviceCollection.AddSingleton(applicationInfo);
+
+ serviceCollection.AddRhino(false);
+ serviceCollection.AddRhinoConverters();
+ serviceCollection.AddTransient();
+ serviceCollection.AddTransient();
+ serviceCollection.AddTransient();
// override default thread context
- services.AddSingleton(new ImporterThreadContext());
+ serviceCollection.AddSingleton(new ImporterThreadContext());
// override sqlite cache, since we don't want to persist to disk any object data
- services.AddTransient();
+ serviceCollection.AddTransient();
- return services;
+ return serviceCollection;
+ }
+
+ // Important to respect disposal, because disposal ensures pending messages are flushed
+ public static IDisposable AddLoggingConfig(this IServiceCollection serviceCollection, Application applicationInfo)
+ {
+ return serviceCollection.AddOpenTelemetry(
+ "Speckle.Importers.Rhino",
+ applicationInfo,
+ HOST_APP_VERSION,
+#if DEBUG || LOCAL
+ new SpeckleLogging(Console: true, File: new(), MinimumLevel: SpeckleLogLevel.Debug),
+ new SpeckleTracing(Console: false),
+ new SpeckleMetrics(Console: false)
+#else
+ new SpeckleLogging(
+ Console: true,
+ File: new(),
+ Otel:
+ [
+ new(
+ Endpoint: new Uri("https://seq.speckle.systems/ingest/otlp/v1/logs"),
+ Headers: new()
+ {
+ // We're using a different token than connectors for seq because we want to beable to
+ // trust the client's timestamps (rather than use the server's timestamps) for better tracing
+ // This setting has more opportunity for abuse, so we're keeping it secret, unlike the connectors token.
+ { "X-Seq-ApiKey", Environment.GetEnvironmentVariable("SEQ_API_KEY").NotNullOrWhiteSpace() }
+ }
+ ),
+ new(
+ Endpoint: new Uri("https://collector.speckle.dev/v1/logs"),
+ Headers: new()
+ {
+ {
+ "authorization",
+ Environment.GetEnvironmentVariable("SPECKLE_COLLECTOR_API_TOKEN").NotNullOrWhiteSpace()
+ }
+ }
+ )
+ ],
+ MinimumLevel: SpeckleLogLevel.Information
+ ),
+ new SpeckleTracing(
+ Console: false,
+ Otel:
+ [
+ new(
+ Endpoint: new Uri("https://seq.speckle.systems/ingest/otlp/v1/traces"),
+ Headers: new()
+ {
+ { "X-Seq-ApiKey", Environment.GetEnvironmentVariable("SEQ_API_KEY").NotNullOrWhiteSpace() }
+ }
+ ),
+ new(
+ Endpoint: new Uri("https://collector.speckle.dev/v1/traces"),
+ Headers: new()
+ {
+ {
+ "authorization",
+ Environment.GetEnvironmentVariable("SPECKLE_COLLECTOR_API_TOKEN").NotNullOrWhiteSpace()
+ }
+ }
+ )
+ ]
+ ),
+ null
+#endif
+ );
}
}
diff --git a/Importers/Rhino/Speckle.Importers.Rhino/Program.cs b/Importers/Rhino/Speckle.Importers.Rhino/Program.cs
index 60c47b93c..0e279712b 100644
--- a/Importers/Rhino/Speckle.Importers.Rhino/Program.cs
+++ b/Importers/Rhino/Speckle.Importers.Rhino/Program.cs
@@ -4,7 +4,9 @@ using System.Text.Json.Serialization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using RhinoInside;
+using Speckle.Connectors.Logging;
using Speckle.Importers.Rhino.Internal;
+using Speckle.Sdk.Logging;
namespace Speckle.Importers.Rhino;
@@ -22,6 +24,8 @@ public static class Program
[SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "IPC")]
public static async Task Main(string[] args)
{
+ //Thread.Sleep(10000); //For Debugging purposes, gives you enough time to attach your IDE to the running process
+
ILogger? logger = null;
ImporterInstance? importer = null;
@@ -31,11 +35,17 @@ public static class Program
var serviceCollection = new ServiceCollection();
serviceCollection.AddRhinoImporter(importerArgs.HostApplication);
+ using var otel = serviceCollection.AddLoggingConfig(importerArgs.HostApplication);
using var serviceProvider = serviceCollection.BuildServiceProvider();
logger = serviceProvider.GetRequiredService>();
TaskScheduler.UnobservedTaskException += (_, eventArgs) =>
logger.LogCritical(eventArgs.Exception, "Unobserved Task Exception");
+ ISdkActivityFactory activityFactory = serviceProvider.GetRequiredService();
+ using var activity = importerArgs.TraceContext is not null
+ ? activityFactory.StartRemote(importerArgs.TraceContext, SdkActivityKind.Consumer)
+ : activityFactory.Start();
+
var factory = serviceProvider.GetRequiredService();
// Error handling flow below here looks a bit of a mess, but we're having to navigate threading issues with rhino inside
@@ -58,7 +68,7 @@ public static class Program
try
{
var results = await importer.RunRhinoImport(CancellationToken.None).ConfigureAwait(false);
- WriteResult(new() { RootObjectId = results.RootId }, importerArgs.ResultsPath);
+ WriteResult(new() { RootObjectId = results.RootObject.id }, importerArgs.ResultsPath);
}
catch (Exception ex)
{
diff --git a/Importers/Rhino/Speckle.Importers.Rhino/Speckle.Importers.Rhino.csproj b/Importers/Rhino/Speckle.Importers.Rhino/Speckle.Importers.Rhino.csproj
index 64a83f87d..b19933521 100644
--- a/Importers/Rhino/Speckle.Importers.Rhino/Speckle.Importers.Rhino.csproj
+++ b/Importers/Rhino/Speckle.Importers.Rhino/Speckle.Importers.Rhino.csproj
@@ -8,9 +8,9 @@
-
-
-
+
+
+
diff --git a/Importers/Rhino/Speckle.Importers.Rhino/packages.lock.json b/Importers/Rhino/Speckle.Importers.Rhino/packages.lock.json
index 60c414cb9..309d86b45 100644
--- a/Importers/Rhino/Speckle.Importers.Rhino/packages.lock.json
+++ b/Importers/Rhino/Speckle.Importers.Rhino/packages.lock.json
@@ -4,11 +4,11 @@
"net8.0-windows7.0": {
"Grasshopper": {
"type": "Direct",
- "requested": "[8.25.25328.11001, )",
- "resolved": "8.25.25328.11001",
- "contentHash": "1uFL9pmgCEbYFd1b3JFGHaLEjQuRgFsiRHmP5u73mdEMdO6+5F/pNV1dQZr3YGLDovUmgrc+jmpsme7wr/J01A==",
+ "requested": "[8.28.26041.11001, )",
+ "resolved": "8.28.26041.11001",
+ "contentHash": "xlLD67F4/c5quwUrLxtAXT3M4Xam7GnhXyepC8/AblIBFcWbKEBzfOv85FlzO0ZPmDJwNjM5kRYML/sAStktZg==",
"dependencies": {
- "RhinoCommon": "[8.25.25328.11001]"
+ "RhinoCommon": "[8.28.26041.11001]"
}
},
"Microsoft.NETFramework.ReferenceAssemblies": {
@@ -48,20 +48,20 @@
},
"RhinoCommon": {
"type": "Direct",
- "requested": "[8.25.25328.11001, )",
- "resolved": "8.25.25328.11001",
- "contentHash": "PDKR9GwqyUXUkTulV4J0dzDIf/aWqSJkL7nkS8ReAx8xhnt/+RQpE8gTjOSCmkSU2tjG6WzclowbTxwMTU7VAA==",
+ "requested": "[8.28.26041.11001, )",
+ "resolved": "8.28.26041.11001",
+ "contentHash": "5mByZF+IdHvRLbYvr6Ek95Pwam6otewAyVHIGSC0sUE1+OscSpd9gbrFWnzo1arfCYmUJcUdsGhf7VayW09fQA==",
"dependencies": {
"System.Drawing.Common": "7.0.0"
}
},
"RhinoWindows": {
"type": "Direct",
- "requested": "[8.25.25328.11001, )",
- "resolved": "8.25.25328.11001",
- "contentHash": "I/+++piwtYTue+iAAQqcMF5QlontqwNnC7Leyhiv2FiF8JpAl6K44ZsJqB7ZEUC6ns0LDfa3mbFzQwUfHwYumQ==",
+ "requested": "[8.28.26041.11001, )",
+ "resolved": "8.28.26041.11001",
+ "contentHash": "7MBG231k5c0/V/USTzbXpaTCiZCECQOuB80DnpgEvvEA3r//IQQDTbrqawDYmN9BEw/FHiFn82bsf6tV+SS5Iw==",
"dependencies": {
- "RhinoCommon": "[8.25.25328.11001]"
+ "RhinoCommon": "[8.28.26041.11001]"
}
},
"Speckle.InterfaceGenerator": {
@@ -193,8 +193,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -202,13 +202,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -274,7 +274,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.dui": {
@@ -306,7 +306,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.converters.rhino8": {
@@ -356,11 +356,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Local.sln b/Local.sln
index e05884507..1ecc177f0 100644
--- a/Local.sln
+++ b/Local.sln
@@ -1,4 +1,4 @@
-Microsoft Visual Studio Solution File, Format Version 12.00
+Microsoft Visual Studio Solution File, Format Version 12.00
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{DEE5DD87-39C1-BF34-B639-A387DCCF972B}"
ProjectSection(SolutionItems) = preProject
.github\workflows\pr.yml = .github\workflows\pr.yml
@@ -309,6 +309,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Sdk", "..\speckle-s
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Sdk.Dependencies", "..\speckle-sharp-sdk\src\Speckle.Sdk.Dependencies\Speckle.Sdk.Dependencies.csproj", "{0677CA87-027F-D526-4463-3517F75B76EC}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Connectors.Plant3d2026", "Connectors\Autocad\Speckle.Connectors.Plant3d2026\Speckle.Connectors.Plant3d2026.csproj", "{B68103BE-A274-4F61-AE98-DE0B75B8BD1C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Converters.Plant3d2026", "Converters\Plant3d\Speckle.Converters.Plant3d2026\Speckle.Converters.Plant3d2026.csproj", "{AEF997CA-1413-4DF7-AFA7-AB4DC9BF92FF}"
+EndProject
+Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Speckle.Connectors.Plant3dShared", "Connectors\Autocad\Speckle.Connectors.Plant3dShared\Speckle.Connectors.Plant3dShared.shproj", "{B1C4A14C-2F4E-4C3D-9B71-A3F5D8E6C912}"
+EndProject
+Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Speckle.Converters.Plant3dShared", "Converters\Plant3d\Speckle.Converters.Plant3dShared\Speckle.Converters.Plant3dShared.shproj", "{C7E3A28D-5F91-4B6E-A8D2-3F1C9E7B4D56}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -790,6 +798,18 @@ Global
{0677CA87-027F-D526-4463-3517F75B76EC}.Local|Any CPU.Build.0 = Local|Any CPU
{0677CA87-027F-D526-4463-3517F75B76EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0677CA87-027F-D526-4463-3517F75B76EC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B68103BE-A274-4F61-AE98-DE0B75B8BD1C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B68103BE-A274-4F61-AE98-DE0B75B8BD1C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B68103BE-A274-4F61-AE98-DE0B75B8BD1C}.Local|Any CPU.ActiveCfg = Local|Any CPU
+ {B68103BE-A274-4F61-AE98-DE0B75B8BD1C}.Local|Any CPU.Build.0 = Local|Any CPU
+ {B68103BE-A274-4F61-AE98-DE0B75B8BD1C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B68103BE-A274-4F61-AE98-DE0B75B8BD1C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AEF997CA-1413-4DF7-AFA7-AB4DC9BF92FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AEF997CA-1413-4DF7-AFA7-AB4DC9BF92FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AEF997CA-1413-4DF7-AFA7-AB4DC9BF92FF}.Local|Any CPU.ActiveCfg = Local|Any CPU
+ {AEF997CA-1413-4DF7-AFA7-AB4DC9BF92FF}.Local|Any CPU.Build.0 = Local|Any CPU
+ {AEF997CA-1413-4DF7-AFA7-AB4DC9BF92FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AEF997CA-1413-4DF7-AFA7-AB4DC9BF92FF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -927,5 +947,9 @@ Global
{37C78F74-1AFB-8865-7C2A-03B6B4262134} = {FF13A09E-0E72-1904-124B-A4E979EF28D3}
{C3BD4841-7C1F-23F7-20AB-C30A678001F5} = {FF13A09E-0E72-1904-124B-A4E979EF28D3}
{02E79865-6261-CDE0-77EA-3DD2E01DACBD} = {FF13A09E-0E72-1904-124B-A4E979EF28D3}
+ {B68103BE-A274-4F61-AE98-DE0B75B8BD1C} = {D3670C11-52FA-1950-6D7E-27C5DEA68A33}
+ {AEF997CA-1413-4DF7-AFA7-AB4DC9BF92FF} = {D3670C11-52FA-1950-6D7E-27C5DEA68A33}
+ {B1C4A14C-2F4E-4C3D-9B71-A3F5D8E6C912} = {A97EFA6B-D703-EF29-A34D-BAD7BA42B5BE}
+ {C7E3A28D-5F91-4B6E-A8D2-3F1C9E7B4D56} = {A97EFA6B-D703-EF29-A34D-BAD7BA42B5BE}
EndGlobalSection
EndGlobal
diff --git a/Local.slnx b/Local.slnx
index 7dbcf2058..93c389168 100644
--- a/Local.slnx
+++ b/Local.slnx
@@ -49,14 +49,18 @@
+
+
+
+
@@ -151,7 +155,7 @@
-
+
@@ -180,7 +184,7 @@
-
+
diff --git a/Sdk/Speckle.Connectors.Common.Tests/Operations/ReceiveOperationTests.cs b/Sdk/Speckle.Connectors.Common.Tests/Operations/ReceiveOperationTests.cs
index 224bdae55..4ac7def16 100644
--- a/Sdk/Speckle.Connectors.Common.Tests/Operations/ReceiveOperationTests.cs
+++ b/Sdk/Speckle.Connectors.Common.Tests/Operations/ReceiveOperationTests.cs
@@ -12,6 +12,7 @@ using Speckle.Sdk.Api.GraphQL.Models;
using Speckle.Sdk.Credentials;
using Speckle.Sdk.Logging;
using Speckle.Sdk.Models;
+using Speckle.Sdk.Pipelines.Progress;
using Speckle.Testing;
namespace Speckle.Connectors.Common.Tests.Operations;
diff --git a/Sdk/Speckle.Connectors.Common.Tests/Operations/ReceiveProgressTests.cs b/Sdk/Speckle.Connectors.Common.Tests/Operations/ReceiveProgressTests.cs
index 414e5b235..3b98b54eb 100644
--- a/Sdk/Speckle.Connectors.Common.Tests/Operations/ReceiveProgressTests.cs
+++ b/Sdk/Speckle.Connectors.Common.Tests/Operations/ReceiveProgressTests.cs
@@ -1,6 +1,7 @@
using Moq;
using NUnit.Framework;
using Speckle.Connectors.Common.Operations;
+using Speckle.Sdk.Pipelines.Progress;
using Speckle.Sdk.Transports;
using Speckle.Testing;
diff --git a/Sdk/Speckle.Connectors.Common.Tests/Operations/SendProgressTests.cs b/Sdk/Speckle.Connectors.Common.Tests/Operations/SendProgressTests.cs
index 5c10f566e..53117b6ac 100644
--- a/Sdk/Speckle.Connectors.Common.Tests/Operations/SendProgressTests.cs
+++ b/Sdk/Speckle.Connectors.Common.Tests/Operations/SendProgressTests.cs
@@ -1,6 +1,7 @@
using Moq;
using NUnit.Framework;
using Speckle.Connectors.Common.Operations;
+using Speckle.Sdk.Pipelines.Progress;
using Speckle.Sdk.Transports;
using Speckle.Testing;
diff --git a/Sdk/Speckle.Connectors.Common.Tests/packages.lock.json b/Sdk/Speckle.Connectors.Common.Tests/packages.lock.json
index c445887e4..4c31c1792 100644
--- a/Sdk/Speckle.Connectors.Common.Tests/packages.lock.json
+++ b/Sdk/Speckle.Connectors.Common.Tests/packages.lock.json
@@ -232,8 +232,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -241,13 +241,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -328,7 +328,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.connectors.logging": {
@@ -338,7 +338,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.testing": {
@@ -347,7 +347,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Moq": "[4.20.70, )",
"NUnit": "[4.1.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.Logging": {
@@ -391,11 +391,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Sdk/Speckle.Connectors.Common/Builders/IHostObjectBuilder.cs b/Sdk/Speckle.Connectors.Common/Builders/IHostObjectBuilder.cs
index aa19cc90f..b558410f2 100644
--- a/Sdk/Speckle.Connectors.Common/Builders/IHostObjectBuilder.cs
+++ b/Sdk/Speckle.Connectors.Common/Builders/IHostObjectBuilder.cs
@@ -1,6 +1,6 @@
using Speckle.Connectors.Common.Conversion;
-using Speckle.Connectors.Common.Operations;
using Speckle.Sdk.Models;
+using Speckle.Sdk.Pipelines.Progress;
namespace Speckle.Connectors.Common.Builders;
diff --git a/Sdk/Speckle.Connectors.Common/Builders/IRootObjectBuilder.cs b/Sdk/Speckle.Connectors.Common/Builders/IRootObjectBuilder.cs
index 1699bc758..e5bc0a3b7 100644
--- a/Sdk/Speckle.Connectors.Common/Builders/IRootObjectBuilder.cs
+++ b/Sdk/Speckle.Connectors.Common/Builders/IRootObjectBuilder.cs
@@ -1,6 +1,7 @@
using Speckle.Connectors.Common.Conversion;
-using Speckle.Connectors.Common.Operations;
using Speckle.Sdk.Models;
+using Speckle.Sdk.Pipelines.Progress;
+using Speckle.Sdk.Pipelines.Send;
namespace Speckle.Connectors.Common.Builders;
@@ -14,4 +15,15 @@ public interface IRootObjectBuilder
);
}
+public interface IRootContinuousTraversalBuilder
+{
+ public Task Build(
+ IReadOnlyList objects,
+ string projectId,
+ SendPipeline sendPipeline,
+ IProgress onOperationProgressed,
+ CancellationToken cancellationToken
+ );
+}
+
public record RootObjectBuilderResult(Base RootObject, IReadOnlyList ConversionResults);
diff --git a/Sdk/Speckle.Connectors.Common/Caching/ISendConversionCache.cs b/Sdk/Speckle.Connectors.Common/Caching/ISendConversionCache.cs
index 4d396b403..afd1210b0 100644
--- a/Sdk/Speckle.Connectors.Common/Caching/ISendConversionCache.cs
+++ b/Sdk/Speckle.Connectors.Common/Caching/ISendConversionCache.cs
@@ -15,6 +15,8 @@ public interface ISendConversionCache
{
void StoreSendResult(string projectId, IReadOnlyDictionary convertedReferences);
+ void AppendSendResult(string projectId, string applicationId, ObjectReference convertedReference);
+
///
/// Call this method whenever you need to invalidate a set of objects that have changed in the host app.
/// Failure to do so correctly will result in cache poisoning and incorrect version creation (stale objects).
diff --git a/Sdk/Speckle.Connectors.Common/Caching/NullSendConversionCache.cs b/Sdk/Speckle.Connectors.Common/Caching/NullSendConversionCache.cs
index 1ae66b67b..845055d5e 100644
--- a/Sdk/Speckle.Connectors.Common/Caching/NullSendConversionCache.cs
+++ b/Sdk/Speckle.Connectors.Common/Caching/NullSendConversionCache.cs
@@ -13,6 +13,8 @@ public class NullSendConversionCache : ISendConversionCache
public void EvictObjects(IEnumerable objectIds) { }
+ public void AppendSendResult(string projectId, string applicationId, ObjectReference convertedReference) { }
+
public void ClearCache() { }
public bool TryGetValue(
diff --git a/Sdk/Speckle.Connectors.Common/Caching/SendConversionCache.cs b/Sdk/Speckle.Connectors.Common/Caching/SendConversionCache.cs
index 521fe2bf1..d2a74e5f4 100644
--- a/Sdk/Speckle.Connectors.Common/Caching/SendConversionCache.cs
+++ b/Sdk/Speckle.Connectors.Common/Caching/SendConversionCache.cs
@@ -17,6 +17,11 @@ public class SendConversionCache : ISendConversionCache
}
}
+ public void AppendSendResult(string projectId, string applicationId, ObjectReference convertedReference)
+ {
+ Cache[(applicationId, projectId)] = convertedReference;
+ }
+
///
public void EvictObjects(IEnumerable objectIds) =>
Cache = Cache
diff --git a/Sdk/Speckle.Connectors.Common/Connector.cs b/Sdk/Speckle.Connectors.Common/Connector.cs
index 9d5b878e9..e45908635 100644
--- a/Sdk/Speckle.Connectors.Common/Connector.cs
+++ b/Sdk/Speckle.Connectors.Common/Connector.cs
@@ -37,7 +37,8 @@ public static class Connector
typeof(Point).Assembly
);
- return serviceCollection.AddSeqLogging(
+ return serviceCollection.AddOpenTelemetry(
+ "Connector",
application,
version,
#if DEBUG || LOCAL
@@ -72,8 +73,9 @@ public static class Connector
);
}
- public static IDisposable AddSeqLogging(
+ public static IDisposable AddOpenTelemetry(
this IServiceCollection serviceCollection,
+ string serviceName,
Application application,
HostAppVersion version,
SpeckleLogging loggingConfig,
@@ -83,6 +85,7 @@ public static class Connector
{
var assemblyVersion = Assembly.GetExecutingAssembly().GetVersion();
var (logging, tracing, metrics) = Observability.Initialize(
+ serviceName,
application.Name + " " + HostApplications.GetVersion(version),
application.Slug,
assemblyVersion,
diff --git a/Sdk/Speckle.Connectors.Common/Conversion/ReportResult.cs b/Sdk/Speckle.Connectors.Common/Conversion/ReportResult.cs
index c27e3bba8..835982cb0 100644
--- a/Sdk/Speckle.Connectors.Common/Conversion/ReportResult.cs
+++ b/Sdk/Speckle.Connectors.Common/Conversion/ReportResult.cs
@@ -1,3 +1,4 @@
+using Speckle.Newtonsoft.Json;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;
@@ -34,8 +35,12 @@ public sealed class SendConversionResult : ConversionResult
SourceType = sourceType;
ResultId = result?.id;
ResultType = result?.speckle_type;
+ Result = result;
Error = FormatError(exception);
}
+
+ [JsonIgnore]
+ public Base? Result { get; }
}
// HACK: I've unsealed this for Grasshopper, non-ideal. Should be discussed and a better pattern may be implemented.
@@ -63,7 +68,6 @@ public class ReceiveConversionResult : ConversionResult
/// send conversion result or a receive conversion result - but i do not believe this requires fully separate classes, especially
/// for what this is meant to be at its core: a list of green or red checkmarks in the UI. To make DX easier, the two classes above embody
/// this one and provided clean constructors for each case.
-/// POC: Inherits from Base so we can attach the conversion report to the root commit object. Can be revisited later (it's not a problem to not inherit from base).
///
public abstract class ConversionResult
{
diff --git a/Sdk/Speckle.Connectors.Common/Extensions/RootObjectBuilderExtensions.cs b/Sdk/Speckle.Connectors.Common/Extensions/RootObjectBuilderExtensions.cs
index fa630c4c8..bb3b6f51f 100644
--- a/Sdk/Speckle.Connectors.Common/Extensions/RootObjectBuilderExtensions.cs
+++ b/Sdk/Speckle.Connectors.Common/Extensions/RootObjectBuilderExtensions.cs
@@ -6,6 +6,21 @@ namespace Speckle.Connectors.Common.Extensions;
public static class RootObjectBuilderExtensions
{
+ public static void LogSendConversionError(
+ this ILogger> logger,
+ Exception ex,
+ string objectType
+ )
+ {
+ LogLevel logLevel = ex switch
+ {
+ SpeckleException => LogLevel.Information,
+ _ => LogLevel.Error
+ };
+
+ logger.Log(logLevel, ex, "Conversion of object {ObjectType} was not successful", objectType);
+ }
+
public static void LogSendConversionError(
this ILogger> logger,
Exception ex,
diff --git a/Sdk/Speckle.Connectors.Common/Extensions/StopwatchPollyfills.cs b/Sdk/Speckle.Connectors.Common/Extensions/StopwatchPollyfills.cs
deleted file mode 100644
index 6bb7932f7..000000000
--- a/Sdk/Speckle.Connectors.Common/Extensions/StopwatchPollyfills.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using System.Diagnostics;
-
-namespace Speckle.Connectors.Common.Extensions;
-
-public static class StopwatchPollyfills
-{
-#if !NET7_0_OR_GREATER
- private static readonly double s_tickFrequency = (double)TimeSpan.TicksPerSecond / Stopwatch.Frequency;
-#endif
-
- public static TimeSpan GetElapsedTime(long startingTimestamp)
- {
-#if NET7_0_OR_GREATER
- return Stopwatch.GetElapsedTime(startingTimestamp);
-#else
-
- long elapsedTicks = Stopwatch.GetTimestamp() - startingTimestamp;
- return new TimeSpan((long)(elapsedTicks * s_tickFrequency));
-#endif
- }
-}
diff --git a/Sdk/Speckle.Connectors.Common/HostApplications.cs b/Sdk/Speckle.Connectors.Common/HostApplications.cs
index e5a97e2d3..fac1bbdaa 100644
--- a/Sdk/Speckle.Connectors.Common/HostApplications.cs
+++ b/Sdk/Speckle.Connectors.Common/HostApplications.cs
@@ -16,6 +16,7 @@ public static class HostApplications
Civil = new("Civil 3D", "civil3d"),
Civil3D = new("Civil 3D", "civil3d"),
AutoCAD = new("AutoCAD", "autocad"),
+ Plant3D = new("Plant 3D", "plant3d"),
MicroStation = new("MicroStation", "microstation"),
OpenRoads = new("OpenRoads", "openroads"),
OpenRail = new("OpenRail", "openrail"),
diff --git a/Sdk/Speckle.Connectors.Common/Instances/IInstanceBaker.cs b/Sdk/Speckle.Connectors.Common/Instances/IInstanceBaker.cs
index a2a8e559f..316e3ca67 100644
--- a/Sdk/Speckle.Connectors.Common/Instances/IInstanceBaker.cs
+++ b/Sdk/Speckle.Connectors.Common/Instances/IInstanceBaker.cs
@@ -1,6 +1,6 @@
-using Speckle.Connectors.Common.Operations;
using Speckle.Sdk.Models.Collections;
using Speckle.Sdk.Models.Instances;
+using Speckle.Sdk.Pipelines.Progress;
namespace Speckle.Connectors.Common.Instances;
diff --git a/Sdk/Speckle.Connectors.Common/Operations/CardProgress.cs b/Sdk/Speckle.Connectors.Common/Operations/CardProgress.cs
deleted file mode 100644
index d1fbd4a8f..000000000
--- a/Sdk/Speckle.Connectors.Common/Operations/CardProgress.cs
+++ /dev/null
@@ -1,3 +0,0 @@
-namespace Speckle.Connectors.Common.Operations;
-
-public readonly record struct CardProgress(string Status, double? Progress);
diff --git a/Sdk/Speckle.Connectors.Common/Operations/ReceiveOperation.cs b/Sdk/Speckle.Connectors.Common/Operations/ReceiveOperation.cs
index 242694a5a..8f2b795d5 100644
--- a/Sdk/Speckle.Connectors.Common/Operations/ReceiveOperation.cs
+++ b/Sdk/Speckle.Connectors.Common/Operations/ReceiveOperation.cs
@@ -8,6 +8,7 @@ using Speckle.Sdk.Credentials;
using Speckle.Sdk.Logging;
using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Extensions;
+using Speckle.Sdk.Pipelines.Progress;
namespace Speckle.Connectors.Common.Operations;
diff --git a/Sdk/Speckle.Connectors.Common/Operations/ReceiveProgress.cs b/Sdk/Speckle.Connectors.Common/Operations/ReceiveProgress.cs
index 3e0cf800d..e46fe67a1 100644
--- a/Sdk/Speckle.Connectors.Common/Operations/ReceiveProgress.cs
+++ b/Sdk/Speckle.Connectors.Common/Operations/ReceiveProgress.cs
@@ -1,4 +1,5 @@
using Speckle.InterfaceGenerator;
+using Speckle.Sdk.Pipelines.Progress;
using Speckle.Sdk.Transports;
namespace Speckle.Connectors.Common.Operations;
diff --git a/Sdk/Speckle.Connectors.Common/Operations/Send/AggregateProgress.cs b/Sdk/Speckle.Connectors.Common/Operations/Send/AggregateProgress.cs
deleted file mode 100644
index 8bcf2f5d6..000000000
--- a/Sdk/Speckle.Connectors.Common/Operations/Send/AggregateProgress.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-namespace Speckle.Connectors.Common.Operations.Send;
-
-public sealed class AggregateProgress : IProgress
-{
- private readonly IProgress[] _progresses;
-
- public AggregateProgress(params IProgress[] progresses)
- {
- _progresses = progresses;
- }
-
- public void Report(T value)
- {
- foreach (var progress in _progresses)
- {
- progress.Report(value);
- }
- }
-}
diff --git a/Sdk/Speckle.Connectors.Common/Operations/Send/IngestionProgressManager.cs b/Sdk/Speckle.Connectors.Common/Operations/Send/IngestionProgressManager.cs
deleted file mode 100644
index 4b4b4e6cd..000000000
--- a/Sdk/Speckle.Connectors.Common/Operations/Send/IngestionProgressManager.cs
+++ /dev/null
@@ -1,92 +0,0 @@
-using System.Diagnostics;
-using Microsoft.Extensions.Logging;
-using Speckle.Connectors.Common.Extensions;
-using Speckle.InterfaceGenerator;
-using Speckle.Sdk.Api;
-using Speckle.Sdk.Api.GraphQL.Inputs;
-using Speckle.Sdk.Api.GraphQL.Models;
-
-namespace Speckle.Connectors.Common.Operations.Send;
-
-public partial interface IIngestionProgressManager : IProgress;
-
-///
-/// An implementation for the entire client side Ingestion progress update reporting
-/// Will throttles ingestion progress messages and reports their progress
-///
-///
-/// The same class exists also in the RVT ODA codebase
-///
-[GenerateAutoInterface]
-public sealed class IngestionProgressManager(
- ILogger logger,
- IClient speckleClient,
- ModelIngestion ingestion,
- string projectId,
- TimeSpan updateInterval,
- CancellationToken cancellationToken
-) : IIngestionProgressManager
-{
- ///
- /// We've picked quite a coarse throttle window to try and avoid over pressure
- ///
- private Task? _lastUpdate;
- private long _lastUpdatedAt;
- private readonly object _lock = new();
-
- [AutoInterfaceIgnore]
- public void Report(CardProgress value)
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- string trimmedMessage;
- lock (_lock)
- {
- if (ShouldIgnoreProgressUpdate())
- {
- return;
- }
-
- _lastUpdatedAt = Stopwatch.GetTimestamp();
-
- trimmedMessage = value.Status.TrimEnd('.');
-
- _lastUpdate = speckleClient
- .Ingestion.UpdateProgress(
- new ModelIngestionUpdateInput(ingestion.id, projectId, trimmedMessage, value.Progress),
- cancellationToken
- )
- .ContinueWith(
- HandleFaultedContinuation,
- CancellationToken.None,
- TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously,
- TaskScheduler.Default
- );
- }
-
- logger.LogInformation("Progress update {Message} {Progress}", trimmedMessage, value.Progress);
- }
-
- /// if the update should be ignored, otherwise
- private bool ShouldIgnoreProgressUpdate()
- {
- if (_lastUpdate is not null && !_lastUpdate.IsCompleted)
- {
- return true;
- }
-
- TimeSpan msSinceLastUpdate = StopwatchPollyfills.GetElapsedTime(_lastUpdatedAt);
- return msSinceLastUpdate < updateInterval;
- }
-
- private void HandleFaultedContinuation(Task updateTask)
- {
- // The progress report failed... could be many reasons.
- // For now, we're not letting this fail the Ingestion in any way
- // we'll log but otherwise let it slide while leaving no unobserved task exceptions
- if (updateTask.IsFaulted)
- {
- logger.LogWarning(updateTask.Exception, "A progress update failed unexpectedly");
- }
- }
-}
diff --git a/Sdk/Speckle.Connectors.Common/Operations/Send/IngestionProgressManagerFactory.cs b/Sdk/Speckle.Connectors.Common/Operations/Send/IngestionProgressManagerFactory.cs
deleted file mode 100644
index c969ee25f..000000000
--- a/Sdk/Speckle.Connectors.Common/Operations/Send/IngestionProgressManagerFactory.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using Microsoft.Extensions.Logging;
-using Speckle.InterfaceGenerator;
-using Speckle.Sdk.Api;
-using Speckle.Sdk.Api.GraphQL.Models;
-
-namespace Speckle.Connectors.Common.Operations.Send;
-
-[GenerateAutoInterface]
-public sealed class IngestionProgressManagerFactory(ILogger logger)
- : IIngestionProgressManagerFactory
-{
- public IIngestionProgressManager CreateInstance(
- IClient speckleClient,
- ModelIngestion ingestion,
- string projectId,
- TimeSpan updateInterval,
- CancellationToken cancellationToken
- )
- {
- return new IngestionProgressManager(logger, speckleClient, ingestion, projectId, updateInterval, cancellationToken);
- }
-}
diff --git a/Sdk/Speckle.Connectors.Common/Operations/SendOperation.cs b/Sdk/Speckle.Connectors.Common/Operations/SendOperation.cs
index 52b55c781..cbd415dd3 100644
--- a/Sdk/Speckle.Connectors.Common/Operations/SendOperation.cs
+++ b/Sdk/Speckle.Connectors.Common/Operations/SendOperation.cs
@@ -1,7 +1,6 @@
using Speckle.Connectors.Common.Builders;
using Speckle.Connectors.Common.Caching;
using Speckle.Connectors.Common.Conversion;
-using Speckle.Connectors.Common.Operations.Send;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.Logging;
using Speckle.InterfaceGenerator;
@@ -10,11 +9,17 @@ using Speckle.Sdk.Api;
using Speckle.Sdk.Api.GraphQL.Inputs;
using Speckle.Sdk.Api.GraphQL.Models;
using Speckle.Sdk.Credentials;
+using Speckle.Sdk.Helpers;
using Speckle.Sdk.Logging;
using Speckle.Sdk.Models;
+using Speckle.Sdk.Pipelines.Progress;
+using Speckle.Sdk.Pipelines.Send;
using Speckle.Sdk.Serialisation;
using Speckle.Sdk.Serialisation.V2.Send;
using Version = Speckle.Sdk.Api.GraphQL.Models.Version;
+#if !NET8_0_OR_GREATER
+using System.Net.Http;
+#endif
namespace Speckle.Connectors.Common.Operations;
@@ -24,13 +29,16 @@ public sealed class SendOperation(
ISendConversionCache sendConversionCache,
ISendProgress sendProgress,
ISendOperationExecutor sendOperationExecutor,
- ISdkActivityFactory activityFactory,
IThreadContext threadContext,
+ ISdkActivityFactory activityFactory,
ISpeckleApplication speckleApplication,
- IIngestionProgressManagerFactory ingestionProgressManagerFactory
+ IIngestionProgressManagerFactory ingestionProgressManagerFactory,
+ ISpeckleHttp speckleHttp,
+ ISendPipelineFactory sendPipelineFactory,
+ IRootContinuousTraversalBuilder? rootContinuousTraversalBuilder = null
) : ISendOperation
{
- public async Task<(SendOperationResult sendResult, string versionId)> Send(
+ public async Task<(SendOperationResult sendResult, string versionId, string? ingestionId)> Send(
IReadOnlyList objects,
SendInfo sendInfo,
string? fileName,
@@ -43,6 +51,20 @@ public sealed class SendOperation(
bool useModelIngestionSend = await CheckUseModelIngestionSend(sendInfo);
if (useModelIngestionSend)
{
+ bool usePackfileSend =
+ rootContinuousTraversalBuilder != null && await CheckPackfileSendEndpoints(sendInfo, cancellationToken);
+ if (usePackfileSend)
+ {
+ return await SendViaPackfile(
+ objects,
+ sendInfo,
+ fileName,
+ fileSizeBytes,
+ versionMessage,
+ uiProgress,
+ cancellationToken
+ );
+ }
return await SendViaIngestion(
objects,
sendInfo,
@@ -59,45 +81,74 @@ public sealed class SendOperation(
}
}
- private async Task<(SendOperationResult sendResult, string versionId)> SendViaIngestion(
+ private async Task<(SendOperationResult sendResult, string versionId, string? ingestionId)> SendViaPackfile(
IReadOnlyList objects,
SendInfo sendInfo,
string? fileName,
long? fileSizeBytes,
+#pragma warning disable IDE0060
string? versionMessage,
+#pragma warning restore IDE0060
IProgress uiProgress,
CancellationToken cancellationToken
)
{
+ if (rootContinuousTraversalBuilder == null)
+ {
+ throw new InvalidOperationException("rootContinuousTraversalBuilder cannot be null");
+ }
+
ModelIngestion ingestion = await sendInfo.Client.Ingestion.Create(
new(
sendInfo.ModelId,
sendInfo.ProjectId,
$"Sending from {speckleApplication.ApplicationAndVersion}",
- new(speckleApplication.Slug, speckleApplication.HostApplicationVersion, fileName, fileSizeBytes)
+ new(speckleApplication.Slug, speckleApplication.HostApplicationVersion, fileName, fileSizeBytes),
+ 600
),
cancellationToken
);
- using var ingestionScope = ActivityScope.SetTag("modelIngestionId", ingestion.id);
+ using var ingestionScope = ActivityScope.SetTag("modelIngestion.Id", ingestion.id);
var ingestionProgress = ingestionProgressManagerFactory.CreateInstance(
sendInfo.Client,
ingestion,
- sendInfo.ProjectId,
- TimeSpan.FromSeconds(5),
+ TimeSpan.FromSeconds(10),
cancellationToken
);
+
AggregateProgress progress = new(ingestionProgress, uiProgress);
try
{
- SendOperationResult result = await ConvertAndSend(objects, sendInfo, progress, cancellationToken);
-
- string createdVersionId = await sendInfo.Client.Ingestion.Complete(
- new(ingestion.id, sendInfo.ProjectId, result.RootObjId, versionMessage),
- CancellationToken.None
+ var sendPipeline = sendPipelineFactory.CreateInstance(
+ sendInfo.ProjectId,
+ ingestion.id,
+ sendInfo.Account,
+ new RenderedStreamProgress(progress),
+ cancellationToken
+ );
+ var buildResult = await rootContinuousTraversalBuilder.Build(
+ objects,
+ sendInfo.ProjectId,
+ sendPipeline,
+ progress,
+ cancellationToken
);
- return (result, createdVersionId);
+ buildResult.RootObject["version"] = 3;
+
+ WriteReferencesToCache(buildResult.ConversionResults, sendInfo.ProjectId);
+
+ SendOperationResult result =
+ new(buildResult.RootObject.id!, new Dictionary(), buildResult.ConversionResults);
+
+ // NOTE: clients do not need to complete the ingestion - that's going to the be the server's job
+ // string createdVersionId = await sendInfo.Client.Ingestion.Complete(
+ // new(ingestion.id, sendInfo.ProjectId, result.RootObjId, versionMessage),
+ // CancellationToken.None
+ // );
+
+ return (result, "latest", ingestion.id);
}
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
{
@@ -117,7 +168,68 @@ public sealed class SendOperation(
}
}
- private async Task<(SendOperationResult sendResult, string versionId)> SendViaVersionCreate(
+ private async Task<(SendOperationResult sendResult, string versionId, string? ingestionId)> SendViaIngestion(
+ IReadOnlyList objects,
+ SendInfo sendInfo,
+ string? fileName,
+ long? fileSizeBytes,
+ string? versionMessage,
+ IProgress uiProgress,
+ CancellationToken cancellationToken
+ )
+ {
+ ModelIngestion ingestion = await sendInfo.Client.Ingestion.Create(
+ new(
+ sendInfo.ModelId,
+ sendInfo.ProjectId,
+ $"Sending from {speckleApplication.ApplicationAndVersion}",
+ new(speckleApplication.Slug, speckleApplication.HostApplicationVersion, fileName, fileSizeBytes),
+ 600
+ ),
+ cancellationToken
+ );
+ using var ingestionScope = ActivityScope.SetTag("modelIngestionId", ingestion.id);
+
+ var ingestionProgress = ingestionProgressManagerFactory.CreateInstance(
+ sendInfo.Client,
+ ingestion,
+ TimeSpan.FromSeconds(5),
+ cancellationToken
+ );
+ AggregateProgress progress = new(ingestionProgress, uiProgress);
+ try
+ {
+ SendOperationResult result = await ConvertAndSend(objects, sendInfo, progress, cancellationToken);
+
+ string createdVersionId = await sendInfo.Client.Ingestion.Complete(
+ new(ingestion.id, sendInfo.ProjectId, result.RootObjId, versionMessage),
+ CancellationToken.None
+ );
+
+ // NOTE: it might seem weird to pass null for ingestion.id 'null' here but there is a reason.
+ // Because we complete ingestion here in .NET which is safe to pass null ingestion id that we don't want DUI explicitly subscribe to ingestion changes.
+ // I am hoping we will get rid of from logical branching once we have model ingestion on public server
+ return (result, createdVersionId, null);
+ }
+ catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
+ {
+ _ = await sendInfo.Client.Ingestion.FailWithCancel(
+ new(ingestion.id, sendInfo.ProjectId, "User requested cancellation"),
+ CancellationToken.None
+ );
+ throw;
+ }
+ catch (Exception ex)
+ {
+ _ = await sendInfo.Client.Ingestion.FailWithError(
+ ModelIngestionFailedInput.FromException(ingestion.id, sendInfo.ProjectId, ex),
+ CancellationToken.None
+ );
+ throw;
+ }
+ }
+
+ private async Task<(SendOperationResult sendResult, string versionId, string? ingestionId)> SendViaVersionCreate(
IReadOnlyList objects,
SendInfo sendInfo,
string? versionMessage,
@@ -137,7 +249,7 @@ public sealed class SendOperation(
),
cancellationToken
);
- return (result, version.id);
+ return (result, version.id, null);
}
public async Task ConvertAndSend(
@@ -239,6 +351,66 @@ public sealed class SendOperation(
return useModelIngestionSend;
}
+
+ ///
+ ///
+ /// server returned a response, but it was neither true nor false (case insensitive)
+ /// Request failed, or the server returned a non-successful status code that wasn't 404
+ ///
+ /// Returns if the server supports the new packfile data uploads,
+ /// if the server doesn't explicitly, or implicitly via a 404 response.
+ /// Will throw for unexpected cases.
+ ///
+ private async Task CheckPackfileSendEndpoints(SendInfo sendInfo, CancellationToken cancellationToken)
+ {
+ Uri url = new Uri(new Uri(sendInfo.Account.serverInfo.url), "/api/v1/data-module-enabled");
+ using HttpClient client = speckleHttp.CreateHttpClient();
+ using var response = await client.GetAsync(url, cancellationToken);
+ if (response.StatusCode != System.Net.HttpStatusCode.NotFound)
+ {
+ response.EnsureSuccessStatusCode();
+#if NET8_0_OR_GREATER
+ string responseBody = await response.Content.ReadAsStringAsync(cancellationToken);
+#else
+ string responseBody = await response.Content.ReadAsStringAsync();
+#endif
+ return bool.Parse(responseBody);
+ }
+
+ return false;
+ }
+
+ ///
+ /// Reads the conversion results and any will be written to cache.
+ /// All other values will be ignored.
+ ///
+ ///
+ /// For the connectors that support send caching, we are reporting all results as either or
+ /// For Navisworks, which we no longer support send caching, it reports other subtypes, and those will not be cached.
+ ///
+ ///
+ ///
+ private void WriteReferencesToCache(IReadOnlyList conversionResults, string projectId)
+ {
+ // We write the objects to the cache after they've been uploaded to the server
+ // There is still an inbuilt "bad" assumption here that, successfully uploading NDJson means the server is able to re-materialize ids -
+ // but this is only true once the `Version` object is created
+ // Since for many reasons, the server could fail to process the json...
+ // This would leave this send cache out-of-sync with the server, and lead to failed processing of subsequent NDJson uploads
+ // For now, we've taken the decision that it's unlikely to happen...
+
+ var references = new Dictionary();
+ foreach (var x in conversionResults)
+ {
+ if (x.Result is ObjectReference r)
+ {
+ // NOTE: why not ToDictionary -> we might end up reoccurring object references for any reason. instancing, linked models etc.
+ // ToDictionary throws 'item already exists' errors. but safe to override items in references dictionary since they are unique
+ references[new Id(x.SourceId)] = r;
+ }
+ }
+ sendConversionCache.StoreSendResult(projectId, references);
+ }
}
public record SendOperationResult(
diff --git a/Sdk/Speckle.Connectors.Common/Operations/SendProgress.cs b/Sdk/Speckle.Connectors.Common/Operations/SendProgress.cs
index e77d17cbd..e1ea5b361 100644
--- a/Sdk/Speckle.Connectors.Common/Operations/SendProgress.cs
+++ b/Sdk/Speckle.Connectors.Common/Operations/SendProgress.cs
@@ -1,4 +1,5 @@
using Speckle.InterfaceGenerator;
+using Speckle.Sdk.Pipelines.Progress;
using Speckle.Sdk.Transports;
namespace Speckle.Connectors.Common.Operations;
diff --git a/Sdk/Speckle.Connectors.Common/Speckle.Connectors.Common.csproj b/Sdk/Speckle.Connectors.Common/Speckle.Connectors.Common.csproj
index 8ae753d87..40d067edf 100644
--- a/Sdk/Speckle.Connectors.Common/Speckle.Connectors.Common.csproj
+++ b/Sdk/Speckle.Connectors.Common/Speckle.Connectors.Common.csproj
@@ -13,10 +13,11 @@
-
+
-
+
-
+
+
diff --git a/Sdk/Speckle.Connectors.Common/packages.lock.json b/Sdk/Speckle.Connectors.Common/packages.lock.json
index 682010d3f..9a7c692a1 100644
--- a/Sdk/Speckle.Connectors.Common/packages.lock.json
+++ b/Sdk/Speckle.Connectors.Common/packages.lock.json
@@ -44,11 +44,11 @@
},
"Speckle.Objects": {
"type": "Direct",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
},
"GraphQL.Client": {
@@ -183,8 +183,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -193,13 +193,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -296,7 +296,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.Logging": {
@@ -367,11 +367,11 @@
},
"Speckle.Objects": {
"type": "Direct",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
},
"GraphQL.Client": {
@@ -492,8 +492,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -501,13 +501,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -566,7 +566,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.Logging": {
diff --git a/Sdk/Speckle.Connectors.Logging/Consts.cs b/Sdk/Speckle.Connectors.Logging/Consts.cs
index d5e463447..fa8595073 100644
--- a/Sdk/Speckle.Connectors.Logging/Consts.cs
+++ b/Sdk/Speckle.Connectors.Logging/Consts.cs
@@ -4,16 +4,18 @@ namespace Speckle.Connectors.Logging;
public static class Consts
{
+ public const string DEPLOYMENT_ENVIRONMENT = "deployment.environment.name";
public const string SERVICE_NAME = "connector.name";
public const string SERVICE_SLUG = "connector.slug";
public const string OS_NAME = "os.name";
public const string OS_TYPE = "os.type";
public const string OS_SLUG = "os.slug";
- public const string RUNTIME_NAME = "runtime.name";
+ public const string RUNTIME_NAME = "process.runtime.name";
+ public const string RUNTIME_VERSION = "process.runtime.version";
public const string USER_ID = "user.id";
public const string USER_DISTINCT_ID = "user.distinctId";
public const string USER_SERVER_URL = "user.server_url";
- public const string TRACING_SOURCE = "speckle";
+ public const string TRACING_SOURCE = "connector";
///
/// A random GUID for adding to the logging context to correlate the service.instance.id
diff --git a/Sdk/Speckle.Connectors.Logging/Internal/ResourceCreator.cs b/Sdk/Speckle.Connectors.Logging/Internal/ResourceCreator.cs
index 497544b23..fa0a3cc95 100644
--- a/Sdk/Speckle.Connectors.Logging/Internal/ResourceCreator.cs
+++ b/Sdk/Speckle.Connectors.Logging/Internal/ResourceCreator.cs
@@ -5,24 +5,33 @@ namespace Speckle.Connectors.Logging.Internal;
internal static class ResourceCreator
{
- internal static ResourceBuilder Create(string applicationAndVersion, string slug, string connectorVersion) =>
- ResourceBuilder
+ internal static ResourceBuilder Create(
+ string serviceName,
+ string applicationAndVersion,
+ string slug,
+ string connectorVersion
+ )
+ {
+ string deploymentEnvironment =
+ Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT")
+ ?? Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")
+ ?? "Development";
+ return ResourceBuilder
.CreateEmpty()
- .AddService(
- serviceName: Consts.TRACING_SOURCE,
- serviceVersion: connectorVersion,
- serviceInstanceId: Consts.StaticSessionId
- )
+ .AddService(serviceName: serviceName, serviceVersion: connectorVersion, serviceInstanceId: Consts.StaticSessionId)
.AddAttributes(
[
+ new(Consts.DEPLOYMENT_ENVIRONMENT, deploymentEnvironment.ToLowerInvariant()),
new(Consts.SERVICE_NAME, applicationAndVersion),
new(Consts.SERVICE_SLUG, slug),
new(Consts.OS_NAME, Environment.OSVersion.ToString()),
new(Consts.OS_TYPE, RuntimeInformation.ProcessArchitecture.ToString()),
new(Consts.OS_SLUG, DetermineHostOsSlug()),
- new(Consts.RUNTIME_NAME, RuntimeInformation.FrameworkDescription),
+ new(Consts.RUNTIME_NAME, ".NET"),
+ new(Consts.RUNTIME_VERSION, RuntimeInformation.FrameworkDescription),
]
);
+ }
private static string DetermineHostOsSlug()
{
diff --git a/Sdk/Speckle.Connectors.Logging/Observability.cs b/Sdk/Speckle.Connectors.Logging/Observability.cs
index 59405aed4..c4b226c91 100644
--- a/Sdk/Speckle.Connectors.Logging/Observability.cs
+++ b/Sdk/Speckle.Connectors.Logging/Observability.cs
@@ -5,13 +5,14 @@ namespace Speckle.Connectors.Logging;
public static class Observability
{
public static (LoggerProvider, IDisposable, IDisposable) Initialize(
+ string serviceName,
string applicationAndVersion,
string slug,
string connectorVersion,
SpeckleObservability observability
)
{
- var resourceBuilder = ResourceCreator.Create(applicationAndVersion, slug, connectorVersion);
+ var resourceBuilder = ResourceCreator.Create(serviceName, applicationAndVersion, slug, connectorVersion);
var logging = LogBuilder.Initialize(
applicationAndVersion,
connectorVersion,
diff --git a/Sdk/Speckle.Connectors.Logging/packages.lock.json b/Sdk/Speckle.Connectors.Logging/packages.lock.json
index e56cd1682..296dcbfcf 100644
--- a/Sdk/Speckle.Connectors.Logging/packages.lock.json
+++ b/Sdk/Speckle.Connectors.Logging/packages.lock.json
@@ -41,23 +41,22 @@
},
"OpenTelemetry.Exporter.OpenTelemetryProtocol": {
"type": "Direct",
- "requested": "[1.11.1, )",
- "resolved": "1.11.1",
- "contentHash": "UiZBa+2b396Oxx9RX7h4ch+yZvX8nezxVkihPLU6zdEUfJbbVY2mNypJKEoW2Vh4xCaCp0fB6na3Kti+KfTVaw==",
+ "requested": "[1.13.1, )",
+ "resolved": "1.13.1",
+ "contentHash": "WFqOpqMkjd8lM/asQRgfLP72UCqThQIGoylDgoYR8x0Bh9UCrdmBJCDU4pVZgI9CtSq1sWXeQuUsRXAl5U4yKg==",
"dependencies": {
- "Grpc.Core": "[2.44.0, 3.0.0)",
- "OpenTelemetry": "1.11.1"
+ "OpenTelemetry": "1.13.1"
}
},
"OpenTelemetry.Instrumentation.Http": {
"type": "Direct",
- "requested": "[1.11.0, )",
- "resolved": "1.11.0",
- "contentHash": "1ncYPNmMaYNPX664uo3FlmSVGETBKQbBvarbGgB5ZynERTFmCsZ7UqefvVe3vnPYOIAGOjbMAbprYF2BfMielg==",
+ "requested": "[1.13.0, )",
+ "resolved": "1.13.0",
+ "contentHash": "B+nmCn3/orrLhUuCC6WwHh9JUkIV/wubpZ+vYOf2CedjOZupgcQcx96Kwy6UVjdNDWGxsEw0jXWXZUQlYnmRqA==",
"dependencies": {
"Microsoft.Extensions.Configuration": "9.0.0",
"Microsoft.Extensions.Options": "9.0.0",
- "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.11.1, 2.0.0)"
+ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.13.1, 2.0.0)"
}
},
"PolySharp": {
@@ -120,23 +119,6 @@
"resolved": "0.9.6",
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
},
- "Grpc.Core": {
- "type": "Transitive",
- "resolved": "2.44.0",
- "contentHash": "H2rTNePSYeEqUgBBqiE5KZ/yOX7jEtETjWjv4gGtnYxrlpZ79VAHe+4KtZAnt2KJMiGvqTm7eo1SPk+QpiPfaw==",
- "dependencies": {
- "Grpc.Core.Api": "2.44.0",
- "System.Memory": "4.5.3"
- }
- },
- "Grpc.Core.Api": {
- "type": "Transitive",
- "resolved": "2.44.0",
- "contentHash": "FBfPMvKwT8q98T8lWa5z6nBMLdH/Mmo5g4yyYYMvbXLWDzo4beqa7CUU5QH3PKvo2X6/b+UAZ2IymXlrYG3IXg==",
- "dependencies": {
- "System.Memory": "4.5.3"
- }
- },
"ILRepack": {
"type": "Transitive",
"resolved": "2.0.33",
@@ -264,29 +246,29 @@
},
"OpenTelemetry": {
"type": "Transitive",
- "resolved": "1.11.1",
- "contentHash": "F+HBI2bE7RKmb8Bj0kBtZIVzCfpTe1ZyY6kYP/jny1+9oq7IdBnNsVXZlPev9OqQzRp3iXpJ1UsnN1YOEwdtkQ==",
+ "resolved": "1.13.1",
+ "contentHash": "rrM2NlZ0Xla2Ar8zzU09n+HoLFq8b+Kjx7vrmR0tdYfWLYWGNcXHOITXUiyaK8RrFEceMEoF45VBsaf4QPmKcg==",
"dependencies": {
"Microsoft.Extensions.Diagnostics.Abstractions": "9.0.0",
"Microsoft.Extensions.Logging.Configuration": "9.0.0",
- "OpenTelemetry.Api.ProviderBuilderExtensions": "1.11.1"
+ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.13.1"
}
},
"OpenTelemetry.Api": {
"type": "Transitive",
- "resolved": "1.11.1",
- "contentHash": "KaBjGMqrqQv41mIkvPUvmAG7yxDlI6qchKhjXlOF3ZwsdcRRLrdrkiDLIJ90iZgUoKVdP8fE1fCri9nc+ug0Cg==",
+ "resolved": "1.13.1",
+ "contentHash": "tieglRERo7Rgu8oE8aamnuXCMPEW5fXIqO5ngTMCNk9pOEXanc0SdQ86ZAD1goNiGcjWHn+P3WMZp0FZSJgCoQ==",
"dependencies": {
"System.Diagnostics.DiagnosticSource": "9.0.0"
}
},
"OpenTelemetry.Api.ProviderBuilderExtensions": {
"type": "Transitive",
- "resolved": "1.11.1",
- "contentHash": "vMdNMQeW55jXIa/Kybec/br6jC+rWybniTi6DCW5lz1kGghKso+J+FC3uBgiq0/pTqusfeDbO5PEHGM/r5z8Ow==",
+ "resolved": "1.13.1",
+ "contentHash": "x8QXMsrIyp+XzDUFQAM+C4upAPNbwaBIPjTWEoonziWAav6weS8OxsMKrE4wz7Zly8ATlsoxk0mWZ+PHO3Wg0w==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.0",
- "OpenTelemetry.Api": "1.11.1"
+ "OpenTelemetry.Api": "1.13.1"
}
},
"System.Buffers": {
@@ -417,22 +399,22 @@
},
"OpenTelemetry.Exporter.OpenTelemetryProtocol": {
"type": "Direct",
- "requested": "[1.11.1, )",
- "resolved": "1.11.1",
- "contentHash": "UiZBa+2b396Oxx9RX7h4ch+yZvX8nezxVkihPLU6zdEUfJbbVY2mNypJKEoW2Vh4xCaCp0fB6na3Kti+KfTVaw==",
+ "requested": "[1.13.1, )",
+ "resolved": "1.13.1",
+ "contentHash": "WFqOpqMkjd8lM/asQRgfLP72UCqThQIGoylDgoYR8x0Bh9UCrdmBJCDU4pVZgI9CtSq1sWXeQuUsRXAl5U4yKg==",
"dependencies": {
- "OpenTelemetry": "1.11.1"
+ "OpenTelemetry": "1.13.1"
}
},
"OpenTelemetry.Instrumentation.Http": {
"type": "Direct",
- "requested": "[1.11.0, )",
- "resolved": "1.11.0",
- "contentHash": "1ncYPNmMaYNPX664uo3FlmSVGETBKQbBvarbGgB5ZynERTFmCsZ7UqefvVe3vnPYOIAGOjbMAbprYF2BfMielg==",
+ "requested": "[1.13.0, )",
+ "resolved": "1.13.0",
+ "contentHash": "B+nmCn3/orrLhUuCC6WwHh9JUkIV/wubpZ+vYOf2CedjOZupgcQcx96Kwy6UVjdNDWGxsEw0jXWXZUQlYnmRqA==",
"dependencies": {
- "Microsoft.Extensions.Configuration": "9.0.0",
- "Microsoft.Extensions.Options": "9.0.0",
- "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.11.1, 2.0.0)"
+ "Microsoft.Extensions.Configuration": "8.0.0",
+ "Microsoft.Extensions.Options": "8.0.0",
+ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.13.1, 2.0.0)"
}
},
"PolySharp": {
@@ -594,29 +576,29 @@
},
"OpenTelemetry": {
"type": "Transitive",
- "resolved": "1.11.1",
- "contentHash": "F+HBI2bE7RKmb8Bj0kBtZIVzCfpTe1ZyY6kYP/jny1+9oq7IdBnNsVXZlPev9OqQzRp3iXpJ1UsnN1YOEwdtkQ==",
+ "resolved": "1.13.1",
+ "contentHash": "rrM2NlZ0Xla2Ar8zzU09n+HoLFq8b+Kjx7vrmR0tdYfWLYWGNcXHOITXUiyaK8RrFEceMEoF45VBsaf4QPmKcg==",
"dependencies": {
"Microsoft.Extensions.Diagnostics.Abstractions": "9.0.0",
"Microsoft.Extensions.Logging.Configuration": "9.0.0",
- "OpenTelemetry.Api.ProviderBuilderExtensions": "1.11.1"
+ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.13.1"
}
},
"OpenTelemetry.Api": {
"type": "Transitive",
- "resolved": "1.11.1",
- "contentHash": "KaBjGMqrqQv41mIkvPUvmAG7yxDlI6qchKhjXlOF3ZwsdcRRLrdrkiDLIJ90iZgUoKVdP8fE1fCri9nc+ug0Cg==",
+ "resolved": "1.13.1",
+ "contentHash": "tieglRERo7Rgu8oE8aamnuXCMPEW5fXIqO5ngTMCNk9pOEXanc0SdQ86ZAD1goNiGcjWHn+P3WMZp0FZSJgCoQ==",
"dependencies": {
"System.Diagnostics.DiagnosticSource": "9.0.0"
}
},
"OpenTelemetry.Api.ProviderBuilderExtensions": {
"type": "Transitive",
- "resolved": "1.11.1",
- "contentHash": "vMdNMQeW55jXIa/Kybec/br6jC+rWybniTi6DCW5lz1kGghKso+J+FC3uBgiq0/pTqusfeDbO5PEHGM/r5z8Ow==",
+ "resolved": "1.13.1",
+ "contentHash": "x8QXMsrIyp+XzDUFQAM+C4upAPNbwaBIPjTWEoonziWAav6weS8OxsMKrE4wz7Zly8ATlsoxk0mWZ+PHO3Wg0w==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.0",
- "OpenTelemetry.Api": "1.11.1"
+ "OpenTelemetry.Api": "1.13.1"
}
},
"System.Diagnostics.DiagnosticSource": {
diff --git a/Sdk/Speckle.Converters.Common.Tests/packages.lock.json b/Sdk/Speckle.Converters.Common.Tests/packages.lock.json
index 3c125a996..a195b78e1 100644
--- a/Sdk/Speckle.Converters.Common.Tests/packages.lock.json
+++ b/Sdk/Speckle.Converters.Common.Tests/packages.lock.json
@@ -247,8 +247,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -256,13 +256,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -341,7 +341,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"speckle.testing": {
@@ -350,7 +350,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Moq": "[4.20.70, )",
"NUnit": "[4.1.0, )",
- "Speckle.Objects": "[3.15.1, )"
+ "Speckle.Objects": "[3.15.3, )"
}
},
"Microsoft.Extensions.Logging": {
@@ -379,11 +379,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
}
}
diff --git a/Sdk/Speckle.Converters.Common/packages.lock.json b/Sdk/Speckle.Converters.Common/packages.lock.json
index 14ceee3c3..89f052232 100644
--- a/Sdk/Speckle.Converters.Common/packages.lock.json
+++ b/Sdk/Speckle.Converters.Common/packages.lock.json
@@ -41,11 +41,11 @@
},
"Speckle.Objects": {
"type": "Direct",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
},
"GraphQL.Client": {
@@ -180,8 +180,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -190,13 +190,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg==",
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
}
@@ -345,11 +345,11 @@
},
"Speckle.Objects": {
"type": "Direct",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
},
"GraphQL.Client": {
@@ -470,8 +470,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -479,13 +479,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
diff --git a/Sdk/Speckle.Testing/packages.lock.json b/Sdk/Speckle.Testing/packages.lock.json
index 59baf0637..19c114ecc 100644
--- a/Sdk/Speckle.Testing/packages.lock.json
+++ b/Sdk/Speckle.Testing/packages.lock.json
@@ -59,11 +59,11 @@
},
"Speckle.Objects": {
"type": "Direct",
- "requested": "[3.15.1, )",
- "resolved": "3.15.1",
- "contentHash": "vFIf01jNVD69N6wE5iYVM7TKA6AbSTZxq1EedJCVZxhj5pkhHBw+23fyO+wz7Cd9ggqsiBUJMuKxUBHaDphGWQ==",
+ "requested": "[3.15.3, )",
+ "resolved": "3.15.3",
+ "contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
"dependencies": {
- "Speckle.Sdk": "3.15.1"
+ "Speckle.Sdk": "3.15.3"
}
},
"Castle.Core": {
@@ -192,8 +192,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "Gt1qAZrMflLMOjDy4cQzJX5pdq5WokphYdsry7pMBlRHRdx9imQhJUPCg528Y2iVSMUnRKvj3A3cHtBeUxysEQ==",
+ "resolved": "3.15.3",
+ "contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Data.Sqlite": "7.0.5",
@@ -201,13 +201,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
- "Speckle.Sdk.Dependencies": "3.15.1"
+ "Speckle.Sdk.Dependencies": "3.15.3"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
- "resolved": "3.15.1",
- "contentHash": "OUOnt4Vnd1J838LTWEpP0ge8WIwjhx8O94kuTbC6AJRfOx9Lw78SG6XtVCE+WXb9zC5h3tzOV9YOng8Ke5yXMg=="
+ "resolved": "3.15.3",
+ "contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
diff --git a/Speckle.Connectors.sln b/Speckle.Connectors.sln
index ef552f92b..820b3160e 100644
--- a/Speckle.Connectors.sln
+++ b/Speckle.Connectors.sln
@@ -307,6 +307,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Importers.JobProces
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Connectors.RhinoImporter", "Connectors\Rhino\Speckle.Connectors.RhinoImporter\Speckle.Connectors.RhinoImporter.csproj", "{5422F2C8-1E00-4DAE-BB01-65A17BE8CD68}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Connectors.Plant3d2026", "Connectors\Autocad\Speckle.Connectors.Plant3d2026\Speckle.Connectors.Plant3d2026.csproj", "{F3A4B5C6-D7E8-4F01-A345-6789ABCDEF01}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Converters.Plant3d2026", "Converters\Plant3d\Speckle.Converters.Plant3d2026\Speckle.Converters.Plant3d2026.csproj", "{C6D7E8F9-0123-4567-89AB-CDEF01234567}"
+EndProject
+Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Speckle.Connectors.Plant3dShared", "Connectors\Autocad\Speckle.Connectors.Plant3dShared\Speckle.Connectors.Plant3dShared.shproj", "{B1C4A14C-2F4E-4C3D-9B71-A3F5D8E6C912}"
+EndProject
+Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Speckle.Converters.Plant3dShared", "Converters\Plant3d\Speckle.Converters.Plant3dShared\Speckle.Converters.Plant3dShared.shproj", "{C7E3A28D-5F91-4B6E-A8D2-3F1C9E7B4D56}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -770,6 +778,18 @@ Global
{5422F2C8-1E00-4DAE-BB01-65A17BE8CD68}.Local|Any CPU.Build.0 = Local|Any CPU
{5422F2C8-1E00-4DAE-BB01-65A17BE8CD68}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5422F2C8-1E00-4DAE-BB01-65A17BE8CD68}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F3A4B5C6-D7E8-4F01-A345-6789ABCDEF01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F3A4B5C6-D7E8-4F01-A345-6789ABCDEF01}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F3A4B5C6-D7E8-4F01-A345-6789ABCDEF01}.Local|Any CPU.ActiveCfg = Local|Any CPU
+ {F3A4B5C6-D7E8-4F01-A345-6789ABCDEF01}.Local|Any CPU.Build.0 = Local|Any CPU
+ {F3A4B5C6-D7E8-4F01-A345-6789ABCDEF01}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F3A4B5C6-D7E8-4F01-A345-6789ABCDEF01}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C6D7E8F9-0123-4567-89AB-CDEF01234567}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C6D7E8F9-0123-4567-89AB-CDEF01234567}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C6D7E8F9-0123-4567-89AB-CDEF01234567}.Local|Any CPU.ActiveCfg = Local|Any CPU
+ {C6D7E8F9-0123-4567-89AB-CDEF01234567}.Local|Any CPU.Build.0 = Local|Any CPU
+ {C6D7E8F9-0123-4567-89AB-CDEF01234567}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C6D7E8F9-0123-4567-89AB-CDEF01234567}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -907,6 +927,10 @@ Global
{92F065BE-97E2-4192-B561-88A6A8CFA53F} = {CD0C216A-2A96-4423-956E-3DDFCAEA510C}
{1953F875-B271-484B-B589-3D4AC1288C2B} = {CD0C216A-2A96-4423-956E-3DDFCAEA510C}
{5422F2C8-1E00-4DAE-BB01-65A17BE8CD68} = {5929C9C7-F971-449E-BC5B-4486016BD11F}
+ {F3A4B5C6-D7E8-4F01-A345-6789ABCDEF01} = {1D9F4468-A382-4D25-8195-F93A884B14DA}
+ {C6D7E8F9-0123-4567-89AB-CDEF01234567} = {1D9F4468-A382-4D25-8195-F93A884B14DA}
+ {B1C4A14C-2F4E-4C3D-9B71-A3F5D8E6C912} = {4721AA15-AF6E-4A62-A2C3-65564DC563E6}
+ {C7E3A28D-5F91-4B6E-A8D2-3F1C9E7B4D56} = {4721AA15-AF6E-4A62-A2C3-65564DC563E6}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {EE253116-7070-4E9A-BCE8-2911C251B8C8}
@@ -1010,5 +1034,19 @@ Global
Connectors\Revit\Speckle.Connectors.RevitShared\Speckle.Connectors.RevitShared.projitems*{f98f97ac-d862-4750-b952-fbe4e9ee0eba}*SharedItemsImports = 5
Connectors\Navisworks\Speckle.Connectors.NavisworksShared\Speckle.Connectors.NavisworksShared.projitems*{fd44e1f0-d20a-49b6-adc9-482d911a74fb}*SharedItemsImports = 5
Connectors\Navisworks\Speckle.Connectors.NavisworksShared\Speckle.Connectors.NavisworksShared.projitems*{fe797118-07cb-44a7-a779-68ff3b69ee40}*SharedItemsImports = 5
+ Connectors\Autocad\Speckle.Connectors.Plant3dShared\Speckle.Connectors.Plant3dShared.projitems*{b1c4a14c-2f4e-4c3d-9b71-a3f5d8e6c912}*SharedItemsImports = 13
+ Connectors\Autocad\Speckle.Connectors.AutocadShared\Speckle.Connectors.AutocadShared.projitems*{d1e2f3a4-b5c6-4d8e-9f01-234567890abc}*SharedItemsImports = 5
+ Connectors\Autocad\Speckle.Connectors.Plant3dShared\Speckle.Connectors.Plant3dShared.projitems*{d1e2f3a4-b5c6-4d8e-9f01-234567890abc}*SharedItemsImports = 5
+ Connectors\Autocad\Speckle.Connectors.AutocadShared\Speckle.Connectors.AutocadShared.projitems*{e2f3a4b5-c6d7-4e9f-8123-456789abcdef}*SharedItemsImports = 5
+ Connectors\Autocad\Speckle.Connectors.Plant3dShared\Speckle.Connectors.Plant3dShared.projitems*{e2f3a4b5-c6d7-4e9f-8123-456789abcdef}*SharedItemsImports = 5
+ Connectors\Autocad\Speckle.Connectors.AutocadShared\Speckle.Connectors.AutocadShared.projitems*{f3a4b5c6-d7e8-4f01-a345-6789abcdef01}*SharedItemsImports = 5
+ Connectors\Autocad\Speckle.Connectors.Plant3dShared\Speckle.Connectors.Plant3dShared.projitems*{f3a4b5c6-d7e8-4f01-a345-6789abcdef01}*SharedItemsImports = 5
+ Converters\Plant3d\Speckle.Converters.Plant3dShared\Speckle.Converters.Plant3dShared.projitems*{c7e3a28d-5f91-4b6e-a8d2-3f1c9e7b4d56}*SharedItemsImports = 13
+ Converters\Autocad\Speckle.Converters.AutocadShared\Speckle.Converters.AutocadShared.projitems*{a4b5c6d7-e8f9-4123-8567-89abcdef0123}*SharedItemsImports = 5
+ Converters\Plant3d\Speckle.Converters.Plant3dShared\Speckle.Converters.Plant3dShared.projitems*{a4b5c6d7-e8f9-4123-8567-89abcdef0123}*SharedItemsImports = 5
+ Converters\Autocad\Speckle.Converters.AutocadShared\Speckle.Converters.AutocadShared.projitems*{b5c6d7e8-f901-4345-a789-abcdef012345}*SharedItemsImports = 5
+ Converters\Plant3d\Speckle.Converters.Plant3dShared\Speckle.Converters.Plant3dShared.projitems*{b5c6d7e8-f901-4345-a789-abcdef012345}*SharedItemsImports = 5
+ Converters\Autocad\Speckle.Converters.AutocadShared\Speckle.Converters.AutocadShared.projitems*{c6d7e8f9-0123-4567-89ab-cdef01234567}*SharedItemsImports = 5
+ Converters\Plant3d\Speckle.Converters.Plant3dShared\Speckle.Converters.Plant3dShared.projitems*{c6d7e8f9-0123-4567-89ab-cdef01234567}*SharedItemsImports = 5
EndGlobalSection
EndGlobal
diff --git a/Speckle.Connectors.slnx b/Speckle.Connectors.slnx
index c764603db..e78cd8d86 100644
--- a/Speckle.Connectors.slnx
+++ b/Speckle.Connectors.slnx
@@ -49,14 +49,18 @@
+
+
+
+
@@ -151,7 +155,7 @@
-
+
@@ -180,7 +184,7 @@
-
+
diff --git a/Speckle.Rhino-importer.slnx b/Speckle.Rhino-importer.slnx
index 5adab161d..a49671c2a 100644
--- a/Speckle.Rhino-importer.slnx
+++ b/Speckle.Rhino-importer.slnx
@@ -22,21 +22,16 @@
-
+
-
+
-
-
-
-
-
-
+
diff --git a/todos.md b/todos.md
new file mode 100644
index 000000000..b7945f4da
--- /dev/null
+++ b/todos.md
@@ -0,0 +1,11 @@
+# TODOs
+
+## Packfile send route for importers
+
+Enable the importer flow to use the packfile send path (`SendViaPackfile` via `SendPipeline` + `IRootContinuousTraversalBuilder`). In this route, the server creates the version at the end of its processing job, so the job processor must skip calling `Ingestion.Complete()`.
+
+The `null` root object ID signals "server handles completion":
+
+1. **`Importers/Rhino/Speckle.Importers.Rhino/Internal/Sender.cs`**: When packfile route is used, return `null` for `RootId` (e.g. `SerializeProcessResults` won't have one — write `RootObjectId = null` in `Program.cs:61`).
+2. **`Importers/Rhino/Speckle.Importers.JobProcessor/JobHandlers/RhinoJobHandler.cs` (line 69-73)**: Stop treating `null` `RootObjectId` as an error. Null means "server handles it", not failure.
+3. **`Importers/Rhino/Speckle.Importers.JobProcessor/JobProcessor.cs` (line 189-192)**: Make `rootObjectId` nullable, skip `ReportSuccess()` when null.