269 lines
7.6 KiB
C#
269 lines
7.6 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using Definition.Enum;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using UnityGameFramework.Runtime;
|
|
|
|
namespace UI
|
|
{
|
|
public class MainOverlayForm : UGuiForm
|
|
{
|
|
[SerializeField] private Image _cueImage;
|
|
[SerializeField] private List<Sprite> _cueBindings = new List<Sprite>();
|
|
[SerializeField] private float _showDuration = 0.2f;
|
|
[SerializeField] private float _hideDuration = 0.2f;
|
|
|
|
private static int _dispatchCount;
|
|
private Coroutine _transitionCoroutine;
|
|
private bool _isClosingByCue;
|
|
private Vector3 _baseScale = Vector3.one;
|
|
private bool _baseScaleInitialized;
|
|
|
|
public static void DispatchCue(EmphasisType emphasis)
|
|
{
|
|
if (GameEntry.UI == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
UGuiForm existingForm = GameEntry.UI.GetUIForm(UIFormId.MainOverlayForm);
|
|
if (emphasis == EmphasisType.EntityCueClose)
|
|
{
|
|
if (existingForm is MainOverlayForm overlay)
|
|
{
|
|
overlay.PlayHideAndClose();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (emphasis != EmphasisType.EntityCue)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (existingForm is MainOverlayForm overlayForm)
|
|
{
|
|
overlayForm.ShowNextCue();
|
|
return;
|
|
}
|
|
|
|
int? formSerialId = GameEntry.UI.OpenUIForm(UIFormId.MainOverlayForm);
|
|
if (!formSerialId.HasValue)
|
|
{
|
|
Log.Warning("MainOverlayForm open failed. Check UIForm.txt config and prefab asset.");
|
|
}
|
|
}
|
|
|
|
protected override void OnOpen(object userData)
|
|
{
|
|
base.OnOpen(userData);
|
|
EnsureBaseScaleInitialized();
|
|
ShowNextCue();
|
|
}
|
|
|
|
protected override void OnClose(bool isShutdown, object userData)
|
|
{
|
|
StopTransition();
|
|
HideCueImage(clearSprite: true);
|
|
base.OnClose(isShutdown, userData);
|
|
}
|
|
|
|
private void ShowNextCue()
|
|
{
|
|
if (_cueImage == null)
|
|
{
|
|
Log.Warning("MainOverlayForm cue image is missing.");
|
|
return;
|
|
}
|
|
|
|
if (_cueBindings == null || _cueBindings.Count == 0)
|
|
{
|
|
HideCueImage(clearSprite: false);
|
|
Log.Warning("MainOverlayForm cue bindings are empty.");
|
|
return;
|
|
}
|
|
|
|
int index = _dispatchCount % _cueBindings.Count;
|
|
_dispatchCount++;
|
|
|
|
Sprite sprite = _cueBindings[index];
|
|
if (sprite == null)
|
|
{
|
|
HideCueImage(clearSprite: false);
|
|
return;
|
|
}
|
|
|
|
EnsureBaseScaleInitialized();
|
|
StopTransition();
|
|
_transitionCoroutine = StartCoroutine(PlayShowRoutine(sprite));
|
|
}
|
|
|
|
private void PlayHideAndClose()
|
|
{
|
|
if (_isClosingByCue)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (_cueImage == null)
|
|
{
|
|
if (GameEntry.UI != null && UIForm != null)
|
|
{
|
|
GameEntry.UI.CloseUIForm(UIForm);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
StopTransition();
|
|
_transitionCoroutine = StartCoroutine(PlayHideAndCloseRoutine());
|
|
}
|
|
|
|
private IEnumerator PlayShowRoutine(Sprite sprite)
|
|
{
|
|
_cueImage.sprite = sprite;
|
|
_cueImage.SetNativeSize();
|
|
_cueImage.gameObject.SetActive(true);
|
|
|
|
SetCueVisual(0f, 0f);
|
|
yield return PlayLerp(0f, 1f, 0f, 0.6f, _showDuration);
|
|
_transitionCoroutine = null;
|
|
}
|
|
|
|
private IEnumerator PlayHideAndCloseRoutine()
|
|
{
|
|
_isClosingByCue = true;
|
|
float fromAlpha = _cueImage.color.a;
|
|
float fromScale = GetCurrentScale01();
|
|
yield return PlayLerp(fromAlpha, 0f, fromScale, 0f, _hideDuration);
|
|
HideCueImage(clearSprite: true);
|
|
_isClosingByCue = false;
|
|
_transitionCoroutine = null;
|
|
|
|
if (GameEntry.UI != null && UIForm != null)
|
|
{
|
|
GameEntry.UI.CloseUIForm(UIForm);
|
|
}
|
|
}
|
|
|
|
private IEnumerator PlayLerp(float fromAlpha, float toAlpha, float fromScale, float toScale, float duration)
|
|
{
|
|
if (_cueImage == null)
|
|
{
|
|
yield break;
|
|
}
|
|
|
|
float safeDuration = Mathf.Max(0f, duration);
|
|
if (safeDuration <= 0f)
|
|
{
|
|
SetCueVisual(toAlpha, toScale);
|
|
yield break;
|
|
}
|
|
|
|
float elapsed = 0f;
|
|
while (elapsed < safeDuration)
|
|
{
|
|
elapsed += Time.unscaledDeltaTime;
|
|
float t = Mathf.Clamp01(elapsed / safeDuration);
|
|
float alpha = Mathf.Lerp(fromAlpha, toAlpha, t);
|
|
float scale = Mathf.Lerp(fromScale, toScale, t);
|
|
SetCueVisual(alpha, scale);
|
|
yield return null;
|
|
}
|
|
|
|
SetCueVisual(toAlpha, toScale);
|
|
}
|
|
|
|
private void SetCueVisual(float alpha, float scale01)
|
|
{
|
|
if (_cueImage == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Color color = _cueImage.color;
|
|
color.a = Mathf.Clamp01(alpha);
|
|
_cueImage.color = color;
|
|
|
|
RectTransform rectTransform = _cueImage.rectTransform;
|
|
if (rectTransform == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
float safeScale = Mathf.Clamp01(scale01);
|
|
rectTransform.localScale = _baseScale * safeScale;
|
|
}
|
|
|
|
private float GetCurrentScale01()
|
|
{
|
|
if (_cueImage == null)
|
|
{
|
|
return 1f;
|
|
}
|
|
|
|
EnsureBaseScaleInitialized();
|
|
RectTransform rectTransform = _cueImage.rectTransform;
|
|
if (rectTransform == null)
|
|
{
|
|
return 1f;
|
|
}
|
|
|
|
float ratioX = Mathf.Abs(_baseScale.x) > 0.0001f ? rectTransform.localScale.x / _baseScale.x : 1f;
|
|
float ratioY = Mathf.Abs(_baseScale.y) > 0.0001f ? rectTransform.localScale.y / _baseScale.y : 1f;
|
|
return Mathf.Clamp01((ratioX + ratioY) * 0.5f);
|
|
}
|
|
|
|
private void EnsureBaseScaleInitialized()
|
|
{
|
|
if (_baseScaleInitialized)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (_cueImage == null || _cueImage.rectTransform == null)
|
|
{
|
|
_baseScale = Vector3.one;
|
|
_baseScaleInitialized = true;
|
|
return;
|
|
}
|
|
|
|
_baseScale = _cueImage.rectTransform.localScale;
|
|
if (_baseScale == Vector3.zero)
|
|
{
|
|
_baseScale = Vector3.one;
|
|
}
|
|
|
|
_baseScaleInitialized = true;
|
|
}
|
|
|
|
private void StopTransition()
|
|
{
|
|
if (_transitionCoroutine != null)
|
|
{
|
|
StopCoroutine(_transitionCoroutine);
|
|
_transitionCoroutine = null;
|
|
}
|
|
|
|
_isClosingByCue = false;
|
|
}
|
|
|
|
private void HideCueImage(bool clearSprite)
|
|
{
|
|
if (_cueImage == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_cueImage.gameObject.SetActive(false);
|
|
SetCueVisual(0f, 0f);
|
|
if (clearSprite)
|
|
{
|
|
_cueImage.sprite = null;
|
|
}
|
|
}
|
|
}
|
|
}
|