Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2bbc8b4fdf | |||
| e9263279ab | |||
| d60b2cb587 | |||
| 13858f4184 | |||
| c1a58859b9 | |||
| 0fb7ad032f | |||
| 7772f5ba00 | |||
| a6340618d0 |
@@ -3,16 +3,16 @@
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"csharpier": {
|
||||
"version": "1.2.6",
|
||||
"version": "0.28.2",
|
||||
"commands": [
|
||||
"csharpier"
|
||||
"dotnet-csharpier"
|
||||
],
|
||||
"rollForward": false
|
||||
},
|
||||
"dotnet-affected": {
|
||||
"version": "6.2.0",
|
||||
"gitversion.tool": {
|
||||
"version": "6.0.2",
|
||||
"commands": [
|
||||
"dotnet-affected"
|
||||
"dotnet-gitversion"
|
||||
],
|
||||
"rollForward": false
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
Directory.Build.targets
|
||||
Directory.Build.props
|
||||
Directory.Packages.props
|
||||
|
||||
*.slnx
|
||||
|
||||
**/bin/*
|
||||
**/obj/*
|
||||
_ReSharper.SharpCompress/
|
||||
bin/
|
||||
*.suo
|
||||
*.user
|
||||
TestArchives/Scratch/
|
||||
TestArchives/Scratch2/
|
||||
TestResults/
|
||||
*.nupkg
|
||||
packages/*/
|
||||
project.lock.json
|
||||
tests/TestArchives/Scratch
|
||||
.vs
|
||||
tools
|
||||
.vscode
|
||||
.idea/
|
||||
|
||||
.DS_Store
|
||||
*.snupkg
|
||||
coverage.xml
|
||||
|
||||
*.received.*
|
||||
@@ -1,7 +1,7 @@
|
||||
printWidth: 120
|
||||
useTabs: false
|
||||
indentSize: 2
|
||||
tabWidth: 2
|
||||
preprocessorSymbolSets:
|
||||
- ""
|
||||
- "DEBUG"
|
||||
- "DEBUG,CODE_STYLE"
|
||||
- ""
|
||||
- "DEBUG"
|
||||
- "DEBUG,CODE_STYLE"
|
||||
|
||||
@@ -239,9 +239,6 @@ dotnet_diagnostic.ide0290.severity = suggestion # primary constructors: subjecti
|
||||
dotnet_diagnostic.ide0290.severity = suggestion # Use primary constructor: Subjective
|
||||
dotnet_diagnostic.ide0037.severity = suggestion # Use inferred member names: Sometimes its nice to be explicit
|
||||
dotnet_diagnostic.ide0301.severity = suggestion # Use collection expression for empty: Subjective, intent
|
||||
dotnet_diagnostic.ide0021.severity = suggestion # Use expression body for constructors : Subjective
|
||||
dotnet_diagnostic.ide0090.severity = suggestion # Simplify new expression : Subjective
|
||||
|
||||
dotnet_diagnostic.ide0047.severity = suggestion # Parentheses preferences: IDEs don't properly pick it up
|
||||
|
||||
# Maintainability rules
|
||||
@@ -254,10 +251,9 @@ dotnet_diagnostic.ca1508.severity = warning # Avoid dead conditional code
|
||||
dotnet_diagnostic.ca1509.severity = warning # Invalid entry in code metrics configuration file
|
||||
dotnet_diagnostic.ca1861.severity = none # Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
|
||||
|
||||
# CA2007: Consider calling ConfigureAwait on the awaited task (this is not needed for application code, in fact we don't want to call anything but ConfigureAwait(true) which is the default)
|
||||
dotnet_diagnostic.CA2007.severity = none
|
||||
|
||||
dotnet_diagnostic.cs8618.severity = suggestion # nullable problem
|
||||
dotnet_diagnostic.CS0809.severity = suggestion # obsolete errors
|
||||
dotnet_diagnostic.CS0618.severity = suggestion # obsolete errors
|
||||
|
||||
|
||||
# Performance rules
|
||||
@@ -314,9 +310,6 @@ dotnet_diagnostic.NUnit2037.severity = warning # Consider using Assert.That(coll
|
||||
dotnet_diagnostic.NUnit2038.severity = warning # Consider using Assert.That(actual, Is.InstanceOf(expected)) instead of Assert.IsInstanceOf(expected, actual)
|
||||
dotnet_diagnostic.NUnit2039.severity = warning # Consider using Assert.That(actual, Is.Not.InstanceOf(expected)) instead of Assert.IsNotInstanceOf(expected, actual)
|
||||
|
||||
# note: added to allow the copy paste from rhino inside of the ValueSet component
|
||||
dotnet_diagnostic.CA1033.severity = none
|
||||
|
||||
[*.{appxmanifest,asax,ascx,aspx,axaml,build,c,c++,cc,cginc,compute,cp,cpp,cs,cshtml,cu,cuh,cxx,dtd,fs,fsi,fsscript,fsx,fx,fxh,h,hh,hlsl,hlsli,hlslinc,hpp,hxx,inc,inl,ino,ipp,ixx,master,ml,mli,mpp,mq4,mq5,mqh,nuspec,paml,razor,resw,resx,shader,skin,tpp,usf,ush,vb,xaml,xamlx,xoml,xsd}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
@@ -4,36 +4,33 @@
|
||||
|
||||
# * @specklesystems/connectors
|
||||
|
||||
# Core
|
||||
# Not needed, falls back on team approval
|
||||
|
||||
# Objects
|
||||
# Converters require product owner approval, anything else falls back to team approval
|
||||
|
||||
Objects/ConverterAutocadCivil/* @clairekuang @connorivy
|
||||
Objects/ConverterCSI/* @connorivy
|
||||
Objects/ConverterDynamo/* @teocomi @alanrynne
|
||||
Objects/ConverterMicrostation/* @connorivy
|
||||
Objects/ConverterRevit/* @connorivy @teocomi
|
||||
Objects/ConverterRhinoGh/* @alanrynne @clairekuang
|
||||
Objects/ConverterTeklaStructures/* @connorivy
|
||||
Objects/StructuralUtilities/PolygonMesher/* @connorivy
|
||||
|
||||
# Connectors
|
||||
|
||||
/Connectors/Autocad/* @oguzhankoral @JR-Morgan @dogukankaratas
|
||||
/Connectors/Civil3d/* @oguzhankoral @JR-Morgan @dogukankaratas
|
||||
/Connectors/CSi/* @bjoernsteinhagen @dogukankaratas
|
||||
/Connectors/Navisworks/* @jsdbroughton
|
||||
/Connectors/Revit/* @oguzhankoral
|
||||
/Connectors/Rhino/* @oguzhankoral @JR-Morgan
|
||||
/Connectors/Tekla/* @bjoernsteinhagen @dogukankaratas
|
||||
ConnectorAutocadCivil/* @clairekuang
|
||||
ConnectorArchicad/* @jozseflkiss
|
||||
ConnectorCSI/* @connorivy
|
||||
ConnectorDynamo/* @teocomi @alanrynne
|
||||
ConnectorGrasshopper/* @alanrynne @clairekuang
|
||||
ConnectorMicrostation/* @clairekuang
|
||||
ConnectorRevit/* @teocomi @connorivy
|
||||
ConnectorRhino/* @clairekuang @alanrynne
|
||||
ConnectorTeklaStructures/* @connorivy
|
||||
|
||||
# Converters
|
||||
/Convertors/Autocad/* @oguzhankoral @JR-Morgan @dogukankaratas
|
||||
/Convertors/Civil3d/* @oguzhankoral @JR-Morgan @dogukankaratas
|
||||
/Convertors/CSi/* @bjoernsteinhagen @dogukankaratas
|
||||
/Convertors/Navisworks/* @jsdbroughton
|
||||
/Convertors/Revit/* @oguzhankoral
|
||||
/Convertors/Rhino/* @oguzhankoral @JR-Morgan
|
||||
/Convertors/Tekla/* @bjoernsteinhagen @dogukankaratas
|
||||
# DesktopUI
|
||||
|
||||
# DUI
|
||||
|
||||
/DUI3/* @oguzhankoral
|
||||
|
||||
# Importers
|
||||
/Importers/* @JR-Morgan @oguzhankoral
|
||||
|
||||
# SDK
|
||||
/SDK/* @JR-Morgan @oguzhankoral
|
||||
|
||||
# Build
|
||||
/Build/* @JR-Morgan @oguzhankoral
|
||||
/.github/* @JR-Morgan @oguzhankoral
|
||||
/.config/* @JR-Morgan @oguzhankoral
|
||||
DesktopUI2/* @teocomi @clairekuang
|
||||
|
||||
@@ -1,46 +1,30 @@
|
||||
<!---
|
||||
|
||||
Provide a short summary in the Title above. Use the following template:
|
||||
Provide a short summary in the Title above. Examples of good PR titles:
|
||||
|
||||
category(project): summary
|
||||
* "Feature: adds metrics to component"
|
||||
|
||||
Categories:
|
||||
* "Fix: resolves duplication in comment thread"
|
||||
|
||||
* feat: (new feature for the user, not a new feature for build script)
|
||||
* fix: (bug fix for the user, not a fix to a build script)
|
||||
* docs: (changes to the documentation)
|
||||
* style: (formatting, missing semi colons, etc; no production code change)
|
||||
* refactor: (refactoring production code, eg. renaming a variable)
|
||||
* test: (adding missing tests, refactoring tests; no production code change)
|
||||
* chore: (updating grunt tasks etc; no production code change)
|
||||
|
||||
Example:
|
||||
|
||||
feat(revit): added category filter to send
|
||||
* "Update: apollo v2.34.0"
|
||||
|
||||
-->
|
||||
|
||||
## Description
|
||||
## Description & motivation
|
||||
|
||||
<!---
|
||||
|
||||
Describe your changes, and why you're making them.
|
||||
Describe your changes, and why you're making them. What benefit will this have to others?
|
||||
|
||||
Link related github issues here ->
|
||||
Fixes #85, Fixes #22, Connects #123
|
||||
Is this linked to an open Github issue, a thread in Speckle community,
|
||||
or another pull request? Link it here.
|
||||
|
||||
If it is related to a Github issue, and resolves it, please link to the issue number, e.g.:
|
||||
Fixes #85, Fixes #22, Fixes username/repo#123
|
||||
Connects #123
|
||||
|
||||
-->
|
||||
|
||||
## User Value
|
||||
|
||||
<!---
|
||||
|
||||
Describe in 1 sentence the user value.
|
||||
|
||||
This can also be a link to the relevant thread in Speckle community, or a link to the Linear issue.
|
||||
-->
|
||||
|
||||
|
||||
## Changes:
|
||||
|
||||
<!---
|
||||
@@ -84,10 +68,35 @@ Describe what tests have been added or amended, and why these demonstrate it wor
|
||||
|
||||
<!---
|
||||
|
||||
This checklist is a useful reminder of related tasks to uphold our repo quality. Amend this list as needed for the pr.
|
||||
This checklist is mostly useful as a reminder of small things that can easily be
|
||||
|
||||
forgotten – it is meant as a helpful tool rather than hoops to jump through.
|
||||
|
||||
Put an `x` between the square brackets, e.g. [x], for all the items that apply,
|
||||
|
||||
make notes next to any that haven't been addressed, and remove any items that are not relevant to this PR.
|
||||
|
||||
-->
|
||||
|
||||
- [ ] My pull request follows the guidelines in the [Contributing guide](https://github.com/specklesystems/speckle-server/blob/main/CONTRIBUTING.md)?
|
||||
- [ ] My pull request does not duplicate any other open [Pull Requests](../../pulls) for the same update/change?
|
||||
- [ ] My commits are related to the pull request and do not amend unrelated code or documentation.
|
||||
- [ ] My code follows a similar style to existing code.
|
||||
- [ ] I have added appropriate tests.
|
||||
- [ ] I have updated or added relevant documentation.
|
||||
|
||||
## References
|
||||
|
||||
<!---
|
||||
|
||||
(Optional -- remove this section if not needed )
|
||||
|
||||
Include **important** links regarding the implementation of this PR.
|
||||
|
||||
This usually includes a RFC or an aggregation of issues and/or individual conversations
|
||||
|
||||
that helped put this solution together. This helps ensure we retain and share knowledge
|
||||
|
||||
regarding the implementation, and may help others understand motivation and design decisions etc..
|
||||
|
||||
-->
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
name: .NET Build
|
||||
|
||||
on:
|
||||
pull_request: # Run build on every pull request that is not to main
|
||||
branches-ignore:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
outputs:
|
||||
version: ${{ steps.set-version.outputs.version }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.2xx # Align with global.json (including roll forward rules)
|
||||
|
||||
- name: Cache Nuget
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.nuget/packages
|
||||
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
||||
|
||||
- name: ⚒️ Run build
|
||||
run: ./build.ps1 test
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.2xx # Align with global.json (including roll forward rules)
|
||||
|
||||
- name: Cache Nuget
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.nuget/packages
|
||||
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
||||
|
||||
- name: ⚒️ Run build
|
||||
run: ./build.sh test-only
|
||||
|
||||
- name: Upload coverage reports to Codecov with GitHub Action
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
file: Converters/**/coverage.xml
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
@@ -0,0 +1,91 @@
|
||||
name: .NET Build and Publish
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main", "dev"] # Continuous delivery on every long-lived branch
|
||||
tags: ["v3.*"] # Manual delivery on every 3.x tag
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
outputs:
|
||||
version: ${{ steps.set-version.outputs.version }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.2xx # Align with global.json (including roll forward rules)
|
||||
|
||||
- name: Cache Nuget
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.nuget/packages
|
||||
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
||||
|
||||
- name: ⚒️ Run GitVersion
|
||||
run: ./build.ps1 build-server-version
|
||||
|
||||
- name: ⚒️ Run build
|
||||
run: ./build.ps1
|
||||
|
||||
- name: ⬆️ Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: output-${{ env.GitVersion_FullSemVer }}
|
||||
path: output/*.*
|
||||
compression-level: 0 # no compression
|
||||
|
||||
- id: set-version
|
||||
name: Set version to output
|
||||
run: echo "version=${{ env.GitVersion_FullSemVer }}" >> "$Env:GITHUB_OUTPUT"
|
||||
|
||||
deploy-installers:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
env:
|
||||
IS_TAG_BUILD: ${{ github.ref_type == 'tag' }}
|
||||
steps:
|
||||
- name: 🔫 Trigger Build Installers
|
||||
uses: ALEEF02/workflow-dispatch@v3.0.0
|
||||
with:
|
||||
workflow: Build Installers
|
||||
repo: specklesystems/connector-installers
|
||||
token: ${{ secrets.CONNECTORS_GH_TOKEN }}
|
||||
inputs: '{ "run_id": "${{ github.run_id }}", "version": "${{ needs.build.outputs.version }}", "public_release": ${{ env.IS_TAG_BUILD }} }'
|
||||
ref: stable-installer-release
|
||||
wait-for-completion: true
|
||||
wait-for-completion-interval: 10s
|
||||
wait-for-completion-timeout: 10m
|
||||
display-workflow-run-url: true
|
||||
display-workflow-run-url-interval: 10s
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.2xx # Align with global.json (including roll forward rules)
|
||||
|
||||
- name: Cache Nuget
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.nuget/packages
|
||||
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
||||
|
||||
- name: ⚒️ Run build
|
||||
run: ./build.sh test-only
|
||||
|
||||
- name: Upload coverage reports to Codecov with GitHub Action
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
file: Converters/**/coverage.xml
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
@@ -1,42 +0,0 @@
|
||||
name: .NET Test
|
||||
|
||||
on:
|
||||
pull_request: {}
|
||||
push:
|
||||
branches: ["main"]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v5
|
||||
with:
|
||||
dotnet-version: 8.0.4xx # Align with global.json (including roll forward rules)
|
||||
|
||||
- name: Cache Nuget
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ~/.nuget/packages
|
||||
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
||||
|
||||
- name: ⚒️ Run Test
|
||||
run: ./build.sh test-and-pack
|
||||
|
||||
- name: Upload coverage reports to Codecov with GitHub Action
|
||||
uses: codecov/codecov-action@v6
|
||||
with:
|
||||
files: Converters/**/coverage.xml
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
# Disabling this code for now, since we no longer need to publish nugets from this repo
|
||||
# But keeping it around incase we ever need in the future.
|
||||
# Ideally, I'd also like to move the nuget token to be an environment secret, and to have tight package scopes
|
||||
# - name: Push to nuget.org
|
||||
# if: ${{ inputs.deployNugets }}
|
||||
# run: dotnet nuget push output/*.nupkg --source "https://api.nuget.org/v3/index.json" --api-key ${{ secrets.CONNECTORS_NUGET_TOKEN }}
|
||||
@@ -1,79 +0,0 @@
|
||||
name: .NET Build and Publish
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main", "installer-test/**"]
|
||||
tags: ["v3.*.*"] # Manual delivery on every 3.x tag
|
||||
|
||||
jobs:
|
||||
build-connectors:
|
||||
runs-on: windows-latest # Keeping on windows for now, for cross platform building of exe projects, we need to use dotnet publish
|
||||
env:
|
||||
SEMVER: "unset"
|
||||
FILE_VERSION: "unset"
|
||||
outputs:
|
||||
semver: ${{ steps.set-version.outputs.semver }}
|
||||
file_version: ${{ steps.set-version.outputs.file_version }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v5
|
||||
with:
|
||||
dotnet-version: 8.0.4xx # Align with global.json (including roll forward rules)
|
||||
|
||||
- name: Cache Nuget
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ~/.nuget/packages
|
||||
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
||||
|
||||
- name: ⚒️ Run build and zip connectors
|
||||
run: ./build.ps1 zip
|
||||
|
||||
- name: ⬆️ Upload artifacts
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: output-${{ env.SEMVER }}
|
||||
path: output/*.*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
compression-level: 0 # no compression
|
||||
|
||||
- id: set-version
|
||||
name: Set version to output
|
||||
run: |
|
||||
echo "semver=${{ env.SEMVER }}" >> "$Env:GITHUB_OUTPUT"
|
||||
echo "file_version=${{ env.FILE_VERSION }}" >> "$Env:GITHUB_OUTPUT"
|
||||
|
||||
deploy-installers:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-connectors
|
||||
env:
|
||||
IS_PUBLIC_RELEASE: ${{ github.ref_type == 'tag' }}
|
||||
steps:
|
||||
- name: 🔫 Trigger Build Installers
|
||||
uses: benc-uk/workflow-dispatch@v1
|
||||
with:
|
||||
workflow: Build Installers
|
||||
repo: specklesystems/connector-installers
|
||||
token: ${{ secrets.CONNECTORS_GH_TOKEN }}
|
||||
inputs: '{
|
||||
"run_id": "${{ github.run_id }}",
|
||||
"semver": "${{ needs.build-connectors.outputs.semver }}",
|
||||
"file_version": "${{ needs.build-connectors.outputs.file_version }}",
|
||||
"repo": "${{ github.repository }}",
|
||||
"is_public_release": ${{ env.IS_PUBLIC_RELEASE }}
|
||||
}'
|
||||
ref: main
|
||||
wait-for-completion: true
|
||||
sync-status: true
|
||||
timeout-minutes: 15
|
||||
|
||||
# Allows us to inspect the artifacts of failed builds, since this below step will be skipped if the above step fails
|
||||
- uses: geekyeggo/delete-artifact@v6
|
||||
with:
|
||||
name: output-*
|
||||
@@ -19,7 +19,4 @@ tools
|
||||
.DS_Store
|
||||
*.snupkg
|
||||
coverage.xml
|
||||
output/
|
||||
Images/Thumbs.db
|
||||
|
||||
.claude/
|
||||
output/
|
||||
@@ -0,0 +1,424 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.10.35027.167
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Config", "Config", "{85A13E25-EB29-4F31-8853-B9EE83275B3D}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.csharpierrc.yaml = .csharpierrc.yaml
|
||||
.editorconfig = .editorconfig
|
||||
codecov.yml = codecov.yml
|
||||
Directory.Build.props = Directory.Build.props
|
||||
Directory.Build.targets = Directory.Build.targets
|
||||
Directory.Packages.props = Directory.Packages.props
|
||||
global.json = global.json
|
||||
README.md = README.md
|
||||
CodeMetricsConfig.txt = CodeMetricsConfig.txt
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DUI3", "DUI3", "{FD4D6594-D81E-456F-8F2E-35B09E04A755}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Revit", "Revit", "{D92751C8-1039-4005-90B2-913E55E0B8BD}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sdk", "Sdk", "{2E00592E-558D-492D-88F9-3ECEE4C0C7DA}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Connectors.Revit2023", "Connectors\Revit\Speckle.Connectors.Revit2023\Speckle.Connectors.Revit2023.csproj", "{01F98733-7352-47AD-A594-537D979DE3DE}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Speckle.Connectors.RevitShared", "Connectors\Revit\Speckle.Connectors.RevitShared\Speckle.Connectors.RevitShared.shproj", "{DC570FFF-6FE5-47BD-8BC1-B471A6067786}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Speckle.Converters.RevitShared", "Converters\Revit\Speckle.Converters.RevitShared\Speckle.Converters.RevitShared.shproj", "{E1C43415-3200-45F4-8BF9-A4DD7D7F2ED6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Revit2023.DependencyInjection", "Converters\Revit\Speckle.Converters.Revit2023.DependencyInjection\Speckle.Converters.Revit2023.DependencyInjection.csproj", "{83EAD6F0-3CB3-456A-AD81-072127D0DE0E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Revit2023", "Converters\Revit\Speckle.Converters.Revit2023\Speckle.Converters.Revit2023.csproj", "{26391930-F86F-47E0-A5F6-B89919E38CE1}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Connectors.DUI", "DUI3\Speckle.Connectors.DUI\Speckle.Connectors.DUI.csproj", "{D81C0B87-F0C1-4297-A147-02F001FB7E1E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Autofac", "Sdk\Speckle.Autofac\Speckle.Autofac.csproj", "{C9D4CA21-182B-4ED2-81BB-280A6FD713F6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Connectors.Utils", "Sdk\Speckle.Connectors.Utils\Speckle.Connectors.Utils.csproj", "{7291B93C-615D-42DE-B8C1-3F9DF643E0FC}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Common", "Sdk\Speckle.Converters.Common\Speckle.Converters.Common.csproj", "{8AEF06C0-CA5C-4460-BC2D-ADE5F35D0434}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Rhino", "Rhino", "{9584AEE5-CD59-46E6-93E6-2DC2B5285B75}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Connectors.Rhino7", "Connectors\Rhino\Speckle.Connectors.Rhino7\Speckle.Connectors.Rhino7.csproj", "{1E2644A9-6B31-4350-8772-CEAAD6EE0B21}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Rhino7", "Converters\Rhino\Speckle.Converters.Rhino7\Speckle.Converters.Rhino7.csproj", "{65A2F556-F14A-49F3-8A92-7F2E1E7ED3B5}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Rhino7.DependencyInjection", "Converters\Rhino\Speckle.Converters.Rhino7.DependencyInjection\Speckle.Converters.Rhino7.DependencyInjection.csproj", "{9C1ECA1D-DE98-4FB7-92D0-FC45BB308E5D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Connectors.ArcGIS3", "Connectors\ArcGIS\Speckle.Connectors.ArcGIS3\Speckle.Connectors.ArcGIS3.csproj", "{A97F7177-86C7-4B38-A6ED-DA51BF762471}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.ArcGIS3", "Converters\ArcGIS\Speckle.Converters.ArcGIS3\Speckle.Converters.ArcGIS3.csproj", "{139F7A79-69E4-4B8A-B2A5-6A30A66C495C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.ArcGIS3.DependencyInjection", "Converters\ArcGIS\Speckle.Converters.ArcGIS3.DependencyInjection\Speckle.Converters.ArcGIS3.DependencyInjection.csproj", "{7DFF1591-237D-499E-A767-EE37B93FB958}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ArcGIS", "ArcGIS", "{CCF48B65-33D1-4E8B-A57B-E03394730B21}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Connectors.Autocad2023", "Connectors\Autocad\Speckle.Connectors.Autocad2023\Speckle.Connectors.Autocad2023.csproj", "{89C4CBC7-1606-40DE-B6DA-FBE3AAC98395}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Speckle.Connectors.AutocadShared", "Connectors\Autocad\Speckle.Connectors.AutocadShared\Speckle.Connectors.AutocadShared.shproj", "{41BC679F-887F-44CF-971D-A5502EE87DB0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Common.DependencyInjection", "Sdk\Speckle.Converters.Common.DependencyInjection\Speckle.Converters.Common.DependencyInjection.csproj", "{11F7D41B-AFCA-4D29-BC08-285A14BF3A3B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Autocad", "Autocad", "{804E065F-914C-414A-AF84-009312C3CFF6}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Speckle.Converters.AutocadShared", "Converters\Autocad\Speckle.Converters.AutocadShared\Speckle.Converters.AutocadShared.shproj", "{9ADD1B7A-6401-4202-8613-F668E2FBC0A4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Autocad2023", "Converters\Autocad\Speckle.Converters.Autocad2023\Speckle.Converters.Autocad2023.csproj", "{631C295A-7CCF-4B42-8686-7034E31469E7}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Autocad2023.DependencyInjection", "Converters\Autocad\Speckle.Converters.Autocad2023.DependencyInjection\Speckle.Converters.Autocad2023.DependencyInjection.csproj", "{D940853C-003A-482C-BDB0-665367F274A0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Connectors.DUI.WebView", "DUI3\Speckle.Connectors.DUI.WebView\Speckle.Connectors.DUI.WebView.csproj", "{7420652C-3046-4F38-BE64-9B9E69D76FA2}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Build", "Build\Build.csproj", "{C50AA3E3-8C31-4131-9DEC-1D8B377D5A89}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HostApps", "HostApps", "{42826721-9A18-4762-8BA9-F1429DD5C5B1}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{59E8E8F3-4E42-4E92-83B3-B1C2AB901D18}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.github\workflows\ci.yml = .github\workflows\ci.yml
|
||||
.github\workflows\main.yml = .github\workflows\main.yml
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Connectors.Civil3d2024", "Connectors\Autocad\Speckle.Connectors.Civil3d2024\Speckle.Connectors.Civil3d2024.csproj", "{CA8EAE01-AB9F-4EC1-B6F3-73721487E9E1}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Speckle.Converters.Civil3dShared", "Converters\Civil3d\Speckle.Converters.Civil3dShared\Speckle.Converters.Civil3dShared.shproj", "{35175682-DA83-4C0A-A49D-B191F5885D8E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Civil3d2024.DependencyInjection", "Converters\Civil3d\Speckle.Converters.Civil3d2024.DependencyInjection\Speckle.Converters.Civil3d2024.DependencyInjection.csproj", "{80F965C4-E2A8-4F54-985D-73D06E45F9CE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Autocad2024", "Converters\Autocad\Speckle.Converters.Autocad2024\Speckle.Converters.Autocad2024.csproj", "{C2DE264A-AA87-4012-B954-17E3F403A237}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Autocad2024.DependencyInjection", "Converters\Autocad\Speckle.Converters.Autocad2024.DependencyInjection\Speckle.Converters.Autocad2024.DependencyInjection.csproj", "{AF507D61-6766-4C20-9F58-23DC29508219}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Civil3d2024", "Converters\Civil3d\Speckle.Converters.Civil3d2024\Speckle.Converters.Civil3d2024.csproj", "{25172C49-7AA4-4739-BB07-69785094C379}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Speckle.Converters.RhinoShared", "Converters\Rhino\Speckle.Converters.RhinoShared\Speckle.Converters.RhinoShared.shproj", "{E1C43415-3200-45F4-8BF9-A4DD7D7F2ED9}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Rhino7.Tests", "Converters\Rhino\Speckle.Converters.Rhino7.Tests\Speckle.Converters.Rhino7.Tests.csproj", "{AC2DB416-F05C-4296-9040-56D6AD4FCD27}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Revit2023.Tests", "Converters\Revit\Speckle.Converters.Revit2023.Tests\Speckle.Converters.Revit2023.Tests.csproj", "{68CF9BDF-94AC-4D2D-A7BD-D1C064F97051}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Testing", "Sdk\Speckle.Testing\Speckle.Testing.csproj", "{A3869243-B462-4986-914B-94E407D8D20F}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Speckle.Converters.RevitShared.DependencyInjection", "Converters\Revit\Speckle.Converters.RevitShared.DependencyInjection\Speckle.Converters.RevitShared.DependencyInjection.shproj", "{6067BA60-D279-4156-8AE1-6B44E2D19187}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Connectors.Revit2024", "Connectors\Revit\Speckle.Connectors.Revit2024\Speckle.Connectors.Revit2024.csproj", "{617BD3C7-87D9-4D28-8AC9-4910945BB9FC}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Revit2024", "Converters\Revit\Speckle.Converters.Revit2024\Speckle.Converters.Revit2024.csproj", "{67B888D9-C6C4-49F1-883C-5B964151D889}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Revit2024.DependencyInjection", "Converters\Revit\Speckle.Converters.Revit2024.DependencyInjection\Speckle.Converters.Revit2024.DependencyInjection.csproj", "{7F3055BA-70AA-424C-8748-345AF35127E9}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2023", "2023", "{E9DEBA00-50A4-485D-BA65-D8AB3E3467AB}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2024", "2024", "{57F59C0C-5687-4AF9-AE1C-1933B539F0E4}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{FC224610-32D3-454E-9BC1-1219FE8ACD5F}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Speckle.Converters.RevitShared.Tests", "Converters\Revit\Speckle.Converters.RevitShared.Tests\Speckle.Converters.RevitShared.Tests.shproj", "{E1C43415-3202-45F4-8BF9-A4DD7D7F2ED6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Revit2024.Tests", "Converters\Revit\Speckle.Converters.Revit2024.Tests\Speckle.Converters.Revit2024.Tests.csproj", "{C32274D9-1B66-4D5C-82F9-EB3F10F46752}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Speckle.Connectors.RevitShared.Cef", "Connectors\Revit\Speckle.Connectors.RevitShared.Cef\Speckle.Connectors.RevitShared.Cef.shproj", "{6A40CBE4-ECAB-4CED-9917-5C64CBF75DA6}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2025", "2025", "{8AC2AD6D-6C74-4B24-8DF6-42717FC9B804}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Connectors.Revit2025", "Connectors\Revit\Speckle.Connectors.Revit2025\Speckle.Connectors.Revit2025.csproj", "{A6DE3DA0-B242-4F49-AEF0-4E26AF92D16C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Revit2025", "Converters\Revit\Speckle.Converters.Revit2025\Speckle.Converters.Revit2025.csproj", "{4D40A101-07E6-4FF2-8934-83434932591D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Revit2025.DependencyInjection", "Converters\Revit\Speckle.Converters.Revit2025.DependencyInjection\Speckle.Converters.Revit2025.DependencyInjection.csproj", "{20751904-0DFC-4126-BF2A-834B53841010}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Connectors.Revit2022", "Connectors\Revit\Speckle.Connectors.Revit2022\Speckle.Connectors.Revit2022.csproj", "{7F1FDCF2-0CE8-4119-B3C1-F2CC6D7E1C36}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Revit2022", "Converters\Revit\Speckle.Converters.Revit2022\Speckle.Converters.Revit2022.csproj", "{19424B55-058C-4E9C-B86F-700AEF9EAEC3}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Revit2022.DependencyInjection", "Converters\Revit\Speckle.Converters.Revit2022.DependencyInjection\Speckle.Converters.Revit2022.DependencyInjection.csproj", "{881D71A3-D276-4108-98C6-0FFD32129B9C}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2022", "2022", "{0AF38BA3-65A0-481B-8CBB-B82E406E1575}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Connectors.DUI.Tests", "DUI3\Speckle.Connectors.DUI.Tests\Speckle.Connectors.DUI.Tests.csproj", "{EB83A3A3-F9B6-4281-8EBF-F7289FB5D885}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.Converters.Revit2022.Tests", "Converters\Revit\Speckle.Converters.Revit2022.Tests\Speckle.Converters.Revit2022.Tests.csproj", "{D8069A23-AD2E-4C9E-8574-7E8C45296A46}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2023", "2023", "{2D5AE63D-85C0-43D1-84BF-04418ED93F63}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2024", "2024", "{2F45036E-D817-41E9-B82F-DBE013EC95D0}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Civil3d", "Civil3d", "{91D70DE1-DC8E-4AE1-B100-0671D6263FC5}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{4721AA15-AF6E-4A62-A2C3-65564DC563E6}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{01F98733-7352-47AD-A594-537D979DE3DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{01F98733-7352-47AD-A594-537D979DE3DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{01F98733-7352-47AD-A594-537D979DE3DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{01F98733-7352-47AD-A594-537D979DE3DE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{83EAD6F0-3CB3-456A-AD81-072127D0DE0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{83EAD6F0-3CB3-456A-AD81-072127D0DE0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{83EAD6F0-3CB3-456A-AD81-072127D0DE0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{83EAD6F0-3CB3-456A-AD81-072127D0DE0E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{26391930-F86F-47E0-A5F6-B89919E38CE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{26391930-F86F-47E0-A5F6-B89919E38CE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{26391930-F86F-47E0-A5F6-B89919E38CE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{26391930-F86F-47E0-A5F6-B89919E38CE1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D81C0B87-F0C1-4297-A147-02F001FB7E1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D81C0B87-F0C1-4297-A147-02F001FB7E1E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D81C0B87-F0C1-4297-A147-02F001FB7E1E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D81C0B87-F0C1-4297-A147-02F001FB7E1E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C9D4CA21-182B-4ED2-81BB-280A6FD713F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C9D4CA21-182B-4ED2-81BB-280A6FD713F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C9D4CA21-182B-4ED2-81BB-280A6FD713F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C9D4CA21-182B-4ED2-81BB-280A6FD713F6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7291B93C-615D-42DE-B8C1-3F9DF643E0FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7291B93C-615D-42DE-B8C1-3F9DF643E0FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7291B93C-615D-42DE-B8C1-3F9DF643E0FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7291B93C-615D-42DE-B8C1-3F9DF643E0FC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8AEF06C0-CA5C-4460-BC2D-ADE5F35D0434}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8AEF06C0-CA5C-4460-BC2D-ADE5F35D0434}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8AEF06C0-CA5C-4460-BC2D-ADE5F35D0434}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8AEF06C0-CA5C-4460-BC2D-ADE5F35D0434}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1E2644A9-6B31-4350-8772-CEAAD6EE0B21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1E2644A9-6B31-4350-8772-CEAAD6EE0B21}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1E2644A9-6B31-4350-8772-CEAAD6EE0B21}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1E2644A9-6B31-4350-8772-CEAAD6EE0B21}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{65A2F556-F14A-49F3-8A92-7F2E1E7ED3B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{65A2F556-F14A-49F3-8A92-7F2E1E7ED3B5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{65A2F556-F14A-49F3-8A92-7F2E1E7ED3B5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{65A2F556-F14A-49F3-8A92-7F2E1E7ED3B5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9C1ECA1D-DE98-4FB7-92D0-FC45BB308E5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9C1ECA1D-DE98-4FB7-92D0-FC45BB308E5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9C1ECA1D-DE98-4FB7-92D0-FC45BB308E5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9C1ECA1D-DE98-4FB7-92D0-FC45BB308E5D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A97F7177-86C7-4B38-A6ED-DA51BF762471}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A97F7177-86C7-4B38-A6ED-DA51BF762471}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A97F7177-86C7-4B38-A6ED-DA51BF762471}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A97F7177-86C7-4B38-A6ED-DA51BF762471}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{139F7A79-69E4-4B8A-B2A5-6A30A66C495C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{139F7A79-69E4-4B8A-B2A5-6A30A66C495C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{139F7A79-69E4-4B8A-B2A5-6A30A66C495C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{139F7A79-69E4-4B8A-B2A5-6A30A66C495C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7DFF1591-237D-499E-A767-EE37B93FB958}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7DFF1591-237D-499E-A767-EE37B93FB958}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7DFF1591-237D-499E-A767-EE37B93FB958}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7DFF1591-237D-499E-A767-EE37B93FB958}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{89C4CBC7-1606-40DE-B6DA-FBE3AAC98395}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{89C4CBC7-1606-40DE-B6DA-FBE3AAC98395}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{89C4CBC7-1606-40DE-B6DA-FBE3AAC98395}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{89C4CBC7-1606-40DE-B6DA-FBE3AAC98395}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{11F7D41B-AFCA-4D29-BC08-285A14BF3A3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{11F7D41B-AFCA-4D29-BC08-285A14BF3A3B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{11F7D41B-AFCA-4D29-BC08-285A14BF3A3B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{11F7D41B-AFCA-4D29-BC08-285A14BF3A3B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{631C295A-7CCF-4B42-8686-7034E31469E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{631C295A-7CCF-4B42-8686-7034E31469E7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{631C295A-7CCF-4B42-8686-7034E31469E7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{631C295A-7CCF-4B42-8686-7034E31469E7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D940853C-003A-482C-BDB0-665367F274A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D940853C-003A-482C-BDB0-665367F274A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D940853C-003A-482C-BDB0-665367F274A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D940853C-003A-482C-BDB0-665367F274A0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7420652C-3046-4F38-BE64-9B9E69D76FA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7420652C-3046-4F38-BE64-9B9E69D76FA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7420652C-3046-4F38-BE64-9B9E69D76FA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7420652C-3046-4F38-BE64-9B9E69D76FA2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C50AA3E3-8C31-4131-9DEC-1D8B377D5A89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C50AA3E3-8C31-4131-9DEC-1D8B377D5A89}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C50AA3E3-8C31-4131-9DEC-1D8B377D5A89}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C50AA3E3-8C31-4131-9DEC-1D8B377D5A89}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CA8EAE01-AB9F-4EC1-B6F3-73721487E9E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CA8EAE01-AB9F-4EC1-B6F3-73721487E9E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CA8EAE01-AB9F-4EC1-B6F3-73721487E9E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CA8EAE01-AB9F-4EC1-B6F3-73721487E9E1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{80F965C4-E2A8-4F54-985D-73D06E45F9CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{80F965C4-E2A8-4F54-985D-73D06E45F9CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{80F965C4-E2A8-4F54-985D-73D06E45F9CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{80F965C4-E2A8-4F54-985D-73D06E45F9CE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C2DE264A-AA87-4012-B954-17E3F403A237}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C2DE264A-AA87-4012-B954-17E3F403A237}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C2DE264A-AA87-4012-B954-17E3F403A237}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C2DE264A-AA87-4012-B954-17E3F403A237}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AF507D61-6766-4C20-9F58-23DC29508219}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AF507D61-6766-4C20-9F58-23DC29508219}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AF507D61-6766-4C20-9F58-23DC29508219}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AF507D61-6766-4C20-9F58-23DC29508219}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{25172C49-7AA4-4739-BB07-69785094C379}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{25172C49-7AA4-4739-BB07-69785094C379}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{25172C49-7AA4-4739-BB07-69785094C379}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{25172C49-7AA4-4739-BB07-69785094C379}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AC2DB416-F05C-4296-9040-56D6AD4FCD27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AC2DB416-F05C-4296-9040-56D6AD4FCD27}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AC2DB416-F05C-4296-9040-56D6AD4FCD27}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AC2DB416-F05C-4296-9040-56D6AD4FCD27}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{68CF9BDF-94AC-4D2D-A7BD-D1C064F97051}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{68CF9BDF-94AC-4D2D-A7BD-D1C064F97051}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{68CF9BDF-94AC-4D2D-A7BD-D1C064F97051}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{68CF9BDF-94AC-4D2D-A7BD-D1C064F97051}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A3869243-B462-4986-914B-94E407D8D20F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A3869243-B462-4986-914B-94E407D8D20F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A3869243-B462-4986-914B-94E407D8D20F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A3869243-B462-4986-914B-94E407D8D20F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{617BD3C7-87D9-4D28-8AC9-4910945BB9FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{617BD3C7-87D9-4D28-8AC9-4910945BB9FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{617BD3C7-87D9-4D28-8AC9-4910945BB9FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{617BD3C7-87D9-4D28-8AC9-4910945BB9FC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{67B888D9-C6C4-49F1-883C-5B964151D889}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{67B888D9-C6C4-49F1-883C-5B964151D889}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{67B888D9-C6C4-49F1-883C-5B964151D889}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{67B888D9-C6C4-49F1-883C-5B964151D889}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7F3055BA-70AA-424C-8748-345AF35127E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7F3055BA-70AA-424C-8748-345AF35127E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7F3055BA-70AA-424C-8748-345AF35127E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7F3055BA-70AA-424C-8748-345AF35127E9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C32274D9-1B66-4D5C-82F9-EB3F10F46752}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C32274D9-1B66-4D5C-82F9-EB3F10F46752}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C32274D9-1B66-4D5C-82F9-EB3F10F46752}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C32274D9-1B66-4D5C-82F9-EB3F10F46752}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A6DE3DA0-B242-4F49-AEF0-4E26AF92D16C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A6DE3DA0-B242-4F49-AEF0-4E26AF92D16C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A6DE3DA0-B242-4F49-AEF0-4E26AF92D16C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A6DE3DA0-B242-4F49-AEF0-4E26AF92D16C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4D40A101-07E6-4FF2-8934-83434932591D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4D40A101-07E6-4FF2-8934-83434932591D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4D40A101-07E6-4FF2-8934-83434932591D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4D40A101-07E6-4FF2-8934-83434932591D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{20751904-0DFC-4126-BF2A-834B53841010}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{20751904-0DFC-4126-BF2A-834B53841010}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{20751904-0DFC-4126-BF2A-834B53841010}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{20751904-0DFC-4126-BF2A-834B53841010}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7F1FDCF2-0CE8-4119-B3C1-F2CC6D7E1C36}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{7F1FDCF2-0CE8-4119-B3C1-F2CC6D7E1C36}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{7F1FDCF2-0CE8-4119-B3C1-F2CC6D7E1C36}.Release|Any CPU.ActiveCfg = Debug|x64
|
||||
{7F1FDCF2-0CE8-4119-B3C1-F2CC6D7E1C36}.Release|Any CPU.Build.0 = Debug|x64
|
||||
{19424B55-058C-4E9C-B86F-700AEF9EAEC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{19424B55-058C-4E9C-B86F-700AEF9EAEC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{19424B55-058C-4E9C-B86F-700AEF9EAEC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{19424B55-058C-4E9C-B86F-700AEF9EAEC3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{881D71A3-D276-4108-98C6-0FFD32129B9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{881D71A3-D276-4108-98C6-0FFD32129B9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{881D71A3-D276-4108-98C6-0FFD32129B9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{881D71A3-D276-4108-98C6-0FFD32129B9C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EB83A3A3-F9B6-4281-8EBF-F7289FB5D885}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EB83A3A3-F9B6-4281-8EBF-F7289FB5D885}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EB83A3A3-F9B6-4281-8EBF-F7289FB5D885}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EB83A3A3-F9B6-4281-8EBF-F7289FB5D885}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D8069A23-AD2E-4C9E-8574-7E8C45296A46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D8069A23-AD2E-4C9E-8574-7E8C45296A46}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D8069A23-AD2E-4C9E-8574-7E8C45296A46}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D8069A23-AD2E-4C9E-8574-7E8C45296A46}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{D92751C8-1039-4005-90B2-913E55E0B8BD} = {42826721-9A18-4762-8BA9-F1429DD5C5B1}
|
||||
{01F98733-7352-47AD-A594-537D979DE3DE} = {E9DEBA00-50A4-485D-BA65-D8AB3E3467AB}
|
||||
{DC570FFF-6FE5-47BD-8BC1-B471A6067786} = {FC224610-32D3-454E-9BC1-1219FE8ACD5F}
|
||||
{E1C43415-3200-45F4-8BF9-A4DD7D7F2ED6} = {FC224610-32D3-454E-9BC1-1219FE8ACD5F}
|
||||
{83EAD6F0-3CB3-456A-AD81-072127D0DE0E} = {E9DEBA00-50A4-485D-BA65-D8AB3E3467AB}
|
||||
{26391930-F86F-47E0-A5F6-B89919E38CE1} = {E9DEBA00-50A4-485D-BA65-D8AB3E3467AB}
|
||||
{D81C0B87-F0C1-4297-A147-02F001FB7E1E} = {FD4D6594-D81E-456F-8F2E-35B09E04A755}
|
||||
{C9D4CA21-182B-4ED2-81BB-280A6FD713F6} = {2E00592E-558D-492D-88F9-3ECEE4C0C7DA}
|
||||
{7291B93C-615D-42DE-B8C1-3F9DF643E0FC} = {2E00592E-558D-492D-88F9-3ECEE4C0C7DA}
|
||||
{8AEF06C0-CA5C-4460-BC2D-ADE5F35D0434} = {2E00592E-558D-492D-88F9-3ECEE4C0C7DA}
|
||||
{9584AEE5-CD59-46E6-93E6-2DC2B5285B75} = {42826721-9A18-4762-8BA9-F1429DD5C5B1}
|
||||
{1E2644A9-6B31-4350-8772-CEAAD6EE0B21} = {9584AEE5-CD59-46E6-93E6-2DC2B5285B75}
|
||||
{65A2F556-F14A-49F3-8A92-7F2E1E7ED3B5} = {9584AEE5-CD59-46E6-93E6-2DC2B5285B75}
|
||||
{9C1ECA1D-DE98-4FB7-92D0-FC45BB308E5D} = {9584AEE5-CD59-46E6-93E6-2DC2B5285B75}
|
||||
{A97F7177-86C7-4B38-A6ED-DA51BF762471} = {CCF48B65-33D1-4E8B-A57B-E03394730B21}
|
||||
{139F7A79-69E4-4B8A-B2A5-6A30A66C495C} = {CCF48B65-33D1-4E8B-A57B-E03394730B21}
|
||||
{7DFF1591-237D-499E-A767-EE37B93FB958} = {CCF48B65-33D1-4E8B-A57B-E03394730B21}
|
||||
{CCF48B65-33D1-4E8B-A57B-E03394730B21} = {42826721-9A18-4762-8BA9-F1429DD5C5B1}
|
||||
{11F7D41B-AFCA-4D29-BC08-285A14BF3A3B} = {2E00592E-558D-492D-88F9-3ECEE4C0C7DA}
|
||||
{804E065F-914C-414A-AF84-009312C3CFF6} = {42826721-9A18-4762-8BA9-F1429DD5C5B1}
|
||||
{7420652C-3046-4F38-BE64-9B9E69D76FA2} = {FD4D6594-D81E-456F-8F2E-35B09E04A755}
|
||||
{C50AA3E3-8C31-4131-9DEC-1D8B377D5A89} = {59E8E8F3-4E42-4E92-83B3-B1C2AB901D18}
|
||||
{E1C43415-3200-45F4-8BF9-A4DD7D7F2ED9} = {9584AEE5-CD59-46E6-93E6-2DC2B5285B75}
|
||||
{AC2DB416-F05C-4296-9040-56D6AD4FCD27} = {9584AEE5-CD59-46E6-93E6-2DC2B5285B75}
|
||||
{68CF9BDF-94AC-4D2D-A7BD-D1C064F97051} = {E9DEBA00-50A4-485D-BA65-D8AB3E3467AB}
|
||||
{A3869243-B462-4986-914B-94E407D8D20F} = {2E00592E-558D-492D-88F9-3ECEE4C0C7DA}
|
||||
{6067BA60-D279-4156-8AE1-6B44E2D19187} = {FC224610-32D3-454E-9BC1-1219FE8ACD5F}
|
||||
{617BD3C7-87D9-4D28-8AC9-4910945BB9FC} = {57F59C0C-5687-4AF9-AE1C-1933B539F0E4}
|
||||
{67B888D9-C6C4-49F1-883C-5B964151D889} = {57F59C0C-5687-4AF9-AE1C-1933B539F0E4}
|
||||
{7F3055BA-70AA-424C-8748-345AF35127E9} = {57F59C0C-5687-4AF9-AE1C-1933B539F0E4}
|
||||
{E9DEBA00-50A4-485D-BA65-D8AB3E3467AB} = {D92751C8-1039-4005-90B2-913E55E0B8BD}
|
||||
{57F59C0C-5687-4AF9-AE1C-1933B539F0E4} = {D92751C8-1039-4005-90B2-913E55E0B8BD}
|
||||
{FC224610-32D3-454E-9BC1-1219FE8ACD5F} = {D92751C8-1039-4005-90B2-913E55E0B8BD}
|
||||
{E1C43415-3202-45F4-8BF9-A4DD7D7F2ED6} = {FC224610-32D3-454E-9BC1-1219FE8ACD5F}
|
||||
{C32274D9-1B66-4D5C-82F9-EB3F10F46752} = {57F59C0C-5687-4AF9-AE1C-1933B539F0E4}
|
||||
{6A40CBE4-ECAB-4CED-9917-5C64CBF75DA6} = {FC224610-32D3-454E-9BC1-1219FE8ACD5F}
|
||||
{8AC2AD6D-6C74-4B24-8DF6-42717FC9B804} = {D92751C8-1039-4005-90B2-913E55E0B8BD}
|
||||
{A6DE3DA0-B242-4F49-AEF0-4E26AF92D16C} = {8AC2AD6D-6C74-4B24-8DF6-42717FC9B804}
|
||||
{4D40A101-07E6-4FF2-8934-83434932591D} = {8AC2AD6D-6C74-4B24-8DF6-42717FC9B804}
|
||||
{20751904-0DFC-4126-BF2A-834B53841010} = {8AC2AD6D-6C74-4B24-8DF6-42717FC9B804}
|
||||
{7F1FDCF2-0CE8-4119-B3C1-F2CC6D7E1C36} = {0AF38BA3-65A0-481B-8CBB-B82E406E1575}
|
||||
{19424B55-058C-4E9C-B86F-700AEF9EAEC3} = {0AF38BA3-65A0-481B-8CBB-B82E406E1575}
|
||||
{881D71A3-D276-4108-98C6-0FFD32129B9C} = {0AF38BA3-65A0-481B-8CBB-B82E406E1575}
|
||||
{0AF38BA3-65A0-481B-8CBB-B82E406E1575} = {D92751C8-1039-4005-90B2-913E55E0B8BD}
|
||||
{EB83A3A3-F9B6-4281-8EBF-F7289FB5D885} = {FD4D6594-D81E-456F-8F2E-35B09E04A755}
|
||||
{D8069A23-AD2E-4C9E-8574-7E8C45296A46} = {0AF38BA3-65A0-481B-8CBB-B82E406E1575}
|
||||
{2D5AE63D-85C0-43D1-84BF-04418ED93F63} = {804E065F-914C-414A-AF84-009312C3CFF6}
|
||||
{89C4CBC7-1606-40DE-B6DA-FBE3AAC98395} = {2D5AE63D-85C0-43D1-84BF-04418ED93F63}
|
||||
{631C295A-7CCF-4B42-8686-7034E31469E7} = {2D5AE63D-85C0-43D1-84BF-04418ED93F63}
|
||||
{D940853C-003A-482C-BDB0-665367F274A0} = {2D5AE63D-85C0-43D1-84BF-04418ED93F63}
|
||||
{2F45036E-D817-41E9-B82F-DBE013EC95D0} = {804E065F-914C-414A-AF84-009312C3CFF6}
|
||||
{C2DE264A-AA87-4012-B954-17E3F403A237} = {2F45036E-D817-41E9-B82F-DBE013EC95D0}
|
||||
{AF507D61-6766-4C20-9F58-23DC29508219} = {2F45036E-D817-41E9-B82F-DBE013EC95D0}
|
||||
{91D70DE1-DC8E-4AE1-B100-0671D6263FC5} = {804E065F-914C-414A-AF84-009312C3CFF6}
|
||||
{CA8EAE01-AB9F-4EC1-B6F3-73721487E9E1} = {91D70DE1-DC8E-4AE1-B100-0671D6263FC5}
|
||||
{25172C49-7AA4-4739-BB07-69785094C379} = {91D70DE1-DC8E-4AE1-B100-0671D6263FC5}
|
||||
{80F965C4-E2A8-4F54-985D-73D06E45F9CE} = {91D70DE1-DC8E-4AE1-B100-0671D6263FC5}
|
||||
{35175682-DA83-4C0A-A49D-B191F5885D8E} = {91D70DE1-DC8E-4AE1-B100-0671D6263FC5}
|
||||
{4721AA15-AF6E-4A62-A2C3-65564DC563E6} = {804E065F-914C-414A-AF84-009312C3CFF6}
|
||||
{41BC679F-887F-44CF-971D-A5502EE87DB0} = {4721AA15-AF6E-4A62-A2C3-65564DC563E6}
|
||||
{9ADD1B7A-6401-4202-8613-F668E2FBC0A4} = {4721AA15-AF6E-4A62-A2C3-65564DC563E6}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {EE253116-7070-4E9A-BCE8-2911C251B8C8}
|
||||
EndGlobalSection
|
||||
GlobalSection(SharedMSBuildProjectFiles) = preSolution
|
||||
Connectors\Revit\Speckle.Connectors.RevitShared.Cef\Speckle.Connectors.RevitShared.Cef.projitems*{01f98733-7352-47ad-a594-537d979de3de}*SharedItemsImports = 5
|
||||
Connectors\Revit\Speckle.Connectors.RevitShared\Speckle.Connectors.RevitShared.projitems*{01f98733-7352-47ad-a594-537d979de3de}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared\Speckle.Converters.RevitShared.projitems*{19424b55-058c-4e9c-b86f-700aef9eaec3}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared.DependencyInjection\Speckle.Converters.RevitShared.DependencyInjection.projitems*{20751904-0dfc-4126-bf2a-834b53841010}*SharedItemsImports = 5
|
||||
Converters\Autocad\Speckle.Converters.AutocadShared\Speckle.Converters.AutocadShared.projitems*{25172c49-7aa4-4739-bb07-69785094c379}*SharedItemsImports = 5
|
||||
Converters\Civil3d\Speckle.Converters.Civil3dShared\Speckle.Converters.Civil3dShared.projitems*{25172c49-7aa4-4739-bb07-69785094c379}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared\Speckle.Converters.RevitShared.projitems*{26391930-f86f-47e0-a5f6-b89919e38ce1}*SharedItemsImports = 5
|
||||
Converters\Civil3d\Speckle.Converters.Civil3dShared\Speckle.Converters.Civil3dShared.projitems*{35175682-da83-4c0a-a49d-b191f5885d8e}*SharedItemsImports = 13
|
||||
Connectors\Autocad\Speckle.Connectors.AutocadShared\Speckle.Connectors.AutocadShared.projitems*{41bc679f-887f-44cf-971d-a5502ee87db0}*SharedItemsImports = 13
|
||||
Converters\Revit\Speckle.Converters.RevitShared\Speckle.Converters.RevitShared.projitems*{4d40a101-07e6-4ff2-8934-83434932591d}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared.DependencyInjection\Speckle.Converters.RevitShared.DependencyInjection.projitems*{6067ba60-d279-4156-8ae1-6b44e2d19187}*SharedItemsImports = 13
|
||||
Connectors\Revit\Speckle.Connectors.RevitShared.Cef\Speckle.Connectors.RevitShared.Cef.projitems*{617bd3c7-87d9-4d28-8ac9-4910945bb9fc}*SharedItemsImports = 5
|
||||
Connectors\Revit\Speckle.Connectors.RevitShared\Speckle.Connectors.RevitShared.projitems*{617bd3c7-87d9-4d28-8ac9-4910945bb9fc}*SharedItemsImports = 5
|
||||
Converters\Autocad\Speckle.Converters.AutocadShared\Speckle.Converters.AutocadShared.projitems*{631c295a-7ccf-4b42-8686-7034e31469e7}*SharedItemsImports = 5
|
||||
Converters\Rhino\Speckle.Converters.RhinoShared\Speckle.Converters.RhinoShared.projitems*{65a2f556-f14a-49f3-8a92-7f2e1e7ed3b5}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared\Speckle.Converters.RevitShared.projitems*{67b888d9-c6c4-49f1-883c-5b964151d889}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared.Tests\Speckle.Converters.RevitShared.Tests.projitems*{68cf9bdf-94ac-4d2d-a7bd-d1c064f97051}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared\Speckle.Converters.RevitShared.projitems*{68cf9bdf-94ac-4d2d-a7bd-d1c064f97051}*SharedItemsImports = 5
|
||||
Connectors\Revit\Speckle.Connectors.RevitShared.Cef\Speckle.Connectors.RevitShared.Cef.projitems*{6a40cbe4-ecab-4ced-9917-5c64cbf75da6}*SharedItemsImports = 13
|
||||
Connectors\Revit\Speckle.Connectors.RevitShared.Cef\Speckle.Connectors.RevitShared.Cef.projitems*{7f1fdcf2-0ce8-4119-b3c1-f2cc6d7e1c36}*SharedItemsImports = 5
|
||||
Connectors\Revit\Speckle.Connectors.RevitShared\Speckle.Connectors.RevitShared.projitems*{7f1fdcf2-0ce8-4119-b3c1-f2cc6d7e1c36}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared.DependencyInjection\Speckle.Converters.RevitShared.DependencyInjection.projitems*{7f3055ba-70aa-424c-8748-345af35127e9}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared.DependencyInjection\Speckle.Converters.RevitShared.DependencyInjection.projitems*{83ead6f0-3cb3-456a-ad81-072127d0de0e}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared.DependencyInjection\Speckle.Converters.RevitShared.DependencyInjection.projitems*{881d71a3-d276-4108-98c6-0ffd32129b9c}*SharedItemsImports = 5
|
||||
Connectors\Autocad\Speckle.Connectors.AutocadShared\Speckle.Connectors.AutocadShared.projitems*{89c4cbc7-1606-40de-b6da-fbe3aac98395}*SharedItemsImports = 5
|
||||
Converters\Autocad\Speckle.Converters.AutocadShared\Speckle.Converters.AutocadShared.projitems*{9add1b7a-6401-4202-8613-f668e2fbc0a4}*SharedItemsImports = 13
|
||||
Connectors\Revit\Speckle.Connectors.RevitShared\Speckle.Connectors.RevitShared.projitems*{a6de3da0-b242-4f49-aef0-4e26af92d16c}*SharedItemsImports = 5
|
||||
Converters\Rhino\Speckle.Converters.RhinoShared\Speckle.Converters.RhinoShared.projitems*{ac2db416-f05c-4296-9040-56d6ad4fcd27}*SharedItemsImports = 5
|
||||
Converters\Autocad\Speckle.Converters.AutocadShared\Speckle.Converters.AutocadShared.projitems*{c2de264a-aa87-4012-b954-17e3f403a237}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared.Tests\Speckle.Converters.RevitShared.Tests.projitems*{c32274d9-1b66-4d5c-82f9-eb3f10f46752}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared\Speckle.Converters.RevitShared.projitems*{c32274d9-1b66-4d5c-82f9-eb3f10f46752}*SharedItemsImports = 5
|
||||
Connectors\Autocad\Speckle.Connectors.AutocadShared\Speckle.Connectors.AutocadShared.projitems*{ca8eae01-ab9f-4ec1-b6f3-73721487e9e1}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared.Tests\Speckle.Converters.RevitShared.Tests.projitems*{d8069a23-ad2e-4c9e-8574-7e8c45296a46}*SharedItemsImports = 5
|
||||
Converters\Revit\Speckle.Converters.RevitShared\Speckle.Converters.RevitShared.projitems*{d8069a23-ad2e-4c9e-8574-7e8c45296a46}*SharedItemsImports = 5
|
||||
Connectors\Revit\Speckle.Connectors.RevitShared\Speckle.Connectors.RevitShared.projitems*{dc570fff-6fe5-47bd-8bc1-b471a6067786}*SharedItemsImports = 13
|
||||
Converters\Revit\Speckle.Converters.RevitShared\Speckle.Converters.RevitShared.projitems*{e1c43415-3200-45f4-8bf9-a4dd7d7f2ed6}*SharedItemsImports = 13
|
||||
Converters\Rhino\Speckle.Converters.RhinoShared\Speckle.Converters.RhinoShared.projitems*{e1c43415-3200-45f4-8bf9-a4dd7d7f2ed9}*SharedItemsImports = 13
|
||||
Converters\Revit\Speckle.Converters.RevitShared.Tests\Speckle.Converters.RevitShared.Tests.projitems*{e1c43415-3202-45f4-8bf9-a4dd7d7f2ed6}*SharedItemsImports = 13
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,116 +0,0 @@
|
||||
using GlobExpressions;
|
||||
using Microsoft.Build.Construction;
|
||||
using static SimpleExec.Command;
|
||||
|
||||
namespace Build;
|
||||
|
||||
public static class Affected
|
||||
{
|
||||
public static readonly string Root = Environment.CurrentDirectory;
|
||||
public const string AFFECTED_PROJECT = "affected.proj";
|
||||
|
||||
private static IEnumerable<string> GetAffectedProjects()
|
||||
{
|
||||
var projFile = Path.Combine(Root, AFFECTED_PROJECT);
|
||||
Console.WriteLine("Affected project file: " + projFile);
|
||||
var project = ProjectRootElement.Open(projFile) ?? throw new InvalidOperationException();
|
||||
var references = project.ItemGroups.SelectMany(x => x.Items).Where(x => x.ItemType == "ProjectReference");
|
||||
|
||||
foreach (var refe in references)
|
||||
{
|
||||
var referencePath = refe.Include[(Root.Length + 1)..];
|
||||
referencePath = Path.GetDirectoryName(referencePath) ?? throw new InvalidOperationException();
|
||||
if (Path.DirectorySeparatorChar != '/')
|
||||
{
|
||||
referencePath = referencePath.Replace(Path.DirectorySeparatorChar, '/');
|
||||
}
|
||||
|
||||
yield return referencePath;
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<IEnumerable<string>> GetTestProjects()
|
||||
{
|
||||
await ComputeAffected();
|
||||
var projFile = Path.Combine(Root, AFFECTED_PROJECT);
|
||||
if (File.Exists(projFile))
|
||||
{
|
||||
var references = GetAffectedProjects();
|
||||
return references.Where(x => x.Contains("Tests"));
|
||||
}
|
||||
return Glob.Files(Root, "**/*.Tests.csproj");
|
||||
}
|
||||
|
||||
public static async Task<ProjectGroup[]> GetAffectedProjectGroups()
|
||||
{
|
||||
await ComputeAffected();
|
||||
var projFile = Path.Combine(Root, AFFECTED_PROJECT);
|
||||
if (File.Exists(projFile))
|
||||
{
|
||||
var references = GetAffectedProjects().ToList();
|
||||
var groups = new List<ProjectGroup>();
|
||||
foreach (var projectGroup in Consts.ProjectGroups)
|
||||
{
|
||||
foreach (var referencePath in references)
|
||||
{
|
||||
if (projectGroup.Projects.Any(x => x.ProjectPath.Contains(referencePath)))
|
||||
{
|
||||
groups.Add(projectGroup);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var group in groups)
|
||||
{
|
||||
Console.WriteLine("Affected project group being built: " + group.HostAppSlug);
|
||||
}
|
||||
|
||||
return groups.ToArray();
|
||||
}
|
||||
|
||||
Console.WriteLine("Using all project groups: " + string.Join(',', Consts.ProjectGroups));
|
||||
return Consts.ProjectGroups;
|
||||
}
|
||||
|
||||
private static bool s_affectedComputed;
|
||||
|
||||
public static async Task ComputeAffected()
|
||||
{
|
||||
if (s_affectedComputed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var currentTag = await Versions.GetCurrentTag();
|
||||
var currentVersion = await Versions.ComputeVersion();
|
||||
var lastTag = await Versions.GetPreviousTag(currentTag);
|
||||
var lastVersion = await Versions.ComputePreviousVersion(currentTag);
|
||||
|
||||
Console.WriteLine($"Last tag: {lastTag}, Current tag: {currentTag}");
|
||||
Console.WriteLine($"Last parsed version: {lastVersion}, Current parsed version: {currentVersion}");
|
||||
|
||||
var sort = currentVersion.CompareSortOrderTo(lastVersion);
|
||||
if (sort == -1)
|
||||
{
|
||||
Console.WriteLine($"Current version {currentVersion} is less than: {lastVersion}");
|
||||
s_affectedComputed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
var majorEquals = currentVersion.Major == lastVersion.Major;
|
||||
if (!majorEquals)
|
||||
{
|
||||
Console.WriteLine($"Current version {currentVersion} is not matching major version: {lastVersion}");
|
||||
s_affectedComputed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
//use tags no matter the version if major versions match
|
||||
var (currentCommit, _) = await ReadAsync("git", $"rev-list -n 1 {currentTag}");
|
||||
var (lastCommit, _) = await ReadAsync("git", $"rev-list -n 1 {lastTag}");
|
||||
await RunAsync("dotnet", $"affected -v --from {currentCommit.Trim()} --to {lastCommit.Trim()}", Root);
|
||||
|
||||
s_affectedComputed = true;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
@@ -9,8 +10,6 @@
|
||||
<PackageReference Include="Bullseye" />
|
||||
<PackageReference Include="Glob" />
|
||||
<PackageReference Include="Microsoft.Build" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.SolutionPersistence" />
|
||||
<PackageReference Include="Semver" />
|
||||
<PackageReference Include="SimpleExec" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -4,13 +4,14 @@ public static class Consts
|
||||
{
|
||||
public static readonly string[] Solutions = ["Speckle.Connectors.sln"];
|
||||
|
||||
public static readonly ProjectGroup[] ProjectGroups =
|
||||
public static readonly InstallerProject[] InstallerManifests =
|
||||
{
|
||||
new("arcgis", [new("Connectors/ArcGIS/Speckle.Connectors.ArcGIS3", "net6.0-windows")]),
|
||||
new(
|
||||
"rhino",
|
||||
[
|
||||
new("Connectors/Rhino/Speckle.Connectors.Rhino7", "net48"),
|
||||
new("Connectors/Rhino/Speckle.Connectors.Rhino8", "net48"),
|
||||
new("Connectors/Rhino/Speckle.Connectors.Rhino8", "net48")
|
||||
]
|
||||
),
|
||||
new(
|
||||
@@ -19,63 +20,14 @@ public static class Consts
|
||||
new("Connectors/Revit/Speckle.Connectors.Revit2022", "net48"),
|
||||
new("Connectors/Revit/Speckle.Connectors.Revit2023", "net48"),
|
||||
new("Connectors/Revit/Speckle.Connectors.Revit2024", "net48"),
|
||||
new("Connectors/Revit/Speckle.Connectors.Revit2025", "net8.0-windows"),
|
||||
new("Connectors/Revit/Speckle.Connectors.Revit2026", "net8.0-windows"),
|
||||
new("Connectors/Revit/Speckle.Connectors.Revit2025", "net8.0-windows")
|
||||
]
|
||||
),
|
||||
new(
|
||||
"autocad",
|
||||
[
|
||||
new("Connectors/Autocad/Speckle.Connectors.Autocad2022", "net48"),
|
||||
new("Connectors/Autocad/Speckle.Connectors.Autocad2023", "net48"),
|
||||
new("Connectors/Autocad/Speckle.Connectors.Autocad2024", "net48"),
|
||||
new("Connectors/Autocad/Speckle.Connectors.Autocad2025", "net8.0-windows"),
|
||||
new("Connectors/Autocad/Speckle.Connectors.Autocad2026", "net8.0-windows"),
|
||||
]
|
||||
),
|
||||
new(
|
||||
"civil3d",
|
||||
[
|
||||
new("Connectors/Autocad/Speckle.Connectors.Civil3d2022", "net48"),
|
||||
new("Connectors/Autocad/Speckle.Connectors.Civil3d2023", "net48"),
|
||||
new("Connectors/Autocad/Speckle.Connectors.Civil3d2024", "net48"),
|
||||
new("Connectors/Autocad/Speckle.Connectors.Civil3d2025", "net8.0-windows"),
|
||||
new("Connectors/Autocad/Speckle.Connectors.Civil3d2026", "net8.0-windows"),
|
||||
]
|
||||
),
|
||||
new("plant3d", [new("Connectors/Autocad/Speckle.Connectors.Plant3d2026", "net8.0-windows")]),
|
||||
new(
|
||||
"navisworks",
|
||||
[
|
||||
new("Connectors/Navisworks/Speckle.Connectors.Navisworks2020", "net48"),
|
||||
new("Connectors/Navisworks/Speckle.Connectors.Navisworks2021", "net48"),
|
||||
new("Connectors/Navisworks/Speckle.Connectors.Navisworks2022", "net48"),
|
||||
new("Connectors/Navisworks/Speckle.Connectors.Navisworks2023", "net48"),
|
||||
new("Connectors/Navisworks/Speckle.Connectors.Navisworks2024", "net48"),
|
||||
new("Connectors/Navisworks/Speckle.Connectors.Navisworks2025", "net48"),
|
||||
new("Connectors/Navisworks/Speckle.Connectors.Navisworks2026", "net48"),
|
||||
]
|
||||
),
|
||||
new(
|
||||
"teklastructures",
|
||||
[
|
||||
new("Connectors/Tekla/Speckle.Connector.Tekla2023", "net48"),
|
||||
new("Connectors/Tekla/Speckle.Connector.Tekla2024", "net48"),
|
||||
new("Connectors/Tekla/Speckle.Connector.Tekla2025", "net48"),
|
||||
]
|
||||
),
|
||||
new(
|
||||
"etabs",
|
||||
[
|
||||
new("Connectors/CSi/Speckle.Connectors.ETABS21", "net48"),
|
||||
new("Connectors/CSi/Speckle.Connectors.ETABS22", "net8.0-windows"),
|
||||
]
|
||||
),
|
||||
new("rhino-importer", [new("Importers/Rhino/Speckle.Importers.JobProcessor", "net8.0-windows")]),
|
||||
new("autocad", [new("Connectors/Autocad/Speckle.Connectors.Autocad2023", "net48")])
|
||||
};
|
||||
}
|
||||
|
||||
public readonly record struct ProjectGroup(string HostAppSlug, IReadOnlyList<InstallerAsset> Projects)
|
||||
public readonly record struct InstallerProject(string HostAppSlug, IReadOnlyList<InstallerAsset> Projects)
|
||||
{
|
||||
public override string ToString() => $"{HostAppSlug}";
|
||||
}
|
||||
|
||||
@@ -23,16 +23,16 @@ public static class Github
|
||||
{
|
||||
Accept = { new MediaTypeWithQualityHeaderValue("application/vnd.github+json") },
|
||||
Authorization = new AuthenticationHeaderValue("Bearer", token),
|
||||
UserAgent = { new ProductInfoHeaderValue("Speckle.build", "3.0.0") },
|
||||
UserAgent = { new ProductInfoHeaderValue("Speckle.build", "3.0.0") }
|
||||
},
|
||||
Content = content,
|
||||
Content = content
|
||||
};
|
||||
request.Headers.Add("X-GitHub-Api-Version", "2022-11-28");
|
||||
var response = await client.SendAsync(request);
|
||||
var response = await client.SendAsync(request).ConfigureAwait(false);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"{response.StatusCode} {response.ReasonPhrase} {await response.Content.ReadAsStringAsync()}"
|
||||
$"{response.StatusCode} {response.ReasonPhrase} {await response.Content.ReadAsStringAsync().ConfigureAwait(false)}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,19 +7,15 @@ using static SimpleExec.Command;
|
||||
const string CLEAN = "clean";
|
||||
const string RESTORE = "restore";
|
||||
const string BUILD = "build";
|
||||
const string PACK = "pack";
|
||||
const string TEST_AFFECTED = "test-affected";
|
||||
const string TEST = "test";
|
||||
const string TEST_ONLY = "test-only";
|
||||
const string FORMAT = "format";
|
||||
const string ZIP = "zip";
|
||||
const string VERSION = "version";
|
||||
const string RESTORE_TOOLS = "restore-tools";
|
||||
const string BUILD_SERVER_VERSION = "build-server-version";
|
||||
const string CLEAN_LOCKS = "clean-locks";
|
||||
const string CHECK_SOLUTIONS = "check-solutions";
|
||||
const string GEN_SOLUTIONS = "generate-solutions";
|
||||
const string DEEP_CLEAN = "deep-clean";
|
||||
const string DEEP_CLEAN_LOCAL = "deep-clean-local";
|
||||
const string DETECT_AFFECTED = "detect-affected";
|
||||
const string TEST_AND_PACK = "test-and-pack";
|
||||
|
||||
//need to pass arguments
|
||||
/*var arguments = new List<string>();
|
||||
@@ -30,67 +26,17 @@ if (args.Length > 1)
|
||||
//arguments = arguments.Skip(1).ToList();
|
||||
}*/
|
||||
|
||||
void Restore(string solution)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"Restoring solution '{solution}'");
|
||||
Console.WriteLine();
|
||||
Run("dotnet", $"restore \".\\{solution}\" --no-cache");
|
||||
}
|
||||
void DeleteFiles(string pattern)
|
||||
{
|
||||
foreach (var f in Glob.Files(".", pattern))
|
||||
{
|
||||
Console.WriteLine("Found and will delete: " + f);
|
||||
File.Delete(f);
|
||||
}
|
||||
}
|
||||
void DeleteDirectories(string pattern)
|
||||
{
|
||||
foreach (var f in Glob.Directories(".", pattern))
|
||||
{
|
||||
if (f.StartsWith("Build"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Console.WriteLine("Found and will delete: " + f);
|
||||
Directory.Delete(f, true);
|
||||
}
|
||||
}
|
||||
|
||||
void CleanSolution(string solution, string configuration)
|
||||
{
|
||||
Console.WriteLine("Cleaning solution: " + solution);
|
||||
|
||||
DeleteDirectories("**/bin");
|
||||
DeleteDirectories("**/obj");
|
||||
DeleteFiles("**/*.lock.json");
|
||||
Restore(solution);
|
||||
}
|
||||
|
||||
Target(
|
||||
CLEAN_LOCKS,
|
||||
Consts.Solutions,
|
||||
s =>
|
||||
{
|
||||
DeleteFiles("**/*.lock.json");
|
||||
Restore(s);
|
||||
}
|
||||
);
|
||||
|
||||
Target(
|
||||
DEEP_CLEAN,
|
||||
Consts.Solutions,
|
||||
s =>
|
||||
{
|
||||
CleanSolution(s, "debug");
|
||||
}
|
||||
);
|
||||
Target(
|
||||
DEEP_CLEAN_LOCAL,
|
||||
() =>
|
||||
{
|
||||
CleanSolution("Local.sln", "Local");
|
||||
foreach (var f in Glob.Files(".", "**/*.lock.json"))
|
||||
{
|
||||
Console.WriteLine("Found and will delete: " + f);
|
||||
File.Delete(f);
|
||||
}
|
||||
Console.WriteLine("Running restore now.");
|
||||
Run("dotnet", "restore .\\Speckle.Connectors.sln --no-cache");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -120,6 +66,17 @@ Target(
|
||||
}
|
||||
);
|
||||
|
||||
Target(
|
||||
VERSION,
|
||||
async () =>
|
||||
{
|
||||
var (output, _) = await ReadAsync("dotnet", "minver -v w").ConfigureAwait(false);
|
||||
output = output.Trim();
|
||||
Console.WriteLine($"Version: {output}");
|
||||
Run("echo", $"\"version={output}\" >> $GITHUB_OUTPUT");
|
||||
}
|
||||
);
|
||||
|
||||
Target(
|
||||
RESTORE_TOOLS,
|
||||
() =>
|
||||
@@ -128,24 +85,12 @@ Target(
|
||||
}
|
||||
);
|
||||
|
||||
Target(
|
||||
DETECT_AFFECTED,
|
||||
DependsOn(RESTORE_TOOLS),
|
||||
async () =>
|
||||
{
|
||||
foreach (var group in await Affected.GetAffectedProjectGroups())
|
||||
{
|
||||
Console.WriteLine("Affected project group being built: " + group.HostAppSlug);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Target(
|
||||
FORMAT,
|
||||
DependsOn(RESTORE_TOOLS),
|
||||
() =>
|
||||
{
|
||||
Run("dotnet", "csharpier check ./");
|
||||
Run("dotnet", "csharpier --check .");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -153,12 +98,18 @@ Target(
|
||||
RESTORE,
|
||||
DependsOn(FORMAT),
|
||||
Consts.Solutions,
|
||||
async s =>
|
||||
s =>
|
||||
{
|
||||
var version = await Versions.ComputeVersion();
|
||||
var fileVersion = await Versions.ComputeFileVersion();
|
||||
Console.WriteLine($"Restoring: {s} - Version: {version} & {fileVersion}");
|
||||
await RunAsync("dotnet", $"restore \"{s}\" --locked-mode");
|
||||
Run("dotnet", $"restore {s} --locked-mode");
|
||||
}
|
||||
);
|
||||
|
||||
Target(
|
||||
BUILD_SERVER_VERSION,
|
||||
DependsOn(RESTORE_TOOLS),
|
||||
() =>
|
||||
{
|
||||
Run("dotnet", "tool run dotnet-gitversion /output json /output buildserver");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -166,32 +117,16 @@ Target(
|
||||
BUILD,
|
||||
DependsOn(RESTORE),
|
||||
Consts.Solutions,
|
||||
async s =>
|
||||
s =>
|
||||
{
|
||||
var version = await Versions.ComputeVersion();
|
||||
var fileVersion = await Versions.ComputeFileVersion();
|
||||
Console.WriteLine($"Restoring: {s} - Version: {version} & {fileVersion}");
|
||||
await RunAsync(
|
||||
"dotnet",
|
||||
$"build \"{s}\" -c Release --no-restore -warnaserror -p:Version={version} -p:FileVersion={fileVersion} -v:m"
|
||||
);
|
||||
var version = Environment.GetEnvironmentVariable("GitVersion_FullSemVer") ?? "3.0.0-localBuild";
|
||||
var fileVersion = Environment.GetEnvironmentVariable("GitVersion_AssemblySemFileVer") ?? "3.0.0.0";
|
||||
Console.WriteLine($"Version: {version} & {fileVersion}");
|
||||
Run("dotnet", $"build {s} -c Release --no-restore -p:Version={version} -p:FileVersion={fileVersion} -v:m");
|
||||
}
|
||||
);
|
||||
|
||||
Target(CHECK_SOLUTIONS, Solutions.CompareConnectorsToLocal);
|
||||
Target(GEN_SOLUTIONS, Solutions.GenerateSolutions);
|
||||
|
||||
Target(
|
||||
TEST_AFFECTED,
|
||||
DependsOn(DETECT_AFFECTED, BUILD, CHECK_SOLUTIONS),
|
||||
async () =>
|
||||
{
|
||||
foreach (var s in await Affected.GetTestProjects())
|
||||
{
|
||||
await RunAsync("dotnet", $"test \"{s}\" -c Release --no-build --no-restore --verbosity=minimal");
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Target(
|
||||
TEST,
|
||||
@@ -199,85 +134,68 @@ Target(
|
||||
Glob.Files(".", "**/*.Tests.csproj"),
|
||||
file =>
|
||||
{
|
||||
Run(
|
||||
"dotnet",
|
||||
$"test \"{file}\" -c Release --no-build --verbosity=minimal /p:AltCover=true /p:AltCoverAttributeFilter=ExcludeFromCodeCoverage /p:AltCoverVerbosity=Warning"
|
||||
);
|
||||
Run("dotnet", $"test {file} -c Release --no-build --no-restore --verbosity=minimal");
|
||||
}
|
||||
);
|
||||
|
||||
Target(TEST_AND_PACK, DependsOn(TEST, PACK));
|
||||
|
||||
Target(
|
||||
PACK,
|
||||
DependsOn(BUILD),
|
||||
Consts.Solutions,
|
||||
async solution =>
|
||||
TEST_ONLY,
|
||||
DependsOn(FORMAT),
|
||||
Glob.Files(".", "**/*.Tests.csproj"),
|
||||
file =>
|
||||
{
|
||||
var version = await Versions.ComputeVersion();
|
||||
var fileVersion = await Versions.ComputeFileVersion();
|
||||
Console.WriteLine($"Version: {version} & {fileVersion}");
|
||||
|
||||
await RunAsync(
|
||||
Run("dotnet", $"restore {file} --locked-mode");
|
||||
Run(
|
||||
"dotnet",
|
||||
$"pack \"{solution}\" -c Release -o output --no-build -p:Version={version} -p:FileVersion={fileVersion} -v:m"
|
||||
$"test {file} -c Release --no-restore --verbosity=minimal /p:AltCover=true /p:AltCoverAttributeFilter=ExcludeFromCodeCoverage /p:AltCoverVerbosity=Warning"
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
Target(
|
||||
ZIP,
|
||||
DependsOn(TEST_AFFECTED),
|
||||
async () =>
|
||||
DependsOn(TEST),
|
||||
Consts.InstallerManifests,
|
||||
x =>
|
||||
{
|
||||
var version = await Versions.ComputeVersion();
|
||||
var fileVersion = await Versions.ComputeFileVersion();
|
||||
foreach (var group in await Affected.GetAffectedProjectGroups())
|
||||
var outputDir = Path.Combine(".", "output");
|
||||
var slugDir = Path.Combine(outputDir, x.HostAppSlug);
|
||||
|
||||
Directory.CreateDirectory(outputDir);
|
||||
Directory.CreateDirectory(slugDir);
|
||||
|
||||
foreach (var asset in x.Projects)
|
||||
{
|
||||
Console.WriteLine($"Zipping: {group.HostAppSlug} as {version}");
|
||||
var outputDir = Path.Combine(".", "output");
|
||||
var slugDir = Path.Combine(outputDir, group.HostAppSlug);
|
||||
|
||||
Directory.CreateDirectory(outputDir);
|
||||
Directory.CreateDirectory(slugDir);
|
||||
|
||||
foreach (var asset in group.Projects)
|
||||
var fullPath = Path.Combine(".", asset.ProjectPath, "bin", "Release", asset.TargetName);
|
||||
if (!Directory.Exists(fullPath))
|
||||
{
|
||||
var fullPath = Path.Combine(".", asset.ProjectPath, "bin", "Release", asset.TargetName);
|
||||
if (!Directory.Exists(fullPath))
|
||||
{
|
||||
throw new InvalidOperationException("Could not find: " + fullPath);
|
||||
}
|
||||
|
||||
var assetName = Path.GetFileName(asset.ProjectPath);
|
||||
var connectorDir = Path.Combine(slugDir, assetName);
|
||||
|
||||
Directory.CreateDirectory(connectorDir);
|
||||
foreach (var directory in Directory.EnumerateDirectories(fullPath, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
Directory.CreateDirectory(directory.Replace(fullPath, connectorDir));
|
||||
}
|
||||
|
||||
foreach (var file in Directory.EnumerateFiles(fullPath, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
Console.WriteLine(file);
|
||||
File.Copy(file, file.Replace(fullPath, connectorDir), true);
|
||||
}
|
||||
throw new InvalidOperationException("Could not find: " + fullPath);
|
||||
}
|
||||
|
||||
var outputPath = Path.Combine(outputDir, $"{group.HostAppSlug}.zip");
|
||||
File.Delete(outputPath);
|
||||
Console.WriteLine($"Zipping: '{slugDir}' to '{outputPath}'");
|
||||
ZipFile.CreateFromDirectory(slugDir, outputPath);
|
||||
var assetName = Path.GetFileName(asset.ProjectPath);
|
||||
var connectorDir = Path.Combine(slugDir, assetName);
|
||||
|
||||
Directory.CreateDirectory(connectorDir);
|
||||
foreach (var directory in Directory.EnumerateDirectories(fullPath, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
Directory.CreateDirectory(directory.Replace(fullPath, connectorDir));
|
||||
}
|
||||
|
||||
foreach (var file in Directory.EnumerateFiles(fullPath, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
Console.WriteLine(file);
|
||||
File.Copy(file, file.Replace(fullPath, connectorDir), true);
|
||||
}
|
||||
}
|
||||
|
||||
string githubEnv = Environment.GetEnvironmentVariable("GITHUB_ENV") ?? "Unset";
|
||||
Console.WriteLine($"GITHUB_ENV: {githubEnv}");
|
||||
File.AppendAllText(githubEnv, $"SEMVER={version}{Environment.NewLine}");
|
||||
File.AppendAllText(githubEnv, $"FILE_VERSION={fileVersion}{Environment.NewLine}");
|
||||
var outputPath = Path.Combine(outputDir, $"{x.HostAppSlug}.zip");
|
||||
File.Delete(outputPath);
|
||||
Console.WriteLine($"Zipping: '{slugDir}' to '{outputPath}'");
|
||||
ZipFile.CreateFromDirectory(slugDir, outputPath);
|
||||
// Directory.Delete(slugDir, true);
|
||||
}
|
||||
);
|
||||
|
||||
Target("default", DependsOn(TEST_AFFECTED), () => Console.WriteLine("Done!"));
|
||||
Target("default", DependsOn(FORMAT, ZIP), () => Console.WriteLine("Done!"));
|
||||
|
||||
await RunTargetsAndExitAsync(args).ConfigureAwait(true);
|
||||
|
||||
@@ -1,117 +1,56 @@
|
||||
using Microsoft.VisualStudio.SolutionPersistence.Model;
|
||||
using Microsoft.VisualStudio.SolutionPersistence.Serializer;
|
||||
using Microsoft.Build.Construction;
|
||||
|
||||
namespace Build;
|
||||
|
||||
public static class Solutions
|
||||
{
|
||||
#pragma warning disable CA1802
|
||||
#pragma warning disable IDE1006
|
||||
private static readonly string DIRECTORY = Environment.CurrentDirectory;
|
||||
#pragma warning restore IDE1006
|
||||
#pragma warning restore CA1802
|
||||
public static async Task CompareConnectorsToLocal()
|
||||
{
|
||||
var localSln = await GetSolution("Local.sln");
|
||||
var connectorsSln = await GetSolution("Speckle.Connectors.sln");
|
||||
var localProjects = localSln.SolutionProjects.ToList();
|
||||
private static bool ValidProjects(KeyValuePair<string, ProjectInSolution> projectInSolution) =>
|
||||
projectInSolution.Value.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat;
|
||||
|
||||
foreach (var value in connectorsSln.SolutionProjects)
|
||||
public static void CompareConnectorsToLocal()
|
||||
{
|
||||
var localSln = SolutionFile.Parse(Path.Combine(Environment.CurrentDirectory, "Local.sln"));
|
||||
var connectorsSln = SolutionFile.Parse(Path.Combine(Environment.CurrentDirectory, "Speckle.Connectors.sln"));
|
||||
var localProjects = localSln.ProjectsByGuid.Where(ValidProjects).ToDictionary();
|
||||
|
||||
foreach ((string? _, ProjectInSolution? value) in connectorsSln.ProjectsByGuid.Where(ValidProjects))
|
||||
{
|
||||
var localProject = localProjects.FirstOrDefault(x => x.ActualDisplayName == value.ActualDisplayName);
|
||||
var localProject = localProjects.Values.FirstOrDefault(x => x.ProjectName == value.ProjectName);
|
||||
if (localProject is null)
|
||||
{
|
||||
throw new InvalidOperationException($"Could not find in LOCAL solution: {value.ActualDisplayName}");
|
||||
throw new InvalidOperationException($"Could not find in LOCAL solution: {value.ProjectName}");
|
||||
}
|
||||
|
||||
if (value.ActualDisplayName != localProject.ActualDisplayName)
|
||||
if (value.ProjectName != localProject.ProjectName)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Projects with different names have same Guid in solution: "
|
||||
+ value.ActualDisplayName
|
||||
+ value.ProjectName
|
||||
+ " and "
|
||||
+ localProject.ActualDisplayName
|
||||
+ localProject.ProjectName
|
||||
);
|
||||
}
|
||||
localProjects.Remove(localProjects.Single(x => x.ActualDisplayName == value.ActualDisplayName));
|
||||
localProjects.Remove(localProjects.Single(x => x.Value.ProjectName == value.ProjectName).Key);
|
||||
}
|
||||
|
||||
void CheckAndRemoveKnown(string projectName)
|
||||
{
|
||||
var localProject = localProjects.FirstOrDefault(x => x.ActualDisplayName == projectName);
|
||||
var localProject = localProjects.Values.FirstOrDefault(x => x.ProjectName == projectName);
|
||||
if (localProject is null)
|
||||
{
|
||||
throw new InvalidOperationException($"Could not find in LOCAL solution: {projectName}");
|
||||
}
|
||||
localProjects.Remove(localProjects.Single(x => x.ActualDisplayName == projectName));
|
||||
localProjects.Remove(localProjects.Single(x => x.Value.ProjectName == projectName).Key);
|
||||
}
|
||||
|
||||
CheckAndRemoveKnown("Speckle.Objects");
|
||||
CheckAndRemoveKnown("Speckle.Sdk");
|
||||
CheckAndRemoveKnown("Speckle.Sdk.Dependencies");
|
||||
CheckAndRemoveKnown("Speckle.Sdk.Logging");
|
||||
if (localProjects.Count != 0)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Could not find in CONNECTOR solution: " + localProjects.First().ActualDisplayName
|
||||
"Could not find in CONNECTOR solution: " + localProjects.First().Value.ProjectName
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task GenerateSolutions()
|
||||
{
|
||||
await GenerateLocalSlnx();
|
||||
foreach (var group in Consts.ProjectGroups)
|
||||
{
|
||||
var connectors = await GetFullSlnx();
|
||||
var slug = group.HostAppSlug;
|
||||
await GenerateConnector(connectors, group, string.Concat(slug[0].ToString().ToUpper(), slug.AsSpan(1)));
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task GenerateLocalSlnx()
|
||||
{
|
||||
var connectors = await GetFullSlnx();
|
||||
connectors.AddProject("..\\speckle-sharp-sdk\\src\\Speckle.Objects\\Speckle.Objects.csproj");
|
||||
connectors.AddProject("..\\speckle-sharp-sdk\\src\\Speckle.Sdk\\Speckle.Sdk.csproj");
|
||||
connectors.AddProject("..\\speckle-sharp-sdk\\src\\Speckle.Sdk.Dependencies\\Speckle.Sdk.Dependencies.csproj");
|
||||
var sln = Path.Combine(DIRECTORY, "Local.slnx");
|
||||
await SolutionSerializers.SlnXml.SaveAsync(sln, connectors, default);
|
||||
sln = Path.Combine(DIRECTORY, "Local.sln");
|
||||
await SolutionSerializers.SlnFileV12.SaveAsync(sln, connectors, default);
|
||||
|
||||
var revit = Consts.ProjectGroups.Single(x => x.HostAppSlug.Equals("revit"));
|
||||
await GenerateConnector(connectors, revit, "Revit.Local");
|
||||
}
|
||||
|
||||
public static async Task GenerateConnector(SolutionModel connectors, ProjectGroup group, string? name)
|
||||
{
|
||||
var path = group.Projects[0].ProjectPath.Split('/');
|
||||
var folder = $"/{path[0]}/{path[1]}/";
|
||||
var foldersToRemove = connectors
|
||||
.SolutionFolders.Where(x =>
|
||||
//need base folder
|
||||
!x.Path.Equals("/Connectors/")
|
||||
//don't grab all
|
||||
&& (x.Path.StartsWith("/Connectors/") && !x.Path.StartsWith(folder))
|
||||
)
|
||||
.ToList();
|
||||
foreach (var folderToRemove in foldersToRemove)
|
||||
{
|
||||
connectors.RemoveFolder(folderToRemove);
|
||||
}
|
||||
var sln = Path.Combine(DIRECTORY, $"Speckle.{name}.slnx");
|
||||
await SolutionSerializers.SlnXml.SaveAsync(sln, connectors, default);
|
||||
}
|
||||
|
||||
public static async Task<SolutionModel> GetFullSlnx()
|
||||
{
|
||||
var connectorsSln = Path.Combine(DIRECTORY, "Speckle.Connectors.slnx");
|
||||
return await SolutionSerializers.SlnXml.OpenAsync(connectorsSln, default);
|
||||
}
|
||||
|
||||
public static async Task<SolutionModel> GetSolution(string solutionName)
|
||||
{
|
||||
var connectorsSln = Path.Combine(DIRECTORY, solutionName);
|
||||
return await SolutionSerializers.SlnFileV12.OpenAsync(connectorsSln, default);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
using Semver;
|
||||
using static SimpleExec.Command;
|
||||
|
||||
namespace Build;
|
||||
|
||||
public static class Versions
|
||||
{
|
||||
private static string? s_currentTag;
|
||||
private static SemVersion? s_currentVersion;
|
||||
|
||||
public static async Task<string> GetCurrentTag()
|
||||
{
|
||||
if (s_currentTag is not null)
|
||||
{
|
||||
return s_currentTag;
|
||||
}
|
||||
//finds current tag or makes one
|
||||
var (currentTag, _) = await ReadAsync("git", "describe --tags");
|
||||
currentTag = currentTag.Trim();
|
||||
s_currentTag = currentTag;
|
||||
return s_currentTag;
|
||||
}
|
||||
|
||||
public static async Task<SemVersion> ComputeVersion()
|
||||
{
|
||||
if (s_currentVersion is not null)
|
||||
{
|
||||
return s_currentVersion;
|
||||
}
|
||||
var currentTag = await GetCurrentTag();
|
||||
|
||||
if (!SemVersion.TryParse(currentTag, SemVersionStyles.AllowLowerV, out var currentVersion))
|
||||
{
|
||||
throw new InvalidOperationException($"Could not parse version: '{currentTag}'");
|
||||
}
|
||||
s_currentVersion = currentVersion;
|
||||
return s_currentVersion;
|
||||
}
|
||||
|
||||
private static string? s_currentFileVersion;
|
||||
|
||||
public static async Task<string> ComputeFileVersion()
|
||||
{
|
||||
if (s_currentFileVersion is not null)
|
||||
{
|
||||
return s_currentFileVersion;
|
||||
}
|
||||
var currentVersion = await ComputeVersion();
|
||||
s_currentFileVersion = currentVersion.WithoutPrereleaseOrMetadata() + ".0";
|
||||
return s_currentFileVersion;
|
||||
}
|
||||
|
||||
public static async Task<string> GetPreviousTag(string currentTag)
|
||||
{
|
||||
//finds a tag starting with current tag and adds no abbrevation
|
||||
var (lastTag, _) = await ReadAsync("git", $"describe --abbrev=0 --tags {currentTag}^");
|
||||
lastTag = lastTag.Trim();
|
||||
|
||||
return lastTag;
|
||||
}
|
||||
|
||||
private static SemVersion? s_previousVersion;
|
||||
|
||||
public static async Task<SemVersion> ComputePreviousVersion(string currentTag)
|
||||
{
|
||||
if (s_previousVersion is not null)
|
||||
{
|
||||
return s_previousVersion;
|
||||
}
|
||||
var lastTag = await GetPreviousTag(currentTag);
|
||||
|
||||
if (!SemVersion.TryParse(lastTag, SemVersionStyles.AllowLowerV, out var lastVersion))
|
||||
{
|
||||
throw new InvalidOperationException($"Could not parse version: '{lastTag}'");
|
||||
}
|
||||
s_previousVersion = lastVersion;
|
||||
return s_previousVersion;
|
||||
}
|
||||
}
|
||||
@@ -16,25 +16,18 @@
|
||||
},
|
||||
"Microsoft.Build": {
|
||||
"type": "Direct",
|
||||
"requested": "[17.11.48, )",
|
||||
"resolved": "17.11.48",
|
||||
"contentHash": "g8Kn575mNAKcuFotV3C7xvF+IbxuHennl67LH2shL2au1U6UqwReTDygCHyU04+koc2Yn7fHIbVQaC08HqEWow==",
|
||||
"requested": "[17.10.4, )",
|
||||
"resolved": "17.10.4",
|
||||
"contentHash": "ZmGA8vhVXFzC4oo48ybQKlEybVKd0Ntfdr+Enqrn5ES1R6e/krIK9hLk0W33xuT0/G6QYd3YdhJZh+Xle717Ag==",
|
||||
"dependencies": {
|
||||
"Microsoft.Build.Framework": "17.11.48",
|
||||
"Microsoft.NET.StringTools": "17.11.48",
|
||||
"Microsoft.Build.Framework": "17.10.4",
|
||||
"Microsoft.NET.StringTools": "17.10.4",
|
||||
"System.Collections.Immutable": "8.0.0",
|
||||
"System.Configuration.ConfigurationManager": "8.0.0",
|
||||
"System.Reflection.Metadata": "8.0.0",
|
||||
"System.Reflection.MetadataLoadContext": "8.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.0.3, )",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
|
||||
"dependencies": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.3"
|
||||
"System.Reflection.MetadataLoadContext": "8.0.0",
|
||||
"System.Security.Principal.Windows": "5.0.0",
|
||||
"System.Threading.Tasks.Dataflow": "8.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.SourceLink.GitHub": {
|
||||
@@ -47,27 +40,12 @@
|
||||
"Microsoft.SourceLink.Common": "8.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.VisualStudio.SolutionPersistence": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.0.52, )",
|
||||
"resolved": "1.0.52",
|
||||
"contentHash": "oNv2JtYXhpdJrX63nibx1JT3uCESOBQ1LAk7Dtz/sr0+laW0KRM6eKp4CZ3MHDR2siIkKsY8MmUkeP5DKkQQ5w=="
|
||||
},
|
||||
"PolySharp": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.14.1, )",
|
||||
"resolved": "1.14.1",
|
||||
"contentHash": "mOOmFYwad3MIOL14VCjj02LljyF1GNw1wP0YVlxtcPvqdxjGGMNdNJJxHptlry3MOd8b40Flm8RPOM8JOlN2sQ=="
|
||||
},
|
||||
"Semver": {
|
||||
"type": "Direct",
|
||||
"requested": "[3.0.0, )",
|
||||
"resolved": "3.0.0",
|
||||
"contentHash": "9jZCicsVgTebqkAujRWtC9J1A5EQVlu0TVKHcgoCuv345ve5DYf4D1MjhKEnQjdRZo6x/vdv6QQrYFs7ilGzLA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "5.0.1"
|
||||
}
|
||||
},
|
||||
"SimpleExec": {
|
||||
"type": "Direct",
|
||||
"requested": "[12.0.0, )",
|
||||
@@ -82,28 +60,18 @@
|
||||
},
|
||||
"Microsoft.Build.Framework": {
|
||||
"type": "Transitive",
|
||||
"resolved": "17.11.48",
|
||||
"contentHash": "C3WIMt2wBl4++NX3jSEpTq5KXBhvAV154R4JrYHkfy9JSBcXWiL0mkgpspk5xSdOj+fS/uz7zluIy6bMM1fkkQ=="
|
||||
"resolved": "17.10.4",
|
||||
"contentHash": "4qXCwNOXBR1dyCzuks9SwTwFJQO/xmf2wcMislotDWJu7MN/r3xDNoU8Ae5QmKIHPaLG1xmfDkYS7qBVzxmeKw=="
|
||||
},
|
||||
"Microsoft.Build.Tasks.Git": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.1",
|
||||
"contentHash": "5WPSmL4YeP7eW+Vc8XZ4DwjYWBAiSwDV9Hm63JJWcz1Ie3Xjv4KuJXzgCstj48LkLfVCYa7mLcx7y+q6yqVvtw=="
|
||||
},
|
||||
"Microsoft.NET.StringTools": {
|
||||
"type": "Transitive",
|
||||
"resolved": "17.11.48",
|
||||
"contentHash": "0IQo089IGBEC4jgtishauZMVr9ZxOWNiGKeDvyzZlvw7p2r253lJh6IJCLLFWXvZnVrVO5mnsYIPamxFPzM08w=="
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net461": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "AmOJZwCqnOCNp6PPcf9joyogScWLtwy0M1WkqfEQ0M9nYwyDD7EX9ZjscKS5iYnyvteX7kzSKFCKt9I9dXA6mA=="
|
||||
"resolved": "17.10.4",
|
||||
"contentHash": "wyABaqY+IHCMMSTQmcc3Ca6vbmg5BaEPgicnEgpll+4xyWZWlkQqUwafweUd9VAhBb4jqplMl6voUHQ6yfdUcg=="
|
||||
},
|
||||
"Microsoft.SourceLink.Common": {
|
||||
"type": "Transitive",
|
||||
@@ -150,6 +118,17 @@
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "+TUFINV2q2ifyXauQXRwy4CiBhqvDEDZeVJU7qfxya4aRYOKzVBpN+4acx25VcPB9ywUN6C0n8drWl110PhZEg=="
|
||||
},
|
||||
"System.Security.Principal.Windows": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA=="
|
||||
},
|
||||
"System.Threading.Tasks.Dataflow": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[6.0.0, )",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "7V0I8tPa9V7UxMx/+7DIwkhls5ouaEMQx6l/GwGm1Y8kJQ61On9B/PxCXFLbgu5/C47g0BP2CUYs+nMv1+Oaqw=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
CA1502: 25
|
||||
CA1501: 5
|
||||
CA1506(Method): 60
|
||||
CA1506(Method): 50
|
||||
CA1506(Type): 95
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Autofac.DependencyInjection;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Logging;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.DUI.Models.Card;
|
||||
using Speckle.Connectors.Utils.Cancellation;
|
||||
using Speckle.Connectors.Utils.Operations;
|
||||
using Speckle.Sdk;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Bindings;
|
||||
|
||||
public sealed class ArcGISReceiveBinding : IReceiveBinding
|
||||
{
|
||||
public string Name { get; } = "receiveBinding";
|
||||
private readonly CancellationManager _cancellationManager;
|
||||
private readonly DocumentModelStore _store;
|
||||
private readonly IUnitOfWorkFactory _unitOfWorkFactory;
|
||||
private readonly IOperationProgressManager _operationProgressManager;
|
||||
private readonly ILogger<ArcGISReceiveBinding> _logger;
|
||||
|
||||
private ReceiveBindingUICommands Commands { get; }
|
||||
public IBridge Parent { get; }
|
||||
|
||||
public ArcGISReceiveBinding(
|
||||
DocumentModelStore store,
|
||||
IBridge parent,
|
||||
CancellationManager cancellationManager,
|
||||
IUnitOfWorkFactory unitOfWorkFactory,
|
||||
IOperationProgressManager operationProgressManager,
|
||||
ILogger<ArcGISReceiveBinding> logger
|
||||
)
|
||||
{
|
||||
_store = store;
|
||||
_cancellationManager = cancellationManager;
|
||||
Parent = parent;
|
||||
Commands = new ReceiveBindingUICommands(parent);
|
||||
_unitOfWorkFactory = unitOfWorkFactory;
|
||||
_operationProgressManager = operationProgressManager;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task Receive(string modelCardId)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get receiver card
|
||||
if (_store.GetModelById(modelCardId) is not ReceiverModelCard modelCard)
|
||||
{
|
||||
// Handle as GLOBAL ERROR at BrowserBridge
|
||||
throw new InvalidOperationException("No download model card was found.");
|
||||
}
|
||||
|
||||
CancellationToken cancellationToken = _cancellationManager.InitCancellationTokenSource(modelCardId);
|
||||
|
||||
using IUnitOfWork<ReceiveOperation> unitOfWork = _unitOfWorkFactory.Resolve<ReceiveOperation>();
|
||||
|
||||
// Receive host objects
|
||||
var receiveOperationResults = await unitOfWork
|
||||
.Service.Execute(
|
||||
modelCard.GetReceiveInfo("ArcGIS"), // POC: get host app name from settings? same for GetSendInfo
|
||||
cancellationToken,
|
||||
(status, progress) =>
|
||||
_operationProgressManager.SetModelProgress(
|
||||
Parent,
|
||||
modelCardId,
|
||||
new ModelCardProgress(modelCardId, status, progress),
|
||||
cancellationToken
|
||||
)
|
||||
)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
modelCard.BakedObjectIds = receiveOperationResults.BakedObjectIds.ToList();
|
||||
Commands.SetModelReceiveResult(
|
||||
modelCardId,
|
||||
receiveOperationResults.BakedObjectIds,
|
||||
receiveOperationResults.ConversionResults
|
||||
);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// SWALLOW -> UI handles it immediately, so we do not need to handle anything for now!
|
||||
// Idea for later -> when cancel called, create promise from UI to solve it later with this catch block.
|
||||
// So have 3 state on UI -> Cancellation clicked -> Cancelling -> Cancelled
|
||||
return;
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal()) // UX reasons - we will report operation exceptions as model card error. We may change this later when we have more exception documentation
|
||||
{
|
||||
_logger.LogModelCardHandledError(ex);
|
||||
Commands.SetModelError(modelCardId, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void CancelReceive(string modelCardId) => _cancellationManager.CancelOperation(modelCardId);
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using ArcGIS.Desktop.Mapping.Events;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Bindings;
|
||||
|
||||
public class ArcGISSelectionBinding : ISelectionBinding
|
||||
{
|
||||
public string Name => "selectionBinding";
|
||||
public IBridge Parent { get; }
|
||||
|
||||
public ArcGISSelectionBinding(IBridge parent)
|
||||
{
|
||||
Parent = parent;
|
||||
var topLevelHandler = parent.TopLevelExceptionHandler;
|
||||
|
||||
// example: https://github.com/Esri/arcgis-pro-sdk-community-samples/blob/master/Map-Authoring/QueryBuilderControl/DefinitionQueryDockPaneViewModel.cs
|
||||
// MapViewEventArgs args = new(MapView.Active);
|
||||
TOCSelectionChangedEvent.Subscribe(_ => topLevelHandler.CatchUnhandled(OnSelectionChanged), true);
|
||||
}
|
||||
|
||||
private void OnSelectionChanged()
|
||||
{
|
||||
SelectionInfo selInfo = GetSelection();
|
||||
Parent.Send(SelectionBindingEvents.SET_SELECTION, selInfo);
|
||||
}
|
||||
|
||||
private void GetLayersFromGroup(GroupLayer group, List<MapMember> nestedLayers)
|
||||
{
|
||||
nestedLayers.Add(group);
|
||||
foreach (MapMember member in group.Layers)
|
||||
{
|
||||
if (member is GroupLayer subGroup)
|
||||
{
|
||||
GetLayersFromGroup(subGroup, nestedLayers);
|
||||
}
|
||||
else
|
||||
{
|
||||
nestedLayers.Add(member);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SelectionInfo GetSelection()
|
||||
{
|
||||
MapView mapView = MapView.Active;
|
||||
List<MapMember> selectedMembers = new();
|
||||
selectedMembers.AddRange(mapView.GetSelectedLayers());
|
||||
selectedMembers.AddRange(mapView.GetSelectedStandaloneTables());
|
||||
|
||||
List<MapMember> allNestedMembers = new();
|
||||
foreach (MapMember member in selectedMembers)
|
||||
{
|
||||
if (member is GroupLayer group)
|
||||
{
|
||||
GetLayersFromGroup(group, allNestedMembers);
|
||||
}
|
||||
else
|
||||
{
|
||||
allNestedMembers.Add(member);
|
||||
}
|
||||
}
|
||||
|
||||
List<string> objectTypes = allNestedMembers
|
||||
.Select(o => o.GetType().ToString().Split(".").Last())
|
||||
.Distinct()
|
||||
.ToList();
|
||||
return new SelectionInfo(
|
||||
allNestedMembers.Select(x => x.URI).ToList(),
|
||||
$"{allNestedMembers.Count} layers ({string.Join(", ", objectTypes)})"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,449 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using ArcGIS.Core.Data;
|
||||
using ArcGIS.Desktop.Editing.Events;
|
||||
using ArcGIS.Desktop.Framework.Threading.Tasks;
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using ArcGIS.Desktop.Mapping.Events;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Autofac.DependencyInjection;
|
||||
using Speckle.Connectors.ArcGIS.Filters;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Exceptions;
|
||||
using Speckle.Connectors.DUI.Logging;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.DUI.Models.Card;
|
||||
using Speckle.Connectors.DUI.Models.Card.SendFilter;
|
||||
using Speckle.Connectors.DUI.Settings;
|
||||
using Speckle.Connectors.Utils.Caching;
|
||||
using Speckle.Connectors.Utils.Cancellation;
|
||||
using Speckle.Connectors.Utils.Operations;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Common;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Bindings;
|
||||
|
||||
public sealed class ArcGISSendBinding : ISendBinding
|
||||
{
|
||||
public string Name => "sendBinding";
|
||||
public SendBindingUICommands Commands { get; }
|
||||
public IBridge Parent { get; }
|
||||
|
||||
private readonly DocumentModelStore _store;
|
||||
private readonly IUnitOfWorkFactory _unitOfWorkFactory; // POC: unused? :D
|
||||
private readonly List<ISendFilter> _sendFilters;
|
||||
private readonly CancellationManager _cancellationManager;
|
||||
private readonly ISendConversionCache _sendConversionCache;
|
||||
private readonly IOperationProgressManager _operationProgressManager;
|
||||
private readonly ILogger<ArcGISSendBinding> _logger;
|
||||
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
|
||||
|
||||
/// <summary>
|
||||
/// Used internally to aggregate the changed objects' id. Note we're using a concurrent dictionary here as the expiry check method is not thread safe, and this was causing problems. See:
|
||||
/// [CNX-202: Unhandled Exception Occurred when receiving in Rhino](https://linear.app/speckle/issue/CNX-202/unhandled-exception-occurred-when-receiving-in-rhino)
|
||||
/// As to why a concurrent dictionary, it's because it's the cheapest/easiest way to do so.
|
||||
/// https://stackoverflow.com/questions/18922985/concurrent-hashsett-in-net-framework
|
||||
/// </summary>
|
||||
private ConcurrentDictionary<string, byte> ChangedObjectIds { get; set; } = new();
|
||||
|
||||
private List<FeatureLayer> SubscribedLayers { get; set; } = new();
|
||||
private List<StandaloneTable> SubscribedTables { get; set; } = new();
|
||||
|
||||
public ArcGISSendBinding(
|
||||
DocumentModelStore store,
|
||||
IBridge parent,
|
||||
IEnumerable<ISendFilter> sendFilters,
|
||||
IUnitOfWorkFactory unitOfWorkFactory,
|
||||
CancellationManager cancellationManager,
|
||||
ISendConversionCache sendConversionCache,
|
||||
IOperationProgressManager operationProgressManager,
|
||||
ILogger<ArcGISSendBinding> logger
|
||||
)
|
||||
{
|
||||
_store = store;
|
||||
_unitOfWorkFactory = unitOfWorkFactory;
|
||||
_sendFilters = sendFilters.ToList();
|
||||
_cancellationManager = cancellationManager;
|
||||
_sendConversionCache = sendConversionCache;
|
||||
_operationProgressManager = operationProgressManager;
|
||||
_logger = logger;
|
||||
_topLevelExceptionHandler = parent.TopLevelExceptionHandler;
|
||||
|
||||
Parent = parent;
|
||||
Commands = new SendBindingUICommands(parent);
|
||||
SubscribeToArcGISEvents();
|
||||
}
|
||||
|
||||
private void SubscribeToArcGISEvents()
|
||||
{
|
||||
LayersRemovedEvent.Subscribe(
|
||||
a => _topLevelExceptionHandler.CatchUnhandled(() => GetIdsForLayersRemovedEvent(a)),
|
||||
true
|
||||
);
|
||||
|
||||
StandaloneTablesRemovedEvent.Subscribe(
|
||||
a => _topLevelExceptionHandler.CatchUnhandled(() => GetIdsForStandaloneTablesRemovedEvent(a)),
|
||||
true
|
||||
);
|
||||
|
||||
MapPropertyChangedEvent.Subscribe(
|
||||
a => _topLevelExceptionHandler.CatchUnhandled(() => GetIdsForMapPropertyChangedEvent(a)),
|
||||
true
|
||||
); // Map units, CRS etc.
|
||||
|
||||
MapMemberPropertiesChangedEvent.Subscribe(
|
||||
a => _topLevelExceptionHandler.CatchUnhandled(() => GetIdsForMapMemberPropertiesChangedEvent(a)),
|
||||
true
|
||||
); // e.g. Layer name
|
||||
|
||||
ActiveMapViewChangedEvent.Subscribe(
|
||||
_ => _topLevelExceptionHandler.CatchUnhandled(SubscribeToMapMembersDataSourceChange),
|
||||
true
|
||||
);
|
||||
|
||||
/*
|
||||
LayersAddedEvent.Subscribe(a => _topLevelExceptionHandler.CatchUnhandled(() => GetIdsForLayersAddedEvent(a)), true);
|
||||
|
||||
StandaloneTablesAddedEvent.Subscribe(
|
||||
a => _topLevelExceptionHandler.CatchUnhandled(() => GetIdsForStandaloneTablesAddedEvent(a)),
|
||||
true
|
||||
);
|
||||
*/
|
||||
}
|
||||
|
||||
private void SubscribeToMapMembersDataSourceChange()
|
||||
{
|
||||
var task = QueuedTask.Run(() =>
|
||||
{
|
||||
if (MapView.Active == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// subscribe to layers
|
||||
foreach (Layer layer in MapView.Active.Map.Layers)
|
||||
{
|
||||
if (layer is FeatureLayer featureLayer)
|
||||
{
|
||||
SubscribeToFeatureLayerDataSourceChange(featureLayer);
|
||||
}
|
||||
}
|
||||
// subscribe to tables
|
||||
foreach (StandaloneTable table in MapView.Active.Map.StandaloneTables)
|
||||
{
|
||||
SubscribeToTableDataSourceChange(table);
|
||||
}
|
||||
});
|
||||
task.Wait();
|
||||
}
|
||||
|
||||
private void SubscribeToFeatureLayerDataSourceChange(FeatureLayer layer)
|
||||
{
|
||||
if (SubscribedLayers.Contains(layer))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Table layerTable = layer.GetTable();
|
||||
if (layerTable != null)
|
||||
{
|
||||
SubscribeToAnyDataSourceChange(layerTable);
|
||||
SubscribedLayers.Add(layer);
|
||||
}
|
||||
}
|
||||
|
||||
private void SubscribeToTableDataSourceChange(StandaloneTable table)
|
||||
{
|
||||
if (SubscribedTables.Contains(table))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Table layerTable = table.GetTable();
|
||||
if (layerTable != null)
|
||||
{
|
||||
SubscribeToAnyDataSourceChange(layerTable);
|
||||
SubscribedTables.Add(table);
|
||||
}
|
||||
}
|
||||
|
||||
private void SubscribeToAnyDataSourceChange(Table layerTable)
|
||||
{
|
||||
RowCreatedEvent.Subscribe(
|
||||
(args) =>
|
||||
{
|
||||
OnRowChanged(args);
|
||||
},
|
||||
layerTable
|
||||
);
|
||||
RowChangedEvent.Subscribe(
|
||||
(args) =>
|
||||
{
|
||||
OnRowChanged(args);
|
||||
},
|
||||
layerTable
|
||||
);
|
||||
RowDeletedEvent.Subscribe(
|
||||
(args) =>
|
||||
{
|
||||
OnRowChanged(args);
|
||||
},
|
||||
layerTable
|
||||
);
|
||||
}
|
||||
|
||||
private void OnRowChanged(RowChangedEventArgs args)
|
||||
{
|
||||
if (args == null || MapView.Active == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// get the path of the edited dataset
|
||||
var datasetURI = args.Row.GetTable().GetPath();
|
||||
|
||||
// find all layers & tables reading from the dataset
|
||||
foreach (Layer layer in MapView.Active.Map.Layers)
|
||||
{
|
||||
if (layer.GetPath() == datasetURI)
|
||||
{
|
||||
ChangedObjectIds[layer.URI] = 1;
|
||||
}
|
||||
}
|
||||
foreach (StandaloneTable table in MapView.Active.Map.StandaloneTables)
|
||||
{
|
||||
if (table.GetPath() == datasetURI)
|
||||
{
|
||||
ChangedObjectIds[table.URI] = 1;
|
||||
}
|
||||
}
|
||||
RunExpirationChecks(false);
|
||||
}
|
||||
|
||||
private void GetIdsForLayersRemovedEvent(LayerEventsArgs args)
|
||||
{
|
||||
foreach (Layer layer in args.Layers)
|
||||
{
|
||||
ChangedObjectIds[layer.URI] = 1;
|
||||
}
|
||||
RunExpirationChecks(true);
|
||||
}
|
||||
|
||||
private void GetIdsForStandaloneTablesRemovedEvent(StandaloneTableEventArgs args)
|
||||
{
|
||||
foreach (StandaloneTable table in args.Tables)
|
||||
{
|
||||
ChangedObjectIds[table.URI] = 1;
|
||||
}
|
||||
RunExpirationChecks(true);
|
||||
}
|
||||
|
||||
private void AddChangedNestedObjectIds(GroupLayer group)
|
||||
{
|
||||
ChangedObjectIds[group.URI] = 1;
|
||||
foreach (var member in group.Layers)
|
||||
{
|
||||
if (member is GroupLayer subGroup)
|
||||
{
|
||||
AddChangedNestedObjectIds(subGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
ChangedObjectIds[member.URI] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void GetIdsForMapPropertyChangedEvent(MapPropertyChangedEventArgs args)
|
||||
{
|
||||
foreach (Map map in args.Maps)
|
||||
{
|
||||
foreach (MapMember member in map.Layers)
|
||||
{
|
||||
if (member is GroupLayer group)
|
||||
{
|
||||
AddChangedNestedObjectIds(group);
|
||||
}
|
||||
else
|
||||
{
|
||||
ChangedObjectIds[member.URI] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
RunExpirationChecks(false);
|
||||
}
|
||||
|
||||
private void GetIdsForLayersAddedEvent(LayerEventsArgs args)
|
||||
{
|
||||
foreach (Layer layer in args.Layers)
|
||||
{
|
||||
if (layer is FeatureLayer featureLayer)
|
||||
{
|
||||
SubscribeToFeatureLayerDataSourceChange(featureLayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void GetIdsForStandaloneTablesAddedEvent(StandaloneTableEventArgs args)
|
||||
{
|
||||
foreach (StandaloneTable table in args.Tables)
|
||||
{
|
||||
SubscribeToTableDataSourceChange(table);
|
||||
}
|
||||
}
|
||||
|
||||
private void GetIdsForMapMemberPropertiesChangedEvent(MapMemberPropertiesChangedEventArgs args)
|
||||
{
|
||||
// don't subscribe to all events (e.g. expanding group, changing visibility etc.)
|
||||
bool validEvent = false;
|
||||
foreach (var hint in args.EventHints)
|
||||
{
|
||||
if (
|
||||
hint == MapMemberEventHint.DataSource
|
||||
|| hint == MapMemberEventHint.DefinitionQuery
|
||||
|| hint == MapMemberEventHint.LabelClasses
|
||||
|| hint == MapMemberEventHint.LabelVisibility
|
||||
|| hint == MapMemberEventHint.Name
|
||||
|| hint == MapMemberEventHint.Renderer
|
||||
|| hint == MapMemberEventHint.SceneLayerType
|
||||
|| hint == MapMemberEventHint.URL
|
||||
)
|
||||
{
|
||||
validEvent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (validEvent)
|
||||
{
|
||||
foreach (MapMember member in args.MapMembers)
|
||||
{
|
||||
ChangedObjectIds[member.URI] = 1;
|
||||
}
|
||||
RunExpirationChecks(false);
|
||||
}
|
||||
}
|
||||
|
||||
public List<ISendFilter> GetSendFilters() => _sendFilters;
|
||||
|
||||
public List<CardSetting> GetSendSettings() => [];
|
||||
|
||||
[SuppressMessage(
|
||||
"Maintainability",
|
||||
"CA1506:Avoid excessive class coupling",
|
||||
Justification = "Being refactored on in parallel, muting this issue so CI can pass initially."
|
||||
)]
|
||||
public async Task Send(string modelCardId)
|
||||
{
|
||||
//poc: dupe code between connectors
|
||||
using var unitOfWork = _unitOfWorkFactory.Resolve<SendOperation<MapMember>>();
|
||||
try
|
||||
{
|
||||
if (_store.GetModelById(modelCardId) is not SenderModelCard modelCard)
|
||||
{
|
||||
// Handle as GLOBAL ERROR at BrowserBridge
|
||||
throw new InvalidOperationException("No publish model card was found.");
|
||||
}
|
||||
|
||||
CancellationToken cancellationToken = _cancellationManager.InitCancellationTokenSource(modelCardId);
|
||||
|
||||
var sendResult = await QueuedTask
|
||||
.Run(async () =>
|
||||
{
|
||||
List<MapMember> mapMembers = modelCard
|
||||
.SendFilter.NotNull()
|
||||
.GetObjectIds()
|
||||
.Select(id => (MapMember)MapView.Active.Map.FindLayer(id) ?? MapView.Active.Map.FindStandaloneTable(id))
|
||||
.Where(obj => obj != null)
|
||||
.ToList();
|
||||
|
||||
if (mapMembers.Count == 0)
|
||||
{
|
||||
// Handle as CARD ERROR in this function
|
||||
throw new SpeckleSendFilterException(
|
||||
"No objects were found to convert. Please update your publish filter!"
|
||||
);
|
||||
}
|
||||
|
||||
// subscribe to the selected layer events
|
||||
foreach (MapMember mapMember in mapMembers)
|
||||
{
|
||||
if (mapMember is FeatureLayer featureLayer)
|
||||
{
|
||||
SubscribeToFeatureLayerDataSourceChange(featureLayer);
|
||||
}
|
||||
else if (mapMember is StandaloneTable table)
|
||||
{
|
||||
SubscribeToTableDataSourceChange(table);
|
||||
}
|
||||
}
|
||||
|
||||
var result = await unitOfWork
|
||||
.Service.Execute(
|
||||
mapMembers,
|
||||
modelCard.GetSendInfo("ArcGIS"), // POC: get host app name from settings? same for GetReceiveInfo
|
||||
(status, progress) =>
|
||||
_operationProgressManager.SetModelProgress(
|
||||
Parent,
|
||||
modelCardId,
|
||||
new ModelCardProgress(modelCardId, status, progress),
|
||||
cancellationToken
|
||||
),
|
||||
cancellationToken
|
||||
)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return result;
|
||||
})
|
||||
.ConfigureAwait(false);
|
||||
|
||||
Commands.SetModelSendResult(modelCardId, sendResult.RootObjId, sendResult.ConversionResults);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// SWALLOW -> UI handles it immediately, so we do not need to handle anything for now!
|
||||
// Idea for later -> when cancel called, create promise from UI to solve it later with this catch block.
|
||||
// So have 3 state on UI -> Cancellation clicked -> Cancelling -> Cancelled
|
||||
return;
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal()) // UX reasons - we will report operation exceptions as model card error. We may change this later when we have more exception documentation
|
||||
{
|
||||
_logger.LogModelCardHandledError(ex);
|
||||
Commands.SetModelError(modelCardId, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void CancelSend(string modelCardId) => _cancellationManager.CancelOperation(modelCardId);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if any sender model cards contain any of the changed objects. If so, also updates the changed objects hashset for each model card - this last part is important for on send change detection.
|
||||
/// </summary>
|
||||
private void RunExpirationChecks(bool idsDeleted)
|
||||
{
|
||||
var senders = _store.GetSenders();
|
||||
List<string> expiredSenderIds = new();
|
||||
string[] objectIdsList = ChangedObjectIds.Keys.ToArray();
|
||||
|
||||
_sendConversionCache.EvictObjects(objectIdsList);
|
||||
|
||||
foreach (SenderModelCard sender in senders)
|
||||
{
|
||||
var objIds = sender.SendFilter.NotNull().GetObjectIds();
|
||||
var intersection = objIds.Intersect(objectIdsList).ToList();
|
||||
bool isExpired = sender.SendFilter.NotNull().CheckExpiry(objectIdsList);
|
||||
if (isExpired)
|
||||
{
|
||||
expiredSenderIds.Add(sender.ModelCardId.NotNull());
|
||||
|
||||
// Update the model card object Ids
|
||||
if (idsDeleted && sender.SendFilter is ArcGISSelectionFilter filter)
|
||||
{
|
||||
List<string> remainingObjIds = objIds.SkipWhile(x => intersection.Contains(x)).ToList();
|
||||
filter.SelectedObjectIds = remainingObjIds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Commands.SetModelsExpired(expiredSenderIds);
|
||||
ChangedObjectIds = new();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
using ArcGIS.Core.Data;
|
||||
using ArcGIS.Desktop.Framework.Threading.Tasks;
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using Speckle.Connectors.ArcGIS.Utils;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.DUI.Models.Card;
|
||||
using Speckle.Connectors.Utils.Common;
|
||||
using Speckle.Sdk.Common;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Bindings;
|
||||
|
||||
//poc: dupe code between connectors
|
||||
public class BasicConnectorBinding : IBasicConnectorBinding
|
||||
{
|
||||
public string Name => "baseBinding";
|
||||
public IBridge Parent { get; }
|
||||
|
||||
public BasicConnectorBindingCommands Commands { get; }
|
||||
private readonly DocumentModelStore _store;
|
||||
|
||||
public BasicConnectorBinding(DocumentModelStore store, IBridge parent)
|
||||
{
|
||||
_store = store;
|
||||
Parent = parent;
|
||||
Commands = new BasicConnectorBindingCommands(parent);
|
||||
|
||||
_store.DocumentChanged += (_, _) =>
|
||||
{
|
||||
Commands.NotifyDocumentChanged();
|
||||
};
|
||||
}
|
||||
|
||||
public string GetSourceApplicationName() => Speckle.Connectors.Utils.Connector.Slug;
|
||||
|
||||
public string GetSourceApplicationVersion() => Speckle.Connectors.Utils.Connector.VersionString;
|
||||
|
||||
public string GetConnectorVersion() => typeof(BasicConnectorBinding).Assembly.GetVersion();
|
||||
|
||||
public DocumentInfo? GetDocumentInfo()
|
||||
{
|
||||
if (MapView.Active is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new DocumentInfo(MapView.Active.Map.URI, MapView.Active.Map.Name, MapView.Active.Map.Name);
|
||||
}
|
||||
|
||||
public DocumentModelStore GetDocumentState() => _store;
|
||||
|
||||
public void AddModel(ModelCard model) => _store.Models.Add(model);
|
||||
|
||||
public void UpdateModel(ModelCard model) => _store.UpdateModel(model);
|
||||
|
||||
public void RemoveModel(ModelCard model) => _store.RemoveModel(model);
|
||||
|
||||
public void HighlightObjects(List<string> objectIds) =>
|
||||
HighlightObjectsOnView(objectIds.Select(x => new ObjectID(x)).ToList());
|
||||
|
||||
public void HighlightModel(string modelCardId)
|
||||
{
|
||||
var model = _store.GetModelById(modelCardId);
|
||||
|
||||
if (model is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var objectIds = new List<ObjectID>();
|
||||
|
||||
if (model is SenderModelCard senderModelCard)
|
||||
{
|
||||
objectIds = senderModelCard.SendFilter.NotNull().GetObjectIds().Select(x => new ObjectID(x)).ToList();
|
||||
}
|
||||
|
||||
if (model is ReceiverModelCard receiverModelCard)
|
||||
{
|
||||
objectIds = receiverModelCard.BakedObjectIds.NotNull().Select(x => new ObjectID(x)).ToList();
|
||||
}
|
||||
|
||||
if (objectIds is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
HighlightObjectsOnView(objectIds);
|
||||
}
|
||||
|
||||
private async void HighlightObjectsOnView(List<ObjectID> objectIds)
|
||||
{
|
||||
MapView mapView = MapView.Active;
|
||||
|
||||
await QueuedTask
|
||||
.Run(() =>
|
||||
{
|
||||
List<MapMemberFeature> mapMembersFeatures = GetMapMembers(objectIds, mapView);
|
||||
ClearSelectionInTOC();
|
||||
ClearSelection();
|
||||
SelectMapMembersInTOC(mapMembersFeatures);
|
||||
SelectMapMembersAndFeatures(mapMembersFeatures);
|
||||
mapView.ZoomToSelected();
|
||||
})
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private List<MapMemberFeature> GetMapMembers(List<ObjectID> objectIds, MapView mapView)
|
||||
{
|
||||
// find the layer on the map (from the objectID) and add the featureID is available
|
||||
List<MapMemberFeature> mapMembersFeatures = new();
|
||||
|
||||
foreach (ObjectID objectId in objectIds)
|
||||
{
|
||||
MapMember mapMember = mapView.Map.FindLayer(objectId.MappedLayerURI, true);
|
||||
if (mapMember is null)
|
||||
{
|
||||
mapMember = mapView.Map.FindStandaloneTable(objectId.MappedLayerURI);
|
||||
}
|
||||
if (mapMember is not null)
|
||||
{
|
||||
MapMemberFeature mapMembersFeat = new(mapMember, objectId.FeatureId);
|
||||
mapMembersFeatures.Add(mapMembersFeat);
|
||||
}
|
||||
}
|
||||
return mapMembersFeatures;
|
||||
}
|
||||
|
||||
private void ClearSelection()
|
||||
{
|
||||
List<Layer> mapMembers = MapView.Active.Map.GetLayersAsFlattenedList().ToList();
|
||||
foreach (var member in mapMembers)
|
||||
{
|
||||
if (member is FeatureLayer featureLayer)
|
||||
{
|
||||
featureLayer.ClearSelection();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearSelectionInTOC()
|
||||
{
|
||||
MapView.Active.ClearTOCSelection();
|
||||
}
|
||||
|
||||
private void SelectMapMembersAndFeatures(List<MapMemberFeature> mapMembersFeatures)
|
||||
{
|
||||
foreach (MapMemberFeature mapMemberFeat in mapMembersFeatures)
|
||||
{
|
||||
MapMember member = mapMemberFeat.MapMember;
|
||||
if (member is FeatureLayer layer)
|
||||
{
|
||||
if (mapMemberFeat.FeatureId == null)
|
||||
{
|
||||
// select full layer if featureID not specified
|
||||
layer.Select();
|
||||
}
|
||||
else
|
||||
{
|
||||
// query features by ID
|
||||
var objectIDfield = layer.GetFeatureClass().GetDefinition().GetObjectIDField();
|
||||
|
||||
// FeatureID range starts from 0, but auto-assigned IDs in the layer start from 1
|
||||
QueryFilter anotherQueryFilter = new() { WhereClause = $"{objectIDfield} = {mapMemberFeat.FeatureId + 1}" };
|
||||
using (Selection onlyOneSelection = layer.Select(anotherQueryFilter, SelectionCombinationMethod.New)) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SelectMapMembersInTOC(List<MapMemberFeature> mapMembersFeatures)
|
||||
{
|
||||
List<Layer> layers = new();
|
||||
List<StandaloneTable> tables = new();
|
||||
|
||||
foreach (MapMemberFeature mapMemberFeat in mapMembersFeatures)
|
||||
{
|
||||
MapMember member = mapMemberFeat.MapMember;
|
||||
if (member is Layer layer)
|
||||
{
|
||||
if (member is not GroupLayer) // group layer selection clears other layers selection
|
||||
{
|
||||
layers.Add(layer);
|
||||
}
|
||||
else
|
||||
{
|
||||
QueuedTask.Run(() => layer.SetExpanded(true));
|
||||
}
|
||||
}
|
||||
else if (member is StandaloneTable table)
|
||||
{
|
||||
tables.Add(table);
|
||||
}
|
||||
}
|
||||
MapView.Active.SelectLayers(layers);
|
||||
|
||||
// this step clears previous selection, not clear how to ADD selection instead
|
||||
// this is why, activating it only if no layers are selected
|
||||
if (layers.Count == 0)
|
||||
{
|
||||
MapView.Active.SelectStandaloneTables(tables);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!--
|
||||
|
||||
Copyright 2022 Esri
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
-->
|
||||
<ArcGIS defaultAssembly="Speckle.Connectors.ArcGIS3.dll" defaultNamespace="Speckle.Connectors.ArcGIS" xmlns="http://schemas.esri.com/DADF/Registry" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.esri.com/DADF/Registry file:///C:/Program%20Files/ArcGIS/Pro/bin/ArcGIS.Desktop.Framework.xsd">
|
||||
<AddInInfo id="{6CB1D25C-B8BF-4A33-9099-C1F8D1B32EFC}" version="1.0" desktopVersion="3.0.34047">
|
||||
<Name>Speckle</Name>
|
||||
<Description>Speckle connector for ArcGIS</Description>
|
||||
<Image>Images\AddinDesktop32.png</Image>
|
||||
<Author>Speckle Systems</Author>
|
||||
<Company>Speckle Systems</Company>
|
||||
<Date>8/5/2021 12:24:21 PM</Date>
|
||||
<Subject>Framework</Subject>
|
||||
<!-- Note subject can be one or more of these topics:
|
||||
Content, Framework, Editing, Geodatabase, Geometry, Geoprocessing, Layouts, Map Authoring, Map Exploration -->
|
||||
</AddInInfo>
|
||||
<modules>
|
||||
<insertModule id="ConnectorArcGIS_Module" className="SpeckleModule" autoLoad="false" caption="SpeckleModule">
|
||||
<!-- uncomment to have the control hosted on a separate tab-->
|
||||
<tabs>
|
||||
<!--<tab id="Speckle_Tab1" caption="New Tab">
|
||||
<group refID="Speckle_Group1"/>
|
||||
</tab>-->
|
||||
</tabs>
|
||||
<groups>
|
||||
<!-- comment this out if you have no controls on the Addin tab to avoid
|
||||
an empty group-->
|
||||
<group id="Speckle_Group1" caption="Speckle" appearsOnAddInTab="true" keytip="G1">
|
||||
<!-- host controls within groups -->
|
||||
<button refID="SpeckleDUI3_SpeckleDUI3OpenButton" size="large" />
|
||||
</group>
|
||||
</groups>
|
||||
<controls>
|
||||
<!-- add your controls here -->
|
||||
<button id="SpeckleDUI3_SpeckleDUI3OpenButton" caption="SpeckleNewUI"
|
||||
className="SpeckleDUI3OpenButton" loadOnClick="true"
|
||||
keytip="B1"
|
||||
smallImage="Images/s2logo_16.png"
|
||||
largeImage="Images/s2logo_32.png">
|
||||
<tooltip heading="Speckle Connector for ArcGIS">
|
||||
<disabledText />
|
||||
</tooltip>
|
||||
</button>
|
||||
</controls>
|
||||
|
||||
<dockPanes>
|
||||
<dockPane id="SpeckleDUI3_SpeckleDUI3" caption="SpeckleNewUI" className="SpeckleDUI3ViewModel" keytip="DockPane" initiallyVisible="true" dock="group" dockWith="esri_core_projectDockPane">
|
||||
<content className="SpeckleDUI3Wrapper" />
|
||||
</dockPane>
|
||||
</dockPanes>
|
||||
|
||||
</insertModule>
|
||||
</modules>
|
||||
</ArcGIS>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 714 B |
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,81 @@
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using Autofac;
|
||||
using Speckle.Autofac;
|
||||
using Speckle.Autofac.DependencyInjection;
|
||||
using Speckle.Connectors.ArcGIS.Bindings;
|
||||
using Speckle.Connectors.ArcGIS.Filters;
|
||||
using Speckle.Connectors.ArcGIS.HostApp;
|
||||
using Speckle.Connectors.ArcGIS.Operations.Receive;
|
||||
using Speckle.Connectors.ArcGis.Operations.Send;
|
||||
using Speckle.Connectors.ArcGIS.Utils;
|
||||
using Speckle.Connectors.DUI;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.DUI.Models.Card.SendFilter;
|
||||
using Speckle.Connectors.DUI.WebView;
|
||||
using Speckle.Connectors.Utils;
|
||||
using Speckle.Connectors.Utils.Builders;
|
||||
using Speckle.Connectors.Utils.Caching;
|
||||
using Speckle.Connectors.Utils.Instances;
|
||||
using Speckle.Connectors.Utils.Operations;
|
||||
using Speckle.Sdk.Models.GraphTraversal;
|
||||
|
||||
// POC: This is a temp reference to root object senders to tweak CI failing after having generic interfaces into common project.
|
||||
// This should go whenever it is aligned.
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.DependencyInjection;
|
||||
|
||||
public class ArcGISConnectorModule : ISpeckleModule
|
||||
{
|
||||
public void Load(SpeckleContainerBuilder builder)
|
||||
{
|
||||
builder.AddAutofac();
|
||||
builder.AddConnectorUtils();
|
||||
builder.AddDUI();
|
||||
builder.AddDUIView();
|
||||
|
||||
// POC: Overwriting the SyncToMainThread to SyncToCurrentThread for ArcGIS only!
|
||||
// On SendOperation, once we called QueuedTask, it expect to run everything on same thread.
|
||||
// builder.AddSingletonInstance<ISyncToThread, SyncToQueuedTask>();
|
||||
|
||||
builder.AddSingleton<DocumentModelStore, ArcGISDocumentStore>();
|
||||
// Register bindings
|
||||
builder.AddSingleton<IBinding, TestBinding>();
|
||||
builder.AddSingleton<IBinding, ConfigBinding>("connectorName", "ArcGIS"); // POC: Easier like this for now, should be cleaned up later
|
||||
builder.AddSingleton<IBinding, AccountBinding>();
|
||||
|
||||
builder.ContainerBuilder.RegisterType<TopLevelExceptionHandlerBinding>().As<IBinding>().AsSelf().SingleInstance();
|
||||
builder.AddSingleton<ITopLevelExceptionHandler>(c =>
|
||||
c.Resolve<TopLevelExceptionHandlerBinding>().Parent.TopLevelExceptionHandler
|
||||
);
|
||||
|
||||
builder
|
||||
.ContainerBuilder.RegisterType<BasicConnectorBinding>()
|
||||
.As<IBinding>()
|
||||
.As<IBasicConnectorBinding>()
|
||||
.SingleInstance();
|
||||
|
||||
builder.AddSingleton<IBinding, ArcGISSelectionBinding>();
|
||||
builder.AddSingleton<IBinding, ArcGISSendBinding>();
|
||||
builder.AddSingleton<IBinding, ArcGISReceiveBinding>();
|
||||
|
||||
builder.AddTransient<ISendFilter, ArcGISSelectionFilter>();
|
||||
builder.AddScoped<IHostObjectBuilder, ArcGISHostObjectBuilder>();
|
||||
builder.AddSingleton(DefaultTraversal.CreateTraversalFunc());
|
||||
|
||||
// register send operation and dependencies
|
||||
builder.AddScoped<SendOperation<MapMember>>();
|
||||
builder.AddScoped<ArcGISRootObjectBuilder>();
|
||||
builder.AddScoped<IRootObjectBuilder<MapMember>, ArcGISRootObjectBuilder>();
|
||||
builder.AddScoped<ArcGISColorManager>();
|
||||
|
||||
builder.AddScoped<ILocalToGlobalUnpacker, LocalToGlobalUnpacker>();
|
||||
|
||||
// register send conversion cache
|
||||
builder.AddSingleton<ISendConversionCache, SendConversionCache>();
|
||||
|
||||
// operation progress manager
|
||||
builder.AddSingleton<IOperationProgressManager, OperationProgressManager>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,358 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Project>
|
||||
<!-- Code to zip up the files-->
|
||||
|
||||
<UsingTask TaskName="PackageAddIn" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
|
||||
<ParameterGroup>
|
||||
<ZipIntermediatePath ParameterType="System.String" Required="true" />
|
||||
<PackageType ParameterType="System.String" Required="true" />
|
||||
<TargetFolder ParameterType="System.String" Required="true" />
|
||||
<TargetFileName ParameterType="System.String" Required="true" />
|
||||
<RootNamespace ParameterType="System.String" Required="true" />
|
||||
<PackageOutputPath ParameterType="System.String" Output="true"/>
|
||||
</ParameterGroup>
|
||||
<Task>
|
||||
<!-- <Reference Include="System.IO.Compression.FileSystem"/>-->
|
||||
<!-- <Reference Include="System.Xml.Linq"/>-->
|
||||
<!-- <Reference Include="System.Xml"/>-->
|
||||
<Using Namespace="System"/>
|
||||
<Using Namespace="System.IO"/>
|
||||
<Using Namespace="System.Xml.Linq"/>
|
||||
<Using Namespace="System.Linq"/>
|
||||
<Using Namespace="System.IO.Compression"/>
|
||||
<Code Type="Fragment" Language="cs">
|
||||
<![CDATA[
|
||||
Success = false;
|
||||
string ConfigNotFound = "{0} was not found. File must be present in the root of the project and its build action set to AddInContent.";
|
||||
string ZipIntermediatePathNotFound = "{0} was not found.";
|
||||
string DefaultAssemblyDoesNotMatch = "Your value of '{0}' for the '{1}' attribute in the {2} does not match the assembly name '{3}' set for your project.";
|
||||
string DefaultNSDoesNotMatch = "Your value of '{0}' for the '{1}' attribute in the {2} does not match the default namespace '{3}' set for your project.";
|
||||
//Create the name of the Config File and extension
|
||||
string extension = "";
|
||||
string config = "";
|
||||
string attrib_asm = "";
|
||||
string attrib_ns = "";
|
||||
var assemblyValMissing = "";
|
||||
var nsValMissing = "";
|
||||
if (PackageType.ToLower() == "plugin")
|
||||
{
|
||||
Log.LogMessage(MessageImportance.Low, "This is an plugin");
|
||||
config = "Config.xml";
|
||||
extension = ".esriPlugin";
|
||||
attrib_asm = "library";
|
||||
attrib_ns = "namespace";
|
||||
assemblyValMissing = "AddIn element 'library' attribute not found";
|
||||
nsValMissing = "AddIn element 'namespace' attribute not found";
|
||||
}
|
||||
else if (PackageType.ToLower() == "configuration")
|
||||
{
|
||||
Log.LogMessage(MessageImportance.Low, "This is an configuration");
|
||||
config = "Config.daml";
|
||||
extension = ".proConfigX";
|
||||
attrib_asm = "defaultAssembly";
|
||||
attrib_ns = "defaultNamespace";
|
||||
assemblyValMissing = "ArcGIS element 'defaultAssembly' attribute not found";
|
||||
nsValMissing = "ArcGIS element 'defaultNamespace' attribute not found";
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.LogMessage(MessageImportance.Low, "This is an addin");
|
||||
config = "Config.daml";
|
||||
bool proSDKProject = File.Exists(Path.Combine(ZipIntermediatePath, config));
|
||||
if (!proSDKProject) //This might be a class library that uses the Pro references only
|
||||
return true;
|
||||
extension = ".esriAddinX";
|
||||
attrib_asm = "defaultAssembly";
|
||||
attrib_ns = "defaultNamespace";
|
||||
assemblyValMissing = "ArcGIS element 'defaultAssembly' attribute not found";
|
||||
nsValMissing = "ArcGIS element 'defaultNamespace' attribute not found";
|
||||
}
|
||||
// Check if Config.daml exists in ZipFolder
|
||||
ZipIntermediatePath = Path.GetFullPath(ZipIntermediatePath);
|
||||
if (!Directory.Exists(ZipIntermediatePath))
|
||||
{
|
||||
Log.LogError(ZipIntermediatePathNotFound, ZipIntermediatePath);
|
||||
return false;
|
||||
}
|
||||
var addInXML = Path.Combine(ZipIntermediatePath, config);
|
||||
Log.LogMessage(MessageImportance.Low, "addInXML: " + addInXML);
|
||||
Log.LogMessage(MessageImportance.High, "PackageType: " + PackageType);
|
||||
if (!File.Exists(addInXML))
|
||||
{
|
||||
Log.LogError(ConfigNotFound, config);
|
||||
return false;
|
||||
}
|
||||
//Verfiy that an assembly with the name defined in the Config.daml
|
||||
//matches the default assembly set in the project. Ditto for the
|
||||
//namespace
|
||||
string DefaultAssembly = "";
|
||||
string DefaultNamespace = "";
|
||||
XDocument xdoc = XDocument.Load(addInXML);
|
||||
XNamespace DefaultNS = "http://schemas.esri.com/DADF/Registry";
|
||||
if (PackageType.ToLower() == "plugin")
|
||||
{
|
||||
var addin = xdoc.Root.Element(DefaultNS + "AddIn");
|
||||
if (addin != null)
|
||||
{
|
||||
var val = addin.Attribute("library");
|
||||
if (val != null)
|
||||
DefaultAssembly = val.Value;
|
||||
val = addin.Attribute("namespace");
|
||||
if (val != null)
|
||||
DefaultNamespace = val.Value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var val = xdoc.Root.Attribute("defaultAssembly");
|
||||
if (val != null)
|
||||
DefaultAssembly = val.Value;
|
||||
val = xdoc.Root.Attribute("defaultNamespace");
|
||||
if (val != null)
|
||||
DefaultNamespace = val.Value;
|
||||
}
|
||||
if (string.IsNullOrEmpty(DefaultAssembly))
|
||||
{
|
||||
Log.LogError(assemblyValMissing);
|
||||
return false;
|
||||
}
|
||||
if (string.IsNullOrEmpty(DefaultNamespace))
|
||||
{
|
||||
Log.LogError(nsValMissing);
|
||||
return false;
|
||||
}
|
||||
|
||||
//check that the addin assembly and default assembly names match
|
||||
if (DefaultAssembly.ToLower() != TargetFileName.ToLower())
|
||||
{
|
||||
Log.LogWarning(DefaultAssemblyDoesNotMatch, DefaultAssembly, attrib_asm, config, TargetFileName);
|
||||
}
|
||||
//Ditto for namespace
|
||||
if (DefaultNamespace.ToLower() != RootNamespace.ToLower())
|
||||
{
|
||||
Log.LogWarning(DefaultNSDoesNotMatch, DefaultNamespace, attrib_ns, config, RootNamespace);
|
||||
}
|
||||
|
||||
if (!Directory.Exists(TargetFolder))
|
||||
{
|
||||
Directory.CreateDirectory(TargetFolder);
|
||||
}
|
||||
|
||||
string addInAssembly = System.IO.Path.GetFileNameWithoutExtension(DefaultAssembly);
|
||||
string archiveName = addInAssembly + extension;
|
||||
try
|
||||
{
|
||||
string file = Path.Combine(TargetFolder, archiveName);
|
||||
if (File.Exists(file))
|
||||
File.Delete(file);
|
||||
System.IO.Compression.ZipFile.CreateFromDirectory(ZipIntermediatePath, file);
|
||||
PackageOutputPath = Path.GetFullPath(file);
|
||||
Success = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.LogErrorFromException(ex);
|
||||
return false;
|
||||
}
|
||||
return Success;
|
||||
]]>
|
||||
</Code>
|
||||
</Task>
|
||||
</UsingTask>
|
||||
<!-- Code to find relative path-->
|
||||
<UsingTask TaskName="ConvertToRelativePath" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
|
||||
<ParameterGroup>
|
||||
<RelativeTo ParameterType="System.String" Required="true"/>
|
||||
<Paths ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
|
||||
<RelativePaths ParameterType="Microsoft.Build.Framework.ITaskItem[]" Output="true"/>
|
||||
</ParameterGroup>
|
||||
<Task>
|
||||
<Using Namespace="System"/>
|
||||
<Using Namespace="System.IO"/>
|
||||
<Using Namespace="System.Linq"/>
|
||||
<Code Type="Fragment" Language="cs">
|
||||
<![CDATA[
|
||||
var result = new List<ITaskItem>();
|
||||
System.Uri relativeTo = new Uri(this.RelativeTo);
|
||||
foreach (var i in Paths) {
|
||||
try {
|
||||
System.Uri itemFullPath = new Uri(i.GetMetadata("FullPath"));
|
||||
var relativeUri = relativeTo.MakeRelativeUri(itemFullPath);
|
||||
|
||||
result.Add(new TaskItem(Uri.UnescapeDataString(relativeUri.ToString())));
|
||||
}
|
||||
catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
RelativePaths = result.ToArray();
|
||||
foreach (var i in RelativePaths)
|
||||
{
|
||||
Log.LogMessage(MessageImportance.Low, "RelativePaths: " + i.ToString());
|
||||
}
|
||||
return true;
|
||||
]]>
|
||||
</Code>
|
||||
</Task>
|
||||
</UsingTask>
|
||||
<UsingTask TaskName="CleanAddIn" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
|
||||
<ParameterGroup>
|
||||
<ProjectDir ParameterType="System.String" Required="true"/>
|
||||
<AssemblyName ParameterType="System.String" Required="true"/>
|
||||
<PackageType ParameterType="System.String" Required="true"/>
|
||||
<!--<ArcGISFolder ParameterType="System.String" Output="true" /> -->
|
||||
<CleanInfo ParameterType="System.String" Output="true"/>
|
||||
</ParameterGroup>
|
||||
<Task>
|
||||
<Reference Include="System.Xml.Linq"/>
|
||||
<Reference Include="System.Xml"/>
|
||||
<Using Namespace="System"/>
|
||||
<Using Namespace="System.IO"/>
|
||||
<Using Namespace="System.Xml.Linq"/>
|
||||
<Using Namespace="System.Linq"/>
|
||||
<Code Type="Fragment" Language="cs">
|
||||
<![CDATA[
|
||||
Success = false;
|
||||
string ConfigNotFound = "{0} was not found. File must be present in the root of the project and its build action set to AddInContent.";
|
||||
|
||||
//Create the name of the Config File and extension
|
||||
string extension = "";
|
||||
string config = "";
|
||||
|
||||
if (PackageType.ToLower() == "plugin")
|
||||
{
|
||||
config = "Config.xml";
|
||||
extension = ".esriPlugin";
|
||||
}
|
||||
else if (PackageType.ToLower() == "configuration")
|
||||
{
|
||||
config = "Config.daml";
|
||||
extension = ".proConfigX";
|
||||
}
|
||||
else
|
||||
{
|
||||
config = "Config.daml";
|
||||
bool proSDKProject = File.Exists(Path.Combine(ProjectDir, config));
|
||||
if (!proSDKProject) //This might be a class library that uses the Pro references only
|
||||
return true;
|
||||
extension = ".esriAddinX";
|
||||
}
|
||||
|
||||
var addInXML = Path.Combine(ProjectDir, config);
|
||||
if (!File.Exists(addInXML))
|
||||
{
|
||||
Log.LogError(ConfigNotFound, config);
|
||||
return false;
|
||||
}
|
||||
|
||||
//Get the add-in id
|
||||
XDocument xdoc = XDocument.Load(addInXML);
|
||||
XNamespace DefaultNS = "http://schemas.esri.com/DADF/Registry";
|
||||
if (PackageType.ToLower() == "plugin")
|
||||
{
|
||||
Log.LogMessage("process plugin");
|
||||
var addInID = xdoc.Root.Element(DefaultNS + "AddInID");
|
||||
CleanInfo = addInID.Value;//let it error if it's missing
|
||||
}
|
||||
else if (PackageType.ToLower() == "addin")
|
||||
{
|
||||
Log.LogMessage("process addin");
|
||||
var addinInfo = xdoc.Root.Element(DefaultNS + "AddInInfo");
|
||||
CleanInfo = addinInfo.Attribute("id").Value;//let it error if it's missing
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.LogMessage("process configuration");
|
||||
CleanInfo = AssemblyName + extension;
|
||||
}
|
||||
Success = true;
|
||||
return Success;
|
||||
]]>
|
||||
</Code>
|
||||
</Task>
|
||||
</UsingTask>
|
||||
<!-- Define additional BuildAction option -->
|
||||
<!-- Set up default zip properties -->
|
||||
<PropertyGroup>
|
||||
<PackageType Condition="'$(PackageType)' == ''">Addin</PackageType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ArcGISFolder>$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\ESRI\ArcGISPro', 'InstallDir', null, RegistryView.Registry64))\bin</ArcGISFolder>
|
||||
<ArcGISFolder Condition="'$(ArcGISFolder)' == ''">$(registry:HKEY_CURRENT_USER\SOFTWARE\ESRI\ArcGISPro@InstallDir)\bin</ArcGISFolder>
|
||||
<ArcGISFolder Condition="'$(ArcGISFolder)' == '' Or !Exists('$(ArcGISFolder)\RegisterAddIn.exe')">$(ProgramData)\EsriProCommon\</ArcGISFolder>
|
||||
</PropertyGroup>
|
||||
<Target Name="ArcGISInstallOutput" AfterTargets="Build">
|
||||
<Message Text="IntermediateOutputPath Name: $(IntermediateOutputPath)..." Importance="High"/>
|
||||
<Message Text="CleanFile Name: $(CleanFile)..." Importance="High"/>
|
||||
<Message Text="ProjectDir Name: $(ProjectDir)..." Importance="High"/>
|
||||
<Message Text="AssemblyName Name: $(AssemblyName)..." Importance="High"/>
|
||||
<Message Text="TargetFileName Name: $(TargetFileName)..." Importance="High"/>
|
||||
<Message Text="RootNamespace: $(RootNamespace)..." Importance="High"/>
|
||||
<Message Text="TargetFolder Name: $(OutDir)..." Importance="High"/>
|
||||
<Message Text="PackageType Name: $(PackageType)..." Importance="High"/>
|
||||
<Message Text="Install dir: $(ArcGISFolder)" Importance="High"/>
|
||||
<!-- Get a list of project outputs from the cache file and FileWritesXXX item,
|
||||
excluding those in intermediate output directory -->
|
||||
<!-- Note clean file may miss listing CopyLocal reference -->
|
||||
<ReadLinesFromFile File="$(IntermediateOutputPath)$(CleanFile)">
|
||||
<Output TaskParameter="Lines" ItemName="CacheOutputFiles" />
|
||||
</ReadLinesFromFile>
|
||||
<FindUnderPath Files="@(CacheOutputFiles)" Path="$(OutDir)">
|
||||
<Output TaskParameter="InPath" ItemName="PackageOutputFiles" />
|
||||
</FindUnderPath>
|
||||
<FindUnderPath Files="@(FileWrites->'%(FullPath)')" Path="$(OutDir)">
|
||||
<Output TaskParameter="InPath" ItemName="PackageOutputFiles" />
|
||||
</FindUnderPath>
|
||||
<FindUnderPath Files="@(FileWritesShareable->'%(FullPath)')" Path="$(OutDir)">
|
||||
<Output TaskParameter="InPath" ItemName="PackageOutputFiles" />
|
||||
</FindUnderPath>
|
||||
<RemoveDuplicates Inputs="@(PackageOutputFiles)">
|
||||
<Output TaskParameter="Filtered" ItemName="FilteredPackageOutputFiles" />
|
||||
</RemoveDuplicates>
|
||||
<ConvertToRelativePath Paths="@(FilteredPackageOutputFiles)" RelativeTo="$(TargetDir)">
|
||||
<Output TaskParameter="RelativePaths" ItemName="ConfigBinaries" />
|
||||
</ConvertToRelativePath>
|
||||
<Message Text="ConvertToRelativePath Task, TargetDir: $(TargetDir) " Importance="High"/>
|
||||
</Target>
|
||||
<Target Name="PackageArcGISContents" AfterTargets="ArcGISInstallOutput">
|
||||
<Message Text="Running PackageArcGISContents..." Importance="High"/>
|
||||
<RemoveDir Condition="Exists('$(ZipIntermediatePath)')" Directories="$(ZipIntermediatePath)" />
|
||||
<Message Text="ZipIntermediatePath: $(ZipIntermediatePath)Install..." Importance="High"/>
|
||||
<!-- Copy project output files, preserving folder structure -->
|
||||
<Copy SourceFiles="@(ConfigBinaries->'$(OutDir)%(Identity)')" ContinueOnError="true" DestinationFolder="$(IntermediateOutputPath)temp_archive\Install\%(RelativeDir)" />
|
||||
<!-- Copy items marked with Content as BuildAction, preserving folder structure & handling linked items -->
|
||||
<!-- Only include items that have CopyToOutputDirectory as Never -->
|
||||
<Copy SourceFiles="@(Content)" Condition="'%(Content.Link)' == '' And ('%(Content.CopyToOutputDirectory)' == 'Never' Or '%(Content.CopyToOutputDirectory)' == '')" DestinationFolder="$(IntermediateOutputPath)temp_archive\%(RelativeDir)" ContinueOnError="true" />
|
||||
<Copy SourceFiles="@(Content)" Condition="'%(Content.Link)' != '' And ('%(Content.CopyToOutputDirectory)' == 'Never' Or '%(Content.CopyToOutputDirectory)' == '')" DestinationFiles="$(IntermediateOutputPath)temp_archive\%(Content.Link)" ContinueOnError="true"/>
|
||||
<!-- Zipping up add-in resources -->
|
||||
<PackageAddIn ZipIntermediatePath="$(IntermediateOutputPath)temp_archive\"
|
||||
PackageType="$(PackageType)"
|
||||
TargetFolder="$(OutDir)"
|
||||
TargetFileName="$(TargetFileName)"
|
||||
RootNamespace="$(RootNamespace)">
|
||||
<Output TaskParameter="PackageOutputPath" PropertyName="PackageFile" />
|
||||
</PackageAddIn>
|
||||
<!-- Shell out to RegisterAddIn.exe to install the package -->
|
||||
<Message Text="Deploying $(PackageType)..." Importance="High"/>
|
||||
<Message Text="ArcGISFolder Name: $(ArcGISFolder)..." Importance="High"/>
|
||||
<Message Text="Unable to execute RegisterAddIn.exe. ArcGIS Pro is not installed." Importance="High" Condition="!Exists('$(ArcGISFolder)')"/>
|
||||
<Message Text="Execute RegisterAddIn.exe "$(PackageFile)" /s..." Importance="High" Condition="Exists('$(ArcGISFolder)')"/>
|
||||
<Exec IgnoreExitCode="true" WorkingDirectory="$(ArcGISFolder)" Command="RegisterAddIn.exe "$(PackageFile)" /s" Condition="Exists('$(ArcGISFolder)') AND $(PackageFile) != '' ">
|
||||
<Output TaskParameter="ExitCode" PropertyName="ESRIRegAddinExitCode" />
|
||||
</Exec>
|
||||
<RemoveDir Condition="Exists('$(ZipIntermediatePath)')" Directories="$(ZipIntermediatePath)" />
|
||||
</Target>
|
||||
<Target Name="CleanArcGISContents" AfterTargets="Clean">
|
||||
<CleanAddIn ProjectDir="$(ProjectDir)"
|
||||
AssemblyName="$(AssemblyName)"
|
||||
PackageType="$(PackageType)">
|
||||
<Output TaskParameter="CleanInfo" PropertyName="CleanInfo" />
|
||||
</CleanAddIn>
|
||||
<Message Text="Clean $(PackageType).$(ArcGISFolder).." Importance="High"/>
|
||||
<Message Text="Execute RegisterAddIn.exe "$(CleanInfo)" /u..." Importance="High" Condition="Exists('$(ArcGISFolder)')"/>
|
||||
<Message Text="Unable to execute RegisterAddIn.exe. ArcGIS Pro is not installed." Importance="High" Condition="!Exists('$(ArcGISFolder)')"/>
|
||||
<Exec IgnoreExitCode="true" WorkingDirectory="$(ArcGISFolder)" Command="RegisterAddIn.exe "$(CleanInfo)" /u /s" Condition="Exists('$(ArcGISFolder)') AND $(CleanInfo) != ''">
|
||||
<Output TaskParameter="ExitCode" PropertyName="ESRIRegAddinExitCode" />
|
||||
</Exec>
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -0,0 +1,10 @@
|
||||
using Speckle.Connectors.DUI.Models.Card.SendFilter;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Filters;
|
||||
|
||||
public class ArcGISEverythingFilter : EverythingSendFilter
|
||||
{
|
||||
public override List<string> GetObjectIds() => new(); // TODO
|
||||
|
||||
public override bool CheckExpiry(string[] changedObjectIds) => true;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using Speckle.Connectors.DUI.Models.Card.SendFilter;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Filters;
|
||||
|
||||
public class ArcGISSelectionFilter : DirectSelectionSendFilter
|
||||
{
|
||||
public override List<string> GetObjectIds() => SelectedObjectIds;
|
||||
|
||||
public override bool CheckExpiry(string[] changedObjectIds) => SelectedObjectIds.Intersect(changedObjectIds).Any();
|
||||
}
|
||||
@@ -0,0 +1,565 @@
|
||||
using System.Drawing;
|
||||
using ArcGIS.Core.CIM;
|
||||
using ArcGIS.Core.Data;
|
||||
using ArcGIS.Desktop.Framework.Threading.Tasks;
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using Speckle.Converters.ArcGIS3.Utils;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using Speckle.Sdk.Models.GraphTraversal;
|
||||
using Speckle.Sdk.Models.Proxies;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.HostApp;
|
||||
|
||||
public class ArcGISColorManager
|
||||
{
|
||||
private Dictionary<string, ColorProxy> ColorProxies { get; set; } = new();
|
||||
public Dictionary<string, Color> ObjectColorsIdMap { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Iterates through a given set of arcGIS map members (layers containing objects) and collects their colors.
|
||||
/// </summary>
|
||||
/// <param name="mapMembersWithDisplayPriority"></param>
|
||||
/// <returns>A list of color proxies, where the application Id is argb value + display priority</returns>
|
||||
/// <remarks>
|
||||
/// In ArcGIS, map members contain a formula, which individual features contained in map members will use to calculate their color.
|
||||
/// Since display priority is important for ArcGIS layers, we are creating different Color Proxies for eg the same argb color value but different display priority.
|
||||
/// </remarks>
|
||||
public List<ColorProxy> UnpackColors(List<(MapMember, int)> mapMembersWithDisplayPriority)
|
||||
{
|
||||
// injected as Singleton, so we need to clean existing proxies first
|
||||
ColorProxies = new();
|
||||
|
||||
foreach ((MapMember mapMember, int priority) in mapMembersWithDisplayPriority)
|
||||
{
|
||||
switch (mapMember)
|
||||
{
|
||||
// FeatureLayer colors will be processed per feature object
|
||||
case FeatureLayer featureLayer:
|
||||
ProcessFeatureLayerColors(featureLayer, priority);
|
||||
break;
|
||||
|
||||
// RasterLayer object colors are converted as mesh vertex colors, but we need to store displayPriority on the raster layer. Default color is used for all rasters.
|
||||
case RasterLayer rasterLayer:
|
||||
ProcessRasterLayerColors(rasterLayer, priority);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ColorProxies.Values.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse Color Proxies and stores in ObjectColorsIdMap the relationship between object ids and colors
|
||||
/// </summary>
|
||||
/// <param name="colorProxies"></param>
|
||||
/// <param name="onOperationProgressed"></param>
|
||||
public void ParseColors(List<ColorProxy> colorProxies, Action<string, double?>? onOperationProgressed)
|
||||
{
|
||||
// injected as Singleton, so we need to clean existing proxies first
|
||||
ObjectColorsIdMap = new();
|
||||
var count = 0;
|
||||
foreach (ColorProxy colorProxy in colorProxies)
|
||||
{
|
||||
onOperationProgressed?.Invoke("Converting colors", (double)++count / colorProxies.Count);
|
||||
foreach (string objectId in colorProxy.objects)
|
||||
{
|
||||
Color convertedColor = Color.FromArgb(colorProxy.value);
|
||||
ObjectColorsIdMap.TryAdd(objectId, convertedColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new CIMUniqueValueClass for UniqueRenderer per each object ID
|
||||
/// </summary>
|
||||
/// <param name="tc"></param>
|
||||
/// <param name="speckleGeometryType"></param>
|
||||
private CIMUniqueValueClass CreateColorCategory(TraversalContext tc, esriGeometryType speckleGeometryType)
|
||||
{
|
||||
Base baseObj = tc.Current;
|
||||
|
||||
// declare default white color
|
||||
Color color = Color.FromArgb(255, 255, 255, 255);
|
||||
|
||||
// get color moving upwards from the object
|
||||
foreach (var parent in tc.GetAscendants())
|
||||
{
|
||||
if (parent.applicationId is string appId && ObjectColorsIdMap.TryGetValue(appId, out Color objColor))
|
||||
{
|
||||
color = objColor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CIMSymbolReference symbol = CreateSymbol(speckleGeometryType, color);
|
||||
|
||||
// First create a "CIMUniqueValueClass"
|
||||
List<CIMUniqueValue> listUniqueValues = new() { new CIMUniqueValue { FieldValues = new string[] { baseObj.id } } };
|
||||
|
||||
CIMUniqueValueClass newUniqueValueClass =
|
||||
new()
|
||||
{
|
||||
Editable = true,
|
||||
Label = baseObj.id,
|
||||
Patch = PatchShape.Default,
|
||||
Symbol = symbol,
|
||||
Visible = true,
|
||||
Values = listUniqueValues.ToArray()
|
||||
};
|
||||
return newUniqueValueClass;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a Symbol from GeometryType and Color
|
||||
/// </summary>
|
||||
/// <param name="speckleGeometryType"></param>
|
||||
/// <param name="color"></param>
|
||||
private CIMSymbolReference CreateSymbol(esriGeometryType speckleGeometryType, Color color)
|
||||
{
|
||||
var symbol = SymbolFactory
|
||||
.Instance.ConstructPointSymbol(ColorFactory.Instance.CreateColor(color))
|
||||
.MakeSymbolReference();
|
||||
|
||||
switch (speckleGeometryType)
|
||||
{
|
||||
case esriGeometryType.esriGeometryLine:
|
||||
case esriGeometryType.esriGeometryPolyline:
|
||||
symbol = SymbolFactory
|
||||
.Instance.ConstructLineSymbol(ColorFactory.Instance.CreateColor(color))
|
||||
.MakeSymbolReference();
|
||||
break;
|
||||
case esriGeometryType.esriGeometryPolygon:
|
||||
case esriGeometryType.esriGeometryMultiPatch:
|
||||
symbol = SymbolFactory
|
||||
.Instance.ConstructPolygonSymbol(ColorFactory.Instance.CreateColor(color))
|
||||
.MakeSymbolReference();
|
||||
break;
|
||||
}
|
||||
|
||||
return symbol;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add CIMUniqueValueClass to Layer Renderer (if exists); apply Renderer to Layer (again)
|
||||
/// </summary>
|
||||
/// <param name="tc"></param>
|
||||
/// <param name="trackerItem"></param>
|
||||
public async Task SetOrEditLayerRenderer(TraversalContext tc, ObjectConversionTracker trackerItem)
|
||||
{
|
||||
if (trackerItem.HostAppMapMember is not FeatureLayer fLayer)
|
||||
{
|
||||
// do nothing with non-feature layers
|
||||
return;
|
||||
}
|
||||
|
||||
// declare default grey color, create default symbol for the given layer geometry type
|
||||
var color = Color.FromArgb(ColorFactory.Instance.GreyRGB.CIMColorToInt());
|
||||
CIMSymbolReference defaultSymbol = CreateSymbol(fLayer.ShapeType, color);
|
||||
|
||||
// get existing renderer classes
|
||||
List<CIMUniqueValueClass> listUniqueValueClasses = new() { };
|
||||
var existingRenderer = QueuedTask.Run(() => fLayer.GetRenderer()).Result;
|
||||
// should be always UniqueRenderer, it's the only type we are creating atm
|
||||
if (existingRenderer is CIMUniqueValueRenderer uniqueRenderer)
|
||||
{
|
||||
if (uniqueRenderer.Groups[0].Classes != null)
|
||||
{
|
||||
listUniqueValueClasses.AddRange(uniqueRenderer.Groups[0].Classes.ToList());
|
||||
}
|
||||
}
|
||||
|
||||
// Add new CIMUniqueValueClass (or multiple, if it's a Collection with elements, e.g. VectorLayer)
|
||||
List<TraversalContext> traversalContexts = new();
|
||||
if (tc.Current is Collection collection)
|
||||
{
|
||||
foreach (var element in collection.elements)
|
||||
{
|
||||
TraversalContext newTc = new(element, "elements", tc);
|
||||
traversalContexts.Add(newTc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
traversalContexts.Add(tc);
|
||||
}
|
||||
|
||||
foreach (var tContext in traversalContexts)
|
||||
{
|
||||
CIMUniqueValueClass newUniqueValueClass = CreateColorCategory(tContext, fLayer.ShapeType);
|
||||
if (!listUniqueValueClasses.Select(x => x.Label).Contains(newUniqueValueClass.Label))
|
||||
{
|
||||
listUniqueValueClasses.Add(newUniqueValueClass);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a list of CIMUniqueValueGroup
|
||||
CIMUniqueValueGroup uvg = new() { Classes = listUniqueValueClasses.ToArray(), };
|
||||
List<CIMUniqueValueGroup> listUniqueValueGroups = new() { uvg };
|
||||
// Create the CIMUniqueValueRenderer
|
||||
CIMUniqueValueRenderer uvr =
|
||||
new()
|
||||
{
|
||||
UseDefaultSymbol = true,
|
||||
DefaultLabel = "all other values",
|
||||
DefaultSymbol = defaultSymbol,
|
||||
Groups = listUniqueValueGroups.ToArray(),
|
||||
Fields = new string[] { "Speckle_ID" }
|
||||
};
|
||||
|
||||
// Set the feature layer's renderer.
|
||||
await QueuedTask.Run(() => fLayer.SetRenderer(uvr)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private string GetColorApplicationId(int argb, double order) => $"{argb}_{order}";
|
||||
|
||||
// Adds the element id to the color proxy based on colorId if it exists in ColorProxies,
|
||||
// otherwise creates a new Color Proxy with the element id in the objects property
|
||||
private void AddElementIdToColorProxy(string elementAppId, int colorValue, string colorId, int displayPriority)
|
||||
{
|
||||
if (ColorProxies.TryGetValue(colorId, out ColorProxy? colorProxy))
|
||||
{
|
||||
colorProxy.objects.Add(elementAppId);
|
||||
}
|
||||
else
|
||||
{
|
||||
ColorProxy newProxy =
|
||||
new()
|
||||
{
|
||||
value = colorValue,
|
||||
applicationId = colorId,
|
||||
objects = new() { elementAppId },
|
||||
name = colorId
|
||||
};
|
||||
|
||||
newProxy["displayOrder"] = displayPriority; // 0 - top layer (top display priority), 1,2,3.. decreasing priority
|
||||
ColorProxies.Add(colorId, newProxy);
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessRasterLayerColors(RasterLayer rasterLayer, int displayPriority)
|
||||
{
|
||||
string elementAppId = $"{rasterLayer.URI}_0"; // POC: explain why count = 0 here
|
||||
int argb = -1;
|
||||
string colorId = GetColorApplicationId(argb, displayPriority); // We are using a default color of -1 for all raster layers
|
||||
AddElementIdToColorProxy(elementAppId, argb, colorId, displayPriority);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Record colors from every feature of the layer into ColorProxies
|
||||
/// </summary>
|
||||
/// <param name="layer"></param>
|
||||
/// <param name="displayPriority"></param>
|
||||
private void ProcessFeatureLayerColors(FeatureLayer layer, int displayPriority)
|
||||
{
|
||||
// first get a list of layer fields
|
||||
// field names are unique, but often their alias is used instead by renderer headings
|
||||
// so we are storing both names and alieas in this dictionary for fast lookup
|
||||
// POC: adding aliases are not optimal, because they do not need to be unique && they can be the same as the name of another field
|
||||
Dictionary<string, FieldDescription> layerFieldDictionary = new();
|
||||
foreach (FieldDescription field in layer.GetFieldDescriptions())
|
||||
{
|
||||
layerFieldDictionary.TryAdd(field.Name, field);
|
||||
layerFieldDictionary.TryAdd(field.Alias, field);
|
||||
}
|
||||
|
||||
CIMRenderer layerRenderer = layer.GetRenderer();
|
||||
int count = 1;
|
||||
using (RowCursor rowCursor = layer.Search())
|
||||
{
|
||||
while (rowCursor.MoveNext())
|
||||
{
|
||||
string elementAppId = $"{layer.URI}_{count}";
|
||||
using (Row row = rowCursor.Current)
|
||||
{
|
||||
// get row color
|
||||
int argb = GetLayerColorByRendererAndRow(layerRenderer, row, layerFieldDictionary);
|
||||
string colorId = GetColorApplicationId(argb, displayPriority);
|
||||
AddElementIdToColorProxy(elementAppId, argb, colorId, displayPriority);
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Attempts to retrieve the color from a CIMSymbol
|
||||
private bool TryGetSymbolColor(CIMSymbol symbol, out int symbolColor)
|
||||
{
|
||||
symbolColor = -1;
|
||||
if (symbol.GetColor() is CIMColor cimColor)
|
||||
{
|
||||
switch (cimColor)
|
||||
{
|
||||
case CIMRGBColor rgbColor:
|
||||
symbolColor = rgbColor.CIMColorToInt();
|
||||
return true;
|
||||
case CIMHSVColor hsvColor:
|
||||
symbolColor = RgbFromHsv(hsvColor);
|
||||
return true;
|
||||
case CIMCMYKColor cmykColor:
|
||||
symbolColor = RgbFromCmyk(cmykColor);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private int RbgToInt(int a, int r, int g, int b)
|
||||
{
|
||||
return (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
|
||||
private int RgbFromCmyk(CIMCMYKColor cmykColor)
|
||||
{
|
||||
float c = cmykColor.C;
|
||||
float m = cmykColor.M;
|
||||
float y = cmykColor.Y;
|
||||
float k = cmykColor.K;
|
||||
|
||||
int r = Convert.ToInt32(255 * (1 - c) * (1 - k));
|
||||
int g = Convert.ToInt32(255 * (1 - m) * (1 - k));
|
||||
int b = Convert.ToInt32(255 * (1 - y) * (1 - k));
|
||||
return RbgToInt(255, r, g, b);
|
||||
}
|
||||
|
||||
private int RgbFromHsv(CIMHSVColor hsvColor)
|
||||
{
|
||||
// Translates HSV color to RGB color
|
||||
// H: 0.0 - 360.0, S: 0.0 - 100.0, V: 0.0 - 100.0
|
||||
// R, G, B: 0.0 - 1.0
|
||||
|
||||
float hue = hsvColor.H;
|
||||
float saturation = hsvColor.S;
|
||||
float value = hsvColor.V;
|
||||
|
||||
float c = (value / 100) * (saturation / 100);
|
||||
float x = c * (1 - Math.Abs(((hue / 60) % 2) - 1));
|
||||
float m = (value / 100) - c;
|
||||
|
||||
float r = 0;
|
||||
float g = 0;
|
||||
float b = 0;
|
||||
|
||||
if (hue >= 0 && hue < 60)
|
||||
{
|
||||
r = c;
|
||||
g = x;
|
||||
b = 0;
|
||||
}
|
||||
else if (hue >= 60 && hue < 120)
|
||||
{
|
||||
r = x;
|
||||
g = c;
|
||||
b = 0;
|
||||
}
|
||||
else if (hue >= 120 && hue < 180)
|
||||
{
|
||||
r = 0;
|
||||
g = c;
|
||||
b = x;
|
||||
}
|
||||
else if (hue >= 180 && hue < 240)
|
||||
{
|
||||
r = 0;
|
||||
g = x;
|
||||
b = c;
|
||||
}
|
||||
else if (hue >= 240 && hue < 300)
|
||||
{
|
||||
r = x;
|
||||
g = 0;
|
||||
b = c;
|
||||
}
|
||||
else if (hue >= 300 && hue < 360)
|
||||
{
|
||||
r = c;
|
||||
g = 0;
|
||||
b = x;
|
||||
}
|
||||
|
||||
r += m;
|
||||
g += m;
|
||||
b += m;
|
||||
|
||||
// convert rgb 0.0-1.0 float to int
|
||||
int red = (int)Math.Round(r * 255);
|
||||
int green = (int)Math.Round(g * 255);
|
||||
int blue = (int)Math.Round(b * 255);
|
||||
|
||||
return RbgToInt(255, red, green, blue);
|
||||
}
|
||||
|
||||
private bool TryGetUniqueRendererColor(
|
||||
CIMUniqueValueRenderer uniqueRenderer,
|
||||
Row row,
|
||||
Dictionary<string, FieldDescription> fields,
|
||||
out int color
|
||||
)
|
||||
{
|
||||
if (!TryGetSymbolColor(uniqueRenderer.DefaultSymbol.Symbol, out color)) // get default color
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// note: usually there is only 1 group
|
||||
foreach (CIMUniqueValueGroup group in uniqueRenderer.Groups)
|
||||
{
|
||||
string[] headings = group.Heading.Split(",");
|
||||
List<string> usedFields = new();
|
||||
foreach (string heading in headings)
|
||||
{
|
||||
if (fields.TryGetValue(heading, out FieldDescription? headingField))
|
||||
{
|
||||
usedFields.Add(headingField.Name);
|
||||
}
|
||||
}
|
||||
|
||||
// loop through all values in groups to see if any have met conditions that result in a different color
|
||||
foreach (CIMUniqueValueClass groupClass in group.Classes)
|
||||
{
|
||||
bool groupConditionsMet = true;
|
||||
foreach (CIMUniqueValue value in groupClass.Values)
|
||||
{
|
||||
// all field values have to match the row values
|
||||
for (int i = 0; i < usedFields.Count; i++)
|
||||
{
|
||||
string groupValue = value.FieldValues[i].Replace("<Null>", "");
|
||||
object? rowValue = row[usedFields[i]];
|
||||
|
||||
(string newRowValue, string newGroupValue) = MakeValuesComparable(rowValue, groupValue);
|
||||
if (newGroupValue != newRowValue)
|
||||
{
|
||||
groupConditionsMet = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set the group color to class symbol color if conditions are met
|
||||
if (groupConditionsMet)
|
||||
{
|
||||
if (!TryGetSymbolColor(groupClass.Symbol.Symbol, out color))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make comparable the Label string of a UniqueValueRenderer (groupValue), and a Feature Attribute value (rowValue)
|
||||
/// </summary>
|
||||
/// <param name="rowValue"></param>
|
||||
/// <param name="groupValue"></param>
|
||||
private (string, string) MakeValuesComparable(object? rowValue, string groupValue)
|
||||
{
|
||||
string newGroupValue = groupValue;
|
||||
string newRowValue = Convert.ToString(rowValue) ?? "";
|
||||
|
||||
// int, doubles are tricky to compare with strings, trimming both to 5 digits
|
||||
if (rowValue is int or short or long)
|
||||
{
|
||||
newRowValue = newRowValue.Split(".")[0];
|
||||
newGroupValue = newGroupValue.Split(".")[0];
|
||||
}
|
||||
else if (rowValue is double || rowValue is float)
|
||||
{
|
||||
newRowValue = string.Concat(
|
||||
newRowValue.Split(".")[0],
|
||||
".",
|
||||
newRowValue.Split(".")[^1].AsSpan(0, Math.Min(5, newRowValue.Split(".")[^1].Length))
|
||||
);
|
||||
newGroupValue = string.Concat(
|
||||
newGroupValue.Split(".")[0],
|
||||
".",
|
||||
newGroupValue.Split(".")[^1].AsSpan(0, Math.Min(5, newGroupValue.Split(".")[^1].Length))
|
||||
);
|
||||
}
|
||||
|
||||
return (newRowValue, newGroupValue);
|
||||
}
|
||||
|
||||
private bool TryGetGraduatedRendererColor(
|
||||
CIMClassBreaksRenderer graduatedRenderer,
|
||||
Row row,
|
||||
Dictionary<string, FieldDescription> fields,
|
||||
out int color
|
||||
)
|
||||
{
|
||||
if (!TryGetSymbolColor(graduatedRenderer.DefaultSymbol.Symbol, out color)) // get default color
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string? usedField = null;
|
||||
if (fields.TryGetValue(graduatedRenderer.Field, out FieldDescription? field))
|
||||
{
|
||||
usedField = field.Name;
|
||||
}
|
||||
|
||||
List<CIMClassBreak> reversedBreaks = new(graduatedRenderer.Breaks);
|
||||
reversedBreaks.Reverse();
|
||||
foreach (var rBreak in reversedBreaks)
|
||||
{
|
||||
// keep looping until the last matching condition
|
||||
if (Convert.ToDouble(row[usedField]) <= rBreak.UpperBound)
|
||||
{
|
||||
if (!TryGetSymbolColor(rBreak.Symbol.Symbol, out color)) // get default color
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Tries to retrieve the feature layer color by renderer and row, or a default color of -1
|
||||
private int GetLayerColorByRendererAndRow(CIMRenderer renderer, Row row, Dictionary<string, FieldDescription> fields)
|
||||
{
|
||||
// default color to white. this will be used if the renderer is not supported.
|
||||
int color = -1;
|
||||
|
||||
// get color depending on renderer type
|
||||
switch (renderer)
|
||||
{
|
||||
case CIMSimpleRenderer simpleRenderer:
|
||||
if (!TryGetSymbolColor(simpleRenderer.Symbol.Symbol, out color))
|
||||
{
|
||||
// POC: report CONVERTED WITH WARNING when implemented
|
||||
}
|
||||
break;
|
||||
|
||||
// unique renderers have groups of conditions that may affect the color of a feature
|
||||
// resulting in a different color than the default renderer symbol color
|
||||
case CIMUniqueValueRenderer uniqueRenderer:
|
||||
if (!TryGetUniqueRendererColor(uniqueRenderer, row, fields, out color)) // get default color
|
||||
{
|
||||
// POC: report CONVERTED WITH WARNING when implemented
|
||||
}
|
||||
break;
|
||||
|
||||
case CIMClassBreaksRenderer graduatedRenderer:
|
||||
if (!TryGetGraduatedRendererColor(graduatedRenderer, row, fields, out color)) // get default color
|
||||
{
|
||||
// POC: report CONVERTED WITH WARNING when implemented
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// POC: report CONVERTED WITH WARNING when implemented, unsupported renderer e.g. CIMProportionalRenderer
|
||||
break;
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using ArcGIS.Desktop.Framework.Threading.Tasks;
|
||||
using Speckle.Connectors.Utils.Operations;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.HostApp;
|
||||
|
||||
public class SyncToQueuedTask : ISyncToThread
|
||||
{
|
||||
public Task<T> RunOnThread<T>(Func<T> func) => QueuedTask.Run(func);
|
||||
}
|
||||
|
After Width: | Height: | Size: 524 B |
|
After Width: | Height: | Size: 948 B |
|
After Width: | Height: | Size: 714 B |
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,387 @@
|
||||
using System.Diagnostics.Contracts;
|
||||
using ArcGIS.Core.CIM;
|
||||
using ArcGIS.Core.Geometry;
|
||||
using ArcGIS.Desktop.Framework.Threading.Tasks;
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using Speckle.Connectors.ArcGIS.HostApp;
|
||||
using Speckle.Connectors.ArcGIS.Utils;
|
||||
using Speckle.Connectors.Utils.Builders;
|
||||
using Speckle.Connectors.Utils.Conversion;
|
||||
using Speckle.Connectors.Utils.Instances;
|
||||
using Speckle.Converters.ArcGIS3;
|
||||
using Speckle.Converters.ArcGIS3.Utils;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Objects.GIS;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using Speckle.Sdk.Models.GraphTraversal;
|
||||
using Speckle.Sdk.Models.Instances;
|
||||
using Speckle.Sdk.Models.Proxies;
|
||||
using RasterLayer = Speckle.Objects.GIS.RasterLayer;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Operations.Receive;
|
||||
|
||||
public class ArcGISHostObjectBuilder : IHostObjectBuilder
|
||||
{
|
||||
private readonly IRootToHostConverter _converter;
|
||||
private readonly INonNativeFeaturesUtils _nonGisFeaturesUtils;
|
||||
private readonly ILocalToGlobalUnpacker _localToGlobalUnpacker;
|
||||
private readonly ILocalToGlobalConverterUtils _localToGlobalConverterUtils;
|
||||
|
||||
// POC: figure out the correct scope to only initialize on Receive
|
||||
private readonly IConversionContextStack<ArcGISDocument, Unit> _contextStack;
|
||||
private readonly GraphTraversal _traverseFunction;
|
||||
private readonly ArcGISColorManager _colorManager;
|
||||
|
||||
public ArcGISHostObjectBuilder(
|
||||
IRootToHostConverter converter,
|
||||
IConversionContextStack<ArcGISDocument, Unit> contextStack,
|
||||
INonNativeFeaturesUtils nonGisFeaturesUtils,
|
||||
ILocalToGlobalUnpacker localToGlobalUnpacker,
|
||||
ILocalToGlobalConverterUtils localToGlobalConverterUtils,
|
||||
GraphTraversal traverseFunction,
|
||||
ArcGISColorManager colorManager
|
||||
)
|
||||
{
|
||||
_converter = converter;
|
||||
_contextStack = contextStack;
|
||||
_nonGisFeaturesUtils = nonGisFeaturesUtils;
|
||||
_localToGlobalUnpacker = localToGlobalUnpacker;
|
||||
_localToGlobalConverterUtils = localToGlobalConverterUtils;
|
||||
_traverseFunction = traverseFunction;
|
||||
_colorManager = colorManager;
|
||||
}
|
||||
|
||||
public async Task<HostObjectBuilderResult> Build(
|
||||
Base rootObject,
|
||||
string projectName,
|
||||
string modelName,
|
||||
Action<string, double?>? onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
// TODO get spatialRef and offsets & rotation from ProjectInfo in CommitObject
|
||||
// ATM, GIS commit CRS is stored per layer (in FeatureClass converter), but should be moved to the Root level too
|
||||
|
||||
// Prompt the UI conversion started. Progress bar will swoosh.
|
||||
onOperationProgressed?.Invoke("Converting", null);
|
||||
|
||||
// get colors
|
||||
List<ColorProxy>? colors = (rootObject["colorProxies"] as List<object>)?.Cast<ColorProxy>().ToList();
|
||||
if (colors != null)
|
||||
{
|
||||
_colorManager.ParseColors(colors, onOperationProgressed);
|
||||
}
|
||||
|
||||
var objectsToConvertTc = _traverseFunction
|
||||
.Traverse(rootObject)
|
||||
.Where(ctx => ctx.Current is not Collection || IsGISType(ctx.Current))
|
||||
.Where(ctx => HasGISParent(ctx) is false)
|
||||
.ToList();
|
||||
|
||||
var instanceDefinitionProxies = (rootObject["instanceDefinitionProxies"] as List<object>)
|
||||
?.Cast<InstanceDefinitionProxy>()
|
||||
.ToList();
|
||||
|
||||
var objectsToConvert = _localToGlobalUnpacker.Unpack(instanceDefinitionProxies, objectsToConvertTc);
|
||||
|
||||
int allCount = objectsToConvert.Count;
|
||||
int count = 0;
|
||||
Dictionary<TraversalContext, ObjectConversionTracker> conversionTracker = new();
|
||||
|
||||
// 1. convert everything
|
||||
List<ReceiveConversionResult> results = new(objectsToConvert.Count);
|
||||
List<string> bakedObjectIds = new();
|
||||
foreach (LocalToGlobalMap objectToConvert in objectsToConvert)
|
||||
{
|
||||
string[] path = GetLayerPath(objectToConvert.TraversalContext);
|
||||
Base obj = objectToConvert.AtomicObject;
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
try
|
||||
{
|
||||
if (IsGISType(obj))
|
||||
{
|
||||
string nestedLayerPath = $"{string.Join("\\", path)}";
|
||||
string datasetId = await QueuedTask.Run(() => (string)_converter.Convert(obj)).ConfigureAwait(false);
|
||||
conversionTracker[objectToConvert.TraversalContext] = new ObjectConversionTracker(
|
||||
obj,
|
||||
nestedLayerPath,
|
||||
datasetId
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = _localToGlobalConverterUtils.TransformObjects(objectToConvert.AtomicObject, objectToConvert.Matrix);
|
||||
|
||||
string nestedLayerPath = $"{string.Join("\\", path)}\\{obj.speckle_type.Split(".")[^1]}";
|
||||
Geometry converted = await QueuedTask.Run(() => (Geometry)_converter.Convert(obj)).ConfigureAwait(false);
|
||||
|
||||
conversionTracker[objectToConvert.TraversalContext] = new ObjectConversionTracker(
|
||||
obj,
|
||||
nestedLayerPath,
|
||||
converted
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal()) // DO NOT CATCH SPECIFIC STUFF, conversion errors should be recoverable
|
||||
{
|
||||
results.Add(new(Status.ERROR, obj, null, null, ex));
|
||||
}
|
||||
onOperationProgressed?.Invoke("Converting", (double)++count / allCount);
|
||||
}
|
||||
|
||||
// 2. convert Database entries with non-GIS geometry datasets
|
||||
onOperationProgressed?.Invoke("Writing to Database", null);
|
||||
await QueuedTask
|
||||
.Run(() =>
|
||||
{
|
||||
_nonGisFeaturesUtils.WriteGeometriesToDatasets(conversionTracker, onOperationProgressed);
|
||||
})
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// Create placeholder for Group Layers
|
||||
Dictionary<string, GroupLayer> createdLayerGroups = new();
|
||||
|
||||
// 3. add layer and tables to the Table Of Content
|
||||
int bakeCount = 0;
|
||||
Dictionary<string, MapMember> bakedMapMembers = new();
|
||||
onOperationProgressed?.Invoke("Adding to Map", bakeCount);
|
||||
|
||||
foreach (var item in conversionTracker)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var trackerItem = conversionTracker[item.Key]; // updated tracker object
|
||||
|
||||
// BAKE OBJECTS HERE
|
||||
if (trackerItem.Exception != null)
|
||||
{
|
||||
results.Add(new(Status.ERROR, trackerItem.Base, null, null, trackerItem.Exception));
|
||||
}
|
||||
else if (trackerItem.DatasetId == null)
|
||||
{
|
||||
results.Add(
|
||||
new(
|
||||
Status.ERROR,
|
||||
trackerItem.Base,
|
||||
null,
|
||||
null,
|
||||
new ArgumentException($"Unknown error: Dataset not created for {trackerItem.Base.speckle_type}")
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (bakedMapMembers.TryGetValue(trackerItem.DatasetId, out MapMember? value))
|
||||
{
|
||||
// if the layer already created, just add more features to report, and more color categories
|
||||
// add layer and layer URI to tracker
|
||||
trackerItem.AddConvertedMapMember(value);
|
||||
trackerItem.AddLayerURI(value.URI);
|
||||
conversionTracker[item.Key] = trackerItem; // not necessary atm, but needed if we use conversionTracker further
|
||||
// only add a report item
|
||||
AddResultsFromTracker(trackerItem, results);
|
||||
|
||||
// add color category
|
||||
await _colorManager.SetOrEditLayerRenderer(item.Key, trackerItem).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// no layer yet, create and add layer to Map
|
||||
MapMember mapMember = await AddDatasetsToMap(trackerItem, createdLayerGroups, projectName, modelName)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// add layer and layer URI to tracker
|
||||
trackerItem.AddConvertedMapMember(mapMember);
|
||||
trackerItem.AddLayerURI(mapMember.URI);
|
||||
conversionTracker[item.Key] = trackerItem; // not necessary atm, but needed if we use conversionTracker further
|
||||
|
||||
// add layer URI to bakedIds
|
||||
bakedObjectIds.Add(trackerItem.MappedLayerURI == null ? "" : trackerItem.MappedLayerURI);
|
||||
|
||||
// mark dataset as already created
|
||||
bakedMapMembers[trackerItem.DatasetId] = mapMember;
|
||||
|
||||
// add report item
|
||||
AddResultsFromTracker(trackerItem, results);
|
||||
|
||||
// add color category
|
||||
await _colorManager.SetOrEditLayerRenderer(item.Key, trackerItem).ConfigureAwait(false);
|
||||
}
|
||||
onOperationProgressed?.Invoke("Adding to Map", (double)++bakeCount / conversionTracker.Count);
|
||||
}
|
||||
bakedObjectIds.AddRange(createdLayerGroups.Values.Select(x => x.URI));
|
||||
|
||||
// TODO: validated a correct set regarding bakedobject ids
|
||||
return new(bakedObjectIds, results);
|
||||
}
|
||||
|
||||
private void AddResultsFromTracker(ObjectConversionTracker trackerItem, List<ReceiveConversionResult> results)
|
||||
{
|
||||
if (trackerItem.MappedLayerURI == null) // should not happen
|
||||
{
|
||||
results.Add(
|
||||
new(
|
||||
Status.ERROR,
|
||||
trackerItem.Base,
|
||||
null,
|
||||
null,
|
||||
new ArgumentException($"Created Layer URI not found for {trackerItem.Base.speckle_type}")
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// encode layer ID and ID of its feature in 1 object represented as string
|
||||
ObjectID objectId = new(trackerItem.MappedLayerURI, trackerItem.DatasetRow);
|
||||
if (trackerItem.HostAppGeom != null) // individual hostAppGeometry
|
||||
{
|
||||
results.Add(
|
||||
new(
|
||||
Status.SUCCESS,
|
||||
trackerItem.Base,
|
||||
objectId.ObjectIdToString(),
|
||||
trackerItem.HostAppGeom.GetType().ToString()
|
||||
)
|
||||
);
|
||||
}
|
||||
else // hostApp Layers
|
||||
{
|
||||
results.Add(
|
||||
new(
|
||||
Status.SUCCESS,
|
||||
trackerItem.Base,
|
||||
objectId.ObjectIdToString(),
|
||||
trackerItem.HostAppMapMember?.GetType().ToString()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Task<MapMember> AddDatasetsToMap(
|
||||
ObjectConversionTracker trackerItem,
|
||||
Dictionary<string, GroupLayer> createdLayerGroups,
|
||||
string projectName,
|
||||
string modelName
|
||||
)
|
||||
{
|
||||
return QueuedTask.Run(() =>
|
||||
{
|
||||
// get layer details
|
||||
string? datasetId = trackerItem.DatasetId; // should not be null here
|
||||
Uri uri =
|
||||
new($"{_contextStack.Current.Document.SpeckleDatabasePath.AbsolutePath.Replace('/', '\\')}\\{datasetId}");
|
||||
string nestedLayerName = trackerItem.NestedLayerName;
|
||||
|
||||
// add group for the current layer
|
||||
string shortName = nestedLayerName.Split("\\")[^1];
|
||||
string nestedLayerPath = string.Join("\\", nestedLayerName.Split("\\").SkipLast(1));
|
||||
|
||||
// if no general group layer found
|
||||
if (createdLayerGroups.Count == 0)
|
||||
{
|
||||
Map map = _contextStack.Current.Document.Map;
|
||||
GroupLayer mainGroupLayer = LayerFactory.Instance.CreateGroupLayer(map, 0, $"{projectName}: {modelName}");
|
||||
createdLayerGroups["Basic Speckle Group"] = mainGroupLayer; // key doesn't really matter here
|
||||
}
|
||||
|
||||
var groupLayer = CreateNestedGroupLayer(nestedLayerPath, createdLayerGroups);
|
||||
|
||||
// Most of the Speckle-written datasets will be containing geometry and added as Layers
|
||||
// although, some datasets might be just tables (e.g. native GIS Tables, in the future maybe Revit schedules etc.
|
||||
// We can create a connection to the dataset in advance and determine its type, but this will be more
|
||||
// expensive, than assuming by default that it's a layer with geometry (which in most cases it's expected to be)
|
||||
try
|
||||
{
|
||||
var layer = LayerFactory.Instance.CreateLayer(uri, groupLayer, layerName: shortName);
|
||||
if (layer == null)
|
||||
{
|
||||
throw new SpeckleException($"Layer '{shortName}' was not created");
|
||||
}
|
||||
|
||||
// if Scene
|
||||
// https://community.esri.com/t5/arcgis-pro-sdk-questions/sdk-equivalent-to-changing-layer-s-elevation/td-p/1346139
|
||||
if (_contextStack.Current.Document.Map.IsScene)
|
||||
{
|
||||
var groundSurfaceLayer = _contextStack.Current.Document.Map.GetGroundElevationSurfaceLayer();
|
||||
var layerElevationSurface = new CIMLayerElevationSurface
|
||||
{
|
||||
ElevationSurfaceLayerURI = groundSurfaceLayer.URI,
|
||||
};
|
||||
|
||||
// for Feature Layers
|
||||
if (layer.GetDefinition() is CIMFeatureLayer cimLyr)
|
||||
{
|
||||
cimLyr.LayerElevation = layerElevationSurface;
|
||||
layer.SetDefinition(cimLyr);
|
||||
}
|
||||
}
|
||||
|
||||
layer.SetExpanded(true);
|
||||
return (MapMember)layer;
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
StandaloneTable table = StandaloneTableFactory.Instance.CreateStandaloneTable(
|
||||
uri,
|
||||
groupLayer,
|
||||
tableName: shortName
|
||||
);
|
||||
return table;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private GroupLayer CreateNestedGroupLayer(string nestedLayerPath, Dictionary<string, GroupLayer> createdLayerGroups)
|
||||
{
|
||||
GroupLayer lastGroup = createdLayerGroups.FirstOrDefault().Value;
|
||||
if (lastGroup == null) // if layer not found
|
||||
{
|
||||
throw new InvalidOperationException("Speckle Layer Group not found");
|
||||
}
|
||||
|
||||
// iterate through each nested level
|
||||
string createdGroupPath = "";
|
||||
var allPathElements = nestedLayerPath.Split("\\").Where(x => !string.IsNullOrEmpty(x));
|
||||
foreach (string pathElement in allPathElements)
|
||||
{
|
||||
createdGroupPath += "\\" + pathElement;
|
||||
if (createdLayerGroups.TryGetValue(createdGroupPath, out var existingGroupLayer))
|
||||
{
|
||||
lastGroup = existingGroupLayer;
|
||||
}
|
||||
else
|
||||
{
|
||||
// create new GroupLayer under last found Group, named with last pathElement
|
||||
lastGroup = LayerFactory.Instance.CreateGroupLayer(lastGroup, 0, pathElement);
|
||||
lastGroup.SetExpanded(true);
|
||||
}
|
||||
createdLayerGroups[createdGroupPath] = lastGroup;
|
||||
}
|
||||
return lastGroup;
|
||||
}
|
||||
|
||||
[Pure]
|
||||
private static string[] GetLayerPath(TraversalContext context)
|
||||
{
|
||||
string[] collectionBasedPath = context.GetAscendantOfType<Collection>().Select(c => c.name).ToArray();
|
||||
string[] reverseOrderPath =
|
||||
collectionBasedPath.Length != 0 ? collectionBasedPath : context.GetPropertyPath().ToArray();
|
||||
|
||||
var originalPath = reverseOrderPath.Reverse().ToArray();
|
||||
return originalPath.Where(x => !string.IsNullOrEmpty(x)).ToArray();
|
||||
}
|
||||
|
||||
[Pure]
|
||||
private static bool HasGISParent(TraversalContext context)
|
||||
{
|
||||
List<Base> gisLayers = context.GetAscendants().Where(IsGISType).Where(obj => obj != context.Current).ToList();
|
||||
return gisLayers.Count > 0;
|
||||
}
|
||||
|
||||
[Pure]
|
||||
private static bool IsGISType(Base obj)
|
||||
{
|
||||
return obj is RasterLayer or VectorLayer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
using System.Diagnostics;
|
||||
using ArcGIS.Core.Geometry;
|
||||
using ArcGIS.Desktop.Framework.Threading.Tasks;
|
||||
using ArcGIS.Desktop.Internal.Mapping;
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using Speckle.Connectors.ArcGIS.HostApp;
|
||||
using Speckle.Connectors.Utils.Builders;
|
||||
using Speckle.Connectors.Utils.Caching;
|
||||
using Speckle.Connectors.Utils.Conversion;
|
||||
using Speckle.Connectors.Utils.Operations;
|
||||
using Speckle.Converters.ArcGIS3;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Objects.GIS;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using Speckle.Sdk.Models.Proxies;
|
||||
using ArcLayer = ArcGIS.Desktop.Mapping.Layer;
|
||||
|
||||
namespace Speckle.Connectors.ArcGis.Operations.Send;
|
||||
|
||||
/// <summary>
|
||||
/// Stateless builder object to turn an ISendFilter into a <see cref="Base"/> object
|
||||
/// </summary>
|
||||
public class ArcGISRootObjectBuilder : IRootObjectBuilder<MapMember>
|
||||
{
|
||||
private readonly IRootToSpeckleConverter _rootToSpeckleConverter;
|
||||
private readonly ISendConversionCache _sendConversionCache;
|
||||
private readonly ArcGISColorManager _colorManager;
|
||||
private readonly IConversionContextStack<ArcGISDocument, Unit> _contextStack;
|
||||
|
||||
public ArcGISRootObjectBuilder(
|
||||
ISendConversionCache sendConversionCache,
|
||||
ArcGISColorManager colorManager,
|
||||
IConversionContextStack<ArcGISDocument, Unit> contextStack,
|
||||
IRootToSpeckleConverter rootToSpeckleConverter
|
||||
)
|
||||
{
|
||||
_sendConversionCache = sendConversionCache;
|
||||
_colorManager = colorManager;
|
||||
_contextStack = contextStack;
|
||||
_rootToSpeckleConverter = rootToSpeckleConverter;
|
||||
}
|
||||
|
||||
public async Task<RootObjectBuilderResult> Build(
|
||||
IReadOnlyList<MapMember> objects,
|
||||
SendInfo sendInfo,
|
||||
Action<string, double?>? onOperationProgressed = null,
|
||||
CancellationToken ct = default
|
||||
)
|
||||
{
|
||||
// TODO: add a warning if Geographic CRS is set
|
||||
// "Data has been sent in the units 'degrees'. It is advisable to set the project CRS to Projected type (e.g. EPSG:32631) to be able to receive geometry correctly in CAD/BIM software"
|
||||
|
||||
int count = 0;
|
||||
|
||||
Collection rootObjectCollection = new() { name = MapView.Active.Map.Name }; //TODO: Collections
|
||||
|
||||
List<SendConversionResult> results = new(objects.Count);
|
||||
var cacheHitCount = 0;
|
||||
List<(GroupLayer, Collection)> nestedGroups = new();
|
||||
|
||||
// reorder selected layers by Table of Content (TOC) order
|
||||
List<(MapMember, int)> layersWithDisplayPriority = GetLayerDisplayPriority(MapView.Active.Map, objects);
|
||||
|
||||
foreach ((MapMember mapMember, _) in layersWithDisplayPriority)
|
||||
{
|
||||
ct.ThrowIfCancellationRequested();
|
||||
var collectionHost = rootObjectCollection;
|
||||
var applicationId = mapMember.URI;
|
||||
Base converted;
|
||||
|
||||
try
|
||||
{
|
||||
int groupCount = nestedGroups.Count; // bake here, because count will change in the loop
|
||||
// if the layer is not a part of the group, reset groups
|
||||
for (int i = 0; i < groupCount; i++)
|
||||
{
|
||||
if (nestedGroups.Count > 0 && !nestedGroups[0].Item1.Layers.Select(x => x.URI).Contains(applicationId))
|
||||
{
|
||||
nestedGroups.RemoveAt(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// break at the first group, which contains current layer
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// don't use cache for group layers
|
||||
if (
|
||||
mapMember is not GroupLayer
|
||||
&& _sendConversionCache.TryGetValue(sendInfo.ProjectId, applicationId, out ObjectReference value)
|
||||
)
|
||||
{
|
||||
converted = value;
|
||||
cacheHitCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mapMember is GroupLayer group)
|
||||
{
|
||||
// group layer will always come before it's contained layers
|
||||
// keep active group last in the list
|
||||
converted = new Collection();
|
||||
nestedGroups.Insert(0, (group, (Collection)converted));
|
||||
}
|
||||
else
|
||||
{
|
||||
converted = await QueuedTask
|
||||
.Run(() => (Collection)_rootToSpeckleConverter.Convert(mapMember))
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// get units & Active CRS (for writing geometry coords)
|
||||
converted["units"] = _contextStack.Current.Document.ActiveCRSoffsetRotation.SpeckleUnitString;
|
||||
|
||||
var spatialRef = _contextStack.Current.Document.ActiveCRSoffsetRotation.SpatialReference;
|
||||
converted["crs"] = new CRS
|
||||
{
|
||||
wkt = spatialRef.Wkt,
|
||||
name = spatialRef.Name,
|
||||
offset_y = Convert.ToSingle(_contextStack.Current.Document.ActiveCRSoffsetRotation.LatOffset),
|
||||
offset_x = Convert.ToSingle(_contextStack.Current.Document.ActiveCRSoffsetRotation.LonOffset),
|
||||
rotation = Convert.ToSingle(_contextStack.Current.Document.ActiveCRSoffsetRotation.TrueNorthRadians),
|
||||
units_native = _contextStack.Current.Document.ActiveCRSoffsetRotation.SpeckleUnitString,
|
||||
};
|
||||
}
|
||||
|
||||
// other common properties for layers and groups
|
||||
converted["name"] = mapMember.Name;
|
||||
converted.applicationId = applicationId;
|
||||
}
|
||||
|
||||
if (nestedGroups.Count == 0 || nestedGroups.Count == 1 && nestedGroups[0].Item2.applicationId == applicationId)
|
||||
{
|
||||
// add to host if no groups, or current root group
|
||||
collectionHost.elements.Add(converted);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we are adding a layer inside the group
|
||||
var parentCollection = nestedGroups.FirstOrDefault(x =>
|
||||
x.Item1.Layers.Select(y => y.URI).Contains(applicationId)
|
||||
);
|
||||
parentCollection.Item2.elements.Add(converted);
|
||||
}
|
||||
|
||||
results.Add(new(Status.SUCCESS, applicationId, mapMember.GetType().Name, converted));
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
results.Add(new(Status.ERROR, applicationId, mapMember.GetType().Name, null, ex));
|
||||
// POC: add logging
|
||||
}
|
||||
|
||||
onOperationProgressed?.Invoke("Converting", (double)++count / objects.Count);
|
||||
}
|
||||
|
||||
// POC: Add Color Proxies
|
||||
List<ColorProxy> colorProxies = _colorManager.UnpackColors(layersWithDisplayPriority);
|
||||
rootObjectCollection["colorProxies"] = colorProxies;
|
||||
|
||||
// POC: Log would be nice, or can be removed.
|
||||
Debug.WriteLine(
|
||||
$"Cache hit count {cacheHitCount} out of {objects.Count} ({(double)cacheHitCount / objects.Count})"
|
||||
);
|
||||
|
||||
return new RootObjectBuilderResult(rootObjectCollection, results);
|
||||
}
|
||||
|
||||
// Gets the layer display priority for selected layers
|
||||
public List<(MapMember, int)> GetLayerDisplayPriority(Map map, IReadOnlyList<MapMember> mapMembers)
|
||||
{
|
||||
// first get all map layers
|
||||
Dictionary<MapMember, int> layersIndices = new();
|
||||
int count = 0;
|
||||
var layers = map.Layers;
|
||||
count = UnpackLayersOrder(layersIndices, layers, count);
|
||||
|
||||
// iterate through tables
|
||||
foreach (var layer in map.StandaloneTables)
|
||||
{
|
||||
layersIndices[layer] = count + 100; // random number, will be recalculated below
|
||||
}
|
||||
|
||||
// recalculate selected layer priority from all map layers
|
||||
List<(MapMember, int)> selectedLayers = new();
|
||||
int newCount = 0;
|
||||
foreach (KeyValuePair<MapMember, int> valuePair in layersIndices)
|
||||
{
|
||||
if (mapMembers.Contains(valuePair.Key))
|
||||
{
|
||||
selectedLayers.Add((valuePair.Key, newCount));
|
||||
newCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return selectedLayers;
|
||||
}
|
||||
|
||||
private int UnpackLayersOrder(
|
||||
Dictionary<MapMember, int> layersIndices,
|
||||
IEnumerable<ArcLayer> layersToUnpack,
|
||||
int count
|
||||
)
|
||||
{
|
||||
foreach (var layer in layersToUnpack)
|
||||
{
|
||||
switch (layer)
|
||||
{
|
||||
case GroupLayer subGroup:
|
||||
layersIndices[layer] = count;
|
||||
count++;
|
||||
count = UnpackLayersOrder(layersIndices, subGroup.Layers, count);
|
||||
break;
|
||||
case ILayerContainerInternal subLayerContainerInternal:
|
||||
layersIndices[layer] = count;
|
||||
count++;
|
||||
count = UnpackLayersOrder(layersIndices, subLayerContainerInternal.InternalLayers, count);
|
||||
break;
|
||||
default:
|
||||
layersIndices[layer] = count;
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"profiles": {
|
||||
"Speckle.Connectors.ArcGIS3_all_users": {
|
||||
"commandName": "Executable",
|
||||
"executablePath": "C:\\Program Files\\ArcGIS\\Pro\\bin\\ArcGISPro.exe",
|
||||
"commandLineArgs": ""
|
||||
},
|
||||
"Speckle.Connectors.ArcGIS3_user": {
|
||||
"commandName": "Executable",
|
||||
"executablePath": "C:\\Users\\%USERNAME%\\AppData\\Local\\Programs\\ArcGIS\\Pro\\bin\\ArcGISPro.exe",
|
||||
"commandLineArgs": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<UseWPF>true</UseWPF>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<RootNameSpace>Speckle.Connectors.ArcGIS</RootNameSpace>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<EnableWindowsTargeting>true</EnableWindowsTargeting>
|
||||
<DefineConstants>$(DefineConstants);ARCGIS3</DefineConstants>
|
||||
<Configurations>Debug;Release;Local</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="Config.daml" />
|
||||
<Content Include="Images\s2logo_16.png" />
|
||||
<Content Include="Images\s2logo_32.png" />
|
||||
<Content Include="DarkImages\s2logo_16.png" />
|
||||
<Content Include="DarkImages\s2logo_32.png" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Esri.ArcGISPro.Extensions30" IncludeAssets="compile" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Converters\ArcGIS\Speckle.Converters.ArcGIS3.DependencyInjection\Speckle.Converters.ArcGIS3.DependencyInjection.csproj" />
|
||||
<ProjectReference Include="..\..\..\DUI3\Speckle.Connectors.DUI.WebView\Speckle.Connectors.DUI.WebView.csproj" />
|
||||
<ProjectReference Include="..\..\..\Sdk\Speckle.Connectors.Utils\Speckle.Connectors.Utils.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="Esri.ArcGISPro.Extensions30.Speckle.targets" />
|
||||
</Project>
|
||||
@@ -0,0 +1,42 @@
|
||||
using ArcGIS.Desktop.Framework;
|
||||
using ArcGIS.Desktop.Framework.Contracts;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS;
|
||||
|
||||
internal sealed class SpeckleDUI3ViewModel : DockPane
|
||||
{
|
||||
private const string DOCKPANE_ID = "SpeckleDUI3_SpeckleDUI3";
|
||||
|
||||
internal static void Create()
|
||||
{
|
||||
var pane = FrameworkApplication.DockPaneManager.Find(DOCKPANE_ID);
|
||||
pane?.Activate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the pane is initialized.
|
||||
/// </summary>
|
||||
protected override async Task InitializeAsync()
|
||||
{
|
||||
await base.InitializeAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the pane is uninitialized.
|
||||
/// </summary>
|
||||
protected override async Task UninitializeAsync()
|
||||
{
|
||||
await base.UninitializeAsync().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Button implementation to create a new instance of the pane and activate it.
|
||||
/// </summary>
|
||||
internal sealed class SpeckleDUI3OpenButton : Button
|
||||
{
|
||||
protected override void OnClick()
|
||||
{
|
||||
SpeckleDUI3ViewModel.Create();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.Windows.Controls;
|
||||
using Speckle.Connectors.DUI.WebView;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS;
|
||||
|
||||
public class SpeckleDUI3Wrapper : UserControl
|
||||
{
|
||||
public SpeckleDUI3Wrapper()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
Content = SpeckleModule.Current.Container.Resolve<DUI3ControlWebView>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using ArcGIS.Desktop.Framework;
|
||||
using Speckle.Autofac;
|
||||
using Speckle.Autofac.DependencyInjection;
|
||||
using Speckle.Connectors.Utils;
|
||||
using Speckle.Sdk.Common;
|
||||
using Speckle.Sdk.Host;
|
||||
using Module = ArcGIS.Desktop.Framework.Contracts.Module;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS;
|
||||
|
||||
/// <summary>
|
||||
/// This sample shows how to implement pane that contains an Edge WebView2 control using the built-in ArcGIS Pro SDK's WebBrowser control. For details on how to utilize the WebBrowser control in an add-in see here: https://github.com/Esri/arcgis-pro-sdk/wiki/ProConcepts-Framework#webbrowser For details on how to utilize the Microsoft Edge web browser control in an add-in see here: https://github.com/Esri/arcgis-pro-sdk/wiki/ProConcepts-Framework#webbrowser-control
|
||||
/// </summary>
|
||||
internal sealed class SpeckleModule : Module
|
||||
{
|
||||
private static SpeckleModule? s_this;
|
||||
private readonly IDisposable? _disposableLogger;
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the singleton instance to this module here
|
||||
/// </summary>
|
||||
public static SpeckleModule Current =>
|
||||
s_this ??= (SpeckleModule)FrameworkApplication.FindModule("ConnectorArcGIS_Module");
|
||||
|
||||
public SpeckleContainer Container { get; }
|
||||
|
||||
public SpeckleModule()
|
||||
{
|
||||
AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolver.OnAssemblyResolve<SpeckleModule>;
|
||||
|
||||
var builder = SpeckleContainerBuilder.CreateInstance();
|
||||
// init DI
|
||||
_disposableLogger = Connector.Initialize(HostApplications.ArcGIS, GetVersion());
|
||||
|
||||
Container = builder
|
||||
.LoadAutofacModules(
|
||||
Assembly.GetExecutingAssembly(),
|
||||
[Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location).NotNull()]
|
||||
)
|
||||
.Build();
|
||||
}
|
||||
|
||||
private HostAppVersion GetVersion()
|
||||
{
|
||||
#if ARCGIS3
|
||||
return HostAppVersion.v3;
|
||||
#else
|
||||
throw new NotImplementedException();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by Framework when ArcGIS Pro is closing
|
||||
/// </summary>
|
||||
/// <returns>False to prevent Pro from closing, otherwise True</returns>
|
||||
protected override bool CanUnload()
|
||||
{
|
||||
//TODO - add your business logic
|
||||
//return false to ~cancel~ Application close
|
||||
_disposableLogger?.Dispose();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
using System.Xml.Linq;
|
||||
using ArcGIS.Desktop.Core.Events;
|
||||
using ArcGIS.Desktop.Framework.Threading.Tasks;
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using ArcGIS.Desktop.Mapping.Events;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Newtonsoft.Json;
|
||||
using Speckle.Sdk.Common;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Utils;
|
||||
|
||||
public class ArcGISDocumentStore : DocumentModelStore
|
||||
{
|
||||
public ArcGISDocumentStore(
|
||||
JsonSerializerSettings serializerOption,
|
||||
ITopLevelExceptionHandler topLevelExceptionHandler
|
||||
)
|
||||
: base(serializerOption, true)
|
||||
{
|
||||
ActiveMapViewChangedEvent.Subscribe(a => topLevelExceptionHandler.CatchUnhandled(() => OnMapViewChanged(a)), true);
|
||||
ProjectSavingEvent.Subscribe(
|
||||
_ =>
|
||||
{
|
||||
topLevelExceptionHandler.CatchUnhandled(OnProjectSaving);
|
||||
return Task.CompletedTask;
|
||||
},
|
||||
true
|
||||
);
|
||||
ProjectClosingEvent.Subscribe(
|
||||
_ =>
|
||||
{
|
||||
topLevelExceptionHandler.CatchUnhandled(OnProjectClosing);
|
||||
return Task.CompletedTask;
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
// in case plugin was loaded into already opened Map, read metadata from the current Map
|
||||
if (!IsDocumentInit && MapView.Active != null)
|
||||
{
|
||||
IsDocumentInit = true;
|
||||
ReadFromFile();
|
||||
OnDocumentChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnProjectClosing()
|
||||
{
|
||||
if (MapView.Active is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
WriteToFile();
|
||||
}
|
||||
|
||||
private void OnProjectSaving()
|
||||
{
|
||||
if (MapView.Active is not null)
|
||||
{
|
||||
WriteToFile();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On map view switch, this event trigger twice, first for outgoing view, second for incoming view.
|
||||
/// </summary>
|
||||
private void OnMapViewChanged(ActiveMapViewChangedEventArgs args)
|
||||
{
|
||||
if (args.IncomingView is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IsDocumentInit = true;
|
||||
ReadFromFile();
|
||||
OnDocumentChanged();
|
||||
}
|
||||
|
||||
public override void WriteToFile()
|
||||
{
|
||||
Map map = MapView.Active.Map;
|
||||
QueuedTask.Run(() =>
|
||||
{
|
||||
// Read existing metadata - To prevent messing existing metadata. 🤞 Hope other add-in developers will do same :D
|
||||
var existingMetadata = map.GetMetadata();
|
||||
|
||||
// Parse existing metadata
|
||||
XDocument existingXmlDocument = !string.IsNullOrEmpty(existingMetadata)
|
||||
? XDocument.Parse(existingMetadata)
|
||||
: new XDocument(new XElement("metadata"));
|
||||
|
||||
string serializedModels = Serialize();
|
||||
|
||||
XElement xmlModelCards = new("SpeckleModelCards", serializedModels);
|
||||
|
||||
// Check if SpeckleModelCards element already exists at root and update it
|
||||
var speckleModelCardsElement = existingXmlDocument.Root?.Element("SpeckleModelCards");
|
||||
if (speckleModelCardsElement != null)
|
||||
{
|
||||
speckleModelCardsElement.ReplaceWith(xmlModelCards);
|
||||
}
|
||||
else
|
||||
{
|
||||
existingXmlDocument.Root?.Add(xmlModelCards);
|
||||
}
|
||||
|
||||
map.SetMetadata(existingXmlDocument.ToString());
|
||||
});
|
||||
}
|
||||
|
||||
public override void ReadFromFile()
|
||||
{
|
||||
Map map = MapView.Active.Map;
|
||||
QueuedTask.Run(() =>
|
||||
{
|
||||
var metadata = map.GetMetadata();
|
||||
var root = XDocument.Parse(metadata).Root;
|
||||
var element = root?.Element("SpeckleModelCards");
|
||||
if (element is null)
|
||||
{
|
||||
Models = new();
|
||||
return;
|
||||
}
|
||||
|
||||
string modelsString = element.Value;
|
||||
Models = Deserialize(modelsString).NotNull();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Utils;
|
||||
|
||||
// bind together a layer object on the map, and auto-assigned ID if the specific feature
|
||||
public readonly struct MapMemberFeature
|
||||
{
|
||||
public int? FeatureId { get; } // unique feature id (start from 0) of a feature in the layer
|
||||
public MapMember MapMember { get; } // layer object on the Map
|
||||
|
||||
public MapMemberFeature(MapMember mapMember, int? featureId)
|
||||
{
|
||||
MapMember = mapMember;
|
||||
FeatureId = featureId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
namespace Speckle.Connectors.ArcGIS.Utils;
|
||||
|
||||
// this struct is needed to be able to parse single-string value into IDs of both a layer, and it's individual feature
|
||||
public struct ObjectID
|
||||
{
|
||||
private const string FEATURE_ID_SEPARATOR = "__speckleFeatureId__";
|
||||
public string MappedLayerURI { get; } // unique ID of the layer on the map
|
||||
public int? FeatureId { get; } // unique feature id (start from 0) of a feature in the layer
|
||||
|
||||
public ObjectID(string encodedId)
|
||||
{
|
||||
List<string> stringParts = encodedId.Split(FEATURE_ID_SEPARATOR).ToList();
|
||||
MappedLayerURI = stringParts[0];
|
||||
FeatureId = null;
|
||||
if (stringParts.Count > 1)
|
||||
{
|
||||
FeatureId = Convert.ToInt32(stringParts[1]);
|
||||
}
|
||||
}
|
||||
|
||||
public ObjectID(string layerId, int? featureId)
|
||||
{
|
||||
MappedLayerURI = layerId;
|
||||
FeatureId = featureId;
|
||||
}
|
||||
|
||||
public readonly string ObjectIdToString()
|
||||
{
|
||||
if (FeatureId == null)
|
||||
{
|
||||
return $"{MappedLayerURI}";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"{MappedLayerURI}{FEATURE_ID_SEPARATOR}{FeatureId}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,18 @@
|
||||
{
|
||||
"version": 2,
|
||||
"dependencies": {
|
||||
"net8.0-windows7.0": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"net6.0-windows7.0": {
|
||||
"Esri.ArcGISPro.Extensions30": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.0.3, )",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
|
||||
"dependencies": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.3"
|
||||
}
|
||||
"requested": "[3.2.0.49743, )",
|
||||
"resolved": "3.2.0.49743",
|
||||
"contentHash": "fmnYm+mD14Cz0Uqh1ij37SfLJerkyFHK5581y5tXT/l3H2ZvUmVuuxjYquXzyzj9p7IexQzMW4xCpxe+mD922g=="
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"type": "Direct",
|
||||
"requested": "[3.1.0, )",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "jjo4YXRx6MIpv6DiRxJjSpl+sPP0+5VW0clMEdLyIAz44PPwrDTFrd5PZckIxIXl1kKZ2KK6IL2nkt0+ug2MQg=="
|
||||
},
|
||||
"Microsoft.SourceLink.GitHub": {
|
||||
"type": "Direct",
|
||||
@@ -27,24 +30,6 @@
|
||||
"resolved": "1.14.1",
|
||||
"contentHash": "mOOmFYwad3MIOL14VCjj02LljyF1GNw1wP0YVlxtcPvqdxjGGMNdNJJxHptlry3MOd8b40Flm8RPOM8JOlN2sQ=="
|
||||
},
|
||||
"RhinoCommon": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.28.26041.11001, )",
|
||||
"resolved": "8.28.26041.11001",
|
||||
"contentHash": "5mByZF+IdHvRLbYvr6Ek95Pwam6otewAyVHIGSC0sUE1+OscSpd9gbrFWnzo1arfCYmUJcUdsGhf7VayW09fQA==",
|
||||
"dependencies": {
|
||||
"System.Drawing.Common": "7.0.0"
|
||||
}
|
||||
},
|
||||
"RhinoWindows": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.28.26041.11001, )",
|
||||
"resolved": "8.28.26041.11001",
|
||||
"contentHash": "7MBG231k5c0/V/USTzbXpaTCiZCECQOuB80DnpgEvvEA3r//IQQDTbrqawDYmN9BEw/FHiFn82bsf6tV+SS5Iw==",
|
||||
"dependencies": {
|
||||
"RhinoCommon": "[8.28.26041.11001]"
|
||||
}
|
||||
},
|
||||
"Speckle.InterfaceGenerator": {
|
||||
"type": "Direct",
|
||||
"requested": "[0.9.6, )",
|
||||
@@ -87,109 +72,116 @@
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
|
||||
},
|
||||
"Microsoft.CSharp": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.7.0",
|
||||
"contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA=="
|
||||
},
|
||||
"Microsoft.Data.Sqlite": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.5",
|
||||
"contentHash": "KGxbPeWsQMnmQy43DSBxAFtHz3l2JX8EWBSGUCvT3CuZ8KsuzbkqMIJMDOxWtG8eZSoCDI04aiVQjWuuV8HmSw==",
|
||||
"resolved": "7.0.7",
|
||||
"contentHash": "tiNmV1oPy+Z2R7Wd0bPB/FxCr8B+/5q11OpDMG751GA/YuOL7MZrBFfzv5oFRlFe08K6sjrnbrauzzGIeNrzLQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Data.Sqlite.Core": "7.0.5",
|
||||
"Microsoft.Data.Sqlite.Core": "7.0.7",
|
||||
"SQLitePCLRaw.bundle_e_sqlite3": "2.1.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Data.Sqlite.Core": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.5",
|
||||
"contentHash": "FTerRmQPqHrCrnoUzhBu+E+1DNGwyrAMLqHkAqOOOu5pGfyMOj8qQUBxI/gDtWtG11p49UxSfWmBzRNlwZqfUg==",
|
||||
"resolved": "7.0.7",
|
||||
"contentHash": "21FRzcJhaTrlv7kTrqr/ltFcSQM2TyuTTPhUcjO8H73od7Bb3QraNW90c7lUucNI/245XPkKZG4fp7/7OsKCSg==",
|
||||
"dependencies": {
|
||||
"SQLitePCLRaw.core": "2.1.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "Lu41BWNmwhKr6LgyQvcYBOge0pPvmiaK8R5UHXX4//wBhonJyWcT2OK1mqYfEM5G7pTf31fPrpIHOT6sN7EGOA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "2.2.0"
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "ESz6bVoDQX7sgWdKHF6G9Pq672T8k+19AFb/txDXwdz7MoqaNQj2/in3agm/3qae9V+WvQZH86LLTNVo0it8vQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
"Microsoft.Extensions.Primitives": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Binder": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "vJ9xvOZCnUAIHcGC3SU35r3HKmHTVIeHzo6u/qzlHAqD8m6xv92MLin4oJntTvkpKxVX3vI1GFFkIQtU3AdlsQ==",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "o9eELDBfNkR7sUtYysFZ1Q7BQ1mYt27DMkups/3vu7xgPyOpMD+iAfrBZFzUXT2iw0fmFb8s1gfNBZS+IgjKdQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "2.2.0"
|
||||
"Microsoft.Extensions.Configuration": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "KVkv3aF2MQpmGFRh4xRx2CNbc2sjDFk+lH4ySrjWSOS+XoY1Xc+sJphw3N0iYOpoeCCq8976ceVYDH8sdx2qIQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "f9hstgjVmr6rmrfGSpfsVOl2irKAgr1QjrSi3FgnS7kulxband50f2brRLwySAQTADPZeTdow0mpSMcoAdadCw=="
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "44rDtOf1JXXAFpNT2EXMExaDm/4OJ2RXOL9i9lE4bK427nzC7Exphv+beB6IgluyE2GIoo8zezTStMXI7MQ8WA=="
|
||||
},
|
||||
"Microsoft.Extensions.Options": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "9b6JHY7TAXrSfZ6EEGf+j8XnqKIiMPErfmaNXhJYSCb+BUW2H4RtzkNJvwLJzwgzqBP0wtTjyA6Uw4BPPdmkMw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Primitives": "2.2.0",
|
||||
"System.ComponentModel.Annotations": "4.5.0"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0",
|
||||
"Microsoft.Extensions.Primitives": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.1",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net461": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "AmOJZwCqnOCNp6PPcf9joyogScWLtwy0M1WkqfEQ0M9nYwyDD7EX9ZjscKS5iYnyvteX7kzSKFCKt9I9dXA6mA=="
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "LEKAnX7lhUhSoIc2XraCTK3M4IU/LdVUzCe464Sa4+7F4ZJuXHHRzZli2mDbiT4xzAZhgqXbvfnb5+CNDcQFfg=="
|
||||
},
|
||||
"Microsoft.SourceLink.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
|
||||
},
|
||||
"Microsoft.Win32.SystemEvents": {
|
||||
"Polly": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "2nXPrhdAyAzir0gLl8Yy8S5Mnm/uBSQQA7jEsILOS1MTyS7DbmV1NgViMtvV1sfCD1ebITpNwb1NIinKeJgUVQ=="
|
||||
"resolved": "7.2.3",
|
||||
"contentHash": "DeCY0OFbNdNxsjntr1gTXHJ5pKUwYzp04Er2LLeN3g6pWhffsGuKVfMBLe1lw7x76HrPkLxKEFxBlpRxS2nDEQ=="
|
||||
},
|
||||
"Polly.Contrib.WaitAndRetry": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.1.1",
|
||||
"contentHash": "1MUQLiSo4KDkQe6nzQRhIU05lm9jlexX5BVsbuw0SL82ynZ+GzAHQxJVDPVBboxV37Po3SG077aX8DuSy8TkaA=="
|
||||
},
|
||||
"Polly.Extensions.Http": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.0",
|
||||
"contentHash": "drrG+hB3pYFY7w1c3BD+lSGYvH2oIclH8GRSehgfyP5kjnFnHKQuuBhuHLv+PWyFuaTDyk/vfRpnxOzd11+J8g==",
|
||||
"dependencies": {
|
||||
"Polly": "7.1.0"
|
||||
}
|
||||
},
|
||||
"Speckle.DoubleNumerics": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.0.1",
|
||||
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
|
||||
},
|
||||
"Speckle.Newtonsoft.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "13.0.2",
|
||||
"contentHash": "g1BejUZwax5PRfL6xHgLEK23sqHWOgOj9hE7RvfRRlN00AGt8GnPYt8HedSK7UB3HiRW8zCA9Pn0iiYxCK24BA=="
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"Speckle.Sdk.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.15.3",
|
||||
"contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.5",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.15.3"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.15.3",
|
||||
"contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
|
||||
"resolved": "3.1.0-dev.107",
|
||||
"contentHash": "phWGEyqiZlB5LichJtVA45xFFvxRxlU8rBTEag3llZeNIlSXRW0wzWmAq8gdQftHJyw59iupZwH2Tx+jglzp8w=="
|
||||
},
|
||||
"SQLitePCLRaw.bundle_e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
@@ -221,19 +213,6 @@
|
||||
"SQLitePCLRaw.core": "2.1.4"
|
||||
}
|
||||
},
|
||||
"System.ComponentModel.Annotations": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
|
||||
},
|
||||
"System.Drawing.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "KIX+oBU38pxkKPxvLcLfIkOV5Ien8ReN78wro7OF5/erwcmortzeFx+iBswlh2Vz6gVne0khocQudGwaO1Ey6A==",
|
||||
"dependencies": {
|
||||
"Microsoft.Win32.SystemEvents": "7.0.0"
|
||||
}
|
||||
},
|
||||
"System.Memory": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.3",
|
||||
@@ -244,25 +223,25 @@
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ=="
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe": {
|
||||
"System.Text.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.1",
|
||||
"contentHash": "Zh8t8oqolRaFa9vmOZfdQm/qKejdqz0J9kr7o2Fu0vPeoH3BL1EOXipKWwkWtLT1JPzjByrF19fGuFlNbmPpiw=="
|
||||
"resolved": "5.0.2",
|
||||
"contentHash": "I47dVIGiV6SfAyppphxqupertT/5oZkYLDCX6vC3HpOI4ZLjyoKAreUoem2ie6G0RbRuFrlqz/PcTQjfb2DOfQ=="
|
||||
},
|
||||
"speckle.connectors.common": {
|
||||
"speckle.autofac": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Converters.Common": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.15.3, )"
|
||||
"Autofac": "[5.2.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Connectors.Common": "[1.0.0, )"
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[3.1.0, )",
|
||||
"Speckle.Autofac": "[1.0.0, )",
|
||||
"Speckle.Connectors.Utils": "[1.0.0, )",
|
||||
"Speckle.Sdk": "[3.1.0-dev.107, )",
|
||||
"System.Threading.Tasks.Dataflow": "[6.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui.webview": {
|
||||
@@ -272,90 +251,108 @@
|
||||
"Speckle.Connectors.DUI": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.logging": {
|
||||
"type": "Project"
|
||||
"speckle.connectors.utils": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging": "[3.1.0, )",
|
||||
"Speckle.Autofac": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.1.0-dev.107, )",
|
||||
"Speckle.Sdk": "[3.1.0-dev.107, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.arcgis3": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Esri.ArcGISPro.Extensions30": "[3.2.0.49743, )",
|
||||
"Speckle.Converters.Common": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.arcgis3.dependencyinjection": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Speckle.Converters.ArcGIS3": "[1.0.0, )",
|
||||
"Speckle.Converters.Common.DependencyInjection": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.15.3, )"
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[3.1.0, )",
|
||||
"Speckle.Autofac": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.1.0-dev.107, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.rhino8": {
|
||||
"speckle.converters.common.dependencyinjection": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Speckle.Autofac": "[1.0.0, )",
|
||||
"Speckle.Converters.Common": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
"Autofac": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0"
|
||||
}
|
||||
"requested": "[5.2.0, )",
|
||||
"resolved": "5.2.0",
|
||||
"contentHash": "V8dBH0dsv75uDzl7Sw+HkhKDPUw2eXnlMjcSVMH+tLo2s67MpTKGyDj1pDcpR+IF2u4YRs0s3/x7R88YJzIWvg=="
|
||||
},
|
||||
"Microsoft.Extensions.Logging": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==",
|
||||
"requested": "[3.1.0, )",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "P+8sKQ8L4ooL79sxxqwFPxGGC3aBrUDLB/dZqhs4J0XjTyrkeeyJQ4D4nzJB6OnAhy78HIIgQ/RbD6upOXLynw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Binder": "2.2.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Options": "2.2.0"
|
||||
"Microsoft.Extensions.Configuration.Binder": "3.1.0",
|
||||
"Microsoft.Extensions.DependencyInjection": "3.1.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "3.1.0",
|
||||
"Microsoft.Extensions.Options": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
|
||||
},
|
||||
"Microsoft.Web.WebView2": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[1.0.1938.49, )",
|
||||
"resolved": "1.0.1938.49",
|
||||
"contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
|
||||
},
|
||||
"Speckle.DoubleNumerics": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[4.1.0, )",
|
||||
"resolved": "4.1.0",
|
||||
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.15.3, )",
|
||||
"resolved": "3.15.3",
|
||||
"contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
|
||||
"requested": "[3.1.0-dev.107, )",
|
||||
"resolved": "3.1.0-dev.107",
|
||||
"contentHash": "MTXyE6Gs63wEW2kzLAtGCtZU+heohj87piVHSzanPg5qznqw0TXcvYBAg1IfeAg0ya5KMZ2IqT05GtW8bda1pQ==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.15.3"
|
||||
"Speckle.Sdk": "3.1.0-dev.107"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.1.0-dev.107, )",
|
||||
"resolved": "3.1.0-dev.107",
|
||||
"contentHash": "3qaL0N8fIcliOeDszBIYR9q1w/YG7OQod95F5l0Ju1R/RlB2WVaAC4CElPe6jHvZl96cDKOJ6K55827omL7QTQ==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.7",
|
||||
"Polly": "7.2.3",
|
||||
"Polly.Contrib.WaitAndRetry": "1.1.1",
|
||||
"Polly.Extensions.Http": "3.0.0",
|
||||
"Speckle.DoubleNumerics": "4.0.1",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Logging": "3.1.0-dev.107",
|
||||
"System.Text.Json": "5.0.2"
|
||||
}
|
||||
},
|
||||
"System.Threading.Tasks.Dataflow": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[6.0.0, )",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "+tyDCU3/B1lDdOOAJywHQoFwyXIUghIaP2BxG79uvhfTnO+D9qIgjVlL/JV2NTliYbMHpd6eKDmHp2VHpij7MA=="
|
||||
}
|
||||
},
|
||||
"net8.0-windows7.0/win-x64": {
|
||||
"Microsoft.Win32.SystemEvents": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "2nXPrhdAyAzir0gLl8Yy8S5Mnm/uBSQQA7jEsILOS1MTyS7DbmV1NgViMtvV1sfCD1ebITpNwb1NIinKeJgUVQ=="
|
||||
},
|
||||
"net6.0-windows7.0/win-x64": {
|
||||
"SQLitePCLRaw.lib.e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
|
||||
},
|
||||
"System.Drawing.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.0",
|
||||
"contentHash": "KIX+oBU38pxkKPxvLcLfIkOV5Ien8ReN78wro7OF5/erwcmortzeFx+iBswlh2Vz6gVne0khocQudGwaO1Ey6A==",
|
||||
"dependencies": {
|
||||
"Microsoft.Win32.SystemEvents": "7.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Web.WebView2": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[1.0.1938.49, )",
|
||||
@@ -1,57 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project>
|
||||
<Target AfterTargets="Clean" Name="CleanAddinAutocad" Condition="'$(AutoCADVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true' And '$(OS)' == 'Windows_NT'">
|
||||
<RemoveDir Directories="$(AppData)\Autodesk\ApplicationPlugins\Speckle.Connectors.Autocad.bundle\Contents\Windows\Speckle.Connectors.Autocad$(AutoCADVersion);" />
|
||||
</Target>
|
||||
|
||||
<Target AfterTargets="Build" Name="AfterBuildAutoCAD" Condition="'$(AutoCADVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true' And '$(OS)' == 'Windows_NT'">
|
||||
<ItemGroup>
|
||||
<AutoCADDLLs Include="$(TargetDir)\**\*.*" />
|
||||
</ItemGroup>
|
||||
<Message Text="AutoCAD Version $(AutoCADVersion)" Importance="high"/>
|
||||
<Copy DestinationFolder="$(AppData)\Autodesk\ApplicationPlugins\Speckle.Connectors.Autocad.bundle\Contents\Windows\Speckle.Connectors.Autocad$(AutoCADVersion)\%(RecursiveDir)" SourceFiles="@(AutoCADDLLs)" />
|
||||
<Copy DestinationFolder="$(AppData)\Autodesk\ApplicationPlugins\Speckle.Connectors.Autocad.bundle\" SourceFiles="$(TargetDir)\Plugin\BundleAutoCAD\PackageContents.xml" />
|
||||
</Target>
|
||||
|
||||
<Target AfterTargets="Clean" Name="CleanAddinCivil3D" Condition="'$(Civil3DVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true' And '$(OS)' == 'Windows_NT'">
|
||||
<RemoveDir Directories="$(AppData)\Autodesk\ApplicationPlugins\Speckle.Connectors.Civil3d.bundle\Contents\Windows\Speckle.Connectors.Civil3d$(Civil3DVersion);" />
|
||||
</Target>
|
||||
|
||||
<Target AfterTargets="Build" Name="AfterBuildCivil3D" Condition="'$(Civil3DVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true' And '$(OS)' == 'Windows_NT'">
|
||||
<ItemGroup>
|
||||
<Civil3DDLLs Include="$(TargetDir)\**\*.*" />
|
||||
</ItemGroup>
|
||||
<Message Text="Civil3D Version $(Civil3DVersion)" Importance="high"/>
|
||||
<Copy DestinationFolder="$(AppData)\Autodesk\ApplicationPlugins\Speckle.Connectors.Civil3d.bundle\Contents\Windows\Speckle.Connectors.Civil3d$(Civil3DVersion)\%(RecursiveDir)" SourceFiles="@(Civil3DDLLs)" />
|
||||
<Copy DestinationFolder="$(AppData)\Autodesk\ApplicationPlugins\Speckle.Connectors.Civil3d.bundle\" SourceFiles="$(TargetDir)\Plugin\BundleCivil3D\PackageContents.xml" />
|
||||
</Target>
|
||||
|
||||
<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' And '$(OS)' == 'Windows_NT'">
|
||||
<StartAction>Program</StartAction>
|
||||
<StartProgram>$(ProgramW6432)\Autodesk\AutoCAD $(Civil3DVersion)\acad.exe</StartProgram>
|
||||
<StartArguments>/product C3D</StartArguments>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target AfterTargets="Clean" Name="CleanAddinPlant3D" Condition="'$(Plant3DVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true' And '$(OS)' == 'Windows_NT'">
|
||||
<RemoveDir Directories="$(AppData)\Autodesk\ApplicationPlugins\Speckle.Connectors.Plant3d.bundle\Contents\Windows\Speckle.Connectors.Plant3d$(Plant3DVersion);" />
|
||||
</Target>
|
||||
|
||||
<Target AfterTargets="Build" Name="AfterBuildPlant3D" Condition="'$(Plant3DVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true' And '$(OS)' == 'Windows_NT'">
|
||||
<ItemGroup>
|
||||
<Plant3DDLLs Include="$(TargetDir)\**\*.*" />
|
||||
</ItemGroup>
|
||||
<Message Text="Plant3D Version $(Plant3DVersion)" Importance="high"/>
|
||||
<Copy DestinationFolder="$(AppData)\Autodesk\ApplicationPlugins\Speckle.Connectors.Plant3d.bundle\Contents\Windows\Speckle.Connectors.Plant3d$(Plant3DVersion)\%(RecursiveDir)" SourceFiles="@(Plant3DDLLs)" />
|
||||
<Copy DestinationFolder="$(AppData)\Autodesk\ApplicationPlugins\Speckle.Connectors.Plant3d.bundle\" SourceFiles="$(TargetDir)\Plugin\BundlePlant3D\PackageContents.xml" />
|
||||
</Target>
|
||||
|
||||
<PropertyGroup Condition="'$(Plant3DVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true' And '$(OS)' == 'Windows_NT'">
|
||||
<StartAction>Program</StartAction>
|
||||
<StartProgram>$(ProgramW6432)\Autodesk\AutoCAD $(Plant3DVersion)\acad.exe</StartProgram>
|
||||
<StartArguments>/product PLNT3D</StartArguments>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -2,21 +2,20 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net48</TargetFramework>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<UseWpf>true</UseWpf>
|
||||
<AutoCADVersion>2022</AutoCADVersion>
|
||||
<DefineConstants>$(DefineConstants);AUTOCAD;AUTOCAD2022;AUTOCAD2022_OR_GREATER</DefineConstants>
|
||||
<Configurations>Debug;Release;Local</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2022.0.2" ExcludeAssets="runtime" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Converters\Autocad\Speckle.Converters.Autocad2022\Speckle.Converters.Autocad2022.csproj" />
|
||||
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2022.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Converters\Autocad\Speckle.Converters.Autocad2022.DependencyInjection\Speckle.Converters.Autocad2022.DependencyInjection.csproj" />
|
||||
<ProjectReference Include="..\..\..\DUI3\Speckle.Connectors.DUI.WebView\Speckle.Connectors.DUI.WebView.csproj" />
|
||||
<ProjectReference Include="..\..\..\Sdk\Speckle.Converters.Common\Speckle.Converters.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<Import Project="..\Speckle.Connectors.AutocadShared\Speckle.Connectors.AutocadShared.projitems" Label="Shared" />
|
||||
</Project>
|
||||
|
||||
@@ -2,15 +2,6 @@
|
||||
"version": 2,
|
||||
"dependencies": {
|
||||
".NETFramework,Version=v4.8": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.0.3, )",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
|
||||
"dependencies": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net48": "1.0.3"
|
||||
}
|
||||
},
|
||||
"Microsoft.SourceLink.GitHub": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.0.0, )",
|
||||
@@ -73,8 +64,8 @@
|
||||
},
|
||||
"Microsoft.Bcl.AsyncInterfaces": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.4",
|
||||
"contentHash": "9VGI5kxIvrNG2mqLQZnUR6y/3fcnygD8eNpHR+CqfbnIXvea6nehnYknDKQTxZVPMpzpNca+7DxLBmpdB3q0Bw==",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ==",
|
||||
"dependencies": {
|
||||
"System.Threading.Tasks.Extensions": "4.5.4"
|
||||
}
|
||||
@@ -91,106 +82,115 @@
|
||||
},
|
||||
"Microsoft.Data.Sqlite": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.5",
|
||||
"contentHash": "KGxbPeWsQMnmQy43DSBxAFtHz3l2JX8EWBSGUCvT3CuZ8KsuzbkqMIJMDOxWtG8eZSoCDI04aiVQjWuuV8HmSw==",
|
||||
"resolved": "7.0.7",
|
||||
"contentHash": "tiNmV1oPy+Z2R7Wd0bPB/FxCr8B+/5q11OpDMG751GA/YuOL7MZrBFfzv5oFRlFe08K6sjrnbrauzzGIeNrzLQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Data.Sqlite.Core": "7.0.5",
|
||||
"Microsoft.Data.Sqlite.Core": "7.0.7",
|
||||
"SQLitePCLRaw.bundle_e_sqlite3": "2.1.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Data.Sqlite.Core": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.5",
|
||||
"contentHash": "FTerRmQPqHrCrnoUzhBu+E+1DNGwyrAMLqHkAqOOOu5pGfyMOj8qQUBxI/gDtWtG11p49UxSfWmBzRNlwZqfUg==",
|
||||
"resolved": "7.0.7",
|
||||
"contentHash": "21FRzcJhaTrlv7kTrqr/ltFcSQM2TyuTTPhUcjO8H73od7Bb3QraNW90c7lUucNI/245XPkKZG4fp7/7OsKCSg==",
|
||||
"dependencies": {
|
||||
"SQLitePCLRaw.core": "2.1.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "Lu41BWNmwhKr6LgyQvcYBOge0pPvmiaK8R5UHXX4//wBhonJyWcT2OK1mqYfEM5G7pTf31fPrpIHOT6sN7EGOA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "2.2.0"
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "ESz6bVoDQX7sgWdKHF6G9Pq672T8k+19AFb/txDXwdz7MoqaNQj2/in3agm/3qae9V+WvQZH86LLTNVo0it8vQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
"Microsoft.Extensions.Primitives": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Binder": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "vJ9xvOZCnUAIHcGC3SU35r3HKmHTVIeHzo6u/qzlHAqD8m6xv92MLin4oJntTvkpKxVX3vI1GFFkIQtU3AdlsQ==",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "o9eELDBfNkR7sUtYysFZ1Q7BQ1mYt27DMkups/3vu7xgPyOpMD+iAfrBZFzUXT2iw0fmFb8s1gfNBZS+IgjKdQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "2.2.0"
|
||||
"Microsoft.Extensions.Configuration": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "KVkv3aF2MQpmGFRh4xRx2CNbc2sjDFk+lH4ySrjWSOS+XoY1Xc+sJphw3N0iYOpoeCCq8976ceVYDH8sdx2qIQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "1.1.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "f9hstgjVmr6rmrfGSpfsVOl2irKAgr1QjrSi3FgnS7kulxband50f2brRLwySAQTADPZeTdow0mpSMcoAdadCw=="
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "44rDtOf1JXXAFpNT2EXMExaDm/4OJ2RXOL9i9lE4bK427nzC7Exphv+beB6IgluyE2GIoo8zezTStMXI7MQ8WA=="
|
||||
},
|
||||
"Microsoft.Extensions.Options": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "9b6JHY7TAXrSfZ6EEGf+j8XnqKIiMPErfmaNXhJYSCb+BUW2H4RtzkNJvwLJzwgzqBP0wtTjyA6Uw4BPPdmkMw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Primitives": "2.2.0",
|
||||
"System.ComponentModel.Annotations": "4.5.0"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0",
|
||||
"Microsoft.Extensions.Primitives": "3.1.0",
|
||||
"System.ComponentModel.Annotations": "4.7.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "LEKAnX7lhUhSoIc2XraCTK3M4IU/LdVUzCe464Sa4+7F4ZJuXHHRzZli2mDbiT4xzAZhgqXbvfnb5+CNDcQFfg==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.1",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.1"
|
||||
"System.Memory": "4.5.2",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.7.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net48": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "zMk4D+9zyiEWByyQ7oPImPN/Jhpj166Ky0Nlla4eXlNL8hI/BtSJsgR8Inldd4NNpIAH3oh8yym0W2DrhXdSLQ=="
|
||||
},
|
||||
"Microsoft.SourceLink.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
|
||||
},
|
||||
"Polly": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.2.3",
|
||||
"contentHash": "DeCY0OFbNdNxsjntr1gTXHJ5pKUwYzp04Er2LLeN3g6pWhffsGuKVfMBLe1lw7x76HrPkLxKEFxBlpRxS2nDEQ=="
|
||||
},
|
||||
"Polly.Contrib.WaitAndRetry": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.1.1",
|
||||
"contentHash": "1MUQLiSo4KDkQe6nzQRhIU05lm9jlexX5BVsbuw0SL82ynZ+GzAHQxJVDPVBboxV37Po3SG077aX8DuSy8TkaA=="
|
||||
},
|
||||
"Polly.Extensions.Http": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.0",
|
||||
"contentHash": "drrG+hB3pYFY7w1c3BD+lSGYvH2oIclH8GRSehgfyP5kjnFnHKQuuBhuHLv+PWyFuaTDyk/vfRpnxOzd11+J8g==",
|
||||
"dependencies": {
|
||||
"Polly": "7.1.0"
|
||||
}
|
||||
},
|
||||
"Speckle.DoubleNumerics": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.0.1",
|
||||
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
|
||||
},
|
||||
"Speckle.Newtonsoft.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "13.0.2",
|
||||
"contentHash": "g1BejUZwax5PRfL6xHgLEK23sqHWOgOj9hE7RvfRRlN00AGt8GnPYt8HedSK7UB3HiRW8zCA9Pn0iiYxCK24BA=="
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"Speckle.Sdk.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.15.3",
|
||||
"contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.5",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.15.3"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.15.3",
|
||||
"contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
|
||||
}
|
||||
"resolved": "3.1.0-dev.107",
|
||||
"contentHash": "phWGEyqiZlB5LichJtVA45xFFvxRxlU8rBTEag3llZeNIlSXRW0wzWmAq8gdQftHJyw59iupZwH2Tx+jglzp8w=="
|
||||
},
|
||||
"SQLitePCLRaw.bundle_e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
@@ -224,22 +224,22 @@
|
||||
},
|
||||
"System.Buffers": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "AwarXzzoDwX6BgrhjoJsk6tUezZEozOT5Y9QKF94Gl4JK91I4PIIBkBco9068Y9/Dra8Dkbie99kXB8+1BaYKw=="
|
||||
"resolved": "4.5.1",
|
||||
"contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
|
||||
},
|
||||
"System.ComponentModel.Annotations": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
|
||||
"resolved": "4.7.0",
|
||||
"contentHash": "0YFqjhp/mYkDGpU0Ye1GjE53HMp9UVfGN7seGpAMttAC0C40v5gw598jCgpbBLMmCo0E5YRLBv5Z2doypO49ZQ=="
|
||||
},
|
||||
"System.Memory": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.3",
|
||||
"contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA==",
|
||||
"resolved": "4.5.4",
|
||||
"contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==",
|
||||
"dependencies": {
|
||||
"System.Buffers": "4.4.0",
|
||||
"System.Numerics.Vectors": "4.4.0",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.2"
|
||||
"System.Buffers": "4.5.1",
|
||||
"System.Numerics.Vectors": "4.5.0",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
|
||||
}
|
||||
},
|
||||
"System.Net.WebSockets.Client.Managed": {
|
||||
@@ -253,8 +253,8 @@
|
||||
},
|
||||
"System.Numerics.Vectors": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ=="
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ=="
|
||||
},
|
||||
"System.Reactive": {
|
||||
"type": "Transitive",
|
||||
@@ -266,8 +266,32 @@
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.3",
|
||||
"contentHash": "3TIsJhD1EiiT0w2CcDMN/iSSwnNnsrnbzeVHSKkaEgV85txMprmuO+Yq2AdSbeVGcg28pdNDTPK87tJhX7VFHw=="
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "ZD9TMpsmYJLrxbbmdvhwt9YEgG5WntEnZ/d1eH8JBX9LBp+Ju8BSBhUGbZMNVHHomWo2KVImJhTDl2hIgw/6MA=="
|
||||
},
|
||||
"System.Text.Encodings.Web": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.1",
|
||||
"contentHash": "KmJ+CJXizDofbq6mpqDoRRLcxgOd2z9X3XoFNULSbvbqVRZkFX3istvr+MUjL6Zw1RT+RNdoI4GYidIINtgvqQ==",
|
||||
"dependencies": {
|
||||
"System.Buffers": "4.5.1",
|
||||
"System.Memory": "4.5.4"
|
||||
}
|
||||
},
|
||||
"System.Text.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.2",
|
||||
"contentHash": "I47dVIGiV6SfAyppphxqupertT/5oZkYLDCX6vC3HpOI4ZLjyoKAreUoem2ie6G0RbRuFrlqz/PcTQjfb2DOfQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
"System.Buffers": "4.5.1",
|
||||
"System.Memory": "4.5.4",
|
||||
"System.Numerics.Vectors": "4.5.0",
|
||||
"System.Runtime.CompilerServices.Unsafe": "5.0.0",
|
||||
"System.Text.Encodings.Web": "5.0.1",
|
||||
"System.Threading.Tasks.Extensions": "4.5.4",
|
||||
"System.ValueTuple": "4.5.0"
|
||||
}
|
||||
},
|
||||
"System.Threading.Tasks.Extensions": {
|
||||
"type": "Transitive",
|
||||
@@ -277,20 +301,25 @@
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.common": {
|
||||
"System.ValueTuple": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ=="
|
||||
},
|
||||
"speckle.autofac": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Converters.Common": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.15.3, )"
|
||||
"Autofac": "[5.2.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Connectors.Common": "[1.0.0, )"
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[3.1.0, )",
|
||||
"Speckle.Autofac": "[1.0.0, )",
|
||||
"Speckle.Connectors.Utils": "[1.0.0, )",
|
||||
"Speckle.Sdk": "[3.1.0-dev.107, )",
|
||||
"System.Threading.Tasks.Dataflow": "[6.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui.webview": {
|
||||
@@ -300,8 +329,14 @@
|
||||
"Speckle.Connectors.DUI": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.logging": {
|
||||
"type": "Project"
|
||||
"speckle.connectors.utils": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging": "[3.1.0, )",
|
||||
"Speckle.Autofac": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.1.0-dev.107, )",
|
||||
"Speckle.Sdk": "[3.1.0-dev.107, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.autocad2022": {
|
||||
"type": "Project",
|
||||
@@ -310,39 +345,55 @@
|
||||
"Speckle.Converters.Common": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.autocad2022.dependencyinjection": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Autofac": "[5.2.0, )",
|
||||
"Speckle.Converters.Autocad2022": "[1.0.0, )",
|
||||
"Speckle.Converters.Common.DependencyInjection": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.15.3, )"
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[3.1.0, )",
|
||||
"Speckle.Autofac": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.1.0-dev.107, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==",
|
||||
"speckle.converters.common.dependencyinjection": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0"
|
||||
"Speckle.Autofac": "[1.0.0, )",
|
||||
"Speckle.Converters.Common": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"Autofac": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[5.2.0, )",
|
||||
"resolved": "5.2.0",
|
||||
"contentHash": "V8dBH0dsv75uDzl7Sw+HkhKDPUw2eXnlMjcSVMH+tLo2s67MpTKGyDj1pDcpR+IF2u4YRs0s3/x7R88YJzIWvg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "1.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==",
|
||||
"requested": "[3.1.0, )",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "P+8sKQ8L4ooL79sxxqwFPxGGC3aBrUDLB/dZqhs4J0XjTyrkeeyJQ4D4nzJB6OnAhy78HIIgQ/RbD6upOXLynw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Binder": "2.2.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Options": "2.2.0"
|
||||
"Microsoft.Extensions.Configuration.Binder": "3.1.0",
|
||||
"Microsoft.Extensions.DependencyInjection": "3.1.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "3.1.0",
|
||||
"Microsoft.Extensions.Options": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
|
||||
"requested": "[3.1.0, )",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "jjo4YXRx6MIpv6DiRxJjSpl+sPP0+5VW0clMEdLyIAz44PPwrDTFrd5PZckIxIXl1kKZ2KK6IL2nkt0+ug2MQg=="
|
||||
},
|
||||
"Microsoft.Web.WebView2": {
|
||||
"type": "CentralTransitive",
|
||||
@@ -350,20 +401,38 @@
|
||||
"resolved": "1.0.1938.49",
|
||||
"contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
|
||||
},
|
||||
"Speckle.DoubleNumerics": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[4.1.0, )",
|
||||
"resolved": "4.1.0",
|
||||
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.15.3, )",
|
||||
"resolved": "3.15.3",
|
||||
"contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
|
||||
"requested": "[3.1.0-dev.107, )",
|
||||
"resolved": "3.1.0-dev.107",
|
||||
"contentHash": "MTXyE6Gs63wEW2kzLAtGCtZU+heohj87piVHSzanPg5qznqw0TXcvYBAg1IfeAg0ya5KMZ2IqT05GtW8bda1pQ==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.15.3"
|
||||
"Speckle.Sdk": "3.1.0-dev.107"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.1.0-dev.107, )",
|
||||
"resolved": "3.1.0-dev.107",
|
||||
"contentHash": "3qaL0N8fIcliOeDszBIYR9q1w/YG7OQod95F5l0Ju1R/RlB2WVaAC4CElPe6jHvZl96cDKOJ6K55827omL7QTQ==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.7",
|
||||
"Polly": "7.2.3",
|
||||
"Polly.Contrib.WaitAndRetry": "1.1.1",
|
||||
"Polly.Extensions.Http": "3.0.0",
|
||||
"Speckle.DoubleNumerics": "4.0.1",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Logging": "3.1.0-dev.107",
|
||||
"System.Text.Json": "5.0.2"
|
||||
}
|
||||
},
|
||||
"System.Threading.Tasks.Dataflow": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[6.0.0, )",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "+tyDCU3/B1lDdOOAJywHQoFwyXIUghIaP2BxG79uvhfTnO+D9qIgjVlL/JV2NTliYbMHpd6eKDmHp2VHpij7MA=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,21 +2,20 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net48</TargetFramework>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<UseWpf>true</UseWpf>
|
||||
<AutoCADVersion>2023</AutoCADVersion>
|
||||
<DefineConstants>$(DefineConstants);AUTOCAD;AUTOCAD2023;AUTOCAD2022_OR_GREATER;AUTOCAD2023_OR_GREATER</DefineConstants>
|
||||
<Configurations>Debug;Release;Local</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2023.0.0" ExcludeAssets="runtime" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Converters\Autocad\Speckle.Converters.Autocad2023\Speckle.Converters.Autocad2023.csproj" />
|
||||
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2023.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Converters\Autocad\Speckle.Converters.Autocad2023.DependencyInjection\Speckle.Converters.Autocad2023.DependencyInjection.csproj" />
|
||||
<ProjectReference Include="..\..\..\DUI3\Speckle.Connectors.DUI.WebView\Speckle.Connectors.DUI.WebView.csproj" />
|
||||
<ProjectReference Include="..\..\..\Sdk\Speckle.Converters.Common\Speckle.Converters.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<Import Project="..\Speckle.Connectors.AutocadShared\Speckle.Connectors.AutocadShared.projitems" Label="Shared" />
|
||||
</Project>
|
||||
|
||||
@@ -2,15 +2,6 @@
|
||||
"version": 2,
|
||||
"dependencies": {
|
||||
".NETFramework,Version=v4.8": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.0.3, )",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
|
||||
"dependencies": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net48": "1.0.3"
|
||||
}
|
||||
},
|
||||
"Microsoft.SourceLink.GitHub": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.0.0, )",
|
||||
@@ -73,8 +64,8 @@
|
||||
},
|
||||
"Microsoft.Bcl.AsyncInterfaces": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.4",
|
||||
"contentHash": "9VGI5kxIvrNG2mqLQZnUR6y/3fcnygD8eNpHR+CqfbnIXvea6nehnYknDKQTxZVPMpzpNca+7DxLBmpdB3q0Bw==",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ==",
|
||||
"dependencies": {
|
||||
"System.Threading.Tasks.Extensions": "4.5.4"
|
||||
}
|
||||
@@ -91,106 +82,115 @@
|
||||
},
|
||||
"Microsoft.Data.Sqlite": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.5",
|
||||
"contentHash": "KGxbPeWsQMnmQy43DSBxAFtHz3l2JX8EWBSGUCvT3CuZ8KsuzbkqMIJMDOxWtG8eZSoCDI04aiVQjWuuV8HmSw==",
|
||||
"resolved": "7.0.7",
|
||||
"contentHash": "tiNmV1oPy+Z2R7Wd0bPB/FxCr8B+/5q11OpDMG751GA/YuOL7MZrBFfzv5oFRlFe08K6sjrnbrauzzGIeNrzLQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Data.Sqlite.Core": "7.0.5",
|
||||
"Microsoft.Data.Sqlite.Core": "7.0.7",
|
||||
"SQLitePCLRaw.bundle_e_sqlite3": "2.1.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Data.Sqlite.Core": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.5",
|
||||
"contentHash": "FTerRmQPqHrCrnoUzhBu+E+1DNGwyrAMLqHkAqOOOu5pGfyMOj8qQUBxI/gDtWtG11p49UxSfWmBzRNlwZqfUg==",
|
||||
"resolved": "7.0.7",
|
||||
"contentHash": "21FRzcJhaTrlv7kTrqr/ltFcSQM2TyuTTPhUcjO8H73od7Bb3QraNW90c7lUucNI/245XPkKZG4fp7/7OsKCSg==",
|
||||
"dependencies": {
|
||||
"SQLitePCLRaw.core": "2.1.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "Lu41BWNmwhKr6LgyQvcYBOge0pPvmiaK8R5UHXX4//wBhonJyWcT2OK1mqYfEM5G7pTf31fPrpIHOT6sN7EGOA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "2.2.0"
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "ESz6bVoDQX7sgWdKHF6G9Pq672T8k+19AFb/txDXwdz7MoqaNQj2/in3agm/3qae9V+WvQZH86LLTNVo0it8vQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
"Microsoft.Extensions.Primitives": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Binder": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "vJ9xvOZCnUAIHcGC3SU35r3HKmHTVIeHzo6u/qzlHAqD8m6xv92MLin4oJntTvkpKxVX3vI1GFFkIQtU3AdlsQ==",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "o9eELDBfNkR7sUtYysFZ1Q7BQ1mYt27DMkups/3vu7xgPyOpMD+iAfrBZFzUXT2iw0fmFb8s1gfNBZS+IgjKdQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "2.2.0"
|
||||
"Microsoft.Extensions.Configuration": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "KVkv3aF2MQpmGFRh4xRx2CNbc2sjDFk+lH4ySrjWSOS+XoY1Xc+sJphw3N0iYOpoeCCq8976ceVYDH8sdx2qIQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "1.1.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "f9hstgjVmr6rmrfGSpfsVOl2irKAgr1QjrSi3FgnS7kulxband50f2brRLwySAQTADPZeTdow0mpSMcoAdadCw=="
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "44rDtOf1JXXAFpNT2EXMExaDm/4OJ2RXOL9i9lE4bK427nzC7Exphv+beB6IgluyE2GIoo8zezTStMXI7MQ8WA=="
|
||||
},
|
||||
"Microsoft.Extensions.Options": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "9b6JHY7TAXrSfZ6EEGf+j8XnqKIiMPErfmaNXhJYSCb+BUW2H4RtzkNJvwLJzwgzqBP0wtTjyA6Uw4BPPdmkMw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Primitives": "2.2.0",
|
||||
"System.ComponentModel.Annotations": "4.5.0"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0",
|
||||
"Microsoft.Extensions.Primitives": "3.1.0",
|
||||
"System.ComponentModel.Annotations": "4.7.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "LEKAnX7lhUhSoIc2XraCTK3M4IU/LdVUzCe464Sa4+7F4ZJuXHHRzZli2mDbiT4xzAZhgqXbvfnb5+CNDcQFfg==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.1",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.1"
|
||||
"System.Memory": "4.5.2",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.7.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net48": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "zMk4D+9zyiEWByyQ7oPImPN/Jhpj166Ky0Nlla4eXlNL8hI/BtSJsgR8Inldd4NNpIAH3oh8yym0W2DrhXdSLQ=="
|
||||
},
|
||||
"Microsoft.SourceLink.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
|
||||
},
|
||||
"Polly": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.2.3",
|
||||
"contentHash": "DeCY0OFbNdNxsjntr1gTXHJ5pKUwYzp04Er2LLeN3g6pWhffsGuKVfMBLe1lw7x76HrPkLxKEFxBlpRxS2nDEQ=="
|
||||
},
|
||||
"Polly.Contrib.WaitAndRetry": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.1.1",
|
||||
"contentHash": "1MUQLiSo4KDkQe6nzQRhIU05lm9jlexX5BVsbuw0SL82ynZ+GzAHQxJVDPVBboxV37Po3SG077aX8DuSy8TkaA=="
|
||||
},
|
||||
"Polly.Extensions.Http": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.0",
|
||||
"contentHash": "drrG+hB3pYFY7w1c3BD+lSGYvH2oIclH8GRSehgfyP5kjnFnHKQuuBhuHLv+PWyFuaTDyk/vfRpnxOzd11+J8g==",
|
||||
"dependencies": {
|
||||
"Polly": "7.1.0"
|
||||
}
|
||||
},
|
||||
"Speckle.DoubleNumerics": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.0.1",
|
||||
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
|
||||
},
|
||||
"Speckle.Newtonsoft.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "13.0.2",
|
||||
"contentHash": "g1BejUZwax5PRfL6xHgLEK23sqHWOgOj9hE7RvfRRlN00AGt8GnPYt8HedSK7UB3HiRW8zCA9Pn0iiYxCK24BA=="
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"Speckle.Sdk.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.15.3",
|
||||
"contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.5",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.15.3"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.15.3",
|
||||
"contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
|
||||
}
|
||||
"resolved": "3.1.0-dev.107",
|
||||
"contentHash": "phWGEyqiZlB5LichJtVA45xFFvxRxlU8rBTEag3llZeNIlSXRW0wzWmAq8gdQftHJyw59iupZwH2Tx+jglzp8w=="
|
||||
},
|
||||
"SQLitePCLRaw.bundle_e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
@@ -224,22 +224,22 @@
|
||||
},
|
||||
"System.Buffers": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "AwarXzzoDwX6BgrhjoJsk6tUezZEozOT5Y9QKF94Gl4JK91I4PIIBkBco9068Y9/Dra8Dkbie99kXB8+1BaYKw=="
|
||||
"resolved": "4.5.1",
|
||||
"contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
|
||||
},
|
||||
"System.ComponentModel.Annotations": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
|
||||
"resolved": "4.7.0",
|
||||
"contentHash": "0YFqjhp/mYkDGpU0Ye1GjE53HMp9UVfGN7seGpAMttAC0C40v5gw598jCgpbBLMmCo0E5YRLBv5Z2doypO49ZQ=="
|
||||
},
|
||||
"System.Memory": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.3",
|
||||
"contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA==",
|
||||
"resolved": "4.5.4",
|
||||
"contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==",
|
||||
"dependencies": {
|
||||
"System.Buffers": "4.4.0",
|
||||
"System.Numerics.Vectors": "4.4.0",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.2"
|
||||
"System.Buffers": "4.5.1",
|
||||
"System.Numerics.Vectors": "4.5.0",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
|
||||
}
|
||||
},
|
||||
"System.Net.WebSockets.Client.Managed": {
|
||||
@@ -253,8 +253,8 @@
|
||||
},
|
||||
"System.Numerics.Vectors": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ=="
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ=="
|
||||
},
|
||||
"System.Reactive": {
|
||||
"type": "Transitive",
|
||||
@@ -266,8 +266,32 @@
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.3",
|
||||
"contentHash": "3TIsJhD1EiiT0w2CcDMN/iSSwnNnsrnbzeVHSKkaEgV85txMprmuO+Yq2AdSbeVGcg28pdNDTPK87tJhX7VFHw=="
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "ZD9TMpsmYJLrxbbmdvhwt9YEgG5WntEnZ/d1eH8JBX9LBp+Ju8BSBhUGbZMNVHHomWo2KVImJhTDl2hIgw/6MA=="
|
||||
},
|
||||
"System.Text.Encodings.Web": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.1",
|
||||
"contentHash": "KmJ+CJXizDofbq6mpqDoRRLcxgOd2z9X3XoFNULSbvbqVRZkFX3istvr+MUjL6Zw1RT+RNdoI4GYidIINtgvqQ==",
|
||||
"dependencies": {
|
||||
"System.Buffers": "4.5.1",
|
||||
"System.Memory": "4.5.4"
|
||||
}
|
||||
},
|
||||
"System.Text.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.2",
|
||||
"contentHash": "I47dVIGiV6SfAyppphxqupertT/5oZkYLDCX6vC3HpOI4ZLjyoKAreUoem2ie6G0RbRuFrlqz/PcTQjfb2DOfQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
"System.Buffers": "4.5.1",
|
||||
"System.Memory": "4.5.4",
|
||||
"System.Numerics.Vectors": "4.5.0",
|
||||
"System.Runtime.CompilerServices.Unsafe": "5.0.0",
|
||||
"System.Text.Encodings.Web": "5.0.1",
|
||||
"System.Threading.Tasks.Extensions": "4.5.4",
|
||||
"System.ValueTuple": "4.5.0"
|
||||
}
|
||||
},
|
||||
"System.Threading.Tasks.Extensions": {
|
||||
"type": "Transitive",
|
||||
@@ -277,20 +301,25 @@
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.common": {
|
||||
"System.ValueTuple": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ=="
|
||||
},
|
||||
"speckle.autofac": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Converters.Common": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.15.3, )"
|
||||
"Autofac": "[5.2.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Connectors.Common": "[1.0.0, )"
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[3.1.0, )",
|
||||
"Speckle.Autofac": "[1.0.0, )",
|
||||
"Speckle.Connectors.Utils": "[1.0.0, )",
|
||||
"Speckle.Sdk": "[3.1.0-dev.107, )",
|
||||
"System.Threading.Tasks.Dataflow": "[6.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui.webview": {
|
||||
@@ -300,8 +329,14 @@
|
||||
"Speckle.Connectors.DUI": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.logging": {
|
||||
"type": "Project"
|
||||
"speckle.connectors.utils": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging": "[3.1.0, )",
|
||||
"Speckle.Autofac": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.1.0-dev.107, )",
|
||||
"Speckle.Sdk": "[3.1.0-dev.107, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.autocad2023": {
|
||||
"type": "Project",
|
||||
@@ -310,39 +345,55 @@
|
||||
"Speckle.Converters.Common": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.autocad2023.dependencyinjection": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Autofac": "[5.2.0, )",
|
||||
"Speckle.Converters.Autocad2023": "[1.0.0, )",
|
||||
"Speckle.Converters.Common.DependencyInjection": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.15.3, )"
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[3.1.0, )",
|
||||
"Speckle.Autofac": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.1.0-dev.107, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==",
|
||||
"speckle.converters.common.dependencyinjection": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0"
|
||||
"Speckle.Autofac": "[1.0.0, )",
|
||||
"Speckle.Converters.Common": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"Autofac": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[5.2.0, )",
|
||||
"resolved": "5.2.0",
|
||||
"contentHash": "V8dBH0dsv75uDzl7Sw+HkhKDPUw2eXnlMjcSVMH+tLo2s67MpTKGyDj1pDcpR+IF2u4YRs0s3/x7R88YJzIWvg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "1.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==",
|
||||
"requested": "[3.1.0, )",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "P+8sKQ8L4ooL79sxxqwFPxGGC3aBrUDLB/dZqhs4J0XjTyrkeeyJQ4D4nzJB6OnAhy78HIIgQ/RbD6upOXLynw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Binder": "2.2.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Options": "2.2.0"
|
||||
"Microsoft.Extensions.Configuration.Binder": "3.1.0",
|
||||
"Microsoft.Extensions.DependencyInjection": "3.1.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "3.1.0",
|
||||
"Microsoft.Extensions.Options": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
|
||||
"requested": "[3.1.0, )",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "jjo4YXRx6MIpv6DiRxJjSpl+sPP0+5VW0clMEdLyIAz44PPwrDTFrd5PZckIxIXl1kKZ2KK6IL2nkt0+ug2MQg=="
|
||||
},
|
||||
"Microsoft.Web.WebView2": {
|
||||
"type": "CentralTransitive",
|
||||
@@ -350,20 +401,38 @@
|
||||
"resolved": "1.0.1938.49",
|
||||
"contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
|
||||
},
|
||||
"Speckle.DoubleNumerics": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[4.1.0, )",
|
||||
"resolved": "4.1.0",
|
||||
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.15.3, )",
|
||||
"resolved": "3.15.3",
|
||||
"contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
|
||||
"requested": "[3.1.0-dev.107, )",
|
||||
"resolved": "3.1.0-dev.107",
|
||||
"contentHash": "MTXyE6Gs63wEW2kzLAtGCtZU+heohj87piVHSzanPg5qznqw0TXcvYBAg1IfeAg0ya5KMZ2IqT05GtW8bda1pQ==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.15.3"
|
||||
"Speckle.Sdk": "3.1.0-dev.107"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.1.0-dev.107, )",
|
||||
"resolved": "3.1.0-dev.107",
|
||||
"contentHash": "3qaL0N8fIcliOeDszBIYR9q1w/YG7OQod95F5l0Ju1R/RlB2WVaAC4CElPe6jHvZl96cDKOJ6K55827omL7QTQ==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.7",
|
||||
"Polly": "7.2.3",
|
||||
"Polly.Contrib.WaitAndRetry": "1.1.1",
|
||||
"Polly.Extensions.Http": "3.0.0",
|
||||
"Speckle.DoubleNumerics": "4.0.1",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Logging": "3.1.0-dev.107",
|
||||
"System.Text.Json": "5.0.2"
|
||||
}
|
||||
},
|
||||
"System.Threading.Tasks.Dataflow": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[6.0.0, )",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "+tyDCU3/B1lDdOOAJywHQoFwyXIUghIaP2BxG79uvhfTnO+D9qIgjVlL/JV2NTliYbMHpd6eKDmHp2VHpij7MA=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net48</TargetFramework>
|
||||
<AutoCADVersion>2024</AutoCADVersion>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<UseWpf>true</UseWpf>
|
||||
<AutoCADVersion>2024</AutoCADVersion>
|
||||
<DefineConstants>$(DefineConstants);AUTOCAD;AUTOCAD2024;AUTOCAD2022_OR_GREATER;AUTOCAD2023_OR_GREATER;AUTOCAD2024_OR_GREATER</DefineConstants>
|
||||
<Configurations>Debug;Release;Local</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2024.0.0" ExcludeAssets="runtime" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Converters\Autocad\Speckle.Converters.Autocad2024\Speckle.Converters.Autocad2024.csproj" />
|
||||
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2024.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Converters\Autocad\Speckle.Converters.Autocad2024.DependencyInjection\Speckle.Converters.Autocad2024.DependencyInjection.csproj" />
|
||||
<ProjectReference Include="..\..\..\DUI3\Speckle.Connectors.DUI.WebView\Speckle.Connectors.DUI.WebView.csproj" />
|
||||
<ProjectReference Include="..\..\..\Sdk\Speckle.Converters.Common\Speckle.Converters.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<Import Project="..\Speckle.Connectors.AutocadShared\Speckle.Connectors.AutocadShared.projitems" Label="Shared" />
|
||||
</Project>
|
||||
|
||||
@@ -2,15 +2,6 @@
|
||||
"version": 2,
|
||||
"dependencies": {
|
||||
".NETFramework,Version=v4.8": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.0.3, )",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
|
||||
"dependencies": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net48": "1.0.3"
|
||||
}
|
||||
},
|
||||
"Microsoft.SourceLink.GitHub": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.0.0, )",
|
||||
@@ -73,8 +64,8 @@
|
||||
},
|
||||
"Microsoft.Bcl.AsyncInterfaces": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.4",
|
||||
"contentHash": "9VGI5kxIvrNG2mqLQZnUR6y/3fcnygD8eNpHR+CqfbnIXvea6nehnYknDKQTxZVPMpzpNca+7DxLBmpdB3q0Bw==",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ==",
|
||||
"dependencies": {
|
||||
"System.Threading.Tasks.Extensions": "4.5.4"
|
||||
}
|
||||
@@ -91,106 +82,115 @@
|
||||
},
|
||||
"Microsoft.Data.Sqlite": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.5",
|
||||
"contentHash": "KGxbPeWsQMnmQy43DSBxAFtHz3l2JX8EWBSGUCvT3CuZ8KsuzbkqMIJMDOxWtG8eZSoCDI04aiVQjWuuV8HmSw==",
|
||||
"resolved": "7.0.7",
|
||||
"contentHash": "tiNmV1oPy+Z2R7Wd0bPB/FxCr8B+/5q11OpDMG751GA/YuOL7MZrBFfzv5oFRlFe08K6sjrnbrauzzGIeNrzLQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Data.Sqlite.Core": "7.0.5",
|
||||
"Microsoft.Data.Sqlite.Core": "7.0.7",
|
||||
"SQLitePCLRaw.bundle_e_sqlite3": "2.1.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Data.Sqlite.Core": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.5",
|
||||
"contentHash": "FTerRmQPqHrCrnoUzhBu+E+1DNGwyrAMLqHkAqOOOu5pGfyMOj8qQUBxI/gDtWtG11p49UxSfWmBzRNlwZqfUg==",
|
||||
"resolved": "7.0.7",
|
||||
"contentHash": "21FRzcJhaTrlv7kTrqr/ltFcSQM2TyuTTPhUcjO8H73od7Bb3QraNW90c7lUucNI/245XPkKZG4fp7/7OsKCSg==",
|
||||
"dependencies": {
|
||||
"SQLitePCLRaw.core": "2.1.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "Lu41BWNmwhKr6LgyQvcYBOge0pPvmiaK8R5UHXX4//wBhonJyWcT2OK1mqYfEM5G7pTf31fPrpIHOT6sN7EGOA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "2.2.0"
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "ESz6bVoDQX7sgWdKHF6G9Pq672T8k+19AFb/txDXwdz7MoqaNQj2/in3agm/3qae9V+WvQZH86LLTNVo0it8vQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
"Microsoft.Extensions.Primitives": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Binder": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "vJ9xvOZCnUAIHcGC3SU35r3HKmHTVIeHzo6u/qzlHAqD8m6xv92MLin4oJntTvkpKxVX3vI1GFFkIQtU3AdlsQ==",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "o9eELDBfNkR7sUtYysFZ1Q7BQ1mYt27DMkups/3vu7xgPyOpMD+iAfrBZFzUXT2iw0fmFb8s1gfNBZS+IgjKdQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "2.2.0"
|
||||
"Microsoft.Extensions.Configuration": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "KVkv3aF2MQpmGFRh4xRx2CNbc2sjDFk+lH4ySrjWSOS+XoY1Xc+sJphw3N0iYOpoeCCq8976ceVYDH8sdx2qIQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "1.1.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "f9hstgjVmr6rmrfGSpfsVOl2irKAgr1QjrSi3FgnS7kulxband50f2brRLwySAQTADPZeTdow0mpSMcoAdadCw=="
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "44rDtOf1JXXAFpNT2EXMExaDm/4OJ2RXOL9i9lE4bK427nzC7Exphv+beB6IgluyE2GIoo8zezTStMXI7MQ8WA=="
|
||||
},
|
||||
"Microsoft.Extensions.Options": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "9b6JHY7TAXrSfZ6EEGf+j8XnqKIiMPErfmaNXhJYSCb+BUW2H4RtzkNJvwLJzwgzqBP0wtTjyA6Uw4BPPdmkMw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Primitives": "2.2.0",
|
||||
"System.ComponentModel.Annotations": "4.5.0"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0",
|
||||
"Microsoft.Extensions.Primitives": "3.1.0",
|
||||
"System.ComponentModel.Annotations": "4.7.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "LEKAnX7lhUhSoIc2XraCTK3M4IU/LdVUzCe464Sa4+7F4ZJuXHHRzZli2mDbiT4xzAZhgqXbvfnb5+CNDcQFfg==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.1",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.1"
|
||||
"System.Memory": "4.5.2",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.7.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net48": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "zMk4D+9zyiEWByyQ7oPImPN/Jhpj166Ky0Nlla4eXlNL8hI/BtSJsgR8Inldd4NNpIAH3oh8yym0W2DrhXdSLQ=="
|
||||
},
|
||||
"Microsoft.SourceLink.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
|
||||
},
|
||||
"Polly": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.2.3",
|
||||
"contentHash": "DeCY0OFbNdNxsjntr1gTXHJ5pKUwYzp04Er2LLeN3g6pWhffsGuKVfMBLe1lw7x76HrPkLxKEFxBlpRxS2nDEQ=="
|
||||
},
|
||||
"Polly.Contrib.WaitAndRetry": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.1.1",
|
||||
"contentHash": "1MUQLiSo4KDkQe6nzQRhIU05lm9jlexX5BVsbuw0SL82ynZ+GzAHQxJVDPVBboxV37Po3SG077aX8DuSy8TkaA=="
|
||||
},
|
||||
"Polly.Extensions.Http": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.0",
|
||||
"contentHash": "drrG+hB3pYFY7w1c3BD+lSGYvH2oIclH8GRSehgfyP5kjnFnHKQuuBhuHLv+PWyFuaTDyk/vfRpnxOzd11+J8g==",
|
||||
"dependencies": {
|
||||
"Polly": "7.1.0"
|
||||
}
|
||||
},
|
||||
"Speckle.DoubleNumerics": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.0.1",
|
||||
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
|
||||
},
|
||||
"Speckle.Newtonsoft.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "13.0.2",
|
||||
"contentHash": "g1BejUZwax5PRfL6xHgLEK23sqHWOgOj9hE7RvfRRlN00AGt8GnPYt8HedSK7UB3HiRW8zCA9Pn0iiYxCK24BA=="
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"Speckle.Sdk.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.15.3",
|
||||
"contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.5",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.15.3"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.15.3",
|
||||
"contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "9.0.4"
|
||||
}
|
||||
"resolved": "3.1.0-dev.107",
|
||||
"contentHash": "phWGEyqiZlB5LichJtVA45xFFvxRxlU8rBTEag3llZeNIlSXRW0wzWmAq8gdQftHJyw59iupZwH2Tx+jglzp8w=="
|
||||
},
|
||||
"SQLitePCLRaw.bundle_e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
@@ -224,22 +224,22 @@
|
||||
},
|
||||
"System.Buffers": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "AwarXzzoDwX6BgrhjoJsk6tUezZEozOT5Y9QKF94Gl4JK91I4PIIBkBco9068Y9/Dra8Dkbie99kXB8+1BaYKw=="
|
||||
"resolved": "4.5.1",
|
||||
"contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
|
||||
},
|
||||
"System.ComponentModel.Annotations": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
|
||||
"resolved": "4.7.0",
|
||||
"contentHash": "0YFqjhp/mYkDGpU0Ye1GjE53HMp9UVfGN7seGpAMttAC0C40v5gw598jCgpbBLMmCo0E5YRLBv5Z2doypO49ZQ=="
|
||||
},
|
||||
"System.Memory": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.3",
|
||||
"contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA==",
|
||||
"resolved": "4.5.4",
|
||||
"contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==",
|
||||
"dependencies": {
|
||||
"System.Buffers": "4.4.0",
|
||||
"System.Numerics.Vectors": "4.4.0",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.2"
|
||||
"System.Buffers": "4.5.1",
|
||||
"System.Numerics.Vectors": "4.5.0",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
|
||||
}
|
||||
},
|
||||
"System.Net.WebSockets.Client.Managed": {
|
||||
@@ -253,8 +253,8 @@
|
||||
},
|
||||
"System.Numerics.Vectors": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.4.0",
|
||||
"contentHash": "UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ=="
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ=="
|
||||
},
|
||||
"System.Reactive": {
|
||||
"type": "Transitive",
|
||||
@@ -266,8 +266,32 @@
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.3",
|
||||
"contentHash": "3TIsJhD1EiiT0w2CcDMN/iSSwnNnsrnbzeVHSKkaEgV85txMprmuO+Yq2AdSbeVGcg28pdNDTPK87tJhX7VFHw=="
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "ZD9TMpsmYJLrxbbmdvhwt9YEgG5WntEnZ/d1eH8JBX9LBp+Ju8BSBhUGbZMNVHHomWo2KVImJhTDl2hIgw/6MA=="
|
||||
},
|
||||
"System.Text.Encodings.Web": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.1",
|
||||
"contentHash": "KmJ+CJXizDofbq6mpqDoRRLcxgOd2z9X3XoFNULSbvbqVRZkFX3istvr+MUjL6Zw1RT+RNdoI4GYidIINtgvqQ==",
|
||||
"dependencies": {
|
||||
"System.Buffers": "4.5.1",
|
||||
"System.Memory": "4.5.4"
|
||||
}
|
||||
},
|
||||
"System.Text.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.2",
|
||||
"contentHash": "I47dVIGiV6SfAyppphxqupertT/5oZkYLDCX6vC3HpOI4ZLjyoKAreUoem2ie6G0RbRuFrlqz/PcTQjfb2DOfQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
"System.Buffers": "4.5.1",
|
||||
"System.Memory": "4.5.4",
|
||||
"System.Numerics.Vectors": "4.5.0",
|
||||
"System.Runtime.CompilerServices.Unsafe": "5.0.0",
|
||||
"System.Text.Encodings.Web": "5.0.1",
|
||||
"System.Threading.Tasks.Extensions": "4.5.4",
|
||||
"System.ValueTuple": "4.5.0"
|
||||
}
|
||||
},
|
||||
"System.Threading.Tasks.Extensions": {
|
||||
"type": "Transitive",
|
||||
@@ -277,20 +301,25 @@
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.common": {
|
||||
"System.ValueTuple": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ=="
|
||||
},
|
||||
"speckle.autofac": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Converters.Common": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.15.3, )"
|
||||
"Autofac": "[5.2.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Connectors.Common": "[1.0.0, )"
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[3.1.0, )",
|
||||
"Speckle.Autofac": "[1.0.0, )",
|
||||
"Speckle.Connectors.Utils": "[1.0.0, )",
|
||||
"Speckle.Sdk": "[3.1.0-dev.107, )",
|
||||
"System.Threading.Tasks.Dataflow": "[6.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui.webview": {
|
||||
@@ -300,8 +329,14 @@
|
||||
"Speckle.Connectors.DUI": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.logging": {
|
||||
"type": "Project"
|
||||
"speckle.connectors.utils": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging": "[3.1.0, )",
|
||||
"Speckle.Autofac": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.1.0-dev.107, )",
|
||||
"Speckle.Sdk": "[3.1.0-dev.107, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.autocad2024": {
|
||||
"type": "Project",
|
||||
@@ -311,39 +346,55 @@
|
||||
"Speckle.Converters.Common": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.autocad2024.dependencyinjection": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Autofac": "[5.2.0, )",
|
||||
"Speckle.Converters.Autocad2024": "[1.0.0, )",
|
||||
"Speckle.Converters.Common.DependencyInjection": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.15.3, )"
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[3.1.0, )",
|
||||
"Speckle.Autofac": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.1.0-dev.107, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==",
|
||||
"speckle.converters.common.dependencyinjection": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0"
|
||||
"Speckle.Autofac": "[1.0.0, )",
|
||||
"Speckle.Converters.Common": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"Autofac": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[5.2.0, )",
|
||||
"resolved": "5.2.0",
|
||||
"contentHash": "V8dBH0dsv75uDzl7Sw+HkhKDPUw2eXnlMjcSVMH+tLo2s67MpTKGyDj1pDcpR+IF2u4YRs0s3/x7R88YJzIWvg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "1.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==",
|
||||
"requested": "[3.1.0, )",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "P+8sKQ8L4ooL79sxxqwFPxGGC3aBrUDLB/dZqhs4J0XjTyrkeeyJQ4D4nzJB6OnAhy78HIIgQ/RbD6upOXLynw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Binder": "2.2.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Options": "2.2.0"
|
||||
"Microsoft.Extensions.Configuration.Binder": "3.1.0",
|
||||
"Microsoft.Extensions.DependencyInjection": "3.1.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "3.1.0",
|
||||
"Microsoft.Extensions.Options": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
|
||||
"requested": "[3.1.0, )",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "jjo4YXRx6MIpv6DiRxJjSpl+sPP0+5VW0clMEdLyIAz44PPwrDTFrd5PZckIxIXl1kKZ2KK6IL2nkt0+ug2MQg=="
|
||||
},
|
||||
"Microsoft.Web.WebView2": {
|
||||
"type": "CentralTransitive",
|
||||
@@ -351,20 +402,38 @@
|
||||
"resolved": "1.0.1938.49",
|
||||
"contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
|
||||
},
|
||||
"Speckle.DoubleNumerics": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[4.1.0, )",
|
||||
"resolved": "4.1.0",
|
||||
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.15.3, )",
|
||||
"resolved": "3.15.3",
|
||||
"contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
|
||||
"requested": "[3.1.0-dev.107, )",
|
||||
"resolved": "3.1.0-dev.107",
|
||||
"contentHash": "MTXyE6Gs63wEW2kzLAtGCtZU+heohj87piVHSzanPg5qznqw0TXcvYBAg1IfeAg0ya5KMZ2IqT05GtW8bda1pQ==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.15.3"
|
||||
"Speckle.Sdk": "3.1.0-dev.107"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.1.0-dev.107, )",
|
||||
"resolved": "3.1.0-dev.107",
|
||||
"contentHash": "3qaL0N8fIcliOeDszBIYR9q1w/YG7OQod95F5l0Ju1R/RlB2WVaAC4CElPe6jHvZl96cDKOJ6K55827omL7QTQ==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.7",
|
||||
"Polly": "7.2.3",
|
||||
"Polly.Contrib.WaitAndRetry": "1.1.1",
|
||||
"Polly.Extensions.Http": "3.0.0",
|
||||
"Speckle.DoubleNumerics": "4.0.1",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Logging": "3.1.0-dev.107",
|
||||
"System.Text.Json": "5.0.2"
|
||||
}
|
||||
},
|
||||
"System.Threading.Tasks.Dataflow": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[6.0.0, )",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "+tyDCU3/B1lDdOOAJywHQoFwyXIUghIaP2BxG79uvhfTnO+D9qIgjVlL/JV2NTliYbMHpd6eKDmHp2VHpij7MA=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<AutoCADVersion>2025</AutoCADVersion>
|
||||
<DefineConstants>$(DefineConstants);AUTOCAD;AUTOCAD2025;AUTOCAD2022_OR_GREATER;AUTOCAD2023_OR_GREATER;AUTOCAD2024_OR_GREATER;AUTOCAD2025_OR_GREATER</DefineConstants>
|
||||
<DefineConstants>$(DefineConstants);AUTOCAD2025;AUTOCAD</DefineConstants>
|
||||
<Configurations>Debug;Release;Local</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- .NET Core uses this to move native dependencies into a root for runtime selection and usage for non-windows development https://learn.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#enablewindowstargeting -->
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<!--This is needed for managed dependencies-->
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<!--This is needed for the rest-->
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<!--This is needed just to keep folder paths the same as the netframework versions of autocad/civil-->
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <!-- .NET Core uses this to move native dependencies into a root for runtime selection and usage for non-windows development https://learn.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#enablewindowstargeting -->
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2025.0.0" ExcludeAssets="runtime" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Converters\Autocad\Speckle.Converters.Autocad2025\Speckle.Converters.Autocad2025.csproj" />
|
||||
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2025.0.0" />
|
||||
<FrameworkReference Include="Microsoft.WindowsDesktop.App"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Converters\Autocad\Speckle.Converters.Autocad2025.DependencyInjection\Speckle.Converters.Autocad2025.DependencyInjection.csproj" />
|
||||
<ProjectReference Include="..\..\..\DUI3\Speckle.Connectors.DUI.WebView\Speckle.Connectors.DUI.WebView.csproj" />
|
||||
<ProjectReference Include="..\..\..\Sdk\Speckle.Converters.Common\Speckle.Converters.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<Import Project="..\Speckle.Connectors.AutocadShared\Speckle.Connectors.AutocadShared.projitems" Label="Shared" />
|
||||
</Project>
|
||||
|
||||
@@ -2,15 +2,6 @@
|
||||
"version": 2,
|
||||
"dependencies": {
|
||||
"net8.0-windows7.0": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.0.3, )",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
|
||||
"dependencies": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.3"
|
||||
}
|
||||
},
|
||||
"Microsoft.SourceLink.GitHub": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.0.0, )",
|
||||
@@ -75,104 +66,116 @@
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
|
||||
},
|
||||
"Microsoft.CSharp": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.7.0",
|
||||
"contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA=="
|
||||
},
|
||||
"Microsoft.Data.Sqlite": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.5",
|
||||
"contentHash": "KGxbPeWsQMnmQy43DSBxAFtHz3l2JX8EWBSGUCvT3CuZ8KsuzbkqMIJMDOxWtG8eZSoCDI04aiVQjWuuV8HmSw==",
|
||||
"resolved": "7.0.7",
|
||||
"contentHash": "tiNmV1oPy+Z2R7Wd0bPB/FxCr8B+/5q11OpDMG751GA/YuOL7MZrBFfzv5oFRlFe08K6sjrnbrauzzGIeNrzLQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Data.Sqlite.Core": "7.0.5",
|
||||
"Microsoft.Data.Sqlite.Core": "7.0.7",
|
||||
"SQLitePCLRaw.bundle_e_sqlite3": "2.1.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Data.Sqlite.Core": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.5",
|
||||
"contentHash": "FTerRmQPqHrCrnoUzhBu+E+1DNGwyrAMLqHkAqOOOu5pGfyMOj8qQUBxI/gDtWtG11p49UxSfWmBzRNlwZqfUg==",
|
||||
"resolved": "7.0.7",
|
||||
"contentHash": "21FRzcJhaTrlv7kTrqr/ltFcSQM2TyuTTPhUcjO8H73od7Bb3QraNW90c7lUucNI/245XPkKZG4fp7/7OsKCSg==",
|
||||
"dependencies": {
|
||||
"SQLitePCLRaw.core": "2.1.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "Lu41BWNmwhKr6LgyQvcYBOge0pPvmiaK8R5UHXX4//wBhonJyWcT2OK1mqYfEM5G7pTf31fPrpIHOT6sN7EGOA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "2.2.0"
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "ESz6bVoDQX7sgWdKHF6G9Pq672T8k+19AFb/txDXwdz7MoqaNQj2/in3agm/3qae9V+WvQZH86LLTNVo0it8vQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
"Microsoft.Extensions.Primitives": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Binder": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "vJ9xvOZCnUAIHcGC3SU35r3HKmHTVIeHzo6u/qzlHAqD8m6xv92MLin4oJntTvkpKxVX3vI1GFFkIQtU3AdlsQ==",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "o9eELDBfNkR7sUtYysFZ1Q7BQ1mYt27DMkups/3vu7xgPyOpMD+iAfrBZFzUXT2iw0fmFb8s1gfNBZS+IgjKdQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "2.2.0"
|
||||
"Microsoft.Extensions.Configuration": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "KVkv3aF2MQpmGFRh4xRx2CNbc2sjDFk+lH4ySrjWSOS+XoY1Xc+sJphw3N0iYOpoeCCq8976ceVYDH8sdx2qIQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "f9hstgjVmr6rmrfGSpfsVOl2irKAgr1QjrSi3FgnS7kulxband50f2brRLwySAQTADPZeTdow0mpSMcoAdadCw=="
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "44rDtOf1JXXAFpNT2EXMExaDm/4OJ2RXOL9i9lE4bK427nzC7Exphv+beB6IgluyE2GIoo8zezTStMXI7MQ8WA=="
|
||||
},
|
||||
"Microsoft.Extensions.Options": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "9b6JHY7TAXrSfZ6EEGf+j8XnqKIiMPErfmaNXhJYSCb+BUW2H4RtzkNJvwLJzwgzqBP0wtTjyA6Uw4BPPdmkMw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Primitives": "2.2.0",
|
||||
"System.ComponentModel.Annotations": "4.5.0"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0",
|
||||
"Microsoft.Extensions.Primitives": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.1",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net461": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "AmOJZwCqnOCNp6PPcf9joyogScWLtwy0M1WkqfEQ0M9nYwyDD7EX9ZjscKS5iYnyvteX7kzSKFCKt9I9dXA6mA=="
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "LEKAnX7lhUhSoIc2XraCTK3M4IU/LdVUzCe464Sa4+7F4ZJuXHHRzZli2mDbiT4xzAZhgqXbvfnb5+CNDcQFfg=="
|
||||
},
|
||||
"Microsoft.SourceLink.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
|
||||
},
|
||||
"Polly": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.2.3",
|
||||
"contentHash": "DeCY0OFbNdNxsjntr1gTXHJ5pKUwYzp04Er2LLeN3g6pWhffsGuKVfMBLe1lw7x76HrPkLxKEFxBlpRxS2nDEQ=="
|
||||
},
|
||||
"Polly.Contrib.WaitAndRetry": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.1.1",
|
||||
"contentHash": "1MUQLiSo4KDkQe6nzQRhIU05lm9jlexX5BVsbuw0SL82ynZ+GzAHQxJVDPVBboxV37Po3SG077aX8DuSy8TkaA=="
|
||||
},
|
||||
"Polly.Extensions.Http": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.0",
|
||||
"contentHash": "drrG+hB3pYFY7w1c3BD+lSGYvH2oIclH8GRSehgfyP5kjnFnHKQuuBhuHLv+PWyFuaTDyk/vfRpnxOzd11+J8g==",
|
||||
"dependencies": {
|
||||
"Polly": "7.1.0"
|
||||
}
|
||||
},
|
||||
"Speckle.DoubleNumerics": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.0.1",
|
||||
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
|
||||
},
|
||||
"Speckle.Newtonsoft.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "13.0.2",
|
||||
"contentHash": "g1BejUZwax5PRfL6xHgLEK23sqHWOgOj9hE7RvfRRlN00AGt8GnPYt8HedSK7UB3HiRW8zCA9Pn0iiYxCK24BA=="
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"Speckle.Sdk.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.15.3",
|
||||
"contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.5",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.15.3"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.15.3",
|
||||
"contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
|
||||
"resolved": "3.1.0-dev.107",
|
||||
"contentHash": "phWGEyqiZlB5LichJtVA45xFFvxRxlU8rBTEag3llZeNIlSXRW0wzWmAq8gdQftHJyw59iupZwH2Tx+jglzp8w=="
|
||||
},
|
||||
"SQLitePCLRaw.bundle_e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
@@ -204,11 +207,6 @@
|
||||
"SQLitePCLRaw.core": "2.1.4"
|
||||
}
|
||||
},
|
||||
"System.ComponentModel.Annotations": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
|
||||
},
|
||||
"System.Memory": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.3",
|
||||
@@ -219,25 +217,25 @@
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ=="
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe": {
|
||||
"System.Text.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.1",
|
||||
"contentHash": "Zh8t8oqolRaFa9vmOZfdQm/qKejdqz0J9kr7o2Fu0vPeoH3BL1EOXipKWwkWtLT1JPzjByrF19fGuFlNbmPpiw=="
|
||||
"resolved": "5.0.2",
|
||||
"contentHash": "I47dVIGiV6SfAyppphxqupertT/5oZkYLDCX6vC3HpOI4ZLjyoKAreUoem2ie6G0RbRuFrlqz/PcTQjfb2DOfQ=="
|
||||
},
|
||||
"speckle.connectors.common": {
|
||||
"speckle.autofac": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Converters.Common": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.15.3, )"
|
||||
"Autofac": "[5.2.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Connectors.Common": "[1.0.0, )"
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[3.1.0, )",
|
||||
"Speckle.Autofac": "[1.0.0, )",
|
||||
"Speckle.Connectors.Utils": "[1.0.0, )",
|
||||
"Speckle.Sdk": "[3.1.0-dev.107, )",
|
||||
"System.Threading.Tasks.Dataflow": "[6.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui.webview": {
|
||||
@@ -247,8 +245,14 @@
|
||||
"Speckle.Connectors.DUI": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.logging": {
|
||||
"type": "Project"
|
||||
"speckle.connectors.utils": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging": "[3.1.0, )",
|
||||
"Speckle.Autofac": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.1.0-dev.107, )",
|
||||
"Speckle.Sdk": "[3.1.0-dev.107, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.autocad2025": {
|
||||
"type": "Project",
|
||||
@@ -258,39 +262,52 @@
|
||||
"Speckle.Converters.Common": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.autocad2025.dependencyinjection": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Autofac": "[5.2.0, )",
|
||||
"Speckle.Converters.Autocad2025": "[1.0.0, )",
|
||||
"Speckle.Converters.Common.DependencyInjection": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.15.3, )"
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[3.1.0, )",
|
||||
"Speckle.Autofac": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.1.0-dev.107, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==",
|
||||
"speckle.converters.common.dependencyinjection": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0"
|
||||
"Speckle.Autofac": "[1.0.0, )",
|
||||
"Speckle.Converters.Common": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"Autofac": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[5.2.0, )",
|
||||
"resolved": "5.2.0",
|
||||
"contentHash": "V8dBH0dsv75uDzl7Sw+HkhKDPUw2eXnlMjcSVMH+tLo2s67MpTKGyDj1pDcpR+IF2u4YRs0s3/x7R88YJzIWvg=="
|
||||
},
|
||||
"Microsoft.Extensions.Logging": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==",
|
||||
"requested": "[3.1.0, )",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "P+8sKQ8L4ooL79sxxqwFPxGGC3aBrUDLB/dZqhs4J0XjTyrkeeyJQ4D4nzJB6OnAhy78HIIgQ/RbD6upOXLynw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Binder": "2.2.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Options": "2.2.0"
|
||||
"Microsoft.Extensions.Configuration.Binder": "3.1.0",
|
||||
"Microsoft.Extensions.DependencyInjection": "3.1.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "3.1.0",
|
||||
"Microsoft.Extensions.Options": "3.1.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
|
||||
"requested": "[3.1.0, )",
|
||||
"resolved": "3.1.0",
|
||||
"contentHash": "jjo4YXRx6MIpv6DiRxJjSpl+sPP0+5VW0clMEdLyIAz44PPwrDTFrd5PZckIxIXl1kKZ2KK6IL2nkt0+ug2MQg=="
|
||||
},
|
||||
"Microsoft.Web.WebView2": {
|
||||
"type": "CentralTransitive",
|
||||
@@ -298,20 +315,38 @@
|
||||
"resolved": "1.0.1938.49",
|
||||
"contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
|
||||
},
|
||||
"Speckle.DoubleNumerics": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[4.1.0, )",
|
||||
"resolved": "4.1.0",
|
||||
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.15.3, )",
|
||||
"resolved": "3.15.3",
|
||||
"contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
|
||||
"requested": "[3.1.0-dev.107, )",
|
||||
"resolved": "3.1.0-dev.107",
|
||||
"contentHash": "MTXyE6Gs63wEW2kzLAtGCtZU+heohj87piVHSzanPg5qznqw0TXcvYBAg1IfeAg0ya5KMZ2IqT05GtW8bda1pQ==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.15.3"
|
||||
"Speckle.Sdk": "3.1.0-dev.107"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.1.0-dev.107, )",
|
||||
"resolved": "3.1.0-dev.107",
|
||||
"contentHash": "3qaL0N8fIcliOeDszBIYR9q1w/YG7OQod95F5l0Ju1R/RlB2WVaAC4CElPe6jHvZl96cDKOJ6K55827omL7QTQ==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.7",
|
||||
"Polly": "7.2.3",
|
||||
"Polly.Contrib.WaitAndRetry": "1.1.1",
|
||||
"Polly.Extensions.Http": "3.0.0",
|
||||
"Speckle.DoubleNumerics": "4.0.1",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Logging": "3.1.0-dev.107",
|
||||
"System.Text.Json": "5.0.2"
|
||||
}
|
||||
},
|
||||
"System.Threading.Tasks.Dataflow": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[6.0.0, )",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "+tyDCU3/B1lDdOOAJywHQoFwyXIUghIaP2BxG79uvhfTnO+D9qIgjVlL/JV2NTliYbMHpd6eKDmHp2VHpij7MA=="
|
||||
}
|
||||
},
|
||||
"net8.0-windows7.0/win-x64": {
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<AutoCADVersion>2026</AutoCADVersion>
|
||||
<DefineConstants>$(DefineConstants);AUTOCAD;AUTOCAD2026;AUTOCAD2022_OR_GREATER;AUTOCAD2023_OR_GREATER;AUTOCAD2024_OR_GREATER;AUTOCAD2025_OR_GREATER;AUTOCAD2026_OR_GREATER</DefineConstants>
|
||||
<Configurations>Debug;Release;Local</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- .NET Core uses this to move native dependencies into a root for runtime selection and usage for non-windows development https://learn.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#enablewindowstargeting -->
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<!--This is needed for managed dependencies-->
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<!--This is needed for the rest-->
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<!--This is needed just to keep folder paths the same as the netframework versions of autocad/civil-->
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2026.0.0" ExcludeAssets="runtime" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Converters\Autocad\Speckle.Converters.Autocad2026\Speckle.Converters.Autocad2026.csproj" />
|
||||
<ProjectReference Include="..\..\..\DUI3\Speckle.Connectors.DUI.WebView\Speckle.Connectors.DUI.WebView.csproj" />
|
||||
<ProjectReference Include="..\..\..\Sdk\Speckle.Converters.Common\Speckle.Converters.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\Speckle.Connectors.AutocadShared\Speckle.Connectors.AutocadShared.projitems" Label="Shared" />
|
||||
</Project>
|
||||
@@ -1,331 +0,0 @@
|
||||
{
|
||||
"version": 2,
|
||||
"dependencies": {
|
||||
"net8.0-windows7.0": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.0.3, )",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
|
||||
"dependencies": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.3"
|
||||
}
|
||||
},
|
||||
"Microsoft.SourceLink.GitHub": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.0.0, )",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Build.Tasks.Git": "8.0.0",
|
||||
"Microsoft.SourceLink.Common": "8.0.0"
|
||||
}
|
||||
},
|
||||
"PolySharp": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.14.1, )",
|
||||
"resolved": "1.14.1",
|
||||
"contentHash": "mOOmFYwad3MIOL14VCjj02LljyF1GNw1wP0YVlxtcPvqdxjGGMNdNJJxHptlry3MOd8b40Flm8RPOM8JOlN2sQ=="
|
||||
},
|
||||
"Speckle.AutoCAD.API": {
|
||||
"type": "Direct",
|
||||
"requested": "[2026.0.0, )",
|
||||
"resolved": "2026.0.0",
|
||||
"contentHash": "WlkV81PmbK/ftoM7aGpU6LGosKbePBQej9MO/m63rFMozX89tsitEhE12o58wu7K/4FmRUdAMolYtdK20EDBnw=="
|
||||
},
|
||||
"Speckle.InterfaceGenerator": {
|
||||
"type": "Direct",
|
||||
"requested": "[0.9.6, )",
|
||||
"resolved": "0.9.6",
|
||||
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
|
||||
},
|
||||
"GraphQL.Client": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "8yPNBbuVBpTptivyAlak4GZvbwbUcjeQTL4vN1HKHRuOykZ4r7l5fcLS6vpyPyLn0x8FsL31xbOIKyxbmR9rbA==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client.Abstractions": "6.0.0",
|
||||
"GraphQL.Client.Abstractions.Websocket": "6.0.0",
|
||||
"System.Reactive": "5.0.0"
|
||||
}
|
||||
},
|
||||
"GraphQL.Client.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "h7uzWFORHZ+CCjwr/ThAyXMr0DPpzEANDa4Uo54wqCQ+j7qUKwqYTgOrb1W40sqbvNaZm9v/X7It31SUw0maHA==",
|
||||
"dependencies": {
|
||||
"GraphQL.Primitives": "6.0.0"
|
||||
}
|
||||
},
|
||||
"GraphQL.Client.Abstractions.Websocket": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "Nr9bPf8gIOvLuXpqEpqr9z9jslYFJOvd0feHth3/kPqeR3uMbjF5pjiwh4jxyMcxHdr8Pb6QiXkV3hsSyt0v7A==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client.Abstractions": "6.0.0"
|
||||
}
|
||||
},
|
||||
"GraphQL.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "yg72rrYDapfsIUrul7aF6wwNnTJBOFvuA9VdDTQpPa8AlAriHbufeXYLBcodKjfUdkCnaiggX1U/nEP08Zb5GA=="
|
||||
},
|
||||
"Microsoft.Build.Tasks.Git": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
|
||||
},
|
||||
"Microsoft.Data.Sqlite": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.5",
|
||||
"contentHash": "KGxbPeWsQMnmQy43DSBxAFtHz3l2JX8EWBSGUCvT3CuZ8KsuzbkqMIJMDOxWtG8eZSoCDI04aiVQjWuuV8HmSw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Data.Sqlite.Core": "7.0.5",
|
||||
"SQLitePCLRaw.bundle_e_sqlite3": "2.1.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Data.Sqlite.Core": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.5",
|
||||
"contentHash": "FTerRmQPqHrCrnoUzhBu+E+1DNGwyrAMLqHkAqOOOu5pGfyMOj8qQUBxI/gDtWtG11p49UxSfWmBzRNlwZqfUg==",
|
||||
"dependencies": {
|
||||
"SQLitePCLRaw.core": "2.1.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Binder": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "vJ9xvOZCnUAIHcGC3SU35r3HKmHTVIeHzo6u/qzlHAqD8m6xv92MLin4oJntTvkpKxVX3vI1GFFkIQtU3AdlsQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "f9hstgjVmr6rmrfGSpfsVOl2irKAgr1QjrSi3FgnS7kulxband50f2brRLwySAQTADPZeTdow0mpSMcoAdadCw=="
|
||||
},
|
||||
"Microsoft.Extensions.Options": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Primitives": "2.2.0",
|
||||
"System.ComponentModel.Annotations": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.1",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net461": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "AmOJZwCqnOCNp6PPcf9joyogScWLtwy0M1WkqfEQ0M9nYwyDD7EX9ZjscKS5iYnyvteX7kzSKFCKt9I9dXA6mA=="
|
||||
},
|
||||
"Microsoft.SourceLink.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
|
||||
},
|
||||
"Speckle.Newtonsoft.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "13.0.2",
|
||||
"contentHash": "g1BejUZwax5PRfL6xHgLEK23sqHWOgOj9hE7RvfRRlN00AGt8GnPYt8HedSK7UB3HiRW8zCA9Pn0iiYxCK24BA=="
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.15.3",
|
||||
"contentHash": "6gmPoWTv7DwqvUae57wCLF93upE9RIjaCZFue9UMY4I6FB8vLbMGfcyiUwnUY551WlGOual15ISS3G15/kMmnw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.5",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.15.3"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.15.3",
|
||||
"contentHash": "VLgyGi1kQNWe0fzRO0U3qnZZUQGDeFacnpn25Yy3esE0qeo4tqa1BrvXPv2ivEZbbhBkkg6+Gd+CztDIyw3Y/w=="
|
||||
},
|
||||
"SQLitePCLRaw.bundle_e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "EWI1olKDjFEBMJu0+3wuxwziIAdWDVMYLhuZ3Qs84rrz+DHwD00RzWPZCa+bLnHCf3oJwuFZIRsHT5p236QXww==",
|
||||
"dependencies": {
|
||||
"SQLitePCLRaw.lib.e_sqlite3": "2.1.4",
|
||||
"SQLitePCLRaw.provider.e_sqlite3": "2.1.4"
|
||||
}
|
||||
},
|
||||
"SQLitePCLRaw.core": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "inBjvSHo9UDKneGNzfUfDjK08JzlcIhn1+SP5Y3m6cgXpCxXKCJDy6Mka7LpgSV+UZmKSnC8rTwB0SQ0xKu5pA==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.3"
|
||||
}
|
||||
},
|
||||
"SQLitePCLRaw.lib.e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
|
||||
},
|
||||
"SQLitePCLRaw.provider.e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "CSlb5dUp1FMIkez9Iv5EXzpeq7rHryVNqwJMWnpq87j9zWZexaEMdisDktMsnnrzKM6ahNrsTkjqNodTBPBxtQ==",
|
||||
"dependencies": {
|
||||
"SQLitePCLRaw.core": "2.1.4"
|
||||
}
|
||||
},
|
||||
"System.ComponentModel.Annotations": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
|
||||
},
|
||||
"System.Memory": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.3",
|
||||
"contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA=="
|
||||
},
|
||||
"System.Reactive": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ=="
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.1",
|
||||
"contentHash": "Zh8t8oqolRaFa9vmOZfdQm/qKejdqz0J9kr7o2Fu0vPeoH3BL1EOXipKWwkWtLT1JPzjByrF19fGuFlNbmPpiw=="
|
||||
},
|
||||
"speckle.connectors.common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Converters.Common": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.15.3, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Connectors.Common": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui.webview": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Web.WebView2": "[1.0.1938.49, )",
|
||||
"Speckle.Connectors.DUI": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.logging": {
|
||||
"type": "Project"
|
||||
},
|
||||
"speckle.converters.autocad2026": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Speckle.AutoCAD.API": "[2026.0.0, )",
|
||||
"Speckle.Connectors.DUI.WebView": "[1.0.0, )",
|
||||
"Speckle.Converters.Common": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.15.3, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Binder": "2.2.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Options": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
|
||||
},
|
||||
"Microsoft.Web.WebView2": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[1.0.1938.49, )",
|
||||
"resolved": "1.0.1938.49",
|
||||
"contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
|
||||
},
|
||||
"Speckle.DoubleNumerics": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[4.1.0, )",
|
||||
"resolved": "4.1.0",
|
||||
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.15.3, )",
|
||||
"resolved": "3.15.3",
|
||||
"contentHash": "zmHnLKR46in0xH5ashD+ENlYUPDktUMZhXYYOb8aWHAG3Zxai2WvmDJtdf7pV9GTafkpR6fCo2EQTeCoY+XXxQ==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.15.3"
|
||||
}
|
||||
}
|
||||
},
|
||||
"net8.0-windows7.0/win-x64": {
|
||||
"SQLitePCLRaw.lib.e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
|
||||
},
|
||||
"Microsoft.Web.WebView2": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[1.0.1938.49, )",
|
||||
"resolved": "1.0.1938.49",
|
||||
"contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Common.Threading;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.DUI.Models.Card;
|
||||
using Speckle.Connectors.Utils.Common;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Common;
|
||||
using Speckle.Sdk.Credentials;
|
||||
@@ -14,50 +13,31 @@ namespace Speckle.Connectors.Autocad.Bindings;
|
||||
|
||||
public class AutocadBasicConnectorBinding : IBasicConnectorBinding
|
||||
{
|
||||
private readonly IAccountManager _accountManager;
|
||||
public string Name { get; set; } = "baseBinding";
|
||||
public IBrowserBridge Parent { get; }
|
||||
public IBridge Parent { get; }
|
||||
|
||||
private readonly DocumentModelStore _store;
|
||||
private readonly ISpeckleApplication _speckleApplication;
|
||||
private readonly IThreadContext _threadContext;
|
||||
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
|
||||
private readonly ILogger<AutocadBasicConnectorBinding> _logger;
|
||||
|
||||
public BasicConnectorBindingCommands Commands { get; }
|
||||
|
||||
public AutocadBasicConnectorBinding(
|
||||
DocumentModelStore store,
|
||||
IBrowserBridge parent,
|
||||
IAccountManager accountManager,
|
||||
ISpeckleApplication speckleApplication,
|
||||
ILogger<AutocadBasicConnectorBinding> logger,
|
||||
IThreadContext threadContext,
|
||||
ITopLevelExceptionHandler topLevelExceptionHandler
|
||||
)
|
||||
public AutocadBasicConnectorBinding(DocumentModelStore store, IBridge parent)
|
||||
{
|
||||
_store = store;
|
||||
Parent = parent;
|
||||
_accountManager = accountManager;
|
||||
_speckleApplication = speckleApplication;
|
||||
Commands = new BasicConnectorBindingCommands(parent);
|
||||
_logger = logger;
|
||||
_threadContext = threadContext;
|
||||
_topLevelExceptionHandler = topLevelExceptionHandler;
|
||||
_store.DocumentChanged += (_, _) =>
|
||||
_topLevelExceptionHandler.FireAndForget(async () =>
|
||||
{
|
||||
await Commands.NotifyDocumentChanged();
|
||||
});
|
||||
{
|
||||
Commands.NotifyDocumentChanged();
|
||||
};
|
||||
}
|
||||
|
||||
public string GetConnectorVersion() => _speckleApplication.SpeckleVersion;
|
||||
public string GetConnectorVersion() => typeof(AutocadBasicConnectorBinding).Assembly.GetVersion();
|
||||
|
||||
public string GetSourceApplicationName() => _speckleApplication.Slug;
|
||||
public string GetSourceApplicationName() => Utils.Connector.Slug;
|
||||
|
||||
public string GetSourceApplicationVersion() => _speckleApplication.HostApplicationVersion;
|
||||
public string GetSourceApplicationVersion() => Utils.Connector.VersionString;
|
||||
|
||||
public Account[] GetAccounts() => _accountManager.GetAccounts().ToArray();
|
||||
public Account[] GetAccounts() => AccountManager.GetAccounts().ToArray();
|
||||
|
||||
public DocumentInfo? GetDocumentInfo()
|
||||
{
|
||||
@@ -73,25 +53,23 @@ public class AutocadBasicConnectorBinding : IBasicConnectorBinding
|
||||
|
||||
public DocumentModelStore GetDocumentState() => _store;
|
||||
|
||||
public void AddModel(ModelCard model) => _store.AddModel(model);
|
||||
public void AddModel(ModelCard model) => _store.Models.Add(model);
|
||||
|
||||
public void UpdateModel(ModelCard model) => _store.UpdateModel(model);
|
||||
|
||||
public void RemoveModel(ModelCard model) => _store.RemoveModel(model);
|
||||
|
||||
public void RemoveModels(List<ModelCard> models) => _store.RemoveModels(models);
|
||||
|
||||
public async Task HighlightObjects(IReadOnlyList<string> objectIds)
|
||||
public void HighlightObjects(List<string> objectIds)
|
||||
{
|
||||
// POC: Will be addressed to move it into AutocadContext!
|
||||
var doc = Application.DocumentManager.MdiActiveDocument;
|
||||
|
||||
var dbObjects = doc.GetObjects(objectIds);
|
||||
var acadObjectIds = dbObjects.Select(tuple => tuple.Root.Id).ToArray();
|
||||
await HighlightObjectsOnView(acadObjectIds);
|
||||
HighlightObjectsOnView(acadObjectIds);
|
||||
}
|
||||
|
||||
public async Task HighlightModel(string modelCardId)
|
||||
public void HighlightModel(string modelCardId)
|
||||
{
|
||||
// POC: Will be addressed to move it into AutocadContext!
|
||||
var doc = Application.DocumentManager.MdiActiveDocument;
|
||||
@@ -104,16 +82,14 @@ public class AutocadBasicConnectorBinding : IBasicConnectorBinding
|
||||
var objectIds = Array.Empty<ObjectId>();
|
||||
|
||||
var model = _store.GetModelById(modelCardId);
|
||||
|
||||
if (model == null)
|
||||
{
|
||||
_logger.LogError("Model was null when highlighting received model");
|
||||
return;
|
||||
}
|
||||
|
||||
if (model is SenderModelCard senderModelCard)
|
||||
{
|
||||
var dbObjects = doc.GetObjects(senderModelCard.SendFilter.NotNull().RefreshObjectIds());
|
||||
var dbObjects = doc.GetObjects(senderModelCard.SendFilter.NotNull().GetObjectIds());
|
||||
objectIds = dbObjects.Select(tuple => tuple.Root.Id).ToArray();
|
||||
}
|
||||
|
||||
@@ -125,22 +101,22 @@ public class AutocadBasicConnectorBinding : IBasicConnectorBinding
|
||||
|
||||
if (objectIds.Length == 0)
|
||||
{
|
||||
await Commands.SetModelError(modelCardId, new OperationCanceledException("No objects found to highlight."));
|
||||
Commands.SetModelError(modelCardId, new OperationCanceledException("No objects found to highlight."));
|
||||
return;
|
||||
}
|
||||
|
||||
await HighlightObjectsOnView(objectIds, modelCardId);
|
||||
HighlightObjectsOnView(objectIds, modelCardId);
|
||||
}
|
||||
|
||||
private async Task HighlightObjectsOnView(ObjectId[] objectIds, string? modelCardId = null)
|
||||
private void HighlightObjectsOnView(ObjectId[] objectIds, string? modelCardId = null)
|
||||
{
|
||||
var doc = Application.DocumentManager.MdiActiveDocument;
|
||||
|
||||
await _threadContext.RunOnMainAsync(async () =>
|
||||
Parent.RunOnMainThread(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
doc.Editor.SetImpliedSelection([]); // Deselects
|
||||
doc.Editor.SetImpliedSelection(Array.Empty<ObjectId>()); // Deselects
|
||||
try
|
||||
{
|
||||
doc.Editor.SetImpliedSelection(objectIds);
|
||||
@@ -171,7 +147,6 @@ public class AutocadBasicConnectorBinding : IBasicConnectorBinding
|
||||
{
|
||||
// Note: we're swallowing exeptions here because of a weird case when receiving blocks, we would have
|
||||
// acad api throw an error on accessing entity.GeometricExtents.
|
||||
// may also throw Autodesk.AutoCAD.Runtime.Exception for invalid extents on objects like rays and xlines
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,7 +158,7 @@ public class AutocadBasicConnectorBinding : IBasicConnectorBinding
|
||||
{
|
||||
if (modelCardId != null)
|
||||
{
|
||||
await Commands.SetModelError(modelCardId, new OperationCanceledException("Failed to highlight objects."));
|
||||
Commands.SetModelError(modelCardId, new OperationCanceledException("Failed to highlight objects."));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
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;
|
||||
|
||||
public abstract class AutocadReceiveBaseBinding(
|
||||
IBrowserBridge parent,
|
||||
ICancellationManager cancellationManager,
|
||||
IThreadContext threadContext,
|
||||
IReceiveOperationManagerFactory receiveOperationManagerFactory
|
||||
) : IReceiveBinding
|
||||
{
|
||||
public string Name => "receiveBinding";
|
||||
public IBrowserBridge Parent { get; } = parent;
|
||||
|
||||
private ReceiveBindingUICommands Commands { get; } = new(parent);
|
||||
|
||||
protected abstract void InitializeSettings(IServiceProvider serviceProvider, ModelCard mc);
|
||||
|
||||
public void CancelReceive(string modelCardId) => cancellationManager.CancelOperation(modelCardId);
|
||||
|
||||
public async Task Receive(string modelCardId) =>
|
||||
await threadContext.RunOnMainAsync(async () => await ReceiveInternal(modelCardId));
|
||||
|
||||
private async Task ReceiveInternal(string modelCardId)
|
||||
{
|
||||
using var manager = receiveOperationManagerFactory.Create();
|
||||
await manager.Process(
|
||||
Commands,
|
||||
modelCardId,
|
||||
InitializeSettings,
|
||||
async (_, processor) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
// Disable document activation (document creation and document switch)
|
||||
// Not disabling results in DUI model card being out of sync with the active document
|
||||
// The DocumentActivated event isn't usable probably because it is pushed to back of main thread queue
|
||||
Application.DocumentManager.DocumentActivationEnabled = false;
|
||||
return await processor();
|
||||
}
|
||||
finally
|
||||
{
|
||||
// reenable document activation
|
||||
Application.DocumentManager.DocumentActivationEnabled = true;
|
||||
|
||||
// regenerate doc to flush graphics, sometimes some objects (ellipses, nurbs curves) do not appear fully visible after receive.
|
||||
// Adding a regen (must be run on main thread) here, but it doesn't seem to work:
|
||||
// it's run on main thread, tried sending the "regen" string to execute, also tried regen after every object bake, but still can't fix.
|
||||
// the objects should appear visible if you manually call the "regen" command after the operation finishes, or click on a view on the view cube which also calls regen.
|
||||
Application.DocumentManager.CurrentDocument.Editor.Regen();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,101 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Speckle.Connectors.Common.Cancellation;
|
||||
using Speckle.Connectors.Common.Threading;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Autofac.DependencyInjection;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Logging;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.DUI.Models.Card;
|
||||
using Speckle.Converters.Autocad;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Connectors.Utils.Cancellation;
|
||||
using Speckle.Connectors.Utils.Operations;
|
||||
using Speckle.Sdk;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Bindings;
|
||||
|
||||
public sealed class AutocadReceiveBinding : AutocadReceiveBaseBinding
|
||||
public sealed class AutocadReceiveBinding : IReceiveBinding
|
||||
{
|
||||
private readonly IAutocadConversionSettingsFactory _autocadConversionSettingsFactory;
|
||||
public string Name => "receiveBinding";
|
||||
public IBridge Parent { get; }
|
||||
|
||||
private readonly DocumentModelStore _store;
|
||||
private readonly CancellationManager _cancellationManager;
|
||||
private readonly IUnitOfWorkFactory _unitOfWorkFactory;
|
||||
private readonly IOperationProgressManager _operationProgressManager;
|
||||
private readonly ILogger<AutocadReceiveBinding> _logger;
|
||||
|
||||
private ReceiveBindingUICommands Commands { get; }
|
||||
|
||||
public AutocadReceiveBinding(
|
||||
IBrowserBridge parent,
|
||||
ICancellationManager cancellationManager,
|
||||
IAutocadConversionSettingsFactory autocadConversionSettingsFactory,
|
||||
IThreadContext threadContext,
|
||||
IReceiveOperationManagerFactory receiveOperationManagerFactory
|
||||
DocumentModelStore store,
|
||||
IBridge parent,
|
||||
CancellationManager cancellationManager,
|
||||
IUnitOfWorkFactory unitOfWorkFactory,
|
||||
IOperationProgressManager operationProgressManager,
|
||||
ILogger<AutocadReceiveBinding> logger
|
||||
)
|
||||
: base(parent, cancellationManager, threadContext, receiveOperationManagerFactory)
|
||||
{
|
||||
_autocadConversionSettingsFactory = autocadConversionSettingsFactory;
|
||||
_store = store;
|
||||
_cancellationManager = cancellationManager;
|
||||
_unitOfWorkFactory = unitOfWorkFactory;
|
||||
_operationProgressManager = operationProgressManager;
|
||||
_logger = logger;
|
||||
Parent = parent;
|
||||
Commands = new ReceiveBindingUICommands(parent);
|
||||
}
|
||||
|
||||
protected override void InitializeSettings(IServiceProvider serviceProvider, ModelCard mc)
|
||||
public void CancelReceive(string modelCardId) => _cancellationManager.CancelOperation(modelCardId);
|
||||
|
||||
public async Task Receive(string modelCardId)
|
||||
{
|
||||
serviceProvider
|
||||
.GetRequiredService<IConverterSettingsStore<AutocadConversionSettings>>()
|
||||
.Initialize(_autocadConversionSettingsFactory.Create(Application.DocumentManager.CurrentDocument));
|
||||
using var unitOfWork = _unitOfWorkFactory.Resolve<ReceiveOperation>();
|
||||
try
|
||||
{
|
||||
// Get receiver card
|
||||
if (_store.GetModelById(modelCardId) is not ReceiverModelCard modelCard)
|
||||
{
|
||||
// Handle as GLOBAL ERROR at BrowserBridge
|
||||
throw new InvalidOperationException("No download model card was found.");
|
||||
}
|
||||
|
||||
CancellationToken cancellationToken = _cancellationManager.InitCancellationTokenSource(modelCardId);
|
||||
|
||||
// Disable document activation (document creation and document switch)
|
||||
// Not disabling results in DUI model card being out of sync with the active document
|
||||
// The DocumentActivated event isn't usable probably because it is pushed to back of main thread queue
|
||||
Application.DocumentManager.DocumentActivationEnabled = false;
|
||||
|
||||
// Receive host objects
|
||||
var operationResults = await unitOfWork
|
||||
.Service.Execute(
|
||||
modelCard.GetReceiveInfo(Speckle.Connectors.Utils.Connector.Slug),
|
||||
cancellationToken,
|
||||
(status, progress) =>
|
||||
_operationProgressManager.SetModelProgress(
|
||||
Parent,
|
||||
modelCardId,
|
||||
new ModelCardProgress(modelCardId, status, progress),
|
||||
cancellationToken
|
||||
)
|
||||
)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
Commands.SetModelReceiveResult(modelCardId, operationResults.BakedObjectIds, operationResults.ConversionResults);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// SWALLOW -> UI handles it immediately, so we do not need to handle anything for now!
|
||||
// Idea for later -> when cancel called, create promise from UI to solve it later with this catch block.
|
||||
// So have 3 state on UI -> Cancellation clicked -> Cancelling -> Cancelled
|
||||
return;
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal()) // UX reasons - we will report operation exceptions as model card error. We may change this later when we have more exception documentation
|
||||
{
|
||||
_logger.LogModelCardHandledError(ex);
|
||||
Commands.SetModelError(modelCardId, ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// reenable document activation
|
||||
Application.DocumentManager.DocumentActivationEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Autodesk.AutoCAD.EditorInput;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Common.Threading;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
|
||||
@@ -9,23 +8,17 @@ namespace Speckle.Connectors.Autocad.Bindings;
|
||||
|
||||
public class AutocadSelectionBinding : ISelectionBinding
|
||||
{
|
||||
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
|
||||
private readonly IThreadContext _threadContext;
|
||||
private const string SELECTION_EVENT = "setSelection";
|
||||
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
|
||||
private readonly HashSet<Document> _visitedDocuments = new();
|
||||
|
||||
public string Name => "selectionBinding";
|
||||
|
||||
public IBrowserBridge Parent { get; }
|
||||
public IBridge Parent { get; }
|
||||
|
||||
public AutocadSelectionBinding(
|
||||
IBrowserBridge parent,
|
||||
ITopLevelExceptionHandler topLevelExceptionHandler,
|
||||
IThreadContext threadContext
|
||||
)
|
||||
public AutocadSelectionBinding(IBridge parent)
|
||||
{
|
||||
_topLevelExceptionHandler = topLevelExceptionHandler;
|
||||
_threadContext = threadContext;
|
||||
_topLevelExceptionHandler = parent.TopLevelExceptionHandler;
|
||||
Parent = parent;
|
||||
|
||||
// POC: Use here Context for doc. In converters it's OK but we are still lacking to use context into bindings.
|
||||
@@ -48,7 +41,7 @@ public class AutocadSelectionBinding : ISelectionBinding
|
||||
if (!_visitedDocuments.Contains(document))
|
||||
{
|
||||
document.ImpliedSelectionChanged += (_, _) =>
|
||||
_topLevelExceptionHandler.FireAndForget(async () => await _threadContext.RunOnMainAsync(OnSelectionChanged));
|
||||
_topLevelExceptionHandler.CatchUnhandled(() => Parent.RunOnMainThread(OnSelectionChanged));
|
||||
|
||||
_visitedDocuments.Add(document);
|
||||
}
|
||||
@@ -59,10 +52,10 @@ public class AutocadSelectionBinding : ISelectionBinding
|
||||
// Ui requests to GetSelection() should just return this local copy that is kept up to date by the event handler.
|
||||
private SelectionInfo _selectionInfo;
|
||||
|
||||
private async Task OnSelectionChanged()
|
||||
private void OnSelectionChanged()
|
||||
{
|
||||
_selectionInfo = GetSelectionInternal();
|
||||
await Parent.Send(SELECTION_EVENT, _selectionInfo);
|
||||
Parent.Send(SELECTION_EVENT, _selectionInfo);
|
||||
}
|
||||
|
||||
public SelectionInfo GetSelection() => _selectionInfo;
|
||||
@@ -89,17 +82,6 @@ public class AutocadSelectionBinding : ISelectionBinding
|
||||
|
||||
objectTypes.Add(dbObject.GetType().Name);
|
||||
objs.Add(dbObject.GetSpeckleApplicationId());
|
||||
|
||||
// do the same also for each AttributeReference inside the BlockReference (attribute change is not affecting the block otherwise)
|
||||
if (dbObject is BlockReference blockReference)
|
||||
{
|
||||
foreach (ObjectId id in blockReference.AttributeCollection)
|
||||
{
|
||||
var attr = (AttributeReference)tr.GetObject(id, OpenMode.ForRead);
|
||||
objectTypes.Add(attr.GetType().Name);
|
||||
objs.Add(attr.GetSpeckleApplicationId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tr.Commit();
|
||||
|
||||
@@ -1,227 +0,0 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Autodesk.AutoCAD.Geometry;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Common.Caching;
|
||||
using Speckle.Connectors.Common.Cancellation;
|
||||
using Speckle.Connectors.Common.Threading;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.DUI.Models.Card;
|
||||
using Speckle.Connectors.DUI.Models.Card.SendFilter;
|
||||
using Speckle.Connectors.DUI.Settings;
|
||||
using Speckle.Sdk.Common;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Bindings;
|
||||
|
||||
[SuppressMessage("ReSharper", "AsyncVoidMethod")]
|
||||
public abstract class AutocadSendBaseBinding : ISendBinding
|
||||
{
|
||||
public string Name => "sendBinding";
|
||||
public SendBindingUICommands Commands { get; }
|
||||
private OperationProgressManager OperationProgressManager { get; }
|
||||
public IBrowserBridge Parent { get; }
|
||||
|
||||
private readonly DocumentModelStore _store;
|
||||
private readonly List<ISendFilter> _sendFilters;
|
||||
private readonly ICancellationManager _cancellationManager;
|
||||
private readonly ISendConversionCache _sendConversionCache;
|
||||
private readonly IThreadContext _threadContext;
|
||||
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
|
||||
private readonly IAppIdleManager _idleManager;
|
||||
private readonly ISendOperationManagerFactory _sendOperationManagerFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Used internally to aggregate the changed objects' id. Note we're using a concurrent dictionary here as the expiry check method is not thread safe, and this was causing problems. See:
|
||||
/// [CNX-202: Unhandled Exception Occurred when receiving in Rhino](https://linear.app/speckle/issue/CNX-202/unhandled-exception-occurred-when-receiving-in-rhino)
|
||||
/// As to why a concurrent dictionary, it's because it's the cheapest/easiest way to do so.
|
||||
/// https://stackoverflow.com/questions/18922985/concurrent-hashsett-in-net-framework
|
||||
/// </summary>
|
||||
private ConcurrentBag<string> ChangedObjectIds { get; set; } = new();
|
||||
|
||||
private readonly List<string> _docSubsTracker = new();
|
||||
private readonly Dictionary<string, Matrix3d> _docUcsTracker = new();
|
||||
|
||||
protected AutocadSendBaseBinding(
|
||||
DocumentModelStore store,
|
||||
IBrowserBridge parent,
|
||||
IEnumerable<ISendFilter> sendFilters,
|
||||
ICancellationManager cancellationManager,
|
||||
ISendConversionCache sendConversionCache,
|
||||
IThreadContext threadContext,
|
||||
ITopLevelExceptionHandler topLevelExceptionHandler,
|
||||
IAppIdleManager idleManager,
|
||||
ISendOperationManagerFactory sendOperationManagerFactory
|
||||
)
|
||||
{
|
||||
_store = store;
|
||||
_cancellationManager = cancellationManager;
|
||||
_sendFilters = sendFilters.ToList();
|
||||
_sendConversionCache = sendConversionCache;
|
||||
_threadContext = threadContext;
|
||||
_topLevelExceptionHandler = topLevelExceptionHandler;
|
||||
_idleManager = idleManager;
|
||||
_sendOperationManagerFactory = sendOperationManagerFactory;
|
||||
Parent = parent;
|
||||
Commands = new SendBindingUICommands(parent);
|
||||
|
||||
Application.DocumentManager.DocumentActivated += (_, args) =>
|
||||
_topLevelExceptionHandler.CatchUnhandled(() => SubscribeToObjectChanges(args.Document));
|
||||
|
||||
if (Application.DocumentManager.CurrentDocument != null)
|
||||
{
|
||||
// catches the case when autocad just opens up with a blank new doc
|
||||
SubscribeToObjectChanges(Application.DocumentManager.CurrentDocument);
|
||||
}
|
||||
|
||||
Application.SystemVariableChanged += (_, e) =>
|
||||
_topLevelExceptionHandler.CatchUnhandled(() => OnSystemVariableChanged(e));
|
||||
|
||||
// Since ids of the objects generates from same seed, we should clear the cache always whenever doc swapped.
|
||||
_store.DocumentChanged += (_, _) =>
|
||||
{
|
||||
_sendConversionCache.ClearCache();
|
||||
};
|
||||
}
|
||||
|
||||
private void SubscribeToObjectChanges(Document doc)
|
||||
{
|
||||
if (doc == null || doc.Database == null || _docSubsTracker.Contains(doc.Name))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_docSubsTracker.Add(doc.Name);
|
||||
_docUcsTracker[doc.Name] = doc.Editor.CurrentUserCoordinateSystem;
|
||||
|
||||
doc.Database.ObjectAppended += (_, e) => OnObjectChanged(e.DBObject);
|
||||
doc.Database.ObjectErased += (_, e) => OnObjectChanged(e.DBObject);
|
||||
doc.Database.ObjectModified += (_, e) => OnObjectChanged(e.DBObject);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles system variable changes to detect UCS modifications.
|
||||
/// When UCS changes, clears the conversion cache and expires all sender model cards.
|
||||
/// </summary>
|
||||
private void OnSystemVariableChanged(Autodesk.AutoCAD.ApplicationServices.SystemVariableChangedEventArgs e)
|
||||
{
|
||||
// check if this is a UCS-defining system variable
|
||||
string varName = e.Name.ToUpperInvariant();
|
||||
bool isUcsChange = varName == "UCSNAME" || varName == "UCSORG" || varName == "UCSXDIR" || varName == "UCSYDIR";
|
||||
|
||||
if (!isUcsChange)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// get the currently active document
|
||||
Document doc = Application.DocumentManager.MdiActiveDocument;
|
||||
if (doc == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var currentUcs = doc.Editor.CurrentUserCoordinateSystem;
|
||||
|
||||
// first time tracking this document's UCS
|
||||
if (!_docUcsTracker.TryGetValue(doc.Name, out Matrix3d storedUcs))
|
||||
{
|
||||
_docUcsTracker[doc.Name] = currentUcs;
|
||||
return;
|
||||
}
|
||||
|
||||
// ucs hasn't actually changed (multiple variables fire for single UCS change)
|
||||
if (currentUcs.IsEqualTo(storedUcs))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// ucs has changed - all cached conversions invalid
|
||||
_sendConversionCache.ClearCache();
|
||||
_docUcsTracker[doc.Name] = currentUcs;
|
||||
|
||||
// expire all sender model cards
|
||||
_idleManager.SubscribeToIdle(nameof(ExpireAllSenders), async () => await ExpireAllSenders());
|
||||
}
|
||||
|
||||
private void OnObjectChanged(DBObject dbObject) =>
|
||||
_topLevelExceptionHandler.CatchUnhandled(() => OnChangeChangedObjectIds(dbObject));
|
||||
|
||||
private void OnChangeChangedObjectIds(DBObject dBObject)
|
||||
{
|
||||
ChangedObjectIds.Add(dBObject.GetSpeckleApplicationId());
|
||||
_idleManager.SubscribeToIdle(nameof(RunExpirationChecks), async () => await RunExpirationChecks());
|
||||
}
|
||||
|
||||
private async Task RunExpirationChecks()
|
||||
{
|
||||
var senders = _store.GetSenders();
|
||||
List<string> expiredSenderIds = new();
|
||||
|
||||
_sendConversionCache.EvictObjects(ChangedObjectIds);
|
||||
|
||||
foreach (SenderModelCard modelCard in senders)
|
||||
{
|
||||
var intersection = modelCard.SendFilter.NotNull().RefreshObjectIds().Intersect(ChangedObjectIds).ToList();
|
||||
bool isExpired = intersection.Count != 0;
|
||||
if (isExpired)
|
||||
{
|
||||
expiredSenderIds.Add(modelCard.ModelCardId.NotNull());
|
||||
}
|
||||
}
|
||||
|
||||
await Commands.SetModelsExpired(expiredSenderIds);
|
||||
ChangedObjectIds = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Expires all sender model cards when a global change occurs (like UCS change).
|
||||
/// </summary>
|
||||
private async Task ExpireAllSenders()
|
||||
{
|
||||
var senders = _store.GetSenders();
|
||||
var expiredSenderIds = senders.Select(s => s.ModelCardId.NotNull()).ToList();
|
||||
if (expiredSenderIds.Count > 0)
|
||||
{
|
||||
await Commands.SetModelsExpired(expiredSenderIds);
|
||||
}
|
||||
}
|
||||
|
||||
public List<ISendFilter> GetSendFilters() => _sendFilters;
|
||||
|
||||
public List<ICardSetting> GetSendSettings() => [];
|
||||
|
||||
public async Task Send(string modelCardId) =>
|
||||
await _threadContext.RunOnMainAsync(async () => await SendInternal(modelCardId));
|
||||
|
||||
protected abstract void InitializeSettings(IServiceProvider serviceProvider);
|
||||
|
||||
private async Task SendInternal(string modelCardId)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var manager = _sendOperationManagerFactory.Create();
|
||||
// Disable document activation (document creation and document switch)
|
||||
// Not disabling results in DUI model card being out of sync with the active document
|
||||
// The DocumentActivated event isn't usable probably because it is pushed to back of main thread queue
|
||||
Application.DocumentManager.DocumentActivationEnabled = false;
|
||||
await manager.Process(
|
||||
Commands,
|
||||
modelCardId,
|
||||
(sp, card) => InitializeSettings(sp),
|
||||
card => Application.DocumentManager.CurrentDocument.GetObjects(card.SendFilter.NotNull().RefreshObjectIds()),
|
||||
Application.DocumentManager.CurrentDocument.Name,
|
||||
null
|
||||
);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// renable document activation
|
||||
Application.DocumentManager.DocumentActivationEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void CancelSend(string modelCardId) => _cancellationManager.CancelOperation(modelCardId);
|
||||
}
|
||||
@@ -1,51 +1,213 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Speckle.Connectors.Common.Caching;
|
||||
using Speckle.Connectors.Common.Cancellation;
|
||||
using Speckle.Connectors.Common.Threading;
|
||||
using System.Collections.Concurrent;
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Autofac.DependencyInjection;
|
||||
using Speckle.Connectors.Autocad.HostApp;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Exceptions;
|
||||
using Speckle.Connectors.DUI.Logging;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.DUI.Models.Card;
|
||||
using Speckle.Connectors.DUI.Models.Card.SendFilter;
|
||||
using Speckle.Converters.Autocad;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Connectors.DUI.Settings;
|
||||
using Speckle.Connectors.Utils.Caching;
|
||||
using Speckle.Connectors.Utils.Cancellation;
|
||||
using Speckle.Connectors.Utils.Operations;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Common;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Bindings;
|
||||
|
||||
public sealed class AutocadSendBinding : AutocadSendBaseBinding
|
||||
public sealed class AutocadSendBinding : ISendBinding
|
||||
{
|
||||
private readonly IAutocadConversionSettingsFactory _autocadConversionSettingsFactory;
|
||||
public string Name => "sendBinding";
|
||||
public SendBindingUICommands Commands { get; }
|
||||
private OperationProgressManager OperationProgressManager { get; }
|
||||
public IBridge Parent { get; }
|
||||
|
||||
private readonly DocumentModelStore _store;
|
||||
private readonly IAutocadIdleManager _idleManager;
|
||||
private readonly List<ISendFilter> _sendFilters;
|
||||
private readonly CancellationManager _cancellationManager;
|
||||
private readonly IUnitOfWorkFactory _unitOfWorkFactory;
|
||||
private readonly ISendConversionCache _sendConversionCache;
|
||||
private readonly IOperationProgressManager _operationProgressManager;
|
||||
private readonly ILogger<AutocadSendBinding> _logger;
|
||||
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
|
||||
|
||||
/// <summary>
|
||||
/// Used internally to aggregate the changed objects' id. Note we're using a concurrent dictionary here as the expiry check method is not thread safe, and this was causing problems. See:
|
||||
/// [CNX-202: Unhandled Exception Occurred when receiving in Rhino](https://linear.app/speckle/issue/CNX-202/unhandled-exception-occurred-when-receiving-in-rhino)
|
||||
/// As to why a concurrent dictionary, it's because it's the cheapest/easiest way to do so.
|
||||
/// https://stackoverflow.com/questions/18922985/concurrent-hashsett-in-net-framework
|
||||
/// </summary>
|
||||
private ConcurrentDictionary<string, byte> ChangedObjectIds { get; set; } = new();
|
||||
|
||||
public AutocadSendBinding(
|
||||
DocumentModelStore store,
|
||||
IBrowserBridge parent,
|
||||
IAutocadIdleManager idleManager,
|
||||
IBridge parent,
|
||||
IEnumerable<ISendFilter> sendFilters,
|
||||
ICancellationManager cancellationManager,
|
||||
CancellationManager cancellationManager,
|
||||
IUnitOfWorkFactory unitOfWorkFactory,
|
||||
ISendConversionCache sendConversionCache,
|
||||
IAutocadConversionSettingsFactory autocadConversionSettingsFactory,
|
||||
IThreadContext threadContext,
|
||||
ITopLevelExceptionHandler topLevelExceptionHandler,
|
||||
IAppIdleManager appIdleManager,
|
||||
ISendOperationManagerFactory sendOperationManagerFactory
|
||||
IOperationProgressManager operationProgressManager,
|
||||
ILogger<AutocadSendBinding> logger
|
||||
)
|
||||
: base(
|
||||
store,
|
||||
parent,
|
||||
sendFilters,
|
||||
cancellationManager,
|
||||
sendConversionCache,
|
||||
threadContext,
|
||||
topLevelExceptionHandler,
|
||||
appIdleManager,
|
||||
sendOperationManagerFactory
|
||||
)
|
||||
{
|
||||
_autocadConversionSettingsFactory = autocadConversionSettingsFactory;
|
||||
_store = store;
|
||||
_idleManager = idleManager;
|
||||
_unitOfWorkFactory = unitOfWorkFactory;
|
||||
_cancellationManager = cancellationManager;
|
||||
_sendFilters = sendFilters.ToList();
|
||||
_sendConversionCache = sendConversionCache;
|
||||
_operationProgressManager = operationProgressManager;
|
||||
_logger = logger;
|
||||
_topLevelExceptionHandler = parent.TopLevelExceptionHandler;
|
||||
Parent = parent;
|
||||
Commands = new SendBindingUICommands(parent);
|
||||
|
||||
Application.DocumentManager.DocumentActivated += (_, args) =>
|
||||
_topLevelExceptionHandler.CatchUnhandled(() => SubscribeToObjectChanges(args.Document));
|
||||
|
||||
if (Application.DocumentManager.CurrentDocument != null)
|
||||
{
|
||||
// catches the case when autocad just opens up with a blank new doc
|
||||
SubscribeToObjectChanges(Application.DocumentManager.CurrentDocument);
|
||||
}
|
||||
// Since ids of the objects generates from same seed, we should clear the cache always whenever doc swapped.
|
||||
_store.DocumentChanged += (_, _) =>
|
||||
{
|
||||
_sendConversionCache.ClearCache();
|
||||
};
|
||||
}
|
||||
|
||||
protected override void InitializeSettings(IServiceProvider serviceProvider)
|
||||
private readonly List<string> _docSubsTracker = new();
|
||||
|
||||
private void SubscribeToObjectChanges(Document doc)
|
||||
{
|
||||
serviceProvider
|
||||
.GetRequiredService<IConverterSettingsStore<AutocadConversionSettings>>()
|
||||
.Initialize(_autocadConversionSettingsFactory.Create(Application.DocumentManager.CurrentDocument));
|
||||
if (doc == null || doc.Database == null || _docSubsTracker.Contains(doc.Name))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_docSubsTracker.Add(doc.Name);
|
||||
doc.Database.ObjectAppended += (_, e) => OnObjectChanged(e.DBObject);
|
||||
doc.Database.ObjectErased += (_, e) => OnObjectChanged(e.DBObject);
|
||||
doc.Database.ObjectModified += (_, e) => OnObjectChanged(e.DBObject);
|
||||
}
|
||||
|
||||
private void OnObjectChanged(DBObject dbObject)
|
||||
{
|
||||
_topLevelExceptionHandler.CatchUnhandled(() => OnChangeChangedObjectIds(dbObject));
|
||||
}
|
||||
|
||||
private void OnChangeChangedObjectIds(DBObject dBObject)
|
||||
{
|
||||
ChangedObjectIds[dBObject.GetSpeckleApplicationId()] = 1;
|
||||
_idleManager.SubscribeToIdle(nameof(AutocadSendBinding), RunExpirationChecks);
|
||||
}
|
||||
|
||||
private void RunExpirationChecks()
|
||||
{
|
||||
var senders = _store.GetSenders();
|
||||
string[] objectIdsList = ChangedObjectIds.Keys.ToArray();
|
||||
List<string> expiredSenderIds = new();
|
||||
|
||||
_sendConversionCache.EvictObjects(objectIdsList);
|
||||
|
||||
foreach (SenderModelCard modelCard in senders)
|
||||
{
|
||||
var intersection = modelCard.SendFilter.NotNull().GetObjectIds().Intersect(objectIdsList).ToList();
|
||||
bool isExpired = intersection.Count != 0;
|
||||
if (isExpired)
|
||||
{
|
||||
expiredSenderIds.Add(modelCard.ModelCardId.NotNull());
|
||||
}
|
||||
}
|
||||
|
||||
Commands.SetModelsExpired(expiredSenderIds);
|
||||
ChangedObjectIds = new();
|
||||
}
|
||||
|
||||
public List<ISendFilter> GetSendFilters() => _sendFilters;
|
||||
|
||||
public List<CardSetting> GetSendSettings() => [];
|
||||
|
||||
public Task Send(string modelCardId)
|
||||
{
|
||||
Parent.RunOnMainThread(async () => await SendInternal(modelCardId).ConfigureAwait(false));
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task SendInternal(string modelCardId)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_store.GetModelById(modelCardId) is not SenderModelCard modelCard)
|
||||
{
|
||||
// Handle as GLOBAL ERROR at BrowserBridge
|
||||
throw new InvalidOperationException("No publish model card was found.");
|
||||
}
|
||||
|
||||
using var uow = _unitOfWorkFactory.Resolve<SendOperation<AutocadRootObject>>();
|
||||
|
||||
CancellationToken cancellationToken = _cancellationManager.InitCancellationTokenSource(modelCardId);
|
||||
|
||||
// Disable document activation (document creation and document switch)
|
||||
// Not disabling results in DUI model card being out of sync with the active document
|
||||
// The DocumentActivated event isn't usable probably because it is pushed to back of main thread queue
|
||||
Application.DocumentManager.DocumentActivationEnabled = false;
|
||||
|
||||
// Get elements to convert
|
||||
List<AutocadRootObject> autocadObjects = Application.DocumentManager.CurrentDocument.GetObjects(
|
||||
modelCard.SendFilter.NotNull().GetObjectIds()
|
||||
);
|
||||
|
||||
if (autocadObjects.Count == 0)
|
||||
{
|
||||
// Handle as CARD ERROR in this function
|
||||
throw new SpeckleSendFilterException("No objects were found to convert. Please update your publish filter!");
|
||||
}
|
||||
|
||||
var sendResult = await uow
|
||||
.Service.Execute(
|
||||
autocadObjects,
|
||||
modelCard.GetSendInfo(Speckle.Connectors.Utils.Connector.Slug),
|
||||
(status, progress) =>
|
||||
_operationProgressManager.SetModelProgress(
|
||||
Parent,
|
||||
modelCardId,
|
||||
new ModelCardProgress(modelCardId, status, progress),
|
||||
cancellationToken
|
||||
),
|
||||
cancellationToken
|
||||
)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
Commands.SetModelSendResult(modelCardId, sendResult.RootObjId, sendResult.ConversionResults);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// SWALLOW -> UI handles it immediately, so we do not need to handle anything for now!
|
||||
// Idea for later -> when cancel called, create promise from UI to solve it later with this catch block.
|
||||
// So have 3 state on UI -> Cancellation clicked -> Cancelling -> Cancelled
|
||||
return;
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal()) // UX reasons - we will report operation exceptions as model card error. We may change this later when we have more exception documentation
|
||||
{
|
||||
_logger.LogModelCardHandledError(ex);
|
||||
Commands.SetModelError(modelCardId, ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// renable document activation
|
||||
Application.DocumentManager.DocumentActivationEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void CancelSend(string modelCardId) => _cancellationManager.CancelOperation(modelCardId);
|
||||
}
|
||||
|
||||
@@ -1,34 +1,21 @@
|
||||
#if AUTOCAD
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Speckle.Connectors.Autocad.Bindings;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Connectors.Common.Builders;
|
||||
using Speckle.Autofac.DependencyInjection;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Sdk;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.DependencyInjection;
|
||||
|
||||
public static class AutocadConnectorModule
|
||||
public class AutocadConnectorModule : ISpeckleModule
|
||||
{
|
||||
public static void AddAutocad(this IServiceCollection serviceCollection)
|
||||
public void Load(SpeckleContainerBuilder builder)
|
||||
{
|
||||
serviceCollection.AddAutocadBase();
|
||||
SharedRegistration.Load(builder);
|
||||
|
||||
// Send
|
||||
serviceCollection.LoadSend();
|
||||
serviceCollection.AddScoped<IRootObjectBuilder<AutocadRootObject>, AutocadRootObjectBuilder>();
|
||||
serviceCollection.AddScoped<
|
||||
IRootContinuousTraversalBuilder<AutocadRootObject>,
|
||||
AutocadContinuousTraversalBuilder
|
||||
>();
|
||||
// Operations
|
||||
SharedRegistration.LoadSend(builder);
|
||||
SharedRegistration.LoadReceive(builder);
|
||||
|
||||
// Receive
|
||||
serviceCollection.LoadReceive();
|
||||
|
||||
// Register vertical specific bindings
|
||||
serviceCollection.AddSingleton<IBinding, AutocadSendBinding>();
|
||||
serviceCollection.AddMatchingInterfacesAsTransient(Assembly.GetExecutingAssembly());
|
||||
// Register bindings
|
||||
builder.AddSingleton<IBinding, ConfigBinding>("connectorName", "Autocad"); // POC: Easier like this for now, should be cleaned up later
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
#if CIVIL3D
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Connectors.Common.Builders;
|
||||
|
||||
using Speckle.Autofac.DependencyInjection;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.DependencyInjection;
|
||||
|
||||
public static class Civil3dConnectorModule
|
||||
public class Civil3dConnectorModule : ISpeckleModule
|
||||
{
|
||||
public static void AddCivil3d(this IServiceCollection serviceCollection)
|
||||
public void Load(SpeckleContainerBuilder builder)
|
||||
{
|
||||
serviceCollection.AddAutocadBase();
|
||||
SharedRegistration.Load(builder);
|
||||
SharedRegistration.LoadSend(builder);
|
||||
|
||||
// send
|
||||
serviceCollection.LoadSend();
|
||||
serviceCollection.AddScoped<IRootObjectBuilder<AutocadRootObject>, Civil3dRootObjectBuilder>();
|
||||
// Register bindings
|
||||
builder.AddSingleton<IBinding, ConfigBinding>("connectorName", "Civil3d"); // POC: Easier like this for now, should be cleaned up later
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,93 +1,101 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Autofac;
|
||||
using Speckle.Autofac;
|
||||
using Speckle.Autofac.DependencyInjection;
|
||||
using Speckle.Connectors.Autocad.Bindings;
|
||||
using Speckle.Connectors.Autocad.Filters;
|
||||
using Speckle.Connectors.Autocad.HostApp;
|
||||
using Speckle.Connectors.Autocad.Operations.Receive;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Connectors.Common;
|
||||
using Speckle.Connectors.Common.Builders;
|
||||
using Speckle.Connectors.Common.Caching;
|
||||
using Speckle.Connectors.Common.Instances;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Connectors.Common.Threading;
|
||||
using Speckle.Connectors.DUI;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.DUI.Models.Card.SendFilter;
|
||||
using Speckle.Connectors.DUI.WebView;
|
||||
using Speckle.Connectors.Utils;
|
||||
using Speckle.Connectors.Utils.Builders;
|
||||
using Speckle.Connectors.Utils.Caching;
|
||||
using Speckle.Connectors.Utils.Instances;
|
||||
using Speckle.Connectors.Utils.Operations;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Sdk.Models.GraphTraversal;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.DependencyInjection;
|
||||
|
||||
public static class SharedRegistration
|
||||
{
|
||||
public static void AddAutocadBase(this IServiceCollection serviceCollection)
|
||||
public static void Load(SpeckleContainerBuilder builder)
|
||||
{
|
||||
serviceCollection.AddConnectors();
|
||||
serviceCollection.AddDUI<DefaultThreadContext, AutocadDocumentStore>();
|
||||
serviceCollection.AddDUIView();
|
||||
builder.AddAutofac();
|
||||
builder.AddConnectorUtils();
|
||||
builder.AddDUI();
|
||||
builder.AddDUIView();
|
||||
|
||||
// Register other connector specific types
|
||||
serviceCollection.AddTransient<TransactionContext>();
|
||||
serviceCollection.AddSingleton(new AutocadDocumentManager()); // TODO: Dependent to TransactionContext, can be moved to AutocadContext
|
||||
serviceCollection.AddSingleton<AutocadContext>();
|
||||
|
||||
// Unpackers and builders
|
||||
serviceCollection.AddScoped<AutocadLayerUnpacker>();
|
||||
serviceCollection.AddScoped<AutocadLayerBaker>();
|
||||
|
||||
serviceCollection.AddScoped<AutocadInstanceUnpacker>();
|
||||
serviceCollection.AddScoped<AutocadInstanceBaker>();
|
||||
|
||||
serviceCollection.AddScoped<AutocadGroupUnpacker>();
|
||||
serviceCollection.AddScoped<AutocadGroupBaker>();
|
||||
|
||||
serviceCollection.AddScoped<AutocadColorUnpacker>();
|
||||
serviceCollection.AddScoped<IAutocadColorBaker, AutocadColorBaker>();
|
||||
|
||||
serviceCollection.AddScoped<AutocadMaterialUnpacker>();
|
||||
serviceCollection.AddScoped<IAutocadMaterialBaker, AutocadMaterialBaker>();
|
||||
|
||||
serviceCollection.AddSingleton<IAppIdleManager, AutocadIdleManager>();
|
||||
builder.AddTransient<TransactionContext>();
|
||||
builder.AddSingleton(new AutocadDocumentManager()); // TODO: Dependent to TransactionContext, can be moved to AutocadContext
|
||||
builder.AddSingleton<DocumentModelStore, AutocadDocumentStore>();
|
||||
builder.AddSingleton<AutocadContext>();
|
||||
builder.AddScoped<AutocadGroupManager>();
|
||||
builder.AddScoped<AutocadLayerManager>();
|
||||
builder.AddScoped<AutocadColorManager>();
|
||||
builder.AddScoped<AutocadMaterialManager>();
|
||||
builder.AddSingleton<IAutocadIdleManager, AutocadIdleManager>();
|
||||
builder.AddSingleton<IHostToSpeckleUnitConverter<UnitsValue>>();
|
||||
|
||||
// operation progress manager
|
||||
serviceCollection.AddSingleton<IOperationProgressManager, OperationProgressManager>();
|
||||
builder.AddSingleton<IOperationProgressManager, OperationProgressManager>();
|
||||
|
||||
// Register bindings
|
||||
serviceCollection.AddSingleton<IBinding, TestBinding>();
|
||||
serviceCollection.AddSingleton<IBinding, AccountBinding>();
|
||||
serviceCollection.AddSingleton<IBinding, AutocadSelectionBinding>();
|
||||
serviceCollection.AddSingleton<IBinding>(sp => sp.GetRequiredService<IBasicConnectorBinding>());
|
||||
serviceCollection.AddSingleton<IBasicConnectorBinding, AutocadBasicConnectorBinding>();
|
||||
serviceCollection.AddSingleton<IBinding, ConfigBinding>();
|
||||
builder.AddSingleton<IBinding, TestBinding>();
|
||||
builder.AddSingleton<IBinding, AccountBinding>();
|
||||
builder.AddSingleton<IBinding, AutocadSelectionBinding>();
|
||||
builder
|
||||
.ContainerBuilder.RegisterType<AutocadBasicConnectorBinding>()
|
||||
.As<IBinding>()
|
||||
.As<IBasicConnectorBinding>()
|
||||
.SingleInstance();
|
||||
|
||||
//Top Level ExceptionHandler
|
||||
builder.ContainerBuilder.RegisterType<TopLevelExceptionHandlerBinding>().As<IBinding>().AsSelf().SingleInstance();
|
||||
builder.AddSingleton<ITopLevelExceptionHandler>(c =>
|
||||
c.Resolve<TopLevelExceptionHandlerBinding>().Parent.TopLevelExceptionHandler
|
||||
);
|
||||
}
|
||||
|
||||
public static void LoadSend(this IServiceCollection serviceCollection)
|
||||
public static void LoadSend(SpeckleContainerBuilder builder)
|
||||
{
|
||||
// Operations
|
||||
serviceCollection.AddScoped<SendOperation<AutocadRootObject>>();
|
||||
builder.AddScoped<SendOperation<AutocadRootObject>>();
|
||||
|
||||
// Object Builders
|
||||
builder.AddScoped<IRootObjectBuilder<AutocadRootObject>, AutocadRootObjectBuilder>();
|
||||
|
||||
// Register bindings
|
||||
builder.AddSingleton<IBinding, AutocadSendBinding>();
|
||||
|
||||
// register send filters
|
||||
serviceCollection.AddTransient<ISendFilter, AutocadSelectionFilter>();
|
||||
builder.AddTransient<ISendFilter, AutocadSelectionFilter>();
|
||||
|
||||
// register send conversion cache
|
||||
serviceCollection.AddSingleton<ISendConversionCache, SendConversionCache>();
|
||||
serviceCollection.AddScoped<
|
||||
builder.AddSingleton<ISendConversionCache, SendConversionCache>();
|
||||
builder.AddScoped<
|
||||
IInstanceObjectsManager<AutocadRootObject, List<Entity>>,
|
||||
InstanceObjectsManager<AutocadRootObject, List<Entity>>
|
||||
>();
|
||||
builder.AddScoped<AutocadInstanceObjectManager>();
|
||||
}
|
||||
|
||||
public static void LoadReceive(this IServiceCollection serviceCollection)
|
||||
public static void LoadReceive(SpeckleContainerBuilder builder)
|
||||
{
|
||||
// traversal
|
||||
serviceCollection.AddSingleton(DefaultTraversal.CreateTraversalFunc());
|
||||
builder.AddSingleton(DefaultTraversal.CreateTraversalFunc());
|
||||
|
||||
// Object Builders
|
||||
serviceCollection.AddScoped<IHostObjectBuilder, AutocadHostObjectBuilder>();
|
||||
builder.AddScoped<IHostObjectBuilder, AutocadHostObjectBuilder>();
|
||||
|
||||
// Register bindings
|
||||
serviceCollection.AddSingleton<IBinding, AutocadReceiveBinding>();
|
||||
builder.AddSingleton<IBinding, AutocadReceiveBinding>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,7 @@ namespace Speckle.Connectors.Autocad.Filters;
|
||||
|
||||
public class AutocadSelectionFilter : DirectSelectionSendFilter
|
||||
{
|
||||
public AutocadSelectionFilter()
|
||||
{
|
||||
IsDefault = true;
|
||||
}
|
||||
public override List<string> GetObjectIds() => SelectedObjectIds;
|
||||
|
||||
public override List<string> RefreshObjectIds() => SelectedObjectIds;
|
||||
public override bool CheckExpiry(string[] changedObjectIds) => SelectedObjectIds.Intersect(changedObjectIds).Any();
|
||||
}
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
using Autodesk.AutoCAD.Colors;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.InterfaceGenerator;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Models.Proxies;
|
||||
using Speckle.Sdk.Pipelines.Progress;
|
||||
using AutocadColor = Autodesk.AutoCAD.Colors.Color;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// Expects to be a scoped dependency for a given operation and helps with layer creation and cleanup.
|
||||
/// </summary>
|
||||
[GenerateAutoInterface]
|
||||
public class AutocadColorBaker(ILogger<AutocadColorBaker> logger) : IAutocadColorBaker
|
||||
{
|
||||
/// <summary>
|
||||
/// For receive operations
|
||||
/// </summary>
|
||||
public Dictionary<string, AutocadColor> ObjectColorsIdMap { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Parse Color Proxies and stores in ObjectColorIdMap the relationship between object ids and colors
|
||||
/// </summary>
|
||||
/// <param name="colorProxies"></param>
|
||||
/// <param name="onOperationProgressed"></param>
|
||||
public void ParseColors(IReadOnlyCollection<ColorProxy> colorProxies, IProgress<CardProgress> onOperationProgressed)
|
||||
{
|
||||
var count = 0;
|
||||
foreach (ColorProxy colorProxy in colorProxies)
|
||||
{
|
||||
try
|
||||
{
|
||||
onOperationProgressed.Report(new("Converting colors", (double)++count / colorProxies.Count));
|
||||
|
||||
// skip any colors with source = layer, since object color default source is by layer
|
||||
if (colorProxy["source"] is string source && source == "layer")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (string objectId in colorProxy.objects)
|
||||
{
|
||||
AutocadColor convertedColor = ConvertColorProxyToColor(colorProxy);
|
||||
#if NET8_0
|
||||
ObjectColorsIdMap.TryAdd(objectId, convertedColor);
|
||||
#else
|
||||
if (!ObjectColorsIdMap.ContainsKey(objectId))
|
||||
{
|
||||
ObjectColorsIdMap.Add(objectId, convertedColor);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
logger.LogError(ex, "Failed parsing color proxy");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private AutocadColor ConvertColorProxyToColor(ColorProxy colorProxy)
|
||||
{
|
||||
// if source = block, return a default ByBlock color
|
||||
if (colorProxy["source"] is string source && source == "block")
|
||||
{
|
||||
return AutocadColor.FromColorIndex(ColorMethod.ByBlock, 0);
|
||||
}
|
||||
|
||||
return colorProxy["autocadColorIndex"] is long index
|
||||
? AutocadColor.FromColorIndex(ColorMethod.ByAci, (short)index)
|
||||
: AutocadColor.FromColor(System.Drawing.Color.FromArgb(colorProxy.value));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
using Autodesk.AutoCAD.Colors;
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Sdk.Models.Instances;
|
||||
using Speckle.Sdk.Models.Proxies;
|
||||
using AutocadColor = Autodesk.AutoCAD.Colors.Color;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// Expects to be a scoped dependency for a given operation and helps with layer creation and cleanup.
|
||||
/// </summary>
|
||||
public class AutocadColorManager
|
||||
{
|
||||
// POC: Will be addressed to move it into AutocadContext!
|
||||
private Document Doc => Application.DocumentManager.MdiActiveDocument;
|
||||
|
||||
/// <summary>
|
||||
/// For receive operations
|
||||
/// </summary>
|
||||
public Dictionary<string, AutocadColor> ObjectColorsIdMap { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// For send operations
|
||||
/// </summary>
|
||||
private Dictionary<string, ColorProxy> ColorProxies { get; } = new();
|
||||
private readonly Dictionary<string, AutocadColor> _layerColorDict = new(); // keeps track of layer colors for object inheritance
|
||||
private readonly Dictionary<string, string> _objectsByLayerDict = new(); // keeps track of ids for all objects that inherited their color by layer
|
||||
|
||||
/// <summary>
|
||||
/// Processes an object's color and adds the object id to a color proxy in <see cref="ColorProxies"/> if object color is set ByAci, ByColor, or ByBlock.
|
||||
/// Otherwise, stores the object id and color in a corresponding ByLayer dictionary for further processing block definitions after all objects are converted.
|
||||
/// From testing, a definition object will inherit its layer's color if by layer, otherwise it will inherit the instance color settings (which we are sending with the instance).
|
||||
/// Skips processing ByPen for now, because I don't understand what this means.
|
||||
/// </summary>
|
||||
/// <param name="objectId"></param>
|
||||
/// <param name="color"></param>
|
||||
private void ProcessObjectColor(string objectId, AutocadColor color, string? layerId = null)
|
||||
{
|
||||
switch (color.ColorMethod)
|
||||
{
|
||||
case ColorMethod.ByAci:
|
||||
case ColorMethod.ByColor:
|
||||
case ColorMethod.ByBlock:
|
||||
AddObjectIdToColorProxy(objectId, color);
|
||||
break;
|
||||
case ColorMethod.ByLayer:
|
||||
if (layerId != null)
|
||||
{
|
||||
#if NET8_0
|
||||
_objectsByLayerDict.TryAdd(objectId, layerId);
|
||||
#else
|
||||
if (!_objectsByLayerDict.ContainsKey(objectId))
|
||||
{
|
||||
_objectsByLayerDict.Add(objectId, layerId);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case ColorMethod.ByPen: // POC: no idea what this means
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void AddObjectIdToColorProxy(string objectId, AutocadColor color)
|
||||
{
|
||||
string colorId = color.GetSpeckleApplicationId();
|
||||
if (ColorProxies.TryGetValue(colorId, out ColorProxy? proxy))
|
||||
{
|
||||
proxy.objects.Add(objectId);
|
||||
}
|
||||
else
|
||||
{
|
||||
ColorProxy newColor = ConvertColorToColorProxy(color);
|
||||
newColor.objects.Add(objectId);
|
||||
ColorProxies[colorId] = newColor;
|
||||
}
|
||||
}
|
||||
|
||||
private ColorProxy ConvertColorToColorProxy(AutocadColor color)
|
||||
{
|
||||
int argb = color.ColorValue.ToArgb();
|
||||
string name = color.ColorNameForDisplay;
|
||||
string id = color.GetSpeckleApplicationId();
|
||||
|
||||
ColorProxy colorProxy = new(argb, id, name) { objects = new() };
|
||||
|
||||
// add the color source as well for receiving in other apps
|
||||
// POC: in order to support full fidelity color support across autocad and rhino, we need to keep track of the color source property. Not sure if this is the best place to keep track of the source, vs on a ColorSourceProxy or as a property on the atomic object.
|
||||
colorProxy["source"] = color.IsByBlock
|
||||
? "block"
|
||||
: color.IsByLayer
|
||||
? "layer"
|
||||
: "object";
|
||||
|
||||
// set additional properties if by aci or by block
|
||||
// ByBlock colors for some reason do not have their color value set to the correct color (white): instead it's a near-black
|
||||
// ByACI is an Autocad internal index for set rgb values, which effects name presentation, see: https://gohtx.com/acadcolors.php
|
||||
if (color.IsByAci)
|
||||
{
|
||||
colorProxy["autocadColorIndex"] = (int)color.ColorIndex;
|
||||
}
|
||||
else if (color.IsByBlock)
|
||||
{
|
||||
colorProxy.value = -1;
|
||||
}
|
||||
|
||||
return colorProxy;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes colors for definition objects that had their colors inherited. This method is in place primarily to process complex color inheritance in blocks.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// We are **always setting the color** (treating it as ColorMethod.ByColor) for definition objects with color "ByLayer" because this overrides instance color, to guarantee they look correct in the viewer and when receiving.
|
||||
/// </remarks>
|
||||
public void ProcessDefinitionObjects(List<InstanceDefinitionProxy> definitions)
|
||||
{
|
||||
// process all definition objects, while removing process objects from the by block color dict as necessary
|
||||
foreach (InstanceDefinitionProxy definition in definitions)
|
||||
{
|
||||
foreach (string objectId in definition.objects)
|
||||
{
|
||||
if (_objectsByLayerDict.TryGetValue(objectId, out string? layerId))
|
||||
{
|
||||
if (_layerColorDict.TryGetValue(layerId, out AutocadColor? layerColor))
|
||||
{
|
||||
AddObjectIdToColorProxy(objectId, layerColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Iterates through a given set of autocad objects, layers, and definitions to collect atomic object colors.
|
||||
/// </summary>
|
||||
/// <param name="unpackedAutocadRootObjects">atomic root objects, including definition objects</param>
|
||||
/// <param name="layers">layers used by atomic objects</param>
|
||||
/// <param name="definitions">definitions used by instances in atomic objects</param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// Due to complications in color inheritance for blocks, we are processing block definition object colors last.
|
||||
/// </remarks>
|
||||
public List<ColorProxy> UnpackColors(
|
||||
List<AutocadRootObject> unpackedAutocadRootObjects,
|
||||
List<LayerTableRecord> layers,
|
||||
List<InstanceDefinitionProxy> definitions
|
||||
)
|
||||
{
|
||||
// Stage 1: unpack colors from objects
|
||||
foreach (AutocadRootObject rootObj in unpackedAutocadRootObjects)
|
||||
{
|
||||
Entity entity = rootObj.Root;
|
||||
ProcessObjectColor(rootObj.ApplicationId, entity.Color, entity.LayerId.ToString());
|
||||
}
|
||||
|
||||
// Stage 2: make sure we collect layer colors as well
|
||||
foreach (LayerTableRecord layer in layers)
|
||||
{
|
||||
ProcessObjectColor(layer.GetSpeckleApplicationId(), layer.Color);
|
||||
_layerColorDict.Add(layer.Id.ToString(), layer.Color);
|
||||
}
|
||||
|
||||
// Stage 3: process definition objects that inherited their colors
|
||||
ProcessDefinitionObjects(definitions);
|
||||
|
||||
return ColorProxies.Values.ToList();
|
||||
}
|
||||
|
||||
public AutocadColor ConvertColorProxyToColor(ColorProxy colorProxy)
|
||||
{
|
||||
// if source = block, return a default ByBlock color
|
||||
if (colorProxy["source"] is string source && source == "block")
|
||||
{
|
||||
return AutocadColor.FromColorIndex(ColorMethod.ByBlock, 0);
|
||||
}
|
||||
|
||||
return colorProxy["autocadColorIndex"] is long index
|
||||
? AutocadColor.FromColorIndex(ColorMethod.ByAci, (short)index)
|
||||
: AutocadColor.FromColor(System.Drawing.Color.FromArgb(colorProxy.value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse Color Proxies and stores in ObjectColorIdMap the relationship between object ids and colors
|
||||
/// </summary>
|
||||
/// <param name="colorProxies"></param>
|
||||
/// <param name="onOperationProgressed"></param>
|
||||
public void ParseColors(List<ColorProxy> colorProxies, Action<string, double?>? onOperationProgressed)
|
||||
{
|
||||
var count = 0;
|
||||
foreach (ColorProxy colorProxy in colorProxies)
|
||||
{
|
||||
onOperationProgressed?.Invoke("Converting colors", (double)++count / colorProxies.Count);
|
||||
|
||||
// skip any colors with source = layer, since object color default source is by layer
|
||||
if (colorProxy["source"] is string source && source == "layer")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (string objectId in colorProxy.objects)
|
||||
{
|
||||
AutocadColor convertedColor = ConvertColorProxyToColor(colorProxy);
|
||||
#if NET8_0
|
||||
ObjectColorsIdMap.TryAdd(objectId, convertedColor);
|
||||
#else
|
||||
if (!ObjectColorsIdMap.ContainsKey(objectId))
|
||||
{
|
||||
ObjectColorsIdMap.Add(objectId, convertedColor);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
using Autodesk.AutoCAD.Colors;
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Models.Proxies;
|
||||
using AutocadColor = Autodesk.AutoCAD.Colors.Color;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// Expects to be a scoped dependency for a given operation and helps with layer creation and cleanup.
|
||||
/// </summary>
|
||||
public class AutocadColorUnpacker
|
||||
{
|
||||
private readonly ILogger<AutocadColorUnpacker> _logger;
|
||||
|
||||
public AutocadColorUnpacker(ILogger<AutocadColorUnpacker> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For send operations
|
||||
/// </summary>
|
||||
private Dictionary<string, ColorProxy> ColorProxies { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Iterates through a given set of autocad objects and layers to collect colors.
|
||||
/// </summary>
|
||||
/// <param name="unpackedAutocadRootObjects">atomic root objects, including instance objects</param>
|
||||
/// <param name="layers">layers used by atomic objects</param>
|
||||
/// <returns></returns>
|
||||
public List<ColorProxy> UnpackColors(
|
||||
List<AutocadRootObject> unpackedAutocadRootObjects,
|
||||
List<LayerTableRecord> layers
|
||||
)
|
||||
{
|
||||
// Stage 1: unpack colors from objects
|
||||
foreach (AutocadRootObject rootObj in unpackedAutocadRootObjects)
|
||||
{
|
||||
try
|
||||
{
|
||||
Entity entity = rootObj.Root;
|
||||
ProcessObjectColor(rootObj.ApplicationId, entity.Color);
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
_logger.LogError(ex, "Failed to unpack colors from Autocad Entity");
|
||||
}
|
||||
}
|
||||
|
||||
// Stage 2: make sure we collect layer colors as well
|
||||
foreach (LayerTableRecord layer in layers)
|
||||
{
|
||||
try
|
||||
{
|
||||
ProcessObjectColor(layer.GetSpeckleApplicationId(), layer.Color);
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
_logger.LogError(ex, "Failed to unpack colors from Autocad Layer");
|
||||
}
|
||||
}
|
||||
|
||||
return ColorProxies.Values.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes an object's color and adds the object id to a color proxy in <see cref="ColorProxies"/> if object color is set ByAci, ByColor, or ByBlock.
|
||||
/// Skips processing ByPen for now, because I don't understand what this means.
|
||||
/// </summary>
|
||||
/// <param name="objectId"></param>
|
||||
/// <param name="color"></param>
|
||||
/// <remarks>Skips processing object colors if it is "ByLayer" since autocad commits are structured by layer and by default sets the color by layer on receive. If this ever changes, then we do need to start processing object colors by layer.</remarks>
|
||||
private void ProcessObjectColor(string objectId, AutocadColor color)
|
||||
{
|
||||
switch (color.ColorMethod)
|
||||
{
|
||||
case ColorMethod.ByAci:
|
||||
case ColorMethod.ByColor:
|
||||
case ColorMethod.ByBlock:
|
||||
AddObjectIdToColorProxy(objectId, color);
|
||||
break;
|
||||
case ColorMethod.ByLayer: // skipping these since autocad commits are structured by layer. Will need to be updated if this ever changes!!
|
||||
case ColorMethod.ByPen: // POC: no idea what this means
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void AddObjectIdToColorProxy(string objectId, AutocadColor color)
|
||||
{
|
||||
string colorId = color.GetSpeckleApplicationId();
|
||||
if (ColorProxies.TryGetValue(colorId, out ColorProxy? proxy))
|
||||
{
|
||||
proxy.objects.Add(objectId);
|
||||
}
|
||||
else
|
||||
{
|
||||
ColorProxy newColor = ConvertColorToColorProxy(color);
|
||||
newColor.objects.Add(objectId);
|
||||
ColorProxies[colorId] = newColor;
|
||||
}
|
||||
}
|
||||
|
||||
private ColorProxy ConvertColorToColorProxy(AutocadColor color)
|
||||
{
|
||||
int argb = color.ColorValue.ToArgb();
|
||||
string name = color.ColorNameForDisplay;
|
||||
string id = color.GetSpeckleApplicationId();
|
||||
|
||||
ColorProxy colorProxy = new()
|
||||
{
|
||||
value = argb,
|
||||
applicationId = id,
|
||||
name = name,
|
||||
objects = new(),
|
||||
};
|
||||
|
||||
// add the color source as well for receiving in other apps
|
||||
// POC: in order to support full fidelity color support across autocad and rhino, we need to keep track of the color source property. Not sure if this is the best place to keep track of the source, vs on a ColorSourceProxy or as a property on the atomic object.
|
||||
colorProxy["source"] =
|
||||
color.IsByBlock ? "block"
|
||||
: color.IsByLayer ? "layer"
|
||||
: "object";
|
||||
|
||||
// set additional properties if by aci or by block
|
||||
// ByBlock colors for some reason do not have their color value set to the correct color (white): instead it's a near-black
|
||||
// ByACI is an Autocad internal index for set rgb values, which effects name presentation, see: https://gohtx.com/acadcolors.php
|
||||
if (color.IsByAci)
|
||||
{
|
||||
colorProxy["autocadColorIndex"] = (int)color.ColorIndex;
|
||||
}
|
||||
else if (color.IsByBlock)
|
||||
{
|
||||
colorProxy.value = -1;
|
||||
}
|
||||
|
||||
return colorProxy;
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,25 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.DUI.Utils;
|
||||
using Speckle.Newtonsoft.Json;
|
||||
using Speckle.Sdk.Common;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
public class AutocadDocumentStore : DocumentModelStore
|
||||
{
|
||||
private const string NULL_DOCUMENT_NAME = "Null Doc";
|
||||
private readonly string _nullDocumentName = "Null Doc";
|
||||
private string _previousDocName;
|
||||
private readonly AutocadDocumentManager _autocadDocumentManager;
|
||||
|
||||
public AutocadDocumentStore(
|
||||
ILogger<DocumentModelStore> logger,
|
||||
IJsonSerializer jsonSerializer,
|
||||
JsonSerializerSettings jsonSerializerSettings,
|
||||
AutocadDocumentManager autocadDocumentManager,
|
||||
ITopLevelExceptionHandler topLevelExceptionHandler
|
||||
)
|
||||
: base(logger, jsonSerializer)
|
||||
: base(jsonSerializerSettings, true)
|
||||
{
|
||||
_autocadDocumentManager = autocadDocumentManager;
|
||||
_previousDocName = NULL_DOCUMENT_NAME;
|
||||
_previousDocName = _nullDocumentName;
|
||||
|
||||
// POC: Will be addressed to move it into AutocadContext!
|
||||
if (Application.DocumentManager.MdiActiveDocument != null)
|
||||
@@ -42,38 +41,39 @@ public class AutocadDocumentStore : DocumentModelStore
|
||||
|
||||
private void OnDocChangeInternal(Document? doc)
|
||||
{
|
||||
var currentDocName = doc != null ? doc.Name : NULL_DOCUMENT_NAME;
|
||||
var currentDocName = doc != null ? doc.Name : _nullDocumentName;
|
||||
if (_previousDocName == currentDocName)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_previousDocName = currentDocName;
|
||||
LoadState();
|
||||
ReadFromFile();
|
||||
OnDocumentChanged();
|
||||
}
|
||||
|
||||
protected override void LoadState()
|
||||
public override void ReadFromFile()
|
||||
{
|
||||
Models = new();
|
||||
|
||||
// POC: Will be addressed to move it into AutocadContext!
|
||||
Document? doc = Application.DocumentManager.MdiActiveDocument;
|
||||
|
||||
if (doc == null)
|
||||
{
|
||||
ClearAndSave();
|
||||
return;
|
||||
}
|
||||
|
||||
string? serializedModelCards = _autocadDocumentManager.ReadModelCards(doc);
|
||||
if (serializedModelCards == null)
|
||||
{
|
||||
ClearAndSave();
|
||||
return;
|
||||
}
|
||||
LoadFromString(serializedModelCards);
|
||||
|
||||
Models = Deserialize(serializedModelCards).NotNull();
|
||||
}
|
||||
|
||||
protected override void HostAppSaveState(string modelCardState)
|
||||
public override void WriteToFile()
|
||||
{
|
||||
// POC: Will be addressed to move it into AutocadContext!
|
||||
Document doc = Application.DocumentManager.MdiActiveDocument;
|
||||
@@ -83,6 +83,7 @@ public class AutocadDocumentStore : DocumentModelStore
|
||||
return;
|
||||
}
|
||||
|
||||
_autocadDocumentManager.WriteModelCards(doc, modelCardState);
|
||||
string modelCardsString = Serialize();
|
||||
_autocadDocumentManager.WriteModelCards(doc, modelCardsString);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Common.Conversion;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Dependencies;
|
||||
using Speckle.Sdk.Models.Proxies;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// This resource expects to be injected "fresh" in each receive operation (scoped lifetime).
|
||||
/// Extracts group information from a set of objects into proxies in send operations; also creates groups from a set of proxies in receive operations.
|
||||
/// TODO: Oguzhan! Check whats happening on second receive unless purge groups? naming etc..
|
||||
/// </summary>
|
||||
public class AutocadGroupBaker
|
||||
{
|
||||
private readonly ILogger<AutocadGroupBaker> _logger;
|
||||
private readonly AutocadContext _autocadContext;
|
||||
|
||||
public AutocadGroupBaker(AutocadContext autocadContext, ILogger<AutocadGroupBaker> logger)
|
||||
{
|
||||
_autocadContext = autocadContext;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates groups in the host app from a set of group proxies. Can be called after the bake operation of all atomic objects (including instances) is complete.
|
||||
/// </summary>
|
||||
/// <param name="groupProxies"></param>
|
||||
/// <param name="applicationIdMap"></param>
|
||||
/// <returns></returns>
|
||||
// TODO: Oguzhan! Do not report here too! But this is TBD that we don't know the shape of the report yet.
|
||||
public IReadOnlyCollection<ReceiveConversionResult> CreateGroups(
|
||||
IEnumerable<GroupProxy> groupProxies,
|
||||
Dictionary<string, IReadOnlyCollection<Entity>> applicationIdMap
|
||||
)
|
||||
{
|
||||
HashSet<ReceiveConversionResult> results = new();
|
||||
|
||||
using var groupCreationTransaction =
|
||||
Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
|
||||
var groupDictionary = (DBDictionary)
|
||||
groupCreationTransaction.GetObject(
|
||||
Application.DocumentManager.CurrentDocument.Database.GroupDictionaryId,
|
||||
OpenMode.ForWrite
|
||||
);
|
||||
|
||||
foreach (var gp in groupProxies.OrderBy(group => group.objects.Count))
|
||||
{
|
||||
try
|
||||
{
|
||||
var entities = gp.objects.SelectMany(oldObjId => applicationIdMap[oldObjId]);
|
||||
var ids = new ObjectIdCollection();
|
||||
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
ids.Add(entity.ObjectId);
|
||||
}
|
||||
|
||||
var groupName = _autocadContext.RemoveInvalidChars(gp.name);
|
||||
var newGroup = new Group(groupName, true); // NOTE: this constructor sets both the description (as it says) but also the name at the same time
|
||||
newGroup.Append(ids);
|
||||
|
||||
groupDictionary.UpgradeOpen();
|
||||
groupDictionary.SetAt(groupName, newGroup);
|
||||
|
||||
groupCreationTransaction.AddNewlyCreatedDBObject(newGroup, true);
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
results.Add(new ReceiveConversionResult(Status.ERROR, gp, null, null, ex));
|
||||
_logger.LogError(ex, "Failed to bake Autocad Group");
|
||||
}
|
||||
}
|
||||
|
||||
groupCreationTransaction.Commit();
|
||||
|
||||
return results.Freeze();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Connectors.Utils.Conversion;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Models.Proxies;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// This resource expects to be injected "fresh" in each send/receive operation (scoped lifetime). Extracts group information from a set of objects into proxies in send operations; also creates groups from a set of proxies in receive operations.
|
||||
/// </summary>
|
||||
public class AutocadGroupManager
|
||||
{
|
||||
private readonly AutocadContext _autocadContext;
|
||||
|
||||
public AutocadGroupManager(AutocadContext autocadContext)
|
||||
{
|
||||
_autocadContext = autocadContext;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unpacks a selection of atomic objects into their groups
|
||||
/// </summary>
|
||||
/// <param name="autocadObjects"></param>
|
||||
/// <returns></returns>
|
||||
public List<GroupProxy> UnpackGroups(IEnumerable<AutocadRootObject> autocadObjects)
|
||||
{
|
||||
var groupProxies = new Dictionary<string, GroupProxy>();
|
||||
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
|
||||
foreach (var (dbObject, applicationId) in autocadObjects)
|
||||
{
|
||||
var persistentReactorIds = dbObject.GetPersistentReactorIds();
|
||||
foreach (ObjectId oReactorId in persistentReactorIds)
|
||||
{
|
||||
var obj = transaction.GetObject(oReactorId, OpenMode.ForRead);
|
||||
if (obj is not Group group)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var groupAppId = group.GetSpeckleApplicationId();
|
||||
if (groupProxies.TryGetValue(groupAppId, out GroupProxy? groupProxy))
|
||||
{
|
||||
groupProxy.objects.Add(applicationId);
|
||||
}
|
||||
else
|
||||
{
|
||||
groupProxies[groupAppId] = new()
|
||||
{
|
||||
applicationId = groupAppId,
|
||||
name = group.Name,
|
||||
objects = [applicationId]
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return groupProxies.Values.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates groups in the host app from a set of group proxies. Can be called after the bake operation of all atomic objects (including instances) is complete.
|
||||
/// </summary>
|
||||
/// <param name="groupProxies"></param>
|
||||
/// <param name="applicationIdMap"></param>
|
||||
/// <returns></returns>
|
||||
public List<ReceiveConversionResult> CreateGroups(
|
||||
IEnumerable<GroupProxy> groupProxies,
|
||||
Dictionary<string, List<Entity>> applicationIdMap
|
||||
)
|
||||
{
|
||||
List<ReceiveConversionResult> results = new();
|
||||
|
||||
using var groupCreationTransaction =
|
||||
Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
|
||||
var groupDictionary = (DBDictionary)
|
||||
groupCreationTransaction.GetObject(
|
||||
Application.DocumentManager.CurrentDocument.Database.GroupDictionaryId,
|
||||
OpenMode.ForWrite
|
||||
);
|
||||
|
||||
foreach (var gp in groupProxies.OrderBy(group => group.objects.Count))
|
||||
{
|
||||
try
|
||||
{
|
||||
var entities = gp.objects.SelectMany(oldObjId => applicationIdMap[oldObjId]);
|
||||
var ids = new ObjectIdCollection();
|
||||
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
ids.Add(entity.ObjectId);
|
||||
}
|
||||
|
||||
var groupName = _autocadContext.RemoveInvalidChars(gp.name);
|
||||
var newGroup = new Group(groupName, true); // NOTE: this constructor sets both the description (as it says) but also the name at the same time
|
||||
newGroup.Append(ids);
|
||||
|
||||
groupDictionary.UpgradeOpen();
|
||||
groupDictionary.SetAt(groupName, newGroup);
|
||||
|
||||
groupCreationTransaction.AddNewlyCreatedDBObject(newGroup, true);
|
||||
}
|
||||
catch (Exception e) when (!e.IsFatal())
|
||||
{
|
||||
results.Add(new ReceiveConversionResult(Status.ERROR, gp, null, null, e));
|
||||
}
|
||||
}
|
||||
|
||||
groupCreationTransaction.Commit();
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Models.Proxies;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// This resource expects to be injected "fresh" in each send/receive operation (scoped lifetime). Extracts group information from a set of objects into proxies in send operations; also creates groups from a set of proxies in receive operations.
|
||||
/// </summary>
|
||||
public class AutocadGroupUnpacker
|
||||
{
|
||||
private readonly ILogger<AutocadGroupUnpacker> _logger;
|
||||
|
||||
public AutocadGroupUnpacker(ILogger<AutocadGroupUnpacker> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unpacks a selection of atomic objects into their groups
|
||||
/// </summary>
|
||||
/// <param name="autocadObjects"></param>
|
||||
/// <returns></returns>
|
||||
public List<GroupProxy> UnpackGroups(IEnumerable<AutocadRootObject> autocadObjects)
|
||||
{
|
||||
var groupProxies = new Dictionary<string, GroupProxy>();
|
||||
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
|
||||
foreach (var (dbObject, applicationId) in autocadObjects)
|
||||
{
|
||||
try
|
||||
{
|
||||
var persistentReactorIds = dbObject.GetPersistentReactorIds();
|
||||
foreach (ObjectId oReactorId in persistentReactorIds)
|
||||
{
|
||||
var obj = transaction.GetObject(oReactorId, OpenMode.ForRead);
|
||||
if (obj is not Group group)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var groupAppId = group.GetSpeckleApplicationId();
|
||||
if (groupProxies.TryGetValue(groupAppId, out GroupProxy? groupProxy))
|
||||
{
|
||||
groupProxy.objects.Add(applicationId);
|
||||
}
|
||||
else
|
||||
{
|
||||
groupProxies[groupAppId] = new()
|
||||
{
|
||||
applicationId = groupAppId,
|
||||
name = group.Name,
|
||||
objects = [applicationId],
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
_logger.LogError(ex, "Failed on unpacking Autocad group");
|
||||
}
|
||||
}
|
||||
|
||||
return groupProxies.Values.ToList();
|
||||
}
|
||||
}
|
||||
@@ -3,17 +3,23 @@ using Speckle.InterfaceGenerator;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
public partial interface IAutocadIdleManager : IAppIdleManager;
|
||||
|
||||
[GenerateAutoInterface]
|
||||
public sealed class AutocadIdleManager(IIdleCallManager idleCallManager)
|
||||
: AppIdleManager(idleCallManager),
|
||||
IAutocadIdleManager
|
||||
public class AutocadIdleManager(IIdleCallManager idleCallManager) : IAutocadIdleManager
|
||||
{
|
||||
private readonly IIdleCallManager _idleCallManager = idleCallManager;
|
||||
|
||||
protected override void AddEvent() => Application.Idle += AutocadAppOnIdle;
|
||||
/// <summary>
|
||||
/// Subscribe deferred action to AutocadIdle event to run it whenever Autocad become idle.
|
||||
/// </summary>
|
||||
/// <param name="action"> Action to call whenever Autocad become Idle.</param>
|
||||
public void SubscribeToIdle(string id, Action action) =>
|
||||
idleCallManager.SubscribeToIdle(
|
||||
id,
|
||||
action,
|
||||
() =>
|
||||
{
|
||||
Application.Idle += AutocadAppOnIdle;
|
||||
}
|
||||
);
|
||||
|
||||
private void AutocadAppOnIdle(object? sender, EventArgs e) =>
|
||||
_idleCallManager.AppOnIdle(() => Application.Idle -= AutocadAppOnIdle);
|
||||
idleCallManager.AppOnIdle(() => Application.Idle -= AutocadAppOnIdle);
|
||||
}
|
||||
|
||||
@@ -1,297 +0,0 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Autodesk.AutoCAD.Geometry;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Common.Conversion;
|
||||
using Speckle.Connectors.Common.Instances;
|
||||
using Speckle.Converters.Autocad;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.DoubleNumerics;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Common;
|
||||
using Speckle.Sdk.Common.Exceptions;
|
||||
using Speckle.Sdk.Dependencies;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using Speckle.Sdk.Models.Instances;
|
||||
using Speckle.Sdk.Pipelines.Progress;
|
||||
using AutocadColor = Autodesk.AutoCAD.Colors.Color;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// Expects to be a scoped dependency receive operation.
|
||||
/// </summary>
|
||||
public class AutocadInstanceBaker : IInstanceBaker<IReadOnlyCollection<Entity>>
|
||||
{
|
||||
private readonly AutocadLayerBaker _layerBaker;
|
||||
private readonly IAutocadColorBaker _colorBaker;
|
||||
private readonly IAutocadMaterialBaker _materialBaker;
|
||||
private readonly AutocadContext _autocadContext;
|
||||
private readonly ILogger<AutocadInstanceBaker> _logger;
|
||||
private readonly IConverterSettingsStore<AutocadConversionSettings> _converterSettings;
|
||||
|
||||
public AutocadInstanceBaker(
|
||||
AutocadLayerBaker layerBaker,
|
||||
IAutocadColorBaker colorBaker,
|
||||
IAutocadMaterialBaker materialBaker,
|
||||
AutocadContext autocadContext,
|
||||
ILogger<AutocadInstanceBaker> logger,
|
||||
IConverterSettingsStore<AutocadConversionSettings> converterSettings
|
||||
)
|
||||
{
|
||||
_layerBaker = layerBaker;
|
||||
_colorBaker = colorBaker;
|
||||
_materialBaker = materialBaker;
|
||||
_autocadContext = autocadContext;
|
||||
_logger = logger;
|
||||
_converterSettings = converterSettings;
|
||||
}
|
||||
|
||||
[SuppressMessage("Maintainability", "CA1506:Avoid excessive class coupling")]
|
||||
public BakeResult BakeInstances(
|
||||
ICollection<(Collection[] collectionPath, IInstanceComponent obj)> instanceComponents,
|
||||
Dictionary<string, IReadOnlyCollection<Entity>> applicationIdMap,
|
||||
string baseLayerName,
|
||||
IProgress<CardProgress> onOperationProgressed
|
||||
)
|
||||
{
|
||||
var sortedInstanceComponents = instanceComponents
|
||||
.OrderByDescending(x => x.obj.maxDepth) // Sort by max depth, so we start baking from the deepest element first
|
||||
.ThenBy(x => x.obj is InstanceDefinitionProxy ? 0 : 1) // Ensure we bake the deepest definition first, then any instances that depend on it
|
||||
.ToList();
|
||||
|
||||
var definitionIdAndApplicationIdMap = new Dictionary<string, ObjectId>();
|
||||
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
var conversionResults = new HashSet<ReceiveConversionResult>();
|
||||
var createdObjectIds = new HashSet<string>();
|
||||
var consumedObjectIds = new HashSet<string>();
|
||||
var count = 0;
|
||||
|
||||
foreach (var (collectionPath, instanceOrDefinition) in sortedInstanceComponents)
|
||||
{
|
||||
try
|
||||
{
|
||||
onOperationProgressed.Report(new("Converting blocks", (double)++count / sortedInstanceComponents.Count));
|
||||
|
||||
if (instanceOrDefinition is InstanceDefinitionProxy { applicationId: not null } definitionProxy)
|
||||
{
|
||||
// TODO: create definition (block table record)
|
||||
var constituentEntities = definitionProxy
|
||||
.objects.Select(id =>
|
||||
applicationIdMap.TryGetValue(id, out IReadOnlyCollection<Entity>? value) ? value : null
|
||||
)
|
||||
.Where(x => x is not null)
|
||||
.SelectMany(ent => ent!)
|
||||
.ToList();
|
||||
|
||||
var record = new BlockTableRecord();
|
||||
var objectIds = new ObjectIdCollection();
|
||||
// We're expecting to have Name prop always for definitions. If there is an edge case, ask to Dim or Ogu
|
||||
record.Name = _autocadContext.RemoveInvalidChars(
|
||||
$"{definitionProxy.name}-({definitionProxy.applicationId})-{baseLayerName}"
|
||||
);
|
||||
|
||||
foreach (var entity in constituentEntities)
|
||||
{
|
||||
objectIds.Add(entity.ObjectId);
|
||||
}
|
||||
|
||||
if (constituentEntities.Count == 0)
|
||||
{
|
||||
throw new ConversionException("No objects found to create instance definition.");
|
||||
}
|
||||
|
||||
using var blockTable = (BlockTable)
|
||||
transaction.GetObject(Application.DocumentManager.CurrentDocument.Database.BlockTableId, OpenMode.ForWrite);
|
||||
var id = blockTable.Add(record);
|
||||
record.AssumeOwnershipOf(objectIds);
|
||||
|
||||
definitionIdAndApplicationIdMap[definitionProxy.applicationId] = id;
|
||||
transaction.AddNewlyCreatedDBObject(record, true);
|
||||
var consumedEntitiesHandleValues = constituentEntities.Select(ent => ent.GetSpeckleApplicationId()).ToArray();
|
||||
consumedObjectIds.UnionWith(consumedEntitiesHandleValues);
|
||||
createdObjectIds.RemoveWhere(newId => consumedEntitiesHandleValues.Contains(newId));
|
||||
}
|
||||
else if (
|
||||
instanceOrDefinition is InstanceProxy instanceProxy
|
||||
&& definitionIdAndApplicationIdMap.TryGetValue(instanceProxy.definitionId, out ObjectId definitionId)
|
||||
)
|
||||
{
|
||||
var matrix3d = GetMatrix3d(instanceProxy.transform, instanceProxy.units);
|
||||
var insertionPoint = Point3d.Origin.TransformBy(matrix3d);
|
||||
|
||||
var modelSpaceBlockTableRecord = Application.DocumentManager.CurrentDocument.Database.GetModelSpace(
|
||||
OpenMode.ForWrite
|
||||
);
|
||||
|
||||
// POC: collectionPath for instances should be an array of size 1, because we are flattening collections on traversal
|
||||
string layerName = _layerBaker.CreateLayerForReceive(collectionPath, baseLayerName);
|
||||
|
||||
// get color and material if any
|
||||
string instanceId = instanceProxy.applicationId ?? instanceProxy.id.NotNull();
|
||||
AutocadColor? objColor = _colorBaker.ObjectColorsIdMap.TryGetValue(instanceId, out AutocadColor? color)
|
||||
? color
|
||||
: null;
|
||||
ObjectId objMaterial = _materialBaker.ObjectMaterialsIdMap.TryGetValue(instanceId, out ObjectId matId)
|
||||
? matId
|
||||
: ObjectId.Null;
|
||||
|
||||
BlockReference blockRef = new(insertionPoint, definitionId) { BlockTransform = matrix3d, Layer = layerName };
|
||||
|
||||
if (objColor is not null)
|
||||
{
|
||||
blockRef.Color = objColor;
|
||||
}
|
||||
|
||||
if (objMaterial != ObjectId.Null)
|
||||
{
|
||||
blockRef.MaterialId = objMaterial;
|
||||
}
|
||||
|
||||
modelSpaceBlockTableRecord.AppendEntity(blockRef);
|
||||
|
||||
applicationIdMap[instanceId] = new List<Entity> { blockRef };
|
||||
|
||||
transaction.AddNewlyCreatedDBObject(blockRef, true);
|
||||
conversionResults.Add(
|
||||
new(Status.SUCCESS, instanceProxy, blockRef.GetSpeckleApplicationId(), "Instance (Block)")
|
||||
);
|
||||
createdObjectIds.Add(blockRef.GetSpeckleApplicationId());
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
_logger.LogError(ex, "Failed to create an instance from proxy");
|
||||
conversionResults.Add(new(Status.ERROR, instanceOrDefinition as Base ?? new Base(), null, null, ex));
|
||||
}
|
||||
}
|
||||
|
||||
transaction.Commit();
|
||||
return new(createdObjectIds.Freeze(), consumedObjectIds.Freeze(), conversionResults.Freeze());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleans up any previously created instances.
|
||||
/// POC: This function will not be able to delete block definitions if the user creates a new one composed out of received definitions.
|
||||
/// </summary>
|
||||
/// <param name="namePrefix"></param>
|
||||
public void PurgeInstances(string namePrefix)
|
||||
{
|
||||
namePrefix = _autocadContext.RemoveInvalidChars(namePrefix);
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
var instanceDefinitionsToDelete = new Dictionary<string, BlockTableRecord>();
|
||||
|
||||
// Helper function that recurses through a given block table record's constituent objects and purges inner instances as required.
|
||||
void TraverseAndClean(BlockTableRecord btr)
|
||||
{
|
||||
foreach (var objectId in btr)
|
||||
{
|
||||
var obj = transaction.GetObject(objectId, OpenMode.ForRead) as BlockReference;
|
||||
if (obj == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var definition = (BlockTableRecord)transaction.GetObject(obj.BlockTableRecord, OpenMode.ForRead);
|
||||
if (obj.IsErased)
|
||||
{
|
||||
TraverseAndClean(definition);
|
||||
continue;
|
||||
}
|
||||
|
||||
obj.UpgradeOpen();
|
||||
obj.Erase();
|
||||
TraverseAndClean(definition);
|
||||
instanceDefinitionsToDelete[obj.BlockTableRecord.ToString()] = definition;
|
||||
}
|
||||
}
|
||||
|
||||
using var blockTable = (BlockTable)
|
||||
transaction.GetObject(Application.DocumentManager.CurrentDocument.Database.BlockTableId, OpenMode.ForRead);
|
||||
|
||||
// deep clean definitions
|
||||
foreach (var btrId in blockTable)
|
||||
{
|
||||
var btr = (BlockTableRecord)transaction.GetObject(btrId, OpenMode.ForRead);
|
||||
if (btr.Name.Contains(namePrefix)) // POC: this is tightly coupled with a naming convention for definitions in the instance object manager
|
||||
{
|
||||
TraverseAndClean(btr);
|
||||
instanceDefinitionsToDelete[btr.Name] = btr;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var def in instanceDefinitionsToDelete.Values)
|
||||
{
|
||||
def.UpgradeOpen();
|
||||
def.Erase();
|
||||
}
|
||||
|
||||
transaction.Commit();
|
||||
}
|
||||
|
||||
private Matrix3d GetMatrix3d(Matrix4x4 matrix, string units)
|
||||
{
|
||||
var sf = Units.GetConversionFactor(units, _converterSettings.Current.SpeckleUnits);
|
||||
|
||||
var scaledTransform = new[]
|
||||
{
|
||||
matrix.M11,
|
||||
matrix.M12,
|
||||
matrix.M13,
|
||||
matrix.M14 * sf,
|
||||
matrix.M21,
|
||||
matrix.M22,
|
||||
matrix.M23,
|
||||
matrix.M24 * sf,
|
||||
matrix.M31,
|
||||
matrix.M32,
|
||||
matrix.M33,
|
||||
matrix.M34 * sf,
|
||||
matrix.M41,
|
||||
matrix.M42,
|
||||
matrix.M43,
|
||||
matrix.M44,
|
||||
};
|
||||
|
||||
var m3d = new Matrix3d(scaledTransform);
|
||||
if (!m3d.IsScaledOrtho())
|
||||
{
|
||||
m3d = new Matrix3d(MakePerpendicular(m3d));
|
||||
}
|
||||
|
||||
return m3d;
|
||||
}
|
||||
|
||||
// https://forums.autodesk.com/t5/net/set-blocktransform-values/m-p/6452121#M49479
|
||||
private double[] MakePerpendicular(Matrix3d matrix)
|
||||
{
|
||||
// Get the basis vectors of the matrix
|
||||
Vector3d right = new(matrix[0, 0], matrix[1, 0], matrix[2, 0]);
|
||||
Vector3d up = new(matrix[0, 1], matrix[1, 1], matrix[2, 1]);
|
||||
|
||||
Vector3d newForward = right.CrossProduct(up).GetNormal();
|
||||
Vector3d newUp = newForward.CrossProduct(right).GetNormal();
|
||||
|
||||
return
|
||||
[
|
||||
right.X,
|
||||
newUp.X,
|
||||
newForward.X,
|
||||
matrix[0, 3],
|
||||
right.Y,
|
||||
newUp.Y,
|
||||
newForward.Y,
|
||||
matrix[1, 3],
|
||||
right.Z,
|
||||
newUp.Z,
|
||||
newForward.Z,
|
||||
matrix[2, 3],
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
matrix[3, 3],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,437 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Autodesk.AutoCAD.Geometry;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Connectors.Utils.Conversion;
|
||||
using Speckle.Connectors.Utils.Instances;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.DoubleNumerics;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Common;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using Speckle.Sdk.Models.Instances;
|
||||
using AutocadColor = Autodesk.AutoCAD.Colors.Color;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// Expects to be a scoped dependency per send or receive operation.
|
||||
/// POC: Split later unpacker and baker.
|
||||
/// </summary>
|
||||
public class AutocadInstanceObjectManager : IInstanceUnpacker<AutocadRootObject>, IInstanceBaker<List<Entity>>
|
||||
{
|
||||
private readonly AutocadLayerManager _autocadLayerManager;
|
||||
private readonly AutocadColorManager _autocadColorManager;
|
||||
private readonly AutocadMaterialManager _autocadMaterialManager;
|
||||
private readonly IHostToSpeckleUnitConverter<UnitsValue> _unitsConverter;
|
||||
private readonly AutocadContext _autocadContext;
|
||||
|
||||
private readonly IInstanceObjectsManager<AutocadRootObject, List<Entity>> _instanceObjectsManager;
|
||||
|
||||
public AutocadInstanceObjectManager(
|
||||
AutocadLayerManager autocadLayerManager,
|
||||
AutocadColorManager autocadColorManager,
|
||||
AutocadMaterialManager autocadMaterialManager,
|
||||
IHostToSpeckleUnitConverter<UnitsValue> unitsConverter,
|
||||
AutocadContext autocadContext,
|
||||
IInstanceObjectsManager<AutocadRootObject, List<Entity>> instanceObjectsManager
|
||||
)
|
||||
{
|
||||
_autocadLayerManager = autocadLayerManager;
|
||||
_autocadColorManager = autocadColorManager;
|
||||
_autocadMaterialManager = autocadMaterialManager;
|
||||
_unitsConverter = unitsConverter;
|
||||
_autocadContext = autocadContext;
|
||||
_instanceObjectsManager = instanceObjectsManager;
|
||||
}
|
||||
|
||||
public UnpackResult<AutocadRootObject> UnpackSelection(IEnumerable<AutocadRootObject> objects)
|
||||
{
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
|
||||
foreach (var obj in objects)
|
||||
{
|
||||
// Note: isDynamicBlock always returns false for a selection of doc objects. Instances of dynamic blocks are represented in the document as blocks that have
|
||||
// a definition reference to the anonymous block table record.
|
||||
if (obj.Root is BlockReference blockReference && !blockReference.IsDynamicBlock)
|
||||
{
|
||||
UnpackInstance(blockReference, 0, transaction);
|
||||
}
|
||||
_instanceObjectsManager.AddAtomicObject(obj.ApplicationId, obj);
|
||||
}
|
||||
return _instanceObjectsManager.GetUnpackResult();
|
||||
}
|
||||
|
||||
private void UnpackInstance(BlockReference instance, int depth, Transaction transaction)
|
||||
{
|
||||
string instanceId = instance.GetSpeckleApplicationId();
|
||||
|
||||
// If this instance has a reference to an anonymous block, it means it's spawned from a dynamic block. Anonymous blocks are
|
||||
// used to represent specific "instances" of dynamic ones.
|
||||
// We do not want to send the full dynamic block definition, but its current "instance", as such here we're making sure we
|
||||
// take up the anon block table reference definition (if it exists). If it's not an instance of a dynamic block, we're
|
||||
// using the normal def reference.
|
||||
ObjectId definitionId = !instance.AnonymousBlockTableRecord.IsNull
|
||||
? instance.AnonymousBlockTableRecord
|
||||
: instance.BlockTableRecord;
|
||||
|
||||
InstanceProxy instanceProxy =
|
||||
new()
|
||||
{
|
||||
applicationId = instanceId,
|
||||
definitionId = definitionId.ToString(),
|
||||
maxDepth = depth,
|
||||
transform = GetMatrix(instance.BlockTransform.ToArray()),
|
||||
units = _unitsConverter.ConvertOrThrow(Application.DocumentManager.CurrentDocument.Database.Insunits)
|
||||
};
|
||||
_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.
|
||||
// This will enable on receive to create them in the correct order (descending by max depth, interleaved definitions and instances).
|
||||
// We need to interleave the creation of definitions and instances, as some definitions may depend on instances.
|
||||
if (
|
||||
!_instanceObjectsManager.TryGetInstanceProxiesFromDefinitionId(
|
||||
definitionId.ToString(),
|
||||
out List<InstanceProxy> instanceProxiesWithSameDefinition
|
||||
)
|
||||
)
|
||||
{
|
||||
instanceProxiesWithSameDefinition = new List<InstanceProxy>();
|
||||
_instanceObjectsManager.AddInstanceProxiesByDefinitionId(
|
||||
definitionId.ToString(),
|
||||
instanceProxiesWithSameDefinition
|
||||
);
|
||||
}
|
||||
|
||||
// We ensure that all previous instance proxies that have the same definition are at this max depth. I kind of have a feeling this can be done more elegantly, but YOLO
|
||||
foreach (var instanceProxyWithSameDefinition in instanceProxiesWithSameDefinition)
|
||||
{
|
||||
if (instanceProxyWithSameDefinition.maxDepth < depth)
|
||||
{
|
||||
instanceProxyWithSameDefinition.maxDepth = depth;
|
||||
}
|
||||
}
|
||||
|
||||
instanceProxiesWithSameDefinition.Add(_instanceObjectsManager.GetInstanceProxy(instanceId));
|
||||
|
||||
if (
|
||||
_instanceObjectsManager.TryGetInstanceDefinitionProxy(definitionId.ToString(), out InstanceDefinitionProxy value)
|
||||
)
|
||||
{
|
||||
int depthDifference = depth - value.maxDepth;
|
||||
if (depthDifference > 0)
|
||||
{
|
||||
// all MaxDepth of children definitions and its instances should be increased with difference of depth
|
||||
_instanceObjectsManager.UpdateChildrenMaxDepth(value, depthDifference);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var definition = (BlockTableRecord)transaction.GetObject(definitionId, OpenMode.ForRead);
|
||||
var definitionProxy = new InstanceDefinitionProxy()
|
||||
{
|
||||
applicationId = definitionId.ToString(),
|
||||
objects = new(),
|
||||
maxDepth = depth,
|
||||
name = !instance.AnonymousBlockTableRecord.IsNull ? "Dynamic instance " + definitionId : definition.Name,
|
||||
["comments"] = definition.Comments
|
||||
};
|
||||
|
||||
// Go through each definition object
|
||||
foreach (ObjectId id in definition)
|
||||
{
|
||||
Entity obj = (Entity)transaction.GetObject(id, OpenMode.ForRead);
|
||||
|
||||
// In the case of dynamic blocks, this prevents sending objects that are not visibile in its current state.
|
||||
if (!obj.Visible)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string appId = obj.GetSpeckleApplicationId();
|
||||
definitionProxy.objects.Add(appId);
|
||||
|
||||
if (obj is BlockReference blockReference)
|
||||
{
|
||||
UnpackInstance(blockReference, depth + 1, transaction);
|
||||
}
|
||||
|
||||
_instanceObjectsManager.AddAtomicObject(appId, new(obj, appId));
|
||||
}
|
||||
|
||||
_instanceObjectsManager.AddDefinitionProxy(definitionId.ToString(), definitionProxy);
|
||||
}
|
||||
|
||||
public BakeResult BakeInstances(
|
||||
List<(Collection[] collectionPath, IInstanceComponent obj)> instanceComponents,
|
||||
Dictionary<string, List<Entity>> applicationIdMap,
|
||||
string baseLayerName,
|
||||
Action<string, double?>? onOperationProgressed
|
||||
)
|
||||
{
|
||||
var sortedInstanceComponents = instanceComponents
|
||||
.OrderByDescending(x => x.obj.maxDepth) // Sort by max depth, so we start baking from the deepest element first
|
||||
.ThenBy(x => x.obj is InstanceDefinitionProxy ? 0 : 1) // Ensure we bake the deepest definition first, then any instances that depend on it
|
||||
.ToList();
|
||||
|
||||
var definitionIdAndApplicationIdMap = new Dictionary<string, ObjectId>();
|
||||
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
var conversionResults = new List<ReceiveConversionResult>();
|
||||
var createdObjectIds = new List<string>();
|
||||
var consumedObjectIds = new List<string>();
|
||||
var count = 0;
|
||||
|
||||
foreach (var (collectionPath, instanceOrDefinition) in sortedInstanceComponents)
|
||||
{
|
||||
try
|
||||
{
|
||||
onOperationProgressed?.Invoke("Converting blocks", (double)++count / sortedInstanceComponents.Count);
|
||||
if (instanceOrDefinition is InstanceDefinitionProxy { applicationId: not null } definitionProxy)
|
||||
{
|
||||
// TODO: create definition (block table record)
|
||||
var constituentEntities = definitionProxy
|
||||
.objects.Select(id => applicationIdMap.TryGetValue(id, out List<Entity>? value) ? value : null)
|
||||
.Where(x => x is not null)
|
||||
.SelectMany(ent => ent!)
|
||||
.ToList();
|
||||
|
||||
var record = new BlockTableRecord();
|
||||
var objectIds = new ObjectIdCollection();
|
||||
// We're expecting to have Name prop always for definitions. If there is an edge case, ask to Dim or Ogu
|
||||
record.Name = _autocadContext.RemoveInvalidChars(
|
||||
$"{definitionProxy.name}-({definitionProxy.applicationId})-{baseLayerName}"
|
||||
);
|
||||
|
||||
foreach (var entity in constituentEntities)
|
||||
{
|
||||
objectIds.Add(entity.ObjectId);
|
||||
}
|
||||
|
||||
if (constituentEntities.Count == 0)
|
||||
{
|
||||
throw new ConversionException("No objects found to create instance definition.");
|
||||
}
|
||||
|
||||
using var blockTable = (BlockTable)
|
||||
transaction.GetObject(Application.DocumentManager.CurrentDocument.Database.BlockTableId, OpenMode.ForWrite);
|
||||
var id = blockTable.Add(record);
|
||||
record.AssumeOwnershipOf(objectIds);
|
||||
|
||||
definitionIdAndApplicationIdMap[definitionProxy.applicationId] = id;
|
||||
transaction.AddNewlyCreatedDBObject(record, true);
|
||||
var consumedEntitiesHandleValues = constituentEntities.Select(ent => ent.GetSpeckleApplicationId()).ToArray();
|
||||
consumedObjectIds.AddRange(consumedEntitiesHandleValues);
|
||||
createdObjectIds.RemoveAll(newId => consumedEntitiesHandleValues.Contains(newId));
|
||||
}
|
||||
else if (
|
||||
instanceOrDefinition is InstanceProxy instanceProxy
|
||||
&& definitionIdAndApplicationIdMap.TryGetValue(instanceProxy.definitionId, out ObjectId definitionId)
|
||||
)
|
||||
{
|
||||
var matrix3d = GetMatrix3d(instanceProxy.transform, instanceProxy.units);
|
||||
var insertionPoint = Point3d.Origin.TransformBy(matrix3d);
|
||||
|
||||
var modelSpaceBlockTableRecord = Application.DocumentManager.CurrentDocument.Database.GetModelSpace(
|
||||
OpenMode.ForWrite
|
||||
);
|
||||
|
||||
// POC: collectionPath for instances should be an array of size 1, because we are flattening collections on traversal
|
||||
string layerName = _autocadLayerManager.CreateLayerForReceive(collectionPath, baseLayerName);
|
||||
|
||||
// get color and material if any
|
||||
string instanceId = instanceProxy.applicationId ?? instanceProxy.id;
|
||||
AutocadColor? objColor = _autocadColorManager.ObjectColorsIdMap.TryGetValue(
|
||||
instanceId,
|
||||
out AutocadColor? color
|
||||
)
|
||||
? color
|
||||
: null;
|
||||
ObjectId objMaterial = _autocadMaterialManager.ObjectMaterialsIdMap.TryGetValue(
|
||||
instanceId,
|
||||
out ObjectId matId
|
||||
)
|
||||
? matId
|
||||
: ObjectId.Null;
|
||||
|
||||
BlockReference blockRef = new(insertionPoint, definitionId) { BlockTransform = matrix3d, Layer = layerName, };
|
||||
|
||||
if (objColor is not null)
|
||||
{
|
||||
blockRef.Color = objColor;
|
||||
}
|
||||
|
||||
if (objMaterial != ObjectId.Null)
|
||||
{
|
||||
blockRef.MaterialId = objMaterial;
|
||||
}
|
||||
|
||||
modelSpaceBlockTableRecord.AppendEntity(blockRef);
|
||||
|
||||
applicationIdMap[instanceId] = new List<Entity> { blockRef };
|
||||
|
||||
transaction.AddNewlyCreatedDBObject(blockRef, true);
|
||||
conversionResults.Add(
|
||||
new(Status.SUCCESS, instanceProxy, blockRef.GetSpeckleApplicationId(), "Instance (Block)")
|
||||
);
|
||||
createdObjectIds.Add(blockRef.GetSpeckleApplicationId());
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
conversionResults.Add(new(Status.ERROR, instanceOrDefinition as Base ?? new Base(), null, null, ex));
|
||||
}
|
||||
}
|
||||
|
||||
transaction.Commit();
|
||||
return new(createdObjectIds, consumedObjectIds, conversionResults);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleans up any previously created instances.
|
||||
/// POC: This function will not be able to delete block definitions if the user creates a new one composed out of received definitions.
|
||||
/// </summary>
|
||||
/// <param name="namePrefix"></param>
|
||||
public void PurgeInstances(string namePrefix)
|
||||
{
|
||||
namePrefix = _autocadContext.RemoveInvalidChars(namePrefix);
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
var instanceDefinitionsToDelete = new Dictionary<string, BlockTableRecord>();
|
||||
|
||||
// Helper function that recurses through a given block table record's constituent objects and purges inner instances as required.
|
||||
void TraverseAndClean(BlockTableRecord btr)
|
||||
{
|
||||
foreach (var objectId in btr)
|
||||
{
|
||||
var obj = transaction.GetObject(objectId, OpenMode.ForRead) as BlockReference;
|
||||
if (obj == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var definition = (BlockTableRecord)transaction.GetObject(obj.BlockTableRecord, OpenMode.ForRead);
|
||||
if (obj.IsErased)
|
||||
{
|
||||
TraverseAndClean(definition);
|
||||
continue;
|
||||
}
|
||||
|
||||
obj.UpgradeOpen();
|
||||
obj.Erase();
|
||||
TraverseAndClean(definition);
|
||||
instanceDefinitionsToDelete[obj.BlockTableRecord.ToString()] = definition;
|
||||
}
|
||||
}
|
||||
|
||||
using var blockTable = (BlockTable)
|
||||
transaction.GetObject(Application.DocumentManager.CurrentDocument.Database.BlockTableId, OpenMode.ForRead);
|
||||
|
||||
// deep clean definitions
|
||||
foreach (var btrId in blockTable)
|
||||
{
|
||||
var btr = (BlockTableRecord)transaction.GetObject(btrId, OpenMode.ForRead);
|
||||
if (btr.Name.Contains(namePrefix)) // POC: this is tightly coupled with a naming convention for definitions in the instance object manager
|
||||
{
|
||||
TraverseAndClean(btr);
|
||||
instanceDefinitionsToDelete[btr.Name] = btr;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var def in instanceDefinitionsToDelete.Values)
|
||||
{
|
||||
def.UpgradeOpen();
|
||||
def.Erase();
|
||||
}
|
||||
|
||||
transaction.Commit();
|
||||
}
|
||||
|
||||
private Matrix4x4 GetMatrix(double[] t)
|
||||
{
|
||||
return new Matrix4x4(
|
||||
t[0],
|
||||
t[1],
|
||||
t[2],
|
||||
t[3],
|
||||
t[4],
|
||||
t[5],
|
||||
t[6],
|
||||
t[7],
|
||||
t[8],
|
||||
t[9],
|
||||
t[10],
|
||||
t[11],
|
||||
t[12],
|
||||
t[13],
|
||||
t[14],
|
||||
t[15]
|
||||
);
|
||||
}
|
||||
|
||||
private Matrix3d GetMatrix3d(Matrix4x4 matrix, string units)
|
||||
{
|
||||
var sf = Units.GetConversionFactor(
|
||||
units,
|
||||
_unitsConverter.ConvertOrThrow(Application.DocumentManager.CurrentDocument.Database.Insunits)
|
||||
);
|
||||
|
||||
var scaledTransform = new[]
|
||||
{
|
||||
matrix.M11,
|
||||
matrix.M12,
|
||||
matrix.M13,
|
||||
matrix.M14 * sf,
|
||||
matrix.M21,
|
||||
matrix.M22,
|
||||
matrix.M23,
|
||||
matrix.M24 * sf,
|
||||
matrix.M31,
|
||||
matrix.M32,
|
||||
matrix.M33,
|
||||
matrix.M34 * sf,
|
||||
matrix.M41,
|
||||
matrix.M42,
|
||||
matrix.M43,
|
||||
matrix.M44
|
||||
};
|
||||
|
||||
var m3d = new Matrix3d(scaledTransform);
|
||||
if (!m3d.IsScaledOrtho())
|
||||
{
|
||||
m3d = new Matrix3d(MakePerpendicular(m3d));
|
||||
}
|
||||
|
||||
return m3d;
|
||||
}
|
||||
|
||||
// https://forums.autodesk.com/t5/net/set-blocktransform-values/m-p/6452121#M49479
|
||||
private static double[] MakePerpendicular(Matrix3d matrix)
|
||||
{
|
||||
// Get the basis vectors of the matrix
|
||||
Vector3d right = new(matrix[0, 0], matrix[1, 0], matrix[2, 0]);
|
||||
Vector3d up = new(matrix[0, 1], matrix[1, 1], matrix[2, 1]);
|
||||
|
||||
Vector3d newForward = right.CrossProduct(up).GetNormal();
|
||||
Vector3d newUp = newForward.CrossProduct(right).GetNormal();
|
||||
|
||||
return new[]
|
||||
{
|
||||
right.X,
|
||||
newUp.X,
|
||||
newForward.X,
|
||||
matrix[0, 3],
|
||||
right.Y,
|
||||
newUp.Y,
|
||||
newForward.Y,
|
||||
matrix[1, 3],
|
||||
right.Z,
|
||||
newUp.Z,
|
||||
newForward.Z,
|
||||
matrix[2, 3],
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
matrix[3, 3],
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,188 +0,0 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Connectors.Common.Instances;
|
||||
using Speckle.Converters.Autocad.Helpers;
|
||||
using Speckle.Converters.AutocadShared.ToSpeckle;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Models.Instances;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// Expects to be a scoped dependency per send operation.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
public UnpackResult<AutocadRootObject> UnpackSelection(IEnumerable<AutocadRootObject> objects)
|
||||
{
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
|
||||
foreach (var obj in objects)
|
||||
{
|
||||
// Note: isDynamicBlock always returns false for a selection of doc objects. Instances of dynamic blocks are represented in the document as blocks that have
|
||||
// a definition reference to the anonymous block table record.
|
||||
if (obj.Root is BlockReference blockReference && !blockReference.IsDynamicBlock)
|
||||
{
|
||||
UnpackInstance(blockReference, 0, transaction);
|
||||
}
|
||||
|
||||
_instanceObjectsManager.AddAtomicObject(obj.ApplicationId, obj);
|
||||
}
|
||||
return _instanceObjectsManager.GetUnpackResult();
|
||||
}
|
||||
|
||||
private void UnpackInstance(BlockReference instance, int depth, Transaction transaction)
|
||||
{
|
||||
try
|
||||
{
|
||||
string instanceId = instance.GetSpeckleApplicationId();
|
||||
|
||||
// If this instance has a reference to an anonymous block, it means it's spawned from a dynamic block. Anonymous blocks are
|
||||
// used to represent specific "instances" of dynamic ones.
|
||||
// We do not want to send the full dynamic block definition, but its current "instance", as such here we're making sure we
|
||||
// take up the anon block table reference definition (if it exists). If it's not an instance of a dynamic block, we're
|
||||
// using the normal def reference.
|
||||
ObjectId definitionId = !instance.AnonymousBlockTableRecord.IsNull
|
||||
? instance.AnonymousBlockTableRecord
|
||||
: instance.BlockTableRecord;
|
||||
|
||||
// transforms on instances are always stored in WCS
|
||||
InstanceProxy instanceProxy = new()
|
||||
{
|
||||
applicationId = instanceId,
|
||||
definitionId = definitionId.ToString(),
|
||||
maxDepth = depth,
|
||||
transform = TransformHelper.ConvertToInstanceMatrix4x4(instance.BlockTransform),
|
||||
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.
|
||||
// This will enable on receive to create them in the correct order (descending by max depth, interleaved definitions and instances).
|
||||
// We need to interleave the creation of definitions and instances, as some definitions may depend on instances.
|
||||
if (
|
||||
!_instanceObjectsManager.TryGetInstanceProxiesFromDefinitionId(
|
||||
definitionId.ToString(),
|
||||
out List<InstanceProxy>? instanceProxiesWithSameDefinition
|
||||
)
|
||||
)
|
||||
{
|
||||
instanceProxiesWithSameDefinition = new List<InstanceProxy>();
|
||||
_instanceObjectsManager.AddInstanceProxiesByDefinitionId(
|
||||
definitionId.ToString(),
|
||||
instanceProxiesWithSameDefinition
|
||||
);
|
||||
}
|
||||
|
||||
// We ensure that all previous instance proxies that have the same definition are at this max depth. I kind of have a feeling this can be done more elegantly, but YOLO
|
||||
foreach (var instanceProxyWithSameDefinition in instanceProxiesWithSameDefinition)
|
||||
{
|
||||
if (instanceProxyWithSameDefinition.maxDepth < depth)
|
||||
{
|
||||
instanceProxyWithSameDefinition.maxDepth = depth;
|
||||
}
|
||||
}
|
||||
|
||||
instanceProxiesWithSameDefinition.Add(_instanceObjectsManager.GetInstanceProxy(instanceId));
|
||||
|
||||
// Add text attributes from Instances as separate atomic objects:
|
||||
// AttributeReferences found on Instances are just a text, not a part of the Instance
|
||||
// They are not actually references and are not linked to AttributeDefinition (as one would expect),
|
||||
// and already have the correct position (no need for transforms).
|
||||
// We don't want to create a new BlockDefinition for every changed text for now, because AutoCAD API doesn't provide one,
|
||||
// e.g. AnonymousBlockTableRecord is provided for each dynamic blocks with geometry changes, but not for Attribute changes.
|
||||
// Docs on AttributeReference usage (used totally independent of AttributeDefinition): https://help.autodesk.com/view/OARX/2025/ENU/?guid=GUID-BA69D85A-2AED-43C2-B5B7-73022B5F28F8
|
||||
// Case of trying to match AttributeDefinition with AttributeReference via Tag value (which is not unique): https://forums.autodesk.com/t5/net-forum/get-the-value-of-an-attribute-in-c/td-p/9060940
|
||||
|
||||
foreach (ObjectId id in instance.AttributeCollection)
|
||||
{
|
||||
var reference = (AttributeReference)transaction.GetObject(id, OpenMode.ForRead);
|
||||
string refAppId = reference.GetSpeckleApplicationId();
|
||||
_instanceObjectsManager.AddAtomicObject(refAppId, new(reference, refAppId));
|
||||
}
|
||||
|
||||
// rely on already converted Definition
|
||||
if (
|
||||
_instanceObjectsManager.TryGetInstanceDefinitionProxy(
|
||||
definitionId.ToString(),
|
||||
out InstanceDefinitionProxy? value
|
||||
)
|
||||
)
|
||||
{
|
||||
int depthDifference = depth - value.maxDepth;
|
||||
if (depthDifference > 0)
|
||||
{
|
||||
// all MaxDepth of children definitions and its instances should be increased with difference of depth
|
||||
_instanceObjectsManager.UpdateChildrenMaxDepth(value, depthDifference);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var definition = (BlockTableRecord)transaction.GetObject(definitionId, OpenMode.ForRead);
|
||||
var definitionProxy = new InstanceDefinitionProxy()
|
||||
{
|
||||
applicationId = definitionId.ToString(),
|
||||
objects = new(),
|
||||
maxDepth = depth,
|
||||
name = !instance.AnonymousBlockTableRecord.IsNull ? "Dynamic instance " + definitionId : definition.Name,
|
||||
};
|
||||
|
||||
// Go through each definition object
|
||||
foreach (ObjectId id in definition)
|
||||
{
|
||||
Entity obj = (Entity)transaction.GetObject(id, OpenMode.ForRead);
|
||||
|
||||
// In the case of dynamic blocks, this prevents sending objects that are not visible in its current state.
|
||||
// Also skipping AttributeDefinition because it only contains default text values. We convert AttributeReference above instead, as a separate object.
|
||||
if (!obj.Visible || obj is AttributeDefinition)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
string appId = obj.GetSpeckleApplicationId();
|
||||
definitionProxy.objects.Add(appId);
|
||||
|
||||
if (obj is BlockReference blockReference)
|
||||
{
|
||||
UnpackInstance(blockReference, depth + 1, transaction);
|
||||
}
|
||||
|
||||
_instanceObjectsManager.AddAtomicDefinitionObjectId(appId);
|
||||
_instanceObjectsManager.AddAtomicObject(appId, new(obj, appId));
|
||||
}
|
||||
|
||||
_instanceObjectsManager.AddDefinitionProxy(definitionId.ToString(), definitionProxy);
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
_logger.LogError(ex, "Failed unpacking Autocad instance");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,59 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Autodesk.AutoCAD.EditorInput;
|
||||
using Autodesk.AutoCAD.LayerManager;
|
||||
using Speckle.Connectors.Common.Operations.Receive;
|
||||
using Speckle.Sdk.Common;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using Speckle.Sdk.Models.GraphTraversal;
|
||||
using AutocadColor = Autodesk.AutoCAD.Colors.Color;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
public class AutocadLayerBaker : TraversalContextUnpacker
|
||||
/// <summary>
|
||||
/// Expects to be a scoped dependency for a given operation and helps with layer creation and cleanup.
|
||||
/// </summary>
|
||||
public class AutocadLayerManager
|
||||
{
|
||||
private readonly string _layerFilterName = "Speckle";
|
||||
private readonly AutocadContext _autocadContext;
|
||||
private readonly IAutocadMaterialBaker _materialBaker;
|
||||
private readonly IAutocadColorBaker _colorBaker;
|
||||
private readonly AutocadMaterialManager _materialManager;
|
||||
private readonly AutocadColorManager _colorManager;
|
||||
private readonly string _layerFilterName = "Speckle";
|
||||
public Dictionary<string, Layer> CollectionCache { get; } = new();
|
||||
|
||||
// POC: Will be addressed to move it into AutocadContext!
|
||||
private Document Doc => Application.DocumentManager.MdiActiveDocument;
|
||||
private readonly HashSet<string> _uniqueLayerNames = new();
|
||||
|
||||
public AutocadLayerBaker(
|
||||
public AutocadLayerManager(
|
||||
AutocadContext autocadContext,
|
||||
IAutocadMaterialBaker materialBaker,
|
||||
IAutocadColorBaker colorBaker
|
||||
AutocadMaterialManager materialManager,
|
||||
AutocadColorManager colorManager
|
||||
)
|
||||
{
|
||||
_autocadContext = autocadContext;
|
||||
_materialBaker = materialBaker;
|
||||
_colorBaker = colorBaker;
|
||||
_materialManager = materialManager;
|
||||
_colorManager = colorManager;
|
||||
}
|
||||
|
||||
public Layer GetOrCreateSpeckleLayer(Entity entity, Transaction tr, out LayerTableRecord? layer)
|
||||
{
|
||||
string layerName = entity.Layer;
|
||||
layer = null;
|
||||
if (CollectionCache.TryGetValue(layerName, out Layer? speckleLayer))
|
||||
{
|
||||
return speckleLayer;
|
||||
}
|
||||
if (tr.GetObject(entity.LayerId, OpenMode.ForRead) is LayerTableRecord autocadLayer)
|
||||
{
|
||||
// Layers and geometries can have same application ids.....
|
||||
// We should prevent it for sketchup converter. Because when it happens "objects_to_bake" definition
|
||||
// is changing on the way if it happens.
|
||||
speckleLayer = new Layer(layerName) { applicationId = autocadLayer.GetSpeckleApplicationId() }; // Do not use handle directly, see note in the 'GetSpeckleApplicationId' method
|
||||
CollectionCache[layerName] = speckleLayer;
|
||||
layer = autocadLayer;
|
||||
return speckleLayer;
|
||||
}
|
||||
throw new SpeckleConversionException("Unexpected condition in GetOrCreateSpeckleLayer");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -45,7 +73,7 @@ public class AutocadLayerBaker : TraversalContextUnpacker
|
||||
// get the color and material if any, of the leaf collection with a color
|
||||
AutocadColor? layerColor = null;
|
||||
ObjectId layerMaterial = ObjectId.Null;
|
||||
if (_colorBaker.ObjectColorsIdMap.Count > 0 || _materialBaker.ObjectMaterialsIdMap.Count > 0)
|
||||
if (_colorManager.ObjectColorsIdMap.Count > 0 || _materialManager.ObjectMaterialsIdMap.Count > 0)
|
||||
{
|
||||
bool foundColor = false;
|
||||
bool foundMaterial = false;
|
||||
@@ -53,16 +81,16 @@ public class AutocadLayerBaker : TraversalContextUnpacker
|
||||
// Goes up the tree to find any potential parent layer that has a material/color
|
||||
for (int j = layerPath.Length - 1; j >= 0; j--)
|
||||
{
|
||||
string layerId = layerPath[j].applicationId ?? layerPath[j].id.NotNull();
|
||||
string layerId = layerPath[j].applicationId ?? layerPath[j].id;
|
||||
|
||||
if (!foundColor)
|
||||
{
|
||||
foundColor = _colorBaker.ObjectColorsIdMap.TryGetValue(layerId, out layerColor);
|
||||
foundColor = _colorManager.ObjectColorsIdMap.TryGetValue(layerId, out layerColor);
|
||||
}
|
||||
|
||||
if (!foundMaterial)
|
||||
{
|
||||
foundMaterial = _materialBaker.ObjectMaterialsIdMap.TryGetValue(layerId, out layerMaterial);
|
||||
foundMaterial = _materialManager.ObjectMaterialsIdMap.TryGetValue(layerId, out layerMaterial);
|
||||
}
|
||||
|
||||
if (foundColor && foundMaterial)
|
||||
@@ -199,4 +227,22 @@ public class AutocadLayerBaker : TraversalContextUnpacker
|
||||
groupFilter.NestedFilters.Add(layerFilter);
|
||||
Doc.Database.LayerFilters = layerFilterTree;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a valid collection representing a layer for a given context.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns>A new Speckle Layer object</returns>
|
||||
public Collection[] GetLayerPath(TraversalContext context)
|
||||
{
|
||||
Collection[] collectionBasedPath = context.GetAscendantOfType<Collection>().Reverse().ToArray();
|
||||
|
||||
if (collectionBasedPath.Length == 0)
|
||||
{
|
||||
string[] path = context.GetPropertyPath().Reverse().ToArray();
|
||||
collectionBasedPath = [new Collection(string.Join("-", path))];
|
||||
}
|
||||
|
||||
return collectionBasedPath;
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
public class AutocadLayerUnpacker
|
||||
{
|
||||
private readonly Dictionary<string, Layer> _layerCollectionCache = new();
|
||||
|
||||
public Layer GetOrCreateSpeckleLayer(Entity entity, Transaction tr, out LayerTableRecord? layer)
|
||||
{
|
||||
string layerName = entity.Layer;
|
||||
layer = null;
|
||||
if (_layerCollectionCache.TryGetValue(layerName, out Layer? speckleLayer))
|
||||
{
|
||||
return speckleLayer;
|
||||
}
|
||||
if (tr.GetObject(entity.LayerId, OpenMode.ForRead) is LayerTableRecord autocadLayer)
|
||||
{
|
||||
speckleLayer = new Layer(layerName) { applicationId = autocadLayer.GetSpeckleApplicationId() }; // Do not use handle directly, see note in the 'GetSpeckleApplicationId' method
|
||||
_layerCollectionCache[layerName] = speckleLayer;
|
||||
layer = autocadLayer;
|
||||
return speckleLayer;
|
||||
}
|
||||
|
||||
throw new SpeckleException("Unexpected condition in GetOrCreateSpeckleLayer");
|
||||
}
|
||||
}
|
||||
@@ -1,202 +0,0 @@
|
||||
using Autodesk.AutoCAD.Colors;
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Autodesk.AutoCAD.GraphicsInterface;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Common.Conversion;
|
||||
using Speckle.InterfaceGenerator;
|
||||
using Speckle.Objects.Other;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Common;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Pipelines.Progress;
|
||||
using Material = Autodesk.AutoCAD.DatabaseServices.Material;
|
||||
using RenderMaterial = Speckle.Objects.Other.RenderMaterial;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// Expects to be a scoped dependency for a given operation and helps with layer creation and cleanup.
|
||||
/// </summary>
|
||||
[GenerateAutoInterface]
|
||||
public class AutocadMaterialBaker : IAutocadMaterialBaker
|
||||
{
|
||||
private readonly ILogger<AutocadMaterialBaker> _logger;
|
||||
private readonly AutocadContext _autocadContext;
|
||||
private Document Doc => Application.DocumentManager.MdiActiveDocument;
|
||||
public Dictionary<string, ObjectId> ObjectMaterialsIdMap { get; } = new();
|
||||
|
||||
public AutocadMaterialBaker(AutocadContext autocadContext, ILogger<AutocadMaterialBaker> logger)
|
||||
{
|
||||
_autocadContext = autocadContext;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to get material id from original object or its parent (if provided) as fallback).
|
||||
/// It covers one-to-many problem, i.e.
|
||||
/// - rhino: Brep (material id is extracted into render material proxy objects) -> [Mesh, Mesh, ...] (child objects application ids ARE NOT EXIST in render material proxy objects)
|
||||
/// - revit : RevitElement (material IS NOT extracted into render material proxy objects) -> [Mesh, Mesh...] (child objects application ids EXIST in render material proxy objects)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a question that we need to answer where to handle these cases.
|
||||
/// We alsa do reverse search for layer render materials on Revit Receive, and mutating the proxy list accordingly.
|
||||
/// These cases are increasing, and need some ideation around it before going more messy.
|
||||
/// </remarks>
|
||||
public bool TryGetMaterialId(Base originalObject, Base? parentObject, out ObjectId materialId)
|
||||
{
|
||||
materialId = ObjectId.Null;
|
||||
var originalObjectId = originalObject.applicationId ?? originalObject.id.NotNull();
|
||||
if (ObjectMaterialsIdMap.TryGetValue(originalObjectId, out ObjectId originalObjectMaterialId))
|
||||
{
|
||||
materialId = originalObjectMaterialId;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (parentObject is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var subObjectId = parentObject.applicationId ?? parentObject.id.NotNull();
|
||||
if (ObjectMaterialsIdMap.TryGetValue(subObjectId, out ObjectId subObjectMaterialId))
|
||||
{
|
||||
materialId = subObjectMaterialId;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all materials with a name starting with <paramref name="namePrefix"/> from the active document
|
||||
/// </summary>
|
||||
/// <param name="namePrefix"></param>
|
||||
public void PurgeMaterials(string namePrefix)
|
||||
{
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
if (transaction.GetObject(Doc.Database.MaterialDictionaryId, OpenMode.ForWrite) is DBDictionary materialDict)
|
||||
{
|
||||
foreach (var entry in materialDict)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (entry.Key.Contains(namePrefix))
|
||||
{
|
||||
materialDict.Remove(entry.Value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
_logger.LogError(ex, "Failed to purge a material from the document");
|
||||
}
|
||||
}
|
||||
}
|
||||
transaction.Commit();
|
||||
}
|
||||
|
||||
public void ParseAndBakeRenderMaterials(
|
||||
IReadOnlyCollection<RenderMaterialProxy> materialProxies,
|
||||
string baseLayerPrefix,
|
||||
IProgress<CardProgress> onOperationProgressed
|
||||
)
|
||||
{
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
var materialDict = transaction.GetObject(Doc.Database.MaterialDictionaryId, OpenMode.ForWrite) as DBDictionary;
|
||||
|
||||
if (materialDict == null)
|
||||
{
|
||||
// POC: we should report failed conversion here if material dict is not accessible, but it is not linked to a Base source
|
||||
transaction.Commit();
|
||||
return;
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
foreach (RenderMaterialProxy materialProxy in materialProxies)
|
||||
{
|
||||
onOperationProgressed.Report(new("Converting render materials", (double)++count / materialProxies.Count));
|
||||
|
||||
// bake render material
|
||||
RenderMaterial renderMaterial = materialProxy.value;
|
||||
string renderMaterialId = renderMaterial.applicationId ?? renderMaterial.id.NotNull();
|
||||
ObjectId materialId = ObjectId.Null;
|
||||
|
||||
if (!ObjectMaterialsIdMap.TryGetValue(renderMaterialId, out materialId))
|
||||
{
|
||||
(materialId, ReceiveConversionResult result) = BakeMaterial(
|
||||
renderMaterial,
|
||||
baseLayerPrefix,
|
||||
materialDict,
|
||||
transaction
|
||||
);
|
||||
}
|
||||
|
||||
if (materialId == ObjectId.Null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// parse render material object ids
|
||||
foreach (string objectId in materialProxy.objects)
|
||||
{
|
||||
ObjectMaterialsIdMap[objectId] = materialId;
|
||||
}
|
||||
}
|
||||
|
||||
transaction.Commit();
|
||||
}
|
||||
|
||||
private (ObjectId, ReceiveConversionResult) BakeMaterial(
|
||||
RenderMaterial renderMaterial,
|
||||
string baseLayerPrefix,
|
||||
DBDictionary materialDict,
|
||||
Transaction tr
|
||||
)
|
||||
{
|
||||
ObjectId materialId = ObjectId.Null;
|
||||
|
||||
try
|
||||
{
|
||||
// POC: Currently we're relying on the render material name for identification if it's coming from speckle and from which model; could we do something else?
|
||||
// POC: we should assume render materials all have application ids?
|
||||
string renderMaterialId = renderMaterial.applicationId ?? renderMaterial.id.NotNull();
|
||||
string matName = _autocadContext.RemoveInvalidChars(
|
||||
$"{renderMaterial.name}-({renderMaterialId})-{baseLayerPrefix}"
|
||||
);
|
||||
|
||||
MaterialMap map = new();
|
||||
MaterialOpacityComponent opacity = new(renderMaterial.opacity, map);
|
||||
var systemDiffuse = System.Drawing.Color.FromArgb(renderMaterial.diffuse);
|
||||
EntityColor entityDiffuseColor = new(systemDiffuse.R, systemDiffuse.G, systemDiffuse.B);
|
||||
MaterialColor diffuseColor = new(Method.Override, 1, entityDiffuseColor);
|
||||
MaterialDiffuseComponent diffuse = new(diffuseColor, map);
|
||||
|
||||
Material mat = new()
|
||||
{
|
||||
Name = matName,
|
||||
Opacity = opacity,
|
||||
Diffuse = diffuse,
|
||||
};
|
||||
|
||||
if (renderMaterial["reflectivity"] is double reflectivity)
|
||||
{
|
||||
mat.Reflectivity = reflectivity;
|
||||
}
|
||||
|
||||
if (renderMaterial["ior"] is double ior)
|
||||
{
|
||||
mat.Refraction = new(ior, map);
|
||||
}
|
||||
|
||||
// POC: assumes all materials with this prefix has already been purged from doc
|
||||
materialId = materialDict.SetAt(matName, mat);
|
||||
tr.AddNewlyCreatedDBObject(mat, true);
|
||||
|
||||
return (materialId, new(Status.SUCCESS, renderMaterial, matName, "Material"));
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
_logger.LogError(ex, "Failed to add a material to the document");
|
||||
return (materialId, new(Status.ERROR, renderMaterial, null, null, ex));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,267 @@
|
||||
using Autodesk.AutoCAD.Colors;
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Autodesk.AutoCAD.GraphicsInterface;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Connectors.Utils.Conversion;
|
||||
using Speckle.Objects.Other;
|
||||
using Speckle.Sdk;
|
||||
using Material = Autodesk.AutoCAD.DatabaseServices.Material;
|
||||
using RenderMaterial = Speckle.Objects.Other.RenderMaterial;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// Expects to be a scoped dependency for a given operation and helps with layer creation and cleanup.
|
||||
/// </summary>
|
||||
public class AutocadMaterialManager
|
||||
{
|
||||
private readonly AutocadContext _autocadContext;
|
||||
|
||||
// POC: Will be addressed to move it into AutocadContext!
|
||||
private Document Doc => Application.DocumentManager.MdiActiveDocument;
|
||||
|
||||
public Dictionary<string, ObjectId> ObjectMaterialsIdMap { get; } = new();
|
||||
|
||||
public AutocadMaterialManager(AutocadContext autocadContext)
|
||||
{
|
||||
_autocadContext = autocadContext;
|
||||
}
|
||||
|
||||
private RenderMaterialProxy ConvertMaterialToRenderMaterialProxy(Material material, string id)
|
||||
{
|
||||
EntityColor diffuseColor = material.Diffuse.Color.Color;
|
||||
System.Drawing.Color diffuse = System.Drawing.Color.FromArgb(
|
||||
diffuseColor.Red,
|
||||
diffuseColor.Green,
|
||||
diffuseColor.Blue
|
||||
);
|
||||
|
||||
string name = material.Name;
|
||||
double opacity = material.Opacity.Percentage;
|
||||
|
||||
RenderMaterial renderMaterial = new(opacity: opacity, diffuse: diffuse) { name = name, applicationId = id };
|
||||
|
||||
// Add additional properties
|
||||
renderMaterial["ior"] = material.Refraction.Index;
|
||||
renderMaterial["reflectivity"] = material.Reflectivity;
|
||||
|
||||
return new(renderMaterial, new()) { applicationId = id };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Iterates through a given set of autocad objects and collects their materials. Note: expects objects to be "atomic", and extracted out of their instances already.
|
||||
/// </summary>
|
||||
/// <param name="unpackedAutocadObjects"></param>
|
||||
/// <param name="layers"></param>
|
||||
/// <returns></returns>
|
||||
public List<RenderMaterialProxy> UnpackMaterials(
|
||||
List<AutocadRootObject> unpackedAutocadObjects,
|
||||
List<LayerTableRecord> layers
|
||||
)
|
||||
{
|
||||
Dictionary<string, RenderMaterialProxy> materialProxies = new();
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
|
||||
// Stage 1: unpack materials from objects
|
||||
foreach (AutocadRootObject rootObj in unpackedAutocadObjects)
|
||||
{
|
||||
Entity entity = rootObj.Root;
|
||||
|
||||
// skip inherited materials
|
||||
if (entity.Material == "ByLayer" || entity.Material == "ByBlock")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (transaction.GetObject(entity.MaterialId, OpenMode.ForRead) is Material material)
|
||||
{
|
||||
string materialId = material.GetSpeckleApplicationId();
|
||||
if (materialProxies.TryGetValue(materialId, out RenderMaterialProxy? value))
|
||||
{
|
||||
value.objects.Add(rootObj.ApplicationId);
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderMaterialProxy materialProxy = ConvertMaterialToRenderMaterialProxy(material, materialId);
|
||||
materialProxy.objects.Add(rootObj.ApplicationId);
|
||||
materialProxies[materialId] = materialProxy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stage 2: make sure we collect layer colors as well
|
||||
foreach (LayerTableRecord layer in layers)
|
||||
{
|
||||
if (transaction.GetObject(layer.MaterialId, OpenMode.ForRead) is Material material)
|
||||
{
|
||||
string materialId = material.GetSpeckleApplicationId();
|
||||
string layerId = layer.GetSpeckleApplicationId(); // Do not use handle directly, see note in the 'GetSpeckleApplicationId' method
|
||||
if (materialProxies.TryGetValue(materialId, out RenderMaterialProxy? value))
|
||||
{
|
||||
value.objects.Add(layerId);
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderMaterialProxy materialProxy = ConvertMaterialToRenderMaterialProxy(material, materialId);
|
||||
materialProxy.objects.Add(layerId);
|
||||
materialProxies[materialId] = materialProxy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
transaction.Commit();
|
||||
return materialProxies.Values.ToList();
|
||||
}
|
||||
|
||||
private (ObjectId, ReceiveConversionResult) BakeMaterial(
|
||||
RenderMaterial renderMaterial,
|
||||
string baseLayerPrefix,
|
||||
DBDictionary materialDict,
|
||||
Transaction tr
|
||||
)
|
||||
{
|
||||
ObjectId materialId = ObjectId.Null;
|
||||
|
||||
try
|
||||
{
|
||||
// POC: Currently we're relying on the render material name for identification if it's coming from speckle and from which model; could we do something else?
|
||||
// POC: we should assume render materials all have application ids?
|
||||
string renderMaterialId = renderMaterial.applicationId ?? renderMaterial.id;
|
||||
string matName = _autocadContext.RemoveInvalidChars(
|
||||
$"{renderMaterial.name}-({renderMaterialId})-{baseLayerPrefix}"
|
||||
);
|
||||
|
||||
MaterialMap map = new();
|
||||
MaterialOpacityComponent opacity = new(renderMaterial.opacity, map);
|
||||
var systemDiffuse = System.Drawing.Color.FromArgb(renderMaterial.diffuse);
|
||||
EntityColor entityDiffuseColor = new(systemDiffuse.R, systemDiffuse.G, systemDiffuse.B);
|
||||
MaterialColor diffuseColor = new(Method.Override, 1, entityDiffuseColor);
|
||||
MaterialDiffuseComponent diffuse = new(diffuseColor, map);
|
||||
|
||||
Material mat =
|
||||
new()
|
||||
{
|
||||
Name = matName,
|
||||
Opacity = opacity,
|
||||
Diffuse = diffuse
|
||||
};
|
||||
|
||||
if (renderMaterial["reflectivity"] is double reflectivity)
|
||||
{
|
||||
mat.Reflectivity = reflectivity;
|
||||
}
|
||||
|
||||
if (renderMaterial["ior"] is double ior)
|
||||
{
|
||||
mat.Refraction = new(ior, map);
|
||||
}
|
||||
|
||||
// POC: assumes all materials with this prefix has already been purged from doc
|
||||
materialId = materialDict.SetAt(matName, mat);
|
||||
tr.AddNewlyCreatedDBObject(mat, true);
|
||||
|
||||
return (materialId, new(Status.SUCCESS, renderMaterial, matName, "Material"));
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
return (materialId, new(Status.ERROR, renderMaterial, null, null, ex));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all materials with a name starting with <paramref name="namePrefix"/> from the active document
|
||||
/// </summary>
|
||||
/// <param name="namePrefix"></param>
|
||||
public void PurgeMaterials(string namePrefix)
|
||||
{
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
if (transaction.GetObject(Doc.Database.MaterialDictionaryId, OpenMode.ForWrite) is DBDictionary materialDict)
|
||||
{
|
||||
foreach (var entry in materialDict)
|
||||
{
|
||||
if (entry.Key.Contains(namePrefix))
|
||||
{
|
||||
materialDict.Remove(entry.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
transaction.Commit();
|
||||
}
|
||||
|
||||
public List<ReceiveConversionResult> ParseAndBakeRenderMaterials(
|
||||
List<RenderMaterialProxy> materialProxies,
|
||||
string baseLayerPrefix,
|
||||
Action<string, double?>? onOperationProgressed
|
||||
)
|
||||
{
|
||||
List<ReceiveConversionResult> results = new();
|
||||
Dictionary<string, string> objectRenderMaterialsIdMap = new();
|
||||
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
var materialDict = transaction.GetObject(Doc.Database.MaterialDictionaryId, OpenMode.ForWrite) as DBDictionary;
|
||||
|
||||
if (materialDict == null)
|
||||
{
|
||||
// POC: we should report failed conversion here if material dict is not accessible, but it is not linked to a Base source
|
||||
transaction.Commit();
|
||||
return results;
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
foreach (RenderMaterialProxy materialProxy in materialProxies)
|
||||
{
|
||||
onOperationProgressed?.Invoke("Converting render materials", (double)++count / materialProxies.Count);
|
||||
|
||||
// bake render material
|
||||
RenderMaterial renderMaterial = materialProxy.value;
|
||||
string renderMaterialId = renderMaterial.applicationId ?? renderMaterial.id;
|
||||
ObjectId materialId = ObjectId.Null;
|
||||
|
||||
if (!ObjectMaterialsIdMap.TryGetValue(renderMaterialId, out materialId))
|
||||
{
|
||||
(materialId, ReceiveConversionResult result) = BakeMaterial(
|
||||
renderMaterial,
|
||||
baseLayerPrefix,
|
||||
materialDict,
|
||||
transaction
|
||||
);
|
||||
|
||||
results.Add(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
// POC: this shouldn't happen, but will if there are render materials with the same applicationID
|
||||
results.Add(
|
||||
new(
|
||||
Status.ERROR,
|
||||
renderMaterial,
|
||||
exception: new ArgumentException("Another render material of the same id has already been created.")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (materialId == ObjectId.Null)
|
||||
{
|
||||
results.Add(
|
||||
new(
|
||||
Status.ERROR,
|
||||
renderMaterial,
|
||||
exception: new InvalidOperationException("Render material failed to be added to document.")
|
||||
)
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// parse render material object ids
|
||||
foreach (string objectId in materialProxy.objects)
|
||||
{
|
||||
ObjectMaterialsIdMap[objectId] = materialId;
|
||||
}
|
||||
}
|
||||
|
||||
transaction.Commit();
|
||||
return results;
|
||||
}
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
using Autodesk.AutoCAD.Colors;
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Autocad.Operations.Send;
|
||||
using Speckle.Objects.Other;
|
||||
using Speckle.Sdk;
|
||||
using Material = Autodesk.AutoCAD.DatabaseServices.Material;
|
||||
using RenderMaterial = Speckle.Objects.Other.RenderMaterial;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// Expects to be a scoped dependency for a given operation and helps with layer creation and cleanup.
|
||||
/// </summary>
|
||||
public class AutocadMaterialUnpacker
|
||||
{
|
||||
private readonly ILogger<AutocadMaterialUnpacker> _logger;
|
||||
|
||||
public AutocadMaterialUnpacker(ILogger<AutocadMaterialUnpacker> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Iterates through a given set of autocad objects and collects their materials. Note: expects objects to be "atomic", and extracted out of their instances already.
|
||||
/// </summary>
|
||||
/// <param name="unpackedAutocadObjects"></param>
|
||||
/// <param name="layers"></param>
|
||||
/// <returns></returns>
|
||||
public List<RenderMaterialProxy> UnpackMaterials(
|
||||
List<AutocadRootObject> unpackedAutocadObjects,
|
||||
List<LayerTableRecord> layers
|
||||
)
|
||||
{
|
||||
Dictionary<string, RenderMaterialProxy> materialProxies = new();
|
||||
using var transaction = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
|
||||
// Stage 1: unpack materials from objects
|
||||
foreach (AutocadRootObject rootObj in unpackedAutocadObjects)
|
||||
{
|
||||
try
|
||||
{
|
||||
Entity entity = rootObj.Root;
|
||||
|
||||
// skip inherited materials
|
||||
if (entity.Material == "ByLayer" || entity.Material == "ByBlock")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (transaction.GetObject(entity.MaterialId, OpenMode.ForRead) is Material material)
|
||||
{
|
||||
// skip default material
|
||||
if (material.Name == "Global")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string materialId = material.GetSpeckleApplicationId();
|
||||
if (materialProxies.TryGetValue(materialId, out RenderMaterialProxy? value))
|
||||
{
|
||||
value.objects.Add(rootObj.ApplicationId);
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderMaterialProxy materialProxy = ConvertMaterialToRenderMaterialProxy(material, materialId);
|
||||
materialProxy.objects.Add(rootObj.ApplicationId);
|
||||
materialProxies[materialId] = materialProxy;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
_logger.LogError(ex, "Failed to unpack render material from Autocad Entity");
|
||||
}
|
||||
}
|
||||
|
||||
// Stage 2: make sure we collect layer materials as well
|
||||
foreach (LayerTableRecord layer in layers)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (transaction.GetObject(layer.MaterialId, OpenMode.ForRead) is Material material)
|
||||
{
|
||||
// skip default material
|
||||
if (material.Name == "Global")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string materialId = material.GetSpeckleApplicationId();
|
||||
string layerId = layer.GetSpeckleApplicationId(); // Do not use handle directly, see note in the 'GetSpeckleApplicationId' method
|
||||
if (materialProxies.TryGetValue(materialId, out RenderMaterialProxy? value))
|
||||
{
|
||||
value.objects.Add(layerId);
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderMaterialProxy materialProxy = ConvertMaterialToRenderMaterialProxy(material, materialId);
|
||||
materialProxy.objects.Add(layerId);
|
||||
materialProxies[materialId] = materialProxy;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
_logger.LogError(ex, "Failed to unpack render material from Autocad Layer");
|
||||
}
|
||||
}
|
||||
|
||||
transaction.Commit();
|
||||
return materialProxies.Values.ToList();
|
||||
}
|
||||
|
||||
private RenderMaterialProxy ConvertMaterialToRenderMaterialProxy(Material material, string id)
|
||||
{
|
||||
EntityColor diffuseColor = material.Diffuse.Color.Color;
|
||||
System.Drawing.Color diffuse = System.Drawing.Color.FromArgb(
|
||||
diffuseColor.Red,
|
||||
diffuseColor.Green,
|
||||
diffuseColor.Blue
|
||||
);
|
||||
|
||||
RenderMaterial renderMaterial = new()
|
||||
{
|
||||
name = material.Name,
|
||||
opacity = material.Opacity.Percentage,
|
||||
diffuse = diffuse.ToArgb(),
|
||||
applicationId = id,
|
||||
};
|
||||
|
||||
// Add additional properties
|
||||
renderMaterial["ior"] = material.Refraction.Index;
|
||||
renderMaterial["reflectivity"] = material.Reflectivity;
|
||||
|
||||
return new RenderMaterialProxy()
|
||||
{
|
||||
value = renderMaterial,
|
||||
objects = new(),
|
||||
applicationId = id,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,297 +0,0 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Speckle.Connectors.Autocad.HostApp;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Common.Builders;
|
||||
using Speckle.Connectors.Common.Conversion;
|
||||
using Speckle.Connectors.Common.Extensions;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Connectors.Common.Operations.Receive;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Sdk.Common;
|
||||
using Speckle.Sdk.Dependencies;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using Speckle.Sdk.Models.Instances;
|
||||
using Speckle.Sdk.Pipelines.Progress;
|
||||
using AutocadColor = Autodesk.AutoCAD.Colors.Color;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Operations.Receive;
|
||||
|
||||
/// <summary>
|
||||
/// <para>Base class for AutoCAD host object builders. Expects to be a scoped dependency per receive operation.</para>
|
||||
/// </summary>
|
||||
public abstract class AutocadHostObjectBaseBuilder : IHostObjectBuilder
|
||||
{
|
||||
private readonly IRootToHostConverter _converter;
|
||||
private readonly AutocadLayerBaker _layerBaker;
|
||||
private readonly AutocadGroupBaker _groupBaker;
|
||||
private readonly AutocadInstanceBaker _instanceBaker;
|
||||
private readonly IAutocadMaterialBaker _materialBaker;
|
||||
private readonly IAutocadColorBaker _colorBaker;
|
||||
private readonly AutocadContext _autocadContext;
|
||||
private readonly RootObjectUnpacker _rootObjectUnpacker;
|
||||
private readonly IReceiveConversionHandler _conversionHandler;
|
||||
|
||||
protected AutocadHostObjectBaseBuilder(
|
||||
IRootToHostConverter converter,
|
||||
AutocadLayerBaker layerBaker,
|
||||
AutocadGroupBaker groupBaker,
|
||||
AutocadInstanceBaker instanceBaker,
|
||||
IAutocadMaterialBaker materialBaker,
|
||||
IAutocadColorBaker colorBaker,
|
||||
AutocadContext autocadContext,
|
||||
RootObjectUnpacker rootObjectUnpacker,
|
||||
IReceiveConversionHandler conversionHandler
|
||||
)
|
||||
{
|
||||
_converter = converter;
|
||||
_layerBaker = layerBaker;
|
||||
_groupBaker = groupBaker;
|
||||
_instanceBaker = instanceBaker;
|
||||
_materialBaker = materialBaker;
|
||||
_colorBaker = colorBaker;
|
||||
_autocadContext = autocadContext;
|
||||
_rootObjectUnpacker = rootObjectUnpacker;
|
||||
_conversionHandler = conversionHandler;
|
||||
}
|
||||
|
||||
public Task<HostObjectBuilderResult> Build(
|
||||
Base rootObject,
|
||||
string projectName,
|
||||
string modelName,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
// Prompt the UI conversion started. Progress bar will swoosh.
|
||||
onOperationProgressed.Report(new("Converting", null));
|
||||
|
||||
// Layer filter for received commit with project and model name
|
||||
_layerBaker.CreateLayerFilter(projectName, modelName);
|
||||
|
||||
// 0 - Clean then Rock n Roll!
|
||||
string baseLayerPrefix = _autocadContext.RemoveInvalidChars($"SPK-{projectName}-{modelName}-");
|
||||
PreReceiveDeepClean(baseLayerPrefix);
|
||||
|
||||
// 1 - Unpack objects and proxies from root commit object
|
||||
var unpackedRoot = _rootObjectUnpacker.Unpack(rootObject);
|
||||
|
||||
// 2 - Split atomic objects and instance components with their path
|
||||
var (atomicObjects, instanceComponents) = _rootObjectUnpacker.SplitAtomicObjectsAndInstances(
|
||||
unpackedRoot.ObjectsToConvert
|
||||
);
|
||||
var atomicObjectsWithPath = _layerBaker.GetAtomicObjectsWithPath(atomicObjects);
|
||||
var instanceComponentsWithPath = _layerBaker.GetInstanceComponentsWithPath(instanceComponents);
|
||||
|
||||
// POC: these are not captured by traversal, so we need to re-add them here
|
||||
if (unpackedRoot.DefinitionProxies != null && unpackedRoot.DefinitionProxies.Count > 0)
|
||||
{
|
||||
var transformed = unpackedRoot.DefinitionProxies.Select(proxy =>
|
||||
(Array.Empty<Collection>(), proxy as IInstanceComponent)
|
||||
);
|
||||
instanceComponentsWithPath.AddRange(transformed);
|
||||
}
|
||||
|
||||
// 3 - Parse and bake proxies (materials and colors), as they are used later down the line by layers and objects
|
||||
if (unpackedRoot.RenderMaterialProxies != null)
|
||||
{
|
||||
_materialBaker.ParseAndBakeRenderMaterials(
|
||||
unpackedRoot.RenderMaterialProxies,
|
||||
baseLayerPrefix,
|
||||
onOperationProgressed
|
||||
);
|
||||
}
|
||||
|
||||
if (unpackedRoot.ColorProxies != null)
|
||||
{
|
||||
_colorBaker.ParseColors(unpackedRoot.ColorProxies, onOperationProgressed);
|
||||
}
|
||||
|
||||
// 3.5 - Parse and bake additional proxies that are needed for conversion
|
||||
ParseAndBakeAdditionalProxies(rootObject, baseLayerPrefix);
|
||||
|
||||
// 4 - Convert atomic objects
|
||||
HashSet<ReceiveConversionResult> results = new();
|
||||
HashSet<string> bakedObjectIds = new();
|
||||
Dictionary<string, IReadOnlyCollection<Entity>> applicationIdMap = new();
|
||||
var count = 0;
|
||||
foreach (var (layerPath, atomicObject) in atomicObjectsWithPath)
|
||||
{
|
||||
onOperationProgressed.Report(new("Converting objects", (double)++count / atomicObjects.Count));
|
||||
var ex = _conversionHandler.TryConvert(() =>
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
string objectId = atomicObject.applicationId ?? atomicObject.id.NotNull();
|
||||
IReadOnlyCollection<Entity> convertedObjects = ConvertObject(atomicObject, layerPath, baseLayerPrefix);
|
||||
|
||||
applicationIdMap[objectId] = convertedObjects;
|
||||
|
||||
results.UnionWith(
|
||||
convertedObjects.Select(e => new ReceiveConversionResult(
|
||||
Status.SUCCESS,
|
||||
atomicObject,
|
||||
e.GetSpeckleApplicationId(),
|
||||
e.GetType().ToString()
|
||||
))
|
||||
);
|
||||
|
||||
bakedObjectIds.UnionWith(convertedObjects.Select(e => e.GetSpeckleApplicationId()));
|
||||
});
|
||||
if (ex != null)
|
||||
{
|
||||
results.Add(new(Status.ERROR, atomicObject, null, null, ex));
|
||||
}
|
||||
}
|
||||
|
||||
// 5 - Convert instances
|
||||
var (createdInstanceIds, consumedObjectIds, instanceConversionResults) = _instanceBaker.BakeInstances(
|
||||
instanceComponentsWithPath,
|
||||
applicationIdMap,
|
||||
baseLayerPrefix,
|
||||
onOperationProgressed
|
||||
);
|
||||
|
||||
bakedObjectIds.RemoveWhere(id => consumedObjectIds.Contains(id));
|
||||
bakedObjectIds.UnionWith(createdInstanceIds);
|
||||
results.RemoveWhere(result => result.ResultId != null && consumedObjectIds.Contains(result.ResultId));
|
||||
results.UnionWith(instanceConversionResults);
|
||||
|
||||
// 6 - Create groups
|
||||
if (unpackedRoot.GroupProxies != null)
|
||||
{
|
||||
IReadOnlyCollection<ReceiveConversionResult> groupResults = _groupBaker.CreateGroups(
|
||||
unpackedRoot.GroupProxies,
|
||||
applicationIdMap
|
||||
);
|
||||
results.UnionWith(groupResults);
|
||||
}
|
||||
|
||||
return Task.FromResult(new HostObjectBuilderResult(bakedObjectIds, results));
|
||||
}
|
||||
|
||||
protected void PreReceiveDeepClean(string baseLayerPrefix)
|
||||
{
|
||||
_layerBaker.DeleteAllLayersByPrefix(baseLayerPrefix);
|
||||
_instanceBaker.PurgeInstances(baseLayerPrefix);
|
||||
_materialBaker.PurgeMaterials(baseLayerPrefix);
|
||||
PreReceiveAdditionalDeepClean(baseLayerPrefix);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method for adding app-specific additional deep clean of the document prior to receiving.
|
||||
/// </summary>
|
||||
protected virtual void PreReceiveAdditionalDeepClean(string baseLayerPrefix) { }
|
||||
|
||||
/// <summary>
|
||||
/// Method for parsing and baking additional app-specific proxies on the root prior to converting and baking objects
|
||||
/// </summary>
|
||||
protected virtual void ParseAndBakeAdditionalProxies(Base rootObject, string baseLayerPrefix) { }
|
||||
|
||||
private IReadOnlyCollection<Entity> ConvertObject(Base obj, Collection[] layerPath, string baseLayerNamePrefix)
|
||||
{
|
||||
string layerName = _layerBaker.CreateLayerForReceive(layerPath, baseLayerNamePrefix);
|
||||
var convertedEntities = new HashSet<Entity>();
|
||||
|
||||
using var tr = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
|
||||
// 1: convert
|
||||
var converted = _converter.Convert(obj);
|
||||
|
||||
// 2: handle result
|
||||
switch (converted)
|
||||
{
|
||||
case Entity entity:
|
||||
var bakedEntity = BakeObject(entity, obj, layerName, tr);
|
||||
convertedEntities.Add(bakedEntity);
|
||||
break;
|
||||
|
||||
case List<(Entity, Base)> listConversionResult: // this is from fallback conversion for brep/brepx/subdx/extrusionx/polycurve
|
||||
var bakedFallbackEntities = BakeObjectsAsGroup(listConversionResult, obj, layerName, baseLayerNamePrefix, tr);
|
||||
convertedEntities.UnionWith(bakedFallbackEntities);
|
||||
break;
|
||||
|
||||
default:
|
||||
// TODO: capture defualt case with report object here? Same as in Rhino
|
||||
break;
|
||||
}
|
||||
|
||||
tr.Commit();
|
||||
return convertedEntities.Freeze();
|
||||
}
|
||||
|
||||
private Entity BakeObject(
|
||||
Entity entity,
|
||||
Base originalObject,
|
||||
string layerName,
|
||||
Transaction tr,
|
||||
Base? parentObject = null
|
||||
)
|
||||
{
|
||||
var objId = originalObject.applicationId ?? originalObject.id.NotNull();
|
||||
if (_colorBaker.ObjectColorsIdMap.TryGetValue(objId, out AutocadColor? color))
|
||||
{
|
||||
entity.Color = color;
|
||||
}
|
||||
|
||||
if (_materialBaker.TryGetMaterialId(originalObject, parentObject, out ObjectId matId))
|
||||
{
|
||||
entity.MaterialId = matId;
|
||||
}
|
||||
|
||||
entity.AppendToDb(layerName);
|
||||
|
||||
// Hook for derived classes to perform additional operations after entity is added to database
|
||||
PostBakeEntity(entity, originalObject, tr);
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method for additional app-specific operations on entities after the entity has been added to the document database.
|
||||
/// Called after the entity is added to the database in an open transaction
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="originalObject"></param>
|
||||
/// <param name="tr"></param>
|
||||
protected virtual void PostBakeEntity(Entity entity, Base originalObject, Transaction tr)
|
||||
{
|
||||
// Default implementation does nothing - override in derived classes
|
||||
}
|
||||
|
||||
private List<Entity> BakeObjectsAsGroup(
|
||||
List<(Entity, Base)> fallbackConversionResult,
|
||||
Base parentObject,
|
||||
string layerName,
|
||||
string baseLayerName,
|
||||
Transaction tr
|
||||
)
|
||||
{
|
||||
var ids = new ObjectIdCollection();
|
||||
var entities = new List<Entity>();
|
||||
foreach (var (conversionResult, originalObject) in fallbackConversionResult)
|
||||
{
|
||||
BakeObject(conversionResult, originalObject, layerName, tr, parentObject);
|
||||
ids.Add(conversionResult.ObjectId);
|
||||
entities.Add(conversionResult);
|
||||
}
|
||||
|
||||
if (entities.Count <= 1) // return if empty list or only one, because we don't want to create empty or single item groups.
|
||||
{
|
||||
return entities;
|
||||
}
|
||||
var groupDictionary = (DBDictionary)
|
||||
tr.GetObject(Application.DocumentManager.CurrentDocument.Database.GroupDictionaryId, OpenMode.ForWrite);
|
||||
|
||||
var groupName = _autocadContext.RemoveInvalidChars(
|
||||
$@"{parentObject.speckle_type.Split('.').Last()} - {parentObject.applicationId ?? parentObject.id} ({baseLayerName})"
|
||||
);
|
||||
|
||||
var newGroup = new Group(groupName, true);
|
||||
newGroup.Append(ids);
|
||||
groupDictionary.UpgradeOpen();
|
||||
groupDictionary.SetAt(groupName, newGroup);
|
||||
tr.AddNewlyCreatedDBObject(newGroup, true);
|
||||
|
||||
return entities;
|
||||
}
|
||||
}
|
||||
@@ -1,35 +1,284 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Speckle.Connectors.Autocad.HostApp;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Connectors.Common.Operations.Receive;
|
||||
using Speckle.Connectors.Autocad.HostApp.Extensions;
|
||||
using Speckle.Connectors.Utils.Builders;
|
||||
using Speckle.Connectors.Utils.Conversion;
|
||||
using Speckle.Connectors.Utils.Operations;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Objects.Other;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using Speckle.Sdk.Models.GraphTraversal;
|
||||
using Speckle.Sdk.Models.Instances;
|
||||
using Speckle.Sdk.Models.Proxies;
|
||||
using AutocadColor = Autodesk.AutoCAD.Colors.Color;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Operations.Receive;
|
||||
|
||||
/// <summary>
|
||||
/// <para>AutoCAD-specific host object builder. Expects to be a scoped dependency per receive operation.</para>
|
||||
/// <para>Expects to be a scoped dependency per receive operation.</para>
|
||||
/// </summary>
|
||||
public sealed class AutocadHostObjectBuilder : AutocadHostObjectBaseBuilder
|
||||
public class AutocadHostObjectBuilder : IHostObjectBuilder
|
||||
{
|
||||
private readonly AutocadLayerManager _autocadLayerManager;
|
||||
private readonly IRootToHostConverter _converter;
|
||||
private readonly GraphTraversal _traversalFunction;
|
||||
private readonly ISyncToThread _syncToThread;
|
||||
private readonly AutocadGroupManager _groupManager;
|
||||
private readonly AutocadMaterialManager _materialManager;
|
||||
private readonly AutocadColorManager _colorManager;
|
||||
private readonly AutocadInstanceObjectManager _instanceObjectsManager;
|
||||
private readonly AutocadContext _autocadContext;
|
||||
|
||||
public AutocadHostObjectBuilder(
|
||||
IRootToHostConverter converter,
|
||||
AutocadLayerBaker layerBaker,
|
||||
AutocadGroupBaker groupBaker,
|
||||
AutocadInstanceBaker instanceBaker,
|
||||
IAutocadMaterialBaker materialBaker,
|
||||
IAutocadColorBaker colorBaker,
|
||||
AutocadContext autocadContext,
|
||||
RootObjectUnpacker rootObjectUnpacker,
|
||||
IReceiveConversionHandler conversionHandler
|
||||
GraphTraversal traversalFunction,
|
||||
AutocadLayerManager autocadLayerManager,
|
||||
AutocadGroupManager groupManager,
|
||||
AutocadInstanceObjectManager instanceObjectsManager,
|
||||
AutocadMaterialManager materialManager,
|
||||
AutocadColorManager colorManager,
|
||||
ISyncToThread syncToThread,
|
||||
AutocadContext autocadContext
|
||||
)
|
||||
: base(
|
||||
converter,
|
||||
layerBaker,
|
||||
groupBaker,
|
||||
instanceBaker,
|
||||
materialBaker,
|
||||
colorBaker,
|
||||
autocadContext,
|
||||
rootObjectUnpacker,
|
||||
conversionHandler
|
||||
) { }
|
||||
{
|
||||
_converter = converter;
|
||||
_traversalFunction = traversalFunction;
|
||||
_autocadLayerManager = autocadLayerManager;
|
||||
_groupManager = groupManager;
|
||||
_instanceObjectsManager = instanceObjectsManager;
|
||||
_materialManager = materialManager;
|
||||
_colorManager = colorManager;
|
||||
_syncToThread = syncToThread;
|
||||
_autocadContext = autocadContext;
|
||||
}
|
||||
|
||||
public Task<HostObjectBuilderResult> Build(
|
||||
Base rootObject,
|
||||
string projectName,
|
||||
string modelName,
|
||||
Action<string, double?>? onOperationProgressed,
|
||||
CancellationToken _
|
||||
)
|
||||
{
|
||||
return _syncToThread.RunOnThread(() =>
|
||||
{
|
||||
// Prompt the UI conversion started. Progress bar will swoosh.
|
||||
onOperationProgressed?.Invoke("Converting", null);
|
||||
|
||||
// Layer filter for received commit with project and model name
|
||||
_autocadLayerManager.CreateLayerFilter(projectName, modelName);
|
||||
|
||||
string baseLayerPrefix = _autocadContext.RemoveInvalidChars($"SPK-{projectName}-{modelName}-");
|
||||
|
||||
PreReceiveDeepClean(baseLayerPrefix);
|
||||
|
||||
List<ReceiveConversionResult> results = new();
|
||||
List<string> bakedObjectIds = new();
|
||||
|
||||
var objectGraph = _traversalFunction.Traverse(rootObject).Where(obj => obj.Current is not Collection);
|
||||
|
||||
// POC: these are not captured by traversal, so we need to re-add them here
|
||||
var instanceDefinitionProxies = (rootObject["instanceDefinitionProxies"] as List<object>)
|
||||
?.Cast<InstanceDefinitionProxy>()
|
||||
.ToList();
|
||||
|
||||
var instanceComponents = new List<(Collection[] path, IInstanceComponent obj)>();
|
||||
// POC: these are not captured by traversal, so we need to re-add them here
|
||||
if (instanceDefinitionProxies != null && instanceDefinitionProxies.Count > 0)
|
||||
{
|
||||
var transformed = instanceDefinitionProxies.Select(proxy =>
|
||||
(Array.Empty<Collection>(), proxy as IInstanceComponent)
|
||||
);
|
||||
instanceComponents.AddRange(transformed);
|
||||
}
|
||||
|
||||
// POC: get colors
|
||||
List<ColorProxy>? colors = (rootObject["colorProxies"] as List<object>)?.Cast<ColorProxy>().ToList();
|
||||
if (colors != null)
|
||||
{
|
||||
_colorManager.ParseColors(colors, onOperationProgressed);
|
||||
}
|
||||
|
||||
// POC: get render materials
|
||||
List<RenderMaterialProxy>? renderMaterials = (rootObject["renderMaterialProxies"] as List<object>)
|
||||
?.Cast<RenderMaterialProxy>()
|
||||
.ToList();
|
||||
|
||||
if (renderMaterials != null)
|
||||
{
|
||||
List<ReceiveConversionResult> materialResults = _materialManager.ParseAndBakeRenderMaterials(
|
||||
renderMaterials,
|
||||
baseLayerPrefix,
|
||||
onOperationProgressed
|
||||
);
|
||||
|
||||
results.AddRange(materialResults);
|
||||
}
|
||||
|
||||
// POC: get group proxies
|
||||
var groupProxies = (rootObject["groupProxies"] as List<object>)?.Cast<GroupProxy>().ToList();
|
||||
|
||||
var atomicObjects = new List<(Collection[] layerPath, Base obj)>();
|
||||
|
||||
foreach (TraversalContext tc in objectGraph)
|
||||
{
|
||||
// create new speckle layer from layer path
|
||||
Collection[] layerPath = _autocadLayerManager.GetLayerPath(tc);
|
||||
switch (tc.Current)
|
||||
{
|
||||
case IInstanceComponent instanceComponent:
|
||||
instanceComponents.Add((layerPath, instanceComponent));
|
||||
break;
|
||||
case GroupProxy:
|
||||
continue;
|
||||
default:
|
||||
atomicObjects.Add((layerPath, tc.Current));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Stage 1: Convert atomic objects
|
||||
Dictionary<string, List<Entity>> applicationIdMap = new();
|
||||
var count = 0;
|
||||
foreach (var (layerPath, atomicObject) in atomicObjects)
|
||||
{
|
||||
string objectId = atomicObject.applicationId ?? atomicObject.id;
|
||||
onOperationProgressed?.Invoke("Converting objects", (double)++count / atomicObjects.Count);
|
||||
try
|
||||
{
|
||||
List<Entity> convertedObjects = ConvertObject(atomicObject, layerPath, baseLayerPrefix).ToList();
|
||||
|
||||
applicationIdMap[objectId] = convertedObjects;
|
||||
|
||||
results.AddRange(
|
||||
convertedObjects.Select(e => new ReceiveConversionResult(
|
||||
Status.SUCCESS,
|
||||
atomicObject,
|
||||
e.GetSpeckleApplicationId(),
|
||||
e.GetType().ToString()
|
||||
))
|
||||
);
|
||||
|
||||
bakedObjectIds.AddRange(convertedObjects.Select(e => e.GetSpeckleApplicationId()));
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
results.Add(new(Status.ERROR, atomicObject, null, null, ex));
|
||||
}
|
||||
}
|
||||
|
||||
// Stage 2: Convert instances
|
||||
var (createdInstanceIds, consumedObjectIds, instanceConversionResults) = _instanceObjectsManager.BakeInstances(
|
||||
instanceComponents,
|
||||
applicationIdMap,
|
||||
baseLayerPrefix,
|
||||
onOperationProgressed
|
||||
);
|
||||
|
||||
bakedObjectIds.RemoveAll(id => consumedObjectIds.Contains(id));
|
||||
bakedObjectIds.AddRange(createdInstanceIds);
|
||||
results.RemoveAll(result => result.ResultId != null && consumedObjectIds.Contains(result.ResultId));
|
||||
results.AddRange(instanceConversionResults);
|
||||
|
||||
// Stage 3: Create group
|
||||
if (groupProxies != null)
|
||||
{
|
||||
List<ReceiveConversionResult> groupResults = _groupManager.CreateGroups(groupProxies, applicationIdMap);
|
||||
results.AddRange(groupResults);
|
||||
}
|
||||
|
||||
return new HostObjectBuilderResult(bakedObjectIds, results);
|
||||
});
|
||||
}
|
||||
|
||||
private void PreReceiveDeepClean(string baseLayerPrefix)
|
||||
{
|
||||
_autocadLayerManager.DeleteAllLayersByPrefix(baseLayerPrefix);
|
||||
_instanceObjectsManager.PurgeInstances(baseLayerPrefix);
|
||||
_materialManager.PurgeMaterials(baseLayerPrefix);
|
||||
}
|
||||
|
||||
private IEnumerable<Entity> ConvertObject(Base obj, Collection[] layerPath, string baseLayerNamePrefix)
|
||||
{
|
||||
string layerName = _autocadLayerManager.CreateLayerForReceive(layerPath, baseLayerNamePrefix);
|
||||
var convertedEntities = new List<Entity>();
|
||||
|
||||
using var tr = Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
|
||||
|
||||
// 1: convert
|
||||
var converted = _converter.Convert(obj);
|
||||
|
||||
// 2: handle result
|
||||
if (converted is Entity entity)
|
||||
{
|
||||
var bakedEntity = BakeObject(entity, obj, layerName);
|
||||
convertedEntities.Add(bakedEntity);
|
||||
}
|
||||
else if (converted is IEnumerable<(object, Base)> fallbackConversionResult)
|
||||
{
|
||||
var bakedFallbackEntities = BakeObjectsAsGroup(fallbackConversionResult, obj, layerName, baseLayerNamePrefix);
|
||||
convertedEntities.AddRange(bakedFallbackEntities);
|
||||
}
|
||||
|
||||
tr.Commit();
|
||||
return convertedEntities;
|
||||
}
|
||||
|
||||
private Entity BakeObject(Entity entity, Base originalObject, string layerName)
|
||||
{
|
||||
var objId = originalObject.applicationId ?? originalObject.id;
|
||||
if (_colorManager.ObjectColorsIdMap.TryGetValue(objId, out AutocadColor? color))
|
||||
{
|
||||
entity.Color = color;
|
||||
}
|
||||
|
||||
if (_materialManager.ObjectMaterialsIdMap.TryGetValue(objId, out ObjectId matId))
|
||||
{
|
||||
entity.MaterialId = matId;
|
||||
}
|
||||
|
||||
entity.AppendToDb(layerName);
|
||||
return entity;
|
||||
}
|
||||
|
||||
private List<Entity> BakeObjectsAsGroup(
|
||||
IEnumerable<(object, Base)> fallbackConversionResult,
|
||||
Base originatingObject,
|
||||
string layerName,
|
||||
string baseLayerName
|
||||
)
|
||||
{
|
||||
var ids = new ObjectIdCollection();
|
||||
var entities = new List<Entity>();
|
||||
foreach (var (conversionResult, originalBaseObject) in fallbackConversionResult)
|
||||
{
|
||||
if (conversionResult is not Entity entity)
|
||||
{
|
||||
// TODO: throw?
|
||||
continue;
|
||||
}
|
||||
|
||||
BakeObject(entity, originalBaseObject, layerName);
|
||||
ids.Add(entity.ObjectId);
|
||||
entities.Add(entity);
|
||||
}
|
||||
|
||||
var tr = Application.DocumentManager.CurrentDocument.Database.TransactionManager.TopTransaction;
|
||||
var groupDictionary = (DBDictionary)
|
||||
tr.GetObject(Application.DocumentManager.CurrentDocument.Database.GroupDictionaryId, OpenMode.ForWrite);
|
||||
|
||||
var groupName = _autocadContext.RemoveInvalidChars(
|
||||
$@"{originatingObject.speckle_type.Split('.').Last()} - {originatingObject.applicationId ?? originatingObject.id} ({baseLayerName})"
|
||||
);
|
||||
|
||||
var newGroup = new Group(groupName, true);
|
||||
newGroup.Append(ids);
|
||||
groupDictionary.UpgradeOpen();
|
||||
groupDictionary.SetAt(groupName, newGroup);
|
||||
tr.AddNewlyCreatedDBObject(newGroup, true);
|
||||
|
||||
return entities;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,196 +0,0 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Autocad.HostApp;
|
||||
using Speckle.Connectors.Common.Builders;
|
||||
using Speckle.Connectors.Common.Caching;
|
||||
using Speckle.Connectors.Common.Conversion;
|
||||
using Speckle.Connectors.Common.Extensions;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Logging;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using Speckle.Sdk.Models.Instances;
|
||||
using Speckle.Sdk.Pipelines.Progress;
|
||||
using Speckle.Sdk.Pipelines.Send;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Operations.Send;
|
||||
|
||||
/// <summary>
|
||||
/// Abstract base class for AutoCAD continuous traversal builders that stream objects through a
|
||||
/// <see cref="SendPipeline"/> for packfile-based uploads. Same conversion logic as
|
||||
/// <see cref="AutocadRootObjectBaseBuilder"/>, but processes elements through the pipeline.
|
||||
/// </summary>
|
||||
public abstract class AutocadContinuousTraversalBaseBuilder : IRootContinuousTraversalBuilder<AutocadRootObject>
|
||||
{
|
||||
private readonly IRootToSpeckleConverter _converter;
|
||||
private readonly string[] _documentPathSeparator = ["\\"];
|
||||
private readonly ISendConversionCache _sendConversionCache;
|
||||
private readonly AutocadInstanceUnpacker _instanceUnpacker;
|
||||
private readonly AutocadMaterialUnpacker _materialUnpacker;
|
||||
private readonly AutocadColorUnpacker _colorUnpacker;
|
||||
private readonly AutocadGroupUnpacker _groupUnpacker;
|
||||
private readonly ILogger<AutocadRootObjectBuilder> _logger;
|
||||
private readonly ISdkActivityFactory _activityFactory;
|
||||
|
||||
protected AutocadContinuousTraversalBaseBuilder(
|
||||
IRootToSpeckleConverter converter,
|
||||
ISendConversionCache sendConversionCache,
|
||||
AutocadInstanceUnpacker instanceObjectManager,
|
||||
AutocadMaterialUnpacker materialUnpacker,
|
||||
AutocadColorUnpacker colorUnpacker,
|
||||
AutocadGroupUnpacker groupUnpacker,
|
||||
ILogger<AutocadRootObjectBuilder> logger,
|
||||
ISdkActivityFactory activityFactory
|
||||
)
|
||||
{
|
||||
_converter = converter;
|
||||
_sendConversionCache = sendConversionCache;
|
||||
_instanceUnpacker = instanceObjectManager;
|
||||
_materialUnpacker = materialUnpacker;
|
||||
_colorUnpacker = colorUnpacker;
|
||||
_groupUnpacker = groupUnpacker;
|
||||
_logger = logger;
|
||||
_activityFactory = activityFactory;
|
||||
}
|
||||
|
||||
[SuppressMessage(
|
||||
"Maintainability",
|
||||
"CA1506:Avoid excessive class coupling",
|
||||
Justification = """
|
||||
It is already simplified but has many different references since it is a builder. Do not know can we simplify it now.
|
||||
Later we might consider to refactor proxies from one proxy manager? but we do not know the shape of it all potential
|
||||
proxy classes yet. So I'm supressing this one now!!!
|
||||
"""
|
||||
)]
|
||||
public async Task<RootObjectBuilderResult> Build(
|
||||
IReadOnlyList<AutocadRootObject> objects,
|
||||
string projectId,
|
||||
SendPipeline sendPipeline,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
// 0 - Init the root
|
||||
Collection root = new()
|
||||
{
|
||||
name = Application
|
||||
.DocumentManager.CurrentDocument.Name.Split(_documentPathSeparator, StringSplitOptions.None)
|
||||
.Reverse()
|
||||
.First(),
|
||||
};
|
||||
|
||||
Document doc = Application.DocumentManager.CurrentDocument;
|
||||
using Transaction tr = doc.Database.TransactionManager.StartTransaction();
|
||||
|
||||
// 1 - Unpack the instances
|
||||
var (atomicObjects, _, instanceProxies, instanceDefinitionProxies) = _instanceUnpacker.UnpackSelection(objects);
|
||||
root[ProxyKeys.INSTANCE_DEFINITION] = instanceDefinitionProxies;
|
||||
|
||||
// 2 - Unpack the groups
|
||||
root[ProxyKeys.GROUP] = _groupUnpacker.UnpackGroups(atomicObjects);
|
||||
using (var _ = _activityFactory.Start("Converting objects"))
|
||||
{
|
||||
// 3 - Convert atomic objects and process through pipeline
|
||||
List<LayerTableRecord> usedAcadLayers = new();
|
||||
List<SendConversionResult> results = new();
|
||||
int count = 0;
|
||||
foreach (var (entity, applicationId) in atomicObjects)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
(Collection objectCollection, LayerTableRecord? autocadLayer) = CreateObjectCollection(entity, tr);
|
||||
|
||||
if (autocadLayer is not null)
|
||||
{
|
||||
usedAcadLayers.Add(autocadLayer);
|
||||
root.elements.Add(objectCollection);
|
||||
}
|
||||
|
||||
var result = await ConvertAutocadEntity(
|
||||
entity,
|
||||
applicationId,
|
||||
objectCollection,
|
||||
instanceProxies,
|
||||
projectId,
|
||||
sendPipeline
|
||||
);
|
||||
results.Add(result);
|
||||
|
||||
onOperationProgressed.Report(
|
||||
new($"Converting objects... ({count:N0} / {atomicObjects.Count:N0})", (double)++count / atomicObjects.Count)
|
||||
);
|
||||
}
|
||||
|
||||
if (results.All(x => x.Status == Status.ERROR))
|
||||
{
|
||||
throw new SpeckleException("Failed to convert all objects.");
|
||||
}
|
||||
|
||||
// 4 - Unpack the render material proxies
|
||||
root[ProxyKeys.RENDER_MATERIAL] = _materialUnpacker.UnpackMaterials(atomicObjects, usedAcadLayers);
|
||||
|
||||
// 5 - Unpack the color proxies
|
||||
root[ProxyKeys.COLOR] = _colorUnpacker.UnpackColors(atomicObjects, usedAcadLayers);
|
||||
|
||||
// add any additional properties (most likely from verticals)
|
||||
AddAdditionalProxiesToRoot(root);
|
||||
|
||||
// Process root collection and wait for all uploads
|
||||
await sendPipeline.Process(root);
|
||||
await sendPipeline.WaitForUpload();
|
||||
|
||||
return new RootObjectBuilderResult(root, results);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual (Collection, LayerTableRecord?) CreateObjectCollection(Entity entity, Transaction tr)
|
||||
{
|
||||
return (new(), null);
|
||||
}
|
||||
|
||||
public virtual void AddAdditionalProxiesToRoot(Collection rootCollection)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
private async Task<SendConversionResult> ConvertAutocadEntity(
|
||||
Entity entity,
|
||||
string applicationId,
|
||||
Collection collectionHost,
|
||||
IReadOnlyDictionary<string, InstanceProxy> instanceProxies,
|
||||
string projectId,
|
||||
SendPipeline sendPipeline
|
||||
)
|
||||
{
|
||||
string sourceType = entity.GetType().ToString();
|
||||
try
|
||||
{
|
||||
Base converted;
|
||||
if (entity is BlockReference && instanceProxies.TryGetValue(applicationId, out InstanceProxy? instanceProxy))
|
||||
{
|
||||
converted = instanceProxy;
|
||||
}
|
||||
else if (_sendConversionCache.TryGetValue(projectId, applicationId, out ObjectReference? value))
|
||||
{
|
||||
converted = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
converted = _converter.Convert(entity);
|
||||
converted.applicationId = applicationId;
|
||||
}
|
||||
|
||||
// NOTE: this is the main part that differentiate from the main root object builder
|
||||
var reference = await sendPipeline.Process(converted).ConfigureAwait(false);
|
||||
collectionHost.elements.Add(reference);
|
||||
return new(Status.SUCCESS, applicationId, sourceType, reference);
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
_logger.LogSendConversionError(ex, sourceType);
|
||||
return new(Status.ERROR, applicationId, sourceType, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Autocad.HostApp;
|
||||
using Speckle.Connectors.Common.Caching;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Sdk.Logging;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Operations.Send;
|
||||
|
||||
public sealed class AutocadContinuousTraversalBuilder : AutocadContinuousTraversalBaseBuilder
|
||||
{
|
||||
private readonly AutocadLayerUnpacker _layerUnpacker;
|
||||
|
||||
public AutocadContinuousTraversalBuilder(
|
||||
AutocadLayerUnpacker layerUnpacker,
|
||||
IRootToSpeckleConverter converter,
|
||||
ISendConversionCache sendConversionCache,
|
||||
AutocadInstanceUnpacker instanceObjectManager,
|
||||
AutocadMaterialUnpacker materialUnpacker,
|
||||
AutocadColorUnpacker colorUnpacker,
|
||||
AutocadGroupUnpacker groupUnpacker,
|
||||
ILogger<AutocadRootObjectBuilder> logger,
|
||||
ISdkActivityFactory activityFactory
|
||||
)
|
||||
: base(
|
||||
converter,
|
||||
sendConversionCache,
|
||||
instanceObjectManager,
|
||||
materialUnpacker,
|
||||
colorUnpacker,
|
||||
groupUnpacker,
|
||||
logger,
|
||||
activityFactory
|
||||
)
|
||||
{
|
||||
_layerUnpacker = layerUnpacker;
|
||||
}
|
||||
|
||||
public override (Collection, LayerTableRecord?) CreateObjectCollection(Entity entity, Transaction tr)
|
||||
{
|
||||
Layer layer = _layerUnpacker.GetOrCreateSpeckleLayer(entity, tr, out LayerTableRecord? autocadLayer);
|
||||
|
||||
return (layer, autocadLayer);
|
||||
}
|
||||
}
|
||||
@@ -1,228 +0,0 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Autodesk.AutoCAD.Geometry;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Autocad.HostApp;
|
||||
using Speckle.Connectors.Common.Builders;
|
||||
using Speckle.Connectors.Common.Caching;
|
||||
using Speckle.Connectors.Common.Conversion;
|
||||
using Speckle.Connectors.Common.Extensions;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Converters.Autocad;
|
||||
using Speckle.Converters.Autocad.Helpers;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Logging;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using Speckle.Sdk.Models.Instances;
|
||||
using Speckle.Sdk.Pipelines.Progress;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Operations.Send;
|
||||
|
||||
public abstract class AutocadRootObjectBaseBuilder : IRootObjectBuilder<AutocadRootObject>
|
||||
{
|
||||
private readonly IRootToSpeckleConverter _converter;
|
||||
private readonly IConverterSettingsStore<AutocadConversionSettings> _converterSettings;
|
||||
private readonly string[] _documentPathSeparator = ["\\"];
|
||||
private readonly ISendConversionCache _sendConversionCache;
|
||||
private readonly AutocadInstanceUnpacker _instanceUnpacker;
|
||||
private readonly AutocadMaterialUnpacker _materialUnpacker;
|
||||
private readonly AutocadColorUnpacker _colorUnpacker;
|
||||
private readonly AutocadGroupUnpacker _groupUnpacker;
|
||||
private readonly ILogger<AutocadRootObjectBuilder> _logger;
|
||||
private readonly ISdkActivityFactory _activityFactory;
|
||||
|
||||
protected AutocadRootObjectBaseBuilder(
|
||||
IRootToSpeckleConverter converter,
|
||||
IConverterSettingsStore<AutocadConversionSettings> converterSettings,
|
||||
ISendConversionCache sendConversionCache,
|
||||
AutocadInstanceUnpacker instanceObjectManager,
|
||||
AutocadMaterialUnpacker materialUnpacker,
|
||||
AutocadColorUnpacker colorUnpacker,
|
||||
AutocadGroupUnpacker groupUnpacker,
|
||||
ILogger<AutocadRootObjectBuilder> logger,
|
||||
ISdkActivityFactory activityFactory
|
||||
)
|
||||
{
|
||||
_converter = converter;
|
||||
_converterSettings = converterSettings;
|
||||
_sendConversionCache = sendConversionCache;
|
||||
_instanceUnpacker = instanceObjectManager;
|
||||
_materialUnpacker = materialUnpacker;
|
||||
_colorUnpacker = colorUnpacker;
|
||||
_groupUnpacker = groupUnpacker;
|
||||
_logger = logger;
|
||||
_activityFactory = activityFactory;
|
||||
}
|
||||
|
||||
[SuppressMessage(
|
||||
"Maintainability",
|
||||
"CA1506:Avoid excessive class coupling",
|
||||
Justification = """
|
||||
It is already simplified but has many different references since it is a builder. Do not know can we simplify it now.
|
||||
Later we might consider to refactor proxies from one proxy manager? but we do not know the shape of it all potential
|
||||
proxy classes yet. So I'm supressing this one now!!!
|
||||
"""
|
||||
)]
|
||||
public Task<RootObjectBuilderResult> Build(
|
||||
IReadOnlyList<AutocadRootObject> objects,
|
||||
string projectId,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
// 0 - Init the root
|
||||
Collection root = new()
|
||||
{
|
||||
name = Application
|
||||
.DocumentManager.CurrentDocument.Name // POC: https://spockle.atlassian.net/browse/CNX-9319
|
||||
.Split(_documentPathSeparator, StringSplitOptions.None)
|
||||
.Reverse()
|
||||
.First(),
|
||||
};
|
||||
|
||||
// TODO: better handling for document and transactions!!
|
||||
Document doc = Application.DocumentManager.CurrentDocument;
|
||||
using Transaction tr = doc.Database.TransactionManager.StartTransaction();
|
||||
|
||||
// 1 - Unpack the instances
|
||||
var (atomicObjects, atomicDefinitionObjectIds, instanceProxies, instanceDefinitionProxies) =
|
||||
_instanceUnpacker.UnpackSelection(objects);
|
||||
root[ProxyKeys.INSTANCE_DEFINITION] = instanceDefinitionProxies;
|
||||
|
||||
// 2 - Unpack the groups
|
||||
root[ProxyKeys.GROUP] = _groupUnpacker.UnpackGroups(atomicObjects);
|
||||
|
||||
// 3 - Add the Reference Point
|
||||
Matrix3d? referenceTransform = null;
|
||||
if (
|
||||
Application.DocumentManager.CurrentDocument.Editor.CurrentUserCoordinateSystem is Matrix3d matrix
|
||||
&& matrix != Matrix3d.Identity
|
||||
)
|
||||
{
|
||||
referenceTransform = matrix.Inverse();
|
||||
|
||||
/* POC: Do not attach transform to root for now! we are not consuming this in autocad/civil on receive and in revit it will undo all baked transforms :(
|
||||
var transformMatrix = ReferencePointHelper.CreateTransformDataForRootObject(matrix);
|
||||
root[ReferencePointHelper.REFERENCE_POINT_TRANSFORM_KEY] = transformMatrix;
|
||||
*/
|
||||
}
|
||||
|
||||
using (var _ = _activityFactory.Start("Converting objects"))
|
||||
{
|
||||
List<LayerTableRecord> usedAcadLayers = new(); // Keeps track of autocad layers used, so we can pass them on later to the material and color unpacker.
|
||||
List<SendConversionResult> results = new();
|
||||
int count = 0;
|
||||
|
||||
// 4 - Convert atomic objects
|
||||
foreach (var (entity, applicationId) in atomicObjects)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
// Create and add a collection for this entity if not done so already.
|
||||
(Collection objectCollection, LayerTableRecord? autocadLayer) = CreateObjectCollection(entity, tr);
|
||||
|
||||
if (autocadLayer is not null)
|
||||
{
|
||||
usedAcadLayers.Add(autocadLayer);
|
||||
root.elements.Add(objectCollection);
|
||||
}
|
||||
|
||||
SendConversionResult? result = null;
|
||||
// If this is a atomic definition object, we *do not* want to bake in the reference point transform to the object
|
||||
if (atomicDefinitionObjectIds.Contains(applicationId))
|
||||
{
|
||||
using (_converterSettings.Push(currentSettings => currentSettings with { ReferencePointTransform = null }))
|
||||
{
|
||||
result = ConvertAutocadEntity(entity, applicationId, objectCollection, instanceProxies, projectId);
|
||||
}
|
||||
}
|
||||
else // this is a selected atomic object (not part of definition)
|
||||
{
|
||||
result = ConvertAutocadEntity(
|
||||
entity,
|
||||
applicationId,
|
||||
objectCollection,
|
||||
instanceProxies,
|
||||
projectId,
|
||||
referenceTransform // set this for top level instance proxies to use if needed
|
||||
);
|
||||
}
|
||||
|
||||
results.Add(result);
|
||||
onOperationProgressed.Report(new("Converting", (double)++count / atomicObjects.Count));
|
||||
}
|
||||
|
||||
if (results.All(x => x.Status == Status.ERROR))
|
||||
{
|
||||
throw new SpeckleException("Failed to convert all objects."); // fail fast instead creating empty commit! It will appear as model card error with red color.
|
||||
}
|
||||
|
||||
// 5 - Unpack the render material proxies
|
||||
root[ProxyKeys.RENDER_MATERIAL] = _materialUnpacker.UnpackMaterials(atomicObjects, usedAcadLayers);
|
||||
|
||||
// 6 - Unpack the color proxies
|
||||
root[ProxyKeys.COLOR] = _colorUnpacker.UnpackColors(atomicObjects, usedAcadLayers);
|
||||
|
||||
// add any additional properties (most likely from verticals)
|
||||
AddAdditionalProxiesToRoot(root);
|
||||
|
||||
return Task.FromResult(new RootObjectBuilderResult(root, results));
|
||||
}
|
||||
}
|
||||
|
||||
public virtual (Collection, LayerTableRecord?) CreateObjectCollection(Entity entity, Transaction tr)
|
||||
{
|
||||
return (new(), null);
|
||||
}
|
||||
|
||||
public virtual void AddAdditionalProxiesToRoot(Collection rootCollection)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
private SendConversionResult ConvertAutocadEntity(
|
||||
Entity entity,
|
||||
string applicationId,
|
||||
Collection collectionHost,
|
||||
IReadOnlyDictionary<string, InstanceProxy> instanceProxies,
|
||||
string projectId,
|
||||
Matrix3d? transform = null
|
||||
)
|
||||
{
|
||||
string sourceType = entity.GetType().ToString();
|
||||
try
|
||||
{
|
||||
Base converted;
|
||||
if (entity is BlockReference br && instanceProxies.TryGetValue(applicationId, out InstanceProxy? instanceProxy))
|
||||
{
|
||||
// modify transform by reference point this if it is top level
|
||||
if (instanceProxy.maxDepth == 0 && transform is Matrix3d validTransform)
|
||||
{
|
||||
instanceProxy.transform = TransformHelper.ConvertToInstanceMatrix4x4(
|
||||
br.BlockTransform.PreMultiplyBy(validTransform)
|
||||
);
|
||||
}
|
||||
|
||||
converted = instanceProxy;
|
||||
}
|
||||
else if (_sendConversionCache.TryGetValue(projectId, applicationId, out ObjectReference? value))
|
||||
{
|
||||
converted = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
converted = _converter.Convert(entity);
|
||||
converted.applicationId = applicationId;
|
||||
}
|
||||
|
||||
collectionHost.elements.Add(converted);
|
||||
return new(Status.SUCCESS, applicationId, sourceType, converted);
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
_logger.LogSendConversionError(ex, sourceType);
|
||||
return new(Status.ERROR, applicationId, sourceType, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,49 +1,162 @@
|
||||
using System.Diagnostics;
|
||||
using Autodesk.AutoCAD.DatabaseServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Autocad.HostApp;
|
||||
using Speckle.Connectors.Common.Caching;
|
||||
using Speckle.Converters.Autocad;
|
||||
using Speckle.Connectors.Utils.Builders;
|
||||
using Speckle.Connectors.Utils.Caching;
|
||||
using Speckle.Connectors.Utils.Conversion;
|
||||
using Speckle.Connectors.Utils.Operations;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Sdk.Logging;
|
||||
using Speckle.Objects.Other;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using Speckle.Sdk.Models.Instances;
|
||||
using Speckle.Sdk.Models.Proxies;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Operations.Send;
|
||||
|
||||
public sealed class AutocadRootObjectBuilder : AutocadRootObjectBaseBuilder
|
||||
public class AutocadRootObjectBuilder : IRootObjectBuilder<AutocadRootObject>
|
||||
{
|
||||
private readonly AutocadLayerUnpacker _layerUnpacker;
|
||||
private readonly IRootToSpeckleConverter _converter;
|
||||
private readonly string[] _documentPathSeparator = ["\\"];
|
||||
private readonly ISendConversionCache _sendConversionCache;
|
||||
private readonly AutocadInstanceObjectManager _instanceObjectsManager;
|
||||
private readonly AutocadMaterialManager _materialManager;
|
||||
private readonly AutocadColorManager _colorManager;
|
||||
private readonly AutocadLayerManager _layerManager;
|
||||
private readonly AutocadGroupManager _groupManager;
|
||||
private readonly ISyncToThread _syncToThread;
|
||||
|
||||
public AutocadRootObjectBuilder(
|
||||
AutocadLayerUnpacker layerUnpacker,
|
||||
IRootToSpeckleConverter converter,
|
||||
IConverterSettingsStore<AutocadConversionSettings> converterSettings,
|
||||
ISendConversionCache sendConversionCache,
|
||||
AutocadInstanceUnpacker instanceObjectManager,
|
||||
AutocadMaterialUnpacker materialUnpacker,
|
||||
AutocadColorUnpacker colorUnpacker,
|
||||
AutocadGroupUnpacker groupUnpacker,
|
||||
ILogger<AutocadRootObjectBuilder> logger,
|
||||
ISdkActivityFactory activityFactory
|
||||
AutocadInstanceObjectManager instanceObjectManager,
|
||||
AutocadMaterialManager materialManager,
|
||||
AutocadColorManager colorManager,
|
||||
AutocadLayerManager layerManager,
|
||||
AutocadGroupManager groupManager,
|
||||
ISyncToThread syncToThread
|
||||
)
|
||||
: base(
|
||||
converter,
|
||||
converterSettings,
|
||||
sendConversionCache,
|
||||
instanceObjectManager,
|
||||
materialUnpacker,
|
||||
colorUnpacker,
|
||||
groupUnpacker,
|
||||
logger,
|
||||
activityFactory
|
||||
)
|
||||
{
|
||||
_layerUnpacker = layerUnpacker;
|
||||
_converter = converter;
|
||||
_sendConversionCache = sendConversionCache;
|
||||
_instanceObjectsManager = instanceObjectManager;
|
||||
_materialManager = materialManager;
|
||||
_colorManager = colorManager;
|
||||
_layerManager = layerManager;
|
||||
_groupManager = groupManager;
|
||||
_syncToThread = syncToThread;
|
||||
}
|
||||
|
||||
public override (Collection, LayerTableRecord?) CreateObjectCollection(Entity entity, Transaction tr)
|
||||
public Task<RootObjectBuilderResult> Build(
|
||||
IReadOnlyList<AutocadRootObject> objects,
|
||||
SendInfo sendInfo,
|
||||
Action<string, double?>? onOperationProgressed = null,
|
||||
CancellationToken ct = default
|
||||
)
|
||||
{
|
||||
Layer layer = _layerUnpacker.GetOrCreateSpeckleLayer(entity, tr, out LayerTableRecord? autocadLayer);
|
||||
return _syncToThread.RunOnThread(() =>
|
||||
{
|
||||
Collection modelWithLayers =
|
||||
new()
|
||||
{
|
||||
name = Application
|
||||
.DocumentManager.CurrentDocument.Name // POC: https://spockle.atlassian.net/browse/CNX-9319
|
||||
.Split(_documentPathSeparator, StringSplitOptions.None)
|
||||
.Reverse()
|
||||
.First()
|
||||
};
|
||||
|
||||
return (layer, autocadLayer);
|
||||
// TODO: better handling for document and transactions!!
|
||||
Document doc = Application.DocumentManager.CurrentDocument;
|
||||
using Transaction tr = doc.Database.TransactionManager.StartTransaction();
|
||||
|
||||
// Keeps track of autocad layers used, so we can pass them on later to the material and color unpacker.
|
||||
List<LayerTableRecord> usedAcadLayers = new();
|
||||
int count = 0;
|
||||
|
||||
var (atomicObjects, instanceProxies, instanceDefinitionProxies) = _instanceObjectsManager.UnpackSelection(
|
||||
objects
|
||||
);
|
||||
|
||||
List<SendConversionResult> results = new();
|
||||
var cacheHitCount = 0;
|
||||
|
||||
foreach (var (entity, applicationId) in atomicObjects)
|
||||
{
|
||||
ct.ThrowIfCancellationRequested();
|
||||
try
|
||||
{
|
||||
Base converted;
|
||||
if (entity is BlockReference && instanceProxies.TryGetValue(applicationId, out InstanceProxy? instanceProxy))
|
||||
{
|
||||
converted = instanceProxy;
|
||||
}
|
||||
else if (_sendConversionCache.TryGetValue(sendInfo.ProjectId, applicationId, out ObjectReference value))
|
||||
{
|
||||
converted = value;
|
||||
cacheHitCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
converted = _converter.Convert(entity);
|
||||
converted.applicationId = applicationId;
|
||||
}
|
||||
|
||||
// Create and add a collection for each layer if not done so already.
|
||||
Layer layer = _layerManager.GetOrCreateSpeckleLayer(entity, tr, out LayerTableRecord? autocadLayer);
|
||||
if (autocadLayer is not null)
|
||||
{
|
||||
usedAcadLayers.Add(autocadLayer);
|
||||
modelWithLayers.elements.Add(layer);
|
||||
}
|
||||
|
||||
layer.elements.Add(converted);
|
||||
results.Add(new(Status.SUCCESS, applicationId, entity.GetType().ToString(), converted));
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
results.Add(new(Status.ERROR, applicationId, entity.GetType().ToString(), null, ex));
|
||||
// POC: add logging
|
||||
}
|
||||
onOperationProgressed?.Invoke("Converting", (double)++count / atomicObjects.Count);
|
||||
}
|
||||
|
||||
// POC: Log would be nice, or can be removed.
|
||||
Debug.WriteLine(
|
||||
$"Cache hit count {cacheHitCount} out of {objects.Count} ({(double)cacheHitCount / objects.Count})"
|
||||
);
|
||||
|
||||
var conversionFailedAppIds = results
|
||||
.FindAll(result => result.Status == Status.ERROR)
|
||||
.Select(result => result.SourceId);
|
||||
|
||||
// Cleans up objects that failed to convert from definition proxies.
|
||||
// see https://linear.app/speckle/issue/CNX-115/viewer-handle-gracefully-instances-with-elements-that-failed-to
|
||||
foreach (var definitionProxy in instanceDefinitionProxies)
|
||||
{
|
||||
definitionProxy.objects.RemoveAll(id => conversionFailedAppIds.Contains(id));
|
||||
}
|
||||
// Set definition proxies
|
||||
modelWithLayers["instanceDefinitionProxies"] = instanceDefinitionProxies;
|
||||
|
||||
// set groups
|
||||
List<GroupProxy> groupProxies = _groupManager.UnpackGroups(atomicObjects);
|
||||
modelWithLayers["groupProxies"] = groupProxies;
|
||||
|
||||
// set materials
|
||||
List<RenderMaterialProxy> materialProxies = _materialManager.UnpackMaterials(atomicObjects, usedAcadLayers);
|
||||
modelWithLayers["renderMaterialProxies"] = materialProxies;
|
||||
|
||||
// set colors
|
||||
List<ColorProxy> colorProxies = _colorManager.UnpackColors(
|
||||
atomicObjects,
|
||||
usedAcadLayers,
|
||||
instanceDefinitionProxies
|
||||
);
|
||||
modelWithLayers["colorProxies"] = colorProxies;
|
||||
|
||||
return new RootObjectBuilderResult(modelWithLayers, results);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,30 @@
|
||||
using Speckle.Connectors.Common;
|
||||
using Speckle.Sdk.Host;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Plugin;
|
||||
|
||||
public static class AppUtils
|
||||
{
|
||||
public static Speckle.Sdk.Application App =>
|
||||
public static HostApplication App =>
|
||||
#if CIVIL3D
|
||||
HostApplications.Civil3D;
|
||||
#elif PLANT3D
|
||||
HostApplications.Plant3D;
|
||||
#elif AUTOCAD
|
||||
HostApplications.AutoCAD;
|
||||
#else
|
||||
throw new NotSupportedException();
|
||||
throw new NotImplementedException();
|
||||
#endif
|
||||
|
||||
public static HostAppVersion Version =>
|
||||
#if AUTOCAD2026 || CIVIL3D2026 || PLANT3D2026
|
||||
HostAppVersion.v2026;
|
||||
#elif AUTOCAD2025 || CIVIL3D2025 || PLANT3D2025
|
||||
HostAppVersion.v2025;
|
||||
#elif AUTOCAD2024 || CIVIL3D2024 || PLANT3D2024
|
||||
#if CIVIL3D2024
|
||||
HostAppVersion.v2024;
|
||||
#elif AUTOCAD2023|| CIVIL3D2023
|
||||
#elif AUTOCAD2025
|
||||
HostAppVersion.v2025;
|
||||
#elif AUTOCAD2024
|
||||
HostAppVersion.v2024;
|
||||
#elif AUTOCAD2023
|
||||
HostAppVersion.v2023;
|
||||
#elif AUTOCAD2022 || CIVIL3D2022
|
||||
#elif AUTOCAD2022
|
||||
HostAppVersion.v2022;
|
||||
#else
|
||||
throw new NotSupportedException();
|
||||
throw new NotImplementedException();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,29 +1,22 @@
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using Autodesk.AutoCAD.Runtime;
|
||||
using Autodesk.AutoCAD.Windows;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Speckle.Connectors.Common;
|
||||
using Speckle.Connectors.DUI;
|
||||
using Speckle.Autofac.DependencyInjection;
|
||||
using Speckle.Connectors.DUI.WebView;
|
||||
#if AUTOCAD
|
||||
using Speckle.Connectors.Autocad.DependencyInjection;
|
||||
using Speckle.Converters.Autocad;
|
||||
#elif CIVIL3D
|
||||
using Speckle.Converters.Civil3dShared;
|
||||
using Speckle.Connectors.Civil3dShared.DependencyInjection;
|
||||
#elif PLANT3D
|
||||
using Speckle.Connectors.Plant3dShared.DependencyInjection;
|
||||
using Speckle.Converters.Plant3dShared;
|
||||
#endif
|
||||
using Speckle.Connectors.Utils;
|
||||
using Speckle.Sdk.Common;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Plugin;
|
||||
|
||||
public class AutocadCommand
|
||||
{
|
||||
private static PaletteSet? PaletteSet { get; set; }
|
||||
private static readonly Guid s_id = new("7C27DD2B-86E8-4D31-B3DE-B34B267B1DC8");
|
||||
public ServiceProvider? Container { get; private set; }
|
||||
private static readonly Guid s_id = new("3223E594-1B09-4E54-B3DD-8EA0BECE7BA5");
|
||||
public SpeckleContainer? Container { get; private set; }
|
||||
private IDisposable? _disposableLogger;
|
||||
public const string COMMAND_STRING = "Speckle";
|
||||
public const string COMMAND_STRING = "SpeckleNewUI";
|
||||
|
||||
[CommandMethod(COMMAND_STRING)]
|
||||
public void Command()
|
||||
@@ -34,33 +27,26 @@ public class AutocadCommand
|
||||
return;
|
||||
}
|
||||
|
||||
PaletteSet = new PaletteSet($"Speckle", s_id)
|
||||
PaletteSet = new PaletteSet("Speckle DUI3", s_id)
|
||||
{
|
||||
Size = new Size(400, 500),
|
||||
DockEnabled = (DockSides)((int)DockSides.Left + (int)DockSides.Right),
|
||||
DockEnabled = (DockSides)((int)DockSides.Left + (int)DockSides.Right)
|
||||
};
|
||||
|
||||
var builder = SpeckleContainerBuilder.CreateInstance();
|
||||
|
||||
// init DI
|
||||
var services = new ServiceCollection();
|
||||
_disposableLogger = Connector.Initialize(AppUtils.App, AppUtils.Version);
|
||||
Container = builder
|
||||
.LoadAutofacModules(
|
||||
Assembly.GetExecutingAssembly(),
|
||||
[Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location).NotNull()]
|
||||
)
|
||||
.Build();
|
||||
|
||||
_disposableLogger = services.Initialize(AppUtils.App, AppUtils.Version);
|
||||
var panelWebView = Container.Resolve<DUI3ControlWebView>();
|
||||
|
||||
#if AUTOCAD
|
||||
services.AddAutocad();
|
||||
services.AddAutocadConverters();
|
||||
#elif CIVIL3D
|
||||
services.AddCivil3d();
|
||||
services.AddCivil3dConverters();
|
||||
#elif PLANT3D
|
||||
services.AddPlant3d();
|
||||
services.AddPlant3dConverters();
|
||||
#endif
|
||||
Container = services.BuildServiceProvider();
|
||||
Container.UseDUI();
|
||||
|
||||
var panelWebView = Container.GetRequiredService<DUI3ControlWebView>();
|
||||
|
||||
PaletteSet.AddVisual("Speckle", panelWebView);
|
||||
PaletteSet.AddVisual("Speckle DUI3 WebView", panelWebView);
|
||||
|
||||
FocusPalette();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Autodesk.AutoCAD.Runtime;
|
||||
using Speckle.Connectors.Common;
|
||||
using Speckle.Autofac;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Plugin;
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using Autodesk.Windows;
|
||||
using Speckle.Sdk;
|
||||
#if !AUTOCAD2025_OR_GREATER && !CIVIL3D2025_OR_GREATER && !PLANT3D2025_OR_GREATER
|
||||
using System.IO;
|
||||
#endif
|
||||
using Speckle.Sdk.Logging;
|
||||
|
||||
namespace Speckle.Connectors.Autocad.Plugin;
|
||||
|
||||
@@ -48,19 +47,20 @@ public class AutocadRibbon
|
||||
|
||||
private void Create()
|
||||
{
|
||||
RibbonTab tab = FindOrMakeTab("Speckle");
|
||||
RibbonPanelSource source = new() { Title = "Speckle" };
|
||||
RibbonTab tab = FindOrMakeTab("Add-ins");
|
||||
RibbonPanelSource source = new() { Title = "Speckle 2 (New Beta)" };
|
||||
RibbonPanel panel = new() { Source = source };
|
||||
tab.Panels.Add(panel);
|
||||
|
||||
RibbonToolTip speckleToolTip = new()
|
||||
{
|
||||
Title = "Speckle",
|
||||
Content = $"Next Gen Speckle Connector for {AppUtils.App.Name}",
|
||||
IsHelpEnabled = true, // Without this "Press F1 for help" does not appear in the tooltip
|
||||
};
|
||||
RibbonToolTip speckleToolTip =
|
||||
new()
|
||||
{
|
||||
Title = "Speckle 2 (New Beta)",
|
||||
Content = "Speckle Connector for " + AppUtils.App.Name,
|
||||
IsHelpEnabled = true // Without this "Press F1 for help" does not appear in the tooltip
|
||||
};
|
||||
|
||||
_ = CreateSpeckleButton("Speckle", source, null, speckleToolTip, "logo");
|
||||
_ = CreateSpeckleButton("Connector " + AppUtils.App.Name + " (New)", source, null, speckleToolTip, "logo");
|
||||
}
|
||||
|
||||
private void ComponentManager_ItemInitialized(object? sender, RibbonItemEventArgs e)
|
||||
@@ -120,7 +120,7 @@ public class AutocadRibbon
|
||||
ShowText = true,
|
||||
ToolTip = tooltip,
|
||||
HelpSource = new System.Uri("https://speckle.guide/user/autocadcivil.html"),
|
||||
Size = RibbonItemSize.Large,
|
||||
Size = RibbonItemSize.Large
|
||||
};
|
||||
|
||||
if (TryLoadPngImgSource(imageName + "16.png", out ImageSource? imageSource))
|
||||
@@ -178,9 +178,18 @@ public class AutocadRibbon
|
||||
{
|
||||
stream = assembly.GetManifestResourceStream(resource);
|
||||
}
|
||||
catch (FileLoadException) { }
|
||||
catch (FileNotFoundException) { }
|
||||
catch (NotImplementedException) { }
|
||||
catch (FileLoadException flEx)
|
||||
{
|
||||
SpeckleLog.Logger.Error(flEx, "Could not load app image source: {exceptionMessage}");
|
||||
}
|
||||
catch (FileNotFoundException fnfEx)
|
||||
{
|
||||
SpeckleLog.Logger.Error(fnfEx, "Could not find app image source: {exceptionMessage}");
|
||||
}
|
||||
catch (NotImplementedException niEx)
|
||||
{
|
||||
SpeckleLog.Logger.Error(niEx, "App image source could not be loaded: {exceptionMessage}");
|
||||
}
|
||||
|
||||
if (stream is null)
|
||||
{
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ApplicationPackage
|
||||
SchemaVersion="1.0"
|
||||
AppVersion="1.0"
|
||||
Author="AEC SYSTEMS LTD"
|
||||
Name="Speckle for AutoCAD"
|
||||
Description="Speckle for AutoCAD"
|
||||
Icon="./Contents/Resources/Logo.ico"
|
||||
ProductCode="{958850b9-3782-4e6f-b9b3-1b570e0fcae1}"
|
||||
UpgradeCode="{274de351-80aa-4972-9b45-6a93f8ce968f}"
|
||||
>
|
||||
<!-- For now, we're not updating the AppVersion & ProductCodes with each version -->
|
||||
|
||||
<CompanyDetails Name="Speckle" Url="https://speckle.systems" Email="support@speckle.systems" />
|
||||
<Components>
|
||||
<!-- AutoCAD 2022 -->
|
||||
<ComponentEntry
|
||||
AppName="Speckle.Connectors.Autocad2022"
|
||||
ModuleName="./Contents/Windows/Speckle.Connectors.Autocad2022/Speckle.Connectors.Autocad2022.dll"
|
||||
LoadOnAutoCADStartup="True"
|
||||
>
|
||||
<RuntimeRequirements OS="Win64" Platform="AutoCAD" SeriesMin="R24.1" SeriesMax="R24.1" />
|
||||
</ComponentEntry>
|
||||
|
||||
<!-- AutoCAD 2023 -->
|
||||
<ComponentEntry
|
||||
AppName="Speckle.Connectors.Autocad2023"
|
||||
ModuleName="./Contents/Windows/Speckle.Connectors.Autocad2023/Speckle.Connectors.Autocad2023.dll"
|
||||
LoadOnAutoCADStartup="True"
|
||||
>
|
||||
<RuntimeRequirements OS="Win64" Platform="AutoCAD" SeriesMin="R24.2" SeriesMax="R24.2" />
|
||||
</ComponentEntry>
|
||||
|
||||
<!-- AutoCAD 2024 -->
|
||||
<ComponentEntry
|
||||
AppName="Speckle.Connectors.Autocad2024"
|
||||
ModuleName="./Contents/Windows/Speckle.Connectors.Autocad2024/Speckle.Connectors.Autocad2024.dll"
|
||||
LoadOnAutoCADStartup="True"
|
||||
>
|
||||
<RuntimeRequirements OS="Win64" Platform="AutoCAD" SeriesMin="R24.3" SeriesMax="R24.3" />
|
||||
</ComponentEntry>
|
||||
|
||||
<!-- AutoCAD 2025 -->
|
||||
<ComponentEntry
|
||||
AppName="Speckle.Connectors.Autocad2025"
|
||||
ModuleName="./Contents/Windows/Speckle.Connectors.Autocad2025/Speckle.Connectors.Autocad2025.dll"
|
||||
LoadOnAutoCADStartup="True"
|
||||
>
|
||||
<RuntimeRequirements OS="Win64" Platform="AutoCAD" SeriesMin="R25.0" SeriesMax="R25.0" />
|
||||
</ComponentEntry>
|
||||
|
||||
<!-- AutoCAD 2026 -->
|
||||
<ComponentEntry
|
||||
AppName="Speckle.Connectors.Autocad2026"
|
||||
ModuleName="./Contents/Windows/Speckle.Connectors.Autocad2026/Speckle.Connectors.Autocad2026.dll"
|
||||
LoadOnAutoCADStartup="True"
|
||||
>
|
||||
<RuntimeRequirements OS="Win64" Platform="AutoCAD" SeriesMin="R25.1" SeriesMax="R25.1" />
|
||||
</ComponentEntry>
|
||||
</Components>
|
||||
</ApplicationPackage>
|
||||
@@ -1,61 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ApplicationPackage
|
||||
SchemaVersion="1.0"
|
||||
AppVersion="1.0"
|
||||
Author="AEC SYSTEMS LTD"
|
||||
Name="Speckle for Civil 3D"
|
||||
Description="Speckle for Civil 3D"
|
||||
Icon="./Contents/Resources/Logo.ico"
|
||||
ProductCode="{cecad7b2-daa9-4a9d-941d-737619ffd999}"
|
||||
UpgradeCode="{ccf4134d-0e24-4e91-8bf4-781ec7313bef}"
|
||||
>
|
||||
<!-- For now, we're not updating the AppVersion & ProductCodes with each version -->
|
||||
|
||||
<CompanyDetails Name="Speckle" Url="https://speckle.systems" Email="support@speckle.systems" />
|
||||
<Components>
|
||||
<!-- AutoCAD 2022 -->
|
||||
<ComponentEntry
|
||||
AppName="Speckle.Connectors.Civil3d2022"
|
||||
ModuleName="./Contents/Windows/Speckle.Connectors.Civil3d2022/Speckle.Connectors.Civil3d2022.dll"
|
||||
LoadOnAutoCADStartup="True"
|
||||
>
|
||||
<RuntimeRequirements OS="Win64" Platform="Civil3D" SeriesMin="R24.1" SeriesMax="R24.1" />
|
||||
</ComponentEntry>
|
||||
|
||||
<!-- AutoCAD 2023 -->
|
||||
<ComponentEntry
|
||||
AppName="Speckle.Connectors.Civil3d2023"
|
||||
ModuleName="./Contents/Windows/Speckle.Connectors.Civil3d2023/Speckle.Connectors.Civil3d2023.dll"
|
||||
LoadOnAutoCADStartup="True"
|
||||
>
|
||||
<RuntimeRequirements OS="Win64" Platform="Civil3D" SeriesMin="R24.2" SeriesMax="R24.2" />
|
||||
</ComponentEntry>
|
||||
|
||||
<!-- AutoCAD 2024 -->
|
||||
<ComponentEntry
|
||||
AppName="Speckle.Connectors.Civil3d2024"
|
||||
ModuleName="./Contents/Windows/Speckle.Connectors.Civil3d2024/Speckle.Connectors.Civil3d2024.dll"
|
||||
LoadOnAutoCADStartup="True"
|
||||
>
|
||||
<RuntimeRequirements OS="Win64" Platform="Civil3D" SeriesMin="R24.3" SeriesMax="R24.3" />
|
||||
</ComponentEntry>
|
||||
|
||||
<!-- AutoCAD 2025 -->
|
||||
<ComponentEntry
|
||||
AppName="Speckle.Connectors.Civil3d2025"
|
||||
ModuleName="./Contents/Windows/Speckle.Connectors.Civil3d2025/Speckle.Connectors.Civil3d2025.dll"
|
||||
LoadOnAutoCADStartup="True"
|
||||
>
|
||||
<RuntimeRequirements OS="Win64" Platform="Civil3D" SeriesMin="R25.0" SeriesMax="R25.0" />
|
||||
</ComponentEntry>
|
||||
|
||||
<!-- AutoCAD 2026 -->
|
||||
<ComponentEntry
|
||||
AppName="Speckle.Connectors.Civil3d2026"
|
||||
ModuleName="./Contents/Windows/Speckle.Connectors.Civil3d2026/Speckle.Connectors.Civil3d2026.dll"
|
||||
LoadOnAutoCADStartup="True"
|
||||
>
|
||||
<RuntimeRequirements OS="Win64" Platform="Civil3D" SeriesMin="R25.1" SeriesMax="R25.1" />
|
||||
</ComponentEntry>
|
||||
</Components>
|
||||
</ApplicationPackage>
|
||||