// Initialise receiver public async void Init(string StreamId, string URL) { Client = new SpeckleCore.SpeckleApiClient(URL); // Assign events Client.OnReady += Client_OnReady; Client.OnLogData += Client_OnLogData; Client.OnWsMessage += Client_OnWsMessage; Client.OnError += Client_OnError; SpeckleObjects = new List <SpeckleCore.SpeckleObject>(); await Client.IntializeReceiver(StreamId, Application.productName, "Unity", Application.buildGUID, authToken); Client.Stream = (await Client.StreamGetAsync(Client.StreamId, null)).Resource; rootGameObject = new GameObject(Client.Stream.Name); // Call event on SpeckleManager to allow users to do their own thing when a stream is created transform.GetComponent <UnitySpeckle>().OnReceiverCreated.Invoke(this); UpdateGlobal(); }
public async void UpdateGlobal() { bRefreshingDisplay = true; var streamGetResponse = await Client.StreamGetAsync(Client.StreamId, null); if (streamGetResponse.Success == false) { Debug.Log(streamGetResponse.Message); // TODO: Actually handle this } Client.Stream = streamGetResponse.Resource; // This is gross of the C# API Debug.Log("Getting objects...."); var getObjectResult = await Client.ObjectGetBulkAsync(Client.Stream.Objects.Select(obj => obj._id).ToArray(), null); // TODO: Check if ObjectGetBulkAsync returns objects in a corresponding order. If it does, the next little bit can be simplified Dictionary <string, SpeckleCore.SpeckleObject> ObjectCache = getObjectResult.Resources.ToDictionary(speckleObject => speckleObject._id); SpeckleObjects = Client.Stream.Objects.Select(speckleObject => ObjectCache[speckleObject._id]).ToList(); // Remove old layers foreach (SpeckleCore.Layer layer in Layers.Keys.Where(layer => Client.Stream.Layers.Where(newLayer => newLayer.Guid != layer.Guid).Count() > 0).ToList()) // ToList is required because we're modifying Layers, I think { Destroy(Layers[layer]); Layers.Remove(layer); } // Add new layers foreach (SpeckleCore.Layer layer in Client.Stream.Layers.Where(layer => !Layers.ContainsKey(layer)).ToList()) { Layers[layer] = new GameObject(layer.Name); Layers[layer].transform.SetParent(rootGameObject.transform); } // Mark all existing objects foreach (UnitySpeckleObjectData usod in rootGameObject.GetComponentsInChildren <UnitySpeckleObjectData>()) { usod.LayerName = null; } // Create new objects for (int i = 0; i < SpeckleObjects.Count; i++) { SpeckleCore.Layer layer = LayerFromIndex(i); GameObject layerObject = Layers[layer]; GameObject gameObject = (GameObject)SpeckleCore.Converter.Deserialise(SpeckleObjects[i]); // TODO: This creates a new game object even if one already exists. It should reuse objects which already exist // TODO: The more fundamental issue is that checking which layer an object is in is tricky. Perhaps layers map more naturally to Unity's tags. gameObject.GetComponent <UnitySpeckleObjectData>().LayerName = layer.Name; gameObject.transform.SetParent(layerObject.transform); } // Destroy all objects which are still marked foreach (UnitySpeckleObjectData usod in rootGameObject.GetComponentsInChildren <UnitySpeckleObjectData>()) { if (usod.LayerName == null) { Destroy(usod.gameObject); } } bRefreshingDisplay = false; transform.GetComponent <UnitySpeckle>().OnUpdateReceived.Invoke(this); }