Files
chameleon/Assets/Scripts/Editor/VideoClipPlaylistItemDrawer.cs
adminandClaude Fable 5 36ce4a66df Add VideoClipPlaylist component for sequential gapless clip playback
Plays a list of items (clip + percentage range) on a VideoPlayer.
Double-buffers via a second player (auto-created child incl. AudioSource
copy) and drives the screen texture through a MaterialPropertyBlock,
flipping only once the next player delivers frames - no black/freeze gap.
Editor drawer renders each item as clip row + min-max percent range slider.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 16:38:57 +02:00

59 lines
2.6 KiB
C#

using UnityEditor;
using UnityEngine;
/// <summary>
/// Draws a <see cref="VideoClipPlaylist.Item"/> as two lines: the clip field and a
/// percent min-max slider (stored normalized 0..1) selecting the played portion.
/// </summary>
[CustomPropertyDrawer(typeof(VideoClipPlaylist.Item))]
public class VideoClipPlaylistItemDrawer : PropertyDrawer
{
private const float PercentFieldWidth = 44f;
private const float Gap = 4f;
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
=> EditorGUIUtility.singleLineHeight * 2f + EditorGUIUtility.standardVerticalSpacing;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
SerializedProperty clipProp = property.FindPropertyRelative(nameof(VideoClipPlaylist.Item.clip));
SerializedProperty rangeProp = property.FindPropertyRelative(nameof(VideoClipPlaylist.Item.range));
EditorGUI.BeginProperty(position, label, property);
float line = EditorGUIUtility.singleLineHeight;
var clipRect = new Rect(position.x, position.y, position.width, line);
EditorGUI.PropertyField(clipRect, clipProp, label);
var rowRect = new Rect(position.x, clipRect.yMax + EditorGUIUtility.standardVerticalSpacing,
position.width, line);
Rect rangeRect = EditorGUI.PrefixLabel(rowRect, new GUIContent("Range (%)",
"Played portion of the clip in percent (start/end)."));
Vector2 range = rangeProp.vector2Value;
float min = Mathf.Round(range.x * 1000f) / 10f;
float max = Mathf.Round(range.y * 1000f) / 10f;
var minRect = new Rect(rangeRect.x, rangeRect.y, PercentFieldWidth, line);
var maxRect = new Rect(rangeRect.xMax - PercentFieldWidth, rangeRect.y, PercentFieldWidth, line);
var sliderRect = new Rect(minRect.xMax + Gap, rangeRect.y,
Mathf.Max(0f, rangeRect.width - 2f * (PercentFieldWidth + Gap)), line);
EditorGUI.BeginChangeCheck();
int indent = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0; // fields inside the row must not re-indent
min = EditorGUI.FloatField(minRect, min);
EditorGUI.MinMaxSlider(sliderRect, ref min, ref max, 0f, 100f);
max = EditorGUI.FloatField(maxRect, max);
EditorGUI.indentLevel = indent;
if (EditorGUI.EndChangeCheck())
{
min = Mathf.Clamp(min, 0f, 100f);
max = Mathf.Clamp(max, min, 100f);
rangeProp.vector2Value = new Vector2(min / 100f, max / 100f);
}
EditorGUI.EndProperty();
}
}