< Summary

Class:XRJoystick
Assembly:Test
File(s):E:/Unity/Unity Project/VR-Basics/Assets/_Course Library/Scripts/Core/XRJoystick.cs
Covered lines:24
Uncovered lines:67
Coverable lines:91
Total lines:215
Line coverage:26.3% (24 of 91)
Covered branches:0
Total branches:0
Covered methods:6
Total methods:16
Method coverage:37.5% (6 of 16)

Coverage History

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
XRJoystick()0%000100%
OnEnable()0%000100%
OnDisable()0%000100%
StartGrab(...)0%0000%
EndGrab(...)0%0000%
ResetRotation()0%0000%
ProcessInteractable(...)0%00030.77%
FindJoystickRotation(...)0%0000%
ConvertToLocal(...)0%0000%
GetRotationDifference(...)0%0000%
ApplyRotation(...)0%0000%
SetValue(...)0%0000%
CalculateValue(...)0%0000%
Normalize(...)0%0000%

File(s)

E:/Unity/Unity Project/VR-Basics/Assets/_Course Library/Scripts/Core/XRJoystick.cs

#LineLine coverage
 1using System;
 2using System.Diagnostics.CodeAnalysis;
 3using UnityEngine;
 4using UnityEngine.Events;
 5using UnityEngine.XR.Interaction.Toolkit;
 6using HenryLab;
 7
 8
 9/// <summary>
 10/// An interactable joystick that can move side to side, and forward and back by a direct interactor
 11/// </summary>
 12public class XRJoystick : XRBaseInteractable
 13{
 14    [ExcludeFromCodeCoverage] public float TriggeringTime => 4.5f;
 15    [ExcludeFromCodeCoverage] public string Name => Str.Transformable;
 16
 17    [ExcludeFromCodeCoverage]
 18    public void Triggerring()
 19    {
 20        var obj = EntityManager.Instance.vrexplorerMono.gameObject;
 21        XRDirectInteractor interactor;
 22        if(!obj.TryGetComponent(out interactor))
 23        {
 24            interactor = obj.AddComponent<XRDirectInteractor>();
 25        }
 26        if(!obj.GetComponent<ActionBasedController>())
 27        {
 28            obj.AddComponent<ActionBasedController>();
 29        }
 30        var e = new SelectEnterEventArgs() { interactorObject = interactor };
 31        StartGrab(e);
 32        selectEntered.Invoke(e);
 33    }
 34
 35    [ExcludeFromCodeCoverage]
 36    public void Triggerred()
 37    {
 38        var obj = EntityManager.Instance.vrexplorerMono.gameObject;
 39        XRDirectInteractor interactor;
 40        if(!obj.TryGetComponent(out interactor))
 41        {
 42            interactor = obj.AddComponent<XRDirectInteractor>();
 43        }
 44        if(!obj.GetComponent<ActionBasedController>())
 45        {
 46            obj.AddComponent<ActionBasedController>();
 47        }
 48
 49        OnXValueChange.Invoke(DeltaRotation.x);
 50        OnYValueChange.Invoke(DeltaRotation.y);
 51        Vector3 targetPosition = selectInteractor.transform.position;
 52        Vector3 newRotation = FindJoystickRotation(targetPosition);
 53        ApplyRotation(newRotation);
 54        SetValue(newRotation);
 55        var e = new SelectExitEventArgs() { interactorObject = interactor };
 56        EndGrab(e);
 57        selectExited.Invoke(e);
 58
 59    }
 60
 61    [ExcludeFromCodeCoverage] public Vector3 DeltaPosition => new Vector3(0, 0, 0);
 62
 63    [ExcludeFromCodeCoverage] public Vector3 DeltaRotation => new Vector3(90, 30, 0);
 64
 65    [ExcludeFromCodeCoverage] public Vector3 DeltaScale => new Vector3(0, 0, 0);
 66
 67    public enum JoystickType
 68    {
 69        None,
 70        Both,
 71        FrontBack,
 72        LeftRight,
 73    }
 74
 75    [Tooltip("Joystick sensitivity")]
 876    public float rateOfChange = 0.1f;
 77
 78    [Tooltip("Contols how the joystick behaves ")]
 879    public JoystickType leverType = JoystickType.Both;
 80
 81    [Tooltip("The transform of the visual component of the joystick")]
 882    public Transform handle = null;
 83
 84    [Serializable] public class ValueChangeEvent : UnityEvent<float> { }
 85
 86    // When the joystick's x value changes
 887    public ValueChangeEvent OnXValueChange = new ValueChangeEvent();
 88
 89    // When the joystick's y value changes
 890    public ValueChangeEvent OnYValueChange = new ValueChangeEvent();
 91
 892    public Vector2 Value { get; private set; } = Vector2.zero;
 93
 94
 95
 896    private IXRSelectInteractor selectInteractor = null;
 97
 898    private Vector3 initialPosition = Vector3.zero;
 99
 8100    private readonly int minRotation = -30;
 8101    private readonly int maxRotation = 30;
 102
 103    protected override void OnEnable()
 4104    {
 4105        base.OnEnable();
 4106        selectEntered.AddListener(StartGrab);
 4107        selectExited.AddListener(EndGrab);
 4108    }
 109
 110    protected override void OnDisable()
 4111    {
 4112        base.OnDisable();
 4113        selectEntered.RemoveListener(StartGrab);
 4114        selectExited.RemoveListener(EndGrab);
 4115    }
 116
 117    private void StartGrab(SelectEnterEventArgs eventArgs)
 0118    {
 0119        selectInteractor = eventArgs.interactorObject;
 0120        initialPosition = ConvertToLocal(selectInteractor.transform.position);
 0121    }
 122
 123    private void EndGrab(SelectExitEventArgs eventArgs)
 0124    {
 0125        selectInteractor = null;
 0126        ResetRotation();
 0127    }
 128
 129    private void ResetRotation()
 0130    {
 0131        handle.localRotation = Quaternion.identity;
 0132        initialPosition = Vector3.zero;
 0133        SetValue(Vector3.zero);
 0134    }
 135
 136    public override void ProcessInteractable(XRInteractionUpdateOrder.UpdatePhase updatePhase)
 14020137    {
 14020138        base.ProcessInteractable(updatePhase);
 139
 14020140        if(isSelected)
 0141        {
 0142            if(updatePhase == XRInteractionUpdateOrder.UpdatePhase.Dynamic)
 0143            {
 0144                Vector3 targetPosition = selectInteractor.transform.position;
 0145                Vector3 newRotation = FindJoystickRotation(targetPosition);
 146
 0147                ApplyRotation(newRotation);
 0148                SetValue(newRotation);
 0149            }
 0150        }
 14020151    }
 152
 153    private Vector3 FindJoystickRotation(Vector3 target)
 0154    {
 0155        Vector3 currentPosition = ConvertToLocal(target);
 0156        Vector3 positionDifference = currentPosition - initialPosition;
 0157        positionDifference.y = rateOfChange;
 158
 0159        Vector3 finalRotation = Vector3.zero;
 160
 0161        if(leverType == JoystickType.FrontBack || leverType == JoystickType.Both)
 0162        {
 0163            float xRotation = GetRotationDifference(positionDifference.y, positionDifference.z);
 0164            finalRotation.x = xRotation;
 0165        }
 166
 0167        if(leverType == JoystickType.LeftRight || leverType == JoystickType.Both)
 0168        {
 0169            float zRotation = GetRotationDifference(positionDifference.y, positionDifference.x);
 0170            finalRotation.z = zRotation;
 0171        }
 172
 0173        return finalRotation;
 0174    }
 175
 176    private Vector3 ConvertToLocal(Vector3 target)
 0177    {
 0178        return transform.InverseTransformPoint(target);
 0179    }
 180
 181    private float GetRotationDifference(float yRelative, float xRelative)
 0182    {
 0183        float difference = Mathf.Atan2(xRelative, yRelative) * Mathf.Rad2Deg;
 0184        difference = Mathf.Clamp(difference, minRotation, maxRotation);
 0185        return difference;
 0186    }
 187
 188    private void ApplyRotation(Vector3 newRotation)
 0189    {
 0190        newRotation.z *= -1;
 0191        handle.localRotation = Quaternion.Euler(newRotation);
 0192    }
 193
 194    private void SetValue(Vector3 rotation)
 0195    {
 0196        Value = CalculateValue(rotation);
 0197        OnXValueChange.Invoke(Value.x);
 0198        OnYValueChange.Invoke(Value.y);
 0199    }
 200
 201    private Vector2 CalculateValue(Vector3 rotation)
 0202    {
 0203        Vector2 newValue = Vector2.zero;
 0204        newValue.x = Normalize(rotation.z);
 0205        newValue.y = Normalize(rotation.x);
 0206        return newValue;
 0207    }
 208
 209    private float Normalize(float value)
 0210    {
 0211        value = Mathf.InverseLerp(minRotation, maxRotation, value);
 0212        value = Mathf.Lerp(-1, 1, value);
 0213        return value;
 0214    }
 215}