예제 #1
0
        protected override bool DetectSetup()
        {
            finalDirection = direction;
            SetConstraints(finalDirection);

            return(true);
        }
예제 #2
0
        private float CalculateValue()
        {
            if (!subDirectionFound)
            {
                float angleX = Mathf.Abs(transform.localRotation.eulerAngles.x - initialLocalRotation.x) % 90;
                float angleY = Mathf.Abs(transform.localRotation.eulerAngles.y - initialLocalRotation.y) % 90;
                float angleZ = Mathf.Abs(transform.localRotation.eulerAngles.z - initialLocalRotation.z) % 90;
                angleX = (Mathf.RoundToInt(angleX) >= 89) ? 0 : angleX;
                angleY = (Mathf.RoundToInt(angleY) >= 89) ? 0 : angleY;
                angleZ = (Mathf.RoundToInt(angleZ) >= 89) ? 0 : angleZ;

                if (Mathf.RoundToInt(angleX) != 0 || Mathf.RoundToInt(angleY) != 0 || Mathf.RoundToInt(angleZ) != 0)
                {
                    subDirection      = angleX < angleY ? (angleY < angleZ ? KnobDirection.z : KnobDirection.y) : (angleX < angleZ ? KnobDirection.z : KnobDirection.x);
                    subDirectionFound = true;
                }
            }

            float angle = 0;

            switch (subDirection)
            {
            case KnobDirection.x:
                angle = transform.localRotation.eulerAngles.x - initialLocalRotation.x;
                break;

            case KnobDirection.y:
                angle = transform.localRotation.eulerAngles.y - initialLocalRotation.y;
                break;

            case KnobDirection.z:
                angle = transform.localRotation.eulerAngles.z - initialLocalRotation.z;
                break;
            }
            angle = Mathf.Round(angle * 1000f) / 1000f; // not rounding will produce slight offsets in 4th digit that mess up initial value

            // Quaternion.angle will calculate shortest route and only go to 180
            float value = 0;

            if (angle > 0 && angle <= 180)
            {
                value = 360 - Quaternion.Angle(initialRotation, transform.rotation);
            }
            else
            {
                value = Quaternion.Angle(initialRotation, transform.rotation);
            }

            // adjust to value scale
            value = Mathf.Round((min + Mathf.Clamp01(value / 360f) * (max - min)) / stepSize) * stepSize;
            if (min > max && angle != 0)
            {
                value = (max + min) - value;
            }

            return(value);
        }
예제 #3
0
        private KnobDirection DetectDirection()
        {
            KnobDirection direction = KnobDirection.x;
            Bounds        bounds    = Utilities.GetBounds(transform);

            // shoot rays in all directions to learn about surroundings
            RaycastHit hitForward;
            RaycastHit hitBack;
            RaycastHit hitLeft;
            RaycastHit hitRight;
            RaycastHit hitUp;
            RaycastHit hitDown;

            Physics.Raycast(bounds.center, Vector3.forward, out hitForward, bounds.extents.z * MAX_AUTODETECT_KNOB_WIDTH, Physics.DefaultRaycastLayers, QueryTriggerInteraction.UseGlobal);
            Physics.Raycast(bounds.center, Vector3.back, out hitBack, bounds.extents.z * MAX_AUTODETECT_KNOB_WIDTH, Physics.DefaultRaycastLayers, QueryTriggerInteraction.UseGlobal);
            Physics.Raycast(bounds.center, Vector3.left, out hitLeft, bounds.extents.x * MAX_AUTODETECT_KNOB_WIDTH, Physics.DefaultRaycastLayers, QueryTriggerInteraction.UseGlobal);
            Physics.Raycast(bounds.center, Vector3.right, out hitRight, bounds.extents.x * MAX_AUTODETECT_KNOB_WIDTH, Physics.DefaultRaycastLayers, QueryTriggerInteraction.UseGlobal);
            Physics.Raycast(bounds.center, Vector3.up, out hitUp, bounds.extents.y * MAX_AUTODETECT_KNOB_WIDTH, Physics.DefaultRaycastLayers, QueryTriggerInteraction.UseGlobal);
            Physics.Raycast(bounds.center, Vector3.down, out hitDown, bounds.extents.y * MAX_AUTODETECT_KNOB_WIDTH, Physics.DefaultRaycastLayers, QueryTriggerInteraction.UseGlobal);

            // shortest valid ray wins
            float lengthX    = (hitRight.collider != null) ? hitRight.distance : float.MaxValue;
            float lengthY    = (hitDown.collider != null) ? hitDown.distance : float.MaxValue;
            float lengthZ    = (hitBack.collider != null) ? hitBack.distance : float.MaxValue;
            float lengthNegX = (hitLeft.collider != null) ? hitLeft.distance : float.MaxValue;
            float lengthNegY = (hitUp.collider != null) ? hitUp.distance : float.MaxValue;
            float lengthNegZ = (hitForward.collider != null) ? hitForward.distance : float.MaxValue;

            // TODO: not yet the right decision strategy, works only partially
            if (Utilities.IsLowest(lengthX, new float[] { lengthY, lengthZ, lengthNegX, lengthNegY, lengthNegZ }))
            {
                direction = KnobDirection.z;
            }
            else if (Utilities.IsLowest(lengthY, new float[] { lengthX, lengthZ, lengthNegX, lengthNegY, lengthNegZ }))
            {
                direction = KnobDirection.y;
            }
            else if (Utilities.IsLowest(lengthZ, new float[] { lengthX, lengthY, lengthNegX, lengthNegY, lengthNegZ }))
            {
                direction = KnobDirection.x;
            }
            else if (Utilities.IsLowest(lengthNegX, new float[] { lengthX, lengthY, lengthZ, lengthNegY, lengthNegZ }))
            {
                direction = KnobDirection.z;
            }
            else if (Utilities.IsLowest(lengthNegY, new float[] { lengthX, lengthY, lengthZ, lengthNegX, lengthNegZ }))
            {
                direction = KnobDirection.y;
            }
            else if (Utilities.IsLowest(lengthNegZ, new float[] { lengthX, lengthY, lengthZ, lengthNegX, lengthNegY }))
            {
                direction = KnobDirection.x;
            }

            return(direction);
        }
