diff --git a/Assets/Tests/PlayMode/ConvertToNativeTests.cs b/Assets/Tests/PlayMode/ConvertToNativeTests.cs index 0d5fc44..1a92fe7 100644 --- a/Assets/Tests/PlayMode/ConvertToNativeTests.cs +++ b/Assets/Tests/PlayMode/ConvertToNativeTests.cs @@ -1,5 +1,3 @@ - -using System.Collections; using System.Collections.Generic; using System.Threading.Tasks; using NUnit.Framework; @@ -9,7 +7,6 @@ using Speckle.Core.Api; using Speckle.Core.Models; using UnityEngine; -using UnityEngine.TestTools; namespace Speckle.ConnectorUnity.Tests { @@ -25,7 +22,7 @@ private static Base Receive(string stream) { return Task.Run(async () => await Helpers.Receive(stream)).Result; } - + [Test, TestCaseSource(nameof(TestCases))] public void ToNative_Passes(string stream) { @@ -37,14 +34,13 @@ public void ToNative_Passes(string stream) Assert.That(results, HasSomeComponent()); } - private static Constraint HasSomeComponent() where T : Component + private static Constraint HasSomeComponent() + where T : Component { - return Has.Some.Matches( - x => - { - return x.WasSuccessful(out var success, out _) - && success.GetComponent(); - }); + return Has.Some.Matches(x => + { + return x.WasSuccessful(out var success, out _) && success.GetComponent(); + }); } } } diff --git a/Packages/systems.speckle.speckle-unity/Editor/Components/SpeckleReceiverEditor.cs b/Packages/systems.speckle.speckle-unity/Editor/Components/SpeckleReceiverEditor.cs index fb072ca..be631c8 100644 --- a/Packages/systems.speckle.speckle-unity/Editor/Components/SpeckleReceiverEditor.cs +++ b/Packages/systems.speckle.speckle-unity/Editor/Components/SpeckleReceiverEditor.cs @@ -13,7 +13,7 @@ namespace Speckle.ConnectorUnity.Components.Editor [CustomEditor(typeof(SpeckleReceiver))] public class SpeckleReceiverEditor : UnityEditor.Editor { - private static bool _generateAssets = false; + private static bool _generateAssets; private bool _foldOutStatus = true; private Texture2D? _previewImage; diff --git a/Packages/systems.speckle.speckle-unity/Editor/NativeCache/AssetDBNativeCache.cs b/Packages/systems.speckle.speckle-unity/Editor/NativeCache/AssetDBNativeCache.cs index 39c0ab4..5dddeb3 100644 --- a/Packages/systems.speckle.speckle-unity/Editor/NativeCache/AssetDBNativeCache.cs +++ b/Packages/systems.speckle.speckle-unity/Editor/NativeCache/AssetDBNativeCache.cs @@ -79,12 +79,6 @@ private bool WriteObject(Base speckleObject, Object nativeObject) return _readCache.TrySaveObject(speckleObject, nativeObject); } - public override void BeginWrite() - { - base.BeginWrite(); - //AssetDatabase.StartAssetEditing(); - } - public override void FinishWrite() { if (!isWriting) diff --git a/Packages/systems.speckle.speckle-unity/Editor/Wrappers/Selection/StreamSelectionEditor.cs b/Packages/systems.speckle.speckle-unity/Editor/Wrappers/Selection/StreamSelectionEditor.cs index 30d2975..84ebc32 100644 --- a/Packages/systems.speckle.speckle-unity/Editor/Wrappers/Selection/StreamSelectionEditor.cs +++ b/Packages/systems.speckle.speckle-unity/Editor/Wrappers/Selection/StreamSelectionEditor.cs @@ -1,6 +1,7 @@ #nullable enable using System; using System.Collections.Generic; +using System.Globalization; using Speckle.Core.Api; using Speckle.Core.Credentials; using UnityEditor; @@ -49,8 +50,8 @@ public StreamSelectionDrawer() ("Description", s => s.description), ("Is Public", s => s.isPublic.ToString()), ("Role", s => s.role), - ("Created at", s => s.createdAt.ToString()), - ("Updated at", s => s.updatedAt.ToString()), + ("Created at", s => s.createdAt.ToString(CultureInfo.InvariantCulture)), + ("Updated at", s => s.updatedAt.ToString(CultureInfo.InvariantCulture)), }; } } @@ -70,7 +71,11 @@ public BranchSelectionDrawer() $"<{nameof(BranchSelection.CommitsLimit)}>k__BackingField", }; - details = new (string, Func)[] { ("Description", s => s.description), }; + details = new (string, Func)[] + { + ("Model Id", s => s.id), + ("Description", s => s.description), + }; } } @@ -85,7 +90,7 @@ public CommitSelectionDrawer() { ("Commit Id", s => s.id), ("Author Name", s => s.authorName), - ("Created At", s => s.createdAt.ToString()), + ("Created At", s => s.createdAt.ToString(CultureInfo.InvariantCulture)), ("Source Application", s => s.sourceApplication), ("Reference Object Id", s => s.referencedObject), }; @@ -108,9 +113,9 @@ public abstract class OptionSelectionDrawer : PropertyDrawer protected (string, Func)[] details = { }; - private string[] GetFormattedOptions(TOption[] options) + private string[] GetFormattedOptions(IReadOnlyList options) { - int optionsCount = options.Length; + int optionsCount = options.Count; string[] choices = new string[optionsCount]; for (int i = 0; i < optionsCount; i++) { @@ -182,10 +187,10 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten var provider = ScriptableObject.CreateInstance(); provider.Title = typeof(TOption).Name; provider.listItems = GetFormattedOptions(t.Options); - ; + provider.onSetIndexCallback = o => { - t.SelectedIndex = o; + t.Selected = t.Options[o]; }; SearchWindow.Open(new SearchWindowContext(windowPos), provider); } @@ -260,7 +265,7 @@ public sealed class StringListSearchProvider : ScriptableObject, ISearchWindowPr public List CreateSearchTree(SearchWindowContext context) { List searchList = - new(listItems.Length + 1) { new SearchTreeGroupEntry(new GUIContent(Title), 0) }; + new(listItems.Length + 1) { new SearchTreeGroupEntry(new GUIContent(Title)) }; for (int i = 0; i < listItems.Length; i++) { @@ -275,9 +280,9 @@ public List CreateSearchTree(SearchWindowContext context) return searchList; } - public bool OnSelectEntry(SearchTreeEntry SearchTreeEntry, SearchWindowContext context) + public bool OnSelectEntry(SearchTreeEntry searchTreeEntry, SearchWindowContext context) { - onSetIndexCallback?.Invoke((int)SearchTreeEntry.userData); + onSetIndexCallback?.Invoke((int)searchTreeEntry.userData); return true; } diff --git a/Packages/systems.speckle.speckle-unity/Editor/Wrappers/SpecklePropertiesEditor.cs b/Packages/systems.speckle.speckle-unity/Editor/Wrappers/SpecklePropertiesEditor.cs index cc929ef..c9d7f3f 100644 --- a/Packages/systems.speckle.speckle-unity/Editor/Wrappers/SpecklePropertiesEditor.cs +++ b/Packages/systems.speckle.speckle-unity/Editor/Wrappers/SpecklePropertiesEditor.cs @@ -18,25 +18,26 @@ public class SpecklePropertiesEditor : UnityEditor.Editor { private static readonly string[] SpeckleTypeOptionStrings; private static readonly Type[] SpeckleTypeOptions; - + private static HashSet ArrayFoldoutState = new(); private static bool instancePropFoldoutState = true; private static bool dynamicPropFoldoutState = true; - private static bool isEditMode = false; + private static bool isEditMode; static SpecklePropertiesEditor() { var options = typeof(Mesh).Assembly .GetTypes() - .Where(x => x.IsSubclassOf(typeof(Base)) && !x.IsAbstract).ToList(); + .Where(x => x.IsSubclassOf(typeof(Base)) && !x.IsAbstract) + .ToList(); var strings = options .Where(x => x.FullName != null) .Select(x => x.FullName!.Replace('.', '/')); - - var manualTypes = new [] { typeof(Base), typeof(Collection)}; - var manualStrings = new []{ nameof(Base), nameof(Collection)}; - + + 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(); @@ -45,64 +46,82 @@ static SpecklePropertiesEditor() } private static GUILayoutOption[] propLayoutOptions = { GUILayout.ExpandWidth(true) }; - + public override void OnInspectorGUI() { SpeckleProperties properties = (SpeckleProperties)target; //Edit Mode - isEditMode = EditorGUILayout.ToggleLeft("Enable Inspector Edit Mode (experimental)", isEditMode); + isEditMode = EditorGUILayout.ToggleLeft( + "Enable Inspector Edit Mode (experimental)", + isEditMode + ); if (isEditMode) { GUILayout.Label( "Modifying properties through the inspector is experimental and can lead to invalid objects, proceed at your own risk!", - EditorStyles.helpBox); + EditorStyles.helpBox + ); GUILayout.Space(10); } GUI.enabled = isEditMode; - + // SpeckleType - GUILayout.Label("Speckle Type: ", EditorStyles.boldLabel ); - + GUILayout.Label("Speckle Type: ", EditorStyles.boldLabel); + var oldIndex = Array.IndexOf(SpeckleTypeOptions, properties.SpeckleType); - var speckleTypeSelectedIndex = EditorGUILayout.Popup(oldIndex, SpeckleTypeOptionStrings); - - if(oldIndex != speckleTypeSelectedIndex && speckleTypeSelectedIndex >= 0) + var speckleTypeSelectedIndex = EditorGUILayout.Popup( + oldIndex, + SpeckleTypeOptionStrings + ); + + if (oldIndex != speckleTypeSelectedIndex && speckleTypeSelectedIndex >= 0) { properties.SpeckleType = SpeckleTypeOptions[speckleTypeSelectedIndex]; } - + // Instance Properties - var InstancePropertyNames = DynamicBase.GetInstanceMembersNames(properties.SpeckleType); - instancePropFoldoutState = EditorGUILayout.Foldout(instancePropFoldoutState, "Instance Properties: ", EditorStyles.foldoutHeader); + var instancePropertyNames = + (IReadOnlyCollection) + DynamicBase.GetInstanceMembersNames(properties.SpeckleType); + instancePropFoldoutState = EditorGUILayout.Foldout( + instancePropFoldoutState, + "Instance Properties: ", + EditorStyles.foldoutHeader + ); if (instancePropFoldoutState) { - foreach (var propName in InstancePropertyNames) + foreach (var propName in instancePropertyNames) { - if (!properties.Data.TryGetValue(propName, out object? existingValue)) continue; - + if (!properties.Data.TryGetValue(propName, out object? existingValue)) + continue; + var newValue = CreateField(existingValue, propName, propLayoutOptions); - if(newValue != existingValue) + if (newValue != existingValue) properties.Data[propName] = newValue; - } } - + GUILayout.Space(10); - dynamicPropFoldoutState = EditorGUILayout.Foldout(dynamicPropFoldoutState, "Dynamic Properties:", EditorStyles.foldoutHeader); + dynamicPropFoldoutState = EditorGUILayout.Foldout( + dynamicPropFoldoutState, + "Dynamic Properties:", + EditorStyles.foldoutHeader + ); if (dynamicPropFoldoutState) { - var ignoreSet = InstancePropertyNames.ToImmutableHashSet(); + var ignoreSet = instancePropertyNames.ToImmutableHashSet(); foreach (var kvp in properties.Data) { - if (ignoreSet.Contains(kvp.Key)) continue; - + if (ignoreSet.Contains(kvp.Key)) + continue; + var existingValue = kvp.Value; var newValue = CreateField(existingValue, kvp.Key, propLayoutOptions); - if(newValue != existingValue) + if (newValue != existingValue) properties.Data[kvp.Key] = newValue; - + GUILayout.Space(10); } } @@ -118,13 +137,18 @@ public override void OnInspectorGUI() _ => CreateFieldPrimitive(v, propName, options), }; - if (ret != null) return ret; - - EditorGUILayout.TextField(propName, v == null? "NULL" : v.ToString()); + if (ret != null) + return ret; + + EditorGUILayout.TextField(propName, v == null ? "NULL" : v.ToString()); return v; } - - private static object? CreateFieldPrimitive(object? v, string propName, params GUILayoutOption[] options) + + private static object? CreateFieldPrimitive( + object? v, + string propName, + params GUILayoutOption[] options + ) { return v switch { @@ -135,11 +159,19 @@ public override void OnInspectorGUI() string s => EditorGUILayout.TextField(propName, s, options), bool b => EditorGUILayout.Toggle(propName, b, options), Enum e => EditorGUILayout.EnumPopup(propName, e, options), - Point p => PointToVector3(EditorGUILayout.Vector3Field(propName, new Vector3((float)p.x, (float)p.z, (float)p.z), options), p), + Point p + => PointToVector3( + EditorGUILayout.Vector3Field( + propName, + new Vector3((float)p.x, (float)p.z, (float)p.z), + options + ), + p + ), _ => null, }; } - + private static Point PointToVector3(Vector3 vector, Point p) { p.x = vector.x; @@ -147,10 +179,13 @@ private static Point PointToVector3(Vector3 vector, Point p) p.z = vector.z; return p; } - + private IList ArrayField(string propName, IList list, params GUILayoutOption[] options) { - bool isExpanded = EditorGUILayout.Foldout(ArrayFoldoutState.Contains(propName), propName); + bool isExpanded = EditorGUILayout.Foldout( + ArrayFoldoutState.Contains(propName), + propName + ); if (isExpanded) { ArrayFoldoutState.Add(propName); @@ -158,10 +193,13 @@ private IList ArrayField(string propName, IList list, params GUILayoutOption[] o { object? item = list[i]; var r = CreateFieldPrimitive(item, i.ToString(), options); - + if (r == null) { - EditorGUILayout.TextField(i.ToString(), item == null? "NULL" : item.ToString()); + EditorGUILayout.TextField( + i.ToString(), + item == null ? "NULL" : item.ToString() + ); continue; } //Update list item @@ -175,6 +213,5 @@ private IList ArrayField(string propName, IList list, params GUILayoutOption[] o return list; } - } } diff --git a/Packages/systems.speckle.speckle-unity/Runtime/Components/SpeckleReceiver.cs b/Packages/systems.speckle.speckle-unity/Runtime/Components/SpeckleReceiver.cs index b52e3ea..fef544f 100644 --- a/Packages/systems.speckle.speckle-unity/Runtime/Components/SpeckleReceiver.cs +++ b/Packages/systems.speckle.speckle-unity/Runtime/Components/SpeckleReceiver.cs @@ -514,7 +514,7 @@ protected void Initialise(bool forceRefresh = false) Branch.Initialise(); Commit.Initialise(); Commit.OnSelectionChange = () => OnCommitSelectionChange?.Invoke(Commit.Selected); - if (Account.Options is not { Length: > 0 } || forceRefresh) + if (Account.Options is not { Count: > 0 } || forceRefresh) Account.RefreshOptions(); } @@ -540,7 +540,7 @@ public void OnAfterDeserialize() #region Deprecated members - [Obsolete("use " + nameof(ReceiveAndConvertRoutine), true)] + [Obsolete("use " + nameof(ReceiveAndConvert_Routine), true)] public IEnumerator ReceiveAndConvertRoutine( SpeckleReceiver speckleReceiver, string rootObjectName, diff --git a/Packages/systems.speckle.speckle-unity/Runtime/Components/SpeckleSender.cs b/Packages/systems.speckle.speckle-unity/Runtime/Components/SpeckleSender.cs index c654147..cb74d88 100644 --- a/Packages/systems.speckle.speckle-unity/Runtime/Components/SpeckleSender.cs +++ b/Packages/systems.speckle.speckle-unity/Runtime/Components/SpeckleSender.cs @@ -230,7 +230,7 @@ protected void Initialise(bool forceRefresh = false) Stream.Initialise(); Branch.Initialise(); Branch.OnSelectionChange = () => OnBranchSelectionChange?.Invoke(Branch.Selected); - if (Account.Options is not { Length: > 0 } || forceRefresh) + if (Account.Options is not { Count: > 0 } || forceRefresh) Account.RefreshOptions(); } 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 0105c13..1dc5ccc 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 @@ -47,21 +47,27 @@ public Vector3 VectorByCoordinates(double x, double y, double z, string units) public Vector3 VectorFromPoint(Point p) => VectorByCoordinates(p.x, p.y, p.z, p.units); - /// - /// - /// - /// + /// flat list of x,y,z values + /// /// - public Vector3[] ArrayToPoints(IList arr, string units) + /// Length of must be a multiple of 3 + public Vector3[] ArrayToPoints(IReadOnlyList arr, string units) { if (arr.Count % 3 != 0) - throw new Exception("Array malformed: length not a multiple of 3"); + { + throw new ArgumentException( + "Array malformed: length not a multiple of 3", + nameof(arr) + ); + } Vector3[] points = new Vector3[arr.Count / 3]; - var f = GetConversionFactor(units); + double f = GetConversionFactor(units); for (int i = 2, k = 0; i < arr.Count; i += 3) + { points[k++] = VectorByCoordinates(arr[i - 2], arr[i - 1], arr[i], f); + } return points; } @@ -70,13 +76,7 @@ public Vector3[] ArrayToPoints(IList arr, string units) #region ToSpeckle - //TODO: more of these - - /// - /// - /// - /// - /// + [Obsolete("", true)] public virtual Point PointToSpeckle(Vector3 p) { //switch y and z @@ -117,7 +117,7 @@ public virtual Point PointToSpeckle(Vector3 p) { Vector3 newPt = VectorByCoordinates(point.x, point.y, point.z, point.units); - var go = NewPointBasedGameObject(new Vector3[] { newPt, newPt }, point.speckle_type); + var go = NewPointBasedGameObject(new[] { newPt, newPt }, point.speckle_type); return go; } @@ -352,30 +352,30 @@ private static GameObject InstantiateCopy(GameObject existingGo) public Matrix4x4 TransformToNativeMatrix(STransform speckleTransform) { var sf = GetConversionFactor(speckleTransform.units); - var smatrix = speckleTransform.matrix; + var sMatrix = speckleTransform.matrix; return new Matrix4x4 { // Left (X -> X) - [0, 0] = (float)smatrix.M11, - [2, 0] = (float)smatrix.M21, - [1, 0] = (float)smatrix.M31, - [3, 0] = (float)smatrix.M41, + [0, 0] = (float)sMatrix.M11, + [2, 0] = (float)sMatrix.M21, + [1, 0] = (float)sMatrix.M31, + [3, 0] = (float)sMatrix.M41, //Up (Z -> Y) - [0, 2] = (float)smatrix.M12, - [2, 2] = (float)smatrix.M22, - [1, 2] = (float)smatrix.M32, - [3, 2] = (float)smatrix.M42, + [0, 2] = (float)sMatrix.M12, + [2, 2] = (float)sMatrix.M22, + [1, 2] = (float)sMatrix.M32, + [3, 2] = (float)sMatrix.M42, //Forwards (Y -> Z) - [0, 1] = (float)smatrix.M13, - [2, 1] = (float)smatrix.M23, - [1, 1] = (float)smatrix.M33, - [3, 1] = (float)smatrix.M43, + [0, 1] = (float)sMatrix.M13, + [2, 1] = (float)sMatrix.M23, + [1, 1] = (float)sMatrix.M33, + [3, 1] = (float)sMatrix.M43, //Translation - [0, 3] = (float)(smatrix.M14 * sf), - [2, 3] = (float)(smatrix.M24 * sf), - [1, 3] = (float)(smatrix.M34 * sf), - [3, 3] = (float)smatrix.M44, + [0, 3] = (float)(sMatrix.M14 * sf), + [2, 3] = (float)(sMatrix.M24 * sf), + [1, 3] = (float)(sMatrix.M34 * sf), + [3, 3] = (float)sMatrix.M44, }; } diff --git a/Packages/systems.speckle.speckle-unity/Runtime/NativeCache/AbstractNativeCache.cs b/Packages/systems.speckle.speckle-unity/Runtime/NativeCache/AbstractNativeCache.cs index 31a6369..28951e3 100644 --- a/Packages/systems.speckle.speckle-unity/Runtime/NativeCache/AbstractNativeCache.cs +++ b/Packages/systems.speckle.speckle-unity/Runtime/NativeCache/AbstractNativeCache.cs @@ -14,7 +14,7 @@ namespace Speckle.ConnectorUnity.NativeCache [ExecuteAlways] public abstract class AbstractNativeCache : ScriptableObject { - protected bool isWriting = false; + protected bool isWriting; public abstract bool TryGetObject( Base speckleObject, [NotNullWhen(true)] out T? nativeObject diff --git a/Packages/systems.speckle.speckle-unity/Runtime/Streams.cs b/Packages/systems.speckle.speckle-unity/Runtime/Streams.cs index 1ef6660..be95ae6 100644 --- a/Packages/systems.speckle.speckle-unity/Runtime/Streams.cs +++ b/Packages/systems.speckle.speckle-unity/Runtime/Streams.cs @@ -1,10 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System.Collections.Generic; using System.Threading.Tasks; using Speckle.Core.Api; using Speckle.Core.Credentials; -using Speckle.Core.Logging; namespace Speckle.ConnectorUnity { 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 65c54cd..ffe61cd 100644 --- a/Packages/systems.speckle.speckle-unity/Runtime/Wrappers/Selection/BranchSelection.cs +++ b/Packages/systems.speckle.speckle-unity/Runtime/Wrappers/Selection/BranchSelection.cs @@ -9,8 +9,12 @@ namespace Speckle.ConnectorUnity.Wrappers.Selection [Serializable] public sealed class BranchSelection : OptionSelection { - [field: SerializeField, Range(1, 100), Tooltip("Number of branches to request")] - public int BranchesLimit { get; set; } = 100; + [field: + SerializeField, + Range(1, ServerLimits.BRANCH_GET_LIMIT), + Tooltip("Number of branches to request") + ] + public int BranchesLimit { get; set; } = ServerLimits.OLD_BRANCH_GET_LIMIT; [field: SerializeField, Range(1, 100), Tooltip("Number of commits to request")] public int CommitsLimit { get; set; } = 25; @@ -30,14 +34,14 @@ public void Initialise() StreamSelection.OnSelectionChange = RefreshOptions; } - protected override string? KeyFunction(Branch? value) => value?.name; + protected override string? KeyFunction(Branch? value) => value?.id; public override void RefreshOptions() { Stream? stream = StreamSelection.Selected; if (stream == null) return; - IList branches; + IReadOnlyList branches; try { branches = Client! diff --git a/Packages/systems.speckle.speckle-unity/Runtime/Wrappers/Selection/CommitSelection.cs b/Packages/systems.speckle.speckle-unity/Runtime/Wrappers/Selection/CommitSelection.cs index 9acaf93..f614062 100644 --- a/Packages/systems.speckle.speckle-unity/Runtime/Wrappers/Selection/CommitSelection.cs +++ b/Packages/systems.speckle.speckle-unity/Runtime/Wrappers/Selection/CommitSelection.cs @@ -29,7 +29,7 @@ public void Initialise() public override void RefreshOptions() { - Branch? branch = BranchSelection!.Selected; + Branch? branch = BranchSelection.Selected; if (branch == null) return; List commits = branch.commits.items; diff --git a/Packages/systems.speckle.speckle-unity/Runtime/Wrappers/Selection/OptionSelection.cs b/Packages/systems.speckle.speckle-unity/Runtime/Wrappers/Selection/OptionSelection.cs index 156d4f2..9db7193 100644 --- a/Packages/systems.speckle.speckle-unity/Runtime/Wrappers/Selection/OptionSelection.cs +++ b/Packages/systems.speckle.speckle-unity/Runtime/Wrappers/Selection/OptionSelection.cs @@ -10,7 +10,7 @@ namespace Speckle.ConnectorUnity.Wrappers.Selection /// /// Reusable serializable type that abstracts /// the fetching of objects. - /// And exposes an of + /// And exposes an list of /// with serialised selection. /// /// @@ -18,32 +18,42 @@ namespace Speckle.ConnectorUnity.Wrappers.Selection public abstract class OptionSelection where TOption : class { + public IReadOnlyList Options { get; protected set; } = Array.Empty(); + + private Dictionary? _indexMap; + [SerializeField] - private int selectedIndex = -1; + private string? selectedId; - public int SelectedIndex + public TOption? Selected { - get => selectedIndex; + get + { + if (selectedId == null) + return null; + + TryGetOption(selectedId, out var value); + return value; + } set { - selectedIndex = value; + selectedId = KeyFunction(value); OnSelectionChange?.Invoke(); } } - public TOption? Selected + public bool TryGetOption(string key, [NotNullWhen(true)] out TOption? value) { - get + if (_indexMap is not null && _indexMap.TryGetValue(key, out int index)) { - if (Options is null) - return null; - if (SelectedIndex < 0 || SelectedIndex >= Options.Length) - return null; - return Options[SelectedIndex]; + value = Options[index]; + return true; } + + value = null; + return false; } - public TOption[] Options { get; protected set; } = Array.Empty(); public Action? OnSelectionChange { get; set; } public abstract Client? Client { get; } @@ -53,36 +63,38 @@ public TOption? Selected public abstract void RefreshOptions(); - protected void GenerateOptions(IList source, Func isDefault) + protected void GenerateOptions( + IReadOnlyCollection source, + Func isDefault + ) { List optionsToAdd = new(source.Count); - int defaultOption = -1; + Dictionary indexMap = new(source.Count); + string? defaultOption = null; int index = 0; foreach (TOption? a in source) { if (a == null) continue; + + var key = KeyFunction(a); optionsToAdd.Add(a); + indexMap.Add(key, index); + if (isDefault(a, index)) - defaultOption = index; + defaultOption = key; + index++; } - TOption? currentSelected = Selected; - bool selectionOutOfRange = SelectedIndex < 0 || SelectedIndex >= optionsToAdd.Count; - if ( - selectionOutOfRange - || ( - currentSelected != null - && KeyFunction(currentSelected) != KeyFunction(optionsToAdd[SelectedIndex]) - ) - ) + string? currentSelected = KeyFunction(Selected); + if (currentSelected is null || !indexMap.ContainsKey(currentSelected)) { - selectedIndex = defaultOption; + selectedId = defaultOption; } - Options = optionsToAdd.ToArray(); - //Debug.Log($"{this.GetType()} updated"); + Options = optionsToAdd; + _indexMap = indexMap; OnSelectionChange?.Invoke(); } } diff --git a/Packages/systems.speckle.speckle-unity/Runtime/Wrappers/Selection/StreamSelection.cs b/Packages/systems.speckle.speckle-unity/Runtime/Wrappers/Selection/StreamSelection.cs index e86b9d8..c06240e 100644 --- a/Packages/systems.speckle.speckle-unity/Runtime/Wrappers/Selection/StreamSelection.cs +++ b/Packages/systems.speckle.speckle-unity/Runtime/Wrappers/Selection/StreamSelection.cs @@ -36,7 +36,7 @@ public override void RefreshOptions() { if (Client == null) return; - IList streams; + IReadOnlyList streams; try { streams = Client.StreamsGet(StreamsLimit).GetAwaiter().GetResult(); diff --git a/Packages/systems.speckle.speckle-unity/Runtime/Wrappers/SpeckleProperties.cs b/Packages/systems.speckle.speckle-unity/Runtime/Wrappers/SpeckleProperties.cs index fd5b4f0..20eba09 100644 --- a/Packages/systems.speckle.speckle-unity/Runtime/Wrappers/SpeckleProperties.cs +++ b/Packages/systems.speckle.speckle-unity/Runtime/Wrappers/SpeckleProperties.cs @@ -5,7 +5,6 @@ using Speckle.Core.Api; using Speckle.Core.Models; using Speckle.Core.Serialisation; -using Speckle.Newtonsoft.Json; using UnityEngine; namespace Speckle.ConnectorUnity.Wrappers