Compare commits
49 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a945e35a2a | |||
| e7ee172f90 | |||
| d49b1eea33 | |||
| d8afd74171 | |||
| b88f50ced6 | |||
| e130045930 | |||
| ae72cc3adb | |||
| 816539ce18 | |||
| c6cdb0d893 | |||
| dd026e24a3 | |||
| 76015ed30c | |||
| b9fbf60df5 | |||
| 50d69a0f0e | |||
| 2f8477e072 | |||
| 973a91ac5a | |||
| 60a39b775c | |||
| f84b5e7c90 | |||
| 5e93f23d06 | |||
| 471613a77f | |||
| 778ddf4b47 | |||
| 180c1d8345 | |||
| ae847d8625 | |||
| a4ba43a632 | |||
| b7d23aea8d | |||
| bb8634f650 | |||
| 34c56e7c41 | |||
| a92986c1ce | |||
| 831e5c0a82 | |||
| 2adfee6f49 | |||
| 4bb67318a8 | |||
| dadf07a3c3 | |||
| 7f6c8bb1a3 | |||
| eb8db87d9f | |||
| bf91a8d6a3 | |||
| bce949951c | |||
| 744b185cfe | |||
| 8919ba2491 | |||
| fc82dda558 | |||
| d70fe9df73 | |||
| d2c78695fe | |||
| 4aa087e38d | |||
| a3cbb1bcb6 | |||
| 60823dda97 | |||
| 40650bfed2 | |||
| b0423af14b | |||
| 636af5c7c2 | |||
| efc532fce0 | |||
| 4bf54550aa | |||
| 43773c63eb |
@@ -81,7 +81,6 @@ public static class Solutions
|
||||
|
||||
var revit = Consts.ProjectGroups.Single(x => x.HostAppSlug.Equals("revit"));
|
||||
await GenerateConnector(connectors, revit, "Revit.Local");
|
||||
await GenerateMacSolutions();
|
||||
}
|
||||
|
||||
public static async Task GenerateConnector(SolutionModel connectors, ProjectGroup group, string? name)
|
||||
@@ -115,23 +114,4 @@ public static class Solutions
|
||||
var connectorsSln = Path.Combine(DIRECTORY, solutionName);
|
||||
return await SolutionSerializers.SlnFileV12.OpenAsync(connectorsSln, default);
|
||||
}
|
||||
|
||||
public static async Task GenerateMacSolutions()
|
||||
{
|
||||
var connectors = await GetFullSlnx();
|
||||
var foldersToRemove = connectors
|
||||
.SolutionFolders.Where(x =>
|
||||
//need base folder
|
||||
!x.Path.Equals("/Connectors/")
|
||||
//don't grab all
|
||||
&& (x.Path.StartsWith("/Connectors/"))
|
||||
)
|
||||
.ToList();
|
||||
foreach (var folderToRemove in foldersToRemove)
|
||||
{
|
||||
connectors.RemoveFolder(folderToRemove);
|
||||
}
|
||||
var sln = Path.Combine(DIRECTORY, $"Speckle.Connectors.Mac.slnx");
|
||||
await SolutionSerializers.SlnXml.SaveAsync(sln, connectors, default);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project>
|
||||
<Target AfterTargets="Clean" Name="CleanAddinAutocad" Condition="'$(AutoCADVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
|
||||
<Target AfterTargets="Clean" Name="CleanAddinAutocad" Condition="'$(AutoCADVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true' And '$(OS)' == 'Windows_NT'">
|
||||
<RemoveDir Directories="$(AppData)\Autodesk\ApplicationPlugins\Speckle.Connectors.Autocad$(AutoCADVersion);" />
|
||||
</Target>
|
||||
|
||||
<Target AfterTargets="Build" Name="AfterBuildAutoCAD" Condition="'$(AutoCADVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
|
||||
<Target AfterTargets="Build" Name="AfterBuildAutoCAD" Condition="'$(AutoCADVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true' And '$(OS)' == 'Windows_NT'">
|
||||
<ItemGroup>
|
||||
<AutoCADDLLs Include="$(TargetDir)\**\*.*" />
|
||||
</ItemGroup>
|
||||
@@ -12,11 +12,11 @@
|
||||
<Copy DestinationFolder="$(AppData)\Autodesk\ApplicationPlugins\Speckle.Connectors.Autocad$(AutoCADVersion)\%(RecursiveDir)" SourceFiles="@(AutoCADDLLs)" />
|
||||
</Target>
|
||||
|
||||
<Target AfterTargets="Clean" Name="CleanAddinCivil3D" Condition="'$(Civil3DVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
|
||||
<Target AfterTargets="Clean" Name="CleanAddinCivil3D" Condition="'$(Civil3DVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true' And '$(OS)' == 'Windows_NT'">
|
||||
<RemoveDir Directories="$(AppData)\Autodesk\ApplicationPlugins\Speckle.Connectors.Civil3d$(Civil3DVersion);" />
|
||||
</Target>
|
||||
|
||||
<Target AfterTargets="Build" Name="AfterBuildCivil3D" Condition="'$(Civil3DVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
|
||||
<Target AfterTargets="Build" Name="AfterBuildCivil3D" Condition="'$(Civil3DVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true' And '$(OS)' == 'Windows_NT'">
|
||||
<ItemGroup>
|
||||
<Civil3DDLLs Include="$(TargetDir)\**\*.*" />
|
||||
</ItemGroup>
|
||||
@@ -24,11 +24,11 @@
|
||||
<Copy DestinationFolder="$(AppData)\Autodesk\ApplicationPlugins\Speckle.Connectors.Civil3d$(Civil3DVersion)\%(RecursiveDir)" SourceFiles="@(Civil3DDLLs)" />
|
||||
</Target>
|
||||
|
||||
<PropertyGroup Condition="'$(AutoCADVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
|
||||
<PropertyGroup Condition="'$(AutoCADVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true' And '$(OS)' == 'Windows_NT'">
|
||||
<StartAction>Program</StartAction>
|
||||
<StartProgram>$(ProgramW6432)\Autodesk\AutoCAD $(AutoCADVersion)\acad.exe</StartProgram>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Civil3DVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
|
||||
<PropertyGroup Condition="'$(Civil3DVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true' And '$(OS)' == 'Windows_NT'">
|
||||
<StartAction>Program</StartAction>
|
||||
<StartProgram>$(ProgramW6432)\Autodesk\AutoCAD $(Civil3DVersion)\acad.exe</StartProgram>
|
||||
<StartArguments>/product C3D</StartArguments>
|
||||
|
||||
@@ -259,9 +259,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -292,7 +292,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
@@ -336,18 +336,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -357,14 +357,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,9 +259,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -292,7 +292,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
@@ -336,18 +336,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -357,14 +357,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,9 +259,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -293,7 +293,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
@@ -337,18 +337,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -358,14 +358,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,9 +210,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -244,7 +244,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
@@ -288,18 +288,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.5",
|
||||
@@ -307,14 +307,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
},
|
||||
"net8.0-windows7.0/win-x64": {
|
||||
|
||||
@@ -210,9 +210,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -244,7 +244,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
@@ -288,18 +288,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.5",
|
||||
@@ -307,14 +307,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
},
|
||||
"net8.0-windows7.0/win-x64": {
|
||||
|
||||
+2
-1
@@ -2,6 +2,7 @@ using Speckle.Connectors.Common.Cancellation;
|
||||
using Speckle.Connectors.Common.Threading;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Models.Card;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Bindings;
|
||||
|
||||
@@ -17,7 +18,7 @@ public abstract class AutocadReceiveBaseBinding(
|
||||
|
||||
private ReceiveBindingUICommands Commands { get; } = new(parent);
|
||||
|
||||
protected abstract void InitializeSettings(IServiceProvider serviceProvider);
|
||||
protected abstract void InitializeSettings(IServiceProvider serviceProvider, ModelCard mc);
|
||||
|
||||
public void CancelReceive(string modelCardId) => cancellationManager.CancelOperation(modelCardId);
|
||||
|
||||
|
||||
+2
-1
@@ -3,6 +3,7 @@ using Speckle.Connectors.Common.Cancellation;
|
||||
using Speckle.Connectors.Common.Threading;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Models.Card;
|
||||
using Speckle.Converters.Autocad;
|
||||
using Speckle.Converters.Common;
|
||||
|
||||
@@ -24,7 +25,7 @@ public sealed class AutocadReceiveBinding : AutocadReceiveBaseBinding
|
||||
_autocadConversionSettingsFactory = autocadConversionSettingsFactory;
|
||||
}
|
||||
|
||||
protected override void InitializeSettings(IServiceProvider serviceProvider)
|
||||
protected override void InitializeSettings(IServiceProvider serviceProvider, ModelCard mc)
|
||||
{
|
||||
serviceProvider
|
||||
.GetRequiredService<IConverterSettingsStore<AutocadConversionSettings>>()
|
||||
|
||||
+11
@@ -3,6 +3,7 @@ using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Connectors.Common.Instances;
|
||||
using Speckle.Converters.AutocadShared.ToSpeckle;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.DoubleNumerics;
|
||||
using Speckle.Sdk;
|
||||
@@ -17,16 +18,19 @@ public class AutocadInstanceUnpacker : IInstanceUnpacker<AutocadRootObject>
|
||||
{
|
||||
private readonly IHostToSpeckleUnitConverter<UnitsValue> _unitsConverter;
|
||||
private readonly IInstanceObjectsManager<AutocadRootObject, List<Entity>> _instanceObjectsManager;
|
||||
private readonly IPropertiesExtractor _propertiesExtractor;
|
||||
private readonly ILogger<AutocadInstanceUnpacker> _logger;
|
||||
|
||||
public AutocadInstanceUnpacker(
|
||||
IHostToSpeckleUnitConverter<UnitsValue> unitsConverter,
|
||||
IInstanceObjectsManager<AutocadRootObject, List<Entity>> instanceObjectsManager,
|
||||
IPropertiesExtractor propertiesExtractor,
|
||||
ILogger<AutocadInstanceUnpacker> logger
|
||||
)
|
||||
{
|
||||
_unitsConverter = unitsConverter;
|
||||
_instanceObjectsManager = instanceObjectsManager;
|
||||
_propertiesExtractor = propertiesExtractor;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
@@ -71,6 +75,13 @@ public class AutocadInstanceUnpacker : IInstanceUnpacker<AutocadRootObject>
|
||||
transform = GetMatrix(instance.BlockTransform.ToArray()),
|
||||
units = _unitsConverter.ConvertOrThrow(Application.DocumentManager.CurrentDocument.Database.Insunits)
|
||||
};
|
||||
|
||||
var properties = _propertiesExtractor.GetProperties(instance);
|
||||
if (properties?.Count > 0)
|
||||
{
|
||||
instanceProxy["properties"] = properties;
|
||||
}
|
||||
|
||||
_instanceObjectsManager.AddInstanceProxy(instanceId, instanceProxy);
|
||||
|
||||
// For each block instance that has the same definition, we need to keep track of the "maximum depth" at which is found.
|
||||
|
||||
+2
-8
@@ -60,7 +60,7 @@ public abstract class AutocadRootObjectBaseBuilder : IRootObjectBuilder<AutocadR
|
||||
)]
|
||||
public Task<RootObjectBuilderResult> Build(
|
||||
IReadOnlyList<AutocadRootObject> objects,
|
||||
SendInfo sendInfo,
|
||||
string projectId,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
@@ -106,13 +106,7 @@ public abstract class AutocadRootObjectBaseBuilder : IRootObjectBuilder<AutocadR
|
||||
root.elements.Add(objectCollection);
|
||||
}
|
||||
|
||||
var result = ConvertAutocadEntity(
|
||||
entity,
|
||||
applicationId,
|
||||
objectCollection,
|
||||
instanceProxies,
|
||||
sendInfo.ProjectId
|
||||
);
|
||||
var result = ConvertAutocadEntity(entity, applicationId, objectCollection, instanceProxies, projectId);
|
||||
results.Add(result);
|
||||
|
||||
onOperationProgressed.Report(new("Converting", (double)++count / atomicObjects.Count));
|
||||
|
||||
@@ -268,9 +268,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -302,7 +302,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
@@ -346,18 +346,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -367,14 +367,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,9 +268,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -302,7 +302,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
@@ -346,18 +346,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -367,14 +367,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,9 +268,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -302,7 +302,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
@@ -346,18 +346,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -367,14 +367,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,9 +219,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -254,7 +254,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
@@ -298,18 +298,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.5",
|
||||
@@ -317,14 +317,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
},
|
||||
"net8.0-windows7.0/win-x64": {
|
||||
|
||||
@@ -219,9 +219,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -254,7 +254,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
@@ -298,18 +298,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.5",
|
||||
@@ -317,14 +317,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
},
|
||||
"net8.0-windows7.0/win-x64": {
|
||||
|
||||
+2
-1
@@ -4,6 +4,7 @@ using Speckle.Connectors.Common.Cancellation;
|
||||
using Speckle.Connectors.Common.Threading;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Models.Card;
|
||||
using Speckle.Converters.Autocad;
|
||||
using Speckle.Converters.Civil3dShared;
|
||||
using Speckle.Converters.Common;
|
||||
@@ -31,7 +32,7 @@ public sealed class Civil3dReceiveBinding : AutocadReceiveBaseBinding
|
||||
|
||||
// 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 receive binding for civil3d due to using a different unit converter (needed for conversion settings construction)
|
||||
protected override void InitializeSettings(IServiceProvider serviceProvider)
|
||||
protected override void InitializeSettings(IServiceProvider serviceProvider, ModelCard mc)
|
||||
{
|
||||
serviceProvider
|
||||
.GetRequiredService<IConverterSettingsStore<Civil3dConversionSettings>>()
|
||||
|
||||
@@ -70,7 +70,7 @@ public class CsiRootObjectBuilder : IRootObjectBuilder<ICsiWrapper>
|
||||
/// </remarks>
|
||||
public async Task<RootObjectBuilderResult> Build(
|
||||
IReadOnlyList<ICsiWrapper> csiObjects,
|
||||
SendInfo sendInfo,
|
||||
string projectId,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
|
||||
@@ -259,9 +259,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -285,7 +285,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.etabs21": {
|
||||
@@ -335,18 +335,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -356,14 +356,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,9 +210,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -236,7 +236,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.etabs22": {
|
||||
@@ -286,18 +286,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.5",
|
||||
@@ -305,14 +305,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<Target Name="PostBuild" AfterTargets="Build">
|
||||
<Target Name="PostBuild" AfterTargets="Build" Condition="'$(NavisworksVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true' And '$(OS)' == 'Windows_NT'">
|
||||
<Message Text="Navisworks Version $(NavisworksVersion)" Importance="high"/>
|
||||
<RemoveDir Directories="$(PluginVersionContentTarget)" Condition="Exists('$(PluginVersionContentTarget)')"/>
|
||||
|
||||
|
||||
@@ -259,9 +259,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -285,7 +285,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.navisworks2020": {
|
||||
@@ -337,18 +337,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -358,14 +358,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
},
|
||||
".NETFramework,Version=v4.8/win-x64": {
|
||||
|
||||
@@ -259,9 +259,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -285,7 +285,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.navisworks2021": {
|
||||
@@ -337,18 +337,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -358,14 +358,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
},
|
||||
".NETFramework,Version=v4.8/win-x64": {
|
||||
|
||||
@@ -259,9 +259,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -285,7 +285,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.navisworks2022": {
|
||||
@@ -337,18 +337,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -358,14 +358,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
},
|
||||
".NETFramework,Version=v4.8/win-x64": {
|
||||
|
||||
@@ -259,9 +259,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -285,7 +285,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.navisworks2023": {
|
||||
@@ -337,18 +337,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -358,14 +358,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
},
|
||||
".NETFramework,Version=v4.8/win-x64": {
|
||||
|
||||
@@ -259,9 +259,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -285,7 +285,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.navisworks2024": {
|
||||
@@ -337,18 +337,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -358,14 +358,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
},
|
||||
".NETFramework,Version=v4.8/win-x64": {
|
||||
|
||||
@@ -265,9 +265,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -291,7 +291,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.navisworks2025": {
|
||||
@@ -337,18 +337,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -358,14 +358,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
},
|
||||
".NETFramework,Version=v4.8/win-x64": {
|
||||
|
||||
@@ -266,9 +266,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -292,7 +292,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.navisworks2026": {
|
||||
@@ -339,18 +339,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -360,14 +360,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
},
|
||||
".NETFramework,Version=v4.8/win-x64": {
|
||||
|
||||
-20
@@ -14,7 +14,6 @@ using Speckle.Connectors.DUI.Models.Card.SendFilter;
|
||||
using Speckle.Connectors.DUI.Settings;
|
||||
using Speckle.Converter.Navisworks.Settings;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Common;
|
||||
|
||||
namespace Speckle.Connector.Navisworks.Bindings;
|
||||
@@ -28,7 +27,6 @@ public class NavisworksSendBinding : ISendBinding
|
||||
|
||||
private readonly DocumentModelStore _store;
|
||||
private readonly ICancellationManager _cancellationManager;
|
||||
private readonly ISpeckleApplication _speckleApplication;
|
||||
private readonly INavisworksConversionSettingsFactory _conversionSettingsFactory;
|
||||
private readonly ToSpeckleSettingsManagerNavisworks _toSpeckleSettingsManagerNavisworks;
|
||||
private readonly IElementSelectionService _selectionService;
|
||||
@@ -39,7 +37,6 @@ public class NavisworksSendBinding : ISendBinding
|
||||
DocumentModelStore store,
|
||||
IBrowserBridge parent,
|
||||
ICancellationManager cancellationManager,
|
||||
ISpeckleApplication speckleApplication,
|
||||
INavisworksConversionSettingsFactory conversionSettingsFactory,
|
||||
ToSpeckleSettingsManagerNavisworks toSpeckleSettingsManagerNavisworks,
|
||||
IElementSelectionService selectionService,
|
||||
@@ -51,7 +48,6 @@ public class NavisworksSendBinding : ISendBinding
|
||||
Commands = new SendBindingUICommands(parent);
|
||||
_store = store;
|
||||
_cancellationManager = cancellationManager;
|
||||
_speckleApplication = speckleApplication;
|
||||
_conversionSettingsFactory = conversionSettingsFactory;
|
||||
_toSpeckleSettingsManagerNavisworks = toSpeckleSettingsManagerNavisworks;
|
||||
_selectionService = selectionService;
|
||||
@@ -133,22 +129,6 @@ public class NavisworksSendBinding : ISendBinding
|
||||
return modelItems.Count == 0 ? throw new SpeckleSendFilterException(message) : modelItems;
|
||||
}
|
||||
|
||||
private async Task<SendOperationResult> ExecuteSendOperation(
|
||||
IServiceScope scope,
|
||||
SenderModelCard modelCard,
|
||||
List<NAV.ModelItem> navisworksModelItems,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken token
|
||||
) =>
|
||||
await scope
|
||||
.ServiceProvider.GetRequiredService<SendOperation<NAV.ModelItem>>()
|
||||
.Execute(
|
||||
navisworksModelItems,
|
||||
modelCard.GetSendInfo(_speckleApplication.ApplicationAndVersion),
|
||||
onOperationProgressed,
|
||||
token
|
||||
);
|
||||
|
||||
public void CancelSend(string modelCardId) => _cancellationManager.CancelOperation(modelCardId);
|
||||
|
||||
/// <summary>
|
||||
|
||||
+13
-13
@@ -151,22 +151,22 @@ public class NavisworksSavedViewsFilter : DiscriminatedObject, ISendFilterSelect
|
||||
|
||||
foreach (NAV.SavedItem item in ((NAV.GroupItem)parentItem).Children)
|
||||
{
|
||||
switch (item.IsGroup)
|
||||
switch (item)
|
||||
{
|
||||
// THIS IS COMMENTED OUT AS IT IS LEGACY DEFENSIVE BEHAVIOUR - DISCUSSION REQUIRED
|
||||
// case false when item is NAV.SavedViewpoint { ContainsVisibilityOverrides: false }:
|
||||
// // If the saved view does not contain visibility overrides, this is effectively everything in the model.
|
||||
// // This will need to be the documented behaviour.
|
||||
// break;
|
||||
case false:
|
||||
collectedSets.Add((NAV.SavedViewpoint)item);
|
||||
// case NAV.SavedViewpoint { ContainsVisibilityOverrides: false }:
|
||||
// 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:
|
||||
// Skip animation cuts.
|
||||
break;
|
||||
default: // handles item.IsGroup == true
|
||||
if (((NAV.GroupItem)item).Children.Count > 0) // Don't add empty groups
|
||||
{
|
||||
CollectSavedViews(item, collectedSets);
|
||||
}
|
||||
case NAV.SavedViewpoint savedViewpoint:
|
||||
collectedSets.Add(savedViewpoint);
|
||||
break;
|
||||
case NAV.GroupItem groupItem when groupItem.Children.Count > 0:
|
||||
CollectSavedViews(groupItem, collectedSets);
|
||||
break;
|
||||
// No action for empty groups or unknown types.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-19
@@ -32,18 +32,9 @@ public class NavisworksRootObjectBuilder(
|
||||
|
||||
internal NavisworksConversionSettings GetCurrentSettings() => converterSettings.Current;
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously builds a Speckle object hierarchy from Navisworks model items.
|
||||
/// </summary>
|
||||
/// <param name="navisworksModelItems">The list of Navisworks items to convert.</param>
|
||||
/// <param name="sendInfo">Information about the send operation.</param>
|
||||
/// <param name="onOperationProgressed">Progress reporting callback.</param>
|
||||
/// <param name="cancellationToken">Token to cancel the operation.</param>
|
||||
/// <returns>A result containing the root collection and conversion results.</returns>
|
||||
/// <exception cref="SpeckleException">Thrown when no objects can be converted.</exception>
|
||||
public async Task<RootObjectBuilderResult> Build(
|
||||
IReadOnlyList<NAV.ModelItem> navisworksModelItems,
|
||||
SendInfo sendInfo,
|
||||
string projectId,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
@@ -54,7 +45,7 @@ public class NavisworksRootObjectBuilder(
|
||||
#endif
|
||||
using var activity = activityFactory.Start("Build");
|
||||
|
||||
ValidateInputs(navisworksModelItems, sendInfo, onOperationProgressed);
|
||||
ValidateInputs(navisworksModelItems, projectId, onOperationProgressed);
|
||||
|
||||
// 2. Initialize root collection
|
||||
var rootCollection = InitializeRootCollection();
|
||||
@@ -62,7 +53,7 @@ public class NavisworksRootObjectBuilder(
|
||||
// 3. Convert all model items and store results
|
||||
var (convertedElements, conversionResults) = await ConvertModelItemsAsync(
|
||||
navisworksModelItems,
|
||||
sendInfo,
|
||||
projectId,
|
||||
onOperationProgressed,
|
||||
cancellationToken
|
||||
);
|
||||
@@ -80,7 +71,7 @@ public class NavisworksRootObjectBuilder(
|
||||
|
||||
private static void ValidateInputs(
|
||||
IReadOnlyList<NAV.ModelItem> navisworksModelItems,
|
||||
SendInfo sendInfo,
|
||||
string projectId,
|
||||
IProgress<CardProgress> onOperationProgressed
|
||||
)
|
||||
{
|
||||
@@ -94,9 +85,11 @@ public class NavisworksRootObjectBuilder(
|
||||
throw new ArgumentNullException(nameof(navisworksModelItems));
|
||||
}
|
||||
|
||||
if (onOperationProgressed == null || sendInfo == null)
|
||||
if (onOperationProgressed == null || projectId == null)
|
||||
{
|
||||
throw new ArgumentNullException(onOperationProgressed == null ? nameof(onOperationProgressed) : nameof(sendInfo));
|
||||
throw new ArgumentNullException(
|
||||
onOperationProgressed == null ? nameof(onOperationProgressed) : nameof(projectId)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,7 +102,7 @@ public class NavisworksRootObjectBuilder(
|
||||
|
||||
private Task<(Dictionary<string, Base?> converted, List<SendConversionResult> results)> ConvertModelItemsAsync(
|
||||
IReadOnlyList<NAV.ModelItem> navisworksModelItems,
|
||||
SendInfo sendInfo,
|
||||
string projectId,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
@@ -122,7 +115,7 @@ public class NavisworksRootObjectBuilder(
|
||||
foreach (var item in navisworksModelItems)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var converted = ConvertNavisworksItem(item, convertedBases, sendInfo);
|
||||
var converted = ConvertNavisworksItem(item, convertedBases, projectId);
|
||||
results.Add(converted);
|
||||
processedCount++;
|
||||
onOperationProgressed.Report(new CardProgress("Converting", (double)processedCount / totalCount));
|
||||
@@ -310,7 +303,7 @@ public class NavisworksRootObjectBuilder(
|
||||
private SendConversionResult ConvertNavisworksItem(
|
||||
NAV.ModelItem navisworksItem,
|
||||
Dictionary<string, Base?> convertedBases,
|
||||
SendInfo sendInfo
|
||||
string projectId
|
||||
)
|
||||
{
|
||||
string applicationId = elementSelectionService.GetModelItemPath(navisworksItem);
|
||||
@@ -318,7 +311,7 @@ public class NavisworksRootObjectBuilder(
|
||||
|
||||
try
|
||||
{
|
||||
Base converted = sendConversionCache.TryGetValue(applicationId, sendInfo.ProjectId, out ObjectReference? cached)
|
||||
Base converted = sendConversionCache.TryGetValue(applicationId, projectId, out ObjectReference? cached)
|
||||
? cached
|
||||
: rootToSpeckleConverter.Convert(navisworksItem);
|
||||
|
||||
|
||||
+10
-14
@@ -63,23 +63,19 @@ public class ToSpeckleSettingsManagerNavisworks : IToSpeckleSettingsManagerNavis
|
||||
throw new ArgumentNullException(nameof(modelCard));
|
||||
}
|
||||
|
||||
var originString = modelCard.Settings?.First(s => s.Id == "originMode").Value as string;
|
||||
|
||||
if (originString is not null && OriginModeSetting.OriginModeMap.TryGetValue(originString, out OriginMode origin))
|
||||
var originString = modelCard.Settings?.FirstOrDefault(s => s.Id == "originMode")?.Value as string;
|
||||
if (!OriginModeSetting.OriginModeMap.TryGetValue(originString ?? string.Empty, out var origin))
|
||||
{
|
||||
if (_originModeCache.TryGetValue(modelCard.ModelCardId.NotNull(), out OriginMode previousType))
|
||||
{
|
||||
if (previousType != origin)
|
||||
{
|
||||
EvictCacheForModelCard(modelCard);
|
||||
}
|
||||
}
|
||||
|
||||
_originModeCache[modelCard.ModelCardId.NotNull()] = origin;
|
||||
return origin;
|
||||
return OriginMode.ModelOrigin; // Default to ModelOrigin if not specified or invalid
|
||||
}
|
||||
|
||||
throw new ArgumentException($"Invalid origin mode value: {originString}");
|
||||
if (_originModeCache.TryGetValue(modelCard.ModelCardId.NotNull(), out var previousType) && previousType != origin)
|
||||
{
|
||||
EvictCacheForModelCard(modelCard);
|
||||
}
|
||||
|
||||
_originModeCache[modelCard.ModelCardId.NotNull()] = origin;
|
||||
return origin;
|
||||
}
|
||||
|
||||
public bool GetConvertHiddenElements(SenderModelCard modelCard)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project>
|
||||
<Target AfterTargets="Clean" Name="CleanAddinsRevit" Condition="'$(RevitVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
|
||||
<Target AfterTargets="Clean" Name="CleanAddinsRevit" Condition="'$(RevitVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true' And '$(OS)' == 'Windows_NT'">
|
||||
<RemoveDir Directories="$(TargetDir);$(ProjectDir)\..\Release\Release$(RevitVersion);$(AppData)\Autodesk\Revit\Addins\$(RevitVersion)\Speckle.Connectors.Revit$(RevitVersion);" />
|
||||
<Delete Files="$(AppData)\Autodesk\Revit\Addins\$(RevitVersion)\Speckle.Connectors.Revit$(RevitVersion).addin" />
|
||||
</Target>
|
||||
|
||||
<Target AfterTargets="Build" Name="AfterBuildRevit" Condition="'$(RevitVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
|
||||
<Target AfterTargets="Build" Name="AfterBuildRevit" Condition="'$(RevitVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true' And '$(OS)' == 'Windows_NT'">
|
||||
<ItemGroup>
|
||||
<RevitDLLs Include="$(TargetDir)\**\*.*" Exclude="$(TargetDir)*.addin" />
|
||||
<SourceManifest Include="$(TargetDir)\Plugin\Speckle.Connectors.Revit$(RevitVersion).addin" />
|
||||
|
||||
@@ -281,9 +281,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -306,7 +306,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.revit2022": {
|
||||
@@ -351,11 +351,11 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Revit.API": {
|
||||
@@ -366,9 +366,9 @@
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -378,14 +378,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,9 +281,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -306,7 +306,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.revit2023": {
|
||||
@@ -351,11 +351,11 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Revit.API": {
|
||||
@@ -366,9 +366,9 @@
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -378,14 +378,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,9 +281,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -306,7 +306,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.revit2024": {
|
||||
@@ -351,11 +351,11 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Revit.API": {
|
||||
@@ -366,9 +366,9 @@
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -378,14 +378,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,9 +226,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -251,7 +251,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.revit2025": {
|
||||
@@ -296,11 +296,11 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Revit.API": {
|
||||
@@ -311,9 +311,9 @@
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.5",
|
||||
@@ -321,14 +321,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
},
|
||||
"net8.0-windows7.0/win-x64": {
|
||||
|
||||
@@ -219,9 +219,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -244,7 +244,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.revit2026": {
|
||||
@@ -280,11 +280,11 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Revit.API": {
|
||||
@@ -295,9 +295,9 @@
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.5",
|
||||
@@ -305,14 +305,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
},
|
||||
"net8.0-windows7.0/win-x64": {
|
||||
|
||||
@@ -3,16 +3,18 @@ using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Common.Cancellation;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Settings;
|
||||
using Speckle.Connectors.Revit.Plugin;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Converters.RevitShared.Settings;
|
||||
|
||||
namespace Speckle.Connectors.Revit.Bindings;
|
||||
|
||||
internal sealed class RevitReceiveBinding(
|
||||
public sealed class RevitReceiveBinding(
|
||||
ICancellationManager cancellationManager,
|
||||
IBrowserBridge parent,
|
||||
ILogger<RevitReceiveBinding> logger,
|
||||
Speckle.Connectors.Revit.Operations.Receive.Settings.ToHostSettingsManager toHostSettingsManager,
|
||||
IRevitConversionSettingsFactory revitConversionSettingsFactory,
|
||||
IReceiveOperationManagerFactory receiveOperationManagerFactory
|
||||
) : IReceiveBinding
|
||||
@@ -21,6 +23,11 @@ internal sealed class RevitReceiveBinding(
|
||||
public IBrowserBridge Parent { get; } = parent;
|
||||
private IReceiveBindingUICommands Commands { get; } = new ReceiveBindingUICommands(parent);
|
||||
|
||||
#pragma warning disable CA1024
|
||||
public List<ICardSetting> GetReceiveSettings() =>
|
||||
[new Speckle.Connectors.Revit.Operations.Receive.Settings.ReferencePointSetting(ReceiveReferencePointType.Source)];
|
||||
#pragma warning restore CA1024
|
||||
|
||||
public void CancelReceive(string modelCardId) => cancellationManager.CancelOperation(modelCardId);
|
||||
|
||||
public async Task Receive(string modelCardId)
|
||||
@@ -29,13 +36,13 @@ internal sealed class RevitReceiveBinding(
|
||||
await manager.Process(
|
||||
Commands,
|
||||
modelCardId,
|
||||
(sp) =>
|
||||
(sp, card) =>
|
||||
{
|
||||
sp.GetRequiredService<IConverterSettingsStore<RevitConversionSettings>>()
|
||||
.Initialize(
|
||||
revitConversionSettingsFactory.Create(
|
||||
DetailLevelType.Coarse, // TODO figure out
|
||||
null,
|
||||
toHostSettingsManager.GetReferencePointSetting(card),
|
||||
false,
|
||||
true,
|
||||
false
|
||||
|
||||
+3
@@ -11,6 +11,7 @@ using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.Revit.Bindings;
|
||||
using Speckle.Connectors.Revit.HostApp;
|
||||
using Speckle.Connectors.Revit.Operations.Receive;
|
||||
using Speckle.Connectors.Revit.Operations.Receive.Settings;
|
||||
using Speckle.Connectors.Revit.Operations.Send;
|
||||
using Speckle.Connectors.Revit.Operations.Send.Settings;
|
||||
using Speckle.Connectors.Revit.Plugin;
|
||||
@@ -57,10 +58,12 @@ public static class ServiceRegistration
|
||||
// send operation and dependencies
|
||||
serviceCollection.AddScoped<SendOperation<DocumentToConvert>>();
|
||||
serviceCollection.AddScoped<ElementUnpacker>();
|
||||
serviceCollection.AddScoped<LevelUnpacker>();
|
||||
serviceCollection.AddScoped<SendCollectionManager>();
|
||||
serviceCollection.AddScoped<IRootObjectBuilder<DocumentToConvert>, RevitRootObjectBuilder>();
|
||||
serviceCollection.AddSingleton<ISendConversionCache, SendConversionCache>();
|
||||
serviceCollection.AddSingleton<ToSpeckleSettingsManager>();
|
||||
serviceCollection.AddSingleton<ToHostSettingsManager>();
|
||||
serviceCollection.AddSingleton<LinkedModelHandler>();
|
||||
|
||||
// receive operation and dependencies
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
using Autodesk.Revit.DB;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Converters.RevitShared.Helpers;
|
||||
using Speckle.Converters.RevitShared.Settings;
|
||||
using Speckle.Converters.RevitShared.ToSpeckle.Properties;
|
||||
using Speckle.Objects.Data;
|
||||
using Speckle.Objects.Other;
|
||||
|
||||
namespace Speckle.Connectors.Revit.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// Helper class to proxify the levels. Runs over for every element with their LevelId prop.
|
||||
/// We can handle bottom-top levels for elements later only if it is asked.
|
||||
/// </summary>
|
||||
public class LevelUnpacker
|
||||
{
|
||||
private readonly LevelExtractor _levelExtractor;
|
||||
private readonly PropertiesExtractor _propertiesExtractor;
|
||||
private readonly IConverterSettingsStore<RevitConversionSettings> _converterSettings;
|
||||
|
||||
public LevelUnpacker(
|
||||
LevelExtractor levelExtractor,
|
||||
PropertiesExtractor propertiesExtractor,
|
||||
IConverterSettingsStore<RevitConversionSettings> converterSettings
|
||||
)
|
||||
{
|
||||
_levelExtractor = levelExtractor;
|
||||
_propertiesExtractor = propertiesExtractor;
|
||||
_converterSettings = converterSettings;
|
||||
}
|
||||
|
||||
public List<LevelProxy> Unpack(List<Element> elements)
|
||||
{
|
||||
Dictionary<string, LevelProxy> levelProxies = new();
|
||||
foreach (var element in elements)
|
||||
{
|
||||
if (levelProxies.TryGetValue(element.LevelId.ToString(), out LevelProxy? levelProxy))
|
||||
{
|
||||
levelProxy.objects.Add(element.UniqueId);
|
||||
}
|
||||
else
|
||||
{
|
||||
var level = _levelExtractor.GetLevel(element);
|
||||
if (level is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var levelDataObject = new DataObject()
|
||||
{
|
||||
name = level.Name,
|
||||
displayValue = [],
|
||||
properties = _propertiesExtractor.GetProperties(level)
|
||||
};
|
||||
var unitSettings = _converterSettings.Current.Document.GetUnits();
|
||||
var lengthUnitType = unitSettings.GetFormatOptions(Autodesk.Revit.DB.SpecTypeId.Length).GetUnitTypeId();
|
||||
levelDataObject["elevation"] = UnitUtils.ConvertFromInternalUnits(level.Elevation, lengthUnitType);
|
||||
levelDataObject["units"] = _converterSettings.Current.SpeckleUnits;
|
||||
|
||||
levelProxies[element.LevelId.ToString()] = new LevelProxy()
|
||||
{
|
||||
applicationId = level.UniqueId,
|
||||
objects = [element.UniqueId],
|
||||
value = levelDataObject
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return levelProxies.Values.ToList();
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ public class SendCollectionManager
|
||||
{
|
||||
private readonly IConverterSettingsStore<RevitConversionSettings> _converterSettings;
|
||||
private readonly Dictionary<string, Collection> _collectionCache = new();
|
||||
private readonly Dictionary<ElementId, (string name, Dictionary<string, object?> props)> _levelCache = new(); // stores level id and its properties
|
||||
private readonly Dictionary<ElementId, string> _levelCache = new(); // stores level id and its properties
|
||||
private readonly Dictionary<string, Collection> _linkedModelCollections = new(); // cache for linked model collections
|
||||
private Collection? _mainModelCollection; // collection for main model elements
|
||||
|
||||
@@ -91,13 +91,11 @@ public class SendCollectionManager
|
||||
|
||||
// get the level and its properties
|
||||
string levelName = "No Level";
|
||||
Dictionary<string, object?> levelProperties = new();
|
||||
if (element.LevelId != ElementId.InvalidElementId)
|
||||
{
|
||||
if (_levelCache.TryGetValue(element.LevelId, out var cachedLevel))
|
||||
{
|
||||
levelName = cachedLevel.name;
|
||||
levelProperties = cachedLevel.props;
|
||||
levelName = cachedLevel;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -105,9 +103,7 @@ public class SendCollectionManager
|
||||
{
|
||||
var level = (Level)doc.GetElement(element.LevelId);
|
||||
levelName = level.Name;
|
||||
levelProperties.Add("elevation", level.Elevation);
|
||||
levelProperties.Add("units", _converterSettings.Current.SpeckleUnits);
|
||||
_levelCache.Add(element.LevelId, (levelName, levelProperties));
|
||||
_levelCache.Add(element.LevelId, levelName);
|
||||
}
|
||||
// the exception is swallowed since if an exception occurs, we fall back to "No Level" for the element
|
||||
catch (Exception e) when (!e.IsFatal()) { }
|
||||
@@ -157,12 +153,6 @@ public class SendCollectionManager
|
||||
else
|
||||
{
|
||||
childCollection = new Collection(pathItem);
|
||||
// add properties to level collection
|
||||
if (i == 0 && levelProperties.Count > 0)
|
||||
{
|
||||
childCollection["properties"] = levelProperties;
|
||||
}
|
||||
|
||||
previousCollection.elements.Add(childCollection);
|
||||
_collectionCache[flatPathName] = childCollection;
|
||||
}
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
using Speckle.Connectors.DUI.Settings;
|
||||
using Speckle.Converters.RevitShared.Settings;
|
||||
|
||||
namespace Speckle.Connectors.Revit.Operations.Receive.Settings;
|
||||
|
||||
public class ReferencePointSetting(ReceiveReferencePointType value) : ICardSetting
|
||||
{
|
||||
public string? Id { get; set; } = "referencePoint";
|
||||
public string? Title { get; set; } = "Reference Point";
|
||||
public string? Type { get; set; } = "string";
|
||||
public List<string>? Enum { get; set; } = System.Enum.GetNames(typeof(ReceiveReferencePointType)).ToList();
|
||||
public object? Value { get; set; } = value.ToString();
|
||||
|
||||
public static readonly Dictionary<string, ReceiveReferencePointType> ReferencePointMap = System
|
||||
.Enum.GetValues(typeof(ReceiveReferencePointType))
|
||||
.Cast<ReceiveReferencePointType>()
|
||||
.ToDictionary(v => v.ToString(), v => v);
|
||||
}
|
||||
+25
-3
@@ -64,14 +64,14 @@ public sealed class RevitHostObjectBuilder(
|
||||
)
|
||||
{
|
||||
// TODO: formalise getting transform info from rootObject. this dict access is gross.
|
||||
Autodesk.Revit.DB.Transform? referencePointTransform = null;
|
||||
Autodesk.Revit.DB.Transform? referencePointTransformFromRootObject = null;
|
||||
if (
|
||||
rootObject.DynamicPropertyKeys.Contains(ReferencePointHelper.REFERENCE_POINT_TRANSFORM_KEY)
|
||||
&& rootObject[ReferencePointHelper.REFERENCE_POINT_TRANSFORM_KEY] is Dictionary<string, object> transformDict
|
||||
&& transformDict.TryGetValue("transform", out var transformValue)
|
||||
)
|
||||
{
|
||||
referencePointTransform = ReferencePointHelper.GetTransformFromRootObject(transformValue);
|
||||
referencePointTransformFromRootObject = ReferencePointHelper.GetTransformFromRootObject(transformValue);
|
||||
}
|
||||
|
||||
var baseGroupName = $"Project {projectName}: Model {modelName}"; // TODO: unify this across connectors!
|
||||
@@ -184,11 +184,15 @@ public sealed class RevitHostObjectBuilder(
|
||||
{
|
||||
using var _ = activityFactory.Start("Baking objects");
|
||||
transactionManager.StartTransaction(true, "Baking objects");
|
||||
|
||||
using (
|
||||
converterSettings.Push(currentSettings =>
|
||||
currentSettings with
|
||||
{
|
||||
ReferencePointTransform = referencePointTransform
|
||||
ReferencePointTransform = CalculateNewTransform(
|
||||
currentSettings.ReferencePointTransform,
|
||||
referencePointTransformFromRootObject
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
@@ -217,6 +221,24 @@ public sealed class RevitHostObjectBuilder(
|
||||
return conversionResults.builderResult;
|
||||
}
|
||||
|
||||
private Autodesk.Revit.DB.Transform? CalculateNewTransform(
|
||||
Autodesk.Revit.DB.Transform? receiveTransform,
|
||||
Autodesk.Revit.DB.Transform? rootTransform
|
||||
)
|
||||
{
|
||||
if (receiveTransform == null)
|
||||
{
|
||||
return rootTransform;
|
||||
}
|
||||
|
||||
if (rootTransform == null)
|
||||
{
|
||||
return receiveTransform;
|
||||
}
|
||||
|
||||
return rootTransform.Multiply(receiveTransform);
|
||||
}
|
||||
|
||||
private (
|
||||
HostObjectBuilderResult builderResult,
|
||||
List<(DirectShape res, string applicationId)> postBakePaintTargets
|
||||
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.UI;
|
||||
using Speckle.Connectors.DUI.Models.Card;
|
||||
using Speckle.Converters.RevitShared.Helpers;
|
||||
using Speckle.Converters.RevitShared.Settings;
|
||||
using Speckle.InterfaceGenerator;
|
||||
|
||||
namespace Speckle.Connectors.Revit.Operations.Receive.Settings;
|
||||
|
||||
[GenerateAutoInterface]
|
||||
public class ToHostSettingsManager : IToHostSettingsManager
|
||||
{
|
||||
private readonly RevitContext _revitContext;
|
||||
|
||||
public ToHostSettingsManager(RevitContext revitContext)
|
||||
{
|
||||
_revitContext = revitContext;
|
||||
}
|
||||
|
||||
public Transform? GetReferencePointSetting(ModelCard modelCard)
|
||||
{
|
||||
var referencePointString = modelCard.Settings?.First(s => s.Id == "referencePoint").Value as string;
|
||||
if (
|
||||
referencePointString is not null
|
||||
&& ReferencePointSetting.ReferencePointMap.TryGetValue(
|
||||
referencePointString,
|
||||
out ReceiveReferencePointType referencePoint
|
||||
)
|
||||
)
|
||||
{
|
||||
// get the current transform from setting first
|
||||
// we are doing this because we can't track if reference points were changed between send operations.
|
||||
Transform? currentTransform = GetTransform(referencePoint);
|
||||
return currentTransform;
|
||||
}
|
||||
|
||||
throw new ArgumentException($"Invalid reference point value: {referencePointString}");
|
||||
}
|
||||
|
||||
private Transform? GetTransform(ReceiveReferencePointType referencePointType)
|
||||
{
|
||||
Transform? referencePointTransform = null;
|
||||
|
||||
if (_revitContext.UIApplication is UIApplication uiApplication)
|
||||
{
|
||||
// first get the main doc base points and reference setting transform
|
||||
using FilteredElementCollector filteredElementCollector = new(uiApplication.ActiveUIDocument.Document);
|
||||
var points = filteredElementCollector.OfClass(typeof(BasePoint)).Cast<BasePoint>().ToList();
|
||||
BasePoint? projectPoint = points.FirstOrDefault(o => !o.IsShared);
|
||||
BasePoint? surveyPoint = points.FirstOrDefault(o => o.IsShared);
|
||||
|
||||
switch (referencePointType)
|
||||
{
|
||||
// note that the project base (ui) rotation is registered on the survey pt, not on the base point
|
||||
case ReceiveReferencePointType.ProjectBase:
|
||||
if (projectPoint is not null)
|
||||
{
|
||||
referencePointTransform = Transform.CreateTranslation(projectPoint.Position);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("Couldn't retrieve Project Point from document");
|
||||
}
|
||||
break;
|
||||
|
||||
// note that the project base (ui) rotation is registered on the survey pt, not on the base point
|
||||
case ReceiveReferencePointType.Survey:
|
||||
if (surveyPoint is not null && projectPoint is not null)
|
||||
{
|
||||
// POC: should a null angle resolve to 0?
|
||||
// retrieve the survey point rotation from the project point
|
||||
var angle = projectPoint.get_Parameter(BuiltInParameter.BASEPOINT_ANGLETON_PARAM)?.AsDouble() ?? 0;
|
||||
|
||||
// POC: following disposed incorrectly or early or maybe a false negative?
|
||||
using Transform translation = Transform.CreateTranslation(surveyPoint.Position);
|
||||
referencePointTransform = translation.Multiply(Transform.CreateRotation(XYZ.BasisZ, angle));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("Couldn't retrieve Survey and Project Point from document");
|
||||
}
|
||||
break;
|
||||
|
||||
case ReceiveReferencePointType.Source:
|
||||
break;
|
||||
case ReceiveReferencePointType.InternalOrigin:
|
||||
break;
|
||||
}
|
||||
|
||||
return referencePointTransform;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException(
|
||||
"Revit Context UI Application was null when retrieving reference point transform."
|
||||
);
|
||||
}
|
||||
}
|
||||
+11
-10
@@ -23,6 +23,7 @@ public class RevitRootObjectBuilder(
|
||||
IConverterSettingsStore<RevitConversionSettings> converterSettings,
|
||||
ISendConversionCache sendConversionCache,
|
||||
ElementUnpacker elementUnpacker,
|
||||
LevelUnpacker levelUnpacker,
|
||||
IThreadContext threadContext,
|
||||
SendCollectionManager sendCollectionManager,
|
||||
ILogger<RevitRootObjectBuilder> logger,
|
||||
@@ -32,17 +33,17 @@ public class RevitRootObjectBuilder(
|
||||
{
|
||||
public Task<RootObjectBuilderResult> Build(
|
||||
IReadOnlyList<DocumentToConvert> documentElementContexts,
|
||||
SendInfo sendInfo,
|
||||
string projectId,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken ct = default
|
||||
) =>
|
||||
threadContext.RunOnMainAsync(
|
||||
() => Task.FromResult(BuildSync(documentElementContexts, sendInfo, onOperationProgressed, ct))
|
||||
() => Task.FromResult(BuildSync(documentElementContexts, projectId, onOperationProgressed, ct))
|
||||
);
|
||||
|
||||
private RootObjectBuilderResult BuildSync(
|
||||
IReadOnlyList<DocumentToConvert> documentElementContexts,
|
||||
SendInfo sendInfo,
|
||||
string projectId,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
@@ -182,10 +183,7 @@ public class RevitRootObjectBuilder(
|
||||
// non-transformed elements can safely rely on cache
|
||||
// TODO: Potential here to transform cached objects and NOT reconvert,
|
||||
// TODO: we wont do !hasTransform here, and re-set application id before this
|
||||
if (
|
||||
!hasTransform
|
||||
&& sendConversionCache.TryGetValue(sendInfo.ProjectId, applicationId, out ObjectReference? value)
|
||||
)
|
||||
if (!hasTransform && sendConversionCache.TryGetValue(projectId, applicationId, out ObjectReference? value))
|
||||
{
|
||||
converted = value;
|
||||
cacheHitCount++;
|
||||
@@ -232,12 +230,15 @@ public class RevitRootObjectBuilder(
|
||||
throw new SpeckleException("Failed to convert all objects.");
|
||||
}
|
||||
|
||||
var idsAndSubElementIds = elementUnpacker.GetElementsAndSubelementIdsFromAtomicObjects(
|
||||
atomicObjectsByDocumentAndTransform.SelectMany(t => t.Elements).ToList()
|
||||
);
|
||||
var flatElements = atomicObjectsByDocumentAndTransform.SelectMany(t => t.Elements).ToList();
|
||||
var idsAndSubElementIds = elementUnpacker.GetElementsAndSubelementIdsFromAtomicObjects(flatElements);
|
||||
|
||||
var renderMaterialProxies = revitToSpeckleCacheSingleton.GetRenderMaterialProxyListForObjects(idsAndSubElementIds);
|
||||
rootObject[ProxyKeys.RENDER_MATERIAL] = renderMaterialProxies;
|
||||
|
||||
var levelProxies = levelUnpacker.Unpack(flatElements);
|
||||
rootObject[ProxyKeys.LEVEL] = levelProxies;
|
||||
|
||||
// NOTE: these are currently not used anywhere, we'll skip them until someone calls for it back
|
||||
// rootObject[ProxyKeys.PARAMETER_DEFINITIONS] = _parameterDefinitionHandler.Definitions;
|
||||
|
||||
|
||||
+3
-3
@@ -57,7 +57,7 @@ public class ToSpeckleSettingsManager : IToSpeckleSettingsManager
|
||||
throw new ArgumentException($"Invalid geometry fidelity value: {fidelityString}");
|
||||
}
|
||||
|
||||
public Transform? GetReferencePointSetting(SenderModelCard modelCard)
|
||||
public Transform? GetReferencePointSetting(ModelCard modelCard)
|
||||
{
|
||||
var referencePointString = modelCard.Settings?.First(s => s.Id == "referencePoint").Value as string;
|
||||
if (
|
||||
@@ -75,9 +75,9 @@ public class ToSpeckleSettingsManager : IToSpeckleSettingsManager
|
||||
if (_referencePointCache.TryGetValue(modelCard.ModelCardId.NotNull(), out Transform? previousTransform))
|
||||
{
|
||||
// invalidate conversion cache if the transform has changed
|
||||
if (previousTransform != currentTransform)
|
||||
if (modelCard is SenderModelCard senderModelCard && previousTransform != currentTransform)
|
||||
{
|
||||
EvictCacheForModelCard(modelCard);
|
||||
EvictCacheForModelCard(senderModelCard);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -22,6 +22,7 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\DocumentModelStorageSchema.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\DocumentToConvert.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\Elements.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\LevelUnpacker.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\LinkedModelHandler.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\RevitMaterialBaker.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\SupportedCategoriesUtils.cs" />
|
||||
@@ -36,7 +37,9 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\SendCollectionManager.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\ElementUnpacker.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Operations\Receive\ITransactionManager.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)operations\receive\ReferencePointSetting.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Operations\Receive\RevitHostObjectBuilder.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)operations\receive\ToHostSettingsManager.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Operations\Receive\TransactionManager.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\Filters\IRevitSendFilter.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\Filters\RevitCategoriesFilter.cs" />
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
<ItemGroup>
|
||||
<PublicReleasePath Include="$(AppData)\McNeel\Rhinoceros\$(RhinoVersion).0\Plug-ins\Speckle.Connectors.Rhino$(RhinoVersion) (2153799A-0CEC-40DE-BC3A-01E5055222FF)" />
|
||||
</ItemGroup>
|
||||
<Target AfterTargets="Build" Name="WarnIfPublicReleaseVersionInstalled" Condition="'$(RhinoVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
|
||||
<Target AfterTargets="Build" Name="WarnIfPublicReleaseVersionInstalled" Condition="'$(RhinoVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true' And '$(OS)' == 'Windows_NT'">
|
||||
<Warning
|
||||
Text="Conflicting Rhino plugin detected - Do you have a public release installed?"
|
||||
Condition="Exists(@(PublicReleasePath))" />
|
||||
</Target>
|
||||
|
||||
<Target AfterTargets="Build" Name="AfterBuildRhino" Condition="'$(RhinoVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
|
||||
<Target AfterTargets="Build" Name="AfterBuildRhino" Condition="'$(RhinoVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true' And '$(OS)' == 'Windows_NT'">
|
||||
<Message Text="Rhino Version $(RhinoVersion)" Importance="high"/>
|
||||
</Target>
|
||||
</Project>
|
||||
|
||||
@@ -13,9 +13,12 @@
|
||||
},
|
||||
"GrasshopperAsyncComponent": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.2.3, )",
|
||||
"resolved": "1.2.3",
|
||||
"contentHash": "KdCmyZ7Su8T3wb5t5BEbSg2inz+aJfGFHpDysColTdeyYX9S6MRJK69UV4kYYHE+ro1FKPADOwoSE6eLKq/yDA=="
|
||||
"requested": "[2.0.3, )",
|
||||
"resolved": "2.0.3",
|
||||
"contentHash": "AZvHP96WhYZWftVi7J3J65LiZmXO3hGS6W4AntMMb099gkrLqeiBKC2DOYD6YM9cOyQqly3S5knbUL2yr0jc4Q==",
|
||||
"dependencies": {
|
||||
"PolySharp": "1.14.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
@@ -322,9 +325,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.logging": {
|
||||
@@ -334,7 +337,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.rhino7": {
|
||||
@@ -379,18 +382,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -400,14 +403,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,12 @@
|
||||
},
|
||||
"GrasshopperAsyncComponent": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.2.3, )",
|
||||
"resolved": "1.2.3",
|
||||
"contentHash": "KdCmyZ7Su8T3wb5t5BEbSg2inz+aJfGFHpDysColTdeyYX9S6MRJK69UV4kYYHE+ro1FKPADOwoSE6eLKq/yDA=="
|
||||
"requested": "[2.0.3, )",
|
||||
"resolved": "2.0.3",
|
||||
"contentHash": "AZvHP96WhYZWftVi7J3J65LiZmXO3hGS6W4AntMMb099gkrLqeiBKC2DOYD6YM9cOyQqly3S5knbUL2yr0jc4Q==",
|
||||
"dependencies": {
|
||||
"PolySharp": "1.14.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
@@ -322,9 +325,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )",
|
||||
"Speckle.Sdk": "[3.4.2, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )",
|
||||
"Speckle.Sdk": "[3.4.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.logging": {
|
||||
@@ -334,7 +337,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.4.2, )"
|
||||
"Speckle.Objects": "[3.4.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.rhino8": {
|
||||
@@ -379,18 +382,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "2TcYsGm+vG5mpZj+fiwPJv/4wXtstrWb9FasxsQN2JdUNDKvg1/rVFE9Pby1tPWN+4J0X0QaXutGj0yNwLRe7w==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "WMDYkTxoSbzh2WzuubMUKx37M6f7D/k/xOOV50oB9bQA0TiUAVcCFKAW0VHZZF4OhjBBxV8N2FM2yr2oaNc/Ww==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.4.2"
|
||||
"Speckle.Sdk": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "SOjUacHaCt+w19DhSgwQijhcwYZZSgmRVBOLk/O1Lwlq66cHVy3pzyBbsNR8zM+rVAtXrpahf60TjBg2EsD5Zg==",
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "w6vfOyckHVWqOqDjBO+PmVT5LeYu8voMMypOpa+w/2LrgMH6CxkCMYYjyOK8/rb3Ss989f2EjkpksQ3lcHPN/Q==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -400,14 +403,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.4.2"
|
||||
"Speckle.Sdk.Dependencies": "3.4.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.4.2, )",
|
||||
"resolved": "3.4.2",
|
||||
"contentHash": "mYjR5i5zaNxkR2VXi2Ills3XG3VZ4z3wLSQBn7GldAudtxI8yS09M6w4ltFNcBmgLlnYHYiIbsWEilIGUbi0Nw=="
|
||||
"requested": "[3.4.5, )",
|
||||
"resolved": "3.4.5",
|
||||
"contentHash": "8X9Qpksyp2MDb/G2Du7OFehdCtt0A0AclMKUFNsDSot5h8fTrvT620kW64ycm4l+PKXsPvCKDspOiGi4+9HrMQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+26
-6
@@ -36,7 +36,13 @@ public class CreateCollection : VariableParameterComponentBase
|
||||
|
||||
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
|
||||
{
|
||||
pManager.AddGenericParameter("Collection", "C", "Created parent collection", GH_ParamAccess.item);
|
||||
pManager.AddParameter(
|
||||
new SpeckleCollectionParam(),
|
||||
"Collection",
|
||||
"C",
|
||||
"Created parent collection",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
}
|
||||
|
||||
protected override void SolveInstance(IGH_DataAccess dataAccess)
|
||||
@@ -152,12 +158,26 @@ public class CreateCollection : VariableParameterComponentBase
|
||||
{
|
||||
foreach (var obj in objects)
|
||||
{
|
||||
var wrapperGoo = new SpeckleObjectWrapperGoo();
|
||||
if (wrapperGoo.CastFrom(obj))
|
||||
// handle data objects directly (deep copy to avoid mutations)
|
||||
// NOTE: DataObject first, since a DataObject with one geo is castable to speckle geometry
|
||||
if (obj is SpeckleDataObjectWrapperGoo dataObjectWrapperGoo)
|
||||
{
|
||||
wrapperGoo.Value.Path = childPath;
|
||||
wrapperGoo.Value.Parent = parentCollection;
|
||||
parentCollection.Elements.Add(wrapperGoo.Value);
|
||||
var dataObjectWrapper = dataObjectWrapperGoo.Value.DeepCopy();
|
||||
dataObjectWrapper.Path = childPath;
|
||||
dataObjectWrapper.Parent = parentCollection;
|
||||
parentCollection.Elements.Add(dataObjectWrapper);
|
||||
}
|
||||
// handle geometry objects (deep copy to avoid mutations)
|
||||
else if (obj?.ToSpeckleGeometryWrapper() is SpeckleGeometryWrapper objWrapper)
|
||||
{
|
||||
SpeckleGeometryWrapper wrapper = objWrapper.DeepCopy();
|
||||
wrapper.Path = childPath;
|
||||
wrapper.Parent = parentCollection;
|
||||
parentCollection.Elements.Add(wrapper);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, $"{obj?.GetType().Name} type cannot be added to collections.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+29
-26
@@ -2,6 +2,7 @@ using System.Collections;
|
||||
using System.Runtime.InteropServices;
|
||||
using Grasshopper.Kernel;
|
||||
using Grasshopper.Kernel.Parameters;
|
||||
using Grasshopper.Kernel.Types;
|
||||
using Speckle.Connectors.GrasshopperShared.HostApp;
|
||||
using Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
using Speckle.Connectors.GrasshopperShared.Properties;
|
||||
@@ -30,9 +31,9 @@ public class ExpandCollection : GH_Component, IGH_VariableParameterComponent
|
||||
{
|
||||
pManager.AddParameter(
|
||||
new SpeckleCollectionParam(GH_ParamAccess.item),
|
||||
"Data",
|
||||
"D",
|
||||
"The data you want to expand",
|
||||
"Collection",
|
||||
"C",
|
||||
"The Collection you want to expand",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
}
|
||||
@@ -51,15 +52,11 @@ public class ExpandCollection : GH_Component, IGH_VariableParameterComponent
|
||||
Name = wrapper.Name;
|
||||
NickName = wrapper.Name;
|
||||
|
||||
var objects = wrapper
|
||||
.Elements.Where(el => el is not SpeckleCollectionWrapper)
|
||||
.OfType<SpeckleObjectWrapper>()
|
||||
.Select(o => new SpeckleObjectWrapperGoo(o))
|
||||
.ToList();
|
||||
var collections = wrapper
|
||||
.Elements.Where(el => el is SpeckleCollectionWrapper)
|
||||
.OfType<SpeckleCollectionWrapper>()
|
||||
.ToList();
|
||||
// Separate objects and collections
|
||||
// Note: SpeckleBlockInstanceWrapper inherits from SpeckleObjectWrapper,
|
||||
// so it will be included in objects
|
||||
List<SpeckleWrapper> objects = wrapper.GetAtomicObjects().ToList();
|
||||
List<SpeckleCollectionWrapper> collections = wrapper.Elements.OfType<SpeckleCollectionWrapper>().ToList();
|
||||
|
||||
var outputParams = new List<OutputParamWrapper>();
|
||||
if (objects.Count != 0)
|
||||
@@ -69,11 +66,14 @@ public class ExpandCollection : GH_Component, IGH_VariableParameterComponent
|
||||
Name = "_objects",
|
||||
NickName = "_objs",
|
||||
Description =
|
||||
"Some collections may contain a mix of objects and other collections. Here we output the atomic objects from within this collection.",
|
||||
"Some collections may contain a mix of objects and other collections. These are the objects directly contained in this collection.",
|
||||
Access = GH_ParamAccess.list
|
||||
};
|
||||
|
||||
outputParams.Add(new OutputParamWrapper(param, objects, null));
|
||||
// Create appropriate Goo types for each object (downside of the inheritance refactor)
|
||||
List<IGH_Goo> atomicObjectGoos = objects.Select(obj => obj.CreateGoo()).ToList();
|
||||
|
||||
outputParams.Add(new OutputParamWrapper(param, atomicObjectGoos, null));
|
||||
}
|
||||
|
||||
foreach (SpeckleCollectionWrapper childWrapper in collections)
|
||||
@@ -86,7 +86,7 @@ public class ExpandCollection : GH_Component, IGH_VariableParameterComponent
|
||||
*/
|
||||
|
||||
var hasInnerCollections = childWrapper.Elements.Any(el => el is SpeckleCollectionWrapper);
|
||||
var topology = childWrapper.Topology; // Note: this is a reminder for the future
|
||||
var topology = childWrapper.Topology;
|
||||
var nickName = childWrapper.Name;
|
||||
if (nickName.Length > 16)
|
||||
{
|
||||
@@ -102,18 +102,22 @@ public class ExpandCollection : GH_Component, IGH_VariableParameterComponent
|
||||
? GH_ParamAccess.item
|
||||
: topology is null
|
||||
? GH_ParamAccess.list
|
||||
: GH_ParamAccess.tree // we will directly set objects out; note access can be list or tree based on whether it will be a path based collection
|
||||
: GH_ParamAccess.tree
|
||||
};
|
||||
|
||||
outputParams.Add(
|
||||
new OutputParamWrapper(
|
||||
param,
|
||||
hasInnerCollections
|
||||
? new SpeckleCollectionWrapperGoo(childWrapper)
|
||||
: childWrapper.Elements.OfType<SpeckleObjectWrapper>().Select(o => new SpeckleObjectWrapperGoo(o)).ToList(),
|
||||
topology
|
||||
)
|
||||
);
|
||||
object outputValue;
|
||||
if (hasInnerCollections)
|
||||
{
|
||||
outputValue = new SpeckleCollectionWrapperGoo(childWrapper);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create appropriate Goo types for child objects
|
||||
List<IGH_Goo> childObjectGoos = childWrapper.GetAtomicObjects().Select(obj => obj.CreateGoo()).ToList();
|
||||
outputValue = childObjectGoos;
|
||||
}
|
||||
|
||||
outputParams.Add(new OutputParamWrapper(param, outputValue, topology));
|
||||
}
|
||||
|
||||
if (da.Iteration == 0 && OutputMismatch(outputParams))
|
||||
@@ -142,7 +146,6 @@ public class ExpandCollection : GH_Component, IGH_VariableParameterComponent
|
||||
da.SetDataList(i, outParamWrapper.Values as IList);
|
||||
break;
|
||||
case GH_ParamAccess.tree:
|
||||
//TODO: means we need to convert the collection to a tree
|
||||
var topo = outParamWrapper.Topology.NotNull();
|
||||
var values = outParamWrapper.Values as IList;
|
||||
var tree = GrasshopperHelpers.CreateDataTreeFromTopologyAndItems(topo, values.NotNull());
|
||||
|
||||
@@ -3,17 +3,19 @@ namespace Speckle.Connectors.GrasshopperShared.Components;
|
||||
// NOTE: The number of spaces determines the order in which they display in the ribbon (nice hack)
|
||||
public static class ComponentCategories
|
||||
{
|
||||
// ribbon
|
||||
public const string PRIMARY_RIBBON = "Speckle";
|
||||
public const string OPERATIONS = " Ops";
|
||||
public const string OBJECTS = " Objects";
|
||||
public const string COLLECTIONS = " Collections";
|
||||
|
||||
// categories
|
||||
public const string OPERATIONS = " Models";
|
||||
public const string OBJECTS = " Objects";
|
||||
public const string COLLECTIONS = " Collections";
|
||||
public const string PARAMETERS = " Params";
|
||||
public const string DEVELOPER = "Dev";
|
||||
}
|
||||
|
||||
public enum ComponentState
|
||||
{
|
||||
Cancelled,
|
||||
Expired,
|
||||
NeedsInput,
|
||||
Receiving,
|
||||
|
||||
+74
-46
@@ -2,12 +2,14 @@ using System.Collections;
|
||||
using System.Runtime.InteropServices;
|
||||
using Grasshopper.Kernel;
|
||||
using Grasshopper.Kernel.Parameters;
|
||||
using Grasshopper.Kernel.Types;
|
||||
using Rhino.Geometry;
|
||||
using Speckle.Connectors.GrasshopperShared.HostApp;
|
||||
using Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
using Speckle.Connectors.GrasshopperShared.Properties;
|
||||
using Speckle.Sdk.Common.Exceptions;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.Dev;
|
||||
|
||||
@@ -28,12 +30,7 @@ public class DeconstructSpeckleParam : GH_Component, IGH_VariableParameterCompon
|
||||
|
||||
protected override void RegisterInputParams(GH_InputParamManager pManager)
|
||||
{
|
||||
pManager.AddGenericParameter(
|
||||
"Speckle Param",
|
||||
"SP",
|
||||
"Speckle param to deconstruct. Expects Collections, Objects, Materials, or Properties",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
pManager.AddGenericParameter("Speckle Param", "SP", "Speckle param to deconstruct", GH_ParamAccess.item);
|
||||
}
|
||||
|
||||
protected override void RegisterOutputParams(GH_OutputParamManager pManager) { }
|
||||
@@ -47,20 +44,29 @@ public class DeconstructSpeckleParam : GH_Component, IGH_VariableParameterCompon
|
||||
|
||||
switch (data)
|
||||
{
|
||||
case SpeckleObjectWrapperGoo obj:
|
||||
Name = string.IsNullOrEmpty(obj.Value.Name) ? obj.Value.Base.speckle_type : obj.Value.Name;
|
||||
outputParams = CreateOutputParamsFromBase(obj.Value.Base);
|
||||
case SpeckleCollectionWrapperGoo collectionGoo when collectionGoo.Value != null:
|
||||
// get children elements from the wrapper to override the elements prop while parsing
|
||||
List<IGH_Goo> children = collectionGoo.Value.Elements.Select(o => ((SpeckleWrapper)o).CreateGoo()).ToList();
|
||||
outputParams = ParseSpeckleWrapper(collectionGoo.Value, children);
|
||||
break;
|
||||
case SpeckleCollectionWrapperGoo coll:
|
||||
Name = string.IsNullOrEmpty(coll.Value.Collection.name)
|
||||
? coll.Value.Collection.speckle_type
|
||||
: coll.Value.Collection.name;
|
||||
outputParams = CreateOutputParamsFromBase(coll.Value.Collection);
|
||||
case SpeckleDataObjectWrapperGoo dataObjectGoo when dataObjectGoo.Value != null:
|
||||
// get geometries from the wrapper to override the displayvalue prop while parsing
|
||||
List<IGH_Goo> display = dataObjectGoo.Value.Geometries.Select(o => o.CreateGoo()).ToList();
|
||||
outputParams = ParseSpeckleWrapper(dataObjectGoo.Value, null, display);
|
||||
break;
|
||||
case SpeckleMaterialWrapperGoo matGoo:
|
||||
Name = string.IsNullOrEmpty(matGoo.Value.Name) ? matGoo.Value.Material.speckle_type : matGoo.Value.Name;
|
||||
outputParams = CreateOutputParamsFromBase(matGoo.Value.Base);
|
||||
case SpeckleGeometryWrapperGoo objectGoo when objectGoo.Value != null:
|
||||
outputParams = ParseSpeckleWrapper(objectGoo.Value);
|
||||
break;
|
||||
case SpeckleBlockInstanceWrapperGoo blockInstanceGoo when blockInstanceGoo.Value != null:
|
||||
outputParams = ParseSpeckleWrapper(blockInstanceGoo.Value);
|
||||
break;
|
||||
case SpeckleBlockDefinitionWrapperGoo blockDef:
|
||||
outputParams = ParseSpeckleWrapper(blockDef.Value);
|
||||
break;
|
||||
case SpeckleMaterialWrapperGoo materialGoo when materialGoo.Value != null:
|
||||
outputParams = ParseSpeckleWrapper(materialGoo.Value);
|
||||
break;
|
||||
|
||||
case SpecklePropertyGroupGoo propGoo:
|
||||
Name = $"properties ({propGoo.Value.Count})";
|
||||
outputParams = new();
|
||||
@@ -72,10 +78,17 @@ public class DeconstructSpeckleParam : GH_Component, IGH_VariableParameterCompon
|
||||
: value is SpecklePropertyGroupGoo propGroup
|
||||
? propGroup
|
||||
: value;
|
||||
outputParams.Add(CreateOutputParamByKeyValue(key, outputValue, GH_ParamAccess.item));
|
||||
|
||||
OutputParamWrapper output =
|
||||
outputValue is IList
|
||||
? CreateOutputParamByKeyValue(key, outputValue, GH_ParamAccess.list)
|
||||
: CreateOutputParamByKeyValue(key, outputValue, GH_ParamAccess.item);
|
||||
outputParams.Add(output);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, $"Type cannot be deconstructed: {data.GetType().Name}");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -111,7 +124,21 @@ public class DeconstructSpeckleParam : GH_Component, IGH_VariableParameterCompon
|
||||
}
|
||||
}
|
||||
|
||||
private List<OutputParamWrapper> CreateOutputParamsFromBase(Base @base)
|
||||
private List<OutputParamWrapper> ParseSpeckleWrapper(
|
||||
SpeckleWrapper wrapper,
|
||||
List<IGH_Goo>? elements = null,
|
||||
List<IGH_Goo>? displayValue = null
|
||||
)
|
||||
{
|
||||
Name = string.IsNullOrEmpty(wrapper.Name) ? wrapper.Base.speckle_type : wrapper.Name;
|
||||
return CreateOutputParamsFromBase(wrapper.Base, elements, displayValue);
|
||||
}
|
||||
|
||||
private List<OutputParamWrapper> CreateOutputParamsFromBase(
|
||||
Base @base,
|
||||
List<IGH_Goo>? elements = null,
|
||||
List<IGH_Goo>? displayValue = null
|
||||
)
|
||||
{
|
||||
List<OutputParamWrapper> result = new();
|
||||
if (@base == null)
|
||||
@@ -132,16 +159,25 @@ public class DeconstructSpeckleParam : GH_Component, IGH_VariableParameterCompon
|
||||
|
||||
case IList list:
|
||||
List<object> nativeObjects = new();
|
||||
|
||||
// override list value if base is a collection and this is the elements prop, since this is empty if coming from a collectionwrapper
|
||||
if (@base is Collection && prop.Key == "elements" && elements != null)
|
||||
{
|
||||
list = elements;
|
||||
}
|
||||
|
||||
// override list value if base is a dataobject and this is the displayvalue prop, since this is empty if coming from a dataobject wrapper
|
||||
if (@base is Speckle.Objects.Data.DataObject && prop.Key == "displayValue" && displayValue != null)
|
||||
{
|
||||
list = displayValue;
|
||||
}
|
||||
|
||||
foreach (var x in list)
|
||||
{
|
||||
switch (x)
|
||||
{
|
||||
case SpeckleCollectionWrapper collWrapper:
|
||||
nativeObjects.Add(new SpeckleCollectionWrapperGoo(collWrapper));
|
||||
break;
|
||||
|
||||
case SpeckleObjectWrapper objWrapper:
|
||||
nativeObjects.Add(new SpeckleObjectWrapperGoo(objWrapper));
|
||||
case SpeckleWrapper wrapper:
|
||||
nativeObjects.Add(wrapper.CreateGoo());
|
||||
break;
|
||||
|
||||
case Base xBase:
|
||||
@@ -163,16 +199,8 @@ public class DeconstructSpeckleParam : GH_Component, IGH_VariableParameterCompon
|
||||
result.Add(CreateOutputParamByKeyValue(prop.Key, propertyGoo, GH_ParamAccess.item));
|
||||
break;
|
||||
|
||||
case SpeckleCollectionWrapper collWrapper:
|
||||
result.Add(
|
||||
CreateOutputParamByKeyValue(prop.Key, new SpeckleCollectionWrapperGoo(collWrapper), GH_ParamAccess.item)
|
||||
);
|
||||
break;
|
||||
|
||||
case SpeckleObjectWrapper objWrapper:
|
||||
result.Add(
|
||||
CreateOutputParamByKeyValue(prop.Key, new SpeckleObjectWrapperGoo(objWrapper), GH_ParamAccess.item)
|
||||
);
|
||||
case SpeckleWrapper wrapper:
|
||||
result.Add(CreateOutputParamByKeyValue(prop.Key, wrapper.CreateGoo(), GH_ParamAccess.item));
|
||||
break;
|
||||
|
||||
case Base baseValue:
|
||||
@@ -194,24 +222,24 @@ public class DeconstructSpeckleParam : GH_Component, IGH_VariableParameterCompon
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<SpeckleObjectWrapperGoo> ConvertOrCreateWrapper(Base @base)
|
||||
private List<SpeckleGeometryWrapperGoo> ConvertOrCreateWrapper(Base @base)
|
||||
{
|
||||
try
|
||||
{
|
||||
// convert the base and create a wrapper for each result
|
||||
List<(GeometryBase, Base)> convertedBase = SpeckleConversionContext.ConvertToHost(@base);
|
||||
List<SpeckleObjectWrapperGoo> convertedWrappers = new();
|
||||
foreach ((GeometryBase g, Base b) in convertedBase)
|
||||
List<(object, Base)> convertedBase = SpeckleConversionContext.ConvertToHost(@base);
|
||||
List<SpeckleGeometryWrapperGoo> convertedWrappers = new();
|
||||
foreach ((object o, Base b) in convertedBase)
|
||||
{
|
||||
SpeckleObjectWrapper convertedWrapper =
|
||||
GeometryBase? g = o as GeometryBase;
|
||||
SpeckleGeometryWrapper convertedWrapper =
|
||||
new()
|
||||
{
|
||||
Base = b,
|
||||
GeometryBase = g,
|
||||
Name = b["name"] as string ?? "",
|
||||
Color = null,
|
||||
Material = null,
|
||||
WrapperGuid = null
|
||||
Material = null
|
||||
};
|
||||
|
||||
convertedWrappers.Add(new(convertedWrapper));
|
||||
@@ -223,17 +251,17 @@ public class DeconstructSpeckleParam : GH_Component, IGH_VariableParameterCompon
|
||||
{
|
||||
// some classes, like RawEncoding, have no direct conversion or fallback value.
|
||||
// when this is the case, wrap it to allow users to further expand the object.
|
||||
SpeckleObjectWrapper convertedWrapper =
|
||||
SpeckleGeometryWrapper convertedWrapper =
|
||||
new()
|
||||
{
|
||||
Base = @base,
|
||||
GeometryBase = null,
|
||||
Name = @base[Constants.NAME_PROP] as string ?? "",
|
||||
Color = null,
|
||||
Material = null,
|
||||
WrapperGuid = null,
|
||||
Material = null
|
||||
};
|
||||
return new() { new SpeckleObjectWrapperGoo(convertedWrapper) };
|
||||
|
||||
return new() { new SpeckleGeometryWrapperGoo(convertedWrapper) };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using Grasshopper.Kernel;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Connectors.GrasshopperShared.HostApp;
|
||||
using Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
using Speckle.Connectors.GrasshopperShared.Properties;
|
||||
using Speckle.Connectors.GrasshopperShared.Registration;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Api;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.Dev;
|
||||
|
||||
[Guid("18152AE4-4BE7-46F0-9826-09061897A5CC")]
|
||||
public class TokenUrlComponent : GH_Component
|
||||
{
|
||||
public TokenUrlComponent()
|
||||
: base(
|
||||
"Speckle Model URL",
|
||||
"URL",
|
||||
"Create a Speckle model link using URL and developer token",
|
||||
ComponentCategories.PRIMARY_RIBBON,
|
||||
ComponentCategories.DEVELOPER
|
||||
) { }
|
||||
|
||||
public override Guid ComponentGuid => GetType().GUID;
|
||||
protected override Bitmap Icon => Resources.speckle_inputs_token;
|
||||
|
||||
protected override void RegisterInputParams(GH_InputParamManager pManager)
|
||||
{
|
||||
pManager.AddTextParameter("Speckle Url", "Url", "Speckle URL", GH_ParamAccess.item);
|
||||
pManager.AddTextParameter("Speckle Token", "Token", "Speckle Authorization Token", GH_ParamAccess.item);
|
||||
}
|
||||
|
||||
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
|
||||
{
|
||||
pManager.AddParameter(new SpeckleUrlModelResourceParam());
|
||||
}
|
||||
|
||||
protected override void SolveInstance(IGH_DataAccess da)
|
||||
{
|
||||
// get inputs
|
||||
string urlInput = "";
|
||||
if (!da.GetData(0, ref urlInput))
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"Speckle Url is missing");
|
||||
return;
|
||||
}
|
||||
|
||||
string tokenInput = "";
|
||||
if (!da.GetData(1, ref tokenInput))
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"Speckle token is missing");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// NOTE: once we split the logic in Sender and Receiver components, we need to set flag correctly
|
||||
var (resource, hasPermission) = SolveInstanceWithUrAndToken(urlInput, tokenInput, true);
|
||||
if (!hasPermission)
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "You do not have enough permission for this project.");
|
||||
}
|
||||
da.SetData(0, resource);
|
||||
}
|
||||
catch (SpeckleException e)
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, e.Message);
|
||||
da.AbortComponentSolution();
|
||||
}
|
||||
}
|
||||
|
||||
public (SpeckleUrlModelResource resource, bool hasPermission) SolveInstanceWithUrAndToken(
|
||||
string input,
|
||||
string token,
|
||||
bool isSender
|
||||
)
|
||||
{
|
||||
// When input is provided, lock interaction of buttons so only text is shown (no context menu)
|
||||
// Should perform validation, fill in all internal data of the component (project, model, version, account)
|
||||
// Should notify user if any of this goes wrong.
|
||||
|
||||
var resources = SpeckleResourceBuilder.FromUrlString(input, token);
|
||||
if (resources.Length != 1)
|
||||
{
|
||||
// POC: this shouldn't ever hit since exceptions are thrown in the FromUrlString method
|
||||
throw new SpeckleException($"FromUrlString parser returned an invalid resource");
|
||||
}
|
||||
|
||||
var resource = resources.First();
|
||||
using var scope = PriorityLoader.CreateScopeForActiveDocument();
|
||||
var account = resource.Account.GetAccount(scope);
|
||||
if (account != null)
|
||||
{
|
||||
scope.Get<IAccountService>().SetUserSelectedAccountId(account.id);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new SpeckleException("No account found for server URL");
|
||||
}
|
||||
|
||||
IClient client = scope.Get<IClientFactory>().Create(account);
|
||||
|
||||
var project = client.Project.Get(resource.ProjectId).Result;
|
||||
var projectPermissions = client.Project.GetPermissions(resource.ProjectId).Result;
|
||||
if (project != null && project.workspaceId != null)
|
||||
{
|
||||
var workspace = client.Workspace.Get(project.workspaceId).Result;
|
||||
}
|
||||
|
||||
switch (resource)
|
||||
{
|
||||
case SpeckleUrlLatestModelVersionResource latestVersionResource:
|
||||
var model = client.Model.Get(latestVersionResource.ModelId, latestVersionResource.ProjectId).Result;
|
||||
break;
|
||||
case SpeckleUrlModelVersionResource versionResource:
|
||||
var m = client.Model.Get(versionResource.ModelId, versionResource.ProjectId).Result;
|
||||
// TODO: this wont be the case when we have separation between send and receive components
|
||||
var v = client.Version.Get(versionResource.VersionId, versionResource.ProjectId).Result;
|
||||
break;
|
||||
case SpeckleUrlModelObjectResource:
|
||||
throw new SpeckleException("Object URLs are not supported");
|
||||
default:
|
||||
throw new SpeckleException("Unknown Speckle resource type");
|
||||
}
|
||||
|
||||
return (resource, isSender ? projectPermissions.canPublish.authorized : projectPermissions.canLoad.authorized);
|
||||
}
|
||||
}
|
||||
-241
@@ -1,241 +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;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.Objects;
|
||||
|
||||
[Guid("F9418610-ACAE-4417-B010-19EBEA6A121F")]
|
||||
public class CreateSpeckleObject : GH_Component
|
||||
{
|
||||
public CreateSpeckleObject()
|
||||
: base(
|
||||
"Speckle Object",
|
||||
"SO",
|
||||
"Create or modify a Speckle Object",
|
||||
ComponentCategories.PRIMARY_RIBBON,
|
||||
ComponentCategories.OBJECTS
|
||||
) { }
|
||||
|
||||
public override Guid ComponentGuid => GetType().GUID;
|
||||
protected override Bitmap Icon => Resources.speckle_objects_object;
|
||||
|
||||
protected override void RegisterInputParams(GH_InputParamManager pManager)
|
||||
{
|
||||
pManager.AddGenericParameter(
|
||||
"Object",
|
||||
"O",
|
||||
"Input Object. Speckle Objects, Model Objects, and geometry are accepted.",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
Params.Input[0].Optional = true;
|
||||
|
||||
pManager.AddGenericParameter(
|
||||
"Geometry",
|
||||
"G",
|
||||
"Geometry of the Speckle Object. GeometryBase in Grasshopper includes text entities.",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
Params.Input[1].Optional = true;
|
||||
|
||||
pManager.AddTextParameter("Name", "N", "Name of the Speckle Object", GH_ParamAccess.item);
|
||||
Params.Input[2].Optional = true;
|
||||
|
||||
pManager.AddGenericParameter(
|
||||
"Properties",
|
||||
"P",
|
||||
"The properties of the Speckle Object. Speckle Properties and User Content are accepted.",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
Params.Input[3].Optional = true;
|
||||
|
||||
pManager.AddColourParameter("Color", "c", "The color of the Speckle Object", GH_ParamAccess.item);
|
||||
Params.Input[4].Optional = true;
|
||||
|
||||
pManager.AddGenericParameter(
|
||||
"Material",
|
||||
"m",
|
||||
"The material of the Speckle Object. Display Materials, Model Materials, and Speckle Materials are accepted.",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
Params.Input[5].Optional = true;
|
||||
|
||||
/* POC: disable for now as we are doing anything with this
|
||||
pManager.AddTextParameter(
|
||||
"Path",
|
||||
"p",
|
||||
"The Collection Path of the Speckle Object. Should be delimited with `:`",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
Params.Input[6].Optional = true;
|
||||
*/
|
||||
}
|
||||
|
||||
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
|
||||
{
|
||||
pManager.AddParameter(new SpeckleObjectParam(), "Object", "O", "Speckle Object", GH_ParamAccess.item);
|
||||
|
||||
pManager.AddGenericParameter(
|
||||
"Geometry",
|
||||
"G",
|
||||
"Geometry of the Speckle Object. GeometryBase in Grasshopper includes text entities.",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
|
||||
pManager.AddTextParameter("Name", "N", "Name of the Speckle Object", GH_ParamAccess.item);
|
||||
|
||||
pManager.AddParameter(
|
||||
new SpecklePropertyGroupParam(),
|
||||
"Properties",
|
||||
"P",
|
||||
"The properties of the Speckle Object",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
|
||||
pManager.AddColourParameter("Color", "c", "The color of the Speckle Object", GH_ParamAccess.item);
|
||||
|
||||
pManager.AddParameter(
|
||||
new SpeckleMaterialParam(),
|
||||
"Material",
|
||||
"M",
|
||||
"The material of the Speckle Object.",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
|
||||
pManager.AddTextParameter(
|
||||
"Path",
|
||||
"p",
|
||||
$"The Collection Path of the Speckle Object, delimited with `{Constants.LAYER_PATH_DELIMITER}`",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
}
|
||||
|
||||
protected override void SolveInstance(IGH_DataAccess da)
|
||||
{
|
||||
IGH_Goo? inputObject = null;
|
||||
da.GetData(0, ref inputObject);
|
||||
|
||||
IGH_GeometricGoo? inputGeometry = null;
|
||||
da.GetData(1, ref inputGeometry);
|
||||
|
||||
string? inputName = null;
|
||||
da.GetData(2, ref inputName);
|
||||
|
||||
IGH_Goo? inputProperties = null;
|
||||
da.GetData(3, ref inputProperties);
|
||||
|
||||
Color? inputColor = null;
|
||||
da.GetData(4, ref inputColor);
|
||||
|
||||
IGH_Goo? inputMaterial = null;
|
||||
da.GetData(5, ref inputMaterial);
|
||||
|
||||
//string? inputPath = null;
|
||||
//da.GetData(6, ref inputPath);
|
||||
|
||||
// keep track of mutation
|
||||
// poc: we should not mark mutations on color or material, as this shouldn't affect the appId of the object, and will allow original display values to stay intact on send.
|
||||
bool mutated = false;
|
||||
|
||||
// process the object
|
||||
SpeckleObjectWrapperGoo result = new();
|
||||
if (inputObject != null)
|
||||
{
|
||||
if (!result.CastFrom(inputObject))
|
||||
{
|
||||
AddRuntimeMessage(
|
||||
GH_RuntimeMessageLevel.Warning,
|
||||
$"Object input is not valid. Only Speckle Objects, Baked Model Objects, and Geometry are accepted."
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// process geometry
|
||||
// at this point, we can ensure that the Base in the wrapper is a DataObject.
|
||||
if (inputObject == null && inputGeometry == null)
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"Pass in an Object or Geometry.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (inputGeometry != null)
|
||||
{
|
||||
result.Value.GeometryBase = inputGeometry.GeometricGooToGeometryBase();
|
||||
Base converted = SpeckleConversionContext.ConvertToSpeckle(result.Value.GeometryBase);
|
||||
converted[Constants.NAME_PROP] = result.Value.Name;
|
||||
converted.applicationId = result.Value.ApplicationId;
|
||||
result.Value.Base = converted;
|
||||
mutated = true;
|
||||
}
|
||||
|
||||
// process name
|
||||
if (inputName != null)
|
||||
{
|
||||
result.Value.Name = inputName;
|
||||
mutated = true;
|
||||
}
|
||||
|
||||
// process properties
|
||||
if (inputProperties != null)
|
||||
{
|
||||
SpecklePropertyGroupGoo propGoo = new();
|
||||
if (!propGoo.CastFrom(inputProperties))
|
||||
{
|
||||
AddRuntimeMessage(
|
||||
GH_RuntimeMessageLevel.Warning,
|
||||
$"Properties input is not valid. Only Speckle Properties and User Content are accepted."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
result.Value.Properties = propGoo;
|
||||
mutated = true;
|
||||
}
|
||||
|
||||
// process color (no mutation)
|
||||
if (inputColor != null)
|
||||
{
|
||||
result.Value.Color = inputColor;
|
||||
}
|
||||
|
||||
// process material (no mutation)
|
||||
if (inputMaterial != null)
|
||||
{
|
||||
SpeckleMaterialWrapperGoo matWrapperGoo = new();
|
||||
if (!matWrapperGoo.CastFrom(inputMaterial))
|
||||
{
|
||||
AddRuntimeMessage(
|
||||
GH_RuntimeMessageLevel.Warning,
|
||||
$"Material input is not valid. Only Display Materials, Baked Model Materials, and Speckle Materials are accepted."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
result.Value.Material = matWrapperGoo.Value;
|
||||
}
|
||||
|
||||
// process application Id. Use a new appId if mutated, or if this is a new object
|
||||
result.Value.ApplicationId = mutated
|
||||
? Guid.NewGuid().ToString()
|
||||
: result.Value.ApplicationId ?? Guid.NewGuid().ToString();
|
||||
|
||||
// get the path
|
||||
string path =
|
||||
result.Value.Path.Count > 1
|
||||
? string.Join(Constants.LAYER_PATH_DELIMITER, result.Value.Path)
|
||||
: result.Value.Path.FirstOrDefault();
|
||||
|
||||
// set all the data
|
||||
da.SetData(0, result.Value);
|
||||
da.SetData(1, result.Value.GeometryBase);
|
||||
da.SetData(2, result.Value.Name);
|
||||
da.SetData(3, result.Value.Properties);
|
||||
da.SetData(4, result.Value.Color);
|
||||
da.SetData(5, result.Value.Material);
|
||||
da.SetData(6, path);
|
||||
}
|
||||
}
|
||||
+39
-2
@@ -17,6 +17,7 @@ public class CreateSpeckleProperties : VariableParameterComponentBase
|
||||
|
||||
public override Guid ComponentGuid => GetType().GUID;
|
||||
protected override Bitmap Icon => Resources.speckle_properties_create;
|
||||
public override GH_Exposure Exposure => GH_Exposure.quarternary;
|
||||
|
||||
public CreateSpeckleProperties()
|
||||
: base(
|
||||
@@ -35,7 +36,13 @@ public class CreateSpeckleProperties : VariableParameterComponentBase
|
||||
|
||||
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
|
||||
{
|
||||
pManager.AddGenericParameter("Properties", "P", "Properties for Speckle Objects", GH_ParamAccess.item);
|
||||
pManager.AddParameter(
|
||||
new SpecklePropertyGroupParam(),
|
||||
"Properties",
|
||||
"P",
|
||||
"Properties for Speckle Objects",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
}
|
||||
|
||||
protected override void SolveInstance(IGH_DataAccess da)
|
||||
@@ -59,7 +66,17 @@ public class CreateSpeckleProperties : VariableParameterComponentBase
|
||||
for (int i = 0; i < Params.Input.Count; i++)
|
||||
{
|
||||
var paramName = Params.Input[i].NickName;
|
||||
var propertyValue = ExtractPropertyValue(da, i, paramName);
|
||||
|
||||
var data = Params.Input[i].VolatileData.AllData(true).ToList();
|
||||
if (data.Count == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ISpecklePropertyGoo? propertyValue =
|
||||
Params.Input[i].Access == GH_ParamAccess.item
|
||||
? ExtractPropertyValue(da, i, paramName)
|
||||
: ExtractPropertyListValue(da, i, paramName);
|
||||
|
||||
if (propertyValue != null)
|
||||
{
|
||||
@@ -100,6 +117,26 @@ public class CreateSpeckleProperties : VariableParameterComponentBase
|
||||
return propertyGoo;
|
||||
}
|
||||
|
||||
private ISpecklePropertyGoo? ExtractPropertyListValue(IGH_DataAccess da, int index, string paramName)
|
||||
{
|
||||
List<object?> value = new();
|
||||
da.GetDataList(index, value);
|
||||
|
||||
var propertyGoo = new SpecklePropertyGoo();
|
||||
|
||||
if (!propertyGoo.CastFrom(value))
|
||||
{
|
||||
AddRuntimeMessage(
|
||||
GH_RuntimeMessageLevel.Error,
|
||||
$"Parameter '{paramName}' contains invalid data type. Only strings, numbers, and booleans are supported."
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return propertyGoo;
|
||||
}
|
||||
|
||||
protected override void AppendComponentSpecificMenuItems(ToolStripDropDown menu)
|
||||
{
|
||||
Menu_AppendSeparator(menu);
|
||||
|
||||
+53
-37
@@ -1,6 +1,8 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using Grasshopper.Kernel;
|
||||
using Grasshopper.Kernel.Types;
|
||||
using Speckle.Connectors.GrasshopperShared.Components.BaseComponents;
|
||||
using Speckle.Connectors.GrasshopperShared.HostApp;
|
||||
using Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
using Speckle.Connectors.GrasshopperShared.Properties;
|
||||
|
||||
@@ -14,6 +16,7 @@ public class FilterSpeckleObjects : GH_Component
|
||||
{
|
||||
public override Guid ComponentGuid => GetType().GUID;
|
||||
protected override Bitmap Icon => Resources.speckle_objects_filter;
|
||||
public override GH_Exposure Exposure => GH_Exposure.primary;
|
||||
|
||||
public FilterSpeckleObjects()
|
||||
: base(
|
||||
@@ -26,7 +29,7 @@ public class FilterSpeckleObjects : GH_Component
|
||||
|
||||
protected override void RegisterInputParams(GH_InputParamManager pManager)
|
||||
{
|
||||
pManager.AddParameter(new SpeckleObjectParam(), "Objects", "O", "Speckle Objects to filter", GH_ParamAccess.list);
|
||||
pManager.AddGenericParameter("Objects", "O", "Speckle Objects to filter", GH_ParamAccess.list);
|
||||
|
||||
pManager.AddTextParameter("Name", "N", "Find objects with a matching name", GH_ParamAccess.item);
|
||||
Params.Input[1].Optional = true;
|
||||
@@ -61,16 +64,9 @@ public class FilterSpeckleObjects : GH_Component
|
||||
|
||||
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
|
||||
{
|
||||
pManager.AddParameter(
|
||||
new SpeckleObjectParam(),
|
||||
"Objects",
|
||||
"O",
|
||||
"The objects that match the queries",
|
||||
GH_ParamAccess.tree
|
||||
);
|
||||
pManager.AddGenericParameter("Objects", "O", "The objects that match the queries", GH_ParamAccess.tree);
|
||||
|
||||
pManager.AddParameter(
|
||||
new SpeckleObjectParam(),
|
||||
pManager.AddGenericParameter(
|
||||
"Culled Objects",
|
||||
"co",
|
||||
"The objects that did not match the queries",
|
||||
@@ -80,11 +76,24 @@ public class FilterSpeckleObjects : GH_Component
|
||||
|
||||
protected override void SolveInstance(IGH_DataAccess dataAccess)
|
||||
{
|
||||
List<SpeckleObjectWrapperGoo?> inputObjects = new();
|
||||
List<IGH_Goo> inputObjects = new();
|
||||
dataAccess.GetDataList(0, inputObjects);
|
||||
|
||||
if (inputObjects.Count == 0)
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"Add objects to filter");
|
||||
return;
|
||||
}
|
||||
|
||||
List<SpeckleWrapper?> objects = inputObjects
|
||||
.Select(o => o.ToSpeckleObjectWrapper())
|
||||
.Where(o => o is not null)
|
||||
.ToList();
|
||||
|
||||
int unsupported = inputObjects.Count - objects.Count;
|
||||
if (unsupported > 0)
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, $"Input contained {unsupported} unsupported objects.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -99,21 +108,16 @@ public class FilterSpeckleObjects : GH_Component
|
||||
string speckleId = "";
|
||||
dataAccess.GetData(5, ref speckleId);
|
||||
|
||||
List<SpeckleObjectWrapper> matchedObjects = new();
|
||||
List<SpeckleObjectWrapper> removedObjects = new();
|
||||
for (int i = 0; i < inputObjects.Count; i++)
|
||||
List<SpeckleWrapper> matchedObjects = new();
|
||||
List<SpeckleWrapper> removedObjects = new();
|
||||
for (int i = 0; i < objects.Count; i++)
|
||||
{
|
||||
SpeckleObjectWrapperGoo? inputObject = inputObjects[i];
|
||||
if (inputObject is null)
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"A null input object was detected.");
|
||||
return;
|
||||
}
|
||||
SpeckleWrapper wrapper = objects[i]!;
|
||||
|
||||
// filter by name
|
||||
if (!MatchesSearchPattern(name, inputObject.Value.Name))
|
||||
if (!MatchesSearchPattern(name, wrapper.Name))
|
||||
{
|
||||
removedObjects.Add(inputObject.Value);
|
||||
removedObjects.Add(wrapper);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -125,49 +129,61 @@ public class FilterSpeckleObjects : GH_Component
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (string key in inputObject.Value.Properties.Value.Keys)
|
||||
SpecklePropertyGroupGoo? properties = wrapper is SpeckleDataObjectWrapper dataObjPropWrapper
|
||||
? dataObjPropWrapper.Properties
|
||||
: wrapper is SpeckleGeometryWrapper geoPropWrapper
|
||||
? geoPropWrapper.Properties
|
||||
: null;
|
||||
|
||||
if (properties is not null)
|
||||
{
|
||||
if (MatchesSearchPattern(property, key))
|
||||
foreach (string key in properties.Value.Keys)
|
||||
{
|
||||
foundProperty = true;
|
||||
break;
|
||||
if (MatchesSearchPattern(property, key))
|
||||
{
|
||||
foundProperty = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundProperty)
|
||||
{
|
||||
removedObjects.Add(inputObject.Value);
|
||||
removedObjects.Add(wrapper);
|
||||
continue;
|
||||
}
|
||||
|
||||
// filter by material name
|
||||
if (!MatchesSearchPattern(material, inputObject.Value.Material?.Name ?? ""))
|
||||
if (wrapper is SpeckleGeometryWrapper geoWrapper)
|
||||
{
|
||||
removedObjects.Add(inputObject.Value);
|
||||
continue;
|
||||
if (!MatchesSearchPattern(material, geoWrapper.Material?.Name ?? ""))
|
||||
{
|
||||
removedObjects.Add(wrapper);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// filter by application id
|
||||
if (!MatchesSearchPattern(appId, inputObject.Value.Base.applicationId ?? ""))
|
||||
if (!MatchesSearchPattern(appId, wrapper.Base.applicationId ?? ""))
|
||||
{
|
||||
removedObjects.Add(inputObject.Value);
|
||||
removedObjects.Add(wrapper);
|
||||
continue;
|
||||
}
|
||||
|
||||
// filter by speckle id
|
||||
if (!MatchesSearchPattern(speckleId, inputObject.Value.Base.id ?? ""))
|
||||
if (!MatchesSearchPattern(speckleId, wrapper.Base.id ?? ""))
|
||||
{
|
||||
removedObjects.Add(inputObject.Value);
|
||||
removedObjects.Add(wrapper);
|
||||
continue;
|
||||
}
|
||||
|
||||
matchedObjects.Add(inputObject.Value);
|
||||
matchedObjects.Add(wrapper);
|
||||
}
|
||||
|
||||
// Set output objects
|
||||
dataAccess.SetDataList(0, matchedObjects);
|
||||
dataAccess.SetDataList(1, removedObjects);
|
||||
dataAccess.SetDataList(0, matchedObjects.Select(o => o.CreateGoo()));
|
||||
dataAccess.SetDataList(1, removedObjects.Select(o => o.CreateGoo()));
|
||||
}
|
||||
|
||||
private bool MatchesSearchPattern(string searchPattern, string target)
|
||||
|
||||
-141
@@ -1,141 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using Grasshopper.Kernel;
|
||||
using Speckle.Connectors.GrasshopperShared.HostApp;
|
||||
using Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
using Speckle.Connectors.GrasshopperShared.Properties;
|
||||
using Speckle.Sdk;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.Objects;
|
||||
|
||||
/// <summary>
|
||||
/// Given a collection, this component will output the objects in the subcollection corresponding to the input path
|
||||
/// </summary>
|
||||
[Guid("77CAEE94-F0B9-4611-897C-71F2A22BA311")]
|
||||
public class GetCollectionObjects : GH_Component
|
||||
{
|
||||
public override Guid ComponentGuid => GetType().GUID;
|
||||
protected override Bitmap Icon => Resources.speckle_objects_query;
|
||||
|
||||
public GetCollectionObjects()
|
||||
: base(
|
||||
"Query Objects",
|
||||
"qO",
|
||||
"Retrieves the objects inside a Speckle collection at the specified path",
|
||||
ComponentCategories.PRIMARY_RIBBON,
|
||||
ComponentCategories.OBJECTS
|
||||
) { }
|
||||
|
||||
protected override void RegisterInputParams(GH_InputParamManager pManager)
|
||||
{
|
||||
pManager.AddParameter(
|
||||
new SpeckleCollectionParam(),
|
||||
"Collection",
|
||||
"C",
|
||||
"Collection to retrieve objects from",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
|
||||
pManager.AddTextParameter(
|
||||
"Path",
|
||||
"C",
|
||||
"Get the Speckle objects in the subcollection indicated by this path",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
|
||||
Params.Input[1].Optional = true;
|
||||
}
|
||||
|
||||
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
|
||||
{
|
||||
pManager.AddParameter(
|
||||
new SpeckleObjectParam(),
|
||||
"Objects",
|
||||
"O",
|
||||
"The objects in the input collection that match the queries",
|
||||
GH_ParamAccess.tree
|
||||
);
|
||||
}
|
||||
|
||||
protected override void SolveInstance(IGH_DataAccess dataAccess)
|
||||
{
|
||||
SpeckleCollectionWrapperGoo collectionWrapperGoo = new();
|
||||
dataAccess.GetData(0, ref collectionWrapperGoo);
|
||||
|
||||
if (collectionWrapperGoo.Value == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string path = "";
|
||||
dataAccess.GetData(1, ref path);
|
||||
|
||||
// filter by collection path
|
||||
// Note: the collection paths selector will omit the target collection from the path of nested collections.
|
||||
// the discard ("_objects") will be used to indicate objects found directly in the target collection.
|
||||
List<SpeckleObjectWrapper> filteredObjects = new();
|
||||
SpeckleCollectionWrapper? targetCollectionWrapper = null;
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
targetCollectionWrapper =
|
||||
path == "_objects" ? collectionWrapperGoo.Value : FindCollection(collectionWrapperGoo.Value, path);
|
||||
filteredObjects = targetCollectionWrapper
|
||||
.Elements.Where(e => e is SpeckleObjectWrapper)
|
||||
.Select(e => (SpeckleObjectWrapper)e)
|
||||
.ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
filteredObjects = GetAllObjectsFromCollection(collectionWrapperGoo.Value).ToList();
|
||||
}
|
||||
|
||||
// Set output objects
|
||||
if (targetCollectionWrapper?.Topology is string topology && !string.IsNullOrEmpty(topology))
|
||||
{
|
||||
var tree = GrasshopperHelpers.CreateDataTreeFromTopologyAndItems(topology, filteredObjects);
|
||||
dataAccess.SetDataTree(0, tree);
|
||||
}
|
||||
else
|
||||
{
|
||||
dataAccess.SetDataList(0, filteredObjects);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<SpeckleObjectWrapper> GetAllObjectsFromCollection(SpeckleCollectionWrapper collectionWrapper)
|
||||
{
|
||||
foreach (SpeckleWrapper element in collectionWrapper.Elements)
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case SpeckleCollectionWrapper childCollectionWrapper:
|
||||
foreach (var item in GetAllObjectsFromCollection(childCollectionWrapper))
|
||||
{
|
||||
yield return item;
|
||||
}
|
||||
break;
|
||||
case SpeckleObjectWrapper objectWrapper:
|
||||
yield return objectWrapper;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private SpeckleCollectionWrapper FindCollection(SpeckleCollectionWrapper root, string unifiedPath)
|
||||
{
|
||||
// POC: SpeckleCollections now have a full list<string> path prop on them always. Is this easier to use?
|
||||
List<string> paths = unifiedPath.Split([Constants.LAYER_PATH_DELIMITER], StringSplitOptions.None).ToList();
|
||||
SpeckleCollectionWrapper currentCollectionWrapper = root;
|
||||
while (paths.Count != 0)
|
||||
{
|
||||
currentCollectionWrapper = currentCollectionWrapper
|
||||
.Elements.OfType<SpeckleCollectionWrapper>()
|
||||
.First(wrapper => wrapper.Name == paths.First());
|
||||
paths.RemoveAt(0);
|
||||
if (paths.Count == 0)
|
||||
{
|
||||
return currentCollectionWrapper;
|
||||
}
|
||||
}
|
||||
|
||||
throw new SpeckleException("Did not find collection");
|
||||
}
|
||||
}
|
||||
-178
@@ -1,178 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using Grasshopper.Kernel;
|
||||
using Grasshopper.Kernel.Parameters;
|
||||
using Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
using Speckle.Connectors.GrasshopperShared.Properties;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.Objects;
|
||||
|
||||
[Guid("116F08A5-BAA7-45B3-B6C8-469E452C9AC7")]
|
||||
public class GetObjectProperties : GH_Component, IGH_VariableParameterComponent
|
||||
{
|
||||
public override Guid ComponentGuid => GetType().GUID;
|
||||
|
||||
protected override Bitmap Icon => Resources.speckle_properties_query;
|
||||
|
||||
public GetObjectProperties()
|
||||
: base(
|
||||
"Query Properties",
|
||||
"qP",
|
||||
"Retrieves the values of the properties inside Speckle Objects at the specified keys",
|
||||
ComponentCategories.PRIMARY_RIBBON,
|
||||
ComponentCategories.OBJECTS
|
||||
) { }
|
||||
|
||||
protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
|
||||
{
|
||||
pManager.AddParameter(
|
||||
new SpeckleObjectParam(),
|
||||
"Objects",
|
||||
"O",
|
||||
"Speckle Objects to retrieve properties",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
pManager.AddTextParameter("Keys", "K", "Property keys to filter by", GH_ParamAccess.list);
|
||||
}
|
||||
|
||||
protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) { }
|
||||
|
||||
protected override void SolveInstance(IGH_DataAccess da)
|
||||
{
|
||||
List<string> paths = new();
|
||||
da.GetDataList(1, paths);
|
||||
|
||||
if (paths.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (OutputMismatch(paths))
|
||||
{
|
||||
OnPingDocument()
|
||||
.ScheduleSolution(
|
||||
5,
|
||||
_ =>
|
||||
{
|
||||
CreateOutputs(paths);
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
SpeckleObjectWrapperGoo objectWrapperGoo = new();
|
||||
da.GetData(0, ref objectWrapperGoo);
|
||||
|
||||
// flatten object properties, if any
|
||||
SpecklePropertyGroupGoo properties = objectWrapperGoo.Value.Properties;
|
||||
if (properties.Value.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Dictionary<string, SpecklePropertyGoo> flattenedProps = properties.Flatten();
|
||||
|
||||
for (int i = 0; i < paths.Count; i++)
|
||||
{
|
||||
var name = paths[i];
|
||||
if (FindProperty(flattenedProps, name) is SpecklePropertyGoo prop)
|
||||
{
|
||||
da.SetData(i, prop.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
da.SetData(i, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// attempts to find a property by concatenated key, or returns null if not
|
||||
private SpecklePropertyGoo? FindProperty(Dictionary<string, SpecklePropertyGoo> props, string unifiedPath)
|
||||
{
|
||||
if (!props.TryGetValue(unifiedPath, out SpecklePropertyGoo currentGoo))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return currentGoo;
|
||||
}
|
||||
|
||||
private bool OutputMismatch(List<string> outputParams)
|
||||
{
|
||||
if (Params.Output.Count != outputParams.Count)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
foreach (var newParam in outputParams)
|
||||
{
|
||||
var oldParam = Params.Output[count];
|
||||
if (oldParam.NickName != newParam || oldParam.Name != newParam)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void CreateOutputs(List<string> outputParams)
|
||||
{
|
||||
// Ensure we have the required count of output parameters
|
||||
while (Params.Output.Count != outputParams.Count)
|
||||
{
|
||||
if (Params.Output.Count > outputParams.Count) // if too many, unregister
|
||||
{
|
||||
Params.UnregisterOutputParameter(Params.Output[^1]);
|
||||
}
|
||||
|
||||
if (Params.Output.Count < outputParams.Count) // if too little, add some
|
||||
{
|
||||
var param = new Param_GenericObject
|
||||
{
|
||||
Name = "newParam",
|
||||
NickName = "newParam",
|
||||
MutableNickName = false,
|
||||
Access = GH_ParamAccess.item
|
||||
};
|
||||
Params.RegisterOutputParam(param);
|
||||
}
|
||||
}
|
||||
|
||||
// now unify names and nicknames
|
||||
int index = 0;
|
||||
foreach (var newParam in outputParams)
|
||||
{
|
||||
Params.Output[index].NickName = newParam;
|
||||
Params.Output[index].Name = newParam;
|
||||
index++;
|
||||
}
|
||||
|
||||
// now we can update the output params
|
||||
Params.OnParametersChanged();
|
||||
VariableParameterMaintenance();
|
||||
ExpireSolution(false);
|
||||
}
|
||||
|
||||
public bool CanInsertParameter(GH_ParameterSide side, int index) => false;
|
||||
|
||||
public bool CanRemoveParameter(GH_ParameterSide side, int index) => false;
|
||||
|
||||
public IGH_Param CreateParameter(GH_ParameterSide side, int index)
|
||||
{
|
||||
var myParam = new Param_GenericObject
|
||||
{
|
||||
Name = GH_ComponentParamServer.InventUniqueNickname("ABCD", Params.Input),
|
||||
MutableNickName = true,
|
||||
Optional = true
|
||||
};
|
||||
myParam.NickName = myParam.Name;
|
||||
return myParam;
|
||||
}
|
||||
|
||||
public bool DestroyParameter(GH_ParameterSide side, int index) => side == GH_ParameterSide.Output;
|
||||
|
||||
public void VariableParameterMaintenance() { }
|
||||
}
|
||||
+13
-22
@@ -1,11 +1,9 @@
|
||||
using Grasshopper.Kernel;
|
||||
using Grasshopper.Kernel.Types;
|
||||
using Speckle.Connectors.Common.Extensions;
|
||||
using Speckle.Connectors.GrasshopperShared.Components.BaseComponents;
|
||||
using Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
using Speckle.Connectors.GrasshopperShared.Properties;
|
||||
#if RHINO8_OR_GREATER
|
||||
using Grasshopper.Rhinoceros.Model;
|
||||
#endif
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.Objects;
|
||||
|
||||
@@ -21,36 +19,29 @@ public class PropertyGroupPathsSelector : ValueSet<IGH_Goo>
|
||||
) { }
|
||||
|
||||
public override Guid ComponentGuid => new Guid("8882BE3A-81F1-4416-B420-58D69E4CC8F1");
|
||||
|
||||
protected override Bitmap Icon => Resources.speckle_inputs_property;
|
||||
public override GH_Exposure Exposure => GH_Exposure.quarternary;
|
||||
|
||||
protected override void LoadVolatileData()
|
||||
{
|
||||
var objectPropertyGroups = VolatileData
|
||||
var propertyGroups = VolatileData
|
||||
.AllData(true)
|
||||
.OfType<SpeckleObjectWrapperGoo>()
|
||||
.Select(goo => goo.Value.Properties)
|
||||
.Where(goo => goo is SpecklePropertyGroupGoo)
|
||||
.Select(goo =>
|
||||
goo switch
|
||||
{
|
||||
SpecklePropertyGroupGoo geometryGoo => geometryGoo,
|
||||
_ => throw new InvalidOperationException("Unexpected goo type")
|
||||
}
|
||||
)
|
||||
.ToList();
|
||||
|
||||
#if RHINO8_OR_GREATER
|
||||
// support model objects direct piping also
|
||||
if (objectPropertyGroups.Count != VolatileData.DataCount)
|
||||
{
|
||||
var modelObjects = VolatileData
|
||||
.AllData(true)
|
||||
.OfType<ModelObject>()
|
||||
.Select(mo => new SpeckleObjectWrapperGoo(mo).Value.Properties)
|
||||
.ToList();
|
||||
objectPropertyGroups.AddRange(modelObjects);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (objectPropertyGroups.Count == 0)
|
||||
if (propertyGroups.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var paths = GetPropertyPaths(objectPropertyGroups);
|
||||
var paths = GetPropertyPaths(propertyGroups);
|
||||
m_data.Clear();
|
||||
m_data.AppendRange(paths.Select(s => new GH_String(s)));
|
||||
}
|
||||
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using Grasshopper.Kernel;
|
||||
using Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
using Speckle.Connectors.GrasshopperShared.Properties;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.Objects;
|
||||
|
||||
[Guid("116F08A5-BAA7-45B3-B6C8-469E452C9AC7")]
|
||||
public class QueryProperties : GH_Component
|
||||
{
|
||||
public override Guid ComponentGuid => GetType().GUID;
|
||||
|
||||
protected override Bitmap Icon => Resources.speckle_properties_query;
|
||||
public override GH_Exposure Exposure => GH_Exposure.quarternary;
|
||||
|
||||
public QueryProperties()
|
||||
: base(
|
||||
"Query Properties",
|
||||
"qP",
|
||||
"Retrieves the values of the Properties at the specified keys",
|
||||
ComponentCategories.PRIMARY_RIBBON,
|
||||
ComponentCategories.OBJECTS
|
||||
) { }
|
||||
|
||||
protected override void RegisterInputParams(GH_InputParamManager pManager)
|
||||
{
|
||||
pManager.AddParameter(
|
||||
new SpecklePropertyGroupParam(),
|
||||
"Properties",
|
||||
"P",
|
||||
"Speckle Properties",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
pManager.AddTextParameter("Keys", "K", "Property keys to filter by", GH_ParamAccess.list);
|
||||
}
|
||||
|
||||
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
|
||||
{
|
||||
pManager.AddGenericParameter("Values", "V", "The values of the specified keys", GH_ParamAccess.list);
|
||||
}
|
||||
|
||||
protected override void SolveInstance(IGH_DataAccess da)
|
||||
{
|
||||
SpecklePropertyGroupGoo? properties = null;
|
||||
if (!da.GetData(0, ref properties))
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"Input a Speckle Properties item");
|
||||
return;
|
||||
}
|
||||
|
||||
List<string> keys = new();
|
||||
if (!da.GetDataList(1, keys))
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"Input a key");
|
||||
return;
|
||||
}
|
||||
|
||||
if (properties == null || properties.Value.Count == 0 || keys.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<object?> values = new();
|
||||
foreach (string key in keys)
|
||||
{
|
||||
ISpecklePropertyGoo? value = GetValueByPath(properties, key);
|
||||
values.Add(value);
|
||||
}
|
||||
|
||||
da.SetDataList(0, values);
|
||||
}
|
||||
|
||||
public static ISpecklePropertyGoo? GetValueByPath(SpecklePropertyGroupGoo data, string path)
|
||||
{
|
||||
string[] keys = path.Split('.');
|
||||
ISpecklePropertyGoo? current = data;
|
||||
|
||||
foreach (var key in keys)
|
||||
{
|
||||
if (current is SpecklePropertyGroupGoo dict)
|
||||
{
|
||||
if (dict.Value.TryGetValue(key, out ISpecklePropertyGoo next))
|
||||
{
|
||||
current = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return null; // Current is not a dictionary, path is invalid
|
||||
}
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
}
|
||||
+282
@@ -0,0 +1,282 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using Grasshopper.Kernel;
|
||||
using Grasshopper.Kernel.Parameters;
|
||||
using Grasshopper.Kernel.Types;
|
||||
using Rhino.DocObjects;
|
||||
using Speckle.Connectors.GrasshopperShared.HostApp;
|
||||
using Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
using Speckle.Connectors.GrasshopperShared.Properties;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.Objects;
|
||||
|
||||
/// <summary>
|
||||
/// Given a collection, this component will output the objects in the collection that satisfy the input parameters
|
||||
/// </summary>
|
||||
[Guid("77CAEE94-F0B9-4611-897C-71F2A22BA311")]
|
||||
public class QuerySpeckleObjects : GH_Component, IGH_VariableParameterComponent
|
||||
{
|
||||
public override Guid ComponentGuid => GetType().GUID;
|
||||
protected override Bitmap Icon => Resources.speckle_objects_query;
|
||||
public override GH_Exposure Exposure => GH_Exposure.primary;
|
||||
|
||||
public QuerySpeckleObjects()
|
||||
: base(
|
||||
"Query Speckle Objects",
|
||||
"qO",
|
||||
"Retrieves the Speckle objects inside a Speckle collection satisfying the input conditions",
|
||||
ComponentCategories.PRIMARY_RIBBON,
|
||||
ComponentCategories.OBJECTS
|
||||
) { }
|
||||
|
||||
protected override void RegisterInputParams(GH_InputParamManager pManager)
|
||||
{
|
||||
pManager.AddParameter(
|
||||
new SpeckleCollectionParam(),
|
||||
"Collection",
|
||||
"C",
|
||||
"Collection to retrieve objects from",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
|
||||
pManager.AddTextParameter(
|
||||
"Path",
|
||||
"C",
|
||||
"Get the Speckle objects in the subcollection indicated by this path",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
|
||||
Params.Input[1].Optional = true;
|
||||
}
|
||||
|
||||
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
|
||||
{
|
||||
pManager.AddGenericParameter(
|
||||
"Objects",
|
||||
"O",
|
||||
"The objects in the input collection that match the queries",
|
||||
GH_ParamAccess.tree
|
||||
);
|
||||
}
|
||||
|
||||
// The list of filters that can be added by the user as a dynamic output
|
||||
// The order of this array will determine the order of outputs in this component
|
||||
private List<ObjectType> Filters =>
|
||||
[
|
||||
ObjectType.InstanceReference,
|
||||
ObjectType.Point,
|
||||
ObjectType.PointSet,
|
||||
ObjectType.Curve,
|
||||
ObjectType.Extrusion,
|
||||
ObjectType.Brep,
|
||||
ObjectType.SubD,
|
||||
ObjectType.Mesh,
|
||||
ObjectType.Hatch
|
||||
];
|
||||
|
||||
private string GetFilterNickName(ObjectType type) =>
|
||||
type switch
|
||||
{
|
||||
ObjectType.InstanceReference => "Block Instances",
|
||||
ObjectType.Point => "Points",
|
||||
ObjectType.PointSet => "Point Clouds",
|
||||
ObjectType.Curve => "Curves",
|
||||
ObjectType.Extrusion => "Extrusions",
|
||||
ObjectType.Brep => "Breps",
|
||||
ObjectType.SubD => "SubDs",
|
||||
ObjectType.Mesh => "Meshes",
|
||||
ObjectType.Hatch => "Hatches",
|
||||
_ => ""
|
||||
};
|
||||
|
||||
private List<int>? _outputFilterIndices;
|
||||
|
||||
// Caches the list of all objects by geometrybase type
|
||||
private readonly Dictionary<ObjectType, List<SpeckleGeometryWrapper>> _filterDict = new();
|
||||
|
||||
protected override void SolveInstance(IGH_DataAccess dataAccess)
|
||||
{
|
||||
SpeckleCollectionWrapperGoo collectionWrapperGoo = new();
|
||||
dataAccess.GetData(0, ref collectionWrapperGoo);
|
||||
|
||||
if (collectionWrapperGoo.Value == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string path = "";
|
||||
dataAccess.GetData(1, ref path);
|
||||
|
||||
// filter by collection path
|
||||
// Note: the collection paths selector will omit the target collection from the path of nested collections.
|
||||
// the discard ("_objects") will be used to indicate objects found directly in the target collection.
|
||||
List<SpeckleWrapper> filteredObjects;
|
||||
SpeckleCollectionWrapper? targetCollectionWrapper = null;
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
targetCollectionWrapper =
|
||||
path == "_objects" ? collectionWrapperGoo.Value : FindCollectionAtPath(collectionWrapperGoo.Value, path);
|
||||
if (targetCollectionWrapper is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
filteredObjects = targetCollectionWrapper.GetAtomicObjects(true).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
filteredObjects = collectionWrapperGoo.Value.GetAtomicObjects(true).ToList();
|
||||
}
|
||||
|
||||
// sort geometry objects by filters
|
||||
var geometryObjects = filteredObjects.OfType<SpeckleGeometryWrapper>().ToList();
|
||||
if (_filterDict.Count == 0)
|
||||
{
|
||||
SortObjectsByGeometryBaseType(geometryObjects);
|
||||
}
|
||||
|
||||
// Set output objects
|
||||
for (int i = 0; i < Params.Output.Count; i++)
|
||||
{
|
||||
List<SpeckleWrapper> outputValues =
|
||||
i == 0 ? filteredObjects : _filterDict[Filters[i - 1]].Select(o => (SpeckleWrapper)o).ToList();
|
||||
List<IGH_Goo> outputGoos = outputValues.Select(o => o.CreateGoo()).ToList();
|
||||
if (targetCollectionWrapper?.Topology is string topology && !string.IsNullOrEmpty(topology))
|
||||
{
|
||||
var tree = GrasshopperHelpers.CreateDataTreeFromTopologyAndItems(topology, outputGoos);
|
||||
dataAccess.SetDataTree(i, tree);
|
||||
}
|
||||
else
|
||||
{
|
||||
dataAccess.SetDataList(i, outputGoos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the input objects by the FilterType enums, based on the type of their geometryBase
|
||||
private void SortObjectsByGeometryBaseType(List<SpeckleGeometryWrapper> objs)
|
||||
{
|
||||
if (_filterDict.Count > 0)
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"Stored input objects are in an invalid state.");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (ObjectType filter in Filters)
|
||||
{
|
||||
_filterDict.Add(filter, new());
|
||||
}
|
||||
|
||||
foreach (var wrapper in objs)
|
||||
{
|
||||
if (
|
||||
wrapper.GeometryBase?.ObjectType is ObjectType objType
|
||||
&& _filterDict.TryGetValue(objType, out List<SpeckleGeometryWrapper>? value)
|
||||
)
|
||||
{
|
||||
value.Add(wrapper);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private SpeckleCollectionWrapper? FindCollectionAtPath(SpeckleCollectionWrapper root, string unifiedPath)
|
||||
{
|
||||
// POC: SpeckleCollections now have a full list<string> path prop on them always. Is this easier to use?
|
||||
List<string> paths = unifiedPath.Split([Constants.LAYER_PATH_DELIMITER], StringSplitOptions.None).ToList();
|
||||
SpeckleCollectionWrapper currentCollectionWrapper = root;
|
||||
while (paths.Count != 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
currentCollectionWrapper = currentCollectionWrapper
|
||||
.Elements.OfType<SpeckleCollectionWrapper>()
|
||||
.First(wrapper => wrapper.Name == paths.First());
|
||||
|
||||
paths.RemoveAt(0);
|
||||
if (paths.Count == 0)
|
||||
{
|
||||
return currentCollectionWrapper;
|
||||
}
|
||||
}
|
||||
catch (InvalidOperationException) // when no wrappers match the current path
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, $"[{unifiedPath}] is an invalid path for this collection");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool CanInsertParameter(GH_ParameterSide side, int index)
|
||||
{
|
||||
if (side == GH_ParameterSide.Input || index == 0 || index > Filters.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// repopulate current output params if needed
|
||||
if (_outputFilterIndices is null)
|
||||
{
|
||||
_outputFilterIndices = new();
|
||||
foreach (var output in Params.Output)
|
||||
{
|
||||
if (Enum.TryParse(output.Name, out ObjectType filter))
|
||||
{
|
||||
_outputFilterIndices.Add(Filters.IndexOf(filter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int? previousFilterIndex = index == 1 ? null : _outputFilterIndices[index - 2];
|
||||
int? nextFilterIndex = index > _outputFilterIndices.Count ? null : _outputFilterIndices[index - 1];
|
||||
return (previousFilterIndex is null && nextFilterIndex != 0)
|
||||
|| (nextFilterIndex is null && previousFilterIndex != Filters.Count - 1)
|
||||
|| nextFilterIndex - previousFilterIndex > 1;
|
||||
}
|
||||
|
||||
public bool CanRemoveParameter(GH_ParameterSide side, int index) => side == GH_ParameterSide.Output && index != 0;
|
||||
|
||||
public IGH_Param CreateParameter(GH_ParameterSide side, int index)
|
||||
{
|
||||
// get the next filter name based on what the previous output filter at this index is
|
||||
// index should account for the first output which is always all objects
|
||||
int? previousFilterIndex = _outputFilterIndices is null || index == 1 ? null : _outputFilterIndices[index - 2];
|
||||
_outputFilterIndices = null;
|
||||
|
||||
ObjectType filter = previousFilterIndex is null ? Filters.First() : Filters[(int)previousFilterIndex + 1];
|
||||
return new Param_GenericObject
|
||||
{
|
||||
Name = filter.ToString(),
|
||||
NickName = GetFilterNickName(filter),
|
||||
MutableNickName = false,
|
||||
Optional = true
|
||||
};
|
||||
}
|
||||
|
||||
public bool DestroyParameter(GH_ParameterSide side, int index)
|
||||
{
|
||||
_outputFilterIndices = null;
|
||||
return side == GH_ParameterSide.Output;
|
||||
}
|
||||
|
||||
public void VariableParameterMaintenance() { }
|
||||
|
||||
public override void AddedToDocument(GH_Document document)
|
||||
{
|
||||
base.AddedToDocument(document);
|
||||
Params.ParameterSourcesChanged += OnParameterSourceChanged;
|
||||
}
|
||||
|
||||
public override void RemovedFromDocument(GH_Document document)
|
||||
{
|
||||
Params.ParameterSourcesChanged -= OnParameterSourceChanged;
|
||||
base.RemovedFromDocument(document);
|
||||
}
|
||||
|
||||
private void OnParameterSourceChanged(object sender, GH_ParamServerEventArgs args)
|
||||
{
|
||||
// an empty filter dict will trigger the SortObjectsByGeometryBaseType method.
|
||||
// we only want to re-sort objects if an input has changed, not on every trigger of solve instance.
|
||||
_filterDict.Clear();
|
||||
}
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
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;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.Objects;
|
||||
|
||||
[Guid("8D2E3F4A-1B5C-4E7F-9A8B-3C6D9E2F1A4B")]
|
||||
public class SpeckleBlockDefinitionPassthrough : GH_Component
|
||||
{
|
||||
public SpeckleBlockDefinitionPassthrough()
|
||||
: base(
|
||||
"Speckle Block Definition",
|
||||
"SBD",
|
||||
"Create or modify a Speckle Block Definition",
|
||||
ComponentCategories.PRIMARY_RIBBON,
|
||||
ComponentCategories.OBJECTS
|
||||
) { }
|
||||
|
||||
public override Guid ComponentGuid => GetType().GUID;
|
||||
protected override Bitmap Icon => Resources.speckle_objects_block_def;
|
||||
public override GH_Exposure Exposure => GH_Exposure.tertiary;
|
||||
|
||||
protected override void RegisterInputParams(GH_InputParamManager pManager)
|
||||
{
|
||||
pManager.AddParameter(
|
||||
new SpeckleBlockDefinitionWrapperParam(),
|
||||
"Block Definition",
|
||||
"BD",
|
||||
"Input Block Definition. Speckle definitions and Model definitions are accepted.",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
Params.Input[0].Optional = true;
|
||||
|
||||
pManager.AddGenericParameter(
|
||||
"Geometry",
|
||||
"G",
|
||||
"Geometry to include in the Block Definition. Speckle geometry and instances or Model objects and instances are accepted.",
|
||||
GH_ParamAccess.list
|
||||
);
|
||||
Params.Input[1].Optional = true;
|
||||
|
||||
pManager.AddTextParameter("Name", "N", "Name of the Speckle Definition", GH_ParamAccess.item);
|
||||
Params.Input[2].Optional = true;
|
||||
}
|
||||
|
||||
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
|
||||
{
|
||||
pManager.AddParameter(
|
||||
new SpeckleBlockDefinitionWrapperParam(),
|
||||
"Block Definition",
|
||||
"BD",
|
||||
"Speckle Block Definition",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
|
||||
pManager.AddGenericParameter("Geometry", "G", "Geometry contained in the Block Definition", GH_ParamAccess.list);
|
||||
|
||||
pManager.AddTextParameter("Name", "N", "Name of the Block Definition", GH_ParamAccess.item);
|
||||
}
|
||||
|
||||
protected override void SolveInstance(IGH_DataAccess da)
|
||||
{
|
||||
SpeckleBlockDefinitionWrapperGoo? inputDefinition = null;
|
||||
da.GetData(0, ref inputDefinition);
|
||||
|
||||
List<IGH_Goo> inputObjects = new();
|
||||
da.GetDataList(1, inputObjects);
|
||||
|
||||
if (inputDefinition == null && inputObjects.Count == 0)
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"Pass in a Definition or Geometry.");
|
||||
return;
|
||||
}
|
||||
|
||||
string? inputName = null;
|
||||
da.GetData(2, ref inputName);
|
||||
|
||||
if (inputDefinition == null && string.IsNullOrWhiteSpace(inputName))
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"Pass in a Name for the definition.");
|
||||
return;
|
||||
}
|
||||
|
||||
// process the definition
|
||||
// deep copy so we don't mutate the object
|
||||
SpeckleBlockDefinitionWrapperGoo result = inputDefinition != null ? new(inputDefinition.Value.DeepCopy()) : new();
|
||||
|
||||
// process geometry
|
||||
if (inputObjects.Count > 0)
|
||||
{
|
||||
List<SpeckleGeometryWrapper> processedObjects = new();
|
||||
foreach (IGH_Goo goo in inputObjects)
|
||||
{
|
||||
if (goo.ToSpeckleGeometryWrapper() is SpeckleGeometryWrapper gooWrapper)
|
||||
{
|
||||
processedObjects.Add(gooWrapper);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, $"Unsupported type {goo.TypeName} not added to definition");
|
||||
}
|
||||
}
|
||||
|
||||
result.Value.Objects = processedObjects;
|
||||
result.Value.InstanceDefinitionProxy.objects = processedObjects.Select(o => o.ApplicationId!).ToList(); // TODO: this could also be set at the same time as `Objects` on the definition wrapper.
|
||||
}
|
||||
|
||||
// process name
|
||||
if (inputName != null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(inputName))
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, $"Pass in a non-empty name for the definition.");
|
||||
return;
|
||||
}
|
||||
|
||||
result.Value.Name = inputName;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
+227
@@ -0,0 +1,227 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using Grasshopper.Kernel;
|
||||
using Grasshopper.Kernel.Types;
|
||||
using Rhino.Geometry;
|
||||
using Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
using Speckle.Connectors.GrasshopperShared.Properties;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.Objects;
|
||||
|
||||
[Guid("2F8A9B1C-3D4E-5F6A-7B8C-9D0E1F2A3B4C")]
|
||||
public class SpeckleBlockInstancePassthrough : GH_Component
|
||||
{
|
||||
public SpeckleBlockInstancePassthrough()
|
||||
: base(
|
||||
"Speckle Block Instance",
|
||||
"SBI",
|
||||
"Create or modify a Speckle Block Instance",
|
||||
ComponentCategories.PRIMARY_RIBBON,
|
||||
ComponentCategories.OBJECTS
|
||||
) { }
|
||||
|
||||
public override Guid ComponentGuid => GetType().GUID;
|
||||
protected override Bitmap Icon => Resources.speckle_objects_block_inst;
|
||||
public override GH_Exposure Exposure => GH_Exposure.tertiary;
|
||||
|
||||
protected override void RegisterInputParams(GH_InputParamManager pManager)
|
||||
{
|
||||
int instanceIndex = pManager.AddParameter(
|
||||
new SpeckleBlockInstanceParam(),
|
||||
"Block Instance",
|
||||
"BI",
|
||||
"Input Block Instance. Speckle instances and Grasshopper instances are accepted.",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
Params.Input[instanceIndex].Optional = true;
|
||||
|
||||
int definitionIndex = pManager.AddParameter(
|
||||
new SpeckleBlockDefinitionWrapperParam(),
|
||||
"Definition",
|
||||
"D",
|
||||
"Block Instance Definition. Speckle definitions and Grasshopper definitions are accepted.",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
Params.Input[definitionIndex].Optional = true;
|
||||
|
||||
int transformIndex = pManager.AddGenericParameter(
|
||||
"Transform",
|
||||
"T",
|
||||
"Transform of the Speckle instance. Transforms and Planes are accepted.",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
Params.Input[transformIndex].Optional = true;
|
||||
|
||||
int nameIndex = pManager.AddTextParameter("Name", "N", "Name of the Speckle Instance", GH_ParamAccess.item);
|
||||
Params.Input[nameIndex].Optional = true;
|
||||
|
||||
int propIndex = pManager.AddParameter(
|
||||
new SpecklePropertyGroupParam(),
|
||||
"Properties",
|
||||
"P",
|
||||
"The properties of the Speckle Instance. Speckle Properties and User Content are accepted.",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
Params.Input[propIndex].Optional = true;
|
||||
|
||||
int colorIndex = pManager.AddColourParameter(
|
||||
"Color",
|
||||
"c",
|
||||
"The color of the Speckle Instance",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
Params.Input[colorIndex].Optional = true;
|
||||
|
||||
int matIndex = pManager.AddParameter(
|
||||
new SpeckleMaterialParam(),
|
||||
"Material",
|
||||
"m",
|
||||
"The material of the Speckle Instance. Display Materials, Model Materials, and Speckle Materials are accepted.",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
Params.Input[matIndex].Optional = true;
|
||||
}
|
||||
|
||||
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
|
||||
{
|
||||
pManager.AddParameter(
|
||||
new SpeckleBlockInstanceParam(),
|
||||
"Block Instance",
|
||||
"BI",
|
||||
"Speckle Block Instance",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
|
||||
pManager.AddParameter(
|
||||
new SpeckleBlockDefinitionWrapperParam(),
|
||||
"Definition",
|
||||
"D",
|
||||
"Block Definition of the instance",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
|
||||
pManager.AddGenericParameter("Transform", "T", "Transform of the Block Instance", GH_ParamAccess.item);
|
||||
|
||||
pManager.AddTextParameter("Name", "N", "Name of the Block Instance", GH_ParamAccess.item);
|
||||
|
||||
pManager.AddParameter(
|
||||
new SpecklePropertyGroupParam(),
|
||||
"Properties",
|
||||
"P",
|
||||
"Properties of the Block Instance",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
|
||||
pManager.AddColourParameter("Color", "c", "The color of the Speckle Object", GH_ParamAccess.item);
|
||||
|
||||
pManager.AddParameter(
|
||||
new SpeckleMaterialParam(),
|
||||
"Material",
|
||||
"M",
|
||||
"The material of the Block Instance.",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
}
|
||||
|
||||
protected override void SolveInstance(IGH_DataAccess da)
|
||||
{
|
||||
SpeckleBlockInstanceWrapperGoo? inputInstance = null;
|
||||
da.GetData(0, ref inputInstance);
|
||||
|
||||
SpeckleBlockDefinitionWrapperGoo? inputDefinition = null;
|
||||
da.GetData(1, ref inputDefinition);
|
||||
|
||||
if (inputInstance == null && inputDefinition == null)
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"Pass in an Instance or Definition.");
|
||||
return;
|
||||
}
|
||||
|
||||
IGH_Goo? inputTransform = null;
|
||||
da.GetData(2, ref inputTransform);
|
||||
|
||||
string? inputName = null;
|
||||
da.GetData(3, ref inputName);
|
||||
|
||||
SpecklePropertyGroupGoo? inputProperties = null;
|
||||
da.GetData(4, ref inputProperties);
|
||||
|
||||
Color? inputColor = null;
|
||||
da.GetData(5, ref inputColor);
|
||||
|
||||
SpeckleMaterialWrapperGoo? inputMaterial = null;
|
||||
da.GetData(6, ref inputMaterial);
|
||||
|
||||
// process the instance
|
||||
// deep copy so we don't mutate the incoming object
|
||||
SpeckleBlockInstanceWrapperGoo result =
|
||||
inputInstance != null ? new((SpeckleBlockInstanceWrapper)inputInstance.Value.DeepCopy()) : new();
|
||||
|
||||
// process definition
|
||||
if (inputDefinition != null)
|
||||
{
|
||||
result.Value.Definition = inputDefinition.Value;
|
||||
}
|
||||
|
||||
// Process transform
|
||||
if (inputTransform != null)
|
||||
{
|
||||
Transform? extractedTransform = ExtractTransform(inputTransform);
|
||||
if (extractedTransform.HasValue)
|
||||
{
|
||||
result.Value.Transform = extractedTransform.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
AddRuntimeMessage(
|
||||
GH_RuntimeMessageLevel.Warning,
|
||||
"Transform input is not valid. Only Transforms and Planes are accepted."
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Process name
|
||||
if (inputName != null)
|
||||
{
|
||||
result.Value.Name = inputName;
|
||||
}
|
||||
|
||||
// Process properties
|
||||
if (inputProperties != null)
|
||||
{
|
||||
result.Value.Properties = inputProperties;
|
||||
}
|
||||
|
||||
// process color (no mutation)
|
||||
if (inputColor != null)
|
||||
{
|
||||
result.Value.Color = inputColor;
|
||||
}
|
||||
|
||||
// process material (no mutation)
|
||||
if (inputMaterial != null)
|
||||
{
|
||||
result.Value.Material = inputMaterial.Value;
|
||||
}
|
||||
|
||||
// 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);
|
||||
da.SetData(1, result.Value.Definition);
|
||||
da.SetData(2, new GH_Transform(result.Value.Transform));
|
||||
da.SetData(3, result.Value.Name);
|
||||
da.SetData(4, result.Value.Properties);
|
||||
da.SetData(5, result.Value.Color);
|
||||
da.SetData(6, result.Value.Material);
|
||||
}
|
||||
|
||||
private Transform? ExtractTransform(IGH_Goo input) =>
|
||||
input switch
|
||||
{
|
||||
GH_Transform ghTransform => ghTransform.Value,
|
||||
GH_Plane ghPlane => Transform.PlaneToPlane(Plane.WorldXY, ghPlane.Value),
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
+176
@@ -0,0 +1,176 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using Grasshopper.Kernel;
|
||||
using Speckle.Connectors.GrasshopperShared.HostApp;
|
||||
using Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
using Speckle.Connectors.GrasshopperShared.Properties;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.Objects;
|
||||
|
||||
[Guid("5CE8AA40-7706-4893-853D-4C77604548FA")]
|
||||
public class SpeckleDataObjectPassthrough : GH_Component
|
||||
{
|
||||
public SpeckleDataObjectPassthrough()
|
||||
: base(
|
||||
"Speckle Data Object",
|
||||
"SDO",
|
||||
"Create or modify a Speckle Data Object",
|
||||
ComponentCategories.PRIMARY_RIBBON,
|
||||
ComponentCategories.OBJECTS
|
||||
) { }
|
||||
|
||||
public override Guid ComponentGuid => GetType().GUID;
|
||||
protected override Bitmap Icon => Resources.speckle_objects_dataobject;
|
||||
public override GH_Exposure Exposure => GH_Exposure.secondary;
|
||||
|
||||
protected override void RegisterInputParams(GH_InputParamManager pManager)
|
||||
{
|
||||
int objIndex = pManager.AddParameter(
|
||||
new SpeckleDataObjectParam(),
|
||||
"Speckle Data Object",
|
||||
"SDO",
|
||||
"Input Speckle DataObject. Model Objects are also accepted.",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
Params.Input[objIndex].Optional = true;
|
||||
|
||||
int geoIndex = pManager.AddParameter(
|
||||
new SpeckleGeometryWrapperParam(),
|
||||
"Geometries",
|
||||
"G",
|
||||
"Geometries of the Speckle Data Object. Speckle Geometry and Grasshopper geometry are accepted.",
|
||||
GH_ParamAccess.list
|
||||
);
|
||||
Params.Input[geoIndex].Optional = true;
|
||||
|
||||
int nameIndex = pManager.AddTextParameter("Name", "N", "Name of the Speckle Data Object", GH_ParamAccess.item);
|
||||
Params.Input[nameIndex].Optional = true;
|
||||
|
||||
int propIndex = pManager.AddParameter(
|
||||
new SpecklePropertyGroupParam(),
|
||||
"Properties",
|
||||
"P",
|
||||
"The properties of the Speckle Data Object. Speckle Properties and User Content are accepted.",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
Params.Input[propIndex].Optional = true;
|
||||
}
|
||||
|
||||
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
|
||||
{
|
||||
pManager.AddParameter(
|
||||
new SpeckleDataObjectParam(),
|
||||
"Speckle Data Object",
|
||||
"SDO",
|
||||
"Speckle Data Object",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
|
||||
pManager.AddParameter(
|
||||
new SpeckleGeometryWrapperParam(),
|
||||
"Geometries",
|
||||
"G",
|
||||
"Geometries of the Speckle Data Object.",
|
||||
GH_ParamAccess.list
|
||||
);
|
||||
|
||||
pManager.AddTextParameter("Name", "N", "Name of the Speckle Data Object", GH_ParamAccess.item);
|
||||
|
||||
pManager.AddParameter(
|
||||
new SpecklePropertyGroupParam(),
|
||||
"Properties",
|
||||
"P",
|
||||
"The properties of the Speckle Data Object",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
|
||||
pManager.AddTextParameter(
|
||||
"Path",
|
||||
"p",
|
||||
$"The Collection Path of the Speckle Geometry, delimited with `{Constants.LAYER_PATH_DELIMITER}`",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
}
|
||||
|
||||
protected override void SolveInstance(IGH_DataAccess da)
|
||||
{
|
||||
// process the object
|
||||
// deep copy so we don't mutate the object
|
||||
SpeckleDataObjectWrapperGoo inputObject = new();
|
||||
SpeckleDataObjectWrapper? result = null;
|
||||
if (da.GetData(0, ref inputObject))
|
||||
{
|
||||
result = inputObject.Value.DeepCopy();
|
||||
}
|
||||
|
||||
List<SpeckleGeometryWrapperGoo> inputGeometry = new();
|
||||
if (!da.GetDataList(1, inputGeometry) && result == null)
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"Pass in a Speckle DataObject or Geometries.");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var inputGeo in inputGeometry)
|
||||
{
|
||||
if (inputGeo.Value is SpeckleBlockInstanceWrapper)
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, $"DataObjects cannot contain Block Instances.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
string? inputName = null;
|
||||
da.GetData(2, ref inputName);
|
||||
|
||||
SpecklePropertyGroupGoo? inputProperties = null;
|
||||
da.GetData(3, ref inputProperties);
|
||||
|
||||
// process geometry
|
||||
if (result == null)
|
||||
{
|
||||
result = new SpeckleDataObjectWrapperGoo().Value;
|
||||
}
|
||||
|
||||
if (inputGeometry.Count > 0)
|
||||
{
|
||||
result.Geometries.Clear();
|
||||
foreach (var inputGeo in inputGeometry)
|
||||
{
|
||||
// deep copy so we don't mutate the input geo which may be speckle geometry
|
||||
SpeckleGeometryWrapper mutatingGeo = inputGeo.Value.DeepCopy();
|
||||
|
||||
// assign fields before adding, otherwise they will be out of sync with wrapper
|
||||
mutatingGeo.Base[Constants.NAME_PROP] = result.Name;
|
||||
mutatingGeo.Properties = result.Properties;
|
||||
mutatingGeo.Parent = result.Parent;
|
||||
mutatingGeo.Path = result.Path;
|
||||
|
||||
result.Geometries.Add(mutatingGeo);
|
||||
}
|
||||
}
|
||||
|
||||
// process name
|
||||
if (inputName != null)
|
||||
{
|
||||
result!.Name = inputName;
|
||||
}
|
||||
|
||||
// process properties
|
||||
if (inputProperties != null)
|
||||
{
|
||||
result!.Properties = inputProperties;
|
||||
}
|
||||
|
||||
// get the path
|
||||
string path =
|
||||
result!.Path.Count > 1
|
||||
? string.Join(Constants.LAYER_PATH_DELIMITER, result!.Path)
|
||||
: result!.Path.FirstOrDefault();
|
||||
|
||||
// set all the data
|
||||
da.SetData(0, result.CreateGoo());
|
||||
da.SetDataList(1, result.Geometries);
|
||||
da.SetData(2, result.Name);
|
||||
da.SetData(3, result.Properties);
|
||||
da.SetData(4, path);
|
||||
}
|
||||
}
|
||||
+253
@@ -0,0 +1,253 @@
|
||||
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;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.Objects;
|
||||
|
||||
[Guid("F9418610-ACAE-4417-B010-19EBEA6A121F")]
|
||||
public class SpeckleGeometryPassthrough : GH_Component
|
||||
{
|
||||
public SpeckleGeometryPassthrough()
|
||||
: base(
|
||||
"Speckle Geometry",
|
||||
"SG",
|
||||
"Create or modify a Speckle Geometry",
|
||||
ComponentCategories.PRIMARY_RIBBON,
|
||||
ComponentCategories.OBJECTS
|
||||
) { }
|
||||
|
||||
public override Guid ComponentGuid => GetType().GUID;
|
||||
protected override Bitmap Icon => Resources.speckle_objects_geometry;
|
||||
public override GH_Exposure Exposure => GH_Exposure.secondary;
|
||||
|
||||
protected override void RegisterInputParams(GH_InputParamManager pManager)
|
||||
{
|
||||
int objIndex = pManager.AddGenericParameter(
|
||||
"Speckle Geometry",
|
||||
"SG",
|
||||
"Input Speckle Geometry. Model Objects are also accepted.",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
Params.Input[objIndex].Optional = true;
|
||||
|
||||
int geoIndex = pManager.AddGeometryParameter(
|
||||
"Geometry",
|
||||
"G",
|
||||
"Geometry of the Speckle Geometry.",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
Params.Input[geoIndex].Optional = true;
|
||||
|
||||
int nameIndex = pManager.AddTextParameter("Name", "N", "Name of the Speckle Geometry", GH_ParamAccess.item);
|
||||
Params.Input[nameIndex].Optional = true;
|
||||
|
||||
int propIndex = pManager.AddParameter(
|
||||
new SpecklePropertyGroupParam(),
|
||||
"Properties",
|
||||
"P",
|
||||
"The properties of the Speckle Geometry. Speckle Properties and User Content are accepted.",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
Params.Input[propIndex].Optional = true;
|
||||
|
||||
int colorIndex = pManager.AddColourParameter(
|
||||
"Color",
|
||||
"c",
|
||||
"The color of the Speckle Geometry",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
Params.Input[colorIndex].Optional = true;
|
||||
|
||||
int matIndex = pManager.AddParameter(
|
||||
new SpeckleMaterialParam(),
|
||||
"Material",
|
||||
"m",
|
||||
"The material of the Speckle Geometry. Display Materials, Model Materials, and Speckle Materials are accepted.",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
Params.Input[matIndex].Optional = true;
|
||||
|
||||
/* POC: disable for now as we are doing anything with this
|
||||
pManager.AddTextParameter(
|
||||
"Path",
|
||||
"p",
|
||||
"The Collection Path of the Speckle Object. Should be delimited with `:`",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
Params.Input[6].Optional = true;
|
||||
*/
|
||||
}
|
||||
|
||||
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
|
||||
{
|
||||
pManager.AddGenericParameter("Speckle Geometry", "SG", "Speckle Geometry", GH_ParamAccess.item);
|
||||
|
||||
pManager.AddGeometryParameter("Geometry", "G", "Geometry of the Speckle Geometry.", GH_ParamAccess.item);
|
||||
|
||||
pManager.AddTextParameter("Name", "N", "Name of the Speckle Geometry", GH_ParamAccess.item);
|
||||
|
||||
pManager.AddParameter(
|
||||
new SpecklePropertyGroupParam(),
|
||||
"Properties",
|
||||
"P",
|
||||
"The properties of the Speckle Geometry",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
|
||||
pManager.AddColourParameter("Color", "c", "The color of the Speckle Geometry", GH_ParamAccess.item);
|
||||
|
||||
pManager.AddParameter(
|
||||
new SpeckleMaterialParam(),
|
||||
"Material",
|
||||
"M",
|
||||
"The material of the Speckle Geometry.",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
|
||||
pManager.AddTextParameter(
|
||||
"Path",
|
||||
"p",
|
||||
$"The Collection Path of the Speckle Geometry, delimited with `{Constants.LAYER_PATH_DELIMITER}`",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
}
|
||||
|
||||
protected override void SolveInstance(IGH_DataAccess da)
|
||||
{
|
||||
// process the object
|
||||
// deep copy so we don't mutate the object
|
||||
IGH_Goo? inputObject = null;
|
||||
SpeckleGeometryWrapper? result = null;
|
||||
if (da.GetData(0, ref inputObject))
|
||||
{
|
||||
if (inputObject?.ToSpeckleGeometryWrapper() is SpeckleGeometryWrapper gooWrapper)
|
||||
{
|
||||
result = gooWrapper.DeepCopy();
|
||||
}
|
||||
else
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, $"Unsupported object type: {inputObject?.TypeName}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
IGH_GeometricGoo? inputGeometry = null;
|
||||
da.GetData(1, ref inputGeometry);
|
||||
|
||||
if (result == null && inputGeometry == null)
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"Pass in a Speckle Geometry or Geometry.");
|
||||
return;
|
||||
}
|
||||
|
||||
string? inputName = null;
|
||||
da.GetData(2, ref inputName);
|
||||
|
||||
SpecklePropertyGroupGoo? inputProperties = null;
|
||||
da.GetData(3, ref inputProperties);
|
||||
|
||||
Color? inputColor = null;
|
||||
da.GetData(4, ref inputColor);
|
||||
|
||||
SpeckleMaterialWrapperGoo? inputMaterial = null;
|
||||
da.GetData(5, ref inputMaterial);
|
||||
|
||||
// process geometry
|
||||
// deep copy so we don't mutate the input geo which may be speckle objects
|
||||
if (inputGeometry != null)
|
||||
{
|
||||
if (inputGeometry.ToSpeckleGeometryWrapper() is SpeckleGeometryWrapper geoWrapper)
|
||||
{
|
||||
SpeckleGeometryWrapper mutatingGeo = geoWrapper.DeepCopy();
|
||||
if (result is null)
|
||||
{
|
||||
result = mutatingGeo;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we need to switch to the actual object wrapper type of the incoming geo if this is a mutation on the object
|
||||
if (mutatingGeo is SpeckleBlockInstanceWrapper mutatingInstance && result is not SpeckleBlockInstanceWrapper)
|
||||
{
|
||||
MatchNonGeometryProps(mutatingInstance, result);
|
||||
result = mutatingInstance;
|
||||
}
|
||||
else if (mutatingGeo is not SpeckleBlockInstanceWrapper && result is SpeckleBlockInstanceWrapper)
|
||||
{
|
||||
MatchNonGeometryProps(mutatingGeo, result);
|
||||
result = mutatingGeo;
|
||||
}
|
||||
|
||||
mutatingGeo.Base[Constants.NAME_PROP] = result.Name; // assign these before assigning base since otherwise wrapper name and app will reset
|
||||
mutatingGeo.Base.applicationId = result.ApplicationId; // assign these before assigning base since otherwise wrapper name and app will reset
|
||||
result.Base = mutatingGeo.Base;
|
||||
result.GeometryBase = mutatingGeo.GeometryBase;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddRuntimeMessage(
|
||||
GH_RuntimeMessageLevel.Error,
|
||||
$"{inputGeometry.TypeName} is not a valid type for Speckle Geometry."
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// process name
|
||||
if (inputName != null)
|
||||
{
|
||||
result!.Name = inputName;
|
||||
}
|
||||
|
||||
// process properties
|
||||
if (inputProperties != null)
|
||||
{
|
||||
result!.Properties = inputProperties;
|
||||
}
|
||||
|
||||
// process color (no mutation)
|
||||
if (inputColor != null)
|
||||
{
|
||||
result!.Color = inputColor;
|
||||
}
|
||||
|
||||
// process material (no mutation)
|
||||
if (inputMaterial != null)
|
||||
{
|
||||
result!.Material = inputMaterial.Value;
|
||||
}
|
||||
|
||||
// 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 =
|
||||
result!.Path.Count > 1
|
||||
? string.Join(Constants.LAYER_PATH_DELIMITER, result!.Path)
|
||||
: result!.Path.FirstOrDefault();
|
||||
|
||||
// set all the data
|
||||
da.SetData(0, result.CreateGoo());
|
||||
da.SetData(1, result.GeometryBase);
|
||||
da.SetData(2, result.Name);
|
||||
da.SetData(3, result.Properties);
|
||||
da.SetData(4, result.Color);
|
||||
da.SetData(5, result.Material);
|
||||
da.SetData(6, path);
|
||||
}
|
||||
|
||||
// keeps the geometry and wrapped base the same while assigning all other props from the inut wrapper
|
||||
private void MatchNonGeometryProps(SpeckleGeometryWrapper wrapper, SpeckleGeometryWrapper wrapperToMatch)
|
||||
{
|
||||
wrapper.Name = wrapperToMatch.Name;
|
||||
wrapper.ApplicationId = wrapperToMatch.ApplicationId;
|
||||
wrapper.Properties = wrapperToMatch.Properties;
|
||||
wrapper.Parent = wrapperToMatch.Parent;
|
||||
wrapper.Path = wrapperToMatch.Path;
|
||||
wrapper.Color = wrapperToMatch.Color;
|
||||
wrapper.Material = wrapperToMatch.Material;
|
||||
}
|
||||
}
|
||||
+235
@@ -0,0 +1,235 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using GH_IO.Serialization;
|
||||
using Grasshopper.Kernel;
|
||||
using Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
using Speckle.Connectors.GrasshopperShared.Properties;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.Objects;
|
||||
|
||||
/// <summary>
|
||||
/// CreateSpeckleProperties passthrough component by key value pairs
|
||||
/// </summary>
|
||||
[Guid("FED2298C-0D2B-4868-94B5-B8D17F9385A5")]
|
||||
public class SpecklePropertiesPassthrough : GH_Component
|
||||
{
|
||||
public override Guid ComponentGuid => GetType().GUID;
|
||||
protected override Bitmap Icon => Resources.speckle_properties_properties;
|
||||
public override GH_Exposure Exposure => GH_Exposure.quarternary;
|
||||
|
||||
private enum PropertyMode
|
||||
{
|
||||
Merge, // this should be default mode
|
||||
Replace,
|
||||
Remove
|
||||
}
|
||||
|
||||
private PropertyMode _mode = PropertyMode.Merge;
|
||||
private PropertyMode Mode
|
||||
{
|
||||
get => _mode;
|
||||
set
|
||||
{
|
||||
if (_mode != value)
|
||||
{
|
||||
_mode = value;
|
||||
Message = Mode.ToString();
|
||||
ExpireSolution(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SpecklePropertiesPassthrough()
|
||||
: base(
|
||||
"Speckle Properties",
|
||||
"SP",
|
||||
"Creates or modifies a set of properties for Speckle objects by keyvalue",
|
||||
ComponentCategories.PRIMARY_RIBBON,
|
||||
ComponentCategories.OBJECTS
|
||||
)
|
||||
{
|
||||
Message = Mode.ToString();
|
||||
}
|
||||
|
||||
protected override void RegisterInputParams(GH_InputParamManager pManager)
|
||||
{
|
||||
pManager.AddParameter(new SpecklePropertyGroupParam(), "Properties", "P", "Input properties", GH_ParamAccess.item);
|
||||
Params.Input[0].Optional = true;
|
||||
|
||||
pManager.AddTextParameter("Keys", "k", "Keys of all properties", GH_ParamAccess.list);
|
||||
Params.Input[1].Optional = true;
|
||||
|
||||
pManager.AddGenericParameter(
|
||||
"Values",
|
||||
"v",
|
||||
"Values of all properties. Accepts text, number, bool, null, or other properties as inputs.",
|
||||
GH_ParamAccess.list
|
||||
);
|
||||
Params.Input[2].Optional = true;
|
||||
}
|
||||
|
||||
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
|
||||
{
|
||||
pManager.AddParameter(new SpecklePropertyGroupParam(), "Properties", "P", "Properties", GH_ParamAccess.item);
|
||||
pManager.AddTextParameter("Keys", "k", "Keys of all properties", GH_ParamAccess.list);
|
||||
pManager.AddGenericParameter("Values", "v", "Values of all properties", GH_ParamAccess.list);
|
||||
}
|
||||
|
||||
protected override void SolveInstance(IGH_DataAccess da)
|
||||
{
|
||||
SpecklePropertyGroupGoo? inputProperties = null;
|
||||
da.GetData(0, ref inputProperties);
|
||||
|
||||
List<string> inputKeys = new();
|
||||
bool hasKeys = da.GetDataList(1, inputKeys);
|
||||
|
||||
List<object?> inputValues = new();
|
||||
bool hasValues = da.GetDataList(2, inputValues);
|
||||
|
||||
// if no props or keyvalues were input, create empty props and return
|
||||
if (inputProperties == null && !hasKeys)
|
||||
{
|
||||
SpecklePropertyGroupGoo emptyProps = new();
|
||||
da.SetData(0, emptyProps);
|
||||
da.SetDataList(1, emptyProps.Value.Keys);
|
||||
da.SetDataList(2, emptyProps.Value.Values);
|
||||
return;
|
||||
}
|
||||
|
||||
// validate that keys and values are of valid length
|
||||
if ((Mode == PropertyMode.Merge || Mode == PropertyMode.Replace) && inputKeys.Count != inputValues.Count)
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"Keys and values are mismatched in length");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Mode == PropertyMode.Remove && (inputKeys.Count == 0 || inputValues.Count > 0))
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"Only input keys to remove");
|
||||
return;
|
||||
}
|
||||
|
||||
// process the properties
|
||||
Dictionary<string, ISpecklePropertyGoo> result =
|
||||
inputProperties is null || Mode == PropertyMode.Replace
|
||||
? new()
|
||||
: inputProperties.Value.ToDictionary(entry => entry.Key, entry => entry.Value);
|
||||
|
||||
// process keys and values
|
||||
if (hasKeys)
|
||||
{
|
||||
// check for duplicate keys
|
||||
var duplicates = inputKeys.GroupBy(x => x).Where(g => g.Count() > 1).Select(g => g.Key);
|
||||
if (duplicates.Any())
|
||||
{
|
||||
AddRuntimeMessage(
|
||||
GH_RuntimeMessageLevel.Error,
|
||||
$"Duplicate property keys found: {string.Join(", ", duplicates)}"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// set keyvalue pairs
|
||||
for (int i = 0; i < inputKeys.Count; i++)
|
||||
{
|
||||
string key = inputKeys[i];
|
||||
object? value = Mode == PropertyMode.Remove ? null : inputValues[i];
|
||||
ISpecklePropertyGoo? convertedValue = null;
|
||||
switch (value)
|
||||
{
|
||||
case SpecklePropertyGroupGoo propGoo:
|
||||
convertedValue = propGoo;
|
||||
break;
|
||||
case null:
|
||||
convertedValue = new SpecklePropertyGoo();
|
||||
break;
|
||||
default:
|
||||
SpecklePropertyGoo propValue = new();
|
||||
if (!propValue.CastFrom(value))
|
||||
{
|
||||
AddRuntimeMessage(
|
||||
GH_RuntimeMessageLevel.Error,
|
||||
$"Values contain an invalid data type. Only strings, numbers, booleans, planes, vectors, intervals, and other Speckle properties are supported."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
convertedValue = propValue;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (Mode)
|
||||
{
|
||||
case PropertyMode.Merge:
|
||||
if (result.ContainsKey(key))
|
||||
{
|
||||
result[key] = convertedValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Add(key, convertedValue);
|
||||
}
|
||||
break;
|
||||
case PropertyMode.Replace:
|
||||
result.Add(key, convertedValue);
|
||||
break;
|
||||
case PropertyMode.Remove:
|
||||
result.Remove(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var groupGoo = new SpecklePropertyGroupGoo(result);
|
||||
da.SetData(0, groupGoo);
|
||||
da.SetDataList(1, result.Keys);
|
||||
da.SetDataList(2, result.Values);
|
||||
}
|
||||
|
||||
public override void AppendAdditionalMenuItems(ToolStripDropDown menu)
|
||||
{
|
||||
base.AppendAdditionalMenuItems(menu);
|
||||
|
||||
Menu_AppendSeparator(menu); // modes section
|
||||
foreach (PropertyMode mode in Enum.GetValues(typeof(PropertyMode)))
|
||||
{
|
||||
var modeItem = Menu_AppendItem(menu, mode.ToString(), (_, _) => Mode = mode, true, mode == Mode);
|
||||
switch (mode)
|
||||
{
|
||||
case PropertyMode.Merge:
|
||||
modeItem.ToolTipText =
|
||||
"Input keyvalue pairs will be merged with existing properties. Any existing keys will be updated with new values.";
|
||||
break;
|
||||
case PropertyMode.Replace:
|
||||
modeItem.ToolTipText = "Existing properties will be cleared and replaced by input keyvalue pairs.";
|
||||
break;
|
||||
case PropertyMode.Remove:
|
||||
modeItem.ToolTipText = "Existing keyvalue pairs that match the input keys will be removed from properties.";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Menu_AppendSeparator(menu);
|
||||
}
|
||||
|
||||
public override bool Write(GH_IWriter writer)
|
||||
{
|
||||
var result = base.Write(writer);
|
||||
writer.SetString("Mode", Mode.ToString());
|
||||
return result;
|
||||
}
|
||||
|
||||
public override bool Read(GH_IReader reader)
|
||||
{
|
||||
var result = base.Read(reader);
|
||||
string mode = "";
|
||||
if (reader.TryGetString("Mode", ref mode))
|
||||
{
|
||||
if (Enum.TryParse(mode, out PropertyMode modeEnum))
|
||||
{
|
||||
Mode = modeEnum;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
using System.Diagnostics;
|
||||
using Grasshopper.Kernel;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Speckle.Connectors.GrasshopperShared.Properties;
|
||||
using Speckle.Connectors.GrasshopperShared.Registration;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Credentials;
|
||||
using Timer = System.Timers.Timer;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.Operations;
|
||||
|
||||
public class AccountManagerComponent : GH_Component, IDisposable
|
||||
{
|
||||
private bool _disposed;
|
||||
private bool _isAddingAccount;
|
||||
private Timer _timeoutTimer;
|
||||
private Timer? _accountCheckerTimer;
|
||||
|
||||
private List<Account>? Accounts { get; set; }
|
||||
private string? CustomUrlInput { get; set; }
|
||||
private readonly IAccountManager _accountManager;
|
||||
public override Guid ComponentGuid => new("c8ede281-acdf-49bf-8611-e9579be1bd41");
|
||||
|
||||
protected override Bitmap Icon => Resources.speckle_operations_account;
|
||||
|
||||
public override GH_Exposure Exposure => GH_Exposure.primary;
|
||||
|
||||
public GhContextMenuButton SignInButton { get; }
|
||||
|
||||
public AccountManagerComponent()
|
||||
: base(
|
||||
"Sign In",
|
||||
"SI",
|
||||
"Sign in to a Speckle Account",
|
||||
ComponentCategories.PRIMARY_RIBBON,
|
||||
ComponentCategories.OPERATIONS
|
||||
)
|
||||
{
|
||||
Attributes = new AccountManagerComponentAttributes(this);
|
||||
_accountManager = PriorityLoader.Container.GetRequiredService<IAccountManager>();
|
||||
Accounts = _accountManager.GetAccounts().ToList();
|
||||
|
||||
SignInButton = new GhContextMenuButton("Sign In", "Sign In", "Click to sign into Speckle account.", AuthFlow);
|
||||
}
|
||||
|
||||
private bool AuthFlow(ToolStripDropDown menu)
|
||||
{
|
||||
_isAddingAccount = true;
|
||||
ResumeAccountChecker();
|
||||
|
||||
string url = string.IsNullOrEmpty(CustomUrlInput)
|
||||
? "http://localhost:29364/auth/add-account"
|
||||
: $"http://localhost:29364/auth/add-account?serverUrl={new Uri(CustomUrlInput).GetLeftPart(UriPartial.Authority)}";
|
||||
|
||||
// Open the auth URL in the default browser
|
||||
try
|
||||
{
|
||||
Process.Start(new ProcessStartInfo { FileName = url, UseShellExecute = true });
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"Sign in failed: {ex.Message}");
|
||||
_isAddingAccount = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
_timeoutTimer = new Timer(30_000);
|
||||
_timeoutTimer.Elapsed += (s, e) =>
|
||||
{
|
||||
_timeoutTimer.Stop();
|
||||
if (_isAddingAccount)
|
||||
{
|
||||
_isAddingAccount = false;
|
||||
PauseAccountChecker();
|
||||
AddRuntimeMessage(
|
||||
GH_RuntimeMessageLevel.Warning,
|
||||
"Sign in timed out. This may have happened because you tried adding an existing account."
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
_timeoutTimer.Start();
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool CheckIfAccountAdded()
|
||||
{
|
||||
var previousAccountCount = Accounts?.Count ?? 0;
|
||||
Accounts = _accountManager.GetAccounts().ToList();
|
||||
return previousAccountCount < Accounts.Count;
|
||||
}
|
||||
|
||||
private void PauseAccountChecker()
|
||||
{
|
||||
_accountCheckerTimer?.Stop();
|
||||
_accountCheckerTimer?.Dispose();
|
||||
_accountCheckerTimer = null;
|
||||
}
|
||||
|
||||
private void ResumeAccountChecker()
|
||||
{
|
||||
_accountCheckerTimer?.Dispose();
|
||||
|
||||
_accountCheckerTimer = new Timer(1000); // check every 1 second
|
||||
_accountCheckerTimer.Elapsed += (s, e) =>
|
||||
{
|
||||
bool accountAdded = CheckIfAccountAdded();
|
||||
if (accountAdded)
|
||||
{
|
||||
_accountCheckerTimer.Stop();
|
||||
_isAddingAccount = false;
|
||||
// Optionally cancel timeout timer
|
||||
_timeoutTimer?.Stop();
|
||||
|
||||
OnPingDocument()
|
||||
?.ScheduleSolution(
|
||||
100,
|
||||
doc =>
|
||||
{
|
||||
ExpireSolution(true);
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Account added successfully!");
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
_accountCheckerTimer.Start();
|
||||
}
|
||||
|
||||
protected override void RegisterInputParams(GH_InputParamManager pManager)
|
||||
{
|
||||
var urlIndex = pManager.AddTextParameter(
|
||||
"Server Url",
|
||||
"Url",
|
||||
"Optional URL for signing into a self deployed Speckle server.",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
pManager[urlIndex].Optional = true;
|
||||
}
|
||||
|
||||
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
|
||||
{
|
||||
pManager.AddTextParameter($"Accounts", "Accounts", "List of available accounts", GH_ParamAccess.list);
|
||||
}
|
||||
|
||||
protected override void SolveInstance(IGH_DataAccess da)
|
||||
{
|
||||
string? urlInput = null;
|
||||
if (da.GetData(0, ref urlInput))
|
||||
{
|
||||
CustomUrlInput = urlInput;
|
||||
}
|
||||
|
||||
if (Accounts != null)
|
||||
{
|
||||
da.SetDataList(0, Accounts);
|
||||
}
|
||||
else
|
||||
{
|
||||
da.SetDataList(0, new List<Account>());
|
||||
}
|
||||
}
|
||||
|
||||
public override void ExpirePreview(bool redraw)
|
||||
{
|
||||
SignInButton.ExpirePreview(redraw);
|
||||
base.ExpirePreview(redraw);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_timeoutTimer?.Dispose();
|
||||
_accountManager.Dispose();
|
||||
_accountCheckerTimer?.Dispose();
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
using Grasshopper.GUI.Canvas;
|
||||
using Grasshopper.Kernel;
|
||||
using Grasshopper.Kernel.Attributes;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.Operations;
|
||||
|
||||
public class AccountManagerComponentAttributes : GH_ComponentAttributes
|
||||
{
|
||||
private readonly AccountManagerComponent _typedOwner;
|
||||
|
||||
public AccountManagerComponentAttributes(IGH_Component component)
|
||||
: base(component)
|
||||
{
|
||||
_typedOwner = (AccountManagerComponent)component;
|
||||
}
|
||||
|
||||
public override void AppendToAttributeTree(List<IGH_Attributes> attributes)
|
||||
{
|
||||
base.AppendToAttributeTree(attributes);
|
||||
_typedOwner.SignInButton.Attributes?.AppendToAttributeTree(attributes);
|
||||
}
|
||||
|
||||
private void InitialiseAttributes()
|
||||
{
|
||||
_typedOwner.SignInButton.Attributes ??= new GhContextMenuButtonAttributes(_typedOwner.SignInButton)
|
||||
{
|
||||
Parent = this,
|
||||
};
|
||||
}
|
||||
|
||||
protected override void Layout()
|
||||
{
|
||||
base.Layout();
|
||||
var baseRec = GH_Convert.ToRectangle(Bounds);
|
||||
baseRec.Height += 26;
|
||||
|
||||
var btnRec = baseRec;
|
||||
btnRec.Y = baseRec.Bottom - 26;
|
||||
btnRec.Height = 26;
|
||||
btnRec.Inflate(-2, -2);
|
||||
|
||||
Bounds = baseRec;
|
||||
InitialiseAttributes();
|
||||
|
||||
_typedOwner.SignInButton.Attributes.Pivot = btnRec.Location;
|
||||
_typedOwner.SignInButton.Attributes.Bounds = btnRec;
|
||||
}
|
||||
|
||||
protected override void Render(GH_Canvas canvas, Graphics graphics, GH_CanvasChannel channel)
|
||||
{
|
||||
base.Render(canvas, graphics, channel);
|
||||
_typedOwner.SignInButton.Attributes.RenderToCanvas(canvas, channel);
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Sdk.Credentials;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.Operations.Receive;
|
||||
|
||||
public record GrasshopperReceiveInfo(
|
||||
string AccountId,
|
||||
Uri ServerUrl,
|
||||
Account Account,
|
||||
string? WorkspaceId,
|
||||
string ProjectId,
|
||||
string ProjectName,
|
||||
@@ -13,4 +13,4 @@ public record GrasshopperReceiveInfo(
|
||||
string SelectedVersionId,
|
||||
string SourceApplication,
|
||||
string? SelectedVersionUserId
|
||||
) : ReceiveInfo(AccountId, ServerUrl, ProjectId, ProjectName, ModelId, ModelName, SelectedVersionId, SourceApplication);
|
||||
) : ReceiveInfo(Account, ProjectId, ProjectName, ModelId, ModelName, SelectedVersionId, SourceApplication);
|
||||
|
||||
+130
-136
@@ -7,7 +7,6 @@ using GrasshopperAsyncComponent;
|
||||
using Rhino;
|
||||
using Speckle.Connectors.Common;
|
||||
using Speckle.Connectors.Common.Analytics;
|
||||
using Speckle.Connectors.Common.Instances;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Connectors.Common.Operations.Receive;
|
||||
using Speckle.Connectors.GrasshopperShared.HostApp;
|
||||
@@ -26,7 +25,7 @@ using Speckle.Sdk.Models.Extensions;
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.Operations.Receive;
|
||||
|
||||
[Guid("1587DF34-83E5-4AFE-B42E-F7C5C37ECD68")]
|
||||
public class ReceiveAsyncComponent : GH_AsyncComponent
|
||||
public class ReceiveAsyncComponent : GH_AsyncComponent<ReceiveAsyncComponent>
|
||||
{
|
||||
public ReceiveAsyncComponent()
|
||||
: base("Load", "L", "Load a model from Speckle", ComponentCategories.PRIMARY_RIBBON, ComponentCategories.OPERATIONS)
|
||||
@@ -38,6 +37,8 @@ public class ReceiveAsyncComponent : GH_AsyncComponent
|
||||
public override Guid ComponentGuid => GetType().GUID;
|
||||
protected override Bitmap Icon => Resources.speckle_operations_load;
|
||||
|
||||
public override GH_Exposure Exposure => GH_Exposure.secondary;
|
||||
|
||||
public string InputType { get; set; }
|
||||
public bool AutoReceive { get; set; }
|
||||
public string ReceivedVersionId { get; set; }
|
||||
@@ -280,11 +281,7 @@ public class ReceiveAsyncComponent : GH_AsyncComponent
|
||||
try
|
||||
{
|
||||
using var scope = PriorityLoader.CreateScopeForActiveDocument();
|
||||
Account? account =
|
||||
urlResource.AccountId != null
|
||||
? scope.Get<IAccountManager>().GetAccount(urlResource.AccountId)
|
||||
: scope.Get<IAccountService>().GetAccountWithServerUrlFallback("", new Uri(urlResource.Server)); // fallback the account that matches with URL if any
|
||||
|
||||
Account? account = urlResource.Account.GetAccount(scope);
|
||||
if (account is null)
|
||||
{
|
||||
throw new SpeckleAccountManagerException($"No default account was found");
|
||||
@@ -302,24 +299,28 @@ public class ReceiveAsyncComponent : GH_AsyncComponent
|
||||
}
|
||||
}
|
||||
|
||||
public class ReceiveComponentWorker : WorkerInstance
|
||||
public sealed class ReceiveComponentWorker : WorkerInstance<ReceiveAsyncComponent>
|
||||
{
|
||||
public ReceiveComponentWorker(GH_Component p)
|
||||
: base(p) { }
|
||||
public ReceiveComponentWorker(
|
||||
ReceiveAsyncComponent p,
|
||||
string id = "baseWorker",
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
: base(p, id, cancellationToken) { }
|
||||
|
||||
public Base Root { get; set; }
|
||||
public SpeckleUrlModelResource? UrlModelResource { get; set; }
|
||||
public SpeckleCollectionWrapperGoo Result { get; set; }
|
||||
private List<(GH_RuntimeMessageLevel, string)> RuntimeMessages { get; } = new();
|
||||
|
||||
public override WorkerInstance Duplicate()
|
||||
public override WorkerInstance<ReceiveAsyncComponent> Duplicate(string id, CancellationToken cancellationToken)
|
||||
{
|
||||
return new ReceiveComponentWorker(Parent);
|
||||
return new ReceiveComponentWorker(Parent, id, cancellationToken);
|
||||
}
|
||||
|
||||
public override void GetData(IGH_DataAccess da, GH_ComponentParamServer p)
|
||||
{
|
||||
UrlModelResource = ((ReceiveAsyncComponent)Parent).UrlModelResource;
|
||||
UrlModelResource = Parent.UrlModelResource;
|
||||
}
|
||||
|
||||
public override void SetData(IGH_DataAccess da)
|
||||
@@ -334,7 +335,7 @@ public class ReceiveComponentWorker : WorkerInstance
|
||||
Parent.AddRuntimeMessage(level, message);
|
||||
}
|
||||
|
||||
var parent = (ReceiveAsyncComponent)Parent;
|
||||
var parent = Parent;
|
||||
|
||||
parent.CurrentComponentState = ComponentState.UpToDate;
|
||||
|
||||
@@ -348,130 +349,19 @@ public class ReceiveComponentWorker : WorkerInstance
|
||||
da.SetData(0, Result);
|
||||
}
|
||||
|
||||
#pragma warning disable CA1506
|
||||
public override void DoWork(Action<string, double> reportProgress, Action done)
|
||||
#pragma warning restore CA1506
|
||||
public override async Task DoWork(Action<string, double> reportProgress, Action done)
|
||||
{
|
||||
var receiveComponent = (ReceiveAsyncComponent)Parent;
|
||||
|
||||
try
|
||||
{
|
||||
if (UrlModelResource is null)
|
||||
{
|
||||
throw new InvalidOperationException("Model Resource was null");
|
||||
}
|
||||
|
||||
// Means it's a copy paste of an empty non-init component; set the record and exit fast.
|
||||
if (receiveComponent.JustPastedIn && !receiveComponent.AutoReceive)
|
||||
{
|
||||
receiveComponent.JustPastedIn = false;
|
||||
return;
|
||||
}
|
||||
|
||||
receiveComponent.CurrentComponentState = ComponentState.Receiving;
|
||||
RhinoApp.InvokeOnUiThread(
|
||||
(Action)
|
||||
delegate
|
||||
{
|
||||
receiveComponent.OnDisplayExpired(true);
|
||||
}
|
||||
);
|
||||
|
||||
var t = Task.Run(async () =>
|
||||
{
|
||||
// Step 1 - RECEIVE FROM SERVER
|
||||
var receiveInfo = await UrlModelResource
|
||||
.GetReceiveInfo(receiveComponent.ApiClient, CancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var progress = new Progress<CardProgress>(p =>
|
||||
{
|
||||
reportProgress(Id, p.Progress ?? 0);
|
||||
//eceiveComponent.Message = $"{p.Status}";
|
||||
});
|
||||
|
||||
if (CancellationToken.IsCancellationRequested)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (receiveInfo == null)
|
||||
{
|
||||
done();
|
||||
return;
|
||||
}
|
||||
|
||||
using var scope = PriorityLoader.CreateScopeForActiveDocument();
|
||||
Root = await scope
|
||||
.Get<GrasshopperReceiveOperation>()
|
||||
.ReceiveCommitObject(receiveInfo, progress, CancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (CancellationToken.IsCancellationRequested)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 2 - CONVERT
|
||||
//receiveComponent.Message = $"Unpacking...";
|
||||
LocalToGlobalUnpacker localToGlobalUnpacker = new();
|
||||
TraversalContextUnpacker traversalContextUnpacker = new();
|
||||
var unpackedRoot = scope.Get<RootObjectUnpacker>().Unpack(Root);
|
||||
|
||||
// "flatten" block instances
|
||||
var localToGlobalMaps = localToGlobalUnpacker.Unpack(
|
||||
unpackedRoot.DefinitionProxies,
|
||||
unpackedRoot.ObjectsToConvert.ToList()
|
||||
);
|
||||
|
||||
// TODO: unpack colors and render materials
|
||||
GrasshopperColorUnpacker colorUnpacker = new(unpackedRoot);
|
||||
GrasshopperMaterialUnpacker materialUnpacker = new(unpackedRoot);
|
||||
|
||||
GrasshopperCollectionRebuilder collectionRebuilder =
|
||||
new((Root as Collection) ?? new Collection() { name = "unnamed" });
|
||||
|
||||
LocalToGlobalMapHandler mapHandler =
|
||||
new(traversalContextUnpacker, collectionRebuilder, colorUnpacker, materialUnpacker);
|
||||
|
||||
int count = 0;
|
||||
int total = localToGlobalMaps.Count;
|
||||
|
||||
foreach (var map in localToGlobalMaps)
|
||||
{
|
||||
mapHandler.CreateGrasshopperObjectFromMap(map);
|
||||
count++;
|
||||
}
|
||||
|
||||
Result = new SpeckleCollectionWrapperGoo(collectionRebuilder.RootCollectionWrapper);
|
||||
|
||||
// TODO: If we have NodeRun events later, better to have `ComponentTracker` to use across components
|
||||
var customProperties = new Dictionary<string, object>()
|
||||
{
|
||||
{ "isAsync", true },
|
||||
{ "sourceHostApp", HostApplications.GetSlugFromHostAppNameAndVersion(receiveInfo.SourceApplication) },
|
||||
{ "auto", receiveComponent.AutoReceive }
|
||||
};
|
||||
if (receiveInfo.WorkspaceId != null)
|
||||
{
|
||||
customProperties.Add("workspace_id", receiveInfo.WorkspaceId);
|
||||
}
|
||||
|
||||
if (receiveInfo.SelectedVersionUserId != null)
|
||||
{
|
||||
customProperties.Add(
|
||||
"isMultiplayer",
|
||||
receiveInfo.SelectedVersionUserId != receiveComponent.ApiClient.Account.userInfo.id
|
||||
);
|
||||
}
|
||||
await scope
|
||||
.Get<IMixPanelManager>()
|
||||
.TrackEvent(MixPanelEvents.Receive, receiveComponent.ApiClient.Account, customProperties);
|
||||
|
||||
// DONE
|
||||
done();
|
||||
});
|
||||
t.Wait();
|
||||
await Receive(reportProgress);
|
||||
done();
|
||||
}
|
||||
catch (OperationCanceledException) when (CancellationToken.IsCancellationRequested)
|
||||
{
|
||||
RuntimeMessages.Add((GH_RuntimeMessageLevel.Remark, "Operation cancelled"));
|
||||
Parent.CurrentComponentState = ComponentState.Expired;
|
||||
//No need to call `done()` - GrasshopperAsyncComponent assumes immediate cancel,
|
||||
//thus it has already performed clean-up actions that would normally be done on `done()`
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
@@ -479,6 +369,110 @@ public class ReceiveComponentWorker : WorkerInstance
|
||||
done();
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable CA1506
|
||||
private async Task Receive(Action<string, double> reportProgress)
|
||||
#pragma warning restore CA1506
|
||||
{
|
||||
if (UrlModelResource is null)
|
||||
{
|
||||
throw new InvalidOperationException("Model Resource was null");
|
||||
}
|
||||
|
||||
// Means it's a copy paste of an empty non-init component; set the record and exit fast.
|
||||
if (Parent.JustPastedIn && !Parent.AutoReceive)
|
||||
{
|
||||
Parent.JustPastedIn = false;
|
||||
return;
|
||||
}
|
||||
|
||||
Parent.CurrentComponentState = ComponentState.Receiving;
|
||||
RhinoApp.InvokeOnUiThread(
|
||||
(Action)
|
||||
delegate
|
||||
{
|
||||
Parent.OnDisplayExpired(true);
|
||||
}
|
||||
);
|
||||
|
||||
// Step 1 - RECEIVE FROM SERVER
|
||||
var receiveInfo = await UrlModelResource.GetReceiveInfo(Parent.ApiClient, CancellationToken).ConfigureAwait(false);
|
||||
|
||||
var progress = new Progress<CardProgress>(p =>
|
||||
{
|
||||
reportProgress(Id, p.Progress ?? 0);
|
||||
//eceiveComponent.Message = $"{p.Status}";
|
||||
});
|
||||
|
||||
CancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (receiveInfo == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using var scope = PriorityLoader.CreateScopeForActiveDocument();
|
||||
Root = await scope
|
||||
.Get<GrasshopperReceiveOperation>()
|
||||
.ReceiveCommitObject(receiveInfo, progress, CancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
CancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
// Step 2 - CONVERT
|
||||
//receiveComponent.Message = $"Unpacking...";
|
||||
TraversalContextUnpacker traversalContextUnpacker = new();
|
||||
var unpackedRoot = scope.Get<RootObjectUnpacker>().Unpack(Root);
|
||||
|
||||
// separate atomic objects from block instances
|
||||
var (atomicObjects, blockInstances) = scope
|
||||
.Get<RootObjectUnpacker>()
|
||||
.SplitAtomicObjectsAndInstances(unpackedRoot.ObjectsToConvert);
|
||||
|
||||
// initialize unpackers and collection builder
|
||||
var colorUnpacker = new GrasshopperColorUnpacker(unpackedRoot);
|
||||
var materialUnpacker = new GrasshopperMaterialUnpacker(unpackedRoot);
|
||||
var collectionRebuilder = new GrasshopperCollectionRebuilder(
|
||||
(Root as Collection) ?? new Collection { name = "unnamed" }
|
||||
);
|
||||
|
||||
// convert atomic objects directly
|
||||
var mapHandler = new LocalToGlobalMapHandler(
|
||||
traversalContextUnpacker,
|
||||
collectionRebuilder,
|
||||
colorUnpacker,
|
||||
materialUnpacker
|
||||
);
|
||||
|
||||
foreach (var atomicContext in atomicObjects)
|
||||
{
|
||||
mapHandler.ConvertAtomicObject(atomicContext);
|
||||
}
|
||||
|
||||
// process block instances using converted atomic objects
|
||||
// block processing needs converted objects, but object filtering needs block definitions.
|
||||
mapHandler.ConvertBlockInstances(blockInstances, unpackedRoot.DefinitionProxies);
|
||||
|
||||
Result = new SpeckleCollectionWrapperGoo(collectionRebuilder.RootCollectionWrapper);
|
||||
|
||||
// TODO: If we have NodeRun events later, better to have `ComponentTracker` to use across components
|
||||
var customProperties = new Dictionary<string, object>()
|
||||
{
|
||||
{ "isAsync", true },
|
||||
{ "sourceHostApp", HostApplications.GetSlugFromHostAppNameAndVersion(receiveInfo.SourceApplication) },
|
||||
{ "auto", Parent.AutoReceive }
|
||||
};
|
||||
if (receiveInfo.WorkspaceId != null)
|
||||
{
|
||||
customProperties.Add("workspace_id", receiveInfo.WorkspaceId);
|
||||
}
|
||||
|
||||
if (receiveInfo.SelectedVersionUserId != null)
|
||||
{
|
||||
customProperties.Add("isMultiplayer", receiveInfo.SelectedVersionUserId != Parent.ApiClient.Account.userInfo.id);
|
||||
}
|
||||
await scope.Get<IMixPanelManager>().TrackEvent(MixPanelEvents.Receive, Parent.ApiClient.Account, customProperties);
|
||||
}
|
||||
}
|
||||
|
||||
public class ReceiveAsyncComponentAttributes : GH_ComponentAttributes
|
||||
@@ -537,7 +531,7 @@ public class ReceiveAsyncComponentAttributes : GH_ComponentAttributes
|
||||
else
|
||||
{
|
||||
var palette =
|
||||
state == ComponentState.Expired || state == ComponentState.UpToDate || state == ComponentState.Cancelled
|
||||
state == ComponentState.Expired || state == ComponentState.UpToDate
|
||||
? GH_Palette.Black
|
||||
: GH_Palette.Transparent;
|
||||
var text = state != ComponentState.Receiving ? "Load" : "Loading...";
|
||||
|
||||
+23
-23
@@ -2,7 +2,6 @@ using Grasshopper.Kernel;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Speckle.Connectors.Common;
|
||||
using Speckle.Connectors.Common.Analytics;
|
||||
using Speckle.Connectors.Common.Instances;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Connectors.Common.Operations.Receive;
|
||||
using Speckle.Connectors.GrasshopperShared.Components.BaseComponents;
|
||||
@@ -116,18 +115,12 @@ public class ReceiveComponent : SpeckleTaskCapableComponent<ReceiveComponentInpu
|
||||
}
|
||||
|
||||
using var scope = PriorityLoader.CreateScopeForActiveDocument();
|
||||
var accountService = scope.ServiceProvider.GetRequiredService<IAccountService>();
|
||||
var accountManager = scope.ServiceProvider.GetRequiredService<IAccountManager>();
|
||||
var clientFactory = scope.ServiceProvider.GetRequiredService<IClientFactory>();
|
||||
var receiveOperation = scope.ServiceProvider.GetRequiredService<GrasshopperReceiveOperation>();
|
||||
|
||||
// Do the thing 👇🏼
|
||||
|
||||
Account? account =
|
||||
input.Resource.AccountId != null
|
||||
? accountManager.GetAccount(input.Resource.AccountId)
|
||||
: accountService.GetAccountWithServerUrlFallback("", new Uri(input.Resource.Server)); // fallback the account that matches with URL if any
|
||||
|
||||
Account? account = input.Resource.Account.GetAccount(scope);
|
||||
if (account is null)
|
||||
{
|
||||
throw new SpeckleAccountManagerException($"No default account was found");
|
||||
@@ -165,32 +158,39 @@ public class ReceiveComponent : SpeckleTaskCapableComponent<ReceiveComponentInpu
|
||||
|
||||
// We need to rethink these lovely unpackers, there's a bit too many of 'em
|
||||
var rootObjectUnpacker = scope.ServiceProvider.GetService<RootObjectUnpacker>();
|
||||
var localToGlobalUnpacker = new LocalToGlobalUnpacker();
|
||||
var traversalContextUnpacker = new TraversalContextUnpacker();
|
||||
|
||||
var unpackedRoot = rootObjectUnpacker.Unpack(root);
|
||||
|
||||
// "flatten" block instances
|
||||
var localToGlobalMaps = localToGlobalUnpacker.Unpack(
|
||||
unpackedRoot.DefinitionProxies,
|
||||
unpackedRoot.ObjectsToConvert.ToList()
|
||||
// split atomic objects from block components before conversion
|
||||
var (atomicObjects, blockInstances) = rootObjectUnpacker.SplitAtomicObjectsAndInstances(
|
||||
unpackedRoot.ObjectsToConvert
|
||||
);
|
||||
|
||||
// unpack colors and render materials
|
||||
GrasshopperColorUnpacker colorUnpacker = new(unpackedRoot);
|
||||
GrasshopperMaterialUnpacker materialUnpacker = new(unpackedRoot);
|
||||
// Initialize unpackers and collection builder
|
||||
var colorUnpacker = new GrasshopperColorUnpacker(unpackedRoot);
|
||||
var materialUnpacker = new GrasshopperMaterialUnpacker(unpackedRoot);
|
||||
var collectionRebuilder = new GrasshopperCollectionRebuilder(
|
||||
(root as Collection) ?? new Collection { name = "unnamed" }
|
||||
);
|
||||
|
||||
GrasshopperCollectionRebuilder collectionRebuilder =
|
||||
new((root as Collection) ?? new Collection() { name = "unnamed" });
|
||||
// convert atomic objects directly
|
||||
var mapHandler = new LocalToGlobalMapHandler(
|
||||
traversalContextUnpacker,
|
||||
collectionRebuilder,
|
||||
colorUnpacker,
|
||||
materialUnpacker
|
||||
);
|
||||
|
||||
LocalToGlobalMapHandler mapHandler =
|
||||
new(traversalContextUnpacker, collectionRebuilder, colorUnpacker, materialUnpacker);
|
||||
|
||||
foreach (var map in localToGlobalMaps)
|
||||
foreach (var atomicContext in atomicObjects)
|
||||
{
|
||||
mapHandler.CreateGrasshopperObjectFromMap(map);
|
||||
mapHandler.ConvertAtomicObject(atomicContext);
|
||||
}
|
||||
|
||||
// process block instances using converted atomic objects
|
||||
// block processing needs converted objects, but object filtering needs block definitions.
|
||||
mapHandler.ConvertBlockInstances(blockInstances, unpackedRoot.DefinitionProxies);
|
||||
|
||||
// var x = new SpeckleCollectionGoo { Value = collGen.RootCollection };
|
||||
var goo = new SpeckleCollectionWrapperGoo(collectionRebuilder.RootCollectionWrapper);
|
||||
return new ReceiveComponentOutput { RootObject = goo };
|
||||
|
||||
+3
-3
@@ -1,12 +1,12 @@
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Sdk.Credentials;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.Operations.Send;
|
||||
|
||||
public record GrasshopperSendInfo(
|
||||
string AccountId,
|
||||
Uri ServerUrl,
|
||||
Account Account,
|
||||
string? WorkspaceId,
|
||||
string ProjectId,
|
||||
string ModelId,
|
||||
string SourceApplication
|
||||
) : SendInfo(AccountId, ServerUrl, ProjectId, ModelId, SourceApplication);
|
||||
) : SendInfo(Account, ProjectId, ModelId, SourceApplication);
|
||||
|
||||
+106
-122
@@ -16,17 +16,15 @@ using Speckle.Connectors.GrasshopperShared.Properties;
|
||||
using Speckle.Connectors.GrasshopperShared.Registration;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Api;
|
||||
using Speckle.Sdk.Common;
|
||||
using Speckle.Sdk.Credentials;
|
||||
using Speckle.Sdk.Models.Extensions;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.Operations.Send;
|
||||
|
||||
[Guid("52481972-7867-404F-8D9F-E1481183F355")]
|
||||
public class SendAsyncComponent : GH_AsyncComponent
|
||||
public class SendAsyncComponent : GH_AsyncComponent<SendAsyncComponent>
|
||||
{
|
||||
public GhContextMenuButton ProjectContextMenuButton { get; set; }
|
||||
public GhContextMenuButton ModelContextMenuButton { get; set; }
|
||||
|
||||
public SendAsyncComponent()
|
||||
: base(
|
||||
"Publish",
|
||||
@@ -43,6 +41,7 @@ public class SendAsyncComponent : GH_AsyncComponent
|
||||
public override Guid ComponentGuid => GetType().GUID;
|
||||
|
||||
protected override Bitmap Icon => Resources.speckle_operations_publish;
|
||||
public override GH_Exposure Exposure => GH_Exposure.secondary;
|
||||
|
||||
public ComponentState CurrentComponentState { get; set; } = ComponentState.NeedsInput;
|
||||
public bool AutoSend { get; set; }
|
||||
@@ -55,6 +54,8 @@ public class SendAsyncComponent : GH_AsyncComponent
|
||||
public SpeckleUrlModelResource? OutputParam { get; set; }
|
||||
public bool HasMultipleInputs { get; set; }
|
||||
|
||||
public string? VersionMessage { get; private set; }
|
||||
|
||||
protected override void RegisterInputParams(GH_InputParamManager pManager)
|
||||
{
|
||||
pManager.AddParameter(new SpeckleUrlModelResourceParam());
|
||||
@@ -65,6 +66,8 @@ public class SendAsyncComponent : GH_AsyncComponent
|
||||
"The collection model object to send",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
pManager.AddTextParameter("Version Message", "versionMessage", "The version message", GH_ParamAccess.item);
|
||||
pManager[2].Optional = true;
|
||||
}
|
||||
|
||||
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
|
||||
@@ -156,12 +159,8 @@ public class SendAsyncComponent : GH_AsyncComponent
|
||||
|
||||
using var scope = PriorityLoader.CreateScopeForActiveDocument();
|
||||
|
||||
var accountService = scope.ServiceProvider.GetRequiredService<IAccountService>();
|
||||
var accountManager = scope.ServiceProvider.GetRequiredService<IAccountManager>();
|
||||
var clientFactory = scope.ServiceProvider.GetRequiredService<IClientFactory>();
|
||||
|
||||
// We need to call this always in here to be able to react and set events :/
|
||||
ParseInput(da, accountService, accountManager, clientFactory);
|
||||
ParseInput(da, scope);
|
||||
|
||||
if (
|
||||
(AutoSend || CurrentComponentState == ComponentState.Ready || CurrentComponentState == ComponentState.Sending)
|
||||
@@ -198,7 +197,7 @@ public class SendAsyncComponent : GH_AsyncComponent
|
||||
|
||||
public override void DisplayProgress(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
if (Workers.Count == 0)
|
||||
if (WorkerCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -240,12 +239,7 @@ public class SendAsyncComponent : GH_AsyncComponent
|
||||
base.DocumentContextChanged(document, context);
|
||||
}
|
||||
|
||||
private void ParseInput(
|
||||
IGH_DataAccess da,
|
||||
IAccountService accountService,
|
||||
IAccountManager accountManager,
|
||||
IClientFactory clientFactory
|
||||
)
|
||||
private void ParseInput(IGH_DataAccess da, IServiceScope scope)
|
||||
{
|
||||
HostApp.SpeckleUrlModelResource? dataInput = null;
|
||||
da.GetData(0, ref dataInput);
|
||||
@@ -259,17 +253,14 @@ public class SendAsyncComponent : GH_AsyncComponent
|
||||
UrlModelResource = dataInput;
|
||||
try
|
||||
{
|
||||
Account? account =
|
||||
dataInput.AccountId != null
|
||||
? accountManager.GetAccount(dataInput.AccountId)
|
||||
: accountService.GetAccountWithServerUrlFallback("", new Uri(dataInput.Server)); // fallback the account that matches with URL if any
|
||||
Account? account = dataInput.Account.GetAccount(scope);
|
||||
if (account is null)
|
||||
{
|
||||
throw new SpeckleAccountManagerException($"No default account was found");
|
||||
}
|
||||
|
||||
ApiClient?.Dispose();
|
||||
ApiClient = clientFactory.Create(account);
|
||||
ApiClient = scope.Get<IClientFactory>().Create(account);
|
||||
}
|
||||
catch (Exception e) when (!e.IsFatal())
|
||||
{
|
||||
@@ -285,21 +276,29 @@ public class SendAsyncComponent : GH_AsyncComponent
|
||||
return;
|
||||
}
|
||||
RootCollectionWrapper = rootCollectionWrapper;
|
||||
|
||||
string? versionMessage = null;
|
||||
da.GetData(2, ref versionMessage);
|
||||
VersionMessage = versionMessage;
|
||||
}
|
||||
}
|
||||
|
||||
public class SendComponentWorker : WorkerInstance
|
||||
public class SendComponentWorker : WorkerInstance<SendAsyncComponent>
|
||||
{
|
||||
public SendComponentWorker(GH_Component p)
|
||||
: base(p) { }
|
||||
public SendComponentWorker(
|
||||
SendAsyncComponent p,
|
||||
string id = "baseWorker",
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
: base(p, id, cancellationToken) { }
|
||||
|
||||
private Stopwatch _stopwatch;
|
||||
private Stopwatch? _stopwatch;
|
||||
public SpeckleUrlModelResource? OutputParam { get; set; }
|
||||
private List<(GH_RuntimeMessageLevel, string)> RuntimeMessages { get; } = new();
|
||||
|
||||
public override WorkerInstance Duplicate()
|
||||
public override WorkerInstance<SendAsyncComponent> Duplicate(string id, CancellationToken cancellationToken)
|
||||
{
|
||||
return new SendComponentWorker(Parent);
|
||||
return new SendComponentWorker(Parent, id, cancellationToken);
|
||||
}
|
||||
|
||||
public override void GetData(IGH_DataAccess da, GH_ComponentParamServer p)
|
||||
@@ -310,18 +309,18 @@ public class SendComponentWorker : WorkerInstance
|
||||
|
||||
public override void SetData(IGH_DataAccess da)
|
||||
{
|
||||
_stopwatch.Stop();
|
||||
_stopwatch.NotNull("GetData must be called before SetData").Stop();
|
||||
|
||||
if (((SendAsyncComponent)Parent).JustPastedIn)
|
||||
if (Parent.JustPastedIn)
|
||||
{
|
||||
((SendAsyncComponent)Parent).JustPastedIn = false;
|
||||
da.SetData(0, ((SendAsyncComponent)Parent).OutputParam);
|
||||
Parent.JustPastedIn = false;
|
||||
da.SetData(0, Parent.OutputParam);
|
||||
return;
|
||||
}
|
||||
|
||||
if (CancellationToken.IsCancellationRequested)
|
||||
{
|
||||
((SendAsyncComponent)Parent).CurrentComponentState = ComponentState.Expired;
|
||||
Parent.CurrentComponentState = ComponentState.Expired;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -332,9 +331,9 @@ public class SendComponentWorker : WorkerInstance
|
||||
|
||||
da.SetData(0, OutputParam);
|
||||
|
||||
((SendAsyncComponent)Parent).CurrentComponentState = ComponentState.UpToDate;
|
||||
((SendAsyncComponent)Parent).OutputParam = OutputParam; // ref the outputs in the parent too, so we can serialise them on write/read
|
||||
((SendAsyncComponent)Parent).OverallProgress = 0;
|
||||
Parent.CurrentComponentState = ComponentState.UpToDate;
|
||||
Parent.OutputParam = OutputParam; // ref the outputs in the parent too, so we can serialise them on write/read
|
||||
Parent.OverallProgress = 0;
|
||||
|
||||
var hasWarnings = RuntimeMessages.Count > 0;
|
||||
if (!hasWarnings)
|
||||
@@ -356,96 +355,24 @@ public class SendComponentWorker : WorkerInstance
|
||||
}
|
||||
}
|
||||
|
||||
public override void DoWork(Action<string, double> reportProgress, Action done)
|
||||
public override async Task DoWork(Action<string, double> reportProgress, Action done)
|
||||
{
|
||||
var sendComponent = (SendAsyncComponent)Parent;
|
||||
|
||||
if (sendComponent.JustPastedIn || sendComponent.HasMultipleInputs)
|
||||
if (Parent.JustPastedIn || Parent.HasMultipleInputs)
|
||||
{
|
||||
done();
|
||||
return;
|
||||
}
|
||||
|
||||
if (CancellationToken.IsCancellationRequested)
|
||||
{
|
||||
sendComponent.CurrentComponentState = ComponentState.Expired;
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
SpeckleUrlModelResource? urlModelResource = sendComponent.UrlModelResource;
|
||||
if (urlModelResource is null)
|
||||
{
|
||||
throw new InvalidOperationException("Url Resource was null");
|
||||
}
|
||||
|
||||
SpeckleCollectionWrapperGoo? rootCollectionWrapper = sendComponent.RootCollectionWrapper;
|
||||
if (rootCollectionWrapper is null)
|
||||
{
|
||||
throw new InvalidOperationException("Root Collection was null");
|
||||
}
|
||||
|
||||
var t = Task.Run(async () =>
|
||||
{
|
||||
if (CancellationToken.IsCancellationRequested)
|
||||
{
|
||||
sendComponent.CurrentComponentState = ComponentState.Expired;
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 1 - SEND TO SERVER
|
||||
var sendInfo = await urlModelResource
|
||||
.GetSendInfo(sendComponent.ApiClient, CancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var progress = new Progress<CardProgress>(p =>
|
||||
{
|
||||
reportProgress(Id, p.Progress ?? 0);
|
||||
//sendComponent.Message = $"{p.Status}";
|
||||
});
|
||||
|
||||
using var scope = PriorityLoader.CreateScopeForActiveDocument();
|
||||
var sendOperation = scope.ServiceProvider.GetRequiredService<SendOperation<SpeckleCollectionWrapperGoo>>();
|
||||
SendOperationResult? result = await sendOperation
|
||||
.Execute(
|
||||
new List<SpeckleCollectionWrapperGoo>() { rootCollectionWrapper },
|
||||
sendInfo,
|
||||
progress,
|
||||
CancellationToken
|
||||
)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// TODO: If we have NodeRun events later, better to have `ComponentTracker` to use across components
|
||||
var customProperties = new Dictionary<string, object>()
|
||||
{
|
||||
{ "isAsync", true },
|
||||
{ "auto", sendComponent.AutoSend }
|
||||
};
|
||||
if (sendInfo.WorkspaceId != null)
|
||||
{
|
||||
customProperties.Add("workspace_id", sendInfo.WorkspaceId);
|
||||
}
|
||||
|
||||
var mixPanelManager = scope.ServiceProvider.GetRequiredService<IMixPanelManager>();
|
||||
await mixPanelManager.TrackEvent(MixPanelEvents.Send, sendComponent.ApiClient.Account, customProperties);
|
||||
|
||||
SpeckleUrlModelVersionResource? createdVersion =
|
||||
new(
|
||||
sendInfo.AccountId,
|
||||
sendInfo.ServerUrl.ToString(),
|
||||
sendInfo.WorkspaceId,
|
||||
sendInfo.ProjectId,
|
||||
sendInfo.ModelId,
|
||||
result.VersionId
|
||||
);
|
||||
OutputParam = createdVersion;
|
||||
sendComponent.Url = $"{createdVersion.Server}projects/{sendInfo.ProjectId}/models/{sendInfo.ModelId}";
|
||||
|
||||
// DONE
|
||||
done();
|
||||
});
|
||||
t.Wait();
|
||||
await Send(reportProgress);
|
||||
done();
|
||||
}
|
||||
catch (OperationCanceledException) when (CancellationToken.IsCancellationRequested)
|
||||
{
|
||||
RuntimeMessages.Add((GH_RuntimeMessageLevel.Remark, "Operation cancelled"));
|
||||
Parent.CurrentComponentState = ComponentState.Expired;
|
||||
//No need to call `done()` - GrasshopperAsyncComponent assumes immediate cancel,
|
||||
//thus it has already performed clean-up actions that would normally be done on `done()`
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
@@ -453,6 +380,65 @@ public class SendComponentWorker : WorkerInstance
|
||||
done();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task Send(Action<string, double> reportProgress)
|
||||
{
|
||||
SpeckleUrlModelResource? urlModelResource = Parent.UrlModelResource;
|
||||
if (urlModelResource is null)
|
||||
{
|
||||
throw new InvalidOperationException("Url Resource was null");
|
||||
}
|
||||
|
||||
SpeckleCollectionWrapperGoo? rootCollectionWrapper = Parent.RootCollectionWrapper;
|
||||
if (rootCollectionWrapper is null)
|
||||
{
|
||||
throw new InvalidOperationException("Root Collection was null");
|
||||
}
|
||||
|
||||
// Step 1 - SEND TO SERVER
|
||||
var sendInfo = await urlModelResource.GetSendInfo(Parent.ApiClient, CancellationToken).ConfigureAwait(false);
|
||||
|
||||
var progress = new Progress<CardProgress>(p =>
|
||||
{
|
||||
reportProgress(Id, p.Progress ?? 0);
|
||||
//sendComponent.Message = $"{p.Status}";
|
||||
});
|
||||
|
||||
using var scope = PriorityLoader.CreateScopeForActiveDocument();
|
||||
var sendOperation = scope.ServiceProvider.GetRequiredService<SendOperation<SpeckleCollectionWrapperGoo>>();
|
||||
SendOperationResult? result = await sendOperation
|
||||
.Execute(
|
||||
new List<SpeckleCollectionWrapperGoo>() { rootCollectionWrapper },
|
||||
sendInfo,
|
||||
Parent.VersionMessage,
|
||||
progress,
|
||||
CancellationToken
|
||||
)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// TODO: If we have NodeRun events later, better to have `ComponentTracker` to use across components
|
||||
var customProperties = new Dictionary<string, object>() { { "isAsync", true }, { "auto", Parent.AutoSend } };
|
||||
if (sendInfo.WorkspaceId != null)
|
||||
{
|
||||
customProperties.Add("workspace_id", sendInfo.WorkspaceId);
|
||||
}
|
||||
|
||||
var mixPanelManager = scope.ServiceProvider.GetRequiredService<IMixPanelManager>();
|
||||
await mixPanelManager
|
||||
.TrackEvent(MixPanelEvents.Send, Parent.ApiClient.Account, customProperties)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
SpeckleUrlModelVersionResource createdVersion =
|
||||
new(
|
||||
new(sendInfo.Account.id, null, sendInfo.Account.serverInfo.url),
|
||||
sendInfo.WorkspaceId,
|
||||
sendInfo.ProjectId,
|
||||
sendInfo.ModelId,
|
||||
result.VersionId
|
||||
);
|
||||
OutputParam = createdVersion;
|
||||
Parent.Url = $"{createdVersion.Account.Server}/projects/{sendInfo.ProjectId}/models/{sendInfo.ModelId}";
|
||||
}
|
||||
}
|
||||
|
||||
public class SendAsyncComponentAttributes : GH_ComponentAttributes
|
||||
@@ -496,7 +482,7 @@ public class SendAsyncComponentAttributes : GH_ComponentAttributes
|
||||
{
|
||||
if (((SendAsyncComponent)Owner).AutoSend)
|
||||
{
|
||||
var autoSendButton = GH_Capsule.CreateTextCapsule(
|
||||
using var autoSendButton = GH_Capsule.CreateTextCapsule(
|
||||
ButtonBounds,
|
||||
ButtonBounds,
|
||||
GH_Palette.Blue,
|
||||
@@ -506,7 +492,6 @@ public class SendAsyncComponentAttributes : GH_ComponentAttributes
|
||||
);
|
||||
|
||||
autoSendButton.Render(graphics, Selected, Owner.Locked, false);
|
||||
autoSendButton.Dispose();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -517,7 +502,7 @@ public class SendAsyncComponentAttributes : GH_ComponentAttributes
|
||||
|
||||
var text = state == ComponentState.Sending ? "Publishing..." : "Publish";
|
||||
|
||||
var button = GH_Capsule.CreateTextCapsule(
|
||||
using var button = GH_Capsule.CreateTextCapsule(
|
||||
ButtonBounds,
|
||||
ButtonBounds,
|
||||
palette,
|
||||
@@ -526,7 +511,6 @@ public class SendAsyncComponentAttributes : GH_ComponentAttributes
|
||||
state == ComponentState.Expired ? 10 : 0
|
||||
);
|
||||
button.Render(graphics, Selected, Owner.Locked, false);
|
||||
button.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+20
-15
@@ -49,6 +49,8 @@ public class SendComponent : SpeckleTaskCapableComponent<SendComponentInput, Sen
|
||||
|
||||
public string? Url { get; private set; }
|
||||
|
||||
public string? VersionMessage { get; private set; }
|
||||
|
||||
protected override Bitmap Icon => Resources.speckle_operations_syncpublish;
|
||||
|
||||
protected override void RegisterInputParams(GH_InputParamManager pManager)
|
||||
@@ -61,7 +63,8 @@ public class SendComponent : SpeckleTaskCapableComponent<SendComponentInput, Sen
|
||||
"The model collection to publish",
|
||||
GH_ParamAccess.item
|
||||
);
|
||||
|
||||
pManager.AddTextParameter("Version Message", "versionMessage", "The version message", GH_ParamAccess.item);
|
||||
pManager[2].Optional = true;
|
||||
pManager.AddBooleanParameter("Run", "r", "Run the publish operation", GH_ParamAccess.item);
|
||||
}
|
||||
|
||||
@@ -86,8 +89,12 @@ public class SendComponent : SpeckleTaskCapableComponent<SendComponentInput, Sen
|
||||
SpeckleCollectionWrapperGoo rootCollectionWrapper = new();
|
||||
da.GetData(1, ref rootCollectionWrapper);
|
||||
|
||||
string? versionMessage = null;
|
||||
da.GetData(2, ref versionMessage);
|
||||
VersionMessage = versionMessage;
|
||||
|
||||
bool run = false;
|
||||
da.GetData(2, ref run);
|
||||
da.GetData(3, ref run);
|
||||
|
||||
return new SendComponentInput(resource.NotNull(), rootCollectionWrapper, run);
|
||||
}
|
||||
@@ -160,16 +167,10 @@ public class SendComponent : SpeckleTaskCapableComponent<SendComponentInput, Sen
|
||||
}
|
||||
|
||||
using var scope = PriorityLoader.CreateScopeForActiveDocument();
|
||||
var accountService = scope.ServiceProvider.GetRequiredService<IAccountService>();
|
||||
var accountManager = scope.ServiceProvider.GetRequiredService<IAccountManager>();
|
||||
var clientFactory = scope.ServiceProvider.GetRequiredService<IClientFactory>();
|
||||
var sendOperation = scope.ServiceProvider.GetRequiredService<SendOperation<SpeckleCollectionWrapperGoo>>();
|
||||
|
||||
Account? account =
|
||||
input.Resource.AccountId != null
|
||||
? accountManager.GetAccount(input.Resource.AccountId)
|
||||
: accountService.GetAccountWithServerUrlFallback("", new Uri(input.Resource.Server)); // fallback the account that matches with URL if any
|
||||
|
||||
Account? account = input.Resource.Account.GetAccount(scope);
|
||||
if (account is null)
|
||||
{
|
||||
throw new SpeckleAccountManagerException($"No default account was found");
|
||||
@@ -183,8 +184,14 @@ 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
|
||||
.Execute(new List<SpeckleCollectionWrapperGoo>() { input.Input }, sendInfo, progress, cancellationToken)
|
||||
await sendOperation
|
||||
.Execute(
|
||||
new List<SpeckleCollectionWrapperGoo>() { input.Input },
|
||||
sendInfo,
|
||||
VersionMessage,
|
||||
progress,
|
||||
cancellationToken
|
||||
)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// TODO: If we have NodeRun events later, better to have `ComponentTracker` to use across components
|
||||
@@ -199,14 +206,12 @@ public class SendComponent : SpeckleTaskCapableComponent<SendComponentInput, Sen
|
||||
|
||||
SpeckleUrlLatestModelVersionResource createdVersionResource =
|
||||
new(
|
||||
sendInfo.AccountId,
|
||||
sendInfo.ServerUrl.ToString(),
|
||||
new(sendInfo.Account.id, null, sendInfo.Account.serverInfo.url),
|
||||
sendInfo.WorkspaceId,
|
||||
sendInfo.ProjectId,
|
||||
sendInfo.ModelId
|
||||
);
|
||||
Url = $"{createdVersionResource.Server}projects/{sendInfo.ProjectId}/models/{sendInfo.ModelId}";
|
||||
|
||||
Url = $"{sendInfo.Account.serverInfo.url}/projects/{sendInfo.ProjectId}/models/{sendInfo.ModelId}";
|
||||
return new SendComponentOutput(createdVersionResource);
|
||||
}
|
||||
}
|
||||
|
||||
+41
-8
@@ -1,3 +1,4 @@
|
||||
using System.Diagnostics;
|
||||
using GH_IO.Serialization;
|
||||
using Grasshopper.Kernel;
|
||||
using Speckle.Connectors.GrasshopperShared.Components.Operations.Wizard;
|
||||
@@ -31,10 +32,12 @@ public class SpeckleSelectModelComponent : GH_Component
|
||||
|
||||
protected override Bitmap Icon => Resources.speckle_inputs_model;
|
||||
|
||||
public override GH_Exposure Exposure => GH_Exposure.primary;
|
||||
|
||||
public SpeckleSelectModelComponent()
|
||||
: base(
|
||||
"Speckle Model URL",
|
||||
"URL",
|
||||
"Speckle Model",
|
||||
"SM",
|
||||
"User selectable model from Speckle",
|
||||
ComponentCategories.PRIMARY_RIBBON,
|
||||
ComponentCategories.OPERATIONS
|
||||
@@ -99,13 +102,13 @@ public class SpeckleSelectModelComponent : GH_Component
|
||||
try
|
||||
{
|
||||
// NOTE: once we split the logic in Sender and Receiver components, we need to set flag correctly
|
||||
var (resource, hasPermission) = SpeckleOperationWizard.SolveInstanceWithUrlInput(urlInput, true);
|
||||
var (resource, hasPermission) = SpeckleOperationWizard.SolveInstanceWithUrlInput(urlInput, true, null);
|
||||
if (!hasPermission)
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "You do not have enough permission for this project.");
|
||||
}
|
||||
_storedUserId = SpeckleOperationWizard.SelectedAccount?.id;
|
||||
_storedServer = resource.Server;
|
||||
_storedServer = resource.Account.Server;
|
||||
da.SetData(0, resource);
|
||||
}
|
||||
catch (SpeckleException e)
|
||||
@@ -257,8 +260,11 @@ public class SpeckleSelectModelComponent : GH_Component
|
||||
da.SetData(
|
||||
0,
|
||||
new SpeckleUrlLatestModelVersionResource(
|
||||
SpeckleOperationWizard.SelectedAccount.id,
|
||||
SpeckleOperationWizard.SelectedAccount.serverInfo.url,
|
||||
new AccountResource(
|
||||
SpeckleOperationWizard.SelectedAccount.id,
|
||||
null,
|
||||
SpeckleOperationWizard.SelectedAccount.serverInfo.url
|
||||
),
|
||||
SpeckleOperationWizard.SelectedWorkspace?.id,
|
||||
SpeckleOperationWizard.SelectedProject.id,
|
||||
SpeckleOperationWizard.SelectedModel.id
|
||||
@@ -271,8 +277,11 @@ public class SpeckleSelectModelComponent : GH_Component
|
||||
da.SetData(
|
||||
0,
|
||||
new SpeckleUrlModelVersionResource(
|
||||
SpeckleOperationWizard.SelectedAccount.id,
|
||||
SpeckleOperationWizard.SelectedAccount.serverInfo.url,
|
||||
new AccountResource(
|
||||
SpeckleOperationWizard.SelectedAccount.id,
|
||||
null,
|
||||
SpeckleOperationWizard.SelectedAccount.serverInfo.url
|
||||
),
|
||||
SpeckleOperationWizard.SelectedWorkspace?.id,
|
||||
SpeckleOperationWizard.SelectedProject.id,
|
||||
SpeckleOperationWizard.SelectedModel.id,
|
||||
@@ -325,6 +334,30 @@ public class SpeckleSelectModelComponent : GH_Component
|
||||
SpeckleOperationWizard.SelectedAccount?.id == account.id
|
||||
);
|
||||
}
|
||||
|
||||
if (SpeckleOperationWizard.SelectedAccount != null && SpeckleOperationWizard.SelectedProject != null)
|
||||
{
|
||||
Menu_AppendSeparator(menu);
|
||||
Menu_AppendItem(
|
||||
menu,
|
||||
$"View model online ↗",
|
||||
(s, e) =>
|
||||
Open(
|
||||
SpeckleOperationWizard.SelectedAccount.serverInfo.url,
|
||||
SpeckleOperationWizard.SelectedProject.id,
|
||||
SpeckleOperationWizard.SelectedModel?.id,
|
||||
SpeckleOperationWizard.SelectedVersion?.id
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static void Open(string server, string projectId, string? modelId, string? versionId)
|
||||
{
|
||||
string url =
|
||||
$"{server}/projects/{projectId}/models/{(modelId is null ? "" : modelId)}{(versionId is null ? "" : $"@{versionId}")}";
|
||||
var psi = new ProcessStartInfo { FileName = url, UseShellExecute = true };
|
||||
Process.Start(psi);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Write(GH_IWriter writer)
|
||||
|
||||
+1
@@ -71,6 +71,7 @@ public class ModelMenuHandler
|
||||
|
||||
private bool PopulateMenu(ToolStripDropDown menu)
|
||||
{
|
||||
menu.LayoutStyle = ToolStripLayoutStyle.VerticalStackWithOverflow;
|
||||
_menu = menu;
|
||||
_searchItem = new SearchToolStripMenuItem(menu, Refetch);
|
||||
|
||||
|
||||
+1
@@ -71,6 +71,7 @@ public class ProjectMenuHandler
|
||||
|
||||
private bool PopulateMenu(ToolStripDropDown menu)
|
||||
{
|
||||
menu.LayoutStyle = ToolStripLayoutStyle.VerticalStackWithOverflow;
|
||||
_menu = menu;
|
||||
_searchItem = new SearchToolStripMenuItem(menu, Refetch);
|
||||
|
||||
|
||||
+17
-14
@@ -16,6 +16,7 @@ public class SearchToolStripMenuItem
|
||||
|
||||
public SearchToolStripMenuItem(ToolStripDropDown parent, Func<string, Task> onSearchTextChanged)
|
||||
{
|
||||
parent.LayoutStyle = ToolStripLayoutStyle.VerticalStackWithOverflow;
|
||||
ParentDropDown = parent;
|
||||
ParentDropDown.Opacity = 0.95;
|
||||
ParentDropDown.TopLevel = true;
|
||||
@@ -38,9 +39,11 @@ public class SearchToolStripMenuItem
|
||||
{
|
||||
var item = new ToolStripMenuItem(text)
|
||||
{
|
||||
TextAlign = ContentAlignment.MiddleLeft,
|
||||
Checked = isChecked ?? false,
|
||||
Image = image,
|
||||
ImageScaling = ToolStripItemImageScaling.SizeToFit
|
||||
ImageScaling = ToolStripItemImageScaling.SizeToFit,
|
||||
ImageAlign = ContentAlignment.MiddleLeft
|
||||
};
|
||||
item.Click += click;
|
||||
if (visible == false)
|
||||
@@ -60,10 +63,10 @@ public class SearchToolStripMenuItem
|
||||
{
|
||||
var textBox = new TextBox
|
||||
{
|
||||
BorderStyle = BorderStyle.None,
|
||||
Width = 600,
|
||||
Font = new Font("Segoe UI", 9),
|
||||
TextAlign = HorizontalAlignment.Left,
|
||||
BorderStyle = BorderStyle.None,
|
||||
Width = ParentDropDown.Width,
|
||||
Font = new Font("Segoe UI", 9),
|
||||
Text = SEARCH_PLACEHOLDER_TEXT,
|
||||
BackColor = Color.White,
|
||||
};
|
||||
@@ -105,10 +108,10 @@ public class SearchToolStripMenuItem
|
||||
|
||||
SearchHost = new ToolStripControlHost(textBox)
|
||||
{
|
||||
Alignment = ToolStripItemAlignment.Left,
|
||||
ControlAlign = ContentAlignment.MiddleLeft,
|
||||
Name = SearchItemId,
|
||||
AutoSize = false,
|
||||
Size = new Size(170, 24),
|
||||
Margin = new Padding(4),
|
||||
Margin = new Padding(2),
|
||||
Padding = new Padding(2)
|
||||
};
|
||||
|
||||
@@ -118,12 +121,6 @@ public class SearchToolStripMenuItem
|
||||
|
||||
private void RegisterEvents()
|
||||
{
|
||||
// Resets the search filter
|
||||
// ParentDropDown.Opening += async (sender, args) =>
|
||||
// {
|
||||
// await _onSearchTextChanged.Invoke("");
|
||||
// };
|
||||
|
||||
ParentDropDown.ItemClicked += (sender, args) =>
|
||||
{
|
||||
// we are not closing the dropdown only if user clicked the first item of the dropdown which is TextBox that we use for search
|
||||
@@ -135,8 +132,14 @@ public class SearchToolStripMenuItem
|
||||
ParentDropDown.Close();
|
||||
};
|
||||
|
||||
ParentDropDown.Closed += (sender, args) =>
|
||||
// Resets the list with empty search texts, otherwise on next menu pop up we end up with latest state
|
||||
ParentDropDown.Closed += async (sender, args) =>
|
||||
{
|
||||
// clear list only if search text is not null
|
||||
if (SearchText != null)
|
||||
{
|
||||
await _onSearchTextChanged.Invoke("");
|
||||
}
|
||||
SearchText = null;
|
||||
};
|
||||
}
|
||||
|
||||
+15
-9
@@ -26,6 +26,7 @@ public class SpeckleOperationWizard
|
||||
public Project? SelectedProject { get; private set; }
|
||||
public Model? SelectedModel { get; private set; }
|
||||
public Version? SelectedVersion { get; private set; }
|
||||
public bool IsLatestVersion { get; private set; }
|
||||
|
||||
public WorkspaceMenuHandler WorkspaceMenuHandler { get; }
|
||||
public ProjectMenuHandler ProjectMenuHandler { get; }
|
||||
@@ -65,13 +66,17 @@ public class SpeckleOperationWizard
|
||||
ModelMenuHandler.ModelSelected += OnModelSelected;
|
||||
}
|
||||
|
||||
public (SpeckleUrlModelResource resource, bool hasPermission) SolveInstanceWithUrlInput(string input, bool isSender)
|
||||
public (SpeckleUrlModelResource resource, bool hasPermission) SolveInstanceWithUrlInput(
|
||||
string input,
|
||||
bool isSender,
|
||||
string? token
|
||||
)
|
||||
{
|
||||
// When input is provided, lock interaction of buttons so only text is shown (no context menu)
|
||||
// Should perform validation, fill in all internal data of the component (project, model, version, account)
|
||||
// Should notify user if any of this goes wrong.
|
||||
|
||||
var resources = SpeckleResourceBuilder.FromUrlString(input);
|
||||
var resources = SpeckleResourceBuilder.FromUrlString(input, token);
|
||||
if (resources.Length == 0)
|
||||
{
|
||||
throw new SpeckleException($"Input url string was empty");
|
||||
@@ -83,8 +88,8 @@ public class SpeckleOperationWizard
|
||||
}
|
||||
|
||||
var resource = resources.First();
|
||||
|
||||
var account = _accountService.GetAccountWithServerUrlFallback(string.Empty, new Uri(resource.Server));
|
||||
using var scope = PriorityLoader.CreateScopeForActiveDocument();
|
||||
var account = resource.Account.GetAccount(scope);
|
||||
SetAccount(account, false);
|
||||
|
||||
if (SelectedAccount == null)
|
||||
@@ -116,7 +121,7 @@ public class SpeckleOperationWizard
|
||||
|
||||
// TODO: this wont be the case when we have separation between send and receive components
|
||||
var v = client.Version.Get(versionResource.VersionId, versionResource.ProjectId).Result;
|
||||
VersionMenuHandler?.RedrawMenuButton(v);
|
||||
VersionMenuHandler?.RedrawMenuButton(v, false);
|
||||
break;
|
||||
case SpeckleUrlModelObjectResource:
|
||||
throw new SpeckleException("Object URLs are not supported");
|
||||
@@ -238,7 +243,7 @@ public class SpeckleOperationWizard
|
||||
using IClient client = _clientFactory.Create(SelectedAccount);
|
||||
var version = client.Version.Get(versionId, SelectedProject.id).Result;
|
||||
SelectedVersion = version;
|
||||
VersionMenuHandler?.RedrawMenuButton(SelectedVersion);
|
||||
VersionMenuHandler?.RedrawMenuButton(SelectedVersion, IsLatestVersion);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -438,13 +443,14 @@ public class SpeckleOperationWizard
|
||||
private void OnModelSelected(object sender, ModelSelectedEventArgs e)
|
||||
{
|
||||
SelectedModel = e.SelectedModel;
|
||||
ResetVersions();
|
||||
ResetVersions(true);
|
||||
_refreshComponent.Invoke();
|
||||
}
|
||||
|
||||
private void OnVersionSelected(object sender, VersionSelectedEventArgs e)
|
||||
{
|
||||
SelectedVersion = e.SelectedVersion;
|
||||
IsLatestVersion = e.IsLatest;
|
||||
_refreshComponent.Invoke();
|
||||
}
|
||||
|
||||
@@ -469,10 +475,10 @@ public class SpeckleOperationWizard
|
||||
ResetVersions();
|
||||
}
|
||||
|
||||
private void ResetVersions()
|
||||
private void ResetVersions(bool defaultToLatest = false)
|
||||
{
|
||||
SelectedVersion = null;
|
||||
VersionMenuHandler?.Reset();
|
||||
VersionMenuHandler?.Reset(defaultToLatest);
|
||||
}
|
||||
|
||||
private Task CreateNewWorkspace()
|
||||
|
||||
+23
-20
@@ -1,11 +1,12 @@
|
||||
using Speckle.Sdk.Api.GraphQL.Models;
|
||||
using Speckle.Sdk.Api.GraphQL.Models;
|
||||
using Version = Speckle.Sdk.Api.GraphQL.Models.Version;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.Operations.Wizard;
|
||||
|
||||
public class VersionSelectedEventArgs(Version? version) : EventArgs
|
||||
public class VersionSelectedEventArgs(Version? version, bool isLatest) : EventArgs
|
||||
{
|
||||
public Version? SelectedVersion { get; } = version;
|
||||
public bool IsLatest { get; } = isLatest;
|
||||
}
|
||||
|
||||
public class VersionMenuHandler
|
||||
@@ -14,6 +15,7 @@ public class VersionMenuHandler
|
||||
private readonly Func<int, Task<ResourceCollection<Version>>> _fetchVersions;
|
||||
private ToolStripDropDown? _menu;
|
||||
private Version? SelectedVersion { get; set; }
|
||||
public bool IsLatest { get; set; }
|
||||
|
||||
public ResourceCollection<Version>? Versions { get; set; }
|
||||
|
||||
@@ -32,14 +34,15 @@ public class VersionMenuHandler
|
||||
);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
public void Reset(bool isLatest = false)
|
||||
{
|
||||
_menu?.Items.Clear();
|
||||
_menu?.Close();
|
||||
IsLatest = isLatest;
|
||||
SelectedVersion = null;
|
||||
Versions = null;
|
||||
FetchedVersionCount = 10;
|
||||
RedrawMenuButton(null);
|
||||
RedrawMenuButton(null, isLatest);
|
||||
}
|
||||
|
||||
private async Task Refetch(int versionCount)
|
||||
@@ -50,6 +53,7 @@ public class VersionMenuHandler
|
||||
|
||||
private bool PopulateMenu(ToolStripDropDown menu)
|
||||
{
|
||||
menu.LayoutStyle = ToolStripLayoutStyle.VerticalStackWithOverflow;
|
||||
_menu = menu;
|
||||
|
||||
if (Versions is null)
|
||||
@@ -78,7 +82,7 @@ public class VersionMenuHandler
|
||||
return;
|
||||
}
|
||||
|
||||
AddMenuItem("Latest Version", (_, _) => OnVersionSelected(null), true, SelectedVersion == null);
|
||||
AddMenuItem("Latest Version", (_, _) => OnVersionSelected(null, true), true, SelectedVersion == null);
|
||||
AddMenuSeparator();
|
||||
|
||||
foreach (var version in Versions.items)
|
||||
@@ -87,7 +91,7 @@ public class VersionMenuHandler
|
||||
|
||||
var versionItem = AddMenuItem(
|
||||
$"{version.id} - {desc}",
|
||||
(_, _) => OnVersionSelected(version),
|
||||
(_, _) => OnVersionSelected(version, false),
|
||||
true,
|
||||
SelectedVersion?.id == version.id
|
||||
);
|
||||
@@ -122,8 +126,9 @@ public class VersionMenuHandler
|
||||
}
|
||||
}
|
||||
|
||||
public void RedrawMenuButton(Version? version)
|
||||
public void RedrawMenuButton(Version? version, bool isLatest)
|
||||
{
|
||||
IsLatest = isLatest;
|
||||
var suffix = VersionContextMenuButton.Enabled
|
||||
? "Left-click to select another version."
|
||||
: "Selection is disabled due to component input.";
|
||||
@@ -133,26 +138,21 @@ public class VersionMenuHandler
|
||||
VersionContextMenuButton.NickName = version.id;
|
||||
VersionContextMenuButton.Description = $"{version.message ?? "No message"}\n\n{suffix}";
|
||||
}
|
||||
// else if (_model != null)
|
||||
// {
|
||||
// VersionContextMenuButton.NickName = "Latest Version";
|
||||
// VersionContextMenuButton.Name = "Latest Version";
|
||||
// VersionContextMenuButton.Description = "Gets the latest version from the selected model";
|
||||
// }
|
||||
else
|
||||
{
|
||||
VersionContextMenuButton.Name = "Select Version";
|
||||
VersionContextMenuButton.Name = IsLatest ? "Latest Version" : "Select Version";
|
||||
VersionContextMenuButton.NickName = "Version";
|
||||
VersionContextMenuButton.Description = "Left-click to select version";
|
||||
VersionContextMenuButton.Description = "Left-click to select a specific version";
|
||||
}
|
||||
}
|
||||
|
||||
private void OnVersionSelected(Version? version)
|
||||
private void OnVersionSelected(Version? version, bool isLatest)
|
||||
{
|
||||
_menu?.Close();
|
||||
SelectedVersion = version;
|
||||
RedrawMenuButton(SelectedVersion);
|
||||
VersionSelected?.Invoke(this, new VersionSelectedEventArgs(version));
|
||||
IsLatest = isLatest;
|
||||
RedrawMenuButton(SelectedVersion, isLatest);
|
||||
VersionSelected?.Invoke(this, new VersionSelectedEventArgs(version, isLatest));
|
||||
}
|
||||
|
||||
private ToolStripMenuItem AddMenuItem(
|
||||
@@ -162,7 +162,7 @@ public class VersionMenuHandler
|
||||
bool? isChecked = null
|
||||
)
|
||||
{
|
||||
var item = new ToolStripMenuItem(text) { Checked = isChecked ?? false };
|
||||
var item = new ToolStripMenuItem(text) { Checked = isChecked ?? false, TextAlign = ContentAlignment.MiddleLeft };
|
||||
item.Click += click;
|
||||
if (visible == false)
|
||||
{
|
||||
@@ -173,5 +173,8 @@ public class VersionMenuHandler
|
||||
return item;
|
||||
}
|
||||
|
||||
private void AddMenuSeparator() => _menu?.Items.Add(new ToolStripSeparator());
|
||||
private void AddMenuSeparator()
|
||||
{
|
||||
_menu?.Items.Add(new ToolStripSeparator());
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -1,4 +1,4 @@
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Drawing2D;
|
||||
using Speckle.Sdk.Api.GraphQL.Models;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.Operations.Wizard;
|
||||
@@ -56,6 +56,7 @@ public class WorkspaceMenuHandler
|
||||
|
||||
private bool PopulateMenu(ToolStripDropDown menu)
|
||||
{
|
||||
menu.LayoutStyle = ToolStripLayoutStyle.VerticalStackWithOverflow;
|
||||
_menu = menu;
|
||||
_searchItem = new SearchToolStripMenuItem(menu, Refetch);
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
using Grasshopper.Kernel;
|
||||
using Speckle.Connectors.GrasshopperShared.Properties;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.HostApp.Extras;
|
||||
|
||||
public class ListAccessStateTag : GH_StateTag
|
||||
{
|
||||
public override string Description => "This parameter is set to List access";
|
||||
public override string Name => "List Access";
|
||||
public override Bitmap Icon => Resources.speckle_state_access;
|
||||
}
|
||||
@@ -96,16 +96,128 @@ public static class GrasshopperHelpers
|
||||
return t;
|
||||
}
|
||||
|
||||
public static Matrix4x4 TransformToMatrix(Transform rhinoTransform, string? units)
|
||||
{
|
||||
var currentDoc = RhinoDoc.ActiveDoc; // POC: too much right now to interface around
|
||||
var conversionFactor = Units.GetConversionFactor(currentDoc.ModelUnitSystem.ToSpeckleString(), units);
|
||||
|
||||
var m = new Matrix4x4
|
||||
{
|
||||
M11 = rhinoTransform.M00,
|
||||
M12 = rhinoTransform.M01,
|
||||
M13 = rhinoTransform.M02,
|
||||
M14 = rhinoTransform.M03 * conversionFactor,
|
||||
|
||||
M21 = rhinoTransform.M10,
|
||||
M22 = rhinoTransform.M11,
|
||||
M23 = rhinoTransform.M12,
|
||||
M24 = rhinoTransform.M13 * conversionFactor,
|
||||
|
||||
M31 = rhinoTransform.M20,
|
||||
M32 = rhinoTransform.M21,
|
||||
M33 = rhinoTransform.M22,
|
||||
M34 = rhinoTransform.M23 * conversionFactor,
|
||||
|
||||
M41 = rhinoTransform.M30,
|
||||
M42 = rhinoTransform.M31,
|
||||
M43 = rhinoTransform.M32,
|
||||
M44 = rhinoTransform.M33
|
||||
};
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all of the atomic objects inside a collection wrapper.
|
||||
/// </summary>
|
||||
/// <param name="coll"></param>
|
||||
/// <param name="recurse">Will recurse into sub collections to get atomic objects</param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<SpeckleWrapper> GetAtomicObjects(this SpeckleCollectionWrapper coll, bool recurse = false)
|
||||
{
|
||||
foreach (var element in coll.Elements)
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case SpeckleDataObjectWrapper dataObject:
|
||||
yield return dataObject;
|
||||
break;
|
||||
case SpeckleGeometryWrapper geo: // covers both instances and geo
|
||||
yield return geo;
|
||||
break;
|
||||
case SpeckleCollectionWrapper subColl:
|
||||
if (recurse)
|
||||
{
|
||||
foreach (var subElement in subColl.GetAtomicObjects(recurse))
|
||||
{
|
||||
yield return subElement;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to cast an IGH_Goo to a Speckle Geometry Wrapper
|
||||
/// </summary>
|
||||
/// <param name="goo"></param>
|
||||
/// <returns>A reference to the Speckle Geometry Wrapper from the goo, if any</returns>
|
||||
/// <remarks>This method **does not** deep copy the return value</remarks>
|
||||
public static SpeckleGeometryWrapper? ToSpeckleGeometryWrapper(this IGH_Goo goo)
|
||||
{
|
||||
SpeckleBlockInstanceWrapperGoo instanceGoo = new();
|
||||
if (instanceGoo.CastFrom(goo))
|
||||
{
|
||||
return instanceGoo.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
SpeckleGeometryWrapperGoo objGoo = new();
|
||||
return objGoo.CastFrom(goo) ? objGoo.Value : null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to cast an IGH_Goo to a Speckle Geometry or DataObject Wrapper
|
||||
/// </summary>
|
||||
/// <param name="goo"></param>
|
||||
/// <returns>A reference to the Speckle Wrapper from the goo, if any</returns>
|
||||
/// <remarks>This method **does not** deep copy the return value</remarks>
|
||||
public static SpeckleWrapper? ToSpeckleObjectWrapper(this IGH_Goo goo)
|
||||
{
|
||||
// first preserve data objects as they are
|
||||
// this is processed first because data objects with 1 display value can be cast to geometry wrappers
|
||||
if (goo is SpeckleDataObjectWrapperGoo dataObject)
|
||||
{
|
||||
return dataObject.Value;
|
||||
}
|
||||
|
||||
// then try to process as geometry
|
||||
SpeckleBlockInstanceWrapperGoo instanceGoo = new();
|
||||
if (instanceGoo.CastFrom(goo))
|
||||
{
|
||||
return instanceGoo.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
SpeckleGeometryWrapperGoo objGoo = new();
|
||||
return objGoo.CastFrom(goo) ? objGoo.Value : null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to cast the goo to a geometry base object.
|
||||
/// </summary>
|
||||
/// <param name="geoGeo"></param>
|
||||
/// <param name="geoGoo"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="SpeckleException">If it fails to cast</exception>
|
||||
public static GeometryBase GeometricGooToGeometryBase(this IGH_GeometricGoo geoGeo)
|
||||
public static GeometryBase ToGeometryBase(this IGH_GeometricGoo geoGoo)
|
||||
{
|
||||
// note: some objects (like text entities) can have multiple properties of name "Value"
|
||||
var value = geoGeo.GetType().GetProperties().FirstOrDefault(x => x.Name == "Value")?.GetValue(geoGeo);
|
||||
var value = geoGoo.GetType().GetProperties().FirstOrDefault(x => x.Name == "Value")?.GetValue(geoGoo);
|
||||
switch (value)
|
||||
{
|
||||
case GeometryBase gb:
|
||||
|
||||
+7
-5
@@ -12,13 +12,13 @@ namespace Speckle.Connectors.GrasshopperShared.HostApp;
|
||||
/// </summary>
|
||||
public static class SpeckleConversionContext
|
||||
{
|
||||
public static Base ConvertToSpeckle(GeometryBase geo)
|
||||
public static Base ConvertToSpeckle(object geo)
|
||||
{
|
||||
using var scope = PriorityLoader.CreateScopeForActiveDocument();
|
||||
return scope.ServiceProvider.GetRequiredService<IRootToSpeckleConverter>().Convert(geo);
|
||||
}
|
||||
|
||||
public static List<(GeometryBase, Base)> ConvertToHost(Base input)
|
||||
public static List<(object, Base)> ConvertToHost(Base input)
|
||||
{
|
||||
using var scope = PriorityLoader.CreateScopeForActiveDocument();
|
||||
var result = scope.ServiceProvider.GetRequiredService<IRootToHostConverter>().Convert(input);
|
||||
@@ -26,9 +26,11 @@ public static class SpeckleConversionContext
|
||||
return result switch
|
||||
{
|
||||
GeometryBase geometry => [(geometry, input)],
|
||||
List<GeometryBase> geometryList => geometryList.Select(o => (o, input)).ToList(),
|
||||
IEnumerable<(GeometryBase, Base)> fallbackConversionResult => fallbackConversionResult.ToList(),
|
||||
_ => throw new SpeckleException("Failed to convert input to rhino")
|
||||
List<GeometryBase> geometryList => geometryList.Select(o => ((object)o, input)).ToList(),
|
||||
IEnumerable<(GeometryBase, Base)> fallbackConversionResult
|
||||
=> fallbackConversionResult.Select(o => ((object)o.Item1, o.Item2)).ToList(),
|
||||
object obj => [(obj, input)],
|
||||
_ => throw new SpeckleException("Failed to convert input to grasshopper")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Connectors.GrasshopperShared.Components.Operations.Receive;
|
||||
using Speckle.Connectors.GrasshopperShared.Components.Operations.Send;
|
||||
using Speckle.Connectors.GrasshopperShared.Registration;
|
||||
using Speckle.Sdk.Api;
|
||||
using Speckle.Sdk.Api.GraphQL.Models;
|
||||
using Speckle.Sdk.Common;
|
||||
using Speckle.Sdk.Credentials;
|
||||
using Version = Speckle.Sdk.Api.GraphQL.Models.Version;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.HostApp;
|
||||
|
||||
// noting that if the user inputs a model url string, this will not contain account info
|
||||
// (and that's why the accountID is nullable in the record resource)
|
||||
public abstract record SpeckleUrlModelResource(string? AccountId, string Server, string? WorkspaceId, string ProjectId)
|
||||
public abstract record SpeckleUrlModelResource(AccountResource Account, string? WorkspaceId, string ProjectId)
|
||||
{
|
||||
public abstract Task<GrasshopperReceiveInfo> GetReceiveInfo(
|
||||
IClient client,
|
||||
@@ -20,12 +24,11 @@ public abstract record SpeckleUrlModelResource(string? AccountId, string Server,
|
||||
}
|
||||
|
||||
public record SpeckleUrlLatestModelVersionResource(
|
||||
string? AccountId,
|
||||
string Server,
|
||||
AccountResource Account,
|
||||
string? WorkspaceId,
|
||||
string ProjectId,
|
||||
string ModelId
|
||||
) : SpeckleUrlModelResource(AccountId, Server, WorkspaceId, ProjectId)
|
||||
) : SpeckleUrlModelResource(Account, WorkspaceId, ProjectId)
|
||||
{
|
||||
public override async Task<GrasshopperReceiveInfo> GetReceiveInfo(
|
||||
IClient client,
|
||||
@@ -39,8 +42,7 @@ public record SpeckleUrlLatestModelVersionResource(
|
||||
Version version = model.versions.items[0];
|
||||
|
||||
var info = new GrasshopperReceiveInfo(
|
||||
client.Account.id,
|
||||
new Uri(Server),
|
||||
client.Account,
|
||||
project.workspaceId,
|
||||
ProjectId,
|
||||
project.name,
|
||||
@@ -64,8 +66,7 @@ public record SpeckleUrlLatestModelVersionResource(
|
||||
await client.Model.Get(ModelId, ProjectId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return new GrasshopperSendInfo(
|
||||
client.Account.id,
|
||||
new Uri(Server),
|
||||
client.Account,
|
||||
WorkspaceId,
|
||||
ProjectId,
|
||||
ModelId,
|
||||
@@ -75,13 +76,12 @@ public record SpeckleUrlLatestModelVersionResource(
|
||||
}
|
||||
|
||||
public record SpeckleUrlModelVersionResource(
|
||||
string? AccountId,
|
||||
string Server,
|
||||
AccountResource Account,
|
||||
string? WorkspaceId,
|
||||
string ProjectId,
|
||||
string ModelId,
|
||||
string VersionId
|
||||
) : SpeckleUrlModelResource(AccountId, Server, WorkspaceId, ProjectId)
|
||||
) : SpeckleUrlModelResource(Account, WorkspaceId, ProjectId)
|
||||
{
|
||||
public override async Task<GrasshopperReceiveInfo> GetReceiveInfo(
|
||||
IClient client,
|
||||
@@ -93,8 +93,7 @@ public record SpeckleUrlModelVersionResource(
|
||||
Version version = await client.Version.Get(VersionId, ProjectId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var info = new GrasshopperReceiveInfo(
|
||||
client.Account.id,
|
||||
new Uri(Server),
|
||||
client.Account,
|
||||
project.workspaceId,
|
||||
ProjectId,
|
||||
project.name,
|
||||
@@ -118,8 +117,7 @@ public record SpeckleUrlModelVersionResource(
|
||||
await client.Model.Get(ModelId, ProjectId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return new GrasshopperSendInfo(
|
||||
client.Account.id,
|
||||
new Uri(Server),
|
||||
client.Account,
|
||||
WorkspaceId,
|
||||
ProjectId,
|
||||
ModelId,
|
||||
@@ -129,12 +127,11 @@ public record SpeckleUrlModelVersionResource(
|
||||
}
|
||||
|
||||
public record SpeckleUrlModelObjectResource(
|
||||
string? AccountId,
|
||||
string Server,
|
||||
AccountResource Account,
|
||||
string? WorkspaceId,
|
||||
string ProjectId,
|
||||
string ObjectId
|
||||
) : SpeckleUrlModelResource(AccountId, Server, WorkspaceId, ProjectId)
|
||||
) : SpeckleUrlModelResource(Account, WorkspaceId, ProjectId)
|
||||
{
|
||||
public override Task<GrasshopperReceiveInfo> GetReceiveInfo(
|
||||
IClient client,
|
||||
@@ -146,3 +143,17 @@ public record SpeckleUrlModelObjectResource(
|
||||
CancellationToken cancellationToken = default
|
||||
) => throw new NotImplementedException("Object Resources are not supported yet");
|
||||
}
|
||||
|
||||
public record AccountResource(string? AccountId, string? Token, string Server)
|
||||
{
|
||||
public Account? GetAccount(IServiceScope scope)
|
||||
{
|
||||
if (Token is not null)
|
||||
{
|
||||
return scope.Get<IAccountFactory>().CreateAccount(new Uri(Server), Token).GetAwaiter().GetResult();
|
||||
}
|
||||
return AccountId != null
|
||||
? scope.Get<IAccountManager>().GetAccount(AccountId)
|
||||
: scope.Get<IAccountService>().GetAccountWithServerUrlFallback("", new Uri(Server)); // fallback the account that matches with URL if a
|
||||
}
|
||||
}
|
||||
|
||||
+21
-8
@@ -13,16 +13,16 @@ public record SpeckleResourceBuilder
|
||||
@"/projects/(?<projectId>[\w\d]+)(?:/models/(?<model>[\w\d]+(?:@[\w\d]+)?)(?:,(?<additionalModels>[\w\d]+(?:@[\w\d]+)?))*)?"
|
||||
);
|
||||
|
||||
public static SpeckleUrlModelResource[] FromUrlString(string speckleModel)
|
||||
public static SpeckleUrlModelResource[] FromUrlString(string speckleModel, string? token)
|
||||
{
|
||||
var uri = new Uri(speckleModel);
|
||||
var serverUrl = uri.GetLeftPart(UriPartial.Authority);
|
||||
var match = s_fe2UrlRegex.Match(speckleModel);
|
||||
var result = ParseFe2RegexMatch(serverUrl, match);
|
||||
var result = ParseFe2RegexMatch(serverUrl, match, token);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static SpeckleUrlModelResource[] ParseFe2RegexMatch(string serverUrl, Match match)
|
||||
private static SpeckleUrlModelResource[] ParseFe2RegexMatch(string serverUrl, Match match, string? token)
|
||||
{
|
||||
var projectId = match.Groups["projectId"];
|
||||
var model = match.Groups["model"];
|
||||
@@ -48,7 +48,7 @@ public record SpeckleResourceBuilder
|
||||
throw new NotSupportedException("Federation model urls are not supported");
|
||||
}
|
||||
|
||||
var modelRes = GetUrlModelResource(null, serverUrl, null, projectId.Value, model.Value);
|
||||
var modelRes = GetUrlModelResource(null, token, serverUrl, null, projectId.Value, model.Value);
|
||||
|
||||
var result = new List<SpeckleUrlModelResource> { modelRes };
|
||||
|
||||
@@ -56,7 +56,14 @@ public record SpeckleResourceBuilder
|
||||
{
|
||||
foreach (Capture additionalModelsCapture in additionalModels.Captures)
|
||||
{
|
||||
var extraModel = GetUrlModelResource(null, serverUrl, null, projectId.Value, additionalModelsCapture.Value);
|
||||
var extraModel = GetUrlModelResource(
|
||||
null,
|
||||
token,
|
||||
serverUrl,
|
||||
null,
|
||||
projectId.Value,
|
||||
additionalModelsCapture.Value
|
||||
);
|
||||
result.Add(extraModel);
|
||||
}
|
||||
}
|
||||
@@ -66,6 +73,7 @@ public record SpeckleResourceBuilder
|
||||
|
||||
private static SpeckleUrlModelResource GetUrlModelResource(
|
||||
string? accountId,
|
||||
string? token,
|
||||
string serverUrl,
|
||||
string? workspaceId,
|
||||
string projectId,
|
||||
@@ -74,15 +82,20 @@ public record SpeckleResourceBuilder
|
||||
{
|
||||
if (modelValue.Length == 32)
|
||||
{
|
||||
return new SpeckleUrlModelObjectResource(accountId, serverUrl, workspaceId, projectId, modelValue); // Model value is an ObjectID
|
||||
return new SpeckleUrlModelObjectResource(new(accountId, token, serverUrl), workspaceId, projectId, modelValue); // Model value is an ObjectID
|
||||
}
|
||||
|
||||
if (!modelValue.Contains('@'))
|
||||
{
|
||||
return new SpeckleUrlLatestModelVersionResource(accountId, serverUrl, workspaceId, projectId, modelValue); // Model has no version attached
|
||||
return new SpeckleUrlLatestModelVersionResource(
|
||||
new(accountId, token, serverUrl),
|
||||
workspaceId,
|
||||
projectId,
|
||||
modelValue
|
||||
); // Model has no version attached
|
||||
}
|
||||
|
||||
var res = modelValue.Split('@');
|
||||
return new SpeckleUrlModelVersionResource(accountId, serverUrl, workspaceId, projectId, res[0], res[1]);
|
||||
return new SpeckleUrlModelVersionResource(new(accountId, token, serverUrl), workspaceId, projectId, res[0], res[1]);
|
||||
}
|
||||
}
|
||||
|
||||
+260
@@ -0,0 +1,260 @@
|
||||
using Rhino.Geometry;
|
||||
using Speckle.Connectors.Common.Operations.Receive;
|
||||
using Speckle.Connectors.GrasshopperShared.HostApp;
|
||||
using Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using Speckle.Sdk.Models.GraphTraversal;
|
||||
using Speckle.Sdk.Models.Instances;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Operations.Receive;
|
||||
|
||||
/// <summary>
|
||||
/// Reconstructs block instances and definitions from received proxies back into Grasshopper wrapper objects.
|
||||
/// Tracks and returns object IDs consumed by block definitions to prevent duplication in collection hierarchy.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Geometry objects that define blocks must already be converted and present in convertedObjectsMap at this stage.
|
||||
/// Follows Rhino's pattern where objects consumed by block definitions should not appear as standalone objects.
|
||||
/// </remarks>
|
||||
internal sealed class GrasshopperBlockUnpacker
|
||||
{
|
||||
private readonly TraversalContextUnpacker _traversalContextUnpacker;
|
||||
private readonly GrasshopperColorUnpacker _colorUnpacker;
|
||||
private readonly GrasshopperMaterialUnpacker _materialUnpacker;
|
||||
|
||||
public GrasshopperBlockUnpacker(
|
||||
TraversalContextUnpacker traversalContextUnpacker,
|
||||
GrasshopperColorUnpacker colorUnpacker,
|
||||
GrasshopperMaterialUnpacker materialUnpacker
|
||||
)
|
||||
{
|
||||
_traversalContextUnpacker = traversalContextUnpacker;
|
||||
_colorUnpacker = colorUnpacker;
|
||||
_materialUnpacker = materialUnpacker;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates block definitions and instances from receive pipeline, returning consumed object IDs.
|
||||
/// </summary>
|
||||
/// <returns>Set of object IDs that have been consumed by block definitions and should not appear standalone</returns>
|
||||
public HashSet<string> UnpackBlocks(
|
||||
IReadOnlyCollection<TraversalContext> blockComponents,
|
||||
IReadOnlyCollection<InstanceDefinitionProxy>? definitionProxies,
|
||||
Dictionary<string, SpeckleGeometryWrapper> convertedObjectsMap,
|
||||
GrasshopperCollectionRebuilder collectionRebuilder
|
||||
)
|
||||
{
|
||||
var consumedObjectIds = new HashSet<string>();
|
||||
var sortedComponents = ExtractAndSortBlocks(blockComponents, definitionProxies);
|
||||
|
||||
CreateBlocksInDependencyOrder(sortedComponents, convertedObjectsMap, collectionRebuilder, consumedObjectIds);
|
||||
|
||||
return consumedObjectIds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts blocks from TraversalContext and adds metadata definitions, then sorts by depth.
|
||||
/// Deepest definitions first, then instances, to handle nested hierarchies correctly.
|
||||
/// </summary>
|
||||
private List<(Collection[] path, IInstanceComponent component)> ExtractAndSortBlocks(
|
||||
IReadOnlyCollection<TraversalContext> blockComponents,
|
||||
IReadOnlyCollection<InstanceDefinitionProxy>? definitionProxies
|
||||
)
|
||||
{
|
||||
var allComponents = new List<(Collection[] path, IInstanceComponent component)>();
|
||||
|
||||
// Extract instances from traversal contexts
|
||||
foreach (var traversalContext in blockComponents)
|
||||
{
|
||||
if (traversalContext.Current is IInstanceComponent instanceComponent)
|
||||
{
|
||||
var collectionPath = _traversalContextUnpacker.GetCollectionPath(traversalContext).ToArray();
|
||||
allComponents.Add((collectionPath, instanceComponent));
|
||||
}
|
||||
}
|
||||
|
||||
// Add definition proxies from metadata (these don't have collection paths)
|
||||
if (definitionProxies != null)
|
||||
{
|
||||
foreach (var definitionProxy in definitionProxies)
|
||||
{
|
||||
allComponents.Add((Array.Empty<Collection>(), definitionProxy));
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by depth (deepest first) then by type (definitions before instances)
|
||||
return allComponents
|
||||
.OrderByDescending(x => x.component.maxDepth)
|
||||
.ThenBy(x => x.component is InstanceDefinitionProxy ? 0 : 1)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates definitions and instances in dependency order, populating convertedObjectsMap
|
||||
/// with instances as they're created (following Rhino's applicationIdMap pattern).
|
||||
/// </summary>
|
||||
private void CreateBlocksInDependencyOrder(
|
||||
List<(Collection[] path, IInstanceComponent component)> sortedComponents,
|
||||
Dictionary<string, SpeckleGeometryWrapper> convertedObjectsMap,
|
||||
GrasshopperCollectionRebuilder collectionRebuilder,
|
||||
HashSet<string> consumedObjectIds
|
||||
)
|
||||
{
|
||||
var definitions = new Dictionary<string, SpeckleBlockDefinitionWrapper>();
|
||||
|
||||
// NOTE: This relies on ExtractAndSortBlocks to have done its job correctly!
|
||||
foreach (var (collectionPath, component) in sortedComponents)
|
||||
{
|
||||
if (component is InstanceDefinitionProxy definitionProxy)
|
||||
{
|
||||
// Create definition using current state of convertedObjectsMap
|
||||
var definitionId = definitionProxy.applicationId ?? definitionProxy.id ?? Guid.NewGuid().ToString();
|
||||
var definition = CreateBlockDefinitionWrapper(
|
||||
definitionProxy,
|
||||
definitionId,
|
||||
convertedObjectsMap,
|
||||
consumedObjectIds
|
||||
);
|
||||
if (definition != null)
|
||||
{
|
||||
definitions[definitionId] = definition;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: throw?
|
||||
}
|
||||
}
|
||||
else if (component is InstanceProxy instanceProxy)
|
||||
{
|
||||
// Create instance using available definitions
|
||||
string instanceId = instanceProxy.applicationId ?? instanceProxy.id ?? Guid.NewGuid().ToString();
|
||||
SpeckleBlockInstanceWrapper? instance = CreateBlockInstanceWrapper(
|
||||
instanceProxy,
|
||||
instanceId,
|
||||
definitions,
|
||||
_colorUnpacker,
|
||||
_materialUnpacker
|
||||
);
|
||||
if (instance != null)
|
||||
{
|
||||
AddInstanceToCollection(instance, collectionPath, collectionRebuilder);
|
||||
convertedObjectsMap[instanceId] = instance;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: throw?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="SpeckleBlockDefinitionWrapper"/> from its proxy using pre-converted defining objects.
|
||||
/// Tracks consumed object IDs to prevent duplication in collection hierarchy.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Objects used in block definitions are considered "consumed" and should not appear as standalone objects,
|
||||
/// matching Rhino's behavior where doc.Objects.Delete() removes consumed objects after block creation.
|
||||
/// </remarks>
|
||||
private SpeckleBlockDefinitionWrapper? CreateBlockDefinitionWrapper(
|
||||
InstanceDefinitionProxy definitionProxy,
|
||||
string definitionId,
|
||||
Dictionary<string, SpeckleGeometryWrapper> convertedObjectsMap,
|
||||
HashSet<string> consumedObjectIds
|
||||
)
|
||||
{
|
||||
var definitionObjects = new List<SpeckleGeometryWrapper>();
|
||||
var currentDefinitionObjectIds = new HashSet<string>();
|
||||
|
||||
foreach (var objectId in definitionProxy.objects)
|
||||
{
|
||||
if (convertedObjectsMap.TryGetValue(objectId, out var convertedObject))
|
||||
{
|
||||
definitionObjects.Add(convertedObject);
|
||||
currentDefinitionObjectIds.Add(objectId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: throw?
|
||||
}
|
||||
}
|
||||
|
||||
// Only create definition if we have objects
|
||||
if (definitionObjects.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Track consumed objects (matches Rhino's consumedObjectIds.UnionWith pattern)
|
||||
consumedObjectIds.UnionWith(currentDefinitionObjectIds);
|
||||
|
||||
return new SpeckleBlockDefinitionWrapper
|
||||
{
|
||||
Base = definitionProxy,
|
||||
Name = definitionProxy.name,
|
||||
Objects = definitionObjects,
|
||||
ApplicationId = definitionId
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="SpeckleBlockInstanceWrapper"/> from its proxy using.
|
||||
/// </summary>
|
||||
private SpeckleBlockInstanceWrapper? CreateBlockInstanceWrapper(
|
||||
InstanceProxy instanceProxy,
|
||||
string instanceId,
|
||||
Dictionary<string, SpeckleBlockDefinitionWrapper> definitions,
|
||||
GrasshopperColorUnpacker colorUnpacker,
|
||||
GrasshopperMaterialUnpacker materialUnpacker
|
||||
)
|
||||
{
|
||||
// Find the referenced definition
|
||||
if (!definitions.TryGetValue(instanceProxy.definitionId, out var definition))
|
||||
{
|
||||
return null; // Definition not found or failed to build
|
||||
}
|
||||
|
||||
Transform transform = GrasshopperHelpers.MatrixToTransform(instanceProxy.transform, instanceProxy.units);
|
||||
return new SpeckleBlockInstanceWrapper
|
||||
{
|
||||
Base = instanceProxy,
|
||||
Name = instanceProxy["name"] as string ?? "",
|
||||
ApplicationId = instanceId,
|
||||
Transform = transform,
|
||||
Definition = definition,
|
||||
GeometryBase = new InstanceReferenceGeometry(Guid.Empty, transform), //Instances shouldn't be using this except for the filter objects node,
|
||||
Color = colorUnpacker.Cache.TryGetValue(instanceProxy.applicationId ?? "", out var cachedInstanceColor)
|
||||
? cachedInstanceColor
|
||||
: null,
|
||||
Material = materialUnpacker.Cache.TryGetValue(instanceProxy.applicationId ?? "", out var cachedInstanceMaterial)
|
||||
? cachedInstanceMaterial
|
||||
: null,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an instance to the collection and sets up hierarchy relationships.
|
||||
/// </summary>
|
||||
private void AddInstanceToCollection(
|
||||
SpeckleBlockInstanceWrapper instance,
|
||||
Collection[] collectionPath,
|
||||
GrasshopperCollectionRebuilder collectionRebuilder
|
||||
)
|
||||
{
|
||||
var pathList = collectionPath.ToList();
|
||||
|
||||
// Get or create the target collection
|
||||
var targetCollection = collectionRebuilder.GetOrCreateSpeckleCollectionFromPath(
|
||||
pathList,
|
||||
_colorUnpacker,
|
||||
_materialUnpacker
|
||||
);
|
||||
|
||||
// Set up instance hierarchy properties
|
||||
instance.Path = pathList.Select(c => c.name).ToList();
|
||||
instance.Parent = targetCollection;
|
||||
|
||||
// Add to collection
|
||||
targetCollection.Elements.Add(instance);
|
||||
}
|
||||
}
|
||||
+35
-16
@@ -25,27 +25,12 @@ internal sealed class GrasshopperCollectionRebuilder
|
||||
}
|
||||
|
||||
public void AppendSpeckleGrasshopperObject(
|
||||
SpeckleObjectWrapper speckleGrasshopperObjectWrapper,
|
||||
ISpeckleCollectionObject speckleGrasshopperObjectWrapper,
|
||||
List<Collection> collectionPath,
|
||||
GrasshopperColorUnpacker colorUnpacker,
|
||||
GrasshopperMaterialUnpacker materialUnpacker
|
||||
)
|
||||
{
|
||||
// add the object color and material
|
||||
speckleGrasshopperObjectWrapper.Color = colorUnpacker.Cache.TryGetValue(
|
||||
speckleGrasshopperObjectWrapper.Base.applicationId ?? "",
|
||||
out var cachedColor
|
||||
)
|
||||
? cachedColor
|
||||
: null;
|
||||
|
||||
speckleGrasshopperObjectWrapper.Material = materialUnpacker.Cache.TryGetValue(
|
||||
speckleGrasshopperObjectWrapper.Base.applicationId ?? "",
|
||||
out var cachedMaterial
|
||||
)
|
||||
? cachedMaterial
|
||||
: null;
|
||||
|
||||
var collWrapper = GetOrCreateSpeckleCollectionFromPath(collectionPath, colorUnpacker, materialUnpacker);
|
||||
collWrapper.Elements.Add(speckleGrasshopperObjectWrapper);
|
||||
}
|
||||
@@ -110,4 +95,38 @@ internal sealed class GrasshopperCollectionRebuilder
|
||||
|
||||
return previousCollectionWrapper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes consumed objects from the collection hierarchy.
|
||||
/// Matches Rhino's pattern: createdObjectIds.RemoveWhere(id => consumedObjectIds.Contains(id))
|
||||
/// </summary>
|
||||
/// <param name="consumedObjectIds">Set of object IDs that have been consumed by block definitions</param>
|
||||
public void RemoveConsumedObjects(HashSet<string> consumedObjectIds)
|
||||
{
|
||||
if (consumedObjectIds.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveConsumedObjectsFromCollection(RootCollectionWrapper, consumedObjectIds);
|
||||
}
|
||||
|
||||
private static void RemoveConsumedObjectsFromCollection(
|
||||
SpeckleCollectionWrapper collection,
|
||||
HashSet<string> consumedObjectIds
|
||||
)
|
||||
{
|
||||
// Remove consumed objects from this level
|
||||
collection.Elements.RemoveAll(element =>
|
||||
element is SpeckleGeometryWrapper obj
|
||||
&& obj.ApplicationId != null
|
||||
&& consumedObjectIds.Contains(obj.ApplicationId)
|
||||
);
|
||||
|
||||
// Recurse into child collections
|
||||
foreach (var childCollection in collection.Elements.OfType<SpeckleCollectionWrapper>())
|
||||
{
|
||||
RemoveConsumedObjectsFromCollection(childCollection, consumedObjectIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-5
@@ -1,7 +1,6 @@
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Connectors.Logging;
|
||||
using Speckle.Sdk.Api;
|
||||
using Speckle.Sdk.Credentials;
|
||||
using Speckle.Sdk.Logging;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Transports;
|
||||
@@ -10,7 +9,6 @@ namespace Speckle.Connectors.GrasshopperShared.Operations.Receive;
|
||||
|
||||
public class GrasshopperReceiveOperation
|
||||
{
|
||||
private readonly IAccountService _accountService;
|
||||
private readonly IServerTransportFactory _serverTransportFactory;
|
||||
private readonly IProgressDisplayManager _progressDisplayManager;
|
||||
private readonly ISdkActivityFactory _activityFactory;
|
||||
@@ -18,7 +16,6 @@ public class GrasshopperReceiveOperation
|
||||
private readonly IClientFactory _clientFactory;
|
||||
|
||||
public GrasshopperReceiveOperation(
|
||||
IAccountService accountService,
|
||||
IServerTransportFactory serverTransportFactory,
|
||||
IProgressDisplayManager progressDisplayManager,
|
||||
ISdkActivityFactory activityFactory,
|
||||
@@ -26,7 +23,6 @@ public class GrasshopperReceiveOperation
|
||||
IClientFactory clientFactory
|
||||
)
|
||||
{
|
||||
_accountService = accountService;
|
||||
_serverTransportFactory = serverTransportFactory;
|
||||
_progressDisplayManager = progressDisplayManager;
|
||||
_activityFactory = activityFactory;
|
||||
@@ -43,7 +39,7 @@ public class GrasshopperReceiveOperation
|
||||
using var execute = _activityFactory.Start("Receive Operation");
|
||||
execute?.SetTag("receiveInfo", receiveInfo);
|
||||
// 2 - Check account exist
|
||||
Account account = _accountService.GetAccountWithServerUrlFallback(receiveInfo.AccountId, receiveInfo.ServerUrl);
|
||||
var account = receiveInfo.Account;
|
||||
using IClient apiClient = _clientFactory.Create(account);
|
||||
using var userScope = ActivityScope.SetTag(Consts.USER_ID, account.GetHashedEmail());
|
||||
|
||||
|
||||
+130
-62
@@ -1,17 +1,27 @@
|
||||
using Rhino.Geometry;
|
||||
using Speckle.Connectors.Common.Instances;
|
||||
using Speckle.Connectors.Common.Operations.Receive;
|
||||
using Speckle.Connectors.GrasshopperShared.HostApp;
|
||||
using Speckle.Connectors.GrasshopperShared.Operations.Receive;
|
||||
using Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
using Speckle.Sdk.Common.Exceptions;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.GraphTraversal;
|
||||
using Speckle.Sdk.Models.Instances;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Operations.Receive;
|
||||
|
||||
/// <summary>
|
||||
/// Handles conversion of atomic objects from TraversalContexts into Grasshopper wrapper objects.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Follows Rhino's approach: atomic objects are converted directly without pre-transformation,
|
||||
/// with instance transformations handled separately during block reconstruction. Implements consumedObjectIds
|
||||
/// tracking to prevent objects consumed by block definitions from appearing as standalone objects.
|
||||
/// </remarks>
|
||||
internal sealed class LocalToGlobalMapHandler
|
||||
{
|
||||
private readonly TraversalContextUnpacker _traversalContextUnpacker;
|
||||
public Dictionary<string, SpeckleGeometryWrapper> ConvertedObjectsMap { get; } = new();
|
||||
public readonly GrasshopperCollectionRebuilder CollectionRebuilder;
|
||||
|
||||
private readonly TraversalContextUnpacker _traversalContextUnpacker;
|
||||
private readonly GrasshopperColorUnpacker _colorUnpacker;
|
||||
private readonly GrasshopperMaterialUnpacker _materialUnpacker;
|
||||
|
||||
@@ -29,91 +39,149 @@ internal sealed class LocalToGlobalMapHandler
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a grasshopper speckle object from a local to global map, and appends it to the collection rebuilder.
|
||||
/// POC: TODO: this should decimate dataobjects into their display values, while storing the same properties etc
|
||||
/// This is because we don't want to be storing one-to-many maps in the object wrapper, this will complicate mutations
|
||||
/// Converts atomic object from TraversalContext to SpeckleObjectWrapper.
|
||||
/// </summary>
|
||||
/// <param name="map"></param>
|
||||
///
|
||||
public void CreateGrasshopperObjectFromMap(LocalToGlobalMap map)
|
||||
public void ConvertAtomicObject(TraversalContext atomicContext)
|
||||
{
|
||||
var obj = atomicContext.Current;
|
||||
var objId = obj.applicationId ?? obj.id;
|
||||
|
||||
if (objId == null || ConvertedObjectsMap.ContainsKey(objId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
List<(GeometryBase, Base)> converted = SpeckleConversionContext.ConvertToHost(map.AtomicObject);
|
||||
List<(object, Base)> converted = SpeckleConversionContext.ConvertToHost(obj);
|
||||
|
||||
if (converted.Count == 0)
|
||||
{
|
||||
return; // TODO: throw?
|
||||
return;
|
||||
}
|
||||
|
||||
// get the units and transform by matrices in the map
|
||||
string units = map.AtomicObject["units"] is string u
|
||||
? u
|
||||
: converted.First().Item2["units"] is string convertedU
|
||||
? convertedU
|
||||
: "none";
|
||||
var path = _traversalContextUnpacker.GetCollectionPath(atomicContext).ToList();
|
||||
|
||||
foreach (var matrix in map.Matrix)
|
||||
{
|
||||
var mat = GrasshopperHelpers.MatrixToTransform(matrix, units);
|
||||
converted.ForEach(res => res.Item1.Transform(mat));
|
||||
}
|
||||
|
||||
// get the collection
|
||||
var path = _traversalContextUnpacker.GetCollectionPath(map.TraversalContext).ToList();
|
||||
SpeckleCollectionWrapper objectCollection = CollectionRebuilder.GetOrCreateSpeckleCollectionFromPath(
|
||||
// Always create collection - consumed objects will be cleaned up later
|
||||
var objectCollection = CollectionRebuilder.GetOrCreateSpeckleCollectionFromPath(
|
||||
path,
|
||||
_colorUnpacker,
|
||||
_materialUnpacker
|
||||
);
|
||||
|
||||
// get the name and properties
|
||||
SpecklePropertyGroupGoo propertyGroup = new();
|
||||
string name = "";
|
||||
if (map.AtomicObject is Speckle.Objects.Data.DataObject da)
|
||||
if (obj is Speckle.Objects.Data.DataObject dataObject)
|
||||
{
|
||||
propertyGroup.CastFrom(da.properties);
|
||||
name = da.name;
|
||||
// get geometries
|
||||
List<SpeckleGeometryWrapper> geometries = new();
|
||||
foreach ((object convertedObj, Base original) in converted)
|
||||
{
|
||||
if (convertedObj is GeometryBase geometryBase)
|
||||
{
|
||||
SpeckleGeometryWrapper wrapper =
|
||||
new()
|
||||
{
|
||||
Base = original,
|
||||
GeometryBase = geometryBase,
|
||||
Color = _colorUnpacker.Cache.TryGetValue(original.applicationId ?? "", out var cachedObjColor)
|
||||
? cachedObjColor
|
||||
: null,
|
||||
Material = _materialUnpacker.Cache.TryGetValue(original.applicationId ?? "", out var cachedObjMaterial)
|
||||
? cachedObjMaterial
|
||||
: null,
|
||||
};
|
||||
|
||||
geometries.Add(wrapper);
|
||||
}
|
||||
}
|
||||
|
||||
SpecklePropertyGroupGoo propertyGroup = new();
|
||||
propertyGroup.CastFrom(dataObject.properties);
|
||||
|
||||
// remove the displayvalue of the original dataobject since these are now processed and stored on the wrapper
|
||||
// to prevent storing of duplicate Base
|
||||
dataObject.displayValue.Clear();
|
||||
|
||||
var dataObjectWrapper = new SpeckleDataObjectWrapper()
|
||||
{
|
||||
Base = dataObject,
|
||||
Geometries = geometries,
|
||||
Path = path.Select(p => p.name).ToList(),
|
||||
Parent = objectCollection,
|
||||
Name = dataObject.name,
|
||||
Properties = propertyGroup,
|
||||
ApplicationId = dataObject.applicationId,
|
||||
};
|
||||
|
||||
// Add to collections (not to map since these won't be definition objects)
|
||||
CollectionRebuilder.AppendSpeckleGrasshopperObject(dataObjectWrapper, path, _colorUnpacker, _materialUnpacker);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (map.AtomicObject[Constants.PROPERTIES_PROP] is Dictionary<string, object?> props)
|
||||
SpecklePropertyGroupGoo propertyGroup = new();
|
||||
if (obj[Constants.PROPERTIES_PROP] is Dictionary<string, object?> props)
|
||||
{
|
||||
propertyGroup.CastFrom(props);
|
||||
}
|
||||
|
||||
if (map.AtomicObject[Constants.NAME_PROP] is string n)
|
||||
foreach ((object convertedObj, Base original) in converted)
|
||||
{
|
||||
name = n;
|
||||
if (convertedObj is GeometryBase geometryBase)
|
||||
{
|
||||
var wrapper = new SpeckleGeometryWrapper()
|
||||
{
|
||||
Base = original,
|
||||
Path = path.Select(p => p.name).ToList(),
|
||||
Parent = objectCollection,
|
||||
GeometryBase = geometryBase,
|
||||
Properties = propertyGroup,
|
||||
Name = obj[Constants.NAME_PROP] as string ?? "",
|
||||
Color = _colorUnpacker.Cache.TryGetValue(original.applicationId ?? "", out var cachedObjColor)
|
||||
? cachedObjColor
|
||||
: null,
|
||||
Material = _materialUnpacker.Cache.TryGetValue(original.applicationId ?? "", out var cachedObjMaterial)
|
||||
? cachedObjMaterial
|
||||
: null,
|
||||
ApplicationId = objId
|
||||
};
|
||||
|
||||
// Always add to both map and collections
|
||||
ConvertedObjectsMap[objId] = wrapper;
|
||||
CollectionRebuilder.AppendSpeckleGrasshopperObject(wrapper, path, _colorUnpacker, _materialUnpacker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create objects for every value in converted. This is where one to many is not handled very nicely.
|
||||
// we will decimate dataobjects and multi-object display values here
|
||||
// meaning for every value in the display value, we will create a grasshopper wrapper, while preserving app id, name, props, etc
|
||||
// similar objects will be re-packaged on send
|
||||
foreach ((GeometryBase geometryBase, Base original) in converted)
|
||||
{
|
||||
var gh = new SpeckleObjectWrapper()
|
||||
{
|
||||
Base = original,
|
||||
Path = path.Select(p => p.name).ToList(),
|
||||
Parent = objectCollection,
|
||||
GeometryBase = geometryBase,
|
||||
Properties = propertyGroup,
|
||||
Name = name,
|
||||
Color = null,
|
||||
Material = null,
|
||||
WrapperGuid = map.AtomicObject.applicationId,
|
||||
ApplicationId = original.applicationId ?? Guid.NewGuid().ToString() // create if none
|
||||
};
|
||||
|
||||
CollectionRebuilder.AppendSpeckleGrasshopperObject(gh, path, _colorUnpacker, _materialUnpacker);
|
||||
}
|
||||
}
|
||||
catch (ConversionException)
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
// TODO
|
||||
// TODO: throw?
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts block instances and definitions from traversal contexts into Grasshopper wrapper objects.
|
||||
/// Automatically handles cleanup of consumed objects from the collection hierarchy.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Deliberately handles both block conversion AND consumed object cleanup in a single operation.
|
||||
/// Too much, I know, BUT it ensures the cleanup always occurs immediately after block processing without
|
||||
/// requiring receive components to call a separate cleanup method in the correct order.
|
||||
/// </remarks>
|
||||
public void ConvertBlockInstances(
|
||||
IReadOnlyCollection<TraversalContext> blocks,
|
||||
IReadOnlyCollection<InstanceDefinitionProxy>? definitionProxies
|
||||
)
|
||||
{
|
||||
var blockUnpacker = new GrasshopperBlockUnpacker(_traversalContextUnpacker, _colorUnpacker, _materialUnpacker);
|
||||
|
||||
// Get consumed object IDs from unpacker
|
||||
var consumedObjectIds = blockUnpacker.UnpackBlocks(
|
||||
blocks,
|
||||
definitionProxies,
|
||||
ConvertedObjectsMap,
|
||||
CollectionRebuilder
|
||||
);
|
||||
|
||||
// Clean up consumed objects from collections
|
||||
CollectionRebuilder.RemoveConsumedObjects(consumedObjectIds);
|
||||
}
|
||||
}
|
||||
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
using Speckle.Connectors.Common.Instances;
|
||||
using Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
using Speckle.Sdk.Models.Instances;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Operations.Send;
|
||||
|
||||
/// <summary>
|
||||
/// Processes block instances and their nested definitions for publish.
|
||||
/// Handles nested definitions and depth tracking (injected InstanceObjectsManager).
|
||||
/// </summary>
|
||||
internal sealed class GrasshopperBlockPacker
|
||||
{
|
||||
private readonly IInstanceObjectsManager<SpeckleGeometryWrapper, List<string>> _instanceObjectsManager;
|
||||
|
||||
public GrasshopperBlockPacker(IInstanceObjectsManager<SpeckleGeometryWrapper, List<string>> instanceObjectsManager)
|
||||
{
|
||||
_instanceObjectsManager = instanceObjectsManager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a map of instance definition id to instance definition proxy
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Storing <see cref="InstanceDefinitionProxy"/> directly and not the wrapper (matching Rhino).
|
||||
/// </remarks>
|
||||
public Dictionary<string, InstanceDefinitionProxy> InstanceDefinitionProxies { get; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Processes a <see cref="SpeckleBlockInstanceWrapper"/> by tracking it in InstanceObjectsManager and recursively
|
||||
/// processing its definition. Handles depth calculation for nested block hierarchies.
|
||||
/// </summary>
|
||||
/// <param name="blockInstance">The block instance to process</param>
|
||||
/// <param name="depth">Current nesting depth (0 = top level, increases for nested instances)</param>
|
||||
public List<SpeckleGeometryWrapper>? ProcessInstance(SpeckleBlockInstanceWrapper? blockInstance, int depth = 0)
|
||||
{
|
||||
if (blockInstance?.Definition == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
blockInstance.ApplicationId ??= Guid.NewGuid().ToString();
|
||||
var instanceId = blockInstance.ApplicationId;
|
||||
|
||||
blockInstance.InstanceProxy.maxDepth = depth;
|
||||
_instanceObjectsManager.AddInstanceProxy(instanceId, blockInstance.InstanceProxy);
|
||||
|
||||
return ProcessDefinition(blockInstance.Definition, depth);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes a block definition, adding it and its objects to InstanceObjectsManager.
|
||||
/// Updates maxDepth for existing definitions when encountered at greater depths.
|
||||
/// </summary>
|
||||
private List<SpeckleGeometryWrapper>? ProcessDefinition(SpeckleBlockDefinitionWrapper definition, int depth = 0)
|
||||
{
|
||||
// Use wrapper's id as definitive identifier. Create if empty.
|
||||
definition.ApplicationId ??= Guid.NewGuid().ToString();
|
||||
string definitionId = definition.ApplicationId;
|
||||
|
||||
// Check if already processed using InstanceObjectsManager
|
||||
if (
|
||||
_instanceObjectsManager.TryGetInstanceDefinitionProxy(definitionId, out InstanceDefinitionProxy? definitionProxy)
|
||||
)
|
||||
{
|
||||
int depthDifference = depth - definitionProxy.maxDepth;
|
||||
if (depthDifference > 0)
|
||||
{
|
||||
// Use InstanceObjectsManager to update max depth
|
||||
_instanceObjectsManager.UpdateChildrenMaxDepth(definitionProxy, depthDifference);
|
||||
}
|
||||
|
||||
return null; // this prevents infinite recursion
|
||||
}
|
||||
|
||||
// Process objects recursively
|
||||
var objectsToAdd = new List<SpeckleGeometryWrapper>();
|
||||
var currentObjectIds = new List<string>(); // Track current object IDs for proxy update
|
||||
|
||||
foreach (var obj in definition.Objects)
|
||||
{
|
||||
if (obj.ApplicationId == null) // we should be loud about this. If gone through all casting etc. this should be complete!
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Object in block definition '{definition.Name}' missing ApplicationId during send operation. This indicates a processing pipeline error."
|
||||
);
|
||||
}
|
||||
|
||||
objectsToAdd.Add(obj);
|
||||
currentObjectIds.Add(obj.ApplicationId); // Collect current ID
|
||||
_instanceObjectsManager.AddAtomicObject(obj.ApplicationId, obj);
|
||||
|
||||
if (obj is SpeckleBlockInstanceWrapper nestedInstance)
|
||||
{
|
||||
var nestedObjects = ProcessInstance(nestedInstance, depth + 1);
|
||||
if (nestedObjects != null)
|
||||
{
|
||||
objectsToAdd.AddRange(nestedObjects);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add definition to InstanceObjectsManager
|
||||
definition.InstanceDefinitionProxy.objects = currentObjectIds;
|
||||
definition.InstanceDefinitionProxy.maxDepth = depth;
|
||||
_instanceObjectsManager.AddDefinitionProxy(definitionId, definition.InstanceDefinitionProxy);
|
||||
InstanceDefinitionProxies[definitionId] = definition.InstanceDefinitionProxy;
|
||||
|
||||
return objectsToAdd;
|
||||
}
|
||||
}
|
||||
+137
-43
@@ -1,14 +1,26 @@
|
||||
using Speckle.Connectors.Common.Builders;
|
||||
using Speckle.Connectors.Common.Instances;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Connectors.GrasshopperShared.HostApp;
|
||||
using Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using DataObject = Speckle.Objects.Data.DataObject;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Operations.Send;
|
||||
|
||||
public class GrasshopperRootObjectBuilder() : IRootObjectBuilder<SpeckleCollectionWrapperGoo>
|
||||
public class GrasshopperRootObjectBuilder : IRootObjectBuilder<SpeckleCollectionWrapperGoo>
|
||||
{
|
||||
private readonly IInstanceObjectsManager<SpeckleGeometryWrapper, List<string>> _instanceObjectsManager;
|
||||
|
||||
// each Build() call gets a fresh scoped IInstanceObjectsManager
|
||||
public GrasshopperRootObjectBuilder(
|
||||
IInstanceObjectsManager<SpeckleGeometryWrapper, List<string>> instanceObjectsManager
|
||||
)
|
||||
{
|
||||
_instanceObjectsManager = instanceObjectsManager;
|
||||
}
|
||||
|
||||
// Keeps track of the wrapper applicationId of processed objects for send.
|
||||
// This is used to keep track of the following situations:
|
||||
// 1 - objects with the same name, properties, and application id are packaged into a data object. this can happen when receiving data objects.
|
||||
@@ -18,14 +30,11 @@ public class GrasshopperRootObjectBuilder() : IRootObjectBuilder<SpeckleCollecti
|
||||
|
||||
public Task<RootObjectBuilderResult> Build(
|
||||
IReadOnlyList<SpeckleCollectionWrapperGoo> input,
|
||||
SendInfo sendInfo,
|
||||
string projectId,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken ct = default
|
||||
)
|
||||
{
|
||||
// TODO: Send info is used in other connectors to get the project ID to populate the SendConversionCache
|
||||
Console.WriteLine($"Send Info {sendInfo}");
|
||||
|
||||
// deep copy input (to not mutate input) and set the input collection name to "Grasshopper Model"
|
||||
var inputCollectionGoo = (SpeckleCollectionWrapperGoo)input[0].Duplicate();
|
||||
inputCollectionGoo.Value.Name = "Grasshopper Model";
|
||||
@@ -33,13 +42,15 @@ public class GrasshopperRootObjectBuilder() : IRootObjectBuilder<SpeckleCollecti
|
||||
// create packers for colors and render materials
|
||||
GrasshopperColorPacker colorPacker = new();
|
||||
GrasshopperMaterialPacker materialPacker = new();
|
||||
GrasshopperBlockPacker blockPacker = new(_instanceObjectsManager);
|
||||
|
||||
// unwrap the input collection to remove all wrappers
|
||||
Collection root = Unwrap(inputCollectionGoo.Value, colorPacker, materialPacker);
|
||||
Collection root = Unwrap(inputCollectionGoo.Value, colorPacker, materialPacker, blockPacker);
|
||||
|
||||
// add proxies
|
||||
root[ProxyKeys.COLOR] = colorPacker.ColorProxies.Values.ToList();
|
||||
root[ProxyKeys.RENDER_MATERIAL] = materialPacker.RenderMaterialProxies.Values.ToList();
|
||||
root[ProxyKeys.INSTANCE_DEFINITION] = blockPacker.InstanceDefinitionProxies.Values.ToList();
|
||||
|
||||
// TODO: Not getting any conversion results yet
|
||||
var result = new RootObjectBuilderResult(root, []);
|
||||
@@ -47,46 +58,60 @@ public class GrasshopperRootObjectBuilder() : IRootObjectBuilder<SpeckleCollecti
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
// Unwraps collection wrappers and object wrapppers.
|
||||
// Also packs colors and Render Materials into proxies while unwrapping.
|
||||
// Unwraps collection wrappers and object wrappers.
|
||||
// Also packs colors, render materials and block definitions into proxies while unwrapping.
|
||||
private Collection Unwrap(
|
||||
SpeckleCollectionWrapper wrapper,
|
||||
GrasshopperColorPacker colorPacker,
|
||||
GrasshopperMaterialPacker materialPacker
|
||||
GrasshopperMaterialPacker materialPacker,
|
||||
GrasshopperBlockPacker blockPacker
|
||||
)
|
||||
{
|
||||
Collection currentColl = wrapper.Collection;
|
||||
|
||||
// unpack color and render material
|
||||
// unpack color, render material and block definitions
|
||||
colorPacker.ProcessColor(wrapper.ApplicationId, wrapper.Color);
|
||||
materialPacker.ProcessMaterial(wrapper.ApplicationId, wrapper.Material);
|
||||
|
||||
// iterate through this wrapper's elements to unwrap children
|
||||
// HashSet<string> collObjectIds = new();
|
||||
foreach (SpeckleWrapper wrapperElement in wrapper.Elements)
|
||||
foreach (ISpeckleCollectionObject element in wrapper.Elements)
|
||||
{
|
||||
if (wrapperElement is SpeckleCollectionWrapper collWrapper)
|
||||
switch (element)
|
||||
{
|
||||
// create an application id for this collection if none exists. This will be used for color and render material proxies
|
||||
collWrapper.ApplicationId ??= collWrapper.GetSpeckleApplicationId();
|
||||
case SpeckleCollectionWrapper collWrapper:
|
||||
// create an application id for this collection if none exists. This will be used for color and render material proxies
|
||||
collWrapper.ApplicationId ??= collWrapper.GetSpeckleApplicationId();
|
||||
|
||||
// add to collection and continue unwrap
|
||||
currentColl.elements.Add(collWrapper.Collection);
|
||||
Unwrap(collWrapper, colorPacker, materialPacker);
|
||||
}
|
||||
else if (wrapperElement is SpeckleObjectWrapper so)
|
||||
{
|
||||
// process the object first. This may result in application id mutations, so this must be done before processing color and materials.
|
||||
//ProcessObjectWrapper(so, ref collObjectIds);
|
||||
DataObject dataObject = ConvertWrappersToDataObject(
|
||||
new List<SpeckleObjectWrapper>() { so },
|
||||
Guid.NewGuid().ToString() // note: we are always generating a new id here, do *not* use the Base appid as this will cause conflicts in viewer for color and material proxy application
|
||||
);
|
||||
currentColl.elements.Add(dataObject);
|
||||
// add to collection and continue unwrap
|
||||
currentColl.elements.Add(collWrapper.Collection);
|
||||
Unwrap(collWrapper, colorPacker, materialPacker, blockPacker);
|
||||
break;
|
||||
|
||||
// unpack color and render material
|
||||
colorPacker.ProcessColor(so.ApplicationId, so.Color);
|
||||
materialPacker.ProcessMaterial(so.ApplicationId, so.Material);
|
||||
case SpeckleGeometryWrapper so: // handles both SpeckleObjectWrapper and SpeckleBlockInstanceWrapper (inheritance)
|
||||
// convert wrapper to base and add to collection - common for all object wrappers
|
||||
Base objectBase = UnwrapGeometry(so);
|
||||
string applicationId = objectBase.applicationId!;
|
||||
currentColl.elements.Add(objectBase);
|
||||
|
||||
// do block instance specific stuff (if this object wrapper is actually a block instance)
|
||||
if (so is SpeckleBlockInstanceWrapper blockInstance)
|
||||
{
|
||||
ProcessBlockInstanceDefinition(blockInstance, colorPacker, materialPacker, blockPacker, currentColl);
|
||||
}
|
||||
|
||||
// process color and material for all object wrappers (including block instances)
|
||||
colorPacker.ProcessColor(applicationId, so.Color);
|
||||
materialPacker.ProcessMaterial(applicationId, so.Material);
|
||||
break;
|
||||
|
||||
case SpeckleDataObjectWrapper dataObjectWrapper:
|
||||
// convert wrapper to DataObject and add to collection
|
||||
// UnwrapDataObject will unwrap underlying geometry and handle color and material
|
||||
// arguably doing too much, but I'm apprehensive looping twice without good reason
|
||||
DataObject dataObject = UnwrapDataObject(dataObjectWrapper, colorPacker, materialPacker);
|
||||
currentColl.elements.Add(dataObject);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,21 +130,90 @@ public class GrasshopperRootObjectBuilder() : IRootObjectBuilder<SpeckleCollecti
|
||||
return currentColl;
|
||||
}
|
||||
|
||||
// creates a data object from the input wrappers.
|
||||
// assumes these wrappers have been processed for similarity, so that the name and props of all wrappers are the same.
|
||||
private DataObject ConvertWrappersToDataObject(List<SpeckleObjectWrapper> wrappers, string appId)
|
||||
/// <summary>
|
||||
/// Converts a <see cref="SpeckleGeometryWrapper"/> to underlying Base object with dynamically attached properties.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// POC: if we move properties assignment to auto set the wrapped base, we can get rid of this entirely!
|
||||
/// </remarks>
|
||||
private Base UnwrapGeometry(SpeckleGeometryWrapper wrapper)
|
||||
{
|
||||
Dictionary<string, object?> props = new();
|
||||
|
||||
wrappers.First().Properties.CastTo<Dictionary<string, object?>>(ref props);
|
||||
|
||||
return new()
|
||||
Dictionary<string, object?> props = [];
|
||||
Base baseObject = wrapper.Base;
|
||||
if (wrapper.Properties.CastTo(ref props))
|
||||
{
|
||||
displayValue = wrappers.Select(o => o.Base).ToList(),
|
||||
name = wrappers.First().Name,
|
||||
properties = props,
|
||||
applicationId = appId
|
||||
};
|
||||
baseObject["properties"] = props; // setting props here on base since it's not auto-set, like name and appid
|
||||
}
|
||||
|
||||
return baseObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes a block instance's definition and adds the defining objects to the current collection.
|
||||
/// Handles nested block hierarchies and depth calculation via GrasshopperBlockPacker.
|
||||
/// </summary>
|
||||
private void ProcessBlockInstanceDefinition(
|
||||
SpeckleBlockInstanceWrapper blockInstance,
|
||||
GrasshopperColorPacker colorPacker,
|
||||
GrasshopperMaterialPacker materialPacker,
|
||||
GrasshopperBlockPacker blockPacker,
|
||||
Collection currentColl
|
||||
)
|
||||
{
|
||||
// NOTE: Depth calculation handled by GrasshopperBlockPacker.ProcessInstance()
|
||||
// Objects start with maxDepth=0, then updated during processing
|
||||
|
||||
// process block for definition collection and get defining objects
|
||||
var definitionObjects = blockPacker.ProcessInstance(blockInstance);
|
||||
|
||||
if (definitionObjects != null)
|
||||
{
|
||||
foreach (var definitionObject in definitionObjects)
|
||||
{
|
||||
Base defObjectBase = UnwrapGeometry(definitionObject);
|
||||
string applicationId = defObjectBase.applicationId!;
|
||||
|
||||
// just add to current collection for now
|
||||
currentColl.elements.Add(defObjectBase);
|
||||
|
||||
colorPacker.ProcessColor(applicationId, definitionObject.Color);
|
||||
materialPacker.ProcessMaterial(applicationId, definitionObject.Material);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a <see cref="SpeckleDataObjectWrapper"/> to underlying DataObject with properly configured displayValue.
|
||||
/// Processes colors and materials for each individual geometry during conversion.
|
||||
/// </summary>
|
||||
private DataObject UnwrapDataObject(
|
||||
SpeckleDataObjectWrapper wrapper,
|
||||
GrasshopperColorPacker colorPacker,
|
||||
GrasshopperMaterialPacker materialPacker
|
||||
)
|
||||
{
|
||||
DataObject dataObject = wrapper.DataObject;
|
||||
|
||||
// Convert geometries back to Base objects for displayValue
|
||||
var displayValue = new List<Base>();
|
||||
foreach (var geometryWrapper in wrapper.Geometries)
|
||||
{
|
||||
Base geometryBase = UnwrapGeometry(geometryWrapper);
|
||||
displayValue.Add(geometryBase);
|
||||
|
||||
// process color and material for each geometry while we're iterating
|
||||
// this could be in the switch statements (like SpeckleGeometryWrapper) but then we're unnecessarily looping twice
|
||||
if (geometryWrapper.ApplicationId != null)
|
||||
{
|
||||
colorPacker.ProcessColor(geometryWrapper.ApplicationId, geometryWrapper.Color);
|
||||
materialPacker.ProcessMaterial(geometryWrapper.ApplicationId, geometryWrapper.Material);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the DataObject's displayValue
|
||||
dataObject.displayValue = displayValue;
|
||||
|
||||
return dataObject;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
namespace Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
|
||||
public interface ISpecklePropertyGoo
|
||||
{
|
||||
bool Equals(ISpecklePropertyGoo other);
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Design",
|
||||
"CA1040:Avoid empty interfaces",
|
||||
Justification = "Needed to identify acceptable values of properties without multiple inheritance"
|
||||
Justification = "Needed to identify acceptable values of objects in collections"
|
||||
)]
|
||||
public interface ISpecklePropertyGoo { }
|
||||
public interface ISpeckleCollectionObject { }
|
||||
|
||||
-377
@@ -1,377 +0,0 @@
|
||||
using Grasshopper.Kernel;
|
||||
using Grasshopper.Kernel.Types;
|
||||
using Rhino;
|
||||
using Rhino.DocObjects;
|
||||
using Rhino.Geometry;
|
||||
using Speckle.Connectors.GrasshopperShared.Components;
|
||||
using Speckle.Connectors.GrasshopperShared.HostApp;
|
||||
using Speckle.Connectors.GrasshopperShared.Properties;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using Layer = Rhino.DocObjects.Layer;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
|
||||
/// <summary>
|
||||
/// A Wrapper class representing a Speckle Collection to Rhino Layer relationship.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When constructing, the following properties need to be set in order:
|
||||
/// <see cref="SpeckleWrapper.Base"/>, then <see cref="SpeckleWrapper.Name"/> and <see cref="SpeckleWrapper.ApplicationId"/>
|
||||
/// This is because chanbging the Name or ApplicationId will update Collection.
|
||||
/// </remarks>
|
||||
#pragma warning disable CA1711 // Identifiers should not have incorrect suffix
|
||||
public class SpeckleCollectionWrapper : SpeckleWrapper
|
||||
#pragma warning restore CA1711 // Identifiers should not have incorrect suffix
|
||||
{
|
||||
public override required Base Base
|
||||
{
|
||||
get => Collection;
|
||||
set
|
||||
{
|
||||
if (value is not Collection coll)
|
||||
{
|
||||
throw new ArgumentException("Cannot create collection wrapper from a non-Collection Base");
|
||||
}
|
||||
|
||||
Collection = coll;
|
||||
}
|
||||
}
|
||||
|
||||
public Collection Collection { get; set; }
|
||||
|
||||
private List<string> StoredPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of Collection names that build up the path to this collection (inclusive of <see cref="SpeckleWrapper.Name"/>;
|
||||
/// </summary>
|
||||
/// <remarks>Setting this property will update all element paths inside <see cref="Elements"/></remarks>
|
||||
public required List<string> Path
|
||||
{
|
||||
get => StoredPath;
|
||||
set
|
||||
{
|
||||
StoredPath = value;
|
||||
OnPathChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public List<SpeckleWrapper> Elements { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// The Grasshopper Topology of this collection. This setter also sets the "topology" prop dynamicall on <see cref="Collection"/>
|
||||
/// </summary>
|
||||
public string? Topology
|
||||
{
|
||||
get => Collection[Constants.TOPOLOGY_PROP] as string;
|
||||
set => Collection[Constants.TOPOLOGY_PROP] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The color of the <see cref="Base"/>
|
||||
/// </summary>
|
||||
public required Color? Color { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The material of the <see cref="Base"/>
|
||||
/// </summary>
|
||||
public required SpeckleMaterialWrapper? Material { get; set; }
|
||||
|
||||
public override string ToString() => $"{Name} [{Elements.Count}]";
|
||||
|
||||
/// <summary>
|
||||
/// Will attempt to retrieve an existing Layer from the <see cref="Path"/>.
|
||||
/// </summary>
|
||||
/// <returns>Index of existing layer if found, or -1 if not.</returns>
|
||||
public int GetLayerIndex() => RhinoDoc.ActiveDoc.Layers.FindByFullPath(string.Join("::", Path), -1);
|
||||
|
||||
// updates the elements' paths inside this collection
|
||||
private void OnPathChanged()
|
||||
{
|
||||
var newPath = StoredPath.ToList();
|
||||
|
||||
// then update paths and parents of all children
|
||||
foreach (var element in Elements)
|
||||
{
|
||||
if (element is SpeckleObjectWrapper o)
|
||||
{
|
||||
o.Path = newPath;
|
||||
o.Parent = this;
|
||||
}
|
||||
else if (element is SpeckleCollectionWrapper c)
|
||||
{
|
||||
// don't forget to add the child collection name to the path
|
||||
newPath.Add(c.Name);
|
||||
c.Path = newPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SpeckleCollectionWrapper DeepCopy() =>
|
||||
new()
|
||||
{
|
||||
Base = new Collection(Collection.name) { applicationId = Collection.applicationId, id = Collection.id },
|
||||
Color = Color,
|
||||
Material = Material,
|
||||
ApplicationId = ApplicationId,
|
||||
Name = Name,
|
||||
Path = Path,
|
||||
Topology = Topology,
|
||||
Elements = Elements
|
||||
.Select(e =>
|
||||
e is SpeckleCollectionWrapper c
|
||||
? c.DeepCopy()
|
||||
: e is SpeckleObjectWrapper o
|
||||
? o.DeepCopy()
|
||||
: e
|
||||
)
|
||||
.ToList()
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Bakes this collection as a layer, in its path structure.
|
||||
/// </summary>
|
||||
/// <param name="doc"></param>
|
||||
/// <param name="obj_ids"></param>
|
||||
/// <param name="bakeObjects"></param>
|
||||
/// <returns>The index of the baked layer</returns>
|
||||
public int Bake(RhinoDoc doc, List<Guid> obj_ids, bool bakeObjects, int parentLayerIndex = -1)
|
||||
{
|
||||
if (!LayerExists(doc, Path, out int currentLayerIndex))
|
||||
{
|
||||
if (parentLayerIndex != -1)
|
||||
{
|
||||
Guid parentLayerId = doc.Layers[parentLayerIndex].Id;
|
||||
currentLayerIndex = CreateLayer(doc, Collection.name, parentLayerId, Color);
|
||||
Guid currentLayerId = doc.Layers.FindIndex(currentLayerIndex).Id;
|
||||
obj_ids.Add(currentLayerId);
|
||||
}
|
||||
else
|
||||
{
|
||||
currentLayerIndex = CreateLayerByPath(doc, Path, Color, obj_ids);
|
||||
}
|
||||
}
|
||||
|
||||
// then bake elements in this collection
|
||||
foreach (var obj in Elements)
|
||||
{
|
||||
if (obj is SpeckleObjectWrapper so)
|
||||
{
|
||||
if (bakeObjects)
|
||||
{
|
||||
so.Bake(doc, obj_ids, currentLayerIndex, true);
|
||||
}
|
||||
}
|
||||
else if (obj is SpeckleCollectionWrapper c)
|
||||
{
|
||||
c.Bake(doc, obj_ids, bakeObjects, currentLayerIndex);
|
||||
}
|
||||
}
|
||||
|
||||
return currentLayerIndex;
|
||||
}
|
||||
|
||||
private bool LayerExists(RhinoDoc doc, List<string> path, out int layerIndex)
|
||||
{
|
||||
var fullPath = string.Join("::", path);
|
||||
layerIndex = doc.Layers.FindByFullPath(fullPath, -1);
|
||||
return layerIndex != -1;
|
||||
}
|
||||
|
||||
private int CreateLayer(RhinoDoc doc, string name, Guid parentId, Color? color)
|
||||
{
|
||||
Layer layer = new() { Name = name, ParentLayerId = parentId };
|
||||
if (color is not null)
|
||||
{
|
||||
layer.Color = color.Value;
|
||||
}
|
||||
|
||||
return doc.Layers.Add(layer);
|
||||
}
|
||||
|
||||
private int CreateLayerByPath(RhinoDoc doc, List<string> path, Color? color, List<Guid> obj_ids)
|
||||
{
|
||||
if (path.Count == 0 || doc == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int parentLayerIndex = -1;
|
||||
List<string> currentfullpath = new();
|
||||
Guid currentLayerId = Guid.Empty;
|
||||
foreach (string layerName in path)
|
||||
{
|
||||
currentfullpath.Add(layerName);
|
||||
|
||||
// Find or create the layer at this level
|
||||
if (LayerExists(doc, currentfullpath, out int currentLayerIndex))
|
||||
{
|
||||
currentLayerId = doc.Layers.FindIndex(currentLayerIndex).Id;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentLayerIndex = CreateLayer(doc, layerName, currentLayerId, color);
|
||||
currentLayerId = doc.Layers.FindIndex(currentLayerIndex).Id;
|
||||
obj_ids.Add(currentLayerId);
|
||||
}
|
||||
|
||||
parentLayerIndex = currentLayerIndex;
|
||||
}
|
||||
|
||||
return parentLayerIndex;
|
||||
}
|
||||
}
|
||||
|
||||
public partial class SpeckleCollectionWrapperGoo : GH_Goo<SpeckleCollectionWrapper> //, IGH_PreviewData // can be made previewable later
|
||||
{
|
||||
public override IGH_Goo Duplicate() => new SpeckleCollectionWrapperGoo(Value.DeepCopy());
|
||||
|
||||
public override string ToString() => $@"Speckle Collection Goo [{m_value.Name} ({Value.Elements.Count})]";
|
||||
|
||||
public override bool IsValid => true;
|
||||
public override string TypeName => "Speckle collection wrapper";
|
||||
public override string TypeDescription => "Speckle collection wrapper";
|
||||
|
||||
public override bool CastFrom(object source)
|
||||
{
|
||||
switch (source)
|
||||
{
|
||||
case SpeckleCollectionWrapper speckleGrasshopperCollection:
|
||||
Value = speckleGrasshopperCollection;
|
||||
return true;
|
||||
case GH_Goo<SpeckleCollectionWrapper> speckleGrasshopperCollectionGoo:
|
||||
Value = speckleGrasshopperCollectionGoo.Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle case of model objects in rhino 8
|
||||
return CastFromModelLayer(source);
|
||||
}
|
||||
|
||||
#if !RHINO8_OR_GREATER
|
||||
private bool CastFromModelLayer(object _) => false;
|
||||
|
||||
private bool CastToModelLayer<T>(ref T _) => false;
|
||||
#endif
|
||||
|
||||
public override bool CastTo<T>(ref T target)
|
||||
{
|
||||
return CastToModelLayer(ref target);
|
||||
}
|
||||
|
||||
public SpeckleCollectionWrapperGoo() { }
|
||||
|
||||
public SpeckleCollectionWrapperGoo(SpeckleCollectionWrapper value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public class SpeckleCollectionParam : GH_Param<SpeckleCollectionWrapperGoo>, IGH_BakeAwareObject, IGH_PreviewObject
|
||||
{
|
||||
public SpeckleCollectionParam()
|
||||
: this(GH_ParamAccess.item) { }
|
||||
|
||||
public SpeckleCollectionParam(IGH_InstanceDescription tag)
|
||||
: base(tag) { }
|
||||
|
||||
public SpeckleCollectionParam(IGH_InstanceDescription tag, GH_ParamAccess access)
|
||||
: base(tag, access) { }
|
||||
|
||||
public SpeckleCollectionParam(GH_ParamAccess access)
|
||||
: base(
|
||||
"Speckle Collection",
|
||||
"SCO",
|
||||
"A Speckle collection, corresponding to layers in Rhino",
|
||||
ComponentCategories.PRIMARY_RIBBON,
|
||||
ComponentCategories.PARAMETERS,
|
||||
access
|
||||
) { }
|
||||
|
||||
public override Guid ComponentGuid => new("6E871D5B-B221-4992-882A-EFE6796F3010");
|
||||
protected override Bitmap Icon => Resources.speckle_param_collection;
|
||||
|
||||
bool IGH_BakeAwareObject.IsBakeCapable => // False if no data
|
||||
!VolatileData.IsEmpty;
|
||||
|
||||
void IGH_BakeAwareObject.BakeGeometry(RhinoDoc doc, List<Guid> obj_ids)
|
||||
{
|
||||
// Iterate over all data stored in the parameter
|
||||
foreach (var item in VolatileData.AllData(true))
|
||||
{
|
||||
if (item is SpeckleCollectionWrapperGoo goo)
|
||||
{
|
||||
goo.Value.Bake(doc, obj_ids, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IGH_BakeAwareObject.BakeGeometry(RhinoDoc doc, ObjectAttributes att, List<Guid> obj_ids)
|
||||
{
|
||||
// Iterate over all data stored in the parameter
|
||||
foreach (var item in VolatileData.AllData(true))
|
||||
{
|
||||
if (item is SpeckleCollectionWrapperGoo goo)
|
||||
{
|
||||
goo.Value.Bake(doc, obj_ids, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private BoundingBox _clippingBox;
|
||||
public BoundingBox ClippingBox => _clippingBox;
|
||||
|
||||
bool IGH_PreviewObject.Hidden { get; set; }
|
||||
|
||||
public bool IsPreviewCapable => !VolatileData.IsEmpty;
|
||||
|
||||
private List<SpeckleObjectWrapper> _previewObjects = new();
|
||||
|
||||
public void DrawViewportMeshes(IGH_PreviewArgs args)
|
||||
{
|
||||
_previewObjects = new();
|
||||
_clippingBox = new();
|
||||
|
||||
foreach (var item in VolatileData.AllData(true))
|
||||
{
|
||||
if (item is SpeckleCollectionWrapperGoo goo)
|
||||
{
|
||||
FlattenForPreview(goo.Value);
|
||||
}
|
||||
}
|
||||
|
||||
if (_previewObjects.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var isSelected = args.Document.SelectedObjects().Contains(this);
|
||||
foreach (var elem in _previewObjects)
|
||||
{
|
||||
elem.DrawPreview(args, isSelected);
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawViewportWires(IGH_PreviewArgs args)
|
||||
{
|
||||
// todo?
|
||||
}
|
||||
|
||||
private void FlattenForPreview(SpeckleCollectionWrapper collWrapper)
|
||||
{
|
||||
foreach (var element in collWrapper.Elements)
|
||||
{
|
||||
if (element is SpeckleCollectionWrapper subCollWrapper)
|
||||
{
|
||||
FlattenForPreview(subCollWrapper);
|
||||
}
|
||||
|
||||
if (element is SpeckleObjectWrapper objWrapper)
|
||||
{
|
||||
_previewObjects.Add(objWrapper);
|
||||
var box = objWrapper.GeometryBase is null ? new() : objWrapper.GeometryBase.GetBoundingBox(false);
|
||||
_clippingBox.Union(box);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-287
@@ -1,287 +0,0 @@
|
||||
using Grasshopper.Kernel;
|
||||
using Grasshopper.Kernel.Types;
|
||||
using Rhino;
|
||||
using Rhino.DocObjects;
|
||||
using Speckle.Connectors.GrasshopperShared.Components;
|
||||
using Speckle.Connectors.GrasshopperShared.HostApp;
|
||||
using Speckle.Connectors.GrasshopperShared.Properties;
|
||||
using Speckle.Sdk.Models;
|
||||
using SpeckleRenderMaterial = Speckle.Objects.Other.RenderMaterial;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper around a render material base object and its converted speckle equivalent.
|
||||
/// </summary>
|
||||
public class SpeckleMaterialWrapper : SpeckleWrapper
|
||||
{
|
||||
public override required Base Base
|
||||
{
|
||||
get => Material;
|
||||
set
|
||||
{
|
||||
if (value is not SpeckleRenderMaterial mat)
|
||||
{
|
||||
throw new ArgumentException("Cannot create material wrapper from a non-SpeckleRenderMaterial Base");
|
||||
}
|
||||
|
||||
Material = mat;
|
||||
}
|
||||
}
|
||||
|
||||
public SpeckleRenderMaterial Material { get; set; }
|
||||
|
||||
public required Material RhinoMaterial { get; set; }
|
||||
|
||||
// The guid of the rhino render material that corresponds to the rhino material, if it exists.
|
||||
public required Guid RhinoRenderMaterialId { get; set; }
|
||||
|
||||
public override string ToString() => $"Speckle Wrapper [{typeof(Material)}]";
|
||||
|
||||
/// <summary>
|
||||
/// Creates the material in the document
|
||||
/// </summary>
|
||||
/// <param name="doc"></param>
|
||||
/// <param name="name">The name override, if any. Used for param baking where the nickname is changed by the user, or no name is available.</param>
|
||||
/// <returns>The index of the created material in the material table</returns>
|
||||
public int Bake(RhinoDoc doc, string? name = null)
|
||||
{
|
||||
Material bakeMaterial = new();
|
||||
bakeMaterial.CopyFrom(RhinoMaterial);
|
||||
|
||||
// set the material name
|
||||
// this should be the given name in the rhino material *unless* an override name is passed in
|
||||
if (name != null)
|
||||
{
|
||||
bakeMaterial.Name = name;
|
||||
}
|
||||
|
||||
return doc.Materials.Add(bakeMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
public partial class SpeckleMaterialWrapperGoo : GH_Goo<SpeckleMaterialWrapper>
|
||||
{
|
||||
public override IGH_Goo Duplicate() => throw new NotImplementedException();
|
||||
|
||||
public override string ToString() => $@"Speckle Material Goo [{Value.Name}]";
|
||||
|
||||
public override bool IsValid => true;
|
||||
public override string TypeName => "Speckle render material wrapper";
|
||||
public override string TypeDescription => "A wrapper around speckle render materials.";
|
||||
|
||||
public override bool CastFrom(object source)
|
||||
{
|
||||
switch (source)
|
||||
{
|
||||
case SpeckleMaterialWrapper speckleGrasshopperMaterial:
|
||||
Value = speckleGrasshopperMaterial;
|
||||
return true;
|
||||
case GH_Goo<SpeckleMaterialWrapper> speckleGrasshopperMaterialGoo:
|
||||
Value = speckleGrasshopperMaterialGoo.Value;
|
||||
return true;
|
||||
case GH_Material materialGoo:
|
||||
var gooMaterial = ToRhinoMaterial(materialGoo.Value);
|
||||
Value = new()
|
||||
{
|
||||
Base = ToSpeckleRenderMaterial(materialGoo.Value),
|
||||
Name = gooMaterial.Name,
|
||||
RhinoMaterial = gooMaterial,
|
||||
RhinoRenderMaterialId = Guid.Empty,
|
||||
};
|
||||
return true;
|
||||
case Material material:
|
||||
Value = new()
|
||||
{
|
||||
Base = ToSpeckleRenderMaterial(material),
|
||||
Name = material.Name,
|
||||
RhinoMaterial = material,
|
||||
RhinoRenderMaterialId = Guid.Empty
|
||||
};
|
||||
return true;
|
||||
case SpeckleRenderMaterial speckleMaterial:
|
||||
Value = new()
|
||||
{
|
||||
Base = speckleMaterial,
|
||||
Name = speckleMaterial.name,
|
||||
RhinoMaterial = ToRhinoMaterial(speckleMaterial),
|
||||
RhinoRenderMaterialId = Guid.Empty,
|
||||
ApplicationId = speckleMaterial.applicationId,
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
return CastFromModelRenderMaterial(source);
|
||||
}
|
||||
|
||||
#if !RHINO8_OR_GREATER
|
||||
private bool CastFromModelRenderMaterial(object _) => false;
|
||||
|
||||
private bool CastToModelRenderMaterial<T>(ref T _) => false;
|
||||
#endif
|
||||
|
||||
public override bool CastTo<T>(ref T target)
|
||||
{
|
||||
var type = typeof(T);
|
||||
|
||||
if (type == typeof(GH_Material))
|
||||
{
|
||||
target = (T)(object)(new GH_Material() { Value = new(Value.RhinoMaterial) });
|
||||
return true;
|
||||
}
|
||||
|
||||
return CastToModelRenderMaterial(ref target);
|
||||
}
|
||||
|
||||
public SpeckleMaterialWrapperGoo(SpeckleMaterialWrapper value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public SpeckleMaterialWrapperGoo() { }
|
||||
|
||||
private SpeckleRenderMaterial ToSpeckleRenderMaterial(Rhino.Display.DisplayMaterial mat)
|
||||
{
|
||||
SpeckleRenderMaterial speckleRenderMaterial =
|
||||
new()
|
||||
{
|
||||
name = mat.GetSpeckleApplicationId(),
|
||||
opacity = 1 - mat.Transparency,
|
||||
metalness = mat.Shine,
|
||||
diffuse = mat.Diffuse.ToArgb(),
|
||||
emissive = mat.Emission.ToArgb(),
|
||||
applicationId = mat.GetSpeckleApplicationId(),
|
||||
};
|
||||
|
||||
// add additional dynamic props for rhino material receive
|
||||
speckleRenderMaterial["specular"] = mat.Specular.ToArgb();
|
||||
speckleRenderMaterial["shine"] = mat.Shine;
|
||||
|
||||
return speckleRenderMaterial;
|
||||
}
|
||||
|
||||
private SpeckleRenderMaterial ToSpeckleRenderMaterial(Material mat)
|
||||
{
|
||||
SpeckleRenderMaterial speckleRenderMaterial =
|
||||
new()
|
||||
{
|
||||
name = mat.Name,
|
||||
opacity = 1 - mat.Transparency,
|
||||
diffuse = mat.DiffuseColor.ToArgb(),
|
||||
emissive = mat.EmissionColor.ToArgb(),
|
||||
applicationId = mat.Name,
|
||||
["specular"] = mat.SpecularColor.ToArgb(),
|
||||
["shine"] = mat.AmbientColor,
|
||||
["ior"] = mat.IndexOfRefraction
|
||||
};
|
||||
|
||||
return speckleRenderMaterial;
|
||||
}
|
||||
|
||||
private Material ToRhinoMaterial(Rhino.Display.DisplayMaterial mat) =>
|
||||
new()
|
||||
{
|
||||
DiffuseColor = mat.Diffuse,
|
||||
EmissionColor = mat.Emission,
|
||||
Transparency = mat.Transparency,
|
||||
SpecularColor = mat.Specular,
|
||||
Shine = mat.Shine,
|
||||
};
|
||||
|
||||
private Material ToRhinoMaterial(SpeckleRenderMaterial mat) =>
|
||||
new()
|
||||
{
|
||||
Name = mat.name,
|
||||
DiffuseColor = mat.diffuseColor,
|
||||
EmissionColor = mat.emissiveColor,
|
||||
Transparency = 1 - mat.opacity,
|
||||
Shine = mat["shine"] is double shine ? shine : default,
|
||||
IndexOfRefraction = mat["ior"] is double ior ? ior : default
|
||||
};
|
||||
}
|
||||
|
||||
public class SpeckleMaterialParam : GH_Param<SpeckleMaterialWrapperGoo>, IGH_BakeAwareObject
|
||||
{
|
||||
private const string NICKNAME = "Speckle Material";
|
||||
|
||||
public SpeckleMaterialParam()
|
||||
: this(GH_ParamAccess.item) { }
|
||||
|
||||
public SpeckleMaterialParam(IGH_InstanceDescription tag)
|
||||
: base(tag) { }
|
||||
|
||||
public SpeckleMaterialParam(IGH_InstanceDescription tag, GH_ParamAccess access)
|
||||
: base(tag, access) { }
|
||||
|
||||
public SpeckleMaterialParam(GH_ParamAccess access)
|
||||
: base(
|
||||
NICKNAME,
|
||||
"SM",
|
||||
"Represents a Speckle material",
|
||||
ComponentCategories.PRIMARY_RIBBON,
|
||||
ComponentCategories.PARAMETERS,
|
||||
access
|
||||
) { }
|
||||
|
||||
public override Guid ComponentGuid => new("1A08CF79-2072-4B14-9430-E4465FF0C0FE");
|
||||
|
||||
protected override Bitmap Icon => Resources.speckle_param_material;
|
||||
|
||||
bool IGH_BakeAwareObject.IsBakeCapable => // False if no data
|
||||
!VolatileData.IsEmpty;
|
||||
|
||||
void IGH_BakeAwareObject.BakeGeometry(RhinoDoc doc, List<Guid> obj_ids)
|
||||
{
|
||||
// Iterate over all data stored in the parameter
|
||||
foreach (var item in VolatileData.AllData(true))
|
||||
{
|
||||
if (item is SpeckleMaterialWrapperGoo goo)
|
||||
{
|
||||
// get the param nickname if it is a custom name.
|
||||
// this is used to override the name of the material.
|
||||
// the nickname should also be used in case of an empty name on the rhino material
|
||||
string? name =
|
||||
NickName != NICKNAME
|
||||
? NickName
|
||||
: string.IsNullOrEmpty(goo.Value.Name)
|
||||
? NickName
|
||||
: null;
|
||||
|
||||
int bakeIndex = goo.Value.Bake(doc, name);
|
||||
|
||||
if (bakeIndex == -1)
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"Failed to add material {name} to document.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IGH_BakeAwareObject.BakeGeometry(RhinoDoc doc, ObjectAttributes att, List<Guid> obj_ids)
|
||||
{
|
||||
// Iterate over all data stored in the parameter
|
||||
foreach (var item in VolatileData.AllData(true))
|
||||
{
|
||||
if (item is SpeckleMaterialWrapperGoo goo)
|
||||
{
|
||||
// get the param nickname if it is a custom name.
|
||||
// this is used to override the name of the material.
|
||||
// the nickname should also be used in case of an empty name on the rhino material
|
||||
string? name =
|
||||
NickName != NICKNAME
|
||||
? NickName
|
||||
: string.IsNullOrEmpty(goo.Value.Name)
|
||||
? NickName
|
||||
: null;
|
||||
|
||||
int bakeIndex = goo.Value.Bake(doc, name);
|
||||
if (bakeIndex == -1)
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"Failed to add material {name} to document.");
|
||||
}
|
||||
|
||||
obj_ids.Add(doc.Materials[bakeIndex].Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-262
@@ -1,262 +0,0 @@
|
||||
#if RHINO8_OR_GREATER
|
||||
using Grasshopper.Kernel;
|
||||
using Grasshopper.Kernel.Types;
|
||||
using Rhino;
|
||||
using Rhino.Geometry;
|
||||
using Grasshopper.Rhinoceros.Model;
|
||||
using Speckle.Connectors.GrasshopperShared.HostApp;
|
||||
using Speckle.Sdk.Models;
|
||||
using Rhino.DocObjects;
|
||||
using Grasshopper.Rhinoceros.Render;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
|
||||
public partial class SpeckleObjectWrapperGoo : GH_Goo<SpeckleObjectWrapper>, IGH_PreviewData
|
||||
{
|
||||
public SpeckleObjectWrapperGoo(ModelObject mo)
|
||||
{
|
||||
CastFrom(mo);
|
||||
}
|
||||
|
||||
private bool TryCastToExtrusion<T>(ref T target)
|
||||
{
|
||||
Extrusion? extrusion = null;
|
||||
if (GH_Convert.ToExtrusion(Value.GeometryBase, ref extrusion, GH_Conversion.Both))
|
||||
{
|
||||
target = (T)(object)new GH_Extrusion(extrusion);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryCastToPointcloud<T>(ref T target)
|
||||
{
|
||||
PointCloud? pointCloud = null;
|
||||
if (GH_Convert.ToPointCloud(Value.GeometryBase, ref pointCloud, GH_Conversion.Both))
|
||||
{
|
||||
target = (T)(object)new GH_PointCloud(pointCloud);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryCastToHatch<T>(ref T target)
|
||||
{
|
||||
Hatch? hatch = null;
|
||||
if (GH_Convert.ToHatch(Value.GeometryBase, ref hatch, GH_Conversion.Both))
|
||||
{
|
||||
target = (T)(object)new GH_Hatch(hatch);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryCastToSubD<T>(ref T target)
|
||||
{
|
||||
SubD? subd = null;
|
||||
if (GH_Convert.ToSubD(Value.GeometryBase, ref subd, GH_Conversion.Both))
|
||||
{
|
||||
target = (T)(object)new GH_SubD(subd);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool CastToModelObject<T>(ref T target)
|
||||
{
|
||||
var type = typeof(T);
|
||||
|
||||
if (type == typeof(ModelObject))
|
||||
{
|
||||
// create attributes
|
||||
ObjectAttributes atts = new();
|
||||
CastTo<ObjectAttributes>(ref atts);
|
||||
|
||||
// create model object
|
||||
ModelObject modelObject = new(RhinoDoc.ActiveDoc, atts, Value.GeometryBase);
|
||||
target = (T)(object)modelObject;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type == typeof(ObjectAttributes))
|
||||
{
|
||||
ObjectAttributes atts = new() { Name = Value.Name };
|
||||
|
||||
if (Value.Color is Color color)
|
||||
{
|
||||
atts.ObjectColor = color;
|
||||
atts.ColorSource = ObjectColorSource.ColorFromObject;
|
||||
}
|
||||
|
||||
// POC: only set material if it exists in the doc. Avoiding baking during cast.
|
||||
// ModelObject.Render.Material has no setter, so we are handling it here.
|
||||
if (
|
||||
Value.Material is SpeckleMaterialWrapper materialWrapper
|
||||
&& materialWrapper.RhinoRenderMaterialId != Guid.Empty
|
||||
)
|
||||
{
|
||||
Rhino.Render.RenderMaterial renderMaterial = RhinoDoc.ActiveDoc.RenderMaterials.Find(
|
||||
materialWrapper.RhinoRenderMaterialId
|
||||
);
|
||||
|
||||
atts.RenderMaterial = renderMaterial;
|
||||
atts.MaterialSource = ObjectMaterialSource.MaterialFromObject;
|
||||
}
|
||||
|
||||
// POC: only set layer if it exists in the doc. Avoid baking during cast.
|
||||
// ModelObject.Layer has no setter, so we are handling it here.
|
||||
if (Value.Parent is SpeckleCollectionWrapper collectionWrapper)
|
||||
{
|
||||
int layerIndex = collectionWrapper.GetLayerIndex();
|
||||
if (layerIndex != -1)
|
||||
{
|
||||
atts.LayerIndex = layerIndex;
|
||||
}
|
||||
}
|
||||
|
||||
// add props
|
||||
Value.Properties.AssignToObjectAttributes(atts);
|
||||
|
||||
target = (T)(object)atts;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type == typeof(ModelRenderMaterial))
|
||||
{
|
||||
if (Value.Material is SpeckleMaterialWrapper matWrapper)
|
||||
{
|
||||
SpeckleMaterialWrapperGoo matWrapperGoo = new(matWrapper);
|
||||
ModelRenderMaterial modelMat = new();
|
||||
if (matWrapperGoo.CastTo<ModelRenderMaterial>(ref modelMat))
|
||||
{
|
||||
target = (T)(object)modelMat;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type == typeof(ModelLayer))
|
||||
{
|
||||
if (Value.Parent is SpeckleCollectionWrapper collWrapper)
|
||||
{
|
||||
SpeckleCollectionWrapperGoo collWrapperGoo = new(collWrapper);
|
||||
ModelLayer modelLayer = new();
|
||||
if (collWrapperGoo.CastTo<ModelLayer>(ref modelLayer))
|
||||
{
|
||||
target = (T)(object)modelLayer;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool CastFromModelObject(object source)
|
||||
{
|
||||
if (source is ModelObject modelObject)
|
||||
{
|
||||
if (GetGeometryFromModelObject(modelObject) is GeometryBase modelGB)
|
||||
{
|
||||
Base modelConverted = SpeckleConversionContext.ConvertToSpeckle(modelGB);
|
||||
SpecklePropertyGroupGoo propertyGroup = new();
|
||||
propertyGroup.CastFrom(modelObject.UserText);
|
||||
|
||||
// get the object layer
|
||||
SpeckleCollectionWrapperGoo collWrapperGoo = new();
|
||||
SpeckleCollectionWrapper? collWrapper = collWrapperGoo.CastFrom(modelObject.Layer)
|
||||
? collWrapperGoo.Value
|
||||
: null;
|
||||
|
||||
// update the converted Base with props as well
|
||||
modelConverted.applicationId = modelObject.Id?.ToString();
|
||||
modelConverted[Constants.NAME_PROP] = modelObject.Name.ToString();
|
||||
Dictionary<string, object?> propertyDict = new();
|
||||
foreach (var entry in modelObject.UserText)
|
||||
{
|
||||
propertyDict.Add(entry.Key, entry.Value);
|
||||
}
|
||||
|
||||
modelConverted[Constants.PROPERTIES_PROP] = propertyDict;
|
||||
|
||||
// get the object color and material
|
||||
Color? color = GetColorFromModelObject(modelObject);
|
||||
SpeckleMaterialWrapperGoo? materialWrapper = new();
|
||||
if (GetMaterialFromModelObject(modelObject) is Rhino.Render.RenderMaterial renderMat)
|
||||
{
|
||||
materialWrapper.CastFrom(renderMat);
|
||||
}
|
||||
|
||||
SpeckleObjectWrapper so =
|
||||
new()
|
||||
{
|
||||
GeometryBase = modelGB,
|
||||
Base = modelConverted,
|
||||
Parent = collWrapper,
|
||||
Name = modelObject.Name.ToString(),
|
||||
Color = color,
|
||||
Material = materialWrapper.Value,
|
||||
Properties = propertyGroup,
|
||||
WrapperGuid = null // keep this null, processed on send
|
||||
};
|
||||
|
||||
Value = so;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Could not retrieve geometry from Model Object {modelObject.ObjectType}. Did you forget to bake these objects in your document?"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private GeometryBase? GetGeometryFromModelObject(ModelObject modelObject) =>
|
||||
RhinoDoc.ActiveDoc.Objects.FindId(modelObject.Id ?? Guid.Empty)?.Geometry;
|
||||
|
||||
private Color? GetColorFromModelObject(ModelObject modelObject)
|
||||
{
|
||||
// we need to retrieve the actual color by the color source (otherwise will return default color for anything other than by object)
|
||||
int? argb = null;
|
||||
switch (modelObject.Display.Color?.Source)
|
||||
{
|
||||
case ObjectColorSource.ColorFromLayer:
|
||||
argb = modelObject.Layer.DisplayColor?.ToArgb();
|
||||
break;
|
||||
case ObjectColorSource.ColorFromObject:
|
||||
argb = modelObject.Display.Color?.Color.ToArgb();
|
||||
break;
|
||||
case ObjectColorSource.ColorFromMaterial:
|
||||
Rhino.Render.RenderMaterial? mat = GetMaterialFromModelObject(modelObject);
|
||||
argb = mat?.ToMaterial(Rhino.Render.RenderTexture.TextureGeneration.Skip)?.DiffuseColor.ToArgb();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return argb is int validArgb ? Color.FromArgb(validArgb) : null;
|
||||
}
|
||||
|
||||
private Rhino.Render.RenderMaterial? GetMaterialFromModelObject(ModelObject modelObject)
|
||||
{
|
||||
// we need to retrieve the actual material by the material source (otherwise will return default material for anything other than by object)
|
||||
Guid? matId = null;
|
||||
switch (modelObject.Render.Material?.Source)
|
||||
{
|
||||
case ObjectMaterialSource.MaterialFromLayer:
|
||||
matId = modelObject.Layer.Material.Id;
|
||||
break;
|
||||
case ObjectMaterialSource.MaterialFromObject:
|
||||
matId = modelObject.Render.Material?.Material?.Id;
|
||||
break;
|
||||
case ObjectMaterialSource.MaterialFromParent: // POC: too complicated for now
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return matId is Guid validId ? RhinoDoc.ActiveDoc.RenderMaterials.Find(validId) : null;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
-545
@@ -1,545 +0,0 @@
|
||||
using Grasshopper.Kernel;
|
||||
using Grasshopper.Kernel.Types;
|
||||
using Rhino;
|
||||
using Rhino.Display;
|
||||
using Rhino.DocObjects;
|
||||
using Rhino.Geometry;
|
||||
using Speckle.Connectors.GrasshopperShared.Components;
|
||||
using Speckle.Connectors.GrasshopperShared.HostApp;
|
||||
using Speckle.Connectors.GrasshopperShared.Properties;
|
||||
using Speckle.Sdk.Models;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper around a geometry base object and its converted speckle equivalent.
|
||||
/// </summary>
|
||||
public class SpeckleObjectWrapper : SpeckleWrapper
|
||||
{
|
||||
public override required Base Base { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The GeometryBase corresponding to the <see cref="SpeckleWrapper.Base"/>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// POC: how will we send intervals and other gh native objects? do we? maybe not for now?
|
||||
/// Objects using fallback conversion (eg DataObjects) will create one wrapper per geometry in the display value.
|
||||
/// </remarks>
|
||||
public required GeometryBase? GeometryBase { get; set; }
|
||||
|
||||
// The list of layer/collection names that forms the full path to this object
|
||||
public List<string> Path { get; set; } = new();
|
||||
public SpeckleCollectionWrapper? Parent { get; set; }
|
||||
public SpecklePropertyGroupGoo Properties { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// The color of the <see cref="Base"/>
|
||||
/// </summary>
|
||||
public Color? Color { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The material of the <see cref="Base"/>
|
||||
/// </summary>
|
||||
public SpeckleMaterialWrapper? Material { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Represents the guid of this <see cref="SpeckleObjectWrapper"/>
|
||||
/// </summary>
|
||||
/// <remarks>This property will usually be assigned in create components, or in publish components, and may differ from <see cref="Base.applicationId"/></remarks>
|
||||
public required string? WrapperGuid { get; set; }
|
||||
|
||||
public override string ToString() => $"Speckle Wrapper [{GeometryBase?.GetType().Name}]";
|
||||
|
||||
public void DrawPreview(IGH_PreviewArgs args, bool isSelected = false)
|
||||
{
|
||||
switch (GeometryBase)
|
||||
{
|
||||
case Mesh m:
|
||||
args.Display.DrawMeshShaded(m, isSelected ? args.ShadeMaterial_Selected : args.ShadeMaterial);
|
||||
break;
|
||||
|
||||
case Brep b:
|
||||
args.Display.DrawBrepShaded(b, isSelected ? args.ShadeMaterial_Selected : args.ShadeMaterial);
|
||||
args.Display.DrawBrepWires(
|
||||
b,
|
||||
isSelected ? args.WireColour_Selected : args.WireColour,
|
||||
args.DefaultCurveThickness
|
||||
);
|
||||
break;
|
||||
|
||||
case Extrusion e:
|
||||
args.Display.DrawExtrusionWires(e, isSelected ? args.WireColour_Selected : args.WireColour);
|
||||
break;
|
||||
|
||||
case SubD d:
|
||||
args.Display.DrawSubDShaded(d, isSelected ? args.ShadeMaterial_Selected : args.ShadeMaterial);
|
||||
args.Display.DrawSubDWires(
|
||||
d,
|
||||
isSelected ? args.WireColour_Selected : args.WireColour,
|
||||
args.DefaultCurveThickness
|
||||
);
|
||||
break;
|
||||
|
||||
case Curve c:
|
||||
args.Display.DrawCurve(c, isSelected ? args.WireColour_Selected : args.WireColour, args.DefaultCurveThickness);
|
||||
break;
|
||||
|
||||
case Rhino.Geometry.Point p:
|
||||
args.Display.DrawPoint(p.Location, isSelected ? args.WireColour_Selected : args.WireColour);
|
||||
break;
|
||||
|
||||
case PointCloud pc:
|
||||
args.Display.DrawPointCloud(pc, 1, isSelected ? args.WireColour_Selected : args.WireColour);
|
||||
break;
|
||||
|
||||
case Hatch h:
|
||||
args.Display.DrawHatch(
|
||||
h,
|
||||
isSelected ? args.WireColour_Selected : args.WireColour,
|
||||
isSelected ? args.WireColour_Selected : args.WireColour
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawPreviewRaw(DisplayPipeline display, DisplayMaterial material)
|
||||
{
|
||||
switch (GeometryBase)
|
||||
{
|
||||
case Mesh m:
|
||||
display.DrawMeshShaded(m, material);
|
||||
break;
|
||||
case Brep b:
|
||||
display.DrawBrepShaded(b, material);
|
||||
display.DrawBrepWires(b, material.Diffuse);
|
||||
break;
|
||||
case Extrusion e:
|
||||
var eBrep = e.ToBrep();
|
||||
display.DrawBrepShaded(eBrep, material);
|
||||
display.DrawBrepWires(eBrep, material.Diffuse);
|
||||
break;
|
||||
case SubD d:
|
||||
display.DrawSubDShaded(d, material);
|
||||
display.DrawSubDWires(d, material.Diffuse, display.DefaultCurveThickness);
|
||||
break;
|
||||
case Curve c:
|
||||
display.DrawCurve(c, material.Diffuse);
|
||||
break;
|
||||
case Rhino.Geometry.Point p:
|
||||
display.DrawPoint(p.Location, material.Diffuse);
|
||||
break;
|
||||
case PointCloud pc:
|
||||
display.DrawPointCloud(pc, 1, material.Diffuse);
|
||||
break;
|
||||
case Hatch h:
|
||||
display.DrawHatch(h, material.Diffuse, material.Diffuse);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void Bake(RhinoDoc doc, List<Guid> obj_ids, int bakeLayerIndex = -1, bool layersAlreadyCreated = false)
|
||||
{
|
||||
// get or make layers
|
||||
if (!layersAlreadyCreated && bakeLayerIndex < 0)
|
||||
{
|
||||
if (Path.Count > 0 && Parent != null)
|
||||
{
|
||||
bakeLayerIndex = Parent.Bake(doc, obj_ids, false);
|
||||
}
|
||||
|
||||
if (bakeLayerIndex < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// create attributes
|
||||
using ObjectAttributes att = new() { Name = Name, LayerIndex = bakeLayerIndex };
|
||||
|
||||
if (Color is Color color)
|
||||
{
|
||||
att.ObjectColor = color;
|
||||
att.ColorSource = ObjectColorSource.ColorFromObject;
|
||||
}
|
||||
|
||||
if (Material is SpeckleMaterialWrapper materialWrapper)
|
||||
{
|
||||
int matIndex = materialWrapper.Bake(doc, materialWrapper.Name);
|
||||
if (matIndex >= 0)
|
||||
{
|
||||
att.MaterialIndex = matIndex;
|
||||
att.MaterialSource = ObjectMaterialSource.MaterialFromObject;
|
||||
}
|
||||
}
|
||||
|
||||
// add props
|
||||
Properties.AssignToObjectAttributes(att);
|
||||
|
||||
// add to doc
|
||||
Guid guid = doc.Objects.Add(GeometryBase, att);
|
||||
obj_ids.Add(guid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines similarity of two SpeckleObjectWrappers.
|
||||
/// If the path, name, and properties of the wrappers are the same, they should be considered similar.
|
||||
/// This should be used to pack similar objects into one `DataObject` on send.
|
||||
/// </summary>
|
||||
/// <param name="objWrapper">The object wrapper to compare to</param>
|
||||
/// <returns></returns>
|
||||
/// <remarks> Application Id is not considered in similarity, because these can be unique to objects inside the same displayvalue for proxy reasons</remarks>
|
||||
public bool SmellsLike(SpeckleObjectWrapper objWrapper)
|
||||
{
|
||||
if (Path != objWrapper.Path)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Name != objWrapper.Name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
if (!Properties.Equals(objWrapper.Properties))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public SpeckleObjectWrapper DeepCopy() =>
|
||||
new()
|
||||
{
|
||||
Base = Base.ShallowCopy(),
|
||||
GeometryBase = GeometryBase?.Duplicate(),
|
||||
Color = Color,
|
||||
Material = Material,
|
||||
WrapperGuid = WrapperGuid,
|
||||
ApplicationId = ApplicationId,
|
||||
Parent = Parent,
|
||||
Properties = Properties,
|
||||
Name = Name,
|
||||
Path = Path
|
||||
};
|
||||
}
|
||||
|
||||
public partial class SpeckleObjectWrapperGoo : GH_Goo<SpeckleObjectWrapper>, IGH_PreviewData
|
||||
{
|
||||
public override IGH_Goo Duplicate()
|
||||
{
|
||||
return new SpeckleObjectWrapperGoo(Value.DeepCopy());
|
||||
}
|
||||
|
||||
public override string ToString() => $@"Speckle Object Goo [{m_value.Base.speckle_type}]";
|
||||
|
||||
public override bool IsValid => true;
|
||||
public override string TypeName => "Speckle object wrapper";
|
||||
public override string TypeDescription => "A wrapper around speckle grasshopper objects.";
|
||||
|
||||
/// <summary>
|
||||
/// Casts from Speckle objects, geometry base, and model objects.
|
||||
/// All non-Speckle objects will be converted to its geometry equivalent.
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
public override bool CastFrom(object source)
|
||||
{
|
||||
switch (source)
|
||||
{
|
||||
case SpeckleObjectWrapper wrapper:
|
||||
Value = wrapper.DeepCopy();
|
||||
return true;
|
||||
case GH_Goo<SpeckleObjectWrapper> speckleGrasshopperObjectGoo:
|
||||
Value = speckleGrasshopperObjectGoo.Value.DeepCopy();
|
||||
return true;
|
||||
case IGH_GeometricGoo geometricGoo:
|
||||
var gooGB = geometricGoo.GeometricGooToGeometryBase();
|
||||
var gooConverted = SpeckleConversionContext.ConvertToSpeckle(gooGB);
|
||||
Value = new SpeckleObjectWrapper()
|
||||
{
|
||||
GeometryBase = gooGB,
|
||||
Base = gooConverted,
|
||||
Name = "",
|
||||
Color = null,
|
||||
Material = null,
|
||||
WrapperGuid = null,
|
||||
ApplicationId = Guid.NewGuid().ToString()
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle case of model objects in rhino 8
|
||||
return CastFromModelObject(source);
|
||||
}
|
||||
|
||||
#if !RHINO8_OR_GREATER
|
||||
private bool CastFromModelObject(object _) => false;
|
||||
|
||||
private bool CastToModelObject<T>(ref T _) => false;
|
||||
#endif
|
||||
|
||||
public override bool CastTo<T>(ref T target)
|
||||
{
|
||||
if (Value.GeometryBase == null)
|
||||
{
|
||||
return CastToModelObject(ref target);
|
||||
}
|
||||
|
||||
return target switch
|
||||
{
|
||||
GH_Surface => TryCastToSurface(ref target),
|
||||
GH_Mesh => TryCastToMesh(ref target),
|
||||
GH_Brep => TryCastToBrep(ref target),
|
||||
GH_Line => TryCastToLine(ref target),
|
||||
GH_Curve => TryCastToCurve(ref target),
|
||||
GH_Point => TryCastToPoint(ref target),
|
||||
GH_Circle => TryCastToCircle(ref target),
|
||||
GH_Arc => TryCastToArc(ref target),
|
||||
#if RHINO8_OR_GREATER
|
||||
GH_Extrusion => TryCastToExtrusion(ref target),
|
||||
GH_PointCloud => TryCastToPointcloud(ref target),
|
||||
GH_SubD => TryCastToSubD(ref target),
|
||||
GH_Hatch => TryCastToHatch(ref target),
|
||||
#endif
|
||||
IGH_GeometricGoo => TryCastToGeometricGoo(ref target),
|
||||
_ => CastToModelObject(ref target)
|
||||
};
|
||||
}
|
||||
|
||||
private bool TryCastToSurface<T>(ref T target)
|
||||
{
|
||||
Surface? surface = null;
|
||||
if (GH_Convert.ToSurface(Value.GeometryBase, ref surface, GH_Conversion.Both))
|
||||
{
|
||||
target = (T)(object)new GH_Surface(surface);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryCastToMesh<T>(ref T target)
|
||||
{
|
||||
Mesh? mesh = null;
|
||||
if (GH_Convert.ToMesh(Value.GeometryBase, ref mesh, GH_Conversion.Both))
|
||||
{
|
||||
target = (T)(object)new GH_Mesh(mesh);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryCastToBrep<T>(ref T target)
|
||||
{
|
||||
Brep? brep = null;
|
||||
if (GH_Convert.ToBrep(Value.GeometryBase, ref brep, GH_Conversion.Both))
|
||||
{
|
||||
target = (T)(object)new GH_Brep(brep);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryCastToLine<T>(ref T target)
|
||||
{
|
||||
Line line = new();
|
||||
if (GH_Convert.ToLine(Value.GeometryBase, ref line, GH_Conversion.Both))
|
||||
{
|
||||
target = (T)(object)new GH_Line(line);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryCastToCurve<T>(ref T target)
|
||||
{
|
||||
Curve? curve = null;
|
||||
if (GH_Convert.ToCurve(Value.GeometryBase, ref curve, GH_Conversion.Both))
|
||||
{
|
||||
target = (T)(object)new GH_Curve(curve);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryCastToPoint<T>(ref T target)
|
||||
{
|
||||
Point3d point = new();
|
||||
if (GH_Convert.ToPoint3d(Value.GeometryBase, ref point, GH_Conversion.Both))
|
||||
{
|
||||
target = (T)(object)new GH_Point(point);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryCastToGeometricGoo<T>(ref T target)
|
||||
{
|
||||
var geometricGoo = GH_Convert.ToGeometricGoo(Value.GeometryBase);
|
||||
if (geometricGoo != null && geometricGoo is T convertedGoo)
|
||||
{
|
||||
target = convertedGoo;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryCastToCircle<T>(ref T target)
|
||||
{
|
||||
var circle = new Rhino.Geometry.Circle();
|
||||
if (GH_Convert.ToCircle(Value.GeometryBase, ref circle, GH_Conversion.Both))
|
||||
{
|
||||
target = (T)(object)new GH_Circle(circle);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryCastToArc<T>(ref T target)
|
||||
{
|
||||
var arc = new Arc();
|
||||
if (GH_Convert.ToArc(Value.GeometryBase, ref arc, GH_Conversion.Both))
|
||||
{
|
||||
target = (T)(object)new GH_Arc(arc);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void DrawViewportWires(GH_PreviewWireArgs args)
|
||||
{
|
||||
// TODO ?
|
||||
}
|
||||
|
||||
public void DrawViewportMeshes(GH_PreviewMeshArgs args)
|
||||
{
|
||||
Value.DrawPreviewRaw(args.Pipeline, args.Material);
|
||||
}
|
||||
|
||||
BoundingBox IGH_PreviewData.ClippingBox =>
|
||||
Value.GeometryBase is null ? new() : Value.GeometryBase.GetBoundingBox(false);
|
||||
|
||||
public SpeckleObjectWrapperGoo(SpeckleObjectWrapper value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public SpeckleObjectWrapperGoo()
|
||||
{
|
||||
Value = new()
|
||||
{
|
||||
Base = new(),
|
||||
GeometryBase = null,
|
||||
Color = null,
|
||||
Material = null,
|
||||
WrapperGuid = null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class SpeckleObjectParam : GH_Param<SpeckleObjectWrapperGoo>, IGH_BakeAwareObject, IGH_PreviewObject
|
||||
{
|
||||
public SpeckleObjectParam()
|
||||
: this(GH_ParamAccess.item) { }
|
||||
|
||||
public SpeckleObjectParam(IGH_InstanceDescription tag)
|
||||
: base(tag) { }
|
||||
|
||||
public SpeckleObjectParam(IGH_InstanceDescription tag, GH_ParamAccess access)
|
||||
: base(tag, access) { }
|
||||
|
||||
public SpeckleObjectParam(GH_ParamAccess access)
|
||||
: base(
|
||||
"Speckle Object",
|
||||
"SO",
|
||||
"Represents a Speckle object",
|
||||
ComponentCategories.PRIMARY_RIBBON,
|
||||
ComponentCategories.PARAMETERS,
|
||||
access
|
||||
) { }
|
||||
|
||||
public override Guid ComponentGuid => new("22FD5510-D5D3-4101-8727-153FFD329E4F");
|
||||
|
||||
protected override Bitmap Icon => Resources.speckle_param_object;
|
||||
|
||||
public bool IsBakeCapable =>
|
||||
// False if no data
|
||||
!VolatileData.IsEmpty;
|
||||
|
||||
public void BakeGeometry(RhinoDoc doc, List<Guid> obj_ids)
|
||||
{
|
||||
// Iterate over all data stored in the parameter
|
||||
foreach (var item in VolatileData.AllData(true))
|
||||
{
|
||||
if (item is SpeckleObjectWrapperGoo goo)
|
||||
{
|
||||
goo.Value.Bake(doc, obj_ids);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bakes the object
|
||||
/// </summary>
|
||||
/// <param name="doc"></param>
|
||||
/// <param name="att"></param>
|
||||
/// <param name="obj_ids"></param>
|
||||
/// <remarks>
|
||||
/// The attributes come from the user dialog after calling bake.
|
||||
/// The selected layer from the dialog will only be user if no path is already present on the object.
|
||||
/// </remarks>
|
||||
public void BakeGeometry(RhinoDoc doc, ObjectAttributes att, List<Guid> obj_ids)
|
||||
{
|
||||
// Iterate over all data stored in the parameter
|
||||
foreach (var item in VolatileData.AllData(true))
|
||||
{
|
||||
if (item is SpeckleObjectWrapperGoo goo)
|
||||
{
|
||||
int layerIndex = goo.Value.Path.Count == 0 ? att.LayerIndex : -1;
|
||||
bool layerCreated = goo.Value.Path.Count == 0;
|
||||
goo.Value.Bake(doc, obj_ids, layerIndex, layerCreated);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsPreviewCapable => !VolatileData.IsEmpty;
|
||||
|
||||
public BoundingBox ClippingBox
|
||||
{
|
||||
get
|
||||
{
|
||||
BoundingBox clippingBox = new();
|
||||
|
||||
// Iterate over all data stored in the parameter
|
||||
foreach (var item in VolatileData.AllData(true))
|
||||
{
|
||||
if (item is SpeckleObjectWrapperGoo goo && goo.Value.GeometryBase is GeometryBase gb)
|
||||
{
|
||||
var box = gb.GetBoundingBox(false);
|
||||
clippingBox.Union(box);
|
||||
}
|
||||
}
|
||||
return clippingBox;
|
||||
}
|
||||
}
|
||||
bool IGH_PreviewObject.Hidden { get; set; }
|
||||
|
||||
public void DrawViewportWires(IGH_PreviewArgs args)
|
||||
{
|
||||
// todo?
|
||||
}
|
||||
|
||||
public void DrawViewportMeshes(IGH_PreviewArgs args)
|
||||
{
|
||||
var isSelected = args.Document.SelectedObjects().Contains(this);
|
||||
foreach (var item in VolatileData.AllData(true))
|
||||
{
|
||||
if (item is SpeckleObjectWrapperGoo goo)
|
||||
{
|
||||
goo.Value.DrawPreview(args, isSelected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user