예제 #4
0
        protected override bool DetectSetup()
        {
            finalDirection = direction;

            if (cjCreated)
            {
                cj.angularXMotion = ConfigurableJointMotion.Locked;
                cj.angularYMotion = ConfigurableJointMotion.Locked;
                cj.angularZMotion = ConfigurableJointMotion.Locked;

                switch (finalDirection)
                {
                case KnobDirection.x:
                    cj.angularXMotion = ConfigurableJointMotion.Free;
                    break;

                case KnobDirection.y:
                    cj.angularYMotion = ConfigurableJointMotion.Free;
                    break;

                case KnobDirection.z:
                    cj.angularZMotion = ConfigurableJointMotion.Free;
                    break;
                }
            }

            if (cj)
            {
                cj.xMotion = ConfigurableJointMotion.Locked;
                cj.yMotion = ConfigurableJointMotion.Locked;
                cj.zMotion = ConfigurableJointMotion.Locked;

                if (connectedTo)
                {
                    cj.connectedBody = connectedTo.GetComponent <Rigidbody>();
                }
            }

            return(true);
        }
예제 #5
0
        protected override bool DetectSetup()
        {
            finalDirection = direction;

            if (cjCreated)
            {
                cj.angularXMotion = ConfigurableJointMotion.Locked;
                cj.angularYMotion = ConfigurableJointMotion.Locked;
                cj.angularZMotion = ConfigurableJointMotion.Locked;

                switch (finalDirection)
                {
                    case KnobDirection.x:
                        cj.angularXMotion = ConfigurableJointMotion.Free;
                        break;
                    case KnobDirection.y:
                        cj.angularYMotion = ConfigurableJointMotion.Free;
                        break;
                    case KnobDirection.z:
                        cj.angularZMotion = ConfigurableJointMotion.Free;
                        break;
                }
            }

            if (cj)
            {
                cj.xMotion = ConfigurableJointMotion.Locked;
                cj.yMotion = ConfigurableJointMotion.Locked;
                cj.zMotion = ConfigurableJointMotion.Locked;

                if (connectedTo)
                {
                    cj.connectedBody = connectedTo.GetComponent<Rigidbody>();
                }
            }

            return true;
        }
예제 #6
0
        private void SetConstraints(KnobDirection direction)
        {
            if (!rb)
            {
                return;
            }

            rb.constraints = RigidbodyConstraints.FreezeAll;
            switch (direction)
            {
            case KnobDirection.x:
                rb.constraints -= RigidbodyConstraints.FreezeRotationX;
                break;

            case KnobDirection.y:
                rb.constraints -= RigidbodyConstraints.FreezeRotationY;
                break;

            case KnobDirection.z:
                rb.constraints -= RigidbodyConstraints.FreezeRotationZ;
                break;
            }
        }
