222 lines
7.3 KiB
C#
222 lines
7.3 KiB
C#
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
|
|
using Microsoft.MixedReality.Toolkit.Input;
|
|
using Microsoft.MixedReality.Toolkit.Utilities;
|
|
using UnityEngine;
|
|
|
|
namespace Microsoft.MixedReality.Toolkit.UI.PulseShader
|
|
{
|
|
/// <summary>
|
|
/// Script for triggering the pulse shader effect on HoloLens 2 hand mesh.
|
|
/// </summary>
|
|
public class PulseShaderHandMeshHandler : PulseShaderHandler, IMixedRealityPointerHandler
|
|
{
|
|
[Space]
|
|
[SerializeField]
|
|
[Tooltip("Trigger the pulse shader visual if the palm of the left or right hand is facing the camera.")]
|
|
private bool pulseOnLookAtPalms = false;
|
|
|
|
/// <summary>
|
|
/// Trigger the pulse shader visual if the palm of the left or right hand is facing the camera.
|
|
/// </summary>
|
|
public bool PulseOnLookAtPalms
|
|
{
|
|
get => pulseOnLookAtPalms;
|
|
set => pulseOnLookAtPalms = value;
|
|
}
|
|
|
|
[SerializeField]
|
|
[Tooltip("Trigger the pulse shader visual if the hand is in the pinch/select gesture. ")]
|
|
private bool pulseFingerTipsOnPinch = false;
|
|
|
|
/// <summary>
|
|
/// Trigger the pulse shader visual if the hand is in the pinch/select gesture.
|
|
/// </summary>
|
|
public bool PulseFingerTipsOnPinch
|
|
{
|
|
get => pulseFingerTipsOnPinch;
|
|
set => pulseFingerTipsOnPinch = value;
|
|
}
|
|
|
|
[SerializeField]
|
|
[Tooltip("Trigger the pulse shader visual once if the left or right hand enters the frame and is tracked.")]
|
|
private bool pulseOnHandDetected = true;
|
|
|
|
/// <summary>
|
|
/// Trigger the pulse shader visual once if the left or right hand enters the frame and is tracked.
|
|
/// </summary>
|
|
public bool PulseOnHandDetected
|
|
{
|
|
get => pulseOnHandDetected;
|
|
set => pulseOnHandDetected = value;
|
|
}
|
|
|
|
[SerializeField]
|
|
[Tooltip("The length of time required for the palm to face the camera before the pulse shader visual is triggered. ")]
|
|
private float palmFacingTime = 0.25f;
|
|
|
|
/// <summary>
|
|
/// The length of time required for the palm to face the camera before the pulse shader visual is triggered.
|
|
/// </summary>
|
|
public float PalmFacingTime
|
|
{
|
|
get => palmFacingTime;
|
|
set => palmFacingTime = value;
|
|
}
|
|
|
|
[SerializeField]
|
|
[Tooltip("The local origin of the palms.")]
|
|
private Vector3 pulseOriginPalms = new Vector3(0.5f, 0.5f, 0);
|
|
|
|
/// <summary>
|
|
/// The local origin of the palms.
|
|
/// </summary>
|
|
public Vector3 PulseOriginPalms
|
|
{
|
|
get => pulseOriginPalms;
|
|
set => pulseOriginPalms = value;
|
|
}
|
|
|
|
[SerializeField]
|
|
[Tooltip("The local origin of the pulse shader visual for the finger tips. ")]
|
|
private Vector3 pulseOriginFingertips = new Vector3(0, 1f, 0);
|
|
|
|
/// <summary>
|
|
/// The local origin of the pulse shader visual for the finger tips.
|
|
/// </summary>
|
|
public Vector3 PulseOriginFingertips
|
|
{
|
|
get => pulseOriginFingertips;
|
|
set => pulseOriginFingertips = value;
|
|
}
|
|
|
|
private bool pulseTriggeredLeft = false;
|
|
private bool pulseTriggeredRight = false;
|
|
|
|
private float palmFacingTimer = 0;
|
|
|
|
protected override void Start()
|
|
{
|
|
base.Start();
|
|
|
|
CoreServices.InputSystem?.RegisterHandler<IMixedRealityPointerHandler>(this);
|
|
}
|
|
|
|
protected override void OnDestroy()
|
|
{
|
|
base.OnDestroy();
|
|
|
|
CoreServices.InputSystem?.UnregisterHandler<IMixedRealityPointerHandler>(this);
|
|
}
|
|
|
|
protected override void Update()
|
|
{
|
|
if (PulseOnLookAtPalms)
|
|
{
|
|
if (IsAPalmFacingCamera())
|
|
{
|
|
if (palmFacingTimer >= 0)
|
|
{
|
|
palmFacingTimer += Time.deltaTime;
|
|
if (palmFacingTimer > PalmFacingTime)
|
|
{
|
|
PulsePalms();
|
|
palmFacingTimer = -1;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
palmFacingTimer = 0;
|
|
}
|
|
}
|
|
|
|
if (PulseOnHandDetected)
|
|
{
|
|
// If joints are detected then an articulated hand is present
|
|
bool isLeftHandDetected = HandJointUtils.TryGetJointPose(TrackedHandJoint.Palm, Handedness.Left, out MixedRealityPose leftPose);
|
|
bool isRightHandDetected = HandJointUtils.TryGetJointPose(TrackedHandJoint.Palm, Handedness.Right, out MixedRealityPose rightPose);
|
|
|
|
TriggerPulseOnHandDetected(isLeftHandDetected, isRightHandDetected);
|
|
}
|
|
}
|
|
|
|
private void TriggerPulseOnHandDetected(bool isLeftHandDetected, bool isRightHandDetected)
|
|
{
|
|
// Left Hand
|
|
if (isLeftHandDetected && !pulseTriggeredLeft)
|
|
{
|
|
pulseTriggeredLeft = true;
|
|
PulsePalms();
|
|
}
|
|
else if (!isLeftHandDetected && pulseTriggeredLeft)
|
|
{
|
|
pulseTriggeredLeft = false;
|
|
}
|
|
|
|
// Right Hand
|
|
if (isRightHandDetected && !pulseTriggeredRight)
|
|
{
|
|
pulseTriggeredRight = true;
|
|
PulsePalms();
|
|
}
|
|
else if (!isRightHandDetected && pulseTriggeredRight)
|
|
{
|
|
pulseTriggeredRight = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the local origin of the pulse shader visual to the palms and trigger the animation.
|
|
/// </summary>
|
|
public void PulsePalms()
|
|
{
|
|
SetLocalOrigin(PulseOriginPalms);
|
|
PulseOnce();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the local origin of the pulse shader visual to the finger tips and trigger the animation.
|
|
/// </summary>
|
|
public void PulseFingerTips()
|
|
{
|
|
SetLocalOrigin(PulseOriginFingertips);
|
|
PulseOnce();
|
|
}
|
|
|
|
// Check if the palm is facing the camera
|
|
private bool IsAPalmFacingCamera()
|
|
{
|
|
foreach (IMixedRealityController controller in CoreServices.InputSystem.DetectedControllers)
|
|
{
|
|
if (controller.ControllerHandedness.IsMatch(Handedness.Both)
|
|
&& controller is IMixedRealityHand jointedHand
|
|
&& jointedHand.TryGetJoint(TrackedHandJoint.Palm, out MixedRealityPose palmPose)
|
|
&& Vector3.Dot(palmPose.Up, CameraCache.Main.transform.forward) > 0.0f)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
#region Pointer Handler
|
|
|
|
public void OnPointerDown(MixedRealityPointerEventData eventData)
|
|
{
|
|
if (PulseFingerTipsOnPinch)
|
|
{
|
|
PulseFingerTips();
|
|
}
|
|
}
|
|
|
|
public void OnPointerDragged(MixedRealityPointerEventData eventData) { }
|
|
public void OnPointerUp(MixedRealityPointerEventData eventData) { }
|
|
public void OnPointerClicked(MixedRealityPointerEventData eventData) { }
|
|
|
|
#endregion
|
|
}
|
|
}
|