Skip to content

Commit

Permalink
feat(Haptics): extract haptics out of ControllerActions
Browse files Browse the repository at this point in the history
The haptic feedback has now been removed from the ControllerActions
script and placed in the Shared Methods script meaning that it can
be called simply by knowing the ID of the controller to rumble.

This means it no longer requires a script to be attached to a script
alias object to achieve haptic feedback.

A new Instance Methods script has been added that handles running
any co-routines such as the haptic feedback co-routine in a global
manner rather than being tied to a specific controller objeect.
  • Loading branch information
thestonefox committed Mar 6, 2017
1 parent 1c34429 commit 529196f
Show file tree
Hide file tree
Showing 15 changed files with 166 additions and 93 deletions.
13 changes: 2 additions & 11 deletions Assets/VRTK/Examples/Resources/Scripts/Archery/BowAim.cs
Expand Up @@ -21,9 +21,6 @@ public class BowAim : MonoBehaviour
private VRTK_InteractGrab holdControl;
private VRTK_InteractGrab stringControl;

private VRTK_ControllerActions stringActions;
private VRTK_ControllerActions holdActions;

private Quaternion releaseRotation;
private Quaternion baseRotation;
private bool fired;
Expand Down Expand Up @@ -65,17 +62,11 @@ private void DoObjectGrab(object sender, InteractableObjectEventArgs e)
{
holdControl = VRTK_DeviceFinder.GetControllerLeftHand().GetComponent<VRTK_InteractGrab>();
stringControl = VRTK_DeviceFinder.GetControllerRightHand().GetComponent<VRTK_InteractGrab>();

holdActions = VRTK_DeviceFinder.GetControllerLeftHand().GetComponent<VRTK_ControllerActions>();
stringActions = VRTK_DeviceFinder.GetControllerRightHand().GetComponent<VRTK_ControllerActions>();
}
else
{
stringControl = VRTK_DeviceFinder.GetControllerLeftHand().GetComponent<VRTK_InteractGrab>();
holdControl = VRTK_DeviceFinder.GetControllerRightHand().GetComponent<VRTK_InteractGrab>();

stringActions = VRTK_DeviceFinder.GetControllerLeftHand().GetComponent<VRTK_ControllerActions>();
holdActions = VRTK_DeviceFinder.GetControllerRightHand().GetComponent<VRTK_ControllerActions>();
}
StartCoroutine("GetBaseRotation");
}
Expand Down Expand Up @@ -172,8 +163,8 @@ private void PullString()

if (!currentPull.ToString("F2").Equals(previousPull.ToString("F2")))
{
holdActions.TriggerHapticPulse(bowVibration);
stringActions.TriggerHapticPulse(stringVibration);
VRTK_SharedMethods.TriggerHapticPulse(VRTK_DeviceFinder.GetControllerIndex(holdControl.gameObject), bowVibration);
VRTK_SharedMethods.TriggerHapticPulse(VRTK_DeviceFinder.GetControllerIndex(stringControl.gameObject), stringVibration);
}
previousPull = currentPull;
}
Expand Down
Expand Up @@ -9,30 +9,27 @@ public class FireExtinguisher_Base : VRTK_InteractableObject
public FireExtinguisher_Sprayer sprayer;

private VRTK_ControllerEvents controllerEvents;
private VRTK_ControllerActions controllerActions;

public override void StartUsing(GameObject usingObject)
{
base.StartUsing(usingObject);
controllerEvents = usingObject.GetComponent<VRTK_ControllerEvents>();
controllerActions = usingObject.GetComponent<VRTK_ControllerActions>();
}

public override void StopUsing(GameObject previousUsingObject)
{
base.StopUsing(previousUsingObject);
controllerEvents = null;
controllerActions = null;
}

