302 lines
9.9 KiB
C#
302 lines
9.9 KiB
C#
using System;
|
|
using System.Collections;
|
|
using AibisDream.Framework;
|
|
using AibisDream.Kit;
|
|
using DG.Tweening;
|
|
using RainbowArt.CleanFlatUI;
|
|
using UnityEngine;
|
|
using UnityEngine.ResourceManagement.AsyncOperations;
|
|
using UnityEngine.UI;
|
|
|
|
namespace AibisDream.UI
|
|
{
|
|
/// <summary>
|
|
/// 主要用来放置淡入淡出,图片展示等演出工具
|
|
/// </summary>
|
|
public class PlayToolPanel : MonoBehaviour, IUIPanel
|
|
{
|
|
public bool IsOpen => gameObject.activeSelf;
|
|
public bool IsCloseable => false;
|
|
|
|
[Header("Obj尺寸参数")] public float objWidth;
|
|
public float objHeight;
|
|
|
|
/// <summary>Addressable Key 模板,与 Obj 精灵 Address 一致。</summary>
|
|
private const string ObjSpritePath = "Sprite/Obj/{0}.png";
|
|
|
|
#region 索引
|
|
|
|
private Image _fadeImage;
|
|
private GameObject _showObjPanel;
|
|
private Image _showObjImage;
|
|
private Image _fullScreenImage;
|
|
private Image _redFlash;
|
|
private ModalWindowProgressBar _window;
|
|
private ModalWindow _warningWindow;
|
|
private SignBoard _signBoard;
|
|
private TimeTurner _timeTurner;
|
|
private int _timeFlowsVersion;
|
|
|
|
#endregion
|
|
|
|
private void Awake()
|
|
{
|
|
InitRefs();
|
|
}
|
|
|
|
private void InitRefs()
|
|
{
|
|
_fadeImage = transform.Find("Fade Image").GetComponent<Image>();
|
|
_showObjPanel = transform.Find("Show Obj").gameObject;
|
|
_showObjImage = _showObjPanel.transform.Find("Obj").GetComponent<Image>();
|
|
_fullScreenImage = transform.Find("Full Screen Image").GetComponent<Image>();
|
|
_window = transform.Find("进度条窗口").GetComponent<ModalWindowProgressBar>();
|
|
_redFlash = transform.Find("Red Flash").GetComponent<Image>();
|
|
_warningWindow = transform.Find("警告窗口").GetComponent<ModalWindow>();
|
|
_signBoard = transform.GetComponentInChildren<SignBoard>();
|
|
_timeTurner = transform.GetComponentInChildren<TimeTurner>();
|
|
}
|
|
|
|
private static string NormalizeObjPicName(string picName)
|
|
{
|
|
if (string.IsNullOrEmpty(picName)) return picName;
|
|
return picName.EndsWith(".png", StringComparison.OrdinalIgnoreCase)
|
|
? picName.Substring(0, picName.Length - 4)
|
|
: picName;
|
|
}
|
|
|
|
public IEnumerator FadeInAsync(float duration = 1)
|
|
{
|
|
return _fadeImage.FadeInAsync(duration);
|
|
}
|
|
|
|
public IEnumerator FadeOutAsync(float duration = 1)
|
|
{
|
|
return _fadeImage.FadeOutAsync(duration);
|
|
}
|
|
|
|
public void FadeInSync(float duration = 1)
|
|
{
|
|
StartCoroutine(FadeInAsync(duration));
|
|
}
|
|
|
|
public void FadeOutSync(float duration = 1)
|
|
{
|
|
StartCoroutine(FadeOutAsync(duration));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 捕获遮罩终态:黑屏盖住(FadeIn 完成) vs 画面可见(FadeOut 完成 / HideAll)。
|
|
/// 与 <see cref="FadeKit"/> 一致——终态以 <c>gameObject.activeSelf</c> 为准(FadeOut 结束会 SetActive(false))。
|
|
/// </summary>
|
|
public bool CaptureFadeScreenCovered()
|
|
{
|
|
if (_fadeImage == null) return false;
|
|
return _fadeImage.gameObject.activeSelf;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 按快照终态还原遮罩(同步设置 active 与颜色,与 <see cref="FadeKit"/> 终态一致)。
|
|
/// </summary>
|
|
public void ApplyFadeScreenCovered(bool isCovered)
|
|
{
|
|
if (_fadeImage == null) return;
|
|
|
|
_fadeImage.DOKill();
|
|
if (isCovered)
|
|
{
|
|
_fadeImage.gameObject.SetActive(true);
|
|
_fadeImage.color = Color.white;
|
|
}
|
|
else
|
|
{
|
|
_fadeImage.color = Color.clear;
|
|
_fadeImage.gameObject.SetActive(false);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 显示物体
|
|
/// </summary>
|
|
/// <returns>协程</returns>
|
|
public IEnumerator ShowObj(string picName, float duration = 1)
|
|
{
|
|
_showObjPanel.gameObject.SetActive(true);
|
|
|
|
var key = string.Format(ObjSpritePath, NormalizeObjPicName(picName));
|
|
var handle = ResourceSystem.LoadAsync<Sprite>(key);
|
|
yield return handle;
|
|
if (handle.Status != AsyncOperationStatus.Succeeded || handle.Result == null)
|
|
{
|
|
Debug.LogError($"[PlayToolPanel] Failed to load sprite: {key}");
|
|
yield break;
|
|
}
|
|
|
|
var newSprite = handle.Result;
|
|
// 获取图片的长宽比
|
|
var imageAspect = (float)newSprite.texture.width / newSprite.texture.height;
|
|
|
|
// 计算新的尺寸
|
|
if (imageAspect > 1) // 宽图
|
|
{
|
|
var newHeight = objWidth / imageAspect;
|
|
_showObjImage.rectTransform.sizeDelta = new Vector2(objWidth, newHeight);
|
|
}
|
|
else // 高图
|
|
{
|
|
var newWidth = objHeight * imageAspect;
|
|
_showObjImage.rectTransform.sizeDelta = new Vector2(newWidth, objHeight);
|
|
}
|
|
|
|
// 淡入
|
|
_showObjImage.sprite = newSprite;
|
|
yield return _showObjImage.FadeInAsync(duration);
|
|
}
|
|
|
|
public IEnumerator HideObj(float duration = 1)
|
|
{
|
|
yield return _showObjImage.FadeOutAsync(duration);
|
|
_showObjPanel.SetActive(false);
|
|
}
|
|
|
|
public IEnumerator ShowFullScreen(string picName, float duration = 1)
|
|
{
|
|
var key = string.Format(ObjSpritePath, NormalizeObjPicName(picName));
|
|
var handle = ResourceSystem.LoadAsync<Sprite>(key);
|
|
yield return handle;
|
|
if (handle.Status != AsyncOperationStatus.Succeeded || handle.Result == null)
|
|
{
|
|
Debug.LogError($"[PlayToolPanel] Failed to load sprite: {key}");
|
|
yield break;
|
|
}
|
|
|
|
_fullScreenImage.sprite = handle.Result;
|
|
|
|
// 淡入
|
|
yield return _fullScreenImage.FadeInAsync(duration);
|
|
}
|
|
|
|
public IEnumerator HideFullScreen(float duration = 1)
|
|
{
|
|
yield return _fullScreenImage.FadeOutAsync(duration);
|
|
}
|
|
|
|
public IEnumerator OpenProgressWindow(string title, string description, float duration)
|
|
{
|
|
AudioManager.Instance.PlaySfx("event:/Scriptal/Ui");
|
|
_window.TitleValue = title;
|
|
_window.DescriptionValue = description;
|
|
float currentProgress = 0;
|
|
|
|
DOTween.To(
|
|
() => currentProgress,
|
|
value =>
|
|
{
|
|
currentProgress = value;
|
|
_window.SetProgress(currentProgress); // 更新进度
|
|
},
|
|
100,
|
|
duration
|
|
);
|
|
|
|
_window.ShowModalWindow();
|
|
|
|
// 获取 moveText 的 RectTransform
|
|
RectTransform moveTextRect =
|
|
_window.transform.Find("View/mask/moveText")?.GetComponent<RectTransform>();
|
|
if (moveTextRect != null)
|
|
{
|
|
moveTextRect.DOAnchorPosY(0f, duration).SetEase(Ease.Linear);
|
|
}
|
|
|
|
// 等待用户确认
|
|
yield return new WaitUntil(() => currentProgress >= 100);
|
|
_window.HideModalWindow();
|
|
moveTextRect.DOAnchorPosY(1326f, 0.1f).SetEase(Ease.Linear);
|
|
}
|
|
|
|
// 红色闪烁效果
|
|
public IEnumerator FlashRed(float duration)
|
|
{
|
|
_redFlash.gameObject.SetActive(true);
|
|
yield return _redFlash.FadeInAsync(duration / 2);
|
|
yield return _redFlash.FadeOutAsync(duration / 2);
|
|
_redFlash.gameObject.SetActive(false);
|
|
}
|
|
|
|
public void ShowSignBoard()
|
|
{
|
|
_signBoard.ShowSignBoard();
|
|
}
|
|
|
|
public void EnableSignBoard()
|
|
{
|
|
_signBoard.EnableSignBoard();
|
|
}
|
|
|
|
public void CloseSignBoard()
|
|
{
|
|
_signBoard.CloseSignBoard();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 清理演出层内容,但不影响黑屏遮罩(用于返回主界面时在遮罩下重置状态)。
|
|
/// </summary>
|
|
public void ClearPresentationEffects()
|
|
{
|
|
_timeFlowsVersion++;
|
|
|
|
_fullScreenImage.FadeOut(0.1f);
|
|
_showObjImage.FadeOut(0.1f);
|
|
_showObjPanel.SetActive(false);
|
|
|
|
_timeTurner.ForceStop();
|
|
}
|
|
|
|
// ------------------------------- 时间流转 -------------------------------
|
|
public IEnumerator TimeFlowsOn(string originState, string targetState)
|
|
{
|
|
var version = ++_timeFlowsVersion;
|
|
|
|
// 黑屏淡入
|
|
yield return _fadeImage.FadeInAsync(0.5f);
|
|
if (version != _timeFlowsVersion) yield break;
|
|
|
|
// 时间流转
|
|
yield return _timeTurner.TurnTimeTo(originState, targetState);
|
|
if (version != _timeFlowsVersion) yield break;
|
|
|
|
// 黑屏淡出
|
|
yield return _fadeImage.FadeOutAsync(0.5f);
|
|
}
|
|
|
|
#region 感觉这个面板应该常驻
|
|
|
|
public void Show()
|
|
{
|
|
gameObject.SetActive(true);
|
|
}
|
|
|
|
public void Hide()
|
|
{
|
|
gameObject.SetActive(false);
|
|
}
|
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// 打开警告窗口
|
|
/// </summary>
|
|
/// <param name="description">警告描述文本</param>
|
|
/// <returns>等待玩家确认的协程</returns>
|
|
public IEnumerator OpenWarningWindow(string description)
|
|
{
|
|
AudioManager.Instance.PlaySfx("event:/Scriptal/Ui");
|
|
_warningWindow.DescriptionValue = description;
|
|
_warningWindow.ShowModalWindow();
|
|
|
|
// 等待玩家点击确认按钮
|
|
yield return new WaitUntil(() => !_warningWindow.gameObject.activeSelf);
|
|
}
|
|
}
|
|
} |