Merge branch 'master' into mania-difficulty

This commit is contained in:
Dean Herbert
2018-03-12 13:31:48 +09:00
committed by GitHub
259 changed files with 5722 additions and 1366 deletions

View File

@ -12,8 +12,16 @@ namespace osu.Game.Beatmaps
/// Converts a Beatmap for another mode.
/// </summary>
/// <typeparam name="T">The type of HitObject stored in the Beatmap.</typeparam>
public abstract class BeatmapConverter<T> where T : HitObject
public abstract class BeatmapConverter<T> : IBeatmapConverter
where T : HitObject
{
private event Action<HitObject, IEnumerable<HitObject>> ObjectConverted;
event Action<HitObject, IEnumerable<HitObject>> IBeatmapConverter.ObjectConverted
{
add => ObjectConverted += value;
remove => ObjectConverted -= value;
}
/// <summary>
/// Checks if a Beatmap can be converted using this Beatmap Converter.
/// </summary>
@ -32,6 +40,8 @@ namespace osu.Game.Beatmaps
return ConvertBeatmap(new Beatmap(original));
}
void IBeatmapConverter.Convert(Beatmap original) => Convert(original);
/// <summary>
/// Performs the conversion of a Beatmap using this Beatmap Converter.
/// </summary>
@ -63,8 +73,11 @@ namespace osu.Game.Beatmaps
yield break;
}
var converted = ConvertHitObject(original, beatmap).ToList();
ObjectConverted?.Invoke(original, converted);
// Convert the hit object
foreach (var obj in ConvertHitObject(original, beatmap))
foreach (var obj in converted)
{
if (obj == null)
continue;

View File

@ -29,8 +29,8 @@ namespace osu.Game.Beatmaps
set => approachRate = value;
}
public float SliderMultiplier { get; set; } = 1;
public float SliderTickRate { get; set; } = 1;
public double SliderMultiplier { get; set; } = 1;
public double SliderTickRate { get; set; } = 1;
/// <summary>
/// Maps a difficulty value [0, 10] to a two-piece linear range of values.

View File

@ -1,6 +1,8 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
namespace osu.Game.Beatmaps.ControlPoints
{
public class DifficultyControlPoint : ControlPoint
@ -8,6 +10,12 @@ namespace osu.Game.Beatmaps.ControlPoints
/// <summary>
/// The speed multiplier at this control point.
/// </summary>
public double SpeedMultiplier = 1;
public double SpeedMultiplier
{
get => speedMultiplier;
set => speedMultiplier = MathHelper.Clamp(value, 0.1, 10);
}
private double speedMultiplier = 1;
}
}

View File

@ -1,6 +1,7 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Game.Beatmaps.Timing;
namespace osu.Game.Beatmaps.ControlPoints
@ -15,6 +16,12 @@ namespace osu.Game.Beatmaps.ControlPoints
/// <summary>
/// The beat length at this control point.
/// </summary>
public double BeatLength = 1000;
public double BeatLength
{
get => beatLength;
set => beatLength = MathHelper.Clamp(value, 6, 60000);
}
private double beatLength = 1000;
}
}

View File

@ -47,12 +47,12 @@ namespace osu.Game.Beatmaps
foreach (var mod in Mods.OfType<IApplicableToDifficulty>())
mod.ApplyToDifficulty(Beatmap.BeatmapInfo.BaseDifficulty);
foreach (var h in Beatmap.HitObjects)
h.ApplyDefaults(Beatmap.ControlPointInfo, Beatmap.BeatmapInfo.BaseDifficulty);
foreach (var mod in mods.OfType<IApplicableToHitObject<T>>())
foreach (var obj in Beatmap.HitObjects)
mod.ApplyToHitObject(obj);
foreach (var h in Beatmap.HitObjects)
h.ApplyDefaults(Beatmap.ControlPointInfo, Beatmap.BeatmapInfo.BaseDifficulty);
}
protected virtual void PreprocessHitObjects()

View File

