mirror of
https://github.com/ppy/osu.git
synced 2024-12-15 09:02:55 +08:00
Merge branch 'changelog-overlay' of https://github.com/HoutarouOreki/osu into changelog-overlay
This commit is contained in:
commit
50b6f88a4e
@ -28,18 +28,20 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
|
|
||||||
protected override IEnumerable<ConvertValue> CreateConvertValue(HitObject hitObject)
|
protected override IEnumerable<ConvertValue> CreateConvertValue(HitObject hitObject)
|
||||||
{
|
{
|
||||||
if (hitObject is JuiceStream stream)
|
switch (hitObject)
|
||||||
{
|
{
|
||||||
foreach (var nested in stream.NestedHitObjects)
|
case JuiceStream stream:
|
||||||
yield return new ConvertValue((CatchHitObject)nested);
|
foreach (var nested in stream.NestedHitObjects)
|
||||||
|
yield return new ConvertValue((CatchHitObject)nested);
|
||||||
|
break;
|
||||||
|
case BananaShower shower:
|
||||||
|
foreach (var nested in shower.NestedHitObjects)
|
||||||
|
yield return new ConvertValue((CatchHitObject)nested);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
yield return new ConvertValue((CatchHitObject)hitObject);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (hitObject is BananaShower shower)
|
|
||||||
{
|
|
||||||
foreach (var nested in shower.NestedHitObjects)
|
|
||||||
yield return new ConvertValue((CatchHitObject)nested);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
yield return new ConvertValue((CatchHitObject)hitObject);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Ruleset CreateRuleset() => new CatchRuleset();
|
protected override Ruleset CreateRuleset() => new CatchRuleset();
|
||||||
|
@ -46,13 +46,16 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
|||||||
|
|
||||||
foreach (var hitObject in beatmap.HitObjects)
|
foreach (var hitObject in beatmap.HitObjects)
|
||||||
{
|
{
|
||||||
// We want to only consider fruits that contribute to the combo. Droplets are addressed as accuracy and spinners are not relevant for "skill" calculations.
|
switch (hitObject)
|
||||||
if (hitObject is Fruit)
|
|
||||||
{
|
{
|
||||||
difficultyHitObjects.Add(new CatchDifficultyHitObject((CatchHitObject)hitObject, halfCatchWidth));
|
// We want to only consider fruits that contribute to the combo. Droplets are addressed as accuracy and spinners are not relevant for "skill" calculations.
|
||||||
|
case Fruit fruit:
|
||||||
|
difficultyHitObjects.Add(new CatchDifficultyHitObject(fruit, halfCatchWidth));
|
||||||
|
break;
|
||||||
|
case JuiceStream _:
|
||||||
|
difficultyHitObjects.AddRange(hitObject.NestedHitObjects.OfType<CatchHitObject>().Where(o => !(o is TinyDroplet)).Select(o => new CatchDifficultyHitObject(o, halfCatchWidth)));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (hitObject is JuiceStream)
|
|
||||||
difficultyHitObjects.AddRange(hitObject.NestedHitObjects.OfType<CatchHitObject>().Where(o => !(o is TinyDroplet)).Select(o => new CatchDifficultyHitObject(o, halfCatchWidth)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
difficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime));
|
difficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime));
|
||||||
|
@ -23,8 +23,10 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
private readonly CatcherArea catcherArea;
|
private readonly CatcherArea catcherArea;
|
||||||
|
|
||||||
public CatchPlayfield(BeatmapDifficulty difficulty, Func<CatchHitObject, DrawableHitObject<CatchHitObject>> getVisualRepresentation)
|
public CatchPlayfield(BeatmapDifficulty difficulty, Func<CatchHitObject, DrawableHitObject<CatchHitObject>> getVisualRepresentation)
|
||||||
: base(ScrollingDirection.Down, BASE_WIDTH)
|
: base(BASE_WIDTH)
|
||||||
{
|
{
|
||||||
|
Direction.Value = ScrollingDirection.Down;
|
||||||
|
|
||||||
Container explodingFruitContainer;
|
Container explodingFruitContainer;
|
||||||
|
|
||||||
Anchor = Anchor.TopCentre;
|
Anchor = Anchor.TopCentre;
|
||||||
|
@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
|
|
||||||
private Drawable createColumn(ScrollingDirection direction, ManiaAction action)
|
private Drawable createColumn(ScrollingDirection direction, ManiaAction action)
|
||||||
{
|
{
|
||||||
var column = new Column(direction)
|
var column = new Column
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
|
@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
{
|
{
|
||||||
var specialAction = ManiaAction.Special1;
|
var specialAction = ManiaAction.Special1;
|
||||||
|
|
||||||
var stage = new ManiaStage(direction, 0, new StageDefinition { Columns = 2 }, ref action, ref specialAction) { VisibleTimeRange = { Value = 2000 } };
|
var stage = new ManiaStage(0, new StageDefinition { Columns = 2 }, ref action, ref specialAction) { VisibleTimeRange = { Value = 2000 } };
|
||||||
stages.Add(stage);
|
stages.Add(stage);
|
||||||
|
|
||||||
return new ScrollingTestContainer(direction)
|
return new ScrollingTestContainer(direction)
|
||||||
|
@ -133,26 +133,26 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
|
|
||||||
if (ConversionDifficulty > 6.5)
|
if (ConversionDifficulty > 6.5)
|
||||||
{
|
{
|
||||||
if ((convertType & PatternType.LowProbability) > 0)
|
if (convertType.HasFlag(PatternType.LowProbability))
|
||||||
return generateNRandomNotes(HitObject.StartTime, 0.78, 0.3, 0);
|
return generateNRandomNotes(HitObject.StartTime, 0.78, 0.3, 0);
|
||||||
return generateNRandomNotes(HitObject.StartTime, 0.85, 0.36, 0.03);
|
return generateNRandomNotes(HitObject.StartTime, 0.85, 0.36, 0.03);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ConversionDifficulty > 4)
|
if (ConversionDifficulty > 4)
|
||||||
{
|
{
|
||||||
if ((convertType & PatternType.LowProbability) > 0)
|
if (convertType.HasFlag(PatternType.LowProbability))
|
||||||
return generateNRandomNotes(HitObject.StartTime, 0.43, 0.08, 0);
|
return generateNRandomNotes(HitObject.StartTime, 0.43, 0.08, 0);
|
||||||
return generateNRandomNotes(HitObject.StartTime, 0.56, 0.18, 0);
|
return generateNRandomNotes(HitObject.StartTime, 0.56, 0.18, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ConversionDifficulty > 2.5)
|
if (ConversionDifficulty > 2.5)
|
||||||
{
|
{
|
||||||
if ((convertType & PatternType.LowProbability) > 0)
|
if (convertType.HasFlag(PatternType.LowProbability))
|
||||||
return generateNRandomNotes(HitObject.StartTime, 0.3, 0, 0);
|
return generateNRandomNotes(HitObject.StartTime, 0.3, 0, 0);
|
||||||
return generateNRandomNotes(HitObject.StartTime, 0.37, 0.08, 0);
|
return generateNRandomNotes(HitObject.StartTime, 0.37, 0.08, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((convertType & PatternType.LowProbability) > 0)
|
if (convertType.HasFlag(PatternType.LowProbability))
|
||||||
return generateNRandomNotes(HitObject.StartTime, 0.17, 0, 0);
|
return generateNRandomNotes(HitObject.StartTime, 0.17, 0, 0);
|
||||||
return generateNRandomNotes(HitObject.StartTime, 0.27, 0, 0);
|
return generateNRandomNotes(HitObject.StartTime, 0.27, 0, 0);
|
||||||
}
|
}
|
||||||
@ -209,7 +209,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
var pattern = new Pattern();
|
var pattern = new Pattern();
|
||||||
|
|
||||||
int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true);
|
int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true);
|
||||||
if ((convertType & PatternType.ForceNotStack) > 0 && PreviousPattern.ColumnWithObjects < TotalColumns)
|
if (convertType.HasFlag(PatternType.ForceNotStack) && PreviousPattern.ColumnWithObjects < TotalColumns)
|
||||||
{
|
{
|
||||||
while (PreviousPattern.ColumnHasObject(nextColumn))
|
while (PreviousPattern.ColumnHasObject(nextColumn))
|
||||||
nextColumn = Random.Next(RandomStart, TotalColumns);
|
nextColumn = Random.Next(RandomStart, TotalColumns);
|
||||||
@ -361,7 +361,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
|
|
||||||
bool isDoubleSample(SampleInfo sample) => sample.Name == SampleInfo.HIT_CLAP || sample.Name == SampleInfo.HIT_FINISH;
|
bool isDoubleSample(SampleInfo sample) => sample.Name == SampleInfo.HIT_CLAP || sample.Name == SampleInfo.HIT_FINISH;
|
||||||
|
|
||||||
bool canGenerateTwoNotes = (convertType & PatternType.LowProbability) == 0;
|
bool canGenerateTwoNotes = !convertType.HasFlag(PatternType.LowProbability);
|
||||||
canGenerateTwoNotes &= HitObject.Samples.Any(isDoubleSample) || sampleInfoListAt(HitObject.StartTime).Any(isDoubleSample);
|
canGenerateTwoNotes &= HitObject.Samples.Any(isDoubleSample) || sampleInfoListAt(HitObject.StartTime).Any(isDoubleSample);
|
||||||
|
|
||||||
if (canGenerateTwoNotes)
|
if (canGenerateTwoNotes)
|
||||||
@ -391,7 +391,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
int columnRepeat = Math.Min(spanCount, TotalColumns);
|
int columnRepeat = Math.Min(spanCount, TotalColumns);
|
||||||
|
|
||||||
int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true);
|
int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true);
|
||||||
if ((convertType & PatternType.ForceNotStack) > 0 && PreviousPattern.ColumnWithObjects < TotalColumns)
|
if (convertType.HasFlag(PatternType.ForceNotStack) && PreviousPattern.ColumnWithObjects < TotalColumns)
|
||||||
{
|
{
|
||||||
while (PreviousPattern.ColumnHasObject(nextColumn))
|
while (PreviousPattern.ColumnHasObject(nextColumn))
|
||||||
nextColumn = Random.Next(RandomStart, TotalColumns);
|
nextColumn = Random.Next(RandomStart, TotalColumns);
|
||||||
@ -425,7 +425,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
var pattern = new Pattern();
|
var pattern = new Pattern();
|
||||||
|
|
||||||
int holdColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true);
|
int holdColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true);
|
||||||
if ((convertType & PatternType.ForceNotStack) > 0 && PreviousPattern.ColumnWithObjects < TotalColumns)
|
if (convertType.HasFlag(PatternType.ForceNotStack) && PreviousPattern.ColumnWithObjects < TotalColumns)
|
||||||
{
|
{
|
||||||
while (PreviousPattern.ColumnHasObject(holdColumn))
|
while (PreviousPattern.ColumnHasObject(holdColumn))
|
||||||
holdColumn = Random.Next(RandomStart, TotalColumns);
|
holdColumn = Random.Next(RandomStart, TotalColumns);
|
||||||
|
@ -33,15 +33,19 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
|
|
||||||
bool generateHold = endTime - HitObject.StartTime >= 100;
|
bool generateHold = endTime - HitObject.StartTime >= 100;
|
||||||
|
|
||||||
if (TotalColumns == 8)
|
switch (TotalColumns)
|
||||||
{
|
{
|
||||||
if (HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_FINISH) && endTime - HitObject.StartTime < 1000)
|
case 8 when HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_FINISH) && endTime - HitObject.StartTime < 1000:
|
||||||
addToPattern(pattern, 0, generateHold);
|
addToPattern(pattern, 0, generateHold);
|
||||||
else
|
break;
|
||||||
|
case 8:
|
||||||
addToPattern(pattern, getNextRandomColumn(RandomStart), generateHold);
|
addToPattern(pattern, getNextRandomColumn(RandomStart), generateHold);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (TotalColumns > 0)
|
||||||
|
addToPattern(pattern, getNextRandomColumn(0), generateHold);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (TotalColumns > 0)
|
|
||||||
addToPattern(pattern, getNextRandomColumn(0), generateHold);
|
|
||||||
|
|
||||||
return pattern;
|
return pattern;
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
|
|
||||||
private readonly PatternType convertType;
|
private readonly PatternType convertType;
|
||||||
|
|
||||||
public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, PatternType lastStair, IBeatmap originalBeatmap)
|
public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density,
|
||||||
|
PatternType lastStair, IBeatmap originalBeatmap)
|
||||||
: base(random, hitObject, beatmap, previousPattern, originalBeatmap)
|
: base(random, hitObject, beatmap, previousPattern, originalBeatmap)
|
||||||
{
|
{
|
||||||
if (previousTime > hitObject.StartTime) throw new ArgumentOutOfRangeException(nameof(previousTime));
|
if (previousTime > hitObject.StartTime) throw new ArgumentOutOfRangeException(nameof(previousTime));
|
||||||
@ -79,7 +80,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
else
|
else
|
||||||
convertType |= PatternType.LowProbability;
|
convertType |= PatternType.LowProbability;
|
||||||
|
|
||||||
if ((convertType & PatternType.KeepSingle) == 0)
|
if (!convertType.HasFlag(PatternType.KeepSingle))
|
||||||
{
|
{
|
||||||
if (HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_FINISH) && TotalColumns != 8)
|
if (HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_FINISH) && TotalColumns != 8)
|
||||||
convertType |= PatternType.Mirror;
|
convertType |= PatternType.Mirror;
|
||||||
@ -107,7 +108,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
|
|
||||||
int lastColumn = PreviousPattern.HitObjects.FirstOrDefault()?.Column ?? 0;
|
int lastColumn = PreviousPattern.HitObjects.FirstOrDefault()?.Column ?? 0;
|
||||||
|
|
||||||
if ((convertType & PatternType.Reverse) > 0 && PreviousPattern.HitObjects.Any())
|
if (convertType.HasFlag(PatternType.Reverse) && PreviousPattern.HitObjects.Any())
|
||||||
{
|
{
|
||||||
// Generate a new pattern by copying the last hit objects in reverse-column order
|
// Generate a new pattern by copying the last hit objects in reverse-column order
|
||||||
for (int i = RandomStart; i < TotalColumns; i++)
|
for (int i = RandomStart; i < TotalColumns; i++)
|
||||||
@ -117,7 +118,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
return pattern;
|
return pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((convertType & PatternType.Cycle) > 0 && PreviousPattern.HitObjects.Count() == 1
|
if (convertType.HasFlag(PatternType.Cycle) && PreviousPattern.HitObjects.Count() == 1
|
||||||
// If we convert to 7K + 1, let's not overload the special key
|
// If we convert to 7K + 1, let's not overload the special key
|
||||||
&& (TotalColumns != 8 || lastColumn != 0)
|
&& (TotalColumns != 8 || lastColumn != 0)
|
||||||
// Make sure the last column was not the centre column
|
// Make sure the last column was not the centre column
|
||||||
@ -130,7 +131,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
return pattern;
|
return pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((convertType & PatternType.ForceStack) > 0 && PreviousPattern.HitObjects.Any())
|
if (convertType.HasFlag(PatternType.ForceStack) && PreviousPattern.HitObjects.Any())
|
||||||
{
|
{
|
||||||
// Generate a new pattern by placing on the already filled columns
|
// Generate a new pattern by placing on the already filled columns
|
||||||
for (int i = RandomStart; i < TotalColumns; i++)
|
for (int i = RandomStart; i < TotalColumns; i++)
|
||||||
@ -142,7 +143,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
|
|
||||||
if (PreviousPattern.HitObjects.Count() == 1)
|
if (PreviousPattern.HitObjects.Count() == 1)
|
||||||
{
|
{
|
||||||
if ((convertType & PatternType.Stair) > 0)
|
if (convertType.HasFlag(PatternType.Stair))
|
||||||
{
|
{
|
||||||
// Generate a new pattern by placing on the next column, cycling back to the start if there is no "next"
|
// Generate a new pattern by placing on the next column, cycling back to the start if there is no "next"
|
||||||
int targetColumn = lastColumn + 1;
|
int targetColumn = lastColumn + 1;
|
||||||
@ -153,7 +154,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
return pattern;
|
return pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((convertType & PatternType.ReverseStair) > 0)
|
if (convertType.HasFlag(PatternType.ReverseStair))
|
||||||
{
|
{
|
||||||
// Generate a new pattern by placing on the previous column, cycling back to the end if there is no "previous"
|
// Generate a new pattern by placing on the previous column, cycling back to the end if there is no "previous"
|
||||||
int targetColumn = lastColumn - 1;
|
int targetColumn = lastColumn - 1;
|
||||||
@ -165,10 +166,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((convertType & PatternType.KeepSingle) > 0)
|
if (convertType.HasFlag(PatternType.KeepSingle))
|
||||||
return pattern = generateRandomNotes(1);
|
return pattern = generateRandomNotes(1);
|
||||||
|
|
||||||
if ((convertType & PatternType.Mirror) > 0)
|
if (convertType.HasFlag(PatternType.Mirror))
|
||||||
{
|
{
|
||||||
if (ConversionDifficulty > 6.5)
|
if (ConversionDifficulty > 6.5)
|
||||||
return pattern = generateRandomPatternWithMirrored(0.12, 0.38, 0.12);
|
return pattern = generateRandomPatternWithMirrored(0.12, 0.38, 0.12);
|
||||||
@ -179,21 +180,21 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
|
|
||||||
if (ConversionDifficulty > 6.5)
|
if (ConversionDifficulty > 6.5)
|
||||||
{
|
{
|
||||||
if ((convertType & PatternType.LowProbability) > 0)
|
if (convertType.HasFlag(PatternType.LowProbability))
|
||||||
return pattern = generateRandomPattern(0.78, 0.42, 0, 0);
|
return pattern = generateRandomPattern(0.78, 0.42, 0, 0);
|
||||||
return pattern = generateRandomPattern(1, 0.62, 0, 0);
|
return pattern = generateRandomPattern(1, 0.62, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ConversionDifficulty > 4)
|
if (ConversionDifficulty > 4)
|
||||||
{
|
{
|
||||||
if ((convertType & PatternType.LowProbability) > 0)
|
if (convertType.HasFlag(PatternType.LowProbability))
|
||||||
return pattern = generateRandomPattern(0.35, 0.08, 0, 0);
|
return pattern = generateRandomPattern(0.35, 0.08, 0, 0);
|
||||||
return pattern = generateRandomPattern(0.52, 0.15, 0, 0);
|
return pattern = generateRandomPattern(0.52, 0.15, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ConversionDifficulty > 2)
|
if (ConversionDifficulty > 2)
|
||||||
{
|
{
|
||||||
if ((convertType & PatternType.LowProbability) > 0)
|
if (convertType.HasFlag(PatternType.LowProbability))
|
||||||
return pattern = generateRandomPattern(0.18, 0, 0, 0);
|
return pattern = generateRandomPattern(0.18, 0, 0, 0);
|
||||||
return pattern = generateRandomPattern(0.45, 0, 0, 0);
|
return pattern = generateRandomPattern(0.45, 0, 0, 0);
|
||||||
}
|
}
|
||||||
@ -204,9 +205,9 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
{
|
{
|
||||||
foreach (var obj in pattern.HitObjects)
|
foreach (var obj in pattern.HitObjects)
|
||||||
{
|
{
|
||||||
if ((convertType & PatternType.Stair) > 0 && obj.Column == TotalColumns - 1)
|
if (convertType.HasFlag(PatternType.Stair) && obj.Column == TotalColumns - 1)
|
||||||
StairType = PatternType.ReverseStair;
|
StairType = PatternType.ReverseStair;
|
||||||
if ((convertType & PatternType.ReverseStair) > 0 && obj.Column == RandomStart)
|
if (convertType.HasFlag(PatternType.ReverseStair) && obj.Column == RandomStart)
|
||||||
StairType = PatternType.Stair;
|
StairType = PatternType.Stair;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -225,7 +226,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
{
|
{
|
||||||
var pattern = new Pattern();
|
var pattern = new Pattern();
|
||||||
|
|
||||||
bool allowStacking = (convertType & PatternType.ForceNotStack) == 0;
|
bool allowStacking = !convertType.HasFlag(PatternType.ForceNotStack);
|
||||||
|
|
||||||
if (!allowStacking)
|
if (!allowStacking)
|
||||||
noteCount = Math.Min(noteCount, TotalColumns - RandomStart - PreviousPattern.ColumnWithObjects);
|
noteCount = Math.Min(noteCount, TotalColumns - RandomStart - PreviousPattern.ColumnWithObjects);
|
||||||
@ -235,7 +236,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
{
|
{
|
||||||
while (pattern.ColumnHasObject(nextColumn) || PreviousPattern.ColumnHasObject(nextColumn) && !allowStacking)
|
while (pattern.ColumnHasObject(nextColumn) || PreviousPattern.ColumnHasObject(nextColumn) && !allowStacking)
|
||||||
{
|
{
|
||||||
if ((convertType & PatternType.Gathered) > 0)
|
if (convertType.HasFlag(PatternType.Gathered))
|
||||||
{
|
{
|
||||||
nextColumn++;
|
nextColumn++;
|
||||||
if (nextColumn == TotalColumns)
|
if (nextColumn == TotalColumns)
|
||||||
@ -367,7 +368,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
{
|
{
|
||||||
addToCentre = false;
|
addToCentre = false;
|
||||||
|
|
||||||
if ((convertType & PatternType.ForceNotStack) > 0)
|
if (convertType.HasFlag(PatternType.ForceNotStack))
|
||||||
return getRandomNoteCount(1 / 2f + p2 / 2, p2, (p2 + p3) / 2, p3);
|
return getRandomNoteCount(1 / 2f + p2 / 2, p2, (p2 + p3) / 2, p3);
|
||||||
|
|
||||||
switch (TotalColumns)
|
switch (TotalColumns)
|
||||||
|
@ -56,10 +56,15 @@ namespace osu.Game.Rulesets.Mania.Replays
|
|||||||
{
|
{
|
||||||
foreach (var point in group)
|
foreach (var point in group)
|
||||||
{
|
{
|
||||||
if (point is HitPoint)
|
switch (point)
|
||||||
actions.Add(columnActions[point.Column]);
|
{
|
||||||
if (point is ReleasePoint)
|
case HitPoint _:
|
||||||
actions.Remove(columnActions[point.Column]);
|
actions.Add(columnActions[point.Column]);
|
||||||
|
break;
|
||||||
|
case ReleasePoint _:
|
||||||
|
actions.Remove(columnActions[point.Column]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Replay.Frames.Add(new ManiaReplayFrame(group.First().Time, actions.ToArray()));
|
Replay.Frames.Add(new ManiaReplayFrame(group.First().Time, actions.ToArray()));
|
||||||
|
@ -32,8 +32,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
|
|
||||||
protected override Container<Drawable> Content => hitObjectArea;
|
protected override Container<Drawable> Content => hitObjectArea;
|
||||||
|
|
||||||
public Column(ScrollingDirection direction)
|
public Column()
|
||||||
: base(direction)
|
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Y;
|
RelativeSizeAxes = Axes.Y;
|
||||||
Width = column_width;
|
Width = column_width;
|
||||||
|
@ -12,7 +12,6 @@ using osu.Game.Rulesets.Judgements;
|
|||||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Mania.Configuration;
|
using osu.Game.Rulesets.Mania.Configuration;
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.UI
|
namespace osu.Game.Rulesets.Mania.UI
|
||||||
{
|
{
|
||||||
@ -21,8 +20,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
public List<Column> Columns => stages.SelectMany(x => x.Columns).ToList();
|
public List<Column> Columns => stages.SelectMany(x => x.Columns).ToList();
|
||||||
private readonly List<ManiaStage> stages = new List<ManiaStage>();
|
private readonly List<ManiaStage> stages = new List<ManiaStage>();
|
||||||
|
|
||||||
public ManiaPlayfield(ScrollingDirection direction, List<StageDefinition> stageDefinitions)
|
public ManiaPlayfield(List<StageDefinition> stageDefinitions)
|
||||||
: base(direction)
|
|
||||||
{
|
{
|
||||||
if (stageDefinitions == null)
|
if (stageDefinitions == null)
|
||||||
throw new ArgumentNullException(nameof(stageDefinitions));
|
throw new ArgumentNullException(nameof(stageDefinitions));
|
||||||
@ -42,7 +40,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
int firstColumnIndex = 0;
|
int firstColumnIndex = 0;
|
||||||
for (int i = 0; i < stageDefinitions.Count; i++)
|
for (int i = 0; i < stageDefinitions.Count; i++)
|
||||||
{
|
{
|
||||||
var newStage = new ManiaStage(direction, firstColumnIndex, stageDefinitions[i], ref normalColumnAction, ref specialColumnAction);
|
var newStage = new ManiaStage(firstColumnIndex, stageDefinitions[i], ref normalColumnAction, ref specialColumnAction);
|
||||||
newStage.VisibleTimeRange.BindTo(VisibleTimeRange);
|
newStage.VisibleTimeRange.BindTo(VisibleTimeRange);
|
||||||
|
|
||||||
playfieldGrid.Content[0][i] = newStage;
|
playfieldGrid.Content[0][i] = newStage;
|
||||||
|
@ -87,7 +87,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
return dependencies;
|
return dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected sealed override Playfield CreatePlayfield() => new ManiaPlayfield(scrollingInfo.Direction, Beatmap.Stages)
|
protected sealed override Playfield CreatePlayfield() => new ManiaPlayfield(Beatmap.Stages)
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
|
@ -11,11 +11,6 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
{
|
{
|
||||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||||
|
|
||||||
public ManiaScrollingPlayfield(ScrollingDirection direction)
|
|
||||||
: base(direction)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(IScrollingInfo scrollingInfo)
|
private void load(IScrollingInfo scrollingInfo)
|
||||||
{
|
{
|
||||||
|
@ -43,8 +43,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
|
|
||||||
private readonly int firstColumnIndex;
|
private readonly int firstColumnIndex;
|
||||||
|
|
||||||
public ManiaStage(ScrollingDirection direction, int firstColumnIndex, StageDefinition definition, ref ManiaAction normalColumnStartAction, ref ManiaAction specialColumnStartAction)
|
public ManiaStage(int firstColumnIndex, StageDefinition definition, ref ManiaAction normalColumnStartAction, ref ManiaAction specialColumnStartAction)
|
||||||
: base(direction)
|
|
||||||
{
|
{
|
||||||
this.firstColumnIndex = firstColumnIndex;
|
this.firstColumnIndex = firstColumnIndex;
|
||||||
|
|
||||||
@ -124,7 +123,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
for (int i = 0; i < definition.Columns; i++)
|
for (int i = 0; i < definition.Columns; i++)
|
||||||
{
|
{
|
||||||
var isSpecial = definition.IsSpecialColumn(i);
|
var isSpecial = definition.IsSpecialColumn(i);
|
||||||
var column = new Column(direction)
|
var column = new Column
|
||||||
{
|
{
|
||||||
IsSpecial = isSpecial,
|
IsSpecial = isSpecial,
|
||||||
Action = { Value = isSpecial ? specialColumnStartAction++ : normalColumnStartAction++ }
|
Action = { Value = isSpecial ? specialColumnStartAction++ : normalColumnStartAction++ }
|
||||||
|
@ -285,44 +285,45 @@ namespace osu.Game.Rulesets.Osu.Replays
|
|||||||
|
|
||||||
AddFrameToReplay(startFrame);
|
AddFrameToReplay(startFrame);
|
||||||
|
|
||||||
// We add intermediate frames for spinning / following a slider here.
|
switch (h)
|
||||||
if (h is Spinner)
|
|
||||||
{
|
{
|
||||||
Spinner s = h as Spinner;
|
// We add intermediate frames for spinning / following a slider here.
|
||||||
|
case Spinner spinner:
|
||||||
Vector2 difference = startPosition - SPINNER_CENTRE;
|
|
||||||
|
|
||||||
float radius = difference.Length;
|
|
||||||
float angle = radius == 0 ? 0 : (float)Math.Atan2(difference.Y, difference.X);
|
|
||||||
|
|
||||||
double t;
|
|
||||||
|
|
||||||
for (double j = h.StartTime + FrameDelay; j < s.EndTime; j += FrameDelay)
|
|
||||||
{
|
{
|
||||||
t = ApplyModsToTime(j - h.StartTime) * spinnerDirection;
|
Vector2 difference = startPosition - SPINNER_CENTRE;
|
||||||
|
|
||||||
Vector2 pos = SPINNER_CENTRE + CirclePosition(t / 20 + angle, SPIN_RADIUS);
|
float radius = difference.Length;
|
||||||
AddFrameToReplay(new OsuReplayFrame((int)j, new Vector2(pos.X, pos.Y), action));
|
float angle = radius == 0 ? 0 : (float)Math.Atan2(difference.Y, difference.X);
|
||||||
|
|
||||||
|
double t;
|
||||||
|
|
||||||
|
for (double j = h.StartTime + FrameDelay; j < spinner.EndTime; j += FrameDelay)
|
||||||
|
{
|
||||||
|
t = ApplyModsToTime(j - h.StartTime) * spinnerDirection;
|
||||||
|
|
||||||
|
Vector2 pos = SPINNER_CENTRE + CirclePosition(t / 20 + angle, SPIN_RADIUS);
|
||||||
|
AddFrameToReplay(new OsuReplayFrame((int)j, new Vector2(pos.X, pos.Y), action));
|
||||||
|
}
|
||||||
|
|
||||||
|
t = ApplyModsToTime(spinner.EndTime - h.StartTime) * spinnerDirection;
|
||||||
|
Vector2 endPosition = SPINNER_CENTRE + CirclePosition(t / 20 + angle, SPIN_RADIUS);
|
||||||
|
|
||||||
|
AddFrameToReplay(new OsuReplayFrame(spinner.EndTime, new Vector2(endPosition.X, endPosition.Y), action));
|
||||||
|
|
||||||
|
endFrame.Position = endPosition;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
case Slider slider:
|
||||||
t = ApplyModsToTime(s.EndTime - h.StartTime) * spinnerDirection;
|
|
||||||
Vector2 endPosition = SPINNER_CENTRE + CirclePosition(t / 20 + angle, SPIN_RADIUS);
|
|
||||||
|
|
||||||
AddFrameToReplay(new OsuReplayFrame(s.EndTime, new Vector2(endPosition.X, endPosition.Y), action));
|
|
||||||
|
|
||||||
endFrame.Position = endPosition;
|
|
||||||
}
|
|
||||||
else if (h is Slider)
|
|
||||||
{
|
|
||||||
Slider s = h as Slider;
|
|
||||||
|
|
||||||
for (double j = FrameDelay; j < s.Duration; j += FrameDelay)
|
|
||||||
{
|
{
|
||||||
Vector2 pos = s.StackedPositionAt(j / s.Duration);
|
for (double j = FrameDelay; j < slider.Duration; j += FrameDelay)
|
||||||
AddFrameToReplay(new OsuReplayFrame(h.StartTime + j, new Vector2(pos.X, pos.Y), action));
|
{
|
||||||
}
|
Vector2 pos = slider.StackedPositionAt(j / slider.Duration);
|
||||||
|
AddFrameToReplay(new OsuReplayFrame(h.StartTime + j, new Vector2(pos.X, pos.Y), action));
|
||||||
|
}
|
||||||
|
|
||||||
AddFrameToReplay(new OsuReplayFrame(s.EndTime, new Vector2(s.StackedEndPosition.X, s.StackedEndPosition.Y), action));
|
AddFrameToReplay(new OsuReplayFrame(slider.EndTime, new Vector2(slider.StackedEndPosition.X, slider.StackedEndPosition.Y), action));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We only want to let go of our button if we are at the end of the current replay. Otherwise something is still going on after us so we need to keep the button pressed!
|
// We only want to let go of our button if we are at the end of the current replay. Otherwise something is still going on after us so we need to keep the button pressed!
|
||||||
|
@ -39,6 +39,11 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
|||||||
|
|
||||||
private int downCount;
|
private int downCount;
|
||||||
|
|
||||||
|
private const float pressed_scale = 1.2f;
|
||||||
|
private const float released_scale = 1f;
|
||||||
|
|
||||||
|
private float targetScale => downCount > 0 ? pressed_scale : released_scale;
|
||||||
|
|
||||||
public bool OnPressed(OsuAction action)
|
public bool OnPressed(OsuAction action)
|
||||||
{
|
{
|
||||||
switch (action)
|
switch (action)
|
||||||
@ -46,7 +51,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
|||||||
case OsuAction.LeftButton:
|
case OsuAction.LeftButton:
|
||||||
case OsuAction.RightButton:
|
case OsuAction.RightButton:
|
||||||
downCount++;
|
downCount++;
|
||||||
ActiveCursor.ScaleTo(1).ScaleTo(1.2f, 100, Easing.OutQuad);
|
ActiveCursor.ScaleTo(released_scale).ScaleTo(targetScale, 100, Easing.OutQuad);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +65,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
|||||||
case OsuAction.LeftButton:
|
case OsuAction.LeftButton:
|
||||||
case OsuAction.RightButton:
|
case OsuAction.RightButton:
|
||||||
if (--downCount == 0)
|
if (--downCount == 0)
|
||||||
ActiveCursor.ScaleTo(1, 200, Easing.OutQuad);
|
ActiveCursor.ScaleTo(targetScale, 200, Easing.OutQuad);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,13 +77,13 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
|||||||
protected override void PopIn()
|
protected override void PopIn()
|
||||||
{
|
{
|
||||||
fadeContainer.FadeTo(1, 300, Easing.OutQuint);
|
fadeContainer.FadeTo(1, 300, Easing.OutQuint);
|
||||||
ActiveCursor.ScaleTo(1, 400, Easing.OutQuint);
|
ActiveCursor.ScaleTo(targetScale, 400, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PopOut()
|
protected override void PopOut()
|
||||||
{
|
{
|
||||||
fadeContainer.FadeTo(0.05f, 450, Easing.OutQuint);
|
fadeContainer.FadeTo(0.05f, 450, Easing.OutQuint);
|
||||||
ActiveCursor.ScaleTo(0.8f, 450, Easing.OutQuint);
|
ActiveCursor.ScaleTo(targetScale * 0.8f, 450, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class OsuCursor : Container
|
public class OsuCursor : Container
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
using osu.Framework.Graphics.Cursor;
|
using osu.Framework.Graphics.Cursor;
|
||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
@ -33,19 +34,30 @@ namespace osu.Game.Rulesets.Osu.UI
|
|||||||
|
|
||||||
protected override DrawableHitObject<OsuHitObject> GetVisualRepresentation(OsuHitObject h)
|
protected override DrawableHitObject<OsuHitObject> GetVisualRepresentation(OsuHitObject h)
|
||||||
{
|
{
|
||||||
if (h is HitCircle circle)
|
switch (h)
|
||||||
return new DrawableHitCircle(circle);
|
{
|
||||||
|
case HitCircle circle:
|
||||||
|
return new DrawableHitCircle(circle);
|
||||||
|
case Slider slider:
|
||||||
|
return new DrawableSlider(slider);
|
||||||
|
case Spinner spinner:
|
||||||
|
return new DrawableSpinner(spinner);
|
||||||
|
}
|
||||||
|
|
||||||
if (h is Slider slider)
|
|
||||||
return new DrawableSlider(slider);
|
|
||||||
|
|
||||||
if (h is Spinner spinner)
|
|
||||||
return new DrawableSpinner(spinner);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new OsuReplayInputHandler(replay);
|
protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new OsuReplayInputHandler(replay);
|
||||||
|
|
||||||
|
public override double GameplayStartTime
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var first = (OsuHitObject)Objects.First();
|
||||||
|
return first.StartTime - first.TimePreempt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected override Vector2 GetAspectAdjustedSize()
|
protected override Vector2 GetAspectAdjustedSize()
|
||||||
{
|
{
|
||||||
var aspectSize = DrawSize.X * 0.75f < DrawSize.Y ? new Vector2(DrawSize.X, DrawSize.X * 0.75f) : new Vector2(DrawSize.Y * 4f / 3f, DrawSize.Y);
|
var aspectSize = DrawSize.X * 0.75f < DrawSize.Y ? new Vector2(DrawSize.X, DrawSize.X * 0.75f) : new Vector2(DrawSize.Y * 4f / 3f, DrawSize.Y);
|
||||||
|
@ -80,30 +80,31 @@ namespace osu.Game.Rulesets.Taiko.Scoring
|
|||||||
|
|
||||||
foreach (var obj in beatmap.HitObjects)
|
foreach (var obj in beatmap.HitObjects)
|
||||||
{
|
{
|
||||||
if (obj is Hit)
|
switch (obj)
|
||||||
{
|
{
|
||||||
AddJudgement(new TaikoJudgement { Result = HitResult.Great });
|
case Hit _:
|
||||||
if (obj.IsStrong)
|
AddJudgement(new TaikoJudgement { Result = HitResult.Great });
|
||||||
AddJudgement(new TaikoStrongHitJudgement());
|
if (obj.IsStrong)
|
||||||
}
|
AddJudgement(new TaikoStrongHitJudgement());
|
||||||
else if (obj is DrumRoll)
|
break;
|
||||||
{
|
case DrumRoll drumRoll:
|
||||||
for (int i = 0; i < ((DrumRoll)obj).NestedHitObjects.OfType<DrumRollTick>().Count(); i++)
|
var count = drumRoll.NestedHitObjects.OfType<DrumRollTick>().Count();
|
||||||
{
|
for (int i = 0; i < count; i++)
|
||||||
AddJudgement(new TaikoDrumRollTickJudgement { Result = HitResult.Great });
|
{
|
||||||
|
AddJudgement(new TaikoDrumRollTickJudgement { Result = HitResult.Great });
|
||||||
|
|
||||||
|
if (obj.IsStrong)
|
||||||
|
AddJudgement(new TaikoStrongHitJudgement());
|
||||||
|
}
|
||||||
|
|
||||||
|
AddJudgement(new TaikoJudgement { Result = HitResult.Great });
|
||||||
|
|
||||||
if (obj.IsStrong)
|
if (obj.IsStrong)
|
||||||
AddJudgement(new TaikoStrongHitJudgement());
|
AddJudgement(new TaikoStrongHitJudgement());
|
||||||
}
|
break;
|
||||||
|
case Swell _:
|
||||||
AddJudgement(new TaikoJudgement { Result = HitResult.Great });
|
AddJudgement(new TaikoJudgement { Result = HitResult.Great });
|
||||||
|
break;
|
||||||
if (obj.IsStrong)
|
|
||||||
AddJudgement(new TaikoStrongHitJudgement());
|
|
||||||
}
|
|
||||||
else if (obj is Swell)
|
|
||||||
{
|
|
||||||
AddJudgement(new TaikoJudgement { Result = HitResult.Great });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,8 +58,9 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
private readonly Box background;
|
private readonly Box background;
|
||||||
|
|
||||||
public TaikoPlayfield(ControlPointInfo controlPoints)
|
public TaikoPlayfield(ControlPointInfo controlPoints)
|
||||||
: base(ScrollingDirection.Left)
|
|
||||||
{
|
{
|
||||||
|
Direction.Value = ScrollingDirection.Left;
|
||||||
|
|
||||||
AddRangeInternal(new Drawable[]
|
AddRangeInternal(new Drawable[]
|
||||||
{
|
{
|
||||||
backgroundContainer = new Container
|
backgroundContainer = new Container
|
||||||
@ -212,13 +213,15 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
|
|
||||||
base.Add(h);
|
base.Add(h);
|
||||||
|
|
||||||
var barline = h as DrawableBarLine;
|
switch (h)
|
||||||
if (barline != null)
|
{
|
||||||
barlineContainer.Add(barline.CreateProxy());
|
case DrawableBarLine barline:
|
||||||
|
barlineContainer.Add(barline.CreateProxy());
|
||||||
var taikoObject = h as DrawableTaikoHitObject;
|
break;
|
||||||
if (taikoObject != null)
|
case DrawableTaikoHitObject taikoObject:
|
||||||
topLevelHitContainer.Add(taikoObject.CreateProxiedContent());
|
topLevelHitContainer.Add(taikoObject.CreateProxiedContent());
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
||||||
|
@ -98,32 +98,22 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
|
|
||||||
protected override DrawableHitObject<TaikoHitObject> GetVisualRepresentation(TaikoHitObject h)
|
protected override DrawableHitObject<TaikoHitObject> GetVisualRepresentation(TaikoHitObject h)
|
||||||
{
|
{
|
||||||
var centreHit = h as CentreHit;
|
switch (h)
|
||||||
if (centreHit != null)
|
|
||||||
{
|
{
|
||||||
if (h.IsStrong)
|
case CentreHit centreHit when h.IsStrong:
|
||||||
return new DrawableCentreHitStrong(centreHit);
|
return new DrawableCentreHitStrong(centreHit);
|
||||||
return new DrawableCentreHit(centreHit);
|
case CentreHit centreHit:
|
||||||
}
|
return new DrawableCentreHit(centreHit);
|
||||||
|
case RimHit rimHit when h.IsStrong:
|
||||||
var rimHit = h as RimHit;
|
|
||||||
if (rimHit != null)
|
|
||||||
{
|
|
||||||
if (h.IsStrong)
|
|
||||||
return new DrawableRimHitStrong(rimHit);
|
return new DrawableRimHitStrong(rimHit);
|
||||||
return new DrawableRimHit(rimHit);
|
case RimHit rimHit:
|
||||||
|
return new DrawableRimHit(rimHit);
|
||||||
|
case DrumRoll drumRoll:
|
||||||
|
return new DrawableDrumRoll(drumRoll);
|
||||||
|
case Swell swell:
|
||||||
|
return new DrawableSwell(swell);
|
||||||
}
|
}
|
||||||
|
|
||||||
var drumRoll = h as DrumRoll;
|
|
||||||
if (drumRoll != null)
|
|
||||||
{
|
|
||||||
return new DrawableDrumRoll(drumRoll);
|
|
||||||
}
|
|
||||||
|
|
||||||
var swell = h as Swell;
|
|
||||||
if (swell != null)
|
|
||||||
return new DrawableSwell(swell);
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,11 +25,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
Children = new[]
|
Children = new[]
|
||||||
{
|
{
|
||||||
new NamedIconButton("No change", new IconButton()),
|
new NamedIconButton("No change", new IconButton()),
|
||||||
new NamedIconButton("Background colours", new IconButton
|
new NamedIconButton("Background colours", new ColouredIconButton()),
|
||||||
{
|
|
||||||
FlashColour = Color4.DarkGreen,
|
|
||||||
HoverColour = Color4.Green,
|
|
||||||
}),
|
|
||||||
new NamedIconButton("Full-width", new IconButton { ButtonSize = new Vector2(200, 30) }),
|
new NamedIconButton("Full-width", new IconButton { ButtonSize = new Vector2(200, 30) }),
|
||||||
new NamedIconButton("Unchanging size", new IconButton(), false),
|
new NamedIconButton("Unchanging size", new IconButton(), false),
|
||||||
new NamedIconButton("Icon colours", new IconButton
|
new NamedIconButton("Icon colours", new IconButton
|
||||||
@ -41,6 +37,15 @@ namespace osu.Game.Tests.Visual
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class ColouredIconButton : IconButton
|
||||||
|
{
|
||||||
|
public ColouredIconButton()
|
||||||
|
{
|
||||||
|
FlashColour = Color4.DarkGreen;
|
||||||
|
HoverColour = Color4.Green;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class NamedIconButton : Container
|
private class NamedIconButton : Container
|
||||||
{
|
{
|
||||||
public NamedIconButton(string name, IconButton button, bool allowSizeChange = true)
|
public NamedIconButton(string name, IconButton button, bool allowSizeChange = true)
|
||||||
|
@ -18,7 +18,6 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
IsCounting = true,
|
|
||||||
Children = new KeyCounter[]
|
Children = new KeyCounter[]
|
||||||
{
|
{
|
||||||
new KeyCounterKeyboard(Key.Z),
|
new KeyCounterKeyboard(Key.Z),
|
||||||
|
@ -16,7 +16,6 @@ using osu.Game.Rulesets;
|
|||||||
using osu.Game.Screens.Select;
|
using osu.Game.Screens.Select;
|
||||||
using osu.Game.Screens.Select.Carousel;
|
using osu.Game.Screens.Select.Carousel;
|
||||||
using osu.Game.Screens.Select.Filter;
|
using osu.Game.Screens.Select.Filter;
|
||||||
using osu.Game.Tests.Platform;
|
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual
|
namespace osu.Game.Tests.Visual
|
||||||
{
|
{
|
||||||
@ -28,6 +27,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
private RulesetStore rulesets;
|
private RulesetStore rulesets;
|
||||||
|
|
||||||
private WorkingBeatmap defaultBeatmap;
|
private WorkingBeatmap defaultBeatmap;
|
||||||
|
private DatabaseContextFactory factory;
|
||||||
|
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
{
|
{
|
||||||
@ -59,13 +59,14 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
TestSongSelect songSelect = null;
|
TestSongSelect songSelect = null;
|
||||||
|
|
||||||
var storage = new TestStorage(@"TestCasePlaySongSelect");
|
factory = new DatabaseContextFactory(LocalStorage);
|
||||||
|
factory.ResetDatabase();
|
||||||
|
|
||||||
// this is by no means clean. should be replacing inside of OsuGameBase somehow.
|
using (var usage = factory.Get())
|
||||||
IDatabaseContextFactory factory = new SingletonContextFactory(new OsuDbContext());
|
usage.Migrate();
|
||||||
|
|
||||||
Dependencies.Cache(rulesets = new RulesetStore(factory));
|
Dependencies.Cache(rulesets = new RulesetStore(factory));
|
||||||
Dependencies.Cache(manager = new BeatmapManager(storage, factory, rulesets, null, null)
|
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, null)
|
||||||
{
|
{
|
||||||
DefaultBeatmap = defaultBeatmap = Beatmap.Default
|
DefaultBeatmap = defaultBeatmap = Beatmap.Default
|
||||||
});
|
});
|
||||||
|
@ -117,7 +117,6 @@ namespace osu.Game.Tests.Visual
|
|||||||
public new readonly ScrollingDirection Direction;
|
public new readonly ScrollingDirection Direction;
|
||||||
|
|
||||||
public TestPlayfield(ScrollingDirection direction)
|
public TestPlayfield(ScrollingDirection direction)
|
||||||
: base(direction)
|
|
||||||
{
|
{
|
||||||
Direction = direction;
|
Direction = direction;
|
||||||
|
|
||||||
|
@ -45,6 +45,16 @@ namespace osu.Game.Beatmaps
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<DownloadBeatmapSetRequest> BeatmapDownloadBegan;
|
public event Action<DownloadBeatmapSetRequest> BeatmapDownloadBegan;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fired when a beatmap download is interrupted, due to user cancellation or other failures.
|
||||||
|
/// </summary>
|
||||||
|
public event Action<DownloadBeatmapSetRequest> BeatmapDownloadFailed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fired when a beatmap load is requested (into the interactive game UI).
|
||||||
|
/// </summary>
|
||||||
|
public Action<BeatmapSetInfo> PresentBeatmap;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A default representation of a WorkingBeatmap to use when no beatmap is available.
|
/// A default representation of a WorkingBeatmap to use when no beatmap is available.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -79,33 +89,46 @@ namespace osu.Game.Beatmaps
|
|||||||
this.audioManager = audioManager;
|
this.audioManager = audioManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Populate(BeatmapSetInfo model, ArchiveReader archive)
|
protected override void Populate(BeatmapSetInfo beatmapSet, ArchiveReader archive)
|
||||||
{
|
{
|
||||||
model.Beatmaps = createBeatmapDifficulties(archive);
|
if (archive != null)
|
||||||
|
beatmapSet.Beatmaps = createBeatmapDifficulties(archive);
|
||||||
|
|
||||||
foreach (BeatmapInfo b in model.Beatmaps)
|
foreach (BeatmapInfo b in beatmapSet.Beatmaps)
|
||||||
{
|
{
|
||||||
// remove metadata from difficulties where it matches the set
|
// remove metadata from difficulties where it matches the set
|
||||||
if (model.Metadata.Equals(b.Metadata))
|
if (beatmapSet.Metadata.Equals(b.Metadata))
|
||||||
b.Metadata = null;
|
b.Metadata = null;
|
||||||
|
|
||||||
// by setting the model here, we can update the noline set id below.
|
b.BeatmapSet = beatmapSet;
|
||||||
b.BeatmapSet = model;
|
|
||||||
|
|
||||||
fetchAndPopulateOnlineIDs(b, model.Beatmaps);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if a set already exists with the same online id, delete if it does.
|
// check if a set already exists with the same online id, delete if it does.
|
||||||
if (model.OnlineBeatmapSetID != null)
|
if (beatmapSet.OnlineBeatmapSetID != null)
|
||||||
{
|
{
|
||||||
var existingOnlineId = beatmaps.ConsumableItems.FirstOrDefault(b => b.OnlineBeatmapSetID == model.OnlineBeatmapSetID);
|
var existingOnlineId = beatmaps.ConsumableItems.FirstOrDefault(b => b.OnlineBeatmapSetID == beatmapSet.OnlineBeatmapSetID);
|
||||||
if (existingOnlineId != null)
|
if (existingOnlineId != null)
|
||||||
{
|
{
|
||||||
Delete(existingOnlineId);
|
Delete(existingOnlineId);
|
||||||
beatmaps.PurgeDeletable(s => s.ID == existingOnlineId.ID);
|
beatmaps.PurgeDeletable(s => s.ID == existingOnlineId.ID);
|
||||||
Logger.Log($"Found existing beatmap set with same OnlineBeatmapSetID ({model.OnlineBeatmapSetID}). It has been purged.", LoggingTarget.Database);
|
Logger.Log($"Found existing beatmap set with same OnlineBeatmapSetID ({beatmapSet.OnlineBeatmapSetID}). It has been purged.", LoggingTarget.Database);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
validateOnlineIds(beatmapSet.Beatmaps);
|
||||||
|
|
||||||
|
foreach (BeatmapInfo b in beatmapSet.Beatmaps)
|
||||||
|
fetchAndPopulateOnlineIDs(b, beatmapSet.Beatmaps);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateOnlineIds(List<BeatmapInfo> beatmaps)
|
||||||
|
{
|
||||||
|
var beatmapIds = beatmaps.Where(b => b.OnlineBeatmapID.HasValue).Select(b => b.OnlineBeatmapID).ToList();
|
||||||
|
|
||||||
|
// ensure all IDs are unique in this set and none match existing IDs in the local beatmap store.
|
||||||
|
if (beatmapIds.GroupBy(b => b).Any(g => g.Count() > 1) || QueryBeatmaps(b => beatmapIds.Contains(b.OnlineBeatmapID)).Any())
|
||||||
|
// remove all online IDs if any problems were found.
|
||||||
|
beatmaps.ForEach(b => b.OnlineBeatmapID = null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override BeatmapSetInfo CheckForExisting(BeatmapSetInfo model)
|
protected override BeatmapSetInfo CheckForExisting(BeatmapSetInfo model)
|
||||||
@ -143,7 +166,7 @@ namespace osu.Game.Beatmaps
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var downloadNotification = new ProgressNotification
|
var downloadNotification = new DownloadNotification
|
||||||
{
|
{
|
||||||
CompletionText = $"Imported {beatmapSetInfo.Metadata.Artist} - {beatmapSetInfo.Metadata.Title}!",
|
CompletionText = $"Imported {beatmapSetInfo.Metadata.Artist} - {beatmapSetInfo.Metadata.Title}!",
|
||||||
Text = $"Downloading {beatmapSetInfo.Metadata.Artist} - {beatmapSetInfo.Metadata.Title}",
|
Text = $"Downloading {beatmapSetInfo.Metadata.Artist} - {beatmapSetInfo.Metadata.Title}",
|
||||||
@ -163,18 +186,28 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
Task.Factory.StartNew(() =>
|
Task.Factory.StartNew(() =>
|
||||||
{
|
{
|
||||||
|
BeatmapSetInfo importedBeatmap;
|
||||||
|
|
||||||
// This gets scheduled back to the update thread, but we want the import to run in the background.
|
// This gets scheduled back to the update thread, but we want the import to run in the background.
|
||||||
using (var stream = new MemoryStream(data))
|
using (var stream = new MemoryStream(data))
|
||||||
using (var archive = new ZipArchiveReader(stream, beatmapSetInfo.ToString()))
|
using (var archive = new ZipArchiveReader(stream, beatmapSetInfo.ToString()))
|
||||||
Import(archive);
|
importedBeatmap = Import(archive);
|
||||||
|
|
||||||
|
downloadNotification.CompletionClickAction = () =>
|
||||||
|
{
|
||||||
|
PresentBeatmap?.Invoke(importedBeatmap);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
downloadNotification.State = ProgressNotificationState.Completed;
|
downloadNotification.State = ProgressNotificationState.Completed;
|
||||||
|
|
||||||
currentDownloads.Remove(request);
|
currentDownloads.Remove(request);
|
||||||
}, TaskCreationOptions.LongRunning);
|
}, TaskCreationOptions.LongRunning);
|
||||||
};
|
};
|
||||||
|
|
||||||
request.Failure += error =>
|
request.Failure += error =>
|
||||||
{
|
{
|
||||||
|
BeatmapDownloadFailed?.Invoke(request);
|
||||||
|
|
||||||
if (error is OperationCanceledException) return;
|
if (error is OperationCanceledException) return;
|
||||||
|
|
||||||
downloadNotification.State = ProgressNotificationState.Cancelled;
|
downloadNotification.State = ProgressNotificationState.Cancelled;
|
||||||
@ -276,7 +309,7 @@ namespace osu.Game.Beatmaps
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="query">The query.</param>
|
/// <param name="query">The query.</param>
|
||||||
/// <returns>Results from the provided query.</returns>
|
/// <returns>Results from the provided query.</returns>
|
||||||
public IEnumerable<BeatmapInfo> QueryBeatmaps(Expression<Func<BeatmapInfo, bool>> query) => beatmaps.Beatmaps.AsNoTracking().Where(query);
|
public IQueryable<BeatmapInfo> QueryBeatmaps(Expression<Func<BeatmapInfo, bool>> query) => beatmaps.Beatmaps.AsNoTracking().Where(query);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Denotes whether an osu-stable installation is present to perform automated imports from.
|
/// Denotes whether an osu-stable installation is present to perform automated imports from.
|
||||||
@ -339,8 +372,6 @@ namespace osu.Game.Beatmaps
|
|||||||
{
|
{
|
||||||
var beatmapInfos = new List<BeatmapInfo>();
|
var beatmapInfos = new List<BeatmapInfo>();
|
||||||
|
|
||||||
bool invalidateOnlineIDs = false;
|
|
||||||
|
|
||||||
foreach (var name in reader.Filenames.Where(f => f.EndsWith(".osu")))
|
foreach (var name in reader.Filenames.Where(f => f.EndsWith(".osu")))
|
||||||
{
|
{
|
||||||
using (var raw = reader.GetStream(name))
|
using (var raw = reader.GetStream(name))
|
||||||
@ -357,38 +388,15 @@ namespace osu.Game.Beatmaps
|
|||||||
beatmap.BeatmapInfo.Hash = ms.ComputeSHA2Hash();
|
beatmap.BeatmapInfo.Hash = ms.ComputeSHA2Hash();
|
||||||
beatmap.BeatmapInfo.MD5Hash = ms.ComputeMD5Hash();
|
beatmap.BeatmapInfo.MD5Hash = ms.ComputeMD5Hash();
|
||||||
|
|
||||||
if (beatmap.BeatmapInfo.OnlineBeatmapID.HasValue)
|
var ruleset = rulesets.GetRuleset(beatmap.BeatmapInfo.RulesetID);
|
||||||
{
|
|
||||||
var ourId = beatmap.BeatmapInfo.OnlineBeatmapID;
|
|
||||||
|
|
||||||
// check that no existing beatmap in database exists that is imported with the same online beatmap ID. if so, give it precedence.
|
|
||||||
if (QueryBeatmap(b => b.OnlineBeatmapID.Value == ourId) != null)
|
|
||||||
beatmap.BeatmapInfo.OnlineBeatmapID = null;
|
|
||||||
|
|
||||||
// check that no other beatmap in this imported set has a conflicting online beatmap ID. If so, presume *all* are incorrect.
|
|
||||||
if (beatmapInfos.Any(b => b.OnlineBeatmapID == ourId))
|
|
||||||
invalidateOnlineIDs = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
RulesetInfo ruleset = rulesets.GetRuleset(beatmap.BeatmapInfo.RulesetID);
|
|
||||||
|
|
||||||
beatmap.BeatmapInfo.Ruleset = ruleset;
|
beatmap.BeatmapInfo.Ruleset = ruleset;
|
||||||
|
// TODO: this should be done in a better place once we actually need to dynamically update it.
|
||||||
if (ruleset != null)
|
beatmap.BeatmapInfo.StarDifficulty = ruleset?.CreateInstance().CreateDifficultyCalculator(new DummyConversionBeatmap(beatmap)).Calculate().StarRating ?? 0;
|
||||||
{
|
|
||||||
// TODO: this should be done in a better place once we actually need to dynamically update it.
|
|
||||||
beatmap.BeatmapInfo.StarDifficulty = ruleset.CreateInstance().CreateDifficultyCalculator(new DummyConversionBeatmap(beatmap)).Calculate().StarRating;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
beatmap.BeatmapInfo.StarDifficulty = 0;
|
|
||||||
|
|
||||||
beatmapInfos.Add(beatmap.BeatmapInfo);
|
beatmapInfos.Add(beatmap.BeatmapInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (invalidateOnlineIDs)
|
|
||||||
beatmapInfos.ForEach(b => b.OnlineBeatmapID = null);
|
|
||||||
|
|
||||||
return beatmapInfos;
|
return beatmapInfos;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -401,12 +409,12 @@ namespace osu.Game.Beatmaps
|
|||||||
/// <returns>True if population was successful.</returns>
|
/// <returns>True if population was successful.</returns>
|
||||||
private bool fetchAndPopulateOnlineIDs(BeatmapInfo beatmap, IEnumerable<BeatmapInfo> otherBeatmaps, bool force = false)
|
private bool fetchAndPopulateOnlineIDs(BeatmapInfo beatmap, IEnumerable<BeatmapInfo> otherBeatmaps, bool force = false)
|
||||||
{
|
{
|
||||||
|
if (api?.State != APIState.Online)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!force && beatmap.OnlineBeatmapID != null && beatmap.BeatmapSet.OnlineBeatmapSetID != null)
|
if (!force && beatmap.OnlineBeatmapID != null && beatmap.BeatmapSet.OnlineBeatmapSetID != null)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (api.State != APIState.Online)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Logger.Log("Attempting online lookup for IDs...", LoggingTarget.Database);
|
Logger.Log("Attempting online lookup for IDs...", LoggingTarget.Database);
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -453,5 +461,21 @@ namespace osu.Game.Beatmaps
|
|||||||
protected override Texture GetBackground() => null;
|
protected override Texture GetBackground() => null;
|
||||||
protected override Track GetTrack() => null;
|
protected override Track GetTrack() => null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class DownloadNotification : ProgressNotification
|
||||||
|
{
|
||||||
|
public override bool IsImportant => false;
|
||||||
|
|
||||||
|
protected override Notification CreateCompletionNotification() => new SilencedProgressCompletionNotification
|
||||||
|
{
|
||||||
|
Activated = CompletionClickAction,
|
||||||
|
Text = CompletionText
|
||||||
|
};
|
||||||
|
|
||||||
|
private class SilencedProgressCompletionNotification : ProgressCompletionNotification
|
||||||
|
{
|
||||||
|
public override bool IsImportant => false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ using System.Linq;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Configuration;
|
using osu.Framework.Configuration;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Online.API.Requests;
|
||||||
|
|
||||||
namespace osu.Game.Beatmaps.Drawables
|
namespace osu.Game.Beatmaps.Drawables
|
||||||
{
|
{
|
||||||
@ -19,9 +20,9 @@ namespace osu.Game.Beatmaps.Drawables
|
|||||||
private BeatmapManager beatmaps;
|
private BeatmapManager beatmaps;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the associated beatmap set has been downloading (by this instance or any other instance).
|
/// Holds the current download state of the beatmap, whether is has already been downloaded, is in progress, or is not downloaded.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly BindableBool Downloaded = new BindableBool();
|
public readonly Bindable<DownloadStatus> DownloadState = new Bindable<DownloadStatus>();
|
||||||
|
|
||||||
public BeatmapSetDownloader(BeatmapSetInfo set, bool noVideo = false)
|
public BeatmapSetDownloader(BeatmapSetInfo set, bool noVideo = false)
|
||||||
{
|
{
|
||||||
@ -36,10 +37,16 @@ namespace osu.Game.Beatmaps.Drawables
|
|||||||
|
|
||||||
beatmaps.ItemAdded += setAdded;
|
beatmaps.ItemAdded += setAdded;
|
||||||
beatmaps.ItemRemoved += setRemoved;
|
beatmaps.ItemRemoved += setRemoved;
|
||||||
|
beatmaps.BeatmapDownloadBegan += downloadBegan;
|
||||||
|
beatmaps.BeatmapDownloadFailed += downloadFailed;
|
||||||
|
|
||||||
// initial value
|
// initial value
|
||||||
if (set.OnlineBeatmapSetID != null)
|
if (set.OnlineBeatmapSetID != null && beatmaps.QueryBeatmapSets(s => s.OnlineBeatmapSetID == set.OnlineBeatmapSetID && !s.DeletePending).Any())
|
||||||
Downloaded.Value = beatmaps.QueryBeatmapSets(s => s.OnlineBeatmapSetID == set.OnlineBeatmapSetID && !s.DeletePending).Any();
|
DownloadState.Value = DownloadStatus.Downloaded;
|
||||||
|
else if (beatmaps.GetExistingDownload(set) != null)
|
||||||
|
DownloadState.Value = DownloadStatus.Downloading;
|
||||||
|
else
|
||||||
|
DownloadState.Value = DownloadStatus.NotDownloaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
@ -50,6 +57,8 @@ namespace osu.Game.Beatmaps.Drawables
|
|||||||
{
|
{
|
||||||
beatmaps.ItemAdded -= setAdded;
|
beatmaps.ItemAdded -= setAdded;
|
||||||
beatmaps.ItemRemoved -= setRemoved;
|
beatmaps.ItemRemoved -= setRemoved;
|
||||||
|
beatmaps.BeatmapDownloadBegan -= downloadBegan;
|
||||||
|
beatmaps.BeatmapDownloadFailed -= downloadFailed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,28 +66,45 @@ namespace osu.Game.Beatmaps.Drawables
|
|||||||
/// Begin downloading the associated beatmap set.
|
/// Begin downloading the associated beatmap set.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>True if downloading began. False if an existing download is active or completed.</returns>
|
/// <returns>True if downloading began. False if an existing download is active or completed.</returns>
|
||||||
public bool Download()
|
public void Download()
|
||||||
{
|
{
|
||||||
if (Downloaded.Value)
|
if (DownloadState.Value > DownloadStatus.NotDownloaded)
|
||||||
return false;
|
return;
|
||||||
|
|
||||||
if (beatmaps.GetExistingDownload(set) != null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
beatmaps.Download(set, noVideo);
|
beatmaps.Download(set, noVideo);
|
||||||
return true;
|
|
||||||
|
DownloadState.Value = DownloadStatus.Downloading;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAdded(BeatmapSetInfo s)
|
private void setAdded(BeatmapSetInfo s)
|
||||||
{
|
{
|
||||||
if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID)
|
if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID)
|
||||||
Downloaded.Value = true;
|
DownloadState.Value = DownloadStatus.Downloaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setRemoved(BeatmapSetInfo s)
|
private void setRemoved(BeatmapSetInfo s)
|
||||||
{
|
{
|
||||||
if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID)
|
if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID)
|
||||||
Downloaded.Value = false;
|
DownloadState.Value = DownloadStatus.NotDownloaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void downloadBegan(DownloadBeatmapSetRequest d)
|
||||||
|
{
|
||||||
|
if (d.BeatmapSet.OnlineBeatmapSetID == set.OnlineBeatmapSetID)
|
||||||
|
DownloadState.Value = DownloadStatus.Downloading;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void downloadFailed(DownloadBeatmapSetRequest d)
|
||||||
|
{
|
||||||
|
if (d.BeatmapSet.OnlineBeatmapSetID == set.OnlineBeatmapSetID)
|
||||||
|
DownloadState.Value = DownloadStatus.NotDownloaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum DownloadStatus
|
||||||
|
{
|
||||||
|
NotDownloaded,
|
||||||
|
Downloading,
|
||||||
|
Downloaded,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,28 +62,30 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
|
|
||||||
protected override void ParseLine(Beatmap beatmap, Section section, string line)
|
protected override void ParseLine(Beatmap beatmap, Section section, string line)
|
||||||
{
|
{
|
||||||
|
var strippedLine = StripComments(line);
|
||||||
|
|
||||||
switch (section)
|
switch (section)
|
||||||
{
|
{
|
||||||
case Section.General:
|
case Section.General:
|
||||||
handleGeneral(line);
|
handleGeneral(strippedLine);
|
||||||
return;
|
return;
|
||||||
case Section.Editor:
|
case Section.Editor:
|
||||||
handleEditor(line);
|
handleEditor(strippedLine);
|
||||||
return;
|
return;
|
||||||
case Section.Metadata:
|
case Section.Metadata:
|
||||||
handleMetadata(line);
|
handleMetadata(line);
|
||||||
return;
|
return;
|
||||||
case Section.Difficulty:
|
case Section.Difficulty:
|
||||||
handleDifficulty(line);
|
handleDifficulty(strippedLine);
|
||||||
return;
|
return;
|
||||||
case Section.Events:
|
case Section.Events:
|
||||||
handleEvent(line);
|
handleEvent(strippedLine);
|
||||||
return;
|
return;
|
||||||
case Section.TimingPoints:
|
case Section.TimingPoints:
|
||||||
handleTimingPoint(line);
|
handleTimingPoint(strippedLine);
|
||||||
return;
|
return;
|
||||||
case Section.HitObjects:
|
case Section.HitObjects:
|
||||||
handleHitObject(line);
|
handleHitObject(strippedLine);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,9 +307,9 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
bool omitFirstBarSignature = false;
|
bool omitFirstBarSignature = false;
|
||||||
if (split.Length >= 8)
|
if (split.Length >= 8)
|
||||||
{
|
{
|
||||||
int effectFlags = int.Parse(split[7]);
|
EffectFlags effectFlags = (EffectFlags)int.Parse(split[7]);
|
||||||
kiaiMode = (effectFlags & 1) > 0;
|
kiaiMode = effectFlags.HasFlag(EffectFlags.Kiai);
|
||||||
omitFirstBarSignature = (effectFlags & 8) > 0;
|
omitFirstBarSignature = effectFlags.HasFlag(EffectFlags.OmitFirstBarLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
string stringSampleSet = sampleSet.ToString().ToLower();
|
string stringSampleSet = sampleSet.ToString().ToLower();
|
||||||
@ -405,5 +407,13 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
private double getOffsetTime() => ApplyOffsets ? offset : 0;
|
private double getOffsetTime() => ApplyOffsets ? offset : 0;
|
||||||
|
|
||||||
private double getOffsetTime(double time) => time + (ApplyOffsets ? offset : 0);
|
private double getOffsetTime(double time) => time + (ApplyOffsets ? offset : 0);
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
internal enum EffectFlags
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Kiai = 1,
|
||||||
|
OmitFirstBarLine = 8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,8 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
|
|
||||||
protected virtual void ParseLine(T output, Section section, string line)
|
protected virtual void ParseLine(T output, Section section, string line)
|
||||||
{
|
{
|
||||||
|
line = StripComments(line);
|
||||||
|
|
||||||
switch (section)
|
switch (section)
|
||||||
{
|
{
|
||||||
case Section.Colours:
|
case Section.Colours:
|
||||||
@ -65,6 +67,14 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected string StripComments(string line)
|
||||||
|
{
|
||||||
|
var index = line.IndexOf("//", StringComparison.Ordinal);
|
||||||
|
if (index > 0)
|
||||||
|
return line.Substring(0, index);
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
private bool hasComboColours;
|
private bool hasComboColours;
|
||||||
|
|
||||||
private void handleColours(T output, string line)
|
private void handleColours(T output, string line)
|
||||||
|
@ -42,6 +42,8 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
|
|
||||||
protected override void ParseLine(Storyboard storyboard, Section section, string line)
|
protected override void ParseLine(Storyboard storyboard, Section section, string line)
|
||||||
{
|
{
|
||||||
|
line = StripComments(line);
|
||||||
|
|
||||||
switch (section)
|
switch (section)
|
||||||
{
|
{
|
||||||
case Section.Events:
|
case Section.Events:
|
||||||
|
@ -5,6 +5,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using osu.Framework.IO.File;
|
using osu.Framework.IO.File;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
@ -175,7 +176,24 @@ namespace osu.Game.Database
|
|||||||
/// <param name="archive">The archive to be imported.</param>
|
/// <param name="archive">The archive to be imported.</param>
|
||||||
public TModel Import(ArchiveReader archive)
|
public TModel Import(ArchiveReader archive)
|
||||||
{
|
{
|
||||||
TModel item = null;
|
try
|
||||||
|
{
|
||||||
|
return Import(CreateModel(archive), archive);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Logger.Error(e, $"Model creation of {archive.Name} failed.", LoggingTarget.Database);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Import an item from a <see cref="TModel"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">The model to be imported.</param>
|
||||||
|
/// <param name="archive">An optional archive to use for model population.</param>
|
||||||
|
public TModel Import(TModel item, ArchiveReader archive = null)
|
||||||
|
{
|
||||||
delayEvents();
|
delayEvents();
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -186,18 +204,16 @@ namespace osu.Game.Database
|
|||||||
{
|
{
|
||||||
if (!write.IsTransactionLeader) throw new InvalidOperationException($"Ensure there is no parent transaction so errors can correctly be handled by {this}");
|
if (!write.IsTransactionLeader) throw new InvalidOperationException($"Ensure there is no parent transaction so errors can correctly be handled by {this}");
|
||||||
|
|
||||||
// create a new model (don't yet add to database)
|
|
||||||
item = CreateModel(archive);
|
|
||||||
|
|
||||||
var existing = CheckForExisting(item);
|
var existing = CheckForExisting(item);
|
||||||
|
|
||||||
if (existing != null)
|
if (existing != null)
|
||||||
{
|
{
|
||||||
Logger.Log($"Found existing {typeof(TModel)} for {archive.Name} (ID {existing.ID}). Skipping import.", LoggingTarget.Database);
|
Logger.Log($"Found existing {typeof(TModel)} for {item} (ID {existing.ID}). Skipping import.", LoggingTarget.Database);
|
||||||
return existing;
|
return existing;
|
||||||
}
|
}
|
||||||
|
|
||||||
item.Files = createFileInfos(archive, Files);
|
if (archive != null)
|
||||||
|
item.Files = createFileInfos(archive, Files);
|
||||||
|
|
||||||
Populate(item, archive);
|
Populate(item, archive);
|
||||||
|
|
||||||
@ -211,11 +227,11 @@ namespace osu.Game.Database
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Log($"Import of {archive.Name} successfully completed!", LoggingTarget.Database);
|
Logger.Log($"Import of {item} successfully completed!", LoggingTarget.Database);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Logger.Error(e, $"Import of {archive.Name} failed and has been rolled back.", LoggingTarget.Database);
|
Logger.Error(e, $"Import of {item} failed and has been rolled back.", LoggingTarget.Database);
|
||||||
item = null;
|
item = null;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@ -227,12 +243,6 @@ namespace osu.Game.Database
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Import an item from a <see cref="TModel"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="item">The model to be imported.</param>
|
|
||||||
public void Import(TModel item) => ModelStore.Add(item);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Perform an update of the specified item.
|
/// Perform an update of the specified item.
|
||||||
/// TODO: Support file changes.
|
/// TODO: Support file changes.
|
||||||
@ -385,8 +395,8 @@ namespace osu.Game.Database
|
|||||||
/// After this method, the model should be in a state ready to commit to a store.
|
/// After this method, the model should be in a state ready to commit to a store.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="model">The model to populate.</param>
|
/// <param name="model">The model to populate.</param>
|
||||||
/// <param name="archive">The archive to use as a reference for population.</param>
|
/// <param name="archive">The archive to use as a reference for population. May be null.</param>
|
||||||
protected virtual void Populate(TModel model, ArchiveReader archive)
|
protected virtual void Populate(TModel model, [CanBeNull] ArchiveReader archive)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ namespace osu.Game.Database
|
|||||||
{
|
{
|
||||||
public class DatabaseContextFactory : IDatabaseContextFactory
|
public class DatabaseContextFactory : IDatabaseContextFactory
|
||||||
{
|
{
|
||||||
private readonly GameHost host;
|
private readonly Storage storage;
|
||||||
|
|
||||||
private const string database_name = @"client";
|
private const string database_name = @"client";
|
||||||
|
|
||||||
@ -26,9 +26,9 @@ namespace osu.Game.Database
|
|||||||
|
|
||||||
private IDbContextTransaction currentWriteTransaction;
|
private IDbContextTransaction currentWriteTransaction;
|
||||||
|
|
||||||
public DatabaseContextFactory(GameHost host)
|
public DatabaseContextFactory(Storage storage)
|
||||||
{
|
{
|
||||||
this.host = host;
|
this.storage = storage;
|
||||||
recycleThreadContexts();
|
recycleThreadContexts();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ namespace osu.Game.Database
|
|||||||
|
|
||||||
private void recycleThreadContexts() => threadContexts = new ThreadLocal<OsuDbContext>(CreateContext);
|
private void recycleThreadContexts() => threadContexts = new ThreadLocal<OsuDbContext>(CreateContext);
|
||||||
|
|
||||||
protected virtual OsuDbContext CreateContext() => new OsuDbContext(host.Storage.GetDatabaseConnectionString(database_name))
|
protected virtual OsuDbContext CreateContext() => new OsuDbContext(storage.GetDatabaseConnectionString(database_name))
|
||||||
{
|
{
|
||||||
Database = { AutoTransactionsEnabled = false }
|
Database = { AutoTransactionsEnabled = false }
|
||||||
};
|
};
|
||||||
@ -129,7 +129,7 @@ namespace osu.Game.Database
|
|||||||
recycleThreadContexts();
|
recycleThreadContexts();
|
||||||
GC.Collect();
|
GC.Collect();
|
||||||
GC.WaitForPendingFinalizers();
|
GC.WaitForPendingFinalizers();
|
||||||
host.Storage.DeleteDatabase(database_name);
|
storage.DeleteDatabase(database_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,19 +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
|
|
||||||
|
|
||||||
namespace osu.Game.Database
|
|
||||||
{
|
|
||||||
public class SingletonContextFactory : IDatabaseContextFactory
|
|
||||||
{
|
|
||||||
private readonly OsuDbContext context;
|
|
||||||
|
|
||||||
public SingletonContextFactory(OsuDbContext context)
|
|
||||||
{
|
|
||||||
this.context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OsuDbContext Get() => context;
|
|
||||||
|
|
||||||
public DatabaseWriteUsage GetForWrite(bool withTransaction = true) => new DatabaseWriteUsage(context, null);
|
|
||||||
}
|
|
||||||
}
|
|
@ -26,10 +26,10 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
direction = value;
|
direction = value;
|
||||||
base.Direction = (direction & BarDirection.Horizontal) > 0 ? FillDirection.Vertical : FillDirection.Horizontal;
|
base.Direction = direction.HasFlag(BarDirection.Horizontal) ? FillDirection.Vertical : FillDirection.Horizontal;
|
||||||
foreach (var bar in Children)
|
foreach (var bar in Children)
|
||||||
{
|
{
|
||||||
bar.Size = (direction & BarDirection.Horizontal) > 0 ? new Vector2(1, 1.0f / Children.Count) : new Vector2(1.0f / Children.Count, 1);
|
bar.Size = direction.HasFlag(BarDirection.Horizontal) ? new Vector2(1, 1.0f / Children.Count) : new Vector2(1.0f / Children.Count, 1);
|
||||||
bar.Direction = direction;
|
bar.Direction = direction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,14 +56,14 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
if (bar.Bar != null)
|
if (bar.Bar != null)
|
||||||
{
|
{
|
||||||
bar.Bar.Length = length;
|
bar.Bar.Length = length;
|
||||||
bar.Bar.Size = (direction & BarDirection.Horizontal) > 0 ? new Vector2(1, size) : new Vector2(size, 1);
|
bar.Bar.Size = direction.HasFlag(BarDirection.Horizontal) ? new Vector2(1, size) : new Vector2(size, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Add(new Bar
|
Add(new Bar
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Size = (direction & BarDirection.Horizontal) > 0 ? new Vector2(1, size) : new Vector2(size, 1),
|
Size = direction.HasFlag(BarDirection.Horizontal) ? new Vector2(1, size) : new Vector2(size, 1),
|
||||||
Length = length,
|
Length = length,
|
||||||
Direction = Direction,
|
Direction = Direction,
|
||||||
});
|
});
|
||||||
|
@ -3,31 +3,17 @@
|
|||||||
|
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
using osu.Game.Graphics.Containers;
|
|
||||||
|
|
||||||
namespace osu.Game.Graphics.UserInterface
|
namespace osu.Game.Graphics.UserInterface
|
||||||
{
|
{
|
||||||
public class IconButton : OsuClickableContainer
|
public class IconButton : OsuAnimatedButton
|
||||||
{
|
{
|
||||||
public const float BUTTON_SIZE = 30;
|
public const float BUTTON_SIZE = 30;
|
||||||
|
|
||||||
private Color4? flashColour;
|
|
||||||
/// <summary>
|
|
||||||
/// The colour that should be flashed when the <see cref="IconButton"/> is clicked.
|
|
||||||
/// </summary>
|
|
||||||
public Color4 FlashColour
|
|
||||||
{
|
|
||||||
get { return flashColour ?? Color4.White; }
|
|
||||||
set { flashColour = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private Color4? iconColour;
|
private Color4? iconColour;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The icon colour. This does not affect <see cref="IconButton.Colour"/>.
|
/// The icon colour. This does not affect <see cref="IconButton.Colour"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -42,6 +28,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Color4? iconHoverColour;
|
private Color4? iconHoverColour;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The icon colour while the <see cref="IconButton"/> is hovered.
|
/// The icon colour while the <see cref="IconButton"/> is hovered.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -51,20 +38,6 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
set { iconHoverColour = value; }
|
set { iconHoverColour = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private Color4? hoverColour;
|
|
||||||
/// <summary>
|
|
||||||
/// The background colour of the <see cref="IconButton"/> while it is hovered.
|
|
||||||
/// </summary>
|
|
||||||
public Color4 HoverColour
|
|
||||||
{
|
|
||||||
get { return hoverColour ?? Color4.White; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
hoverColour = value;
|
|
||||||
hover.Colour = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The icon.
|
/// The icon.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -88,93 +61,39 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Vector2 ButtonSize
|
public Vector2 ButtonSize
|
||||||
{
|
{
|
||||||
get { return content.Size; }
|
get => Content.Size;
|
||||||
set { content.Size = value; }
|
set
|
||||||
|
{
|
||||||
|
Content.RelativeSizeAxes = Axes.None;
|
||||||
|
Content.Size = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly Container content;
|
|
||||||
private readonly SpriteIcon icon;
|
private readonly SpriteIcon icon;
|
||||||
private readonly Box hover;
|
|
||||||
|
|
||||||
public IconButton()
|
public IconButton()
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both;
|
AutoSizeAxes = Axes.Both;
|
||||||
|
ButtonSize = new Vector2(BUTTON_SIZE);
|
||||||
|
|
||||||
Children = new Drawable[]
|
Add(icon = new SpriteIcon
|
||||||
{
|
{
|
||||||
content = new Container
|
Origin = Anchor.Centre,
|
||||||
{
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Size = new Vector2(18),
|
||||||
Anchor = Anchor.Centre,
|
});
|
||||||
Size = new Vector2(BUTTON_SIZE),
|
|
||||||
CornerRadius = 5,
|
|
||||||
Masking = true,
|
|
||||||
EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
|
||||||
Colour = Color4.Black.Opacity(0.04f),
|
|
||||||
Type = EdgeEffectType.Shadow,
|
|
||||||
Radius = 5,
|
|
||||||
},
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
hover = new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Alpha = 0,
|
|
||||||
},
|
|
||||||
icon = new SpriteIcon
|
|
||||||
{
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Size = new Vector2(18),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuColour colours)
|
|
||||||
{
|
|
||||||
if (hoverColour == null)
|
|
||||||
HoverColour = colours.Yellow.Opacity(0.6f);
|
|
||||||
|
|
||||||
if (flashColour == null)
|
|
||||||
FlashColour = colours.Yellow;
|
|
||||||
|
|
||||||
Enabled.ValueChanged += enabled => this.FadeColour(enabled ? Color4.White : colours.Gray9, 200, Easing.OutQuint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnHover(InputState state)
|
protected override bool OnHover(InputState state)
|
||||||
{
|
{
|
||||||
hover.FadeIn(500, Easing.OutQuint);
|
|
||||||
icon.FadeColour(IconHoverColour, 500, Easing.OutQuint);
|
icon.FadeColour(IconHoverColour, 500, Easing.OutQuint);
|
||||||
return base.OnHover(state);
|
return base.OnHover(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnHoverLost(InputState state)
|
protected override void OnHoverLost(InputState state)
|
||||||
{
|
{
|
||||||
hover.FadeOut(500, Easing.OutQuint);
|
|
||||||
icon.FadeColour(IconColour, 500, Easing.OutQuint);
|
icon.FadeColour(IconColour, 500, Easing.OutQuint);
|
||||||
base.OnHoverLost(state);
|
base.OnHoverLost(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnClick(InputState state)
|
|
||||||
{
|
|
||||||
hover.FlashColour(FlashColour, 800, Easing.OutQuint);
|
|
||||||
return base.OnClick(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
|
|
||||||
{
|
|
||||||
content.ScaleTo(0.75f, 2000, Easing.OutQuint);
|
|
||||||
return base.OnMouseDown(state, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args)
|
|
||||||
{
|
|
||||||
content.ScaleTo(1, 1000, Easing.OutElastic);
|
|
||||||
return base.OnMouseUp(state, args);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
109
osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs
Normal file
109
osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
// 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.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Input;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Graphics.UserInterface
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Highlight on hover, bounce on click.
|
||||||
|
/// </summary>
|
||||||
|
public class OsuAnimatedButton : OsuClickableContainer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The colour that should be flashed when the <see cref="IconButton"/> is clicked.
|
||||||
|
/// </summary>
|
||||||
|
protected Color4 FlashColour = Color4.White.Opacity(0.3f);
|
||||||
|
|
||||||
|
private Color4 hoverColour = Color4.White.Opacity(0.1f);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The background colour of the <see cref="IconButton"/> while it is hovered.
|
||||||
|
/// </summary>
|
||||||
|
protected Color4 HoverColour
|
||||||
|
{
|
||||||
|
get => hoverColour;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
hoverColour = value;
|
||||||
|
hover.Colour = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Container<Drawable> Content => content;
|
||||||
|
|
||||||
|
private readonly Container content;
|
||||||
|
private readonly Box hover;
|
||||||
|
|
||||||
|
public OsuAnimatedButton()
|
||||||
|
{
|
||||||
|
base.Content.Add(content = new Container
|
||||||
|
{
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
CornerRadius = 5,
|
||||||
|
Masking = true,
|
||||||
|
EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Colour = Color4.Black.Opacity(0.04f),
|
||||||
|
Type = EdgeEffectType.Shadow,
|
||||||
|
Radius = 5,
|
||||||
|
},
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
hover = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = HoverColour,
|
||||||
|
Blending = BlendingMode.Additive,
|
||||||
|
Alpha = 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
Enabled.BindValueChanged(enabled => this.FadeColour(enabled ? Color4.White : colours.Gray9, 200, Easing.OutQuint), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnHover(InputState state)
|
||||||
|
{
|
||||||
|
hover.FadeIn(500, Easing.OutQuint);
|
||||||
|
return base.OnHover(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnHoverLost(InputState state)
|
||||||
|
{
|
||||||
|
hover.FadeOut(500, Easing.OutQuint);
|
||||||
|
base.OnHoverLost(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnClick(InputState state)
|
||||||
|
{
|
||||||
|
hover.FlashColour(FlashColour, 800, Easing.OutQuint);
|
||||||
|
return base.OnClick(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
|
||||||
|
{
|
||||||
|
Content.ScaleTo(0.75f, 2000, Easing.OutQuint);
|
||||||
|
return base.OnMouseDown(state, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args)
|
||||||
|
{
|
||||||
|
Content.ScaleTo(1, 1000, Easing.OutElastic);
|
||||||
|
return base.OnMouseUp(state, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -56,15 +56,15 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
base.Origin = value;
|
base.Origin = value;
|
||||||
c1.Origin = c1.Anchor = (value & Anchor.x2) > 0 ? Anchor.TopLeft : Anchor.TopRight;
|
c1.Origin = c1.Anchor = value.HasFlag(Anchor.x2) ? Anchor.TopLeft : Anchor.TopRight;
|
||||||
c2.Origin = c2.Anchor = (value & Anchor.x2) > 0 ? Anchor.TopRight : Anchor.TopLeft;
|
c2.Origin = c2.Anchor = value.HasFlag(Anchor.x2) ? Anchor.TopRight : Anchor.TopLeft;
|
||||||
|
|
||||||
X = (value & Anchor.x2) > 0 ? SIZE_RETRACTED.X * shear * 0.5f : 0;
|
X = value.HasFlag(Anchor.x2) ? SIZE_RETRACTED.X * shear * 0.5f : 0;
|
||||||
|
|
||||||
Remove(c1);
|
Remove(c1);
|
||||||
Remove(c2);
|
Remove(c2);
|
||||||
c1.Depth = (value & Anchor.x2) > 0 ? 0 : 1;
|
c1.Depth = value.HasFlag(Anchor.x2) ? 0 : 1;
|
||||||
c2.Depth = (value & Anchor.x2) > 0 ? 1 : 0;
|
c2.Depth = value.HasFlag(Anchor.x2) ? 1 : 0;
|
||||||
Add(c1);
|
Add(c1);
|
||||||
Add(c2);
|
Add(c2);
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ using osu.Framework.Input;
|
|||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
using osu.Framework.Threading;
|
using osu.Framework.Threading;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Overlays.Notifications;
|
using osu.Game.Overlays.Notifications;
|
||||||
@ -34,6 +35,7 @@ using osu.Game.Rulesets.Mods;
|
|||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
using osu.Game.Overlays.Volume;
|
using osu.Game.Overlays.Volume;
|
||||||
|
using osu.Game.Screens.Select;
|
||||||
|
|
||||||
namespace osu.Game
|
namespace osu.Game
|
||||||
{
|
{
|
||||||
@ -179,6 +181,41 @@ namespace osu.Game
|
|||||||
/// <param name="setId">The set to display.</param>
|
/// <param name="setId">The set to display.</param>
|
||||||
public void ShowBeatmapSet(int setId) => beatmapSetOverlay.FetchAndShowBeatmapSet(setId);
|
public void ShowBeatmapSet(int setId) => beatmapSetOverlay.FetchAndShowBeatmapSet(setId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Present a beatmap at song select.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="beatmap">The beatmap to select.</param>
|
||||||
|
public void PresentBeatmap(BeatmapSetInfo beatmap)
|
||||||
|
{
|
||||||
|
CloseAllOverlays(false);
|
||||||
|
|
||||||
|
void setBeatmap()
|
||||||
|
{
|
||||||
|
if (Beatmap.Disabled)
|
||||||
|
{
|
||||||
|
Schedule(setBeatmap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Beatmap.Value = BeatmapManager.GetWorkingBeatmap(beatmap.Beatmaps.First());
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (currentScreen)
|
||||||
|
{
|
||||||
|
case SongSelect _:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// navigate to song select if we are not already there.
|
||||||
|
var menu = (MainMenu)intro.ChildScreen;
|
||||||
|
|
||||||
|
menu.MakeCurrent();
|
||||||
|
menu.LoadToSolo();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
setBeatmap();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Show a user's profile as an overlay.
|
/// Show a user's profile as an overlay.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -245,6 +282,7 @@ namespace osu.Game
|
|||||||
BeatmapManager.PostNotification = n => notifications?.Post(n);
|
BeatmapManager.PostNotification = n => notifications?.Post(n);
|
||||||
|
|
||||||
BeatmapManager.GetStableStorage = GetStorageForStableInstall;
|
BeatmapManager.GetStableStorage = GetStorageForStableInstall;
|
||||||
|
BeatmapManager.PresentBeatmap = PresentBeatmap;
|
||||||
|
|
||||||
AddRange(new Drawable[]
|
AddRange(new Drawable[]
|
||||||
{
|
{
|
||||||
|
@ -107,7 +107,7 @@ namespace osu.Game
|
|||||||
{
|
{
|
||||||
Resources.AddStore(new DllResourceStore(@"osu.Game.Resources.dll"));
|
Resources.AddStore(new DllResourceStore(@"osu.Game.Resources.dll"));
|
||||||
|
|
||||||
dependencies.Cache(contextFactory = new DatabaseContextFactory(Host));
|
dependencies.Cache(contextFactory = new DatabaseContextFactory(Host.Storage));
|
||||||
|
|
||||||
dependencies.Cache(new LargeTextureStore(new RawTextureLoaderStore(new NamespacedResourceStore<byte[]>(Resources, @"Textures"))));
|
dependencies.Cache(new LargeTextureStore(new RawTextureLoaderStore(new NamespacedResourceStore<byte[]>(Resources, @"Textures"))));
|
||||||
|
|
||||||
|
@ -61,21 +61,29 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
|
|||||||
|
|
||||||
Action = () =>
|
Action = () =>
|
||||||
{
|
{
|
||||||
if (!downloader.Download())
|
if (downloader.DownloadState.Value == BeatmapSetDownloader.DownloadStatus.Downloading)
|
||||||
{
|
{
|
||||||
Content.MoveToX(-5, 50, Easing.OutSine).Then()
|
Content.MoveToX(-5, 50, Easing.OutSine).Then()
|
||||||
.MoveToX(5, 100, Easing.InOutSine).Then()
|
.MoveToX(5, 100, Easing.InOutSine).Then()
|
||||||
.MoveToX(-5, 100, Easing.InOutSine).Then()
|
.MoveToX(-5, 100, Easing.InOutSine).Then()
|
||||||
.MoveToX(0, 50, Easing.InSine);
|
.MoveToX(0, 50, Easing.InSine);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
downloader.Download();
|
||||||
};
|
};
|
||||||
|
|
||||||
downloader.Downloaded.ValueChanged += d =>
|
downloader.DownloadState.ValueChanged += state =>
|
||||||
{
|
{
|
||||||
if (d)
|
switch (state)
|
||||||
this.FadeOut(200);
|
{
|
||||||
else
|
case BeatmapSetDownloader.DownloadStatus.Downloaded:
|
||||||
this.FadeIn(200);
|
this.FadeOut(200);
|
||||||
|
break;
|
||||||
|
case BeatmapSetDownloader.DownloadStatus.NotDownloaded:
|
||||||
|
this.FadeIn(200);
|
||||||
|
break;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Direct
|
|||||||
|
|
||||||
public DirectGridPanel(BeatmapSetInfo beatmap) : base(beatmap)
|
public DirectGridPanel(BeatmapSetInfo beatmap) : base(beatmap)
|
||||||
{
|
{
|
||||||
Width = 400;
|
Width = 380;
|
||||||
Height = 140 + vertical_padding; //full height of all the elements plus vertical padding (autosize uses the image)
|
Height = 140 + vertical_padding; //full height of all the elements plus vertical padding (autosize uses the image)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,11 +168,10 @@ namespace osu.Game.Overlays.Direct
|
|||||||
},
|
},
|
||||||
new DownloadButton(SetInfo)
|
new DownloadButton(SetInfo)
|
||||||
{
|
{
|
||||||
Size = new Vector2(30),
|
Size = new Vector2(50, 30),
|
||||||
Margin = new MarginPadding(horizontal_padding),
|
Margin = new MarginPadding(horizontal_padding),
|
||||||
Anchor = Anchor.CentreRight,
|
Anchor = Anchor.TopRight,
|
||||||
Origin = Anchor.CentreRight,
|
Origin = Anchor.TopRight,
|
||||||
Colour = colours.Gray5,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -120,8 +120,8 @@ namespace osu.Game.Overlays.Direct
|
|||||||
Alpha = 0,
|
Alpha = 0,
|
||||||
Child = new DownloadButton(SetInfo)
|
Child = new DownloadButton(SetInfo)
|
||||||
{
|
{
|
||||||
Size = new Vector2(height - vertical_padding * 2),
|
Size = new Vector2(height - vertical_padding * 3),
|
||||||
Margin = new MarginPadding { Left = vertical_padding },
|
Margin = new MarginPadding { Left = vertical_padding, Right = vertical_padding },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
new FillFlowContainer
|
new FillFlowContainer
|
||||||
|
@ -99,6 +99,7 @@ namespace osu.Game.Overlays.Direct
|
|||||||
attachDownload(downloadRequest);
|
attachDownload(downloadRequest);
|
||||||
|
|
||||||
beatmaps.BeatmapDownloadBegan += attachDownload;
|
beatmaps.BeatmapDownloadBegan += attachDownload;
|
||||||
|
beatmaps.ItemAdded += setAdded;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool DisposeOnDeathRemoval => true;
|
public override bool DisposeOnDeathRemoval => true;
|
||||||
@ -107,6 +108,7 @@ namespace osu.Game.Overlays.Direct
|
|||||||
{
|
{
|
||||||
base.Dispose(isDisposing);
|
base.Dispose(isDisposing);
|
||||||
beatmaps.BeatmapDownloadBegan -= attachDownload;
|
beatmaps.BeatmapDownloadBegan -= attachDownload;
|
||||||
|
beatmaps.ItemAdded -= setAdded;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
@ -171,6 +173,12 @@ namespace osu.Game.Overlays.Direct
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setAdded(BeatmapSetInfo s)
|
||||||
|
{
|
||||||
|
if (s.OnlineBeatmapSetID == SetInfo.OnlineBeatmapSetID)
|
||||||
|
progressBar.FadeOut(500);
|
||||||
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
@ -1,76 +1,109 @@
|
|||||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Input;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.Drawables;
|
using osu.Game.Beatmaps.Drawables;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Direct
|
namespace osu.Game.Overlays.Direct
|
||||||
{
|
{
|
||||||
public class DownloadButton : OsuClickableContainer
|
public class DownloadButton : OsuAnimatedButton
|
||||||
{
|
{
|
||||||
private readonly SpriteIcon icon;
|
private readonly SpriteIcon icon;
|
||||||
|
private readonly SpriteIcon checkmark;
|
||||||
|
private readonly BeatmapSetDownloader downloader;
|
||||||
|
private readonly Box background;
|
||||||
|
|
||||||
|
private OsuColour colours;
|
||||||
|
|
||||||
public DownloadButton(BeatmapSetInfo set, bool noVideo = false)
|
public DownloadButton(BeatmapSetInfo set, bool noVideo = false)
|
||||||
{
|
{
|
||||||
BeatmapSetDownloader downloader;
|
AddRange(new Drawable[]
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
{
|
||||||
downloader = new BeatmapSetDownloader(set, noVideo),
|
downloader = new BeatmapSetDownloader(set, noVideo),
|
||||||
|
background = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Depth = float.MaxValue
|
||||||
|
},
|
||||||
icon = new SpriteIcon
|
icon = new SpriteIcon
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Size = new Vector2(30),
|
Size = new Vector2(13),
|
||||||
Icon = FontAwesome.fa_osu_chevron_down_o,
|
Icon = FontAwesome.fa_download,
|
||||||
},
|
},
|
||||||
};
|
checkmark = new SpriteIcon
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
X = 8,
|
||||||
|
Size = Vector2.Zero,
|
||||||
|
Icon = FontAwesome.fa_check,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Action = () =>
|
Action = () =>
|
||||||
{
|
{
|
||||||
if (!downloader.Download())
|
if (downloader.DownloadState == BeatmapSetDownloader.DownloadStatus.Downloading)
|
||||||
{
|
{
|
||||||
|
// todo: replace with ShakeContainer after https://github.com/ppy/osu/pull/2909 is merged.
|
||||||
Content.MoveToX(-5, 50, Easing.OutSine).Then()
|
Content.MoveToX(-5, 50, Easing.OutSine).Then()
|
||||||
.MoveToX(5, 100, Easing.InOutSine).Then()
|
.MoveToX(5, 100, Easing.InOutSine).Then()
|
||||||
.MoveToX(-5, 100, Easing.InOutSine).Then()
|
.MoveToX(-5, 100, Easing.InOutSine).Then()
|
||||||
.MoveToX(0, 50, Easing.InSine);
|
.MoveToX(0, 50, Easing.InSine);
|
||||||
}
|
}
|
||||||
};
|
else if (downloader.DownloadState == BeatmapSetDownloader.DownloadStatus.Downloaded)
|
||||||
|
{
|
||||||
downloader.Downloaded.ValueChanged += d =>
|
// TODO: Jump to song select with this set when the capability is implemented
|
||||||
{
|
}
|
||||||
if (d)
|
|
||||||
this.FadeOut(200);
|
|
||||||
else
|
else
|
||||||
this.FadeIn(200);
|
{
|
||||||
|
downloader.Download();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
icon.ScaleTo(0.9f, 1000, Easing.Out);
|
base.LoadComplete();
|
||||||
return base.OnMouseDown(state, args);
|
downloader.DownloadState.BindValueChanged(updateState, true);
|
||||||
|
FinishTransforms(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args)
|
[BackgroundDependencyLoader(permitNulls: true)]
|
||||||
|
private void load(OsuColour colours)
|
||||||
{
|
{
|
||||||
icon.ScaleTo(1f, 500, Easing.OutElastic);
|
this.colours = colours;
|
||||||
return base.OnMouseUp(state, args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnHover(InputState state)
|
private void updateState(BeatmapSetDownloader.DownloadStatus state)
|
||||||
{
|
{
|
||||||
icon.ScaleTo(1.1f, 500, Easing.OutElastic);
|
switch (state)
|
||||||
return base.OnHover(state);
|
{
|
||||||
}
|
case BeatmapSetDownloader.DownloadStatus.NotDownloaded:
|
||||||
|
background.FadeColour(colours.Gray4, 500, Easing.InOutExpo);
|
||||||
|
icon.MoveToX(0, 500, Easing.InOutExpo);
|
||||||
|
checkmark.ScaleTo(Vector2.Zero, 500, Easing.InOutExpo);
|
||||||
|
break;
|
||||||
|
|
||||||
protected override void OnHoverLost(InputState state)
|
case BeatmapSetDownloader.DownloadStatus.Downloading:
|
||||||
{
|
background.FadeColour(colours.Blue, 500, Easing.InOutExpo);
|
||||||
icon.ScaleTo(1f, 500, Easing.OutElastic);
|
icon.MoveToX(0, 500, Easing.InOutExpo);
|
||||||
|
checkmark.ScaleTo(Vector2.Zero, 500, Easing.InOutExpo);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BeatmapSetDownloader.DownloadStatus.Downloaded:
|
||||||
|
background.FadeColour(colours.Green, 500, Easing.InOutExpo);
|
||||||
|
icon.MoveToX(-8, 500, Easing.InOutExpo);
|
||||||
|
checkmark.ScaleTo(new Vector2(13), 500, Easing.InOutExpo);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,8 @@ namespace osu.Game.Overlays.Mods
|
|||||||
|
|
||||||
private void rulesetChanged(RulesetInfo newRuleset)
|
private void rulesetChanged(RulesetInfo newRuleset)
|
||||||
{
|
{
|
||||||
|
if (newRuleset == null) return;
|
||||||
|
|
||||||
var instance = newRuleset.CreateInstance();
|
var instance = newRuleset.CreateInstance();
|
||||||
|
|
||||||
foreach (ModSection section in ModSectionsContainer.Children)
|
foreach (ModSection section in ModSectionsContainer.Children)
|
||||||
@ -173,7 +175,10 @@ namespace osu.Game.Overlays.Mods
|
|||||||
refreshSelectedMods();
|
refreshSelectedMods();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refreshSelectedMods() => SelectedMods.Value = ModSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray();
|
private void refreshSelectedMods()
|
||||||
|
{
|
||||||
|
SelectedMods.Value = ModSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
public ModSelectOverlay()
|
public ModSelectOverlay()
|
||||||
{
|
{
|
||||||
|
@ -142,14 +142,14 @@ namespace osu.Game.Overlays
|
|||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Children = new[]
|
Children = new[]
|
||||||
{
|
{
|
||||||
prevButton = new IconButton
|
prevButton = new MusicIconButton
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Action = prev,
|
Action = prev,
|
||||||
Icon = FontAwesome.fa_step_backward,
|
Icon = FontAwesome.fa_step_backward,
|
||||||
},
|
},
|
||||||
playButton = new IconButton
|
playButton = new MusicIconButton
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
@ -158,7 +158,7 @@ namespace osu.Game.Overlays
|
|||||||
Action = play,
|
Action = play,
|
||||||
Icon = FontAwesome.fa_play_circle_o,
|
Icon = FontAwesome.fa_play_circle_o,
|
||||||
},
|
},
|
||||||
nextButton = new IconButton
|
nextButton = new MusicIconButton
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
@ -167,7 +167,7 @@ namespace osu.Game.Overlays
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
playlistButton = new IconButton
|
playlistButton = new MusicIconButton
|
||||||
{
|
{
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Anchor = Anchor.CentreRight,
|
Anchor = Anchor.CentreRight,
|
||||||
@ -405,6 +405,16 @@ namespace osu.Game.Overlays
|
|||||||
Prev
|
Prev
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class MusicIconButton : IconButton
|
||||||
|
{
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
HoverColour = colours.YellowDark.Opacity(0.6f);
|
||||||
|
FlashColour = colours.Yellow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class Background : BufferedContainer
|
private class Background : BufferedContainer
|
||||||
{
|
{
|
||||||
private readonly Sprite sprite;
|
private readonly Sprite sprite;
|
||||||
|
@ -128,7 +128,8 @@ namespace osu.Game.Overlays
|
|||||||
var section = sections.Children.FirstOrDefault(s => s.AcceptTypes.Any(accept => accept.IsAssignableFrom(ourType)));
|
var section = sections.Children.FirstOrDefault(s => s.AcceptTypes.Any(accept => accept.IsAssignableFrom(ourType)));
|
||||||
section?.Add(notification, notification.DisplayOnTop ? -runningDepth : runningDepth);
|
section?.Add(notification, notification.DisplayOnTop ? -runningDepth : runningDepth);
|
||||||
|
|
||||||
State = Visibility.Visible;
|
if (notification.IsImportant)
|
||||||
|
State = Visibility.Visible;
|
||||||
|
|
||||||
updateCounts();
|
updateCounts();
|
||||||
});
|
});
|
||||||
|
@ -23,6 +23,11 @@ namespace osu.Game.Overlays.Notifications
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action Closed;
|
public event Action Closed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether this notification should forcefully display itself.
|
||||||
|
/// </summary>
|
||||||
|
public virtual bool IsImportant => true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Run on user activating the notification. Return true to close.
|
/// Run on user activating the notification. Return true to close.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -188,16 +188,17 @@ namespace osu.Game.Overlays
|
|||||||
int optionCount = 0;
|
int optionCount = 0;
|
||||||
int selectedOption = -1;
|
int selectedOption = -1;
|
||||||
|
|
||||||
if (description.RawValue is bool)
|
switch (description.RawValue)
|
||||||
{
|
{
|
||||||
optionCount = 1;
|
case bool val:
|
||||||
if ((bool)description.RawValue) selectedOption = 0;
|
optionCount = 1;
|
||||||
}
|
if (val) selectedOption = 0;
|
||||||
else if (description.RawValue is Enum)
|
break;
|
||||||
{
|
case Enum _:
|
||||||
var values = Enum.GetValues(description.RawValue.GetType());
|
var values = Enum.GetValues(description.RawValue.GetType());
|
||||||
optionCount = values.Length;
|
optionCount = values.Length;
|
||||||
selectedOption = Convert.ToInt32(description.RawValue);
|
selectedOption = Convert.ToInt32(description.RawValue);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
textLine2.Origin = optionCount > 0 ? Anchor.BottomCentre : Anchor.Centre;
|
textLine2.Origin = optionCount > 0 ? Anchor.BottomCentre : Anchor.Centre;
|
||||||
|
@ -118,9 +118,9 @@ namespace osu.Game.Overlays.Toolbar
|
|||||||
{
|
{
|
||||||
Direction = FillDirection.Vertical,
|
Direction = FillDirection.Vertical,
|
||||||
RelativeSizeAxes = Axes.Both, //stops us being considered in parent's autosize
|
RelativeSizeAxes = Axes.Both, //stops us being considered in parent's autosize
|
||||||
Anchor = (TooltipAnchor & Anchor.x0) > 0 ? Anchor.BottomLeft : Anchor.BottomRight,
|
Anchor = TooltipAnchor.HasFlag(Anchor.x0) ? Anchor.BottomLeft : Anchor.BottomRight,
|
||||||
Origin = TooltipAnchor,
|
Origin = TooltipAnchor,
|
||||||
Position = new Vector2((TooltipAnchor & Anchor.x0) > 0 ? 5 : -5, 5),
|
Position = new Vector2(TooltipAnchor.HasFlag(Anchor.x0) ? 5 : -5, 5),
|
||||||
Alpha = 0,
|
Alpha = 0,
|
||||||
Children = new[]
|
Children = new[]
|
||||||
{
|
{
|
||||||
|
@ -62,15 +62,19 @@ namespace osu.Game.Rulesets.Difficulty
|
|||||||
|
|
||||||
IEnumerable<Mod> createDifficultyAdjustmentModCombinations(IEnumerable<Mod> currentSet, Mod[] adjustmentSet, int currentSetCount = 0, int adjustmentSetStart = 0)
|
IEnumerable<Mod> createDifficultyAdjustmentModCombinations(IEnumerable<Mod> currentSet, Mod[] adjustmentSet, int currentSetCount = 0, int adjustmentSetStart = 0)
|
||||||
{
|
{
|
||||||
// Initial-case: Empty current set
|
switch (currentSetCount)
|
||||||
if (currentSetCount == 0)
|
{
|
||||||
yield return new NoModMod();
|
case 0:
|
||||||
|
// Initial-case: Empty current set
|
||||||
if (currentSetCount == 1)
|
yield return new NoModMod();
|
||||||
yield return currentSet.Single();
|
break;
|
||||||
|
case 1:
|
||||||
if (currentSetCount > 1)
|
yield return currentSet.Single();
|
||||||
yield return new MultiMod(currentSet.ToArray());
|
break;
|
||||||
|
default:
|
||||||
|
yield return new MultiMod(currentSet.ToArray());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Apply mods in the adjustment set recursively. Using the entire adjustment set would result in duplicate multi-mod mod
|
// Apply mods in the adjustment set recursively. Using the entire adjustment set would result in duplicate multi-mod mod
|
||||||
// combinations in further recursions, so a moving subset is used to eliminate this effect
|
// combinations in further recursions, so a moving subset is used to eliminate this effect
|
||||||
|
@ -11,7 +11,7 @@ using osu.Game.Rulesets.UI;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Mods
|
namespace osu.Game.Rulesets.Mods
|
||||||
{
|
{
|
||||||
public class ModAutoplay<T> : ModAutoplay, IApplicableToRulesetContainer<T>
|
public abstract class ModAutoplay<T> : ModAutoplay, IApplicableToRulesetContainer<T>
|
||||||
where T : HitObject
|
where T : HitObject
|
||||||
{
|
{
|
||||||
protected virtual Score CreateReplayScore(Beatmap<T> beatmap) => new Score { Replay = new Replay() };
|
protected virtual Score CreateReplayScore(Beatmap<T> beatmap) => new Score { Replay = new Replay() };
|
||||||
|
@ -30,6 +30,8 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
{
|
{
|
||||||
string[] split = text.Split(',');
|
string[] split = text.Split(',');
|
||||||
|
|
||||||
|
Vector2 pos = new Vector2((int)Convert.ToSingle(split[0], CultureInfo.InvariantCulture), (int)Convert.ToSingle(split[1], CultureInfo.InvariantCulture));
|
||||||
|
|
||||||
ConvertHitObjectType type = (ConvertHitObjectType)int.Parse(split[3]) & ~ConvertHitObjectType.ColourHax;
|
ConvertHitObjectType type = (ConvertHitObjectType)int.Parse(split[3]) & ~ConvertHitObjectType.ColourHax;
|
||||||
bool combo = type.HasFlag(ConvertHitObjectType.NewCombo);
|
bool combo = type.HasFlag(ConvertHitObjectType.NewCombo);
|
||||||
type &= ~ConvertHitObjectType.NewCombo;
|
type &= ~ConvertHitObjectType.NewCombo;
|
||||||
@ -39,17 +41,15 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
|
|
||||||
HitObject result = null;
|
HitObject result = null;
|
||||||
|
|
||||||
if ((type & ConvertHitObjectType.Circle) > 0)
|
if (type.HasFlag(ConvertHitObjectType.Circle))
|
||||||
{
|
{
|
||||||
result = CreateHit(new Vector2(int.Parse(split[0]), int.Parse(split[1])), combo);
|
result = CreateHit(pos, combo);
|
||||||
|
|
||||||
if (split.Length > 5)
|
if (split.Length > 5)
|
||||||
readCustomSampleBanks(split[5], bankInfo);
|
readCustomSampleBanks(split[5], bankInfo);
|
||||||
}
|
}
|
||||||
else if ((type & ConvertHitObjectType.Slider) > 0)
|
else if (type.HasFlag(ConvertHitObjectType.Slider))
|
||||||
{
|
{
|
||||||
var pos = new Vector2(int.Parse(split[0]), int.Parse(split[1]));
|
|
||||||
|
|
||||||
CurveType curveType = CurveType.Catmull;
|
CurveType curveType = CurveType.Catmull;
|
||||||
double length = 0;
|
double length = 0;
|
||||||
var points = new List<Vector2> { Vector2.Zero };
|
var points = new List<Vector2> { Vector2.Zero };
|
||||||
@ -150,14 +150,14 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
|
|
||||||
result = CreateSlider(pos, combo, points, length, curveType, repeatCount, nodeSamples);
|
result = CreateSlider(pos, combo, points, length, curveType, repeatCount, nodeSamples);
|
||||||
}
|
}
|
||||||
else if ((type & ConvertHitObjectType.Spinner) > 0)
|
else if (type.HasFlag(ConvertHitObjectType.Spinner))
|
||||||
{
|
{
|
||||||
result = CreateSpinner(new Vector2(512, 384) / 2, Convert.ToDouble(split[5], CultureInfo.InvariantCulture) + offset);
|
result = CreateSpinner(new Vector2(512, 384) / 2, Convert.ToDouble(split[5], CultureInfo.InvariantCulture) + offset);
|
||||||
|
|
||||||
if (split.Length > 6)
|
if (split.Length > 6)
|
||||||
readCustomSampleBanks(split[6], bankInfo);
|
readCustomSampleBanks(split[6], bankInfo);
|
||||||
}
|
}
|
||||||
else if ((type & ConvertHitObjectType.Hold) > 0)
|
else if (type.HasFlag(ConvertHitObjectType.Hold))
|
||||||
{
|
{
|
||||||
// Note: Hold is generated by BMS converts
|
// Note: Hold is generated by BMS converts
|
||||||
|
|
||||||
@ -170,7 +170,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
readCustomSampleBanks(string.Join(":", ss.Skip(1)), bankInfo);
|
readCustomSampleBanks(string.Join(":", ss.Skip(1)), bankInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = CreateHold(new Vector2(int.Parse(split[0]), int.Parse(split[1])), combo, endTime + offset);
|
result = CreateHold(pos, combo, endTime + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == null)
|
if (result == null)
|
||||||
@ -266,7 +266,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if ((type & LegacySoundType.Finish) > 0)
|
if (type.HasFlag(LegacySoundType.Finish))
|
||||||
{
|
{
|
||||||
soundTypes.Add(new SampleInfo
|
soundTypes.Add(new SampleInfo
|
||||||
{
|
{
|
||||||
@ -276,7 +276,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((type & LegacySoundType.Whistle) > 0)
|
if (type.HasFlag(LegacySoundType.Whistle))
|
||||||
{
|
{
|
||||||
soundTypes.Add(new SampleInfo
|
soundTypes.Add(new SampleInfo
|
||||||
{
|
{
|
||||||
@ -286,7 +286,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((type & LegacySoundType.Clap) > 0)
|
if (type.HasFlag(LegacySoundType.Clap))
|
||||||
{
|
{
|
||||||
soundTypes.Add(new SampleInfo
|
soundTypes.Add(new SampleInfo
|
||||||
{
|
{
|
||||||
|
@ -15,10 +15,10 @@ namespace osu.Game.Rulesets.Replays.Legacy
|
|||||||
public bool MouseLeft => MouseLeft1 || MouseLeft2;
|
public bool MouseLeft => MouseLeft1 || MouseLeft2;
|
||||||
public bool MouseRight => MouseRight1 || MouseRight2;
|
public bool MouseRight => MouseRight1 || MouseRight2;
|
||||||
|
|
||||||
public bool MouseLeft1 => (ButtonState & ReplayButtonState.Left1) > 0;
|
public bool MouseLeft1 => ButtonState.HasFlag(ReplayButtonState.Left1);
|
||||||
public bool MouseRight1 => (ButtonState & ReplayButtonState.Right1) > 0;
|
public bool MouseRight1 => ButtonState.HasFlag(ReplayButtonState.Right1);
|
||||||
public bool MouseLeft2 => (ButtonState & ReplayButtonState.Left2) > 0;
|
public bool MouseLeft2 => ButtonState.HasFlag(ReplayButtonState.Left2);
|
||||||
public bool MouseRight2 => (ButtonState & ReplayButtonState.Right2) > 0;
|
public bool MouseRight2 => ButtonState.HasFlag(ReplayButtonState.Right2);
|
||||||
|
|
||||||
public ReplayButtonState ButtonState;
|
public ReplayButtonState ButtonState;
|
||||||
|
|
||||||
|
@ -56,6 +56,12 @@ namespace osu.Game.Rulesets.UI
|
|||||||
|
|
||||||
public abstract IEnumerable<HitObject> Objects { get; }
|
public abstract IEnumerable<HitObject> Objects { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The point in time at which gameplay starts, including any required lead-in for display purposes.
|
||||||
|
/// Defaults to two seconds before the first <see cref="HitObject"/>. Override as necessary.
|
||||||
|
/// </summary>
|
||||||
|
public virtual double GameplayStartTime => Objects.First().StartTime - 2000;
|
||||||
|
|
||||||
private readonly Lazy<Playfield> playfield;
|
private readonly Lazy<Playfield> playfield;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -83,6 +89,14 @@ namespace osu.Game.Rulesets.UI
|
|||||||
Ruleset = ruleset;
|
Ruleset = ruleset;
|
||||||
playfield = new Lazy<Playfield>(CreatePlayfield);
|
playfield = new Lazy<Playfield>(CreatePlayfield);
|
||||||
|
|
||||||
|
IsPaused.ValueChanged += paused =>
|
||||||
|
{
|
||||||
|
if (HasReplayLoaded)
|
||||||
|
return;
|
||||||
|
|
||||||
|
KeyBindingInputManager.UseParentInput = !paused;
|
||||||
|
};
|
||||||
|
|
||||||
Cursor = CreateCursor();
|
Cursor = CreateCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,6 +128,11 @@ namespace osu.Game.Rulesets.UI
|
|||||||
|
|
||||||
public Replay Replay { get; private set; }
|
public Replay Replay { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the game is paused. Used to block user input.
|
||||||
|
/// </summary>
|
||||||
|
public readonly BindableBool IsPaused = new BindableBool();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets a replay to be used, overriding local input.
|
/// Sets a replay to be used, overriding local input.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -57,22 +57,23 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public new ScrollingHitObjectContainer HitObjects => (ScrollingHitObjectContainer)base.HitObjects;
|
public new ScrollingHitObjectContainer HitObjects => (ScrollingHitObjectContainer)base.HitObjects;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The direction in which <see cref="DrawableHitObject"/>s in this <see cref="ScrollingPlayfield"/> should scroll.
|
||||||
|
/// </summary>
|
||||||
protected readonly Bindable<ScrollingDirection> Direction = new Bindable<ScrollingDirection>();
|
protected readonly Bindable<ScrollingDirection> Direction = new Bindable<ScrollingDirection>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new <see cref="ScrollingPlayfield"/>.
|
/// Creates a new <see cref="ScrollingPlayfield"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="direction">The direction in which <see cref="DrawableHitObject"/>s in this container should scroll.</param>
|
|
||||||
/// <param name="customWidth">The width to scale the internal coordinate space to.
|
/// <param name="customWidth">The width to scale the internal coordinate space to.
|
||||||
/// May be null if scaling based on <paramref name="customHeight"/> is desired. If <paramref name="customHeight"/> is also null, no scaling will occur.
|
/// May be null if scaling based on <paramref name="customHeight"/> is desired. If <paramref name="customHeight"/> is also null, no scaling will occur.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="customHeight">The height to scale the internal coordinate space to.
|
/// <param name="customHeight">The height to scale the internal coordinate space to.
|
||||||
/// May be null if scaling based on <paramref name="customWidth"/> is desired. If <paramref name="customWidth"/> is also null, no scaling will occur.
|
/// May be null if scaling based on <paramref name="customWidth"/> is desired. If <paramref name="customWidth"/> is also null, no scaling will occur.
|
||||||
/// </param>
|
/// </param>
|
||||||
protected ScrollingPlayfield(ScrollingDirection direction, float? customWidth = null, float? customHeight = null)
|
protected ScrollingPlayfield(float? customWidth = null, float? customHeight = null)
|
||||||
: base(customWidth, customHeight)
|
: base(customWidth, customHeight)
|
||||||
{
|
{
|
||||||
Direction.Value = direction;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
|
@ -27,16 +27,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline
|
|||||||
|
|
||||||
public TimelineButton()
|
public TimelineButton()
|
||||||
{
|
{
|
||||||
InternalChild = button = new IconButton
|
InternalChild = button = new TimelineIconButton { Action = () => Action?.Invoke() };
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
IconColour = OsuColour.Gray(0.35f),
|
|
||||||
IconHoverColour = Color4.White,
|
|
||||||
HoverColour = OsuColour.Gray(0.25f),
|
|
||||||
FlashColour = OsuColour.Gray(0.5f),
|
|
||||||
Action = () => Action?.Invoke()
|
|
||||||
};
|
|
||||||
|
|
||||||
button.Enabled.BindTo(Enabled);
|
button.Enabled.BindTo(Enabled);
|
||||||
Width = button.ButtonSize.X;
|
Width = button.ButtonSize.X;
|
||||||
@ -48,5 +39,18 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline
|
|||||||
|
|
||||||
button.ButtonSize = new Vector2(button.ButtonSize.X, DrawHeight);
|
button.ButtonSize = new Vector2(button.ButtonSize.X, DrawHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class TimelineIconButton : IconButton
|
||||||
|
{
|
||||||
|
public TimelineIconButton()
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre;
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
IconColour = OsuColour.Gray(0.35f);
|
||||||
|
IconHoverColour = Color4.White;
|
||||||
|
HoverColour = OsuColour.Gray(0.25f);
|
||||||
|
FlashColour = OsuColour.Gray(0.5f);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
OnChart = delegate { Push(new ChartListing()); },
|
OnChart = delegate { Push(new ChartListing()); },
|
||||||
OnDirect = delegate { Push(new OnlineListing()); },
|
OnDirect = delegate { Push(new OnlineListing()); },
|
||||||
OnEdit = delegate { Push(new Editor()); },
|
OnEdit = delegate { Push(new Editor()); },
|
||||||
OnSolo = delegate { Push(consumeSongSelect()); },
|
OnSolo = onSolo,
|
||||||
OnMulti = delegate { Push(new Multiplayer()); },
|
OnMulti = delegate { Push(new Multiplayer()); },
|
||||||
OnExit = Exit,
|
OnExit = Exit,
|
||||||
}
|
}
|
||||||
@ -85,6 +85,10 @@ namespace osu.Game.Screens.Menu
|
|||||||
LoadComponentAsync(songSelect = new PlaySongSelect());
|
LoadComponentAsync(songSelect = new PlaySongSelect());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void LoadToSolo() => Schedule(onSolo);
|
||||||
|
|
||||||
|
private void onSolo() => Push(consumeSongSelect());
|
||||||
|
|
||||||
private Screen consumeSongSelect()
|
private Screen consumeSongSelect()
|
||||||
{
|
{
|
||||||
var s = songSelect;
|
var s = songSelect;
|
||||||
|
@ -195,7 +195,6 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
protected virtual KeyCounterCollection CreateKeyCounter() => new KeyCounterCollection
|
protected virtual KeyCounterCollection CreateKeyCounter() => new KeyCounterCollection
|
||||||
{
|
{
|
||||||
IsCounting = true,
|
|
||||||
FadeTime = 50,
|
FadeTime = 50,
|
||||||
Anchor = Anchor.BottomRight,
|
Anchor = Anchor.BottomRight,
|
||||||
Origin = Anchor.BottomRight,
|
Origin = Anchor.BottomRight,
|
||||||
|
@ -19,7 +19,7 @@ namespace osu.Game.Screens.Play
|
|||||||
private Container textLayer;
|
private Container textLayer;
|
||||||
private SpriteText countSpriteText;
|
private SpriteText countSpriteText;
|
||||||
|
|
||||||
public bool IsCounting { get; set; }
|
public bool IsCounting { get; set; } = true;
|
||||||
private int countPresses;
|
private int countPresses;
|
||||||
public int CountPresses
|
public int CountPresses
|
||||||
{
|
{
|
||||||
|
@ -53,8 +53,7 @@ namespace osu.Game.Screens.Play
|
|||||||
configVisibility.BindValueChanged(_ => updateVisibility(), true);
|
configVisibility.BindValueChanged(_ => updateVisibility(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//further: change default values here and in KeyCounter if needed, instead of passing them in every constructor
|
private bool isCounting = true;
|
||||||
private bool isCounting;
|
|
||||||
public bool IsCounting
|
public bool IsCounting
|
||||||
{
|
{
|
||||||
get { return isCounting; }
|
get { return isCounting; }
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Configuration;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Timing;
|
using osu.Framework.Timing;
|
||||||
@ -18,7 +19,7 @@ namespace osu.Game.Screens.Play
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class PauseContainer : Container
|
public class PauseContainer : Container
|
||||||
{
|
{
|
||||||
public bool IsPaused { get; private set; }
|
public readonly BindableBool IsPaused = new BindableBool();
|
||||||
|
|
||||||
public Func<bool> CheckCanPause;
|
public Func<bool> CheckCanPause;
|
||||||
|
|
||||||
@ -39,9 +40,6 @@ namespace osu.Game.Screens.Play
|
|||||||
public Action OnRetry;
|
public Action OnRetry;
|
||||||
public Action OnQuit;
|
public Action OnQuit;
|
||||||
|
|
||||||
public Action OnResume;
|
|
||||||
public Action OnPause;
|
|
||||||
|
|
||||||
private readonly FramedClock framedClock;
|
private readonly FramedClock framedClock;
|
||||||
private readonly DecoupleableInterpolatingFramedClock decoupledClock;
|
private readonly DecoupleableInterpolatingFramedClock decoupledClock;
|
||||||
|
|
||||||
@ -84,9 +82,8 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
// stop the seekable clock (stops the audio eventually)
|
// stop the seekable clock (stops the audio eventually)
|
||||||
decoupledClock.Stop();
|
decoupledClock.Stop();
|
||||||
IsPaused = true;
|
IsPaused.Value = true;
|
||||||
|
|
||||||
OnPause?.Invoke();
|
|
||||||
pauseOverlay.Show();
|
pauseOverlay.Show();
|
||||||
|
|
||||||
lastPauseActionTime = Time.Current;
|
lastPauseActionTime = Time.Current;
|
||||||
@ -96,7 +93,7 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
if (!IsPaused) return;
|
if (!IsPaused) return;
|
||||||
|
|
||||||
IsPaused = false;
|
IsPaused.Value = false;
|
||||||
IsResuming = false;
|
IsResuming = false;
|
||||||
lastPauseActionTime = Time.Current;
|
lastPauseActionTime = Time.Current;
|
||||||
|
|
||||||
@ -105,7 +102,6 @@ namespace osu.Game.Screens.Play
|
|||||||
decoupledClock.Seek(decoupledClock.CurrentTime);
|
decoupledClock.Seek(decoupledClock.CurrentTime);
|
||||||
decoupledClock.Start();
|
decoupledClock.Start();
|
||||||
|
|
||||||
OnResume?.Invoke();
|
|
||||||
pauseOverlay.Hide();
|
pauseOverlay.Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,10 +138,9 @@ namespace osu.Game.Screens.Play
|
|||||||
sourceClock = (IAdjustableClock)working.Track ?? new StopwatchClock();
|
sourceClock = (IAdjustableClock)working.Track ?? new StopwatchClock();
|
||||||
adjustableClock = new DecoupleableInterpolatingFramedClock { IsCoupled = false };
|
adjustableClock = new DecoupleableInterpolatingFramedClock { IsCoupled = false };
|
||||||
|
|
||||||
var firstObjectTime = RulesetContainer.Objects.First().StartTime;
|
|
||||||
adjustableClock.Seek(AllowLeadIn
|
adjustableClock.Seek(AllowLeadIn
|
||||||
? Math.Min(0, firstObjectTime - Math.Max(beatmap.ControlPointInfo.TimingPointAt(firstObjectTime).BeatLength * 4, beatmap.BeatmapInfo.AudioLeadIn))
|
? Math.Min(RulesetContainer.GameplayStartTime, beatmap.HitObjects.First().StartTime - beatmap.BeatmapInfo.AudioLeadIn)
|
||||||
: firstObjectTime);
|
: RulesetContainer.GameplayStartTime);
|
||||||
|
|
||||||
adjustableClock.ProcessFrame();
|
adjustableClock.ProcessFrame();
|
||||||
|
|
||||||
@ -163,15 +162,10 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
pauseContainer = new PauseContainer(offsetClock, adjustableClock)
|
pauseContainer = new PauseContainer(offsetClock, adjustableClock)
|
||||||
{
|
{
|
||||||
|
Retries = RestartCount,
|
||||||
OnRetry = Restart,
|
OnRetry = Restart,
|
||||||
OnQuit = Exit,
|
OnQuit = Exit,
|
||||||
CheckCanPause = () => AllowPause && ValidForResume && !HasFailed && !RulesetContainer.HasReplayLoaded,
|
CheckCanPause = () => AllowPause && ValidForResume && !HasFailed && !RulesetContainer.HasReplayLoaded,
|
||||||
OnPause = () =>
|
|
||||||
{
|
|
||||||
pauseContainer.Retries = RestartCount;
|
|
||||||
hudOverlay.KeyCounter.IsCounting = !pauseContainer.IsPaused;
|
|
||||||
},
|
|
||||||
OnResume = () => hudOverlay.KeyCounter.IsCounting = true,
|
|
||||||
Children = new[]
|
Children = new[]
|
||||||
{
|
{
|
||||||
storyboardContainer = new Container
|
storyboardContainer = new Container
|
||||||
@ -199,7 +193,7 @@ namespace osu.Game.Screens.Play
|
|||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre
|
Origin = Anchor.Centre
|
||||||
},
|
},
|
||||||
new SkipOverlay(firstObjectTime)
|
new SkipOverlay(RulesetContainer.GameplayStartTime)
|
||||||
{
|
{
|
||||||
Clock = Clock, // skip button doesn't want to use the audio clock directly
|
Clock = Clock, // skip button doesn't want to use the audio clock directly
|
||||||
ProcessCustomClock = false,
|
ProcessCustomClock = false,
|
||||||
@ -219,9 +213,7 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
if (!IsCurrentScreen) return;
|
if (!IsCurrentScreen) return;
|
||||||
|
|
||||||
//we want to hide the hitrenderer immediately (looks better).
|
pauseContainer.Hide();
|
||||||
//we may be able to remove this once the mouse cursor trail is improved.
|
|
||||||
RulesetContainer?.Hide();
|
|
||||||
Restart();
|
Restart();
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -230,6 +222,8 @@ namespace osu.Game.Screens.Play
|
|||||||
hudOverlay.HoldToQuit.Action = Exit;
|
hudOverlay.HoldToQuit.Action = Exit;
|
||||||
hudOverlay.KeyCounter.Visible.BindTo(RulesetContainer.HasReplayLoaded);
|
hudOverlay.KeyCounter.Visible.BindTo(RulesetContainer.HasReplayLoaded);
|
||||||
|
|
||||||
|
RulesetContainer.IsPaused.BindTo(pauseContainer.IsPaused);
|
||||||
|
|
||||||
if (ShowStoryboard)
|
if (ShowStoryboard)
|
||||||
initializeStoryboard(false);
|
initializeStoryboard(false);
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
{
|
{
|
||||||
Rank = newRank;
|
Rank = newRank;
|
||||||
|
|
||||||
if (IsLoaded)
|
if (LoadState >= LoadState.Ready)
|
||||||
updateTexture();
|
updateTexture();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,10 +84,10 @@ namespace osu.Game.Screens.Select
|
|||||||
|
|
||||||
protected override void UpdateBeatmap(WorkingBeatmap beatmap)
|
protected override void UpdateBeatmap(WorkingBeatmap beatmap)
|
||||||
{
|
{
|
||||||
base.UpdateBeatmap(beatmap);
|
|
||||||
|
|
||||||
beatmap.Mods.BindTo(SelectedMods);
|
beatmap.Mods.BindTo(SelectedMods);
|
||||||
|
|
||||||
|
base.UpdateBeatmap(beatmap);
|
||||||
|
|
||||||
BeatmapDetails.Beatmap = beatmap;
|
BeatmapDetails.Beatmap = beatmap;
|
||||||
|
|
||||||
if (beatmap.Track != null)
|
if (beatmap.Track != null)
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Input;
|
using OpenTK.Input;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
@ -20,6 +21,7 @@ using osu.Game.Graphics.Containers;
|
|||||||
using osu.Game.Input.Bindings;
|
using osu.Game.Input.Bindings;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Screens.Backgrounds;
|
using osu.Game.Screens.Backgrounds;
|
||||||
using osu.Game.Screens.Edit;
|
using osu.Game.Screens.Edit;
|
||||||
using osu.Game.Screens.Menu;
|
using osu.Game.Screens.Menu;
|
||||||
@ -70,7 +72,14 @@ namespace osu.Game.Screens.Select
|
|||||||
private DependencyContainer dependencies;
|
private DependencyContainer dependencies;
|
||||||
|
|
||||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||||
=> dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
{
|
||||||
|
dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
||||||
|
dependencies.CacheAs(this);
|
||||||
|
dependencies.CacheAs(Ruleset);
|
||||||
|
dependencies.CacheAs<IBindable<RulesetInfo>>(Ruleset);
|
||||||
|
|
||||||
|
return dependencies;
|
||||||
|
}
|
||||||
|
|
||||||
protected SongSelect()
|
protected SongSelect()
|
||||||
{
|
{
|
||||||
@ -189,9 +198,9 @@ namespace osu.Game.Screens.Select
|
|||||||
[BackgroundDependencyLoader(true)]
|
[BackgroundDependencyLoader(true)]
|
||||||
private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours)
|
private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours)
|
||||||
{
|
{
|
||||||
dependencies.CacheAs(this);
|
// manual binding to parent ruleset to allow for delayed load in the incoming direction.
|
||||||
dependencies.CacheAs(Ruleset);
|
base.Ruleset.ValueChanged += r => updateSelectedBeatmap(beatmapNoDebounce);
|
||||||
dependencies.CacheAs<IBindable<RulesetInfo>>(Ruleset);
|
Ruleset.ValueChanged += r => base.Ruleset.Value = r;
|
||||||
|
|
||||||
if (Footer != null)
|
if (Footer != null)
|
||||||
{
|
{
|
||||||
@ -277,7 +286,7 @@ namespace osu.Game.Screens.Select
|
|||||||
// If selecting new beatmap without bypassing filters failed, there's possibly a ruleset mismatch
|
// If selecting new beatmap without bypassing filters failed, there's possibly a ruleset mismatch
|
||||||
if (beatmap?.BeatmapInfo?.Ruleset != null && beatmap.BeatmapInfo.Ruleset != Ruleset.Value)
|
if (beatmap?.BeatmapInfo?.Ruleset != null && beatmap.BeatmapInfo.Ruleset != Ruleset.Value)
|
||||||
{
|
{
|
||||||
Ruleset.Value = beatmap.BeatmapInfo.Ruleset;
|
base.Ruleset.Value = beatmap.BeatmapInfo.Ruleset;
|
||||||
Carousel.SelectBeatmap(beatmap.BeatmapInfo);
|
Carousel.SelectBeatmap(beatmap.BeatmapInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -295,18 +304,25 @@ namespace osu.Game.Screens.Select
|
|||||||
|
|
||||||
void performLoad()
|
void performLoad()
|
||||||
{
|
{
|
||||||
|
WorkingBeatmap working = Beatmap.Value;
|
||||||
|
bool preview = false;
|
||||||
|
|
||||||
// We may be arriving here due to another component changing the bindable Beatmap.
|
// We may be arriving here due to another component changing the bindable Beatmap.
|
||||||
// In these cases, the other component has already loaded the beatmap, so we don't need to do so again.
|
// In these cases, the other component has already loaded the beatmap, so we don't need to do so again.
|
||||||
if (beatmap?.Equals(Beatmap.Value.BeatmapInfo) != true)
|
if (beatmap?.Equals(Beatmap.Value.BeatmapInfo) != true)
|
||||||
{
|
{
|
||||||
bool preview = beatmap?.BeatmapSetInfoID != Beatmap.Value?.BeatmapInfo.BeatmapSetInfoID;
|
preview = beatmap?.BeatmapSetInfoID != Beatmap.Value?.BeatmapInfo.BeatmapSetInfoID;
|
||||||
|
working = beatmaps.GetWorkingBeatmap(beatmap, Beatmap.Value);
|
||||||
Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmap, Beatmap.Value);
|
|
||||||
ensurePlayingSelected(preview);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
working.Mods.Value = Enumerable.Empty<Mod>();
|
||||||
|
|
||||||
|
Beatmap.Value = working;
|
||||||
Ruleset.Value = ruleset;
|
Ruleset.Value = ruleset;
|
||||||
|
|
||||||
|
ensurePlayingSelected(preview);
|
||||||
|
|
||||||
UpdateBeatmap(Beatmap.Value);
|
UpdateBeatmap(Beatmap.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,8 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
protected override void ParseLine(SkinConfiguration skin, Section section, string line)
|
protected override void ParseLine(SkinConfiguration skin, Section section, string line)
|
||||||
{
|
{
|
||||||
|
line = StripComments(line);
|
||||||
|
|
||||||
switch (section)
|
switch (section)
|
||||||
{
|
{
|
||||||
case Section.General:
|
case Section.General:
|
||||||
|
@ -1,19 +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.Platform;
|
|
||||||
|
|
||||||
namespace osu.Game.Tests.Platform
|
|
||||||
{
|
|
||||||
public class TestStorage : DesktopStorage
|
|
||||||
{
|
|
||||||
public TestStorage(string baseName) : base(baseName, null)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string GetDatabaseConnectionString(string name)
|
|
||||||
{
|
|
||||||
return "DataSource=:memory:";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +1,12 @@
|
|||||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
using osu.Framework.Configuration;
|
using osu.Framework.Configuration;
|
||||||
|
using osu.Framework.Platform;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
@ -20,6 +22,9 @@ namespace osu.Game.Tests.Visual
|
|||||||
|
|
||||||
protected DependencyContainer Dependencies { get; private set; }
|
protected DependencyContainer Dependencies { get; private set; }
|
||||||
|
|
||||||
|
private readonly Lazy<Storage> localStorage;
|
||||||
|
protected Storage LocalStorage => localStorage.Value;
|
||||||
|
|
||||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||||
{
|
{
|
||||||
Dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
Dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
||||||
@ -33,6 +38,11 @@ namespace osu.Game.Tests.Visual
|
|||||||
return Dependencies;
|
return Dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected OsuTestCase()
|
||||||
|
{
|
||||||
|
localStorage = new Lazy<Storage>(() => new DesktopStorage($"{GetType().Name}-{Guid.NewGuid()}", null));
|
||||||
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(AudioManager audioManager, RulesetStore rulesets)
|
private void load(AudioManager audioManager, RulesetStore rulesets)
|
||||||
{
|
{
|
||||||
@ -50,6 +60,9 @@ namespace osu.Game.Tests.Visual
|
|||||||
beatmap.Disabled = true;
|
beatmap.Disabled = true;
|
||||||
beatmap.Value.Track.Stop();
|
beatmap.Value.Track.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (localStorage.IsValueCreated)
|
||||||
|
localStorage.Value.DeleteDirectory(".");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override ITestCaseTestRunner CreateRunner() => new OsuTestCaseTestRunner();
|
protected override ITestCaseTestRunner CreateRunner() => new OsuTestCaseTestRunner();
|
||||||
|
@ -43,7 +43,7 @@ namespace osu.Game.Users
|
|||||||
|
|
||||||
country = value;
|
country = value;
|
||||||
|
|
||||||
if (IsLoaded)
|
if (LoadState >= LoadState.Ready)
|
||||||
sprite.Texture = getFlagTexture();
|
sprite.Texture = getFlagTexture();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user