Files
Kizza00232Jera 17532b524f [unity] avatars
2025-06-11 14:45:45 +02:00

581 lines
18 KiB
C#

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#nullable enable
#if USING_XR_MANAGEMENT && (USING_XR_SDK_OCULUS || USING_XR_SDK_OPENXR) && !OVRPLUGIN_UNSUPPORTED_PLATFORM
#define USING_XR_SDK
#endif
using System.Collections;
using System.Collections.Generic;
using Oculus.Avatar2;
using UnityEngine;
public class UIInputController : MonoBehaviour, IUIControllerInterface
{
private const string logScope = "UIInputController";
#if USING_XR_SDK
private readonly UIInputControllerButton _navigateMenuInput = new()
{
axis2d = OVRInput.Axis2D.PrimaryThumbstick,
controller = OVRInput.Controller.LTouch,
description = "Move Left-thumbstick left and right to navigate UI tabs",
scope = logScope
};
private readonly UIInputControllerButton _navigateSubMenuInput = new()
{
axis2d = OVRInput.Axis2D.PrimaryThumbstick,
controller = OVRInput.Controller.RTouch,
description = "Move Right-thumbstick left and right to navigate sub menu items",
scope = logScope
};
private readonly UIInputControllerButton _selectButton = new()
{
button = OVRInput.Button.One,
controller = OVRInput.Controller.RTouch,
description = "Select the current sub menu item",
scope = logScope
};
private readonly UIInputControllerButton _menuButton = new()
{
button = OVRInput.Button.Start,
controller = OVRInput.Controller.LTouch,
description = "Toggle Meta Avatars SDK UI",
scope = logScope
};
private readonly UIInputControllerButton _scrollButton = new UIInputControllerButton
{
axis2d = OVRInput.Axis2D.PrimaryThumbstick,
controller = OVRInput.Controller.RTouch,
description = "Scroll up and down",
scope = logScope
};
private readonly UIInputControllerButton _returnButton = new UIInputControllerButton
{
button = OVRInput.Button.Two,
controller = OVRInput.Controller.RTouch,
description = "Return to upper settings menu",
scope = logScope
};
#endif
#if UNITY_EDITOR
private readonly KeyCode _editorMenuButton = KeyCode.Escape;
#endif
private UIWindowController? _uiWindowController;
private const float MENU_AXIS_INPUT_INTERVAL = 0.5f;
private const float SCENE_AXIS_INPUT_INTERVAL = 0.5f;
private const float AXIS_DEADZONE = 0.2f;
private const float CONTROLLER_SCROLL_MULTIPLIER = 0.005f;
private const float CONTROLLER_SCROLL_DEADZONE = 0.25f;
private bool _navigateMenuAxisInputEnabled = true;
private bool _navigateSubMenuAxisInputEnabled = false;
private bool _menuNavigationEnabled = true;
private void Start()
{
if (UIManager.Instance != null && UIManager.Instance.Initialized)
{
_uiWindowController = UIManager.Instance.GetUIWindowController();
}
}
private void NavigateMenu(Vector2 axisValue)
{
_navigateSubMenuAxisInputEnabled = false;
switch (axisValue.x)
{
case < -AXIS_DEADZONE when _uiWindowController != null:
_uiWindowController.MoveSectionIndex(-1);
break;
case > AXIS_DEADZONE when _uiWindowController != null:
_uiWindowController.MoveSectionIndex(1);
break;
}
StartCoroutine(AddIntervalDelayToMenuAxisInput());
}
private void NavigateSubMenu(Vector2 axisValue)
{
if (UIManager.Instance == null || !UIManager.Instance.Initialized)
{
OvrAvatarLog.LogError("UIInputController::NavigateSubMenu : UIManager instance not found.", logScope);
return;
}
var sectionType = UIManager.Instance.GetActiveSectionType();
switch (axisValue.x)
{
case < -AXIS_DEADZONE:
switch (sectionType)
{
case UIWindowController.UISectionType.Scenes:
SelectPreviousScene();
break;
case UIWindowController.UISectionType.Settings:
SelectPreviousAvatarSetting();
break;
case UIWindowController.UISectionType.Logs:
HandleUILoggerSelection();
break;
}
break;
case > AXIS_DEADZONE:
switch (sectionType)
{
case UIWindowController.UISectionType.Scenes:
SelectNextScene();
break;
case UIWindowController.UISectionType.Settings:
SelectNextAvatarSetting();
break;
case UIWindowController.UISectionType.Logs:
HandleUILoggerSelection();
break;
}
break;
}
StartCoroutine(AddIntervalDelayToSubMenuAxisInput());
}
public bool IsMenuNavigationEnabled()
{
return _menuNavigationEnabled;
}
private IEnumerator AddIntervalDelayToMenuAxisInput()
{
if (_navigateMenuAxisInputEnabled)
{
_navigateMenuAxisInputEnabled = false;
yield return new WaitForSecondsRealtime(MENU_AXIS_INPUT_INTERVAL);
_navigateMenuAxisInputEnabled = true;
}
}
private IEnumerator AddIntervalDelayToSubMenuAxisInput()
{
if (!_navigateSubMenuAxisInputEnabled)
{
yield break;
}
_navigateSubMenuAxisInputEnabled = false;
yield return new WaitForSecondsRealtime(SCENE_AXIS_INPUT_INTERVAL);
_navigateSubMenuAxisInputEnabled = true;
}
public void SetMenuNavigationEnabled(bool isEnabled)
{
_navigateMenuAxisInputEnabled = isEnabled;
_menuNavigationEnabled = _navigateMenuAxisInputEnabled || _navigateSubMenuAxisInputEnabled;
}
public void SetSubMenuNavigationEnabled(bool isEnabled)
{
_navigateSubMenuAxisInputEnabled = isEnabled;
_menuNavigationEnabled = _navigateMenuAxisInputEnabled || _navigateSubMenuAxisInputEnabled;
}
private void CheckInput()
{
if (UIManager.Instance != null && UIManager.Instance.IsLoadingScene())
{
return;
}
#if UNITY_EDITOR
// Menu button
if (!OvrAvatarUtility.IsHeadsetActive() && Input.GetKeyUp(_editorMenuButton))
{
MenuButtonPressed();
}
#endif
#if USING_XR_SDK
// Menu button
if (OVRInput.GetUp(_menuButton.button))
{
MenuButtonPressed();
}
// Don't check for input if UI is not enabled
if (!UIManager.IsPaused)
{
return;
}
if (_menuNavigationEnabled && _navigateMenuAxisInputEnabled)
{
var controllerInput = OVRInput.Get(_navigateMenuInput.axis2d);
if (Mathf.Abs(controllerInput.x) >= AXIS_DEADZONE)
{
NavigateMenu(controllerInput);
}
}
if (_menuNavigationEnabled && _navigateSubMenuAxisInputEnabled)
{
var controllerInput = OVRInput.Get(_navigateSubMenuInput.axis2d, _navigateSubMenuInput.controller);
if (Mathf.Abs(controllerInput.x) >= AXIS_DEADZONE)
{
NavigateSubMenu(controllerInput);
}
}
// Load currently selected Scene OR open currently selected Avatar's settings
if (_menuNavigationEnabled && OVRInput.GetUp(_selectButton.button, _selectButton.controller))
{
SelectCurrentSubMenuItem();
}
// return
if (_menuNavigationEnabled && OVRInput.GetUp(_returnButton.button, _returnButton.controller))
{
ReturnFromSubMenuItem();
}
#endif
}
private void MenuButtonPressed()
{
if (UIManager.Instance == null || !UIManager.Instance.Initialized)
{
OvrAvatarLog.LogError("UIInputController::MenuButtonPressed : UIManager instance not found.", logScope);
return;
}
if (UIManager.IsPaused)
{
ResumeScene();
}
else
{
PauseScene();
}
}
private void PauseScene()
{
if (UIManager.Instance == null || !UIManager.Instance.Initialized)
{
OvrAvatarLog.LogError("UIInputController::PauseScene : UIManager instance not found.", logScope);
return;
}
UIManager.Instance.Pause();
}
private void ResumeScene()
{
if (UIManager.Instance == null || !UIManager.Instance.Initialized)
{
OvrAvatarLog.LogError("UIInputController::ResumeScene : UIManager instance not found.", logScope);
return;
}
UIManager.Instance.Resume();
}
private void SelectNextScene()
{
if (UIManager.Instance == null || !UIManager.Instance.Initialized)
{
OvrAvatarLog.LogError("UIInputController::SelectNextScene : UIManager instance not found.", logScope);
return;
}
var sectionType = UIManager.Instance.GetActiveSectionType();
if (sectionType != UIWindowController.UISectionType.Scenes)
{
return;
}
UISceneSwitcher? sceneSwitcher = UIManager.Instance.GetUISceneSwitcher();
if (sceneSwitcher == null)
{
OvrAvatarLog.LogError("UIInputController::SelectNextScene : Failed to get UISceneSwitcher from UIManager.", logScope);
return;
}
sceneSwitcher.SelectNextSceneButton();
}
private void SelectPreviousScene()
{
if (UIManager.Instance == null || !UIManager.Instance.Initialized)
{
OvrAvatarLog.LogError("UIInputController::SelectPreviousScene : UIManager instance not found.", logScope);
return;
}
var sectionType = UIManager.Instance.GetActiveSectionType();
if (sectionType != UIWindowController.UISectionType.Scenes)
{
return;
}
UISceneSwitcher? sceneSwitcher = UIManager.Instance.GetUISceneSwitcher();
if (sceneSwitcher == null)
{
OvrAvatarLog.LogError("UIInputController::SelectPreviousScene : Failed to get UISceneSwitcher from UIManager.", logScope);
return;
}
sceneSwitcher.SelectPreviousSceneButton();
}
private void SelectCurrentSubMenuItem()
{
if (UIManager.Instance == null || !UIManager.Instance.Initialized)
{
OvrAvatarLog.LogError("UIInputController::SelectCurrentSubMenuItem : UIManager instance not found.", logScope);
return;
}
var sectionType = UIManager.Instance.GetActiveSectionType();
if (sectionType == UIWindowController.UISectionType.Invalid)
{
return;
}
switch (sectionType)
{
case UIWindowController.UISectionType.Scenes:
UISceneSwitcher? sceneSwitcher = UIManager.Instance.GetUISceneSwitcher();
if (sceneSwitcher == null)
{
OvrAvatarLog.LogError("UIInputController::SelectCurrentSubMenuItem : Failed to get UISceneSwitcher from UIManager.", logScope);
return;
}
sceneSwitcher.LoadSelectedScene();
break;
case UIWindowController.UISectionType.Settings:
UISettingsManager? settingsManager = UIManager.Instance.GetUISettingsManager();
if (settingsManager == null)
{
OvrAvatarLog.LogError("UIInputController::SelectCurrentSubMenuItem : Failed to get UISettingsManager from UIManager.", logScope);
return;
}
settingsManager.SelectSettingsItem();
break;
case UIWindowController.UISectionType.Logs:
UILogger? uiLogger = UIManager.Instance.GetUILogger();
if (uiLogger == null)
{
OvrAvatarLog.LogError("UIInputController::SelectCurrentSubMenuItem : Failed to get UILogger from UIManager.", logScope);
return;
}
uiLogger.ApplyCurrentButton();
break;
}
}
private void SelectNextAvatarSetting()
{
if (UIManager.Instance == null || !UIManager.Instance.Initialized)
{
OvrAvatarLog.LogError("UIInputController::SelectNextAvatarSetting : UIManager instance not found.", logScope);
return;
}
var sectionType = UIManager.Instance.GetActiveSectionType();
if (sectionType != UIWindowController.UISectionType.Settings)
{
return;
}
UISettingsManager? settingsManager = UIManager.Instance.GetUISettingsManager();
if (settingsManager == null)
{
OvrAvatarLog.LogError("UIInputController::SelectNextAvatarSetting : Failed to get settingsManager from UIManager.", logScope);
return;
}
settingsManager.SelectNextSettingsSection();
}
private void SelectPreviousAvatarSetting()
{
if (UIManager.Instance == null || !UIManager.Instance.Initialized)
{
OvrAvatarLog.LogError("UIInputController::SelectPreviousAvatarSetting : UIManager instance not found.", logScope);
return;
}
var sectionType = UIManager.Instance.GetActiveSectionType();
if (sectionType != UIWindowController.UISectionType.Settings)
{
return;
}
UISettingsManager? settingsManager = UIManager.Instance.GetUISettingsManager();
if (settingsManager == null)
{
OvrAvatarLog.LogError("UIInputController::SelectPreviousAvatarSetting : Failed to get settingsManager from UIManager.", logScope);
return;
}
settingsManager.SelectPreviousSettingsSection();
}
private void HandleUILoggerSelection()
{
if (UIManager.Instance == null || !UIManager.Instance.Initialized)
{
OvrAvatarLog.LogError("UIInputController::SelectPreviousAvatarSetting : UIManager instance not found.", logScope);
return;
}
var sectionType = UIManager.Instance.GetActiveSectionType();
if (sectionType != UIWindowController.UISectionType.Logs)
{
return;
}
UILogger? uiLogger = UIManager.Instance.GetUILogger();
if (uiLogger == null)
{
OvrAvatarLog.LogError("UIInputController::ToggleUILoggerSelection : Failed to get UILogger from UIManager.", logScope);
return;
}
uiLogger.SelectNextLogExportOption();
}
private void ReturnFromSubMenuItem()
{
if (UIManager.Instance == null || !UIManager.Instance.Initialized)
{
OvrAvatarLog.LogError("UIInputController::SelectCurrentSubMenuItem : UIManager instance not found.", logScope);
return;
}
var sectionType = UIManager.Instance.GetActiveSectionType();
if (sectionType != UIWindowController.UISectionType.Settings)
{
return;
}
UISettingsManager? settingsManager = UIManager.Instance.GetUISettingsManager();
if (settingsManager == null)
{
OvrAvatarLog.LogError("UIInputController::SelectCurrentSubMenuItem : Failed to get UISettingsManager from UIManager.", logScope);
return;
}
settingsManager.ReturnFromSubMenu();
}
private void CheckScrollInput()
{
if (!UIManager.IsPaused)
{
return;
}
#if USING_XR_SDK
if (_uiWindowController == null)
{
return;
}
var scrollRect = _uiWindowController.GetActiveScrollArea();
if (scrollRect == null)
{
return;
}
Vector2 thumbstickMovement = OVRInput.Get(_scrollButton.axis2d, _scrollButton.controller);
if (Mathf.Abs(thumbstickMovement.y) < CONTROLLER_SCROLL_DEADZONE)
{
return;
}
var newPos = Mathf.Clamp(scrollRect.normalizedPosition.y + thumbstickMovement.y * scrollRect.scrollSensitivity * CONTROLLER_SCROLL_MULTIPLIER, 0.0f, 1.0f);
scrollRect.verticalNormalizedPosition = newPos;
#endif
}
public static void SetUINavigationEnabled(bool isEnabled)
{
if (UIManager.Instance != null)
{
var inputController = UIManager.Instance.GetUIInputController();
if (inputController != null)
{
inputController.SetMenuNavigationEnabled(isEnabled);
}
}
}
public static void SetUISubMenuNavigationEnabled(bool isEnabled)
{
if (UIManager.Instance != null)
{
var inputController = UIManager.Instance.GetUIInputController();
if (inputController != null)
{
inputController.SetSubMenuNavigationEnabled(isEnabled);
}
}
}
private void Update()
{
CheckInput();
CheckScrollInput();
}
#if USING_XR_SDK
public List<UIInputControllerButton> GetControlSchema()
{
var buttons = new List<UIInputControllerButton>
{
_navigateMenuInput,
_navigateSubMenuInput,
_selectButton,
_menuButton,
_scrollButton,
_returnButton,
};
return buttons;
}
#endif
}