265 lines
8.9 KiB
C#
265 lines
8.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Cielonos.MainGame.Effects.Feedback;
|
|
using SLSUtilities.Feedback;
|
|
using UnityEngine;
|
|
|
|
namespace Cielonos.MainGame.Inventory
|
|
{
|
|
[RequireComponent(typeof(ItemBase))]
|
|
public class FeedbackSubcontroller : SubcontrollerBase<ItemBase>
|
|
{
|
|
public FeedbackDataCollection feedbackDataCollection;
|
|
public FeedbackData this[string feedbackName] => GetFeedbackData(feedbackName);
|
|
|
|
private IFeedbackTimeProvider _timeProvider;
|
|
private readonly List<FeedbackPlayer> _activePlayers = new List<FeedbackPlayer>(8);
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
_timeProvider = new CharacterFeedbackTimeProvider(owner.player);
|
|
}
|
|
|
|
public FeedbackData GetFeedbackData(string feedbackName)
|
|
{
|
|
if (feedbackDataCollection == null)
|
|
{
|
|
Debug.LogWarning($"[Item.FeedbackSubcontroller] feedbackDataCollection is null on {owner?.name}.");
|
|
return null;
|
|
}
|
|
|
|
if (!feedbackDataCollection.TryGet(feedbackName, out FeedbackData data))
|
|
{
|
|
Debug.LogWarning($"[Item.FeedbackSubcontroller] FeedbackData '{feedbackName}' not found on {owner?.name}.");
|
|
return null;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
public bool TryGetFeedbackData(string feedbackName, out FeedbackData data)
|
|
{
|
|
data = null;
|
|
if (feedbackDataCollection == null || string.IsNullOrEmpty(feedbackName)) return false;
|
|
return feedbackDataCollection.TryGet(feedbackName, out data);
|
|
}
|
|
|
|
public bool HasFeedback(string feedbackName)
|
|
{
|
|
return TryGetFeedbackData(feedbackName, out _);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 通过新系统播放一个 FeedbackData。
|
|
/// </summary>
|
|
public FeedbackPlayer PlayFeedback(FeedbackData data, bool stopPrevious = false)
|
|
{
|
|
return PlayFeedback(data, null, stopPrevious);
|
|
}
|
|
|
|
public FeedbackPlayer PlayFeedback(FeedbackData data, Action<RuntimeFeedback> configureRuntime, bool stopPrevious = false)
|
|
{
|
|
if (data == null) return null;
|
|
|
|
if (data.playbackStrategy == FeedbackPlaybackStrategy.Detached)
|
|
{
|
|
return PlayDetachedFeedback(data, configureRuntime, stopPrevious);
|
|
}
|
|
|
|
if (!data.CanPlay()) return null;
|
|
data.RecordPlay();
|
|
|
|
if (stopPrevious)
|
|
{
|
|
StopFeedback(data);
|
|
}
|
|
|
|
_timeProvider ??= owner?.player != null ? new CharacterFeedbackTimeProvider(owner.player) : DefaultFeedbackTimeProvider.Instance;
|
|
|
|
RuntimeFeedback runtimeFeedback = data.CreateRuntimeFeedback();
|
|
configureRuntime?.Invoke(runtimeFeedback);
|
|
|
|
Transform ownerTransform = owner?.player?.transform;
|
|
var player = new FeedbackPlayer(runtimeFeedback, _timeProvider, ownerTransform);
|
|
player.Play();
|
|
_activePlayers.Add(player);
|
|
return player;
|
|
}
|
|
|
|
public FeedbackPlayer PlayFeedback(RuntimeFeedback runtimeFeedback, bool stopPrevious = false)
|
|
{
|
|
if (runtimeFeedback == null) return null;
|
|
|
|
FeedbackData template = runtimeFeedback.templateData;
|
|
if (runtimeFeedback.playbackStrategy == FeedbackPlaybackStrategy.Detached)
|
|
{
|
|
return PlayDetachedFeedback(runtimeFeedback, stopPrevious);
|
|
}
|
|
|
|
if (template != null)
|
|
{
|
|
if (!FeedbackPlaybackGate.CanPlay(template)) return null;
|
|
FeedbackPlaybackGate.RecordPlay(template);
|
|
}
|
|
|
|
if (stopPrevious && template != null)
|
|
{
|
|
StopFeedback(template);
|
|
}
|
|
|
|
_timeProvider ??= owner?.player != null ? new CharacterFeedbackTimeProvider(owner.player) : DefaultFeedbackTimeProvider.Instance;
|
|
Transform ownerTransform = owner?.player?.transform;
|
|
var player = new FeedbackPlayer(runtimeFeedback, _timeProvider, ownerTransform);
|
|
player.Play();
|
|
_activePlayers.Add(player);
|
|
return player;
|
|
}
|
|
|
|
private FeedbackPlayer PlayDetachedFeedback(FeedbackData data, Action<RuntimeFeedback> configureRuntime, bool stopPrevious)
|
|
{
|
|
RuntimeFeedback runtimeFeedback = data.CreateRuntimeFeedback();
|
|
configureRuntime?.Invoke(runtimeFeedback);
|
|
return PlayDetachedFeedback(runtimeFeedback, stopPrevious);
|
|
}
|
|
|
|
private FeedbackPlayer PlayDetachedFeedback(RuntimeFeedback runtimeFeedback, bool stopPrevious)
|
|
{
|
|
FeedbackManager manager = FeedbackManager.Instance;
|
|
if (manager == null)
|
|
{
|
|
Debug.LogWarning($"[Item.FeedbackSubcontroller] Cannot play detached FeedbackData '{runtimeFeedback?.feedbackName}': FeedbackManager not found.");
|
|
return null;
|
|
}
|
|
|
|
if (stopPrevious && runtimeFeedback?.templateData != null)
|
|
{
|
|
manager.Stop(runtimeFeedback.templateData);
|
|
}
|
|
|
|
return manager.Play(runtimeFeedback);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 通过名称从 FeedbackDataCollection 中查找并播放。
|
|
/// </summary>
|
|
public FeedbackPlayer PlayFeedback(string name, bool stopPrevious = false)
|
|
{
|
|
return PlayFeedback(name, null, stopPrevious);
|
|
}
|
|
|
|
public FeedbackPlayer PlayFeedback(string name, Action<RuntimeFeedback> configureRuntime, bool stopPrevious = false)
|
|
{
|
|
if (feedbackDataCollection == null)
|
|
{
|
|
Debug.LogWarning($"[Item.FeedbackSubcontroller] feedbackDataCollection is null on {owner?.name}.");
|
|
return null;
|
|
}
|
|
|
|
if (!feedbackDataCollection.TryGet(name, out FeedbackData data))
|
|
{
|
|
Debug.LogWarning($"[Item.FeedbackSubcontroller] FeedbackData '{name}' not found on {owner?.name}.");
|
|
return null;
|
|
}
|
|
|
|
return PlayFeedback(data, configureRuntime, stopPrevious);
|
|
}
|
|
|
|
public FeedbackPlayer TryPlayFeedback(string name, bool stopPrevious = false)
|
|
{
|
|
return TryGetFeedbackData(name, out FeedbackData data) ? PlayFeedback(data, stopPrevious) : null;
|
|
}
|
|
|
|
public FeedbackPlayer TryPlayFirstFeedback(params string[] feedbackNames)
|
|
{
|
|
return TryPlayFirstFeedback(false, feedbackNames);
|
|
}
|
|
|
|
public FeedbackPlayer TryPlayFirstFeedback(bool stopPrevious, params string[] feedbackNames)
|
|
{
|
|
if (feedbackNames == null) return null;
|
|
|
|
for (int i = 0; i < feedbackNames.Length; i++)
|
|
{
|
|
if (TryGetFeedbackData(feedbackNames[i], out FeedbackData data))
|
|
{
|
|
return PlayFeedback(data, stopPrevious);
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 停止指定 FeedbackData 的所有活跃播放器。
|
|
/// </summary>
|
|
public void StopFeedback(FeedbackData data)
|
|
{
|
|
if (data != null && data.playbackStrategy == FeedbackPlaybackStrategy.Detached)
|
|
{
|
|
FeedbackManager.Instance?.Stop(data);
|
|
return;
|
|
}
|
|
|
|
for (int i = _activePlayers.Count - 1; i >= 0; i--)
|
|
{
|
|
if (_activePlayers[i].Data == data)
|
|
{
|
|
_activePlayers[i].Stop();
|
|
_activePlayers.RemoveAt(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 按名称停止正在播放的 Feedback。
|
|
/// </summary>
|
|
public void StopFeedback(string feedbackName)
|
|
{
|
|
if (feedbackDataCollection == null) return;
|
|
if (feedbackDataCollection.TryGet(feedbackName, out FeedbackData data))
|
|
{
|
|
StopFeedback(data);
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 停止所有活跃的新系统播放器。
|
|
/// </summary>
|
|
public void StopAllFeedbacks()
|
|
{
|
|
for (int i = _activePlayers.Count - 1; i >= 0; i--)
|
|
{
|
|
_activePlayers[i].Stop();
|
|
}
|
|
_activePlayers.Clear();
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
float dt = Time.deltaTime;
|
|
for (int i = _activePlayers.Count - 1; i >= 0; i--)
|
|
{
|
|
FeedbackPlayer player = _activePlayers[i];
|
|
player.Tick(dt);
|
|
|
|
if (player.IsCompleted || !player.IsActive)
|
|
{
|
|
_activePlayers.RemoveAt(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
StopAllFeedbacks();
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
StopAllFeedbacks();
|
|
}
|
|
}
|
|
}
|