Files
sbox-public/game/editor/MovieMaker/Code/Project/Extensions.cs
s&box team 71f266059a Open source release
This commit imports the C# engine code and game files, excluding C++ source code.

[Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
2025-11-24 09:05:18 +00:00

66 lines
1.9 KiB
C#

using Sandbox.MovieMaker;
using System.Linq;
using Sandbox.MovieMaker.Compiled;
namespace Editor.MovieMaker;
#nullable enable
/// <summary>
/// Helper methods for working with <see cref="MovieProject"/>, <see cref="ProjectTrack{T}"/>, or <see cref="PropertyBlock"/>.
/// </summary>
public static class ProjectExtensions
{
public static MovieProject FromCompiled( this MovieClip clip ) =>
new MovieProject( clip );
public static IEnumerable<IProjectPropertyBlock> GetBlocks( this IProjectPropertyTrack track, MovieTimeRange timeRange )
{
return track.Blocks.Where( x => x.TimeRange.Intersect( timeRange ) is not null );
}
public static IEnumerable<PropertyBlock<T>> GetBlocks<T>( this ProjectPropertyTrack<T> track, MovieTimeRange timeRange )
{
return track.Blocks.Where( x => x.TimeRange.Intersect( timeRange ) is not null );
}
public static T GetValue<T>( this IReadOnlyList<IPropertyBlock<T>> blocks, MovieTime time )
{
return blocks.GetLastBlock( time ).GetValue( time );
}
public static T GetLastBlock<T>( this IReadOnlyList<T> blocks, MovieTime time )
where T : ITrackBlock
{
if ( blocks.Count == 0 ) throw new ArgumentException( "Expected at least one block.", nameof( blocks ) );
if ( time <= blocks[0].TimeRange.Start ) return blocks[0];
if ( time >= blocks[^1].TimeRange.End ) return blocks[^1];
// TODO: binary search?
// We go backwards because if we're exactly on a block boundary, we want to use the later block
for ( var i = blocks.Count - 1; i >= 0; --i )
{
var block = blocks[i];
if ( block.TimeRange.Start > time ) continue;
return block;
}
return blocks[0];
}
public static T? GetBlock<T>( this IReadOnlyList<T> blocks, MovieTime time )
where T : ITrackBlock
{
if ( blocks.Count == 0 ) return default;
var block = blocks.GetLastBlock( time );
return block.TimeRange.Contains( time ) ? block : default;
}
}