Skip to content

Commit

Permalink
feat(Interaction): extract haptics out of interactable object
Browse files Browse the repository at this point in the history
  > ** Breaking Changes **

The haptic feedback on the interactable object has now been extracted
into it's own script that performs the haptic feedback.

This cleans up optional parameters on the interactable object and
separates the responsibility of the operation into it's own script.
  • Loading branch information
thestonefox committed Nov 10, 2016
1 parent 5ddd1ef commit 36c0f9d
Show file tree
Hide file tree
Showing 8 changed files with 202 additions and 75 deletions.
34 changes: 0 additions & 34 deletions Assets/VRTK/Editor/VRTK_InteractableObjectEditor.cs
Expand Up @@ -43,17 +43,6 @@ public override void OnInspectorGUI()
EditorGUILayout.PropertyField(serializedObject.FindProperty("touchHighlightColor"));
}

GUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel(VRTK_EditorUtilities.BuildGUIContent<VRTK_InteractableObject>("rumbleOnTouch"));
EditorGUI.indentLevel--;
GUILayout.Label("Strength", GUILayout.MinWidth(49f));
float y = EditorGUILayout.FloatField(targ.rumbleOnTouch.y, GUILayout.MinWidth(10f));
GUILayout.Label("Duration", GUILayout.MinWidth(50f));
float x = EditorGUILayout.FloatField(targ.rumbleOnTouch.x, GUILayout.MinWidth(10f));
targ.rumbleOnTouch = new Vector2(x, y);
EditorGUI.indentLevel++;
GUILayout.EndHorizontal();

