Compare commits

..

9 Commits

Author SHA1 Message Date
Jonathon Broughton 4c42138732 updates category mapping for Civil 3D interoperability
Modifies send settings for better compatibility with Civil 3D mappings.

Enhances logging for category mapping to assist in debugging and monitoring.

Adds additional category mappings to improve conversion accuracy.
2026-01-12 18:10:18 +00:00
Jonathon Broughton 8c84f673df Refactors constructor 2025-12-20 10:25:12 +00:00
Jonathon Broughton 6157cc9d40 Updates method visibility for send settings
Changes the visibility of the send settings method to virtual, enabling overrides in derived classes.
2025-12-19 22:54:44 +00:00
Jonathon Broughton c7e35f6776 Enhance PropertiesExtractor for Revit category mapping 2025-12-19 22:45:04 +00:00
Jonathon Broughton 73c426057a Implement Civil3DBuiltInCategoryExtractor
Update projitems for Civil3DBuiltInCategoryExtractor
2025-12-19 22:45:03 +00:00
Jonathon Broughton 3245bb2be2 Update Civil3dConversionSettings to include Revit category mapping
Update Civil3dConversionSettingsFactory to support Revit category mapping
2025-12-19 22:45:00 +00:00
Jonathon Broughton aeec0976af Implement ToSpeckleSettingsManagerCivil3d
Update projitems for new Civil3D send settings
2025-12-19 22:44:58 +00:00
Jonathon Broughton 18005abc3d Implement Revit category mapping setting for Civil3D 2025-12-19 22:44:57 +00:00
Jonathon Broughton a98e1ccfaa Add new settings and dependencies for Civil3D
Add Civil3D settings to Dependency Injection
2025-12-19 22:44:56 +00:00
186 changed files with 3016 additions and 4961 deletions
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -281,15 +281,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -313,7 +312,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -357,18 +356,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
}
}
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -281,15 +281,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -313,7 +312,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -357,18 +356,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
}
}
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -281,15 +281,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -314,7 +313,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -358,18 +357,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
}
}
@@ -157,8 +157,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -230,15 +230,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -263,7 +262,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -307,18 +306,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
},
"net8.0-windows7.0/win-x64": {
@@ -157,8 +157,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -230,15 +230,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -263,7 +262,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -307,18 +306,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
},
"net8.0-windows7.0/win-x64": {
@@ -125,7 +125,7 @@ public abstract class AutocadSendBaseBinding : ISendBinding
public List<ISendFilter> GetSendFilters() => _sendFilters;
public List<ICardSetting> GetSendSettings() => [];
public virtual List<ICardSetting> GetSendSettings() => [];
public async Task Send(string modelCardId) =>
await _threadContext.RunOnMainAsync(async () => await SendInternal(modelCardId));
@@ -180,8 +180,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -191,13 +191,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -290,15 +290,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -323,7 +322,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -367,18 +366,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
}
}
@@ -180,8 +180,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -191,13 +191,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -290,15 +290,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -323,7 +322,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -367,18 +366,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
}
}
@@ -180,8 +180,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -191,13 +191,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -290,15 +290,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -323,7 +322,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -367,18 +366,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
}
}
@@ -166,8 +166,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -239,15 +239,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -273,7 +272,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -317,18 +316,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
},
"net8.0-windows7.0/win-x64": {
@@ -166,8 +166,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -239,15 +239,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -273,7 +272,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -317,18 +316,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
},
"net8.0-windows7.0/win-x64": {
@@ -1,5 +1,6 @@
using Microsoft.Extensions.DependencyInjection;
using Speckle.Connectors.Autocad.Bindings;
using Speckle.Connectors.Civil3dShared.Operations.Send.Settings;
using Speckle.Connectors.Common.Caching;
using Speckle.Connectors.Common.Cancellation;
using Speckle.Connectors.Common.Threading;
@@ -7,56 +8,63 @@ using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Models.Card.SendFilter;
using Speckle.Connectors.DUI.Settings;
using Speckle.Converters.Autocad;
using Speckle.Converters.Civil3dShared;
using Speckle.Converters.Common;
namespace Speckle.Connectors.Civil3dShared.Bindings;
public sealed class Civil3dSendBinding : AutocadSendBaseBinding
{
private readonly ICivil3dConversionSettingsFactory _civil3dConversionSettingsFactory;
private readonly IAutocadConversionSettingsFactory _autocadConversionSettingsFactory;
public Civil3dSendBinding(
DocumentModelStore store,
IBrowserBridge parent,
IEnumerable<ISendFilter> sendFilters,
ICancellationManager cancellationManager,
ISendConversionCache sendConversionCache,
ICivil3dConversionSettingsFactory civil3dConversionSettingsFactory,
IAutocadConversionSettingsFactory autocadConversionSettingsFactory,
IThreadContext threadContext,
ITopLevelExceptionHandler topLevelExceptionHandler,
IAppIdleManager appIdleManager,
ISendOperationManagerFactory sendOperationManagerFactory
public sealed class Civil3dSendBinding(
DocumentModelStore store,
IBrowserBridge parent,
IEnumerable<ISendFilter> sendFilters,
ICancellationManager cancellationManager,
ISendConversionCache sendConversionCache,
ICivil3dConversionSettingsFactory civil3dConversionSettingsFactory,
IAutocadConversionSettingsFactory autocadConversionSettingsFactory,
IToSpeckleSettingsManagerCivil3d toSpeckleSettingsManagerCivil3d,
IThreadContext threadContext,
ITopLevelExceptionHandler topLevelExceptionHandler,
IAppIdleManager appIdleManager,
ISendOperationManagerFactory sendOperationManagerFactory
)
: AutocadSendBaseBinding(
store,
parent,
sendFilters,
cancellationManager,
sendConversionCache,
threadContext,
topLevelExceptionHandler,
appIdleManager,
sendOperationManagerFactory
)
: base(
store,
parent,
sendFilters,
cancellationManager,
sendConversionCache,
threadContext,
topLevelExceptionHandler,
appIdleManager,
sendOperationManagerFactory
)
{
_civil3dConversionSettingsFactory = civil3dConversionSettingsFactory;
_autocadConversionSettingsFactory = autocadConversionSettingsFactory;
}
{
private readonly DocumentModelStore _store = store;
public override List<ICardSetting> GetSendSettings() => [new RevitCategoryMappingSetting(true)];
// POC: we're registering the conversion settings for autocad here because we need the autocad conversion settings to be able to use the autocad typed converters.
// POC: We need a separate send binding for civil3d due to using a different unit converter (needed for conversion settings construction)
// POC: We need a separate a send binding for Civil3d due to using a different unit converter (needed for conversion settings construction)
protected override void InitializeSettings(IServiceProvider serviceProvider)
{
// Get the model card from the store to access user settings
var modelCard = _store.GetSenders().FirstOrDefault();
bool mappingToRevitCategories = false;
if (modelCard != null)
{
mappingToRevitCategories = toSpeckleSettingsManagerCivil3d.GetMappingToRevitCategories(modelCard);
}
serviceProvider
.GetRequiredService<IConverterSettingsStore<Civil3dConversionSettings>>()
.Initialize(_civil3dConversionSettingsFactory.Create(Application.DocumentManager.CurrentDocument));
.Initialize(
civil3dConversionSettingsFactory.Create(Application.DocumentManager.CurrentDocument, mappingToRevitCategories)
);
serviceProvider
.GetRequiredService<IConverterSettingsStore<AutocadConversionSettings>>()
.Initialize(_autocadConversionSettingsFactory.Create(Application.DocumentManager.CurrentDocument));
.Initialize(autocadConversionSettingsFactory.Create(Application.DocumentManager.CurrentDocument));
}
}
@@ -6,6 +6,7 @@ using Speckle.Connectors.Civil3dShared.Bindings;
using Speckle.Connectors.Civil3dShared.HostApp;
using Speckle.Connectors.Civil3dShared.Operations.Receive;
using Speckle.Connectors.Civil3dShared.Operations.Send;
using Speckle.Connectors.Civil3dShared.Operations.Send.Settings;
using Speckle.Connectors.Common.Builders;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Converters.Civil3dShared.ToSpeckle;
@@ -24,6 +25,9 @@ public static class Civil3dConnectorModule
serviceCollection.AddScoped<IRootObjectBuilder<AutocadRootObject>, Civil3dRootObjectBuilder>();
serviceCollection.AddSingleton<IBinding, Civil3dSendBinding>();
// send settings
serviceCollection.AddSingleton<ToSpeckleSettingsManagerCivil3d>();
// add receive
serviceCollection.LoadReceive();
serviceCollection.AddScoped<IHostObjectBuilder, Civil3dHostObjectBuilder>();
@@ -0,0 +1,12 @@
using Speckle.Connectors.DUI.Settings;
namespace Speckle.Connectors.Civil3dShared.Operations.Send.Settings;
public class RevitCategoryMappingSetting(bool value) : ICardSetting
{
public string? Id { get; set; } = "mappingToRevitCategories";
public string? Title { get; set; } = "Map to Revit Categories";
public string? Type { get; set; } = "boolean";
public List<string>? Enum { get; set; }
public object? Value { get; set; } = value;
}
@@ -0,0 +1,42 @@
using System.Diagnostics.CodeAnalysis;
using Speckle.Connectors.Common.Caching;
using Speckle.Connectors.DUI.Models.Card;
using Speckle.InterfaceGenerator;
using Speckle.Sdk.Common;
namespace Speckle.Connectors.Civil3dShared.Operations.Send.Settings;
[GenerateAutoInterface]
public class ToSpeckleSettingsManagerCivil3d : IToSpeckleSettingsManagerCivil3d
{
private readonly ISendConversionCache _sendConversionCache;
private readonly Dictionary<string, bool?> _revitCategoryMappingCache = [];
public ToSpeckleSettingsManagerCivil3d(ISendConversionCache sendConversionCache)
{
_sendConversionCache = sendConversionCache;
}
public bool GetMappingToRevitCategories([NotNull] SenderModelCard modelCard)
{
var value = modelCard.Settings?.FirstOrDefault(s => s.Id == "mappingToRevitCategories")?.Value as bool?;
var returnValue = value != null && value.NotNull();
if (_revitCategoryMappingCache.TryGetValue(modelCard.ModelCardId.NotNull(), out var previousValue))
{
if (previousValue != returnValue)
{
EvictCacheForModelCard(modelCard);
}
}
_revitCategoryMappingCache[modelCard.ModelCardId] = returnValue;
return returnValue;
}
private void EvictCacheForModelCard(SenderModelCard modelCard)
{
var objectIds = modelCard.SendFilter != null ? modelCard.SendFilter.NotNull().SelectedObjectIds : [];
_sendConversionCache.EvictObjects(objectIds);
}
}
@@ -14,6 +14,8 @@
<Compile Include="$(MSBuildThisFileDirectory)HostApp\PropertySetBaker.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Operations\Receive\Civil3dHostObjectBuilder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\Civil3dRootObjectBuilder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\Settings\RevitCategoryMappingSetting.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\Settings\ToSpeckleSettingsManagerCivil3d.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bindings\Civil3dSendBinding.cs" />
</ItemGroup>
<ItemGroup>
@@ -21,5 +23,6 @@
<Folder Include="$(MSBuildThisFileDirectory)HostApp\" />
<Folder Include="$(MSBuildThisFileDirectory)Operations\Receive\" />
<Folder Include="$(MSBuildThisFileDirectory)Operations\Send\" />
<Folder Include="$(MSBuildThisFileDirectory)Operations\Send\Settings\" />
</ItemGroup>
</Project>
</Project>
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -281,15 +281,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -306,7 +305,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.converters.etabs21": {
@@ -356,18 +355,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
}
}
@@ -157,8 +157,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -230,15 +230,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -255,7 +254,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.converters.etabs22": {
@@ -305,18 +304,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
}
}
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -281,15 +281,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -306,7 +305,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.converters.navisworks2020": {
@@ -358,18 +357,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
},
".NETFramework,Version=v4.8/win-x64": {
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -281,15 +281,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -306,7 +305,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.converters.navisworks2021": {
@@ -358,18 +357,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
},
".NETFramework,Version=v4.8/win-x64": {
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -281,15 +281,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -306,7 +305,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.converters.navisworks2022": {
@@ -358,18 +357,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
},
".NETFramework,Version=v4.8/win-x64": {
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -281,15 +281,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -306,7 +305,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.converters.navisworks2023": {
@@ -358,18 +357,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
},
".NETFramework,Version=v4.8/win-x64": {
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -281,15 +281,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -306,7 +305,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.converters.navisworks2024": {
@@ -358,18 +357,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
},
".NETFramework,Version=v4.8/win-x64": {
@@ -177,8 +177,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -188,13 +188,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -287,15 +287,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -312,7 +311,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.converters.navisworks2025": {
@@ -358,18 +357,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
},
".NETFramework,Version=v4.8/win-x64": {
@@ -186,8 +186,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -197,13 +197,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -288,15 +288,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -313,7 +312,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.converters.navisworks2026": {
@@ -360,18 +359,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
},
".NETFramework,Version=v4.8/win-x64": {
@@ -6,22 +6,32 @@ using Speckle.Sdk;
namespace Speckle.Connector.Navisworks.Bindings;
public class NavisworksBasicConnectorBinding(
IBrowserBridge parent,
DocumentModelStore store,
ISpeckleApplication speckleApplication
) : IBasicConnectorBinding
public class NavisworksBasicConnectorBinding : IBasicConnectorBinding
{
public string Name => "baseBinding";
public IBrowserBridge Parent { get; } = parent;
public IBrowserBridge Parent { get; }
public BasicConnectorBindingCommands Commands { get; }
public BasicConnectorBindingCommands Commands { get; } = new(parent);
private readonly DocumentModelStore _store;
private readonly ISpeckleApplication _speckleApplication;
public string GetSourceApplicationName() => speckleApplication.Slug;
public NavisworksBasicConnectorBinding(
IBrowserBridge parent,
DocumentModelStore store,
ISpeckleApplication speckleApplication
)
{
Parent = parent;
_store = store;
_speckleApplication = speckleApplication;
Commands = new BasicConnectorBindingCommands(parent);
}
public string GetSourceApplicationVersion() => speckleApplication.HostApplicationVersion;
public string GetSourceApplicationName() => _speckleApplication.Slug;
public string GetConnectorVersion() => speckleApplication.SpeckleVersion;
public string GetSourceApplicationVersion() => _speckleApplication.HostApplicationVersion;
public string GetConnectorVersion() => _speckleApplication.SpeckleVersion;
public DocumentInfo? GetDocumentInfo() =>
NavisworksApp.ActiveDocument is null || NavisworksApp.ActiveDocument.Models.Count == 0
@@ -32,15 +42,15 @@ public class NavisworksBasicConnectorBinding(
NavisworksApp.ActiveDocument.GetHashCode().ToString()
);
public DocumentModelStore GetDocumentState() => store;
public DocumentModelStore GetDocumentState() => _store;
public void AddModel(ModelCard model) => store.AddModel(model);
public void AddModel(ModelCard model) => _store.AddModel(model);
public void UpdateModel(ModelCard model) => store.UpdateModel(model);
public void UpdateModel(ModelCard model) => _store.UpdateModel(model);
public void RemoveModel(ModelCard model) => store.RemoveModel(model);
public void RemoveModel(ModelCard model) => _store.RemoveModel(model);
public void RemoveModels(List<ModelCard> models) => store.RemoveModels(models);
public void RemoveModels(List<ModelCard> models) => _store.RemoveModels(models);
public Task HighlightModel(string modelCardId) => Task.CompletedTask;
@@ -1,6 +1,6 @@
using Speckle.Connector.Navisworks.Services;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Converter.Navisworks.Services;
namespace Speckle.Connector.Navisworks.Bindings;
@@ -12,7 +12,6 @@ using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Models.Card;
using Speckle.Connectors.DUI.Models.Card.SendFilter;
using Speckle.Connectors.DUI.Settings;
using Speckle.Converter.Navisworks.Services;
using Speckle.Converter.Navisworks.Settings;
using Speckle.Converters.Common;
using Speckle.Sdk.Common;
@@ -59,12 +58,12 @@ public class NavisworksSendBinding : ISendBinding
private static void SubscribeToNavisworksEvents() { }
// WARNING: Changes to filter behavior here must match everywhere filters are used, or saved sets won't update correctly
// Do not change the behavior/scope of this class on send binding unless make sure the behavior is same. Otherwise, we might not be able to update list of saved sets.
public List<ISendFilter> GetSendFilters() =>
[
new NavisworksSelectionFilter() { IsDefault = true },
new NavisworksSavedSetsFilter(new ConnectorElementSelectionService()),
new NavisworksSavedViewsFilter(new ConnectorElementSelectionService())
new NavisworksSavedSetsFilter(new ElementSelectionService()),
new NavisworksSavedViewsFilter(new ElementSelectionService())
];
public List<ICardSetting> GetSendSettings() =>
@@ -106,7 +105,6 @@ public class NavisworksSendBinding : ISendBinding
)
{
var selectedPaths = modelCard.SendFilter.NotNull().RefreshObjectIds();
var convertHiddenElementsSetting =
modelCard.Settings!.FirstOrDefault(s => s.Id == "convertHiddenElements")?.Value as bool? ?? false;
var message = convertHiddenElementsSetting
@@ -117,78 +115,30 @@ public class NavisworksSendBinding : ISendBinding
{
throw new SpeckleSendFilterException(message);
}
onOperationProgressed.Report(new CardProgress("Getting selection...", null));
await Task.CompletedTask;
int estimatedCapacity = selectedPaths.Count * 10;
var modelItems = new List<NAV.ModelItem>(estimatedCapacity);
var modelItems = new List<NAV.ModelItem>();
double count = 0;
foreach (var path in selectedPaths)
{
onOperationProgressed.Report(new CardProgress("Getting selection...", count / selectedPaths.Count));
await Task.CompletedTask;
var modelItem = _selectionService.GetModelItemFromPath(path);
var hasChildren = modelItem.Children.Any();
if (hasChildren)
{
int nodesVisited = 0;
int hiddenBranchesPruned = 0;
const int REPORT_INTERVAL = 1000;
void TraverseWithProgress(NAV.ModelItem node)
{
nodesVisited++;
if (nodesVisited % REPORT_INTERVAL == 0)
{
onOperationProgressed.Report(
new CardProgress(
$"Expanding tree: {nodesVisited} visited, {modelItems.Count} with geometry, {hiddenBranchesPruned} hidden",
null
)
);
Task.Delay(1).Wait();
}
if (!_selectionService.IsVisible(node))
{
hiddenBranchesPruned++;
return;
}
if (node.HasGeometry)
{
modelItems.Add(node);
}
foreach (var child in node.Children)
{
TraverseWithProgress(child);
}
}
TraverseWithProgress(modelItem);
}
else
{
if (modelItem.HasGeometry && _selectionService.IsVisible(modelItem))
{
modelItems.Add(modelItem);
}
}
modelItems.AddRange(_selectionService.GetGeometryNodes(modelItem).Where(_selectionService.IsVisible));
count++;
}
return modelItems.Count == 0 ? throw new SpeckleSendFilterException(message) : modelItems;
}
public void CancelSend(string modelCardId) => _cancellationManager.CancelOperation(modelCardId);
/// <summary>
/// Cancels all outstanding send operations for the current document.
/// This method is called when the active document changes, to ensure
/// that any in-progress send operations are properly canceled before
/// the new document is loaded.
/// </summary>
public void CancelAllSendOperations()
{
foreach (var modelCardId in _store.GetSenders().Select(m => m.ModelCardId))
@@ -15,7 +15,7 @@ using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Models.Card.SendFilter;
using Speckle.Connectors.DUI.WebView;
using Speckle.Converter.Navisworks.Constants.Registers;
using Speckle.Converter.Navisworks.Services;
using Speckle.Converter.Navisworks.Settings;
using Speckle.Converters.Common;
using Speckle.Sdk.Models.GraphTraversal;
@@ -53,6 +53,9 @@ public static class NavisworksConnectorServiceRegistration
serviceCollection.AddScoped<NavisworksMaterialUnpacker>();
serviceCollection.AddScoped<NavisworksColorUnpacker>();
// Register dual shared geometry stores for instancing pattern
serviceCollection.AddScoped<InstanceStoreManager>();
serviceCollection.AddSingleton<IAppIdleManager, NavisworksIdleManager>();
// Sending operations
@@ -61,9 +64,6 @@ public static class NavisworksConnectorServiceRegistration
serviceCollection.AddSingleton(DefaultTraversal.CreateTraversalFunc());
serviceCollection.AddSingleton<IOperationProgressManager, OperationProgressManager>();
// Registers and caches
serviceCollection.AddScoped<IInstanceFragmentRegistry, InstanceFragmentRegistry>();
// Register Intercom/interop
serviceCollection.AddSingleton<NavisworksDocumentModelStore>();
serviceCollection.AddSingleton<DocumentModelStore>(sp => sp.GetRequiredService<NavisworksDocumentModelStore>());
@@ -73,9 +73,6 @@ public static class NavisworksConnectorServiceRegistration
serviceCollection.AddScoped<ISendFilter, NavisworksSelectionFilter>();
serviceCollection.AddScoped<ISendFilter, NavisworksSavedSetsFilter>();
serviceCollection.AddScoped<ISendFilter, NavisworksSavedViewsFilter>();
serviceCollection.AddScoped<
Converter.Navisworks.Services.IElementSelectionService,
ConnectorElementSelectionService
>();
serviceCollection.AddScoped<IElementSelectionService, ElementSelectionService>();
}
}
@@ -1,12 +1,31 @@
namespace Speckle.Connector.Navisworks.Services;
using Speckle.InterfaceGenerator;
using static Speckle.Converter.Navisworks.Helpers.ElementSelectionHelper;
/// <summary>
/// Connector-specific element selection service that extends the converter's base implementation.
/// Inherits the cached visibility checking and path resolution from the converter layer.
/// </summary>
public class ConnectorElementSelectionService : Converter.Navisworks.Services.ElementSelectionService
namespace Speckle.Connector.Navisworks.Services;
[GenerateAutoInterface]
public class ElementSelectionService : IElementSelectionService
{
// This inherits all functionality from the converter's ElementSelectionService
// including cached IsVisible, GetModelItemPath, GetModelItemFromPath, and GetGeometryNodes
// Connector-specific extensions can be added here if needed in the future
private readonly Dictionary<Guid, bool> _visibleCache = new();
public string GetModelItemPath(NAV.ModelItem modelItem) => ResolveModelItemToIndexPath(modelItem);
public NAV.ModelItem GetModelItemFromPath(string path) => ResolveIndexPathToModelItem(path);
public bool IsVisible(NAV.ModelItem modelItem)
{
var key = modelItem.InstanceGuid;
if (_visibleCache.TryGetValue(key, out var isVisible))
{
return isVisible;
}
//same as ElementSelectionHelper.IsElementVisible
foreach (var item in modelItem.AncestorsAndSelf)
{
_visibleCache[item.InstanceGuid] = !item.IsHidden;
}
return _visibleCache[key];
}
public IEnumerable<NAV.ModelItem> GetGeometryNodes(NAV.ModelItem modelItem) => ResolveGeometryLeafNodes(modelItem);
}
@@ -1,6 +1,6 @@
using Microsoft.Extensions.Logging;
using Speckle.Connector.Navisworks.Services;
using Speckle.Converter.Navisworks.Helpers;
using Speckle.Converter.Navisworks.Services;
using Speckle.Converter.Navisworks.Settings;
using Speckle.Converters.Common;
using Speckle.Sdk;
@@ -130,20 +130,16 @@ public class NavisworksColorUnpacker(
var comSelection = ComBridge.ToInwOpSelection([modelItem]);
try
{
var paths = comSelection.Paths();
var pathsCollection = comSelection.Paths();
try
{
foreach (ComApi.InwOaPath path in paths)
foreach (ComApi.InwOaPath path in pathsCollection)
{
GC.KeepAlive(path);
var fragments = path.Fragments();
var fragmentsCollection = path.Fragments();
try
{
foreach (ComApi.InwOaFragment3 fragment in fragments)
foreach (ComApi.InwOaFragment3 fragment in fragmentsCollection.OfType<ComApi.InwOaFragment3>())
{
GC.KeepAlive(fragment);
fragment.GenerateSimplePrimitives(ComApi.nwEVertexProperty.eNORMAL, primitiveChecker);
if (primitiveChecker.HasTriangles)
@@ -154,9 +150,9 @@ public class NavisworksColorUnpacker(
}
finally
{
if (fragments != null)
if (fragmentsCollection != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(fragments);
System.Runtime.InteropServices.Marshal.ReleaseComObject(fragmentsCollection);
}
}
}
@@ -165,9 +161,9 @@ public class NavisworksColorUnpacker(
}
finally
{
if (paths != null)
if (pathsCollection != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(paths);
System.Runtime.InteropServices.Marshal.ReleaseComObject(pathsCollection);
}
}
}
@@ -120,6 +120,17 @@ public sealed class NavisworksDocumentEvents
}
}
private void UnsubscribeFromDocumentModelEvents(object _)
{
var activeDocument = NavisworksApp.ActiveDocument;
if (activeDocument != null)
{
UnsubscribeFromModelEvents(activeDocument);
}
_isSubscribed = false;
}
private void UnsubscribeFromModelEvents(NAV.Document document)
{
document.Models.CollectionChanged -= HandleDocumentModelCountChanged;
@@ -1,18 +1,22 @@
using Autodesk.Navisworks.Api.ComApi;
using Autodesk.Navisworks.Api.Interop.ComApi;
using Microsoft.Extensions.Logging;
using Speckle.Connector.Navisworks.Services;
using Speckle.Converter.Navisworks.Constants;
using Speckle.Converter.Navisworks.Helpers;
using Speckle.Converter.Navisworks.Services;
using Speckle.Converter.Navisworks.Settings;
using Speckle.Converter.Navisworks.ToSpeckle;
using Speckle.Converters.Common;
using Speckle.Objects.Other;
using Speckle.Sdk;
using static Speckle.Converter.Navisworks.Constants.MaterialConstants;
namespace Speckle.Connector.Navisworks.HostApp;
public class NavisworksMaterialUnpacker(
ILogger<NavisworksMaterialUnpacker> logger,
IConverterSettingsStore<NavisworksConversionSettings> converterSettings,
IElementSelectionService selectionService
IElementSelectionService selectionService,
GeometryToSpeckleConverter converter
)
{
private static T SelectByRepresentationMode<T>(
@@ -70,6 +74,66 @@ public class NavisworksMaterialUnpacker(
var navisworksObjectId = selectionService.GetModelItemPath(navisworksObject);
var finalId = mergedIds.TryGetValue(navisworksObjectId, out var mergedId) ? mergedId : navisworksObjectId;
string hashId = "";
try
{
var item = selectionService.GetModelItemFromPath(finalId);
var comSelection = ComApiBridge.ToInwOpSelection([item]);
try
{
var paths = comSelection.Paths();
try
{
if (paths.Count > 0)
{
var firstPath = paths.OfType<InwOaPath>().FirstOrDefault();
if (firstPath != null)
{
var fragments = firstPath.Fragments();
try
{
if (fragments.Count > 1)
{
var fragmentId = converter.GenerateFragmentId(paths);
hashId = $"{InstanceConstants.GEOMETRY_ID_PREFIX}{fragmentId}";
}
}
finally
{
if (fragments != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(fragments);
}
}
}
}
}
finally
{
if (paths != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(paths);
}
}
}
finally
{
if (comSelection != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(comSelection);
}
}
}
catch (Exception ex) when (!ex.IsFatal())
{ // If COM interop fails during hash generation, fall back to using finalId
logger.LogWarning(
ex,
"Failed to generate fragment hash ID for item {ItemId}, using finalId as fallback",
finalId
);
hashId = "";
}
var geometry = navisworksObject.Geometry;
var mode = converterSettings.Current.User.VisualRepresentationMode;
@@ -98,7 +162,7 @@ public class NavisworksMaterialUnpacker(
);
var materialName =
$"{DEFAULT_MATERIAL_NAME_PREFIX}{Math.Abs(ColorConverter.NavisworksColorToColor(renderColor).ToArgb())}";
$"{MaterialConstants.DEFAULT_MATERIAL_NAME_PREFIX}{Math.Abs(ColorConverter.NavisworksColorToColor(renderColor).ToArgb())}";
var itemCategory = navisworksObject.PropertyCategories.FindCategoryByDisplayName("Item");
if (itemCategory != null)
@@ -124,14 +188,14 @@ public class NavisworksMaterialUnpacker(
if (renderMaterialProxies.TryGetValue(renderMaterialId.ToString(), out RenderMaterialProxy? value))
{
value.objects.Add(finalId);
value.objects.Add(!string.IsNullOrEmpty(hashId) ? hashId : finalId);
}
else
{
renderMaterialProxies[renderMaterialId.ToString()] = new RenderMaterialProxy()
{
value = CreateRenderMaterial(materialName, renderTransparency, renderColor, renderMaterialId),
objects = [finalId]
objects = [!string.IsNullOrEmpty(hashId) ? hashId : finalId]
};
}
}
@@ -155,7 +219,9 @@ public class NavisworksMaterialUnpacker(
var speckleRenderMaterial = new RenderMaterial()
{
name = !string.IsNullOrEmpty(name) ? name : $"{DEFAULT_MATERIAL_NAME_PREFIX}{Math.Abs(color.ToArgb())}",
name = !string.IsNullOrEmpty(name)
? name
: $"{MaterialConstants.DEFAULT_MATERIAL_NAME_PREFIX}{Math.Abs(color.ToArgb())}",
opacity = 1 - transparency,
metalness = 0,
roughness = 1,
@@ -1,7 +1,7 @@
using Speckle.Connectors.DUI.Exceptions;
using Speckle.Connector.Navisworks.Services;
using Speckle.Connectors.DUI.Exceptions;
using Speckle.Connectors.DUI.Models.Card.SendFilter;
using Speckle.Connectors.DUI.Utils;
using Speckle.Converter.Navisworks.Services;
namespace Speckle.Connector.Navisworks.Operations.Send.Filters;
@@ -1,7 +1,7 @@
using Speckle.Connectors.DUI.Exceptions;
using Speckle.Connector.Navisworks.Services;
using Speckle.Connectors.DUI.Exceptions;
using Speckle.Connectors.DUI.Models.Card.SendFilter;
using Speckle.Connectors.DUI.Utils;
using Speckle.Converter.Navisworks.Services;
namespace Speckle.Connector.Navisworks.Operations.Send.Filters;
@@ -48,6 +48,8 @@ public class NavisworksSavedViewsFilter : DiscriminatedObject, ISendFilterSelect
return objectIds;
}
var savedViews = NavisworksApp.ActiveDocument.SavedViewpoints;
foreach (var savedViewItem in SelectedItems.Select(item => ResolveSavedView(item.Id)))
{
// Get the visible elements in the saved view.
@@ -80,12 +82,12 @@ public class NavisworksSavedViewsFilter : DiscriminatedObject, ISendFilterSelect
{
var objectIds = new List<string>();
// THIS IS COMMENTED OUT AS IT IS LEGACY DEFENSIVE BEHAVIOR - DISCUSSION REQUIRED
// THIS IS COMMENTED OUT AS IT IS LEGACY DEFENSIVE BEHAVIOUR - DISCUSSION REQUIRED
// if (!savedView.ContainsVisibilityOverrides)
// {
// // We check this again as the view settings may have changed in the saved card.
// // If the saved view does not contain visibility overrides, this is effectively everything in the model.
// // This will need to be the documented behavior.
// // This will need to be the documented behaviour.
// throw new SpeckleSendFilterException(
// "Saved view does not contain visibility overrides. This would effectively publish everything in the model."
// );
@@ -152,7 +154,7 @@ public class NavisworksSavedViewsFilter : DiscriminatedObject, ISendFilterSelect
switch (item)
{
// case NAV.SavedViewpoint { ContainsVisibilityOverrides: false }:
// Legacy defensive behavior: skip viewpoints without visibility overrides.
// Legacy defensive behaviour: skip viewpoints without visibility overrides.
// Essentially, send everything, or whatever the current view state for hidden elements is.
// break;
case NAV.SavedViewpointAnimationCut:
@@ -1,4 +1,4 @@
using static Speckle.Converter.Navisworks.Constants.PathConstants;
using Speckle.Converter.Navisworks.Constants;
namespace Speckle.Connector.Navisworks.Operations.Send.Filters;
@@ -15,6 +15,6 @@ public static class SavedItemHelpers
current = current.Parent;
}
return string.Join(SET_SEPARATOR, pathParts);
return string.Join(PathConstants.SET_SEPARATOR, pathParts);
}
}
@@ -1,5 +1,5 @@
using Speckle.Connector.Navisworks.Services;
using static Speckle.Converter.Navisworks.Constants.PathConstants;
using Speckle.Converter.Navisworks.Constants;
namespace Speckle.Connector.Navisworks.Operations.Send;
@@ -10,29 +10,29 @@ public static class GeometryNodeMerger
{
/// <summary>
/// Groups sibling geometry nodes based on material properties for merging.
/// This only merges nodes that share the same parent and have identical material properties.
/// Only merges nodes that share the same parent and have identical material properties.
/// </summary>
/// <param name="nodes">The collection of ModelItems to process</param>
/// <returns>Dictionary mapping parent paths (with material signature suffix) to their mergeable child nodes</returns>
public static Dictionary<string, List<NAV.ModelItem>> GroupSiblingGeometryNodes(IReadOnlyList<NAV.ModelItem> nodes)
{
var selectionService = new ConnectorElementSelectionService();
var selectionService = new ElementSelectionService();
// Group nameless geometry nodes by parent path and material signature
var mergeableGroups = nodes
.Where(node => node.HasGeometry && string.IsNullOrEmpty(node.DisplayName)) // Only anonymous geometry nodes
.GroupBy(node =>
{
// Get the parent path
// Get parent path
var path = selectionService.GetModelItemPath(node);
var lastSeparatorIndex = path.LastIndexOf(SEPARATOR);
var lastSeparatorIndex = path.LastIndexOf(PathConstants.SEPARATOR);
var parentPath = lastSeparatorIndex == -1 ? path : path[..lastSeparatorIndex];
// Generate material signature
string signature = GenerateSignature(node);
// Combine parent path with signature
return $"{parentPath}{MATERIAL_SEPARATOR}{signature}";
return $"{parentPath}{PathConstants.MATERIAL_SEPARATOR}{signature}";
})
.Where(group => group.Count() > 1) // Only include groups with multiple children
.ToDictionary(group => group.Key, group => group.ToList());
@@ -95,7 +95,7 @@ public static class GeometryNodeMerger
// Build a consistent string representation of all properties
var hashInput = new System.Text.StringBuilder();
// Sort keys to ensure a consistent order
// Sort keys to ensure consistent order
var sortedKeys = properties.Keys.OrderBy(k => k).ToList();
foreach (var key in sortedKeys)
@@ -139,7 +139,7 @@ public static class GeometryNodeMerger
/// </summary>
private static string GetMaterialName(NAV.ModelItem node)
{
// Check the Item category for material name
// Check Item category for material name
var itemCategory = node.PropertyCategories.FindCategoryByDisplayName("Item");
if (itemCategory != null)
{
@@ -1,8 +1,8 @@
using Speckle.Converter.Navisworks.Services;
using Speckle.Connector.Navisworks.Services;
using Speckle.Converter.Navisworks.Constants;
using Speckle.Converters.Common;
using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Collections;
using static Speckle.Converter.Navisworks.Constants.PathConstants;
namespace Speckle.Connector.Navisworks.Operations.Send;
@@ -59,8 +59,8 @@ public class NavisworksHierarchyBuilder
allPaths.Sort(
(a, b) =>
{
var depthA = a.Count(c => c == SEPARATOR);
var depthB = b.Count(c => c == SEPARATOR);
var depthA = a.Count(c => c == PathConstants.SEPARATOR);
var depthB = b.Count(c => c == PathConstants.SEPARATOR);
return depthB.CompareTo(depthA); // <- Sort in ascending order of path length
}
);
@@ -126,7 +126,7 @@ public class NavisworksHierarchyBuilder
private static string GetParentPath(string path)
{
var idx = path.LastIndexOf(SEPARATOR);
var idx = path.LastIndexOf(PathConstants.SEPARATOR);
return idx == -1 ? string.Empty : path[..idx];
}
@@ -1,5 +1,6 @@
using Microsoft.Extensions.Logging;
using Speckle.Connector.Navisworks.HostApp;
using Speckle.Connector.Navisworks.Services;
using Speckle.Connectors.Common.Builders;
using Speckle.Connectors.Common.Caching;
using Speckle.Connectors.Common.Conversion;
@@ -13,10 +14,7 @@ using Speckle.Sdk;
using Speckle.Sdk.Logging;
using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Collections;
using Speckle.Sdk.Models.Instances;
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;
@@ -28,15 +26,14 @@ public class NavisworksRootObjectBuilder(
ISdkActivityFactory activityFactory,
NavisworksMaterialUnpacker materialUnpacker,
NavisworksColorUnpacker colorUnpacker,
Speckle.Converter.Navisworks.Constants.Registers.IInstanceFragmentRegistry instanceRegistry,
IElementSelectionService elementSelectionService,
IUiUnitsCache uiUnitsCache
IUiUnitsCache uiUnitsCache,
InstanceStoreManager instanceStoreManager
) : IRootObjectBuilder<NAV.ModelItem>
{
#pragma warning disable CA1823
#pragma warning restore CA1823
private bool SkipNodeMerging { get; set; }
private bool DisableGroupingForInstanceTesting { get; set; }
internal NavisworksConversionSettings GetCurrentSettings() => converterSettings.Current;
public async Task<RootObjectBuilderResult> Build(
IReadOnlyList<NAV.ModelItem> navisworksModelItems,
@@ -46,14 +43,14 @@ public class NavisworksRootObjectBuilder(
)
{
#if DEBUG
SkipNodeMerging = false;
DisableGroupingForInstanceTesting = false;
SkipNodeMerging = true;
#endif
using var activity = activityFactory.Start("Build");
ValidateInputs(navisworksModelItems, projectId, onOperationProgressed);
var rootCollection = InitializeRootCollection();
(Dictionary<string, Base?> convertedElements, List<SendConversionResult> conversionResults) =
await ConvertModelItemsAsync(navisworksModelItems, projectId, onOperationProgressed, cancellationToken);
@@ -61,17 +58,30 @@ public class NavisworksRootObjectBuilder(
var groupedNodes = SkipNodeMerging ? [] : GroupSiblingGeometryNodes(navisworksModelItems);
var finalElements = BuildFinalElements(convertedElements, groupedNodes);
List<Base> geometryDefinitions = instanceStoreManager.GetGeometryDefinitions();
await AddProxiesToCollection(rootCollection, navisworksModelItems, groupedNodes);
AddInstanceDefinitionsToCollection(rootCollection, ref finalElements);
int finalInstanceProxyCount = CountInstanceProxiesRecursive(finalElements);
logger.LogInformation(
"Final output contains {count} InstanceProxy objects in displayValues",
finalInstanceProxyCount
);
var geometryDefinitionsCollection = new Collection
{
name = "Geometry Definitions",
["units"] = converterSettings.Current.Derived.SpeckleUnits,
elements = geometryDefinitions
};
var mainElementsCollection = new Collection
{
name = rootCollection.name,
["units"] = converterSettings.Current.Derived.SpeckleUnits,
elements = finalElements
};
rootCollection.elements = [mainElementsCollection];
if (geometryDefinitions.Count > 0)
{
rootCollection.elements.Add(geometryDefinitionsCollection);
}
rootCollection.elements = finalElements;
return new RootObjectBuilderResult(rootCollection, conversionResults);
}
@@ -117,32 +127,16 @@ public class NavisworksRootObjectBuilder(
var convertedBases = new Dictionary<string, Base?>();
int processedCount = 0;
int totalCount = navisworksModelItems.Count;
int instanceProxyCount = 0;
foreach (var item in navisworksModelItems)
{
cancellationToken.ThrowIfCancellationRequested();
var converted = ConvertNavisworksItem(item, convertedBases, projectId);
results.Add(converted);
if (
converted.Status == Status.SUCCESS
&& convertedBases.TryGetValue(elementSelectionService.GetModelItemPath(item), out var convertedBase)
&& convertedBase?["displayValue"] is List<Base> displayValues
)
{
instanceProxyCount += displayValues.Count(dv => dv.GetType().Name == "InstanceProxy");
}
processedCount++;
onOperationProgressed.Report(new CardProgress("Converting", (double)processedCount / totalCount));
}
logger.LogInformation(
"Converted {total} items, found {instanceProxies} InstanceProxy objects",
totalCount,
instanceProxyCount
);
return Task.FromResult((convertedBases, results));
}
@@ -161,24 +155,10 @@ public class NavisworksRootObjectBuilder(
{
var finalElements = new List<Base>();
var processedPaths = new HashSet<string>();
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");
}
AddGroupedElements(finalElements, convertedBases, groupedNodes, processedPaths);
if (converterSettings.Current.User.PreserveModelHierarchy)
{
logger.LogInformation("Building hierarchy (PreserveModelHierarchy=true)");
var hierarchyBuilder = new NavisworksHierarchyBuilder(
convertedBases,
rootToSpeckleConverter,
@@ -188,10 +168,7 @@ public class NavisworksRootObjectBuilder(
return hierarchyBuilder.BuildHierarchy();
}
logger.LogInformation("Adding remaining elements (flat mode)");
AddRemainingElements(finalElements, convertedBases, processedPaths);
logger.LogInformation("Final elements count: {count}", finalElements.Count);
return finalElements;
}
@@ -204,7 +181,7 @@ public class NavisworksRootObjectBuilder(
{
foreach (var group in groupedNodes)
{
var siblingBases = new List<Base>(group.Value.Count);
var siblingBases = new List<Base>();
foreach (var itemPath in group.Value.Select(elementSelectionService.GetModelItemPath))
{
processedPaths.Add(itemPath);
@@ -259,29 +236,10 @@ public class NavisworksRootObjectBuilder(
string cleanParentPath = ElementSelectionHelper.GetCleanPath(groupKey);
(string name, string path) = GetElementNameAndPath(cleanParentPath);
int estimatedCapacity = siblingBases.Sum(b => (b["displayValue"] as List<Base>)?.Count ?? 0);
var displayValues = new List<Base>(estimatedCapacity);
displayValues.AddRange(
siblingBases
.Where(sibling => sibling["displayValue"] is List<Base>)
.SelectMany(sibling => (List<Base>)sibling["displayValue"]!)
);
var instanceProxyCount = displayValues.Count(dv => dv.GetType().Name == "InstanceProxy");
if (instanceProxyCount > 0)
{
logger.LogDebug(
"Group {groupKey} merging {siblings} siblings with {proxies} InstanceProxy objects",
groupKey,
siblingBases.Count,
instanceProxyCount
);
}
return new NavisworksObject
{
name = name,
displayValue = displayValues,
displayValue = siblingBases.SelectMany(b => b["displayValue"] as List<Base> ?? []).ToList(),
properties = siblingBases.First()["properties"] as Dictionary<string, object?> ?? [],
units = converterSettings.Current.Derived.SpeckleUnits,
applicationId = groupKey,
@@ -322,100 +280,25 @@ public class NavisworksRootObjectBuilder(
var renderMaterials = materialUnpacker.UnpackRenderMaterial(navisworksModelItems, groupedNodes);
if (renderMaterials.Count > 0)
{
rootCollection[RENDER_MATERIAL] = renderMaterials;
rootCollection[ProxyKeys.RENDER_MATERIAL] = renderMaterials;
}
var colors = colorUnpacker.UnpackColor(navisworksModelItems, groupedNodes);
if (colors.Count > 0)
{
rootCollection[COLOR] = colors;
rootCollection[ProxyKeys.COLOR] = colors;
}
var instanceDefinitionProxies = instanceStoreManager.GetInstanceDefinitionProxies();
if (instanceDefinitionProxies.Count > 0)
{
rootCollection[ProxyKeys.INSTANCE_DEFINITION] = instanceDefinitionProxies.ToList();
}
return Task.CompletedTask;
}
private void AddInstanceDefinitionsToCollection(Collection rootCollection, ref List<Base> finalElements)
{
using var _ = activityFactory.Start("BuildInstanceDefinitions");
// Get all definition geometries from the registry
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);
if (allDefinitions.Count > 100)
{
logger.LogWarning(
"Large number of definition groups ({count}) detected - this may indicate instance grouping is not working effectively",
allDefinitions.Count
);
}
var instanceDefinitionProxies = new List<InstanceDefinitionProxy>(allDefinitions.Count);
int estimatedGeometryCount = allDefinitions.Sum(kvp => kvp.Value.Count);
var allDefinitionGeometries = new List<Base>(estimatedGeometryCount);
foreach (var kvp in allDefinitions)
{
var groupKey = kvp.Key;
var geometries = kvp.Value;
var groupKeyHash = groupKey.ToHashString();
var defProxy = new InstanceDefinitionProxy
{
name = $"Shared Geometry {groupKeyHash}",
objects = geometries.Select(g => g.applicationId ?? "").Where(id => !string.IsNullOrEmpty(id)).ToList(),
applicationId = $"{DEFINITION_ID_PREFIX}{groupKeyHash}",
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 int CountInstanceProxiesRecursive(List<Base> elements)
{
int count = 0;
foreach (var element in elements)
{
if (element["displayValue"] is List<Base> displayValues)
{
count += displayValues.Count(dv => dv.GetType().Name == "InstanceProxy");
}
if (element is Collection { elements: not null } collection)
{
count += CountInstanceProxiesRecursive(collection.elements);
}
}
return count;
}
private SendConversionResult ConvertNavisworksItem(
NAV.ModelItem navisworksItem,
Dictionary<string, Base?> convertedBases,
@@ -1,4 +1,5 @@
using Speckle.Connectors.Common.Caching;
using System.Diagnostics.CodeAnalysis;
using Speckle.Connectors.Common.Caching;
using Speckle.Connectors.DUI.Models.Card;
using Speckle.Converter.Navisworks.Settings;
using Speckle.InterfaceGenerator;
@@ -7,106 +8,158 @@ using Speckle.Sdk.Common;
namespace Speckle.Connector.Navisworks.Operations.Send.Settings;
[GenerateAutoInterface]
public class ToSpeckleSettingsManagerNavisworks(ISendConversionCache sendConversionCache)
: IToSpeckleSettingsManagerNavisworks
public class ToSpeckleSettingsManagerNavisworks : IToSpeckleSettingsManagerNavisworks
{
// cache invalidation process run with ModelCardId since the settings are model-specific
private readonly ISendConversionCache _sendConversionCache;
// cache invalidation process run with ModelCardId since the settings are model specific
private readonly Dictionary<string, RepresentationMode> _visualRepresentationCache = [];
private readonly Dictionary<string, OriginMode> _originModeCache = [];
private readonly Dictionary<string, bool> _convertHiddenElementsCache = [];
private readonly Dictionary<string, bool> _includeInternalPropertiesCache = [];
private readonly Dictionary<string, bool> _preserveModelHierarchyCache = [];
private readonly Dictionary<string, bool> _revitCategoryMappingCache = [];
private readonly Dictionary<string, bool?> _convertHiddenElementsCache = [];
private readonly Dictionary<string, bool?> _includeInternalPropertiesCache = [];
private readonly Dictionary<string, bool?> _preserveModelHierarchyCache = [];
private readonly Dictionary<string, bool?> _revitCategoryMappingCache = [];
/// <summary>
/// Generic helper to get a setting value with caching and cache invalidation.
/// </summary>
private T GetCachedSetting<T>(
SenderModelCard modelCard,
string settingId,
Dictionary<string, T> cache,
Func<object?, T> valueExtractor,
T defaultValue
)
public ToSpeckleSettingsManagerNavisworks(ISendConversionCache sendConversionCache)
{
_sendConversionCache = sendConversionCache;
}
public RepresentationMode GetVisualRepresentationMode(SenderModelCard modelCard)
{
if (modelCard == null)
{
throw new ArgumentNullException(nameof(modelCard));
}
var settingValue = modelCard.Settings?.FirstOrDefault(s => s.Id == settingId)?.Value;
var returnValue = settingValue != null ? valueExtractor(settingValue) : defaultValue;
var representationString = modelCard.Settings?.First(s => s.Id == "visualRepresentation").Value as string;
if (
cache.TryGetValue(modelCard.ModelCardId.NotNull(), out var previousValue)
&& !EqualityComparer<T>.Default.Equals(previousValue, returnValue)
representationString is not null
&& VisualRepresentationSetting.VisualRepresentationMap.TryGetValue(
representationString,
out RepresentationMode representation
)
)
{
if (_visualRepresentationCache.TryGetValue(modelCard.ModelCardId.NotNull(), out RepresentationMode previousType))
{
if (previousType != representation)
{
EvictCacheForModelCard(modelCard);
}
}
_visualRepresentationCache[modelCard.ModelCardId.NotNull()] = representation;
return representation;
}
throw new ArgumentException($"Invalid visual representation value: {representationString}");
}
public OriginMode GetOriginMode(SenderModelCard modelCard)
{
if (modelCard == null)
{
throw new ArgumentNullException(nameof(modelCard));
}
var originString = modelCard.Settings?.FirstOrDefault(s => s.Id == "originMode")?.Value as string;
if (!OriginModeSetting.OriginModeMap.TryGetValue(originString ?? string.Empty, out var origin))
{
return OriginMode.ModelOrigin; // Default to ModelOrigin if not specified or invalid
}
if (_originModeCache.TryGetValue(modelCard.ModelCardId.NotNull(), out var previousType) && previousType != origin)
{
EvictCacheForModelCard(modelCard);
}
cache[modelCard.ModelCardId.NotNull()] = returnValue;
_originModeCache[modelCard.ModelCardId.NotNull()] = origin;
return origin;
}
public bool GetMappingToRevitCategories(SenderModelCard modelCard)
{
if (modelCard == null)
{
throw new ArgumentNullException(nameof(modelCard));
}
var value = modelCard.Settings?.FirstOrDefault(s => s.Id == "mappingToRevitCategories")?.Value as bool?;
var returnValue = value != null && value.NotNull();
if (_revitCategoryMappingCache.TryGetValue(modelCard.ModelCardId.NotNull(), out var previousValue))
{
if (previousValue != returnValue)
{
EvictCacheForModelCard(modelCard);
}
}
_revitCategoryMappingCache[modelCard.ModelCardId] = returnValue;
return returnValue;
}
public RepresentationMode GetVisualRepresentationMode(SenderModelCard modelCard) =>
GetCachedSetting(
modelCard,
"visualRepresentation",
_visualRepresentationCache,
value =>
public bool GetConvertHiddenElements(SenderModelCard modelCard)
{
if (modelCard == null)
{
throw new ArgumentNullException(nameof(modelCard));
}
var value = modelCard.Settings?.FirstOrDefault(s => s.Id == "convertHiddenElements")?.Value as bool?;
var returnValue = value != null && value.NotNull();
if (_convertHiddenElementsCache.TryGetValue(modelCard.ModelCardId.NotNull(), out var previousValue))
{
if (previousValue != returnValue)
{
var representationString = value as string;
return
representationString is not null
&& VisualRepresentationSetting.VisualRepresentationMap.TryGetValue(
representationString,
out RepresentationMode representation
)
? representation
: throw new ArgumentException($"Invalid visual representation value: {representationString}");
},
RepresentationMode.Active // default value if setting not found
);
EvictCacheForModelCard(modelCard);
}
}
public OriginMode GetOriginMode(SenderModelCard modelCard) =>
GetCachedSetting(
modelCard,
"originMode",
_originModeCache,
value =>
_convertHiddenElementsCache[modelCard.ModelCardId] = returnValue;
return returnValue;
}
public bool GetIncludeInternalProperties([NotNull] SenderModelCard modelCard)
{
var value = modelCard.Settings?.FirstOrDefault(s => s.Id == "includeInternalProperties")?.Value as bool?;
var returnValue = value != null && value.NotNull();
if (_includeInternalPropertiesCache.TryGetValue(modelCard.ModelCardId.NotNull(), out var previousValue))
{
if (previousValue != returnValue)
{
var originString = value as string;
if (OriginModeSetting.OriginModeMap.TryGetValue(originString ?? string.Empty, out var origin))
{
return origin;
}
return OriginMode.ModelOrigin;
},
OriginMode.ModelOrigin
);
EvictCacheForModelCard(modelCard);
}
}
public bool GetMappingToRevitCategories(SenderModelCard modelCard) =>
GetCachedSetting(modelCard, "mappingToRevitCategories", _revitCategoryMappingCache, value => value is true, false);
_includeInternalPropertiesCache[modelCard.ModelCardId] = returnValue;
return returnValue;
}
public bool GetConvertHiddenElements(SenderModelCard modelCard) =>
GetCachedSetting(modelCard, "convertHiddenElements", _convertHiddenElementsCache, value => value is true, false);
public bool GetPreserveModelHierarchy([NotNull] SenderModelCard modelCard)
{
var value = modelCard.Settings?.FirstOrDefault(s => s.Id == "preserveModelHierarchy")?.Value as bool?;
public bool GetIncludeInternalProperties(SenderModelCard modelCard) =>
GetCachedSetting(
modelCard,
"includeInternalProperties",
_includeInternalPropertiesCache,
value => value is true,
false
);
var returnValue = value != null && value.NotNull();
if (_preserveModelHierarchyCache.TryGetValue(modelCard.ModelCardId.NotNull(), out var previousValue))
{
if (previousValue != returnValue)
{
EvictCacheForModelCard(modelCard);
}
}
public bool GetPreserveModelHierarchy(SenderModelCard modelCard) =>
GetCachedSetting(modelCard, "preserveModelHierarchy", _preserveModelHierarchyCache, value => value is true, false);
_preserveModelHierarchyCache[modelCard.ModelCardId] = returnValue;
return returnValue;
}
private void EvictCacheForModelCard(SenderModelCard modelCard)
{
var objectIds = modelCard.SendFilter != null ? modelCard.SendFilter.NotNull().SelectedObjectIds : [];
sendConversionCache.EvictObjects(objectIds);
_sendConversionCache.EvictObjects(objectIds);
}
}
@@ -14,7 +14,7 @@ public static class SpeckleV3Tool
public const string RIBBON_STRINGS = "NavisworksRibbon.name";
public const string PLUGIN_SUFFIX = ".Speckle";
public static Sdk.Application App =>
public static Speckle.Sdk.Application App =>
#if NAVIS
HostApplications.Navisworks;
#else
@@ -193,8 +193,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -204,13 +204,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -303,15 +303,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.logging": {
@@ -327,7 +326,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.converters.revit2022": {
@@ -372,11 +371,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"Speckle.Revit.API": {
@@ -384,12 +383,6 @@
"requested": "[2023.0.0, )",
"resolved": "2022.0.2.1",
"contentHash": "IrLN4WyI2ix+g3zCpo7sX8zNB3FrtrdQ3E2RpceGVPNG00v8OfD+Kei7o1bn1u/ML46iBYRAr/JcsLbwfUQsBw=="
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
}
}
@@ -193,8 +193,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -204,13 +204,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -303,15 +303,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.logging": {
@@ -327,7 +326,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.converters.revit2023": {
@@ -372,11 +371,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"Speckle.Revit.API": {
@@ -384,12 +383,6 @@
"requested": "[2023.0.0, )",
"resolved": "2023.0.0",
"contentHash": "tq40eD7psgTbV+epNouYyqfo6+hEi7FmXZqcxEOsAV7zfYyWhL6Rt3vmojkWGNuerGbH6oRI6KIIxrnlCNb8Hw=="
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
}
}
@@ -193,8 +193,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -204,13 +204,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -303,15 +303,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.logging": {
@@ -327,7 +326,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.converters.revit2024": {
@@ -372,11 +371,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"Speckle.Revit.API": {
@@ -384,12 +383,6 @@
"requested": "[2023.0.0, )",
"resolved": "2024.0.0",
"contentHash": "a4dsvZ00ocvzTgCD6dUdydf0jIZDVcDhs6dUX9cv+y3aTDbU8rmzhYXWt8sThedIG+IPSVa0vHmAH9pKiJL3SQ=="
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
}
}
@@ -173,8 +173,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -246,15 +246,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.logging": {
@@ -270,7 +269,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.converters.revit2025": {
@@ -315,11 +314,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"Speckle.Revit.API": {
@@ -327,12 +326,6 @@
"requested": "[2023.0.0, )",
"resolved": "2025.0.0",
"contentHash": "Hwf/3Ydc7KxvjgD9pSZKLSJRsFTsxYg95YyTm6f43hcsGjmk49GsLFQt921Z9OcvUVewOggQHcmBgti+P2EPHw=="
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
},
"net8.0-windows7.0/win-x64": {
@@ -3,15 +3,17 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
xmlns:dui="clr-namespace:Speckle.Connectors.DUI;assembly=Speckle.Connectors.DUI"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<!-- WebView2 is created lazily -->
<Border Name="BrowserContainer" Background="White">
<TextBlock Name="LoadingText"
Text="Loading Speckle..."
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="14"
Foreground="Gray" />
</Border>
<UserControl.Resources>
<wv2:CoreWebView2CreationProperties x:Key="EvergreenWebView2CreationProperties" UserDataFolder="C:\temp" />
</UserControl.Resources>
<DockPanel>
<wv2:WebView2
CreationProperties="{StaticResource EvergreenWebView2CreationProperties}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Name="Browser" Grid.Row="0" Source="{x:Static dui:Url.Netlify}" />
</DockPanel>
</UserControl>
@@ -2,8 +2,6 @@ using System.Windows.Controls;
using System.Windows.Threading;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.Wpf;
using Speckle.Connectors.DUI;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.Revit.Plugin;
@@ -14,10 +12,6 @@ public sealed partial class RevitControlWebView : UserControl, IBrowserScriptExe
{
private readonly IServiceProvider _serviceProvider;
private readonly IRevitTask _revitTask;
#pragma warning disable CA2213
private WebView2? _browser;
#pragma warning restore CA2213
private bool _isInitializing;
public RevitControlWebView(IServiceProvider serviceProvider, IRevitTask revitTask)
{
@@ -25,61 +19,35 @@ public sealed partial class RevitControlWebView : UserControl, IBrowserScriptExe
_revitTask = revitTask;
InitializeComponent();
// Delay WebView2 creation until the panel is actually visible
// This avoids conflicts with other plugins (like pyRevit) during startup
IsVisibleChanged += OnIsVisibleChanged;
}
private void OnIsVisibleChanged(object sender, System.Windows.DependencyPropertyChangedEventArgs e)
{
if (e.NewValue is true && _browser == null && !_isInitializing)
{
_isInitializing = true;
Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, CreateWebView2);
}
}
private void CreateWebView2()
{
_browser = new WebView2
{
CreationProperties = new CoreWebView2CreationProperties { UserDataFolder = "C:\\temp" },
HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch,
VerticalAlignment = System.Windows.VerticalAlignment.Stretch,
Source = Url.Netlify
};
_browser.CoreWebView2InitializationCompleted += (sender, args) =>
Browser.CoreWebView2InitializationCompleted += (sender, args) =>
_serviceProvider
.GetRequiredService<ITopLevelExceptionHandler>()
.CatchUnhandled(() => OnInitialized(sender, args));
BrowserContainer.Child = _browser;
}
public bool IsBrowserInitialized => _browser?.IsInitialized ?? false;
public bool IsBrowserInitialized => Browser.IsInitialized;
public object BrowserElement => _browser!;
public object BrowserElement => Browser;
public void ExecuteScript(string script)
{
if (_browser == null || !_browser.IsInitialized)
if (!Browser.IsInitialized)
{
throw new InvalidOperationException("Failed to execute script, Webview2 is not initialized yet.");
}
_revitTask.Run(() => _browser.ExecuteScriptAsync(script));
_revitTask.Run(() => Browser.ExecuteScriptAsync(script));
}
public void SendProgress(string script)
{
if (_browser == null || !_browser.IsInitialized)
if (!Browser.IsInitialized)
{
throw new InvalidOperationException("Failed to execute script, Webview2 is not initialized yet.");
}
//always invoke even on the main thread because it's better somehow
_browser.Dispatcher.Invoke(
Browser.Dispatcher.Invoke(
//fire and forget
() => _browser.ExecuteScriptAsync(script),
() => Browser.ExecuteScriptAsync(script),
DispatcherPriority.Background
);
}
@@ -106,18 +74,11 @@ public sealed partial class RevitControlWebView : UserControl, IBrowserScriptExe
private void SetupBinding(IBinding binding)
{
binding.Parent.AssociateWithBinding(binding);
_browser!.CoreWebView2.AddHostObjectToScript(binding.Name, binding.Parent);
Browser.CoreWebView2.AddHostObjectToScript(binding.Name, binding.Parent);
}
public void ShowDevTools() => _browser?.CoreWebView2?.OpenDevToolsWindow();
public void ShowDevTools() => Browser.CoreWebView2.OpenDevToolsWindow();
//https://github.com/MicrosoftEdge/WebView2Feedback/issues/2161
public void Dispose()
{
if (_browser != null)
{
_browser.Dispatcher.Invoke(() => _browser.Dispose(), DispatcherPriority.Send);
_browser = null;
}
}
public void Dispose() => Browser.Dispatcher.Invoke(() => Browser.Dispose(), DispatcherPriority.Send);
}
@@ -166,8 +166,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -239,15 +239,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.logging": {
@@ -263,7 +262,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.converters.revit2026": {
@@ -299,11 +298,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"Speckle.Revit.API": {
@@ -311,12 +310,6 @@
"requested": "[2023.0.0, )",
"resolved": "2026.0.0",
"contentHash": "SiqqKbF1pXyZWXZhAl2JhjYhTt7RiYO5JaQrAjq+OlleAjT4zatwAp/DnTwQspFbP7UZr3b2Ed2kuWNN0ZFelw=="
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
},
"net8.0-windows7.0/win-x64": {
@@ -42,17 +42,6 @@ public partial class CefSharpPanel : Page, Autodesk.Revit.UI.IDockablePaneProvid
}
}
public Task ExecuteScriptAsyncMethod(string script, CancellationToken cancellationToken)
{
Browser.Dispatcher.Invoke(
() => Browser.ExecuteScriptAsync(script),
DispatcherPriority.Background,
cancellationToken
);
return Task.CompletedTask;
}
public void SendProgress(string script) => ExecuteScript(script);
public bool IsBrowserInitialized => Browser.IsBrowserInitialized;
@@ -24,7 +24,7 @@ namespace Speckle.Connectors.Revit.Bindings;
internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
{
private readonly RevitIdleManager _revitIdleManager;
private readonly IAppIdleManager _idleManager;
private readonly RevitContext _revitContext;
private readonly DocumentModelStore _store;
private readonly ICancellationManager _cancellationManager;
@@ -38,9 +38,6 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
private readonly LinkedModelHandler _linkedModelHandler;
private readonly IThreadContext _threadContext;
private readonly ISendOperationManagerFactory _sendOperationManagerFactory;
private bool _isDocChangedSubscribed;
private EventHandler<Autodesk.Revit.DB.Events.DocumentChangedEventArgs>? _documentChangedHandler;
private readonly ConnectorConfig _config;
/// <summary>
/// Used internally to aggregate the changed objects' id. Note we're using a concurrent dictionary here as the expiry check method is not thread safe, and this was causing problems. See:
@@ -51,7 +48,7 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
private ConcurrentHashSet<ElementId> ChangedObjectIds { get; set; } = new();
public RevitSendBinding(
RevitIdleManager revitIdleManager,
IAppIdleManager idleManager,
RevitContext revitContext,
DocumentModelStore store,
ICancellationManager cancellationManager,
@@ -65,12 +62,11 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
LinkedModelHandler linkedModelHandler,
IThreadContext threadContext,
IRevitTask revitTask,
ISendOperationManagerFactory sendOperationManagerFactory,
IConfigStore configStore
ISendOperationManagerFactory sendOperationManagerFactory
)
: base("sendBinding", bridge)
{
_revitIdleManager = revitIdleManager;
_idleManager = idleManager;
_revitContext = revitContext;
_store = store;
_cancellationManager = cancellationManager;
@@ -83,7 +79,6 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
_linkedModelHandler = linkedModelHandler;
_threadContext = threadContext;
_sendOperationManagerFactory = sendOperationManagerFactory;
_config = configStore.GetConnectorConfig();
Commands = new SendBindingUICommands(bridge);
// TODO expiry events
@@ -91,58 +86,12 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
revitTask.Run(() =>
{
// revitContext.UIApplication.NotNull().Application.DocumentChanged += (_, e) =>
// _topLevelExceptionHandler.CatchUnhandled(() => DocChangeHandler(e));
_documentChangedHandler = (_, e) => _topLevelExceptionHandler.CatchUnhandled(() => DocChangeHandler(e));
_store.ModelCardsChanged += (_, e) => OnModelCardsChanged(e);
revitContext.UIApplication.NotNull().Application.DocumentChanged += (_, e) =>
_topLevelExceptionHandler.CatchUnhandled(() => DocChangeHandler(e));
_store.DocumentChanged += (_, _) => topLevelExceptionHandler.FireAndForget(async () => await OnDocumentChanged());
});
}
private void OnModelCardsChanged(ModelCardsChangedEventArgs e)
{
if (
!_config.DocumentChangeListeningDisabled
&& e.ModelCards.Count > 0
&& e.ModelCards.Any(m => m.TypeDiscriminator == nameof(SenderModelCard))
)
{
SubscribeDocChanged();
}
else
{
UnsubscribeDocChanged();
}
}
private void SubscribeDocChanged()
{
if (_documentChangedHandler == null || _isDocChangedSubscribed)
{
return;
}
_threadContext.RunOnMain(() =>
{
_revitContext.UIApplication.NotNull().Application.DocumentChanged += _documentChangedHandler;
});
_isDocChangedSubscribed = true;
}
private void UnsubscribeDocChanged()
{
if (_documentChangedHandler == null || !_isDocChangedSubscribed)
{
return;
}
_threadContext.RunOnMain(() =>
{
_revitContext.UIApplication.NotNull().Application.DocumentChanged -= _documentChangedHandler;
});
_isDocChangedSubscribed = false;
}
public List<ISendFilter> GetSendFilters() =>
[
new RevitSelectionFilter { IsDefault = true },
@@ -327,7 +276,7 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
if (addedElementIds.Count > 0)
{
_revitIdleManager.SubscribeToIdle(nameof(PostSetObjectIds), PostSetObjectIds);
_idleManager.SubscribeToIdle(nameof(PostSetObjectIds), PostSetObjectIds);
}
if (HaveUnitsChanged(doc))
@@ -347,8 +296,8 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
_sendConversionCache.EvictObjects(unpackedObjectIds);
}
_revitIdleManager.SubscribeToIdle(nameof(CheckFilterExpiration), CheckFilterExpiration);
_revitIdleManager.SubscribeToIdle(nameof(RunExpirationChecks), RunExpirationChecks);
_idleManager.SubscribeToIdle(nameof(CheckFilterExpiration), CheckFilterExpiration);
_idleManager.SubscribeToIdle(nameof(RunExpirationChecks), RunExpirationChecks);
}
// Keeps track of doc and current units
@@ -1,6 +1,5 @@
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Settings;
using Speckle.Connectors.Revit.Plugin;
using Speckle.Converters.RevitShared.Helpers;
using Speckle.Sdk.Common;
@@ -18,32 +17,27 @@ internal sealed class SelectionBinding : RevitBaseBinding, ISelectionBinding, ID
public SelectionBinding(
RevitContext revitContext,
IBrowserBridge parent,
RevitIdleManager idleManager,
#if REVIT2022
IAppIdleManager idleManager,
ITopLevelExceptionHandler topLevelExceptionHandler,
#endif
IRevitTask revitTask,
IConfigStore configStore
IRevitTask revitTask
)
: base("selectionBinding", parent)
{
_revitContext = revitContext;
if (!configStore.GetConnectorConfig().SelectionChangeListeningDisabled)
{
#if REVIT2022
// NOTE: getting the selection data should be a fast function all, even for '000s of elements - and having a timer hitting it every 1s is ok.
_selectionTimer = new System.Timers.Timer(1000);
_selectionTimer.Elapsed += (_, _) => topLevelExceptionHandler.CatchUnhandled(OnSelectionChanged);
_selectionTimer.Start();
// NOTE: getting the selection data should be a fast function all, even for '000s of elements - and having a timer hitting it every 1s is ok.
_selectionTimer = new System.Timers.Timer(1000);
_selectionTimer.Elapsed += (_, _) => topLevelExceptionHandler.CatchUnhandled(OnSelectionChanged);
_selectionTimer.Start();
#else
revitTask.Run(
() =>
_revitContext.UIApplication.NotNull().SelectionChanged += (_, _) =>
idleManager.SubscribeToIdle(nameof(OnSelectionChanged), OnSelectionChanged)
);
revitTask.Run(
() =>
_revitContext.UIApplication.NotNull().SelectionChanged += (_, _) =>
idleManager.SubscribeToIdle(nameof(OnSelectionChanged), OnSelectionChanged)
);
#endif
}
}
private void OnSelectionChanged()
@@ -48,12 +48,11 @@ public static class ServiceRegistration
serviceCollection.AddSingleton<IBinding, SelectionBinding>();
serviceCollection.AddSingleton<IBinding, RevitSendBinding>();
serviceCollection.AddSingleton<IBinding, RevitReceiveBinding>();
serviceCollection.AddSingleton<RevitIdleManager>();
serviceCollection.AddSingleton<IBinding>(sp => sp.GetRequiredService<IBasicConnectorBinding>());
serviceCollection.AddSingleton<IBasicConnectorBinding, BasicConnectorBindingRevit>();
// serviceCollection.AddSingleton<IAppIdleManager, RevitIdleManager>();
serviceCollection.AddSingleton<IAppIdleManager, RevitIdleManager>();
// send operation and dependencies
serviceCollection.AddScoped<SendOperation<DocumentToConvert>>();
@@ -17,16 +17,13 @@ namespace Speckle.Connectors.Revit.HostApp;
internal sealed class RevitDocumentStore : DocumentModelStore
{
private readonly ILogger<RevitDocumentStore> _logger;
//private readonly IAppIdleManager _idleManager;
private readonly RevitIdleManager _idleManager;
private readonly IAppIdleManager _idleManager;
private readonly RevitContext _revitContext;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
private readonly ISqLiteJsonCacheManager _jsonCacheManager;
public RevitDocumentStore(
//IAppIdleManager idleManager,
RevitIdleManager idleManager,
IAppIdleManager idleManager,
RevitContext revitContext,
IJsonSerializer jsonSerializer,
ITopLevelExceptionHandler topLevelExceptionHandler,
@@ -37,7 +34,6 @@ internal sealed class RevitDocumentStore : DocumentModelStore
: base(logger, jsonSerializer)
{
_jsonCacheManager = jsonCacheManagerFactory.CreateForUser("ConnectorsFileData");
//_idleManager = idleManager;
_idleManager = idleManager;
_revitContext = revitContext;
_topLevelExceptionHandler = topLevelExceptionHandler;
@@ -5,6 +5,7 @@ using Speckle.Converters.Common;
using Speckle.Converters.RevitShared.Settings;
using Speckle.Objects.Other;
using Speckle.Sdk;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models.Collections;
using Speckle.Sdk.Models.Extensions;
using Speckle.Sdk.Models.GraphTraversal;
@@ -31,24 +32,6 @@ public class RevitMaterialBaker
_converterSettings = converterSettings;
}
private ElementId? FindExistingMaterialByName(string? materialName)
{
if (string.IsNullOrWhiteSpace(materialName))
{
return null;
}
string sanitizedName = _revitUtils.RemoveInvalidChars(materialName!);
using var collector = new FilteredElementCollector(_converterSettings.Current.Document);
var existingMaterial = collector
.OfClass(typeof(Material))
.Cast<Material>()
.FirstOrDefault(m => string.Equals(m.Name, sanitizedName, StringComparison.OrdinalIgnoreCase));
return existingMaterial?.Id;
}
/// <summary>
/// Checks the every atomic object has render material or not, if not it tries to find it from its layer tree and mutates
/// its render material proxy objects list with the traversal current. It will also map displayable objects' display values to their
@@ -123,9 +106,11 @@ public class RevitMaterialBaker
/// Will bake render materials in the revit document.
/// </summary>
/// <param name="speckleRenderMaterialProxies"></param>
/// <param name="baseLayerName"></param>
/// <returns></returns>
public Dictionary<string, ElementId> BakeMaterials(
IReadOnlyCollection<RenderMaterialProxy> speckleRenderMaterialProxies
IReadOnlyCollection<RenderMaterialProxy> speckleRenderMaterialProxies,
string baseLayerName
)
{
Dictionary<string, ElementId> objectIdAndMaterialIndexMap = new();
@@ -135,42 +120,27 @@ public class RevitMaterialBaker
try
{
// first try to match existing material by name
ElementId? existingMaterialId = FindExistingMaterialByName(speckleRenderMaterial.name);
// all values assumed to be on the 0 - 1 scale need to pass through this validation and logging (if assumption wrong)
double roughness = ClampToUnitRange(speckleRenderMaterial.roughness, "roughness", speckleRenderMaterial.name);
double opacity = ClampToUnitRange(speckleRenderMaterial.opacity, "opacity", speckleRenderMaterial.name);
double metalness = ClampToUnitRange(speckleRenderMaterial.metalness, "metalness", speckleRenderMaterial.name);
ElementId materialIdToUse;
var diffuse = System.Drawing.Color.FromArgb(speckleRenderMaterial.diffuse);
double transparency = 1 - opacity;
double smoothness = 1 - roughness;
string materialId = speckleRenderMaterial.applicationId ?? speckleRenderMaterial.id.NotNull();
string matName = _revitUtils.RemoveInvalidChars($"{speckleRenderMaterial.name}-({materialId})-{baseLayerName}");
if (existingMaterialId != null)
{
// Use existing material
materialIdToUse = existingMaterialId;
}
else
{
// create new material
// all values assumed to be on the 0 - 1 scale need to pass through this validation and logging (if assumption wrong)
double roughness = ClampToUnitRange(speckleRenderMaterial.roughness, "roughness", speckleRenderMaterial.name);
double opacity = ClampToUnitRange(speckleRenderMaterial.opacity, "opacity", speckleRenderMaterial.name);
double metalness = ClampToUnitRange(speckleRenderMaterial.metalness, "metalness", speckleRenderMaterial.name);
var diffuse = System.Drawing.Color.FromArgb(speckleRenderMaterial.diffuse);
double transparency = 1 - opacity;
double smoothness = 1 - roughness;
string matName = _revitUtils.RemoveInvalidChars($"{speckleRenderMaterial.name}");
var newMaterialId = Material.Create(_converterSettings.Current.Document, matName);
var revitMaterial = (Material)_converterSettings.Current.Document.GetElement(newMaterialId);
revitMaterial.Color = new Color(diffuse.R, diffuse.G, diffuse.B);
revitMaterial.Transparency = (int)(transparency * 100);
revitMaterial.Shininess = (int)(metalness * 128);
revitMaterial.Smoothness = (int)(smoothness * 100);
materialIdToUse = revitMaterial.Id;
}
var newMaterialId = Material.Create(_converterSettings.Current.Document, matName);
var revitMaterial = (Material)_converterSettings.Current.Document.GetElement(newMaterialId);
revitMaterial.Color = new Color(diffuse.R, diffuse.G, diffuse.B);
revitMaterial.Transparency = (int)(transparency * 100);
revitMaterial.Shininess = (int)(metalness * 128);
revitMaterial.Smoothness = (int)(smoothness * 128);
foreach (var objectId in proxy.objects)
{
objectIdAndMaterialIndexMap[objectId] = materialIdToUse;
objectIdAndMaterialIndexMap[objectId] = revitMaterial.Id;
}
}
catch (Exception ex) when (!ex.IsFatal())
@@ -21,7 +21,6 @@ using Speckle.Sdk.Common;
using Speckle.Sdk.Common.Exceptions;
using Speckle.Sdk.Logging;
using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Instances;
using Transform = Speckle.Objects.Other.Transform;
namespace Speckle.Connectors.Revit.Operations.Receive;
@@ -39,15 +38,12 @@ public sealed class RevitHostObjectBuilder(
IThreadContext threadContext,
RevitToHostCacheSingleton revitToHostCacheSingleton,
ITypedConverter<
(Base atomicObject, IReadOnlyCollection<Matrix4x4> matrix, DataObject? parentDataObject),
(Base atomicObject, IReadOnlyCollection<Matrix4x4> matrix),
DirectShape
> localToGlobalDirectShapeConverter,
IReceiveConversionHandler conversionHandler
) : IHostObjectBuilder, IDisposable
{
// Maps atomic object applicationId -> parent DataObject
private readonly Dictionary<string, DataObject> _atomicObjectToParentDataObject = new();
public Task<HostObjectBuilderResult> Build(
Base rootObject,
string projectName,
@@ -106,9 +102,6 @@ public sealed class RevitHostObjectBuilder(
unpackedRoot.ObjectsToConvert.ToList()
);
// Register DataObjects with InstanceProxy displayValues
RegisterDataObjectsWithInstanceProxies(unpackedRoot);
// NOTE: below is 💩... https://github.com/specklesystems/speckle-sharp-connectors/pull/813 broke sketchup to revit workflow
// ids were modified to fix receiving instances [CNX-1707](https://linear.app/speckle/issue/CNX-1707/revit-curves-and-meshes-in-blocks-come-as-duplicated)
// but we then broke sketchup to revit because applicationIds in proxies didn't match modified application ids which cam from #813 hack
@@ -183,15 +176,12 @@ public sealed class RevitHostObjectBuilder(
}
}
// Update DataObject lookup IDs
UpdateAtomicObjectLookupWithModifiedIds(originalToModifiedIds);
// 2 - Bake materials (now with the updated IDs)
if (unpackedRoot.RenderMaterialProxies != null)
{
transactionManager.StartTransaction(true, "Baking materials");
materialBaker.MapLayersRenderMaterials(unpackedRoot);
var map = materialBaker.BakeMaterials(unpackedRoot.RenderMaterialProxies);
var map = materialBaker.BakeMaterials(unpackedRoot.RenderMaterialProxies, baseGroupName);
foreach (var kvp in map)
{
revitToHostCacheSingleton.MaterialsByObjectId.Add(kvp.Key, kvp.Value);
@@ -244,87 +234,6 @@ public sealed class RevitHostObjectBuilder(
return conversionResults.builderResult;
}
/// <summary>
/// Registers DataObjects that have InstanceProxy displayValues and builds the lookup.
/// </summary>
private void RegisterDataObjectsWithInstanceProxies(RootObjectUnpackerResult unpackedRoot)
{
var definitionToDataObject = new Dictionary<string, DataObject>();
foreach (var tc in unpackedRoot.ObjectsToConvert)
{
if (tc.Current is DataObject dataObject)
{
var instanceProxies = dataObject.displayValue.OfType<InstanceProxy>().ToList();
if (instanceProxies.Count > 0)
{
foreach (var ip in instanceProxies)
{
definitionToDataObject[ip.definitionId] = dataObject;
}
}
}
}
// Build lookup: definition object applicationId -> parent DataObject
_atomicObjectToParentDataObject.Clear();
if (unpackedRoot.DefinitionProxies is not null)
{
foreach (var defProxy in unpackedRoot.DefinitionProxies)
{
if (
defProxy.applicationId is not null
&& definitionToDataObject.TryGetValue(defProxy.applicationId, out var parentDataObject)
)
{
foreach (var objectId in defProxy.objects)
{
_atomicObjectToParentDataObject[objectId] = parentDataObject;
}
}
else
{
logger.LogError(
"Could not find parent DataObject for DefinitionProxy {ApplicationId}",
defProxy.applicationId
);
}
}
}
}
/// <summary>
/// Updates the atomic object lookup with modified IDs
/// </summary>
private void UpdateAtomicObjectLookupWithModifiedIds(Dictionary<string, List<string>> originalToModifiedIds)
{
// Build updated entries first to avoid modifying collection during iteration
var entriesToAdd = new List<KeyValuePair<string, DataObject>>();
var keysToRemove = new List<string>();
foreach (var kvp in _atomicObjectToParentDataObject)
{
if (originalToModifiedIds.TryGetValue(kvp.Key, out var modifiedIds))
{
keysToRemove.Add(kvp.Key);
foreach (var modifiedId in modifiedIds)
{
entriesToAdd.Add(new(modifiedId, kvp.Value));
}
}
}
foreach (var key in keysToRemove)
{
_atomicObjectToParentDataObject.Remove(key);
}
foreach (var entry in entriesToAdd)
{
_atomicObjectToParentDataObject[entry.Key] = entry.Value;
}
}
private Autodesk.Revit.DB.Transform? CalculateNewTransform(
Autodesk.Revit.DB.Transform? receiveTransform,
Autodesk.Revit.DB.Transform? rootTransform
@@ -369,17 +278,9 @@ public sealed class RevitHostObjectBuilder(
onOperationProgressed.Report(new("Converting", (double)++count / localToGlobalMaps.Count));
if (result is DirectShapeDefinitionWrapper)
{
// Look up parent DataObject for this atomic object (handles InstanceProxy displayValue)
var atomicId = localToGlobalMap.AtomicObject.applicationId;
DataObject? parentDataObject = null;
if (atomicId is not null)
{
_atomicObjectToParentDataObject.TryGetValue(atomicId, out parentDataObject);
}
// direct shape creation happens here
DirectShape directShapes = localToGlobalDirectShapeConverter.Convert(
(localToGlobalMap.AtomicObject, localToGlobalMap.Matrix, parentDataObject)
(localToGlobalMap.AtomicObject, localToGlobalMap.Matrix)
);
bakedObjectIds.Add(directShapes.UniqueId);
@@ -450,7 +351,6 @@ public sealed class RevitHostObjectBuilder(
DirectShapeLibrary.GetDirectShapeLibrary(converterSettings.Current.Document).Reset(); // Note: this needs to be cleared, as it is being used in the converter
revitToHostCacheSingleton.MaterialsByObjectId.Clear(); // Massive hack!
_atomicObjectToParentDataObject.Clear();
groupManager.PurgeGroups(baseGroupName);
materialBaker.PurgeMaterials(baseGroupName);
}
@@ -81,11 +81,7 @@ public class RevitCategoriesFilter : DiscriminatedObject, ISendFilter, IRevitSen
foreach (Category category in _doc.Settings.Categories)
{
if (SupportedCategoriesUtils.IsSupportedCategory(category)
#if REVIT2023_OR_GREATER
&& category.BuiltInCategory != BuiltInCategory.INVALID
#endif
)
if (SupportedCategoriesUtils.IsSupportedCategory(category))
{
categories.Add(new CategoryData(category.Name, category.Id.ToString()));
}
@@ -1,4 +1,3 @@
using System.Diagnostics.CodeAnalysis;
using Autodesk.Revit.DB;
using Microsoft.Extensions.Logging;
using Speckle.Connectors.Common.Builders;
@@ -8,7 +7,6 @@ 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;
@@ -31,8 +29,7 @@ public class RevitRootObjectBuilder(
SendCollectionManager sendCollectionManager,
ILogger<RevitRootObjectBuilder> logger,
RevitToSpeckleCacheSingleton revitToSpeckleCacheSingleton,
LinkedModelHandler linkedModelHandler,
IConfigStore configStore
LinkedModelHandler linkedModelHandler
) : IRootObjectBuilder<DocumentToConvert>
{
public Task<RootObjectBuilderResult> Build(
@@ -45,7 +42,6 @@ public class RevitRootObjectBuilder(
() => Task.FromResult(BuildSync(documentElementContexts, projectId, onOperationProgressed, ct))
);
[SuppressMessage("Maintainability", "CA1506:Avoid excessive class coupling")]
private RootObjectBuilderResult BuildSync(
IReadOnlyList<DocumentToConvert> documentElementContexts,
string projectId,
@@ -138,8 +134,6 @@ public class RevitRootObjectBuilder(
var cacheHitCount = 0;
var skippedObjectCount = 0;
var config = configStore.GetConnectorConfig();
foreach (var atomicObjectByDocumentAndTransform in atomicObjectsByDocumentAndTransform)
{
string? modelDisplayName = null;
@@ -191,11 +185,7 @@ public class RevitRootObjectBuilder(
// 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)
)
if (!hasTransform && sendConversionCache.TryGetValue(projectId, applicationId, out ObjectReference? value))
{
converted = value;
cacheHitCount++;
@@ -1,112 +1,43 @@
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Events;
using Microsoft.Extensions.Logging;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Converters.RevitShared.Helpers;
using Speckle.Sdk.Common;
namespace Speckle.Connectors.Revit.Plugin;
/// <remarks>
/// Please do NOT try and refactor this class.
/// Whether it's to try and generalize with the <see cref="IdleCallManager"/> class
/// or to unnecessary try and make this class thread safe.
/// This class is a simple singleton, targeted to a Revit's host app requirements
/// where everything happens on the main thread, and we can avoid overly complex threading/thread-safty.
///
/// Previous good refactors with good intention have lead to poor debugging experiences, over-engineered threading,
/// and low confidence in the reliability.
/// </remarks>
/// should be registered as singleton
public class RevitIdleManager(
RevitContext revitContext,
ITopLevelExceptionHandler topLevelExceptionHandler,
ILogger<RevitIdleManager> logger
)
public sealed class RevitIdleManager : AppIdleManager
{
private readonly UIApplication _uiApplication = revitContext.UIApplication.NotNull();
private readonly UIApplication _uiApplication;
private readonly IIdleCallManager _idleCallManager;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
private readonly Dictionary<string, Func<Task>> _calls = new();
private bool _hasSubscribed;
private event EventHandler<IdlingEventArgs>? OnIdle;
private bool _isExecutingIdle;
/// <summary>
/// Defers the invocation of an <paramref name="action"/> until next Revit idle tick (deduped by name).
/// The <paramref name="action"/> will be called only once.
/// </summary>
/// <param name="name">A key that prevents enqueuing duplicate events</param>
/// <param name="action">The action to be invoked</param>
/// <example>
/// Some events in host app are triggered many times, we might get 10x per object
/// Making this more like a deferred action, so we don't update the UI many times
/// </example>
/// <remarks>
/// This function must be called on the main thread
/// </remarks>
public void SubscribeToIdle(string name, Action action)
public RevitIdleManager(
RevitContext revitContext,
IIdleCallManager idleCallManager,
ITopLevelExceptionHandler topLevelExceptionHandler,
IRevitTask revitTask
)
: base(idleCallManager)
{
SubscribeToIdle(
name,
() =>
{
action.Invoke();
return Task.CompletedTask;
}
_topLevelExceptionHandler = topLevelExceptionHandler;
_uiApplication = revitContext.UIApplication.NotNull();
_idleCallManager = idleCallManager;
revitTask.Run(
() => _uiApplication.Idling += (s, e) => OnIdle?.Invoke(s, e) // will be called on the main thread always and fixing the Revit exceptions on subscribing/unsubscribing Idle events
);
}
/// <inheritdoc cref="SubscribeToIdle(string, Action)"/>
public void SubscribeToIdle(string name, Func<Task> action)
protected override void AddEvent()
{
if (_isExecutingIdle)
_topLevelExceptionHandler.CatchUnhandled(() =>
{
logger.LogWarning("SubscribeToIdle called while already executing idle events");
}
_calls[name] = action;
if (_hasSubscribed)
{
return;
}
_hasSubscribed = true;
_uiApplication.Idling += RevitAppOnIdle;
}
private void RevitAppOnIdle(object? sender, IdlingEventArgs e)
{
topLevelExceptionHandler.CatchUnhandled(() =>
{
if (_isExecutingIdle)
{
logger.LogWarning("SubscribeToIdle called while already executing idle events");
}
_isExecutingIdle = true;
try
{
try
{
foreach (KeyValuePair<string, Func<Task>> kvp in _calls)
{
topLevelExceptionHandler.FireAndForget(kvp.Value.Invoke);
}
}
finally
{
_calls.Clear();
}
}
finally
{
_uiApplication.Idling -= RevitAppOnIdle;
_isExecutingIdle = false;
// setting last will delay entering re-subscription
_hasSubscribed = false;
}
OnIdle += RevitAppOnIdle;
});
}
private void RevitAppOnIdle(object? sender, IdlingEventArgs e) =>
_idleCallManager.AppOnIdle(() => OnIdle -= RevitAppOnIdle);
}
@@ -54,9 +54,9 @@
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\Settings\DetailLevelSetting.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\IRevitPlugin.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\RevitCommand.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\RevitIdleManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\RevitTask.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\RevitExternalApplication.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\RevitIdleManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\RevitThreadContext.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\RevitCefPlugin.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\SpeckleRevitTaskException.cs" />
@@ -204,8 +204,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -215,13 +215,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -347,7 +347,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.logging": {
@@ -357,7 +357,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.converters.rhino7": {
@@ -402,11 +402,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
}
}
@@ -204,8 +204,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -215,13 +215,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -347,7 +347,7 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.logging": {
@@ -357,7 +357,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.converters.rhino8": {
@@ -401,11 +401,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
}
}
@@ -1,311 +0,0 @@
using System.Runtime.InteropServices;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Types;
using Speckle.Connectors.GrasshopperShared.HostApp;
using Speckle.Connectors.GrasshopperShared.Parameters;
using Speckle.Connectors.GrasshopperShared.Properties;
using Speckle.Sdk.Models.Collections;
namespace Speckle.Connectors.GrasshopperShared.Components.Collections;
/// <summary>
/// Creates collections by matching name tree structure to elements tree structure.
/// Each branch in the names tree corresponds to the same-path branch in the elements tree.
/// </summary>
[Guid("7E8F9A1B-2C3D-4E5F-6A7B-8C9D0E1F2A3B")]
public class CollectionsByName : GH_Component
{
public override Guid ComponentGuid => GetType().GUID;
protected override Bitmap Icon => Resources.speckle_collections_create; // TODO: Update to specific icon if available
public override GH_Exposure Exposure => GH_Exposure.primary;
public CollectionsByName()
: base(
"Collections by Name",
"CbN",
"Creates collections by matching name tree structure to objects tree structure. Each branch in the names tree corresponds to the same-path branch in the objects tree.",
ComponentCategories.PRIMARY_RIBBON,
ComponentCategories.COLLECTIONS
) { }
protected override void RegisterInputParams(GH_InputParamManager pManager)
{
pManager.AddTextParameter(
"Names",
"N",
"Collection names (tree structure must match Objects tree structure)",
GH_ParamAccess.tree
);
pManager.AddGenericParameter(
"Objects",
"O",
"Objects to group into collections (tree structure must match Names tree structure)",
GH_ParamAccess.tree
);
}
protected override void RegisterOutputParams(GH_OutputParamManager pManager) =>
pManager.AddParameter(
new SpeckleCollectionParam(),
"Collection",
"C",
"Root collection containing named sub-collections",
GH_ParamAccess.item
);
protected override void SolveInstance(IGH_DataAccess da)
{
// access the tree data directly from parameters
var namesParam = Params.Input[0];
var elementsParam = Params.Input[1];
var namesTree = namesParam.VolatileData;
var elementsTree = elementsParam.VolatileData;
// validate that both inputs have data
if (namesTree.IsEmpty)
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Names tree is empty");
return;
}
if (elementsTree.IsEmpty)
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Objects tree is empty");
return;
}
// validate tree structures match exactly
if (!TreeStructuresMatch(namesTree, elementsTree))
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Tree structures and topologies must match exactly");
return;
}
// create root collection
var rootCollection = CollectionHelpers.CreateRootCollection(InstanceGuid.ToString());
// process each path
foreach (var path in namesTree.Paths)
{
var nameBranch = namesTree.get_Branch(path);
var elementsBranch = elementsTree.get_Branch(path);
// validate name branch - throw if empty
if (nameBranch.Count == 0)
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, $"Name branch at path {path} is empty");
return;
}
// validate name branch - just warn if multiple, use first
if (nameBranch.Count > 1)
{
AddRuntimeMessage(
GH_RuntimeMessageLevel.Warning,
$"Name branch at path {path} has {nameBranch.Count} names - using first name only"
);
}
// get the collection name
string collectionName = GetCollectionName(nameBranch[0]);
if (string.IsNullOrWhiteSpace(collectionName))
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, $"Invalid collection name at path {path}");
return;
}
// skip empty element branches with warning
if (elementsBranch.Count == 0)
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"Skipping empty elements branch at path {path}");
continue;
}
// parse nested collection path (e.g. parent::child)
var collectionNames = collectionName.Split(
new[] { Constants.LAYER_PATH_DELIMITER },
StringSplitOptions.RemoveEmptyEntries
);
// create or get nested collection structure
var targetCollection = GetOrCreateNestedCollection(rootCollection, collectionNames, elementsBranch, path);
// add elements to deepest collection
AddElementsToCollection(targetCollection, elementsBranch, path);
}
// validate collection has content
if (rootCollection.Elements.Count == 0)
{
AddRuntimeMessage(
GH_RuntimeMessageLevel.Error,
"Collection contains no valid geometry. All branches were empty or contained unsupported types."
);
return;
}
// validate for duplicate application IDs (following CreateCollection pattern)
if (CollectionHelpers.HasDuplicateApplicationIds(rootCollection))
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "The same object(s) cannot appear in multiple collections");
return;
}
da.SetData(0, new SpeckleCollectionWrapperGoo(rootCollection));
}
/// <summary>
/// Validates that two tree structures have exactly matching paths
/// </summary>
private bool TreeStructuresMatch(
Grasshopper.Kernel.Data.IGH_Structure namesTree,
Grasshopper.Kernel.Data.IGH_Structure elementsTree
)
{
if (namesTree.PathCount != elementsTree.PathCount)
{
return false;
}
// check that all paths match exactly
var namePaths = namesTree.Paths.ToList();
var elementPaths = elementsTree.Paths.ToList();
for (int i = 0; i < namePaths.Count; i++)
{
if (namePaths[i].CompareTo(elementPaths[i]) != 0)
{
return false;
}
}
return true;
}
/// <summary>
/// Extracts collection name, handling GH_String and other text types
/// </summary>
private string GetCollectionName(object nameObj) =>
nameObj switch
{
GH_String ghString => ghString.Value,
IGH_Goo goo => goo.ToString(),
_ => nameObj.ToString()
};
/// <summary>
/// Gets or creates a nested collection structure based on the collection names.
/// </summary>
/// <remarks>
/// Handles paths like "parent::child::grandchild" by creating intermediate collections.
/// </remarks>
private SpeckleCollectionWrapper GetOrCreateNestedCollection(
SpeckleCollectionWrapper rootCollection,
string[] collectionNames,
System.Collections.IList elementsBranch,
Grasshopper.Kernel.Data.GH_Path path
)
{
SpeckleCollectionWrapper currentCollection = rootCollection;
var currentPath = new List<string>(rootCollection.Path);
foreach (var collectionName in collectionNames)
{
// build path for this level
currentPath.Add(collectionName);
// check if child collection already exists
var existingChild = currentCollection
.Elements.OfType<SpeckleCollectionWrapper>()
.FirstOrDefault(c => c.Name == collectionName);
if (existingChild != null)
{
// use existing collection
currentCollection = existingChild;
}
else
{
// create new child collection
var newChild = new SpeckleCollectionWrapper
{
Base = new Collection(),
Name = collectionName,
Path = currentPath.ToList(),
Color = null,
Material = null,
Topology = null, // only set topology on leaf collections
ApplicationId = Guid.NewGuid().ToString()
};
currentCollection.Elements.Add(newChild);
currentCollection = newChild;
}
}
// set topology on the final (leaf) collection
currentCollection.Topology = GetBranchTopology(path, elementsBranch.Count);
return currentCollection;
}
/// <summary>
/// Adds elements from a branch to the target collection
/// </summary>
private void AddElementsToCollection(
SpeckleCollectionWrapper targetCollection,
System.Collections.IList elementsBranch,
Grasshopper.Kernel.Data.GH_Path path
)
{
foreach (var item in elementsBranch)
{
if (item == null)
{
// preserve nulls for topology (CNX-2855 pattern)
targetCollection.Elements.Add(null);
continue;
}
// convert to SpeckleWrapper if possible - cast to IGH_Goo first
if (item is not IGH_Goo goo)
{
AddRuntimeMessage(
GH_RuntimeMessageLevel.Warning,
$"Unsupported object type in branch {path}: {item.GetType().Name}"
);
continue;
}
var wrapper = goo.ToSpeckleObjectWrapper();
if (wrapper == null)
{
AddRuntimeMessage(
GH_RuntimeMessageLevel.Warning,
$"Unsupported object type in branch {path}: {item.GetType().Name}"
);
continue;
}
if (wrapper is ISpeckleCollectionObject collectionObject)
{
targetCollection.Elements.Add(collectionObject);
}
else
{
AddRuntimeMessage(
GH_RuntimeMessageLevel.Warning,
$"Object type {wrapper.GetType().Name} is not a valid collection element"
);
}
}
}
/// <summary>
/// Creates topology string for a single branch (following GrasshopperHelpers.GetParamTopology pattern)
/// </summary>
private string GetBranchTopology(Grasshopper.Kernel.Data.GH_Path path, int count) =>
$"{path.ToString(false)}-{count}";
}
@@ -47,7 +47,7 @@ public class CreateCollection : VariableParameterComponentBase
protected override void SolveInstance(IGH_DataAccess dataAccess)
{
var rootCollection = CollectionHelpers.CreateRootCollection(InstanceGuid.ToString());
var rootCollection = CreateRootCollection();
bool hasAnyInput = false;
foreach (var inputParam in Params.Input)
@@ -73,14 +73,14 @@ public class CreateCollection : VariableParameterComponentBase
}
// validate for duplicate application IDs across the entire collection hierarchy
if (CollectionHelpers.HasDuplicateApplicationIds(rootCollection))
if (HasDuplicateApplicationIds(rootCollection))
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "The same object(s) cannot appear in multiple collections");
return;
}
// validate collection isn't empty (CNX-2855)
if (rootCollection.Elements.Count == 0 || !rootCollection.Elements.Any(CollectionHelpers.HasAnyValidContent))
if (rootCollection.Elements.Count == 0 || !rootCollection.Elements.Any(HasAnyValidContent))
{
AddRuntimeMessage(
GH_RuntimeMessageLevel.Error,
@@ -233,6 +233,56 @@ public class CreateCollection : VariableParameterComponentBase
}
}
/// <summary>
/// Validates that all application IDs are unique across the entire collection hierarchy.
/// Shows an error if duplicates are found, indicating objects appear in multiple collections.
/// </summary>
/// <returns>True if duplicates exist, false if all IDs are unique</returns>
private bool HasDuplicateApplicationIds(SpeckleCollectionWrapper rootCollection)
{
// args to CheckForDuplicateApplicationIds passed in since the method can recursively check
var seenIds = new HashSet<string>();
var duplicateIds = new HashSet<string>();
// iterate, create hash set and check all application IDs
ProcessAndCheckForDuplicateApplicationIds(rootCollection, seenIds, duplicateIds);
return duplicateIds.Count > 0;
}
/// <summary>
/// Recursively collects application IDs from all in the collection hierarchy.
/// </summary>
/// <remarks>
/// Only checks the wrapper's ApplicationId, not for example geometries within DataObjects.
/// </remarks>
private void ProcessAndCheckForDuplicateApplicationIds(
SpeckleCollectionWrapper collection,
HashSet<string> seenIds,
HashSet<string> duplicateIds
)
{
foreach (var element in collection.Elements)
{
switch (element)
{
case null:
break; // skip nulls (CNX-2855)
case SpeckleCollectionWrapper childCollection:
// recurse into child collections
ProcessAndCheckForDuplicateApplicationIds(childCollection, seenIds, duplicateIds);
break;
case SpeckleWrapper wrapper:
if (wrapper.ApplicationId != null && !seenIds.Add(wrapper.ApplicationId))
{
duplicateIds.Add(wrapper.ApplicationId);
}
break;
}
}
}
// IGH_VariableParameterComponent implementation
public override bool CanInsertParameter(GH_ParameterSide side, int index) => side == GH_ParameterSide.Input;
@@ -1,6 +1,5 @@
using System.Runtime.InteropServices;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Parameters;
using Grasshopper.Kernel.Types;
using Speckle.Connectors.GrasshopperShared.Components.BaseComponents;
using Speckle.Connectors.GrasshopperShared.HostApp;
@@ -13,7 +12,7 @@ namespace Speckle.Connectors.GrasshopperShared.Components.Objects;
/// Given a list of objects, this component will filter the list for objects that match the queries.
/// </summary>
[Guid("26AEA046-4DD4-4F61-8251-E92A6D2AC880")]
public class FilterSpeckleObjects : GH_Component, IGH_VariableParameterComponent
public class FilterSpeckleObjects : GH_Component
{
public override Guid ComponentGuid => GetType().GUID;
protected override Bitmap Icon => Resources.speckle_objects_filter;
@@ -50,6 +49,17 @@ public class FilterSpeckleObjects : GH_Component, IGH_VariableParameterComponent
GH_ParamAccess.item
);
Params.Input[3].Optional = true;
pManager.AddTextParameter(
"Application Id",
"aID",
"Find objects with a matching applicationId",
GH_ParamAccess.item
);
Params.Input[4].Optional = true;
pManager.AddTextParameter("Speckle Id", "sID", "Find objects with a matching Speckle id", GH_ParamAccess.item);
Params.Input[5].Optional = true;
}
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
@@ -93,39 +103,101 @@ public class FilterSpeckleObjects : GH_Component, IGH_VariableParameterComponent
dataAccess.GetData(2, ref property);
string material = "";
dataAccess.GetData(3, ref material);
// optional parameters - only read if they've been added via ⊕
string appId = "";
dataAccess.GetData(4, ref appId);
string speckleId = "";
int? appIdIndex = FindInputIndexByName("Application Id");
int? speckleIdIndex = FindInputIndexByName("Speckle Id");
if (appIdIndex.HasValue)
{
dataAccess.GetData(appIdIndex.Value, ref appId);
}
if (speckleIdIndex.HasValue)
{
dataAccess.GetData(speckleIdIndex.Value, ref speckleId);
}
bool filterByAppId = appIdIndex.HasValue;
bool filterBySpeckleId = speckleIdIndex.HasValue;
dataAccess.GetData(5, ref speckleId);
List<SpeckleWrapper> matchedObjects = new();
List<SpeckleWrapper> removedObjects = new();
foreach (SpeckleWrapper wrapper in objects.Cast<SpeckleWrapper>())
for (int i = 0; i < objects.Count; i++)
{
if (MatchesAllFilters(wrapper, name, property, material, appId, filterByAppId, speckleId, filterBySpeckleId))
SpeckleWrapper wrapper = objects[i]!;
// filter by name
if (!MatchesSearchPattern(name, wrapper.Name))
{
matchedObjects.Add(wrapper);
removedObjects.Add(wrapper);
continue;
}
// filter by property
bool foundProperty = false;
if (string.IsNullOrEmpty(property))
{
foundProperty = true;
}
else
{
removedObjects.Add(wrapper);
SpecklePropertyGroupGoo? properties = wrapper is SpeckleDataObjectWrapper dataObjPropWrapper
? dataObjPropWrapper.Properties
: wrapper is SpeckleGeometryWrapper geoPropWrapper
? geoPropWrapper.Properties
: null;
if (properties is not null)
{
// use flattened properties to search ALL nested property keys
// fix for [CNX-2512](https://linear.app/speckle/issue/CNX-2512/filter-objects-material-and-property-key-inputs-dont-work-as-expected)
Dictionary<string, SpecklePropertyGoo> flattenedProps = properties.Flatten();
foreach (string key in flattenedProps.Keys)
{
if (MatchesSearchPattern(property, key))
{
foundProperty = true;
break;
}
}
}
}
if (!foundProperty)
{
removedObjects.Add(wrapper);
continue;
}
// filter by material name
bool materialMatches = true;
if (!string.IsNullOrEmpty(material))
{
materialMatches = false;
if (wrapper is SpeckleGeometryWrapper geoWrapper)
{
materialMatches = MatchesSearchPattern(material, geoWrapper.Material?.Name ?? "");
}
else if (wrapper is SpeckleDataObjectWrapper dataObjWrapper)
{
// check if ANY geometry in the data object has a matching material (not sure about this...)
// fix for [CNX-2512](https://linear.app/speckle/issue/CNX-2512/filter-objects-material-and-property-key-inputs-dont-work-as-expected)
materialMatches = dataObjWrapper.Geometries.Any(geo =>
MatchesSearchPattern(material, geo.Material?.Name ?? "")
);
}
}
if (!materialMatches)
{
removedObjects.Add(wrapper);
continue;
}
// filter by application id
if (!MatchesSearchPattern(appId, wrapper.Base.applicationId ?? ""))
{
removedObjects.Add(wrapper);
continue;
}
// filter by speckle id
if (!MatchesSearchPattern(speckleId, wrapper.Base.id ?? ""))
{
removedObjects.Add(wrapper);
continue;
}
matchedObjects.Add(wrapper);
}
// Set output objects
@@ -142,190 +214,4 @@ public class FilterSpeckleObjects : GH_Component, IGH_VariableParameterComponent
return Operator.IsSymbolNameLike(target, searchPattern);
}
/// <summary>
/// Determines if a wrapper matches all active filter criteria.
/// </summary>
private bool MatchesAllFilters(
SpeckleWrapper wrapper,
string name,
string property,
string material,
string appId,
bool filterByAppId,
string speckleId,
bool filterBySpeckleId
)
{
// filter by name
if (!MatchesSearchPattern(name, wrapper.Name))
{
return false;
}
// filter by property
if (!MatchesPropertyFilter(wrapper, property))
{
return false;
}
// filter by material name
if (!MatchesMaterialFilter(wrapper, material))
{
return false;
}
// filter by application id (only if parameter was added)
if (filterByAppId && !MatchesSearchPattern(appId, wrapper.Base.applicationId ?? ""))
{
return false;
}
// filter by speckle id (only if parameter was added)
if (filterBySpeckleId && !MatchesSearchPattern(speckleId, wrapper.Base.id ?? ""))
{
return false;
}
return true;
}
private bool MatchesPropertyFilter(SpeckleWrapper wrapper, string property)
{
if (string.IsNullOrEmpty(property))
{
return true;
}
SpecklePropertyGroupGoo? properties = wrapper is SpeckleDataObjectWrapper dataObjPropWrapper
? dataObjPropWrapper.Properties
: wrapper is SpeckleGeometryWrapper geoPropWrapper
? geoPropWrapper.Properties
: null;
if (properties is null)
{
return false;
}
// use flattened properties to search ALL nested property keys
return properties.Flatten().Keys.Any(key => MatchesSearchPattern(property, key));
}
private bool MatchesMaterialFilter(SpeckleWrapper wrapper, string material)
{
if (string.IsNullOrEmpty(material))
{
return true;
}
if (wrapper is SpeckleGeometryWrapper geoWrapper)
{
return MatchesSearchPattern(material, geoWrapper.Material?.Name ?? "");
}
if (wrapper is SpeckleDataObjectWrapper dataObjWrapper)
{
// check if ANY geometry in the data object has a matching material
return dataObjWrapper.Geometries.Any(geo => MatchesSearchPattern(material, geo.Material?.Name ?? ""));
}
return false;
}
/// <summary>
/// Finds the index of an input parameter by its Name.
/// Returns null if the parameter doesn't exist.
/// </summary>
private int? FindInputIndexByName(string paramName)
{
for (int i = 0; i < Params.Input.Count; i++)
{
if (Params.Input[i].Name == paramName)
{
return i;
}
}
return null;
}
#region IGH_VariableParameterComponent
public bool CanInsertParameter(GH_ParameterSide side, int index)
{
if (side != GH_ParameterSide.Input)
{
return false;
}
// only allow inserting after the fixed parameters (index 4+)
if (index < 4)
{
return false;
}
// check how many optional params are already added (total inputs - 4 fixed)
int addedOptionalCount = Params.Input.Count - 4;
// we have 2 optional parameters available
return addedOptionalCount < 2;
}
public bool CanRemoveParameter(GH_ParameterSide side, int index) =>
// only allow removing optional input parameters (index 4+)
side == GH_ParameterSide.Input
&& index >= 4;
/// <remarks>
/// The ternary operator for NickName is needed due to a Grasshopper quirk where
/// dynamically created parameters don't respect the "Draw Full Names" setting automatically.
/// We check CanvasFullNames at creation time to set the appropriate NickName.
/// This does not handle the case where the user toggles "Draw Full Names" while the
/// component is already on the canvas. Handling that would require subscribing to
/// Grasshopper.CentralSettings.CanvasFullNamesChanged event, which is overkill for now.
/// </remarks>
public IGH_Param CreateParameter(GH_ParameterSide side, int index)
{
bool hasAppId = FindInputIndexByName("Application Id").HasValue;
bool hasSpeckleId = FindInputIndexByName("Speckle Id").HasValue;
if (!hasAppId)
{
return new Param_String
{
Name = "Application Id",
NickName = Grasshopper.CentralSettings.CanvasFullNames ? "Application Id" : "aID", // see remarks
Description = "Find objects with a matching applicationId",
Access = GH_ParamAccess.item,
Optional = true
};
}
if (!hasSpeckleId)
{
return new Param_String
{
Name = "Speckle Id",
NickName = Grasshopper.CentralSettings.CanvasFullNames ? "Speckle Id" : "sID", // see remarks
Description = "Find objects with a matching Speckle id",
Access = GH_ParamAccess.item,
Optional = true
};
}
return new Param_String();
}
public bool DestroyParameter(GH_ParameterSide side, int index) => side == GH_ParameterSide.Input && index >= 4;
public void VariableParameterMaintenance()
{
// ensure all optional parameters stay marked as optional
for (int i = 4; i < Params.Input.Count; i++)
{
Params.Input[i].Optional = true;
}
}
#endregion
}
@@ -9,7 +9,7 @@ namespace Speckle.Connectors.GrasshopperShared.Components.Objects;
[Guid("8D2E3F4A-1B5C-4E7F-9A8B-3C6D9E2F1A4B")]
public class SpeckleBlockDefinitionPassthrough()
: SpecklePassthroughComponentBase(
: SpeckleSolveInstance(
"Speckle Block Definition",
"SBD",
"Create or modify a Speckle Block Definition",
@@ -21,9 +21,6 @@ public class SpeckleBlockDefinitionPassthrough()
protected override Bitmap Icon => Resources.speckle_objects_block_def;
public override GH_Exposure Exposure => GH_Exposure.tertiary;
protected override int FixedInputCount => 3;
protected override int FixedOutputCount => 3;
protected override void RegisterInputParams(GH_InputParamManager pManager)
{
pManager.AddParameter(
@@ -125,16 +122,12 @@ public class SpeckleBlockDefinitionPassthrough()
result.Value.Name = inputName;
}
// process application id (only if user provided one, otherwise preserve existing)
if (TryGetApplicationIdInput(da, out string? inputAppId))
{
result.Value.ApplicationId = inputAppId;
}
// no need to process application Id.
// New definitions should have a new appID generated in the new() constructor, and we want to preserve old appID otherwise for changetracking.
// set outputs
da.SetData(0, result);
da.SetDataList(1, result.Value.Objects.Select(o => o.CreateGoo()));
da.SetData(2, result.Value.Name);
SetApplicationIdOutput(da, result.Value.ApplicationId);
}
}
@@ -9,7 +9,7 @@ namespace Speckle.Connectors.GrasshopperShared.Components.Objects;
[Guid("2F8A9B1C-3D4E-5F6A-7B8C-9D0E1F2A3B4C")]
public class SpeckleBlockInstancePassthrough()
: SpecklePassthroughComponentBase(
: SpeckleSolveInstance(
"Speckle Block Instance",
"SBI",
"Create or modify a Speckle Block Instance",
@@ -21,9 +21,6 @@ public class SpeckleBlockInstancePassthrough()
protected override Bitmap Icon => Resources.speckle_objects_block_inst;
public override GH_Exposure Exposure => GH_Exposure.tertiary;
protected override int FixedInputCount => 7;
protected override int FixedOutputCount => 7;
protected override void RegisterInputParams(GH_InputParamManager pManager)
{
int instanceIndex = pManager.AddParameter(
@@ -208,11 +205,8 @@ public class SpeckleBlockInstancePassthrough()
result.Value.Material = inputMaterial.Value;
}
// process application id (only if user provided one, otherwise preserve existing)
if (TryGetApplicationIdInput(da, out string? inputAppId))
{
result.Value.ApplicationId = inputAppId;
}
// no need to process application id.
// new appids are generated if this is a new object, otherwise the input object appID should be preserved for change tracking.
// Set outputs
da.SetData(0, result);
@@ -222,7 +216,6 @@ public class SpeckleBlockInstancePassthrough()
da.SetData(4, result.Value.Properties);
da.SetData(5, result.Value.Color);
da.SetData(6, result.Value.Material);
SetApplicationIdOutput(da, result.Value.ApplicationId);
}
private Transform? ExtractTransform(IGH_Goo input) =>
@@ -8,7 +8,7 @@ namespace Speckle.Connectors.GrasshopperShared.Components.Objects;
[Guid("5CE8AA40-7706-4893-853D-4C77604548FA")]
public class SpeckleDataObjectPassthrough()
: SpecklePassthroughComponentBase(
: SpeckleSolveInstance(
"Speckle Data Object",
"SDO",
"Create or modify a Speckle Data Object",
@@ -20,9 +20,6 @@ public class SpeckleDataObjectPassthrough()
protected override Bitmap Icon => Resources.speckle_objects_dataobject;
public override GH_Exposure Exposure => GH_Exposure.secondary;
protected override int FixedInputCount => 4;
protected override int FixedOutputCount => 5;
protected override void RegisterInputParams(GH_InputParamManager pManager)
{
int objIndex = pManager.AddParameter(
@@ -161,17 +158,9 @@ public class SpeckleDataObjectPassthrough()
result.Properties = inputProperties;
}
// process application id (only if user provided one)
if (TryGetApplicationIdInput(da, out string? inputAppId))
{
result.ApplicationId = inputAppId;
}
else
{
// generate application ID for new data objects. Unlike SpeckleGeometry, DataObject wrappers aren't created
// through casting (which auto-generates IDs), so we must explicitly ensure an ID exists here
result.ApplicationId ??= Guid.NewGuid().ToString();
}
// generate application ID for new data objects. Unlike SpeckleGeometry, DataObject wrappers aren't created
// through casting (which auto-generates IDs), so we must explicitly ensure an ID exists here
result.ApplicationId ??= Guid.NewGuid().ToString();
// get the path
string? path =
@@ -183,6 +172,5 @@ public class SpeckleDataObjectPassthrough()
da.SetData(2, result.Name);
da.SetData(3, result.Properties);
da.SetData(4, path);
SetApplicationIdOutput(da, result.ApplicationId);
}
}
@@ -10,7 +10,7 @@ namespace Speckle.Connectors.GrasshopperShared.Components.Objects;
[Guid("F9418610-ACAE-4417-B010-19EBEA6A121F")]
public class SpeckleGeometryPassthrough()
: SpecklePassthroughComponentBase(
: SpeckleSolveInstance(
"Speckle Geometry",
"SG",
"Create or modify a Speckle Geometry",
@@ -22,9 +22,6 @@ public class SpeckleGeometryPassthrough()
protected override Bitmap Icon => Resources.speckle_objects_geometry;
public override GH_Exposure Exposure => GH_Exposure.secondary;
protected override int FixedInputCount => 6;
protected override int FixedOutputCount => 7;
protected override void RegisterInputParams(GH_InputParamManager pManager)
{
int objIndex = pManager.AddGenericParameter(
@@ -223,11 +220,8 @@ public class SpeckleGeometryPassthrough()
result.Material = inputMaterial.Value;
}
// process application id (only if user provided one, otherwise preserve existing)
if (TryGetApplicationIdInput(da, out string? inputAppId))
{
result.ApplicationId = inputAppId;
}
// no need to process application Id.
// New definitions should have a new appID generated in the new() constructor, and we want to preserve old appID otherwise for changetracking.
// get the path
string? path =
@@ -241,7 +235,6 @@ public class SpeckleGeometryPassthrough()
da.SetData(4, result.Color);
da.SetData(5, result.Material);
da.SetData(6, path);
SetApplicationIdOutput(da, result.ApplicationId);
}
// keeps the geometry and wrapped base the same while assigning all other props from the inut wrapper
@@ -1,19 +1,8 @@
using Speckle.Connectors.Common.Operations;
using Speckle.Sdk.Credentials;
using Version = Speckle.Sdk.Api.GraphQL.Models.Version;
namespace Speckle.Connectors.GrasshopperShared.Components.Operations.Receive;
/// <param name="Account"></param>
/// <param name="WorkspaceId"></param>
/// <param name="ProjectId"></param>
/// <param name="ProjectName"></param>
/// <param name="ModelId"></param>
/// <param name="ModelName"></param>
/// <param name="SelectedVersionId"></param>
/// <param name="SourceApplication">See <see cref="Version.sourceApplication"/></param>
/// <param name="ReceivingApplicationSlug">Slug of the application doing the receiving (i.e. the current host app)</param>
/// <param name="SelectedVersionUserId"></param>
public record GrasshopperReceiveInfo(
Account Account,
string? WorkspaceId,
@@ -23,6 +12,5 @@ public record GrasshopperReceiveInfo(
string ModelName,
string SelectedVersionId,
string SourceApplication,
string ReceivingApplicationSlug,
string? SelectedVersionUserId
) : ReceiveInfo(Account, ProjectId, ProjectName, ModelId, ModelName, SelectedVersionId, ReceivingApplicationSlug);
) : ReceiveInfo(Account, ProjectId, ProjectName, ModelId, ModelName, SelectedVersionId, SourceApplication);
@@ -87,7 +87,6 @@ public class SendAsyncComponent : GH_AsyncComponent<SendAsyncComponent>
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
{
pManager.AddParameter(new SpeckleUrlModelResourceParam());
pManager.AddTextParameter("Version ID", "V", "ID of the created version", GH_ParamAccess.item);
}
public override void AppendAdditionalMenuItems(ToolStripDropDown menu)
@@ -322,7 +321,6 @@ public class SendComponentWorker : WorkerInstance<SendAsyncComponent>
private Stopwatch? _stopwatch;
public SpeckleUrlModelResource? OutputParam { get; set; }
public string? OutputVersionId { get; set; }
private List<(GH_RuntimeMessageLevel, string)> RuntimeMessages { get; } = new();
public override WorkerInstance<SendAsyncComponent> Duplicate(string id, CancellationToken cancellationToken)
@@ -334,7 +332,6 @@ public class SendComponentWorker : WorkerInstance<SendAsyncComponent>
{
_stopwatch = new Stopwatch();
_stopwatch.Start();
OutputVersionId = null;
}
public override void SetData(IGH_DataAccess da)
@@ -345,7 +342,6 @@ public class SendComponentWorker : WorkerInstance<SendAsyncComponent>
{
Parent.JustPastedIn = false;
da.SetData(0, Parent.OutputParam);
da.SetData(1, OutputVersionId);
return;
}
@@ -361,7 +357,6 @@ public class SendComponentWorker : WorkerInstance<SendAsyncComponent>
}
da.SetData(0, OutputParam);
da.SetData(1, OutputVersionId);
Parent.CurrentComponentState = ComponentState.UpToDate;
Parent.OutputParam = OutputParam; // ref the outputs in the parent too, so we can serialise them on write/read
@@ -378,7 +373,7 @@ public class SendComponentWorker : WorkerInstance<SendAsyncComponent>
*/
Parent.AddRuntimeMessage(
GH_RuntimeMessageLevel.Remark,
"Successfully published to Speckle. Right-click on the component to view online."
$"Successfully published to Speckle. Right-click on the component to view online."
);
Parent.AddRuntimeMessage(
GH_RuntimeMessageLevel.Remark,
@@ -476,7 +471,6 @@ public class SendComponentWorker : WorkerInstance<SendAsyncComponent>
result.VersionId
);
OutputParam = createdVersion;
OutputVersionId = result.VersionId;
Parent.Url = $"{createdVersion.Account.Server}/projects/{sendInfo.ProjectId}/models/{sendInfo.ModelId}";
}
}
@@ -36,10 +36,9 @@ public class SendComponentInput
}
}
public class SendComponentOutput(SpeckleUrlModelResource? resource, string? versionId = null)
public class SendComponentOutput(SpeckleUrlModelResource? resource)
{
public SpeckleUrlModelResource? Resource { get; } = resource;
public string? VersionId { get; } = versionId;
}
public class SendComponent : SpeckleTaskCapableComponent<SendComponentInput, SendComponentOutput>
@@ -87,11 +86,8 @@ public class SendComponent : SpeckleTaskCapableComponent<SendComponentInput, Sen
pManager.AddBooleanParameter("Run", "r", "Run the publish operation", GH_ParamAccess.item);
}
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
{
protected override void RegisterOutputParams(GH_OutputParamManager pManager) =>
pManager.AddParameter(new SpeckleUrlModelResourceParam());
pManager.AddTextParameter("Version ID", "V", "ID of the created version", GH_ParamAccess.item);
}
protected override SendComponentInput GetInput(IGH_DataAccess da)
{
@@ -138,7 +134,6 @@ public class SendComponent : SpeckleTaskCapableComponent<SendComponentInput, Sen
else
{
da.SetData(0, result.Resource);
da.SetData(1, result.VersionId);
Message = "Done";
}
}
@@ -221,7 +216,7 @@ public class SendComponent : SpeckleTaskCapableComponent<SendComponentInput, Sen
using var client = clientFactory.Create(account);
var sendInfo = await input.Resource.GetSendInfo(client, cancellationToken).ConfigureAwait(false);
var result = await sendOperation
await sendOperation
.Execute(
new List<SpeckleCollectionWrapperGoo> { collectionToSend },
sendInfo,
@@ -249,6 +244,6 @@ public class SendComponent : SpeckleTaskCapableComponent<SendComponentInput, Sen
sendInfo.ModelId
);
Url = $"{sendInfo.Account.serverInfo.url}/projects/{sendInfo.ProjectId}/models/{sendInfo.ModelId}";
return new SendComponentOutput(createdVersionResource, result.VersionId);
return new SendComponentOutput(createdVersionResource);
}
}
@@ -1,231 +0,0 @@
using GH_IO.Serialization;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Parameters;
namespace Speckle.Connectors.GrasshopperShared.Components;
/// <summary>
/// Base class for passthrough components with "hidden" Application ID parameter.
/// </summary>
/// <remarks>
/// Users can click ⊕ to add an optional Application ID input and output.
/// </remarks>
public abstract class SpecklePassthroughComponentBase : SpeckleSolveInstance, IGH_VariableParameterComponent
{
private const string APP_ID_NAME = "Application Id";
private const string APP_ID_NICKNAME = "aID";
private const string APP_ID_DESCRIPTION = "The application id of the Speckle objects";
protected abstract int FixedInputCount { get; }
protected abstract int FixedOutputCount { get; }
private bool HasApplicationIdParam => Params.Input.Count > FixedInputCount;
protected SpecklePassthroughComponentBase(
string name,
string nickname,
string description,
string category,
string subCategory
)
: base(name, nickname, description, category, subCategory) { }
/// <summary>
/// Reads the optional Application Id input. Returns true if user provided a valid value.
/// </summary>
protected bool TryGetApplicationIdInput(IGH_DataAccess da, out string? applicationId)
{
applicationId = null;
if (!HasApplicationIdParam)
{
return false;
}
string appId = string.Empty;
if (da.GetData(FixedInputCount, ref appId))
{
if (string.IsNullOrWhiteSpace(appId))
{
AddRuntimeMessage(
GH_RuntimeMessageLevel.Warning,
"Empty Application Id ignored - existing or auto-generated id will be used"
);
return false;
}
applicationId = appId;
return true;
}
return false;
}
/// <summary>
/// Sets the Application Id output (if the parameter exists).
/// </summary>
protected void SetApplicationIdOutput(IGH_DataAccess da, string? applicationId)
{
if (!HasApplicationIdParam)
{
return;
}
da.SetData(FixedOutputCount, applicationId);
}
public bool CanInsertParameter(GH_ParameterSide side, int index)
{
// only allow inserting if not yet added
if (HasApplicationIdParam)
{
return false;
}
// only allow at the end position
return side switch
{
GH_ParameterSide.Input => index == FixedInputCount,
GH_ParameterSide.Output => index == FixedOutputCount,
_ => false
};
}
public bool CanRemoveParameter(GH_ParameterSide side, int index)
{
if (!HasApplicationIdParam)
{
return false;
}
return side switch
{
GH_ParameterSide.Input => index == FixedInputCount,
GH_ParameterSide.Output => index == FixedOutputCount,
_ => false
};
}
/// <remarks>
/// The ternary for NickName handles a Grasshopper quirk where dynamically created parameters
/// don't respect the "Draw Full Names" setting automatically.
/// </remarks>
public IGH_Param CreateParameter(GH_ParameterSide side, int index)
{
// when adding on either side, add both input and output together
if (side == GH_ParameterSide.Input && Params.Output.Count == FixedOutputCount)
{
OnPingDocument()?.ScheduleSolution(5, _ => AddApplicationIdOutput());
}
else if (side == GH_ParameterSide.Output && Params.Input.Count == FixedInputCount)
{
OnPingDocument()?.ScheduleSolution(5, _ => AddApplicationIdInput());
}
return CreateApplicationIdParam();
}
public bool DestroyParameter(GH_ParameterSide side, int index)
{
// when removing from either side, remove both input and output together
if (side == GH_ParameterSide.Input && index == FixedInputCount && Params.Output.Count > FixedOutputCount)
{
OnPingDocument()?.ScheduleSolution(5, _ => RemoveApplicationIdOutput());
}
else if (side == GH_ParameterSide.Output && index == FixedOutputCount && Params.Input.Count > FixedInputCount)
{
OnPingDocument()?.ScheduleSolution(5, _ => RemoveApplicationIdInput());
}
return side switch
{
GH_ParameterSide.Input => index == FixedInputCount,
GH_ParameterSide.Output => index == FixedOutputCount,
_ => false
};
}
public void VariableParameterMaintenance()
{
// ensure the Application Id input stays optional
if (HasApplicationIdParam && Params.Input.Count > FixedInputCount)
{
Params.Input[FixedInputCount].Optional = true;
}
}
private static IGH_Param CreateApplicationIdParam() =>
new Param_String
{
Name = APP_ID_NAME,
NickName = Grasshopper.CentralSettings.CanvasFullNames ? APP_ID_NAME : APP_ID_NICKNAME,
Description = APP_ID_DESCRIPTION,
Access = GH_ParamAccess.item,
Optional = true
};
private void AddApplicationIdInput()
{
if (Params.Input.Count > FixedInputCount)
{
return;
}
Params.RegisterInputParam(CreateApplicationIdParam());
Params.OnParametersChanged();
VariableParameterMaintenance();
ExpireSolution(true);
}
private void AddApplicationIdOutput()
{
if (Params.Output.Count > FixedOutputCount)
{
return;
}
Params.RegisterOutputParam(CreateApplicationIdParam());
Params.OnParametersChanged();
ExpireSolution(true);
}
private void RemoveApplicationIdInput()
{
if (Params.Input.Count <= FixedInputCount)
{
return;
}
Params.UnregisterInputParameter(Params.Input[FixedInputCount]);
Params.OnParametersChanged();
ExpireSolution(true);
}
private void RemoveApplicationIdOutput()
{
if (Params.Output.Count <= FixedOutputCount)
{
return;
}
Params.UnregisterOutputParameter(Params.Output[FixedOutputCount]);
Params.OnParametersChanged();
ExpireSolution(true);
}
public override bool Write(GH_IWriter writer)
{
var result = base.Write(writer);
writer.SetBoolean("HasApplicationIdParam", HasApplicationIdParam);
return result;
}
public override bool Read(GH_IReader reader)
{
var result = base.Read(reader);
// parameters are restored by GH serialization, this flag is for reference
bool hasAppIdParam = false;
reader.TryGetBoolean("HasApplicationIdParam", ref hasAppIdParam);
return result;
}
}
@@ -1,83 +0,0 @@
using Speckle.Connectors.GrasshopperShared.Parameters;
using Speckle.Sdk.Models.Collections;
namespace Speckle.Connectors.GrasshopperShared.Components.Collections;
/// <summary>
/// Shared helper methods for collection components to avoid code duplication
/// </summary>
public static class CollectionHelpers
{
/// <summary>
/// Creates a root collection wrapper with default values
/// </summary>
public static SpeckleCollectionWrapper CreateRootCollection(string instanceGuid) =>
new SpeckleCollectionWrapper
{
Base = new Collection(),
Name = "Unnamed",
Path = new List<string> { "Unnamed" },
Color = null,
Material = null,
ApplicationId = instanceGuid
};
/// <summary>
/// Validates that all application IDs are unique across the entire collection hierarchy.
/// </summary>
/// <returns>True if duplicates exist, false if all IDs are unique</returns>
public static bool HasDuplicateApplicationIds(SpeckleCollectionWrapper rootCollection)
{
var seenIds = new HashSet<string>();
var duplicateIds = new HashSet<string>();
ProcessAndCheckForDuplicateApplicationIds(rootCollection, seenIds, duplicateIds);
return duplicateIds.Count > 0;
}
/// <summary>
/// Recursively collects application IDs from all wrappers in the collection hierarchy.
/// </summary>
/// <remarks>
/// Only checks the wrapper's ApplicationId, not for example geometries within DataObjects.
/// </remarks>
private static void ProcessAndCheckForDuplicateApplicationIds(
SpeckleCollectionWrapper collection,
HashSet<string> seenIds,
HashSet<string> duplicateIds
)
{
foreach (var element in collection.Elements)
{
switch (element)
{
case null:
break; // skip nulls (CNX-2855)
case SpeckleCollectionWrapper childCollection:
// recurse into child collections
ProcessAndCheckForDuplicateApplicationIds(childCollection, seenIds, duplicateIds);
break;
case SpeckleWrapper wrapper:
if (wrapper.ApplicationId != null && !seenIds.Add(wrapper.ApplicationId))
{
duplicateIds.Add(wrapper.ApplicationId);
}
break;
}
}
}
/// <summary>
/// Recursively checks if collection or any descendants contain valid geometry/data objects
/// </summary>
public static bool HasAnyValidContent(ISpeckleCollectionObject? element) =>
element switch
{
SpeckleGeometryWrapper => true,
SpeckleDataObjectWrapper => true,
SpeckleCollectionWrapper collection => collection.Elements.Any(HasAnyValidContent),
_ => false
};
}
@@ -1,5 +1,4 @@
using Microsoft.Extensions.DependencyInjection;
using Speckle.Connectors.Common;
using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.GrasshopperShared.Components.Operations.Receive;
using Speckle.Connectors.GrasshopperShared.Components.Operations.Send;
@@ -51,7 +50,6 @@ public record SpeckleUrlLatestModelVersionResource(
model.name,
version.id,
version.sourceApplication.NotNull(),
HostApplications.Grasshopper.Slug,
version.authorUser?.id
);
@@ -67,7 +65,13 @@ public record SpeckleUrlLatestModelVersionResource(
await client.Project.Get(ProjectId, cancellationToken).ConfigureAwait(false);
await client.Model.Get(ModelId, ProjectId, cancellationToken).ConfigureAwait(false);
return new GrasshopperSendInfo(client.Account, WorkspaceId, ProjectId, ModelId, HostApplications.Grasshopper.Slug);
return new GrasshopperSendInfo(
client.Account,
WorkspaceId,
ProjectId,
ModelId,
"Grasshopper8" // TODO: Grab from the right place!
);
}
}
@@ -97,7 +101,6 @@ public record SpeckleUrlModelVersionResource(
model.name,
VersionId,
version.sourceApplication.NotNull(),
HostApplications.Grasshopper.Slug,
version.authorUser?.id
);
@@ -113,7 +116,13 @@ public record SpeckleUrlModelVersionResource(
await client.Project.Get(ProjectId, cancellationToken).ConfigureAwait(false);
await client.Model.Get(ModelId, ProjectId, cancellationToken).ConfigureAwait(false);
return new GrasshopperSendInfo(client.Account, WorkspaceId, ProjectId, ModelId, HostApplications.Grasshopper.Slug);
return new GrasshopperSendInfo(
client.Account,
WorkspaceId,
ProjectId,
ModelId,
"Grasshopper8" // TODO: Grab from the right place!
);
}
}
@@ -95,7 +95,7 @@ public class GrasshopperReceiveOperation
.ConfigureAwait(false);
await apiClient
.Version.Received(new(version.id, receiveInfo.ProjectId, receiveInfo.ReceivingApplicationSlug), cancellationToken)
.Version.Received(new(version.id, receiveInfo.ProjectId, receiveInfo.SourceApplication), cancellationToken)
.ConfigureAwait(false);
return commitObject;
}
@@ -225,14 +225,6 @@ internal sealed class LocalToGlobalMapHandler
var entry = _dataObjectInstanceRegistry.GetEntries()[dataObjectId];
var resolvedGeometries = ResolveInstanceProxiesToGeometries(entry.InstanceProxies);
var primitiveConverted = dataObject
.displayValue.Where(item => item is not InstanceProxy)
.SelectMany(item => SpeckleConversionContext.Current.ConvertToHost(item))
.ToList();
resolvedGeometries.AddRange(ConvertToGeometryWrappers(primitiveConverted));
var dataObjectWrapper = CreateDataObjectWrapper(dataObject, resolvedGeometries, path, objectCollection);
CollectionRebuilder.AppendSpeckleGrasshopperObject(dataObjectWrapper, path, _colorUnpacker, _materialUnpacker);
@@ -14,7 +14,6 @@
<Compile Include="$(MSBuildThisFileDirectory)Components\BaseComponents\ValueSet.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Components\BaseComponents\VariableParameterComponentBase.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Components\Collections\CollectionPathsSelector.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Components\Collections\CollectionsByName.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Components\Collections\CreateCollection.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Components\Collections\ExpandCollection.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Components\Objects\ExpandSpeckleProperties.cs" />
@@ -42,9 +41,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Components\Operations\Wizard\VersionMenuHandler.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Components\Operations\Wizard\WorkspaceMenuHandler.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Components\Operations\Wizard\SpeckleOperationWizard.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Components\SpecklePassthroughComponentBase.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Components\SpeckleSolveInstance.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\CollectionHelpers.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\Extras\StateTag.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\KeyWatcher.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Operations\Receive\GrasshopperBlockUnpacker.cs" />
@@ -185,8 +185,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -328,15 +328,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -362,7 +361,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.converters.rhino7": {
@@ -422,11 +421,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Resources.Extensions": {
@@ -438,12 +437,6 @@
"System.Formats.Nrbf": "9.0.4",
"System.Memory": "4.5.5"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
}
}
@@ -185,8 +185,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -328,15 +328,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -362,7 +361,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.converters.rhino8": {
@@ -421,11 +420,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Resources.Extensions": {
@@ -437,12 +436,6 @@
"System.Formats.Nrbf": "9.0.4",
"System.Memory": "4.5.5"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
}
}
@@ -174,8 +174,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -255,15 +255,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -280,7 +279,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.converters.rhino8": {
@@ -330,18 +329,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
},
"net8.0-windows7.0/win-x64": {
@@ -122,9 +122,7 @@ public class RhinoLayerBaker : TraversalContextUnpacker
continue;
}
var cleanNewLayerName = string.IsNullOrWhiteSpace(collection.name)
? "unnamed"
: RhinoUtils.CleanLayerName(collection.name);
var cleanNewLayerName = RhinoUtils.CleanLayerName(collection.name);
if (!ModelComponent.IsValidComponentName(cleanNewLayerName))
{
@@ -14,7 +14,6 @@ public static class RhinoUtils
public static string CleanLayerName(string str)
{
var sb = new StringBuilder(str.Length);
bool lastWasSpace = true;
foreach (char c in str)
{
@@ -31,29 +30,10 @@ public static class RhinoUtils
if (s_replaceWithHyphen.Contains(c))
{
sb.Append('-');
lastWasSpace = false;
continue;
}
// Collapse double spaces into one and skip leading spaces.
// e.g. " Items Name " -> "Items Name"
if (c == ' ')
{
if (!lastWasSpace)
{
sb.Append(c);
lastWasSpace = true;
}
continue;
}
sb.Append(c);
lastWasSpace = false;
}
if (sb.Length > 0 && sb[^1] == ' ')
{
sb.Length--;
}
return sb.ToString();
@@ -2,7 +2,6 @@ using Microsoft.Extensions.DependencyInjection;
using Rhino.PlugIns;
using Speckle.Connectors.Common;
using Speckle.Connectors.DUI;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.Rhino.DependencyInjection;
using Speckle.Converters.Rhino;
using Speckle.Sdk;
@@ -51,10 +50,6 @@ public class SpeckleConnectorsRhinoPlugin : PlugIn
// but the Rhino connector has `.rhp` as it is extension.
Container = services.BuildServiceProvider();
// FORCE INITIALIZATION RhinoDocumentStore to register event handlers for BeginOpenDocument and EndOpenDocument
// this is needed when the user opens a Rhino file by double clicking the file,
// instead of opening a file in an already running Rhino instance
Container.GetRequiredService<DocumentModelStore>();
Container.UseDUI();
return LoadReturnCode.Success;
@@ -210,8 +210,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -221,13 +221,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -347,15 +347,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -381,7 +380,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"LibTessDotNet": {
@@ -431,18 +430,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
}
}
@@ -229,8 +229,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -240,13 +240,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -428,15 +428,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -462,7 +461,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"LibTessDotNet": {
@@ -512,18 +511,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
}
}
@@ -229,8 +229,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -240,13 +240,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -428,15 +428,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -462,7 +461,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"LibTessDotNet": {
@@ -512,18 +511,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
}
}
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -279,7 +279,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"Microsoft.Extensions.Logging": {
@@ -308,11 +308,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
}
}
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -279,7 +279,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"Microsoft.Extensions.Logging": {
@@ -308,11 +308,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
}
}
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -281,15 +281,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -306,7 +305,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -350,18 +349,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
}
}
@@ -157,8 +157,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -230,15 +230,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -255,7 +254,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -299,18 +298,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
}
}
@@ -157,8 +157,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -230,15 +230,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -255,7 +254,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -299,18 +298,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
}
}
@@ -171,8 +171,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -279,7 +279,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"Microsoft.Extensions.Logging": {
@@ -308,11 +308,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
}
}
@@ -157,8 +157,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -228,7 +228,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"Microsoft.Extensions.Logging": {
@@ -257,11 +257,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
}
}
@@ -180,8 +180,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -191,13 +191,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -288,7 +288,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"Microsoft.Extensions.Logging": {
@@ -317,11 +317,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
}
}
@@ -180,8 +180,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -191,13 +191,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -288,7 +288,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"Microsoft.Extensions.Logging": {
@@ -317,11 +317,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
}
}
@@ -180,8 +180,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -191,13 +191,13 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -288,7 +288,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"Microsoft.Extensions.Logging": {
@@ -317,11 +317,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
}
}
@@ -166,8 +166,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -239,15 +239,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -264,7 +263,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -308,18 +307,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
}
}
@@ -166,8 +166,8 @@
},
"Speckle.Sdk": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "LbKL7I5lFa2R8nSkY6FsePipSR3qQHr/6lxvCHX1Q/zyRxHYrcQXQo0X9gxuCjun/b6PThosdysOiYtRVaDZnA==",
"resolved": "3.11.1",
"contentHash": "D04pCdleqLeDxthANCb8+X1xfEYr4+Q3GTuHtqOrMQeGHDAVPc5G3M0D6VYEUYbLYav0NBZ6tNuWO2Y/fqfWSw==",
"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.12.0"
"Speckle.Sdk.Dependencies": "3.11.1"
}
},
"Speckle.Sdk.Dependencies": {
"type": "Transitive",
"resolved": "3.12.0",
"contentHash": "L8eoBpEYIlJ593bAltaIAxcwbmwALSdL4+6ayjtzRlHX3bUfsGKd6jj/r0P4xX3H4tQFJScPn7u89oHitHaaPQ=="
"resolved": "3.11.1",
"contentHash": "u8lJ+ECslmVPsn4yOCg3hAzj3zh6r+gp2oQh8RDGn22NihIPOsMhBFvoBruL1QVhXdJcS4rI2J6VEAbdvL9FRg=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
@@ -239,15 +239,14 @@
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"System.Threading.Tasks.Dataflow": "[10.0.2, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -264,7 +263,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.12.0, )"
"Speckle.Objects": "[3.11.1, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -308,18 +307,12 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.12.0, )",
"resolved": "3.12.0",
"contentHash": "IQ9dcPsBnm207TFrxGDAPlL3T+9JSkqxczClK9G67saYHjsMAowrh71GkqgsZGxk5x0dCnbAOnV4szj2c6gJ5A==",
"requested": "[3.11.1, )",
"resolved": "3.11.1",
"contentHash": "JUCY3bA6Pa+fa6wZV9uQ9mhLRihvICkF58nIr28Yi94j0th7wSg4l8WeThl3ubKVnHDQE5mdVffVlY1e5ZUkuQ==",
"dependencies": {
"Speckle.Sdk": "3.12.0"
"Speckle.Sdk": "3.11.1"
}
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "h1jjCvwBFPXfH4y8KeGXERA+D/oKWUwZ5zX8TXO3YSQRi7zWiNxhvc8GTgFFEW11yTvepjVugDxemtzNDMW7Qw=="
}
}
}
@@ -1,3 +1,3 @@
namespace Speckle.Converters.Civil3dShared;
public record Civil3dConversionSettings(Document Document, string SpeckleUnits);
public record Civil3dConversionSettings(Document Document, string SpeckleUnits, bool MappingToRevitCategories = false);
@@ -7,8 +7,8 @@ namespace Speckle.Converters.Civil3dShared;
public class Civil3dConversionSettingsFactory(IHostToSpeckleUnitConverter<AAEC.BuiltInUnit> unitsConverter)
: ICivil3dConversionSettingsFactory
{
public Civil3dConversionSettings Create(Document document) =>
new(document, unitsConverter.ConvertOrThrow(GetDocBuiltInUnit(document)));
public Civil3dConversionSettings Create(Document document, bool mappingToRevitCategories = false) =>
new(document, unitsConverter.ConvertOrThrow(GetDocBuiltInUnit(document)), mappingToRevitCategories);
private static AAEC.BuiltInUnit GetDocBuiltInUnit(Document doc)
{

Some files were not shown because too many files have changed in this diff Show More