using System.Collections; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; public class UnimplementedFeaturePrompt : MonoBehaviour { public static bool RuntimeEnabled = false; private static UnimplementedFeaturePrompt instance; [Header("Flash")] [SerializeField] private int flashCount = 2; [SerializeField] private float flashOnTime = 0.04f; [SerializeField] private float flashOffTime = 0.03f; private GameObject root; private GameObject pressText; private GameObject noChoice; private GameObject choiceLessThanFive; private GameObject image3; private Button continueButton; private Button considerButton; private Button doNotShowAgainButton; private Button okayButton; private Coroutine flashRoutine; public static void ShowPrompt() { if (!RuntimeEnabled) return; EnsureInstance(); if (instance != null) instance.ShowInternal(); } private static void EnsureInstance() { if (instance != null) return; GameObject host = SceneObjectLookupCache.Find("__UnimplementedFeaturePromptHost"); if (host == null) { host = new GameObject("__UnimplementedFeaturePromptHost"); DontDestroyOnLoad(host); } instance = host.GetComponent(); if (instance == null) instance = host.AddComponent(); } private void OnEnable() { SceneManager.sceneLoaded -= OnSceneLoaded; SceneManager.sceneLoaded += OnSceneLoaded; } private void OnDisable() { SceneManager.sceneLoaded -= OnSceneLoaded; } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { // Re-resolve references every scene so we can reuse existing UI if present. root = null; pressText = null; noChoice = null; choiceLessThanFive = null; image3 = null; continueButton = null; considerButton = null; doNotShowAgainButton = null; okayButton = null; } private void ShowInternal() { EnsurePromptRoot(); if (root == null) { Debug.LogWarning("[UnimplementedFeaturePrompt] Prompt root was not found and fallback creation failed."); return; } EnsureMinimumPromptElements(); BringRootToFront(); BindOkayButton(); root.SetActive(true); CanvasGroup rootGroup = root.GetComponent(); if (rootGroup != null) rootGroup.alpha = 1f; SetActiveSafe(noChoice, false); SetActiveSafe(choiceLessThanFive, false); SetActiveSafe(image3, false); SetButtonVisible(continueButton, false); SetButtonVisible(considerButton, false); SetButtonVisible(doNotShowAgainButton, false); SetButtonVisible(okayButton, true); SetActiveSafe(pressText, true); if (flashRoutine != null) StopCoroutine(flashRoutine); flashRoutine = StartCoroutine(FlashMessage()); } private IEnumerator FlashMessage() { GameObject target = pressText != null ? pressText : root; if (target == null) yield break; CanvasGroup cg = target.GetComponent(); if (cg == null) cg = target.AddComponent(); int count = Mathf.Max(1, flashCount); float onTime = Mathf.Clamp(flashOnTime, 0.01f, 0.05f); float offTime = Mathf.Clamp(flashOffTime, 0.01f, 0.05f); cg.alpha = 0f; for (int i = 0; i < count; i++) { cg.alpha = 1f; yield return new WaitForSecondsRealtime(onTime); if (i < count - 1) { cg.alpha = 0f; yield return new WaitForSecondsRealtime(offTime); } } cg.alpha = 1f; flashRoutine = null; } private void OnOkayClicked() { if (flashRoutine != null) { StopCoroutine(flashRoutine); flashRoutine = null; } if (root != null) { UI_PanelExitUtility.PlayExitThen(root, () => { if (root != null) root.SetActive(false); }); } } private void BindOkayButton() { if (okayButton == null) return; okayButton.onClick.RemoveListener(OnOkayClicked); okayButton.onClick.AddListener(OnOkayClicked); } private void EnsurePromptRoot() { Scene activeScene = SceneManager.GetActiveScene(); if (root != null && root.scene.IsValid() && root.scene == activeScene) return; root = FindSceneObjectByExactName("\uFF01mustselectyouridol"); if (root == null) root = FindSceneObjectByContainsName("mustselectyouridol"); if (root == null) root = CreateFallbackPrompt(); if (root == null) return; pressText = FindChildByName(root.transform, "Press an unimplemented feature"); if (pressText == null) pressText = FindChildByName(root.transform, "pressanunimplementedfeature"); noChoice = FindChildByName(root.transform, "No choice"); choiceLessThanFive = FindChildByName(root.transform, "choice < 5"); image3 = FindChildByName(root.transform, "Image (3)"); continueButton = FindButtonByName(root.transform, "Continue"); considerButton = FindButtonByName(root.transform, "Consider"); doNotShowAgainButton = FindButtonByName(root.transform, "Do not show again"); okayButton = FindButtonByName(root.transform, "okay"); if (okayButton == null) okayButton = FindButtonByContainsName(root.transform, "ok"); } private GameObject CreateFallbackPrompt() { Canvas canvas = FindTopCanvasInActiveScene(); if (canvas == null) canvas = CreateFallbackCanvas(); if (canvas == null) return null; GameObject rootGo = new GameObject("\uFF01mustselectyouridol", typeof(RectTransform), typeof(CanvasGroup), typeof(Image)); rootGo.transform.SetParent(canvas.transform, false); RectTransform rootRt = rootGo.GetComponent(); rootRt.anchorMin = Vector2.zero; rootRt.anchorMax = Vector2.one; rootRt.offsetMin = Vector2.zero; rootRt.offsetMax = Vector2.zero; Image bg = rootGo.GetComponent(); bg.color = new Color(0f, 0f, 0f, 0.35f); GameObject textGo = new GameObject("Press an unimplemented feature", typeof(RectTransform), typeof(Text)); textGo.transform.SetParent(rootGo.transform, false); RectTransform textRt = textGo.GetComponent(); textRt.anchorMin = new Vector2(0.5f, 0.5f); textRt.anchorMax = new Vector2(0.5f, 0.5f); textRt.sizeDelta = new Vector2(820f, 80f); textRt.anchoredPosition = new Vector2(0f, 40f); Text t = textGo.GetComponent(); t.font = Resources.GetBuiltinResource("LegacyRuntime.ttf"); t.fontSize = 40; t.alignment = TextAnchor.MiddleCenter; t.color = Color.white; t.text = "Press an unimplemented feature"; GameObject okayGo = new GameObject("okay", typeof(RectTransform), typeof(Image), typeof(Button)); okayGo.transform.SetParent(rootGo.transform, false); RectTransform okayRt = okayGo.GetComponent(); okayRt.anchorMin = new Vector2(0.5f, 0.5f); okayRt.anchorMax = new Vector2(0.5f, 0.5f); okayRt.sizeDelta = new Vector2(200f, 60f); okayRt.anchoredPosition = new Vector2(0f, -40f); Image okBg = okayGo.GetComponent(); okBg.color = Color.white; GameObject okayTextGo = new GameObject("Text (Legacy)", typeof(RectTransform), typeof(Text)); okayTextGo.transform.SetParent(okayGo.transform, false); RectTransform okayTextRt = okayTextGo.GetComponent(); okayTextRt.anchorMin = Vector2.zero; okayTextRt.anchorMax = Vector2.one; okayTextRt.offsetMin = Vector2.zero; okayTextRt.offsetMax = Vector2.zero; Text okText = okayTextGo.GetComponent(); okText.font = Resources.GetBuiltinResource("LegacyRuntime.ttf"); okText.fontSize = 30; okText.alignment = TextAnchor.MiddleCenter; okText.color = new Color(0.23f, 0.23f, 0.23f, 1f); okText.text = "okay"; return rootGo; } private static void SetButtonVisible(Button button, bool visible) { if (button != null) button.gameObject.SetActive(visible); } private static void SetActiveSafe(GameObject go, bool active) { if (go != null) go.SetActive(active); } private static GameObject FindSceneObjectByExactName(string objectName) { if (string.IsNullOrEmpty(objectName)) return null; Scene scene = SceneManager.GetActiveScene(); Transform[] all = UnityEngine.Object.FindObjectsByType(FindObjectsInactive.Include, FindObjectsSortMode.None); for (int i = 0; i < all.Length; i++) { Transform t = all[i]; if (t == null || t.gameObject.scene != scene) continue; if (string.Equals(t.name, objectName, System.StringComparison.OrdinalIgnoreCase)) return t.gameObject; } return null; } private static GameObject FindSceneObjectByContainsName(string token) { if (string.IsNullOrEmpty(token)) return null; Scene scene = SceneManager.GetActiveScene(); Transform[] all = UnityEngine.Object.FindObjectsByType(FindObjectsInactive.Include, FindObjectsSortMode.None); for (int i = 0; i < all.Length; i++) { Transform t = all[i]; if (t == null || t.gameObject.scene != scene) continue; if (t.name.IndexOf(token, System.StringComparison.OrdinalIgnoreCase) >= 0) return t.gameObject; } return null; } private static GameObject FindChildByName(Transform root, string childName) { if (root == null || string.IsNullOrEmpty(childName)) return null; Transform[] children = root.GetComponentsInChildren(true); for (int i = 0; i < children.Length; i++) { Transform c = children[i]; if (c != null && string.Equals(c.name, childName, System.StringComparison.OrdinalIgnoreCase)) return c.gameObject; } return null; } private static Button FindButtonByName(Transform root, string buttonName) { if (root == null || string.IsNullOrEmpty(buttonName)) return null; Button[] buttons = root.GetComponentsInChildren