115 lines
4.1 KiB
C#
115 lines
4.1 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using Sirenix.OdinInspector;
|
||
using UniRx;
|
||
using UnityEngine;
|
||
|
||
namespace SLSUtilities.Feedback
|
||
{
|
||
/// <summary>
|
||
/// 单个反馈序列的完整数据定义,是 Feedback 系统的核心 ScriptableObject。
|
||
/// 包含多条轨道(Track),每条轨道包含按时间排列的片段(Clip)。
|
||
/// </summary>
|
||
[CreateAssetMenu(fileName = "NewFeedbackData", menuName = "SLS/Feedback/FeedbackData")]
|
||
public partial class FeedbackData : SerializedScriptableObject
|
||
{
|
||
/// <summary>
|
||
/// 父级集合引用,由 FeedbackDataCollection 自动维护。
|
||
/// </summary>
|
||
[ReadOnly, ShowInInspector]
|
||
public FeedbackDataCollection parentCollection;
|
||
|
||
/// <summary>
|
||
/// 用于字典索引的名称,在 FeedbackDataCollection 中按此名称查找。
|
||
/// </summary>
|
||
[Title("Editor Settings")]
|
||
public string feedbackName;
|
||
|
||
/// <summary>
|
||
/// 全局默认的时间设置。Clip 可选择覆盖此设置。
|
||
/// </summary>
|
||
public FeedbackTimeSettings defaultTimeSettings = new FeedbackTimeSettings();
|
||
|
||
/// <summary>
|
||
/// 反馈轨道列表,多条轨道天然并行播放。
|
||
/// </summary>
|
||
[Title("Feedback Tracks")]
|
||
[ListDrawerSettings(ShowFoldout = true, ListElementLabelName = "trackName")]
|
||
public List<FeedbackTrack> tracks = new List<FeedbackTrack>();
|
||
|
||
/// <summary>
|
||
/// 所有轨道的最大时长。
|
||
/// </summary>
|
||
public float TotalDuration => tracks.Count > 0 ? tracks.Max(t => t.TotalDuration) : 0f;
|
||
|
||
/// <summary>
|
||
/// 运行时预览:通过 FeedbackManager 播放此反馈。
|
||
/// 仅在 Play 模式下可用。
|
||
/// </summary>
|
||
[Button("Preview", ButtonSizes.Medium)]
|
||
[EnableIf("@UnityEngine.Application.isPlaying")]
|
||
public void Preview()
|
||
{
|
||
if (!Application.isPlaying)
|
||
{
|
||
Debug.LogWarning("[FeedbackData] Preview is only available in Play mode.");
|
||
return;
|
||
}
|
||
|
||
if (FeedbackManager.Instance == null)
|
||
{
|
||
Debug.LogWarning("[FeedbackData] Preview failed: FeedbackManager not found in scene. " +
|
||
"Add a GameObject with FeedbackManager component.");
|
||
return;
|
||
}
|
||
|
||
FeedbackPlayer player = FeedbackManager.Instance.Play(this);
|
||
Debug.Log($"[FeedbackData] Previewing '{feedbackName}' (Duration: {TotalDuration:F2}s)");
|
||
}
|
||
}
|
||
|
||
public partial class FeedbackData
|
||
{
|
||
public FeedbackTrack Track(string name)
|
||
{
|
||
FeedbackTrack track = tracks.FirstOrDefault(t => t.trackName == name);
|
||
if (track == null)
|
||
{
|
||
Debug.LogWarning($"[FeedbackData] Track '{name}' not found in FeedbackData '{feedbackName}'.");
|
||
}
|
||
return track;
|
||
}
|
||
|
||
public FeedbackClip Clip(string trackName, Func<FeedbackClip, bool> predicate)
|
||
{
|
||
FeedbackTrack track = Track(trackName);
|
||
if (track == null) return null;
|
||
|
||
FeedbackClip clip = track.clips.FirstOrDefault(predicate);
|
||
if (clip == null)
|
||
{
|
||
Debug.LogWarning($"[FeedbackData] Clip matching predicate not found in Track '{trackName}' of FeedbackData '{feedbackName}'.");
|
||
}
|
||
return clip;
|
||
}
|
||
|
||
public FeedbackClip Clip<T>(string trackName) where T : FeedbackActionBase
|
||
{
|
||
return Clip(trackName, c => c.action.GetType() == typeof(T));
|
||
}
|
||
|
||
public FeedbackClip Clip(string trackName, string clipName)
|
||
{
|
||
return Clip(trackName, c => c.clipName == clipName);
|
||
}
|
||
|
||
public T Action<T>(string trackName) where T : FeedbackActionBase
|
||
{
|
||
FeedbackTrack track = Track(trackName);
|
||
FeedbackClip clip = track?.clips.FirstOrDefault(c => c.action.GetType() == typeof(T));
|
||
return clip?.action as T;
|
||
}
|
||
}
|
||
}
|