198 lines
6.6 KiB
C#
198 lines
6.6 KiB
C#
#nullable enable
|
|
using ImGuiNET;
|
|
using T3.Core.Animation;
|
|
using T3.Editor.Gui.Input;
|
|
using T3.Editor.Gui.Interaction;
|
|
using T3.Editor.UiModel.InputsAndTypes;
|
|
|
|
namespace T3.Editor.Gui.Windows.TimeLine.TimeClips;
|
|
|
|
internal static class ClipTimingEditor
|
|
{
|
|
|
|
internal static void DrawPopUp(ClipArea.LayerContext context)
|
|
{
|
|
if (TimeClipEditorRequested)
|
|
{
|
|
ImGui.OpenPopup((string) TimeEditPopupId);
|
|
TimeClipEditorRequested = false;
|
|
}
|
|
|
|
if (context.ClipSelection.Count == 0)
|
|
return;
|
|
|
|
ImGui.SetNextWindowSize(new Vector2(350, 0));
|
|
|
|
ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, new Vector2(10,4));
|
|
if (ImGui.BeginPopup((string)TimeEditPopupId))
|
|
{
|
|
FrameStats.Current.OpenedPopUpName = TimeEditPopupId;
|
|
DrawContent(context);
|
|
ImGui.EndPopup();
|
|
}
|
|
ImGui.PopStyleVar();
|
|
}
|
|
|
|
|
|
private static void DrawContent(ClipArea.LayerContext context)
|
|
{
|
|
_clips.Clear();
|
|
_clips.AddRange(context.ClipSelection.GetAllOrSelectedClips());
|
|
|
|
InitCombinedRanges();
|
|
var labelWidth = 70 * T3Ui.UiScaleFactor;
|
|
var width = 70 * T3Ui.UiScaleFactor;
|
|
|
|
FormInputs.AddSectionSubHeader("Edit clip timing");
|
|
|
|
ImGui.NewLine();
|
|
ImGui.SameLine(labelWidth);
|
|
ImGui.TextUnformatted("Start");
|
|
|
|
ImGui.SameLine(labelWidth + width);
|
|
ImGui.TextUnformatted("Duration");
|
|
|
|
ImGui.SameLine(labelWidth + 2*width);
|
|
ImGui.TextUnformatted("End");
|
|
|
|
EditClipTimingRange(Ranges.ClipRange,"Clip", _combinedTimeRange);
|
|
EditClipTimingRange(Ranges.SourceRange,"Source", _combinedSourceRange);
|
|
FormInputs.AddVerticalSpace();
|
|
|
|
ImGui.TextUnformatted("Speed");
|
|
ImGui.SameLine(labelWidth);
|
|
|
|
var size = new Vector2(100, 0);
|
|
ImGui.PushID(0);
|
|
if (SingleValueEdit.Draw(ref _combinedSpeedPercentage, size, min: 0, max: 999, clampMin: false, clampMax: false, scale: 0.01f, format: "{0:0.0}%") != InputEditStateFlags.Nothing)
|
|
{
|
|
foreach (var clip in _clips)
|
|
{
|
|
var clipDuration = clip.TimeRange.Duration;
|
|
clip.SourceRange.End = clip.SourceRange.Start + clipDuration * (_combinedSpeedPercentage / 100);
|
|
}
|
|
}
|
|
}
|
|
|
|
private enum Ranges
|
|
{
|
|
ClipRange,
|
|
SourceRange,
|
|
}
|
|
|
|
private static void EditClipTimingRange(Ranges range, string label, TimeRange r)
|
|
{
|
|
ImGui.PushID((int)range);
|
|
|
|
ImGui.TextUnformatted(label);
|
|
ImGui.SameLine(70 * T3Ui.UiScaleFactor);
|
|
|
|
var size = new Vector2(70, 0) * T3Ui.UiScaleFactor;
|
|
|
|
// Start
|
|
ImGui.PushID(0);
|
|
if (SingleValueEdit.Draw(ref r.Start, size, min: 0, max: 999) != InputEditStateFlags.Nothing)
|
|
{
|
|
if (!float.IsNaN(r.Start))
|
|
{
|
|
foreach (var clip in _clips)
|
|
{
|
|
switch (range)
|
|
{
|
|
case Ranges.ClipRange:
|
|
clip.TimeRange.Start = r.Start;
|
|
break;
|
|
case Ranges.SourceRange:
|
|
clip.SourceRange.Start = r.Start;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
ImGui.PopID();
|
|
|
|
// Duration
|
|
ImGui.SameLine();
|
|
ImGui.PushID(1);
|
|
var duration = r.Duration;
|
|
if (SingleValueEdit.Draw(ref duration, size, min: 0, max: 999) != InputEditStateFlags.Nothing)
|
|
{
|
|
if (!float.IsNaN(duration))
|
|
{
|
|
foreach (var clip in _clips)
|
|
{
|
|
switch (range)
|
|
{
|
|
case Ranges.ClipRange:
|
|
clip.TimeRange.Duration = duration;
|
|
break;
|
|
case Ranges.SourceRange:
|
|
clip.SourceRange.Duration = duration;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
ImGui.PopID();
|
|
|
|
ImGui.SameLine();
|
|
ImGui.PushID(2);
|
|
if (SingleValueEdit.Draw(ref r.End, size, min: 0, max: 999) == InputEditStateFlags.Finished)
|
|
{
|
|
if (!float.IsNaN(r.End))
|
|
{
|
|
foreach (var clip in _clips)
|
|
{
|
|
switch (range)
|
|
{
|
|
case Ranges.ClipRange:
|
|
clip.TimeRange.End = r.End;
|
|
break;
|
|
case Ranges.SourceRange:
|
|
clip.SourceRange.End = r.End;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
ImGui.PopID();
|
|
ImGui.PopID();
|
|
}
|
|
|
|
private static void InitCombinedRanges()
|
|
{
|
|
var isFirst = true;
|
|
|
|
foreach (var clip in _clips)
|
|
{
|
|
var speed = clip.Speed * 100;
|
|
if (isFirst)
|
|
{
|
|
_combinedTimeRange.Start = clip.TimeRange.Start;
|
|
_combinedTimeRange.End = clip.TimeRange.End;
|
|
_combinedSourceRange.Start = clip.SourceRange.Start;
|
|
_combinedSourceRange.End = clip.SourceRange.End;
|
|
_combinedSpeedPercentage = speed;
|
|
isFirst = false;
|
|
}
|
|
else
|
|
{
|
|
if (Math.Abs(_combinedTimeRange.Start - clip.TimeRange.Start) > 0.001f) _combinedTimeRange.Start = float.NaN;
|
|
if (Math.Abs(_combinedTimeRange.End - clip.TimeRange.End) > 0.001f) _combinedTimeRange.End = float.NaN;
|
|
if (Math.Abs(_combinedSourceRange.Start - clip.SourceRange.Start) > 0.001f) _combinedSourceRange.Start = float.NaN;
|
|
if (Math.Abs(_combinedSourceRange.End - clip.SourceRange.End) > 0.001f) _combinedSourceRange.End = float.NaN;
|
|
|
|
if(Math.Abs(speed - _combinedSpeedPercentage) > 0.001) _combinedSpeedPercentage= float.NaN;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static TimeRange _combinedTimeRange;
|
|
private static TimeRange _combinedSourceRange;
|
|
private static float _combinedSpeedPercentage = 1;
|
|
|
|
private static readonly List<TimeClip> _clips =[];
|
|
|
|
internal static bool TimeClipEditorRequested;
|
|
private const string TimeEditPopupId = nameof(TimeEditPopupId);
|
|
} |