Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/bjorn/cnx-835-add-converter-proj…
Browse files Browse the repository at this point in the history
…ects-and-top-level-converter' into bjorn/cnx-835-add-converter-projects-and-top-level-converter
  • Loading branch information
bjoernsteinhagen committed Dec 3, 2024
2 parents f862e13 + 93fce9e commit 76d9f65
Show file tree
Hide file tree
Showing 12 changed files with 115 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,7 @@ public AutocadColorBaker(ILogger<AutocadColorBaker> logger)
/// </summary>
/// <param name="colorProxies"></param>
/// <param name="onOperationProgressed"></param>
public async Task ParseColors(
IReadOnlyCollection<ColorProxy> colorProxies,
IProgress<CardProgress> onOperationProgressed
)
public void ParseColors(IReadOnlyCollection<ColorProxy> colorProxies, IProgress<CardProgress> onOperationProgressed)
{
var count = 0;
foreach (ColorProxy colorProxy in colorProxies)
Expand Down Expand Up @@ -64,8 +61,6 @@ IProgress<CardProgress> onOperationProgressed
{
_logger.LogError(ex, "Failed parsing color proxy");
}

await Task.Yield();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ IConverterSettingsStore<AutocadConversionSettings> converterSettings
}

[SuppressMessage("Maintainability", "CA1506:Avoid excessive class coupling")]
public async Task<BakeResult> BakeInstances(
public BakeResult BakeInstances(
IReadOnlyCollection<(Collection[] collectionPath, IInstanceComponent obj)> instanceComponents,
Dictionary<string, List<Entity>> applicationIdMap,
string baseLayerName,
Expand Down Expand Up @@ -167,7 +167,6 @@ instanceOrDefinition is InstanceProxy instanceProxy
}

transaction.Commit();
await Task.Yield();
return new(createdObjectIds, consumedObjectIds, conversionResults);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public void PurgeMaterials(string namePrefix)
transaction.Commit();
}

public async Task ParseAndBakeRenderMaterials(
public void ParseAndBakeRenderMaterials(
List<RenderMaterialProxy> materialProxies,
string baseLayerPrefix,
IProgress<CardProgress> onOperationProgressed
Expand Down Expand Up @@ -140,7 +140,6 @@ IProgress<CardProgress> onOperationProgressed
}

transaction.Commit();
await Task.Yield();
}

private (ObjectId, ReceiveConversionResult) BakeMaterial(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,15 @@ CancellationToken _
// NOTE: This is the only place we apply ISyncToThread across connectors. We need to sync up with main thread here
// after GetObject and Deserialization. It is anti-pattern now. Happiness level 3/10 but works.
return await _syncToThread
.RunOnThread(
async () => await BuildImpl(rootObject, projectName, modelName, onOperationProgressed).ConfigureAwait(false)
)
.RunOnThread(async () =>
{
await Task.CompletedTask.ConfigureAwait(true);
return BuildSync(rootObject, projectName, modelName, onOperationProgressed);
})
.ConfigureAwait(false);
}

