diff --git a/osu.Game.Tests/Visual/Navigation/TestFirstRunSetup.cs b/osu.Game.Tests/Visual/Navigation/TestFirstRunSetup.cs new file mode 100644 index 0000000000..ab49334af1 --- /dev/null +++ b/osu.Game.Tests/Visual/Navigation/TestFirstRunSetup.cs @@ -0,0 +1,15 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; + +namespace osu.Game.Tests.Visual.Navigation +{ + public class TestFirstRunSetup : OsuGameTestScene + { + [Test] + public void TestOverlay() + { + } + } +} diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 5a150b0c49..52aa6b8f07 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -149,6 +149,8 @@ namespace osu.Game protected SettingsOverlay Settings; + private FirstRunSetupOverlay firstRunOverlay; + private VolumeOverlay volume; private OsuLogo osuLogo; @@ -791,6 +793,7 @@ namespace osu.Game loadComponentSingleFile(CreateUpdateManager(), Add, true); // overlay elements + loadComponentSingleFile(firstRunOverlay = new FirstRunSetupOverlay(), overlayContent.Add, true); loadComponentSingleFile(new ManageCollectionsDialog(), overlayContent.Add, true); loadComponentSingleFile(beatmapListing = new BeatmapListingOverlay(), overlayContent.Add, true); loadComponentSingleFile(dashboard = new DashboardOverlay(), overlayContent.Add, true); diff --git a/osu.Game/Overlays/FirstRunSetup/FirstRunSetupScreen.cs b/osu.Game/Overlays/FirstRunSetup/FirstRunSetupScreen.cs new file mode 100644 index 0000000000..d00d21d347 --- /dev/null +++ b/osu.Game/Overlays/FirstRunSetup/FirstRunSetupScreen.cs @@ -0,0 +1,51 @@ +// 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.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Events; +using osu.Framework.Screens; + +namespace osu.Game.Overlays.FirstRunSetup +{ + public abstract class FirstRunSetupScreen : Screen + { + [Resolved] + protected FirstRunSetupOverlay Overlay { get; private set; } + + protected Container Content { get; private set; } + + protected FirstRunSetupScreen() + { + InternalChildren = new Drawable[] + { + Content = new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding(20), + }, + }; + } + + protected override bool OnClick(ClickEvent e) => true; + + public override void OnEntering(IScreen last) + { + base.OnEntering(last); + this.FadeOut().Delay(200).FadeIn(200); + } + + public override void OnResuming(IScreen last) + { + base.OnResuming(last); + this.FadeIn(200); + } + + public override void OnSuspending(IScreen next) + { + base.OnSuspending(next); + this.FadeOut(200); + } + } +} diff --git a/osu.Game/Overlays/FirstRunSetup/ScreenWelcome.cs b/osu.Game/Overlays/FirstRunSetup/ScreenWelcome.cs new file mode 100644 index 0000000000..be21712c95 --- /dev/null +++ b/osu.Game/Overlays/FirstRunSetup/ScreenWelcome.cs @@ -0,0 +1,58 @@ +// 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.Framework.Graphics.Containers; +using osu.Framework.Screens; +using osu.Framework.Utils; +using osu.Game.Graphics.Containers; +using osu.Game.Screens.OnlinePlay.Match.Components; +using osuTK; + +namespace osu.Game.Overlays.FirstRunSetup +{ + public class ScreenWelcome : FirstRunSetupScreen + { + public ScreenWelcome() + { + Content.Children = new Drawable[] + { + new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new OsuTextFlowContainer + { + Text = "Welcome to the first-run setup guide!\n\nThis will help you get osu! setup in a way that suits you.", + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y + }, + } + }, + new PurpleTriangleButton + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.X, + Margin = new MarginPadding(10), + Text = "Get started", + Action = () => this.Push(new ScreenWelcome()), + } + }; + } + + public override void OnEntering(IScreen last) + { + base.OnEntering(last); + Overlay.MoveDisplayTo(new Vector2(RNG.NextSingle(), RNG.NextSingle())); + } + + public override void OnResuming(IScreen last) + { + base.OnResuming(last); + Overlay.MoveDisplayTo(new Vector2(RNG.NextSingle(), RNG.NextSingle())); + } + } +} diff --git a/osu.Game/Overlays/FirstRunSetupOverlay.cs b/osu.Game/Overlays/FirstRunSetupOverlay.cs new file mode 100644 index 0000000000..218e6018e2 --- /dev/null +++ b/osu.Game/Overlays/FirstRunSetupOverlay.cs @@ -0,0 +1,134 @@ +// 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.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Framework.Screens; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Online.API; +using osu.Game.Overlays.Dialog; +using osu.Game.Overlays.FirstRunSetup; +using osu.Game.Rulesets.UI; +using osu.Game.Screens.Menu; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays +{ + [Cached] + public class FirstRunSetupOverlay : OsuFocusedOverlayContainer + { + protected override bool StartHidden => true; + + [Resolved] + private DialogOverlay dialogOverlay { get; set; } + + [Resolved] + private OsuGame osuGame { get; set; } + + private ScreenWelcome welcomeScreen; + + private Container currentDisplayContainer; + + private PlayfieldBorder border; + + public FirstRunSetupOverlay() + { + RelativeSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader] + private void load(IAPIProvider api, OsuColour colours) + { + Children = new Drawable[] + { + border = new PlayfieldBorder + { + PlayfieldBorderStyle = { Value = PlayfieldBorderStyle.Full }, + Colour = colours.Blue, + }, + currentDisplayContainer = new Container + { + Origin = Anchor.Centre, + RelativePositionAxes = Axes.Both, + Size = new Vector2(400, 300), + Position = new Vector2(0.5f), + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Radius = 5, + Colour = Color4.Black.Opacity(0.2f), + }, + Masking = true, + CornerRadius = 10, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + Alpha = 0.8f, + }, + new ScreenStack(welcomeScreen = new ScreenWelcome()) + { + RelativeSizeAxes = Axes.Both, + }, + } + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + // if we are valid for display, only do so after reaching the main menu. + osuGame.PerformFromScreen(_ => + { + Show(); + }, new[] { typeof(MainMenu) }); + + border + .FadeInFromZero(500) + .Delay(1000) + .FadeOut(500) + .Loop(); + } + + protected override bool OnClick(ClickEvent e) + { + if (dialogOverlay.CurrentDialog == null) + { + dialogOverlay.Push(new ConfirmDialog("Are you sure you want to exit the setup process?", + Hide, + () => { })); + } + + return base.OnClick(e); + } + + protected override void PopIn() + { + base.PopIn(); + this.FadeIn(400, Easing.OutQuint); + + if (welcomeScreen.GetChildScreen() != null) + welcomeScreen.MakeCurrent(); + } + + protected override void PopOut() + { + base.PopOut(); + this.FadeOut(100); + } + + public void MoveDisplayTo(Vector2 position) => + currentDisplayContainer.MoveTo(position, 1000, Easing.OutElasticQuarter); + } +}