1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 17:32:54 +08:00

Merge branch 'master' into osu-markdown

This commit is contained in:
Dan Balasescu 2021-05-10 20:02:04 +09:00 committed by GitHub
commit e7355da201
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
62 changed files with 466 additions and 591 deletions

View File

@ -1,28 +1,22 @@
// 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.Game.Beatmaps;
using osu.Game.Replays;
using osu.Game.Rulesets.EmptyFreeform.Objects;
using osu.Game.Rulesets.Replays;
namespace osu.Game.Rulesets.EmptyFreeform.Replays
{
public class EmptyFreeformAutoGenerator : AutoGenerator
public class EmptyFreeformAutoGenerator : AutoGenerator<EmptyFreeformReplayFrame>
{
protected Replay Replay;
protected List<ReplayFrame> Frames => Replay.Frames;
public new Beatmap<EmptyFreeformHitObject> Beatmap => (Beatmap<EmptyFreeformHitObject>)base.Beatmap;
public EmptyFreeformAutoGenerator(IBeatmap beatmap)
: base(beatmap)
{
Replay = new Replay();
}
public override Replay Generate()
protected override void GenerateFrames()
{
Frames.Add(new EmptyFreeformReplayFrame());
@ -35,8 +29,6 @@ namespace osu.Game.Rulesets.EmptyFreeform.Replays
// todo: add required inputs and extra frames.
});
}
return Replay;
}
}
}

View File

@ -1,28 +1,22 @@
// 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.Game.Beatmaps;
using osu.Game.Replays;
using osu.Game.Rulesets.Pippidon.Objects;
using osu.Game.Rulesets.Replays;
namespace osu.Game.Rulesets.Pippidon.Replays
{
public class PippidonAutoGenerator : AutoGenerator
public class PippidonAutoGenerator : AutoGenerator<PippidonReplayFrame>
{
protected Replay Replay;
protected List<ReplayFrame> Frames => Replay.Frames;
public new Beatmap<PippidonHitObject> Beatmap => (Beatmap<PippidonHitObject>)base.Beatmap;
public PippidonAutoGenerator(IBeatmap beatmap)
: base(beatmap)
{
Replay = new Replay();
}
public override Replay Generate()
protected override void GenerateFrames()
{
Frames.Add(new PippidonReplayFrame());
@ -34,8 +28,6 @@ namespace osu.Game.Rulesets.Pippidon.Replays
Position = hitObject.Position,
});
}
return Replay;
}
}
}

View File

@ -1,28 +1,22 @@
// 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.Game.Beatmaps;
using osu.Game.Replays;
using osu.Game.Rulesets.EmptyScrolling.Objects;
using osu.Game.Rulesets.Replays;
namespace osu.Game.Rulesets.EmptyScrolling.Replays
{
public class EmptyScrollingAutoGenerator : AutoGenerator
public class EmptyScrollingAutoGenerator : AutoGenerator<EmptyScrollingReplayFrame>
{
protected Replay Replay;
protected List<ReplayFrame> Frames => Replay.Frames;
public new Beatmap<EmptyScrollingHitObject> Beatmap => (Beatmap<EmptyScrollingHitObject>)base.Beatmap;
public EmptyScrollingAutoGenerator(IBeatmap beatmap)
: base(beatmap)
{
Replay = new Replay();
}
public override Replay Generate()
protected override void GenerateFrames()
{
Frames.Add(new EmptyScrollingReplayFrame());
@ -34,8 +28,6 @@ namespace osu.Game.Rulesets.EmptyScrolling.Replays
// todo: add required inputs and extra frames.
});
}
return Replay;
}
}
}

View File

@ -2,29 +2,23 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using osu.Game.Beatmaps;
using osu.Game.Replays;
using osu.Game.Rulesets.Pippidon.Objects;
using osu.Game.Rulesets.Pippidon.UI;
using osu.Game.Rulesets.Replays;
namespace osu.Game.Rulesets.Pippidon.Replays
{
public class PippidonAutoGenerator : AutoGenerator
public class PippidonAutoGenerator : AutoGenerator<PippidonReplayFrame>
{
protected Replay Replay;
protected List<ReplayFrame> Frames => Replay.Frames;
public new Beatmap<PippidonHitObject> Beatmap => (Beatmap<PippidonHitObject>)base.Beatmap;
public PippidonAutoGenerator(IBeatmap beatmap)
: base(beatmap)
{
Replay = new Replay();
}
public override Replay Generate()
protected override void GenerateFrames()
{
int currentLane = 0;
@ -55,8 +49,6 @@ namespace osu.Game.Rulesets.Pippidon.Replays
currentLane = hitObject.Lane;
}
return Replay;
}
private void addFrame(double time, PippidonAction direction)

View File

@ -52,6 +52,6 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.422.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.506.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.507.0" />
</ItemGroup>
</Project>

View File

@ -5,7 +5,6 @@ using System;
using System.Linq;
using osu.Framework.Utils;
using osu.Game.Beatmaps;
using osu.Game.Replays;
using osu.Game.Rulesets.Catch.Beatmaps;
using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.UI;
@ -13,26 +12,19 @@ using osu.Game.Rulesets.Replays;
namespace osu.Game.Rulesets.Catch.Replays
{
internal class CatchAutoGenerator : AutoGenerator
internal class CatchAutoGenerator : AutoGenerator<CatchReplayFrame>
{
public const double RELEASE_DELAY = 20;
public new CatchBeatmap Beatmap => (CatchBeatmap)base.Beatmap;
public CatchAutoGenerator(IBeatmap beatmap)
: base(beatmap)
{
Replay = new Replay();
}
protected Replay Replay;
private CatchReplayFrame currentFrame;
public override Replay Generate()
protected override void GenerateFrames()
{
if (Beatmap.HitObjects.Count == 0)
return Replay;
return;
// todo: add support for HT DT
const double dash_speed = Catcher.BASE_SPEED;
@ -119,15 +111,11 @@ namespace osu.Game.Rulesets.Catch.Replays
}
}
}
return Replay;
}
private void addFrame(double time, float? position = null, bool dashing = false)
{
var last = currentFrame;
currentFrame = new CatchReplayFrame(time, position, dashing, last);
Replay.Frames.Add(currentFrame);
Frames.Add(new CatchReplayFrame(time, position, dashing, LastFrame));
}
}
}

View File

@ -3,7 +3,6 @@
using System.Collections.Generic;
using System.Linq;
using osu.Game.Replays;
using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Objects;
@ -11,7 +10,7 @@ using osu.Game.Rulesets.Replays;
namespace osu.Game.Rulesets.Mania.Replays
{
internal class ManiaAutoGenerator : AutoGenerator
internal class ManiaAutoGenerator : AutoGenerator<ManiaReplayFrame>
{
public const double RELEASE_DELAY = 20;
@ -22,8 +21,6 @@ namespace osu.Game.Rulesets.Mania.Replays
public ManiaAutoGenerator(ManiaBeatmap beatmap)
: base(beatmap)
{
Replay = new Replay();
columnActions = new ManiaAction[Beatmap.TotalColumns];
var normalAction = ManiaAction.Key1;
@ -43,12 +40,10 @@ namespace osu.Game.Rulesets.Mania.Replays
}
}
protected Replay Replay;
public override Replay Generate()
protected override void GenerateFrames()
{
if (Beatmap.HitObjects.Count == 0)
return Replay;
return;
var pointGroups = generateActionPoints().GroupBy(a => a.Time).OrderBy(g => g.First().Time);
@ -70,10 +65,8 @@ namespace osu.Game.Rulesets.Mania.Replays
}
}
Replay.Frames.Add(new ManiaReplayFrame(group.First().Time, actions.ToArray()));
Frames.Add(new ManiaReplayFrame(group.First().Time, actions.ToArray()));
}
return Replay;
}
private IEnumerable<IActionPoint> generateActionPoints()

View File

@ -26,6 +26,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
{
AccentColour = Color4.Transparent
};
// SliderSelectionBlueprint relies on calling ReceivePositionalInputAt on this drawable to determine whether selection should occur.
// Without AlwaysPresent, a movement in a parent container (ie. the editor composer area resizing) could cause incorrect input handling.
AlwaysPresent = true;
}
[BackgroundDependencyLoader]

View File

