Exemplo n.º 1
0
    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;
                }
            }
        }
    }