/// <summary> /// Called when a surface is going to be added, removed, or updated. /// We only care about removal so we can remove our internal copy of the surface mesh. /// </summary> /// <param name="surfaceId">The surface ID that is being added/removed/updated</param> /// <param name="changeType">Added | Removed | Updated</param> /// <param name="bounds">The world volume the mesh is in.</param> /// <param name="updateTime">When the mesh was updated.</param> private void MappingObserver_SurfaceChanged(SurfaceId surfaceId, SurfaceChange changeType, Bounds bounds, DateTime updateTime) { // We only need to worry about removing meshes from our list. Adding and updating is // done when the mesh data is actually ready. if (changeType == SurfaceChange.Removed) { int meshIndex = FindMeshIndexInInputMeshList(surfaceId.handle); if(meshIndex >= 0) { inputMeshList.RemoveAt(meshIndex); } } }
/// <summary> /// Handles the SurfaceObserver's OnSurfaceChanged event. /// </summary> /// <param name="id">The identifier assigned to the surface which has changed.</param> /// <param name="changeType">The type of change that occurred on the surface.</param> /// <param name="bounds">The bounds of the surface.</param> /// <param name="updateTime">The date and time at which the change occurred.</param> private void SurfaceObserver_OnSurfaceChanged(SurfaceId id, SurfaceChange changeType, Bounds bounds, System.DateTime updateTime) { if (!IsRunning) { return; } switch (changeType) { case SurfaceChange.Added: case SurfaceChange.Updated: meshWorkQueue.Enqueue(id); break; case SurfaceChange.Removed: RemoveMeshObject(id.handle); break; } }
private void OnSurfaceChanged(SurfaceId surfaceId, SurfaceChange changeType, Bounds bounds, DateTime updateTime) { // Find the surface List <SpatialMappingSource.SurfaceObject> surfaceObjects = SpatialMappingManager.Instance.GetSurfaceObjects(); // Find it (in both lists) int surfaceObjectIndex = FindSurfaceIndexInList(surfaceId.handle, surfaceObjects); int meshDataIndex = FindMeshIndexInInputMeshList(surfaceId.handle); // Deal with the change switch (changeType) { case SurfaceChange.Added: { if (surfaceObjectIndex >= 0 && surfaceObjectIndex < surfaceObjects.Count) { AddOrUpdateMeshInList(surfaceId.handle, surfaceObjectIndex, surfaceObjects); } } break; case SurfaceChange.Removed: { if (meshDataIndex >= 0 && meshDataIndex < inputMeshList.Count) { inputMeshList.RemoveAt(meshDataIndex); } } break; case SurfaceChange.Updated: { if ((surfaceObjectIndex >= 0 && surfaceObjectIndex < surfaceObjects.Count) && (meshDataIndex >= 0 && meshDataIndex < inputMeshList.Count)) { AddOrUpdateMeshInList(surfaceId.handle, surfaceObjectIndex, surfaceObjects, meshDataIndex); } } break; } }
/// <summary> /// Handles the SurfaceObserver's OnSurfaceChanged event. /// </summary> /// <param name="id">The identifier assigned to the surface which has changed.</param> /// <param name="changeType">The type of change that occurred on the surface.</param> /// <param name="bounds">The bounds of the surface.</param> /// <param name="updateTime">The date and time at which the change occurred.</param> private void SurfaceObserver_OnSurfaceChanged(SurfaceId id, SurfaceChange changeType, Bounds bounds, DateTime updateTime) { // Verify that the client of the Surface Observer is expecting updates. if (ObserverState != ObserverStates.Running) { return; } switch (changeType) { /// Interestingly, surface is pushed to queue only when it's updated but not added. case SurfaceChange.Added: //Debug.Log(System.String.Format("SurfaceObserver_OnSurfaceChanged: ADDED id: {0}", id)); surfaceAddCount += 1; break; case SurfaceChange.Updated: if (!isSurfaceObsolete(id) || SpatialMappingManager.Instance.isSurfaceNearCamera(bounds)) { surfaceWorkQueue.Enqueue(id); //Debug.Log(System.String.Format("SurfaceObserver_OnSurfaceChanged: UPDATED id: {0}", id)); surfaceUpdateCount += 1; } break; case SurfaceChange.Removed: Debug.Log(System.String.Format("SurfaceObserver_OnSurfaceChanged: REMOVED id: {0}", id)); surfaceRemoveCount += 1; SurfaceObject?removedSurface = RemoveSurfaceIfFound(id.handle, destroyGameObject: false); if (removedSurface != null) { ReclaimSurface(removedSurface.Value); } break; default: Debug.LogErrorFormat("Unexpected {0} value: {1}.", changeType.GetType(), changeType); break; } }
/// <summary> /// This method handles observed changes to surfaces (added, updated, or removed). /// These changes have their source in the update loop where the surface observer /// is updated. /// </summary> /// <param name="id">The unique id of the surface</param> /// <param name="changeType">Says if the surface has been added, updated, or removed</param> /// <param name="bounds">The axis aligned bounding box containing the surface</param> /// <param name="updateTime">Time of the update</param> private void SurfaceChangedHandler(SurfaceId id, SurfaceChange changeType, Bounds bounds, DateTime updateTime) { ISpatialSurface surface = null; switch (changeType) { case SurfaceChange.Added: case SurfaceChange.Updated: if (_surfaceEntries.TryGetValue(id.handle, out surface)) { if (surface.MeshStatus == SurfaceMeshStatuses.UP_TO_DATE) { surface.MeshStatus = SurfaceMeshStatuses.OUTDATED; surface.UpdateTime = updateTime; } } else { surface = _surfaceEntryFactory.Create(updateTime, id.handle, _castShadows, _recieveShadows, _meshMaterial, _addColliders, _physicMaterial); surface.Instance.transform.SetParent(_meshParent != null ? _meshParent : transform, false); _surfaceEntries[id.handle] = surface; } break; case SurfaceChange.Removed: if (_surfaceEntries.TryGetValue(id.handle, out surface)) { _surfaceEntries.Remove(id.handle); Mesh mesh = surface.Mesh.mesh; if (mesh) { Destroy(mesh); } Destroy(surface.Instance); } break; default: break; } }
/// <summary> /// Handles the SurfaceObserver's OnSurfaceChanged event. /// </summary> /// <param name="id">The identifier assigned to the surface which has changed.</param> /// <param name="changeType">The type of change that occurred on the surface.</param> /// <param name="bounds">The bounds of the surface.</param> /// <param name="updateTime">The date and time at which the change occurred.</param> private void SurfaceObserver_OnSurfaceChanged(SurfaceId id, SurfaceChange changeType, Bounds bounds, System.DateTime updateTime) { if (!WaitingForSceneObserverAccess) { return; } using (OnSurfaceChangedPerfMarker.Auto()) { switch (changeType) { case SurfaceChange.Added: case SurfaceChange.Updated: meshWorkQueue.Enqueue(id); break; case SurfaceChange.Removed: RemoveMeshObject(id.handle); break; } } }
private void OnSurfaceChanged(SurfaceId surfaceId, SurfaceChange changeType, Bounds bounds, System.DateTime updateTime) { switch (changeType) { case (SurfaceChange.Added): case (SurfaceChange.Updated): if (!spatialMeshObjects.ContainsKey(surfaceId)) { var meshPiece = new GameObject("spatial-mapping-" + surfaceId); meshPiece.transform.parent = transform; var pieceRenderer = meshPiece.AddComponent <MeshRenderer>(); pieceRenderer.material = surfaceMat; spatialMeshObjects[surfaceId] = meshPiece; } GameObject target = spatialMeshObjects[surfaceId]; SurfaceData sd = new SurfaceData( surfaceId, target.GetComponent <MeshFilter>() ?? target.AddComponent <MeshFilter>(), target.GetComponent <WorldAnchor>() ?? target.AddComponent <WorldAnchor>(), target.GetComponent <MeshCollider>() ?? target.AddComponent <MeshCollider>(), 256, true); observer.RequestMeshAsync(sd, OnDataReady); break; case (SurfaceChange.Removed): var obj = spatialMeshObjects[surfaceId]; spatialMeshObjects.Remove(surfaceId); if (obj != null) { GameObject.Destroy(obj); } break; default: break; } }
// This handler receives surface changed events and is propagated by the // Update method on SurfaceObserver. void SurfaceChangedHandler(SurfaceId id, SurfaceChange changeType, Bounds bounds, DateTime updateTime) { SurfaceEntry entry; switch (changeType) { case SurfaceChange.Added: case SurfaceChange.Updated: if (m_Surfaces.TryGetValue(id.handle, out entry)) { // If this surface has already been baked, mark it as needing bake // in addition to the update time so the "next surface to bake" // logic will order it correctly. if (entry.m_BakedState == BakedState.Baked) { entry.m_BakedState = BakedState.UpdatePostBake; entry.m_UpdateTime = updateTime; //send mesh to the ground staton. //old way /* * NetworkMeshSource.getSingleton().sendMesh(entry.m_Surface.GetComponent<MeshFilter>().mesh, * entry.m_Surface.transform.position, * entry.m_Surface.transform.rotation); */ } } else { // This is a brand new surface so create an entry for it. entry = new SurfaceEntry(); entry.m_BakedState = BakedState.NeverBaked; entry.m_UpdateTime = updateTime; entry.m_Id = id.handle; entry.m_Surface = new GameObject(System.String.Format("Surface-{0}", id.handle)); entry.m_Surface.AddComponent <MeshFilter>(); entry.m_Surface.AddComponent <MeshCollider>(); MeshRenderer mr = entry.m_Surface.AddComponent <MeshRenderer>(); mr.shadowCastingMode = ShadowCastingMode.Off; mr.receiveShadows = false; entry.m_Surface.AddComponent <WorldAnchor>(); entry.m_Surface.GetComponent <MeshRenderer>().sharedMaterial = m_drawMat; m_Surfaces[id.handle] = entry; if (!SurfacesList.Contains(entry)) { SurfacesList.Add(entry); } } break; case SurfaceChange.Removed: if (m_Surfaces.TryGetValue(id.handle, out entry)) { m_Surfaces.Remove(id.handle); Mesh mesh = entry.m_Surface.GetComponent <MeshFilter>().mesh; if (mesh) { Destroy(mesh); } Destroy(entry.m_Surface); } break; } }
/// <summary> /// Handles the SurfaceObserver's OnSurfaceChanged event. /// </summary> /// <param name="id">The identifier assigned to the surface which has changed.</param> /// <param name="surface">The surface</param> /// <param name="changeType">The type of change that occurred on the surface.</param> /// <param name="updateTime">The date and time at which the change occurred.</param> protected virtual void OnSurfaceChanged(Guid id, SpatialMappingSurface surface, SurfaceChange changeType, DateTimeOffset updateTime) { WaveForegroundTask.Run(() => { if (surface.Mesh == null) { return; } Debug.WriteLine("OnSurfaceChanged [" + changeType + "] " + id); string entityId = this.GetEntityNameFromSurfaceId(id); switch (changeType) { case SurfaceChange.Added: case SurfaceChange.Updated: var surfaceEntity = this.Owner.FindChild(entityId); if (surfaceEntity == null) { surfaceEntity = this.CreateNewSurfaceEntity(entityId, surface); surfaceEntity.Tag = SurfaceEntityTag; if (surfaceEntity != null) { this.Owner.AddChild(surfaceEntity); } } else { this.RefreshModel(surface, surfaceEntity); this.UpdateSurfaceEntity(surface, surfaceEntity); } break; case SurfaceChange.Removed: // Remove the child entity this.Owner.RemoveChild(entityId); break; default: break; } }); }
private static void InvokeSurfaceChangedEvent(SurfaceChangedDelegate onSurfaceChanged, int surfaceId, SurfaceChange changeType, Bounds bounds, long updateTime) { if (onSurfaceChanged != null) { SurfaceId id; id.handle = surfaceId; onSurfaceChanged(id, changeType, bounds, DateTime.FromFileTime(updateTime)); } }
/// <summary> /// Handles the SurfaceObserver's OnSurfaceChanged event. /// </summary> /// <param name="id">The identifier assigned to the surface which has changed.</param> /// <param name="changeType">The type of change that occurred on the surface.</param> /// <param name="bounds">The bounds of the surface.</param> /// <param name="updateTime">The date and time at which the change occurred.</param> private void SurfaceObserver_OnSurfaceChanged(SurfaceId id, SurfaceChange changeType, Bounds bounds, System.DateTime updateTime) { // Verify that the client of the Surface Observer is expecting updates. if (ObserverState != ObserverStates.Running) { return; } GameObject surface; switch (changeType) { // Adding and updating are nearly identical. The only difference is if a new gameobject to contain // the surface needs to be created. case SurfaceChange.Added: case SurfaceChange.Updated: // Check to see if the surface is known to the observer. // If so, we want to add it for cleanup after we get new meshes // We do this because Unity doesn't properly cleanup baked collision data if (surfaces.TryGetValue(id.handle, out surface)) { pendingCleanup.Add(id.handle, surface); surfaces.Remove(id.handle); } // Get an available surface object ready to be used surface = GetSurfaceObject(id.handle, transform); // Add the surface to our dictionary of known surfaces so // we can interact with it later. surfaces.Add(id.handle, surface); // Add the request to create the mesh for this surface to our work queue. QueueSurfaceDataRequest(id, surface); break; case SurfaceChange.Removed: // Always process surface removal events. // This code can be made more thread safe if (surfaces.TryGetValue(id.handle, out surface)) { surfaces.Remove(id.handle); CleanupSurface(surface); RemoveSurfaceObject(surface, false); } break; } //List<MeshFilter> filters = SpatialMappingManager.Instance.GetMeshFilters(); //CombineInstance[] combine = new CombineInstance[filters.Count]; //int i = 0; //while (i < filters.Count) //{ // combine[i].mesh = filters[i].mesh; // combine[i].transform = filters[i].transform.localToWorldMatrix; // i++; //} //Mesh mesh = new Mesh(); //mesh.CombineMeshes(combine); //byte[] serialized = MeshSerializer.WriteMesh(mesh, true); //GameObject obj = PhotonView.Find("MyPrefabName"); //PhotonView photonView = PhotonView.Get(obj); //if (photonView) //{ // photonView.RPC("GetStreamData", RpcTarget.All, serialized); //} // Event if (SurfaceChanged != null) { SurfaceChanged(id, changeType, bounds, updateTime); } }
/// <summary> /// Handler for calling SurfaceObserver.Update which will then handle the changes /// /// The actual changes will be handled via HandleAdd (for SurfaceChange.Added and SurfaceChange.Updated) and HandleDelete (for SurfaceChange.Removed) /// </summary> /// <param name="surfaceId">The identifier of the surface in question</param> /// <param name="changeType">What type of change this is (add, update, or remove)</param> /// <param name="bounds">The bounds of the mesh</param> /// <param name="updateTime">The time the update occurred</param> protected virtual void SurfaceObserver_OnSurfaceChanged(SurfaceId surfaceId, SurfaceChange changeType, Bounds bounds, System.DateTime updateTime) { switch (changeType) { case SurfaceChange.Added: case SurfaceChange.Updated: HandleAdd(surfaceId, updateTime, bakeMeshes); break; case SurfaceChange.Removed: HandleDelete(surfaceId); break; default: break; } }
/// <summary> /// This handler receives events when surfaces change, and propagates those events /// using the SurfaceObserver’s Update method /// </summary> /// <param name="id">Handle identifying the surface</param> /// <param name="changeType">Reason for update</param> /// <param name="bounds">New bounds of th esurface</param> /// <param name="updateTime">Time stamp of modification.</param> private void SurfaceChangedHandler(SurfaceId id, SurfaceChange changeType, Bounds bounds, DateTime updateTime) { SurfaceEntry entry; switch (changeType) { case SurfaceChange.Added: case SurfaceChange.Updated: if (surfaces.TryGetValue(id.handle, out entry)) { // If the system has already baked this Surface, lower its priority. if (entry.currentState == BakedState.Baked) { entry.currentState = BakedState.UpdatePostBake; entry.updateTime = updateTime; } } else { // This is a brand new Surface so create an entry for it. entry = new SurfaceEntry(); entry.currentState = BakedState.NeverBaked; entry.updateTime = updateTime; entry.handle = id.handle; entry.surfaceObject = new GameObject(System.String.Format("Surface-{0}", id.handle)); entry.surfaceObject.layer = spatialMappingLayer; if (HangerObject != null) { entry.surfaceObject.transform.SetParent(HangerObject, false); } entry.surfaceObject.AddComponent <MeshFilter>(); if (Collide) { entry.surfaceObject.AddComponent <MeshCollider>(); } MeshRenderer mr = entry.surfaceObject.AddComponent <MeshRenderer>(); mr.shadowCastingMode = ShadowCastingMode.Off; mr.receiveShadows = false; mr.sharedMaterial = DrawMaterial; mr.enabled = this.Display; entry.worldAnchorChild = new GameObject(entry.surfaceObject.name + "WorldAnchor"); entry.worldAnchorChild.transform.SetParent(entry.surfaceObject.transform, false); entry.worldAnchorChild.AddComponent <WorldAnchor>(); // Add an adapter component to keep the surface object where the WorldAnchor means it to be. var adapter = entry.surfaceObject.AddComponent <WorldAnchorAdapter>(); adapter.TargetObject = entry.surfaceObject.transform; adapter.WorldAnchorObject = entry.worldAnchorChild; surfaces[id.handle] = entry; } break; case SurfaceChange.Removed: if (surfaces.TryGetValue(id.handle, out entry)) { surfaces.Remove(id.handle); Destroy(entry.surfaceObject); // Note entry.worldAnchorChild is child of surfaceObject, so will get destroyed // along with components. } break; } }
/// <summary> /// Handles the SurfaceObserver's OnSurfaceChanged event. /// </summary> /// <param name="id">The identifier assigned to the surface which has changed.</param> /// <param name="changeType">The type of change that occurred on the surface.</param> /// <param name="bounds">The bounds of the surface.</param> /// <param name="updateTime">The date and time at which the change occurred.</param> private void SurfaceObserver_OnSurfaceChanged(SurfaceId id, SurfaceChange changeType, Bounds bounds, System.DateTime updateTime) { // Verify that the client of the Surface Observer is expecting updates. if (ObserverState != ObserverStates.Running) { return; } GameObject surface; switch (changeType) { // Adding and updating are nearly identical. The only difference is if a new GameObject to contain // the surface needs to be created. case SurfaceChange.Added: case SurfaceChange.Updated: // Check to see if the surface is known to the observer. if (!surfaces.TryGetValue(id.handle, out surface)) { // If we are adding a new surface, construct a GameObject // to represent its state and attach some Mesh-related // components to it. surface = AddSurfaceObject(null, string.Format("Surface-{0}", id.handle), transform); surface.AddComponent<WorldAnchor>(); // Add the surface to our dictionary of known surfaces so // we can interact with it later. surfaces.Add(id.handle, surface); } // Add the request to create the mesh for this surface to our work queue. QueueSurfaceDataRequest(id, surface); break; case SurfaceChange.Removed: // Always process surface removal events. if (surfaces.TryGetValue(id.handle, out surface)) { RemoveSurfaceObject(surface); surfaces.Remove(id.handle); } break; } }
/// <summary> /// Process all spatial surfaces /// </summary> /// <param name="handler">The handler to receive the surface information</param> /// <param name="ignorePrevious">Ignore previous surfaces</param> public void UpdateSurfaces(OnSurfaceChangedHandler handler, bool ignorePrevious) { ////if (!this.pendingChanges && !ignorePrevious) ////{ //// return; ////} this.pendingChanges = false; lock (this) { if (this.updateSurfacesTask != null) { return; } this.updateSurfacesTask = System.Threading.Tasks.Task.Run(() => { try { this.surfaceMeshOptions.IncludeVertexNormals = this.ObtainNormals; var surfaceCollection = this.surfaceObserver.GetObservedSurfaces(); foreach (var pair in surfaceCollection) { // Gets the MixedReality surface var id = pair.Key; var surfaceInfo = pair.Value; SpatialMappingSurface surface; SurfaceChange change = SurfaceChange.Updated; if (!this.surfaces.TryGetValue(id, out surface)) { surface = new SpatialMappingSurfaceInternal() { Id = id }; this.surfaces.Add(id, surface); change = SurfaceChange.Added; } if (surface.UpdateTime < surfaceInfo.UpdateTime) { this.UpdateSurface(handler, change, surface as SpatialMappingSurfaceInternal, this.TrianglesPerCubicMeter, surfaceInfo, this.surfaceMeshOptions); } else if (ignorePrevious) { if (handler != null) { handler(id, surface, SurfaceChange.Removed, surface.UpdateTime); } } } var surafacesToRemove = this.surfaces.Where(id => !surfaceCollection.ContainsKey(id.Key)).ToList(); foreach (var pair in surafacesToRemove) { var id = pair.Key; var surface = pair.Value; this.surfaces.Remove(id); surface.Dispose(); if (handler != null) { handler(id, surface, SurfaceChange.Removed, surface.UpdateTime); } } } catch (Exception e) { Debug.WriteLine(e); } this.updateSurfacesTask = null; }); } }
/// <summary> /// Handles the SurfaceObserver's OnSurfaceChanged event. /// </summary> /// <param name="surfaceId">The identifier assigned to the surface which has changed.</param> /// <param name="changeType">The type of change that occurred on the surface.</param> /// <param name="bounds">The bounds of the surface.</param> /// <param name="updateTime">The date and time at which the change occurred.</param> private async void SurfaceObserver_OnSurfaceChanged(SurfaceId surfaceId, SurfaceChange changeType, Bounds bounds, DateTime updateTime) { // If we're adding or updating a mesh if (changeType != SurfaceChange.Removed) { var spatialMeshObject = await RequestSpatialMeshObject(surfaceId.handle); spatialMeshObject.GameObject.name = $"SpatialMesh_{surfaceId.handle.ToString()}"; var worldAnchor = spatialMeshObject.GameObject.EnsureComponent <WorldAnchor>(); var surfaceData = new SurfaceData(surfaceId, spatialMeshObject.Filter, worldAnchor, spatialMeshObject.Collider, MeshTrianglesPerCubicMeter, true); if (!observer.RequestMeshAsync(surfaceData, OnDataReady)) { Debug.LogError($"Mesh request failed for spatial observer with Id {surfaceId.handle.ToString()}"); RaiseMeshRemoved(spatialMeshObject); } void OnDataReady(SurfaceData cookedData, bool outputWritten, float elapsedCookTimeSeconds) { if (!outputWritten) { Debug.LogWarning($"No output for {cookedData.id.handle}"); return; } if (!SpatialMeshObjects.TryGetValue(cookedData.id.handle, out SpatialMeshObject meshObject)) { // Likely it was removed before data could be cooked. return; } // Apply the appropriate material to the mesh. SpatialMeshDisplayOptions displayOption = MeshDisplayOption; if (displayOption != SpatialMeshDisplayOptions.None) { meshObject.Renderer.enabled = true; meshObject.Renderer.sharedMaterial = (displayOption == SpatialMeshDisplayOptions.Visible) ? MeshVisibleMaterial : MeshOcclusionMaterial; } else { meshObject.Renderer.enabled = false; } // Recalculate the mesh normals if requested. if (MeshRecalculateNormals) { meshObject.Filter.sharedMesh.RecalculateNormals(); } meshObject.GameObject.SetActive(true); switch (changeType) { case SurfaceChange.Added: RaiseMeshAdded(meshObject); break; case SurfaceChange.Updated: RaiseMeshUpdated(meshObject); break; } } } else if (SpatialMeshObjects.TryGetValue(surfaceId.handle, out SpatialMeshObject meshObject)) { RaiseMeshRemoved(meshObject); } }
/// <summary> /// Handles the SurfaceObserver's OnSurfaceChanged event. /// </summary> /// <param name="id">The identifier assigned to the surface which has changed.</param> /// <param name="surface">The surface</param> /// <param name="changeType">The type of change that occurred on the surface.</param> /// <param name="updateTime">The date and time at which the change occurred.</param> protected virtual void OnSurfaceChanged(Guid id, SpatialMappingSurface surface, SurfaceChange changeType, DateTimeOffset updateTime) { WaveServices.Dispatcher.RunOnWaveThread(() => { if (surface.Mesh == null) { return; } Debug.WriteLine("OnSurfaceChanged [" + changeType + "] " + id); string entityId = this.GetEntityNameFromSurfaceId(id); switch (changeType) { case SurfaceChange.Added: case SurfaceChange.Updated: var surfaceEntity = this.Owner.FindChild(entityId); if (surfaceEntity == null) { surfaceEntity = this.CreateNewSurfaceEntity(entityId, surface); surfaceEntity.Tag = SurfaceEntityTag; if (surfaceEntity != null) { this.Owner.AddChild(surfaceEntity); } } else { this.RefreshModel(surface, surfaceEntity); this.UpdateSurfaceEntity(surface, surfaceEntity); } break; case SurfaceChange.Removed: // Remove the child entity this.Owner.RemoveChild(entityId); break; default: break; } }); }
/// <summary> /// Handles the SurfaceObserver's OnSurfaceChanged event. /// </summary> /// <param name="id">The identifier assigned to the surface which has changed.</param> /// <param name="changeType">The type of change that occurred on the surface.</param> /// <param name="bounds">The bounds of the surface.</param> /// <param name="updateTime">The date and time at which the change occurred.</param> private void SurfaceObserver_OnSurfaceChanged(SurfaceId id, SurfaceChange changeType, Bounds bounds, System.DateTime updateTime) { // Verify that the client of the Surface Observer is expecting updates. if (ObserverState != ObserverStates.Running) { return; } GameObject surface; switch (changeType) { // Adding and updating are nearly identical. The only difference is if a new gameobject to contain // the surface needs to be created. case SurfaceChange.Added: case SurfaceChange.Updated: // Check to see if the surface is known to the observer. // If so, we want to add it for cleanup after we get new meshes // We do this because Unity doesn't properly cleanup baked collision data if (surfaces.TryGetValue(id.handle, out surface)) { pendingCleanup.Add(id.handle, surface); surfaces.Remove(id.handle); } // Get an available surface object ready to be used surface = GetSurfaceObject(id.handle, transform); // Add the surface to our dictionary of known surfaces so // we can interact with it later. surfaces.Add(id.handle, surface); // Add the request to create the mesh for this surface to our work queue. QueueSurfaceDataRequest(id, surface); break; case SurfaceChange.Removed: // Always process surface removal events. // This code can be made more thread safe if (surfaces.TryGetValue(id.handle, out surface)) { surfaces.Remove(id.handle); CleanupSurface(surface); RemoveSurfaceObject(surface, false); } break; } // Event if (SurfaceChanged != null) { SurfaceChanged(id, changeType, bounds, updateTime); } }