< Summary

Class:XRJoystick
Assembly:Test
File(s):E:/Unity/Unity Project/VR-Basics/Assets/_Course Library/Scripts/Core/XRJoystick.cs
Covered lines:82
Uncovered lines:9
Coverable lines:91
Total lines:215
Line coverage:90.1% (82 of 91)
Covered branches:0
Total branches:0
Covered methods:16
Total methods:16
Method coverage:100% (16 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%000100%
EndGrab(...)0%000100%
ResetRotation()0%000100%
ProcessInteractable(...)0%00030.77%
FindJoystickRotation(...)0%000100%
ConvertToLocal(...)0%000100%
GetRotationDifference(...)0%000100%
ApplyRotation(...)0%000100%
SetValue(...)0%000100%
CalculateValue(...)0%000100%
Normalize(...)0%000100%

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, ITransformableEntity
 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")]
 476    public float rateOfChange = 0.1f;
 77
 78    [Tooltip("Contols how the joystick behaves ")]
 479    public JoystickType leverType = JoystickType.Both;
 80
 81    [Tooltip("The transform of the visual component of the joystick")]
 482    public Transform handle = null;
 83
 84    [Serializable] public class ValueChangeEvent : UnityEvent<float> { }
 85
 86    // When the joystick's x value changes
 487    public ValueChangeEvent OnXValueChange = new ValueChangeEvent();
 88
 89    // When the joystick's y value changes
 490    public ValueChangeEvent OnYValueChange = new ValueChangeEvent();
 91
 4092    public Vector2 Value { get; private set; } = Vector2.zero;
 93
 94
 95
 496    private IXRSelectInteractor selectInteractor = null;
 97
 498    private Vector3 initialPosition = Vector3.zero;
 99
 4100    private readonly int minRotation = -30;
 4101    private readonly int maxRotation = 30;
 102
 103    protected override void OnEnable()
 2104    {
 2105        base.OnEnable();
 2106        selectEntered.AddListener(StartGrab);
 2107        selectExited.AddListener(EndGrab);
 2108    }
 109
 110    protected override void OnDisable()
 2111    {
 2112        base.OnDisable();
 2113        selectEntered.RemoveListener(StartGrab);
 2114        selectExited.RemoveListener(EndGrab);
 2115    }
 116
 117    private void StartGrab(SelectEnterEventArgs eventArgs)
 8118    {
 8119        selectInteractor = eventArgs.interactorObject;
 8120        initialPosition = ConvertToLocal(selectInteractor.transform.position);
 8121    }
 122
 123    private void EndGrab(SelectExitEventArgs eventArgs)
 8124    {
 8125        selectInteractor = null;
 8126        ResetRotation();
 8127    }
 128
 129    private void ResetRotation()
 8130    {
 8131        handle.localRotation = Quaternion.identity;
 8132        initialPosition = Vector3.zero;
 8133        SetValue(Vector3.zero);
 8134    }
 135
 136    public override void ProcessInteractable(XRInteractionUpdateOrder.UpdatePhase updatePhase)
 10572137    {
 10572138        base.ProcessInteractable(updatePhase);
 139
 10572140        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        }
 10572151    }
 152
 153    private Vector3 FindJoystickRotation(Vector3 target)
 4154    {
 4155        Vector3 currentPosition = ConvertToLocal(target);
 4156        Vector3 positionDifference = currentPosition - initialPosition;
 4157        positionDifference.y = rateOfChange;
 158
 4159        Vector3 finalRotation = Vector3.zero;
 160
 4161        if(leverType == JoystickType.FrontBack || leverType == JoystickType.Both)
 4162        {
 4163            float xRotation = GetRotationDifference(positionDifference.y, positionDifference.z);
 4164            finalRotation.x = xRotation;
 4165        }
 166
 4167        if(leverType == JoystickType.LeftRight || leverType == JoystickType.Both)
 2168        {
 2169            float zRotation = GetRotationDifference(positionDifference.y, positionDifference.x);
 2170            finalRotation.z = zRotation;
 2171        }
 172
 4173        return finalRotation;
 4174    }
 175
 176    private Vector3 ConvertToLocal(Vector3 target)
 12177    {
 12178        return transform.InverseTransformPoint(target);
 12179    }
 180
 181    private float GetRotationDifference(float yRelative, float xRelative)
 6182    {
 6183        float difference = Mathf.Atan2(xRelative, yRelative) * Mathf.Rad2Deg;
 6184        difference = Mathf.Clamp(difference, minRotation, maxRotation);
 6185        return difference;
 6186    }
 187
 188    private void ApplyRotation(Vector3 newRotation)
 4189    {
 4190        newRotation.z *= -1;
 4191        handle.localRotation = Quaternion.Euler(newRotation);
 4192    }
 193
 194    private void SetValue(Vector3 rotation)
 12195    {
 12196        Value = CalculateValue(rotation);
 12197        OnXValueChange.Invoke(Value.x);
 12198        OnYValueChange.Invoke(Value.y);
 12199    }
 200
 201    private Vector2 CalculateValue(Vector3 rotation)
 12202    {
 12203        Vector2 newValue = Vector2.zero;
 12204        newValue.x = Normalize(rotation.z);
 12205        newValue.y = Normalize(rotation.x);
 12206        return newValue;
 12207    }
 208
 209    private float Normalize(float value)
 24210    {
 24211        value = Mathf.InverseLerp(minRotation, maxRotation, value);
 24212        value = Mathf.Lerp(-1, 1, value);
 24213        return value;
 24214    }
 215}