diff --git a/Assets/SpecklePlayground.unity b/Assets/SpecklePlayground.unity index d8a460c..4cc1441 100644 --- a/Assets/SpecklePlayground.unity +++ b/Assets/SpecklePlayground.unity @@ -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: + k__BackingField: + rid: 3905486442366500889 + k__BackingField: + rid: 3905486442366500890 + 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 + k__BackingField: 50 + k__BackingField: + rid: 3905486442366500889 + - rid: 3905486442366500891 + type: {class: BranchSelection, ns: Speckle.ConnectorUnity.Wrappers.Selection, asm: Speckle.ConnectorUnity.Wrappers} + data: + selectedIndex: 0 + k__BackingField: 100 + k__BackingField: 0 + 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: + k__BackingField: + rid: 3905486442366500885 + k__BackingField: + rid: 3905486442366500886 + k__BackingField: + rid: 3905486442366500887 + 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 + k__BackingField: 50 + k__BackingField: + rid: 3905486442366500885 + - rid: 3905486442366500887 + type: {class: BranchSelection, ns: Speckle.ConnectorUnity.Wrappers.Selection, asm: Speckle.ConnectorUnity.Wrappers} + data: + selectedIndex: 0 + k__BackingField: 100 + k__BackingField: 25 + k__BackingField: + rid: 3905486442366500886 + - rid: 3905486442366500888 + type: {class: CommitSelection, ns: Speckle.ConnectorUnity.Wrappers.Selection, asm: Speckle.ConnectorUnity.Wrappers} + data: + selectedIndex: 0 + 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: + 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: - k__BackingField: - rid: 5855987529328361546 - k__BackingField: - rid: 5855987529328361547 - 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 - k__BackingField: 50 - k__BackingField: - rid: 5855987529328361546 - - rid: 5855987529328361548 - type: {class: BranchSelection, ns: Speckle.ConnectorUnity.Wrappers.Selection, asm: Speckle.ConnectorUnity.Wrappers} - data: - selectedIndex: 0 - k__BackingField: 30 - k__BackingField: 0 - 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: - k__BackingField: - rid: 5855987529328361542 - k__BackingField: - rid: 5855987529328361543 - k__BackingField: - rid: 5855987529328361544 - 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 - k__BackingField: 50 - k__BackingField: - rid: 5855987529328361542 - - rid: 5855987529328361544 - type: {class: BranchSelection, ns: Speckle.ConnectorUnity.Wrappers.Selection, asm: Speckle.ConnectorUnity.Wrappers} - data: - selectedIndex: 0 - k__BackingField: 30 - k__BackingField: 15 - k__BackingField: - rid: 5855987529328361543 - - rid: 5855987529328361545 - type: {class: CommitSelection, ns: Speckle.ConnectorUnity.Wrappers.Selection, asm: Speckle.ConnectorUnity.Wrappers} - data: - selectedIndex: 0 - 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: - 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 diff --git a/Packages/systems.speckle.speckle-unity/Editor/Components/SpeckleReceiverEditor.cs b/Packages/systems.speckle.speckle-unity/Editor/Components/SpeckleReceiverEditor.cs index 8ed4c21..0aa2a52 100644 --- a/Packages/systems.speckle.speckle-unity/Editor/Components/SpeckleReceiverEditor.cs +++ b/Packages/systems.speckle.speckle-unity/Editor/Components/SpeckleReceiverEditor.cs @@ -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 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 ReceiveCommit() + private async Task 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 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 } + } } diff --git a/Packages/systems.speckle.speckle-unity/Editor/Wrappers/SpecklePropertiesEditor.cs b/Packages/systems.speckle.speckle-unity/Editor/Wrappers/SpecklePropertiesEditor.cs index f908f2a..cc929ef 100644 --- a/Packages/systems.speckle.speckle-unity/Editor/Wrappers/SpecklePropertiesEditor.cs +++ b/Packages/systems.speckle.speckle-unity/Editor/Wrappers/SpecklePropertiesEditor.cs @@ -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() diff --git a/Packages/systems.speckle.speckle-unity/Runtime/Components/RecursiveConverter.ToNative.cs b/Packages/systems.speckle.speckle-unity/Runtime/Components/RecursiveConverter.ToNative.cs index 1cf662d..a2b76fc 100644 --- a/Packages/systems.speckle.speckle-unity/Runtime/Components/RecursiveConverter.ToNative.cs +++ b/Packages/systems.speckle.speckle-unity/Runtime/Components/RecursiveConverter.ToNative.cs @@ -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)); } /// @@ -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 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; } diff --git a/Packages/systems.speckle.speckle-unity/Runtime/Components/SpeckleReceiver.cs b/Packages/systems.speckle.speckle-unity/Runtime/Components/SpeckleReceiver.cs index 4ffad78..d5ee72c 100644 --- a/Packages/systems.speckle.speckle-unity/Runtime/Components/SpeckleReceiver.cs +++ b/Packages/systems.speckle.speckle-unity/Runtime/Components/SpeckleReceiver.cs @@ -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; /// /// Receive the selected object, and converts ToNative as children of @@ -65,7 +65,11 @@ namespace Speckle.ConnectorUnity.Components /// function does not throw, instead calls , and calls on complteion public IEnumerator ReceiveAndConvert_Routine(Transform? parent, Predicate? 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(); } /// public async void ReceiveAndConvert_Async(Transform? parent, Predicate? 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(); + } } /// @@ -124,6 +129,12 @@ namespace Speckle.ConnectorUnity.Components /// Awaitable commit object /// /// thrown when selection is incomplete + /// + /// This function is safe to call concurrently from any threads. + /// For this reason we use parameter, rather than use the property + ///
+ /// Additionally, and won't be called. + ///
public async Task 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"); + } + + /// + /// Starts a new receive operation with a + /// + /// already receiving + 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; + } + /// /// Receives the requested using async Task /// @@ -230,7 +273,7 @@ namespace Speckle.ConnectorUnity.Components return requestedObject; } - + /// /// Helper method for using . /// 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"); - } /// /// @@ -334,22 +363,21 @@ namespace Speckle.ConnectorUnity.Components /// /// when , will fetch 360 degree preview image /// Callback function to be called when the web request completes - /// if , , or was - public bool GetPreviewImage(/*bool allAngles,*/ Action callback) + /// The executing or if , , or was + public Coroutine? GetPreviewImage(/*bool allAngles,*/ Action 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 diff --git a/Packages/systems.speckle.speckle-unity/Runtime/Converter/Unity/ConverterUnity.Geometry.cs b/Packages/systems.speckle.speckle-unity/Runtime/Converter/Unity/ConverterUnity.Geometry.cs index 703debc..a885538 100644 --- a/Packages/systems.speckle.speckle-unity/Runtime/Converter/Unity/ConverterUnity.Geometry.cs +++ b/Packages/systems.speckle.speckle-unity/Runtime/Converter/Unity/ConverterUnity.Geometry.cs @@ -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); diff --git a/Packages/systems.speckle.speckle-unity/Runtime/Converter/Unity/ConverterUnity.cs b/Packages/systems.speckle.speckle-unity/Runtime/Converter/Unity/ConverterUnity.cs index 76b4fac..0cc8f38 100644 --- a/Packages/systems.speckle.speckle-unity/Runtime/Converter/Unity/ConverterUnity.cs +++ b/Packages/systems.speckle.speckle-unity/Runtime/Converter/Unity/ConverterUnity.cs @@ -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: diff --git a/Packages/systems.speckle.speckle-unity/Runtime/Wrappers/Selection/BranchSelection.cs b/Packages/systems.speckle.speckle-unity/Runtime/Wrappers/Selection/BranchSelection.cs index 2b70aa2..1eabdfc 100644 --- a/Packages/systems.speckle.speckle-unity/Runtime/Wrappers/Selection/BranchSelection.cs +++ b/Packages/systems.speckle.speckle-unity/Runtime/Wrappers/Selection/BranchSelection.cs @@ -10,9 +10,9 @@ namespace Speckle.ConnectorUnity.Wrappers.Selection public sealed class BranchSelection : OptionSelection { [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; }