A game framework written with osu! in mind.
at master 121 lines 4.2 kB view raw
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. 2// See the LICENCE file in the repository root for full licence text. 3 4using System; 5using System.Collections.Generic; 6 7namespace osu.Framework.Graphics.Transforms 8{ 9 public abstract class Transform 10 { 11 internal ulong TransformID; 12 13 /// <summary> 14 /// Whether this <see cref="Transform"/> has been applied to an <see cref="ITransformable"/>. 15 /// </summary> 16 internal bool Applied; 17 18 /// <summary> 19 /// Whether this <see cref="Transform"/> has been applied completely to an <see cref="ITransformable"/>. 20 /// Used to track whether we still need to apply for targets which allow rewind. 21 /// </summary> 22 internal bool AppliedToEnd; 23 24 /// <summary> 25 /// Whether this <see cref="Transform"/> can be rewound. 26 /// </summary> 27 public bool Rewindable = true; 28 29 public abstract ITransformable TargetTransformable { get; } 30 31 public double StartTime { get; internal set; } 32 public double EndTime { get; internal set; } 33 34 public bool IsLooping { get; internal set; } 35 public double LoopDelay { get; internal set; } 36 37 public abstract string TargetMember { get; } 38 39 /// <summary> 40 /// The name of the grouping this <see cref="Transform"/> belongs to. 41 /// Defaults to <see cref="TargetMember"/>. 42 /// </summary> 43 /// <remarks> 44 /// Transforms in a single group affect the same property (or properties) of a <see cref="Transformable"/>. 45 /// It is assumed that transforms in different groups are independent from each other 46 /// in that they affect different properties, and therefore they can be applied independently 47 /// in any order without affecting the end result. 48 /// </remarks> 49 public virtual string TargetGrouping => TargetMember; 50 51 public abstract void Apply(double time); 52 53 public abstract void ReadIntoStartValue(); 54 55 internal bool HasStartValue; 56 57 internal ITransformSequence CompletionTargetSequence; 58 59 internal ITransformSequence AbortTargetSequence; 60 61 public Transform Clone() => (Transform)MemberwiseClone(); 62 63 public static readonly IComparer<Transform> COMPARER = new TransformTimeComparer(); 64 65 private class TransformTimeComparer : IComparer<Transform> 66 { 67 public int Compare(Transform x, Transform y) 68 { 69 if (x == null) throw new ArgumentNullException(nameof(x)); 70 if (y == null) throw new ArgumentNullException(nameof(y)); 71 72 int compare = x.StartTime.CompareTo(y.StartTime); 73 if (compare != 0) return compare; 74 75 compare = x.TransformID.CompareTo(y.TransformID); 76 77 return compare; 78 } 79 } 80 81 internal void TriggerComplete() => CompletionTargetSequence?.TransformCompleted(); 82 83 internal void TriggerAbort() => AbortTargetSequence?.TransformAborted(); 84 } 85 86 public abstract class Transform<TValue> : Transform 87 { 88 public TValue StartValue { get; protected set; } 89 public TValue EndValue { get; protected internal set; } 90 } 91 92 public abstract class Transform<TValue, TEasing, T> : Transform<TValue> 93 where TEasing : IEasingFunction 94 where T : class, ITransformable 95 { 96 public override ITransformable TargetTransformable => Target; 97 98 public T Target { get; internal set; } 99 100 public TEasing Easing { get; internal set; } 101 102 public sealed override void Apply(double time) 103 { 104 Apply(Target, time); 105 Applied = true; 106 } 107 108 public sealed override void ReadIntoStartValue() => ReadIntoStartValue(Target); 109 110 protected abstract void Apply(T d, double time); 111 112 protected abstract void ReadIntoStartValue(T d); 113 114 public override string ToString() => $"{Target.GetType().Name}.{TargetMember} {StartTime:0.000}-{EndTime:0.000}ms {StartValue} -> {EndValue}"; 115 } 116 117 public abstract class Transform<TValue, T> : Transform<TValue, DefaultEasingFunction, T> 118 where T : class, ITransformable 119 { 120 } 121}