c73ff7f412
- NasPublisher: DSM 7.2 multipart body 수동 구성으로 업로드 401 오류 해결 - NasPublisher: 비밀번호 StreamingAssets/nas_config.json 분리, .gitignore 등록 - NasPublisher: staticBaseUrl 포트 8180 → 80 수정 - BeatSageUploader: Easy 난이도 제거, ExpertPlus(.dat) 추가 - NoteData: DifficultyMap에서 easy 제거, expertplus 추가 - SongCreatorManager: toggleEasy → toggleExpertPlus 교체 - SongDetailPanel: btnEasy → btnExpertPlus 교체 - DownloadManager: DownloadHandlerFile 경로 정규화(Path.GetFullPath), mapFile 빈 값 방어 처리 - PersistentXRRig: FindObjectsOfType obsolete 경고 수정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
162 lines
5.2 KiB
C#
162 lines
5.2 KiB
C#
using UnityEngine;
|
|
using UnityEngine.InputSystem;
|
|
using UnityEngine.SceneManagement;
|
|
using UnityEngine.UI;
|
|
|
|
/// <summary>
|
|
/// 에디터/PC 환경 전용 테스트 보조 스크립트.
|
|
/// RuntimeInitializeOnLoadMethod로 자동 생성되므로 씬에 직접 추가할 필요 없습니다.
|
|
/// Quest 빌드 시 자동으로 비활성화됩니다.
|
|
///
|
|
/// 기능:
|
|
/// 1. TrackedDeviceGraphicRaycaster → GraphicRaycaster 교체 (마우스 클릭 활성화)
|
|
/// 2. Canvas EventCamera 자동 갱신 (클릭 위치 정확도)
|
|
/// 3. ESC 키로 씬별 뒤로가기
|
|
/// </summary>
|
|
public class DesktopUIMode : MonoBehaviour
|
|
{
|
|
#if !UNITY_ANDROID || UNITY_EDITOR
|
|
|
|
// 어떤 씬에서 Play를 눌러도 자동 실행
|
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
|
|
private static void AutoCreate()
|
|
{
|
|
if (FindObjectOfType<DesktopUIMode>() != null) return; // 이미 있으면 생성 안 함
|
|
|
|
var go = new GameObject("[DesktopUIMode]");
|
|
go.AddComponent<DesktopUIMode>();
|
|
}
|
|
|
|
// ESC 뒤로가기 씬 매핑
|
|
private static readonly System.Collections.Generic.Dictionary<string, string> BackSceneMap =
|
|
new System.Collections.Generic.Dictionary<string, string>
|
|
{
|
|
{ "SongSelect", "Intro" },
|
|
{ "SongCreator", "Intro" },
|
|
{ "MapEditorScene", "SongCreator" },
|
|
{ "Game", "SongSelect" },
|
|
};
|
|
|
|
private void Awake()
|
|
{
|
|
// 중복 방지 (씬에 직접 놓은 경우 AutoCreate와 겹칠 수 있음)
|
|
if (FindObjectsOfType<DesktopUIMode>().Length > 1)
|
|
{
|
|
Destroy(gameObject);
|
|
return;
|
|
}
|
|
|
|
DontDestroyOnLoad(gameObject);
|
|
SceneManager.sceneLoaded += OnSceneLoaded;
|
|
PatchCanvases(); // 현재 씬 즉시 패치
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
SceneManager.sceneLoaded -= OnSceneLoaded;
|
|
}
|
|
|
|
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
|
{
|
|
StartCoroutine(PatchAfterFrame());
|
|
}
|
|
|
|
private System.Collections.IEnumerator PatchAfterFrame()
|
|
{
|
|
yield return null; // Canvas.Awake 이후 실행 보장
|
|
PatchCanvases();
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
RefreshCanvasCameras(); // 매 프레임 worldCamera 갱신 (카메라 초기화 타이밍 보정)
|
|
|
|
if (Keyboard.current?.escapeKey.wasPressedThisFrame == true)
|
|
GoBack();
|
|
}
|
|
|
|
// ── Canvas 패치 ──────────────────────────────────────────
|
|
|
|
private static void PatchCanvases()
|
|
{
|
|
foreach (var canvas in FindObjectsOfType<Canvas>())
|
|
{
|
|
if (canvas.renderMode != RenderMode.WorldSpace) continue;
|
|
|
|
// TrackedDeviceGraphicRaycaster → GraphicRaycaster
|
|
var tracked = canvas.GetComponent("TrackedDeviceGraphicRaycaster");
|
|
if (tracked != null)
|
|
{
|
|
DestroyImmediate(tracked);
|
|
if (canvas.GetComponent<GraphicRaycaster>() == null)
|
|
canvas.gameObject.AddComponent<GraphicRaycaster>();
|
|
|
|
Debug.Log($"[DesktopUIMode] {canvas.name} Raycaster 교체 완료");
|
|
}
|
|
}
|
|
|
|
RemoveDuplicateAudioListeners();
|
|
RefreshCanvasCameras();
|
|
}
|
|
|
|
private static void RemoveDuplicateAudioListeners()
|
|
{
|
|
var listeners = FindObjectsOfType<AudioListener>();
|
|
if (listeners.Length <= 1) return;
|
|
|
|
// 첫 번째(DontDestroyOnLoad에 없는 것 우선)만 남기고 나머지 제거
|
|
AudioListener keep = null;
|
|
foreach (var al in listeners)
|
|
{
|
|
if (al.gameObject.scene.name != "DontDestroyOnLoad")
|
|
{ keep = al; break; }
|
|
}
|
|
if (keep == null) keep = listeners[0];
|
|
|
|
foreach (var al in listeners)
|
|
{
|
|
if (al != keep)
|
|
{
|
|
Debug.Log($"[DesktopUIMode] 중복 AudioListener 제거: {al.gameObject.name}");
|
|
DestroyImmediate(al);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void RefreshCanvasCameras()
|
|
{
|
|
Camera cam = Camera.main;
|
|
if (cam == null)
|
|
{
|
|
// Camera.main이 없으면 씬에서 직접 찾기 (DontDestroyOnLoad 제외)
|
|
foreach (var c in FindObjectsOfType<Camera>())
|
|
{
|
|
if (c.enabled && c.gameObject.scene.name != "DontDestroyOnLoad")
|
|
{
|
|
cam = c;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (cam == null) cam = FindObjectOfType<Camera>(); // 최후 수단
|
|
if (cam == null) return;
|
|
|
|
foreach (var canvas in FindObjectsOfType<Canvas>())
|
|
{
|
|
if (canvas.renderMode == RenderMode.WorldSpace && canvas.worldCamera != cam)
|
|
canvas.worldCamera = cam;
|
|
}
|
|
}
|
|
|
|
// ── ESC 뒤로가기 ─────────────────────────────────────────
|
|
|
|
private static void GoBack()
|
|
{
|
|
string current = SceneManager.GetActiveScene().name;
|
|
if (BackSceneMap.TryGetValue(current, out string target))
|
|
SceneManager.LoadScene(target);
|
|
}
|
|
|
|
#endif
|
|
}
|