mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 10:18:22 +08:00
Merge branch 'master' into directory-select-screen
This commit is contained in:
commit
d75ef160e8
@ -52,6 +52,6 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.422.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.510.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.513.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
@ -28,10 +28,12 @@ namespace osu.Game.Rulesets.Catch.Mods
|
||||
catchPlayfield.CatcherArea.MovableCatcher.CatchFruitOnPlate = false;
|
||||
}
|
||||
|
||||
protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void ApplyNormalVisibilityState(DrawableHitObject hitObject, ArmedState state)
|
||||
{
|
||||
base.ApplyNormalVisibilityState(hitObject, state);
|
||||
|
||||
if (!(hitObject is DrawableCatchHitObject catchDrawable))
|
||||
return;
|
||||
|
||||
@ -54,7 +56,7 @@ namespace osu.Game.Rulesets.Catch.Mods
|
||||
var offset = hitObject.TimePreempt * fade_out_offset_multiplier;
|
||||
var duration = offset - hitObject.TimePreempt * fade_out_duration_multiplier;
|
||||
|
||||
using (drawable.BeginAbsoluteSequence(hitObject.StartTime - offset, true))
|
||||
using (drawable.BeginAbsoluteSequence(hitObject.StartTime - offset))
|
||||
drawable.FadeOut(duration);
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
explosion = new LegacyRollingCounter(skin, LegacyFont.Combo)
|
||||
explosion = new LegacyRollingCounter(LegacyFont.Combo)
|
||||
{
|
||||
Alpha = 0.65f,
|
||||
Blending = BlendingParameters.Additive,
|
||||
@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
||||
Origin = Anchor.Centre,
|
||||
Scale = new Vector2(1.5f),
|
||||
},
|
||||
counter = new LegacyRollingCounter(skin, LegacyFont.Combo)
|
||||
counter = new LegacyRollingCounter(LegacyFont.Combo)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
|
@ -8,6 +8,7 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Mods
|
||||
@ -39,5 +40,13 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void ApplyNormalVisibilityState(DrawableHitObject hitObject, ArmedState state)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Osu.Edit.Checks;
|
||||
@ -224,12 +225,14 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks
|
||||
|
||||
private void assertOk(IBeatmap beatmap)
|
||||
{
|
||||
Assert.That(check.Run(beatmap, new TestWorkingBeatmap(beatmap)), Is.Empty);
|
||||
var context = new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap));
|
||||
Assert.That(check.Run(context), Is.Empty);
|
||||
}
|
||||
|
||||
private void assertOffscreenCircle(IBeatmap beatmap)
|
||||
{
|
||||
var issues = check.Run(beatmap, new TestWorkingBeatmap(beatmap)).ToList();
|
||||
var context = new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap));
|
||||
var issues = check.Run(context).ToList();
|
||||
|
||||
Assert.That(issues, Has.Count.EqualTo(1));
|
||||
Assert.That(issues.Single().Template is CheckOffscreenObjects.IssueTemplateOffscreenCircle);
|
||||
@ -237,7 +240,8 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks
|
||||
|
||||
private void assertOffscreenSlider(IBeatmap beatmap)
|
||||
{
|
||||
var issues = check.Run(beatmap, new TestWorkingBeatmap(beatmap)).ToList();
|
||||
var context = new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap));
|
||||
var issues = check.Run(context).ToList();
|
||||
|
||||
Assert.That(issues, Has.Count.EqualTo(1));
|
||||
Assert.That(issues.Single().Template is CheckOffscreenObjects.IssueTemplateOffscreenSlider);
|
||||
|
@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
|
||||
hitCircle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||
|
||||
Child = new SkinProvidingContainer(new DefaultSkin())
|
||||
Child = new SkinProvidingContainer(new DefaultSkin(null))
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = drawableHitCircle = new DrawableHitCircle(hitCircle)
|
||||
|
@ -2,7 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Checks.Components;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osuTK;
|
||||
@ -31,9 +31,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Checks
|
||||
new IssueTemplateOffscreenSlider(this)
|
||||
};
|
||||
|
||||
public IEnumerable<Issue> Run(IBeatmap playableBeatmap, IWorkingBeatmap workingBeatmap)
|
||||
public IEnumerable<Issue> Run(BeatmapVerifierContext context)
|
||||
{
|
||||
foreach (var hitobject in playableBeatmap.HitObjects)
|
||||
foreach (var hitobject in context.Beatmap.HitObjects)
|
||||
{
|
||||
switch (hitobject)
|
||||
{
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Checks.Components;
|
||||
using osu.Game.Rulesets.Osu.Edit.Checks;
|
||||
@ -17,9 +16,9 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
new CheckOffscreenObjects()
|
||||
};
|
||||
|
||||
public IEnumerable<Issue> Run(IBeatmap playableBeatmap, WorkingBeatmap workingBeatmap)
|
||||
public IEnumerable<Issue> Run(BeatmapVerifierContext context)
|
||||
{
|
||||
return checks.SelectMany(check => check.Run(playableBeatmap, workingBeatmap));
|
||||
return checks.SelectMany(check => check.Run(context));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,13 +43,11 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
|
||||
protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state)
|
||||
{
|
||||
base.ApplyIncreasedVisibilityState(hitObject, state);
|
||||
applyState(hitObject, true);
|
||||
}
|
||||
|
||||
protected override void ApplyNormalVisibilityState(DrawableHitObject hitObject, ArmedState state)
|
||||
{
|
||||
base.ApplyNormalVisibilityState(hitObject, state);
|
||||
applyState(hitObject, false);
|
||||
}
|
||||
|
||||
@ -60,20 +58,20 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
|
||||
OsuHitObject hitObject = drawableOsuObject.HitObject;
|
||||
|
||||
(double startTime, double duration) fadeOut = getFadeOutParameters(drawableOsuObject);
|
||||
(double fadeStartTime, double fadeDuration) = getFadeOutParameters(drawableOsuObject);
|
||||
|
||||
switch (drawableObject)
|
||||
{
|
||||
case DrawableSliderTail _:
|
||||
using (drawableObject.BeginAbsoluteSequence(fadeOut.startTime, true))
|
||||
drawableObject.FadeOut(fadeOut.duration);
|
||||
using (drawableObject.BeginAbsoluteSequence(fadeStartTime))
|
||||
drawableObject.FadeOut(fadeDuration);
|
||||
|
||||
break;
|
||||
|
||||
case DrawableSliderRepeat sliderRepeat:
|
||||
using (drawableObject.BeginAbsoluteSequence(fadeOut.startTime, true))
|
||||
using (drawableObject.BeginAbsoluteSequence(fadeStartTime))
|
||||
// only apply to circle piece – reverse arrow is not affected by hidden.
|
||||
sliderRepeat.CirclePiece.FadeOut(fadeOut.duration);
|
||||
sliderRepeat.CirclePiece.FadeOut(fadeDuration);
|
||||
|
||||
break;
|
||||
|
||||
@ -88,23 +86,23 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
else
|
||||
{
|
||||
// we don't want to see the approach circle
|
||||
using (circle.BeginAbsoluteSequence(hitObject.StartTime - hitObject.TimePreempt, true))
|
||||
using (circle.BeginAbsoluteSequence(hitObject.StartTime - hitObject.TimePreempt))
|
||||
circle.ApproachCircle.Hide();
|
||||
}
|
||||
|
||||
using (drawableObject.BeginAbsoluteSequence(fadeOut.startTime, true))
|
||||
fadeTarget.FadeOut(fadeOut.duration);
|
||||
using (drawableObject.BeginAbsoluteSequence(fadeStartTime))
|
||||
fadeTarget.FadeOut(fadeDuration);
|
||||
break;
|
||||
|
||||
case DrawableSlider slider:
|
||||
using (slider.BeginAbsoluteSequence(fadeOut.startTime, true))
|
||||
slider.Body.FadeOut(fadeOut.duration, Easing.Out);
|
||||
using (slider.BeginAbsoluteSequence(fadeStartTime))
|
||||
slider.Body.FadeOut(fadeDuration, Easing.Out);
|
||||
|
||||
break;
|
||||
|
||||
case DrawableSliderTick sliderTick:
|
||||
using (sliderTick.BeginAbsoluteSequence(fadeOut.startTime, true))
|
||||
sliderTick.FadeOut(fadeOut.duration);
|
||||
using (sliderTick.BeginAbsoluteSequence(fadeStartTime))
|
||||
sliderTick.FadeOut(fadeDuration);
|
||||
|
||||
break;
|
||||
|
||||
@ -112,14 +110,14 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
// hide elements we don't care about.
|
||||
// todo: hide background
|
||||
|
||||
using (spinner.BeginAbsoluteSequence(fadeOut.startTime, true))
|
||||
spinner.FadeOut(fadeOut.duration);
|
||||
using (spinner.BeginAbsoluteSequence(fadeStartTime))
|
||||
spinner.FadeOut(fadeDuration);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private (double startTime, double duration) getFadeOutParameters(DrawableOsuHitObject drawableObject)
|
||||
private (double fadeStartTime, double fadeDuration) getFadeOutParameters(DrawableOsuHitObject drawableObject)
|
||||
{
|
||||
switch (drawableObject)
|
||||
{
|
||||
@ -137,7 +135,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
return getParameters(drawableObject.HitObject);
|
||||
}
|
||||
|
||||
static (double startTime, double duration) getParameters(OsuHitObject hitObject)
|
||||
static (double fadeStartTime, double fadeDuration) getParameters(OsuHitObject hitObject)
|
||||
{
|
||||
var fadeOutStartTime = hitObject.StartTime - hitObject.TimePreempt + hitObject.TimeFadeIn;
|
||||
var fadeOutDuration = hitObject.TimePreempt * fade_out_duration_multiplier;
|
||||
|
@ -76,7 +76,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
||||
Scale = new Vector2(SPRITE_SCALE),
|
||||
Y = SPINNER_TOP_OFFSET + 115,
|
||||
},
|
||||
bonusCounter = new LegacySpriteText(source, LegacyFont.Score)
|
||||
bonusCounter = new LegacySpriteText(LegacyFont.Score)
|
||||
{
|
||||
Alpha = 0f,
|
||||
Anchor = Anchor.TopCentre,
|
||||
@ -92,7 +92,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
||||
Scale = new Vector2(SPRITE_SCALE),
|
||||
Position = new Vector2(-87, 445 + spm_hide_offset),
|
||||
},
|
||||
spmCounter = new LegacySpriteText(source, LegacyFont.Score)
|
||||
spmCounter = new LegacySpriteText(LegacyFont.Score)
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopRight,
|
||||
|
@ -100,7 +100,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
||||
if (!this.HasFont(LegacyFont.HitCircle))
|
||||
return null;
|
||||
|
||||
return new LegacySpriteText(Source, LegacyFont.HitCircle)
|
||||
return new LegacySpriteText(LegacyFont.HitCircle)
|
||||
{
|
||||
// stable applies a blanket 0.8x scale to hitcircle fonts
|
||||
Scale = new Vector2(0.8f),
|
||||
|
@ -60,7 +60,7 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
|
||||
var hitWindows = new OsuHitWindows();
|
||||
foreach (var result in Enum.GetValues(typeof(HitResult)).OfType<HitResult>().Where(r => r > HitResult.None && hitWindows.IsHitResultAllowed(r)))
|
||||
poolDictionary.Add(result, new DrawableJudgementPool(result, onJudgmentLoaded));
|
||||
poolDictionary.Add(result, new DrawableJudgementPool(result, onJudgementLoaded));
|
||||
|
||||
AddRangeInternal(poolDictionary.Values);
|
||||
|
||||
@ -102,7 +102,7 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
}
|
||||
}
|
||||
|
||||
private void onJudgmentLoaded(DrawableOsuJudgement judgement)
|
||||
private void onJudgementLoaded(DrawableOsuJudgement judgement)
|
||||
{
|
||||
judgementAboveHitObjectLayer.Add(judgement.GetProxyAboveHitObjectsContent());
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.Taiko.Skinning.Legacy;
|
||||
using osu.Game.Skinning;
|
||||
@ -27,7 +28,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning
|
||||
}));
|
||||
|
||||
AddToggleStep("Toggle passing", passing => this.ChildrenOfType<LegacyTaikoScroller>().ForEach(s => s.LastResult.Value =
|
||||
new JudgementResult(null, new Judgement()) { Type = passing ? HitResult.Great : HitResult.Miss }));
|
||||
new JudgementResult(new HitObject(), new Judgement()) { Type = passing ? HitResult.Great : HitResult.Miss }));
|
||||
|
||||
AddToggleStep("toggle playback direction", reversed => this.reversed = reversed);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Mods
|
||||
{
|
||||
@ -10,5 +11,13 @@ namespace osu.Game.Rulesets.Taiko.Mods
|
||||
public override string Description => @"Beats fade out before you hit them!";
|
||||
public override double ScoreMultiplier => 1.06;
|
||||
public override bool HasImplementation => false;
|
||||
|
||||
protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void ApplyNormalVisibilityState(DrawableHitObject hitObject, ArmedState state)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
@ -12,6 +14,7 @@ namespace osu.Game.Rulesets.Taiko.Mods
|
||||
public class TaikoModRandom : ModRandom, IApplicableToBeatmap
|
||||
{
|
||||
public override string Description => @"Shuffle around the colours!";
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(TaikoModSwap)).ToArray();
|
||||
|
||||
public void ApplyToBeatmap(IBeatmap beatmap)
|
||||
{
|
||||
|
33
osu.Game.Rulesets.Taiko/Mods/TaikoModSwap.cs
Normal file
33
osu.Game.Rulesets.Taiko/Mods/TaikoModSwap.cs
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Taiko.Beatmaps;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Mods
|
||||
{
|
||||
public class TaikoModSwap : Mod, IApplicableToBeatmap
|
||||
{
|
||||
public override string Name => "Swap";
|
||||
public override string Acronym => "SW";
|
||||
public override string Description => @"Dons become kats, kats become dons";
|
||||
public override ModType Type => ModType.Conversion;
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModRandom)).ToArray();
|
||||
|
||||
public void ApplyToBeatmap(IBeatmap beatmap)
|
||||
{
|
||||
var taikoBeatmap = (TaikoBeatmap)beatmap;
|
||||
|
||||
foreach (var obj in taikoBeatmap.HitObjects)
|
||||
{
|
||||
if (obj is Hit hit)
|
||||
hit.Type = hit.Type == HitType.Centre ? HitType.Rim : HitType.Centre;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
||||
base.Update();
|
||||
|
||||
// store X before checking wide enough so if we perform layout there is no positional discrepancy.
|
||||
float currentX = (InternalChildren?.FirstOrDefault()?.X ?? 0) - (float)Clock.ElapsedFrameTime * 0.1f;
|
||||
float currentX = (InternalChildren.FirstOrDefault()?.X ?? 0) - (float)Clock.ElapsedFrameTime * 0.1f;
|
||||
|
||||
// ensure we have enough sprites
|
||||
if (!InternalChildren.Any()
|
||||
|
@ -136,6 +136,7 @@ namespace osu.Game.Rulesets.Taiko
|
||||
new TaikoModRandom(),
|
||||
new TaikoModDifficultyAdjust(),
|
||||
new TaikoModClassic(),
|
||||
new TaikoModSwap(),
|
||||
};
|
||||
|
||||
case ModType.Automation:
|
||||
|
@ -12,6 +12,7 @@ using osu.Framework.Platform;
|
||||
using osu.Game.IPC;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Database;
|
||||
@ -264,7 +265,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
|
||||
// change filename
|
||||
var firstFile = new FileInfo(Directory.GetFiles(extractedFolder).First());
|
||||
firstFile.MoveTo(Path.Combine(firstFile.DirectoryName, $"{firstFile.Name}-changed{firstFile.Extension}"));
|
||||
firstFile.MoveTo(Path.Combine(firstFile.DirectoryName.AsNonNull(), $"{firstFile.Name}-changed{firstFile.Extension}"));
|
||||
|
||||
using (var zip = ZipArchive.Create())
|
||||
{
|
||||
|
@ -6,6 +6,7 @@ using Moq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Checks;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
|
||||
@ -40,23 +41,23 @@ namespace osu.Game.Tests.Editing.Checks
|
||||
mock.SetupGet(w => w.Beatmap).Returns(beatmap);
|
||||
mock.SetupGet(w => w.Track).Returns((Track)null);
|
||||
|
||||
Assert.That(check.Run(beatmap, mock.Object), Is.Empty);
|
||||
Assert.That(check.Run(new BeatmapVerifierContext(beatmap, mock.Object)), Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAcceptable()
|
||||
{
|
||||
var mock = getMockWorkingBeatmap(192);
|
||||
var context = getContext(192);
|
||||
|
||||
Assert.That(check.Run(beatmap, mock.Object), Is.Empty);
|
||||
Assert.That(check.Run(context), Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNullBitrate()
|
||||
{
|
||||
var mock = getMockWorkingBeatmap(null);
|
||||
var context = getContext(null);
|
||||
|
||||
var issues = check.Run(beatmap, mock.Object).ToList();
|
||||
var issues = check.Run(context).ToList();
|
||||
|
||||
Assert.That(issues, Has.Count.EqualTo(1));
|
||||
Assert.That(issues.Single().Template is CheckAudioQuality.IssueTemplateNoBitrate);
|
||||
@ -65,9 +66,9 @@ namespace osu.Game.Tests.Editing.Checks
|
||||
[Test]
|
||||
public void TestZeroBitrate()
|
||||
{
|
||||
var mock = getMockWorkingBeatmap(0);
|
||||
var context = getContext(0);
|
||||
|
||||
var issues = check.Run(beatmap, mock.Object).ToList();
|
||||
var issues = check.Run(context).ToList();
|
||||
|
||||
Assert.That(issues, Has.Count.EqualTo(1));
|
||||
Assert.That(issues.Single().Template is CheckAudioQuality.IssueTemplateNoBitrate);
|
||||
@ -76,9 +77,9 @@ namespace osu.Game.Tests.Editing.Checks
|
||||
[Test]
|
||||
public void TestTooHighBitrate()
|
||||
{
|
||||
var mock = getMockWorkingBeatmap(320);
|
||||
var context = getContext(320);
|
||||
|
||||
var issues = check.Run(beatmap, mock.Object).ToList();
|
||||
var issues = check.Run(context).ToList();
|
||||
|
||||
Assert.That(issues, Has.Count.EqualTo(1));
|
||||
Assert.That(issues.Single().Template is CheckAudioQuality.IssueTemplateTooHighBitrate);
|
||||
@ -87,14 +88,19 @@ namespace osu.Game.Tests.Editing.Checks
|
||||
[Test]
|
||||
public void TestTooLowBitrate()
|
||||
{
|
||||
var mock = getMockWorkingBeatmap(64);
|
||||
var context = getContext(64);
|
||||
|
||||
var issues = check.Run(beatmap, mock.Object).ToList();
|
||||
var issues = check.Run(context).ToList();
|
||||
|
||||
Assert.That(issues, Has.Count.EqualTo(1));
|
||||
Assert.That(issues.Single().Template is CheckAudioQuality.IssueTemplateTooLowBitrate);
|
||||
}
|
||||
|
||||
private BeatmapVerifierContext getContext(int? audioBitrate)
|
||||
{
|
||||
return new BeatmapVerifierContext(beatmap, getMockWorkingBeatmap(audioBitrate).Object);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the mock of the working beatmap with the given audio properties.
|
||||
/// </summary>
|
||||
|
@ -9,6 +9,7 @@ using Moq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Checks;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using FileInfo = osu.Game.IO.FileInfo;
|
||||
@ -53,25 +54,25 @@ namespace osu.Game.Tests.Editing.Checks
|
||||
{
|
||||
// While this is a problem, it is out of scope for this check and is caught by a different one.
|
||||
beatmap.Metadata.BackgroundFile = null;
|
||||
var mock = getMockWorkingBeatmap(null, System.Array.Empty<byte>());
|
||||
var context = getContext(null, System.Array.Empty<byte>());
|
||||
|
||||
Assert.That(check.Run(beatmap, mock.Object), Is.Empty);
|
||||
Assert.That(check.Run(context), Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAcceptable()
|
||||
{
|
||||
var mock = getMockWorkingBeatmap(new Texture(1920, 1080));
|
||||
var context = getContext(new Texture(1920, 1080));
|
||||
|
||||
Assert.That(check.Run(beatmap, mock.Object), Is.Empty);
|
||||
Assert.That(check.Run(context), Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTooHighResolution()
|
||||
{
|
||||
var mock = getMockWorkingBeatmap(new Texture(3840, 2160));
|
||||
var context = getContext(new Texture(3840, 2160));
|
||||
|
||||
var issues = check.Run(beatmap, mock.Object).ToList();
|
||||
var issues = check.Run(context).ToList();
|
||||
|
||||
Assert.That(issues, Has.Count.EqualTo(1));
|
||||
Assert.That(issues.Single().Template is CheckBackgroundQuality.IssueTemplateTooHighResolution);
|
||||
@ -80,9 +81,9 @@ namespace osu.Game.Tests.Editing.Checks
|
||||
[Test]
|
||||
public void TestLowResolution()
|
||||
{
|
||||
var mock = getMockWorkingBeatmap(new Texture(640, 480));
|
||||
var context = getContext(new Texture(640, 480));
|
||||
|
||||
var issues = check.Run(beatmap, mock.Object).ToList();
|
||||
var issues = check.Run(context).ToList();
|
||||
|
||||
Assert.That(issues, Has.Count.EqualTo(1));
|
||||
Assert.That(issues.Single().Template is CheckBackgroundQuality.IssueTemplateLowResolution);
|
||||
@ -91,9 +92,9 @@ namespace osu.Game.Tests.Editing.Checks
|
||||
[Test]
|
||||
public void TestTooLowResolution()
|
||||
{
|
||||
var mock = getMockWorkingBeatmap(new Texture(100, 100));
|
||||
var context = getContext(new Texture(100, 100));
|
||||
|
||||
var issues = check.Run(beatmap, mock.Object).ToList();
|
||||
var issues = check.Run(context).ToList();
|
||||
|
||||
Assert.That(issues, Has.Count.EqualTo(1));
|
||||
Assert.That(issues.Single().Template is CheckBackgroundQuality.IssueTemplateTooLowResolution);
|
||||
@ -102,14 +103,19 @@ namespace osu.Game.Tests.Editing.Checks
|
||||
[Test]
|
||||
public void TestTooUncompressed()
|
||||
{
|
||||
var mock = getMockWorkingBeatmap(new Texture(1920, 1080), new byte[1024 * 1024 * 3]);
|
||||
var context = getContext(new Texture(1920, 1080), new byte[1024 * 1024 * 3]);
|
||||
|
||||
var issues = check.Run(beatmap, mock.Object).ToList();
|
||||
var issues = check.Run(context).ToList();
|
||||
|
||||
Assert.That(issues, Has.Count.EqualTo(1));
|
||||
Assert.That(issues.Single().Template is CheckBackgroundQuality.IssueTemplateTooUncompressed);
|
||||
}
|
||||
|
||||
private BeatmapVerifierContext getContext(Texture background, [CanBeNull] byte[] fileBytes = null)
|
||||
{
|
||||
return new BeatmapVerifierContext(beatmap, getMockWorkingBeatmap(background, fileBytes).Object);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the mock of the working beatmap with the given background and filesize.
|
||||
/// </summary>
|
||||
|
@ -6,11 +6,13 @@ using System.Linq;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Checks;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
|
||||
namespace osu.Game.Tests.Editing.Checks
|
||||
{
|
||||
@ -105,7 +107,7 @@ namespace osu.Game.Tests.Editing.Checks
|
||||
new HitCircle { StartTime = 300 }
|
||||
};
|
||||
|
||||
var issues = check.Run(getPlayableBeatmap(hitobjects), null).ToList();
|
||||
var issues = check.Run(getContext(hitobjects)).ToList();
|
||||
|
||||
Assert.That(issues, Has.Count.EqualTo(3));
|
||||
Assert.That(issues.Where(issue => issue.Template is CheckConcurrentObjects.IssueTemplateConcurrentDifferent).ToList(), Has.Count.EqualTo(2));
|
||||
@ -164,12 +166,12 @@ namespace osu.Game.Tests.Editing.Checks
|
||||
|
||||
private void assertOk(List<HitObject> hitobjects)
|
||||
{
|
||||
Assert.That(check.Run(getPlayableBeatmap(hitobjects), null), Is.Empty);
|
||||
Assert.That(check.Run(getContext(hitobjects)), Is.Empty);
|
||||
}
|
||||
|
||||
private void assertConcurrentSame(List<HitObject> hitobjects, int count = 1)
|
||||
{
|
||||
var issues = check.Run(getPlayableBeatmap(hitobjects), null).ToList();
|
||||
var issues = check.Run(getContext(hitobjects)).ToList();
|
||||
|
||||
Assert.That(issues, Has.Count.EqualTo(count));
|
||||
Assert.That(issues.All(issue => issue.Template is CheckConcurrentObjects.IssueTemplateConcurrentSame));
|
||||
@ -177,18 +179,16 @@ namespace osu.Game.Tests.Editing.Checks
|
||||
|
||||
private void assertConcurrentDifferent(List<HitObject> hitobjects, int count = 1)
|
||||
{
|
||||
var issues = check.Run(getPlayableBeatmap(hitobjects), null).ToList();
|
||||
var issues = check.Run(getContext(hitobjects)).ToList();
|
||||
|
||||
Assert.That(issues, Has.Count.EqualTo(count));
|
||||
Assert.That(issues.All(issue => issue.Template is CheckConcurrentObjects.IssueTemplateConcurrentDifferent));
|
||||
}
|
||||
|
||||
private IBeatmap getPlayableBeatmap(List<HitObject> hitobjects)
|
||||
private BeatmapVerifierContext getContext(List<HitObject> hitobjects)
|
||||
{
|
||||
return new Beatmap<HitObject>
|
||||
{
|
||||
HitObjects = hitobjects
|
||||
};
|
||||
var beatmap = new Beatmap<HitObject> { HitObjects = hitobjects };
|
||||
return new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.IO;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Checks;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
@ -45,7 +46,8 @@ namespace osu.Game.Tests.Editing.Checks
|
||||
[Test]
|
||||
public void TestBackgroundSetAndInFiles()
|
||||
{
|
||||
Assert.That(check.Run(beatmap, new TestWorkingBeatmap(beatmap)), Is.Empty);
|
||||
var context = new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap));
|
||||
Assert.That(check.Run(context), Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -53,7 +55,8 @@ namespace osu.Game.Tests.Editing.Checks
|
||||
{
|
||||
beatmap.BeatmapInfo.BeatmapSet.Files.Clear();
|
||||
|
||||
var issues = check.Run(beatmap, new TestWorkingBeatmap(beatmap)).ToList();
|
||||
var context = new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap));
|
||||
var issues = check.Run(context).ToList();
|
||||
|
||||
Assert.That(issues, Has.Count.EqualTo(1));
|
||||
Assert.That(issues.Single().Template is CheckFilePresence.IssueTemplateDoesNotExist);
|
||||
@ -64,7 +67,8 @@ namespace osu.Game.Tests.Editing.Checks
|
||||
{
|
||||
beatmap.Metadata.BackgroundFile = null;
|
||||
|
||||
var issues = check.Run(beatmap, new TestWorkingBeatmap(beatmap)).ToList();
|
||||
var context = new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap));
|
||||
var issues = check.Run(context).ToList();
|
||||
|
||||
Assert.That(issues, Has.Count.EqualTo(1));
|
||||
Assert.That(issues.Single().Template is CheckFilePresence.IssueTemplateNoneSet);
|
||||
|
@ -7,10 +7,12 @@ using Moq;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Checks;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
|
||||
namespace osu.Game.Tests.Editing.Checks
|
||||
{
|
||||
@ -100,12 +102,12 @@ namespace osu.Game.Tests.Editing.Checks
|
||||
}, count: 2);
|
||||
|
||||
// Start and end are 2 ms and 1.25 ms off respectively, hence two different issues in one object.
|
||||
var hitobjects = new List<HitObject>
|
||||
var hitObjects = new List<HitObject>
|
||||
{
|
||||
getSliderMock(startTime: 98, endTime: 398.75d).Object
|
||||
};
|
||||
|
||||
var issues = check.Run(getPlayableBeatmap(hitobjects), null).ToList();
|
||||
var issues = check.Run(getContext(hitObjects)).ToList();
|
||||
|
||||
Assert.That(issues, Has.Count.EqualTo(2));
|
||||
Assert.That(issues.Any(issue => issue.Template is CheckUnsnappedObjects.IssueTemplateSmallUnsnap));
|
||||
@ -122,34 +124,36 @@ namespace osu.Game.Tests.Editing.Checks
|
||||
return mockSlider;
|
||||
}
|
||||
|
||||
private void assertOk(List<HitObject> hitobjects)
|
||||
private void assertOk(List<HitObject> hitObjects)
|
||||
{
|
||||
Assert.That(check.Run(getPlayableBeatmap(hitobjects), null), Is.Empty);
|
||||
Assert.That(check.Run(getContext(hitObjects)), Is.Empty);
|
||||
}
|
||||
|
||||
private void assert1Ms(List<HitObject> hitobjects, int count = 1)
|
||||
private void assert1Ms(List<HitObject> hitObjects, int count = 1)
|
||||
{
|
||||
var issues = check.Run(getPlayableBeatmap(hitobjects), null).ToList();
|
||||
var issues = check.Run(getContext(hitObjects)).ToList();
|
||||
|
||||
Assert.That(issues, Has.Count.EqualTo(count));
|
||||
Assert.That(issues.All(issue => issue.Template is CheckUnsnappedObjects.IssueTemplateSmallUnsnap));
|
||||
}
|
||||
|
||||
private void assert2Ms(List<HitObject> hitobjects, int count = 1)
|
||||
private void assert2Ms(List<HitObject> hitObjects, int count = 1)
|
||||
{
|
||||
var issues = check.Run(getPlayableBeatmap(hitobjects), null).ToList();
|
||||
var issues = check.Run(getContext(hitObjects)).ToList();
|
||||
|
||||
Assert.That(issues, Has.Count.EqualTo(count));
|
||||
Assert.That(issues.All(issue => issue.Template is CheckUnsnappedObjects.IssueTemplateLargeUnsnap));
|
||||
}
|
||||
|
||||
private IBeatmap getPlayableBeatmap(List<HitObject> hitobjects)
|
||||
private BeatmapVerifierContext getContext(List<HitObject> hitObjects)
|
||||
{
|
||||
return new Beatmap<HitObject>
|
||||
var beatmap = new Beatmap<HitObject>
|
||||
{
|
||||
ControlPointInfo = cpi,
|
||||
HitObjects = hitobjects
|
||||
HitObjects = hitObjects
|
||||
};
|
||||
|
||||
return new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ namespace osu.Game.Tests.Mods
|
||||
if (isValid)
|
||||
Assert.IsNull(invalid);
|
||||
else
|
||||
Assert.That(invalid?.Select(t => t.GetType()), Is.EquivalentTo(expectedInvalid));
|
||||
Assert.That(invalid.Select(t => t.GetType()), Is.EquivalentTo(expectedInvalid));
|
||||
}
|
||||
|
||||
public abstract class CustomMod1 : Mod
|
||||
|
@ -4,6 +4,7 @@
|
||||
using System.Linq;
|
||||
using Humanizer;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Tests.Visual.Multiplayer;
|
||||
@ -34,7 +35,7 @@ namespace osu.Game.Tests.NonVisual.Multiplayer
|
||||
changeState(6, MultiplayerUserState.WaitingForLoad);
|
||||
checkPlayingUserCount(6);
|
||||
|
||||
AddStep("another user left", () => Client.RemoveUser(Client.Room?.Users.Last().User));
|
||||
AddStep("another user left", () => Client.RemoveUser((Client.Room?.Users.Last().User).AsNonNull()));
|
||||
checkPlayingUserCount(5);
|
||||
|
||||
AddStep("leave room", () => Client.LeaveRoom());
|
||||
|
@ -167,5 +167,21 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
AddStep("move mouse away", () => InputManager.MoveMouseTo(selectionBox, new Vector2(20)));
|
||||
AddUntilStep("rotation handle hidden", () => rotationHandle.Alpha == 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that hovering over two handles instantaneously from one to another does not crash or cause issues to the visibility state.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestHoverOverTwoHandlesInstantaneously()
|
||||
{
|
||||
AddStep("hover over top-left scale handle", () =>
|
||||
InputManager.MoveMouseTo(this.ChildrenOfType<SelectionBoxScaleHandle>().Single(s => s.Anchor == Anchor.TopLeft)));
|
||||
AddStep("hover over top-right scale handle", () =>
|
||||
InputManager.MoveMouseTo(this.ChildrenOfType<SelectionBoxScaleHandle>().Single(s => s.Anchor == Anchor.TopRight)));
|
||||
AddUntilStep("top-left rotation handle hidden", () =>
|
||||
this.ChildrenOfType<SelectionBoxRotationHandle>().Single(r => r.Anchor == Anchor.TopLeft).Alpha == 0);
|
||||
AddUntilStep("top-right rotation handle shown", () =>
|
||||
this.ChildrenOfType<SelectionBoxRotationHandle>().Single(r => r.Anchor == Anchor.TopRight).Alpha == 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +1,18 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
public class TestSceneComboCounter : SkinnableTestScene
|
||||
{
|
||||
private IEnumerable<SkinnableComboCounter> comboCounters => CreatedDrawables.OfType<SkinnableComboCounter>();
|
||||
|
||||
protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset();
|
||||
|
||||
[Cached]
|
||||
@ -25,7 +21,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
[SetUpSteps]
|
||||
public void SetUpSteps()
|
||||
{
|
||||
AddStep("Create combo counters", () => SetContents(() => new SkinnableComboCounter()));
|
||||
AddStep("Create combo counters", () => SetContents(() => new SkinnableDrawable(new HUDSkinComponent(HUDSkinComponents.ComboCounter))));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -2,10 +2,12 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Skinning.Editor;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
@ -14,12 +16,17 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
private SkinEditor skinEditor;
|
||||
|
||||
[Resolved]
|
||||
private SkinManager skinManager { get; set; }
|
||||
|
||||
protected override bool Autoplay => true;
|
||||
|
||||
[SetUpSteps]
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
AddStep("add editor overlay", () =>
|
||||
AddStep("reload skin editor", () =>
|
||||
{
|
||||
skinEditor?.Expire();
|
||||
Player.ScaleTo(SkinEditorOverlay.VISIBLE_TARGET_SCALE);
|
||||
|
@ -1,13 +1,11 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Screens.Play;
|
||||
@ -32,12 +30,13 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
SetContents(() =>
|
||||
{
|
||||
var ruleset = new OsuRuleset();
|
||||
var mods = new[] { ruleset.GetAutoplayMod() };
|
||||
var working = CreateWorkingBeatmap(ruleset.RulesetInfo);
|
||||
var beatmap = working.GetPlayableBeatmap(ruleset.RulesetInfo);
|
||||
var beatmap = working.GetPlayableBeatmap(ruleset.RulesetInfo, mods);
|
||||
|
||||
var drawableRuleset = ruleset.CreateDrawableRulesetWith(beatmap);
|
||||
var drawableRuleset = ruleset.CreateDrawableRulesetWith(beatmap, mods);
|
||||
|
||||
var hudOverlay = new HUDOverlay(drawableRuleset, Array.Empty<Mod>())
|
||||
var hudOverlay = new HUDOverlay(drawableRuleset, mods)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
|
@ -7,7 +7,7 @@ using osu.Framework.Testing;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
@ -22,7 +22,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
public void SetUpSteps()
|
||||
{
|
||||
AddStep("Set initial accuracy", () => scoreProcessor.Accuracy.Value = 1);
|
||||
AddStep("Create accuracy counters", () => SetContents(() => new SkinnableAccuracyCounter()));
|
||||
AddStep("Create accuracy counters", () => SetContents(() => new SkinnableDrawable(new HUDSkinComponent(HUDSkinComponents.AccuracyCounter))));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Testing;
|
||||
@ -12,14 +10,12 @@ using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Judgements;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
public class TestSceneSkinnableHealthDisplay : SkinnableTestScene
|
||||
{
|
||||
private IEnumerable<SkinnableHealthDisplay> healthDisplays => CreatedDrawables.OfType<SkinnableHealthDisplay>();
|
||||
|
||||
protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset();
|
||||
|
||||
[Cached(typeof(HealthProcessor))]
|
||||
@ -28,10 +24,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
[SetUpSteps]
|
||||
public void SetUpSteps()
|
||||
{
|
||||
AddStep("Create health displays", () =>
|
||||
{
|
||||
SetContents(() => new SkinnableHealthDisplay());
|
||||
});
|
||||
AddStep("Create health displays", () => SetContents(() => new SkinnableDrawable(new HUDSkinComponent(HUDSkinComponents.HealthDisplay))));
|
||||
AddStep(@"Reset all", delegate
|
||||
{
|
||||
healthProcessor.Health.Value = 1;
|
||||
|
@ -1,23 +1,18 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
public class TestSceneSkinnableScoreCounter : SkinnableTestScene
|
||||
{
|
||||
private IEnumerable<SkinnableScoreCounter> scoreCounters => CreatedDrawables.OfType<SkinnableScoreCounter>();
|
||||
|
||||
protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset();
|
||||
|
||||
[Cached]
|
||||
@ -26,7 +21,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
[SetUpSteps]
|
||||
public void SetUpSteps()
|
||||
{
|
||||
AddStep("Create score counters", () => SetContents(() => new SkinnableScoreCounter()));
|
||||
AddStep("Create score counters", () => SetContents(() => new SkinnableDrawable(new HUDSkinComponent(HUDSkinComponents.ScoreCounter))));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -40,7 +35,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
[Test]
|
||||
public void TestVeryLargeScore()
|
||||
{
|
||||
AddStep("set large score", () => scoreCounters.ForEach(counter => scoreProcessor.TotalScore.Value = 1_000_000_000));
|
||||
AddStep("set large score", () => scoreProcessor.TotalScore.Value = 1_000_000_000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddStep("set user ready", () => client.ChangeState(MultiplayerUserState.Ready));
|
||||
AddStep("delete beatmap", () => beatmaps.Delete(importedSet));
|
||||
|
||||
AddAssert("user state is idle", () => client.LocalUser?.State == MultiplayerUserState.Idle);
|
||||
AddUntilStep("user state is idle", () => client.LocalUser?.State == MultiplayerUserState.Idle);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -13,6 +13,7 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
@ -45,14 +46,14 @@ namespace osu.Game.Tests.Visual.Online
|
||||
switch (args.Action)
|
||||
{
|
||||
case NotifyCollectionChangedAction.Add:
|
||||
args.NewItems.Cast<Mod>().ForEach(mod => selectedMods.Add(new OsuSpriteText
|
||||
args.NewItems.AsNonNull().Cast<Mod>().ForEach(mod => selectedMods.Add(new OsuSpriteText
|
||||
{
|
||||
Text = mod.Acronym,
|
||||
}));
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Remove:
|
||||
args.OldItems.Cast<Mod>().ForEach(mod =>
|
||||
args.OldItems.AsNonNull().Cast<Mod>().ForEach(mod =>
|
||||
{
|
||||
foreach (var selected in selectedMods)
|
||||
{
|
||||
|
@ -11,11 +11,13 @@ using osu.Framework.Platform;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Screens.OnlinePlay;
|
||||
using osu.Game.Screens.OnlinePlay.Playlists;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
using osu.Game.Users;
|
||||
using osuTK.Input;
|
||||
@ -24,8 +26,6 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
{
|
||||
public class TestScenePlaylistsRoomSubScreen : RoomTestScene
|
||||
{
|
||||
protected override bool UseOnlineAPI => true;
|
||||
|
||||
[Cached(typeof(IRoomManager))]
|
||||
private readonly TestRoomManager roomManager = new TestRoomManager();
|
||||
|
||||
@ -41,6 +41,18 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, host, Beatmap.Default));
|
||||
|
||||
manager.Import(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo.BeatmapSet).Wait();
|
||||
|
||||
((DummyAPIAccess)API).HandleRequest = req =>
|
||||
{
|
||||
switch (req)
|
||||
{
|
||||
case CreateRoomScoreRequest createRoomScoreRequest:
|
||||
createRoomScoreRequest.TriggerSuccess(new APIScoreToken { ID = 1 });
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
[SetUpSteps]
|
||||
@ -59,12 +71,16 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
Room.Name.Value = "my awesome room";
|
||||
Room.Host.Value = new User { Id = 2, Username = "peppy" };
|
||||
Room.RecentParticipants.Add(Room.Host.Value);
|
||||
Room.EndDate.Value = DateTimeOffset.Now.AddMinutes(5);
|
||||
Room.Playlist.Add(new PlaylistItem
|
||||
{
|
||||
Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo },
|
||||
Ruleset = { Value = new OsuRuleset().RulesetInfo }
|
||||
});
|
||||
});
|
||||
|
||||
AddStep("start match", () => match.ChildrenOfType<PlaylistsReadyButton>().First().Click());
|
||||
AddUntilStep("player loader loaded", () => Stack.CurrentScreen is PlayerLoader);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -1,32 +1,65 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Screens.Ranking.Expanded;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Ranking
|
||||
{
|
||||
public class TestSceneStarRatingDisplay : OsuTestScene
|
||||
{
|
||||
public TestSceneStarRatingDisplay()
|
||||
[Test]
|
||||
public void TestDisplay()
|
||||
{
|
||||
Child = new FillFlowContainer
|
||||
AddStep("load displays", () => Child = new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Children = new Drawable[]
|
||||
ChildrenEnumerable = new[]
|
||||
{
|
||||
new StarRatingDisplay(new StarDifficulty(1.23, 0)),
|
||||
new StarRatingDisplay(new StarDifficulty(2.34, 0)),
|
||||
new StarRatingDisplay(new StarDifficulty(3.45, 0)),
|
||||
new StarRatingDisplay(new StarDifficulty(4.56, 0)),
|
||||
new StarRatingDisplay(new StarDifficulty(5.67, 0)),
|
||||
new StarRatingDisplay(new StarDifficulty(6.78, 0)),
|
||||
new StarRatingDisplay(new StarDifficulty(10.11, 0)),
|
||||
}
|
||||
};
|
||||
1.23,
|
||||
2.34,
|
||||
3.45,
|
||||
4.56,
|
||||
5.67,
|
||||
6.78,
|
||||
10.11,
|
||||
}.Select(starRating => new StarRatingDisplay(new StarDifficulty(starRating, 0))
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestChangingStarRatingDisplay()
|
||||
{
|
||||
StarRatingDisplay starRating = null;
|
||||
|
||||
AddStep("load display", () => Child = starRating = new StarRatingDisplay(new StarDifficulty(5.55, 1))
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Scale = new Vector2(3f),
|
||||
});
|
||||
|
||||
AddRepeatStep("set random value", () =>
|
||||
{
|
||||
starRating.Current.Value = new StarDifficulty(RNG.NextDouble(0.0, 11.0), 1);
|
||||
}, 10);
|
||||
|
||||
AddSliderStep("set exact stars", 0.0, 11.0, 5.55, d =>
|
||||
{
|
||||
if (starRating != null)
|
||||
starRating.Current.Value = new StarDifficulty(d, 1);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,151 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.Play;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.SongSelect
|
||||
{
|
||||
public class TestSceneBeatmapMetadataDisplay : OsuTestScene
|
||||
{
|
||||
private BeatmapMetadataDisplay display;
|
||||
|
||||
[Resolved]
|
||||
private BeatmapManager manager { get; set; }
|
||||
|
||||
[Cached(typeof(BeatmapDifficultyCache))]
|
||||
private readonly TestBeatmapDifficultyCache testDifficultyCache = new TestBeatmapDifficultyCache();
|
||||
|
||||
[Test]
|
||||
public void TestLocal([Values("Beatmap", "Some long title and stuff")]
|
||||
string title,
|
||||
[Values("Trial", "Some1's very hardest difficulty")]
|
||||
string version)
|
||||
{
|
||||
showMetadataForBeatmap(() => CreateWorkingBeatmap(new Beatmap
|
||||
{
|
||||
BeatmapInfo =
|
||||
{
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = title,
|
||||
},
|
||||
Version = version,
|
||||
StarDifficulty = RNG.NextDouble(0, 10),
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDelayedStarRating()
|
||||
{
|
||||
AddStep("block calculation", () => testDifficultyCache.BlockCalculation = true);
|
||||
|
||||
showMetadataForBeatmap(() => CreateWorkingBeatmap(new Beatmap
|
||||
{
|
||||
BeatmapInfo =
|
||||
{
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = "Heavy beatmap",
|
||||
},
|
||||
Version = "10k objects",
|
||||
StarDifficulty = 99.99f,
|
||||
}
|
||||
}));
|
||||
|
||||
AddStep("allow calculation", () => testDifficultyCache.BlockCalculation = false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRandomFromDatabase()
|
||||
{
|
||||
showMetadataForBeatmap(() =>
|
||||
{
|
||||
var allBeatmapSets = manager.GetAllUsableBeatmapSets(IncludedDetails.Minimal);
|
||||
if (allBeatmapSets.Count == 0)
|
||||
return manager.DefaultBeatmap;
|
||||
|
||||
var randomBeatmapSet = allBeatmapSets[RNG.Next(0, allBeatmapSets.Count - 1)];
|
||||
var randomBeatmap = randomBeatmapSet.Beatmaps[RNG.Next(0, randomBeatmapSet.Beatmaps.Count - 1)];
|
||||
|
||||
return manager.GetWorkingBeatmap(randomBeatmap);
|
||||
});
|
||||
}
|
||||
|
||||
private void showMetadataForBeatmap(Func<WorkingBeatmap> getBeatmap)
|
||||
{
|
||||
AddStep("setup display", () =>
|
||||
{
|
||||
var randomMods = Ruleset.Value.CreateInstance().GetAllMods().OrderBy(_ => RNG.Next()).Take(5).ToList();
|
||||
|
||||
OsuLogo logo = new OsuLogo { Scale = new Vector2(0.15f) };
|
||||
|
||||
Remove(testDifficultyCache);
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
testDifficultyCache,
|
||||
display = new BeatmapMetadataDisplay(getBeatmap(), new Bindable<IReadOnlyList<Mod>>(randomMods), logo)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Alpha = 0f,
|
||||
}
|
||||
};
|
||||
|
||||
display.FadeIn(400, Easing.OutQuint);
|
||||
});
|
||||
|
||||
AddWaitStep("wait a bit", 5);
|
||||
|
||||
AddStep("finish loading", () => display.Loading = false);
|
||||
}
|
||||
|
||||
private class TestBeatmapDifficultyCache : BeatmapDifficultyCache
|
||||
{
|
||||
private TaskCompletionSource<bool> calculationBlocker;
|
||||
|
||||
private bool blockCalculation;
|
||||
|
||||
public bool BlockCalculation
|
||||
{
|
||||
get => blockCalculation;
|
||||
set
|
||||
{
|
||||
if (value == blockCalculation)
|
||||
return;
|
||||
|
||||
blockCalculation = value;
|
||||
|
||||
if (value)
|
||||
calculationBlocker = new TaskCompletionSource<bool>();
|
||||
else
|
||||
calculationBlocker?.SetResult(false);
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<StarDifficulty> GetDifficultyAsync(BeatmapInfo beatmapInfo, RulesetInfo rulesetInfo = null, IEnumerable<Mod> mods = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (blockCalculation)
|
||||
await calculationBlocker.Task;
|
||||
|
||||
return await base.GetDifficultyAsync(beatmapInfo, rulesetInfo, mods, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -264,7 +264,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
|
||||
private void moveLogoFacade()
|
||||
{
|
||||
if (!(logoFacade?.Transforms).Any() && !(transferContainer?.Transforms).Any())
|
||||
if (!logoFacade.Transforms.Any() && !transferContainer.Transforms.Any())
|
||||
{
|
||||
Random random = new Random();
|
||||
trackingContainer.Delay(500).MoveTo(new Vector2(random.Next(0, (int)logo.Parent.DrawWidth), random.Next(0, (int)logo.Parent.DrawHeight)), 300);
|
||||
|
@ -7,6 +7,7 @@ using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.Win32;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Threading;
|
||||
@ -77,8 +78,8 @@ namespace osu.Game.Tournament.IPC
|
||||
using (var stream = IPCStorage.GetStream(file_ipc_filename))
|
||||
using (var sr = new StreamReader(stream))
|
||||
{
|
||||
var beatmapId = int.Parse(sr.ReadLine());
|
||||
var mods = int.Parse(sr.ReadLine());
|
||||
var beatmapId = int.Parse(sr.ReadLine().AsNonNull());
|
||||
var mods = int.Parse(sr.ReadLine().AsNonNull());
|
||||
|
||||
if (lastBeatmapId != beatmapId)
|
||||
{
|
||||
@ -124,7 +125,7 @@ namespace osu.Game.Tournament.IPC
|
||||
using (var stream = IPCStorage.GetStream(file_ipc_state_filename))
|
||||
using (var sr = new StreamReader(stream))
|
||||
{
|
||||
State.Value = (TourneyState)Enum.Parse(typeof(TourneyState), sr.ReadLine());
|
||||
State.Value = (TourneyState)Enum.Parse(typeof(TourneyState), sr.ReadLine().AsNonNull());
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
|
@ -103,8 +103,8 @@ namespace osu.Game.Beatmaps
|
||||
/// <param name="mods">The <see cref="Mod"/>s to get the difficulty with.</param>
|
||||
/// <param name="cancellationToken">An optional <see cref="CancellationToken"/> which stops computing the star difficulty.</param>
|
||||
/// <returns>The <see cref="StarDifficulty"/>.</returns>
|
||||
public Task<StarDifficulty> GetDifficultyAsync([NotNull] BeatmapInfo beatmapInfo, [CanBeNull] RulesetInfo rulesetInfo = null, [CanBeNull] IEnumerable<Mod> mods = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
public virtual Task<StarDifficulty> GetDifficultyAsync([NotNull] BeatmapInfo beatmapInfo, [CanBeNull] RulesetInfo rulesetInfo = null,
|
||||
[CanBeNull] IEnumerable<Mod> mods = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// In the case that the user hasn't given us a ruleset, use the beatmap's default ruleset.
|
||||
rulesetInfo ??= beatmapInfo.Ruleset;
|
||||
|
@ -7,6 +7,7 @@ using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.IO.Serialization;
|
||||
@ -127,6 +128,8 @@ namespace osu.Game.Beatmaps
|
||||
// Metadata
|
||||
public string Version { get; set; }
|
||||
|
||||
private string versionString => string.IsNullOrEmpty(Version) ? string.Empty : $"[{Version}]";
|
||||
|
||||
[JsonProperty("difficulty_rating")]
|
||||
public double StarDifficulty { get; set; }
|
||||
|
||||
@ -143,11 +146,12 @@ namespace osu.Game.Beatmaps
|
||||
Version
|
||||
}.Concat(Metadata?.SearchableTerms ?? Enumerable.Empty<string>()).Where(s => !string.IsNullOrEmpty(s)).ToArray();
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string version = string.IsNullOrEmpty(Version) ? string.Empty : $"[{Version}]";
|
||||
public override string ToString() => $"{Metadata ?? BeatmapSet?.Metadata} {versionString}".Trim();
|
||||
|
||||
return $"{Metadata ?? BeatmapSet?.Metadata} {version}".Trim();
|
||||
public RomanisableString ToRomanisableString()
|
||||
{
|
||||
var metadata = (Metadata ?? BeatmapSet?.Metadata)?.ToRomanisableString() ?? new RomanisableString(null, null);
|
||||
return new RomanisableString($"{metadata.GetPreferred(true)} {versionString}".Trim(), $"{metadata.GetPreferred(false)} {versionString}".Trim());
|
||||
}
|
||||
|
||||
public bool Equals(BeatmapInfo other)
|
||||
|
@ -2,7 +2,6 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
@ -83,6 +82,12 @@ namespace osu.Game.Beatmaps
|
||||
beatmap.BeatmapSet.OnlineBeatmapSetID = res.OnlineBeatmapSetID;
|
||||
beatmap.OnlineBeatmapID = res.OnlineBeatmapID;
|
||||
|
||||
if (beatmap.Metadata != null)
|
||||
beatmap.Metadata.AuthorID = res.AuthorID;
|
||||
|
||||
if (beatmap.BeatmapSet.Metadata != null)
|
||||
beatmap.BeatmapSet.Metadata.AuthorID = res.AuthorID;
|
||||
|
||||
LogForModel(set, $"Online retrieval mapped {beatmap} to {res.OnlineBeatmapSetID} / {res.OnlineBeatmapID}.");
|
||||
}
|
||||
}
|
||||
@ -157,7 +162,7 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
using (var cmd = db.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = "SELECT beatmapset_id, beatmap_id, approved FROM osu_beatmaps WHERE checksum = @MD5Hash OR beatmap_id = @OnlineBeatmapID OR filename = @Path";
|
||||
cmd.CommandText = "SELECT beatmapset_id, beatmap_id, approved, user_id FROM osu_beatmaps WHERE checksum = @MD5Hash OR beatmap_id = @OnlineBeatmapID OR filename = @Path";
|
||||
|
||||
cmd.Parameters.Add(new SqliteParameter("@MD5Hash", beatmap.MD5Hash));
|
||||
cmd.Parameters.Add(new SqliteParameter("@OnlineBeatmapID", beatmap.OnlineBeatmapID ?? (object)DBNull.Value));
|
||||
@ -174,6 +179,12 @@ namespace osu.Game.Beatmaps
|
||||
beatmap.BeatmapSet.OnlineBeatmapSetID = reader.GetInt32(0);
|
||||
beatmap.OnlineBeatmapID = reader.GetInt32(1);
|
||||
|
||||
if (beatmap.Metadata != null)
|
||||
beatmap.Metadata.AuthorID = reader.GetInt32(3);
|
||||
|
||||
if (beatmap.BeatmapSet.Metadata != null)
|
||||
beatmap.BeatmapSet.Metadata.AuthorID = reader.GetInt32(3);
|
||||
|
||||
LogForModel(set, $"Cached local retrieval for {beatmap}.");
|
||||
return true;
|
||||
}
|
||||
@ -194,17 +205,6 @@ namespace osu.Game.Beatmaps
|
||||
cacheDownloadRequest?.Dispose();
|
||||
updateScheduler?.Dispose();
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
private class CachedOnlineBeatmapLookup
|
||||
{
|
||||
public int approved { get; set; }
|
||||
|
||||
public int? beatmapset_id { get; set; }
|
||||
|
||||
public int? beatmap_id { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Users;
|
||||
@ -34,6 +35,21 @@ namespace osu.Game.Beatmaps
|
||||
[JsonIgnore]
|
||||
public List<BeatmapSetInfo> BeatmapSets { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Helper property to deserialize a username to <see cref="User"/>.
|
||||
/// </summary>
|
||||
[JsonProperty(@"user_id")]
|
||||
[Column("AuthorID")]
|
||||
public int AuthorID
|
||||
{
|
||||
get => Author?.Id ?? 1;
|
||||
set
|
||||
{
|
||||
Author ??= new User();
|
||||
Author.Id = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper property to deserialize a username to <see cref="User"/>.
|
||||
/// </summary>
|
||||
@ -42,7 +58,11 @@ namespace osu.Game.Beatmaps
|
||||
public string AuthorString
|
||||
{
|
||||
get => Author?.Username;
|
||||
set => Author = new User { Username = value };
|
||||
set
|
||||
{
|
||||
Author ??= new User();
|
||||
Author.Username = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -71,6 +91,12 @@ namespace osu.Game.Beatmaps
|
||||
return $"{Artist} - {Title} {author}".Trim();
|
||||
}
|
||||
|
||||
public RomanisableString ToRomanisableString()
|
||||
{
|
||||
string author = Author == null ? string.Empty : $"({Author})";
|
||||
return new RomanisableString($"{ArtistUnicode} - {TitleUnicode} {author}".Trim(), $"{Artist} - {Title} {author}".Trim());
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public string[] SearchableTerms => new[]
|
||||
{
|
||||
|
@ -324,7 +324,7 @@ namespace osu.Game.Beatmaps
|
||||
public bool SkinLoaded => skin.IsResultAvailable;
|
||||
public ISkin Skin => skin.Value;
|
||||
|
||||
protected virtual ISkin GetSkin() => new DefaultSkin();
|
||||
protected virtual ISkin GetSkin() => new DefaultSkin(null);
|
||||
private readonly RecyclableLazy<ISkin> skin;
|
||||
|
||||
public abstract Stream GetStream(string storagePath);
|
||||
|
@ -472,7 +472,7 @@ namespace osu.Game.Database
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delete new file.
|
||||
/// Delete an existing file.
|
||||
/// </summary>
|
||||
/// <param name="model">The item to operate on.</param>
|
||||
/// <param name="file">The existing file to be deleted.</param>
|
||||
|
@ -3,8 +3,10 @@
|
||||
|
||||
using System;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Extensions
|
||||
@ -43,5 +45,23 @@ namespace osu.Game.Extensions
|
||||
/// <returns>The delta vector in Parent's coordinates.</returns>
|
||||
public static Vector2 ScreenSpaceDeltaToParentSpace(this Drawable drawable, Vector2 delta) =>
|
||||
drawable.Parent.ToLocalSpace(drawable.Parent.ToScreenSpace(Vector2.Zero) + delta);
|
||||
|
||||
public static SkinnableInfo CreateSkinnableInfo(this Drawable component) => new SkinnableInfo(component);
|
||||
|
||||
public static void ApplySkinnableInfo(this Drawable component, SkinnableInfo info)
|
||||
{
|
||||
// todo: can probably make this better via deserialisation directly using a common interface.
|
||||
component.Position = info.Position;
|
||||
component.Rotation = info.Rotation;
|
||||
component.Scale = info.Scale;
|
||||
component.Anchor = info.Anchor;
|
||||
component.Origin = info.Origin;
|
||||
|
||||
if (component is Container container)
|
||||
{
|
||||
foreach (var child in info.Children)
|
||||
container.Add(child.CreateInstance());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
|
||||
namespace osu.Game.Extensions
|
||||
{
|
||||
@ -50,7 +51,7 @@ namespace osu.Game.Extensions
|
||||
}
|
||||
else if (continuationTask.IsFaulted)
|
||||
{
|
||||
tcs.TrySetException(continuationTask.Exception);
|
||||
tcs.TrySetException(continuationTask.Exception.AsNonNull());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
31
osu.Game/Extensions/TypeExtensions.cs
Normal file
31
osu.Game/Extensions/TypeExtensions.cs
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace osu.Game.Extensions
|
||||
{
|
||||
internal static class TypeExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns <paramref name="type"/>'s <see cref="Type.AssemblyQualifiedName"/>
|
||||
/// with the assembly version, culture and public key token values removed.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method is usually used in extensibility scenarios (i.e. for custom rulesets or skins)
|
||||
/// when a version-agnostic identifier associated with a C# class - potentially originating from
|
||||
/// an external assembly - is needed.
|
||||
/// Leaving only the type and assembly names in such a scenario allows to preserve compatibility
|
||||
/// across assembly versions.
|
||||
/// </remarks>
|
||||
internal static string GetInvariantInstantiationInfo(this Type type)
|
||||
{
|
||||
string assemblyQualifiedName = type.AssemblyQualifiedName;
|
||||
if (assemblyQualifiedName == null)
|
||||
throw new ArgumentException($"{type}'s assembly-qualified name is null. Ensure that it is a concrete type and not a generic type parameter.", nameof(type));
|
||||
|
||||
return string.Join(',', assemblyQualifiedName.Split(',').Take(2));
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,10 @@ using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Graphics.Containers
|
||||
@ -59,6 +62,14 @@ namespace osu.Game.Graphics.Containers
|
||||
public void AddLink(string text, LinkAction action, string argument, string tooltipText = null, Action<SpriteText> creationParameters = null)
|
||||
=> createLink(AddText(text, creationParameters), new LinkDetails(action, argument), tooltipText);
|
||||
|
||||
public void AddLink(LocalisableString text, LinkAction action, string argument, string tooltipText = null, Action<SpriteText> creationParameters = null)
|
||||
{
|
||||
var spriteText = new OsuSpriteText { Text = text };
|
||||
|
||||
AddText(spriteText, creationParameters);
|
||||
createLink(spriteText.Yield(), new LinkDetails(action, argument), tooltipText);
|
||||
}
|
||||
|
||||
public void AddLink(IEnumerable<SpriteText> text, LinkAction action = LinkAction.External, string linkArgument = null, string tooltipText = null)
|
||||
{
|
||||
foreach (var t in text)
|
||||
|
18
osu.Game/Graphics/UserInterface/DangerousTriangleButton.cs
Normal file
18
osu.Game/Graphics/UserInterface/DangerousTriangleButton.cs
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
|
||||
namespace osu.Game.Graphics.UserInterface
|
||||
{
|
||||
public class DangerousTriangleButton : TriangleButton
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
BackgroundColour = colours.PinkDark;
|
||||
Triangles.ColourDark = colours.PinkDarker;
|
||||
Triangles.ColourLight = colours.Pink;
|
||||
}
|
||||
}
|
||||
}
|
@ -38,6 +38,7 @@ namespace osu.Game.IO.Legacy
|
||||
/// <summary> Reads a string from the buffer. Overrides the base implementation so it can cope with nulls. </summary>
|
||||
public override string ReadString()
|
||||
{
|
||||
// ReSharper disable once AssignNullToNotNullAttribute
|
||||
if (ReadByte() == 0) return null;
|
||||
|
||||
return base.ReadString();
|
||||
|
@ -5,6 +5,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
|
||||
namespace osu.Game.IO.Serialization.Converters
|
||||
{
|
||||
@ -60,7 +61,7 @@ namespace osu.Game.IO.Serialization.Converters
|
||||
throw new JsonException("Expected $type token.");
|
||||
|
||||
var typeName = lookupTable[(int)tok["$type"]];
|
||||
var instance = (T)Activator.CreateInstance(Type.GetType(typeName));
|
||||
var instance = (T)Activator.CreateInstance(Type.GetType(typeName).AsNonNull());
|
||||
serializer.Populate(itemReader, instance);
|
||||
|
||||
list.Add(instance);
|
||||
|
@ -48,7 +48,7 @@ namespace osu.Game.Input.Bindings
|
||||
new KeyBinding(new[] { InputKey.Control, InputKey.O }, GlobalAction.ToggleSettings),
|
||||
new KeyBinding(new[] { InputKey.Control, InputKey.D }, GlobalAction.ToggleBeatmapListing),
|
||||
new KeyBinding(new[] { InputKey.Control, InputKey.N }, GlobalAction.ToggleNotifications),
|
||||
new KeyBinding(new[] { InputKey.Shift, InputKey.F2 }, GlobalAction.ToggleSkinEditor),
|
||||
new KeyBinding(new[] { InputKey.Control, InputKey.Shift, InputKey.S }, GlobalAction.ToggleSkinEditor),
|
||||
|
||||
new KeyBinding(InputKey.Escape, GlobalAction.Back),
|
||||
new KeyBinding(InputKey.ExtraMouseButton1, GlobalAction.Back),
|
||||
|
508
osu.Game/Migrations/20210511060743_AddSkinInstantiationInfo.Designer.cs
generated
Normal file
508
osu.Game/Migrations/20210511060743_AddSkinInstantiationInfo.Designer.cs
generated
Normal file
@ -0,0 +1,508 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using osu.Game.Database;
|
||||
|
||||
namespace osu.Game.Migrations
|
||||
{
|
||||
[DbContext(typeof(OsuDbContext))]
|
||||
[Migration("20210511060743_AddSkinInstantiationInfo")]
|
||||
partial class AddSkinInstantiationInfo
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "2.2.6-servicing-10079");
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<float>("ApproachRate");
|
||||
|
||||
b.Property<float>("CircleSize");
|
||||
|
||||
b.Property<float>("DrainRate");
|
||||
|
||||
b.Property<float>("OverallDifficulty");
|
||||
|
||||
b.Property<double>("SliderMultiplier");
|
||||
|
||||
b.Property<double>("SliderTickRate");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.ToTable("BeatmapDifficulty");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<double>("AudioLeadIn");
|
||||
|
||||
b.Property<double>("BPM");
|
||||
|
||||
b.Property<int>("BaseDifficultyID");
|
||||
|
||||
b.Property<int>("BeatDivisor");
|
||||
|
||||
b.Property<int>("BeatmapSetInfoID");
|
||||
|
||||
b.Property<bool>("Countdown");
|
||||
|
||||
b.Property<double>("DistanceSpacing");
|
||||
|
||||
b.Property<bool>("EpilepsyWarning");
|
||||
|
||||
b.Property<int>("GridSize");
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<bool>("Hidden");
|
||||
|
||||
b.Property<double>("Length");
|
||||
|
||||
b.Property<bool>("LetterboxInBreaks");
|
||||
|
||||
b.Property<string>("MD5Hash");
|
||||
|
||||
b.Property<int?>("MetadataID");
|
||||
|
||||
b.Property<int?>("OnlineBeatmapID");
|
||||
|
||||
b.Property<string>("Path");
|
||||
|
||||
b.Property<int>("RulesetID");
|
||||
|
||||
b.Property<bool>("SpecialStyle");
|
||||
|
||||
b.Property<float>("StackLeniency");
|
||||
|
||||
b.Property<double>("StarDifficulty");
|
||||
|
||||
b.Property<int>("Status");
|
||||
|
||||
b.Property<string>("StoredBookmarks");
|
||||
|
||||
b.Property<double>("TimelineZoom");
|
||||
|
||||
b.Property<string>("Version");
|
||||
|
||||
b.Property<bool>("WidescreenStoryboard");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("BaseDifficultyID");
|
||||
|
||||
b.HasIndex("BeatmapSetInfoID");
|
||||
|
||||
b.HasIndex("Hash");
|
||||
|
||||
b.HasIndex("MD5Hash");
|
||||
|
||||
b.HasIndex("MetadataID");
|
||||
|
||||
b.HasIndex("OnlineBeatmapID")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("RulesetID");
|
||||
|
||||
b.ToTable("BeatmapInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapMetadata", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Artist");
|
||||
|
||||
b.Property<string>("ArtistUnicode");
|
||||
|
||||
b.Property<string>("AudioFile");
|
||||
|
||||
b.Property<string>("AuthorString")
|
||||
.HasColumnName("Author");
|
||||
|
||||
b.Property<string>("BackgroundFile");
|
||||
|
||||
b.Property<int>("PreviewTime");
|
||||
|
||||
b.Property<string>("Source");
|
||||
|
||||
b.Property<string>("Tags");
|
||||
|
||||
b.Property<string>("Title");
|
||||
|
||||
b.Property<string>("TitleUnicode");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.ToTable("BeatmapMetadata");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("BeatmapSetInfoID");
|
||||
|
||||
b.Property<int>("FileInfoID");
|
||||
|
||||
b.Property<string>("Filename")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("BeatmapSetInfoID");
|
||||
|
||||
b.HasIndex("FileInfoID");
|
||||
|
||||
b.ToTable("BeatmapSetFileInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<DateTimeOffset>("DateAdded");
|
||||
|
||||
b.Property<bool>("DeletePending");
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<int?>("MetadataID");
|
||||
|
||||
b.Property<int?>("OnlineBeatmapSetID");
|
||||
|
||||
b.Property<bool>("Protected");
|
||||
|
||||
b.Property<int>("Status");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("DeletePending");
|
||||
|
||||
b.HasIndex("Hash")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("MetadataID");
|
||||
|
||||
b.HasIndex("OnlineBeatmapSetID")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("BeatmapSetInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Key")
|
||||
.HasColumnName("Key");
|
||||
|
||||
b.Property<int?>("RulesetID");
|
||||
|
||||
b.Property<int?>("SkinInfoID");
|
||||
|
||||
b.Property<string>("StringValue")
|
||||
.HasColumnName("Value");
|
||||
|
||||
b.Property<int?>("Variant");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("SkinInfoID");
|
||||
|
||||
b.HasIndex("RulesetID", "Variant");
|
||||
|
||||
b.ToTable("Settings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.IO.FileInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<int>("ReferenceCount");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("Hash")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("ReferenceCount");
|
||||
|
||||
b.ToTable("FileInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("IntAction")
|
||||
.HasColumnName("Action");
|
||||
|
||||
b.Property<string>("KeysString")
|
||||
.HasColumnName("Keys");
|
||||
|
||||
b.Property<int?>("RulesetID");
|
||||
|
||||
b.Property<int?>("Variant");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("IntAction");
|
||||
|
||||
b.HasIndex("RulesetID", "Variant");
|
||||
|
||||
b.ToTable("KeyBinding");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b =>
|
||||
{
|
||||
b.Property<int?>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<bool>("Available");
|
||||
|
||||
b.Property<string>("InstantiationInfo");
|
||||
|
||||
b.Property<string>("Name");
|
||||
|
||||
b.Property<string>("ShortName");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("Available");
|
||||
|
||||
b.HasIndex("ShortName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("RulesetInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("FileInfoID");
|
||||
|
||||
b.Property<string>("Filename")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<int?>("ScoreInfoID");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("FileInfoID");
|
||||
|
||||
b.HasIndex("ScoreInfoID");
|
||||
|
||||
b.ToTable("ScoreFileInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<double>("Accuracy")
|
||||
.HasColumnType("DECIMAL(1,4)");
|
||||
|
||||
b.Property<int>("BeatmapInfoID");
|
||||
|
||||
b.Property<int>("Combo");
|
||||
|
||||
b.Property<DateTimeOffset>("Date");
|
||||
|
||||
b.Property<bool>("DeletePending");
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<int>("MaxCombo");
|
||||
|
||||
b.Property<string>("ModsJson")
|
||||
.HasColumnName("Mods");
|
||||
|
||||
b.Property<long?>("OnlineScoreID");
|
||||
|
||||
b.Property<double?>("PP");
|
||||
|
||||
b.Property<int>("Rank");
|
||||
|
||||
b.Property<int>("RulesetID");
|
||||
|
||||
b.Property<string>("StatisticsJson")
|
||||
.HasColumnName("Statistics");
|
||||
|
||||
b.Property<long>("TotalScore");
|
||||
|
||||
b.Property<int?>("UserID")
|
||||
.HasColumnName("UserID");
|
||||
|
||||
b.Property<string>("UserString")
|
||||
.HasColumnName("User");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("BeatmapInfoID");
|
||||
|
||||
b.HasIndex("OnlineScoreID")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("RulesetID");
|
||||
|
||||
b.ToTable("ScoreInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("FileInfoID");
|
||||
|
||||
b.Property<string>("Filename")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<int>("SkinInfoID");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("FileInfoID");
|
||||
|
||||
b.HasIndex("SkinInfoID");
|
||||
|
||||
b.ToTable("SkinFileInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Skinning.SkinInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Creator");
|
||||
|
||||
b.Property<bool>("DeletePending");
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<string>("InstantiationInfo");
|
||||
|
||||
b.Property<string>("Name");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("DeletePending");
|
||||
|
||||
b.HasIndex("Hash")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("SkinInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty")
|
||||
.WithMany()
|
||||
.HasForeignKey("BaseDifficultyID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet")
|
||||
.WithMany("Beatmaps")
|
||||
.HasForeignKey("BeatmapSetInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata")
|
||||
.WithMany("Beatmaps")
|
||||
.HasForeignKey("MetadataID");
|
||||
|
||||
b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset")
|
||||
.WithMany()
|
||||
.HasForeignKey("RulesetID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo")
|
||||
.WithMany("Files")
|
||||
.HasForeignKey("BeatmapSetInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
|
||||
.WithMany()
|
||||
.HasForeignKey("FileInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata")
|
||||
.WithMany("BeatmapSets")
|
||||
.HasForeignKey("MetadataID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Skinning.SkinInfo")
|
||||
.WithMany("Settings")
|
||||
.HasForeignKey("SkinInfoID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
|
||||
.WithMany()
|
||||
.HasForeignKey("FileInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Scoring.ScoreInfo")
|
||||
.WithMany("Files")
|
||||
.HasForeignKey("ScoreInfoID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "Beatmap")
|
||||
.WithMany("Scores")
|
||||
.HasForeignKey("BeatmapInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset")
|
||||
.WithMany()
|
||||
.HasForeignKey("RulesetID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
|
||||
.WithMany()
|
||||
.HasForeignKey("FileInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Skinning.SkinInfo")
|
||||
.WithMany("Files")
|
||||
.HasForeignKey("SkinInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace osu.Game.Migrations
|
||||
{
|
||||
public partial class AddSkinInstantiationInfo : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "InstantiationInfo",
|
||||
table: "SkinInfo",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "InstantiationInfo",
|
||||
table: "SkinInfo");
|
||||
}
|
||||
}
|
||||
}
|
511
osu.Game/Migrations/20210514062639_AddAuthorIdToBeatmapMetadata.Designer.cs
generated
Normal file
511
osu.Game/Migrations/20210514062639_AddAuthorIdToBeatmapMetadata.Designer.cs
generated
Normal file
@ -0,0 +1,511 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using osu.Game.Database;
|
||||
|
||||
namespace osu.Game.Migrations
|
||||
{
|
||||
[DbContext(typeof(OsuDbContext))]
|
||||
[Migration("20210514062639_AddAuthorIdToBeatmapMetadata")]
|
||||
partial class AddAuthorIdToBeatmapMetadata
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "2.2.6-servicing-10079");
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<float>("ApproachRate");
|
||||
|
||||
b.Property<float>("CircleSize");
|
||||
|
||||
b.Property<float>("DrainRate");
|
||||
|
||||
b.Property<float>("OverallDifficulty");
|
||||
|
||||
b.Property<double>("SliderMultiplier");
|
||||
|
||||
b.Property<double>("SliderTickRate");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.ToTable("BeatmapDifficulty");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<double>("AudioLeadIn");
|
||||
|
||||
b.Property<double>("BPM");
|
||||
|
||||
b.Property<int>("BaseDifficultyID");
|
||||
|
||||
b.Property<int>("BeatDivisor");
|
||||
|
||||
b.Property<int>("BeatmapSetInfoID");
|
||||
|
||||
b.Property<bool>("Countdown");
|
||||
|
||||
b.Property<double>("DistanceSpacing");
|
||||
|
||||
b.Property<bool>("EpilepsyWarning");
|
||||
|
||||
b.Property<int>("GridSize");
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<bool>("Hidden");
|
||||
|
||||
b.Property<double>("Length");
|
||||
|
||||
b.Property<bool>("LetterboxInBreaks");
|
||||
|
||||
b.Property<string>("MD5Hash");
|
||||
|
||||
b.Property<int?>("MetadataID");
|
||||
|
||||
b.Property<int?>("OnlineBeatmapID");
|
||||
|
||||
b.Property<string>("Path");
|
||||
|
||||
b.Property<int>("RulesetID");
|
||||
|
||||
b.Property<bool>("SpecialStyle");
|
||||
|
||||
b.Property<float>("StackLeniency");
|
||||
|
||||
b.Property<double>("StarDifficulty");
|
||||
|
||||
b.Property<int>("Status");
|
||||
|
||||
b.Property<string>("StoredBookmarks");
|
||||
|
||||
b.Property<double>("TimelineZoom");
|
||||
|
||||
b.Property<string>("Version");
|
||||
|
||||
b.Property<bool>("WidescreenStoryboard");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("BaseDifficultyID");
|
||||
|
||||
b.HasIndex("BeatmapSetInfoID");
|
||||
|
||||
b.HasIndex("Hash");
|
||||
|
||||
b.HasIndex("MD5Hash");
|
||||
|
||||
b.HasIndex("MetadataID");
|
||||
|
||||
b.HasIndex("OnlineBeatmapID")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("RulesetID");
|
||||
|
||||
b.ToTable("BeatmapInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapMetadata", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Artist");
|
||||
|
||||
b.Property<string>("ArtistUnicode");
|
||||
|
||||
b.Property<string>("AudioFile");
|
||||
|
||||
b.Property<int>("AuthorID")
|
||||
.HasColumnName("AuthorID");
|
||||
|
||||
b.Property<string>("AuthorString")
|
||||
.HasColumnName("Author");
|
||||
|
||||
b.Property<string>("BackgroundFile");
|
||||
|
||||
b.Property<int>("PreviewTime");
|
||||
|
||||
b.Property<string>("Source");
|
||||
|
||||
b.Property<string>("Tags");
|
||||
|
||||
b.Property<string>("Title");
|
||||
|
||||
b.Property<string>("TitleUnicode");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.ToTable("BeatmapMetadata");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("BeatmapSetInfoID");
|
||||
|
||||
b.Property<int>("FileInfoID");
|
||||
|
||||
b.Property<string>("Filename")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("BeatmapSetInfoID");
|
||||
|
||||
b.HasIndex("FileInfoID");
|
||||
|
||||
b.ToTable("BeatmapSetFileInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<DateTimeOffset>("DateAdded");
|
||||
|
||||
b.Property<bool>("DeletePending");
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<int?>("MetadataID");
|
||||
|
||||
b.Property<int?>("OnlineBeatmapSetID");
|
||||
|
||||
b.Property<bool>("Protected");
|
||||
|
||||
b.Property<int>("Status");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("DeletePending");
|
||||
|
||||
b.HasIndex("Hash")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("MetadataID");
|
||||
|
||||
b.HasIndex("OnlineBeatmapSetID")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("BeatmapSetInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Key")
|
||||
.HasColumnName("Key");
|
||||
|
||||
b.Property<int?>("RulesetID");
|
||||
|
||||
b.Property<int?>("SkinInfoID");
|
||||
|
||||
b.Property<string>("StringValue")
|
||||
.HasColumnName("Value");
|
||||
|
||||
b.Property<int?>("Variant");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("SkinInfoID");
|
||||
|
||||
b.HasIndex("RulesetID", "Variant");
|
||||
|
||||
b.ToTable("Settings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.IO.FileInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<int>("ReferenceCount");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("Hash")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("ReferenceCount");
|
||||
|
||||
b.ToTable("FileInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("IntAction")
|
||||
.HasColumnName("Action");
|
||||
|
||||
b.Property<string>("KeysString")
|
||||
.HasColumnName("Keys");
|
||||
|
||||
b.Property<int?>("RulesetID");
|
||||
|
||||
b.Property<int?>("Variant");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("IntAction");
|
||||
|
||||
b.HasIndex("RulesetID", "Variant");
|
||||
|
||||
b.ToTable("KeyBinding");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b =>
|
||||
{
|
||||
b.Property<int?>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<bool>("Available");
|
||||
|
||||
b.Property<string>("InstantiationInfo");
|
||||
|
||||
b.Property<string>("Name");
|
||||
|
||||
b.Property<string>("ShortName");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("Available");
|
||||
|
||||
b.HasIndex("ShortName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("RulesetInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("FileInfoID");
|
||||
|
||||
b.Property<string>("Filename")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<int?>("ScoreInfoID");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("FileInfoID");
|
||||
|
||||
b.HasIndex("ScoreInfoID");
|
||||
|
||||
b.ToTable("ScoreFileInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<double>("Accuracy")
|
||||
.HasColumnType("DECIMAL(1,4)");
|
||||
|
||||
b.Property<int>("BeatmapInfoID");
|
||||
|
||||
b.Property<int>("Combo");
|
||||
|
||||
b.Property<DateTimeOffset>("Date");
|
||||
|
||||
b.Property<bool>("DeletePending");
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<int>("MaxCombo");
|
||||
|
||||
b.Property<string>("ModsJson")
|
||||
.HasColumnName("Mods");
|
||||
|
||||
b.Property<long?>("OnlineScoreID");
|
||||
|
||||
b.Property<double?>("PP");
|
||||
|
||||
b.Property<int>("Rank");
|
||||
|
||||
b.Property<int>("RulesetID");
|
||||
|
||||
b.Property<string>("StatisticsJson")
|
||||
.HasColumnName("Statistics");
|
||||
|
||||
b.Property<long>("TotalScore");
|
||||
|
||||
b.Property<int?>("UserID")
|
||||
.HasColumnName("UserID");
|
||||
|
||||
b.Property<string>("UserString")
|
||||
.HasColumnName("User");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("BeatmapInfoID");
|
||||
|
||||
b.HasIndex("OnlineScoreID")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("RulesetID");
|
||||
|
||||
b.ToTable("ScoreInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("FileInfoID");
|
||||
|
||||
b.Property<string>("Filename")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<int>("SkinInfoID");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("FileInfoID");
|
||||
|
||||
b.HasIndex("SkinInfoID");
|
||||
|
||||
b.ToTable("SkinFileInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Skinning.SkinInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Creator");
|
||||
|
||||
b.Property<bool>("DeletePending");
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<string>("InstantiationInfo");
|
||||
|
||||
b.Property<string>("Name");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("DeletePending");
|
||||
|
||||
b.HasIndex("Hash")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("SkinInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty")
|
||||
.WithMany()
|
||||
.HasForeignKey("BaseDifficultyID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet")
|
||||
.WithMany("Beatmaps")
|
||||
.HasForeignKey("BeatmapSetInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata")
|
||||
.WithMany("Beatmaps")
|
||||
.HasForeignKey("MetadataID");
|
||||
|
||||
b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset")
|
||||
.WithMany()
|
||||
.HasForeignKey("RulesetID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo")
|
||||
.WithMany("Files")
|
||||
.HasForeignKey("BeatmapSetInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
|
||||
.WithMany()
|
||||
.HasForeignKey("FileInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata")
|
||||
.WithMany("BeatmapSets")
|
||||
.HasForeignKey("MetadataID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Skinning.SkinInfo")
|
||||
.WithMany("Settings")
|
||||
.HasForeignKey("SkinInfoID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
|
||||
.WithMany()
|
||||
.HasForeignKey("FileInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Scoring.ScoreInfo")
|
||||
.WithMany("Files")
|
||||
.HasForeignKey("ScoreInfoID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "Beatmap")
|
||||
.WithMany("Scores")
|
||||
.HasForeignKey("BeatmapInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset")
|
||||
.WithMany()
|
||||
.HasForeignKey("RulesetID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
|
||||
.WithMany()
|
||||
.HasForeignKey("FileInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Skinning.SkinInfo")
|
||||
.WithMany("Files")
|
||||
.HasForeignKey("SkinInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace osu.Game.Migrations
|
||||
{
|
||||
public partial class AddAuthorIdToBeatmapMetadata : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "AuthorID",
|
||||
table: "BeatmapMetadata",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "AuthorID",
|
||||
table: "BeatmapMetadata");
|
||||
}
|
||||
}
|
||||
}
|
@ -126,6 +126,9 @@ namespace osu.Game.Migrations
|
||||
|
||||
b.Property<string>("AudioFile");
|
||||
|
||||
b.Property<int>("AuthorID")
|
||||
.HasColumnName("AuthorID");
|
||||
|
||||
b.Property<string>("AuthorString")
|
||||
.HasColumnName("Author");
|
||||
|
||||
@ -141,8 +144,6 @@ namespace osu.Game.Migrations
|
||||
|
||||
b.Property<string>("TitleUnicode");
|
||||
|
||||
b.Property<string>("VideoFile");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.ToTable("BeatmapMetadata");
|
||||
@ -352,7 +353,7 @@ namespace osu.Game.Migrations
|
||||
|
||||
b.Property<long>("TotalScore");
|
||||
|
||||
b.Property<long?>("UserID")
|
||||
b.Property<int?>("UserID")
|
||||
.HasColumnName("UserID");
|
||||
|
||||
b.Property<string>("UserString")
|
||||
@ -402,6 +403,8 @@ namespace osu.Game.Migrations
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<string>("InstantiationInfo");
|
||||
|
||||
b.Property<string>("Name");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
@ -270,7 +270,7 @@ namespace osu.Game.Online.API
|
||||
{
|
||||
try
|
||||
{
|
||||
return JObject.Parse(req.GetResponseString()).SelectToken("form_error", true).AsNonNull().ToObject<RegistrationRequest.RegistrationRequestErrors>();
|
||||
return JObject.Parse(req.GetResponseString().AsNonNull()).SelectToken("form_error", true).AsNonNull().ToObject<RegistrationRequest.RegistrationRequestErrors>();
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
@ -24,7 +24,13 @@ namespace osu.Game.Online.Spectator
|
||||
[Key(2)]
|
||||
public IEnumerable<APIMod> Mods { get; set; } = Enumerable.Empty<APIMod>();
|
||||
|
||||
public bool Equals(SpectatorState other) => BeatmapID == other?.BeatmapID && Mods.SequenceEqual(other?.Mods) && RulesetID == other?.RulesetID;
|
||||
public bool Equals(SpectatorState other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
|
||||
return BeatmapID == other.BeatmapID && Mods.SequenceEqual(other.Mods) && RulesetID == other.RulesetID;
|
||||
}
|
||||
|
||||
public override string ToString() => $"Beatmap:{BeatmapID} Mods:{string.Join(',', Mods)} Ruleset:{RulesetID}";
|
||||
}
|
||||
|
@ -339,22 +339,13 @@ namespace osu.Game.Overlays.KeyBinding
|
||||
}
|
||||
}
|
||||
|
||||
public class ClearButton : TriangleButton
|
||||
public class ClearButton : DangerousTriangleButton
|
||||
{
|
||||
public ClearButton()
|
||||
{
|
||||
Text = "Clear";
|
||||
Size = new Vector2(80, 20);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
BackgroundColour = colours.Pink;
|
||||
|
||||
Triangles.ColourDark = colours.PinkDark;
|
||||
Triangles.ColourLight = colours.PinkLight;
|
||||
}
|
||||
}
|
||||
|
||||
public class KeyButton : Container
|
||||
|
@ -11,7 +11,6 @@ using osu.Game.Input;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Rulesets;
|
||||
using osuTK;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Overlays.KeyBinding
|
||||
{
|
||||
@ -55,10 +54,10 @@ namespace osu.Game.Overlays.KeyBinding
|
||||
}
|
||||
}
|
||||
|
||||
public class ResetButton : TriangleButton
|
||||
public class ResetButton : DangerousTriangleButton
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
private void load()
|
||||
{
|
||||
Text = "Reset all bindings in section";
|
||||
RelativeSizeAxes = Axes.X;
|
||||
@ -66,10 +65,6 @@ namespace osu.Game.Overlays.KeyBinding
|
||||
Height = 20;
|
||||
|
||||
Content.CornerRadius = 5;
|
||||
|
||||
BackgroundColour = colours.PinkDark;
|
||||
Triangles.ColourDark = colours.PinkDarker;
|
||||
Triangles.ColourLight = colours.Pink;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit.Checks;
|
||||
using osu.Game.Rulesets.Edit.Checks.Components;
|
||||
|
||||
@ -29,9 +28,9 @@ namespace osu.Game.Rulesets.Edit
|
||||
new CheckConcurrentObjects()
|
||||
};
|
||||
|
||||
public IEnumerable<Issue> Run(IBeatmap playableBeatmap, WorkingBeatmap workingBeatmap)
|
||||
public IEnumerable<Issue> Run(BeatmapVerifierContext context)
|
||||
{
|
||||
return checks.SelectMany(check => check.Run(playableBeatmap, workingBeatmap));
|
||||
return checks.SelectMany(check => check.Run(context));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
38
osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs
Normal file
38
osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace osu.Game.Rulesets.Edit
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the context provided by the beatmap verifier to the checks it runs.
|
||||
/// Contains information about what is being checked and how it should be checked.
|
||||
/// </summary>
|
||||
public class BeatmapVerifierContext
|
||||
{
|
||||
/// <summary>
|
||||
/// The playable beatmap instance of the current beatmap.
|
||||
/// </summary>
|
||||
public readonly IBeatmap Beatmap;
|
||||
|
||||
/// <summary>
|
||||
/// The working beatmap instance of the current beatmap.
|
||||
/// </summary>
|
||||
public readonly IWorkingBeatmap WorkingBeatmap;
|
||||
|
||||
/// <summary>
|
||||
/// The difficulty level which the current beatmap is considered to be.
|
||||
/// </summary>
|
||||
public DifficultyRating InterpretedDifficulty;
|
||||
|
||||
public BeatmapVerifierContext(IBeatmap beatmap, IWorkingBeatmap workingBeatmap, DifficultyRating difficultyRating = DifficultyRating.ExpertPlus)
|
||||
{
|
||||
Beatmap = beatmap;
|
||||
WorkingBeatmap = workingBeatmap;
|
||||
InterpretedDifficulty = difficultyRating;
|
||||
}
|
||||
}
|
||||
}
|
@ -10,6 +10,6 @@ namespace osu.Game.Rulesets.Edit.Checks
|
||||
{
|
||||
protected override CheckCategory Category => CheckCategory.Audio;
|
||||
protected override string TypeOfFile => "audio";
|
||||
protected override string GetFilename(IBeatmap playableBeatmap) => playableBeatmap.Metadata?.AudioFile;
|
||||
protected override string GetFilename(IBeatmap beatmap) => beatmap.Metadata?.AudioFile;
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit.Checks.Components;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Checks
|
||||
@ -26,13 +25,13 @@ namespace osu.Game.Rulesets.Edit.Checks
|
||||
new IssueTemplateNoBitrate(this)
|
||||
};
|
||||
|
||||
public IEnumerable<Issue> Run(IBeatmap playableBeatmap, IWorkingBeatmap workingBeatmap)
|
||||
public IEnumerable<Issue> Run(BeatmapVerifierContext context)
|
||||
{
|
||||
var audioFile = playableBeatmap.Metadata?.AudioFile;
|
||||
var audioFile = context.Beatmap.Metadata?.AudioFile;
|
||||
if (audioFile == null)
|
||||
yield break;
|
||||
|
||||
var track = workingBeatmap.Track;
|
||||
var track = context.WorkingBeatmap.Track;
|
||||
|
||||
if (track?.Bitrate == null || track.Bitrate.Value == 0)
|
||||
yield return new IssueTemplateNoBitrate(this).Create();
|
||||
|
@ -10,6 +10,6 @@ namespace osu.Game.Rulesets.Edit.Checks
|
||||
{
|
||||
protected override CheckCategory Category => CheckCategory.Resources;
|
||||
protected override string TypeOfFile => "background";
|
||||
protected override string GetFilename(IBeatmap playableBeatmap) => playableBeatmap.Metadata?.BackgroundFile;
|
||||
protected override string GetFilename(IBeatmap beatmap) => beatmap.Metadata?.BackgroundFile;
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit.Checks.Components;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Checks
|
||||
@ -30,13 +29,13 @@ namespace osu.Game.Rulesets.Edit.Checks
|
||||
new IssueTemplateTooUncompressed(this)
|
||||
};
|
||||
|
||||
public IEnumerable<Issue> Run(IBeatmap playableBeatmap, IWorkingBeatmap workingBeatmap)
|
||||
public IEnumerable<Issue> Run(BeatmapVerifierContext context)
|
||||
{
|
||||
var backgroundFile = playableBeatmap.Metadata?.BackgroundFile;
|
||||
var backgroundFile = context.Beatmap.Metadata?.BackgroundFile;
|
||||
if (backgroundFile == null)
|
||||
yield break;
|
||||
|
||||
var texture = workingBeatmap.Background;
|
||||
var texture = context.WorkingBeatmap.Background;
|
||||
if (texture == null)
|
||||
yield break;
|
||||
|
||||
@ -48,8 +47,8 @@ namespace osu.Game.Rulesets.Edit.Checks
|
||||
else if (texture.Width < low_width || texture.Height < low_height)
|
||||
yield return new IssueTemplateLowResolution(this).Create(texture.Width, texture.Height);
|
||||
|
||||
string storagePath = playableBeatmap.BeatmapInfo.BeatmapSet.GetPathForFile(backgroundFile);
|
||||
double filesizeMb = workingBeatmap.GetStream(storagePath).Length / (1024d * 1024d);
|
||||
string storagePath = context.Beatmap.BeatmapInfo.BeatmapSet.GetPathForFile(backgroundFile);
|
||||
double filesizeMb = context.WorkingBeatmap.GetStream(storagePath).Length / (1024d * 1024d);
|
||||
|
||||
if (filesizeMb > max_filesize_mb)
|
||||
yield return new IssueTemplateTooUncompressed(this).Create(filesizeMb);
|
||||
|
@ -2,7 +2,6 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit.Checks.Components;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
@ -22,15 +21,17 @@ namespace osu.Game.Rulesets.Edit.Checks
|
||||
new IssueTemplateConcurrentDifferent(this)
|
||||
};
|
||||
|
||||
public IEnumerable<Issue> Run(IBeatmap playableBeatmap, IWorkingBeatmap workingBeatmap)
|
||||
public IEnumerable<Issue> Run(BeatmapVerifierContext context)
|
||||
{
|
||||
for (int i = 0; i < playableBeatmap.HitObjects.Count - 1; ++i)
|
||||
{
|
||||
var hitobject = playableBeatmap.HitObjects[i];
|
||||
var hitObjects = context.Beatmap.HitObjects;
|
||||
|
||||
for (int j = i + 1; j < playableBeatmap.HitObjects.Count; ++j)
|
||||
for (int i = 0; i < hitObjects.Count - 1; ++i)
|
||||
{
|
||||
var hitobject = hitObjects[i];
|
||||
|
||||
for (int j = i + 1; j < hitObjects.Count; ++j)
|
||||
{
|
||||
var nextHitobject = playableBeatmap.HitObjects[j];
|
||||
var nextHitobject = hitObjects[j];
|
||||
|
||||
// Accounts for rulesets with hitobjects separated by columns, such as Mania.
|
||||
// In these cases we only care about concurrent objects within the same column.
|
||||
|
@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Edit.Checks
|
||||
{
|
||||
protected abstract CheckCategory Category { get; }
|
||||
protected abstract string TypeOfFile { get; }
|
||||
protected abstract string GetFilename(IBeatmap playableBeatmap);
|
||||
protected abstract string GetFilename(IBeatmap beatmap);
|
||||
|
||||
public CheckMetadata Metadata => new CheckMetadata(Category, $"Missing {TypeOfFile}");
|
||||
|
||||
@ -21,9 +21,9 @@ namespace osu.Game.Rulesets.Edit.Checks
|
||||
new IssueTemplateDoesNotExist(this)
|
||||
};
|
||||
|
||||
public IEnumerable<Issue> Run(IBeatmap playableBeatmap, IWorkingBeatmap workingBeatmap)
|
||||
public IEnumerable<Issue> Run(BeatmapVerifierContext context)
|
||||
{
|
||||
var filename = GetFilename(playableBeatmap);
|
||||
var filename = GetFilename(context.Beatmap);
|
||||
|
||||
if (filename == null)
|
||||
{
|
||||
@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Edit.Checks
|
||||
}
|
||||
|
||||
// If the file is set, also make sure it still exists.
|
||||
var storagePath = playableBeatmap.BeatmapInfo.BeatmapSet.GetPathForFile(filename);
|
||||
var storagePath = context.Beatmap.BeatmapInfo.BeatmapSet.GetPathForFile(filename);
|
||||
if (storagePath != null)
|
||||
yield break;
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit.Checks.Components;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
@ -22,11 +21,11 @@ namespace osu.Game.Rulesets.Edit.Checks
|
||||
new IssueTemplateSmallUnsnap(this)
|
||||
};
|
||||
|
||||
public IEnumerable<Issue> Run(IBeatmap playableBeatmap, IWorkingBeatmap workingBeatmap)
|
||||
public IEnumerable<Issue> Run(BeatmapVerifierContext context)
|
||||
{
|
||||
var controlPointInfo = playableBeatmap.ControlPointInfo;
|
||||
var controlPointInfo = context.Beatmap.ControlPointInfo;
|
||||
|
||||
foreach (var hitobject in playableBeatmap.HitObjects)
|
||||
foreach (var hitobject in context.Beatmap.HitObjects)
|
||||
{
|
||||
double startUnsnap = hitobject.StartTime - controlPointInfo.GetClosestSnappedTime(hitobject.StartTime);
|
||||
string startPostfix = hitobject is IHasDuration ? "start" : "";
|
||||
|
@ -2,7 +2,6 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Beatmaps;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Checks.Components
|
||||
{
|
||||
@ -24,8 +23,7 @@ namespace osu.Game.Rulesets.Edit.Checks.Components
|
||||
/// <summary>
|
||||
/// Runs this check and returns any issues detected for the provided beatmap.
|
||||
/// </summary>
|
||||
/// <param name="playableBeatmap">The playable beatmap of the beatmap to run the check on.</param>
|
||||
/// <param name="workingBeatmap">The working beatmap of the beatmap to run the check on.</param>
|
||||
public IEnumerable<Issue> Run(IBeatmap playableBeatmap, IWorkingBeatmap workingBeatmap);
|
||||
/// <param name="context">The beatmap verifier context associated with the beatmap.</param>
|
||||
public IEnumerable<Issue> Run(BeatmapVerifierContext context);
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ namespace osu.Game.Rulesets.Edit.Checks.Components
|
||||
/// <summary> An error occurred and a complete check could not be made. </summary>
|
||||
Error,
|
||||
|
||||
// TODO: Negligible issues should be hidden by default.
|
||||
/// <summary> A possible mistake so minor/unlikely that it can often be safely ignored. </summary>
|
||||
Negligible,
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit.Checks.Components;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit
|
||||
@ -12,6 +11,6 @@ namespace osu.Game.Rulesets.Edit
|
||||
/// </summary>
|
||||
public interface IBeatmapVerifier
|
||||
{
|
||||
public IEnumerable<Issue> Run(IBeatmap playableBeatmap, WorkingBeatmap workingBeatmap);
|
||||
public IEnumerable<Issue> Run(BeatmapVerifierContext context);
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,7 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Scoring;
|
||||
@ -18,14 +16,6 @@ namespace osu.Game.Rulesets.Mods
|
||||
public override ModType Type => ModType.DifficultyIncrease;
|
||||
public override bool Ranked => true;
|
||||
|
||||
/// <summary>
|
||||
/// Check whether the provided hitobject should be considered the "first" hideable object.
|
||||
/// Can be used to skip spinners, for instance.
|
||||
/// </summary>
|
||||
/// <param name="hitObject">The hitobject to check.</param>
|
||||
[Obsolete("Use IsFirstAdjustableObject() instead.")] // Can be removed 20210506
|
||||
protected virtual bool IsFirstHideableObject(DrawableHitObject hitObject) => true;
|
||||
|
||||
public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor)
|
||||
{
|
||||
// Default value of ScoreProcessor's Rank in Hidden Mod should be SS+
|
||||
@ -46,39 +36,5 @@ namespace osu.Game.Rulesets.Mods
|
||||
return rank;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state)
|
||||
{
|
||||
#pragma warning disable 618
|
||||
ApplyFirstObjectIncreaseVisibilityState(hitObject, state);
|
||||
#pragma warning restore 618
|
||||
}
|
||||
|
||||
protected override void ApplyNormalVisibilityState(DrawableHitObject hitObject, ArmedState state)
|
||||
{
|
||||
#pragma warning disable 618
|
||||
ApplyHiddenState(hitObject, state);
|
||||
#pragma warning restore 618
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply a special visibility state to the first object in a beatmap, if the user chooses to turn on the "increase first object visibility" setting.
|
||||
/// </summary>
|
||||
/// <param name="hitObject">The hit object to apply the state change to.</param>
|
||||
/// <param name="state">The state of the hit object.</param>
|
||||
[Obsolete("Use ApplyIncreasedVisibilityState() instead.")] // Can be removed 20210506
|
||||
protected virtual void ApplyFirstObjectIncreaseVisibilityState(DrawableHitObject hitObject, ArmedState state)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply a hidden state to the provided object.
|
||||
/// </summary>
|
||||
/// <param name="hitObject">The hit object to apply the state change to.</param>
|
||||
/// <param name="state">The state of the hit object.</param>
|
||||
[Obsolete("Use ApplyNormalVisibilityState() instead.")] // Can be removed 20210506
|
||||
protected virtual void ApplyHiddenState(DrawableHitObject hitObject, ArmedState state)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ using JetBrains.Annotations;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Extensions.EnumExtensions;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.Rulesets.Filter;
|
||||
using osu.Game.Screens.Ranking.Statistics;
|
||||
|
||||
@ -135,7 +136,7 @@ namespace osu.Game.Rulesets
|
||||
Name = Description,
|
||||
ShortName = ShortName,
|
||||
ID = (this as ILegacyRuleset)?.LegacyID,
|
||||
InstantiationInfo = GetType().AssemblyQualifiedName,
|
||||
InstantiationInfo = GetType().GetInvariantInstantiationInfo(),
|
||||
Available = true,
|
||||
};
|
||||
}
|
||||
|
@ -3,8 +3,8 @@
|
||||
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Testing;
|
||||
|
||||
namespace osu.Game.Rulesets
|
||||
@ -18,20 +18,7 @@ namespace osu.Game.Rulesets
|
||||
|
||||
public string ShortName { get; set; }
|
||||
|
||||
private string instantiationInfo;
|
||||
|
||||
public string InstantiationInfo
|
||||
{
|
||||
get => instantiationInfo;
|
||||
set => instantiationInfo = abbreviateInstantiationInfo(value);
|
||||
}
|
||||
|
||||
private string abbreviateInstantiationInfo(string value)
|
||||
{
|
||||
// exclude version onwards, matching only on namespace and type.
|
||||
// this is mainly to allow for new versions of already loaded rulesets to "upgrade" from old.
|
||||
return string.Join(',', value.Split(',').Take(2));
|
||||
}
|
||||
public string InstantiationInfo { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool Available { get; set; }
|
||||
@ -41,7 +28,7 @@ namespace osu.Game.Rulesets
|
||||
{
|
||||
if (!Available) return null;
|
||||
|
||||
var ruleset = (Ruleset)Activator.CreateInstance(Type.GetType(InstantiationInfo));
|
||||
var ruleset = (Ruleset)Activator.CreateInstance(Type.GetType(InstantiationInfo).AsNonNull());
|
||||
|
||||
// overwrite the pre-populated RulesetInfo with a potentially database attached copy.
|
||||
ruleset.RulesetInfo = this;
|
||||
|
@ -7,6 +7,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using osu.Framework;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Database;
|
||||
@ -111,7 +112,7 @@ namespace osu.Game.Rulesets
|
||||
{
|
||||
try
|
||||
{
|
||||
var instanceInfo = ((Ruleset)Activator.CreateInstance(Type.GetType(r.InstantiationInfo))).RulesetInfo;
|
||||
var instanceInfo = ((Ruleset)Activator.CreateInstance(Type.GetType(r.InstantiationInfo).AsNonNull())).RulesetInfo;
|
||||
|
||||
r.Name = instanceInfo.Name;
|
||||
r.ShortName = instanceInfo.ShortName;
|
||||
|
@ -3,9 +3,11 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
@ -24,6 +26,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
/// Includes selection and manipulation support via a <see cref="Components.SelectionHandler{T}"/>.
|
||||
/// </summary>
|
||||
public abstract class BlueprintContainer<T> : CompositeDrawable, IKeyBindingHandler<PlatformAction>
|
||||
where T : class
|
||||
{
|
||||
protected DragBox DragBox { get; private set; }
|
||||
|
||||
@ -39,6 +42,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
[Resolved(CanBeNull = true)]
|
||||
private IEditorChangeHandler changeHandler { get; set; }
|
||||
|
||||
protected readonly BindableList<T> SelectedItems = new BindableList<T>();
|
||||
|
||||
protected BlueprintContainer()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
@ -47,6 +52,24 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
SelectedItems.CollectionChanged += (selectedObjects, args) =>
|
||||
{
|
||||
switch (args.Action)
|
||||
{
|
||||
case NotifyCollectionChangedAction.Add:
|
||||
foreach (var o in args.NewItems)
|
||||
SelectionBlueprints.FirstOrDefault(b => b.Item == o)?.Select();
|
||||
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Remove:
|
||||
foreach (var o in args.OldItems)
|
||||
SelectionBlueprints.FirstOrDefault(b => b.Item == o)?.Deselect();
|
||||
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
SelectionHandler = CreateSelectionHandler();
|
||||
SelectionHandler.DeselectAll = deselectAll;
|
||||
|
||||
|
@ -2,10 +2,8 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input.Events;
|
||||
@ -24,8 +22,6 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
|
||||
protected readonly HitObjectComposer Composer;
|
||||
|
||||
private readonly BindableList<HitObject> selectedHitObjects = new BindableList<HitObject>();
|
||||
|
||||
protected EditorBlueprintContainer(HitObjectComposer composer)
|
||||
{
|
||||
Composer = composer;
|
||||
@ -34,23 +30,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
selectedHitObjects.BindTo(Beatmap.SelectedHitObjects);
|
||||
selectedHitObjects.CollectionChanged += (selectedObjects, args) =>
|
||||
{
|
||||
switch (args.Action)
|
||||
{
|
||||
case NotifyCollectionChangedAction.Add:
|
||||
foreach (var o in args.NewItems)
|
||||
SelectionBlueprints.FirstOrDefault(b => b.Item == o)?.Select();
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Remove:
|
||||
foreach (var o in args.OldItems)
|
||||
SelectionBlueprints.FirstOrDefault(b => b.Item == o)?.Deselect();
|
||||
|
||||
break;
|
||||
}
|
||||
};
|
||||
SelectedItems.BindTo(Beatmap.SelectedHitObjects);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
|
@ -84,8 +84,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
if (activeHandle?.IsHeld == true)
|
||||
return;
|
||||
|
||||
activeHandle = rotationHandles.SingleOrDefault(h => h.IsHeld || h.IsHovered);
|
||||
activeHandle ??= allDragHandles.SingleOrDefault(h => h.IsHovered);
|
||||
activeHandle = rotationHandles.FirstOrDefault(h => h.IsHeld || h.IsHovered);
|
||||
activeHandle ??= allDragHandles.FirstOrDefault(h => h.IsHovered);
|
||||
|
||||
if (activeHandle != null)
|
||||
{
|
||||
|
@ -635,6 +635,9 @@ namespace osu.Game.Screens.Edit
|
||||
case EditorScreenMode.Verify:
|
||||
currentScreen = new VerifyScreen();
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException("Editor menu bar switched to an unsupported mode");
|
||||
}
|
||||
|
||||
LoadComponentAsync(currentScreen, newScreen =>
|
||||
|
@ -10,7 +10,7 @@ using osu.Game.Overlays;
|
||||
|
||||
namespace osu.Game.Screens.Edit
|
||||
{
|
||||
public class RoundedContentEditorScreen : EditorScreen
|
||||
public class EditorRoundedScreen : EditorScreen
|
||||
{
|
||||
public const int HORIZONTAL_PADDING = 100;
|
||||
|
||||
@ -24,7 +24,7 @@ namespace osu.Game.Screens.Edit
|
||||
|
||||
protected override Container<Drawable> Content => roundedContent;
|
||||
|
||||
public RoundedContentEditorScreen(EditorScreenMode mode)
|
||||
public EditorRoundedScreen(EditorScreenMode mode)
|
||||
: base(mode)
|
||||
{
|
||||
ColourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
44
osu.Game/Screens/Edit/EditorRoundedScreenSettings.cs
Normal file
44
osu.Game/Screens/Edit/EditorRoundedScreenSettings.cs
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Overlays;
|
||||
|
||||
namespace osu.Game.Screens.Edit
|
||||
{
|
||||
public abstract class EditorRoundedScreenSettings : CompositeDrawable
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OverlayColourProvider colours)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = colours.Background4,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new OsuScrollContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = CreateSections()
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected abstract IReadOnlyList<Drawable> CreateSections();
|
||||
}
|
||||
}
|
61
osu.Game/Screens/Edit/EditorRoundedScreenSettingsSection.cs
Normal file
61
osu.Game/Screens/Edit/EditorRoundedScreenSettingsSection.cs
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Overlays;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Edit
|
||||
{
|
||||
public abstract class EditorRoundedScreenSettingsSection : CompositeDrawable
|
||||
{
|
||||
private const int header_height = 50;
|
||||
|
||||
protected abstract string HeaderText { get; }
|
||||
|
||||
protected FillFlowContainer Flow { get; private set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OverlayColourProvider colours)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
Masking = true;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = header_height,
|
||||
Padding = new MarginPadding { Horizontal = 20 },
|
||||
Child = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Text = HeaderText,
|
||||
Font = new FontUsage(size: 25, weight: "bold")
|
||||
}
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Y = header_height,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Child = Flow = new FillFlowContainer
|
||||
{
|
||||
Padding = new MarginPadding { Horizontal = 20 },
|
||||
Spacing = new Vector2(10),
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ using osu.Game.Graphics.Containers;
|
||||
|
||||
namespace osu.Game.Screens.Edit.Setup
|
||||
{
|
||||
public class SetupScreen : RoundedContentEditorScreen
|
||||
public class SetupScreen : EditorRoundedScreen
|
||||
{
|
||||
[Cached]
|
||||
private SectionsContainer<SetupSection> sections = new SectionsContainer<SetupSection>();
|
||||
|
@ -93,7 +93,7 @@ namespace osu.Game.Screens.Edit.Setup
|
||||
|
||||
public SetupScreenTabControl()
|
||||
{
|
||||
TabContainer.Margin = new MarginPadding { Horizontal = RoundedContentEditorScreen.HORIZONTAL_PADDING };
|
||||
TabContainer.Margin = new MarginPadding { Horizontal = EditorRoundedScreen.HORIZONTAL_PADDING };
|
||||
|
||||
AddInternal(background = new Box
|
||||
{
|
||||
|
@ -33,7 +33,7 @@ namespace osu.Game.Screens.Edit.Setup
|
||||
Padding = new MarginPadding
|
||||
{
|
||||
Vertical = 10,
|
||||
Horizontal = RoundedContentEditorScreen.HORIZONTAL_PADDING
|
||||
Horizontal = EditorRoundedScreen.HORIZONTAL_PADDING
|
||||
};
|
||||
|
||||
InternalChild = new FillFlowContainer
|
||||
|
@ -2,44 +2,13 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Overlays;
|
||||
|
||||
namespace osu.Game.Screens.Edit.Timing
|
||||
{
|
||||
public class ControlPointSettings : CompositeDrawable
|
||||
public class ControlPointSettings : EditorRoundedScreenSettings
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OverlayColourProvider colours)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = colours.Background4,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new OsuScrollContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = createSections()
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private IReadOnlyList<Drawable> createSections() => new Drawable[]
|
||||
protected override IReadOnlyList<Drawable> CreateSections() => new Drawable[]
|
||||
{
|
||||
new GroupSection(),
|
||||
new TimingSection(),
|
||||
|
@ -15,7 +15,7 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Edit.Timing
|
||||
{
|
||||
public class TimingScreen : RoundedContentEditorScreen
|
||||
public class TimingScreen : EditorRoundedScreen
|
||||
{
|
||||
[Cached]
|
||||
private Bindable<ControlPointGroup> selectedGroup = new Bindable<ControlPointGroup>();
|
||||
|
27
osu.Game/Screens/Edit/Verify/InterpretationSection.cs
Normal file
27
osu.Game/Screens/Edit/Verify/InterpretationSection.cs
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Overlays.Settings;
|
||||
|
||||
namespace osu.Game.Screens.Edit.Verify
|
||||
{
|
||||
internal class InterpretationSection : EditorRoundedScreenSettingsSection
|
||||
{
|
||||
protected override string HeaderText => "Interpretation";
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(VerifyScreen verify)
|
||||
{
|
||||
Flow.Add(new SettingsEnumDropdown<DifficultyRating>
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
TooltipText = "Affects checks that depend on difficulty level",
|
||||
Current = verify.InterpretedDifficulty.GetBoundCopy()
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
115
osu.Game/Screens/Edit/Verify/IssueList.cs
Normal file
115
osu.Game/Screens/Edit/Verify/IssueList.cs
Normal file
@ -0,0 +1,115 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Checks.Components;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Edit.Verify
|
||||
{
|
||||
[Cached]
|
||||
public class IssueList : CompositeDrawable
|
||||
{
|
||||
private IssueTable table;
|
||||
|
||||
[Resolved]
|
||||
private EditorClock clock { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private IBindable<WorkingBeatmap> workingBeatmap { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private EditorBeatmap beatmap { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private VerifyScreen verify { get; set; }
|
||||
|
||||
private IBeatmapVerifier rulesetVerifier;
|
||||
private BeatmapVerifier generalVerifier;
|
||||
private BeatmapVerifierContext context;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OverlayColourProvider colours)
|
||||
{
|
||||
generalVerifier = new BeatmapVerifier();
|
||||
rulesetVerifier = beatmap.BeatmapInfo.Ruleset?.CreateInstance()?.CreateBeatmapVerifier();
|
||||
|
||||
context = new BeatmapVerifierContext(beatmap, workingBeatmap.Value, verify.InterpretedDifficulty.Value);
|
||||
verify.InterpretedDifficulty.BindValueChanged(difficulty => context.InterpretedDifficulty = difficulty.NewValue);
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = colours.Background2,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new OsuScrollContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = table = new IssueTable(),
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight,
|
||||
Margin = new MarginPadding(20),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new TriangleButton
|
||||
{
|
||||
Text = "Refresh",
|
||||
Action = refresh,
|
||||
Size = new Vector2(120, 40),
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
verify.InterpretedDifficulty.BindValueChanged(_ => refresh());
|
||||
verify.HiddenIssueTypes.BindCollectionChanged((_, __) => refresh());
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
private void refresh()
|
||||
{
|
||||
var issues = generalVerifier.Run(context);
|
||||
|
||||
if (rulesetVerifier != null)
|
||||
issues = issues.Concat(rulesetVerifier.Run(context));
|
||||
|
||||
issues = filter(issues);
|
||||
|
||||
table.Issues = issues
|
||||
.OrderBy(issue => issue.Template.Type)
|
||||
.ThenBy(issue => issue.Check.Metadata.Category);
|
||||
}
|
||||
|
||||
private IEnumerable<Issue> filter(IEnumerable<Issue> issues)
|
||||
{
|
||||
return issues.Where(issue => !verify.HiddenIssueTypes.Contains(issue.Template.Type));
|
||||
}
|
||||
}
|
||||
}
|
@ -2,45 +2,16 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
|
||||
namespace osu.Game.Screens.Edit.Verify
|
||||
{
|
||||
public class IssueSettings : CompositeDrawable
|
||||
public class IssueSettings : EditorRoundedScreenSettings
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = colours.Gray3,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new OsuScrollContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = createSections()
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private IReadOnlyList<Drawable> createSections() => new Drawable[]
|
||||
protected override IReadOnlyList<Drawable> CreateSections() => new Drawable[]
|
||||
{
|
||||
new InterpretationSection(),
|
||||
new VisibilitySection()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,9 @@ namespace osu.Game.Screens.Edit.Verify
|
||||
public class IssueTable : EditorTable
|
||||
{
|
||||
[Resolved]
|
||||
private Bindable<Issue> selectedIssue { get; set; }
|
||||
private VerifyScreen verify { get; set; }
|
||||
|
||||
private Bindable<Issue> selectedIssue;
|
||||
|
||||
[Resolved]
|
||||
private EditorClock clock { get; set; }
|
||||
@ -71,6 +73,7 @@ namespace osu.Game.Screens.Edit.Verify
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
selectedIssue = verify.SelectedIssue.GetBoundCopy();
|
||||
selectedIssue.BindValueChanged(issue =>
|
||||
{
|
||||
foreach (var b in BackgroundFlow) b.Selected = b.Item == issue.NewValue;
|
||||
|
@ -1,26 +1,25 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Checks.Components;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Edit.Verify
|
||||
{
|
||||
public class VerifyScreen : RoundedContentEditorScreen
|
||||
[Cached]
|
||||
public class VerifyScreen : EditorRoundedScreen
|
||||
{
|
||||
[Cached]
|
||||
private Bindable<Issue> selectedIssue = new Bindable<Issue>();
|
||||
public readonly Bindable<Issue> SelectedIssue = new Bindable<Issue>();
|
||||
|
||||
public readonly Bindable<DifficultyRating> InterpretedDifficulty = new Bindable<DifficultyRating>();
|
||||
|
||||
public readonly BindableList<IssueType> HiddenIssueTypes = new BindableList<IssueType> { IssueType.Negligible };
|
||||
|
||||
public IssueList IssueList { get; private set; }
|
||||
|
||||
public VerifyScreen()
|
||||
: base(EditorScreenMode.Verify)
|
||||
@ -30,6 +29,10 @@ namespace osu.Game.Screens.Edit.Verify
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
InterpretedDifficulty.Default = EditorBeatmap.BeatmapInfo.DifficultyRating;
|
||||
InterpretedDifficulty.SetDefault();
|
||||
|
||||
IssueList = new IssueList();
|
||||
Child = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
@ -45,92 +48,12 @@ namespace osu.Game.Screens.Edit.Verify
|
||||
{
|
||||
new Drawable[]
|
||||
{
|
||||
new IssueList(),
|
||||
IssueList,
|
||||
new IssueSettings(),
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public class IssueList : CompositeDrawable
|
||||
{
|
||||
private IssueTable table;
|
||||
|
||||
[Resolved]
|
||||
private EditorClock clock { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private IBindable<WorkingBeatmap> workingBeatmap { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private EditorBeatmap beatmap { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private Bindable<Issue> selectedIssue { get; set; }
|
||||
|
||||
private IBeatmapVerifier rulesetVerifier;
|
||||
private BeatmapVerifier generalVerifier;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OverlayColourProvider colours)
|
||||
{
|
||||
generalVerifier = new BeatmapVerifier();
|
||||
rulesetVerifier = beatmap.BeatmapInfo.Ruleset?.CreateInstance()?.CreateBeatmapVerifier();
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = colours.Background2,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new OsuScrollContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = table = new IssueTable(),
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight,
|
||||
Margin = new MarginPadding(20),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new TriangleButton
|
||||
{
|
||||
Text = "Refresh",
|
||||
Action = refresh,
|
||||
Size = new Vector2(120, 40),
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
private void refresh()
|
||||
{
|
||||
var issues = generalVerifier.Run(beatmap, workingBeatmap.Value);
|
||||
|
||||
if (rulesetVerifier != null)
|
||||
issues = issues.Concat(rulesetVerifier.Run(beatmap, workingBeatmap.Value));
|
||||
|
||||
table.Issues = issues
|
||||
.OrderBy(issue => issue.Template.Type)
|
||||
.ThenBy(issue => issue.Check.Metadata.Category);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
54
osu.Game/Screens/Edit/Verify/VisibilitySection.cs
Normal file
54
osu.Game/Screens/Edit/Verify/VisibilitySection.cs
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Rulesets.Edit.Checks.Components;
|
||||
|
||||
namespace osu.Game.Screens.Edit.Verify
|
||||
{
|
||||
internal class VisibilitySection : EditorRoundedScreenSettingsSection
|
||||
{
|
||||
private readonly IssueType[] configurableIssueTypes =
|
||||
{
|
||||
IssueType.Warning,
|
||||
IssueType.Error,
|
||||
IssueType.Negligible
|
||||
};
|
||||
|
||||
private BindableList<IssueType> hiddenIssueTypes;
|
||||
|
||||
protected override string HeaderText => "Visibility";
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OverlayColourProvider colours, VerifyScreen verify)
|
||||
{
|
||||
hiddenIssueTypes = verify.HiddenIssueTypes.GetBoundCopy();
|
||||
|
||||
foreach (IssueType issueType in configurableIssueTypes)
|
||||
{
|
||||
var checkbox = new SettingsCheckbox
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
LabelText = issueType.ToString(),
|
||||
Current = { Default = !hiddenIssueTypes.Contains(issueType) }
|
||||
};
|
||||
|
||||
checkbox.Current.SetDefault();
|
||||
checkbox.Current.BindValueChanged(state =>
|
||||
{
|
||||
if (!state.NewValue)
|
||||
hiddenIssueTypes.Add(issueType);
|
||||
else
|
||||
hiddenIssueTypes.Remove(issueType);
|
||||
});
|
||||
|
||||
Flow.Add(checkbox);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -108,7 +108,7 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
difficultyIconContainer.Child = new DifficultyIcon(beatmap.Value, ruleset.Value, requiredMods) { Size = new Vector2(32) };
|
||||
|
||||
beatmapText.Clear();
|
||||
beatmapText.AddLink(Item.Beatmap.ToString(), LinkAction.OpenBeatmap, Item.Beatmap.Value.OnlineBeatmapID.ToString());
|
||||
beatmapText.AddLink(Item.Beatmap.Value.ToRomanisableString(), LinkAction.OpenBeatmap, Item.Beatmap.Value.OnlineBeatmapID.ToString());
|
||||
|
||||
authorText.Clear();
|
||||
|
||||
|
@ -150,7 +150,11 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
protected void StartPlay()
|
||||
{
|
||||
sampleStart?.Play();
|
||||
ParentScreen?.Push(CreateGameplayScreen());
|
||||
|
||||
// fallback is to allow this class to operate when there is no parent OnlineScreen (testing purposes).
|
||||
var targetScreen = (Screen)ParentScreen ?? this;
|
||||
|
||||
targetScreen.Push(CreateGameplayScreen());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -27,6 +27,7 @@ using osu.Game.Screens.OnlinePlay.Match.Components;
|
||||
using osu.Game.Screens.OnlinePlay.Multiplayer.Match;
|
||||
using osu.Game.Screens.OnlinePlay.Multiplayer.Participants;
|
||||
using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
@ -452,7 +453,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
return new MultiSpectatorScreen(userIds);
|
||||
|
||||
default:
|
||||
return new MultiplayerPlayer(SelectedItem.Value, userIds);
|
||||
return new PlayerLoader(() => new MultiplayerPlayer(SelectedItem.Value, userIds));
|
||||
}
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user