Compare commits

...

211 Commits

Author SHA1 Message Date
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
Claire Kuang 2ae80cc7ba simplifies speckle model resource to model link 2025-04-15 16:43:19 +01: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
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
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
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
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 207630c330 Update DataObjectConverter.cs 2025-04-07 15:41:48 +01:00
Claire Kuang b3e0af9b22 adds brep extrusion and subd receive to data objects 2025-04-07 15:12:33 +01: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
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
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
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
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
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
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
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
Claire Kuang b8f65d4ade fixes fallback conversion bug 2025-03-21 23:50:57 +00: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
Claire Kuang 9031950868 Merge branch 'dev' into dim/grassopper-v3-wip 2025-03-13 12:14:26 +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
Claire Kuang afd59df48a Merge branch 'dev' into dim/grassopper-v3-wip 2025-03-12 12:23:00 +00: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
307 changed files with 18357 additions and 2800 deletions
+3
View File
@@ -314,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
+8 -11
View File
@@ -1,13 +1,10 @@
name: .NET Build
on:
pull_request
on: pull_request
jobs:
jobs:
build:
runs-on: windows-latest
outputs:
version: ${{ steps.set-version.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -18,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
@@ -39,8 +36,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
@@ -51,9 +48,9 @@ jobs:
- 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 }}
+19 -9
View File
@@ -3,15 +3,17 @@ name: .NET Build and Publish
on:
push:
branches: ["main", "installer-test/**"]
tags: ["v3.*"] # Manual delivery on every 3.x tag
tags: ["v3.*.*"] # Manual delivery on every 3.x tag
jobs:
build-windows:
runs-on: windows-latest
env:
SPECKLE_VERSION: "unset"
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
@@ -35,29 +37,37 @@ jobs:
- name: ⬆️ Upload artifacts
uses: actions/upload-artifact@v4
with:
name: output-${{ env.SPECKLE_VERSION }}
name: output-${{ env.SEMVER }}
path: output/*.*
if-no-files-found: error
retention-days: 1
compression-level: 0 # no compression
compression-level: 0 # no compression
- id: set-version
name: Set version to output
run: echo "version=${{ env.SPECKLE_VERSION }}" >> "$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-windows
env:
IS_PUBLIC_RELEASE: ${{ github.ref_type == 'tag' }}
IS_TEST_INSTALLER: ${{ github.ref_type != 'tag' }}
steps:
- name: 🔫 Trigger Build Installers
uses: ALEEF02/workflow-dispatch@v3.0.0
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-windows.outputs.version }}", "public_release": ${{ env.IS_PUBLIC_RELEASE }}, "store_artifacts": ${{ env.IS_TEST_INSTALLER }} }'
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
+1
View File
@@ -10,6 +10,7 @@
<PackageReference Include="Bullseye" />
<PackageReference Include="Glob" />
<PackageReference Include="Microsoft.Build" />
<PackageReference Include="Microsoft.VisualStudio.SolutionPersistence" />
<PackageReference Include="Semver" />
<PackageReference Include="SimpleExec" />
</ItemGroup>
+3 -2
View File
@@ -11,7 +11,7 @@ public static class Consts
"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(
+13 -15
View File
@@ -15,6 +15,7 @@ const string ZIP = "zip";
const string RESTORE_TOOLS = "restore-tools";
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";
@@ -27,14 +28,7 @@ if (args.Length > 1)
args = new[] { arguments.First() };
//arguments = arguments.Skip(1).ToList();
}*/
void Build(string solution, string configuration)
{
Console.WriteLine();
Console.WriteLine();
Console.WriteLine($"Building solution '{solution}' as '{configuration}'");
Console.WriteLine();
Run("dotnet", $"build \".\\{solution}\" --configuration {configuration} --no-restore");
}
void Restore(string solution)
{
Console.WriteLine();
@@ -71,30 +65,31 @@ void CleanSolution(string solution, string configuration)
DeleteDirectories("**/obj");
DeleteFiles("**/*.lock.json");
Restore(solution);
Build(solution, configuration);
}
Target(
CLEAN_LOCKS,
() =>
Consts.Solutions,
s =>
{
DeleteFiles("**/*.lock.json");
Restore("Speckle.Connectors.sln");
Restore(s);
}
);
Target(
DEEP_CLEAN,
() =>
Consts.Solutions,
s =>
{
CleanSolution("Speckle.Connectors.sln", "debug");
CleanSolution(s, "debug");
}
);
Target(
DEEP_CLEAN_LOCAL,
() =>
{
CleanSolution("Local.sln", "local");
CleanSolution("Local.sln", "Local");
}
);
@@ -183,6 +178,7 @@ Target(
);
Target(CHECK_SOLUTIONS, Solutions.CompareConnectorsToLocal);
Target(GEN_SOLUTIONS, Solutions.GenerateSolutions);
Target(
TEST,
@@ -239,6 +235,7 @@ Target(
async () =>
{
var version = await Versions.ComputeVersion();
var fileVersion = await Versions.ComputeFileVersion();
foreach (var group in await Affected.GetAffectedProjectGroups())
{
Console.WriteLine($"Zipping: {group.HostAppSlug} as {version}");
@@ -280,7 +277,8 @@ Target(
string githubEnv = Environment.GetEnvironmentVariable("GITHUB_ENV") ?? "Unset";
Console.WriteLine($"GITHUB_ENV: {githubEnv}");
File.AppendAllText(githubEnv, $"SPECKLE_VERSION={version}{Environment.NewLine}");
File.AppendAllText(githubEnv, $"SEMVER={version}{Environment.NewLine}");
File.AppendAllText(githubEnv, $"FILE_VERSION={fileVersion}{Environment.NewLine}");
}
);
+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);
}
}
+6
View File
@@ -47,6 +47,12 @@
"Microsoft.SourceLink.Common": "8.0.0"
}
},
"Microsoft.VisualStudio.SolutionPersistence": {
"type": "Direct",
"requested": "[1.0.52, )",
"resolved": "1.0.52",
"contentHash": "oNv2JtYXhpdJrX63nibx1JT3uCESOBQ1LAk7Dtz/sr0+laW0KRM6eKp4CZ3MHDR2siIkKsY8MmUkeP5DKkQQ5w=="
},
"PolySharp": {
"type": "Direct",
"requested": "[1.14.1, )",
@@ -3,6 +3,7 @@ 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;
@@ -12,16 +13,13 @@ namespace Speckle.Connectors.ArcGIS.Utils;
public class ArcGISDocumentStore : DocumentModelStore
{
private readonly IThreadContext _threadContext;
public ArcGISDocumentStore(
ILogger<DocumentModelStore> logger,
IJsonSerializer jsonSerializer,
ITopLevelExceptionHandler topLevelExceptionHandler,
IThreadContext threadContext
ITopLevelExceptionHandler topLevelExceptionHandler
)
: base(jsonSerializer)
: base(logger, jsonSerializer)
{
_threadContext = threadContext;
ActiveMapViewChangedEvent.Subscribe(a => topLevelExceptionHandler.CatchUnhandled(() => OnMapViewChanged(a)), true);
ProjectSavingEvent.Subscribe(
_ =>
@@ -233,18 +233,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -269,7 +267,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"LibTessDotNet": {
@@ -313,18 +311,18 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"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",
@@ -334,14 +332,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
},
"net6.0-windows7.0/win-x64": {
@@ -25,12 +25,10 @@
</Target>
<PropertyGroup Condition="'$(AutoCADVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<StartAction>Program</StartAction>
<StartProgram>$(ProgramW6432)\Autodesk\AutoCAD $(AutoCADVersion)\acad.exe</StartProgram>
</PropertyGroup>
<PropertyGroup Condition="'$(Civil3DVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<StartAction>Program</StartAction>
<StartProgram>$(ProgramW6432)\Autodesk\AutoCAD $(Civil3DVersion)\acad.exe</StartProgram>
<StartArguments>/product C3D</StartArguments>
@@ -259,18 +259,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -294,7 +292,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -338,18 +336,18 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"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",
@@ -359,14 +357,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
}
}
@@ -259,18 +259,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -294,7 +292,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -338,18 +336,18 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"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",
@@ -359,14 +357,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
}
}
@@ -259,18 +259,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -295,7 +293,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -339,18 +337,18 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"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",
@@ -360,14 +358,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
}
}
@@ -4,7 +4,13 @@
<AutoCADVersion>2025</AutoCADVersion>
<DefineConstants>$(DefineConstants);AUTOCAD;AUTOCAD2025;AUTOCAD2022_OR_GREATER;AUTOCAD2023_OR_GREATER;AUTOCAD2024_OR_GREATER;AUTOCAD2025_OR_GREATER</DefineConstants>
<Configurations>Debug;Release;Local</Configurations>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <!-- .NET Core uses this to move native dependencies into a root for runtime selection and usage for non-windows development https://learn.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#enablewindowstargeting -->
</PropertyGroup>
<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>
@@ -215,18 +215,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -251,7 +249,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -295,18 +293,18 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -315,14 +313,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
},
"net8.0-windows7.0/win-x64": {
@@ -3,8 +3,14 @@
<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>
<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 -->
<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>
@@ -215,18 +215,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -251,7 +249,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -295,18 +293,18 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -315,14 +313,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
},
"net8.0-windows7.0/win-x64": {
@@ -89,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,3 +1,4 @@
using Microsoft.Extensions.Logging;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Utils;
@@ -9,17 +10,16 @@ public class AutocadDocumentStore : DocumentModelStore
private const string NULL_DOCUMENT_NAME = "Null Doc";
private string _previousDocName;
private readonly AutocadDocumentManager _autocadDocumentManager;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
public AutocadDocumentStore(
ILogger<DocumentModelStore> logger,
IJsonSerializer jsonSerializer,
AutocadDocumentManager autocadDocumentManager,
ITopLevelExceptionHandler topLevelExceptionHandler
)
: base(jsonSerializer)
: base(logger, jsonSerializer)
{
_autocadDocumentManager = autocadDocumentManager;
_topLevelExceptionHandler = topLevelExceptionHandler;
_previousDocName = NULL_DOCUMENT_NAME;
// POC: Will be addressed to move it into AutocadContext!
@@ -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);
@@ -268,18 +268,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -304,7 +302,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -348,18 +346,18 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"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",
@@ -369,14 +367,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
}
}
@@ -268,18 +268,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -304,7 +302,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -348,18 +346,18 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"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",
@@ -369,14 +367,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
}
}
@@ -268,18 +268,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -304,7 +302,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -348,18 +346,18 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"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",
@@ -369,14 +367,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
}
}
@@ -4,7 +4,13 @@
<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>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <!-- .NET Core uses this to move native dependencies into a root for runtime selection and usage for non-windows development https://learn.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#enablewindowstargeting -->
</PropertyGroup>
<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>
@@ -224,18 +224,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -261,7 +259,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -305,18 +303,18 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -325,14 +323,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
},
"net8.0-windows7.0/win-x64": {
@@ -4,7 +4,13 @@
<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>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <!-- .NET Core uses this to move native dependencies into a root for runtime selection and usage for non-windows development https://learn.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#enablewindowstargeting -->
</PropertyGroup>
<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>
@@ -224,18 +224,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -261,7 +259,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -305,18 +303,18 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -325,14 +323,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
},
"net8.0-windows7.0/win-x64": {
@@ -26,6 +26,7 @@ public class CsiDocumentModelStore : DocumentModelStore, IDisposable
private string ModelPathHash { get; set; }
public CsiDocumentModelStore(
ILogger<DocumentModelStore> baseLogger,
IJsonSerializer jsonSerializer,
ISpeckleApplication speckleApplication,
ILogger<CsiDocumentModelStore> logger,
@@ -33,7 +34,7 @@ public class CsiDocumentModelStore : DocumentModelStore, IDisposable
ITopLevelExceptionHandler topLevelExceptionHandler,
IThreadContext threadContext
)
: base(jsonSerializer)
: base(baseLogger, jsonSerializer)
{
_threadContext = threadContext;
_speckleApplication = speckleApplication;
@@ -259,18 +259,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -287,7 +285,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"speckle.converters.etabs21": {
@@ -337,18 +335,18 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"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,14 +356,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
}
}
@@ -215,18 +215,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -243,7 +241,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"speckle.converters.etabs22": {
@@ -293,18 +291,18 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -313,14 +311,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
}
}
@@ -259,18 +259,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -287,7 +285,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"speckle.converters.navisworks2020": {
@@ -339,18 +337,18 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"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",
@@ -360,14 +358,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
},
".NETFramework,Version=v4.8/win-x64": {
@@ -259,18 +259,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -287,7 +285,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"speckle.converters.navisworks2021": {
@@ -339,18 +337,18 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"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",
@@ -360,14 +358,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
},
".NETFramework,Version=v4.8/win-x64": {
@@ -259,18 +259,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -287,7 +285,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"speckle.converters.navisworks2022": {
@@ -339,18 +337,18 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"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",
@@ -360,14 +358,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
},
".NETFramework,Version=v4.8/win-x64": {
@@ -259,18 +259,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -287,7 +285,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"speckle.converters.navisworks2023": {
@@ -339,18 +337,18 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"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",
@@ -360,14 +358,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
},
".NETFramework,Version=v4.8/win-x64": {
@@ -259,18 +259,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -287,7 +285,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"speckle.converters.navisworks2024": {
@@ -339,18 +337,18 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"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",
@@ -360,14 +358,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
},
".NETFramework,Version=v4.8/win-x64": {
@@ -265,18 +265,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -293,7 +291,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"speckle.converters.navisworks2025": {
@@ -339,18 +337,18 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"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",
@@ -360,14 +358,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
},
".NETFramework,Version=v4.8/win-x64": {
@@ -266,18 +266,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.dui.webview": {
@@ -294,7 +292,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"speckle.converters.navisworks2026": {
@@ -341,18 +339,18 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"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",
@@ -362,14 +360,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
},
".NETFramework,Version=v4.8/win-x64": {
@@ -1,4 +1,5 @@
using System.Data;
using Microsoft.Extensions.Logging;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Utils;
@@ -19,10 +20,11 @@ public sealed class NavisworksDocumentModelStore : DocumentModelStore
private string _lastSavedState = string.Empty;
public NavisworksDocumentModelStore(
ILogger<DocumentModelStore> logger,
IJsonSerializer jsonSerializer,
ITopLevelExceptionHandler topLevelExceptionHandler
)
: base(jsonSerializer)
: base(logger, jsonSerializer)
{
_topLevelExceptionHandler = topLevelExceptionHandler;
LoadState();
@@ -4,11 +4,19 @@
<UseWpf>true</UseWpf>
<RevitVersion>2022</RevitVersion>
<DefineConstants>$(DefineConstants);REVIT2022;REVIT2022_OR_GREATER</DefineConstants>
<CefSharpAnyCpuSupport>true</CefSharpAnyCpuSupport>
<Prefer32bit>false</Prefer32bit>
<Configurations>Debug;Release;Local</Configurations>
</PropertyGroup>
<PropertyGroup Label="Things needed to get ancient cef buildling with modern msbuild">
<!--There is a weird bug or misconfiguration in cef 65.0.1 nuget that makes it pick x86 dlls if asked to build x64.-->
<!--Asking it to build AnyCPU appaers to work, but generates MSB3270 warnings, which we are ignoring here-->
<!--Official docs suggest setting the entire solution to x64, which we can't do, and we don't want to create a new SLN just for Revit 2022-->
<CefSharpAnyCpuSupport>true</CefSharpAnyCpuSupport>
<Prefer32bit>false</Prefer32bit>
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
</PropertyGroup>
<Import Project="..\Speckle.Connectors.RevitShared\Speckle.Connectors.RevitShared.projitems" Label="Shared" />
<Import Project="..\Speckle.Connectors.RevitShared.Cef\Speckle.Connectors.RevitShared.Cef.projitems" Label="Shared" />
@@ -287,18 +287,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.logging": {
@@ -308,7 +306,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"speckle.converters.revit2022": {
@@ -353,11 +351,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Revit.API": {
@@ -368,9 +366,9 @@
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"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",
@@ -380,14 +378,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
}
}
@@ -287,18 +287,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.logging": {
@@ -308,7 +306,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"speckle.converters.revit2023": {
@@ -353,11 +351,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Revit.API": {
@@ -368,9 +366,9 @@
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"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",
@@ -380,14 +378,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
}
}
@@ -287,18 +287,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.logging": {
@@ -308,7 +306,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"speckle.converters.revit2024": {
@@ -353,11 +351,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Revit.API": {
@@ -368,9 +366,9 @@
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"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",
@@ -380,14 +378,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
}
}
@@ -237,18 +237,16 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.2.0, )",
"Speckle.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.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.Sdk": "[3.2.0, )",
"Speckle.Sdk.Dependencies": "[3.2.0, )"
"Speckle.Connectors.Common": "[1.0.0, )"
}
},
"speckle.connectors.logging": {
@@ -258,7 +256,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.2.0, )"
"Speckle.Objects": "[3.3.5, )"
}
},
"speckle.converters.revit2025": {
@@ -303,11 +301,11 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "ZgsbDz31Rq87Gtej2soLjTTBaRnnERKvs0QCT2AjGD4Vn5QwqnagPDqFTndWz+w6vG4t2hZH56QfqAmyIiuPag==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.2.0"
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Revit.API": {
@@ -318,9 +316,9 @@
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "DI3ljov8FMIAIosm3quAXlgYKWS+AJriaFC9dGBJh4y1xg4jvD8Tpx4h7Wd3Bib9BsH6Bhe5BUwACLv7dJKxIg==",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
@@ -329,14 +327,14 @@
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.2.0"
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.2.0, )",
"resolved": "3.2.0",
"contentHash": "wgUjHJN8lPF47tAht+2gm8yF2dIQXxTXhoJttzb+89o2ej1jrdwxTUQP1EtfjnixK6QApJ809QQqTbJm5sdaqA=="
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
},
"net8.0-windows7.0/win-x64": {
@@ -0,0 +1,19 @@
<UserControl x:Class="Speckle.Connectors.Revit2026.Plugin.RevitControlWebView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
xmlns:dui="clr-namespace:Speckle.Connectors.DUI;assembly=Speckle.Connectors.DUI"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<wv2:CoreWebView2CreationProperties x:Key="EvergreenWebView2CreationProperties" UserDataFolder="C:\temp" />
</UserControl.Resources>
<DockPanel>
<wv2:WebView2
CreationProperties="{StaticResource EvergreenWebView2CreationProperties}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Name="Browser" Grid.Row="0" Source="{x:Static dui:Url.Netlify}" />
</DockPanel>
</UserControl>
@@ -0,0 +1,84 @@
using System.Windows.Controls;
using System.Windows.Threading;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Web.WebView2.Core;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.Revit.Plugin;
namespace Speckle.Connectors.Revit2026.Plugin;
public sealed partial class RevitControlWebView : UserControl, IBrowserScriptExecutor, IDisposable
{
private readonly IServiceProvider _serviceProvider;
private readonly IRevitTask _revitTask;
public RevitControlWebView(IServiceProvider serviceProvider, IRevitTask revitTask)
{
_serviceProvider = serviceProvider;
_revitTask = revitTask;
InitializeComponent();
Browser.CoreWebView2InitializationCompleted += (sender, args) =>
_serviceProvider
.GetRequiredService<ITopLevelExceptionHandler>()
.CatchUnhandled(() => OnInitialized(sender, args));
}
public bool IsBrowserInitialized => Browser.IsInitialized;
public object BrowserElement => Browser;
public void ExecuteScript(string script)
{
if (!Browser.IsInitialized)
{
throw new InvalidOperationException("Failed to execute script, Webview2 is not initialized yet.");
}
_revitTask.Run(() => Browser.ExecuteScriptAsync(script));
}
public void SendProgress(string script)
{
if (!Browser.IsInitialized)
{
throw new InvalidOperationException("Failed to execute script, Webview2 is not initialized yet.");
}
//always invoke even on the main thread because it's better somehow
Browser.Dispatcher.Invoke(
//fire and forget
() => Browser.ExecuteScriptAsync(script),
DispatcherPriority.Background
);
}
private void OnInitialized(object? sender, CoreWebView2InitializationCompletedEventArgs e)
{
Console.WriteLine(CoreWebView2Environment.GetAvailableBrowserVersionString());
if (!e.IsSuccess)
{
throw new InvalidOperationException("Webview Failed to initialize", e.InitializationException);
}
// We use Lazy here to delay creating the binding until after the Browser is fully initialized.
// Otherwise the Browser cannot respond to any requests to ExecuteScriptAsyncMethod
foreach (var binding in _serviceProvider.GetRequiredService<IEnumerable<IBinding>>())
{
SetupBinding(binding);
}
}
/// <remark>
/// This must be called on the Main thread
/// </remark>
private void SetupBinding(IBinding binding)
{
binding.Parent.AssociateWithBinding(binding);
Browser.CoreWebView2.AddHostObjectToScript(binding.Name, binding.Parent);
}
public void ShowDevTools() => Browser.CoreWebView2.OpenDevToolsWindow();
//https://github.com/MicrosoftEdge/WebView2Feedback/issues/2161
public void Dispose() => Browser.Dispatcher.Invoke(() => Browser.Dispose(), DispatcherPriority.Send);
}
@@ -0,0 +1,22 @@
using System.Windows.Controls;
using Autodesk.Revit.UI;
namespace Speckle.Connectors.Revit2026.Plugin;
public sealed class RevitControlWebViewDockable : UserControl, Autodesk.Revit.UI.IDockablePaneProvider
{
public RevitControlWebViewDockable(RevitControlWebView dUI3ControlWebView)
{
Content = dUI3ControlWebView;
}
public void SetupDockablePane(DockablePaneProviderData data)
{
data.FrameworkElement = this;
data.InitialState = new Autodesk.Revit.UI.DockablePaneState
{
DockPosition = DockPosition.Tabbed,
TabBehind = DockablePanes.BuiltInDockablePanes.ProjectBrowser
};
}
}
@@ -0,0 +1,114 @@
using System.IO;
using System.Reflection;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Autodesk.Revit.UI;
using Speckle.Connectors.Common;
using Speckle.Connectors.Revit.Plugin;
using Speckle.Converters.RevitShared.Helpers;
using Speckle.Sdk;
namespace Speckle.Connectors.Revit2026.Plugin;
internal sealed class RevitWebViewPlugin(
UIControlledApplication uIControlledApplication,
RevitContext revitContext,
RevitControlWebViewDockable webViewPanel,
ISpeckleApplication speckleApplication
) : IRevitPlugin
{
public void Initialise()
{
// Create and register panels before app initialized. this is needed for double-click file open
CreateTabAndRibbonPanel(uIControlledApplication);
RegisterDockablePane();
uIControlledApplication.ControlledApplication.ApplicationInitialized += OnApplicationInitialized;
}
public void Shutdown()
{
// POC: should we be cleaning up the RibbonPanel etc...
// Should we be indicating to any active in-flight functions that we are being closed?
}
// POC: Could be injected but maybe not worthwhile
private void CreateTabAndRibbonPanel(UIControlledApplication application)
{
// POC: some top-level handling and feedback here
try
{
application.CreateRibbonTab(Connector.TabName);
}
catch (ArgumentException)
{
// exception occurs when the speckle tab has already been created.
// this happens when both the dui2 and the dui3 connectors are installed. Can be safely ignored.
}
RibbonPanel specklePanel = application.CreateRibbonPanel(Connector.TabName, Connector.TabTitle);
var dui3Button = (PushButton)
specklePanel.AddItem(
new PushButtonData(
"Speckle (Beta) for Revit",
Connector.TabTitle,
typeof(RevitExternalApplication).Assembly.Location,
typeof(SpeckleRevitCommand).FullName
)
);
string path = typeof(RevitWebViewPlugin).Assembly.Location;
dui3Button.Image = LoadPngImgSource(
$"Speckle.Connectors.Revit{speckleApplication.HostApplicationVersion}.Assets.logo16.png",
path
);
dui3Button.LargeImage = LoadPngImgSource(
$"Speckle.Connectors.Revit{speckleApplication.HostApplicationVersion}.Assets.logo32.png",
path
);
dui3Button.ToolTipImage = LoadPngImgSource(
$"Speckle.Connectors.Revit{speckleApplication.HostApplicationVersion}.Assets.logo32.png",
path
);
dui3Button.ToolTip = "Speckle (Beta) for Revit";
//dui3Button.AvailabilityClassName = typeof(CmdAvailabilityViews).FullName;
dui3Button.SetContextualHelp(new ContextualHelp(ContextualHelpType.Url, "https://speckle.systems"));
}
private void OnApplicationInitialized(object? sender, Autodesk.Revit.DB.Events.ApplicationInitializedEventArgs e)
{
var uiApplication = new UIApplication(sender as Autodesk.Revit.ApplicationServices.Application);
revitContext.UIApplication = uiApplication;
// POC: might be worth to interface this out, we shall see...
global::Revit.Async.RevitTask.Initialize(uiApplication);
}
private void RegisterDockablePane()
{
// Registering dockable pane should happen before UiApplication is initialized with RevitTask.
// Otherwise pane cannot be registered for double-click file open.
uIControlledApplication.RegisterDockablePane(
RevitExternalApplication.DockablePanelId,
Connector.TabTitle,
webViewPanel
);
}
private ImageSource? LoadPngImgSource(string sourceName, string path)
{
try
{
var assembly = Assembly.LoadFrom(Path.Combine(path));
var icon = assembly.GetManifestResourceStream(sourceName);
PngBitmapDecoder decoder = new(icon, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
ImageSource source = decoder.Frames[0];
return source;
}
catch (Exception ex) when (!ex.IsFatal())
{
// POC: logging
}
return null;
}
}
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<RevitAddIns>
<AddIn Type="Application">
<Name>Speckle (Beta) for Revit</Name>
<Description>Speckle (Beta) for Revit</Description>
<Assembly>Speckle.Connectors.Revit2026\Speckle.Connectors.Revit2026.dll</Assembly>
<FullClassName>Speckle.Connectors.Revit.Plugin.RevitExternalApplication</FullClassName>
<ClientId>27ccff2c-011c-4374-bb79-b93990d0c86a</ClientId>
<VendorId>speckle</VendorId>
<VendorDescription>Speckle: Empowering your design and construction data. For any problems, visit our community forum https://speckle.community</VendorDescription>
</AddIn>
</RevitAddIns>
@@ -0,0 +1,9 @@
{
"profiles": {
"ConnectorRevit2026": {
"commandName": "Executable",
"executablePath": "C:\\Program Files\\Autodesk\\Revit 2026\\Revit.exe",
"runtime": "net8.0-windows"
}
}
}
@@ -0,0 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<UseWpf>true</UseWpf>
<RevitVersion>2026</RevitVersion>
<DefineConstants>$(DefineConstants);REVIT2026;REVIT2022_OR_GREATER;REVIT2023_OR_GREATER;REVIT2024_OR_GREATER;REVIT2025_OR_GREATER;REVIT2026_OR_GREATER</DefineConstants><CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<Configurations>Debug;Release;Local</Configurations>
</PropertyGroup>
<Import Project="..\Speckle.Connectors.RevitShared\Speckle.Connectors.RevitShared.projitems" Label="Shared" />
<ItemGroup>
<ProjectReference Include="..\..\..\Converters\Revit\Speckle.Converters.Revit2026\Speckle.Converters.Revit2026.csproj" />
<ProjectReference Include="..\..\..\DUI3\Speckle.Connectors.DUI\Speckle.Connectors.DUI.csproj" />
<ProjectReference Include="..\..\..\Sdk\Speckle.Connectors.Common\Speckle.Connectors.Common.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Revit.Async" />
<PackageReference Include="Microsoft.Web.WebView2" IncludeAssets="compile" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" VersionOverride="8.0.0" />
</ItemGroup>
<ItemGroup>
<Content Include="Plugin\Speckle.Connectors.Revit2026.addin">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
@@ -0,0 +1,338 @@
{
"version": 2,
"dependencies": {
"net8.0-windows7.0": {
"Microsoft.Extensions.DependencyInjection": {
"type": "Direct",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "V8S3bsm50ig6JSyrbcJJ8bW2b9QLGouz+G1miK3UTaOWmMtFwNNNzUf4AleyDWUmTrWMLNnFSLEQtxmxgNQnNQ==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0"
}
},
"Microsoft.NETFramework.ReferenceAssemblies": {
"type": "Direct",
"requested": "[1.0.3, )",
"resolved": "1.0.3",
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
"dependencies": {
"Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.3"
}
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
"dependencies": {
"Microsoft.Build.Tasks.Git": "8.0.0",
"Microsoft.SourceLink.Common": "8.0.0"
}
},
"Microsoft.Web.WebView2": {
"type": "Direct",
"requested": "[1.0.1938.49, )",
"resolved": "1.0.1938.49",
"contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
},
"PolySharp": {
"type": "Direct",
"requested": "[1.14.1, )",
"resolved": "1.14.1",
"contentHash": "mOOmFYwad3MIOL14VCjj02LljyF1GNw1wP0YVlxtcPvqdxjGGMNdNJJxHptlry3MOd8b40Flm8RPOM8JOlN2sQ=="
},
"Revit.Async": {
"type": "Direct",
"requested": "[2.1.1, )",
"resolved": "2.1.1",
"contentHash": "aK6R/fxrn3jpiKc8LYqfWZ+OfEKNnwgkiln1uyuvaPnTWBOvfiisnOfe7+Sgogr4iEuMmuMDsmBRMCycMlUpnw=="
},
"Speckle.InterfaceGenerator": {
"type": "Direct",
"requested": "[0.9.6, )",
"resolved": "0.9.6",
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
},
"GraphQL.Client": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "8yPNBbuVBpTptivyAlak4GZvbwbUcjeQTL4vN1HKHRuOykZ4r7l5fcLS6vpyPyLn0x8FsL31xbOIKyxbmR9rbA==",
"dependencies": {
"GraphQL.Client.Abstractions": "6.0.0",
"GraphQL.Client.Abstractions.Websocket": "6.0.0",
"System.Reactive": "5.0.0"
}
},
"GraphQL.Client.Abstractions": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "h7uzWFORHZ+CCjwr/ThAyXMr0DPpzEANDa4Uo54wqCQ+j7qUKwqYTgOrb1W40sqbvNaZm9v/X7It31SUw0maHA==",
"dependencies": {
"GraphQL.Primitives": "6.0.0"
}
},
"GraphQL.Client.Abstractions.Websocket": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "Nr9bPf8gIOvLuXpqEpqr9z9jslYFJOvd0feHth3/kPqeR3uMbjF5pjiwh4jxyMcxHdr8Pb6QiXkV3hsSyt0v7A==",
"dependencies": {
"GraphQL.Client.Abstractions": "6.0.0"
}
},
"GraphQL.Primitives": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "yg72rrYDapfsIUrul7aF6wwNnTJBOFvuA9VdDTQpPa8AlAriHbufeXYLBcodKjfUdkCnaiggX1U/nEP08Zb5GA=="
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
},
"Microsoft.CSharp": {
"type": "Transitive",
"resolved": "4.7.0",
"contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA=="
},
"Microsoft.Data.Sqlite": {
"type": "Transitive",
"resolved": "7.0.5",
"contentHash": "KGxbPeWsQMnmQy43DSBxAFtHz3l2JX8EWBSGUCvT3CuZ8KsuzbkqMIJMDOxWtG8eZSoCDI04aiVQjWuuV8HmSw==",
"dependencies": {
"Microsoft.Data.Sqlite.Core": "7.0.5",
"SQLitePCLRaw.bundle_e_sqlite3": "2.1.4"
}
},
"Microsoft.Data.Sqlite.Core": {
"type": "Transitive",
"resolved": "7.0.5",
"contentHash": "FTerRmQPqHrCrnoUzhBu+E+1DNGwyrAMLqHkAqOOOu5pGfyMOj8qQUBxI/gDtWtG11p49UxSfWmBzRNlwZqfUg==",
"dependencies": {
"SQLitePCLRaw.core": "2.1.4"
}
},
"Microsoft.Extensions.Configuration": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==",
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "2.2.0"
}
},
"Microsoft.Extensions.Configuration.Abstractions": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==",
"dependencies": {
"Microsoft.Extensions.Primitives": "2.2.0"
}
},
"Microsoft.Extensions.Configuration.Binder": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "vJ9xvOZCnUAIHcGC3SU35r3HKmHTVIeHzo6u/qzlHAqD8m6xv92MLin4oJntTvkpKxVX3vI1GFFkIQtU3AdlsQ==",
"dependencies": {
"Microsoft.Extensions.Configuration": "2.2.0"
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "cjWrLkJXK0rs4zofsK4bSdg+jhDLTaxrkXu4gS6Y7MAlCvRyNNgwY/lJi5RDlQOnSZweHqoyvgvbdvQsRIW+hg=="
},
"Microsoft.Extensions.Options": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Primitives": "2.2.0",
"System.ComponentModel.Annotations": "4.5.0"
}
},
"Microsoft.Extensions.Primitives": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==",
"dependencies": {
"System.Memory": "4.5.1",
"System.Runtime.CompilerServices.Unsafe": "4.5.1"
}
},
"Microsoft.NETFramework.ReferenceAssemblies.net461": {
"type": "Transitive",
"resolved": "1.0.3",
"contentHash": "AmOJZwCqnOCNp6PPcf9joyogScWLtwy0M1WkqfEQ0M9nYwyDD7EX9ZjscKS5iYnyvteX7kzSKFCKt9I9dXA6mA=="
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Speckle.Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.2",
"contentHash": "g1BejUZwax5PRfL6xHgLEK23sqHWOgOj9hE7RvfRRlN00AGt8GnPYt8HedSK7UB3HiRW8zCA9Pn0iiYxCK24BA=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "EWI1olKDjFEBMJu0+3wuxwziIAdWDVMYLhuZ3Qs84rrz+DHwD00RzWPZCa+bLnHCf3oJwuFZIRsHT5p236QXww==",
"dependencies": {
"SQLitePCLRaw.lib.e_sqlite3": "2.1.4",
"SQLitePCLRaw.provider.e_sqlite3": "2.1.4"
}
},
"SQLitePCLRaw.core": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "inBjvSHo9UDKneGNzfUfDjK08JzlcIhn1+SP5Y3m6cgXpCxXKCJDy6Mka7LpgSV+UZmKSnC8rTwB0SQ0xKu5pA==",
"dependencies": {
"System.Memory": "4.5.3"
}
},
"SQLitePCLRaw.lib.e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
},
"SQLitePCLRaw.provider.e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "CSlb5dUp1FMIkez9Iv5EXzpeq7rHryVNqwJMWnpq87j9zWZexaEMdisDktMsnnrzKM6ahNrsTkjqNodTBPBxtQ==",
"dependencies": {
"SQLitePCLRaw.core": "2.1.4"
}
},
"System.ComponentModel.Annotations": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
},
"System.Memory": {
"type": "Transitive",
"resolved": "4.5.3",
"contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA=="
},
"System.Reactive": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ=="
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
"resolved": "4.5.1",
"contentHash": "Zh8t8oqolRaFa9vmOZfdQm/qKejdqz0J9kr7o2Fu0vPeoH3BL1EOXipKWwkWtLT1JPzjByrF19fGuFlNbmPpiw=="
},
"speckle.connectors.common": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.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.logging": {
"type": "Project"
},
"speckle.converters.common": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.3.5, )"
}
},
"speckle.converters.revit2026": {
"type": "Project",
"dependencies": {
"Speckle.Converters.Common": "[1.0.0, )",
"Speckle.Revit.API": "[2026.0.0, )"
}
},
"Microsoft.Extensions.Logging": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==",
"dependencies": {
"Microsoft.Extensions.Configuration.Binder": "2.2.0",
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Logging.Abstractions": "2.2.0",
"Microsoft.Extensions.Options": "2.2.0"
}
},
"Microsoft.Extensions.Logging.Abstractions": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
},
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Revit.API": {
"type": "CentralTransitive",
"requested": "[2023.0.0, )",
"resolved": "2026.0.0",
"contentHash": "SiqqKbF1pXyZWXZhAl2JhjYhTt7RiYO5JaQrAjq+OlleAjT4zatwAp/DnTwQspFbP7UZr3b2Ed2kuWNN0ZFelw=="
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"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.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
},
"net8.0-windows7.0/win-x64": {
"Microsoft.Web.WebView2": {
"type": "Direct",
"requested": "[1.0.1938.49, )",
"resolved": "1.0.1938.49",
"contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
},
"SQLitePCLRaw.lib.e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
}
}
}
}
@@ -18,6 +18,8 @@ public partial class CefSharpPanel : Page, Autodesk.Revit.UI.IDockablePaneProvid
Browser.Dispatcher.Invoke(() => Browser.ExecuteScriptAsync(script), DispatcherPriority.Background);
}
public void SendProgress(string script) => ExecuteScript(script);
public bool IsBrowserInitialized => Browser.IsBrowserInitialized;
public object BrowserElement => Browser;
@@ -1,8 +1,8 @@
using Autodesk.Revit.DB;
using Revit.Async;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Models.Card;
using Speckle.Connectors.Revit.Plugin;
using Speckle.Connectors.RevitShared;
using Speckle.Connectors.RevitShared.Operations.Send.Filters;
using Speckle.Converters.RevitShared.Helpers;
@@ -23,13 +23,15 @@ internal sealed class BasicConnectorBindingRevit : IBasicConnectorBinding
private readonly RevitContext _revitContext;
private readonly ISpeckleApplication _speckleApplication;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
private readonly IRevitTask _revitTask;
public BasicConnectorBindingRevit(
DocumentModelStore store,
IBrowserBridge parent,
RevitContext revitContext,
ISpeckleApplication speckleApplication,
ITopLevelExceptionHandler topLevelExceptionHandler
ITopLevelExceptionHandler topLevelExceptionHandler,
IRevitTask revitTask
)
{
Name = "baseBinding";
@@ -38,6 +40,7 @@ internal sealed class BasicConnectorBindingRevit : IBasicConnectorBinding
_revitContext = revitContext;
_speckleApplication = speckleApplication;
_topLevelExceptionHandler = topLevelExceptionHandler;
_revitTask = revitTask;
Commands = new BasicConnectorBindingCommands(parent);
_store.DocumentChanged += (_, _) =>
@@ -105,7 +108,7 @@ internal sealed class BasicConnectorBindingRevit : IBasicConnectorBinding
var view = revitViewsFilter.GetView();
if (view is not null)
{
await RevitTask
await _revitTask
.RunAsync(() =>
{
_revitContext.UIApplication.ActiveUIDocument.ActiveView = view;
@@ -170,7 +173,7 @@ internal sealed class BasicConnectorBindingRevit : IBasicConnectorBinding
_revitContext.UIApplication?.ActiveUIDocument
?? throw new SpeckleException("Unable to retrieve active UI document");
await RevitTask
await _revitTask
.RunAsync(() =>
{
activeUIDoc.Selection.SetElementIds(objectIds);
@@ -10,6 +10,7 @@ using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Models.Card;
using Speckle.Connectors.Revit.Plugin;
using Speckle.Converters.Common;
using Speckle.Converters.RevitShared.Helpers;
using Speckle.Converters.RevitShared.Settings;
using Speckle.Sdk;
@@ -27,6 +28,7 @@ internal sealed class RevitReceiveBinding : IReceiveBinding
private readonly IServiceProvider _serviceProvider;
private readonly IRevitConversionSettingsFactory _revitConversionSettingsFactory;
private readonly ISpeckleApplication _speckleApplication;
private readonly RevitToHostCacheSingleton _revitToHostCacheSingleton;
private ReceiveBindingUICommands Commands { get; }
public RevitReceiveBinding(
@@ -37,7 +39,8 @@ internal sealed class RevitReceiveBinding : IReceiveBinding
IOperationProgressManager operationProgressManager,
ILogger<RevitReceiveBinding> logger,
IRevitConversionSettingsFactory revitConversionSettingsFactory,
ISpeckleApplication speckleApplication
ISpeckleApplication speckleApplication,
RevitToHostCacheSingleton revitToHostCacheSingleton
)
{
Parent = parent;
@@ -48,6 +51,7 @@ internal sealed class RevitReceiveBinding : IReceiveBinding
_revitConversionSettingsFactory = revitConversionSettingsFactory;
_speckleApplication = speckleApplication;
_cancellationManager = cancellationManager;
_revitToHostCacheSingleton = revitToHostCacheSingleton;
Commands = new ReceiveBindingUICommands(parent);
}
@@ -75,7 +79,8 @@ internal sealed class RevitReceiveBinding : IReceiveBinding
DetailLevelType.Coarse, // TODO figure out
null,
false,
true
true,
false
)
);
// Receive host objects
@@ -68,7 +68,8 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
ISpeckleApplication speckleApplication,
ITopLevelExceptionHandler topLevelExceptionHandler,
LinkedModelHandler linkedModelHandler,
IThreadContext threadContext
IThreadContext threadContext,
IRevitTask revitTask
)
: base("sendBinding", bridge)
{
@@ -92,9 +93,12 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
// TODO expiry events
// TODO filters need refresh events
revitContext.UIApplication.NotNull().Application.DocumentChanged += (_, e) =>
_topLevelExceptionHandler.CatchUnhandled(() => DocChangeHandler(e));
_store.DocumentChanged += (_, _) => topLevelExceptionHandler.FireAndForget(async () => await OnDocumentChanged());
revitTask.Run(() =>
{
revitContext.UIApplication.NotNull().Application.DocumentChanged += (_, e) =>
_topLevelExceptionHandler.CatchUnhandled(() => DocChangeHandler(e));
_store.DocumentChanged += (_, _) => topLevelExceptionHandler.FireAndForget(async () => await OnDocumentChanged());
});
}
public List<ISendFilter> GetSendFilters() =>
@@ -109,7 +113,8 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
new DetailLevelSetting(DetailLevelType.Medium),
new ReferencePointSetting(ReferencePointType.InternalOrigin),
new SendParameterNullOrEmptyStringsSetting(false),
new LinkedModelsSetting(true)
new LinkedModelsSetting(true),
new SendRebarsAsVolumetricSetting(false)
];
public void CancelSend(string modelCardId) => _cancellationManager.CancelOperation(modelCardId);
@@ -137,7 +142,8 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
_toSpeckleSettingsManager.GetDetailLevelSetting(modelCard),
_toSpeckleSettingsManager.GetReferencePointSetting(modelCard),
_toSpeckleSettingsManager.GetSendParameterNullOrEmptyStringsSetting(modelCard),
_toSpeckleSettingsManager.GetLinkedModelsSetting(modelCard)
_toSpeckleSettingsManager.GetLinkedModelsSetting(modelCard),
_toSpeckleSettingsManager.GetSendRebarsAsVolumetric(modelCard)
)
);
@@ -206,8 +212,13 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
var elementsOnMainModel = allElements.Where(el => el is not RevitLinkInstance).ToList();
var linkedModels = allElements.OfType<RevitLinkInstance>().ToList();
// create context for main document elements
List<DocumentToConvert> documentElementContexts = [new(null, activeUIDoc.Document, elementsOnMainModel)];
// should ideally reuse the initialized value from the scoped IConverterSettingsStore<RevitConversionSettings>.
// but, it's scoped and to avoid bigger scarier changes I'm re-fetching the setting here (inexpensive operation?)
Transform? mainModelTransform = _toSpeckleSettingsManager.GetReferencePointSetting(modelCard);
List<DocumentToConvert> documentElementContexts =
[
new(mainModelTransform, activeUIDoc.Document, elementsOnMainModel)
];
// get the linked models setting - this decision belongs at this level
bool includeLinkedModels = _toSpeckleSettingsManager.GetLinkedModelsSetting(modelCard);
@@ -226,7 +237,11 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
continue;
}
var transform = linkedModel.GetTotalTransform().Inverse;
// transform maps linked model elements into the main model's reference point coordinate system
// first apply the user's reference point transform (setting) then adjust for the linked model's placement relative to host.
Transform transform = (mainModelTransform ?? Transform.Identity).Multiply(
linkedModel.GetTotalTransform().Inverse
);
// decision about whether to process elements is made here, not in the handler
// only collects elements from linked models when the setting is enabled
@@ -263,10 +278,6 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
modelCard.SendFilter.IdMap,
newSelectedObjectIds
);
// In UI, we are not explicitly trigger UpdateModel to save the state into file for some edge cases. Instead we save it directly via document model store.
// Comment in the UI -> """ otherwise it is leading cleanup on document store bc of deferred action when we switched to the another doc"""
_store.SaveState();
}
return documentElementContexts;
@@ -1,5 +1,6 @@
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.Revit.Plugin;
using Speckle.Converters.RevitShared.Helpers;
using Speckle.Sdk.Common;
@@ -12,30 +13,30 @@ internal sealed class SelectionBinding : RevitBaseBinding, ISelectionBinding, ID
private readonly System.Timers.Timer _selectionTimer;
#endif
private readonly RevitContext _revitContext;
private readonly IAppIdleManager _idleManager;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
public SelectionBinding(
RevitContext revitContext,
IBrowserBridge parent,
IAppIdleManager idleManager,
ITopLevelExceptionHandler topLevelExceptionHandler
ITopLevelExceptionHandler topLevelExceptionHandler,
IRevitTask revitTask
)
: base("selectionBinding", parent)
{
_revitContext = revitContext;
_idleManager = idleManager;
_topLevelExceptionHandler = topLevelExceptionHandler;
#if REVIT2022
// NOTE: getting the selection data should be a fast function all, even for '000s of elements - and having a timer hitting it every 1s is ok.
_selectionTimer = new System.Timers.Timer(1000);
_selectionTimer.Elapsed += (_, _) => _topLevelExceptionHandler.CatchUnhandled(OnSelectionChanged);
_selectionTimer.Elapsed += (_, _) => topLevelExceptionHandler.CatchUnhandled(OnSelectionChanged);
_selectionTimer.Start();
#else
_revitContext.UIApplication.NotNull().SelectionChanged += (_, _) =>
_idleManager.SubscribeToIdle(nameof(OnSelectionChanged), OnSelectionChanged);
revitTask.Run(
() =>
_revitContext.UIApplication.NotNull().SelectionChanged += (_, _) =>
idleManager.SubscribeToIdle(nameof(OnSelectionChanged), OnSelectionChanged)
);
#endif
}
@@ -1,5 +1,5 @@
using System.Reflection;
using Autodesk.Revit.DB;
using CefSharp;
using Microsoft.Extensions.DependencyInjection;
using Speckle.Connectors.Common;
using Speckle.Connectors.Common.Builders;
@@ -15,7 +15,13 @@ using Speckle.Connectors.Revit.Operations.Send;
using Speckle.Connectors.Revit.Operations.Send.Settings;
using Speckle.Connectors.Revit.Plugin;
using Speckle.Converters.Common;
using Speckle.Sdk;
using Speckle.Sdk.Models.GraphTraversal;
#if REVIT2026_OR_GREATER
using Speckle.Connectors.Revit2026.Plugin;
#else
using CefSharp;
#endif
namespace Speckle.Connectors.Revit.DependencyInjection;
@@ -27,6 +33,7 @@ public static class ServiceRegistration
serviceCollection.AddConnectors();
serviceCollection.AddDUI<RevitThreadContext, RevitDocumentStore>();
RegisterUiDependencies(serviceCollection);
serviceCollection.AddMatchingInterfacesAsTransient(Assembly.GetExecutingAssembly());
// Storage Schema
serviceCollection.AddScoped<DocumentModelStorageSchema>();
@@ -80,7 +87,7 @@ public static class ServiceRegistration
serviceCollection.AddSingleton<CefSharpPanel>();
serviceCollection.AddSingleton<IBrowserScriptExecutor>(sp => sp.GetRequiredService<CefSharpPanel>());
serviceCollection.AddSingleton<IRevitPlugin, RevitCefPlugin>();
#else
#elif !REVIT2026_OR_GREATER
// different versions for different versions of CEF
serviceCollection.AddSingleton(BindingOptions.DefaultBinder);
@@ -90,6 +97,11 @@ public static class ServiceRegistration
serviceCollection.AddSingleton(panel);
serviceCollection.AddSingleton<IBrowserScriptExecutor>(c => c.GetRequiredService<CefSharpPanel>());
serviceCollection.AddSingleton<IRevitPlugin, RevitCefPlugin>();
#else
serviceCollection.AddSingleton<IRevitPlugin, RevitWebViewPlugin>();
serviceCollection.AddSingleton<IBrowserScriptExecutor>(c => c.GetRequiredService<RevitControlWebView>());
serviceCollection.AddSingleton<RevitControlWebView>();
serviceCollection.AddSingleton<RevitControlWebViewDockable>();
#endif
}
}
@@ -63,7 +63,9 @@ public class LinkedModelHandler
viewFilter.GetView().NotNull().Id,
linkInstance.Id
);
return viewCollector.WhereElementIsNotElementType().ToElements().ToList();
// NOTE: related to [CNX-1482](https://linear.app/speckle/issue/CNX-1482/wall-sweeps-published-duplicated). See RevitViewsFilter.cs
return viewCollector.WhereElementIsNotElementType().Where(e => !string.IsNullOrEmpty(e.Name)).ToList();
#else
// 🚨 LIMITATION: in Revit 2023 and below, we can only check if the entire linked model is visible,
// not individual elements within it. If the linked model is visible, all its elements will be included.
@@ -2,10 +2,12 @@ using Autodesk.Revit.DB;
using Autodesk.Revit.DB.ExtensibleStorage;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.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;
using Speckle.Connectors.Revit.Plugin;
using Speckle.Converters.RevitShared.Helpers;
using Speckle.Sdk.Common;
@@ -25,15 +27,17 @@ internal sealed class RevitDocumentStore : DocumentModelStore
private readonly IThreadContext _threadContext;
public RevitDocumentStore(
ILogger<DocumentModelStore> logger,
IAppIdleManager idleManager,
RevitContext revitContext,
IJsonSerializer jsonSerializer,
DocumentModelStorageSchema documentModelStorageSchema,
IdStorageSchema idStorageSchema,
ITopLevelExceptionHandler topLevelExceptionHandler,
IThreadContext threadContext
IThreadContext threadContext,
IRevitTask revitTask
)
: base(jsonSerializer)
: base(logger, jsonSerializer)
{
_idleManager = idleManager;
_revitContext = revitContext;
@@ -44,18 +48,21 @@ internal sealed class RevitDocumentStore : DocumentModelStore
UIApplication uiApplication = _revitContext.UIApplication.NotNull();
uiApplication.ViewActivated += (s, e) => _topLevelExceptionHandler.CatchUnhandled(() => OnViewActivated(s, e));
revitTask.Run(() =>
{
uiApplication.ViewActivated += (s, e) => _topLevelExceptionHandler.CatchUnhandled(() => OnViewActivated(s, e));
uiApplication.Application.DocumentOpening += (_, _) =>
_topLevelExceptionHandler.CatchUnhandled(() => IsDocumentInit = false);
uiApplication.Application.DocumentOpening += (_, _) =>
_topLevelExceptionHandler.CatchUnhandled(() => IsDocumentInit = false);
uiApplication.Application.DocumentOpened += (_, _) =>
_topLevelExceptionHandler.CatchUnhandled(() => IsDocumentInit = false);
uiApplication.Application.DocumentOpened += (_, _) =>
_topLevelExceptionHandler.CatchUnhandled(() => IsDocumentInit = false);
// There is no event that we can hook here for double-click file open...
// It is kind of harmless since we create this object as "SingleInstance".
LoadState();
OnDocumentChanged();
// There is no event that we can hook here for double-click file open...
// It is kind of harmless since we create this object as "SingleInstance".
LoadState();
OnDocumentChanged();
});
}
/// <summary>
@@ -87,9 +94,9 @@ internal sealed class RevitDocumentStore : DocumentModelStore
protected override void HostAppSaveState(string modelCardState)
{
var doc = _revitContext.UIApplication?.ActiveUIDocument?.Document;
var document = _revitContext.UIApplication?.ActiveUIDocument?.Document;
// POC: this can happen? A: Not really, imho (dim) (Adam seyz yes it can if loading also triggers a save)
if (doc == null)
if (document == null)
{
return;
}
@@ -97,9 +104,14 @@ internal sealed class RevitDocumentStore : DocumentModelStore
_threadContext
.RunOnMain(() =>
{
using Transaction t = new(doc, "Speckle Write State");
//if not the same active document then don't save the current cards to a bad document!
if (!EnsureActiveDocumentIsSame(document))
{
return;
}
using Transaction t = new(document, "Speckle Write State");
t.Start();
using DataStorage ds = GetSettingsDataStorage(doc) ?? DataStorage.Create(doc);
using DataStorage ds = GetSettingsDataStorage(document) ?? DataStorage.Create(document);
using Entity stateEntity = new(_documentModelStorageSchema.GetSchema());
string serializedModels = Serialize();
@@ -115,6 +127,17 @@ internal sealed class RevitDocumentStore : DocumentModelStore
.FireAndForget();
}
private bool EnsureActiveDocumentIsSame(Document document)
{
var localDoc = _revitContext.UIApplication?.ActiveUIDocument?.Document;
if (localDoc == null)
{
return false;
}
return localDoc.Equals(document);
}
protected override void LoadState()
{
var stateEntity = GetSpeckleEntity(_revitContext.UIApplication?.ActiveUIDocument?.Document);
@@ -13,7 +13,25 @@ public static class SupportedCategoriesUtils
/// <returns></returns>
public static bool IsSupportedCategory(Category? category)
{
if (category is null || !category.IsVisibleInUI)
if (category is null)
{
return false;
}
// stacked walls are "not visible in the ui" whereas they clearly are.
// see [CNX-1301: Revit Stacked Walls are not sending](https://linear.app/speckle/issue/CNX-1301/revit-stacked-walls-are-not-sending)
#if REVIT2023_OR_GREATER
if (category.BuiltInCategory == BuiltInCategory.OST_StackedWalls)
{
return true;
}
#else
if (category.Name == "Stacked Walls")
{
return true;
}
#endif
if (!category.IsVisibleInUI) //&& category.BuiltInCategory != BuiltInCategory.OST_StackedWalls)
{
return false;
}
@@ -14,6 +14,7 @@ using Speckle.Converters.RevitShared.Helpers;
using Speckle.Converters.RevitShared.Settings;
using Speckle.DoubleNumerics;
using Speckle.Objects;
using Speckle.Objects.Data;
using Speckle.Objects.Geometry;
using Speckle.Sdk;
using Speckle.Sdk.Common;
@@ -61,6 +62,17 @@ public sealed class RevitHostObjectBuilder(
CancellationToken cancellationToken
)
{
// TODO: formalise getting transform info from rootObject. this dict access is gross.
Autodesk.Revit.DB.Transform? referencePointTransform = null;
if (
rootObject.DynamicPropertyKeys.Contains(ReferencePointHelper.REFERENCE_POINT_TRANSFORM_KEY)
&& rootObject[ReferencePointHelper.REFERENCE_POINT_TRANSFORM_KEY] is Dictionary<string, object> transformDict
&& transformDict.TryGetValue("transform", out var transformValue)
)
{
referencePointTransform = ReferencePointHelper.GetTransformFromRootObject(transformValue);
}
var baseGroupName = $"Project {projectName}: Model {modelName}"; // TODO: unify this across connectors!
onOperationProgressed.Report(new("Converting", null));
@@ -110,7 +122,17 @@ public sealed class RevitHostObjectBuilder(
{
using var _ = activityFactory.Start("Baking objects");
transactionManager.StartTransaction(true, "Baking objects");
conversionResults = BakeObjects(localToGlobalMaps, onOperationProgressed, cancellationToken);
using (
converterSettings.Push(currentSettings =>
currentSettings with
{
ReferencePointTransform = referencePointTransform
}
)
)
{
conversionResults = BakeObjects(localToGlobalMaps, onOperationProgressed, cancellationToken);
}
transactionManager.CommitTransaction();
}
@@ -167,15 +189,21 @@ public sealed class RevitHostObjectBuilder(
//TODO TransformTo will be deprecated as it's dangerous and requires ID transposing which is wrong!
//ID needs to be copied to the new instance
var id = localToGlobalMap.AtomicObject.id;
var originalAppId = localToGlobalMap.AtomicObject.applicationId;
ITransformable? newTransformable = null;
foreach (var mat in localToGlobalMap.Matrix)
{
transformable.TransformTo(new Transform() { matrix = mat, units = units }, out newTransformable);
transformable = newTransformable; // we need to keep the reference to the new object, as we're going to use it in the cache
transformable = newTransformable;
}
localToGlobalMap.AtomicObject = (newTransformable as Base)!;
localToGlobalMap.AtomicObject.id = id; // restore the id, as it's used in the cache
localToGlobalMap.AtomicObject.id = id;
// Make applicationId unique by appending a short GUID
// This prevents DirectShapeLibrary from using the same definition for multiple instances
localToGlobalMap.AtomicObject.applicationId = $"{originalAppId ?? id}_{Guid.NewGuid().ToString("N")[..8]}"; // hack of all of the ages. related to CNX-1707
localToGlobalMap.Matrix = new HashSet<Matrix4x4>(); // flush out the list, as we've applied the transforms already
}
@@ -192,9 +220,13 @@ public sealed class RevitHostObjectBuilder(
bakedObjectIds.Add(directShapes.UniqueId);
groupManager.AddToTopLevelGroup(directShapes);
if (localToGlobalMap.AtomicObject is IRawEncodedObject and Base myBase)
// we need to establish where the "normal route" is, this targets specifically IRawEncodedObject and
// processes just IRawEncodedObject in maps to create post base paint targets for solids specifically
// this smells big time.
// TODO: created material is wrong nonetheless but visually it all looks correct in Revit. Investigate what is going on
if (localToGlobalMap.AtomicObject is Base myBase)
{
postBakePaintTargets.Add((directShapes, myBase.applicationId ?? myBase.id.NotNull()));
SetSolidPostBakePaintTargets(myBase, directShapes, postBakePaintTargets);
}
conversionResults.Add(
@@ -259,4 +291,24 @@ public sealed class RevitHostObjectBuilder(
}
public void Dispose() => transactionManager?.Dispose();
// NOTE: temp poc HACK!
// this hack only works if we are only assuming one material applied to the solids inside DataObject displayValue. as soon as we have multiple solids with multiple materials it will break again.
// TODO: clean this up / refactor
private void SetSolidPostBakePaintTargets(Base baseObj, DirectShape directShapes, List<(DirectShape, string)> targets)
{
switch (baseObj)
{
case IRawEncodedObject:
targets.Add((directShapes, baseObj.applicationId ?? baseObj.id.NotNull()));
break;
case DataObject dataObj:
foreach (var item in dataObj.displayValue)
{
SetSolidPostBakePaintTargets(item, directShapes, targets);
}
break;
}
}
}
@@ -25,7 +25,7 @@ public class RevitViewsFilter : DiscriminatedObject, ISendFilter, IRevitSendFilt
public RevitViewsFilter(RevitContext revitContext)
{
_revitContext = revitContext;
_doc = _revitContext.UIApplication?.ActiveUIDocument.Document;
_doc = _revitContext.UIApplication?.ActiveUIDocument?.Document;
GetViews();
}
@@ -60,7 +60,7 @@ public class RevitViewsFilter : DiscriminatedObject, ISendFilter, IRevitSendFilt
}
// Paşa Bilal wants it like this... (three dots = important meaning for ogu)
string[] result = SelectedView.Split(new string[] { " - " }, 2, StringSplitOptions.None);
string[] result = SelectedView.Split([" - "], 2, StringSplitOptions.None);
var viewFamilyString = result[0];
var viewString = result[1];
@@ -72,11 +72,17 @@ public class RevitViewsFilter : DiscriminatedObject, ISendFilter, IRevitSendFilt
if (view is null)
{
throw new SpeckleSendFilterException("View not found, please update your model send filter.");
//this used to throw an exception, but we don't want to fail loudly if the view is not found
return [];
}
using var viewCollector = new FilteredElementCollector(_doc, view.Id);
var elementsInView = viewCollector.ToElements();
var objectIds = elementsInView.Select(e => e.UniqueId).ToList();
// NOTE: FilteredElementCollector() includes sweeps and reveals from a wall family's definition and includes them as additional objects
// on this return. displayValue for Wall already includes these, therefore we end up with duplicate elements on wall sweeps
// related to [CNX-1482](https://linear.app/speckle/issue/CNX-1482/wall-sweeps-published-duplicated)
// i (björn) noticed that all these elements have an empty string as Name parameter, hence below exclusion. tested as much as possible, seems like legit fix
var objectIds = elementsInView.Where(e => !string.IsNullOrEmpty(e.Name)).Select(e => e.UniqueId).ToList();
SelectedObjectIds = objectIds;
return objectIds;
}
@@ -241,6 +241,13 @@ public class RevitRootObjectBuilder(
// NOTE: these are currently not used anywhere, we'll skip them until someone calls for it back
// rootObject[ProxyKeys.PARAMETER_DEFINITIONS] = _parameterDefinitionHandler.Definitions;
// we want to store transform data for chosen reference point setting
if (converterSettings.Current.ReferencePointTransform is Transform transform)
{
var transformMatrix = ReferencePointHelper.CreateTransformDataForRootObject(transform);
rootObject[ReferencePointHelper.REFERENCE_POINT_TRANSFORM_KEY] = transformMatrix;
}
return new RootObjectBuilderResult(rootObject, results);
}
}
@@ -0,0 +1,12 @@
using Speckle.Connectors.DUI.Settings;
namespace Speckle.Connectors.Revit.Operations.Send.Settings;
public class SendRebarsAsVolumetricSetting(bool value) : ICardSetting
{
public string? Id { get; set; } = "sendRebarsAsVolumetric";
public string? Title { get; set; } = "Send Rebars As Volumetric";
public string? Type { get; set; } = "boolean";
public object? Value { get; set; } = value;
public List<string>? Enum { get; set; }
}
@@ -22,6 +22,7 @@ public class ToSpeckleSettingsManager : IToSpeckleSettingsManager
private readonly Dictionary<string, Transform?> _referencePointCache = new();
private readonly Dictionary<string, bool?> _sendNullParamsCache = new();
private readonly Dictionary<string, bool?> _sendLinkedModelsCache = new();
private readonly Dictionary<string, bool?> _sendRebarsAsVolumetricCache = new();
public ToSpeckleSettingsManager(
RevitContext revitContext,
@@ -121,6 +122,21 @@ public class ToSpeckleSettingsManager : IToSpeckleSettingsManager
return returnValue;
}
public bool GetSendRebarsAsVolumetric(SenderModelCard modelCard)
{
var value = modelCard.Settings?.First(s => s.Id == "sendRebarsAsVolumetric").Value as bool?;
var returnValue = value != null && value.NotNull();
if (_sendRebarsAsVolumetricCache.TryGetValue(modelCard.ModelCardId.NotNull(), out bool? previousValue))
{
if (previousValue != returnValue)
{
EvictCacheForModelCard(modelCard);
}
}
_sendRebarsAsVolumetricCache[modelCard.ModelCardId] = returnValue;
return returnValue;
}
private void EvictCacheForModelCard(SenderModelCard modelCard)
{
var objectIds = modelCard.SendFilter != null ? modelCard.SendFilter.NotNull().SelectedObjectIds : [];
@@ -174,9 +190,6 @@ public class ToSpeckleSettingsManager : IToSpeckleSettingsManager
case ReferencePointType.InternalOrigin:
break;
default:
break;
}
return referencePointTransform;
@@ -1,3 +1,4 @@
#if !REVIT2026_OR_GREATER
using System.Diagnostics;
using System.IO;
using System.Reflection;
@@ -6,7 +7,6 @@ using System.Windows.Media.Imaging;
using Autodesk.Revit.UI;
using CefSharp;
using Microsoft.Extensions.DependencyInjection;
using Revit.Async;
using Speckle.Connectors.Common;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
@@ -104,7 +104,7 @@ internal sealed class RevitCefPlugin : IRevitPlugin
_revitContext.UIApplication = uiApplication;
// POC: might be worth to interface this out, we shall see...
RevitTask.Initialize(uiApplication);
global::Revit.Async.RevitTask.Initialize(uiApplication);
PostApplicationInit(); // for double-click file open
}
@@ -181,3 +181,4 @@ internal sealed class RevitCefPlugin : IRevitPlugin
return null;
}
}
#endif
@@ -1,7 +1,6 @@
using Autodesk.Revit.UI;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Revit.Async;
using Speckle.Connectors.Common;
using Speckle.Connectors.DUI;
using Speckle.Connectors.Revit.DependencyInjection;
@@ -30,6 +29,8 @@ internal sealed class RevitExternalApplication : IExternalApplication
return HostAppVersion.v2024;
#elif REVIT2025
return HostAppVersion.v2025;
#elif REVIT2026
return HostAppVersion.v2026;
#else
throw new NotImplementedException();
#endif
@@ -50,7 +51,7 @@ internal sealed class RevitExternalApplication : IExternalApplication
_container = services.BuildServiceProvider();
_container.UseDUI();
RevitTask.Initialize(application);
global::Revit.Async.RevitTask.Initialize(application);
// resolve root object
_revitPlugin = _container.GetRequiredService<IRevitPlugin>();
_revitPlugin.Initialise();
@@ -58,7 +59,7 @@ internal sealed class RevitExternalApplication : IExternalApplication
catch (Exception e) when (!e.IsFatal())
{
_container
.GetRequiredService<ILoggerFactory>()
?.GetRequiredService<ILoggerFactory>()
.CreateLogger<RevitExternalApplication>()
.LogCritical(e, "Unhandled exception");
// POC: feedback?
@@ -17,14 +17,17 @@ public sealed class RevitIdleManager : AppIdleManager
public RevitIdleManager(
RevitContext revitContext,
IIdleCallManager idleCallManager,
ITopLevelExceptionHandler topLevelExceptionHandler
ITopLevelExceptionHandler topLevelExceptionHandler,
IRevitTask revitTask
)
: base(idleCallManager)
{
_topLevelExceptionHandler = topLevelExceptionHandler;
_uiApplication = revitContext.UIApplication.NotNull();
_idleCallManager = idleCallManager;
_uiApplication.Idling += (s, e) => OnIdle?.Invoke(s, e); // will be called on the main thread always and fixing the Revit exceptions on subscribing/unsubscribing Idle events
revitTask.Run(
() => _uiApplication.Idling += (s, e) => OnIdle?.Invoke(s, e) // will be called on the main thread always and fixing the Revit exceptions on subscribing/unsubscribing Idle events
);
}
protected override void AddEvent()
@@ -0,0 +1,21 @@
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bridge;
using Speckle.InterfaceGenerator;
namespace Speckle.Connectors.Revit.Plugin;
[GenerateAutoInterface]
public class RevitTask(ITopLevelExceptionHandler topLevelExceptionHandler) : IRevitTask
{
public void Run(Func<Task> handler) =>
global::Revit.Async.RevitTask.RunAsync(() => topLevelExceptionHandler.FireAndForget(handler)).FireAndForget();
public void Run(Action handler) =>
global::Revit.Async.RevitTask.RunAsync(() => topLevelExceptionHandler.CatchUnhandled(handler)).FireAndForget();
public Task RunAsync(Func<Task> handler) =>
global::Revit.Async.RevitTask.RunAsync(() => topLevelExceptionHandler.CatchUnhandledAsync(handler));
public Task RunAsync(Action handler) =>
global::Revit.Async.RevitTask.RunAsync(() => topLevelExceptionHandler.CatchUnhandled(handler));
}
@@ -1,4 +1,3 @@
using Revit.Async;
using Speckle.Connectors.Common.Threading;
using Speckle.Sdk;
@@ -20,11 +19,13 @@ public class RevitThreadContext : ThreadContext
protected override Task<T> RunMainAsync<T>(Func<Task<T>> action) => CatchExceptions(action);
protected override Task RunMain(Action action) => CatchExceptions(action);
private static async Task<T> CatchExceptions<T>(Func<T> action)
{
Exception? ex = null;
//force the usage of the application overload
var ret = await RevitTask.RunAsync(_ =>
var ret = await global::Revit.Async.RevitTask.RunAsync(_ =>
{
try
{
@@ -47,7 +48,7 @@ public class RevitThreadContext : ThreadContext
{
Exception? ex = null;
//force the usage of the application overload
var ret = await RevitTask.RunAsync(async _ =>
var ret = await global::Revit.Async.RevitTask.RunAsync(async _ =>
{
try
{
@@ -70,7 +71,7 @@ public class RevitThreadContext : ThreadContext
{
Exception? ex = null;
//force the usage of the application overload
await RevitTask.RunAsync(async _ =>
await global::Revit.Async.RevitTask.RunAsync(async _ =>
{
try
{
@@ -86,4 +87,25 @@ public class RevitThreadContext : ThreadContext
throw new SpeckleRevitTaskException(ex);
}
}
private static async Task CatchExceptions(Action action)
{
Exception? ex = null;
//force the usage of the application overload
await global::Revit.Async.RevitTask.RunAsync(() =>
{
try
{
action();
}
catch (Exception e) when (!e.IsFatal())
{
ex = e;
}
});
if (ex is not null)
{
throw new SpeckleRevitTaskException(ex);
}
}
}
@@ -45,11 +45,13 @@
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\RevitRootObjectBuilder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\Settings\LinkedModelsSetting.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\Settings\SendParameterNullOrEmptyStringsSetting.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\Settings\SendRebarsAsVolumetricSetting.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\Settings\ToSpeckleSettingsManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\Settings\ReferencePointSetting.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\Settings\DetailLevelSetting.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\IRevitPlugin.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\RevitCommand.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\RevitTask.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\RevitExternalApplication.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\RevitIdleManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\RevitThreadContext.cs" />
+7 -2
View File
@@ -1,7 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<Target AfterTargets="Clean" Name="CleanAddinRhino" Condition="'$(RhinoVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
<RemoveDir Directories="$(AppData)\McNeel\Rhinoceros\$(RhinoVersion).0\Plug-ins\Speckle.Connectors.Rhino$(RhinoVersion) (8dd5f30b-a13d-4a24-abdc-3e05c8c87144)" />
<ItemGroup>
<PublicReleasePath Include="$(AppData)\McNeel\Rhinoceros\$(RhinoVersion).0\Plug-ins\Speckle.Connectors.Rhino$(RhinoVersion) (2153799A-0CEC-40DE-BC3A-01E5055222FF)" />
</ItemGroup>
<Target AfterTargets="Build" Name="WarnIfPublicReleaseVersionInstalled" Condition="'$(RhinoVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
<Warning
Text="Conflicting Rhino plugin detected - Do you have a public release installed?"
Condition="Exists(@(PublicReleasePath))" />
</Target>
<Target AfterTargets="Build" Name="AfterBuildRhino" Condition="'$(RhinoVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
@@ -0,0 +1,20 @@
{
"profiles": {
"Rhino7Core": {
"commandName": "Executable",
"executablePath": "C:\\Program Files\\Rhino 7\\System\\Rhino.exe",
"commandLineArgs": "/netcore /runscript=\"_Grasshopper\"",
"environmentVariables": {
"RHINO_PACKAGE_DIRS": "$(ProjectDir)$(OutputPath)\\"
}
},
"Rhino7NetFx": {
"commandName": "Executable",
"executablePath": "C:\\Program Files\\Rhino 7\\System\\Rhino.exe",
"commandLineArgs": "/netfx /runscript=\"_Grasshopper\"",
"environmentVariables": {
"RHINO_PACKAGE_DIRS": "$(ProjectDir)$(OutputPath)\\"
}
}
}
}
@@ -0,0 +1,44 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Select the framework(s) you wish to target.
Rhino 6: net45
Rhino 7: net48
Rhino 8 Windows: net48, net7.0, net7.0-windows, net7.0-windows10.0.22000.0, etc
Rhino 8 Mac: net7.0, net7.0-macos, net7.0-macos12.0, etc
-->
<TargetFramework>net48</TargetFramework>
<Configurations>Debug;Release;Local</Configurations>
<TargetExt>.gha</TargetExt>
<EnableWindowsTargeting>true</EnableWindowsTargeting>
<UseWindowsForms>true</UseWindowsForms>
<!--Root Namespace needs to be aligned across all grasshopper csproj to ensure the .resx file in the shared project has the correct resource namespace-->
<RootNamespace>Speckle.Connectors.GrasshopperShared</RootNamespace>
<DefineConstants>$(DefineConstants);GRASSHOPPER;RHINO7;RHINO7_OR_GREATER</DefineConstants>
</PropertyGroup>
<PropertyGroup>
<Title>Speckle.Connectors.Grasshopper7</Title>
<Description>Description of Speckle.Connectors.Grasshopper7</Description>
</PropertyGroup>
<PropertyGroup>
<NeutralLanguage>en-US</NeutralLanguage>
<GenerateResourceUsePreserializedResources>True</GenerateResourceUsePreserializedResources>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="GrasshopperAsyncComponent" />
<PackageReference Include="RhinoCommon" IncludeAssets="compile; build" PrivateAssets="all" VersionOverride="7.13.21348.13001" />
<PackageReference Include="Grasshopper" IncludeAssets="compile; build" PrivateAssets="all" VersionOverride="7.13.21348.13001" />
<PackageReference Include="System.Resources.Extensions" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Converters\Rhino\Speckle.Converters.Rhino7\Speckle.Converters.Rhino7.csproj" />
<ProjectReference Include="..\..\..\Sdk\Speckle.Connectors.Common\Speckle.Connectors.Common.csproj" />
</ItemGroup>
<Import Project="..\Speckle.Connectors.GrasshopperShared\Speckle.Connectors.GrasshopperShared.projitems" Label="Shared" />
</Project>
@@ -0,0 +1,414 @@
{
"version": 2,
"dependencies": {
".NETFramework,Version=v4.8": {
"Grasshopper": {
"type": "Direct",
"requested": "[7.13.21348.13001, )",
"resolved": "7.13.21348.13001",
"contentHash": "XoxWouU2mzZAmj4kRP/ZqsKG+7e6Q+NBBitJSK/uxjuV8vNsGK2K19GW5ptDjjPuhd7GBI00KSB8Q1+JYFjELA==",
"dependencies": {
"RhinoCommon": "[7.13.21348.13001]"
}
},
"GrasshopperAsyncComponent": {
"type": "Direct",
"requested": "[1.2.3, )",
"resolved": "1.2.3",
"contentHash": "KdCmyZ7Su8T3wb5t5BEbSg2inz+aJfGFHpDysColTdeyYX9S6MRJK69UV4kYYHE+ro1FKPADOwoSE6eLKq/yDA=="
},
"Microsoft.NETFramework.ReferenceAssemblies": {
"type": "Direct",
"requested": "[1.0.3, )",
"resolved": "1.0.3",
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
"dependencies": {
"Microsoft.NETFramework.ReferenceAssemblies.net48": "1.0.3"
}
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
"dependencies": {
"Microsoft.Build.Tasks.Git": "8.0.0",
"Microsoft.SourceLink.Common": "8.0.0"
}
},
"PolySharp": {
"type": "Direct",
"requested": "[1.14.1, )",
"resolved": "1.14.1",
"contentHash": "mOOmFYwad3MIOL14VCjj02LljyF1GNw1wP0YVlxtcPvqdxjGGMNdNJJxHptlry3MOd8b40Flm8RPOM8JOlN2sQ=="
},
"RhinoCommon": {
"type": "Direct",
"requested": "[7.13.21348.13001, )",
"resolved": "7.13.21348.13001",
"contentHash": "JQdaNw61ddBqIe08E9O4N/grwrN1hjDHcYW7tWylwCZyFR7SepoCD4NS+6LN6+oSQhNbhLi9Bf+hQOFYFdRAEA=="
},
"Speckle.InterfaceGenerator": {
"type": "Direct",
"requested": "[0.9.6, )",
"resolved": "0.9.6",
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
},
"System.Resources.Extensions": {
"type": "Direct",
"requested": "[9.0.4, )",
"resolved": "9.0.4",
"contentHash": "X1oj5i1gy6O4TDU8Z48djqbDJJz4qkT+LgvD0Z2pbCsXieJNms9H5yBbvahXdEJad07Ntai5bST4J5XWoNmMsg==",
"dependencies": {
"System.Formats.Nrbf": "9.0.4",
"System.Memory": "4.5.5"
}
},
"GraphQL.Client": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "8yPNBbuVBpTptivyAlak4GZvbwbUcjeQTL4vN1HKHRuOykZ4r7l5fcLS6vpyPyLn0x8FsL31xbOIKyxbmR9rbA==",
"dependencies": {
"GraphQL.Client.Abstractions": "6.0.0",
"GraphQL.Client.Abstractions.Websocket": "6.0.0",
"System.Net.WebSockets.Client.Managed": "1.0.22",
"System.Reactive": "5.0.0"
}
},
"GraphQL.Client.Abstractions": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "h7uzWFORHZ+CCjwr/ThAyXMr0DPpzEANDa4Uo54wqCQ+j7qUKwqYTgOrb1W40sqbvNaZm9v/X7It31SUw0maHA==",
"dependencies": {
"GraphQL.Primitives": "6.0.0"
}
},
"GraphQL.Client.Abstractions.Websocket": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "Nr9bPf8gIOvLuXpqEpqr9z9jslYFJOvd0feHth3/kPqeR3uMbjF5pjiwh4jxyMcxHdr8Pb6QiXkV3hsSyt0v7A==",
"dependencies": {
"GraphQL.Client.Abstractions": "6.0.0"
}
},
"GraphQL.Primitives": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "yg72rrYDapfsIUrul7aF6wwNnTJBOFvuA9VdDTQpPa8AlAriHbufeXYLBcodKjfUdkCnaiggX1U/nEP08Zb5GA=="
},
"Microsoft.Bcl.AsyncInterfaces": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ==",
"dependencies": {
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
"Microsoft.Bcl.HashCode": {
"type": "Transitive",
"resolved": "1.1.1",
"contentHash": "MalY0Y/uM/LjXtHfX/26l2VtN4LDNZ2OE3aumNOHDLsT4fNYy2hiHXI4CXCqKpNUNm7iJ2brrc4J89UdaL56FA=="
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
},
"Microsoft.CSharp": {
"type": "Transitive",
"resolved": "4.7.0",
"contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA=="
},
"Microsoft.Data.Sqlite": {
"type": "Transitive",
"resolved": "7.0.5",
"contentHash": "KGxbPeWsQMnmQy43DSBxAFtHz3l2JX8EWBSGUCvT3CuZ8KsuzbkqMIJMDOxWtG8eZSoCDI04aiVQjWuuV8HmSw==",
"dependencies": {
"Microsoft.Data.Sqlite.Core": "7.0.5",
"SQLitePCLRaw.bundle_e_sqlite3": "2.1.4"
}
},
"Microsoft.Data.Sqlite.Core": {
"type": "Transitive",
"resolved": "7.0.5",
"contentHash": "FTerRmQPqHrCrnoUzhBu+E+1DNGwyrAMLqHkAqOOOu5pGfyMOj8qQUBxI/gDtWtG11p49UxSfWmBzRNlwZqfUg==",
"dependencies": {
"SQLitePCLRaw.core": "2.1.4"
}
},
"Microsoft.Extensions.Configuration": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==",
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "2.2.0"
}
},
"Microsoft.Extensions.Configuration.Abstractions": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==",
"dependencies": {
"Microsoft.Extensions.Primitives": "2.2.0"
}
},
"Microsoft.Extensions.Configuration.Binder": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "vJ9xvOZCnUAIHcGC3SU35r3HKmHTVIeHzo6u/qzlHAqD8m6xv92MLin4oJntTvkpKxVX3vI1GFFkIQtU3AdlsQ==",
"dependencies": {
"Microsoft.Extensions.Configuration": "2.2.0"
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "f9hstgjVmr6rmrfGSpfsVOl2irKAgr1QjrSi3FgnS7kulxband50f2brRLwySAQTADPZeTdow0mpSMcoAdadCw=="
},
"Microsoft.Extensions.Options": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Primitives": "2.2.0",
"System.ComponentModel.Annotations": "4.5.0"
}
},
"Microsoft.Extensions.Primitives": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==",
"dependencies": {
"System.Memory": "4.5.1",
"System.Runtime.CompilerServices.Unsafe": "4.5.1"
}
},
"Microsoft.NETFramework.ReferenceAssemblies.net48": {
"type": "Transitive",
"resolved": "1.0.3",
"contentHash": "zMk4D+9zyiEWByyQ7oPImPN/Jhpj166Ky0Nlla4eXlNL8hI/BtSJsgR8Inldd4NNpIAH3oh8yym0W2DrhXdSLQ=="
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Speckle.Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.2",
"contentHash": "g1BejUZwax5PRfL6xHgLEK23sqHWOgOj9hE7RvfRRlN00AGt8GnPYt8HedSK7UB3HiRW8zCA9Pn0iiYxCK24BA=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "EWI1olKDjFEBMJu0+3wuxwziIAdWDVMYLhuZ3Qs84rrz+DHwD00RzWPZCa+bLnHCf3oJwuFZIRsHT5p236QXww==",
"dependencies": {
"SQLitePCLRaw.lib.e_sqlite3": "2.1.4",
"SQLitePCLRaw.provider.dynamic_cdecl": "2.1.4"
}
},
"SQLitePCLRaw.core": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "inBjvSHo9UDKneGNzfUfDjK08JzlcIhn1+SP5Y3m6cgXpCxXKCJDy6Mka7LpgSV+UZmKSnC8rTwB0SQ0xKu5pA==",
"dependencies": {
"System.Memory": "4.5.3"
}
},
"SQLitePCLRaw.lib.e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
},
"SQLitePCLRaw.provider.dynamic_cdecl": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "ZsaKKhgYF9B1fvcnOGKl3EycNAwd9CRWX7v0rEfuPWhQQ5Jjpvf2VEHahiLIGHio3hxi3EIKFJw9KvyowWOUAw==",
"dependencies": {
"SQLitePCLRaw.core": "2.1.4"
}
},
"System.Buffers": {
"type": "Transitive",
"resolved": "4.5.1",
"contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
},
"System.Collections.Immutable": {
"type": "Transitive",
"resolved": "9.0.4",
"contentHash": "wfm2NgK22MmBe5qJjp52qzpkeDZKb4l9LbdubhZSehY1z4LS+lld6R+B+UQNb2AZRHu/QJlHxEUcRst5hIEejg==",
"dependencies": {
"System.Memory": "4.5.5",
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
}
},
"System.ComponentModel.Annotations": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
},
"System.Formats.Nrbf": {
"type": "Transitive",
"resolved": "9.0.4",
"contentHash": "HuDjUInoaQvnX+3bRg2lX+KLD2raiDJA0v3c4hmukAHSQT8rpa6+2NKRoz+1W8Jmbu5ocvc+xPPKgHMVjeJpOg==",
"dependencies": {
"Microsoft.Bcl.HashCode": "1.1.1",
"System.Reflection.Metadata": "9.0.4",
"System.ValueTuple": "4.5.0"
}
},
"System.Memory": {
"type": "Transitive",
"resolved": "4.5.5",
"contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==",
"dependencies": {
"System.Buffers": "4.5.1",
"System.Numerics.Vectors": "4.5.0",
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
}
},
"System.Net.WebSockets.Client.Managed": {
"type": "Transitive",
"resolved": "1.0.22",
"contentHash": "WqEOxPlXjuZrIjUtXNE9NxEfU/n5E35iV2PtoZdJSUC4tlrqwHnTee+wvMIM4OUaJWmwrymeqcgYrE0IkGAgLA==",
"dependencies": {
"System.Buffers": "4.4.0",
"System.Numerics.Vectors": "4.4.0"
}
},
"System.Numerics.Vectors": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ=="
},
"System.Reactive": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ==",
"dependencies": {
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
"System.Reflection.Metadata": {
"type": "Transitive",
"resolved": "9.0.4",
"contentHash": "qeJNsMmZPc/Lieg0Md+D4F6LoLcxV3b9QsUNmBRXc2ZVOkMbAcwuO9l2jbQFv3n+fLiHJilN8v6i5aJNivjrCQ==",
"dependencies": {
"System.Collections.Immutable": "9.0.4",
"System.Memory": "4.5.5"
}
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
},
"System.Threading.Tasks.Extensions": {
"type": "Transitive",
"resolved": "4.5.4",
"contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==",
"dependencies": {
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
}
},
"System.ValueTuple": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ=="
},
"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.logging": {
"type": "Project"
},
"speckle.converters.common": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.3.5, )"
}
},
"speckle.converters.rhino7": {
"type": "Project",
"dependencies": {
"RhinoCommon": "[7.13.21348.13001, )",
"Speckle.Converters.Common": "[1.0.0, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0"
}
},
"Microsoft.Extensions.Logging": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==",
"dependencies": {
"Microsoft.Extensions.Configuration.Binder": "2.2.0",
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Logging.Abstractions": "2.2.0",
"Microsoft.Extensions.Options": "2.2.0"
}
},
"Microsoft.Extensions.Logging.Abstractions": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
},
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"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",
"Microsoft.CSharp": "4.7.0",
"Microsoft.Data.Sqlite": "7.0.5",
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
}
}
}
@@ -0,0 +1,20 @@
{
"profiles": {
"Rhino8Core": {
"commandName": "Executable",
"executablePath": "C:\\Program Files\\Rhino 8\\System\\Rhino.exe",
"commandLineArgs": "/netcore /runscript=\"_Grasshopper\"",
"environmentVariables": {
"RHINO_PACKAGE_DIRS": "$(ProjectDir)$(OutputPath)\\"
}
},
"Rhino8NetFx": {
"commandName": "Executable",
"executablePath": "C:\\Program Files\\Rhino 8\\System\\Rhino.exe",
"commandLineArgs": "/netfx /runscript=\"_Grasshopper\"",
"environmentVariables": {
"RHINO_PACKAGE_DIRS": "$(ProjectDir)$(OutputPath)\\"
}
}
}
}
@@ -0,0 +1,55 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Select the framework(s) you wish to target.
Rhino 6: net45
Rhino 7: net48
Rhino 8 Windows: net48, net7.0, net7.0-windows, net7.0-windows10.0.22000.0, etc
Rhino 8 Mac: net7.0, net7.0-macos, net7.0-macos12.0, etc
-->
<TargetFramework>net48</TargetFramework>
<Configurations>Debug;Release;Local</Configurations>
<TargetExt>.gha</TargetExt>
<EnableWindowsTargeting>true</EnableWindowsTargeting>
<UseWindowsForms>true</UseWindowsForms>
<!--Root Namespace needs to be aligned across all grasshopper csproj to ensure the .resx file in the shared project has the correct resource namespace-->
<RootNamespace>Speckle.Connectors.GrasshopperShared</RootNamespace>
<DefineConstants>$(DefineConstants);GRASSHOPPER;RHINO8;RHINO7_OR_GREATER;RHINO8_OR_GREATER</DefineConstants>
</PropertyGroup>
<PropertyGroup>
<NeutralLanguage>en-US</NeutralLanguage>
<GenerateResourceUsePreserializedResources>True</GenerateResourceUsePreserializedResources>
</PropertyGroup>
<PropertyGroup>
<Title>Speckle.Connectors.Grasshopper8</Title>
<Description>Description of Speckle.Connectors.Grasshopper8</Description>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="GrasshopperAsyncComponent" />
<PackageReference Include="RhinoCommon" IncludeAssets="compile; build" PrivateAssets="all" />
<PackageReference Include="Grasshopper" IncludeAssets="compile; build" PrivateAssets="all" />
<PackageReference Include="System.Resources.Extensions" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Converters\Rhino\Speckle.Converters.Rhino8\Speckle.Converters.Rhino8.csproj" />
<ProjectReference Include="..\..\..\Sdk\Speckle.Connectors.Common\Speckle.Connectors.Common.csproj" />
</ItemGroup>
<ItemGroup>
<!--
*.gh files are copied by the rhino.iss file into %appdata%\Grasshopper\Libraries
Since that folder is not specific to any Rhino version, only one Speckle.Connectors.Grasshopper
project need copy it to the output dir (tho this needs to be aligned in the iss file)
-->
<Content Include="..\Sample Files\*.gh">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Import Project="..\Speckle.Connectors.GrasshopperShared\Speckle.Connectors.GrasshopperShared.projitems" Label="Shared" />
</Project>
@@ -0,0 +1,414 @@
{
"version": 2,
"dependencies": {
".NETFramework,Version=v4.8": {
"Grasshopper": {
"type": "Direct",
"requested": "[8.9.24194.18121, )",
"resolved": "8.9.24194.18121",
"contentHash": "ZQ7vT1urn9jG2KLMdT/aVhCsijN349lj2Lrg7+Cd5A84KOW+RIErG6IqH+133hc9HT9D10+7oi/XnIlgYZRzqQ==",
"dependencies": {
"RhinoCommon": "[8.9.24194.18121]"
}
},
"GrasshopperAsyncComponent": {
"type": "Direct",
"requested": "[1.2.3, )",
"resolved": "1.2.3",
"contentHash": "KdCmyZ7Su8T3wb5t5BEbSg2inz+aJfGFHpDysColTdeyYX9S6MRJK69UV4kYYHE+ro1FKPADOwoSE6eLKq/yDA=="
},
"Microsoft.NETFramework.ReferenceAssemblies": {
"type": "Direct",
"requested": "[1.0.3, )",
"resolved": "1.0.3",
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
"dependencies": {
"Microsoft.NETFramework.ReferenceAssemblies.net48": "1.0.3"
}
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
"dependencies": {
"Microsoft.Build.Tasks.Git": "8.0.0",
"Microsoft.SourceLink.Common": "8.0.0"
}
},
"PolySharp": {
"type": "Direct",
"requested": "[1.14.1, )",
"resolved": "1.14.1",
"contentHash": "mOOmFYwad3MIOL14VCjj02LljyF1GNw1wP0YVlxtcPvqdxjGGMNdNJJxHptlry3MOd8b40Flm8RPOM8JOlN2sQ=="
},
"RhinoCommon": {
"type": "Direct",
"requested": "[8.9.24194.18121, )",
"resolved": "8.9.24194.18121",
"contentHash": "XRMnm38sBFeMT5AAtRTJdSaql/YNtT02AGi8TEVP1VZ4fkm8VJ1q2nNioWN3tW/+H8Tdi4nV+DuhB/5uE41MCg=="
},
"Speckle.InterfaceGenerator": {
"type": "Direct",
"requested": "[0.9.6, )",
"resolved": "0.9.6",
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
},
"System.Resources.Extensions": {
"type": "Direct",
"requested": "[9.0.4, )",
"resolved": "9.0.4",
"contentHash": "X1oj5i1gy6O4TDU8Z48djqbDJJz4qkT+LgvD0Z2pbCsXieJNms9H5yBbvahXdEJad07Ntai5bST4J5XWoNmMsg==",
"dependencies": {
"System.Formats.Nrbf": "9.0.4",
"System.Memory": "4.5.5"
}
},
"GraphQL.Client": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "8yPNBbuVBpTptivyAlak4GZvbwbUcjeQTL4vN1HKHRuOykZ4r7l5fcLS6vpyPyLn0x8FsL31xbOIKyxbmR9rbA==",
"dependencies": {
"GraphQL.Client.Abstractions": "6.0.0",
"GraphQL.Client.Abstractions.Websocket": "6.0.0",
"System.Net.WebSockets.Client.Managed": "1.0.22",
"System.Reactive": "5.0.0"
}
},
"GraphQL.Client.Abstractions": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "h7uzWFORHZ+CCjwr/ThAyXMr0DPpzEANDa4Uo54wqCQ+j7qUKwqYTgOrb1W40sqbvNaZm9v/X7It31SUw0maHA==",
"dependencies": {
"GraphQL.Primitives": "6.0.0"
}
},
"GraphQL.Client.Abstractions.Websocket": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "Nr9bPf8gIOvLuXpqEpqr9z9jslYFJOvd0feHth3/kPqeR3uMbjF5pjiwh4jxyMcxHdr8Pb6QiXkV3hsSyt0v7A==",
"dependencies": {
"GraphQL.Client.Abstractions": "6.0.0"
}
},
"GraphQL.Primitives": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "yg72rrYDapfsIUrul7aF6wwNnTJBOFvuA9VdDTQpPa8AlAriHbufeXYLBcodKjfUdkCnaiggX1U/nEP08Zb5GA=="
},
"Microsoft.Bcl.AsyncInterfaces": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ==",
"dependencies": {
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
"Microsoft.Bcl.HashCode": {
"type": "Transitive",
"resolved": "1.1.1",
"contentHash": "MalY0Y/uM/LjXtHfX/26l2VtN4LDNZ2OE3aumNOHDLsT4fNYy2hiHXI4CXCqKpNUNm7iJ2brrc4J89UdaL56FA=="
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
},
"Microsoft.CSharp": {
"type": "Transitive",
"resolved": "4.7.0",
"contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA=="
},
"Microsoft.Data.Sqlite": {
"type": "Transitive",
"resolved": "7.0.5",
"contentHash": "KGxbPeWsQMnmQy43DSBxAFtHz3l2JX8EWBSGUCvT3CuZ8KsuzbkqMIJMDOxWtG8eZSoCDI04aiVQjWuuV8HmSw==",
"dependencies": {
"Microsoft.Data.Sqlite.Core": "7.0.5",
"SQLitePCLRaw.bundle_e_sqlite3": "2.1.4"
}
},
"Microsoft.Data.Sqlite.Core": {
"type": "Transitive",
"resolved": "7.0.5",
"contentHash": "FTerRmQPqHrCrnoUzhBu+E+1DNGwyrAMLqHkAqOOOu5pGfyMOj8qQUBxI/gDtWtG11p49UxSfWmBzRNlwZqfUg==",
"dependencies": {
"SQLitePCLRaw.core": "2.1.4"
}
},
"Microsoft.Extensions.Configuration": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==",
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "2.2.0"
}
},
"Microsoft.Extensions.Configuration.Abstractions": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==",
"dependencies": {
"Microsoft.Extensions.Primitives": "2.2.0"
}
},
"Microsoft.Extensions.Configuration.Binder": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "vJ9xvOZCnUAIHcGC3SU35r3HKmHTVIeHzo6u/qzlHAqD8m6xv92MLin4oJntTvkpKxVX3vI1GFFkIQtU3AdlsQ==",
"dependencies": {
"Microsoft.Extensions.Configuration": "2.2.0"
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "f9hstgjVmr6rmrfGSpfsVOl2irKAgr1QjrSi3FgnS7kulxband50f2brRLwySAQTADPZeTdow0mpSMcoAdadCw=="
},
"Microsoft.Extensions.Options": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Primitives": "2.2.0",
"System.ComponentModel.Annotations": "4.5.0"
}
},
"Microsoft.Extensions.Primitives": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==",
"dependencies": {
"System.Memory": "4.5.1",
"System.Runtime.CompilerServices.Unsafe": "4.5.1"
}
},
"Microsoft.NETFramework.ReferenceAssemblies.net48": {
"type": "Transitive",
"resolved": "1.0.3",
"contentHash": "zMk4D+9zyiEWByyQ7oPImPN/Jhpj166Ky0Nlla4eXlNL8hI/BtSJsgR8Inldd4NNpIAH3oh8yym0W2DrhXdSLQ=="
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Speckle.Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.2",
"contentHash": "g1BejUZwax5PRfL6xHgLEK23sqHWOgOj9hE7RvfRRlN00AGt8GnPYt8HedSK7UB3HiRW8zCA9Pn0iiYxCK24BA=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "EWI1olKDjFEBMJu0+3wuxwziIAdWDVMYLhuZ3Qs84rrz+DHwD00RzWPZCa+bLnHCf3oJwuFZIRsHT5p236QXww==",
"dependencies": {
"SQLitePCLRaw.lib.e_sqlite3": "2.1.4",
"SQLitePCLRaw.provider.dynamic_cdecl": "2.1.4"
}
},
"SQLitePCLRaw.core": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "inBjvSHo9UDKneGNzfUfDjK08JzlcIhn1+SP5Y3m6cgXpCxXKCJDy6Mka7LpgSV+UZmKSnC8rTwB0SQ0xKu5pA==",
"dependencies": {
"System.Memory": "4.5.3"
}
},
"SQLitePCLRaw.lib.e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
},
"SQLitePCLRaw.provider.dynamic_cdecl": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "ZsaKKhgYF9B1fvcnOGKl3EycNAwd9CRWX7v0rEfuPWhQQ5Jjpvf2VEHahiLIGHio3hxi3EIKFJw9KvyowWOUAw==",
"dependencies": {
"SQLitePCLRaw.core": "2.1.4"
}
},
"System.Buffers": {
"type": "Transitive",
"resolved": "4.5.1",
"contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
},
"System.Collections.Immutable": {
"type": "Transitive",
"resolved": "9.0.4",
"contentHash": "wfm2NgK22MmBe5qJjp52qzpkeDZKb4l9LbdubhZSehY1z4LS+lld6R+B+UQNb2AZRHu/QJlHxEUcRst5hIEejg==",
"dependencies": {
"System.Memory": "4.5.5",
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
}
},
"System.ComponentModel.Annotations": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
},
"System.Formats.Nrbf": {
"type": "Transitive",
"resolved": "9.0.4",
"contentHash": "HuDjUInoaQvnX+3bRg2lX+KLD2raiDJA0v3c4hmukAHSQT8rpa6+2NKRoz+1W8Jmbu5ocvc+xPPKgHMVjeJpOg==",
"dependencies": {
"Microsoft.Bcl.HashCode": "1.1.1",
"System.Reflection.Metadata": "9.0.4",
"System.ValueTuple": "4.5.0"
}
},
"System.Memory": {
"type": "Transitive",
"resolved": "4.5.5",
"contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==",
"dependencies": {
"System.Buffers": "4.5.1",
"System.Numerics.Vectors": "4.5.0",
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
}
},
"System.Net.WebSockets.Client.Managed": {
"type": "Transitive",
"resolved": "1.0.22",
"contentHash": "WqEOxPlXjuZrIjUtXNE9NxEfU/n5E35iV2PtoZdJSUC4tlrqwHnTee+wvMIM4OUaJWmwrymeqcgYrE0IkGAgLA==",
"dependencies": {
"System.Buffers": "4.4.0",
"System.Numerics.Vectors": "4.4.0"
}
},
"System.Numerics.Vectors": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ=="
},
"System.Reactive": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ==",
"dependencies": {
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
"System.Reflection.Metadata": {
"type": "Transitive",
"resolved": "9.0.4",
"contentHash": "qeJNsMmZPc/Lieg0Md+D4F6LoLcxV3b9QsUNmBRXc2ZVOkMbAcwuO9l2jbQFv3n+fLiHJilN8v6i5aJNivjrCQ==",
"dependencies": {
"System.Collections.Immutable": "9.0.4",
"System.Memory": "4.5.5"
}
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
},
"System.Threading.Tasks.Extensions": {
"type": "Transitive",
"resolved": "4.5.4",
"contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==",
"dependencies": {
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
}
},
"System.ValueTuple": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ=="
},
"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.logging": {
"type": "Project"
},
"speckle.converters.common": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.3.5, )"
}
},
"speckle.converters.rhino8": {
"type": "Project",
"dependencies": {
"RhinoCommon": "[8.9.24194.18121, )",
"Speckle.Converters.Common": "[1.0.0, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0"
}
},
"Microsoft.Extensions.Logging": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==",
"dependencies": {
"Microsoft.Extensions.Configuration.Binder": "2.2.0",
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Logging.Abstractions": "2.2.0",
"Microsoft.Extensions.Options": "2.2.0"
}
},
"Microsoft.Extensions.Logging.Abstractions": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
},
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
"dependencies": {
"Speckle.Sdk": "3.3.5"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"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",
"Microsoft.CSharp": "4.7.0",
"Microsoft.Data.Sqlite": "7.0.5",
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Logging": "2.2.0",
"Speckle.DoubleNumerics": "4.1.0",
"Speckle.Newtonsoft.Json": "13.0.2",
"Speckle.Sdk.Dependencies": "3.3.5"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.3.5, )",
"resolved": "3.3.5",
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
}
}
}
}
@@ -0,0 +1,101 @@
namespace Speckle.Connectors.GrasshopperShared.Components.BaseComponents;
internal static class Operator
{
public enum CompareMethod
{
Nothing,
Equals,
StartsWith, // <
EndsWith, // >
Contains, // ?
Wildcard, // :
Regex, // ;
}
public static CompareMethod CompareMethodFromPattern(string pattern)
{
bool not = false;
return CompareMethodFromPattern(ref pattern, ref not);
}
public static CompareMethod CompareMethodFromPattern(ref string pattern, ref bool not)
{
if (pattern is null)
{
return CompareMethod.Nothing;
}
if (string.IsNullOrEmpty(pattern))
{
return CompareMethod.Equals;
}
switch (pattern[0])
{
case '~':
not = !not;
pattern = pattern[1..];
return CompareMethodFromPattern(ref pattern, ref not);
case '<':
pattern = pattern[1..];
return string.IsNullOrEmpty(pattern) ? CompareMethod.Equals : CompareMethod.StartsWith;
case '>':
pattern = pattern[1..];
return string.IsNullOrEmpty(pattern) ? CompareMethod.Equals : CompareMethod.EndsWith;
case '?':
pattern = pattern[1..];
return string.IsNullOrEmpty(pattern) ? CompareMethod.Equals : CompareMethod.Contains;
case ':':
pattern = pattern[1..];
return string.IsNullOrEmpty(pattern) ? CompareMethod.Equals : CompareMethod.Wildcard;
case ';':
pattern = pattern[1..];
return string.IsNullOrEmpty(pattern) ? CompareMethod.Equals : CompareMethod.Regex;
default:
return CompareMethod.Equals;
}
}
public static bool IsSymbolNameLike(this string source, string pattern)
{
if (pattern is null)
{
return true;
}
if (pattern == source)
{
return true;
}
bool not = false;
switch (CompareMethodFromPattern(ref pattern, ref not))
{
case CompareMethod.Nothing:
return not ^ false;
case CompareMethod.Equals:
return not ^ string.Equals(source, pattern, StringComparison.Ordinal);
case CompareMethod.StartsWith:
return not ^ source.StartsWith(pattern, StringComparison.Ordinal);
case CompareMethod.EndsWith:
return not ^ source.EndsWith(pattern, StringComparison.Ordinal);
case CompareMethod.Contains:
return not ^ (source.IndexOf(pattern, StringComparison.Ordinal) >= 0);
/*
case CompareMethod.Wildcard:
return not
^ Microsoft.VisualBasic.CompilerServices.LikeOperator.LikeString(
source,
pattern,
Microsoft.VisualBasic.CompareMethod.Text
);
*/
case CompareMethod.Regex:
var regex = new System.Text.RegularExpressions.Regex(pattern);
return not ^ regex.IsMatch(source);
}
return false;
}
}
@@ -0,0 +1,25 @@
using Microsoft.Extensions.DependencyInjection;
using Speckle.Connectors.GrasshopperShared.Registration;
namespace Speckle.Connectors.GrasshopperShared.Components.BaseComponents;
public abstract class SpeckleScopedTaskCapableComponent<TInput, TOutput>(
string name,
string nickname,
string description,
string category,
string subCategory
) : SpeckleTaskCapableComponent<TInput, TOutput>(name, nickname, description, category, subCategory)
{
protected override Task<TOutput> PerformTask(TInput input, CancellationToken cancellationToken = default)
{
/*using*/var scope = PriorityLoader.Container.CreateScope(); // NOTE: this component does not work as intended in e.g the receive component; the scope gets disposed before the task completes.
return PerformScopedTask(input, scope, cancellationToken);
}
protected abstract Task<TOutput> PerformScopedTask(
TInput input,
IServiceScope scope,
CancellationToken cancellationToken = default
);
}
@@ -0,0 +1,60 @@
using Grasshopper.Kernel;
using Speckle.Sdk;
namespace Speckle.Connectors.GrasshopperShared.Components.BaseComponents;
public abstract class SpeckleTaskCapableComponent<TInput, TOutput>(
string name,
string nickname,
string description,
string category,
string subCategory
) : GH_TaskCapableComponent<TOutput>(name, nickname, description, category, subCategory)
{
protected override void SolveInstance(IGH_DataAccess da)
{
//TODO: We're missing activity and logging here. Will enable it for all inherited classes.
if (InPreSolve)
{
// Collect the data and create the task
try
{
var input = GetInput(da);
TaskList.Add(PerformTask(input, CancelToken));
}
catch (SpeckleException e)
{
Console.WriteLine(e);
}
return;
}
if (!GetSolveResults(da, out TOutput result))
{
// INFO: This will run synchronously. Useful for Rhino.Compute runs, but can also be enabled by user.
try
{
TInput input = GetInput(da);
var syncResult = PerformTask(input).Result;
result = syncResult;
}
catch (SpeckleException e)
{
Console.WriteLine(e);
return;
}
}
if (result is not null)
{
SetOutput(da, result);
}
}
protected abstract TInput GetInput(IGH_DataAccess da);
protected abstract void SetOutput(IGH_DataAccess da, TOutput result);
protected abstract Task<TOutput> PerformTask(TInput input, CancellationToken cancellationToken = default);
}
@@ -0,0 +1,85 @@
using Grasshopper.Kernel.Types;
using Speckle.Connectors.GrasshopperShared.Components.BaseComponents;
using Speckle.Connectors.GrasshopperShared.HostApp;
using Speckle.Connectors.GrasshopperShared.Parameters;
using Speckle.Connectors.GrasshopperShared.Properties;
namespace Speckle.Connectors.GrasshopperShared.Components.Collections;
public class CollectionPathsSelector : ValueSet<IGH_Goo>
{
public CollectionPathsSelector()
: base(
"Collection Selector",
"cSelect",
"Allows you to select a set of collection paths for querying",
ComponentCategories.PRIMARY_RIBBON,
ComponentCategories.COLLECTIONS
) { }
public override Guid ComponentGuid => new Guid("65FC4D58-2209-41B6-9B22-BE51C8B28604");
protected override Bitmap Icon => Resources.speckle_inputs_collection;
protected override void LoadVolatileData()
{
var collections = VolatileData
.AllData(true)
.OfType<SpeckleCollectionWrapperGoo>()
.Select(goo => goo.Value)
.ToList();
if (collections.Count == 0)
{
return;
}
// NOTE: supporting multiple collections? maybe? not really?
var paths = new List<string>();
foreach (SpeckleCollectionWrapper wrapper in collections)
{
// note: we are skipping the input collection, to make the output paths more intuitive
foreach (var element in wrapper.Elements)
{
if (element is SpeckleCollectionWrapper childCollectionWrapper)
{
paths.AddRange(GetPaths(childCollectionWrapper));
}
else
{
// include the input collection only if there are objects directly inside
paths.Add("_objects");
}
}
}
m_data.Clear();
m_data.AppendRange(paths.Select(s => new GH_String(s)));
}
private List<string> GetPaths(SpeckleCollectionWrapper wrapper)
{
var currentPath = new List<string>();
var allPaths = new HashSet<string>();
void GetPathsInternal(SpeckleCollectionWrapper w)
{
currentPath.Add(w.Name);
var subCols = w.Elements.OfType<SpeckleCollectionWrapper>().ToList();
// NOTE: here we're basically outputting only paths that correspond to a collection
// that has values inside of it.
if (subCols.Count != w.Elements.Count)
{
allPaths.Add(string.Join(Constants.LAYER_PATH_DELIMITER, currentPath));
}
foreach (var subCol in subCols)
{
GetPathsInternal(subCol);
}
currentPath.RemoveAt(currentPath.Count - 1);
}
GetPathsInternal(wrapper);
return allPaths.ToList();
}
}
@@ -0,0 +1,204 @@
using Grasshopper.Kernel;
using Grasshopper.Kernel.Parameters;
using Speckle.Connectors.GrasshopperShared.HostApp;
using Speckle.Connectors.GrasshopperShared.HostApp.Extras;
using Speckle.Connectors.GrasshopperShared.Parameters;
using Speckle.Connectors.GrasshopperShared.Properties;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models.Collections;
namespace Speckle.Connectors.GrasshopperShared.Components.Collections;
#pragma warning disable CA1711
public class CreateCollection : GH_Component, IGH_VariableParameterComponent
#pragma warning restore CA1711
{
public override Guid ComponentGuid => new("BDCE743E-7BDB-479B-AA81-19854AB5A254");
protected override Bitmap Icon => Resources.speckle_collections_create;
private readonly DebounceDispatcher _debounceDispatcher = new();
public CreateCollection()
: base(
"Create Collection",
"cC",
"Creates a new Collection",
ComponentCategories.PRIMARY_RIBBON,
ComponentCategories.COLLECTIONS
) { }
protected override void RegisterInputParams(GH_InputParamManager pManager)
{
var p = CreateParameter(GH_ParameterSide.Input, 0);
pManager.AddParameter(p);
}
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
{
pManager.AddGenericParameter("Collection", "C", "Created parent collection", GH_ParamAccess.tree);
}
protected override void SolveInstance(IGH_DataAccess dataAccess)
{
string rootName = "Unnamed";
Collection rootCollection = new();
SpeckleCollectionWrapper rootSpeckleCollectionWrapper =
new()
{
Base = rootCollection,
Name = rootName,
Path = new() { rootName },
Color = null,
Material = null,
ApplicationId = InstanceGuid.ToString()
};
foreach (var inputParam in Params.Input)
{
var data = inputParam.VolatileData.AllData(true).ToList();
if (data.Count == 0)
{
continue;
}
var inputCollections = data.OfType<SpeckleCollectionWrapperGoo>()
.Empty()
.Select(o => (SpeckleCollectionWrapperGoo)o.Duplicate())
.ToList();
var inputNonCollections = data.Where(t => t is not SpeckleCollectionWrapperGoo).Empty().ToList();
if (inputCollections.Count != 0 && inputNonCollections.Count != 0)
{
// TODO: error out! we want to disallow setting objects and collections in the same parent collection
AddRuntimeMessage(
GH_RuntimeMessageLevel.Error,
$"Parameter {inputParam.NickName} should not contain both objects and collections."
);
return;
}
List<string> childPath = new() { rootName };
childPath.Add(inputParam.NickName);
SpeckleCollectionWrapper childSpeckleCollectionWrapper =
new()
{
Base = new Collection(),
Name = inputParam.NickName,
Path = childPath,
Color = null,
Material = null,
Topology = GrasshopperHelpers.GetParamTopology(inputParam),
ApplicationId = inputParam.InstanceGuid.ToString(),
};
// handle collection inputs
// if on this port we're only receiving collections, we should become "pass-through" to not create
// needless nesting
if (inputCollections.Count == data.Count)
{
var nameTest = new HashSet<string>();
foreach (SpeckleCollectionWrapperGoo wrapperGoo in inputCollections)
{
// update the speckle collection path
wrapperGoo.Value.Path = childPath;
foreach (
string subCollectionName in wrapperGoo.Value.Elements.OfType<SpeckleCollectionWrapper>().Select(c => c.Name)
)
{
var hasNotSeenNameBefore = nameTest.Add(subCollectionName);
if (!hasNotSeenNameBefore)
{
AddRuntimeMessage(
GH_RuntimeMessageLevel.Error,
$"Duplicate collection name found: {subCollectionName} in input parameter {inputParam.NickName}. Please ensure collection names are unique per nesting level.\n See https://speckle.docs/grashopper/collections"
);
return;
}
}
childSpeckleCollectionWrapper.Elements.AddRange(wrapperGoo.Value.Elements);
}
rootSpeckleCollectionWrapper.Elements.Add(childSpeckleCollectionWrapper);
continue;
}
// handle object inputs
foreach (var obj in inputNonCollections)
{
SpeckleObjectWrapperGoo wrapperGoo = new();
if (wrapperGoo.CastFrom(obj))
{
wrapperGoo.Value.Path = childPath;
wrapperGoo.Value.Parent = childSpeckleCollectionWrapper;
childSpeckleCollectionWrapper.Elements.Add(wrapperGoo.Value);
}
}
rootSpeckleCollectionWrapper.Elements.Add(childSpeckleCollectionWrapper);
}
dataAccess.SetData(0, new SpeckleCollectionWrapperGoo(rootSpeckleCollectionWrapper));
}
public bool CanInsertParameter(GH_ParameterSide side, int index)
{
return side == GH_ParameterSide.Input;
}
public bool CanRemoveParameter(GH_ParameterSide side, int index)
{
return side == GH_ParameterSide.Input;
}
public IGH_Param CreateParameter(GH_ParameterSide side, int index)
{
var myParam = new Param_GenericObject
{
Name = $"Sub-Collection {Params.Input.Count + 1}",
MutableNickName = true,
Optional = true,
Access = GH_ParamAccess.tree // always tree
};
myParam.NickName = myParam.Name;
myParam.Optional = true;
return myParam;
}
public bool DestroyParameter(GH_ParameterSide side, int index)
{
return side == GH_ParameterSide.Input;
}
public void VariableParameterMaintenance()
{
// TODO?
}
public override void AddedToDocument(GH_Document document)
{
base.AddedToDocument(document);
Params.ParameterChanged += (sender, args) =>
{
if (args.ParameterSide == GH_ParameterSide.Output)
{
return;
}
switch (args.OriginalArguments.Type)
{
case GH_ObjectEventType.NickName:
// This means the user is typing characters, debounce until it stops for 400ms before expiring the solution.
// Prevents UI from locking too soon while writing new names for inputs.
args.Parameter.Name = args.Parameter.NickName;
_debounceDispatcher.Debounce(500, e => ExpireSolution(true));
break;
case GH_ObjectEventType.NickNameAccepted:
args.Parameter.Name = args.Parameter.NickName;
ExpireSolution(true);
break;
}
};
}
}
@@ -0,0 +1,226 @@
using System.Collections;
using System.Runtime.InteropServices;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Parameters;
using Speckle.Connectors.GrasshopperShared.HostApp;
using Speckle.Connectors.GrasshopperShared.Parameters;
using Speckle.Connectors.GrasshopperShared.Properties;
using Speckle.Sdk.Common;
namespace Speckle.Connectors.GrasshopperShared.Components.Collections;
#pragma warning disable CA1711
[Guid("69BC8CFB-A72F-4A83-9263-F3399DDA2E5E")]
public class ExpandCollection : GH_Component, IGH_VariableParameterComponent
#pragma warning restore CA1711
{
public ExpandCollection()
: base(
"Expand Collection",
"eC",
"Expands a Collection into its children",
ComponentCategories.PRIMARY_RIBBON,
ComponentCategories.COLLECTIONS
) { }
public override Guid ComponentGuid => GetType().GUID;
protected override Bitmap Icon => Resources.speckle_collections_expand;
protected override void RegisterInputParams(GH_InputParamManager pManager)
{
pManager.AddParameter(
new SpeckleCollectionParam(GH_ParamAccess.item),
"Data",
"D",
"The data you want to expand",
GH_ParamAccess.item
);
}
protected override void RegisterOutputParams(GH_OutputParamManager pManager) { }
protected override void SolveInstance(IGH_DataAccess da)
{
SpeckleCollectionWrapperGoo res = new();
da.GetData(0, ref res);
SpeckleCollectionWrapper wrapper = res.Value;
if (wrapper is null)
{
return;
}
Name = wrapper.Name;
NickName = wrapper.Name;
var objects = wrapper
.Elements.Where(el => el is not SpeckleCollectionWrapper)
.OfType<SpeckleObjectWrapper>()
.Select(o => new SpeckleObjectWrapperGoo(o))
.ToList();
var collections = wrapper
.Elements.Where(el => el is SpeckleCollectionWrapper)
.OfType<SpeckleCollectionWrapper>()
.ToList();
var outputParams = new List<OutputParamWrapper>();
if (objects.Count != 0)
{
var param = new Param_GenericObject()
{
Name = "_objects",
NickName = "_objs",
Description =
"Some collections may contain a mix of objects and other collections. Here we output the atomic objects from within this collection.",
Access = GH_ParamAccess.list
};
outputParams.Add(new OutputParamWrapper(param, objects, null));
}
foreach (SpeckleCollectionWrapper childWrapper in collections)
{
// skip empty
if (childWrapper.Elements.Count == 0)
{
continue;
}
var hasInnerCollections = childWrapper.Elements.Any(el => el is SpeckleCollectionWrapper);
var topology = childWrapper.Topology; // Note: this is a reminder for the future
var nickName = childWrapper.Name;
if (nickName.Length > 16)
{
nickName = childWrapper.Name[..6];
nickName += "..." + childWrapper.Name[^6..];
}
var param = new Param_GenericObject()
{
Name = childWrapper.Name,
NickName = nickName,
Access = hasInnerCollections
? GH_ParamAccess.item
: topology is null
? GH_ParamAccess.list
: GH_ParamAccess.tree // we will directly set objects out; note access can be list or tree based on whether it will be a path based collection
};
outputParams.Add(
new OutputParamWrapper(
param,
hasInnerCollections
? new SpeckleCollectionWrapperGoo(childWrapper)
: childWrapper.Elements.OfType<SpeckleObjectWrapper>().Select(o => new SpeckleObjectWrapperGoo(o)).ToList(),
topology
)
);
}
if (da.Iteration == 0 && OutputMismatch(outputParams))
{
OnPingDocument()
.ScheduleSolution(
5,
_ =>
{
CreateOutputs(outputParams);
}
);
}
else
{
for (int i = 0; i < outputParams.Count; i++)
{
var outParam = Params.Output[i];
var outParamWrapper = outputParams[i];
switch (outParam.Access)
{
case GH_ParamAccess.item:
da.SetData(i, outParamWrapper.Values);
break;
case GH_ParamAccess.list:
da.SetDataList(i, outParamWrapper.Values as IList);
break;
case GH_ParamAccess.tree:
//TODO: means we need to convert the collection to a tree
var topo = outParamWrapper.Topology.NotNull();
var values = outParamWrapper.Values as IList;
var tree = GrasshopperHelpers.CreateDataTreeFromTopologyAndItems(topo, values.NotNull());
da.SetDataTree(i, tree);
break;
}
}
}
}
private bool OutputMismatch(List<OutputParamWrapper> outputParams)
{
if (Params.Output.Count != outputParams.Count)
{
return true;
}
var count = 0;
foreach (var newParam in outputParams)
{
var oldParam = Params.Output[count];
if (
oldParam.NickName != newParam.Param.NickName
|| oldParam.Name != newParam.Param.Name
|| oldParam.Access != newParam.Param.Access
)
{
return true;
}
count++;
}
return false;
}
private void CreateOutputs(List<OutputParamWrapper> outputParams)
{
// TODO: better, nicer handling of creation/removal
while (Params.Output.Count > 0)
{
Params.UnregisterOutputParameter(Params.Output[^1]);
}
foreach (var newParam in outputParams)
{
var param = new Param_GenericObject
{
Name = newParam.Param.Name,
NickName = newParam.Param.NickName,
MutableNickName = false,
Access = newParam.Param.Access
};
Params.RegisterOutputParam(param);
}
Params.OnParametersChanged();
VariableParameterMaintenance();
ExpireSolution(false);
}
public void VariableParameterMaintenance() { }
public bool CanInsertParameter(GH_ParameterSide side, int index) => false;
public bool CanRemoveParameter(GH_ParameterSide side, int index) => false;
public IGH_Param CreateParameter(GH_ParameterSide side, int index)
{
var myParam = new Param_GenericObject
{
Name = GH_ComponentParamServer.InventUniqueNickname("ABCD", Params.Input),
MutableNickName = true,
Optional = true
};
myParam.NickName = myParam.Name;
return myParam;
}
public bool DestroyParameter(GH_ParameterSide side, int index) => side == GH_ParameterSide.Output;
}
public record OutputParamWrapper(Param_GenericObject Param, object Values, string? Topology);
@@ -0,0 +1,23 @@
namespace Speckle.Connectors.GrasshopperShared.Components;
// NOTE: The number of spaces determines the order in which they display in the ribbon (nice hack)
public static class ComponentCategories
{
public const string PRIMARY_RIBBON = "Speckle";
public const string OPERATIONS = " Ops";
public const string OBJECTS = " Objects";
public const string COLLECTIONS = " Collections";
public const string PARAMETERS = " Params";
public const string DEVELOPER = "Dev";
}
public enum ComponentState
{
Cancelled,
Expired,
NeedsInput,
Receiving,
Ready,
Sending,
UpToDate
}
@@ -0,0 +1,314 @@
using System.Collections;
using System.Runtime.InteropServices;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Parameters;
using Rhino.Geometry;
using Speckle.Connectors.GrasshopperShared.HostApp;
using Speckle.Connectors.GrasshopperShared.Parameters;
using Speckle.Connectors.GrasshopperShared.Properties;
using Speckle.Sdk.Common.Exceptions;
using Speckle.Sdk.Models;
namespace Speckle.Connectors.GrasshopperShared.Components.Dev;
[Guid("C491D26C-84CB-4684-8BD2-AA78D0F2FE53")]
public class DeconstructSpeckleParam : GH_Component, IGH_VariableParameterComponent
{
public DeconstructSpeckleParam()
: base(
"Deconstruct",
"D",
"Deconstructs any Speckle param into its atomic parts",
ComponentCategories.PRIMARY_RIBBON,
ComponentCategories.DEVELOPER
) { }
public override Guid ComponentGuid => GetType().GUID;
protected override Bitmap Icon => Resources.speckle_deconstruct;
protected override void RegisterInputParams(GH_InputParamManager pManager)
{
pManager.AddGenericParameter(
"Speckle Param",
"SP",
"Speckle param to deconstruct. Expects Collections, Objects, or Materials",
GH_ParamAccess.item
);
}
protected override void RegisterOutputParams(GH_OutputParamManager pManager) { }
protected override void SolveInstance(IGH_DataAccess da)
{
object data = new();
da.GetData(0, ref data);
List<OutputParamWrapper> outputParams = new();
switch (data)
{
case SpeckleObjectWrapperGoo obj:
Name = string.IsNullOrEmpty(obj.Value.Name) ? obj.Value.Base.speckle_type : obj.Value.Name;
outputParams = CreateOutputParamsFromBase(obj.Value.Base);
break;
case SpeckleCollectionWrapperGoo coll:
Name = string.IsNullOrEmpty(coll.Value.Collection.name)
? coll.Value.Collection.speckle_type
: coll.Value.Collection.name;
outputParams = CreateOutputParamsFromBase(coll.Value.Collection);
break;
case SpeckleMaterialWrapperGoo matGoo:
Name = string.IsNullOrEmpty(matGoo.Value.Name) ? matGoo.Value.Material.speckle_type : matGoo.Value.Name;
outputParams = CreateOutputParamsFromBase(matGoo.Value.Base);
break;
default:
return;
}
NickName = Name;
if (da.Iteration == 0 && OutputMismatch(outputParams))
{
OnPingDocument()
.ScheduleSolution(
5,
_ =>
{
CreateOutputs(outputParams);
}
);
}
else
{
for (int i = 0; i < outputParams.Count; i++)
{
var outParam = Params.Output[i];
var outParamWrapper = outputParams[i];
switch (outParam.Access)
{
case GH_ParamAccess.item:
da.SetData(i, outParamWrapper.Value);
break;
case GH_ParamAccess.list:
da.SetDataList(i, outParamWrapper.Value as IList);
break;
}
}
}
}
private List<OutputParamWrapper> CreateOutputParamsFromBase(Base @base)
{
List<OutputParamWrapper> result = new();
if (@base == null)
{
return result;
}
// cycle through base props
foreach (var prop in @base.GetMembers(DynamicBaseMemberType.Instance | DynamicBaseMemberType.Dynamic))
{
// Convert and add to corresponding output structure
var value = prop.Value;
switch (value)
{
case null:
result.Add(CreateOutputParamByKeyValue(prop.Key, null, GH_ParamAccess.item));
break;
case IList list:
List<object> nativeObjects = new();
foreach (var x in list)
{
switch (x)
{
case SpeckleCollectionWrapper collWrapper:
nativeObjects.Add(new SpeckleCollectionWrapperGoo(collWrapper));
break;
case SpeckleObjectWrapper objWrapper:
nativeObjects.Add(new SpeckleObjectWrapperGoo(objWrapper));
break;
case Base xBase:
nativeObjects.AddRange(ConvertOrCreateWrapper(xBase));
break;
default:
nativeObjects.Add(x);
break;
}
}
result.Add(CreateOutputParamByKeyValue(prop.Key, nativeObjects, GH_ParamAccess.list));
break;
case Dictionary<string, object?> dict: // this should be treated a properties dict
SpecklePropertyGroupGoo propertyGoo = new();
propertyGoo.CastFrom(dict);
result.Add(CreateOutputParamByKeyValue(prop.Key, propertyGoo, GH_ParamAccess.item));
break;
case SpeckleCollectionWrapper collWrapper:
result.Add(
CreateOutputParamByKeyValue(prop.Key, new SpeckleCollectionWrapperGoo(collWrapper), GH_ParamAccess.item)
);
break;
case SpeckleObjectWrapper objWrapper:
result.Add(
CreateOutputParamByKeyValue(prop.Key, new SpeckleObjectWrapperGoo(objWrapper), GH_ParamAccess.item)
);
break;
case Base baseValue:
result.Add(CreateOutputParamByKeyValue(prop.Key, ConvertOrCreateWrapper(baseValue), GH_ParamAccess.list));
break;
default:
// we don't want to output dynamic property keys
if (prop.Key == nameof(Base.DynamicPropertyKeys))
{
continue;
}
result.Add(CreateOutputParamByKeyValue(prop.Key, prop.Value, GH_ParamAccess.item));
break;
}
}
return result;
}
private List<SpeckleObjectWrapperGoo> ConvertOrCreateWrapper(Base @base)
{
try
{
// convert the base and create a wrapper for each result
List<(GeometryBase, Base)> convertedBase = SpeckleConversionContext.ConvertToHost(@base);
List<SpeckleObjectWrapperGoo> convertedWrappers = new();
foreach ((GeometryBase g, Base b) in convertedBase)
{
SpeckleObjectWrapper convertedWrapper =
new()
{
Base = b,
GeometryBase = g,
Name = b["name"] as string ?? "",
Color = null,
Material = null,
WrapperGuid = null
};
convertedWrappers.Add(new(convertedWrapper));
}
return convertedWrappers;
}
catch (ConversionException)
{
// some classes, like RawEncoding, have no direct conversion or fallback value.
// when this is the case, wrap it to allow users to further expand the object.
SpeckleObjectWrapper convertedWrapper =
new()
{
Base = @base,
GeometryBase = null,
Name = @base[Constants.NAME_PROP] as string ?? "",
Color = null,
Material = null,
WrapperGuid = null,
};
return new() { new SpeckleObjectWrapperGoo(convertedWrapper) };
}
}
private OutputParamWrapper CreateOutputParamByKeyValue(string key, object? value, GH_ParamAccess access)
{
Param_GenericObject param =
new()
{
Name = key,
NickName = key,
Description = "",
Access = access
};
return new OutputParamWrapper(param, value);
}
public bool CanInsertParameter(GH_ParameterSide side, int index) => false;
public bool CanRemoveParameter(GH_ParameterSide side, int index) => false;
public void VariableParameterMaintenance() { }
public IGH_Param CreateParameter(GH_ParameterSide side, int index)
{
var myParam = new Param_GenericObject
{
Name = GH_ComponentParamServer.InventUniqueNickname("ABCD", Params.Input),
MutableNickName = true,
Optional = true
};
myParam.NickName = myParam.Name;
return myParam;
}
public bool DestroyParameter(GH_ParameterSide side, int index)
{
return side == GH_ParameterSide.Output;
}
private void CreateOutputs(List<OutputParamWrapper> outputParams)
{
// TODO: better, nicer handling of creation/removal
while (Params.Output.Count > 0)
{
Params.UnregisterOutputParameter(Params.Output[^1]);
}
foreach (var newParam in outputParams)
{
var param = new Param_GenericObject
{
Name = newParam.Param.Name,
NickName = newParam.Param.NickName,
MutableNickName = false,
Access = newParam.Param.Access
};
Params.RegisterOutputParam(param);
}
Params.OnParametersChanged();
VariableParameterMaintenance();
ExpireSolution(false);
}
private bool OutputMismatch(List<OutputParamWrapper> outputParams)
{
if (Params.Output.Count != outputParams.Count)
{
return true;
}
var count = 0;
foreach (var newParam in outputParams)
{
var oldParam = Params.Output[count];
if (
oldParam.NickName != newParam.Param.NickName
|| oldParam.Name != newParam.Param.Name
|| oldParam.Access != newParam.Param.Access
)
{
return true;
}
count++;
}
return false;
}
}
public record OutputParamWrapper(Param_GenericObject Param, object? Value);
@@ -0,0 +1,19 @@
using Grasshopper.Kernel;
namespace Speckle.Connectors.GrasshopperShared.Components;
public class GhContextMenuButton(
string name,
string nickname,
string description,
Func<ToolStripDropDown, bool>? populateMenuAction = null
) : GH_DocumentObject(name, nickname, description, "Speckle", "UI")
{
public bool Enabled { get; set; } = true;
public override void CreateAttributes() => Attributes = new GhContextMenuButtonAttributes(this);
public override Guid ComponentGuid => new("B01FFD91-F4EC-4332-A9AA-F917AEDAA51D");
public override bool AppendMenuItems(ToolStripDropDown menu) => populateMenuAction?.Invoke(menu) ?? false;
}
@@ -0,0 +1,59 @@
using Grasshopper.GUI;
using Grasshopper.GUI.Canvas;
using Grasshopper.Kernel;
namespace Speckle.Connectors.GrasshopperShared.Components;
public class GhContextMenuButtonAttributes(GhContextMenuButton owner) : GH_Attributes<GhContextMenuButton>(owner)
{
protected override void Render(GH_Canvas canvas, Graphics graphics, GH_CanvasChannel channel)
{
base.Render(canvas, graphics, channel);
if (channel != GH_CanvasChannel.Objects)
{
return; // No wires or other layers are being drawn in this component.
}
using var button1 = GH_Capsule.CreateTextCapsule(
Bounds,
Bounds,
Owner.Enabled ? GH_Palette.Black : GH_Palette.Grey,
Owner.Name,
2,
0
);
button1.Render(graphics, Parent.Selected, false, false);
}
public override GH_ObjectResponse RespondToMouseDown(GH_Canvas sender, GH_CanvasMouseEvent e)
{
if (Bounds.Contains(e.CanvasLocation) && e.Button == MouseButtons.Left)
{
// handle the mouse down to prevent component selection
return GH_ObjectResponse.Handled;
}
return base.RespondToMouseDown(sender, e);
}
public override GH_ObjectResponse RespondToMouseUp(GH_Canvas sender, GH_CanvasMouseEvent e)
{
// detect left-clicks on enabled buttons
if (Owner.Enabled && e.Button == MouseButtons.Left && Bounds.Contains(e.CanvasLocation))
{
// show menu
ToolStripDropDown menu = new();
Owner.AppendMenuItems(menu);
menu.Show(sender, sender.PointToClient(Cursor.Position));
return GH_ObjectResponse.Handled;
}
// block right-clicks to prevent the default context menu
if (e.Button == MouseButtons.Right && Bounds.Contains(e.CanvasLocation))
{
return GH_ObjectResponse.Handled;
}
return base.RespondToMouseUp(sender, e);
}
}
@@ -0,0 +1,231 @@
using System.Runtime.InteropServices;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Types;
using Speckle.Connectors.GrasshopperShared.HostApp;
using Speckle.Connectors.GrasshopperShared.Parameters;
using Speckle.Connectors.GrasshopperShared.Properties;
using Speckle.Sdk.Models;
namespace Speckle.Connectors.GrasshopperShared.Components.Objects;
[Guid("F9418610-ACAE-4417-B010-19EBEA6A121F")]
public class CreateSpeckleObject : GH_Component
{
public CreateSpeckleObject()
: base(
"Speckle Object",
"SO",
"Create or modify a Speckle Object",
ComponentCategories.PRIMARY_RIBBON,
ComponentCategories.OBJECTS
) { }
public override Guid ComponentGuid => GetType().GUID;
protected override Bitmap Icon => Resources.speckle_objects_object;
protected override void RegisterInputParams(GH_InputParamManager pManager)
{
pManager.AddGenericParameter(
"Object",
"O",
"Input Object. Speckle objects, Model Objects, and geometry are accepted.",
GH_ParamAccess.item
);
Params.Input[0].Optional = true;
pManager.AddGenericParameter("Geometry", "G", "The geometry of the Speckle Object", GH_ParamAccess.item);
Params.Input[1].Optional = true;
pManager.AddTextParameter("Name", "N", "Name of the Speckle Object", GH_ParamAccess.item);
Params.Input[2].Optional = true;
pManager.AddGenericParameter(
"Properties",
"P",
"The properties of the Speckle Object. Speckle Properties and User Content are accepted.",
GH_ParamAccess.item
);
Params.Input[3].Optional = true;
pManager.AddColourParameter("Color", "c", "The color of the Speckle Object", GH_ParamAccess.item);
Params.Input[4].Optional = true;
pManager.AddGenericParameter(
"Material",
"m",
"The material of the Speckle Object. Display Materials, Model Materials, and Speckle Materials are accepted.",
GH_ParamAccess.item
);
Params.Input[5].Optional = true;
/* POC: disable for now as we are doing anything with this
pManager.AddTextParameter(
"Path",
"p",
"The Collection Path of the Speckle Object. Should be delimited with `:`",
GH_ParamAccess.item
);
Params.Input[6].Optional = true;
*/
}
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
{
pManager.AddParameter(new SpeckleObjectParam(), "Object", "O", "Speckle Object", GH_ParamAccess.item);
pManager.AddGenericParameter("Geometry", "G", "The geometry of the Speckle Object", GH_ParamAccess.item);
pManager.AddTextParameter("Name", "N", "Name of the Speckle Object", GH_ParamAccess.item);
pManager.AddParameter(
new SpecklePropertyGroupParam(),
"Properties",
"P",
"The properties of the Speckle Object",
GH_ParamAccess.item
);
pManager.AddColourParameter("Color", "c", "The color of the Speckle Object", GH_ParamAccess.item);
pManager.AddParameter(
new SpeckleMaterialParam(),
"Material",
"M",
"The material of the Speckle Object.",
GH_ParamAccess.item
);
pManager.AddTextParameter(
"Path",
"p",
$"The Collection Path of the Speckle Object, delimited with `{Constants.LAYER_PATH_DELIMITER}`",
GH_ParamAccess.item
);
}
protected override void SolveInstance(IGH_DataAccess da)
{
IGH_Goo? inputObject = null;
da.GetData(0, ref inputObject);
IGH_GeometricGoo? inputGeometry = null;
da.GetData(1, ref inputGeometry);
string? inputName = null;
da.GetData(2, ref inputName);
IGH_Goo? inputProperties = null;
da.GetData(3, ref inputProperties);
Color? inputColor = null;
da.GetData(4, ref inputColor);
IGH_Goo? inputMaterial = null;
da.GetData(5, ref inputMaterial);
//string? inputPath = null;
//da.GetData(6, ref inputPath);
// keep track of mutation
// poc: we should not mark mutations on color or material, as this shouldn't affect the appId of the object, and will allow original display values to stay intact on send.
bool mutated = false;
// process the object
SpeckleObjectWrapperGoo result = new();
if (inputObject != null)
{
if (!result.CastFrom(inputObject))
{
AddRuntimeMessage(
GH_RuntimeMessageLevel.Warning,
$"Object input is not valid. Only Speckle Objects, Baked Model Objects, and Geometry are accepted."
);
return;
}
}
// process geometry
// at this point, we can ensure that the Base in the wrapper is a DataObject.
if (inputObject == null && inputGeometry == null)
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"Pass in an Object or Geometry.");
return;
}
if (inputGeometry != null)
{
result.Value.GeometryBase = inputGeometry.GeometricGooToGeometryBase();
Base converted = SpeckleConversionContext.ConvertToSpeckle(result.Value.GeometryBase);
converted[Constants.NAME_PROP] = result.Value.Name;
converted.applicationId = result.Value.ApplicationId;
result.Value.Base = converted;
mutated = true;
}
// process name
if (inputName != null)
{
result.Value.Name = inputName;
mutated = true;
}
// process properties
if (inputProperties != null)
{
SpecklePropertyGroupGoo propGoo = new();
if (!propGoo.CastFrom(inputProperties))
{
AddRuntimeMessage(
GH_RuntimeMessageLevel.Warning,
$"Properties input is not valid. Only Speckle Properties and User Content are accepted."
);
return;
}
result.Value.Properties = propGoo;
mutated = true;
}
// process color (no mutation)
if (inputColor != null)
{
result.Value.Color = inputColor;
}
// process material (no mutation)
if (inputMaterial != null)
{
SpeckleMaterialWrapperGoo matWrapperGoo = new();
if (!matWrapperGoo.CastFrom(inputMaterial))
{
AddRuntimeMessage(
GH_RuntimeMessageLevel.Warning,
$"Material input is not valid. Only Display Materials, Baked Model Materials, and Speckle Materials are accepted."
);
return;
}
result.Value.Material = matWrapperGoo.Value;
}
// process application Id. Use a new appId if mutated, or if this is a new object
result.Value.ApplicationId = mutated
? Guid.NewGuid().ToString()
: result.Value.ApplicationId ?? Guid.NewGuid().ToString();
// get the path
string path =
result.Value.Path.Count > 1
? string.Join(Constants.LAYER_PATH_DELIMITER, result.Value.Path)
: result.Value.Path.FirstOrDefault();
// set all the data
da.SetData(0, result.Value);
da.SetData(1, result.Value.GeometryBase);
da.SetData(2, result.Value.Name);
da.SetData(3, result.Value.Properties);
da.SetData(4, result.Value.Color);
da.SetData(5, result.Value.Material);
da.SetData(6, path);
}
}
@@ -0,0 +1,140 @@
using System.Runtime.InteropServices;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Parameters;
using Speckle.Connectors.GrasshopperShared.HostApp.Extras;
using Speckle.Connectors.GrasshopperShared.Parameters;
using Speckle.Connectors.GrasshopperShared.Properties;
namespace Speckle.Connectors.GrasshopperShared.Components.Objects;
[Guid("A3FD5CBF-DFB0-44DF-9988-04466EB8E5E6")]
public class CreateSpeckleProperties : GH_Component, IGH_VariableParameterComponent
{
public CreateSpeckleProperties()
: base(
"Create Properties",
"CP",
"Creates a set of properties for Speckle objects",
ComponentCategories.PRIMARY_RIBBON,
ComponentCategories.OBJECTS
) { }
public override Guid ComponentGuid => GetType().GUID;
protected override Bitmap Icon => Resources.speckle_properties_create;
private readonly DebounceDispatcher _debounceDispatcher = new();
protected override void RegisterInputParams(GH_InputParamManager pManager)
{
var p = CreateParameter(GH_ParameterSide.Input, 0);
pManager.AddParameter(p);
}
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
{
pManager.AddGenericParameter("Properties", "P", "Properties for Speckle Objects", GH_ParamAccess.item);
}
protected override void SolveInstance(IGH_DataAccess da)
{
// Create a data tree to store output
Dictionary<string, object?> properties = new();
// Check for structure of all inputs to see matching branches
foreach (var inputParam in Params.Input)
{
string inputName = inputParam.NickName;
if (properties.ContainsKey(inputName))
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, $"Duplicate property name found: {inputName}.");
return;
}
properties.Add(inputName, new());
}
for (int i = 0; i < Params.Input.Count; i++)
{
object? value = null;
var success = da.GetData(i, ref value);
var actualValue = value?.GetType().GetProperty("Value").GetValue(value); // note: unsure if reflection here hurts our performance
if (!success || value == null || actualValue == null)
{
AddRuntimeMessage(
GH_RuntimeMessageLevel.Warning,
$"Parameter {Params.Input[i].NickName} should not contain anything other than strings, doubles, ints, and bools."
);
return;
}
properties[Params.Input[i].NickName] = actualValue;
}
var groupGoo = new SpecklePropertyGroupGoo(properties);
da.SetData(0, groupGoo);
}
public bool CanInsertParameter(GH_ParameterSide side, int index)
{
return side == GH_ParameterSide.Input;
}
public bool CanRemoveParameter(GH_ParameterSide side, int index)
{
return side == GH_ParameterSide.Input;
}
public IGH_Param CreateParameter(GH_ParameterSide side, int index)
{
var myParam = new Param_GenericObject
{
Name = $"Property {Params.Input.Count + 1}",
MutableNickName = true,
Optional = true,
Access = GH_ParamAccess.item
};
myParam.NickName = myParam.Name;
myParam.Optional = true;
return myParam;
}
public bool DestroyParameter(GH_ParameterSide side, int index)
{
return side == GH_ParameterSide.Input;
}
public void VariableParameterMaintenance()
{
// TODO?
}
public override void AddedToDocument(GH_Document document)
{
base.AddedToDocument(document);
Params.ParameterChanged += (sender, args) =>
{
if (args.ParameterSide == GH_ParameterSide.Output)
{
return;
}
switch (args.OriginalArguments.Type)
{
case GH_ObjectEventType.NickName:
// This means the user is typing characters, debounce until it stops for 400ms before expiring the solution.
// Prevents UI from locking too soon while writing new names for inputs.
args.Parameter.Name = args.Parameter.NickName;
_debounceDispatcher.Debounce(500, e => ExpireSolution(true));
break;
case GH_ObjectEventType.NickNameAccepted:
args.Parameter.Name = args.Parameter.NickName;
ExpireSolution(true);
break;
}
};
}
}
@@ -0,0 +1,182 @@
using System.Runtime.InteropServices;
using Grasshopper.Kernel;
using Speckle.Connectors.GrasshopperShared.Components.BaseComponents;
using Speckle.Connectors.GrasshopperShared.Parameters;
using Speckle.Connectors.GrasshopperShared.Properties;
namespace Speckle.Connectors.GrasshopperShared.Components.Objects;
/// <summary>
/// Given a list of objects, this component will filter the list for objects that match the queries.
/// </summary>
[Guid("26AEA046-4DD4-4F61-8251-E92A6D2AC880")]
public class FilterSpeckleObjects : GH_Component
{
public override Guid ComponentGuid => GetType().GUID;
protected override Bitmap Icon => Resources.speckle_objects_filter;
public FilterSpeckleObjects()
: base(
"Filter Objects",
"fO",
"Filters a list of Speckle Objects according to inputs. Filter methods: Equals (default), StartsWith(<), EndsWith(>) , Contains(?), Regex(;)",
ComponentCategories.PRIMARY_RIBBON,
ComponentCategories.OBJECTS
) { }
protected override void RegisterInputParams(GH_InputParamManager pManager)
{
pManager.AddParameter(new SpeckleObjectParam(), "Objects", "O", "Speckle Objects to filter", GH_ParamAccess.list);
pManager.AddTextParameter("Name", "N", "Find objects with a matching name", GH_ParamAccess.item);
Params.Input[1].Optional = true;
pManager.AddTextParameter(
"Property Key",
"P",
"Find objects with a property that has a matching key",
GH_ParamAccess.item
);
Params.Input[2].Optional = true;
pManager.AddTextParameter(
"Material Name",
"M",
"Find objects with a render material that has a matching name",
GH_ParamAccess.item
);
Params.Input[3].Optional = true;
pManager.AddTextParameter(
"Application Id",
"aID",
"Find objects with a matching applicationId",
GH_ParamAccess.item
);
Params.Input[4].Optional = true;
pManager.AddTextParameter("Speckle Id", "sID", "Find objects with a matching Speckle id", GH_ParamAccess.item);
Params.Input[5].Optional = true;
}
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
{
pManager.AddParameter(
new SpeckleObjectParam(),
"Objects",
"O",
"The objects that match the queries",
GH_ParamAccess.tree
);
pManager.AddParameter(
new SpeckleObjectParam(),
"Culled Objects",
"co",
"The objects that did not match the queries",
GH_ParamAccess.tree
);
}
protected override void SolveInstance(IGH_DataAccess dataAccess)
{
List<SpeckleObjectWrapperGoo?> inputObjects = new();
dataAccess.GetDataList(0, inputObjects);
if (inputObjects.Count == 0)
{
return;
}
string name = "";
dataAccess.GetData(1, ref name);
string property = "";
dataAccess.GetData(2, ref property);
string material = "";
dataAccess.GetData(3, ref material);
string appId = "";
dataAccess.GetData(4, ref appId);
string speckleId = "";
dataAccess.GetData(5, ref speckleId);
List<SpeckleObjectWrapper> matchedObjects = new();
List<SpeckleObjectWrapper> removedObjects = new();
for (int i = 0; i < inputObjects.Count; i++)
{
SpeckleObjectWrapperGoo? inputObject = inputObjects[i];
if (inputObject is null)
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"A null input object was detected.");
return;
}
// filter by name
if (!MatchesSearchPattern(name, inputObject.Value.Name))
{
removedObjects.Add(inputObject.Value);
continue;
}
// filter by property
bool foundProperty = false;
if (string.IsNullOrEmpty(property))
{
foundProperty = true;
}
else
{
foreach (string key in inputObject.Value.Properties.Value.Keys)
{
if (MatchesSearchPattern(property, key))
{
foundProperty = true;
break;
}
}
}
if (!foundProperty)
{
removedObjects.Add(inputObject.Value);
continue;
}
// filter by material name
if (!MatchesSearchPattern(material, inputObject.Value.Material?.Name ?? ""))
{
removedObjects.Add(inputObject.Value);
continue;
}
// filter by application id
if (!MatchesSearchPattern(appId, inputObject.Value.Base.applicationId ?? ""))
{
removedObjects.Add(inputObject.Value);
continue;
}
// filter by speckle id
if (!MatchesSearchPattern(speckleId, inputObject.Value.Base.id ?? ""))
{
removedObjects.Add(inputObject.Value);
continue;
}
matchedObjects.Add(inputObject.Value);
}
// Set output objects
dataAccess.SetDataList(0, matchedObjects);
dataAccess.SetDataList(1, removedObjects);
}
private bool MatchesSearchPattern(string searchPattern, string target)
{
if (string.IsNullOrEmpty(searchPattern))
{
return true;
}
return Operator.IsSymbolNameLike(target, searchPattern);
}
}
@@ -0,0 +1,141 @@
using System.Runtime.InteropServices;
using Grasshopper.Kernel;
using Speckle.Connectors.GrasshopperShared.HostApp;
using Speckle.Connectors.GrasshopperShared.Parameters;
using Speckle.Connectors.GrasshopperShared.Properties;
using Speckle.Sdk;
namespace Speckle.Connectors.GrasshopperShared.Components.Objects;
/// <summary>
/// Given a collection, this component will output the objects in the subcollection corresponding to the input path
/// </summary>
[Guid("77CAEE94-F0B9-4611-897C-71F2A22BA311")]
public class GetCollectionObjects : GH_Component
{
public override Guid ComponentGuid => GetType().GUID;
protected override Bitmap Icon => Resources.speckle_objects_query;
public GetCollectionObjects()
: base(
"Query Objects",
"qO",
"Retrieves the objects inside a Speckle collection at the specified path",
ComponentCategories.PRIMARY_RIBBON,
ComponentCategories.OBJECTS
) { }
protected override void RegisterInputParams(GH_InputParamManager pManager)
{
pManager.AddParameter(
new SpeckleCollectionParam(),
"Collection",
"C",
"Collection to retrieve objects from",
GH_ParamAccess.item
);
pManager.AddTextParameter(
"Path",
"C",
"Get the Speckle objects in the subcollection indicated by this path",
GH_ParamAccess.item
);
Params.Input[1].Optional = true;
}
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
{
pManager.AddParameter(
new SpeckleObjectParam(),
"Objects",
"O",
"The objects in the input collection that match the queries",
GH_ParamAccess.tree
);
}
protected override void SolveInstance(IGH_DataAccess dataAccess)
{
SpeckleCollectionWrapperGoo collectionWrapperGoo = new();
dataAccess.GetData(0, ref collectionWrapperGoo);
if (collectionWrapperGoo.Value == null)
{
return;
}
string path = "";
dataAccess.GetData(1, ref path);
// filter by collection path
// Note: the collection paths selector will omit the target collection from the path of nested collections.
// the discard ("_objects") will be used to indicate objects found directly in the target collection.
List<SpeckleObjectWrapper> filteredObjects = new();
SpeckleCollectionWrapper? targetCollectionWrapper = null;
if (!string.IsNullOrEmpty(path))
{
targetCollectionWrapper =
path == "_objects" ? collectionWrapperGoo.Value : FindCollection(collectionWrapperGoo.Value, path);
filteredObjects = targetCollectionWrapper
.Elements.Where(e => e is SpeckleObjectWrapper)
.Select(e => (SpeckleObjectWrapper)e)
.ToList();
}
else
{
filteredObjects = GetAllObjectsFromCollection(collectionWrapperGoo.Value).ToList();
}
// Set output objects
if (targetCollectionWrapper?.Topology is string topology && !string.IsNullOrEmpty(topology))
{
var tree = GrasshopperHelpers.CreateDataTreeFromTopologyAndItems(topology, filteredObjects);
dataAccess.SetDataTree(0, tree);
}
else
{
dataAccess.SetDataList(0, filteredObjects);
}
}
private IEnumerable<SpeckleObjectWrapper> GetAllObjectsFromCollection(SpeckleCollectionWrapper collectionWrapper)
{
foreach (SpeckleWrapper element in collectionWrapper.Elements)
{
switch (element)
{
case SpeckleCollectionWrapper childCollectionWrapper:
foreach (var item in GetAllObjectsFromCollection(childCollectionWrapper))
{
yield return item;
}
break;
case SpeckleObjectWrapper objectWrapper:
yield return objectWrapper;
break;
}
}
}
private SpeckleCollectionWrapper FindCollection(SpeckleCollectionWrapper root, string unifiedPath)
{
// POC: SpeckleCollections now have a full list<string> path prop on them always. Is this easier to use?
List<string> paths = unifiedPath.Split([Constants.LAYER_PATH_DELIMITER], StringSplitOptions.None).ToList();
SpeckleCollectionWrapper currentCollectionWrapper = root;
while (paths.Count != 0)
{
currentCollectionWrapper = currentCollectionWrapper
.Elements.OfType<SpeckleCollectionWrapper>()
.First(wrapper => wrapper.Name == paths.First());
paths.RemoveAt(0);
if (paths.Count == 0)
{
return currentCollectionWrapper;
}
}
throw new SpeckleException("Did not find collection");
}
}
@@ -0,0 +1,162 @@
using System.Runtime.InteropServices;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Parameters;
using Speckle.Connectors.GrasshopperShared.Parameters;
using Speckle.Connectors.GrasshopperShared.Properties;
namespace Speckle.Connectors.GrasshopperShared.Components.Objects;
[Guid("116F08A5-BAA7-45B3-B6C8-469E452C9AC7")]
public class GetObjectProperties : GH_Component, IGH_VariableParameterComponent
{
public override Guid ComponentGuid => GetType().GUID;
protected override Bitmap Icon => Resources.speckle_properties_query;
public GetObjectProperties()
: base(
"Query Properties",
"qP",
"Retrieves the values of the properties inside Speckle Objects at the specified keys",
ComponentCategories.PRIMARY_RIBBON,
ComponentCategories.OBJECTS
) { }
protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
{
pManager.AddParameter(
new SpeckleObjectParam(),
"Objects",
"O",
"Speckle Objects to retrieve properties",
GH_ParamAccess.item
);
pManager.AddTextParameter("Keys", "K", "Property keys to filter by", GH_ParamAccess.list);
}
protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) { }
protected override void SolveInstance(IGH_DataAccess da)
{
List<string> paths = new();
da.GetDataList(1, paths);
if (paths.Count == 0)
{
return;
}
if (OutputMismatch(paths))
{
OnPingDocument()
.ScheduleSolution(
5,
_ =>
{
CreateOutputs(paths);
}
);
}
else
{
SpeckleObjectWrapperGoo objectWrapperGoo = new();
da.GetData(0, ref objectWrapperGoo);
for (int i = 0; i < paths.Count; i++)
{
var name = paths[i];
SpecklePropertyGoo objectProperty = FindProperty(objectWrapperGoo.Value.Properties, name);
da.SetData(i, objectProperty.Value);
}
}
}
private SpecklePropertyGoo FindProperty(SpecklePropertyGroupGoo root, string unifiedPath)
{
if (!root.Value.TryGetValue(unifiedPath, out SpecklePropertyGoo currentGoo))
{
return new() { Path = unifiedPath, Value = "" };
}
return currentGoo;
}
private bool OutputMismatch(List<string> outputParams)
{
if (Params.Output.Count != outputParams.Count)
{
return true;
}
var count = 0;
foreach (var newParam in outputParams)
{
var oldParam = Params.Output[count];
if (oldParam.NickName != newParam || oldParam.Name != newParam)
{
return true;
}
count++;
}
return false;
}
private void CreateOutputs(List<string> outputParams)
{
// Ensure we have the required count of output parameters
while (Params.Output.Count != outputParams.Count)
{
if (Params.Output.Count > outputParams.Count) // if too many, unregister
{
Params.UnregisterOutputParameter(Params.Output[^1]);
}
if (Params.Output.Count < outputParams.Count) // if too little, add some
{
var param = new Param_GenericObject
{
Name = "newParam",
NickName = "newParam",
MutableNickName = false,
Access = GH_ParamAccess.item
};
Params.RegisterOutputParam(param);
}
}
// now unify names and nicknames
int index = 0;
foreach (var newParam in outputParams)
{
Params.Output[index].NickName = newParam;
Params.Output[index].Name = newParam;
index++;
}
// now we can update the output params
Params.OnParametersChanged();
VariableParameterMaintenance();
ExpireSolution(false);
}
public bool CanInsertParameter(GH_ParameterSide side, int index) => false;
public bool CanRemoveParameter(GH_ParameterSide side, int index) => false;
public IGH_Param CreateParameter(GH_ParameterSide side, int index)
{
var myParam = new Param_GenericObject
{
Name = GH_ComponentParamServer.InventUniqueNickname("ABCD", Params.Input),
MutableNickName = true,
Optional = true
};
myParam.NickName = myParam.Name;
return myParam;
}
public bool DestroyParameter(GH_ParameterSide side, int index) => side == GH_ParameterSide.Output;
public void VariableParameterMaintenance() { }
}
@@ -0,0 +1,69 @@
using Grasshopper.Kernel.Types;
using Speckle.Connectors.Common.Extensions;
using Speckle.Connectors.GrasshopperShared.Components.BaseComponents;
using Speckle.Connectors.GrasshopperShared.Parameters;
using Speckle.Connectors.GrasshopperShared.Properties;
#if RHINO8_OR_GREATER
using Grasshopper.Rhinoceros.Model;
#endif
namespace Speckle.Connectors.GrasshopperShared.Components.Objects;
public class PropertyGroupPathsSelector : ValueSet<IGH_Goo>
{
public PropertyGroupPathsSelector()
: base(
"Property Selector",
"pSelect",
"Allows you to select a set of property keys for querying",
ComponentCategories.PRIMARY_RIBBON,
ComponentCategories.OBJECTS
) { }
public override Guid ComponentGuid => new Guid("8882BE3A-81F1-4416-B420-58D69E4CC8F1");
protected override Bitmap Icon => Resources.speckle_inputs_property;
protected override void LoadVolatileData()
{
var objectPropertyGroups = VolatileData
.AllData(true)
.OfType<SpeckleObjectWrapperGoo>()
.Select(goo => goo.Value.Properties.Value)
.ToList();
#if RHINO8_OR_GREATER
// support model objects direct piping also
if (objectPropertyGroups.Count != VolatileData.DataCount)
{
var modelObjects = VolatileData
.AllData(true)
.OfType<ModelObject>()
.Select(mo => new SpeckleObjectWrapperGoo(mo).Value.Properties.Value)
.ToList();
objectPropertyGroups.AddRange(modelObjects);
}
#endif
if (objectPropertyGroups.Count == 0)
{
return;
}
var paths = GetPropertyPaths(objectPropertyGroups);
m_data.Clear();
m_data.AppendRange(paths.Select(s => new GH_String(s)));
}
private static List<string> GetPropertyPaths(List<Dictionary<string, SpecklePropertyGoo>> objectPropertyGroups)
{
var result = new HashSet<string>();
foreach (var dict in objectPropertyGroups)
{
result.AddRange(
dict.Keys.Where(k => !(k.EndsWith(".name") || k.EndsWith(".units") || k.EndsWith(".internalDefinitionName")))
);
}
return result.ToList();
}
}
@@ -0,0 +1,16 @@
using Speckle.Connectors.Common.Operations;
namespace Speckle.Connectors.GrasshopperShared.Components.Operations.Receive;
public record GrasshopperReceiveInfo(
string AccountId,
Uri ServerUrl,
string? WorkspaceId,
string ProjectId,
string ProjectName,
string ModelId,
string ModelName,
string SelectedVersionId,
string SourceApplication,
string? SelectedVersionUserId
) : ReceiveInfo(AccountId, ServerUrl, ProjectId, ProjectName, ModelId, ModelName, SelectedVersionId, SourceApplication);
@@ -0,0 +1,595 @@
using System.Runtime.InteropServices;
using Grasshopper.GUI;
using Grasshopper.GUI.Canvas;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Attributes;
using GrasshopperAsyncComponent;
using Microsoft.Extensions.DependencyInjection;
using Rhino;
using Speckle.Connectors.Common;
using Speckle.Connectors.Common.Analytics;
using Speckle.Connectors.Common.Instances;
using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Common.Operations.Receive;
using Speckle.Connectors.GrasshopperShared.HostApp;
using Speckle.Connectors.GrasshopperShared.Operations.Receive;
using Speckle.Connectors.GrasshopperShared.Parameters;
using Speckle.Connectors.GrasshopperShared.Properties;
using Speckle.Connectors.GrasshopperShared.Registration;
using Speckle.Sdk;
using Speckle.Sdk.Api;
using Speckle.Sdk.Api.GraphQL.Models;
using Speckle.Sdk.Credentials;
using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Collections;
using Speckle.Sdk.Models.Extensions;
namespace Speckle.Connectors.GrasshopperShared.Components.Operations.Receive;
[Guid("1587DF34-83E5-4AFE-B42E-F7C5C37ECD68")]
public class ReceiveAsyncComponent : GH_AsyncComponent
{
public ReceiveAsyncComponent()
: base("Load", "L", "Load a model from Speckle", ComponentCategories.PRIMARY_RIBBON, ComponentCategories.OPERATIONS)
{
BaseWorker = new ReceiveComponentWorker(this);
Attributes = new ReceiveAsyncComponentAttributes(this);
}
public override Guid ComponentGuid => GetType().GUID;
protected override Bitmap Icon => Resources.speckle_operations_load;
public string InputType { get; set; }
public bool AutoReceive { get; set; }
public string ReceivedVersionId { get; set; }
public ComponentState CurrentComponentState { get; set; } = ComponentState.NeedsInput;
public bool JustPastedIn { get; set; }
public string LastVersionDate { get; set; }
public string LastInfoMessage { get; set; }
public HostApp.SpeckleUrlModelResource? UrlModelResource { get; set; }
// DI props
public IClient ApiClient { get; private set; }
public MixPanelManager MixPanelManager { get; private set; }
public GrasshopperReceiveOperation ReceiveOperation { get; private set; }
public RootObjectUnpacker RootObjectUnpacker { get; private set; }
public static IServiceScope? Scope { get; private set; }
public AccountService AccountService { get; private set; }
public AccountManager AccountManager { get; private set; }
public IClientFactory ClientFactory { get; private set; }
protected override void RegisterInputParams(GH_InputParamManager pManager)
{
pManager.AddParameter(new SpeckleUrlModelResourceParam(GH_ParamAccess.item));
}
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
{
pManager.AddParameter(
new SpeckleCollectionParam(GH_ParamAccess.item),
"Collection",
"collection",
"The model collection of the loaded version",
GH_ParamAccess.item
);
}
protected override void SolveInstance(IGH_DataAccess da)
{
da.DisableGapLogic();
// Dependency Injection
Scope = PriorityLoader.Container.CreateScope();
ReceiveOperation = Scope.ServiceProvider.GetRequiredService<GrasshopperReceiveOperation>();
MixPanelManager = Scope.ServiceProvider.GetRequiredService<MixPanelManager>();
RootObjectUnpacker = Scope.ServiceProvider.GetService<RootObjectUnpacker>();
AccountService = Scope.ServiceProvider.GetRequiredService<AccountService>();
AccountManager = Scope.ServiceProvider.GetRequiredService<AccountManager>();
ClientFactory = Scope.ServiceProvider.GetRequiredService<IClientFactory>();
// We need to call this always in here to be able to react and set events :/
ParseInput(da);
if (
(
AutoReceive
|| CurrentComponentState == ComponentState.Ready
|| CurrentComponentState == ComponentState.Receiving
) && !JustPastedIn
)
{
CurrentComponentState = ComponentState.Receiving;
// Delegate control to parent async component.
base.SolveInstance(da);
return;
}
if (JustPastedIn)
{
// This ensures that we actually do a run. The worker will check and determine if it needs to pull an existing object or not.
OnDisplayExpired(true);
base.SolveInstance(da);
}
else
{
CurrentComponentState = ComponentState.Expired;
Message = "Expired";
OnDisplayExpired(true);
}
}
public override void AppendAdditionalMenuItems(ToolStripDropDown menu)
{
base.AppendAdditionalMenuItems(menu);
Menu_AppendSeparator(menu);
if (InputType == "Model")
{
var autoReceiveMi = Menu_AppendItem(
menu,
"Load automatically",
(s, e) =>
{
AutoReceive = !AutoReceive;
RhinoApp.InvokeOnUiThread(
(Action)
delegate
{
OnDisplayExpired(true);
}
);
},
true,
AutoReceive
);
autoReceiveMi.ToolTipText =
"Toggle automatic loading. If set, any new version will be loaded instantly. This only is applicable when receiving from a model url.";
}
else
{
var autoReceiveMi = Menu_AppendItem(menu, "Automatic loading is disabled because you have specified a version.");
autoReceiveMi.ToolTipText = "To enable automatic loading, select a model without selecting a specific version.";
}
Menu_AppendSeparator(menu);
if (CurrentComponentState == ComponentState.Receiving)
{
Menu_AppendItem(
menu,
"Cancel Load",
(s, e) =>
{
CurrentComponentState = ComponentState.Expired;
RequestCancellation();
}
);
}
}
private void HandleNewCommit()
{
Message = "Expired";
CurrentComponentState = ComponentState.Expired;
AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, $"There is a newer version available for this {InputType}");
RhinoApp.InvokeOnUiThread(
(Action)
delegate
{
if (AutoReceive)
{
ExpireSolution(true);
}
else
{
OnDisplayExpired(true);
}
}
);
}
public override void RemovedFromDocument(GH_Document document)
{
RequestCancellation();
Scope?.Dispose();
base.RemovedFromDocument(document);
}
public override void DocumentContextChanged(GH_Document document, GH_DocumentContext context)
{
switch (context)
{
case GH_DocumentContext.Loaded:
{
// Will execute every time a document becomes active (from background or opening file.).
if (UrlModelResource != null)
{
Task.Run(async () =>
{
// Ensure fresh instance of client.
ResetApiClient(UrlModelResource);
// Get last commit from the branch
var b = UrlModelResource.GetReceiveInfo(ApiClient);
await b;
// Compare version ids. If they don't match, notify user or fetch data if in auto mode
if (b.Result.SelectedVersionId != ReceivedVersionId)
{
HandleNewCommit();
}
OnDisplayExpired(true);
});
}
break;
}
case GH_DocumentContext.Unloaded:
// Will execute every time a document becomes inactive (in background or closing file.)
// Correctly dispose of the client when changing documents to prevent subscription handlers being called in background.
CurrentComponentState = ComponentState.Expired;
RequestCancellation();
ApiClient?.Dispose();
break;
}
base.DocumentContextChanged(document, context);
}
private void ParseInput(IGH_DataAccess da)
{
HostApp.SpeckleUrlModelResource? dataInput = null;
da.GetData(0, ref dataInput);
if (dataInput is null)
{
UrlModelResource = null;
TriggerAutoSave();
return;
}
// set the type of url input
switch (dataInput)
{
case SpeckleUrlModelVersionResource:
InputType = "Version";
AutoReceive = false;
LastInfoMessage = "";
ResetApiClient(dataInput);
return;
case SpeckleUrlModelResource:
InputType = "Model";
// handled in do work
break;
default:
InputType = "Invalid";
break;
}
if (UrlModelResource != null && UrlModelResource.Equals(dataInput) && !JustPastedIn)
{
return;
}
UrlModelResource = dataInput;
ResetApiClient(UrlModelResource);
}
private void ApiClient_OnVersionCreated(object sender, ProjectVersionsUpdatedMessage e)
{
HandleNewCommit();
}
public void ResetApiClient(SpeckleUrlModelResource urlResource)
{
try
{
Account? account =
urlResource.AccountId != null
? AccountManager.GetAccount(urlResource.AccountId)
: AccountService.GetAccountWithServerUrlFallback("", new Uri(urlResource.Server)); // fallback the account that matches with URL if any
if (account is null)
{
throw new SpeckleAccountManagerException($"No default account was found");
}
ApiClient?.Dispose();
ApiClient = ClientFactory.Create(account);
ApiClient.Subscription.CreateProjectVersionsUpdatedSubscription(urlResource.ProjectId).Listeners +=
ApiClient_OnVersionCreated;
}
catch (Exception e) when (!e.IsFatal())
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, e.ToFormattedString());
}
}
}
public class ReceiveComponentWorker : WorkerInstance
{
public ReceiveComponentWorker(GH_Component p)
: base(p) { }
public Base Root { get; set; }
public SpeckleUrlModelResource? UrlModelResource { get; set; }
public SpeckleCollectionWrapperGoo Result { get; set; }
private List<(GH_RuntimeMessageLevel, string)> RuntimeMessages { get; } = new();
public override WorkerInstance Duplicate()
{
return new ReceiveComponentWorker(Parent);
}
public override void GetData(IGH_DataAccess da, GH_ComponentParamServer p)
{
UrlModelResource = ((ReceiveAsyncComponent)Parent).UrlModelResource;
}
public override void SetData(IGH_DataAccess da)
{
if (CancellationToken.IsCancellationRequested)
{
return;
}
foreach (var (level, message) in RuntimeMessages)
{
Parent.AddRuntimeMessage(level, message);
}
var parent = (ReceiveAsyncComponent)Parent;
parent.CurrentComponentState = ComponentState.UpToDate;
parent.JustPastedIn = false;
if (Result == null)
{
return;
}
da.SetData(0, Result);
}
#pragma warning disable CA1506
public override void DoWork(Action<string, double> reportProgress, Action done)
#pragma warning restore CA1506
{
var receiveComponent = (ReceiveAsyncComponent)Parent;
try
{
if (UrlModelResource is null)
{
throw new InvalidOperationException("Model Resource was null");
}
// Means it's a copy paste of an empty non-init component; set the record and exit fast.
if (receiveComponent.JustPastedIn && !receiveComponent.AutoReceive)
{
receiveComponent.JustPastedIn = false;
return;
}
receiveComponent.CurrentComponentState = ComponentState.Receiving;
RhinoApp.InvokeOnUiThread(
(Action)
delegate
{
receiveComponent.OnDisplayExpired(true);
}
);
var t = Task.Run(async () =>
{
// Step 1 - RECEIVE FROM SERVER
var receiveInfo = await UrlModelResource
.GetReceiveInfo(receiveComponent.ApiClient, CancellationToken)
.ConfigureAwait(false);
var progress = new Progress<CardProgress>(p =>
{
reportProgress(Id, p.Progress ?? 0);
//eceiveComponent.Message = $"{p.Status}";
});
if (CancellationToken.IsCancellationRequested)
{
return;
}
if (receiveInfo == null)
{
done();
return;
}
Root = await receiveComponent
.ReceiveOperation.ReceiveCommitObject(receiveInfo, progress, CancellationToken)
.ConfigureAwait(false);
if (CancellationToken.IsCancellationRequested)
{
return;
}
// Step 2 - CONVERT
//receiveComponent.Message = $"Unpacking...";
LocalToGlobalUnpacker localToGlobalUnpacker = new();
TraversalContextUnpacker traversalContextUnpacker = new();
var unpackedRoot = receiveComponent.RootObjectUnpacker.Unpack(Root);
// "flatten" block instances
var localToGlobalMaps = localToGlobalUnpacker.Unpack(
unpackedRoot.DefinitionProxies,
unpackedRoot.ObjectsToConvert.ToList()
);
// TODO: unpack colors and render materials
GrasshopperColorUnpacker colorUnpacker = new(unpackedRoot);
GrasshopperMaterialUnpacker materialUnpacker = new(unpackedRoot);
GrasshopperCollectionRebuilder collectionRebuilder =
new((Root as Collection) ?? new Collection() { name = "unnamed" });
LocalToGlobalMapHandler mapHandler =
new(traversalContextUnpacker, collectionRebuilder, colorUnpacker, materialUnpacker);
int count = 0;
int total = localToGlobalMaps.Count;
foreach (var map in localToGlobalMaps)
{
mapHandler.CreateGrasshopperObjectFromMap(map);
count++;
}
Result = new SpeckleCollectionWrapperGoo(collectionRebuilder.RootCollectionWrapper);
// TODO: If we have NodeRun events later, better to have `ComponentTracker` to use across components
var customProperties = new Dictionary<string, object>()
{
{ "isAsync", true },
{ "sourceHostApp", HostApplications.GetSlugFromHostAppNameAndVersion(receiveInfo.SourceApplication) },
{ "auto", receiveComponent.AutoReceive }
};
if (receiveInfo.WorkspaceId != null)
{
customProperties.Add("workspace_id", receiveInfo.WorkspaceId);
}
if (receiveInfo.SelectedVersionUserId != null)
{
customProperties.Add(
"isMultiplayer",
receiveInfo.SelectedVersionUserId != receiveComponent.ApiClient.Account.userInfo.id
);
}
await receiveComponent.MixPanelManager.TrackEvent(
MixPanelEvents.Receive,
receiveComponent.ApiClient.Account,
customProperties
);
// DONE
done();
});
t.Wait();
}
catch (Exception ex) when (!ex.IsFatal())
{
RuntimeMessages.Add((GH_RuntimeMessageLevel.Error, ex.ToFormattedString()));
done();
}
}
}
public class ReceiveAsyncComponentAttributes : GH_ComponentAttributes
{
private bool _selected;
public ReceiveAsyncComponentAttributes(GH_Component owner)
: base(owner) { }
private Rectangle ButtonBounds { get; set; }
public override bool Selected
{
get => _selected;
set => _selected = value;
}
protected override void Layout()
{
base.Layout();
var baseRec = GH_Convert.ToRectangle(Bounds);
baseRec.Height += 26;
var btnRec = baseRec;
btnRec.Y = btnRec.Bottom - 26;
btnRec.Height = 26;
btnRec.Inflate(-2, -2);
Bounds = baseRec;
ButtonBounds = btnRec;
}
protected override void Render(GH_Canvas canvas, Graphics graphics, GH_CanvasChannel channel)
{
base.Render(canvas, graphics, channel);
var state = ((ReceiveAsyncComponent)Owner).CurrentComponentState;
if (channel == GH_CanvasChannel.Objects)
{
if (((ReceiveAsyncComponent)Owner).AutoReceive)
{
var autoReceiveButton = GH_Capsule.CreateTextCapsule(
ButtonBounds,
ButtonBounds,
GH_Palette.Blue,
"Auto Load",
2,
0
);
autoReceiveButton.Render(graphics, Selected, Owner.Locked, false);
autoReceiveButton.Dispose();
}
else
{
var palette =
state == ComponentState.Expired || state == ComponentState.UpToDate || state == ComponentState.Cancelled
? GH_Palette.Black
: GH_Palette.Transparent;
var text = state != ComponentState.Receiving ? "Load" : "Loading...";
var button = GH_Capsule.CreateTextCapsule(
ButtonBounds,
ButtonBounds,
palette,
text,
2,
state == ComponentState.Expired ? 10 : 0
);
button.Render(graphics, Selected, Owner.Locked, false);
button.Dispose();
}
}
}
public override GH_ObjectResponse RespondToMouseDown(GH_Canvas sender, GH_CanvasMouseEvent e)
{
if (e.Button != MouseButtons.Left)
{
return base.RespondToMouseDown(sender, e);
}
if (!((RectangleF)ButtonBounds).Contains(e.CanvasLocation))
{
return base.RespondToMouseDown(sender, e);
}
if (((ReceiveAsyncComponent)Owner).CurrentComponentState == ComponentState.Receiving)
{
return GH_ObjectResponse.Handled;
}
if (((ReceiveAsyncComponent)Owner).AutoReceive)
{
((ReceiveAsyncComponent)Owner).AutoReceive = false;
Owner.OnDisplayExpired(true);
return GH_ObjectResponse.Handled;
}
// TODO: check if owner has null account/client, and call the reset thing SYNC
((ReceiveAsyncComponent)Owner).CurrentComponentState = ComponentState.Ready;
Owner.ExpireSolution(true);
return GH_ObjectResponse.Handled;
}
}

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