using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text.Json.Serialization; using Sandbox.MovieMaker; namespace Editor.MovieMaker; #nullable enable partial record PropertySignal { public static PropertySignal operator -( PropertySignal a, PropertySignal b ) { if ( Transformer.GetDefault() is not { } transformer ) return a; if ( a.Equals( b ) ) return transformer.Identity; if ( b.IsIdentity ) return a; return new ToLocalOperation( a, b ); } [return: NotNullIfNotNull( nameof(a) )] public static PropertySignal operator +( PropertySignal a, PropertySignal b ) { if ( Transformer.GetDefault() is null ) return a; if ( a.IsIdentity ) return b; if ( b.IsIdentity ) return a; return new ToGlobalOperation( a, b ); } [JsonIgnore] public virtual bool IsIdentity => false; } public interface IAdditiveSignal : IPropertySignal { PropertySignal First { get; } PropertySignal Second { get; } } [JsonDiscriminator( "ToLocal" )] file sealed record ToLocalOperation( PropertySignal First, PropertySignal Second ) : BinaryOperation( First, Second ) { public override T GetValue( MovieTime time ) => _transformer.Apply( _transformer.Invert( Second.GetValue( time ) ), First.GetValue( time ) ); [SkipHotload] private static ITransformer _transformer = Transformer.GetDefaultOrThrow(); } [JsonDiscriminator( "ToGlobal" )] file sealed record ToGlobalOperation( PropertySignal First, PropertySignal Second ) : BinaryOperation( First, Second ), IAdditiveSignal { public override T GetValue( MovieTime time ) => _transformer.Apply( First.GetValue( time ), Second.GetValue( time ) ); protected override IEnumerable OnGetKeyframes() => Second.Keyframes; protected override PropertySignal OnWithKeyframes( IReadOnlyList> keyframes ) { var second = Second.WithKeyframes( [..keyframes.Select( x => x with { Value = _transformer.Difference( First.GetValue( x.Time ), x.Value ) } )] ); return second.IsIdentity ? First : First + second; } PropertySignal IAdditiveSignal.First => First; PropertySignal IAdditiveSignal.Second => Second; [SkipHotload] private static ITransformer _transformer = Transformer.GetDefaultOrThrow(); }