// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.Toolkit.Utilities.Editor;
using UnityEngine.Events;
namespace Microsoft.MixedReality.Toolkit.UI
{
///
/// Basic press event receiver
///
public class InteractableOnPressReceiver : ReceiverBase
{
///
/// Invoked on pointer release
///
[InspectorField(Type = InspectorField.FieldTypes.Event, Label = "On Release", Tooltip = "The button is released")]
public UnityEvent OnRelease = new UnityEvent();
///
/// Invoked on pointer press
///
public UnityEvent OnPress => uEvent;
///
/// Type of valid interaction distances to fire press events
///
public enum InteractionType
{
///
/// Support Near and Far press interactions
///
NearAndFar = 0,
///
/// Support Near press interactions only
///
NearOnly = 1,
///
/// Support Far press interactions only
///
FarOnly = 2
}
///
/// Specify whether press event is for near or far interaction
///
[InspectorField(Label = "Interaction Filter",
Tooltip = "Specify whether press event is for near or far interaction",
Type = InspectorField.FieldTypes.DropdownInt, Options = new string[] { "Near and Far", "Near Only", "Far Only" })]
public int InteractionFilter = (int)InteractionType.NearAndFar;
private bool hasDown;
private bool isNear = false;
///
/// Receiver that raises press and release unity events
///
public InteractableOnPressReceiver(UnityEvent ev) : base(ev, "OnPress") { }
///
/// Receiver that raises press and release unity events
///
public InteractableOnPressReceiver() : this(new UnityEvent()) { }
///
/// checks if the received interactable state matches the press filter
///
/// true if interactable state matches filter
private bool IsFilterValid()
{
if (InteractionFilter == (int)InteractionType.FarOnly && isNear
|| InteractionFilter == (int)InteractionType.NearOnly && !isNear)
{
return false;
}
else
{
return true;
}
}
///
public override void OnUpdate(InteractableStates state, Interactable source)
{
bool hadDown = hasDown;
hasDown = state.GetState(InteractableStates.InteractableStateEnum.Pressed).Value > 0;
if (hasDown != hadDown)
{
if (hasDown)
{
isNear = state.GetState(InteractableStates.InteractableStateEnum.PhysicalTouch).Value > 0;
if (IsFilterValid())
{
uEvent.Invoke();
}
}
else
{
if (IsFilterValid())
{
OnRelease.Invoke();
}
}
}
}
}
}