void FixedUpdate() { Vector3 worldAxis = transform.TransformDirection(Axis); Vector3 end = transform.position + worldAxis * MaxDistance; float m_CurrentDistance = (transform.position - m_StartPosition).magnitude; RaycastHit info; float move = 0.0f; if (m_Rigidbody.SweepTest(-worldAxis, out info, ReturnSpeed * Time.deltaTime + 0.005f)) {//hitting something, if the contact is < mean we are pressed, move downward move = (ReturnSpeed * Time.deltaTime) - info.distance; } else { move -= ReturnSpeed * Time.deltaTime; } float newDistance = Mathf.Clamp(m_CurrentDistance + move, 0, MaxDistance); m_Rigidbody.position = m_StartPosition + worldAxis * newDistance; if (!m_Pressed && Mathf.Approximately(newDistance, MaxDistance)) { // Was just pressed m_Pressed = true; buttonPressAudioBlock.PlayIfNotNull(); } else if (m_Pressed && !Mathf.Approximately(newDistance, MaxDistance)) { // Was just released m_Pressed = false; buttonReleaseAudioBlock.PlayIfNotNull(); OnButtonReleased.Invoke(); } }
public override void ProcessInteractable(XRInteractionUpdateOrder.UpdatePhase updatePhase) { if (isSelected) { if (updatePhase == XRInteractionUpdateOrder.UpdatePhase.Fixed) { m_StartingWorldAxis = m_OriginalTransform.TransformDirection(LocalAxisStart); Vector3 worldAxisStart = m_SyncTransform.TransformDirection(LocalAxisStart); Vector3 worldRotationAxis = m_SyncTransform.TransformDirection(LocalRotationAxis); float angle = 0.0f; Vector3 newRight = worldAxisStart; if (DialType == InteractionType.ControllerRotation) { Quaternion difference = m_GrabbingInteractor.transform.rotation * Quaternion.Inverse(m_GrabbedRotation); newRight = difference * worldAxisStart; //get the new angle between the original right and this new right along the up axis angle = Vector3.SignedAngle(m_StartingWorldAxis, newRight, worldRotationAxis); if (angle < 0) { angle = 360 + angle; } } else { Vector3 centerToController = m_GrabbingInteractor.transform.position - transform.position; centerToController.Normalize(); newRight = centerToController; angle = Vector3.SignedAngle(m_StartingWorldAxis, newRight, worldRotationAxis); if (angle < 0) { angle = 360 + angle; } } //if the angle is < 0 or > to the max rotation, we clamp but TO THE CLOSEST (a simple clamp would clamp // of an angle of 350 for a 0-180 angle range would clamp to 180, when we want to clamp to 0) if (angle > RotationAngleMaximum) { float upDiff = 360 - angle; float lowerDiff = angle - RotationAngleMaximum; if (upDiff < lowerDiff) { angle = 0; } else { angle = RotationAngleMaximum; } } float finalAngle = angle; if (!SnapOnRelease && Steps > 0) { int step = Mathf.RoundToInt(angle / m_StepSize); finalAngle = step * m_StepSize; if (!Mathf.Approximately(finalAngle, m_CurrentAngle)) { snapAudioBlock.PlayIfNotNull(); OnDialStepChanged.Invoke(step); OnDialChanged.Invoke(this); m_CurrentStep = step; } } //first, we use the raw angle to move the sync transform, that allow to keep the proper current rotation //even if we snap during rotation newRight = Quaternion.AngleAxis(angle, worldRotationAxis) * m_StartingWorldAxis; angle = Vector3.SignedAngle(worldAxisStart, newRight, worldRotationAxis); Quaternion newRot = Quaternion.AngleAxis(angle, worldRotationAxis) * m_SyncTransform.rotation; //then we redo it but this time using finalAngle, that will snap if needed. newRight = Quaternion.AngleAxis(finalAngle, worldRotationAxis) * m_StartingWorldAxis; m_CurrentAngle = finalAngle; OnDialAngleChanged.Invoke(finalAngle); OnDialChanged.Invoke(this); finalAngle = Vector3.SignedAngle(worldAxisStart, newRight, worldRotationAxis); Quaternion newRBRotation = Quaternion.AngleAxis(finalAngle, worldRotationAxis) * m_SyncTransform.rotation; if (RotatingRigidbody != null) { RotatingRigidbody.MoveRotation(newRBRotation); } else { transform.rotation = newRBRotation; } m_SyncTransform.transform.rotation = newRot; m_GrabbedRotation = m_GrabbingInteractor.transform.rotation; } } }
public override void ProcessInteractable(XRInteractionUpdateOrder.UpdatePhase updatePhase) { if (isSelected) { if (updatePhase == XRInteractionUpdateOrder.UpdatePhase.Fixed) { Vector3 WorldAxis = transform.TransformDirection(LocalAxis); Vector3 distance = m_GrabbingInteractor.transform.position - transform.position - m_GrabbedOffset; float projected = Vector3.Dot(distance, WorldAxis); //ajust projected to clamp it to steps if there is steps if (Steps != 0 && !SnapOnlyOnRelease) { int steps = Mathf.RoundToInt(projected / m_StepLength); projected = steps * m_StepLength; } Vector3 targetPoint; if (projected > 0) { targetPoint = Vector3.MoveTowards(transform.position, m_EndPoint, projected); } else { targetPoint = Vector3.MoveTowards(transform.position, m_StartPoint, -projected); } if (Steps > 0) { int posStep = Mathf.RoundToInt((targetPoint - m_StartPoint).magnitude / m_StepLength); if (posStep != m_CurrentStep) { snapAudioBlock.PlayIfNotNull(); OnDragStep.Invoke(posStep); } m_CurrentStep = posStep; } OnDragDistance.Invoke((targetPoint - m_StartPoint).magnitude); Vector3 move = targetPoint - transform.position; if (MovingRigidbody != null) { MovingRigidbody.MovePosition(MovingRigidbody.position + move); } else { transform.position = transform.position + move; } } } else { if (ReturnOnFree) { Vector3 targetPoint = Vector3.MoveTowards(transform.position, m_StartPoint, ReturnSpeed * Time.deltaTime); Vector3 move = targetPoint - transform.position; if (MovingRigidbody != null) { MovingRigidbody.MovePosition(MovingRigidbody.position + move); } else { transform.position = transform.position + move; } } } }