Esempio n. 1
0
        public IEnumerator ForceGrab(HVRGrabbable grabbable)
        {
            var needsCollisionEnabled = true;
            var grabPoint             = grabbable.GetForceGrabPoint(HandGrabber.HandSide) ?? grabbable.transform;

            try
            {
                HandGrabber.DisableHandCollision(grabbable);

                _grabbableCollided = false;
                IsHoldActive       = true;


                grabbable.IsBeingForcedGrabbed = true;
                grabbable.Rigidbody.useGravity = false;
                grabbable.Rigidbody.drag       = 0f;

                fts.solve_ballistic_arc_lateral(false,
                                                grabPoint.position,
                                                ForceTime,
                                                JointAnchorWorldPosition,
                                                JointAnchorWorldPosition.y + YOffset,
                                                out var velocity,
                                                out var gravity);

                grabbable.Rigidbody.velocity = velocity;

                var elapsed = 0f;

                var targetRotation    = grabbable.GetForceGrabPointRotation(HandGrabber.HandSide);
                var startHandRotation = HandGrabber.HandWorldRotation;

                while (GrabbedTarget)
                {
                    if (elapsed > ForceTime)
                    {
                        break;
                    }

                    var currentVector = JointAnchorWorldPosition - grabPoint.position;

                    currentVector.y = 0;

                    var percentTime = elapsed / ForceTime;
                    var yExtra      = YOffset * (1 - percentTime);

                    if (percentTime < .3)
                    {
                        _grabbableCollided = false;
                    }
                    else if (_grabbableCollided)
                    {
                        if (grabbable.Rigidbody.velocity.magnitude > MaximumVelocityPostCollision)
                        {
                            grabbable.Rigidbody.velocity = grabbable.Rigidbody.velocity.normalized * MaximumVelocityPostCollision;
                        }
                        ForceRelease();
                        //Debug.Log($"Collided while force grabbing.");
                        break;
                    }


                    fts.solve_ballistic_arc_lateral(
                        false,
                        grabPoint.position,
                        ForceTime - elapsed,
                        JointAnchorWorldPosition,
                        JointAnchorWorldPosition.y + yExtra,
                        out velocity, out gravity);

                    grabbable.Rigidbody.velocity = velocity;
                    grabbable.Rigidbody.AddForce(-Vector3.up * gravity, ForceMode.Acceleration);

                    if (AutoGrab && (JointAnchorWorldPosition - grabPoint.position).magnitude < AutoGrabDistance)
                    {
                        if (HandGrabber.TryAutoGrab(GrabbedTarget))
                        {
                            needsCollisionEnabled = false;
                            IsForceGrabbing       = false;
                            break;
                        }
                    }

                    if (currentVector.magnitude < .1f)
                    {
                        //Debug.Log($"<.1f");
                        break;
                    }

                    var handDelta = Quaternion.Angle(HandGrabber.HandWorldRotation, startHandRotation);
                    if (Mathf.Abs(handDelta) > 20)
                    {
                        startHandRotation = HandGrabber.HandWorldRotation;
                    }

                    //todo
                    var delta = startHandRotation * Quaternion.Inverse(targetRotation);

                    delta.ToAngleAxis(out var angle, out var axis);

                    if (angle > 180.0f)
                    {
                        angle -= 360.0f;
                    }

                    var remaining = ForceTime - elapsed;

                    if (percentTime > .3f && Mathf.Abs(angle) > 1 && remaining > .01)
                    {
                        grabbable.Rigidbody.angularVelocity = axis * (angle * Mathf.Deg2Rad) / ForceTime;
                    }
                    else
                    {
                        grabbable.Rigidbody.angularVelocity = Vector3.zero;
                    }

                    elapsed += Time.fixedDeltaTime;
                    yield return(new WaitForFixedUpdate());
                }
            }
            finally
            {
                if (needsCollisionEnabled)
                {
                    HandGrabber.EnableHandCollision(grabbable);
                }

                IsHoldActive = false;
                grabbable.IsBeingForcedGrabbed = false;
                grabbable.Collided.RemoveListener(OnGrabbableCollided);
                grabbable.Grabbed.RemoveListener(OnGrabbableGrabbed);
                if (IsGrabbing)
                {
                    ForceRelease();
                }

                IsForceGrabbing = false;
            }

            if (AutoGrab && AdditionalAutoGrabTime > 0 && !grabbable.IsBeingHeld)
            {
                _additionalGrabRoutine = StartCoroutine(ContinueAutoGrab(grabbable, grabPoint));
            }
        }
