mirror of
https://github.com/ppy/osu.git
synced 2024-11-06 06:57:39 +08:00
Resolve merge conflict
This commit is contained in:
commit
34dc8e7375
@ -1,9 +1,11 @@
|
||||
osu!lazer is currently in early stages of development and is not yet ready for end users. Please avoid creating issues or bugs if you do not personally intend to fix them. Some acceptable topics include:
|
||||
osu!lazer is currently still under heavy development!
|
||||
|
||||
Please ensure that you are making an issue for one of the following:
|
||||
|
||||
- A bug with currently implemented features (not features that don't exist)
|
||||
- A feature you are considering adding, so we can collaborate on feedback and design.
|
||||
- Discussions about technical design decisions
|
||||
- Bugs that you have found and are personally willing and able to fix
|
||||
- TODO lists of smaller tasks around larger features
|
||||
|
||||
Basically, issues are not a place for you to get help. They are a place for developers to collaborate on the game.
|
||||
|
||||
If your issue qualifies, replace this text with a detailed description of your issue with as much relevant information as you can provide.
|
||||
|
||||
Screenshots and log files are highly welcomed.
|
@ -1 +1 @@
|
||||
Subproject commit 6915954abdba64e72f698aa58698b00159f3678d
|
||||
Subproject commit d29c8365ba3cf7924b57cf22341f4af55658764c
|
@ -28,16 +28,14 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
}
|
||||
|
||||
protected override Beatmap CreateBeatmap()
|
||||
protected override Beatmap CreateBeatmap(Ruleset ruleset)
|
||||
{
|
||||
var beatmap = new Beatmap
|
||||
{
|
||||
BeatmapInfo = new BeatmapInfo
|
||||
{
|
||||
BaseDifficulty = new BeatmapDifficulty
|
||||
{
|
||||
CircleSize = 6,
|
||||
}
|
||||
BaseDifficulty = new BeatmapDifficulty { CircleSize = 6 },
|
||||
Ruleset = ruleset.RulesetInfo
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -15,19 +15,18 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
}
|
||||
|
||||
protected override Beatmap CreateBeatmap()
|
||||
protected override Beatmap CreateBeatmap(Ruleset ruleset)
|
||||
{
|
||||
var beatmap = new Beatmap
|
||||
{
|
||||
BeatmapInfo = new BeatmapInfo
|
||||
{
|
||||
BaseDifficulty = new BeatmapDifficulty
|
||||
{
|
||||
CircleSize = 6,
|
||||
}
|
||||
BaseDifficulty = new BeatmapDifficulty { CircleSize = 6 },
|
||||
Ruleset = ruleset.RulesetInfo
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
for (int i = 0; i < 512; i++)
|
||||
beatmap.HitObjects.Add(new Fruit { X = 0.5f + i / 2048f * (i % 10 - 5), StartTime = i * 100, NewCombo = i % 8 == 0 });
|
||||
|
||||
|
@ -15,9 +15,10 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
}
|
||||
|
||||
protected override Beatmap CreateBeatmap()
|
||||
protected override Beatmap CreateBeatmap(Ruleset ruleset)
|
||||
{
|
||||
var beatmap = new Beatmap();
|
||||
var beatmap = new Beatmap { BeatmapInfo = { Ruleset = ruleset.RulesetInfo } };
|
||||
|
||||
|
||||
for (int i = 0; i < 512; i++)
|
||||
if (i % 5 < 3)
|
||||
|
@ -77,7 +77,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||
yield break;
|
||||
}
|
||||
|
||||
var objects = IsForCurrentRuleset ? generateSpecific(original) : generateConverted(original);
|
||||
var objects = IsForCurrentRuleset ? generateSpecific(original, beatmap) : generateConverted(original, beatmap);
|
||||
|
||||
if (objects == null)
|
||||
yield break;
|
||||
@ -110,10 +110,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||
/// Method that generates hit objects for osu!mania specific beatmaps.
|
||||
/// </summary>
|
||||
/// <param name="original">The original hit object.</param>
|
||||
/// <param name="originalBeatmap">The original beatmap. This is used to look-up any values dependent on a fully-loaded beatmap.</param>
|
||||
/// <returns>The hit objects generated.</returns>
|
||||
private IEnumerable<ManiaHitObject> generateSpecific(HitObject original)
|
||||
private IEnumerable<ManiaHitObject> generateSpecific(HitObject original, Beatmap originalBeatmap)
|
||||
{
|
||||
var generator = new SpecificBeatmapPatternGenerator(random, original, beatmap, lastPattern);
|
||||
var generator = new SpecificBeatmapPatternGenerator(random, original, beatmap, lastPattern, originalBeatmap);
|
||||
|
||||
Pattern newPattern = generator.Generate();
|
||||
lastPattern = newPattern;
|
||||
@ -125,26 +126,25 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||
/// Method that generates hit objects for non-osu!mania beatmaps.
|
||||
/// </summary>
|
||||
/// <param name="original">The original hit object.</param>
|
||||
/// <param name="originalBeatmap">The original beatmap. This is used to look-up any values dependent on a fully-loaded beatmap.</param>
|
||||
/// <returns>The hit objects generated.</returns>
|
||||
private IEnumerable<ManiaHitObject> generateConverted(HitObject original)
|
||||
private IEnumerable<ManiaHitObject> generateConverted(HitObject original, Beatmap originalBeatmap)
|
||||
{
|
||||
var endTimeData = original as IHasEndTime;
|
||||
var distanceData = original as IHasDistance;
|
||||
var positionData = original as IHasPosition;
|
||||
|
||||
// Following lines currently commented out to appease resharper
|
||||
|
||||
Patterns.PatternGenerator conversion = null;
|
||||
|
||||
if (distanceData != null)
|
||||
conversion = new DistanceObjectPatternGenerator(random, original, beatmap, lastPattern);
|
||||
conversion = new DistanceObjectPatternGenerator(random, original, beatmap, lastPattern, originalBeatmap);
|
||||
else if (endTimeData != null)
|
||||
conversion = new EndTimeObjectPatternGenerator(random, original, beatmap);
|
||||
conversion = new EndTimeObjectPatternGenerator(random, original, beatmap, originalBeatmap);
|
||||
else if (positionData != null)
|
||||
{
|
||||
computeDensity(original.StartTime);
|
||||
|
||||
conversion = new HitObjectPatternGenerator(random, original, beatmap, lastPattern, lastTime, lastPosition, density, lastStair);
|
||||
conversion = new HitObjectPatternGenerator(random, original, beatmap, lastPattern, lastTime, lastPosition, density, lastStair, originalBeatmap);
|
||||
|
||||
recordNote(original.StartTime, positionData.Position);
|
||||
}
|
||||
@ -153,10 +153,9 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||
return null;
|
||||
|
||||
Pattern newPattern = conversion.Generate();
|
||||
lastPattern = newPattern;
|
||||
|
||||
var stairPatternGenerator = conversion as HitObjectPatternGenerator;
|
||||
lastStair = stairPatternGenerator?.StairType ?? lastStair;
|
||||
lastPattern = conversion is EndTimeObjectPatternGenerator ? lastPattern : newPattern;
|
||||
lastStair = (conversion as HitObjectPatternGenerator)?.StairType ?? lastStair;
|
||||
|
||||
return newPattern.HitObjects;
|
||||
}
|
||||
@ -166,8 +165,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||
/// </summary>
|
||||
private class SpecificBeatmapPatternGenerator : Patterns.Legacy.PatternGenerator
|
||||
{
|
||||
public SpecificBeatmapPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern)
|
||||
: base(random, hitObject, beatmap, previousPattern)
|
||||
public SpecificBeatmapPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, Beatmap originalBeatmap)
|
||||
: base(random, hitObject, beatmap, previousPattern, originalBeatmap)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.MathUtils;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
@ -29,11 +30,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
|
||||
private PatternType convertType;
|
||||
|
||||
public DistanceObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern)
|
||||
: base(random, hitObject, beatmap, previousPattern)
|
||||
public DistanceObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, Beatmap originalBeatmap)
|
||||
: base(random, hitObject, beatmap, previousPattern, originalBeatmap)
|
||||
{
|
||||
convertType = PatternType.None;
|
||||
if (Beatmap.ControlPointInfo.EffectPointAt(hitObject.StartTime).KiaiMode)
|
||||
if (!Beatmap.ControlPointInfo.EffectPointAt(hitObject.StartTime).KiaiMode)
|
||||
convertType = PatternType.LowProbability;
|
||||
|
||||
var distanceData = hitObject as IHasDistance;
|
||||
@ -305,19 +306,19 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
p4 = 0;
|
||||
break;
|
||||
case 3:
|
||||
p2 = Math.Max(p2, 0.1);
|
||||
p2 = Math.Min(p2, 0.1);
|
||||
p3 = 0;
|
||||
p4 = 0;
|
||||
break;
|
||||
case 4:
|
||||
p2 = Math.Max(p2, 0.3);
|
||||
p3 = Math.Max(p3, 0.04);
|
||||
p2 = Math.Min(p2, 0.3);
|
||||
p3 = Math.Min(p3, 0.04);
|
||||
p4 = 0;
|
||||
break;
|
||||
case 5:
|
||||
p2 = Math.Max(p2, 0.34);
|
||||
p3 = Math.Max(p3, 0.1);
|
||||
p4 = Math.Max(p4, 0.03);
|
||||
p2 = Math.Min(p2, 0.34);
|
||||
p3 = Math.Min(p3, 0.1);
|
||||
p4 = Math.Min(p4, 0.03);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -396,17 +397,19 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
// Create the hold note
|
||||
addToPattern(pattern, holdColumn, startTime, endTime);
|
||||
|
||||
int noteCount = 1;
|
||||
int nextColumn = Random.Next(RandomStart, TotalColumns);
|
||||
int noteCount;
|
||||
if (ConversionDifficulty > 6.5)
|
||||
noteCount = GetRandomNoteCount(0.63, 0);
|
||||
else if (ConversionDifficulty > 4)
|
||||
noteCount = GetRandomNoteCount(TotalColumns < 6 ? 0.12 : 0.45, 0);
|
||||
else if (ConversionDifficulty > 2.5)
|
||||
noteCount = GetRandomNoteCount(TotalColumns < 6 ? 0 : 0.24, 0);
|
||||
else
|
||||
noteCount = 0;
|
||||
noteCount = Math.Min(TotalColumns - 1, noteCount);
|
||||
|
||||
bool ignoreHead = !sampleInfoListAt(startTime).Any(s => s.Name == SampleInfo.HIT_WHISTLE || s.Name == SampleInfo.HIT_FINISH || s.Name == SampleInfo.HIT_CLAP);
|
||||
int nextColumn = Random.Next(RandomStart, TotalColumns);
|
||||
|
||||
var rowPattern = new Pattern();
|
||||
for (int i = 0; i <= spanCount; i++)
|
||||
|
@ -7,6 +7,7 @@ using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using System.Linq;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
@ -15,8 +16,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
{
|
||||
private readonly double endTime;
|
||||
|
||||
public EndTimeObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap)
|
||||
: base(random, hitObject, beatmap, new Pattern())
|
||||
public EndTimeObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Beatmap originalBeatmap)
|
||||
: base(random, hitObject, beatmap, new Pattern(), originalBeatmap)
|
||||
{
|
||||
var endtimeData = HitObject as IHasEndTime;
|
||||
|
||||
|
@ -5,6 +5,7 @@ using System;
|
||||
using System.Linq;
|
||||
using OpenTK;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Mania.MathUtils;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
@ -19,8 +20,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
|
||||
private readonly PatternType convertType;
|
||||
|
||||
public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, PatternType lastStair)
|
||||
: base(random, hitObject, beatmap, previousPattern)
|
||||
public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, PatternType lastStair, Beatmap originalBeatmap)
|
||||
: base(random, hitObject, beatmap, previousPattern, originalBeatmap)
|
||||
{
|
||||
if (previousTime > hitObject.StartTime) throw new ArgumentOutOfRangeException(nameof(previousTime));
|
||||
if (density < 0) throw new ArgumentOutOfRangeException(nameof(density));
|
||||
@ -308,20 +309,20 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
p5 = 0;
|
||||
break;
|
||||
case 3:
|
||||
p2 = Math.Max(p2, 0.1);
|
||||
p2 = Math.Min(p2, 0.1);
|
||||
p3 = 0;
|
||||
p4 = 0;
|
||||
p5 = 0;
|
||||
break;
|
||||
case 4:
|
||||
p2 = Math.Max(p2, 0.23);
|
||||
p3 = Math.Max(p3, 0.04);
|
||||
p2 = Math.Min(p2, 0.23);
|
||||
p3 = Math.Min(p3, 0.04);
|
||||
p4 = 0;
|
||||
p5 = 0;
|
||||
break;
|
||||
case 5:
|
||||
p3 = Math.Max(p3, 0.15);
|
||||
p4 = Math.Max(p4, 0.03);
|
||||
p3 = Math.Min(p3, 0.15);
|
||||
p4 = Math.Min(p4, 0.03);
|
||||
p5 = 0;
|
||||
break;
|
||||
}
|
||||
@ -355,23 +356,23 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
p3 = 0;
|
||||
break;
|
||||
case 3:
|
||||
centreProbability = Math.Max(centreProbability, 0.03);
|
||||
p2 = Math.Max(p2, 0.1);
|
||||
centreProbability = Math.Min(centreProbability, 0.03);
|
||||
p2 = 0;
|
||||
p3 = 0;
|
||||
break;
|
||||
case 4:
|
||||
centreProbability = 0;
|
||||
p2 = Math.Max(p2 * 2, 0.2);
|
||||
p2 = Math.Min(p2 * 2, 0.2);
|
||||
p3 = 0;
|
||||
break;
|
||||
case 5:
|
||||
centreProbability = Math.Max(centreProbability, 0.03);
|
||||
centreProbability = Math.Min(centreProbability, 0.03);
|
||||
p3 = 0;
|
||||
break;
|
||||
case 6:
|
||||
centreProbability = 0;
|
||||
p2 = Math.Max(p2 * 2, 0.5);
|
||||
p3 = Math.Max(p3 * 2, 0.15);
|
||||
p2 = Math.Min(p2 * 2, 0.5);
|
||||
p3 = Math.Min(p3 * 2, 0.15);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -25,14 +25,20 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
/// </summary>
|
||||
protected readonly FastRandom Random;
|
||||
|
||||
protected PatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern)
|
||||
/// <summary>
|
||||
/// The beatmap which <see cref="HitObject"/> is being converted from.
|
||||
/// </summary>
|
||||
protected readonly Beatmap OriginalBeatmap;
|
||||
|
||||
protected PatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, Beatmap originalBeatmap)
|
||||
: base(hitObject, beatmap, previousPattern)
|
||||
{
|
||||
if (random == null) throw new ArgumentNullException(nameof(random));
|
||||
if (beatmap == null) throw new ArgumentNullException(nameof(beatmap));
|
||||
if (previousPattern == null) throw new ArgumentNullException(nameof(previousPattern));
|
||||
if (originalBeatmap == null) throw new ArgumentNullException(nameof(originalBeatmap));
|
||||
|
||||
Random = random;
|
||||
OriginalBeatmap = originalBeatmap;
|
||||
|
||||
RandomStart = TotalColumns == 8 ? 1 : 0;
|
||||
}
|
||||
|
||||
@ -94,17 +100,20 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
if (conversionDifficulty != null)
|
||||
return conversionDifficulty.Value;
|
||||
|
||||
HitObject lastObject = Beatmap.HitObjects.LastOrDefault();
|
||||
HitObject firstObject = Beatmap.HitObjects.FirstOrDefault();
|
||||
HitObject lastObject = OriginalBeatmap.HitObjects.LastOrDefault();
|
||||
HitObject firstObject = OriginalBeatmap.HitObjects.FirstOrDefault();
|
||||
|
||||
double drainTime = (lastObject?.StartTime ?? 0) - (firstObject?.StartTime ?? 0);
|
||||
drainTime -= Beatmap.TotalBreakTime;
|
||||
drainTime -= OriginalBeatmap.TotalBreakTime;
|
||||
|
||||
if (drainTime == 0)
|
||||
drainTime = 10000;
|
||||
drainTime = 10000000;
|
||||
|
||||
BeatmapDifficulty difficulty = Beatmap.BeatmapInfo.BaseDifficulty;
|
||||
conversionDifficulty = ((difficulty.DrainRate + MathHelper.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + Beatmap.HitObjects.Count / drainTime * 9f) / 38f * 5f / 1.15;
|
||||
// We need this in seconds
|
||||
drainTime /= 1000;
|
||||
|
||||
BeatmapDifficulty difficulty = OriginalBeatmap.BeatmapInfo.BaseDifficulty;
|
||||
conversionDifficulty = ((difficulty.DrainRate + MathHelper.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + OriginalBeatmap.HitObjects.Count / drainTime * 9f) / 38f * 5f / 1.15;
|
||||
conversionDifficulty = Math.Min(conversionDifficulty.Value, 12);
|
||||
|
||||
return conversionDifficulty.Value;
|
||||
|
@ -4,18 +4,142 @@
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania
|
||||
{
|
||||
public class ManiaDifficultyCalculator : DifficultyCalculator<ManiaHitObject>
|
||||
internal class ManiaDifficultyCalculator : DifficultyCalculator<ManiaHitObject>
|
||||
{
|
||||
private const double star_scaling_factor = 0.018;
|
||||
|
||||
/// <summary>
|
||||
/// In milliseconds. For difficulty calculation we will only look at the highest strain value in each time interval of size strain_step.
|
||||
/// This is to eliminate higher influence of stream over aim by simply having more HitObjects with high strain.
|
||||
/// The higher this value, the less strains there will be, indirectly giving long beatmaps an advantage.
|
||||
/// </summary>
|
||||
private const double strain_step = 400;
|
||||
|
||||
/// <summary>
|
||||
/// The weighting of each strain value decays to this number * it's previous value
|
||||
/// </summary>
|
||||
private const double decay_weight = 0.9;
|
||||
|
||||
/// <summary>
|
||||
/// HitObjects are stored as a member variable.
|
||||
/// </summary>
|
||||
private readonly List<ManiaHitObjectDifficulty> difficultyHitObjects = new List<ManiaHitObjectDifficulty>();
|
||||
|
||||
public ManiaDifficultyCalculator(Beatmap beatmap)
|
||||
: base(beatmap)
|
||||
{
|
||||
}
|
||||
|
||||
public override double Calculate(Dictionary<string, double> categoryDifficulty = null) => 0;
|
||||
public ManiaDifficultyCalculator(Beatmap beatmap, Mod[] mods)
|
||||
: base(beatmap, mods)
|
||||
{
|
||||
}
|
||||
|
||||
public override double Calculate(Dictionary<string, double> categoryDifficulty = null)
|
||||
{
|
||||
// Fill our custom DifficultyHitObject class, that carries additional information
|
||||
difficultyHitObjects.Clear();
|
||||
|
||||
int columnCount = (Beatmap as ManiaBeatmap)?.TotalColumns ?? 7;
|
||||
|
||||
foreach (var hitObject in Beatmap.HitObjects)
|
||||
difficultyHitObjects.Add(new ManiaHitObjectDifficulty(hitObject, columnCount));
|
||||
|
||||
// Sort DifficultyHitObjects by StartTime of the HitObjects - just to make sure.
|
||||
difficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime));
|
||||
|
||||
if (!calculateStrainValues())
|
||||
return 0;
|
||||
|
||||
double starRating = calculateDifficulty() * star_scaling_factor;
|
||||
|
||||
categoryDifficulty?.Add("Strain", starRating);
|
||||
|
||||
return starRating;
|
||||
}
|
||||
|
||||
private bool calculateStrainValues()
|
||||
{
|
||||
// Traverse hitObjects in pairs to calculate the strain value of NextHitObject from the strain value of CurrentHitObject and environment.
|
||||
using (List<ManiaHitObjectDifficulty>.Enumerator hitObjectsEnumerator = difficultyHitObjects.GetEnumerator())
|
||||
{
|
||||
if (!hitObjectsEnumerator.MoveNext())
|
||||
return false;
|
||||
|
||||
ManiaHitObjectDifficulty current = hitObjectsEnumerator.Current;
|
||||
|
||||
// First hitObject starts at strain 1. 1 is the default for strain values, so we don't need to set it here. See DifficultyHitObject.
|
||||
while (hitObjectsEnumerator.MoveNext())
|
||||
{
|
||||
var next = hitObjectsEnumerator.Current;
|
||||
next?.CalculateStrains(current, TimeRate);
|
||||
current = next;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private double calculateDifficulty()
|
||||
{
|
||||
double actualStrainStep = strain_step * TimeRate;
|
||||
|
||||
// Find the highest strain value within each strain step
|
||||
List<double> highestStrains = new List<double>();
|
||||
double intervalEndTime = actualStrainStep;
|
||||
double maximumStrain = 0; // We need to keep track of the maximum strain in the current interval
|
||||
|
||||
ManiaHitObjectDifficulty previousHitObject = null;
|
||||
foreach (var hitObject in difficultyHitObjects)
|
||||
{
|
||||
// While we are beyond the current interval push the currently available maximum to our strain list
|
||||
while (hitObject.BaseHitObject.StartTime > intervalEndTime)
|
||||
{
|
||||
highestStrains.Add(maximumStrain);
|
||||
|
||||
// The maximum strain of the next interval is not zero by default! We need to take the last hitObject we encountered, take its strain and apply the decay
|
||||
// until the beginning of the next interval.
|
||||
if (previousHitObject == null)
|
||||
{
|
||||
maximumStrain = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
double individualDecay = Math.Pow(ManiaHitObjectDifficulty.INDIVIDUAL_DECAY_BASE, (intervalEndTime - previousHitObject.BaseHitObject.StartTime) / 1000);
|
||||
double overallDecay = Math.Pow(ManiaHitObjectDifficulty.OVERALL_DECAY_BASE, (intervalEndTime - previousHitObject.BaseHitObject.StartTime) / 1000);
|
||||
maximumStrain = previousHitObject.IndividualStrain * individualDecay + previousHitObject.OverallStrain * overallDecay;
|
||||
}
|
||||
|
||||
// Go to the next time interval
|
||||
intervalEndTime += actualStrainStep;
|
||||
}
|
||||
|
||||
// Obtain maximum strain
|
||||
double strain = hitObject.IndividualStrain + hitObject.OverallStrain;
|
||||
maximumStrain = Math.Max(strain, maximumStrain);
|
||||
|
||||
previousHitObject = hitObject;
|
||||
}
|
||||
|
||||
// Build the weighted sum over the highest strains for each interval
|
||||
double difficulty = 0;
|
||||
double weight = 1;
|
||||
highestStrains.Sort((a, b) => b.CompareTo(a)); // Sort from highest to lowest strain.
|
||||
|
||||
foreach (double strain in highestStrains)
|
||||
{
|
||||
difficulty += weight * strain;
|
||||
weight *= decay_weight;
|
||||
}
|
||||
|
||||
return difficulty;
|
||||
}
|
||||
|
||||
protected override BeatmapConverter<ManiaHitObject> CreateBeatmapConverter(Beatmap beatmap) => new ManiaBeatmapConverter(true, beatmap);
|
||||
}
|
||||
|
@ -91,6 +91,7 @@ namespace osu.Game.Rulesets.Mania
|
||||
},
|
||||
new ManiaModRandom(),
|
||||
new ManiaModDualStages(),
|
||||
new ManiaModMirror(),
|
||||
new MultiMod
|
||||
{
|
||||
Mods = new Mod[]
|
||||
@ -112,7 +113,7 @@ namespace osu.Game.Rulesets.Mania
|
||||
|
||||
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_mania_o };
|
||||
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new ManiaDifficultyCalculator(beatmap);
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new ManiaDifficultyCalculator(beatmap, mods);
|
||||
|
||||
public override int? LegacyID => 3;
|
||||
|
||||
|
28
osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs
Normal file
28
osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using System.Linq;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
public class ManiaModMirror : Mod, IApplicableToRulesetContainer<ManiaHitObject>
|
||||
{
|
||||
public override string Name => "Mirror";
|
||||
public override string ShortenedName => "MR";
|
||||
public override ModType Type => ModType.Special;
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override bool Ranked => true;
|
||||
|
||||
public void ApplyToRulesetContainer(RulesetContainer<ManiaHitObject> rulesetContainer)
|
||||
{
|
||||
var availableColumns = ((ManiaRulesetContainer)rulesetContainer).Beatmap.TotalColumns;
|
||||
|
||||
rulesetContainer.Objects.OfType<ManiaHitObject>().ForEach(h => h.Column = availableColumns - 1 - h.Column);
|
||||
}
|
||||
}
|
||||
}
|
113
osu.Game.Rulesets.Mania/Objects/ManiaHitObjectDifficulty.cs
Normal file
113
osu.Game.Rulesets.Mania/Objects/ManiaHitObjectDifficulty.cs
Normal file
@ -0,0 +1,113 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using System;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects
|
||||
{
|
||||
internal class ManiaHitObjectDifficulty
|
||||
{
|
||||
/// <summary>
|
||||
/// Factor by how much individual / overall strain decays per second.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// These values are results of tweaking a lot and taking into account general feedback.
|
||||
/// </remarks>
|
||||
internal const double INDIVIDUAL_DECAY_BASE = 0.125;
|
||||
internal const double OVERALL_DECAY_BASE = 0.30;
|
||||
|
||||
internal ManiaHitObject BaseHitObject;
|
||||
|
||||
private readonly int beatmapColumnCount;
|
||||
|
||||
|
||||
private readonly double endTime;
|
||||
private readonly double[] heldUntil;
|
||||
|
||||
/// <summary>
|
||||
/// Measures jacks or more generally: repeated presses of the same button
|
||||
/// </summary>
|
||||
private readonly double[] individualStrains;
|
||||
|
||||
internal double IndividualStrain
|
||||
{
|
||||
get
|
||||
{
|
||||
return individualStrains[BaseHitObject.Column];
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
individualStrains[BaseHitObject.Column] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Measures note density in a way
|
||||
/// </summary>
|
||||
internal double OverallStrain = 1;
|
||||
|
||||
public ManiaHitObjectDifficulty(ManiaHitObject baseHitObject, int columnCount)
|
||||
{
|
||||
BaseHitObject = baseHitObject;
|
||||
|
||||
endTime = (baseHitObject as IHasEndTime)?.EndTime ?? baseHitObject.StartTime;
|
||||
|
||||
beatmapColumnCount = columnCount;
|
||||
heldUntil = new double[beatmapColumnCount];
|
||||
individualStrains = new double[beatmapColumnCount];
|
||||
|
||||
for (int i = 0; i < beatmapColumnCount; ++i)
|
||||
{
|
||||
individualStrains[i] = 0;
|
||||
heldUntil[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
internal void CalculateStrains(ManiaHitObjectDifficulty previousHitObject, double timeRate)
|
||||
{
|
||||
// TODO: Factor in holds
|
||||
double timeElapsed = (BaseHitObject.StartTime - previousHitObject.BaseHitObject.StartTime) / timeRate;
|
||||
double individualDecay = Math.Pow(INDIVIDUAL_DECAY_BASE, timeElapsed / 1000);
|
||||
double overallDecay = Math.Pow(OVERALL_DECAY_BASE, timeElapsed / 1000);
|
||||
|
||||
double holdFactor = 1.0; // Factor to all additional strains in case something else is held
|
||||
double holdAddition = 0; // Addition to the current note in case it's a hold and has to be released awkwardly
|
||||
|
||||
// Fill up the heldUntil array
|
||||
for (int i = 0; i < beatmapColumnCount; ++i)
|
||||
{
|
||||
heldUntil[i] = previousHitObject.heldUntil[i];
|
||||
|
||||
// If there is at least one other overlapping end or note, then we get an addition, buuuuuut...
|
||||
if (BaseHitObject.StartTime < heldUntil[i] && endTime > heldUntil[i])
|
||||
{
|
||||
holdAddition = 1.0;
|
||||
}
|
||||
|
||||
// ... this addition only is valid if there is _no_ other note with the same ending. Releasing multiple notes at the same time is just as easy as releasing 1
|
||||
if (endTime == heldUntil[i])
|
||||
{
|
||||
holdAddition = 0;
|
||||
}
|
||||
|
||||
// We give a slight bonus to everything if something is held meanwhile
|
||||
if (heldUntil[i] > endTime)
|
||||
{
|
||||
holdFactor = 1.25;
|
||||
}
|
||||
|
||||
// Decay individual strains
|
||||
individualStrains[i] = previousHitObject.individualStrains[i] * individualDecay;
|
||||
}
|
||||
|
||||
heldUntil[BaseHitObject.Column] = endTime;
|
||||
|
||||
// Increase individual strain in own column
|
||||
IndividualStrain += 2.0 * holdFactor;
|
||||
|
||||
OverallStrain = previousHitObject.OverallStrain * overallDecay + (1.0 + holdAddition) * holdFactor;
|
||||
}
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
private bool isForCurrentRuleset;
|
||||
|
||||
[NonParallelizable]
|
||||
[TestCase("basic", false), Ignore("See: https://github.com/ppy/osu/issues/2150")]
|
||||
[TestCase("basic", false)]
|
||||
public void Test(string name, bool isForCurrentRuleset)
|
||||
{
|
||||
this.isForCurrentRuleset = isForCurrentRuleset;
|
||||
|
@ -1,17 +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 osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.UI
|
||||
{
|
||||
internal class DrawableManiaJudgement : DrawableJudgement
|
||||
{
|
||||
public DrawableManiaJudgement(Judgement judgement)
|
||||
: base(judgement)
|
||||
public DrawableManiaJudgement(Judgement judgement, DrawableHitObject judgedObject)
|
||||
: base(judgement, judgedObject)
|
||||
{
|
||||
JudgementText.TextSize = 25;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
if (JudgementText != null)
|
||||
JudgementText.TextSize = 25;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
|
@ -15,6 +15,7 @@ using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
@ -40,7 +41,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
private readonly Container<Drawable> content;
|
||||
|
||||
public Container<DrawableManiaJudgement> Judgements => judgements;
|
||||
private readonly Container<DrawableManiaJudgement> judgements;
|
||||
private readonly JudgementContainer<DrawableManiaJudgement> judgements;
|
||||
|
||||
private readonly Container topLevelContainer;
|
||||
|
||||
@ -114,7 +115,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
Padding = new MarginPadding { Top = HIT_TARGET_POSITION }
|
||||
}
|
||||
},
|
||||
judgements = new Container<DrawableManiaJudgement>
|
||||
judgements = new JudgementContainer<DrawableManiaJudgement>
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.Centre,
|
||||
@ -171,7 +172,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
||||
{
|
||||
judgements.Clear();
|
||||
judgements.Add(new DrawableManiaJudgement(judgement)
|
||||
judgements.Add(new DrawableManiaJudgement(judgement, judgedObject)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
|
@ -81,6 +81,7 @@
|
||||
<Compile Include="Judgements\ManiaJudgement.cs" />
|
||||
<Compile Include="ManiaDifficultyCalculator.cs" />
|
||||
<Compile Include="Mods\IPlayfieldTypeMod.cs" />
|
||||
<Compile Include="Mods\ManiaModMirror.cs" />
|
||||
<Compile Include="Mods\ManiaKeyMod.cs" />
|
||||
<Compile Include="Mods\ManiaModAutoplay.cs" />
|
||||
<Compile Include="Mods\ManiaModDaycore.cs" />
|
||||
@ -114,6 +115,7 @@
|
||||
<Compile Include="Objects\Drawables\Pieces\GlowPiece.cs" />
|
||||
<Compile Include="Objects\Drawables\Pieces\LaneGlowPiece.cs" />
|
||||
<Compile Include="Objects\Drawables\Pieces\NotePiece.cs" />
|
||||
<Compile Include="Objects\ManiaHitObjectDifficulty.cs" />
|
||||
<Compile Include="Objects\Types\IHasColumn.cs" />
|
||||
<Compile Include="Replays\ManiaAutoGenerator.cs" />
|
||||
<Compile Include="Replays\ManiaFramedReplayInputHandler.cs" />
|
||||
|
@ -1,26 +0,0 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Edit.Layers.Selection;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Edit.Layers.Selection.Overlays;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Edit.Layers.Selection
|
||||
{
|
||||
public class OsuHitObjectOverlayLayer : HitObjectOverlayLayer
|
||||
{
|
||||
protected override HitObjectOverlay CreateOverlayFor(DrawableHitObject hitObject)
|
||||
{
|
||||
switch (hitObject)
|
||||
{
|
||||
case DrawableHitCircle circle:
|
||||
return new HitCircleOverlay(circle);
|
||||
case DrawableSlider slider:
|
||||
return new SliderOverlay(slider);
|
||||
}
|
||||
|
||||
return base.CreateOverlayFor(hitObject);
|
||||
}
|
||||
}
|
||||
}
|
@ -4,15 +4,15 @@
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Edit.Layers.Selection;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Edit.Layers.Selection.Overlays
|
||||
{
|
||||
public class HitCircleOverlay : HitObjectOverlay
|
||||
public class HitCircleMask : HitObjectMask
|
||||
{
|
||||
public HitCircleOverlay(DrawableHitCircle hitCircle)
|
||||
public HitCircleMask(DrawableHitCircle hitCircle)
|
||||
: base(hitCircle)
|
||||
{
|
||||
Origin = Anchor.Centre;
|
||||
@ -22,6 +22,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Layers.Selection.Overlays
|
||||
Scale = hitCircle.Scale;
|
||||
|
||||
AddInternal(new RingPiece());
|
||||
|
||||
hitCircle.HitObject.PositionChanged += _ => Position = hitCircle.Position;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
@ -4,28 +4,29 @@
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Edit.Layers.Selection;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Edit.Layers.Selection.Overlays
|
||||
{
|
||||
public class SliderCircleOverlay : HitObjectOverlay
|
||||
public class SliderCircleMask : HitObjectMask
|
||||
{
|
||||
public SliderCircleOverlay(DrawableHitCircle sliderHead, DrawableSlider slider)
|
||||
: this(sliderHead, sliderHead.Position, slider)
|
||||
public SliderCircleMask(DrawableHitCircle sliderHead, DrawableSlider slider)
|
||||
: this(sliderHead, Vector2.Zero, slider)
|
||||
{
|
||||
}
|
||||
|
||||
public SliderCircleOverlay(DrawableSliderTail sliderTail, DrawableSlider slider)
|
||||
: this(sliderTail, sliderTail.Position, slider)
|
||||
public SliderCircleMask(DrawableSliderTail sliderTail, DrawableSlider slider)
|
||||
: this(sliderTail, ((Slider)slider.HitObject).Curve.PositionAt(1), slider)
|
||||
{
|
||||
}
|
||||
|
||||
private readonly DrawableOsuHitObject hitObject;
|
||||
|
||||
private SliderCircleOverlay(DrawableOsuHitObject hitObject, Vector2 position, DrawableSlider slider)
|
||||
private SliderCircleMask(DrawableOsuHitObject hitObject, Vector2 position, DrawableSlider slider)
|
||||
: base(hitObject)
|
||||
{
|
||||
this.hitObject = hitObject;
|
@ -4,36 +4,41 @@
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Edit.Layers.Selection;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Edit.Layers.Selection.Overlays
|
||||
{
|
||||
public class SliderOverlay : HitObjectOverlay
|
||||
public class SliderMask : HitObjectMask
|
||||
{
|
||||
private readonly SliderBody body;
|
||||
private readonly DrawableSlider slider;
|
||||
|
||||
public SliderOverlay(DrawableSlider slider)
|
||||
public SliderMask(DrawableSlider slider)
|
||||
: base(slider)
|
||||
{
|
||||
this.slider = slider;
|
||||
|
||||
var obj = (Slider)slider.HitObject;
|
||||
Position = slider.Position;
|
||||
|
||||
var sliderObject = (Slider)slider.HitObject;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
body = new SliderBody(obj)
|
||||
body = new SliderBody(sliderObject)
|
||||
{
|
||||
AccentColour = Color4.Transparent,
|
||||
PathWidth = obj.Scale * 64
|
||||
PathWidth = sliderObject.Scale * 64
|
||||
},
|
||||
new SliderCircleOverlay(slider.HeadCircle, slider),
|
||||
new SliderCircleOverlay(slider.TailCircle, slider),
|
||||
new SliderCircleMask(slider.HeadCircle, slider),
|
||||
new SliderCircleMask(slider.TailCircle, slider),
|
||||
};
|
||||
|
||||
sliderObject.PositionChanged += _ => Position = slider.Position;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -46,12 +51,13 @@ namespace osu.Game.Rulesets.Osu.Edit.Layers.Selection.Overlays
|
||||
{
|
||||
base.Update();
|
||||
|
||||
Position = slider.Position;
|
||||
Size = slider.Size;
|
||||
OriginPosition = slider.OriginPosition;
|
||||
|
||||
// Need to cause one update
|
||||
body.UpdateProgress(0);
|
||||
}
|
||||
|
||||
public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => body.ReceiveMouseInputAt(screenSpacePos);
|
||||
}
|
||||
}
|
@ -5,10 +5,11 @@ using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Layers.Selection;
|
||||
using osu.Game.Rulesets.Edit.Tools;
|
||||
using osu.Game.Rulesets.Osu.Edit.Layers.Selection;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Edit.Layers.Selection.Overlays;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
@ -32,6 +33,17 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
|
||||
protected override ScalableContainer CreateLayerContainer() => new ScalableContainer(OsuPlayfield.BASE_SIZE.X) { RelativeSizeAxes = Axes.Both };
|
||||
|
||||
protected override HitObjectOverlayLayer CreateHitObjectOverlayLayer() => new OsuHitObjectOverlayLayer();
|
||||
public override HitObjectMask CreateMaskFor(DrawableHitObject hitObject)
|
||||
{
|
||||
switch (hitObject)
|
||||
{
|
||||
case DrawableHitCircle circle:
|
||||
return new HitCircleMask(circle);
|
||||
case DrawableSlider slider:
|
||||
return new SliderMask(slider);
|
||||
}
|
||||
|
||||
return base.CreateMaskFor(hitObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -66,6 +66,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
//may not be so correct
|
||||
Size = circle.DrawSize;
|
||||
|
||||
HitObject.PositionChanged += _ => Position = HitObject.StackedPosition;
|
||||
}
|
||||
|
||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||
|
@ -2,24 +2,24 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Osu.Judgements;
|
||||
using OpenTK;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
public class DrawableOsuJudgement : DrawableJudgement
|
||||
{
|
||||
public DrawableOsuJudgement(OsuJudgement judgement)
|
||||
: base(judgement)
|
||||
public DrawableOsuJudgement(Judgement judgement, DrawableHitObject judgedObject)
|
||||
: base(judgement, judgedObject)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
if (Judgement.Result != HitResult.Miss)
|
||||
JudgementText.TransformSpacingTo(new Vector2(14, 0), 1800, Easing.OutQuint);
|
||||
JudgementText?.TransformSpacingTo(new Vector2(14, 0), 1800, Easing.OutQuint);
|
||||
|
||||
base.LoadComplete();
|
||||
}
|
||||
|
@ -83,6 +83,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
components.Add(drawableRepeatPoint);
|
||||
AddNested(drawableRepeatPoint);
|
||||
}
|
||||
|
||||
HitObject.PositionChanged += _ => Position = HitObject.StackedPosition;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Skinning;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
@ -19,15 +20,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
Blending = BlendingMode.Additive;
|
||||
Alpha = 0;
|
||||
|
||||
Children = new Drawable[]
|
||||
Child = new SkinnableDrawable("Play/osu/hitcircle-explode", _ => new TrianglesPiece
|
||||
{
|
||||
new TrianglesPiece
|
||||
{
|
||||
Blending = BlendingMode.Additive,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0.2f,
|
||||
}
|
||||
};
|
||||
Blending = BlendingMode.Additive,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0.2f,
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using OpenTK;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
@ -14,22 +15,21 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
Size = new Vector2(128);
|
||||
|
||||
Masking = true;
|
||||
CornerRadius = Size.X / 2;
|
||||
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
Blending = BlendingMode.Additive;
|
||||
Alpha = 0;
|
||||
|
||||
Children = new Drawable[]
|
||||
Child = new SkinnableDrawable("Play/osu/hitcircle-flash", name => new CircularContainer
|
||||
{
|
||||
new Box
|
||||
Masking = true,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
}
|
||||
};
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,41 @@
|
||||
// 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 osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using OpenTK;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Edit.Types;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects
|
||||
{
|
||||
public abstract class OsuHitObject : HitObject, IHasCombo, IHasPosition
|
||||
public abstract class OsuHitObject : HitObject, IHasCombo, IHasEditablePosition
|
||||
{
|
||||
public const double OBJECT_RADIUS = 64;
|
||||
|
||||
public event Action<Vector2> PositionChanged;
|
||||
|
||||
public double TimePreempt = 600;
|
||||
public double TimeFadein = 400;
|
||||
|
||||
public Vector2 Position { get; set; }
|
||||
private Vector2 position;
|
||||
|
||||
public Vector2 Position
|
||||
{
|
||||
get => position;
|
||||
set
|
||||
{
|
||||
if (position == value)
|
||||
return;
|
||||
position = value;
|
||||
|
||||
PositionChanged?.Invoke(value);
|
||||
}
|
||||
}
|
||||
|
||||
public float X => Position.X;
|
||||
public float Y => Position.Y;
|
||||
|
||||
@ -48,5 +66,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
|
||||
Scale = (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5) / 2;
|
||||
}
|
||||
|
||||
public virtual void OffsetPosition(Vector2 offset) => Position += offset;
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
|
||||
private void createSliderEnds()
|
||||
{
|
||||
HeadCircle = new HitCircle
|
||||
HeadCircle = new SliderCircle(this)
|
||||
{
|
||||
StartTime = StartTime,
|
||||
Position = Position,
|
||||
@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
SampleControlPoint = SampleControlPoint
|
||||
};
|
||||
|
||||
TailCircle = new HitCircle
|
||||
TailCircle = new SliderCircle(this)
|
||||
{
|
||||
StartTime = EndTime,
|
||||
Position = EndPosition,
|
||||
|
19
osu.Game.Rulesets.Osu/Objects/SliderCircle.cs
Normal file
19
osu.Game.Rulesets.Osu/Objects/SliderCircle.cs
Normal file
@ -0,0 +1,19 @@
|
||||
// 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.Rulesets.Osu.Objects
|
||||
{
|
||||
public class SliderCircle : HitCircle
|
||||
{
|
||||
private readonly Slider slider;
|
||||
|
||||
public SliderCircle(Slider slider)
|
||||
{
|
||||
this.slider = slider;
|
||||
}
|
||||
|
||||
public override void OffsetPosition(Vector2 offset) => slider.OffsetPosition(offset);
|
||||
}
|
||||
}
|
17
osu.Game.Rulesets.Osu/Tests/TestCaseEditor.cs
Normal file
17
osu.Game.Rulesets.Osu/Tests/TestCaseEditor.cs
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseEditor : EditorTestCase
|
||||
{
|
||||
public TestCaseEditor()
|
||||
: base(new OsuRuleset())
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
public class OsuPlayfield : Playfield
|
||||
{
|
||||
private readonly Container approachCircles;
|
||||
private readonly Container judgementLayer;
|
||||
private readonly JudgementContainer<DrawableOsuJudgement> judgementLayer;
|
||||
private readonly ConnectionRenderer<OsuHitObject> connectionLayer;
|
||||
|
||||
// Todo: This should not be a thing, but is currently required for the editor
|
||||
@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Depth = 2,
|
||||
},
|
||||
judgementLayer = new Container
|
||||
judgementLayer = new JudgementContainer<DrawableOsuJudgement>
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Depth = 1,
|
||||
@ -75,16 +75,13 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
|
||||
private void onJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
||||
{
|
||||
var osuJudgement = (OsuJudgement)judgement;
|
||||
var osuObject = (OsuHitObject)judgedObject.HitObject;
|
||||
|
||||
if (!judgedObject.DisplayJudgement)
|
||||
return;
|
||||
|
||||
DrawableOsuJudgement explosion = new DrawableOsuJudgement(osuJudgement)
|
||||
DrawableOsuJudgement explosion = new DrawableOsuJudgement(judgement, judgedObject)
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Position = osuObject.StackedEndPosition + osuJudgement.PositionOffset
|
||||
Position = ((OsuHitObject)judgedObject.HitObject).StackedEndPosition + ((OsuJudgement)judgement).PositionOffset
|
||||
};
|
||||
|
||||
judgementLayer.Add(explosion);
|
||||
|
@ -64,10 +64,9 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="Beatmaps\OsuBeatmapConverter.cs" />
|
||||
<Compile Include="Beatmaps\OsuBeatmapProcessor.cs" />
|
||||
<Compile Include="Edit\Layers\Selection\OsuHitObjectOverlayLayer.cs" />
|
||||
<Compile Include="Edit\Layers\Selection\Overlays\HitCircleOverlay.cs" />
|
||||
<Compile Include="Edit\Layers\Selection\Overlays\SliderCircleOverlay.cs" />
|
||||
<Compile Include="Edit\Layers\Selection\Overlays\SliderOverlay.cs" />
|
||||
<Compile Include="Edit\Layers\Selection\Overlays\HitCircleMask.cs" />
|
||||
<Compile Include="Edit\Layers\Selection\Overlays\SliderCircleMask.cs" />
|
||||
<Compile Include="Edit\Layers\Selection\Overlays\SliderMask.cs" />
|
||||
<Compile Include="Edit\OsuEditPlayfield.cs" />
|
||||
<Compile Include="Edit\OsuEditRulesetContainer.cs" />
|
||||
<Compile Include="Edit\OsuHitObjectComposer.cs" />
|
||||
@ -118,6 +117,7 @@
|
||||
<Compile Include="Objects\Drawables\Pieces\SliderBody.cs" />
|
||||
<Compile Include="Objects\ISliderProgress.cs" />
|
||||
<Compile Include="Objects\RepeatPoint.cs" />
|
||||
<Compile Include="Objects\SliderCircle.cs" />
|
||||
<Compile Include="Objects\SliderTick.cs" />
|
||||
<Compile Include="OsuDifficulty\OsuDifficultyCalculator.cs" />
|
||||
<Compile Include="OsuDifficulty\Preprocessing\OsuDifficultyBeatmap.cs" />
|
||||
@ -130,6 +130,7 @@
|
||||
<Compile Include="Replays\OsuReplayFrame.cs" />
|
||||
<Compile Include="Replays\OsuReplayInputHandler.cs" />
|
||||
<Compile Include="Tests\OsuBeatmapConversionTest.cs" />
|
||||
<Compile Include="Tests\TestCaseEditor.cs" />
|
||||
<Compile Include="Tests\TestCaseHitCircle.cs" />
|
||||
<Compile Include="Tests\TestCaseHitCircleHidden.cs" />
|
||||
<Compile Include="Tests\TestCasePerformancePoints.cs" />
|
||||
|
@ -15,17 +15,14 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
/// </summary>
|
||||
public class DrawableTaikoJudgement : DrawableJudgement
|
||||
{
|
||||
public readonly DrawableHitObject JudgedObject;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new judgement text.
|
||||
/// </summary>
|
||||
/// <param name="judgedObject">The object which is being judged.</param>
|
||||
/// <param name="judgement">The judgement to visualise.</param>
|
||||
public DrawableTaikoJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
||||
: base(judgement)
|
||||
public DrawableTaikoJudgement(Judgement judgement, DrawableHitObject judgedObject)
|
||||
: base(judgement, judgedObject)
|
||||
{
|
||||
JudgedObject = judgedObject;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
|
@ -16,6 +16,7 @@ using System.Linq;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Taiko.Objects.Drawables;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.UI
|
||||
@ -41,7 +42,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
|
||||
private readonly Container<HitExplosion> hitExplosionContainer;
|
||||
private readonly Container<KiaiHitExplosion> kiaiExplosionContainer;
|
||||
private readonly Container<DrawableTaikoJudgement> judgementContainer;
|
||||
private readonly JudgementContainer<DrawableTaikoJudgement> judgementContainer;
|
||||
|
||||
protected override Container<Drawable> Content => content;
|
||||
private readonly Container content;
|
||||
@ -131,7 +132,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
Margin = new MarginPadding { Left = HIT_TARGET_OFFSET },
|
||||
Blending = BlendingMode.Additive
|
||||
},
|
||||
judgementContainer = new Container<DrawableTaikoJudgement>
|
||||
judgementContainer = new JudgementContainer<DrawableTaikoJudgement>
|
||||
{
|
||||
Name = "Judgements",
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
@ -227,7 +228,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
{
|
||||
if (judgedObject.DisplayJudgement && judgementContainer.FirstOrDefault(j => j.JudgedObject == judgedObject) == null)
|
||||
{
|
||||
judgementContainer.Add(new DrawableTaikoJudgement(judgedObject, judgement)
|
||||
judgementContainer.Add(new DrawableTaikoJudgement(judgement, judgedObject)
|
||||
{
|
||||
Anchor = judgement.IsHit ? Anchor.TopLeft : Anchor.CentreLeft,
|
||||
Origin = judgement.IsHit ? Anchor.BottomCentre : Anchor.Centre,
|
||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||
using (var stream = new StreamReader(resStream))
|
||||
{
|
||||
var beatmap = decoder.DecodeBeatmap(stream);
|
||||
var beatmap = decoder.Decode(stream);
|
||||
var beatmapInfo = beatmap.BeatmapInfo;
|
||||
var metadata = beatmap.Metadata;
|
||||
|
||||
@ -47,7 +47,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||
using (var stream = new StreamReader(resStream))
|
||||
{
|
||||
var beatmapInfo = decoder.DecodeBeatmap(stream).BeatmapInfo;
|
||||
var beatmapInfo = decoder.Decode(stream).BeatmapInfo;
|
||||
|
||||
int[] expectedBookmarks =
|
||||
{
|
||||
@ -72,7 +72,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||
using (var stream = new StreamReader(resStream))
|
||||
{
|
||||
var beatmap = decoder.DecodeBeatmap(stream);
|
||||
var beatmap = decoder.Decode(stream);
|
||||
var beatmapInfo = beatmap.BeatmapInfo;
|
||||
var metadata = beatmap.Metadata;
|
||||
|
||||
@ -96,7 +96,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||
using (var stream = new StreamReader(resStream))
|
||||
{
|
||||
var difficulty = decoder.DecodeBeatmap(stream).BeatmapInfo.BaseDifficulty;
|
||||
var difficulty = decoder.Decode(stream).BeatmapInfo.BaseDifficulty;
|
||||
|
||||
Assert.AreEqual(6.5f, difficulty.DrainRate);
|
||||
Assert.AreEqual(4, difficulty.CircleSize);
|
||||
@ -114,7 +114,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||
using (var stream = new StreamReader(resStream))
|
||||
{
|
||||
var beatmap = decoder.DecodeBeatmap(stream);
|
||||
var beatmap = decoder.Decode(stream);
|
||||
var metadata = beatmap.Metadata;
|
||||
var breakPoint = beatmap.Breaks[0];
|
||||
|
||||
@ -132,7 +132,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||
using (var stream = new StreamReader(resStream))
|
||||
{
|
||||
var beatmap = decoder.DecodeBeatmap(stream);
|
||||
var beatmap = decoder.Decode(stream);
|
||||
var controlPoints = beatmap.ControlPointInfo;
|
||||
|
||||
Assert.AreEqual(4, controlPoints.TimingPoints.Count);
|
||||
@ -167,7 +167,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||
using (var stream = new StreamReader(resStream))
|
||||
{
|
||||
var comboColors = decoder.DecodeBeatmap(stream).ComboColors;
|
||||
var comboColors = decoder.Decode(stream).ComboColors;
|
||||
|
||||
Color4[] expectedColors =
|
||||
{
|
||||
@ -191,7 +191,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||
using (var stream = new StreamReader(resStream))
|
||||
{
|
||||
var hitObjects = decoder.DecodeBeatmap(stream).HitObjects;
|
||||
var hitObjects = decoder.Decode(stream).HitObjects;
|
||||
|
||||
var curveData = hitObjects[0] as IHasCurve;
|
||||
var positionData = hitObjects[0] as IHasPosition;
|
||||
|
@ -18,11 +18,11 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
[Test]
|
||||
public void TestDecodeStoryboardEvents()
|
||||
{
|
||||
var decoder = new LegacyBeatmapDecoder();
|
||||
var decoder = new LegacyStoryboardDecoder();
|
||||
using (var resStream = Resource.OpenResource("Himeringo - Yotsuya-san ni Yoroshiku (RLC) [Winber1's Extreme].osu"))
|
||||
using (var stream = new StreamReader(resStream))
|
||||
{
|
||||
var storyboard = decoder.GetStoryboardDecoder().DecodeStoryboard(stream);
|
||||
var storyboard = decoder.Decode(stream);
|
||||
|
||||
Assert.IsTrue(storyboard.HasDrawable);
|
||||
Assert.AreEqual(4, storyboard.Layers.Count());
|
||||
|
@ -159,7 +159,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
using (var sr = new StreamReader(stream))
|
||||
{
|
||||
|
||||
var legacyDecoded = new LegacyBeatmapDecoder { ApplyOffsets = false }.DecodeBeatmap(sr);
|
||||
var legacyDecoded = new LegacyBeatmapDecoder { ApplyOffsets = false }.Decode(sr);
|
||||
using (var ms = new MemoryStream())
|
||||
using (var sw = new StreamWriter(ms))
|
||||
using (var sr2 = new StreamReader(ms))
|
||||
@ -168,7 +168,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
sw.Flush();
|
||||
|
||||
ms.Position = 0;
|
||||
return (legacyDecoded, new JsonBeatmapDecoder().DecodeBeatmap(sr2));
|
||||
return (legacyDecoded, new JsonBeatmapDecoder().Decode(sr2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
|
||||
BeatmapMetadata meta;
|
||||
using (var stream = new StreamReader(reader.GetStream("Soleily - Renatus (Deif) [Platter].osu")))
|
||||
meta = Decoder.GetDecoder(stream).DecodeBeatmap(stream).Metadata;
|
||||
meta = Decoder.GetDecoder<Beatmap>(stream).Decode(stream).Metadata;
|
||||
|
||||
Assert.AreEqual(241526, meta.OnlineBeatmapSetID);
|
||||
Assert.AreEqual("Soleily", meta.Artist);
|
||||
|
@ -12,6 +12,7 @@ using osu.Framework.Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Screens.Select.Carousel;
|
||||
using osu.Game.Screens.Select.Filter;
|
||||
@ -22,6 +23,7 @@ namespace osu.Game.Tests.Visual
|
||||
public class TestCaseBeatmapCarousel : OsuTestCase
|
||||
{
|
||||
private TestBeatmapCarousel carousel;
|
||||
private RulesetStore rulesets;
|
||||
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
@ -46,8 +48,10 @@ namespace osu.Game.Tests.Visual
|
||||
private const int set_count = 5;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
private void load(RulesetStore rulesets)
|
||||
{
|
||||
this.rulesets = rulesets;
|
||||
|
||||
Add(carousel = new TestBeatmapCarousel
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
@ -75,6 +79,7 @@ namespace osu.Game.Tests.Visual
|
||||
testRemoveAll();
|
||||
testEmptyTraversal();
|
||||
testHiding();
|
||||
testSelectingFilteredRuleset();
|
||||
}
|
||||
|
||||
private void ensureRandomFetchSuccess() =>
|
||||
@ -363,6 +368,41 @@ namespace osu.Game.Tests.Visual
|
||||
}
|
||||
}
|
||||
|
||||
private void testSelectingFilteredRuleset()
|
||||
{
|
||||
var testMixed = createTestBeatmapSet(set_count + 1);
|
||||
AddStep("add mixed ruleset beatmapset", () =>
|
||||
{
|
||||
for (int i = 0; i <= 2; i++)
|
||||
{
|
||||
testMixed.Beatmaps[i].Ruleset = rulesets.AvailableRulesets.ElementAt(i);
|
||||
testMixed.Beatmaps[i].RulesetID = i;
|
||||
}
|
||||
|
||||
carousel.UpdateBeatmapSet(testMixed);
|
||||
});
|
||||
AddStep("filter to ruleset 0", () =>
|
||||
carousel.Filter(new FilterCriteria { Ruleset = rulesets.AvailableRulesets.ElementAt(0) }, false));
|
||||
AddStep("select filtered map skipping filtered", () => carousel.SelectBeatmap(testMixed.Beatmaps[1], false));
|
||||
AddAssert("unfiltered beatmap selected", () => carousel.SelectedBeatmap.Equals(testMixed.Beatmaps[0]));
|
||||
|
||||
AddStep("remove mixed set", () =>
|
||||
{
|
||||
carousel.RemoveBeatmapSet(testMixed);
|
||||
testMixed = null;
|
||||
});
|
||||
var testSingle = createTestBeatmapSet(set_count + 2);
|
||||
testSingle.Beatmaps.ForEach(b =>
|
||||
{
|
||||
b.Ruleset = rulesets.AvailableRulesets.ElementAt(1);
|
||||
b.RulesetID = b.Ruleset.ID ?? 1;
|
||||
});
|
||||
AddStep("add single ruleset beatmapset", () => carousel.UpdateBeatmapSet(testSingle));
|
||||
AddStep("select filtered map skipping filtered", () => carousel.SelectBeatmap(testSingle.Beatmaps[0], false));
|
||||
checkNoSelection();
|
||||
AddStep("remove single ruleset set", () => carousel.RemoveBeatmapSet(testSingle));
|
||||
}
|
||||
|
||||
private BeatmapSetInfo createTestBeatmapSet(int id)
|
||||
{
|
||||
return new BeatmapSetInfo
|
||||
|
@ -3,9 +3,9 @@
|
||||
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps.Timing;
|
||||
using osu.Game.Screens.Play.BreaksOverlay;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
|
@ -1,49 +0,0 @@
|
||||
// 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 NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Screens.Edit;
|
||||
using osu.Game.Screens.Edit.Screens;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseEditor : OsuTestCase
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(Editor), typeof(EditorScreen) };
|
||||
|
||||
private readonly Random rng;
|
||||
|
||||
private BeatmapManager beatmaps;
|
||||
private OsuGameBase osuGame;
|
||||
|
||||
public TestCaseEditor()
|
||||
{
|
||||
rng = new Random(1337);
|
||||
|
||||
Add(new Editor());
|
||||
AddStep("Next beatmap", nextBeatmap);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuGameBase osuGame, BeatmapManager beatmaps)
|
||||
{
|
||||
this.osuGame = osuGame;
|
||||
this.beatmaps = beatmaps;
|
||||
}
|
||||
|
||||
private void nextBeatmap()
|
||||
{
|
||||
var sets = beatmaps.GetAllUsableBeatmapSets();
|
||||
if (sets.Count == 0)
|
||||
return;
|
||||
|
||||
BeatmapInfo info = sets[rng.Next(0, sets.Count)].Beatmaps[0];
|
||||
osuGame.Beatmap.Value = beatmaps.GetWorkingBeatmap(info);
|
||||
}
|
||||
}
|
||||
}
|
@ -8,13 +8,12 @@ using osu.Framework.Allocation;
|
||||
using OpenTK;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Layers.Selection;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Edit;
|
||||
using osu.Game.Rulesets.Osu.Edit.Layers.Selection;
|
||||
using osu.Game.Rulesets.Osu.Edit.Layers.Selection.Overlays;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Screens.Edit.Screens.Compose.Layers;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
@ -24,17 +23,15 @@ namespace osu.Game.Tests.Visual
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(SelectionBox),
|
||||
typeof(SelectionLayer),
|
||||
typeof(CaptureBox),
|
||||
typeof(SelectionBox),
|
||||
typeof(HitObjectComposer),
|
||||
typeof(OsuHitObjectComposer),
|
||||
typeof(HitObjectOverlayLayer),
|
||||
typeof(OsuHitObjectOverlayLayer),
|
||||
typeof(HitObjectOverlay),
|
||||
typeof(HitCircleOverlay),
|
||||
typeof(SliderOverlay),
|
||||
typeof(SliderCircleOverlay)
|
||||
typeof(HitObjectMaskLayer),
|
||||
typeof(HitObjectMask),
|
||||
typeof(HitCircleMask),
|
||||
typeof(SliderMask),
|
||||
typeof(SliderCircleMask)
|
||||
};
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
|
@ -58,6 +58,12 @@ namespace osu.Game.Tests.Visual
|
||||
|
||||
checkSupporterTag(false);
|
||||
|
||||
AddStep("Show null dummy", () => profile.ShowUser(new User
|
||||
{
|
||||
Username = @"Null",
|
||||
Id = 1,
|
||||
}, false));
|
||||
|
||||
AddStep("Show ppy", () => profile.ShowUser(new User
|
||||
{
|
||||
Username = @"peppy",
|
||||
|
@ -126,7 +126,6 @@
|
||||
<Compile Include="Visual\TestCaseDirect.cs" />
|
||||
<Compile Include="Visual\TestCaseDrawableRoom.cs" />
|
||||
<Compile Include="Visual\TestCaseDrawings.cs" />
|
||||
<Compile Include="Visual\TestCaseEditor.cs" />
|
||||
<Compile Include="Visual\TestCaseEditorCompose.cs" />
|
||||
<Compile Include="Visual\TestCaseEditorComposeRadioButtons.cs" />
|
||||
<Compile Include="Visual\TestCaseEditorComposeTimeline.cs" />
|
||||
|
@ -22,6 +22,7 @@ namespace osu.Game.Beatmaps
|
||||
public BeatmapInfo BeatmapInfo = new BeatmapInfo();
|
||||
public ControlPointInfo ControlPointInfo = new ControlPointInfo();
|
||||
public List<BreakPeriod> Breaks = new List<BreakPeriod>();
|
||||
|
||||
public List<Color4> ComboColors = new List<Color4>
|
||||
{
|
||||
new Color4(17, 136, 170, 255),
|
||||
@ -85,9 +86,13 @@ namespace osu.Game.Beatmaps
|
||||
/// Constructs a new beatmap.
|
||||
/// </summary>
|
||||
/// <param name="original">The original beatmap to use the parameters of.</param>
|
||||
public Beatmap(Beatmap original = null)
|
||||
public Beatmap(Beatmap original)
|
||||
: base(original)
|
||||
{
|
||||
}
|
||||
|
||||
public Beatmap()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -301,7 +301,7 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
BeatmapMetadata metadata;
|
||||
using (var stream = new StreamReader(reader.GetStream(mapName)))
|
||||
metadata = Decoder.GetDecoder(stream).DecodeBeatmap(stream).Metadata;
|
||||
metadata = Decoder.GetDecoder<Beatmap>(stream).Decode(stream).Metadata;
|
||||
|
||||
return new BeatmapSetInfo
|
||||
{
|
||||
@ -328,8 +328,8 @@ namespace osu.Game.Beatmaps
|
||||
raw.CopyTo(ms);
|
||||
ms.Position = 0;
|
||||
|
||||
var decoder = Decoder.GetDecoder(sr);
|
||||
Beatmap beatmap = decoder.DecodeBeatmap(sr);
|
||||
var decoder = Decoder.GetDecoder<Beatmap>(sr);
|
||||
Beatmap beatmap = decoder.Decode(sr);
|
||||
|
||||
beatmap.BeatmapInfo.Path = name;
|
||||
beatmap.BeatmapInfo.Hash = ms.ComputeSHA2Hash();
|
||||
|
@ -7,6 +7,7 @@ using System.Linq;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.IO.Stores;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Beatmaps.Formats;
|
||||
using osu.Game.Graphics.Textures;
|
||||
using osu.Game.Storyboards;
|
||||
@ -30,10 +31,7 @@ namespace osu.Game.Beatmaps
|
||||
try
|
||||
{
|
||||
using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo.Path))))
|
||||
{
|
||||
Decoder decoder = Decoder.GetDecoder(stream);
|
||||
return decoder.DecodeBeatmap(stream);
|
||||
}
|
||||
return Decoder.GetDecoder<Beatmap>(stream).Decode(stream);
|
||||
}
|
||||
catch
|
||||
{
|
||||
@ -78,23 +76,23 @@ namespace osu.Game.Beatmaps
|
||||
Storyboard storyboard;
|
||||
try
|
||||
{
|
||||
using (var beatmap = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo.Path))))
|
||||
using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo.Path))))
|
||||
{
|
||||
Decoder decoder = Decoder.GetDecoder(beatmap);
|
||||
var decoder = Decoder.GetDecoder<Storyboard>(stream);
|
||||
|
||||
// todo: support loading from both set-wide storyboard *and* beatmap specific.
|
||||
|
||||
if (BeatmapSetInfo?.StoryboardFile == null)
|
||||
storyboard = decoder.GetStoryboardDecoder().DecodeStoryboard(beatmap);
|
||||
storyboard = decoder.Decode(stream);
|
||||
else
|
||||
{
|
||||
using (var reader = new StreamReader(store.GetStream(getPathForFile(BeatmapSetInfo.StoryboardFile))))
|
||||
storyboard = decoder.GetStoryboardDecoder().DecodeStoryboard(beatmap, reader);
|
||||
using (var secondaryStream = new StreamReader(store.GetStream(getPathForFile(BeatmapSetInfo.StoryboardFile))))
|
||||
storyboard = decoder.Decode(stream, secondaryStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error(e, "Storyboard failed to load");
|
||||
storyboard = new Storyboard();
|
||||
}
|
||||
|
||||
|
@ -24,9 +24,15 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
protected DifficultyCalculator(Beatmap beatmap, Mod[] mods = null)
|
||||
{
|
||||
Beatmap = CreateBeatmapConverter(beatmap).Convert(beatmap);
|
||||
Mods = mods ?? new Mod[0];
|
||||
|
||||
var converter = CreateBeatmapConverter(beatmap);
|
||||
|
||||
foreach (var mod in Mods.OfType<IApplicableToBeatmapConverter<T>>())
|
||||
mod.ApplyToBeatmapConverter(converter);
|
||||
|
||||
Beatmap = converter.Convert(beatmap);
|
||||
|
||||
ApplyMods(Mods);
|
||||
|
||||
PreprocessHitObjects();
|
||||
|
@ -4,38 +4,64 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using osu.Game.Storyboards;
|
||||
using System.Linq;
|
||||
|
||||
namespace osu.Game.Beatmaps.Formats
|
||||
{
|
||||
public abstract class Decoder<TOutput> : Decoder
|
||||
where TOutput : new()
|
||||
{
|
||||
protected virtual TOutput CreateTemplateObject() => new TOutput();
|
||||
|
||||
public TOutput Decode(StreamReader primaryStream, params StreamReader[] otherStreams)
|
||||
{
|
||||
var output = CreateTemplateObject();
|
||||
foreach (StreamReader stream in new[] { primaryStream }.Concat(otherStreams))
|
||||
ParseStreamInto(stream, output);
|
||||
return output;
|
||||
}
|
||||
|
||||
protected abstract void ParseStreamInto(StreamReader stream, TOutput beatmap);
|
||||
}
|
||||
|
||||
public abstract class Decoder
|
||||
{
|
||||
private static readonly Dictionary<string, Func<string, Decoder>> decoders = new Dictionary<string, Func<string, Decoder>>();
|
||||
private static readonly Dictionary<Type, Dictionary<string, Func<string, Decoder>>> decoders = new Dictionary<Type, Dictionary<string, Func<string, Decoder>>>();
|
||||
|
||||
static Decoder()
|
||||
{
|
||||
LegacyDecoder.Register();
|
||||
LegacyBeatmapDecoder.Register();
|
||||
JsonBeatmapDecoder.Register();
|
||||
LegacyStoryboardDecoder.Register();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a <see cref="Decoder"/> to parse a <see cref="Beatmap"/>.
|
||||
/// </summary>
|
||||
/// <param name="stream">A stream pointing to the <see cref="Beatmap"/>.</param>
|
||||
public static Decoder GetDecoder(StreamReader stream)
|
||||
public static Decoder<T> GetDecoder<T>(StreamReader stream)
|
||||
where T : new()
|
||||
{
|
||||
if (stream == null)
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
|
||||
if (!decoders.TryGetValue(typeof(T), out var typedDecoders))
|
||||
throw new IOException(@"Unknown decoder type");
|
||||
|
||||
string line;
|
||||
do
|
||||
{ line = stream.ReadLine()?.Trim(); }
|
||||
while (line != null && line.Length == 0);
|
||||
{
|
||||
line = stream.ReadLine()?.Trim();
|
||||
} while (line != null && line.Length == 0);
|
||||
|
||||
if (line == null || !decoders.ContainsKey(line))
|
||||
if (line == null)
|
||||
throw new IOException(@"Unknown file format");
|
||||
|
||||
return decoders[line](line);
|
||||
var decoder = typedDecoders.Select(d => line.StartsWith(d.Key) ? d.Value : null).FirstOrDefault();
|
||||
if (decoder == null)
|
||||
throw new IOException(@"Unknown file format");
|
||||
|
||||
return (Decoder<T>)decoder.Invoke(line);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -43,41 +69,12 @@ namespace osu.Game.Beatmaps.Formats
|
||||
/// </summary>
|
||||
/// <param name="magic">A string in the file which triggers this decoder to be used.</param>
|
||||
/// <param name="constructor">A function which constructs the <see cref="Decoder"/> given <paramref name="magic"/>.</param>
|
||||
protected static void AddDecoder(string magic, Func<string, Decoder> constructor)
|
||||
protected static void AddDecoder<T>(string magic, Func<string, Decoder> constructor)
|
||||
{
|
||||
decoders[magic] = constructor;
|
||||
if (!decoders.TryGetValue(typeof(T), out var typedDecoders))
|
||||
decoders.Add(typeof(T), typedDecoders = new Dictionary<string, Func<string, Decoder>>());
|
||||
|
||||
typedDecoders[magic] = constructor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a <see cref="Decoder"/> to parse a <see cref="Storyboard"/>
|
||||
/// </summary>
|
||||
public abstract Decoder GetStoryboardDecoder();
|
||||
|
||||
public virtual Beatmap DecodeBeatmap(StreamReader stream)
|
||||
{
|
||||
var beatmap = new Beatmap
|
||||
{
|
||||
BeatmapInfo = new BeatmapInfo
|
||||
{
|
||||
Metadata = new BeatmapMetadata(),
|
||||
BaseDifficulty = new BeatmapDifficulty(),
|
||||
},
|
||||
};
|
||||
|
||||
ParseBeatmap(stream, beatmap);
|
||||
return beatmap;
|
||||
}
|
||||
|
||||
protected abstract void ParseBeatmap(StreamReader stream, Beatmap beatmap);
|
||||
|
||||
public virtual Storyboard DecodeStoryboard(params StreamReader[] streams)
|
||||
{
|
||||
var storyboard = new Storyboard();
|
||||
foreach (StreamReader stream in streams)
|
||||
ParseStoryboard(stream, storyboard);
|
||||
return storyboard;
|
||||
}
|
||||
|
||||
protected abstract void ParseStoryboard(StreamReader stream, Storyboard storyboard);
|
||||
}
|
||||
}
|
||||
|
@ -3,20 +3,17 @@
|
||||
|
||||
using System.IO;
|
||||
using osu.Game.IO.Serialization;
|
||||
using osu.Game.Storyboards;
|
||||
|
||||
namespace osu.Game.Beatmaps.Formats
|
||||
{
|
||||
public class JsonBeatmapDecoder : Decoder
|
||||
public class JsonBeatmapDecoder : Decoder<Beatmap>
|
||||
{
|
||||
public static void Register()
|
||||
{
|
||||
AddDecoder("{", m => new JsonBeatmapDecoder());
|
||||
AddDecoder<Beatmap>("{", m => new JsonBeatmapDecoder());
|
||||
}
|
||||
|
||||
public override Decoder GetStoryboardDecoder() => this;
|
||||
|
||||
protected override void ParseBeatmap(StreamReader stream, Beatmap beatmap)
|
||||
protected override void ParseStreamInto(StreamReader stream, Beatmap beatmap)
|
||||
{
|
||||
stream.BaseStream.Position = 0;
|
||||
stream.DiscardBufferedData();
|
||||
@ -26,10 +23,5 @@ namespace osu.Game.Beatmaps.Formats
|
||||
foreach (var hitObject in beatmap.HitObjects)
|
||||
hitObject.ApplyDefaults(beatmap.ControlPointInfo, beatmap.BeatmapInfo.BaseDifficulty);
|
||||
}
|
||||
|
||||
protected override void ParseStoryboard(StreamReader stream, Storyboard storyboard)
|
||||
{
|
||||
// throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Beatmaps.Timing;
|
||||
using osu.Game.Rulesets.Objects.Legacy;
|
||||
@ -12,8 +13,10 @@ using osu.Framework;
|
||||
|
||||
namespace osu.Game.Beatmaps.Formats
|
||||
{
|
||||
public class LegacyBeatmapDecoder : LegacyDecoder
|
||||
public class LegacyBeatmapDecoder : LegacyDecoder<Beatmap>
|
||||
{
|
||||
public const int LATEST_VERSION = 14;
|
||||
|
||||
private Beatmap beatmap;
|
||||
|
||||
private bool hasCustomColours;
|
||||
@ -22,6 +25,11 @@ namespace osu.Game.Beatmaps.Formats
|
||||
private LegacySampleBank defaultSampleBank;
|
||||
private int defaultSampleVolume = 100;
|
||||
|
||||
public static void Register()
|
||||
{
|
||||
AddDecoder<Beatmap>(@"osu file format v", m => new LegacyBeatmapDecoder(int.Parse(m.Split('v').Last())));
|
||||
}
|
||||
|
||||
/// <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.
|
||||
@ -35,29 +43,18 @@ namespace osu.Game.Beatmaps.Formats
|
||||
|
||||
private readonly int offset = UniversalOffset;
|
||||
|
||||
public LegacyBeatmapDecoder()
|
||||
public LegacyBeatmapDecoder(int version = LATEST_VERSION) : base(version)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
offset += FormatVersion < 5 ? 24 : 0;
|
||||
}
|
||||
|
||||
protected override void ParseBeatmap(StreamReader stream, Beatmap beatmap)
|
||||
protected override void ParseStreamInto(StreamReader stream, Beatmap beatmap)
|
||||
{
|
||||
if (stream == null)
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
if (beatmap == null)
|
||||
throw new ArgumentNullException(nameof(beatmap));
|
||||
|
||||
this.beatmap = beatmap;
|
||||
this.beatmap.BeatmapInfo.BeatmapVersion = BeatmapVersion;
|
||||
this.beatmap.BeatmapInfo.BeatmapVersion = FormatVersion;
|
||||
|
||||
ParseContent(stream);
|
||||
base.ParseStreamInto(stream, beatmap);
|
||||
|
||||
// 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).
|
||||
@ -67,14 +64,9 @@ namespace osu.Game.Beatmaps.Formats
|
||||
hitObject.ApplyDefaults(this.beatmap.ControlPointInfo, this.beatmap.BeatmapInfo.BaseDifficulty);
|
||||
}
|
||||
|
||||
protected override bool ShouldSkipLine(string line)
|
||||
{
|
||||
if (base.ShouldSkipLine(line) || line.StartsWith(" ") || line.StartsWith("_"))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
protected override bool ShouldSkipLine(string line) => base.ShouldSkipLine(line) || line.StartsWith(" ") || line.StartsWith("_");
|
||||
|
||||
protected override void ProcessSection(Section section, string line)
|
||||
protected override void ParseLine(Beatmap beatmap, Section section, string line)
|
||||
{
|
||||
switch (section)
|
||||
{
|
||||
|
@ -4,47 +4,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
using osu.Game.Storyboards;
|
||||
|
||||
namespace osu.Game.Beatmaps.Formats
|
||||
{
|
||||
public abstract class LegacyDecoder : Decoder
|
||||
public abstract class LegacyDecoder<T> : Decoder<T>
|
||||
where T : new()
|
||||
{
|
||||
public static void Register()
|
||||
protected readonly int FormatVersion;
|
||||
|
||||
protected LegacyDecoder(int version)
|
||||
{
|
||||
AddDecoder(@"osu file format v14", m => new LegacyBeatmapDecoder(m));
|
||||
AddDecoder(@"osu file format v13", m => new LegacyBeatmapDecoder(m));
|
||||
AddDecoder(@"osu file format v12", m => new LegacyBeatmapDecoder(m));
|
||||
AddDecoder(@"osu file format v11", m => new LegacyBeatmapDecoder(m));
|
||||
AddDecoder(@"osu file format v10", m => new LegacyBeatmapDecoder(m));
|
||||
AddDecoder(@"osu file format v9", m => new LegacyBeatmapDecoder(m));
|
||||
AddDecoder(@"osu file format v8", m => new LegacyBeatmapDecoder(m));
|
||||
AddDecoder(@"osu file format v7", m => new LegacyBeatmapDecoder(m));
|
||||
AddDecoder(@"osu file format v6", m => new LegacyBeatmapDecoder(m));
|
||||
AddDecoder(@"osu file format v5", m => new LegacyBeatmapDecoder(m));
|
||||
AddDecoder(@"osu file format v4", m => new LegacyBeatmapDecoder(m));
|
||||
AddDecoder(@"osu file format v3", m => new LegacyBeatmapDecoder(m));
|
||||
// TODO: differences between versions
|
||||
FormatVersion = version;
|
||||
}
|
||||
|
||||
protected int BeatmapVersion;
|
||||
|
||||
public override Decoder GetStoryboardDecoder() => new LegacyStoryboardDecoder(BeatmapVersion);
|
||||
|
||||
public override Beatmap DecodeBeatmap(StreamReader stream) => new LegacyBeatmap(base.DecodeBeatmap(stream));
|
||||
|
||||
protected override void ParseBeatmap(StreamReader stream, Beatmap beatmap)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override void ParseStoryboard(StreamReader stream, Storyboard storyboard)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected void ParseContent(StreamReader stream)
|
||||
protected override void ParseStreamInto(StreamReader stream, T beatmap)
|
||||
{
|
||||
Section section = Section.None;
|
||||
|
||||
@ -54,13 +27,6 @@ namespace osu.Game.Beatmaps.Formats
|
||||
if (ShouldSkipLine(line))
|
||||
continue;
|
||||
|
||||
// It's already set in ParseBeatmap... why do it again?
|
||||
//if (line.StartsWith(@"osu file format v"))
|
||||
//{
|
||||
// Beatmap.BeatmapInfo.BeatmapVersion = int.Parse(line.Substring(17));
|
||||
// continue;
|
||||
//}
|
||||
|
||||
if (line.StartsWith(@"[") && line.EndsWith(@"]"))
|
||||
{
|
||||
if (!Enum.TryParse(line.Substring(1, line.Length - 2), out section))
|
||||
@ -68,18 +34,13 @@ namespace osu.Game.Beatmaps.Formats
|
||||
continue;
|
||||
}
|
||||
|
||||
ProcessSection(section, line);
|
||||
ParseLine(beatmap, section, line);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual bool ShouldSkipLine(string line)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(line) || line.StartsWith("//"))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
protected virtual bool ShouldSkipLine(string line) => string.IsNullOrWhiteSpace(line) || line.StartsWith("//");
|
||||
|
||||
protected abstract void ProcessSection(Section section, string line);
|
||||
protected abstract void ParseLine(T output, Section section, string line);
|
||||
|
||||
protected KeyValuePair<string, string> SplitKeyVal(string line, char separator)
|
||||
{
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using OpenTK;
|
||||
@ -13,37 +13,34 @@ using osu.Game.Storyboards;
|
||||
|
||||
namespace osu.Game.Beatmaps.Formats
|
||||
{
|
||||
public class LegacyStoryboardDecoder : LegacyDecoder
|
||||
public class LegacyStoryboardDecoder : LegacyDecoder<Storyboard>
|
||||
{
|
||||
private Storyboard storyboard;
|
||||
|
||||
private StoryboardSprite storyboardSprite;
|
||||
private CommandTimelineGroup timelineGroup;
|
||||
|
||||
private Storyboard storyboard;
|
||||
|
||||
private readonly Dictionary<string, string> variables = new Dictionary<string, string>();
|
||||
|
||||
public LegacyStoryboardDecoder()
|
||||
: base(0)
|
||||
{
|
||||
}
|
||||
|
||||
public LegacyStoryboardDecoder(int beatmapVersion)
|
||||
public static void Register()
|
||||
{
|
||||
BeatmapVersion = beatmapVersion;
|
||||
// note that this isn't completely correct
|
||||
AddDecoder<Storyboard>(@"osu file format v", m => new LegacyStoryboardDecoder());
|
||||
AddDecoder<Storyboard>(@"[Events]", m => new LegacyStoryboardDecoder());
|
||||
}
|
||||
|
||||
protected override void ParseStoryboard(StreamReader stream, Storyboard storyboard)
|
||||
protected override void ParseStreamInto(StreamReader stream, Storyboard storyboard)
|
||||
{
|
||||
if (stream == null)
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
if (storyboard == null)
|
||||
throw new ArgumentNullException(nameof(storyboard));
|
||||
|
||||
this.storyboard = storyboard;
|
||||
|
||||
ParseContent(stream);
|
||||
base.ParseStreamInto(stream, storyboard);
|
||||
}
|
||||
|
||||
protected override void ProcessSection(Section section, string line)
|
||||
protected override void ParseLine(Storyboard storyboard, Section section, string line)
|
||||
{
|
||||
switch (section)
|
||||
{
|
||||
@ -80,38 +77,38 @@ namespace osu.Game.Beatmaps.Formats
|
||||
switch (type)
|
||||
{
|
||||
case EventType.Sprite:
|
||||
{
|
||||
var layer = parseLayer(split[1]);
|
||||
var origin = parseOrigin(split[2]);
|
||||
var path = cleanFilename(split[3]);
|
||||
var x = float.Parse(split[4], NumberFormatInfo.InvariantInfo);
|
||||
var y = float.Parse(split[5], NumberFormatInfo.InvariantInfo);
|
||||
storyboardSprite = new StoryboardSprite(path, origin, new Vector2(x, y));
|
||||
storyboard.GetLayer(layer).Add(storyboardSprite);
|
||||
}
|
||||
{
|
||||
var layer = parseLayer(split[1]);
|
||||
var origin = parseOrigin(split[2]);
|
||||
var path = cleanFilename(split[3]);
|
||||
var x = float.Parse(split[4], NumberFormatInfo.InvariantInfo);
|
||||
var y = float.Parse(split[5], NumberFormatInfo.InvariantInfo);
|
||||
storyboardSprite = new StoryboardSprite(path, origin, new Vector2(x, y));
|
||||
storyboard.GetLayer(layer).Add(storyboardSprite);
|
||||
}
|
||||
break;
|
||||
case EventType.Animation:
|
||||
{
|
||||
var layer = parseLayer(split[1]);
|
||||
var origin = parseOrigin(split[2]);
|
||||
var path = cleanFilename(split[3]);
|
||||
var x = float.Parse(split[4], NumberFormatInfo.InvariantInfo);
|
||||
var y = float.Parse(split[5], NumberFormatInfo.InvariantInfo);
|
||||
var frameCount = int.Parse(split[6]);
|
||||
var frameDelay = double.Parse(split[7], NumberFormatInfo.InvariantInfo);
|
||||
var loopType = split.Length > 8 ? (AnimationLoopType)Enum.Parse(typeof(AnimationLoopType), split[8]) : AnimationLoopType.LoopForever;
|
||||
storyboardSprite = new StoryboardAnimation(path, origin, new Vector2(x, y), frameCount, frameDelay, loopType);
|
||||
storyboard.GetLayer(layer).Add(storyboardSprite);
|
||||
}
|
||||
{
|
||||
var layer = parseLayer(split[1]);
|
||||
var origin = parseOrigin(split[2]);
|
||||
var path = cleanFilename(split[3]);
|
||||
var x = float.Parse(split[4], NumberFormatInfo.InvariantInfo);
|
||||
var y = float.Parse(split[5], NumberFormatInfo.InvariantInfo);
|
||||
var frameCount = int.Parse(split[6]);
|
||||
var frameDelay = double.Parse(split[7], NumberFormatInfo.InvariantInfo);
|
||||
var loopType = split.Length > 8 ? (AnimationLoopType)Enum.Parse(typeof(AnimationLoopType), split[8]) : AnimationLoopType.LoopForever;
|
||||
storyboardSprite = new StoryboardAnimation(path, origin, new Vector2(x, y), frameCount, frameDelay, loopType);
|
||||
storyboard.GetLayer(layer).Add(storyboardSprite);
|
||||
}
|
||||
break;
|
||||
case EventType.Sample:
|
||||
{
|
||||
var time = double.Parse(split[1], CultureInfo.InvariantCulture);
|
||||
var layer = parseLayer(split[2]);
|
||||
var path = cleanFilename(split[3]);
|
||||
var volume = split.Length > 4 ? float.Parse(split[4], CultureInfo.InvariantCulture) : 100;
|
||||
storyboard.GetLayer(layer).Add(new StoryboardSample(path, time, volume));
|
||||
}
|
||||
{
|
||||
var time = double.Parse(split[1], CultureInfo.InvariantCulture);
|
||||
var layer = parseLayer(split[2]);
|
||||
var path = cleanFilename(split[3]);
|
||||
var volume = split.Length > 4 ? float.Parse(split[4], CultureInfo.InvariantCulture) : 100;
|
||||
storyboard.GetLayer(layer).Add(new StoryboardSample(path, time, volume));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -124,120 +121,120 @@ namespace osu.Game.Beatmaps.Formats
|
||||
switch (commandType)
|
||||
{
|
||||
case "T":
|
||||
{
|
||||
var triggerName = split[1];
|
||||
var startTime = split.Length > 2 ? double.Parse(split[2], CultureInfo.InvariantCulture) : double.MinValue;
|
||||
var endTime = split.Length > 3 ? double.Parse(split[3], CultureInfo.InvariantCulture) : double.MaxValue;
|
||||
var groupNumber = split.Length > 4 ? int.Parse(split[4]) : 0;
|
||||
timelineGroup = storyboardSprite?.AddTrigger(triggerName, startTime, endTime, groupNumber);
|
||||
}
|
||||
{
|
||||
var triggerName = split[1];
|
||||
var startTime = split.Length > 2 ? double.Parse(split[2], CultureInfo.InvariantCulture) : double.MinValue;
|
||||
var endTime = split.Length > 3 ? double.Parse(split[3], CultureInfo.InvariantCulture) : double.MaxValue;
|
||||
var groupNumber = split.Length > 4 ? int.Parse(split[4]) : 0;
|
||||
timelineGroup = storyboardSprite?.AddTrigger(triggerName, startTime, endTime, groupNumber);
|
||||
}
|
||||
break;
|
||||
case "L":
|
||||
{
|
||||
var startTime = double.Parse(split[1], CultureInfo.InvariantCulture);
|
||||
var loopCount = int.Parse(split[2]);
|
||||
timelineGroup = storyboardSprite?.AddLoop(startTime, loopCount);
|
||||
}
|
||||
{
|
||||
var startTime = double.Parse(split[1], CultureInfo.InvariantCulture);
|
||||
var loopCount = int.Parse(split[2]);
|
||||
timelineGroup = storyboardSprite?.AddLoop(startTime, loopCount);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if (string.IsNullOrEmpty(split[3]))
|
||||
split[3] = split[2];
|
||||
|
||||
var easing = (Easing)int.Parse(split[1]);
|
||||
var startTime = double.Parse(split[2], CultureInfo.InvariantCulture);
|
||||
var endTime = double.Parse(split[3], CultureInfo.InvariantCulture);
|
||||
|
||||
switch (commandType)
|
||||
{
|
||||
if (string.IsNullOrEmpty(split[3]))
|
||||
split[3] = split[2];
|
||||
|
||||
var easing = (Easing)int.Parse(split[1]);
|
||||
var startTime = double.Parse(split[2], CultureInfo.InvariantCulture);
|
||||
var endTime = double.Parse(split[3], CultureInfo.InvariantCulture);
|
||||
|
||||
switch (commandType)
|
||||
case "F":
|
||||
{
|
||||
case "F":
|
||||
{
|
||||
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||
timelineGroup?.Alpha.Add(easing, startTime, endTime, startValue, endValue);
|
||||
}
|
||||
break;
|
||||
case "S":
|
||||
{
|
||||
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||
timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startValue), new Vector2(endValue));
|
||||
}
|
||||
break;
|
||||
case "V":
|
||||
{
|
||||
var startX = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||
var startY = float.Parse(split[5], CultureInfo.InvariantCulture);
|
||||
var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX;
|
||||
var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY;
|
||||
timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startX, startY), new Vector2(endX, endY));
|
||||
}
|
||||
break;
|
||||
case "R":
|
||||
{
|
||||
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||
timelineGroup?.Rotation.Add(easing, startTime, endTime, MathHelper.RadiansToDegrees(startValue), MathHelper.RadiansToDegrees(endValue));
|
||||
}
|
||||
break;
|
||||
case "M":
|
||||
{
|
||||
var startX = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||
var startY = float.Parse(split[5], CultureInfo.InvariantCulture);
|
||||
var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX;
|
||||
var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY;
|
||||
timelineGroup?.X.Add(easing, startTime, endTime, startX, endX);
|
||||
timelineGroup?.Y.Add(easing, startTime, endTime, startY, endY);
|
||||
}
|
||||
break;
|
||||
case "MX":
|
||||
{
|
||||
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||
timelineGroup?.X.Add(easing, startTime, endTime, startValue, endValue);
|
||||
}
|
||||
break;
|
||||
case "MY":
|
||||
{
|
||||
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||
timelineGroup?.Y.Add(easing, startTime, endTime, startValue, endValue);
|
||||
}
|
||||
break;
|
||||
case "C":
|
||||
{
|
||||
var startRed = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||
var startGreen = float.Parse(split[5], CultureInfo.InvariantCulture);
|
||||
var startBlue = float.Parse(split[6], CultureInfo.InvariantCulture);
|
||||
var endRed = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startRed;
|
||||
var endGreen = split.Length > 8 ? float.Parse(split[8], CultureInfo.InvariantCulture) : startGreen;
|
||||
var endBlue = split.Length > 9 ? float.Parse(split[9], CultureInfo.InvariantCulture) : startBlue;
|
||||
timelineGroup?.Colour.Add(easing, startTime, endTime,
|
||||
new Color4(startRed / 255f, startGreen / 255f, startBlue / 255f, 1),
|
||||
new Color4(endRed / 255f, endGreen / 255f, endBlue / 255f, 1));
|
||||
}
|
||||
break;
|
||||
case "P":
|
||||
{
|
||||
var type = split[4];
|
||||
switch (type)
|
||||
{
|
||||
case "A":
|
||||
timelineGroup?.BlendingMode.Add(easing, startTime, endTime, BlendingMode.Additive, startTime == endTime ? BlendingMode.Additive : BlendingMode.Inherit);
|
||||
break;
|
||||
case "H":
|
||||
timelineGroup?.FlipH.Add(easing, startTime, endTime, true, startTime == endTime);
|
||||
break;
|
||||
case "V":
|
||||
timelineGroup?.FlipV.Add(easing, startTime, endTime, true, startTime == endTime);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new InvalidDataException($@"Unknown command type: {commandType}");
|
||||
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||
timelineGroup?.Alpha.Add(easing, startTime, endTime, startValue, endValue);
|
||||
}
|
||||
break;
|
||||
case "S":
|
||||
{
|
||||
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||
timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startValue), new Vector2(endValue));
|
||||
}
|
||||
break;
|
||||
case "V":
|
||||
{
|
||||
var startX = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||
var startY = float.Parse(split[5], CultureInfo.InvariantCulture);
|
||||
var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX;
|
||||
var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY;
|
||||
timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startX, startY), new Vector2(endX, endY));
|
||||
}
|
||||
break;
|
||||
case "R":
|
||||
{
|
||||
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||
timelineGroup?.Rotation.Add(easing, startTime, endTime, MathHelper.RadiansToDegrees(startValue), MathHelper.RadiansToDegrees(endValue));
|
||||
}
|
||||
break;
|
||||
case "M":
|
||||
{
|
||||
var startX = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||
var startY = float.Parse(split[5], CultureInfo.InvariantCulture);
|
||||
var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX;
|
||||
var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY;
|
||||
timelineGroup?.X.Add(easing, startTime, endTime, startX, endX);
|
||||
timelineGroup?.Y.Add(easing, startTime, endTime, startY, endY);
|
||||
}
|
||||
break;
|
||||
case "MX":
|
||||
{
|
||||
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||
timelineGroup?.X.Add(easing, startTime, endTime, startValue, endValue);
|
||||
}
|
||||
break;
|
||||
case "MY":
|
||||
{
|
||||
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||
timelineGroup?.Y.Add(easing, startTime, endTime, startValue, endValue);
|
||||
}
|
||||
break;
|
||||
case "C":
|
||||
{
|
||||
var startRed = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||
var startGreen = float.Parse(split[5], CultureInfo.InvariantCulture);
|
||||
var startBlue = float.Parse(split[6], CultureInfo.InvariantCulture);
|
||||
var endRed = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startRed;
|
||||
var endGreen = split.Length > 8 ? float.Parse(split[8], CultureInfo.InvariantCulture) : startGreen;
|
||||
var endBlue = split.Length > 9 ? float.Parse(split[9], CultureInfo.InvariantCulture) : startBlue;
|
||||
timelineGroup?.Colour.Add(easing, startTime, endTime,
|
||||
new Color4(startRed / 255f, startGreen / 255f, startBlue / 255f, 1),
|
||||
new Color4(endRed / 255f, endGreen / 255f, endBlue / 255f, 1));
|
||||
}
|
||||
break;
|
||||
case "P":
|
||||
{
|
||||
var type = split[4];
|
||||
switch (type)
|
||||
{
|
||||
case "A":
|
||||
timelineGroup?.BlendingMode.Add(easing, startTime, endTime, BlendingMode.Additive, startTime == endTime ? BlendingMode.Additive : BlendingMode.Inherit);
|
||||
break;
|
||||
case "H":
|
||||
timelineGroup?.FlipH.Add(easing, startTime, endTime, true, startTime == endTime);
|
||||
break;
|
||||
case "V":
|
||||
timelineGroup?.FlipV.Add(easing, startTime, endTime, true, startTime == endTime);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new InvalidDataException($@"Unknown command type: {commandType}");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -269,6 +266,7 @@ namespace osu.Game.Beatmaps.Formats
|
||||
case LegacyOrigins.BottomRight:
|
||||
return Anchor.BottomRight;
|
||||
}
|
||||
|
||||
throw new InvalidDataException($@"Unknown origin: {value}");
|
||||
}
|
||||
|
||||
|
@ -66,8 +66,10 @@ namespace osu.Game.Graphics.Containers
|
||||
{
|
||||
Vector2 offset = (input.CurrentState.Mouse == null ? Vector2.Zero : ToLocalSpace(input.CurrentState.Mouse.NativeState.Position) - DrawSize / 2) * ParallaxAmount;
|
||||
|
||||
content.Position = Interpolation.ValueAt(MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 1000), content.Position, offset, 0, 1000, Easing.OutQuint);
|
||||
content.Scale = new Vector2(1 + ParallaxAmount);
|
||||
double elapsed = MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 1000);
|
||||
|
||||
content.Position = Interpolation.ValueAt(elapsed, content.Position, offset, 0, 1000, Easing.OutQuint);
|
||||
content.Scale = Interpolation.ValueAt(elapsed, content.Scale, new Vector2(1 + ParallaxAmount), 0, 1000, Easing.OutQuint);
|
||||
}
|
||||
|
||||
firstUpdate = false;
|
||||
|
66
osu.Game/Graphics/DrawableDate.cs
Normal file
66
osu.Game/Graphics/DrawableDate.cs
Normal file
@ -0,0 +1,66 @@
|
||||
// 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 Humanizer;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
|
||||
namespace osu.Game.Graphics
|
||||
{
|
||||
public class DrawableDate : OsuSpriteText, IHasTooltip
|
||||
{
|
||||
private readonly DateTimeOffset date;
|
||||
private ScheduledDelegate updateTask;
|
||||
|
||||
public DrawableDate(DateTimeOffset date)
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
Font = "Exo2.0-RegularItalic";
|
||||
|
||||
this.date = date.ToLocalTime();
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
updateTime();
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
Scheduler.Add(updateTimeWithReschedule);
|
||||
}
|
||||
|
||||
private void updateTimeWithReschedule()
|
||||
{
|
||||
updateTime();
|
||||
|
||||
var diffToNow = DateTimeOffset.Now.Subtract(date);
|
||||
|
||||
double timeUntilNextUpdate = 1000;
|
||||
if (diffToNow.TotalSeconds > 60)
|
||||
{
|
||||
timeUntilNextUpdate *= 60;
|
||||
if (diffToNow.TotalMinutes > 60)
|
||||
{
|
||||
timeUntilNextUpdate *= 60;
|
||||
|
||||
if (diffToNow.TotalHours > 24)
|
||||
timeUntilNextUpdate *= 24;
|
||||
}
|
||||
}
|
||||
|
||||
Scheduler.AddDelayed(updateTimeWithReschedule, timeUntilNextUpdate);
|
||||
}
|
||||
|
||||
public override bool HandleMouseInput => true;
|
||||
|
||||
private void updateTime() => Text = date.Humanize();
|
||||
public string TooltipText => date.ToString();
|
||||
}
|
||||
}
|
@ -125,7 +125,6 @@ namespace osu.Game.Online.API
|
||||
userReq.Success += u =>
|
||||
{
|
||||
LocalUser.Value = u;
|
||||
Username = LocalUser.Value.Username;
|
||||
failureCount = 0;
|
||||
|
||||
//we're connected!
|
||||
|
@ -130,11 +130,7 @@ namespace osu.Game.Overlays.Profile
|
||||
}
|
||||
}
|
||||
},
|
||||
infoTextLeft = new OsuTextFlowContainer(t =>
|
||||
{
|
||||
t.TextSize = 14;
|
||||
t.Alpha = 0.8f;
|
||||
})
|
||||
infoTextLeft = new OsuTextFlowContainer(t => t.TextSize = 14)
|
||||
{
|
||||
X = UserProfileOverlay.CONTENT_X_MARGIN,
|
||||
Y = cover_height + 20,
|
||||
@ -318,11 +314,23 @@ namespace osu.Game.Overlays.Profile
|
||||
colourBar.Show();
|
||||
}
|
||||
|
||||
void boldItalic(SpriteText t)
|
||||
void boldItalic(SpriteText t) => t.Font = @"Exo2.0-BoldItalic";
|
||||
void lightText(SpriteText t) => t.Alpha = 0.8f;
|
||||
|
||||
OsuSpriteText createScoreText(string text) => new OsuSpriteText
|
||||
{
|
||||
t.Font = @"Exo2.0-BoldItalic";
|
||||
t.Alpha = 1;
|
||||
}
|
||||
TextSize = 14,
|
||||
Text = text
|
||||
};
|
||||
|
||||
OsuSpriteText createScoreNumberText(string text) => new OsuSpriteText
|
||||
{
|
||||
TextSize = 14,
|
||||
Font = @"Exo2.0-Bold",
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
Text = text
|
||||
};
|
||||
|
||||
if (user.Age != null)
|
||||
{
|
||||
@ -331,7 +339,7 @@ namespace osu.Game.Overlays.Profile
|
||||
|
||||
if (user.Country != null)
|
||||
{
|
||||
infoTextLeft.AddText("from ");
|
||||
infoTextLeft.AddText("from ", lightText);
|
||||
infoTextLeft.AddText(user.Country.FullName, boldItalic);
|
||||
countryFlag.Country = user.Country;
|
||||
}
|
||||
@ -344,18 +352,18 @@ namespace osu.Game.Overlays.Profile
|
||||
}
|
||||
else
|
||||
{
|
||||
infoTextLeft.AddText("Joined ");
|
||||
infoTextLeft.AddText(user.JoinDate.LocalDateTime.ToShortDateString(), boldItalic);
|
||||
infoTextLeft.AddText("Joined ", lightText);
|
||||
infoTextLeft.AddText(new DrawableDate(user.JoinDate), boldItalic);
|
||||
}
|
||||
|
||||
infoTextLeft.NewLine();
|
||||
infoTextLeft.AddText("Last seen ");
|
||||
infoTextLeft.AddText(user.LastVisit.LocalDateTime.ToShortDateString(), boldItalic);
|
||||
infoTextLeft.AddText("Last seen ", lightText);
|
||||
infoTextLeft.AddText(new DrawableDate(user.LastVisit), boldItalic);
|
||||
infoTextLeft.NewParagraph();
|
||||
|
||||
if (user.PlayStyle?.Length > 0)
|
||||
{
|
||||
infoTextLeft.AddText("Plays with ");
|
||||
infoTextLeft.AddText("Plays with ", lightText);
|
||||
infoTextLeft.AddText(string.Join(", ", user.PlayStyle), boldItalic);
|
||||
}
|
||||
|
||||
@ -411,23 +419,6 @@ namespace osu.Game.Overlays.Profile
|
||||
}
|
||||
}
|
||||
|
||||
// These could be local functions when C# 7 enabled
|
||||
|
||||
private OsuSpriteText createScoreText(string text) => new OsuSpriteText
|
||||
{
|
||||
TextSize = 14,
|
||||
Text = text
|
||||
};
|
||||
|
||||
private OsuSpriteText createScoreNumberText(string text) => new OsuSpriteText
|
||||
{
|
||||
TextSize = 14,
|
||||
Font = @"Exo2.0-Bold",
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
Text = text
|
||||
};
|
||||
|
||||
private void tryAddInfoRightLine(FontAwesome icon, string str, string url = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(str)) return;
|
||||
@ -436,10 +427,12 @@ namespace osu.Game.Overlays.Profile
|
||||
if (url != null)
|
||||
{
|
||||
infoTextRight.AddLink(" " + str, url);
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
infoTextRight.AddText(" " + str);
|
||||
}
|
||||
|
||||
infoTextRight.NewLine();
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,7 @@ namespace osu.Game.Overlays.Profile
|
||||
{
|
||||
placeholder.FadeIn(fade_duration, Easing.Out);
|
||||
|
||||
if (user == null)
|
||||
if (user?.Statistics?.Ranks.Global == null)
|
||||
{
|
||||
rankText.Text = string.Empty;
|
||||
performanceText.Text = string.Empty;
|
||||
@ -105,7 +105,7 @@ namespace osu.Game.Overlays.Profile
|
||||
return;
|
||||
}
|
||||
|
||||
int[] userRanks = user.RankHistory?.Data ?? new[] { user.Statistics.Ranks.Global };
|
||||
int[] userRanks = user.RankHistory?.Data ?? new[] { user.Statistics.Ranks.Global.Value };
|
||||
ranks = userRanks.Select((x, index) => new KeyValuePair<int, int>(index, x)).Where(x => x.Value != 0).ToArray();
|
||||
|
||||
if (ranks.Length > 1)
|
||||
|
@ -54,12 +54,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
|
||||
RightFlowContainer.SetLayoutPosition(text, 1);
|
||||
|
||||
LeftFlowContainer.Add(new BeatmapMetadataContainer(Score.Beatmap));
|
||||
LeftFlowContainer.Add(new OsuSpriteText
|
||||
{
|
||||
Text = Score.Date.LocalDateTime.ToShortDateString(),
|
||||
TextSize = 11,
|
||||
Colour = OsuColour.Gray(0xAA),
|
||||
});
|
||||
LeftFlowContainer.Add(new DrawableDate(Score.Date));
|
||||
|
||||
foreach (Mod mod in Score.Mods)
|
||||
modsContainer.Add(new ModIcon(mod) { Scale = new Vector2(0.5f) });
|
||||
|
@ -6,7 +6,6 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.Chat;
|
||||
@ -40,14 +39,12 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
|
||||
RelativeSizeAxes = Axes.X,
|
||||
});
|
||||
|
||||
RightFlowContainer.Add(new OsuSpriteText
|
||||
RightFlowContainer.Add(new DrawableDate(activity.CreatedAt)
|
||||
{
|
||||
Text = activity.CreatedAt.LocalDateTime.ToShortDateString(),
|
||||
TextSize = 13,
|
||||
Colour = OsuColour.Gray(0xAA),
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
Font = "Exo2.0-RegularItalic",
|
||||
TextSize = 12,
|
||||
Colour = OsuColour.Gray(0xAA),
|
||||
});
|
||||
|
||||
var formatted = createMessage();
|
||||
|
@ -55,7 +55,7 @@ namespace osu.Game.Overlays.Toolbar
|
||||
avatar.User = new User();
|
||||
break;
|
||||
case APIState.Online:
|
||||
Text = api.Username;
|
||||
Text = api.LocalUser.Value.Username;
|
||||
avatar.User = api.LocalUser;
|
||||
break;
|
||||
}
|
||||
|
@ -169,15 +169,18 @@ namespace osu.Game.Overlays
|
||||
{
|
||||
Header.User = user;
|
||||
|
||||
foreach (string id in user.ProfileOrder)
|
||||
if (user.ProfileOrder != null)
|
||||
{
|
||||
var sec = sections.FirstOrDefault(s => s.Identifier == id);
|
||||
if (sec != null)
|
||||
foreach (string id in user.ProfileOrder)
|
||||
{
|
||||
sec.User.Value = user;
|
||||
var sec = sections.FirstOrDefault(s => s.Identifier == id);
|
||||
if (sec != null)
|
||||
{
|
||||
sec.User.Value = user;
|
||||
|
||||
sectionsContainer.Add(sec);
|
||||
tabs.AddItem(sec);
|
||||
sectionsContainer.Add(sec);
|
||||
tabs.AddItem(sec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,10 +10,10 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit.Layers;
|
||||
using osu.Game.Rulesets.Edit.Layers.Selection;
|
||||
using osu.Game.Rulesets.Edit.Tools;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Screens.Edit.Screens.Compose.Layers;
|
||||
using osu.Game.Screens.Edit.Screens.Compose.RadioButtons;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit
|
||||
@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Edit
|
||||
return;
|
||||
}
|
||||
|
||||
HitObjectOverlayLayer hitObjectOverlayLayer = CreateHitObjectOverlayLayer();
|
||||
HitObjectMaskLayer hitObjectMaskLayer = new HitObjectMaskLayer(this);
|
||||
SelectionLayer selectionLayer = new SelectionLayer(rulesetContainer.Playfield);
|
||||
|
||||
var layerBelowRuleset = new BorderLayer
|
||||
@ -62,7 +62,7 @@ namespace osu.Game.Rulesets.Edit
|
||||
layerAboveRuleset.Children = new Drawable[]
|
||||
{
|
||||
selectionLayer, // Below object overlays for input
|
||||
hitObjectOverlayLayer,
|
||||
hitObjectMaskLayer,
|
||||
selectionLayer.CreateProxy() // Proxy above object overlays for selections
|
||||
};
|
||||
|
||||
@ -106,8 +106,10 @@ namespace osu.Game.Rulesets.Edit
|
||||
}
|
||||
};
|
||||
|
||||
selectionLayer.ObjectSelected += hitObjectOverlayLayer.AddOverlay;
|
||||
selectionLayer.ObjectDeselected += hitObjectOverlayLayer.RemoveOverlay;
|
||||
selectionLayer.ObjectSelected += hitObjectMaskLayer.AddOverlay;
|
||||
selectionLayer.ObjectDeselected += hitObjectMaskLayer.RemoveOverlay;
|
||||
selectionLayer.SelectionCleared += hitObjectMaskLayer.RemoveSelectionOverlay;
|
||||
selectionLayer.SelectionFinished += hitObjectMaskLayer.AddSelectionOverlay;
|
||||
|
||||
toolboxCollection.Items =
|
||||
new[] { new RadioButton("Select", () => setCompositionTool(null)) }
|
||||
@ -138,14 +140,22 @@ namespace osu.Game.Rulesets.Edit
|
||||
|
||||
protected abstract IReadOnlyList<ICompositionTool> CompositionTools { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="HitObjectMask"/> for a specific <see cref="DrawableHitObject"/>.
|
||||
/// </summary>
|
||||
/// <param name="hitObject">The <see cref="DrawableHitObject"/> to create the overlay for.</param>
|
||||
public virtual HitObjectMask CreateMaskFor(DrawableHitObject hitObject) => null;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="SelectionBox"/> which outlines <see cref="DrawableHitObject"/>s
|
||||
/// and handles all hitobject movement/pattern adjustments.
|
||||
/// </summary>
|
||||
/// <param name="overlays">The <see cref="DrawableHitObject"/> overlays.</param>
|
||||
public virtual SelectionBox CreateSelectionOverlay(IReadOnlyList<HitObjectMask> overlays) => new SelectionBox(overlays);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ScalableContainer"/> which provides a layer above or below the <see cref="Playfield"/>.
|
||||
/// </summary>
|
||||
protected virtual ScalableContainer CreateLayerContainer() => new ScalableContainer { RelativeSizeAxes = Axes.Both };
|
||||
|
||||
/// <summary>
|
||||
/// Creates the <see cref="HitObjectOverlayLayer"/> which overlays selected <see cref="DrawableHitObject"/>s.
|
||||
/// </summary>
|
||||
protected virtual HitObjectOverlayLayer CreateHitObjectOverlayLayer() => new HitObjectOverlayLayer();
|
||||
}
|
||||
}
|
||||
|
21
osu.Game/Rulesets/Edit/HitObjectMask.cs
Normal file
21
osu.Game/Rulesets/Edit/HitObjectMask.cs
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit
|
||||
{
|
||||
/// <summary>
|
||||
/// A mask placed above a <see cref="DrawableHitObject"/> adding editing functionality.
|
||||
/// </summary>
|
||||
public class HitObjectMask : Container
|
||||
{
|
||||
public readonly DrawableHitObject HitObject;
|
||||
|
||||
public HitObjectMask(DrawableHitObject hitObject)
|
||||
{
|
||||
HitObject = hitObject;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
// 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.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Layers.Selection
|
||||
{
|
||||
/// <summary>
|
||||
/// A box which encloses <see cref="DrawableHitObject"/>s.
|
||||
/// </summary>
|
||||
public class CaptureBox : VisibilityContainer
|
||||
{
|
||||
private readonly IDrawable captureArea;
|
||||
private readonly IReadOnlyList<DrawableHitObject> capturedObjects;
|
||||
|
||||
public CaptureBox(IDrawable captureArea, IReadOnlyList<DrawableHitObject> capturedObjects)
|
||||
{
|
||||
this.captureArea = captureArea;
|
||||
this.capturedObjects = capturedObjects;
|
||||
|
||||
Masking = true;
|
||||
BorderThickness = SelectionBox.BORDER_RADIUS;
|
||||
|
||||
InternalChild = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
AlwaysPresent = true,
|
||||
Alpha = 0
|
||||
};
|
||||
|
||||
State = Visibility.Visible;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
BorderColour = colours.Yellow;
|
||||
|
||||
// Move the rectangle to cover the hitobjects
|
||||
var topLeft = new Vector2(float.MaxValue, float.MaxValue);
|
||||
var bottomRight = new Vector2(float.MinValue, float.MinValue);
|
||||
|
||||
foreach (var obj in capturedObjects)
|
||||
{
|
||||
topLeft = Vector2.ComponentMin(topLeft, captureArea.ToLocalSpace(obj.SelectionQuad.TopLeft));
|
||||
bottomRight = Vector2.ComponentMax(bottomRight, captureArea.ToLocalSpace(obj.SelectionQuad.BottomRight));
|
||||
}
|
||||
|
||||
topLeft -= new Vector2(5);
|
||||
bottomRight += new Vector2(5);
|
||||
|
||||
Size = bottomRight - topLeft;
|
||||
Position = topLeft;
|
||||
}
|
||||
|
||||
public override bool DisposeOnDeathRemoval => true;
|
||||
|
||||
protected override void PopIn() => this.FadeIn();
|
||||
protected override void PopOut() => this.FadeOut();
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Layers.Selection
|
||||
{
|
||||
public class HitObjectOverlay : OverlayContainer
|
||||
{
|
||||
// ReSharper disable once NotAccessedField.Local
|
||||
// This will be used later to handle drag movement, etc
|
||||
private readonly DrawableHitObject hitObject;
|
||||
|
||||
public HitObjectOverlay(DrawableHitObject hitObject)
|
||||
{
|
||||
this.hitObject = hitObject;
|
||||
|
||||
State = Visibility.Visible;
|
||||
}
|
||||
|
||||
protected override void PopIn() => Alpha = 1;
|
||||
protected override void PopOut() => Alpha = 0;
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Layers.Selection
|
||||
{
|
||||
/// <summary>
|
||||
/// A box that represents a drag selection.
|
||||
/// </summary>
|
||||
public class SelectionBox : VisibilityContainer
|
||||
{
|
||||
public const float BORDER_RADIUS = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="SelectionBox"/>.
|
||||
/// </summary>
|
||||
public SelectionBox()
|
||||
{
|
||||
Masking = true;
|
||||
BorderColour = Color4.White;
|
||||
BorderThickness = BORDER_RADIUS;
|
||||
|
||||
Child = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0.1f
|
||||
};
|
||||
}
|
||||
|
||||
public void SetDragRectangle(RectangleF rectangle)
|
||||
{
|
||||
var topLeft = Parent.ToLocalSpace(rectangle.TopLeft);
|
||||
var bottomRight = Parent.ToLocalSpace(rectangle.BottomRight);
|
||||
|
||||
Position = topLeft;
|
||||
Size = bottomRight - topLeft;
|
||||
}
|
||||
|
||||
public override bool DisposeOnDeathRemoval => true;
|
||||
|
||||
protected override void PopIn() => this.FadeIn(250, Easing.OutQuint);
|
||||
protected override void PopOut() => this.FadeOut(250, Easing.OutQuint);
|
||||
}
|
||||
}
|
13
osu.Game/Rulesets/Edit/Types/IHasEditablePosition.cs
Normal file
13
osu.Game/Rulesets/Edit/Types/IHasEditablePosition.cs
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Types
|
||||
{
|
||||
public interface IHasEditablePosition : IHasPosition
|
||||
{
|
||||
void OffsetPosition(Vector2 offset);
|
||||
}
|
||||
}
|
@ -9,7 +9,10 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Skinning;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Judgements
|
||||
{
|
||||
@ -18,43 +21,37 @@ namespace osu.Game.Rulesets.Judgements
|
||||
/// </summary>
|
||||
public class DrawableJudgement : Container
|
||||
{
|
||||
private const float judgement_size = 80;
|
||||
|
||||
protected readonly Judgement Judgement;
|
||||
|
||||
protected readonly SpriteText JudgementText;
|
||||
public readonly DrawableHitObject JudgedObject;
|
||||
|
||||
protected SpriteText JudgementText;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a drawable which visualises a <see cref="Judgements.Judgement"/>.
|
||||
/// </summary>
|
||||
/// <param name="judgement">The judgement to visualise.</param>
|
||||
public DrawableJudgement(Judgement judgement)
|
||||
public DrawableJudgement(Judgement judgement, DrawableHitObject judgedObject)
|
||||
{
|
||||
Judgement = judgement;
|
||||
JudgedObject = judgedObject;
|
||||
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
||||
Children = new[]
|
||||
{
|
||||
JudgementText = new OsuSpriteText
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Text = judgement.Result.GetDescription().ToUpper(),
|
||||
Font = @"Venera",
|
||||
Scale = new Vector2(0.85f, 1),
|
||||
TextSize = 12
|
||||
}
|
||||
};
|
||||
Size = new Vector2(judgement_size);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
switch (Judgement.Result)
|
||||
Child = new SkinnableDrawable($"Play/{Judgement.Result}", _ => JudgementText = new OsuSpriteText
|
||||
{
|
||||
case HitResult.Miss:
|
||||
Colour = colours.Red;
|
||||
break;
|
||||
}
|
||||
Text = Judgement.Result.GetDescription().ToUpper(),
|
||||
Font = @"Venera",
|
||||
Colour = Judgement.Result == HitResult.Miss ? colours.Red : Color4.White,
|
||||
Scale = new Vector2(0.85f, 1),
|
||||
TextSize = 12
|
||||
}, restrictSize: false);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
|
@ -188,8 +188,8 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
||||
|
||||
string[] split = str.Split(':');
|
||||
|
||||
var bank = (LegacyDecoder.LegacySampleBank)Convert.ToInt32(split[0]);
|
||||
var addbank = (LegacyDecoder.LegacySampleBank)Convert.ToInt32(split[1]);
|
||||
var bank = (LegacyBeatmapDecoder.LegacySampleBank)Convert.ToInt32(split[0]);
|
||||
var addbank = (LegacyBeatmapDecoder.LegacySampleBank)Convert.ToInt32(split[1]);
|
||||
|
||||
// Let's not implement this for now, because this doesn't fit nicely into the bank structure
|
||||
//string sampleFile = split2.Length > 4 ? split2[4] : string.Empty;
|
||||
|
@ -63,7 +63,7 @@ namespace osu.Game.Rulesets
|
||||
var instances = loaded_assemblies.Values.Select(r => (Ruleset)Activator.CreateInstance(r, (RulesetInfo)null)).ToList();
|
||||
|
||||
//add all legacy modes in correct order
|
||||
foreach (var r in instances.Where(r => r.LegacyID >= 0).OrderBy(r => r.LegacyID))
|
||||
foreach (var r in instances.Where(r => r.LegacyID != null).OrderBy(r => r.LegacyID))
|
||||
{
|
||||
if (context.RulesetInfo.SingleOrDefault(rsi => rsi.ID == r.RulesetInfo.ID) == null)
|
||||
context.RulesetInfo.Add(r.RulesetInfo);
|
||||
@ -72,7 +72,7 @@ namespace osu.Game.Rulesets
|
||||
context.SaveChanges();
|
||||
|
||||
//add any other modes
|
||||
foreach (var r in instances.Where(r => r.LegacyID < 0))
|
||||
foreach (var r in instances.Where(r => r.LegacyID == null))
|
||||
if (context.RulesetInfo.FirstOrDefault(ri => ri.InstantiationInfo == r.RulesetInfo.InstantiationInfo) == null)
|
||||
context.RulesetInfo.Add(r.RulesetInfo);
|
||||
|
||||
|
@ -2,7 +2,9 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Scoring
|
||||
@ -23,9 +25,15 @@ namespace osu.Game.Rulesets.Scoring
|
||||
|
||||
protected PerformanceCalculator(Ruleset ruleset, Beatmap beatmap, Score score)
|
||||
{
|
||||
Beatmap = CreateBeatmapConverter().Convert(beatmap);
|
||||
Score = score;
|
||||
|
||||
var converter = CreateBeatmapConverter();
|
||||
|
||||
foreach (var mod in score.Mods.OfType<IApplicableToBeatmapConverter<TObject>>())
|
||||
mod.ApplyToBeatmapConverter(converter);
|
||||
|
||||
Beatmap = converter.Convert(beatmap);
|
||||
|
||||
var diffCalc = ruleset.CreateDifficultyCalculator(beatmap, score.Mods);
|
||||
diffCalc.Calculate(attributes);
|
||||
}
|
||||
|
24
osu.Game/Rulesets/UI/JudgementContainer.cs
Normal file
24
osu.Game/Rulesets/UI/JudgementContainer.cs
Normal file
@ -0,0 +1,24 @@
|
||||
// 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 osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
|
||||
namespace osu.Game.Rulesets.UI
|
||||
{
|
||||
public class JudgementContainer<T> : Container<T>
|
||||
where T : DrawableJudgement
|
||||
{
|
||||
public override void Add(T judgement)
|
||||
{
|
||||
if (judgement == null) throw new ArgumentNullException(nameof(judgement));
|
||||
|
||||
// remove any existing judgements for the judged object.
|
||||
// this can be the case when rewinding.
|
||||
RemoveAll(c => c.JudgedObject == judgement.JudgedObject);
|
||||
|
||||
base.Add(judgement);
|
||||
}
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Layers
|
||||
namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
{
|
||||
public class BorderLayer : Container
|
||||
{
|
@ -1,20 +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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Layers.Selection
|
||||
namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
{
|
||||
public class HitObjectOverlayLayer : CompositeDrawable
|
||||
public class HitObjectMaskLayer : CompositeDrawable
|
||||
{
|
||||
private readonly Dictionary<DrawableHitObject, HitObjectOverlay> existingOverlays = new Dictionary<DrawableHitObject, HitObjectOverlay>();
|
||||
private readonly HitObjectComposer composer;
|
||||
private readonly Container<HitObjectMask> overlayContainer;
|
||||
|
||||
public HitObjectOverlayLayer()
|
||||
public HitObjectMaskLayer(HitObjectComposer composer)
|
||||
{
|
||||
this.composer = composer;
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
InternalChild = overlayContainer = new Container<HitObjectMask> { RelativeSizeAxes = Axes.Both };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -23,12 +28,11 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
|
||||
/// <param name="hitObject">The <see cref="DrawableHitObject"/> to create an overlay for.</param>
|
||||
public void AddOverlay(DrawableHitObject hitObject)
|
||||
{
|
||||
var overlay = CreateOverlayFor(hitObject);
|
||||
var overlay = composer.CreateMaskFor(hitObject);
|
||||
if (overlay == null)
|
||||
return;
|
||||
|
||||
existingOverlays[hitObject] = overlay;
|
||||
AddInternal(overlay);
|
||||
overlayContainer.Add(overlay);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -37,17 +41,22 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
|
||||
/// <param name="hitObject">The <see cref="DrawableHitObject"/> to remove the overlay for.</param>
|
||||
public void RemoveOverlay(DrawableHitObject hitObject)
|
||||
{
|
||||
if (!existingOverlays.TryGetValue(hitObject, out var existing))
|
||||
var existing = overlayContainer.FirstOrDefault(h => h.HitObject == hitObject);
|
||||
if (existing == null)
|
||||
return;
|
||||
|
||||
existing.Hide();
|
||||
existing.Expire();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="HitObjectOverlay"/> for a specific <see cref="DrawableHitObject"/>.
|
||||
/// </summary>
|
||||
/// <param name="hitObject">The <see cref="DrawableHitObject"/> to create the overlay for.</param>
|
||||
protected virtual HitObjectOverlay CreateOverlayFor(DrawableHitObject hitObject) => null;
|
||||
private SelectionBox currentSelectionBox;
|
||||
|
||||
public void AddSelectionOverlay() => AddInternal(currentSelectionBox = composer.CreateSelectionOverlay(overlayContainer));
|
||||
|
||||
public void RemoveSelectionOverlay()
|
||||
{
|
||||
currentSelectionBox?.Hide();
|
||||
currentSelectionBox?.Expire();
|
||||
}
|
||||
}
|
||||
}
|
102
osu.Game/Screens/Edit/Screens/Compose/Layers/SelectionBox.cs
Normal file
102
osu.Game/Screens/Edit/Screens/Compose/Layers/SelectionBox.cs
Normal file
@ -0,0 +1,102 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Types;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
{
|
||||
/// <summary>
|
||||
/// A box which surrounds <see cref="DrawableHitObject"/>s and provides interactive handles, context menus etc.
|
||||
/// </summary>
|
||||
public class SelectionBox : VisibilityContainer
|
||||
{
|
||||
private readonly IReadOnlyList<HitObjectMask> overlays;
|
||||
|
||||
public const float BORDER_RADIUS = 2;
|
||||
|
||||
public SelectionBox(IReadOnlyList<HitObjectMask> overlays)
|
||||
{
|
||||
this.overlays = overlays;
|
||||
|
||||
Masking = true;
|
||||
BorderThickness = BORDER_RADIUS;
|
||||
|
||||
InternalChild = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
AlwaysPresent = true,
|
||||
Alpha = 0
|
||||
};
|
||||
|
||||
State = Visibility.Visible;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
BorderColour = colours.Yellow;
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
// Todo: We might need to optimise this
|
||||
|
||||
// Move the rectangle to cover the hitobjects
|
||||
var topLeft = new Vector2(float.MaxValue, float.MaxValue);
|
||||
var bottomRight = new Vector2(float.MinValue, float.MinValue);
|
||||
|
||||
foreach (var obj in overlays)
|
||||
{
|
||||
topLeft = Vector2.ComponentMin(topLeft, Parent.ToLocalSpace(obj.HitObject.SelectionQuad.TopLeft));
|
||||
bottomRight = Vector2.ComponentMax(bottomRight, Parent.ToLocalSpace(obj.HitObject.SelectionQuad.BottomRight));
|
||||
}
|
||||
|
||||
topLeft -= new Vector2(5);
|
||||
bottomRight += new Vector2(5);
|
||||
|
||||
Size = bottomRight - topLeft;
|
||||
Position = topLeft;
|
||||
}
|
||||
|
||||
public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => overlays.Any(o => o.ReceiveMouseInputAt(screenSpacePos));
|
||||
|
||||
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true;
|
||||
|
||||
protected override bool OnDragStart(InputState state) => true;
|
||||
|
||||
protected override bool OnDrag(InputState state)
|
||||
{
|
||||
// Todo: Various forms of snapping
|
||||
foreach (var hitObject in overlays.Select(o => o.HitObject.HitObject))
|
||||
{
|
||||
switch (hitObject)
|
||||
{
|
||||
case IHasEditablePosition editablePosition:
|
||||
editablePosition.OffsetPosition(state.Mouse.Delta);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnDragEnd(InputState state) => true;
|
||||
|
||||
public override bool DisposeOnDeathRemoval => true;
|
||||
|
||||
protected override void PopIn() => this.FadeIn();
|
||||
protected override void PopOut() => this.FadeOut();
|
||||
}
|
||||
}
|
@ -8,12 +8,14 @@ using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Layers.Selection
|
||||
namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
{
|
||||
public class SelectionLayer : CompositeDrawable
|
||||
{
|
||||
@ -27,6 +29,16 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
|
||||
/// </summary>
|
||||
public event Action<DrawableHitObject> ObjectDeselected;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when the selection has been cleared.
|
||||
/// </summary>
|
||||
public event Action SelectionCleared;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when the user has finished selecting all <see cref="DrawableHitObject"/>s.
|
||||
/// </summary>
|
||||
public event Action SelectionFinished;
|
||||
|
||||
private readonly Playfield playfield;
|
||||
|
||||
public SelectionLayer(Playfield playfield)
|
||||
@ -36,8 +48,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
private SelectionBox selectionBox;
|
||||
private CaptureBox captureBox;
|
||||
private DragBox dragBox;
|
||||
|
||||
private readonly HashSet<DrawableHitObject> selectedHitObjects = new HashSet<DrawableHitObject>();
|
||||
|
||||
@ -49,20 +60,20 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
|
||||
|
||||
protected override bool OnDragStart(InputState state)
|
||||
{
|
||||
AddInternal(selectionBox = new SelectionBox());
|
||||
AddInternal(dragBox = new DragBox());
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnDrag(InputState state)
|
||||
{
|
||||
selectionBox.Show();
|
||||
dragBox.Show();
|
||||
|
||||
var dragPosition = state.Mouse.NativeState.Position;
|
||||
var dragStartPosition = state.Mouse.NativeState.PositionMouseDown ?? dragPosition;
|
||||
|
||||
var screenSpaceDragQuad = new Quad(dragStartPosition.X, dragStartPosition.Y, dragPosition.X - dragStartPosition.X, dragPosition.Y - dragStartPosition.Y);
|
||||
|
||||
selectionBox.SetDragRectangle(screenSpaceDragQuad.AABBFloat);
|
||||
dragBox.SetDragRectangle(screenSpaceDragQuad.AABBFloat);
|
||||
selectQuad(screenSpaceDragQuad);
|
||||
|
||||
return true;
|
||||
@ -70,8 +81,8 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
|
||||
|
||||
protected override bool OnDragEnd(InputState state)
|
||||
{
|
||||
selectionBox.Hide();
|
||||
selectionBox.Expire();
|
||||
dragBox.Hide();
|
||||
dragBox.Expire();
|
||||
|
||||
finishSelection();
|
||||
|
||||
@ -95,7 +106,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
|
||||
if (!select(hitObject))
|
||||
return;
|
||||
|
||||
clearCapture();
|
||||
clearSelection();
|
||||
finishSelection();
|
||||
}
|
||||
|
||||
@ -122,7 +133,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
|
||||
if (!deselect(hitObject))
|
||||
return;
|
||||
|
||||
clearCapture();
|
||||
clearSelection();
|
||||
finishSelection();
|
||||
}
|
||||
|
||||
@ -148,7 +159,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
|
||||
selectedHitObjects.ForEach(h => ObjectDeselected?.Invoke(h));
|
||||
selectedHitObjects.Clear();
|
||||
|
||||
clearCapture();
|
||||
clearSelection();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -180,18 +191,49 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
|
||||
select(target);
|
||||
}
|
||||
|
||||
private void clearCapture()
|
||||
{
|
||||
captureBox?.Hide();
|
||||
captureBox?.Expire();
|
||||
}
|
||||
private void clearSelection() => SelectionCleared?.Invoke();
|
||||
|
||||
private void finishSelection()
|
||||
{
|
||||
if (selectedHitObjects.Count == 0)
|
||||
return;
|
||||
SelectionFinished?.Invoke();
|
||||
}
|
||||
|
||||
AddInternal(captureBox = new CaptureBox(this, selectedHitObjects.ToList()));
|
||||
/// <summary>
|
||||
/// A box that represents a drag selection.
|
||||
/// </summary>
|
||||
private class DragBox : VisibilityContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="DragBox"/>.
|
||||
/// </summary>
|
||||
public DragBox()
|
||||
{
|
||||
Masking = true;
|
||||
BorderColour = Color4.White;
|
||||
BorderThickness = SelectionBox.BORDER_RADIUS;
|
||||
|
||||
Child = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0.1f
|
||||
};
|
||||
}
|
||||
|
||||
public void SetDragRectangle(RectangleF rectangle)
|
||||
{
|
||||
var topLeft = Parent.ToLocalSpace(rectangle.TopLeft);
|
||||
var bottomRight = Parent.ToLocalSpace(rectangle.BottomRight);
|
||||
|
||||
Position = topLeft;
|
||||
Size = bottomRight - topLeft;
|
||||
}
|
||||
|
||||
public override bool DisposeOnDeathRemoval => true;
|
||||
|
||||
protected override void PopIn() => this.FadeIn(250, Easing.OutQuint);
|
||||
protected override void PopOut() => this.FadeOut(250, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
}
|
@ -8,6 +8,9 @@ using osu.Game.Beatmaps;
|
||||
|
||||
namespace osu.Game.Screens.Edit.Screens
|
||||
{
|
||||
/// <summary>
|
||||
/// TODO: eventually make this inherit Screen and add a local scren stack inside the Editor.
|
||||
/// </summary>
|
||||
public class EditorScreen : Container
|
||||
{
|
||||
public readonly Bindable<WorkingBeatmap> Beatmap = new Bindable<WorkingBeatmap>();
|
||||
|
@ -1,13 +1,13 @@
|
||||
// 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.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Screens.Play.BreaksOverlay
|
||||
namespace osu.Game.Screens.Play.Break
|
||||
{
|
||||
public class BlurredIcon : BufferedContainer
|
||||
{
|
@ -1,18 +1,15 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics;
|
||||
using OpenTK;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Beatmaps.Timing;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Screens.Play.BreaksOverlay
|
||||
namespace osu.Game.Screens.Play.Break
|
||||
{
|
||||
public class ArrowsOverlay : VisibilityContainer
|
||||
public class BreakArrows : CompositeDrawable
|
||||
{
|
||||
private const double fade_duration = BreakPeriod.MIN_BREAK_DURATION / 2;
|
||||
|
||||
private const int glow_icon_size = 60;
|
||||
private const int glow_icon_blur_sigma = 10;
|
||||
private const float glow_icon_final_offset = 0.22f;
|
||||
@ -29,10 +26,10 @@ namespace osu.Game.Screens.Play.BreaksOverlay
|
||||
private readonly BlurredIcon leftBlurredIcon;
|
||||
private readonly BlurredIcon rightBlurredIcon;
|
||||
|
||||
public ArrowsOverlay()
|
||||
public BreakArrows()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Children = new Drawable[]
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
leftGlowIcon = new GlowIcon
|
||||
{
|
||||
@ -82,22 +79,22 @@ namespace osu.Game.Screens.Play.BreaksOverlay
|
||||
};
|
||||
}
|
||||
|
||||
protected override void PopIn()
|
||||
public void Show(double duration)
|
||||
{
|
||||
leftGlowIcon.MoveToX(-glow_icon_final_offset, fade_duration, Easing.OutQuint);
|
||||
rightGlowIcon.MoveToX(glow_icon_final_offset, fade_duration, Easing.OutQuint);
|
||||
leftGlowIcon.MoveToX(-glow_icon_final_offset, duration, Easing.OutQuint);
|
||||
rightGlowIcon.MoveToX(glow_icon_final_offset, duration, Easing.OutQuint);
|
||||
|
||||
leftBlurredIcon.MoveToX(-blurred_icon_final_offset, fade_duration, Easing.OutQuint);
|
||||
rightBlurredIcon.MoveToX(blurred_icon_final_offset, fade_duration, Easing.OutQuint);
|
||||
leftBlurredIcon.MoveToX(-blurred_icon_final_offset, duration, Easing.OutQuint);
|
||||
rightBlurredIcon.MoveToX(blurred_icon_final_offset, duration, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override void PopOut()
|
||||
public void Hide(double duration)
|
||||
{
|
||||
leftGlowIcon.MoveToX(-glow_icon_offscreen_offset, fade_duration, Easing.OutQuint);
|
||||
rightGlowIcon.MoveToX(glow_icon_offscreen_offset, fade_duration, Easing.OutQuint);
|
||||
leftGlowIcon.MoveToX(-glow_icon_offscreen_offset, duration, Easing.OutQuint);
|
||||
rightGlowIcon.MoveToX(glow_icon_offscreen_offset, duration, Easing.OutQuint);
|
||||
|
||||
leftBlurredIcon.MoveToX(-blurred_icon_offscreen_offset, fade_duration, Easing.OutQuint);
|
||||
rightBlurredIcon.MoveToX(blurred_icon_offscreen_offset, fade_duration, Easing.OutQuint);
|
||||
leftBlurredIcon.MoveToX(-blurred_icon_offscreen_offset, duration, Easing.OutQuint);
|
||||
rightBlurredIcon.MoveToX(blurred_icon_offscreen_offset, duration, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,24 +1,21 @@
|
||||
// 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.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Beatmaps.Timing;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Screens.Play.BreaksOverlay
|
||||
namespace osu.Game.Screens.Play.Break
|
||||
{
|
||||
public class InfoContainer : VisibilityContainer
|
||||
public class BreakInfo : Container
|
||||
{
|
||||
private const double fade_duration = BreakPeriod.MIN_BREAK_DURATION / 2;
|
||||
public PercentageBreakInfoLine AccuracyDisplay;
|
||||
public BreakInfoLine<int> RankDisplay;
|
||||
public BreakInfoLine<ScoreRank> GradeDisplay;
|
||||
|
||||
public PercentageInfoLine AccuracyDisplay;
|
||||
public InfoLine<int> RankDisplay;
|
||||
public InfoLine<ScoreRank> GradeDisplay;
|
||||
|
||||
public InfoContainer()
|
||||
public BreakInfo()
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
Child = new FillFlowContainer
|
||||
@ -43,16 +40,13 @@ namespace osu.Game.Screens.Play.BreaksOverlay
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
AccuracyDisplay = new PercentageInfoLine("Accuracy"),
|
||||
RankDisplay = new InfoLine<int>("Rank"),
|
||||
GradeDisplay = new InfoLine<ScoreRank>("Grade"),
|
||||
AccuracyDisplay = new PercentageBreakInfoLine("Accuracy"),
|
||||
RankDisplay = new BreakInfoLine<int>("Rank"),
|
||||
GradeDisplay = new BreakInfoLine<ScoreRank>("Grade"),
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected override void PopIn() => this.FadeIn(fade_duration);
|
||||
protected override void PopOut() => this.FadeOut(fade_duration);
|
||||
}
|
||||
}
|
@ -8,9 +8,9 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
|
||||
namespace osu.Game.Screens.Play.BreaksOverlay
|
||||
namespace osu.Game.Screens.Play.Break
|
||||
{
|
||||
public class InfoLine<T> : Container
|
||||
public class BreakInfoLine<T> : Container
|
||||
where T : struct
|
||||
{
|
||||
private const int margin = 2;
|
||||
@ -22,7 +22,7 @@ namespace osu.Game.Screens.Play.BreaksOverlay
|
||||
|
||||
private readonly string prefix;
|
||||
|
||||
public InfoLine(string name, string prefix = @"")
|
||||
public BreakInfoLine(string name, string prefix = @"")
|
||||
{
|
||||
this.prefix = prefix;
|
||||
|
||||
@ -71,9 +71,9 @@ namespace osu.Game.Screens.Play.BreaksOverlay
|
||||
}
|
||||
}
|
||||
|
||||
public class PercentageInfoLine : InfoLine<double>
|
||||
public class PercentageBreakInfoLine : BreakInfoLine<double>
|
||||
{
|
||||
public PercentageInfoLine(string name, string prefix = "") : base(name, prefix)
|
||||
public PercentageBreakInfoLine(string name, string prefix = "") : base(name, prefix)
|
||||
{
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using OpenTK;
|
||||
using osu.Framework.Allocation;
|
||||
|
||||
namespace osu.Game.Screens.Play.BreaksOverlay
|
||||
namespace osu.Game.Screens.Play.Break
|
||||
{
|
||||
public class GlowIcon : Container
|
||||
{
|
||||
@ -16,24 +16,24 @@ namespace osu.Game.Screens.Play.BreaksOverlay
|
||||
|
||||
public override Vector2 Size
|
||||
{
|
||||
get { return base.Size; }
|
||||
set
|
||||
{
|
||||
blurredIcon.Size = spriteIcon.Size = value;
|
||||
blurredIcon.ForceRedraw();
|
||||
}
|
||||
get { return base.Size; }
|
||||
}
|
||||
|
||||
public Vector2 BlurSigma
|
||||
{
|
||||
set { blurredIcon.BlurSigma = value; }
|
||||
get { return blurredIcon.BlurSigma; }
|
||||
set { blurredIcon.BlurSigma = value; }
|
||||
}
|
||||
|
||||
public FontAwesome Icon
|
||||
{
|
||||
set { spriteIcon.Icon = blurredIcon.Icon = value; }
|
||||
get { return spriteIcon.Icon; }
|
||||
set { spriteIcon.Icon = blurredIcon.Icon = value; }
|
||||
}
|
||||
|
||||
public GlowIcon()
|
@ -1,18 +1,16 @@
|
||||
// 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.Graphics;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Beatmaps.Timing;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Play.BreaksOverlay
|
||||
namespace osu.Game.Screens.Play.Break
|
||||
{
|
||||
public class LetterboxOverlay : VisibilityContainer
|
||||
public class LetterboxOverlay : CompositeDrawable
|
||||
{
|
||||
private const double fade_duration = BreakPeriod.MIN_BREAK_DURATION / 2;
|
||||
private const int height = 350;
|
||||
|
||||
private static readonly Color4 transparent_black = new Color4(0, 0, 0, 0);
|
||||
@ -20,7 +18,7 @@ namespace osu.Game.Screens.Play.BreaksOverlay
|
||||
public LetterboxOverlay()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Children = new Drawable[]
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
@ -48,8 +46,5 @@ namespace osu.Game.Screens.Play.BreaksOverlay
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void PopIn() => this.FadeIn(fade_duration);
|
||||
protected override void PopOut() => this.FadeOut(fade_duration);
|
||||
}
|
||||
}
|
@ -1,18 +1,15 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Framework.Graphics;
|
||||
using System;
|
||||
using osu.Game.Beatmaps.Timing;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
|
||||
namespace osu.Game.Screens.Play.BreaksOverlay
|
||||
namespace osu.Game.Screens.Play.Break
|
||||
{
|
||||
public class RemainingTimeCounter : Counter
|
||||
{
|
||||
private const double fade_duration = BreakPeriod.MIN_BREAK_DURATION / 2;
|
||||
|
||||
private readonly OsuSpriteText counter;
|
||||
|
||||
public RemainingTimeCounter()
|
||||
@ -25,13 +22,8 @@ namespace osu.Game.Screens.Play.BreaksOverlay
|
||||
TextSize = 33,
|
||||
Font = "Venera",
|
||||
};
|
||||
|
||||
Alpha = 0;
|
||||
}
|
||||
|
||||
protected override void OnCountChanged(double count) => counter.Text = ((int)Math.Ceiling(count / 1000)).ToString();
|
||||
|
||||
public override void Show() => this.FadeIn(fade_duration);
|
||||
public override void Hide() => this.FadeOut(fade_duration);
|
||||
}
|
||||
}
|
@ -1,15 +1,16 @@
|
||||
// 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.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Game.Beatmaps.Timing;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Game.Screens.Play.Break;
|
||||
|
||||
namespace osu.Game.Screens.Play.BreaksOverlay
|
||||
namespace osu.Game.Screens.Play
|
||||
{
|
||||
public class BreakOverlay : Container
|
||||
{
|
||||
@ -18,28 +19,26 @@ namespace osu.Game.Screens.Play.BreaksOverlay
|
||||
private const int vertical_margin = 25;
|
||||
|
||||
private List<BreakPeriod> breaks;
|
||||
|
||||
private readonly Container fadeContainer;
|
||||
|
||||
public List<BreakPeriod> Breaks
|
||||
{
|
||||
get => breaks;
|
||||
set
|
||||
{
|
||||
breaks = value;
|
||||
initializeBreaks();
|
||||
}
|
||||
get
|
||||
{
|
||||
return breaks;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool RemoveCompletedTransforms => false;
|
||||
|
||||
private readonly bool letterboxing;
|
||||
private readonly LetterboxOverlay letterboxOverlay;
|
||||
private readonly Container remainingTimeAdjustmentBox;
|
||||
private readonly Container remainingTimeBox;
|
||||
private readonly RemainingTimeCounter remainingTimeCounter;
|
||||
private readonly InfoContainer info;
|
||||
private readonly ArrowsOverlay arrowsOverlay;
|
||||
private readonly BreakInfo info;
|
||||
private readonly BreakArrows breakArrows;
|
||||
|
||||
public BreakOverlay(bool letterboxing, ScoreProcessor scoreProcessor)
|
||||
: this(letterboxing)
|
||||
@ -49,61 +48,72 @@ namespace osu.Game.Screens.Play.BreaksOverlay
|
||||
|
||||
public BreakOverlay(bool letterboxing)
|
||||
{
|
||||
this.letterboxing = letterboxing;
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Children = new Drawable[]
|
||||
Child = fadeContainer = new Container
|
||||
{
|
||||
letterboxOverlay = new LetterboxOverlay
|
||||
Alpha = 0,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
},
|
||||
remainingTimeAdjustmentBox = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Width = 0,
|
||||
Child = remainingTimeBox = new Container
|
||||
new LetterboxOverlay
|
||||
{
|
||||
Alpha = letterboxing ? 1 : 0,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
},
|
||||
remainingTimeAdjustmentBox = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 8,
|
||||
CornerRadius = 4,
|
||||
Masking = true,
|
||||
Child = new Box { RelativeSizeAxes = Axes.Both }
|
||||
Width = 0,
|
||||
Child = remainingTimeBox = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 8,
|
||||
CornerRadius = 4,
|
||||
Masking = true,
|
||||
Child = new Box { RelativeSizeAxes = Axes.Both }
|
||||
}
|
||||
},
|
||||
remainingTimeCounter = new RemainingTimeCounter
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
Margin = new MarginPadding { Bottom = vertical_margin },
|
||||
},
|
||||
info = new BreakInfo
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Margin = new MarginPadding { Top = vertical_margin },
|
||||
},
|
||||
breakArrows = new BreakArrows
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
}
|
||||
},
|
||||
remainingTimeCounter = new RemainingTimeCounter
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
Margin = new MarginPadding { Bottom = vertical_margin },
|
||||
},
|
||||
info = new InfoContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Margin = new MarginPadding { Top = vertical_margin },
|
||||
},
|
||||
arrowsOverlay = new ArrowsOverlay
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
initializeBreaks();
|
||||
}
|
||||
|
||||
private void initializeBreaks()
|
||||
{
|
||||
if (!IsLoaded) return; // we need a clock.
|
||||
|
||||
FinishTransforms(true);
|
||||
Scheduler.CancelDelayedTasks();
|
||||
|
||||
if (breaks == null)
|
||||
return;
|
||||
if (breaks == null) return; //we need breaks.
|
||||
|
||||
foreach (var b in breaks)
|
||||
{
|
||||
@ -112,6 +122,9 @@ namespace osu.Game.Screens.Play.BreaksOverlay
|
||||
|
||||
using (BeginAbsoluteSequence(b.StartTime, true))
|
||||
{
|
||||
fadeContainer.FadeIn(fade_duration);
|
||||
breakArrows.Show(fade_duration);
|
||||
|
||||
remainingTimeAdjustmentBox
|
||||
.ResizeWidthTo(remaining_time_container_max_size, fade_duration, Easing.OutQuint)
|
||||
.Delay(b.Duration - fade_duration)
|
||||
@ -123,37 +136,16 @@ namespace osu.Game.Screens.Play.BreaksOverlay
|
||||
.ResizeWidthTo(1);
|
||||
|
||||
remainingTimeCounter.CountTo(b.Duration).CountTo(0, b.Duration);
|
||||
}
|
||||
|
||||
using (BeginAbsoluteSequence(b.StartTime))
|
||||
{
|
||||
Schedule(showBreak);
|
||||
using (BeginDelayedSequence(b.Duration - fade_duration))
|
||||
Schedule(hideBreak);
|
||||
using (BeginDelayedSequence(b.Duration - fade_duration, true))
|
||||
{
|
||||
fadeContainer.FadeOut(fade_duration);
|
||||
breakArrows.Hide(fade_duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void showBreak()
|
||||
{
|
||||
if (letterboxing)
|
||||
letterboxOverlay.Show();
|
||||
|
||||
remainingTimeCounter.Show();
|
||||
info.Show();
|
||||
arrowsOverlay.Show();
|
||||
}
|
||||
|
||||
private void hideBreak()
|
||||
{
|
||||
if (letterboxing)
|
||||
letterboxOverlay.Hide();
|
||||
|
||||
remainingTimeCounter.Hide();
|
||||
info.Hide();
|
||||
arrowsOverlay.Hide();
|
||||
}
|
||||
|
||||
private void bindProcessor(ScoreProcessor processor)
|
||||
{
|
||||
info.AccuracyDisplay.Current.BindTo(processor.Accuracy);
|
@ -25,7 +25,6 @@ using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Screens.Play.BreaksOverlay;
|
||||
using osu.Game.Screens.Ranking;
|
||||
using osu.Game.Storyboards.Drawables;
|
||||
|
||||
|
@ -169,20 +169,43 @@ namespace osu.Game.Screens.Select
|
||||
});
|
||||
}
|
||||
|
||||
public void SelectBeatmap(BeatmapInfo beatmap)
|
||||
/// <summary>
|
||||
/// Selects a given beatmap on the carousel.
|
||||
///
|
||||
/// If bypassFilters is false, we will try to select another unfiltered beatmap in the same set. If the
|
||||
/// entire set is filtered, no selection is made.
|
||||
/// </summary>
|
||||
/// <param name="beatmap">The beatmap to select.</param>
|
||||
/// <param name="bypassFilters">Whether to select the beatmap even if it is filtered (i.e., not visible on carousel).</param>
|
||||
/// <returns>True if a selection was made, False if it wasn't.</returns>
|
||||
public bool SelectBeatmap(BeatmapInfo beatmap, bool bypassFilters = true)
|
||||
{
|
||||
if (beatmap?.Hidden != false)
|
||||
return;
|
||||
return false;
|
||||
|
||||
foreach (CarouselBeatmapSet group in beatmapSets)
|
||||
foreach (CarouselBeatmapSet set in beatmapSets)
|
||||
{
|
||||
var item = group.Beatmaps.FirstOrDefault(p => p.Beatmap.Equals(beatmap));
|
||||
if (!bypassFilters && set.Filtered)
|
||||
continue;
|
||||
|
||||
var item = set.Beatmaps.FirstOrDefault(p => p.Beatmap.Equals(beatmap));
|
||||
|
||||
if (item == null)
|
||||
// The beatmap that needs to be selected doesn't exist in this set
|
||||
continue;
|
||||
|
||||
if (!bypassFilters && item.Filtered)
|
||||
// The beatmap exists in this set but is filtered, so look for the first unfiltered map in the set
|
||||
item = set.Beatmaps.FirstOrDefault(b => !b.Filtered);
|
||||
|
||||
if (item != null)
|
||||
{
|
||||
select(item);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -214,11 +214,7 @@ namespace osu.Game.Screens.Select
|
||||
Beatmap.DisabledChanged += disabled => Carousel.AllowSelection = !disabled;
|
||||
Beatmap.TriggerChange();
|
||||
|
||||
Beatmap.ValueChanged += b =>
|
||||
{
|
||||
if (IsCurrentScreen)
|
||||
Carousel.SelectBeatmap(b?.BeatmapInfo);
|
||||
};
|
||||
Beatmap.ValueChanged += workingBeatmapChanged;
|
||||
}
|
||||
|
||||
public void Edit(BeatmapInfo beatmap)
|
||||
@ -261,6 +257,17 @@ namespace osu.Game.Screens.Select
|
||||
// We need to keep track of the last selected beatmap ignoring debounce to play the correct selection sounds.
|
||||
private BeatmapInfo beatmapNoDebounce;
|
||||
|
||||
private void workingBeatmapChanged(WorkingBeatmap beatmap)
|
||||
{
|
||||
if (IsCurrentScreen && !Carousel.SelectBeatmap(beatmap?.BeatmapInfo, false))
|
||||
// If selecting new beatmap without bypassing filters failed, there's possibly a ruleset mismatch
|
||||
if (beatmap?.BeatmapInfo?.Ruleset != null && beatmap.BeatmapInfo.Ruleset != Ruleset.Value)
|
||||
{
|
||||
Ruleset.Value = beatmap.BeatmapInfo.Ruleset;
|
||||
Carousel.SelectBeatmap(beatmap.BeatmapInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// selection has been changed as the result of interaction with the carousel.
|
||||
/// </summary>
|
||||
@ -450,16 +457,14 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
private void carouselBeatmapsLoaded()
|
||||
{
|
||||
if (!Beatmap.IsDefault && Beatmap.Value.BeatmapSetInfo?.DeletePending == false && Beatmap.Value.BeatmapSetInfo?.Protected == false)
|
||||
if (!Beatmap.IsDefault && Beatmap.Value.BeatmapSetInfo?.DeletePending == false && Beatmap.Value.BeatmapSetInfo?.Protected == false && Carousel.SelectBeatmap(Beatmap.Value.BeatmapInfo, false))
|
||||
return;
|
||||
|
||||
if (Carousel.SelectedBeatmapSet == null && !Carousel.SelectNextRandom())
|
||||
{
|
||||
Carousel.SelectBeatmap(Beatmap.Value.BeatmapInfo);
|
||||
}
|
||||
else if (Carousel.SelectedBeatmapSet == null)
|
||||
{
|
||||
if (!Carousel.SelectNextRandom())
|
||||
// in the case random selection failed, we want to trigger selectionChanged
|
||||
// to show the dummy beatmap (we have nothing else to display).
|
||||
carouselSelectionChanged(null);
|
||||
// in the case random selection failed, we want to trigger selectionChanged
|
||||
// to show the dummy beatmap (we have nothing else to display).
|
||||
carouselSelectionChanged(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,15 +29,26 @@ namespace osu.Game.Skinning
|
||||
|
||||
public override Drawable GetDrawableComponent(string componentName)
|
||||
{
|
||||
switch (componentName)
|
||||
{
|
||||
case "Play/Miss":
|
||||
componentName = "hit0";
|
||||
break;
|
||||
case "Play/Meh":
|
||||
componentName = "hit50";
|
||||
break;
|
||||
case "Play/Good":
|
||||
componentName = "hit100";
|
||||
break;
|
||||
case "Play/Great":
|
||||
componentName = "hit300";
|
||||
break;
|
||||
}
|
||||
|
||||
var texture = textures.Get(componentName);
|
||||
if (texture == null) return null;
|
||||
|
||||
return new Sprite
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
FillMode = FillMode.Fit,
|
||||
Texture = texture,
|
||||
};
|
||||
return new Sprite { Texture = texture };
|
||||
}
|
||||
|
||||
public override SampleChannel GetSample(string sampleName) => samples.Get(sampleName);
|
||||
@ -47,8 +58,14 @@ namespace osu.Game.Skinning
|
||||
private readonly SkinInfo skin;
|
||||
private readonly IResourceStore<byte[]> underlyingStore;
|
||||
|
||||
private string getPathForFile(string filename) =>
|
||||
skin.Files.FirstOrDefault(f => string.Equals(Path.GetFileNameWithoutExtension(f.Filename), filename.Split('/').Last(), StringComparison.InvariantCultureIgnoreCase))?.FileInfo.StoragePath;
|
||||
private string getPathForFile(string filename)
|
||||
{
|
||||
string lastPiece = filename.Split('/').Last();
|
||||
|
||||
var file = skin.Files.FirstOrDefault(f =>
|
||||
string.Equals(Path.GetFileNameWithoutExtension(f.Filename), lastPiece, StringComparison.InvariantCultureIgnoreCase));
|
||||
return file?.FileInfo.StoragePath;
|
||||
}
|
||||
|
||||
public LegacySkinResourceStore(SkinInfo skin, IResourceStore<byte[]> underlyingStore)
|
||||
{
|
||||
|
@ -3,13 +3,14 @@
|
||||
|
||||
using System;
|
||||
using osu.Framework.Graphics;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Skinning
|
||||
{
|
||||
public class SkinnableDrawable : SkinnableDrawable<Drawable>
|
||||
{
|
||||
public SkinnableDrawable(string name, Func<string, Drawable> defaultImplementation, bool fallback = true)
|
||||
: base(name, defaultImplementation, fallback)
|
||||
public SkinnableDrawable(string name, Func<string, Drawable> defaultImplementation, bool fallback = true, bool restrictSize = true)
|
||||
: base(name, defaultImplementation, fallback, restrictSize)
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -21,10 +22,20 @@ namespace osu.Game.Skinning
|
||||
|
||||
private readonly string componentName;
|
||||
|
||||
public SkinnableDrawable(string name, Func<string, T> defaultImplementation, bool fallback = true) : base(fallback)
|
||||
private readonly bool restrictSize;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="name">The namespace-complete resource name for this skinnable element.</param>
|
||||
/// <param name="defaultImplementation">A function to create the default skin implementation of this element.</param>
|
||||
/// <param name="fallback">Whther to fallback to the default implementation when a custom skin is specified but not implementation is present.</param>
|
||||
/// <param name="restrictSize">Whether a user-skin drawable should be limited to the size of our parent.</param>
|
||||
public SkinnableDrawable(string name, Func<string, T> defaultImplementation, bool fallback = true, bool restrictSize = true) : base(fallback)
|
||||
{
|
||||
componentName = name;
|
||||
createDefault = defaultImplementation;
|
||||
this.restrictSize = restrictSize;
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
@ -32,11 +43,25 @@ namespace osu.Game.Skinning
|
||||
protected override void SkinChanged(Skin skin, bool allowFallback)
|
||||
{
|
||||
var drawable = skin.GetDrawableComponent(componentName);
|
||||
if (drawable == null && allowFallback)
|
||||
if (drawable != null)
|
||||
{
|
||||
if (restrictSize)
|
||||
{
|
||||
drawable.RelativeSizeAxes = Axes.Both;
|
||||
drawable.Size = Vector2.One;
|
||||
drawable.FillMode = FillMode.Fit;
|
||||
}
|
||||
}
|
||||
else if (allowFallback)
|
||||
drawable = createDefault(componentName);
|
||||
|
||||
if (drawable != null)
|
||||
{
|
||||
drawable.Origin = Anchor.Centre;
|
||||
drawable.Anchor = Anchor.Centre;
|
||||
|
||||
InternalChild = drawable;
|
||||
}
|
||||
else
|
||||
ClearInternal();
|
||||
}
|
||||
|
@ -112,9 +112,9 @@ namespace osu.Game.Tests.Beatmaps
|
||||
using (var resStream = openResource($"{resource_namespace}.{name}.osu"))
|
||||
using (var stream = new StreamReader(resStream))
|
||||
{
|
||||
var decoder = Decoder.GetDecoder(stream);
|
||||
var decoder = Decoder.GetDecoder<Beatmap>(stream);
|
||||
((LegacyBeatmapDecoder)decoder).ApplyOffsets = false;
|
||||
return decoder.DecodeBeatmap(stream);
|
||||
return decoder.Decode(stream);
|
||||
}
|
||||
}
|
||||
|
||||
|
720
osu.Game/Tests/Beatmaps/TestBeatmap.cs
Normal file
720
osu.Game/Tests/Beatmaps/TestBeatmap.cs
Normal file
@ -0,0 +1,720 @@
|
||||
// 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.IO;
|
||||
using System.Text;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets;
|
||||
using Decoder = osu.Game.Beatmaps.Formats.Decoder;
|
||||
|
||||
namespace osu.Game.Tests.Beatmaps
|
||||
{
|
||||
public class TestBeatmap : Beatmap
|
||||
{
|
||||
public TestBeatmap(RulesetInfo ruleset)
|
||||
: base(createTestBeatmap())
|
||||
{
|
||||
BeatmapInfo.Ruleset = ruleset;
|
||||
}
|
||||
|
||||
private static Beatmap createTestBeatmap()
|
||||
{
|
||||
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(test_beatmap_data)))
|
||||
using (var reader = new StreamReader(stream))
|
||||
return Decoder.GetDecoder<Beatmap>(reader).Decode(reader);
|
||||
}
|
||||
|
||||
private const string test_beatmap_data =
|
||||
@"osu file format v14
|
||||
|
||||
[General]
|
||||
AudioLeadIn: 500
|
||||
PreviewTime: 53498
|
||||
Countdown: 0
|
||||
SampleSet: Soft
|
||||
StackLeniency: 0.7
|
||||
Mode: 0
|
||||
LetterboxInBreaks: 0
|
||||
WidescreenStoryboard: 1
|
||||
|
||||
[Editor]
|
||||
DistanceSpacing: 1.2
|
||||
BeatDivisor: 4
|
||||
GridSize: 4
|
||||
TimelineZoom: 1
|
||||
|
||||
[Metadata]
|
||||
Title:My Love
|
||||
TitleUnicode:My Love
|
||||
Artist:Kuba Oms
|
||||
ArtistUnicode:Kuba Oms
|
||||
Creator:W h i t e
|
||||
Version:Hard
|
||||
Source:ADHD
|
||||
Tags:Monthly Beatmapping Contest Electronic folk pop w_h_i_t_e
|
||||
BeatmapID:397534
|
||||
BeatmapSetID:163112
|
||||
|
||||
[Difficulty]
|
||||
HPDrainRate:5
|
||||
CircleSize:4
|
||||
OverallDifficulty:6
|
||||
ApproachRate:7
|
||||
SliderMultiplier:1.44
|
||||
SliderTickRate:2
|
||||
|
||||
[Events]
|
||||
//Break Periods
|
||||
2,69870,83770
|
||||
2,152170,158770
|
||||
//Storyboard Layer 0 (Background)
|
||||
//Storyboard Layer 1 (Fail)
|
||||
//Storyboard Layer 2 (Pass)
|
||||
//Storyboard Layer 3 (Foreground)
|
||||
//Storyboard Sound Samples
|
||||
|
||||
[TimingPoints]
|
||||
2170,468.75,4,2,0,40,1,0
|
||||
4045,-100,4,2,0,30,0,0
|
||||
4162,-100,4,2,0,40,0,0
|
||||
5920,-100,4,2,0,30,0,0
|
||||
6037,-100,4,2,0,40,0,0
|
||||
7795,-100,4,2,0,30,0,0
|
||||
7912,-100,4,2,0,40,0,0
|
||||
9670,-100,4,2,0,40,0,0
|
||||
9787,-100,4,2,0,50,0,0
|
||||
11545,-100,4,2,0,40,0,0
|
||||
11662,-100,4,2,0,50,0,0
|
||||
13420,-100,4,2,0,40,0,0
|
||||
13537,-100,4,2,0,50,0,0
|
||||
15295,-100,4,2,0,40,0,0
|
||||
15412,-100,4,2,0,50,0,0
|
||||
17170,-100,4,2,0,40,0,0
|
||||
17287,-100,4,2,0,50,0,0
|
||||
19045,-100,4,2,0,40,0,0
|
||||
19162,-100,4,2,0,50,0,0
|
||||
20920,-100,4,2,0,40,0,0
|
||||
21037,-100,4,2,0,50,0,0
|
||||
22795,-100,4,2,0,40,0,0
|
||||
22912,-100,4,2,0,50,0,0
|
||||
24670,-100,4,2,0,70,0,0
|
||||
37560,-200,4,2,0,30,0,0
|
||||
38263,-200,4,2,0,5,0,0
|
||||
38966,-100,4,2,0,30,0,0
|
||||
39670,-100,4,2,0,70,0,0
|
||||
53732,-100,4,2,0,40,0,0
|
||||
54670,-100,4,2,0,80,0,1
|
||||
55138,-100,4,2,0,60,0,1
|
||||
55255,-100,4,2,0,80,0,1
|
||||
56076,-100,4,2,0,60,0,1
|
||||
56193,-100,4,2,0,80,0,1
|
||||
57013,-100,4,2,0,60,0,1
|
||||
57130,-100,4,2,0,80,0,1
|
||||
57951,-100,4,2,0,60,0,1
|
||||
58068,-100,4,2,0,80,0,1
|
||||
58888,-100,4,2,0,60,0,1
|
||||
59005,-100,4,2,0,80,0,1
|
||||
59826,-100,4,2,0,60,0,1
|
||||
59943,-100,4,2,0,80,0,1
|
||||
60763,-100,4,2,0,60,0,1
|
||||
60880,-100,4,2,0,80,0,1
|
||||
61701,-100,4,2,0,60,0,1
|
||||
61818,-100,4,2,0,80,0,1
|
||||
62638,-100,4,2,0,60,0,1
|
||||
62755,-100,4,2,0,80,0,1
|
||||
63576,-100,4,2,0,60,0,1
|
||||
63693,-100,4,2,0,80,0,1
|
||||
64513,-100,4,2,0,60,0,1
|
||||
64630,-100,4,2,0,80,0,1
|
||||
65451,-100,4,2,0,60,0,1
|
||||
65568,-100,4,2,0,80,0,1
|
||||
66388,-100,4,2,0,60,0,1
|
||||
66505,-100,4,2,0,80,0,1
|
||||
67326,-100,4,2,0,60,0,1
|
||||
67443,-100,4,2,0,80,0,1
|
||||
68263,-100,4,2,0,60,0,1
|
||||
68380,-100,4,2,0,80,0,1
|
||||
69201,-100,4,2,0,60,0,1
|
||||
69318,-100,4,2,0,80,0,1
|
||||
69670,-100,4,2,0,70,0,0
|
||||
84670,-100,4,2,0,70,0,0
|
||||
97560,-200,4,2,0,70,0,0
|
||||
97795,-200,4,2,0,30,0,0
|
||||
98966,-100,4,2,0,30,0,0
|
||||
99670,-100,4,2,0,70,0,0
|
||||
113732,-100,4,2,0,40,0,0
|
||||
114670,-100,4,2,0,80,0,1
|
||||
115138,-100,4,2,0,60,0,1
|
||||
115255,-100,4,2,0,80,0,1
|
||||
116076,-100,4,2,0,60,0,1
|
||||
116193,-100,4,2,0,80,0,1
|
||||
117013,-100,4,2,0,60,0,1
|
||||
117130,-100,4,2,0,80,0,1
|
||||
117951,-100,4,2,0,60,0,1
|
||||
118068,-100,4,2,0,80,0,1
|
||||
118888,-100,4,2,0,60,0,1
|
||||
119005,-100,4,2,0,80,0,1
|
||||
119826,-100,4,2,0,60,0,1
|
||||
119943,-100,4,2,0,80,0,1
|
||||
120763,-100,4,2,0,60,0,1
|
||||
120880,-100,4,2,0,80,0,1
|
||||
121701,-100,4,2,0,60,0,1
|
||||
121818,-100,4,2,0,80,0,1
|
||||
122638,-100,4,2,0,60,0,1
|
||||
122755,-100,4,2,0,80,0,1
|
||||
123576,-100,4,2,0,60,0,1
|
||||
123693,-100,4,2,0,80,0,1
|
||||
124513,-100,4,2,0,60,0,1
|
||||
124630,-100,4,2,0,80,0,1
|
||||
125451,-100,4,2,0,60,0,1
|
||||
125568,-100,4,2,0,80,0,1
|
||||
126388,-100,4,2,0,60,0,1
|
||||
126505,-100,4,2,0,80,0,1
|
||||
127326,-100,4,2,0,60,0,1
|
||||
127443,-100,4,2,0,80,0,1
|
||||
128263,-100,4,2,0,60,0,1
|
||||
128380,-100,4,2,0,80,0,1
|
||||
129201,-100,4,2,0,60,0,1
|
||||
129318,-100,4,2,0,80,0,1
|
||||
129670,-200,4,2,0,40,0,0
|
||||
144670,-133.333333333333,4,2,0,40,0,0
|
||||
159670,-133.333333333333,4,2,0,40,0,0
|
||||
163420,-133.333333333333,4,2,0,45,0,0
|
||||
163888,-125,4,2,0,50,0,0
|
||||
164357,-117.647058823529,4,2,0,55,0,0
|
||||
164826,-111.111111111111,4,2,0,60,0,0
|
||||
165295,-105.263157894737,4,2,0,65,0,0
|
||||
165763,-100,4,2,0,70,0,0
|
||||
166232,-100,4,2,0,40,0,0
|
||||
167170,-100,4,2,0,80,0,1
|
||||
167638,-100,4,2,0,60,0,1
|
||||
167755,-100,4,2,0,80,0,1
|
||||
168576,-100,4,2,0,60,0,1
|
||||
168693,-100,4,2,0,80,0,1
|
||||
169513,-100,4,2,0,60,0,1
|
||||
169630,-100,4,2,0,80,0,1
|
||||
170451,-100,4,2,0,60,0,1
|
||||
170568,-100,4,2,0,80,0,1
|
||||
171388,-100,4,2,0,60,0,1
|
||||
171505,-100,4,2,0,80,0,1
|
||||
172326,-100,4,2,0,60,0,1
|
||||
172443,-100,4,2,0,80,0,1
|
||||
173263,-100,4,2,0,60,0,1
|
||||
173380,-100,4,2,0,80,0,1
|
||||
174201,-100,4,2,0,60,0,1
|
||||
174318,-100,4,2,0,80,0,1
|
||||
175138,-100,4,2,0,60,0,1
|
||||
175255,-100,4,2,0,80,0,1
|
||||
176076,-100,4,2,0,60,0,1
|
||||
176193,-100,4,2,0,80,0,1
|
||||
177013,-100,4,2,0,60,0,1
|
||||
177130,-100,4,2,0,80,0,1
|
||||
177951,-100,4,2,0,60,0,1
|
||||
178068,-100,4,2,0,80,0,1
|
||||
178888,-100,4,2,0,60,0,1
|
||||
179005,-100,4,2,0,80,0,1
|
||||
179826,-100,4,2,0,60,0,1
|
||||
179943,-100,4,2,0,80,0,1
|
||||
180763,-100,4,2,0,60,0,1
|
||||
180880,-100,4,2,0,80,0,1
|
||||
180998,-100,4,2,0,80,0,0
|
||||
181466,-100,4,2,0,60,0,0
|
||||
181584,-100,4,2,0,80,0,0
|
||||
181935,-100,4,2,0,80,0,0
|
||||
182170,-100,4,2,0,80,0,1
|
||||
182638,-100,4,2,0,60,0,1
|
||||
182755,-100,4,2,0,80,0,1
|
||||
183576,-100,4,2,0,60,0,1
|
||||
183693,-100,4,2,0,80,0,1
|
||||
184513,-100,4,2,0,60,0,1
|
||||
184630,-100,4,2,0,80,0,1
|
||||
185451,-100,4,2,0,60,0,1
|
||||
185568,-100,4,2,0,80,0,1
|
||||
186388,-100,4,2,0,60,0,1
|
||||
186505,-100,4,2,0,80,0,1
|
||||
187326,-100,4,2,0,60,0,1
|
||||
187443,-100,4,2,0,80,0,1
|
||||
188263,-100,4,2,0,60,0,1
|
||||
188380,-100,4,2,0,80,0,1
|
||||
189201,-100,4,2,0,60,0,1
|
||||
189318,-100,4,2,0,80,0,1
|
||||
190138,-100,4,2,0,60,0,1
|
||||
190255,-100,4,2,0,80,0,1
|
||||
191076,-100,4,2,0,60,0,1
|
||||
191193,-100,4,2,0,80,0,1
|
||||
192013,-100,4,2,0,60,0,1
|
||||
192130,-100,4,2,0,80,0,1
|
||||
192951,-100,4,2,0,60,0,1
|
||||
193068,-100,4,2,0,80,0,1
|
||||
193888,-100,4,2,0,60,0,1
|
||||
194005,-100,4,2,0,80,0,1
|
||||
194826,-100,4,2,0,60,0,1
|
||||
194943,-100,4,2,0,80,0,1
|
||||
195295,-100,4,2,0,50,0,1
|
||||
195529,-100,4,2,0,52,0,1
|
||||
195646,-100,4,2,0,54,0,1
|
||||
195763,-100,4,2,0,56,0,1
|
||||
195880,-100,4,2,0,58,0,1
|
||||
195998,-100,4,2,0,60,0,1
|
||||
196115,-100,4,2,0,62,0,1
|
||||
196232,-100,4,2,0,64,0,1
|
||||
196349,-100,4,2,0,68,0,1
|
||||
196466,-100,4,2,0,70,0,1
|
||||
196584,-100,4,2,0,72,0,1
|
||||
196701,-100,4,2,0,74,0,1
|
||||
196818,-100,4,2,0,76,0,1
|
||||
196935,-100,4,2,0,78,0,1
|
||||
197052,-100,4,2,0,80,0,1
|
||||
197170,-100,4,2,0,80,0,0
|
||||
197873,-100,4,2,0,60,0,0
|
||||
197990,-100,4,2,0,80,0,0
|
||||
198341,-100,4,2,0,60,0,0
|
||||
199045,-100,4,2,0,80,0,0
|
||||
199279,-100,4,2,0,60,0,0
|
||||
199630,-100,4,2,0,80,0,0
|
||||
200216,-100,4,2,0,60,0,0
|
||||
200334,-100,4,2,0,80,0,0
|
||||
201623,-100,4,2,0,60,0,0
|
||||
201740,-100,4,2,0,80,0,0
|
||||
202326,-100,4,2,0,60,0,0
|
||||
202443,-100,4,2,0,80,0,0
|
||||
203029,-100,4,2,0,60,0,0
|
||||
203498,-100,4,2,0,80,0,0
|
||||
203966,-100,4,2,0,60,0,0
|
||||
204201,-100,4,2,0,80,0,0
|
||||
205373,-100,4,2,0,60,0,0
|
||||
205490,-100,4,2,0,80,0,0
|
||||
205841,-100,4,2,0,60,0,0
|
||||
206076,-100,4,2,0,60,0,0
|
||||
206545,-100,4,2,0,80,0,0
|
||||
206779,-100,4,2,0,60,0,0
|
||||
207130,-100,4,2,0,80,0,0
|
||||
207716,-100,4,2,0,60,0,0
|
||||
207951,-100,4,2,0,80,0,0
|
||||
209123,-100,4,2,0,60,0,0
|
||||
209240,-100,4,2,0,80,0,0
|
||||
209826,-100,4,2,0,60,0,0
|
||||
209943,-100,4,2,0,80,0,0
|
||||
210529,-100,4,2,0,60,0,0
|
||||
210880,-100,4,2,0,80,0,0
|
||||
211232,-100,4,2,0,60,0,0
|
||||
211701,-100,4,2,0,70,0,0
|
||||
212170,-100,4,2,0,80,0,0
|
||||
212873,-100,4,2,0,60,0,0
|
||||
212990,-100,4,2,0,80,0,0
|
||||
213341,-100,4,2,0,60,0,0
|
||||
213576,-100,4,2,0,60,0,0
|
||||
214045,-100,4,2,0,80,0,0
|
||||
214279,-100,4,2,0,60,0,0
|
||||
214630,-100,4,2,0,80,0,0
|
||||
215216,-100,4,2,0,60,0,0
|
||||
215451,-100,4,2,0,80,0,0
|
||||
216623,-100,4,2,0,60,0,0
|
||||
216740,-100,4,2,0,80,0,0
|
||||
217326,-100,4,2,0,60,0,0
|
||||
217443,-100,4,2,0,80,0,0
|
||||
218029,-100,4,2,0,60,0,0
|
||||
218498,-100,4,2,0,80,0,0
|
||||
218732,-100,4,2,0,50,0,0
|
||||
219670,-100,4,2,0,70,0,0
|
||||
220138,-100,4,2,0,65,0,0
|
||||
220373,-100,4,2,0,45,0,0
|
||||
220490,-100,4,2,0,65,0,0
|
||||
220607,-100,4,2,0,60,0,0
|
||||
220841,-100,4,2,0,35,0,0
|
||||
221076,-100,4,2,0,35,0,0
|
||||
221545,-100,4,2,0,50,0,0
|
||||
221779,-100,4,2,0,30,0,0
|
||||
222013,-111.111111111111,4,2,0,25,0,0
|
||||
222130,-111.111111111111,4,2,0,40,0,0
|
||||
222482,-125,4,2,0,40,0,0
|
||||
222716,-125,4,2,0,20,0,0
|
||||
222951,-100,4,2,0,15,0,0
|
||||
223420,-100,4,2,0,30,0,0
|
||||
224357,-100,4,2,0,25,0,0
|
||||
225295,-100,4,2,0,20,0,0
|
||||
226232,-100,4,2,0,15,0,0
|
||||
226701,-100,4,2,0,10,0,0
|
||||
227170,-100,4,2,0,5,0,0
|
||||
|
||||
[Colours]
|
||||
Combo1 : 17,254,176
|
||||
Combo2 : 173,255,95
|
||||
Combo3 : 255,88,100
|
||||
Combo4 : 255,94,55
|
||||
|
||||
[HitObjects]
|
||||
320,256,2170,6,0,P|256:284|192:256,1,144,4|0,0:0|0:0,0:0:0:0:
|
||||
144,184,2873,1,0,0:0:0:0:
|
||||
108,260,3107,2,0,P|112:296|100:336,1,72
|
||||
28,288,3576,2,0,P|24:252|36:212,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
76,140,4045,6,0,L|220:136,1,144,4|0,0:0|0:0,0:0:0:0:
|
||||
292,88,4748,1,0,0:0:0:0:
|
||||
292,88,4982,2,0,P|304:120|300:168,1,72
|
||||
388,168,5451,2,0,P|396:133|416:103,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
472,172,5920,6,0,B|470:200|457:222|457:222|488:256|476:308,1,144,4|0,0:0|0:0,0:0:0:0:
|
||||
396,280,6623,1,0,0:0:0:0:
|
||||
324,328,6857,2,0,P|288:332|252:324,1,72
|
||||
180,280,7326,2,0,L|108:284,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
256,192,7795,12,0,9670,0:0:0:0:
|
||||
428,212,10138,1,0,0:0:0:0:
|
||||
292,320,10607,1,0,0:0:0:0:
|
||||
184,184,11076,2,0,L|112:180,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
24,172,11545,5,6,0:0:0:0:
|
||||
160,280,12013,1,0,0:0:0:0:
|
||||
268,144,12482,1,0,0:0:0:0:
|
||||
132,36,12951,2,0,L|204:32,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
284,60,13420,6,0,P|340:100|344:180,2,144,6|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
268,144,14591,1,0,0:0:0:0:
|
||||
284,228,14826,2,0,P|316:248|364:252,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
436,248,15295,6,0,P|372:272|344:340,1,144,6|2,0:0|0:0,0:0:0:0:
|
||||
168,338,16232,2,0,P|141:273|76:248,1,144,2|2,0:0|0:0,0:0:0:0:
|
||||
4,296,16935,1,0,0:0:0:0:
|
||||
80,336,17170,5,6,0:0:0:0:
|
||||
44,168,17638,1,0,0:0:0:0:
|
||||
212,128,18107,1,0,0:0:0:0:
|
||||
248,296,18576,2,0,P|284:288|320:292,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
400,324,19045,5,6,0:0:0:0:
|
||||
280,200,19513,1,0,0:0:0:0:
|
||||
368,52,19982,1,0,0:0:0:0:
|
||||
488,176,20451,2,0,P|452:168|416:172,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
336,200,20920,6,0,P|284:216|200:192,1,144,6|0,0:0|0:0,0:0:0:0:
|
||||
200,192,21857,2,0,L|204:264,1,72,0|0,0:3|0:0,0:0:0:0:
|
||||
117,244,22326,2,0,L|120:172,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
40,152,22795,6,0,L|28:296,2,144,6|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
152,24,24201,1,0,0:0:0:0:
|
||||
220,76,24435,1,0,3:0:0:0:
|
||||
304,56,24670,6,0,P|288:120|296:196,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
344,268,25373,1,0,0:0:0:0:
|
||||
416,316,25607,2,0,P|452:312|508:316,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
244,344,26545,6,0,P|176:356|108:328,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
60,256,27248,1,0,0:0:0:0:
|
||||
36,172,27482,2,0,L|40:100,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
188,252,28420,6,0,P|192:184|196:100,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
140,40,29123,1,0,0:0:0:0:
|
||||
140,40,29357,2,0,B|172:16|220:24|220:24|288:36,1,144,0|2,0:0|0:3,0:0:0:0:
|
||||
364,52,30060,1,0,0:0:0:0:
|
||||
308,116,30295,6,0,B|300:168|300:168|328:256,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
340,340,30998,1,0,0:0:0:0:
|
||||
260,308,31232,2,0,L|188:304,1,72,0|2,0:0|0:3,0:0:0:0:
|
||||
100,296,31701,1,2,0:3:0:0:
|
||||
136,374,31935,1,0,0:0:0:0:
|
||||
152,224,32170,6,0,P|160:152|132:88,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
56,48,32873,1,0,0:0:0:0:
|
||||
60,136,33107,2,0,L|56:208,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
224,76,34045,6,0,P|289:104|360:96,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
432,48,34748,1,0,0:0:0:0:
|
||||
440,132,34982,2,0,B|432:156|432:156|436:204,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
448,304,35920,6,0,B|412:315|380:292|380:292|348:269|312:280,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
332,364,36623,1,0,0:0:0:0:
|
||||
247,339,36857,2,0,P|230:308|225:273,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
312,280,37560,6,0,L|316:172,1,108
|
||||
134,35,38966,5,0,0:0:0:0:
|
||||
72,96,39201,2,0,P|119:119|171:111,1,108,0|0,0:0|0:0,0:0:0:0:
|
||||
192,100,39670,6,0,L|200:172,1,72,4|2,0:0|0:0,0:0:0:0:
|
||||
147,240,40138,2,0,P|133:272|132:308,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
216,292,40607,2,0,B|260:308|260:308|356:292,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
356,292,41310,1,2,0:0:0:0:
|
||||
436,327,41545,6,0,P|441:292|435:257,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
364,204,42013,2,0,P|336:144|352:68,1,144,0|4,1:0|2:3,1:0:0:0:
|
||||
404,0,42716,1,2,0:0:0:0:
|
||||
440,80,42951,2,0,B|464:84|464:84|512:80,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
351,71,43420,6,0,B|296:68|296:68|268:76|268:76|196:72,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
120,68,44123,1,2,0:0:0:0:
|
||||
160,144,44357,2,0,P|172:180|168:232,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
76,264,44826,2,0,P|76:228|88:194,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
160,144,45295,5,4,0:3:0:0:
|
||||
244,164,45529,1,2,0:0:0:0:
|
||||
268,248,45763,2,0,L|344:252,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
408,156,46232,2,0,L|336:159,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
212,72,46701,2,0,L|288:76,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
400,72,47170,6,0,P|464:96|488:172,1,144,4|0,2:0|1:0,1:0:0:0:
|
||||
476,248,47873,1,2,0:0:0:0:
|
||||
436,324,48107,2,0,L|284:320,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
204,316,48810,1,2,0:0:0:0:
|
||||
127,355,49045,6,0,P|120:321|124:285,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
192,232,49513,2,0,L|335:228,1,144,0|4,1:0|2:3,1:0:0:0:
|
||||
412,188,50216,1,2,0:0:0:0:
|
||||
444,108,50451,2,0,P|452:72|448:36,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
368,68,50920,6,0,B|332:79|300:56|300:56|268:33|232:44,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
152,76,51623,1,2,0:0:0:0:
|
||||
76,116,51857,2,0,L|80:268,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
80,260,52560,1,2,0:0:0:0:
|
||||
8,308,52795,6,0,P|34:334|69:346,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
148,312,53263,2,0,P|163:278|162:241,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
156,156,53732,5,0,3:0:0:0:
|
||||
156,156,53966,1,2,0:0:0:0:
|
||||
236,196,54201,2,0,L|312:192,1,72,8|0,0:3|0:0,0:0:0:0:
|
||||
368,256,54670,6,0,P|392:216|352:116,1,144,4|2,0:0|1:2,0:0:0:0:
|
||||
288,92,55373,1,0,0:0:0:0:
|
||||
360,40,55607,2,0,L|432:36,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
288,92,56076,2,0,L|216:88,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
132,72,56545,6,0,P|172:88|200:184,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
143,241,57248,1,0,0:0:0:0:
|
||||
65,202,57482,2,0,P|87:174|119:157,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
132,324,57951,2,0,P|98:312|72:288,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
143,241,58420,6,0,L|288:240,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
372,240,59123,1,0,0:0:0:0:
|
||||
330,314,59357,2,0,P|318:350|322:390,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
452,264,59826,2,0,P|453:228|442:194,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
384,128,60295,6,0,B|336:144|336:144|244:128,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
164,160,60998,2,0,P|160:116|168:88,1,72,0|4,0:0|0:3,0:0:0:0:
|
||||
244,128,61466,2,0,P|248:172|240:200,1,72,0|2,3:0|1:2,0:0:0:0:
|
||||
168,248,61935,1,0,0:0:0:0:
|
||||
120,320,62170,6,0,P|196:328|252:272,2,144,4|2|4,0:3|1:2|0:3,0:0:0:0:
|
||||
80,244,63341,1,0,3:0:0:0:
|
||||
100,160,63576,2,0,L|24:156,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
180,128,64045,6,0,P|249:138|304:94,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
226,57,64748,1,0,0:0:0:0:
|
||||
304,94,64982,2,0,L|300:166,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
377,203,65451,2,0,L|388:132,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
468,180,65920,6,0,L|432:328,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
276,252,66857,2,0,P|208:248|140:280,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
84,344,67560,1,0,0:0:0:0:
|
||||
56,260,67795,6,0,L|52:188,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
168,128,68732,2,0,L|172:56,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
244,168,69435,1,0,0:0:0:0:
|
||||
332,164,69670,1,4,0:3:0:0:
|
||||
208,328,84670,6,0,P|224:264|216:188,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
168,116,85373,1,0,0:0:0:0:
|
||||
96,68,85607,2,0,P|60:72|4:68,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
268,40,86545,6,0,P|336:28|404:56,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
452,128,87248,1,0,0:0:0:0:
|
||||
476,212,87482,2,0,L|472:284,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
324,132,88420,6,0,P|320:200|316:284,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
372,344,89123,1,0,0:0:0:0:
|
||||
372,344,89357,2,0,B|340:368|292:360|292:360|224:348,1,144,0|2,0:0|0:3,0:0:0:0:
|
||||
148,332,90060,1,0,0:0:0:0:
|
||||
204,268,90295,6,0,B|212:216|212:216|184:128,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
172,44,90998,1,0,0:0:0:0:
|
||||
252,76,91232,2,0,L|324:80,1,72,0|2,0:0|0:3,0:0:0:0:
|
||||
412,88,91701,1,2,0:3:0:0:
|
||||
377,9,91935,1,0,0:0:0:0:
|
||||
360,160,92170,6,0,P|352:232|380:296,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
456,336,92873,1,0,0:0:0:0:
|
||||
452,248,93107,2,0,L|456:176,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
288,308,94045,6,0,P|223:280|152:288,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
80,336,94748,1,0,0:0:0:0:
|
||||
72,252,94982,2,0,B|80:228|80:228|76:180,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
64,80,95920,6,0,B|100:69|132:92|132:92|164:115|200:104,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
180,20,96623,1,0,0:0:0:0:
|
||||
265,45,96857,2,0,P|282:76|287:111,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
200,104,97560,1,0,0:0:0:0:
|
||||
200,104,97677,1,0,0:0:0:0:
|
||||
200,104,97795,6,0,B|196:142|217:166|217:166|176:180|160:220,1,144,4|0,0:3|0:0,0:0:0:0:
|
||||
240,248,98966,5,0,0:0:0:0:
|
||||
202,325,99201,2,0,P|254:333|301:309,1,108,0|0,0:0|0:0,0:0:0:0:
|
||||
315,292,99670,6,0,L|323:220,1,72,4|2,0:0|0:0,0:0:0:0:
|
||||
365,144,100138,2,0,P|379:112|380:76,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
296,92,100607,2,0,B|252:76|252:76|156:92,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
156,92,101310,1,2,0:0:0:0:
|
||||
76,57,101545,6,0,P|71:92|77:127,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
148,180,102013,2,0,P|176:240|160:316,1,144,0|4,1:0|2:3,1:0:0:0:
|
||||
108,384,102716,1,2,0:0:0:0:
|
||||
72,304,102951,2,0,B|48:300|48:300|0:304,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
161,313,103420,6,0,B|216:316|216:316|244:308|244:308|316:312,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
392,316,104123,1,2,0:0:0:0:
|
||||
352,240,104357,2,0,P|340:204|344:152,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
436,120,104826,2,0,P|436:156|424:190,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
352,240,105295,5,4,0:3:0:0:
|
||||
268,220,105529,1,2,0:0:0:0:
|
||||
244,136,105763,2,0,L|168:132,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
104,228,106232,2,0,L|176:225,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
300,312,106701,2,0,L|224:308,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
112,312,107170,6,0,P|48:288|24:212,1,144,4|0,2:0|1:0,1:0:0:0:
|
||||
36,136,107873,1,2,0:0:0:0:
|
||||
76,60,108107,2,0,L|228:64,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
308,68,108810,1,2,0:0:0:0:
|
||||
385,29,109045,6,0,P|392:63|388:99,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
320,152,109513,2,0,L|177:156,1,144,0|4,1:0|2:3,1:0:0:0:
|
||||
100,196,110216,1,2,0:0:0:0:
|
||||
68,276,110451,2,0,P|60:312|64:348,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
144,316,110920,6,0,B|180:305|212:328|212:328|244:351|280:340,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
360,308,111623,1,2,0:0:0:0:
|
||||
436,268,111857,2,0,L|432:116,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
432,124,112560,1,2,0:0:0:0:
|
||||
504,76,112795,6,0,P|478:50|443:38,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
364,72,113263,2,0,P|349:106|350:143,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
356,228,113732,5,0,3:0:0:0:
|
||||
356,228,113966,1,2,0:0:0:0:
|
||||
276,188,114201,2,0,L|200:192,1,72,8|0,0:3|0:0,0:0:0:0:
|
||||
144,128,114670,6,0,P|120:168|160:268,1,144,4|2,0:0|1:2,0:0:0:0:
|
||||
224,292,115373,1,0,0:0:0:0:
|
||||
152,344,115607,2,0,L|80:348,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
224,292,116076,2,0,L|296:296,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
380,312,116545,6,0,P|340:296|312:200,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
369,143,117248,1,0,0:0:0:0:
|
||||
447,182,117482,2,0,P|425:210|393:227,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
380,60,117951,2,0,P|414:72|440:96,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
369,143,118420,6,0,L|224:144,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
140,144,119123,1,0,0:0:0:0:
|
||||
182,70,119357,2,0,P|194:34|190:-6,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
60,120,119826,2,0,P|59:156|70:190,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
128,256,120295,6,0,B|176:240|176:240|268:256,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
348,224,120998,2,0,P|352:268|344:296,1,72,0|4,0:0|0:3,0:0:0:0:
|
||||
268,256,121466,2,0,P|264:212|272:184,1,72,0|2,3:0|1:2,0:0:0:0:
|
||||
344,136,121935,1,0,0:0:0:0:
|
||||
392,64,122170,6,0,P|316:56|260:112,2,144,4|2|4,0:3|1:2|0:3,0:0:0:0:
|
||||
432,140,123341,1,0,3:0:0:0:
|
||||
412,224,123576,2,0,L|488:228,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
332,256,124045,6,0,P|263:246|208:290,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
286,327,124748,1,0,0:0:0:0:
|
||||
208,290,124982,2,0,L|212:218,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
135,181,125451,2,0,L|124:252,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
44,204,125920,6,0,L|80:56,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
236,132,126857,2,0,P|304:136|372:104,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
428,40,127560,1,0,0:0:0:0:
|
||||
456,124,127795,6,0,L|460:196,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
344,256,128732,2,0,L|340:328,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
268,216,129435,1,0,0:0:0:0:
|
||||
180,220,129670,5,4,2:0:0:0:
|
||||
256,40,130373,1,2,0:0:0:0:
|
||||
64,68,131076,1,2,0:0:0:0:
|
||||
92,136,131310,1,0,0:0:0:0:
|
||||
64,204,131545,6,0,L|60:288,1,72
|
||||
31,343,132248,2,0,P|86:345|127:309,1,108
|
||||
332,220,133420,5,2,0:0:0:0:
|
||||
256,40,134123,1,2,0:0:0:0:
|
||||
448,68,134826,1,2,0:0:0:0:
|
||||
420,136,135060,1,0,0:0:0:0:
|
||||
448,204,135295,6,0,L|452:288,1,72,2|0,0:0|0:0,0:0:0:0:
|
||||
480,343,135998,2,0,P|426:345|385:309,1,108
|
||||
256,192,137170,5,2,0:0:0:0:
|
||||
156,360,137873,1,2,0:0:0:0:
|
||||
356,360,138576,2,0,L|352:308,1,36,2|0,0:0|0:0,0:0:0:0:
|
||||
304,268,139045,6,0,P|336:253|372:252,1,72
|
||||
448,260,139748,2,0,L|444:152,1,108
|
||||
256,192,140920,5,2,0:0:0:0:
|
||||
356,24,141623,1,2,0:0:0:0:
|
||||
156,24,142326,2,0,L|160:72,1,36,2|0,0:0|0:0,0:0:0:0:
|
||||
208,116,142795,6,0,P|176:131|140:132,1,72,2|0,0:0|0:0,0:0:0:0:
|
||||
64,124,143498,2,0,L|68:232,1,108
|
||||
68,232,144670,5,4,0:3:0:0:
|
||||
216,320,145138,1,4,0:3:0:0:
|
||||
304,172,145607,1,4,0:3:0:0:
|
||||
156,84,146075,1,4,0:3:0:0:
|
||||
296,320,146545,5,4,0:3:0:0:
|
||||
208,172,147013,1,4,0:3:0:0:
|
||||
356,84,147482,1,4,0:3:0:0:
|
||||
444,232,147950,1,4,0:3:0:0:
|
||||
296,320,148420,6,0,P|252:328|192:296,2,108.000004119873,4|4|4,0:3|0:3|0:3,0:0:0:0:
|
||||
260,248,149591,1,0,0:0:0:0:
|
||||
320,196,149826,2,0,L|316:140,1,54.0000020599366,4|0,0:3|0:0,0:0:0:0:
|
||||
120,236,159670,6,0,L|176:232,1,54.0000020599366,4|0,0:3|0:0,0:0:0:0:
|
||||
160,152,160138,2,0,L|104:156,1,54.0000020599366,2|0,0:0|0:0,0:0:0:0:
|
||||
240,180,160607,2,0,P|292:188|344:172,1,108.000004119873,4|2,0:3|0:0,3:0:0:0:
|
||||
408,120,161310,1,0,3:0:0:0:
|
||||
424,200,161545,6,0,L|420:256,1,54.0000020599366,4|0,0:3|0:0,0:0:0:0:
|
||||
376,320,162013,2,0,P|396:328|480:304,2,108.000004119873,2|6|2,2:0|0:3|2:0,3:0:0:0:
|
||||
312,268,163185,1,0,0:0:0:0:
|
||||
296,348,163420,6,0,L|240:344,1,54.0000020599366,4|0,3:0|3:0,0:0:0:0:
|
||||
160,320,163888,2,0,L|100:316,1,57.6,4|0,3:0|3:0,0:0:0:0:
|
||||
64,232,164357,6,0,L|128:228,1,61.2000011672974,4|0,3:0|3:0,0:0:0:0:
|
||||
204,200,164825,2,0,L|268:196,1,61.2000011672974,4|0,3:0|3:0,0:0:0:0:
|
||||
232,108,165295,6,0,L|164:104,1,68.399998173523,4|0,3:0|3:0,0:0:0:0:
|
||||
80,84,165763,2,0,L|4:80,1,72,4|0,3:0|3:0,0:0:0:0:
|
||||
324,120,167170,6,0,P|388:128|456:92,1,144,4|2,0:0|1:2,0:0:0:0:
|
||||
496,168,167873,1,0,0:0:0:0:
|
||||
496,168,168107,2,0,P|484:204|488:256,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
408,296,168576,2,0,P|398:261|378:231,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
296,200,169045,6,0,B|228:228|156:204,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
84,156,169748,1,0,0:0:0:0:
|
||||
80,244,169982,2,0,L|76:316,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
170,274,170451,2,0,L|156:204,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
216,140,170920,6,0,L|284:276,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
320,344,171623,1,0,0:0:0:0:
|
||||
372,276,171857,2,0,P|366:240|349:207,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
312,132,172326,2,0,L|276:60,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
208,20,172795,6,0,P|272:36|348:12,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
424,48,173498,2,0,L|412:132,1,72,0|4,0:0|0:3,0:0:0:0:
|
||||
484,168,173966,2,0,L|472:252,1,72,0|2,3:0|1:2,0:0:0:0:
|
||||
400,280,174435,1,0,0:0:0:0:
|
||||
346,348,174670,6,0,P|414:363|472:324,2,144,4|2|4,0:3|1:2|0:3,0:0:0:0:
|
||||
312,268,175841,1,0,3:0:0:0:
|
||||
256,336,176076,2,0,L|184:332,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
80,244,176545,6,0,B|140:248|140:248|164:244|164:244|223:247,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
312,268,177248,1,0,0:0:0:0:
|
||||
224,247,177482,2,0,P|240:215|272:187,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
204,131,177951,2,0,P|233:111|275:103,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
240,23,178420,6,0,B|280:15|316:35|316:35|376:71,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
399,236,179357,2,0,B|359:244|323:224|323:224|263:188,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
204,132,180060,1,0,0:0:0:0:
|
||||
184,216,180295,6,0,L|188:288,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
120,156,180998,1,0,0:0:0:0:
|
||||
56,96,181232,2,0,L|60:24,2,72,4|2|0,0:3|0:0|1:0,0:0:0:0:
|
||||
36,180,181935,1,0,0:0:0:0:
|
||||
100,240,182170,6,0,P|144:300|116:380,2,144,4|2|4,0:0|1:2|0:3,0:0:0:0:
|
||||
60,316,183341,1,0,0:0:0:0:
|
||||
220,352,183576,2,0,L|308:348,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
396,264,184045,6,0,B|336:268|336:268|312:264|312:264|253:267,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
253,267,184748,1,0,0:0:0:0:
|
||||
268,180,184982,2,0,L|339:177,1,72,4|0,0:3|0:0,0:0:0:0:
|
||||
164,280,185451,2,0,L|92:282,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
52,208,185920,6,0,P|8:268|32:344,2,144,4|2|4,0:3|1:2|0:3,0:0:0:0:
|
||||
140,212,187091,1,0,0:0:0:0:
|
||||
92,284,187326,2,0,P|104:316|100:368,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
52,208,187795,6,0,P|48:136|76:72,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
160,52,188498,2,0,P|188:28|220:16,1,72,0|4,0:0|0:3,0:0:0:0:
|
||||
232,100,188966,2,0,P|268:93|301:98,1,72,0|2,0:0|1:2,0:0:0:0:
|
||||
372,152,189435,1,0,0:0:0:0:
|
||||
420,224,189670,6,0,P|428:296|400:360,2,144,4|2|4,0:3|1:2|0:3,0:0:0:0:
|
||||
372,152,190841,1,0,0:0:0:0:
|
||||
392,68,191076,2,0,L|465:64,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
304,92,191545,6,0,P|236:104|168:76,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
108,12,192248,1,0,0:0:0:0:
|
||||
168,76,192482,2,0,L|172:152,1,72,4|0,0:3|0:0,0:0:0:0:
|
||||
80,136,192951,2,0,L|101:204,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
12,220,193420,6,0,B|50:279|50:279|80:300|120:292,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
284,232,194357,2,0,B|320:221|352:244|352:244|384:267|420:256,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
488,200,195060,1,0,0:0:0:0:
|
||||
507,284,195295,6,0,P|492:315|464:338,1,72,4|0,0:0|0:0,0:0:0:0:
|
||||
380,356,195763,2,0,L|236:352,1,144,0|4,1:0|0:3,0:0:0:0:
|
||||
152,328,196466,1,0,3:0:0:0:
|
||||
64,336,196701,2,0,P|29:325|4:300,1,72,0|0,1:0|0:0,0:0:0:0:
|
||||
76,252,197170,6,0,P|108:188|96:116,1,144,4|0,0:0|1:0,0:0:0:0:
|
||||
36,56,197873,1,2,0:0:0:0:
|
||||
120,32,198107,2,0,L|192:28,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
248,152,199045,6,0,P|280:168|304:196,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
336,277,199513,2,0,P|306:296|269:303,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
183,290,199982,2,0,P|180:254|193:219,2,72,4|2|0,0:3|0:0|1:0,0:0:0:0:
|
||||
436,252,200920,6,0,P|404:188|416:116,1,144,4|0,0:3|1:0,0:0:0:0:
|
||||
476,56,201623,1,2,0:0:0:0:
|
||||
392,32,201857,2,0,L|320:28,2,72,4|0|2,0:3|0:0|1:2,0:0:0:0:
|
||||
264,152,202795,6,0,P|232:168|208:196,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
176,277,203263,2,0,P|205:296|242:303,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
329,290,203732,2,0,P|331:254|318:219,2,72,4|2|0,0:3|0:0|1:0,0:0:0:0:
|
||||
72,324,204670,6,0,B|60:272|60:272|76:180,1,144,4|0,0:0|1:0,0:0:0:0:
|
||||
92,96,205373,1,2,0:0:0:0:
|
||||
8,124,205607,2,0,P|5:88|14:53,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
168,192,206545,6,0,P|200:174|237:173,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
320,160,207013,2,0,P|318:196|301:229,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
272,307,207482,2,0,P|240:287|221:256,2,72,4|2|0,0:3|0:0|1:0,0:0:0:0:
|
||||
440,324,208420,6,0,B|452:272|452:272|436:180,1,144,4|0,0:3|1:0,0:0:0:0:
|
||||
420,96,209123,1,2,0:0:0:0:
|
||||
504,124,209357,2,0,P|507:88|498:53,2,72,4|0|2,0:3|0:0|1:2,0:0:0:0:
|
||||
344,192,210295,6,0,P|311:174|274:173,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
190,156,210763,2,0,P|191:192|208:225,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
288,256,211232,1,4,0:3:0:0:
|
||||
132,332,211701,1,0,1:0:0:0:
|
||||
28,192,212170,6,0,P|16:120|44:56,1,144,4|0,0:0|1:0,0:0:0:0:
|
||||
120,16,212873,1,2,0:0:0:0:
|
||||
204,32,213107,2,0,L|304:28,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
192,204,214045,6,0,P|196:240|216:272,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
298,241,214513,2,0,P|327:219|345:186,1,72,6|0,1:2|0:0,0:0:0:0:
|
||||
280,132,214982,2,0,P|246:117|209:118,2,72,4|2|0,0:3|0:0|1:0,0:0:0:0:
|
||||
484,192,215920,6,0,P|496:120|468:56,1,144,4|0,0:3|1:0,0:0:0:0:
|
||||
392,16,216623,1,2,0:0:0:0:
|
||||
308,32,216857,2,0,L|208:28,2,72,4|0|2,0:3|0:0|1:2,0:0:0:0:
|
||||
320,204,217795,6,0,P|316:240|296:272,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
213,241,218263,2,0,P|184:219|166:186,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
232,132,218732,2,0,B|260:112|300:116|300:116|384:128,1,144,4|0,0:3|1:0,0:0:0:0:
|
||||
348,336,219670,6,0,B|320:356|280:352|280:352|196:340,1,144,4|0,0:0|1:0,0:0:0:0:
|
||||
124,328,220373,1,2,0:0:0:0:
|
||||
54,276,220607,2,0,P|41:308|39:345,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
156,80,221545,6,0,L|251:94,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
212,169,222013,2,0,L|148:160,1,64.799998022461,2|0,1:2|0:0,0:0:0:0:
|
||||
140,240,222482,2,0,L|216:252,2,57.6,4|2|0,0:3|0:0|1:0,0:0:0:0:
|
||||
256,192,223420,12,0,227170,0:0:0:0:
|
||||
";
|
||||
}
|
||||
}
|
@ -1,14 +1,22 @@
|
||||
// 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.Linq;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
|
||||
namespace osu.Game.Tests.Beatmaps
|
||||
{
|
||||
public class TestWorkingBeatmap : WorkingBeatmap
|
||||
{
|
||||
public TestWorkingBeatmap(RulesetInfo ruleset)
|
||||
: this(new TestBeatmap(ruleset))
|
||||
{
|
||||
}
|
||||
|
||||
public TestWorkingBeatmap(Beatmap beatmap)
|
||||
: base(beatmap.BeatmapInfo)
|
||||
{
|
||||
@ -16,9 +24,23 @@ namespace osu.Game.Tests.Beatmaps
|
||||
}
|
||||
|
||||
private readonly Beatmap beatmap;
|
||||
|
||||
protected override Beatmap GetBeatmap() => beatmap;
|
||||
protected override Texture GetBackground() => null;
|
||||
protected override Track GetTrack() => new TrackVirtual();
|
||||
|
||||
protected override Track GetTrack()
|
||||
{
|
||||
var lastObject = beatmap.HitObjects.LastOrDefault();
|
||||
if (lastObject != null)
|
||||
return new TestTrack(((lastObject as IHasEndTime)?.EndTime ?? lastObject.StartTime) + 1000);
|
||||
return new TrackVirtual();
|
||||
}
|
||||
|
||||
private class TestTrack : TrackVirtual
|
||||
{
|
||||
public TestTrack(double length)
|
||||
{
|
||||
Length = length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
33
osu.Game/Tests/Visual/EditorTestCase.cs
Normal file
33
osu.Game/Tests/Visual/EditorTestCase.cs
Normal file
@ -0,0 +1,33 @@
|
||||
// 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.Framework.Allocation;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Screens.Edit;
|
||||
using osu.Game.Screens.Edit.Screens;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
public abstract class EditorTestCase : ScreenTestCase
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(Editor), typeof(EditorScreen) };
|
||||
|
||||
private readonly Ruleset ruleset;
|
||||
|
||||
protected EditorTestCase(Ruleset ruleset)
|
||||
{
|
||||
this.ruleset = ruleset;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuGameBase osuGame)
|
||||
{
|
||||
osuGame.Beatmap.Value = new TestWorkingBeatmap(ruleset.RulesetInfo);
|
||||
|
||||
LoadComponentAsync(new Editor(), LoadScreen);
|
||||
}
|
||||
}
|
||||
}
|
@ -128,7 +128,7 @@ namespace osu.Game.Tests.Visual
|
||||
private void load(BeatmapManager beatmaps)
|
||||
{
|
||||
var sets = beatmaps.GetAllUsableBeatmapSets();
|
||||
var allBeatmaps = sets.SelectMany(s => s.Beatmaps).Where(b => ruleset.LegacyID < 0 || b.RulesetID == ruleset.LegacyID);
|
||||
var allBeatmaps = sets.SelectMany(s => s.Beatmaps).Where(b => ruleset.LegacyID == null || b.RulesetID == ruleset.LegacyID);
|
||||
|
||||
allBeatmaps.ForEach(b => beatmapDisplays.Add(new BeatmapDisplay(b)));
|
||||
}
|
||||
|
@ -1,9 +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 System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Beatmaps;
|
||||
@ -59,24 +57,13 @@ namespace osu.Game.Tests.Visual
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual Beatmap CreateBeatmap()
|
||||
{
|
||||
Beatmap beatmap;
|
||||
|
||||
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(test_beatmap_data)))
|
||||
using (var reader = new StreamReader(stream))
|
||||
beatmap = Game.Beatmaps.Formats.Decoder.GetDecoder(reader).DecodeBeatmap(reader);
|
||||
|
||||
return beatmap;
|
||||
}
|
||||
protected virtual Beatmap CreateBeatmap(Ruleset ruleset) => new TestBeatmap(ruleset.RulesetInfo);
|
||||
|
||||
private Player loadPlayerFor(RulesetInfo ri) => loadPlayerFor(ri.CreateInstance());
|
||||
|
||||
private Player loadPlayerFor(Ruleset r)
|
||||
{
|
||||
var beatmap = CreateBeatmap();
|
||||
|
||||
beatmap.BeatmapInfo.Ruleset = r.RulesetInfo;
|
||||
var beatmap = CreateBeatmap(r);
|
||||
|
||||
working = new TestWorkingBeatmap(beatmap);
|
||||
working.Mods.Value = new[] { r.GetAllMods().First(m => m is ModNoFail) };
|
||||
@ -107,699 +94,5 @@ namespace osu.Game.Tests.Visual
|
||||
AllowLeadIn = false,
|
||||
AllowResults = false,
|
||||
};
|
||||
|
||||
private const string test_beatmap_data =
|
||||
@"osu file format v14
|
||||
|
||||
[General]
|
||||
AudioLeadIn: 500
|
||||
PreviewTime: 53498
|
||||
Countdown: 0
|
||||
SampleSet: Soft
|
||||
StackLeniency: 0.7
|
||||
Mode: 0
|
||||
LetterboxInBreaks: 0
|
||||
WidescreenStoryboard: 1
|
||||
|
||||
[Editor]
|
||||
DistanceSpacing: 1.2
|
||||
BeatDivisor: 4
|
||||
GridSize: 4
|
||||
TimelineZoom: 1
|
||||
|
||||
[Metadata]
|
||||
Title:My Love
|
||||
TitleUnicode:My Love
|
||||
Artist:Kuba Oms
|
||||
ArtistUnicode:Kuba Oms
|
||||
Creator:W h i t e
|
||||
Version:Hard
|
||||
Source:ADHD
|
||||
Tags:Monthly Beatmapping Contest Electronic folk pop w_h_i_t_e
|
||||
BeatmapID:397534
|
||||
BeatmapSetID:163112
|
||||
|
||||
[Difficulty]
|
||||
HPDrainRate:5
|
||||
CircleSize:4
|
||||
OverallDifficulty:6
|
||||
ApproachRate:7
|
||||
SliderMultiplier:1.44
|
||||
SliderTickRate:2
|
||||
|
||||
[Events]
|
||||
//Break Periods
|
||||
2,69870,83770
|
||||
2,152170,158770
|
||||
//Storyboard Layer 0 (Background)
|
||||
//Storyboard Layer 1 (Fail)
|
||||
//Storyboard Layer 2 (Pass)
|
||||
//Storyboard Layer 3 (Foreground)
|
||||
//Storyboard Sound Samples
|
||||
|
||||
[TimingPoints]
|
||||
2170,468.75,4,2,0,40,1,0
|
||||
4045,-100,4,2,0,30,0,0
|
||||
4162,-100,4,2,0,40,0,0
|
||||
5920,-100,4,2,0,30,0,0
|
||||
6037,-100,4,2,0,40,0,0
|
||||
7795,-100,4,2,0,30,0,0
|
||||
7912,-100,4,2,0,40,0,0
|
||||
9670,-100,4,2,0,40,0,0
|
||||
9787,-100,4,2,0,50,0,0
|
||||
11545,-100,4,2,0,40,0,0
|
||||
11662,-100,4,2,0,50,0,0
|
||||
13420,-100,4,2,0,40,0,0
|
||||
13537,-100,4,2,0,50,0,0
|
||||
15295,-100,4,2,0,40,0,0
|
||||
15412,-100,4,2,0,50,0,0
|
||||
17170,-100,4,2,0,40,0,0
|
||||
17287,-100,4,2,0,50,0,0
|
||||
19045,-100,4,2,0,40,0,0
|
||||
19162,-100,4,2,0,50,0,0
|
||||
20920,-100,4,2,0,40,0,0
|
||||
21037,-100,4,2,0,50,0,0
|
||||
22795,-100,4,2,0,40,0,0
|
||||
22912,-100,4,2,0,50,0,0
|
||||
24670,-100,4,2,0,70,0,0
|
||||
37560,-200,4,2,0,30,0,0
|
||||
38263,-200,4,2,0,5,0,0
|
||||
38966,-100,4,2,0,30,0,0
|
||||
39670,-100,4,2,0,70,0,0
|
||||
53732,-100,4,2,0,40,0,0
|
||||
54670,-100,4,2,0,80,0,1
|
||||
55138,-100,4,2,0,60,0,1
|
||||
55255,-100,4,2,0,80,0,1
|
||||
56076,-100,4,2,0,60,0,1
|
||||
56193,-100,4,2,0,80,0,1
|
||||
57013,-100,4,2,0,60,0,1
|
||||
57130,-100,4,2,0,80,0,1
|
||||
57951,-100,4,2,0,60,0,1
|
||||
58068,-100,4,2,0,80,0,1
|
||||
58888,-100,4,2,0,60,0,1
|
||||
59005,-100,4,2,0,80,0,1
|
||||
59826,-100,4,2,0,60,0,1
|
||||
59943,-100,4,2,0,80,0,1
|
||||
60763,-100,4,2,0,60,0,1
|
||||
60880,-100,4,2,0,80,0,1
|
||||
61701,-100,4,2,0,60,0,1
|
||||
61818,-100,4,2,0,80,0,1
|
||||
62638,-100,4,2,0,60,0,1
|
||||
62755,-100,4,2,0,80,0,1
|
||||
63576,-100,4,2,0,60,0,1
|
||||
63693,-100,4,2,0,80,0,1
|
||||
64513,-100,4,2,0,60,0,1
|
||||
64630,-100,4,2,0,80,0,1
|
||||
65451,-100,4,2,0,60,0,1
|
||||
65568,-100,4,2,0,80,0,1
|
||||
66388,-100,4,2,0,60,0,1
|
||||
66505,-100,4,2,0,80,0,1
|
||||
67326,-100,4,2,0,60,0,1
|
||||
67443,-100,4,2,0,80,0,1
|
||||
68263,-100,4,2,0,60,0,1
|
||||
68380,-100,4,2,0,80,0,1
|
||||
69201,-100,4,2,0,60,0,1
|
||||
69318,-100,4,2,0,80,0,1
|
||||
69670,-100,4,2,0,70,0,0
|
||||
84670,-100,4,2,0,70,0,0
|
||||
97560,-200,4,2,0,70,0,0
|
||||
97795,-200,4,2,0,30,0,0
|
||||
98966,-100,4,2,0,30,0,0
|
||||
99670,-100,4,2,0,70,0,0
|
||||
113732,-100,4,2,0,40,0,0
|
||||
114670,-100,4,2,0,80,0,1
|
||||
115138,-100,4,2,0,60,0,1
|
||||
115255,-100,4,2,0,80,0,1
|
||||
116076,-100,4,2,0,60,0,1
|
||||
116193,-100,4,2,0,80,0,1
|
||||
117013,-100,4,2,0,60,0,1
|
||||
117130,-100,4,2,0,80,0,1
|
||||
117951,-100,4,2,0,60,0,1
|
||||
118068,-100,4,2,0,80,0,1
|
||||
118888,-100,4,2,0,60,0,1
|
||||
119005,-100,4,2,0,80,0,1
|
||||
119826,-100,4,2,0,60,0,1
|
||||
119943,-100,4,2,0,80,0,1
|
||||
120763,-100,4,2,0,60,0,1
|
||||
120880,-100,4,2,0,80,0,1
|
||||
121701,-100,4,2,0,60,0,1
|
||||
121818,-100,4,2,0,80,0,1
|
||||
122638,-100,4,2,0,60,0,1
|
||||
122755,-100,4,2,0,80,0,1
|
||||
123576,-100,4,2,0,60,0,1
|
||||
123693,-100,4,2,0,80,0,1
|
||||
124513,-100,4,2,0,60,0,1
|
||||
124630,-100,4,2,0,80,0,1
|
||||
125451,-100,4,2,0,60,0,1
|
||||
125568,-100,4,2,0,80,0,1
|
||||
126388,-100,4,2,0,60,0,1
|
||||
126505,-100,4,2,0,80,0,1
|
||||
127326,-100,4,2,0,60,0,1
|
||||
127443,-100,4,2,0,80,0,1
|
||||
128263,-100,4,2,0,60,0,1
|
||||
128380,-100,4,2,0,80,0,1
|
||||
129201,-100,4,2,0,60,0,1
|
||||
129318,-100,4,2,0,80,0,1
|
||||
129670,-200,4,2,0,40,0,0
|
||||
144670,-133.333333333333,4,2,0,40,0,0
|
||||
159670,-133.333333333333,4,2,0,40,0,0
|
||||
163420,-133.333333333333,4,2,0,45,0,0
|
||||
163888,-125,4,2,0,50,0,0
|
||||
164357,-117.647058823529,4,2,0,55,0,0
|
||||
164826,-111.111111111111,4,2,0,60,0,0
|
||||
165295,-105.263157894737,4,2,0,65,0,0
|
||||
165763,-100,4,2,0,70,0,0
|
||||
166232,-100,4,2,0,40,0,0
|
||||
167170,-100,4,2,0,80,0,1
|
||||
167638,-100,4,2,0,60,0,1
|
||||
167755,-100,4,2,0,80,0,1
|
||||
168576,-100,4,2,0,60,0,1
|
||||
168693,-100,4,2,0,80,0,1
|
||||
169513,-100,4,2,0,60,0,1
|
||||
169630,-100,4,2,0,80,0,1
|
||||
170451,-100,4,2,0,60,0,1
|
||||
170568,-100,4,2,0,80,0,1
|
||||
171388,-100,4,2,0,60,0,1
|
||||
171505,-100,4,2,0,80,0,1
|
||||
172326,-100,4,2,0,60,0,1
|
||||
172443,-100,4,2,0,80,0,1
|
||||
173263,-100,4,2,0,60,0,1
|
||||
173380,-100,4,2,0,80,0,1
|
||||
174201,-100,4,2,0,60,0,1
|
||||
174318,-100,4,2,0,80,0,1
|
||||
175138,-100,4,2,0,60,0,1
|
||||
175255,-100,4,2,0,80,0,1
|
||||
176076,-100,4,2,0,60,0,1
|
||||
176193,-100,4,2,0,80,0,1
|
||||
177013,-100,4,2,0,60,0,1
|
||||
177130,-100,4,2,0,80,0,1
|
||||
177951,-100,4,2,0,60,0,1
|
||||
178068,-100,4,2,0,80,0,1
|
||||
178888,-100,4,2,0,60,0,1
|
||||
179005,-100,4,2,0,80,0,1
|
||||
179826,-100,4,2,0,60,0,1
|
||||
179943,-100,4,2,0,80,0,1
|
||||
180763,-100,4,2,0,60,0,1
|
||||
180880,-100,4,2,0,80,0,1
|
||||
180998,-100,4,2,0,80,0,0
|
||||
181466,-100,4,2,0,60,0,0
|
||||
181584,-100,4,2,0,80,0,0
|
||||
181935,-100,4,2,0,80,0,0
|
||||
182170,-100,4,2,0,80,0,1
|
||||
182638,-100,4,2,0,60,0,1
|
||||
182755,-100,4,2,0,80,0,1
|
||||
183576,-100,4,2,0,60,0,1
|
||||
183693,-100,4,2,0,80,0,1
|
||||
184513,-100,4,2,0,60,0,1
|
||||
184630,-100,4,2,0,80,0,1
|
||||
185451,-100,4,2,0,60,0,1
|
||||
185568,-100,4,2,0,80,0,1
|
||||
186388,-100,4,2,0,60,0,1
|
||||
186505,-100,4,2,0,80,0,1
|
||||
187326,-100,4,2,0,60,0,1
|
||||
187443,-100,4,2,0,80,0,1
|
||||
188263,-100,4,2,0,60,0,1
|
||||
188380,-100,4,2,0,80,0,1
|
||||
189201,-100,4,2,0,60,0,1
|
||||
189318,-100,4,2,0,80,0,1
|
||||
190138,-100,4,2,0,60,0,1
|
||||
190255,-100,4,2,0,80,0,1
|
||||
191076,-100,4,2,0,60,0,1
|
||||
191193,-100,4,2,0,80,0,1
|
||||
192013,-100,4,2,0,60,0,1
|
||||
192130,-100,4,2,0,80,0,1
|
||||
192951,-100,4,2,0,60,0,1
|
||||
193068,-100,4,2,0,80,0,1
|
||||
193888,-100,4,2,0,60,0,1
|
||||
194005,-100,4,2,0,80,0,1
|
||||
194826,-100,4,2,0,60,0,1
|
||||
194943,-100,4,2,0,80,0,1
|
||||
195295,-100,4,2,0,50,0,1
|
||||
195529,-100,4,2,0,52,0,1
|
||||
195646,-100,4,2,0,54,0,1
|
||||
195763,-100,4,2,0,56,0,1
|
||||
195880,-100,4,2,0,58,0,1
|
||||
195998,-100,4,2,0,60,0,1
|
||||
196115,-100,4,2,0,62,0,1
|
||||
196232,-100,4,2,0,64,0,1
|
||||
196349,-100,4,2,0,68,0,1
|
||||
196466,-100,4,2,0,70,0,1
|
||||
196584,-100,4,2,0,72,0,1
|
||||
196701,-100,4,2,0,74,0,1
|
||||
196818,-100,4,2,0,76,0,1
|
||||
196935,-100,4,2,0,78,0,1
|
||||
197052,-100,4,2,0,80,0,1
|
||||
197170,-100,4,2,0,80,0,0
|
||||
197873,-100,4,2,0,60,0,0
|
||||
197990,-100,4,2,0,80,0,0
|
||||
198341,-100,4,2,0,60,0,0
|
||||
199045,-100,4,2,0,80,0,0
|
||||
199279,-100,4,2,0,60,0,0
|
||||
199630,-100,4,2,0,80,0,0
|
||||
200216,-100,4,2,0,60,0,0
|
||||
200334,-100,4,2,0,80,0,0
|
||||
201623,-100,4,2,0,60,0,0
|
||||
201740,-100,4,2,0,80,0,0
|
||||
202326,-100,4,2,0,60,0,0
|
||||
202443,-100,4,2,0,80,0,0
|
||||
203029,-100,4,2,0,60,0,0
|
||||
203498,-100,4,2,0,80,0,0
|
||||
203966,-100,4,2,0,60,0,0
|
||||
204201,-100,4,2,0,80,0,0
|
||||
205373,-100,4,2,0,60,0,0
|
||||
205490,-100,4,2,0,80,0,0
|
||||
205841,-100,4,2,0,60,0,0
|
||||
206076,-100,4,2,0,60,0,0
|
||||
206545,-100,4,2,0,80,0,0
|
||||
206779,-100,4,2,0,60,0,0
|
||||
207130,-100,4,2,0,80,0,0
|
||||
207716,-100,4,2,0,60,0,0
|
||||
207951,-100,4,2,0,80,0,0
|
||||
209123,-100,4,2,0,60,0,0
|
||||
209240,-100,4,2,0,80,0,0
|
||||
209826,-100,4,2,0,60,0,0
|
||||
209943,-100,4,2,0,80,0,0
|
||||
210529,-100,4,2,0,60,0,0
|
||||
210880,-100,4,2,0,80,0,0
|
||||
211232,-100,4,2,0,60,0,0
|
||||
211701,-100,4,2,0,70,0,0
|
||||
212170,-100,4,2,0,80,0,0
|
||||
212873,-100,4,2,0,60,0,0
|
||||
212990,-100,4,2,0,80,0,0
|
||||
213341,-100,4,2,0,60,0,0
|
||||
213576,-100,4,2,0,60,0,0
|
||||
214045,-100,4,2,0,80,0,0
|
||||
214279,-100,4,2,0,60,0,0
|
||||
214630,-100,4,2,0,80,0,0
|
||||
215216,-100,4,2,0,60,0,0
|
||||
215451,-100,4,2,0,80,0,0
|
||||
216623,-100,4,2,0,60,0,0
|
||||
216740,-100,4,2,0,80,0,0
|
||||
217326,-100,4,2,0,60,0,0
|
||||
217443,-100,4,2,0,80,0,0
|
||||
218029,-100,4,2,0,60,0,0
|
||||
218498,-100,4,2,0,80,0,0
|
||||
218732,-100,4,2,0,50,0,0
|
||||
219670,-100,4,2,0,70,0,0
|
||||
220138,-100,4,2,0,65,0,0
|
||||
220373,-100,4,2,0,45,0,0
|
||||
220490,-100,4,2,0,65,0,0
|
||||
220607,-100,4,2,0,60,0,0
|
||||
220841,-100,4,2,0,35,0,0
|
||||
221076,-100,4,2,0,35,0,0
|
||||
221545,-100,4,2,0,50,0,0
|
||||
221779,-100,4,2,0,30,0,0
|
||||
222013,-111.111111111111,4,2,0,25,0,0
|
||||
222130,-111.111111111111,4,2,0,40,0,0
|
||||
222482,-125,4,2,0,40,0,0
|
||||
222716,-125,4,2,0,20,0,0
|
||||
222951,-100,4,2,0,15,0,0
|
||||
223420,-100,4,2,0,30,0,0
|
||||
224357,-100,4,2,0,25,0,0
|
||||
225295,-100,4,2,0,20,0,0
|
||||
226232,-100,4,2,0,15,0,0
|
||||
226701,-100,4,2,0,10,0,0
|
||||
227170,-100,4,2,0,5,0,0
|
||||
|
||||
|
||||
[Colours]
|
||||
Combo1 : 17,254,176
|
||||
Combo2 : 173,255,95
|
||||
Combo3 : 255,88,100
|
||||
Combo4 : 255,94,55
|
||||
|
||||
[HitObjects]
|
||||
320,256,2170,6,0,P|256:284|192:256,1,144,4|0,0:0|0:0,0:0:0:0:
|
||||
144,184,2873,1,0,0:0:0:0:
|
||||
108,260,3107,2,0,P|112:296|100:336,1,72
|
||||
28,288,3576,2,0,P|24:252|36:212,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
76,140,4045,6,0,L|220:136,1,144,4|0,0:0|0:0,0:0:0:0:
|
||||
292,88,4748,1,0,0:0:0:0:
|
||||
292,88,4982,2,0,P|304:120|300:168,1,72
|
||||
388,168,5451,2,0,P|396:133|416:103,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
472,172,5920,6,0,B|470:200|457:222|457:222|488:256|476:308,1,144,4|0,0:0|0:0,0:0:0:0:
|
||||
396,280,6623,1,0,0:0:0:0:
|
||||
324,328,6857,2,0,P|288:332|252:324,1,72
|
||||
180,280,7326,2,0,L|108:284,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
256,192,7795,12,0,9670,0:0:0:0:
|
||||
428,212,10138,1,0,0:0:0:0:
|
||||
292,320,10607,1,0,0:0:0:0:
|
||||
184,184,11076,2,0,L|112:180,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
24,172,11545,5,6,0:0:0:0:
|
||||
160,280,12013,1,0,0:0:0:0:
|
||||
268,144,12482,1,0,0:0:0:0:
|
||||
132,36,12951,2,0,L|204:32,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
284,60,13420,6,0,P|340:100|344:180,2,144,6|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
268,144,14591,1,0,0:0:0:0:
|
||||
284,228,14826,2,0,P|316:248|364:252,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
436,248,15295,6,0,P|372:272|344:340,1,144,6|2,0:0|0:0,0:0:0:0:
|
||||
168,338,16232,2,0,P|141:273|76:248,1,144,2|2,0:0|0:0,0:0:0:0:
|
||||
4,296,16935,1,0,0:0:0:0:
|
||||
80,336,17170,5,6,0:0:0:0:
|
||||
44,168,17638,1,0,0:0:0:0:
|
||||
212,128,18107,1,0,0:0:0:0:
|
||||
248,296,18576,2,0,P|284:288|320:292,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
400,324,19045,5,6,0:0:0:0:
|
||||
280,200,19513,1,0,0:0:0:0:
|
||||
368,52,19982,1,0,0:0:0:0:
|
||||
488,176,20451,2,0,P|452:168|416:172,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
336,200,20920,6,0,P|284:216|200:192,1,144,6|0,0:0|0:0,0:0:0:0:
|
||||
200,192,21857,2,0,L|204:264,1,72,0|0,0:3|0:0,0:0:0:0:
|
||||
117,244,22326,2,0,L|120:172,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
40,152,22795,6,0,L|28:296,2,144,6|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
152,24,24201,1,0,0:0:0:0:
|
||||
220,76,24435,1,0,3:0:0:0:
|
||||
304,56,24670,6,0,P|288:120|296:196,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
344,268,25373,1,0,0:0:0:0:
|
||||
416,316,25607,2,0,P|452:312|508:316,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
244,344,26545,6,0,P|176:356|108:328,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
60,256,27248,1,0,0:0:0:0:
|
||||
36,172,27482,2,0,L|40:100,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
188,252,28420,6,0,P|192:184|196:100,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
140,40,29123,1,0,0:0:0:0:
|
||||
140,40,29357,2,0,B|172:16|220:24|220:24|288:36,1,144,0|2,0:0|0:3,0:0:0:0:
|
||||
364,52,30060,1,0,0:0:0:0:
|
||||
308,116,30295,6,0,B|300:168|300:168|328:256,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
340,340,30998,1,0,0:0:0:0:
|
||||
260,308,31232,2,0,L|188:304,1,72,0|2,0:0|0:3,0:0:0:0:
|
||||
100,296,31701,1,2,0:3:0:0:
|
||||
136,374,31935,1,0,0:0:0:0:
|
||||
152,224,32170,6,0,P|160:152|132:88,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
56,48,32873,1,0,0:0:0:0:
|
||||
60,136,33107,2,0,L|56:208,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
224,76,34045,6,0,P|289:104|360:96,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
432,48,34748,1,0,0:0:0:0:
|
||||
440,132,34982,2,0,B|432:156|432:156|436:204,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
448,304,35920,6,0,B|412:315|380:292|380:292|348:269|312:280,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
332,364,36623,1,0,0:0:0:0:
|
||||
247,339,36857,2,0,P|230:308|225:273,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
312,280,37560,6,0,L|316:172,1,108
|
||||
134,35,38966,5,0,0:0:0:0:
|
||||
72,96,39201,2,0,P|119:119|171:111,1,108,0|0,0:0|0:0,0:0:0:0:
|
||||
192,100,39670,6,0,L|200:172,1,72,4|2,0:0|0:0,0:0:0:0:
|
||||
147,240,40138,2,0,P|133:272|132:308,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
216,292,40607,2,0,B|260:308|260:308|356:292,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
356,292,41310,1,2,0:0:0:0:
|
||||
436,327,41545,6,0,P|441:292|435:257,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
364,204,42013,2,0,P|336:144|352:68,1,144,0|4,1:0|2:3,1:0:0:0:
|
||||
404,0,42716,1,2,0:0:0:0:
|
||||
440,80,42951,2,0,B|464:84|464:84|512:80,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
351,71,43420,6,0,B|296:68|296:68|268:76|268:76|196:72,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
120,68,44123,1,2,0:0:0:0:
|
||||
160,144,44357,2,0,P|172:180|168:232,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
76,264,44826,2,0,P|76:228|88:194,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
160,144,45295,5,4,0:3:0:0:
|
||||
244,164,45529,1,2,0:0:0:0:
|
||||
268,248,45763,2,0,L|344:252,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
408,156,46232,2,0,L|336:159,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
212,72,46701,2,0,L|288:76,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
400,72,47170,6,0,P|464:96|488:172,1,144,4|0,2:0|1:0,1:0:0:0:
|
||||
476,248,47873,1,2,0:0:0:0:
|
||||
436,324,48107,2,0,L|284:320,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
204,316,48810,1,2,0:0:0:0:
|
||||
127,355,49045,6,0,P|120:321|124:285,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
192,232,49513,2,0,L|335:228,1,144,0|4,1:0|2:3,1:0:0:0:
|
||||
412,188,50216,1,2,0:0:0:0:
|
||||
444,108,50451,2,0,P|452:72|448:36,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
368,68,50920,6,0,B|332:79|300:56|300:56|268:33|232:44,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
152,76,51623,1,2,0:0:0:0:
|
||||
76,116,51857,2,0,L|80:268,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
80,260,52560,1,2,0:0:0:0:
|
||||
8,308,52795,6,0,P|34:334|69:346,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
148,312,53263,2,0,P|163:278|162:241,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
156,156,53732,5,0,3:0:0:0:
|
||||
156,156,53966,1,2,0:0:0:0:
|
||||
236,196,54201,2,0,L|312:192,1,72,8|0,0:3|0:0,0:0:0:0:
|
||||
368,256,54670,6,0,P|392:216|352:116,1,144,4|2,0:0|1:2,0:0:0:0:
|
||||
288,92,55373,1,0,0:0:0:0:
|
||||
360,40,55607,2,0,L|432:36,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
288,92,56076,2,0,L|216:88,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
132,72,56545,6,0,P|172:88|200:184,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
143,241,57248,1,0,0:0:0:0:
|
||||
65,202,57482,2,0,P|87:174|119:157,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
132,324,57951,2,0,P|98:312|72:288,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
143,241,58420,6,0,L|288:240,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
372,240,59123,1,0,0:0:0:0:
|
||||
330,314,59357,2,0,P|318:350|322:390,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
452,264,59826,2,0,P|453:228|442:194,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
384,128,60295,6,0,B|336:144|336:144|244:128,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
164,160,60998,2,0,P|160:116|168:88,1,72,0|4,0:0|0:3,0:0:0:0:
|
||||
244,128,61466,2,0,P|248:172|240:200,1,72,0|2,3:0|1:2,0:0:0:0:
|
||||
168,248,61935,1,0,0:0:0:0:
|
||||
120,320,62170,6,0,P|196:328|252:272,2,144,4|2|4,0:3|1:2|0:3,0:0:0:0:
|
||||
80,244,63341,1,0,3:0:0:0:
|
||||
100,160,63576,2,0,L|24:156,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
180,128,64045,6,0,P|249:138|304:94,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
226,57,64748,1,0,0:0:0:0:
|
||||
304,94,64982,2,0,L|300:166,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
377,203,65451,2,0,L|388:132,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
468,180,65920,6,0,L|432:328,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
276,252,66857,2,0,P|208:248|140:280,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
84,344,67560,1,0,0:0:0:0:
|
||||
56,260,67795,6,0,L|52:188,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
168,128,68732,2,0,L|172:56,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
244,168,69435,1,0,0:0:0:0:
|
||||
332,164,69670,1,4,0:3:0:0:
|
||||
208,328,84670,6,0,P|224:264|216:188,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
168,116,85373,1,0,0:0:0:0:
|
||||
96,68,85607,2,0,P|60:72|4:68,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
268,40,86545,6,0,P|336:28|404:56,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
452,128,87248,1,0,0:0:0:0:
|
||||
476,212,87482,2,0,L|472:284,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
324,132,88420,6,0,P|320:200|316:284,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
372,344,89123,1,0,0:0:0:0:
|
||||
372,344,89357,2,0,B|340:368|292:360|292:360|224:348,1,144,0|2,0:0|0:3,0:0:0:0:
|
||||
148,332,90060,1,0,0:0:0:0:
|
||||
204,268,90295,6,0,B|212:216|212:216|184:128,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
172,44,90998,1,0,0:0:0:0:
|
||||
252,76,91232,2,0,L|324:80,1,72,0|2,0:0|0:3,0:0:0:0:
|
||||
412,88,91701,1,2,0:3:0:0:
|
||||
377,9,91935,1,0,0:0:0:0:
|
||||
360,160,92170,6,0,P|352:232|380:296,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
456,336,92873,1,0,0:0:0:0:
|
||||
452,248,93107,2,0,L|456:176,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
288,308,94045,6,0,P|223:280|152:288,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
80,336,94748,1,0,0:0:0:0:
|
||||
72,252,94982,2,0,B|80:228|80:228|76:180,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
64,80,95920,6,0,B|100:69|132:92|132:92|164:115|200:104,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
180,20,96623,1,0,0:0:0:0:
|
||||
265,45,96857,2,0,P|282:76|287:111,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
200,104,97560,1,0,0:0:0:0:
|
||||
200,104,97677,1,0,0:0:0:0:
|
||||
200,104,97795,6,0,B|196:142|217:166|217:166|176:180|160:220,1,144,4|0,0:3|0:0,0:0:0:0:
|
||||
240,248,98966,5,0,0:0:0:0:
|
||||
202,325,99201,2,0,P|254:333|301:309,1,108,0|0,0:0|0:0,0:0:0:0:
|
||||
315,292,99670,6,0,L|323:220,1,72,4|2,0:0|0:0,0:0:0:0:
|
||||
365,144,100138,2,0,P|379:112|380:76,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
296,92,100607,2,0,B|252:76|252:76|156:92,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
156,92,101310,1,2,0:0:0:0:
|
||||
76,57,101545,6,0,P|71:92|77:127,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
148,180,102013,2,0,P|176:240|160:316,1,144,0|4,1:0|2:3,1:0:0:0:
|
||||
108,384,102716,1,2,0:0:0:0:
|
||||
72,304,102951,2,0,B|48:300|48:300|0:304,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
161,313,103420,6,0,B|216:316|216:316|244:308|244:308|316:312,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
392,316,104123,1,2,0:0:0:0:
|
||||
352,240,104357,2,0,P|340:204|344:152,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
436,120,104826,2,0,P|436:156|424:190,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
352,240,105295,5,4,0:3:0:0:
|
||||
268,220,105529,1,2,0:0:0:0:
|
||||
244,136,105763,2,0,L|168:132,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
104,228,106232,2,0,L|176:225,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
300,312,106701,2,0,L|224:308,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
112,312,107170,6,0,P|48:288|24:212,1,144,4|0,2:0|1:0,1:0:0:0:
|
||||
36,136,107873,1,2,0:0:0:0:
|
||||
76,60,108107,2,0,L|228:64,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
308,68,108810,1,2,0:0:0:0:
|
||||
385,29,109045,6,0,P|392:63|388:99,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
320,152,109513,2,0,L|177:156,1,144,0|4,1:0|2:3,1:0:0:0:
|
||||
100,196,110216,1,2,0:0:0:0:
|
||||
68,276,110451,2,0,P|60:312|64:348,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
144,316,110920,6,0,B|180:305|212:328|212:328|244:351|280:340,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
360,308,111623,1,2,0:0:0:0:
|
||||
436,268,111857,2,0,L|432:116,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
432,124,112560,1,2,0:0:0:0:
|
||||
504,76,112795,6,0,P|478:50|443:38,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
364,72,113263,2,0,P|349:106|350:143,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
356,228,113732,5,0,3:0:0:0:
|
||||
356,228,113966,1,2,0:0:0:0:
|
||||
276,188,114201,2,0,L|200:192,1,72,8|0,0:3|0:0,0:0:0:0:
|
||||
144,128,114670,6,0,P|120:168|160:268,1,144,4|2,0:0|1:2,0:0:0:0:
|
||||
224,292,115373,1,0,0:0:0:0:
|
||||
152,344,115607,2,0,L|80:348,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
224,292,116076,2,0,L|296:296,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
380,312,116545,6,0,P|340:296|312:200,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
369,143,117248,1,0,0:0:0:0:
|
||||
447,182,117482,2,0,P|425:210|393:227,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
380,60,117951,2,0,P|414:72|440:96,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
369,143,118420,6,0,L|224:144,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
140,144,119123,1,0,0:0:0:0:
|
||||
182,70,119357,2,0,P|194:34|190:-6,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
60,120,119826,2,0,P|59:156|70:190,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
128,256,120295,6,0,B|176:240|176:240|268:256,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
348,224,120998,2,0,P|352:268|344:296,1,72,0|4,0:0|0:3,0:0:0:0:
|
||||
268,256,121466,2,0,P|264:212|272:184,1,72,0|2,3:0|1:2,0:0:0:0:
|
||||
344,136,121935,1,0,0:0:0:0:
|
||||
392,64,122170,6,0,P|316:56|260:112,2,144,4|2|4,0:3|1:2|0:3,0:0:0:0:
|
||||
432,140,123341,1,0,3:0:0:0:
|
||||
412,224,123576,2,0,L|488:228,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
332,256,124045,6,0,P|263:246|208:290,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
286,327,124748,1,0,0:0:0:0:
|
||||
208,290,124982,2,0,L|212:218,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
135,181,125451,2,0,L|124:252,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
44,204,125920,6,0,L|80:56,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
236,132,126857,2,0,P|304:136|372:104,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
428,40,127560,1,0,0:0:0:0:
|
||||
456,124,127795,6,0,L|460:196,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
344,256,128732,2,0,L|340:328,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
268,216,129435,1,0,0:0:0:0:
|
||||
180,220,129670,5,4,2:0:0:0:
|
||||
256,40,130373,1,2,0:0:0:0:
|
||||
64,68,131076,1,2,0:0:0:0:
|
||||
92,136,131310,1,0,0:0:0:0:
|
||||
64,204,131545,6,0,L|60:288,1,72
|
||||
31,343,132248,2,0,P|86:345|127:309,1,108
|
||||
332,220,133420,5,2,0:0:0:0:
|
||||
256,40,134123,1,2,0:0:0:0:
|
||||
448,68,134826,1,2,0:0:0:0:
|
||||
420,136,135060,1,0,0:0:0:0:
|
||||
448,204,135295,6,0,L|452:288,1,72,2|0,0:0|0:0,0:0:0:0:
|
||||
480,343,135998,2,0,P|426:345|385:309,1,108
|
||||
256,192,137170,5,2,0:0:0:0:
|
||||
156,360,137873,1,2,0:0:0:0:
|
||||
356,360,138576,2,0,L|352:308,1,36,2|0,0:0|0:0,0:0:0:0:
|
||||
304,268,139045,6,0,P|336:253|372:252,1,72
|
||||
448,260,139748,2,0,L|444:152,1,108
|
||||
256,192,140920,5,2,0:0:0:0:
|
||||
356,24,141623,1,2,0:0:0:0:
|
||||
156,24,142326,2,0,L|160:72,1,36,2|0,0:0|0:0,0:0:0:0:
|
||||
208,116,142795,6,0,P|176:131|140:132,1,72,2|0,0:0|0:0,0:0:0:0:
|
||||
64,124,143498,2,0,L|68:232,1,108
|
||||
68,232,144670,5,4,0:3:0:0:
|
||||
216,320,145138,1,4,0:3:0:0:
|
||||
304,172,145607,1,4,0:3:0:0:
|
||||
156,84,146075,1,4,0:3:0:0:
|
||||
296,320,146545,5,4,0:3:0:0:
|
||||
208,172,147013,1,4,0:3:0:0:
|
||||
356,84,147482,1,4,0:3:0:0:
|
||||
444,232,147950,1,4,0:3:0:0:
|
||||
296,320,148420,6,0,P|252:328|192:296,2,108.000004119873,4|4|4,0:3|0:3|0:3,0:0:0:0:
|
||||
260,248,149591,1,0,0:0:0:0:
|
||||
320,196,149826,2,0,L|316:140,1,54.0000020599366,4|0,0:3|0:0,0:0:0:0:
|
||||
120,236,159670,6,0,L|176:232,1,54.0000020599366,4|0,0:3|0:0,0:0:0:0:
|
||||
160,152,160138,2,0,L|104:156,1,54.0000020599366,2|0,0:0|0:0,0:0:0:0:
|
||||
240,180,160607,2,0,P|292:188|344:172,1,108.000004119873,4|2,0:3|0:0,3:0:0:0:
|
||||
408,120,161310,1,0,3:0:0:0:
|
||||
424,200,161545,6,0,L|420:256,1,54.0000020599366,4|0,0:3|0:0,0:0:0:0:
|
||||
376,320,162013,2,0,P|396:328|480:304,2,108.000004119873,2|6|2,2:0|0:3|2:0,3:0:0:0:
|
||||
312,268,163185,1,0,0:0:0:0:
|
||||
296,348,163420,6,0,L|240:344,1,54.0000020599366,4|0,3:0|3:0,0:0:0:0:
|
||||
160,320,163888,2,0,L|100:316,1,57.6,4|0,3:0|3:0,0:0:0:0:
|
||||
64,232,164357,6,0,L|128:228,1,61.2000011672974,4|0,3:0|3:0,0:0:0:0:
|
||||
204,200,164825,2,0,L|268:196,1,61.2000011672974,4|0,3:0|3:0,0:0:0:0:
|
||||
232,108,165295,6,0,L|164:104,1,68.399998173523,4|0,3:0|3:0,0:0:0:0:
|
||||
80,84,165763,2,0,L|4:80,1,72,4|0,3:0|3:0,0:0:0:0:
|
||||
324,120,167170,6,0,P|388:128|456:92,1,144,4|2,0:0|1:2,0:0:0:0:
|
||||
496,168,167873,1,0,0:0:0:0:
|
||||
496,168,168107,2,0,P|484:204|488:256,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
408,296,168576,2,0,P|398:261|378:231,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
296,200,169045,6,0,B|228:228|156:204,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
84,156,169748,1,0,0:0:0:0:
|
||||
80,244,169982,2,0,L|76:316,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
170,274,170451,2,0,L|156:204,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
216,140,170920,6,0,L|284:276,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
320,344,171623,1,0,0:0:0:0:
|
||||
372,276,171857,2,0,P|366:240|349:207,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
312,132,172326,2,0,L|276:60,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
208,20,172795,6,0,P|272:36|348:12,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
424,48,173498,2,0,L|412:132,1,72,0|4,0:0|0:3,0:0:0:0:
|
||||
484,168,173966,2,0,L|472:252,1,72,0|2,3:0|1:2,0:0:0:0:
|
||||
400,280,174435,1,0,0:0:0:0:
|
||||
346,348,174670,6,0,P|414:363|472:324,2,144,4|2|4,0:3|1:2|0:3,0:0:0:0:
|
||||
312,268,175841,1,0,3:0:0:0:
|
||||
256,336,176076,2,0,L|184:332,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
80,244,176545,6,0,B|140:248|140:248|164:244|164:244|223:247,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
312,268,177248,1,0,0:0:0:0:
|
||||
224,247,177482,2,0,P|240:215|272:187,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
204,131,177951,2,0,P|233:111|275:103,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
240,23,178420,6,0,B|280:15|316:35|316:35|376:71,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
399,236,179357,2,0,B|359:244|323:224|323:224|263:188,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
204,132,180060,1,0,0:0:0:0:
|
||||
184,216,180295,6,0,L|188:288,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
120,156,180998,1,0,0:0:0:0:
|
||||
56,96,181232,2,0,L|60:24,2,72,4|2|0,0:3|0:0|1:0,0:0:0:0:
|
||||
36,180,181935,1,0,0:0:0:0:
|
||||
100,240,182170,6,0,P|144:300|116:380,2,144,4|2|4,0:0|1:2|0:3,0:0:0:0:
|
||||
60,316,183341,1,0,0:0:0:0:
|
||||
220,352,183576,2,0,L|308:348,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
396,264,184045,6,0,B|336:268|336:268|312:264|312:264|253:267,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
253,267,184748,1,0,0:0:0:0:
|
||||
268,180,184982,2,0,L|339:177,1,72,4|0,0:3|0:0,0:0:0:0:
|
||||
164,280,185451,2,0,L|92:282,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
52,208,185920,6,0,P|8:268|32:344,2,144,4|2|4,0:3|1:2|0:3,0:0:0:0:
|
||||
140,212,187091,1,0,0:0:0:0:
|
||||
92,284,187326,2,0,P|104:316|100:368,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
52,208,187795,6,0,P|48:136|76:72,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
160,52,188498,2,0,P|188:28|220:16,1,72,0|4,0:0|0:3,0:0:0:0:
|
||||
232,100,188966,2,0,P|268:93|301:98,1,72,0|2,0:0|1:2,0:0:0:0:
|
||||
372,152,189435,1,0,0:0:0:0:
|
||||
420,224,189670,6,0,P|428:296|400:360,2,144,4|2|4,0:3|1:2|0:3,0:0:0:0:
|
||||
372,152,190841,1,0,0:0:0:0:
|
||||
392,68,191076,2,0,L|465:64,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
304,92,191545,6,0,P|236:104|168:76,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
108,12,192248,1,0,0:0:0:0:
|
||||
168,76,192482,2,0,L|172:152,1,72,4|0,0:3|0:0,0:0:0:0:
|
||||
80,136,192951,2,0,L|101:204,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
12,220,193420,6,0,B|50:279|50:279|80:300|120:292,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
284,232,194357,2,0,B|320:221|352:244|352:244|384:267|420:256,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
488,200,195060,1,0,0:0:0:0:
|
||||
507,284,195295,6,0,P|492:315|464:338,1,72,4|0,0:0|0:0,0:0:0:0:
|
||||
380,356,195763,2,0,L|236:352,1,144,0|4,1:0|0:3,0:0:0:0:
|
||||
152,328,196466,1,0,3:0:0:0:
|
||||
64,336,196701,2,0,P|29:325|4:300,1,72,0|0,1:0|0:0,0:0:0:0:
|
||||
76,252,197170,6,0,P|108:188|96:116,1,144,4|0,0:0|1:0,0:0:0:0:
|
||||
36,56,197873,1,2,0:0:0:0:
|
||||
120,32,198107,2,0,L|192:28,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
248,152,199045,6,0,P|280:168|304:196,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
336,277,199513,2,0,P|306:296|269:303,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
183,290,199982,2,0,P|180:254|193:219,2,72,4|2|0,0:3|0:0|1:0,0:0:0:0:
|
||||
436,252,200920,6,0,P|404:188|416:116,1,144,4|0,0:3|1:0,0:0:0:0:
|
||||
476,56,201623,1,2,0:0:0:0:
|
||||
392,32,201857,2,0,L|320:28,2,72,4|0|2,0:3|0:0|1:2,0:0:0:0:
|
||||
264,152,202795,6,0,P|232:168|208:196,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
176,277,203263,2,0,P|205:296|242:303,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
329,290,203732,2,0,P|331:254|318:219,2,72,4|2|0,0:3|0:0|1:0,0:0:0:0:
|
||||
72,324,204670,6,0,B|60:272|60:272|76:180,1,144,4|0,0:0|1:0,0:0:0:0:
|
||||
92,96,205373,1,2,0:0:0:0:
|
||||
8,124,205607,2,0,P|5:88|14:53,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
168,192,206545,6,0,P|200:174|237:173,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
320,160,207013,2,0,P|318:196|301:229,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
272,307,207482,2,0,P|240:287|221:256,2,72,4|2|0,0:3|0:0|1:0,0:0:0:0:
|
||||
440,324,208420,6,0,B|452:272|452:272|436:180,1,144,4|0,0:3|1:0,0:0:0:0:
|
||||
420,96,209123,1,2,0:0:0:0:
|
||||
504,124,209357,2,0,P|507:88|498:53,2,72,4|0|2,0:3|0:0|1:2,0:0:0:0:
|
||||
344,192,210295,6,0,P|311:174|274:173,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
190,156,210763,2,0,P|191:192|208:225,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
288,256,211232,1,4,0:3:0:0:
|
||||
132,332,211701,1,0,1:0:0:0:
|
||||
28,192,212170,6,0,P|16:120|44:56,1,144,4|0,0:0|1:0,0:0:0:0:
|
||||
120,16,212873,1,2,0:0:0:0:
|
||||
204,32,213107,2,0,L|304:28,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
192,204,214045,6,0,P|196:240|216:272,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
298,241,214513,2,0,P|327:219|345:186,1,72,6|0,1:2|0:0,0:0:0:0:
|
||||
280,132,214982,2,0,P|246:117|209:118,2,72,4|2|0,0:3|0:0|1:0,0:0:0:0:
|
||||
484,192,215920,6,0,P|496:120|468:56,1,144,4|0,0:3|1:0,0:0:0:0:
|
||||
392,16,216623,1,2,0:0:0:0:
|
||||
308,32,216857,2,0,L|208:28,2,72,4|0|2,0:3|0:0|1:2,0:0:0:0:
|
||||
320,204,217795,6,0,P|316:240|296:272,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
213,241,218263,2,0,P|184:219|166:186,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
232,132,218732,2,0,B|260:112|300:116|300:116|384:128,1,144,4|0,0:3|1:0,0:0:0:0:
|
||||
348,336,219670,6,0,B|320:356|280:352|280:352|196:340,1,144,4|0,0:0|1:0,0:0:0:0:
|
||||
124,328,220373,1,2,0:0:0:0:
|
||||
54,276,220607,2,0,P|41:308|39:345,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
156,80,221545,6,0,L|251:94,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
212,169,222013,2,0,L|148:160,1,64.799998022461,2|0,1:2|0:0,0:0:0:0:
|
||||
140,240,222482,2,0,L|216:252,2,57.6,4|2|0,0:3|0:0|1:0,0:0:0:0:
|
||||
256,192,223420,12,0,227170,0:0:0:0:
|
||||
";
|
||||
}
|
||||
}
|
||||
|
@ -73,10 +73,10 @@ namespace osu.Game.Users
|
||||
public struct UserRanks
|
||||
{
|
||||
[JsonProperty(@"global")]
|
||||
public int Global;
|
||||
public int? Global;
|
||||
|
||||
[JsonProperty(@"country")]
|
||||
public int Country;
|
||||
public int? Country;
|
||||
}
|
||||
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user