@ -8,6 +8,7 @@ using OpenTK.Graphics;
using osu.Game.Beatmaps.Timing;
using osu.Game.Rulesets.Objects.Legacy;
using osu.Game.Beatmaps.ControlPoints;
using osu.Framework;
namespace osu.Game.Beatmaps.Formats
{
@ -21,6 +22,19 @@ namespace osu.Game.Beatmaps.Formats
private LegacySampleBank defaultSampleBank;
private int defaultSampleVolume = 100;
/// <summary>
/// lazer's audio timings in general doesn't match stable. this is the result of user testing, albeit limited.
/// This only seems to be required on windows. We need to eventually figure out why, with a bit of luck.
/// </summary>
public static int UniversalOffset => RuntimeInfo.OS == RuntimeInfo.Platform.Windows ? -22 : 0;
/// <summary>
/// Whether or not beatmap or runtime offsets should be applied. Defaults on; only disable for testing purposes.
/// </summary>
public bool ApplyOffsets = true;
private readonly int offset = UniversalOffset;
public LegacyBeatmapDecoder()
{
}
@ -28,6 +42,9 @@ namespace osu.Game.Beatmaps.Formats
public LegacyBeatmapDecoder(string header)
{
BeatmapVersion = int.Parse(header.Substring(17));
// BeatmapVersion 4 and lower had an incorrect offset (stable has this set as 24ms off)
offset += BeatmapVersion < 5 ? 24 : 0;
}
protected override void ParseBeatmap(StreamReader stream, Beatmap beatmap)
@ -42,6 +59,10 @@ namespace osu.Game.Beatmaps.Formats
ParseContent(stream);
// objects may be out of order *only* if a user has manually edited an .osu file.
// unfortunately there are ranked maps in this state (example: https://osu.ppy.sh/s/594828).
this.beatmap.HitObjects.Sort((x, y) => x.StartTime.CompareTo(y.StartTime));
foreach (var hitObject in this.beatmap.HitObjects)
hitObject.ApplyDefaults(this.beatmap.ControlPointInfo, this.beatmap.BeatmapInfo.BaseDifficulty);
}
@ -98,7 +119,7 @@ namespace osu.Game.Beatmaps.Formats
beatmap.BeatmapInfo.AudioLeadIn = int.Parse(pair.Value);
break;
case @"PreviewTime":
metadata.PreviewTime = int.Parse(pair.Value);
metadata.PreviewTime = getOffsetTime(int.Parse(pair.Value));
break;
case @"Countdown":
beatmap.BeatmapInfo.Countdown = int.Parse(pair.Value) == 1;
@ -228,10 +249,10 @@ namespace osu.Game.Beatmaps.Formats
difficulty.ApproachRate = float.Parse(pair.Value, NumberFormatInfo.InvariantInfo);
break;
case @"SliderMultiplier":
difficulty.SliderMultiplier = float.Parse(pair.Value, NumberFormatInfo.InvariantInfo);
difficulty.SliderMultiplier = double.Parse(pair.Value, NumberFormatInfo.InvariantInfo);
break;
case @"SliderTickRate":
difficulty.SliderTickRate = float.Parse(pair.Value, NumberFormatInfo.InvariantInfo);
difficulty.SliderTickRate = double.Parse(pair.Value, NumberFormatInfo.InvariantInfo);
break;
}
}
@ -253,8 +274,8 @@ namespace osu.Game.Beatmaps.Formats
case EventType.Break:
var breakEvent = new BreakPeriod
{
StartTime = double.Parse(split[1], NumberFormatInfo.InvariantInfo),
EndTime = double.Parse(split[2], NumberFormatInfo.InvariantInfo)
StartTime = getOffsetTime(double.Parse(split[1], NumberFormatInfo.InvariantInfo)),
EndTime = getOffsetTime(double.Parse(split[2], NumberFormatInfo.InvariantInfo))
};
if (!breakEvent.HasEffect)
@ -269,7 +290,7 @@ namespace osu.Game.Beatmaps.Formats
{
string[] split = line.Split(',');
double time = double.Parse(split[0].Trim(), NumberFormatInfo.InvariantInfo);
double time = getOffsetTime(double.Parse(split[0].Trim(), NumberFormatInfo.InvariantInfo));
double beatLength = double.Parse(split[1].Trim(), NumberFormatInfo.InvariantInfo);
double speedMultiplier = beatLength < 0 ? 100.0 / -beatLength : 1;
@ -392,7 +413,14 @@ namespace osu.Game.Beatmaps.Formats
var obj = parser.Parse(line);
if (obj != null)
{
obj.StartTime = getOffsetTime(obj.StartTime);
beatmap.HitObjects.Add(obj);
}
}
private int getOffsetTime(int time) => time + (ApplyOffsets ? offset : 0);
private double getOffsetTime(double time) => time + (ApplyOffsets ? offset : 0);
}
}

View File

@ -0,0 +1,25 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using osu.Game.Rulesets.Objects;
namespace osu.Game.Beatmaps
{
public interface IBeatmapConverter
{
/// <summary>
/// Invoked when a <see cref="HitObject"/> has been converted.
/// The first argument contains the <see cref="HitObject"/> that was converted.
/// The second argument contains the <see cref="HitObject"/>s that were output from the conversion process.
/// </summary>
event Action<HitObject, IEnumerable<HitObject>> ObjectConverted;
/// <summary>
/// Converts a Beatmap using this Beatmap Converter.
/// </summary>
/// <param name="original">The un-converted Beatmap.</param>
void Convert(Beatmap beatmap);
}
}