Compare commits

...

464 Commits

Author SHA1 Message Date
Björn Steinhagen f319e0dc1d Merge pull request #861 from specklesystems/dev
.NET Build and Publish / build-windows (push) Has been cancelled
.NET Build and Publish / build-linux (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
Dev -> Main for 3.2.2
2025-05-22 15:46:55 +02:00
Claire Kuang bdd1e61b6d adds logo to gh converter (#858)
Co-authored-by: Björn Steinhagen <steinhagen.bjoern@gmail.com>
2025-05-22 13:28:39 +00:00
Björn Steinhagen c8ceeab2d9 fix: reverting setting render material appearance (#859) 2025-05-22 15:16:11 +02:00
KatKatKateryna 81f2ed0a75 Kateryna/cnx 1615 hatch loop conversion failed (#824)
* handle hatch segments that are not a Polyline

* send elliptical curves

* support line segments

* support sending nurb curves

* send approximated Hatch with nurb2d segment

* send nurb loops for hatches

* optimize

* comment

* comments

* cut down Nurbs converter

* simplify hatch conversion

* fix nurb3d

* optimize

* rearrange

* fix ellipse bug on send

* fix rhino curves on receive

* fix single>multi conversion issue on receive

* shorten nurbs converter on send

* shorten statement

* explain 'count' var

* return multiple line segments without constructing a polyline

* comment

* refactor(autocad): refactors hatch and region conversion and fixes some bugs (#856)

* refactors hatch to speckle converter, and also fixes elevation bug

* refactors region converter

* removes excessive nurb converter

* Update Speckle.Converters.AutocadShared.projitems

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-05-22 13:03:21 +00:00
Claire Kuang 2232227a8b updates sample files to rhino 7 only components (#842) 2025-05-22 11:27:32 +00:00
Björn Steinhagen 871359738c feat: use render appearance (#827)
Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-05-22 10:47:56 +01:00
Claire Kuang ea2cb90b2e feat(grasshopper): deconstruct and create empty props (#853)
* adds ability to deconstruct speckle props, and also to create empty props

* by default add an input parameter

---------

Co-authored-by: Björn Steinhagen <steinhagen.bjoern@gmail.com>
2025-05-22 09:30:21 +00:00
Björn Steinhagen 248c96d9c2 fix: sketchup to revit colors (#857) 2025-05-22 09:18:46 +02:00
KatKatKateryna a71a9ef32c Kateryna/cnx 1570 gh send text (#841)
* add text converter to GH

* Get the first matching Property named Value

* adjust parameter description (debatable)

* add text converter to GH

* Get the first matching Property named Value

* adjust parameter description (debatable)

* add text converter to GH

* Get the first matching Property named Value

* adjust parameter description (debatable)

* fake commit

* Revert "fake commit"

This reverts commit 702fbce8d5.

* adjusts comments and factors in text scale in rhino

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-05-21 15:18:28 +00:00
Jedd Morgan ed7b6abe72 Merge pull request #854 from specklesystems/dev
.NET Build and Publish / build-windows (push) Has been cancelled
.NET Build and Publish / build-linux (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
Dev -> Main
2025-05-21 11:59:51 +01:00
Jedd Morgan c7e439b9a4 Merge pull request #855 from specklesystems/jrm/main-dev2
Update dev with changes from main
2025-05-21 11:46:14 +01:00
Jedd Morgan 817a8c0910 Merge remote-tracking branch 'origin/dev' 2025-05-21 11:36:55 +01:00
Björn Steinhagen 6f5456e082 chore(grasshopper): change button behavior from right-click to left-click (#851)
* fix: left-click enabled for `SpeckleSelectModelComponent`

* fix: left-click instead of right-click

- `RespondToMouseDown` to disable component selection when clicking the button
- `RespondToMouseUp` to respond to left-click and not right-click

* refactor: left-click instead of right-click description

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-05-21 09:26:38 +01:00
Jedd Morgan 46a5243b2b Fix(deployment): Fixed issue with Autocad Civil3D depolyment (#849)
* Fixed .NET8 versions of AutoCAD/Civil3d

* Supress cef warnings that are bugging me

* Test installers

* Back to main
2025-05-20 13:28:11 +00:00
Björn Steinhagen f35ddfa7af fix(revit): walls sweeps published duplicated (#850)
* fix: wall sweeps duplicate publish

* docs: reporting on findings

* fix: wall sweeps published duplicated

* fix: same thing for linked models
2025-05-20 14:30:19 +02:00
Claire Kuang 5a43e8c165 adds pressure pipe base curve, display value, and partdata (#844)
Co-authored-by: Björn Steinhagen <steinhagen.bjoern@gmail.com>
2025-05-20 10:25:55 +01:00
Björn Steinhagen 0b136663e4 feat: direct shape name (#846) 2025-05-20 10:24:48 +02:00
Jedd Morgan 47ac752065 Rhino align guid between 8 and 7 (#847) 2025-05-19 17:05:28 +01:00
KatKatKateryna 84f6f3fbe6 Kateryna/cnx 1498 rhino mesh conversion problem on some geometries (#836)
* move geometry to origin before meshing

* reorder stuff

* move what's relevalt to MeshExtractor

* add minEdgeLength

* comments

* add minEdge setting

* adjust variables

* fix the matrix

* move all injections outside the method (except converter)

* add methods to Extrusion and Hatches. SubD doesn't seem to be affected

* typo

* restructure

* typos

* move methods

* get min edge length

* make function available for mesh

* add method to mesh conversions

* add logic to subd

* unnecessary change; spaces

* typo

* comments

* move FarFromOrigin to extension

* remove duplicate code; adjust MeshConverter logic

* reduce threshold to 1e5

* comment

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-05-19 15:59:47 +01:00
Björn Steinhagen 05c84c92f2 feat(tekla): model dialog with suggested model name (#845)
* feat: model dialog with suggested model name

* fix: nullability
2025-05-19 14:03:00 +02:00
kekesidavid ac85dc652d fix (Revit) :Hermite Spline conversion when NURBS conversion failing (#843)
* falling back to displayvalue when nurbsspline createcurve throws an argument exception

* comment update
2025-05-16 13:48:48 +02:00
Jedd Morgan b6f18b72fa Deep clean no longer builds (#840) 2025-05-15 14:39:41 +01:00
Adam Hathcock 5080d2878c Generate HostApp specific sln and slnx (#798)
* add slnx and generate from it (but got errors)

* can generate slnx

* Can generate hostapp specific slnx

* use slnx for build and clean up

* Revert as we're still on 8 SDK

* really not use slnx for builds

* Make the code generate SLNs too

* use existing consts

* add grasshopper

* Don't generate old slns for slugs

* add SLNX info to the readme

* forgot revit 26
2025-05-15 09:53:09 +01:00
Oğuzhan Koral 485325c800 Merge pull request #838 from specklesystems/dev
.NET Build and Publish / build-windows (push) Has been cancelled
.NET Build and Publish / build-linux (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
Update dev to main
2025-05-14 22:29:28 +03:00
Jedd Morgan a62600f342 Bump SDK version (#837) 2025-05-14 19:16:38 +00:00
Jedd Morgan 21174c809f Chore(rhino): Include grasshopper sample files in build output for installers to copy to Components folder (#835)
* Copy sample files to output dir

* Just rhino 8 needs to copy
2025-05-14 19:05:47 +00:00
Oğuzhan Koral 68a0ed3334 Feat(gh): add tracking for metrics (#833)
* add MixPanel manager like v2

* add mixpanel to send and receive

* fix tests

* Delete old events

* Don't track receive and send operation

They are already tracked by UI - we shouldn't track them on low level, they always need to be tracked with UI clicks etc

* Pass account from outside

* Add email if available

* Add mixpanel to GH

* Add ui dui3 prop as default

* Remove mixpanel object from tests

* renames categories

* TODO notes for NodeRun later

* Add note for account id nullability

* Grasshopper specific send and receive info for workspace ids

* Auto property

* isMultiplayer prop for mixpanel

* fix mismatch in account id and user id

* Helper function for convertion source app name to slug

---------

Co-authored-by: Adam Hathcock <adam@hathcock.uk>
Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-05-14 21:35:20 +03:00
Jedd Morgan bee0030e42 Merge pull request #796 from specklesystems/installer-test/grasshopper
ci(grasshopper): Grasshopper Installer
2025-05-14 14:59:31 +03:00
Adam Hathcock 85abaafba3 Update to SDK 3.3.4 (#832) 2025-05-14 13:41:44 +03:00
Adam Hathcock 4e85a6cccc feat(Revit 2026) Add projects and fixes for Revit 2026 usage (#736)
* add base revit 26 projects

* fix up cef replacement

* fix up revit 2026 events

* add revit events

* fixes for revit 26

* use right version of DI for Revit26

* add Revit26 to local

* fmt

* use visual studio to fix slns

* Add revit to installer constants

* move webview stuff to 2026 specific area to avoid build issues

* update locks

* Revit 2026 wants to invoke scripts with RevitTask.  Abstract RevitTask

* fmt

* fix project copying

* use 3.2 SDK

* fix build

* Revit 2025 is now CEF vulnerable

* add SendProgress to not overload revit context

* update Revit 26 lock files

* update locks

---------

Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
2025-05-14 12:55:00 +03:00
Adam Hathcock 8c4bc75a69 Ensure only the correct document is what we save the current model cards to. (#831) 2025-05-14 10:06:10 +01:00
Adam Hathcock 44920f7727 fix (dev) Don't throw exceptions but handle missing model cards and log it. (#784)
* Don't throw exceptions but handle missing model cards and log it.

* Change another thing to not throw

* RunMain for Revit should always run on the Revit context

* add comment
2025-05-13 12:39:42 +00:00
Adam Hathcock 87b81c4201 Active Revit document can be null (#829) 2025-05-13 13:28:10 +01:00
Oğuzhan Koral 882c938729 feat(Grasshopper): adds Grasshopper (#789)
* feat: Boilerplate project for Grasshopper v3

* Working POC receive with working Rhino conversions

* v3 Receive outputs most objects, very basic

* feat: Working initial nodes

Receive, Collection, URL parsing for models, root object unpacking

* feat: unpacking logic wip

* feat: total wip expand collection node

* wip

* wip

* feat: adds value type component, all is very raw and wip

* mega wips

* wip wip

* wip

* wip

* wip: conversions (wip!)

* wip: centralises converter access in grasshopper

makes life... easier

* wip: filter objects by path

* wip: various cleanup

* wip: more cleanup and comments

* dev merge build fixes

* Adds Alan's select model component

* adds point, pointcloud, and hatch display to grasshopper object

* adds send component

* fixes send component and adds additional bitmap icons

* Update GrasshopperSendOperation.cs

* adds url to send component

* fixes fallback conversion bug

* feat(grasshopper): asyncify send and receive nodes (#694)

* adds async component base

* adds reference to async component

* adds async to send component

* updates receive async to be a separate component

also adds cancellation, auto receive, progress

* package lock updates

* updates send async with cancellation, progress, and more

* Update packages.lock.json

* Update Local.sln

* reorganize classes

- refactor create collection node to not duplicate logic
- adds model object support to object goo cast method

* adds bake to params

* castfrom bug

* fix converter bugs after dev merge

* adds layer baker and bake to objects

* cleans up typed converters for brep, extrusion, subd

* fixes modelobject casting

* adds bake to object param

* updates object and collection baking

* feat(grasshopper): add property receive nodes (#690)

* adds property path selector and filter by path components

* Update PropertyGroupPathsSelector.cs

* Auto stash before merge of "claire/cnx-1428-property-paths-selector-node" and "origin/claire/cnx-1428-property-paths-selector-node"

* fix dev merge issues

* Update packages.lock.json

* Create packages.lock.json

---------

Co-authored-by: Dimitrie Stefanescu <didimitrie@gmail.com>

* refactors everything to use new speckle collection class

* fixes bake bug

* uses observable collections to add proper baking to create collection nodes

* Update SpeckleCollectionWrapper.cs

* fix/feat: various

re-applies topology; prevents mutation on send; renames wrapper classes to have wrapper in name etc.

* chore: package.lock.json commit.

this might be not needed?

* feat(grasshopper): polishes property filtering nodes (#714)

* refactors properties to cast to simple types

* updates property groups

* merge conflict fixes

* fixes property group bugs

* fixes model object property group cast

* fixes property group cast

* update param category

* fixes output tree generation

* supports model object casting in the path selector

note: model objects will also register in the path list, along with their props. need to fix this

* feat(grasshopper): add create data object node (#719)

* Avoid multiple enumeration issues when saving if we copy the list first (#713)

* add create data object component

* fixes extrusion display

* adds name and user strings dynamically to output model objects

---------

Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>

* Revert "feat(grasshopper): add create data object node (#719)"

This reverts commit 04bd151da3.

* feat(grasshopper): adds create object node (#724)

* Avoid multiple enumeration issues when saving if we copy the list first (#713)

* add create data object component

* fixes extrusion display

* adds name and user strings dynamically to output model objects

* undo geometry list to geometry in object goo

* Update SpeckleGrasshopperObject.cs

---------

Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>

* adds create property group component (#725)

* fixes property bug

* more prop casting fixes

* feat(grasshopper): add support for grasshopper in rhino 7 (#733)

* moves gh 8 to shared project

* adds grasshopper 7

* moves model object logic into partial class files

* Update Local.sln

* adds brep extrusion and subd receive to data objects

* Update DataObjectConverter.cs

* package locks

* feat(grasshopper): add support for sending and receiving colors (#745)

* feat (revit): receive Region as native FilledRegion (#696)

* regions with failed viewId

* render stuff in the first found suitable view

* use native or fallback conversion depending on the view

* better comments

* implement conditional conversion

* remove comment

* comment

* unload Root Host converter

* fix highlighting the model

* inject PlanView converter

* specify views in which receive is supported

* throw unsupported views in advance

* remove redundant check

* ViewManager added; View check is moved to the beginning of receive operation (to throw once and not for every object)

* simplify and remove unused

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>

* adds color baker to receive

* Update SpeckleGrasshopperObject.ModelObjects.cs

* adds colors on send

* Update GrasshopperColorUnpacker.cs

* removes host object builder (unneeded)

* fixes navisworks package locks

---------

Co-authored-by: KatKatKateryna <89912278+KatKatKateryna@users.noreply.github.com>

* fixes layer baking (#746)

* adds preview to speckle object params (#747)

* fix(grasshopper): renames collections, publish, and load (#748)

* renames collections, publish, and load names

* adds bool run to sync load and publish

* creates expand object component (#750)

also refactors previews for collections to be on the parameter

* chore(grasshopper): changes collection path selector to omit input collection name (#751)

* changes collection path selector to omit input collection name

also fixes preview bug in collections

* changes direct object path to colleciton name instead of "_"

* fixes path bug for objects directly inside input collection

* feat(grasshopper): add support for sending and receiving render materials (#753)

* adds support for render materials on receive and create speckle object

also adds a speckle material wrapper and param

* fixes receiving and baking bugs

* Update GrasshopperColorUnpacker.cs

* Update GrasshopperSendOperation.cs

* update locks

* feat(grasshopper): adds regex search to valueset component (#754)

* adds regex search to valueset component

* Update SpecklePropertyWrapper.cs

* cleans run

* feat(grasshopper): adds icons to all components  fml (#755)

* adds param icons

* adds all icons

* Update FilterPropertiesByPropertyGroupPaths.cs

* Update Speckle.Connectors.GrasshopperShared.projitems

* fixes async send exception (#758)

* small fix to publish to include created version

* simplifies speckle model resource to model link

* dev changes

* more dev merge fixes

* Revert "more dev merge fixes"

This reverts commit 1323c336c7.

* Revert "dev changes"

This reverts commit c5ff149bb6.

* Revert "Merge branch 'dev' into grasshopper"

This reverts commit 8bcc70cced, reversing
changes made to 2ae80cc7ba.

* fixes material baking on objects (#767)

* not really a fix, but optimizes enumeration (#769)

* fixes exception, and also removes dynamic keys prop (#772)

* adds better tooltip and warning (#773)

* adds casting from speckle object to model object (#774)

* feat(grasshopper): adds render material to model object cast if it exists (#775)

* adds casting from speckle object to model object

* casts render material if it exists

* Update SpeckleGrasshopperObject.cs

* fixes send async issue

* feat(grasshopper): add filter objects node (#778)

* updates resources

* adds a temporary filter object component

* Update GetCollectionObjects.cs

* fixes bugs in collection and filter nodes

* adds nuget

* adds missing package references

* adds missing prop

* fixes default render material bug (#779)

* feat(grasshopper): changes expand obj node to deconstruct node (#781)

* changes expand obj to deconstruct

* Update ComponentUtils.cs

* fixes bug in deconstruct node

* update package locks

* Reverted revithostobjectbuilder to match dev

* Reverted revit converter to match dev

* reverts changes to various files in importers, local, and sdk

* reverts changes to tests and rhino send binding

* updates local with grasshopper

* more merge conflict resolutions

* more merge conflict build fixes

* removes extra tests

* removes unused package locks

* feat(grasshopper): adds casting of collections to model layers (#790)

* adds casting to model layers

* Account Service fixes

* feat(grasshopper): make create object a passthrough (#791)

* changes create speckle object to a passthrough node

also adds casting from model object to material and properties

* Update SpeckleMaterialWrapper.ModelObjects.cs

* repackages objects into data objects on send (#794)

* allows for creation of multiple property groups (#799)

* bump nuget

* refactor(grasshopper): removes Base inheritance on wrappers (#802)

* removes base inheritance and adds new speckleWrapper class

* removes all base inheritence

* small send bugs

* Feat(gh): add search to account and project node (#804)

* Add search and show more components for projects, models, versions

* Cleanup

* Proper button for show more versions

* Fix build errors

* feat(grasshopper): filter objects node now outputs list of removed objects (#805)

* allows for creation of multiple property groups

* adds second output to filter objects component

* removes load on open option

* add path to create speckle object output

* Update CreateSpeckleObject.cs

* Update FilterSpeckleObjects.cs

* feat(grasshopper): add layer to model object casting (#807)

* preserves layer on model object casting, if exists

* Update SpeckleCollectionWrapper.cs

* adds deep copying and fixes more mutations in create collection and send

* adds casting of speckle mat to render mat, and hides url param

* bug fixes

* removes dataobject grouping (#809)

* fix(grasshopper): adds support for pointcloud and hatch (#811)

* adds missing pointcloud and hatch conversions

* changes name of create speckle object

* removes passthrough speckle object name change

* should fix topology issue

* throws clearer exception when casting unbaked model objects to speckle objects

* Dim/gh props (#812)

* feat: makes property creation node item based

* feat: makes property paths selector output a flat list regardless of input structure

* feat: adds simple & clean get obj props

* feat: leaner output param diff

allows for connections to be held when swapping nodes and such

* feat: cleanup (replaces old component with new)

* adds error and returns in case of bad type input in create props

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>

* fix(grasshopper): materials stuff (#816)

* fixed by always sending new id on the wrapper.

* Update CreateSpeckleObject.cs

* fix(grasshopper): more material bugs (#817)

* fixes render material proxy assignment bug

* retrieves model object color and material depending on source

* chore(grasshopper): adjusts icons and names (#818)

* adjusts icon sizes, cleans up names

* removes wrongly sized icons

* update locks

* Update GrasshopperReceiveOperation.cs

* feat(grasshopper): adds sample scripts and documentation (#822)

* adds docs and sample scripts

* Update Speckle Grasshopper - Sample Scripts.gh

* updates sample scripts and docs

* fixed units (#823)

* removes unneeded files

* removes changes to unrelated files

* re-adds missing controlpoint converter

* oops wrong folder

* Update ControlPointToSpeckleConverter.cs

* fixes geometry mutation bug in speckle object passthrough node

* Feat(gh): workspaces and search wizard (#820)

* WIP

* Menu handlers for projects and models

* Extract all handlers outside

* Remove account from handlers

* Reset version count

* Add workspaces

* Introduce SpeckleOperationWizard

* Move sync ops to dev section

* Fix sdk remainings

* Organize files and namespaces

* Remove context menu setters

* Bump sdk to 3.3.0

* Get the last selected account id from config

* Add workspaces to select model component

* Handle workspaces

* Add separator at ctor

* Get rid of from last fetched collections in wizard

* Reorder public privy functions

* Bump sdk 3.3.3 for project with permissions

* Remove expire solution on account change

* Move SolveInstanceWithUrlInput to wizard

* Better state handling on search

* handle account switch

* close menu explicitly when reset

* Have workspace logo

* Don't populate menu completely after search

* Logo as prop in workspaces

* Create a workspace flow

* Bump sdk back to 3.3.3

* Fixed DI

* Fix unplug URL state

* Set icon null when reset workspace

* personal projects as workspace

* Handle project permissions over pasted URL

* Clean up the main component

* handle all errors at the top level for wizard component

* Set last used account id to config

* Change the message level to warning for accounts

---------

Co-authored-by: Adam Hathcock <adam@hathcock.uk>

---------

Co-authored-by: Alan Rynne <alan@speckle.systems>
Co-authored-by: Dimitrie Stefanescu <didimitrie@gmail.com>
Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>
Co-authored-by: KatKatKateryna <89912278+KatKatKateryna@users.noreply.github.com>
Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
Co-authored-by: oguzhankoral <oguzhankoral@gmail.com>
Co-authored-by: Adam Hathcock <adam@hathcock.uk>
2025-05-13 12:47:39 +03:00
Oğuzhan Koral b42aa1d7fb Merge branch 'dev' into grasshopper 2025-05-13 12:19:07 +03:00
Oğuzhan Koral bed7376982 Feat(gh): workspaces and search wizard (#820)
* WIP

* Menu handlers for projects and models

* Extract all handlers outside

* Remove account from handlers

* Reset version count

* Add workspaces

* Introduce SpeckleOperationWizard

* Move sync ops to dev section

* Fix sdk remainings

* Organize files and namespaces

* Remove context menu setters

* Bump sdk to 3.3.0

* Get the last selected account id from config

* Add workspaces to select model component

* Handle workspaces

* Add separator at ctor

* Get rid of from last fetched collections in wizard

* Reorder public privy functions

* Bump sdk 3.3.3 for project with permissions

* Remove expire solution on account change

* Move SolveInstanceWithUrlInput to wizard

* Better state handling on search

* handle account switch

* close menu explicitly when reset

* Have workspace logo

* Don't populate menu completely after search

* Logo as prop in workspaces

* Create a workspace flow

* Bump sdk back to 3.3.3

* Fixed DI

* Fix unplug URL state

* Set icon null when reset workspace

* personal projects as workspace

* Handle project permissions over pasted URL

* Clean up the main component

* handle all errors at the top level for wizard component

* Set last used account id to config

* Change the message level to warning for accounts

---------

Co-authored-by: Adam Hathcock <adam@hathcock.uk>
2025-05-13 00:23:09 +03:00
Björn Steinhagen 3b6623e51a feat(revit): rebar displayValue options on send (#821)
* feat: add send rebars as solid toggle

* feat: rebar `displayValue` default of centrelines

* feat: sending rebars as solid poc

- need to refactor to avoid duplicate code
- is this the best way? what if user view isn't fine?

* refactor: extract common code and code comments

* refactor: reduce code duplication in DisplayValueExtractor with record

* refactor: wording volumetric not solid
2025-05-12 20:16:23 +02:00
Björn Steinhagen e55b936863 fix(revit): handling colors (#826)
* fix: material colors poc

* refactor: cleaning the hack

* docs: live pr comments
2025-05-12 19:48:29 +02:00
Claire Kuang 3b4cdc8897 fixes geometry mutation bug in speckle object passthrough node 2025-05-12 15:34:21 +01:00
Claire Kuang 8bedc9dd97 Update ControlPointToSpeckleConverter.cs 2025-05-12 14:39:11 +01:00
Claire Kuang eaa783cc1f oops wrong folder 2025-05-12 14:35:16 +01:00
Claire Kuang 8c2ded58b2 re-adds missing controlpoint converter 2025-05-12 14:33:41 +01:00
Claire Kuang c384c0fa15 Merge branch 'dev' into grasshopper 2025-05-12 14:10:51 +01:00
Claire Kuang cfcf68daa8 removes changes to unrelated files 2025-05-12 13:50:46 +01:00
KatKatKateryna 1116f8d16d Kateryna/cnx 1762 texts inside dynamic blocks (#819)
* first pass: read AttributeReference instead of AttributeDefinition

* fix transformation matrix

* cleaning

* add unique appIDs,, convert definitions always if there are attributes

* assign reference appId

* split the condition

* move attributes to list

* add attribute change event; reduce logic

* unused import

* comment

* comments
2025-05-12 13:46:31 +01:00
Claire Kuang 84a445eba8 Merge branch 'dev' into grasshopper 2025-05-12 13:41:12 +01:00
Claire Kuang da13a90a4e removes unneeded files 2025-05-12 13:39:40 +01:00
Claire Kuang d0ab0494d9 fixed units (#823) 2025-05-11 12:31:19 +01:00
Claire Kuang b0f6f86c53 feat(grasshopper): adds sample scripts and documentation (#822)
* adds docs and sample scripts

* Update Speckle Grasshopper - Sample Scripts.gh

* updates sample scripts and docs
2025-05-11 11:57:38 +01:00
Björn Steinhagen 71eeb1bcef fix(revit): publish id instead of name for type id (#806)
* fix: explicit check for "Type ID" and subsequent send of id

* fix: internal definition name

* docs: some comments

* refactor: internal name check in ParseParametersSet not GetValue

* fix: ToString for id return

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-05-08 21:04:35 +02:00
Björn Steinhagen d31a48c27a fix(revit): ITransformable objects loading in groups and duplicated (#813) 2025-05-08 10:32:48 +02:00
Claire Kuang 2d06bdf0ce Update GrasshopperReceiveOperation.cs 2025-05-07 20:08:57 +01:00
Claire Kuang 414702bba1 Merge branch 'grasshopper' of https://github.com/specklesystems/speckle-sharp-connectors into grasshopper 2025-05-07 19:51:50 +01:00
Claire Kuang 512ab1104e update locks 2025-05-07 19:51:45 +01:00
Claire Kuang f1e0ca8631 chore(grasshopper): adjusts icons and names (#818)
* adjusts icon sizes, cleans up names

* removes wrongly sized icons
2025-05-07 19:40:05 +01:00
Claire Kuang b509948061 Merge branch 'dev' into grasshopper 2025-05-07 19:07:50 +01:00
Claire Kuang ea9c5ad1c5 fix(grasshopper): more material bugs (#817)
* fixes render material proxy assignment bug

* retrieves model object color and material depending on source
2025-05-07 17:45:19 +01:00
Adam Hathcock 62b6e873c4 Use SDK 3.3.0 (#815)
* Update to 3.3.0-alpha.18

* add null check for receive

* use 3.3.0 final
2025-05-07 13:08:12 +01:00
Claire Kuang bdd7ad96b8 Merge branch 'dev' into grasshopper 2025-05-07 08:54:21 +01:00
Claire Kuang 8ce4573169 fix(grasshopper): materials stuff (#816)
* fixed by always sending new id on the wrapper.

* Update CreateSpeckleObject.cs
2025-05-06 19:14:25 +01:00
Claire Kuang 0d2201328b refactor(civil3d): alignment spiral direction throws exception (#788)
* adds property exception handler

* Update CorridorHandler.cs

* Update PropertyHandler.cs

* Update AlignmentSubentityArcToSpeckleRawConverter.cs
2025-05-06 17:07:00 +00:00
KatKatKateryna a7101a5227 Kateryna/cnx 1537 autocad send text (#808)
* send DBText (except justification)

* fixed justification

* comments

* mtext added

* update properties

* support alignments

* comments
2025-05-06 17:56:14 +01:00
KatKatKateryna 87dc15a3f3 feat (rhino): send text (#739)
* support TextEntity

* add alignment; split to lines

* add rotation; add textDot converter

* simplify text splitting check

* adapt to changes in Text class

* fix

* optimize

* adjust namespace

* global usings

* more specific alignment conversions

* aesthetic fixes

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-05-06 11:34:38 +01:00
Dimitrie Stefanescu 830ec5dd80 Dim/gh props (#812)
* feat: makes property creation node item based

* feat: makes property paths selector output a flat list regardless of input structure

* feat: adds simple & clean get obj props

* feat: leaner output param diff

allows for connections to be held when swapping nodes and such

* feat: cleanup (replaces old component with new)

* adds error and returns in case of bad type input in create props

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-05-06 09:49:51 +01:00
Claire Kuang 288f344036 throws clearer exception when casting unbaked model objects to speckle objects 2025-05-05 19:08:58 +01:00
Claire Kuang 88969d2cc6 should fix topology issue 2025-05-05 16:58:58 +01:00
Claire Kuang 29952926ad removes passthrough speckle object name change 2025-05-05 15:18:57 +01:00
Claire Kuang 92ba334728 fix(grasshopper): adds support for pointcloud and hatch (#811)
* adds missing pointcloud and hatch conversions

* changes name of create speckle object
2025-05-05 15:08:27 +01:00
Claire Kuang 9cb6aa8cdc removes dataobject grouping (#809) 2025-05-05 14:10:06 +01:00
Claire Kuang 0f3103c779 Merge branch 'dev' into grasshopper 2025-05-05 10:49:00 +01:00
kekesidavid 7c7692b472 skip converting breps/mehses with skew transform (#801)
* skip converting meshes with skew transform

* catching all exceptions if creating scale in revit transform fails
2025-05-05 11:40:50 +02:00
Claire Kuang d49a673722 feat(grasshopper): add layer to model object casting (#807)
* preserves layer on model object casting, if exists

* Update SpeckleCollectionWrapper.cs

* adds deep copying and fixes more mutations in create collection and send

* adds casting of speckle mat to render mat, and hides url param

* bug fixes
2025-05-04 20:45:49 +01:00
Claire Kuang eeb7ab6810 feat(grasshopper): filter objects node now outputs list of removed objects (#805)
* allows for creation of multiple property groups

* adds second output to filter objects component

* removes load on open option

* add path to create speckle object output

* Update CreateSpeckleObject.cs

* Update FilterSpeckleObjects.cs
2025-05-02 13:14:51 +01:00
Claire Kuang 932ca98666 Merge branch 'dev' into grasshopper 2025-05-01 21:36:09 +01:00
oguzhankoral 0a828d6a89 Fix build errors 2025-05-01 21:50:58 +03:00
Oğuzhan Koral e843f3570d Feat(gh): add search to account and project node (#804)
* Add search and show more components for projects, models, versions

* Cleanup

* Proper button for show more versions
2025-05-01 21:30:41 +03:00
Claire Kuang d87adfdcee refactor(grasshopper): removes Base inheritance on wrappers (#802)
* removes base inheritance and adds new speckleWrapper class

* removes all base inheritence

* small send bugs
2025-05-01 16:45:41 +01:00
KatKatKateryna b86a5d8902 update package version (#800) 2025-05-01 10:02:18 +01:00
Claire Kuang c14997e70f bump nuget 2025-04-30 18:20:53 +01:00
Claire Kuang e65bf42dda Merge branch 'grasshopper' of https://github.com/specklesystems/speckle-sharp-connectors into grasshopper 2025-04-30 18:19:16 +01:00
Claire Kuang 938c1c7371 Merge branch 'dev' into grasshopper 2025-04-30 18:19:01 +01:00
Claire Kuang ecabf4ba92 allows for creation of multiple property groups (#799) 2025-04-30 18:17:53 +01:00
Oğuzhan Koral 0483815f7e Merge pull request #797 from specklesystems/dev
.NET Build and Publish / build-windows (push) Has been cancelled
.NET Build and Publish / build-linux (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
Update dev into main
2025-04-30 17:06:42 +03:00
Björn Steinhagen c958157f17 fix(revit): create DirectShapes under respective categories (#795)
* fix: getting builtinCategory

i think this has moved from atomicObject level to inside properties (at some stage) which broke this and caused category to always be null

* docs: comment on accessing builtInCategory

* docs: extra comment

* docs: live pr review

* refactor: not loud about missing property anymore :(
2025-04-30 12:54:00 +02:00
Björn Steinhagen e3656394d0 Merge pull request #793 from specklesystems/bjorn/cnx-1524-revit-receive-reference-point-setting
feat(revit): receive reacts to rootObject reference point setting
2025-04-30 13:36:09 +03:00
Adam Hathcock b6b3e4514f chore(dev) Clean up references for Local.sln (#787)
* Revert "main (revert)  Back to sdk 3.1.8 (#777)"

This reverts commit 4a8bde2ed6.

* update to 3.2.1

* Clean up references for Local.sln
2025-04-29 17:15:09 +01:00
Claire Kuang cd29d08f0b repackages objects into data objects on send (#794) 2025-04-29 13:46:25 +01:00
Adam Hathcock d15d170b7c update(dev) Use SDK 3.2.1 (#785)
* Revert "main (revert)  Back to sdk 3.1.8 (#777)"

This reverts commit 4a8bde2ed6.

* update to 3.2.1

---------

Co-authored-by: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com>
2025-04-29 14:26:14 +03:00
Björn Steinhagen 4e5a415ae6 fix(revit): send reference setting is broken (#792)
* fix: main model DocumentToConvert with transform

- was previously hard-coded to null, therefore never transformed

* fix: accounting for reference point setting w linked model

combine mainModelTransform and linkedModel.GetTotalTransform().Inverse to align the linked model’s elements correctly under the main model’s chosen reference point.
2025-04-28 11:34:42 +02:00
Claire Kuang 2b63125018 feat(grasshopper): make create object a passthrough (#791)
* changes create speckle object to a passthrough node

also adds casting from model object to material and properties

* Update SpeckleMaterialWrapper.ModelObjects.cs
2025-04-25 18:01:14 +01:00
Claire Kuang 3e3246d1af feat(grasshopper): adds casting of collections to model layers (#790)
* adds casting to model layers

* Account Service fixes
2025-04-25 15:32:01 +01:00
Claire Kuang a51e20ae39 removes unused package locks 2025-04-25 14:48:26 +01:00
Claire Kuang d449938b7f removes extra tests 2025-04-25 14:45:46 +01:00
Claire Kuang e98f3364aa more merge conflict build fixes 2025-04-25 14:39:07 +01:00
Claire Kuang 5063d26f86 more merge conflict resolutions 2025-04-25 14:23:24 +01:00
Claire Kuang f225e53806 updates local with grasshopper 2025-04-25 14:06:39 +01:00
Claire Kuang 25d2a2b02e reverts changes to tests and rhino send binding 2025-04-25 14:02:25 +01:00
Claire Kuang 1231b62ea7 reverts changes to various files in importers, local, and sdk 2025-04-25 13:57:56 +01:00
Claire Kuang 1852838897 Reverted revit converter to match dev 2025-04-25 13:40:15 +01:00
Claire Kuang 655f922e38 Reverted revithostobjectbuilder to match dev 2025-04-25 13:32:32 +01:00
Claire Kuang 4c89b86f2a update package locks 2025-04-25 13:20:02 +01:00
Claire Kuang c48e3bee36 Merge branch 'dev' into grasshopper 2025-04-25 13:16:32 +01:00
jhdempsey86 5f08a784ff fix(civil3d): Fix further alignment spiral/arc/line bug (#740)
* Caught error with SpiralDirection

Caught error with SpiralDirection

* Applied a fix to getting all AlignmentSubEntitySpiral properties so they return null if an exception is thrown

* Applied same solution to AlignmentSubentityArcToSpeckleRawConverter and AlignmentSubentityLineToSpeckleRawConverter

* Update AlignmentSubentitySpiralToSpeckleRawConverter.cs

* Update AlignmentSubentitySpiralToSpeckleRawConverter.cs

* formatting

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-04-25 13:03:03 +01:00
Jedd Morgan 3c831646b1 Merge pull request #786 from specklesystems/jrm/main-to-dev
Main -> dev
2025-04-24 15:22:23 +01:00
Jedd Morgan e80d67c0b5 Merge branch 'dev' into jrm/main-to-dev 2025-04-24 14:54:22 +01:00
Jedd Morgan 27a1d50a78 refactor(ci): Update workflow to use new consolidated deployment workflow (#743)
.NET Build and Publish / build-windows (push) Has been cancelled
.NET Build and Publish / build-linux (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
* Ci experiment

* with comma

* is_public_release

* Pass fileversion via envars

* semver

* to main

* keep fetch depth on linux

* last test (tm)

* Updated workflow-dispatch

* Fetch depth now required for prs too

* and for tests too

* target main
2025-04-24 16:44:06 +03:00
Jedd Morgan 9e28c95a3c Merge pull request #783 from specklesystems/jrm/dev-main
Dev -> Main
2025-04-24 13:02:17 +01:00
Jedd Morgan b1973b561f Merge pull request #776 from specklesystems/jrm/main-dev
Back merge Main -> Dev
2025-04-24 12:54:30 +01:00
Jedd Morgan 5e61a35c53 Merge branch 'main' into jrm/dev-main 2025-04-24 12:52:27 +01:00
Jedd Morgan bfe390ef80 Merge remote-tracking branch 'origin/main' into jrm/main-dev 2025-04-24 12:45:34 +01:00
Claire Kuang 43685aff56 fixes bug in deconstruct node 2025-04-24 10:34:14 +01:00
Claire Kuang bf2168b149 feat(grasshopper): changes expand obj node to deconstruct node (#781)
* changes expand obj to deconstruct

* Update ComponentUtils.cs
2025-04-23 19:13:47 +01:00
Claire Kuang ed45b876c1 fixes default render material bug (#779) 2025-04-23 16:20:15 +01:00
Claire Kuang c1d29f3269 feat(grasshopper): add filter objects node (#778)
* updates resources

* adds a temporary filter object component

* Update GetCollectionObjects.cs

* fixes bugs in collection and filter nodes

* adds nuget

* adds missing package references

* adds missing prop
2025-04-23 13:00:00 +01:00
Adam Hathcock 4a8bde2ed6 main (revert) Back to sdk 3.1.8 (#777)
.NET Build and Publish / build-windows (push) Has been cancelled
.NET Build and Publish / build-linux (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
* Revert to 3.1.8 SDK

* Unreact to SDK 3.2
2025-04-22 17:55:17 +01:00
Jedd Morgan a405d2fb2e Merge branch 'dev' into jrm/main-dev 2025-04-22 16:37:49 +01:00
Claire Kuang 3430fde41b fixes send async issue 2025-04-22 10:37:10 +01:00
Claire Kuang f70b2a77d5 feat(grasshopper): adds render material to model object cast if it exists (#775)
* adds casting from speckle object to model object

* casts render material if it exists

* Update SpeckleGrasshopperObject.cs
2025-04-21 20:41:54 +01:00
Claire Kuang dfaf374847 adds casting from speckle object to model object (#774) 2025-04-21 20:16:39 +01:00
Oğuzhan Koral d270be3ef9 Merge pull request #771 from specklesystems/oguzhan/cnx-1643-store-user-selected-workspace-id
Feat: workspaces config
2025-04-21 18:59:47 +03:00
Claire Kuang d75c4d1f66 adds better tooltip and warning (#773) 2025-04-21 15:40:34 +01:00
Claire Kuang fa904f5302 fixes exception, and also removes dynamic keys prop (#772) 2025-04-21 15:26:43 +01:00
Oğuzhan Koral 4dd0280534 Merge branch 'dev' into oguzhan/cnx-1643-store-user-selected-workspace-id 2025-04-21 17:20:06 +03:00
Dimitrie Stefanescu 9f04750c26 Merge pull request #770 from specklesystems/dimitrie/cnx-1301-revit-stacked-walls-are-not-sending
fix: allows for stacked walls to be sent
2025-04-21 15:19:54 +01:00
oguzhankoral d3ad8e828c Workspaces config 2025-04-21 17:00:22 +03:00
Dimitrie Stefanescu b9f474decf fix: allows for stacked walls to be sent 2025-04-21 14:10:44 +01:00
Claire Kuang 4d31a91a6a not really a fix, but optimizes enumeration (#769) 2025-04-21 14:02:37 +01:00
Oğuzhan Koral 891e032f8e Merge pull request #768 from specklesystems/dev
.NET Build and Publish / build-windows (push) Has been cancelled
.NET Build and Publish / build-linux (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
Update dev to main
2025-04-21 15:59:18 +03:00
Oğuzhan Koral 8b7c127e93 Revert "Fix the object tracking for next session (#765)" (#766)
This reverts commit c10c03637a.
2025-04-21 15:49:59 +03:00
Claire Kuang 48c94db489 fixes material baking on objects (#767) 2025-04-21 13:43:58 +01:00
Claire Kuang 74982e025b Revert "Merge branch 'dev' into grasshopper"
This reverts commit 8bcc70cced, reversing
changes made to 2ae80cc7ba.
2025-04-21 12:52:26 +01:00
Claire Kuang 7047be0aff Revert "dev changes"
This reverts commit c5ff149bb6.
2025-04-21 12:52:20 +01:00
Claire Kuang afab68c27f Revert "more dev merge fixes"
This reverts commit 1323c336c7.
2025-04-21 12:52:08 +01:00
Claire Kuang 1323c336c7 more dev merge fixes 2025-04-21 12:47:15 +01:00
Claire Kuang c5ff149bb6 dev changes 2025-04-21 12:05:30 +01:00
Claire Kuang 8bcc70cced Merge branch 'dev' into grasshopper 2025-04-21 12:04:40 +01:00
Oğuzhan Koral de9b56bf18 Merge pull request #764 from specklesystems/dev
.NET Build and Publish / build-windows (push) Has been cancelled
.NET Build and Publish / build-linux (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
Merge dev into main
2025-04-21 09:04:25 +03:00
Oğuzhan Koral c10c03637a Fix the object tracking for next session (#765) 2025-04-18 16:41:46 +03:00
Oğuzhan Koral c4f734329a Disable regions in revit (#763) 2025-04-18 11:50:57 +03:00
Adam Hathcock 2f8f0d0f6f test: add tests for receive operation (#661)
* add tests for receive operation

* clean up some items and tests

* First initialization changes for SDK 3.2

* Update to SDK 3.2

* merge fixes

* fmt

* ifc changes

* fix tests and remove fakes again

* fmt

* remove extra tests from local sln

* update locks for 3.2

* fix mismerge

---------

Co-authored-by: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com>
2025-04-16 16:58:22 +01:00
Björn Steinhagen c60e8d6feb fix(revit): borked transformations in consecutive sends (#759)
* fix: borked transformations
* refactor: more explicit in getting of main doc unit setting
2025-04-16 09:54:15 +02:00
Claire Kuang 2ae80cc7ba simplifies speckle model resource to model link 2025-04-15 16:43:19 +01:00
Adam Hathcock 67a8592a8a Remove ref assemblies and fixes async event handling for Rhino (#756)
* Remove ref assemblies and fixes async event handling for Rhino

* fmt

* ifc parser is net 8

* allow for net48 targets on non-windows platforms
2025-04-15 15:41:20 +00:00
Claire Kuang 91579a69f0 small fix to publish to include created version 2025-04-15 16:40:12 +01:00
Claire Kuang b5e697ad0e Merge branch 'dev' into grasshopper 2025-04-15 16:24:57 +01:00
Adam Hathcock 6f11d50445 Add versionid to send results when creating one (#760)
* Add versionid to send results when creating one

* fix another test
2025-04-15 16:22:27 +01:00
Claire Kuang 2590d96178 fixes async send exception (#758) 2025-04-15 15:39:18 +01:00
Claire Kuang 5a9e202899 Merge branch 'dev' into grasshopper 2025-04-15 15:30:46 +01:00
Adam Hathcock bfd741e707 Revit 2025 is now CEF vulnerable (#757) 2025-04-15 10:34:04 +00:00
Claire Kuang a9206fbb81 feat(grasshopper): adds icons to all components fml (#755)
* adds param icons

* adds all icons

* Update FilterPropertiesByPropertyGroupPaths.cs

* Update Speckle.Connectors.GrasshopperShared.projitems
2025-04-14 22:11:17 +01:00
Claire Kuang 52edfd3b85 feat(grasshopper): adds regex search to valueset component (#754)
* adds regex search to valueset component

* Update SpecklePropertyWrapper.cs

* cleans run
2025-04-14 12:58:14 +01:00
Claire Kuang 0b9c170fc7 update locks 2025-04-14 12:20:52 +01:00
Claire Kuang dfbfc1c722 Merge branch 'dev' into grasshopper 2025-04-14 12:20:31 +01:00
Claire Kuang 344b8b2dde feat(grasshopper): add support for sending and receiving render materials (#753)
* adds support for render materials on receive and create speckle object

also adds a speckle material wrapper and param

* fixes receiving and baking bugs

* Update GrasshopperColorUnpacker.cs

* Update GrasshopperSendOperation.cs
2025-04-12 16:25:46 +01:00
Adam Hathcock 6652f7534c feat (SDK 3.2) React to to SDK 3.2 changes (#749)
* First initialization changes for SDK 3.2

* Update to SDK 3.2

* merge fixes

* fmt

* ifc changes

* update locks
2025-04-11 16:51:57 +03:00
Oğuzhan Koral 7b092ec5e4 Add workspace slug to model card (#752) 2025-04-11 11:44:43 +00:00
Adam Hathcock 175454bda2 feat(Autocad 2026) Add Autocad and Civil3d 2026 (#744)
* add autocad 26 stuff

* fix targets and remove some duplication

* add 2026 gubbins

* Fix build for Autocad and new projects

* fmt

* fmt when new line doesn't picked up

* add to local

* can do a receive in civil

* only show debounced items in console

* add civil to build consts

* add civil 26 to local sln

* Bump nuget and project references from 2025 to 2026

---------

Co-authored-by: oguzhankoral <oguzhankoral@gmail.com>
2025-04-11 07:40:29 +00:00
Claire Kuang cb94ea011a fixes path bug for objects directly inside input collection 2025-04-10 10:59:06 +01:00
Claire Kuang 998cb452f9 chore(grasshopper): changes collection path selector to omit input collection name (#751)
* changes collection path selector to omit input collection name

also fixes preview bug in collections

* changes direct object path to colleciton name instead of "_"
2025-04-09 22:10:34 +01:00
Claire Kuang 828e9b7ba1 creates expand object component (#750)
also refactors previews for collections to be on the parameter
2025-04-09 18:00:07 +01:00
Claire Kuang 33bba6ebd0 fix(grasshopper): renames collections, publish, and load (#748)
* renames collections, publish, and load names

* adds bool run to sync load and publish
2025-04-09 10:06:37 +01:00
Claire Kuang 99fb2cc072 adds preview to speckle object params (#747) 2025-04-08 23:25:30 +01:00
Claire Kuang eaa62804da fixes layer baking (#746) 2025-04-08 22:28:51 +01:00
Claire Kuang 0c7abc9263 feat(grasshopper): add support for sending and receiving colors (#745)
* feat (revit): receive Region as native FilledRegion (#696)

* regions with failed viewId

* render stuff in the first found suitable view

* use native or fallback conversion depending on the view

* better comments

* implement conditional conversion

* remove comment

* comment

* unload Root Host converter

* fix highlighting the model

* inject PlanView converter

* specify views in which receive is supported

* throw unsupported views in advance

* remove redundant check

* ViewManager added; View check is moved to the beginning of receive operation (to throw once and not for every object)

* simplify and remove unused

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>

* adds color baker to receive

* Update SpeckleGrasshopperObject.ModelObjects.cs

* adds colors on send

* Update GrasshopperColorUnpacker.cs

* removes host object builder (unneeded)

* fixes navisworks package locks

---------

Co-authored-by: KatKatKateryna <89912278+KatKatKateryna@users.noreply.github.com>
2025-04-08 21:54:13 +01:00
Claire Kuang e54a816a0d Merge branch 'dev' into grasshopper 2025-04-08 21:20:36 +01:00
Jedd Morgan 00d59913c2 fix(ci): Add Navisworks 2026 to the build consts (#742)
.NET Build and Publish / build-windows (push) Has been cancelled
.NET Build and Publish / build-linux (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
2025-04-08 16:22:26 +01:00
Oğuzhan Koral 373b0e5397 Merge pull request #741 from specklesystems/dev
Update dev into main
2025-04-08 17:47:36 +03:00
Jedd Morgan e9ebe65775 Reworded error message for DataObjects that have no displayValue (#718) 2025-04-08 13:58:23 +00:00
Claire Kuang 249fc40105 feat(rhino): receives properties as user strings (#726)
* adds receiving properties as user strings

* skips props that ends with noisy strings

---------

Co-authored-by: Dimitrie Stefanescu <didimitrie@gmail.com>
Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
2025-04-08 13:44:55 +00:00
Jonathon Broughton a81261a0e3 feat(Navisworks): CNX-1582 - Add 2026 support (#731)
* Adds Navisworks 2026 connector

Introduces a new connector for Navisworks 2026, enabling Speckle to interact with the latest version of the software.

This includes project files, dependency configurations, and plugin manifest updates.

* Adds support for unreleased Navisworks version

Adds provisional support for a newer, unreleased version of Navisworks.

Uses a temporary workaround to handle the version number until the official SDK is available.

* Updates Speckle dependencies

Updates the Speckle.Objects, Speckle.Sdk, and Speckle.Sdk.Dependencies packages to version 3.1.8 in the Navisworks connector.

This ensures compatibility and incorporates the latest features and fixes from the Speckle ecosystem.

* Updates Navisworks 2026 support

Uses the correct enum value for the 2026 Navisworks version.

This ensures that the application correctly identifies and supports the
specified version when it becomes available in the SDK.

* Updates WebView2 and adds System.Reactive

Updates the WebView2 package to the latest version.

Adds the System.Reactive package.

* Also lock the converters dependency

* Fix local.sln

---------

Co-authored-by: Adam Hathcock <adam@hathcock.uk>
2025-04-08 13:36:15 +00:00
Björn Steinhagen 6e4894d3bc fix(revit): Enable view-based filtering for multiple linked model instances (#727)
* feat: poc for independant view returns for instance

- next commit will optimise unnecesarry / redundant for loops

* refactor: earlier exit in FindLinkInstanceForDocument

- early exit in FindLinkInstanceForDocument in no transform
- linq expression for matching transform hash
- some docs

---------

Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
2025-04-08 13:14:39 +00:00
kekesidavid e4f1ef8564 Feat(rhino): send filter for layers (#728)
* rhino layers filter implemented

* removed commented out code

* Correct the id and add type as select

* Refresh send filters whenever layer has changed

---------

Co-authored-by: KatKatKateryna <89912278+KatKatKateryna@users.noreply.github.com>
Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
Co-authored-by: oguzhankoral <oguzhankoral@gmail.com>
2025-04-08 08:43:22 +00:00
Dogukan Karatas 2cd7f4f905 applies scale factor (#738) 2025-04-08 07:58:47 +00:00
Claire Kuang 865bda4de6 package locks 2025-04-07 16:21:23 +01:00
Claire Kuang 33b53abc73 Merge branch 'dev' into grasshopper 2025-04-07 16:19:04 +01:00
Claire Kuang c6d06fbda1 feat(rhino): add brep, extursion, subd support to data object to host conversion (#735)
* Update DataObjectConverter.cs

* Update DataObjectConverter.cs
2025-04-07 14:55:24 +00:00
Claire Kuang 207630c330 Update DataObjectConverter.cs 2025-04-07 15:41:48 +01:00
Oğuzhan Koral 6337a9e220 Add type for send filter (#729) 2025-04-07 14:27:41 +00:00
Claire Kuang b3e0af9b22 adds brep extrusion and subd receive to data objects 2025-04-07 15:12:33 +01:00
Adam Hathcock 65f97b4f4a Update to SDK 3.1.8 (#734) 2025-04-07 11:15:05 +00:00
Claire Kuang 0498794fa1 feat(grasshopper): add support for grasshopper in rhino 7 (#733)
* moves gh 8 to shared project

* adds grasshopper 7

* moves model object logic into partial class files

* Update Local.sln
2025-04-07 10:38:44 +01:00
Claire Kuang 16e5ca691a Merge branch 'dev' into grasshopper 2025-04-07 07:18:55 +01:00
KatKatKateryna cf570342d2 feat (revit): receive Region as native FilledRegion (#696)
* regions with failed viewId

* render stuff in the first found suitable view

* use native or fallback conversion depending on the view

* better comments

* implement conditional conversion

* remove comment

* comment

* unload Root Host converter

* fix highlighting the model

* inject PlanView converter

* specify views in which receive is supported

* throw unsupported views in advance

* remove redundant check

* ViewManager added; View check is moved to the beginning of receive operation (to throw once and not for every object)

* simplify and remove unused

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-04-07 04:58:15 +08:00
KatKatKateryna 33e4008e4b fix autocad send region polycurve (#732) 2025-04-04 19:03:56 +08:00
KatKatKateryna bcefe3b4c4 feat (autocad): region and hatches conversions (#681)
* clean send (except closed circular arcs)

* split functions

* include inner loops for complex regions

* reorient only polycurves with arcs

* regions to host

* merge conflict

* substract regions on receive

* optimize

* add checks

* fix icurve, receive hatches

* hatch receive

* reduce dataObject conversions

* finally hatches are recorded in a database

* regrouped

* simplify

* rename

* send hatch (only the first)

* remove hatches for now

* comment

* fixed icurve converter and reference in DataObject converter

* reformat

* hatch to speckle

* hatch to host

* hatch receive works

* set solid pattern on receive

* send properly and throw if complex hacth

* calculate mesh area from region

* prevent Autocad crash by catching exceptions in the middle of transaction

* sending both polylines and curves for hatches

* boolean operation for sending hatches

* turned 2d Hatch curves into 3d - now Brep creation doesn't fail!

* circles handled

* construct both polyline and vertices in parallel

* handling splines on receive

* comments

* don't reverse proper segments

* basic comment fixes

* open block table for write more concise

* use top-level transaction

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-04-01 18:36:04 +08:00
Claire Kuang dd770e61ee more prop casting fixes 2025-03-31 17:17:56 +01:00
Claire Kuang eb752fe381 fixes property bug 2025-03-31 16:59:18 +01:00
Claire Kuang 4bdb107954 adds create property group component (#725) 2025-03-28 18:02:59 +00:00
Claire Kuang 64d1091b79 Merge branch 'dev' into grasshopper 2025-03-28 15:51:09 +00:00
Claire Kuang a411aaa3f0 feat(grasshopper): adds create object node (#724)
* Avoid multiple enumeration issues when saving if we copy the list first (#713)

* add create data object component

* fixes extrusion display

* adds name and user strings dynamically to output model objects

* undo geometry list to geometry in object goo

* Update SpeckleGrasshopperObject.cs

---------

Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>
2025-03-28 15:49:12 +00:00
Jedd Morgan 13f3bb8ae5 Merge pull request #723 from specklesystems/jrm/main-dev-merge
Main -> Dev
2025-03-28 14:49:47 +00:00
Jedd Morgan d31cb47a85 Merge branch 'dev' into jrm/main-dev-merge 2025-03-28 14:40:55 +00:00
Dimitrie Stefanescu 640cc92641 Merge pull request #722 from specklesystems/revert-719-claire/cnx-844-send-createobject-node
Revert "feat(grasshopper): add create data object node"
2025-03-28 14:37:58 +00:00
Dimitrie Stefanescu ef9c23f7de Revert "feat(grasshopper): add create data object node (#719)"
This reverts commit 04bd151da3.
2025-03-28 14:36:48 +00:00
Claire Kuang 04bd151da3 feat(grasshopper): add create data object node (#719)
* Avoid multiple enumeration issues when saving if we copy the list first (#713)

* add create data object component

* fixes extrusion display

* adds name and user strings dynamically to output model objects

---------

Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>
2025-03-28 13:50:58 +00:00
Björn Steinhagen 378438f1bc fix(revit): respect view visibility in linked models when sending (#716)
* fix(revit): sening via views with correct visibility to linked models

* handle not null

* pass path name to function instead full doc

* refactor: move common code outside

* docs: commenting on known limitations

* refactor: preprocessor directive specific stuff back in place

* refactor: oversight on common code

* fix: method name

* docs: cleanup

---------

Co-authored-by: oguzhankoral <oguzhankoral@gmail.com>
2025-03-27 14:44:11 +03:00
Jedd Morgan b485a4ff6f Don't build everything when zero changes (#715)
.NET Build and Publish / build-windows (push) Has been cancelled
.NET Build and Publish / build-linux (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
2025-03-26 15:21:12 +00:00
Jedd Morgan 5697afc292 fix(ifc): Fixed regression with IFC Site geometry not being converted (#712)
* IFC spatial elements now attach geometry as separate data object

* removed unnecessary attribute

* Updated tester for faster testing
2025-03-26 14:57:50 +00:00
Claire Kuang 03c1d4ed32 feat(grasshopper): polishes property filtering nodes (#714)
* refactors properties to cast to simple types

* updates property groups

* merge conflict fixes

* fixes property group bugs

* fixes model object property group cast

* fixes property group cast

* update param category

* fixes output tree generation

* supports model object casting in the path selector

note: model objects will also register in the path list, along with their props. need to fix this
2025-03-26 13:31:48 +00:00
Adam Hathcock 07a681eda7 Avoid multiple enumeration issues when saving if we copy the list first (#713) 2025-03-26 13:14:10 +00:00
Dimitrie Stefanescu b17f4b02aa chore: package.lock.json commit.
this might be not needed?
2025-03-25 15:02:10 +00:00
Dimitrie Stefanescu 03a780ffd5 Merge pull request #711 from specklesystems/grasshopper
Grasshopper
2025-03-25 14:43:49 +00:00
Dimitrie Stefanescu b1240cfbe8 Merge pull request #702 from specklesystems/claire/cnx-1450-add-bake-to-collection-and-object-nodes
feat(grasshopper): adds bake to collection and object params
2025-03-25 14:35:15 +00:00
Dimitrie Stefanescu fed185fbed fix/feat: various
re-applies topology; prevents mutation on send; renames wrapper classes to have wrapper in name etc.
2025-03-25 14:23:13 +00:00
Adam Hathcock 4ec45d3cd5 Merge pull request #709 from specklesystems/dev
.NET Build and Publish / build-windows (push) Has been cancelled
.NET Build and Publish / build-linux (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
Bump sdk to 3.1.7 (#708)
2025-03-25 12:14:05 +00:00
Oğuzhan Koral 939c710bf2 Bump sdk to 3.1.7 (#708)
* Bump sdk to 3.1.7

* missing lock file changes

---------

Co-authored-by: Adam Hathcock <adam@hathcock.uk>
2025-03-25 12:05:00 +00:00
Jedd Morgan ac1345bbaf Merge pull request #703 from specklesystems/dev
Update dev into main
2025-03-25 11:54:03 +00:00
Jedd Morgan 95a7bdb81f Merge pull request #707 from specklesystems/main
Main to dev
2025-03-25 11:46:27 +00:00
Jedd Morgan b1a5824bcd Update pr.yml (#706) 2025-03-25 11:44:08 +00:00
Dimitrie Stefanescu 09f9b1ee51 Revit linked models (#699)
* Bjorn/cnx 1359 have a setting in UI whether include or not (#646)

* feat(revit): linked model settings

* docs: cache invalidation note

* Feat(revit): linked models POC (#656)

* cleanup on RefreshElementsIdsOnSender

* POC for multiple and copied linked models

* fix render materials for copied linked models

* comment

* comment

* split linked models with collections

* style: ci potential null on key

* style: not null

---------

Co-authored-by: Björn <steinhagen.bjoern@gmail.com>

* feat(revit): sending linked model poc round two (#657)

* Added IFC app name (#648)

* test: add tests for threadcontext (#651)

* add tests for threadcontext

* add test for extensions

* remove needed usage

* fix for looking for model store (#654)

Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>

* test: Send Operation tests (#652)

* add tests for threadcontext

* add test for extensions

* remove needed usage

* move cancellation

* Only add send operation tests

---------

Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>

* chore (autocad/civil): add regen after receive (#650)

* regenerates doc

* moves regen to receive base binding

* Update AutocadReceiveBaseBinding.cs

* feat: linked model send responsive to ui

- current throw just a placeholder
- small variable name refactor

* fix: object reference not set to an instance of an object

* fix: display value extractor

* refactor: converterSettings as readonly field

* feat: warning in response to ui setting not enabled

* docs: todos etc.

* Revert "Merge branch 'dev' into bjorn/cnx-1360-get-linked-models-on-send-function-according-to-setting"

This reverts commit 7202058a98, reversing
changes made to 4bc9ec2352.

---------

Co-authored-by: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com>
Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>
Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
Co-authored-by: Claire Kuang <kuang.claire@gmail.com>

* fix: transform needed to be inversed (#659)

* feat(revit): linked models send by category (#666)

* docs: notes on collection filtering

* feature: RevitCategoriesFilter with linked models too

poc

* docs: notes

* feat(revit): commit structure (#675)

* feat: collection structure switch

- poc
- if linked models, send nested
- if not linked, send flat

* docs: comments on updates

* docs: comment on exception swallowing

* fix: nullability

* refactor: linked model helper class and refactor (#682)

* fix: premature processing of linked models

- add early check for linked models setting
- skips expensive element collection for linked models when disabled
- add empty document contexts for linked models when disabled to maintain warning generation (HACK)
- improve code readability with clearer variable names and comments

* refactor: category ids outside of linked model processing

- inefficient to repeat for every document

* fix: improve separation of concerns for linked model handling

- extract linked model processing to a dedicated method
- add IsLinkedDocument flag to DocumentToConvert class
- move linked model warning generation to RevitRootObjectBuilder
- make RevitSendBinding responsible only for element collection

* refactor: dedicated LinkedModelHandler class for linked model processing

- extract linked model element collection logic to a separate class
- improve separation of concerns between flow control and element collection
- add clear documentation explaining the responsibility boundaries

* fix: duplicate if check still floating around

* docs: over-explaining myself

* Fix(revit): do not use converter settings in element unpacker (#687)

* fix resetting the selected object ids after collecting the elements

* Pass document to element unpacker for the sake of linked models

* fix: send by categories mode

---------

Co-authored-by: Björn <steinhagen.bjoern@gmail.com>

* fix(revit): handle multiple linked model instances with transform hashing (#688)

* feat: linked model transform caching in RevitRootObjectBuilder

Add transform-specific hashing to properly handle multiple instances of the same linked model. Uses transform properties to create a unique suffix for the applicationId, preventing cached objects from being incorrectly reused across different transform contexts.

* more comments

---------

Co-authored-by: oguzhankoral <oguzhankoral@gmail.com>

* fix: handle null elements when unpacking linked model groups

- add null element check before GroupBy in ElementUnpacker to prevent NullReferenceException
- improve robustness when processing groups in linked models
- add documentation explaining linked model element handling throughout UnpackElements method
- edge case where group member elements might not resolve properly in linked contexts

* make linked model setting true by default

* Fix(revit): illegal attempt to modify document (#700)

* Run refresh object ids in revit task

* Proper not null

* await instead .result

* feat(revit): collection structure for multiple linked model instances  (#701)

* feat: suffix for instances of linked model

* Extract out GetIdFromDocumentToConvert

---------

Co-authored-by: oguzhankoral <oguzhankoral@gmail.com>

* Correct receive default setting for linked models even if irrevelant

* Fix post conflict

* Cleanup the code

* Add comment

---------

Co-authored-by: Björn Steinhagen <steinhagen.bjoern@gmail.com>
Co-authored-by: oguzhankoral <oguzhankoral@gmail.com>
Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
Co-authored-by: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com>
Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>
Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-03-25 11:02:29 +00:00
Claire Kuang 11212c946a Update SpeckleCollectionWrapper.cs 2025-03-24 23:38:30 +00:00
Claire Kuang 2eee9561b4 uses observable collections to add proper baking to create collection nodes 2025-03-24 23:37:58 +00:00
Claire Kuang b221a69f76 fixes bake bug 2025-03-24 22:48:07 +00:00
Claire Kuang 6b0ed5c075 refactors everything to use new speckle collection class 2025-03-24 18:30:39 +00:00
KatKatKateryna 1a687fb188 ignore helper objects on selection (#689) 2025-03-25 00:02:14 +08:00
Dimitrie Stefanescu 30e050fff2 Merge pull request #698 from specklesystems/dimitrie/cnx-614-rhino-8-to-rhino-8-breps-not-working
fix: filter out elems with null geometry
2025-03-24 12:37:57 +00:00
Dimitrie Stefanescu 30ab3b108e fix: filter out elems with null geometry
this is a blind fix: works on bilal's computer, i could not reproduce
2025-03-24 12:29:33 +00:00
Claire Kuang da31864192 Merge branch 'dim/grassopper-v3-wip' into claire/cnx-1450-add-bake-to-collection-and-object-nodes 2025-03-24 11:56:29 +00:00
Claire Kuang f6239d279f feat(grasshopper): add property receive nodes (#690)
* adds property path selector and filter by path components

* Update PropertyGroupPathsSelector.cs

* Auto stash before merge of "claire/cnx-1428-property-paths-selector-node" and "origin/claire/cnx-1428-property-paths-selector-node"

* fix dev merge issues

* Update packages.lock.json

* Create packages.lock.json

---------

Co-authored-by: Dimitrie Stefanescu <didimitrie@gmail.com>
2025-03-24 11:40:48 +00:00
Adam Hathcock 1f3ac7a5ad Exclude library assets for all host applications for connectors/converters (#697)
* Exclude runtime assets from autocad 2022-2025

* add exclude to navisworks too

* exclude from remaining csprojs
2025-03-24 11:02:07 +00:00
Claire Kuang 7aff696bae updates object and collection baking 2025-03-23 22:06:07 +00:00
Claire Kuang 371722f28c adds bake to object param 2025-03-23 20:22:48 +00:00
Claire Kuang d25c40bcd6 Merge branch 'dim/grassopper-v3-wip' into claire/cnx-1450-add-bake-to-collection-and-object-nodes 2025-03-23 18:32:48 +00:00
Claire Kuang 913acc7707 fixes modelobject casting 2025-03-23 18:32:21 +00:00
Claire Kuang 1d83c98077 cleans up typed converters for brep, extrusion, subd 2025-03-23 17:43:20 +00:00
Claire Kuang 2c2a7929bf adds layer baker and bake to objects 2025-03-23 17:27:43 +00:00
Claire Kuang 5335329719 fix converter bugs after dev merge 2025-03-23 17:13:29 +00:00
Claire Kuang cc010c8cc8 Merge branch 'dev' into dim/grassopper-v3-wip 2025-03-23 15:27:20 +00:00
Claire Kuang 80b136b934 castfrom bug 2025-03-23 15:24:57 +00:00
Claire Kuang e8f61f8dbf adds bake to params 2025-03-23 15:11:14 +00:00
Claire Kuang bf2099f8a6 reorganize classes
- refactor create collection node to not duplicate logic
- adds model object support to object goo cast method
2025-03-23 15:01:08 +00:00
Claire Kuang f7f31263a6 feat(grasshopper): asyncify send and receive nodes (#694)
* adds async component base

* adds reference to async component

* adds async to send component

* updates receive async to be a separate component

also adds cancellation, auto receive, progress

* package lock updates

* updates send async with cancellation, progress, and more

* Update packages.lock.json

* Update Local.sln
2025-03-23 10:28:18 +00:00
KatKatKateryna 33e515efb6 feat(rhino): sending region display values as meshes (#685)
* send meshes

* comment

* refactor displayMeshExtractor

* comment

* error message

* comments

* Update HatchToSpeckleConverter.cs

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-03-22 09:21:15 +00:00
Claire Kuang b8f65d4ade fixes fallback conversion bug 2025-03-21 23:50:57 +00:00
jhdempsey86 4a5c91231d Caught error with SpiralDirection (#692)
Caught error with SpiralDirection

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-03-21 09:04:41 +00:00
KatKatKateryna 97a8df93d9 Arcgis send regions (#678)
* send regions

* send meshes

* comment

* typo

* adjust jsons

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-03-19 23:09:55 +08:00
Claire Kuang 96b2eb1832 Merge branch 'dev' into dim/grassopper-v3-wip 2025-03-19 11:57:05 +00:00
Claire Kuang b972a2f8bd adds url to send component 2025-03-19 11:55:18 +00:00
Claire Kuang c504848e0b Update GrasshopperSendOperation.cs 2025-03-19 10:31:34 +00:00
Claire Kuang 7d88e39272 fixes send component and adds additional bitmap icons 2025-03-19 10:27:29 +00:00
Claire Kuang 82adf0e20e adds send component 2025-03-18 20:22:49 +00:00
Claire Kuang 66de3f978a adds point, pointcloud, and hatch display to grasshopper object 2025-03-18 11:32:39 +00:00
Adam Hathcock 0106befa7d Caches visibility for the lifetime of the send (#672)
* Add selection progress and try/finally for exceptions

* format

* Caches visibility for the lifetime of the send

* clean up
2025-03-18 08:37:46 +00:00
KatKatKateryna ef87d5838b Rhino region conversions (#643)
* rhino hatch; autocad regions

* rhino: attempting to extract mesh

* stick to curves

* POC sending hatches

* receive region

* add tolerance

* change displayValue to curves

* revert autocad changes

* switch to curveConverter, add bbox

* lock files

* remove unused converter

* Revert "lock files"

This reverts commit 9ff42c00fe.

* comment

* remove checks, fix displayValue

* address comments

* remove displayValue

* bbox not required

* update nuget

* Revert "update nuget"

This reverts commit 28e6c30b2c.

* upgraded nuget

* convert Regions from DataObjects on Receive

* small fixes

* check result hatches

* json update

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-03-17 17:16:10 +00:00
Oğuzhan Koral 295162127a Merge pull request #684 from specklesystems/dev
.NET Build and Publish / build-windows (push) Has been cancelled
.NET Build and Publish / build-linux (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
Merge dev into main
2025-03-17 17:41:55 +03:00
jhdempsey86 6d336fbac4 fix(Civil3D): Update CorridorDisplayValueExtractor.cs to fix PropertySetDefinitionName error (#669)
* Update CorridorDisplayValueExtractor.cs

For unknown reasons, sometimes trying to get the PropertySetDefinitionName throws an exception.
Updated to catch this, ignore that propery set, and move to the next one. It is never the "Corridor Identity" property set that has this issue, so there should be no missing data.

* .

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-03-17 14:04:36 +00:00
Adam Hathcock 6b2078fadb (feat/fix) Navisworks: Add selection progress and try/finally for exceptions (#671)
* Add selection progress and try/finally for exceptions

* format

---------

Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
2025-03-17 13:53:08 +00:00
Adam Hathcock bfd465449a Bump SDK to 3.1.4 (#683) 2025-03-17 13:00:08 +00:00
Adam Hathcock a9a4893bdb test: Send/Receive Progress tests (#662)
* add tests for receive progress

* add send progress tests

* fmt
2025-03-17 15:09:04 +03:00
Adam Hathcock 21066eebbb Add tests for send caching (#660) 2025-03-17 11:51:07 +00:00
Claire Kuang 9d5ff85cff feat(revit): adds level extractor and levels to revit objects (#679)
* adds level extractor and levels to revit objects

* changes return to null when no level

* bumps sdk
2025-03-17 14:43:30 +03:00
Adam Hathcock 64befa758d fix(Revit) improving revit selection perf (#623)
* Revit allocation improvements

* fmt

* Don't use concurrent bag
2025-03-17 14:31:44 +03:00
Adam Hathcock d9a0cbb4bf Build everything always, only zip affected groups (#677)
* Build everything always, only zip affected groups

* get the dependencies right

* try dependencies again

* can't use affected in enums
2025-03-17 11:02:44 +00:00
Oğuzhan Koral 50807b1e88 Feat(accounts): Add remove account to binding (#680)
* Add remove account to binding

* Remove models as batch
2025-03-15 21:29:36 +03:00
Oğuzhan Koral 7780071073 Fix(autocad): Remove circular dependency (#676)
* Remove circular dependency

* removes polycurve to spline raw converter

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-03-14 20:02:45 +03:00
Jedd Morgan be63b4ab55 public release on tag (#674)
.NET Build and Publish / build-windows (push) Has been cancelled
.NET Build and Publish / build-linux (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
* public release on tag

* and nuget
2025-03-14 13:36:32 +00:00
Jedd Morgan 63c5bb26cb Added quotes escape in build (#673) 2025-03-14 13:29:57 +00:00
Adam Hathcock f7a1d98d8a feat: building/publish only affected projects (#665)
.NET Build and Publish / build-windows (push) Has been cancelled
.NET Build and Publish / build-linux (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
* Add affected usage with tag math

* use this branch as a test branch

* adjust test

* fix github action

* build refactor to get affected work

* Lazy affected

* put if statement on job

* add conditions around build and publish for linux

* affected tests and small refactor

* fmt

* verbose

* full checkout

* more testing and made things more clear

* adjust installer test branch

* add comments

* use zip on release

* detect main release

* use right trigger for release

* fix build

* maybe fix if statement...version env var don't work

* use current branch, not target branch

* test installer should be stored

* write to github action env vars

* use the env var correctly

* format

* set the output version as before

---------

Co-authored-by: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com>
2025-03-14 12:37:49 +00:00
Jedd Morgan a14de5bdde File import service now creates branch if one doesn't already exist (#670) 2025-03-14 12:03:11 +00:00
Claire Kuang 9031950868 Merge branch 'dev' into dim/grassopper-v3-wip 2025-03-13 12:14:26 +00:00
Jedd Morgan a89407ae3c Ignore null properties and empty psets (#668) 2025-03-12 17:51:57 +00:00
Claire Kuang 4cef9efd51 Adds Alan's select model component 2025-03-12 16:15:19 +00:00
Claire Kuang a40e9495e5 dev merge build fixes 2025-03-12 14:49:37 +00:00
Jedd Morgan a3285a4f67 Use 3 instead of 0 for cardinality indicator of triangle faces (#667) 2025-03-12 14:28:49 +00:00
Claire Kuang afd59df48a Merge branch 'dev' into dim/grassopper-v3-wip 2025-03-12 12:23:00 +00:00
Jedd Morgan ae4b1b0ab5 Merge pull request #655 from specklesystems/jrm/ifc-collections-data-objects
Send IfcProjects, IfcSites, IfcBuildings, and IfcStoreys as Collections
2025-03-12 08:32:30 +00:00
Jedd Morgan ed9d81d206 Better exception messages for breps that fail to meshify (#634) 2025-03-11 16:08:05 +00:00
Adam Hathcock a2fc846613 Remove stack usage to hash (#663) 2025-03-11 12:26:38 +00:00
Adam Hathcock 184953f5f0 Update to SDK 3.1.1 (#658) 2025-03-10 12:52:44 +03:00
Adam Hathcock d71b36c2f7 Sped up Rhino receive hot spots (#596)
* Sped up Rhino receive hot spots

* formatting

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-03-09 17:42:22 +00:00
Claire Kuang f152cff619 chore (autocad/civil): add regen after receive (#650)
* regenerates doc

* moves regen to receive base binding

* Update AutocadReceiveBaseBinding.cs
2025-03-07 14:33:15 +00:00
Adam Hathcock 4aed602089 test: Send Operation tests (#652)
* add tests for threadcontext

* add test for extensions

* remove needed usage

* move cancellation

* Only add send operation tests

---------

Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
2025-03-07 16:44:21 +03:00
Adam Hathcock 63c4d31467 fix for looking for model store (#654)
Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
2025-03-07 13:32:28 +00:00
Adam Hathcock b807be35ff test: add tests for threadcontext (#651)
* add tests for threadcontext

* add test for extensions

* remove needed usage
2025-03-07 16:27:58 +03:00
Jedd Morgan 32ea041c5e Added IFC app name (#648) 2025-03-06 16:22:47 +00:00
Adam Hathcock 950c8373d9 fix: Autocad perf - Adds early exit to idle manager to shortcut call check (#609)
* Refactors idle manager to shortcut call check

* fix tests

* Match the id of idle action with the function name

it is more safe with this way bc we might accidentially skip some deferred actions if we use class name

---------

Co-authored-by: oguzhankoral <oguzhankoral@gmail.com>
2025-03-06 15:10:24 +03:00
Adam Hathcock 9d5faa92e8 feat: Perf testing helpers for Jetbrains (#635)
* add perf project

* formatting

* add perf project to local
2025-03-06 11:04:14 +00:00
KatKatKateryna fd88fc2eeb stop color unpacking (#638)
Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
2025-03-05 20:31:02 +00:00
Jonathon Broughton 9d2ae1ca55 Fix(Navisworks): CNX-1329 - Fix Saved Sets Filter to Properly Handle Nested Folders (#631)
* Improve error messages for object conversion

- Updated exception messages to be more informative based on visibility settings.
- Simplified the logic for throwing exceptions when no model items are found.

* Refactor saved sets filter logic

- Introduced new methods for collecting saved sets and building hierarchical names.
- Simplified selection set resolution with a more concise approach.
- Updated initialisation of items to use arrays instead of lists.
- Improved error handling when resolving GUIDs for selection sets.
2025-03-05 20:25:35 +00:00
Claire Kuang 670a562d48 feat(civil3d): add civil3d receive (#644)
* adds receive to civil3d

* Update AutocadReceiveBaseBinding.cs

* remove usings

* Update Civil3dReceiveBinding.cs
2025-03-05 15:08:46 +00:00
Adam Hathcock e6d983302c Do some stack work to speed up Rhino hotspots (#590)
Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-03-05 14:34:39 +00:00
Jedd Morgan fe5b77e766 Nuget publish only on release (#647) 2025-03-05 12:46:30 +00:00
Björn Steinhagen 663fe445bf Revert "feat(revit): linked model settings (#641)" (#645)
This reverts commit 74d2d2860c.
2025-03-05 15:03:59 +03:00
Björn Steinhagen 74d2d2860c feat(revit): linked model settings (#641)
* feat(revit): linked model settings

* docs: cache invalidation note
2025-03-04 16:35:22 +01:00
Jedd Morgan 2e405b2f28 Don't skip server from IFC importer (#640) 2025-03-04 13:54:50 +00:00
Adam Hathcock 331c631b35 fix: Update SDK to 276 (#637)
* Update SDK to 247

* update to SDK 276
2025-03-04 08:44:23 +00:00
Adam Hathcock ddd6039722 Change targets of common assemblies from NET Standard to platform specific. (#597)
* Update SDK to 257

* remove netstandard2 target from (most) things.  Target net48, net6, and net8

* update to SDK 267

* adjust ifc tester

* Update to SDK 268

* merge fixes
2025-02-27 15:46:15 +00:00
Jedd Morgan 835e3ba005 No files, no success (#608) 2025-02-27 15:04:35 +00:00
Jedd Morgan af548ba626 Fixed duplicate elements (#604)
Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>
2025-02-27 14:08:10 +00:00
Jedd Morgan 3ff40757e0 Corrected tekla structures slug (#632) 2025-02-27 10:52:55 +00:00
Claire Kuang a8571fdd61 detaches featurelines so they are queryable (#627) 2025-02-27 13:41:59 +03:00
Oğuzhan Koral f8a6d27c6d revert revit task back for highlight view (#629) 2025-02-26 18:29:56 +00:00
Dogukan Karatas 4e1604f77e updates after build (#628) 2025-02-26 18:17:44 +00:00
Adam Hathcock 00af4ad338 fix: Use a concurrent dictionary to cache types since the converter is effectively a singleton (#624)
* Use a concurrent dictionary to cache types since the converter is effectively a singleton

* Don't modify the collection in the getter

---------

Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
2025-02-26 20:34:06 +03:00
Jonathon Broughton 7fed9e03e9 enhancement(Navisworks): CNX-972 - less aggressive object merging (#622)
* Remove unused path constants and update namespace

Deleted an unnecessary file for path constants. Updated the namespace in the remaining file to better reflect its purpose and added a new constant for material separation.

* Remove unused send filters

- Deleted the send filters list and related parameters from the constructor.
- Cleaned up code to streamline the binding process.
- Updated comments for clarity on behaviour expectations.

* Update Navisworks object creation logic

- Added extraction of parent path from the group key.
- Changed applicationId to use the parent path instead of the group key.

* Add path cleaning method and simplify geometry resolution

- Introduced `GetCleanPath` to remove material signatures from paths.
- Updated `ResolveIndexPathToModelItem` to use the new path cleaning method.
- Simplified `ResolveGeometryLeafNodes` to use expression-bodied member syntax.

* Improve geometry node grouping logic

- Added material signature handling for merging nodes.
- Enhanced grouping to only include anonymous geometry nodes.
- Introduced a method to create material signatures based on properties.
- Updated the parent path extraction from composite keys.

* Added an extendable signature generation pattern

- Simplified the grouping of anonymous geometry nodes.
- Replaced material signature generation with a new method for better clarity.
- Added functionality to include additional material properties in the signature.
- Improved hash generation for consistent property representation.

* Update material separator in path constants

Changed the material separator from "::MATERIAL::" to "::". This simplifies the constant and may improve compatibility with other components.

* Changed how the parent path is derived from the group key.

- Introduced a cleaner method to get the parent path.
- Updated applicationId to use the full composite key for uniqueness.

* Updated node path retrieval to use a more concise method.

- Simplified the creation of `mergedIds` by using a single variable for group keys.
- Removed unnecessary comments and whitespace for cleaner code.

* Add missing import for Navisworks constants

Included the Navisworks constants import to ensure proper functionality.

* Replaced custom hash function with MD5, suppressing related warnings.
2025-02-26 14:25:09 +00:00
KatKatKateryna e9c2c85a7f Arcgis detailed progress and cancellation (#614)
* pass cancellation token to individual features

* move count to a separate function

* remove per-layer progress report

* fix count

* reorder

* count layers only once

* move count to "unpacking selection" activityFactory

* remove outdated comment
2025-02-26 18:16:00 +08:00
Jonathon Broughton 82c7877425 Refine property handling logic (#621)
- Excluded "Transform" category from processing.
- Added a list of excluded properties: "Hidden", "Required", "Internal_Type".
- Improved handling for the "Item" category to add non-excluded properties directly to root level.
- Ensured only non-empty property dictionaries are processed.
2025-02-25 14:52:48 +00:00
Jonathon Broughton 2338be46c2 feat(Navisworks): CNX-1065 Enable optional full hierarchy mode (#616)
* Add preserve model hierarchy feature

- Introduced PreserveModelHierarchySetting to manage hierarchy preservation.
- Updated NavisworksSendBinding to include new setting.
- Added HierarchyBuilder class for future functionality.
- Enhanced ToSpeckleSettingsManagerNavisworks with caching for the new setting.
- Modified conversion settings to support model hierarchy preservation.

* Add Navisworks hierarchy builder class

Implemented a new class to rebuild the Navisworks document hierarchy from geometry leaves, maintaining parent-child relationships. Key updates include:
- Added constructor and private fields for managing geometry and conversion services.
- Developed a method to build the hierarchical structure of Speckle objects.
- Implemented logic for climbing up the document structure to resolve missing ancestors.
- Introduced methods for converting model items and pruning empty collections.

* Refactor hierarchy handling in object builder

- Added support for preserving model hierarchy.
- Introduced a new hierarchy builder for nested structures.
- Adjusted flow to handle flat mode when hierarchy is not needed.

* Refactor model item conversion logic

- Simplified the conversion method for Navisworks ModelItem.
- Consolidated geometry and non-geometry object creation into single methods.
- Added parameter for property handler to streamline property retrieval.
- Improved clarity by reducing redundancy in code structure.

* Refactor hierarchy builder for cleaner conversion

- Replaced custom conversion method with a direct call to the converter.
- Removed redundant code related to converting ModelItem to Speckle Collection.
- Streamlined the process of handling model items in the hierarchy.

* Remove unnecessary comment in hierarchy builder

Cleaned up the code by deleting a redundant comment about resolving ModelItem from a path string. This helps improve readability without losing any functionality.
2025-02-25 14:40:52 +00:00
Adam Hathcock 8f72eb35d3 fix(Revit): Catch exceptions and reprocess them around RevitTask (#617)
* Catch exceptions and reprocess them around RevitTask

* Added SpeckleRevitTaskException to know when exceptions are jumping over revit task to handle the UI

* add comments

* Add fatch when

---------

Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
2025-02-25 16:54:10 +03:00
Oğuzhan Koral a3f7069c37 Feat(navis): send filter dropdown navis poc (#619)
* Add Saved Sets Filter

* formatting

* !!!

* fml

* Unclear why formatting rules are not being applied

* !!!

* !

* fixed?

* Add new filter for saved sets in Navisworks

- Included a new file for NavisworksSavedSetsFilter.

* POC ISendFilterSelect

* Align saved sets filtler with ISendFilterSelect

* No DI for send filters

* reverse condition

* Remove ISendFilterSelect from revit views

* Add notes

* Improve object selection error handling

- Updated logic for retrieving model items to use selected paths.
- Enhanced error messages based on visibility settings of objects.
- Simplified null checks for selected items in filters.

---------

Co-authored-by: Jonathon Broughton <jonathon@stardotbmp.com>
2025-02-25 12:56:38 +00:00
Dogukan Karatas 3842e109b6 feat(tekla): speckle ribbon (#612)
* adds a ribbon

* updates speckle.svg

* updates logo

---------

Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
2025-02-25 08:14:17 +01:00
Claire Kuang 4ae2106608 fixes pointcloud plane bug (#615) 2025-02-21 17:30:25 +00:00
Claire Kuang 3656587081 fix(autocad/Rhino): add support for receiving any convertible geometry in dataobject display values (#599)
* adds additional geometry conversions to autocad and rhino

* removes unused converters

* fixes zip bug

---------

Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
2025-02-21 19:17:23 +03:00
Claire Kuang b315cebf3a fix(revit): missing directshape geo and other geometry fixes (#611)
* Claire/revit areas curves fix (#610)

* fixes display values for get_geometry method, and changes modelcurves to be sent as revitobject

also removes `level` prop in objects and adds the units and elevation to the level collection instead

* Update Speckle.Converters.RevitShared.projitems

* removes top level pointcloud converter

* Update RevitElementTopLevelConverterToSpeckle.cs
2025-02-21 18:18:07 +03:00
Oğuzhan Koral fb18466aba Source application should be app name and version (#613) 2025-02-20 21:30:23 +03:00
Jonathon Broughton b721c2fb31 fix(Navisworks): CNX-1299 Navisworks properties cleanup and NavisworksObject adoption (#607)
* Update property handling interface

Changed method to retrieve properties from Navisworks model items. Updated the method signature for clarity and improved functionality.

* Add property retrieval method to handler

Implemented a new method for getting properties from model items. It processes property sets and returns a dictionary of category values, enhancing the functionality of the property handler.

* Fix namespace formatting and improve property handling

- Cleaned up the namespace declaration.
- Added a check to ensure properties are a dictionary before processing.
- Streamlined property validation logic for better clarity.

* Simplified the `AddModelProperties` method signature by reducing parameters.

* Refactor property handling in base class

- Added a new method to retrieve properties from model items.
- Simplified the structure of processed property sets by removing nested dictionaries.

* Add hierarchical property retrieval method

Implemented a new method to get properties from model items.
- Introduced `GetProperties` to collect and filter hierarchical properties.
- Enhanced data handling with improved dictionary management for properties.

* Fix namespace formatting issues

Updated the namespace declarations in property handler files to ensure proper formatting.

* Refactor model item conversion logic

- Updated the method for converting Navisworks ModelItems.
- Simplified the creation of non-geometry objects.
- Removed unnecessary property handling code.
- Enhanced clarity by restructuring return values.

* Refactor model item conversion logic

- Simplified the conversion method for model items.
- Added a new method to handle geometry objects.
- Introduced property handling based on user settings.
- Improved clarity and maintainability of the code.

* Refactor geometry property handling

- Updated comments to clarify property merging rules.
- Removed unused methods for creating geometry and non-geometry objects.
- Simplified code structure for better readability.

* Refactor conversion method for brevity

Streamlined the `Convert` method to use an expression-bodied member. Removed unnecessary null check block and simplified the logic for better readability.

* Fix import statement formatting

Updated the import statement for consistency by removing an invisible character.

* Add class properties handling to property dictionaries

- Integrated class properties extraction into both property handlers.
- Updated logic to add or update entries in the property dictionaries based on extracted class properties.
- Ensured null checks for class properties before processing.

* Refactor property handling methods

- Removed the AssignPropertySets method for simplification.
- Streamlined GetProperties to directly return processed property sets.
- Cleaned up unnecessary checks and loops for better readability.

* Add ClassPropertiesExtractor to service registration

- Registered a new ClassPropertiesExtractor for better property handling.
- Kept existing property handlers and settings management intact.

* Refactor HierarchicalPropertyHandler for clarity

- Removed redundant property assignment logic.
- Integrated class properties extraction directly into the main method.
- Simplified error handling by eliminating unnecessary checks.

* Refactor property assignment methods

Removed the AssignProperties and AssignClassProperties methods to streamline property handling. Kept the abstract method for getting properties while maintaining the overall structure of the class.

* Refactor ClassPropertiesExtractor to instance method

Changed ClassPropertiesExtractor from static to instance class. Updated GetClassProperties method to be an instance method, allowing for better flexibility and potential state management in the future.
2025-02-20 09:52:30 +00:00
Claire Kuang 76aa953210 moves class properties to top level of properties dictionary (#606) 2025-02-19 17:05:38 +00:00
Jedd Morgan 52d15dc827 add support for vertex normals in rhino (#605) 2025-02-19 12:11:06 +00:00
Björn Steinhagen dbbc4f7fcd fix(revit): use correct unit-specific scaling for material quantities (#602) 2025-02-19 08:21:19 +00:00
Oğuzhan Koral 85b4a88407 Merge pull request #600 from specklesystems/dogukan/tekla-runtime-fix
fix(tekla): remove runtime identifier
2025-02-19 03:04:59 +03:00
Dogukan Karatas 65a2e674bb removes runtime identifier 2025-02-19 00:58:30 +01:00
Dimitrie Stefanescu 9a84e4469e Merge pull request #598 from specklesystems/dimitrie/cnx-1186-revit-rooms-not-visible-in-the-viewer
feat: moving back to translucid rooms.
2025-02-18 17:07:42 +00:00
Dimitrie Stefanescu b8a49d5fed feat: moving back to translucid rooms.
now people will be angry they cannot select furniture in some cases.
2025-02-18 17:01:36 +00:00
Dogukan Karatas 12dcf471d3 fix (tekla): updates the vebview2 dependency (#562)
* updates webview dependencies

* updates csproj

---------

Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>
Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
2025-02-18 19:08:26 +03:00
Claire Kuang 42e45affbd refactor(civil3d): properties cleanup (#588)
* Cleans civil3d props

also removes catchment and network proxies. this info is now captured in assignments

* Update ClassPropertiesExtractor.cs

* some bug fixes

* Update PartDataExtractor.cs

* adds parcel areas and excludes labels
2025-02-18 16:38:20 +01:00
Dimitrie Stefanescu fcce4e3f63 feat: adds support for formulas in user strings (#594)
Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-02-18 15:15:08 +00:00
Claire Kuang 370c5b2064 adds area boundary segments to display value of area (#592) 2025-02-18 15:06:54 +00:00
Claire Kuang 39dfb0f426 removes assignment of bearing to z (#593) 2025-02-18 14:53:58 +00:00
Adam Hathcock 1c62fbbe99 Update SDK to 268 (#567)
* Update SDK to 257

* update to SDK 267

* adjust ifc tester

* Update to SDK 268

* update SDK version to 270
2025-02-18 10:14:55 +00:00
Jedd Morgan 6f03aa8678 Jedd's IFC improvements (#510)
* ifc safe

* reverted LibraryImport as it would need more testing

* IFC app ids
2025-02-17 16:35:26 +00:00
Björn Steinhagen f882b0f5bd fix(etabs): ensure csi operations run on main thread to prevent etabs exceptions (#589)
* fix: ensure operations run on main thread to prevent etabsexceptions

* pr comments

* fix: ensure consistent exception handler usage in selection binding
2025-02-17 11:53:21 +01:00
Björn Steinhagen 4ffe9fe4b0 feat(revit): extract material type enum on structural asset (#586)
* feat: material type distinction

* refactor: mixed concerns

Some structural asset stuff was in the MaterialQuantitiesToSpeckle.cs

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-02-14 11:24:24 +00:00
Claire Kuang d50b095683 refactor(revit): properties cleanup (#581)
* clean properties in revit

also adds properties to non-dataobjects and changes grids to have a curve display value after removing curve prop on grids

* removes number from room since this is included in params

* refactors supported categories and throws when all selected objects are unsupported categories

* stupid typos

---------

Co-authored-by: Dimitrie Stefanescu <didimitrie@gmail.com>
2025-02-14 09:49:51 +00:00
Dimitrie Stefanescu daebbbef1c Merge pull request #587 from specklesystems/adam/cnx-1238-rhino-8-restarting-during-an-operation-throws-with-key-not
fix: (cancellation manager should return cancelled token instead of throwing exception)
2025-02-13 12:18:05 +00:00
Adam Hathcock b43631e46b fix and add tests 2025-02-13 10:54:49 +00:00
Adam Hathcock ea9768b1f2 check tokens more aggressively when doing operations 2025-02-13 10:50:12 +00:00
Adam Hathcock 2756555eb9 Cancellation manager shouldn't throw on get 2025-02-13 10:49:15 +00:00
Adam Hathcock 1f1422900e Adam/cnx 1217 arcgis toc not unblocked after cancellation during (#580)
* Send with QueuedTask

* more QueuedTask usage and format

* Fix highlight/selection changes
2025-02-13 09:32:10 +00:00
Dimitrie Stefanescu 45a76eada4 Dimitrie/cnx 1240 receiving materials in rhino 8 broken for layers (#585)
* reverts previous fix

* fix: applies the minimal fix

* chore: adds comment for future

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-02-12 18:54:16 +00:00
Björn Steinhagen 0e65b6aa57 feat(etabs): geometric properties through new cDatabaseTable extractor (#584)
* feature: database table extractor

* feature: frame length extraction

* feat: shell area extraction

* feat: frame length extraction

* feat: shell area extraction

* docs: cleaned up object extractors

* refactor: extensible database table extraction

* flexible indexing (can be defined by user, defaults to typical use-case of "UniqueName")
* better variable naming and more descriptive (better than csi's api)
* some fail safes e.g. when forgetting to put indexingColumn in array of columns to fetch

* refactor: using DatabaseTableExtractor for material name lookup

* lookup for material name of a shell can use the database table extractor and simplifies EtabsShellPropertiesExtractor a lot

* fix: openings shouldn't look for material assignments

Frustrating way Etabs handles openings - they shouldn't be a SHELL. Anyways. Rant over

* refactor: database table extractor handles dictionary lookups
2025-02-12 18:43:44 +00:00
Dimitrie Stefanescu 5c2c0ff303 Merge pull request #582 from specklesystems/dimitrie/cnx-1239-rhino-fix-the-documentisinit-post-copy-paste
Rhino: fixes change detection post copy paste events
2025-02-12 15:00:32 +00:00
Dimitrie Stefanescu a6fd4547ea feat: adds previous dix 2025-02-12 14:38:47 +00:00
Adam Hathcock 0d27eadfeb add deep clean local docs (#579) 2025-02-11 14:06:12 +00:00
Dimitrie Stefanescu 0b26e021cd fix: prevents fatal crash on old model cards (#548)
* fix: prevents fatal crash on old model cards

* fix: formatting

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
2025-02-10 20:33:42 +03:00
Claire Kuang a0d5e3b2d4 fix(Autocad): missing solids on receive (#576)
* Fix threading bug

* untangle revit

* adds brepx converter

also changes groups to not be created if list conversion returns 1 or less objects

* revert rhino

* revert autocad

* revert rest

* remove event agg and rhino implementation

* remove event aggr from revit

* remove event aggr from autocad and civil

* remove event aggr tests

* remove event aggr from tekla

* Remove event aggr for navis

* remove event aggr from csi etabs

* remove event aggr for arcgis

* remove remaining pieces

* adds brep converter

* push autocad to run operations on main thread

* adds teklaidlemanager

* bring navis idle manager back

* run send on main

* adds extrusionx and subdx support

* adjusts converter return types to fallback case

---------

Co-authored-by: oguzhankoral <oguzhankoral@gmail.com>
Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
Co-authored-by: Dogukan Karatas <karatasdogukan@gmail.com>
2025-02-10 20:25:24 +03:00
Claire Kuang 1ebc32f07e feat(autocad/rhino): add name and properties (#556)
* adds name and properties to rhino and autocad

* move properties extractor to converter and updates attributes event listener

* moves name and properties back to connector because abstract rhinoobjectconverter doesn't capture all top level converters

* Update RhinoObjectToSpeckleTopLevelConverter.cs

* Update ServiceRegistration.cs

* adds explicit conditions for object attribute change event

* feat: simplifies rhino implementation

* fix: comments out acad usage as we can't test it

* fix: civil services (removal of acad props extraction)

* Update RhinoSendBinding.cs

* Update PropertiesExtractor.cs

---------

Co-authored-by: Dimitrie Stefanescu <didimitrie@gmail.com>
2025-02-10 19:59:46 +03:00
Claire Kuang a3b1cd52ad fix(rhino): bakes render materials on receive instead of materials (#564)
* switches to baking render materials instead of materials

* makes sure to purge render materials before receive
2025-02-10 15:17:14 +00:00
Dogukan Karatas c7cfb8c6c7 feature (tekla): extract user-defined attributes (#566)
* adds uda's to the properties

* reformatted

* updates entry structure

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-02-10 15:06:34 +00:00
Oğuzhan Koral 93246157c7 Fix: threading on browser bridge + remove event aggr (#574)
* Fix threading bug

* untangle revit

* revert rhino

* revert autocad

* revert rest

* remove event agg and rhino implementation

* remove event aggr from revit

* remove event aggr from autocad and civil

* remove event aggr tests

* remove event aggr from tekla

* Remove event aggr for navis

* remove event aggr from csi etabs

* remove event aggr for arcgis

* remove remaining pieces

* push autocad to run operations on main thread

* adds teklaidlemanager

* bring navis idle manager back

* run send on main

* remove unused function

---------

Co-authored-by: Dogukan Karatas <karatasdogukan@gmail.com>
2025-02-10 17:50:26 +03:00
Oğuzhan Koral 18499bdc69 Chore: update code ownership (#575)
* update code ownership

* fix typo for claire :)
2025-02-07 10:35:08 +00:00
Jedd Morgan feaae9e5ee Event Aggregator Deadlock Fix (#568)
* deadlock fix

* Changed list construction

* typo
2025-02-06 12:07:23 +00:00
Björn Steinhagen 4ee48bdfae feat(revit): add density to material quantities (#558)
* feat: thermal and structural asset extraction initial scope

* feat: thermal and structural asset extraction poc

* feat: property set extraction (1/3)

* feat: property set extraction (2/3)

- scaling internal units can't be so complicated?
- to discuss :(

* feat: property set extraction (3/3)

- Simplification to just extract density from structural asset (if present)
- Just one property extraction => no need to create material proxy
- Scaled from internal units to match scaling to model units which occurs on other material quantities

* feat: display parameter unit with associated quantities

* feat: added name of structuralAsset to material quantities

* fix: safe string conversions

* fix: explicitly returning cached value

* fix: validation before dict insertion

* style: dict access

* fix: nullability

---------

Co-authored-by: KatKatKateryna <89912278+KatKatKateryna@users.noreply.github.com>
2025-02-06 08:49:28 +01:00
Adam Hathcock 1c11e4a6c5 Add Local to relevant csprojs and use local config in Local sln (#563) 2025-02-05 15:41:45 +00:00
Dimitrie Stefanescu 413c1ad562 Merge pull request #565 from specklesystems/dimitrie/cnx-1180-v3-send-stuck-sending-forever-for-curtain-walls-and-model
fix: ensures we don't go crazy on null categories
2025-02-05 15:51:34 +01:00
Dimitrie Stefanescu d9adca0154 fix: make ci happy - push and see 2025-02-05 14:43:40 +00:00
Dimitrie Stefanescu 74870a6a8e fix: formatting 2025-02-05 13:25:25 +00:00
Dimitrie Stefanescu cba391081c fix: ensures we don't go crazy on null categories 2025-02-05 13:18:13 +00:00
Dimitrie Stefanescu ccc3187e78 fix(rhino): only create groups if needed (#561) 2025-02-04 17:33:58 +00:00
Adam Hathcock 1e8ad93dbe Update to SDK 255 (#557) 2025-02-04 15:58:55 +00:00
kekesidavid a2b01c0bbb switched from trianglenet to libtessdotnet (#559) 2025-02-04 16:09:47 +01:00
kekesidavid a70a894089 extrude simple holed surfaces in tekla (#550)
* extrude simple holed surfaces in tekla

* typo

* units fix
2025-02-04 15:33:30 +01:00
Dimitrie Stefanescu 65baf4221d Merge pull request #555 from specklesystems/fix-clean
Add deep-clean-local.
2025-02-04 12:25:45 +01:00
Adam Hathcock 2a4b5f7218 add build and restore functions with output 2025-02-04 10:00:17 +00:00
Adam Hathcock cfa723d164 Add deep-clean-local. Be more explicit about what solution is being cleaned 2025-02-04 09:52:50 +00:00
Adam Hathcock 143da829d8 Revert to SDK 251 to avoid potential issues (#554) 2025-02-04 09:23:02 +00:00
Adam Hathcock a8a98fe824 Update to SDK 254 (#551) 2025-02-03 17:54:13 +00:00
Adam Hathcock efadfdc479 Update to SDK 252 (#546) 2025-02-03 14:08:53 +00:00
Dimitrie Stefanescu f7ee2555f4 Merge pull request #547 from specklesystems/dimitrie/cnx-1086-stuck-at-publish-when-trying-to-publish-not-supported-array
fix/feat: adds support for arrays (radial and linear) in revit
2025-02-03 14:42:34 +01:00
Dimitrie Stefanescu 286a1c070c Merge branch 'dev' into dimitrie/cnx-1086-stuck-at-publish-when-trying-to-publish-not-supported-array 2025-02-03 14:34:48 +01:00
Claire Kuang 4af90950ff fix(rhino): colors and materials are preserved on empty layers (#542)
* Update RhinoLayerBaker.cs

* fixes color and material assignment to layers with no objects

---------

Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
2025-02-03 13:14:21 +00:00
Dimitrie Stefanescu a23f9c1ffa Merge remote-tracking branch 'origin/dimitrie/cnx-1086-stuck-at-publish-when-trying-to-publish-not-supported-array' into dimitrie/cnx-1086-stuck-at-publish-when-trying-to-publish-not-supported-array 2025-02-03 12:57:53 +00:00
Dimitrie Stefanescu 64dfa44692 fix: formatting 2025-02-03 12:57:44 +00:00
Dimitrie Stefanescu 573c63fa62 Merge branch 'dev' into dimitrie/cnx-1086-stuck-at-publish-when-trying-to-publish-not-supported-array 2025-02-03 13:57:05 +01:00
Dimitrie Stefanescu 52aeb36f19 fix/feat: adds support for arrays (radial and linear) in revit 2025-02-03 12:49:47 +00:00
Jedd Morgan 593f95daf6 Fix codecov reports (#545) 2025-02-03 12:43:57 +00:00
Adam Hathcock e5e02bdab1 Cancellationmanager revamp (#527)
* rhino and arc fix usage

* fix registration

* fix the rest

* use interface

* don't use rhino layer if there is no name

* formatting

* add tests

* formatting

* add to local and move

* Update OTEL to remove grpc dependency

* Fix deprecated method

* really fixed with no incremental builds for tests

* Fix references and lock

* Update nuggets
2025-02-03 12:11:09 +00:00
Dimitrie Stefanescu e9f3701a86 feat(rhino): wraps receive in an undo operation (#544)
* feat(rhino): wraps receive in an undo operation

* fix: formatting
2025-02-01 19:43:22 +03:00
Dimitrie Stefanescu 3a7baf0659 Merge pull request #543 from specklesystems/dimitrie/cnx-1152-rhino-change-tracking-not-working-in-first-open-doc
fix(rhino): isDocumentInit is set to true even on paste operations
2025-02-01 14:10:42 +01:00
Dimitrie Stefanescu 24bff4b1ce fix: isDocumentInit is set to true even on paste operations 2025-02-01 13:04:11 +00:00
Dimitrie Stefanescu 184c53c3a2 fix: exceptions on null layers (#540)
it does seem like a rhino layer can have null full name in some cases

Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>
2025-01-30 16:41:57 +00:00
Björn Steinhagen 16ce6ac09f fix: catch tendon and link as warning (#538) 2025-01-30 16:46:11 +01:00
Adam Hathcock f379996f31 Better handle UnobservedTaskExceptions without the Event Aggregator. … (#539)
* Better handle UnobservedTaskExceptions without the Event Aggregator.  Logs will have them.

* formatting
2025-01-30 13:55:18 +00:00
kekesidavid 48e66f9084 Mesh generator logic to triangulate 2D and 3D surfaces (#529)
* added mesh generator logic to triangulate 2D and 3D surfaces from polygon inputs

* removed empty folder

* checking hole polygon vertex order, added comments

* csharpier

* added MeshTriangulation project to Local sln

* added reference to MeshTriangulator in Tekla Converters
2025-01-29 15:27:09 +01:00
Jedd Morgan f2249356d8 Add to build (#525) 2025-01-29 14:02:07 +00:00
Björn Steinhagen f4765b9e82 bjorn/cnx-1133-user-facing-attributes-not-consistent-for-joints (#536)
* style: user facing attributes for joint

* bug: using old strings
2025-01-29 14:46:29 +01:00
Claire Kuang e4a29085f3 chore(template): amends pr template to be more descriptive (#535)
* Update pull_request_template.md

* Update pull_request_template.md
2025-01-29 12:56:17 +00:00
Jonathon Broughton 462d01a3b2 feat(Navisworks): CNX-1043 Enable shared ribbon for v2 and v3 Navisworks connectors (#504)
* Add Speckle v2 and v3 launch buttons to the Navisworks ribbon

- Added `LaunchSpeckleConnector` class with constants for command and plugin names
- Updated `NavisworksRibbon.name` file to include display names for Speckle v2 and v3
- Updated `NavisworksRibbon.xaml` file to include ribbon panels and buttons for Speckle v2 and v3
- Updated `NavisworksRibbon.xaml.cs` file to include commands for launching Speckle v2 and v3 connectors
- Added resources for the icons of the new buttons

* Delete AppUtils.cs and Commands.cs, add Utilities.cs

- Delete AppUtils.cs and Commands.cs (Replaced by v2 and v3 Tools)
- Add Utilities.cs for plugin utilities functionality

* Update Speckle Connector for Navisworks to use the new SpeckleV3Tool plugin and developer ID. Also, initialize the services with the correct version of Navisworks.

* Update RibbonHandler class in Navisworks connector plugin:
- Refactor the CanExecuteCommand method to handle different commandIds.
- Add a static constructor to subscribe to the PluginRecordsChanged event.
- Implement OnPluginRecordsChanged method to reset the cached state of V2 plugin availability.
- Modify ExecuteCommand method to load and activate the appropriate plugin based on the commandId.
- Add a new IsValidVersion method to check if the current version of Navisworks is compatible with the plugin.

* Update ribbon handling logic in NavisworksRibbon.xaml.cs

- Find the v2 plugin and update the availability state
- Hide the v2 ribbon tab if it exists

* Fix ribbon handling for Speckle v3 and v2 tools

Refactor the code in `RibbonHandler` to improve the handling of commands for Speckle v3 and v2 tools. The changes include:
- Extracting a new method `HandleCommand` to handle the loading and activation of plugins
- Removing duplicated code by calling `HandleCommand` for both Speckle v3 and v2 tools
- Adding null checks when finding plugin records
- Returning early if plugin loading should be skipped

* XMLDOC comments added

- Added two summary comments to describe the purpose of the methods `CanExecuteCommand()` and `ExecuteCommand()`.

* Add Speckle V2 and V3 tools to Navisworks plugin

- Added `SpeckleV2Tool.cs` file with constants for Speckle V2 tool
- Added `SpeckleV3Tool.cs` file with constants for Speckle V3 tool

* Refactor Utilities.cs for Navisworks plugin

- Add conditional compilation for DEBUG mode

* Remove debug code and comments in Utilities.cs

- Remove debug code that prints available plugins to the Debug output window
- Remove unused using statement for System.Text

* Refactor plugin activation logic in NavisworksRibbon.xaml.cs and Utilities.cs

- Simplify ActivatePluginPane method in Utilities.cs
- Remove unused parameter 'command' from ActivatePluginPane method

* Update Speckle branding and UI elements

- Changed display names for Speckle versions to reflect beta status.
- Updated XAML to simplify ribbon panel structure.
- Adjusted constants in the tool class for consistency with new naming.

* Fix formatting and improve error messages

- Added missing newlines for better readability in code.
- Updated error message to enhance clarity for users.
- Cleaned up XML formatting in project files for consistency.
- Ensured all package references are properly formatted.

* Add missing namespace for Navisworks integration

- Included the HostApp namespace to improve functionality.
- Ensures better access to required classes and methods.

* Fix message box formatting in Navisworks plugin

Updated the message box string concatenation for better readability.
2025-01-29 10:57:44 +00:00
Jonathon Broughton 8ca43a1ad5 feat(Navisworks): CNX-1064 - Add hierarchy path property to converted Navisworks objects (#500)
* Add DisplayPathHelper class for generating display paths in Navisworks

This commit adds a new file, `DisplayPathHelper.cs`, which contains a helper class for generating display paths by traversing Navisworks model item ancestors. The `GenerateDisplayPath` method takes a `ModelItem` as input and returns a string representing the full path of display names from ancestors, stopping at the first object ancestor. If no first object ancestor is found, it returns just the model item's display name.

The helper class uses a constant `PATH_DELIMITER` to separate the display names in the generated path. It throws an exception if the input `modelItem` is null.

The algorithm works by starting from the first object ancestor and traversing backwards to the root, collecting non-empty display names along the way. Finally, it reverses the collected names and joins them with the delimiter to form the final display path string.

These changes improve code reusability and readability by encapsulating logic related to generating display paths in Navisworks models.

* Update NavisworksRootObjectBuilder.cs

- Modified the CreateNavisworksObject method to handle cases where the convertedBase or groupKey is null and return null in those cases
- Added a new private method GetDisplayPath to retrieve the modelItem and displayPath based on the applicationId
- Updated the CreateNavisworksObject methods to include the displayNamePath property in the returned NavisworksObject

* Refactor NavisworksRootObjectBuilder.cs: Add FindMeaningfulAncestorName method

This commit adds a new private method, FindMeaningfulAncestorName, to the NavisworksRootObjectBuilder class. This method is used to find the name of the most meaningful ancestor of a given NAV.ModelItem object. It iterates through the ancestors until it finds an ancestor with a non-empty DisplayName and no geometry. The found name is then used as the "name" property in the created NavisworksObject instances. Additionally, the "displayNamePath" property has been renamed to "path" for consistency.

* Refactor display path generation for Navisworks model items

- Update the helper class to generate display paths by traversing meaningful Navisworks model item ancestors.
- Skip nodes without meaningful names or geometry nodes when generating the display path.
- Reverse the collected names to build the path from root to leaf.

* Rename DisplayPathHelper.cs to HierarchyHelper.cs
- Renamed the file from "DisplayPathHelper.cs" to "HierarchyHelper.cs"
- Updated all references to the renamed file

Refactor helper class for generating display paths
- Refactored the helper class to extract hierarchical context from Navisworks model items in a single traversal
- Changed the method name from "GenerateDisplayPath" to "ExtractContext"
- Modified the method signature to return a tuple of strings (Name, Path)
- Updated the implementation logic accordingly

Improve traversal and extraction logic
- Improved the traversal logic by collecting both name and path information while traversing up the tree once
- Extracted meaningful name and path information from model items in a more efficient way
- Handled cases where model item has no meaningful name or is a geometry node

* Refactor NavisworksRootObjectBuilder.cs for improved context extraction

- Extracted the GetContext method to retrieve the name and path of a model item
- Replaced calls to GetDisplayPath with calls to GetContext for consistency
- Updated CreateNavisworksObject and ConvertBase methods to use the extracted context information instead of finding meaningful ancestor names
- Updated the "path" property in the returned NavisworksObject instances with the extracted path
2025-01-29 10:48:34 +00:00
Björn Steinhagen bb252a5115 bjorn/cnx-1112-get-user-facing-names-of-properties (#526)
* style: user facing names for frames

* style: user facing names for shells

* styling: user facing names for proxies

* style: dict utils as extension methods
2025-01-29 11:25:15 +01:00
Björn Steinhagen 4d7225fab4 bjorn/cnx-1119-remove-caching-from-progress (#534)
* Add PeriodicThreadedEvent to EA and use it

* All timers gone

* add tests

* bug: build issues

* bug: form not being disposed properly

* feat: remove caching

---------

Co-authored-by: Adam Hathcock <adam@hathcock.uk>
2025-01-29 11:08:02 +01:00
Adam Hathcock 9219cdfc53 Add PeriodicThreadedEvent to EA and use it (#530)
* Add PeriodicThreadedEvent to EA and use it

* All timers gone

* add tests

* bug: build issues

* bug: form not being disposed properly

---------

Co-authored-by: Björn <steinhagen.bjoern@gmail.com>
2025-01-29 09:28:03 +00:00
Björn Steinhagen 03f0b1fc56 bjorn/cnx-1111-switching-documents-does-not-invalidate-active-connector (#528)
* bug: close plugin when user switches model

* bug: refresh plugin when model changes

* style: remove log information
2025-01-28 15:43:42 +00:00
Adam Hathcock 9e18134c5e Use Event Aggregator with Navisworks (#523)
* Convert selection and idle events

* init NW2025

* testing NW

* formatting
2025-01-28 15:25:19 +00:00
Claire Kuang 67c7ddbf0a fix(all): aligns all panel, button, and tooltip text across connectors (#521)
* updates button labels and panel text

* adds rhino toolbar

* removes unnecessary images

* feat: Add rui to Rhino projects with AssemblyName as filename

---------

Co-authored-by: Alan Rynne <alan@speckle.systems>
2025-01-28 15:07:49 +00:00
Adam Hathcock 79a6062923 Use Event Aggregator with Autocad/Civil (#517)
* Rework doc selection

* add more events

* use idle events

* Fix autocad events and format
2025-01-28 10:12:29 +00:00
Jedd Morgan 81c3c420a7 added workflow back into sln (#524) 2025-01-27 15:38:22 +00:00
Björn Steinhagen 315a0cbf5e bjorn/cnx-1105-add-dynamic-setselection-support-no-events-available (#522)
* refresh GetSelection and UI icon

- refreshing GetSelection based on RVT22 approach
- adding Speckle Beta icon to the UI

* feat: changing default plugin size
2025-01-27 11:37:04 +01:00
Jedd Morgan d753ea47e2 Renamed CI workflows for clarity (#519) 2025-01-24 15:44:16 +00:00
Jedd Morgan da5caa8319 bump sdk (#515)
* bump sdk

* bump sdk for exception handling

* adjust tester

* update SDK

* fix tester again

* fix import

---------

Co-authored-by: Adam Hathcock <adam@hathcock.uk>
2025-01-24 14:04:06 +00:00
Adam Hathcock ca7714a8a3 Use Event Aggregator with Revit (#513)
* This is a workaround for Revit's order of operations when initializing

* Fix event listening

* Only allow methods on classes as opposed to anonymous lambdas

* formatting

* moved revit changed to fresh branch

* fix tests

* weakreference found should remove subscription

* Fix anonymous lambdas

* allow for static handlers and add tests

* Clean up

* formatting

* Change publish to avoid reentrancy issues.  Change from semaphore to lock statement
2025-01-24 13:12:43 +00:00
Adam Hathcock 4b5f3981d3 Some clean up for ETABs (#518)
* Some clean up

* have a model and resizable dialog
2025-01-23 15:50:01 +00:00
Björn Steinhagen 7eb1de4709 bjorn/cnx-880-add-sections-and-materials-as-proxies (#499)
* HostAppVersion

v21 and v22 following SDK updates

* Working POC for material and section proxies

* Refactoring section unpacking

Refactoring in accordance with PropertiesExtractor example

* Material unpackers

* Notes and documentation

* More explanations

* materialId

- Interim solution for viewer filtering is appending the materialId to assignments for each object
- For FRAME this was easy
- For SHELL not so easy. No GetMaterial method avaiable given a AreaObj sectionName. Implemented lightweight materialCache based on cDatabaseTable. Marked as temporary based on previous discussions

* Explicit dictionary entries

* Repeated property strings as consts

- Fair point for repeated strings in the CsiMaterialPropertyExtractor.cs
- Even more reason to include this across all repeated strings. Categories of properties screaming out for this. Added additionally

* PR review comments

- Dictionary lookups for material and section proxies
- Only create proxies for assigned sections and materials (not pretty)

* refactor(etabs): adds singleton converter cache for material and section relationships (#514)

* This is a workaround for Revit's order of operations when initializing (#511)

* This is a workaround for Revit's order of operations when initializing

* Fix event listening

* adds a singleton cache for material and section relationships to csishared

* updating extraction results and simplifying classes

* Only allow methods on classes as opposed to anonymous lambdas for Event Subscription (#512)

* This is a workaround for Revit's order of operations when initializing

* Fix event listening

* Only allow methods on classes as opposed to anonymous lambdas

* formatting

* fix tests

* weakreference found should remove subscription

* doument model store fix (#516)

* testing commit

---------

Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>
Co-authored-by: Björn <steinhagen.bjoern@gmail.com>

* resolving conflicts, testing and small tweaks

- merged dev into branch
- added "type" parameter to group proxies for sections in order to distinguish between frame sections and shell sections

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>
2025-01-22 22:43:47 +01:00
Björn Steinhagen e52df074a1 doument model store fix (#516) 2025-01-22 19:46:11 +01:00
Adam Hathcock 9846817c7f Only allow methods on classes as opposed to anonymous lambdas for Event Subscription (#512)
* This is a workaround for Revit's order of operations when initializing

* Fix event listening

* Only allow methods on classes as opposed to anonymous lambdas

* formatting

* fix tests

* weakreference found should remove subscription
2025-01-22 15:19:48 +00:00
Adam Hathcock c9ca1c0a25 This is a workaround for Revit's order of operations when initializing (#511)
* This is a workaround for Revit's order of operations when initializing

* Fix event listening
2025-01-22 10:44:31 +00:00
Claire Kuang fd2dd9a165 Update DisplayValueExtractor.cs (#509) 2025-01-21 16:38:57 +00:00
Adam Hathcock 83efebfed9 Introduce Event aggregator (#417)
* Remove Dataflow usage

* format and remove dep

* merge fixes

* Fix serializer

* Add MainThreadContext

* add some main context detection

* add RevitMainThreadContext

* remove revit async?

* formatting

* use mainThreadContext

* Use more MainThreadContext

* some rearranging

* renaming

* Revit needs new run async

* merge fixes

* gather on worker, convert on main

* operations know threading but not host apps

* rhino options

* revit can receive

* autocad in progress

* need to yield for UI thread async

* revamp yield

* Found APIContext and removed it

* ArcGIS runs all workers on MCT thread

* Refactor ThreadContext and ArcGIS saving is always on a worker

* Revit threading is simplier?

* ArcGIS can not always go to the queued task

* format

* fix tekla compile errors

* Use EventAggregator to decouple exception handler and UI

* it's ALIVE

* regenerate locks

* Add Prism Evening to DUI

* clean up

* always run on background thread

* Clean up to be specific

* update etabs

* thread context

* autocad threading?

* merge fixes

* remove more async

* clean up

* fix build issues

* Do top level handling in event aggregator

* add some rhino events

* add more Rhino events and do Idle as OneTime with Id

* fix up rhino idle usages

* fmt

* can build agian

* Use valuetask

* fmt

* fix up some bridge execution to be sync

* cleanup

* add some non async paths for progress

* format

* remove needless selection

* Fixes

* Convert tekla

* selection event is used without idle

* Build fixes from merge

* Fix tests and clean up

* Add new events

* Properly dispose one time events

* Minor tekla updates
2025-01-21 14:20:01 +00:00
Claire Kuang 00669ea3c5 fix(civil3d): handles property exceptions for corridor elements (#508)
* Update GeneralPropertiesExtractor.cs

* Update GeneralPropertiesExtractor.cs

* Update CorridorDisplayValueExtractor.cs
2025-01-20 16:59:49 +00:00
Jedd Morgan f02bf2630a Required Keyword changes (#496)
* Required Keyword changes

* Bump deps

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-01-20 14:12:43 +00:00
Adam Hathcock db4d2f7eb0 Fix dev build (#498)
* Fix build

* gitversion doesn't want a shallow clone
2025-01-15 13:18:36 +00:00
Adam Hathcock b9d2f376d6 Fix build (#497) 2025-01-15 12:31:07 +00:00
Adam Hathcock 49baeae780 add gitversion to linux build to version nuget correctly. rename builds (#495)
* add gitversion to linux build to version nuget correctly.  rename builds

* fix naming
2025-01-15 12:18:38 +00:00
Adam Hathcock d76865e621 moving IFC to connectors repo (#488)
* First pass of moving IFC to connectors repo

* Fix some errors and ignore others

* fix namespaces and exceptions

* fix namespaces

* formatting

* Fix namespaces and move stuff

* add linux ci

* more csproj changes

* importer stuff will be the nuget

* add pack version and to Local sln

* do a nuget push on main

* fix restore
2025-01-15 12:01:45 +00:00
Adam Hathcock bedf363810 Update to SDK 228 (#494) 2025-01-15 11:30:43 +00:00
Jonathon Broughton 48670c4030 Update NavisworksDocumentModelStore.cs (#491)
- Add reference to `Autodesk.Navisworks.Api.DocumentParts.DocumentDatabase`
- Add `_lastSavedState` field to store the last saved state
- Compare current state with last saved state before saving
- Update last saved state after successful save
- Rename `ClearAndSave` method to `ClearAndSaveThisState` for clarity pseudo override
- Reset last saved state when clearing models
2025-01-14 10:52:46 +00:00
Adam Hathcock ba0cdd307f Add better progress tor receive (#487)
* update SDK

* Add better progress to receive

---------

Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
2025-01-14 07:38:19 +00:00
Jonathon Broughton 2a508e6302 fix(Navisworks): CNX-895 - Add ColorProxy Support for 2D Linework (#492)
* Add ColorUnpacker

* Add ColorConverter helper class for Navisworks conversion

This commit adds a new file, ColorConverter.cs, to the Helpers folder in the NavisworksShared project. The ColorConverter class provides methods for converting Navisworks colors to System.Drawing.Color, generating color hash strings, and getting human-readable color names.

* Refactor NavisworksMaterialUnpacker.cs for improved color conversion

The code changes in this commit refactor the NavisworksMaterialUnpacker.cs file to improve the color conversion process. Specifically, the ColorConverter class is now used to convert Navisworks colors to standard colors. This change enhances the accuracy and reliability of color conversions throughout the codebase.

* Add NavisworksColorUnpacker class to improve color unpacking logic

The commit adds the `NavisworksColorUnpacker` class to improve the logic for unpacking colours from Navisworks objects. It introduces a new method `UnpackColor` that takes in a list of Navisworks objects and a dictionary of grouped nodes. The method iterates over the objects, skips non-2D elements, and extracts colour information based on the selected representation mode.

The commit also introduces a helper method `Is2DElement` that checks if a given model item is a 2D element by examining its geometry using the ComApi.

Additionally, a new class `PrimitiveChecker` is added to implement the callback interface for checking primitive types in Navisworks geometry.

These changes aim to enhance the accuracy and efficiency of color unpacking for Navisworks objects.

* Add NavisworksColorUnpacker to service registration

Add NavisworksColorUnpacker to service registration

This commit adds the NavisworksColorUnpacker class to the service registration in the NavisworksConnectorServiceRegistration.cs file. Additionally, it includes the necessary changes in the NavisworksRootObjectBuilder.cs file to inject the NavisworksColorUnpacker dependency.

* Refactor BuildAsync function to reduce complexity

- Validate input parameters before processing
- Initialize root collection with name and units
- Convert all model items and store results
- Validate conversion results to ensure successful conversion
- Build final elements by grouping sibling geometry nodes and adding remaining non-grouped nodes
- Add proxies (render materials and colors) to the root collection if applicable
2025-01-14 09:54:18 +03:00
Adam Hathcock 9d70579c40 add msbuild targets files that are specific to host apps (#483)
* add custom navisworks targets

* add more targets files that are specific to host apps
2025-01-13 13:03:43 +00:00
Adam Hathcock e4ac573631 Always run Main stuff on the revit message pump (#486)
* Always run Main stuff on the revit message pump

* formatting
2025-01-13 12:34:35 +00:00
Adam Hathcock 11327cf544 Update SDK to 225 (#477)
* Update SDK to 223

* update to 225
2025-01-13 12:13:22 +00:00
KatKatKateryna 029e10b661 fix path encoding (#481)
* fix path encoding

* add comments

* more compact
2025-01-13 19:22:37 +08:00
Dimitrie Stefanescu c1c8b645e0 Merge pull request #485 from specklesystems/dimitrie/cnx-124-conversion-of-areas-and-rooms-cannot-handle-more-complex
fix: ignoring extra categories we cannot support correctly
2025-01-10 20:46:29 +00:00
Dimitrie Stefanescu 49ef7d1353 fix: revit 2022 2025-01-10 20:37:51 +00:00
Dimitrie Stefanescu 745886e9dd chore: adds comment i missed out on earlier 2025-01-10 20:05:32 +00:00
Dimitrie Stefanescu 825945a547 fix: ignoring extra categories we cannot support correctly 2025-01-10 19:55:13 +00:00
Dimitrie Stefanescu e9556170f5 Merge pull request #484 from specklesystems/dimitrie/cnx-916-revit-all-conversions-pass-nothing-fails-philosophical
Dimitrie/cnx 916 revit all conversions pass nothing fails
2025-01-10 19:31:44 +00:00
Dimitrie Stefanescu 87ffe5b5f8 fix: revit 2022 error 2025-01-10 19:27:53 +00:00
Dimitrie Stefanescu 9466d8b883 fix: review comment 2025-01-10 19:26:02 +00:00
Dimitrie Stefanescu 25e37e257e fix/performance: prevents endless throws for elements with invalid locations 2025-01-10 18:52:13 +00:00
Dimitrie Stefanescu 165c0c9f0d feat: cleans up views 2025-01-10 18:51:47 +00:00
Dimitrie Stefanescu 98cfebf5bc feat: cleans up categories
and prevents (most) unsupported/unnecessary element sending
2025-01-10 18:51:05 +00:00
Claire Kuang 1d910bfc45 fix(civil): adds top level cogopoint converter (#476)
* adds top level cogopoint converter

* change to typeof

---------

Co-authored-by: Adam Hathcock <adam@hathcock.uk>
2025-01-10 14:22:42 +00:00
Adam Hathcock 94104c2365 NameAndRankValue now uses a type to get FullName to avoid conflicts (#475)
* NameAndRankValue now uses a type to get FullName to avoid conflicts

* Full namespace for tests
2025-01-10 13:59:59 +00:00
Adam Hathcock c5d37a1250 Add custom assembly resolve for Navisworks (#478)
* Add custom assembly resolve for Navisworks

* format
2025-01-10 09:37:15 +00:00
Dimitrie Stefanescu 5812e1c976 Merge pull request #482 from specklesystems/dimitrie/cnx-851-stacked-wall-duplicate-geometry-or-materials-not-applied
fix: stacked wall duplication when sending by view
2025-01-09 18:35:08 +00:00
Dimitrie Stefanescu 01bc8bf929 fix: stacked wall duplication when sending by view 2025-01-09 18:22:28 +00:00
Oğuzhan Koral dbefb1b290 Null check before attempt to override view options (#474) 2025-01-08 21:26:34 +03:00
Dimitrie Stefanescu b5b9d061ef Merge pull request #473 from specklesystems/dimitrie/cnx-933-model-cards-out-of-snyc-with-application-when-opening-saved
fix: expired cards on file open
2025-01-08 14:06:31 +00:00
Dimitrie Stefanescu 20e08bba76 fix: expired cards on file open 2025-01-08 13:59:24 +00:00
Dogukan Karatas 23710ee3fb adds null check (#470)
Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
2025-01-08 09:30:08 +00:00
Dimitrie Stefanescu 9b5cc21aa4 Merge pull request #472 from specklesystems/dimitrie/cnx-925-object-tracking-modifying-layer-color-or-layer-name
Dimitrie/cnx 925 Invalidates model cards from layer change events (name, colour)
2025-01-07 18:48:55 +00:00
Dimitrie Stefanescu 1016c9b82b fix: more naming 2025-01-07 18:42:01 +00:00
Dimitrie Stefanescu c6b9651d08 chore: naming 2025-01-07 18:37:44 +00:00
Dimitrie Stefanescu 73302f101a feat: adds layer changes object tracking 2025-01-07 17:57:50 +00:00
Dimitrie Stefanescu 516b4d785f feat: run extra intersection checks only if needed 2025-01-07 17:49:14 +00:00
Dimitrie Stefanescu a9850c2eec feat: adds support for group selection events (#471)
* feat: adds support for group selection events

* feat: stores group objects separately so we don't reconvert them

this will be necessary as well for layer change events later down the line

* chore: comments
2025-01-07 19:29:26 +03:00
Dimitrie Stefanescu 64c5503637 Merge pull request #466 from specklesystems/update-sdk
Update SDK to 222
2025-01-07 15:48:06 +00:00
Adam Hathcock d15ea4310a Merge branch 'dev' into update-sdk 2025-01-07 15:39:41 +00:00
Dogukan Karatas 9fa3ef83e5 adds update selection (#469) 2025-01-07 14:10:58 +00:00
Dimitrie Stefanescu 724e8fe029 Dimitrie/cnx 938 did not find a layer in cache (#468)
* fix: adds a converter for displayable objects

* fix: ensures correct layer creation for collections with empty names
2025-01-07 17:03:37 +03:00
Adam Hathcock 3ea5677497 Rhino panels should be treated as if they might have been used before… (#467)
* Rhino panels should be treated as if they might have been used before as Panels.Closed isn't called

* formatting

* Only Reinitialize when Rhino 8 and greater

* format
2025-01-07 12:38:52 +00:00
Adam Hathcock a1e3e509fd Update SDK to 222 2025-01-03 15:58:10 +00:00
Adam Hathcock 95b3731df2 Fix Navisworks and others progress by yielding to UI thread (#465)
* Navisworks needs proper Async to update UI thread inline

* Tested Autocad and Rhino

* format and fix

* ArcGIS should yield too

* async/await for Tekla and ETABs
2024-12-31 15:04:25 +00:00
Jonathon Broughton dcc29f3461 Update Navisworks connector plugin bundle target and version content target paths. (#464) 2024-12-25 16:36:28 +00:00
Jonathon Broughton 13740de72f fix(Navisworks): CNX-973 Fix: Material ID Logic and Render Proxy Cache (#463) 2024-12-25 16:32:10 +00:00
Adam Hathcock f2f11c3f2b Threading revamp: add ThreadContext and remove Dataflow usage (#400)
* Navisworks Connector Init

* Build crap

* Moar Init

* WIP - not yet working

* Minor fixes

* Fix missing constuctors

* unfix

* Test commit

* Test commit

* Remove Dataflow usage

* format and remove dep

* merge fixes

* Fix serializer

* Add MainThreadContext

* add some main context detection

* add RevitMainThreadContext

* remove revit async?

* Handle Document Events

* Document Model Store

* Proper implementation

* package updates

* updated to dev

* Document Events binding ???

* registration order

* Minimised events subscribed and handle new document state to clear models

* Stub Send command

* Refactor Connector class to change access modifier of Container property

The commit modifies the access modifier of the Container property in the Connector class from public to private. This change improves encapsulation and ensures that the property can only be accessed within the class itself.

* Fix NavisworksDocumentStore model list initialization and document validation

The commit fixes the initialization of the Models list in the NavisworksDocumentStore class. Instead of assigning an empty array, it now uses the Clear() method to clear the existing models.

Additionally, the commit improves the document validation logic by checking if critical properties are accessible before considering the document valid. It also handles cases where the document is disposed.

These changes ensure proper initialization of model lists and accurate document validation in NavisworksDocumentStore.

* Effectively debouncing on the SDI changes events

* Get Selected Objects

* ElementSelectionExtension is a collection of helpers to aid the resolution of intent

* [Navisworks] Manage document and model state changes

- Refactor NavisworksDocumentEvents to manage both document and model state change notifications
- Update comments to reflect the new functionality
- Rename SubscribeToEvents method to SubscribeToDocumentModelEvents for clarity
- Add HandleDocumentModelCountChanging and HandleDocumentModelCountChanged methods to track model count changes
- Update OnDocumentModelCountChanged method name to NotifyValidModelStateChange for clarity
- Update UnsubscribeFromEvents method name to UnsubscribeFromDocumentModelEvents for clarity
- Remove unused constants from NavisworksDocumentStore class

* formatting

* use mainThreadContext

* Use more MainThreadContext

* Update Navisworks API references and fix typos

- Update references to `Autodesk.Navisworks.Api` namespace to `NAV` namespace
- Fix typo in file name: `GlobalUsings.cs` renamed to `GlobalUsing.cs`
- Update references to `ModelItem` type from `Autodesk.Navisworks.Api` namespace to `NAV.ModelItem`
- Update references to `Document` type from `Autodesk.Navisworks.Api` namespace to `NAV.Document`
- Update references to database related types from `Autodesk.Navisworks.Api.Data` namespace to `NAV.Data`
- Add new file: NavisworksRootObjectBuilder.cs
- Remove unused using statements

* Add Navisworks2024 converter dependencies and update project references

- Added "Objects.Converter.Navisworks2024" to the packages.lock.json file with dependencies on "Speckle.Converters.Common" and "Speckle.Navisworks.API"
- Updated the Speckle.Connectors.Navisworks2024.csproj file to include a reference to "Speckle.Converters.Navisworks2024.csproj" and "Speckle.Converters.Common.csproj"
- Added "speckle.converters.common" to the packages.lock.json file with dependencies on "Microsoft.Extensions.Logging.Abstractions" and "Speckle.Objects"
- Renamed files:
  - NavisworksConversionSettings.cs -> NavisworksConversionSettingsFactory.cs
  - GlobalUsings.cs -> GlobalUsing.cs
  - NavisworksConversionSettings.cs -> Settings/NavisworksConversionSettings.cs
  - NavisworksConversionSettings.cs -> Services/NavisworksToSpeckleUnitConverter.cs
  - NavisworksConversionSettings.cs -> ToSpeckle/NavisworksRootToSpeckleConverter.cs

* feat: Add NavisworksSendBinding changes

- Added Microsoft.Extensions.DependencyInjection and Microsoft.Extensions.Logging namespaces
- Added Speckle.Connectors.Common.Operations namespace
- Added Speckle.Connectors.DUI.Exceptions, Speckle.Connectors.DUI.Logging, and Speckle.Connectors.DUI.Models.Card namespaces
- Added Speckle.Sdk and Speckle.Sdk.Common namespaces
- Updated constructor of NavisworksSendBinding class to include additional parameters
- Updated Send method in NavisworksSendBinding class to include try-catch block for handling exceptions during send operation
- Updated CancelSend method in NavisworksSendBinding class to call the cancellation manager's CancelOperation method with the modelCardId parameter
- Added ResolveIndexPathToModelItem method in ElementSelectionExtension class to resolve the model item path from an index path string
- Added ResolveGeometryLeafNodes method in ElementSelectionExtension class to resolve geometry leaf nodes from a model item
- Updated Send method in NavisworksSendBinding class to use the resolved model items for sending data

* Update namespace in Navisworks plugin files

- Update namespace from "Speckle.Connector.Navisworks.NavisPlugin" to "Speckle.Connector.Navisworks.Plugin" in Commands.cs, DockableConnectorPane.cs, and NavisworksRibbon.xaml.cs files.

* Add Navisworks sending operations and converters

- Added sending operations for Navisworks models
- Registered the root object builder and send operation for Navisworks model items
- Added Navisworks converters to the service registration
- Updated the NavisworksRootToSpeckleConverter to handle null targets and validate target type before conversion

* Add folder to project items

- Added a new folder to the project items in the Navisworks converter.
- The folder includes the necessary files for extensions, global using, service registration, and conversion settings factory.

* Refactor NavisworksConversionSettings class to use properties instead of fields

- Convert fields to properties in NavisworksConversionSettings class
- Update constructor to initialize properties instead of fields

* Add Navisworks conversion settings factory and store initialization

- Add `INavisworksConversionSettingsFactory` to the constructor of `NavisworksSendBinding`
- Initialize `_conversionSettingsFactory` in the constructor of `NavisworksSendBinding`
- Initialize the conversion settings store with `_conversionSettingsFactory.Create(NavisworksApp.ActiveDocument)`

* Change element selection path separator from '.' to '/' in ElementSelectionExtension.cs

This commit updates the code in ElementSelectionExtension.cs to change the default separator used for resolving a Navisworks model item's unique index path representation. The previous separator was '.', and it has been changed to '/'. This change ensures consistency and compatibility with other parts of the codebase that rely on this representation.

* Add Navisworks model item to Speckle converter

- Add `ModelItemToSpeckleConverter.cs` file for converting Navisworks model items to Speckle objects.
- Update `GlobalUsing.cs` to include `SSM` namespace.
- Update project file `Speckle.Converters.NavisworksShared.projitems` to include the new converter file.

* some rearranging

* renaming

* Revit needs new run async

* merge fixes

* gather on worker, convert on main

* Update Speckle.Objects and Speckle.Sdk versions to 3.1.0-dev.200

- Updated the requested and resolved versions of Speckle.Objects and Speckle.Sdk to 3.1.0-dev.200 in packages.lock.json files for Connectors/Navisworks/Speckle.Connectors.Navisworks2024 and Converters/Navisworks/Speckle.Converters.Navisworks2024 directories.
- Also updated the contentHash values for both packages.

Note: This commit updates the versions of Speckle.Objects and Speckle.Sdk to 3.1.0-dev.200 in the mentioned directories' packages.lock.json files, along with their respective contentHash values being updated as well.

* operations know threading but not host apps

* Add Navisworks and 2024 projects, along with their connectors and converters

This commit adds the Navisworks project, along with the 2024 project. It also includes the connectors and converters for both projects.

* rhino options

* revit can receive

* autocad in progress

* need to yield for UI thread async

* revamp yield

* Found APIContext and removed it

* ArcGIS runs all workers on MCT thread

* Refactor ThreadContext and ArcGIS saving is always on a worker

* Revit threading is simplier?

* ArcGIS can not always go to the queued task

* format

* fix tekla compile errors

* update etabs

* thread context

* autocad threading?

* Add Navisworks conversion settings and modes

This commit adds new files for Navisworks conversion settings and modes.
- The `ConversionModes.cs` file defines enums for representation mode and origin mode used during conversion.
- The `NavisworksConversionSettings.cs` file represents the settings used for Navisworks conversions, including properties such as document, units, origin mode, hidden elements, visual representation mode, and more.
- A new factory class `NavisworksConversionSettingsFactory.cs` is added to create instances of the conversion settings with calculated values based on the active document.
- A new file `GeometryHelpers.cs` which contains a static class `GeometryHelpers`. The class provides a method `VectorMatch` that compares two vectors to determine if they are approximately equal within a given tolerance. The method takes in two vectors and an optional tolerance value, and returns true if the vectors match within the tolerance, otherwise false.

* Add ArrayExtensions.cs for converting arrays to generic type arrays

This commit adds a new file, ArrayExtensions.cs, which contains an extension method for converting arrays to generic type arrays. The method uses the `Array.Copy` function to copy the elements of the original array into a new array of the specified generic type. This allows for more flexibility when working with arrays in the codebase.

Specifically Navisworks heavily uses 1* indexed arrays which are a pain to access generically.

* Delete Navisworks converters

This commit deletes two files: ModelItemToSpeckleConverter.cs and NavisworksRootToSpeckleConverter.cs. These files contained code related to converting Navisworks models to Speckle format. The deletion of these files indicates that the functionality provided by these converters is no longer needed or has been replaced by other methods.

* Add new classes for double-precision geometric primitives and transformation matrices

- Added `Primitives.cs` file containing definitions for `PointD`, `TriangleD`, and `LineD` classes with double-precision vertex storage
- Added `TransformMatrix.cs` file containing a class for 4x4 transformation matrices
- Updated project items to include the new files in the build process

* Add NavisworksObject and NavisworksGeometryObject classes

This commit adds the NavisworksObject and NavisworksGeometryObject classes to handle non-geometry and geometry-based Speckle objects converted from Navisworks. These classes implement the INavisworksObject interface, which provides methods for adding properties to objects and retrieving property values by key. The NavisworksObject class represents a non-geometry object with a name property and a dictionary of properties, while the NavisworksGeometryObject class represents a geometry-based object with a displayValue property, name property, and a dictionary of properties.

* Add ClassPropertiesExtractor, DisplayValueExtractor, and PropertySetsExtractor classes

- Added ClassPropertiesExtractor class to extract class properties from a NAV.ModelItem
- Added DisplayValueExtractor class to extract display values from a NAV.ModelItem
- Added PropertySetsExtractor class to extract property sets from a NAV.ModelItem

* feat: Add ExcludeProperties option to NavisworksConversionSettings

This commit adds a new boolean property, ExcludeProperties, to the NavisworksConversionSettings class. This property allows users to specify whether properties should be excluded from the output. The default value is set to false.

Changes:
- Added ExcludeProperties boolean property to NavisworksConversionSettings
- Updated NavisworksConversionSettingsFactory to include _excludeProperties field and pass it to the NavisworksConversionSettings constructor

* feat: Add ModelItemTopLevelConverterToSpeckle

This commit adds the `ModelItemTopLevelConverterToSpeckle` class, which converts Navisworks `ModelItem` objects to Speckle Base objects. The converter extracts display values, class properties, and property sets from the Navisworks object and creates a corresponding Speckle Base object.

* Add ModelPropertiesExtractor to NavisworksShared

This commit adds the ModelPropertiesExtractor class to the NavisworksShared project. The ModelPropertiesExtractor is responsible for extracting model properties from a NAV.Model and adding them to a dictionary. These properties include Creator, Filename, Source Filename, Units, Transform, Guid, and Source Guid. The extracted properties are then added to the navisworks object as key-value pairs.

* Refactor PropertyHelpers to handle property conversion and sanitization

- Refactored `PropertyHelpers` class to be static
- Added a dictionary of type handlers for converting property values
- Implemented `ConvertPropertyValue` method to convert property values based on their data type
- Added support for handling different data types, including boolean, string, integer, double, datetime, named constant, and 3D point
- Implemented `SanitizePropertyName` method to replace invalid characters in property names with underscores
- Added `IsCategoryToBeSkipped` method to determine if a property category should be skipped during processing

* feat: Add property set extraction logic

This commit adds logic to extract property sets from a NAV.ModelItem. It iterates through the property categories and properties, skipping certain categories as needed. Each property is added to a dictionary with its sanitized name as the key and its converted value based on Speckle units. The resulting property sets are stored in a dictionary with the sanitized category name as the key.

* Refactor ModelItemTopLevelConverterToSpeckle: Add IRootToSpeckleConverter interface

This commit adds the `IRootToSpeckleConverter` interface to the `ModelItemTopLevelConverterToSpeckle` class. It also modifies the `Convert` method to handle null target objects and updates the implementation of the `CreateNonGeometryObject` method.

* Add Navisworks 2020 - 2025

In addition to 2024

* Update DocumentModelStore.cs

- Made `HostAppSaveState` and `LoadState` methods public
- Updated method signatures to reflect changes

* Add BoundingBoxToSpeckleRawConverter

This commit adds the BoundingBoxToSpeckleRawConverter class, which is responsible for converting NAV.BoundingBox3D objects to Box objects. It includes methods for converting the target object and a nullable version of it. The converter uses settings from the IConverterSettingsStore interface to set up the base plane and create the bounding box with appropriate units and intervals.

* Fix null reference exception in NavisworksRootObjectBuilder.cs

The code change fixes a null reference exception that occurs when checking if `navisworksModelItems` is empty or null. If it is, a `SpeckleException` is thrown with the message "No objects to convert". Additionally, a check for `sendInfo` being null has been added before continuing with the conversion process. The progress of the conversion is reported using the `onOperationProgressed` callback.

* Refactor NavisworksBasicConnectorBinding and NavisworksSendBinding

- Simplify AddModel method in NavisworksBasicConnectorBinding
- Remove unused import statements in NavisworksSendBinding
- Update initialization of conversion settings in NavisworksSendBinding

* Update NavisworksServiceRegistration.cs

- Removed unused using statements
- Updated AddDUI method to use NavisworksDocumentModelStore
- Updated DocumentModelStore registration to use NavisworksDocumentModelStore

* Refactor NavisworksDocumentModelStore to updated API

- Clear the store and save when models are removed
- Load state from the database when models are added
- Rename methods for clarity: ReadFromFile() -> LoadState(), WriteToFile() -> HostAppSaveState()
- Improve exception handling and error messages

* Refactor data extractors in Navisworks converter

- Make `GetClassProperties`, `GetDisplayValue`, `GetModelProperties`, and `GetPropertySets` methods internal
- Remove unused using statements

* Update GlobalUsing.cs: Remove unnecessary global using statement

The commit removes an unnecessary global using statement in the GlobalUsing.cs file. This change helps to clean up the code and improve readability.

* Add NavisworksPrimitiveProcessor and PrimitiveProcessor classes

- Added NavisworksPrimitiveProcessor class with methods for processing Navisworks primitives
- Added PrimitiveProcessor class with methods for processing generic primitives
- Updated the constructor of PrimitiveProcessor to accept an additional parameter for local to world transformation
- Updated the Line, Point, and Triangle methods in both classes to use the new transformation logic

* feat: Add internal modifier to VectorMatch method

- Changed the access modifier of the VectorMatch method in GeometryHelpers class from public to internal.

feat: Add sealed modifier to NavisworksObject and NavisworksGeometryObject classes

- Added the sealed modifier to the NavisworksObject and NavisworksGeometryObject classes in NavisworksObjects.cs file.

refactor: Rename enum values in ConversionModes.cs

- Renamed the enum values MODEL_ORIGIN, PROJECT_BASE_ORIGIN, and BOUNDING_BOX_ORIGIN to MODELORIGIN, PROJECTBASEORIGIN, and BOUNDINGBOXORIGIN respectively in ConversionModes.cs file.

refactor: Update CreateGeometryObject method signature

- Updated the CreateGeometryObject method signature in ModelItemTopLevelConverterToSpeckle.cs file by making it static and using DisplayValueExtractor.GetDisplayValue instead of _displayValueExtractor.GetDisplayValue.

* Change origin mode constants to use camel case and update related calculations

- Update the origin mode constant from "MODEL_ORIGIN" to "MODELORIGIN"
- Update the origin mode constant from "PROJECT_BASE_ORIGIN" to "PROJECTBASEORIGIN"
- Update the origin mode constant from "BOUNDING_BOX_ORIGIN" to "BOUNDINGBOXORIGIN"
- Update the calculation of the transformation vector based on the new origin mode constants

* Add NavisworksPrimitiveProcessor and BoundingBoxToSpeckleRawConverter

The commit adds two new files: NavisworksPrimitiveProcessor.cs and BoundingBoxToSpeckleRawConverter.cs to the project. These files are included in the compilation process.

* Add support for Speckle connectors in Navisworks versions 2020 to 2025.

- Added runtime requirements and component entries for Navisworks versions 2020 to 2025.
- Each component entry includes the module name and app description.

* Add database transaction for table creation in NavisworksDocumentModelStore.cs

This commit adds a database transaction to ensure the existence of the required table before performing any operations in NavisworksDocumentModelStore.cs. This helps maintain data integrity and prevents errors related to missing tables.

* Update Navisworks connectors to include Speckle.Connectors.DUI dependency.

- Added "Speckle.Connectors.DUI" as a dependency in the Navisworks2020, Navisworks2021, Navisworks2022, Navisworks2023, and Navisworks2024 packages.
- Updated project references in the Navisworks2024 package to include the "Speckle.Connectors.DUI" project.
- Added "Speckle.Connectors.DUI" as a dependency in the Navisworks2025 package.
- Renamed "NavisworksServiceRegistration.cs" to "NavisworksConnectorServiceRegistration.cs".
- Updated project references in the NavisworksConverters for 2020 and 2021 packages to include the "Speckle.Connectors.DUI" project.

* Refactor NavisworksSendBinding constructor parameters and dependencies

- Changed the type of `_conversionSettingsFactory` parameter in `NavisworksSendBinding` constructor from `INavisworksConversionSettingsFactory` to `NavisworksConversionSettingsFactory`.
- Removed duplicate initialization of `Parent` and `Commands` properties in the `NavisworksSendBinding` constructor.
- Moved the call to `SubscribeToNavisworksEvents()` after initializing `_conversionSettingsFactory`.

Register additional services for Navisworks connector

- Added registration for `ToSpeckleSettingsManager`.
- Added registration for `IOperationProgressManager`.

Refactor NavisworksRootObjectBuilder

- Updated access to `_converterSettings.Current.SpeckleUnits` to `_converterSettings.Current.Derived.SpeckleUnits`.

Update DockableConnectorPane.cs

- Updated the call to `services.AddNavisworksConverters()` to use the correct method name, which is now `services.AddNavisworksConverter()`.

Refactor ClassPropertiesExtractor, ModelPropertiesExtractor, and PropertySetsExtractor

- Updated access to `_settingsStore.Current.ExcludeProperties` to use `_settingsStore.Current.User.ExcludeProperties`.

Register additional services for Navisworks converter

- Added registration for `IToSpeckleSettingsManager`.
- Added registration for `INavisworksConversionSettingsFactory`.

* Bruh!!

- Update the type of _conversionSettingsFactory field from NavisworksConversionSettingsFactory to INavisworksConversionSettingsFactory.
- Update the type of conversionSettingsFactory parameter in the constructor from NavisworksConversionSettingsFactory to INavisworksConversionSettingsFactory.

* Add NavisworksRootObjectBuilder and related settings classes for sending operations

Add NavisworksRootObjectBuilder and related settings classes for sending operations

- Added NavisworksRootObjectBuilder class for sending operations
- Added ConvertHiddenElementsSetting class for sending operations
- Added IncludeInternalPropertiesSetting class for sending operations
- Added OriginModeSetting class for sending operations
- Added VisualRepresentationSetting class for sending operations

* Refactor conversion mode and origin mode enums

- Renamed "ACTIVE" to "Active"
- Renamed "ORIGINAL" to "Original"
- Renamed "PERMANENT" to "Permanent"
- Renamed "MODELORIGIN" to "ModelOrigin"
- Renamed "PROJECTBASEORIGIN" to "ProjectBasePoint"
- Renamed "BOUNDINGBOXORIGIN" to "BoundingBoxCenter"

Updated the NavisworksConversionSettingsFactory class:

- Updated references and imports
- Updated switch cases for originMode enum with new names

* feat: Add new settings to NavisworksSendBinding and remove unused import

- Added new settings to the `GetSendSettings()` method in `NavisworksSendBinding` class.
- Removed unused import of `Speckle.Connector.Navisworks.Settings` in `NavisworksConverterServiceRegistration.cs`.

* Update Navisworks connector service registration and settings manager

- Updated the service registration in `NavisworksConnectorServiceRegistration.cs` to use `ToSpeckleSettingsManagerNavisworks` instead of `ToSpeckleSettingsManager`.
- Renamed `ToSpeckleSettingsManager.cs` to `ToSpeckleSettingsManagerNavisworks.cs` in the send operations settings folder.
- Updated the project file `Speckle.Connectors.NavisworksShared.projitems` to include the renamed file.
- Added a new dependency on `speckle.connectors.dui.webview`, which includes dependencies on `Microsoft.Web.WebView2` and `Speckle.Connectors.DUI`.
- Updated the conversion settings factory in `NavisworksConversionSettingsFactory.cs` to use `IToSpeckleSettingsManagerNavisworks` instead of `IToSpeckleSettingsManager`.

* Add project references to DUI and Navisworks converters in Navisworks connectors

- Added a project reference to `Speckle.Connectors.DUI` in the Navisworks 2020, 2021, 2022, 2023, and 2025 connector projects.
- Added project references to the respective Navisworks converter projects in the Navisworks 2020, 2021, 2022, 2023, and 2025 connector projects.
- Removed a compile include for `NavisworksSelectionFilter.cs` from the shared Navisworks converter projitems file.
- Added a compile include for `NavisworksSelectionFilter.cs` in the send filters folder of the shared Navisworks converter projitems file.

* here we go again

This commit adds support for Navisworks conversion settings in the SendBinding class. It introduces a new interface, IToSpeckleSettingsManagerNavisworks, and implements it in the ToSpeckleSettingsManagerNavisworks class. The NavisworksSendBinding constructor now takes an additional parameter of type IToSpeckleSettingsManagerNavisworks.

In addition, some file and namespace renaming has been done to align with the changes made.

* FFS - Cyclical relationships or missing assemblies

* FFS

- Removed references to Navisworks2020, Navisworks2021, Navisworks2022, Navisworks2023, and Navisworks2025 connectors in packages.lock.json files
- Commented out project references to Navisworks2020, Navisworks2021, Navisworks2022, Navisworks2023, and Navisworks2025 connectors in csproj files
- Updated project reference for shared converter in shproj file

* Update NavisworksConnectorServiceRegistration.cs

- Update the registration of ToSpeckleSettingsManagerNavisworks to use the interface IToSpeckleSettingsManagerNavisworks instead of the concrete class ToSpeckleSettingsManagerNavisworks.

* Update NavisworksSendBinding to use ToSpeckleSettingsManagerNavisworks instead of IToSpeckleSettingsManagerNavisworks for conversion settings retrieval.

Update NavisworksSendBinding to use ToSpeckleSettingsManagerNavisworks instead of IToSpeckleSettingsManagerNavisworks for conversion settings retrieval.

This commit updates the NavisworksSendBinding code to replace the usage of IToSpeckleSettingsManagerNavisworks with ToSpeckleSettingsManagerNavisworks for retrieving conversion settings. This change ensures consistency and improves the overall functionality of the code.

* merge fixes

* Refactor NavisworksObjects.cs: Improve object representation and property handling

- Rename `NavisworksObject` to `NavisworksModelItem`
- Remove unused properties and suppress style warnings
- Add required parameters to constructors for `name` and `displayValue`
- Update property accessors for `elements`, `displayValue`, and `name`
- Improve implementation of `AddProperty` and `GetProperty` methods

* Refactor display value extraction and object creation in Navisworks converter

- Refactored the `GetDisplayValue` method in `DisplayValueExtractor.cs` to be an instance method instead of static.
- Updated the `CreateGeometryObject` method in `ModelItemTopLevelConverterToSpeckle.cs` to use an instance of `DisplayValueExtractor`.
- Changed the return type of `CreateNonGeometryObject` method in `ModelItemTopLevelConverterToSpeckle.cs` to match the updated class name.

These changes improve code organization and maintainability.

* Update Speckle SDK and Objects to version 3.1.0-dev.203 in Navisworks connectors for versions 2020, 2021, 2022, and 2023.

* remove more async

* clean up

* can build agian

* Use valuetask

* fmt

* fix up some bridge execution to be sync

* Refactor NavisworksRootObjectBuilder.cs: Improve initialization of root object collection

- Initialize root object collection with name and units in a more concise way
- Improve readability and maintainability of the code

* Fix logger import in NavisworksRootObjectBuilder.cs

The commit fixes an issue with the logger import in the NavisworksRootObjectBuilder.cs file. The incorrect namespace was causing a compilation error. This change ensures that the correct namespace is used for the logger, resolving the compilation error and allowing for proper logging functionality.

* Refactor ClassPropertiesExtractor to simplify GetClassProperties method

The GetClassProperties method in the ClassPropertiesExtractor class has been refactored to improve readability and reduce unnecessary code. The if statement that checks for exclusion of properties has been removed, as it is no longer needed. Instead, the ExtractClassProperties method is directly returned. This change simplifies the logic and improves code maintainability.

* Fix static method in DisplayValueExtractor

The commit fixes a bug in the DisplayValueExtractor class where the GetDisplayValue method was not declared as static. This caused a compilation error. The fix makes the method static, allowing it to be called without an instance of the class.

* Add BasePropertyHandler, HierarchicalPropertyHandler, IPropertyHandler, and StandardPropertyHandler classes for handling property assignment in Navisworks conversion.

- Added IPropertyHandler interface to define the contract for handling property assignment to Speckle objects.
- Added BasePropertyHandler class to provide common functionality for property assignment.
- Added StandardPropertyHandler class to handle standard property assignment without any merging or hierarchy processing.
- Added HierarchicalPropertyHandler class to handle property assignment with hierarchy merging for objects that require ancestor properties.

* Refactor class hierarchy and method signatures for Navisworks conversion

- Make `GetClassProperties` method in `ClassPropertiesExtractor` static
- Remove `classPropertiesExtractor` parameter from constructors in `BasePropertyHandler`, `HierarchicalPropertyHandler`, and `StandardPropertyHandler`
- Update references to `classPropertiesExtractor.GetClassProperties(modelItem)` to use the static method `ClassPropertiesExtractor.GetClassProperties(modelItem)`
- Rename private field `_properties` in classes implementing `INavisworksObject` to `Properties`
- Rename public property `elements` in class `NavisworksModelItem` to `Elements`
- Rename public property `displayValue` in class `NavisworksModelGeometry` to lowercase (`displayvalue`)
- Add missing using statements

* Add ElementSelectionHelper class for working with Navisworks ModelItem selections.

This commit adds a new file, ElementSelectionHelper.cs, which contains a static class called ElementSelectionHelper. This class provides extension methods for working with Navisworks ModelItem selections. The class includes the following significant changes:

- Added ResolveModelItemToIndexPath method: This method takes a Navisworks ModelItem and resolves it to its unique index path representation. The resulting string represents the model item's path, including the model index and a hierarchical path identifier separated by a specified separator.
- Added ResolveIndexPathToModelItem method: This method takes an index path string and resolves it to a Navisworks ModelItem. It splits the index path into parts, assigns the first part to the modelIndex variable as an integer, and joins the remaining parts as the pathId string.
- Added IsElementVisible method: This method determines whether a Navisworks ModelItem and all its ancestors are visible. It checks the visibility status for each item in the item's ancestorsAndSelf collection and returns true if none of them are hidden.
- Added ResolveGeometryLeafNodes method: This method takes a Navisworks ModelItem and returns a list of all its descendants (including itself) that have geometry.

These changes enhance functionality related to working with Navisworks ModelItems in Speckle.Converter.NavisworksShared.Helpers namespace.

* cleanup

* WIP on jsdb/navisworks
WIP on jsdb/navisworks

- Replaced `ModelItemTopLevelConverterToSpeckle` with `NavisworksRootToSpeckleConverter` in `NavisworksConverterServiceRegistration.cs`
- Added new files to the project: `BasePropertyHandler.cs`, `HieraerchicalPropertyHandler.cs`, `IPropertyHandler.cs`, and `StandardPrpertyHandler.cs`
- Updated the file path in the project items XML
- Modified `NavisworksRootToSpeckleConverter.cs` to use the updated method name

* Update Speckle.Objects to version 3.1.0-dev.205 in Navisworks connectors for versions 2020, 2021, and 2022.

- Update Speckle.Objects to version 3.1.0-dev.205
- Update Speckle.Sdk to version 3.1.0-dev.205
- Update Speckle.Sdk.Dependencies to version 3.1.0-dev.205

* Fix reserved term replacement in PropertyHelpers.cs

The commit fixes a bug in the PropertyHelpers.cs file where the reserved term "Item" was not being replaced correctly. The replacement has been changed from "Item_" to "Item".

* Refactor property handlers and model objects

- Remove unused code in ClassPropertiesExtractor.cs
- Refactor PropertySetsExtractor.cs to use dependency injection for settingsStore
- Refactor BasePropertyHandler.cs to include classPropertiesExtractor parameter
- Rename HieraerchicalPropertyHandler.cs to HierarchicalPropertyHandler.cs
- Rename StandardPrpertyHandler.cs to StandardPropertyHandler.cs
- Update NavisworksConverterServiceRegistration.cs to register the new property handlers

* Refactor model item name retrieval logic in ModelItemTopLevelConverterToSpeckle.cs

- Refactored the GetObjectName method to improve readability and maintainability.
- Updated the logic to retrieve the target object's display name, cycling through parent objects if necessary.
- Added a fallback case to return "Unnamed model item" if no valid display name is found.

* Whitespace in property name conversion to _ in PropertyHelpers.cs

The code change fixes a bug in the `PropertyHelpers.cs` file where property names were not being converted correctly. The regular expression used to replace characters now includes whitespace characters as well. This ensures that all invalid characters are replaced with underscores, allowing for proper conversion of property names.

* Add GeometryNodeMerger class to handle merging of sibling geometry nodes.

- Added `GeometryNodeMerger` class to handle grouping and merging of sibling geometry nodes.
- Updated `NavisworksRootObjectBuilderExtensions` to use `GeometryNodeMerger` for grouping and merging.
- Updated `NavisworksRootObjectBuilder` to use `ClassPropertiesExtractor` and `PropertySetsExtractor`.
- Refactored code in `NavisworksRootObjectBuilder.Build()` method to improve readability and maintainability.

* modify GeometryNodeMerger.cs and NavisworksRootObjectBuilder.cs

- Modified GeometryNodeMerger.cs to only group anonymous geometry nodes
- Modified NavisworksRootObjectBuilder.cs to refactor the Build method, handle grouped nodes first, and set the final elements list

* add some non async paths for progress

* format

* remove needless selection

* Initialize root collection, convert and store model items, process and merge grouped nodes, add remaining non-grouped nodes, finalize and return.

* Add NavisworksMaterialUnpacker class for unpacking render materials

This commit adds a new file, NavisworksMaterialUnpacker.cs, which contains the implementation of the NavisworksMaterialUnpacker class. This class is responsible for unpacking render materials from Navisworks objects.

The NavisworksMaterialUnpacker class includes methods such as UnpackRenderMaterial and ConvertRenderColorAndTransparencyToSpeckle, which handle the extraction and conversion of render material properties.

Additionally, the project file Speckle.Connectors.NavisworksShared.projitems has been updated to include the newly added NavisworksMaterialUnpacker.cs file.

* Add `NavisworksMaterialUnpacker` to `NavisworksRootObjectBuilder` constructor

- Add `NavisworksMaterialUnpacker` to the service collection in `NavisworksConnectorServiceRegistration.cs`.
- Update the constructor of `NavisworksRootObjectBuilder` to include dependencies for `IRootToSpeckleConverter`, `ISendConversionCache`, `IConverterSettingsStore<NavisworksConversionSettings>`, `ILogger<NavisworksRootObjectBuilder>`, `ISdkActivityFactory`, and `NavisworksMaterialUnpacker`.

This commit adds the registration of the `NavisworksMaterialUnpacker` class to the service collection in order to enable dependency injection. It also updates the constructor of the `NavisworksRootObjectBuilder` class to include all necessary dependencies for its functionality.

* Update Speckle.Objects to version 3.1.0-dev.212 in Navisworks connectors for versions 2020, 2021, and 2022.

The commit updates the packages.lock.json file for the Navisworks connectors for versions 2020, 2021, and 2022. It changes the requested and resolved version of Speckle.Objects from 3.1.0-dev.205 to 3.1.0-dev.212

* Add NavisworksObject to finalElements in NavisworksRootObjectBuilder

This commit adds the NavisworksObject class to the finalElements list in the NavisworksRootObjectBuilder. The NavisworksObject contains properties such as name, displayValue, properties, and units. This change improves the functionality of the code by including additional information for each element in the finalElements list.

* Add applicationId to NavisworksRootObjectBuilder

This commit adds the applicationId property to the NavisworksRootObjectBuilder class in order to include it in the finalElements list. This change ensures that the applicationId is properly assigned and included when building Navisworks objects for sending.

* RunOnMainThreadAsync implemented

- Refactored GetDocumentInfo method in NavisworksBasicConnectorBinding to run on the main thread using Parent.RunOnMainThreadAsync
- Refactored HighlightObjects method in NavisworksBasicConnectorBinding to run on the main thread using Parent.RunOnMainThreadAsync
- Refactored OnSelectionChange method in NavisworksSelectionBinding to use async/await and run UpdateSelectionAsync on the main thread using Parent.RunOnMainThreadAsync
- Added async/await to Send method in NavisworksSendBinding and refactored code inside it to use async/await for better readability
- Extracted common logic into separate methods in NavisworksSendBinding: GetModelCard, InitializeConverterSettings, GetNavisworksModelItems, ExecuteSendOperation
- Added cancellation support to CancelSend method in NavisworksSendBinding by calling _cancellationManager.CancelOperation with modelCardId as argument
- Refactored ProcessModelStateChange method in NavisworksDocumentEvents to use async/await and added check for _finalModelCount value

* Restore DocumentModelStore.cs accessibility - not sure when that changed

- Change access modifiers of HostAppSaveState and LoadState methods to protected
- Update method comments to reflect changes in access modifiers

* Refactor NavisworksConnectorServiceRegistration and NavisworksDocumentEvents

- Added NavisworksMaterialUnpacker to service collection
- Updated registration of DocumentModelStore in service collection
- Updated references to DocumentModelStore with NavisworksDocumentModelStore in NavisworksDocumentEvents
- Renamed HostAppSaveState method to protected override method in NavisworksDocumentModelStore
- Added public method ReloadState as a wrapper for LoadState in NavisworksDocumentModelStore

* Delete Navisworks solution file

The commit deletes the Navisworks solution file, which is no longer needed.

* Delete  packages.lock.json

* Remove Navisworks 2025

* Reset Navisworks project references and project names

- Updated the project reference for "Navisworks" in Local.sln to use a new GUID
- Updated the project reference for "2024" in Local.sln to use a new GUID
- Updated the project reference for "Shared" in Local.sln to use a new GUID
- Updated the project reference for "Speckle.Connectors.NavisworksShared" in Local.sln to use a new GUID
- Updated the project reference for "Speckle.Converters.NavisworksShared" in Local.sln to use a new GUID
- Updated the project name and GUID for "Navisworks" in Speckle.Connectors.sln
- Updated the project name and GUID for "Shared" in Speckle.Connectors.sln

* Update Microsoft.Web.WebView2 package to version 1.0.2088.41 in Autocad connectors for versions 2022, 2023, 2024, and 2025.

This commit updates the Microsoft.Web.WebView2 package in the Autocad connectors for versions 2022, 2023, 2024, and 2025 from version 1.0.1938.49 to version 1.0.2088.41. This change ensures compatibility with the latest version of the package and includes necessary bug fixes or improvements related to web view functionality in the connectors.

* Reset Navisworks project references and project names

- Updated the project reference for "Navisworks" in Local.sln to use a new GUID
- Updated the project reference for "2024" in Local.sln to use a new GUID
- Updated the project reference for "Shared" in Local.sln to use a new GUID
- Updated the project reference for "Speckle.Connectors.NavisworksShared" in Local.sln to use a new GUID
- Updated the project reference for "Speckle.Converters.NavisworksShared" in Local.sln to use a new GUID
- Updated the project name and GUID for "Navisworks" in Speckle.Connectors.sln
- Updated the project name and GUID for "Shared" in Speckle.Connectors.sln

* Update Microsoft.Web.WebView2 version to [1.0.1938.49, ) in Autocad and Civil3d connectors

This commit updates the version of Microsoft.Web.WebView2 to [1.0.1938.49, ) in the Autocad and Civil3d connectors packages.lock.json files. The previous version was 1.0.2088.41, and the contentHash has also been updated accordingly.

Note: This commit message is exactly 50 characters long, as per the requirement for a short description less than 50 characters.

* Refactor to avoid the early disposal of COM objects

- Remove the `GeometryNodeMerger` class from service registration in `NavisworksConnectorServiceRegistration.cs`
- Change the access modifier of `UnpackRenderMaterial` method in `NavisworksMaterialUnpacker.cs` to internal
- Change the access modifier of `ConvertRenderColorAndTransparencyToSpeckle` method in `NavisworksMaterialUnpacker.cs` to private static
- Change the access modifier of `GroupSiblingGeometryNodes` method in `GeometryNodeMerger.cs` to public static
- Add null checks for parameters in methods:
  - GetClassProperties in ClassPropertiesExtractor.cs
  - GetPropertySets and AssignProperties in BasePropertyHandler.cs
  - AssignClassProperties and ExtractClassProperties in ClassPropertiesExtractor.cs
  - GetPropertySets in PropertySetsExtractor.cs
  - AssignPropertySets, AssignModelProperties, and ExtractModelProperties in ModelPropertiesExtractor.cs
  - NavisworksRootObjectBuilder constructor

* feat: Add geometry conversion functionality

- Added `DisplayValueExtractor` class for extracting display values from Navisworks model items
- Added `GeometryToSpeckleConverter` class for converting Navisworks geometry to Speckle SDK models
- Updated dependencies in `NavisworksConverterServiceRegistration.cs` to include the new classes

* Rename GeomtryNodeMerger.cs to GeometryNodeMerger.cs

This commit renames the file GeomtryNodeMerger.cs to GeometryNodeMerger.cs.

* Remove redundant code shared by both projects

- Updated NavisworksSelectionBinding to include IElementSelectionService as a dependency in the constructor.
- Updated NavisworksSendBinding to include IElementSelectionService as a dependency in the constructor.
- Removed ElementSelectionExtension.cs file.
- Added ElementSelectionService.cs file which includes methods for getting model item path, resolving model item from path, checking visibility of model items, and getting geometry nodes.

* fix lock files

* cannot make null valuetasks

* merge fixes

* update to latest SDK

* scope the classes correctly for the deserialization process

* Navisworks proj cleanup (#443)

* Clean up projects and locks for all Navisworks

* Fix nuget error

* Fixed Local SLN and removed some runtime IDs

* add back RuntimeIdentifier

* We shouldn't be using ConfigureAwait false

* Fix lock files for NW

* Rhino doesn't need explicit run on main threads?

* add back layers and materials on ui thread with comment

* Update to SDK 3.1.0-218

* update locks

* rationalize NW and usage of cancellation token

* format

* remove .ConfigureAwait(false)

* Remove ValueTask and fix ArcGIS doc saving

* run events on the correct thread

* format

* Remove usage of sync context

---------

Co-authored-by: Jonathon Broughton <jonathon@stardotbmp.com>
Co-authored-by: oguzhankoral <oguzhankoral@gmail.com>
Co-authored-by: Jonathon Broughton <760691+jsdbroughton@users.noreply.github.com>
2024-12-20 17:12:18 +03:00
Dimitrie Stefanescu 42c3ca1ec3 wip: more cleanup and comments 2024-12-19 16:16:48 +00:00
Dimitrie Stefanescu 44105d7d75 wip: various cleanup 2024-12-19 16:04:19 +00:00
Dimitrie Stefanescu 2aad40bd0a wip: filter objects by path 2024-12-18 19:13:18 +00:00
Dimitrie Stefanescu d0058d7ee5 wip: centralises converter access in grasshopper
makes life... easier
2024-12-18 13:57:18 +00:00
Dimitrie Stefanescu 38c9077831 wip: conversions (wip!) 2024-12-18 13:18:44 +00:00
Dimitrie Stefanescu 904e7ece88 wip 2024-12-17 17:11:01 +00:00
Dimitrie Stefanescu 267799d916 wip 2024-12-16 13:15:57 +00:00
Dimitrie Stefanescu 2eb872b5e5 wip wip 2024-12-11 17:24:27 +00:00
Dimitrie Stefanescu ce9a2c8807 mega wips 2024-12-11 16:19:50 +00:00
Dimitrie Stefanescu 729d1a4698 feat: adds value type component, all is very raw and wip 2024-12-09 16:04:16 +00:00
Dimitrie Stefanescu 4f74328ffc wip 2024-12-07 15:34:49 +00:00
Dimitrie Stefanescu 54370f3188 wip 2024-12-07 14:27:48 +00:00
Dimitrie Stefanescu 4a51eae628 feat: total wip expand collection node 2024-12-06 14:52:23 +00:00
Dimitrie Stefanescu 34241385f9 feat: unpacking logic wip 2024-12-06 11:56:33 +00:00
Alan Rynne 7ec01ed39f feat: Working initial nodes
Receive, Collection, URL parsing for models, root object unpacking
2024-12-05 11:00:37 +01:00
Alan Rynne 1ff861f9db v3 Receive outputs most objects, very basic 2024-11-28 12:42:44 +01:00
Alan Rynne 4c125afd7b Working POC receive with working Rhino conversions 2024-11-28 11:35:27 +01:00
Alan Rynne e561980e7f feat: Boilerplate project for Grasshopper v3 2024-11-25 16:04:52 +01:00
793 changed files with 41577 additions and 10037 deletions
+3 -3
View File
@@ -9,10 +9,10 @@
],
"rollForward": false
},
"gitversion.tool": {
"version": "6.0.2",
"dotnet-affected": {
"version": "5.0.0",
"commands": [
"dotnet-gitversion"
"dotnet-affected"
],
"rollForward": false
}
+6
View File
@@ -254,6 +254,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
@@ -311,6 +314,9 @@ 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
+29 -26
View File
@@ -4,33 +4,36 @@
# * @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
ConnectorAutocadCivil/* @clairekuang
ConnectorArchicad/* @jozseflkiss
ConnectorCSI/* @connorivy
ConnectorDynamo/* @teocomi @alanrynne
ConnectorGrasshopper/* @alanrynne @clairekuang
ConnectorMicrostation/* @clairekuang
ConnectorRevit/* @teocomi @connorivy
ConnectorRhino/* @clairekuang @alanrynne
ConnectorTeklaStructures/* @connorivy
/Connectors/ArcGIS/* @KatKatKateryna
/Connectors/Autocad/* @clairekuang @oguzhankoral @didimitrie
/Connectors/Civil3d/* @clairekuang @oguzhankoral @didimitrie
/Connectors/CSi/* @bjoernsteinhagen @dogukankaratas
/Connectors/Navisworks/* @jsdbroughton
/Connectors/Revit/* @clairekuang @oguzhankoral @didimitrie
/Connectors/Rhino/* @clairekuang @oguzhankoral @didimitrie
/Connectors/Tekla/* @bjoernsteinhagen @dogukankaratas
# DesktopUI
# Converters
/Convertors/ArcGIS/* @KatKatKateryna
/Convertors/Autocad/* @clairekuang @oguzhankoral @didimitrie
/Convertors/Civil3d/* @clairekuang @oguzhankoral @didimitrie
/Convertors/CSi/* @bjoernsteinhagen @dogukankaratas
/Convertors/Navisworks/* @jsdbroughton
/Convertors/Revit/* @clairekuang @oguzhankoral @didimitrie
/Convertors/Rhino/* @clairekuang @oguzhankoral @didimitrie
/Convertors/Tekla/* @bjoernsteinhagen @dogukankaratas
DesktopUI2/* @teocomi @clairekuang
# DUI
/DUI3/* @clairekuang @oguzhankoral @didimitrie
# Importers
/Importers/* @JR-Morgan @didimitrie @oguzhankoral @adamhathcock
# SDK
/SDK/* @JR-Morgan @clairekuang @didimitrie @oguzhankoral @adamhathcock
# Build
/Build/* @JR-Morgan @oguzhankoral @adamhathcock
+29 -38
View File
@@ -1,30 +1,46 @@
<!---
Provide a short summary in the Title above. Examples of good PR titles:
Provide a short summary in the Title above. Use the following template:
* "Feature: adds metrics to component"
category(project): summary
* "Fix: resolves duplication in comment thread"
Categories:
* "Update: apollo v2.34.0"
* 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
-->
## Description & motivation
## Description
<!---
Describe your changes, and why you're making them. What benefit will this have to others?
Describe your changes, and why you're making them.
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
Link related github issues here ->
Fixes #85, Fixes #22, 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:
<!---
@@ -68,35 +84,10 @@ Describe what tests have been added or amended, and why these demonstrate it wor
<!---
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.
This checklist is a useful reminder of related tasks to uphold our repo quality. Amend this list as needed for the 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..
-->
@@ -1,15 +1,10 @@
name: .NET Build
on:
pull_request: # Run build on every pull request that is not to main
branches-ignore:
- main
on: pull_request
jobs:
jobs:
build:
runs-on: windows-latest
outputs:
version: ${{ steps.set-version.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -20,8 +15,8 @@ jobs:
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.4xx # Align with global.json (including roll forward rules)
- name: Cache Nuget
- name: Cache Nuget
uses: actions/cache@v4
with:
path: ~/.nuget/packages
@@ -34,23 +29,28 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.4xx # Align with global.json (including roll forward rules)
- name: Cache Nuget
- name: Cache Nuget
uses: actions/cache@v4
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
- name: ⚒️ Run build
- name: ⚒️ Run Build on Linux
run: ./build.sh build-linux
- name: ⚒️ Run tests
run: ./build.sh test-only
- name: Upload coverage reports to Codecov with GitHub Action
uses: codecov/codecov-action@v5
with:
file: Converters/**/coverage.xml
files: Converters/**/coverage.xml
token: ${{ secrets.CODECOV_TOKEN }}
@@ -2,14 +2,18 @@ name: .NET Build and Publish
on:
push:
branches: ["main", "dev", "release/*"] # Continuous delivery on every long-lived branch
tags: ["v3.*"] # Manual delivery on every 3.x tag
branches: ["main", "installer-test/**"]
tags: ["v3.*.*"] # Manual delivery on every 3.x tag
jobs:
build:
build-windows:
runs-on: windows-latest
env:
SEMVER: "unset"
FILE_VERSION: "unset"
outputs:
version: ${{ steps.set-version.outputs.version }}
semver: ${{ steps.set-version.outputs.semver }}
file_version: ${{ steps.set-version.outputs.file_version }}
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -27,38 +31,43 @@ jobs:
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: ⚒️ Run build on Windows
run: ./build.ps1 zip
- name: ⬆️ Upload artifacts
uses: actions/upload-artifact@v4
with:
name: output-${{ env.GitVersion_FullSemVer }}
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 "version=${{ env.GitVersion_FullSemVer }}" >> "$Env:GITHUB_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
needs: build-windows
env:
IS_TAG_BUILD: ${{ github.ref_type == 'tag' }}
IS_RELEASE_BRANCH: ${{ startsWith(github.ref_name, 'release/') || github.ref_name == 'main'}}
IS_PUBLIC_RELEASE: ${{ github.ref_type == 'tag' }}
steps:
- name: 🔫 Trigger Build Installers
uses: ALEEF02/workflow-dispatch@v3.0.0
continue-on-error: true
uses: the-actions-org/workflow-dispatch@v4.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 }}, "store_artifacts": ${{ env.IS_RELEASE_BRANCH }} }'
inputs: '{
"run_id": "${{ github.run_id }}",
"semver": "${{ needs.build-windows.outputs.semver }}",
"file_version": "${{ needs.build-windows.outputs.file_version }}",
"repo": "${{ github.repository }}",
"is_public_release": ${{ env.IS_PUBLIC_RELEASE }}
}'
ref: main
wait-for-completion: true
wait-for-completion-interval: 10s
@@ -70,11 +79,13 @@ jobs:
with:
name: output-*
test:
build-linux:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup .NET
uses: actions/setup-dotnet@v4
@@ -87,11 +98,18 @@ jobs:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
- name: ⚒️ Run build
- name: ⚒️ Run tests on Linux
run: ./build.sh test-only
- name: ⚒️ Run Build and Pack on Linux
run: ./build.sh build-linux
- name: Upload coverage reports to Codecov with GitHub Action
uses: codecov/codecov-action@v5
with:
file: Converters/**/coverage.xml
files: Converters/**/coverage.xml
token: ${{ secrets.CODECOV_TOKEN }}
- name: Push to nuget.org
if: (github.ref_type == 'tag')
run: dotnet nuget push output/*.nupkg --source "https://api.nuget.org/v3/index.json" --api-key ${{secrets.CONNECTORS_NUGET_TOKEN }} --skip-duplicate
+116
View File
@@ -0,0 +1,116 @@
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;
}
}
+2
View File
@@ -10,6 +10,8 @@
<PackageReference Include="Bullseye" />
<PackageReference Include="Glob" />
<PackageReference Include="Microsoft.Build" />
<PackageReference Include="Microsoft.VisualStudio.SolutionPersistence" />
<PackageReference Include="Semver" />
<PackageReference Include="SimpleExec" />
</ItemGroup>
</Project>
+19 -8
View File
@@ -4,14 +4,14 @@ public static class Consts
{
public static readonly string[] Solutions = ["Speckle.Connectors.sln"];
public static readonly InstallerProject[] InstallerManifests =
public static readonly ProjectGroup[] ProjectGroups =
{
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(
@@ -20,7 +20,8 @@ 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.Revit2025", "net8.0-windows"),
new("Connectors/Revit/Speckle.Connectors.Revit2026", "net8.0-windows")
]
),
new(
@@ -29,7 +30,8 @@ public static class Consts
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.Autocad2025", "net8.0-windows"),
new("Connectors/Autocad/Speckle.Connectors.Autocad2026", "net8.0-windows")
]
),
new(
@@ -38,7 +40,8 @@ public static class Consts
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.Civil3d2025", "net8.0-windows"),
new("Connectors/Autocad/Speckle.Connectors.Civil3d2026", "net8.0-windows")
]
),
new(
@@ -49,20 +52,28 @@ public static class Consts
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.Navisworks2025", "net48"),
new("Connectors/Navisworks/Speckle.Connectors.Navisworks2026", "net48")
]
),
new(
"tekla-structures",
"teklastructures",
[
new("Connectors/Tekla/Speckle.Connector.Tekla2023", "net48"),
new("Connectors/Tekla/Speckle.Connector.Tekla2024", "net48")
]
),
new(
"etabs",
[
new("Connectors/CSi/Speckle.Connectors.ETABS21", "net48"),
new("Connectors/CSi/Speckle.Connectors.ETABS22", "net8.0-windows"),
]
)
};
}
public readonly record struct InstallerProject(string HostAppSlug, IReadOnlyList<InstallerAsset> Projects)
public readonly record struct ProjectGroup(string HostAppSlug, IReadOnlyList<InstallerAsset> Projects)
{
public override string ToString() => $"{HostAppSlug}";
}
+2 -2
View File
@@ -28,11 +28,11 @@ public static class Github
Content = content
};
request.Headers.Add("X-GitHub-Api-Version", "2022-11-28");
var response = await client.SendAsync(request).ConfigureAwait(false);
var response = await client.SendAsync(request);
if (!response.IsSuccessStatusCode)
{
throw new InvalidOperationException(
$"{response.StatusCode} {response.ReasonPhrase} {await response.Content.ReadAsStringAsync().ConfigureAwait(false)}"
$"{response.StatusCode} {response.ReasonPhrase} {await response.Content.ReadAsStringAsync()}"
);
}
}
+151 -96
View File
@@ -7,16 +7,18 @@ using static SimpleExec.Command;
const string CLEAN = "clean";
const string RESTORE = "restore";
const string BUILD = "build";
const string BUILD_LINUX = "build-linux";
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";
//need to pass arguments
/*var arguments = new List<string>();
@@ -27,44 +29,67 @@ 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 =>
{
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");
DeleteFiles("**/*.lock.json");
Restore(s);
}
);
Target(
DEEP_CLEAN,
Consts.Solutions,
s =>
{
CleanSolution(s, "debug");
}
);
Target(
DEEP_CLEAN_LOCAL,
() =>
{
foreach (var f in Glob.Directories(".", "**/bin"))
{
if (f.StartsWith("Build"))
{
continue;
}
Console.WriteLine("Found and will delete: " + f);
Directory.Delete(f, true);
}
foreach (var f in Glob.Directories(".", "**/obj"))
{
if (f.StartsWith("Build"))
{
continue;
}
Console.WriteLine("Found and will delete: " + f);
Directory.Delete(f, true);
}
Console.WriteLine("Running restore now.");
Run("dotnet", "restore .\\Speckle.Connectors.sln --no-cache");
CleanSolution("Local.sln", "Local");
}
);
@@ -94,17 +119,6 @@ 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,
() =>
@@ -113,6 +127,18 @@ 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),
@@ -124,20 +150,14 @@ Target(
Target(
RESTORE,
DependsOn(FORMAT),
DependsOn(FORMAT, DETECT_AFFECTED),
Consts.Solutions,
s =>
async s =>
{
Run("dotnet", $"restore {s} --locked-mode");
}
);
Target(
BUILD_SERVER_VERSION,
DependsOn(RESTORE_TOOLS),
() =>
{
Run("dotnet", "tool run dotnet-gitversion /output json /output buildserver");
var version = await Versions.ComputeVersion();
var fileVersion = await Versions.ComputeFileVersion();
Console.WriteLine($"Restoring: {s} - Version: {version} & {fileVersion}");
await RunAsync("dotnet", $"restore \"{s}\" --locked-mode");
}
);
@@ -145,40 +165,66 @@ Target(
BUILD,
DependsOn(RESTORE),
Consts.Solutions,
s =>
async s =>
{
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(
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"
$"build \"{s}\" -c Release --no-restore -warnaserror -p:Version={version} -p:FileVersion={fileVersion} -v:m"
);
}
);
Target(CHECK_SOLUTIONS, Solutions.CompareConnectorsToLocal);
Target(GEN_SOLUTIONS, Solutions.GenerateSolutions);
Target(
TEST,
DependsOn(BUILD, CHECK_SOLUTIONS),
Glob.Files(".", "**/*.Tests.csproj"),
file =>
async () =>
{
Run("dotnet", $"test {file} -c Release --no-build --no-restore --verbosity=minimal");
foreach (var s in await Affected.GetTestProjects())
{
await RunAsync("dotnet", $"test \"{s}\" -c Release --no-build --no-restore --verbosity=minimal");
}
}
);
//all tests on purpose
Target(
TEST_ONLY,
DependsOn(FORMAT),
Glob.Files(".", "**/*.Tests.csproj"),
file =>
{
Run("dotnet", $"restore {file} --locked-mode");
Run("dotnet", $"build \"{file}\" -c Release --no-incremental");
Run(
"dotnet",
$"test {file} -c Release --no-restore --verbosity=minimal /p:AltCover=true /p:AltCoverAttributeFilter=ExcludeFromCodeCoverage /p:AltCoverVerbosity=Warning"
$"test \"{file}\" -c Release --no-build --verbosity=minimal /p:AltCover=true /p:AltCoverAttributeFilter=ExcludeFromCodeCoverage /p:AltCoverVerbosity=Warning"
);
}
);
Target(
BUILD_LINUX,
DependsOn(FORMAT),
Glob.Files(".", "**/Speckle.Importers.Ifc.csproj"),
async file =>
{
await RunAsync("dotnet", $"restore \"{file}\" --locked-mode");
var version = await Versions.ComputeVersion();
var fileVersion = await Versions.ComputeFileVersion();
Console.WriteLine($"Version: {version} & {fileVersion}");
await RunAsync(
"dotnet",
$"build \"{file}\" -c Release --no-restore -warnaserror -p:Version={version} -p:FileVersion={fileVersion} -v:m"
);
await RunAsync(
"dotnet",
$"pack \"{file}\" -c Release -o output --no-build -p:Version={version} -p:FileVersion={fileVersion} -v:m"
);
}
);
@@ -186,47 +232,56 @@ Target(
Target(
ZIP,
DependsOn(TEST),
Consts.InstallerManifests,
x =>
async () =>
{
var outputDir = Path.Combine(".", "output");
var slugDir = Path.Combine(outputDir, x.HostAppSlug);
Directory.CreateDirectory(outputDir);
Directory.CreateDirectory(slugDir);
foreach (var asset in x.Projects)
var version = await Versions.ComputeVersion();
var fileVersion = await Versions.ComputeFileVersion();
foreach (var group in await Affected.GetAffectedProjectGroups())
{
var fullPath = Path.Combine(".", asset.ProjectPath, "bin", "Release", asset.TargetName);
if (!Directory.Exists(fullPath))
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)
{
throw new InvalidOperationException("Could not find: " + 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);
}
}
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);
}
var outputPath = Path.Combine(outputDir, $"{group.HostAppSlug}.zip");
File.Delete(outputPath);
Console.WriteLine($"Zipping: '{slugDir}' to '{outputPath}'");
ZipFile.CreateFromDirectory(slugDir, outputPath);
}
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);
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}");
}
);
Target("default", DependsOn(FORMAT, ZIP), () => Console.WriteLine("Done!"));
Target("default", DependsOn(TEST), () => Console.WriteLine("Done!"));
await RunTargetsAndExitAsync(args).ConfigureAwait(true);
+51
View File
@@ -1,4 +1,6 @@
using Microsoft.Build.Construction;
using Microsoft.VisualStudio.SolutionPersistence.Model;
using Microsoft.VisualStudio.SolutionPersistence.Serializer;
namespace Build;
@@ -53,4 +55,53 @@ public static class Solutions
);
}
}
public static async Task GenerateSolutions()
{
await GenerateLocalSlnx();
foreach (var group in Consts.ProjectGroups)
{
var path = group.Projects[0].ProjectPath.Split('/');
var folder = $"/{path[0]}/{path[1]}/";
await GenerateConnector(group.HostAppSlug, folder);
}
}
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("C:\\Users\\adam\\Git\\speckle-sharp-connectors", "Local.slnx");
await SolutionSerializers.SlnXml.SaveAsync(sln, connectors, default);
sln = Path.Combine("C:\\Users\\adam\\Git\\speckle-sharp-connectors", "Local.sln");
await SolutionSerializers.SlnFileV12.SaveAsync(sln, connectors, default);
}
public static async Task GenerateConnector(string slug, string folder)
{
slug = string.Concat(slug[0].ToString().ToUpper(), slug.AsSpan(1));
var connectors = await GetFullSlnx();
var foldersToRemove = connectors
.SolutionFolders.Where(x =>
//need base folder
!x.Path.Equals("/Connectors/")
//don't grab all
&& (x.Path.StartsWith("/Connectors/") && !x.Path.StartsWith(folder))
)
.ToList();
foreach (var folderToRemove in foldersToRemove)
{
connectors.RemoveFolder(folderToRemove);
}
var sln = Path.Combine("C:\\Users\\adam\\Git\\speckle-sharp-connectors", $"Speckle.{slug}.slnx");
await SolutionSerializers.SlnXml.SaveAsync(sln, connectors, default);
}
public static async Task<SolutionModel> GetFullSlnx()
{
var connectorsSln = Path.Combine("C:\\Users\\adam\\Git\\speckle-sharp-connectors", "Speckle.Connectors.slnx");
return await SolutionSerializers.SlnXml.OpenAsync(connectorsSln, default);
}
}
+79
View File
@@ -0,0 +1,79 @@
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;
}
}
+20
View File
@@ -47,12 +47,27 @@
"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, )",
@@ -75,6 +90,11 @@
"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.4",
@@ -19,7 +19,7 @@ namespace Speckle.Connectors.ArcGIS.Bindings;
public sealed class ArcGISReceiveBinding : IReceiveBinding
{
public string Name { get; } = "receiveBinding";
private readonly CancellationManager _cancellationManager;
private readonly ICancellationManager _cancellationManager;
private readonly DocumentModelStore _store;
private readonly IServiceProvider _serviceProvider;
private readonly IOperationProgressManager _operationProgressManager;
@@ -32,7 +32,7 @@ public sealed class ArcGISReceiveBinding : IReceiveBinding
public ArcGISReceiveBinding(
DocumentModelStore store,
IBrowserBridge parent,
CancellationManager cancellationManager,
ICancellationManager cancellationManager,
IServiceProvider serviceProvider,
IOperationProgressManager operationProgressManager,
ILogger<ArcGISReceiveBinding> logger,
@@ -60,7 +60,7 @@ public sealed class ArcGISReceiveBinding : IReceiveBinding
throw new InvalidOperationException("No download model card was found.");
}
CancellationToken cancellationToken = _cancellationManager.InitCancellationTokenSource(modelCardId);
using var cancellationItem = _cancellationManager.GetCancellationItem(modelCardId);
using var scope = _serviceProvider.CreateScope();
scope
.ServiceProvider.GetRequiredService<IConverterSettingsStore<ArcGISConversionSettings>>()
@@ -76,19 +76,16 @@ public sealed class ArcGISReceiveBinding : IReceiveBinding
.ServiceProvider.GetRequiredService<ReceiveOperation>()
.Execute(
modelCard.GetReceiveInfo("ArcGIS"), // POC: get host app name from settings? same for GetSendInfo
_operationProgressManager.CreateOperationProgressEventHandler(Parent, modelCardId, cancellationToken),
cancellationToken
)
.ConfigureAwait(false);
_operationProgressManager.CreateOperationProgressEventHandler(Parent, modelCardId, cancellationItem.Token),
cancellationItem.Token
);
modelCard.BakedObjectIds = receiveOperationResults.BakedObjectIds.ToList();
await Commands
.SetModelReceiveResult(
modelCardId,
receiveOperationResults.BakedObjectIds,
receiveOperationResults.ConversionResults
)
.ConfigureAwait(false);
await Commands.SetModelReceiveResult(
modelCardId,
receiveOperationResults.BakedObjectIds,
receiveOperationResults.ConversionResults
);
}
catch (OperationCanceledException)
{
@@ -100,7 +97,7 @@ public sealed class ArcGISReceiveBinding : IReceiveBinding
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);
await Commands.SetModelError(modelCardId, ex).ConfigureAwait(false);
await Commands.SetModelError(modelCardId, ex);
}
}
@@ -12,15 +12,18 @@ public class ArcGISSelectionBinding : ISelectionBinding
public string Name => "selectionBinding";
public IBrowserBridge Parent { get; }
public ArcGISSelectionBinding(IBrowserBridge parent, MapMembersUtils mapMemberUtils)
public ArcGISSelectionBinding(
IBrowserBridge parent,
MapMembersUtils mapMemberUtils,
ITopLevelExceptionHandler topLevelExceptionHandler
)
{
_mapMemberUtils = mapMemberUtils;
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);
TOCSelectionChangedEvent.Subscribe(_ => topLevelExceptionHandler.CatchUnhandled(OnSelectionChanged), true);
}
private void OnSelectionChanged()
@@ -13,6 +13,7 @@ using Speckle.Connectors.ArcGIS.Utils;
using Speckle.Connectors.Common.Caching;
using Speckle.Connectors.Common.Cancellation;
using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Exceptions;
@@ -38,12 +39,14 @@ public sealed class ArcGISSendBinding : ISendBinding
private readonly DocumentModelStore _store;
private readonly IServiceProvider _serviceProvider;
private readonly List<ISendFilter> _sendFilters;
private readonly CancellationManager _cancellationManager;
private readonly ICancellationManager _cancellationManager;
private readonly ISendConversionCache _sendConversionCache;
private readonly IOperationProgressManager _operationProgressManager;
private readonly ILogger<ArcGISSendBinding> _logger;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
private readonly IArcGISConversionSettingsFactory _arcGISConversionSettingsFactory;
private readonly IThreadContext _threadContext;
private readonly ISpeckleApplication _speckleApplication;
/// <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:
@@ -62,12 +65,15 @@ public sealed class ArcGISSendBinding : ISendBinding
IBrowserBridge parent,
IEnumerable<ISendFilter> sendFilters,
IServiceProvider serviceProvider,
CancellationManager cancellationManager,
ICancellationManager cancellationManager,
ISendConversionCache sendConversionCache,
IOperationProgressManager operationProgressManager,
ILogger<ArcGISSendBinding> logger,
IArcGISConversionSettingsFactory arcGisConversionSettingsFactory,
MapMembersUtils mapMemberUtils
MapMembersUtils mapMemberUtils,
IThreadContext threadContext,
ISpeckleApplication speckleApplication,
ITopLevelExceptionHandler topLevelExceptionHandler
)
{
_store = store;
@@ -77,9 +83,11 @@ public sealed class ArcGISSendBinding : ISendBinding
_sendConversionCache = sendConversionCache;
_operationProgressManager = operationProgressManager;
_logger = logger;
_topLevelExceptionHandler = parent.TopLevelExceptionHandler;
_topLevelExceptionHandler = topLevelExceptionHandler;
_arcGISConversionSettingsFactory = arcGisConversionSettingsFactory;
_mapMemberUtils = mapMemberUtils;
_threadContext = threadContext;
_speckleApplication = speckleApplication;
Parent = parent;
Commands = new SendBindingUICommands(parent);
@@ -90,18 +98,22 @@ public sealed class ArcGISSendBinding : ISendBinding
};
}
private void OnDocumentStoreChangedEvent(object _) => _sendConversionCache.ClearCache();
private void SubscribeToArcGISEvents()
{
LayersRemovedEvent.Subscribe(
a =>
_topLevelExceptionHandler.FireAndForget(async () => await GetIdsForLayersRemovedEvent(a).ConfigureAwait(false)),
_topLevelExceptionHandler.FireAndForget(
async () => await QueuedTask.Run(async () => await GetIdsForLayersRemovedEvent(a))
),
true
);
StandaloneTablesRemovedEvent.Subscribe(
a =>
_topLevelExceptionHandler.FireAndForget(
async () => await GetIdsForStandaloneTablesRemovedEvent(a).ConfigureAwait(false)
async () => await QueuedTask.Run(async () => await GetIdsForStandaloneTablesRemovedEvent(a))
),
true
);
@@ -109,7 +121,7 @@ public sealed class ArcGISSendBinding : ISendBinding
MapPropertyChangedEvent.Subscribe(
a =>
_topLevelExceptionHandler.FireAndForget(
async () => await GetIdsForMapPropertyChangedEvent(a).ConfigureAwait(false)
async () => await QueuedTask.Run(async () => await GetIdsForMapPropertyChangedEvent(a))
),
true
); // Map units, CRS etc.
@@ -117,13 +129,17 @@ public sealed class ArcGISSendBinding : ISendBinding
MapMemberPropertiesChangedEvent.Subscribe(
a =>
_topLevelExceptionHandler.FireAndForget(
async () => await GetIdsForMapMemberPropertiesChangedEvent(a).ConfigureAwait(false)
async () => await QueuedTask.Run(async () => await GetIdsForMapMemberPropertiesChangedEvent(a))
),
true
); // e.g. Layer name
ActiveMapViewChangedEvent.Subscribe(
_ => _topLevelExceptionHandler.CatchUnhandled(SubscribeToMapMembersDataSourceChange),
_ =>
_topLevelExceptionHandler.FireAndForget(async () =>
{
await QueuedTask.Run(SubscribeToMapMembersDataSourceChange);
}),
true
);
@@ -139,28 +155,24 @@ public sealed class ArcGISSendBinding : ISendBinding
private void SubscribeToMapMembersDataSourceChange()
{
var task = QueuedTask.Run(() =>
if (MapView.Active == null)
{
if (MapView.Active == null)
{
return;
}
return;
}
// subscribe to layers
foreach (Layer layer in MapView.Active.Map.Layers)
// subscribe to layers
foreach (Layer layer in MapView.Active.Map.Layers)
{
if (layer is FeatureLayer featureLayer)
{
if (layer is FeatureLayer featureLayer)
{
SubscribeToFeatureLayerDataSourceChange(featureLayer);
}
SubscribeToFeatureLayerDataSourceChange(featureLayer);
}
// subscribe to tables
foreach (StandaloneTable table in MapView.Active.Map.StandaloneTables)
{
SubscribeToTableDataSourceChange(table);
}
});
task.Wait();
}
// subscribe to tables
foreach (StandaloneTable table in MapView.Active.Map.StandaloneTables)
{
SubscribeToTableDataSourceChange(table);
}
}
private void SubscribeToFeatureLayerDataSourceChange(FeatureLayer layer)
@@ -195,25 +207,25 @@ public sealed class ArcGISSendBinding : ISendBinding
{
RowCreatedEvent.Subscribe(
(args) =>
Parent.TopLevelExceptionHandler.FireAndForget(async () =>
_topLevelExceptionHandler.FireAndForget(async () =>
{
await OnRowChanged(args).ConfigureAwait(false);
await OnRowChanged(args);
}),
layerTable
);
RowChangedEvent.Subscribe(
(args) =>
Parent.TopLevelExceptionHandler.FireAndForget(async () =>
_topLevelExceptionHandler.FireAndForget(async () =>
{
await OnRowChanged(args).ConfigureAwait(false);
await OnRowChanged(args);
}),
layerTable
);
RowDeletedEvent.Subscribe(
(args) =>
Parent.TopLevelExceptionHandler.FireAndForget(async () =>
_topLevelExceptionHandler.FireAndForget(async () =>
{
await OnRowChanged(args).ConfigureAwait(false);
await OnRowChanged(args);
}),
layerTable
);
@@ -258,7 +270,7 @@ public sealed class ArcGISSendBinding : ISendBinding
}
}
await RunExpirationChecks(false).ConfigureAwait(false);
await RunExpirationChecks(false);
}
private async Task GetIdsForLayersRemovedEvent(LayerEventsArgs args)
@@ -267,7 +279,7 @@ public sealed class ArcGISSendBinding : ISendBinding
{
ChangedObjectIds[layer.URI] = 1;
}
await RunExpirationChecks(true).ConfigureAwait(false);
await RunExpirationChecks(true);
}
private async Task GetIdsForStandaloneTablesRemovedEvent(StandaloneTableEventArgs args)
@@ -276,7 +288,7 @@ public sealed class ArcGISSendBinding : ISendBinding
{
ChangedObjectIds[table.URI] = 1;
}
await RunExpirationChecks(true).ConfigureAwait(false);
await RunExpirationChecks(true);
}
private async Task GetIdsForMapPropertyChangedEvent(MapPropertyChangedEventArgs args)
@@ -289,7 +301,7 @@ public sealed class ArcGISSendBinding : ISendBinding
ChangedObjectIds[member.URI] = 1;
}
}
await RunExpirationChecks(false).ConfigureAwait(false);
await RunExpirationChecks(false);
}
private void GetIdsForLayersAddedEvent(LayerEventsArgs args)
@@ -339,7 +351,7 @@ public sealed class ArcGISSendBinding : ISendBinding
{
ChangedObjectIds[member.URI] = 1;
}
await RunExpirationChecks(false).ConfigureAwait(false);
await RunExpirationChecks(false);
}
}
@@ -364,66 +376,61 @@ public sealed class ArcGISSendBinding : ISendBinding
throw new InvalidOperationException("No publish model card was found.");
}
CancellationToken cancellationToken = _cancellationManager.InitCancellationTokenSource(modelCardId);
using var cancellationItem = _cancellationManager.GetCancellationItem(modelCardId);
var sendResult = await QueuedTask
.Run(async () =>
{
using var scope = _serviceProvider.CreateScope();
scope
.ServiceProvider.GetRequiredService<IConverterSettingsStore<ArcGISConversionSettings>>()
.Initialize(
_arcGISConversionSettingsFactory.Create(
Project.Current,
MapView.Active.Map,
new CRSoffsetRotation(MapView.Active.Map)
)
);
List<MapMember> mapMembers = modelCard
.SendFilter.NotNull()
.RefreshObjectIds()
.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 scope
.ServiceProvider.GetRequiredService<SendOperation<MapMember>>()
.Execute(
mapMembers,
modelCard.GetSendInfo("ArcGIS"), // POC: get host app name from settings? same for GetReceiveInfo
_operationProgressManager.CreateOperationProgressEventHandler(Parent, modelCardId, cancellationToken),
cancellationToken
using var scope = _serviceProvider.CreateScope();
List<MapMember> mapMembers = await QueuedTask.Run(() =>
{
scope
.ServiceProvider.GetRequiredService<IConverterSettingsStore<ArcGISConversionSettings>>()
.Initialize(
_arcGISConversionSettingsFactory.Create(
Project.Current,
MapView.Active.Map,
new CRSoffsetRotation(MapView.Active.Map)
)
.ConfigureAwait(false);
);
return result;
})
.ConfigureAwait(false);
return modelCard
.SendFilter.NotNull()
.RefreshObjectIds()
.Select(id => (MapMember)MapView.Active.Map.FindLayer(id) ?? MapView.Active.Map.FindStandaloneTable(id))
.Where(obj => obj != null)
.ToList();
});
await Commands
.SetModelSendResult(modelCardId, sendResult.RootObjId, sendResult.ConversionResults)
.ConfigureAwait(false);
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!");
}
await QueuedTask.Run(() =>
{
// 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 sendResult = await scope
.ServiceProvider.GetRequiredService<SendOperation<MapMember>>()
.Execute(
mapMembers,
modelCard.GetSendInfo(_speckleApplication.ApplicationAndVersion),
_operationProgressManager.CreateOperationProgressEventHandler(Parent, modelCardId, cancellationItem.Token),
cancellationItem.Token
);
await Commands.SetModelSendResult(modelCardId, sendResult.RootObjId, sendResult.ConversionResults);
}
catch (OperationCanceledException)
{
@@ -435,7 +442,7 @@ public sealed class ArcGISSendBinding : ISendBinding
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);
await Commands.SetModelError(modelCardId, ex).ConfigureAwait(false);
await Commands.SetModelError(modelCardId, ex);
}
}
@@ -470,7 +477,7 @@ public sealed class ArcGISSendBinding : ISendBinding
}
}
await Commands.SetModelsExpired(expiredSenderIds).ConfigureAwait(false);
await Commands.SetModelsExpired(expiredSenderIds);
ChangedObjectIds = new();
}
}
@@ -21,18 +21,25 @@ public class BasicConnectorBinding : IBasicConnectorBinding
public BasicConnectorBindingCommands Commands { get; }
private readonly DocumentModelStore _store;
private readonly ISpeckleApplication _speckleApplication;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
public BasicConnectorBinding(DocumentModelStore store, IBrowserBridge parent, ISpeckleApplication speckleApplication)
public BasicConnectorBinding(
DocumentModelStore store,
IBrowserBridge parent,
ISpeckleApplication speckleApplication,
ITopLevelExceptionHandler topLevelExceptionHandler
)
{
_store = store;
_speckleApplication = speckleApplication;
_topLevelExceptionHandler = topLevelExceptionHandler;
Parent = parent;
Commands = new BasicConnectorBindingCommands(parent);
_store.DocumentChanged += (_, _) =>
parent.TopLevelExceptionHandler.FireAndForget(async () =>
_topLevelExceptionHandler.FireAndForget(async () =>
{
await Commands.NotifyDocumentChanged().ConfigureAwait(false);
await Commands.NotifyDocumentChanged();
});
}
@@ -60,8 +67,12 @@ public class BasicConnectorBinding : IBasicConnectorBinding
public void RemoveModel(ModelCard model) => _store.RemoveModel(model);
public async Task HighlightObjects(IReadOnlyList<string> objectIds) =>
await HighlightObjectsOnView(objectIds.Select(x => new ObjectID(x)).ToList()).ConfigureAwait(false);
public void RemoveModels(List<ModelCard> models) => _store.RemoveModels(models);
public async Task HighlightObjects(IReadOnlyList<string> objectIds)
{
await HighlightObjectsOnView(objectIds.Select(x => new ObjectID(x)).ToList());
}
public async Task HighlightModel(string modelCardId)
{
@@ -88,24 +99,22 @@ public class BasicConnectorBinding : IBasicConnectorBinding
{
return;
}
await HighlightObjectsOnView(objectIds).ConfigureAwait(false);
await HighlightObjectsOnView(objectIds);
}
private async Task HighlightObjectsOnView(IReadOnlyList<ObjectID> objectIds)
{
MapView mapView = MapView.Active;
await QueuedTask.Run(() =>
{
MapView mapView = MapView.Active;
await QueuedTask
.Run(async () =>
{
List<MapMemberFeature> mapMembersFeatures = GetMapMembers(objectIds, mapView);
ClearSelectionInTOC();
ClearSelection();
await SelectMapMembersInTOC(mapMembersFeatures).ConfigureAwait(false);
SelectMapMembersAndFeatures(mapMembersFeatures);
mapView.ZoomToSelected();
})
.ConfigureAwait(false);
List<MapMemberFeature> mapMembersFeatures = GetMapMembers(objectIds, mapView);
ClearSelectionInTOC();
ClearSelection();
SelectMapMembersInTOC(mapMembersFeatures);
SelectMapMembersAndFeatures(mapMembersFeatures);
mapView.ZoomToSelected();
});
}
private List<MapMemberFeature> GetMapMembers(IReadOnlyList<ObjectID> objectIds, MapView mapView)
@@ -171,7 +180,7 @@ public class BasicConnectorBinding : IBasicConnectorBinding
}
}
private async Task SelectMapMembersInTOC(IReadOnlyList<MapMemberFeature> mapMembersFeatures)
private void SelectMapMembersInTOC(IReadOnlyList<MapMemberFeature> mapMembersFeatures)
{
List<Layer> layers = new();
List<StandaloneTable> tables = new();
@@ -187,7 +196,7 @@ public class BasicConnectorBinding : IBasicConnectorBinding
}
else
{
await QueuedTask.Run(() => layer.SetExpanded(true)).ConfigureAwait(false);
layer.SetExpanded(true);
}
}
else if (member is StandaloneTable table)
@@ -20,7 +20,7 @@
<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>
<Description>Next Gen Speckle Connector (Beta) for ArcGIS</Description>
<Image>Images\AddinDesktop32.png</Image>
<Author>Speckle Systems</Author>
<Company>Speckle Systems</Company>
@@ -33,14 +33,14 @@
<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">
<tab id="Speckle_Tab1" caption="Speckle">
<group refID="Speckle_Group1"/>
</tab>-->
</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">
an empty group. change appearsOnAddinTab to "True" if control is to be in the addin tab-->
<group id="Speckle_Group1" caption="Speckle" appearsOnAddInTab="false" keytip="G1">
<!-- host controls within groups -->
<button refID="SpeckleDUI3_SpeckleDUI3OpenButton" size="large" />
</group>
@@ -59,7 +59,7 @@
</controls>
<dockPanes>
<dockPane id="SpeckleDUI3_SpeckleDUI3" caption="Speckle (Beta) for ArcGIS" className="SpeckleDUI3ViewModel" keytip="DockPane" initiallyVisible="true" dock="group" dockWith="esri_core_projectDockPane">
<dockPane id="SpeckleDUI3_SpeckleDUI3" caption="Speckle (Beta)" className="SpeckleDUI3ViewModel" keytip="DockPane" initiallyVisible="true" dock="group" dockWith="esri_core_projectDockPane">
<content className="SpeckleDUI3Wrapper" />
</dockPane>
</dockPanes>
@@ -10,6 +10,7 @@ using Speckle.Connectors.Common;
using Speckle.Connectors.Common.Builders;
using Speckle.Connectors.Common.Caching;
using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Models.Card.SendFilter;
@@ -26,8 +27,8 @@ public static class ArcGISConnectorModule
{
public static void AddArcGIS(this IServiceCollection serviceCollection)
{
serviceCollection.AddConnectorUtils();
serviceCollection.AddDUI<ArcGISDocumentStore>();
serviceCollection.AddConnectors();
serviceCollection.AddDUI<DefaultThreadContext, ArcGISDocumentStore>();
serviceCollection.AddDUIView();
// Register bindings
@@ -37,7 +38,6 @@ public static class ArcGISConnectorModule
serviceCollection.AddSingleton<IBinding>(sp => sp.GetRequiredService<IBasicConnectorBinding>());
serviceCollection.AddSingleton<IBasicConnectorBinding, BasicConnectorBinding>();
serviceCollection.RegisterTopLevelExceptionHandler();
serviceCollection.AddSingleton(DefaultTraversal.CreateTraversalFunc());
// register send operation and dependencies
@@ -25,7 +25,7 @@ public class ArcGISColorManager
/// </summary>
/// <param name="colorProxies"></param>
/// <param name="onOperationProgressed"></param>
public async Task ParseColors(List<ColorProxy> colorProxies, IProgress<CardProgress> onOperationProgressed)
public void ParseColors(List<ColorProxy> colorProxies, IProgress<CardProgress> onOperationProgressed)
{
// injected as Singleton, so we need to clean existing proxies first
ObjectColorsIdMap = new();
@@ -33,7 +33,6 @@ public class ArcGISColorManager
foreach (ColorProxy colorProxy in colorProxies)
{
onOperationProgressed.Report(new("Converting colors", (double)++count / colorProxies.Count));
await Task.Yield();
foreach (string objectId in colorProxy.objects)
{
Color convertedColor = Color.FromArgb(colorProxy.value);
@@ -47,10 +46,7 @@ public class ArcGISColorManager
/// </summary>
/// <param name="materialProxies"></param>
/// <param name="onOperationProgressed"></param>
public async Task ParseMaterials(
List<RenderMaterialProxy> materialProxies,
IProgress<CardProgress> onOperationProgressed
)
public void ParseMaterials(List<RenderMaterialProxy> materialProxies, IProgress<CardProgress> onOperationProgressed)
{
// injected as Singleton, so we need to clean existing proxies first
ObjectMaterialsIdMap = new();
@@ -58,7 +54,6 @@ public class ArcGISColorManager
foreach (RenderMaterialProxy colorProxy in materialProxies)
{
onOperationProgressed.Report(new("Converting materials", (double)++count / materialProxies.Count));
await Task.Yield();
foreach (string objectId in colorProxy.objects)
{
Color convertedColor = Color.FromArgb(colorProxy.value.diffuse);
@@ -184,6 +184,7 @@ public class ArcGISColorUnpacker
if (StoredColor is int existingColorProxyId)
{
AddObjectIdToColorProxyCache(rowApplicationId, existingColorProxyId);
return;
}
// get the color from the renderer and row
@@ -18,7 +18,7 @@ public class ArcGISLayerUnpacker
/// <param name="parentCollection"></param>
/// <returns>List of layers containing objects.</returns>
/// <exception cref="AC.CalledOnWrongThreadException">Thrown when this method is *not* called on the MCT, because this method accesses mapmember fields</exception>
public async Task<List<ADM.MapMember>> UnpackSelectionAsync(
public List<ADM.MapMember> UnpackSelection(
IEnumerable<ADM.MapMember> mapMembers,
Collection parentCollection,
List<ADM.MapMember>? objects = null
@@ -37,7 +37,7 @@ public class ArcGISLayerUnpacker
Collection containerCollection = CreateAndCacheMapMemberCollection(mapMember, true);
parentCollection.elements.Add(containerCollection);
await UnpackSelectionAsync(container.Layers, containerCollection, objects).ConfigureAwait(false);
UnpackSelection(container.Layers, containerCollection, objects);
break;
default:
@@ -54,7 +54,20 @@ public class ArcGISHostObjectBuilder : IHostObjectBuilder
_colorManager = colorManager;
}
public async Task<HostObjectBuilderResult> Build(
public Task<HostObjectBuilderResult> Build(
Base rootObject,
string projectName,
string modelName,
IProgress<CardProgress> onOperationProgressed,
CancellationToken cancellationToken
)
{
return QueuedTask.Run(
() => BuildInternal(rootObject, projectName, modelName, onOperationProgressed, cancellationToken)
);
}
private HostObjectBuilderResult BuildInternal(
Base rootObject,
string projectName,
string modelName,
@@ -74,14 +87,14 @@ public class ArcGISHostObjectBuilder : IHostObjectBuilder
.ToList();
if (materials != null)
{
await _colorManager.ParseMaterials(materials, onOperationProgressed).ConfigureAwait(false);
_colorManager.ParseMaterials(materials, onOperationProgressed);
}
// get colors
List<ColorProxy>? colors = (rootObject[ProxyKeys.COLOR] as List<object>)?.Cast<ColorProxy>().ToList();
if (colors != null)
{
await _colorManager.ParseColors(colors, onOperationProgressed).ConfigureAwait(false);
_colorManager.ParseColors(colors, onOperationProgressed);
}
int count = 0;
@@ -100,7 +113,7 @@ public class ArcGISHostObjectBuilder : IHostObjectBuilder
try
{
obj = _localToGlobalConverterUtils.TransformObjects(objectToConvert.AtomicObject, objectToConvert.Matrix);
object? conversionResult = await QueuedTask.Run(() => _converter.Convert(obj)).ConfigureAwait(false);
object conversionResult = _converter.Convert(obj);
string nestedLayerPath = $"{string.Join("\\", path)}";
@@ -128,29 +141,20 @@ public class ArcGISHostObjectBuilder : IHostObjectBuilder
// 2.1. Group conversionTrackers (to write into datasets)
onOperationProgressed.Report(new("Grouping features into layers", null));
Dictionary<string, List<(TraversalContext, ObjectConversionTracker)>> convertedGroups = await QueuedTask
.Run(async () =>
{
return await _featureClassUtils
.GroupConversionTrackers(conversionTracker, (s, progres) => onOperationProgressed.Report(new(s, progres)))
.ConfigureAwait(false);
})
.ConfigureAwait(false);
Dictionary<string, List<(TraversalContext, ObjectConversionTracker)>> convertedGroups =
_featureClassUtils.GroupConversionTrackers(
conversionTracker,
(s, progres) => onOperationProgressed.Report(new(s, progres))
);
// 2.2. Write groups of objects to Datasets
onOperationProgressed.Report(new("Writing to Database", null));
await QueuedTask
.Run(async () =>
{
await _featureClassUtils
.CreateDatasets(
conversionTracker,
convertedGroups,
(s, progres) => onOperationProgressed.Report(new(s, progres))
)
.ConfigureAwait(false);
})
.ConfigureAwait(false);
_featureClassUtils.CreateDatasets(
conversionTracker,
convertedGroups,
(s, progres) => onOperationProgressed.Report(new(s, progres))
);
// 3. add layer and tables to the Map and Table Of Content
@@ -202,8 +206,7 @@ public class ArcGISHostObjectBuilder : IHostObjectBuilder
else
{
// no layer yet, create and add layer to Map
MapMember mapMember = await AddDatasetsToMap(trackerItem, createdLayerGroups, projectName, modelName)
.ConfigureAwait(false);
MapMember mapMember = AddDatasetsToMap(trackerItem, createdLayerGroups, projectName, modelName);
// add layer and layer URI to tracker
trackerItem.AddConvertedMapMember(mapMember);
@@ -231,13 +234,13 @@ public class ArcGISHostObjectBuilder : IHostObjectBuilder
if (bakedMember.Value.Item1 is FeatureLayer fLayer)
{
// Set the feature layer's renderer.
await QueuedTask.Run(() => fLayer.SetRenderer(bakedMember.Value.Item2)).ConfigureAwait(false);
fLayer.SetRenderer(bakedMember.Value.Item2);
}
}
bakedObjectIds.AddRange(createdLayerGroups.Values.Select(x => x.URI));
// TODO: validated a correct set regarding bakedobject ids
return new(bakedObjectIds, results);
return new HostObjectBuilderResult(bakedObjectIds, results);
}
private IReadOnlyCollection<LocalToGlobalMap> GetObjectsToConvert(Base rootObject)
@@ -298,80 +301,72 @@ public class ArcGISHostObjectBuilder : IHostObjectBuilder
}
}
private async Task<MapMember> AddDatasetsToMap(
private MapMember AddDatasetsToMap(
ObjectConversionTracker trackerItem,
Dictionary<string, GroupLayer> createdLayerGroups,
string projectName,
string modelName
)
{
return await QueuedTask
.Run(() =>
// get layer details
string? datasetId = trackerItem.DatasetId; // should not be null here
Uri uri = new($"{_settingsStore.Current.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 = _settingsStore.Current.Map;
GroupLayer mainGroupLayer = LayerFactory.Instance.CreateGroupLayer(map, 0, $"{projectName}: {modelName}");
mainGroupLayer.SetExpanded(true);
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)
{
// get layer details
string? datasetId = trackerItem.DatasetId; // should not be null here
Uri uri = new($"{_settingsStore.Current.SpeckleDatabasePath.AbsolutePath.Replace('/', '\\')}\\{datasetId}");
string nestedLayerName = trackerItem.NestedLayerName;
throw new SpeckleException($"Layer '{shortName}' was not created");
}
layer.SetExpanded(false);
// add group for the current layer
string shortName = nestedLayerName.Split("\\")[^1];
string nestedLayerPath = string.Join("\\", nestedLayerName.Split("\\").SkipLast(1));
// if Scene
// https://community.esri.com/t5/arcgis-pro-sdk-questions/sdk-equivalent-to-changing-layer-s-elevation/td-p/1346139
if (_settingsStore.Current.Map.IsScene)
{
var groundSurfaceLayer = _settingsStore.Current.Map.GetGroundElevationSurfaceLayer();
var layerElevationSurface = new CIMLayerElevationSurface { ElevationSurfaceLayerURI = groundSurfaceLayer.URI, };
// if no general group layer found
if (createdLayerGroups.Count == 0)
// for Feature Layers
if (layer.GetDefinition() is CIMFeatureLayer cimLyr)
{
Map map = _settingsStore.Current.Map;
GroupLayer mainGroupLayer = LayerFactory.Instance.CreateGroupLayer(map, 0, $"{projectName}: {modelName}");
mainGroupLayer.SetExpanded(true);
createdLayerGroups["Basic Speckle Group"] = mainGroupLayer; // key doesn't really matter here
cimLyr.LayerElevation = layerElevationSurface;
layer.SetDefinition(cimLyr);
}
}
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");
}
layer.SetExpanded(false);
// if Scene
// https://community.esri.com/t5/arcgis-pro-sdk-questions/sdk-equivalent-to-changing-layer-s-elevation/td-p/1346139
if (_settingsStore.Current.Map.IsScene)
{
var groundSurfaceLayer = _settingsStore.Current.Map.GetGroundElevationSurfaceLayer();
var layerElevationSurface = new CIMLayerElevationSurface
{
ElevationSurfaceLayerURI = groundSurfaceLayer.URI,
};
// for Feature Layers
if (layer.GetDefinition() is CIMFeatureLayer cimLyr)
{
cimLyr.LayerElevation = layerElevationSurface;
layer.SetDefinition(cimLyr);
}
}
return (MapMember)layer;
}
catch (ArgumentException)
{
StandaloneTable table = StandaloneTableFactory.Instance.CreateStandaloneTable(
uri,
groupLayer,
tableName: shortName
);
return table;
}
})
.ConfigureAwait(false);
return layer;
}
catch (ArgumentException)
{
StandaloneTable table = StandaloneTableFactory.Instance.CreateStandaloneTable(
uri,
groupLayer,
tableName: shortName
);
return table;
}
}
private GroupLayer CreateNestedGroupLayer(string nestedLayerPath, Dictionary<string, GroupLayer> createdLayerGroups)
@@ -6,7 +6,6 @@ using Speckle.Connectors.ArcGIS.HostApp;
using Speckle.Connectors.ArcGIS.HostApp.Extensions;
using Speckle.Connectors.ArcGIS.Utils;
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;
@@ -25,7 +24,6 @@ namespace Speckle.Connectors.ArcGis.Operations.Send;
public class ArcGISRootObjectBuilder : IRootObjectBuilder<ADM.MapMember>
{
private readonly IRootToSpeckleConverter _rootToSpeckleConverter;
private readonly ISendConversionCache _sendConversionCache;
private readonly ArcGISLayerUnpacker _layerUnpacker;
private readonly ArcGISColorUnpacker _colorUnpacker;
private readonly IConverterSettingsStore<ArcGISConversionSettings> _converterSettings;
@@ -34,7 +32,6 @@ public class ArcGISRootObjectBuilder : IRootObjectBuilder<ADM.MapMember>
private readonly MapMembersUtils _mapMemberUtils;
public ArcGISRootObjectBuilder(
ISendConversionCache sendConversionCache,
ArcGISLayerUnpacker layerUnpacker,
ArcGISColorUnpacker colorUnpacker,
IConverterSettingsStore<ArcGISConversionSettings> converterSettings,
@@ -44,7 +41,6 @@ public class ArcGISRootObjectBuilder : IRootObjectBuilder<ADM.MapMember>
MapMembersUtils mapMemberUtils
)
{
_sendConversionCache = sendConversionCache;
_layerUnpacker = layerUnpacker;
_colorUnpacker = colorUnpacker;
_converterSettings = converterSettings;
@@ -54,11 +50,18 @@ public class ArcGISRootObjectBuilder : IRootObjectBuilder<ADM.MapMember>
_mapMemberUtils = mapMemberUtils;
}
public async Task<RootObjectBuilderResult> Build(
public Task<RootObjectBuilderResult> Build(
IReadOnlyList<ADM.MapMember> layers,
SendInfo sendInfo,
SendInfo __,
IProgress<CardProgress> onOperationProgressed,
CancellationToken ct = default
CancellationToken cancellationToken
) => QueuedTask.Run(() => BuildInternal(layers, __, onOperationProgressed, cancellationToken));
private async Task<RootObjectBuilderResult> BuildInternal(
IReadOnlyList<ADM.MapMember> layers,
SendInfo __,
IProgress<CardProgress> onOperationProgressed,
CancellationToken cancellationToken
)
{
// TODO: add a warning if Geographic CRS is set
@@ -99,23 +102,28 @@ public class ArcGISRootObjectBuilder : IRootObjectBuilder<ADM.MapMember>
// We need to unpack the selected mapmembers into all leaf-level mapmembers (containing just objects) and build the root collection structure during unpacking.
// Mapmember dynamically attached properties are also added at this step.
List<ADM.MapMember> unpackedLayers;
Dictionary<ADM.MapMember, long> layersWithFeatureCount;
long allFeaturesCount;
ADM.Map map = ADM.MapView.Active.Map;
IEnumerable<ADM.MapMember> layersOrdered = _mapMemberUtils.GetMapMembersInOrder(map, layers);
using (var _ = _activityFactory.Start("Unpacking selection"))
{
unpackedLayers = await QueuedTask
.Run(() => _layerUnpacker.UnpackSelectionAsync(layersOrdered, rootCollection))
.ConfigureAwait(false);
unpackedLayers = _layerUnpacker.UnpackSelection(layersOrdered, rootCollection);
// count number of features to convert. Raster layers are counter as 1 feature for now (not ideal)
layersWithFeatureCount = CountAllFeaturesInLayers(unpackedLayers);
allFeaturesCount = layersWithFeatureCount.Values.Sum();
}
List<SendConversionResult> results = new(unpackedLayers.Count);
onOperationProgressed.Report(new("Converting", null));
using (var convertingActivity = _activityFactory.Start("Converting objects"))
{
int count = 0;
foreach (ADM.MapMember layer in unpackedLayers)
long count = 0;
foreach (var (layer, layerFeatureCount) in layersWithFeatureCount)
{
ct.ThrowIfCancellationRequested();
cancellationToken.ThrowIfCancellationRequested();
string layerApplicationId = layer.GetSpeckleApplicationId();
try
@@ -141,21 +149,33 @@ public class ArcGISRootObjectBuilder : IRootObjectBuilder<ADM.MapMember>
switch (layer)
{
case ADM.FeatureLayer featureLayer:
List<Base> convertedFeatureLayerObjects = await QueuedTask
.Run(() => ConvertFeatureLayerObjectsAsync(featureLayer))
.ConfigureAwait(false);
List<Base> convertedFeatureLayerObjects = ConvertFeatureLayerObjects(
featureLayer,
count,
allFeaturesCount,
onOperationProgressed,
cancellationToken
);
layerCollection.elements.AddRange(convertedFeatureLayerObjects);
break;
case ADM.RasterLayer rasterLayer:
List<Base> convertedRasterLayerObjects = await QueuedTask
.Run(() => ConvertRasterLayerObjectsAsync(rasterLayer))
.ConfigureAwait(false);
List<Base> convertedRasterLayerObjects = ConvertRasterLayerObjects(
rasterLayer,
count,
allFeaturesCount,
onOperationProgressed,
cancellationToken
);
layerCollection.elements.AddRange(convertedRasterLayerObjects);
break;
case ADM.LasDatasetLayer lasDatasetLayer:
List<Base> convertedLasDatasetObjects = await QueuedTask
.Run(() => ConvertLasDatasetLayerObjectsAsync(lasDatasetLayer))
.ConfigureAwait(false);
List<Base> convertedLasDatasetObjects = ConvertLasDatasetLayerObjects(
lasDatasetLayer,
count,
allFeaturesCount,
onOperationProgressed,
cancellationToken
);
layerCollection.elements.AddRange(convertedLasDatasetObjects);
break;
default:
@@ -163,6 +183,8 @@ public class ArcGISRootObjectBuilder : IRootObjectBuilder<ADM.MapMember>
sdkStatus = SdkActivityStatusCode.Error;
break;
}
count += layerFeatureCount;
results.Add(new(status, layerApplicationId, layer.GetType().Name, layerCollection));
convertingActivity?.SetStatus(sdkStatus);
}
@@ -179,7 +201,7 @@ public class ArcGISRootObjectBuilder : IRootObjectBuilder<ADM.MapMember>
convertingActivity?.RecordException(ex);
}
onOperationProgressed.Report(new("Converting", (double)++count / layers.Count));
await Task.Yield();
}
}
@@ -194,96 +216,141 @@ public class ArcGISRootObjectBuilder : IRootObjectBuilder<ADM.MapMember>
return new RootObjectBuilderResult(rootCollection, results);
}
private async Task<List<Base>> ConvertFeatureLayerObjectsAsync(ADM.FeatureLayer featureLayer)
private Dictionary<ADM.MapMember, long> CountAllFeaturesInLayers(List<ADM.MapMember> unpackedLayers)
{
Dictionary<ADM.MapMember, long> layersFeatureCount = new();
foreach (ADM.MapMember layer in unpackedLayers)
{
switch (layer)
{
case ADM.FeatureLayer featureLayer:
layersFeatureCount.Add(featureLayer, featureLayer.GetFeatureClass().GetCount());
break;
case ADM.RasterLayer rasterLayer:
// count Raster layer as 1 feature: not optimal but this is the approach for now
layersFeatureCount.Add(rasterLayer, 1);
break;
case ADM.LasDatasetLayer lasDatasetLayer:
var dataset = lasDatasetLayer.GetLasDataset();
// simple dataset.GetPointCount() keeps returning null, so switched to EstimatePointCount
layersFeatureCount.Add(
lasDatasetLayer,
(long)dataset.EstimatePointCount(dataset.GetDefinition().GetExtent())
);
break;
}
}
return layersFeatureCount;
}
private List<Base> ConvertFeatureLayerObjects(
ADM.FeatureLayer featureLayer,
long count,
long allFeaturesCount,
IProgress<CardProgress> onOperationProgressed,
CancellationToken cancellationToken
)
{
string layerApplicationId = featureLayer.GetSpeckleApplicationId();
List<Base> convertedObjects = new();
await QueuedTask
.Run(() =>
// store the layer renderer for color unpacking
_colorUnpacker.StoreRendererAndFields(featureLayer);
// search the rows of the layer, where each row is treated like an object
// RowCursor is IDisposable but is not being correctly picked up by IDE warnings.
// This means we need to be carefully adding using statements based on the API documentation coming from each method/class
using (ACD.RowCursor rowCursor = featureLayer.Search())
{
while (rowCursor.MoveNext())
{
// store the layer renderer for color unpacking
_colorUnpacker.StoreRendererAndFields(featureLayer);
// allow cancellation before every feature
cancellationToken.ThrowIfCancellationRequested();
// search the rows of the layer, where each row is treated like an object
// RowCursor is IDisposable but is not being correctly picked up by IDE warnings.
// This means we need to be carefully adding using statements based on the API documentation coming from each method/class
using (ACD.RowCursor rowCursor = featureLayer.Search())
// Same IDisposable issue appears to happen on Row class too. Docs say it should always be disposed of manually by the caller.
using (ACD.Row row = rowCursor.Current)
{
while (rowCursor.MoveNext())
{
// Same IDisposable issue appears to happen on Row class too. Docs say it should always be disposed of manually by the caller.
using (ACD.Row row = rowCursor.Current)
{
// get application id. test for subtypes before defaulting to base type.
Base converted = _rootToSpeckleConverter.Convert(row);
string applicationId = row.GetSpeckleApplicationId(layerApplicationId);
converted.applicationId = applicationId;
// get application id. test for subtypes before defaulting to base type.
Base converted = _rootToSpeckleConverter.Convert(row);
string applicationId = row.GetSpeckleApplicationId(layerApplicationId);
converted.applicationId = applicationId;
convertedObjects.Add(converted);
convertedObjects.Add(converted);
// process the object color
_colorUnpacker.ProcessFeatureLayerColor(row, applicationId);
}
}
// process the object color
_colorUnpacker.ProcessFeatureLayerColor(row, applicationId);
}
})
.ConfigureAwait(false);
// update report
onOperationProgressed.Report(new("Converting", (double)++count / allFeaturesCount));
}
}
return convertedObjects;
}
// POC: raster colors are stored as mesh vertex colors in RasterToSpeckleConverter. Should probably move to color unpacker.
private async Task<List<Base>> ConvertRasterLayerObjectsAsync(ADM.RasterLayer rasterLayer)
private List<Base> ConvertRasterLayerObjects(
ADM.RasterLayer rasterLayer,
long count,
long allFeaturesCount,
IProgress<CardProgress> onOperationProgressed,
CancellationToken cancellationToken
)
{
string layerApplicationId = rasterLayer.GetSpeckleApplicationId();
List<Base> convertedObjects = new();
await QueuedTask
.Run(() =>
{
Raster raster = rasterLayer.GetRaster();
Base converted = _rootToSpeckleConverter.Convert(raster);
string applicationId = raster.GetSpeckleApplicationId(layerApplicationId);
converted.applicationId = applicationId;
convertedObjects.Add(converted);
})
.ConfigureAwait(false);
Raster raster = rasterLayer.GetRaster();
// check cancellation token before conversion
cancellationToken.ThrowIfCancellationRequested();
Base converted = _rootToSpeckleConverter.Convert(raster);
string applicationId = raster.GetSpeckleApplicationId(layerApplicationId);
converted.applicationId = applicationId;
convertedObjects.Add(converted);
// update report
onOperationProgressed.Report(new("Converting", (double)++count / allFeaturesCount));
return convertedObjects;
}
private async Task<List<Base>> ConvertLasDatasetLayerObjectsAsync(ADM.LasDatasetLayer lasDatasetLayer)
private List<Base> ConvertLasDatasetLayerObjects(
ADM.LasDatasetLayer lasDatasetLayer,
long count,
long allFeaturesCount,
IProgress<CardProgress> onOperationProgressed,
CancellationToken cancellationToken
)
{
string layerApplicationId = lasDatasetLayer.GetSpeckleApplicationId();
List<Base> convertedObjects = new();
try
{
await QueuedTask
.Run(() =>
// store the layer renderer for color unpacking
_colorUnpacker.StoreRenderer(lasDatasetLayer);
using (ACD.Analyst3D.LasPointCursor ptCursor = lasDatasetLayer.SearchPoints(new ACD.Analyst3D.LasPointFilter()))
{
while (ptCursor.MoveNext())
{
// store the layer renderer for color unpacking
_colorUnpacker.StoreRenderer(lasDatasetLayer);
// allow cancellation before every point
cancellationToken.ThrowIfCancellationRequested();
using (
ACD.Analyst3D.LasPointCursor ptCursor = lasDatasetLayer.SearchPoints(new ACD.Analyst3D.LasPointFilter())
)
using (ACD.Analyst3D.LasPoint pt = ptCursor.Current)
{
while (ptCursor.MoveNext())
{
using (ACD.Analyst3D.LasPoint pt = ptCursor.Current)
{
Base converted = _rootToSpeckleConverter.Convert(pt);
string applicationId = pt.GetSpeckleApplicationId(layerApplicationId);
converted.applicationId = applicationId;
convertedObjects.Add(converted);
Base converted = _rootToSpeckleConverter.Convert(pt);
string applicationId = pt.GetSpeckleApplicationId(layerApplicationId);
converted.applicationId = applicationId;
convertedObjects.Add(converted);
// process the object color
_colorUnpacker.ProcessLasLayerColor(pt, applicationId);
}
}
// process the object color
_colorUnpacker.ProcessLasLayerColor(pt, applicationId);
}
})
.ConfigureAwait(false);
// update report
onOperationProgressed.Report(new("Converting", (double)++count / allFeaturesCount));
}
}
}
catch (ACD.Exceptions.TinException ex)
{
@@ -18,7 +18,7 @@ internal sealed class SpeckleDUI3ViewModel : DockPane
/// </summary>
protected override async Task InitializeAsync()
{
await base.InitializeAsync().ConfigureAwait(false);
await base.InitializeAsync();
}
/// <summary>
@@ -26,7 +26,7 @@ internal sealed class SpeckleDUI3ViewModel : DockPane
/// </summary>
protected override async Task UninitializeAsync()
{
await base.UninitializeAsync().ConfigureAwait(false);
await base.UninitializeAsync();
}
}
@@ -4,7 +4,6 @@ using Speckle.Connectors.ArcGIS.DependencyInjection;
using Speckle.Connectors.Common;
using Speckle.Connectors.DUI;
using Speckle.Converters.ArcGIS3;
using Speckle.Sdk.Host;
using Module = ArcGIS.Desktop.Framework.Contracts.Module;
namespace Speckle.Connectors.ArcGIS;
@@ -3,6 +3,8 @@ using ArcGIS.Desktop.Core.Events;
using ArcGIS.Desktop.Framework.Threading.Tasks;
using ArcGIS.Desktop.Mapping;
using ArcGIS.Desktop.Mapping.Events;
using Microsoft.Extensions.Logging;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Utils;
@@ -11,8 +13,12 @@ namespace Speckle.Connectors.ArcGIS.Utils;
public class ArcGISDocumentStore : DocumentModelStore
{
public ArcGISDocumentStore(IJsonSerializer jsonSerializer, ITopLevelExceptionHandler topLevelExceptionHandler)
: base(jsonSerializer)
public ArcGISDocumentStore(
ILogger<DocumentModelStore> logger,
IJsonSerializer jsonSerializer,
ITopLevelExceptionHandler topLevelExceptionHandler
)
: base(logger, jsonSerializer)
{
ActiveMapViewChangedEvent.Subscribe(a => topLevelExceptionHandler.CatchUnhandled(() => OnMapViewChanged(a)), true);
ProjectSavingEvent.Subscribe(
@@ -74,52 +80,52 @@ public class ArcGISDocumentStore : DocumentModelStore
OnDocumentChanged();
}
protected override void HostAppSaveState(string modelCardState)
{
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"));
XElement xmlModelCards = new("SpeckleModelCards", modelCardState);
// Check if SpeckleModelCards element already exists at root and update it
var speckleModelCardsElement = existingXmlDocument.Root?.Element("SpeckleModelCards");
if (speckleModelCardsElement != null)
protected override void HostAppSaveState(string modelCardState) =>
QueuedTask
.Run(() =>
{
speckleModelCardsElement.ReplaceWith(xmlModelCards);
}
else
Map map = MapView.Active.Map;
// 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"));
XElement xmlModelCards = new("SpeckleModelCards", modelCardState);
// 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());
})
.FireAndForget();
protected override void LoadState() =>
QueuedTask
.Run(() =>
{
existingXmlDocument.Root?.Add(xmlModelCards);
}
Map map = MapView.Active.Map;
var metadata = map.GetMetadata();
var root = XDocument.Parse(metadata).Root;
var element = root?.Element("SpeckleModelCards");
if (element is null)
{
ClearAndSave();
return;
}
map.SetMetadata(existingXmlDocument.ToString());
});
}
protected override void LoadState()
{
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)
{
ClearAndSave();
return;
}
string modelsString = element.Value;
LoadFromString(modelsString);
});
}
string modelsString = element.Value;
LoadFromString(modelsString);
})
.FireAndForget();
}
@@ -166,11 +166,6 @@
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Speckle.DoubleNumerics": {
"type": "Transitive",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
},
"Speckle.Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.2",
@@ -226,24 +221,28 @@
"resolved": "4.5.1",
"contentHash": "Zh8t8oqolRaFa9vmOZfdQm/qKejdqz0J9kr7o2Fu0vPeoH3BL1EOXipKWwkWtLT1JPzjByrF19fGuFlNbmPpiw=="
},
"speckle.common.meshtriangulation": {
"type": "Project",
"dependencies": {
"LibTessDotNet": "[1.1.15, )",
"Speckle.DoubleNumerics": "[4.1.0, )"
}
},
"speckle.connectors.common": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.219, )",
"Speckle.Sdk": "[3.1.0-dev.219, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )",
"Speckle.Sdk": "[3.3.5, )",
"Speckle.Sdk.Dependencies": "[3.3.5, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.219, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.219, )",
"System.Threading.Tasks.Dataflow": "[6.0.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -260,6 +259,7 @@
"type": "Project",
"dependencies": {
"Esri.ArcGISPro.Extensions30": "[3.2.0.49743, )",
"Speckle.Common.MeshTriangulation": "[1.0.0, )",
"Speckle.Converters.Common": "[1.0.0, )"
}
},
@@ -267,9 +267,15 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"LibTessDotNet": {
"type": "CentralTransitive",
"requested": "[1.1.15, )",
"resolved": "1.1.15",
"contentHash": "KuA7N3Nv/lIeawJdQBQJR6oqWD9KETHLbWzBqapwFs+Tby+R5I4crkKujKMm5bXcSuFZ8LNtflFQVadsWCbBjg=="
},
"Microsoft.Extensions.DependencyInjection": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
@@ -297,20 +303,26 @@
"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.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "2thsMUDkRr7lR0PXZJ8k3KWZLWjz/aBY0KaO2SuXM0lIKyJw1APMJ7lXJ89e6JAjBzEbK8yLHBb0qtfcc4bNRw==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.219"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "UTgz9UgkMFGqRLmCq1HPo74MngvKbSZOFWaMRzASHrrnsBtzZatBXjoJBlvVoeBCoiea5Jj+BgZg6RvlV2m3sg==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -318,22 +330,16 @@
"Microsoft.Data.Sqlite": "7.0.5",
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.0.1",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.1.0-dev.219"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "5hqBd9whAs5cC8S/6YUgKFOivjntAkVutKhz06XD/f3Kj6xScT3hwcUaWBxiwK3Mw7FLtiVuU1uG777pjn0PKQ=="
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[6.0.0, )",
"resolved": "6.0.0",
"contentHash": "+tyDCU3/B1lDdOOAJywHQoFwyXIUghIaP2BxG79uvhfTnO+D9qIgjVlL/JV2NTliYbMHpd6eKDmHp2VHpij7MA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
},
"net6.0-windows7.0/win-x64": {
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<Target AfterTargets="Clean" Name="CleanAddinAutocad" Condition="'$(AutoCADVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
<RemoveDir Directories="$(AppData)\Autodesk\ApplicationPlugins\Speckle.Connectors.Autocad$(AutoCADVersion);" />
</Target>
<Target AfterTargets="Build" Name="AfterBuildAutoCAD" Condition="'$(AutoCADVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
<ItemGroup>
<AutoCADDLLs Include="$(TargetDir)\**\*.*" />
</ItemGroup>
<Message Text="AutoCAD Version $(AutoCADVersion)" Importance="high"/>
<Copy DestinationFolder="$(AppData)\Autodesk\ApplicationPlugins\Speckle.Connectors.Autocad$(AutoCADVersion)\%(RecursiveDir)" SourceFiles="@(AutoCADDLLs)" />
</Target>
<Target AfterTargets="Clean" Name="CleanAddinCivil3D" Condition="'$(Civil3DVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
<RemoveDir Directories="$(AppData)\Autodesk\ApplicationPlugins\Speckle.Connectors.Civil3d$(Civil3DVersion);" />
</Target>
<Target AfterTargets="Build" Name="AfterBuildCivil3D" Condition="'$(Civil3DVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
<ItemGroup>
<Civil3DDLLs Include="$(TargetDir)\**\*.*" />
</ItemGroup>
<Message Text="Civil3D Version $(Civil3DVersion)" Importance="high"/>
<Copy DestinationFolder="$(AppData)\Autodesk\ApplicationPlugins\Speckle.Connectors.Civil3d$(Civil3DVersion)\%(RecursiveDir)" SourceFiles="@(Civil3DDLLs)" />
</Target>
<PropertyGroup Condition="'$(AutoCADVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
<StartAction>Program</StartAction>
<StartProgram>$(ProgramW6432)\Autodesk\AutoCAD $(AutoCADVersion)\acad.exe</StartProgram>
</PropertyGroup>
<PropertyGroup Condition="'$(Civil3DVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
<StartAction>Program</StartAction>
<StartProgram>$(ProgramW6432)\Autodesk\AutoCAD $(Civil3DVersion)\acad.exe</StartProgram>
<StartArguments>/product C3D</StartArguments>
</PropertyGroup>
</Project>
@@ -6,12 +6,10 @@
<AutoCADVersion>2022</AutoCADVersion>
<DefineConstants>$(DefineConstants);AUTOCAD;AUTOCAD2022;AUTOCAD2022_OR_GREATER</DefineConstants>
<Configurations>Debug;Release;Local</Configurations>
<StartAction>Program</StartAction>
<StartProgram>$(ProgramW6432)\Autodesk\AutoCAD $(AutoCADVersion)\acad.exe</StartProgram>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2022.0.2" />
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2022.0.2" ExcludeAssets="runtime"/>
</ItemGroup>
<ItemGroup>
@@ -164,11 +164,6 @@
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Speckle.DoubleNumerics": {
"type": "Transitive",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
},
"Speckle.Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.2",
@@ -264,19 +259,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.219, )",
"Speckle.Sdk": "[3.1.0-dev.219, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )",
"Speckle.Sdk": "[3.3.5, )",
"Speckle.Sdk.Dependencies": "[3.3.5, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.219, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.219, )",
"System.Threading.Tasks.Dataflow": "[6.0.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -300,7 +292,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -336,20 +328,26 @@
"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.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "2thsMUDkRr7lR0PXZJ8k3KWZLWjz/aBY0KaO2SuXM0lIKyJw1APMJ7lXJ89e6JAjBzEbK8yLHBb0qtfcc4bNRw==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.219"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "UTgz9UgkMFGqRLmCq1HPo74MngvKbSZOFWaMRzASHrrnsBtzZatBXjoJBlvVoeBCoiea5Jj+BgZg6RvlV2m3sg==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -357,22 +355,16 @@
"Microsoft.Data.Sqlite": "7.0.5",
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.0.1",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.1.0-dev.219"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "5hqBd9whAs5cC8S/6YUgKFOivjntAkVutKhz06XD/f3Kj6xScT3hwcUaWBxiwK3Mw7FLtiVuU1uG777pjn0PKQ=="
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[6.0.0, )",
"resolved": "6.0.0",
"contentHash": "+tyDCU3/B1lDdOOAJywHQoFwyXIUghIaP2BxG79uvhfTnO+D9qIgjVlL/JV2NTliYbMHpd6eKDmHp2VHpij7MA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
}
}
@@ -6,12 +6,10 @@
<AutoCADVersion>2023</AutoCADVersion>
<DefineConstants>$(DefineConstants);AUTOCAD;AUTOCAD2023;AUTOCAD2022_OR_GREATER;AUTOCAD2023_OR_GREATER</DefineConstants>
<Configurations>Debug;Release;Local</Configurations>
<StartAction>Program</StartAction>
<StartProgram>$(ProgramW6432)\Autodesk\AutoCAD $(AutoCADVersion)\acad.exe</StartProgram>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2023.0.0" />
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2023.0.0" ExcludeAssets="runtime"/>
</ItemGroup>
<ItemGroup>
@@ -164,11 +164,6 @@
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Speckle.DoubleNumerics": {
"type": "Transitive",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
},
"Speckle.Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.2",
@@ -264,19 +259,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.219, )",
"Speckle.Sdk": "[3.1.0-dev.219, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )",
"Speckle.Sdk": "[3.3.5, )",
"Speckle.Sdk.Dependencies": "[3.3.5, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.219, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.219, )",
"System.Threading.Tasks.Dataflow": "[6.0.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -300,7 +292,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -336,20 +328,26 @@
"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.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "2thsMUDkRr7lR0PXZJ8k3KWZLWjz/aBY0KaO2SuXM0lIKyJw1APMJ7lXJ89e6JAjBzEbK8yLHBb0qtfcc4bNRw==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.219"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "UTgz9UgkMFGqRLmCq1HPo74MngvKbSZOFWaMRzASHrrnsBtzZatBXjoJBlvVoeBCoiea5Jj+BgZg6RvlV2m3sg==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -357,22 +355,16 @@
"Microsoft.Data.Sqlite": "7.0.5",
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.0.1",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.1.0-dev.219"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "5hqBd9whAs5cC8S/6YUgKFOivjntAkVutKhz06XD/f3Kj6xScT3hwcUaWBxiwK3Mw7FLtiVuU1uG777pjn0PKQ=="
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[6.0.0, )",
"resolved": "6.0.0",
"contentHash": "+tyDCU3/B1lDdOOAJywHQoFwyXIUghIaP2BxG79uvhfTnO+D9qIgjVlL/JV2NTliYbMHpd6eKDmHp2VHpij7MA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
}
}
@@ -1,17 +1,15 @@
<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>
<StartAction>Program</StartAction>
<StartProgram>$(ProgramW6432)\Autodesk\AutoCAD $(AutoCADVersion)\acad.exe</StartProgram>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2024.0.0" />
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2024.0.0" ExcludeAssets="runtime"/>
</ItemGroup>
<ItemGroup>
@@ -164,11 +164,6 @@
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Speckle.DoubleNumerics": {
"type": "Transitive",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
},
"Speckle.Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.2",
@@ -264,19 +259,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.219, )",
"Speckle.Sdk": "[3.1.0-dev.219, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )",
"Speckle.Sdk": "[3.3.5, )",
"Speckle.Sdk.Dependencies": "[3.3.5, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.219, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.219, )",
"System.Threading.Tasks.Dataflow": "[6.0.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -301,7 +293,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -337,20 +329,26 @@
"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.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "2thsMUDkRr7lR0PXZJ8k3KWZLWjz/aBY0KaO2SuXM0lIKyJw1APMJ7lXJ89e6JAjBzEbK8yLHBb0qtfcc4bNRw==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.219"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "UTgz9UgkMFGqRLmCq1HPo74MngvKbSZOFWaMRzASHrrnsBtzZatBXjoJBlvVoeBCoiea5Jj+BgZg6RvlV2m3sg==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -358,22 +356,16 @@
"Microsoft.Data.Sqlite": "7.0.5",
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.0.1",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.1.0-dev.219"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "5hqBd9whAs5cC8S/6YUgKFOivjntAkVutKhz06XD/f3Kj6xScT3hwcUaWBxiwK3Mw7FLtiVuU1uG777pjn0PKQ=="
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[6.0.0, )",
"resolved": "6.0.0",
"contentHash": "+tyDCU3/B1lDdOOAJywHQoFwyXIUghIaP2BxG79uvhfTnO+D9qIgjVlL/JV2NTliYbMHpd6eKDmHp2VHpij7MA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
}
}
@@ -1,20 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
<UseWpf>true</UseWpf>
<AutoCADVersion>2025</AutoCADVersion>
<DefineConstants>$(DefineConstants);AUTOCAD2025;AUTOCAD</DefineConstants>
<DefineConstants>$(DefineConstants);AUTOCAD;AUTOCAD2025;AUTOCAD2022_OR_GREATER;AUTOCAD2023_OR_GREATER;AUTOCAD2024_OR_GREATER;AUTOCAD2025_OR_GREATER</DefineConstants>
<Configurations>Debug;Release;Local</Configurations>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<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 -->
<StartAction>Program</StartAction>
<StartProgram>$(ProgramW6432)\Autodesk\AutoCAD $(AutoCADVersion)\acad.exe</StartProgram>
</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="2025.0.0" />
<FrameworkReference Include="Microsoft.WindowsDesktop.App"/>
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2025.0.0" ExcludeAssets="runtime"/>
</ItemGroup>
<ItemGroup>
@@ -155,11 +155,6 @@
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Speckle.DoubleNumerics": {
"type": "Transitive",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
},
"Speckle.Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.2",
@@ -220,19 +215,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.219, )",
"Speckle.Sdk": "[3.1.0-dev.219, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )",
"Speckle.Sdk": "[3.3.5, )",
"Speckle.Sdk.Dependencies": "[3.3.5, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.219, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.219, )",
"System.Threading.Tasks.Dataflow": "[6.0.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -257,7 +249,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -293,42 +285,42 @@
"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.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "2thsMUDkRr7lR0PXZJ8k3KWZLWjz/aBY0KaO2SuXM0lIKyJw1APMJ7lXJ89e6JAjBzEbK8yLHBb0qtfcc4bNRw==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.219"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "UTgz9UgkMFGqRLmCq1HPo74MngvKbSZOFWaMRzASHrrnsBtzZatBXjoJBlvVoeBCoiea5Jj+BgZg6RvlV2m3sg==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
"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.0.1",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.1.0-dev.219"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "5hqBd9whAs5cC8S/6YUgKFOivjntAkVutKhz06XD/f3Kj6xScT3hwcUaWBxiwK3Mw7FLtiVuU1uG777pjn0PKQ=="
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[6.0.0, )",
"resolved": "6.0.0",
"contentHash": "+tyDCU3/B1lDdOOAJywHQoFwyXIUghIaP2BxG79uvhfTnO+D9qIgjVlL/JV2NTliYbMHpd6eKDmHp2VHpij7MA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
},
"net8.0-windows7.0/win-x64": {
@@ -0,0 +1,27 @@
<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,32 +1,7 @@
{
"version": 2,
"dependencies": {
"net8.0": {
"altcover": {
"type": "Direct",
"requested": "[8.9.3, )",
"resolved": "8.9.3",
"contentHash": "auKC+pDCkLjfhFkSRaAUBu25BOmlLSqucR7YBs/Lkbdc0XRuJoklWafs1KKp+M+VoJ1f0TeMS6B/FO5IeIcu7w=="
},
"FluentAssertions": {
"type": "Direct",
"requested": "[6.12.1, )",
"resolved": "6.12.1",
"contentHash": "hciWwryyLw3eonfqhFpOMTXyM1/auJChYslEBA+iGJyuBs5O3t/kA8YaeH4iRo/2Fe3ElSYL86C0miivtZ0f3g==",
"dependencies": {
"System.Configuration.ConfigurationManager": "4.4.0"
}
},
"Microsoft.NET.Test.Sdk": {
"type": "Direct",
"requested": "[17.11.1, )",
"resolved": "17.11.1",
"contentHash": "U3Ty4BaGoEu+T2bwSko9tWqWUOU16WzSFkq6U8zve75oRBMSLTBdMAZrVNNz1Tq12aCdDom9fcOcM9QZaFHqFg==",
"dependencies": {
"Microsoft.CodeCoverage": "17.11.1",
"Microsoft.TestPlatform.TestHost": "17.11.1"
}
},
"net8.0-windows7.0": {
"Microsoft.NETFramework.ReferenceAssemblies": {
"type": "Direct",
"requested": "[1.0.3, )",
@@ -46,62 +21,24 @@
"Microsoft.SourceLink.Common": "8.0.0"
}
},
"Moq": {
"type": "Direct",
"requested": "[4.20.70, )",
"resolved": "4.20.70",
"contentHash": "4rNnAwdpXJBuxqrOCzCyICXHSImOTRktCgCWXWykuF1qwoIsVvEnR7PjbMk/eLOxWvhmj5Kwt+kDV3RGUYcNwg==",
"dependencies": {
"Castle.Core": "5.1.1"
}
},
"NUnit": {
"type": "Direct",
"requested": "[4.1.0, )",
"resolved": "4.1.0",
"contentHash": "MT/DpAhjtiytzhTgTqIhBuWx4y26PKfDepYUHUM+5uv4TsryHC2jwFo5e6NhWkApCm/G6kZ80dRjdJFuAxq3rg=="
},
"NUnit.Analyzers": {
"type": "Direct",
"requested": "[4.2.0, )",
"resolved": "4.2.0",
"contentHash": "4fJojPkzdoa4nB2+p6U+fITvPnVvwWSnsmiJ/Dl30xqiL3oxNbYvfeSLVd91hOmEjoUqSwN3Z7j1aFedjqWbUA=="
},
"NUnit3TestAdapter": {
"type": "Direct",
"requested": "[4.6.0, )",
"resolved": "4.6.0",
"contentHash": "R7e1+a4vuV/YS+ItfL7f//rG+JBvVeVLX4mHzFEZo4W1qEKl8Zz27AqvQSAqo+BtIzUCo4aAJMYa56VXS4hudw=="
},
"PolySharp": {
"type": "Direct",
"requested": "[1.14.1, )",
"resolved": "1.14.1",
"contentHash": "mOOmFYwad3MIOL14VCjj02LljyF1GNw1wP0YVlxtcPvqdxjGGMNdNJJxHptlry3MOd8b40Flm8RPOM8JOlN2sQ=="
},
"Speckle.AutoCAD.API": {
"type": "Direct",
"requested": "[2026.0.0, )",
"resolved": "2026.0.0",
"contentHash": "WlkV81PmbK/ftoM7aGpU6LGosKbePBQej9MO/m63rFMozX89tsitEhE12o58wu7K/4FmRUdAMolYtdK20EDBnw=="
},
"Speckle.InterfaceGenerator": {
"type": "Direct",
"requested": "[0.9.6, )",
"resolved": "0.9.6",
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
},
"Speckle.Revit2023.Fakes": {
"type": "Direct",
"requested": "[0.3.1, )",
"resolved": "0.3.1",
"contentHash": "uHYAqg2ljL5WpYYAQujgiS6olkGD31lXToyc0yIugAi0cnHtP5z95hjzg3QBbmFizVYyD5n2IwFnR49UiSVfJg==",
"dependencies": {
"System.Drawing.Common": "8.0.6"
}
},
"Castle.Core": {
"type": "Transitive",
"resolved": "5.1.1",
"contentHash": "rpYtIczkzGpf+EkZgDr9CClTdemhsrwA/W5hMoPjLkRFnXzH44zDLoovXeKtmxb1ykXK9aJVODSpiJml8CTw2g==",
"dependencies": {
"System.Diagnostics.EventLog": "6.0.0"
}
},
"GraphQL.Client": {
"type": "Transitive",
"resolved": "6.0.0",
@@ -138,11 +75,6 @@
"resolved": "8.0.0",
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
},
"Microsoft.CodeCoverage": {
"type": "Transitive",
"resolved": "17.11.1",
"contentHash": "nPJqrcA5iX+Y0kqoT3a+pD/8lrW/V7ayqnEJQsTonSoPz59J8bmoQhcSN4G8+UJ64Hkuf0zuxnfuj2lkHOq4cA=="
},
"Microsoft.CSharp": {
"type": "Transitive",
"resolved": "4.7.0",
@@ -223,38 +155,6 @@
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Microsoft.TestPlatform.ObjectModel": {
"type": "Transitive",
"resolved": "17.11.1",
"contentHash": "E2jZqAU6JeWEVsyOEOrSW1o1bpHLgb25ypvKNB/moBXPVsFYBPd/Jwi7OrYahG50J83LfHzezYI+GaEkpAotiA==",
"dependencies": {
"System.Reflection.Metadata": "1.6.0"
}
},
"Microsoft.TestPlatform.TestHost": {
"type": "Transitive",
"resolved": "17.11.1",
"contentHash": "DnG+GOqJXO/CkoqlJWeDFTgPhqD/V6VqUIL3vINizCWZ3X+HshCtbbyDdSHQQEjrc2Sl/K3yaxX6s+5LFEdYuw==",
"dependencies": {
"Microsoft.TestPlatform.ObjectModel": "17.11.1",
"Newtonsoft.Json": "13.0.1"
}
},
"Microsoft.Win32.SystemEvents": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "9opKRyOKMCi2xJ7Bj7kxtZ1r9vbzosMvRrdEhVhDz8j8MoBGgB+WmC94yH839NPH+BclAjtQ/pyagvi/8gDLkw=="
},
"Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.1",
"contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A=="
},
"Speckle.DoubleNumerics": {
"type": "Transitive",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
},
"Speckle.Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.2",
@@ -295,27 +195,6 @@
"resolved": "4.5.0",
"contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
},
"System.Configuration.ConfigurationManager": {
"type": "Transitive",
"resolved": "4.4.0",
"contentHash": "gWwQv/Ug1qWJmHCmN17nAbxJYmQBM/E94QxKLksvUiiKB1Ld3Sc/eK1lgmbSjDFxkQhVuayI/cGFZhpBSodLrg==",
"dependencies": {
"System.Security.Cryptography.ProtectedData": "4.4.0"
}
},
"System.Diagnostics.EventLog": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "lcyUiXTsETK2ALsZrX+nWuHSIQeazhqPphLfaRxzdGaG93+0kELqpgEHtwWOlQe7+jSFnKwaCAgL4kjeZCQJnw=="
},
"System.Drawing.Common": {
"type": "Transitive",
"resolved": "8.0.6",
"contentHash": "aSwRnJzz6fZ73JvWMMG0KvBwOnXsBTFtfHLriQyAPrDIZ+NrDfl15GWbO/A35k0dtH77D7jfxzEcFF7RONtU/w==",
"dependencies": {
"Microsoft.Win32.SystemEvents": "8.0.0"
}
},
"System.Memory": {
"type": "Transitive",
"resolved": "4.5.3",
@@ -326,33 +205,60 @@
"resolved": "5.0.0",
"contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ=="
},
"System.Reflection.Metadata": {
"type": "Transitive",
"resolved": "1.6.0",
"contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ=="
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
"resolved": "4.5.1",
"contentHash": "Zh8t8oqolRaFa9vmOZfdQm/qKejdqz0J9kr7o2Fu0vPeoH3BL1EOXipKWwkWtLT1JPzjByrF19fGuFlNbmPpiw=="
},
"System.Security.Cryptography.ProtectedData": {
"type": "Transitive",
"resolved": "4.4.0",
"contentHash": "cJV7ScGW7EhatRsjehfvvYVBvtiSMKgN8bOVI0bQhnF5bU7vnHVIsH49Kva7i7GWaWYvmEzkYVk1TC+gZYBEog=="
"speckle.connectors.common": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.3.5, )",
"Speckle.Sdk": "[3.3.5, )",
"Speckle.Sdk.Dependencies": "[3.3.5, )"
}
},
"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.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"speckle.testing": {
"type": "Project",
"Microsoft.Extensions.DependencyInjection": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==",
"dependencies": {
"Moq": "[4.20.70, )",
"NUnit": "[4.1.0, )"
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0"
}
},
"Microsoft.Extensions.Logging": {
@@ -373,36 +279,61 @@
"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.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "2thsMUDkRr7lR0PXZJ8k3KWZLWjz/aBY0KaO2SuXM0lIKyJw1APMJ7lXJ89e6JAjBzEbK8yLHBb0qtfcc4bNRw==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.219"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "UTgz9UgkMFGqRLmCq1HPo74MngvKbSZOFWaMRzASHrrnsBtzZatBXjoJBlvVoeBCoiea5Jj+BgZg6RvlV2m3sg==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
"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.0.1",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.1.0-dev.219"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "5hqBd9whAs5cC8S/6YUgKFOivjntAkVutKhz06XD/f3Kj6xScT3hwcUaWBxiwK3Mw7FLtiVuU1uG777pjn0PKQ=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
},
"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,6 +1,7 @@
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;
@@ -19,6 +20,8 @@ public class AutocadBasicConnectorBinding : IBasicConnectorBinding
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; }
@@ -28,7 +31,9 @@ public class AutocadBasicConnectorBinding : IBasicConnectorBinding
IBrowserBridge parent,
IAccountManager accountManager,
ISpeckleApplication speckleApplication,
ILogger<AutocadBasicConnectorBinding> logger
ILogger<AutocadBasicConnectorBinding> logger,
IThreadContext threadContext,
ITopLevelExceptionHandler topLevelExceptionHandler
)
{
_store = store;
@@ -36,12 +41,14 @@ public class AutocadBasicConnectorBinding : IBasicConnectorBinding
_accountManager = accountManager;
_speckleApplication = speckleApplication;
Commands = new BasicConnectorBindingCommands(parent);
_store.DocumentChanged += (_, _) =>
parent.TopLevelExceptionHandler.FireAndForget(async () =>
{
await Commands.NotifyDocumentChanged().ConfigureAwait(false);
});
_logger = logger;
_threadContext = threadContext;
_topLevelExceptionHandler = topLevelExceptionHandler;
_store.DocumentChanged += (_, _) =>
_topLevelExceptionHandler.FireAndForget(async () =>
{
await Commands.NotifyDocumentChanged();
});
}
public string GetConnectorVersion() => _speckleApplication.SpeckleVersion;
@@ -72,6 +79,8 @@ public class AutocadBasicConnectorBinding : IBasicConnectorBinding
public void RemoveModel(ModelCard model) => _store.RemoveModel(model);
public void RemoveModels(List<ModelCard> models) => _store.RemoveModels(models);
public async Task HighlightObjects(IReadOnlyList<string> objectIds)
{
// POC: Will be addressed to move it into AutocadContext!
@@ -79,7 +88,7 @@ public class AutocadBasicConnectorBinding : IBasicConnectorBinding
var dbObjects = doc.GetObjects(objectIds);
var acadObjectIds = dbObjects.Select(tuple => tuple.Root.Id).ToArray();
await HighlightObjectsOnView(acadObjectIds).ConfigureAwait(false);
await HighlightObjectsOnView(acadObjectIds);
}
public async Task HighlightModel(string modelCardId)
@@ -116,79 +125,73 @@ public class AutocadBasicConnectorBinding : IBasicConnectorBinding
if (objectIds.Length == 0)
{
await Commands
.SetModelError(modelCardId, new OperationCanceledException("No objects found to highlight."))
.ConfigureAwait(false);
await Commands.SetModelError(modelCardId, new OperationCanceledException("No objects found to highlight."));
return;
}
await HighlightObjectsOnView(objectIds, modelCardId).ConfigureAwait(false);
await HighlightObjectsOnView(objectIds, modelCardId);
}
private async Task HighlightObjectsOnView(ObjectId[] objectIds, string? modelCardId = null)
{
var doc = Application.DocumentManager.MdiActiveDocument;
await Parent
.RunOnMainThreadAsync(async () =>
await _threadContext.RunOnMainAsync(async () =>
{
try
{
doc.Editor.SetImpliedSelection([]); // Deselects
try
{
doc.Editor.SetImpliedSelection(Array.Empty<ObjectId>()); // Deselects
doc.Editor.SetImpliedSelection(objectIds);
}
catch (Exception e) when (!e.IsFatal())
{
// SWALLOW REASON:
// If the objects under the blocks, it won't be able to select them.
// If we try, API will throw the invalid input error, because we request something from API that Autocad doesn't
// handle it on its current canvas. Block elements only selectable when in its scope.
}
doc.Editor.UpdateScreen();
Extents3d selectedExtents = new();
var tr = doc.TransactionManager.StartTransaction();
foreach (ObjectId objectId in objectIds)
{
try
{
doc.Editor.SetImpliedSelection(objectIds);
var entity = (Entity?)tr.GetObject(objectId, OpenMode.ForRead);
if (entity?.GeometricExtents != null)
{
selectedExtents.AddExtents(entity.GeometricExtents);
}
}
catch (Exception e) when (!e.IsFatal())
{
// SWALLOW REASON:
// If the objects under the blocks, it won't be able to select them.
// If we try, API will throw the invalid input error, because we request something from API that Autocad doesn't
// handle it on its current canvas. Block elements only selectable when in its scope.
// 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
}
doc.Editor.UpdateScreen();
Extents3d selectedExtents = new();
var tr = doc.TransactionManager.StartTransaction();
foreach (ObjectId objectId in objectIds)
{
try
{
var entity = (Entity?)tr.GetObject(objectId, OpenMode.ForRead);
if (entity?.GeometricExtents != null)
{
selectedExtents.AddExtents(entity.GeometricExtents);
}
}
catch (Exception e) when (!e.IsFatal())
{
// 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
}
}
doc.Editor.Zoom(selectedExtents);
tr.Commit();
Autodesk.AutoCAD.Internal.Utils.FlushGraphics();
}
catch (Exception ex) when (!ex.IsFatal())
doc.Editor.Zoom(selectedExtents);
tr.Commit();
Autodesk.AutoCAD.Internal.Utils.FlushGraphics();
}
catch (Exception ex) when (!ex.IsFatal())
{
if (modelCardId != null)
{
if (modelCardId != null)
{
await Commands
.SetModelError(modelCardId, new OperationCanceledException("Failed to highlight objects."))
.ConfigureAwait(false);
}
else
{
// This will happen, in some cases, where we highlight individual objects. Should be caught by the top level handler and not
// crash the host app.
throw;
}
await Commands.SetModelError(modelCardId, new OperationCanceledException("Failed to highlight objects."));
}
})
.ConfigureAwait(false);
else
{
// This will happen, in some cases, where we highlight individual objects. Should be caught by the top level handler and not
// crash the host app.
throw;
}
}
});
}
}
@@ -0,0 +1,119 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Speckle.Connectors.Common.Cancellation;
using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Logging;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Models.Card;
using Speckle.Sdk;
namespace Speckle.Connectors.Autocad.Bindings;
public abstract class AutocadReceiveBaseBinding : IReceiveBinding
{
public string Name => "receiveBinding";
public IBrowserBridge Parent { get; }
private readonly DocumentModelStore _store;
private readonly ICancellationManager _cancellationManager;
private readonly IServiceProvider _serviceProvider;
private readonly IOperationProgressManager _operationProgressManager;
private readonly ILogger<AutocadReceiveBinding> _logger;
private readonly ISpeckleApplication _speckleApplication;
private readonly IThreadContext _threadContext;
private ReceiveBindingUICommands Commands { get; }
protected AutocadReceiveBaseBinding(
DocumentModelStore store,
IBrowserBridge parent,
ICancellationManager cancellationManager,
IServiceProvider serviceProvider,
IOperationProgressManager operationProgressManager,
ILogger<AutocadReceiveBinding> logger,
ISpeckleApplication speckleApplication,
IThreadContext threadContext
)
{
_store = store;
_cancellationManager = cancellationManager;
_serviceProvider = serviceProvider;
_operationProgressManager = operationProgressManager;
_logger = logger;
_speckleApplication = speckleApplication;
_threadContext = threadContext;
Parent = parent;
Commands = new ReceiveBindingUICommands(parent);
}
protected abstract void InitializeSettings(IServiceProvider serviceProvider);
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 scope = _serviceProvider.CreateScope();
InitializeSettings(scope.ServiceProvider);
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.");
}
using var cancellationItem = _cancellationManager.GetCancellationItem(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 scope
.ServiceProvider.GetRequiredService<ReceiveOperation>()
.Execute(
modelCard.GetReceiveInfo(_speckleApplication.Slug),
_operationProgressManager.CreateOperationProgressEventHandler(Parent, modelCardId, cancellationItem.Token),
cancellationItem.Token
);
await 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);
await Commands.SetModelError(modelCardId, ex);
}
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,109 +1,49 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Speckle.Connectors.Common.Cancellation;
using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
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.Sdk;
namespace Speckle.Connectors.Autocad.Bindings;
public sealed class AutocadReceiveBinding : IReceiveBinding
public sealed class AutocadReceiveBinding : AutocadReceiveBaseBinding
{
public string Name => "receiveBinding";
public IBrowserBridge Parent { get; }
private readonly DocumentModelStore _store;
private readonly CancellationManager _cancellationManager;
private readonly IServiceProvider _serviceProvider;
private readonly IOperationProgressManager _operationProgressManager;
private readonly ILogger<AutocadReceiveBinding> _logger;
private readonly IAutocadConversionSettingsFactory _autocadConversionSettingsFactory;
private readonly ISpeckleApplication _speckleApplication;
private ReceiveBindingUICommands Commands { get; }
public AutocadReceiveBinding(
DocumentModelStore store,
IBrowserBridge parent,
CancellationManager cancellationManager,
ICancellationManager cancellationManager,
IServiceProvider serviceProvider,
IOperationProgressManager operationProgressManager,
ILogger<AutocadReceiveBinding> logger,
IAutocadConversionSettingsFactory autocadConversionSettingsFactory,
ISpeckleApplication speckleApplication
ISpeckleApplication speckleApplication,
IThreadContext threadContext
)
: base(
store,
parent,
cancellationManager,
serviceProvider,
operationProgressManager,
logger,
speckleApplication,
threadContext
)
{
_store = store;
_cancellationManager = cancellationManager;
_serviceProvider = serviceProvider;
_operationProgressManager = operationProgressManager;
_logger = logger;
_autocadConversionSettingsFactory = autocadConversionSettingsFactory;
_speckleApplication = speckleApplication;
Parent = parent;
Commands = new ReceiveBindingUICommands(parent);
}
public void CancelReceive(string modelCardId) => _cancellationManager.CancelOperation(modelCardId);
public async Task Receive(string modelCardId)
protected override void InitializeSettings(IServiceProvider serviceProvider)
{
using var scope = _serviceProvider.CreateScope();
scope
.ServiceProvider.GetRequiredService<IConverterSettingsStore<AutocadConversionSettings>>()
serviceProvider
.GetRequiredService<IConverterSettingsStore<AutocadConversionSettings>>()
.Initialize(_autocadConversionSettingsFactory.Create(Application.DocumentManager.CurrentDocument));
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 scope
.ServiceProvider.GetRequiredService<ReceiveOperation>()
.Execute(
modelCard.GetReceiveInfo(_speckleApplication.Slug),
_operationProgressManager.CreateOperationProgressEventHandler(Parent, modelCardId, cancellationToken),
cancellationToken
)
.ConfigureAwait(false);
await Commands
.SetModelReceiveResult(modelCardId, operationResults.BakedObjectIds, operationResults.ConversionResults)
.ConfigureAwait(false);
}
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);
await Commands.SetModelError(modelCardId, ex).ConfigureAwait(false);
}
finally
{
// reenable document activation
Application.DocumentManager.DocumentActivationEnabled = true;
}
}
}
@@ -1,6 +1,7 @@
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;
@@ -8,17 +9,23 @@ namespace Speckle.Connectors.Autocad.Bindings;
public class AutocadSelectionBinding : ISelectionBinding
{
private const string SELECTION_EVENT = "setSelection";
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
private readonly IThreadContext _threadContext;
private const string SELECTION_EVENT = "setSelection";
private readonly HashSet<Document> _visitedDocuments = new();
public string Name => "selectionBinding";
public IBrowserBridge Parent { get; }
public AutocadSelectionBinding(IBrowserBridge parent)
public AutocadSelectionBinding(
IBrowserBridge parent,
ITopLevelExceptionHandler topLevelExceptionHandler,
IThreadContext threadContext
)
{
_topLevelExceptionHandler = parent.TopLevelExceptionHandler;
_topLevelExceptionHandler = topLevelExceptionHandler;
_threadContext = threadContext;
Parent = parent;
// POC: Use here Context for doc. In converters it's OK but we are still lacking to use context into bindings.
@@ -41,9 +48,7 @@ public class AutocadSelectionBinding : ISelectionBinding
if (!_visitedDocuments.Contains(document))
{
document.ImpliedSelectionChanged += (_, _) =>
_topLevelExceptionHandler.FireAndForget(
async () => await Parent.RunOnMainThreadAsync(OnSelectionChanged).ConfigureAwait(false)
);
_topLevelExceptionHandler.FireAndForget(async () => await _threadContext.RunOnMainAsync(OnSelectionChanged));
_visitedDocuments.Add(document);
}
@@ -57,7 +62,7 @@ public class AutocadSelectionBinding : ISelectionBinding
private async Task OnSelectionChanged()
{
_selectionInfo = GetSelectionInternal();
await Parent.Send(SELECTION_EVENT, _selectionInfo).ConfigureAwait(false);
await Parent.Send(SELECTION_EVENT, _selectionInfo);
}
public SelectionInfo GetSelection() => _selectionInfo;
@@ -84,6 +89,17 @@ 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,13 +1,14 @@
using System.Collections.Concurrent;
using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
using Autodesk.AutoCAD.DatabaseServices;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Speckle.Connectors.Autocad.HostApp;
using Speckle.Connectors.Autocad.HostApp.Extensions;
using Speckle.Connectors.Autocad.Operations.Send;
using Speckle.Connectors.Common.Caching;
using Speckle.Connectors.Common.Cancellation;
using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Exceptions;
@@ -21,6 +22,7 @@ using Speckle.Sdk.Common;
namespace Speckle.Connectors.Autocad.Bindings;
[SuppressMessage("ReSharper", "AsyncVoidMethod")]
public abstract class AutocadSendBaseBinding : ISendBinding
{
public string Name => "sendBinding";
@@ -29,15 +31,16 @@ public abstract class AutocadSendBaseBinding : ISendBinding
public IBrowserBridge Parent { get; }
private readonly DocumentModelStore _store;
private readonly IAutocadIdleManager _idleManager;
private readonly List<ISendFilter> _sendFilters;
private readonly CancellationManager _cancellationManager;
private readonly ICancellationManager _cancellationManager;
private readonly IServiceProvider _serviceProvider;
private readonly ISendConversionCache _sendConversionCache;
private readonly IOperationProgressManager _operationProgressManager;
private readonly ILogger<AutocadSendBinding> _logger;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
private readonly ISpeckleApplication _speckleApplication;
private readonly IThreadContext _threadContext;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
private readonly IAppIdleManager _idleManager;
/// <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:
@@ -45,23 +48,24 @@ public abstract class AutocadSendBaseBinding : ISendBinding
/// 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 ConcurrentBag<string> ChangedObjectIds { get; set; } = new();
protected AutocadSendBaseBinding(
DocumentModelStore store,
IAutocadIdleManager idleManager,
IBrowserBridge parent,
IEnumerable<ISendFilter> sendFilters,
CancellationManager cancellationManager,
ICancellationManager cancellationManager,
IServiceProvider serviceProvider,
ISendConversionCache sendConversionCache,
IOperationProgressManager operationProgressManager,
ILogger<AutocadSendBinding> logger,
ISpeckleApplication speckleApplication
ISpeckleApplication speckleApplication,
IThreadContext threadContext,
ITopLevelExceptionHandler topLevelExceptionHandler,
IAppIdleManager idleManager
)
{
_store = store;
_idleManager = idleManager;
_serviceProvider = serviceProvider;
_cancellationManager = cancellationManager;
_sendFilters = sendFilters.ToList();
@@ -69,7 +73,9 @@ public abstract class AutocadSendBaseBinding : ISendBinding
_operationProgressManager = operationProgressManager;
_logger = logger;
_speckleApplication = speckleApplication;
_topLevelExceptionHandler = parent.TopLevelExceptionHandler;
_threadContext = threadContext;
_topLevelExceptionHandler = topLevelExceptionHandler;
_idleManager = idleManager;
Parent = parent;
Commands = new SendBindingUICommands(parent);
@@ -103,31 +109,25 @@ public abstract class AutocadSendBaseBinding : ISendBinding
doc.Database.ObjectModified += (_, e) => OnObjectChanged(e.DBObject);
}
private void OnObjectChanged(DBObject dbObject)
{
private void OnObjectChanged(DBObject dbObject) =>
_topLevelExceptionHandler.CatchUnhandled(() => OnChangeChangedObjectIds(dbObject));
}
private void OnChangeChangedObjectIds(DBObject dBObject)
{
ChangedObjectIds[dBObject.GetSpeckleApplicationId()] = 1;
_idleManager.SubscribeToIdle(
nameof(AutocadSendBinding),
async () => await RunExpirationChecks().ConfigureAwait(false)
);
ChangedObjectIds.Add(dBObject.GetSpeckleApplicationId());
_idleManager.SubscribeToIdle(nameof(RunExpirationChecks), async () => await RunExpirationChecks());
}
private async Task RunExpirationChecks()
{
var senders = _store.GetSenders();
string[] objectIdsList = ChangedObjectIds.Keys.ToArray();
List<string> expiredSenderIds = new();
_sendConversionCache.EvictObjects(objectIdsList);
_sendConversionCache.EvictObjects(ChangedObjectIds);
foreach (SenderModelCard modelCard in senders)
{
var intersection = modelCard.SendFilter.NotNull().RefreshObjectIds().Intersect(objectIdsList).ToList();
var intersection = modelCard.SendFilter.NotNull().RefreshObjectIds().Intersect(ChangedObjectIds).ToList();
bool isExpired = intersection.Count != 0;
if (isExpired)
{
@@ -135,7 +135,7 @@ public abstract class AutocadSendBaseBinding : ISendBinding
}
}
await Commands.SetModelsExpired(expiredSenderIds).ConfigureAwait(false);
await Commands.SetModelsExpired(expiredSenderIds);
ChangedObjectIds = new();
}
@@ -144,9 +144,7 @@ public abstract class AutocadSendBaseBinding : ISendBinding
public List<ICardSetting> GetSendSettings() => [];
public async Task Send(string modelCardId) =>
await Parent
.RunOnMainThreadAsync(async () => await SendInternal(modelCardId).ConfigureAwait(false))
.ConfigureAwait(false);
await _threadContext.RunOnMainAsync(async () => await SendInternal(modelCardId));
protected abstract void InitializeSettings(IServiceProvider serviceProvider);
@@ -163,7 +161,7 @@ public abstract class AutocadSendBaseBinding : ISendBinding
using var scope = _serviceProvider.CreateScope();
InitializeSettings(scope.ServiceProvider);
CancellationToken cancellationToken = _cancellationManager.InitCancellationTokenSource(modelCardId);
using var cancellationItem = _cancellationManager.GetCancellationItem(modelCardId);
// Disable document activation (document creation and document switch)
// Not disabling results in DUI model card being out of sync with the active document
@@ -185,15 +183,12 @@ public abstract class AutocadSendBaseBinding : ISendBinding
.ServiceProvider.GetRequiredService<SendOperation<AutocadRootObject>>()
.Execute(
autocadObjects,
modelCard.GetSendInfo(_speckleApplication.Slug),
_operationProgressManager.CreateOperationProgressEventHandler(Parent, modelCardId, cancellationToken),
cancellationToken
)
.ConfigureAwait(false);
modelCard.GetSendInfo(_speckleApplication.ApplicationAndVersion),
_operationProgressManager.CreateOperationProgressEventHandler(Parent, modelCardId, cancellationItem.Token),
cancellationItem.Token
);
await Commands
.SetModelSendResult(modelCardId, sendResult.RootObjId, sendResult.ConversionResults)
.ConfigureAwait(false);
await Commands.SetModelSendResult(modelCardId, sendResult.RootObjId, sendResult.ConversionResults);
}
catch (OperationCanceledException)
{
@@ -205,7 +200,7 @@ public abstract class AutocadSendBaseBinding : ISendBinding
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);
await Commands.SetModelError(modelCardId, ex).ConfigureAwait(false);
await Commands.SetModelError(modelCardId, ex);
}
finally
{
@@ -1,8 +1,8 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Speckle.Connectors.Autocad.HostApp;
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;
@@ -19,20 +19,21 @@ public sealed class AutocadSendBinding : AutocadSendBaseBinding
public AutocadSendBinding(
DocumentModelStore store,
IAutocadIdleManager idleManager,
IBrowserBridge parent,
IEnumerable<ISendFilter> sendFilters,
CancellationManager cancellationManager,
ICancellationManager cancellationManager,
IServiceProvider serviceProvider,
ISendConversionCache sendConversionCache,
IOperationProgressManager operationProgressManager,
ILogger<AutocadSendBinding> logger,
IAutocadConversionSettingsFactory autocadConversionSettingsFactory,
ISpeckleApplication speckleApplication
ISpeckleApplication speckleApplication,
IThreadContext threadContext,
ITopLevelExceptionHandler topLevelExceptionHandler,
IAppIdleManager appIdleManager
)
: base(
store,
idleManager,
parent,
sendFilters,
cancellationManager,
@@ -40,7 +41,10 @@ public sealed class AutocadSendBinding : AutocadSendBaseBinding
sendConversionCache,
operationProgressManager,
logger,
speckleApplication
speckleApplication,
threadContext,
topLevelExceptionHandler,
appIdleManager
)
{
_autocadConversionSettingsFactory = autocadConversionSettingsFactory;
@@ -10,6 +10,7 @@ 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;
@@ -23,8 +24,8 @@ public static class SharedRegistration
{
public static void AddAutocadBase(this IServiceCollection serviceCollection)
{
serviceCollection.AddConnectorUtils();
serviceCollection.AddDUI<AutocadDocumentStore>();
serviceCollection.AddConnectors();
serviceCollection.AddDUI<DefaultThreadContext, AutocadDocumentStore>();
serviceCollection.AddDUIView();
// Register other connector specific types
@@ -43,10 +44,10 @@ public static class SharedRegistration
serviceCollection.AddScoped<AutocadGroupBaker>();
serviceCollection.AddScoped<AutocadColorUnpacker>();
serviceCollection.AddScoped<AutocadColorBaker>();
serviceCollection.AddScoped<IAutocadColorBaker, AutocadColorBaker>();
serviceCollection.AddScoped<AutocadMaterialUnpacker>();
serviceCollection.AddScoped<AutocadMaterialBaker>();
serviceCollection.AddScoped<IAutocadMaterialBaker, AutocadMaterialBaker>();
serviceCollection.AddSingleton<IAppIdleManager, AutocadIdleManager>();
@@ -60,8 +61,6 @@ public static class SharedRegistration
serviceCollection.AddSingleton<IBinding>(sp => sp.GetRequiredService<IBasicConnectorBinding>());
serviceCollection.AddSingleton<IBasicConnectorBinding, AutocadBasicConnectorBinding>();
serviceCollection.AddSingleton<IBinding, ConfigBinding>();
serviceCollection.RegisterTopLevelExceptionHandler();
}
public static void LoadSend(this IServiceCollection serviceCollection)
@@ -1,6 +1,7 @@
using Autodesk.AutoCAD.Colors;
using Microsoft.Extensions.Logging;
using Speckle.Connectors.Common.Operations;
using Speckle.InterfaceGenerator;
using Speckle.Sdk;
using Speckle.Sdk.Models.Proxies;
using AutocadColor = Autodesk.AutoCAD.Colors.Color;
@@ -10,15 +11,9 @@ 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 AutocadColorBaker
[GenerateAutoInterface]
public class AutocadColorBaker(ILogger<AutocadColorBaker> logger) : IAutocadColorBaker
{
private readonly ILogger<AutocadColorBaker> _logger;
public AutocadColorBaker(ILogger<AutocadColorBaker> logger)
{
_logger = logger;
}
/// <summary>
/// For receive operations
/// </summary>
@@ -59,7 +54,7 @@ public class AutocadColorBaker
}
catch (Exception ex) when (!ex.IsFatal())
{
_logger.LogError(ex, "Failed parsing color proxy");
logger.LogError(ex, "Failed parsing color proxy");
}
}
}
@@ -1,3 +1,4 @@
using Microsoft.Extensions.Logging;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Utils;
@@ -6,19 +7,20 @@ namespace Speckle.Connectors.Autocad.HostApp;
public class AutocadDocumentStore : DocumentModelStore
{
private readonly string _nullDocumentName = "Null Doc";
private const string NULL_DOCUMENT_NAME = "Null Doc";
private string _previousDocName;
private readonly AutocadDocumentManager _autocadDocumentManager;
public AutocadDocumentStore(
ILogger<DocumentModelStore> logger,
IJsonSerializer jsonSerializer,
AutocadDocumentManager autocadDocumentManager,
ITopLevelExceptionHandler topLevelExceptionHandler
)
: base(jsonSerializer)
: base(logger, jsonSerializer)
{
_autocadDocumentManager = autocadDocumentManager;
_previousDocName = _nullDocumentName;
_previousDocName = NULL_DOCUMENT_NAME;
// POC: Will be addressed to move it into AutocadContext!
if (Application.DocumentManager.MdiActiveDocument != null)
@@ -40,7 +42,7 @@ public class AutocadDocumentStore : DocumentModelStore
private void OnDocChangeInternal(Document? doc)
{
var currentDocName = doc != null ? doc.Name : _nullDocumentName;
var currentDocName = doc != null ? doc.Name : NULL_DOCUMENT_NAME;
if (_previousDocName == currentDocName)
{
return;
@@ -12,10 +12,7 @@ public sealed class AutocadIdleManager(IIdleCallManager idleCallManager)
{
private readonly IIdleCallManager _idleCallManager = idleCallManager;
protected override void AddEvent()
{
Application.Idle += AutocadAppOnIdle;
}
protected override void AddEvent() => Application.Idle += AutocadAppOnIdle;
private void AutocadAppOnIdle(object? sender, EventArgs e) =>
_idleCallManager.AppOnIdle(() => Application.Idle -= AutocadAppOnIdle);
@@ -26,16 +26,16 @@ namespace Speckle.Connectors.Autocad.HostApp;
public class AutocadInstanceBaker : IInstanceBaker<IReadOnlyCollection<Entity>>
{
private readonly AutocadLayerBaker _layerBaker;
private readonly AutocadColorBaker _colorBaker;
private readonly AutocadMaterialBaker _materialBaker;
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,
AutocadColorBaker colorBaker,
AutocadMaterialBaker materialBaker,
IAutocadColorBaker colorBaker,
IAutocadMaterialBaker materialBaker,
AutocadContext autocadContext,
ILogger<AutocadInstanceBaker> logger,
IConverterSettingsStore<AutocadConversionSettings> converterSettings
@@ -101,6 +101,23 @@ public class AutocadInstanceUnpacker : IInstanceUnpacker<AutocadRootObject>
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(),
@@ -131,12 +148,12 @@ public class AutocadInstanceUnpacker : IInstanceUnpacker<AutocadRootObject>
{
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)
// 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);
@@ -12,15 +12,15 @@ public class AutocadLayerBaker : TraversalContextUnpacker
{
private readonly string _layerFilterName = "Speckle";
private readonly AutocadContext _autocadContext;
private readonly AutocadMaterialBaker _materialBaker;
private readonly AutocadColorBaker _colorBaker;
private readonly IAutocadMaterialBaker _materialBaker;
private readonly IAutocadColorBaker _colorBaker;
private Document Doc => Application.DocumentManager.MdiActiveDocument;
private readonly HashSet<string> _uniqueLayerNames = new();
public AutocadLayerBaker(
AutocadContext autocadContext,
AutocadMaterialBaker materialBaker,
AutocadColorBaker colorBaker
IAutocadMaterialBaker materialBaker,
IAutocadColorBaker colorBaker
)
{
_autocadContext = autocadContext;
@@ -4,6 +4,7 @@ using Autodesk.AutoCAD.GraphicsInterface;
using Microsoft.Extensions.Logging;
using Speckle.Connectors.Common.Conversion;
using Speckle.Connectors.Common.Operations;
using Speckle.InterfaceGenerator;
using Speckle.Objects.Other;
using Speckle.Sdk;
using Speckle.Sdk.Common;
@@ -16,7 +17,8 @@ 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 AutocadMaterialBaker
[GenerateAutoInterface]
public class AutocadMaterialBaker : IAutocadMaterialBaker
{
private readonly ILogger<AutocadMaterialBaker> _logger;
private readonly AutocadContext _autocadContext;
@@ -20,86 +20,44 @@ namespace Speckle.Connectors.Autocad.Operations.Receive;
/// <summary>
/// <para>Expects to be a scoped dependency per receive operation.</para>
/// </summary>
public class AutocadHostObjectBuilder : IHostObjectBuilder
public class AutocadHostObjectBuilder(
IRootToHostConverter converter,
AutocadLayerBaker layerBaker,
AutocadGroupBaker groupBaker,
AutocadInstanceBaker instanceBaker,
IAutocadMaterialBaker materialBaker,
IAutocadColorBaker colorBaker,
AutocadContext autocadContext,
RootObjectUnpacker rootObjectUnpacker
) : IHostObjectBuilder
{
private readonly AutocadLayerBaker _layerBaker;
private readonly IRootToHostConverter _converter;
private readonly ISyncToThread _syncToThread;
private readonly AutocadGroupBaker _groupBaker;
private readonly AutocadMaterialBaker _materialBaker;
private readonly AutocadColorBaker _colorBaker;
private readonly AutocadInstanceBaker _instanceBaker;
private readonly AutocadContext _autocadContext;
private readonly RootObjectUnpacker _rootObjectUnpacker;
public AutocadHostObjectBuilder(
IRootToHostConverter converter,
AutocadLayerBaker layerBaker,
AutocadGroupBaker groupBaker,
AutocadInstanceBaker instanceBaker,
AutocadMaterialBaker materialBaker,
AutocadColorBaker colorBaker,
ISyncToThread syncToThread,
AutocadContext autocadContext,
RootObjectUnpacker rootObjectUnpacker
)
{
_converter = converter;
_layerBaker = layerBaker;
_groupBaker = groupBaker;
_instanceBaker = instanceBaker;
_materialBaker = materialBaker;
_colorBaker = colorBaker;
_syncToThread = syncToThread;
_autocadContext = autocadContext;
_rootObjectUnpacker = rootObjectUnpacker;
}
public async Task<HostObjectBuilderResult> Build(
public Task<HostObjectBuilderResult> Build(
Base rootObject,
string projectName,
string modelName,
IProgress<CardProgress> onOperationProgressed,
CancellationToken _
)
{
// NOTE: This is the only place we apply ISyncToThread across connectors. We need to sync up with main thread here
// after GetObject and Deserialization. It is anti-pattern now. Happiness level 3/10 but works.
return await _syncToThread
.RunOnThread(async () =>
{
await Task.CompletedTask.ConfigureAwait(true);
return BuildSync(rootObject, projectName, modelName, onOperationProgressed);
})
.ConfigureAwait(false);
}
private HostObjectBuilderResult BuildSync(
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);
layerBaker.CreateLayerFilter(projectName, modelName);
// 0 - Clean then Rock n Roll!
string baseLayerPrefix = _autocadContext.RemoveInvalidChars($"SPK-{projectName}-{modelName}-");
string baseLayerPrefix = autocadContext.RemoveInvalidChars($"SPK-{projectName}-{modelName}-");
PreReceiveDeepClean(baseLayerPrefix);
// 1 - Unpack objects and proxies from root commit object
var unpackedRoot = _rootObjectUnpacker.Unpack(rootObject);
var unpackedRoot = rootObjectUnpacker.Unpack(rootObject);
// 2 - Split atomic objects and instance components with their path
var (atomicObjects, instanceComponents) = _rootObjectUnpacker.SplitAtomicObjectsAndInstances(
var (atomicObjects, instanceComponents) = rootObjectUnpacker.SplitAtomicObjectsAndInstances(
unpackedRoot.ObjectsToConvert
);
var atomicObjectsWithPath = _layerBaker.GetAtomicObjectsWithPath(atomicObjects);
var instanceComponentsWithPath = _layerBaker.GetInstanceComponentsWithPath(instanceComponents);
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)
@@ -113,7 +71,7 @@ public class AutocadHostObjectBuilder : IHostObjectBuilder
// 3 - Bake materials and colors, as they are used later down the line by layers and objects
if (unpackedRoot.RenderMaterialProxies != null)
{
_materialBaker.ParseAndBakeRenderMaterials(
materialBaker.ParseAndBakeRenderMaterials(
unpackedRoot.RenderMaterialProxies,
baseLayerPrefix,
onOperationProgressed
@@ -122,10 +80,10 @@ public class AutocadHostObjectBuilder : IHostObjectBuilder
if (unpackedRoot.ColorProxies != null)
{
_colorBaker.ParseColors(unpackedRoot.ColorProxies, onOperationProgressed);
colorBaker.ParseColors(unpackedRoot.ColorProxies, onOperationProgressed);
}
// 5 - Convert atomic objects
// 4 - Convert atomic objects
HashSet<ReceiveConversionResult> results = new();
HashSet<string> bakedObjectIds = new();
Dictionary<string, IReadOnlyCollection<Entity>> applicationIdMap = new();
@@ -134,6 +92,7 @@ public class AutocadHostObjectBuilder : IHostObjectBuilder
{
string objectId = atomicObject.applicationId ?? atomicObject.id.NotNull();
onOperationProgressed.Report(new("Converting objects", (double)++count / atomicObjects.Count));
cancellationToken.ThrowIfCancellationRequested();
try
{
IReadOnlyCollection<Entity> convertedObjects = ConvertObject(atomicObject, layerPath, baseLayerPrefix);
@@ -157,8 +116,8 @@ public class AutocadHostObjectBuilder : IHostObjectBuilder
}
}
// 6 - Convert instances
var (createdInstanceIds, consumedObjectIds, instanceConversionResults) = _instanceBaker.BakeInstances(
// 5 - Convert instances
var (createdInstanceIds, consumedObjectIds, instanceConversionResults) = instanceBaker.BakeInstances(
instanceComponentsWithPath,
applicationIdMap,
baseLayerPrefix,
@@ -170,46 +129,52 @@ public class AutocadHostObjectBuilder : IHostObjectBuilder
results.RemoveWhere(result => result.ResultId != null && consumedObjectIds.Contains(result.ResultId));
results.UnionWith(instanceConversionResults);
// 7 - Create groups
// 6 - Create groups
if (unpackedRoot.GroupProxies != null)
{
IReadOnlyCollection<ReceiveConversionResult> groupResults = _groupBaker.CreateGroups(
IReadOnlyCollection<ReceiveConversionResult> groupResults = groupBaker.CreateGroups(
unpackedRoot.GroupProxies,
applicationIdMap
);
results.UnionWith(groupResults);
}
return new HostObjectBuilderResult(bakedObjectIds, results);
return Task.FromResult(new HostObjectBuilderResult(bakedObjectIds, results));
}
private void PreReceiveDeepClean(string baseLayerPrefix)
{
_layerBaker.DeleteAllLayersByPrefix(baseLayerPrefix);
_instanceBaker.PurgeInstances(baseLayerPrefix);
_materialBaker.PurgeMaterials(baseLayerPrefix);
layerBaker.DeleteAllLayersByPrefix(baseLayerPrefix);
instanceBaker.PurgeInstances(baseLayerPrefix);
materialBaker.PurgeMaterials(baseLayerPrefix);
}
private IReadOnlyCollection<Entity> ConvertObject(Base obj, Collection[] layerPath, string baseLayerNamePrefix)
{
string layerName = _layerBaker.CreateLayerForReceive(layerPath, 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);
var converted = converter.Convert(obj);
// 2: handle result
if (converted is Entity entity)
switch (converted)
{
var bakedEntity = BakeObject(entity, obj, layerName);
convertedEntities.Add(bakedEntity);
}
else if (converted is List<(Entity, Base)> fallbackConversionResult)
{
var bakedFallbackEntities = BakeObjectsAsGroup(fallbackConversionResult, obj, layerName, baseLayerNamePrefix);
convertedEntities.UnionWith(bakedFallbackEntities);
case Entity entity:
var bakedEntity = BakeObject(entity, obj, layerName);
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);
convertedEntities.UnionWith(bakedFallbackEntities);
break;
default:
// TODO: capture defualt case with report object here? Same as in Rhino
break;
}
tr.Commit();
@@ -219,12 +184,12 @@ public class AutocadHostObjectBuilder : IHostObjectBuilder
private Entity BakeObject(Entity entity, Base originalObject, string layerName, Base? parentObject = null)
{
var objId = originalObject.applicationId ?? originalObject.id.NotNull();
if (_colorBaker.ObjectColorsIdMap.TryGetValue(objId, out AutocadColor? color))
if (colorBaker.ObjectColorsIdMap.TryGetValue(objId, out AutocadColor? color))
{
entity.Color = color;
}
if (_materialBaker.TryGetMaterialId(originalObject, parentObject, out ObjectId matId))
if (materialBaker.TryGetMaterialId(originalObject, parentObject, out ObjectId matId))
{
entity.MaterialId = matId;
}
@@ -249,11 +214,16 @@ public class AutocadHostObjectBuilder : IHostObjectBuilder
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 tr = Application.DocumentManager.CurrentDocument.Database.TransactionManager.TopTransaction;
var groupDictionary = (DBDictionary)
tr.GetObject(Application.DocumentManager.CurrentDocument.Database.GroupDictionaryId, OpenMode.ForWrite);
var groupName = _autocadContext.RemoveInvalidChars(
var groupName = autocadContext.RemoveInvalidChars(
$@"{parentObject.speckle_type.Split('.').Last()} - {parentObject.applicationId ?? parentObject.id} ({baseLayerName})"
);
@@ -49,13 +49,6 @@ public abstract class AutocadRootObjectBaseBuilder : IRootObjectBuilder<AutocadR
_activityFactory = activityFactory;
}
public Task<RootObjectBuilderResult> Build(
IReadOnlyList<AutocadRootObject> objects,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
CancellationToken ct = default
) => Task.FromResult(BuildSync(objects, sendInfo, onOperationProgressed, ct));
[SuppressMessage(
"Maintainability",
"CA1506:Avoid excessive class coupling",
@@ -65,11 +58,11 @@ public abstract class AutocadRootObjectBaseBuilder : IRootObjectBuilder<AutocadR
proxy classes yet. So I'm supressing this one now!!!
"""
)]
private RootObjectBuilderResult BuildSync(
public Task<RootObjectBuilderResult> Build(
IReadOnlyList<AutocadRootObject> objects,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
CancellationToken ct = default
CancellationToken cancellationToken
)
{
// 0 - Init the root
@@ -101,7 +94,7 @@ public abstract class AutocadRootObjectBaseBuilder : IRootObjectBuilder<AutocadR
int count = 0;
foreach (var (entity, applicationId) in atomicObjects)
{
ct.ThrowIfCancellationRequested();
cancellationToken.ThrowIfCancellationRequested();
using (var convertActivity = _activityFactory.Start("Converting object"))
{
// Create and add a collection for this entity if not done so already.
@@ -140,7 +133,7 @@ public abstract class AutocadRootObjectBaseBuilder : IRootObjectBuilder<AutocadR
// add any additional properties (most likely from verticals)
AddAdditionalProxiesToRoot(root);
return new RootObjectBuilderResult(root, results);
return Task.FromResult(new RootObjectBuilderResult(root, results));
}
}
@@ -1,10 +1,10 @@
using Speckle.Sdk.Host;
using Speckle.Connectors.Common;
namespace Speckle.Connectors.Autocad.Plugin;
public static class AppUtils
{
public static HostApplication App =>
public static Speckle.Sdk.Application App =>
#if CIVIL3D
HostApplications.Civil3D;
#elif AUTOCAD
@@ -14,7 +14,9 @@ public static class AppUtils
#endif
public static HostAppVersion Version =>
#if AUTOCAD2025 || CIVIL3D2025
#if AUTOCAD2026 || CIVIL3D2026
HostAppVersion.v2026;
#elif AUTOCAD2025 || CIVIL3D2025
HostAppVersion.v2025;
#elif AUTOCAD2024 || CIVIL3D2024
HostAppVersion.v2024;
@@ -31,7 +31,7 @@ public class AutocadCommand
return;
}
PaletteSet = new PaletteSet($"Speckle (Beta) for {AppUtils.App.Name}", s_id)
PaletteSet = new PaletteSet($"Speckle (Beta)", s_id)
{
Size = new Size(400, 500),
DockEnabled = (DockSides)((int)DockSides.Left + (int)DockSides.Right)
@@ -52,7 +52,7 @@ public class AutocadCommand
var panelWebView = Container.GetRequiredService<DUI3ControlWebView>();
PaletteSet.AddVisual($"Speckle (Beta) for {AppUtils.App.Name} WebView", panelWebView);
PaletteSet.AddVisual("Speckle (Beta)", panelWebView);
FocusPalette();
}
@@ -1,9 +1,11 @@
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
using System.IO;
#endif
namespace Speckle.Connectors.Autocad.Plugin;
@@ -46,20 +48,20 @@ public class AutocadRibbon
private void Create()
{
RibbonTab tab = FindOrMakeTab("Add-ins");
RibbonPanelSource source = new() { Title = "Speckle 2 (New Beta)" };
RibbonTab tab = FindOrMakeTab("Speckle");
RibbonPanelSource source = new() { Title = "Speckle (Beta)" };
RibbonPanel panel = new() { Source = source };
tab.Panels.Add(panel);
RibbonToolTip speckleToolTip =
new()
{
Title = "Speckle 2 (New Beta)",
Content = "Speckle Connector for " + AppUtils.App.Name,
Title = "Speckle (Beta)",
Content = $"Next Gen Speckle Connector (Beta) for {AppUtils.App.Name}",
IsHelpEnabled = true // Without this "Press F1 for help" does not appear in the tooltip
};
_ = CreateSpeckleButton("Connector " + AppUtils.App.Name + " (New)", source, null, speckleToolTip, "logo");
_ = CreateSpeckleButton("Speckle (Beta)", source, null, speckleToolTip, "logo");
}
private void ComponentManager_ItemInitialized(object? sender, RibbonItemEventArgs e)
@@ -9,6 +9,7 @@
<Import_RootNamespace>Speckle.Connectors.AutocadShared</Import_RootNamespace>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)Bindings\AutocadReceiveBaseBinding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bindings\AutocadSelectionBinding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bindings\AutocadReceiveBinding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bindings\AutocadSendBinding.cs" />
@@ -21,6 +22,7 @@
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadColorUnpacker.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadGroupBaker.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadGroupUnpacker.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadIdleManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadInstanceBaker.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadInstanceUnpacker.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadLayerBaker.cs" />
@@ -29,7 +31,6 @@
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadContext.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadDocumentManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadDocumentModelStore.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadIdleManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadMaterialUnpacker.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\Extensions\DatabaseExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\Extensions\DocumentExtensions.cs" />
@@ -6,12 +6,10 @@
<Civil3DVersion>2022</Civil3DVersion>
<DefineConstants>$(DefineConstants);CIVIL3D;CIVIL3D2022;CIVIL3D2022_OR_GREATER</DefineConstants>
<Configurations>Debug;Release;Local</Configurations>
<StartAction>Program</StartAction>
<StartProgram>$(ProgramW6432)\Autodesk\AutoCAD $(Civil3DVersion)\acad.exe</StartProgram>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Speckle.AutoCAD.API" />
<PackageReference Include="Speckle.Civil3D.API" />
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2022.0.2" ExcludeAssets="runtime"/>
<PackageReference Include="Speckle.Civil3D.API" VersionOverride="2022.0.2" ExcludeAssets="runtime"/>
</ItemGroup>
<ItemGroup>
@@ -173,11 +173,6 @@
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Speckle.DoubleNumerics": {
"type": "Transitive",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
},
"Speckle.Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.2",
@@ -273,19 +268,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.219, )",
"Speckle.Sdk": "[3.1.0-dev.219, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )",
"Speckle.Sdk": "[3.3.5, )",
"Speckle.Sdk.Dependencies": "[3.3.5, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.219, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.219, )",
"System.Threading.Tasks.Dataflow": "[6.0.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -310,7 +302,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -346,20 +338,26 @@
"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.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "2thsMUDkRr7lR0PXZJ8k3KWZLWjz/aBY0KaO2SuXM0lIKyJw1APMJ7lXJ89e6JAjBzEbK8yLHBb0qtfcc4bNRw==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.219"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "UTgz9UgkMFGqRLmCq1HPo74MngvKbSZOFWaMRzASHrrnsBtzZatBXjoJBlvVoeBCoiea5Jj+BgZg6RvlV2m3sg==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -367,22 +365,16 @@
"Microsoft.Data.Sqlite": "7.0.5",
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.0.1",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.1.0-dev.219"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "5hqBd9whAs5cC8S/6YUgKFOivjntAkVutKhz06XD/f3Kj6xScT3hwcUaWBxiwK3Mw7FLtiVuU1uG777pjn0PKQ=="
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[6.0.0, )",
"resolved": "6.0.0",
"contentHash": "+tyDCU3/B1lDdOOAJywHQoFwyXIUghIaP2BxG79uvhfTnO+D9qIgjVlL/JV2NTliYbMHpd6eKDmHp2VHpij7MA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
}
}
@@ -6,13 +6,11 @@
<Civil3DVersion>2023</Civil3DVersion>
<DefineConstants>$(DefineConstants);CIVIL3D;CIVIL3D2023;CIVIL3D2022_OR_GREATER;CIVIL3D2023_OR_GREATER</DefineConstants>
<Configurations>Debug;Release;Local</Configurations>
<StartAction>Program</StartAction>
<StartProgram>$(ProgramW6432)\Autodesk\AutoCAD $(Civil3DVersion)\acad.exe</StartProgram>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2023.0.0" />
<PackageReference Include="Speckle.Civil3D.API" VersionOverride="2023.0.0" />
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2023.0.0" ExcludeAssets="runtime"/>
<PackageReference Include="Speckle.Civil3D.API" VersionOverride="2023.0.0" ExcludeAssets="runtime"/>
</ItemGroup>
<ItemGroup>
@@ -173,11 +173,6 @@
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Speckle.DoubleNumerics": {
"type": "Transitive",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
},
"Speckle.Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.2",
@@ -273,19 +268,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.219, )",
"Speckle.Sdk": "[3.1.0-dev.219, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )",
"Speckle.Sdk": "[3.3.5, )",
"Speckle.Sdk.Dependencies": "[3.3.5, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.219, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.219, )",
"System.Threading.Tasks.Dataflow": "[6.0.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -310,7 +302,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -346,20 +338,26 @@
"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.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "2thsMUDkRr7lR0PXZJ8k3KWZLWjz/aBY0KaO2SuXM0lIKyJw1APMJ7lXJ89e6JAjBzEbK8yLHBb0qtfcc4bNRw==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.219"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "UTgz9UgkMFGqRLmCq1HPo74MngvKbSZOFWaMRzASHrrnsBtzZatBXjoJBlvVoeBCoiea5Jj+BgZg6RvlV2m3sg==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -367,22 +365,16 @@
"Microsoft.Data.Sqlite": "7.0.5",
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.0.1",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.1.0-dev.219"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "5hqBd9whAs5cC8S/6YUgKFOivjntAkVutKhz06XD/f3Kj6xScT3hwcUaWBxiwK3Mw7FLtiVuU1uG777pjn0PKQ=="
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[6.0.0, )",
"resolved": "6.0.0",
"contentHash": "+tyDCU3/B1lDdOOAJywHQoFwyXIUghIaP2BxG79uvhfTnO+D9qIgjVlL/JV2NTliYbMHpd6eKDmHp2VHpij7MA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
}
}
@@ -6,13 +6,11 @@
<Civil3DVersion>2024</Civil3DVersion>
<DefineConstants>$(DefineConstants);CIVIL3D;CIVIL3D2024;CIVIL3D2022_OR_GREATER;CIVIL3D2023_OR_GREATER;CIVIL3D2024_OR_GREATER</DefineConstants>
<Configurations>Debug;Release;Local</Configurations>
<StartAction>Program</StartAction>
<StartProgram>$(ProgramW6432)\Autodesk\AutoCAD $(Civil3DVersion)\acad.exe</StartProgram>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2024.0.0" />
<PackageReference Include="Speckle.Civil3D.API" VersionOverride="2024.0.0" />
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2024.0.0" ExcludeAssets="runtime"/>
<PackageReference Include="Speckle.Civil3D.API" VersionOverride="2024.0.0" ExcludeAssets="runtime"/>
</ItemGroup>
<ItemGroup>
@@ -173,11 +173,6 @@
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Speckle.DoubleNumerics": {
"type": "Transitive",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
},
"Speckle.Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.2",
@@ -273,19 +268,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.219, )",
"Speckle.Sdk": "[3.1.0-dev.219, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )",
"Speckle.Sdk": "[3.3.5, )",
"Speckle.Sdk.Dependencies": "[3.3.5, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.219, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.219, )",
"System.Threading.Tasks.Dataflow": "[6.0.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -310,7 +302,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -346,20 +338,26 @@
"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.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "2thsMUDkRr7lR0PXZJ8k3KWZLWjz/aBY0KaO2SuXM0lIKyJw1APMJ7lXJ89e6JAjBzEbK8yLHBb0qtfcc4bNRw==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.219"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "UTgz9UgkMFGqRLmCq1HPo74MngvKbSZOFWaMRzASHrrnsBtzZatBXjoJBlvVoeBCoiea5Jj+BgZg6RvlV2m3sg==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -367,22 +365,16 @@
"Microsoft.Data.Sqlite": "7.0.5",
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.0.1",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.1.0-dev.219"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "5hqBd9whAs5cC8S/6YUgKFOivjntAkVutKhz06XD/f3Kj6xScT3hwcUaWBxiwK3Mw7FLtiVuU1uG777pjn0PKQ=="
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[6.0.0, )",
"resolved": "6.0.0",
"contentHash": "+tyDCU3/B1lDdOOAJywHQoFwyXIUghIaP2BxG79uvhfTnO+D9qIgjVlL/JV2NTliYbMHpd6eKDmHp2VHpij7MA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
}
}
@@ -1,21 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
<UseWpf>true</UseWpf>
<Civil3DVersion>2025</Civil3DVersion>
<DefineConstants>$(DefineConstants);CIVIL3D2025;CIVIL3D;CIVIL3D2022_OR_GREATER;CIVIL3D2023_OR_GREATER;CIVIL3D2024_OR_GREATER;CIVIL3D2025_OR_GREATER</DefineConstants>
<Configurations>Debug;Release;Local</Configurations>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<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 -->
<StartAction>Program</StartAction>
<StartProgram>$(ProgramW6432)\Autodesk\AutoCAD $(Civil3DVersion)\acad.exe</StartProgram>
</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="2025.0.0" />
<PackageReference Include="Speckle.Civil3d.API" VersionOverride="2025.0.0" />
<FrameworkReference Include="Microsoft.WindowsDesktop.App" />
<PackageReference Include="Speckle.AutoCAD.API" VersionOverride="2025.0.0" ExcludeAssets="runtime"/>
<PackageReference Include="Speckle.Civil3d.API" VersionOverride="2025.0.0" ExcludeAssets="runtime"/>
</ItemGroup>
<ItemGroup>
@@ -164,11 +164,6 @@
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Speckle.DoubleNumerics": {
"type": "Transitive",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
},
"Speckle.Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.2",
@@ -229,19 +224,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.219, )",
"Speckle.Sdk": "[3.1.0-dev.219, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )",
"Speckle.Sdk": "[3.3.5, )",
"Speckle.Sdk.Dependencies": "[3.3.5, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.219, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.219, )",
"System.Threading.Tasks.Dataflow": "[6.0.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -267,7 +259,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -303,42 +295,42 @@
"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.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "2thsMUDkRr7lR0PXZJ8k3KWZLWjz/aBY0KaO2SuXM0lIKyJw1APMJ7lXJ89e6JAjBzEbK8yLHBb0qtfcc4bNRw==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.219"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "UTgz9UgkMFGqRLmCq1HPo74MngvKbSZOFWaMRzASHrrnsBtzZatBXjoJBlvVoeBCoiea5Jj+BgZg6RvlV2m3sg==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
"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.0.1",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.1.0-dev.219"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "5hqBd9whAs5cC8S/6YUgKFOivjntAkVutKhz06XD/f3Kj6xScT3hwcUaWBxiwK3Mw7FLtiVuU1uG777pjn0PKQ=="
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[6.0.0, )",
"resolved": "6.0.0",
"contentHash": "+tyDCU3/B1lDdOOAJywHQoFwyXIUghIaP2BxG79uvhfTnO+D9qIgjVlL/JV2NTliYbMHpd6eKDmHp2VHpij7MA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
},
"net8.0-windows7.0/win-x64": {
@@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<Civil3DVersion>2026</Civil3DVersion>
<DefineConstants>$(DefineConstants);CIVIL3D2026;CIVIL3D;CIVIL3D2022_OR_GREATER;CIVIL3D2023_OR_GREATER;CIVIL3D2024_OR_GREATER;CIVIL3D2025_OR_GREATER;CIVIL3D2026_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"/>
<PackageReference Include="Speckle.Civil3d.API" VersionOverride="2026.0.0" ExcludeAssets="runtime"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Converters\Civil3d\Speckle.Converters.Civil3d2026\Speckle.Converters.Civil3d2026.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.Civil3dShared\Speckle.Connectors.Civil3dShared.projitems" Label="Shared" />
<Import Project="..\Speckle.Connectors.AutocadShared\Speckle.Connectors.AutocadShared.projitems" Label="Shared" />
</Project>
@@ -1,32 +1,7 @@
{
"version": 2,
"dependencies": {
"net8.0": {
"altcover": {
"type": "Direct",
"requested": "[8.9.3, )",
"resolved": "8.9.3",
"contentHash": "auKC+pDCkLjfhFkSRaAUBu25BOmlLSqucR7YBs/Lkbdc0XRuJoklWafs1KKp+M+VoJ1f0TeMS6B/FO5IeIcu7w=="
},
"FluentAssertions": {
"type": "Direct",
"requested": "[6.12.1, )",
"resolved": "6.12.1",
"contentHash": "hciWwryyLw3eonfqhFpOMTXyM1/auJChYslEBA+iGJyuBs5O3t/kA8YaeH4iRo/2Fe3ElSYL86C0miivtZ0f3g==",
"dependencies": {
"System.Configuration.ConfigurationManager": "4.4.0"
}
},
"Microsoft.NET.Test.Sdk": {
"type": "Direct",
"requested": "[17.11.1, )",
"resolved": "17.11.1",
"contentHash": "U3Ty4BaGoEu+T2bwSko9tWqWUOU16WzSFkq6U8zve75oRBMSLTBdMAZrVNNz1Tq12aCdDom9fcOcM9QZaFHqFg==",
"dependencies": {
"Microsoft.CodeCoverage": "17.11.1",
"Microsoft.TestPlatform.TestHost": "17.11.1"
}
},
"net8.0-windows7.0": {
"Microsoft.NETFramework.ReferenceAssemblies": {
"type": "Direct",
"requested": "[1.0.3, )",
@@ -46,62 +21,33 @@
"Microsoft.SourceLink.Common": "8.0.0"
}
},
"Moq": {
"type": "Direct",
"requested": "[4.20.70, )",
"resolved": "4.20.70",
"contentHash": "4rNnAwdpXJBuxqrOCzCyICXHSImOTRktCgCWXWykuF1qwoIsVvEnR7PjbMk/eLOxWvhmj5Kwt+kDV3RGUYcNwg==",
"dependencies": {
"Castle.Core": "5.1.1"
}
},
"NUnit": {
"type": "Direct",
"requested": "[4.1.0, )",
"resolved": "4.1.0",
"contentHash": "MT/DpAhjtiytzhTgTqIhBuWx4y26PKfDepYUHUM+5uv4TsryHC2jwFo5e6NhWkApCm/G6kZ80dRjdJFuAxq3rg=="
},
"NUnit.Analyzers": {
"type": "Direct",
"requested": "[4.2.0, )",
"resolved": "4.2.0",
"contentHash": "4fJojPkzdoa4nB2+p6U+fITvPnVvwWSnsmiJ/Dl30xqiL3oxNbYvfeSLVd91hOmEjoUqSwN3Z7j1aFedjqWbUA=="
},
"NUnit3TestAdapter": {
"type": "Direct",
"requested": "[4.6.0, )",
"resolved": "4.6.0",
"contentHash": "R7e1+a4vuV/YS+ItfL7f//rG+JBvVeVLX4mHzFEZo4W1qEKl8Zz27AqvQSAqo+BtIzUCo4aAJMYa56VXS4hudw=="
},
"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.Civil3D.API": {
"type": "Direct",
"requested": "[2026.0.0, )",
"resolved": "2026.0.0",
"contentHash": "JcQvKvA3KC+9hzJiWlaZ3REtvqJV+AFHPIU5J6Xp7JHlNyhnaalN37WXpWIKhNAUwL9ppUBOXMZpQupbFytUwg==",
"dependencies": {
"Speckle.AutoCAD.API": "2026.0.0"
}
},
"Speckle.InterfaceGenerator": {
"type": "Direct",
"requested": "[0.9.6, )",
"resolved": "0.9.6",
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
},
"Speckle.Rhino7.Fakes": {
"type": "Direct",
"requested": "[0.3.1, )",
"resolved": "0.3.1",
"contentHash": "II0zR/4QfPC/j44zfVTSqplZsd/GXHEa4eKRZFdjHuXnXBcd80uObWAb0C2Wm88KSlKOnSYAeQLEMmPjK5Kw3w==",
"dependencies": {
"System.Drawing.Common": "8.0.6"
}
},
"Castle.Core": {
"type": "Transitive",
"resolved": "5.1.1",
"contentHash": "rpYtIczkzGpf+EkZgDr9CClTdemhsrwA/W5hMoPjLkRFnXzH44zDLoovXeKtmxb1ykXK9aJVODSpiJml8CTw2g==",
"dependencies": {
"System.Diagnostics.EventLog": "6.0.0"
}
},
"GraphQL.Client": {
"type": "Transitive",
"resolved": "6.0.0",
@@ -138,11 +84,6 @@
"resolved": "8.0.0",
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
},
"Microsoft.CodeCoverage": {
"type": "Transitive",
"resolved": "17.11.1",
"contentHash": "nPJqrcA5iX+Y0kqoT3a+pD/8lrW/V7ayqnEJQsTonSoPz59J8bmoQhcSN4G8+UJ64Hkuf0zuxnfuj2lkHOq4cA=="
},
"Microsoft.CSharp": {
"type": "Transitive",
"resolved": "4.7.0",
@@ -223,38 +164,6 @@
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Microsoft.TestPlatform.ObjectModel": {
"type": "Transitive",
"resolved": "17.11.1",
"contentHash": "E2jZqAU6JeWEVsyOEOrSW1o1bpHLgb25ypvKNB/moBXPVsFYBPd/Jwi7OrYahG50J83LfHzezYI+GaEkpAotiA==",
"dependencies": {
"System.Reflection.Metadata": "1.6.0"
}
},
"Microsoft.TestPlatform.TestHost": {
"type": "Transitive",
"resolved": "17.11.1",
"contentHash": "DnG+GOqJXO/CkoqlJWeDFTgPhqD/V6VqUIL3vINizCWZ3X+HshCtbbyDdSHQQEjrc2Sl/K3yaxX6s+5LFEdYuw==",
"dependencies": {
"Microsoft.TestPlatform.ObjectModel": "17.11.1",
"Newtonsoft.Json": "13.0.1"
}
},
"Microsoft.Win32.SystemEvents": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "9opKRyOKMCi2xJ7Bj7kxtZ1r9vbzosMvRrdEhVhDz8j8MoBGgB+WmC94yH839NPH+BclAjtQ/pyagvi/8gDLkw=="
},
"Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.1",
"contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A=="
},
"Speckle.DoubleNumerics": {
"type": "Transitive",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
},
"Speckle.Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.2",
@@ -295,27 +204,6 @@
"resolved": "4.5.0",
"contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
},
"System.Configuration.ConfigurationManager": {
"type": "Transitive",
"resolved": "4.4.0",
"contentHash": "gWwQv/Ug1qWJmHCmN17nAbxJYmQBM/E94QxKLksvUiiKB1Ld3Sc/eK1lgmbSjDFxkQhVuayI/cGFZhpBSodLrg==",
"dependencies": {
"System.Security.Cryptography.ProtectedData": "4.4.0"
}
},
"System.Diagnostics.EventLog": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "lcyUiXTsETK2ALsZrX+nWuHSIQeazhqPphLfaRxzdGaG93+0kELqpgEHtwWOlQe7+jSFnKwaCAgL4kjeZCQJnw=="
},
"System.Drawing.Common": {
"type": "Transitive",
"resolved": "8.0.6",
"contentHash": "aSwRnJzz6fZ73JvWMMG0KvBwOnXsBTFtfHLriQyAPrDIZ+NrDfl15GWbO/A35k0dtH77D7jfxzEcFF7RONtU/w==",
"dependencies": {
"Microsoft.Win32.SystemEvents": "8.0.0"
}
},
"System.Memory": {
"type": "Transitive",
"resolved": "4.5.3",
@@ -326,33 +214,61 @@
"resolved": "5.0.0",
"contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ=="
},
"System.Reflection.Metadata": {
"type": "Transitive",
"resolved": "1.6.0",
"contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ=="
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
"resolved": "4.5.1",
"contentHash": "Zh8t8oqolRaFa9vmOZfdQm/qKejdqz0J9kr7o2Fu0vPeoH3BL1EOXipKWwkWtLT1JPzjByrF19fGuFlNbmPpiw=="
},
"System.Security.Cryptography.ProtectedData": {
"type": "Transitive",
"resolved": "4.4.0",
"contentHash": "cJV7ScGW7EhatRsjehfvvYVBvtiSMKgN8bOVI0bQhnF5bU7vnHVIsH49Kva7i7GWaWYvmEzkYVk1TC+gZYBEog=="
"speckle.connectors.common": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.3.5, )",
"Speckle.Sdk": "[3.3.5, )",
"Speckle.Sdk.Dependencies": "[3.3.5, )"
}
},
"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.civil3d2026": {
"type": "Project",
"dependencies": {
"Speckle.AutoCAD.API": "[2026.0.0, )",
"Speckle.Civil3d.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.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"speckle.testing": {
"type": "Project",
"Microsoft.Extensions.DependencyInjection": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==",
"dependencies": {
"Moq": "[4.20.70, )",
"NUnit": "[4.1.0, )"
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0"
}
},
"Microsoft.Extensions.Logging": {
@@ -373,36 +289,61 @@
"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.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "2thsMUDkRr7lR0PXZJ8k3KWZLWjz/aBY0KaO2SuXM0lIKyJw1APMJ7lXJ89e6JAjBzEbK8yLHBb0qtfcc4bNRw==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.219"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "UTgz9UgkMFGqRLmCq1HPo74MngvKbSZOFWaMRzASHrrnsBtzZatBXjoJBlvVoeBCoiea5Jj+BgZg6RvlV2m3sg==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
"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.0.1",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.1.0-dev.219"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "5hqBd9whAs5cC8S/6YUgKFOivjntAkVutKhz06XD/f3Kj6xScT3hwcUaWBxiwK3Mw7FLtiVuU1uG777pjn0PKQ=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
},
"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=="
}
}
}
@@ -0,0 +1,60 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Speckle.Connectors.Autocad.Bindings;
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.Converters.Autocad;
using Speckle.Converters.Civil3dShared;
using Speckle.Converters.Common;
using Speckle.Sdk;
namespace Speckle.Connectors.Civil3dShared.Bindings;
public sealed class Civil3dReceiveBinding : AutocadReceiveBaseBinding
{
private readonly ICivil3dConversionSettingsFactory _civil3dConversionSettingsFactory;
private readonly IAutocadConversionSettingsFactory _autocadConversionSettingsFactory;
public Civil3dReceiveBinding(
DocumentModelStore store,
IBrowserBridge parent,
ICancellationManager cancellationManager,
IServiceProvider serviceProvider,
IOperationProgressManager operationProgressManager,
ILogger<AutocadReceiveBinding> logger,
ICivil3dConversionSettingsFactory civil3dConversionSettingsFactory,
IAutocadConversionSettingsFactory autocadConversionSettingsFactory,
ISpeckleApplication speckleApplication,
IThreadContext threadContext
)
: base(
store,
parent,
cancellationManager,
serviceProvider,
operationProgressManager,
logger,
speckleApplication,
threadContext
)
{
_civil3dConversionSettingsFactory = civil3dConversionSettingsFactory;
_autocadConversionSettingsFactory = autocadConversionSettingsFactory;
}
// POC: we're registering the conversion settings for autocad here because we need the autocad conversion settings to be able to use the autocad typed converters.
// POC: We need a separate receive binding for civil3d due to using a different unit converter (needed for conversion settings construction)
protected override void InitializeSettings(IServiceProvider serviceProvider)
{
serviceProvider
.GetRequiredService<IConverterSettingsStore<Civil3dConversionSettings>>()
.Initialize(_civil3dConversionSettingsFactory.Create(Application.DocumentManager.CurrentDocument));
serviceProvider
.GetRequiredService<IConverterSettingsStore<AutocadConversionSettings>>()
.Initialize(_autocadConversionSettingsFactory.Create(Application.DocumentManager.CurrentDocument));
}
}
@@ -1,9 +1,9 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Speckle.Connectors.Autocad.Bindings;
using Speckle.Connectors.Autocad.HostApp;
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;
@@ -22,21 +22,22 @@ public sealed class Civil3dSendBinding : AutocadSendBaseBinding
public Civil3dSendBinding(
DocumentModelStore store,
IAutocadIdleManager idleManager,
IBrowserBridge parent,
IEnumerable<ISendFilter> sendFilters,
CancellationManager cancellationManager,
ICancellationManager cancellationManager,
IServiceProvider serviceProvider,
ISendConversionCache sendConversionCache,
IOperationProgressManager operationProgressManager,
ILogger<AutocadSendBinding> logger,
ICivil3dConversionSettingsFactory civil3dConversionSettingsFactory,
IAutocadConversionSettingsFactory autocadConversionSettingsFactory,
ISpeckleApplication speckleApplication
ISpeckleApplication speckleApplication,
IThreadContext threadContext,
ITopLevelExceptionHandler topLevelExceptionHandler,
IAppIdleManager appIdleManager
)
: base(
store,
idleManager,
parent,
sendFilters,
cancellationManager,
@@ -44,7 +45,10 @@ public sealed class Civil3dSendBinding : AutocadSendBaseBinding
sendConversionCache,
operationProgressManager,
logger,
speckleApplication
speckleApplication,
threadContext,
topLevelExceptionHandler,
appIdleManager
)
{
_civil3dConversionSettingsFactory = civil3dConversionSettingsFactory;
@@ -6,7 +6,6 @@ using Speckle.Connectors.Civil3dShared.Bindings;
using Speckle.Connectors.Civil3dShared.Operations.Send;
using Speckle.Connectors.Common.Builders;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Converters.Civil3dShared.Helpers;
using Speckle.Converters.Civil3dShared.ToSpeckle;
using Speckle.Sdk;
@@ -17,18 +16,20 @@ public static class Civil3dConnectorModule
public static void AddCivil3d(this IServiceCollection serviceCollection)
{
serviceCollection.AddAutocadBase();
serviceCollection.LoadSend();
// register civil specific send classes
// add send
serviceCollection.LoadSend();
serviceCollection.AddScoped<IRootObjectBuilder<AutocadRootObject>, Civil3dRootObjectBuilder>();
serviceCollection.AddSingleton<IBinding, Civil3dSendBinding>();
// automatically detects the Class:IClass interface pattern to register all generated interfaces
serviceCollection.AddMatchingInterfacesAsTransient(Assembly.GetExecutingAssembly());
// add receive
serviceCollection.LoadReceive();
serviceCollection.AddSingleton<IBinding, Civil3dReceiveBinding>();
// additional classes
serviceCollection.AddScoped<PropertySetDefinitionHandler>();
serviceCollection.AddScoped<CatchmentGroupHandler>();
serviceCollection.AddScoped<PipeNetworkHandler>();
// automatically detects the Class:IClass interface pattern to register all generated interfaces
serviceCollection.AddMatchingInterfacesAsTransient(Assembly.GetExecutingAssembly());
}
}
@@ -4,7 +4,6 @@ using Speckle.Connectors.Autocad.HostApp;
using Speckle.Connectors.Autocad.Operations.Send;
using Speckle.Connectors.Common.Caching;
using Speckle.Connectors.Common.Operations;
using Speckle.Converters.Civil3dShared.Helpers;
using Speckle.Converters.Civil3dShared.ToSpeckle;
using Speckle.Converters.Common;
using Speckle.Sdk.Logging;
@@ -16,14 +15,10 @@ public sealed class Civil3dRootObjectBuilder : AutocadRootObjectBaseBuilder
{
private readonly AutocadLayerUnpacker _layerUnpacker;
private readonly PropertySetDefinitionHandler _propertySetDefinitionHandler;
private readonly CatchmentGroupHandler _catchmentGroupHandler;
private readonly PipeNetworkHandler _pipeNetworkHandler;
public Civil3dRootObjectBuilder(
AutocadLayerUnpacker layerUnpacker,
PropertySetDefinitionHandler propertySetDefinitionHandler,
CatchmentGroupHandler catchmentGroupHandler,
PipeNetworkHandler pipeNetworkHandler,
IRootToSpeckleConverter converter,
ISendConversionCache sendConversionCache,
AutocadInstanceUnpacker instanceObjectManager,
@@ -46,8 +41,6 @@ public sealed class Civil3dRootObjectBuilder : AutocadRootObjectBaseBuilder
{
_layerUnpacker = layerUnpacker;
_propertySetDefinitionHandler = propertySetDefinitionHandler;
_catchmentGroupHandler = catchmentGroupHandler;
_pipeNetworkHandler = pipeNetworkHandler;
}
public override (Collection, LayerTableRecord?) CreateObjectCollection(Entity entity, Transaction tr)
@@ -57,11 +50,8 @@ public sealed class Civil3dRootObjectBuilder : AutocadRootObjectBaseBuilder
return (layer, autocadLayer);
}
// POC: probably will need to add Network proxies as well
public override void AddAdditionalProxiesToRoot(Collection rootObject)
{
rootObject[ProxyKeys.PROPERTYSET_DEFINITIONS] = _propertySetDefinitionHandler.Definitions;
rootObject["catchmentGroupProxies"] = _catchmentGroupHandler.CatchmentGroupProxiesCache.Values.ToList();
rootObject["pipeNetworkProxies"] = _pipeNetworkHandler.PipeNetworkProxiesCache.Values.ToList();
}
}
@@ -9,13 +9,13 @@
<Import_RootNamespace>Speckle.Connectors.Civil3dShared</Import_RootNamespace>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)Bindings\Civil3dReceiveBinding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)DependencyInjection\Civil3dConnectorModule.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\Civil3dRootObjectBuilder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bindings\Civil3dSendBinding.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="$(MSBuildThisFileDirectory)DependencyInjection\" />
<Folder Include="$(MSBuildThisFileDirectory)Bindings\" />
<Folder Include="$(MSBuildThisFileDirectory)Operations\Send\" />
</ItemGroup>
</Project>
@@ -1,4 +1,5 @@
using Speckle.Connectors.DUI.Bindings;
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;
@@ -10,7 +11,8 @@ public class CsiSharedBasicConnectorBinding : IBasicConnectorBinding
{
private readonly ISpeckleApplication _speckleApplication;
private readonly DocumentModelStore _store;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
private readonly IThreadContext _threadContext;
public string Name => "baseBinding";
public IBrowserBridge Parent { get; }
public BasicConnectorBindingCommands Commands { get; }
@@ -18,13 +20,27 @@ public class CsiSharedBasicConnectorBinding : IBasicConnectorBinding
public CsiSharedBasicConnectorBinding(
IBrowserBridge parent,
ISpeckleApplication speckleApplication,
DocumentModelStore store
DocumentModelStore store,
ITopLevelExceptionHandler topLevelExceptionHandler,
IThreadContext threadContext
)
{
_threadContext = threadContext;
Parent = parent;
_speckleApplication = speckleApplication;
_store = store;
Commands = new BasicConnectorBindingCommands(parent);
_topLevelExceptionHandler = topLevelExceptionHandler;
Commands = new BasicConnectorBindingCommands(Parent);
_store.DocumentChanged += (_, _) =>
_topLevelExceptionHandler.FireAndForget(async () =>
{
// enforce main thread
await _threadContext.RunOnMainAsync(async () =>
{
await Commands.NotifyDocumentChanged();
});
});
}
public string GetConnectorVersion() => _speckleApplication.SpeckleVersion;
@@ -33,15 +49,24 @@ public class CsiSharedBasicConnectorBinding : IBasicConnectorBinding
public string GetSourceApplicationVersion() => _speckleApplication.HostApplicationVersion;
public DocumentInfo? GetDocumentInfo() => new DocumentInfo("ETABS Model", "ETABS Model", "1");
public DocumentInfo? GetDocumentInfo() => new("ETABS Model", "ETABS Model", "1");
public DocumentModelStore GetDocumentState() => _store;
public void AddModel(ModelCard model) => _store.AddModel(model);
/// <remarks>Operations must run on the main thread for ETABS and SAP 2000</remarks>
public void AddModel(ModelCard model) =>
_topLevelExceptionHandler.CatchUnhandled(() => _threadContext.RunOnThread(() => _store.AddModel(model), true));
public void UpdateModel(ModelCard model) => _store.UpdateModel(model);
/// <remarks>Operations must run on the main thread for ETABS and SAP 2000</remarks>
public void UpdateModel(ModelCard model) =>
_topLevelExceptionHandler.CatchUnhandled(() => _threadContext.RunOnThread(() => _store.UpdateModel(model), true));
public void RemoveModel(ModelCard model) => _store.RemoveModel(model);
/// <remarks>Operations must run on the main thread for ETABS and SAP 2000</remarks>
public void RemoveModel(ModelCard model) =>
_topLevelExceptionHandler.CatchUnhandled(() => _threadContext.RunOnThread(() => _store.RemoveModel(model), true));
public void RemoveModels(List<ModelCard> models) =>
_topLevelExceptionHandler.CatchUnhandled(() => _threadContext.RunOnThread(() => _store.RemoveModels(models), true));
public Task HighlightModel(string modelCardId) => Task.CompletedTask;
@@ -1,20 +1,78 @@
using Speckle.Connectors.CSiShared.HostApp;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.CSiShared.HostApp;
using Speckle.Connectors.CSiShared.Utils;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Converters.CSiShared.Utils;
using Timer = System.Timers.Timer;
namespace Speckle.Connectors.CSiShared.Bindings;
public class CsiSharedSelectionBinding : ISelectionBinding
public class CsiSharedSelectionBinding : ISelectionBinding, IDisposable
{
public string Name => "selectionBinding";
public IBrowserBridge Parent { get; }
private bool _disposed;
private readonly Timer _selectionTimer;
private readonly ICsiApplicationService _csiApplicationService;
private readonly IThreadContext _threadContext;
private HashSet<string> _lastSelection = new();
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
public CsiSharedSelectionBinding(IBrowserBridge parent, ICsiApplicationService csiApplicationService)
public IBrowserBridge Parent { get; }
public string Name => "selectionBinding";
public CsiSharedSelectionBinding(
IBrowserBridge parent,
ICsiApplicationService csiApplicationService,
ITopLevelExceptionHandler topLevelExceptionHandler,
IThreadContext threadContext
)
{
_threadContext = threadContext;
Parent = parent;
_csiApplicationService = csiApplicationService;
_topLevelExceptionHandler = topLevelExceptionHandler;
_selectionTimer = new Timer(1000);
_selectionTimer.Elapsed += (_, _) =>
_topLevelExceptionHandler.CatchUnhandled(() => _threadContext.RunOnMain(CheckSelectionChanged));
_selectionTimer.Start();
}
private void CheckSelectionChanged()
{
// timer callbacks are on a background thread, but CSI API calls must be on main thread
var currentSelection = GetSelection();
var currentIds = new HashSet<string>(currentSelection.SelectedObjectIds);
if (!_lastSelection.SetEquals(currentIds))
{
_lastSelection = currentIds;
// ensure UI updates also run on main thread
_threadContext.RunOnMain(
() =>
_topLevelExceptionHandler.CatchUnhandled(
() => Parent.Send(SelectionBindingEvents.SET_SELECTION, currentSelection)
)
);
}
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_selectionTimer?.Dispose();
}
_disposed = true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
@@ -25,42 +83,26 @@ public class CsiSharedSelectionBinding : ISelectionBinding
/// </remarks>
public SelectionInfo GetSelection()
{
// TODO: Since this is standard across CSi Suite - better stored in an enum?
var objectTypeMap = new Dictionary<int, string>
{
{ 1, "Point" },
{ 2, "Frame" },
{ 3, "Cable" },
{ 4, "Tendon" },
{ 5, "Area" },
{ 6, "Solid" },
{ 7, "Link" }
};
int numberItems = 0;
int[] objectType = Array.Empty<int>();
string[] objectName = Array.Empty<string>();
int[] objectType = [];
string[] objectName = [];
_csiApplicationService.SapModel.SelectObj.GetSelected(ref numberItems, ref objectType, ref objectName);
var encodedIds = new List<string>(numberItems);
var typeCounts = new Dictionary<string, int>();
for (int i = 0; i < numberItems; i++)
{
var typeKey = objectType[i];
var typeName = objectTypeMap.TryGetValue(typeKey, out var name) ? name : $"Unknown ({typeKey})";
encodedIds.Add(ObjectIdentifier.Encode(typeKey, objectName[i]));
var typeKey = (ModelObjectType)objectType[i];
var typeName = typeKey.ToString();
encodedIds.Add(ObjectIdentifier.Encode(objectType[i], objectName[i]));
typeCounts[typeName] = (typeCounts.TryGetValue(typeName, out var count) ? count : 0) + 1; // NOTE: Cross-framework compatibility (net 48 and net8)
}
var summary =
encodedIds.Count == 0
? "No objects selected."
: $"{encodedIds.Count} objects ({string.Join(", ",
typeCounts.Select(kv => $"{kv.Value} {kv.Key}"))})";
return new SelectionInfo(encodedIds, summary);
}
}
@@ -27,10 +27,9 @@ public sealed class CsiSharedSendBinding : ISendBinding
public IBrowserBridge Parent { get; }
private readonly DocumentModelStore _store;
private readonly IAppIdleManager _idleManager;
private readonly IServiceProvider _serviceProvider;
private readonly List<ISendFilter> _sendFilters;
private readonly CancellationManager _cancellationManager;
private readonly ICancellationManager _cancellationManager;
private readonly IOperationProgressManager _operationProgressManager;
private readonly ILogger<CsiSharedSendBinding> _logger;
private readonly ICsiApplicationService _csiApplicationService;
@@ -40,11 +39,10 @@ public sealed class CsiSharedSendBinding : ISendBinding
public CsiSharedSendBinding(
DocumentModelStore store,
IAppIdleManager idleManager,
IBrowserBridge parent,
IEnumerable<ISendFilter> sendFilters,
IServiceProvider serviceProvider,
CancellationManager cancellationManager,
ICancellationManager cancellationManager,
IOperationProgressManager operationProgressManager,
ILogger<CsiSharedSendBinding> logger,
ICsiConversionSettingsFactory csiConversionSettingsFactory,
@@ -54,7 +52,6 @@ public sealed class CsiSharedSendBinding : ISendBinding
)
{
_store = store;
_idleManager = idleManager;
_serviceProvider = serviceProvider;
_sendFilters = sendFilters.ToList();
_cancellationManager = cancellationManager;
@@ -87,7 +84,7 @@ public sealed class CsiSharedSendBinding : ISendBinding
.ServiceProvider.GetRequiredService<IConverterSettingsStore<CsiConversionSettings>>()
.Initialize(_csiConversionSettingsFactory.Create(_csiApplicationService.SapModel));
CancellationToken cancellationToken = _cancellationManager.InitCancellationTokenSource(modelCardId);
using var cancellationItem = _cancellationManager.GetCancellationItem(modelCardId);
List<ICsiWrapper> wrappers = modelCard
.SendFilter.NotNull()
@@ -104,15 +101,12 @@ public sealed class CsiSharedSendBinding : ISendBinding
.ServiceProvider.GetRequiredService<SendOperation<ICsiWrapper>>()
.Execute(
wrappers,
modelCard.GetSendInfo(_speckleApplication.Slug),
_operationProgressManager.CreateOperationProgressEventHandler(Parent, modelCardId, cancellationToken),
cancellationToken
)
.ConfigureAwait(false);
modelCard.GetSendInfo(_speckleApplication.ApplicationAndVersion),
_operationProgressManager.CreateOperationProgressEventHandler(Parent, modelCardId, cancellationItem.Token),
cancellationItem.Token
);
await Commands
.SetModelSendResult(modelCardId, sendResult.RootObjId, sendResult.ConversionResults)
.ConfigureAwait(false);
await Commands.SetModelSendResult(modelCardId, sendResult.RootObjId, sendResult.ConversionResults);
}
catch (OperationCanceledException)
{
@@ -121,7 +115,7 @@ public sealed class CsiSharedSendBinding : ISendBinding
catch (Exception ex) when (!ex.IsFatal())
{
_logger.LogModelCardHandledError(ex);
await Commands.SetModelError(modelCardId, ex).ConfigureAwait(false);
await Commands.SetModelError(modelCardId, ex);
}
}
@@ -13,22 +13,4 @@ namespace Speckle.Connectors.CSiShared.HostApp;
public interface ICsiApplicationService
{
cSapModel SapModel { get; }
void Initialize(cSapModel sapModel, cPluginCallback pluginCallback);
}
public class CsiApplicationService : ICsiApplicationService
{
public cSapModel SapModel { get; private set; }
private cPluginCallback _pluginCallback;
public CsiApplicationService()
{
SapModel = null!;
}
public void Initialize(cSapModel sapModel, cPluginCallback pluginCallback)
{
SapModel = sapModel;
_pluginCallback = pluginCallback;
}
}
@@ -1,46 +1,100 @@
using System.IO;
using Microsoft.Extensions.Logging;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Utils;
using Speckle.Sdk;
using Speckle.Sdk.Helpers;
using Speckle.Sdk.Logging;
using Timer = System.Timers.Timer;
namespace Speckle.Connectors.CSiShared.HostApp;
public class CsiDocumentModelStore : DocumentModelStore
public class CsiDocumentModelStore : DocumentModelStore, IDisposable
{
private readonly ISpeckleApplication _speckleApplication;
private readonly ILogger<CsiDocumentModelStore> _logger;
private readonly ICsiApplicationService _csiApplicationService;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
private readonly IThreadContext _threadContext;
private readonly Timer _modelCheckTimer;
private string _lastModelFilename = string.Empty;
private bool _disposed;
private string HostAppUserDataPath { get; set; }
private string DocumentStateFile { get; set; }
private string ModelPathHash { get; set; }
public CsiDocumentModelStore(
IJsonSerializer jsonSerializerSettings,
ILogger<DocumentModelStore> baseLogger,
IJsonSerializer jsonSerializer,
ISpeckleApplication speckleApplication,
ILogger<CsiDocumentModelStore> logger,
ICsiApplicationService csiApplicationService
ICsiApplicationService csiApplicationService,
ITopLevelExceptionHandler topLevelExceptionHandler,
IThreadContext threadContext
)
: base(jsonSerializerSettings)
: base(baseLogger, jsonSerializer)
{
_threadContext = threadContext;
_speckleApplication = speckleApplication;
_logger = logger;
_csiApplicationService = csiApplicationService;
_topLevelExceptionHandler = topLevelExceptionHandler;
// initialize timer to check for model changes
_modelCheckTimer = new Timer(1000);
// timer runs on background thread but model checks must be on main thread
_modelCheckTimer.Elapsed += (_, _) =>
_topLevelExceptionHandler.CatchUnhandled(() => _threadContext.RunOnMain(CheckModelChanges));
_modelCheckTimer.Start();
}
private void CheckModelChanges()
{
string currentFilename = _csiApplicationService.SapModel.GetModelFilename();
if (string.IsNullOrEmpty(currentFilename) || currentFilename == _lastModelFilename)
{
return;
}
_lastModelFilename = currentFilename;
SetPaths();
LoadState();
OnDocumentChanged();
}
public override Task OnDocumentStoreInitialized()
{
var currentFilename = _csiApplicationService.SapModel.GetModelFilename();
if (!string.IsNullOrEmpty(currentFilename))
{
_lastModelFilename = currentFilename;
SetPaths();
LoadState();
}
return Task.CompletedTask;
}
private void SetPaths()
{
ModelPathHash = Crypt.Md5(_csiApplicationService.SapModel.GetModelFilepath(), length: 32);
HostAppUserDataPath = Path.Combine(
SpecklePathProvider.UserSpeckleFolderPath,
"ConnectorsFileData",
_speckleApplication.Slug
);
DocumentStateFile = Path.Combine(HostAppUserDataPath, $"{ModelPathHash}.json");
try
{
ModelPathHash = Crypt.Md5(_csiApplicationService.SapModel.GetModelFilename(), length: 32);
HostAppUserDataPath = Path.Combine(
SpecklePathProvider.UserSpeckleFolderPath,
"ConnectorsFileData",
_speckleApplication.Slug
);
DocumentStateFile = Path.Combine(HostAppUserDataPath, $"{ModelPathHash}.json");
_logger.LogDebug($"Paths set - Hash: {ModelPathHash}, File: {DocumentStateFile}");
}
catch (Exception ex) when (!ex.IsFatal())
{
_logger.LogError(ex, "Error in setting paths for CsiDocumentModelStore");
}
}
protected override void HostAppSaveState(string modelCardState)
@@ -51,29 +105,53 @@ public class CsiDocumentModelStore : DocumentModelStore
{
Directory.CreateDirectory(HostAppUserDataPath);
}
File.WriteAllText(DocumentStateFile, modelCardState);
}
catch (Exception ex) when (!ex.IsFatal())
{
_logger.LogError(ex.Message);
_logger.LogError(ex, "Failed to save state");
}
}
protected override void LoadState()
{
if (!Directory.Exists(HostAppUserDataPath))
try
{
if (!File.Exists(DocumentStateFile))
{
ClearAndSave();
return;
}
string serializedState = File.ReadAllText(DocumentStateFile);
LoadFromString(serializedState);
}
catch (Exception ex) when (!ex.IsFatal())
{
_logger.LogError(ex, "Failed to load state, initializing empty state");
ClearAndSave();
}
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
if (!File.Exists(DocumentStateFile))
if (disposing)
{
ClearAndSave();
return;
_modelCheckTimer.Dispose();
}
string serializedState = File.ReadAllText(DocumentStateFile);
LoadFromString(serializedState);
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
@@ -1,20 +0,0 @@
using Speckle.Connectors.DUI.Bridge;
namespace Speckle.Connectors.CSiShared.HostApp;
public sealed class CsiIdleManager : AppIdleManager
{
private readonly IIdleCallManager _idleCallManager;
public CsiIdleManager(IIdleCallManager idleCallManager)
: base(idleCallManager)
{
_idleCallManager = idleCallManager;
}
protected override void AddEvent()
{
// TODO: CSi specific idle handling can be added here if needed
_idleCallManager.AppOnIdle(() => { });
}
}
@@ -0,0 +1,115 @@
using Speckle.Converters.Common;
using Speckle.Converters.CSiShared;
using Speckle.Converters.CSiShared.Utils;
namespace Speckle.Connectors.CSiShared.HostApp.Helpers;
/// <summary>
/// Base frame section property extractor for CSi products.
/// </summary>
/// <remarks>
/// Handles common Csi API calls for frame section properties
/// Provides foundation for application-specific extractors.
/// </remarks>
public class CsiFrameSectionPropertyExtractor : IFrameSectionPropertyExtractor
{
private readonly IConverterSettingsStore<CsiConversionSettings> _settingsStore;
public CsiFrameSectionPropertyExtractor(IConverterSettingsStore<CsiConversionSettings> settingsStore)
{
_settingsStore = settingsStore;
}
public void ExtractProperties(string sectionName, Dictionary<string, object?> properties)
{
GetMaterialName(sectionName, properties);
GetSectionProperties(sectionName, properties);
GetPropertyModifiers(sectionName, properties);
}
private void GetMaterialName(string sectionName, Dictionary<string, object?> properties)
{
// get material name
string materialName = string.Empty;
_settingsStore.Current.SapModel.PropFrame.GetMaterial(sectionName, ref materialName);
// append to General Data of properties dictionary
Dictionary<string, object?> generalData = properties.EnsureNested(SectionPropertyCategory.GENERAL_DATA);
generalData["Material"] = materialName;
}
private void GetSectionProperties(string sectionName, Dictionary<string, object?> properties)
{
double crossSectionalArea = 0,
shearAreaInMajorAxisDirection = 0,
shearAreaInMinorAxisDirection = 0,
torsionalConstant = 0,
momentOfInertiaAboutMajorAxis = 0,
momentOfInertiaAboutMinorAxis = 0,
sectionModulusAboutMajorAxis = 0,
sectionModulusAboutMinorAxis = 0,
plasticModulusAboutMajorAxis = 0,
plasticModulusAboutMinorAxis = 0,
radiusOfGyrationAboutMajorAxis = 0,
radiusOfGyrationAboutMinorAxis = 0;
_settingsStore.Current.SapModel.PropFrame.GetSectProps(
sectionName,
ref crossSectionalArea,
ref shearAreaInMajorAxisDirection,
ref shearAreaInMinorAxisDirection,
ref torsionalConstant,
ref momentOfInertiaAboutMajorAxis,
ref momentOfInertiaAboutMinorAxis,
ref sectionModulusAboutMajorAxis,
ref sectionModulusAboutMinorAxis,
ref plasticModulusAboutMajorAxis,
ref plasticModulusAboutMinorAxis,
ref radiusOfGyrationAboutMajorAxis,
ref radiusOfGyrationAboutMinorAxis
);
string distanceUnit = _settingsStore.Current.SpeckleUnits;
string areaUnit = $"{distanceUnit}²"; // // TODO: Formalize this better
string modulusUnit = $"{distanceUnit}³"; // // TODO: Formalize this better
string inertiaUnit = $"{distanceUnit}\u2074"; // TODO: Formalize this better
Dictionary<string, object?> mechanicalProperties = properties.EnsureNested(
SectionPropertyCategory.SECTION_PROPERTIES
);
mechanicalProperties.AddWithUnits("Area", crossSectionalArea, areaUnit);
mechanicalProperties.AddWithUnits("As2", shearAreaInMajorAxisDirection, areaUnit);
mechanicalProperties.AddWithUnits("As3", shearAreaInMinorAxisDirection, areaUnit);
mechanicalProperties.AddWithUnits("J", torsionalConstant, inertiaUnit);
mechanicalProperties.AddWithUnits("I22", momentOfInertiaAboutMajorAxis, inertiaUnit);
mechanicalProperties.AddWithUnits("I33", momentOfInertiaAboutMinorAxis, inertiaUnit);
mechanicalProperties.AddWithUnits("S22", sectionModulusAboutMajorAxis, modulusUnit);
mechanicalProperties.AddWithUnits("S33", sectionModulusAboutMinorAxis, modulusUnit);
mechanicalProperties.AddWithUnits("Z22", plasticModulusAboutMajorAxis, modulusUnit);
mechanicalProperties.AddWithUnits("Z33", plasticModulusAboutMinorAxis, modulusUnit);
mechanicalProperties.AddWithUnits("R22", radiusOfGyrationAboutMajorAxis, distanceUnit);
mechanicalProperties.AddWithUnits("R33", radiusOfGyrationAboutMinorAxis, distanceUnit);
}
private void GetPropertyModifiers(string sectionName, Dictionary<string, object?> properties)
{
double[] stiffnessModifiersArray = [];
_settingsStore.Current.SapModel.PropFrame.GetModifiers(sectionName, ref stiffnessModifiersArray);
Dictionary<string, object?> modifiers =
new()
{
["Cross-section (Axial) Area"] = stiffnessModifiersArray[0],
["Shear Area in 2 Direction"] = stiffnessModifiersArray[1],
["Shear Area in 3 Direction"] = stiffnessModifiersArray[2],
["Torsional Constant"] = stiffnessModifiersArray[3],
["Moment of Inertia about 2 Axis"] = stiffnessModifiersArray[4],
["Moment of Inertia about 3 Axis"] = stiffnessModifiersArray[5],
["Mass"] = stiffnessModifiersArray[6],
["Weight"] = stiffnessModifiersArray[7],
};
Dictionary<string, object?> generalData = properties.EnsureNested(SectionPropertyCategory.GENERAL_DATA);
generalData["Modifiers"] = modifiers;
}
}
@@ -0,0 +1,212 @@
using Speckle.Converters.Common;
using Speckle.Converters.CSiShared;
using Speckle.Converters.CSiShared.Utils;
namespace Speckle.Connectors.CSiShared.HostApp.Helpers;
/// <summary>
/// Base material property extractor for CSi products.
/// </summary>
/// <remarks>
/// Currently, all material property extraction can happen on a CsiShared level which simplifies things a lot.
/// Properties depend on the directional symmetry of the material, hence the switch statements.
/// </remarks>
public class CsiMaterialPropertyExtractor
{
/// <summary>
/// Property strings for all mechanical properties, used by numerous methods.
/// </summary>
private static class MechanicalPropertyNames
{
public const string MODULUS_OF_ELASTICITY = "Modulus of Elasticity, E";
public const string MODULUS_OF_ELASTICITY_ARRAY = "Modulus of Elasticity Array, E";
public const string POISSON_RATIO = "Poisson's Ratio, U";
public const string POISSON_RATIO_ARRAY = "Poisson's Ratio Array, U";
public const string THERMAL_COEFFICIENT = "Coefficient of Thermal Expansion, A";
public const string THERMAL_COEFFICIENT_ARRAY = "Coefficient of Thermal Expansion Array, A";
public const string SHEAR_MODULUS = "Shear Modulus, G";
public const string SHEAR_MODULUS_ARRAY = "Shear Modulus Array, G";
}
private readonly IConverterSettingsStore<CsiConversionSettings> _settingsStore;
public CsiMaterialPropertyExtractor(IConverterSettingsStore<CsiConversionSettings> settingsStore)
{
_settingsStore = settingsStore;
}
public void ExtractProperties(string materialName, Dictionary<string, object?> properties)
{
GetGeneralProperties(materialName, properties);
GetWeightAndMassProperties(materialName, properties); // TODO: Add units
GetMechanicalProperties(materialName, properties); // TODO: Add units
}
private void GetGeneralProperties(string materialName, Dictionary<string, object?> properties)
{
{
eMatType materialType = default;
int materialColor = 0;
string materialNotes = string.Empty;
string materialGuid = string.Empty;
_settingsStore.Current.SapModel.PropMaterial.GetMaterial(
materialName,
ref materialType,
ref materialColor,
ref materialNotes,
ref materialGuid
);
var generalData = properties.EnsureNested(SectionPropertyCategory.GENERAL_DATA);
generalData["Name"] = materialName;
generalData["Type"] = materialType.ToString();
generalData["Notes"] = materialNotes;
}
}
private void GetWeightAndMassProperties(string materialName, Dictionary<string, object?> properties)
{
double weightPerUnitVolume = double.NaN;
double massPerUnitVolume = double.NaN;
_settingsStore.Current.SapModel.PropMaterial.GetWeightAndMass(
materialName,
ref weightPerUnitVolume,
ref massPerUnitVolume
);
var weightAndMass = properties.EnsureNested("Weight and Mass");
weightAndMass["Weight per Unit Volume"] = weightPerUnitVolume;
weightAndMass["Mass per Unit Volume"] = massPerUnitVolume;
}
private void GetMechanicalProperties(string materialName, Dictionary<string, object?> properties)
{
int materialDirectionalSymmetryKey = 0;
eMatType materialType = default;
_settingsStore.Current.SapModel.PropMaterial.GetTypeOAPI(
materialName,
ref materialType,
ref materialDirectionalSymmetryKey
);
var materialDirectionalSymmetryValue = materialDirectionalSymmetryKey switch
{
0 => DirectionalSymmetryType.ISOTROPIC,
1 => DirectionalSymmetryType.ORTHOTROPIC,
2 => DirectionalSymmetryType.ANISOTROPIC,
3 => DirectionalSymmetryType.UNIAXIAL,
_ => throw new ArgumentException($"Unknown symmetry type: {materialDirectionalSymmetryKey}")
};
var mechanicalProperties = properties.EnsureNested("Mechanical Properties");
mechanicalProperties["Directional Symmetry Type"] = materialDirectionalSymmetryValue.ToString();
GetMechanicalPropertiesByType(materialName, materialDirectionalSymmetryValue, mechanicalProperties);
}
private void GetMechanicalPropertiesByType(
string materialName,
DirectionalSymmetryType directionalSymmetryType,
Dictionary<string, object?> mechanicalProperties
)
{
switch (directionalSymmetryType)
{
case DirectionalSymmetryType.ISOTROPIC:
ExtractIsotropicProperties(materialName, mechanicalProperties);
break;
case DirectionalSymmetryType.ORTHOTROPIC:
ExtractOrthotropicProperties(materialName, mechanicalProperties);
break;
case DirectionalSymmetryType.ANISOTROPIC:
ExtractAnisotropicProperties(materialName, mechanicalProperties);
break;
case DirectionalSymmetryType.UNIAXIAL:
ExtractUniaxialProperties(materialName, mechanicalProperties);
break;
default:
throw new ArgumentException($"Unknown directional symmetry type: {directionalSymmetryType}");
}
}
private void ExtractIsotropicProperties(string materialName, Dictionary<string, object?> mechanicalProperties)
{
double modulusOfElasticity = double.NaN;
double poissonRatio = double.NaN;
double thermalCoefficient = double.NaN;
double shearModulus = double.NaN;
_settingsStore.Current.SapModel.PropMaterial.GetMPIsotropic(
materialName,
ref modulusOfElasticity,
ref poissonRatio,
ref thermalCoefficient,
ref shearModulus
);
mechanicalProperties[MechanicalPropertyNames.MODULUS_OF_ELASTICITY] = modulusOfElasticity;
mechanicalProperties[MechanicalPropertyNames.POISSON_RATIO] = poissonRatio;
mechanicalProperties[MechanicalPropertyNames.THERMAL_COEFFICIENT] = thermalCoefficient;
mechanicalProperties[MechanicalPropertyNames.SHEAR_MODULUS] = shearModulus;
}
private void ExtractOrthotropicProperties(string materialName, Dictionary<string, object?> mechanicalProperties)
{
double[] modulusOfElasticityArray = [];
double[] poissonRatioArray = [];
double[] thermalCoefficientArray = [];
double[] shearModulusArray = [];
_settingsStore.Current.SapModel.PropMaterial.GetMPOrthotropic(
materialName,
ref modulusOfElasticityArray,
ref poissonRatioArray,
ref thermalCoefficientArray,
ref shearModulusArray
);
mechanicalProperties[MechanicalPropertyNames.MODULUS_OF_ELASTICITY_ARRAY] = modulusOfElasticityArray;
mechanicalProperties[MechanicalPropertyNames.POISSON_RATIO_ARRAY] = poissonRatioArray;
mechanicalProperties[MechanicalPropertyNames.THERMAL_COEFFICIENT_ARRAY] = thermalCoefficientArray;
mechanicalProperties[MechanicalPropertyNames.SHEAR_MODULUS_ARRAY] = shearModulusArray;
}
private void ExtractAnisotropicProperties(string materialName, Dictionary<string, object?> mechanicalProperties)
{
double[] modulusOfElasticityArray = [];
double[] poissonRatioArray = [];
double[] thermalCoefficientArray = [];
double[] shearModulusArray = [];
_settingsStore.Current.SapModel.PropMaterial.GetMPAnisotropic(
materialName,
ref modulusOfElasticityArray,
ref poissonRatioArray,
ref thermalCoefficientArray,
ref shearModulusArray
);
mechanicalProperties[MechanicalPropertyNames.MODULUS_OF_ELASTICITY_ARRAY] = modulusOfElasticityArray;
mechanicalProperties[MechanicalPropertyNames.POISSON_RATIO_ARRAY] = poissonRatioArray;
mechanicalProperties[MechanicalPropertyNames.THERMAL_COEFFICIENT_ARRAY] = thermalCoefficientArray;
mechanicalProperties[MechanicalPropertyNames.SHEAR_MODULUS_ARRAY] = shearModulusArray;
}
private void ExtractUniaxialProperties(string materialName, Dictionary<string, object?> mechanicalProperties)
{
double modulusOfElasticity = double.NaN;
double thermalCoefficient = double.NaN;
_settingsStore.Current.SapModel.PropMaterial.GetMPUniaxial(
materialName,
ref modulusOfElasticity,
ref thermalCoefficient
);
mechanicalProperties[MechanicalPropertyNames.MODULUS_OF_ELASTICITY] = modulusOfElasticity;
mechanicalProperties[MechanicalPropertyNames.THERMAL_COEFFICIENT] = thermalCoefficient;
}
}
@@ -0,0 +1,68 @@
using Speckle.Converters.Common;
using Speckle.Converters.CSiShared;
using Speckle.Converters.CSiShared.Utils;
namespace Speckle.Connectors.CSiShared.HostApp.Helpers;
/// <summary>
/// Base shell section property extractor for CSi products.
/// </summary>
/// <remarks>
/// Handles common Csi API calls for shell section properties.
/// Provides foundation for application-specific extractors.
/// </remarks>
public class CsiShellSectionPropertyExtractor : IShellSectionPropertyExtractor
{
private readonly IConverterSettingsStore<CsiConversionSettings> _settingsStore;
public CsiShellSectionPropertyExtractor(IConverterSettingsStore<CsiConversionSettings> settingsStore)
{
_settingsStore = settingsStore;
}
public void ExtractProperties(string sectionName, Dictionary<string, object?> properties)
{
GetPropertyType(sectionName, properties);
GetPropertyModifiers(sectionName, properties);
}
private void GetPropertyType(string sectionName, Dictionary<string, object?> properties)
{
int propertyTypeKey = 1;
_settingsStore.Current.SapModel.PropArea.GetTypeOAPI(sectionName, ref propertyTypeKey);
var propertyTypeValue = propertyTypeKey switch
{
1 => AreaPropertyType.SHELL,
2 => AreaPropertyType.PLANE,
3 => AreaPropertyType.ASOLID,
_ => throw new ArgumentException($"Unknown property type: {propertyTypeKey}"),
};
var generalData = properties.EnsureNested(SectionPropertyCategory.GENERAL_DATA);
generalData["Property Type"] = propertyTypeValue.ToString();
}
private void GetPropertyModifiers(string sectionName, Dictionary<string, object?> properties)
{
double[] stiffnessModifiersArray = [];
_settingsStore.Current.SapModel.PropArea.GetModifiers(sectionName, ref stiffnessModifiersArray);
Dictionary<string, object?> modifiers =
new()
{
["Membrane f11 Direction"] = stiffnessModifiersArray[0],
["Membrane f22 Direction"] = stiffnessModifiersArray[1],
["Membrane f12 Direction"] = stiffnessModifiersArray[2],
["Bending m11 Direction"] = stiffnessModifiersArray[3],
["Bending m22 Direction"] = stiffnessModifiersArray[3],
["Bending m12 Direction"] = stiffnessModifiersArray[4],
["Shear v13 Direction"] = stiffnessModifiersArray[5],
["Shear v23 Direction"] = stiffnessModifiersArray[6],
["Mass"] = stiffnessModifiersArray[7],
["Weight"] = stiffnessModifiersArray[8]
};
var generalData = properties.EnsureNested(SectionPropertyCategory.GENERAL_DATA);
generalData["Modifiers"] = modifiers;
}
}
@@ -0,0 +1,18 @@
namespace Speckle.Connectors.CSiShared.HostApp.Helpers;
/// <summary>
/// Contract for host application specific section property extraction.
/// </summary>
/// <remarks>
/// Mirrors property extraction system pattern by composing with base extractor.
/// Enables both shared and application-specific property extraction in one call.
/// </remarks>
public interface IApplicationSectionPropertyExtractor
{
void ExtractProperties(string sectionName, Dictionary<string, object?> properties);
}
// NOTE: Seemingly silly, but allows us to register the correct extractor for the correct type.
public interface IApplicationFrameSectionPropertyExtractor : IApplicationSectionPropertyExtractor { }
public interface IApplicationShellSectionPropertyExtractor : IApplicationSectionPropertyExtractor { }
@@ -0,0 +1,14 @@
namespace Speckle.Connectors.CSiShared.HostApp.Helpers;
/// <summary>
/// Core contract for section property extraction common across CSi products.
/// </summary>
public interface ISectionPropertyExtractor
{
void ExtractProperties(string sectionName, Dictionary<string, object?> properties);
}
// NOTE: Seemingly silly, but allows us to register the correct extractor for the correct type.
public interface IFrameSectionPropertyExtractor : ISectionPropertyExtractor { }
public interface IShellSectionPropertyExtractor : ISectionPropertyExtractor { }
@@ -0,0 +1,10 @@
using Speckle.Sdk.Models.Proxies;
namespace Speckle.Connectors.CSiShared.HostApp.Helpers;
// NOTE: Interface because Etabs and Sap2000 section unpacking and extraction is different.
// At ServiceRegistration, we inject the correct implementation of the ISectionUnpacker
public interface ISectionUnpacker
{
IEnumerable<GroupProxy> UnpackSections();
}
@@ -0,0 +1,51 @@
using Speckle.Connectors.CSiShared.HostApp.Helpers;
using Speckle.Converters.CSiShared.ToSpeckle.Helpers;
using Speckle.Sdk.Models.Proxies;
namespace Speckle.Connectors.CSiShared.HostApp;
/// <summary>
/// Creates material proxies based on stored entries from the materials cache
/// </summary>
public class MaterialUnpacker
{
private readonly CsiMaterialPropertyExtractor _propertyExtractor;
private readonly CsiToSpeckleCacheSingleton _csiToSpeckleCacheSingleton;
public MaterialUnpacker(
CsiMaterialPropertyExtractor propertyExtractor,
CsiToSpeckleCacheSingleton csiToSpeckleCacheSingleton
)
{
_propertyExtractor = propertyExtractor;
_csiToSpeckleCacheSingleton = csiToSpeckleCacheSingleton;
}
// Creates a list of material proxies from the csi materials cache
public IEnumerable<IProxyCollection> UnpackMaterials()
{
foreach (var kvp in _csiToSpeckleCacheSingleton.MaterialCache)
{
// get the cached entry
string materialName = kvp.Key;
List<string> sectionIds = kvp.Value;
// get the properties of the material
Dictionary<string, object?> properties = new(); // create empty dictionary
_propertyExtractor.ExtractProperties(materialName, properties); // dictionary mutated with respective properties
// create the material proxy
GroupProxy materialProxy =
new()
{
id = materialName,
name = materialName,
applicationId = materialName,
objects = sectionIds,
["properties"] = properties
};
yield return materialProxy;
}
}
}
@@ -1,11 +1,12 @@
using Microsoft.Extensions.Logging;
using Speckle.Connectors.Common.Builders;
using Speckle.Connectors.Common.Caching;
using Speckle.Connectors.Common.Conversion;
using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.CSiShared.HostApp;
using Speckle.Connectors.CSiShared.HostApp.Helpers;
using Speckle.Converters.Common;
using Speckle.Converters.CSiShared;
using Speckle.Converters.CSiShared.Extensions;
using Speckle.Sdk;
using Speckle.Sdk.Logging;
using Speckle.Sdk.Models;
@@ -13,47 +14,72 @@ using Speckle.Sdk.Models.Collections;
namespace Speckle.Connectors.CSiShared.Builders;
/// <summary>
/// Manages the conversion of CSi model objects and establishes proxy-based relationships.
/// </summary>
/// <remarks>
/// Core responsibilities:
/// - Converts ICsiWrappers to Speckle objects through caching-aware conversion
/// - Creates proxy objects for materials and sections from model data
/// - Establishes relationships between objects and their dependencies
///
/// The builder follows a two-phase process:
/// 1. Conversion Phase: ICsiWrappers → Speckle objects with cached results handling
/// 2. Relationship Phase: Material/section proxy creation and relationship mapping
/// </remarks>
public class CsiRootObjectBuilder : IRootObjectBuilder<ICsiWrapper>
{
private readonly IRootToSpeckleConverter _rootToSpeckleConverter;
private readonly ISendConversionCache _sendConversionCache;
private readonly IConverterSettingsStore<CsiConversionSettings> _converterSettings;
private readonly CsiSendCollectionManager _sendCollectionManager;
private readonly MaterialUnpacker _materialUnpacker;
private readonly ISectionUnpacker _sectionUnpacker;
private readonly ILogger<CsiRootObjectBuilder> _logger;
private readonly ISdkActivityFactory _activityFactory;
private readonly ICsiApplicationService _csiApplicationService;
public CsiRootObjectBuilder(
IRootToSpeckleConverter rootToSpeckleConverter,
ISendConversionCache sendConversionCache,
IConverterSettingsStore<CsiConversionSettings> converterSettings,
CsiSendCollectionManager sendCollectionManager,
MaterialUnpacker materialUnpacker,
ISectionUnpacker sectionUnpacker,
ILogger<CsiRootObjectBuilder> logger,
ISdkActivityFactory activityFactory,
ICsiApplicationService csiApplicationService
)
{
_sendConversionCache = sendConversionCache;
_converterSettings = converterSettings;
_sendCollectionManager = sendCollectionManager;
_materialUnpacker = materialUnpacker;
_sectionUnpacker = sectionUnpacker;
_rootToSpeckleConverter = rootToSpeckleConverter;
_logger = logger;
_activityFactory = activityFactory;
_csiApplicationService = csiApplicationService;
}
/// <summary>
/// Converts Csi objects into a Speckle-compatible object hierarchy with established relationships.
/// </summary>
/// <remarks>
/// Operation sequence:
/// 1. Creates root collection with model metadata
/// 2. Converts each object with caching and progress tracking
/// 3. Creates proxies for materials and sections
/// </remarks>
public async Task<RootObjectBuilderResult> Build(
IReadOnlyList<ICsiWrapper> csiObjects,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
CancellationToken cancellationToken = default
CancellationToken cancellationToken
)
{
using var activity = _activityFactory.Start("Build");
string modelFileName = _csiApplicationService.SapModel.GetModelFilename(false) ?? "Unnamed model";
Collection rootObjectCollection = new() { name = modelFileName };
rootObjectCollection["units"] = _converterSettings.Current.SpeckleUnits;
Collection rootObjectCollection =
new() { name = modelFileName, ["units"] = _converterSettings.Current.SpeckleUnits };
List<SendConversionResult> results = new(csiObjects.Count);
int count = 0;
@@ -62,14 +88,15 @@ public class CsiRootObjectBuilder : IRootObjectBuilder<ICsiWrapper>
{
foreach (ICsiWrapper csiObject in csiObjects)
{
using var _2 = _activityFactory.Start("Convert");
cancellationToken.ThrowIfCancellationRequested();
using var _2 = _activityFactory.Start("Convert");
var result = ConvertCSiObject(csiObject, rootObjectCollection, sendInfo.ProjectId);
var result = ConvertCsiObject(csiObject, rootObjectCollection);
results.Add(result);
count++;
onOperationProgressed.Report(new("Converting", (double)count / csiObjects.Count));
await Task.Yield();
}
}
@@ -78,33 +105,55 @@ public class CsiRootObjectBuilder : IRootObjectBuilder<ICsiWrapper>
throw new SpeckleException("Failed to convert all objects.");
}
await Task.Yield();
using (var _ = _activityFactory.Start("Process Proxies"))
{
// Create and add material proxies
rootObjectCollection[ProxyKeys.MATERIAL] = _materialUnpacker.UnpackMaterials().ToList();
// Create and all section proxies (frame and shell)
rootObjectCollection[ProxyKeys.SECTION] = _sectionUnpacker.UnpackSections().ToList();
}
return new RootObjectBuilderResult(rootObjectCollection, results);
}
private SendConversionResult ConvertCSiObject(ICsiWrapper csiObject, Collection typeCollection, string projectId)
/// <summary>
/// Converts a single Csi wrapper "object" to a data object with appropriate collection management.
/// </summary>
private SendConversionResult ConvertCsiObject(ICsiWrapper csiObject, Collection typeCollection)
{
string applicationId = $"{csiObject.ObjectType}{csiObject.Name}"; // TODO: NO! Use GUID
string sourceType = csiObject.ObjectName;
string applicationId = csiObject switch
{
CsiJointWrapper jointWrapper => jointWrapper.GetSpeckleApplicationId(_csiApplicationService.SapModel),
CsiFrameWrapper frameWrapper => frameWrapper.GetSpeckleApplicationId(_csiApplicationService.SapModel),
CsiCableWrapper cableWrapper => cableWrapper.GetSpeckleApplicationId(_csiApplicationService.SapModel),
CsiTendonWrapper tendonWrapper => tendonWrapper.ObjectName, // No GetGUID method in the Csi API available
CsiShellWrapper shellWrapper => shellWrapper.GetSpeckleApplicationId(_csiApplicationService.SapModel),
CsiSolidWrapper solidWrapper => solidWrapper.GetSpeckleApplicationId(_csiApplicationService.SapModel),
CsiLinkWrapper linkWrapper => linkWrapper.GetSpeckleApplicationId(_csiApplicationService.SapModel),
_ => throw new ArgumentException($"Unsupported wrapper type: {csiObject.GetType()}", nameof(csiObject))
};
try
{
Base converted;
if (_sendConversionCache.TryGetValue(projectId, applicationId, out ObjectReference? value))
{
converted = value;
}
else
{
converted = _rootToSpeckleConverter.Convert(csiObject);
}
Base converted = _rootToSpeckleConverter.Convert(csiObject);
var collection = _sendCollectionManager.AddObjectCollectionToRoot(converted, typeCollection);
collection.elements ??= new List<Base>();
collection.elements.Add(converted);
return new(Status.SUCCESS, applicationId, sourceType, converted);
}
// Expected not implemented:
// TODO: SAP 2000: CsiCableWrapper, CsiSolidWrapper
// TODO: ETABS: CsiLinkWrapper, CsiTendonWrapper
// NOTE: CsiLinkWrapper - not important to data extraction workflow
// NOTE: CsiTendonWrapper - not typically modelled in ETABS, rather SAFE
catch (NotImplementedException ex)
{
_logger.LogError(ex, sourceType);
return new(Status.WARNING, applicationId, sourceType, null, ex);
}
catch (Exception ex) when (!ex.IsFatal())
{
_logger.LogError(ex, sourceType);
@@ -10,8 +10,8 @@ public abstract class CSiPluginBase : cPluginContract, IDisposable
public void Main(ref cSapModel sapModel, ref cPluginCallback pluginCallback)
{
_panel = CreateForm();
_panel.SetSapModel(ref sapModel, ref pluginCallback);
_panel.FormClosed += (s, e) => Dispose();
_panel.Initialize(ref sapModel, ref pluginCallback);
_panel.FormClosed += (_, _) => Dispose();
if (string.Equals(s_modality, "Non-Modal", StringComparison.OrdinalIgnoreCase))
{
@@ -1,37 +1,33 @@
using System.ComponentModel;
using System.Reflection;
using System.Windows.Forms.Integration;
using Microsoft.Extensions.DependencyInjection;
using Speckle.Connectors.Common;
using Speckle.Connectors.CSiShared.HostApp;
using Speckle.Connectors.DUI;
using Speckle.Connectors.DUI.WebView;
using Speckle.Converters.CSiShared;
using Speckle.Sdk.Host;
namespace Speckle.Connectors.CSiShared;
[DesignerCategory("")]
public abstract class SpeckleFormBase : Form
public abstract class SpeckleFormBase : Form, ICsiApplicationService
{
protected ElementHost Host { get; set; }
public static new ServiceProvider? Container { get; set; }
private cSapModel _sapModel;
private ElementHost Host { get; set; }
private cPluginCallback _pluginCallback;
private bool _disposed;
#pragma warning disable CA2213
private ServiceProvider _container;
#pragma warning restore CA2213
protected SpeckleFormBase()
{
Text = "Speckle (Beta)";
var services = new ServiceCollection();
ConfigureServices(services);
Container = services.BuildServiceProvider();
var webview = Container.GetRequiredService<DUI3ControlWebView>();
Host = new() { Child = webview, Dock = DockStyle.Fill };
Controls.Add(Host);
FormClosing += Form1Closing;
Size = new System.Drawing.Size(400, 600);
}
public cSapModel SapModel { get; private set; }
protected virtual void ConfigureServices(IServiceCollection services)
{
services.Initialize(GetHostApplication(), GetVersion());
@@ -39,27 +35,65 @@ public abstract class SpeckleFormBase : Form
services.AddCsiConverters();
}
protected abstract HostApplication GetHostApplication();
protected abstract Speckle.Sdk.Application GetHostApplication();
protected abstract HostAppVersion GetVersion();
public void SetSapModel(ref cSapModel sapModel, ref cPluginCallback pluginCallback)
public void Initialize(ref cSapModel sapModel, ref cPluginCallback pluginCallback)
{
_sapModel = sapModel;
// store app-specific model and callback references (callback if at all possible?)
SapModel = sapModel;
_pluginCallback = pluginCallback;
var csiService = Container.GetRequiredService<ICsiApplicationService>();
csiService.Initialize(sapModel, pluginCallback);
string assemblyName =
Assembly.GetExecutingAssembly().GetName().Name
?? throw new InvalidOperationException("Could not determine executing assembly name");
string resourcePath = $"{assemblyName}.Resources.et_element_Speckle.bmp";
// load and set the speckle icon from embedded resources
using (var stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(resourcePath))
{
if (stream == null)
{
throw new InvalidOperationException($"Could not find resource: {resourcePath}");
}
using var bmp = new Bitmap(stream);
Icon = Icon.FromHandle(bmp.GetHicon());
}
// configure dependency injection services
var services = new ServiceCollection();
services.AddSingleton<ICsiApplicationService>(this);
ConfigureServices(services);
// build service container and initialize ui framework
_container = services.BuildServiceProvider();
_container.UseDUI();
// setup webview control and form properties
var webview = _container.GetRequiredService<DUI3ControlWebView>();
Host = new() { Child = webview, Dock = DockStyle.Fill };
Controls.Add(Host);
FormBorderStyle = FormBorderStyle.Sizable;
// this.TopLevel = true;
// TODO: Get IntrPtr for Csi window
FormClosing += Form1Closing;
}
protected void Form1Closing(object? sender, FormClosingEventArgs e)
{
Host.Dispose();
_pluginCallback.Finish(0);
}
private void Form1Closing(object? sender, FormClosingEventArgs e) => _pluginCallback.Finish(0);
public new void ShowDialog()
protected override void Dispose(bool disposing)
{
base.ShowDialog();
if (!_disposed)
{
if (disposing)
{
_container.Dispose();
Host.Dispose();
base.Dispose(disposing);
}
_disposed = true;
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 352 KiB

@@ -1,18 +1,20 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Speckle.Connectors.Common;
using Speckle.Connectors.Common.Builders;
using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.CSiShared.Bindings;
using Speckle.Connectors.CSiShared.Builders;
using Speckle.Connectors.CSiShared.Filters;
using Speckle.Connectors.CSiShared.HostApp;
using Speckle.Connectors.CSiShared.HostApp.Helpers;
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.Converters.CSiShared;
using Speckle.Converters.CSiShared.ToSpeckle.Helpers;
namespace Speckle.Connectors.CSiShared;
@@ -21,21 +23,17 @@ public static class ServiceRegistration
public static IServiceCollection AddCsi(this IServiceCollection services)
{
services.AddSingleton<IBrowserBridge, BrowserBridge>();
services.AddSingleton<ICsiApplicationService, CsiApplicationService>();
services.AddConnectorUtils();
services.AddDUI<CsiDocumentModelStore>();
services.AddConnectors();
services.AddDUI<DefaultThreadContext, CsiDocumentModelStore>();
services.AddDUIView();
services.AddSingleton<DocumentModelStore, CsiDocumentModelStore>();
services.AddSingleton<IBinding, TestBinding>();
services.AddSingleton<IBinding, ConfigBinding>();
services.AddSingleton<IBinding, AccountBinding>();
services.AddSingleton<IBinding>(sp => sp.GetRequiredService<IBasicConnectorBinding>());
services.AddSingleton<IBasicConnectorBinding, CsiSharedBasicConnectorBinding>();
services.AddSingleton<IAppIdleManager, CsiIdleManager>();
services.AddSingleton<IBinding, CsiSharedSelectionBinding>();
services.AddSingleton<IBinding, CsiSharedSendBinding>();
@@ -45,7 +43,13 @@ public static class ServiceRegistration
services.AddScoped<IRootObjectBuilder<ICsiWrapper>, CsiRootObjectBuilder>();
services.AddScoped<SendOperation<ICsiWrapper>>();
services.RegisterTopLevelExceptionHandler();
services.AddScoped<CsiMaterialPropertyExtractor>();
services.AddScoped<MaterialUnpacker>();
services.AddScoped<IFrameSectionPropertyExtractor, CsiFrameSectionPropertyExtractor>();
services.AddScoped<IShellSectionPropertyExtractor, CsiShellSectionPropertyExtractor>();
// add converter caches
services.AddScoped<CsiToSpeckleCacheSingleton>();
return services;
}
@@ -8,20 +8,34 @@
<PropertyGroup Label="Configuration">
<Import_RootNamespace>Speckle.Connectors.CSiShared</Import_RootNamespace>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Resources\et_element_Speckle.bmp">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)Bindings\CsiSharedBasicConnectorBinding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bindings\CsiSharedSelectionBinding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bindings\CsiSharedSendBinding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Filters\CsiSharedSelectionFilter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\MaterialUnpacker.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\CsiSendCollectionManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\Helpers\CsiFrameSectionPropertyExtractor.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\Helpers\CsiMaterialPropertyExtractor.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\Helpers\CsiShellSectionPropertyExtractor.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\Helpers\IApplicationSectionPropertyExtractor.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\Helpers\ISectionPropertyExtractor.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\Helpers\ISectionUnpacker.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\CsiRootObjectBuilder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\CsiPluginBase.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\SpeckleFormBase.cs" />
<Compile Include="$(MSBuildThisFileDirectory)GlobalUsing.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\CsiApplicationService.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\CsiDocumentModelStore.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\CsiIdleManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ServiceRegistration.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Utils\ObjectIdentifiers.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="$(MSBuildThisFileDirectory)Resources\et_element_Speckle.bmp" />
</ItemGroup>
</Project>
@@ -1,5 +1,5 @@
using Speckle.Connectors.Common;
using Speckle.Connectors.ETABSShared;
using Speckle.Sdk.Host;
// NOTE: Plugin entry point must match the assembly name, otherwise ETABS hits you with a "Not found" error when loading plugin
// Disabling error below to prioritize DUI3 project structure. Name of cPlugin class cannot be changed
@@ -8,5 +8,5 @@ namespace Speckle.Connectors.ETABS21;
public class SpeckleForm : EtabsSpeckleFormBase
{
protected override HostAppVersion GetVersion() => HostAppVersion.v2021; // TODO: We need a v21
protected override HostAppVersion GetVersion() => HostAppVersion.v21;
}
@@ -2,14 +2,13 @@
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Platforms>AnyCPU</Platforms>
<UseWindowsForms>true</UseWindowsForms>
<UseWPF>true</UseWPF>
<ETABSVersion>21</ETABSVersion>
<DefineConstants>$(DefineConstants);ETABS21</DefineConstants>
<EnableDynamicLoading>true</EnableDynamicLoading>
<Configurations>Debug;Release;Local</Configurations>
</PropertyGroup>
<ItemGroup>
@@ -164,11 +164,6 @@
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Speckle.DoubleNumerics": {
"type": "Transitive",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
},
"Speckle.Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.2",
@@ -264,19 +259,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.219, )",
"Speckle.Sdk": "[3.1.0-dev.219, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )",
"Speckle.Sdk": "[3.3.5, )",
"Speckle.Sdk.Dependencies": "[3.3.5, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.219, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.219, )",
"System.Threading.Tasks.Dataflow": "[6.0.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -293,7 +285,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"speckle.converters.etabs21": {
@@ -335,20 +327,26 @@
"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.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "2thsMUDkRr7lR0PXZJ8k3KWZLWjz/aBY0KaO2SuXM0lIKyJw1APMJ7lXJ89e6JAjBzEbK8yLHBb0qtfcc4bNRw==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.219"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "UTgz9UgkMFGqRLmCq1HPo74MngvKbSZOFWaMRzASHrrnsBtzZatBXjoJBlvVoeBCoiea5Jj+BgZg6RvlV2m3sg==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
@@ -356,22 +354,16 @@
"Microsoft.Data.Sqlite": "7.0.5",
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.0.1",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.1.0-dev.219"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "5hqBd9whAs5cC8S/6YUgKFOivjntAkVutKhz06XD/f3Kj6xScT3hwcUaWBxiwK3Mw7FLtiVuU1uG777pjn0PKQ=="
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[6.0.0, )",
"resolved": "6.0.0",
"contentHash": "+tyDCU3/B1lDdOOAJywHQoFwyXIUghIaP2BxG79uvhfTnO+D9qIgjVlL/JV2NTliYbMHpd6eKDmHp2VHpij7MA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
}
}
@@ -1,5 +1,5 @@
using Speckle.Connectors.Common;
using Speckle.Connectors.ETABSShared;
using Speckle.Sdk.Host;
// NOTE: Plugin entry point must match the assembly name, otherwise ETABS hits you with a "Not found" error when loading plugin
// Disabling error below to prioritize DUI3 project structure. Name of cPlugin class cannot be changed
@@ -8,5 +8,5 @@ namespace Speckle.Connectors.ETABS22;
public class SpeckleForm : EtabsSpeckleFormBase
{
protected override HostAppVersion GetVersion() => HostAppVersion.v2021; // TODO: v22
protected override HostAppVersion GetVersion() => HostAppVersion.v22;
}
@@ -2,14 +2,13 @@
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Platforms>AnyCPU</Platforms>
<UseWindowsForms>true</UseWindowsForms>
<UseWPF>true</UseWPF>
<ETABSVersion>22</ETABSVersion>
<DefineConstants>$(DefineConstants);ETABS22;ETABS22_OR_GREATER</DefineConstants>
<EnableDynamicLoading>true</EnableDynamicLoading>
<Configurations>Debug;Release;Local</Configurations>
</PropertyGroup>
<ItemGroup>
@@ -155,11 +155,6 @@
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Speckle.DoubleNumerics": {
"type": "Transitive",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
},
"Speckle.Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.2",
@@ -220,19 +215,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.219, )",
"Speckle.Sdk": "[3.1.0-dev.219, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )",
"Speckle.Sdk": "[3.3.5, )",
"Speckle.Sdk.Dependencies": "[3.3.5, )"
}
},
"speckle.connectors.dui": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.219, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.219, )",
"System.Threading.Tasks.Dataflow": "[6.0.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -249,7 +241,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.219, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"speckle.converters.etabs22": {
@@ -291,42 +283,42 @@
"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.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "2thsMUDkRr7lR0PXZJ8k3KWZLWjz/aBY0KaO2SuXM0lIKyJw1APMJ7lXJ89e6JAjBzEbK8yLHBb0qtfcc4bNRw==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.219"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "UTgz9UgkMFGqRLmCq1HPo74MngvKbSZOFWaMRzASHrrnsBtzZatBXjoJBlvVoeBCoiea5Jj+BgZg6RvlV2m3sg==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
"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.0.1",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.1.0-dev.219"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.219, )",
"resolved": "3.1.0-dev.219",
"contentHash": "5hqBd9whAs5cC8S/6YUgKFOivjntAkVutKhz06XD/f3Kj6xScT3hwcUaWBxiwK3Mw7FLtiVuU1uG777pjn0PKQ=="
},
"System.Threading.Tasks.Dataflow": {
"type": "CentralTransitive",
"requested": "[6.0.0, )",
"resolved": "6.0.0",
"contentHash": "+tyDCU3/B1lDdOOAJywHQoFwyXIUghIaP2BxG79uvhfTnO+D9qIgjVlL/JV2NTliYbMHpd6eKDmHp2VHpij7MA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
}
}

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