예제 #7
0
        private KnobDirection DetectDirection()
        {
            KnobDirection direction = KnobDirection.x;
            Bounds bounds = Utilities.GetBounds(transform);

            // shoot rays in all directions to learn about surroundings
            RaycastHit hitForward;
            RaycastHit hitBack;
            RaycastHit hitLeft;
            RaycastHit hitRight;
            RaycastHit hitUp;
            RaycastHit hitDown;
            Physics.Raycast(bounds.center, Vector3.forward, out hitForward, bounds.extents.z * MAX_AUTODETECT_KNOB_WIDTH, Physics.DefaultRaycastLayers, QueryTriggerInteraction.UseGlobal);
            Physics.Raycast(bounds.center, Vector3.back, out hitBack, bounds.extents.z * MAX_AUTODETECT_KNOB_WIDTH, Physics.DefaultRaycastLayers, QueryTriggerInteraction.UseGlobal);
            Physics.Raycast(bounds.center, Vector3.left, out hitLeft, bounds.extents.x * MAX_AUTODETECT_KNOB_WIDTH, Physics.DefaultRaycastLayers, QueryTriggerInteraction.UseGlobal);
            Physics.Raycast(bounds.center, Vector3.right, out hitRight, bounds.extents.x * MAX_AUTODETECT_KNOB_WIDTH, Physics.DefaultRaycastLayers, QueryTriggerInteraction.UseGlobal);
            Physics.Raycast(bounds.center, Vector3.up, out hitUp, bounds.extents.y * MAX_AUTODETECT_KNOB_WIDTH, Physics.DefaultRaycastLayers, QueryTriggerInteraction.UseGlobal);
            Physics.Raycast(bounds.center, Vector3.down, out hitDown, bounds.extents.y * MAX_AUTODETECT_KNOB_WIDTH, Physics.DefaultRaycastLayers, QueryTriggerInteraction.UseGlobal);

            // shortest valid ray wins
            float lengthX = (hitRight.collider != null) ? hitRight.distance : float.MaxValue;
            float lengthY = (hitDown.collider != null) ? hitDown.distance : float.MaxValue;
            float lengthZ = (hitBack.collider != null) ? hitBack.distance : float.MaxValue;
            float lengthNegX = (hitLeft.collider != null) ? hitLeft.distance : float.MaxValue;
            float lengthNegY = (hitUp.collider != null) ? hitUp.distance : float.MaxValue;
            float lengthNegZ = (hitForward.collider != null) ? hitForward.distance : float.MaxValue;

            // TODO: not yet the right decision strategy, works only partially
            if (Utilities.IsLowest(lengthX, new float[] { lengthY, lengthZ, lengthNegX, lengthNegY, lengthNegZ }))
            {
                direction = KnobDirection.z;
            }
            else if (Utilities.IsLowest(lengthY, new float[] { lengthX, lengthZ, lengthNegX, lengthNegY, lengthNegZ }))
            {
                direction = KnobDirection.y;
            }
            else if (Utilities.IsLowest(lengthZ, new float[] { lengthX, lengthY, lengthNegX, lengthNegY, lengthNegZ }))
            {
                direction = KnobDirection.x;
            }
            else if (Utilities.IsLowest(lengthNegX, new float[] { lengthX, lengthY, lengthZ, lengthNegY, lengthNegZ }))
            {
                direction = KnobDirection.z;
            }
            else if (Utilities.IsLowest(lengthNegY, new float[] { lengthX, lengthY, lengthZ, lengthNegX, lengthNegZ }))
            {
                direction = KnobDirection.y;
            }
            else if (Utilities.IsLowest(lengthNegZ, new float[] { lengthX, lengthY, lengthZ, lengthNegX, lengthNegY }))
            {
                direction = KnobDirection.x;
            }

            return direction;
        }
예제 #8
0
        private float CalculateValue()
        {
            if (!subDirectionFound)
            {
                float angleX = Mathf.Abs(transform.localRotation.eulerAngles.x - initialLocalRotation.x) % 90;
                float angleY = Mathf.Abs(transform.localRotation.eulerAngles.y - initialLocalRotation.y) % 90;
                float angleZ = Mathf.Abs(transform.localRotation.eulerAngles.z - initialLocalRotation.z) % 90;
                angleX = (Mathf.RoundToInt(angleX) >= 89) ? 0 : angleX;
                angleY = (Mathf.RoundToInt(angleY) >= 89) ? 0 : angleY;
                angleZ = (Mathf.RoundToInt(angleZ) >= 89) ? 0 : angleZ;

                if (Mathf.RoundToInt(angleX) != 0 || Mathf.RoundToInt(angleY) != 0 || Mathf.RoundToInt(angleZ) != 0)
                {
                    subDirection = angleX < angleY ? (angleY < angleZ ? KnobDirection.z : KnobDirection.y) : (angleX < angleZ ? KnobDirection.z : KnobDirection.x);
                    subDirectionFound = true;
                }
            }

            float angle = 0;
            switch (subDirection)
            {
                case KnobDirection.x:
                    angle = transform.localRotation.eulerAngles.x - initialLocalRotation.x;
                    break;
                case KnobDirection.y:
                    angle = transform.localRotation.eulerAngles.y - initialLocalRotation.y;
                    break;
                case KnobDirection.z:
                    angle = transform.localRotation.eulerAngles.z - initialLocalRotation.z;
                    break;
            }
            angle = Mathf.Round(angle * 1000f) / 1000f; // not rounding will produce slight offsets in 4th digit that mess up initial value

            // Quaternion.angle will calculate shortest route and only go to 180
            float value = 0;
            if (angle > 0 && angle <= 180)
            {
                value = 360 - Quaternion.Angle(initialRotation, transform.rotation);
            }
            else
            {
                value = Quaternion.Angle(initialRotation, transform.rotation);
            }

            // adjust to value scale
            value = Mathf.Round((min + Mathf.Clamp01(value / 360f) * (max - min)) / stepSize) * stepSize;
            if (min > max && angle != 0)
            {
                value = (max + min) - value;
            }

            return value;
        }