651 lines
21 KiB
C#
651 lines
21 KiB
C#
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using UnityEngine.Events;
|
|
using UnityEngine.SceneManagement;
|
|
using System.Collections.Generic;
|
|
|
|
public class btmandtopController : MonoBehaviour
|
|
{
|
|
[Header("player unique so")]
|
|
public Player_SO player_SO;
|
|
[Header("put prefabs here")]
|
|
public GameObject putPrefabsHere;
|
|
[Header("son buttons")]
|
|
public Button settings_launch;
|
|
public Button userInfo_launch;
|
|
public Button store_launch;
|
|
public Button showLevel_display;
|
|
public Button email_display;
|
|
public Button notice_display;
|
|
|
|
public Button button_Music;
|
|
[Header("MusicPic")]
|
|
public RectTransform musicPicRoot;
|
|
public bool showMusicPicInUI = false;
|
|
public string uiSceneName = "UI_UI";
|
|
public float musicPicFadeTime = 0.25f;
|
|
|
|
[Header("sig prefabs")]
|
|
public GameObject showLevel_prefab;
|
|
public GameObject store_prefab;
|
|
public GameObject settings_prefab;
|
|
public GameObject userInfo_prefab;
|
|
public GameObject email_prefab;
|
|
public GameObject notice_prefab;
|
|
|
|
[Header("New Back Buttons")]
|
|
[SerializeField] private Button back_navButton;
|
|
[SerializeField] private Button home_navButton;
|
|
[SerializeField] private Button settings_navButton;
|
|
[SerializeField] private string homeSceneName = "UI_UI";
|
|
[SerializeField] private string backFallbackSceneName = "Main_main";
|
|
|
|
private UnityAction instantiateSettings;
|
|
private UnityAction instantiateUserInfo;
|
|
private UnityAction instantiateStore;
|
|
private UnityAction instantiateShowLevel;
|
|
private UnityAction instantiateEmail;
|
|
private UnityAction instantiateNotice;
|
|
private UnityAction navBackAction;
|
|
private UnityAction navHomeAction;
|
|
private UnityAction navSettingsAction;
|
|
|
|
// cached reference to the settings instance to ensure only one exists
|
|
private GameObject settingsInstance;
|
|
private GameObject showLevelInstance;
|
|
private GameObject emailInstance;
|
|
private GameObject noticeInstance;
|
|
private CanvasGroup musicPicGroup;
|
|
private Coroutine musicPicFade;
|
|
private bool musicPicVisible = true;
|
|
private bool navSceneLoading = false;
|
|
|
|
private static readonly List<string> sceneHistory = new List<string>();
|
|
private static bool sceneHistoryHooked = false;
|
|
private static string trackedCurrentScene = string.Empty;
|
|
|
|
void Awake()
|
|
{
|
|
EnsureMusicPicRoot();
|
|
InitializeSceneHistoryIfNeeded();
|
|
}
|
|
|
|
void Start()
|
|
{
|
|
if (button_Music == null)
|
|
{
|
|
var btn = transform.Find("Button_Music") as RectTransform;
|
|
if (btn != null)
|
|
button_Music = btn.GetComponent<Button>();
|
|
if (button_Music == null)
|
|
{
|
|
var any = FindByName("Button_Music");
|
|
if (any != null) button_Music = any.GetComponent<Button>();
|
|
}
|
|
}
|
|
instantiateSettings = () => ToggleSettingsPrefab();
|
|
instantiateUserInfo = () => InstantiatePrefab(userInfo_prefab);
|
|
instantiateStore = () => InstantiatePrefab(store_prefab);
|
|
instantiateShowLevel = () => ShowLevelPrefab();
|
|
instantiateEmail = () => ShowEmailPrefab();
|
|
instantiateNotice = () => ShowNoticePrefab();
|
|
|
|
if (settings_launch != null)
|
|
settings_launch.onClick.AddListener(instantiateSettings);
|
|
if (userInfo_launch != null)
|
|
userInfo_launch.onClick.AddListener(instantiateUserInfo);
|
|
if (store_launch != null)
|
|
store_launch.onClick.AddListener(instantiateStore);
|
|
if (showLevel_display != null)
|
|
showLevel_display.onClick.AddListener(instantiateShowLevel);
|
|
if (email_display != null)
|
|
email_display.onClick.AddListener(instantiateEmail);
|
|
if (notice_display != null)
|
|
notice_display.onClick.AddListener(instantiateNotice);
|
|
|
|
BindNewBackButtons();
|
|
|
|
EnsureMusicPicRoot();
|
|
SetupMusicPicDefault();
|
|
if (button_Music != null)
|
|
button_Music.onClick.AddListener(ToggleMusicPicLocal);
|
|
|
|
var binder = BgmUiBinder.Instance != null ? BgmUiBinder.Instance : Object.FindAnyObjectByType<BgmUiBinder>();
|
|
if (binder != null && musicPicRoot != null)
|
|
{
|
|
binder.SetMusicRoot(musicPicRoot);
|
|
}
|
|
|
|
// Pre-instantiate settings prefab and keep it inactive, ensuring only one exists
|
|
if (settings_prefab != null && putPrefabsHere != null)
|
|
{
|
|
// Try to find existing one in scene first
|
|
if (settingsInstance == null)
|
|
{
|
|
var existing = GameObject.Find(settings_prefab.name + "(Clone)");
|
|
if (existing != null)
|
|
{
|
|
settingsInstance = existing;
|
|
}
|
|
}
|
|
|
|
if (settingsInstance == null)
|
|
{
|
|
settingsInstance = Instantiate(settings_prefab, putPrefabsHere.transform);
|
|
EnsureSettingsEnterAnimator(settingsInstance);
|
|
settingsInstance.SetActive(false);
|
|
|
|
// try to set canvas camera now as in previous behavior
|
|
try
|
|
{
|
|
Canvas c = settingsInstance.GetComponentInChildren<Canvas>(true);
|
|
if (c != null)
|
|
{
|
|
Camera[] cams = Object.FindObjectsByType<Camera>(FindObjectsInactive.Exclude, FindObjectsSortMode.None);
|
|
if (cams != null && cams.Length > 0)
|
|
{
|
|
c.worldCamera = cams[0];
|
|
}
|
|
cams = null;
|
|
c = null;
|
|
}
|
|
}
|
|
catch { }
|
|
}
|
|
else
|
|
{
|
|
// ensure it's parented correctly under putPrefabsHere
|
|
settingsInstance.transform.SetParent(putPrefabsHere.transform, false);
|
|
EnsureSettingsEnterAnimator(settingsInstance);
|
|
settingsInstance.SetActive(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
private void FixedUpdate()
|
|
{
|
|
if(Input.GetKeyDown(KeyCode.Escape))
|
|
{
|
|
//ToggleSettingsPrefab();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private void ToggleMusicPic()
|
|
{
|
|
var binder = BgmUiBinder.Instance != null ? BgmUiBinder.Instance : Object.FindAnyObjectByType<BgmUiBinder>();
|
|
if (binder != null)
|
|
{
|
|
binder.ToggleMusicPic();
|
|
var spectrum = binder.GetSpectrumRoot();
|
|
if (spectrum != null && binder.transform != null)
|
|
{
|
|
spectrum.localRotation = binder.transform.localRotation;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void EnsureMusicPicRoot()
|
|
{
|
|
if (musicPicRoot != null)
|
|
return;
|
|
var child = transform.Find("MusicPic");
|
|
if (child != null)
|
|
{
|
|
musicPicRoot = child as RectTransform;
|
|
return;
|
|
}
|
|
var sceneMusic = GameObject.Find("MusicPic");
|
|
if (sceneMusic != null)
|
|
{
|
|
musicPicRoot = sceneMusic.GetComponent<RectTransform>();
|
|
if (musicPicRoot != null)
|
|
{
|
|
musicPicRoot.SetParent(transform, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void SetupMusicPicDefault()
|
|
{
|
|
if (musicPicRoot == null)
|
|
return;
|
|
EnsureMusicPicGroup();
|
|
SetMusicPicVisible(false, true);
|
|
}
|
|
|
|
private void EnsureMusicPicGroup()
|
|
{
|
|
if (musicPicRoot == null)
|
|
return;
|
|
if (musicPicGroup == null)
|
|
musicPicGroup = musicPicRoot.GetComponent<CanvasGroup>();
|
|
if (musicPicGroup == null)
|
|
musicPicGroup = musicPicRoot.gameObject.AddComponent<CanvasGroup>();
|
|
}
|
|
|
|
private void ToggleMusicPicLocal()
|
|
{
|
|
EnsureMusicPicRoot();
|
|
var binder = BgmUiBinder.Instance != null ? BgmUiBinder.Instance : Object.FindAnyObjectByType<BgmUiBinder>();
|
|
if (musicPicRoot == null)
|
|
{
|
|
if (binder != null)
|
|
binder.ToggleMusicPic();
|
|
return;
|
|
}
|
|
|
|
SetMusicPicVisible(!musicPicVisible, false);
|
|
}
|
|
|
|
private void SetMusicPicVisible(bool visible, bool instant)
|
|
{
|
|
if (musicPicRoot == null)
|
|
return;
|
|
EnsureMusicPicGroup();
|
|
musicPicVisible = visible;
|
|
|
|
if (musicPicFade != null)
|
|
{
|
|
StopCoroutine(musicPicFade);
|
|
musicPicFade = null;
|
|
}
|
|
|
|
if (instant)
|
|
{
|
|
musicPicGroup.alpha = visible ? 1f : 0f;
|
|
musicPicGroup.interactable = visible;
|
|
musicPicGroup.blocksRaycasts = visible;
|
|
musicPicRoot.gameObject.SetActive(visible);
|
|
return;
|
|
}
|
|
|
|
musicPicRoot.gameObject.SetActive(true);
|
|
musicPicFade = StartCoroutine(FadeMusicPic(visible));
|
|
}
|
|
|
|
private System.Collections.IEnumerator FadeMusicPic(bool visibleAtEnd)
|
|
{
|
|
EnsureMusicPicGroup();
|
|
if (musicPicGroup == null)
|
|
yield break;
|
|
float start = musicPicGroup != null ? musicPicGroup.alpha : 0f;
|
|
float target = visibleAtEnd ? 1f : 0f;
|
|
float t = 0f;
|
|
while (t < 1f)
|
|
{
|
|
if (musicPicGroup == null || musicPicRoot == null)
|
|
yield break;
|
|
t += Time.unscaledDeltaTime / Mathf.Max(0.0001f, musicPicFadeTime);
|
|
float eased = Mathf.SmoothStep(0f, 1f, t);
|
|
musicPicGroup.alpha = Mathf.LerpUnclamped(start, target, eased);
|
|
yield return null;
|
|
}
|
|
if (musicPicGroup != null)
|
|
{
|
|
musicPicGroup.alpha = target;
|
|
musicPicGroup.interactable = visibleAtEnd;
|
|
musicPicGroup.blocksRaycasts = visibleAtEnd;
|
|
}
|
|
if (!visibleAtEnd && musicPicRoot != null)
|
|
{
|
|
musicPicRoot.gameObject.SetActive(false);
|
|
}
|
|
}
|
|
|
|
GameObject FindByName(string name)
|
|
{
|
|
var all = Resources.FindObjectsOfTypeAll<Transform>();
|
|
for (int i = 0; i < all.Length; i++)
|
|
{
|
|
var t = all[i];
|
|
if (t == null) continue;
|
|
if (!t.gameObject.scene.IsValid() || !t.gameObject.scene.isLoaded) continue;
|
|
if (t.name == name) return t.gameObject;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
void OnDestroy()
|
|
{
|
|
if (musicPicFade != null)
|
|
{
|
|
StopCoroutine(musicPicFade);
|
|
musicPicFade = null;
|
|
}
|
|
musicPicGroup = null;
|
|
if (settings_launch != null)
|
|
settings_launch.onClick.RemoveListener(instantiateSettings);
|
|
if (userInfo_launch != null)
|
|
userInfo_launch.onClick.RemoveListener(instantiateUserInfo);
|
|
if (store_launch != null)
|
|
store_launch.onClick.RemoveListener(instantiateStore);
|
|
if (showLevel_display != null)
|
|
showLevel_display.onClick.RemoveListener(instantiateShowLevel);
|
|
if (email_display != null)
|
|
email_display.onClick.RemoveListener(instantiateEmail);
|
|
if (notice_display != null)
|
|
notice_display.onClick.RemoveListener(instantiateNotice);
|
|
|
|
if (button_Music != null)
|
|
button_Music.onClick.RemoveListener(ToggleMusicPicLocal);
|
|
|
|
if (back_navButton != null && navBackAction != null)
|
|
back_navButton.onClick.RemoveListener(navBackAction);
|
|
if (home_navButton != null && navHomeAction != null)
|
|
home_navButton.onClick.RemoveListener(navHomeAction);
|
|
if (settings_navButton != null && navSettingsAction != null)
|
|
settings_navButton.onClick.RemoveListener(navSettingsAction);
|
|
}
|
|
|
|
private void ToggleSettingsPrefab()
|
|
{
|
|
if (settings_prefab == null || putPrefabsHere == null) return;
|
|
|
|
// If we don't have an instance (it may have been destroyed), instantiate one
|
|
if (settingsInstance == null)
|
|
{
|
|
settingsInstance = Instantiate(settings_prefab, putPrefabsHere.transform);
|
|
EnsureSettingsEnterAnimator(settingsInstance);
|
|
|
|
// attempt to set canvas camera
|
|
try
|
|
{
|
|
Canvas c = settingsInstance.GetComponentInChildren<Canvas>(true);
|
|
if (c != null)
|
|
{
|
|
Camera[] cams = Object.FindObjectsByType<Camera>(FindObjectsInactive.Exclude, FindObjectsSortMode.None);
|
|
if (cams != null && cams.Length > 0)
|
|
{
|
|
c.worldCamera = cams[0];
|
|
}
|
|
cams = null;
|
|
c = null;
|
|
}
|
|
}
|
|
catch { }
|
|
|
|
settingsInstance.SetActive(true);
|
|
return;
|
|
}
|
|
|
|
EnsureSettingsEnterAnimator(settingsInstance);
|
|
|
|
// Toggle active state
|
|
bool active = settingsInstance.activeSelf;
|
|
settingsInstance.SetActive(!active);
|
|
}
|
|
|
|
private void ShowLevelPrefab()
|
|
{
|
|
ShowPrefab(showLevel_prefab, ref showLevelInstance);
|
|
CloseInfoPanels(showLevelInstance);
|
|
}
|
|
|
|
private void ShowEmailPrefab()
|
|
{
|
|
ShowPrefab(email_prefab, ref emailInstance);
|
|
CloseInfoPanels(emailInstance);
|
|
}
|
|
|
|
private void ShowNoticePrefab()
|
|
{
|
|
ShowPrefab(notice_prefab, ref noticeInstance);
|
|
CloseInfoPanels(noticeInstance);
|
|
}
|
|
|
|
private void ShowPrefab(GameObject prefab, ref GameObject instance)
|
|
{
|
|
if (prefab == null || putPrefabsHere == null) return;
|
|
|
|
if (instance == null)
|
|
{
|
|
instance = FindExistingInstance(prefab);
|
|
if (instance == null)
|
|
{
|
|
instance = Instantiate(prefab, putPrefabsHere.transform);
|
|
TryAssignCanvasCamera(instance);
|
|
}
|
|
else
|
|
{
|
|
instance.transform.SetParent(putPrefabsHere.transform, false);
|
|
}
|
|
}
|
|
|
|
instance.SetActive(true);
|
|
instance.transform.SetAsLastSibling();
|
|
}
|
|
|
|
private void CloseInfoPanels(GameObject keep)
|
|
{
|
|
CloseInstance(ref showLevelInstance, keep);
|
|
CloseInstance(ref emailInstance, keep);
|
|
CloseInstance(ref noticeInstance, keep);
|
|
}
|
|
|
|
private void CloseInstance(ref GameObject instance, GameObject keep)
|
|
{
|
|
if (instance == null || instance == keep) return;
|
|
instance.SetActive(false);
|
|
}
|
|
|
|
private GameObject FindExistingInstance(GameObject prefab)
|
|
{
|
|
if (prefab == null || putPrefabsHere == null) return null;
|
|
|
|
Transform parent = putPrefabsHere.transform;
|
|
for (int i = 0; i < parent.childCount; i++)
|
|
{
|
|
Transform child = parent.GetChild(i);
|
|
if (child == null) continue;
|
|
if (child.name == prefab.name || child.name == prefab.name + "(Clone)")
|
|
{
|
|
return child.gameObject;
|
|
}
|
|
}
|
|
|
|
GameObject existing = GameObject.Find(prefab.name + "(Clone)");
|
|
return existing;
|
|
}
|
|
|
|
private void TryAssignCanvasCamera(GameObject instance)
|
|
{
|
|
if (instance == null) return;
|
|
|
|
try
|
|
{
|
|
Canvas c = instance.GetComponentInChildren<Canvas>(true);
|
|
if (c != null)
|
|
{
|
|
Camera[] cams = Object.FindObjectsByType<Camera>(FindObjectsInactive.Exclude, FindObjectsSortMode.None);
|
|
if (cams != null && cams.Length > 0)
|
|
{
|
|
c.worldCamera = cams[0];
|
|
}
|
|
}
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
private void InstantiatePrefab(GameObject prefab)
|
|
{
|
|
if (prefab != null && putPrefabsHere != null)
|
|
{
|
|
GameObject instance = Instantiate(prefab, putPrefabsHere.transform);
|
|
instance = null;
|
|
}
|
|
}
|
|
|
|
private void EnsureSettingsEnterAnimator(GameObject instance)
|
|
{
|
|
if (instance == null) return;
|
|
|
|
UI_SettingsPanelEnterAnim anim = instance.GetComponent<UI_SettingsPanelEnterAnim>();
|
|
if (anim == null)
|
|
anim = instance.AddComponent<UI_SettingsPanelEnterAnim>();
|
|
anim.enabled = true;
|
|
}
|
|
|
|
private void BindNewBackButtons()
|
|
{
|
|
ResolveNewBackButtons();
|
|
|
|
navBackAction = OnBackNavClicked;
|
|
navHomeAction = OnHomeNavClicked;
|
|
navSettingsAction = OnSettingsNavClicked;
|
|
|
|
if (back_navButton != null)
|
|
{
|
|
back_navButton.onClick.RemoveListener(navBackAction);
|
|
back_navButton.onClick.AddListener(navBackAction);
|
|
}
|
|
|
|
if (home_navButton != null)
|
|
{
|
|
home_navButton.onClick.RemoveListener(navHomeAction);
|
|
home_navButton.onClick.AddListener(navHomeAction);
|
|
}
|
|
|
|
if (settings_navButton != null)
|
|
{
|
|
settings_navButton.onClick.RemoveListener(navSettingsAction);
|
|
settings_navButton.onClick.AddListener(navSettingsAction);
|
|
}
|
|
}
|
|
|
|
private void ResolveNewBackButtons()
|
|
{
|
|
Transform navRoot = FindChildRecursive(transform, "New back");
|
|
if (navRoot == null)
|
|
{
|
|
GameObject sceneRoot = FindByName("New back");
|
|
if (sceneRoot != null)
|
|
navRoot = sceneRoot.transform;
|
|
}
|
|
|
|
if (back_navButton == null)
|
|
back_navButton = FindButtonByName(navRoot, "back");
|
|
if (home_navButton == null)
|
|
home_navButton = FindButtonByName(navRoot, "home");
|
|
if (settings_navButton == null)
|
|
settings_navButton = FindButtonByName(navRoot, "settings");
|
|
}
|
|
|
|
private static Transform FindChildRecursive(Transform root, string childName)
|
|
{
|
|
if (root == null || string.IsNullOrEmpty(childName)) return null;
|
|
if (root.name == childName) return root;
|
|
|
|
for (int i = 0; i < root.childCount; i++)
|
|
{
|
|
Transform child = root.GetChild(i);
|
|
Transform found = FindChildRecursive(child, childName);
|
|
if (found != null) return found;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private static Button FindButtonByName(Transform root, string name)
|
|
{
|
|
if (string.IsNullOrEmpty(name)) return null;
|
|
|
|
if (root != null)
|
|
{
|
|
Button[] buttons = root.GetComponentsInChildren<Button>(true);
|
|
for (int i = 0; i < buttons.Length; i++)
|
|
{
|
|
Button btn = buttons[i];
|
|
if (btn != null && string.Equals(btn.gameObject.name, name, System.StringComparison.OrdinalIgnoreCase))
|
|
return btn;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static void InitializeSceneHistoryIfNeeded()
|
|
{
|
|
if (sceneHistoryHooked) return;
|
|
sceneHistoryHooked = true;
|
|
trackedCurrentScene = SceneManager.GetActiveScene().name ?? string.Empty;
|
|
SceneManager.sceneLoaded += OnSceneLoadedTrackHistory;
|
|
}
|
|
|
|
private static void OnSceneLoadedTrackHistory(Scene scene, LoadSceneMode mode)
|
|
{
|
|
string incoming = scene.name ?? string.Empty;
|
|
if (!string.IsNullOrEmpty(trackedCurrentScene) &&
|
|
!string.Equals(trackedCurrentScene, incoming, System.StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
if (sceneHistory.Count == 0 ||
|
|
!string.Equals(sceneHistory[sceneHistory.Count - 1], trackedCurrentScene, System.StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
sceneHistory.Add(trackedCurrentScene);
|
|
if (sceneHistory.Count > 24) sceneHistory.RemoveAt(0);
|
|
}
|
|
}
|
|
trackedCurrentScene = incoming;
|
|
}
|
|
|
|
private static string PopPreviousSceneName(string currentScene)
|
|
{
|
|
for (int i = sceneHistory.Count - 1; i >= 0; i--)
|
|
{
|
|
string candidate = sceneHistory[i];
|
|
sceneHistory.RemoveAt(i);
|
|
if (string.IsNullOrEmpty(candidate)) continue;
|
|
if (string.Equals(candidate, currentScene, System.StringComparison.OrdinalIgnoreCase)) continue;
|
|
return candidate;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private void OnBackNavClicked()
|
|
{
|
|
if (navSceneLoading) return;
|
|
InitializeSceneHistoryIfNeeded();
|
|
|
|
string current = SceneManager.GetActiveScene().name ?? string.Empty;
|
|
string target = PopPreviousSceneName(current);
|
|
if (string.IsNullOrEmpty(target))
|
|
{
|
|
target = string.IsNullOrEmpty(backFallbackSceneName) ? "Main_main" : backFallbackSceneName;
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(target) &&
|
|
!string.Equals(target, current, System.StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
StartCoroutine(LoadNavSceneAsync(target));
|
|
}
|
|
}
|
|
|
|
private void OnHomeNavClicked()
|
|
{
|
|
if (navSceneLoading) return;
|
|
string target = string.IsNullOrEmpty(homeSceneName) ? "UI_UI" : homeSceneName;
|
|
StartCoroutine(LoadNavSceneAsync(target));
|
|
}
|
|
|
|
private void OnSettingsNavClicked()
|
|
{
|
|
ToggleSettingsPrefab();
|
|
}
|
|
|
|
private System.Collections.IEnumerator LoadNavSceneAsync(string sceneName)
|
|
{
|
|
if (string.IsNullOrEmpty(sceneName)) yield break;
|
|
if (navSceneLoading) yield break;
|
|
|
|
navSceneLoading = true;
|
|
Time.timeScale = 1f;
|
|
AsyncOperation op = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Single);
|
|
while (op != null && !op.isDone)
|
|
{
|
|
yield return null;
|
|
}
|
|
navSceneLoading = false;
|
|
}
|
|
}
|