summaryrefslogtreecommitdiff
path: root/Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts
diff options
context:
space:
mode:
authorpryazha <pryadeiniv@mail.ru>2025-07-02 08:46:23 -0700
committerpryazha <pryadeiniv@mail.ru>2025-07-02 08:46:23 -0700
commit8263edd59284aba390aca011d25b79efecef4c48 (patch)
tree6346e2afaaabd32156601cafaf20d4ee813befaf /Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts
Diffstat (limited to 'Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts')
-rw-r--r--Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorControllerUI.cs253
-rw-r--r--Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorControllerUI.cs.meta11
-rw-r--r--Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorHandsUI.cs206
-rw-r--r--Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorHandsUI.cs.meta11
-rw-r--r--Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorUI.cs1181
-rw-r--r--Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorUI.cs.meta11
6 files changed, 1673 insertions, 0 deletions
diff --git a/Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorControllerUI.cs b/Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorControllerUI.cs
new file mode 100644
index 0000000..fa6fdad
--- /dev/null
+++ b/Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorControllerUI.cs
@@ -0,0 +1,253 @@
+using UnityEngine.InputSystem;
+using UnityEngine.UI;
+using UnityEngine.XR.Interaction.Toolkit.Inputs.Simulation;
+
+namespace UnityEngine.XR.Interaction.Toolkit.Samples.DeviceSimulator
+{
+ [RequireComponent(typeof(XRDeviceSimulatorUI))]
+ class XRDeviceSimulatorControllerUI : MonoBehaviour
+ {
+ [Header("General")]
+
+ [SerializeField]
+ Image m_ControllerImage;
+
+ [SerializeField]
+ Image m_ControllerOverlayImage;
+
+ [Header("Primary Button")]
+
+ [SerializeField]
+ Image m_PrimaryButtonImage;
+
+ [SerializeField]
+ Text m_PrimaryButtonText;
+
+ [SerializeField]
+ Image m_PrimaryButtonIcon;
+
+ [Header("Secondary Button")]
+
+ [SerializeField]
+ Image m_SecondaryButtonImage;
+
+ [SerializeField]
+ Text m_SecondaryButtonText;
+
+ [SerializeField]
+ Image m_SecondaryButtonIcon;
+
+ [Header("Trigger")]
+
+ [SerializeField]
+ Image m_TriggerButtonImage;
+
+ [SerializeField]
+ Text m_TriggerButtonText;
+
+ [SerializeField]
+ Image m_TriggerButtonIcon;
+
+ [Header("Grip")]
+
+ [SerializeField]
+ Image m_GripButtonImage;
+
+ [SerializeField]
+ Text m_GripButtonText;
+
+ [SerializeField]
+ Image m_GripButtonIcon;
+
+ [Header("Thumbstick")]
+
+ [SerializeField]
+ Image m_ThumbstickButtonImage;
+
+ [SerializeField]
+ Text m_ThumbstickButtonText;
+
+ [SerializeField]
+ Image m_ThumbstickButtonIcon;
+
+ [Header("Menu")]
+
+ [SerializeField]
+ Image m_MenuButtonImage;
+
+ [SerializeField]
+ Text m_MenuButtonText;
+
+ [SerializeField]
+ Image m_MenuButtonIcon;
+
+ XRDeviceSimulatorUI m_MainUIManager;
+
+ bool m_PrimaryButtonActivated;
+ bool m_SecondaryButtonActivated;
+ bool m_TriggerActivated;
+ bool m_GripActivated;
+ bool m_MenuActivated;
+ bool m_XAxisTranslateActivated;
+ bool m_YAxisTranslateActivated;
+
+ protected void Awake()
+ {
+ m_MainUIManager = GetComponent<XRDeviceSimulatorUI>();
+ }
+
+ internal void Initialize(XRDeviceSimulator simulator)
+ {
+ m_PrimaryButtonText.text = simulator.primaryButtonAction.action.controls[0].displayName;
+ m_SecondaryButtonText.text = simulator.secondaryButtonAction.action.controls[0].displayName;
+ m_GripButtonText.text = simulator.gripAction.action.controls[0].displayName;
+ m_TriggerButtonText.text = simulator.triggerAction.action.controls[0].displayName;
+ m_MenuButtonText.text = simulator.menuAction.action.controls[0].displayName;
+
+ var disabledImgColor = m_MainUIManager.disabledColor;
+ m_ThumbstickButtonImage.color = disabledImgColor;
+ m_ControllerImage.color = m_MainUIManager.disabledDeviceColor;
+ m_ControllerOverlayImage.color = disabledImgColor;
+ }
+
+ internal void SetAsActiveController(bool active, XRDeviceSimulator simulator, bool isRestingHand = false)
+ {
+ var controls = isRestingHand ?
+ simulator.restingHandAxis2DAction.action.controls :
+ simulator.axis2DAction.action.controls;
+
+ m_ThumbstickButtonText.text = $"{controls[0].displayName}, {controls[1].displayName}, {controls[2].displayName}, {controls[3].displayName}";
+
+ UpdateButtonVisuals(active, m_PrimaryButtonIcon, m_PrimaryButtonText, simulator.primaryButtonAction.action.controls[0]);
+ UpdateButtonVisuals(active, m_SecondaryButtonIcon, m_SecondaryButtonText, simulator.secondaryButtonAction.action.controls[0]);
+ UpdateButtonVisuals(active, m_TriggerButtonIcon, m_TriggerButtonText, simulator.triggerAction.action.controls[0]);
+ UpdateButtonVisuals(active, m_GripButtonIcon, m_GripButtonText, simulator.gripAction.action.controls[0]);
+ UpdateButtonVisuals(active, m_MenuButtonIcon, m_MenuButtonText, simulator.menuAction.action.controls[0]);
+ UpdateButtonVisuals(active || isRestingHand, m_ThumbstickButtonIcon, m_ThumbstickButtonText, simulator.axis2DAction.action.controls[0]);
+
+ if (active)
+ {
+ UpdateButtonColor(m_PrimaryButtonImage, m_PrimaryButtonActivated);
+ UpdateButtonColor(m_SecondaryButtonImage, m_SecondaryButtonActivated);
+ UpdateButtonColor(m_TriggerButtonImage, m_TriggerActivated);
+ UpdateButtonColor(m_GripButtonImage, m_GripActivated);
+ UpdateButtonColor(m_MenuButtonImage, m_MenuActivated);
+ UpdateButtonColor(m_ThumbstickButtonImage, m_XAxisTranslateActivated || m_YAxisTranslateActivated);
+
+ m_ControllerImage.color = m_MainUIManager.deviceColor;
+ m_ControllerOverlayImage.color = m_MainUIManager.enabledColor;
+ }
+ else
+ {
+ UpdateDisableControllerButton(m_PrimaryButtonActivated, m_PrimaryButtonImage, m_PrimaryButtonIcon, m_PrimaryButtonText);
+ UpdateDisableControllerButton(m_SecondaryButtonActivated, m_SecondaryButtonImage, m_SecondaryButtonIcon, m_SecondaryButtonText);
+ UpdateDisableControllerButton(m_TriggerActivated, m_TriggerButtonImage, m_TriggerButtonIcon, m_TriggerButtonText);
+ UpdateDisableControllerButton(m_GripActivated, m_GripButtonImage, m_GripButtonIcon, m_GripButtonText);
+ UpdateDisableControllerButton(m_MenuActivated, m_MenuButtonImage, m_MenuButtonIcon, m_MenuButtonText);
+
+ if (!isRestingHand)
+ UpdateDisableControllerButton(m_XAxisTranslateActivated || m_YAxisTranslateActivated, m_ThumbstickButtonImage, m_ThumbstickButtonIcon, m_ThumbstickButtonText);
+ else
+ m_ThumbstickButtonImage.color = m_MainUIManager.buttonColor;
+
+ m_ControllerImage.color = m_MainUIManager.disabledDeviceColor;
+ m_ControllerOverlayImage.color = m_MainUIManager.disabledColor;
+ }
+ }
+
+ // This function keeps the button selected color active if the key if hold when the controller is disabled.
+ // Other buttons are disabled to avoid adding extra noise.
+ void UpdateDisableControllerButton(bool active, Image button, Image buttonIcon, Text buttonText)
+ {
+ if (active)
+ {
+ var tmpColor = m_MainUIManager.selectedColor;
+ tmpColor.a = 0.5f;
+ button.color = tmpColor;
+ buttonText.gameObject.SetActive(true);
+ buttonIcon.gameObject.SetActive(true);
+ }
+ else
+ {
+ button.color = m_MainUIManager.disabledButtonColor;
+ buttonText.gameObject.SetActive(false);
+ buttonIcon.gameObject.SetActive(false);
+ }
+ }
+
+ void UpdateButtonVisuals(bool active, Image buttonIcon, Text buttonText, InputControl control)
+ {
+ buttonText.gameObject.SetActive(active);
+ buttonIcon.gameObject.SetActive(active);
+
+ var color = active ? m_MainUIManager.enabledColor : m_MainUIManager.disabledColor;
+ buttonText.color = color;
+ buttonIcon.color = color;
+
+ buttonIcon.transform.localScale = Vector3.one;
+ buttonIcon.sprite = m_MainUIManager.GetInputIcon(control);
+ switch (control.name)
+ {
+ case "leftButton":
+ buttonText.text = "L Mouse";
+ buttonIcon.color = Color.white;
+ buttonIcon.transform.localScale = new Vector3(-1f, 1f, 1f);
+ break;
+ case "rightButton":
+ buttonText.text = "R Mouse";
+ buttonIcon.color = Color.white;
+ break;
+ default:
+ buttonIcon.sprite = m_MainUIManager.keyboardSprite;
+ break;
+ }
+ }
+
+ void UpdateButtonColor(Image image, bool activated)
+ {
+ image.color = activated ? m_MainUIManager.selectedColor : m_MainUIManager.buttonColor;
+ }
+
+ internal void OnPrimaryButton(bool activated)
+ {
+ m_PrimaryButtonActivated = activated;
+ UpdateButtonColor(m_PrimaryButtonImage, activated);
+ }
+
+ internal void OnSecondaryButton(bool activated)
+ {
+ m_SecondaryButtonActivated = activated;
+ UpdateButtonColor(m_SecondaryButtonImage, activated);
+ }
+
+ internal void OnTrigger(bool activated)
+ {
+ m_TriggerActivated = activated;
+ UpdateButtonColor(m_TriggerButtonImage, activated);
+ }
+
+ internal void OnGrip(bool activated)
+ {
+ m_GripActivated = activated;
+ UpdateButtonColor(m_GripButtonImage, activated);
+ }
+
+ internal void OnMenu(bool activated)
+ {
+ m_MenuActivated = activated;
+ UpdateButtonColor(m_MenuButtonImage, activated);
+ }
+
+ internal void OnXAxisTranslatePerformed(bool activated)
+ {
+ m_XAxisTranslateActivated = activated;
+ UpdateButtonColor(m_ThumbstickButtonImage, activated);
+ }
+
+ internal void OnZAxisTranslatePerformed(bool activated)
+ {
+ m_YAxisTranslateActivated = activated;
+ UpdateButtonColor(m_ThumbstickButtonImage, activated);
+ }
+ }
+}
diff --git a/Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorControllerUI.cs.meta b/Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorControllerUI.cs.meta
new file mode 100644
index 0000000..84889f4
--- /dev/null
+++ b/Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorControllerUI.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a907ece591e731e49b5d7be45f089972
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorHandsUI.cs b/Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorHandsUI.cs
new file mode 100644
index 0000000..9089792
--- /dev/null
+++ b/Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorHandsUI.cs
@@ -0,0 +1,206 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine.InputSystem;
+using UnityEngine.UI;
+using UnityEngine.XR.Interaction.Toolkit.Inputs.Readers;
+using UnityEngine.XR.Interaction.Toolkit.Inputs.Simulation;
+
+namespace UnityEngine.XR.Interaction.Toolkit.Samples.DeviceSimulator
+{
+ [RequireComponent(typeof(XRDeviceSimulatorUI))]
+ class XRDeviceSimulatorHandsUI : MonoBehaviour
+ {
+ [Serializable]
+ class HandExpressionUI
+ {
+ [SerializeField]
+ Sprite m_Sprite;
+ [SerializeField]
+ Image m_ButtonImage;
+ [SerializeField]
+ Image m_Icon;
+ [SerializeField]
+ Text m_BindText;
+ [SerializeField]
+ Text m_TitleText;
+
+ InputAction m_Action;
+
+ public Sprite sprite
+ {
+ get => m_Sprite;
+ set => m_Sprite = value;
+ }
+
+ public void Initialize(InputAction action, string name, Sprite icon)
+ {
+ m_Action = action;
+ m_BindText.text = m_Action?.controls[0].displayName;
+ m_TitleText.text = $"[{name}]";
+ if (icon != null)
+ m_Sprite = icon;
+ }
+
+ public void UpdateButtonVisuals(bool active, XRDeviceSimulatorUI uiManager)
+ {
+ UpdateButtonActive(active);
+
+ Color color = active ? uiManager.enabledColor : uiManager.disabledColor;
+ m_BindText.color = color;
+ m_TitleText.color = color;
+ m_Icon.color = color;
+
+ m_Icon.transform.localScale = Vector3.one;
+ m_Icon.sprite = uiManager.GetInputIcon(m_Action?.controls[0]);
+ m_Icon.enabled = m_Icon.sprite != null;
+ }
+
+ public void SetButtonColor(Color color)
+ {
+ m_ButtonImage.color = color;
+ }
+
+ public void UpdateButtonActive(bool active)
+ {
+ m_BindText.gameObject.SetActive(active);
+ m_TitleText.gameObject.SetActive(active);
+ m_Icon.gameObject.SetActive(active);
+ }
+ }
+
+ [Header("General")]
+
+ [SerializeField]
+ Image m_HandImage;
+
+ [SerializeField]
+ Sprite m_HandDefaultSprite;
+
+ [SerializeField]
+ List<HandExpressionUI> m_Expressions = new List<HandExpressionUI>();
+
+ XRDeviceSimulatorUI m_MainUIManager;
+ HandExpressionUI m_ActiveExpression;
+ SimulatedHandExpressionManager m_HandExpressionManager;
+
+ protected void Awake()
+ {
+ m_MainUIManager = GetComponent<XRDeviceSimulatorUI>();
+ }
+
+ internal void Initialize(XRDeviceSimulator simulator)
+ {
+ if (!simulator.gameObject.TryGetComponent(out m_HandExpressionManager))
+ {
+ Debug.LogError($"Could not find SimulatedHandExpressionManager component on {simulator.name}, disabling simulator UI.");
+ gameObject.SetActive(false);
+ return;
+ }
+
+ for (var index = 0; index < m_HandExpressionManager.simulatedHandExpressions.Count; ++index)
+ {
+ var simulatedExpression = m_HandExpressionManager.simulatedHandExpressions[index];
+ if (index >= m_Expressions.Count)
+ {
+ Debug.LogWarning("The Device Simulator has more expressions than the UI can display.", this);
+ }
+ else
+ {
+ InputAction action = null;
+ switch (simulatedExpression.toggleInput.inputSourceMode)
+ {
+ case XRInputButtonReader.InputSourceMode.InputActionReference:
+ action = simulatedExpression.toggleInput.inputActionReferencePerformed;
+ break;
+ case XRInputButtonReader.InputSourceMode.InputAction:
+ action = simulatedExpression.toggleInput.inputActionPerformed;
+ break;
+ default:
+ Debug.LogWarning($"Toggle Input for Simulated Hand Expression \"{simulatedExpression.name}\" is not an input action, cannot display binding or icon in UI.", this);
+ break;
+ }
+
+ m_Expressions[index].Initialize(action, simulatedExpression.name, simulatedExpression.icon);
+ }
+ }
+
+ m_HandImage.color = m_MainUIManager.disabledDeviceColor;
+ }
+
+ internal void SetActive(bool active, XRDeviceSimulator simulator)
+ {
+ foreach (var expression in m_Expressions)
+ {
+ expression.UpdateButtonVisuals(active, m_MainUIManager);
+ }
+
+ if (active)
+ {
+ foreach (var expression in m_Expressions)
+ {
+ var isActiveExpression = m_ActiveExpression == expression;
+ expression.SetButtonColor(isActiveExpression ? m_MainUIManager.selectedColor : m_MainUIManager.buttonColor);
+ }
+
+ m_HandImage.color = m_MainUIManager.deviceColor;
+ }
+ else
+ {
+ var disabledSelectedColor = m_MainUIManager.selectedColor;
+ disabledSelectedColor.a = 0.5f;
+ foreach (var expression in m_Expressions)
+ {
+ var isActiveExpression = m_ActiveExpression == expression;
+ expression.SetButtonColor(isActiveExpression ? disabledSelectedColor : m_MainUIManager.disabledButtonColor);
+ expression.UpdateButtonActive(isActiveExpression);
+ }
+
+ m_HandImage.color = m_MainUIManager.disabledDeviceColor;
+ }
+ }
+
+ internal void ToggleExpression(SimulatedHandExpression simulatedExpression, XRDeviceSimulator simulator)
+ {
+ // The index of the hand expression corresponds 1:1 with the index of the UI button
+ var index = m_HandExpressionManager.simulatedHandExpressions.IndexOf(simulatedExpression);
+
+ if (index >= m_Expressions.Count)
+ {
+ Debug.LogWarning("The Device Simulator has more expressions than the UI can display.", this);
+ }
+ else if (index < 0)
+ {
+ Debug.LogError($"The Device Simulator tried to toggle {simulatedExpression.name} but it was not found in the list of simulated hand expressions, the UI can not be updated.", this);
+ }
+ else
+ {
+ ToggleExpression(m_Expressions[index]);
+ }
+ }
+
+ void ToggleExpression(HandExpressionUI expression)
+ {
+ if (m_ActiveExpression == expression)
+ {
+ SetExpressionActiveStatus(false, expression);
+ m_ActiveExpression = null;
+ m_HandImage.sprite = m_HandDefaultSprite;
+ }
+ else
+ {
+ if (m_ActiveExpression != null)
+ SetExpressionActiveStatus(false, m_ActiveExpression);
+
+ SetExpressionActiveStatus(true, expression);
+ m_ActiveExpression = expression;
+ }
+ }
+
+ void SetExpressionActiveStatus(bool isActive, HandExpressionUI expression)
+ {
+ expression.SetButtonColor(isActive ? m_MainUIManager.selectedColor : m_MainUIManager.buttonColor);
+ if (isActive)
+ m_HandImage.sprite = expression.sprite;
+ }
+ }
+}
diff --git a/Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorHandsUI.cs.meta b/Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorHandsUI.cs.meta
new file mode 100644
index 0000000..5171c4d
--- /dev/null
+++ b/Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorHandsUI.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f35ac646ecbef4ece8c3eac9e74e1828
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorUI.cs b/Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorUI.cs
new file mode 100644
index 0000000..76766a2
--- /dev/null
+++ b/Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorUI.cs
@@ -0,0 +1,1181 @@
+using System;
+using UnityEngine.InputSystem;
+using UnityEngine.Serialization;
+using UnityEngine.UI;
+using UnityEngine.XR.Interaction.Toolkit.Inputs.Simulation;
+
+#if UNITY_EDITOR
+using UnityEditor;
+#endif
+
+namespace UnityEngine.XR.Interaction.Toolkit.Samples.DeviceSimulator
+{
+ class XRDeviceSimulatorUI : MonoBehaviour
+ {
+ XRDeviceSimulator m_Simulator;
+ SimulatedDeviceLifecycleManager m_DeviceLifecycleManager;
+ SimulatedHandExpressionManager m_HandExpressionManager;
+
+ const string k_MouseDeviceType = "Mouse";
+ const string k_TranslateLookText = "Move";
+ const string k_RotateLookText = "Look";
+
+#if UNITY_EDITOR
+ const string k_MenuOpenStateKey = "XRI." + nameof(XRDeviceSimulatorUI) + ".MenuOpenState";
+#endif
+ [SerializeField]
+ [HideInInspector]
+ bool m_IsMenuOpen = true;
+
+ bool isMenuOpen
+ {
+ get
+ {
+#if UNITY_EDITOR
+ m_IsMenuOpen = EditorPrefs.GetBool(k_MenuOpenStateKey, m_IsMenuOpen);
+#endif
+ return m_IsMenuOpen;
+ }
+
+ set
+ {
+ m_IsMenuOpen = value;
+#if UNITY_EDITOR
+ EditorPrefs.SetBool(k_MenuOpenStateKey, m_IsMenuOpen);
+#endif
+ }
+ }
+
+ [Header("Open/Close Panels")]
+
+ [SerializeField]
+ GameObject m_XRDeviceSimulatorMainPanel;
+ [SerializeField]
+ GameObject m_XRDeviceSimulatorCollapsedPanel;
+
+ [Header("Sprites")]
+
+ [SerializeField]
+ Sprite m_HmdSpriteDark;
+ [SerializeField]
+ Sprite m_HmdSpriteLight;
+
+ [SerializeField]
+ Sprite m_KeyboardSprite;
+ internal Sprite keyboardSprite => m_KeyboardSprite;
+
+ [SerializeField]
+ Sprite m_MouseSprite;
+ internal Sprite mouseSprite => m_MouseSprite;
+
+ [SerializeField]
+ Sprite m_RMouseSpriteDark;
+ internal Sprite rMouseSpriteDark => m_RMouseSpriteDark;
+
+ [SerializeField]
+ Sprite m_RMouseSpriteLight;
+ internal Sprite rMouseSpriteLight => m_RMouseSpriteLight;
+
+ [HideInInspector]
+ [SerializeField]
+ Sprite m_RMouseSprite;
+ internal Sprite rMouseSprite
+ {
+ get
+ {
+#if !UNITY_EDITOR
+ if (m_RMouseSprite == null)
+ m_RMouseSprite = m_RMouseSpriteDark;
+#endif
+ return m_RMouseSprite;
+ }
+ }
+
+ [SerializeField]
+ Sprite m_RoundedRectangle;
+
+ [Header("General")]
+
+ [SerializeField]
+ Text m_CycleDevicesText;
+
+ [SerializeField]
+ Text m_CurrentSelectedDeviceText;
+
+ [Header("Headset Device")]
+
+ [SerializeField]
+ Image m_HeadsetImage;
+
+ [Space]
+
+ [SerializeField]
+ Image m_HeadsetMoveButton;
+
+ [SerializeField]
+ Image m_HeadsetMoveButtonIcon;
+
+ [SerializeField]
+ Text m_HeadsetMoveButtonText;
+
+ [SerializeField]
+ Image m_HeadsetMoveValueIcon;
+
+ [SerializeField]
+ Text m_HeadsetMoveValueText;
+
+ [Space]
+
+ [SerializeField]
+ Image m_HeadsetLookButton;
+
+ [SerializeField]
+ Text m_HeadsetLookButtonText;
+
+ [SerializeField]
+ Image m_HeadsetLookValueIcon;
+
+ [SerializeField]
+ Text m_HeadsetLookValueText;
+
+ [Space]
+
+ [SerializeField]
+ [FormerlySerializedAs("m_ShowCursorButton")]
+ Image m_CursorLockButton;
+
+ [SerializeField]
+ [FormerlySerializedAs("m_ShowCursorValueText")]
+ Text m_CursorLockValueText;
+
+ [Space]
+
+ [SerializeField]
+ Text m_MouseModeButtonText;
+
+ [SerializeField]
+ Text m_MouseModeValueText;
+
+ [Space]
+
+ [SerializeField]
+ Image m_HeadsetSelectedButton;
+
+ [SerializeField]
+ Text m_HeadsetSelectedValueText;
+
+ [Header("Controllers")]
+
+ [SerializeField]
+ Image m_ControllerSelectedButton;
+
+ [SerializeField]
+ Image m_ControllerSelectedIcon;
+
+ [SerializeField]
+ Text m_ControllerSelectedText;
+
+ [SerializeField]
+ Text m_ControllersSelectedValueText;
+
+ [SerializeField]
+ CanvasGroup m_ControllersCanvasGroup;
+
+ [Header("Left Controller")]
+
+ [SerializeField]
+ XRDeviceSimulatorControllerUI m_LeftController;
+
+ [SerializeField]
+ Text m_LeftControllerButtonText;
+
+ [Header("Right Controller")]
+
+ [SerializeField]
+ XRDeviceSimulatorControllerUI m_RightController;
+
+ [SerializeField]
+ Text m_RightControllerButtonText;
+
+ [Header("Hands")]
+
+ [SerializeField]
+ Image m_HandsSelectedButton;
+
+ [SerializeField]
+ Image m_HandsSelectedIcon;
+
+ [SerializeField]
+ Text m_HandsSelectedText;
+
+ [SerializeField]
+ Image m_HandsSelectedValueIcon;
+
+ [SerializeField]
+ Text m_HandsSelectedValueText;
+
+ [SerializeField]
+ CanvasGroup m_HandsCanvasGroup;
+
+ [Header("Left Hand")]
+
+ [SerializeField]
+ XRDeviceSimulatorHandsUI m_LeftHand;
+
+ [SerializeField]
+ Text m_LeftHandButtonText;
+
+ [Header("Right Hand")]
+
+ [SerializeField]
+ XRDeviceSimulatorHandsUI m_RightHand;
+
+ [SerializeField]
+ Text m_RightHandButtonText;
+
+ static readonly Color k_EnabledColorDark = new Color(0xC4 / 255f, 0xC4 / 255f, 0xC4 / 255f);
+ static readonly Color k_EnabledColorLight = new Color(0x55 / 255f, 0x55 / 255f, 0x55 / 255f);
+ [HideInInspector]
+ [SerializeField]
+ Color m_EnabledColor = Color.clear;
+ internal Color enabledColor
+ {
+ get
+ {
+#if !UNITY_EDITOR
+ if (m_EnabledColor == Color.clear)
+ m_EnabledColor = k_EnabledColorDark;
+#endif
+ return m_EnabledColor;
+ }
+ }
+
+ static readonly Color k_DisabledColorDark = new Color(0xC4 / 255f, 0xC4 / 255f, 0xC4 / 255f, 0.5f);
+ static readonly Color k_DisabledColorLight = new Color(0x55 / 255f, 0x55 / 255f, 0x55 / 255f, 0.5f);
+ [HideInInspector]
+ [SerializeField]
+ Color m_DisabledColor = Color.clear;
+ internal Color disabledColor
+ {
+ get
+ {
+#if !UNITY_EDITOR
+ if (m_DisabledColor == Color.clear)
+ m_DisabledColor = k_DisabledColorDark;
+#endif
+ return m_DisabledColor;
+ }
+ }
+
+ static readonly Color k_ButtonColorDark = new Color(0x55 / 255f, 0x55 / 255f, 0x55 / 255f);
+ static readonly Color k_ButtonColorLight = new Color(0xE4 / 255f, 0xE4 / 255f, 0xE4 / 255f);
+ [HideInInspector]
+ [SerializeField]
+ Color m_ButtonColor = Color.clear;
+ internal Color buttonColor
+ {
+ get
+ {
+#if !UNITY_EDITOR
+ if (m_ButtonColor == Color.clear)
+ m_ButtonColor = k_ButtonColorDark;
+#endif
+ return m_ButtonColor;
+ }
+ }
+
+ static readonly Color k_DisabledButtonColorDark = new Color(0x55 / 255f, 0x55 / 255f, 0x55 / 255f, 0.5f);
+ static readonly Color k_DisabledButtonColorLight = new Color(0xE4 / 255f, 0xE4 / 255f, 0xE4 / 255f, 0.5f);
+ [HideInInspector]
+ [SerializeField]
+ Color m_DisabledButtonColor = Color.clear;
+ internal Color disabledButtonColor
+ {
+ get
+ {
+#if !UNITY_EDITOR
+ if (m_DisabledButtonColor == Color.clear)
+ m_DisabledButtonColor = k_DisabledButtonColorDark;
+#endif
+ return m_DisabledButtonColor;
+ }
+ }
+
+ static readonly Color k_SelectedColorDark = new Color(0x4F / 255f, 0x65 / 255f, 0x7F / 255f);
+ static readonly Color k_SelectedColorLight = new Color(0x96 / 255f, 0xC3 / 255f, 0xFB / 255f);
+ [HideInInspector]
+ [SerializeField]
+ Color m_SelectedColor = Color.clear;
+ internal Color selectedColor
+ {
+ get
+ {
+#if !UNITY_EDITOR
+ if (m_SelectedColor == Color.clear)
+ m_SelectedColor = k_SelectedColorDark;
+#endif
+ return m_SelectedColor;
+ }
+ }
+
+ static readonly Color k_BackgroundColorDark = Color.black;
+ static readonly Color k_BackgroundColorLight = new Color(0xB6 / 255f, 0xB6 / 255f, 0xB6 / 255f);
+ [HideInInspector]
+ [SerializeField]
+ Color m_BackgroundColor = Color.clear;
+ internal Color backgroundColor
+ {
+ get
+ {
+#if !UNITY_EDITOR
+ if (m_BackgroundColor == Color.clear)
+ m_BackgroundColor = k_BackgroundColorDark;
+#endif
+ return m_BackgroundColor;
+ }
+ }
+
+ static readonly Color k_DeviceColorDark = new Color(0x6E / 255f, 0x6E / 255f, 0x6E / 255f);
+ static readonly Color k_DeviceColorLight = new Color(0xE4 / 255f, 0xE4 / 255f, 0xE4 / 255f);
+ [HideInInspector]
+ [SerializeField]
+ Color m_DeviceColor = Color.clear;
+ internal Color deviceColor
+ {
+ get
+ {
+#if !UNITY_EDITOR
+ if (m_DeviceColor == Color.clear)
+ m_DeviceColor = k_DeviceColorDark;
+#endif
+ return m_DeviceColor;
+ }
+ }
+
+ static readonly Color k_DisabledDeviceColorDark = new Color(0x58 / 255f, 0x58 / 255f, 0x58 / 255f);
+ static readonly Color k_DisabledDeviceColorLight = new Color(0xA2 / 255f, 0xA2 / 255f, 0xA2 / 255f, 0.5f);
+ [HideInInspector]
+ [SerializeField]
+ Color m_DisabledDeviceColor = Color.clear;
+ internal Color disabledDeviceColor
+ {
+ get
+ {
+#if !UNITY_EDITOR
+ if (m_DisabledDeviceColor == Color.clear)
+ m_DisabledDeviceColor = k_DisabledDeviceColorDark;
+#endif
+ return m_DisabledDeviceColor;
+ }
+ }
+
+
+ // Handles 2 axis activation for 1 UI Button
+ bool m_XAxisActivated;
+ bool m_ZAxisActivated;
+
+ /// <summary>
+ /// See <see cref="MonoBehaviour"/>.
+ /// </summary>
+ protected void Start()
+ {
+ var simulator = GetComponentInParent<XRDeviceSimulator>();
+ if (simulator != null)
+ Initialize(simulator);
+ }
+
+ /// <summary>
+ /// See <see cref="MonoBehaviour"/>.
+ /// </summary>
+ protected void Update()
+ {
+#if XR_HANDS_1_1_OR_NEWER
+ if (m_DeviceLifecycleManager.deviceMode != SimulatedDeviceLifecycleManager.DeviceMode.Hand)
+ return;
+
+ for (var index = 0; index < m_HandExpressionManager.simulatedHandExpressions.Count; ++index)
+ {
+ var simulatedExpression = m_HandExpressionManager.simulatedHandExpressions[index];
+ if (simulatedExpression.toggleInput.ReadWasPerformedThisFrame())
+ {
+ if (m_Simulator.manipulatingLeftHand)
+ m_LeftHand.ToggleExpression(simulatedExpression, m_Simulator);
+
+ if (m_Simulator.manipulatingRightHand)
+ m_RightHand.ToggleExpression(simulatedExpression, m_Simulator);
+ }
+ }
+#endif
+ }
+
+ /// <summary>
+ /// See <see cref="MonoBehaviour"/>.
+ /// </summary>
+ protected void OnDestroy()
+ {
+ if (m_Simulator != null)
+ {
+ Unsubscribe(m_Simulator.manipulateLeftAction, OnManipulateLeftAction);
+ Unsubscribe(m_Simulator.manipulateRightAction, OnManipulateRightAction);
+ Unsubscribe(m_Simulator.toggleManipulateLeftAction, OnToggleManipulateLeftAction);
+ Unsubscribe(m_Simulator.toggleManipulateRightAction, OnToggleManipulateRightAction);
+ Unsubscribe(m_Simulator.toggleManipulateBodyAction, OnToggleManipulateBodyAction);
+ Unsubscribe(m_Simulator.manipulateHeadAction, OnManipulateHeadAction);
+ Unsubscribe(m_Simulator.handControllerModeAction, OnHandControllerModeAction);
+ Unsubscribe(m_Simulator.cycleDevicesAction, OnCycleDevicesAction);
+ Unsubscribe(m_Simulator.stopManipulationAction, OnStopManipulationAction);
+ Unsubscribe(m_Simulator.toggleMouseTransformationModeAction, OnToggleMouseTransformationModeAction);
+ Unsubscribe(m_Simulator.negateModeAction, OnNegateModeAction);
+ Unsubscribe(m_Simulator.toggleCursorLockAction, OnToggleCursorLockAction);
+ Unsubscribe(m_Simulator.keyboardXTranslateAction, OnKeyboardXTranslateAction);
+ Unsubscribe(m_Simulator.keyboardYTranslateAction, OnKeyboardYTranslateAction);
+ Unsubscribe(m_Simulator.keyboardZTranslateAction, OnKeyboardZTranslateAction);
+ Unsubscribe(m_Simulator.restingHandAxis2DAction, OnRestingHandAxis2DAction);
+ Unsubscribe(m_Simulator.gripAction, OnGripAction);
+ Unsubscribe(m_Simulator.triggerAction, OnTriggerAction);
+ Unsubscribe(m_Simulator.menuAction, OnMenuAction);
+ Unsubscribe(m_Simulator.primaryButtonAction, OnPrimaryButtonAction);
+ Unsubscribe(m_Simulator.secondaryButtonAction, OnSecondaryButtonAction);
+ }
+ }
+
+ void Initialize(XRDeviceSimulator simulator)
+ {
+ m_Simulator = simulator;
+
+ if (!m_Simulator.gameObject.TryGetComponent(out m_DeviceLifecycleManager))
+ {
+ Debug.LogError($"Could not find SimulatedDeviceLifecycleManager component on {m_Simulator.name}, disabling simulator UI.");
+ gameObject.SetActive(false);
+ return;
+ }
+
+ if (!m_Simulator.gameObject.TryGetComponent(out m_HandExpressionManager))
+ {
+ Debug.LogError($"Could not find SimulatedHandExpressionManager component on {m_Simulator.name}, disabling simulator UI.");
+ gameObject.SetActive(false);
+ return;
+ }
+
+ InitColorTheme();
+ Initialize();
+ // Start with the headset enabled
+ OnSetMouseMode();
+ OnActivateHeadsetDevice();
+ }
+
+ void InitColorTheme()
+ {
+#if UNITY_EDITOR
+ var isEditorPro = EditorGUIUtility.isProSkin;
+ m_EnabledColor = isEditorPro ? k_EnabledColorDark : k_EnabledColorLight;
+ m_DisabledColor = isEditorPro ? k_DisabledColorDark : k_DisabledColorLight;
+ m_ButtonColor = isEditorPro ? k_ButtonColorDark : k_ButtonColorLight;
+ m_DisabledButtonColor = isEditorPro ? k_DisabledButtonColorDark : k_DisabledButtonColorLight;
+ m_SelectedColor = isEditorPro ? k_SelectedColorDark : k_SelectedColorLight;
+ m_BackgroundColor = isEditorPro ? k_BackgroundColorDark : k_BackgroundColorLight;
+ m_DeviceColor = isEditorPro ? k_DeviceColorDark : k_DeviceColorLight;
+ m_DisabledDeviceColor = isEditorPro ? k_DisabledDeviceColorDark : k_DisabledDeviceColorLight;
+ m_HeadsetImage.sprite = isEditorPro ? m_HmdSpriteDark : m_HmdSpriteLight;
+ m_RMouseSprite = isEditorPro ? m_RMouseSpriteDark : m_RMouseSpriteLight;
+#endif
+ }
+
+ void Initialize()
+ {
+ var bckgrdAlpha = m_XRDeviceSimulatorMainPanel.GetComponent<Image>().color.a;
+
+ foreach (var image in GetComponentsInChildren<Image>(true))
+ image.color = image.sprite == null || image.sprite == m_RoundedRectangle ? buttonColor : enabledColor;
+
+
+ foreach (var text in GetComponentsInChildren<Text>(true))
+ text.color = enabledColor;
+
+ m_HeadsetImage.color = Color.white;
+
+ var bckgrdColor = backgroundColor;
+ bckgrdColor.a = bckgrdAlpha;
+ m_XRDeviceSimulatorMainPanel.GetComponent<Image>().color = bckgrdColor;
+ m_XRDeviceSimulatorCollapsedPanel.GetComponent<Image>().color = bckgrdColor;
+
+ m_CycleDevicesText.text = m_Simulator.cycleDevicesAction.action.controls[0].displayName;
+
+ // Headset
+ var toggleManipulateBodyActionControl = m_Simulator.toggleManipulateBodyAction.action.controls[0];
+ m_HeadsetSelectedValueText.text = $"{toggleManipulateBodyActionControl.displayName}";
+
+ var ctrlsBinding1 = m_Simulator.axis2DAction.action.controls;
+ var ctrlsBinding2 = m_Simulator.keyboardYTranslateAction.action.controls;
+ m_HeadsetMoveValueText.text = $"{ctrlsBinding1[0].displayName},{ctrlsBinding1[1].displayName},{ctrlsBinding1[2].displayName},{ctrlsBinding1[3].displayName} + " +
+ $"{ctrlsBinding2[0].displayName},{ctrlsBinding2[1].displayName}";
+
+ m_CursorLockValueText.text = m_Simulator.toggleCursorLockAction.action.controls[0].displayName;
+ m_CursorLockButton.color = Cursor.lockState == CursorLockMode.Locked ? selectedColor : buttonColor;
+
+ m_HeadsetLookButtonText.text = m_Simulator.mouseTransformationMode == XRDeviceSimulator.TransformationMode.Translate ? k_TranslateLookText : k_RotateLookText;
+ m_MouseModeValueText.text = m_Simulator.toggleMouseTransformationModeAction.action.controls[0].displayName;
+
+ var manipulateHeadActionControl = m_Simulator.manipulateHeadAction.action.controls[0];
+ m_HeadsetLookValueIcon.sprite = GetInputIcon(manipulateHeadActionControl);
+ if (manipulateHeadActionControl.name.Equals("leftButton") || manipulateHeadActionControl.name.Equals("rightButton"))
+ {
+ m_HeadsetLookValueIcon.color = Color.white;
+
+ // If the binding is using the left button, mirror the MouseR image
+ if (manipulateHeadActionControl.name.Equals("leftButton"))
+ m_HeadsetLookValueIcon.transform.localScale = new Vector3(-1f, 1f, 1f);
+ }
+ m_HeadsetLookValueText.text = manipulateHeadActionControl.device.name == k_MouseDeviceType ? k_MouseDeviceType : manipulateHeadActionControl.displayName;
+
+ m_LeftController.Initialize(m_Simulator);
+ m_RightController.Initialize(m_Simulator);
+ var toggleSlashHoldLeftText = $"{m_Simulator.toggleManipulateLeftAction.action.controls[0].displayName} / {m_Simulator.manipulateLeftAction.action.controls[0].displayName} [Hold]";
+ var toggleSlashHoldRightText = $"{m_Simulator.toggleManipulateRightAction.action.controls[0].displayName} / {m_Simulator.manipulateRightAction.action.controls[0].displayName} [Hold]";
+ m_LeftControllerButtonText.text = toggleSlashHoldLeftText;
+ m_RightControllerButtonText.text = toggleSlashHoldRightText;
+
+ m_LeftHand.Initialize(m_Simulator);
+ m_RightHand.Initialize(m_Simulator);
+ m_LeftHandButtonText.text = toggleSlashHoldLeftText;
+ m_RightHandButtonText.text = toggleSlashHoldRightText;
+
+ UpdateDeviceInputMethod();
+
+ HandsSetActive(false);
+
+#if XR_HANDS_1_1_OR_NEWER
+ m_HandsSelectedValueIcon.color = enabledColor;
+ m_HandsSelectedValueText.color = enabledColor;
+#else
+ m_HandsSelectedValueIcon.color = disabledColor;
+ m_HandsSelectedValueText.color = disabledColor;
+#endif
+
+ m_HeadsetMoveButtonIcon.color = enabledColor;
+
+ // Update OnDestroy with corresponding Unsubscribe call when adding here
+ Subscribe(m_Simulator.manipulateLeftAction, OnManipulateLeftAction);
+ Subscribe(m_Simulator.manipulateRightAction, OnManipulateRightAction);
+ Subscribe(m_Simulator.toggleManipulateLeftAction, OnToggleManipulateLeftAction);
+ Subscribe(m_Simulator.toggleManipulateRightAction, OnToggleManipulateRightAction);
+ Subscribe(m_Simulator.toggleManipulateBodyAction, OnToggleManipulateBodyAction);
+ Subscribe(m_Simulator.manipulateHeadAction, OnManipulateHeadAction);
+ Subscribe(m_Simulator.handControllerModeAction, OnHandControllerModeAction);
+ Subscribe(m_Simulator.cycleDevicesAction, OnCycleDevicesAction);
+ Subscribe(m_Simulator.stopManipulationAction, OnStopManipulationAction);
+ Subscribe(m_Simulator.toggleMouseTransformationModeAction, OnToggleMouseTransformationModeAction);
+ Subscribe(m_Simulator.negateModeAction, OnNegateModeAction);
+ Subscribe(m_Simulator.toggleCursorLockAction, OnToggleCursorLockAction);
+ Subscribe(m_Simulator.keyboardXTranslateAction, OnKeyboardXTranslateAction);
+ Subscribe(m_Simulator.keyboardYTranslateAction, OnKeyboardYTranslateAction);
+ Subscribe(m_Simulator.keyboardZTranslateAction, OnKeyboardZTranslateAction);
+ Subscribe(m_Simulator.restingHandAxis2DAction, OnRestingHandAxis2DAction);
+ Subscribe(m_Simulator.gripAction, OnGripAction);
+ Subscribe(m_Simulator.triggerAction, OnTriggerAction);
+ Subscribe(m_Simulator.menuAction, OnMenuAction);
+ Subscribe(m_Simulator.primaryButtonAction, OnPrimaryButtonAction);
+ Subscribe(m_Simulator.secondaryButtonAction, OnSecondaryButtonAction);
+
+ m_XRDeviceSimulatorMainPanel.SetActive(isMenuOpen);
+ m_XRDeviceSimulatorCollapsedPanel.SetActive(!isMenuOpen);
+ }
+
+ void UpdateDeviceInputMethod()
+ {
+ var toggleManipulateText = $"{m_Simulator.toggleManipulateLeftAction.action.controls[0].displayName}, {m_Simulator.toggleManipulateRightAction.action.controls[0].displayName} [Toggle]";
+#if XR_HANDS_1_1_OR_NEWER
+ var modeChangeText = m_Simulator.handControllerModeAction != null ? $"{m_Simulator.handControllerModeAction.action.controls[0].displayName}" : string.Empty;
+#else
+ var modeChangeText = string.Empty;
+#endif
+
+ m_ControllersSelectedValueText.text = m_DeviceLifecycleManager.deviceMode == SimulatedDeviceLifecycleManager.DeviceMode.Controller ? toggleManipulateText : modeChangeText;
+ m_HandsSelectedValueText.text = m_DeviceLifecycleManager.deviceMode == SimulatedDeviceLifecycleManager.DeviceMode.Hand ? toggleManipulateText : modeChangeText;
+
+ var modeColor = m_DeviceLifecycleManager.deviceMode == SimulatedDeviceLifecycleManager.DeviceMode.Controller ? enabledColor : disabledColor;
+ m_ControllerSelectedIcon.color = modeColor;
+ m_ControllerSelectedText.color = modeColor;
+
+ modeColor = m_DeviceLifecycleManager.deviceMode == SimulatedDeviceLifecycleManager.DeviceMode.Hand ? enabledColor : disabledColor;
+ m_HandsSelectedIcon.color = modeColor;
+ m_HandsSelectedText.color = modeColor;
+ }
+
+ internal Sprite GetInputIcon(InputControl control)
+ {
+ if (control == null)
+ return null;
+
+ var icon = keyboardSprite;
+ if (control.device.name == k_MouseDeviceType)
+ {
+ switch (control.name)
+ {
+ case "leftButton":
+ case "rightButton":
+ icon = rMouseSprite;
+ break;
+ default:
+ icon = mouseSprite;
+ break;
+ }
+ }
+
+ return icon;
+ }
+
+ /// <summary>
+ /// Hides the simulator UI panel when called while displaying the simulator button.
+ /// </summary>
+ public void OnClickCloseSimulatorUIPanel()
+ {
+ isMenuOpen = false;
+ m_XRDeviceSimulatorMainPanel.SetActive(false);
+ m_XRDeviceSimulatorCollapsedPanel.SetActive(true);
+ }
+
+ /// <summary>
+ /// Displays the simulator UI panel when called while hiding the simulator button.
+ /// </summary>
+ public void OnClickOpenSimulatorUIPanel()
+ {
+ isMenuOpen = true;
+ m_XRDeviceSimulatorMainPanel.SetActive(true);
+ m_XRDeviceSimulatorCollapsedPanel.SetActive(false);
+ }
+
+ void OnActivateLeftDevice()
+ {
+ if (m_DeviceLifecycleManager.deviceMode == SimulatedDeviceLifecycleManager.DeviceMode.Controller)
+ OnActivateLeftController();
+ else if (m_DeviceLifecycleManager.deviceMode == SimulatedDeviceLifecycleManager.DeviceMode.Hand)
+ OnActivateLeftHand();
+ }
+
+ void OnActivateRightDevice()
+ {
+ if (m_DeviceLifecycleManager.deviceMode == SimulatedDeviceLifecycleManager.DeviceMode.Controller)
+ OnActivateRightController();
+ else if (m_DeviceLifecycleManager.deviceMode == SimulatedDeviceLifecycleManager.DeviceMode.Hand)
+ OnActivateRightHand();
+ }
+
+ void OnActivateBothDevices()
+ {
+ if (m_DeviceLifecycleManager.deviceMode == SimulatedDeviceLifecycleManager.DeviceMode.Controller)
+ OnActivateBothControllers();
+ else if (m_DeviceLifecycleManager.deviceMode == SimulatedDeviceLifecycleManager.DeviceMode.Hand)
+ OnActivateBothHands();
+ }
+
+ /// <summary>
+ /// Sets the Left Controller device as active to receive input.
+ /// </summary>
+ void OnActivateLeftController()
+ {
+ m_CurrentSelectedDeviceText.text = "Left Controller";
+ OnActivateController(m_LeftController);
+ }
+
+ /// <summary>
+ /// Sets the Right Controller device as active to receive input.
+ /// </summary>
+ void OnActivateRightController()
+ {
+ m_CurrentSelectedDeviceText.text = "Right Controller";
+ OnActivateController(m_RightController);
+ }
+
+ void OnActivateController(XRDeviceSimulatorControllerUI controller)
+ {
+ ControllersSetActive(true);
+ PushCurrentButtonState(controller);
+ controller.SetAsActiveController(true, m_Simulator);
+ var other = controller == m_LeftController ? m_RightController : m_LeftController;
+ other.SetAsActiveController(false, m_Simulator, true);
+
+ HeadDeviceSetActive(false);
+ HandsSetActive(false);
+ }
+
+ /// <summary>
+ /// Sets both Left & Right Controller devices as active to receive input.
+ /// </summary>
+ void OnActivateBothControllers()
+ {
+ ControllersSetActive(true);
+ m_CurrentSelectedDeviceText.text = "Left & Right Controllers";
+ PushCurrentButtonState(m_LeftController);
+ PushCurrentButtonState(m_RightController);
+ m_LeftController.SetAsActiveController(true, m_Simulator);
+ m_RightController.SetAsActiveController(true, m_Simulator);
+
+ HeadDeviceSetActive(false);
+ HandsSetActive(false);
+ }
+
+ void PushCurrentButtonState(XRDeviceSimulatorControllerUI controller)
+ {
+ controller.OnGrip(m_Simulator.gripAction.action.inProgress);
+ controller.OnTrigger(m_Simulator.triggerAction.action.inProgress);
+ controller.OnMenu(m_Simulator.menuAction.action.inProgress);
+ controller.OnPrimaryButton(m_Simulator.primaryButtonAction.action.inProgress);
+ controller.OnSecondaryButton(m_Simulator.secondaryButtonAction.action.inProgress);
+ controller.OnXAxisTranslatePerformed(m_Simulator.keyboardXTranslateAction.action.inProgress);
+ controller.OnZAxisTranslatePerformed(m_Simulator.keyboardZTranslateAction.action.inProgress);
+ }
+
+ /// <summary>
+ /// Sets the Left Hand device as active to receive input.
+ /// </summary>
+ void OnActivateLeftHand()
+ {
+ m_CurrentSelectedDeviceText.text = "Left Hand";
+ OnActivateHand(m_LeftHand);
+ }
+
+ /// <summary>
+ /// Sets the Right Hand device as active to receive input.
+ /// </summary>
+ void OnActivateRightHand()
+ {
+ m_CurrentSelectedDeviceText.text = "Right Hand";
+ OnActivateHand(m_RightHand);
+ }
+
+ void OnActivateHand(XRDeviceSimulatorHandsUI hand)
+ {
+ HandsSetActive(true);
+ hand.SetActive(true, m_Simulator);
+ XRDeviceSimulatorHandsUI otherHand = hand == m_LeftHand ? m_RightHand : m_LeftHand;
+ otherHand.SetActive(false, m_Simulator);
+
+ HeadDeviceSetActive(false);
+ ControllersSetActive(false);
+ }
+
+ /// <summary>
+ /// Sets both Left & Right Hand devices as active to receive input.
+ /// </summary>
+ void OnActivateBothHands()
+ {
+ HandsSetActive(true);
+ m_CurrentSelectedDeviceText.text = "Left & Right Hands";
+ m_LeftHand.SetActive(true, m_Simulator);
+ m_RightHand.SetActive(true, m_Simulator);
+
+ HeadDeviceSetActive(false);
+ ControllersSetActive(false);
+ }
+
+ /// <summary>
+ /// Sets the headset device as active to receive input.
+ /// </summary>
+ void OnActivateHeadsetDevice(bool activated = true)
+ {
+ m_LeftController.SetAsActiveController(false, m_Simulator);
+ m_RightController.SetAsActiveController(false, m_Simulator);
+
+ m_LeftHand.SetActive(false, m_Simulator);
+ m_RightHand.SetActive(false, m_Simulator);
+
+ m_CurrentSelectedDeviceText.text = activated ? "Head Mounted Display (HMD)" : "None";
+ m_HeadsetImage.gameObject.SetActive(activated);
+
+ HeadDeviceSetActive(activated);
+
+ if (m_Simulator.manipulatingFPS)
+ {
+ ControllersSetActive(false, m_DeviceLifecycleManager.deviceMode == SimulatedDeviceLifecycleManager.DeviceMode.Controller);
+ HandsSetActive(false, m_DeviceLifecycleManager.deviceMode == SimulatedDeviceLifecycleManager.DeviceMode.Hand);
+ }
+ else
+ {
+ HandsSetActive(false, Mathf.Approximately(m_HandsCanvasGroup.alpha, 1f));
+ ControllersSetActive(false, Mathf.Approximately(m_ControllersCanvasGroup.alpha, 1f));
+ }
+ }
+
+ /// <summary>
+ /// Updates all the UI associated the the Headset.
+ /// </summary>
+ /// <param name="active">Whether the headset is the active device or not.</param>
+ void HeadDeviceSetActive(bool active)
+ {
+ m_HeadsetImage.gameObject.SetActive(active);
+ m_HeadsetSelectedButton.color = active ? selectedColor : buttonColor;
+
+ var currentColor = active ? enabledColor : disabledColor;
+ m_HeadsetMoveButtonIcon.color = currentColor;
+ m_HeadsetMoveButtonText.color = currentColor;
+ m_HeadsetMoveValueIcon.color = currentColor;
+ m_HeadsetMoveValueText.color = currentColor;
+
+ m_HeadsetMoveButton.color = active ? buttonColor : disabledButtonColor;
+ }
+
+ void HandsSetActive(bool isActive, bool showCanvasGroup = false)
+ {
+ m_HandsCanvasGroup.alpha = isActive || showCanvasGroup ? 1f : 0f;
+
+#if XR_HANDS_1_1_OR_NEWER
+ m_HandsSelectedButton.color = isActive ? selectedColor : buttonColor;
+#else
+ m_HandsSelectedButton.color = disabledButtonColor;
+#endif
+ }
+
+ void ControllersSetActive(bool isActive, bool showCanvasGroup = false)
+ {
+ m_ControllersCanvasGroup.alpha = isActive || showCanvasGroup ? 1f : 0f;
+ m_ControllerSelectedButton.color = isActive ? selectedColor : buttonColor;
+ }
+
+ static void Subscribe(InputActionReference reference, Action<InputAction.CallbackContext> performedOrCanceled)
+ {
+ var action = reference != null ? reference.action : null;
+ if (action != null && performedOrCanceled != null)
+ {
+ action.performed += performedOrCanceled;
+ action.canceled += performedOrCanceled;
+ }
+ }
+
+ static void Unsubscribe(InputActionReference reference, Action<InputAction.CallbackContext> performedOrCanceled)
+ {
+ var action = reference != null ? reference.action : null;
+ if (action != null && performedOrCanceled != null)
+ {
+ action.performed -= performedOrCanceled;
+ action.canceled -= performedOrCanceled;
+ }
+ }
+
+ void OnManipulateLeftAction(InputAction.CallbackContext context)
+ {
+ if (context.phase.IsInProgress())
+ {
+ if (m_Simulator.manipulatingLeftDevice && m_Simulator.manipulatingRightDevice)
+ OnActivateBothDevices();
+ else if (m_Simulator.manipulatingLeftDevice)
+ OnActivateLeftDevice();
+ }
+ else
+ {
+ if (m_Simulator.manipulatingRightDevice)
+ OnActivateRightDevice();
+ else
+ OnActivateHeadsetDevice(m_Simulator.manipulatingFPS);
+ }
+ }
+
+ void OnManipulateRightAction(InputAction.CallbackContext context)
+ {
+ if (context.phase.IsInProgress())
+ {
+ if (m_Simulator.manipulatingLeftDevice && m_Simulator.manipulatingRightDevice)
+ OnActivateBothDevices();
+ else if (m_Simulator.manipulatingRightDevice)
+ OnActivateRightDevice();
+ }
+ else
+ {
+ if (m_Simulator.manipulatingLeftDevice)
+ OnActivateLeftDevice();
+ else
+ OnActivateHeadsetDevice(m_Simulator.manipulatingFPS);
+ }
+ }
+
+ void OnToggleManipulateLeftAction(InputAction.CallbackContext context)
+ {
+ if (context.phase.IsInProgress())
+ {
+ if (m_Simulator.manipulatingLeftDevice)
+ OnActivateLeftDevice();
+ else
+ OnActivateHeadsetDevice();
+ }
+ }
+
+ void OnToggleManipulateRightAction(InputAction.CallbackContext context)
+ {
+ if (context.phase.IsInProgress())
+ {
+ if (m_Simulator.manipulatingRightDevice)
+ OnActivateRightDevice();
+ else
+ OnActivateHeadsetDevice();
+ }
+ }
+
+ void OnToggleManipulateBodyAction(InputAction.CallbackContext context)
+ {
+ if (context.phase.IsInProgress())
+ {
+ OnActivateHeadsetDevice();
+ }
+ }
+
+ void OnManipulateHeadAction(InputAction.CallbackContext context)
+ {
+ var isInProgress = context.phase.IsInProgress();
+ var noDevices = !m_Simulator.manipulatingLeftDevice && !m_Simulator.manipulatingRightDevice;
+ if (isInProgress)
+ {
+ if (m_Simulator.manipulatingFPS || noDevices)
+ OnActivateHeadsetDevice();
+ }
+ else if (noDevices)
+ {
+ OnActivateHeadsetDevice(m_Simulator.manipulatingFPS);
+ }
+
+ m_HeadsetLookButton.color = isInProgress ? selectedColor : buttonColor;
+ }
+
+ void OnHandControllerModeAction(InputAction.CallbackContext context)
+ {
+#if XR_HANDS_1_1_OR_NEWER
+ if (context.phase.IsInProgress())
+ {
+ if (m_Simulator.manipulatingLeftDevice && m_Simulator.manipulatingRightDevice)
+ OnActivateBothDevices();
+ else if (m_Simulator.manipulatingLeftDevice)
+ OnActivateLeftDevice();
+ else if (m_Simulator.manipulatingRightDevice)
+ OnActivateRightDevice();
+ else if (m_Simulator.manipulatingFPS)
+ OnActivateHeadsetDevice();
+ else
+ {
+ ControllersSetActive(false, m_DeviceLifecycleManager.deviceMode == SimulatedDeviceLifecycleManager.DeviceMode.Controller);
+ HandsSetActive(false, m_DeviceLifecycleManager.deviceMode == SimulatedDeviceLifecycleManager.DeviceMode.Hand);
+ }
+ }
+
+ UpdateDeviceInputMethod();
+#endif
+ }
+
+ void OnCycleDevicesAction(InputAction.CallbackContext context)
+ {
+ if (context.phase.IsInProgress())
+ {
+ if (m_Simulator.manipulatingFPS)
+ OnActivateHeadsetDevice();
+
+ if (m_Simulator.manipulatingLeftDevice)
+ OnActivateLeftDevice();
+
+ if (m_Simulator.manipulatingRightDevice)
+ OnActivateRightDevice();
+ }
+ }
+
+ void OnStopManipulationAction(InputAction.CallbackContext context)
+ {
+ if (context.phase.IsInProgress())
+ OnActivateHeadsetDevice(m_Simulator.manipulatingFPS);
+ }
+
+ void OnToggleMouseTransformationModeAction(InputAction.CallbackContext context)
+ {
+ if (context.phase.IsInProgress())
+ OnSetMouseMode();
+ }
+
+ void OnNegateModeAction(InputAction.CallbackContext context)
+ {
+ OnSetMouseMode();
+ }
+
+ void OnToggleCursorLockAction(InputAction.CallbackContext context)
+ {
+ if (context.phase.IsInProgress())
+ OnCursorLockChanged();
+ }
+
+ void OnKeyboardXTranslateAction(InputAction.CallbackContext context)
+ {
+ OnXAxisTranslatePerformed(context.phase.IsInProgress(), false);
+ }
+
+ void OnKeyboardYTranslateAction(InputAction.CallbackContext context)
+ {
+ OnYAxisTranslatePerformed(context.phase.IsInProgress());
+ }
+
+ void OnKeyboardZTranslateAction(InputAction.CallbackContext context)
+ {
+ OnZAxisTranslatePerformed(context.phase.IsInProgress(), false);
+ }
+
+ void OnRestingHandAxis2DAction(InputAction.CallbackContext context)
+ {
+ var restingHandAxis2DInput = Vector2.ClampMagnitude(context.ReadValue<Vector2>(), 1f);
+ if (context.phase.IsInProgress())
+ {
+ if (restingHandAxis2DInput.x != 0f)
+ OnXAxisTranslatePerformed(true, true);
+ if (restingHandAxis2DInput.y != 0f)
+ OnZAxisTranslatePerformed(true, true);
+ }
+ else
+ {
+ if (restingHandAxis2DInput.x == 0f)
+ OnXAxisTranslatePerformed(false, true);
+ if (restingHandAxis2DInput.y == 0f)
+ OnZAxisTranslatePerformed(false, true);
+ }
+ }
+
+ void OnGripAction(InputAction.CallbackContext context)
+ {
+ OnGripPerformed(context.phase.IsInProgress());
+ }
+
+ void OnTriggerAction(InputAction.CallbackContext context)
+ {
+ OnTriggerPerformed(context.phase.IsInProgress());
+ }
+
+ void OnMenuAction(InputAction.CallbackContext context)
+ {
+ OnMenuPerformed(context.phase.IsInProgress());
+ }
+
+ void OnPrimaryButtonAction(InputAction.CallbackContext context)
+ {
+ OnPrimaryButtonPerformed(context.phase.IsInProgress());
+ }
+
+ void OnSecondaryButtonAction(InputAction.CallbackContext context)
+ {
+ OnSecondaryButtonPerformed(context.phase.IsInProgress());
+ }
+
+ void OnSetMouseMode()
+ {
+ // Translate/Rotate
+ m_MouseModeButtonText.text = m_Simulator.negateMode
+ ? XRDeviceSimulator.Negate(m_Simulator.mouseTransformationMode).ToString()
+ : m_Simulator.mouseTransformationMode.ToString();
+ // Move/Look
+ m_HeadsetLookButtonText.text =
+ m_Simulator.mouseTransformationMode == XRDeviceSimulator.TransformationMode.Translate
+ ? k_TranslateLookText
+ : k_RotateLookText;
+ }
+
+ void OnCursorLockChanged()
+ {
+ m_CursorLockButton.color = Cursor.lockState == CursorLockMode.Locked ? selectedColor : buttonColor;
+ }
+
+ // x-axis [A-D]
+ void OnXAxisTranslatePerformed(bool activated, bool restingHand)
+ {
+ var active = activated;
+ if (!restingHand)
+ {
+ m_XAxisActivated = activated;
+ active |= m_ZAxisActivated;
+ }
+
+ if (m_Simulator.manipulatingLeftController)
+ {
+ var lController = restingHand ? m_RightController : m_LeftController;
+ lController.OnXAxisTranslatePerformed(active);
+ }
+
+ if (m_Simulator.manipulatingRightController)
+ {
+ var rController = restingHand ? m_LeftController : m_RightController;
+ rController.OnXAxisTranslatePerformed(active);
+ }
+
+ if (m_Simulator.manipulatingFPS)
+ m_HeadsetMoveButton.color = active ? selectedColor : buttonColor;
+ }
+
+ // y-axis [Q-E]
+ void OnYAxisTranslatePerformed(bool activated)
+ {
+ if (m_Simulator.manipulatingFPS)
+ m_HeadsetMoveButton.color = activated ? selectedColor : buttonColor;
+ }
+
+ // z-axis [W-S]
+ void OnZAxisTranslatePerformed(bool activated, bool restingHand)
+ {
+ var active = activated;
+ if (!restingHand)
+ {
+ m_ZAxisActivated = activated;
+ active |= m_XAxisActivated;
+ }
+
+ if (m_Simulator.manipulatingLeftController)
+ {
+ var lController = restingHand ? m_RightController : m_LeftController;
+ lController.OnZAxisTranslatePerformed(active);
+ }
+
+ if (m_Simulator.manipulatingRightController)
+ {
+ var rController = restingHand ? m_LeftController : m_RightController;
+ rController.OnZAxisTranslatePerformed(active);
+ }
+
+ if (m_Simulator.manipulatingFPS)
+ m_HeadsetMoveButton.color = active ? selectedColor : buttonColor;
+ }
+
+ void OnMenuPerformed(bool activated)
+ {
+ if (m_Simulator.manipulatingLeftController)
+ m_LeftController.OnMenu(activated);
+
+ if (m_Simulator.manipulatingRightController)
+ m_RightController.OnMenu(activated);
+ }
+
+ void OnGripPerformed(bool activated)
+ {
+ if (m_Simulator.manipulatingLeftController)
+ m_LeftController.OnGrip(activated);
+
+ if (m_Simulator.manipulatingRightController)
+ m_RightController.OnGrip(activated);
+ }
+
+ void OnTriggerPerformed(bool activated)
+ {
+ if (m_Simulator.manipulatingLeftController)
+ m_LeftController.OnTrigger(activated);
+
+ if (m_Simulator.manipulatingRightController)
+ m_RightController.OnTrigger(activated);
+ }
+
+ void OnPrimaryButtonPerformed(bool activated)
+ {
+ if (m_Simulator.manipulatingLeftController)
+ m_LeftController.OnPrimaryButton(activated);
+
+ if (m_Simulator.manipulatingRightController)
+ m_RightController.OnPrimaryButton(activated);
+ }
+
+ void OnSecondaryButtonPerformed(bool activated)
+ {
+ if (m_Simulator.manipulatingLeftController)
+ m_LeftController.OnSecondaryButton(activated);
+
+ if (m_Simulator.manipulatingRightController)
+ m_RightController.OnSecondaryButton(activated);
+ }
+ }
+}
diff --git a/Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorUI.cs.meta b/Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorUI.cs.meta
new file mode 100644
index 0000000..5306c71
--- /dev/null
+++ b/Assets/Samples/XR Interaction Toolkit/3.1.2/XR Device Simulator/XRDeviceSimulator/Scripts/XRDeviceSimulatorUI.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e8b922481d9264546b97958b2c7cf0a0
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: