// --------------------------------------------------------------------------------------------------------------------
//
// Copyright (c) VRMADA, All rights reserved.
//
// --------------------------------------------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using UltimateXR.Core;
using UltimateXR.Devices.Visualization;
using UltimateXR.Haptics;
using UltimateXR.Manipulation;
using UnityEngine;
namespace UltimateXR.Devices
{
///
/// Controller interface for all XR input devices, supporting single controller and dual controller setups.
///
public interface IUxrControllerInput : IUxrDevice
{
#region Public Types & Data
///
/// Event called right before the controller input state is updated.
///
event EventHandler Updating;
///
/// Event called right after the controller input state has been updated.
///
event EventHandler Updated;
///
/// Event called after a controller button state changed.
///
event EventHandler ButtonStateChanged;
///
/// Event called after a element changed.
///
event EventHandler Input1DChanged;
///
/// Event called after a element changed.
///
event EventHandler Input2DChanged;
///
/// Event called right before haptic feedback was requested.
///
event EventHandler HapticRequesting;
///
/// Gets the setup type. See .
///
UxrControllerSetupType SetupType { get; }
///
///
/// Gets whether can be used. In devices, it
/// may be used to control which hand is holding the controller. In
/// devices it is used to determine which hands have the (dominant) and
/// (non-dominant) roles.
///
/// Devices such as gamepads don't support handedness and will target the single device no matter which
/// is used. In this case it is good practice to use to target the
/// device in order to make the code cleaner.
///
bool IsHandednessSupported { get; }
///
///
/// Gets which hand is holding the controller in setups where
/// is available. In setups
/// it identifies the dominant hand. In both cases, determines which hand it is.
///
/// In devices where handedness is not applicable (
/// is false) it is good practice to use to address the
/// device, even if both left and right can too.
///
///
UxrHandSide Primary { get; }
///
/// Gets which hand is not holding the controller in setups where
/// is available. In setups
/// it identifies the non-dominant hand.
///
///
UxrHandSide Secondary { get; }
///
/// Gets the left controller name, or empty if not connected / doesn't exist. In
/// configurations where is not
/// available, both sides will return the same name.
///
string LeftControllerName { get; }
///
/// Gets the right controller name, or empty if not connected / doesn't exist. In
/// configurations where is not
/// available, both sides will return the same name.
///
string RightControllerName { get; }
///
/// Gets the left instanced 3D controller model, if available. In
/// configurations where is false, both sides will return the same model.
///
UxrController3DModel LeftController3DModel { get; }
///
/// Gets the right instanced 3D controller model, if available. In
/// configurations where is false, both sides will return the same model.
///
UxrController3DModel RightController3DModel { get; }
///
/// Gets a value indicating whether the main two-axis input element is a touchpad. If false, it usually means the main
/// joystick is a thumbstick.
///
bool MainJoystickIsTouchpad { get; }
///
/// Gets the controller's joystick dead zone [0.0, 1.0]. Some controllers may have a more sensitive joystick,
/// and this property can be used to compensate in different implementations.
///
float JoystickDeadZone { get; }
///
///
/// Gets or sets the handedness, which is the -dominant- hand in
/// controller setups. In
/// controller setups where the controller is grabbed with one hand, it determines which hand is being used.
///
/// If false, such as in gamepads, the handedness value should be ignored.
///
///
///
///
UxrHandSide Handedness { get; set; }
#endregion
#region Public Methods
///
/// Checks whether the given controller is enabled.
///
///
/// Which controller to check. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Whether the given controller is enabled
bool IsControllerEnabled(UxrHandSide handSide);
///
/// Checks if the given controller has specific elements.
///
///
/// Which controller to check. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Flags indicating the element(s) to look for
/// True if the controller has all the elements specified. If one is missing, it will return false
bool HasControllerElements(UxrHandSide handSide, UxrControllerElements controllerElements);
///
/// Gets the capabilities of the XR controller.
///
///
/// Which controller to check. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Device capabilities flags
UxrControllerInputCapabilities GetControllerCapabilities(UxrHandSide handSide);
///
/// Gets the state of an analog controller input element.
///
///
/// Which controller to get input from. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Element to get the input from
/// Whether to return ignored input by
/// Input value [0.0, 1.0]
float GetInput1D(UxrHandSide handSide, UxrInput1D input1D, bool getIgnoredInput = false);
///
/// Gets the state of a 2D input element (joystick, touchpad...).
///
///
/// Which controller to get input from. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Element to get the input from
/// Whether to return ignored input by
///
/// Vector2 telling the state of the controller element. Each component between [-1.0, 1.0]
///
Vector2 GetInput2D(UxrHandSide handSide, UxrInput2D input2D, bool getIgnoredInput = false);
///
/// Gets an uint value representing touch states for each the controller flags in the
/// current frame.
///
///
/// Which controller to get input from. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Whether to return ignored input by
/// Button flags representing touch states for each controller button in the current frame
///
uint GetButtonTouchFlags(UxrHandSide handSide, bool getIgnoredInput = false);
///
/// Gets an uint value representing touch states for each the controller flags in the
/// last frame.
///
///
/// Which controller to get input from. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Whether to return ignored input by
/// Button flags representing touch states for each controller button in the last frame
///
uint GetButtonTouchFlagsLastFrame(UxrHandSide handSide, bool getIgnoredInput = false);
///
/// Gets an uint value representing press states for each the controller flags in the
/// current frame.
///
///
/// Which controller to get input from. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Whether to return ignored input by
/// Button flags representing press states for each controller button in the current frame
///
uint GetButtonPressFlags(UxrHandSide handSide, bool getIgnoredInput = false);
///
/// Gets an uint value representing press states for each the in the last frame.
///
///
/// Which controller to get input from. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Whether to return ignored input by
/// Button flags representing press states for each controller button in the last frame
///
uint GetButtonPressFlagsLastFrame(UxrHandSide handSide, bool getIgnoredInput = false);
///
/// Checks if a given input event took place for a button or all buttons in a set in the current frame.
///
///
/// Which controller to get input from. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
///
/// Button (or buttons by flag composition) to check. If it's a combination, all buttons require to
/// meet the event criteria
///
/// Input event type to check for
/// Whether to return ignored input by
///
/// True if the given event happened during the current frame for the specified button. If more than one button
/// was specified by using flags it will return true only if the input event happened for all the given buttons.
///
bool GetButtonsEvent(UxrHandSide handSide, UxrInputButtons buttons, UxrButtonEventType buttonEventType, bool getIgnoredInput = false);
///
/// Checks if a given input event took place for a button or any button in a set in the current frame.
///
///
/// Which controller to get input from. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
///
/// Button (or buttons by flag composition) to check. If it's a combination, any button that meets
/// the event criteria will be enough
///
/// Input event type to check for
/// Whether to return ignored input by
///
/// True if the given event happened during the current frame for the specified button. If more than one button
/// was specified by using flags it will return true as long as any button had the event.
///
bool GetButtonsEventAny(UxrHandSide handSide, UxrInputButtons buttons, UxrButtonEventType buttonEventType, bool getIgnoredInput = false);
///
/// Checks if the given button or all buttons in a set are being touched in the current frame.
///
///
/// Which controller to get input from. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Button (or buttons by flag composition) to check
/// Whether to return ignored input by
///
/// True if the given button is being touched in the current frame. If more than one button was specified by using
/// flags it will return true only if all are being touched.
///
bool GetButtonsTouch(UxrHandSide handSide, UxrInputButtons buttons, bool getIgnoredInput = false);
///
/// Checks if the given button or any button in a set is being touched in the current frame.
///
///
/// Which controller to get input from. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Button (or buttons by flag composition) to check
/// Whether to return ignored input by
///
/// True if the given button is being touched in the current frame. If more than one button was specified by using
/// flags it will return true if any button in the set is being touched.
///
bool GetButtonsTouchAny(UxrHandSide handSide, UxrInputButtons buttons, bool getIgnoredInput = false);
///
/// Checks if the given button or buttons are being touched in the current frame but weren't the previous frame
/// (touch-down).
///
///
/// Which controller to get input from. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Button (or buttons by flag composition) to check
/// Whether to return ignored input by
///
/// True if the given button is just started being touched in the current frame. If more than one button was specified
/// by using flags it will return true only if all meet the condition.
///
bool GetButtonsTouchDown(UxrHandSide handSide, UxrInputButtons buttons, bool getIgnoredInput = false);
///
/// Checks if the given button or any button in a set is being touched in the current frame but not in the previous
/// frame (touch-down).
///
///
/// Which controller to get input from. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Button (or buttons by flag composition) to check
/// Whether to return ignored input by
///
/// True if the given button is just started being touched in the current frame. If more than one button was specified
/// by using flags it will return true if any meets the condition.
///
bool GetButtonsTouchDownAny(UxrHandSide handSide, UxrInputButtons buttons, bool getIgnoredInput = false);
///
/// Checks if the given button or buttons aren't being touched in the current frame but were during the previous frame
/// (release touch).
///
///
/// Which controller to get input from. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Button (or buttons by flag composition) to check
/// Whether to return ignored input by
///
/// True if the given button is being released from touching in the current frame. If more than one button was
/// specified by using flags it will return true only if all meet the condition.
///
bool GetButtonsTouchUp(UxrHandSide handSide, UxrInputButtons buttons, bool getIgnoredInput = false);
///
/// Checks if the given button or any button in a set isn't being touched in the current frame but was during the
/// previous frame (release touch).
///
///
/// Which controller to get input from. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Button (or buttons by flag composition) to check
/// Whether to return ignored input by
///
/// True if the given button is being released from touching in the current frame. If more than one button was
/// specified by using flags it will return true as long as any meets the condition.
///
bool GetButtonsTouchUpAny(UxrHandSide handSide, UxrInputButtons buttons, bool getIgnoredInput = false);
///
/// Checks if the given button or buttons are being pressed in the current frame.
///
///
/// Which controller to get input from. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Button (or buttons by flag composition) to check
/// Whether to return ignored input by
///
/// True if the given button is being pressed in the current frame. If more than one button was specified by using
/// flags it will return true only if all are being pressed.
///
bool GetButtonsPress(UxrHandSide handSide, UxrInputButtons buttons, bool getIgnoredInput = false);
///
/// Checks if the given button or any button in a set is being pressed in the current frame.
///
///
/// Which controller to get input from. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Button (or buttons by flag composition) to check
/// Whether to return ignored input by
///
/// True if the given button is being pressed in the current frame. If more than one button was specified by using
/// flags it will return true as long as any is being pressed.
///
bool GetButtonsPressAny(UxrHandSide handSide, UxrInputButtons buttons, bool getIgnoredInput = false);
///
/// Checks if the given button or buttons are being pressed in the current frame but weren't the previous frame
/// (press-down).
///
///
/// Which controller to get input from. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Button (or buttons by flag composition) to check
/// Whether to return ignored input by
///
/// True if the given button is just started being pressed in the current frame. If more than one button was specified
/// by using flags it will return true only if all meet the condition.
///
bool GetButtonsPressDown(UxrHandSide handSide, UxrInputButtons buttons, bool getIgnoredInput = false);
///
/// Checks if the given button or any button in a set is being pressed in the current frame but wasn't the previous
/// frame (press-down).
///
///
/// Which controller to get input from. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Button (or buttons by flag composition) to check
/// Whether to return ignored input by
///
/// True if the given button is just started being pressed in the current frame. If more than one button was specified
/// by using flags it will return true only if any meets the condition.
///
bool GetButtonsPressDownAny(UxrHandSide handSide, UxrInputButtons buttons, bool getIgnoredInput = false);
///
/// Checks if the given button or buttons aren't being pressed in the current frame but were during the previous frame
/// (release press).
///
///
/// Which controller to get input from. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Button (or buttons by flag composition) to check
/// Whether to return ignored input by
///
/// True if the given button is being released from pressing in the current frame. If more than one button was
/// specified by using flags it will return true only if all meet the condition.
///
bool GetButtonsPressUp(UxrHandSide handSide, UxrInputButtons buttons, bool getIgnoredInput = false);
///
/// Checks if the given button or any button in a set isn't being pressed in the current frame but was during the
/// previous frame (release press).
///
///
/// Which controller to get input from. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Button (or buttons by flag composition) to check
/// Whether to return ignored input by
///
/// True if the given button is being released from pressing in the current frame. If more than one button was
/// specified by using flags it will return true if any meets the condition.
///
bool GetButtonsPressUpAny(UxrHandSide handSide, UxrInputButtons buttons, bool getIgnoredInput = false);
///
/// Sends haptic feedback to a controller if the controller supports it.
///
///
/// Which controller to send the haptic feedback to. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Clip to send
void SendHapticFeedback(UxrHandSide handSide, UxrHapticClip hapticClip);
///
/// Sends haptic feedback to a controller if the controller supports it.
///
///
/// Which controller to send the haptic feedback to. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Frequency of the feedback in hz
/// Amplitude of the feedback between range [0.0, 1.0]
/// Feedback duration in seconds
/// The mode (stop and override all current haptics or mix it with the current existing haptics)
void SendHapticFeedback(UxrHandSide handSide,
float frequency,
float amplitude,
float durationSeconds,
UxrHapticMode hapticMode = UxrHapticMode.Mix);
///
/// Sends a predefined haptic clip to a controller.
///
///
/// Which controller to send the haptic feedback to. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// The clip type from a set of predefined clips
/// The intensity of the haptic feedback
/// The duration in seconds. A zero/negative value will use a default duration.
/// Whether the clip will stop all currently playing haptics or mix with them
public void SendHapticFeedback(UxrHandSide handSide,
UxrHapticClipType clipType,
float amplitude,
float durationSeconds = -1.0f,
UxrHapticMode hapticMode = UxrHapticMode.Mix);
///
/// Sends haptic feedback to XR controllers that are being used to manipulate a grabbable object.
/// Each hand associated to an XR controller that is grabbing the object will receive haptic feedback.
///
/// Grabbable object
/// Clip type to send
/// Intensity of the haptic feedback
/// Duration in seconds
/// Override current haptic feedback or mix it?
public void SendGrabbableHapticFeedback(UxrGrabbableObject grabbableObject,
UxrHapticClipType clipType,
float amplitude,
float durationSeconds = -1.0f,
UxrHapticMode hapticMode = UxrHapticMode.Mix);
///
/// Sends haptic feedback to XR controllers that are being used to manipulate a grabbable object.
/// Each hand associated to an XR controller that is grabbing the object will receive haptic feedback.
///
/// Grabbable object
/// Haptic clip to send
public void SendGrabbableHapticFeedback(UxrGrabbableObject grabbableObject, UxrHapticClip hapticClip);
///
/// Stops all current haptics in a given controller.
///
///
/// Which controller to stop sending haptic feedback to. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
void StopHapticFeedback(UxrHandSide handSide);
///
/// Gets the instanced controller 3D model for a given hand.
///
///
/// Which controller to get the 3D model of. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
UxrController3DModel GetController3DModel(UxrHandSide handSide);
///
/// Returns a list of GameObjects that represent parts of the instantiated controller. This can be useful
/// to highlight buttons or other elements during tutorials.
/// Functionality to make these elements blink is also provided by the framework.
///
///
/// Which controller to get the elements of. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Element (or elements using flags) to retrieve the GameObject(s) for
/// A list of GameObject, one for each element requested
///
///
///
///
///
IEnumerable GetControllerElementsGameObjects(UxrHandSide handSide, UxrControllerElements controllerElements);
///
/// Starts blinking one or more elements in a controller. This can be useful during tutorials to highlight which
/// button(s) to press.
///
///
/// Which controller. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Element (or elements using flags) that should blink
///
/// Emission color use to blink. Usually it can be set to white with a mid alpha value to avoid
/// too much brightness
///
/// Blinks per second
/// Duration in seconds that it should blink
///
///
///
///
///
void StartControllerElementsBlinking(UxrHandSide handSide,
UxrControllerElements controllerElements,
Color emissionColor,
float blinksPerSec = 3.0f,
float durationSeconds = -1.0f);
///
/// Stops controller elements to blink
///
///
/// Which controller. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Element (or elements using flags) that should stop blinking
///
///
///
///
///
void StopControllerElementsBlinking(UxrHandSide handSide, UxrControllerElements controllerElements);
///
/// Stops all controller elements to blink
///
///
/// Which controller. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
///
///
///
///
///
void StopAllBlinking(UxrHandSide handSide);
///
/// Checks if any specific controller element is currently blinking
///
///
/// Which controller. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Element (or elements using flags) that should be checked
/// True if any of the given elements is blinking
///
///
///
///
///
bool IsAnyControllerElementBlinking(UxrHandSide handSide, UxrControllerElements controllerElements);
///
/// Checks if all elements of a specific controller element are currently blinking
///
///
/// Which controller. In devices where
/// is false, such as in gamepads, both hands will address the single device.
///
/// Element (or elements using flags) that should be checked
/// True if all of the given elements are blinking
///
///
///
///
///
bool AreAllControllerElementsBlinking(UxrHandSide handSide, UxrControllerElements controllerElements);
#endregion
}
}