Improved Editor Cancellation

This commit is contained in:
Jedd Morgan
2023-06-11 14:39:14 +01:00
parent dc58f6b0b0
commit d9f7895b3f
8 changed files with 397 additions and 353 deletions
+199 -199
View File
@@ -377,6 +377,165 @@ Rigidbody:
m_Interpolate: 0
m_Constraints: 0
m_CollisionDetection: 0
--- !u!1 &50753198
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 50753202}
- component: {fileID: 50753201}
- component: {fileID: 50753200}
- component: {fileID: 50753199}
m_Layer: 0
m_Name: Speckle Connector
m_TagString: Untagged
m_Icon: {fileID: 2800000, guid: ee2ed9d8fff3a1d4db5590491978062e, type: 3}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &50753199
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 50753198}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: b95e704835cc48444b81e33c978f6f7f, type: 3}
m_Name:
m_EditorClassIdentifier:
<Account>k__BackingField:
rid: 3905486442366500889
<Stream>k__BackingField:
rid: 3905486442366500890
<Branch>k__BackingField:
rid: 3905486442366500891
OnBranchSelectionChange:
m_PersistentCalls:
m_Calls: []
OnErrorAction:
m_PersistentCalls:
m_Calls: []
OnSendProgressAction:
m_PersistentCalls:
m_Calls: []
references:
version: 2
RefIds:
- rid: 3905486442366500889
type: {class: AccountSelection, ns: Speckle.ConnectorUnity.Wrappers.Selection, asm: Speckle.ConnectorUnity.Wrappers}
data:
selectedIndex: 0
- rid: 3905486442366500890
type: {class: StreamSelection, ns: Speckle.ConnectorUnity.Wrappers.Selection, asm: Speckle.ConnectorUnity.Wrappers}
data:
selectedIndex: 0
<StreamsLimit>k__BackingField: 50
<AccountSelection>k__BackingField:
rid: 3905486442366500889
- rid: 3905486442366500891
type: {class: BranchSelection, ns: Speckle.ConnectorUnity.Wrappers.Selection, asm: Speckle.ConnectorUnity.Wrappers}
data:
selectedIndex: 0
<BranchesLimit>k__BackingField: 100
<CommitsLimit>k__BackingField: 0
<StreamSelection>k__BackingField:
rid: 3905486442366500890
--- !u!114 &50753200
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 50753198}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0bc895f6cb37b674995dc13b79783c55, type: 3}
m_Name:
m_EditorClassIdentifier:
<Account>k__BackingField:
rid: 3905486442366500885
<Stream>k__BackingField:
rid: 3905486442366500886
<Branch>k__BackingField:
rid: 3905486442366500887
<Commit>k__BackingField:
rid: 3905486442366500888
OnCommitSelectionChange:
m_PersistentCalls:
m_Calls: []
OnReceiveProgressAction:
m_PersistentCalls:
m_Calls: []
OnErrorAction:
m_PersistentCalls:
m_Calls: []
OnTotalChildrenCountKnown:
m_PersistentCalls:
m_Calls: []
OnComplete:
m_PersistentCalls:
m_Calls: []
references:
version: 2
RefIds:
- rid: 3905486442366500885
type: {class: AccountSelection, ns: Speckle.ConnectorUnity.Wrappers.Selection, asm: Speckle.ConnectorUnity.Wrappers}
data:
selectedIndex: 0
- rid: 3905486442366500886
type: {class: StreamSelection, ns: Speckle.ConnectorUnity.Wrappers.Selection, asm: Speckle.ConnectorUnity.Wrappers}
data:
selectedIndex: 0
<StreamsLimit>k__BackingField: 50
<AccountSelection>k__BackingField:
rid: 3905486442366500885
- rid: 3905486442366500887
type: {class: BranchSelection, ns: Speckle.ConnectorUnity.Wrappers.Selection, asm: Speckle.ConnectorUnity.Wrappers}
data:
selectedIndex: 0
<BranchesLimit>k__BackingField: 100
<CommitsLimit>k__BackingField: 25
<StreamSelection>k__BackingField:
rid: 3905486442366500886
- rid: 3905486442366500888
type: {class: CommitSelection, ns: Speckle.ConnectorUnity.Wrappers.Selection, asm: Speckle.ConnectorUnity.Wrappers}
data:
selectedIndex: 0
<BranchSelection>k__BackingField:
rid: 3905486442366500887
--- !u!114 &50753201
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 50753198}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ed6cbf9ce4dca0349997d163ec9bce7e, type: 3}
m_Name:
m_EditorClassIdentifier:
<AssetCache>k__BackingField: {fileID: 1490514812}
--- !u!4 &50753202
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 50753198}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 9
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &73017256
GameObject:
m_ObjectHideFlags: 0
@@ -928,165 +1087,6 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 194696812}
m_CullTransparentMesh: 1
--- !u!1 &218987857
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 218987861}
- component: {fileID: 218987860}
- component: {fileID: 218987859}
- component: {fileID: 218987858}
m_Layer: 0
m_Name: Speckle Connector
m_TagString: Untagged
m_Icon: {fileID: 2800000, guid: ee2ed9d8fff3a1d4db5590491978062e, type: 3}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &218987858
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 218987857}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: b95e704835cc48444b81e33c978f6f7f, type: 3}
m_Name:
m_EditorClassIdentifier:
<Account>k__BackingField:
rid: 5855987529328361546
<Stream>k__BackingField:
rid: 5855987529328361547
<Branch>k__BackingField:
rid: 5855987529328361548
OnBranchSelectionChange:
m_PersistentCalls:
m_Calls: []
OnErrorAction:
m_PersistentCalls:
m_Calls: []
OnSendProgressAction:
m_PersistentCalls:
m_Calls: []
references:
version: 2
RefIds:
- rid: 5855987529328361546
type: {class: AccountSelection, ns: Speckle.ConnectorUnity.Wrappers.Selection, asm: Speckle.ConnectorUnity.Wrappers}
data:
selectedIndex: 0
- rid: 5855987529328361547
type: {class: StreamSelection, ns: Speckle.ConnectorUnity.Wrappers.Selection, asm: Speckle.ConnectorUnity.Wrappers}
data:
selectedIndex: 0
<StreamsLimit>k__BackingField: 50
<AccountSelection>k__BackingField:
rid: 5855987529328361546
- rid: 5855987529328361548
type: {class: BranchSelection, ns: Speckle.ConnectorUnity.Wrappers.Selection, asm: Speckle.ConnectorUnity.Wrappers}
data:
selectedIndex: 0
<BranchesLimit>k__BackingField: 30
<CommitsLimit>k__BackingField: 0
<StreamSelection>k__BackingField:
rid: 5855987529328361547
--- !u!114 &218987859
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 218987857}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0bc895f6cb37b674995dc13b79783c55, type: 3}
m_Name:
m_EditorClassIdentifier:
<Account>k__BackingField:
rid: 5855987529328361542
<Stream>k__BackingField:
rid: 5855987529328361543
<Branch>k__BackingField:
rid: 5855987529328361544
<Commit>k__BackingField:
rid: 5855987529328361545
OnCommitSelectionChange:
m_PersistentCalls:
m_Calls: []
OnReceiveProgressAction:
m_PersistentCalls:
m_Calls: []
OnErrorAction:
m_PersistentCalls:
m_Calls: []
OnTotalChildrenCountKnown:
m_PersistentCalls:
m_Calls: []
OnComplete:
m_PersistentCalls:
m_Calls: []
references:
version: 2
RefIds:
- rid: 5855987529328361542
type: {class: AccountSelection, ns: Speckle.ConnectorUnity.Wrappers.Selection, asm: Speckle.ConnectorUnity.Wrappers}
data:
selectedIndex: 0
- rid: 5855987529328361543
type: {class: StreamSelection, ns: Speckle.ConnectorUnity.Wrappers.Selection, asm: Speckle.ConnectorUnity.Wrappers}
data:
selectedIndex: 0
<StreamsLimit>k__BackingField: 50
<AccountSelection>k__BackingField:
rid: 5855987529328361542
- rid: 5855987529328361544
type: {class: BranchSelection, ns: Speckle.ConnectorUnity.Wrappers.Selection, asm: Speckle.ConnectorUnity.Wrappers}
data:
selectedIndex: 0
<BranchesLimit>k__BackingField: 30
<CommitsLimit>k__BackingField: 15
<StreamSelection>k__BackingField:
rid: 5855987529328361543
- rid: 5855987529328361545
type: {class: CommitSelection, ns: Speckle.ConnectorUnity.Wrappers.Selection, asm: Speckle.ConnectorUnity.Wrappers}
data:
selectedIndex: 0
<BranchSelection>k__BackingField:
rid: 5855987529328361544
--- !u!114 &218987860
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 218987857}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ed6cbf9ce4dca0349997d163ec9bce7e, type: 3}
m_Name:
m_EditorClassIdentifier:
<AssetCache>k__BackingField: {fileID: 1710028308}
--- !u!4 &218987861
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 218987857}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 9
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &234733581
GameObject:
m_ObjectHideFlags: 0
@@ -1135,6 +1135,19 @@ Transform:
m_Father: {fileID: 0}
m_RootOrder: 4
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &236313388
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2a4a29c776298714c88f406ad39c6095, type: 3}
m_Name:
m_EditorClassIdentifier:
matchByName: 1
--- !u!1 &310693430
GameObject:
m_ObjectHideFlags: 0
@@ -1616,18 +1629,6 @@ Rigidbody:
m_Interpolate: 0
m_Constraints: 0
m_CollisionDetection: 0
--- !u!114 &540478226
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: b3354e8208862c341940152f5340d41a, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &641375517
GameObject:
m_ObjectHideFlags: 0
@@ -3176,6 +3177,21 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1465364520}
m_CullTransparentMesh: 1
--- !u!114 &1490514812
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 88d6b4f2f80eaa14f9f07505f7e44ec2, type: 3}
m_Name:
m_EditorClassIdentifier:
nativeCaches:
- {fileID: 236313388}
- {fileID: 1545552959}
--- !u!1 &1506703863
GameObject:
m_ObjectHideFlags: 0
@@ -3341,6 +3357,18 @@ CanvasGroup:
m_Interactable: 1
m_BlocksRaycasts: 1
m_IgnoreParentGroups: 0
--- !u!114 &1545552959
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: b3354e8208862c341940152f5340d41a, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &1587881868
GameObject:
m_ObjectHideFlags: 0
@@ -3599,21 +3627,6 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1707872729}
m_CullTransparentMesh: 1
--- !u!114 &1710028308
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 88d6b4f2f80eaa14f9f07505f7e44ec2, type: 3}
m_Name:
m_EditorClassIdentifier:
nativeCaches:
- {fileID: 1771830985}
- {fileID: 540478226}
--- !u!1 &1729237655
GameObject:
m_ObjectHideFlags: 0
@@ -3726,19 +3739,6 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1762991479}
m_CullTransparentMesh: 1
--- !u!114 &1771830985
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2a4a29c776298714c88f406ad39c6095, type: 3}
m_Name:
m_EditorClassIdentifier:
matchByName: 1
--- !u!1 &1885647142
GameObject:
m_ObjectHideFlags: 0
@@ -7,6 +7,7 @@ using Speckle.ConnectorUnity.Utils;
using Speckle.Core.Api;
using Speckle.Core.Logging;
using Speckle.Core.Models;
using Speckle.Core.Models.GraphTraversal;
using UnityEditor;
using UnityEngine;
@@ -20,35 +21,9 @@ namespace Speckle.ConnectorUnity.Components.Editor
private static bool generateAssets = false;
private bool foldOutStatus = true;
private Texture2D? previewImage;
public void OnEnable()
{
Init();
}
public void Reset()
{
Init();
}
private void Init()
{
var speckleReceiver = (SpeckleReceiver) target;
UpdatePreviewImage();
speckleReceiver.OnCommitSelectionChange.AddListener(_ => UpdatePreviewImage());
UpdateGenerateAssets();
}
private void UpdatePreviewImage()
{
previewImage = null;
((SpeckleReceiver)target).GetPreviewImage(t => previewImage = t);
}
public override async void OnInspectorGUI()
{
var speckleReceiver = (SpeckleReceiver)target;
DrawDefaultInspector();
//Preview image
@@ -78,38 +53,100 @@ namespace Speckle.ConnectorUnity.Components.Editor
{
try
{
Base commitObject = await ReceiveCommit();
int childrenConverted = 0;
float totalChildren = commitObject.totalChildrenCount;
foreach (var e in speckleReceiver.Converter.RecursivelyConvertToNative_Enumerable(
commitObject,
speckleReceiver.transform))
{
Base speckleObject = e.traversalContext.current;
float progress =
childrenConverted++ /
totalChildren; //wont reach 100% because not all objects are convertable
string resultMessage = e.WasSuccessful(out _, out var ex)
? $"Successfully converted {CoreUtils.GenerateObjectName(speckleObject)}"
: $"Failed to convert {CoreUtils.GenerateObjectName(speckleObject)}: {ex}";
EditorUtility.DisplayProgressBar(
"Converting To Native...",
resultMessage,
progress);
}
await ReceiveSelection();
}
catch (OperationCanceledException ex)
{
Debug.Log($"Receive operation cancelled\n{ex}", this);
}
catch (Exception ex)
{
Debug.LogError($"Failed to receive selection {ex}", this);
}
finally
{
EditorUtility.ClearProgressBar();
}
}
}
public void OnEnable()
{
Init();
}
public void Reset()
{
Init();
}
private void Init()
{
var speckleReceiver = (SpeckleReceiver) target;
UpdatePreviewImage();
speckleReceiver.OnCommitSelectionChange.AddListener(_ => UpdatePreviewImage());
UpdateGenerateAssets();
}
private void UpdatePreviewImage()
{
previewImage = null;
((SpeckleReceiver)target).GetPreviewImage(t => previewImage = t);
}
private async Task ReceiveSelection()
{
var speckleReceiver = (SpeckleReceiver)target;
Base commitObject = await ReceiveCommit();
int childrenConverted = 0;
float totalChildren = commitObject.totalChildrenCount;
bool shouldCancel = false;
bool BeforeConvert(TraversalContext context)
{
Base b = context.current;
//NOTE: progress wont reach 100% because not all objects are convertable
float progress = childrenConverted / totalChildren;
shouldCancel = EditorUtility.DisplayCancelableProgressBar(
"Converting To Native...",
$"{b.speckle_type} - {b.id}",
progress);
return true;
}
foreach (var conversionResult in speckleReceiver.Converter.RecursivelyConvertToNative_Enumerable(
commitObject,
speckleReceiver.transform,
BeforeConvert))
{
Base speckleObject = conversionResult.SpeckleObject;
if (conversionResult.WasSuccessful(out _, out var ex))
{
childrenConverted++;
}
else
{
Debug.LogWarning(
$"Failed to convert Speckle object of type {speckleObject.speckle_type}\n{ex}",
this);
}
if (shouldCancel) break;
}
Debug.Log(
shouldCancel
? $"Stopped converting to native. Created {childrenConverted} {nameof(GameObject)}s: Responding to cancel through editor"
: $"Finished converting to native. Created {childrenConverted} {nameof(GameObject)}s ",
this);
}
private void UpdateGenerateAssets()
@@ -118,63 +155,22 @@ namespace Speckle.ConnectorUnity.Components.Editor
speckleReceiver.Converter.AssetCache.nativeCaches = NativeCacheFactory.GetDefaultNativeCacheSetup(generateAssets);
}
[Obsolete]
public async Task<GameObject?> ReceiveAndConvert(SpeckleReceiver speckleReceiver)
{
speckleReceiver.CancellationTokenSource?.Cancel();
if (!speckleReceiver.GetSelection(out _, out _, out Commit? commit, out string? error))
{
Debug.LogWarning($"Not ready to receive: {error}", speckleReceiver);
return null;
}
Base? commitObject = await ReceiveCommit().ConfigureAwait(true);;
if (commitObject == null) return null;
var gameObject = Convert(speckleReceiver, commitObject, commit.id);
Debug.Log($"Successfully received and converted commit: {commit.id}", target);
return gameObject;
}
[Obsolete]
private GameObject Convert(SpeckleReceiver receiver, Base commitObject, string name)
{
//Convert Speckle Objects
int childrenConverted = 0;
float totalChildren = commitObject.totalChildrenCount;
void BeforeConvertCallback(Base b)
{
//TODO: this is an incorrect way of measuring progress, as totalChildren != total convertable children
float progress = childrenConverted++ / totalChildren;
EditorUtility.DisplayProgressBar("Converting To Native...",
$"{b.speckle_type} - {b.id}",
progress);
}
var go = receiver.ConvertToNativeWithCategories(commitObject,
name, BeforeConvertCallback);
go.transform.SetParent(receiver.transform);
return go;
}
private async Task<Base> ReceiveCommit()
private async Task<Base> ReceiveCommit()
{
var speckleReceiver = (SpeckleReceiver)target;
speckleReceiver.BeginOperation();
string serverLogName = speckleReceiver.Account.Client?.ServerUrl ?? "Speckle";
string message = $"Receiving data from {serverLogName}...";
using CancellationTokenSource cancellationSource = new();
EditorUtility.DisplayProgressBar(message, "Making request", 0f);
EditorUtility.DisplayProgressBar(message, "Fetching data", 0f);
var totalObjectCount = 1;
void OnTotalChildrenKnown(int count)
{
totalObjectCount = count;
EditorApplication.delayCall += () => EditorUtility.DisplayProgressBar(message, "Established connection", 0f);
EditorApplication.delayCall += () => EditorUtility.DisplayProgressBar(message, $"Fetching data {0}/{totalObjectCount}", 0f);
}
void OnProgress(ConcurrentDictionary<string, int> dict)
@@ -189,20 +185,17 @@ namespace Speckle.ConnectorUnity.Components.Editor
if (shouldCancel)
{
cancellationSource.Cancel();
speckleReceiver.CancellationTokenSource!.Cancel();
}
};
}
//TODO cancellation but think about disposal!
if (speckleReceiver.IsReceiving) throw new InvalidOperationException("A pending receive operation has already started");
Base commitObject;
try
{
speckleReceiver.OnTotalChildrenCountKnown.AddListener(OnTotalChildrenKnown);
speckleReceiver.OnReceiveProgressAction.AddListener(OnProgress);
commitObject = await speckleReceiver.ReceiveAsync(cancellationSource.Token).ConfigureAwait(false);
commitObject = await speckleReceiver.ReceiveAsync(speckleReceiver.CancellationToken).ConfigureAwait(false);
}
catch(Exception ex)
{
@@ -213,6 +206,7 @@ namespace Speckle.ConnectorUnity.Components.Editor
speckleReceiver.OnTotalChildrenCountKnown.RemoveListener(OnTotalChildrenKnown);
speckleReceiver.OnReceiveProgressAction.RemoveListener(OnProgress);
EditorApplication.delayCall += EditorUtility.ClearProgressBar;
speckleReceiver.FinishOperation();
}
return commitObject;
@@ -237,5 +231,6 @@ namespace Speckle.ConnectorUnity.Components.Editor
EditorGUIUtility.SetIconForObject(go, icon);
#endif
}
}
}
@@ -34,12 +34,16 @@ namespace Speckle.ConnectorUnity.Wrappers.Editor
.Where(x => x.FullName != null)
.Select(x => x.FullName!.Replace('.', '/'));
var manualTypes = new [] { typeof(Base), typeof(Collection)};
var manualStrings = new []{ nameof(Base), nameof(Collection)};
//Manually Add `Base`
SpeckleTypeOptions = options.Concat(manualTypes).ToArray();
SpeckleTypeOptionStrings = strings.Concat(manualStrings).ToArray();
SpeckleTypeOptionStrings = strings.Append(nameof(Base)).ToArray();
SpeckleTypeOptions = options.Append(typeof(Base)).ToArray();
Debug.Assert(SpeckleTypeOptions.Length == SpeckleTypeOptionStrings.Length);
}
private static GUILayoutOption[] propLayoutOptions = { GUILayout.ExpandWidth(true) };
public override void OnInspectorGUI()
@@ -4,7 +4,6 @@ using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Speckle.ConnectorUnity.NativeCache;
using Speckle.ConnectorUnity.Utils;
using Speckle.Core.Logging;
using Speckle.Core.Models;
@@ -43,7 +42,7 @@ namespace Speckle.ConnectorUnity.Components
public ConversionResult(TraversalContext traversalContext, [NotNull] GameObject? converted)
: this(traversalContext, converted, null)
{
if (converted == null) throw new ArgumentNullException(nameof(converted));
if (converted is null) throw new ArgumentNullException(nameof(converted));
}
/// <summary>
@@ -57,7 +56,7 @@ namespace Speckle.ConnectorUnity.Components
GameObject? converted = null)
: this(traversalContext, converted, exception)
{
if (exception == null) throw new ArgumentNullException(nameof(exception));
if (exception is null) throw new ArgumentNullException(nameof(exception));
}
private ConversionResult(TraversalContext traversalContext, GameObject? converted, Exception? exception)
@@ -137,12 +136,6 @@ namespace Speckle.ConnectorUnity.Components
Dictionary<Base, GameObject?> created = new();
foreach (var conversionResult in ConvertTree(objectsToConvert, parent, created))
{
Base speckleObject = conversionResult.SpeckleObject;
if (!conversionResult.WasSuccessful(out var converted, out var ex))
{
Debug.LogWarning($"Failed to convert Speckle object of type {speckleObject.speckle_type}\n{ex}",this);
}
yield return conversionResult;
}
@@ -55,7 +55,7 @@ namespace Speckle.ConnectorUnity.Components
#nullable enable
protected internal CancellationTokenSource? CancellationTokenSource { get; private set; }
protected internal CancellationToken CancellationToken => CancellationTokenSource?.Token ?? default;
public bool IsReceiving => CancellationTokenSource != null;
public bool IsReceiving => CancellationTokenSource != null;
/// <summary>
/// Receive the selected <see cref="Commit"/> object, and converts ToNative as children of <paramref name="parent"/>
@@ -65,7 +65,11 @@ namespace Speckle.ConnectorUnity.Components
/// <remarks>function does not throw, instead calls <see cref="OnErrorAction"/>, and calls <see cref="OnComplete"/> on complteion</remarks>
public IEnumerator ReceiveAndConvert_Routine(Transform? parent, Predicate<TraversalContext>? predicate = null)
{
if (IsReceiving) OnErrorAction.Invoke("Failed to receive", new InvalidOperationException("A pending receive operation has already started"));
if (IsReceiving)
{
OnErrorAction.Invoke("Failed to receive", new InvalidOperationException("A pending receive operation has already started"));
yield break;
}
CancellationTokenSource?.Dispose();
CancellationTokenSource = new();
@@ -83,6 +87,7 @@ namespace Speckle.ConnectorUnity.Components
if (receiveOperation.IsFaulted)
{
OnErrorAction.Invoke("Failed to receive", receiveOperation.Exception);
FinishOperation();
yield break;
}
@@ -94,28 +99,28 @@ namespace Speckle.ConnectorUnity.Components
}
OnComplete.Invoke(parent);
FinishOperation();
}
/// <inheritdoc cref="ReceiveAndConvert_Routine"/>
public async void ReceiveAndConvert_Async(Transform? parent, Predicate<TraversalContext>? predicate = null)
{
if (IsReceiving) OnErrorAction.Invoke("Failed to receive", new InvalidOperationException("A pending receive operation has already started"));
CancellationTokenSource?.Dispose();
CancellationTokenSource = new();
try
{
BeginOperation();
Base commitObject = await ReceiveAsync(CancellationToken).ConfigureAwait(true);
Converter.RecursivelyConvertToNative_Sync(commitObject, parent, predicate);
OnComplete.Invoke(parent);
}
catch(Exception ex)
catch (Exception ex)
{
OnErrorAction.Invoke("Failed to receive", ex);
}
OnComplete.Invoke(parent);
finally
{
FinishOperation();
}
}
/// <summary>
@@ -124,6 +129,12 @@ namespace Speckle.ConnectorUnity.Components
/// <returns>Awaitable commit object</returns>
/// <param name="token"></param>
/// <exception cref="SpeckleException">thrown when selection is incomplete</exception>
/// <remarks>
/// This function is safe to call concurrently from any threads.
/// For this reason we use <paramref name="token"/> parameter, rather than use the <see cref="CancellationToken"/> property
/// <br/>
/// Additionally, <see cref="OnComplete"/> and <see cref="OnErrorAction"/> won't be called.
/// </remarks>
public async Task<Base> ReceiveAsync(CancellationToken token)
{
token.ThrowIfCancellationRequested();
@@ -145,6 +156,38 @@ namespace Speckle.ConnectorUnity.Components
return result;
}
public void ValidateSelection(out Client client, out Stream stream, out Commit commit)
{
Client? selectedClient = Account.Client;
client = selectedClient ?? throw new InvalidOperationException("Invalid account selection");
Stream? selectedStream = Stream.Selected;
stream = selectedStream ?? throw new InvalidOperationException("Invalid stream selection");
Commit? selectedCommit = Commit.Selected;
commit = selectedCommit ?? throw new InvalidOperationException("Invalid commit selection");
}
/// <summary>
/// Starts a new receive operation with a <see cref="CancellationToken"/>
/// </summary>
/// <exception cref="InvalidOperationException">already receiving</exception>
protected internal void BeginOperation()
{
if (IsReceiving) throw new InvalidOperationException("A pending receive operation has already started");
CancellationTokenSource?.Dispose();
CancellationTokenSource = new();
}
protected internal void FinishOperation()
{
if (!IsReceiving) throw new InvalidOperationException("No pending operations to finish");
CancellationTokenSource!.Dispose();
CancellationTokenSource = null;
}
/// <summary>
/// Receives the requested <see cref="objectId"/> using async Task
/// </summary>
@@ -230,7 +273,7 @@ namespace Speckle.ConnectorUnity.Components
return requestedObject;
}
/// <summary>
/// Helper method for using <see cref="RecursiveConverter"/>.
/// Creates blank GameObjects for each property/category of the root object.
@@ -272,20 +315,6 @@ namespace Speckle.ConnectorUnity.Components
return rootObject;
}
public void ValidateSelection(out Client client, out Stream stream, out Commit commit)
{
Client? selectedClient = Account.Client;
client = selectedClient ?? throw new InvalidOperationException("Invalid account selection");
Stream? selectedStream = Stream.Selected;
stream = selectedStream ?? throw new InvalidOperationException("Invalid stream selection");
Commit? selectedCommit = Commit.Selected;
commit = selectedCommit ?? throw new InvalidOperationException("Invalid commit selection");
}
/// <summary>
///
@@ -334,22 +363,21 @@ namespace Speckle.ConnectorUnity.Components
/// </summary>
/// <param name="allAngles">when <see langword="true"/>, will fetch 360 degree preview image</param>
/// <param name="callback">Callback function to be called when the web request completes</param>
/// <returns><see langword="false"/> if <see cref="Account"/>, <see cref="Stream"/>, or <see cref="Commit"/> was <see langword="null"/></returns>
public bool GetPreviewImage(/*bool allAngles,*/ Action<Texture2D?> callback)
/// <returns>The executing <see cref="Coroutine"/> or <see langword="null"/> if <see cref="Account"/>, <see cref="Stream"/>, or <see cref="Commit"/> was <see langword="null"/></returns>
public Coroutine? GetPreviewImage(/*bool allAngles,*/ Action<Texture2D?> callback)
{
Account? account = Account.Selected;
if (account == null) return false;
if (account == null) return null;
string? streamId = Stream.Selected?.id;
if (streamId == null) return false;
if (streamId == null) return null;
string? commitId = Commit.Selected?.id;
if (commitId == null) return false;
if (commitId == null) return null;
string angles = /*allAngles ? "all" :*/ "";
string url = $"{account.serverInfo.url}/preview/{streamId}/commits/{commitId}/{angles}";
string authToken = account.token;
StartCoroutine(Utils.Utils.GetImageRoutine(url, authToken, callback));
return true;
return StartCoroutine(Utils.Utils.GetImageRoutine(url, authToken, callback));
}
#if UNITY_EDITOR
@@ -235,8 +235,12 @@ namespace Objects.Converter.Unity
var geometry = instance.definition is BlockDefinition b
? b.geometry
: GraphTraversal.TraverseMember(instance.definition["elements"]);
: GraphTraversal.TraverseMember(new[]
{
instance.definition["elements"] ?? instance.definition["@elements"],
instance.definition["displayValue"] ?? instance.definition["@displayValue"],
});
foreach (Base geo in geometry)
{
if (geo is SMesh m) meshes.Add(m);
@@ -5,6 +5,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Objects.BuiltElements;
using Objects.Organization;
using Objects.Other;
using Speckle.ConnectorUnity.Utils;
using Speckle.ConnectorUnity.NativeCache;
@@ -113,6 +114,8 @@ namespace Objects.Converter.Unity
return MeshToNative(o);
case Instance o:
return InstanceToNative(o);
case Collection c:
return CollectionToNative(c);
default:
//Object is not a raw geometry, convert it as display value element
@@ -183,6 +186,19 @@ namespace Objects.Converter.Unity
}
}
public GameObject CollectionToNative(Collection collection)
{
var name = collection.name ?? $"{collection.collectionType} -- {collection.applicationId ?? collection.id}";
var go = new GameObject(name);
AttachSpeckleProperties(go, collection.GetType(), GetProperties(collection));
if (name == "Rooms")
{
go.SetActive(false);
}
return go;
}
public bool CanConvertToNative(Base @object)
{
switch (@object)
@@ -195,10 +211,14 @@ namespace Objects.Converter.Unity
// return true;
// case Curve _:
// return true;
// case View3D _:
// case View2D:
// return false;
// case View _:
// return true;
case View2D:
return false;
case Model:
return false; //This allows us to traverse older commits pre-collections
case Collection:
return true;
case Mesh:
return true;
case Instance:
@@ -10,9 +10,9 @@ namespace Speckle.ConnectorUnity.Wrappers.Selection
public sealed class BranchSelection : OptionSelection<Branch>
{
[field: SerializeField, Range(1,100), Tooltip("Number of branches to request")]
public int BranchesLimit { get; set; } = 30;
public int BranchesLimit { get; set; } = 100;
[field: SerializeField, Range(1,100), Tooltip("Number of commits to request")]
public int CommitsLimit { get; set; } = 15;
public int CommitsLimit { get; set; } = 25;
[field: SerializeReference]
public StreamSelection StreamSelection { get; private set; }