/// <summary> /// Ends the movement session if a session was previously active. /// </summary> /// <param name="forceEnd"> Forces the movement to end and not return pending if it's true. </param> public void EndMovementSession(bool forceEnd = false) { if (movementSessionState == MovementSessionState.ShutDown) { Debug.LogWarning("MLMovementBehavior.EndMovementSession failed to end the movement session. Reason: Movement session was never started."); return; } if (forceEnd) { EndAllCollisions(CollisionType.All); } else { EndAllCollisions(CollisionType.Hard); } #if PLATFORM_LUMIN // Passing float.MaxValue if forceEnd is true to ensure movement ends with a Timeout result. MLResult result = MLMovement.End(sessionHandle, forceEnd ? float.MaxValue : Time.deltaTime, out sessionObject); if (result.IsOk || result.Result == MLResult.Code.Pending) { if (AllowCollision) { objectRigidbody.position = sessionObject.ObjectPosition; objectRigidbody.rotation = sessionObject.ObjectRotation.normalized; objectRigidbody.velocity = Vector3.zero; objectRigidbody.angularVelocity = Vector3.zero; } else { transform.position = sessionObject.ObjectPosition; transform.rotation = sessionObject.ObjectRotation.normalized; } if (result.IsOk) { sessionHandle = UnityEngine.XR.MagicLeap.Native.MagicLeapNativeBindings.InvalidHandle; movementSessionState = MovementSessionState.ShutDown; } else { movementSessionState = MovementSessionState.PendingShutDown; } } else if (result.Result == MLResult.Code.Timeout) { hardCollisionMap.Clear(); softCollisionMap.Clear(); sessionHandle = UnityEngine.XR.MagicLeap.Native.MagicLeapNativeBindings.InvalidHandle; movementSessionState = MovementSessionState.ShutDown; } else { Debug.LogErrorFormat("MLMovementBehavior.EndMovementSession failed to end the movement session, disabling script. Reason: {0}", result); enabled = false; return; } #endif }
/// <summary> /// Updates an existing hard collision session with new info. /// </summary> /// <param name="collision">The latest collision data.</param> void UpdateHardCollision(ref Collision collision) { #if PLATFORM_LUMIN int objId = collision.gameObject.GetInstanceID(); MLResult result = MLMovement.UpdateHardCollision(sessionHandle, hardCollisionMap[objId], collision.contacts[0].normal); if (!result.IsOk) { Debug.LogErrorFormat("MLMovementBehavior.UpdateHardCollision failed to update a hard collision, disabling script. Reason: {0}", result); enabled = false; return; } #endif }
/// <summary> /// Ends the collision matching the id and handle passed. /// </summary> /// <param name="collisionId">The id of the collider object.</param> /// <param name="collisionHandle">The handle for the collision session.</param> void EndCollision(CollisionType type, int collisionId, ulong collisionHandle) { if (type == CollisionType.Hard) { hardCollisionMap.Remove(collisionId); } else if (type == CollisionType.Soft) { softCollisionMap.Remove(collisionId); } #if PLATFORM_LUMIN MLResult result = MLMovement.EndCollision(sessionHandle, collisionHandle); if (!result.IsOk) { Debug.LogErrorFormat("MLMovementBehavior.EndCollision failed to end collision session, disabling script. Reason: {0}", result); enabled = false; } #endif }
/// <summary> /// Starts a new soft collision session given some collider data. /// </summary> /// <param name="other">The collider data.</param> void StartSoftCollision(ref Collider other) { #if PLATFORM_LUMIN ulong collisionHandle = UnityEngine.XR.MagicLeap.Native.MagicLeapNativeBindings.InvalidHandle; Vector3 thisCenter = objectCollider.bounds.center; Vector3 otherCenter = other.bounds.center; float maxDistance = Vector3.Distance(thisCenter, otherCenter); float closesetDistance = maxDistance * (other.gameObject.GetComponent <MLMovementColliderBehavior>().MaxDepth / 100.0f); MLResult result = MLMovement.StartSoftCollision(sessionHandle, otherCenter, closesetDistance, maxDistance, out collisionHandle); if (!result.IsOk) { Debug.LogErrorFormat("MLMovementBehavior.StartSoftCollision failed to start a soft collision, disabling script. Reason: {0}", result); enabled = false; return; } softCollisionMap.Add(other.gameObject.GetInstanceID(), collisionHandle); #endif }
/// <summary> /// Ends all collision sessions currently running. /// </summary> void EndAllCollisions(CollisionType type) { #if PLATFORM_LUMIN MLResult result; #endif if (type.HasFlag(CollisionType.Hard)) { foreach (KeyValuePair <int, ulong> collision in hardCollisionMap) { #if PLATFORM_LUMIN result = MLMovement.EndCollision(sessionHandle, collision.Value); if (!result.IsOk) { Debug.LogErrorFormat("MLMovementBehavior.EndAllCollisions failed to end hard collision session, disabling script. Reason: {0}", result); enabled = false; return; } #endif } hardCollisionMap.Clear(); } if (type.HasFlag(CollisionType.Soft)) { foreach (KeyValuePair <int, ulong> collision in softCollisionMap) { #if PLATFORM_LUMIN result = MLMovement.EndCollision(sessionHandle, collision.Value); if (!result.IsOk) { Debug.LogErrorFormat("MLMovementBehavior.EndAllCollisions failed to end soft collision session, disabling script. Reason: {0}", result); enabled = false; return; } #endif } softCollisionMap.Clear(); } }
/// <summary> /// Updates object and movement session with latest data and applies depth and rotation changes /// to the object. /// </summary> void Update() { if (movementSessionState == MovementSessionState.Running) { #if PLATFORM_LUMIN MLResult result; if (UseTouchForRotation && ControllerHandler.ConnectedController != null && ControllerHandler.ConnectedController.CurrentTouchpadGesture.Type == MLInput.Controller.TouchpadGesture.GestureType.RadialScroll) { float deltaRadians = 0.0f; Vector2 newPos = new Vector2(ControllerHandler.ConnectedController.Touch1PosAndForce.x, ControllerHandler.ConnectedController.Touch1PosAndForce.y); if (ControllerHandler.ConnectedController.CurrentTouchpadGesture.Direction == MLInput.Controller.TouchpadGesture.GestureDirection.Clockwise) { deltaRadians = Mathf.Min(Vector2.SignedAngle(previousTouchPosition, newPos), MaxRotationDelta) * Mathf.Deg2Rad; } else { deltaRadians = Mathf.Max(Vector2.SignedAngle(previousTouchPosition, newPos), -MaxRotationDelta) * Mathf.Deg2Rad; } previousTouchPosition = newPos; result = MLMovement.ChangeRotation(sessionHandle, deltaRadians); if (!result.IsOk) { Debug.LogErrorFormat("MLMovementBehavior.Update failed to change the object rotation in movement session, disabling script. Reason: {0}", result); enabled = false; return; } } else if (UseTouchForDepth && ControllerHandler.ConnectedController != null && ControllerHandler.ConnectedController.Touch1Active && Mathf.Abs(ControllerHandler.ConnectedController.Touch1PosAndForce.y) > Mathf.Abs(ControllerHandler.ConnectedController.Touch1PosAndForce.x)) { float unsignedDepthDelta = MaxDepthDelta * Mathf.Pow(ControllerHandler.ConnectedController.Touch1PosAndForce.z, 3.0f); result = MLMovement.ChangeDepth(sessionHandle, (ControllerHandler.ConnectedController.Touch1PosAndForce.y > 0.0f) ? unsignedDepthDelta : -unsignedDepthDelta); if (!result.IsOk) { Debug.LogErrorFormat("MLMovementBehavior.Update failed to change the object depth in movement session, disabling script. Reason: {0}", result); enabled = false; return; } } #endif switch (sessionInteractionMode) { case MovementInteractionMode.ThreeDof: { #if PLATFORM_LUMIN session3DofControls.HeadposePosition = mainCamera.transform.position; if (sessionInputDriverType == MovementInputDriverType.Controller) { session3DofControls.ControlRotation = (ControllerHandler.ConnectedController != null) ? ControllerHandler.ConnectedController.Orientation.normalized : Quaternion.identity; } else { session3DofControls.ControlRotation = mainCamera.transform.rotation.normalized; } result = MLMovement.Update3Dof(sessionHandle, in session3DofControls, Time.deltaTime, ref sessionObject); if (!result.IsOk) { Debug.LogErrorFormat("MLMovementBehavior.Update failed to update the current 3dof movement session, disabling script. Reason: {0}", result); enabled = false; return; } #endif break; } case MovementInteractionMode.SixDof: { #if PLATFORM_LUMIN session6DofControls.HeadposePosition = mainCamera.transform.position; session6DofControls.HeadposeRotation = mainCamera.transform.rotation.normalized; if (sessionInputDriverType == MovementInputDriverType.Controller) { session6DofControls.ControlPosition = (ControllerHandler.ConnectedController != null) ? ControllerHandler.ConnectedController.Position : Vector3.zero; session6DofControls.ControlRotation = (ControllerHandler.ConnectedController != null) ? ControllerHandler.ConnectedController.Orientation.normalized : Quaternion.identity; } else { session6DofControls.ControlPosition = mainCamera.transform.position; session6DofControls.ControlRotation = mainCamera.transform.rotation.normalized; } result = MLMovement.Update6Dof(sessionHandle, in session6DofControls, Time.deltaTime, ref sessionObject); if (!result.IsOk) { Debug.LogErrorFormat("MLMovementBehavior.Update failed to update the current 6dof movement session, disabling script. Reason: {0}", result); enabled = false; return; } #endif break; } default: { Debug.LogError("MLMovementBehavior.Update failed to update the movement session, disabling script. Reason: Invalid InteractionMode parameter."); enabled = false; return; } } if (AllowCollision) { #if PLATFORM_LUMIN objectRigidbody.position = sessionObject.ObjectPosition; objectRigidbody.rotation = sessionObject.ObjectRotation.normalized; #endif objectRigidbody.velocity = Vector3.zero; objectRigidbody.angularVelocity = Vector3.zero; } else { #if PLATFORM_LUMIN transform.position = sessionObject.ObjectPosition; transform.rotation = sessionObject.ObjectRotation.normalized; #endif } } else if (movementSessionState == MovementSessionState.PendingShutDown) { EndMovementSession(); } }