Compare commits

...

46 Commits

Author SHA1 Message Date
Oğuzhan Koral 96e729ef50 Merge pull request #595 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 releases to dev
2025-02-18 19:38:22 +03:00
Dogukan Karatas 12dcf471d3 fix (tekla): updates the vebview2 dependency (#562)
* updates webview dependencies

* updates csproj

---------

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

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

* Update ClassPropertiesExtractor.cs

* some bug fixes

* Update PartDataExtractor.cs

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

* update to SDK 267

* adjust ifc tester

* Update to SDK 268

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

* reverted LibraryImport as it would need more testing

* IFC app ids
2025-02-17 16:35:26 +00:00
Björn Steinhagen 6d4e12dfae Merge pull request #591 from specklesystems/dev
test(etabs): bundled installer with ini file magic
2025-02-17 13:52:57 +01:00
Björn Steinhagen f882b0f5bd fix(etabs): ensure csi operations run on main thread to prevent etabs exceptions (#589)
* fix: ensure operations run on main thread to prevent etabsexceptions

* pr comments

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

* refactor: mixed concerns

Some structural asset stuff was in the MaterialQuantitiesToSpeckle.cs

---------

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

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

* removes number from room since this is included in params

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

* stupid typos

---------

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

* more QueuedTask usage and format

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

* fix: applies the minimal fix

* chore: adds comment for future

---------

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

* feature: frame length extraction

* feat: shell area extraction

* feat: frame length extraction

* feat: shell area extraction

* docs: cleaned up object extractors

* refactor: extensible database table extraction

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

* refactor: using DatabaseTableExtractor for material name lookup

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

* fix: openings shouldn't look for material assignments

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

* refactor: database table extractor handles dictionary lookups
2025-02-12 18:43:44 +00:00
Dimitrie Stefanescu 5c2c0ff303 Merge pull request #582 from specklesystems/dimitrie/cnx-1239-rhino-fix-the-documentisinit-post-copy-paste
Rhino: fixes change detection post copy paste events
2025-02-12 15:00:32 +00:00
Dimitrie Stefanescu a6fd4547ea feat: adds previous dix 2025-02-12 14:38:47 +00:00
Adam Hathcock 0d27eadfeb add deep clean local docs (#579) 2025-02-11 14:06:12 +00:00
Oğuzhan Koral 929db22785 Merge pull request #578 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 release from dev
2025-02-10 17:53:46 +00:00
Dimitrie Stefanescu 0b26e021cd fix: prevents fatal crash on old model cards (#548)
* fix: prevents fatal crash on old model cards

* fix: formatting

---------

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

* untangle revit

* adds brepx converter

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

* revert rhino

* revert autocad

* revert rest

* remove event agg and rhino implementation

* remove event aggr from revit

* remove event aggr from autocad and civil

* remove event aggr tests

* remove event aggr from tekla

* Remove event aggr for navis

* remove event aggr from csi etabs

* remove event aggr for arcgis

* remove remaining pieces

* adds brep converter

* push autocad to run operations on main thread

* adds teklaidlemanager

* bring navis idle manager back

* run send on main

* adds extrusionx and subdx support

* adjusts converter return types to fallback case

---------

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

* move properties extractor to converter and updates attributes event listener

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

* Update RhinoObjectToSpeckleTopLevelConverter.cs

* Update ServiceRegistration.cs

* adds explicit conditions for object attribute change event

* feat: simplifies rhino implementation

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

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

* Update RhinoSendBinding.cs

* Update PropertiesExtractor.cs

---------

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

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

* reformatted

* updates entry structure

---------

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

* untangle revit

* revert rhino

* revert autocad

* revert rest

* remove event agg and rhino implementation

* remove event aggr from revit

* remove event aggr from autocad and civil

* remove event aggr tests

* remove event aggr from tekla

* Remove event aggr for navis

* remove event aggr from csi etabs

* remove event aggr for arcgis

* remove remaining pieces

* push autocad to run operations on main thread

* adds teklaidlemanager

* bring navis idle manager back

* run send on main

* remove unused function

---------

Co-authored-by: Dogukan Karatas <karatasdogukan@gmail.com>
2025-02-10 17:50:26 +03:00
Jedd Morgan 931d7ff8d2 Merge pull request #577 from specklesystems/dev
test(etabs): installer
2025-02-10 10:27:38 +00:00
Oğuzhan Koral 18499bdc69 Chore: update code ownership (#575)
* update code ownership

* fix typo for claire :)
2025-02-07 10:35:08 +00:00
Jedd Morgan e78914955c Merge pull request #541 from specklesystems/dev
test(etabs): installer
2025-01-30 17:22:52 +00:00
Jedd Morgan 87569c9c66 Merge pull request #537 from specklesystems/dev
Test for ETABS installer
2025-01-29 15:19:34 +00:00
Oğuzhan Koral 189ea3a19b Merge pull request #501 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 release
2025-01-16 19:18:02 +03:00
Oğuzhan Koral 370588fa89 Merge pull request #461 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
.NET Build and Publish / test (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
Update dev to release
2024-12-20 16:14:59 +03:00
Oğuzhan Koral c9802396f5 Merge pull request #448 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
.NET Build and Publish / test (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
Update dev to release
2024-12-13 01:54:05 +03:00
Oğuzhan Koral 9644444ea7 Merge pull request #437 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
.NET Build and Publish / test (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
Update dev to release
2024-12-04 22:38:16 +03:00
Alan Rynne bb0fffd4d7 Merge pull request #414 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
.NET Build and Publish / test (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
Update `release/3.0.0` with changes from `dev`
2024-11-27 16:23:50 +01:00
Alan Rynne c719cfd66f Merge pull request #383 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
.NET Build and Publish / test (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
Update `release/3.0.0` with changes from `dev`
2024-11-12 15:56:02 +01:00
Oğuzhan Koral 92435ce1a1 Merge pull request #376 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
.NET Build and Publish / test (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
Update release/3.0.0 with changes from dev
2024-11-08 18:16:16 +00:00
Oğuzhan Koral 71409e8af8 Merge pull request #374 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
.NET Build and Publish / test (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
Update release/3.0.0 with changes from dev
2024-11-08 15:13:47 +00:00
Alan Rynne 8060f46882 Merge pull request #359 from specklesystems/dev
Update `release/3.0.0` with changes from `dev`
2024-11-06 18:49:52 +01:00
Alan Rynne 6671edd36e Merge pull request #354 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
.NET Build and Publish / test (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
Update `release/3.0.0` with changes from `dev`
2024-11-06 14:22:08 +01:00
Alan Rynne bc15ff3a34 Merge pull request #347 from specklesystems/dev
Update `release/3.0.0` with changes from `dev`
2024-11-05 10:30:20 +01:00
Alan Rynne de275dcf02 Merge pull request #337 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
.NET Build and Publish / test (push) Has been cancelled
.NET Build and Publish / deploy-installers (push) Has been cancelled
Update `release/3.0.0` with changes from `dev`
2024-10-31 12:17:57 +01:00
Alan Rynne 6158739df0 Merge pull request #331 from specklesystems/dev
Update `release/3.0.0` with changes from `dev`
2024-10-28 13:05:26 +01:00
254 changed files with 4903 additions and 4940 deletions
+29 -26
View File
@@ -4,33 +4,36 @@
# * @specklesystems/connectors
# Core
# Not needed, falls back on team approval
# Objects
# Converters require product owner approval, anything else falls back to team approval
Objects/ConverterAutocadCivil/* @clairekuang @connorivy
Objects/ConverterCSI/* @connorivy
Objects/ConverterDynamo/* @teocomi @alanrynne
Objects/ConverterMicrostation/* @connorivy
Objects/ConverterRevit/* @connorivy @teocomi
Objects/ConverterRhinoGh/* @alanrynne @clairekuang
Objects/ConverterTeklaStructures/* @connorivy
Objects/StructuralUtilities/PolygonMesher/* @connorivy
# Connectors
ConnectorAutocadCivil/* @clairekuang
ConnectorArchicad/* @jozseflkiss
ConnectorCSI/* @connorivy
ConnectorDynamo/* @teocomi @alanrynne
ConnectorGrasshopper/* @alanrynne @clairekuang
ConnectorMicrostation/* @clairekuang
ConnectorRevit/* @teocomi @connorivy
ConnectorRhino/* @clairekuang @alanrynne
ConnectorTeklaStructures/* @connorivy
/Connectors/ArcGIS/* @KatKatKateryna
/Connectors/Autocad/* @clairekuang @oguzhankoral @didimitrie
/Connectors/Civil3d/* @clairekuang @oguzhankoral @didimitrie
/Connectors/CSi/* @bjoernsteinhagen @dogukankaratas
/Connectors/Navisworks/* @jsdbroughton
/Connectors/Revit/* @clairekuang @oguzhankoral @didimitrie
/Connectors/Rhino/* @clairekuang @oguzhankoral @didimitrie
/Connectors/Tekla/* @bjoernsteinhagen @dogukankaratas
# DesktopUI
# Converters
/Convertors/ArcGIS/* @KatKatKateryna
/Convertors/Autocad/* @clairekuang @oguzhankoral @didimitrie
/Convertors/Civil3d/* @clairekuang @oguzhankoral @didimitrie
/Convertors/CSi/* @bjoernsteinhagen @dogukankaratas
/Convertors/Navisworks/* @jsdbroughton
/Convertors/Revit/* @clairekuang @oguzhankoral @didimitrie
/Convertors/Rhino/* @clairekuang @oguzhankoral @didimitrie
/Convertors/Tekla/* @bjoernsteinhagen @dogukankaratas
DesktopUI2/* @teocomi @clairekuang
# DUI
/DUI3/* @clairekuang @oguzhankoral @didimitrie
# Importers
/Importers/* @JR-Morgan @didimitrie @oguzhankoral @adamhathcock
# SDK
/SDK/* @JR-Morgan @clairekuang @didimitrie @oguzhankoral @adamhathcock
# Build
/Build/* @JR-Morgan @oguzhankoral @adamhathcock
@@ -3,6 +3,7 @@ using System.Diagnostics.CodeAnalysis;
using ArcGIS.Core.Data;
using ArcGIS.Desktop.Core;
using ArcGIS.Desktop.Editing.Events;
using ArcGIS.Desktop.Framework.Threading.Tasks;
using ArcGIS.Desktop.Mapping;
using ArcGIS.Desktop.Mapping.Events;
using Microsoft.Extensions.DependencyInjection;
@@ -15,7 +16,6 @@ using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.DUI.Exceptions;
using Speckle.Connectors.DUI.Logging;
using Speckle.Connectors.DUI.Models;
@@ -71,7 +71,6 @@ public sealed class ArcGISSendBinding : ISendBinding
IArcGISConversionSettingsFactory arcGisConversionSettingsFactory,
MapMembersUtils mapMemberUtils,
IThreadContext threadContext,
IEventAggregator eventAggregator,
ITopLevelExceptionHandler topLevelExceptionHandler
)
{
@@ -90,7 +89,10 @@ public sealed class ArcGISSendBinding : ISendBinding
Parent = parent;
Commands = new SendBindingUICommands(parent);
SubscribeToArcGISEvents();
eventAggregator.GetEvent<DocumentStoreChangedEvent>().Subscribe(OnDocumentStoreChangedEvent);
_store.DocumentChanged += (_, _) =>
{
_sendConversionCache.ClearCache();
};
}
private void OnDocumentStoreChangedEvent(object _) => _sendConversionCache.ClearCache();
@@ -100,7 +102,7 @@ public sealed class ArcGISSendBinding : ISendBinding
LayersRemovedEvent.Subscribe(
a =>
_topLevelExceptionHandler.FireAndForget(
async () => await _threadContext.RunOnWorkerAsync(async () => await GetIdsForLayersRemovedEvent(a))
async () => await QueuedTask.Run(async () => await GetIdsForLayersRemovedEvent(a))
),
true
);
@@ -108,7 +110,7 @@ public sealed class ArcGISSendBinding : ISendBinding
StandaloneTablesRemovedEvent.Subscribe(
a =>
_topLevelExceptionHandler.FireAndForget(
async () => await _threadContext.RunOnWorkerAsync(async () => await GetIdsForStandaloneTablesRemovedEvent(a))
async () => await QueuedTask.Run(async () => await GetIdsForStandaloneTablesRemovedEvent(a))
),
true
);
@@ -116,7 +118,7 @@ public sealed class ArcGISSendBinding : ISendBinding
MapPropertyChangedEvent.Subscribe(
a =>
_topLevelExceptionHandler.FireAndForget(
async () => await _threadContext.RunOnWorkerAsync(async () => await GetIdsForMapPropertyChangedEvent(a))
async () => await QueuedTask.Run(async () => await GetIdsForMapPropertyChangedEvent(a))
),
true
); // Map units, CRS etc.
@@ -124,8 +126,7 @@ public sealed class ArcGISSendBinding : ISendBinding
MapMemberPropertiesChangedEvent.Subscribe(
a =>
_topLevelExceptionHandler.FireAndForget(
async () =>
await _threadContext.RunOnWorkerAsync(async () => await GetIdsForMapMemberPropertiesChangedEvent(a))
async () => await QueuedTask.Run(async () => await GetIdsForMapMemberPropertiesChangedEvent(a))
),
true
); // e.g. Layer name
@@ -134,7 +135,7 @@ public sealed class ArcGISSendBinding : ISendBinding
_ =>
_topLevelExceptionHandler.FireAndForget(async () =>
{
await _threadContext.RunOnWorker(SubscribeToMapMembersDataSourceChange);
await QueuedTask.Run(SubscribeToMapMembersDataSourceChange);
}),
true
);
@@ -375,21 +376,25 @@ public sealed class ArcGISSendBinding : ISendBinding
using var cancellationItem = _cancellationManager.GetCancellationItem(modelCardId);
using var scope = _serviceProvider.CreateScope();
scope
.ServiceProvider.GetRequiredService<IConverterSettingsStore<ArcGISConversionSettings>>()
.Initialize(
_arcGISConversionSettingsFactory.Create(
Project.Current,
MapView.Active.Map,
new CRSoffsetRotation(MapView.Active.Map)
)
);
List<MapMember> mapMembers = modelCard
.SendFilter.NotNull()
.RefreshObjectIds()
.Select(id => (MapMember)MapView.Active.Map.FindLayer(id) ?? MapView.Active.Map.FindStandaloneTable(id))
.Where(obj => obj != null)
.ToList();
List<MapMember> mapMembers = await QueuedTask.Run(() =>
{
scope
.ServiceProvider.GetRequiredService<IConverterSettingsStore<ArcGISConversionSettings>>()
.Initialize(
_arcGISConversionSettingsFactory.Create(
Project.Current,
MapView.Active.Map,
new CRSoffsetRotation(MapView.Active.Map)
)
);
return modelCard
.SendFilter.NotNull()
.RefreshObjectIds()
.Select(id => (MapMember)MapView.Active.Map.FindLayer(id) ?? MapView.Active.Map.FindStandaloneTable(id))
.Where(obj => obj != null)
.ToList();
});
if (mapMembers.Count == 0)
{
@@ -397,18 +402,21 @@ public sealed class ArcGISSendBinding : ISendBinding
throw new SpeckleSendFilterException("No objects were found to convert. Please update your publish filter!");
}
// subscribe to the selected layer events
foreach (MapMember mapMember in mapMembers)
await QueuedTask.Run(() =>
{
if (mapMember is FeatureLayer featureLayer)
// subscribe to the selected layer events
foreach (MapMember mapMember in mapMembers)
{
SubscribeToFeatureLayerDataSourceChange(featureLayer);
if (mapMember is FeatureLayer featureLayer)
{
SubscribeToFeatureLayerDataSourceChange(featureLayer);
}
else if (mapMember is StandaloneTable table)
{
SubscribeToTableDataSourceChange(table);
}
}
else if (mapMember is StandaloneTable table)
{
SubscribeToTableDataSourceChange(table);
}
}
});
var sendResult = await scope
.ServiceProvider.GetRequiredService<SendOperation<MapMember>>()
@@ -1,9 +1,9 @@
using ArcGIS.Core.Data;
using ArcGIS.Desktop.Framework.Threading.Tasks;
using ArcGIS.Desktop.Mapping;
using Speckle.Connectors.ArcGIS.Utils;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Models.Card;
using Speckle.Sdk;
@@ -21,24 +21,28 @@ public class BasicConnectorBinding : IBasicConnectorBinding
public BasicConnectorBindingCommands Commands { get; }
private readonly DocumentModelStore _store;
private readonly ISpeckleApplication _speckleApplication;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
public BasicConnectorBinding(
DocumentModelStore store,
IBrowserBridge parent,
ISpeckleApplication speckleApplication,
IEventAggregator eventAggregator
ITopLevelExceptionHandler topLevelExceptionHandler
)
{
_store = store;
_speckleApplication = speckleApplication;
_topLevelExceptionHandler = topLevelExceptionHandler;
Parent = parent;
Commands = new BasicConnectorBindingCommands(parent);
eventAggregator.GetEvent<DocumentStoreChangedEvent>().Subscribe(OnDocumentStoreChangedEvent);
_store.DocumentChanged += (_, _) =>
_topLevelExceptionHandler.FireAndForget(async () =>
{
await Commands.NotifyDocumentChanged();
});
}
private async Task OnDocumentStoreChangedEvent(object _) => await Commands.NotifyDocumentChanged();
public string GetSourceApplicationName() => _speckleApplication.Slug;
public string GetSourceApplicationVersion() => _speckleApplication.HostApplicationVersion;
@@ -63,19 +67,18 @@ public class BasicConnectorBinding : IBasicConnectorBinding
public void RemoveModel(ModelCard model) => _store.RemoveModel(model);
public Task HighlightObjects(IReadOnlyList<string> objectIds)
public async Task HighlightObjects(IReadOnlyList<string> objectIds)
{
HighlightObjectsOnView(objectIds.Select(x => new ObjectID(x)).ToList());
return Task.CompletedTask;
await HighlightObjectsOnView(objectIds.Select(x => new ObjectID(x)).ToList());
}
public Task HighlightModel(string modelCardId)
public async Task HighlightModel(string modelCardId)
{
var model = _store.GetModelById(modelCardId);
if (model is null)
{
return Task.CompletedTask;
return;
}
var objectIds = new List<ObjectID>();
@@ -92,22 +95,24 @@ public class BasicConnectorBinding : IBasicConnectorBinding
if (objectIds is null)
{
return Task.CompletedTask;
return;
}
HighlightObjectsOnView(objectIds);
return Task.CompletedTask;
await HighlightObjectsOnView(objectIds);
}
private void HighlightObjectsOnView(IReadOnlyList<ObjectID> objectIds)
private async Task HighlightObjectsOnView(IReadOnlyList<ObjectID> objectIds)
{
MapView mapView = MapView.Active;
await QueuedTask.Run(() =>
{
MapView mapView = MapView.Active;
List<MapMemberFeature> mapMembersFeatures = GetMapMembers(objectIds, mapView);
ClearSelectionInTOC();
ClearSelection();
SelectMapMembersInTOC(mapMembersFeatures);
SelectMapMembersAndFeatures(mapMembersFeatures);
mapView.ZoomToSelected();
List<MapMemberFeature> mapMembersFeatures = GetMapMembers(objectIds, mapView);
ClearSelectionInTOC();
ClearSelection();
SelectMapMembersInTOC(mapMembersFeatures);
SelectMapMembersAndFeatures(mapMembersFeatures);
mapView.ZoomToSelected();
});
}
private List<MapMemberFeature> GetMapMembers(IReadOnlyList<ObjectID> objectIds, MapView mapView)
@@ -10,6 +10,7 @@ using Speckle.Connectors.Common;
using Speckle.Connectors.Common.Builders;
using Speckle.Connectors.Common.Caching;
using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Models.Card.SendFilter;
@@ -27,7 +28,7 @@ public static class ArcGISConnectorModule
public static void AddArcGIS(this IServiceCollection serviceCollection)
{
serviceCollection.AddConnectorUtils();
serviceCollection.AddDUI<ArcGISThreadContext, ArcGISDocumentStore>();
serviceCollection.AddDUI<DefaultThreadContext, ArcGISDocumentStore>();
serviceCollection.AddDUIView();
// Register bindings
@@ -1,6 +1,7 @@
using System.Diagnostics.Contracts;
using ArcGIS.Core.CIM;
using ArcGIS.Core.Geometry;
using ArcGIS.Desktop.Framework.Threading.Tasks;
using ArcGIS.Desktop.Mapping;
using Speckle.Connectors.ArcGIS.HostApp;
using Speckle.Connectors.ArcGIS.Utils;
@@ -53,7 +54,20 @@ public class ArcGISHostObjectBuilder : IHostObjectBuilder
_colorManager = colorManager;
}
public HostObjectBuilderResult Build(
public Task<HostObjectBuilderResult> Build(
Base rootObject,
string projectName,
string modelName,
IProgress<CardProgress> onOperationProgressed,
CancellationToken cancellationToken
)
{
return QueuedTask.Run(
() => BuildInternal(rootObject, projectName, modelName, onOperationProgressed, cancellationToken)
);
}
private HostObjectBuilderResult BuildInternal(
Base rootObject,
string projectName,
string modelName,
@@ -226,7 +240,7 @@ public class ArcGISHostObjectBuilder : IHostObjectBuilder
bakedObjectIds.AddRange(createdLayerGroups.Values.Select(x => x.URI));
// TODO: validated a correct set regarding bakedobject ids
return new(bakedObjectIds, results);
return new HostObjectBuilderResult(bakedObjectIds, results);
}
private IReadOnlyCollection<LocalToGlobalMap> GetObjectsToConvert(Base rootObject)
@@ -1,5 +1,6 @@
using ArcGIS.Core.Data.Raster;
using ArcGIS.Core.Geometry;
using ArcGIS.Desktop.Framework.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Speckle.Connectors.ArcGIS.HostApp;
using Speckle.Connectors.ArcGIS.HostApp.Extensions;
@@ -49,7 +50,14 @@ public class ArcGISRootObjectBuilder : IRootObjectBuilder<ADM.MapMember>
_mapMemberUtils = mapMemberUtils;
}
public async Task<RootObjectBuilderResult> BuildAsync(
public Task<RootObjectBuilderResult> Build(
IReadOnlyList<ADM.MapMember> layers,
SendInfo __,
IProgress<CardProgress> onOperationProgressed,
CancellationToken cancellationToken
) => QueuedTask.Run(() => BuildInternal(layers, __, onOperationProgressed, cancellationToken));
private async Task<RootObjectBuilderResult> BuildInternal(
IReadOnlyList<ADM.MapMember> layers,
SendInfo __,
IProgress<CardProgress> onOperationProgressed,
@@ -1,36 +0,0 @@
using ArcGIS.Desktop.Framework.Threading.Tasks;
using Speckle.Connectors.Common.Threading;
namespace Speckle.Connectors.ArcGIS.Utils;
//don't check for GUI as it's the same check we do in ThreadContext
public class ArcGISThreadContext : ThreadContext
{
protected override Task<T> MainToWorkerAsync<T>(Func<Task<T>> action)
{
if (QueuedTask.OnWorker)
{
return action();
}
else
{
return QueuedTask.Run(async () => await action());
}
}
protected override Task<T> WorkerToMainAsync<T>(Func<Task<T>> action) => QueuedTask.Run(async () => await action());
protected override Task<T> MainToWorker<T>(Func<T> action)
{
if (QueuedTask.OnWorker)
{
return Task.FromResult(action());
}
else
{
return QueuedTask.Run(action);
}
}
protected override Task<T> WorkerToMain<T>(Func<T> action) => QueuedTask.Run(action);
}
@@ -1,10 +1,10 @@
using System.Xml.Linq;
using ArcGIS.Desktop.Core.Events;
using ArcGIS.Desktop.Framework.Threading.Tasks;
using ArcGIS.Desktop.Mapping;
using ArcGIS.Desktop.Mapping.Events;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Utils;
@@ -13,18 +13,15 @@ namespace Speckle.Connectors.ArcGIS.Utils;
public class ArcGISDocumentStore : DocumentModelStore
{
private readonly IThreadContext _threadContext;
private readonly IEventAggregator _eventAggregator;
public ArcGISDocumentStore(
IJsonSerializer jsonSerializer,
ITopLevelExceptionHandler topLevelExceptionHandler,
IThreadContext threadContext,
IEventAggregator eventAggregator
IThreadContext threadContext
)
: base(jsonSerializer)
{
_threadContext = threadContext;
_eventAggregator = eventAggregator;
ActiveMapViewChangedEvent.Subscribe(a => topLevelExceptionHandler.CatchUnhandled(() => OnMapViewChanged(a)), true);
ProjectSavingEvent.Subscribe(
_ =>
@@ -42,16 +39,13 @@ public class ArcGISDocumentStore : DocumentModelStore
},
true
);
}
public override async Task OnDocumentStoreInitialized()
{
// in case plugin was loaded into already opened Map, read metadata from the current Map
if (!IsDocumentInit && MapView.Active != null)
{
IsDocumentInit = true;
LoadState();
await _eventAggregator.GetEvent<DocumentStoreChangedEvent>().PublishAsync(new object());
OnDocumentChanged();
}
}
@@ -76,7 +70,7 @@ public class ArcGISDocumentStore : DocumentModelStore
/// <summary>
/// On map view switch, this event trigger twice, first for outgoing view, second for incoming view.
/// </summary>
private async void OnMapViewChanged(ActiveMapViewChangedEventArgs args)
private void OnMapViewChanged(ActiveMapViewChangedEventArgs args)
{
if (args.IncomingView is null)
{
@@ -85,12 +79,12 @@ public class ArcGISDocumentStore : DocumentModelStore
IsDocumentInit = true;
LoadState();
await _eventAggregator.GetEvent<DocumentStoreChangedEvent>().PublishAsync(new object());
OnDocumentChanged();
}
protected override void HostAppSaveState(string modelCardState) =>
_threadContext
.RunOnWorker(() =>
QueuedTask
.Run(() =>
{
Map map = MapView.Active.Map;
// Read existing metadata - To prevent messing existing metadata. 🤞 Hope other add-in developers will do same :D
@@ -119,8 +113,8 @@ public class ArcGISDocumentStore : DocumentModelStore
.FireAndForget();
protected override void LoadState() =>
_threadContext
.RunOnWorker(() =>
QueuedTask
.Run(() =>
{
Map map = MapView.Active.Map;
var metadata = map.GetMetadata();
@@ -226,9 +226,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -236,8 +236,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui.webview": {
@@ -261,7 +261,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -294,40 +294,40 @@
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "[5.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.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
},
"net6.0-windows7.0/win-x64": {
@@ -259,9 +259,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -269,8 +269,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui.webview": {
@@ -294,7 +294,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -333,40 +333,40 @@
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "[5.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.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
}
}
@@ -259,9 +259,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -269,8 +269,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui.webview": {
@@ -294,7 +294,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -333,40 +333,40 @@
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "[5.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.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
}
}
@@ -259,9 +259,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -269,8 +269,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui.webview": {
@@ -295,7 +295,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -334,40 +334,40 @@
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "[5.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.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
}
}
@@ -215,9 +215,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -225,8 +225,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui.webview": {
@@ -251,7 +251,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -290,39 +290,39 @@
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
"Microsoft.Data.Sqlite": "[7.0.5]",
"Microsoft.Extensions.DependencyInjection.Abstractions": "[2.2.0]",
"Microsoft.Extensions.Logging": "[2.2.0]",
"Speckle.DoubleNumerics": "4.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
},
"net8.0-windows7.0/win-x64": {
@@ -4,7 +4,6 @@ using Speckle.Connectors.Autocad.HostApp.Extensions;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Models.Card;
using Speckle.Sdk;
@@ -22,6 +21,7 @@ public class AutocadBasicConnectorBinding : IBasicConnectorBinding
private readonly DocumentModelStore _store;
private readonly ISpeckleApplication _speckleApplication;
private readonly IThreadContext _threadContext;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
private readonly ILogger<AutocadBasicConnectorBinding> _logger;
public BasicConnectorBindingCommands Commands { get; }
@@ -32,8 +32,8 @@ public class AutocadBasicConnectorBinding : IBasicConnectorBinding
IAccountManager accountManager,
ISpeckleApplication speckleApplication,
ILogger<AutocadBasicConnectorBinding> logger,
IEventAggregator eventAggregator,
IThreadContext threadContext
IThreadContext threadContext,
ITopLevelExceptionHandler topLevelExceptionHandler
)
{
_store = store;
@@ -41,13 +41,16 @@ public class AutocadBasicConnectorBinding : IBasicConnectorBinding
_accountManager = accountManager;
_speckleApplication = speckleApplication;
Commands = new BasicConnectorBindingCommands(parent);
eventAggregator.GetEvent<DocumentStoreChangedEvent>().Subscribe(OnDocumentStoreChangedEvent);
_logger = logger;
_threadContext = threadContext;
_topLevelExceptionHandler = topLevelExceptionHandler;
_store.DocumentChanged += (_, _) =>
_topLevelExceptionHandler.FireAndForget(async () =>
{
await Commands.NotifyDocumentChanged();
});
}
private async Task OnDocumentStoreChangedEvent(object _) => await Commands.NotifyDocumentChanged();
public string GetConnectorVersion() => _speckleApplication.SpeckleVersion;
public string GetSourceApplicationName() => _speckleApplication.Slug;
@@ -2,6 +2,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Speckle.Connectors.Common.Cancellation;
using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Logging;
@@ -25,6 +26,7 @@ public sealed class AutocadReceiveBinding : IReceiveBinding
private readonly ILogger<AutocadReceiveBinding> _logger;
private readonly IAutocadConversionSettingsFactory _autocadConversionSettingsFactory;
private readonly ISpeckleApplication _speckleApplication;
private readonly IThreadContext _threadContext;
private ReceiveBindingUICommands Commands { get; }
@@ -36,7 +38,8 @@ public sealed class AutocadReceiveBinding : IReceiveBinding
IOperationProgressManager operationProgressManager,
ILogger<AutocadReceiveBinding> logger,
IAutocadConversionSettingsFactory autocadConversionSettingsFactory,
ISpeckleApplication speckleApplication
ISpeckleApplication speckleApplication,
IThreadContext threadContext
)
{
_store = store;
@@ -46,13 +49,17 @@ public sealed class AutocadReceiveBinding : IReceiveBinding
_logger = logger;
_autocadConversionSettingsFactory = autocadConversionSettingsFactory;
_speckleApplication = speckleApplication;
_threadContext = threadContext;
Parent = parent;
Commands = new ReceiveBindingUICommands(parent);
}
public void CancelReceive(string modelCardId) => _cancellationManager.CancelOperation(modelCardId);
public async Task Receive(string modelCardId)
public async Task Receive(string modelCardId) =>
await _threadContext.RunOnMainAsync(async () => await ReceiveInternal(modelCardId));
public async Task ReceiveInternal(string modelCardId)
{
using var scope = _serviceProvider.CreateScope();
scope
@@ -1,48 +1,42 @@
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Speckle.Connectors.Autocad.HostApp.Extensions;
using Speckle.Connectors.Autocad.Plugin;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
namespace Speckle.Connectors.Autocad.Bindings;
public class AutocadSelectionBinding : ISelectionBinding
{
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
private readonly IThreadContext _threadContext;
private const string SELECTION_EVENT = "setSelection";
private readonly IEventAggregator _eventAggregator;
private readonly HashSet<string> _visitedDocuments = new();
private readonly HashSet<Document> _visitedDocuments = new();
public string Name => "selectionBinding";
public IBrowserBridge Parent { get; }
public AutocadSelectionBinding(IBrowserBridge parent, IEventAggregator eventAggregator)
public AutocadSelectionBinding(
IBrowserBridge parent,
ITopLevelExceptionHandler topLevelExceptionHandler,
IThreadContext threadContext
)
{
_eventAggregator = eventAggregator;
_topLevelExceptionHandler = topLevelExceptionHandler;
_threadContext = threadContext;
Parent = parent;
// POC: Use here Context for doc. In converters it's OK but we are still lacking to use context into bindings.
// It is with the case of if binding created with already a document
// This is valid when user opens acad file directly double clicking
TryRegisterDocumentForSelection(Application.DocumentManager.MdiActiveDocument);
eventAggregator.GetEvent<DocumentActivatedEvent>().Subscribe(OnDocumentChanged);
eventAggregator.GetEvent<ImpliedSelectionChangedEvent>().Subscribe(OnSelectionChanged);
eventAggregator.GetEvent<DocumentToBeDestroyedEvent>().Subscribe(OnDocumentDestroyed);
Application.DocumentManager.DocumentActivated += (_, e) =>
_topLevelExceptionHandler.CatchUnhandled(() => OnDocumentChanged(e.Document));
}
private void OnDocumentDestroyed(DocumentCollectionEventArgs e)
{
if (!_visitedDocuments.Contains(e.Document.Name))
{
e.Document.ImpliedSelectionChanged -= DocumentOnImpliedSelectionChanged;
_visitedDocuments.Remove(e.Document.Name);
}
}
private void OnDocumentChanged(DocumentCollectionEventArgs e) => TryRegisterDocumentForSelection(e.Document);
private void OnDocumentChanged(Document? document) => TryRegisterDocumentForSelection(document);
private void TryRegisterDocumentForSelection(Document? document)
{
@@ -51,24 +45,21 @@ public class AutocadSelectionBinding : ISelectionBinding
return;
}
if (!_visitedDocuments.Contains(document.Name))
if (!_visitedDocuments.Contains(document))
{
document.ImpliedSelectionChanged += DocumentOnImpliedSelectionChanged;
document.ImpliedSelectionChanged += (_, _) =>
_topLevelExceptionHandler.FireAndForget(async () => await _threadContext.RunOnMainAsync(OnSelectionChanged));
_visitedDocuments.Add(document.Name);
_visitedDocuments.Add(document);
}
}
// ReSharper disable once AsyncVoidMethod
private async void DocumentOnImpliedSelectionChanged(object? sender, EventArgs e) =>
await _eventAggregator.GetEvent<ImpliedSelectionChangedEvent>().PublishAsync(e);
// NOTE: Autocad 2022 caused problems, so we need to refactor things a bit in here to always store
// selection info locally (and get it updated by the event, which we can control to run on the main thread).
// Ui requests to GetSelection() should just return this local copy that is kept up to date by the event handler.
private SelectionInfo _selectionInfo;
private async Task OnSelectionChanged(EventArgs _)
private async Task OnSelectionChanged()
{
_selectionInfo = GetSelectionInternal();
await Parent.Send(SELECTION_EVENT, _selectionInfo);
@@ -1,19 +1,16 @@
using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Speckle.Connectors.Autocad.HostApp.Extensions;
using Speckle.Connectors.Autocad.Operations.Send;
using Speckle.Connectors.Autocad.Plugin;
using Speckle.Connectors.Common.Caching;
using Speckle.Connectors.Common.Cancellation;
using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.DUI.Exceptions;
using Speckle.Connectors.DUI.Logging;
using Speckle.Connectors.DUI.Models;
@@ -42,7 +39,8 @@ public abstract class AutocadSendBaseBinding : ISendBinding
private readonly ILogger<AutocadSendBinding> _logger;
private readonly ISpeckleApplication _speckleApplication;
private readonly IThreadContext _threadContext;
private readonly IEventAggregator _eventAggregator;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
private readonly IAppIdleManager _idleManager;
/// <summary>
/// Used internally to aggregate the changed objects' id. Note we're using a concurrent dictionary here as the expiry check method is not thread safe, and this was causing problems. See:
@@ -63,7 +61,8 @@ public abstract class AutocadSendBaseBinding : ISendBinding
ILogger<AutocadSendBinding> logger,
ISpeckleApplication speckleApplication,
IThreadContext threadContext,
IEventAggregator eventAggregator
ITopLevelExceptionHandler topLevelExceptionHandler,
IAppIdleManager idleManager
)
{
_store = store;
@@ -75,46 +74,29 @@ public abstract class AutocadSendBaseBinding : ISendBinding
_logger = logger;
_speckleApplication = speckleApplication;
_threadContext = threadContext;
_eventAggregator = eventAggregator;
_topLevelExceptionHandler = topLevelExceptionHandler;
_idleManager = idleManager;
Parent = parent;
Commands = new SendBindingUICommands(parent);
Application.DocumentManager.DocumentActivated += (_, args) =>
_topLevelExceptionHandler.CatchUnhandled(() => SubscribeToObjectChanges(args.Document));
if (Application.DocumentManager.CurrentDocument != null)
{
// catches the case when autocad just opens up with a blank new doc
TryRegisterSubscribeToObjectChanges(Application.DocumentManager.CurrentDocument);
SubscribeToObjectChanges(Application.DocumentManager.CurrentDocument);
}
// Since ids of the objects generates from same seed, we should clear the cache always whenever doc swapped.
eventAggregator.GetEvent<DocumentActivatedEvent>().Subscribe(SubscribeToObjectChanges);
eventAggregator.GetEvent<DocumentStoreChangedEvent>().Subscribe(OnDocumentStoreChangedEvent);
eventAggregator.GetEvent<DocumentToBeDestroyedEvent>().Subscribe(OnDocumentDestroyed);
eventAggregator.GetEvent<ObjectAppendedEvent>().Subscribe(OnObjectAppended);
eventAggregator.GetEvent<ObjectErasedEvent>().Subscribe(ObjectErased);
eventAggregator.GetEvent<ObjectModifiedEvent>().Subscribe(ObjectModified);
}
private void OnDocumentDestroyed(DocumentCollectionEventArgs args)
{
Document doc = args.Document;
if (!_docSubsTracker.Contains(doc.Name))
_store.DocumentChanged += (_, _) =>
{
doc.Database.ObjectAppended -= DatabaseOnObjectAppended;
doc.Database.ObjectErased -= DatabaseOnObjectErased;
doc.Database.ObjectModified -= DatabaseObjectModified;
_docSubsTracker.Remove(doc.Name);
}
_sendConversionCache.ClearCache();
};
}
private void OnDocumentStoreChangedEvent(object _) => _sendConversionCache.ClearCache();
private readonly List<string> _docSubsTracker = new();
private void SubscribeToObjectChanges(DocumentCollectionEventArgs e) =>
TryRegisterSubscribeToObjectChanges(e.Document);
private void TryRegisterSubscribeToObjectChanges(Document? doc)
private void SubscribeToObjectChanges(Document doc)
{
if (doc == null || doc.Database == null || _docSubsTracker.Contains(doc.Name))
{
@@ -122,33 +104,21 @@ public abstract class AutocadSendBaseBinding : ISendBinding
}
_docSubsTracker.Add(doc.Name);
doc.Database.ObjectAppended += DatabaseOnObjectAppended;
doc.Database.ObjectErased += DatabaseOnObjectErased;
doc.Database.ObjectModified += DatabaseObjectModified;
doc.Database.ObjectAppended += (_, e) => OnObjectChanged(e.DBObject);
doc.Database.ObjectErased += (_, e) => OnObjectChanged(e.DBObject);
doc.Database.ObjectModified += (_, e) => OnObjectChanged(e.DBObject);
}
private async void DatabaseOnObjectAppended(object sender, ObjectEventArgs e) =>
await _eventAggregator.GetEvent<ObjectAppendedEvent>().PublishAsync(e);
private async void DatabaseOnObjectErased(object sender, ObjectErasedEventArgs e) =>
await _eventAggregator.GetEvent<ObjectErasedEvent>().PublishAsync(e);
private async void DatabaseObjectModified(object sender, ObjectEventArgs e) =>
await _eventAggregator.GetEvent<ObjectModifiedEvent>().PublishAsync(e);
private void OnObjectAppended(ObjectEventArgs e) => OnChangeChangedObjectIds(e.DBObject);
private void ObjectErased(ObjectErasedEventArgs e) => OnChangeChangedObjectIds(e.DBObject);
private void ObjectModified(ObjectEventArgs e) => OnChangeChangedObjectIds(e.DBObject);
private void OnObjectChanged(DBObject dbObject) =>
_topLevelExceptionHandler.CatchUnhandled(() => OnChangeChangedObjectIds(dbObject));
private void OnChangeChangedObjectIds(DBObject dBObject)
{
ChangedObjectIds[dBObject.GetSpeckleApplicationId()] = 1;
_eventAggregator.GetEvent<IdleEvent>().OneTimeSubscribe(nameof(AutocadSendBinding), RunExpirationChecks);
_idleManager.SubscribeToIdle(nameof(AutocadSendBinding), async () => await RunExpirationChecks());
}
private async Task RunExpirationChecks(object _)
private async Task RunExpirationChecks()
{
var senders = _store.GetSenders();
string[] objectIdsList = ChangedObjectIds.Keys.ToArray();
@@ -175,7 +145,7 @@ public abstract class AutocadSendBaseBinding : ISendBinding
public List<ICardSetting> GetSendSettings() => [];
public async Task Send(string modelCardId) =>
await _threadContext.RunOnWorkerAsync(async () => await SendInternal(modelCardId));
await _threadContext.RunOnMainAsync(async () => await SendInternal(modelCardId));
protected abstract void InitializeSettings(IServiceProvider serviceProvider);
@@ -5,7 +5,6 @@ using Speckle.Connectors.Common.Cancellation;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Models.Card.SendFilter;
using Speckle.Converters.Autocad;
@@ -30,7 +29,8 @@ public sealed class AutocadSendBinding : AutocadSendBaseBinding
IAutocadConversionSettingsFactory autocadConversionSettingsFactory,
ISpeckleApplication speckleApplication,
IThreadContext threadContext,
IEventAggregator eventAggregator
ITopLevelExceptionHandler topLevelExceptionHandler,
IAppIdleManager appIdleManager
)
: base(
store,
@@ -43,7 +43,8 @@ public sealed class AutocadSendBinding : AutocadSendBaseBinding
logger,
speckleApplication,
threadContext,
eventAggregator
topLevelExceptionHandler,
appIdleManager
)
{
_autocadConversionSettingsFactory = autocadConversionSettingsFactory;
@@ -13,6 +13,7 @@ using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Models.Card.SendFilter;
using Speckle.Connectors.DUI.WebView;
using Speckle.Sdk.Models.GraphTraversal;
@@ -48,6 +49,8 @@ public static class SharedRegistration
serviceCollection.AddScoped<AutocadMaterialUnpacker>();
serviceCollection.AddScoped<IAutocadMaterialBaker, AutocadMaterialBaker>();
serviceCollection.AddSingleton<IAppIdleManager, AutocadIdleManager>();
// operation progress manager
serviceCollection.AddSingleton<IOperationProgressManager, OperationProgressManager>();
@@ -1,6 +1,4 @@
using Autodesk.AutoCAD.ApplicationServices;
using Speckle.Connectors.Autocad.Plugin;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Utils;
@@ -11,28 +9,19 @@ public class AutocadDocumentStore : DocumentModelStore
private const string NULL_DOCUMENT_NAME = "Null Doc";
private string _previousDocName;
private readonly AutocadDocumentManager _autocadDocumentManager;
private readonly IEventAggregator _eventAggregator;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
public AutocadDocumentStore(
IJsonSerializer jsonSerializer,
AutocadDocumentManager autocadDocumentManager,
IEventAggregator eventAggregator
ITopLevelExceptionHandler topLevelExceptionHandler
)
: base(jsonSerializer)
{
_autocadDocumentManager = autocadDocumentManager;
_eventAggregator = eventAggregator;
_topLevelExceptionHandler = topLevelExceptionHandler;
_previousDocName = NULL_DOCUMENT_NAME;
eventAggregator.GetEvent<DocumentActivatedEvent>().Subscribe(DocChanged);
// since below event triggered as secondary, it breaks the logic in OnDocChangeInternal function, leaving it here for now.
// Autodesk.AutoCAD.ApplicationServices.Application.DocumentWindowCollection.DocumentWindowActivated += (_, args) =>
// OnDocChangeInternal((Document)args.DocumentWindow.Document);
}
public override async Task OnDocumentStoreInitialized()
{
// POC: Will be addressed to move it into AutocadContext!
if (Application.DocumentManager.MdiActiveDocument != null)
{
@@ -40,13 +29,18 @@ public class AutocadDocumentStore : DocumentModelStore
// POC: this logic might go when we have document management in context
// It is with the case of if binding created with already a document
// This is valid when user opens acad file directly double clicking
await TryDocChanged(Application.DocumentManager.MdiActiveDocument);
OnDocChangeInternal(Application.DocumentManager.MdiActiveDocument);
}
Application.DocumentManager.DocumentActivated += (_, e) =>
topLevelExceptionHandler.CatchUnhandled(() => OnDocChangeInternal(e.Document));
// since below event triggered as secondary, it breaks the logic in OnDocChangeInternal function, leaving it here for now.
// Autodesk.AutoCAD.ApplicationServices.Application.DocumentWindowCollection.DocumentWindowActivated += (_, args) =>
// OnDocChangeInternal((Document)args.DocumentWindow.Document);
}
private async Task DocChanged(DocumentCollectionEventArgs e) => await TryDocChanged(e.Document);
private async Task TryDocChanged(Document? doc)
private void OnDocChangeInternal(Document? doc)
{
var currentDocName = doc != null ? doc.Name : NULL_DOCUMENT_NAME;
if (_previousDocName == currentDocName)
@@ -56,7 +50,7 @@ public class AutocadDocumentStore : DocumentModelStore
_previousDocName = currentDocName;
LoadState();
await _eventAggregator.GetEvent<DocumentStoreChangedEvent>().PublishAsync(new object());
OnDocumentChanged();
}
protected override void LoadState()
@@ -0,0 +1,19 @@
using Speckle.Connectors.DUI.Bridge;
using Speckle.InterfaceGenerator;
namespace Speckle.Connectors.Autocad.HostApp;
public partial interface IAutocadIdleManager : IAppIdleManager;
[GenerateAutoInterface]
public sealed class AutocadIdleManager(IIdleCallManager idleCallManager)
: AppIdleManager(idleCallManager),
IAutocadIdleManager
{
private readonly IIdleCallManager _idleCallManager = idleCallManager;
protected override void AddEvent() => Application.Idle += AutocadAppOnIdle;
private void AutocadAppOnIdle(object? sender, EventArgs e) =>
_idleCallManager.AppOnIdle(() => Application.Idle -= AutocadAppOnIdle);
}
@@ -31,7 +31,7 @@ public class AutocadHostObjectBuilder(
RootObjectUnpacker rootObjectUnpacker
) : IHostObjectBuilder
{
public HostObjectBuilderResult Build(
public Task<HostObjectBuilderResult> Build(
Base rootObject,
string projectName,
string modelName,
@@ -139,7 +139,7 @@ public class AutocadHostObjectBuilder(
results.UnionWith(groupResults);
}
return new HostObjectBuilderResult(bakedObjectIds, results);
return Task.FromResult(new HostObjectBuilderResult(bakedObjectIds, results));
}
private void PreReceiveDeepClean(string baseLayerPrefix)
@@ -160,15 +160,21 @@ public class AutocadHostObjectBuilder(
var converted = converter.Convert(obj);
// 2: handle result
if (converted is Entity entity)
switch (converted)
{
var bakedEntity = BakeObject(entity, obj, layerName);
convertedEntities.Add(bakedEntity);
}
else if (converted is List<(Entity, Base)> fallbackConversionResult)
{
var bakedFallbackEntities = BakeObjectsAsGroup(fallbackConversionResult, obj, layerName, baseLayerNamePrefix);
convertedEntities.UnionWith(bakedFallbackEntities);
case Entity entity:
var bakedEntity = BakeObject(entity, obj, layerName);
convertedEntities.Add(bakedEntity);
break;
case List<(Entity, Base)> listConversionResult: // this is from fallback conversion for brep/brepx/subdx/extrusionx
var bakedFallbackEntities = BakeObjectsAsGroup(listConversionResult, obj, layerName, baseLayerNamePrefix);
convertedEntities.UnionWith(bakedFallbackEntities);
break;
default:
// TODO: capture defualt case with report object here? Same as in Rhino
break;
}
tr.Commit();
@@ -208,6 +214,11 @@ public class AutocadHostObjectBuilder(
entities.Add(conversionResult);
}
if (entities.Count <= 1) // return if empty list or only one, because we don't want to create empty or single item groups.
{
return entities;
}
var tr = Application.DocumentManager.CurrentDocument.Database.TransactionManager.TopTransaction;
var groupDictionary = (DBDictionary)
tr.GetObject(Application.DocumentManager.CurrentDocument.Database.GroupDictionaryId, OpenMode.ForWrite);
@@ -16,7 +16,7 @@ using Speckle.Sdk.Models.Instances;
namespace Speckle.Connectors.Autocad.Operations.Send;
public abstract class AutocadRootObjectBaseBuilder : RootObjectBuilderBase<AutocadRootObject>
public abstract class AutocadRootObjectBaseBuilder : IRootObjectBuilder<AutocadRootObject>
{
private readonly IRootToSpeckleConverter _converter;
private readonly string[] _documentPathSeparator = ["\\"];
@@ -58,7 +58,7 @@ public abstract class AutocadRootObjectBaseBuilder : RootObjectBuilderBase<Autoc
proxy classes yet. So I'm supressing this one now!!!
"""
)]
public override RootObjectBuilderResult Build(
public Task<RootObjectBuilderResult> Build(
IReadOnlyList<AutocadRootObject> objects,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
@@ -133,7 +133,7 @@ public abstract class AutocadRootObjectBaseBuilder : RootObjectBuilderBase<Autoc
// add any additional properties (most likely from verticals)
AddAdditionalProxiesToRoot(root);
return new RootObjectBuilderResult(root, results);
return Task.FromResult(new RootObjectBuilderResult(root, results));
}
}
@@ -4,7 +4,6 @@ using Autodesk.AutoCAD.Windows;
using Microsoft.Extensions.DependencyInjection;
using Speckle.Connectors.Common;
using Speckle.Connectors.DUI;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.DUI.WebView;
#if AUTOCAD
using Speckle.Connectors.Autocad.DependencyInjection;
@@ -49,7 +48,6 @@ public class AutocadCommand
services.AddCivil3dConverters();
#endif
Container = services.BuildServiceProvider();
AutocadEvents.Register(Container.GetRequiredService<IEventAggregator>());
Container.UseDUI();
var panelWebView = Container.GetRequiredService<DUI3ControlWebView>();
@@ -1,38 +0,0 @@
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
namespace Speckle.Connectors.Autocad.Plugin;
public class DocumentActivatedEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<DocumentCollectionEventArgs>(threadContext, exceptionHandler);
public class DocumentToBeDestroyedEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<DocumentCollectionEventArgs>(threadContext, exceptionHandler);
public class ImpliedSelectionChangedEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<EventArgs>(threadContext, exceptionHandler);
public class ObjectAppendedEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<ObjectEventArgs>(threadContext, exceptionHandler);
public class ObjectErasedEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<ObjectErasedEventArgs>(threadContext, exceptionHandler);
public class ObjectModifiedEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<ObjectEventArgs>(threadContext, exceptionHandler);
public static class AutocadEvents
{
public static void Register(IEventAggregator eventAggregator)
{
Application.Idle += async (_, e) => await eventAggregator.GetEvent<IdleEvent>().PublishAsync(e);
Application.DocumentManager.DocumentActivated += async (_, e) =>
await eventAggregator.GetEvent<DocumentActivatedEvent>().PublishAsync(e);
Application.DocumentManager.DocumentToBeDestroyed += async (_, e) =>
await eventAggregator.GetEvent<DocumentToBeDestroyedEvent>().PublishAsync(e);
}
}
@@ -21,6 +21,7 @@
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadColorUnpacker.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadGroupBaker.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadGroupUnpacker.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadIdleManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadInstanceBaker.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadInstanceUnpacker.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\AutocadLayerBaker.cs" />
@@ -40,7 +41,6 @@
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\AutocadRootObject.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\AutocadRootObjectBaseBuilder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\AutocadRootObjectBuilder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\AutocadEvents.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\AutocadRibbon.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\AutocadExtensionApplication.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\AutocadCommand.cs" />
@@ -268,9 +268,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -278,8 +278,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui.webview": {
@@ -304,7 +304,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -343,40 +343,40 @@
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "[5.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.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
}
}
@@ -268,9 +268,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -278,8 +278,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui.webview": {
@@ -304,7 +304,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -343,40 +343,40 @@
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "[5.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.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
}
}
@@ -268,9 +268,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -278,8 +278,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui.webview": {
@@ -304,7 +304,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -343,40 +343,40 @@
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "[5.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.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
}
}
@@ -224,9 +224,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -234,8 +234,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui.webview": {
@@ -261,7 +261,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"Microsoft.Extensions.DependencyInjection": {
@@ -300,39 +300,39 @@
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
"Microsoft.Data.Sqlite": "[7.0.5]",
"Microsoft.Extensions.DependencyInjection.Abstractions": "[2.2.0]",
"Microsoft.Extensions.Logging": "[2.2.0]",
"Speckle.DoubleNumerics": "4.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
},
"net8.0-windows7.0/win-x64": {
@@ -6,7 +6,6 @@ using Speckle.Connectors.Common.Cancellation;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Models.Card.SendFilter;
using Speckle.Converters.Autocad;
@@ -34,7 +33,8 @@ public sealed class Civil3dSendBinding : AutocadSendBaseBinding
IAutocadConversionSettingsFactory autocadConversionSettingsFactory,
ISpeckleApplication speckleApplication,
IThreadContext threadContext,
IEventAggregator eventAggregator
ITopLevelExceptionHandler topLevelExceptionHandler,
IAppIdleManager appIdleManager
)
: base(
store,
@@ -47,7 +47,8 @@ public sealed class Civil3dSendBinding : AutocadSendBaseBinding
logger,
speckleApplication,
threadContext,
eventAggregator
topLevelExceptionHandler,
appIdleManager
)
{
_civil3dConversionSettingsFactory = civil3dConversionSettingsFactory;
@@ -6,7 +6,6 @@ using Speckle.Connectors.Civil3dShared.Bindings;
using Speckle.Connectors.Civil3dShared.Operations.Send;
using Speckle.Connectors.Common.Builders;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Converters.Civil3dShared.Helpers;
using Speckle.Converters.Civil3dShared.ToSpeckle;
using Speckle.Sdk;
@@ -28,7 +27,5 @@ public static class Civil3dConnectorModule
// additional classes
serviceCollection.AddScoped<PropertySetDefinitionHandler>();
serviceCollection.AddScoped<CatchmentGroupHandler>();
serviceCollection.AddScoped<PipeNetworkHandler>();
}
}
@@ -4,7 +4,6 @@ using Speckle.Connectors.Autocad.HostApp;
using Speckle.Connectors.Autocad.Operations.Send;
using Speckle.Connectors.Common.Caching;
using Speckle.Connectors.Common.Operations;
using Speckle.Converters.Civil3dShared.Helpers;
using Speckle.Converters.Civil3dShared.ToSpeckle;
using Speckle.Converters.Common;
using Speckle.Sdk.Logging;
@@ -16,14 +15,10 @@ public sealed class Civil3dRootObjectBuilder : AutocadRootObjectBaseBuilder
{
private readonly AutocadLayerUnpacker _layerUnpacker;
private readonly PropertySetDefinitionHandler _propertySetDefinitionHandler;
private readonly CatchmentGroupHandler _catchmentGroupHandler;
private readonly PipeNetworkHandler _pipeNetworkHandler;
public Civil3dRootObjectBuilder(
AutocadLayerUnpacker layerUnpacker,
PropertySetDefinitionHandler propertySetDefinitionHandler,
CatchmentGroupHandler catchmentGroupHandler,
PipeNetworkHandler pipeNetworkHandler,
IRootToSpeckleConverter converter,
ISendConversionCache sendConversionCache,
AutocadInstanceUnpacker instanceObjectManager,
@@ -46,8 +41,6 @@ public sealed class Civil3dRootObjectBuilder : AutocadRootObjectBaseBuilder
{
_layerUnpacker = layerUnpacker;
_propertySetDefinitionHandler = propertySetDefinitionHandler;
_catchmentGroupHandler = catchmentGroupHandler;
_pipeNetworkHandler = pipeNetworkHandler;
}
public override (Collection, LayerTableRecord?) CreateObjectCollection(Entity entity, Transaction tr)
@@ -61,7 +54,5 @@ public sealed class Civil3dRootObjectBuilder : AutocadRootObjectBaseBuilder
public override void AddAdditionalProxiesToRoot(Collection rootObject)
{
rootObject[ProxyKeys.PROPERTYSET_DEFINITIONS] = _propertySetDefinitionHandler.Definitions;
rootObject["catchmentGroupProxies"] = _catchmentGroupHandler.CatchmentGroupProxiesCache.Values.ToList();
rootObject["pipeNetworkProxies"] = _pipeNetworkHandler.PipeNetworkProxiesCache.Values.ToList();
}
}
@@ -1,6 +1,6 @@
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Models.Card;
using Speckle.Sdk;
@@ -11,7 +11,8 @@ public class CsiSharedBasicConnectorBinding : IBasicConnectorBinding
{
private readonly ISpeckleApplication _speckleApplication;
private readonly DocumentModelStore _store;
private readonly IEventAggregator _eventAggregator;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
private readonly IThreadContext _threadContext;
public string Name => "baseBinding";
public IBrowserBridge Parent { get; }
public BasicConnectorBindingCommands Commands { get; }
@@ -20,20 +21,28 @@ public class CsiSharedBasicConnectorBinding : IBasicConnectorBinding
IBrowserBridge parent,
ISpeckleApplication speckleApplication,
DocumentModelStore store,
IEventAggregator eventAggregator
ITopLevelExceptionHandler topLevelExceptionHandler,
IThreadContext threadContext
)
{
_threadContext = threadContext;
Parent = parent;
_speckleApplication = speckleApplication;
_store = store;
_topLevelExceptionHandler = topLevelExceptionHandler;
Commands = new BasicConnectorBindingCommands(Parent);
_eventAggregator = eventAggregator;
_eventAggregator.GetEvent<DocumentStoreChangedEvent>().Subscribe(OnDocumentStoreChangedEvent);
_store.DocumentChanged += (_, _) =>
_topLevelExceptionHandler.FireAndForget(async () =>
{
// enforce main thread
await _threadContext.RunOnMainAsync(async () =>
{
await Commands.NotifyDocumentChanged();
});
});
}
private async Task OnDocumentStoreChangedEvent(object _) => await Commands.NotifyDocumentChanged();
public string GetConnectorVersion() => _speckleApplication.SpeckleVersion;
public string GetSourceApplicationName() => _speckleApplication.Slug;
@@ -44,11 +53,17 @@ public class CsiSharedBasicConnectorBinding : IBasicConnectorBinding
public DocumentModelStore GetDocumentState() => _store;
public void AddModel(ModelCard model) => _store.AddModel(model);
/// <remarks>Operations must run on the main thread for ETABS and SAP 2000</remarks>
public void AddModel(ModelCard model) =>
_topLevelExceptionHandler.CatchUnhandled(() => _threadContext.RunOnThread(() => _store.AddModel(model), true));
public void UpdateModel(ModelCard model) => _store.UpdateModel(model);
/// <remarks>Operations must run on the main thread for ETABS and SAP 2000</remarks>
public void UpdateModel(ModelCard model) =>
_topLevelExceptionHandler.CatchUnhandled(() => _threadContext.RunOnThread(() => _store.UpdateModel(model), true));
public void RemoveModel(ModelCard model) => _store.RemoveModel(model);
/// <remarks>Operations must run on the main thread for ETABS and SAP 2000</remarks>
public void RemoveModel(ModelCard model) =>
_topLevelExceptionHandler.CatchUnhandled(() => _threadContext.RunOnThread(() => _store.RemoveModel(model), true));
public Task HighlightModel(string modelCardId) => Task.CompletedTask;
@@ -1,17 +1,21 @@
using Speckle.Connectors.CSiShared.Events;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.CSiShared.HostApp;
using Speckle.Connectors.CSiShared.Utils;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Converters.CSiShared.Utils;
using Timer = System.Timers.Timer;
namespace Speckle.Connectors.CSiShared.Bindings;
public sealed class CsiSharedSelectionBinding : ISelectionBinding
public class CsiSharedSelectionBinding : ISelectionBinding, IDisposable
{
private bool _disposed;
private readonly Timer _selectionTimer;
private readonly ICsiApplicationService _csiApplicationService;
private readonly IThreadContext _threadContext;
private HashSet<string> _lastSelection = new();
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
public IBrowserBridge Parent { get; }
public string Name => "selectionBinding";
@@ -19,27 +23,58 @@ public sealed class CsiSharedSelectionBinding : ISelectionBinding
public CsiSharedSelectionBinding(
IBrowserBridge parent,
ICsiApplicationService csiApplicationService,
IEventAggregator eventAggregator
ITopLevelExceptionHandler topLevelExceptionHandler,
IThreadContext threadContext
)
{
_threadContext = threadContext;
Parent = parent;
_csiApplicationService = csiApplicationService;
_topLevelExceptionHandler = topLevelExceptionHandler;
eventAggregator.GetEvent<SelectionBindingEvent>().SubscribePeriodic(TimeSpan.FromSeconds(1), CheckSelectionChanged);
_selectionTimer = new Timer(1000);
_selectionTimer.Elapsed += (_, _) =>
_topLevelExceptionHandler.CatchUnhandled(() => _threadContext.RunOnMain(CheckSelectionChanged));
_selectionTimer.Start();
}
private void CheckSelectionChanged(object _)
private void CheckSelectionChanged()
{
// timer callbacks are on a background thread, but CSI API calls must be on main thread
var currentSelection = GetSelection();
var currentIds = new HashSet<string>(currentSelection.SelectedObjectIds);
if (!_lastSelection.SetEquals(currentIds))
{
_lastSelection = currentIds;
Parent.Send(SelectionBindingEvents.SET_SELECTION, currentSelection);
// ensure UI updates also run on main thread
_threadContext.RunOnMain(
() =>
_topLevelExceptionHandler.CatchUnhandled(
() => Parent.Send(SelectionBindingEvents.SET_SELECTION, currentSelection)
)
);
}
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_selectionTimer?.Dispose();
}
_disposed = true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Gets the selection and creates an encoded ID (objectType and objectName).
/// </summary>
@@ -56,22 +91,18 @@ public sealed class CsiSharedSelectionBinding : ISelectionBinding
var encodedIds = new List<string>(numberItems);
var typeCounts = new Dictionary<string, int>();
for (int i = 0; i < numberItems; i++)
{
var typeKey = (ModelObjectType)objectType[i];
var typeName = typeKey.ToString();
encodedIds.Add(ObjectIdentifier.Encode(objectType[i], objectName[i]));
typeCounts[typeName] = (typeCounts.TryGetValue(typeName, out var count) ? count : 0) + 1; // NOTE: Cross-framework compatibility (net 48 and net8)
}
var summary =
encodedIds.Count == 0
? "No objects selected."
: $"{encodedIds.Count} objects ({string.Join(", ",
typeCounts.Select(kv => $"{kv.Value} {kv.Key}"))})";
return new SelectionInfo(encodedIds, summary);
}
}
@@ -1,8 +0,0 @@
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
namespace Speckle.Connectors.CSiShared.Events;
public class ModelChangedEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: PeriodicThreadedEvent(threadContext, exceptionHandler);
@@ -1,8 +0,0 @@
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
namespace Speckle.Connectors.CSiShared.Events;
public class SelectionBindingEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: PeriodicThreadedEvent(threadContext, exceptionHandler);
@@ -1,22 +1,26 @@
using System.IO;
using Microsoft.Extensions.Logging;
using Speckle.Connectors.CSiShared.Events;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Utils;
using Speckle.Sdk;
using Speckle.Sdk.Helpers;
using Speckle.Sdk.Logging;
using Timer = System.Timers.Timer;
namespace Speckle.Connectors.CSiShared.HostApp;
public class CsiDocumentModelStore : DocumentModelStore
public class CsiDocumentModelStore : DocumentModelStore, IDisposable
{
private readonly ISpeckleApplication _speckleApplication;
private readonly ILogger<CsiDocumentModelStore> _logger;
private readonly ICsiApplicationService _csiApplicationService;
private readonly IEventAggregator _eventAggregator;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
private readonly IThreadContext _threadContext;
private readonly Timer _modelCheckTimer;
private string _lastModelFilename = string.Empty;
private bool _disposed;
private string HostAppUserDataPath { get; set; }
private string DocumentStateFile { get; set; }
private string ModelPathHash { get; set; }
@@ -26,18 +30,27 @@ public class CsiDocumentModelStore : DocumentModelStore
ISpeckleApplication speckleApplication,
ILogger<CsiDocumentModelStore> logger,
ICsiApplicationService csiApplicationService,
IEventAggregator eventAggregator
ITopLevelExceptionHandler topLevelExceptionHandler,
IThreadContext threadContext
)
: base(jsonSerializer)
{
_threadContext = threadContext;
_speckleApplication = speckleApplication;
_logger = logger;
_csiApplicationService = csiApplicationService;
_eventAggregator = eventAggregator;
eventAggregator.GetEvent<ModelChangedEvent>().SubscribePeriodic(TimeSpan.FromSeconds(1), CheckModelChanges);
_topLevelExceptionHandler = topLevelExceptionHandler;
// initialize timer to check for model changes
_modelCheckTimer = new Timer(1000);
// timer runs on background thread but model checks must be on main thread
_modelCheckTimer.Elapsed += (_, _) =>
_topLevelExceptionHandler.CatchUnhandled(() => _threadContext.RunOnMain(CheckModelChanges));
_modelCheckTimer.Start();
}
private async Task CheckModelChanges(object _)
private void CheckModelChanges()
{
string currentFilename = _csiApplicationService.SapModel.GetModelFilename();
@@ -49,8 +62,7 @@ public class CsiDocumentModelStore : DocumentModelStore
_lastModelFilename = currentFilename;
SetPaths();
LoadState();
await _eventAggregator.GetEvent<DocumentStoreChangedEvent>().PublishAsync(new object());
OnDocumentChanged();
}
public override Task OnDocumentStoreInitialized()
@@ -120,4 +132,25 @@ public class CsiDocumentModelStore : DocumentModelStore
ClearAndSave();
}
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
if (disposing)
{
_modelCheckTimer.Dispose();
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
@@ -68,7 +68,7 @@ public class CsiRootObjectBuilder : IRootObjectBuilder<ICsiWrapper>
/// 2. Converts each object with caching and progress tracking
/// 3. Creates proxies for materials and sections
/// </remarks>
public async Task<RootObjectBuilderResult> BuildAsync(
public async Task<RootObjectBuilderResult> Build(
IReadOnlyList<ICsiWrapper> csiObjects,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
@@ -17,8 +17,6 @@
<Compile Include="$(MSBuildThisFileDirectory)Bindings\CsiSharedBasicConnectorBinding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bindings\CsiSharedSelectionBinding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bindings\CsiSharedSendBinding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Events\ModelChangedEvent.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Events\SelectionBindingEvent.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Filters\CsiSharedSelectionFilter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\MaterialUnpacker.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\CsiSendCollectionManager.cs" />
@@ -259,9 +259,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -269,8 +269,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui.webview": {
@@ -287,7 +287,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"speckle.converters.etabs21": {
@@ -332,40 +332,40 @@
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "[5.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.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
}
}
@@ -215,9 +215,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -225,8 +225,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui.webview": {
@@ -243,7 +243,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"speckle.converters.etabs22": {
@@ -288,39 +288,39 @@
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
"Microsoft.Data.Sqlite": "[7.0.5]",
"Microsoft.Extensions.DependencyInjection.Abstractions": "[2.2.0]",
"Microsoft.Extensions.Logging": "[2.2.0]",
"Speckle.DoubleNumerics": "4.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
}
}
@@ -259,9 +259,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -269,8 +269,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui.webview": {
@@ -287,7 +287,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"speckle.converters.navisworks2020": {
@@ -334,40 +334,40 @@
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "[5.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.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
},
".NETFramework,Version=v4.8/win-x64": {
@@ -259,9 +259,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -269,8 +269,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui.webview": {
@@ -287,7 +287,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"speckle.converters.navisworks2021": {
@@ -334,40 +334,40 @@
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "[5.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.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
},
".NETFramework,Version=v4.8/win-x64": {
@@ -259,9 +259,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -269,8 +269,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui.webview": {
@@ -287,7 +287,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"speckle.converters.navisworks2022": {
@@ -334,40 +334,40 @@
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "[5.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.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
},
".NETFramework,Version=v4.8/win-x64": {
@@ -259,9 +259,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -269,8 +269,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui.webview": {
@@ -287,7 +287,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"speckle.converters.navisworks2023": {
@@ -334,40 +334,40 @@
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "[5.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.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
},
".NETFramework,Version=v4.8/win-x64": {
@@ -259,9 +259,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -269,8 +269,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui.webview": {
@@ -287,7 +287,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"speckle.converters.navisworks2024": {
@@ -334,40 +334,40 @@
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "[5.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.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
},
".NETFramework,Version=v4.8/win-x64": {
@@ -265,9 +265,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -275,8 +275,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui.webview": {
@@ -293,7 +293,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"speckle.converters.navisworks2025": {
@@ -334,40 +334,40 @@
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "[5.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.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
},
".NETFramework,Version=v4.8/win-x64": {
@@ -1,35 +1,34 @@
using Speckle.Connector.Navisworks.Services;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
namespace Speckle.Connector.Navisworks.Bindings;
public class NavisworksSelectionBinding : ISelectionBinding
{
private readonly IAppIdleManager _idleManager;
private readonly IElementSelectionService _selectionService;
private readonly IEventAggregator _eventAggregator;
private const string SELECTION_EVENT = "setSelection";
public string Name { get; } = "selectionBinding";
public IBrowserBridge Parent { get; }
public NavisworksSelectionBinding(
IAppIdleManager idleManager,
IBrowserBridge parent,
IElementSelectionService selectionService,
IEventAggregator eventAggregator
IElementSelectionService selectionService
)
{
_idleManager = idleManager;
_selectionService = selectionService;
_eventAggregator = eventAggregator;
Parent = parent;
eventAggregator.GetEvent<SelectionChangedEvent>().Subscribe(OnSelectionChange);
NavisworksApp.ActiveDocument.CurrentSelection.Changed += OnSelectionChange;
}
private void OnSelectionChange(object _) =>
_eventAggregator.GetEvent<IdleEvent>().OneTimeSubscribe(nameof(NavisworksSelectionBinding), UpdateSelectionAsync);
private void OnSelectionChange(object? o, EventArgs eventArgs) =>
_idleManager.SubscribeToIdle(nameof(NavisworksSelectionBinding), async () => await UpdateSelectionAsync());
private async Task UpdateSelectionAsync(object _)
private async Task UpdateSelectionAsync()
{
var selInfo = GetSelection();
await Parent.Send(SELECTION_EVENT, selInfo);
@@ -4,6 +4,7 @@ using Speckle.Connector.Navisworks.Operations.Send.Settings;
using Speckle.Connector.Navisworks.Services;
using Speckle.Connectors.Common.Cancellation;
using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Exceptions;
@@ -38,6 +39,7 @@ public class NavisworksSendBinding : ISendBinding
private readonly INavisworksConversionSettingsFactory _conversionSettingsFactory;
private readonly ToSpeckleSettingsManagerNavisworks _toSpeckleSettingsManagerNavisworks;
private readonly IElementSelectionService _selectionService;
private readonly IThreadContext _threadContext;
public NavisworksSendBinding(
DocumentModelStore store,
@@ -51,7 +53,8 @@ public class NavisworksSendBinding : ISendBinding
ISdkActivityFactory activityFactory,
INavisworksConversionSettingsFactory conversionSettingsFactory,
ToSpeckleSettingsManagerNavisworks toSpeckleSettingsManagerNavisworks,
IElementSelectionService selectionService
IElementSelectionService selectionService,
IThreadContext threadContext
)
{
Parent = parent;
@@ -67,6 +70,7 @@ public class NavisworksSendBinding : ISendBinding
_conversionSettingsFactory = conversionSettingsFactory;
_toSpeckleSettingsManagerNavisworks = toSpeckleSettingsManagerNavisworks;
_selectionService = selectionService;
_threadContext = threadContext;
SubscribeToNavisworksEvents();
}
@@ -82,7 +86,10 @@ public class NavisworksSendBinding : ISendBinding
new ConvertHiddenElementsSetting(false),
];
public async Task Send(string modelCardId)
public async Task Send(string modelCardId) =>
await _threadContext.RunOnMainAsync(async () => await SendInternal(modelCardId));
private async Task SendInternal(string modelCardId)
{
using var activity = _activityFactory.Start();
try
@@ -11,6 +11,7 @@ using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Models.Card.SendFilter;
using Speckle.Connectors.DUI.WebView;
@@ -51,6 +52,8 @@ public static class NavisworksConnectorServiceRegistration
serviceCollection.AddScoped<NavisworksMaterialUnpacker>();
serviceCollection.AddScoped<NavisworksColorUnpacker>();
serviceCollection.AddSingleton<IAppIdleManager, NavisworksIdleManager>();
// Sending operations
serviceCollection.AddScoped<IRootObjectBuilder<NAV.ModelItem>, NavisworksRootObjectBuilder>();
serviceCollection.AddScoped<SendOperation<NAV.ModelItem>>();
@@ -1,7 +1,7 @@
using Microsoft.Extensions.DependencyInjection;
using Speckle.Connector.Navisworks.Bindings;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.DUI.Bridge;
namespace Speckle.Connector.Navisworks.HostApp;
@@ -12,7 +12,8 @@ namespace Speckle.Connector.Navisworks.HostApp;
public sealed class NavisworksDocumentEvents
{
private readonly IServiceProvider _serviceProvider;
private readonly IEventAggregator _eventAggregator;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
private readonly IAppIdleManager _idleManager;
private readonly object _subscriptionLock = new();
private bool _isSubscribed;
@@ -25,22 +26,23 @@ public sealed class NavisworksDocumentEvents
/// Initializes a new instance of the <see cref="NavisworksDocumentEvents"/> class and subscribes to document events.
/// </summary>
/// <param name="serviceProvider">The service provider for dependency injection.</param>
public NavisworksDocumentEvents(IServiceProvider serviceProvider, IEventAggregator eventAggregator)
public NavisworksDocumentEvents(
IServiceProvider serviceProvider,
ITopLevelExceptionHandler topLevelExceptionHandler,
IAppIdleManager idleManager
)
{
_serviceProvider = serviceProvider;
_eventAggregator = eventAggregator;
_topLevelExceptionHandler = topLevelExceptionHandler;
_idleManager = idleManager;
_eventAggregator.GetEvent<ActiveDocumentChangingEvent>().Subscribe(UnsubscribeFromDocumentModelEvents);
_eventAggregator.GetEvent<ActiveDocumentChangedEvent>().Subscribe(SubscribeToDocumentModelEvents);
_eventAggregator.GetEvent<CollectionChangingEvent>().Subscribe(HandleDocumentModelCountChanging);
_eventAggregator.GetEvent<CollectionChangedEvent>().Subscribe(HandleDocumentModelCountChanged);
SubscribeToDocumentModelEvents(new object());
SubscribeToDocumentModelEvents();
}
/// <summary>
/// Subscribes to document-level events to monitor model state changes.
/// </summary>
private void SubscribeToDocumentModelEvents(object _)
private void SubscribeToDocumentModelEvents()
{
lock (_subscriptionLock)
{
@@ -52,39 +54,34 @@ public sealed class NavisworksDocumentEvents
var activeDocument = NavisworksApp.ActiveDocument;
if (activeDocument != null)
{
activeDocument.Models.CollectionChanged += OnCollectionChanged;
activeDocument.Models.CollectionChanging += OnCollectionChanging;
activeDocument.Models.CollectionChanged += HandleDocumentModelCountChanged;
activeDocument.Models.CollectionChanging += HandleDocumentModelCountChanging;
}
_isSubscribed = true;
}
}
private async void OnCollectionChanged(object sender, EventArgs _) =>
await _eventAggregator.GetEvent<CollectionChangedEvent>().PublishAsync(sender);
private async void OnCollectionChanging(object sender, EventArgs _) =>
await _eventAggregator.GetEvent<CollectionChangingEvent>().PublishAsync(sender);
/// <summary>
/// Tracks the current model count before changes occur.
/// </summary>
private void HandleDocumentModelCountChanging(object sender) =>
private void HandleDocumentModelCountChanging(object sender, EventArgs e) =>
_priorModelCount = ((NAV.Document)sender).Models.Count;
/// <summary>
/// Schedules processing of model count changes during idle time.
/// </summary>
private void HandleDocumentModelCountChanged(object sender)
private void HandleDocumentModelCountChanged(object sender, EventArgs e)
{
_finalModelCount = ((NAV.Document)sender).Models.Count;
_eventAggregator
.GetEvent<IdleEvent>()
.OneTimeSubscribe(nameof(NavisworksDocumentEvents), ProcessModelStateChangeAsync);
_topLevelExceptionHandler.CatchUnhandled(
() =>
_idleManager.SubscribeToIdle(nameof(NavisworksDocumentEvents), async () => await ProcessModelStateChangeAsync())
);
}
private async Task ProcessModelStateChangeAsync(object _)
private async Task ProcessModelStateChangeAsync()
{
if (_isProcessing)
{
@@ -133,8 +130,8 @@ public sealed class NavisworksDocumentEvents
private void UnsubscribeFromModelEvents(NAV.Document document)
{
document.Models.CollectionChanged -= OnCollectionChanged;
document.Models.CollectionChanging -= OnCollectionChanging;
document.Models.CollectionChanged -= HandleDocumentModelCountChanged;
document.Models.CollectionChanging -= HandleDocumentModelCountChanging;
var sendBinding = _serviceProvider
.GetRequiredService<IEnumerable<IBinding>>()
@@ -0,0 +1,30 @@
using Speckle.Connectors.DUI.Bridge;
namespace Speckle.Connector.Navisworks.HostApp;
/// <summary>
/// Manages the scheduling of deferred operations during Navisworks idle periods.
/// Ensures UI updates and operations are batched efficiently to prevent UI freezing.
/// </summary>
public sealed class NavisworksIdleManager : AppIdleManager
{
private readonly IIdleCallManager _idleCallManager;
/// <summary>
/// Initializes a new instance of the NavisworksIdleManager.
/// </summary>
/// <param name="idleCallManager">The manager responsible for queuing and executing deferred operations.</param>
public NavisworksIdleManager(IIdleCallManager idleCallManager)
: base(idleCallManager)
{
_idleCallManager = idleCallManager;
}
/// <summary>
/// Subscribes to Navisworks idle events when operations are queued.
/// </summary>
protected override void AddEvent() => NavisworksApp.Idle += NavisworksAppOnIdle;
private void NavisworksAppOnIdle(object? sender, EventArgs e) =>
_idleCallManager.AppOnIdle(() => NavisworksApp.Idle -= NavisworksAppOnIdle);
}
@@ -1,34 +0,0 @@
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
namespace Speckle.Connector.Navisworks;
public class SelectionChangedEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<object>(threadContext, exceptionHandler);
public class ActiveDocumentChangingEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<object>(threadContext, exceptionHandler);
public class ActiveDocumentChangedEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<object>(threadContext, exceptionHandler);
public class CollectionChangingEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<object>(threadContext, exceptionHandler);
public class CollectionChangedEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<object>(threadContext, exceptionHandler);
public static class NavisworksEvents
{
public static void Register(IEventAggregator eventAggregator)
{
NavisworksApp.Idle += async (_, _) => await eventAggregator.GetEvent<IdleEvent>().PublishAsync(new object());
NavisworksApp.ActiveDocument.CurrentSelection.Changed += async (_, _) =>
await eventAggregator.GetEvent<SelectionChangedEvent>().PublishAsync(new object());
NavisworksApp.ActiveDocumentChanging += async (_, _) =>
await eventAggregator.GetEvent<ActiveDocumentChangingEvent>().PublishAsync(new object());
NavisworksApp.ActiveDocumentChanged += async (_, _) =>
await eventAggregator.GetEvent<ActiveDocumentChangedEvent>().PublishAsync(new object());
}
}
@@ -41,7 +41,7 @@ public class NavisworksRootObjectBuilder(
/// <param name="cancellationToken">Token to cancel the operation.</param>
/// <returns>A result containing the root collection and conversion results.</returns>
/// <exception cref="SpeckleException">Thrown when no objects can be converted.</exception>
public async Task<RootObjectBuilderResult> BuildAsync(
public async Task<RootObjectBuilderResult> Build(
IReadOnlyList<NAV.ModelItem> navisworksModelItems,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
@@ -7,7 +7,6 @@ using Speckle.Connector.Navisworks.HostApp;
using Speckle.Connector.Navisworks.Plugin.Tools;
using Speckle.Connectors.Common;
using Speckle.Connectors.DUI;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.DUI.WebView;
using Speckle.Converter.Navisworks.DependencyInjection;
using Speckle.Sdk.Host;
@@ -46,7 +45,6 @@ internal sealed class Connector : NAV.Plugins.DockPanePlugin
services.AddNavisworksConverter();
Container = services.BuildServiceProvider();
NavisworksEvents.Register(Container.GetRequiredService<IEventAggregator>());
Container.UseDUI();
Container.GetRequiredService<NavisworksDocumentEvents>();
@@ -18,8 +18,8 @@
<Compile Include="$(MSBuildThisFileDirectory)HostApp\NavisworksColorUnpacker.cs"/>
<Compile Include="$(MSBuildThisFileDirectory)HostApp\NavisworksDocumentEvents.cs"/>
<Compile Include="$(MSBuildThisFileDirectory)HostApp\NavisworksDocumentModelStore.cs"/>
<Compile Include="$(MSBuildThisFileDirectory)HostApp\NavisworksIdleManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\NavisworksMaterialUnpacker.cs"/>
<Compile Include="$(MSBuildThisFileDirectory)NavisworksEvents.cs"/>
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\GeometryNodeMerger.cs"/>
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\NavisworksRootObjectBuilder.cs"/>
<Compile Include="$(MSBuildThisFileDirectory)Operations\Send\Settings\ConvertHiddenEleementsSetting.cs"/>
@@ -287,9 +287,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -297,8 +297,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.logging": {
@@ -308,7 +308,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"speckle.converters.revit2022": {
@@ -348,16 +348,16 @@
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Revit.API": {
@@ -368,26 +368,26 @@
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "[5.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.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
}
}
@@ -287,9 +287,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -297,8 +297,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.logging": {
@@ -308,7 +308,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"speckle.converters.revit2023": {
@@ -348,16 +348,16 @@
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Revit.API": {
@@ -368,26 +368,26 @@
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "[5.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.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
}
}
@@ -287,9 +287,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -297,8 +297,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.logging": {
@@ -308,7 +308,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"speckle.converters.revit2024": {
@@ -348,16 +348,16 @@
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Revit.API": {
@@ -368,26 +368,26 @@
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "[5.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.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
}
}
@@ -237,9 +237,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -247,8 +247,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.logging": {
@@ -258,7 +258,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"speckle.converters.revit2025": {
@@ -298,16 +298,16 @@
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Revit.API": {
@@ -318,25 +318,25 @@
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.CSharp": "4.7.0",
"Microsoft.Data.Sqlite": "[7.0.5]",
"Microsoft.Extensions.DependencyInjection.Abstractions": "[2.2.0]",
"Microsoft.Extensions.Logging": "[2.2.0]",
"Speckle.DoubleNumerics": "4.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
},
"net8.0-windows7.0/win-x64": {
@@ -1,6 +1,6 @@
using Autodesk.Revit.DB;
using Revit.Async;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Models.Card;
using Speckle.Connectors.RevitShared;
@@ -20,15 +20,16 @@ internal sealed class BasicConnectorBindingRevit : IBasicConnectorBinding
public BasicConnectorBindingCommands Commands { get; }
private readonly DocumentModelStore _store;
private readonly IRevitContext _revitContext;
private readonly RevitContext _revitContext;
private readonly ISpeckleApplication _speckleApplication;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
public BasicConnectorBindingRevit(
DocumentModelStore store,
IBrowserBridge parent,
IRevitContext revitContext,
RevitContext revitContext,
ISpeckleApplication speckleApplication,
IEventAggregator eventAggregator
ITopLevelExceptionHandler topLevelExceptionHandler
)
{
Name = "baseBinding";
@@ -36,13 +37,16 @@ internal sealed class BasicConnectorBindingRevit : IBasicConnectorBinding
_store = store;
_revitContext = revitContext;
_speckleApplication = speckleApplication;
_topLevelExceptionHandler = topLevelExceptionHandler;
Commands = new BasicConnectorBindingCommands(parent);
eventAggregator.GetEvent<DocumentStoreChangedEvent>().Subscribe(OnDocumentStoreChangedEvent);
_store.DocumentChanged += (_, _) =>
_topLevelExceptionHandler.FireAndForget(async () =>
{
await Commands.NotifyDocumentChanged();
});
}
private async Task OnDocumentStoreChangedEvent(object _) => await Commands.NotifyDocumentChanged();
public string GetConnectorVersion() => _speckleApplication.SpeckleVersion;
public string GetSourceApplicationName() => _speckleApplication.Slug;
@@ -129,38 +133,46 @@ internal sealed class BasicConnectorBindingRevit : IBasicConnectorBinding
return;
}
HighlightObjectsOnView(elementIds);
await HighlightObjectsOnView(elementIds);
}
/// <summary>
/// Highlights the objects from the given ids.
/// </summary>
/// <param name="objectIds"> UniqueId's of the DB.Elements.</param>
public Task HighlightObjects(IReadOnlyList<string> objectIds)
public async Task HighlightObjects(IReadOnlyList<string> objectIds)
{
var activeUIDoc =
_revitContext.UIApplication?.ActiveUIDocument
?? throw new SpeckleException("Unable to retrieve active UI document");
HighlightObjectsOnView(
objectIds
.Select(uid => ElementIdHelper.GetElementIdFromUniqueId(activeUIDoc.Document, uid))
.Where(el => el is not null)
.Cast<ElementId>()
.ToList()
);
return Task.CompletedTask;
await HighlightObjectsOnView(
objectIds
.Select(uid => ElementIdHelper.GetElementIdFromUniqueId(activeUIDoc.Document, uid))
.Where(el => el is not null)
.Cast<ElementId>()
.ToList()
)
.ConfigureAwait(false);
}
private void HighlightObjectsOnView(List<ElementId> objectIds)
private async Task HighlightObjectsOnView(List<ElementId> objectIds)
{
// POC: don't know if we can rely on storing the ActiveUIDocument, hence getting it each time
var activeUIDoc =
_revitContext.UIApplication?.ActiveUIDocument
?? throw new SpeckleException("Unable to retrieve active UI document");
activeUIDoc.Selection.SetElementIds(objectIds);
activeUIDoc.ShowElements(objectIds);
;
await RevitTask
.RunAsync(() =>
{
activeUIDoc.Selection.SetElementIds(objectIds);
activeUIDoc.ShowElements(objectIds);
})
.ConfigureAwait(false);
// activeUIDoc.Selection.SetElementIds(objectIds);
// activeUIDoc.ShowElements(objectIds);
// ;
}
}
@@ -8,7 +8,6 @@ using Speckle.Connectors.Common.Cancellation;
using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.DUI.Exceptions;
using Speckle.Connectors.DUI.Logging;
using Speckle.Connectors.DUI.Models;
@@ -17,7 +16,6 @@ using Speckle.Connectors.DUI.Models.Card.SendFilter;
using Speckle.Connectors.DUI.Settings;
using Speckle.Connectors.Revit.HostApp;
using Speckle.Connectors.Revit.Operations.Send.Settings;
using Speckle.Connectors.Revit.Plugin;
using Speckle.Connectors.RevitShared.Operations.Send.Filters;
using Speckle.Converters.Common;
using Speckle.Converters.RevitShared.Helpers;
@@ -29,7 +27,8 @@ namespace Speckle.Connectors.Revit.Bindings;
internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
{
private readonly IRevitContext _revitContext;
private readonly IAppIdleManager _idleManager;
private readonly RevitContext _revitContext;
private readonly DocumentModelStore _store;
private readonly ICancellationManager _cancellationManager;
private readonly IServiceProvider _serviceProvider;
@@ -40,7 +39,7 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
private readonly ElementUnpacker _elementUnpacker;
private readonly IRevitConversionSettingsFactory _revitConversionSettingsFactory;
private readonly ISpeckleApplication _speckleApplication;
private readonly IEventAggregator _eventAggregator;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
/// <summary>
/// Used internally to aggregate the changed objects' id. Note we're using a concurrent dictionary here as the expiry check method is not thread safe, and this was causing problems. See:
@@ -51,7 +50,8 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
private ConcurrentDictionary<ElementId, byte> ChangedObjectIds { get; set; } = new();
public RevitSendBinding(
IRevitContext revitContext,
IAppIdleManager idleManager,
RevitContext revitContext,
DocumentModelStore store,
ICancellationManager cancellationManager,
IBrowserBridge bridge,
@@ -63,10 +63,11 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
ElementUnpacker elementUnpacker,
IRevitConversionSettingsFactory revitConversionSettingsFactory,
ISpeckleApplication speckleApplication,
IEventAggregator eventAggregator
ITopLevelExceptionHandler topLevelExceptionHandler
)
: base("sendBinding", bridge)
{
_idleManager = idleManager;
_revitContext = revitContext;
_store = store;
_cancellationManager = cancellationManager;
@@ -78,14 +79,15 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
_elementUnpacker = elementUnpacker;
_revitConversionSettingsFactory = revitConversionSettingsFactory;
_speckleApplication = speckleApplication;
_eventAggregator = eventAggregator;
_topLevelExceptionHandler = topLevelExceptionHandler;
Commands = new SendBindingUICommands(bridge);
// TODO expiry events
// TODO filters need refresh events
eventAggregator.GetEvent<DocumentChangedEvent>().Subscribe(DocChangeHandler);
eventAggregator.GetEvent<DocumentStoreChangedEvent>().Subscribe(OnDocumentStoreChangedEvent);
revitContext.UIApplication.NotNull().Application.DocumentChanged += (_, e) =>
_topLevelExceptionHandler.CatchUnhandled(() => DocChangeHandler(e));
_store.DocumentChanged += (_, _) => topLevelExceptionHandler.FireAndForget(async () => await OnDocumentChanged());
}
private async Task OnDocumentStoreChangedEvent(object _) => await Commands.NotifyDocumentChanged();
@@ -173,7 +175,7 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
private async Task<List<Element>> RefreshElementsOnSender(SenderModelCard modelCard)
{
var activeUIDoc =
_revitContext.UIApplication.ActiveUIDocument
_revitContext.UIApplication.NotNull().ActiveUIDocument
?? throw new SpeckleException("Unable to retrieve active UI document");
if (modelCard.SendFilter is IRevitSendFilter viewFilter)
@@ -249,7 +251,7 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
if (addedElementIds.Count > 0)
{
_eventAggregator.GetEvent<IdleEvent>().OneTimeSubscribe(nameof(PostSetObjectIds), PostSetObjectIds);
_idleManager.SubscribeToIdle(nameof(PostSetObjectIds), PostSetObjectIds);
}
if (HaveUnitsChanged(e.GetDocument()))
@@ -269,8 +271,8 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
_sendConversionCache.EvictObjects(unpackedObjectIds);
}
_eventAggregator.GetEvent<IdleEvent>().OneTimeSubscribe(nameof(CheckFilterExpiration), CheckFilterExpiration);
_eventAggregator.GetEvent<IdleEvent>().OneTimeSubscribe(nameof(RunExpirationChecks), RunExpirationChecks);
_idleManager.SubscribeToIdle(nameof(CheckFilterExpiration), CheckFilterExpiration);
_idleManager.SubscribeToIdle(nameof(RunExpirationChecks), RunExpirationChecks);
}
// Keeps track of doc and current units
@@ -307,7 +309,7 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
return false;
}
private async Task PostSetObjectIds(object _)
private async Task PostSetObjectIds()
{
foreach (var sender in _store.GetSenders().ToList())
{
@@ -318,7 +320,7 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
/// <summary>
/// Notifies ui if any filters need refreshing. Currently, this only applies for view filters.
/// </summary>
private async Task CheckFilterExpiration(object _)
private async Task CheckFilterExpiration()
{
// NOTE: below code seems like more make sense in terms of performance but it causes unmanaged exception on Revit
// using var viewCollector = new FilteredElementCollector(RevitContext.UIApplication?.ActiveUIDocument.Document);
@@ -329,17 +331,21 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
// await Commands.RefreshSendFilters();
// }
if (ChangedObjectIds.Keys.Any(e => _revitContext.UIApplication.ActiveUIDocument.Document.GetElement(e) is View))
if (
ChangedObjectIds.Keys.Any(e =>
_revitContext.UIApplication.NotNull().ActiveUIDocument.Document.GetElement(e) is View
)
)
{
await Commands.RefreshSendFilters();
}
}
private async Task RunExpirationChecks(object _)
private async Task RunExpirationChecks()
{
var senders = _store.GetSenders().ToList();
// string[] objectIdsList = ChangedObjectIds.Keys.ToArray();
var doc = _revitContext.UIApplication.ActiveUIDocument.Document;
var doc = _revitContext.UIApplication.NotNull().ActiveUIDocument.Document;
if (doc == null)
{
@@ -393,6 +399,11 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
viewFilter.SetContext(_revitContext);
}
if (modelCard.SendFilter is null || modelCard.SendFilter.IdMap is null)
{
continue;
}
var selectedObjects = modelCard.SendFilter.NotNull().IdMap.NotNull().Values;
var intersection = selectedObjects.Intersect(objUniqueIds).ToList();
bool isExpired = intersection.Count != 0;
@@ -1,27 +1,47 @@
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.Revit.Plugin;
using Speckle.Converters.RevitShared.Helpers;
using Speckle.Sdk.Common;
namespace Speckle.Connectors.Revit.Bindings;
// POC: we need a base a RevitBaseBinding
internal sealed class SelectionBinding : RevitBaseBinding, ISelectionBinding
internal sealed class SelectionBinding : RevitBaseBinding, ISelectionBinding, IDisposable
{
private readonly IRevitContext _revitContext;
#if REVIT2022
private readonly System.Timers.Timer _selectionTimer;
#endif
private readonly RevitContext _revitContext;
private readonly IAppIdleManager _idleManager;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
public SelectionBinding(IRevitContext revitContext, IBrowserBridge parent, IEventAggregator eventAggregator)
public SelectionBinding(
RevitContext revitContext,
IBrowserBridge parent,
IAppIdleManager idleManager,
ITopLevelExceptionHandler topLevelExceptionHandler
)
: base("selectionBinding", parent)
{
_revitContext = revitContext;
eventAggregator.GetEvent<SelectionChangedEvent>().Subscribe(OnSelectionChanged);
_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.Start();
#else
_revitContext.UIApplication.NotNull().SelectionChanged += (_, _) =>
_idleManager.SubscribeToIdle(nameof(SelectionBinding), OnSelectionChanged);
#endif
}
private void OnSelectionChanged(object _)
private void OnSelectionChanged()
{
if (_revitContext.UIApplication.ActiveUIDocument == null)
if (_revitContext.UIApplication.NotNull().ActiveUIDocument == null)
{
return;
}
@@ -30,7 +50,7 @@ internal sealed class SelectionBinding : RevitBaseBinding, ISelectionBinding
public SelectionInfo GetSelection()
{
if (_revitContext.UIApplication.ActiveUIDocument == null)
if (_revitContext.UIApplication.NotNull().ActiveUIDocument == null)
{
return new SelectionInfo(Array.Empty<string>(), "No objects selected.");
}
@@ -46,4 +66,11 @@ internal sealed class SelectionBinding : RevitBaseBinding, ISelectionBinding
.ToList();
return new SelectionInfo(selectionIds, $"{selectionIds.Count} objects selected.");
}
public void Dispose()
{
#if REVIT2022
_selectionTimer.Dispose();
#endif
}
}
@@ -15,7 +15,6 @@ using Speckle.Connectors.Revit.Operations.Send;
using Speckle.Connectors.Revit.Operations.Send.Settings;
using Speckle.Connectors.Revit.Plugin;
using Speckle.Converters.Common;
using Speckle.Converters.RevitShared.Helpers;
using Speckle.Sdk.Models.GraphTraversal;
namespace Speckle.Connectors.Revit.DependencyInjection;
@@ -45,7 +44,8 @@ public static class ServiceRegistration
serviceCollection.AddSingleton<IBinding>(sp => sp.GetRequiredService<IBasicConnectorBinding>());
serviceCollection.AddSingleton<IBasicConnectorBinding, BasicConnectorBindingRevit>();
serviceCollection.AddSingleton<IRevitContext>(sp => sp.GetRequiredService<IRevitPlugin>());
serviceCollection.AddSingleton<IAppIdleManager, RevitIdleManager>();
// send operation and dependencies
serviceCollection.AddScoped<SendOperation<ElementId>>();
@@ -9,9 +9,9 @@ namespace Speckle.Connectors.Revit.HostApp;
/// </summary>
public class ElementUnpacker
{
private readonly IRevitContext _revitContext;
private readonly RevitContext _revitContext;
public ElementUnpacker(IRevitContext revitContext)
public ElementUnpacker(RevitContext revitContext)
{
_revitContext = revitContext;
}
@@ -1,11 +1,13 @@
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.ExtensibleStorage;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Events;
using Speckle.Connectors.DUI.Eventing;
using Revit.Async;
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;
namespace Speckle.Connectors.Revit.HostApp;
@@ -15,43 +17,48 @@ internal sealed class RevitDocumentStore : DocumentModelStore
// POC: move to somewhere central?
private static readonly Guid s_revitDocumentStoreId = new("D35B3695-EDC9-4E15-B62A-D3FC2CB83FA3");
private readonly IRevitContext _revitContext;
private readonly IAppIdleManager _idleManager;
private readonly RevitContext _revitContext;
private readonly DocumentModelStorageSchema _documentModelStorageSchema;
private readonly IdStorageSchema _idStorageSchema;
private readonly IEventAggregator _eventAggregator;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
public RevitDocumentStore(
IRevitContext revitContext,
IAppIdleManager idleManager,
RevitContext revitContext,
IJsonSerializer jsonSerializer,
DocumentModelStorageSchema documentModelStorageSchema,
IdStorageSchema idStorageSchema,
IEventAggregator eventAggregator
ITopLevelExceptionHandler topLevelExceptionHandler
)
: base(jsonSerializer)
{
_idleManager = idleManager;
_revitContext = revitContext;
_documentModelStorageSchema = documentModelStorageSchema;
_idStorageSchema = idStorageSchema;
_eventAggregator = eventAggregator;
_topLevelExceptionHandler = topLevelExceptionHandler;
eventAggregator.GetEvent<DocumentOpenedEvent>().Subscribe(OnDocumentOpen);
eventAggregator.GetEvent<DocumentOpeningEvent>().Subscribe(OnDocumentOpen);
eventAggregator.GetEvent<ViewActivatedEvent>().Subscribe(OnViewActivated);
UIApplication uiApplication = _revitContext.UIApplication.NotNull();
uiApplication.ViewActivated += (s, e) => _topLevelExceptionHandler.CatchUnhandled(() => OnViewActivated(s, e));
uiApplication.Application.DocumentOpening += (_, _) =>
_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();
}
private void OnDocumentOpen(object _) => IsDocumentInit = false;
public override Task OnDocumentStoreInitialized() =>
_eventAggregator.GetEvent<DocumentStoreChangedEvent>().PublishAsync(new object());
/// <summary>
/// This is the place where we track document switch for new document -> Responsible to Read from new doc
/// </summary>
private void OnViewActivated(ViewActivatedEventArgs e)
private void OnViewActivated(object? _, ViewActivatedEventArgs e)
{
if (e.Document == null)
{
@@ -65,13 +72,14 @@ internal sealed class RevitDocumentStore : DocumentModelStore
}
IsDocumentInit = true;
_eventAggregator.GetEvent<IdleEvent>().OneTimeSubscribe(nameof(RevitDocumentStore), OnIdleEvent);
}
private async Task OnIdleEvent(object _)
{
LoadState();
await _eventAggregator.GetEvent<DocumentStoreChangedEvent>().PublishAsync(new object());
_idleManager.SubscribeToIdle(
nameof(RevitDocumentStore),
() =>
{
LoadState();
OnDocumentChanged();
}
);
}
protected override void HostAppSaveState(string modelCardState)
@@ -83,20 +91,23 @@ internal sealed class RevitDocumentStore : DocumentModelStore
return;
}
using Transaction t = new(doc, "Speckle Write State");
t.Start();
using DataStorage ds = GetSettingsDataStorage(doc) ?? DataStorage.Create(doc);
RevitTask.RunAsync(() =>
{
using Transaction t = new(doc, "Speckle Write State");
t.Start();
using DataStorage ds = GetSettingsDataStorage(doc) ?? DataStorage.Create(doc);
using Entity stateEntity = new(_documentModelStorageSchema.GetSchema());
string serializedModels = Serialize();
stateEntity.Set("contents", serializedModels);
using Entity stateEntity = new(_documentModelStorageSchema.GetSchema());
string serializedModels = Serialize();
stateEntity.Set("contents", serializedModels);
using Entity idEntity = new(_idStorageSchema.GetSchema());
idEntity.Set("Id", s_revitDocumentStoreId);
using Entity idEntity = new(_idStorageSchema.GetSchema());
idEntity.Set("Id", s_revitDocumentStoreId);
ds.SetEntity(idEntity);
ds.SetEntity(stateEntity);
t.Commit();
ds.SetEntity(idEntity);
ds.SetEntity(stateEntity);
t.Commit();
});
}
protected override void LoadState()
@@ -5,7 +5,7 @@ namespace Speckle.Connectors.Revit.HostApp;
public static class SupportedCategoriesUtils
{
/// <summary>
/// Filters out all categories besides Model categories. This utility should be used
/// Filters out all categories besides Model categories, and Grids in Annotation. This utility should be used
/// to clean any elements we might want to send pre-conversion as well as in what categories
/// to display in our category filter.
/// </summary>
@@ -13,18 +13,32 @@ public static class SupportedCategoriesUtils
/// <returns></returns>
public static bool IsSupportedCategory(Category? category)
{
return category is not null
&& (
category.CategoryType == CategoryType.Model
// || category.CategoryType == CategoryType.AnalyticalModel
)
#if REVIT_2023_OR_GREATER
&& category.BuiltInCategory != BuiltInCategory.OST_AreaSchemes
&& category.BuiltInCategory != BuiltInCategory.OST_AreaSchemeLines
if (category is null || !category.IsVisibleInUI)
{
return false;
}
switch (category.CategoryType)
{
case CategoryType.Annotation:
return
#if REVIT2023_OR_GREATER
category.BuiltInCategory == BuiltInCategory.OST_Grids;
#else
&& category.Name != "OST_AreaSchemeLines"
&& category.Name != "OST_AreaSchemes"
category.Name == "OST_Grids";
#endif
&& category.IsVisibleInUI;
case CategoryType.Model:
return
#if REVIT2023_OR_GREATER
category.BuiltInCategory != BuiltInCategory.OST_AreaSchemes
&& category.BuiltInCategory != BuiltInCategory.OST_AreaSchemeLines;
#else
category.Name != "OST_AreaSchemeLines" && category.Name != "OST_AreaSchemes";
#endif
default:
return false;
}
}
}
@@ -5,6 +5,7 @@ using Speckle.Connectors.Common.Conversion;
using Speckle.Connectors.Common.Instances;
using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Common.Operations.Receive;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.Revit.HostApp;
using Speckle.Converters.Common;
using Speckle.Converters.Common.Objects;
@@ -33,6 +34,7 @@ public sealed class RevitHostObjectBuilder(
RevitMaterialBaker materialBaker,
RootObjectUnpacker rootObjectUnpacker,
ILogger<RevitHostObjectBuilder> logger,
IThreadContext threadContext,
RevitToHostCacheSingleton revitToHostCacheSingleton,
ITypedConverter<
(Base atomicObject, IReadOnlyCollection<Matrix4x4> matrix),
@@ -40,7 +42,18 @@ public sealed class RevitHostObjectBuilder(
> localToGlobalDirectShapeConverter
) : IHostObjectBuilder, IDisposable
{
public HostObjectBuilderResult Build(
public Task<HostObjectBuilderResult> Build(
Base rootObject,
string projectName,
string modelName,
IProgress<CardProgress> onOperationProgressed,
CancellationToken cancellationToken
) =>
threadContext.RunOnMainAsync(
() => Task.FromResult(BuildSync(rootObject, projectName, modelName, onOperationProgressed, cancellationToken))
);
private HostObjectBuilderResult BuildSync(
Base rootObject,
string projectName,
string modelName,
@@ -4,5 +4,5 @@ namespace Speckle.Connectors.RevitShared.Operations.Send.Filters;
public interface IRevitSendFilter
{
public void SetContext(IRevitContext revitContext);
public void SetContext(RevitContext revitContext);
}
@@ -4,6 +4,7 @@ using Speckle.Connectors.DUI.Models.Card.SendFilter;
using Speckle.Connectors.DUI.Utils;
using Speckle.Connectors.Revit.HostApp;
using Speckle.Converters.RevitShared.Helpers;
using Speckle.Sdk.Common;
namespace Speckle.Connectors.RevitShared.Operations.Send.Filters;
@@ -11,7 +12,7 @@ public record CategoryData(string Name, string Id);
public class RevitCategoriesFilter : DiscriminatedObject, ISendFilter, IRevitSendFilter
{
private IRevitContext _revitContext;
private RevitContext _revitContext;
private Document? _doc;
public string Id { get; set; } = "revitCategories";
public string Name { get; set; } = "Categories";
@@ -24,10 +25,10 @@ public class RevitCategoriesFilter : DiscriminatedObject, ISendFilter, IRevitSen
public RevitCategoriesFilter() { }
public RevitCategoriesFilter(IRevitContext revitContext)
public RevitCategoriesFilter(RevitContext revitContext)
{
_revitContext = revitContext;
_doc = _revitContext.UIApplication.ActiveUIDocument.Document;
_doc = _revitContext.UIApplication.NotNull().ActiveUIDocument.Document;
GetCategories();
}
@@ -83,7 +84,7 @@ public class RevitCategoriesFilter : DiscriminatedObject, ISendFilter, IRevitSen
/// NOTE: this is needed since we need doc on `GetObjectIds()` function after it deserialized.
/// DI doesn't help here to pass RevitContext from constructor.
/// </summary>
public void SetContext(IRevitContext revitContext)
public void SetContext(RevitContext revitContext)
{
_revitContext = revitContext;
_doc = _revitContext.UIApplication?.ActiveUIDocument.Document;
@@ -8,7 +8,7 @@ namespace Speckle.Connectors.RevitShared.Operations.Send.Filters;
public class RevitViewsFilter : DiscriminatedObject, ISendFilter, IRevitSendFilter
{
private IRevitContext _revitContext;
private RevitContext _revitContext;
private Document? _doc;
public string Id { get; set; } = "revitViews";
public string Name { get; set; } = "Views";
@@ -21,7 +21,7 @@ public class RevitViewsFilter : DiscriminatedObject, ISendFilter, IRevitSendFilt
public RevitViewsFilter() { }
public RevitViewsFilter(IRevitContext revitContext)
public RevitViewsFilter(RevitContext revitContext)
{
_revitContext = revitContext;
_doc = _revitContext.UIApplication?.ActiveUIDocument.Document;
@@ -109,7 +109,7 @@ public class RevitViewsFilter : DiscriminatedObject, ISendFilter, IRevitSendFilt
/// NOTE: this is needed since we need doc on `GetObjectIds()` function after it deserialized.
/// DI doesn't help here to pass RevitContext from constructor.
/// </summary>
public void SetContext(IRevitContext revitContext)
public void SetContext(RevitContext revitContext)
{
_revitContext = revitContext;
_doc = _revitContext.UIApplication?.ActiveUIDocument.Document;
@@ -5,6 +5,7 @@ using Speckle.Connectors.Common.Caching;
using Speckle.Connectors.Common.Conversion;
using Speckle.Connectors.Common.Extensions;
using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Exceptions;
using Speckle.Connectors.Revit.HostApp;
using Speckle.Converters.Common;
@@ -21,14 +22,22 @@ public class RevitRootObjectBuilder(
IConverterSettingsStore<RevitConversionSettings> converterSettings,
ISendConversionCache sendConversionCache,
ElementUnpacker elementUnpacker,
IThreadContext threadContext,
SendCollectionManager sendCollectionManager,
ILogger<RevitRootObjectBuilder> logger,
RevitToSpeckleCacheSingleton revitToSpeckleCacheSingleton
) : RootObjectBuilderBase<ElementId>
) : IRootObjectBuilder<ElementId>
{
// POC: SendSelection and RevitConversionContextStack should be interfaces, former needs interfaces
public override RootObjectBuilderResult Build(
public Task<RootObjectBuilderResult> Build(
IReadOnlyList<ElementId> objects,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
CancellationToken ct = default
) => threadContext.RunOnMainAsync(() => Task.FromResult(BuildSync(objects, sendInfo, onOperationProgressed, ct)));
private RootObjectBuilderResult BuildSync(
IReadOnlyList<ElementId> objects,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
@@ -76,7 +85,7 @@ public class RevitRootObjectBuilder(
var countProgress = 0;
var cacheHitCount = 0;
var skippedObjectCount = 0;
foreach (Element revitElement in atomicObjects)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -96,6 +105,7 @@ public class RevitRootObjectBuilder(
new SpeckleException($"Category {cat} is not supported.")
)
);
skippedObjectCount++;
continue;
}
@@ -125,7 +135,7 @@ public class RevitRootObjectBuilder(
onOperationProgressed.Report(new("Converting", (double)++countProgress / atomicObjects.Count));
}
if (results.All(x => x.Status == Status.ERROR))
if (results.All(x => x.Status == Status.ERROR) || skippedObjectCount == atomicObjects.Count)
{
throw new SpeckleException("Failed to convert all objects.");
}
@@ -13,7 +13,7 @@ namespace Speckle.Connectors.Revit.Operations.Send.Settings;
[GenerateAutoInterface]
public class ToSpeckleSettingsManager : IToSpeckleSettingsManager
{
private readonly IRevitContext _revitContext;
private readonly RevitContext _revitContext;
private readonly ISendConversionCache _sendConversionCache;
private readonly ElementUnpacker _elementUnpacker;
@@ -23,7 +23,7 @@ public class ToSpeckleSettingsManager : IToSpeckleSettingsManager
private readonly Dictionary<string, bool?> _sendNullParamsCache = new();
public ToSpeckleSettingsManager(
IRevitContext revitContext,
RevitContext revitContext,
ISendConversionCache sendConversionCache,
ElementUnpacker elementUnpacker
)
@@ -1,8 +1,6 @@
using Speckle.Converters.RevitShared.Helpers;
namespace Speckle.Connectors.Revit.Plugin;
internal interface IRevitPlugin : IRevitContext
internal interface IRevitPlugin
{
void Initialise();
void Shutdown();
@@ -3,13 +3,15 @@ using System.IO;
using System.Reflection;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Autodesk.Revit.ApplicationServices;
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;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Converters.RevitShared.Helpers;
using Speckle.Sdk;
namespace Speckle.Connectors.Revit.Plugin;
@@ -19,6 +21,7 @@ internal sealed class RevitCefPlugin : IRevitPlugin
private readonly UIControlledApplication _uIControlledApplication;
private readonly IServiceProvider _serviceProvider; // should be lazy to ensure the bindings are not created too early
private readonly BindingOptions _bindingOptions;
private readonly RevitContext _revitContext;
private readonly CefSharpPanel _cefSharpPanel;
private readonly ISpeckleApplication _speckleApplication;
@@ -26,17 +29,17 @@ internal sealed class RevitCefPlugin : IRevitPlugin
UIControlledApplication uIControlledApplication,
IServiceProvider serviceProvider,
BindingOptions bindingOptions,
RevitContext revitContext,
CefSharpPanel cefSharpPanel,
ISpeckleApplication speckleApplication,
IEventAggregator eventAggregator
ISpeckleApplication speckleApplication
)
{
_uIControlledApplication = uIControlledApplication;
_serviceProvider = serviceProvider;
_bindingOptions = bindingOptions;
_revitContext = revitContext;
_cefSharpPanel = cefSharpPanel;
_speckleApplication = speckleApplication;
eventAggregator.GetEvent<ApplicationInitializedEvent>().Subscribe(OnApplicationInitialized);
}
public void Initialise()
@@ -44,6 +47,7 @@ internal sealed class RevitCefPlugin : IRevitPlugin
// 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()
@@ -90,14 +94,27 @@ internal sealed class RevitCefPlugin : IRevitPlugin
$"Speckle.Connectors.Revit{_speckleApplication.HostApplicationVersion}.Assets.logo32.png",
path
);
dui3Button.ToolTip = "Next Gen Speckle Connector (Beta) for Revit";
dui3Button.ToolTip = "Speckle (Beta) for Revit";
//dui3Button.AvailabilityClassName = typeof(CmdAvailabilityViews).FullName;
dui3Button.SetContextualHelp(new ContextualHelp(ContextualHelpType.Url, "https://speckle.systems"));
}
private void OnApplicationInitialized(UIApplication uiApplication)
private void OnApplicationInitialized(object? sender, Autodesk.Revit.DB.Events.ApplicationInitializedEventArgs e)
{
UIApplication = uiApplication;
var uiApplication = new UIApplication(sender as Application);
_revitContext.UIApplication = uiApplication;
// POC: might be worth to interface this out, we shall see...
RevitTask.Initialize(uiApplication);
PostApplicationInit(); // for double-click file open
}
/// <summary>
/// Actions to run after UiApplication initialized. This is needed for double-click file open issue.
/// </summary>
private void PostApplicationInit()
{
var bindings = _serviceProvider.GetRequiredService<IEnumerable<IBinding>>();
// binding the bindings to each bridge
foreach (IBinding binding in bindings)
@@ -106,7 +123,7 @@ internal sealed class RevitCefPlugin : IRevitPlugin
binding.Parent.AssociateWithBinding(binding);
}
_cefSharpPanel.Browser.IsBrowserInitializedChanged += (_, e) =>
_cefSharpPanel.Browser.IsBrowserInitializedChanged += (sender, e) =>
{
if (e.NewValue is false)
{
@@ -142,7 +159,7 @@ internal sealed class RevitCefPlugin : IRevitPlugin
// Otherwise pane cannot be registered for double-click file open.
_uIControlledApplication.RegisterDockablePane(
RevitExternalApplication.DockablePanelId,
"Speckle (Beta)",
"Speckle (Beta) for Revit",
_cefSharpPanel
);
}
@@ -164,6 +181,4 @@ internal sealed class RevitCefPlugin : IRevitPlugin
return null;
}
public UIApplication UIApplication { get; private set; }
}
@@ -1,72 +0,0 @@
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Events;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
namespace Speckle.Connectors.Revit.Plugin;
public class ApplicationInitializedEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<UIApplication>(threadContext, exceptionHandler);
public class ViewActivatedEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<ViewActivatedEventArgs>(threadContext, exceptionHandler);
public class DocumentOpeningEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<object>(threadContext, exceptionHandler);
public class DocumentOpenedEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<object>(threadContext, exceptionHandler);
public class SelectionChangedEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<object>(threadContext, exceptionHandler);
public class DocumentChangedEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<Autodesk.Revit.DB.Events.DocumentChangedEventArgs>(threadContext, exceptionHandler);
#if REVIT2022
public class PeriodicSelectionEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: PeriodicThreadedEvent(threadContext, exceptionHandler);
#endif
public static class RevitEvents
{
private static IEventAggregator? s_eventAggregator;
public static void Register(IEventAggregator eventAggregator, UIControlledApplication application)
{
s_eventAggregator = eventAggregator;
application.Idling += async (_, _) => await eventAggregator.GetEvent<IdleEvent>().PublishAsync(new object());
application.ControlledApplication.ApplicationInitialized += async (sender, _) =>
await eventAggregator
.GetEvent<ApplicationInitializedEvent>()
.PublishAsync(new UIApplication(sender as Application));
application.ViewActivated += async (_, args) =>
await eventAggregator.GetEvent<ViewActivatedEvent>().PublishAsync(args);
application.ControlledApplication.DocumentOpened += async (_, _) =>
await eventAggregator.GetEvent<DocumentOpenedEvent>().PublishAsync(new object());
application.ControlledApplication.DocumentOpening += async (_, _) =>
await eventAggregator.GetEvent<DocumentOpeningEvent>().PublishAsync(new object());
application.ControlledApplication.DocumentChanged += async (_, args) =>
await eventAggregator.GetEvent<DocumentChangedEvent>().PublishAsync(args);
#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.
eventAggregator.GetEvent<PeriodicSelectionEvent>().SubscribePeriodic(TimeSpan.FromSeconds(1), OnSelectionChanged);
#else
application.SelectionChanged += (_, _) =>
eventAggregator.GetEvent<IdleEvent>().OneTimeSubscribe("Selection", OnSelectionChanged);
#endif
}
private static async Task OnSelectionChanged(object _)
{
if (s_eventAggregator is null)
{
return;
}
await s_eventAggregator.GetEvent<SelectionChangedEvent>().PublishAsync(new object());
}
}
@@ -4,7 +4,6 @@ using Microsoft.Extensions.Logging;
using Revit.Async;
using Speckle.Connectors.Common;
using Speckle.Connectors.DUI;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.Revit.DependencyInjection;
using Speckle.Converters.RevitShared;
using Speckle.Sdk;
@@ -53,7 +52,6 @@ internal sealed class RevitExternalApplication : IExternalApplication
_container.UseDUI();
RevitTask.Initialize(application);
RevitEvents.Register(_container.GetRequiredService<IEventAggregator>(), application);
// resolve root object
_revitPlugin = _container.GetRequiredService<IRevitPlugin>();
_revitPlugin.Initialise();
@@ -44,10 +44,10 @@
<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\RevitEvents.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\IRevitPlugin.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\RevitCommand.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\RevitExternalApplication.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\RevitIdleManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\RevitThreadContext.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Plugin\RevitCefPlugin.cs" />
</ItemGroup>
@@ -268,9 +268,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -278,8 +278,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui.webview": {
@@ -296,7 +296,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"speckle.converters.rhino7": {
@@ -342,40 +342,40 @@
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "[5.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.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
}
}
@@ -268,9 +268,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -278,8 +278,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui.webview": {
@@ -296,7 +296,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"speckle.converters.rhino8": {
@@ -342,40 +342,40 @@
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.0.1",
"contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w=="
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "[5.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.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
}
}
@@ -4,7 +4,6 @@ using Rhino.Geometry;
using Speckle.Connectors.Common.Caching;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Models.Card;
using Speckle.Connectors.Rhino.Extensions;
@@ -22,29 +21,32 @@ public sealed class RhinoBasicConnectorBinding : IBasicConnectorBinding
private readonly DocumentModelStore _store;
private readonly ISendConversionCache _sendConversionCache;
private readonly ISpeckleApplication _speckleApplication;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
public RhinoBasicConnectorBinding(
DocumentModelStore store,
IBrowserBridge parent,
ISendConversionCache sendConversionCache,
ISpeckleApplication speckleApplication,
IEventAggregator eventAggregator
ITopLevelExceptionHandler topLevelExceptionHandler
)
{
_store = store;
Parent = parent;
_sendConversionCache = sendConversionCache;
_speckleApplication = speckleApplication;
_topLevelExceptionHandler = topLevelExceptionHandler;
Commands = new BasicConnectorBindingCommands(parent);
eventAggregator.GetEvent<DocumentStoreChangedEvent>().Subscribe(OnDocumentStoreChangedEvent);
}
_store.DocumentChanged += (_, _) =>
_topLevelExceptionHandler.FireAndForget(async () =>
{
await Commands.NotifyDocumentChanged();
// Note: this prevents scaling issues when copy-pasting from one rhino doc to another in the same session.
_sendConversionCache.ClearCache();
});
private async Task OnDocumentStoreChangedEvent(object _)
{
await Commands.NotifyDocumentChanged();
// Note: this prevents scaling issues when copy-pasting from one rhino doc to another in the same session.
_sendConversionCache.ClearCache();
// eventAggregator.GetEvent<DocumentStoreChangedEvent>().Subscribe(OnDocumentStoreChangedEvent);
}
public string GetConnectorVersion() => _speckleApplication.SpeckleVersion;
@@ -2,32 +2,31 @@ using Rhino;
using Rhino.DocObjects;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.RhinoShared;
namespace Speckle.Connectors.Rhino.Bindings;
public class RhinoSelectionBinding : ISelectionBinding
{
private readonly IAppIdleManager _idleManager;
private const string SELECTION_EVENT = "setSelection";
private readonly IEventAggregator _eventAggregator;
public string Name => "selectionBinding";
public IBrowserBridge Parent { get; }
public RhinoSelectionBinding(IBrowserBridge parent, IEventAggregator eventAggregator)
public RhinoSelectionBinding(IAppIdleManager idleManager, IBrowserBridge parent)
{
_idleManager = idleManager;
Parent = parent;
_eventAggregator = eventAggregator;
eventAggregator.GetEvent<SelectObjects>().Subscribe(OnSelectionChange);
eventAggregator.GetEvent<DeselectObjects>().Subscribe(OnSelectionChange);
eventAggregator.GetEvent<DeselectAllObjects>().Subscribe(OnSelectionChange);
RhinoDoc.SelectObjects += OnSelectionChange;
RhinoDoc.DeselectObjects += OnSelectionChange;
RhinoDoc.DeselectAllObjects += OnSelectionChange;
}
private void OnSelectionChange(EventArgs eventArgs) =>
_eventAggregator.GetEvent<IdleEvent>().OneTimeSubscribe(nameof(RhinoSelectionBinding), UpdateSelection);
private void OnSelectionChange(object? o, EventArgs eventArgs) =>
_idleManager.SubscribeToIdle(nameof(RhinoSelectionBinding), UpdateSelection);
private void UpdateSelection(object _)
private void UpdateSelection()
{
SelectionInfo selInfo = GetSelection();
Parent.Send(SELECTION_EVENT, selInfo);
@@ -10,14 +10,12 @@ using Speckle.Connectors.Common.Cancellation;
using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.DUI.Exceptions;
using Speckle.Connectors.DUI.Logging;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Models.Card;
using Speckle.Connectors.DUI.Models.Card.SendFilter;
using Speckle.Connectors.DUI.Settings;
using Speckle.Connectors.RhinoShared;
using Speckle.Converters.Common;
using Speckle.Converters.Rhino;
using Speckle.Sdk;
@@ -42,7 +40,8 @@ public sealed class RhinoSendBinding : ISendBinding
private readonly IRhinoConversionSettingsFactory _rhinoConversionSettingsFactory;
private readonly ISpeckleApplication _speckleApplication;
private readonly ISdkActivityFactory _activityFactory;
private readonly IEventAggregator _eventAggregator;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
private readonly IAppIdleManager _idleManager;
/// <summary>
/// Used internally to aggregate the changed objects' id. Objects in this list will be reconverted.
@@ -64,6 +63,7 @@ public sealed class RhinoSendBinding : ISendBinding
public RhinoSendBinding(
DocumentModelStore store,
IAppIdleManager idleManager,
IBrowserBridge parent,
IEnumerable<ISendFilter> sendFilters,
IServiceProvider serviceProvider,
@@ -74,10 +74,11 @@ public sealed class RhinoSendBinding : ISendBinding
IRhinoConversionSettingsFactory rhinoConversionSettingsFactory,
ISpeckleApplication speckleApplication,
ISdkActivityFactory activityFactory,
IEventAggregator eventAggregator
ITopLevelExceptionHandler topLevelExceptionHandler
)
{
_store = store;
_idleManager = idleManager;
_serviceProvider = serviceProvider;
_sendFilters = sendFilters.ToList();
_cancellationManager = cancellationManager;
@@ -87,203 +88,194 @@ public sealed class RhinoSendBinding : ISendBinding
_rhinoConversionSettingsFactory = rhinoConversionSettingsFactory;
_speckleApplication = speckleApplication;
Parent = parent;
_topLevelExceptionHandler = topLevelExceptionHandler;
Commands = new SendBindingUICommands(parent); // POC: Commands are tightly coupled with their bindings, at least for now, saves us injecting a factory.
_activityFactory = activityFactory;
_eventAggregator = eventAggregator;
PreviousUnitSystem = RhinoDoc.ActiveDoc.ModelUnitSystem;
SubscribeToRhinoEvents(eventAggregator);
SubscribeToRhinoEvents();
}
private void SubscribeToRhinoEvents(IEventAggregator eventAggregator)
#pragma warning disable CA1502
private void SubscribeToRhinoEvents()
#pragma warning restore CA1502
{
eventAggregator.GetEvent<BeginCommandEvent>().Subscribe(OnBeginCommandEvent);
Command.BeginCommand += (_, e) =>
{
if (e.CommandEnglishName == "BlockEdit")
{
var selectedObject = RhinoDoc.ActiveDoc.Objects.GetSelectedObjects(false, false).First();
ChangedObjectIds[selectedObject.Id.ToString()] = 1;
}
eventAggregator.GetEvent<ActiveDocumentChanged>().Subscribe(OnActiveDocumentChanged);
if (e.CommandEnglishName == "Ungroup")
{
foreach (RhinoObject selectedObject in RhinoDoc.ActiveDoc.Objects.GetSelectedObjects(false, false))
{
ChangedObjectIdsInGroupsOrLayers[selectedObject.Id.ToString()] = 1;
}
_idleManager.SubscribeToIdle("a", RunExpirationChecks);
_idleManager.SubscribeToIdle(nameof(RhinoSendBinding), RunExpirationChecks);
}
};
RhinoDoc.ActiveDocumentChanged += (_, e) =>
{
PreviousUnitSystem = e.Document.ModelUnitSystem;
};
// NOTE: BE CAREFUL handling things in this event handler since it is triggered whenever we save something into file!
eventAggregator.GetEvent<DocumentPropertiesChanged>().Subscribe(OnDocumentPropertiesChanged);
RhinoDoc.DocumentPropertiesChanged += async (_, e) =>
{
var newUnit = e.Document.ModelUnitSystem;
if (newUnit != PreviousUnitSystem)
{
PreviousUnitSystem = newUnit;
eventAggregator.GetEvent<AddRhinoObject>().Subscribe(OnAddRhinoObject);
await InvalidateAllSender();
}
};
eventAggregator.GetEvent<DeleteRhinoObject>().Subscribe(OnDeleteRhinoObject);
RhinoDoc.AddRhinoObject += (_, e) =>
_topLevelExceptionHandler.CatchUnhandled(() =>
{
if (!_store.IsDocumentInit)
{
return;
}
ChangedObjectIds[e.ObjectId.ToString()] = 1;
_idleManager.SubscribeToIdle(nameof(RhinoSendBinding), RunExpirationChecks);
});
RhinoDoc.DeleteRhinoObject += (_, e) =>
_topLevelExceptionHandler.CatchUnhandled(() =>
{
if (!_store.IsDocumentInit)
{
return;
}
ChangedObjectIds[e.ObjectId.ToString()] = 1;
_idleManager.SubscribeToIdle(nameof(RhinoSendBinding), RunExpirationChecks);
});
// NOTE: Catches an object's material change from one user defined doc material to another. Does not catch (as the top event is not triggered) swapping material sources for an object or moving to/from the default material (this is handled below)!
eventAggregator.GetEvent<RenderMaterialsTableEvent>().Subscribe(OnRenderMaterialsTableEvent);
RhinoDoc.RenderMaterialsTableEvent += (_, args) =>
_topLevelExceptionHandler.CatchUnhandled(() =>
{
if (!_store.IsDocumentInit)
{
return;
}
eventAggregator.GetEvent<GroupTableEvent>().Subscribe(OnGroupTableEvent);
if (args is RhinoDoc.RenderMaterialAssignmentChangedEventArgs changedEventArgs)
{
ChangedObjectIds[changedEventArgs.ObjectId.ToString()] = 1;
_idleManager.SubscribeToIdle(nameof(RhinoSendBinding), RunExpirationChecks);
}
});
eventAggregator.GetEvent<LayerTableEvent>().Subscribe(OnLayerTableEvent);
RhinoDoc.GroupTableEvent += (_, args) =>
_topLevelExceptionHandler.CatchUnhandled(() =>
{
if (!_store.IsDocumentInit)
{
return;
}
foreach (var obj in RhinoDoc.ActiveDoc.Groups.GroupMembers(args.GroupIndex))
{
ChangedObjectIdsInGroupsOrLayers[obj.Id.ToString()] = 1;
}
_idleManager.SubscribeToIdle(nameof(RhinoSendBinding), RunExpirationChecks);
});
RhinoDoc.LayerTableEvent += (_, args) =>
_topLevelExceptionHandler.CatchUnhandled(() =>
{
if (!_store.IsDocumentInit)
{
return;
}
if (
args.EventType == LayerTableEventType.Deleted
|| args.EventType == LayerTableEventType.Current
|| args.EventType == LayerTableEventType.Added
)
{
return;
}
var layer = RhinoDoc.ActiveDoc.Layers[args.LayerIndex];
var allLayers = args.Document.Layers.Where(l => /* NOTE: layer path may actually be null in some cases (rhino's fault, not ours) */
l.FullPath != null && l.FullPath.Contains(layer.Name)
); // not e imperfect, but layer.GetChildren(true) is valid only in v8 and above; this filter will include the original layer.
foreach (var childLayer in allLayers)
{
var sublayerObjs = RhinoDoc.ActiveDoc.Objects.FindByLayer(childLayer) ?? [];
foreach (var obj in sublayerObjs)
{
ChangedObjectIdsInGroupsOrLayers[obj.Id.ToString()] = 1;
}
}
_idleManager.SubscribeToIdle(nameof(RhinoSendBinding), RunExpirationChecks);
});
// Catches and stores changed material ids. These are then used in the expiry checks to invalidate all objects that have assigned any of those material ids.
eventAggregator.GetEvent<MaterialTableEvent>().Subscribe(OnMaterialTableEvent);
eventAggregator.GetEvent<ModifyObjectAttributes>().Subscribe(OnModifyObjectAttributes);
eventAggregator.GetEvent<ReplaceRhinoObject>().Subscribe(OnReplaceRhinoObject);
}
private void OnActiveDocumentChanged(DocumentEventArgs e) => PreviousUnitSystem = e.Document.ModelUnitSystem;
private async Task OnDocumentPropertiesChanged(DocumentEventArgs e)
{
var newUnit = e.Document.ModelUnitSystem;
if (newUnit != PreviousUnitSystem)
{
PreviousUnitSystem = newUnit;
await InvalidateAllSender();
}
}
private void OnBeginCommandEvent(CommandEventArgs e)
{
if (e.CommandEnglishName == "BlockEdit")
{
var selectedObject = RhinoDoc.ActiveDoc.Objects.GetSelectedObjects(false, false).First();
ChangedObjectIds[selectedObject.Id.ToString()] = 1;
}
if (e.CommandEnglishName == "Ungroup")
{
foreach (RhinoObject selectedObject in RhinoDoc.ActiveDoc.Objects.GetSelectedObjects(false, false))
RhinoDoc.MaterialTableEvent += (_, args) =>
_topLevelExceptionHandler.CatchUnhandled(() =>
{
ChangedObjectIdsInGroupsOrLayers[selectedObject.Id.ToString()] = 1;
}
_eventAggregator.GetEvent<IdleEvent>().OneTimeSubscribe(nameof(RhinoSendBinding), RunExpirationChecks);
}
}
if (!_store.IsDocumentInit)
{
return;
}
private void OnAddRhinoObject(RhinoObjectEventArgs e)
{
if (!_store.IsDocumentInit)
{
return;
}
if (args.EventType == MaterialTableEventType.Modified)
{
ChangedMaterialIndexes[args.Index] = 1;
_idleManager.SubscribeToIdle(nameof(RhinoSendBinding), RunExpirationChecks);
}
});
ChangedObjectIds[e.ObjectId.ToString()] = 1;
_eventAggregator.GetEvent<IdleEvent>().OneTimeSubscribe(nameof(RhinoSendBinding), RunExpirationChecks);
}
private void OnDeleteRhinoObject(RhinoObjectEventArgs e)
{
if (!_store.IsDocumentInit)
{
return;
}
ChangedObjectIds[e.ObjectId.ToString()] = 1;
_eventAggregator.GetEvent<IdleEvent>().OneTimeSubscribe(nameof(RhinoSendBinding), RunExpirationChecks);
}
private void OnRenderMaterialsTableEvent(RhinoDoc.RenderContentTableEventArgs e)
{
if (!_store.IsDocumentInit)
{
return;
}
if (e is RhinoDoc.RenderMaterialAssignmentChangedEventArgs changedEventArgs)
{
ChangedObjectIds[changedEventArgs.ObjectId.ToString()] = 1;
_eventAggregator.GetEvent<IdleEvent>().OneTimeSubscribe(nameof(RhinoSendBinding), RunExpirationChecks);
}
}
private void OnGroupTableEvent(GroupTableEventArgs args)
{
if (!_store.IsDocumentInit)
{
return;
}
foreach (var obj in RhinoDoc.ActiveDoc.Groups.GroupMembers(args.GroupIndex))
{
ChangedObjectIdsInGroupsOrLayers[obj.Id.ToString()] = 1;
}
_eventAggregator.GetEvent<IdleEvent>().OneTimeSubscribe(nameof(RhinoSendBinding), RunExpirationChecks);
}
private void OnLayerTableEvent(LayerTableEventArgs args)
{
if (!_store.IsDocumentInit)
{
return;
}
if (
args.EventType == LayerTableEventType.Deleted
|| args.EventType == LayerTableEventType.Current
|| args.EventType == LayerTableEventType.Added
)
{
return;
}
var layer = RhinoDoc.ActiveDoc.Layers[args.LayerIndex];
if (layer.Name is null)
{
return;
}
// add all objects from the changed layers and sublayers to the non-destructively changed object list.
var allLayers = args.Document.Layers.Where(l => /* NOTE: layer path may actually be null in some cases (rhino's fault, not ours) */
l.FullPath != null && l.FullPath.Contains(layer.Name)
); // not e imperfect, but layer.GetChildren(true) is valid only in v8 and above; this filter will include the original layer.
foreach (var childLayer in allLayers)
{
var sublayerObjs = RhinoDoc.ActiveDoc.Objects.FindByLayer(childLayer) ?? [];
foreach (var obj in sublayerObjs)
RhinoDoc.ModifyObjectAttributes += (_, e) =>
_topLevelExceptionHandler.CatchUnhandled(() =>
{
ChangedObjectIdsInGroupsOrLayers[obj.Id.ToString()] = 1;
}
}
_eventAggregator.GetEvent<IdleEvent>().OneTimeSubscribe(nameof(RhinoSendBinding), RunExpirationChecks);
}
if (!_store.IsDocumentInit)
{
return;
}
private void OnMaterialTableEvent(MaterialTableEventArgs args)
{
if (!_store.IsDocumentInit)
{
return;
}
// NOTE: not sure yet we want to track every attribute changes yet. Explicitly tracking atts that change commit data. TBD
if (
e.OldAttributes.LayerIndex != e.NewAttributes.LayerIndex
|| e.OldAttributes.MaterialSource != e.NewAttributes.MaterialSource
|| e.OldAttributes.MaterialIndex != e.NewAttributes.MaterialIndex // NOTE: this does not work when swapping around from custom doc materials, it works when you swap TO/FROM default material
|| e.OldAttributes.ColorSource != e.NewAttributes.ColorSource
|| e.OldAttributes.ObjectColor != e.NewAttributes.ObjectColor
|| e.OldAttributes.Name != e.NewAttributes.Name
|| e.OldAttributes.UserStringCount != e.NewAttributes.UserStringCount
|| e.OldAttributes.GetUserStrings() != e.NewAttributes.GetUserStrings()
)
{
ChangedObjectIds[e.RhinoObject.Id.ToString()] = 1;
_idleManager.SubscribeToIdle(nameof(RhinoSendBinding), RunExpirationChecks);
}
});
if (args.EventType == MaterialTableEventType.Modified)
{
ChangedMaterialIndexes[args.Index] = 1;
_eventAggregator.GetEvent<IdleEvent>().OneTimeSubscribe(nameof(RhinoSendBinding), RunExpirationChecks);
}
}
RhinoDoc.ReplaceRhinoObject += (_, e) =>
_topLevelExceptionHandler.CatchUnhandled(() =>
{
if (!_store.IsDocumentInit)
{
return;
}
private void OnModifyObjectAttributes(RhinoModifyObjectAttributesEventArgs e)
{
if (!_store.IsDocumentInit)
{
return;
}
// NOTE: not sure yet we want to track every attribute changes yet. TBD
// NOTE: we might want to track here user strings too (once we send them out), and more!
if (
e.OldAttributes.LayerIndex != e.NewAttributes.LayerIndex
|| e.OldAttributes.MaterialSource != e.NewAttributes.MaterialSource
|| e.OldAttributes.MaterialIndex != e.NewAttributes.MaterialIndex // NOTE: this does not work when swapping around from custom doc materials, it works when you swap TO/FROM default material
)
{
ChangedObjectIds[e.RhinoObject.Id.ToString()] = 1;
_eventAggregator.GetEvent<IdleEvent>().OneTimeSubscribe(nameof(RhinoSendBinding), RunExpirationChecks);
}
}
private void OnReplaceRhinoObject(RhinoReplaceObjectEventArgs e)
{
if (!_store.IsDocumentInit)
{
return;
}
ChangedObjectIds[e.NewRhinoObject.Id.ToString()] = 1;
ChangedObjectIds[e.OldRhinoObject.Id.ToString()] = 1;
_eventAggregator.GetEvent<IdleEvent>().OneTimeSubscribe(nameof(RhinoSendBinding), RunExpirationChecks);
ChangedObjectIds[e.NewRhinoObject.Id.ToString()] = 1;
ChangedObjectIds[e.OldRhinoObject.Id.ToString()] = 1;
_idleManager.SubscribeToIdle(nameof(RhinoSendBinding), RunExpirationChecks);
});
}
public List<ISendFilter> GetSendFilters() => _sendFilters;
@@ -350,7 +342,7 @@ public sealed class RhinoSendBinding : ISendBinding
/// <summary>
/// Checks if any sender model cards contain any of the changed objects. If so, also updates the changed objects hashset for each model card - this last part is important for on send change detection.
/// </summary>
private async Task RunExpirationChecks(object _)
private async Task RunExpirationChecks()
{
// Note: added here a guard against executing this if there's no active doc present.
if (RhinoDoc.ActiveDoc == null)
@@ -0,0 +1,37 @@
using Rhino;
using Rhino.DocObjects;
using Speckle.Sdk;
namespace Speckle.Connectors.Rhino.HostApp.Properties;
/// <summary>
/// Extracts properties for rhino objects.
/// </summary>
public class PropertiesExtractor
{
public Dictionary<string, object?> GetProperties(RhinoObject rhObject)
{
Dictionary<string, object?> properties = new();
var userStrings = rhObject.Attributes.GetUserStrings();
foreach (var key in userStrings.AllKeys)
{
try
{
if (userStrings[key].StartsWith("%<"))
{
var value = RhinoApp.ParseTextField(userStrings[key], rhObject, null);
properties[key] = value;
continue;
}
}
catch (Exception ex) when (!ex.IsFatal())
{
// Shh. We can fail silently here - it's not even worth logging. I expect users will complain properties are missing.
}
properties[key] = userStrings[key];
}
return properties;
}
}
@@ -1,37 +1,33 @@
using Rhino;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Utils;
using Speckle.Connectors.RhinoShared;
namespace Speckle.Connectors.Rhino.HostApp;
public class RhinoDocumentStore : DocumentModelStore
{
private readonly IEventAggregator _eventAggregator;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
private const string SPECKLE_KEY = "Speckle_DUI3";
public override bool IsDocumentInit { get; set; } = true; // Note: because of rhino implementation details regarding expiry checking of sender cards.
public RhinoDocumentStore(IJsonSerializer jsonSerializer, IEventAggregator eventAggregator)
public RhinoDocumentStore(IJsonSerializer jsonSerializer, ITopLevelExceptionHandler topLevelExceptionHandler)
: base(jsonSerializer)
{
_eventAggregator = eventAggregator;
eventAggregator.GetEvent<BeginOpenDocument>().Subscribe(OnBeginOpenDocument);
eventAggregator.GetEvent<EndOpenDocument>().Subscribe(OnEndOpenDocument);
}
_topLevelExceptionHandler = topLevelExceptionHandler;
RhinoDoc.BeginOpenDocument += (_, _) => topLevelExceptionHandler.CatchUnhandled(() => IsDocumentInit = false);
RhinoDoc.EndOpenDocument += (_, e) =>
topLevelExceptionHandler.CatchUnhandled(() =>
{
if (e.Document == null)
{
return;
}
private void OnBeginOpenDocument(object _) => IsDocumentInit = false;
private async Task OnEndOpenDocument(DocumentOpenEventArgs e)
{
if (e.Document == null)
{
return;
}
IsDocumentInit = true;
LoadState();
await _eventAggregator.GetEvent<DocumentStoreChangedEvent>().PublishAsync(new object());
IsDocumentInit = true;
LoadState();
OnDocumentChanged();
});
}
protected override void HostAppSaveState(string modelCardState)
@@ -0,0 +1,20 @@
using Rhino;
using Speckle.Connectors.DUI.Bridge;
namespace Speckle.Connectors.Rhino.HostApp;
/// <summary>
/// Rhino Idle Manager is a helper util to manage deferred actions.
/// </summary>
public sealed class RhinoIdleManager(IIdleCallManager idleCallManager) : AppIdleManager(idleCallManager)
{
private readonly IIdleCallManager _idleCallManager = idleCallManager;
protected override void AddEvent()
{
RhinoApp.Idle += RhinoAppOnIdle;
}
private void RhinoAppOnIdle(object? sender, EventArgs e) =>
_idleCallManager.AppOnIdle(() => RhinoApp.Idle -= RhinoAppOnIdle);
}
@@ -1,4 +1,4 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging;
using Rhino;
using Rhino.DocObjects;
using Rhino.Geometry;
@@ -1,4 +1,4 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging;
using Rhino;
using Speckle.Converters.Common;
using Speckle.Converters.Rhino;
@@ -50,7 +50,10 @@ public class RhinoMaterialUnpacker
private void AddObjectIdToRenderMaterialProxy(string objectId, RenderMaterial? renderMaterial, Material? material)
{
string? renderMaterialId = renderMaterial?.Id.ToString() ?? material?.Id.ToString();
// NOTE: material ids are not the same, even if the underlying material is. the number of materials in the mat table corresponds
// with the number of objects, and each material will get a new id, even if it is THE SAME. shockingly, TY bob, material names
// are unique so we use those for identity checks rather than the material's id.
string? renderMaterialId = renderMaterial?.Name ?? material?.Name; //renderMaterial?.Id.ToString() ?? material?.Id.ToString();
if (renderMaterialId is not null)
{
@@ -120,6 +123,11 @@ public class RhinoMaterialUnpacker
// Stage 1: unpack materials from objects
foreach (RhinoObject rootObj in atomicObjects)
{
if (rootObj.Attributes.MaterialSource == ObjectMaterialSource.MaterialFromLayer)
{
continue;
}
// materials are confusing in rhino. we need both render material and material because objects can have either assigned
RenderMaterial? rhinoRenderMaterial = rootObj.GetRenderMaterial(true);
Material? rhinoMaterial = rootObj.GetMaterial(true);
@@ -61,7 +61,7 @@ public class RhinoHostObjectBuilder : IHostObjectBuilder
}
#pragma warning disable CA1506
public HostObjectBuilderResult Build(
public Task<HostObjectBuilderResult> Build(
#pragma warning restore CA1506
Base rootObject,
string projectName,
@@ -103,7 +103,10 @@ public class RhinoHostObjectBuilder : IHostObjectBuilder
if (unpackedRoot.RenderMaterialProxies != null)
{
using var _ = _activityFactory.Start("Render Materials");
_materialBaker.BakeMaterials(unpackedRoot.RenderMaterialProxies, baseLayerName);
_threadContext.RunOnMain(() =>
{
_materialBaker.BakeMaterials(unpackedRoot.RenderMaterialProxies, baseLayerName);
});
}
if (unpackedRoot.ColorProxies != null)
@@ -183,6 +186,7 @@ public class RhinoHostObjectBuilder : IHostObjectBuilder
if (conversionIds.Count == 0)
{
// TODO: add this condition to report object - same as in autocad
throw new SpeckleException($"Failed to convert object.");
}
@@ -237,7 +241,7 @@ public class RhinoHostObjectBuilder : IHostObjectBuilder
}
_converterSettings.Current.Document.Views.Redraw();
return new HostObjectBuilderResult(bakedObjectIds, conversionResults);
return Task.FromResult(new HostObjectBuilderResult(bakedObjectIds, conversionResults));
}
private void PreReceiveDeepClean(string baseLayerName)
@@ -8,6 +8,7 @@ using Speckle.Connectors.Common.Instances;
using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.DUI.Models.Card.SendFilter;
using Speckle.Connectors.Rhino.HostApp;
using Speckle.Connectors.Rhino.HostApp.Properties;
using Speckle.Converters.Common;
using Speckle.Converters.Rhino;
using Speckle.Sdk;
@@ -32,6 +33,7 @@ public class RhinoRootObjectBuilder : IRootObjectBuilder<RhinoObject>
private readonly RhinoGroupUnpacker _groupUnpacker;
private readonly RhinoMaterialUnpacker _materialUnpacker;
private readonly RhinoColorUnpacker _colorUnpacker;
private readonly PropertiesExtractor _propertiesExtractor;
private readonly ILogger<RhinoRootObjectBuilder> _logger;
private readonly ISdkActivityFactory _activityFactory;
@@ -44,6 +46,7 @@ public class RhinoRootObjectBuilder : IRootObjectBuilder<RhinoObject>
RhinoGroupUnpacker groupUnpacker,
RhinoMaterialUnpacker materialUnpacker,
RhinoColorUnpacker colorUnpacker,
PropertiesExtractor propertiesExtractor,
ILogger<RhinoRootObjectBuilder> logger,
ISdkActivityFactory activityFactory
)
@@ -56,11 +59,12 @@ public class RhinoRootObjectBuilder : IRootObjectBuilder<RhinoObject>
_rootToSpeckleConverter = rootToSpeckleConverter;
_materialUnpacker = materialUnpacker;
_colorUnpacker = colorUnpacker;
_propertiesExtractor = propertiesExtractor;
_logger = logger;
_activityFactory = activityFactory;
}
public async Task<RootObjectBuilderResult> BuildAsync(
public async Task<RootObjectBuilderResult> Build(
IReadOnlyList<RhinoObject> rhinoObjects,
SendInfo sendInfo,
IProgress<CardProgress> onOperationProgressed,
@@ -165,6 +169,19 @@ public class RhinoRootObjectBuilder : IRootObjectBuilder<RhinoObject>
converted.applicationId = applicationId;
}
// add name and properties
// POC: this is NOT done in the converter because we don't have a RootToSpeckle converter that captures all top level converters
if (!string.IsNullOrEmpty(rhinoObject.Attributes.Name))
{
converted["name"] = rhinoObject.Attributes.Name;
}
var properties = _propertiesExtractor.GetProperties(rhinoObject);
if (properties.Count > 0)
{
converted["properties"] = properties;
}
// add to host
collectionHost.elements.Add(converted);
@@ -2,9 +2,7 @@ using Microsoft.Extensions.DependencyInjection;
using Rhino.PlugIns;
using Speckle.Connectors.Common;
using Speckle.Connectors.DUI;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.Rhino.DependencyInjection;
using Speckle.Connectors.RhinoShared;
using Speckle.Converters.Rhino;
using Speckle.Sdk;
using Speckle.Sdk.Host;
@@ -53,7 +51,6 @@ public class SpeckleConnectorsRhinoPlugin : PlugIn
// but the Rhino connector has `.rhp` as it is extension.
Container = services.BuildServiceProvider();
RhinoEvents.Register(Container.GetRequiredService<IEventAggregator>());
Container.UseDUI();
return LoadReturnCode.Success;
@@ -10,11 +10,13 @@ using Speckle.Connectors.Common.Operations;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Models.Card.SendFilter;
using Speckle.Connectors.DUI.WebView;
using Speckle.Connectors.Rhino.Bindings;
using Speckle.Connectors.Rhino.Filters;
using Speckle.Connectors.Rhino.HostApp;
using Speckle.Connectors.Rhino.HostApp.Properties;
using Speckle.Connectors.Rhino.Operations.Receive;
using Speckle.Connectors.Rhino.Operations.Send;
using Speckle.Connectors.Rhino.Plugin;
@@ -52,6 +54,7 @@ public static class ServiceRegistration
// register send conversion cache
serviceCollection.AddSingleton<ISendConversionCache, SendConversionCache>();
serviceCollection.AddSingleton<IAppIdleManager, RhinoIdleManager>();
// register send operation and dependencies
serviceCollection.AddScoped<SendOperation<RhinoObject>>();
@@ -79,6 +82,8 @@ public static class ServiceRegistration
serviceCollection.AddScoped<RhinoColorBaker>();
serviceCollection.AddScoped<RhinoColorUnpacker>();
serviceCollection.AddScoped<PropertiesExtractor>();
// operation progress manager
serviceCollection.AddSingleton<IOperationProgressManager, OperationProgressManager>();
}
@@ -1,87 +1,87 @@
using Rhino;
using Rhino.Commands;
using Rhino.DocObjects;
using Rhino.DocObjects.Tables;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
namespace Speckle.Connectors.RhinoShared;
public class BeginOpenDocument(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<DocumentOpenEventArgs>(threadContext, exceptionHandler);
public class EndOpenDocument(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<DocumentOpenEventArgs>(threadContext, exceptionHandler);
public class SelectObjects(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<RhinoObjectSelectionEventArgs>(threadContext, exceptionHandler);
public class DeselectObjects(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<RhinoObjectSelectionEventArgs>(threadContext, exceptionHandler);
public class DeselectAllObjects(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<RhinoDeselectAllObjectsEventArgs>(threadContext, exceptionHandler);
public class ActiveDocumentChanged(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<DocumentEventArgs>(threadContext, exceptionHandler);
public class DocumentPropertiesChanged(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<DocumentEventArgs>(threadContext, exceptionHandler);
public class AddRhinoObject(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<RhinoObjectEventArgs>(threadContext, exceptionHandler);
public class DeleteRhinoObject(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<RhinoObjectEventArgs>(threadContext, exceptionHandler);
public class RenderMaterialsTableEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<RhinoDoc.RenderContentTableEventArgs>(threadContext, exceptionHandler);
public class MaterialTableEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<MaterialTableEventArgs>(threadContext, exceptionHandler);
public class ModifyObjectAttributes(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<RhinoModifyObjectAttributesEventArgs>(threadContext, exceptionHandler);
public class ReplaceRhinoObject(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<RhinoReplaceObjectEventArgs>(threadContext, exceptionHandler);
public class GroupTableEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<GroupTableEventArgs>(threadContext, exceptionHandler);
public class LayerTableEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<LayerTableEventArgs>(threadContext, exceptionHandler);
public class BeginCommandEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
: ThreadedEvent<CommandEventArgs>(threadContext, exceptionHandler);
public static class RhinoEvents
{
public static void Register(IEventAggregator eventAggregator)
{
RhinoApp.Idle += async (_, e) => await eventAggregator.GetEvent<IdleEvent>().PublishAsync(e);
RhinoDoc.BeginOpenDocument += async (_, e) => await eventAggregator.GetEvent<BeginOpenDocument>().PublishAsync(e);
RhinoDoc.EndOpenDocument += async (_, e) => await eventAggregator.GetEvent<EndOpenDocument>().PublishAsync(e);
RhinoDoc.SelectObjects += async (_, e) => await eventAggregator.GetEvent<SelectObjects>().PublishAsync(e);
RhinoDoc.DeselectObjects += async (_, e) => await eventAggregator.GetEvent<DeselectObjects>().PublishAsync(e);
RhinoDoc.DeselectAllObjects += async (_, e) => await eventAggregator.GetEvent<DeselectAllObjects>().PublishAsync(e);
RhinoDoc.ActiveDocumentChanged += async (_, e) =>
await eventAggregator.GetEvent<ActiveDocumentChanged>().PublishAsync(e);
RhinoDoc.DocumentPropertiesChanged += async (_, e) =>
await eventAggregator.GetEvent<DocumentPropertiesChanged>().PublishAsync(e);
RhinoDoc.AddRhinoObject += async (_, e) => await eventAggregator.GetEvent<AddRhinoObject>().PublishAsync(e);
RhinoDoc.DeleteRhinoObject += async (_, e) => await eventAggregator.GetEvent<DeleteRhinoObject>().PublishAsync(e);
RhinoDoc.RenderMaterialsTableEvent += async (_, e) =>
await eventAggregator.GetEvent<RenderMaterialsTableEvent>().PublishAsync(e);
RhinoDoc.MaterialTableEvent += async (_, e) => await eventAggregator.GetEvent<MaterialTableEvent>().PublishAsync(e);
RhinoDoc.ModifyObjectAttributes += async (_, e) =>
await eventAggregator.GetEvent<ModifyObjectAttributes>().PublishAsync(e);
RhinoDoc.ReplaceRhinoObject += async (_, e) => await eventAggregator.GetEvent<ReplaceRhinoObject>().PublishAsync(e);
RhinoDoc.GroupTableEvent += async (_, e) => await eventAggregator.GetEvent<GroupTableEvent>().PublishAsync(e);
RhinoDoc.LayerTableEvent += async (_, e) => await eventAggregator.GetEvent<LayerTableEvent>().PublishAsync(e);
Command.BeginCommand += async (_, e) => await eventAggregator.GetEvent<BeginCommandEvent>().PublishAsync(e);
}
}
// using Rhino;
// using Rhino.Commands;
// using Rhino.DocObjects;
// using Rhino.DocObjects.Tables;
// using Speckle.Connectors.Common.Threading;
// using Speckle.Connectors.DUI.Bridge;
// using Speckle.Connectors.DUI.Eventing;
//
// namespace Speckle.Connectors.RhinoShared;
//
// public class BeginOpenDocument(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
// : ThreadedEvent<DocumentOpenEventArgs>(threadContext, exceptionHandler);
//
// public class EndOpenDocument(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
// : ThreadedEvent<DocumentOpenEventArgs>(threadContext, exceptionHandler);
//
// public class SelectObjects(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
// : ThreadedEvent<RhinoObjectSelectionEventArgs>(threadContext, exceptionHandler);
//
// public class DeselectObjects(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
// : ThreadedEvent<RhinoObjectSelectionEventArgs>(threadContext, exceptionHandler);
//
// public class DeselectAllObjects(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
// : ThreadedEvent<RhinoDeselectAllObjectsEventArgs>(threadContext, exceptionHandler);
//
// public class ActiveDocumentChanged(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
// : ThreadedEvent<DocumentEventArgs>(threadContext, exceptionHandler);
//
// public class DocumentPropertiesChanged(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
// : ThreadedEvent<DocumentEventArgs>(threadContext, exceptionHandler);
//
// public class AddRhinoObject(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
// : ThreadedEvent<RhinoObjectEventArgs>(threadContext, exceptionHandler);
//
// public class DeleteRhinoObject(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
// : ThreadedEvent<RhinoObjectEventArgs>(threadContext, exceptionHandler);
//
// public class RenderMaterialsTableEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
// : ThreadedEvent<RhinoDoc.RenderContentTableEventArgs>(threadContext, exceptionHandler);
//
// public class MaterialTableEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
// : ThreadedEvent<MaterialTableEventArgs>(threadContext, exceptionHandler);
//
// public class ModifyObjectAttributes(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
// : ThreadedEvent<RhinoModifyObjectAttributesEventArgs>(threadContext, exceptionHandler);
//
// public class ReplaceRhinoObject(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
// : ThreadedEvent<RhinoReplaceObjectEventArgs>(threadContext, exceptionHandler);
//
// public class GroupTableEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
// : ThreadedEvent<GroupTableEventArgs>(threadContext, exceptionHandler);
//
// public class LayerTableEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
// : ThreadedEvent<LayerTableEventArgs>(threadContext, exceptionHandler);
//
// public class BeginCommandEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
// : ThreadedEvent<CommandEventArgs>(threadContext, exceptionHandler);
//
// public static class RhinoEvents
// {
// public static void Register(IEventAggregator eventAggregator)
// {
// RhinoApp.Idle += async (_, e) => await eventAggregator.GetEvent<IdleEvent>().PublishAsync(e);
//
// RhinoDoc.BeginOpenDocument += async (_, e) => await eventAggregator.GetEvent<BeginOpenDocument>().PublishAsync(e);
// RhinoDoc.EndOpenDocument += async (_, e) => await eventAggregator.GetEvent<EndOpenDocument>().PublishAsync(e);
// RhinoDoc.SelectObjects += async (_, e) => await eventAggregator.GetEvent<SelectObjects>().PublishAsync(e);
// RhinoDoc.DeselectObjects += async (_, e) => await eventAggregator.GetEvent<DeselectObjects>().PublishAsync(e);
// RhinoDoc.DeselectAllObjects += async (_, e) => await eventAggregator.GetEvent<DeselectAllObjects>().PublishAsync(e);
// RhinoDoc.ActiveDocumentChanged += async (_, e) =>
// await eventAggregator.GetEvent<ActiveDocumentChanged>().PublishAsync(e);
// RhinoDoc.DocumentPropertiesChanged += async (_, e) =>
// await eventAggregator.GetEvent<DocumentPropertiesChanged>().PublishAsync(e);
// RhinoDoc.AddRhinoObject += async (_, e) => await eventAggregator.GetEvent<AddRhinoObject>().PublishAsync(e);
// RhinoDoc.DeleteRhinoObject += async (_, e) => await eventAggregator.GetEvent<DeleteRhinoObject>().PublishAsync(e);
// RhinoDoc.RenderMaterialsTableEvent += async (_, e) =>
// await eventAggregator.GetEvent<RenderMaterialsTableEvent>().PublishAsync(e);
// RhinoDoc.MaterialTableEvent += async (_, e) => await eventAggregator.GetEvent<MaterialTableEvent>().PublishAsync(e);
// RhinoDoc.ModifyObjectAttributes += async (_, e) =>
// await eventAggregator.GetEvent<ModifyObjectAttributes>().PublishAsync(e);
// RhinoDoc.ReplaceRhinoObject += async (_, e) => await eventAggregator.GetEvent<ReplaceRhinoObject>().PublishAsync(e);
// RhinoDoc.GroupTableEvent += async (_, e) => await eventAggregator.GetEvent<GroupTableEvent>().PublishAsync(e);
// RhinoDoc.LayerTableEvent += async (_, e) => await eventAggregator.GetEvent<LayerTableEvent>().PublishAsync(e);
//
// Command.BeginCommand += async (_, e) => await eventAggregator.GetEvent<BeginCommandEvent>().PublishAsync(e);
// }
// }
@@ -21,6 +21,8 @@
<Compile Include="$(MSBuildThisFileDirectory)Bindings\RhinoReceiveBinding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bindings\RhinoSendBinding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bindings\RhinoSelectionBinding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\Properties\PropertiesExtractor.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HostApp\RhinoIdleManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)RhinoEvents.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Registration\ServiceRegistration.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\BoundingBox.cs" />
+23 -14
View File
@@ -1,26 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<Target AfterTargets="Build" Name="AfterBuildTekla" Condition="'$(TeklaVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
<Target AfterTargets="Build" Name="AfterBuildTekla" Condition="'$(TeklaVersion)' != '' And '$(ContinuousIntegrationBuild)' != 'true'">
<ItemGroup>
<TeklaDlls Include="$(TargetDir)\**\*.*" Exclude="$(TargetDir)*.bmp" />
<TeklaBmp Include="$(TargetDir)\Assets\et_element_Speckle.bmp"/>
<TeklaBmp Include="$(TargetDir)\Resources\et_element_Speckle.bmp"/>
</ItemGroup>
<Message Text="Tekla Version $(TeklaVersion)" Importance="high"/>
<!-- Delete win-arm64 folder if it exists -->
<RemoveDir Condition="Exists('$(ProgramData)\Trimble\Tekla Structures\$(TeklaVersion).0\Environments\common\extensions\Speckle3TeklaStructures\runtimes\win-arm64\native')"
Directories="$(ProgramData)\Trimble\Tekla Structures\$(TeklaVersion).0\Environments\common\extensions\Speckle3TeklaStructures\runtimes\win-arm64\native" />
<RemoveDir Condition="Exists('C:\TeklaStructures\$(TeklaVersion).0\Environments\common\extensions\Speckle3TeklaStructures\runtimes\win-arm64\native')"
Directories="C:\TeklaStructures\$(TeklaVersion).0\Environments\common\extensions\Speckle3TeklaStructures\runtimes\win-arm64\native" />
<!-- ProgramData path -->
<Copy Condition="Exists('$(ProgramData)\Trimble\Tekla Structures\$(TeklaVersion).0')"
DestinationFolder="$(ProgramData)\Trimble\Tekla Structures\$(TeklaVersion).0\Environments\common\extensions\Speckle3TeklaStructures\%(RecursiveDir)"
SourceFiles="@(TeklaDlls)" />
<ItemGroup Condition="'$(Configuration)' == 'Debug'">
<Copy Condition="Exists('$(ProgramData)\Trimble\Tekla Structures\$(TeklaVersion).0')"
DestinationFolder="$(ProgramData)\Trimble\Tekla Structures\$(TeklaVersion).0\Bitmaps"
SourceFiles="@(TeklaBmp)" />
</ItemGroup>
<Copy Condition="Exists('C:\TeklaStructures\2024.0')"
DestinationFolder="C:\TeklaStructures\2024.0\Environments\common\extensions\Speckle3TeklaStructures\%(RecursiveDir)"
<Copy Condition="Exists('$(ProgramData)\Trimble\Tekla Structures\$(TeklaVersion).0')"
DestinationFolder="$(ProgramData)\Trimble\Tekla Structures\$(TeklaVersion).0\Bitmaps"
SourceFiles="@(TeklaBmp)" />
<!-- TeklaStructures direct path -->
<Copy Condition="Exists('C:\TeklaStructures\$(TeklaVersion).0')"
DestinationFolder="C:\TeklaStructures\$(TeklaVersion).0\Environments\common\extensions\Speckle3TeklaStructures\%(RecursiveDir)"
SourceFiles="@(TeklaDlls)" />
<ItemGroup Condition="'$(Configuration)' == 'Debug'">
<Copy Condition="Exists('C:\TeklaStructures\2024.0')"
DestinationFolder="$(ProgramFiles)\TeklaStructures\2024.0\bin\Env\Bitmaps"
SourceFiles="@(TeklaBmp)" />
</ItemGroup>
<Copy Condition="Exists('C:\TeklaStructures\$(TeklaVersion).0')"
DestinationFolder="C:\TeklaStructures\$(TeklaVersion).0\Bitmaps"
SourceFiles="@(TeklaBmp)" />
</Target>
</Project>
@@ -3,6 +3,7 @@
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TeklaVersion>2023</TeklaVersion>
<UseWpf>true</UseWpf>
<DefineConstants>$(DefineConstants);TEKLA2023</DefineConstants>
@@ -325,9 +325,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -335,8 +335,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui.webview": {
@@ -362,7 +362,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"LibTessDotNet": {
@@ -412,35 +412,48 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "[5.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.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
},
".NETFramework,Version=v4.8/win-x64": {
"SQLitePCLRaw.lib.e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
},
"Microsoft.Web.WebView2": {
"type": "CentralTransitive",
"requested": "[1.0.1938.49, )",
"resolved": "1.0.1938.49",
"contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
}
}
}
@@ -406,9 +406,9 @@
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Speckle.Connectors.Logging": "[1.0.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )",
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui": {
@@ -416,8 +416,8 @@
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Connectors.Common": "[1.0.0, )",
"Speckle.Sdk": "[3.1.0-dev.255, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.255, )"
"Speckle.Sdk": "[3.1.0-dev.270, )",
"Speckle.Sdk.Dependencies": "[3.1.0-dev.270, )"
}
},
"speckle.connectors.dui.webview": {
@@ -443,7 +443,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
"Speckle.Objects": "[3.1.0-dev.255, )"
"Speckle.Objects": "[3.1.0-dev.270, )"
}
},
"LibTessDotNet": {
@@ -493,35 +493,35 @@
},
"Speckle.Objects": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "0S9YVdu5nx7SYS0y5Gq1nwCbxfYB2UxsUUCskaGmzRAm+QzHGqCLYHgadz7Sw5mNAF3bOTLVrOYMzyLAWFWxJA==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "9lCAC/Hsz2cbTVjwgHixLX2R7TNF8C90xd6rm0LsFPRgx926k15ep4k9q9wXHrblmP5Mc34qD1x9cwrSXzCiaA==",
"dependencies": {
"Speckle.Sdk": "3.1.0-dev.255"
"Speckle.Sdk": "3.1.0-dev.270"
}
},
"Speckle.Sdk": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "TsFpIv8ipvOD/r0se1XmcNPo7t5dWVadwV32Z6vUqoW3s94VIE54/ZTHNkRCEYHFhfOyTcFfbLegiei+0D13bQ==",
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "dzcd3A5jn4KpcgC8a1VuoLt1RwDvUfazmi5uKbiXuGFuxXMkGbZXr+xmXbyDL1C0HQqm+vZpOBcdSea/Q62/0g==",
"dependencies": {
"GraphQL.Client": "6.0.0",
"Microsoft.Bcl.AsyncInterfaces": "[5.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.0.1",
"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.1.0-dev.255"
"Speckle.Sdk.Dependencies": "3.1.0-dev.270"
}
},
"Speckle.Sdk.Dependencies": {
"type": "CentralTransitive",
"requested": "[3.1.0-dev.255, )",
"resolved": "3.1.0-dev.255",
"contentHash": "koFeWc/EB2XrMH2aKl2Hqwrqk/fAGYEVKgxFlFpnEAsbZf7Kk57gBQ3ViV5l6X9vqMHGWFc4dWUp24diq/XPtQ=="
"requested": "[3.1.0-dev.270, )",
"resolved": "3.1.0-dev.270",
"contentHash": "4nkNrmfNwnI+clIgZgBn+M42ISstQs1GrZH/6F97cmU0uczanVy0JTw011vKp5pPGmwZx8QFxVXbvwV5Ofx47A=="
}
}
}

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