Esempio n. 2
0
        public IEnumerator ForcePull(HVRGrabbable grabbable)
        {
            var rb          = grabbable.Rigidbody;
            var drag        = rb.drag;
            var angularDrag = rb.angularDrag;

            HandGrabber.DisableHandCollision(grabbable);

            rb.useGravity  = false;
            rb.drag        = 0f;
            rb.angularDrag = 0f;
            grabbable.IsBeingForcedGrabbed = true;
            IsHoldActive = true;

            var grabPoint        = grabbable.GetForceGrabPoint(HandGrabber.HandSide) ?? grabbable.transform;
            var posableGrabPoint = grabPoint.GetComponent <HVRPosableGrabPoint>();

            var isPhysicsGrab = grabbable.GrabType == HVRGrabType.PhysicPoser;

            if (!isPhysicsGrab && grabbable.GrabType != HVRGrabType.Offset)
            {
                var actualGrabPoint = HandGrabber.GetGrabPoint(grabbable);
                isPhysicsGrab = actualGrabPoint == null && grabbable.PhysicsPoserFallback;
            }


            var direction     = HandGrabber.JointAnchorWorldPosition - grabPoint.position;
            var startDistance = direction.magnitude;
            var distance      = startDistance;

            var settings = grabbable.ForcePullOverride ?? ForcePullSettings;

            var Spring   = settings.Spring;
            var Damper   = settings.Damper;
            var MaxForce = settings.MaxForce;

            var SlerpDamper   = settings.SlerpDamper;
            var SlerpMaxForce = settings.SlerpMaxForce;
            var SlerpSpring   = settings.SlerpSpring;

            var DynamicGrabThreshold = settings.DynamicGrabThreshold;
            var DistanceThreshold    = settings.DistanceThreshold;
            var Speed              = settings.Speed;
            var DistanceToRotate   = settings.RotateTriggerDistance;
            var RotateOverDistance = settings.RotateOverDistance;

            var MaxMissSpeed        = settings.MaxMissSpeed;
            var MaxMissAngularSpeed = settings.MaxMissAngularSpeed;

            _forceAnchor.transform.position = grabPoint.transform.position;
            _forceAnchor.transform.rotation = grabbable.transform.rotation;

            if (posableGrabPoint)
            {
                _forceAnchor.transform.rotation = posableGrabPoint.GetPoseWithJointRotation(HandSide);
            }

            var joint = _forceAnchor.AddComponent <ConfigurableJoint>();

            joint.autoConfigureConnectedAnchor = false;
            joint.rotationDriveMode            = RotationDriveMode.Slerp;
            joint.SetLinearDrive(Spring, Damper, MaxForce);
            joint.SetSlerpDrive(SlerpSpring, SlerpDamper, SlerpMaxForce);
            joint.connectedBody   = rb;
            joint.connectedAnchor = rb.transform.InverseTransformPoint(grabPoint.position);

            var limit = isPhysicsGrab ? DynamicGrabThreshold : DistanceThreshold;


            var rotating      = false;
            var rotateSpeed   = 0f;
            var elapsed       = 0f;
            var needsRotating = posableGrabPoint;

            while (GrabbedTarget && Inputs.GetForceGrabActive(HandSide) && distance > limit)
            {
                direction = HandGrabber.JointAnchorWorldPosition - grabPoint.position;
                distance  = direction.magnitude;

                if ((isPhysicsGrab || grabbable.GrabType == HVRGrabType.Offset) && distance < DynamicGrabThreshold && HandGrabber.TryAutoGrab(grabbable))
                {
                    rb.angularVelocity = Vector3.zero;
                    rb.velocity        = Vector3.zero;
                    break;
                }


                _forceAnchor.transform.position = Vector3.MoveTowards(_forceAnchor.transform.position, JointAnchorWorldPosition, Speed * Time.fixedDeltaTime);
                var dir = _forceAnchor.transform.position - grabPoint.position;
                if (dir.magnitude > .3f)
                {
                    _forceAnchor.transform.position = grabPoint.position + dir.normalized * .3f;
                }

                if (needsRotating && !rotating)
                {
                    if (settings.RotationTrigger == ForcePullRotationTrigger.DistanceToHand)
                    {
                        rotating = distance < DistanceToRotate && posableGrabPoint;
                    }
                    else if (settings.RotationTrigger == ForcePullRotationTrigger.PercentTraveled)
                    {
                        rotating = (startDistance - distance) / startDistance > settings.RotateTriggerPercent / 100f;
                    }
                    else if (settings.RotationTrigger == ForcePullRotationTrigger.TimeSinceStart)
                    {
                        rotating = elapsed > settings.RotateTriggerTime;
                    }

                    if (rotating)
                    {
                        if (settings.RotationStyle == ForceRotationStyle.RotateOverDistance)
                        {
                            var rotatateDistance = Mathf.Min(RotateOverDistance, distance);
                            var time             = rotatateDistance / Speed;
                            rotateSpeed = Quaternion.Angle(joint.transform.rotation, HandGrabber.HandWorldRotation) / time;
                        }
                        else if (settings.RotationStyle == ForceRotationStyle.RotateOverRemaining)
                        {
                            var time = distance / Speed;
                            rotateSpeed = Quaternion.Angle(joint.transform.rotation, HandGrabber.HandWorldRotation) / time;
                        }
                    }
                }

                if (rotating)
                {
                    joint.transform.rotation = Quaternion.RotateTowards(joint.transform.rotation, HandGrabber.HandWorldRotation, rotateSpeed * Time.fixedDeltaTime);
                }

                yield return(new WaitForFixedUpdate());

                elapsed += Time.fixedDeltaTime;
            }

            joint.connectedBody = null;
            Destroy(joint);

            IsForceGrabbing = false;
            IsHoldActive    = false;

            if (grabbable)
            {
                rb.useGravity      = true;
                rb.drag            = drag;
                rb.angularDrag     = angularDrag;
                rb.velocity        = Vector3.ClampMagnitude(rb.velocity, MaxMissSpeed);
                rb.angularVelocity = Vector3.ClampMagnitude(rb.angularVelocity, MaxMissAngularSpeed);

                if (IsGrabbing)
                {
                    direction = HandGrabber.JointAnchorWorldPosition - grabPoint.position;
                    if (direction.magnitude < limit)
                    {
                        if (HandGrabber.TryAutoGrab(grabbable))
                        {
                            rb.angularVelocity = Vector3.zero;
                            rb.velocity        = Vector3.zero;
                        }
                        else
                        {
                            HandGrabber.EnableHandCollision(grabbable);
                            ForceRelease();
                        }
                    }

                    grabbable.IsBeingForcedGrabbed = false;
                }
            }
        }