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