using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace OCES.Audio
{
///
/// 环境音通道播放器。
/// 与 MusicChannelPlayer 逻辑相同,但使用 AmbienceTransition 表,不涉及节拍对齐。
///
class AmbienceChannelPlayer
{
readonly AmbienceTransitionConfig m_transitionConfig;
readonly MonoBehaviour m_coroutineHost;
readonly ChannelFader m_fader;
readonly List m_transitionCandidates = new();
ContainerPlayHandle m_currentHandle;
Coroutine m_transitionCoroutine;
Coroutine m_currentFadeOutCoroutine;
Coroutine m_currentFadeInCoroutine;
uint m_currentContainerId;
internal AmbienceChannelPlayer(
AmbienceTransitionConfig transitionConfig,
LongAudioContainerPlayer player,
MonoBehaviour coroutineHost)
{
this.m_transitionConfig = transitionConfig;
this.m_coroutineHost = coroutineHost;
this.m_fader = new ChannelFader(player, coroutineHost);
}
// ─────────────────────────────────────────────
// 公开接口
// ─────────────────────────────────────────────
internal void SwitchTo(uint newContainerId)
{
if (newContainerId == this.m_currentContainerId && this.m_currentHandle != null)
return;
AmbienceTransition transition = ResolveTransition((int)this.m_currentContainerId, (int)newContainerId);
if (this.m_transitionCoroutine != null)
this.m_coroutineHost.StopCoroutine(this.m_transitionCoroutine);
this.m_transitionCoroutine = this.m_coroutineHost.StartCoroutine(
DoTransition(newContainerId, transition));
}
public void Stop()
{
if (this.m_transitionCoroutine != null)
this.m_coroutineHost.StopCoroutine(this.m_transitionCoroutine);
this.m_fader.StopCurrent();
}
// ─────────────────────────────────────────────
// Transition 流程(无节拍对齐)
// ─────────────────────────────────────────────
IEnumerator DoTransition(uint newContainerId, AmbienceTransition transition)
{
if (newContainerId == this.m_fader.CurrentContainerId && this.m_fader.CurrentHandle != null) yield break;
// 如果等待期间被切回来了,就不淡变了
if (this.m_currentFadeInCoroutine != null)
{
this.m_coroutineHost.StopCoroutine(this.m_currentFadeInCoroutine);
this.m_currentFadeInCoroutine = null;
}
if (this.m_currentFadeOutCoroutine != null)
{
this.m_coroutineHost.StopCoroutine(this.m_currentFadeOutCoroutine);
this.m_currentFadeOutCoroutine = null;
}
ContainerPlayHandle outgoing = this.m_fader.CurrentHandle;
float outgoingVolume = this.m_fader.CurrentVolume;
this.m_currentFadeOutCoroutine = this.m_coroutineHost.StartCoroutine(
this.m_fader.FadeOutBranch(outgoing, outgoingVolume, transition));
this.m_currentFadeInCoroutine = this.m_coroutineHost.StartCoroutine(
this.m_fader.FadeInBranch(newContainerId, transition));
yield return this.m_currentFadeInCoroutine;
this.m_currentFadeInCoroutine = null;
}
// ─────────────────────────────────────────────
// 工具
// ─────────────────────────────────────────────
AmbienceTransition ResolveTransition(int sourceContainerId, int destinationContainerId)
{
this.m_transitionCandidates.Clear();
foreach (AmbienceTransition transition in this.m_transitionConfig.AmbienceTransitionList())
{
bool sourceMatch = transition.SourceContainerID == sourceContainerId || transition.SourceContainerID < 0;
bool destMatch = transition.DestinationContainerID == destinationContainerId || transition.DestinationContainerID < 0;
if (sourceMatch && destMatch)
{
this.m_transitionCandidates.Add(transition);
}
}
if (this.m_transitionCandidates.Count == 0)
return this.m_transitionConfig.QueryById(1);
AmbienceTransition best = this.m_transitionCandidates[0];
for (int i = 1; i < this.m_transitionCandidates.Count; i++)
{
if (this.m_transitionCandidates[i].Id > best.Id)
best = this.m_transitionCandidates[i];
}
return best;
}
}
}