@ -2,10 +2,8 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using System.Linq;
using osu.Game.Beatmaps;
using osu.Game.Replays;
using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Taiko.Beatmaps;
@ -13,7 +11,7 @@ using osu.Game.Rulesets.Objects;
namespace osu.Game.Rulesets.Taiko.Replays
{
public class TaikoAutoGenerator : AutoGenerator
public class TaikoAutoGenerator : AutoGenerator<TaikoReplayFrame>
{
public new TaikoBeatmap Beatmap => (TaikoBeatmap)base.Beatmap;
@ -22,16 +20,12 @@ namespace osu.Game.Rulesets.Taiko.Replays
public TaikoAutoGenerator(IBeatmap beatmap)
: base(beatmap)
{
Replay = new Replay();
}
protected Replay Replay;
protected List<ReplayFrame> Frames => Replay.Frames;
public override Replay Generate()
protected override void GenerateFrames()
{
if (Beatmap.HitObjects.Count == 0)
return Replay;
return;
bool hitButton = true;
@ -128,8 +122,6 @@ namespace osu.Game.Rulesets.Taiko.Replays
hitButton = !hitButton;
}
return Replay;
}
}
}

View File

@ -4,9 +4,11 @@
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;
namespace osu.Game.Tests.Visual.Gameplay
@ -17,31 +19,21 @@ namespace osu.Game.Tests.Visual.Gameplay
protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset();
[Cached]
private ScoreProcessor scoreProcessor = new ScoreProcessor();
[SetUpSteps]
public void SetUpSteps()
{
AddStep("Create combo counters", () => SetContents(() =>
{
var comboCounter = new SkinnableComboCounter();
comboCounter.Current.Value = 1;
return comboCounter;
}));
AddStep("Create combo counters", () => SetContents(() => new SkinnableComboCounter()));
}
[Test]
public void TestComboCounterIncrementing()
{
AddRepeatStep("increase combo", () =>
{
foreach (var counter in comboCounters)
counter.Current.Value++;
}, 10);
AddRepeatStep("increase combo", () => scoreProcessor.Combo.Value++, 10);
AddStep("reset combo", () =>
{
foreach (var counter in comboCounters)
counter.Current.Value = 0;
});
AddStep("reset combo", () => scoreProcessor.Combo.Value = 0);
}
}
}

View File

