UI update 02
This commit is contained in:
@@ -147,6 +147,7 @@ namespace Bansonic
|
||||
{
|
||||
if (currentInstance != null && currentController != null)
|
||||
{
|
||||
ReparentIfNeeded();
|
||||
if (!currentInstance.activeInHierarchy)
|
||||
{
|
||||
currentInstance.SetActive(true);
|
||||
@@ -169,6 +170,7 @@ namespace Bansonic
|
||||
|
||||
currentInstance.name = prefab.name;
|
||||
currentController = currentInstance.GetComponent<itemGetPrefab>();
|
||||
ReparentIfNeeded();
|
||||
}
|
||||
|
||||
private static Transform ResolveParent()
|
||||
@@ -184,6 +186,11 @@ namespace Bansonic
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsTransitionCanvas(canvas))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (best == null || canvas.sortingOrder >= best.sortingOrder)
|
||||
{
|
||||
best = canvas;
|
||||
@@ -193,6 +200,52 @@ namespace Bansonic
|
||||
return best != null ? best.transform : null;
|
||||
}
|
||||
|
||||
private static void ReparentIfNeeded()
|
||||
{
|
||||
if (currentInstance == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Transform currentParent = currentInstance.transform.parent;
|
||||
bool needsReparent = currentParent == null || HasTransitionAncestor(currentParent);
|
||||
if (!needsReparent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Transform targetParent = ResolveParent();
|
||||
if (targetParent == null || targetParent == currentParent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
currentInstance.transform.SetParent(targetParent, false);
|
||||
currentInstance.transform.SetAsLastSibling();
|
||||
}
|
||||
|
||||
private static bool IsTransitionCanvas(Canvas canvas)
|
||||
{
|
||||
return canvas != null && HasTransitionAncestor(canvas.transform);
|
||||
}
|
||||
|
||||
private static bool HasTransitionAncestor(Transform transform)
|
||||
{
|
||||
Transform current = transform;
|
||||
while (current != null)
|
||||
{
|
||||
if (current.GetComponent<gTransBlack>() != null ||
|
||||
current.GetComponent<BansonicSceneTransitionOverlay>() != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
current = current.parent;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Color ResolveRarityColor(ItemRarity rarity)
|
||||
{
|
||||
ItemRarityColorConfigSO rarityConfig = GetRarityConfig();
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Bansonic
|
||||
/// </summary>
|
||||
public static class gNotice
|
||||
{
|
||||
// --- 事件定义:用于通知 UI 层 ---
|
||||
// 用于通知 UI 层
|
||||
/// <summary>
|
||||
/// 当任何通知被显示时触发
|
||||
/// 参数1:类型前缀(如 [Info])
|
||||
|
||||
@@ -0,0 +1,506 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using DG.Tweening;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Bansonic
|
||||
{
|
||||
public static class gTransition
|
||||
{
|
||||
private const string PrefabResourcePath = "gTransitionPrefab";
|
||||
|
||||
public static bool IsBusy
|
||||
{
|
||||
get
|
||||
{
|
||||
BansonicSceneTransitionOverlay instance = BansonicSceneTransitionOverlay.EnsureInstance(PrefabResourcePath);
|
||||
return instance != null && instance.IsBusy;
|
||||
}
|
||||
}
|
||||
|
||||
public static void FadeOut(float duration = 0.25f)
|
||||
{
|
||||
BansonicSceneTransitionOverlay instance = BansonicSceneTransitionOverlay.EnsureInstance(PrefabResourcePath);
|
||||
if (instance == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
instance.FadeOut(duration);
|
||||
}
|
||||
|
||||
public static void FadeIn(float duration = 0.25f)
|
||||
{
|
||||
BansonicSceneTransitionOverlay instance = BansonicSceneTransitionOverlay.EnsureInstance(PrefabResourcePath);
|
||||
if (instance == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
instance.FadeIn(duration);
|
||||
}
|
||||
|
||||
public static bool LoadScene(
|
||||
string sceneName,
|
||||
LoadSceneMode mode = LoadSceneMode.Single,
|
||||
float fadeOutDuration = 0.25f,
|
||||
float fadeInDuration = 0.25f,
|
||||
float holdBlackDuration = 0f,
|
||||
Action onComplete = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(sceneName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BansonicSceneTransitionOverlay instance = BansonicSceneTransitionOverlay.EnsureInstance(PrefabResourcePath);
|
||||
if (instance == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return instance.BeginLoadScene(sceneName, mode, fadeOutDuration, fadeInDuration, holdBlackDuration, onComplete);
|
||||
}
|
||||
|
||||
public static bool ReloadCurrentScene(
|
||||
float fadeOutDuration = 0.25f,
|
||||
float fadeInDuration = 0.25f,
|
||||
float holdBlackDuration = 0f,
|
||||
Action onComplete = null)
|
||||
{
|
||||
Scene activeScene = SceneManager.GetActiveScene();
|
||||
if (!activeScene.IsValid() || string.IsNullOrWhiteSpace(activeScene.name))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return LoadScene(activeScene.name, LoadSceneMode.Single, fadeOutDuration, fadeInDuration, holdBlackDuration, onComplete);
|
||||
}
|
||||
|
||||
public static bool Run(
|
||||
IEnumerator routine,
|
||||
float fadeOutDuration = 0.25f,
|
||||
float fadeInDuration = 0.25f,
|
||||
float holdBlackDuration = 0f,
|
||||
Action onComplete = null)
|
||||
{
|
||||
if (routine == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BansonicSceneTransitionOverlay instance = BansonicSceneTransitionOverlay.EnsureInstance(PrefabResourcePath);
|
||||
if (instance == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return instance.BeginWrappedRoutine(routine, fadeOutDuration, fadeInDuration, holdBlackDuration, onComplete);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class BansonicSceneTransitionOverlay : MonoBehaviour
|
||||
{
|
||||
private const string RuntimeObjectName = "BansonicSceneTransitionOverlay_Runtime";
|
||||
|
||||
[SerializeField] private gTransBlack transitionBlack;
|
||||
[SerializeField] private CanvasGroup canvasGroup;
|
||||
[SerializeField] private Image blackoutImage;
|
||||
|
||||
private Tween currentTween;
|
||||
private Coroutine transitionRoutine;
|
||||
|
||||
public bool IsBusy
|
||||
{
|
||||
get { return transitionRoutine != null; }
|
||||
}
|
||||
|
||||
public static BansonicSceneTransitionOverlay EnsureInstance(string prefabResourcePath)
|
||||
{
|
||||
BansonicSceneTransitionOverlay existing = FindExisting();
|
||||
if (existing != null)
|
||||
{
|
||||
existing.EnsureSetup();
|
||||
return existing;
|
||||
}
|
||||
|
||||
GameObject prefab = Resources.Load<GameObject>(prefabResourcePath);
|
||||
if (prefab != null)
|
||||
{
|
||||
GameObject prefabInstance = Object.Instantiate(prefab);
|
||||
prefabInstance.name = prefab.name;
|
||||
Object.DontDestroyOnLoad(prefabInstance);
|
||||
BansonicSceneTransitionOverlay overlayFromPrefab = prefabInstance.GetComponent<BansonicSceneTransitionOverlay>();
|
||||
if (overlayFromPrefab == null)
|
||||
{
|
||||
overlayFromPrefab = prefabInstance.AddComponent<BansonicSceneTransitionOverlay>();
|
||||
}
|
||||
if (overlayFromPrefab != null)
|
||||
{
|
||||
overlayFromPrefab.EnsureSetup();
|
||||
}
|
||||
return overlayFromPrefab;
|
||||
}
|
||||
|
||||
return CreateRuntimeInstance();
|
||||
}
|
||||
|
||||
public void FadeOut(float duration)
|
||||
{
|
||||
EnsureSetup();
|
||||
StartSingleTransition(true, duration);
|
||||
}
|
||||
|
||||
public void FadeIn(float duration)
|
||||
{
|
||||
EnsureSetup();
|
||||
StartSingleTransition(false, duration);
|
||||
}
|
||||
|
||||
public bool BeginLoadScene(
|
||||
string sceneName,
|
||||
LoadSceneMode mode,
|
||||
float fadeOutDuration,
|
||||
float fadeInDuration,
|
||||
float holdBlackDuration,
|
||||
Action onComplete)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(sceneName) || IsBusy)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
transitionRoutine = StartCoroutine(LoadSceneRoutine(sceneName, mode, fadeOutDuration, fadeInDuration, holdBlackDuration, onComplete));
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool BeginWrappedRoutine(
|
||||
IEnumerator routine,
|
||||
float fadeOutDuration,
|
||||
float fadeInDuration,
|
||||
float holdBlackDuration,
|
||||
Action onComplete)
|
||||
{
|
||||
if (routine == null || IsBusy)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
transitionRoutine = StartCoroutine(WrappedRoutine(routine, fadeOutDuration, fadeInDuration, holdBlackDuration, onComplete));
|
||||
return true;
|
||||
}
|
||||
|
||||
private static BansonicSceneTransitionOverlay FindExisting()
|
||||
{
|
||||
BansonicSceneTransitionOverlay[] all = FindObjectsByType<BansonicSceneTransitionOverlay>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
||||
return all != null && all.Length > 0 ? all[0] : null;
|
||||
}
|
||||
|
||||
private static BansonicSceneTransitionOverlay CreateRuntimeInstance()
|
||||
{
|
||||
GameObject root = new GameObject(
|
||||
RuntimeObjectName,
|
||||
typeof(RectTransform),
|
||||
typeof(Canvas),
|
||||
typeof(CanvasScaler),
|
||||
typeof(GraphicRaycaster),
|
||||
typeof(CanvasGroup),
|
||||
typeof(Image),
|
||||
typeof(BansonicSceneTransitionOverlay));
|
||||
|
||||
RectTransform rect = root.GetComponent<RectTransform>();
|
||||
rect.anchorMin = Vector2.zero;
|
||||
rect.anchorMax = Vector2.one;
|
||||
rect.offsetMin = Vector2.zero;
|
||||
rect.offsetMax = Vector2.zero;
|
||||
rect.pivot = new Vector2(0.5f, 0.5f);
|
||||
|
||||
Canvas canvas = root.GetComponent<Canvas>();
|
||||
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||
canvas.sortingOrder = short.MaxValue;
|
||||
canvas.pixelPerfect = false;
|
||||
|
||||
CanvasScaler scaler = root.GetComponent<CanvasScaler>();
|
||||
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
||||
scaler.referenceResolution = new Vector2(1920f, 1080f);
|
||||
scaler.matchWidthOrHeight = 0.5f;
|
||||
|
||||
Image image = root.GetComponent<Image>();
|
||||
image.color = Color.black;
|
||||
image.raycastTarget = true;
|
||||
|
||||
CanvasGroup group = root.GetComponent<CanvasGroup>();
|
||||
group.alpha = 0f;
|
||||
group.interactable = false;
|
||||
group.blocksRaycasts = false;
|
||||
|
||||
Object.DontDestroyOnLoad(root);
|
||||
|
||||
BansonicSceneTransitionOverlay overlay = root.GetComponent<BansonicSceneTransitionOverlay>();
|
||||
overlay.canvasGroup = group;
|
||||
overlay.blackoutImage = image;
|
||||
overlay.EnsureSetup();
|
||||
return overlay;
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
EnsureSetup();
|
||||
Object.DontDestroyOnLoad(gameObject);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
KillTween();
|
||||
}
|
||||
|
||||
private void EnsureSetup()
|
||||
{
|
||||
if (transitionBlack == null)
|
||||
{
|
||||
transitionBlack = GetComponent<gTransBlack>();
|
||||
if (transitionBlack == null)
|
||||
{
|
||||
transitionBlack = GetComponentInChildren<gTransBlack>(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (canvasGroup == null)
|
||||
{
|
||||
if (transitionBlack != null && transitionBlack.CanvasGroup != null)
|
||||
{
|
||||
canvasGroup = transitionBlack.CanvasGroup;
|
||||
}
|
||||
else
|
||||
{
|
||||
canvasGroup = GetComponent<CanvasGroup>();
|
||||
if (canvasGroup == null)
|
||||
{
|
||||
canvasGroup = GetComponentInChildren<CanvasGroup>(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (blackoutImage == null)
|
||||
{
|
||||
blackoutImage = GetComponent<Image>();
|
||||
if (blackoutImage == null)
|
||||
{
|
||||
blackoutImage = GetComponentInChildren<Image>(true);
|
||||
}
|
||||
}
|
||||
|
||||
Canvas canvas = transitionBlack != null && transitionBlack.Canvas != null
|
||||
? transitionBlack.Canvas
|
||||
: GetComponentInChildren<Canvas>(true);
|
||||
if (canvas != null)
|
||||
{
|
||||
if (canvas.renderMode == RenderMode.ScreenSpaceOverlay)
|
||||
{
|
||||
canvas.sortingOrder = short.MaxValue;
|
||||
}
|
||||
}
|
||||
|
||||
if (transitionBlack != null)
|
||||
{
|
||||
transitionBlack.RefreshCanvasCamera();
|
||||
}
|
||||
|
||||
if (blackoutImage != null)
|
||||
{
|
||||
blackoutImage.color = Color.black;
|
||||
blackoutImage.raycastTarget = true;
|
||||
}
|
||||
|
||||
if (canvasGroup != null)
|
||||
{
|
||||
canvasGroup.alpha = Mathf.Clamp01(canvasGroup.alpha);
|
||||
if (!IsBusy)
|
||||
{
|
||||
canvasGroup.alpha = 0f;
|
||||
}
|
||||
|
||||
if (canvasGroup.alpha <= 0f)
|
||||
{
|
||||
canvasGroup.interactable = false;
|
||||
canvasGroup.blocksRaycasts = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void StartSingleTransition(bool fadeToBlack, float duration)
|
||||
{
|
||||
if (transitionRoutine != null)
|
||||
{
|
||||
StopCoroutine(transitionRoutine);
|
||||
transitionRoutine = null;
|
||||
}
|
||||
|
||||
KillTween();
|
||||
EnsureSetup();
|
||||
gameObject.SetActive(true);
|
||||
|
||||
if (canvasGroup == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float safeDuration = Mathf.Max(0f, duration);
|
||||
float targetAlpha = fadeToBlack ? 1f : 0f;
|
||||
|
||||
if (fadeToBlack)
|
||||
{
|
||||
canvasGroup.interactable = true;
|
||||
canvasGroup.blocksRaycasts = true;
|
||||
}
|
||||
|
||||
if (safeDuration <= 0f)
|
||||
{
|
||||
canvasGroup.alpha = targetAlpha;
|
||||
if (!fadeToBlack)
|
||||
{
|
||||
canvasGroup.interactable = false;
|
||||
canvasGroup.blocksRaycasts = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
currentTween = canvasGroup.DOFade(targetAlpha, safeDuration)
|
||||
.SetEase(Ease.Linear)
|
||||
.SetUpdate(true)
|
||||
.OnComplete(() =>
|
||||
{
|
||||
if (canvasGroup == null)
|
||||
{
|
||||
currentTween = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fadeToBlack)
|
||||
{
|
||||
canvasGroup.interactable = false;
|
||||
canvasGroup.blocksRaycasts = false;
|
||||
}
|
||||
|
||||
currentTween = null;
|
||||
});
|
||||
}
|
||||
|
||||
private IEnumerator LoadSceneRoutine(
|
||||
string sceneName,
|
||||
LoadSceneMode mode,
|
||||
float fadeOutDuration,
|
||||
float fadeInDuration,
|
||||
float holdBlackDuration,
|
||||
Action onComplete)
|
||||
{
|
||||
yield return WrappedRoutine(LoadSceneOperation(sceneName, mode), fadeOutDuration, fadeInDuration, holdBlackDuration, onComplete);
|
||||
transitionRoutine = null;
|
||||
}
|
||||
|
||||
private IEnumerator WrappedRoutine(
|
||||
IEnumerator routine,
|
||||
float fadeOutDuration,
|
||||
float fadeInDuration,
|
||||
float holdBlackDuration,
|
||||
Action onComplete)
|
||||
{
|
||||
EnsureSetup();
|
||||
yield return FadeRoutine(1f, Mathf.Max(0f, fadeOutDuration), true);
|
||||
|
||||
if (holdBlackDuration > 0f)
|
||||
{
|
||||
yield return new WaitForSecondsRealtime(holdBlackDuration);
|
||||
}
|
||||
|
||||
while (routine != null && routine.MoveNext())
|
||||
{
|
||||
yield return routine.Current;
|
||||
}
|
||||
|
||||
yield return null;
|
||||
yield return null;
|
||||
|
||||
if (transitionBlack != null)
|
||||
{
|
||||
transitionBlack.RefreshCanvasCamera();
|
||||
}
|
||||
|
||||
Canvas.ForceUpdateCanvases();
|
||||
|
||||
yield return FadeRoutine(0f, Mathf.Max(0f, fadeInDuration), false);
|
||||
|
||||
onComplete?.Invoke();
|
||||
transitionRoutine = null;
|
||||
}
|
||||
|
||||
private IEnumerator LoadSceneOperation(string sceneName, LoadSceneMode mode)
|
||||
{
|
||||
AsyncOperation operation = SceneManager.LoadSceneAsync(sceneName, mode);
|
||||
while (operation != null && !operation.isDone)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator FadeRoutine(float targetAlpha, float duration, bool blocking)
|
||||
{
|
||||
EnsureSetup();
|
||||
gameObject.SetActive(true);
|
||||
|
||||
if (canvasGroup == null)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
KillTween();
|
||||
|
||||
canvasGroup.interactable = blocking;
|
||||
canvasGroup.blocksRaycasts = blocking;
|
||||
|
||||
if (duration <= 0f)
|
||||
{
|
||||
canvasGroup.alpha = targetAlpha;
|
||||
if (!blocking)
|
||||
{
|
||||
canvasGroup.interactable = false;
|
||||
canvasGroup.blocksRaycasts = false;
|
||||
}
|
||||
yield break;
|
||||
}
|
||||
|
||||
bool completed = false;
|
||||
currentTween = canvasGroup.DOFade(targetAlpha, duration)
|
||||
.SetEase(Ease.Linear)
|
||||
.SetUpdate(true)
|
||||
.OnComplete(() =>
|
||||
{
|
||||
completed = true;
|
||||
currentTween = null;
|
||||
if (canvasGroup != null && !blocking)
|
||||
{
|
||||
canvasGroup.interactable = false;
|
||||
canvasGroup.blocksRaycasts = false;
|
||||
}
|
||||
});
|
||||
|
||||
while (!completed)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void KillTween()
|
||||
{
|
||||
if (currentTween != null && currentTween.IsActive())
|
||||
{
|
||||
currentTween.Kill(false);
|
||||
}
|
||||
|
||||
currentTween = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e56a534c01b33c64b980d8eb1fcb816c
|
||||
Reference in New Issue
Block a user