private async Task<HostObjectBuilderResult> BuildImpl(
private HostObjectBuilderResult BuildSync(
Base rootObject,
string projectName,
string modelName,
Expand Down Expand Up @@ -108,14 +110,16 @@ IProgress<CardProgress> onOperationProgressed
// 3 - Bake materials and colors, as they are used later down the line by layers and objects
if (unpackedRoot.RenderMaterialProxies != null)
{
await _materialBaker
.ParseAndBakeRenderMaterials(unpackedRoot.RenderMaterialProxies, baseLayerPrefix, onOperationProgressed)
.ConfigureAwait(true);
_materialBaker.ParseAndBakeRenderMaterials(
unpackedRoot.RenderMaterialProxies,
baseLayerPrefix,
onOperationProgressed
);
}

if (unpackedRoot.ColorProxies != null)
{
await _colorBaker.ParseColors(unpackedRoot.ColorProxies, onOperationProgressed).ConfigureAwait(true);
_colorBaker.ParseColors(unpackedRoot.ColorProxies, onOperationProgressed);
}

// 5 - Convert atomic objects
Expand All @@ -129,8 +133,7 @@ await _materialBaker
onOperationProgressed.Report(new("Converting objects", (double)++count / atomicObjects.Count));
try
{
List<Entity> convertedObjects = await ConvertObject(atomicObject, layerPath, baseLayerPrefix)
.ConfigureAwait(true);
List<Entity> convertedObjects = ConvertObject(atomicObject, layerPath, baseLayerPrefix);

applicationIdMap[objectId] = convertedObjects;

Expand All @@ -152,9 +155,12 @@ await _materialBaker
}

// 6 - Convert instances
var (createdInstanceIds, consumedObjectIds, instanceConversionResults) = await _instanceBaker
.BakeInstances(instanceComponentsWithPath, applicationIdMap, baseLayerPrefix, onOperationProgressed)
.ConfigureAwait(true);
var (createdInstanceIds, consumedObjectIds, instanceConversionResults) = _instanceBaker.BakeInstances(
instanceComponentsWithPath,
applicationIdMap,
baseLayerPrefix,
onOperationProgressed
);

bakedObjectIds.RemoveAll(id => consumedObjectIds.Contains(id));
bakedObjectIds.AddRange(createdInstanceIds);
Expand All @@ -181,7 +187,7 @@ private void PreReceiveDeepClean(string baseLayerPrefix)
_materialBaker.PurgeMaterials(baseLayerPrefix);
}

private async Task<List<Entity>> ConvertObject(Base obj, Collection[] layerPath, string baseLayerNamePrefix)
private List<Entity> ConvertObject(Base obj, Collection[] layerPath, string baseLayerNamePrefix)
{
string layerName = _layerBaker.CreateLayerForReceive(layerPath, baseLayerNamePrefix);
var convertedEntities = new List<Entity>();
Expand All @@ -204,7 +210,6 @@ private async Task<List<Entity>> ConvertObject(Base obj, Collection[] layerPath,
}

tr.Commit();
await Task.Delay(10).ConfigureAwait(true);
return convertedEntities;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,10 @@ await Commands
_logger.LogModelCardHandledError(ex);
await Commands.SetModelError(modelCardId, ex).ConfigureAwait(false);
}
finally
{
// otherwise the id of the operation persists on the cancellation manager and triggers 'Operations cancelled because of document swap!' message to UI.
_cancellationManager.CancelOperation(modelCardId);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@ await Commands
_logger.LogModelCardHandledError(ex);
await Commands.SetModelError(modelCardId, ex).ConfigureAwait(false);
}
finally
{
// otherwise the id of the operation persists on the cancellation manager and triggers 'Operations cancelled because of document swap!' message to UI.
_cancellationManager.CancelOperation(modelCardId);
}
}

private async Task<List<Element>> RefreshElementsOnSender(SenderModelCard modelCard)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Rhino;
using Rhino.Commands;
using Rhino.DocObjects;
using Rhino.DocObjects.Tables;
using Speckle.Connectors.Common.Caching;
using Speckle.Connectors.Common.Cancellation;
using Speckle.Connectors.Common.Operations;
Expand Down Expand Up @@ -49,6 +50,7 @@ public sealed class RhinoSendBinding : ISendBinding
/// https://stackoverflow.com/questions/18922985/concurrent-hashsett-in-net-framework
/// </summary>
private ConcurrentDictionary<string, byte> ChangedObjectIds { get; set; } = new();
private ConcurrentDictionary<int, byte> ChangedMaterialIndexes { get; set; } = new();

private UnitSystem PreviousUnitSystem { get; set; }

Expand Down Expand Up @@ -152,6 +154,17 @@ private void SubscribeToRhinoEvents()
}
});

// Catches and stores changed material ids. These are then used in the expiry checks to invalidate all objects that have assigned any of those material ids.
RhinoDoc.MaterialTableEvent += (_, args) =>
_topLevelExceptionHandler.CatchUnhandled(() =>
{
if (args.EventType == MaterialTableEventType.Modified)
{
ChangedMaterialIndexes[args.Index] = 1;
_idleManager.SubscribeToIdle(nameof(RhinoSendBinding), RunExpirationChecks);
}
});

RhinoDoc.ModifyObjectAttributes += (_, e) =>
_topLevelExceptionHandler.CatchUnhandled(() =>
{
Expand Down Expand Up @@ -266,11 +279,30 @@ private async Task RunExpirationChecks()
_logger.LogError("Rhino expiration checks were running without an active doc.");
return;
}
var senders = _store.GetSenders();
string[] objectIdsList = ChangedObjectIds.Keys.ToArray(); // NOTE: could not copy to array happens here
List<string> expiredSenderIds = new();

// Invalidate any objects whose materials have changed
if (!ChangedMaterialIndexes.IsEmpty)
{
var changedMaterialIndexes = ChangedMaterialIndexes.Keys.ToArray();
foreach (var rhinoObject in RhinoDoc.ActiveDoc.Objects)
{
if (changedMaterialIndexes.Contains(rhinoObject.Attributes.MaterialIndex))
{
ChangedObjectIds[rhinoObject.Id.ToString()] = 1;
}
}
}

if (ChangedObjectIds.IsEmpty)
{
return;
}

// Actual model card invalidation
string[] objectIdsList = ChangedObjectIds.Keys.ToArray(); // NOTE: could not copy to array happens here
_sendConversionCache.EvictObjects(objectIdsList);
var senders = _store.GetSenders();
List<string> expiredSenderIds = new();

foreach (SenderModelCard modelCard in senders)
{
Expand All @@ -284,6 +316,7 @@ private async Task RunExpirationChecks()

await Commands.SetModelsExpired(expiredSenderIds).ConfigureAwait(false);
ChangedObjectIds = new();
ChangedMaterialIndexes = new();
}

private async Task InvalidateAllSender()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ ILogger<RhinoInstanceBaker> logger
/// <param name="instanceComponents">Instance definitions and instances that need creating.</param>
/// <param name="applicationIdMap">A dict mapping { original application id -> [resulting application ids post conversion] }</param>
/// <param name="onOperationProgressed"></param>
public async Task<BakeResult> BakeInstances(
public BakeResult BakeInstances(
IReadOnlyCollection<(Collection[] collectionPath, IInstanceComponent obj)> instanceComponents,
Dictionary<string, List<string>> applicationIdMap,
string baseLayerName,
Expand Down Expand Up @@ -153,7 +153,6 @@ instanceOrDefinition is InstanceProxy instanceProxy
}
}

await Task.Yield();
return new(createdObjectIds, consumedObjectIds, conversionResults);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ ISdkActivityFactory activityFactory
}

