using System.Collections;
using UnityEngine;
using DG.Tweening;
using Yarn.Unity;
using AibisDream.Framework;
using AibisDream.Kit;
using UnityEngine.Rendering;
using UnityEngine.ResourceManagement.AsyncOperations;
namespace AibisDream.FixSystem
{
public class MemoryProcess : MonoBehaviour
{
private const string MemorySpritePath = "Sprite/Memory/{0}.png";
private const float FadeMaterialStartValue = -15f;
private const float DefaultFadeDuration = 1f;
private const float SearchStartDelay = 1f;
private const float ProjectorMoveDuration = 2f;
[SerializeField] private GameObject memoryView;
[SerializeField] private GameObject projector;
[SerializeField] private SpriteRenderer memoryFinishedSpriteRenderer; // 用于显示记忆处理结束的表现
[SerializeField] private SpriteRenderer memoryFinishedImageNoColor; // 用于显示记忆处理结束的表现
[SerializeField] private Volume mainEffect;
[SerializeField] private Volume memoryClarityVolume;
[SerializeField] private Volume memoryFrequencyVolume;
[SerializeField] private Volume memoryProcessVolume;
[SerializeField] private MemorySlider frequencySlider; // 频率调节滑动条
[SerializeField] private MemorySlider claritySlider; // 清晰度调节滑动条
[SerializeField] private CanvasGroup playBackground;
[SerializeField] private GameObject memoryGroup;
private bool isProcessing = false; // 新增变量来追踪是否正在处理记忆
private bool isPlayingFaderSound = false; // 追踪音效是否正在播放
private PunchTape _activePunchTape;
[SerializeField] private MemoryPunchTapeSlot punchTapeSlot;
[SerializeField] private Material fadeMaterial;
public void OpenMemoryView()
{
memoryGroup.SetActive(true);
memoryView.gameObject.SetActive(true);
}
public IEnumerator DropMemoryProjector()
{
DG.Tweening.Sequence zoomInSequence = DOTween.Sequence();
zoomInSequence.Append(projector.transform.DOLocalMoveY(-5, ProjectorMoveDuration).SetEase(Ease.OutElastic, 0.5f));
yield return zoomInSequence.WaitForCompletion();
}
public void PullMemoryProjector()
{
DG.Tweening.Sequence zoomOutSequence = DOTween.Sequence();
zoomOutSequence.Append(projector.transform.DOLocalMoveY(0, ProjectorMoveDuration).SetEase(Ease.OutElastic, 0.5f));
}
public void CloseMemoryView()
{
memoryView.gameObject.SetActive(false);
memoryGroup.SetActive(false);
}
public void OnEnter()
{
OpenMemoryView();
PrepareMemoryView();
}
public void OnShow()
{
Debug.Log("memoryView showed.");
PrepareMemoryView();
}
private void PrepareMemoryView()
{
EnsurePunchTapeSlotReference();
PunchTapeManager.Instance.OpenFavoritesPanel();
playBackground.gameObject.SetActive(false);
playBackground.alpha = 0;
}
public void OnExit()
{
// 停止拉条音频
if (isPlayingFaderSound)
{
AudioManager.Instance.StopSfx("event:/ActionFB/mem_fader");
isPlayingFaderSound = false;
}
PunchTapeManager.Instance.CloseFavoritesPanel();
CloseMemoryView();
// 离开视图时的逻辑
Debug.Log("MemoryView exited.");
if (frequencySlider != null)
{
frequencySlider.SetInteractable(false);
frequencySlider.LockSlider();
}
if (claritySlider != null)
{
claritySlider.SetInteractable(false);
claritySlider.LockSlider();
}
}
private void Awake()
{
InitSystem();
}
private void EnsurePunchTapeSlotReference()
{
if (punchTapeSlot != null) return;
punchTapeSlot = MemoryPunchTapeSlot.ActiveInstance;
if (punchTapeSlot == null)
{
Debug.LogWarning(
"[MemoryProcess] 未配置 MemoryPunchTapeSlot:请在 Inspector 将 punchTapeSlot 赋值为场景中的插槽,或确保存在 MemoryPunchTapeSlot。",
this);
}
}
private void InitSystem()
{
FixSystemCenter.SystemDic.Register(this);
if (memoryGroup != null)
memoryGroup.SetActive(false);
}
private void Start()
{
frequencySlider.OnFound += CheckAllFound;
claritySlider.OnFound += CheckAllFound;
Init();
}
private void CheckAllFound()
{
if (frequencySlider.IsFound && claritySlider.IsFound)
OnSearchComplete();
}
private float GetRandomNumber()
{
// 随机决定选择哪个区间
if (UnityEngine.Random.value < 0.5f) // 50% 概率选择第一个区间
{
return UnityEngine.Random.Range(0.5f, 2f);
}
else // 50% 概率选择第二个区间
{
return UnityEngine.Random.Range(4f, 5.5f);
}
}
private void OnSearchComplete()
{
Debug.Log("Memory search completed.");
frequencySlider.SetInteractable(false);
claritySlider.SetInteractable(false);
// 停止拉条音频
if (isPlayingFaderSound)
{
AudioManager.Instance.StopSfx("event:/ActionFB/mem_fader");
isPlayingFaderSound = false;
}
AudioManager.Instance.SetSfxParam("event:/Amb/amb_mem_tuning", "is_mem_tuning", 0);
StartCoroutine(PlayMemory());
}
public void TweenWeight(Volume postProcessingVolume, float targetWeight, float duration)
{
// 动态调整权重
DOTween.To(() => postProcessingVolume.weight, x => postProcessingVolume.weight = x, targetWeight, duration);
}
public void Init()
{
isProcessing = false;
// 停止拉条音频
if (isPlayingFaderSound)
{
AudioManager.Instance.StopSfx("event:/ActionFB/mem_fader");
isPlayingFaderSound = false;
}
if (frequencySlider != null)
frequencySlider.Init(memoryFrequencyVolume);
if (claritySlider != null)
claritySlider.Init(memoryClarityVolume);
ResetPresentationState();
}
///
/// 单条记忆播放结束后的复位:不调用 (避免再次锁条并触发打开 Timeline),
/// 仅禁用拖动;完整 仅在退出 时 执行。
///
private void ResetAfterMemoryFinished()
{
isProcessing = false;
if (isPlayingFaderSound)
{
AudioManager.Instance.StopSfx("event:/ActionFB/mem_fader");
isPlayingFaderSound = false;
}
if (frequencySlider != null)
frequencySlider.SetInteractable(false);
if (claritySlider != null)
claritySlider.SetInteractable(false);
ResetPresentationState();
}
private void ResetPresentationState()
{
if (fadeMaterial != null)
fadeMaterial.SetFloat("_DirectionalDistortionFade", FadeMaterialStartValue);
memoryFinishedSpriteRenderer.color = Color.black;
memoryProcessVolume.weight = 0;
_activePunchTape = null;
playBackground.gameObject.SetActive(false);
playBackground.alpha = 0;
}
[YarnCommand("MemoryFinished")]
public IEnumerator MemoryFinished()
{
yield return playBackground.DOFade(0f, DefaultFadeDuration).WaitForCompletion();
playBackground.gameObject.SetActive(false);
PunchTapeManager.Instance.OpenFavoritesPanel();
ResetAfterMemoryFinished();
EnsurePunchTapeSlotReference();
if (punchTapeSlot != null && punchTapeSlot.punchTape != null)
{
punchTapeSlot.punchTape.used = true;
punchTapeSlot.ReleaseSlot();
}
}
[YarnCommand("ColorFadeOut")]
public IEnumerator ColorFadeOut()
{
if (fadeMaterial == null) yield break;
fadeMaterial.SetFloat("_DirectionalDistortionFade", FadeMaterialStartValue);
Tween tween = fadeMaterial.DOFloat(0, "_DirectionalDistortionFade", 3);
yield return tween.WaitForCompletion();
}
[YarnCommand("PlayMemory")]
public IEnumerator PlayMemory(bool useYarn = false, string memName = "")
{
memoryFinishedSpriteRenderer.color = Color.white;
PunchTapeManager.Instance.CloseFavoritesPanel();
if (useYarn)
{
if (fadeMaterial != null)
fadeMaterial.SetFloat("_DirectionalDistortionFade", FadeMaterialStartValue);
var memoryKey = string.Format(MemorySpritePath, memName);
var memoryHandle = ResourceSystem.LoadAsync(memoryKey);
yield return memoryHandle;
Sprite memSprite = memoryHandle.Status == AsyncOperationStatus.Succeeded ? memoryHandle.Result : null;
memoryFinishedSpriteRenderer.sprite = memSprite;
memoryFinishedImageNoColor.sprite = memSprite;
if (memSprite == null)
{
Debug.LogError("Memory not found: " + memoryKey);
}
}
else
{
EnsurePunchTapeSlotReference();
if (punchTapeSlot == null || punchTapeSlot.punchTape == null)
{
Debug.LogError("[MemoryProcess] PlayMemory:未配置插槽或打孔带数据缺失。", this);
yield break;
}
}
playBackground.gameObject.SetActive(true);
playBackground.alpha = 0;
AudioManager.Instance.PlaySfx("event:/ActionFB/mem_play");
yield return playBackground.DOFade(1f, DefaultFadeDuration).WaitForCompletion();
if (!useYarn)
{
DialogController.Instance.StartDialogNode(
LocalizationKit.GetL10NParamKey(punchTapeSlot.punchTape.ClueName));
}
}
public IEnumerator SearchMemory(PunchTape punchTape, bool isSkipDialogue = false)
{
if (isPlayingFaderSound)
{
AudioManager.Instance.StopSfx("event:/ActionFB/mem_fader");
isPlayingFaderSound = false;
}
frequencySlider.TargetValue = GetRandomNumber();
claritySlider.TargetValue = GetRandomNumber();
PunchTapeManager.Instance.CloseFavoritesPanel();
if (punchTape == null)
{
Debug.Log("no punchTape");
yield break;
}
_activePunchTape = punchTape;
if (isProcessing)
{
Debug.LogWarning("Already processing a memory. Please wait until the process is finished.");
yield break;
}
var searchMemoryKey = string.Format(MemorySpritePath, _activePunchTape.MemoryIndex);
var searchMemoryHandle = ResourceSystem.LoadAsync(searchMemoryKey);
yield return searchMemoryHandle;
Sprite memorySprite = searchMemoryHandle.Status == AsyncOperationStatus.Succeeded
? searchMemoryHandle.Result
: null;
memoryFinishedSpriteRenderer.sprite = memorySprite;
memoryFinishedImageNoColor.sprite = memorySprite;
if (memorySprite == null)
{
Debug.LogError("Memory not found: " + searchMemoryKey);
}
memoryProcessVolume.weight = 1;
AudioManager.Instance.PlaySfx("event:/Scriptal/mem_load");
yield return new WaitForSeconds(SearchStartDelay);
AudioManager.Instance.SetSfxParam("event:/Amb/amb_mem_tuning", "is_mem_tuning", 1);
memoryFinishedSpriteRenderer.color = Color.white;
memoryProcessVolume.weight = 0;
isProcessing = true;
frequencySlider.PrepareForSearch();
claritySlider.PrepareForSearch();
bool freqUnlocked = false;
bool clarityUnlocked = false;
frequencySlider.UnlockSlider(() => freqUnlocked = true);
claritySlider.UnlockSlider(() => clarityUnlocked = true);
yield return new WaitUntil(() => freqUnlocked && clarityUnlocked);
frequencySlider.SetInteractable(true);
claritySlider.SetInteractable(true);
}
public bool IsProcessing()
{
return isProcessing;
}
}
}