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

348 lines
11 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;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using Oculus.Avatar2;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class UISceneSwitcher : MonoBehaviour
{
private const string logScope = "UISceneSwitcher";
private List<string>? _sceneNames;
private List<Button>? _sceneButtons;
private int _currentButtonIndex = 0;
[SerializeField] private UISampleSceneInfo[]? sceneInfos;
private UISampleSceneInfo? _currentSceneInfo;
private string? _currentSceneName;
private void Awake()
{
if (sceneInfos == null || sceneInfos.Length < 1)
{
OvrAvatarLog.LogError("UISceneSwitcher::Awake : Empty 'Scene Infos'. This could be due to an empty field from the inspector.", logScope);
return;
}
_sceneNames = new List<string>();
_sceneButtons = new List<Button>();
_currentSceneName = SceneManager.GetActiveScene().name;
}
private void SetActiveScene(Scene scene, LoadSceneMode loadSceneMode)
{
SceneManager.SetActiveScene(scene);
_currentSceneName = scene.name;
if (UIManager.Instance == null)
{
OvrAvatarLog.LogError("UISceneSwitcher::SetActiveScene Could not retrieve UIManager instance.", logScope);
return;
}
UIManager.Instance.RemoveOnSceneLoadedEvent(SetActiveScene);
}
public List<string>? GetScenes()
{
if (_sceneNames != null)
{
return _sceneNames;
}
OvrAvatarLog.LogError("UISceneSwitcher::GetScenes Could not retrieve scenes list from UISceneSwitcher.", logScope);
return null;
}
public string GetCurrentSceneName()
{
if (_currentSceneName == null)
{
return "INVALID_SCENE";
}
return _currentSceneName;
}
public string GetCurrentSceneDescription()
{
if (sceneInfos == null || sceneInfos.Length < 1)
{
OvrAvatarLog.LogError("UISceneSwitcher::GetCurrentSceneDescription : Empty 'Scene Infos'. This could be due to an empty field from the inspector.", logScope);
return "Could not retrieve current scene's description.";
}
foreach (var sceneInfo in sceneInfos)
{
if (sceneInfo.sceneName == _currentSceneName)
{
if (sceneInfo.sceneDescription == null)
{
OvrAvatarLog.LogError($"UISceneSwitcher::GetCurrentSceneDescription : Null exception in retrieving scene description for {sceneInfo.sceneName}.", logScope);
return "Could not retrieve current scene's description.";
}
return sceneInfo.sceneDescription;
}
}
return "Could not retrieve current scene's description.";
}
private void ResetButtonIndex()
{
_currentButtonIndex = 0;
SelectButtonFromIndex(_currentButtonIndex);
}
public void OnSectionEnable()
{
UIInputController.SetUISubMenuNavigationEnabled(true);
ResetButtonIndex();
}
public void OnSectionDisable()
{
ResetButtonIndex();
}
public void Initialize()
{
PopulateScenes();
if (UIManager.Instance == null)
{
OvrAvatarLog.LogError("UISceneSwitcher::Initialize : No UIManager instance found.", logScope);
return;
}
if (!UIManager.Instance.Initialized)
{
OvrAvatarLog.LogError("UISceneSwitcher::Initialize : No UIManager not initialized.", logScope);
return;
}
UIManager.Instance.AddOnResumeEvent(ResetButtonIndex);
}
private void PopulateScenes()
{
var sceneCount = SceneManager.sceneCountInBuildSettings;
if (sceneCount < 1)
{
OvrAvatarLog.LogWarning("UISceneSwitcher::PopulateScenes : no scenes found in the build.", logScope);
return;
}
if (_sceneNames == null)
{
OvrAvatarLog.LogError("UISceneSwitcher::PopulateScenes : empty scene names.", logScope);
return;
}
for (var i = 0; i < sceneCount; i++)
{
var scenePath = SceneUtility.GetScenePathByBuildIndex(i);
// skip environment scenes
if (OvrAvatarUtility.IsScenePathAnEnvironment(scenePath))
{
continue;
}
var sceneName = System.IO.Path.GetFileNameWithoutExtension(scenePath);
_sceneNames.Add(sceneName);
}
CreateButtons();
ResetButtonIndex();
}
private void CreateButtons()
{
if (_sceneNames == null)
{
OvrAvatarLog.LogError("UISceneSwitcher::CreateButtons : No scenes found.", logScope);
return;
}
if (UIManager.Instance == null || !UIManager.Instance.Initialized)
{
OvrAvatarLog.LogError("UISceneSwitcher::CreateButtons : UIManager instance not found.", logScope);
return;
}
var layoutGroup = UIManager.Instance.GetScenesPanel()?.GetComponentInChildren<GridLayoutGroup>();
var parent = layoutGroup != null ? layoutGroup.gameObject : null;
if (parent != null)
{
foreach (var sceneName in _sceneNames)
{
CreateButtonForScene(sceneName, parent);
}
}
}
private void SelectButtonFromIndex(int index)
{
#if UNITY_EDITOR
if (!OvrAvatarUtility.IsHeadsetActive())
{
// In this situation, we're using a mouse and don't need to "Select" a button.
// This prevents weird behavior when OnPause/OnResume is invoked from UIManager
return;
}
#endif
if (_sceneButtons == null || _sceneButtons.Count < 1)
{
OvrAvatarLog.LogError("UISceneSwitcher::SelectButtonFromIndex : No scene buttons found.", logScope);
return;
}
EventSystem.current.SetSelectedGameObject(null);
_sceneButtons[index].Select();
}
private void LoadScene(string sceneName)
{
if (UIManager.Instance == null || !UIManager.Instance.Initialized)
{
OvrAvatarLog.LogError("UISceneSwitcher::LoadScene : UIManager instance not found.", logScope);
return;
}
UIManager.Instance.Resume();
UIManager.Instance.InvokeOnLoadScene();
UIManager.Instance.AddOnSceneLoadedEvent(SetActiveScene);
OvrAvatarLog.LogInfo($"UISceneSwitcher::LoadScene : Loading scene '{sceneName}'", logScope);
var windowController = UIManager.Instance.GetUIWindowController();
if (windowController == null)
{
OvrAvatarLog.LogError("UISceneSwitcher::LoadScene : Failed to retrieve UIWindowController from UIManager.", logScope);
return;
}
SceneManager.sceneLoaded += windowController.UpdateSceneNameText;
var uiLogger = UIManager.Instance.GetUILogger();
if (uiLogger == null)
{
OvrAvatarLog.LogError("UIWindowController::UpdateLogSection : Failed to retrieve UILogger from UIManager.", logScope);
return;
}
uiLogger.DeactivateUILogger();
uiLogger.DetachUILogger();
var managerGameObject = OvrAvatarManager.Instance.gameObject;
OvrAvatarManager.ResetInstance();
Destroy(managerGameObject);
#if USING_XR_SDK
OvrPlatformInit.ResetOvrPlatformInitState();
#endif
SceneManager.LoadScene(sceneName, LoadSceneMode.Single);
}
private void CreateButtonForScene(string sceneName, GameObject parent)
{
if (UIManager.Instance == null || !UIManager.Instance.Initialized)
{
OvrAvatarLog.LogError("UISceneSwitcher::CreateButtonForScene : UIManager instance not found.", logScope);
return;
}
var buttonGameObject = UIManager.Instance.CreateButtonForUI(parent.transform,
$"Button_Scenes_{sceneName}",
sceneName,
() =>
{
LoadScene(sceneName);
});
if (buttonGameObject == null)
{
OvrAvatarLog.LogError("UISceneSwitcher::CreateButtonForScene : Error in creating UI button game object.", logScope);
return;
}
Button button = buttonGameObject.GetComponent<Button>();
if (button == null)
{
OvrAvatarLog.LogError("UISceneSwitcher::CreateButtonForScene : Created button GameObject has no <Button> component", logScope);
return;
}
_sceneButtons?.Add(button);
}
public void SelectNextSceneButton()
{
if (_sceneButtons == null || _sceneButtons.Count == 0)
{
OvrAvatarLog.LogError("UISceneSwitcher::SelectNextSceneButton : No scene buttons found.", logScope);
return;
}
if (++_currentButtonIndex >= _sceneButtons.Count)
{
_currentButtonIndex = 0;
}
SelectButtonFromIndex(_currentButtonIndex);
}
public void SelectPreviousSceneButton()
{
if (_sceneButtons == null || _sceneButtons.Count == 0)
{
OvrAvatarLog.LogError("UISceneSwitcher::SelectPreviousSceneButton : No scene buttons found.", logScope);
return;
}
if (--_currentButtonIndex < 0)
{
_currentButtonIndex = _sceneButtons.Count - 1;
}
SelectButtonFromIndex(_currentButtonIndex);
}
public void LoadSelectedScene()
{
if (_sceneButtons == null || _sceneButtons.Count == 0 || _sceneNames == null || _sceneNames.Count == 0)
{
OvrAvatarLog.LogError("UISceneSwitcher::LoadSelectedScene : No scene buttons or names found.", logScope);
return;
}
if (_currentButtonIndex < 0 || _currentButtonIndex >= _sceneButtons.Count)
{
OvrAvatarLog.LogError("UISceneSwitcher::LoadSelectedScene : Current button index is out of range.", logScope);
return;
}
LoadScene(_sceneNames[_currentButtonIndex]);
}
}