#pragma warning disable CA1506
public async Task<HostObjectBuilderResult> Build(
public Task<HostObjectBuilderResult> Build(
#pragma warning restore CA1506
Base rootObject,
string projectName,
Expand Down Expand Up @@ -207,9 +207,12 @@ CancellationToken cancellationToken
// 6 - Convert instances
using (var _ = _activityFactory.Start("Converting instances"))
{
var (createdInstanceIds, consumedObjectIds, instanceConversionResults) = await _instanceBaker
.BakeInstances(instanceComponentsWithPath, applicationIdMap, baseLayerName, onOperationProgressed)
.ConfigureAwait(false);
var (createdInstanceIds, consumedObjectIds, instanceConversionResults) = _instanceBaker.BakeInstances(
instanceComponentsWithPath,
applicationIdMap,
baseLayerName,
onOperationProgressed
);

bakedObjectIds.RemoveAll(id => consumedObjectIds.Contains(id)); // remove all objects that have been "consumed"
bakedObjectIds.AddRange(createdInstanceIds); // add instance ids
Expand All @@ -224,7 +227,7 @@ CancellationToken cancellationToken
}

_converterSettings.Current.Document.Views.Redraw();
return new HostObjectBuilderResult(bakedObjectIds, conversionResults);
return Task.FromResult(new HostObjectBuilderResult(bakedObjectIds, conversionResults));
}

private void PreReceiveDeepClean(string baseLayerName)
Expand Down
53 changes: 8 additions & 45 deletions DUI3/Speckle.Connectors.DUI.WebView/DUI3ControlWebView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,57 +26,20 @@ public DUI3ControlWebView(IServiceProvider serviceProvider)

public object BrowserElement => Browser;

// {
// if (!Browser.IsInitialized)
// {
// throw new InvalidOperationException("Failed to execute script, Webview2 is not initialized yet.");
// }
//
// var t = Browser.Dispatcher.Invoke(
// async () =>
// {
// var res = await Browser.ExecuteScriptAsync(script).ConfigureAwait(true);
// await Task.Delay(100).ConfigureAwait(true);
// return res;
// },
// DispatcherPriority.Background
// );
//
// _ = t.IsCompleted;

// bool isAlreadyMainThread = Browser.Dispatcher.CheckAccess();
// if (isAlreadyMainThread)
// {
// Browser.ExecuteScriptAsync(script);
// }
// else
// {
// Browser.Dispatcher.Invoke(
// () =>
// {
// return Browser.ExecuteScriptAsync(script);
// },
// DispatcherPriority.Background
// );
// }
// }

public async Task ExecuteScriptAsyncMethod(string script, CancellationToken cancellationToken)
public Task ExecuteScriptAsyncMethod(string script, CancellationToken cancellationToken)
{
if (!Browser.IsInitialized)
{
throw new InvalidOperationException("Failed to execute script, Webview2 is not initialized yet.");
}

var callbackTask = await Browser
.Dispatcher.InvokeAsync(
async () => await Browser.ExecuteScriptAsync(script).ConfigureAwait(false),
DispatcherPriority.Background,
cancellationToken
)
.Task.ConfigureAwait(false);

_ = await callbackTask.ConfigureAwait(false);
//always invoke even on the main thread because it's better somehow
Browser.Dispatcher.Invoke(
//fire and forget
() => Browser.ExecuteScriptAsync(script),
DispatcherPriority.Background
);
return Task.CompletedTask;
}

private void OnInitialized(object? sender, CoreWebView2InitializationCompletedEventArgs e)
Expand Down
Loading

0 comments on commit 76d9f65

Please sign in to comment.