121 lines
No EOL
3.9 KiB
C#
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);
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
} |