EditorGUILayout.PropertyField(serializedObject.FindProperty("allowedTouchControllers"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("hideControllerOnTouch"));

Expand Down Expand Up @@ -90,17 +79,6 @@ public override void OnInspectorGUI()
EditorGUILayout.PropertyField(serializedObject.FindProperty("holdButtonToGrab"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("grabOverrideButton"));

GUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel(VRTK_EditorUtilities.BuildGUIContent<VRTK_InteractableObject>("rumbleOnGrab"));
EditorGUI.indentLevel--;
GUILayout.Label("Strength", GUILayout.MinWidth(49f));
float y = EditorGUILayout.FloatField(targ.rumbleOnGrab.y, GUILayout.MinWidth(10f));
GUILayout.Label("Duration", GUILayout.MinWidth(50f));
float x = EditorGUILayout.FloatField(targ.rumbleOnGrab.x, GUILayout.MinWidth(10f));
targ.rumbleOnGrab = new Vector2(x, y);
EditorGUI.indentLevel++;
GUILayout.EndHorizontal();

EditorGUILayout.PropertyField(serializedObject.FindProperty("allowedGrabControllers"));
targ.precisionSnap = EditorGUILayout.Toggle(VRTK_EditorUtilities.BuildGUIContent<VRTK_InteractableObject>("precisionSnap", "Precision Grab(Snap)"), targ.precisionSnap);
if (!targ.precisionSnap)
Expand Down Expand Up @@ -152,18 +130,6 @@ public override void OnInspectorGUI()
EditorGUILayout.PropertyField(serializedObject.FindProperty("holdButtonToUse"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("useOverrideButton"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("pointerActivatesUseAction"));

GUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel(VRTK_EditorUtilities.BuildGUIContent<VRTK_InteractableObject>("rumbleOnUse"));
EditorGUI.indentLevel--;
GUILayout.Label("Strength", GUILayout.MinWidth(49f));
float y = EditorGUILayout.FloatField(targ.rumbleOnUse.y, GUILayout.MinWidth(10f));
GUILayout.Label("Duration", GUILayout.MinWidth(50f));
float x = EditorGUILayout.FloatField(targ.rumbleOnUse.x, GUILayout.MinWidth(10f));
targ.rumbleOnUse = new Vector2(x, y);
EditorGUI.indentLevel++;
GUILayout.EndHorizontal();

EditorGUILayout.PropertyField(serializedObject.FindProperty("allowedUseControllers"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("hideControllerOnUse"));

Expand Down
53 changes: 32 additions & 21 deletions Assets/VRTK/Scripts/VRTK_InteractGrab.cs
Expand Up @@ -386,24 +386,26 @@ private bool GrabClimbObject()
return (grabbedObject ? true : false);
}

private void ChooseGrabSequence(VRTK_InteractableObject grabbedObjectScript)
{
if (!grabbedObjectScript.IsGrabbed() || grabbedObjectScript.IsSwappable())
{
InitPrimaryGrab(grabbedObjectScript);
}
else
{
InitSecondaryGrab(grabbedObjectScript);
}
}

private void InitGrabbedObject()
{
grabbedObject = interactTouch.GetTouchedObject();
if (grabbedObject)
{
var grabbedObjectScript = grabbedObject.GetComponent<VRTK_InteractableObject>();

if (!grabbedObjectScript.IsGrabbed() || grabbedObjectScript.IsSwappable())
{
InitPrimaryGrab(grabbedObjectScript);
}
else
{
InitSecondaryGrab(grabbedObjectScript);
}

ChooseGrabSequence(grabbedObjectScript);
updatedHideControllerOnGrab = grabbedObjectScript.CheckHideMode(hideControllerOnGrab, grabbedObjectScript.hideControllerOnGrab);

OnControllerGrabInteractableObject(interactTouch.SetControllerInteractEvent(grabbedObject));
}

Expand Down Expand Up @@ -536,6 +538,23 @@ private void IncrementGrabState()
}
}

private GameObject GetUndroppableObject()
{
return (grabbedObject && grabbedObject.GetComponent<VRTK_InteractableObject>() && !grabbedObject.GetComponent<VRTK_InteractableObject>().IsDroppable() ? grabbedObject : null);
}

private void AttemptHaptics(bool initialGrabAttempt)
{
if (grabbedObject && initialGrabAttempt)
{
var doHaptics = grabbedObject.GetComponentInParent<VRTK_InteractHaptics>();
if (doHaptics)
{
doHaptics.HapticsOnGrab(controllerActions);
}
}
}

private void AttemptGrabObject()
{
var objectToGrab = GetGrabbableObject();
Expand All @@ -550,16 +569,8 @@ private void AttemptGrabObject()
initialGrabAttempt = CheckGrabAttempt(objectToGrabScript);
}

undroppableGrabbedObject = (grabbedObject && grabbedObject.GetComponent<VRTK_InteractableObject>() && !grabbedObject.GetComponent<VRTK_InteractableObject>().IsDroppable() ? grabbedObject : null);

if (grabbedObject && initialGrabAttempt)
{
var rumbleAmount = grabbedObject.GetComponent<VRTK_InteractableObject>().rumbleOnGrab;
if (!rumbleAmount.Equals(Vector2.zero))
{
controllerActions.TriggerHapticPulse((ushort)rumbleAmount.y, rumbleAmount.x, 0.05f);
}
}
undroppableGrabbedObject = GetUndroppableObject();
AttemptHaptics(initialGrabAttempt);
}
else
{
Expand Down
84 changes: 84 additions & 0 deletions Assets/VRTK/Scripts/VRTK_InteractHaptics.cs
@@ -0,0 +1,84 @@
// Interact Haptics|Scripts|0192
namespace VRTK
{
using UnityEngine;

/// <summary>
/// The Interact Haptics script is attached along side the Interactable Object script and provides controller haptics on touch, grab and use of the object.
/// </summary>
public class VRTK_InteractHaptics : MonoBehaviour
{
[Header("Haptics On Touch")]
[Tooltip("Denotes how strong the rumble in the controller will be on touch.")]
[Range(0, 3999)]
public ushort strengthOnTouch = 0;
[Tooltip("Denotes how long the rumble in the controller will last on touch.")]
public float durationOnTouch = 0f;
[Tooltip("Denotes interval betweens rumble in the controller on touch.")]
public float intervalOnTouch = minInterval;

[Header("Haptics On Grab")]
[Tooltip("Denotes how strong the rumble in the controller will be on grab.")]
[Range(0, 3999)]
public ushort strengthOnGrab = 0;
[Tooltip("Denotes how long the rumble in the controller will last on grab.")]
public float durationOnGrab = 0f;
[Tooltip("Denotes interval betweens rumble in the controller on grab.")]
public float intervalOnGrab = minInterval;

[Header("Haptics On Use")]
[Tooltip("Denotes how strong the rumble in the controller will be on use.")]
[Range(0, 3999)]
public ushort strengthOnUse = 0;
[Tooltip("Denotes how long the rumble in the controller will last on use.")]
public float durationOnUse = 0f;
[Tooltip("Denotes interval betweens rumble in the controller on use.")]
public float intervalOnUse = minInterval;

private const float minInterval = 0.05f;

/// <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 void HapticsOnTouch(VRTK_ControllerActions controllerActions)
{
if (strengthOnTouch > 0 && durationOnTouch > 0f)
{
TriggerHapticPulse(controllerActions, 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 void HapticsOnGrab(VRTK_ControllerActions controllerActions)
{
if (strengthOnTouch > 0 && durationOnTouch > 0f)
{
TriggerHapticPulse(controllerActions, 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 void HapticsOnUse(VRTK_ControllerActions controllerActions)
{
if (strengthOnTouch > 0 && durationOnTouch > 0f)
{
TriggerHapticPulse(controllerActions, strengthOnUse, durationOnUse, intervalOnUse);
}
}

private void TriggerHapticPulse(VRTK_ControllerActions controllerActions, ushort strength, float duration, float interval)
{
if (controllerActions)
{
controllerActions.TriggerHapticPulse(strength, duration, (interval >= minInterval ? interval : minInterval));
}
}
}
}
12 changes: 12 additions & 0 deletions Assets/VRTK/Scripts/VRTK_InteractHaptics.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 8 additions & 5 deletions Assets/VRTK/Scripts/VRTK_InteractTouch.cs
Expand Up @@ -250,12 +250,15 @@ private void CheckHideController(VRTK_InteractableObject touchedObjectScript)

private void CheckRumbleController(VRTK_InteractableObject touchedObjectScript)
{
var rumbleAmount = touchedObjectScript.rumbleOnTouch;
if (!rumbleAmount.Equals(Vector2.zero) && !triggerRumble)
if (!triggerRumble)
{
triggerRumble = true;
controllerActions.TriggerHapticPulse((ushort)rumbleAmount.y, rumbleAmount.x, 0.05f);
Invoke("ResetTriggerRumble", rumbleAmount.x);
var doHaptics = touchedObject.GetComponentInParent<VRTK_InteractHaptics>();
if (doHaptics)
{
triggerRumble = true;
doHaptics.HapticsOnTouch(controllerActions);
Invoke("ResetTriggerRumble", doHaptics.durationOnTouch);
}
}
}

Expand Down
16 changes: 10 additions & 6 deletions Assets/VRTK/Scripts/VRTK_InteractUse.cs
Expand Up @@ -146,6 +146,15 @@ private void SetObjectUsingState(GameObject obj, int value)
}
}

private void AttemptHaptics()
{
var doHaptics = usingObject.GetComponentInParent<VRTK_InteractHaptics>();
if (doHaptics)
{
doHaptics.HapticsOnUse(controllerActions);
}
}

private void UseInteractedObject(GameObject touchedObject)
{
if ((usingObject == null || usingObject != touchedObject) && IsObjectUsable(touchedObject))
Expand All @@ -163,6 +172,7 @@ private void UseInteractedObject(GameObject touchedObject)
currentControllerHideState = controllerActions.IsControllerVisible();
OnControllerUseInteractableObject(interactTouch.SetControllerInteractEvent(usingObject));
usingObjectScript.StartUsing(gameObject);
AttemptHaptics();

if (updatedHideControllerOnUse)
{
Expand All @@ -172,12 +182,6 @@ private void UseInteractedObject(GameObject touchedObject)
{
controllerActions.ToggleControllerModel(true, usingObject);
}

var rumbleAmount = usingObjectScript.rumbleOnUse;
if (!rumbleAmount.Equals(Vector2.zero))
{
controllerActions.TriggerHapticPulse((ushort)rumbleAmount.y, rumbleAmount.x, 0.05f);
}
}
}

Expand Down
6 changes: 0 additions & 6 deletions Assets/VRTK/Scripts/VRTK_InteractableObject.cs
Expand Up @@ -114,8 +114,6 @@ public enum SecondaryControllerActions
public bool highlightOnTouch = false;
[Tooltip("The colour to highlight the object when it is touched. This colour will override any globally set colour (for instance on the `VRTK_InteractTouch` script).")]
public Color touchHighlightColor = Color.clear;
[Tooltip("The haptic feedback on the controller can be triggered upon touching the object, the `Strength` denotes the strength of the pulse, the `Duration` denotes the length of time.")]
public Vector2 rumbleOnTouch = Vector2.zero;
[Tooltip("Determines which controller can initiate a touch action.")]
public AllowedController allowedTouchControllers = AllowedController.Both;
[Tooltip("Optionally override the controller setting.")]
Expand All @@ -135,8 +133,6 @@ public enum SecondaryControllerActions
public bool holdButtonToGrab = true;
[Tooltip("If this is set to `Undefined` then the global grab alias button will grab the object, setting it to any other button will ensure the override button is used to grab this specific interactable object.")]
public VRTK_ControllerEvents.ButtonAlias grabOverrideButton = VRTK_ControllerEvents.ButtonAlias.Undefined;
[Tooltip("The haptic feedback on the controller can be triggered upon grabbing the object, the `Strength` denotes the strength of the pulse, the `Duration` denotes the length of time.")]
public Vector2 rumbleOnGrab = Vector2.zero;
[Tooltip("Determines which controller can initiate a grab action.")]
public AllowedController allowedGrabControllers = AllowedController.Both;
[Tooltip("If this is checked then when the controller grabs the object, it will grab it with precision and pick it up at the particular point on the object the controller is touching.")]
Expand Down Expand Up @@ -177,8 +173,6 @@ public enum SecondaryControllerActions
public VRTK_ControllerEvents.ButtonAlias useOverrideButton = VRTK_ControllerEvents.ButtonAlias.Undefined;
[Tooltip("If this is checked then when a World Pointer beam (projected from the controller) hits the interactable object, if the object has `Hold Button To Use` unchecked then whilst the pointer is over the object it will run it's `Using` method. If `Hold Button To Use` is unchecked then the `Using` method will be run when the pointer is deactivated. The world pointer will not throw the `Destination Set` event if it is affecting an interactable object with this setting checked as this prevents unwanted teleporting from happening when using an object with a pointer.")]
public bool pointerActivatesUseAction = false;
[Tooltip("The haptic feedback on the controller can be triggered upon using the object, the `Strength` denotes the strength of the pulse, the `Duration` denotes the length of time.")]
public Vector2 rumbleOnUse = Vector2.zero;
[Tooltip("Determines which controller can initiate a use action.")]
public AllowedController allowedUseControllers = AllowedController.Both;
[Tooltip("Optionally override the controller setting.")]
Expand Down

0 comments on commit 36c0f9d

Please sign in to comment.