diff --git a/Editor/Inspectors/ButtonBehaviourInspector.cs b/Editor/Inspectors/ButtonBehaviourInspector.cs new file mode 100644 index 00000000..1bf36d3f --- /dev/null +++ b/Editor/Inspectors/ButtonBehaviourInspector.cs @@ -0,0 +1,27 @@ +// Copyright (c) Reality Collective. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using RealityToolkit.Input.InteractionBehaviours; +using UnityEditor; +using UnityEditor.UIElements; +using UnityEngine.UIElements; + +namespace RealityToolkit.Editor.Inspectors +{ + [CustomEditor(typeof(ButtonBehaviour), true)] + public class ButtonBehaviourInspector : BaseInteractionBehaviourInspector + { + private const string raiseOnInputDown = "raiseOnInputDown"; + private const string click = "click"; + + public override VisualElement CreateInspectorGUI() + { + var inspector = base.CreateInspectorGUI(); + + inspector.Add(new PropertyField(serializedObject.FindProperty(raiseOnInputDown))); + inspector.Add(new PropertyField(serializedObject.FindProperty(click))); + + return inspector; + } + } +} \ No newline at end of file diff --git a/Runtime/Input/Interactables/InteractableActivationMode.cs.meta b/Editor/Inspectors/ButtonBehaviourInspector.cs.meta similarity index 86% rename from Runtime/Input/Interactables/InteractableActivationMode.cs.meta rename to Editor/Inspectors/ButtonBehaviourInspector.cs.meta index f2c6e24c..49e3a63a 100644 --- a/Runtime/Input/Interactables/InteractableActivationMode.cs.meta +++ b/Editor/Inspectors/ButtonBehaviourInspector.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: a5c30bdcdefe83f45a9a1b81a148e7be +guid: 192c04e9c01ac0e439191e35b1f0b34c MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Editor/Inspectors/ToggleBehaviourInspector.cs b/Editor/Inspectors/ToggleBehaviourInspector.cs new file mode 100644 index 00000000..84acc36a --- /dev/null +++ b/Editor/Inspectors/ToggleBehaviourInspector.cs @@ -0,0 +1,29 @@ +// Copyright (c) Reality Collective. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using RealityToolkit.Input.InteractionBehaviours; +using UnityEditor; +using UnityEditor.UIElements; +using UnityEngine.UIElements; + +namespace RealityToolkit.Editor.Inspectors +{ + [CustomEditor(typeof(ToggleBehaviour), true)] + public class ToggleBehaviourInspector : BaseInteractionBehaviourInspector + { + private const string isOn = "isOn"; + private const string raiseOnInputDown = "raiseOnInputDown"; + private const string valueChanged = "valueChanged"; + + public override VisualElement CreateInspectorGUI() + { + var inspector = base.CreateInspectorGUI(); + + inspector.Add(new PropertyField(serializedObject.FindProperty(isOn))); + inspector.Add(new PropertyField(serializedObject.FindProperty(raiseOnInputDown))); + inspector.Add(new PropertyField(serializedObject.FindProperty(valueChanged))); + + return inspector; + } + } +} diff --git a/Editor/Inspectors/ToggleBehaviourInspector.cs.meta b/Editor/Inspectors/ToggleBehaviourInspector.cs.meta new file mode 100644 index 00000000..d34f80bf --- /dev/null +++ b/Editor/Inspectors/ToggleBehaviourInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4078cdd926e5e214bb912557eff328bf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 8ac5213854cf4dbabd140decf8df1946, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Input/Interactables/IInteractable.cs b/Runtime/Input/Interactables/IInteractable.cs index 8a44aab6..4a74f0ce 100644 --- a/Runtime/Input/Interactables/IInteractable.cs +++ b/Runtime/Input/Interactables/IInteractable.cs @@ -27,11 +27,6 @@ public interface IInteractable /// bool IsValid { get; } - /// - /// Is the currently considered activated? - /// - bool IsActivated { get; } - /// /// Is the currently focused by an ? /// @@ -52,12 +47,6 @@ public interface IInteractable /// InteractableFocusMode FocusMode { get; } - /// - /// The 's activation mode determines how - /// and are raised. - /// - InteractableActivationMode ActivationMode { get; } - /// /// Does the allow direct interaction? /// diff --git a/Runtime/Input/Interactables/Interactable.cs b/Runtime/Input/Interactables/Interactable.cs index 3068534e..b6818984 100644 --- a/Runtime/Input/Interactables/Interactable.cs +++ b/Runtime/Input/Interactables/Interactable.cs @@ -53,9 +53,6 @@ public class Interactable : MonoBehaviour, [SerializeField, Tooltip("The focus mode for this interactable.")] private InteractableFocusMode focusMode = InteractableFocusMode.Single; - [SerializeField, Tooltip("The activation mode for this interactable.")] - private InteractableActivationMode activationMode = InteractableActivationMode.Button; - private readonly HashSet focusingInteractors = new HashSet(); private readonly HashSet selectingInteractors = new HashSet(); private readonly HashSet grabbingInteractors = new HashSet(); @@ -81,9 +78,6 @@ public string Label /// public bool IsValid => isActiveAndEnabled && (DirectInteractionEnabled || FarInteractionEnabled); - /// - public bool IsActivated { get; private set; } - /// public bool IsFocused => focusingInteractors.Count > 0; @@ -96,9 +90,6 @@ public string Label /// public InteractableFocusMode FocusMode => focusMode; - /// - public InteractableActivationMode ActivationMode => activationMode; - /// public bool DirectInteractionEnabled => InputService.DirectInteractionEnabled && directInteraction; @@ -151,59 +142,6 @@ private void OnReset() selectingInteractors.Clear(); } - /// - /// The was activated by . - /// - /// The causing the activation. - protected virtual void OnActivated(IInteractor interactor) - { - if (IsActivated || ActivationMode == InteractableActivationMode.None) - { - return; - } - - IsActivated = ActivationMode == InteractableActivationMode.Toggle; - - for (var i = 0; i < behaviours.Count; i++) - { - var behaviour = behaviours[i]; - var eventArgs = new Events.InteractionEventArgs - { - Interactable = this, - Interactor = interactor - }; - - behaviour.OnActivated(eventArgs); - } - } - - /// - /// The was deactivated by . - /// - /// The causing the deactivation. - protected virtual void OnDeactivated(IInteractor interactor) - { - if (!IsActivated || ActivationMode == InteractableActivationMode.None) - { - return; - } - - IsActivated = false; - - for (var i = 0; i < behaviours.Count; i++) - { - var behaviour = behaviours[i]; - var eventArgs = new Events.InteractionExitEventArgs - { - Interactable = this, - Interactor = interactor, - IsCanceled = false - }; - - behaviour.OnDeactivated(eventArgs); - } - } - /// /// The is focused by . /// @@ -496,18 +434,7 @@ public void OnPointerUp(PointerEventData eventData) } /// - public void OnPointerClicked(PointerEventData eventData) - { - eventData.Use(); - - if (IsActivated) - { - OnDeactivated(eventData.Pointer); - return; - } - - OnActivated(eventData.Pointer); - } + public void OnPointerClicked(PointerEventData eventData) { } #endregion IPointerHandler diff --git a/Runtime/Input/Interactables/InteractableActivationMode.cs b/Runtime/Input/Interactables/InteractableActivationMode.cs deleted file mode 100644 index ca826d70..00000000 --- a/Runtime/Input/Interactables/InteractableActivationMode.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Reality Collective. All rights reserved. -// Licensed under the MIT License. See LICENSE in the project root for license information. - -namespace RealityToolkit.Input.Interactables -{ - /// - /// Options for how an may be activated by s. - /// - public enum InteractableActivationMode - { - /// - /// cannot be activated at all. - /// - None = 0, - /// - /// The has only one activation state. - /// Only - /// is raised once when the is activated. The 's - /// state returns back to false right after that. - /// - Button, - /// - /// The has two activation states, activated and deactivated. - /// - /// and - /// are raised accordingly. - /// - Toggle, - } -} diff --git a/Runtime/Input/InteractionBehaviours/BaseInteractionBehaviour.cs b/Runtime/Input/InteractionBehaviours/BaseInteractionBehaviour.cs index ae130fff..4484f0b6 100644 --- a/Runtime/Input/InteractionBehaviours/BaseInteractionBehaviour.cs +++ b/Runtime/Input/InteractionBehaviours/BaseInteractionBehaviour.cs @@ -74,30 +74,6 @@ protected virtual void OnDestroy() { } /// protected virtual void OnValidate() { } - /// - void IInteractionBehaviour.OnActivated(InteractionEventArgs eventArgs) - { - if (ShouldPerformBehaviour(eventArgs)) - { - OnActivated(eventArgs); - } - } - - /// - protected virtual void OnActivated(InteractionEventArgs eventArgs) { } - - /// - void IInteractionBehaviour.OnDeactivated(InteractionExitEventArgs eventArgs) - { - if (ShouldPerformBehaviour(eventArgs)) - { - OnDeactivated(eventArgs); - } - } - - /// - protected virtual void OnDeactivated(InteractionExitEventArgs eventArgs) { } - /// void IInteractionBehaviour.OnFirstFocusEntered(InteractionEventArgs eventArgs) { diff --git a/Runtime/Input/InteractionBehaviours/ButtonBehaviour.cs b/Runtime/Input/InteractionBehaviours/ButtonBehaviour.cs index 57b710bb..386b7d17 100644 --- a/Runtime/Input/InteractionBehaviours/ButtonBehaviour.cs +++ b/Runtime/Input/InteractionBehaviours/ButtonBehaviour.cs @@ -21,6 +21,9 @@ public class ButtonBehaviour : BaseInteractionBehaviour [Serializable] public class ButtonClickEvent : UnityEvent { } + [SerializeField, Tooltip("If set, the button will raise click on input down instead of when input is released.")] + private bool raiseOnInputDown = false; + [Space] [SerializeField, Tooltip("List of click delegates triggered on click.")] private ButtonClickEvent click = null; @@ -31,9 +34,21 @@ public class ButtonClickEvent : UnityEvent { } public ButtonClickEvent Click => click; /// - protected override void OnActivated(InteractionEventArgs eventArgs) + protected override void OnSelectEntered(InteractionEventArgs eventArgs) + { + if (raiseOnInputDown) + { + Click?.Invoke(); + } + } + + /// + protected override void OnSelectExited(InteractionExitEventArgs eventArgs) { - Click?.Invoke(); + if (!raiseOnInputDown) + { + Click?.Invoke(); + } } } } diff --git a/Runtime/Input/InteractionBehaviours/IInteractionBehaviour.cs b/Runtime/Input/InteractionBehaviours/IInteractionBehaviour.cs index 8e27804c..f6cc0c37 100644 --- a/Runtime/Input/InteractionBehaviours/IInteractionBehaviour.cs +++ b/Runtime/Input/InteractionBehaviours/IInteractionBehaviour.cs @@ -1,4 +1,4 @@ -// Copyright (c) Reality Collective. All rights reserved. +// Copyright (c) Reality Collective. All rights reserved. // Licensed under the MIT License. See LICENSE in the project root for license information. using RealityToolkit.Input.Events; @@ -23,22 +23,6 @@ public interface IInteractionBehaviour /// IInteractable Interactable { get; } - #region Activate - - /// - /// The was activated. - /// - /// . - void OnActivated(InteractionEventArgs eventArgs); - - /// - /// The was deactivated. - /// - /// . - void OnDeactivated(InteractionExitEventArgs eventArgs); - - #endregion Activate - #region Focus /// diff --git a/Runtime/Input/InteractionBehaviours/InteractionEventsBehaviour.cs b/Runtime/Input/InteractionBehaviours/InteractionEventsBehaviour.cs index a1d639d1..ff9b86c6 100644 --- a/Runtime/Input/InteractionBehaviours/InteractionEventsBehaviour.cs +++ b/Runtime/Input/InteractionBehaviours/InteractionEventsBehaviour.cs @@ -18,13 +18,6 @@ namespace RealityToolkit.Input.InteractionBehaviours [AddComponentMenu(RealityToolkitRuntimePreferences.Toolkit_InteractionsAddComponentMenu + "/" + nameof(InteractionEventsBehaviour))] public class InteractionEventsBehaviour : BaseInteractionBehaviour { - [Space] - [SerializeField] - private InteractionEvent activated = null; - - [SerializeField] - private InteractionExitEvent deactivated = null; - [Space] [SerializeField] private InteractionEvent firstFocusEntered = null; @@ -64,12 +57,6 @@ public class InteractionEventsBehaviour : BaseInteractionBehaviour [SerializeField] private InteractionExitEvent lastGrabExited = null; - /// - public InteractionEvent Activated => activated; - - /// - public InteractionExitEvent Deactivated => deactivated; - /// public InteractionEvent FirstFocusEntered => firstFocusEntered; @@ -106,12 +93,6 @@ public class InteractionEventsBehaviour : BaseInteractionBehaviour /// public InteractionExitEvent LastGrabExited => lastGrabExited; - /// - protected override void OnActivated(InteractionEventArgs eventArgs) => Activated?.Invoke(eventArgs); - - /// - protected override void OnDeactivated(InteractionExitEventArgs eventArgs) => Deactivated?.Invoke(eventArgs); - /// protected override void OnFirstFocusEntered(InteractionEventArgs eventArgs) => FirstFocusEntered?.Invoke(eventArgs); diff --git a/Runtime/Input/InteractionBehaviours/SteeringWheelBehaviour.cs b/Runtime/Input/InteractionBehaviours/SteeringWheelBehaviour.cs index 01831624..f13f0461 100644 --- a/Runtime/Input/InteractionBehaviours/SteeringWheelBehaviour.cs +++ b/Runtime/Input/InteractionBehaviours/SteeringWheelBehaviour.cs @@ -27,7 +27,7 @@ public class SteeringWheelBehaviour : BaseInteractionBehaviour [SerializeField, Tooltip("If set, the steering will smoothly reset instead of instantly.")] private bool smoothReset = true; - [SerializeField, Tooltip("Time in seconds to return to neutral position.")] + [SerializeField, Tooltip("Time in seconds to return to neutral position."), Min(.01f)] private float smoothResetDuration = .5f; [SerializeField, Tooltip("Consistent up transform for the steering wheel.")] @@ -146,7 +146,11 @@ protected override void OnLastGrabExited(InteractionExitEventArgs eventArgs) { currentAngle = FindSteeringWheelAngle(); currentInteractor = null; - ReturnToNeutral(); + + if (resetsToNeutral) + { + ReturnToNeutral(); + } } /// @@ -184,9 +188,15 @@ private void ReturnToNeutral() return; } - resetting = true; - elapsedResetTime = 0f; - resetStartRotation = Quaternion.Euler(0f, 0f, CurrentSteeringAngle); + if (smoothReset) + { + resetting = true; + elapsedResetTime = 0f; + resetStartRotation = Quaternion.Euler(0f, 0f, CurrentSteeringAngle); + return; + } + + CurrentSteeringAngle = neutralSteeringRotation.eulerAngles.z; } private static float WrapAngle(float angle) diff --git a/Runtime/Input/InteractionBehaviours/ToggleBehaviour.cs b/Runtime/Input/InteractionBehaviours/ToggleBehaviour.cs index 03acb511..f66e80c5 100644 --- a/Runtime/Input/InteractionBehaviours/ToggleBehaviour.cs +++ b/Runtime/Input/InteractionBehaviours/ToggleBehaviour.cs @@ -21,6 +21,12 @@ public class ToggleBehaviour : BaseInteractionBehaviour [Serializable] public class ToggleEvent : UnityEvent { } + [SerializeField, Tooltip("Is the toggle currently on or off?")] + private bool isOn = false; + + [SerializeField, Tooltip("If set, the button will raise click on input down instead of when input is released.")] + private bool raiseOnInputDown = false; + [Space] [SerializeField, Tooltip("List of delegates triggered on value change.")] private ToggleEvent valueChanged = null; @@ -33,18 +39,43 @@ public class ToggleEvent : UnityEvent { } /// /// Is the toggle currently on or off? /// - public bool IsOn => Interactable.IsActivated; + public bool IsOn + { + get => isOn; + set + { + if (value == isOn) + { + return; + } + + isOn = value; + ValueChanged?.Invoke(isOn); + } + } + + /// + /// Updates without raising . + /// + /// The new value. + public void SetIsOnWithoutNotify(bool isOn) => this.isOn = isOn; /// - protected override void OnActivated(InteractionEventArgs eventArgs) + protected override void OnSelectEntered(InteractionEventArgs eventArgs) { - ValueChanged?.Invoke(IsOn); + if (raiseOnInputDown) + { + IsOn = !IsOn; + } } /// - protected override void OnDeactivated(InteractionExitEventArgs eventArgs) + protected override void OnSelectExited(InteractionExitEventArgs eventArgs) { - ValueChanged?.Invoke(IsOn); + if (!raiseOnInputDown) + { + IsOn = !IsOn; + } } } }