2026-05-21 23:37:34 +09:00
|
|
|
using UnityEngine;
|
|
|
|
|
using UnityEngine.InputSystem;
|
|
|
|
|
using UnityEngine.SceneManagement;
|
|
|
|
|
using UnityEngine.UI;
|
|
|
|
|
|
|
|
|
|
// Editor/PC-only helper — auto-injects at runtime, no need to place in scene.
|
|
|
|
|
// On Quest builds this entire class is stripped.
|
|
|
|
|
//
|
|
|
|
|
// Features:
|
|
|
|
|
// 1. Replaces TrackedDeviceGraphicRaycaster → GraphicRaycaster (enables mouse clicks)
|
|
|
|
|
// 2. Keeps worldCamera up to date on all World Space canvases
|
|
|
|
|
// 3. ESC key navigates back
|
|
|
|
|
public class DesktopUIMode : MonoBehaviour
|
|
|
|
|
{
|
|
|
|
|
#if !UNITY_ANDROID || UNITY_EDITOR
|
|
|
|
|
|
|
|
|
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
|
|
|
|
|
private static void AutoCreate()
|
|
|
|
|
{
|
2026-05-26 18:54:56 +09:00
|
|
|
if (FindFirstObjectByType<DesktopUIMode>() != null) return;
|
2026-05-21 23:37:34 +09:00
|
|
|
new GameObject("[DesktopUIMode]").AddComponent<DesktopUIMode>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static readonly System.Collections.Generic.Dictionary<string, string> BackMap =
|
|
|
|
|
new()
|
|
|
|
|
{
|
|
|
|
|
{ "SongSelect", "Menu" },
|
|
|
|
|
{ "SongCreator", "Menu" },
|
|
|
|
|
{ "MapEditorScene", "SongCreator" },
|
|
|
|
|
{ "Game", "SongSelect" },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
private void Awake()
|
|
|
|
|
{
|
|
|
|
|
if (FindObjectsByType<DesktopUIMode>(FindObjectsSortMode.None).Length > 1)
|
|
|
|
|
{ Destroy(gameObject); return; }
|
|
|
|
|
|
|
|
|
|
DontDestroyOnLoad(gameObject);
|
|
|
|
|
SceneManager.sceneLoaded += OnSceneLoaded;
|
|
|
|
|
PatchCanvases();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnDestroy() => SceneManager.sceneLoaded -= OnSceneLoaded;
|
|
|
|
|
|
|
|
|
|
private void OnSceneLoaded(Scene s, LoadSceneMode m) => StartCoroutine(PatchAfterFrame());
|
|
|
|
|
|
|
|
|
|
private System.Collections.IEnumerator PatchAfterFrame()
|
|
|
|
|
{ yield return null; PatchCanvases(); }
|
|
|
|
|
|
|
|
|
|
private void Update()
|
|
|
|
|
{
|
|
|
|
|
RefreshCanvasCameras();
|
|
|
|
|
if (Keyboard.current?.escapeKey.wasPressedThisFrame == true) GoBack();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void PatchCanvases()
|
|
|
|
|
{
|
|
|
|
|
foreach (var canvas in FindObjectsByType<Canvas>(FindObjectsSortMode.None))
|
|
|
|
|
{
|
|
|
|
|
if (canvas.renderMode != RenderMode.WorldSpace) continue;
|
|
|
|
|
|
|
|
|
|
var tracked = canvas.GetComponent("TrackedDeviceGraphicRaycaster");
|
|
|
|
|
if (tracked != null)
|
|
|
|
|
{
|
|
|
|
|
DestroyImmediate(tracked);
|
|
|
|
|
if (canvas.GetComponent<GraphicRaycaster>() == null)
|
|
|
|
|
canvas.gameObject.AddComponent<GraphicRaycaster>();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RemoveDuplicateAudioListeners();
|
|
|
|
|
RefreshCanvasCameras();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void RemoveDuplicateAudioListeners()
|
|
|
|
|
{
|
|
|
|
|
var listeners = FindObjectsByType<AudioListener>(FindObjectsSortMode.None);
|
|
|
|
|
if (listeners.Length <= 1) return;
|
|
|
|
|
|
|
|
|
|
AudioListener keep = null;
|
|
|
|
|
foreach (var al in listeners)
|
|
|
|
|
if (al.gameObject.scene.name != "DontDestroyOnLoad") { keep = al; break; }
|
|
|
|
|
keep ??= listeners[0];
|
|
|
|
|
|
|
|
|
|
foreach (var al in listeners)
|
|
|
|
|
if (al != keep) DestroyImmediate(al);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void RefreshCanvasCameras()
|
|
|
|
|
{
|
|
|
|
|
Camera cam = Camera.main;
|
|
|
|
|
if (cam == null)
|
|
|
|
|
foreach (var c in FindObjectsByType<Camera>(FindObjectsSortMode.None))
|
|
|
|
|
if (c.enabled && c.gameObject.scene.name != "DontDestroyOnLoad") { cam = c; break; }
|
2026-05-26 18:54:56 +09:00
|
|
|
cam ??= FindFirstObjectByType<Camera>();
|
2026-05-21 23:37:34 +09:00
|
|
|
if (cam == null) return;
|
|
|
|
|
|
|
|
|
|
foreach (var canvas in FindObjectsByType<Canvas>(FindObjectsSortMode.None))
|
|
|
|
|
if (canvas.renderMode == RenderMode.WorldSpace && canvas.worldCamera != cam)
|
|
|
|
|
canvas.worldCamera = cam;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void GoBack()
|
|
|
|
|
{
|
|
|
|
|
if (BackMap.TryGetValue(SceneManager.GetActiveScene().name, out string target))
|
|
|
|
|
SceneManager.LoadScene(target);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
}
|