/// <summary> /// Updates which faces are active. /// </summary> /// <remarks> /// This works by destroying faces that are no longer needed and creating faces which are new. /// </remarks> private void UpdateActiveFaces() { // If were not connected we can't create or update any cut planes if (!RemoteManagerUnity.IsConnected) { return; } // Which faces were added and removed? ClippingBoxFaces removed = (lastFaces & ~faces); ClippingBoxFaces added = (faces & ~lastFaces); // Create and destroy as necessary DestroyFaces(removed); CreateFaces(added); // Sync lastFaces = faces; // Did we exceed the maximum number of cut planes? if (faceObjects.Count > MAX_CUTPLANES) { Debug.LogFormat(LogType.Warning, LogOption.NoStacktrace, null, "{0}", $"There are {faceObjects.Count} cut planes in use but some servers may only support {MAX_CUTPLANES}. Some cut planes may be ignored."); } }
/// <summary> /// Converts a <see cref="ClippingBoxFaces"/> enum value to child position. /// </summary> /// <param name="face"> /// The face to convert. /// </param> /// <param name="parent"> /// The parent transform. /// </param> /// <returns> /// The corresponding position. /// </returns> static private Vector3 FaceToPosition(ClippingBoxFaces face, Transform parent) { switch (face) { case ClippingBoxFaces.PositiveX: return(new Vector3(parent.localScale.x / 2, 0, 0)); case ClippingBoxFaces.NegativeX: return(new Vector3(-parent.localScale.x / 2, 0, 0)); case ClippingBoxFaces.PositiveY: return(new Vector3(0, parent.localScale.y / 2, 0)); case ClippingBoxFaces.NegativeY: return(new Vector3(0, -parent.localScale.y / 2, 0)); case ClippingBoxFaces.PositiveZ: return(new Vector3(0, 0, parent.localScale.z / 2)); case ClippingBoxFaces.NegativeZ: return(new Vector3(0, 0, -parent.localScale.z / 2)); default: throw new InvalidOperationException("Unknown face"); } }
/// <summary> /// Converts a <see cref="ClippingBoxFaces"/> enum value to an ARR direction. /// </summary> /// <param name="face"> /// The face to convert. /// </param> /// <returns> /// The corresponding axis. /// </returns> static private Axis FaceToNormal(ClippingBoxFaces face) { switch (face) { case ClippingBoxFaces.PositiveX: return(Axis.X); case ClippingBoxFaces.NegativeX: return(Axis.X_Neg); case ClippingBoxFaces.PositiveY: return(Axis.Y); case ClippingBoxFaces.NegativeY: return(Axis.Y_Neg); case ClippingBoxFaces.PositiveZ: return(Axis.Z); case ClippingBoxFaces.NegativeZ: return(Axis.Z_Neg); default: // Catch all throw new InvalidOperationException("Unknown face"); } }
/// <summary> /// Destroys the specified faces. /// </summary> /// <param name="faces"> /// The faces to destroy. /// </param> private void DestroyFaces(ClippingBoxFaces faces) { // Loop through specified faces ForSpecificFaces(faces, (face, faceObject) => { // Get the cut plane component ARRCutPlaneComponent cutPlane = faceObject.GetComponent <ARRCutPlaneComponent>(); // If connected, disable the cut plane component if (RemoteManagerUnity.IsConnected) { try { cutPlane.RemoteComponent.Enabled = false; } catch (Exception ex) { Debug.LogFormat(LogType.Warning, LogOption.NoStacktrace, null, "{0}", $"Could not disable cut plane: {ex.Message}"); } } // Remove the face object from the active list faceObjects.Remove(face); // Mark it for destruction GameObject.Destroy(faceObject); }); }
private void RemoteManager_ConnectionStatusChanged(ConnectionStatus status, Result error) { // Were we just disconnected? if (status == ConnectionStatus.Disconnected) { // Destroy all faces DestroyFaces((ClippingBoxFaces)ClippingBoxFaceGroups.All); // Set last faces to none, so on the next connect the right ones will be created lastFaces = (ClippingBoxFaces)ClippingBoxFaceGroups.None; } // Note: Connect and creation is handled as part of the update loop }
private void RemoteManagerUnity_OnSessionUpdate(RemoteManagerUnity.SessionUpdate update) { // Were we just disconnected? if (update == RemoteManagerUnity.SessionUpdate.SessionDisconnected) { // Destroy all faces DestroyFaces((ClippingBoxFaces)ClippingBoxFaceGroups.All); // Set last faces to none, so on the next connect the right ones will be created lastFaces = (ClippingBoxFaces)ClippingBoxFaceGroups.None; } // Note: Connect and creation is handled as part of the update loop }
/// <summary> /// Performs the specified action for the specific faces. /// </summary> /// <param name="faces"> /// The faces to match. /// </param> /// <param name="action"> /// The action to perform. /// </param> private void ForSpecificFaces(ClippingBoxFaces faces, Action <ClippingBoxFaces, GameObject> action) { // Loop through all enum values foreach (ClippingBoxFaces face in Enum.GetValues(typeof(ClippingBoxFaces))) { // But only if this flag was passed in if (faces.HasFlag(face)) { // And only if it's alive if (faceObjects.ContainsKey(face)) { // Perform the action action(face, faceObjects[face]); } } } }
/// <summary> /// Creates the specified faces. /// </summary> /// <param name="faces"> /// The faces to create. /// </param> private void CreateFaces(ClippingBoxFaces faces) { // Loop through all values foreach (ClippingBoxFaces face in Enum.GetValues(typeof(ClippingBoxFaces))) { // Is this face being passed in? if (faces.HasFlag(face)) { // Only create if not already alive if (!faceObjects.ContainsKey(face)) { // Create the object GameObject faceObject = new GameObject(Enum.GetName(typeof(ClippingBoxFaces), face)); // Parent it faceObject.transform.SetParent(transform, worldPositionStays: false); // Create the component ARRCutPlaneComponent cutPlane = faceObject.CreateArrComponent <ARRCutPlaneComponent>(RemoteManagerUnity.CurrentSession); // Configure it if (cutPlane.RemoteComponent != null) { cutPlane.RemoteComponent.Normal = FaceToNormal(face); cutPlane.RemoteComponent.FadeLength = .0000025f; cutPlane.RemoteComponent.FadeColor = new Color4Ub(0, 0, 75, 255); } RemoteEntitySyncObject syncObject = faceObject.GetComponent <RemoteEntitySyncObject>(); if (syncObject != null) { syncObject.SyncEveryFrame = true; } // Add it to the active list faceObjects[face] = faceObject; } } } }