Files
bansonic_beta_main/Assets/scripts/UI/UI_UnimplementedFeatureBlocker.cs

279 lines
8.1 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class UI_UnimplementedFeatureBlocker : MonoBehaviour
{
public static bool RuntimeEnabled = false;
[SerializeField] private string[] blockedButtonNames =
{
"Button_STORY",
"Button_IDOL",
"Button_NOTEBOOK",
"Button_CHARACTER_SET",
"Button_Market",
"Button_Personal_information",
"Button_view_level",
"Button_Mail",
"Button_notice"
};
private Coroutine bindRoutine;
private Coroutine continuousBindRoutine;
private void OnEnable()
{
if (!RuntimeEnabled)
{
CleanupOverlaysInLoadedScenes();
enabled = false;
return;
}
SceneManager.sceneLoaded -= OnSceneLoaded;
SceneManager.sceneLoaded += OnSceneLoaded;
StartBind(SceneManager.GetActiveScene());
if (continuousBindRoutine == null)
continuousBindRoutine = StartCoroutine(ContinuousBindLoop());
}
private void OnDisable()
{
SceneManager.sceneLoaded -= OnSceneLoaded;
if (bindRoutine != null)
{
StopCoroutine(bindRoutine);
bindRoutine = null;
}
if (continuousBindRoutine != null)
{
StopCoroutine(continuousBindRoutine);
continuousBindRoutine = null;
}
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
StartBind(scene);
}
private void StartBind(Scene scene)
{
if (!scene.IsValid() || !scene.isLoaded)
return;
if (bindRoutine != null)
{
StopCoroutine(bindRoutine);
bindRoutine = null;
}
bindRoutine = StartCoroutine(BindRoutine(scene));
}
private IEnumerator BindRoutine(Scene scene)
{
// Repeat binding multiple times so we override listeners added in Start/OnEnable by scene scripts.
for (int i = 0; i < 4; i++)
{
ApplyBlockers();
yield return new WaitForSecondsRealtime(0.12f);
}
bindRoutine = null;
}
private IEnumerator ContinuousBindLoop()
{
while (enabled)
{
ApplyBlockers();
yield return new WaitForSecondsRealtime(0.5f);
}
}
private void ApplyBlockers()
{
if (blockedButtonNames == null || blockedButtonNames.Length == 0)
return;
HashSet<Button> candidates = new HashSet<Button>();
Transform[] all = UnityEngine.Object.FindObjectsByType<Transform>(FindObjectsInactive.Include, FindObjectsSortMode.None);
for (int j = 0; j < all.Length; j++)
{
Transform t = all[j];
if (t == null)
continue;
if (!t.gameObject.scene.IsValid() || !t.gameObject.scene.isLoaded)
continue;
if (!IsBlockedName(t.name))
continue;
CollectNearbyButtons(t, candidates);
}
foreach (Button btn in candidates)
{
if (btn == null)
continue;
btn.onClick.RemoveAllListeners();
btn.onClick.AddListener(OnBlockedButtonClick);
EnsureOverlayClickBlocker(btn);
}
}
private void CollectNearbyButtons(Transform target, HashSet<Button> set)
{
if (target == null || set == null)
return;
Button self = target.GetComponent<Button>();
if (self != null)
set.Add(self);
Button parent = target.GetComponentInParent<Button>(true);
if (parent != null)
set.Add(parent);
Button[] children = target.GetComponentsInChildren<Button>(true);
for (int i = 0; i < children.Length; i++)
{
if (children[i] != null)
set.Add(children[i]);
}
}
private bool IsBlockedName(string objectName)
{
if (string.IsNullOrEmpty(objectName) || blockedButtonNames == null)
return false;
string current = NormalizeName(objectName);
for (int i = 0; i < blockedButtonNames.Length; i++)
{
string target = blockedButtonNames[i];
if (string.IsNullOrEmpty(target))
continue;
string normalizedTarget = NormalizeName(target);
if (current == normalizedTarget)
return true;
if (current.Contains(normalizedTarget) || normalizedTarget.Contains(current))
return true;
}
return false;
}
private string NormalizeName(string value)
{
if (string.IsNullOrEmpty(value))
return string.Empty;
return value
.Replace(" ", "")
.Replace("_", "")
.Replace("-", "")
.ToLowerInvariant();
}
private void EnsureOverlayClickBlocker(Button sourceButton)
{
if (sourceButton == null) return;
const string overlayName = "__BlockedFeatureOverlay";
Transform host = sourceButton.targetGraphic != null
? sourceButton.targetGraphic.transform
: sourceButton.transform;
if (host == null)
host = sourceButton.transform;
Transform existing = host.Find(overlayName);
GameObject overlayGo;
if (existing == null)
{
overlayGo = new GameObject(overlayName, typeof(RectTransform), typeof(Image), typeof(Button));
overlayGo.transform.SetParent(host, false);
RectTransform rt = overlayGo.GetComponent<RectTransform>();
rt.anchorMin = Vector2.zero;
rt.anchorMax = Vector2.one;
rt.offsetMin = Vector2.zero;
rt.offsetMax = Vector2.zero;
rt.localScale = Vector3.one;
Image img = overlayGo.GetComponent<Image>();
img.color = new Color(1f, 1f, 1f, 0f);
img.raycastTarget = true;
}
else
{
overlayGo = existing.gameObject;
}
overlayGo.SetActive(true);
overlayGo.transform.SetAsLastSibling();
Button overlayBtn = overlayGo.GetComponent<Button>();
if (overlayBtn != null)
{
overlayBtn.transition = Selectable.Transition.None;
overlayBtn.onClick.RemoveAllListeners();
overlayBtn.onClick.AddListener(OnBlockedButtonClick);
}
}
private void OnBlockedButtonClick()
{
if (!RuntimeEnabled)
return;
UnimplementedFeaturePrompt.ShowPrompt();
}
private static void CleanupOverlaysInLoadedScenes()
{
Transform[] all = UnityEngine.Object.FindObjectsByType<Transform>(FindObjectsInactive.Include, FindObjectsSortMode.None);
for (int i = 0; i < all.Length; i++)
{
Transform t = all[i];
if (t == null)
continue;
if (!t.gameObject.scene.IsValid() || !t.gameObject.scene.isLoaded)
continue;
if (!string.Equals(t.name, "__BlockedFeatureOverlay", System.StringComparison.Ordinal))
continue;
if (Application.isPlaying)
UnityEngine.Object.Destroy(t.gameObject);
else
UnityEngine.Object.DestroyImmediate(t.gameObject);
}
}
}
static class UI_UnimplementedFeatureBlockerBootstrap
{
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void Init()
{
if (!UI_UnimplementedFeatureBlocker.RuntimeEnabled)
{
GameObject old = SceneObjectLookupCache.Find("__UnimplementedFeatureBlockerHost");
if (old != null)
UnityEngine.Object.Destroy(old);
return;
}
GameObject host = SceneObjectLookupCache.Find("__UnimplementedFeatureBlockerHost");
if (host == null)
host = new GameObject("__UnimplementedFeatureBlockerHost");
UnityEngine.Object.DontDestroyOnLoad(host);
if (host.GetComponent<UI_UnimplementedFeatureBlocker>() == null)
host.AddComponent<UI_UnimplementedFeatureBlocker>();
}
}