protected override void Update()
{
base.Update();
if (controllerEvents)
{
var power = controllerEvents.GetTriggerAxis();
float power = controllerEvents.GetTriggerAxis();
Spray(power);
controllerActions.TriggerHapticPulse(power * 0.25f, 0.1f, 0.01f);
VRTK_SharedMethods.TriggerHapticPulse(VRTK_DeviceFinder.GetControllerIndex(controllerEvents.gameObject), power * 0.25f, 0.1f, 0.01f);
}
else
{
Expand Down
7 changes: 2 additions & 5 deletions Assets/VRTK/Examples/Resources/Scripts/RealGun.cs
Expand Up @@ -18,7 +18,6 @@ public class RealGun : VRTK_InteractableObject
private Collider safetySwitchCollider;

private VRTK_ControllerEvents controllerEvents;
private VRTK_ControllerActions controllerActions;

private float minTriggerRotation = -10f;
private float maxTriggerRotation = 45f;
Expand Down Expand Up @@ -54,7 +53,6 @@ public override void Grabbed(GameObject currentGrabbingObject)
base.Grabbed(currentGrabbingObject);

controllerEvents = currentGrabbingObject.GetComponent<VRTK_ControllerEvents>();
controllerActions = currentGrabbingObject.GetComponent<VRTK_ControllerActions>();

ToggleSlide(true);
ToggleSafetySwitch(true);
Expand Down Expand Up @@ -90,7 +88,6 @@ public override void Ungrabbed(GameObject previousGrabbingObject)
safetySwitch.allowedGrabControllers = AllowedController.Both;

controllerEvents = null;
controllerActions = null;
}

public override void StartUsing(GameObject currentUsingObject)
Expand All @@ -100,11 +97,11 @@ public override void StartUsing(GameObject currentUsingObject)
{
slide.Fire();
FireBullet();
controllerActions.TriggerHapticPulse(0.63f, 0.2f, 0.01f);
VRTK_SharedMethods.TriggerHapticPulse(VRTK_DeviceFinder.GetControllerIndex(controllerEvents.gameObject), 0.63f, 0.2f, 0.01f);
}
else
{
controllerActions.TriggerHapticPulse(0.08f, 0.1f, 0.01f);
VRTK_SharedMethods.TriggerHapticPulse(VRTK_DeviceFinder.GetControllerIndex(controllerEvents.gameObject), 0.08f, 0.1f, 0.01f);
}
}

Expand Down
21 changes: 14 additions & 7 deletions Assets/VRTK/Examples/Resources/Scripts/Sword.cs
Expand Up @@ -4,10 +4,10 @@

