diff --git a/.gitignore b/.gitignore
index 2646b24de..5b1cd032a 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/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.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..c393079d5 100644
--- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Speckle.Connectors.AutocadShared.projitems
+++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Speckle.Connectors.AutocadShared.projitems
@@ -60,5 +60,8 @@
Always
+
+ Always
+
\ No newline at end of file
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..450d02b41
--- /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 Plant3D 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/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/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/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/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/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/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 @@
-
+