@ -4,7 +4,8 @@
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Testing;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Configuration;
using osu.Game.Rulesets.Scoring;
using osu.Game.Screens.Play.HUD;
@ -20,24 +21,28 @@ namespace osu.Game.Tests.Visual.Gameplay
[Resolved]
private OsuConfigManager config { get; set; }
[SetUpSteps]
public void SetUpSteps()
private void create(HealthProcessor healthProcessor)
{
AddStep("create layer", () =>
{
Child = layer = new FailingLayer();
layer.BindHealthProcessor(new DrainingHealthProcessor(1));
Child = new HealthProcessorContainer(healthProcessor)
{
RelativeSizeAxes = Axes.Both,
Child = layer = new FailingLayer()
};
layer.ShowHealth.BindTo(showHealth);
});
AddStep("show health", () => showHealth.Value = true);
AddStep("enable layer", () => config.SetValue(OsuSetting.FadePlayfieldWhenHealthLow, true));
AddUntilStep("layer is visible", () => layer.IsPresent);
}
[Test]
public void TestLayerFading()
{
create(new DrainingHealthProcessor(0));
AddSliderStep("current health", 0.0, 1.0, 1.0, val =>
{
if (layer != null)
@ -53,6 +58,8 @@ namespace osu.Game.Tests.Visual.Gameplay
[Test]
public void TestLayerDisabledViaConfig()
{
create(new DrainingHealthProcessor(0));
AddUntilStep("layer is visible", () => layer.IsPresent);
AddStep("disable layer", () => config.SetValue(OsuSetting.FadePlayfieldWhenHealthLow, false));
AddStep("set health to 0.10", () => layer.Current.Value = 0.1);
AddUntilStep("layer is not visible", () => !layer.IsPresent);
@ -61,7 +68,8 @@ namespace osu.Game.Tests.Visual.Gameplay
[Test]
public void TestLayerVisibilityWithAccumulatingProcessor()
{
AddStep("bind accumulating processor", () => layer.BindHealthProcessor(new AccumulatingHealthProcessor(1)));
create(new AccumulatingHealthProcessor(1));
AddUntilStep("layer is not visible", () => !layer.IsPresent);
AddStep("set health to 0.10", () => layer.Current.Value = 0.1);
AddUntilStep("layer is not visible", () => !layer.IsPresent);
}
@ -69,7 +77,7 @@ namespace osu.Game.Tests.Visual.Gameplay
[Test]
public void TestLayerVisibilityWithDrainingProcessor()
{
AddStep("bind accumulating processor", () => layer.BindHealthProcessor(new DrainingHealthProcessor(1)));
create(new DrainingHealthProcessor(0));
AddStep("set health to 0.10", () => layer.Current.Value = 0.1);
AddWaitStep("wait for potential fade", 10);
AddAssert("layer is still visible", () => layer.IsPresent);
@ -78,6 +86,8 @@ namespace osu.Game.Tests.Visual.Gameplay
[Test]
public void TestLayerVisibilityWithDifferentOptions()
{
create(new DrainingHealthProcessor(0));
AddStep("set health to 0.10", () => layer.Current.Value = 0.1);
AddStep("don't show health", () => showHealth.Value = false);
@ -96,5 +106,16 @@ namespace osu.Game.Tests.Visual.Gameplay
AddStep("enable FadePlayfieldWhenHealthLow", () => config.SetValue(OsuSetting.FadePlayfieldWhenHealthLow, true));
AddUntilStep("layer fade is visible", () => layer.IsPresent);
}
private class HealthProcessorContainer : Container
{
[Cached(typeof(HealthProcessor))]
private readonly HealthProcessor healthProcessor;
public HealthProcessorContainer(HealthProcessor healthProcessor)
{
this.healthProcessor = healthProcessor;
}
}
}
}

View File

@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Testing;
using osu.Game.Configuration;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring;
using osu.Game.Screens.Play;
using osuTK.Input;
@ -19,6 +20,12 @@ namespace osu.Game.Tests.Visual.Gameplay
{
private HUDOverlay hudOverlay;
[Cached]
private ScoreProcessor scoreProcessor = new ScoreProcessor();
[Cached(typeof(HealthProcessor))]
private HealthProcessor healthProcessor = new DrainingHealthProcessor(0);
// best way to check without exposing.
private Drawable hideTarget => hudOverlay.KeyCounter;
private FillFlowContainer<KeyCounter> keyCounterFlow => hudOverlay.KeyCounter.ChildrenOfType<FillFlowContainer<KeyCounter>>().First();
@ -31,9 +38,9 @@ namespace osu.Game.Tests.Visual.Gameplay
{
createNew();
AddRepeatStep("increase combo", () => { hudOverlay.ComboCounter.Current.Value++; }, 10);
AddRepeatStep("increase combo", () => { scoreProcessor.Combo.Value++; }, 10);
AddStep("reset combo", () => { hudOverlay.ComboCounter.Current.Value = 0; });
AddStep("reset combo", () => { scoreProcessor.Combo.Value = 0; });
}
[Test]
@ -139,12 +146,12 @@ namespace osu.Game.Tests.Visual.Gameplay
{
AddStep("create overlay", () =>
{
hudOverlay = new HUDOverlay(null, null, null, Array.Empty<Mod>());
hudOverlay = new HUDOverlay(null, Array.Empty<Mod>());
// Add any key just to display the key counter visually.
hudOverlay.KeyCounter.Add(new KeyCounterKeyboard(Key.Space));
hudOverlay.ComboCounter.Current.Value = 1;
scoreProcessor.Combo.Value = 1;
action?.Invoke(hudOverlay);

View File

@ -2,15 +2,16 @@
// See the LICENCE file in the repository root for full licence text.
using NUnit.Framework;
using osu.Game.Rulesets.Judgements;
using osu.Framework.Utils;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Threading;
using osu.Framework.Utils;
using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets.Catch.Scoring;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mania.Scoring;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Scoring;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Scoring;
@ -20,14 +21,11 @@ namespace osu.Game.Tests.Visual.Gameplay
{
public class TestSceneHitErrorMeter : OsuTestScene
{
private BarHitErrorMeter barMeter;
private BarHitErrorMeter barMeter2;
private BarHitErrorMeter barMeter3;
private ColourHitErrorMeter colourMeter;
private ColourHitErrorMeter colourMeter2;
private ColourHitErrorMeter colourMeter3;
private HitWindows hitWindows;
[Cached]
private ScoreProcessor scoreProcessor = new ScoreProcessor();
public TestSceneHitErrorMeter()
{
recreateDisplay(new OsuHitWindows(), 5);
@ -105,40 +103,40 @@ namespace osu.Game.Tests.Visual.Gameplay
}
});
Add(barMeter = new BarHitErrorMeter(hitWindows, true)
Add(new BarHitErrorMeter(hitWindows, true)
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
});
Add(barMeter2 = new BarHitErrorMeter(hitWindows, false)
Add(new BarHitErrorMeter(hitWindows, false)
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
});
Add(barMeter3 = new BarHitErrorMeter(hitWindows, true)
Add(new BarHitErrorMeter(hitWindows, true)
{
Anchor = Anchor.BottomCentre,
Origin = Anchor.CentreLeft,
Rotation = 270,
});
Add(colourMeter = new ColourHitErrorMeter(hitWindows)
Add(new ColourHitErrorMeter(hitWindows)
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Margin = new MarginPadding { Right = 50 }
});
Add(colourMeter2 = new ColourHitErrorMeter(hitWindows)
Add(new ColourHitErrorMeter(hitWindows)
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Margin = new MarginPadding { Left = 50 }
});
Add(colourMeter3 = new ColourHitErrorMeter(hitWindows)
Add(new ColourHitErrorMeter(hitWindows)
{
Anchor = Anchor.BottomCentre,
Origin = Anchor.CentreLeft,
@ -149,18 +147,11 @@ namespace osu.Game.Tests.Visual.Gameplay
private void newJudgement(double offset = 0)
{
var judgement = new JudgementResult(new HitObject(), new Judgement())
scoreProcessor.ApplyResult(new JudgementResult(new HitCircle { HitWindows = hitWindows }, new Judgement())
{
TimeOffset = offset == 0 ? RNG.Next(-150, 150) : offset,
Type = HitResult.Perfect,
};
barMeter.OnNewJudgement(judgement);
barMeter2.OnNewJudgement(judgement);
barMeter3.OnNewJudgement(judgement);
colourMeter.OnNewJudgement(judgement);
colourMeter2.OnNewJudgement(judgement);
colourMeter3.OnNewJudgement(judgement);
});
}
}
}

View File

@ -2,6 +2,7 @@
// 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;
@ -17,6 +18,12 @@ namespace osu.Game.Tests.Visual.Gameplay
{
public class TestSceneSkinEditorMultipleSkins : SkinnableTestScene
{
[Cached]
private readonly ScoreProcessor scoreProcessor = new ScoreProcessor();
[Cached(typeof(HealthProcessor))]
private HealthProcessor healthProcessor = new DrainingHealthProcessor(0);
[SetUpSteps]
public void SetUpSteps()
{
@ -28,11 +35,9 @@ namespace osu.Game.Tests.Visual.Gameplay
var working = CreateWorkingBeatmap(ruleset.RulesetInfo);
var beatmap = working.GetPlayableBeatmap(ruleset.RulesetInfo);
ScoreProcessor scoreProcessor = new ScoreProcessor();
var drawableRuleset = ruleset.CreateDrawableRulesetWith(beatmap);
var hudOverlay = new HUDOverlay(scoreProcessor, null, drawableRuleset, Array.Empty<Mod>())
var hudOverlay = new HUDOverlay(drawableRuleset, Array.Empty<Mod>())
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
@ -40,7 +45,7 @@ namespace osu.Game.Tests.Visual.Gameplay
// Add any key just to display the key counter visually.
hudOverlay.KeyCounter.Add(new KeyCounterKeyboard(Key.Space));
hudOverlay.ComboCounter.Current.Value = 1;
scoreProcessor.Combo.Value = 1;
return new Container
{

View File

@ -1,49 +1,36 @@
// 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;
namespace osu.Game.Tests.Visual.Gameplay
{
public class TestSceneSkinnableAccuracyCounter : SkinnableTestScene
{
private IEnumerable<SkinnableAccuracyCounter> accuracyCounters => CreatedDrawables.OfType<SkinnableAccuracyCounter>();
protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset();
[Cached]
private ScoreProcessor scoreProcessor = new ScoreProcessor();
[SetUpSteps]
public void SetUpSteps()
{
AddStep("Create combo counters", () => SetContents(() =>
{
var accuracyCounter = new SkinnableAccuracyCounter();
accuracyCounter.Current.Value = 1;
return accuracyCounter;
}));
AddStep("Set initial accuracy", () => scoreProcessor.Accuracy.Value = 1);
AddStep("Create accuracy counters", () => SetContents(() => new SkinnableAccuracyCounter()));
}
[Test]
public void TestChangingAccuracy()
{
AddStep(@"Reset all", delegate
{
foreach (var s in accuracyCounters)
s.Current.Value = 1;
});
AddStep(@"Reset all", () => scoreProcessor.Accuracy.Value = 1);
AddStep(@"Hit! :D", delegate
{
foreach (var s in accuracyCounters)
s.Current.Value -= 0.023f;
});
AddStep(@"Miss :(", () => scoreProcessor.Accuracy.Value -= 0.023);
}
}
}

View File

@ -14,6 +14,7 @@ using osu.Game.Configuration;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Scoring;
using osu.Game.Screens.Play;
using osuTK.Input;
@ -23,6 +24,12 @@ namespace osu.Game.Tests.Visual.Gameplay
{
private HUDOverlay hudOverlay;
[Cached]
private ScoreProcessor scoreProcessor = new ScoreProcessor();
[Cached(typeof(HealthProcessor))]
private HealthProcessor healthProcessor = new DrainingHealthProcessor(0);
private IEnumerable<HUDOverlay> hudOverlays => CreatedDrawables.OfType<HUDOverlay>();
// best way to check without exposing.
@ -37,17 +44,9 @@ namespace osu.Game.Tests.Visual.Gameplay
{
createNew();
AddRepeatStep("increase combo", () =>
{
foreach (var hud in hudOverlays)
hud.ComboCounter.Current.Value++;
}, 10);
AddRepeatStep("increase combo", () => scoreProcessor.Combo.Value++, 10);
AddStep("reset combo", () =>
{
foreach (var hud in hudOverlays)
hud.ComboCounter.Current.Value = 0;
});
AddStep("reset combo", () => scoreProcessor.Combo.Value = 0);
}
[Test]
@ -80,13 +79,11 @@ namespace osu.Game.Tests.Visual.Gameplay
{
SetContents(() =>
{
hudOverlay = new HUDOverlay(null, null, null, Array.Empty<Mod>());
hudOverlay = new HUDOverlay(null, Array.Empty<Mod>());
// Add any key just to display the key counter visually.
hudOverlay.KeyCounter.Add(new KeyCounterKeyboard(Key.Space));
hudOverlay.ComboCounter.Current.Value = 1;
action?.Invoke(hudOverlay);
return hudOverlay;

View File

@ -4,11 +4,14 @@
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.Judgements;
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;
namespace osu.Game.Tests.Visual.Gameplay
@ -19,6 +22,9 @@ namespace osu.Game.Tests.Visual.Gameplay
protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset();
[Cached(typeof(HealthProcessor))]
private HealthProcessor healthProcessor = new DrainingHealthProcessor(0);
[SetUpSteps]
public void SetUpSteps()
{
@ -28,8 +34,7 @@ namespace osu.Game.Tests.Visual.Gameplay
});
AddStep(@"Reset all", delegate
{
foreach (var s in healthDisplays)
s.Current.Value = 1;
healthProcessor.Health.Value = 1;
});
}
@ -38,23 +43,21 @@ namespace osu.Game.Tests.Visual.Gameplay
{
AddRepeatStep(@"decrease hp", delegate
{
foreach (var healthDisplay in healthDisplays)
healthDisplay.Current.Value -= 0.08f;
healthProcessor.Health.Value -= 0.08f;
}, 10);
AddRepeatStep(@"increase hp without flash", delegate
{
foreach (var healthDisplay in healthDisplays)
healthDisplay.Current.Value += 0.1f;
healthProcessor.Health.Value += 0.1f;
}, 3);
AddRepeatStep(@"increase hp with flash", delegate
{
foreach (var healthDisplay in healthDisplays)
healthProcessor.Health.Value += 0.1f;
healthProcessor.ApplyResult(new JudgementResult(new HitCircle(), new OsuJudgement())
{
healthDisplay.Current.Value += 0.1f;
healthDisplay.Flash(new JudgementResult(null, new OsuJudgement()));
}
Type = HitResult.Perfect
});
}, 3);
}
}

View File

@ -4,10 +4,12 @@
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;
namespace osu.Game.Tests.Visual.Gameplay
@ -18,37 +20,27 @@ namespace osu.Game.Tests.Visual.Gameplay
protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset();
[Cached]
private ScoreProcessor scoreProcessor = new ScoreProcessor();
[SetUpSteps]
public void SetUpSteps()
{
AddStep("Create combo counters", () => SetContents(() =>
{
var comboCounter = new SkinnableScoreCounter();
comboCounter.Current.Value = 1;
return comboCounter;
}));
AddStep("Create score counters", () => SetContents(() => new SkinnableScoreCounter()));
}
[Test]
public void TestScoreCounterIncrementing()
{
AddStep(@"Reset all", delegate
{
foreach (var s in scoreCounters)
s.Current.Value = 0;
});
AddStep(@"Reset all", () => scoreProcessor.TotalScore.Value = 0);
AddStep(@"Hit! :D", delegate
{
foreach (var s in scoreCounters)
s.Current.Value += 300;
});
AddStep(@"Hit! :D", () => scoreProcessor.TotalScore.Value += 300);
}
[Test]
public void TestVeryLargeScore()
{
AddStep("set large score", () => scoreCounters.ForEach(counter => counter.Current.Value = 1_000_000_000));
AddStep("set large score", () => scoreCounters.ForEach(counter => scoreProcessor.TotalScore.Value = 1_000_000_000));
}
}
}

View File

@ -133,6 +133,16 @@ namespace osu.Game.Tests.Visual.Gameplay
AddUntilStep("storyboard ends", () => Player.GameplayClockContainer.GameplayClock.CurrentTime >= currentStoryboardDuration);
}
[Test]
public void TestPerformExitNoOutro()
{
CreateTest(null);
AddStep("disable storyboard", () => LocalConfig.SetValue(OsuSetting.ShowStoryboard, false));
AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value);
AddStep("exit via pause", () => Player.ExitViaPause());
AddAssert("player exited", () => Stack.CurrentScreen == null);
}
protected override bool AllowFail => true;
protected override Ruleset CreatePlayerRuleset() => new OsuRuleset();

View File

@ -2,7 +2,10 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Testing;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
@ -14,21 +17,34 @@ namespace osu.Game.Tests.Visual.Online
{
private DummyAPIAccess dummyAPI => (DummyAPIAccess)API;
private NewsOverlay news;
private NewsOverlay overlay;
[SetUp]
public void SetUp() => Schedule(() => Child = news = new NewsOverlay());
public void SetUp() => Schedule(() => Child = overlay = new NewsOverlay());
[Test]
public void TestRequest()
{
setUpNewsResponse(responseExample);
AddStep("Show", () => news.Show());
AddStep("Show article", () => news.ShowArticle("article"));
AddStep("Show", () => overlay.Show());
AddStep("Show article", () => overlay.ShowArticle("article"));
}
private void setUpNewsResponse(GetNewsResponse r)
=> AddStep("set up response", () =>
[Test]
public void TestCursorRequest()
{
setUpNewsResponse(responseWithCursor, "Set up cursor response");
AddStep("Show", () => overlay.Show());
AddUntilStep("Show More button is visible", () => showMoreButton?.Alpha == 1);
setUpNewsResponse(responseWithNoCursor, "Set up no cursor response");
AddStep("Click Show More", () => showMoreButton?.Click());
AddUntilStep("Show More button is hidden", () => showMoreButton?.Alpha == 0);
}
private ShowMoreButton showMoreButton => overlay.ChildrenOfType<ShowMoreButton>().FirstOrDefault();
private void setUpNewsResponse(GetNewsResponse r, string testName = "Set up response")
=> AddStep(testName, () =>
{
dummyAPI.HandleRequest = request =>
{
@ -40,7 +56,7 @@ namespace osu.Game.Tests.Visual.Online
};
});
private GetNewsResponse responseExample => new GetNewsResponse
private static GetNewsResponse responseExample => new GetNewsResponse
{
NewsPosts = new[]
{
@ -62,5 +78,37 @@ namespace osu.Game.Tests.Visual.Online
}
}
};
private static GetNewsResponse responseWithCursor => new GetNewsResponse
{
NewsPosts = new[]
{
new APINewsPost
{
Title = "This post has an image which starts with \"/\" and has many authors!",
Preview = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
Author = "someone, someone1, someone2, someone3, someone4",
FirstImage = "/help/wiki/shared/news/banners/monthly-beatmapping-contest.png",
PublishedAt = DateTimeOffset.Now
}
},
Cursor = new Cursor()
};
private static GetNewsResponse responseWithNoCursor => new GetNewsResponse
{
NewsPosts = new[]
{
new APINewsPost
{
Title = "This post has a full-url image! (HTML entity: &amp;)",
Preview = "boom (HTML entity: &amp;)",
Author = "user (HTML entity: &amp;)",
FirstImage = "https://assets.ppy.sh/artists/88/header.jpg",
PublishedAt = DateTimeOffset.Now
}
},
Cursor = null
};
}
}

View File

@ -108,7 +108,7 @@ namespace osu.Game.Tests.Visual.SongSelect
AddAssert("check version", () => infoWedge.Info.VersionLabel.Current.Value == $"{ruleset.ShortName}Version");
AddAssert("check title", () => infoWedge.Info.TitleLabel.Current.Value == $"{ruleset.ShortName}Source — {ruleset.ShortName}Title");
AddAssert("check artist", () => infoWedge.Info.ArtistLabel.Current.Value == $"{ruleset.ShortName}Artist");
AddAssert("check author", () => infoWedge.Info.MapperContainer.Children.OfType<OsuSpriteText>().Any(s => s.Current.Value == $"{ruleset.ShortName}Author"));
AddAssert("check author", () => infoWedge.Info.MapperContainer.ChildrenOfType<OsuSpriteText>().Any(s => s.Current.Value == $"{ruleset.ShortName}Author"));
}
private void testInfoLabels(int expectedCount)
@ -124,7 +124,7 @@ namespace osu.Game.Tests.Visual.SongSelect
AddAssert("check empty version", () => string.IsNullOrEmpty(infoWedge.Info.VersionLabel.Current.Value));
AddAssert("check default title", () => infoWedge.Info.TitleLabel.Current.Value == Beatmap.Default.BeatmapInfo.Metadata.Title);
AddAssert("check default artist", () => infoWedge.Info.ArtistLabel.Current.Value == Beatmap.Default.BeatmapInfo.Metadata.Artist);
AddAssert("check empty author", () => !infoWedge.Info.MapperContainer.Children.Any());
AddAssert("check empty author", () => !infoWedge.Info.MapperContainer.ChildrenOfType<OsuSpriteText>().Any());
AddAssert("check no info labels", () => !infoWedge.Info.ChildrenOfType<BeatmapInfoWedge.WedgeInfoText.InfoLabel>().Any());
}

View File

@ -304,6 +304,7 @@ namespace osu.Game.Tests.Visual.SongSelect
AddStep(@"Sort by BPM", () => config.SetValue(OsuSetting.SongSelectSortingMode, SortMode.BPM));
AddStep(@"Sort by Length", () => config.SetValue(OsuSetting.SongSelectSortingMode, SortMode.Length));
AddStep(@"Sort by Difficulty", () => config.SetValue(OsuSetting.SongSelectSortingMode, SortMode.Difficulty));
AddStep(@"Sort by Source", () => config.SetValue(OsuSetting.SongSelectSortingMode, SortMode.Source));
}
[Test]

View File

@ -4,11 +4,10 @@
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Screens.Play.HUD;
namespace osu.Game.Graphics.UserInterface
{
public abstract class ScoreCounter : RollingCounter<double>, IScoreCounter
public abstract class ScoreCounter : RollingCounter<double>
{
protected override double RollingDuration => 1000;
protected override Easing RollingEasing => Easing.Out;

View File

@ -23,6 +23,8 @@ namespace osu.Game.Online.API.Requests
return req;
}
protected override string FileExtension => ".osz";
protected override string Target => $@"beatmapsets/{Model.OnlineBeatmapSetID}/download{(noVideo ? "?noVideo=1" : "")}";
}
}

View File

@ -13,6 +13,8 @@ using osuTK.Graphics;
using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics;
using osu.Game.Users;
using osu.Game.Graphics.Containers;
namespace osu.Game.Overlays.BeatmapSet
{
@ -50,7 +52,7 @@ namespace osu.Game.Overlays.BeatmapSet
fields.Children = new Drawable[]
{
new Field("mapped by", BeatmapSet.Metadata.Author.Username, OsuFont.GetFont(weight: FontWeight.Regular, italics: true)),
new Field("mapped by", BeatmapSet.Metadata.Author, OsuFont.GetFont(weight: FontWeight.Regular, italics: true)),
new Field("submitted", online.Submitted, OsuFont.GetFont(weight: FontWeight.Bold))
{
Margin = new MarginPadding { Top = 5 },
@ -146,6 +148,25 @@ namespace osu.Game.Overlays.BeatmapSet
}
};
}
public Field(string first, User second, FontUsage secondFont)
{
AutoSizeAxes = Axes.Both;
Direction = FillDirection.Horizontal;
Children = new[]
{
new LinkFlowContainer(s =>
{
s.Font = OsuFont.GetFont(size: 11);
}).With(d =>
{
d.AutoSizeAxes = Axes.Both;
d.AddText($"{first} ");
d.AddUserLink(second, s => s.Font = secondFont.With(size: 11));
}),
};
}
}
}
}

