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 { public FeedbackDataCollection feedbackDataCollection; public FeedbackData this[string feedbackName] => GetFeedbackData(feedbackName); private IFeedbackTimeProvider _timeProvider; private readonly List _activePlayers = new List(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 _); } /// /// 通过新系统播放一个 FeedbackData。 /// public FeedbackPlayer PlayFeedback(FeedbackData data, bool stopPrevious = false) { return PlayFeedback(data, null, stopPrevious); } public FeedbackPlayer PlayFeedback(FeedbackData data, Action 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 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); } /// /// 通过名称从 FeedbackDataCollection 中查找并播放。 /// public FeedbackPlayer PlayFeedback(string name, bool stopPrevious = false) { return PlayFeedback(name, null, stopPrevious); } public FeedbackPlayer PlayFeedback(string name, Action 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; } /// /// 停止指定 FeedbackData 的所有活跃播放器。 /// 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); } } } /// /// 按名称停止正在播放的 Feedback。 /// public void StopFeedback(string feedbackName) { if (feedbackDataCollection == null) return; if (feedbackDataCollection.TryGet(feedbackName, out FeedbackData data)) { StopFeedback(data); } } /// /// 停止所有活跃的新系统播放器。 /// 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(); } } }