diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 2ac46a14f2..56c4ea639b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -21,7 +21,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected DrawableOsuHitObject(OsuHitObject hitObject) : base(hitObject) { - base.AddInternal(shakeContainer = new ShakeContainer { RelativeSizeAxes = Axes.Both }); + base.AddInternal(shakeContainer = new ShakeContainer + { + ShakeDuration = 30, + RelativeSizeAxes = Axes.Both + }); Alpha = 0; } diff --git a/osu.Game.Tests/Visual/TestCaseAccountCreationOverlay.cs b/osu.Game.Tests/Visual/TestCaseAccountCreationOverlay.cs new file mode 100644 index 0000000000..c8ee86e5fd --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseAccountCreationOverlay.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics.Containers; +using osu.Game.Overlays; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseAccountCreationOverlay : OsuTestCase + { + public TestCaseAccountCreationOverlay() + { + var accountCreation = new AccountCreationOverlay(); + Child = accountCreation; + + accountCreation.State = Visibility.Visible; + } + } +} diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index a24b6594e0..ad46e50344 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -26,7 +26,6 @@ namespace osu.Game.Graphics.Containers private PreviewTrackManager previewTrackManager; - protected readonly Bindable OverlayActivationMode = new Bindable(OverlayActivation.All); protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) diff --git a/osu.Game/Graphics/Containers/ShakeContainer.cs b/osu.Game/Graphics/Containers/ShakeContainer.cs index fde4d59f46..6b7b59bbd9 100644 --- a/osu.Game/Graphics/Containers/ShakeContainer.cs +++ b/osu.Game/Graphics/Containers/ShakeContainer.cs @@ -11,29 +11,43 @@ namespace osu.Game.Graphics.Containers /// public class ShakeContainer : Container { + /// + /// The length of a single shake. + /// + public float ShakeDuration = 80; + + /// + /// Total number of shakes. May be shortened if possible. + /// + public float TotalShakes = 4; + + /// + /// Pixels of displacement per shake. + /// + public float ShakeMagnitude = 8; + /// /// Shake the contents of this container. /// /// The maximum length the shake should last. - public void Shake(double maximumLength) + public void Shake(double? maximumLength = null) { const float shake_amount = 8; - const float shake_duration = 30; // if we don't have enough time, don't bother shaking. - if (maximumLength < shake_duration * 2) + if (maximumLength < ShakeDuration * 2) return; - var sequence = this.MoveToX(shake_amount, shake_duration / 2, Easing.OutSine).Then() - .MoveToX(-shake_amount, shake_duration, Easing.InOutSine).Then(); + var sequence = this.MoveToX(shake_amount, ShakeDuration / 2, Easing.OutSine).Then() + .MoveToX(-shake_amount, ShakeDuration, Easing.InOutSine).Then(); // if we don't have enough time for the second shake, skip it. - if (maximumLength > shake_duration * 4) + if (!maximumLength.HasValue || maximumLength >= ShakeDuration * 4) sequence = sequence - .MoveToX(shake_amount, shake_duration, Easing.InOutSine).Then() - .MoveToX(-shake_amount, shake_duration, Easing.InOutSine).Then(); + .MoveToX(shake_amount, ShakeDuration, Easing.InOutSine).Then() + .MoveToX(-shake_amount, ShakeDuration, Easing.InOutSine).Then(); - sequence.MoveToX(0, shake_duration / 2, Easing.InSine); + sequence.MoveToX(0, ShakeDuration / 2, Easing.InSine); } } } diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 1dda257c95..52bb2f5eeb 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -189,6 +189,11 @@ namespace osu.Game.Online.API this.password = password; } + public void CreateAccount(string email, string username, string password) + { + Debug.Assert(State == APIState.Offline); + } + /// /// Handle a single API request. /// diff --git a/osu.Game/Online/API/RegsitrationRequest.cs b/osu.Game/Online/API/RegsitrationRequest.cs new file mode 100644 index 0000000000..134bf45263 --- /dev/null +++ b/osu.Game/Online/API/RegsitrationRequest.cs @@ -0,0 +1,23 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.IO.Network; + +namespace osu.Game.Online.API +{ + internal class RegsitrationRequest : JsonWebRequest + { + internal string Username; + internal string Email; + internal string Password; + + protected override void PrePerform() + { + AddParameter("user", Username); + AddParameter("user_email", Email); + AddParameter("password", Password); + + base.PrePerform(); + } + } +} diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index cd40d4793a..a5dd7ab071 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -61,6 +61,8 @@ namespace osu.Game private DialogOverlay dialogOverlay; + private AccountCreationOverlay accountCreation; + private DirectOverlay direct; private SocialOverlay social; @@ -405,6 +407,11 @@ namespace osu.Game Depth = -6, }, overlayContent.Add); + loadComponentSingleFile(accountCreation = new AccountCreationOverlay + { + Depth = -7, + }, overlayContent.Add); + dependencies.Cache(idleTracker); dependencies.Cache(settings); dependencies.Cache(onscreenDisplay); @@ -417,6 +424,7 @@ namespace osu.Game dependencies.Cache(beatmapSetOverlay); dependencies.Cache(notifications); dependencies.Cache(dialogOverlay); + dependencies.Cache(accountCreation); Add(externalLinkOpener = new ExternalLinkOpener()); diff --git a/osu.Game/Overlays/AccountCreation/RegistrationBackground.cs b/osu.Game/Overlays/AccountCreation/RegistrationBackground.cs new file mode 100644 index 0000000000..45c495d142 --- /dev/null +++ b/osu.Game/Overlays/AccountCreation/RegistrationBackground.cs @@ -0,0 +1,45 @@ +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; + +namespace osu.Game.Overlays.AccountCreation +{ + public class AccountCreationBackground : Sprite + { + public AccountCreationBackground() + { + FillMode = FillMode.Fill; + RelativeSizeAxes = Axes.Both; + + Anchor = Anchor.CentreRight; + Origin = Anchor.CentreRight; + } + + [BackgroundDependencyLoader] + private void load(LargeTextureStore textures) + { + Texture = textures.Get("Backgrounds/registration"); + } + + protected override void LoadComplete() + { + const float x_movement = 80; + + const float initial_move_time = 5000; + const float loop_move_time = 10000; + + base.LoadComplete(); + this.FadeInFromZero(initial_move_time / 4, Easing.OutQuint); + this.MoveToX(x_movement / 2).MoveToX(0, initial_move_time, Easing.OutQuint); + + using (BeginDelayedSequence(initial_move_time)) + { + this + .MoveToX(x_movement, loop_move_time, Easing.InOutSine) + .Then().MoveToX(0, loop_move_time, Easing.InOutSine) + .Loop(); + } + } + } +} diff --git a/osu.Game/Overlays/AccountCreationOverlay.cs b/osu.Game/Overlays/AccountCreationOverlay.cs new file mode 100644 index 0000000000..b8d428a839 --- /dev/null +++ b/osu.Game/Overlays/AccountCreationOverlay.cs @@ -0,0 +1,234 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osuTK.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.MathUtils; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; +using osu.Game.Overlays.AccountCreation; +using osu.Game.Overlays.Settings; +using osuTK; + +namespace osu.Game.Overlays +{ + public class AccountCreationOverlay : OsuFocusedOverlayContainer, IOnlineComponent + { + private OsuTextFlowContainer usernameDescription; + private OsuTextFlowContainer emailAddressDescription; + private OsuTextFlowContainer passwordDescription; + + private OsuTextBox usernameTextBox; + private OsuTextBox emailTextBox; + private OsuPasswordTextBox passwordTextBox; + + private APIAccess api; + private ShakeContainer registerShake; + private IEnumerable characterCheckText; + + private const float transition_time = 400; + + public AccountCreationOverlay() + { + Size = new Vector2(620, 450); + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + + State = Visibility.Visible; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours, APIAccess api) + { + this.api = api; + + api.Register(this); + + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + 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.6f, + }, + new DelayedLoadWrapper(new AccountCreationBackground(), 0), + new Container + { + RelativeSizeAxes = Axes.Both, + Width = 0.6f, + AutoSizeDuration = transition_time, + AutoSizeEasing = Easing.OutQuint, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + Alpha = 0.9f, + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Padding = new MarginPadding(20), + Spacing = new Vector2(0, 10), + Children = new Drawable[] + { + new OsuSpriteText + { + TextSize = 20, + Margin = new MarginPadding { Vertical = 10 }, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = "Let's create an account!", + }, + usernameTextBox = new OsuTextBox + { + PlaceholderText = "username", + RelativeSizeAxes = Axes.X, + TabbableContentContainer = this + }, + usernameDescription = new OsuTextFlowContainer(cp => { cp.TextSize = 12; }) + { + RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y + }, + emailTextBox = new OsuTextBox + { + PlaceholderText = "email address", + RelativeSizeAxes = Axes.X, + Text = api.ProvidedUsername ?? string.Empty, + TabbableContentContainer = this + }, + emailAddressDescription = new OsuTextFlowContainer(cp => { cp.TextSize = 12; }) + { + RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y + }, + passwordTextBox = new OsuPasswordTextBox + { + PlaceholderText = "password", + RelativeSizeAxes = Axes.X, + TabbableContentContainer = this, + }, + passwordDescription = new OsuTextFlowContainer(cp => { cp.TextSize = 12; }) + { + RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + registerShake = new ShakeContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = new SettingsButton + { + Text = "Register", + Margin = new MarginPadding { Vertical = 20 }, + Action = performRegistration + } + } + } + }, + } + }, + } + } + } + } + }; + + usernameDescription.AddText("This will be your public presence. No profanity, no impersonation. Avoid exposing your own personal details, too!"); + + emailAddressDescription.AddText("Will be used for notifications, account verification and in the case you forget your password. No spam, ever."); + emailAddressDescription.AddText(" Make sure to get it right!", cp => cp.Font = "Exo2.0-Bold"); + + passwordDescription.AddText("At least "); + characterCheckText = passwordDescription.AddText("8 characters long"); + passwordDescription.AddText(". Choose something long but also something you will remember, like a line from your favourite song."); + + passwordTextBox.Current.ValueChanged += text => { + characterCheckText.ForEach(s => s.Colour = text.Length == 0 ? Color4.White : Interpolation.ValueAt(text.Length, Color4.OrangeRed, Color4.YellowGreen, 0, 8, Easing.In)); + }; + } + + private void performRegistration() + { + var textbox = nextUnfilledTextbox(); + + if (textbox != null) + { + Schedule(() => GetContainingInputManager().ChangeFocus(textbox)); + registerShake.Shake(); + return; + } + + api.CreateAccount(emailTextBox.Text, usernameTextBox.Text, passwordTextBox.Text); + } + + private OsuTextBox nextUnfilledTextbox() + { + OsuTextBox textboxIfUsable(OsuTextBox textbox) => !string.IsNullOrEmpty(textbox.Text) ? null : textbox; + + return textboxIfUsable(usernameTextBox) ?? textboxIfUsable(emailTextBox) ?? textboxIfUsable(passwordTextBox); + } + + protected override void PopIn() + { + base.PopIn(); + this.FadeIn(transition_time, Easing.OutQuint); + + var nextTextbox = nextUnfilledTextbox(); + if (nextTextbox != null) + Schedule(() => GetContainingInputManager().ChangeFocus(nextTextbox)); + } + + protected override void PopOut() + { + base.PopOut(); + this.FadeOut(100); + } + + public void APIStateChanged(APIAccess api, APIState state) + { + switch (state) + { + case APIState.Offline: + case APIState.Failing: + break; + case APIState.Connecting: + break; + case APIState.Online: + break; + } + } + } +} diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index 6623fbc73b..0cb6d2d1aa 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -79,7 +79,10 @@ namespace osu.Game.Overlays.Settings.Sections.General Margin = new MarginPadding { Bottom = 5 }, Font = @"Exo2.0-Black", }, - form = new LoginForm() + form = new LoginForm + { + RequestHide = RequestHide + } }; break; case APIState.Failing: @@ -189,6 +192,8 @@ namespace osu.Game.Overlays.Settings.Sections.General private TextBox password; private APIAccess api; + public Action RequestHide; + private void performLogin() { if (!string.IsNullOrEmpty(username.Text) && !string.IsNullOrEmpty(password.Text)) @@ -196,7 +201,7 @@ namespace osu.Game.Overlays.Settings.Sections.General } [BackgroundDependencyLoader(permitNulls: true)] - private void load(APIAccess api, OsuConfigManager config) + private void load(APIAccess api, OsuConfigManager config, AccountCreationOverlay accountCreation) { this.api = api; Direction = FillDirection.Vertical; @@ -207,14 +212,14 @@ namespace osu.Game.Overlays.Settings.Sections.General { username = new OsuTextBox { - PlaceholderText = "Email address", + PlaceholderText = "email address", RelativeSizeAxes = Axes.X, Text = api?.ProvidedUsername ?? string.Empty, TabbableContentContainer = this }, password = new OsuPasswordTextBox { - PlaceholderText = "Password", + PlaceholderText = "password", RelativeSizeAxes = Axes.X, TabbableContentContainer = this, OnCommit = (sender, newText) => performLogin() @@ -237,7 +242,11 @@ namespace osu.Game.Overlays.Settings.Sections.General new SettingsButton { Text = "Register", - //Action = registerLink + Action = () => + { + RequestHide(); + accountCreation.Show(); + } } }; } @@ -322,12 +331,10 @@ namespace osu.Game.Overlays.Settings.Sections.General public const float LABEL_LEFT_MARGIN = 20; private readonly SpriteIcon statusIcon; + public Color4 StatusColour { - set - { - statusIcon.FadeColour(value, 500, Easing.OutQuint); - } + set { statusIcon.FadeColour(value, 500, Easing.OutQuint); } } public UserDropdownHeader() @@ -368,10 +375,13 @@ namespace osu.Game.Overlays.Settings.Sections.General private enum UserAction { Online, + [Description(@"Do not disturb")] DoNotDisturb, + [Description(@"Appear offline")] AppearOffline, + [Description(@"Sign out")] SignOut, } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 85eabb0350..78496830d8 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -24,4 +24,7 @@ + + +