JD2022-TU1/main/tools/framework/JD.Timeline/View/Actions/Macros/ClipExtensions.cs

121 lines
No EOL
3.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using JD.Maths.Utils;
using JD.Serialization;
using TeaBox;
namespace JD.Timeline.View.Actions.Macros
{
/// <summary>
/// Adds utility methods to manipulate clips.
/// </summary>
public static class ClipExtensions
{
/// <summary>
/// Enumerates the clips and the clips of the tape references.
/// </summary>
public static IEnumerable<Clip> Recursive(this IEnumerable<Clip> clips)
{
return clips.RecursiveImplementation().Distinct();
}
public static IEnumerable<Clip> RecursiveImplementation(this IEnumerable<Clip> clips)
{
foreach (var clip in clips)
{
yield return clip;
if (clip is TapeReferenceClip)
{
var subTape = ((TapeReferenceClip)clip).ReferredTape;
if (subTape != null)
{
foreach (var subClip in subTape.Clips.RecursiveImplementation())
{
yield return subClip;
}
}
}
}
}
/// <summary>
/// True if the clip is bound with the provided actor name.
/// </summary>
public static bool ContainsActor(this Clip clip, string actorName)
{
return string.IsNullOrEmpty(actorName) || clip.ReferredActors().Any(actor => actor.Path.Contains(actorName));
}
/// <summary>
/// The list of all referred actor.
/// </summary>
public static IEnumerable<ObjectPath> ReferredActors(this Clip clip)
{
var clipWithActor = clip as ClipWithActor;
var tapeReference = clip as TapeReferenceClip;
if (clipWithActor != null)
{
return clipWithActor.ActorPaths;
}
if (tapeReference != null)
{
var referredTape = tapeReference.ReferredTape;
if (referredTape != null)
{
return referredTape.Clips.Recursive().SelectMany(child => child.ReferredActors());
}
}
return Enumerable.Empty<ObjectPath>();
}
/// <summary>
/// Resize the clip to the new duration and scale the curves according to this value (or not).
/// </summary>
public static void Resize(this Clip clip, int newDuration, bool resizeCurves = true)
{
if (resizeCurves)
{
clip.ScaleCurvesX(newDuration / (float)clip.Duration);
}
clip.Duration = newDuration;
}
/// <summary>
/// Resize the curve in time according to the given ratio.
/// </summary>
public static void ScaleCurvesX(this Clip clip, float ratio)
{
foreach (var curve in clip.Curves)
{
curve.ScaleX(ratio);
}
}
/// <summary>
/// Resize the curve in time according to the given ratio relative to the given offset.
/// </summary>
public static void ScaleCurvesY(this Clip clip, float ratio, float offset)
{
foreach (var curve in clip.Curves)
{
if (curve.Type == BezierCurveType.RotationX
|| curve.Type == BezierCurveType.RotationY
|| curve.Type == BezierCurveType.RotationZ)
{
// the units of the GUI are in degrees, the units of the engine are in radians
var radianOffset = offset * MathConstants.DegreesToRadiansFactor ;
curve.ScaleY(ratio, radianOffset);
}
else
{
curve.ScaleY(ratio, offset);
}
}
}
}
}