diff --git a/Quaver.API/Maps/Qua.cs b/Quaver.API/Maps/Qua.cs index d12ec4159..5dc347f70 100644 --- a/Quaver.API/Maps/Qua.cs +++ b/Quaver.API/Maps/Qua.cs @@ -489,6 +489,7 @@ public void Sort() SortSoundEffects(); SortTimingPoints(); SortSliderVelocities(); + SortScrollSpeedFactors(); } /// @@ -630,6 +631,14 @@ public TimingPointInfo GetTimingPointAt(double time) public SliderVelocityInfo GetScrollVelocityAt(double time, string timingGroupId = DefaultScrollGroupId) => ((ScrollGroup)TimingGroups[timingGroupId]).GetScrollVelocityAt(time); + /// + /// Gets a scroll velocity at a particular time in the map + /// + /// + /// + public ScrollSpeedFactorInfo GetScrollSpeedFactorAt(double time, string timingGroupId = DefaultScrollGroupId) => + ((ScrollGroup)TimingGroups[timingGroupId]).GetScrollSpeedFactorAt(time); + /// /// Finds the length of a timing point. /// @@ -1019,6 +1028,18 @@ public void MirrorHitObjects() /// public void SortBookmarks() => Bookmarks.HybridSort(); + /// + /// + public void SortScrollSpeedFactors() + { + foreach (var (_, timingGroup) in TimingGroups) + { + if (!(timingGroup is ScrollGroup scrollGroup)) + continue; + scrollGroup.ScrollSpeedFactors.HybridSort(); + } + } + /// /// public void SortHitObjects() => HitObjects.HybridSort(); diff --git a/Quaver.API/Maps/Structures/ScrollGroup.cs b/Quaver.API/Maps/Structures/ScrollGroup.cs index 8bfd21c8a..facbb2094 100644 --- a/Quaver.API/Maps/Structures/ScrollGroup.cs +++ b/Quaver.API/Maps/Structures/ScrollGroup.cs @@ -19,11 +19,22 @@ public class ScrollGroup : TimingGroup public List ScrollVelocities { get; [MoonSharpHidden] set; } = new List(); + /// + /// Scroll Speed Factor .qua data + /// + public List ScrollSpeedFactors { get; [MoonSharpHidden] set; } = + new List(); + public SliderVelocityInfo GetScrollVelocityAt(double time) { return ScrollVelocities.AtTime((float)time); } + public ScrollSpeedFactorInfo GetScrollSpeedFactorAt(double time) + { + return ScrollSpeedFactors.AtTime((float)time); + } + /// /// /// @@ -31,7 +42,8 @@ public SliderVelocityInfo GetScrollVelocityAt(double time) protected bool Equals(ScrollGroup other) { return base.Equals(other) && InitialScrollVelocity.Equals(other.InitialScrollVelocity) && - ScrollVelocities.SequenceEqual(other.ScrollVelocities, SliderVelocityInfo.ByValueComparer); + ScrollVelocities.SequenceEqual(other.ScrollVelocities, SliderVelocityInfo.ByValueComparer) && + ScrollSpeedFactors.SequenceEqual(other.ScrollSpeedFactors, ScrollSpeedFactorInfo.ByValueComparer); } /// diff --git a/Quaver.API/Maps/Structures/ScrollSpeedFactorInfo.cs b/Quaver.API/Maps/Structures/ScrollSpeedFactorInfo.cs new file mode 100644 index 000000000..50341447c --- /dev/null +++ b/Quaver.API/Maps/Structures/ScrollSpeedFactorInfo.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MoonSharp.Interpreter; +using MoonSharp.Interpreter.Interop; +using YamlDotNet.Serialization; + +namespace Quaver.API.Maps.Structures +{ + /// + /// ScrollSpeedFactors section of the .qua + /// + [Serializable] + [MoonSharpUserData] + public class ScrollSpeedFactorInfo : IStartTime + { + /// + /// The time in milliseconds at which the scroll speed factor will be exactly + /// + public float StartTime { get; [MoonSharpHidden] set; } + + /// + /// The multiplier given to the scroll speed. + /// It will be lerped to the next scroll speed factor like keyframes, unless this is the last factor change. + /// + public float Multiplier { get; [MoonSharpHidden] set; } + + /// + /// Returns if the SSF is allowed to be edited in lua scripts + /// + [YamlIgnore] + public bool IsEditableInLuaScript + { + get; + [MoonSharpVisible(false)] + set; + } + + /// + /// Sets the start time of the SSF. + /// FOR USE IN LUA SCRIPTS ONLY. + /// + /// + /// + public void SetStartTime(float time) + { + ThrowUneditableException(); + StartTime = time; + } + + /// + /// Sets the multiplier of the SSF. + /// FOR USE IN LUA SCRIPTS ONLY. + /// + /// + /// + public void SetMultiplier(float multiplier) + { + ThrowUneditableException(); + Multiplier = multiplier; + } + + /// + /// + /// + private void ThrowUneditableException() + { + if (!IsEditableInLuaScript) + throw new InvalidOperationException("Value is not allowed to be edited in lua scripts."); + } + + private sealed class StartTimeRelationalComparer : IComparer + { + public int Compare(ScrollSpeedFactorInfo x, ScrollSpeedFactorInfo y) + { + if (ReferenceEquals(x, y)) return 0; + if (ReferenceEquals(null, y)) return 1; + if (ReferenceEquals(null, x)) return -1; + return x.StartTime.CompareTo(y.StartTime); + } + } + + public static IComparer StartTimeComparer { get; } = new StartTimeRelationalComparer(); + + /// + /// By-value comparer, auto-generated by Rider. + /// + private sealed class ByValueEqualityComparer : IEqualityComparer + { + public bool Equals(ScrollSpeedFactorInfo x, ScrollSpeedFactorInfo y) + { + if (ReferenceEquals(x, y)) return true; + if (ReferenceEquals(x, null)) return false; + if (ReferenceEquals(y, null)) return false; + if (x.GetType() != y.GetType()) return false; + return x.StartTime.Equals(y.StartTime) && x.Multiplier.Equals(y.Multiplier); + } + + public int GetHashCode(ScrollSpeedFactorInfo obj) + { + return HashCode.Combine(obj.StartTime, obj.Multiplier); + } + } + + public static IEqualityComparer ByValueComparer { get; } = new ByValueEqualityComparer(); + } +} \ No newline at end of file