diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs index 8ee065aaea..9981585f9e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Skinning; @@ -25,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces [BackgroundDependencyLoader] private void load(TextureStore textures) { - Child = new SkinnableDrawable("Play/osu/approachcircle", name => new Sprite { Texture = textures.Get(name) }); + Child = new SkinnableSprite("Play/osu/approachcircle"); } } } diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs new file mode 100644 index 0000000000..d0db193738 --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs @@ -0,0 +1,68 @@ +// Copyright (c) ppy Pty Ltd . 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.Game.Beatmaps; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Taiko.Beatmaps; +using osu.Game.Rulesets.Taiko.Mods; +using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Screens.Play; +using osu.Game.Tests.Visual; + +namespace osu.Game.Rulesets.Taiko.Tests +{ + public class TestSceneTaikoSuddenDeath : PlayerTestScene + { + public TestSceneTaikoSuddenDeath() + : base(new TaikoRuleset()) + { + } + + protected override bool AllowFail => true; + + protected override Player CreatePlayer(Ruleset ruleset) + { + Mods.Value = Mods.Value.Concat(new[] { new TaikoModSuddenDeath() }).ToArray(); + return new ScoreAccessiblePlayer(); + } + + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => + new TaikoBeatmap + { + HitObjects = + { + new Swell { StartTime = 1500 }, + new Hit { StartTime = 100000 }, + }, + BeatmapInfo = + { + Ruleset = new TaikoRuleset().RulesetInfo + } + }; + + [Test] + public void TestSpinnerDoesNotFail() + { + bool judged = false; + AddStep("Setup judgements", () => + { + judged = false; + ((ScoreAccessiblePlayer)Player).ScoreProcessor.NewJudgement += b => judged = true; + }); + AddUntilStep("swell judged", () => judged); + AddAssert("not failed", () => !Player.HasFailed); + } + + private class ScoreAccessiblePlayer : TestPlayer + { + public ScoreAccessiblePlayer() + : base(false, false) + { + } + + public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; + } + } +} diff --git a/osu.Game.Tests/Visual/Components/TestSceneIdleTracker.cs b/osu.Game.Tests/Visual/Components/TestSceneIdleTracker.cs index e97983dd8b..55aaeed8bf 100644 --- a/osu.Game.Tests/Visual/Components/TestSceneIdleTracker.cs +++ b/osu.Game.Tests/Visual/Components/TestSceneIdleTracker.cs @@ -14,94 +14,132 @@ namespace osu.Game.Tests.Visual.Components [TestFixture] public class TestSceneIdleTracker : ManualInputManagerTestScene { - private readonly IdleTrackingBox box1; - private readonly IdleTrackingBox box2; - private readonly IdleTrackingBox box3; - private readonly IdleTrackingBox box4; + private IdleTrackingBox box1; + private IdleTrackingBox box2; + private IdleTrackingBox box3; + private IdleTrackingBox box4; - public TestSceneIdleTracker() + private IdleTrackingBox[] boxes; + + [SetUp] + public void SetUp() => Schedule(() => { - Children = new Drawable[] + InputManager.MoveMouseTo(Vector2.Zero); + + Children = boxes = new[] { - box1 = new IdleTrackingBox(1000) + box1 = new IdleTrackingBox(2000) { + Name = "TopLeft", RelativeSizeAxes = Axes.Both, Colour = Color4.Red, Anchor = Anchor.TopLeft, Origin = Anchor.TopLeft, }, - box2 = new IdleTrackingBox(2000) + box2 = new IdleTrackingBox(4000) { + Name = "TopRight", RelativeSizeAxes = Axes.Both, Colour = Color4.Green, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, }, - box3 = new IdleTrackingBox(3000) + box3 = new IdleTrackingBox(6000) { + Name = "BottomLeft", RelativeSizeAxes = Axes.Both, Colour = Color4.Blue, Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, }, - box4 = new IdleTrackingBox(4000) + box4 = new IdleTrackingBox(8000) { + Name = "BottomRight", RelativeSizeAxes = Axes.Both, Colour = Color4.Orange, Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, }, }; - } + }); [Test] public void TestNudge() { - AddStep("move mouse to top left", () => InputManager.MoveMouseTo(box1.ScreenSpaceDrawQuad.Centre)); + AddStep("move to top left", () => InputManager.MoveMouseTo(box1)); - AddUntilStep("Wait for all idle", () => box1.IsIdle && box2.IsIdle && box3.IsIdle && box4.IsIdle); + waitForAllIdle(); AddStep("nudge mouse", () => InputManager.MoveMouseTo(box1.ScreenSpaceDrawQuad.Centre + new Vector2(1))); - AddAssert("check not idle", () => !box1.IsIdle); - AddAssert("check idle", () => box2.IsIdle); - AddAssert("check idle", () => box3.IsIdle); - AddAssert("check idle", () => box4.IsIdle); + checkIdleStatus(1, false); + checkIdleStatus(2, true); + checkIdleStatus(3, true); + checkIdleStatus(4, true); } [Test] public void TestMovement() { - AddStep("move mouse", () => InputManager.MoveMouseTo(box2.ScreenSpaceDrawQuad.Centre)); + AddStep("move to top right", () => InputManager.MoveMouseTo(box2)); - AddAssert("check not idle", () => box1.IsIdle); - AddAssert("check not idle", () => !box2.IsIdle); - AddAssert("check idle", () => box3.IsIdle); - AddAssert("check idle", () => box4.IsIdle); + checkIdleStatus(1, true); + checkIdleStatus(2, false); + checkIdleStatus(3, true); + checkIdleStatus(4, true); - AddStep("move mouse", () => InputManager.MoveMouseTo(box3.ScreenSpaceDrawQuad.Centre)); - AddStep("move mouse", () => InputManager.MoveMouseTo(box4.ScreenSpaceDrawQuad.Centre)); + AddStep("move to bottom left", () => InputManager.MoveMouseTo(box3)); + AddStep("move to bottom right", () => InputManager.MoveMouseTo(box4)); - AddAssert("check not idle", () => box1.IsIdle); - AddAssert("check not idle", () => !box2.IsIdle); - AddAssert("check idle", () => !box3.IsIdle); - AddAssert("check idle", () => !box4.IsIdle); + checkIdleStatus(1, true); + checkIdleStatus(2, false); + checkIdleStatus(3, false); + checkIdleStatus(4, false); - AddUntilStep("Wait for all idle", () => box1.IsIdle && box2.IsIdle && box3.IsIdle && box4.IsIdle); + waitForAllIdle(); } [Test] public void TestTimings() { - AddStep("move mouse", () => InputManager.MoveMouseTo(ScreenSpaceDrawQuad.Centre)); + AddStep("move to centre", () => InputManager.MoveMouseTo(Content)); + + checkIdleStatus(1, false); + checkIdleStatus(2, false); + checkIdleStatus(3, false); + checkIdleStatus(4, false); - AddAssert("check not idle", () => !box1.IsIdle && !box2.IsIdle && !box3.IsIdle && !box4.IsIdle); AddUntilStep("Wait for idle", () => box1.IsIdle); - AddAssert("check not idle", () => !box2.IsIdle && !box3.IsIdle && !box4.IsIdle); + + checkIdleStatus(1, true); + checkIdleStatus(2, false); + checkIdleStatus(3, false); + checkIdleStatus(4, false); + AddUntilStep("Wait for idle", () => box2.IsIdle); - AddAssert("check not idle", () => !box3.IsIdle && !box4.IsIdle); + + checkIdleStatus(1, true); + checkIdleStatus(2, true); + checkIdleStatus(3, false); + checkIdleStatus(4, false); + AddUntilStep("Wait for idle", () => box3.IsIdle); + checkIdleStatus(1, true); + checkIdleStatus(2, true); + checkIdleStatus(3, true); + checkIdleStatus(4, false); + + waitForAllIdle(); + } + + private void checkIdleStatus(int box, bool expectedIdle) + { + AddAssert($"box {box} is {(expectedIdle ? "idle" : "active")}", () => boxes[box - 1].IsIdle == expectedIdle); + } + + private void waitForAllIdle() + { AddUntilStep("Wait for all idle", () => box1.IsIdle && box2.IsIdle && box3.IsIdle && box4.IsIdle); } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs index f06f72615b..f4e8a68819 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs @@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void LoadComplete() { base.LoadComplete(); - ScoreProcessor.FailConditions += _ => true; + ScoreProcessor.FailConditions += (_, __) => true; } } } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 5a903b9417..80408ab43b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -76,7 +76,7 @@ namespace osu.Game.Tests.Visual.UserInterface public void TestOsuMods() { var ruleset = rulesets.AvailableRulesets.First(r => r.ID == 0); - AddStep("change ruleset", () => { Ruleset.Value = ruleset; }); + changeRuleset(ruleset); var instance = ruleset.CreateInstance(); @@ -108,7 +108,7 @@ namespace osu.Game.Tests.Visual.UserInterface public void TestManiaMods() { var ruleset = rulesets.AvailableRulesets.First(r => r.ID == 3); - AddStep("change ruleset", () => { Ruleset.Value = ruleset; }); + changeRuleset(ruleset); testRankedText(ruleset.CreateInstance().GetModsFor(ModType.Conversion).First(m => m is ManiaModRandom)); } @@ -119,7 +119,7 @@ namespace osu.Game.Tests.Visual.UserInterface var rulesetOsu = rulesets.AvailableRulesets.First(r => r.ID == 0); var rulesetMania = rulesets.AvailableRulesets.First(r => r.ID == 3); - AddStep("change ruleset to null", () => { Ruleset.Value = null; }); + changeRuleset(null); var instance = rulesetOsu.CreateInstance(); var easierMods = instance.GetModsFor(ModType.DifficultyReduction); @@ -127,15 +127,15 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("set mods externally", () => { modDisplay.Current.Value = new[] { noFailMod }; }); - AddStep("change ruleset to osu", () => { Ruleset.Value = rulesetOsu; }); + changeRuleset(rulesetOsu); AddAssert("ensure mods still selected", () => modDisplay.Current.Value.Single(m => m is OsuModNoFail) != null); - AddStep("change ruleset to mania", () => { Ruleset.Value = rulesetMania; }); + changeRuleset(rulesetMania); AddAssert("ensure mods not selected", () => !modDisplay.Current.Value.Any(m => m is OsuModNoFail)); - AddStep("change ruleset to osu", () => { Ruleset.Value = rulesetOsu; }); + changeRuleset(rulesetOsu); AddAssert("ensure mods not selected", () => !modDisplay.Current.Value.Any()); } @@ -216,14 +216,11 @@ namespace osu.Game.Tests.Visual.UserInterface private void testRankedText(Mod mod) { - waitForLoad(); - AddAssert("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0); + AddUntilStep("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0); selectNext(mod); - waitForLoad(); - AddAssert("check for unranked", () => modSelect.UnrankedLabel.Alpha != 0); + AddUntilStep("check for unranked", () => modSelect.UnrankedLabel.Alpha != 0); selectPrevious(mod); - waitForLoad(); - AddAssert("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0); + AddUntilStep("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0); } private void selectNext(Mod mod) => AddStep($"left click {mod.Name}", () => modSelect.GetModButton(mod)?.SelectNext(1)); @@ -232,7 +229,6 @@ namespace osu.Game.Tests.Visual.UserInterface private void checkSelected(Mod mod) { - waitForLoad(); AddAssert($"check {mod.Name} is selected", () => { var button = modSelect.GetModButton(mod); @@ -240,14 +236,17 @@ namespace osu.Game.Tests.Visual.UserInterface }); } - private void waitForLoad() + private void changeRuleset(RulesetInfo ruleset) { - AddUntilStep("wait for icons to load", () => modSelect.AllLoaded); + AddStep($"change ruleset to {ruleset}", () => { Ruleset.Value = ruleset; }); + waitForLoad(); } + private void waitForLoad() => + AddUntilStep("wait for icons to load", () => modSelect.AllLoaded); + private void checkNotSelected(Mod mod) { - waitForLoad(); AddAssert($"check {mod.Name} is not selected", () => { var button = modSelect.GetModButton(mod); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneNumberBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNumberBox.cs new file mode 100644 index 0000000000..f73450db60 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNumberBox.cs @@ -0,0 +1,55 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Tests.Visual.UserInterface +{ + [TestFixture] + public class TestSceneNumberBox : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(OsuNumberBox), + }; + + private OsuNumberBox numberBox; + + [BackgroundDependencyLoader] + private void load() + { + Child = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + Padding = new MarginPadding { Horizontal = 250 }, + Child = numberBox = new OsuNumberBox + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + PlaceholderText = "Insert numbers here" + } + }; + + clearInput(); + AddStep("enter numbers", () => numberBox.Text = "987654321"); + expectedValue("987654321"); + clearInput(); + AddStep("enter text + single number", () => numberBox.Text = "1 hello 2 world 3"); + expectedValue("123"); + clearInput(); + } + + private void clearInput() => AddStep("clear input", () => numberBox.Text = null); + + private void expectedValue(string value) => AddAssert("expect number", () => numberBox.Text == value); + } +} diff --git a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs index 1dc91abe6d..b036350879 100644 --- a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs @@ -183,7 +183,7 @@ namespace osu.Game.Tournament.Screens.Editors AutoSizeAxes = Axes.Both, Children = new Drawable[] { - new SettingsTextBox + new SettingsNumberBox { LabelText = "Beatmap ID", RelativeSizeAxes = Axes.None, diff --git a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs index 93745acabf..a4479f3cfd 100644 --- a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs @@ -231,7 +231,7 @@ namespace osu.Game.Tournament.Screens.Editors AutoSizeAxes = Axes.Both, Children = new Drawable[] { - new SettingsTextBox + new SettingsNumberBox { LabelText = "User ID", RelativeSizeAxes = Axes.None, diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs index cfa44537d6..9e1888b44b 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs @@ -5,7 +5,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; @@ -191,8 +190,6 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components public RoundDisplay() { - CornerRadius = 10; - Masking = true; Width = 200; Height = 20; } @@ -208,11 +205,6 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components { InternalChildren = new Drawable[] { - new Box - { - Colour = new Color4(47, 71, 67, 255), - RelativeSizeAxes = Axes.Both, - }, new OsuSpriteText { Anchor = Anchor.Centre, diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs index 67d6bc4fa6..dacd98d3b8 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs @@ -51,8 +51,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components name = round.Name.GetBoundCopy(); name.BindValueChanged(n => textName.Text = ((losers ? "Losers " : "") + round.Name).ToUpper(), true); - description = round.Name.GetBoundCopy(); - description.BindValueChanged(n => textDescription.Text = round.Description.Value.ToUpper(), true); + description = round.Description.GetBoundCopy(); + description.BindValueChanged(n => textDescription.Text = round.Description.Value?.ToUpper(), true); } } } diff --git a/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs b/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs index 0db3348e5d..1fee2b29e8 100644 --- a/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs +++ b/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs @@ -6,17 +6,25 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osuTK; namespace osu.Game.Tournament.Screens.Showcase { public class TournamentLogo : CompositeDrawable { - public TournamentLogo() + public TournamentLogo(bool includeRoundBackground = true) { RelativeSizeAxes = Axes.X; - Height = 95; Margin = new MarginPadding { Vertical = 5 }; + + if (includeRoundBackground) + { + AutoSizeAxes = Axes.Y; + } + else + { + Masking = true; + Height = 100; + } } [BackgroundDependencyLoader] @@ -27,9 +35,6 @@ namespace osu.Game.Tournament.Screens.Showcase Texture = textures.Get("game-screen-logo"), Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - FillMode = FillMode.Fit, - RelativeSizeAxes = Axes.Both, - Size = Vector2.One }; } } diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs index 2cb4ffe4e9..c901a5c7ef 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs @@ -34,7 +34,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro RelativeSizeAxes = Axes.Both, Loop = true, }, - new TournamentLogo(), + new TournamentLogo(false), mainContainer = new Container { RelativeSizeAxes = Axes.Both, diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 628f64dc73..06fb52da77 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -222,6 +222,7 @@ namespace osu.Game.Tournament sw.Write(JsonConvert.SerializeObject(ladder, new JsonSerializerSettings { + Formatting = Formatting.Indented, NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore, })); diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 6e162ca95e..e12c46ef16 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -9,7 +9,6 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Bindables; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.IO.Stores; using osu.Game.Beatmaps; @@ -26,7 +25,7 @@ namespace osu.Game.Audio private TrackManagerPreviewTrack current; [BackgroundDependencyLoader] - private void load(AudioManager audio, FrameworkConfigManager config) + private void load(AudioManager audio) { // this is a temporary solution to get around muting ourselves. // todo: update this once we have a BackgroundTrackManager or similar. @@ -36,8 +35,6 @@ namespace osu.Game.Audio trackStore.AddAdjustment(AdjustableProperty.Volume, audio.VolumeTrack); this.audio = audio; - - config.BindWith(FrameworkSetting.VolumeMusic, trackStore.Volume); } /// diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs index 5ead5987a1..47324ee646 100644 --- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; @@ -15,17 +14,6 @@ namespace osu.Game.Graphics.UserInterface { public class OsuCheckbox : Checkbox { - private Bindable bindable; - - public Bindable Bindable - { - set - { - bindable = value; - Current.BindTo(bindable); - } - } - public Color4 CheckedColor { get; set; } = Color4.Cyan; public Color4 UncheckedColor { get; set; } = Color4.White; public int FadeDuration { get; set; } diff --git a/osu.Game/Graphics/UserInterface/OsuNumberBox.cs b/osu.Game/Graphics/UserInterface/OsuNumberBox.cs new file mode 100644 index 0000000000..36288c745a --- /dev/null +++ b/osu.Game/Graphics/UserInterface/OsuNumberBox.cs @@ -0,0 +1,10 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Graphics.UserInterface +{ + public class OsuNumberBox : OsuTextBox + { + protected override bool CanAddCharacter(char character) => char.IsNumber(character); + } +} diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 692e7189a3..35684849a3 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -181,10 +181,10 @@ namespace osu.Game configSkin.ValueChanged += skinId => SkinManager.CurrentSkinInfo.Value = SkinManager.Query(s => s.ID == skinId.NewValue) ?? SkinInfo.Default; configSkin.TriggerChange(); - LocalConfig.BindWith(OsuSetting.VolumeInactive, userInactiveVolume); - IsActive.BindValueChanged(active => updateActiveState(active.NewValue), true); + Audio.AddAdjustment(AdjustableProperty.Volume, inactiveVolumeFade); + Beatmap.BindValueChanged(beatmapChanged, true); } @@ -707,22 +707,14 @@ namespace osu.Game #region Inactive audio dimming - private readonly BindableDouble userInactiveVolume = new BindableDouble(); - private readonly BindableDouble inactiveVolumeFade = new BindableDouble(); private void updateActiveState(bool isActive) { if (isActive) - { - this.TransformBindableTo(inactiveVolumeFade, 1, 500, Easing.OutQuint) - .Finally(_ => Audio.RemoveAdjustment(AdjustableProperty.Volume, inactiveVolumeFade)); //wait for the transition to finish to remove the inactive audio adjustment - } + this.TransformBindableTo(inactiveVolumeFade, 1, 400, Easing.OutQuint); else - { - Audio.AddAdjustment(AdjustableProperty.Volume, inactiveVolumeFade); - this.TransformBindableTo(inactiveVolumeFade, userInactiveVolume.Value, 1500, Easing.OutSine); - } + this.TransformBindableTo(inactiveVolumeFade, LocalConfig.Get(OsuSetting.VolumeInactive), 4000, Easing.OutQuint); } #endregion diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index 5949f1fcd4..1022edfe81 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -134,9 +134,9 @@ namespace osu.Game.Overlays.Dialog Origin = Anchor.BottomCentre, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Position = new Vector2(0f, -50f), Direction = FillDirection.Vertical, Spacing = new Vector2(0f, 10f), + Padding = new MarginPadding { Bottom = 10 }, Children = new Drawable[] { new Container @@ -144,10 +144,6 @@ namespace osu.Game.Overlays.Dialog Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, Size = ringSize, - Margin = new MarginPadding - { - Bottom = 30, - }, Children = new Drawable[] { ring = new CircularContainer @@ -181,15 +177,15 @@ namespace osu.Game.Overlays.Dialog Anchor = Anchor.TopCentre, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding(15), TextAnchor = Anchor.TopCentre, }, body = new OsuTextFlowContainer(t => t.Font = t.Font.With(size: 18)) { + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + TextAnchor = Anchor.TopCentre, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding(15), - TextAnchor = Anchor.TopCentre, }, }, }, diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index 320aa707e2..41160d10ec 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -56,16 +56,12 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.X, Children = new[] { - new NotificationSection + new NotificationSection(@"Notifications", @"Clear All") { - Title = @"Notifications", - ClearText = @"Clear All", AcceptTypes = new[] { typeof(SimpleNotification) } }, - new NotificationSection + new NotificationSection(@"Running Tasks", @"Cancel All") { - Title = @"Running Tasks", - ClearText = @"Cancel All", AcceptTypes = new[] { typeof(ProgressNotification) } } } diff --git a/osu.Game/Overlays/Notifications/NotificationSection.cs b/osu.Game/Overlays/Notifications/NotificationSection.cs index 4608d78324..f9278bbbd2 100644 --- a/osu.Game/Overlays/Notifications/NotificationSection.cs +++ b/osu.Game/Overlays/Notifications/NotificationSection.cs @@ -17,10 +17,7 @@ namespace osu.Game.Overlays.Notifications { public class NotificationSection : AlwaysUpdateFillFlowContainer { - private OsuSpriteText titleText; - private OsuSpriteText countText; - - private ClearAllButton clearButton; + private OsuSpriteText countDrawable; private FlowContainer notifications; @@ -35,28 +32,14 @@ namespace osu.Game.Overlays.Notifications public IEnumerable AcceptTypes; - private string clearText; + private readonly string clearButtonText; - public string ClearText + private readonly string titleText; + + public NotificationSection(string title, string clearButtonText) { - get => clearText; - set - { - clearText = value; - if (clearButton != null) clearButton.Text = clearText; - } - } - - private string title; - - public string Title - { - get => title; - set - { - title = value; - if (titleText != null) titleText.Text = title.ToUpperInvariant(); - } + this.clearButtonText = clearButtonText; + titleText = title; } [BackgroundDependencyLoader] @@ -82,9 +65,9 @@ namespace osu.Game.Overlays.Notifications AutoSizeAxes = Axes.Y, Children = new Drawable[] { - clearButton = new ClearAllButton + new ClearAllButton { - Text = clearText, + Text = clearButtonText, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, Action = clearAll @@ -99,12 +82,12 @@ namespace osu.Game.Overlays.Notifications AutoSizeAxes = Axes.Both, Children = new Drawable[] { - titleText = new OsuSpriteText + new OsuSpriteText { - Text = title.ToUpperInvariant(), + Text = titleText.ToUpperInvariant(), Font = OsuFont.GetFont(weight: FontWeight.Black) }, - countText = new OsuSpriteText + countDrawable = new OsuSpriteText { Text = "3", Colour = colours.Yellow, @@ -134,7 +117,7 @@ namespace osu.Game.Overlays.Notifications { base.Update(); - countText.Text = notifications.Children.Count(c => c.Alpha > 0.99f).ToString(); + countDrawable.Text = notifications.Children.Count(c => c.Alpha > 0.99f).ToString(); } private class ClearAllButton : OsuClickableContainer diff --git a/osu.Game/Overlays/Profile/ProfileSection.cs b/osu.Game/Overlays/Profile/ProfileSection.cs index 4d891384e8..f3590d4bb7 100644 --- a/osu.Game/Overlays/Profile/ProfileSection.cs +++ b/osu.Game/Overlays/Profile/ProfileSection.cs @@ -1,25 +1,29 @@ // Copyright (c) ppy Pty Ltd . 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.Extensions.Color4Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Sprites; using osu.Game.Users; -using osuTK; -using osuTK.Graphics; namespace osu.Game.Overlays.Profile { - public abstract class ProfileSection : FillFlowContainer + public abstract class ProfileSection : Container { public abstract string Title { get; } public abstract string Identifier { get; } private readonly FillFlowContainer content; + private readonly Box background; + private readonly Box underscore; protected override Container Content => content; @@ -27,50 +31,109 @@ namespace osu.Game.Overlays.Profile protected ProfileSection() { - Direction = FillDirection.Vertical; AutoSizeAxes = Axes.Y; RelativeSizeAxes = Axes.X; + InternalChildren = new Drawable[] { - new OsuSpriteText + background = new Box { - Text = Title, - Font = OsuFont.GetFont(size: 20, weight: FontWeight.Regular, italics: true), - Margin = new MarginPadding - { - Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, - Vertical = 10 - } + RelativeSizeAxes = Axes.Both, }, - content = new FillFlowContainer + new SectionTriangles + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + }, + new FillFlowContainer { Direction = FillDirection.Vertical, AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, - Padding = new MarginPadding + Children = new Drawable[] { - Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, - Bottom = 20 - } - }, - new Box - { - RelativeSizeAxes = Axes.X, - Height = 1, - Colour = OsuColour.Gray(34), - EdgeSmoothness = new Vector2(1) + new Container + { + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding + { + Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, + Top = 15, + Bottom = 10, + }, + Children = new Drawable[] + { + new OsuSpriteText + { + Text = Title, + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold), + }, + underscore = new Box + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.TopCentre, + Margin = new MarginPadding { Top = 4 }, + RelativeSizeAxes = Axes.X, + Height = 2, + } + } + }, + content = new FillFlowContainer + { + Direction = FillDirection.Vertical, + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Padding = new MarginPadding + { + Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, + Bottom = 20 + } + }, + }, } }; + } - // placeholder - Add(new OsuSpriteText + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.GreySeafoamDarker; + underscore.Colour = colours.Seafoam; + } + + private class SectionTriangles : Container + { + private readonly Triangles triangles; + private readonly Box foreground; + + public SectionTriangles() { - Text = @"coming soon!", - Colour = Color4.Gray, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Margin = new MarginPadding { Top = 100, Bottom = 100 } - }); + RelativeSizeAxes = Axes.X; + Height = 100; + Masking = true; + Children = new Drawable[] + { + triangles = new Triangles + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.Both, + TriangleScale = 3, + }, + foreground = new Box + { + RelativeSizeAxes = Axes.Both, + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + triangles.ColourLight = colours.GreySeafoamDark; + triangles.ColourDark = colours.GreySeafoamDarker.Darken(0.2f); + foreground.Colour = ColourInfo.GradientVertical(colours.GreySeafoamDarker, colours.GreySeafoamDarker.Opacity(0)); + } } } } diff --git a/osu.Game/Overlays/Settings/SettingsNumberBox.cs b/osu.Game/Overlays/Settings/SettingsNumberBox.cs new file mode 100644 index 0000000000..cb7e63ae6f --- /dev/null +++ b/osu.Game/Overlays/Settings/SettingsNumberBox.cs @@ -0,0 +1,17 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Overlays.Settings +{ + public class SettingsNumberBox : SettingsItem + { + protected override Drawable CreateControl() => new OsuNumberBox + { + Margin = new MarginPadding { Top = 5 }, + RelativeSizeAxes = Axes.X, + }; + } +} diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index 6c9b757c13..5b8c2bb357 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -4,6 +4,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; @@ -21,7 +22,7 @@ namespace osu.Game.Overlays private ProfileSection[] sections; private GetUserRequest userReq; protected ProfileHeader Header; - private SectionsContainer sectionsContainer; + private ProfileSectionsContainer sectionsContainer; private ProfileTabControl tabs; public const float CONTENT_X_MARGIN = 70; @@ -63,12 +64,11 @@ namespace osu.Game.Overlays Add(new Box { RelativeSizeAxes = Axes.Both, - Colour = OsuColour.Gray(0.2f) + Colour = OsuColour.Gray(0.1f) }); - Add(sectionsContainer = new SectionsContainer + Add(sectionsContainer = new ProfileSectionsContainer { - RelativeSizeAxes = Axes.Both, ExpandableHeader = Header = new ProfileHeader(), FixedHeader = tabs, HeaderBackground = new Box @@ -169,5 +169,21 @@ namespace osu.Game.Overlays } } } + + private class ProfileSectionsContainer : SectionsContainer + { + public ProfileSectionsContainer() + { + RelativeSizeAxes = Axes.Both; + } + + protected override FlowContainer CreateScrollContentContainer() => new FillFlowContainer + { + Direction = FillDirection.Vertical, + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Spacing = new Vector2(0, 20), + }; + } } } diff --git a/osu.Game/Rulesets/Mods/ModPerfect.cs b/osu.Game/Rulesets/Mods/ModPerfect.cs index e984fb8574..0994d1f7d3 100644 --- a/osu.Game/Rulesets/Mods/ModPerfect.cs +++ b/osu.Game/Rulesets/Mods/ModPerfect.cs @@ -3,6 +3,7 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mods @@ -14,6 +15,6 @@ namespace osu.Game.Rulesets.Mods public override IconUsage Icon => OsuIcon.ModPerfect; public override string Description => "SS or quit."; - protected override bool FailCondition(ScoreProcessor scoreProcessor) => scoreProcessor.Accuracy.Value != 1; + protected override bool FailCondition(ScoreProcessor scoreProcessor, JudgementResult result) => scoreProcessor.Accuracy.Value != 1; } } diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index 809661db8e..e332abd914 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; @@ -27,6 +28,6 @@ namespace osu.Game.Rulesets.Mods public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; - protected virtual bool FailCondition(ScoreProcessor scoreProcessor) => scoreProcessor.Combo.Value == 0; + protected virtual bool FailCondition(ScoreProcessor scoreProcessor, JudgementResult result) => scoreProcessor.Combo.Value == 0 && result.Judgement.AffectsCombo; } } diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index ce94ca9c7d..47ce28db4c 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Scoring /// /// Additional conditions on top of that cause a failing state. /// - public event Func FailConditions; + public event Func FailConditions; /// /// The current total score. @@ -151,12 +151,12 @@ namespace osu.Game.Rulesets.Scoring /// This can only ever notify subscribers once. /// /// - protected void UpdateFailed() + protected void UpdateFailed(JudgementResult result) { if (HasFailed) return; - if (!DefaultFailCondition && FailConditions?.Invoke(this) != true) + if (!DefaultFailCondition && FailConditions?.Invoke(this, result) != true) return; if (Failed?.Invoke() != false) @@ -287,7 +287,7 @@ namespace osu.Game.Rulesets.Scoring ApplyResult(result); updateScore(); - UpdateFailed(); + UpdateFailed(result); NotifyNewJudgement(result); } diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 5252b41dfd..a56d153646 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -257,7 +257,7 @@ namespace osu.Game.Screens.Multi private void subScreenChanged(IScreen newScreen) { updatePollingRate(isIdle.Value); - createButton.FadeTo(newScreen is MatchSubScreen ? 0 : 1, 200); + createButton.FadeTo(newScreen is LoungeSubScreen ? 1 : 0, 200); updateTrack(); } diff --git a/osu.Game/Screens/Play/PlayerSettings/DiscussionSettings.cs b/osu.Game/Screens/Play/PlayerSettings/DiscussionSettings.cs index 5963352e5b..bb4eea47ca 100644 --- a/osu.Game/Screens/Play/PlayerSettings/DiscussionSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/DiscussionSettings.cs @@ -20,7 +20,7 @@ namespace osu.Game.Screens.Play.PlayerSettings new PlayerCheckbox { LabelText = "Show floating comments", - Bindable = config.GetBindable(OsuSetting.FloatingComments) + Current = config.GetBindable(OsuSetting.FloatingComments) }, new FocusedTextBox { diff --git a/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs b/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs index 826be792bd..7a8696e27c 100644 --- a/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs @@ -25,6 +25,6 @@ namespace osu.Game.Screens.Play.PlayerSettings } [BackgroundDependencyLoader] - private void load(OsuConfigManager config) => mouseButtonsCheckbox.Bindable = config.GetBindable(OsuSetting.MouseDisableButtons); + private void load(OsuConfigManager config) => mouseButtonsCheckbox.Current = config.GetBindable(OsuSetting.MouseDisableButtons); } } diff --git a/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs index aec42eb024..1c8628f704 100644 --- a/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs @@ -47,9 +47,9 @@ namespace osu.Game.Screens.Play.PlayerSettings { dimSliderBar.Bindable = config.GetBindable(OsuSetting.DimLevel); blurSliderBar.Bindable = config.GetBindable(OsuSetting.BlurLevel); - showStoryboardToggle.Bindable = config.GetBindable(OsuSetting.ShowStoryboard); - beatmapSkinsToggle.Bindable = config.GetBindable(OsuSetting.BeatmapSkins); - beatmapHitsoundsToggle.Bindable = config.GetBindable(OsuSetting.BeatmapHitsounds); + showStoryboardToggle.Current = config.GetBindable(OsuSetting.ShowStoryboard); + beatmapSkinsToggle.Current = config.GetBindable(OsuSetting.BeatmapSkins); + beatmapHitsoundsToggle.Current = config.GetBindable(OsuSetting.BeatmapHitsounds); } } } diff --git a/osu.Game/Skinning/SkinnableDrawable.cs b/osu.Game/Skinning/SkinnableDrawable.cs index 3ca58dc625..995cb15136 100644 --- a/osu.Game/Skinning/SkinnableDrawable.cs +++ b/osu.Game/Skinning/SkinnableDrawable.cs @@ -15,6 +15,10 @@ namespace osu.Game.Skinning } } + /// + /// A drawable which can be skinned via an . + /// + /// The type of drawable. public class SkinnableDrawable : SkinReloadableDrawable where T : Drawable { @@ -23,48 +27,63 @@ namespace osu.Game.Skinning /// protected Drawable Drawable { get; private set; } - private readonly Func createDefault; - private readonly string componentName; private readonly bool restrictSize; /// - /// + /// Create a new skinnable drawable. /// /// The namespace-complete resource name for this skinnable element. /// A function to create the default skin implementation of this element. /// A conditional to decide whether to allow fallback to the default implementation if a skinned element is not present. /// Whether a user-skin drawable should be limited to the size of our parent. public SkinnableDrawable(string name, Func defaultImplementation, Func allowFallback = null, bool restrictSize = true) + : this(name, allowFallback, restrictSize) + { + createDefault = defaultImplementation; + } + + protected SkinnableDrawable(string name, Func allowFallback = null, bool restrictSize = true) : base(allowFallback) { componentName = name; - createDefault = defaultImplementation; this.restrictSize = restrictSize; RelativeSizeAxes = Axes.Both; } + private readonly Func createDefault; + + protected virtual T CreateDefault(string name) => createDefault(name); + + /// + /// Whether to apply size restrictions (specified via ) to the default implementation. + /// + protected virtual bool ApplySizeRestrictionsToDefault => false; + protected override void SkinChanged(ISkinSource skin, bool allowFallback) { Drawable = skin.GetDrawableComponent(componentName); + bool isDefault = false; + + if (Drawable == null && allowFallback) + { + Drawable = CreateDefault(componentName); + isDefault = true; + } + if (Drawable != null) { - if (restrictSize) + if (restrictSize && (!isDefault || ApplySizeRestrictionsToDefault)) { Drawable.RelativeSizeAxes = Axes.Both; Drawable.Size = Vector2.One; Drawable.Scale = Vector2.One; Drawable.FillMode = FillMode.Fit; } - } - else if (allowFallback) - Drawable = createDefault(componentName); - if (Drawable != null) - { Drawable.Origin = Anchor.Centre; Drawable.Anchor = Anchor.Centre; diff --git a/osu.Game/Skinning/SkinnableSprite.cs b/osu.Game/Skinning/SkinnableSprite.cs new file mode 100644 index 0000000000..ceb1ed0f70 --- /dev/null +++ b/osu.Game/Skinning/SkinnableSprite.cs @@ -0,0 +1,28 @@ +// Copyright (c) ppy Pty Ltd . 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.Sprites; +using osu.Framework.Graphics.Textures; + +namespace osu.Game.Skinning +{ + /// + /// A skinnable element which uses a stable sprite and can therefore share implementation logic. + /// + public class SkinnableSprite : SkinnableDrawable + { + protected override bool ApplySizeRestrictionsToDefault => true; + + [Resolved] + private TextureStore textures { get; set; } + + public SkinnableSprite(string name, Func allowFallback = null, bool restrictSize = true) + : base(name, allowFallback, restrictSize) + { + } + + protected override Sprite CreateDefault(string name) => new Sprite { Texture = textures.Get(name) }; + } +} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 9dd8c8572e..563e90cec9 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 1482b6ed03..a36638cf84 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + +