JD2022-TU1/main/tools/framework/JD.Serialization/Timeline/Utils/LoopSectionExtensions.cs

87 lines
No EOL
3.2 KiB
C#

using System;
using System.Collections.Generic;
namespace JD.Serialization
{
/// <summary>
/// A tape reference can loop, this represent a part in the loop process of the tape reference.
/// </summary>
public struct LoopSection
{
public int Start;
public int End;
public bool IsPartial;
public bool IsUnusedSpace;
public bool IsReversed;
public int Length => End - Start;
}
public static class LoopSectionExtensions
{
/// <summary>
/// True if the loop type is a repeat loop.
/// </summary>
public static bool Repeats(this TapeReferenceClip.Loop_Enum type)
{
return type == TapeReferenceClip.Loop_Enum.LoopingType_PingPong ||
type == TapeReferenceClip.Loop_Enum.LoopingType_PingPongInfinite ||
type == TapeReferenceClip.Loop_Enum.LoopingType_Loop ||
type == TapeReferenceClip.Loop_Enum.LoopingType_Infinite;
}
public static bool PingPongs(this TapeReferenceClip.Loop_Enum type)
{
return type == TapeReferenceClip.Loop_Enum.LoopingType_PingPong ||
type == TapeReferenceClip.Loop_Enum.LoopingType_PingPongInfinite;
}
public static IEnumerable<LoopSection> EnumerateLoopSections(this TapeReferenceClip tapeReference)
{
int tapeDuration = tapeReference.TapeDuration;
if (tapeDuration <= 0)
{
yield break;
}
if (tapeReference.Loop == TapeReferenceClip.Loop_Enum.LoopingType_Reverse)
{
var lastPart = CreateSection(tapeReference, tapeReference.StopFrame - tapeDuration, tapeReference.StopFrame, tapeDuration);
lastPart.IsReversed = true;
yield return lastPart;
if (lastPart.Start > tapeReference.StartFrame)
{
var unusedSpace = CreateSection(tapeReference, tapeReference.StartFrame, lastPart.Start, tapeDuration);
unusedSpace.IsUnusedSpace = true;
unusedSpace.IsReversed = true;
yield return unusedSpace;
}
yield break;
}
int i = 0;
for (int frame = tapeReference.StartFrame; frame < tapeReference.StopFrame; frame += tapeDuration)
{
i++;
var section = CreateSection(tapeReference, frame, frame + tapeDuration, tapeDuration);
section.IsUnusedSpace = frame != tapeReference.StartFrame && !tapeReference.Loop.Repeats();
section.IsReversed = tapeReference.Loop.PingPongs() && i % 2 == 0;
yield return section;
}
}
private static LoopSection CreateSection(TapeReferenceClip tapeReference, int start, int end, int tapeDuration)
{
var result = new LoopSection
{
Start = Math.Max(start, tapeReference.StartFrame),
End = Math.Min(end, tapeReference.StopFrame)
};
result.IsPartial = result.Length != tapeDuration;
return result;
}
}
}