public class Sword : VRTK_InteractableObject
{
private VRTK_ControllerActions controllerActions;
private float impactMagnifier = 120f;
private float collisionForce = 0f;
private float maxCollisionForce = 4000f;
private GameObject grabbingController;

public float CollisionForce()
{
Expand All @@ -17,22 +17,29 @@ public float CollisionForce()
public override void Grabbed(GameObject grabbingObject)
{
base.Grabbed(grabbingObject);
controllerActions = grabbingObject.GetComponent<VRTK_ControllerActions>();
grabbingController = grabbingObject;
}

protected override void Awake()
public override void Ungrabbed(GameObject previousGrabbingObject)
{
base.Awake();
base.Ungrabbed(previousGrabbingObject);
grabbingController = null;
}

protected override void OnEnable()
{
base.OnEnable();
grabbingController = null;
interactableRigidbody.collisionDetectionMode = CollisionDetectionMode.Continuous;
}

private void OnCollisionEnter(Collision collision)
{
if (controllerActions && IsGrabbed())
if (grabbingController != null && IsGrabbed())
{
collisionForce = VRTK_DeviceFinder.GetControllerVelocity(controllerActions.gameObject).magnitude * impactMagnifier;
collisionForce = VRTK_DeviceFinder.GetControllerVelocity(grabbingController).magnitude * impactMagnifier;
var hapticStrength = collisionForce / maxCollisionForce;
controllerActions.TriggerHapticPulse(hapticStrength, 0.5f, 0.01f);
VRTK_SharedMethods.TriggerHapticPulse(VRTK_DeviceFinder.GetControllerIndex(grabbingController), hapticStrength, 0.5f, 0.01f);
}
else
{
Expand Down
Expand Up @@ -226,11 +226,7 @@ protected override void AttemptHapticPulse(float strength)
{
if (interactingObjects.Count > 0)
{
var controllerActions = interactingObjects[0].GetComponent<VRTK_ControllerActions>();
if (controllerActions)
{
controllerActions.TriggerHapticPulse(strength);
}
VRTK_SharedMethods.TriggerHapticPulse(VRTK_DeviceFinder.GetControllerIndex(interactingObjects[0]), strength);
}
}
#endregion Event Listeners
Expand Down
5 changes: 2 additions & 3 deletions Assets/VRTK/Scripts/Controls/2D/RadialMenuController.cs
Expand Up @@ -88,10 +88,9 @@ protected void DoChangeAngle(float angle, object sender = null)

protected virtual void AttemptHapticPulse(float strength)
{
var controllerActions = GetComponentInParent<VRTK_ControllerActions>();
if (controllerActions)
if (events)
{
controllerActions.TriggerHapticPulse(strength);
VRTK_SharedMethods.TriggerHapticPulse(VRTK_DeviceFinder.GetControllerIndex(events.gameObject), strength);
}
}

Expand Down
44 changes: 5 additions & 39 deletions Assets/VRTK/Scripts/Interactions/VRTK_ControllerActions.cs
Expand Up @@ -2,6 +2,7 @@
namespace VRTK
{
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using Highlighters;
Expand Down Expand Up @@ -57,8 +58,6 @@ public struct ControllerActionsEventArgs
/// The highlighting of the controller is defaulted to use the `VRTK_MaterialColorSwapHighlighter` if no other highlighter is applied to the Object.
/// </remarks>
/// <example>
/// `VRTK/Examples/016_Controller_HapticRumble` demonstrates the ability to hide a controller model and make the controller vibrate for a given length of time at a given intensity.
///
/// `VRTK/Examples/035_Controller_OpacityAndHighlighting` demonstrates the ability to change the opacity of a controller model and to highlight specific elements of a controller such as the buttons or even the entire controller model.
/// </example>
public class VRTK_ControllerActions : MonoBehaviour
Expand Down Expand Up @@ -104,7 +103,6 @@ public class VRTK_ControllerActions : MonoBehaviour
private bool controllerHighlighted = false;
private Dictionary<string, Transform> cachedElements;
private Dictionary<string, object> highlighterOptions;
private Coroutine hapticLoop;

public virtual void OnControllerModelVisible(ControllerActionsEventArgs e)
{
Expand Down Expand Up @@ -361,14 +359,10 @@ public virtual void ToggleHighlightController(bool state, Color? highlight = nul
/// The TriggerHapticPulse/1 method calls a single haptic pulse call on the controller for a single tick.
/// </summary>
/// <param name="strength">The intensity of the rumble of the controller motor. `0` to `1`.</param>
[Obsolete("`VRTK_ControllerActions.TriggerHapticPulse(strength)` has been replaced with `VRTK_SharedMethods.TriggerHapticPulse(index, strength)`. This method will be removed in a future version of VRTK.")]
public virtual void TriggerHapticPulse(float strength)
{
if (enabled)
{
CancelHapticPulse();
var hapticPulseStrength = Mathf.Clamp(strength, 0f, 1f);
VRTK_SDK_Bridge.HapticPulseOnIndex(VRTK_DeviceFinder.GetControllerIndex(gameObject), hapticPulseStrength);
}
VRTK_SharedMethods.TriggerHapticPulse(VRTK_DeviceFinder.GetControllerIndex(gameObject), strength);
}

/// <summary>
Expand All @@ -377,15 +371,10 @@ public virtual void TriggerHapticPulse(float strength)
/// <param name="strength">The intensity of the rumble of the controller motor. `0` to `1`.</param>
/// <param name="duration">The length of time the rumble should continue for.</param>
/// <param name="pulseInterval">The interval to wait between each haptic pulse.</param>
[Obsolete("`VRTK_ControllerActions.TriggerHapticPulse(strength, duration, pulseInterval)` has been replaced with `VRTK_SharedMethods.TriggerHapticPulse(index, strength, duration, pulseInterval)`. This method will be removed in a future version of VRTK.")]
public virtual void TriggerHapticPulse(float strength, float duration, float pulseInterval)
{
if (enabled)
{
CancelHapticPulse();
var hapticPulseStrength = Mathf.Clamp(strength, 0f, 1f);
var hapticModifiers = VRTK_SDK_Bridge.GetHapticModifiers();
hapticLoop = StartCoroutine(HapticPulse(duration * hapticModifiers.durationModifier, hapticPulseStrength, pulseInterval * hapticModifiers.intervalModifier));
}
VRTK_SharedMethods.TriggerHapticPulse(VRTK_DeviceFinder.GetControllerIndex(gameObject), strength, duration, pulseInterval);
}

/// <summary>
Expand Down Expand Up @@ -486,29 +475,6 @@ private void AddHighlighterToElement(Transform element, VRTK_BaseHighlighter par
}
}

private void CancelHapticPulse()
{
if (hapticLoop != null)
{
StopCoroutine(hapticLoop);
}
}

private IEnumerator HapticPulse(float duration, float hapticPulseStrength, float pulseInterval)
{
if (pulseInterval <= 0)
{
yield break;
}

while (duration > 0)
{
VRTK_SDK_Bridge.HapticPulseOnIndex(VRTK_DeviceFinder.GetControllerIndex(gameObject), hapticPulseStrength);
yield return new WaitForSeconds(pulseInterval);
duration -= pulseInterval;
}
}

private IEnumerator CycleColor(Material material, Color startColor, Color endColor, float duration)
{
var elapsedTime = 0f;
Expand Down
2 changes: 1 addition & 1 deletion Assets/VRTK/Scripts/Interactions/VRTK_InteractGrab.cs
Expand Up @@ -418,7 +418,7 @@ protected virtual void AttemptHaptics(bool initialGrabAttempt)
var doHaptics = grabbedObject.GetComponentInParent<VRTK_InteractHaptics>();
if (doHaptics)
{
doHaptics.HapticsOnGrab(controllerActions);
doHaptics.HapticsOnGrab(VRTK_DeviceFinder.GetControllerIndex(interactTouch.gameObject));
}
}
}
Expand Down
25 changes: 11 additions & 14 deletions Assets/VRTK/Scripts/Interactions/VRTK_InteractHaptics.cs
Expand Up @@ -40,36 +40,36 @@ public class VRTK_InteractHaptics : MonoBehaviour
/// <summary>
/// The HapticsOnTouch method triggers the haptic feedback on the given controller for the settings associated with touch.
/// </summary>
/// <param name="controllerActions">The controller to activate the haptic feedback on.</param>
public virtual void HapticsOnTouch(VRTK_ControllerActions controllerActions)
/// <param name="controllerIndex">The controller index to activate the haptic feedback on.</param>
public virtual void HapticsOnTouch(uint controllerIndex)
{
if (strengthOnTouch > 0 && durationOnTouch > 0f)
{
TriggerHapticPulse(controllerActions, strengthOnTouch, durationOnTouch, intervalOnTouch);
TriggerHapticPulse(controllerIndex, strengthOnTouch, durationOnTouch, intervalOnTouch);
}
}

/// <summary>
/// The HapticsOnGrab method triggers the haptic feedback on the given controller for the settings associated with grab.
/// </summary>
/// <param name="controllerActions">The controller to activate the haptic feedback on.</param>
public virtual void HapticsOnGrab(VRTK_ControllerActions controllerActions)
/// <param name="controllerIndex">The controller index to activate the haptic feedback on.</param>
public virtual void HapticsOnGrab(uint controllerIndex)
{
if (strengthOnGrab > 0 && durationOnGrab > 0f)
{
TriggerHapticPulse(controllerActions, strengthOnGrab, durationOnGrab, intervalOnGrab);
TriggerHapticPulse(controllerIndex, strengthOnGrab, durationOnGrab, intervalOnGrab);
}
}

/// <summary>
/// The HapticsOnUse method triggers the haptic feedback on the given controller for the settings associated with use.
/// </summary>
/// <param name="controllerActions">The controller to activate the haptic feedback on.</param>
public virtual void HapticsOnUse(VRTK_ControllerActions controllerActions)
/// <param name="controllerIndex">The controller index to activate the haptic feedback on.</param>
public virtual void HapticsOnUse(uint controllerIndex)
{
if (strengthOnUse > 0 && durationOnUse > 0f)
{
TriggerHapticPulse(controllerActions, strengthOnUse, durationOnUse, intervalOnUse);
TriggerHapticPulse(controllerIndex, strengthOnUse, durationOnUse, intervalOnUse);
}
}

Expand All @@ -81,12 +81,9 @@ protected virtual void OnEnable()
}
}

private void TriggerHapticPulse(VRTK_ControllerActions controllerActions, float strength, float duration, float interval)
private void TriggerHapticPulse(uint controllerIndex, float strength, float duration, float interval)
{
if (controllerActions)
{
controllerActions.TriggerHapticPulse(strength, duration, (interval >= minInterval ? interval : minInterval));
}
VRTK_SharedMethods.TriggerHapticPulse(controllerIndex, strength, duration, (interval >= minInterval ? interval : minInterval));
}
}
}
2 changes: 1 addition & 1 deletion Assets/VRTK/Scripts/Interactions/VRTK_InteractTouch.cs
Expand Up @@ -334,7 +334,7 @@ protected virtual void CheckRumbleController(VRTK_InteractableObject touchedObje
if (doHaptics)
{
triggerRumble = true;
doHaptics.HapticsOnTouch(controllerActions);
doHaptics.HapticsOnTouch(VRTK_DeviceFinder.GetControllerIndex(gameObject));
Invoke("ResetTriggerRumble", doHaptics.durationOnTouch);
}
}
Expand Down
2 changes: 1 addition & 1 deletion Assets/VRTK/Scripts/Interactions/VRTK_InteractUse.cs
Expand Up @@ -229,7 +229,7 @@ protected virtual void AttemptHaptics()
var doHaptics = usingObject.GetComponentInParent<VRTK_InteractHaptics>();
if (doHaptics)
{
doHaptics.HapticsOnUse(controllerActions);
doHaptics.HapticsOnUse(VRTK_DeviceFinder.GetControllerIndex(interactTouch.gameObject));
}
}
}
Expand Down

0 comments on commit 529196f

Please sign in to comment.