2019-01-24 16:43:03 +08:00
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
2018-04-13 17:19:50 +08:00
2018-11-20 15:51:59 +08:00
using osuTK ;
2018-04-13 17:19:50 +08:00
using osu.Game.Beatmaps ;
using osu.Game.Rulesets.Osu.Objects ;
using System ;
using System.Collections.Generic ;
2018-11-28 16:20:37 +08:00
using osu.Game.Replays ;
2018-06-27 11:18:00 +08:00
using osu.Game.Rulesets.Osu.UI ;
2018-04-13 17:19:50 +08:00
using osu.Game.Rulesets.Replays ;
namespace osu.Game.Rulesets.Osu.Replays
{
public abstract class OsuAutoGeneratorBase : AutoGenerator < OsuHitObject >
{
#region Constants
/// <summary>
/// Constants (for spinners).
/// </summary>
2018-06-27 11:18:00 +08:00
protected static readonly Vector2 SPINNER_CENTRE = OsuPlayfield . BASE_SIZE / 2 ;
2019-02-28 12:31:40 +08:00
2018-04-13 17:19:50 +08:00
protected const float SPIN_RADIUS = 50 ;
/// <summary>
/// The time in ms between each ReplayFrame.
/// </summary>
protected readonly double FrameDelay ;
#endregion
#region Construction / Initialisation
protected Replay Replay ;
protected List < ReplayFrame > Frames = > Replay . Frames ;
protected OsuAutoGeneratorBase ( Beatmap < OsuHitObject > beatmap )
: base ( beatmap )
{
2018-11-29 12:22:45 +08:00
Replay = new Replay ( ) ;
2018-04-13 17:19:50 +08:00
// We are using ApplyModsToRate and not ApplyModsToTime to counteract the speed up / slow down from HalfTime / DoubleTime so that we remain at a constant framerate of 60 fps.
FrameDelay = ApplyModsToRate ( 1000.0 / 60.0 ) ;
}
#endregion
#region Utilities
2019-02-28 12:31:40 +08:00
2018-04-13 17:19:50 +08:00
protected double ApplyModsToTime ( double v ) = > v ;
protected double ApplyModsToRate ( double v ) = > v ;
private class ReplayFrameComparer : IComparer < ReplayFrame >
{
public int Compare ( ReplayFrame f1 , ReplayFrame f2 )
{
if ( f1 = = null ) throw new ArgumentNullException ( nameof ( f1 ) ) ;
if ( f2 = = null ) throw new ArgumentNullException ( nameof ( f2 ) ) ;
return f1 . Time . CompareTo ( f2 . Time ) ;
}
}
private static readonly IComparer < ReplayFrame > replay_frame_comparer = new ReplayFrameComparer ( ) ;
protected int FindInsertionIndex ( ReplayFrame frame )
{
int index = Frames . BinarySearch ( frame , replay_frame_comparer ) ;
if ( index < 0 )
{
index = ~ index ;
}
else
{
// Go to the first index which is actually bigger
while ( index < Frames . Count & & frame . Time = = Frames [ index ] . Time )
{
+ + index ;
}
}
return index ;
}
protected void AddFrameToReplay ( ReplayFrame frame ) = > Frames . Insert ( FindInsertionIndex ( frame ) , frame ) ;
protected static Vector2 CirclePosition ( double t , double radius ) = > new Vector2 ( ( float ) ( Math . Cos ( t ) * radius ) , ( float ) ( Math . Sin ( t ) * radius ) ) ;
#endregion
}
}