using UnityEngine; namespace OM.TimelineCreator.Runtime { /// /// Base class for all clip data stored within the timeline system. /// Contains common properties like name, description, timing, activation state, /// display color, and error status. Intended to be inherited by specific clip types (e.g., AnimoraClip). /// [System.Serializable] public abstract class OM_ClipBase // Changed to abstract as it likely isn't instantiated directly { // --- Serialized Fields --- // Using OM_StartGroup for editor organization (requires a custom drawer or editor script) [OM_StartGroup("Clip Info", "Info")] // Group Title, Group ID/Key [SerializeField] private string clipName = "New Clip"; // Default name for the clip [SerializeField, TextArea] // Use TextArea for multi-line editing in the inspector private string clipDescription = ""; // Optional description for the clip [SerializeField] private Color highlightColor = Color.white; // Color used for visual representation in the timeline editor [OM_StartGroup("Settings", "Settings")] // Start a new group for timing properties [SerializeField, OM_HideInInspector] // Hide by default, likely controlled by editor logic (e.g., track UI) private bool isActive = true; // Whether the clip is currently active and should be evaluated [SerializeField, Min(0)] // Ensure start time is not negative private float startTime = 0; // The time (in seconds) on the timeline where this clip begins [SerializeField, Min(0)] // Ensure duration is not negative private float duration = 1; // The length (in seconds) of this clip [SerializeField, OM_HideInInspector] // Hide by default, managed internally or by editor private int orderIndex = 0; // The vertical order/layer index of this clip on the timeline // --- Public Properties (Accessors for Serialized Fields) --- /// /// Gets or sets the name of the clip, displayed in the timeline editor. /// public string ClipName { get => clipName; set => clipName = value; } /// /// Gets or sets the description for the clip, potentially shown as a tooltip or in an inspector. /// public string ClipDescription { get => clipDescription; set => clipDescription = value; } /// /// Gets or sets the color used to highlight this clip in the timeline editor UI. /// public Color HighlightColor { get => highlightColor; set => highlightColor = value; } /// /// Gets or sets a value indicating whether this clip is active. Inactive clips are typically ignored during playback. /// public bool IsActive { get => isActive; set => isActive = value; } /// /// Gets or sets the start time of the clip on the timeline (in seconds). /// Setting this might require updating the editor UI representation. /// public float StartTime { get => startTime; set => startTime = Mathf.Max(0, value); } // Added validation /// /// Gets or sets the duration of the clip (in seconds). /// Setting this might require updating the editor UI representation. /// public float Duration { get => duration; set => duration = Mathf.Max(0, value); } // Added validation /// /// Gets or sets the order index (vertical layer) of the clip. /// This is primarily used for sorting tracks visually and resolving potential overlaps if needed. /// Modifying this usually requires re-sorting or updating the timeline structure. /// public int OrderIndex { get => orderIndex; set => orderIndex = value; } // --- Virtual Methods for Timing --- /// /// Gets the effective start time of the clip. Can be overridden if start time calculation is complex. /// /// The start time in seconds. public virtual float GetStartTime() { return startTime; } /// /// Gets the effective duration of the clip. Can be overridden if duration calculation is complex. /// /// The duration in seconds. public virtual float GetDuration() { return duration; } /// /// Sets the effective duration of the clip. Can be overridden for custom logic. /// /// The new duration in seconds. public virtual void SetDuration(float newDuration) { // Basic implementation with validation duration = Mathf.Max(0, newDuration); // Derived classes might need to trigger UI updates or other logic here } /// /// Sets the effective start time of the clip. Can be overridden for custom logic. /// /// The new start time in seconds. public virtual void SetStartTime(float newStartTime) { // Basic implementation with validation startTime = Mathf.Max(0, newStartTime); // Derived classes might need to trigger UI updates or other logic here } /// /// Calculates and gets the effective end time of the clip (StartTime + Duration). /// /// The end time in seconds. public virtual float GetEndTime() { // Standard calculation, ensures virtual methods for start/duration are used return GetStartTime() + GetDuration(); } // --- Virtual Methods for Playback Eligibility and State --- /// /// Determines if the clip is currently in a state where it can be played. /// Base implementation checks IsActive and HasError. Derived classes (like AnimoraClip) /// can add further conditions (e.g., play chance). /// /// True if the clip can potentially be played, false otherwise. public virtual bool CanBePlayed() { // Default condition: must be active and have no errors. return IsActive && HasError(out _) == false; } /// /// Checks if the clip has any configuration errors that would prevent playback. /// Base implementation always returns false (no errors). Derived classes should override this /// to perform specific validation (e.g., check if targets are assigned). /// /// Output parameter containing the error message if an error is found. /// True if an error exists, false otherwise. public virtual bool HasError(out string error) { error = string.Empty; // Default: no error return false; } /// /// Resets the clip's internal state. Called when resetting the timeline or potentially on clip creation/modification. /// Base implementation does nothing. Derived classes can override to reset specific state variables. /// public virtual void Reset() { // No base state to reset here. Derived classes handle their own state. } /// /// A simple override for ToString() to provide a meaningful representation, often the clip name. /// Useful for debugging and logging. /// /// The clip's name or a default string representation. public override string ToString() { return string.IsNullOrEmpty(clipName) ? base.ToString() : clipName; } } }