Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c671b151b4 | |||
| 600c361d9a | |||
| e8cff89433 | |||
| 2a4647a1b7 | |||
| bf97d8c029 | |||
| 679f5bafb7 | |||
| 1f35ee0101 | |||
| 63c99d3086 | |||
| 7a0acd6c07 | |||
| 6853fa79e8 | |||
| 94c04f67b0 | |||
| f15612034e | |||
| 7c5a3cba60 | |||
| 0cec4095e2 | |||
| 46ab7d6110 | |||
| 169cfd6123 | |||
| 83b7280758 | |||
| 30ea9858c6 |
@@ -6,7 +6,6 @@ public static class Consts
|
||||
|
||||
public static readonly ProjectGroup[] ProjectGroups =
|
||||
{
|
||||
new("arcgis", [new("Connectors/ArcGIS/Speckle.Connectors.ArcGIS3", "net6.0-windows")]),
|
||||
new(
|
||||
"rhino",
|
||||
[
|
||||
|
||||
@@ -75,7 +75,7 @@ public static class Solutions
|
||||
connectors.AddProject("..\\speckle-sharp-sdk\\src\\Speckle.Sdk.Dependencies\\Speckle.Sdk.Dependencies.csproj");
|
||||
var sln = Path.Combine("C:\\Users\\adam\\Git\\speckle-sharp-connectors", "Local.slnx");
|
||||
await SolutionSerializers.SlnXml.SaveAsync(sln, connectors, default);
|
||||
sln = Path.Combine("C:\\Users\\adam\\Git\\speckle-sharp-connectors", "Local.sln");
|
||||
sln = Path.Combine(Environment.CurrentDirectory, "Local.sln");
|
||||
await SolutionSerializers.SlnFileV12.SaveAsync(sln, connectors, default);
|
||||
}
|
||||
|
||||
@@ -95,13 +95,13 @@ public static class Solutions
|
||||
{
|
||||
connectors.RemoveFolder(folderToRemove);
|
||||
}
|
||||
var sln = Path.Combine("C:\\Users\\adam\\Git\\speckle-sharp-connectors", $"Speckle.{slug}.slnx");
|
||||
var sln = Path.Combine(Environment.CurrentDirectory, $"Speckle.{slug}.slnx");
|
||||
await SolutionSerializers.SlnXml.SaveAsync(sln, connectors, default);
|
||||
}
|
||||
|
||||
public static async Task<SolutionModel> GetFullSlnx()
|
||||
{
|
||||
var connectorsSln = Path.Combine("C:\\Users\\adam\\Git\\speckle-sharp-connectors", "Speckle.Connectors.slnx");
|
||||
var connectorsSln = Path.Combine(Environment.CurrentDirectory, "Speckle.Connectors.slnx");
|
||||
return await SolutionSerializers.SlnXml.OpenAsync(connectorsSln, default);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
using ArcGIS.Desktop.Core;
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Common.Cancellation;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Logging;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.DUI.Models.Card;
|
||||
using Speckle.Converters.ArcGIS3;
|
||||
using Speckle.Converters.ArcGIS3.Utils;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Sdk;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Bindings;
|
||||
|
||||
public sealed class ArcGISReceiveBinding : IReceiveBinding
|
||||
{
|
||||
public string Name { get; } = "receiveBinding";
|
||||
private readonly ICancellationManager _cancellationManager;
|
||||
private readonly DocumentModelStore _store;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly IOperationProgressManager _operationProgressManager;
|
||||
private readonly ILogger<ArcGISReceiveBinding> _logger;
|
||||
private readonly IArcGISConversionSettingsFactory _arcGISConversionSettingsFactory;
|
||||
|
||||
private ReceiveBindingUICommands Commands { get; }
|
||||
public IBrowserBridge Parent { get; }
|
||||
|
||||
public ArcGISReceiveBinding(
|
||||
DocumentModelStore store,
|
||||
IBrowserBridge parent,
|
||||
ICancellationManager cancellationManager,
|
||||
IServiceProvider serviceProvider,
|
||||
IOperationProgressManager operationProgressManager,
|
||||
ILogger<ArcGISReceiveBinding> logger,
|
||||
IArcGISConversionSettingsFactory arcGisConversionSettingsFactory
|
||||
)
|
||||
{
|
||||
_store = store;
|
||||
_cancellationManager = cancellationManager;
|
||||
Parent = parent;
|
||||
Commands = new ReceiveBindingUICommands(parent);
|
||||
_serviceProvider = serviceProvider;
|
||||
_operationProgressManager = operationProgressManager;
|
||||
_logger = logger;
|
||||
_arcGISConversionSettingsFactory = arcGisConversionSettingsFactory;
|
||||
}
|
||||
|
||||
public async Task Receive(string modelCardId)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get receiver card
|
||||
if (_store.GetModelById(modelCardId) is not ReceiverModelCard modelCard)
|
||||
{
|
||||
// Handle as GLOBAL ERROR at BrowserBridge
|
||||
throw new InvalidOperationException("No download model card was found.");
|
||||
}
|
||||
|
||||
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)
|
||||
)
|
||||
);
|
||||
// Receive host objects
|
||||
var receiveOperationResults = await scope
|
||||
.ServiceProvider.GetRequiredService<ReceiveOperation>()
|
||||
.Execute(
|
||||
modelCard.GetReceiveInfo("ArcGIS"), // POC: get host app name from settings? same for GetSendInfo
|
||||
_operationProgressManager.CreateOperationProgressEventHandler(Parent, modelCardId, cancellationItem.Token),
|
||||
cancellationItem.Token
|
||||
);
|
||||
|
||||
modelCard.BakedObjectIds = receiveOperationResults.BakedObjectIds.ToList();
|
||||
await Commands.SetModelReceiveResult(
|
||||
modelCardId,
|
||||
receiveOperationResults.BakedObjectIds,
|
||||
receiveOperationResults.ConversionResults
|
||||
);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// SWALLOW -> UI handles it immediately, so we do not need to handle anything for now!
|
||||
// Idea for later -> when cancel called, create promise from UI to solve it later with this catch block.
|
||||
// So have 3 state on UI -> Cancellation clicked -> Cancelling -> Cancelled
|
||||
return;
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal()) // UX reasons - we will report operation exceptions as model card error. We may change this later when we have more exception documentation
|
||||
{
|
||||
_logger.LogModelCardHandledError(ex);
|
||||
await Commands.SetModelError(modelCardId, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void CancelReceive(string modelCardId) => _cancellationManager.CancelOperation(modelCardId);
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using ArcGIS.Desktop.Mapping.Events;
|
||||
using Speckle.Connectors.ArcGIS.Utils;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Bindings;
|
||||
|
||||
public class ArcGISSelectionBinding : ISelectionBinding
|
||||
{
|
||||
private readonly MapMembersUtils _mapMemberUtils;
|
||||
public string Name => "selectionBinding";
|
||||
public IBrowserBridge Parent { get; }
|
||||
|
||||
public ArcGISSelectionBinding(
|
||||
IBrowserBridge parent,
|
||||
MapMembersUtils mapMemberUtils,
|
||||
ITopLevelExceptionHandler topLevelExceptionHandler
|
||||
)
|
||||
{
|
||||
_mapMemberUtils = mapMemberUtils;
|
||||
Parent = parent;
|
||||
|
||||
// example: https://github.com/Esri/arcgis-pro-sdk-community-samples/blob/master/Map-Authoring/QueryBuilderControl/DefinitionQueryDockPaneViewModel.cs
|
||||
// MapViewEventArgs args = new(MapView.Active);
|
||||
TOCSelectionChangedEvent.Subscribe(_ => topLevelExceptionHandler.CatchUnhandled(OnSelectionChanged), true);
|
||||
}
|
||||
|
||||
private void OnSelectionChanged()
|
||||
{
|
||||
SelectionInfo selInfo = GetSelection();
|
||||
Parent.Send(SelectionBindingEvents.SET_SELECTION, selInfo);
|
||||
}
|
||||
|
||||
private void GetLayersFromGroup(GroupLayer group, List<MapMember> nestedLayers)
|
||||
{
|
||||
nestedLayers.Add(group);
|
||||
foreach (MapMember member in group.Layers)
|
||||
{
|
||||
if (member is GroupLayer subGroup)
|
||||
{
|
||||
GetLayersFromGroup(subGroup, nestedLayers);
|
||||
}
|
||||
else
|
||||
{
|
||||
nestedLayers.Add(member);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SelectionInfo GetSelection()
|
||||
{
|
||||
MapView mapView = MapView.Active;
|
||||
List<MapMember> selectedMembers = new();
|
||||
selectedMembers.AddRange(mapView.GetSelectedLayers());
|
||||
selectedMembers.AddRange(mapView.GetSelectedStandaloneTables());
|
||||
|
||||
List<MapMember> allNestedMembers = new();
|
||||
var layerMapMembers = _mapMemberUtils.UnpackMapLayers(selectedMembers);
|
||||
allNestedMembers.AddRange(layerMapMembers);
|
||||
|
||||
List<string> objectTypes = allNestedMembers
|
||||
.Select(o => o.GetType().ToString().Split(".").Last())
|
||||
.Distinct()
|
||||
.ToList();
|
||||
return new SelectionInfo(
|
||||
allNestedMembers.Select(x => x.URI).ToList(),
|
||||
$"{allNestedMembers.Count} layers ({string.Join(", ", objectTypes)})"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,483 +0,0 @@
|
||||
using System.Collections.Concurrent;
|
||||
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;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.ArcGIS.Filters;
|
||||
using Speckle.Connectors.ArcGIS.Utils;
|
||||
using Speckle.Connectors.Common.Caching;
|
||||
using Speckle.Connectors.Common.Cancellation;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Connectors.Common.Threading;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Exceptions;
|
||||
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.Converters.ArcGIS3;
|
||||
using Speckle.Converters.ArcGIS3.Utils;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Common;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Bindings;
|
||||
|
||||
public sealed class ArcGISSendBinding : ISendBinding
|
||||
{
|
||||
public string Name => "sendBinding";
|
||||
public SendBindingUICommands Commands { get; }
|
||||
public IBrowserBridge Parent { get; }
|
||||
|
||||
private readonly DocumentModelStore _store;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly List<ISendFilter> _sendFilters;
|
||||
private readonly ICancellationManager _cancellationManager;
|
||||
private readonly ISendConversionCache _sendConversionCache;
|
||||
private readonly IOperationProgressManager _operationProgressManager;
|
||||
private readonly ILogger<ArcGISSendBinding> _logger;
|
||||
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
|
||||
private readonly IArcGISConversionSettingsFactory _arcGISConversionSettingsFactory;
|
||||
private readonly IThreadContext _threadContext;
|
||||
private readonly ISpeckleApplication _speckleApplication;
|
||||
|
||||
/// <summary>
|
||||
/// Used internally to aggregate the changed objects' id. Note we're using a concurrent dictionary here as the expiry check method is not thread safe, and this was causing problems. See:
|
||||
/// [CNX-202: Unhandled Exception Occurred when receiving in Rhino](https://linear.app/speckle/issue/CNX-202/unhandled-exception-occurred-when-receiving-in-rhino)
|
||||
/// As to why a concurrent dictionary, it's because it's the cheapest/easiest way to do so.
|
||||
/// https://stackoverflow.com/questions/18922985/concurrent-hashsett-in-net-framework
|
||||
/// </summary>
|
||||
private ConcurrentDictionary<string, byte> ChangedObjectIds { get; set; } = new();
|
||||
|
||||
private List<FeatureLayer> SubscribedLayers { get; set; } = new();
|
||||
private List<StandaloneTable> SubscribedTables { get; set; } = new();
|
||||
private readonly MapMembersUtils _mapMemberUtils;
|
||||
|
||||
public ArcGISSendBinding(
|
||||
DocumentModelStore store,
|
||||
IBrowserBridge parent,
|
||||
IEnumerable<ISendFilter> sendFilters,
|
||||
IServiceProvider serviceProvider,
|
||||
ICancellationManager cancellationManager,
|
||||
ISendConversionCache sendConversionCache,
|
||||
IOperationProgressManager operationProgressManager,
|
||||
ILogger<ArcGISSendBinding> logger,
|
||||
IArcGISConversionSettingsFactory arcGisConversionSettingsFactory,
|
||||
MapMembersUtils mapMemberUtils,
|
||||
IThreadContext threadContext,
|
||||
ISpeckleApplication speckleApplication,
|
||||
ITopLevelExceptionHandler topLevelExceptionHandler
|
||||
)
|
||||
{
|
||||
_store = store;
|
||||
_serviceProvider = serviceProvider;
|
||||
_sendFilters = sendFilters.ToList();
|
||||
_cancellationManager = cancellationManager;
|
||||
_sendConversionCache = sendConversionCache;
|
||||
_operationProgressManager = operationProgressManager;
|
||||
_logger = logger;
|
||||
_topLevelExceptionHandler = topLevelExceptionHandler;
|
||||
_arcGISConversionSettingsFactory = arcGisConversionSettingsFactory;
|
||||
_mapMemberUtils = mapMemberUtils;
|
||||
_threadContext = threadContext;
|
||||
_speckleApplication = speckleApplication;
|
||||
|
||||
Parent = parent;
|
||||
Commands = new SendBindingUICommands(parent);
|
||||
SubscribeToArcGISEvents();
|
||||
_store.DocumentChanged += (_, _) =>
|
||||
{
|
||||
_sendConversionCache.ClearCache();
|
||||
};
|
||||
}
|
||||
|
||||
private void OnDocumentStoreChangedEvent(object _) => _sendConversionCache.ClearCache();
|
||||
|
||||
private void SubscribeToArcGISEvents()
|
||||
{
|
||||
LayersRemovedEvent.Subscribe(
|
||||
a =>
|
||||
_topLevelExceptionHandler.FireAndForget(
|
||||
async () => await QueuedTask.Run(async () => await GetIdsForLayersRemovedEvent(a))
|
||||
),
|
||||
true
|
||||
);
|
||||
|
||||
StandaloneTablesRemovedEvent.Subscribe(
|
||||
a =>
|
||||
_topLevelExceptionHandler.FireAndForget(
|
||||
async () => await QueuedTask.Run(async () => await GetIdsForStandaloneTablesRemovedEvent(a))
|
||||
),
|
||||
true
|
||||
);
|
||||
|
||||
MapPropertyChangedEvent.Subscribe(
|
||||
a =>
|
||||
_topLevelExceptionHandler.FireAndForget(
|
||||
async () => await QueuedTask.Run(async () => await GetIdsForMapPropertyChangedEvent(a))
|
||||
),
|
||||
true
|
||||
); // Map units, CRS etc.
|
||||
|
||||
MapMemberPropertiesChangedEvent.Subscribe(
|
||||
a =>
|
||||
_topLevelExceptionHandler.FireAndForget(
|
||||
async () => await QueuedTask.Run(async () => await GetIdsForMapMemberPropertiesChangedEvent(a))
|
||||
),
|
||||
true
|
||||
); // e.g. Layer name
|
||||
|
||||
ActiveMapViewChangedEvent.Subscribe(
|
||||
_ =>
|
||||
_topLevelExceptionHandler.FireAndForget(async () =>
|
||||
{
|
||||
await QueuedTask.Run(SubscribeToMapMembersDataSourceChange);
|
||||
}),
|
||||
true
|
||||
);
|
||||
|
||||
/*
|
||||
LayersAddedEvent.Subscribe(a => _topLevelExceptionHandler.CatchUnhandled(() => GetIdsForLayersAddedEvent(a)), true);
|
||||
|
||||
StandaloneTablesAddedEvent.Subscribe(
|
||||
a => _topLevelExceptionHandler.CatchUnhandled(() => GetIdsForStandaloneTablesAddedEvent(a)),
|
||||
true
|
||||
);
|
||||
*/
|
||||
}
|
||||
|
||||
private void SubscribeToMapMembersDataSourceChange()
|
||||
{
|
||||
if (MapView.Active == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// subscribe to layers
|
||||
foreach (Layer layer in MapView.Active.Map.Layers)
|
||||
{
|
||||
if (layer is FeatureLayer featureLayer)
|
||||
{
|
||||
SubscribeToFeatureLayerDataSourceChange(featureLayer);
|
||||
}
|
||||
}
|
||||
// subscribe to tables
|
||||
foreach (StandaloneTable table in MapView.Active.Map.StandaloneTables)
|
||||
{
|
||||
SubscribeToTableDataSourceChange(table);
|
||||
}
|
||||
}
|
||||
|
||||
private void SubscribeToFeatureLayerDataSourceChange(FeatureLayer layer)
|
||||
{
|
||||
if (SubscribedLayers.Contains(layer))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Table layerTable = layer.GetTable();
|
||||
if (layerTable != null)
|
||||
{
|
||||
SubscribeToAnyDataSourceChange(layerTable);
|
||||
SubscribedLayers.Add(layer);
|
||||
}
|
||||
}
|
||||
|
||||
private void SubscribeToTableDataSourceChange(StandaloneTable table)
|
||||
{
|
||||
if (SubscribedTables.Contains(table))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Table layerTable = table.GetTable();
|
||||
if (layerTable != null)
|
||||
{
|
||||
SubscribeToAnyDataSourceChange(layerTable);
|
||||
SubscribedTables.Add(table);
|
||||
}
|
||||
}
|
||||
|
||||
private void SubscribeToAnyDataSourceChange(Table layerTable)
|
||||
{
|
||||
RowCreatedEvent.Subscribe(
|
||||
(args) =>
|
||||
_topLevelExceptionHandler.FireAndForget(async () =>
|
||||
{
|
||||
await OnRowChanged(args);
|
||||
}),
|
||||
layerTable
|
||||
);
|
||||
RowChangedEvent.Subscribe(
|
||||
(args) =>
|
||||
_topLevelExceptionHandler.FireAndForget(async () =>
|
||||
{
|
||||
await OnRowChanged(args);
|
||||
}),
|
||||
layerTable
|
||||
);
|
||||
RowDeletedEvent.Subscribe(
|
||||
(args) =>
|
||||
_topLevelExceptionHandler.FireAndForget(async () =>
|
||||
{
|
||||
await OnRowChanged(args);
|
||||
}),
|
||||
layerTable
|
||||
);
|
||||
}
|
||||
|
||||
private async Task OnRowChanged(RowChangedEventArgs args)
|
||||
{
|
||||
if (args == null || MapView.Active == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// get the path of the edited dataset
|
||||
Uri datasetPath = args.Row.GetTable().GetPath();
|
||||
|
||||
foreach (Layer layer in MapView.Active.Map.Layers)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (layer.GetPath() == datasetPath)
|
||||
{
|
||||
ChangedObjectIds[layer.URI] = 1;
|
||||
}
|
||||
}
|
||||
catch (UriFormatException) // layer.GetPath() or table.GetPath() can throw this error, if data source was removed from the hard drive
|
||||
{
|
||||
// ignore layers with invalid source URI
|
||||
}
|
||||
}
|
||||
foreach (StandaloneTable table in MapView.Active.Map.StandaloneTables)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (table.GetPath() == datasetPath)
|
||||
{
|
||||
ChangedObjectIds[table.URI] = 1;
|
||||
}
|
||||
}
|
||||
catch (UriFormatException) // layer.GetPath() or table.GetPath() can throw this error, if data source was removed from the hard drive
|
||||
{
|
||||
// ignore layers with invalid source URI
|
||||
}
|
||||
}
|
||||
|
||||
await RunExpirationChecks(false);
|
||||
}
|
||||
|
||||
private async Task GetIdsForLayersRemovedEvent(LayerEventsArgs args)
|
||||
{
|
||||
foreach (Layer layer in args.Layers)
|
||||
{
|
||||
ChangedObjectIds[layer.URI] = 1;
|
||||
}
|
||||
await RunExpirationChecks(true);
|
||||
}
|
||||
|
||||
private async Task GetIdsForStandaloneTablesRemovedEvent(StandaloneTableEventArgs args)
|
||||
{
|
||||
foreach (StandaloneTable table in args.Tables)
|
||||
{
|
||||
ChangedObjectIds[table.URI] = 1;
|
||||
}
|
||||
await RunExpirationChecks(true);
|
||||
}
|
||||
|
||||
private async Task GetIdsForMapPropertyChangedEvent(MapPropertyChangedEventArgs args)
|
||||
{
|
||||
foreach (Map map in args.Maps)
|
||||
{
|
||||
List<MapMember> allMapMembers = _mapMemberUtils.GetAllMapMembers(map);
|
||||
foreach (MapMember member in allMapMembers)
|
||||
{
|
||||
ChangedObjectIds[member.URI] = 1;
|
||||
}
|
||||
}
|
||||
await RunExpirationChecks(false);
|
||||
}
|
||||
|
||||
private void GetIdsForLayersAddedEvent(LayerEventsArgs args)
|
||||
{
|
||||
foreach (Layer layer in args.Layers)
|
||||
{
|
||||
if (layer is FeatureLayer featureLayer)
|
||||
{
|
||||
SubscribeToFeatureLayerDataSourceChange(featureLayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void GetIdsForStandaloneTablesAddedEvent(StandaloneTableEventArgs args)
|
||||
{
|
||||
foreach (StandaloneTable table in args.Tables)
|
||||
{
|
||||
SubscribeToTableDataSourceChange(table);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task GetIdsForMapMemberPropertiesChangedEvent(MapMemberPropertiesChangedEventArgs args)
|
||||
{
|
||||
// don't subscribe to all events (e.g. expanding group, changing visibility etc.)
|
||||
bool validEvent = false;
|
||||
foreach (var hint in args.EventHints)
|
||||
{
|
||||
if (
|
||||
hint == MapMemberEventHint.DataSource
|
||||
|| hint == MapMemberEventHint.DefinitionQuery
|
||||
|| hint == MapMemberEventHint.LabelClasses
|
||||
|| hint == MapMemberEventHint.LabelVisibility
|
||||
|| hint == MapMemberEventHint.Name
|
||||
|| hint == MapMemberEventHint.Renderer
|
||||
|| hint == MapMemberEventHint.SceneLayerType
|
||||
|| hint == MapMemberEventHint.URL
|
||||
)
|
||||
{
|
||||
validEvent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (validEvent)
|
||||
{
|
||||
foreach (MapMember member in args.MapMembers)
|
||||
{
|
||||
ChangedObjectIds[member.URI] = 1;
|
||||
}
|
||||
await RunExpirationChecks(false);
|
||||
}
|
||||
}
|
||||
|
||||
public List<ISendFilter> GetSendFilters() => _sendFilters;
|
||||
|
||||
public List<ICardSetting> GetSendSettings() => [];
|
||||
|
||||
[SuppressMessage(
|
||||
"Maintainability",
|
||||
"CA1506:Avoid excessive class coupling",
|
||||
Justification = "Being refactored on in parallel, muting this issue so CI can pass initially."
|
||||
)]
|
||||
public async Task Send(string modelCardId)
|
||||
{
|
||||
//poc: dupe code between connectors
|
||||
|
||||
try
|
||||
{
|
||||
if (_store.GetModelById(modelCardId) is not SenderModelCard modelCard)
|
||||
{
|
||||
// Handle as GLOBAL ERROR at BrowserBridge
|
||||
throw new InvalidOperationException("No publish model card was found.");
|
||||
}
|
||||
|
||||
using var cancellationItem = _cancellationManager.GetCancellationItem(modelCardId);
|
||||
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
List<MapMember> mapMembers = await QueuedTask.Run(() =>
|
||||
{
|
||||
scope
|
||||
.ServiceProvider.GetRequiredService<IConverterSettingsStore<ArcGISConversionSettings>>()
|
||||
.Initialize(
|
||||
_arcGISConversionSettingsFactory.Create(
|
||||
Project.Current,
|
||||
MapView.Active.Map,
|
||||
new CRSoffsetRotation(MapView.Active.Map)
|
||||
)
|
||||
);
|
||||
|
||||
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)
|
||||
{
|
||||
// Handle as CARD ERROR in this function
|
||||
throw new SpeckleSendFilterException("No objects were found to convert. Please update your publish filter!");
|
||||
}
|
||||
|
||||
await QueuedTask.Run(() =>
|
||||
{
|
||||
// subscribe to the selected layer events
|
||||
foreach (MapMember mapMember in mapMembers)
|
||||
{
|
||||
if (mapMember is FeatureLayer featureLayer)
|
||||
{
|
||||
SubscribeToFeatureLayerDataSourceChange(featureLayer);
|
||||
}
|
||||
else if (mapMember is StandaloneTable table)
|
||||
{
|
||||
SubscribeToTableDataSourceChange(table);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var sendResult = await scope
|
||||
.ServiceProvider.GetRequiredService<SendOperation<MapMember>>()
|
||||
.Execute(
|
||||
mapMembers,
|
||||
modelCard.GetSendInfo(_speckleApplication.ApplicationAndVersion),
|
||||
_operationProgressManager.CreateOperationProgressEventHandler(Parent, modelCardId, cancellationItem.Token),
|
||||
cancellationItem.Token
|
||||
);
|
||||
|
||||
await Commands.SetModelSendResult(modelCardId, sendResult.RootObjId, sendResult.ConversionResults);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// SWALLOW -> UI handles it immediately, so we do not need to handle anything for now!
|
||||
// Idea for later -> when cancel called, create promise from UI to solve it later with this catch block.
|
||||
// So have 3 state on UI -> Cancellation clicked -> Cancelling -> Cancelled
|
||||
return;
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal()) // UX reasons - we will report operation exceptions as model card error. We may change this later when we have more exception documentation
|
||||
{
|
||||
_logger.LogModelCardHandledError(ex);
|
||||
await Commands.SetModelError(modelCardId, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void CancelSend(string modelCardId) => _cancellationManager.CancelOperation(modelCardId);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if any sender model cards contain any of the changed objects. If so, also updates the changed objects hashset for each model card - this last part is important for on send change detection.
|
||||
/// </summary>
|
||||
private async Task RunExpirationChecks(bool idsDeleted)
|
||||
{
|
||||
var senders = _store.GetSenders();
|
||||
List<string> expiredSenderIds = new();
|
||||
string[] objectIdsList = ChangedObjectIds.Keys.ToArray();
|
||||
|
||||
_sendConversionCache.EvictObjects(objectIdsList);
|
||||
|
||||
foreach (SenderModelCard sender in senders)
|
||||
{
|
||||
var objIds = sender.SendFilter.NotNull().RefreshObjectIds();
|
||||
var intersection = objIds.Intersect(objectIdsList).ToList();
|
||||
bool isExpired = intersection.Count != 0;
|
||||
if (isExpired)
|
||||
{
|
||||
expiredSenderIds.Add(sender.ModelCardId.NotNull());
|
||||
|
||||
// Update the model card object Ids
|
||||
if (idsDeleted && sender.SendFilter is ArcGISSelectionFilter filter)
|
||||
{
|
||||
List<string> remainingObjIds = objIds.SkipWhile(x => intersection.Contains(x)).ToList();
|
||||
filter.SelectedObjectIds = remainingObjIds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await Commands.SetModelsExpired(expiredSenderIds);
|
||||
ChangedObjectIds = new();
|
||||
}
|
||||
}
|
||||
@@ -1,216 +0,0 @@
|
||||
using ArcGIS.Core.Data;
|
||||
using ArcGIS.Desktop.Framework.Threading.Tasks;
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using Speckle.Connectors.ArcGIS.Utils;
|
||||
using Speckle.Connectors.DUI.Bindings;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.DUI.Models.Card;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Common;
|
||||
using ArcProject = ArcGIS.Desktop.Core.Project;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Bindings;
|
||||
|
||||
//poc: dupe code between connectors
|
||||
public class BasicConnectorBinding : IBasicConnectorBinding
|
||||
{
|
||||
public string Name => "baseBinding";
|
||||
public IBrowserBridge Parent { get; }
|
||||
|
||||
public BasicConnectorBindingCommands Commands { get; }
|
||||
private readonly DocumentModelStore _store;
|
||||
private readonly ISpeckleApplication _speckleApplication;
|
||||
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
|
||||
|
||||
public BasicConnectorBinding(
|
||||
DocumentModelStore store,
|
||||
IBrowserBridge parent,
|
||||
ISpeckleApplication speckleApplication,
|
||||
ITopLevelExceptionHandler topLevelExceptionHandler
|
||||
)
|
||||
{
|
||||
_store = store;
|
||||
_speckleApplication = speckleApplication;
|
||||
_topLevelExceptionHandler = topLevelExceptionHandler;
|
||||
Parent = parent;
|
||||
Commands = new BasicConnectorBindingCommands(parent);
|
||||
|
||||
_store.DocumentChanged += (_, _) =>
|
||||
_topLevelExceptionHandler.FireAndForget(async () =>
|
||||
{
|
||||
await Commands.NotifyDocumentChanged();
|
||||
});
|
||||
}
|
||||
|
||||
public string GetSourceApplicationName() => _speckleApplication.Slug;
|
||||
|
||||
public string GetSourceApplicationVersion() => _speckleApplication.HostApplicationVersion;
|
||||
|
||||
public string GetConnectorVersion() => _speckleApplication.SpeckleVersion;
|
||||
|
||||
public DocumentInfo? GetDocumentInfo()
|
||||
{
|
||||
if (MapView.Active is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new DocumentInfo(ArcProject.Current.URI, MapView.Active.Map.Name, MapView.Active.Map.URI);
|
||||
}
|
||||
|
||||
public DocumentModelStore GetDocumentState() => _store;
|
||||
|
||||
public void AddModel(ModelCard model) => _store.AddModel(model);
|
||||
|
||||
public void UpdateModel(ModelCard model) => _store.UpdateModel(model);
|
||||
|
||||
public void RemoveModel(ModelCard model) => _store.RemoveModel(model);
|
||||
|
||||
public void RemoveModels(List<ModelCard> models) => _store.RemoveModels(models);
|
||||
|
||||
public async Task HighlightObjects(IReadOnlyList<string> objectIds)
|
||||
{
|
||||
await HighlightObjectsOnView(objectIds.Select(x => new ObjectID(x)).ToList());
|
||||
}
|
||||
|
||||
public async Task HighlightModel(string modelCardId)
|
||||
{
|
||||
var model = _store.GetModelById(modelCardId);
|
||||
|
||||
if (model is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var objectIds = new List<ObjectID>();
|
||||
|
||||
if (model is SenderModelCard senderModelCard)
|
||||
{
|
||||
objectIds = senderModelCard.SendFilter.NotNull().RefreshObjectIds().Select(x => new ObjectID(x)).ToList();
|
||||
}
|
||||
|
||||
if (model is ReceiverModelCard receiverModelCard)
|
||||
{
|
||||
objectIds = receiverModelCard.BakedObjectIds.NotNull().Select(x => new ObjectID(x)).ToList();
|
||||
}
|
||||
|
||||
if (objectIds is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
await HighlightObjectsOnView(objectIds);
|
||||
}
|
||||
|
||||
private async Task HighlightObjectsOnView(IReadOnlyList<ObjectID> objectIds)
|
||||
{
|
||||
await QueuedTask.Run(() =>
|
||||
{
|
||||
MapView mapView = MapView.Active;
|
||||
|
||||
List<MapMemberFeature> mapMembersFeatures = GetMapMembers(objectIds, mapView);
|
||||
ClearSelectionInTOC();
|
||||
ClearSelection();
|
||||
SelectMapMembersInTOC(mapMembersFeatures);
|
||||
SelectMapMembersAndFeatures(mapMembersFeatures);
|
||||
mapView.ZoomToSelected();
|
||||
});
|
||||
}
|
||||
|
||||
private List<MapMemberFeature> GetMapMembers(IReadOnlyList<ObjectID> objectIds, MapView mapView)
|
||||
{
|
||||
// find the layer on the map (from the objectID) and add the featureID is available
|
||||
List<MapMemberFeature> mapMembersFeatures = new();
|
||||
|
||||
foreach (ObjectID objectId in objectIds)
|
||||
{
|
||||
MapMember mapMember = mapView.Map.FindLayer(objectId.MappedLayerURI, true);
|
||||
if (mapMember is null)
|
||||
{
|
||||
mapMember = mapView.Map.FindStandaloneTable(objectId.MappedLayerURI);
|
||||
}
|
||||
if (mapMember is not null)
|
||||
{
|
||||
MapMemberFeature mapMembersFeat = new(mapMember, objectId.FeatureId);
|
||||
mapMembersFeatures.Add(mapMembersFeat);
|
||||
}
|
||||
}
|
||||
return mapMembersFeatures;
|
||||
}
|
||||
|
||||
private void ClearSelection()
|
||||
{
|
||||
List<Layer> mapMembers = MapView.Active.Map.GetLayersAsFlattenedList().ToList();
|
||||
foreach (var member in mapMembers)
|
||||
{
|
||||
if (member is FeatureLayer featureLayer)
|
||||
{
|
||||
featureLayer.ClearSelection();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearSelectionInTOC()
|
||||
{
|
||||
MapView.Active.ClearTOCSelection();
|
||||
}
|
||||
|
||||
private void SelectMapMembersAndFeatures(IReadOnlyList<MapMemberFeature> mapMembersFeatures)
|
||||
{
|
||||
foreach (MapMemberFeature mapMemberFeat in mapMembersFeatures)
|
||||
{
|
||||
MapMember member = mapMemberFeat.MapMember;
|
||||
if (member is FeatureLayer layer)
|
||||
{
|
||||
if (mapMemberFeat.FeatureId == null)
|
||||
{
|
||||
// select full layer if featureID not specified
|
||||
layer.Select();
|
||||
}
|
||||
else
|
||||
{
|
||||
// query features by ID
|
||||
var objectIDfield = layer.GetFeatureClass().GetDefinition().GetObjectIDField();
|
||||
|
||||
// FeatureID range starts from 0, but auto-assigned IDs in the layer start from 1
|
||||
QueryFilter anotherQueryFilter = new() { WhereClause = $"{objectIDfield} = {mapMemberFeat.FeatureId + 1}" };
|
||||
using (Selection onlyOneSelection = layer.Select(anotherQueryFilter, SelectionCombinationMethod.New)) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SelectMapMembersInTOC(IReadOnlyList<MapMemberFeature> mapMembersFeatures)
|
||||
{
|
||||
List<Layer> layers = new();
|
||||
List<StandaloneTable> tables = new();
|
||||
|
||||
foreach (MapMemberFeature mapMemberFeat in mapMembersFeatures)
|
||||
{
|
||||
MapMember member = mapMemberFeat.MapMember;
|
||||
if (member is Layer layer)
|
||||
{
|
||||
if (member is not GroupLayer) // group layer selection clears other layers selection
|
||||
{
|
||||
layers.Add(layer);
|
||||
}
|
||||
else
|
||||
{
|
||||
layer.SetExpanded(true);
|
||||
}
|
||||
}
|
||||
else if (member is StandaloneTable table)
|
||||
{
|
||||
tables.Add(table);
|
||||
}
|
||||
}
|
||||
MapView.Active.SelectLayers(layers);
|
||||
|
||||
// this step clears previous selection, not clear how to ADD selection instead
|
||||
// this is why, activating it only if no layers are selected
|
||||
if (layers.Count == 0)
|
||||
{
|
||||
MapView.Active.SelectStandaloneTables(tables);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!--
|
||||
|
||||
Copyright 2022 Esri
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
-->
|
||||
<ArcGIS defaultAssembly="Speckle.Connectors.ArcGIS3.dll" defaultNamespace="Speckle.Connectors.ArcGIS" xmlns="http://schemas.esri.com/DADF/Registry" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.esri.com/DADF/Registry file:///C:/Program%20Files/ArcGIS/Pro/bin/ArcGIS.Desktop.Framework.xsd">
|
||||
<AddInInfo id="{6CB1D25C-B8BF-4A33-9099-C1F8D1B32EFC}" version="1.0" desktopVersion="3.0.34047">
|
||||
<Name>Speckle</Name>
|
||||
<Description>Next Gen Speckle Connector (Beta) for ArcGIS</Description>
|
||||
<Image>Images\AddinDesktop32.png</Image>
|
||||
<Author>Speckle Systems</Author>
|
||||
<Company>Speckle Systems</Company>
|
||||
<Date>8/5/2021 12:24:21 PM</Date>
|
||||
<Subject>Framework</Subject>
|
||||
<!-- Note subject can be one or more of these topics:
|
||||
Content, Framework, Editing, Geodatabase, Geometry, Geoprocessing, Layouts, Map Authoring, Map Exploration -->
|
||||
</AddInInfo>
|
||||
<modules>
|
||||
<insertModule id="ConnectorArcGIS_Module" className="SpeckleModule" autoLoad="false" caption="SpeckleModule">
|
||||
<!-- uncomment to have the control hosted on a separate tab-->
|
||||
<tabs>
|
||||
<tab id="Speckle_Tab1" caption="Speckle">
|
||||
<group refID="Speckle_Group1"/>
|
||||
</tab>
|
||||
</tabs>
|
||||
<groups>
|
||||
<!-- comment this out if you have no controls on the Addin tab to avoid
|
||||
an empty group. change appearsOnAddinTab to "True" if control is to be in the addin tab-->
|
||||
<group id="Speckle_Group1" caption="Speckle" appearsOnAddInTab="false" keytip="G1">
|
||||
<!-- host controls within groups -->
|
||||
<button refID="SpeckleDUI3_SpeckleDUI3OpenButton" size="large" />
|
||||
</group>
|
||||
</groups>
|
||||
<controls>
|
||||
<!-- add your controls here -->
|
||||
<button id="SpeckleDUI3_SpeckleDUI3OpenButton" caption="Speckle (Beta)"
|
||||
className="SpeckleDUI3OpenButton" loadOnClick="true"
|
||||
keytip="B1"
|
||||
smallImage="Images/s2logo_16.png"
|
||||
largeImage="Images/s2logo_32.png">
|
||||
<tooltip heading="Speckle Connector for ArcGIS">
|
||||
<disabledText />
|
||||
</tooltip>
|
||||
</button>
|
||||
</controls>
|
||||
|
||||
<dockPanes>
|
||||
<dockPane id="SpeckleDUI3_SpeckleDUI3" caption="Speckle (Beta)" className="SpeckleDUI3ViewModel" keytip="DockPane" initiallyVisible="true" dock="group" dockWith="esri_core_projectDockPane">
|
||||
<content className="SpeckleDUI3Wrapper" />
|
||||
</dockPane>
|
||||
</dockPanes>
|
||||
|
||||
</insertModule>
|
||||
</modules>
|
||||
</ArcGIS>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 714 B |
|
Before Width: | Height: | Size: 1.6 KiB |
@@ -1,66 +0,0 @@
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Speckle.Connectors.ArcGIS.Bindings;
|
||||
using Speckle.Connectors.ArcGIS.Filters;
|
||||
using Speckle.Connectors.ArcGIS.HostApp;
|
||||
using Speckle.Connectors.ArcGIS.Operations.Receive;
|
||||
using Speckle.Connectors.ArcGis.Operations.Send;
|
||||
using Speckle.Connectors.ArcGIS.Utils;
|
||||
using Speckle.Connectors.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;
|
||||
using Speckle.Connectors.DUI.WebView;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Sdk.Models.GraphTraversal;
|
||||
|
||||
// POC: This is a temp reference to root object senders to tweak CI failing after having generic interfaces into common project.
|
||||
// This should go whenever it is aligned.
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.DependencyInjection;
|
||||
|
||||
public static class ArcGISConnectorModule
|
||||
{
|
||||
public static void AddArcGIS(this IServiceCollection serviceCollection)
|
||||
{
|
||||
serviceCollection.AddConnectors();
|
||||
serviceCollection.AddDUI<DefaultThreadContext, ArcGISDocumentStore>();
|
||||
serviceCollection.AddDUIView();
|
||||
|
||||
// Register bindings
|
||||
serviceCollection.AddSingleton<IBinding, TestBinding>();
|
||||
serviceCollection.AddSingleton<IBinding, ConfigBinding>();
|
||||
serviceCollection.AddSingleton<IBinding, AccountBinding>();
|
||||
serviceCollection.AddSingleton<IBinding>(sp => sp.GetRequiredService<IBasicConnectorBinding>());
|
||||
serviceCollection.AddSingleton<IBasicConnectorBinding, BasicConnectorBinding>();
|
||||
|
||||
serviceCollection.AddSingleton(DefaultTraversal.CreateTraversalFunc());
|
||||
|
||||
// register send operation and dependencies
|
||||
serviceCollection.AddSingleton<IBinding, ArcGISSendBinding>();
|
||||
serviceCollection.AddScoped<SendOperation<MapMember>>();
|
||||
serviceCollection.AddSingleton<IBinding, ArcGISSelectionBinding>();
|
||||
serviceCollection.AddTransient<ISendFilter, ArcGISSelectionFilter>();
|
||||
serviceCollection.AddScoped<ArcGISRootObjectBuilder>();
|
||||
serviceCollection.AddScoped<IRootObjectBuilder<MapMember>, ArcGISRootObjectBuilder>();
|
||||
serviceCollection.AddScoped<ArcGISLayerUnpacker>();
|
||||
serviceCollection.AddScoped<ArcGISColorUnpacker>();
|
||||
// register send conversion cache
|
||||
serviceCollection.AddSingleton<ISendConversionCache, SendConversionCache>();
|
||||
|
||||
// register receive operation and dependencies
|
||||
// serviceCollection.AddSingleton<IBinding, ArcGISReceiveBinding>(); // POC: disabled until receive code is refactored
|
||||
serviceCollection.AddScoped<LocalToGlobalConverterUtils>();
|
||||
serviceCollection.AddScoped<ArcGISColorManager>();
|
||||
serviceCollection.AddScoped<IHostObjectBuilder, ArcGISHostObjectBuilder>();
|
||||
|
||||
serviceCollection.AddScoped<MapMembersUtils>();
|
||||
|
||||
// operation progress manager
|
||||
serviceCollection.AddSingleton<IOperationProgressManager, OperationProgressManager>();
|
||||
}
|
||||
}
|
||||
@@ -1,356 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Project>
|
||||
<!-- Code to zip up the files-->
|
||||
|
||||
<UsingTask TaskName="PackageAddIn" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
|
||||
<ParameterGroup>
|
||||
<ZipIntermediatePath ParameterType="System.String" Required="true" />
|
||||
<PackageType ParameterType="System.String" Required="true" />
|
||||
<TargetFolder ParameterType="System.String" Required="true" />
|
||||
<TargetFileName ParameterType="System.String" Required="true" />
|
||||
<RootNamespace ParameterType="System.String" Required="true" />
|
||||
<PackageOutputPath ParameterType="System.String" Output="true"/>
|
||||
</ParameterGroup>
|
||||
<Task>
|
||||
<!-- <Reference Include="System.IO.Compression.FileSystem"/>-->
|
||||
<!-- <Reference Include="System.Xml.Linq"/>-->
|
||||
<!-- <Reference Include="System.Xml"/>-->
|
||||
<Using Namespace="System"/>
|
||||
<Using Namespace="System.IO"/>
|
||||
<Using Namespace="System.Xml.Linq"/>
|
||||
<Using Namespace="System.Linq"/>
|
||||
<Using Namespace="System.IO.Compression"/>
|
||||
<Code Type="Fragment" Language="cs">
|
||||
<![CDATA[
|
||||
Success = false;
|
||||
string ConfigNotFound = "{0} was not found. File must be present in the root of the project and its build action set to AddInContent.";
|
||||
string ZipIntermediatePathNotFound = "{0} was not found.";
|
||||
string DefaultAssemblyDoesNotMatch = "Your value of '{0}' for the '{1}' attribute in the {2} does not match the assembly name '{3}' set for your project.";
|
||||
string DefaultNSDoesNotMatch = "Your value of '{0}' for the '{1}' attribute in the {2} does not match the default namespace '{3}' set for your project.";
|
||||
//Create the name of the Config File and extension
|
||||
string extension = "";
|
||||
string config = "";
|
||||
string attrib_asm = "";
|
||||
string attrib_ns = "";
|
||||
var assemblyValMissing = "";
|
||||
var nsValMissing = "";
|
||||
if (PackageType.ToLower() == "plugin")
|
||||
{
|
||||
Log.LogMessage(MessageImportance.Low, "This is an plugin");
|
||||
config = "Config.xml";
|
||||
extension = ".esriPlugin";
|
||||
attrib_asm = "library";
|
||||
attrib_ns = "namespace";
|
||||
assemblyValMissing = "AddIn element 'library' attribute not found";
|
||||
nsValMissing = "AddIn element 'namespace' attribute not found";
|
||||
}
|
||||
else if (PackageType.ToLower() == "configuration")
|
||||
{
|
||||
Log.LogMessage(MessageImportance.Low, "This is an configuration");
|
||||
config = "Config.daml";
|
||||
extension = ".proConfigX";
|
||||
attrib_asm = "defaultAssembly";
|
||||
attrib_ns = "defaultNamespace";
|
||||
assemblyValMissing = "ArcGIS element 'defaultAssembly' attribute not found";
|
||||
nsValMissing = "ArcGIS element 'defaultNamespace' attribute not found";
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.LogMessage(MessageImportance.Low, "This is an addin");
|
||||
config = "Config.daml";
|
||||
bool proSDKProject = File.Exists(Path.Combine(ZipIntermediatePath, config));
|
||||
if (!proSDKProject) //This might be a class library that uses the Pro references only
|
||||
return true;
|
||||
extension = ".esriAddinX";
|
||||
attrib_asm = "defaultAssembly";
|
||||
attrib_ns = "defaultNamespace";
|
||||
assemblyValMissing = "ArcGIS element 'defaultAssembly' attribute not found";
|
||||
nsValMissing = "ArcGIS element 'defaultNamespace' attribute not found";
|
||||
}
|
||||
// Check if Config.daml exists in ZipFolder
|
||||
ZipIntermediatePath = Path.GetFullPath(ZipIntermediatePath);
|
||||
if (!Directory.Exists(ZipIntermediatePath))
|
||||
{
|
||||
Log.LogError(ZipIntermediatePathNotFound, ZipIntermediatePath);
|
||||
return false;
|
||||
}
|
||||
var addInXML = Path.Combine(ZipIntermediatePath, config);
|
||||
Log.LogMessage(MessageImportance.Low, "addInXML: " + addInXML);
|
||||
Log.LogMessage(MessageImportance.High, "PackageType: " + PackageType);
|
||||
if (!File.Exists(addInXML))
|
||||
{
|
||||
Log.LogError(ConfigNotFound, config);
|
||||
return false;
|
||||
}
|
||||
//Verfiy that an assembly with the name defined in the Config.daml
|
||||
//matches the default assembly set in the project. Ditto for the
|
||||
//namespace
|
||||
string DefaultAssembly = "";
|
||||
string DefaultNamespace = "";
|
||||
XDocument xdoc = XDocument.Load(addInXML);
|
||||
XNamespace DefaultNS = "http://schemas.esri.com/DADF/Registry";
|
||||
if (PackageType.ToLower() == "plugin")
|
||||
{
|
||||
var addin = xdoc.Root.Element(DefaultNS + "AddIn");
|
||||
if (addin != null)
|
||||
{
|
||||
var val = addin.Attribute("library");
|
||||
if (val != null)
|
||||
DefaultAssembly = val.Value;
|
||||
val = addin.Attribute("namespace");
|
||||
if (val != null)
|
||||
DefaultNamespace = val.Value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var val = xdoc.Root.Attribute("defaultAssembly");
|
||||
if (val != null)
|
||||
DefaultAssembly = val.Value;
|
||||
val = xdoc.Root.Attribute("defaultNamespace");
|
||||
if (val != null)
|
||||
DefaultNamespace = val.Value;
|
||||
}
|
||||
if (string.IsNullOrEmpty(DefaultAssembly))
|
||||
{
|
||||
Log.LogError(assemblyValMissing);
|
||||
return false;
|
||||
}
|
||||
if (string.IsNullOrEmpty(DefaultNamespace))
|
||||
{
|
||||
Log.LogError(nsValMissing);
|
||||
return false;
|
||||
}
|
||||
|
||||
//check that the addin assembly and default assembly names match
|
||||
if (DefaultAssembly.ToLower() != TargetFileName.ToLower())
|
||||
{
|
||||
Log.LogWarning(DefaultAssemblyDoesNotMatch, DefaultAssembly, attrib_asm, config, TargetFileName);
|
||||
}
|
||||
//Ditto for namespace
|
||||
if (DefaultNamespace.ToLower() != RootNamespace.ToLower())
|
||||
{
|
||||
Log.LogWarning(DefaultNSDoesNotMatch, DefaultNamespace, attrib_ns, config, RootNamespace);
|
||||
}
|
||||
|
||||
if (!Directory.Exists(TargetFolder))
|
||||
{
|
||||
Directory.CreateDirectory(TargetFolder);
|
||||
}
|
||||
|
||||
string addInAssembly = System.IO.Path.GetFileNameWithoutExtension(DefaultAssembly);
|
||||
string archiveName = addInAssembly + extension;
|
||||
try
|
||||
{
|
||||
string file = Path.Combine(TargetFolder, archiveName);
|
||||
if (File.Exists(file))
|
||||
File.Delete(file);
|
||||
System.IO.Compression.ZipFile.CreateFromDirectory(ZipIntermediatePath, file);
|
||||
PackageOutputPath = Path.GetFullPath(file);
|
||||
Success = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.LogErrorFromException(ex);
|
||||
return false;
|
||||
}
|
||||
]]>
|
||||
</Code>
|
||||
</Task>
|
||||
</UsingTask>
|
||||
<!-- Code to find relative path-->
|
||||
<UsingTask TaskName="ConvertToRelativePath" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
|
||||
<ParameterGroup>
|
||||
<RelativeTo ParameterType="System.String" Required="true"/>
|
||||
<Paths ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
|
||||
<RelativePaths ParameterType="Microsoft.Build.Framework.ITaskItem[]" Output="true"/>
|
||||
</ParameterGroup>
|
||||
<Task>
|
||||
<Using Namespace="System"/>
|
||||
<Using Namespace="System.IO"/>
|
||||
<Using Namespace="System.Linq"/>
|
||||
<Code Type="Fragment" Language="cs">
|
||||
<![CDATA[
|
||||
var result = new List<ITaskItem>();
|
||||
System.Uri relativeTo = new Uri(this.RelativeTo);
|
||||
foreach (var i in Paths) {
|
||||
try {
|
||||
System.Uri itemFullPath = new Uri(i.GetMetadata("FullPath"));
|
||||
var relativeUri = relativeTo.MakeRelativeUri(itemFullPath);
|
||||
|
||||
result.Add(new TaskItem(Uri.UnescapeDataString(relativeUri.ToString())));
|
||||
}
|
||||
catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
RelativePaths = result.ToArray();
|
||||
foreach (var i in RelativePaths)
|
||||
{
|
||||
Log.LogMessage(MessageImportance.Low, "RelativePaths: " + i.ToString());
|
||||
}
|
||||
Success = true;
|
||||
]]>
|
||||
</Code>
|
||||
</Task>
|
||||
</UsingTask>
|
||||
<UsingTask TaskName="CleanAddIn" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
|
||||
<ParameterGroup>
|
||||
<ProjectDir ParameterType="System.String" Required="true"/>
|
||||
<AssemblyName ParameterType="System.String" Required="true"/>
|
||||
<PackageType ParameterType="System.String" Required="true"/>
|
||||
<!--<ArcGISFolder ParameterType="System.String" Output="true" /> -->
|
||||
<CleanInfo ParameterType="System.String" Output="true"/>
|
||||
</ParameterGroup>
|
||||
<Task>
|
||||
<!-- <Reference Include="System.Xml.Linq"/>-->
|
||||
<!-- <Reference Include="System.Xml"/>-->
|
||||
<Using Namespace="System"/>
|
||||
<Using Namespace="System.IO"/>
|
||||
<Using Namespace="System.Xml.Linq"/>
|
||||
<Using Namespace="System.Linq"/>
|
||||
<Code Type="Fragment" Language="cs">
|
||||
<![CDATA[
|
||||
Success = false;
|
||||
string ConfigNotFound = "{0} was not found. File must be present in the root of the project and its build action set to AddInContent.";
|
||||
|
||||
//Create the name of the Config File and extension
|
||||
string extension = "";
|
||||
string config = "";
|
||||
|
||||
if (PackageType.ToLower() == "plugin")
|
||||
{
|
||||
config = "Config.xml";
|
||||
extension = ".esriPlugin";
|
||||
}
|
||||
else if (PackageType.ToLower() == "configuration")
|
||||
{
|
||||
config = "Config.daml";
|
||||
extension = ".proConfigX";
|
||||
}
|
||||
else
|
||||
{
|
||||
config = "Config.daml";
|
||||
bool proSDKProject = File.Exists(Path.Combine(ProjectDir, config));
|
||||
if (!proSDKProject) //This might be a class library that uses the Pro references only
|
||||
return true;
|
||||
extension = ".esriAddinX";
|
||||
}
|
||||
|
||||
var addInXML = Path.Combine(ProjectDir, config);
|
||||
if (!File.Exists(addInXML))
|
||||
{
|
||||
Log.LogError(ConfigNotFound, config);
|
||||
return false;
|
||||
}
|
||||
|
||||
//Get the add-in id
|
||||
XDocument xdoc = XDocument.Load(addInXML);
|
||||
XNamespace DefaultNS = "http://schemas.esri.com/DADF/Registry";
|
||||
if (PackageType.ToLower() == "plugin")
|
||||
{
|
||||
Log.LogMessage("process plugin");
|
||||
var addInID = xdoc.Root.Element(DefaultNS + "AddInID");
|
||||
CleanInfo = addInID.Value;//let it error if it's missing
|
||||
}
|
||||
else if (PackageType.ToLower() == "addin")
|
||||
{
|
||||
Log.LogMessage("process addin");
|
||||
var addinInfo = xdoc.Root.Element(DefaultNS + "AddInInfo");
|
||||
CleanInfo = addinInfo.Attribute("id").Value;//let it error if it's missing
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.LogMessage("process configuration");
|
||||
CleanInfo = AssemblyName + extension;
|
||||
}
|
||||
Success = true;
|
||||
]]>
|
||||
</Code>
|
||||
</Task>
|
||||
</UsingTask>
|
||||
<!-- Define additional BuildAction option -->
|
||||
<!-- Set up default zip properties -->
|
||||
<PropertyGroup>
|
||||
<PackageType Condition="'$(PackageType)' == ''">Addin</PackageType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ArcGISFolder>$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\ESRI\ArcGISPro', 'InstallDir', null, RegistryView.Registry64))\bin</ArcGISFolder>
|
||||
<ArcGISFolder Condition="'$(ArcGISFolder)' == ''">$(registry:HKEY_CURRENT_USER\SOFTWARE\ESRI\ArcGISPro@InstallDir)\bin</ArcGISFolder>
|
||||
<ArcGISFolder Condition="'$(ArcGISFolder)' == '' Or !Exists('$(ArcGISFolder)\RegisterAddIn.exe')">$(ProgramData)\EsriProCommon\</ArcGISFolder>
|
||||
</PropertyGroup>
|
||||
<Target Name="ArcGISInstallOutput" AfterTargets="Build">
|
||||
<Message Text="IntermediateOutputPath Name: $(IntermediateOutputPath)..." Importance="High"/>
|
||||
<Message Text="CleanFile Name: $(CleanFile)..." Importance="High"/>
|
||||
<Message Text="ProjectDir Name: $(ProjectDir)..." Importance="High"/>
|
||||
<Message Text="AssemblyName Name: $(AssemblyName)..." Importance="High"/>
|
||||
<Message Text="TargetFileName Name: $(TargetFileName)..." Importance="High"/>
|
||||
<Message Text="RootNamespace: $(RootNamespace)..." Importance="High"/>
|
||||
<Message Text="TargetFolder Name: $(OutDir)..." Importance="High"/>
|
||||
<Message Text="PackageType Name: $(PackageType)..." Importance="High"/>
|
||||
<Message Text="Install dir: $(ArcGISFolder)" Importance="High"/>
|
||||
<!-- Get a list of project outputs from the cache file and FileWritesXXX item,
|
||||
excluding those in intermediate output directory -->
|
||||
<!-- Note clean file may miss listing CopyLocal reference -->
|
||||
<ReadLinesFromFile File="$(IntermediateOutputPath)$(CleanFile)">
|
||||
<Output TaskParameter="Lines" ItemName="CacheOutputFiles" />
|
||||
</ReadLinesFromFile>
|
||||
<FindUnderPath Files="@(CacheOutputFiles)" Path="$(OutDir)">
|
||||
<Output TaskParameter="InPath" ItemName="PackageOutputFiles" />
|
||||
</FindUnderPath>
|
||||
<FindUnderPath Files="@(FileWrites->'%(FullPath)')" Path="$(OutDir)">
|
||||
<Output TaskParameter="InPath" ItemName="PackageOutputFiles" />
|
||||
</FindUnderPath>
|
||||
<FindUnderPath Files="@(FileWritesShareable->'%(FullPath)')" Path="$(OutDir)">
|
||||
<Output TaskParameter="InPath" ItemName="PackageOutputFiles" />
|
||||
</FindUnderPath>
|
||||
<RemoveDuplicates Inputs="@(PackageOutputFiles)">
|
||||
<Output TaskParameter="Filtered" ItemName="FilteredPackageOutputFiles" />
|
||||
</RemoveDuplicates>
|
||||
<ConvertToRelativePath Paths="@(FilteredPackageOutputFiles)" RelativeTo="$(TargetDir)">
|
||||
<Output TaskParameter="RelativePaths" ItemName="ConfigBinaries" />
|
||||
</ConvertToRelativePath>
|
||||
<Message Text="ConvertToRelativePath Task, TargetDir: $(TargetDir) " Importance="High"/>
|
||||
</Target>
|
||||
<Target Name="PackageArcGISContents" AfterTargets="ArcGISInstallOutput">
|
||||
<Message Text="Running PackageArcGISContents..." Importance="High"/>
|
||||
<RemoveDir Condition="Exists('$(ZipIntermediatePath)')" Directories="$(ZipIntermediatePath)" />
|
||||
<Message Text="ZipIntermediatePath: $(ZipIntermediatePath)Install..." Importance="High"/>
|
||||
<!-- Copy project output files, preserving folder structure -->
|
||||
<Copy SourceFiles="@(ConfigBinaries->'$(OutDir)%(Identity)')" ContinueOnError="true" DestinationFolder="$(IntermediateOutputPath)temp_archive\Install\%(RelativeDir)" />
|
||||
<!-- Copy items marked with Content as BuildAction, preserving folder structure & handling linked items -->
|
||||
<!-- Only include items that have CopyToOutputDirectory as Never -->
|
||||
<Copy SourceFiles="@(Content)" Condition="'%(Content.Link)' == '' And ('%(Content.CopyToOutputDirectory)' == 'Never' Or '%(Content.CopyToOutputDirectory)' == '')" DestinationFolder="$(IntermediateOutputPath)temp_archive\%(RelativeDir)" ContinueOnError="true" />
|
||||
<Copy SourceFiles="@(Content)" Condition="'%(Content.Link)' != '' And ('%(Content.CopyToOutputDirectory)' == 'Never' Or '%(Content.CopyToOutputDirectory)' == '')" DestinationFiles="$(IntermediateOutputPath)temp_archive\%(Content.Link)" ContinueOnError="true"/>
|
||||
<!-- Zipping up add-in resources -->
|
||||
<PackageAddIn ZipIntermediatePath="$(IntermediateOutputPath)temp_archive\"
|
||||
PackageType="$(PackageType)"
|
||||
TargetFolder="$(OutDir)"
|
||||
TargetFileName="$(TargetFileName)"
|
||||
RootNamespace="$(RootNamespace)">
|
||||
<Output TaskParameter="PackageOutputPath" PropertyName="PackageFile" />
|
||||
</PackageAddIn>
|
||||
<!-- Shell out to RegisterAddIn.exe to install the package -->
|
||||
<Message Text="Deploying $(PackageType)..." Importance="High"/>
|
||||
<Message Text="ArcGISFolder Name: $(ArcGISFolder)..." Importance="High"/>
|
||||
<Message Text="Unable to execute RegisterAddIn.exe. ArcGIS Pro is not installed." Importance="High" Condition="!Exists('$(ArcGISFolder)')"/>
|
||||
<Message Text="Execute RegisterAddIn.exe "$(PackageFile)" /s..." Importance="High" Condition="Exists('$(ArcGISFolder)')"/>
|
||||
<Exec IgnoreExitCode="true" WorkingDirectory="$(ArcGISFolder)" Command="RegisterAddIn.exe "$(PackageFile)" /s" Condition="Exists('$(ArcGISFolder)') AND $(PackageFile) != '' ">
|
||||
<Output TaskParameter="ExitCode" PropertyName="ESRIRegAddinExitCode" />
|
||||
</Exec>
|
||||
<RemoveDir Condition="Exists('$(ZipIntermediatePath)')" Directories="$(ZipIntermediatePath)" />
|
||||
</Target>
|
||||
<Target Name="CleanArcGISContents" AfterTargets="Clean">
|
||||
<CleanAddIn ProjectDir="$(ProjectDir)"
|
||||
AssemblyName="$(AssemblyName)"
|
||||
PackageType="$(PackageType)">
|
||||
<Output TaskParameter="CleanInfo" PropertyName="CleanInfo" />
|
||||
</CleanAddIn>
|
||||
<Message Text="Clean $(PackageType).$(ArcGISFolder).." Importance="High"/>
|
||||
<Message Text="Execute RegisterAddIn.exe "$(CleanInfo)" /u..." Importance="High" Condition="Exists('$(ArcGISFolder)')"/>
|
||||
<Message Text="Unable to execute RegisterAddIn.exe. ArcGIS Pro is not installed." Importance="High" Condition="!Exists('$(ArcGISFolder)')"/>
|
||||
<Exec IgnoreExitCode="true" WorkingDirectory="$(ArcGISFolder)" Command="RegisterAddIn.exe "$(CleanInfo)" /u /s" Condition="Exists('$(ArcGISFolder)') AND $(CleanInfo) != ''">
|
||||
<Output TaskParameter="ExitCode" PropertyName="ESRIRegAddinExitCode" />
|
||||
</Exec>
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -1,13 +0,0 @@
|
||||
using Speckle.Connectors.DUI.Models.Card.SendFilter;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Filters;
|
||||
|
||||
public class ArcGISSelectionFilter : DirectSelectionSendFilter
|
||||
{
|
||||
public ArcGISSelectionFilter()
|
||||
{
|
||||
IsDefault = true;
|
||||
}
|
||||
|
||||
public override List<string> RefreshObjectIds() => SelectedObjectIds;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
global using AC = ArcGIS.Core;
|
||||
global using ACD = ArcGIS.Core.Data;
|
||||
global using ADM = ArcGIS.Desktop.Mapping;
|
||||
@@ -1,265 +0,0 @@
|
||||
using System.Drawing;
|
||||
using ArcGIS.Core.CIM;
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Converters.ArcGIS3.Utils;
|
||||
using Speckle.Objects;
|
||||
using Speckle.Objects.Other;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using Speckle.Sdk.Models.Extensions;
|
||||
using Speckle.Sdk.Models.GraphTraversal;
|
||||
using Speckle.Sdk.Models.Proxies;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// TODO: definitely need to refactor this, probably will collect colors during layer iteration in the root object builder.
|
||||
/// </summary>
|
||||
public class ArcGISColorManager
|
||||
{
|
||||
public Dictionary<string, Color> ObjectColorsIdMap { get; set; } = new();
|
||||
public Dictionary<string, Color> ObjectMaterialsIdMap { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Parse Color Proxies and stores in ObjectColorsIdMap the relationship between object ids and colors
|
||||
/// </summary>
|
||||
/// <param name="colorProxies"></param>
|
||||
/// <param name="onOperationProgressed"></param>
|
||||
public void ParseColors(List<ColorProxy> colorProxies, IProgress<CardProgress> onOperationProgressed)
|
||||
{
|
||||
// injected as Singleton, so we need to clean existing proxies first
|
||||
ObjectColorsIdMap = new();
|
||||
var count = 0;
|
||||
foreach (ColorProxy colorProxy in colorProxies)
|
||||
{
|
||||
onOperationProgressed.Report(new("Converting colors", (double)++count / colorProxies.Count));
|
||||
foreach (string objectId in colorProxy.objects)
|
||||
{
|
||||
Color convertedColor = Color.FromArgb(colorProxy.value);
|
||||
ObjectColorsIdMap.TryAdd(objectId, convertedColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse Color renderMaterials and stores in ObjectMaterialsIdMap the relationship between object ids and colors
|
||||
/// </summary>
|
||||
/// <param name="materialProxies"></param>
|
||||
/// <param name="onOperationProgressed"></param>
|
||||
public void ParseMaterials(List<RenderMaterialProxy> materialProxies, IProgress<CardProgress> onOperationProgressed)
|
||||
{
|
||||
// injected as Singleton, so we need to clean existing proxies first
|
||||
ObjectMaterialsIdMap = new();
|
||||
var count = 0;
|
||||
foreach (RenderMaterialProxy colorProxy in materialProxies)
|
||||
{
|
||||
onOperationProgressed.Report(new("Converting materials", (double)++count / materialProxies.Count));
|
||||
foreach (string objectId in colorProxy.objects)
|
||||
{
|
||||
Color convertedColor = Color.FromArgb(colorProxy.value.diffuse);
|
||||
ObjectMaterialsIdMap.TryAdd(objectId, convertedColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int CIMColorToInt(CIMColor color)
|
||||
{
|
||||
return (255 << 24)
|
||||
| ((int)Math.Round(color.Values[0]) << 16)
|
||||
| ((int)Math.Round(color.Values[1]) << 8)
|
||||
| (int)Math.Round(color.Values[2]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new CIMUniqueValueClass for UniqueRenderer per each object ID
|
||||
/// </summary>
|
||||
/// <param name="tc"></param>
|
||||
/// <param name="speckleGeometryType"></param>
|
||||
private CIMUniqueValueClass CreateColorCategory(
|
||||
TraversalContext tc,
|
||||
esriGeometryType speckleGeometryType,
|
||||
string uniqueLabel
|
||||
)
|
||||
{
|
||||
// declare default white color
|
||||
Color color = Color.FromArgb(255, 255, 255, 255);
|
||||
bool colorFound = false;
|
||||
|
||||
// get color moving upwards from the object
|
||||
foreach (var parent in tc.GetAscendants())
|
||||
{
|
||||
if (parent.applicationId is string appId)
|
||||
{
|
||||
if (ObjectMaterialsIdMap.TryGetValue(appId, out Color objColorMaterial))
|
||||
{
|
||||
color = objColorMaterial;
|
||||
colorFound = true;
|
||||
break;
|
||||
}
|
||||
if (ObjectColorsIdMap.TryGetValue(appId, out Color objColor))
|
||||
{
|
||||
color = objColor;
|
||||
colorFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handling Revit case, where child objects have separate colors/materials
|
||||
if (!colorFound && tc.Current is IDataObject)
|
||||
{
|
||||
var displayable = tc.Current.TryGetDisplayValue();
|
||||
if (displayable != null)
|
||||
{
|
||||
foreach (var childObj in displayable)
|
||||
{
|
||||
if (childObj.applicationId is string appId)
|
||||
{
|
||||
if (ObjectMaterialsIdMap.TryGetValue(appId, out Color objColorMaterial))
|
||||
{
|
||||
color = objColorMaterial;
|
||||
break;
|
||||
}
|
||||
if (ObjectColorsIdMap.TryGetValue(appId, out Color objColor))
|
||||
{
|
||||
color = objColor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CIMSymbolReference symbol = CreateSymbol(speckleGeometryType, color);
|
||||
|
||||
// First create a "CIMUniqueValueClass"
|
||||
List<CIMUniqueValue> listUniqueValues = new() { new CIMUniqueValue { FieldValues = new string[] { uniqueLabel } } };
|
||||
|
||||
CIMUniqueValueClass newUniqueValueClass =
|
||||
new()
|
||||
{
|
||||
Editable = true,
|
||||
Label = uniqueLabel,
|
||||
Patch = PatchShape.Default,
|
||||
Symbol = symbol,
|
||||
Visible = true,
|
||||
Values = listUniqueValues.ToArray()
|
||||
};
|
||||
return newUniqueValueClass;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a Symbol from GeometryType and Color
|
||||
/// </summary>
|
||||
/// <param name="speckleGeometryType"></param>
|
||||
/// <param name="color"></param>
|
||||
private CIMSymbolReference CreateSymbol(esriGeometryType speckleGeometryType, Color color)
|
||||
{
|
||||
var symbol = SymbolFactory
|
||||
.Instance.ConstructPointSymbol(ColorFactory.Instance.CreateColor(color))
|
||||
.MakeSymbolReference();
|
||||
|
||||
switch (speckleGeometryType)
|
||||
{
|
||||
case esriGeometryType.esriGeometryLine:
|
||||
case esriGeometryType.esriGeometryPolyline:
|
||||
symbol = SymbolFactory
|
||||
.Instance.ConstructLineSymbol(ColorFactory.Instance.CreateColor(color))
|
||||
.MakeSymbolReference();
|
||||
break;
|
||||
case esriGeometryType.esriGeometryPolygon:
|
||||
case esriGeometryType.esriGeometryMultiPatch:
|
||||
symbol = SymbolFactory
|
||||
.Instance.ConstructPolygonSymbol(ColorFactory.Instance.CreateColor(color))
|
||||
.MakeSymbolReference();
|
||||
break;
|
||||
}
|
||||
|
||||
return symbol;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add CIMUniqueValueClass to Layer Renderer (if exists); apply Renderer to Layer (again)
|
||||
/// </summary>
|
||||
/// <param name="tc"></param>
|
||||
/// <param name="trackerItem"></param>
|
||||
public CIMUniqueValueRenderer? CreateOrEditLayerRenderer(
|
||||
TraversalContext tc,
|
||||
ObjectConversionTracker trackerItem,
|
||||
CIMRenderer? existingRenderer
|
||||
)
|
||||
{
|
||||
if (trackerItem.HostAppMapMember is not FeatureLayer fLayer)
|
||||
{
|
||||
// do nothing with non-feature layers
|
||||
return null;
|
||||
}
|
||||
|
||||
// declare default grey color, create default symbol for the given layer geometry type
|
||||
var color = Color.FromArgb(CIMColorToInt(ColorFactory.Instance.GreyRGB));
|
||||
CIMSymbolReference defaultSymbol = CreateSymbol(fLayer.ShapeType, color);
|
||||
|
||||
// get existing renderer classes
|
||||
List<CIMUniqueValueClass> listUniqueValueClasses = new() { };
|
||||
if (existingRenderer is CIMUniqueValueRenderer uniqueRenderer)
|
||||
{
|
||||
if (uniqueRenderer.Groups[0].Classes != null)
|
||||
{
|
||||
listUniqueValueClasses.AddRange(uniqueRenderer.Groups[0].Classes.ToList());
|
||||
}
|
||||
}
|
||||
|
||||
// Add new CIMUniqueValueClass (or multiple, if it's a Collection with elements, e.g. VectorLayer)
|
||||
List<TraversalContext> traversalContexts = new();
|
||||
if (tc.Current is Collection collection)
|
||||
{
|
||||
foreach (var element in collection.elements)
|
||||
{
|
||||
TraversalContext newTc = new(element, "elements", tc);
|
||||
traversalContexts.Add(newTc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
traversalContexts.Add(tc);
|
||||
}
|
||||
|
||||
foreach (var tContext in traversalContexts)
|
||||
{
|
||||
// get unique label
|
||||
string? uniqueLabel = tContext.Current?.id;
|
||||
|
||||
// remove any GIS-specific classes for now
|
||||
/*
|
||||
if (tContext.Current is IGisFeature gisFeat)
|
||||
{
|
||||
var existingLabel = gisFeat.attributes["Speckle_ID"];
|
||||
if (existingLabel is string stringLabel)
|
||||
{
|
||||
uniqueLabel = stringLabel;
|
||||
}
|
||||
}*/
|
||||
|
||||
if (uniqueLabel is not null && !listUniqueValueClasses.Select(x => x.Label).Contains(uniqueLabel))
|
||||
{
|
||||
CIMUniqueValueClass newUniqueValueClass = CreateColorCategory(tContext, fLayer.ShapeType, uniqueLabel);
|
||||
listUniqueValueClasses.Add(newUniqueValueClass);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a list of CIMUniqueValueGroup
|
||||
CIMUniqueValueGroup uvg = new() { Classes = listUniqueValueClasses.ToArray(), Heading = "Speckle_ID" };
|
||||
List<CIMUniqueValueGroup> listUniqueValueGroups = new() { uvg };
|
||||
// Create the CIMUniqueValueRenderer
|
||||
CIMUniqueValueRenderer uvr =
|
||||
new()
|
||||
{
|
||||
UseDefaultSymbol = true,
|
||||
DefaultLabel = "all other values",
|
||||
DefaultSymbol = defaultSymbol,
|
||||
Groups = listUniqueValueGroups.ToArray(),
|
||||
Fields = new string[] { "Speckle_ID" }
|
||||
};
|
||||
return uvr;
|
||||
}
|
||||
}
|
||||
@@ -1,461 +0,0 @@
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using Speckle.Sdk.Models.Proxies;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.HostApp;
|
||||
|
||||
public class ArcGISColorUnpacker
|
||||
{
|
||||
/// <summary>
|
||||
/// Cache of all color proxies for converted features. Key is the Color proxy argb value.
|
||||
/// </summary>
|
||||
public Dictionary<int, ColorProxy> ColorProxyCache { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Stores the current renderer (determined by mapMember)
|
||||
/// </summary>
|
||||
private AC.CIM.CIMRenderer? StoredRenderer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Stores the current renderer (determined by tin mapmember)
|
||||
/// </summary>
|
||||
private AC.CIM.CIMTinRenderer? StoredTinRenderer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Stores the used renderer fields from the layer
|
||||
/// </summary>
|
||||
private List<string> StoredRendererFields { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Stores an already processed color for current mapMember, to dbe used by all mapMember objects. Only applies to simple type renderers
|
||||
/// </summary>
|
||||
private int? StoredColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Stores a feature layer renderer to be used by <see cref="ProcessFeatureLayerColor"/> in <see cref="StoredRenderer"/>, any fields used by the renderer from the layer, and resets the <see cref="StoredColor"/> and <see cref="StoredRendererFields"/>
|
||||
/// </summary>
|
||||
/// <param name="featureLayer"></param>
|
||||
/// <exception cref="AC.CalledOnWrongThreadException">Must be called on MCT.</exception>
|
||||
public void StoreRendererAndFields(ADM.FeatureLayer featureLayer)
|
||||
{
|
||||
// field names are unique, but often their alias is used instead by renderer headings
|
||||
// so we are storing both names and alias in this dictionary for fast lookup
|
||||
// POC: adding aliases are not optimal, because they do not need to be unique && they can be the same as the name of another field
|
||||
Dictionary<string, string> layerFieldDictionary = new();
|
||||
foreach (ADM.FieldDescription field in featureLayer.GetFieldDescriptions())
|
||||
{
|
||||
layerFieldDictionary.TryAdd(field.Name, field.Name);
|
||||
layerFieldDictionary.TryAdd(field.Alias, field.Name);
|
||||
}
|
||||
|
||||
// clear stored values
|
||||
StoredRendererFields = new();
|
||||
StoredColor = null;
|
||||
StoredRenderer = null;
|
||||
|
||||
AC.CIM.CIMRenderer layerRenderer = featureLayer.GetRenderer();
|
||||
List<string> fields = new();
|
||||
bool isSupported = false;
|
||||
switch (layerRenderer)
|
||||
{
|
||||
case AC.CIM.CIMSimpleRenderer:
|
||||
isSupported = true;
|
||||
break;
|
||||
case AC.CIM.CIMUniqueValueRenderer uniqueValueRenderer:
|
||||
isSupported = true;
|
||||
fields = uniqueValueRenderer.Fields.ToList();
|
||||
break;
|
||||
case AC.CIM.CIMClassBreaksRenderer classBreaksRenderer:
|
||||
isSupported = true;
|
||||
fields.Add(classBreaksRenderer.Field);
|
||||
break;
|
||||
default:
|
||||
// TODO: log error here that a renderer is unsupported
|
||||
break;
|
||||
}
|
||||
|
||||
if (isSupported)
|
||||
{
|
||||
StoredRenderer = layerRenderer;
|
||||
foreach (string field in fields)
|
||||
{
|
||||
if (layerFieldDictionary.TryGetValue(field, out string? fieldName))
|
||||
{
|
||||
StoredRendererFields.Add(fieldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a las layer renderer to be used by <see cref="ProcessLasLayerColor"/> in <see cref="StoredTinRenderer"/>
|
||||
/// </summary>
|
||||
/// <param name="lasLayer"></param>
|
||||
/// <exception cref="AC.CalledOnWrongThreadException">Must be called on MCT.</exception>
|
||||
public void StoreRenderer(ADM.LasDatasetLayer lasLayer)
|
||||
{
|
||||
// clear stored values
|
||||
StoredTinRenderer = null;
|
||||
|
||||
// POC: not sure why we are only using the first renderer here
|
||||
AC.CIM.CIMTinRenderer layerRenderer = lasLayer.GetRenderers()[0];
|
||||
bool isSupported = false;
|
||||
switch (layerRenderer)
|
||||
{
|
||||
case AC.CIM.CIMTinUniqueValueRenderer:
|
||||
isSupported = true;
|
||||
break;
|
||||
default:
|
||||
// TODO: log error here that a renderer is unsupported
|
||||
break;
|
||||
}
|
||||
|
||||
if (isSupported)
|
||||
{
|
||||
StoredTinRenderer = layerRenderer;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes a las layer's point color by the stored <see cref="StoredRenderer"/>, and stores the point's id and color proxy to the <see cref="ColorProxyCache"/>.
|
||||
/// POC: logic probably can be combined with ProcessFeatureLayerColor.
|
||||
/// </summary>
|
||||
/// <param name="point"></param>
|
||||
public void ProcessLasLayerColor(ACD.Analyst3D.LasPoint point, string pointApplicationId)
|
||||
{
|
||||
// get the color from the renderer and point
|
||||
AC.CIM.CIMColor? color;
|
||||
switch (StoredTinRenderer)
|
||||
{
|
||||
case AC.CIM.CIMTinUniqueValueRenderer uniqueValueRenderer:
|
||||
color = GetPointColorByUniqueValueRenderer(uniqueValueRenderer, point);
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
// get or create the color proxy for the point
|
||||
int argb = CIMColorToInt(color ?? point.RGBColor);
|
||||
AddObjectIdToColorProxyCache(pointApplicationId, argb);
|
||||
}
|
||||
|
||||
// Retrieves the las point color from a unique value renderer
|
||||
// unique renderers have groups of conditions that may affect the color of a feature
|
||||
// resulting in a different color than the default renderer symbol color
|
||||
private AC.CIM.CIMColor? GetPointColorByUniqueValueRenderer(
|
||||
AC.CIM.CIMTinUniqueValueRenderer renderer,
|
||||
ACD.Analyst3D.LasPoint point
|
||||
)
|
||||
{
|
||||
foreach (AC.CIM.CIMUniqueValueGroup group in renderer.Groups)
|
||||
{
|
||||
foreach (AC.CIM.CIMUniqueValueClass groupClass in group.Classes)
|
||||
{
|
||||
foreach (AC.CIM.CIMUniqueValue value in groupClass.Values)
|
||||
{
|
||||
// all field values have to match the row values
|
||||
for (int i = 0; i < value.FieldValues.Length; i++)
|
||||
{
|
||||
string groupValue = value.FieldValues[i].Replace("<Null>", "");
|
||||
object? pointValue = point.ClassCode;
|
||||
|
||||
if (ValuesAreEqual(groupValue, pointValue))
|
||||
{
|
||||
return groupClass.Symbol.Symbol.GetColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes a feature layer's row color by the stored <see cref="StoredRenderer"/>, and stores the row's id and color proxy to the <see cref="ColorProxyCache"/>.
|
||||
/// </summary>
|
||||
/// <param name="row"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ACD.Exceptions.GeodatabaseException"></exception>
|
||||
public void ProcessFeatureLayerColor(ACD.Row row, string rowApplicationId)
|
||||
{
|
||||
// if stored color is not null, this means the renderer was a simple renderer that applies to the entire layer, and was already created.
|
||||
// just add the row application id to the color proxy.
|
||||
if (StoredColor is int existingColorProxyId)
|
||||
{
|
||||
AddObjectIdToColorProxyCache(rowApplicationId, existingColorProxyId);
|
||||
return;
|
||||
}
|
||||
|
||||
// get the color from the renderer and row
|
||||
AC.CIM.CIMColor? color = null;
|
||||
switch (StoredRenderer)
|
||||
{
|
||||
// simple renderers do not rely on fields, so the color can be retrieved from the renderer directly
|
||||
case AC.CIM.CIMSimpleRenderer simpleRenderer:
|
||||
color = simpleRenderer.Symbol.Symbol.GetColor();
|
||||
break;
|
||||
|
||||
case AC.CIM.CIMUniqueValueRenderer uniqueValueRenderer:
|
||||
color = GetRowColorByUniqueValueRenderer(uniqueValueRenderer, row);
|
||||
break;
|
||||
|
||||
case AC.CIM.CIMClassBreaksRenderer classBreaksRenderer:
|
||||
color = GetRowColorByClassBreaksRenderer(classBreaksRenderer, row);
|
||||
break;
|
||||
}
|
||||
|
||||
if (color is null)
|
||||
{
|
||||
// TODO: log error or throw exception that color could not be retrieved
|
||||
return;
|
||||
}
|
||||
|
||||
// get or create the color proxy for the row
|
||||
int argb = CIMColorToInt(color);
|
||||
AddObjectIdToColorProxyCache(rowApplicationId, argb);
|
||||
|
||||
// store color if from simple renderer
|
||||
if (StoredRenderer is AC.CIM.CIMSimpleRenderer)
|
||||
{
|
||||
StoredColor = argb;
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieves the row color from a class breaks renderer
|
||||
// unique renderers have groups of conditions that may affect the color of a feature
|
||||
// resulting in a different color than the default renderer symbol color
|
||||
private AC.CIM.CIMColor? GetRowColorByClassBreaksRenderer(AC.CIM.CIMClassBreaksRenderer renderer, ACD.Row row)
|
||||
{
|
||||
AC.CIM.CIMColor? color = null;
|
||||
|
||||
// get the default symbol color
|
||||
if (renderer.DefaultSymbol?.Symbol.GetColor() is AC.CIM.CIMColor defaultColor)
|
||||
{
|
||||
color = defaultColor;
|
||||
}
|
||||
|
||||
// get the first stored field, since this renderer should only have 1 field
|
||||
double storedFieldValue = Convert.ToDouble(row[StoredRendererFields.First()]);
|
||||
|
||||
List<AC.CIM.CIMClassBreak> reversedBreaks = new(renderer.Breaks);
|
||||
reversedBreaks.Reverse();
|
||||
foreach (var rBreak in reversedBreaks)
|
||||
{
|
||||
// keep looping until the last matching condition
|
||||
if (storedFieldValue <= rBreak.UpperBound)
|
||||
{
|
||||
if (rBreak.Symbol.Symbol.GetColor() is AC.CIM.CIMColor breakColor)
|
||||
{
|
||||
color = breakColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: log error here, could not retrieve break color from symbol
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
// Retrieves the row color from a unique value renderer
|
||||
// unique renderers have groups of conditions that may affect the color of a feature
|
||||
// resulting in a different color than the default renderer symbol color
|
||||
private AC.CIM.CIMColor? GetRowColorByUniqueValueRenderer(AC.CIM.CIMUniqueValueRenderer renderer, ACD.Row row)
|
||||
{
|
||||
AC.CIM.CIMColor? color = null;
|
||||
|
||||
// get the default symbol color
|
||||
if (renderer.DefaultSymbol?.Symbol.GetColor() is AC.CIM.CIMColor defaultColor)
|
||||
{
|
||||
color = defaultColor;
|
||||
}
|
||||
|
||||
// note: usually there is only 1 group
|
||||
foreach (AC.CIM.CIMUniqueValueGroup group in renderer.Groups)
|
||||
{
|
||||
// loop through all values in groups to see if any have met conditions that result in a different color
|
||||
foreach (AC.CIM.CIMUniqueValueClass groupClass in group.Classes)
|
||||
{
|
||||
bool groupConditionsMet = true;
|
||||
foreach (AC.CIM.CIMUniqueValue value in groupClass.Values)
|
||||
{
|
||||
// all field values have to match the row values
|
||||
for (int i = 0; i < StoredRendererFields.Count; i++)
|
||||
{
|
||||
string groupValue = value.FieldValues[i];
|
||||
object? rowValue = row[StoredRendererFields[i]];
|
||||
|
||||
if (!ValuesAreEqual(groupValue, rowValue))
|
||||
{
|
||||
groupConditionsMet = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set the group color to class symbol color if conditions are met
|
||||
if (groupConditionsMet)
|
||||
{
|
||||
if (groupClass.Symbol.Symbol.GetColor() is AC.CIM.CIMColor groupColor)
|
||||
{
|
||||
color = groupColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: log error here, could not retrieve group color from symbol
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares the label string of a UniqueValueRenderer (groupValue), and an object value (row, las point), to determine if they are equal
|
||||
/// </summary>
|
||||
/// <param name="objectValue"></param>
|
||||
/// <param name="groupValue"></param>
|
||||
private bool ValuesAreEqual(string groupValue, object? objectValue)
|
||||
{
|
||||
switch (objectValue)
|
||||
{
|
||||
case int:
|
||||
case short:
|
||||
case long:
|
||||
case byte:
|
||||
string objectValueString = Convert.ToString(objectValue) ?? "";
|
||||
return groupValue.Equals(objectValueString);
|
||||
|
||||
case string:
|
||||
return groupValue.Equals(objectValue);
|
||||
|
||||
// POC: these are tricky to compare with the label strings accurately, so will trim both values to 5 decimal places.
|
||||
case double d:
|
||||
return double.TryParse(groupValue, out double groupDouble) && groupDouble - d < 0.000001;
|
||||
case float f:
|
||||
return float.TryParse(groupValue, out float groupFloat) && groupFloat - f < 0.000001;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void AddObjectIdToColorProxyCache(string objectId, int argb)
|
||||
{
|
||||
if (ColorProxyCache.TryGetValue(argb, out ColorProxy? colorProxy))
|
||||
{
|
||||
colorProxy.objects.Add(objectId);
|
||||
}
|
||||
else
|
||||
{
|
||||
ColorProxy newColorProxy =
|
||||
new()
|
||||
{
|
||||
name = argb.ToString(),
|
||||
objects = new() { objectId },
|
||||
value = argb,
|
||||
applicationId = argb.ToString()
|
||||
};
|
||||
|
||||
ColorProxyCache.Add(argb, newColorProxy);
|
||||
}
|
||||
}
|
||||
|
||||
private int ArgbToInt(int a, int r, int g, int b)
|
||||
{
|
||||
return (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
|
||||
// Gets the argb int from a CIMColor
|
||||
// Defaults to assuming CIMColor.Values represent the red, green, and blue channels.
|
||||
private int CIMColorToInt(AC.CIM.CIMColor color)
|
||||
{
|
||||
switch (color)
|
||||
{
|
||||
case AC.CIM.CIMHSVColor hsv:
|
||||
(float hsvR, float hsvG, float hsvB) = RgbFromHsv(hsv.H, hsv.S, hsv.V);
|
||||
return ArgbToInt(
|
||||
(int)Math.Round(hsv.Alpha),
|
||||
(int)Math.Round(hsvR * 255),
|
||||
(int)Math.Round(hsvG * 255),
|
||||
(int)Math.Round(hsvB * 255)
|
||||
);
|
||||
|
||||
case AC.CIM.CIMCMYKColor cmyk:
|
||||
float k = cmyk.K;
|
||||
int cmykR = Convert.ToInt32(255 * (1 - cmyk.C) * (1 - k));
|
||||
int cmykG = Convert.ToInt32(255 * (1 - cmyk.M) * (1 - k));
|
||||
int cmykB = Convert.ToInt32(255 * (1 - cmyk.Y) * (1 - k));
|
||||
return ArgbToInt((int)Math.Round(cmyk.Alpha), cmykR, cmykG, cmykB);
|
||||
|
||||
default:
|
||||
return ArgbToInt(
|
||||
(int)Math.Round(color.Alpha),
|
||||
(int)Math.Round(color.Values[0]),
|
||||
(int)Math.Round(color.Values[1]),
|
||||
(int)Math.Round(color.Values[2])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private (float, float, float) RgbFromHsv(float hue, float saturation, float value)
|
||||
{
|
||||
// Translates HSV color to RGB color
|
||||
// H: 0.0 - 360.0, S: 0.0 - 100.0, V: 0.0 - 100.0
|
||||
// R, G, B: 0.0 - 1.0
|
||||
|
||||
float c = (value / 100) * (saturation / 100);
|
||||
float x = c * (1 - Math.Abs(((hue / 60) % 2) - 1));
|
||||
float m = (value / 100) - c;
|
||||
|
||||
float r = 0;
|
||||
float g = 0;
|
||||
float b = 0;
|
||||
|
||||
if (hue >= 0 && hue < 60)
|
||||
{
|
||||
r = c;
|
||||
g = x;
|
||||
b = 0;
|
||||
}
|
||||
else if (hue >= 60 && hue < 120)
|
||||
{
|
||||
r = x;
|
||||
g = c;
|
||||
b = 0;
|
||||
}
|
||||
else if (hue >= 120 && hue < 180)
|
||||
{
|
||||
r = 0;
|
||||
g = c;
|
||||
b = x;
|
||||
}
|
||||
else if (hue >= 180 && hue < 240)
|
||||
{
|
||||
r = 0;
|
||||
g = x;
|
||||
b = c;
|
||||
}
|
||||
else if (hue >= 240 && hue < 300)
|
||||
{
|
||||
r = x;
|
||||
g = 0;
|
||||
b = c;
|
||||
}
|
||||
else if (hue >= 300 && hue < 360)
|
||||
{
|
||||
r = c;
|
||||
g = 0;
|
||||
b = x;
|
||||
}
|
||||
|
||||
r += m;
|
||||
g += m;
|
||||
b += m;
|
||||
|
||||
return (r, g, b);
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
using Speckle.Connectors.ArcGIS.HostApp.Extensions;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.HostApp;
|
||||
|
||||
public class ArcGISLayerUnpacker
|
||||
{
|
||||
/// <summary>
|
||||
/// Cache of all collections created by unpacked Layer MapMembers. Key is the Speckle applicationId (Layer URI).
|
||||
/// </summary>
|
||||
public Dictionary<string, Collection> CollectionCache { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Mapmembers can be layers containing objects, or LayerContainers containing other layers.
|
||||
/// Unpacks selected mapMembers and creates their corresponding collection on the root collection.
|
||||
/// </summary>
|
||||
/// <param name="mapMembers"></param>
|
||||
/// <param name="parentCollection"></param>
|
||||
/// <returns>List of layers containing objects.</returns>
|
||||
/// <exception cref="AC.CalledOnWrongThreadException">Thrown when this method is *not* called on the MCT, because this method accesses mapmember fields</exception>
|
||||
public List<ADM.MapMember> UnpackSelection(
|
||||
IEnumerable<ADM.MapMember> mapMembers,
|
||||
Collection parentCollection,
|
||||
List<ADM.MapMember>? objects = null
|
||||
)
|
||||
{
|
||||
if (objects is null)
|
||||
{
|
||||
objects = new();
|
||||
}
|
||||
|
||||
foreach (ADM.MapMember mapMember in mapMembers)
|
||||
{
|
||||
switch (mapMember)
|
||||
{
|
||||
case ADM.ILayerContainer container:
|
||||
Collection containerCollection = CreateAndCacheMapMemberCollection(mapMember, true);
|
||||
parentCollection.elements.Add(containerCollection);
|
||||
|
||||
UnpackSelection(container.Layers, containerCollection, objects);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!(objects.Contains(mapMember)))
|
||||
{
|
||||
Collection collection = CreateAndCacheMapMemberCollection(mapMember);
|
||||
parentCollection.elements.Add(collection);
|
||||
objects.Add(mapMember);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return objects;
|
||||
}
|
||||
|
||||
private Collection CreateAndCacheMapMemberCollection(ADM.MapMember mapMember, bool isLayerContainer = false)
|
||||
{
|
||||
string mapMemberApplicationId = mapMember.GetSpeckleApplicationId();
|
||||
Collection collection =
|
||||
new()
|
||||
{
|
||||
name = mapMember.Name,
|
||||
applicationId = mapMemberApplicationId,
|
||||
["type"] = mapMember.GetType().Name
|
||||
};
|
||||
|
||||
switch (mapMember)
|
||||
{
|
||||
case ADM.IDisplayTable displayTable: // get fields from layers that implement IDisplayTable, eg FeatureLayer or StandaloneTable
|
||||
Dictionary<string, string>? fields = displayTable
|
||||
.GetFieldDescriptions()
|
||||
.ToDictionary(field => field.Name, field => field.Type.ToString());
|
||||
collection["fields"] = fields;
|
||||
if (mapMember is ADM.BasicFeatureLayer basicFeatureLayer)
|
||||
{
|
||||
collection["shapeType"] = basicFeatureLayer.ShapeType.ToString();
|
||||
}
|
||||
break;
|
||||
|
||||
case ADM.Layer layer:
|
||||
collection["mapLayerType"] = layer.MapLayerType.ToString();
|
||||
break;
|
||||
|
||||
case ADM.ILayerContainer:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!isLayerContainer) // do not cache layer containers, since these won't contain any objects
|
||||
{
|
||||
CollectionCache.Add(mapMemberApplicationId, collection);
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
using ArcGIS.Core.Data.Raster;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.HostApp.Extensions;
|
||||
|
||||
public static class SpeckleApplicationIdExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves the Speckle application id for map members
|
||||
/// </summary>
|
||||
public static string GetSpeckleApplicationId(this ADM.MapMember mapMember) => mapMember.URI;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs the Speckle application id for Features as a concatenation of the layer URI (applicationId)
|
||||
/// and the row OID (index of row in layer).
|
||||
/// </summary>
|
||||
/// <exception cref="ACD.Exceptions.GeodatabaseException">Throws when this is *not* called on MCT. Use QueuedTask.Run.</exception>
|
||||
public static string GetSpeckleApplicationId(this ACD.Row row, string layerApplicationId) =>
|
||||
$"{layerApplicationId}_{row.GetObjectID()}";
|
||||
|
||||
/// <summary>
|
||||
/// Constructs the Speckle application id for Raster as a concatenation of the layer URI (applicationId) and 0-index
|
||||
/// </summary>
|
||||
public static string GetSpeckleApplicationId(this Raster _, string layerApplicationId) => $"{layerApplicationId}_0";
|
||||
|
||||
/// <summary>
|
||||
/// Constructs the Speckle application id for LasDatasets as a concatenation of the layer URI (applicationId)
|
||||
/// and point OID.
|
||||
/// </summary>
|
||||
public static string GetSpeckleApplicationId(this ACD.Analyst3D.LasPoint point, string layerApplicationId) =>
|
||||
$"{layerApplicationId}_{point.PointID}";
|
||||
}
|
||||
|
Before Width: | Height: | Size: 524 B |
|
Before Width: | Height: | Size: 948 B |
|
Before Width: | Height: | Size: 714 B |
|
Before Width: | Height: | Size: 1.6 KiB |
@@ -1,411 +0,0 @@
|
||||
using System.Diagnostics.Contracts;
|
||||
using ArcGIS.Core.CIM;
|
||||
using ArcGIS.Core.Geometry;
|
||||
using ArcGIS.Desktop.Framework.Threading.Tasks;
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
using Speckle.Connectors.ArcGIS.HostApp;
|
||||
using Speckle.Connectors.ArcGIS.Utils;
|
||||
using Speckle.Connectors.Common.Builders;
|
||||
using Speckle.Connectors.Common.Conversion;
|
||||
using Speckle.Connectors.Common.Instances;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Converters.ArcGIS3;
|
||||
using Speckle.Converters.ArcGIS3.Utils;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Objects.Data;
|
||||
using Speckle.Objects.Other;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using Speckle.Sdk.Models.GraphTraversal;
|
||||
using Speckle.Sdk.Models.Instances;
|
||||
using Speckle.Sdk.Models.Proxies;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Operations.Receive;
|
||||
|
||||
public class ArcGISHostObjectBuilder : IHostObjectBuilder
|
||||
{
|
||||
private readonly IRootToHostConverter _converter;
|
||||
private readonly IFeatureClassUtils _featureClassUtils;
|
||||
private readonly ILocalToGlobalUnpacker _localToGlobalUnpacker;
|
||||
private readonly LocalToGlobalConverterUtils _localToGlobalConverterUtils;
|
||||
|
||||
// POC: figure out the correct scope to only initialize on Receive
|
||||
private readonly IConverterSettingsStore<ArcGISConversionSettings> _settingsStore;
|
||||
private readonly GraphTraversal _traverseFunction;
|
||||
private readonly ArcGISColorManager _colorManager;
|
||||
|
||||
public ArcGISHostObjectBuilder(
|
||||
IRootToHostConverter converter,
|
||||
IConverterSettingsStore<ArcGISConversionSettings> settingsStore,
|
||||
IFeatureClassUtils featureClassUtils,
|
||||
ILocalToGlobalUnpacker localToGlobalUnpacker,
|
||||
LocalToGlobalConverterUtils localToGlobalConverterUtils,
|
||||
GraphTraversal traverseFunction,
|
||||
ArcGISColorManager colorManager
|
||||
)
|
||||
{
|
||||
_converter = converter;
|
||||
_settingsStore = settingsStore;
|
||||
_featureClassUtils = featureClassUtils;
|
||||
_localToGlobalUnpacker = localToGlobalUnpacker;
|
||||
_localToGlobalConverterUtils = localToGlobalConverterUtils;
|
||||
_traverseFunction = traverseFunction;
|
||||
_colorManager = colorManager;
|
||||
}
|
||||
|
||||
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,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
// TODO get spatialRef and offsets & rotation from ProjectInfo in CommitObject
|
||||
// ATM, GIS commit CRS is stored per layer (in FeatureClass converter), but should be moved to the Root level too
|
||||
|
||||
// Prompt the UI conversion started. Progress bar will swoosh.
|
||||
onOperationProgressed.Report(new("Converting", null));
|
||||
|
||||
// get materials
|
||||
List<RenderMaterialProxy>? materials = (rootObject[ProxyKeys.RENDER_MATERIAL] as List<object>)
|
||||
?.Cast<RenderMaterialProxy>()
|
||||
.ToList();
|
||||
if (materials != null)
|
||||
{
|
||||
_colorManager.ParseMaterials(materials, onOperationProgressed);
|
||||
}
|
||||
|
||||
// get colors
|
||||
List<ColorProxy>? colors = (rootObject[ProxyKeys.COLOR] as List<object>)?.Cast<ColorProxy>().ToList();
|
||||
if (colors != null)
|
||||
{
|
||||
_colorManager.ParseColors(colors, onOperationProgressed);
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
IReadOnlyCollection<LocalToGlobalMap> objectsToConvert = GetObjectsToConvert(rootObject);
|
||||
Dictionary<TraversalContext, ObjectConversionTracker> conversionTracker = new();
|
||||
|
||||
// 1. convert everything
|
||||
List<ReceiveConversionResult> results = new(objectsToConvert.Count);
|
||||
List<string> bakedObjectIds = new();
|
||||
foreach (LocalToGlobalMap objectToConvert in objectsToConvert)
|
||||
{
|
||||
string[] path = GetLayerPath(objectToConvert.TraversalContext);
|
||||
Base obj = objectToConvert.AtomicObject;
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
try
|
||||
{
|
||||
obj = _localToGlobalConverterUtils.TransformObjects(objectToConvert.AtomicObject, objectToConvert.Matrix);
|
||||
object conversionResult = _converter.Convert(obj);
|
||||
|
||||
string nestedLayerPath = $"{string.Join("\\", path)}";
|
||||
|
||||
if (obj is ArcgisObject gisObj)
|
||||
{
|
||||
nestedLayerPath += $"\\{gisObj.name}";
|
||||
}
|
||||
else
|
||||
{
|
||||
nestedLayerPath += $"\\{obj.speckle_type.Split(".")[^1]}"; // add sub-layer by speckleType, for non-GIS objects
|
||||
}
|
||||
|
||||
conversionTracker[objectToConvert.TraversalContext] = new ObjectConversionTracker(
|
||||
obj,
|
||||
(Geometry?)conversionResult,
|
||||
nestedLayerPath
|
||||
);
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal()) // DO NOT CATCH SPECIFIC STUFF, conversion errors should be recoverable
|
||||
{
|
||||
results.Add(new(Status.ERROR, obj, null, null, ex));
|
||||
}
|
||||
onOperationProgressed.Report(new("Converting", (double)++count / objectsToConvert.Count));
|
||||
}
|
||||
|
||||
// 2.1. Group conversionTrackers (to write into datasets)
|
||||
onOperationProgressed.Report(new("Grouping features into layers", null));
|
||||
Dictionary<string, List<(TraversalContext, ObjectConversionTracker)>> convertedGroups =
|
||||
_featureClassUtils.GroupConversionTrackers(
|
||||
conversionTracker,
|
||||
(s, progres) => onOperationProgressed.Report(new(s, progres))
|
||||
);
|
||||
|
||||
// 2.2. Write groups of objects to Datasets
|
||||
onOperationProgressed.Report(new("Writing to Database", null));
|
||||
|
||||
_featureClassUtils.CreateDatasets(
|
||||
conversionTracker,
|
||||
convertedGroups,
|
||||
(s, progres) => onOperationProgressed.Report(new(s, progres))
|
||||
);
|
||||
|
||||
// 3. add layer and tables to the Map and Table Of Content
|
||||
|
||||
// Create placeholder for GroupLayers
|
||||
Dictionary<string, GroupLayer> createdLayerGroups = new();
|
||||
|
||||
int bakeCount = 0;
|
||||
Dictionary<string, (MapMember, CIMUniqueValueRenderer?)> bakedMapMembers = new();
|
||||
onOperationProgressed.Report(new("Adding to Map", bakeCount));
|
||||
|
||||
foreach (var item in conversionTracker)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var trackerItem = conversionTracker[item.Key]; // updated tracker object
|
||||
|
||||
// BAKE OBJECTS HERE
|
||||
if (trackerItem.Exception != null)
|
||||
{
|
||||
results.Add(new(Status.ERROR, trackerItem.Base, null, null, trackerItem.Exception));
|
||||
}
|
||||
else if (trackerItem.DatasetId == null)
|
||||
{
|
||||
results.Add(
|
||||
new(
|
||||
Status.ERROR,
|
||||
trackerItem.Base,
|
||||
null,
|
||||
null,
|
||||
new ArgumentException($"Unknown error: Dataset not created for {trackerItem.Base.speckle_type}")
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (bakedMapMembers.TryGetValue(trackerItem.DatasetId, out var value))
|
||||
{
|
||||
// if the layer already created, just add more features to report, and more color categories
|
||||
// add layer and layer URI to tracker
|
||||
trackerItem.AddConvertedMapMember(value.Item1);
|
||||
trackerItem.AddLayerURI(value.Item1.URI);
|
||||
conversionTracker[item.Key] = trackerItem; // not necessary atm, but needed if we use conversionTracker further
|
||||
|
||||
// add color category
|
||||
CIMUniqueValueRenderer? uvr = _colorManager.CreateOrEditLayerRenderer(item.Key, trackerItem, value.Item2);
|
||||
// replace renderer
|
||||
bakedMapMembers[trackerItem.DatasetId] = (value.Item1, uvr);
|
||||
|
||||
// only add a report item
|
||||
AddResultsFromTracker(trackerItem, results);
|
||||
}
|
||||
else
|
||||
{
|
||||
// no layer yet, create and add layer to Map
|
||||
MapMember mapMember = AddDatasetsToMap(trackerItem, createdLayerGroups, projectName, modelName);
|
||||
|
||||
// add layer and layer URI to tracker
|
||||
trackerItem.AddConvertedMapMember(mapMember);
|
||||
trackerItem.AddLayerURI(mapMember.URI);
|
||||
conversionTracker[item.Key] = trackerItem; // not necessary atm, but needed if we use conversionTracker further
|
||||
|
||||
// add layer URI to bakedIds
|
||||
bakedObjectIds.Add(trackerItem.MappedLayerURI == null ? "" : trackerItem.MappedLayerURI);
|
||||
|
||||
// add color category
|
||||
CIMUniqueValueRenderer? uvr = _colorManager.CreateOrEditLayerRenderer(item.Key, trackerItem, null);
|
||||
// mark dataset as already created
|
||||
bakedMapMembers[trackerItem.DatasetId] = (mapMember, uvr);
|
||||
|
||||
// add report item
|
||||
AddResultsFromTracker(trackerItem, results);
|
||||
}
|
||||
|
||||
onOperationProgressed.Report(new("Adding to Map", (double)++bakeCount / conversionTracker.Count));
|
||||
}
|
||||
|
||||
// apply renderers to baked layers
|
||||
foreach (var bakedMember in bakedMapMembers)
|
||||
{
|
||||
if (bakedMember.Value.Item1 is FeatureLayer fLayer)
|
||||
{
|
||||
// Set the feature layer's renderer.
|
||||
fLayer.SetRenderer(bakedMember.Value.Item2);
|
||||
}
|
||||
}
|
||||
bakedObjectIds.AddRange(createdLayerGroups.Values.Select(x => x.URI));
|
||||
|
||||
// TODO: validated a correct set regarding bakedobject ids
|
||||
return new HostObjectBuilderResult(bakedObjectIds, results);
|
||||
}
|
||||
|
||||
private IReadOnlyCollection<LocalToGlobalMap> GetObjectsToConvert(Base rootObject)
|
||||
{
|
||||
// keep GISlayers in the list, because they are still needed to extract CRS of the commit (code below)
|
||||
List<TraversalContext> objectsToConvertTc = _traverseFunction.Traverse(rootObject).ToList();
|
||||
|
||||
// now filter the objects
|
||||
objectsToConvertTc = objectsToConvertTc.Where(ctx => ctx.Current is not Collection).ToList();
|
||||
|
||||
var instanceDefinitionProxies = (rootObject[ProxyKeys.INSTANCE_DEFINITION] as List<object>)
|
||||
?.Cast<InstanceDefinitionProxy>()
|
||||
.ToList();
|
||||
|
||||
return _localToGlobalUnpacker.Unpack(instanceDefinitionProxies, objectsToConvertTc);
|
||||
}
|
||||
|
||||
private void AddResultsFromTracker(ObjectConversionTracker trackerItem, List<ReceiveConversionResult> results)
|
||||
{
|
||||
if (trackerItem.MappedLayerURI == null) // should not happen
|
||||
{
|
||||
results.Add(
|
||||
new(
|
||||
Status.ERROR,
|
||||
trackerItem.Base,
|
||||
null,
|
||||
null,
|
||||
new ArgumentException($"Created Layer URI not found for {trackerItem.Base.speckle_type}")
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// encode layer ID and ID of its feature in 1 object represented as string
|
||||
ObjectID objectId = new(trackerItem.MappedLayerURI, trackerItem.DatasetRow);
|
||||
if (trackerItem.HostAppGeom != null) // individual hostAppGeometry
|
||||
{
|
||||
results.Add(
|
||||
new(
|
||||
Status.SUCCESS,
|
||||
trackerItem.Base,
|
||||
objectId.ObjectIdToString(),
|
||||
trackerItem.HostAppGeom.GetType().ToString()
|
||||
)
|
||||
);
|
||||
}
|
||||
else // hostApp Layers
|
||||
{
|
||||
results.Add(
|
||||
new(
|
||||
Status.SUCCESS,
|
||||
trackerItem.Base,
|
||||
objectId.ObjectIdToString(),
|
||||
trackerItem.HostAppMapMember?.GetType().ToString()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private MapMember AddDatasetsToMap(
|
||||
ObjectConversionTracker trackerItem,
|
||||
Dictionary<string, GroupLayer> createdLayerGroups,
|
||||
string projectName,
|
||||
string modelName
|
||||
)
|
||||
{
|
||||
// get layer details
|
||||
string? datasetId = trackerItem.DatasetId; // should not be null here
|
||||
Uri uri = new($"{_settingsStore.Current.SpeckleDatabasePath.AbsolutePath.Replace('/', '\\')}\\{datasetId}");
|
||||
string nestedLayerName = trackerItem.NestedLayerName;
|
||||
|
||||
// add group for the current layer
|
||||
string shortName = nestedLayerName.Split("\\")[^1];
|
||||
string nestedLayerPath = string.Join("\\", nestedLayerName.Split("\\").SkipLast(1));
|
||||
|
||||
// if no general group layer found
|
||||
if (createdLayerGroups.Count == 0)
|
||||
{
|
||||
Map map = _settingsStore.Current.Map;
|
||||
GroupLayer mainGroupLayer = LayerFactory.Instance.CreateGroupLayer(map, 0, $"{projectName}: {modelName}");
|
||||
mainGroupLayer.SetExpanded(true);
|
||||
createdLayerGroups["Basic Speckle Group"] = mainGroupLayer; // key doesn't really matter here
|
||||
}
|
||||
|
||||
var groupLayer = CreateNestedGroupLayer(nestedLayerPath, createdLayerGroups);
|
||||
|
||||
// Most of the Speckle-written datasets will be containing geometry and added as Layers
|
||||
// although, some datasets might be just tables (e.g. native GIS Tables, in the future maybe Revit schedules etc.
|
||||
// We can create a connection to the dataset in advance and determine its type, but this will be more
|
||||
// expensive, than assuming by default that it's a layer with geometry (which in most cases it's expected to be)
|
||||
try
|
||||
{
|
||||
var layer = LayerFactory.Instance.CreateLayer(uri, groupLayer, layerName: shortName);
|
||||
if (layer == null)
|
||||
{
|
||||
throw new SpeckleException($"Layer '{shortName}' was not created");
|
||||
}
|
||||
layer.SetExpanded(false);
|
||||
|
||||
// if Scene
|
||||
// https://community.esri.com/t5/arcgis-pro-sdk-questions/sdk-equivalent-to-changing-layer-s-elevation/td-p/1346139
|
||||
if (_settingsStore.Current.Map.IsScene)
|
||||
{
|
||||
var groundSurfaceLayer = _settingsStore.Current.Map.GetGroundElevationSurfaceLayer();
|
||||
var layerElevationSurface = new CIMLayerElevationSurface { ElevationSurfaceLayerURI = groundSurfaceLayer.URI, };
|
||||
|
||||
// for Feature Layers
|
||||
if (layer.GetDefinition() is CIMFeatureLayer cimLyr)
|
||||
{
|
||||
cimLyr.LayerElevation = layerElevationSurface;
|
||||
layer.SetDefinition(cimLyr);
|
||||
}
|
||||
}
|
||||
|
||||
return layer;
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
StandaloneTable table = StandaloneTableFactory.Instance.CreateStandaloneTable(
|
||||
uri,
|
||||
groupLayer,
|
||||
tableName: shortName
|
||||
);
|
||||
return table;
|
||||
}
|
||||
}
|
||||
|
||||
private GroupLayer CreateNestedGroupLayer(string nestedLayerPath, Dictionary<string, GroupLayer> createdLayerGroups)
|
||||
{
|
||||
GroupLayer lastGroup = createdLayerGroups.FirstOrDefault().Value;
|
||||
if (lastGroup == null) // if layer not found
|
||||
{
|
||||
throw new InvalidOperationException("Speckle Layer Group not found");
|
||||
}
|
||||
|
||||
// iterate through each nested level
|
||||
string createdGroupPath = "";
|
||||
var allPathElements = nestedLayerPath.Split("\\").Where(x => !string.IsNullOrEmpty(x));
|
||||
foreach (string pathElement in allPathElements)
|
||||
{
|
||||
createdGroupPath += "\\" + pathElement;
|
||||
if (createdLayerGroups.TryGetValue(createdGroupPath, out var existingGroupLayer))
|
||||
{
|
||||
lastGroup = existingGroupLayer;
|
||||
}
|
||||
else
|
||||
{
|
||||
// create new GroupLayer under last found Group, named with last pathElement
|
||||
lastGroup = LayerFactory.Instance.CreateGroupLayer(lastGroup, 0, pathElement);
|
||||
lastGroup.SetExpanded(true);
|
||||
}
|
||||
createdLayerGroups[createdGroupPath] = lastGroup;
|
||||
}
|
||||
return lastGroup;
|
||||
}
|
||||
|
||||
[Pure]
|
||||
private static string[] GetLayerPath(TraversalContext context)
|
||||
{
|
||||
string[] collectionBasedPath = context.GetAscendantOfType<Collection>().Select(c => c.name).ToArray();
|
||||
string[] reverseOrderPath =
|
||||
collectionBasedPath.Length != 0 ? collectionBasedPath : context.GetPropertyPath().ToArray();
|
||||
|
||||
var originalPath = reverseOrderPath.Reverse().ToArray();
|
||||
return originalPath.Where(x => !string.IsNullOrEmpty(x)).ToArray();
|
||||
}
|
||||
}
|
||||
@@ -1,362 +0,0 @@
|
||||
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;
|
||||
using Speckle.Connectors.ArcGIS.Utils;
|
||||
using Speckle.Connectors.Common.Builders;
|
||||
using Speckle.Connectors.Common.Conversion;
|
||||
using Speckle.Connectors.Common.Extensions;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Converters.ArcGIS3;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Logging;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
|
||||
namespace Speckle.Connectors.ArcGis.Operations.Send;
|
||||
|
||||
/// <summary>
|
||||
/// Stateless builder object to turn an ISendFilter into a <see cref="Base"/> object
|
||||
/// </summary>
|
||||
public class ArcGISRootObjectBuilder : IRootObjectBuilder<ADM.MapMember>
|
||||
{
|
||||
private readonly IRootToSpeckleConverter _rootToSpeckleConverter;
|
||||
private readonly ArcGISLayerUnpacker _layerUnpacker;
|
||||
private readonly ArcGISColorUnpacker _colorUnpacker;
|
||||
private readonly IConverterSettingsStore<ArcGISConversionSettings> _converterSettings;
|
||||
private readonly ILogger<ArcGISRootObjectBuilder> _logger;
|
||||
private readonly ISdkActivityFactory _activityFactory;
|
||||
private readonly MapMembersUtils _mapMemberUtils;
|
||||
|
||||
public ArcGISRootObjectBuilder(
|
||||
ArcGISLayerUnpacker layerUnpacker,
|
||||
ArcGISColorUnpacker colorUnpacker,
|
||||
IConverterSettingsStore<ArcGISConversionSettings> converterSettings,
|
||||
IRootToSpeckleConverter rootToSpeckleConverter,
|
||||
ILogger<ArcGISRootObjectBuilder> logger,
|
||||
ISdkActivityFactory activityFactory,
|
||||
MapMembersUtils mapMemberUtils
|
||||
)
|
||||
{
|
||||
_layerUnpacker = layerUnpacker;
|
||||
_colorUnpacker = colorUnpacker;
|
||||
_converterSettings = converterSettings;
|
||||
_rootToSpeckleConverter = rootToSpeckleConverter;
|
||||
_logger = logger;
|
||||
_activityFactory = activityFactory;
|
||||
_mapMemberUtils = mapMemberUtils;
|
||||
}
|
||||
|
||||
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,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
// TODO: add a warning if Geographic CRS is set
|
||||
// "Data has been sent in the units 'degrees'. It is advisable to set the project CRS to Projected type (e.g. EPSG:32631) to be able to receive geometry correctly in CAD/BIM software"
|
||||
|
||||
|
||||
// 0 - Create Root collection and attach CRS properties
|
||||
// CRS properties are useful for data based workflows coming out of gis applications
|
||||
SpatialReference sr = _converterSettings.Current.ActiveCRSoffsetRotation.SpatialReference;
|
||||
Dictionary<string, object?> spatialReference =
|
||||
new()
|
||||
{
|
||||
["name"] = sr.Name,
|
||||
["unit"] = sr.Unit.Name,
|
||||
["wkid"] = sr.Wkid,
|
||||
["wkt"] = sr.Wkt,
|
||||
};
|
||||
|
||||
Dictionary<string, object?> crs =
|
||||
new()
|
||||
{
|
||||
["trueNorthRadians"] = _converterSettings.Current.ActiveCRSoffsetRotation.TrueNorthRadians,
|
||||
["latOffset"] = _converterSettings.Current.ActiveCRSoffsetRotation.LatOffset,
|
||||
["lonOffset"] = _converterSettings.Current.ActiveCRSoffsetRotation.LonOffset,
|
||||
["spatialReference"] = spatialReference
|
||||
};
|
||||
|
||||
Collection rootCollection =
|
||||
new()
|
||||
{
|
||||
name = ADM.MapView.Active.Map.Name,
|
||||
["units"] = _converterSettings.Current.SpeckleUnits,
|
||||
["crs"] = crs
|
||||
};
|
||||
|
||||
// 1 - Unpack the selected mapmembers
|
||||
// In Arcgis, mapmembers are collections of other mapmember or objects.
|
||||
// We need to unpack the selected mapmembers into all leaf-level mapmembers (containing just objects) and build the root collection structure during unpacking.
|
||||
// Mapmember dynamically attached properties are also added at this step.
|
||||
List<ADM.MapMember> unpackedLayers;
|
||||
Dictionary<ADM.MapMember, long> layersWithFeatureCount;
|
||||
long allFeaturesCount;
|
||||
ADM.Map map = ADM.MapView.Active.Map;
|
||||
IEnumerable<ADM.MapMember> layersOrdered = _mapMemberUtils.GetMapMembersInOrder(map, layers);
|
||||
using (var _ = _activityFactory.Start("Unpacking selection"))
|
||||
{
|
||||
unpackedLayers = _layerUnpacker.UnpackSelection(layersOrdered, rootCollection);
|
||||
|
||||
// count number of features to convert. Raster layers are counter as 1 feature for now (not ideal)
|
||||
layersWithFeatureCount = CountAllFeaturesInLayers(unpackedLayers);
|
||||
allFeaturesCount = layersWithFeatureCount.Values.Sum();
|
||||
}
|
||||
|
||||
List<SendConversionResult> results = new(unpackedLayers.Count);
|
||||
onOperationProgressed.Report(new("Converting", null));
|
||||
using (var convertingActivity = _activityFactory.Start("Converting objects"))
|
||||
{
|
||||
long count = 0;
|
||||
|
||||
foreach (var (layer, layerFeatureCount) in layersWithFeatureCount)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
string layerApplicationId = layer.GetSpeckleApplicationId();
|
||||
|
||||
try
|
||||
{
|
||||
// get the corresponding collection for this layer - we'll add all converted objects to the collection
|
||||
if (_layerUnpacker.CollectionCache.TryGetValue(layerApplicationId, out Collection? layerCollection))
|
||||
{
|
||||
var status = Status.SUCCESS;
|
||||
var sdkStatus = SdkActivityStatusCode.Ok;
|
||||
|
||||
// TODO: check cache first to see if this layer was previously converted
|
||||
/*
|
||||
if (_sendConversionCache.TryGetValue(
|
||||
sendInfo.ProjectId,
|
||||
layerApplicationId,
|
||||
out ObjectReference? value
|
||||
))
|
||||
{
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
switch (layer)
|
||||
{
|
||||
case ADM.FeatureLayer featureLayer:
|
||||
List<Base> convertedFeatureLayerObjects = ConvertFeatureLayerObjects(
|
||||
featureLayer,
|
||||
count,
|
||||
allFeaturesCount,
|
||||
onOperationProgressed,
|
||||
cancellationToken
|
||||
);
|
||||
layerCollection.elements.AddRange(convertedFeatureLayerObjects);
|
||||
break;
|
||||
case ADM.RasterLayer rasterLayer:
|
||||
List<Base> convertedRasterLayerObjects = ConvertRasterLayerObjects(
|
||||
rasterLayer,
|
||||
count,
|
||||
allFeaturesCount,
|
||||
onOperationProgressed,
|
||||
cancellationToken
|
||||
);
|
||||
layerCollection.elements.AddRange(convertedRasterLayerObjects);
|
||||
break;
|
||||
case ADM.LasDatasetLayer lasDatasetLayer:
|
||||
List<Base> convertedLasDatasetObjects = ConvertLasDatasetLayerObjects(
|
||||
lasDatasetLayer,
|
||||
count,
|
||||
allFeaturesCount,
|
||||
onOperationProgressed,
|
||||
cancellationToken
|
||||
);
|
||||
layerCollection.elements.AddRange(convertedLasDatasetObjects);
|
||||
break;
|
||||
default:
|
||||
status = Status.ERROR;
|
||||
sdkStatus = SdkActivityStatusCode.Error;
|
||||
break;
|
||||
}
|
||||
|
||||
count += layerFeatureCount;
|
||||
results.Add(new(status, layerApplicationId, layer.GetType().Name, layerCollection));
|
||||
convertingActivity?.SetStatus(sdkStatus);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new SpeckleException($"No converted Collection found for layer {layerApplicationId}.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
_logger.LogSendConversionError(ex, layer.GetType().Name);
|
||||
results.Add(new(Status.ERROR, layerApplicationId, layer.GetType().Name, null, ex));
|
||||
convertingActivity?.SetStatus(SdkActivityStatusCode.Error);
|
||||
convertingActivity?.RecordException(ex);
|
||||
}
|
||||
|
||||
await Task.Yield();
|
||||
}
|
||||
}
|
||||
|
||||
if (results.All(x => x.Status == Status.ERROR))
|
||||
{
|
||||
throw new SpeckleException("Failed to convert all objects."); // fail fast instead creating empty commit! It will appear as model card error with red color.
|
||||
}
|
||||
|
||||
// 3 - Add Color Proxies
|
||||
rootCollection[ProxyKeys.COLOR] = _colorUnpacker.ColorProxyCache.Values.ToList();
|
||||
|
||||
return new RootObjectBuilderResult(rootCollection, results);
|
||||
}
|
||||
|
||||
private Dictionary<ADM.MapMember, long> CountAllFeaturesInLayers(List<ADM.MapMember> unpackedLayers)
|
||||
{
|
||||
Dictionary<ADM.MapMember, long> layersFeatureCount = new();
|
||||
|
||||
foreach (ADM.MapMember layer in unpackedLayers)
|
||||
{
|
||||
switch (layer)
|
||||
{
|
||||
case ADM.FeatureLayer featureLayer:
|
||||
layersFeatureCount.Add(featureLayer, featureLayer.GetFeatureClass().GetCount());
|
||||
break;
|
||||
case ADM.RasterLayer rasterLayer:
|
||||
// count Raster layer as 1 feature: not optimal but this is the approach for now
|
||||
layersFeatureCount.Add(rasterLayer, 1);
|
||||
break;
|
||||
case ADM.LasDatasetLayer lasDatasetLayer:
|
||||
var dataset = lasDatasetLayer.GetLasDataset();
|
||||
// simple dataset.GetPointCount() keeps returning null, so switched to EstimatePointCount
|
||||
layersFeatureCount.Add(
|
||||
lasDatasetLayer,
|
||||
(long)dataset.EstimatePointCount(dataset.GetDefinition().GetExtent())
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return layersFeatureCount;
|
||||
}
|
||||
|
||||
private List<Base> ConvertFeatureLayerObjects(
|
||||
ADM.FeatureLayer featureLayer,
|
||||
long count,
|
||||
long allFeaturesCount,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
string layerApplicationId = featureLayer.GetSpeckleApplicationId();
|
||||
List<Base> convertedObjects = new();
|
||||
// store the layer renderer for color unpacking
|
||||
_colorUnpacker.StoreRendererAndFields(featureLayer);
|
||||
|
||||
// search the rows of the layer, where each row is treated like an object
|
||||
// RowCursor is IDisposable but is not being correctly picked up by IDE warnings.
|
||||
// This means we need to be carefully adding using statements based on the API documentation coming from each method/class
|
||||
using (ACD.RowCursor rowCursor = featureLayer.Search())
|
||||
{
|
||||
while (rowCursor.MoveNext())
|
||||
{
|
||||
// allow cancellation before every feature
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
// Same IDisposable issue appears to happen on Row class too. Docs say it should always be disposed of manually by the caller.
|
||||
using (ACD.Row row = rowCursor.Current)
|
||||
{
|
||||
// get application id. test for subtypes before defaulting to base type.
|
||||
Base converted = _rootToSpeckleConverter.Convert(row);
|
||||
string applicationId = row.GetSpeckleApplicationId(layerApplicationId);
|
||||
converted.applicationId = applicationId;
|
||||
|
||||
convertedObjects.Add(converted);
|
||||
|
||||
// process the object color
|
||||
_colorUnpacker.ProcessFeatureLayerColor(row, applicationId);
|
||||
}
|
||||
// update report
|
||||
onOperationProgressed.Report(new("Converting", (double)++count / allFeaturesCount));
|
||||
}
|
||||
}
|
||||
|
||||
return convertedObjects;
|
||||
}
|
||||
|
||||
// POC: raster colors are stored as mesh vertex colors in RasterToSpeckleConverter. Should probably move to color unpacker.
|
||||
private List<Base> ConvertRasterLayerObjects(
|
||||
ADM.RasterLayer rasterLayer,
|
||||
long count,
|
||||
long allFeaturesCount,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
string layerApplicationId = rasterLayer.GetSpeckleApplicationId();
|
||||
List<Base> convertedObjects = new();
|
||||
Raster raster = rasterLayer.GetRaster();
|
||||
|
||||
// check cancellation token before conversion
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
Base converted = _rootToSpeckleConverter.Convert(raster);
|
||||
string applicationId = raster.GetSpeckleApplicationId(layerApplicationId);
|
||||
converted.applicationId = applicationId;
|
||||
convertedObjects.Add(converted);
|
||||
|
||||
// update report
|
||||
onOperationProgressed.Report(new("Converting", (double)++count / allFeaturesCount));
|
||||
|
||||
return convertedObjects;
|
||||
}
|
||||
|
||||
private List<Base> ConvertLasDatasetLayerObjects(
|
||||
ADM.LasDatasetLayer lasDatasetLayer,
|
||||
long count,
|
||||
long allFeaturesCount,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
string layerApplicationId = lasDatasetLayer.GetSpeckleApplicationId();
|
||||
List<Base> convertedObjects = new();
|
||||
|
||||
try
|
||||
{
|
||||
// store the layer renderer for color unpacking
|
||||
_colorUnpacker.StoreRenderer(lasDatasetLayer);
|
||||
|
||||
using (ACD.Analyst3D.LasPointCursor ptCursor = lasDatasetLayer.SearchPoints(new ACD.Analyst3D.LasPointFilter()))
|
||||
{
|
||||
while (ptCursor.MoveNext())
|
||||
{
|
||||
// allow cancellation before every point
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
using (ACD.Analyst3D.LasPoint pt = ptCursor.Current)
|
||||
{
|
||||
Base converted = _rootToSpeckleConverter.Convert(pt);
|
||||
string applicationId = pt.GetSpeckleApplicationId(layerApplicationId);
|
||||
converted.applicationId = applicationId;
|
||||
convertedObjects.Add(converted);
|
||||
|
||||
// process the object color
|
||||
_colorUnpacker.ProcessLasLayerColor(pt, applicationId);
|
||||
}
|
||||
// update report
|
||||
onOperationProgressed.Report(new("Converting", (double)++count / allFeaturesCount));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ACD.Exceptions.TinException ex)
|
||||
{
|
||||
throw new SpeckleException("3D analyst extension is not enabled for .las layer operations", ex);
|
||||
}
|
||||
|
||||
return convertedObjects;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"profiles": {
|
||||
"Speckle.Connectors.ArcGIS3_all_users": {
|
||||
"commandName": "Executable",
|
||||
"executablePath": "C:\\Program Files\\ArcGIS\\Pro\\bin\\ArcGISPro.exe",
|
||||
"commandLineArgs": ""
|
||||
},
|
||||
"Speckle.Connectors.ArcGIS3_user": {
|
||||
"commandName": "Executable",
|
||||
"executablePath": "C:\\Users\\%USERNAME%\\AppData\\Local\\Programs\\ArcGIS\\Pro\\bin\\ArcGISPro.exe",
|
||||
"commandLineArgs": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<UseWPF>true</UseWPF>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<RootNameSpace>Speckle.Connectors.ArcGIS</RootNameSpace>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<EnableWindowsTargeting>true</EnableWindowsTargeting>
|
||||
<DefineConstants>$(DefineConstants);ARCGIS3</DefineConstants>
|
||||
<Configurations>Debug;Release;Local</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="Config.daml" />
|
||||
<Content Include="Images\s2logo_16.png" />
|
||||
<Content Include="Images\s2logo_32.png" />
|
||||
<Content Include="DarkImages\s2logo_16.png" />
|
||||
<Content Include="DarkImages\s2logo_32.png" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Esri.ArcGISPro.Extensions30" IncludeAssets="compile" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Converters\ArcGIS\Speckle.Converters.ArcGIS3\Speckle.Converters.ArcGIS3.csproj" />
|
||||
<ProjectReference Include="..\..\..\DUI3\Speckle.Connectors.DUI.WebView\Speckle.Connectors.DUI.WebView.csproj" />
|
||||
<ProjectReference Include="..\..\..\Sdk\Speckle.Connectors.Common\Speckle.Connectors.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="Esri.ArcGISPro.Extensions30.Speckle.targets" />
|
||||
</Project>
|
||||
@@ -1,42 +0,0 @@
|
||||
using ArcGIS.Desktop.Framework;
|
||||
using ArcGIS.Desktop.Framework.Contracts;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS;
|
||||
|
||||
internal sealed class SpeckleDUI3ViewModel : DockPane
|
||||
{
|
||||
private const string DOCKPANE_ID = "SpeckleDUI3_SpeckleDUI3";
|
||||
|
||||
internal static void Create()
|
||||
{
|
||||
var pane = FrameworkApplication.DockPaneManager.Find(DOCKPANE_ID);
|
||||
pane?.Activate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the pane is initialized.
|
||||
/// </summary>
|
||||
protected override async Task InitializeAsync()
|
||||
{
|
||||
await base.InitializeAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the pane is uninitialized.
|
||||
/// </summary>
|
||||
protected override async Task UninitializeAsync()
|
||||
{
|
||||
await base.UninitializeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Button implementation to create a new instance of the pane and activate it.
|
||||
/// </summary>
|
||||
internal sealed class SpeckleDUI3OpenButton : Button
|
||||
{
|
||||
protected override void OnClick()
|
||||
{
|
||||
SpeckleDUI3ViewModel.Create();
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using System.Windows.Controls;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Speckle.Connectors.DUI.WebView;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS;
|
||||
|
||||
public class SpeckleDUI3Wrapper : UserControl
|
||||
{
|
||||
public SpeckleDUI3Wrapper()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
Content = SpeckleModule.Current.Container.GetRequiredService<DUI3ControlWebView>();
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
using ArcGIS.Desktop.Framework;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Speckle.Connectors.ArcGIS.DependencyInjection;
|
||||
using Speckle.Connectors.Common;
|
||||
using Speckle.Connectors.DUI;
|
||||
using Speckle.Converters.ArcGIS3;
|
||||
using Module = ArcGIS.Desktop.Framework.Contracts.Module;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS;
|
||||
|
||||
/// <summary>
|
||||
/// This sample shows how to implement pane that contains an Edge WebView2 control using the built-in ArcGIS Pro SDK's WebBrowser control. For details on how to utilize the WebBrowser control in an add-in see here: https://github.com/Esri/arcgis-pro-sdk/wiki/ProConcepts-Framework#webbrowser For details on how to utilize the Microsoft Edge web browser control in an add-in see here: https://github.com/Esri/arcgis-pro-sdk/wiki/ProConcepts-Framework#webbrowser-control
|
||||
/// </summary>
|
||||
internal sealed class SpeckleModule : Module
|
||||
{
|
||||
private static SpeckleModule? s_this;
|
||||
private readonly IDisposable? _disposableLogger;
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the singleton instance to this module here
|
||||
/// </summary>
|
||||
public static SpeckleModule Current =>
|
||||
s_this ??= (SpeckleModule)FrameworkApplication.FindModule("ConnectorArcGIS_Module");
|
||||
|
||||
public ServiceProvider Container { get; }
|
||||
|
||||
public SpeckleModule()
|
||||
{
|
||||
AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolver.OnAssemblyResolve<SpeckleModule>;
|
||||
|
||||
var services = new ServiceCollection();
|
||||
// init DI
|
||||
_disposableLogger = services.Initialize(HostApplications.ArcGIS, GetVersion());
|
||||
services.AddArcGIS();
|
||||
services.AddArcGISConverters();
|
||||
Container = services.BuildServiceProvider();
|
||||
Container.UseDUI();
|
||||
}
|
||||
|
||||
private HostAppVersion GetVersion()
|
||||
{
|
||||
#if ARCGIS3
|
||||
return HostAppVersion.v3;
|
||||
#else
|
||||
throw new NotImplementedException();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by Framework when ArcGIS Pro is closing
|
||||
/// </summary>
|
||||
/// <returns>False to prevent Pro from closing, otherwise True</returns>
|
||||
protected override bool CanUnload()
|
||||
{
|
||||
//TODO - add your business logic
|
||||
//return false to ~cancel~ Application close
|
||||
_disposableLogger?.Dispose();
|
||||
Container.Dispose();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
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 Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Common.Threading;
|
||||
using Speckle.Connectors.DUI.Bridge;
|
||||
using Speckle.Connectors.DUI.Models;
|
||||
using Speckle.Connectors.DUI.Utils;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Utils;
|
||||
|
||||
public class ArcGISDocumentStore : DocumentModelStore
|
||||
{
|
||||
public ArcGISDocumentStore(
|
||||
ILogger<DocumentModelStore> logger,
|
||||
IJsonSerializer jsonSerializer,
|
||||
ITopLevelExceptionHandler topLevelExceptionHandler
|
||||
)
|
||||
: base(logger, jsonSerializer)
|
||||
{
|
||||
ActiveMapViewChangedEvent.Subscribe(a => topLevelExceptionHandler.CatchUnhandled(() => OnMapViewChanged(a)), true);
|
||||
ProjectSavingEvent.Subscribe(
|
||||
_ =>
|
||||
{
|
||||
topLevelExceptionHandler.CatchUnhandled(OnProjectSaving);
|
||||
return Task.CompletedTask;
|
||||
},
|
||||
true
|
||||
);
|
||||
ProjectClosingEvent.Subscribe(
|
||||
_ =>
|
||||
{
|
||||
topLevelExceptionHandler.CatchUnhandled(OnProjectClosing);
|
||||
return Task.CompletedTask;
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
// in case plugin was loaded into already opened Map, read metadata from the current Map
|
||||
if (!IsDocumentInit && MapView.Active != null)
|
||||
{
|
||||
IsDocumentInit = true;
|
||||
LoadState();
|
||||
OnDocumentChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnProjectClosing()
|
||||
{
|
||||
if (MapView.Active is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SaveState();
|
||||
}
|
||||
|
||||
private void OnProjectSaving()
|
||||
{
|
||||
if (MapView.Active is not null)
|
||||
{
|
||||
SaveState();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On map view switch, this event trigger twice, first for outgoing view, second for incoming view.
|
||||
/// </summary>
|
||||
private void OnMapViewChanged(ActiveMapViewChangedEventArgs args)
|
||||
{
|
||||
if (args.IncomingView is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IsDocumentInit = true;
|
||||
LoadState();
|
||||
OnDocumentChanged();
|
||||
}
|
||||
|
||||
protected override void HostAppSaveState(string modelCardState) =>
|
||||
QueuedTask
|
||||
.Run(() =>
|
||||
{
|
||||
Map map = MapView.Active.Map;
|
||||
// Read existing metadata - To prevent messing existing metadata. 🤞 Hope other add-in developers will do same :D
|
||||
var existingMetadata = map.GetMetadata();
|
||||
|
||||
// Parse existing metadata
|
||||
XDocument existingXmlDocument = !string.IsNullOrEmpty(existingMetadata)
|
||||
? XDocument.Parse(existingMetadata)
|
||||
: new XDocument(new XElement("metadata"));
|
||||
|
||||
XElement xmlModelCards = new("SpeckleModelCards", modelCardState);
|
||||
|
||||
// Check if SpeckleModelCards element already exists at root and update it
|
||||
var speckleModelCardsElement = existingXmlDocument.Root?.Element("SpeckleModelCards");
|
||||
if (speckleModelCardsElement != null)
|
||||
{
|
||||
speckleModelCardsElement.ReplaceWith(xmlModelCards);
|
||||
}
|
||||
else
|
||||
{
|
||||
existingXmlDocument.Root?.Add(xmlModelCards);
|
||||
}
|
||||
|
||||
map.SetMetadata(existingXmlDocument.ToString());
|
||||
})
|
||||
.FireAndForget();
|
||||
|
||||
protected override void LoadState() =>
|
||||
QueuedTask
|
||||
.Run(() =>
|
||||
{
|
||||
Map map = MapView.Active.Map;
|
||||
var metadata = map.GetMetadata();
|
||||
var root = XDocument.Parse(metadata).Root;
|
||||
var element = root?.Element("SpeckleModelCards");
|
||||
if (element is null)
|
||||
{
|
||||
ClearAndSave();
|
||||
return;
|
||||
}
|
||||
|
||||
string modelsString = element.Value;
|
||||
LoadFromString(modelsString);
|
||||
})
|
||||
.FireAndForget();
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Utils;
|
||||
|
||||
// bind together a layer object on the map, and auto-assigned ID if the specific feature
|
||||
public readonly struct MapMemberFeature
|
||||
{
|
||||
public int? FeatureId { get; } // unique feature id (start from 0) of a feature in the layer
|
||||
public MapMember MapMember { get; } // layer object on the Map
|
||||
|
||||
public MapMemberFeature(MapMember mapMember, int? featureId)
|
||||
{
|
||||
MapMember = mapMember;
|
||||
FeatureId = featureId;
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
using ArcGIS.Desktop.Mapping;
|
||||
|
||||
namespace Speckle.Connectors.ArcGIS.Utils;
|
||||
|
||||
public class MapMembersUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns all Layers and Standalone Tables present on the Map
|
||||
/// </summary>
|
||||
/// <param name="map"></param>
|
||||
/// <returns></returns>
|
||||
public List<MapMember> GetAllMapMembers(Map map)
|
||||
{
|
||||
// first get all map layers
|
||||
List<MapMember> mapMembers = new();
|
||||
var layerMapMembers = UnpackMapLayers(map.Layers);
|
||||
mapMembers.AddRange(layerMapMembers);
|
||||
|
||||
// add tables
|
||||
var standaloneTableMapMembers = UnpackMapLayers(map.StandaloneTables);
|
||||
mapMembers.AddRange(standaloneTableMapMembers);
|
||||
return mapMembers;
|
||||
}
|
||||
|
||||
public List<MapMember> UnpackMapLayers(IEnumerable<MapMember> mapMembersToUnpack)
|
||||
{
|
||||
List<MapMember> mapMembers = new();
|
||||
foreach (var layer in mapMembersToUnpack)
|
||||
{
|
||||
mapMembers.Add(layer);
|
||||
switch (layer)
|
||||
{
|
||||
case ILayerContainer subGroup:
|
||||
var subLayerMapMembers = UnpackMapLayers(subGroup.Layers);
|
||||
mapMembers.AddRange(subLayerMapMembers);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return mapMembers;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sorts the selected mapmembers into the same order as they appear in the Table of Contents (TOC) bar in the file.
|
||||
/// This is a required step before unpacking layers, because depending on the user selection order, some children layers may appear before their container layer if both the container and children layers are selected.
|
||||
/// </summary>
|
||||
public IEnumerable<MapMember> GetMapMembersInOrder(Map map, IReadOnlyList<MapMember> selectedMapMembers)
|
||||
{
|
||||
// first get all map layers
|
||||
List<MapMember> allMapMembers = GetAllMapMembers(map);
|
||||
|
||||
// recalculate selected layer priority from all map layers
|
||||
foreach (MapMember mapMember in allMapMembers)
|
||||
{
|
||||
if (selectedMapMembers.Contains(mapMember))
|
||||
{
|
||||
yield return mapMember;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
namespace Speckle.Connectors.ArcGIS.Utils;
|
||||
|
||||
// this struct is needed to be able to parse single-string value into IDs of both a layer, and it's individual feature
|
||||
public struct ObjectID
|
||||
{
|
||||
private const string FEATURE_ID_SEPARATOR = "__speckleFeatureId__";
|
||||
public string MappedLayerURI { get; } // unique ID of the layer on the map
|
||||
public int? FeatureId { get; } // unique feature id (start from 0) of a feature in the layer
|
||||
|
||||
public ObjectID(string encodedId)
|
||||
{
|
||||
List<string> stringParts = encodedId.Split(FEATURE_ID_SEPARATOR).ToList();
|
||||
MappedLayerURI = stringParts[0];
|
||||
FeatureId = null;
|
||||
if (stringParts.Count > 1)
|
||||
{
|
||||
FeatureId = Convert.ToInt32(stringParts[1]);
|
||||
}
|
||||
}
|
||||
|
||||
public ObjectID(string layerId, int? featureId)
|
||||
{
|
||||
MappedLayerURI = layerId;
|
||||
FeatureId = featureId;
|
||||
}
|
||||
|
||||
public readonly string ObjectIdToString()
|
||||
{
|
||||
if (FeatureId == null)
|
||||
{
|
||||
return $"{MappedLayerURI}";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"{MappedLayerURI}{FEATURE_ID_SEPARATOR}{FeatureId}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,359 +0,0 @@
|
||||
{
|
||||
"version": 2,
|
||||
"dependencies": {
|
||||
"net6.0-windows7.0": {
|
||||
"Esri.ArcGISPro.Extensions30": {
|
||||
"type": "Direct",
|
||||
"requested": "[3.2.0.49743, )",
|
||||
"resolved": "3.2.0.49743",
|
||||
"contentHash": "fmnYm+mD14Cz0Uqh1ij37SfLJerkyFHK5581y5tXT/l3H2ZvUmVuuxjYquXzyzj9p7IexQzMW4xCpxe+mD922g=="
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"type": "Direct",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.0.3, )",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
|
||||
"dependencies": {
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.3"
|
||||
}
|
||||
},
|
||||
"Microsoft.SourceLink.GitHub": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.0.0, )",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Build.Tasks.Git": "8.0.0",
|
||||
"Microsoft.SourceLink.Common": "8.0.0"
|
||||
}
|
||||
},
|
||||
"PolySharp": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.14.1, )",
|
||||
"resolved": "1.14.1",
|
||||
"contentHash": "mOOmFYwad3MIOL14VCjj02LljyF1GNw1wP0YVlxtcPvqdxjGGMNdNJJxHptlry3MOd8b40Flm8RPOM8JOlN2sQ=="
|
||||
},
|
||||
"Speckle.InterfaceGenerator": {
|
||||
"type": "Direct",
|
||||
"requested": "[0.9.6, )",
|
||||
"resolved": "0.9.6",
|
||||
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
|
||||
},
|
||||
"GraphQL.Client": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "8yPNBbuVBpTptivyAlak4GZvbwbUcjeQTL4vN1HKHRuOykZ4r7l5fcLS6vpyPyLn0x8FsL31xbOIKyxbmR9rbA==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client.Abstractions": "6.0.0",
|
||||
"GraphQL.Client.Abstractions.Websocket": "6.0.0",
|
||||
"System.Reactive": "5.0.0"
|
||||
}
|
||||
},
|
||||
"GraphQL.Client.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "h7uzWFORHZ+CCjwr/ThAyXMr0DPpzEANDa4Uo54wqCQ+j7qUKwqYTgOrb1W40sqbvNaZm9v/X7It31SUw0maHA==",
|
||||
"dependencies": {
|
||||
"GraphQL.Primitives": "6.0.0"
|
||||
}
|
||||
},
|
||||
"GraphQL.Client.Abstractions.Websocket": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "Nr9bPf8gIOvLuXpqEpqr9z9jslYFJOvd0feHth3/kPqeR3uMbjF5pjiwh4jxyMcxHdr8Pb6QiXkV3hsSyt0v7A==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client.Abstractions": "6.0.0"
|
||||
}
|
||||
},
|
||||
"GraphQL.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.0",
|
||||
"contentHash": "yg72rrYDapfsIUrul7aF6wwNnTJBOFvuA9VdDTQpPa8AlAriHbufeXYLBcodKjfUdkCnaiggX1U/nEP08Zb5GA=="
|
||||
},
|
||||
"Microsoft.Bcl.AsyncInterfaces": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ=="
|
||||
},
|
||||
"Microsoft.Build.Tasks.Git": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
|
||||
},
|
||||
"Microsoft.CSharp": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.7.0",
|
||||
"contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA=="
|
||||
},
|
||||
"Microsoft.Data.Sqlite": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.5",
|
||||
"contentHash": "KGxbPeWsQMnmQy43DSBxAFtHz3l2JX8EWBSGUCvT3CuZ8KsuzbkqMIJMDOxWtG8eZSoCDI04aiVQjWuuV8HmSw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Data.Sqlite.Core": "7.0.5",
|
||||
"SQLitePCLRaw.bundle_e_sqlite3": "2.1.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Data.Sqlite.Core": {
|
||||
"type": "Transitive",
|
||||
"resolved": "7.0.5",
|
||||
"contentHash": "FTerRmQPqHrCrnoUzhBu+E+1DNGwyrAMLqHkAqOOOu5pGfyMOj8qQUBxI/gDtWtG11p49UxSfWmBzRNlwZqfUg==",
|
||||
"dependencies": {
|
||||
"SQLitePCLRaw.core": "2.1.4"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Binder": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "vJ9xvOZCnUAIHcGC3SU35r3HKmHTVIeHzo6u/qzlHAqD8m6xv92MLin4oJntTvkpKxVX3vI1GFFkIQtU3AdlsQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "f9hstgjVmr6rmrfGSpfsVOl2irKAgr1QjrSi3FgnS7kulxband50f2brRLwySAQTADPZeTdow0mpSMcoAdadCw=="
|
||||
},
|
||||
"Microsoft.Extensions.Options": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Primitives": "2.2.0",
|
||||
"System.ComponentModel.Annotations": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.1",
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.5.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net461": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.0.3",
|
||||
"contentHash": "AmOJZwCqnOCNp6PPcf9joyogScWLtwy0M1WkqfEQ0M9nYwyDD7EX9ZjscKS5iYnyvteX7kzSKFCKt9I9dXA6mA=="
|
||||
},
|
||||
"Microsoft.SourceLink.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
|
||||
},
|
||||
"Speckle.Newtonsoft.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "13.0.2",
|
||||
"contentHash": "g1BejUZwax5PRfL6xHgLEK23sqHWOgOj9hE7RvfRRlN00AGt8GnPYt8HedSK7UB3HiRW8zCA9Pn0iiYxCK24BA=="
|
||||
},
|
||||
"SQLitePCLRaw.bundle_e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "EWI1olKDjFEBMJu0+3wuxwziIAdWDVMYLhuZ3Qs84rrz+DHwD00RzWPZCa+bLnHCf3oJwuFZIRsHT5p236QXww==",
|
||||
"dependencies": {
|
||||
"SQLitePCLRaw.lib.e_sqlite3": "2.1.4",
|
||||
"SQLitePCLRaw.provider.e_sqlite3": "2.1.4"
|
||||
}
|
||||
},
|
||||
"SQLitePCLRaw.core": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "inBjvSHo9UDKneGNzfUfDjK08JzlcIhn1+SP5Y3m6cgXpCxXKCJDy6Mka7LpgSV+UZmKSnC8rTwB0SQ0xKu5pA==",
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.3"
|
||||
}
|
||||
},
|
||||
"SQLitePCLRaw.lib.e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
|
||||
},
|
||||
"SQLitePCLRaw.provider.e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "CSlb5dUp1FMIkez9Iv5EXzpeq7rHryVNqwJMWnpq87j9zWZexaEMdisDktMsnnrzKM6ahNrsTkjqNodTBPBxtQ==",
|
||||
"dependencies": {
|
||||
"SQLitePCLRaw.core": "2.1.4"
|
||||
}
|
||||
},
|
||||
"System.ComponentModel.Annotations": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
|
||||
},
|
||||
"System.Memory": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.3",
|
||||
"contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA=="
|
||||
},
|
||||
"System.Reactive": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ=="
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.1",
|
||||
"contentHash": "Zh8t8oqolRaFa9vmOZfdQm/qKejdqz0J9kr7o2Fu0vPeoH3BL1EOXipKWwkWtLT1JPzjByrF19fGuFlNbmPpiw=="
|
||||
},
|
||||
"speckle.common.meshtriangulation": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"LibTessDotNet": "[1.1.15, )",
|
||||
"Speckle.DoubleNumerics": "[4.1.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Connectors.Common": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui.webview": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Web.WebView2": "[1.0.1938.49, )",
|
||||
"Speckle.Connectors.DUI": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.logging": {
|
||||
"type": "Project"
|
||||
},
|
||||
"speckle.converters.arcgis3": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Esri.ArcGISPro.Extensions30": "[3.2.0.49743, )",
|
||||
"Speckle.Common.MeshTriangulation": "[1.0.0, )",
|
||||
"Speckle.Converters.Common": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
}
|
||||
},
|
||||
"LibTessDotNet": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[1.1.15, )",
|
||||
"resolved": "1.1.15",
|
||||
"contentHash": "KuA7N3Nv/lIeawJdQBQJR6oqWD9KETHLbWzBqapwFs+Tby+R5I4crkKujKMm5bXcSuFZ8LNtflFQVadsWCbBjg=="
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[2.2.0, )",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Binder": "2.2.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Options": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Web.WebView2": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[1.0.1938.49, )",
|
||||
"resolved": "1.0.1938.49",
|
||||
"contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
|
||||
},
|
||||
"Speckle.DoubleNumerics": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[4.1.0, )",
|
||||
"resolved": "4.1.0",
|
||||
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
"Microsoft.Data.Sqlite": "7.0.5",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
}
|
||||
},
|
||||
"net6.0-windows7.0/win-x64": {
|
||||
"SQLitePCLRaw.lib.e_sqlite3": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.4",
|
||||
"contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
|
||||
},
|
||||
"Microsoft.Web.WebView2": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[1.0.1938.49, )",
|
||||
"resolved": "1.0.1938.49",
|
||||
"contentHash": "z8KnFnaTYzhA/ZnyRX0qGfS1NU5ZBJeClAH64F0fVDvdDJTvME7xl6zTJ0Jlfe1BtL3C0NH9xTy64shg2baKdw=="
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -259,9 +259,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -292,7 +292,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
@@ -336,18 +336,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -357,14 +357,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,9 +259,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -292,7 +292,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
@@ -336,18 +336,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -357,14 +357,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,9 +259,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -293,7 +293,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
@@ -337,18 +337,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -358,14 +358,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,9 +215,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -249,7 +249,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
@@ -293,18 +293,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
@@ -313,14 +313,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
},
|
||||
"net8.0-windows7.0/win-x64": {
|
||||
|
||||
@@ -215,9 +215,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -249,7 +249,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
@@ -293,18 +293,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
@@ -313,14 +313,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
},
|
||||
"net8.0-windows7.0/win-x64": {
|
||||
|
||||
@@ -20,7 +20,7 @@ public class AutocadCommand
|
||||
private static readonly Guid s_id = new("3223E594-1B09-4E54-B3DD-8EA0BECE7BA5");
|
||||
public ServiceProvider? Container { get; private set; }
|
||||
private IDisposable? _disposableLogger;
|
||||
public const string COMMAND_STRING = "SpeckleBeta";
|
||||
public const string COMMAND_STRING = "Speckle";
|
||||
|
||||
[CommandMethod(COMMAND_STRING)]
|
||||
public void Command()
|
||||
@@ -31,7 +31,7 @@ public class AutocadCommand
|
||||
return;
|
||||
}
|
||||
|
||||
PaletteSet = new PaletteSet($"Speckle (Beta)", s_id)
|
||||
PaletteSet = new PaletteSet($"Speckle", s_id)
|
||||
{
|
||||
Size = new Size(400, 500),
|
||||
DockEnabled = (DockSides)((int)DockSides.Left + (int)DockSides.Right)
|
||||
@@ -52,7 +52,7 @@ public class AutocadCommand
|
||||
|
||||
var panelWebView = Container.GetRequiredService<DUI3ControlWebView>();
|
||||
|
||||
PaletteSet.AddVisual("Speckle (Beta)", panelWebView);
|
||||
PaletteSet.AddVisual("Speckle", panelWebView);
|
||||
|
||||
FocusPalette();
|
||||
}
|
||||
|
||||
@@ -49,19 +49,19 @@ public class AutocadRibbon
|
||||
private void Create()
|
||||
{
|
||||
RibbonTab tab = FindOrMakeTab("Speckle");
|
||||
RibbonPanelSource source = new() { Title = "Speckle (Beta)" };
|
||||
RibbonPanelSource source = new() { Title = "Speckle" };
|
||||
RibbonPanel panel = new() { Source = source };
|
||||
tab.Panels.Add(panel);
|
||||
|
||||
RibbonToolTip speckleToolTip =
|
||||
new()
|
||||
{
|
||||
Title = "Speckle (Beta)",
|
||||
Content = $"Next Gen Speckle Connector (Beta) for {AppUtils.App.Name}",
|
||||
Title = "Speckle",
|
||||
Content = $"Next Gen Speckle Connector for {AppUtils.App.Name}",
|
||||
IsHelpEnabled = true // Without this "Press F1 for help" does not appear in the tooltip
|
||||
};
|
||||
|
||||
_ = CreateSpeckleButton("Speckle (Beta)", source, null, speckleToolTip, "logo");
|
||||
_ = CreateSpeckleButton("Speckle", source, null, speckleToolTip, "logo");
|
||||
}
|
||||
|
||||
private void ComponentManager_ItemInitialized(object? sender, RibbonItemEventArgs e)
|
||||
|
||||
|
Before Width: | Height: | Size: 714 B After Width: | Height: | Size: 302 B |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 430 B |
@@ -268,9 +268,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -302,7 +302,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
@@ -346,18 +346,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -367,14 +367,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,9 +268,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -302,7 +302,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
@@ -346,18 +346,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -367,14 +367,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,9 +268,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -302,7 +302,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
@@ -346,18 +346,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -367,14 +367,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,9 +224,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -259,7 +259,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
@@ -303,18 +303,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
@@ -323,14 +323,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
},
|
||||
"net8.0-windows7.0/win-x64": {
|
||||
|
||||
@@ -224,9 +224,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -259,7 +259,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
@@ -303,18 +303,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
@@ -323,14 +323,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
},
|
||||
"net8.0-windows7.0/win-x64": {
|
||||
|
||||
@@ -22,7 +22,7 @@ public abstract class SpeckleFormBase : Form, ICsiApplicationService
|
||||
|
||||
protected SpeckleFormBase()
|
||||
{
|
||||
Text = "Speckle (Beta)";
|
||||
Text = "Speckle";
|
||||
Size = new System.Drawing.Size(400, 600);
|
||||
}
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 352 KiB After Width: | Height: | Size: 352 KiB |
@@ -259,9 +259,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -285,7 +285,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.etabs21": {
|
||||
@@ -335,18 +335,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -356,14 +356,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,9 +215,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -241,7 +241,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.etabs22": {
|
||||
@@ -291,18 +291,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
@@ -311,14 +311,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,9 +259,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -285,7 +285,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.navisworks2020": {
|
||||
@@ -337,18 +337,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -358,14 +358,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
},
|
||||
".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.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -285,7 +285,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.navisworks2021": {
|
||||
@@ -337,18 +337,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -358,14 +358,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
},
|
||||
".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.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -285,7 +285,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.navisworks2022": {
|
||||
@@ -337,18 +337,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -358,14 +358,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
},
|
||||
".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.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -285,7 +285,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.navisworks2023": {
|
||||
@@ -337,18 +337,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -358,14 +358,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
},
|
||||
".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.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -285,7 +285,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.navisworks2024": {
|
||||
@@ -337,18 +337,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -358,14 +358,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
},
|
||||
".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.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -291,7 +291,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.navisworks2025": {
|
||||
@@ -337,18 +337,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -358,14 +358,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
},
|
||||
".NETFramework,Version=v4.8/win-x64": {
|
||||
|
||||
@@ -266,9 +266,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -292,7 +292,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.navisworks2026": {
|
||||
@@ -339,18 +339,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -360,14 +360,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
},
|
||||
".NETFramework,Version=v4.8/win-x64": {
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Speckle.Connector.Navisworks.Plugin;
|
||||
DisplayName = SpeckleV3Tool.DISPLAY_NAME,
|
||||
Options = NAV.Plugins.PluginOptions.None,
|
||||
ToolTip = "Speckle Connector for Navisworks",
|
||||
ExtendedToolTip = "Next Gen Speckle Connector (Beta) for Navisworks"
|
||||
ExtendedToolTip = "Next Gen Speckle Connector for Navisworks"
|
||||
)
|
||||
]
|
||||
[SuppressMessage(
|
||||
|
||||
@@ -4,7 +4,7 @@ $utf8
|
||||
|
||||
DisplayName=Speckle
|
||||
Speckle.DisplayName=Speckle
|
||||
SpeckleV3.Title=Speckle (Beta)
|
||||
SpeckleV2.Title=Speckle
|
||||
Speckle_Launch.DisplayName=Speckle (Beta)
|
||||
Speckle_Launch_V2.DisplayName=Speckle
|
||||
SpeckleV3.Title=Speckle
|
||||
SpeckleV2.Title=Speckle (Legacy)
|
||||
Speckle_Launch.DisplayName=Speckle
|
||||
Speckle_Launch_V2.DisplayName=Speckle (Legacy)
|
||||
|
||||
@@ -8,7 +8,7 @@ public static class SpeckleV3Tool
|
||||
public const string COMMAND = "Speckle_Launch";
|
||||
public const string PLUGIN = "SpeckleUI3";
|
||||
public const string PLUGIN_ID = "SpeckleNavisworksNextGen";
|
||||
public const string DISPLAY_NAME = "Speckle (Beta)";
|
||||
public const string DISPLAY_NAME = "Speckle";
|
||||
public const string RIBBON_TAB_ID = "Speckle";
|
||||
public const string RIBBON_TAB_DISPLAY_NAME = "Speckle";
|
||||
public const string RIBBON_STRINGS = "NavisworksRibbon.name";
|
||||
|
||||
|
Before Width: | Height: | Size: 708 B After Width: | Height: | Size: 519 B |
|
Before Width: | Height: | Size: 864 B After Width: | Height: | Size: 997 B |
|
Before Width: | Height: | Size: 714 B After Width: | Height: | Size: 708 B |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 864 B |
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RevitAddIns>
|
||||
<AddIn Type="Application">
|
||||
<Name>Speckle (Beta) for Revit</Name>
|
||||
<Description>Speckle (Beta) for Revit</Description>
|
||||
<Name>Speckle for Revit</Name>
|
||||
<Description>Speckle for Revit</Description>
|
||||
<Assembly>Speckle.Connectors.Revit2022\Speckle.Connectors.Revit2022.dll</Assembly>
|
||||
<FullClassName>Speckle.Connectors.Revit.Plugin.RevitExternalApplication</FullClassName>
|
||||
<ClientId>27ccff2c-011c-4374-bb79-b93990d0c86a</ClientId>
|
||||
|
||||
@@ -281,9 +281,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -306,7 +306,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.revit2022": {
|
||||
@@ -351,11 +351,11 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Revit.API": {
|
||||
@@ -366,9 +366,9 @@
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -378,14 +378,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RevitAddIns>
|
||||
<AddIn Type="Application">
|
||||
<Name>Speckle (Beta) for Revit</Name>
|
||||
<Description>Speckle (Beta) for Revit</Description>
|
||||
<Name>Speckle for Revit</Name>
|
||||
<Description>Speckle for Revit</Description>
|
||||
<Assembly>Speckle.Connectors.Revit2023\Speckle.Connectors.Revit2023.dll</Assembly>
|
||||
<FullClassName>Speckle.Connectors.Revit.Plugin.RevitExternalApplication</FullClassName>
|
||||
<ClientId>27ccff2c-011c-4374-bb79-b93990d0c86a</ClientId>
|
||||
|
||||
@@ -281,9 +281,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -306,7 +306,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.revit2023": {
|
||||
@@ -351,11 +351,11 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Revit.API": {
|
||||
@@ -366,9 +366,9 @@
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -378,14 +378,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RevitAddIns>
|
||||
<AddIn Type="Application">
|
||||
<Name>Speckle (Beta) for Revit</Name>
|
||||
<Description>Speckle (Beta) for Revit</Description>
|
||||
<Name>Speckle for Revit</Name>
|
||||
<Description>Speckle for Revit</Description>
|
||||
<Assembly>Speckle.Connectors.Revit2024\Speckle.Connectors.Revit2024.dll</Assembly>
|
||||
<FullClassName>Speckle.Connectors.Revit.Plugin.RevitExternalApplication</FullClassName>
|
||||
<ClientId>27ccff2c-011c-4374-bb79-b93990d0c86a</ClientId>
|
||||
|
||||
@@ -281,9 +281,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -306,7 +306,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.revit2024": {
|
||||
@@ -351,11 +351,11 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Revit.API": {
|
||||
@@ -366,9 +366,9 @@
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -378,14 +378,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RevitAddIns>
|
||||
<AddIn Type="Application">
|
||||
<Name>Speckle (Beta) for Revit</Name>
|
||||
<Description>Speckle (Beta) for Revit</Description>
|
||||
<Name>Speckle for Revit</Name>
|
||||
<Description>Speckle for Revit</Description>
|
||||
<Assembly>Speckle.Connectors.Revit2025\Speckle.Connectors.Revit2025.dll</Assembly>
|
||||
<FullClassName>Speckle.Connectors.Revit.Plugin.RevitExternalApplication</FullClassName>
|
||||
<ClientId>27ccff2c-011c-4374-bb79-b93990d0c86a</ClientId>
|
||||
|
||||
@@ -231,9 +231,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -256,7 +256,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.revit2025": {
|
||||
@@ -301,11 +301,11 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Revit.API": {
|
||||
@@ -316,9 +316,9 @@
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
@@ -327,14 +327,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
},
|
||||
"net8.0-windows7.0/win-x64": {
|
||||
|
||||
@@ -50,7 +50,7 @@ internal sealed class RevitWebViewPlugin(
|
||||
var dui3Button = (PushButton)
|
||||
specklePanel.AddItem(
|
||||
new PushButtonData(
|
||||
"Speckle (Beta) for Revit",
|
||||
"Speckle for Revit",
|
||||
Connector.TabTitle,
|
||||
typeof(RevitExternalApplication).Assembly.Location,
|
||||
typeof(SpeckleRevitCommand).FullName
|
||||
@@ -70,7 +70,7 @@ internal sealed class RevitWebViewPlugin(
|
||||
$"Speckle.Connectors.Revit{speckleApplication.HostApplicationVersion}.Assets.logo32.png",
|
||||
path
|
||||
);
|
||||
dui3Button.ToolTip = "Speckle (Beta) for Revit";
|
||||
dui3Button.ToolTip = "Speckle for Revit";
|
||||
//dui3Button.AvailabilityClassName = typeof(CmdAvailabilityViews).FullName;
|
||||
dui3Button.SetContextualHelp(new ContextualHelp(ContextualHelpType.Url, "https://speckle.systems"));
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RevitAddIns>
|
||||
<AddIn Type="Application">
|
||||
<Name>Speckle (Beta) for Revit</Name>
|
||||
<Description>Speckle (Beta) for Revit</Description>
|
||||
<Name>Speckle for Revit</Name>
|
||||
<Description>Speckle for Revit</Description>
|
||||
<Assembly>Speckle.Connectors.Revit2026\Speckle.Connectors.Revit2026.dll</Assembly>
|
||||
<FullClassName>Speckle.Connectors.Revit.Plugin.RevitExternalApplication</FullClassName>
|
||||
<ClientId>27ccff2c-011c-4374-bb79-b93990d0c86a</ClientId>
|
||||
|
||||
@@ -224,9 +224,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -249,7 +249,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.revit2026": {
|
||||
@@ -285,11 +285,11 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Revit.API": {
|
||||
@@ -300,9 +300,9 @@
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.CSharp": "4.7.0",
|
||||
@@ -311,14 +311,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
},
|
||||
"net8.0-windows7.0/win-x64": {
|
||||
|
||||
|
Before Width: | Height: | Size: 714 B After Width: | Height: | Size: 302 B |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 430 B |
@@ -94,7 +94,7 @@ internal sealed class RevitCefPlugin : IRevitPlugin
|
||||
$"Speckle.Connectors.Revit{_speckleApplication.HostApplicationVersion}.Assets.logo32.png",
|
||||
path
|
||||
);
|
||||
dui3Button.ToolTip = "Speckle (Beta) for Revit";
|
||||
dui3Button.ToolTip = "Speckle for Revit";
|
||||
//dui3Button.AvailabilityClassName = typeof(CmdAvailabilityViews).FullName;
|
||||
dui3Button.SetContextualHelp(new ContextualHelp(ContextualHelpType.Url, "https://speckle.systems"));
|
||||
}
|
||||
@@ -159,7 +159,7 @@ internal sealed class RevitCefPlugin : IRevitPlugin
|
||||
// Otherwise pane cannot be registered for double-click file open.
|
||||
_uIControlledApplication.RegisterDockablePane(
|
||||
RevitExternalApplication.DockablePanelId,
|
||||
"Speckle (Beta) for Revit",
|
||||
"Speckle for Revit",
|
||||
_cefSharpPanel
|
||||
);
|
||||
}
|
||||
|
||||
@@ -322,9 +322,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.logging": {
|
||||
@@ -334,7 +334,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.rhino7": {
|
||||
@@ -379,18 +379,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -400,14 +400,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,9 +322,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.logging": {
|
||||
@@ -334,7 +334,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.rhino8": {
|
||||
@@ -379,18 +379,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -400,14 +400,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
using GH_IO.Serialization;
|
||||
using Grasshopper.Kernel;
|
||||
using Speckle.Connectors.GrasshopperShared.HostApp.Extras;
|
||||
using Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.BaseComponents;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for variable parameter components with name inheritance support
|
||||
/// </summary>
|
||||
public abstract class VariableParameterComponentBase : GH_Component, IGH_VariableParameterComponent
|
||||
{
|
||||
private readonly DebounceDispatcher _debounceDispatcher = new();
|
||||
private bool _alwaysInheritNames;
|
||||
|
||||
protected VariableParameterComponentBase(
|
||||
string name,
|
||||
string nickname,
|
||||
string description,
|
||||
string category,
|
||||
string subCategory
|
||||
)
|
||||
: base(name, nickname, description, category, subCategory) { }
|
||||
|
||||
public bool AlwaysInheritNames
|
||||
{
|
||||
get => _alwaysInheritNames;
|
||||
set
|
||||
{
|
||||
if (_alwaysInheritNames != value)
|
||||
{
|
||||
_alwaysInheritNames = value;
|
||||
OnAlwaysInheritNamesChanged();
|
||||
UpdateDisplayMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void UpdateDisplayMessage()
|
||||
{
|
||||
Message = AlwaysInheritNames ? "Inheriting names" : "";
|
||||
}
|
||||
|
||||
private void OnAlwaysInheritNamesChanged()
|
||||
{
|
||||
// Update all existing SpeckleVariableParams
|
||||
foreach (var param in Params.Input.OfType<SpeckleVariableParam>())
|
||||
{
|
||||
param.AlwaysInheritNames = AlwaysInheritNames;
|
||||
}
|
||||
OnDisplayExpired(true);
|
||||
}
|
||||
|
||||
protected SpeckleVariableParam CreateVariableParameter(string baseName, GH_ParamAccess access)
|
||||
{
|
||||
var param = new SpeckleVariableParam
|
||||
{
|
||||
Name = baseName,
|
||||
NickName = baseName,
|
||||
MutableNickName = true,
|
||||
Optional = true,
|
||||
Access = access,
|
||||
CanInheritNames = true,
|
||||
AlwaysInheritNames = AlwaysInheritNames
|
||||
};
|
||||
|
||||
// Subscribe to the parameter's name changes for auto-resizing
|
||||
param.ObjectChanged += OnParameterObjectChanged;
|
||||
|
||||
return param;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles parameter object changes, including name changes that require resizing
|
||||
/// </summary>
|
||||
private void OnParameterObjectChanged(IGH_DocumentObject sender, GH_ObjectChangedEventArgs e)
|
||||
{
|
||||
// Only respond to name changes that affect layout
|
||||
if (e.Type == GH_ObjectEventType.NickName || e.Type == GH_ObjectEventType.NickNameAccepted)
|
||||
{
|
||||
// Force immediate component resize for name inheritance
|
||||
TriggerComponentResize();
|
||||
}
|
||||
}
|
||||
|
||||
private void TriggerComponentResize()
|
||||
{
|
||||
// Simple: just expire the layout - Grasshopper handles the rest
|
||||
Attributes?.ExpireLayout();
|
||||
}
|
||||
|
||||
private void OnParameterNameChanged(IGH_Param parameter)
|
||||
{
|
||||
parameter.Name = parameter.NickName;
|
||||
_debounceDispatcher.Debounce(500, _ => ExpireSolution(true));
|
||||
}
|
||||
|
||||
private void OnParameterSourceChanged(IGH_Param parameter, int parameterIndex)
|
||||
{
|
||||
// Auto-add parameter if connecting to the last input
|
||||
if (parameter.SourceCount > 0 && parameterIndex == Params.Input.Count - 1)
|
||||
{
|
||||
var newParam = CreateParameter(GH_ParameterSide.Input, Params.Input.Count);
|
||||
Params.RegisterInputParam(newParam);
|
||||
Params.OnParametersChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override void AddedToDocument(GH_Document document)
|
||||
{
|
||||
base.AddedToDocument(document);
|
||||
Params.ParameterChanged += OnParameterChanged;
|
||||
|
||||
// Ensure all existing parameters are properly subscribed
|
||||
foreach (var param in Params.Input.OfType<SpeckleVariableParam>())
|
||||
{
|
||||
param.ObjectChanged -= OnParameterObjectChanged; // Remove any existing subscription
|
||||
param.ObjectChanged += OnParameterObjectChanged; // Add fresh subscription
|
||||
}
|
||||
}
|
||||
|
||||
public override void RemovedFromDocument(GH_Document document)
|
||||
{
|
||||
Params.ParameterChanged -= OnParameterChanged;
|
||||
|
||||
// Clean up parameter event subscriptions
|
||||
foreach (var param in Params.Input.OfType<SpeckleVariableParam>())
|
||||
{
|
||||
param.ObjectChanged -= OnParameterObjectChanged;
|
||||
}
|
||||
|
||||
base.RemovedFromDocument(document);
|
||||
}
|
||||
|
||||
private void OnParameterChanged(object sender, GH_ParamServerEventArgs args)
|
||||
{
|
||||
if (args.ParameterSide != GH_ParameterSide.Input)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (args.OriginalArguments.Type)
|
||||
{
|
||||
case GH_ObjectEventType.NickName:
|
||||
OnParameterNameChanged(args.Parameter);
|
||||
break;
|
||||
case GH_ObjectEventType.NickNameAccepted:
|
||||
args.Parameter.Name = args.Parameter.NickName;
|
||||
ExpireSolution(true);
|
||||
break;
|
||||
case GH_ObjectEventType.Sources:
|
||||
OnParameterSourceChanged(args.Parameter, args.ParameterIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void AppendAdditionalMenuItems(ToolStripDropDown menu)
|
||||
{
|
||||
base.AppendAdditionalMenuItems(menu);
|
||||
|
||||
Menu_AppendSeparator(menu);
|
||||
var alwaysInheritMenuItem = Menu_AppendItem(
|
||||
menu,
|
||||
"Always inherit names",
|
||||
(_, _) => AlwaysInheritNames = !AlwaysInheritNames,
|
||||
true,
|
||||
AlwaysInheritNames
|
||||
);
|
||||
alwaysInheritMenuItem.ToolTipText = "Parameters auto-inherit source names and update automatically";
|
||||
|
||||
AppendComponentSpecificMenuItems(menu);
|
||||
}
|
||||
|
||||
protected virtual void AppendComponentSpecificMenuItems(ToolStripDropDown menu)
|
||||
{
|
||||
// Override in derived classes for component-specific menu items
|
||||
}
|
||||
|
||||
public override bool Write(GH_IWriter writer)
|
||||
{
|
||||
var result = base.Write(writer);
|
||||
writer.SetBoolean("AlwaysInheritNames", AlwaysInheritNames);
|
||||
WriteComponentSpecificData(writer);
|
||||
return result;
|
||||
}
|
||||
|
||||
public override bool Read(GH_IReader reader)
|
||||
{
|
||||
var result = base.Read(reader);
|
||||
bool alwaysInherit = default;
|
||||
if (reader.TryGetBoolean("AlwaysInheritNames", ref alwaysInherit))
|
||||
{
|
||||
AlwaysInheritNames = alwaysInherit;
|
||||
UpdateExistingParameters();
|
||||
}
|
||||
|
||||
ReadComponentSpecificData(reader);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void UpdateExistingParameters()
|
||||
{
|
||||
foreach (var param in Params.Input.OfType<SpeckleVariableParam>())
|
||||
{
|
||||
param.AlwaysInheritNames = AlwaysInheritNames;
|
||||
param.ObjectChanged -= OnParameterObjectChanged;
|
||||
param.ObjectChanged += OnParameterObjectChanged;
|
||||
}
|
||||
UpdateDisplayMessage();
|
||||
}
|
||||
|
||||
protected virtual void WriteComponentSpecificData(GH_IWriter writer) { }
|
||||
|
||||
protected virtual void ReadComponentSpecificData(GH_IReader reader) { }
|
||||
|
||||
// abstract methods to satisfy IGH_VariableParameterComponent
|
||||
public abstract bool CanInsertParameter(GH_ParameterSide side, int index);
|
||||
public abstract bool CanRemoveParameter(GH_ParameterSide side, int index);
|
||||
public abstract IGH_Param CreateParameter(GH_ParameterSide side, int index);
|
||||
public abstract bool DestroyParameter(GH_ParameterSide side, int index);
|
||||
|
||||
public virtual void VariableParameterMaintenance() { }
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using Grasshopper.Kernel;
|
||||
using Grasshopper.Kernel.Parameters;
|
||||
using Grasshopper.Kernel.Types;
|
||||
using Speckle.Connectors.GrasshopperShared.Components.BaseComponents;
|
||||
using Speckle.Connectors.GrasshopperShared.HostApp;
|
||||
using Speckle.Connectors.GrasshopperShared.HostApp.Extras;
|
||||
using Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
using Speckle.Connectors.GrasshopperShared.Properties;
|
||||
using Speckle.Sdk.Common;
|
||||
@@ -9,15 +9,16 @@ using Speckle.Sdk.Models.Collections;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.Collections;
|
||||
|
||||
/// <summary>
|
||||
/// Simplified CreateCollection component using the base class pattern
|
||||
/// </summary>
|
||||
#pragma warning disable CA1711
|
||||
public class CreateCollection : GH_Component, IGH_VariableParameterComponent
|
||||
public class CreateCollection : VariableParameterComponentBase
|
||||
#pragma warning restore CA1711
|
||||
{
|
||||
public override Guid ComponentGuid => new("BDCE743E-7BDB-479B-AA81-19854AB5A254");
|
||||
protected override Bitmap Icon => Resources.speckle_collections_create;
|
||||
|
||||
private readonly DebounceDispatcher _debounceDispatcher = new();
|
||||
|
||||
public CreateCollection()
|
||||
: base(
|
||||
"Create Collection",
|
||||
@@ -29,29 +30,18 @@ public class CreateCollection : GH_Component, IGH_VariableParameterComponent
|
||||
|
||||
protected override void RegisterInputParams(GH_InputParamManager pManager)
|
||||
{
|
||||
var p = CreateParameter(GH_ParameterSide.Input, 0);
|
||||
pManager.AddParameter(p);
|
||||
var param = CreateParameter(GH_ParameterSide.Input, 0);
|
||||
pManager.AddParameter(param);
|
||||
}
|
||||
|
||||
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
|
||||
{
|
||||
pManager.AddGenericParameter("Collection", "C", "Created parent collection", GH_ParamAccess.tree);
|
||||
pManager.AddGenericParameter("Collection", "C", "Created parent collection", GH_ParamAccess.item);
|
||||
}
|
||||
|
||||
protected override void SolveInstance(IGH_DataAccess dataAccess)
|
||||
{
|
||||
string rootName = "Unnamed";
|
||||
Collection rootCollection = new();
|
||||
SpeckleCollectionWrapper rootSpeckleCollectionWrapper =
|
||||
new()
|
||||
{
|
||||
Base = rootCollection,
|
||||
Name = rootName,
|
||||
Path = new() { rootName },
|
||||
Color = null,
|
||||
Material = null,
|
||||
ApplicationId = InstanceGuid.ToString()
|
||||
};
|
||||
var rootCollection = CreateRootCollection();
|
||||
|
||||
foreach (var inputParam in Params.Input)
|
||||
{
|
||||
@@ -61,154 +51,127 @@ public class CreateCollection : GH_Component, IGH_VariableParameterComponent
|
||||
continue;
|
||||
}
|
||||
|
||||
var inputCollections = data.OfType<SpeckleCollectionWrapperGoo>()
|
||||
.Empty()
|
||||
.Select(o => (SpeckleCollectionWrapperGoo)o.Duplicate())
|
||||
.ToList();
|
||||
var inputNonCollections = data.Where(t => t is not SpeckleCollectionWrapperGoo).Empty().ToList();
|
||||
|
||||
if (inputCollections.Count != 0 && inputNonCollections.Count != 0)
|
||||
var childCollection = ProcessInputParameter(inputParam, data, rootCollection.Name);
|
||||
if (childCollection != null)
|
||||
{
|
||||
// error out! we want to disallow setting objects and collections in the same parent collection
|
||||
AddRuntimeMessage(
|
||||
GH_RuntimeMessageLevel.Error,
|
||||
$"Parameter {inputParam.NickName} should not contain both objects and collections."
|
||||
);
|
||||
return;
|
||||
rootCollection.Elements.Add(childCollection);
|
||||
}
|
||||
|
||||
List<string> childPath = new() { rootName };
|
||||
childPath.Add(inputParam.NickName);
|
||||
SpeckleCollectionWrapper childSpeckleCollectionWrapper =
|
||||
new()
|
||||
{
|
||||
Base = new Collection(),
|
||||
Name = inputParam.NickName,
|
||||
Path = childPath,
|
||||
Color = null,
|
||||
Material = null,
|
||||
Topology = GrasshopperHelpers.GetParamTopology(inputParam),
|
||||
ApplicationId = inputParam.InstanceGuid.ToString(),
|
||||
};
|
||||
|
||||
// handle collection inputs
|
||||
// if on this port we're only receiving collections, we should become "pass-through" to not create
|
||||
// needless nesting
|
||||
if (inputCollections.Count == data.Count)
|
||||
{
|
||||
var nameTest = new HashSet<string>();
|
||||
foreach (SpeckleCollectionWrapperGoo wrapperGoo in inputCollections)
|
||||
{
|
||||
// update the speckle collection path
|
||||
wrapperGoo.Value.Path = childPath;
|
||||
|
||||
foreach (
|
||||
string subCollectionName in wrapperGoo.Value.Elements.OfType<SpeckleCollectionWrapper>().Select(c => c.Name)
|
||||
)
|
||||
{
|
||||
var hasNotSeenNameBefore = nameTest.Add(subCollectionName);
|
||||
if (!hasNotSeenNameBefore)
|
||||
{
|
||||
AddRuntimeMessage(
|
||||
GH_RuntimeMessageLevel.Error,
|
||||
$"Duplicate collection name found: {subCollectionName} in input parameter {inputParam.NickName}. Please ensure collection names are unique per nesting level.\n See https://speckle.docs/grashopper/collections"
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
childSpeckleCollectionWrapper.Elements.AddRange(wrapperGoo.Value.Elements);
|
||||
}
|
||||
|
||||
rootSpeckleCollectionWrapper.Elements.Add(childSpeckleCollectionWrapper);
|
||||
continue;
|
||||
}
|
||||
|
||||
// handle object inputs
|
||||
foreach (var obj in inputNonCollections)
|
||||
{
|
||||
SpeckleObjectWrapperGoo wrapperGoo = new();
|
||||
if (wrapperGoo.CastFrom(obj))
|
||||
{
|
||||
wrapperGoo.Value.Path = childPath;
|
||||
wrapperGoo.Value.Parent = childSpeckleCollectionWrapper;
|
||||
childSpeckleCollectionWrapper.Elements.Add(wrapperGoo.Value);
|
||||
}
|
||||
}
|
||||
|
||||
rootSpeckleCollectionWrapper.Elements.Add(childSpeckleCollectionWrapper);
|
||||
}
|
||||
|
||||
dataAccess.SetData(0, new SpeckleCollectionWrapperGoo(rootSpeckleCollectionWrapper));
|
||||
dataAccess.SetData(0, new SpeckleCollectionWrapperGoo(rootCollection));
|
||||
}
|
||||
|
||||
public bool CanInsertParameter(GH_ParameterSide side, int index)
|
||||
private SpeckleCollectionWrapper CreateRootCollection()
|
||||
{
|
||||
return side == GH_ParameterSide.Input;
|
||||
}
|
||||
|
||||
public bool CanRemoveParameter(GH_ParameterSide side, int index)
|
||||
{
|
||||
return side == GH_ParameterSide.Input;
|
||||
}
|
||||
|
||||
public IGH_Param CreateParameter(GH_ParameterSide side, int index)
|
||||
{
|
||||
Param_GenericObject myParam =
|
||||
new()
|
||||
{
|
||||
Name = $"Sub-Collection {Params.Input.Count + 1}",
|
||||
MutableNickName = true,
|
||||
Optional = true,
|
||||
Access = GH_ParamAccess.tree // always tree
|
||||
};
|
||||
|
||||
myParam.NickName = myParam.Name;
|
||||
myParam.Optional = true;
|
||||
return myParam;
|
||||
}
|
||||
|
||||
public bool DestroyParameter(GH_ParameterSide side, int index)
|
||||
{
|
||||
return side == GH_ParameterSide.Input;
|
||||
}
|
||||
|
||||
public override void AddedToDocument(GH_Document document)
|
||||
{
|
||||
base.AddedToDocument(document);
|
||||
Params.ParameterChanged += (sender, args) =>
|
||||
return new SpeckleCollectionWrapper
|
||||
{
|
||||
if (args.ParameterSide == GH_ParameterSide.Output)
|
||||
{
|
||||
return;
|
||||
}
|
||||
switch (args.OriginalArguments.Type)
|
||||
{
|
||||
case GH_ObjectEventType.NickName:
|
||||
// This means the user is typing characters, debounce until it stops for 400ms before expiring the solution.
|
||||
// Prevents UI from locking too soon while writing new names for inputs.
|
||||
args.Parameter.Name = args.Parameter.NickName;
|
||||
_debounceDispatcher.Debounce(500, e => ExpireSolution(true));
|
||||
break;
|
||||
case GH_ObjectEventType.NickNameAccepted:
|
||||
args.Parameter.Name = args.Parameter.NickName;
|
||||
ExpireSolution(true);
|
||||
break;
|
||||
case GH_ObjectEventType.Sources:
|
||||
// if this event is a source change, and param is the last input, then add a new param automatically
|
||||
if (args.Parameter.SourceCount > 0 && args.ParameterIndex == Params.Input.Count - 1)
|
||||
{
|
||||
IGH_Param param = CreateParameter(GH_ParameterSide.Input, Params.Input.Count);
|
||||
Params.RegisterInputParam(param);
|
||||
Params.OnParametersChanged();
|
||||
}
|
||||
break;
|
||||
}
|
||||
Base = new Collection(),
|
||||
Name = "Unnamed",
|
||||
Path = new List<string> { "Unnamed" },
|
||||
Color = null,
|
||||
Material = null,
|
||||
ApplicationId = InstanceGuid.ToString()
|
||||
};
|
||||
}
|
||||
|
||||
public void VariableParameterMaintenance()
|
||||
private SpeckleCollectionWrapper? ProcessInputParameter(IGH_Param inputParam, List<IGH_Goo> data, string rootName)
|
||||
{
|
||||
//todo
|
||||
var collections = data.OfType<SpeckleCollectionWrapperGoo>().Empty().ToList();
|
||||
var nonCollections = data.Where(t => t is not SpeckleCollectionWrapperGoo).Empty().ToList();
|
||||
|
||||
// Validate input - cannot mix collections and objects
|
||||
if (collections.Count > 0 && nonCollections.Count > 0)
|
||||
{
|
||||
AddRuntimeMessage(
|
||||
GH_RuntimeMessageLevel.Error,
|
||||
$"Parameter {inputParam.NickName} cannot contain both objects and collections."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
var childPath = new List<string> { rootName, inputParam.NickName };
|
||||
var childCollection = new SpeckleCollectionWrapper
|
||||
{
|
||||
Base = new Collection(),
|
||||
Name = inputParam.NickName,
|
||||
Path = childPath,
|
||||
Color = null,
|
||||
Material = null,
|
||||
Topology = GrasshopperHelpers.GetParamTopology(inputParam),
|
||||
ApplicationId = inputParam.InstanceGuid.ToString()
|
||||
};
|
||||
|
||||
if (collections.Count > 0)
|
||||
{
|
||||
ProcessCollectionInputs(collections, childCollection, childPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessObjectInputs(nonCollections, childCollection, childPath);
|
||||
}
|
||||
|
||||
return childCollection;
|
||||
}
|
||||
|
||||
private void ProcessCollectionInputs(
|
||||
List<SpeckleCollectionWrapperGoo> collections,
|
||||
SpeckleCollectionWrapper parentCollection,
|
||||
List<string> childPath
|
||||
)
|
||||
{
|
||||
var duplicateNames = new HashSet<string>();
|
||||
|
||||
foreach (var collectionGoo in collections.Select(c => (SpeckleCollectionWrapperGoo)c.Duplicate()))
|
||||
{
|
||||
collectionGoo.Value.Path = childPath;
|
||||
|
||||
// Check for duplicate names within this collection
|
||||
foreach (
|
||||
var subCollectionName in collectionGoo.Value.Elements.OfType<SpeckleCollectionWrapper>().Select(c => c.Name)
|
||||
)
|
||||
{
|
||||
if (!duplicateNames.Add(subCollectionName))
|
||||
{
|
||||
AddRuntimeMessage(
|
||||
GH_RuntimeMessageLevel.Error,
|
||||
$"Duplicate collection name '{subCollectionName}' found. Collection names must be unique per level."
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
parentCollection.Elements.AddRange(collectionGoo.Value.Elements);
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessObjectInputs(
|
||||
List<IGH_Goo> objects,
|
||||
SpeckleCollectionWrapper parentCollection,
|
||||
List<string> childPath
|
||||
)
|
||||
{
|
||||
foreach (var obj in objects)
|
||||
{
|
||||
var wrapperGoo = new SpeckleObjectWrapperGoo();
|
||||
if (wrapperGoo.CastFrom(obj))
|
||||
{
|
||||
wrapperGoo.Value.Path = childPath;
|
||||
wrapperGoo.Value.Parent = parentCollection;
|
||||
parentCollection.Elements.Add(wrapperGoo.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IGH_VariableParameterComponent implementation
|
||||
public override bool CanInsertParameter(GH_ParameterSide side, int index) => side == GH_ParameterSide.Input;
|
||||
|
||||
public override bool CanRemoveParameter(GH_ParameterSide side, int index) => side == GH_ParameterSide.Input;
|
||||
|
||||
public override bool DestroyParameter(GH_ParameterSide side, int index) => side == GH_ParameterSide.Input;
|
||||
|
||||
public override IGH_Param CreateParameter(GH_ParameterSide side, int index)
|
||||
{
|
||||
var param = CreateVariableParameter($"Sub-Collection {Params.Input.Count + 1}", GH_ParamAccess.tree);
|
||||
return param;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using GH_IO.Serialization;
|
||||
using Grasshopper.Kernel;
|
||||
using Grasshopper.Kernel.Parameters;
|
||||
using Speckle.Connectors.GrasshopperShared.HostApp.Extras;
|
||||
using Speckle.Connectors.GrasshopperShared.Components.BaseComponents;
|
||||
using Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
using Speckle.Connectors.GrasshopperShared.Properties;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Components.Objects;
|
||||
|
||||
/// <summary>
|
||||
/// Simplified CreateSpeckleProperties component using the base class pattern
|
||||
/// </summary>
|
||||
[Guid("A3FD5CBF-DFB0-44DF-9988-04466EB8E5E6")]
|
||||
public class CreateSpeckleProperties : GH_Component, IGH_VariableParameterComponent
|
||||
public class CreateSpeckleProperties : VariableParameterComponentBase
|
||||
{
|
||||
private bool CreateEmptyProperties { get; set; }
|
||||
|
||||
public override Guid ComponentGuid => GetType().GUID;
|
||||
protected override Bitmap Icon => Resources.speckle_properties_create;
|
||||
|
||||
public CreateSpeckleProperties()
|
||||
: base(
|
||||
"Create Properties",
|
||||
@@ -19,18 +27,10 @@ public class CreateSpeckleProperties : GH_Component, IGH_VariableParameterCompon
|
||||
ComponentCategories.OBJECTS
|
||||
) { }
|
||||
|
||||
public override Guid ComponentGuid => GetType().GUID;
|
||||
|
||||
protected override Bitmap Icon => Resources.speckle_properties_create;
|
||||
|
||||
public bool CreateEmptyProperties { get; set; }
|
||||
|
||||
private readonly DebounceDispatcher _debounceDispatcher = new();
|
||||
|
||||
protected override void RegisterInputParams(GH_InputParamManager pManager)
|
||||
{
|
||||
var p = CreateParameter(GH_ParameterSide.Input, 0);
|
||||
pManager.AddParameter(p);
|
||||
var param = CreateParameter(GH_ParameterSide.Input, 0);
|
||||
pManager.AddParameter(param);
|
||||
}
|
||||
|
||||
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
|
||||
@@ -40,147 +40,117 @@ public class CreateSpeckleProperties : GH_Component, IGH_VariableParameterCompon
|
||||
|
||||
protected override void SolveInstance(IGH_DataAccess da)
|
||||
{
|
||||
// Create a data tree to store output
|
||||
Dictionary<string, SpecklePropertyGoo> properties = new();
|
||||
var properties = new Dictionary<string, SpecklePropertyGoo>();
|
||||
|
||||
// Check for structure of all inputs to see matching branches
|
||||
foreach (var inputParam in Params.Input)
|
||||
// Validate for duplicate names
|
||||
var paramNames = Params.Input.Select(p => p.NickName).ToList();
|
||||
var duplicates = paramNames.GroupBy(x => x).Where(g => g.Count() > 1).Select(g => g.Key);
|
||||
|
||||
if (duplicates.Any())
|
||||
{
|
||||
string inputName = inputParam.NickName;
|
||||
|
||||
if (properties.ContainsKey(inputName))
|
||||
{
|
||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, $"Duplicate property name found: {inputName}.");
|
||||
return;
|
||||
}
|
||||
|
||||
properties.Add(inputName, new());
|
||||
AddRuntimeMessage(
|
||||
GH_RuntimeMessageLevel.Error,
|
||||
$"Duplicate property names found: {string.Join(", ", duplicates)}"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Process each input parameter
|
||||
for (int i = 0; i < Params.Input.Count; i++)
|
||||
{
|
||||
object? value = null;
|
||||
da.GetData(i, ref value);
|
||||
var paramName = Params.Input[i].NickName;
|
||||
var propertyValue = ExtractPropertyValue(da, i, paramName);
|
||||
|
||||
// POC: for now, allow empty properties
|
||||
SpecklePropertyGoo actualValue = new();
|
||||
if (value != null)
|
||||
if (propertyValue != null)
|
||||
{
|
||||
if (!actualValue.CastFrom(value))
|
||||
{
|
||||
AddRuntimeMessage(
|
||||
GH_RuntimeMessageLevel.Error,
|
||||
$"Parameter {Params.Input[i].NickName} should not contain anything other than strings, doubles, ints, and bools."
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
properties[paramName] = propertyValue;
|
||||
}
|
||||
|
||||
properties[Params.Input[i].NickName] = actualValue;
|
||||
}
|
||||
|
||||
var groupGoo = new SpecklePropertyGroupGoo(properties);
|
||||
da.SetData(0, groupGoo);
|
||||
}
|
||||
|
||||
public bool CanInsertParameter(GH_ParameterSide side, int index)
|
||||
private SpecklePropertyGoo? ExtractPropertyValue(IGH_DataAccess da, int index, string paramName)
|
||||
{
|
||||
return side == GH_ParameterSide.Input && !CreateEmptyProperties;
|
||||
}
|
||||
object? value = null;
|
||||
da.GetData(index, ref value);
|
||||
|
||||
public bool CanRemoveParameter(GH_ParameterSide side, int index)
|
||||
{
|
||||
return side == GH_ParameterSide.Input;
|
||||
}
|
||||
var propertyGoo = new SpecklePropertyGoo();
|
||||
|
||||
public IGH_Param CreateParameter(GH_ParameterSide side, int index)
|
||||
{
|
||||
var myParam = new Param_GenericObject
|
||||
if (value == null)
|
||||
{
|
||||
Name = $"Property {Params.Input.Count + 1}",
|
||||
MutableNickName = true,
|
||||
Optional = true,
|
||||
Access = GH_ParamAccess.item
|
||||
};
|
||||
return propertyGoo; // Return empty property
|
||||
}
|
||||
|
||||
myParam.NickName = myParam.Name;
|
||||
myParam.Optional = true;
|
||||
return myParam;
|
||||
}
|
||||
|
||||
public bool DestroyParameter(GH_ParameterSide side, int index)
|
||||
{
|
||||
return side == GH_ParameterSide.Input;
|
||||
}
|
||||
|
||||
public void VariableParameterMaintenance()
|
||||
{
|
||||
// todo
|
||||
}
|
||||
|
||||
public override void AddedToDocument(GH_Document document)
|
||||
{
|
||||
base.AddedToDocument(document);
|
||||
Params.ParameterChanged += (sender, args) =>
|
||||
if (!propertyGoo.CastFrom(value))
|
||||
{
|
||||
if (args.ParameterSide == GH_ParameterSide.Output)
|
||||
{
|
||||
return;
|
||||
}
|
||||
AddRuntimeMessage(
|
||||
GH_RuntimeMessageLevel.Error,
|
||||
$"Parameter '{paramName}' contains invalid data type. Only strings, numbers, and booleans are supported."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (args.OriginalArguments.Type)
|
||||
{
|
||||
case GH_ObjectEventType.NickName:
|
||||
// This means the user is typing characters, debounce until it stops for 400ms before expiring the solution.
|
||||
// Prevents UI from locking too soon while writing new names for inputs.
|
||||
args.Parameter.Name = args.Parameter.NickName;
|
||||
_debounceDispatcher.Debounce(500, e => ExpireSolution(true));
|
||||
break;
|
||||
case GH_ObjectEventType.NickNameAccepted:
|
||||
args.Parameter.Name = args.Parameter.NickName;
|
||||
ExpireSolution(true);
|
||||
break;
|
||||
case GH_ObjectEventType.Sources:
|
||||
// if this event is a source change, and param is the last input, then add a new param automatically
|
||||
if (args.Parameter.SourceCount > 0 && args.ParameterIndex == Params.Input.Count - 1)
|
||||
{
|
||||
IGH_Param param = CreateParameter(GH_ParameterSide.Input, Params.Input.Count);
|
||||
Params.RegisterInputParam(param);
|
||||
Params.OnParametersChanged();
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
return propertyGoo;
|
||||
}
|
||||
|
||||
public override void AppendAdditionalMenuItems(ToolStripDropDown menu)
|
||||
protected override void AppendComponentSpecificMenuItems(ToolStripDropDown menu)
|
||||
{
|
||||
base.AppendAdditionalMenuItems(menu);
|
||||
|
||||
Menu_AppendSeparator(menu);
|
||||
ToolStripMenuItem emptyPropsMenuItem = Menu_AppendItem(
|
||||
var emptyPropsMenuItem = Menu_AppendItem(
|
||||
menu,
|
||||
"Create empty Properties",
|
||||
(s, e) =>
|
||||
{
|
||||
CreateEmptyProperties = !CreateEmptyProperties;
|
||||
if (CreateEmptyProperties)
|
||||
{
|
||||
Params.Input.Clear();
|
||||
ClearData();
|
||||
}
|
||||
else if (Params.Input.Count == 0)
|
||||
{
|
||||
var p = CreateParameter(GH_ParameterSide.Input, 0);
|
||||
Params.RegisterInputParam(p);
|
||||
}
|
||||
ExpireSolution(true);
|
||||
},
|
||||
(_, _) => ToggleCreateEmptyProperties(),
|
||||
true,
|
||||
CreateEmptyProperties
|
||||
);
|
||||
emptyPropsMenuItem.ToolTipText =
|
||||
"Toggle creating empty Properties. If set, the output Properties will be empty. Use for removing properties from objects.";
|
||||
emptyPropsMenuItem.ToolTipText = "Creates empty properties. Use for removing properties from objects.";
|
||||
}
|
||||
|
||||
private void ToggleCreateEmptyProperties()
|
||||
{
|
||||
CreateEmptyProperties = !CreateEmptyProperties;
|
||||
|
||||
if (CreateEmptyProperties)
|
||||
{
|
||||
Params.Input.Clear();
|
||||
ClearData();
|
||||
}
|
||||
else if (Params.Input.Count == 0)
|
||||
{
|
||||
var param = CreateParameter(GH_ParameterSide.Input, 0);
|
||||
Params.RegisterInputParam(param);
|
||||
}
|
||||
|
||||
ExpireSolution(true);
|
||||
}
|
||||
|
||||
protected override void WriteComponentSpecificData(GH_IWriter writer)
|
||||
{
|
||||
writer.SetBoolean("CreateEmptyProperties", CreateEmptyProperties);
|
||||
}
|
||||
|
||||
protected override void ReadComponentSpecificData(GH_IReader reader)
|
||||
{
|
||||
bool createEmpty = default;
|
||||
if (reader.TryGetBoolean("CreateEmptyProperties", ref createEmpty))
|
||||
{
|
||||
CreateEmptyProperties = createEmpty;
|
||||
}
|
||||
}
|
||||
|
||||
// IGH_VariableParameterComponent implementation
|
||||
public override bool CanInsertParameter(GH_ParameterSide side, int index) =>
|
||||
side == GH_ParameterSide.Input && !CreateEmptyProperties;
|
||||
|
||||
public override bool CanRemoveParameter(GH_ParameterSide side, int index) => side == GH_ParameterSide.Input;
|
||||
|
||||
public override bool DestroyParameter(GH_ParameterSide side, int index) => side == GH_ParameterSide.Input;
|
||||
|
||||
public override IGH_Param CreateParameter(GH_ParameterSide side, int index)
|
||||
{
|
||||
var param = CreateVariableParameter($"Property {Params.Input.Count + 1}", GH_ParamAccess.item);
|
||||
return param;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ public class SendAsyncComponent : GH_AsyncComponent
|
||||
{
|
||||
Menu_AppendSeparator(menu);
|
||||
|
||||
Menu_AppendItem(menu, $"View created version online ↗", (s, e) => Open(Url));
|
||||
Menu_AppendItem(menu, $"View created model online ↗", (s, e) => Open(Url));
|
||||
}
|
||||
|
||||
Menu_AppendSeparator(menu);
|
||||
@@ -336,7 +336,7 @@ public class SendComponentWorker : WorkerInstance
|
||||
*/
|
||||
Parent.AddRuntimeMessage(
|
||||
GH_RuntimeMessageLevel.Remark,
|
||||
$"Successfully published to Speckle. Right-click to view online."
|
||||
$"Successfully published to Speckle. Right-click on the component to view online."
|
||||
);
|
||||
Parent.AddRuntimeMessage(
|
||||
GH_RuntimeMessageLevel.Remark,
|
||||
@@ -429,8 +429,7 @@ public class SendComponentWorker : WorkerInstance
|
||||
result.VersionId
|
||||
);
|
||||
OutputParam = createdVersion;
|
||||
sendComponent.Url =
|
||||
$"{createdVersion.Server}projects/{sendInfo.ProjectId}/models/{sendInfo.ModelId}@{result.VersionId}";
|
||||
sendComponent.Url = $"{createdVersion.Server}projects/{sendInfo.ProjectId}/models/{sendInfo.ModelId}";
|
||||
|
||||
// DONE
|
||||
done();
|
||||
|
||||
@@ -119,7 +119,7 @@ public class SendComponent : SpeckleScopedTaskCapableComponent<SendComponentInpu
|
||||
{
|
||||
Menu_AppendSeparator(menu);
|
||||
|
||||
Menu_AppendItem(menu, $"View created version online ↗", (s, e) => Open(Url));
|
||||
Menu_AppendItem(menu, $"View created model online ↗", (s, e) => Open(Url));
|
||||
}
|
||||
|
||||
static void Open(string url)
|
||||
@@ -183,7 +183,7 @@ public class SendComponent : SpeckleScopedTaskCapableComponent<SendComponentInpu
|
||||
sendInfo.ProjectId,
|
||||
sendInfo.ModelId
|
||||
);
|
||||
Url = $"{createdVersionResource.Server}projects/{sendInfo.ProjectId}/models/{sendInfo.ModelId}"; // TODO: missing "@VersionId"
|
||||
Url = $"{createdVersionResource.Server}projects/{sendInfo.ProjectId}/models/{sendInfo.ModelId}";
|
||||
|
||||
return new SendComponentOutput(createdVersionResource);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Connectors.GrasshopperShared.HostApp;
|
||||
@@ -49,7 +49,7 @@ public class SpeckleOperationWizard
|
||||
|
||||
var userSelectedAccountId = _accountService.GetUserSelectedAccountId();
|
||||
Accounts = _accountManager.GetAccounts().ToList();
|
||||
SelectedAccount = userSelectedAccountId == null ? null : _accountManager.GetAccount(userSelectedAccountId);
|
||||
SelectedAccount = Accounts.FirstOrDefault(a => a.id == userSelectedAccountId);
|
||||
|
||||
WorkspaceMenuHandler = new WorkspaceMenuHandler(FetchWorkspaces, CreateNewWorkspace);
|
||||
ProjectMenuHandler = new ProjectMenuHandler(FetchProjects);
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
using Grasshopper;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.HostApp;
|
||||
|
||||
/// <summary>
|
||||
/// Simple utility to track Tab key state for name inheritance during parameter connections
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Taken from legacy (v2) code
|
||||
/// </remarks>
|
||||
public static class KeyWatcher
|
||||
{
|
||||
public static bool TabPressed { get; private set; }
|
||||
|
||||
private static bool s_initialized;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the key watcher by hooking into Grasshopper canvas events
|
||||
/// Call this once during component initialization
|
||||
/// </summary>
|
||||
public static void Initialize()
|
||||
{
|
||||
if (s_initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// hook into canvas creation event
|
||||
Instances.CanvasCreated += OnCanvasCreated;
|
||||
|
||||
// if canvas already exists, hook into it immediately
|
||||
if (Instances.ActiveCanvas != null)
|
||||
{
|
||||
HookIntoCanvas(Instances.ActiveCanvas);
|
||||
}
|
||||
|
||||
s_initialized = true;
|
||||
}
|
||||
|
||||
private static void OnCanvasCreated(Grasshopper.GUI.Canvas.GH_Canvas canvas)
|
||||
{
|
||||
if (canvas != null)
|
||||
{
|
||||
HookIntoCanvas(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
private static void HookIntoCanvas(Grasshopper.GUI.Canvas.GH_Canvas canvas)
|
||||
{
|
||||
canvas.KeyDown += (s, e) =>
|
||||
{
|
||||
if (e.KeyCode == Keys.Tab && !TabPressed)
|
||||
{
|
||||
TabPressed = true;
|
||||
}
|
||||
};
|
||||
|
||||
canvas.KeyUp += (s, e) =>
|
||||
{
|
||||
if (TabPressed && e.KeyCode == Keys.Tab)
|
||||
{
|
||||
TabPressed = false;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
using GH_IO.Serialization;
|
||||
using Grasshopper.Kernel;
|
||||
using Grasshopper.Kernel.Parameters;
|
||||
using Speckle.Connectors.GrasshopperShared.HostApp;
|
||||
|
||||
namespace Speckle.Connectors.GrasshopperShared.Parameters;
|
||||
|
||||
/// <summary>
|
||||
/// Simplified parameter with name inheritance support
|
||||
/// Focuses on core functionality: Tab key inheritance and AlwaysInheritNames
|
||||
/// </summary>
|
||||
public class SpeckleVariableParam : Param_GenericObject
|
||||
{
|
||||
private bool _alwaysInheritNames;
|
||||
private readonly HashSet<IGH_Param> _sourceSubscriptions = [];
|
||||
private bool _isUpdatingName; // Prevent recursive updates
|
||||
|
||||
static SpeckleVariableParam()
|
||||
{
|
||||
KeyWatcher.Initialize();
|
||||
}
|
||||
|
||||
public bool CanInheritNames { get; set; } = true;
|
||||
|
||||
public bool AlwaysInheritNames
|
||||
{
|
||||
get => _alwaysInheritNames;
|
||||
set
|
||||
{
|
||||
if (_alwaysInheritNames == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_alwaysInheritNames = value;
|
||||
|
||||
// disable manual renaming when AlwaysInheritNames is enabled
|
||||
MutableNickName = !value;
|
||||
|
||||
if (value)
|
||||
{
|
||||
SubscribeToSources();
|
||||
TryInheritName();
|
||||
}
|
||||
else
|
||||
{
|
||||
UnsubscribeFromSources();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override Guid ComponentGuid => new("A1B2C3D4-E5F6-7890-ABCD-123456789ABC");
|
||||
|
||||
public override void AddSource(IGH_Param source, int index)
|
||||
{
|
||||
base.AddSource(source, index);
|
||||
|
||||
if (AlwaysInheritNames)
|
||||
{
|
||||
SubscribeToSource(source);
|
||||
}
|
||||
|
||||
// Inherit name on Tab key or when AlwaysInheritNames is enabled
|
||||
if (ShouldInheritName())
|
||||
{
|
||||
TryInheritName();
|
||||
}
|
||||
}
|
||||
|
||||
public override void RemoveSource(IGH_Param source)
|
||||
{
|
||||
UnsubscribeFromSource(source);
|
||||
base.RemoveSource(source);
|
||||
|
||||
if (AlwaysInheritNames)
|
||||
{
|
||||
TryInheritName();
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShouldInheritName() => CanInheritNames && (AlwaysInheritNames || KeyWatcher.TabPressed);
|
||||
|
||||
private void TryInheritName()
|
||||
{
|
||||
if (!CanInheritNames || Sources.Count == 0 || _isUpdatingName)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var names = Sources.Select(s => s.NickName).Where(n => !string.IsNullOrWhiteSpace(n)).ToList();
|
||||
if (names.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var inheritedName = string.Join("|", names);
|
||||
|
||||
// Only update if the name actually changed to avoid unnecessary events
|
||||
if (NickName != inheritedName)
|
||||
{
|
||||
_isUpdatingName = true;
|
||||
try
|
||||
{
|
||||
// Temporarily allow renaming for programmatic update
|
||||
MutableNickName = true;
|
||||
|
||||
Name = inheritedName;
|
||||
NickName = inheritedName;
|
||||
|
||||
// Restore the correct state
|
||||
MutableNickName = !AlwaysInheritNames;
|
||||
|
||||
// Tell the parent component its layout needs to be recalculated
|
||||
Attributes.Parent?.ExpireLayout();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isUpdatingName = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SubscribeToSources()
|
||||
{
|
||||
foreach (var source in Sources)
|
||||
{
|
||||
SubscribeToSource(source);
|
||||
}
|
||||
}
|
||||
|
||||
private void SubscribeToSource(IGH_Param source)
|
||||
{
|
||||
if (_sourceSubscriptions.Add(source))
|
||||
{
|
||||
source.ObjectChanged += OnSourceChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private void UnsubscribeFromSources()
|
||||
{
|
||||
foreach (var source in _sourceSubscriptions.ToList())
|
||||
{
|
||||
UnsubscribeFromSource(source);
|
||||
}
|
||||
}
|
||||
|
||||
private void UnsubscribeFromSource(IGH_Param source)
|
||||
{
|
||||
if (_sourceSubscriptions.Remove(source))
|
||||
{
|
||||
source.ObjectChanged -= OnSourceChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSourceChanged(IGH_DocumentObject sender, GH_ObjectChangedEventArgs e)
|
||||
{
|
||||
if (!AlwaysInheritNames || _isUpdatingName)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.Type == GH_ObjectEventType.NickName || e.Type == GH_ObjectEventType.NickNameAccepted)
|
||||
{
|
||||
// Use immediate UI thread invocation for responsive name inheritance
|
||||
Rhino.RhinoApp.InvokeOnUiThread(() =>
|
||||
{
|
||||
if (AlwaysInheritNames && !_isUpdatingName) // Double-check in case it changed
|
||||
{
|
||||
TryInheritName();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public override void RemovedFromDocument(GH_Document document)
|
||||
{
|
||||
UnsubscribeFromSources();
|
||||
base.RemovedFromDocument(document);
|
||||
}
|
||||
|
||||
public override bool Write(GH_IWriter writer)
|
||||
{
|
||||
var result = base.Write(writer);
|
||||
writer.SetBoolean("CanInheritNames", CanInheritNames);
|
||||
writer.SetBoolean("AlwaysInheritNames", AlwaysInheritNames);
|
||||
return result;
|
||||
}
|
||||
|
||||
public override bool Read(GH_IReader reader)
|
||||
{
|
||||
var result = base.Read(reader);
|
||||
bool canInherit = true;
|
||||
if (reader.TryGetBoolean("CanInheritNames", ref canInherit))
|
||||
{
|
||||
CanInheritNames = canInherit;
|
||||
}
|
||||
|
||||
bool alwaysInherit = false;
|
||||
if (reader.TryGetBoolean("AlwaysInheritNames", ref alwaysInherit))
|
||||
{
|
||||
_alwaysInheritNames = alwaysInherit; // Set backing field directly during deserialization to avoid triggering logic
|
||||
MutableNickName = !alwaysInherit; // Set MutableNickName based on the loaded value
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected override void OnVolatileDataCollected()
|
||||
{
|
||||
base.OnVolatileDataCollected();
|
||||
|
||||
// Ensure subscriptions are properly set up after data collection
|
||||
// and after the object is fully deserialized
|
||||
if (AlwaysInheritNames)
|
||||
{
|
||||
SubscribeToSources();
|
||||
TryInheritName();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Components\BaseComponents\SpeckleTaskCapableComponent.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Components\BaseComponents\Operator.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Components\BaseComponents\ValueSet.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Components\BaseComponents\VariableParameterComponentBase.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Components\Collections\CollectionPathsSelector.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Components\Collections\CreateCollection.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Components\Collections\ExpandCollection.cs" />
|
||||
@@ -32,6 +33,7 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Components\Operations\Wizard\VersionMenuHandler.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Components\Operations\Wizard\WorkspaceMenuHandler.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Components\Operations\Wizard\SpeckleOperationWizard.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\KeyWatcher.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Operations\Receive\GrasshopperMaterialUnpacker.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Components\Objects\GetObjectProperties.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Components\Objects\PropertyGroupPathsSelector.cs" />
|
||||
@@ -52,6 +54,7 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\Helpers.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\SpeckleResource.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)HostApp\SpeckleResourceBuilder.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Parameters\SpeckleVariableParam.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Parameters\SpeckleWrapper.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Parameters\SpeckleMaterialWrapper.ModelObjects.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Parameters\SpeckleMaterialWrapper.cs" />
|
||||
|
||||
@@ -306,9 +306,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -341,7 +341,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.rhino7": {
|
||||
@@ -398,18 +398,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -419,14 +419,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
},
|
||||
"System.Resources.Extensions": {
|
||||
"type": "CentralTransitive",
|
||||
|
||||
@@ -306,9 +306,9 @@
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
|
||||
"Speckle.Connectors.Logging": "[1.0.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )",
|
||||
"Speckle.Sdk": "[3.3.5, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )",
|
||||
"Speckle.Sdk": "[3.3.6, )",
|
||||
"Speckle.Sdk.Dependencies": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.connectors.dui": {
|
||||
@@ -341,7 +341,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )",
|
||||
"Speckle.Objects": "[3.3.5, )"
|
||||
"Speckle.Objects": "[3.3.6, )"
|
||||
}
|
||||
},
|
||||
"speckle.converters.rhino8": {
|
||||
@@ -398,18 +398,18 @@
|
||||
},
|
||||
"Speckle.Objects": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "VPbYI8TyPDlKlNUHPLPAL1HveN9649LKVxw8opgGypoqq0MC5I7WxQjDcuB8xKnQ1PCSO8suu4hEJgdyPcEvWg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "zSNOgVwTXu/27oG2OLfJbgi3Myhx23KWFdnVHF+feFEHlnE6PstpnEZRqduoZDQL0FJyEva+nmiBnpZSRe5LSw==",
|
||||
"dependencies": {
|
||||
"Speckle.Sdk": "3.3.5"
|
||||
"Speckle.Sdk": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "7r8CmugwinniEF6v0N0bWuC+xpJaRfa/EnEjzj8NLpFG1b3uAjOxteGlQgR+evVacxTCEsuNkio7Mdv97odgpg==",
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "VHSah5DYRv6OIHPr7ztArgiZNKEs/SRCz0JfLnK+otVZb1awWj4xW2DA2Bb6I466IdUd24fOEJdFRaTHA/X+mw==",
|
||||
"dependencies": {
|
||||
"GraphQL.Client": "6.0.0",
|
||||
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
|
||||
@@ -419,14 +419,14 @@
|
||||
"Microsoft.Extensions.Logging": "2.2.0",
|
||||
"Speckle.DoubleNumerics": "4.1.0",
|
||||
"Speckle.Newtonsoft.Json": "13.0.2",
|
||||
"Speckle.Sdk.Dependencies": "3.3.5"
|
||||
"Speckle.Sdk.Dependencies": "3.3.6"
|
||||
}
|
||||
},
|
||||
"Speckle.Sdk.Dependencies": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[3.3.5, )",
|
||||
"resolved": "3.3.5",
|
||||
"contentHash": "RukqLb0lVNgtmhKPeZJCncibnyutQ6Dr6+UQCa4PjWinIXpSm3A3ywK9ISkU+5StW1QoejiR7kc9a6qmiLys6w=="
|
||||
"requested": "[3.3.6, )",
|
||||
"resolved": "3.3.6",
|
||||
"contentHash": "qwbk9BAR1QZIAwphhwMXz5ftCUYXy2oOm9/Jg57MNeaxLZ8MFooygVwX/ETG4avR8bO+VLqoteBJjWl/yYlRLQ=="
|
||||
},
|
||||
"System.Resources.Extensions": {
|
||||
"type": "CentralTransitive",
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
using Rhino.DocObjects;
|
||||
using Speckle.Sdk.Models;
|
||||
using DataObject = Speckle.Objects.Data.DataObject;
|
||||
|
||||
namespace Speckle.Connectors.Rhino.Extensions;
|
||||
|
||||
public static class SpeckleAttributeExtensions
|
||||
{
|
||||
private const string PROPERTY_PATH_DELIMITER = ".";
|
||||
|
||||
/// <summary>
|
||||
/// Gets Rhino object attributes from a Base, including name and user strings.
|
||||
/// </summary>
|
||||
/// <param name="base"></param>
|
||||
/// <returns></returns>
|
||||
public static ObjectAttributes GetAttributes(this Base @base)
|
||||
{
|
||||
string name = @base["name"] as string ?? "";
|
||||
ObjectAttributes atts = new() { Name = name };
|
||||
Dictionary<string, string> userStrings = new();
|
||||
Dictionary<string, object?> properties = @base is DataObject dataObj
|
||||
? dataObj.properties
|
||||
: @base["properties"] as Dictionary<string, object?> ?? new();
|
||||
FlattenDictionaryToUserStrings(properties, userStrings, "");
|
||||
foreach (var kvp in userStrings)
|
||||
{
|
||||
// POC: we're skipping properties that end with `.name` , `.units`, etc because this is causing a lot of noise atm.
|
||||
if (kvp.Key.EndsWith(".units") || kvp.Key.EndsWith(".name") || kvp.Key.EndsWith(".internalDefinitionName"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
atts.SetUserString(kvp.Key, kvp.Value);
|
||||
}
|
||||
|
||||
return atts;
|
||||
}
|
||||
|
||||
// changes a properties dictionary to <string,string> to assign as user strings.
|
||||
private static void FlattenDictionaryToUserStrings(
|
||||
Dictionary<string, object?> dict,
|
||||
Dictionary<string, string> flattenedDict,
|
||||
string keyPrefix = ""
|
||||
)
|
||||
{
|
||||
foreach (var kvp in dict)
|
||||
{
|
||||
string newKey = string.IsNullOrEmpty(keyPrefix) ? kvp.Key : $"{keyPrefix}{PROPERTY_PATH_DELIMITER}{kvp.Key}";
|
||||
|
||||
if (kvp.Value is Dictionary<string, object?> childDict)
|
||||
{
|
||||
FlattenDictionaryToUserStrings(childDict, flattenedDict, newKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
flattenedDict.Add(newKey, kvp.Value?.ToString() ?? "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,11 @@ public class PropertiesExtractor
|
||||
{
|
||||
try
|
||||
{
|
||||
if (key == "$block-instance-original-object-id$") // skip: this seems to be an invisible user string that shows up on block instances
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (userStrings[key].StartsWith("%<"))
|
||||
{
|
||||
var value = RhinoApp.ParseTextField(userStrings[key], rhObject, null);
|
||||
|
||||
@@ -127,7 +127,9 @@ public class RhinoInstanceBaker : IInstanceBaker<IReadOnlyCollection<string>>
|
||||
int layerIndex = _layerBaker.GetLayerIndex(layerCollection, baseLayerName);
|
||||
string instanceProxyId = instanceProxy.applicationId ?? instanceProxy.id.NotNull();
|
||||
|
||||
ObjectAttributes atts = new() { LayerIndex = layerIndex };
|
||||
// create attributes
|
||||
ObjectAttributes atts = instanceProxy.GetAttributes();
|
||||
atts.LayerIndex = layerIndex;
|
||||
if (_materialBaker.ObjectIdAndMaterialIndexMap.TryGetValue(instanceProxyId, out int mIndex))
|
||||
{
|
||||
atts.MaterialIndex = mIndex;
|
||||
|
||||
@@ -48,18 +48,25 @@ public class RhinoLayerBaker : TraversalContextUnpacker
|
||||
/// <remarks>Make sure this is executing on the main thread, using e.g RhinoApp.InvokeAndWait.</remarks>
|
||||
public void CreateAllLayersForReceive(IEnumerable<Collection[]> paths, string baseLayerName)
|
||||
{
|
||||
CreateBaseLayer(baseLayerName);
|
||||
var uniquePaths = new Dictionary<string, Collection[]>();
|
||||
foreach (var path in paths)
|
||||
try
|
||||
{
|
||||
var names = path.Select(o => string.IsNullOrWhiteSpace(o.name) ? "unnamed" : o.name);
|
||||
var key = string.Join(",", names!);
|
||||
uniquePaths[key] = path;
|
||||
}
|
||||
CreateBaseLayer(baseLayerName);
|
||||
var uniquePaths = new Dictionary<string, Collection[]>();
|
||||
foreach (var path in paths)
|
||||
{
|
||||
var names = path.Select(o => string.IsNullOrWhiteSpace(o.name) ? "unnamed" : o.name);
|
||||
var key = string.Join(",", names!);
|
||||
uniquePaths[key] = path;
|
||||
}
|
||||
|
||||
foreach (var uniquePath in uniquePaths)
|
||||
foreach (var uniquePath in uniquePaths)
|
||||
{
|
||||
var layerIndex = CreateLayerFromPath(uniquePath.Value, baseLayerName);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!ex.IsFatal())
|
||||
{
|
||||
var layerIndex = CreateLayerFromPath(uniquePath.Value, baseLayerName);
|
||||
throw new SpeckleException("Could not create all layers for receive.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +83,7 @@ public class RhinoLayerBaker : TraversalContextUnpacker
|
||||
.Select(o => string.IsNullOrWhiteSpace(o.name) ? "unnamed" : o.name)
|
||||
.Prepend(baseLayerName);
|
||||
|
||||
var layerFullName = string.Join(s_pathSeparator, layerPath);
|
||||
var layerFullName = CleanLayerName(string.Join(s_pathSeparator, layerPath));
|
||||
|
||||
if (_hostLayerCache.TryGetValue(layerFullName, out int existingLayerIndex))
|
||||
{
|
||||
@@ -86,6 +93,22 @@ public class RhinoLayerBaker : TraversalContextUnpacker
|
||||
throw new SpeckleException($"Did not find a layer in the cache with the name {layerFullName}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleans up layer names to be "rhino" proof. Note this can be improved, as "()[] and {}" are illegal only at the start.
|
||||
/// https://docs.mcneel.com/rhino/6/help/en-us/index.htm#information/namingconventions.htm?Highlight=naming
|
||||
/// </summary>
|
||||
/// <param name="layerName"></param>
|
||||
/// <returns></returns>
|
||||
private string CleanLayerName(string layerName) =>
|
||||
layerName
|
||||
.Replace("{", "")
|
||||
.Replace("}", "")
|
||||
.Replace("(", "")
|
||||
.Replace(")", "")
|
||||
.Replace("[", "")
|
||||
.Replace("]", "")
|
||||
.Replace(":", "");
|
||||
|
||||
/// <summary>
|
||||
/// Creates a layer based on the given collection path and adds it to the Rhino document.
|
||||
/// </summary>
|
||||
@@ -101,14 +124,14 @@ public class RhinoLayerBaker : TraversalContextUnpacker
|
||||
{
|
||||
currentLayerName += s_pathSeparator + (string.IsNullOrWhiteSpace(collection.name) ? "unnamed" : collection.name);
|
||||
|
||||
currentLayerName = currentLayerName.Replace("{", "").Replace("}", ""); // Rhino specific cleanup for gh (see RemoveInvalidRhinoChars)
|
||||
currentLayerName = CleanLayerName(currentLayerName); //.Replace("{", "").Replace("}", ""); // Rhino specific cleanup for gh (see RemoveInvalidRhinoChars)
|
||||
if (_hostLayerCache.TryGetValue(currentLayerName, out int value))
|
||||
{
|
||||
previousLayer = currentDocument.Layers.FindIndex(value);
|
||||
continue;
|
||||
}
|
||||
|
||||
var cleanNewLayerName = collection.name.Replace("{", "").Replace("}", "");
|
||||
var cleanNewLayerName = CleanLayerName(collection.name); //.Replace("{", "").Replace("}", "").Replace("(", "").Replace(")", "");
|
||||
Layer newLayer = new() { Name = cleanNewLayerName, ParentLayerId = previousLayer?.Id ?? Guid.Empty };
|
||||
|
||||
// set material
|
||||
|
||||
@@ -7,6 +7,7 @@ using Speckle.Connectors.Common.Extensions;
|
||||
using Speckle.Connectors.Common.Operations;
|
||||
using Speckle.Connectors.Common.Operations.Receive;
|
||||
using Speckle.Connectors.Common.Threading;
|
||||
using Speckle.Connectors.Rhino.Extensions;
|
||||
using Speckle.Connectors.Rhino.HostApp;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Converters.Rhino;
|
||||
@@ -16,7 +17,6 @@ using Speckle.Sdk.Logging;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using Speckle.Sdk.Models.Instances;
|
||||
using DataObject = Speckle.Objects.Data.DataObject;
|
||||
|
||||
namespace Speckle.Connectors.Rhino.Operations.Receive;
|
||||
|
||||
@@ -36,8 +36,6 @@ public class RhinoHostObjectBuilder : IHostObjectBuilder
|
||||
private readonly ISdkActivityFactory _activityFactory;
|
||||
private readonly IThreadContext _threadContext;
|
||||
|
||||
private const string PROPERTY_PATH_DELIMITER = ".";
|
||||
|
||||
public RhinoHostObjectBuilder(
|
||||
IRootToHostConverter converter,
|
||||
IConverterSettingsStore<RhinoConversionSettings> converterSettings,
|
||||
@@ -156,27 +154,8 @@ public class RhinoHostObjectBuilder : IHostObjectBuilder
|
||||
int layerIndex = _layerBaker.GetLayerIndex(path, baseLayerName);
|
||||
|
||||
// 1: create object attributes for baking
|
||||
string name = obj["name"] as string ?? "";
|
||||
using ObjectAttributes atts = new() { LayerIndex = layerIndex, Name = name };
|
||||
Dictionary<string, string> userStrings = new();
|
||||
Dictionary<string, object?> properties = obj is DataObject dataObj
|
||||
? dataObj.properties
|
||||
: obj["properties"] as Dictionary<string, object?> ?? new();
|
||||
FlattenDictionaryToUserStrings(properties, userStrings, "");
|
||||
foreach (var kvp in userStrings)
|
||||
{
|
||||
// POC: we're skipping properties that end with `.name` , `.units`, etc because this is causing a lot of noise atm.
|
||||
if (
|
||||
kvp.Key.EndsWith(".units")
|
||||
|| kvp.Key.EndsWith(".name")
|
||||
|| kvp.Key.EndsWith(".internalDefinitionName")
|
||||
)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
atts.SetUserString(kvp.Key, kvp.Value);
|
||||
}
|
||||
ObjectAttributes atts = obj.GetAttributes();
|
||||
atts.LayerIndex = layerIndex;
|
||||
|
||||
// 2: convert
|
||||
var result = _converter.Convert(obj);
|
||||
@@ -388,26 +367,4 @@ public class RhinoHostObjectBuilder : IHostObjectBuilder
|
||||
|
||||
return objectIds;
|
||||
}
|
||||
|
||||
// changes a properties dictionary to <string,string> to assign as user strings.
|
||||
private void FlattenDictionaryToUserStrings(
|
||||
Dictionary<string, object?> dict,
|
||||
Dictionary<string, string> flattenedDict,
|
||||
string keyPrefix = ""
|
||||
)
|
||||
{
|
||||
foreach (var kvp in dict)
|
||||
{
|
||||
string newKey = string.IsNullOrEmpty(keyPrefix) ? kvp.Key : $"{keyPrefix}{PROPERTY_PATH_DELIMITER}{kvp.Key}";
|
||||
|
||||
if (kvp.Value is Dictionary<string, object?> childDict)
|
||||
{
|
||||
FlattenDictionaryToUserStrings(childDict, flattenedDict, newKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
flattenedDict.Add(newKey, kvp.Value?.ToString() ?? "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||