280 lines
8.1 KiB
C#
280 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",
|
|
"launchEzGame",
|
|
"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 = GameObject.Find("__UnimplementedFeatureBlockerHost");
|
|
if (old != null)
|
|
UnityEngine.Object.Destroy(old);
|
|
return;
|
|
}
|
|
|
|
GameObject host = GameObject.Find("__UnimplementedFeatureBlockerHost");
|
|
if (host == null)
|
|
host = new GameObject("__UnimplementedFeatureBlockerHost");
|
|
UnityEngine.Object.DontDestroyOnLoad(host);
|
|
|
|
if (host.GetComponent<UI_UnimplementedFeatureBlocker>() == null)
|
|
host.AddComponent<UI_UnimplementedFeatureBlocker>();
|
|
}
|
|
}
|