View File

@ -100,7 +100,7 @@ namespace osu.Game.Overlays.News.Displays
{
content.Add(loaded);
showMore.IsLoading = false;
showMore.Show();
showMore.Alpha = lastCursor == null ? 0 : 1;
}, (cancellationToken = new CancellationTokenSource()).Token);
}

View File

@ -204,7 +204,7 @@ namespace osu.Game.Overlays.Volume
{
displayVolume = value;
if (displayVolume > 0.99f)
if (displayVolume >= 0.995f)
{
text.Text = "MAX";
maxGlow.EffectColour = meterColour.Opacity(2f);

View File

@ -1,40 +1,36 @@
// 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 JetBrains.Annotations;
using osu.Game.Beatmaps;
using osu.Game.Replays;
using osu.Game.Rulesets.Objects;
namespace osu.Game.Rulesets.Replays
{
public abstract class AutoGenerator : IAutoGenerator
public abstract class AutoGenerator
{
/// <summary>
/// Creates the auto replay and returns it.
/// Every subclass of OsuAutoGeneratorBase should implement this!
/// The default duration of a key press in milliseconds.
/// </summary>
public abstract Replay Generate();
#region Parameters
public const double KEY_UP_DELAY = 50;
/// <summary>
/// The beatmap we're making.
/// The beatmap the autoplay is generated for.
/// </summary>
protected IBeatmap Beatmap;
#endregion
protected IBeatmap Beatmap { get; }
protected AutoGenerator(IBeatmap beatmap)
{
Beatmap = beatmap;
}
#region Constants
// Shared amongst all modes
public const double KEY_UP_DELAY = 50;
#endregion
/// <summary>
/// Generate the replay of the autoplay.
/// </summary>
public abstract Replay Generate();
protected virtual HitObject GetNextObject(int currentIndex)
{
@ -44,4 +40,37 @@ namespace osu.Game.Rulesets.Replays
return Beatmap.HitObjects[currentIndex + 1];
}
}
public abstract class AutoGenerator<TFrame> : AutoGenerator
where TFrame : ReplayFrame
{
/// <summary>
/// The replay frames of the autoplay.
/// </summary>
protected readonly List<TFrame> Frames = new List<TFrame>();
[CanBeNull]
protected TFrame LastFrame => Frames.Count == 0 ? null : Frames[^1];
protected AutoGenerator(IBeatmap beatmap)
: base(beatmap)
{
}
public sealed override Replay Generate()
{
Frames.Clear();
GenerateFrames();
return new Replay
{
Frames = Frames.OrderBy(frame => frame.Time).Cast<ReplayFrame>().ToList()
};
}
/// <summary>
/// Generate the replay frames of the autoplay and populate <see cref="Frames"/>.
/// </summary>
protected abstract void GenerateFrames();
}
}

View File

@ -1,12 +0,0 @@
// 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.Replays;
namespace osu.Game.Rulesets.Replays
{
public interface IAutoGenerator
{
Replay Generate();
}
}

View File

@ -17,7 +17,6 @@ using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
using osu.Framework.Logging;
using osu.Framework.Screens;
using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Graphics;
@ -144,8 +143,7 @@ namespace osu.Game.Screens.Edit
// Todo: should probably be done at a DrawableRuleset level to share logic with Player.
clock = new EditorClock(playableBeatmap, beatDivisor) { IsCoupled = false };
UpdateClockSource();
clock.ChangeSource(loadableBeatmap.Track);
dependencies.CacheAs(clock);
AddInternal(clock);
@ -308,11 +306,7 @@ namespace osu.Game.Screens.Edit
/// <summary>
/// If the beatmap's track has changed, this method must be called to keep the editor in a valid state.
/// </summary>
public void UpdateClockSource()
{
var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock();
clock.ChangeSource(sourceClock);
}
public void UpdateClockSource() => clock.ChangeSource(Beatmap.Value.Track);
protected void Save()
{
@ -583,7 +577,7 @@ namespace osu.Game.Screens.Edit
private void resetTrack(bool seekToStart = false)
{
Beatmap.Value.Track?.Stop();
Beatmap.Value.Track.Stop();
if (seekToStart)
{

View File

@ -4,12 +4,11 @@
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
using osuTK;
namespace osu.Game.Screens.Play.HUD
{
public class DefaultAccuracyCounter : PercentageCounter, IAccuracyCounter, ISkinnableComponent
public class DefaultAccuracyCounter : GameplayAccuracyCounter, ISkinnableComponent
{
private readonly Vector2 offset = new Vector2(-20, 5);

View File

@ -7,11 +7,12 @@ using osu.Framework.Graphics;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets.Scoring;
using osuTK;
namespace osu.Game.Screens.Play.HUD
{
public class DefaultComboCounter : RollingCounter<int>, IComboCounter, ISkinnableComponent
public class DefaultComboCounter : RollingCounter<int>, ISkinnableComponent
{
private readonly Vector2 offset = new Vector2(20, 5);
@ -24,7 +25,11 @@ namespace osu.Game.Screens.Play.HUD
}
[BackgroundDependencyLoader]
private void load(OsuColour colours) => Colour = colours.BlueLighter;
private void load(OsuColour colours, ScoreProcessor scoreProcessor)
{
Colour = colours.BlueLighter;
Current.BindTo(scoreProcessor.Combo);
}
protected override void Update()
{

View File

@ -107,7 +107,7 @@ namespace osu.Game.Screens.Play.HUD
GlowColour = colours.BlueDarker;
}
public override void Flash(JudgementResult result) => Scheduler.AddOnce(flash);
protected override void Flash(JudgementResult result) => Scheduler.AddOnce(flash);
private void flash()
{

View File

@ -4,11 +4,10 @@
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
namespace osu.Game.Screens.Play.HUD
{
public class DefaultScoreCounter : ScoreCounter, ISkinnableComponent
public class DefaultScoreCounter : GameplayScoreCounter, ISkinnableComponent
{
public DefaultScoreCounter()
: base(6)

View File

@ -39,7 +39,6 @@ namespace osu.Game.Screens.Play.HUD
private readonly Container boxes;
private Bindable<bool> fadePlayfieldWhenHealthLow;
private HealthProcessor healthProcessor;
public FailingLayer()
{
@ -88,18 +87,10 @@ namespace osu.Game.Screens.Play.HUD
updateState();
}
public override void BindHealthProcessor(HealthProcessor processor)
{
base.BindHealthProcessor(processor);
healthProcessor = processor;
updateState();
}
private void updateState()
{
// Don't display ever if the ruleset is not using a draining health display.
var showLayer = healthProcessor is DrainingHealthProcessor && fadePlayfieldWhenHealthLow.Value && ShowHealth.Value;
var showLayer = HealthProcessor is DrainingHealthProcessor && fadePlayfieldWhenHealthLow.Value && ShowHealth.Value;
this.FadeTo(showLayer ? 1 : 0, fade_time, Easing.OutQuint);
}

View 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;
using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Screens.Play.HUD
{
public abstract class GameplayAccuracyCounter : PercentageCounter
{
[BackgroundDependencyLoader]
private void load(ScoreProcessor scoreProcessor)
{
Current.BindTo(scoreProcessor.Accuracy);
}
}
}

View File

@ -0,0 +1,46 @@
// 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.Bindables;
using osu.Game.Configuration;
using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Screens.Play.HUD
{
public abstract class GameplayScoreCounter : ScoreCounter
{
private Bindable<ScoringMode> scoreDisplayMode;
protected GameplayScoreCounter(int leading = 0, bool useCommaSeparator = false)
: base(leading, useCommaSeparator)
{
}
[BackgroundDependencyLoader]
private void load(OsuConfigManager config, ScoreProcessor scoreProcessor)
{
scoreDisplayMode = config.GetBindable<ScoringMode>(OsuSetting.ScoreDisplayMode);
scoreDisplayMode.BindValueChanged(scoreMode =>
{
switch (scoreMode.NewValue)
{
case ScoringMode.Standardised:
RequiredDisplayDigits.Value = 6;
break;
case ScoringMode.Classic:
RequiredDisplayDigits.Value = 8;
break;
default:
throw new ArgumentOutOfRangeException(nameof(scoreMode));
}
}, true);
Current.BindTo(scoreProcessor.TotalScore);
}
}
}

View File

@ -1,6 +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 osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Judgements;
@ -11,26 +12,43 @@ namespace osu.Game.Screens.Play.HUD
{
/// <summary>
/// A container for components displaying the current player health.
/// Gets bound automatically to the <see cref="HealthProcessor"/> when inserted to <see cref="DrawableRuleset.Overlays"/> hierarchy.
/// Gets bound automatically to the <see cref="Rulesets.Scoring.HealthProcessor"/> when inserted to <see cref="DrawableRuleset.Overlays"/> hierarchy.
/// </summary>
public abstract class HealthDisplay : Container, IHealthDisplay
public abstract class HealthDisplay : Container
{
[Resolved]
protected HealthProcessor HealthProcessor { get; private set; }
public Bindable<double> Current { get; } = new BindableDouble(1)
{
MinValue = 0,
MaxValue = 1
};
public virtual void Flash(JudgementResult result)
protected virtual void Flash(JudgementResult result)
{
}
/// <summary>
/// Bind the tracked fields of <see cref="HealthProcessor"/> to this health display.
/// </summary>
public virtual void BindHealthProcessor(HealthProcessor processor)
[BackgroundDependencyLoader]
private void load()
{
Current.BindTo(processor.Health);
Current.BindTo(HealthProcessor.Health);
HealthProcessor.NewJudgement += onNewJudgement;
}
private void onNewJudgement(JudgementResult judgement)
{
if (judgement.IsHit && judgement.Type != HitResult.IgnoreHit)
Flash(judgement);
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (HealthProcessor != null)
HealthProcessor.NewJudgement -= onNewJudgement;
}
}
}

View File

@ -7,7 +7,6 @@ using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Configuration;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Scoring;
using osu.Game.Screens.Play.HUD.HitErrorMeters;
@ -22,17 +21,11 @@ namespace osu.Game.Screens.Play.HUD
private readonly HitWindows hitWindows;
private readonly ScoreProcessor processor;
public HitErrorDisplay(ScoreProcessor processor, HitWindows hitWindows)
public HitErrorDisplay(HitWindows hitWindows)
{
this.processor = processor;
this.hitWindows = hitWindows;
RelativeSizeAxes = Axes.Both;
if (processor != null)
processor.NewJudgement += onNewJudgement;
}
[BackgroundDependencyLoader]
@ -47,15 +40,6 @@ namespace osu.Game.Screens.Play.HUD
type.BindValueChanged(typeChanged, true);
}
private void onNewJudgement(JudgementResult result)
{
if (result.HitObject.HitWindows.WindowFor(HitResult.Miss) == 0)
return;
foreach (var c in Children)
c.OnNewJudgement(result);
}
private void typeChanged(ValueChangedEvent<ScoreMeterType> type)
{
Children.ForEach(c => c.FadeOut(fade_duration, Easing.OutQuint));
@ -139,13 +123,5 @@ namespace osu.Game.Screens.Play.HUD
Add(display);
display.FadeInFromZero(fade_duration, Easing.OutQuint);
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (processor != null)
processor.NewJudgement -= onNewJudgement;
}
}
}

View File

@ -214,7 +214,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
private const int max_concurrent_judgements = 50;
public override void OnNewJudgement(JudgementResult judgement)
protected override void OnNewJudgement(JudgementResult judgement)
{
if (!judgement.IsHit)
return;

View File

@ -26,7 +26,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
InternalChild = judgementsFlow = new JudgementFlow();
}
public override void OnNewJudgement(JudgementResult judgement) => judgementsFlow.Push(GetColourForHitResult(HitWindows.ResultFor(judgement.TimeOffset)));
protected override void OnNewJudgement(JudgementResult judgement) => judgementsFlow.Push(GetColourForHitResult(HitWindows.ResultFor(judgement.TimeOffset)));
private class JudgementFlow : FillFlowContainer<HitErrorCircle>
{

View File

@ -14,6 +14,9 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
{
protected readonly HitWindows HitWindows;
[Resolved]
private ScoreProcessor processor { get; set; }
[Resolved]
private OsuColour colours { get; set; }
@ -22,7 +25,22 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
HitWindows = hitWindows;
}
public abstract void OnNewJudgement(JudgementResult judgement);
protected override void LoadComplete()
{
base.LoadComplete();
processor.NewJudgement += onNewJudgement;
}
private void onNewJudgement(JudgementResult result)
{
if (result.HitObject.HitWindows?.WindowFor(HitResult.Miss) == 0)
return;
OnNewJudgement(result);
}
protected abstract void OnNewJudgement(JudgementResult judgement);
protected Color4 GetColourForHitResult(HitResult result)
{
@ -47,5 +65,13 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
return colours.BlueLight;
}
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (processor != null)
processor.NewJudgement -= onNewJudgement;
}
}
}

View File

@ -1,19 +0,0 @@
// 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.Bindables;
using osu.Framework.Graphics;
namespace osu.Game.Screens.Play.HUD
{
/// <summary>
/// An interface providing a set of methods to update a accuracy counter.
/// </summary>
public interface IAccuracyCounter : IDrawable
{
/// <summary>
/// The current accuracy to be displayed.
/// </summary>
Bindable<double> Current { get; }
}
}

View File

@ -1,19 +0,0 @@
// 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.Bindables;
using osu.Framework.Graphics;
namespace osu.Game.Screens.Play.HUD
{
/// <summary>
/// An interface providing a set of methods to update a combo counter.
/// </summary>
public interface IComboCounter : IDrawable
{
/// <summary>
/// The current combo to be displayed.
/// </summary>
Bindable<int> Current { get; }
}
}

View File

@ -1,26 +0,0 @@
// 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.Bindables;
using osu.Framework.Graphics;
using osu.Game.Rulesets.Judgements;
namespace osu.Game.Screens.Play.HUD
{
/// <summary>
/// An interface providing a set of methods to update a health display.
/// </summary>
public interface IHealthDisplay : IDrawable
{
/// <summary>
/// The current health to be displayed.
/// </summary>
Bindable<double> Current { get; }
/// <summary>
/// Flash the display for a specified result type.
/// </summary>
/// <param name="result">The result type.</param>
void Flash(JudgementResult result);
}
}

View File

@ -1,25 +0,0 @@
// 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.Bindables;
using osu.Framework.Graphics;
namespace osu.Game.Screens.Play.HUD
{
/// <summary>
/// An interface providing a set of methods to update a score counter.
/// </summary>
public interface IScoreCounter : IDrawable
{
/// <summary>
/// The current score to be displayed.
/// </summary>
Bindable<double> Current { get; }
/// <summary>
/// The number of digits required to display most sane scores.
/// This may be exceeded in very rare cases, but is useful to pad or space the display to avoid it jumping around.
/// </summary>
Bindable<int> RequiredDisplayDigits { get; }
}
}

View File

@ -6,6 +6,7 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Game.Rulesets.Scoring;
using osu.Game.Skinning;
using osuTK;
@ -14,7 +15,7 @@ namespace osu.Game.Screens.Play.HUD
/// <summary>
/// Uses the 'x' symbol and has a pop-out effect while rolling over.
/// </summary>
public class LegacyComboCounter : CompositeDrawable, IComboCounter, ISkinnableComponent
public class LegacyComboCounter : CompositeDrawable, ISkinnableComponent
{
public Bindable<int> Current { get; } = new BindableInt { MinValue = 0, };
@ -79,7 +80,7 @@ namespace osu.Game.Screens.Play.HUD
}
[BackgroundDependencyLoader]
private void load()
private void load(ScoreProcessor scoreProcessor)
{
InternalChildren = new[]
{
@ -95,7 +96,7 @@ namespace osu.Game.Screens.Play.HUD
},
};
Current.ValueChanged += combo => updateCount(combo.NewValue == 0);
Current.BindTo(scoreProcessor.Combo);
}
protected override void LoadComplete()
@ -109,7 +110,7 @@ namespace osu.Game.Screens.Play.HUD
popOutCount.Origin = Origin;
popOutCount.Anchor = Anchor;
updateCount(false);
Current.BindValueChanged(combo => updateCount(combo.NewValue == 0), true);
}
private void updateCount(bool rolling)

View File

@ -1,29 +1,16 @@
// 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.Bindables;
using osu.Game.Skinning;
namespace osu.Game.Screens.Play.HUD
{
public class SkinnableAccuracyCounter : SkinnableDrawable, IAccuracyCounter
public class SkinnableAccuracyCounter : SkinnableDrawable
{
public Bindable<double> Current { get; } = new Bindable<double>();
public SkinnableAccuracyCounter()
: base(new HUDSkinComponent(HUDSkinComponents.AccuracyCounter), _ => new DefaultAccuracyCounter())
{
CentreComponent = false;
}
private IAccuracyCounter skinnedCounter;
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
{
base.SkinChanged(skin, allowFallback);
skinnedCounter = Drawable as IAccuracyCounter;
skinnedCounter?.Current.BindTo(Current);
}
}
}

View File

@ -1,29 +1,16 @@
// 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.Bindables;
using osu.Game.Skinning;
namespace osu.Game.Screens.Play.HUD
{
public class SkinnableComboCounter : SkinnableDrawable, IComboCounter
public class SkinnableComboCounter : SkinnableDrawable
{
public Bindable<int> Current { get; } = new Bindable<int>();
public SkinnableComboCounter()
: base(new HUDSkinComponent(HUDSkinComponents.ComboCounter), skinComponent => new DefaultComboCounter())
{
CentreComponent = false;
}
private IComboCounter skinnedCounter;
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
{
base.SkinChanged(skin, allowFallback);
skinnedCounter = Drawable as IComboCounter;
skinnedCounter?.Current.BindTo(Current);
}
}
}

View File

@ -1,50 +1,16 @@
// 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.Bindables;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Scoring;
using osu.Game.Skinning;
namespace osu.Game.Screens.Play.HUD
{
public class SkinnableHealthDisplay : SkinnableDrawable, IHealthDisplay
public class SkinnableHealthDisplay : SkinnableDrawable
{
public Bindable<double> Current { get; } = new BindableDouble(1)
{
MinValue = 0,
MaxValue = 1
};
public void Flash(JudgementResult result) => skinnedCounter?.Flash(result);
private HealthProcessor processor;
public void BindHealthProcessor(HealthProcessor processor)
{
if (this.processor != null)
throw new InvalidOperationException("Can't bind to a processor more than once");
this.processor = processor;
Current.BindTo(processor.Health);
}
public SkinnableHealthDisplay()
: base(new HUDSkinComponent(HUDSkinComponents.HealthDisplay), _ => new DefaultHealthDisplay())
{
CentreComponent = false;
}
private IHealthDisplay skinnedCounter;
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
{
base.SkinChanged(skin, allowFallback);
skinnedCounter = Drawable as IHealthDisplay;
skinnedCounter?.Current.BindTo(Current);
}
}
}

View File

@ -1,61 +1,16 @@
// 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.Bindables;
using osu.Game.Configuration;
using osu.Game.Rulesets.Scoring;
using osu.Game.Skinning;
namespace osu.Game.Screens.Play.HUD
{
public class SkinnableScoreCounter : SkinnableDrawable, IScoreCounter
public class SkinnableScoreCounter : SkinnableDrawable
{
public Bindable<double> Current { get; } = new Bindable<double>();
private Bindable<ScoringMode> scoreDisplayMode;
public Bindable<int> RequiredDisplayDigits { get; } = new Bindable<int>();
public SkinnableScoreCounter()
: base(new HUDSkinComponent(HUDSkinComponents.ScoreCounter), _ => new DefaultScoreCounter())
{
CentreComponent = false;
}
[BackgroundDependencyLoader]
private void load(OsuConfigManager config)
{
scoreDisplayMode = config.GetBindable<ScoringMode>(OsuSetting.ScoreDisplayMode);
scoreDisplayMode.BindValueChanged(scoreMode =>
{
switch (scoreMode.NewValue)
{
case ScoringMode.Standardised:
RequiredDisplayDigits.Value = 6;
break;
case ScoringMode.Classic:
RequiredDisplayDigits.Value = 8;
break;
default:
throw new ArgumentOutOfRangeException(nameof(scoreMode));
}
}, true);
}
private IScoreCounter skinnedCounter;
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
{
base.SkinChanged(skin, allowFallback);
skinnedCounter = Drawable as IScoreCounter;
skinnedCounter?.Current.BindTo(Current);
skinnedCounter?.RequiredDisplayDigits.BindTo(RequiredDisplayDigits);
}
}
}

View File

@ -14,7 +14,6 @@ using osu.Game.Input.Bindings;
using osu.Game.Overlays;
using osu.Game.Overlays.Notifications;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
using osu.Game.Screens.Play.HUD;
using osuTK;
@ -34,21 +33,16 @@ namespace osu.Game.Screens.Play
public float TopScoringElementsHeight { get; private set; }
public readonly KeyCounterDisplay KeyCounter;
public readonly SkinnableComboCounter ComboCounter;
public readonly SkinnableScoreCounter ScoreCounter;
public readonly SkinnableAccuracyCounter AccuracyCounter;
public readonly SkinnableHealthDisplay HealthDisplay;
public readonly SongProgress Progress;
public readonly ModDisplay ModDisplay;
public readonly HitErrorDisplay HitErrorDisplay;
public readonly HoldForMenuButton HoldToQuit;
public readonly PlayerSettingsOverlay PlayerSettingsOverlay;
public readonly FailingLayer FailingLayer;
public Bindable<bool> ShowHealthbar = new Bindable<bool>(true);
private readonly ScoreProcessor scoreProcessor;
private readonly HealthProcessor healthProcessor;
private readonly DrawableRuleset drawableRuleset;
private readonly IReadOnlyList<Mod> mods;
@ -76,10 +70,8 @@ namespace osu.Game.Screens.Play
private IEnumerable<Drawable> hideTargets => new Drawable[] { visibilityContainer, KeyCounter, topRightElements };
public HUDOverlay(ScoreProcessor scoreProcessor, HealthProcessor healthProcessor, DrawableRuleset drawableRuleset, IReadOnlyList<Mod> mods)
public HUDOverlay(DrawableRuleset drawableRuleset, IReadOnlyList<Mod> mods)
{
this.scoreProcessor = scoreProcessor;
this.healthProcessor = healthProcessor;
this.drawableRuleset = drawableRuleset;
this.mods = mods;
@ -87,7 +79,7 @@ namespace osu.Game.Screens.Play
Children = new Drawable[]
{
FailingLayer = CreateFailingLayer(),
CreateFailingLayer(),
visibilityContainer = new Container
{
RelativeSizeAxes = Axes.Both,
@ -106,8 +98,8 @@ namespace osu.Game.Screens.Play
HealthDisplay = CreateHealthDisplay(),
AccuracyCounter = CreateAccuracyCounter(),
ScoreCounter = CreateScoreCounter(),
ComboCounter = CreateComboCounter(),
HitErrorDisplay = CreateHitErrorDisplayOverlay(),
CreateComboCounter(),
CreateHitErrorDisplayOverlay(),
}
},
},
@ -159,12 +151,6 @@ namespace osu.Game.Screens.Play
[BackgroundDependencyLoader(true)]
private void load(OsuConfigManager config, NotificationOverlay notificationOverlay)
{
if (scoreProcessor != null)
BindScoreProcessor(scoreProcessor);
if (healthProcessor != null)
BindHealthProcessor(healthProcessor);
if (drawableRuleset != null)
{
BindDrawableRuleset(drawableRuleset);
@ -276,13 +262,13 @@ namespace osu.Game.Screens.Play
Progress.BindDrawableRuleset(drawableRuleset);
}
protected virtual SkinnableAccuracyCounter CreateAccuracyCounter() => new SkinnableAccuracyCounter();
protected SkinnableAccuracyCounter CreateAccuracyCounter() => new SkinnableAccuracyCounter();
protected virtual SkinnableScoreCounter CreateScoreCounter() => new SkinnableScoreCounter();
protected SkinnableScoreCounter CreateScoreCounter() => new SkinnableScoreCounter();
protected virtual SkinnableComboCounter CreateComboCounter() => new SkinnableComboCounter();
protected SkinnableComboCounter CreateComboCounter() => new SkinnableComboCounter();
protected virtual SkinnableHealthDisplay CreateHealthDisplay() => new SkinnableHealthDisplay();
protected SkinnableHealthDisplay CreateHealthDisplay() => new SkinnableHealthDisplay();
protected virtual FailingLayer CreateFailingLayer() => new FailingLayer
{
@ -315,32 +301,10 @@ namespace osu.Game.Screens.Play
AutoSizeAxes = Axes.Both,
};
protected virtual HitErrorDisplay CreateHitErrorDisplayOverlay() => new HitErrorDisplay(scoreProcessor, drawableRuleset?.FirstAvailableHitWindows);
protected virtual HitErrorDisplay CreateHitErrorDisplayOverlay() => new HitErrorDisplay(drawableRuleset?.FirstAvailableHitWindows);
protected virtual PlayerSettingsOverlay CreatePlayerSettingsOverlay() => new PlayerSettingsOverlay();
protected virtual void BindScoreProcessor(ScoreProcessor processor)
{
ScoreCounter?.Current.BindTo(processor.TotalScore);
AccuracyCounter?.Current.BindTo(processor.Accuracy);
ComboCounter?.Current.BindTo(processor.Combo);
if (HealthDisplay is IHealthDisplay shd)
{
processor.NewJudgement += judgement =>
{
if (judgement.IsHit && judgement.Type != HitResult.IgnoreHit)
shd.Flash(judgement);
};
}
}
protected virtual void BindHealthProcessor(HealthProcessor processor)
{
HealthDisplay?.BindHealthProcessor(processor);
FailingLayer?.BindHealthProcessor(processor);
}
public bool OnPressed(GlobalAction action)
{
switch (action)

View File

@ -203,9 +203,13 @@ namespace osu.Game.Screens.Play
ScoreProcessor.ApplyBeatmap(playableBeatmap);
ScoreProcessor.Mods.BindTo(Mods);
dependencies.CacheAs(ScoreProcessor);
HealthProcessor = ruleset.CreateHealthProcessor(playableBeatmap.HitObjects[0].StartTime);
HealthProcessor.ApplyBeatmap(playableBeatmap);
dependencies.CacheAs(HealthProcessor);
if (!ScoreProcessor.Mode.Disabled)
config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode);
@ -341,7 +345,7 @@ namespace osu.Game.Screens.Play
// display the cursor above some HUD elements.
DrawableRuleset.Cursor?.CreateProxy() ?? new Container(),
DrawableRuleset.ResumeOverlay?.CreateProxy() ?? new Container(),
HUDOverlay = new HUDOverlay(ScoreProcessor, HealthProcessor, DrawableRuleset, Mods.Value)
HUDOverlay = new HUDOverlay(DrawableRuleset, Mods.Value)
{
HoldToQuit =
{
@ -541,8 +545,10 @@ namespace osu.Game.Screens.Play
}
// if the score is ready for display but results screen has not been pushed yet (e.g. storyboard is still playing beyond gameplay), then transition to results screen instead of exiting.
if (prepareScoreForDisplayTask != null)
if (prepareScoreForDisplayTask != null && completionProgressDelegate == null)
{
updateCompletionState(true);
}
}
this.Exit();

View File

@ -28,6 +28,7 @@ using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.UI;
using osu.Game.Screens.Ranking.Expanded;
using osu.Game.Graphics.Containers;
namespace osu.Game.Screens.Select
{
@ -286,7 +287,7 @@ namespace osu.Game.Screens.Select
Margin = new MarginPadding { Top = 10 },
Direction = FillDirection.Horizontal,
AutoSizeAxes = Axes.Both,
Children = getMapper(metadata)
Child = getMapper(metadata),
},
infoLabelContainer = new FillFlowContainer
{
@ -406,24 +407,20 @@ namespace osu.Game.Screens.Select
});
}
private OsuSpriteText[] getMapper(BeatmapMetadata metadata)
private Drawable getMapper(BeatmapMetadata metadata)
{
if (string.IsNullOrEmpty(metadata.Author?.Username))
return Array.Empty<OsuSpriteText>();
if (metadata.Author == null)
return Empty();
return new[]
return new LinkFlowContainer(s =>
{
new OsuSpriteText
{
Text = "mapped by ",
Font = OsuFont.GetFont(size: 15),
},
new OsuSpriteText
{
Text = metadata.Author.Username,
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 15),
}
};
s.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 15);
}).With(d =>
{
d.AutoSizeAxes = Axes.Both;
d.AddText("mapped by ");
d.AddUserLink(metadata.Author);
});
}
protected override void Dispose(bool isDisposing)

