diff --git a/osu-framework b/osu-framework index 0b11b8b1ed..5dbb4a5134 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 0b11b8b1ed740ab74371cf178b5d956ac7bc1547 +Subproject commit 5dbb4a5134dacb2e98ab8f2af219039a72bd32e6 diff --git a/osu.Desktop.VisualTests/Tests/TestCaseDialogOverlay.cs b/osu.Desktop.VisualTests/Tests/TestCaseDialogOverlay.cs new file mode 100644 index 0000000000..1bfdc1df8a --- /dev/null +++ b/osu.Desktop.VisualTests/Tests/TestCaseDialogOverlay.cs @@ -0,0 +1,80 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Screens.Testing; +using osu.Game.Graphics; +using osu.Game.Overlays; +using osu.Game.Overlays.Dialog; + +namespace osu.Desktop.VisualTests.Tests +{ + class TestCaseDialogOverlay : TestCase + { + public override string Name => @"Dialog Overlay"; + public override string Description => @"Display dialogs"; + + DialogOverlay overlay; + + public override void Reset() + { + base.Reset(); + + Add(overlay = new DialogOverlay()); + + AddButton("dialog #1", () => overlay.Push(new PopupDialog + { + Icon = FontAwesome.fa_trash_o, + HeaderText = @"Confirm deletion of", + BodyText = @"Ayase Rie - Yuima-ru*World TVver.", + Buttons = new PopupDialogButton[] + { + new PopupDialogOkButton + { + Text = @"I never want to see this again.", + Action = () => System.Console.WriteLine(@"OK"), + }, + new PopupDialogCancelButton + { + Text = @"Firetruck, I still want quick ranks!", + Action = () => System.Console.WriteLine(@"Cancel"), + }, + }, + })); + + AddButton("dialog #2", () => overlay.Push(new PopupDialog + { + Icon = FontAwesome.fa_gear, + HeaderText = @"What do you want to do with", + BodyText = "Camellia as \"Bang Riot\" - Blastix Riotz", + Buttons = new PopupDialogButton[] + { + new PopupDialogOkButton + { + Text = @"Manage collections", + }, + new PopupDialogOkButton + { + Text = @"Delete...", + }, + new PopupDialogOkButton + { + Text = @"Remove from unplayed", + }, + new PopupDialogOkButton + { + Text = @"Clear local scores", + }, + new PopupDialogOkButton + { + Text = @"Edit", + }, + new PopupDialogCancelButton + { + Text = @"Cancel", + }, + }, + })); + } + } +} diff --git a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj index c3234d7a96..85d6d7055e 100644 --- a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj +++ b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj @@ -194,6 +194,7 @@ + diff --git a/osu.Game/Overlays/Pause/PauseButton.cs b/osu.Game/Graphics/UserInterface/DialogButton.cs similarity index 80% rename from osu.Game/Overlays/Pause/PauseButton.cs rename to osu.Game/Graphics/UserInterface/DialogButton.cs index a14c1fdade..fc7d142a8f 100644 --- a/osu.Game/Overlays/Pause/PauseButton.cs +++ b/osu.Game/Graphics/UserInterface/DialogButton.cs @@ -13,17 +13,15 @@ using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Sprites; -namespace osu.Game.Overlays.Pause +namespace osu.Game.Graphics.UserInterface { - public class PauseButton : ClickableContainer + public class DialogButton : ClickableContainer { private const float hover_width = 0.9f; private const float hover_duration = 500; private const float glow_fade_duration = 250; private const float click_duration = 200; - private Color4 backgroundColour = OsuColour.Gray(34); - private Color4 buttonColour; public Color4 ButtonColour { @@ -35,8 +33,21 @@ namespace osu.Game.Overlays.Pause { buttonColour = value; updateGlow(); - if (colourContainer == null) return; - colourContainer.Colour = ButtonColour; + colourContainer.Colour = value; + } + } + + private Color4 backgroundColour = OsuColour.Gray(34); + public Color4 BackgroundColour + { + get + { + return backgroundColour; + } + set + { + backgroundColour = value; + background.Colour = value; } } @@ -50,16 +61,30 @@ namespace osu.Game.Overlays.Pause set { text = value; - if (spriteText == null) return; spriteText.Text = Text; } } + private float textSize = 28; + internal float TextSize + { + get + { + return textSize; + } + set + { + textSize = value; + spriteText.TextSize = value; + } + } + public SampleChannel SampleClick, SampleHover; private Container backgroundContainer, colourContainer, glowContainer; - private Box leftGlow, centerGlow, rightGlow; + private Box leftGlow, centerGlow, rightGlow, background; private SpriteText spriteText; + private Vector2 hoverSpacing => new Vector2(3f, 0f); private bool didClick; // Used for making sure that the OnMouseDown animation can call instead of OnHoverLost's when clicking @@ -85,8 +110,9 @@ namespace osu.Game.Overlays.Pause protected override bool OnHover(Framework.Input.InputState state) { + spriteText.TransformSpacingTo(hoverSpacing, hover_duration, EasingTypes.OutElastic); + colourContainer.ResizeTo(new Vector2(hover_width, 1f), hover_duration, EasingTypes.OutElastic); - spriteText.TransformSpacingTo(new Vector2(3f, 0f), hover_duration, EasingTypes.OutElastic); glowContainer.FadeIn(glow_fade_duration, EasingTypes.Out); SampleHover?.Play(); return true; @@ -127,8 +153,10 @@ namespace osu.Game.Overlays.Pause rightGlow.ColourInfo = ColourInfo.GradientHorizontal(ButtonColour, new Color4(ButtonColour.R, ButtonColour.G, ButtonColour.B, 0f)); } - public PauseButton() + public DialogButton() { + RelativeSizeAxes = Axes.X; + Children = new Drawable[] { backgroundContainer = new Container @@ -137,12 +165,12 @@ namespace osu.Game.Overlays.Pause Width = 1f, Children = new Drawable[] { - new Box + background = new Box { RelativeSizeAxes = Axes.Both, - Colour = backgroundColour - } - } + Colour = backgroundColour, + }, + }, }, glowContainer = new Container { @@ -156,23 +184,23 @@ namespace osu.Game.Overlays.Pause RelativeSizeAxes = Axes.Both, Origin = Anchor.TopLeft, Anchor = Anchor.TopLeft, - Width = 0.125f + Width = 0.125f, }, centerGlow = new Box { RelativeSizeAxes = Axes.Both, Origin = Anchor.Centre, Anchor = Anchor.Centre, - Width = 0.75f + Width = 0.75f, }, rightGlow = new Box { RelativeSizeAxes = Axes.Both, Origin = Anchor.TopRight, Anchor = Anchor.TopRight, - Width = 0.125f - } - } + Width = 0.125f, + }, + }, }, new Container { @@ -194,7 +222,7 @@ namespace osu.Game.Overlays.Pause { Type = EdgeEffectType.Shadow, Colour = Color4.Black.Opacity(0.2f), - Radius = 5 + Radius = 5, }, Colour = ButtonColour, Shear = new Vector2(0.2f, 0), @@ -203,7 +231,7 @@ namespace osu.Game.Overlays.Pause new Box { EdgeSmoothness = new Vector2(2, 0), - RelativeSizeAxes = Axes.Both + RelativeSizeAxes = Axes.Both, }, new Container { @@ -217,13 +245,13 @@ namespace osu.Game.Overlays.Pause RelativeSizeAxes = Axes.Both, TriangleScale = 4, ColourDark = OsuColour.Gray(0.88f), - Shear = new Vector2(-0.2f, 0) - } - } + Shear = new Vector2(-0.2f, 0), + }, + }, }, - } - } - } + }, + }, + }, }, spriteText = new OsuSpriteText { @@ -234,8 +262,8 @@ namespace osu.Game.Overlays.Pause Font = "Exo2.0-Bold", Shadow = true, ShadowColour = new Color4(0, 0, 0, 0.1f), - Colour = Color4.White - } + Colour = Color4.White, + }, }; updateGlow(); diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index bfb506fd4f..9f7e3e04dc 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -42,6 +42,8 @@ namespace osu.Game private NotificationManager notificationManager; + private DialogOverlay dialogOverlay; + private Intro intro { get @@ -142,6 +144,11 @@ namespace osu.Game Origin = Anchor.TopRight, }).LoadAsync(this, overlayContent.Add); + (dialogOverlay = new DialogOverlay + { + Depth = -4, + }).LoadAsync(this, overlayContent.Add); + Logger.NewEntry += entry => { if (entry.Level < LogLevel.Important) return; @@ -155,6 +162,7 @@ namespace osu.Game Dependencies.Cache(options); Dependencies.Cache(musicController); Dependencies.Cache(notificationManager); + Dependencies.Cache(dialogOverlay); (Toolbar = new Toolbar { diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs new file mode 100644 index 0000000000..5256a90bf1 --- /dev/null +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -0,0 +1,245 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Primitives; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Transforms; +using osu.Framework.Input; +using osu.Game.Graphics; +using osu.Game.Graphics.Backgrounds; +using OpenTK; +using OpenTK.Graphics; +using OpenTK.Input; + +namespace osu.Game.Overlays.Dialog +{ + public class PopupDialog : FocusedOverlayContainer + { + public static readonly float ENTER_DURATION = 500; + public static readonly float EXIT_DURATION = 200; + private readonly Vector2 ringSize = new Vector2(100f); + private readonly Vector2 ringMinifiedSize = new Vector2(20f); + private readonly Vector2 buttonsEnterSpacing = new Vector2(0f, 50f); + + private Container content, ring; + private FillFlowContainer buttonsContainer; + private TextAwesome iconText; + private SpriteText header, body; + + public FontAwesome Icon + { + get { return iconText.Icon; } + set { iconText.Icon = value; } + } + + public string HeaderText + { + get { return header.Text; } + set { header.Text = value; } + } + + public string BodyText + { + get { return body.Text; } + set { body.Text = value; } + } + + public IEnumerable Buttons + { + get { return buttonsContainer.Children; } + set + { + buttonsContainer.Children = value; + foreach (PopupDialogButton b in value) + { + var action = b.Action; + b.Action = () => + { + Hide(); + action?.Invoke(); + }; + } + } + } + + private void pressButtonAtIndex(int index) + { + if (index < Buttons.Count()) + Buttons.Skip(index).First().TriggerClick(); + } + + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (args.Repeat) return false; + + if (args.Key == Key.Enter) + { + Buttons.OfType().FirstOrDefault()?.TriggerClick(); + return true; + } + + // press button at number if 1-9 on number row or keypad are pressed + var k = args.Key; + if (k >= Key.Number1 && k <= Key.Number9) + { + pressButtonAtIndex(k - Key.Number1); + return true; + } + + if (k >= Key.Keypad1 && k <= Key.Keypad9) + { + pressButtonAtIndex(k - Key.Keypad1); + return true; + } + + return base.OnKeyDown(state, args); + } + + protected override void PopIn() + { + base.PopIn(); + + // Reset various animations but only if the dialog animation fully completed + if (content.Alpha == 0) + { + buttonsContainer.TransformSpacingTo(buttonsEnterSpacing); + buttonsContainer.MoveToY(buttonsEnterSpacing.Y); + ring.ResizeTo(ringMinifiedSize); + } + + content.FadeIn(ENTER_DURATION, EasingTypes.OutQuint); + ring.ResizeTo(ringSize, ENTER_DURATION, EasingTypes.OutQuint); + buttonsContainer.TransformSpacingTo(Vector2.Zero, ENTER_DURATION, EasingTypes.OutQuint); + buttonsContainer.MoveToY(0, ENTER_DURATION, EasingTypes.OutQuint); + } + + protected override void PopOut() + { + base.PopOut(); + + content.FadeOut(EXIT_DURATION, EasingTypes.InSine); + } + + public PopupDialog() + { + RelativeSizeAxes = Axes.Both; + + Children = new Drawable[] + { + content = new Container + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Width = 0.4f, + Alpha = 0f, + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + EdgeEffect = new EdgeEffect + { + Type = EdgeEffectType.Shadow, + Colour = Color4.Black.Opacity(0.5f), + Radius = 8, + }, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex(@"221a21"), + }, + new Triangles + { + RelativeSizeAxes = Axes.Both, + ColourLight = OsuColour.FromHex(@"271e26"), + ColourDark = OsuColour.FromHex(@"1e171e"), + TriangleScale = 4, + }, + }, + }, + new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Position = new Vector2(0f, -50f), + Direction = FillDirection.Down, + Spacing = new Vector2(0f, 10f), + Children = new Drawable[] + { + new Container + { + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Size = ringSize, + Margin = new MarginPadding + { + Bottom = 30, + }, + Children = new Drawable[] + { + ring = new CircularContainer + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + BorderColour = Color4.White, + BorderThickness = 5f, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black.Opacity(0), + }, + iconText = new TextAwesome + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Icon = FontAwesome.fa_close, + TextSize = 50, + }, + }, + }, + }, + }, + header = new SpriteText + { + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Text = @"Header", + TextSize = 25, + Shadow = true, + }, + body = new SpriteText + { + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Text = @"Body", + TextSize = 18, + Shadow = true, + }, + }, + }, + buttonsContainer = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Down, + }, + }, + }, + }; + } + } +} diff --git a/osu.Game/Overlays/Dialog/PopupDialogButton.cs b/osu.Game/Overlays/Dialog/PopupDialogButton.cs new file mode 100644 index 0000000000..fe86423d8f --- /dev/null +++ b/osu.Game/Overlays/Dialog/PopupDialogButton.cs @@ -0,0 +1,20 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Overlays.Dialog +{ + public class PopupDialogButton : DialogButton + { + public PopupDialogButton() + { + Height = 50; + BackgroundColour = OsuColour.FromHex(@"150e14"); + TextSize = 18; + } + } +} diff --git a/osu.Game/Overlays/Dialog/PopupDialogCancelButton.cs b/osu.Game/Overlays/Dialog/PopupDialogCancelButton.cs new file mode 100644 index 0000000000..1449577b21 --- /dev/null +++ b/osu.Game/Overlays/Dialog/PopupDialogCancelButton.cs @@ -0,0 +1,20 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Game.Graphics; + +namespace osu.Game.Overlays.Dialog +{ + public class PopupDialogCancelButton : PopupDialogButton + { + [BackgroundDependencyLoader] + private void load(OsuColour colours, AudioManager audio) + { + ButtonColour = colours.Blue; + SampleHover = audio.Sample.Get(@"Menu/menuclick"); + SampleClick = audio.Sample.Get(@"Menu/menuback"); + } + } +} diff --git a/osu.Game/Overlays/Dialog/PopupDialogOKButton.cs b/osu.Game/Overlays/Dialog/PopupDialogOKButton.cs new file mode 100644 index 0000000000..46bf3debc4 --- /dev/null +++ b/osu.Game/Overlays/Dialog/PopupDialogOKButton.cs @@ -0,0 +1,20 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Game.Graphics; + +namespace osu.Game.Overlays.Dialog +{ + public class PopupDialogOkButton : PopupDialogButton + { + [BackgroundDependencyLoader] + private void load(OsuColour colours, AudioManager audio) + { + ButtonColour = colours.Pink; + SampleHover = audio.Sample.Get(@"Menu/menuclick"); + SampleClick = audio.Sample.Get(@"Menu/menu-play-click"); + } + } +} diff --git a/osu.Game/Overlays/DialogOverlay.cs b/osu.Game/Overlays/DialogOverlay.cs new file mode 100644 index 0000000000..95f08e9e24 --- /dev/null +++ b/osu.Game/Overlays/DialogOverlay.cs @@ -0,0 +1,82 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Transforms; +using osu.Game.Graphics; +using osu.Game.Overlays.Dialog; +using OpenTK.Graphics; + +namespace osu.Game.Overlays +{ + public class DialogOverlay : FocusedOverlayContainer + { + private Container dialogContainer; + private PopupDialog currentDialog; + + public void Push(PopupDialog dialog) + { + if (dialog == currentDialog) return; + + currentDialog?.Hide(); + currentDialog = dialog; + + dialogContainer.Add(currentDialog); + + currentDialog.Show(); + currentDialog.StateChanged += onDialogOnStateChanged; + State = Visibility.Visible; + } + + private void onDialogOnStateChanged(OverlayContainer dialog, Visibility v) + { + if (v != Visibility.Hidden) return; + + //handle the dialog being dismissed. + dialog.Delay(PopupDialog.EXIT_DURATION); + dialog.Expire(); + + if (dialog == currentDialog) + State = Visibility.Hidden; + } + + protected override void PopIn() + { + base.PopIn(); + FadeIn(PopupDialog.ENTER_DURATION, EasingTypes.OutQuint); + } + + protected override void PopOut() + { + base.PopOut(); + FadeOut(PopupDialog.EXIT_DURATION, EasingTypes.InSine); + } + + public DialogOverlay() + { + RelativeSizeAxes = Axes.Both; + + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black.Opacity(0.5f), + }, + }, + }, + dialogContainer = new Container + { + RelativeSizeAxes = Axes.Both, + }, + }; + } + } +} diff --git a/osu.Game/Overlays/Pause/PauseOverlay.cs b/osu.Game/Overlays/Pause/PauseOverlay.cs index a392c1dc3e..5c85f3db9e 100644 --- a/osu.Game/Overlays/Pause/PauseOverlay.cs +++ b/osu.Game/Overlays/Pause/PauseOverlay.cs @@ -156,7 +156,6 @@ namespace osu.Game.Overlays.Pause { new ResumeButton { - RelativeSizeAxes = Axes.X, Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, Height = button_height, @@ -164,7 +163,6 @@ namespace osu.Game.Overlays.Pause }, new RetryButton { - RelativeSizeAxes = Axes.X, Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, Height = button_height, @@ -176,7 +174,6 @@ namespace osu.Game.Overlays.Pause }, new QuitButton { - RelativeSizeAxes = Axes.X, Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, Height = button_height, diff --git a/osu.Game/Overlays/Pause/QuitButton.cs b/osu.Game/Overlays/Pause/QuitButton.cs index dc99669111..18b7c4eda9 100644 --- a/osu.Game/Overlays/Pause/QuitButton.cs +++ b/osu.Game/Overlays/Pause/QuitButton.cs @@ -5,10 +5,11 @@ using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Pause { - public class QuitButton : PauseButton + public class QuitButton : DialogButton { [BackgroundDependencyLoader] private void load(AudioManager audio) diff --git a/osu.Game/Overlays/Pause/ResumeButton.cs b/osu.Game/Overlays/Pause/ResumeButton.cs index 1aef384b0b..a5179cb58a 100644 --- a/osu.Game/Overlays/Pause/ResumeButton.cs +++ b/osu.Game/Overlays/Pause/ResumeButton.cs @@ -4,10 +4,11 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Pause { - public class ResumeButton : PauseButton + public class ResumeButton : DialogButton { [BackgroundDependencyLoader] private void load(AudioManager audio, OsuColour colours) diff --git a/osu.Game/Overlays/Pause/RetryButton.cs b/osu.Game/Overlays/Pause/RetryButton.cs index 003d31dfbb..ceab835915 100644 --- a/osu.Game/Overlays/Pause/RetryButton.cs +++ b/osu.Game/Overlays/Pause/RetryButton.cs @@ -4,10 +4,11 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Pause { - public class RetryButton : PauseButton + public class RetryButton : DialogButton { [BackgroundDependencyLoader] private void load(AudioManager audio, OsuColour colours) diff --git a/osu.Game/Screens/Select/BeatmapDeleteDialog.cs b/osu.Game/Screens/Select/BeatmapDeleteDialog.cs new file mode 100644 index 0000000000..a8216d3e4e --- /dev/null +++ b/osu.Game/Screens/Select/BeatmapDeleteDialog.cs @@ -0,0 +1,46 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Allocation; +using osu.Game.Beatmaps; +using osu.Game.Database; +using osu.Game.Graphics; +using osu.Game.Overlays.Dialog; + +namespace osu.Game +{ + public class BeatmapDeleteDialog : PopupDialog + { + private BeatmapDatabase database; + + [BackgroundDependencyLoader] + private void load(BeatmapDatabase beatmapDatabase) + { + database = beatmapDatabase; + } + + public BeatmapDeleteDialog(WorkingBeatmap beatmap) + { + Icon = FontAwesome.fa_trash_o; + HeaderText = @"Confirm deletion of"; + BodyText = $@"{beatmap?.Beatmap?.Metadata?.Artist} - {beatmap?.Beatmap?.Metadata?.Title}"; + Buttons = new PopupDialogButton[] + { + new PopupDialogOkButton + { + Text = @"Yes. Totally. Delete it.", + Action = () => + { + beatmap.Dispose(); + database.Delete(beatmap.BeatmapSetInfo); + }, + }, + new PopupDialogCancelButton + { + Text = @"Firetruck, I didn't mean to!", + }, + }; + } + } +} diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 3011b5bf23..06dc321f3b 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -27,6 +27,7 @@ using osu.Framework.Input; using OpenTK.Input; using System.Collections.Generic; using osu.Framework.Threading; +using osu.Game.Overlays; namespace osu.Game.Screens.Select { @@ -38,6 +39,7 @@ namespace osu.Game.Screens.Select private CarouselContainer carousel; private TrackManager trackManager; + private DialogOverlay dialogOverlay; private static readonly Vector2 wedged_container_size = new Vector2(0.5f, 225); private BeatmapInfoWedge beatmapInfoWedge; @@ -57,7 +59,7 @@ namespace osu.Game.Screens.Select FilterControl filter; [BackgroundDependencyLoader(permitNulls: true)] - private void load(BeatmapDatabase beatmaps, AudioManager audio, Framework.Game game, + private void load(BeatmapDatabase beatmaps, AudioManager audio, DialogOverlay dialog, Framework.Game game, OsuGame osuGame, OsuColour colours) { const float carousel_width = 640; @@ -122,7 +124,7 @@ namespace osu.Game.Screens.Select PreferredPlayMode = playMode.Value })).LoadAsync(Game, l => Push(player)); } - } + }, }; footer.AddButton(@"mods", colours.Yellow, null); @@ -142,6 +144,7 @@ namespace osu.Game.Screens.Select database.BeatmapSetRemoved += onBeatmapSetRemoved; trackManager = audio.Track; + dialogOverlay = dialog; sampleChangeDifficulty = audio.Sample.Get(@"SongSelect/select-difficulty"); sampleChangeBeatmap = audio.Sample.Get(@"SongSelect/select-expand"); @@ -382,12 +385,14 @@ namespace osu.Game.Screens.Select footer.StartButton.TriggerClick(); return true; case Key.Delete: - if (Beatmap != null) + if (state.Keyboard.ShiftPressed) { - Beatmap.Dispose(); - database.Delete(Beatmap.BeatmapSetInfo); + if (Beatmap != null) + dialogOverlay?.Push(new BeatmapDeleteDialog(Beatmap)); + + return true; } - return true; + break; } return base.OnKeyDown(state, args); diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index ddad06a476..1c5996b51e 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -274,13 +274,19 @@ - + + + + + + + @@ -301,6 +307,9 @@ + + +