// 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(); } } } } } }