View File

@ -71,6 +71,9 @@ namespace osu.Game.Screens.Select.Carousel
case SortMode.Author:
return string.Compare(BeatmapSet.Metadata.Author.Username, otherSet.BeatmapSet.Metadata.Author.Username, StringComparison.OrdinalIgnoreCase);
case SortMode.Source:
return string.Compare(BeatmapSet.Metadata.Source, otherSet.BeatmapSet.Metadata.Source, StringComparison.OrdinalIgnoreCase);
case SortMode.DateAdded:
return otherSet.BeatmapSet.DateAdded.CompareTo(BeatmapSet.DateAdded);

View File

@ -28,7 +28,10 @@ namespace osu.Game.Screens.Select.Filter
[Description("Rank Achieved")]
RankAchieved,
[Description("Source")]
Source,
[Description("Title")]
Title
Title,
}
}

View File

@ -4,14 +4,13 @@
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Screens.Play;
using osu.Game.Screens.Play.HUD;
using osuTK;
namespace osu.Game.Skinning
{
public class LegacyAccuracyCounter : PercentageCounter, IAccuracyCounter, ISkinnableComponent
public class LegacyAccuracyCounter : GameplayAccuracyCounter, ISkinnableComponent
{
private readonly ISkin skin;

View File

@ -16,7 +16,7 @@ using osuTK.Graphics;
namespace osu.Game.Skinning
{
public class LegacyHealthDisplay : CompositeDrawable, IHealthDisplay, ISkinnableComponent
public class LegacyHealthDisplay : HealthDisplay
{
private const double epic_cutoff = 0.5;
@ -28,12 +28,6 @@ namespace osu.Game.Skinning
private bool isNewStyle;
public Bindable<double> Current { get; } = new BindableDouble(1)
{
MinValue = 0,
MaxValue = 1
};
public LegacyHealthDisplay(Skin skin)
{
this.skin = skin;
@ -83,7 +77,7 @@ namespace osu.Game.Skinning
marker.Position = fill.Position + new Vector2(fill.DrawWidth, isNewStyle ? fill.DrawHeight / 2 : 0);
}
public void Flash(JudgementResult result) => marker.Flash(result);
protected override void Flash(JudgementResult result) => marker.Flash(result);
private static Texture getTexture(Skin skin, string name) => skin.GetTexture($"scorebar-{name}");
@ -254,7 +248,7 @@ namespace osu.Game.Skinning
Main.ScaleTo(1.4f).Then().ScaleTo(1, 200, Easing.Out);
}
public class LegacyHealthPiece : CompositeDrawable, IHealthDisplay
public class LegacyHealthPiece : CompositeDrawable
{
public Bindable<double> Current { get; } = new Bindable<double>();

View File

@ -1,24 +1,20 @@
// 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.Bindables;
using osu.Framework.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Screens.Play.HUD;
using osuTK;
namespace osu.Game.Skinning
{
public class LegacyScoreCounter : ScoreCounter, ISkinnableComponent
public class LegacyScoreCounter : GameplayScoreCounter, ISkinnableComponent
{
private readonly ISkin skin;
protected override double RollingDuration => 1000;
protected override Easing RollingEasing => Easing.Out;
public new Bindable<double> Current { get; } = new Bindable<double>();
public LegacyScoreCounter(ISkin skin)
: base(6)
{
@ -27,9 +23,6 @@ namespace osu.Game.Skinning
this.skin = skin;
// base class uses int for display, but externally we bind to ScoreProcessor as a double for now.
Current.BindValueChanged(v => base.Current.Value = (int)v.NewValue);
Scale = new Vector2(0.96f);
Margin = new MarginPadding(10);
}

View File

@ -4,7 +4,6 @@
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Input.Events;
using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Screens.Edit;
@ -46,7 +45,7 @@ namespace osu.Game.Tests.Visual
private void beatmapChanged(ValueChangedEvent<WorkingBeatmap> e)
{
Clock.ControlPointInfo = e.NewValue.Beatmap.ControlPointInfo;
Clock.ChangeSource((IAdjustableClock)e.NewValue.Track ?? new StopwatchClock());
Clock.ChangeSource(e.NewValue.Track);
Clock.ProcessFrame();
}

View File

@ -29,7 +29,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" />
<PackageReference Include="Microsoft.NETCore.Targets" Version="3.1.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="ppy.osu.Framework" Version="2021.506.0" />
<PackageReference Include="ppy.osu.Framework" Version="2021.507.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.422.0" />
<PackageReference Include="Sentry" Version="3.3.4" />
<PackageReference Include="SharpCompress" Version="0.28.2" />

View File

@ -70,7 +70,7 @@
<Reference Include="System.Net.Http" />
</ItemGroup>
<ItemGroup Label="Package References">
<PackageReference Include="ppy.osu.Framework.iOS" Version="2021.506.0" />
<PackageReference Include="ppy.osu.Framework.iOS" Version="2021.507.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.422.0" />
</ItemGroup>
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net5.0 / net6.0) -->
@ -93,7 +93,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="ppy.osu.Framework" Version="2021.506.0" />
<PackageReference Include="ppy.osu.Framework" Version="2021.507.0" />
<PackageReference Include="SharpCompress" Version="0.28.2" />
<PackageReference Include="NUnit" Version="3.13.2" />
<PackageReference Include="SharpRaven" Version="2.4.0" />