From 311b5c623c8a41433ffcfe3edef99040a9caed68 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 24 Nov 2016 13:33:32 +0900 Subject: [PATCH 001/133] Adjust difficulty panel offsets slightly. --- osu.Game/Screens/Select/CarouselContainer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Select/CarouselContainer.cs b/osu.Game/Screens/Select/CarouselContainer.cs index 08220ea69d..8e8185e63c 100644 --- a/osu.Game/Screens/Select/CarouselContainer.cs +++ b/osu.Game/Screens/Select/CarouselContainer.cs @@ -77,6 +77,8 @@ namespace osu.Game.Screens.Select foreach (BeatmapPanel panel in group.BeatmapPanels) { + panel.MoveToX(-50, 500, EasingTypes.OutExpo); + if (panel == SelectedPanel) selectedY = currentY + panel.DrawHeight / 2 - DrawHeight / 2; From 1eb04ff11ed92ab72371ee2b3442c5e8dc8f3587 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 24 Nov 2016 13:35:25 +0900 Subject: [PATCH 002/133] Don't use the overlay suffix for beatmapInfo wedge. --- .../Select/{BeatmapInfoOverlay.cs => BeatmapInfoWedge.cs} | 0 osu.Game/Screens/Select/PlaySongSelect.cs | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) rename osu.Game/Screens/Select/{BeatmapInfoOverlay.cs => BeatmapInfoWedge.cs} (100%) diff --git a/osu.Game/Screens/Select/BeatmapInfoOverlay.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs similarity index 100% rename from osu.Game/Screens/Select/BeatmapInfoOverlay.cs rename to osu.Game/Screens/Select/BeatmapInfoWedge.cs diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 604c4aae28..ba06b797ef 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -40,7 +40,7 @@ namespace osu.Game.Screens.Select private static readonly Vector2 wedged_container_size = new Vector2(0.5f, 225); private static readonly Vector2 wedged_container_shear = new Vector2(0.15f, 0); private static readonly Vector2 wedged_container_start_position = new Vector2(0, 50); - private BeatmapInfoOverlay wedgedBeatmapInfoOverlay; + private BeatmapInfoWedge wedgedBeatmapInfoWedge; private static readonly Vector2 BACKGROUND_BLUR = new Vector2(20); private CancellationTokenSource initialAddSetsTask; @@ -102,7 +102,7 @@ namespace osu.Game.Screens.Select Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, }, - wedgedBeatmapInfoOverlay = new BeatmapInfoOverlay + wedgedBeatmapInfoWedge = new BeatmapInfoWedge { Alpha = 0, Position = wedged_container_start_position, @@ -239,7 +239,7 @@ namespace osu.Game.Screens.Select (Background as BackgroundModeBeatmap)?.BlurTo(BACKGROUND_BLUR, 1000); } - wedgedBeatmapInfoOverlay.UpdateBeatmap(beatmap); + wedgedBeatmapInfoWedge.UpdateBeatmap(beatmap); } /// From ece3bc0e01ebe405ae34deaab16a4e7f94cce3ff Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 24 Nov 2016 13:48:48 +0900 Subject: [PATCH 003/133] Refactor BeatmapInfoWedge to be async. --- .../Drawables/BeatmapBackgroundSprite.cs | 24 ++++++++++++ .../Beatmaps/Drawables/BeatmapSetHeader.cs | 25 +------------ osu.Game/Screens/Select/BeatmapInfoWedge.cs | 37 +++++++++++++------ osu.Game/Screens/Select/PlaySongSelect.cs | 6 +-- osu.Game/osu.Game.csproj | 3 +- 5 files changed, 56 insertions(+), 39 deletions(-) create mode 100644 osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs diff --git a/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs new file mode 100644 index 0000000000..e90829873f --- /dev/null +++ b/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs @@ -0,0 +1,24 @@ +//Copyright (c) 2007-2016 ppy Pty Ltd . +//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics.Sprites; + +namespace osu.Game.Beatmaps.Drawables +{ + class BeatmapBackgroundSprite : Sprite + { + private readonly WorkingBeatmap working; + + public BeatmapBackgroundSprite(WorkingBeatmap working) + { + this.working = working; + } + + [BackgroundDependencyLoader] + private void load(OsuGameBase game) + { + Texture = working.Background; + } + } +} diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs index 709885d132..9ab9aaf9f5 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs @@ -156,38 +156,17 @@ namespace osu.Game.Beatmaps.Drawables [BackgroundDependencyLoader] private void load(OsuGameBase game) { - new BeatmapBackground(working) + new BeatmapBackgroundSprite(working) { Anchor = Anchor.Centre, Origin = Anchor.Centre, + FillMode = FillMode.Fill, }.Preload(game, (bg) => { Add(bg); ForceRedraw(); }); } - - class BeatmapBackground : Sprite - { - private readonly WorkingBeatmap working; - - public BeatmapBackground(WorkingBeatmap working) - { - this.working = working; - } - - [BackgroundDependencyLoader] - private void load(OsuGameBase game) - { - Texture = working.Background; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - Scale = new Vector2(1366 / (Texture?.Width ?? 1) * 0.6f); - } - } } } } \ No newline at end of file diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 1e12f03749..c6ed202326 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -1,4 +1,6 @@ using System; +using osu.Framework; +using osu.Framework.Allocation; using OpenTK; using OpenTK.Graphics; using osu.Framework.Graphics; @@ -8,31 +10,37 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; using osu.Game.Database; using osu.Framework.Graphics.Colour; +using osu.Game.Beatmaps.Drawables; namespace osu.Game.Screens.Select { - class BeatmapInfoOverlay : Container + class BeatmapInfoWedge : Container { private Container beatmapInfoContainer; + private BaseGame game; + + [BackgroundDependencyLoader] + private void load(BaseGame game) + { + this.game = game; + } + public void UpdateBeatmap(WorkingBeatmap beatmap) { if (beatmap == null) return; - float newDepth = 0; - if (beatmapInfoContainer != null) - { - newDepth = beatmapInfoContainer.Depth - 1; - beatmapInfoContainer.FadeOut(250); - beatmapInfoContainer.Expire(); - } + var lastContainer = beatmapInfoContainer; + + float newDepth = lastContainer?.Depth - 1 ?? 0; FadeIn(250); BeatmapSetInfo beatmapSetInfo = beatmap.BeatmapSetInfo; BeatmapInfo beatmapInfo = beatmap.BeatmapInfo; - Add(beatmapInfoContainer = new BufferedContainer + + (beatmapInfoContainer = new BufferedContainer { Depth = newDepth, PixelSnapping = true, @@ -51,18 +59,17 @@ namespace osu.Game.Screens.Select }, // We use a container, such that we can set the colour gradient to go across the // vertices of the masked container instead of the vertices of the (larger) sprite. - beatmap.Background == null ? new Container() : new Container + new Container { RelativeSizeAxes = Axes.Both, ColourInfo = ColourInfo.GradientVertical(Color4.White, new Color4(1f, 1f, 1f, 0.3f)), Children = new [] { // Zoomed-in and cropped beatmap background - new Sprite + new BeatmapBackgroundSprite(beatmap) { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Texture = beatmap.Background, FillMode = FillMode.Fill, }, }, @@ -117,6 +124,12 @@ namespace osu.Game.Screens.Select } } } + }).Preload(game, delegate(Drawable d) + { + lastContainer?.FadeOut(250); + lastContainer?.Expire(); + + Add(d); }); } } diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index ba06b797ef..76ecdcb64e 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -40,7 +40,7 @@ namespace osu.Game.Screens.Select private static readonly Vector2 wedged_container_size = new Vector2(0.5f, 225); private static readonly Vector2 wedged_container_shear = new Vector2(0.15f, 0); private static readonly Vector2 wedged_container_start_position = new Vector2(0, 50); - private BeatmapInfoWedge wedgedBeatmapInfoWedge; + private BeatmapInfoWedge beatmapInfoWedge; private static readonly Vector2 BACKGROUND_BLUR = new Vector2(20); private CancellationTokenSource initialAddSetsTask; @@ -102,7 +102,7 @@ namespace osu.Game.Screens.Select Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, }, - wedgedBeatmapInfoWedge = new BeatmapInfoWedge + beatmapInfoWedge = new BeatmapInfoWedge { Alpha = 0, Position = wedged_container_start_position, @@ -239,7 +239,7 @@ namespace osu.Game.Screens.Select (Background as BackgroundModeBeatmap)?.BlurTo(BACKGROUND_BLUR, 1000); } - wedgedBeatmapInfoWedge.UpdateBeatmap(beatmap); + beatmapInfoWedge.UpdateBeatmap(beatmap); } /// diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 9cb1535981..9c2bbf086a 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -63,6 +63,7 @@ + @@ -159,7 +160,7 @@ - + From 97cf6008f3f53a79d2c5ff5f5167a2093f0cf777 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 24 Nov 2016 18:52:27 +0900 Subject: [PATCH 004/133] Remove playfield background box. --- osu.Game.Mode.Osu/UI/OsuPlayfield.cs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/osu.Game.Mode.Osu/UI/OsuPlayfield.cs b/osu.Game.Mode.Osu/UI/OsuPlayfield.cs index 94638fd79c..1e69cd78a3 100644 --- a/osu.Game.Mode.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Mode.Osu/UI/OsuPlayfield.cs @@ -37,15 +37,6 @@ namespace osu.Game.Modes.Osu.UI AddInternal(new Drawable[] { - new Box - { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Colour = Color4.Black, - Depth = float.MinValue, - Alpha = 0.5f, - }, approachCircles = new Container { RelativeSizeAxes = Axes.Both, From 3dff72ac6c4312f46bbabddc3d4f1740df863b3c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 24 Nov 2016 18:58:06 +0900 Subject: [PATCH 005/133] Bypass masking checks for input on playfields. --- osu.Game/Modes/UI/Playfield.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Modes/UI/Playfield.cs b/osu.Game/Modes/UI/Playfield.cs index 8bfd82e407..ff8a03db2a 100644 --- a/osu.Game/Modes/UI/Playfield.cs +++ b/osu.Game/Modes/UI/Playfield.cs @@ -14,6 +14,8 @@ namespace osu.Game.Modes.UI public virtual void Add(DrawableHitObject h) => HitObjects.Add(h); + public override bool Contains(Vector2 screenSpacePos) => true; + public Playfield() { AddInternal(HitObjects = new HitObjectContainer @@ -25,6 +27,8 @@ namespace osu.Game.Modes.UI public class HitObjectContainer : Container { protected override Vector2 DrawScale => new Vector2(DrawSize.X / 512); + + public override bool Contains(Vector2 screenSpacePos) => true; } } } From 6c69bd2ba3c2db6d5feaf4e2607db20bd4e83095 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 24 Nov 2016 21:27:12 +0900 Subject: [PATCH 006/133] Fix regression causing crash on using z/x in player mode. --- osu.Game/Screens/Play/Player.cs | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 14df8d37b4..8691097ebf 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -1,6 +1,7 @@ //Copyright (c) 2007-2016 ppy Pty Ltd . //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Track; @@ -125,26 +126,28 @@ namespace osu.Game.Screens.Play { } + bool leftViaKeyboard; + bool rightViaKeyboard; + protected override void TransformState(InputState state) { base.TransformState(state); MouseState mouse = (MouseState)state.Mouse; - foreach (Key k in state.Keyboard.Keys) + if (state.Keyboard != null) { - switch (k) - { - case Key.Z: - mouse.ButtonStates.Find(s => s.Button == MouseButton.Left).State = true; - break; - case Key.X: - mouse.ButtonStates.Find(s => s.Button == MouseButton.Right).State = true; - break; - } + leftViaKeyboard = state.Keyboard.Keys.Contains(Key.Z); + rightViaKeyboard = state.Keyboard.Keys.Contains(Key.X); + } + + if (state.Mouse != null) + { + if (leftViaKeyboard) mouse.ButtonStates.Find(s => s.Button == MouseButton.Left).State = true; + if (rightViaKeyboard) mouse.ButtonStates.Find(s => s.Button == MouseButton.Right).State = true; } } } } -} +} \ No newline at end of file From d9de35141ee39c4f7b2bcb0dd543a953c3bc494a Mon Sep 17 00:00:00 2001 From: Tom94 Date: Thu, 24 Nov 2016 20:24:35 +0100 Subject: [PATCH 007/133] Update framework. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 1a521bb22c..09c18c415d 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 1a521bb22cfd2c14f58d4cd60fbbfdb70ea8f87b +Subproject commit 09c18c415d280448c44cb73f2c4e60e0092b974c From 495cb926f7045d6e3d491485b5a9a79289339263 Mon Sep 17 00:00:00 2001 From: Tom94 Date: Thu, 24 Nov 2016 20:25:29 +0100 Subject: [PATCH 008/133] Move beatmap panels back to an X of 0 when they are unselected. --- osu.Game/Screens/Select/CarouselContainer.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/CarouselContainer.cs b/osu.Game/Screens/Select/CarouselContainer.cs index 8e8185e63c..cfc36b9caa 100644 --- a/osu.Game/Screens/Select/CarouselContainer.cs +++ b/osu.Game/Screens/Select/CarouselContainer.cs @@ -77,11 +77,11 @@ namespace osu.Game.Screens.Select foreach (BeatmapPanel panel in group.BeatmapPanels) { - panel.MoveToX(-50, 500, EasingTypes.OutExpo); - if (panel == SelectedPanel) selectedY = currentY + panel.DrawHeight / 2 - DrawHeight / 2; + panel.MoveToX(-50, 500, EasingTypes.OutExpo); + movePanel(panel, true, ref currentY); } } @@ -90,7 +90,10 @@ namespace osu.Game.Screens.Select group.Header.MoveToX(0, 500, EasingTypes.OutExpo); foreach (BeatmapPanel panel in group.BeatmapPanels) + { + panel.MoveToX(0, 500, EasingTypes.OutExpo); movePanel(panel, false, ref currentY); + } } } From 12c74b1b0b10c615350dbcce7306fa790b2f634e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 Nov 2016 12:47:58 +0900 Subject: [PATCH 009/133] Don't set hidden; make it based on alpha value. --- osu.Game/Beatmaps/Drawables/BeatmapGroup.cs | 11 +---------- osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs | 1 - osu.Game/Beatmaps/Drawables/Panel.cs | 4 +++- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs b/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs index eed7e9369e..3f5fe58ab5 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs @@ -35,14 +35,8 @@ namespace osu.Game.Beatmaps.Drawables switch (state) { case BeatmapGroupState.Expanded: - //if (!difficulties.Children.All(d => IsLoaded)) - // Task.WhenAll(difficulties.Children.Select(d => d.Preload(Game))).ContinueWith(t => difficulties.Show()); - //else foreach (BeatmapPanel panel in BeatmapPanels) - { - panel.Hidden = false; panel.FadeIn(250); - } Header.State = PanelSelectedState.Selected; if (SelectedPanel != null) @@ -54,11 +48,7 @@ namespace osu.Game.Beatmaps.Drawables SelectedPanel.State = PanelSelectedState.NotSelected; foreach (BeatmapPanel panel in BeatmapPanels) - { - panel.Hidden = true; panel.FadeOut(250); - } - break; } } @@ -76,6 +66,7 @@ namespace osu.Game.Beatmaps.Drawables BeatmapPanels = beatmap.BeatmapSetInfo.Beatmaps.Select(b => new BeatmapPanel(b) { + Alpha = 0, GainedSelection = panelGainedSelection, RelativeSizeAxes = Axes.X, }).ToList(); diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs index 9ab9aaf9f5..a8bf8518d8 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs @@ -27,7 +27,6 @@ namespace osu.Game.Beatmaps.Drawables public BeatmapSetHeader(WorkingBeatmap beatmap) { this.beatmap = beatmap; - Hidden = false; Children = new Drawable[] { diff --git a/osu.Game/Beatmaps/Drawables/Panel.cs b/osu.Game/Beatmaps/Drawables/Panel.cs index cef25d24a5..9aa59f022f 100644 --- a/osu.Game/Beatmaps/Drawables/Panel.cs +++ b/osu.Game/Beatmaps/Drawables/Panel.cs @@ -4,6 +4,7 @@ using osu.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Transformations; using osu.Framework.Input; using OpenTK; using OpenTK.Graphics; @@ -14,7 +15,8 @@ namespace osu.Game.Beatmaps.Drawables { public const float MAX_HEIGHT = 80; - public bool Hidden = true; + public bool Hidden => Alpha == 0 && Transforms.Count == 0; + private Container nestedContainer; protected override Container Content => nestedContainer; From 35a02aa972571634423aa52a0460f6e18313070e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 Nov 2016 12:48:41 +0900 Subject: [PATCH 010/133] Fade in headers but not difficulties by default. --- osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs | 6 ++++++ osu.Game/Beatmaps/Drawables/Panel.cs | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs index a8bf8518d8..bd36ad5149 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs @@ -71,6 +71,12 @@ namespace osu.Game.Beatmaps.Drawables }; } + protected override void LoadComplete() + { + base.LoadComplete(); + FadeInFromZero(250); + } + protected override void Selected() { base.Selected(); diff --git a/osu.Game/Beatmaps/Drawables/Panel.cs b/osu.Game/Beatmaps/Drawables/Panel.cs index 9aa59f022f..e271546cbe 100644 --- a/osu.Game/Beatmaps/Drawables/Panel.cs +++ b/osu.Game/Beatmaps/Drawables/Panel.cs @@ -44,7 +44,6 @@ namespace osu.Game.Beatmaps.Drawables { base.LoadComplete(); applyState(); - FadeInFromZero(250); } private void applyState() From f540bf37655a38cd8d119549c4283e1c8ca478e5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 Nov 2016 12:48:59 +0900 Subject: [PATCH 011/133] Ensure set headers are above difficulties. --- osu.Game/Beatmaps/Drawables/BeatmapGroup.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs b/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs index 3f5fe58ab5..6721257393 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs @@ -60,6 +60,7 @@ namespace osu.Game.Beatmaps.Drawables Header = new BeatmapSetHeader(beatmap) { + Depth = 1, GainedSelection = headerGainedSelection, RelativeSizeAxes = Axes.X, }; From 4184dd232944a4d04b2cb9552cf696db2fa6f541 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 Nov 2016 12:50:18 +0900 Subject: [PATCH 012/133] Change the way we set our initial y position on first display. --- osu.Game/Screens/Select/CarouselContainer.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/CarouselContainer.cs b/osu.Game/Screens/Select/CarouselContainer.cs index cfc36b9caa..26dc77d943 100644 --- a/osu.Game/Screens/Select/CarouselContainer.cs +++ b/osu.Game/Screens/Select/CarouselContainer.cs @@ -74,6 +74,7 @@ namespace osu.Game.Screens.Select if (group.State == BeatmapGroupState.Expanded) { group.Header.MoveToX(-100, 500, EasingTypes.OutExpo); + var headerY = group.Header.Position.Y; foreach (BeatmapPanel panel in group.BeatmapPanels) { @@ -82,6 +83,10 @@ namespace osu.Game.Screens.Select panel.MoveToX(-50, 500, EasingTypes.OutExpo); + //on first display we want to begin hidden under our group's header. + if (panel.Alpha == 0) + panel.MoveToY(headerY); + movePanel(panel, true, ref currentY); } } @@ -119,11 +124,7 @@ namespace osu.Game.Screens.Select public void SelectGroup(BeatmapGroup group, BeatmapPanel panel) { if (SelectedGroup != null && SelectedGroup != group) - { SelectedGroup.State = BeatmapGroupState.Collapsed; - foreach (BeatmapPanel p in group.BeatmapPanels) - p.MoveToY(group.Header.Position.Y); - } SelectedGroup = group; panel.State = PanelSelectedState.Selected; From a3db259071586718122430c1808ddca73d085423 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 23 Nov 2016 06:15:19 -0500 Subject: [PATCH 013/133] Fix VolumeMeter.Bindable --- osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs b/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs index f13019e72c..f4083c55b3 100644 --- a/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs +++ b/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs @@ -13,7 +13,7 @@ namespace osu.Game.Graphics.UserInterface.Volume internal class VolumeMeter : Container { private Box meterFill; - public BindableDouble Bindable; + public BindableDouble Bindable { get; private set; } public VolumeMeter(string meterName) { From 69cb9cf4debf52612815f2547e3e85bd9ec9b2e0 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 23 Nov 2016 06:26:46 -0500 Subject: [PATCH 014/133] Fix up volume encapsulation --- .../UserInterface/Volume/VolumeControl.cs | 35 ++++++++++++------- .../UserInterface/Volume/VolumeMeter.cs | 2 +- osu.Game/OsuGame.cs | 7 +--- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs b/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs index 364ef1c7aa..c94eb40c17 100644 --- a/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs +++ b/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs @@ -6,16 +6,17 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Input; using osu.Framework.Threading; using OpenTK; -using osu.Framework.Allocation; using osu.Framework.Graphics.Primitives; +using osu.Framework.Audio; +using osu.Framework.Allocation; namespace osu.Game.Graphics.UserInterface.Volume { internal class VolumeControl : OverlayContainer { - public BindableDouble VolumeGlobal { get; set; } - public BindableDouble VolumeSample { get; set; } - public BindableDouble VolumeTrack { get; set; } + private BindableDouble volumeGlobal = new BindableDouble(); + private BindableDouble volumeSample = new BindableDouble(); + private BindableDouble volumeTrack = new BindableDouble(); private VolumeMeter volumeMeterMaster; @@ -54,20 +55,20 @@ namespace osu.Game.Graphics.UserInterface.Volume { base.LoadComplete(); - VolumeGlobal.ValueChanged += volumeChanged; - VolumeSample.ValueChanged += volumeChanged; - VolumeTrack.ValueChanged += volumeChanged; + volumeGlobal.ValueChanged += volumeChanged; + volumeSample.ValueChanged += volumeChanged; + volumeTrack.ValueChanged += volumeChanged; - volumeMeterMaster.Bindable = VolumeGlobal; - volumeMeterEffect.Bindable = VolumeSample; - volumeMeterMusic.Bindable = VolumeTrack; + volumeMeterMaster.Bindable.Weld(volumeGlobal); + volumeMeterEffect.Bindable.Weld(volumeSample); + volumeMeterMusic.Bindable.Weld(volumeTrack); } protected override void Dispose(bool isDisposing) { - VolumeGlobal.ValueChanged -= volumeChanged; - VolumeSample.ValueChanged -= volumeChanged; - VolumeTrack.ValueChanged -= volumeChanged; + volumeGlobal.ValueChanged -= volumeChanged; + volumeSample.ValueChanged -= volumeChanged; + volumeTrack.ValueChanged -= volumeChanged; base.Dispose(isDisposing); } @@ -82,6 +83,14 @@ namespace osu.Game.Graphics.UserInterface.Volume volumeMeterMaster.TriggerWheel(state); } + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + volumeGlobal.Weld(audio.Volume); + volumeSample.Weld(audio.VolumeSample); + volumeTrack.Weld(audio.VolumeTrack); + } + ScheduledDelegate popOutDelegate; private VolumeMeter volumeMeterEffect; diff --git a/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs b/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs index f4083c55b3..230066cf9b 100644 --- a/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs +++ b/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs @@ -13,7 +13,7 @@ namespace osu.Game.Graphics.UserInterface.Volume internal class VolumeMeter : Container { private Box meterFill; - public BindableDouble Bindable { get; private set; } + public BindableDouble Bindable { get; private set; } = new BindableDouble(); public VolumeMeter(string meterName) { diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 4f40899500..7bf7e4cd2a 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -97,12 +97,7 @@ namespace osu.Game { RelativeSizeAxes = Axes.Both, }, - volume = new VolumeControl - { - VolumeGlobal = Audio.Volume, - VolumeSample = Audio.VolumeSample, - VolumeTrack = Audio.VolumeTrack - }, + volume = new VolumeControl(), overlayContent = new Container{ RelativeSizeAxes = Axes.Both }, new GlobalHotkeys //exists because UserInputManager is at a level below us. { From 89effca12ea9cb414c8fee8e49042f5f3bb48700 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 23 Nov 2016 06:38:33 -0500 Subject: [PATCH 015/133] Remove need for PlaySongSelect ctor to take a db --- osu-framework | 2 +- .../Tests/TestCasePlaySongSelect.cs | 49 ++++++++++--------- osu.Game/OsuGameBase.cs | 2 +- osu.Game/Screens/Select/PlaySongSelect.cs | 5 +- 4 files changed, 28 insertions(+), 30 deletions(-) diff --git a/osu-framework b/osu-framework index 09c18c415d..d9bd79c4c1 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 09c18c415d280448c44cb73f2c4e60e0092b974c +Subproject commit d9bd79c4c15f7e5eb4e69fa7898b7d358e4516e4 diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs index 244982ded3..57dbb2d266 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs @@ -1,31 +1,32 @@ -//Copyright (c) 2007-2016 ppy Pty Ltd . -//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System.Collections.Generic; -using osu.Desktop.VisualTests.Platform; -using osu.Framework.GameModes.Testing; -using osu.Game.Database; -using osu.Game.Modes; -using osu.Game.Screens.Select; - -namespace osu.Desktop.VisualTests.Tests -{ - class TestCasePlaySongSelect : TestCase - { - private BeatmapDatabase db; - private TestStorage storage; - - public override string Name => @"Song Select"; +//Copyright (c) 2007-2016 ppy Pty Ltd . +//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using osu.Desktop.VisualTests.Platform; +using osu.Framework.GameModes.Testing; +using osu.Game.Database; +using osu.Game.Modes; +using osu.Game.Screens.Select; + +namespace osu.Desktop.VisualTests.Tests +{ + class TestCasePlaySongSelect : TestCase + { + private BeatmapDatabase db; + private TestStorage storage; + + public override string Name => @"Song Select"; public override string Description => @"with fake data"; - public override void Reset() - { + public override void Reset() + { base.Reset(); if (db == null) { storage = new TestStorage(@"TestCasePlaySongSelect"); db = new BeatmapDatabase(storage); + Dependencies.Cache(db, true); var sets = new List(); @@ -35,7 +36,7 @@ namespace osu.Desktop.VisualTests.Tests db.Import(sets); } - Add(new PlaySongSelect(db)); + Add(new PlaySongSelect()); } private BeatmapSetInfo createTestBeatmapSet(int i) @@ -89,6 +90,6 @@ namespace osu.Desktop.VisualTests.Tests }, }), }; - } - } -} + } + } +} diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 7b05093dde..2f3e5025b7 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -45,7 +45,7 @@ namespace osu.Game Dependencies.Cache(new BeatmapDatabase(Host.Storage, Host)); //this completely overrides the framework default. will need to change once we make a proper FontStore. - Dependencies.Cache(Fonts = new FontStore { ScaleAdjust = 0.01f }); + Dependencies.Cache(Fonts = new FontStore { ScaleAdjust = 0.01f }, true); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/FontAwesome")); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/osuFont")); diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 76ecdcb64e..371d014659 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -73,11 +73,8 @@ namespace osu.Game.Screens.Select } } - /// Optionally provide a database to use instead of the OsuGame one. - public PlaySongSelect(BeatmapDatabase database = null) + public PlaySongSelect() { - this.database = database; - const float carouselWidth = 640; const float bottomToolHeight = 50; Children = new Drawable[] From f9f72f25a2c22bc73e4985138e9bdc793371a792 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 Nov 2016 16:26:50 +0900 Subject: [PATCH 016/133] Add basic flow for hitobject judgement. --- .../Tests/TestCaseHitObjects.cs | 2 +- .../Objects/Drawables/DrawableHitCircle.cs | 28 +++++++--- .../Objects/Drawables/DrawableSlider.cs | 2 +- .../Objects/Drawables/HitExplosion.cs | 6 +- osu.Game.Mode.Osu/OsuHitJudgementResolver.cs | 41 ++++++++++++++ osu.Game.Mode.Osu/OsuRuleset.cs | 2 + osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj | 1 + osu.Game/Modes/HitJudgementResolver.cs | 21 ++++--- .../Objects/Drawables/DrawableHitObject.cs | 55 ++++++++++++------- osu.Game/Screens/Play/Player.cs | 7 ++- 10 files changed, 124 insertions(+), 41 deletions(-) create mode 100644 osu.Game.Mode.Osu/OsuHitJudgementResolver.cs diff --git a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs index 31a1bc369e..6da47c5bc4 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs @@ -50,7 +50,7 @@ namespace osu.Desktop.VisualTests.Tests Anchor = Anchor.Centre, Origin = Anchor.Centre, Depth = -i, - State = ArmedState.Armed, + State = ArmedState.Hit, }; approachContainer.Add(d.ApproachCircle.CreateProxy()); diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs index 8c73955ca9..6c11b328a9 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -39,7 +39,9 @@ namespace osu.Game.Modes.Osu.Objects.Drawables circle = new CirclePiece { Colour = osuObject.Colour, - Hit = Hit, + Hit = () => Hit(new JudgementInfo { + UserTriggered = true, + }), }, number = new NumberPiece(), ring = new RingPiece(), @@ -73,7 +75,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Flush(true); //move to DrawableHitObject ApproachCircle.Flush(true); - double t = HitTime ?? osuObject.StartTime; + double t = osuObject.EndTime + (Judgement?.TimeOffset ?? 0); Alpha = 0; @@ -103,14 +105,26 @@ namespace osu.Game.Modes.Osu.Objects.Drawables switch (state) { - case ArmedState.Disarmed: - Delay(osuObject.Duration + 200); - FadeOut(200); + case ArmedState.Idle: + Delay(osuObject.Duration + 500); + FadeOut(500); explosion?.Expire(); explosion = null; break; - case ArmedState.Armed: + case ArmedState.Miss: + ring.FadeOut(); + circle.FadeOut(); + number.FadeOut(); + + explosion?.Expire(); + explosion = null; + + Schedule(() => Add(explosion = new HitExplosion(HitResult.Miss))); + + FadeOut(800); + break; + case ArmedState.Hit: const double flash_in = 30; flash.FadeTo(0.8f, flash_in); @@ -119,7 +133,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables explode.FadeIn(flash_in); - Schedule(() => Add(explosion = new HitExplosion(Judgement.Hit300))); + Schedule(() => Add(explosion = new HitExplosion(Judgement.Result))); Delay(flash_in, true); diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index 693f05cd1f..50203d48ae 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -18,7 +18,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Add(new CirclePiece { Colour = h.Colour, - Hit = Hit, + Hit = () => Hit(new JudgementInfo()), Position = h.Curve.PositionAt(i) - h.Position //non-relative? }); } diff --git a/osu.Game.Mode.Osu/Objects/Drawables/HitExplosion.cs b/osu.Game.Mode.Osu/Objects/Drawables/HitExplosion.cs index a3067a1eab..fac9ab636b 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/HitExplosion.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/HitExplosion.cs @@ -12,7 +12,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables private SpriteText line1; private SpriteText line2; - public HitExplosion(Judgement judgement, ComboJudgement comboJudgement = ComboJudgement.None) + public HitExplosion(HitResult hitResult, ComboResult comboResult = ComboResult.None) { AutoSizeAxes = Axes.Both; Anchor = Anchor.Centre; @@ -27,13 +27,13 @@ namespace osu.Game.Modes.Osu.Objects.Drawables { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Text = judgement.GetDescription(), + Text = hitResult.GetDescription(), Font = @"Venera", TextSize = 20, }, line2 = new SpriteText { - Text = comboJudgement.GetDescription(), + Text = comboResult.GetDescription(), Font = @"Venera", TextSize = 14, } diff --git a/osu.Game.Mode.Osu/OsuHitJudgementResolver.cs b/osu.Game.Mode.Osu/OsuHitJudgementResolver.cs new file mode 100644 index 0000000000..6dc240c7af --- /dev/null +++ b/osu.Game.Mode.Osu/OsuHitJudgementResolver.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using osu.Game.Modes.Objects.Drawables; +using osu.Game.Modes.Osu.Objects.Drawables; + +namespace osu.Game.Modes.Osu +{ + class OsuHitJudgementResolver : HitJudgementResolver + { + double hit50 = 150; + double hit100 = 80; + double hit300 = 30; + public override void CheckJudgement(DrawableHitObject h, JudgementInfo info) + { + DrawableHitCircle circle = h as DrawableHitCircle; + if (circle != null) + { + if (!info.UserTriggered) + { + if (info.TimeOffset > hit50) + info.Result = HitResult.Miss; + return; + } + + double hitOffset = Math.Abs(info.TimeOffset); + + if (hitOffset < hit300) + info.Result = HitResult.Hit300; + else if (hitOffset < hit100) + info.Result = HitResult.Hit100; + else if (hitOffset < hit50) + info.Result = HitResult.Hit50; + else + info.Result = HitResult.Miss; + } + } + } +} diff --git a/osu.Game.Mode.Osu/OsuRuleset.cs b/osu.Game.Mode.Osu/OsuRuleset.cs index ac43e5501c..e79cbef748 100644 --- a/osu.Game.Mode.Osu/OsuRuleset.cs +++ b/osu.Game.Mode.Osu/OsuRuleset.cs @@ -13,6 +13,8 @@ namespace osu.Game.Modes.Osu { public override ScoreOverlay CreateScoreOverlay() => new OsuScoreOverlay(); + public override HitJudgementResolver CreateHitJudgement() => new OsuHitJudgementResolver(); + public override HitRenderer CreateHitRendererWith(List objects) => new OsuHitRenderer { Objects = objects }; public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser(); diff --git a/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj b/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj index e7efa413c4..d63cc2354a 100644 --- a/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj +++ b/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj @@ -52,6 +52,7 @@ + diff --git a/osu.Game/Modes/HitJudgementResolver.cs b/osu.Game/Modes/HitJudgementResolver.cs index 5f2afec369..d9f3cc96c1 100644 --- a/osu.Game/Modes/HitJudgementResolver.cs +++ b/osu.Game/Modes/HitJudgementResolver.cs @@ -4,28 +4,34 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; using osu.Game.Modes.Objects; +using osu.Game.Modes.Objects.Drawables; using OpenTK; namespace osu.Game.Modes { public class HitJudgementResolver { - public JudgementResult CheckJudgement(HitObject h) => new JudgementResult { Combo = ComboJudgement.None, Judgement = Judgement.Hit300 }; + public virtual void CheckJudgement(DrawableHitObject h, JudgementInfo info) + { + info.Result = HitResult.Hit300; + } } - public struct JudgementResult + public class JudgementInfo { - public ComboJudgement Combo; - public Judgement Judgement; - public float TimeOffset; + public bool UserTriggered; + public ComboResult Combo; + public HitResult Result; + public double TimeOffset; public Vector2 PositionOffset; } - public enum ComboJudgement + public enum ComboResult { [Description(@"")] None, @@ -35,8 +41,9 @@ namespace osu.Game.Modes Perfect } - public enum Judgement + public enum HitResult { + Ignore, [Description(@"Miss")] Miss, [Description(@"50")] diff --git a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs index 387d5d061a..0d8b124be2 100644 --- a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs @@ -2,6 +2,7 @@ //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Diagnostics; using osu.Framework; using osu.Framework.Graphics.Containers; @@ -13,11 +14,11 @@ namespace osu.Game.Modes.Objects.Drawables public Action OnHit; public Action OnMiss; - public Func AllowHit; + public Action CheckJudgement; public Container ChildObjects; - public JudgementResult Result; + public JudgementInfo Judgement; public HitObject HitObject; @@ -41,36 +42,47 @@ namespace osu.Game.Modes.Objects.Drawables } } - protected double? HitTime; - - protected virtual bool Hit() + /// + /// Process a hit of this hitobject. Carries out judgement. + /// + /// Preliminary judgement information provided by the hit source. + /// Whether a hit was processed. + protected bool Hit(JudgementInfo judgement) { - if (State != ArmedState.Disarmed) + if (State != ArmedState.Idle) return false; - if (AllowHit?.Invoke(this) == false) + judgement.TimeOffset = Time.Current - HitObject.EndTime; + + CheckJudgement?.Invoke(this, judgement); + + if (judgement.Result == HitResult.Ignore) return false; - HitTime = Time.Current; + Judgement = judgement; - State = ArmedState.Armed; + switch (judgement.Result) + { + default: + State = ArmedState.Hit; + OnHit?.Invoke(this); + break; + case HitResult.Miss: + State = ArmedState.Miss; + OnMiss?.Invoke(this); + break; + } + + return true; } - private bool counted; - protected override void Update() { base.Update(); - if (Time.Current >= HitObject.EndTime && !counted) - { - counted = true; - if (state == ArmedState.Armed) - OnHit?.Invoke(this); - else - OnMiss?.Invoke(this); - } + if (Time.Current >= HitObject.EndTime && Judgement == null) + Hit(new JudgementInfo()); } protected abstract void UpdateState(ArmedState state); @@ -78,7 +90,8 @@ namespace osu.Game.Modes.Objects.Drawables public enum ArmedState { - Disarmed, - Armed + Idle, + Hit, + Miss } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 8691097ebf..a5bbf8c453 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -86,11 +86,16 @@ namespace osu.Game.Screens.Play var scoreOverlay = ruleset.CreateScoreOverlay(); var hitRenderer = ruleset.CreateHitRendererWith(beatmap.HitObjects); + var hitJudgement = ruleset.CreateHitJudgement(); + hitRenderer.OnHit += delegate (HitObject h) { scoreOverlay.OnHit(h); }; hitRenderer.OnMiss += delegate (HitObject h) { scoreOverlay.OnMiss(h); }; if (Autoplay) - hitRenderer.Schedule(() => hitRenderer.DrawableObjects.ForEach(h => h.State = ArmedState.Armed)); + hitRenderer.Schedule(() => hitRenderer.DrawableObjects.ForEach(h => h.State = ArmedState.Hit)); + + //bind DrawableHitObjects to HitJudgement + hitRenderer.Schedule(() => hitRenderer.DrawableObjects.ForEach(h => h.CheckJudgement = hitJudgement.CheckJudgement)); Children = new Drawable[] { From 2013f93a968b523da04285965ea99780da4e602d Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 25 Nov 2016 02:31:19 -0500 Subject: [PATCH 017/133] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index d9bd79c4c1..60e210c1aa 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit d9bd79c4c15f7e5eb4e69fa7898b7d358e4516e4 +Subproject commit 60e210c1aa62a114fb08e50797f8f839da326cc3 From 202028f2c9a1bda1e254de3f3829f0929f4a9cd6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 Nov 2016 16:37:14 +0900 Subject: [PATCH 018/133] Remove glow on miss. --- osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs index 6c11b328a9..a0add258f7 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -116,6 +116,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables ring.FadeOut(); circle.FadeOut(); number.FadeOut(); + glow.FadeOut(); explosion?.Expire(); explosion = null; From ef0f975960ea2c1314ff0370a273dc0c9e8bef82 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 Nov 2016 16:41:00 +0900 Subject: [PATCH 019/133] Fix TestCaseHitObjects. --- osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs index 6da47c5bc4..11365adafe 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs @@ -12,6 +12,7 @@ using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Osu.Objects; using osu.Game.Modes.Osu.Objects.Drawables; using osu.Framework.Graphics.Containers; +using osu.Game.Modes; namespace osu.Desktop.VisualTests.Tests { @@ -51,6 +52,7 @@ namespace osu.Desktop.VisualTests.Tests Origin = Anchor.Centre, Depth = -i, State = ArmedState.Hit, + Judgement = new JudgementInfo { Result = HitResult.Hit300 } }; approachContainer.Add(d.ApproachCircle.CreateProxy()); From e36a51acf0deb94b30aec0b6da0b5a87de0938bd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 Nov 2016 18:14:56 +0900 Subject: [PATCH 020/133] Custom LifetimeList (experimental). --- osu.Game/Beatmaps/Drawables/BeatmapGroup.cs | 1 - osu.Game/Beatmaps/Drawables/Panel.cs | 6 +- osu.Game/Screens/Select/CarouselContainer.cs | 109 +++++++++++++------ 3 files changed, 79 insertions(+), 37 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs b/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs index 6721257393..3f5fe58ab5 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs @@ -60,7 +60,6 @@ namespace osu.Game.Beatmaps.Drawables Header = new BeatmapSetHeader(beatmap) { - Depth = 1, GainedSelection = headerGainedSelection, RelativeSizeAxes = Axes.X, }; diff --git a/osu.Game/Beatmaps/Drawables/Panel.cs b/osu.Game/Beatmaps/Drawables/Panel.cs index e271546cbe..cc8f5d4a55 100644 --- a/osu.Game/Beatmaps/Drawables/Panel.cs +++ b/osu.Game/Beatmaps/Drawables/Panel.cs @@ -15,7 +15,11 @@ namespace osu.Game.Beatmaps.Drawables { public const float MAX_HEIGHT = 80; - public bool Hidden => Alpha == 0 && Transforms.Count == 0; + public override bool RemoveWhenNotAlive => false; + + public bool OnScreen; + + public override bool IsAlive => OnScreen; private Container nestedContainer; diff --git a/osu.Game/Screens/Select/CarouselContainer.cs b/osu.Game/Screens/Select/CarouselContainer.cs index 26dc77d943..b7ffbefec0 100644 --- a/osu.Game/Screens/Select/CarouselContainer.cs +++ b/osu.Game/Screens/Select/CarouselContainer.cs @@ -10,39 +10,85 @@ using osu.Game.Database; using System; using System.Collections.Generic; using System.Linq; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Lists; using osu.Game.Beatmaps.Drawables; - +using osu.Framework.Timing; + namespace osu.Game.Screens.Select { class CarouselContainer : ScrollContainer { private Container scrollableContent; private List groups = new List(); - private List panels = new List(); public BeatmapGroup SelectedGroup { get; private set; } public BeatmapPanel SelectedPanel { get; private set; } - - private List yPositions = new List(); - - public CarouselContainer() - { - DistanceDecayJump = 0.01; - Add(scrollableContent = new Container + private List yPositions = new List(); + private CarouselLifetimeList Lifetime; + + public CarouselContainer() + { + DistanceDecayJump = 0.01; + + Add(scrollableContent = new Container(Lifetime = new CarouselLifetimeList(DepthComparer)) + { + RelativeSizeAxes = Axes.X, + }); + } + + internal class CarouselLifetimeList : LifetimeList + { + public CarouselLifetimeList(IComparer comparer) + : base(comparer) + { + } + + public int StartIndex; + public int EndIndex; + + public override bool Update(FrameTimeInfo time) { - RelativeSizeAxes = Axes.X, - }); - } + bool anyAliveChanged = false; + //check existing items to make sure they haven't died. + foreach (var item in AliveItems.ToArray()) + { + item.UpdateTime(time); + if (!item.IsAlive) + { + //todo: make this more efficient + int i = IndexOf(item); + anyAliveChanged |= CheckItem(item, ref i); + } + } + + //handle custom range + for (int i = StartIndex; i < EndIndex; i++) + { + var item = this[i]; + item.UpdateTime(time); + anyAliveChanged |= CheckItem(item, ref i); + } + + return anyAliveChanged; + } + } + public void AddGroup(BeatmapGroup group) { group.State = BeatmapGroupState.Collapsed; - groups.Add(group); - panels.Add(group.Header); + + group.Header.Depth = scrollableContent.Children.Count(); + scrollableContent.Add(group.Header); + foreach (BeatmapPanel panel in group.BeatmapPanels) - panels.Add(panel); + { + panel.Depth = scrollableContent.Children.Count(); + scrollableContent.Add(panel); + } computeYPositions(); } @@ -134,7 +180,7 @@ namespace osu.Game.Screens.Select ScrollTo(selectedY); } - private static float offsetX(Panel panel, float dist, float halfHeight) + private static float offsetX(float dist, float halfHeight) { // The radius of the circle the carousel moves on. const float CIRCLE_RADIUS = 4; @@ -144,28 +190,16 @@ namespace osu.Game.Screens.Select return 125 + x; } - private void addPanel(int index) - { - Panel panel = panels[index]; - if (panel.Hidden) - return; - - if (!scrollableContent.Contains(panel)) - { - panel.Depth = index + (panel is BeatmapSetHeader ? panels.Count : 0); - scrollableContent.Add(panel); - } - } - protected override void Update() { base.Update(); float drawHeight = DrawHeight; - scrollableContent.RemoveAll(delegate (Panel p) + + Lifetime.AliveItems.ForEach(delegate (Panel p) { float panelPosY = p.Position.Y; - return panelPosY < Current - p.DrawHeight || panelPosY > Current + drawHeight || !IsVisible; + p.OnScreen = panelPosY >= Current - p.DrawHeight && panelPosY <= Current + drawHeight; }); int firstIndex = yPositions.BinarySearch(Current - Panel.MAX_HEIGHT); @@ -173,19 +207,24 @@ namespace osu.Game.Screens.Select int lastIndex = yPositions.BinarySearch(Current + drawHeight); if (lastIndex < 0) lastIndex = ~lastIndex; - for (int i = firstIndex; i < lastIndex; ++i) - addPanel(i); + Lifetime.StartIndex = firstIndex; + Lifetime.EndIndex = lastIndex; float halfHeight = drawHeight / 2; - foreach (Panel panel in scrollableContent.Children) + + for (int i = firstIndex; i < lastIndex; ++i) { + var panel = Lifetime[i]; + + panel.OnScreen = true; + float panelDrawY = panel.Position.Y - Current + panel.DrawHeight / 2; float dist = Math.Abs(1f - panelDrawY / halfHeight); // Setting the origin position serves as an additive position on top of potential // local transformation we may want to apply (e.g. when a panel gets selected, we // may want to smoothly transform it leftwards.) - panel.OriginPosition = new Vector2(-offsetX(panel, dist, halfHeight), 0); + panel.OriginPosition = new Vector2(-offsetX(dist, halfHeight), 0); // We are applying a multiplicative alpha (which is internally done by nesting an // additional container and setting that container's alpha) such that we can From c85454d0343fd6c5d1fc71de17c380c41abc0141 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 25 Nov 2016 05:12:01 -0500 Subject: [PATCH 021/133] Reset db on dispose --- .../Tests/TestCasePlaySongSelect.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs index 57dbb2d266..5d85bf0a5d 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs @@ -12,7 +12,7 @@ namespace osu.Desktop.VisualTests.Tests { class TestCasePlaySongSelect : TestCase { - private BeatmapDatabase db; + private BeatmapDatabase db, oldDb; private TestStorage storage; public override string Name => @"Song Select"; @@ -21,7 +21,7 @@ namespace osu.Desktop.VisualTests.Tests public override void Reset() { base.Reset(); - + oldDb = Dependencies.Get(); if (db == null) { storage = new TestStorage(@"TestCasePlaySongSelect"); @@ -35,9 +35,14 @@ namespace osu.Desktop.VisualTests.Tests db.Import(sets); } - Add(new PlaySongSelect()); } + + protected override void Dispose(bool isDisposing) + { + Dependencies.Cache(oldDb, true); + base.Dispose(isDisposing); + } private BeatmapSetInfo createTestBeatmapSet(int i) { From 396ca9fe9163263ddd60936cc07cef59cdab15f1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 26 Nov 2016 16:51:51 +0900 Subject: [PATCH 022/133] Remove HitJudgementResolver; reimplement in DrawableHitObject. --- .../Tests/TestCaseHitObjects.cs | 1 - .../Objects/Drawables/DrawableHitCircle.cs | 50 ++++++++++++-- .../Objects/Drawables/DrawableOsuHitObject.cs | 32 +++++---- .../Objects/Drawables/DrawableSlider.cs | 3 +- .../Objects/Drawables/HitExplosion.cs | 7 +- .../Objects/Drawables/Pieces/CirclePiece.cs | 3 +- osu.Game.Mode.Osu/OsuHitJudgementResolver.cs | 41 ------------ osu.Game.Mode.Osu/OsuRuleset.cs | 2 - osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj | 2 +- .../Objects/Drawables/DrawableHitObject.cs | 66 ++++++++++++++----- osu.Game/Modes/Ruleset.cs | 2 - osu.Game/Modes/UI/HitRenderer.cs | 4 +- osu.Game/Screens/Play/Player.cs | 5 -- osu.Game/osu.Game.csproj | 1 - 14 files changed, 115 insertions(+), 104 deletions(-) rename osu.Game/Modes/HitJudgementResolver.cs => osu.Game.Mode.Osu/Objects/Drawables/DrawableOsuHitObject.cs (51%) delete mode 100644 osu.Game.Mode.Osu/OsuHitJudgementResolver.cs diff --git a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs index 11365adafe..0569fcf3c3 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs @@ -52,7 +52,6 @@ namespace osu.Desktop.VisualTests.Tests Origin = Anchor.Centre, Depth = -i, State = ArmedState.Hit, - Judgement = new JudgementInfo { Result = HitResult.Hit300 } }; approachContainer.Add(d.ApproachCircle.CreateProxy()); diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs index a0add258f7..dc5d5bf2a6 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -2,6 +2,7 @@ //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.ComponentModel; using osu.Framework.Graphics; using osu.Framework.Graphics.Transformations; using osu.Game.Modes.Objects.Drawables; @@ -10,7 +11,7 @@ using OpenTK; namespace osu.Game.Modes.Osu.Objects.Drawables { - public class DrawableHitCircle : DrawableHitObject + public class DrawableHitCircle : DrawableOsuHitObject { private OsuHitObject osuObject; @@ -39,9 +40,12 @@ namespace osu.Game.Modes.Osu.Objects.Drawables circle = new CirclePiece { Colour = osuObject.Colour, - Hit = () => Hit(new JudgementInfo { - UserTriggered = true, - }), + Hit = () => + { + ((PositionalJudgementInfo)Judgement).PositionOffset = Vector2.Zero; //todo: set to correct value + UpdateJudgement(true); + return true; + }, }, number = new NumberPiece(), ring = new RingPiece(), @@ -68,6 +72,38 @@ namespace osu.Game.Modes.Osu.Objects.Drawables UpdateState(State); } + double hit50 = 150; + double hit100 = 80; + double hit300 = 30; + + protected override void CheckJudgement(bool userTriggered) + { + if (!userTriggered) + { + if (Judgement.TimeOffset > hit50) + Judgement.Result = HitResult.Miss; + return; + } + + double hitOffset = Math.Abs(Judgement.TimeOffset); + + if (hitOffset < hit50) + { + Judgement.Result = HitResult.Hit; + + OsuJudgementInfo osuInfo = Judgement as OsuJudgementInfo; + + if (hitOffset < hit300) + osuInfo.Score = OsuScoreResult.Hit300; + else if (hitOffset < hit100) + osuInfo.Score = OsuScoreResult.Hit100; + else if (hitOffset < hit50) + osuInfo.Score = OsuScoreResult.Hit50; + } + else + Judgement.Result = HitResult.Miss; + } + protected override void UpdateState(ArmedState state) { if (!IsLoaded) return; @@ -75,7 +111,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Flush(true); //move to DrawableHitObject ApproachCircle.Flush(true); - double t = osuObject.EndTime + (Judgement?.TimeOffset ?? 0); + double t = osuObject.EndTime + Judgement.TimeOffset; Alpha = 0; @@ -121,7 +157,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables explosion?.Expire(); explosion = null; - Schedule(() => Add(explosion = new HitExplosion(HitResult.Miss))); + Schedule(() => Add(explosion = new HitExplosion((OsuJudgementInfo)Judgement))); FadeOut(800); break; @@ -134,7 +170,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables explode.FadeIn(flash_in); - Schedule(() => Add(explosion = new HitExplosion(Judgement.Result))); + Schedule(() => Add(explosion = new HitExplosion((OsuJudgementInfo)Judgement))); Delay(flash_in, true); diff --git a/osu.Game/Modes/HitJudgementResolver.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableOsuHitObject.cs similarity index 51% rename from osu.Game/Modes/HitJudgementResolver.cs rename to osu.Game.Mode.Osu/Objects/Drawables/DrawableOsuHitObject.cs index d9f3cc96c1..d416732327 100644 --- a/osu.Game/Modes/HitJudgementResolver.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -1,34 +1,33 @@ -//Copyright (c) 2007-2016 ppy Pty Ltd . -//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; +using System; using System.Collections.Generic; using System.ComponentModel; -using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; using osu.Game.Modes.Objects; using osu.Game.Modes.Objects.Drawables; -using OpenTK; -namespace osu.Game.Modes +namespace osu.Game.Modes.Osu.Objects.Drawables { - public class HitJudgementResolver + public class DrawableOsuHitObject : DrawableHitObject { - public virtual void CheckJudgement(DrawableHitObject h, JudgementInfo info) + public DrawableOsuHitObject(OsuHitObject hitObject) + : base(hitObject) { - info.Result = HitResult.Hit300; + } + + public override JudgementInfo CreateJudgementInfo() => new OsuJudgementInfo(); + + protected override void UpdateState(ArmedState state) + { + throw new NotImplementedException(); } } - public class JudgementInfo + public class OsuJudgementInfo : PositionalJudgementInfo { - public bool UserTriggered; + public OsuScoreResult Score; public ComboResult Combo; - public HitResult Result; - public double TimeOffset; - public Vector2 PositionOffset; } public enum ComboResult @@ -41,9 +40,8 @@ namespace osu.Game.Modes Perfect } - public enum HitResult + public enum OsuScoreResult { - Ignore, [Description(@"Miss")] Miss, [Description(@"50")] diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index 50203d48ae..55e4781cd3 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -5,7 +5,7 @@ using OpenTK; namespace osu.Game.Modes.Osu.Objects.Drawables { - class DrawableSlider : DrawableHitObject + class DrawableSlider : DrawableOsuHitObject { public DrawableSlider(Slider h) : base(h) { @@ -18,7 +18,6 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Add(new CirclePiece { Colour = h.Colour, - Hit = () => Hit(new JudgementInfo()), Position = h.Curve.PositionAt(i) - h.Position //non-relative? }); } diff --git a/osu.Game.Mode.Osu/Objects/Drawables/HitExplosion.cs b/osu.Game.Mode.Osu/Objects/Drawables/HitExplosion.cs index fac9ab636b..a0ab68fa99 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/HitExplosion.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/HitExplosion.cs @@ -3,6 +3,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Transformations; +using osu.Game.Modes.Objects.Drawables; using OpenTK; namespace osu.Game.Modes.Osu.Objects.Drawables @@ -12,7 +13,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables private SpriteText line1; private SpriteText line2; - public HitExplosion(HitResult hitResult, ComboResult comboResult = ComboResult.None) + public HitExplosion(OsuJudgementInfo judgement) { AutoSizeAxes = Axes.Both; Anchor = Anchor.Centre; @@ -27,13 +28,13 @@ namespace osu.Game.Modes.Osu.Objects.Drawables { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Text = hitResult.GetDescription(), + Text = judgement.Score.GetDescription(), Font = @"Venera", TextSize = 20, }, line2 = new SpriteText { - Text = comboResult.GetDescription(), + Text = judgement.Combo.GetDescription(), Font = @"Venera", TextSize = 14, } diff --git a/osu.Game.Mode.Osu/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Mode.Osu/Objects/Drawables/Pieces/CirclePiece.cs index c326c46553..fd55a8315a 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/Pieces/CirclePiece.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/Pieces/CirclePiece.cs @@ -49,8 +49,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { - Hit?.Invoke(); - return true; + return Hit?.Invoke() ?? false; } } } \ No newline at end of file diff --git a/osu.Game.Mode.Osu/OsuHitJudgementResolver.cs b/osu.Game.Mode.Osu/OsuHitJudgementResolver.cs deleted file mode 100644 index 6dc240c7af..0000000000 --- a/osu.Game.Mode.Osu/OsuHitJudgementResolver.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Osu.Objects.Drawables; - -namespace osu.Game.Modes.Osu -{ - class OsuHitJudgementResolver : HitJudgementResolver - { - double hit50 = 150; - double hit100 = 80; - double hit300 = 30; - public override void CheckJudgement(DrawableHitObject h, JudgementInfo info) - { - DrawableHitCircle circle = h as DrawableHitCircle; - if (circle != null) - { - if (!info.UserTriggered) - { - if (info.TimeOffset > hit50) - info.Result = HitResult.Miss; - return; - } - - double hitOffset = Math.Abs(info.TimeOffset); - - if (hitOffset < hit300) - info.Result = HitResult.Hit300; - else if (hitOffset < hit100) - info.Result = HitResult.Hit100; - else if (hitOffset < hit50) - info.Result = HitResult.Hit50; - else - info.Result = HitResult.Miss; - } - } - } -} diff --git a/osu.Game.Mode.Osu/OsuRuleset.cs b/osu.Game.Mode.Osu/OsuRuleset.cs index e79cbef748..ac43e5501c 100644 --- a/osu.Game.Mode.Osu/OsuRuleset.cs +++ b/osu.Game.Mode.Osu/OsuRuleset.cs @@ -13,8 +13,6 @@ namespace osu.Game.Modes.Osu { public override ScoreOverlay CreateScoreOverlay() => new OsuScoreOverlay(); - public override HitJudgementResolver CreateHitJudgement() => new OsuHitJudgementResolver(); - public override HitRenderer CreateHitRendererWith(List objects) => new OsuHitRenderer { Objects = objects }; public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser(); diff --git a/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj b/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj index d63cc2354a..97b4ebcb99 100644 --- a/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj +++ b/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj @@ -41,6 +41,7 @@ + @@ -52,7 +53,6 @@ - diff --git a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs index 0d8b124be2..3508d6c3a6 100644 --- a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs @@ -2,23 +2,26 @@ //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.ComponentModel; using System.Diagnostics; using osu.Framework; using osu.Framework.Graphics.Containers; +using OpenTK; +using Container = osu.Framework.Graphics.Containers.Container; namespace osu.Game.Modes.Objects.Drawables { public abstract class DrawableHitObject : Container, IStateful { //todo: move to a more central implementation. this logic should not be at a drawable level. - public Action OnHit; - public Action OnMiss; - - public Action CheckJudgement; + public Action OnHit; + public Action OnMiss; public Container ChildObjects; - public JudgementInfo Judgement; + protected JudgementInfo Judgement; + + public abstract JudgementInfo CreateJudgementInfo(); public HitObject HitObject; @@ -42,47 +45,55 @@ namespace osu.Game.Modes.Objects.Drawables } } + protected override void LoadComplete() + { + base.LoadComplete(); + + Judgement = CreateJudgementInfo(); + } + /// /// Process a hit of this hitobject. Carries out judgement. /// /// Preliminary judgement information provided by the hit source. /// Whether a hit was processed. - protected bool Hit(JudgementInfo judgement) + protected bool UpdateJudgement(bool userTriggered) { - if (State != ArmedState.Idle) + if (Judgement.Result != null) return false; - judgement.TimeOffset = Time.Current - HitObject.EndTime; + Judgement.TimeOffset = Time.Current - HitObject.EndTime; - CheckJudgement?.Invoke(this, judgement); + CheckJudgement(userTriggered); - if (judgement.Result == HitResult.Ignore) + if (Judgement.Result == null) return false; - Judgement = judgement; - - switch (judgement.Result) + switch (Judgement.Result) { default: State = ArmedState.Hit; - OnHit?.Invoke(this); + OnHit?.Invoke(this, Judgement); break; case HitResult.Miss: State = ArmedState.Miss; - OnMiss?.Invoke(this); + OnMiss?.Invoke(this, Judgement); break; } - return true; } + protected virtual void CheckJudgement(bool userTriggered) + { + + } + protected override void Update() { base.Update(); - if (Time.Current >= HitObject.EndTime && Judgement == null) - Hit(new JudgementInfo()); + UpdateJudgement(false); } protected abstract void UpdateState(ArmedState state); @@ -94,4 +105,23 @@ namespace osu.Game.Modes.Objects.Drawables Hit, Miss } + + public class PositionalJudgementInfo : JudgementInfo + { + public Vector2 PositionOffset; + } + + public class JudgementInfo + { + public HitResult? Result; + public double TimeOffset; + } + + public enum HitResult + { + [Description(@"Miss")] + Miss, + [Description(@"Hit")] + Hit, + } } diff --git a/osu.Game/Modes/Ruleset.cs b/osu.Game/Modes/Ruleset.cs index 6576159f62..d35aab6568 100644 --- a/osu.Game/Modes/Ruleset.cs +++ b/osu.Game/Modes/Ruleset.cs @@ -22,8 +22,6 @@ namespace osu.Game.Modes public abstract HitObjectParser CreateHitObjectParser(); - public virtual HitJudgementResolver CreateHitJudgement() => new HitJudgementResolver(); - public static void Register(Ruleset ruleset) => availableRulesets.TryAdd(ruleset.PlayMode, ruleset.GetType()); protected abstract PlayMode PlayMode { get; } diff --git a/osu.Game/Modes/UI/HitRenderer.cs b/osu.Game/Modes/UI/HitRenderer.cs index f160356cb4..d37cf545a8 100644 --- a/osu.Game/Modes/UI/HitRenderer.cs +++ b/osu.Game/Modes/UI/HitRenderer.cs @@ -75,12 +75,12 @@ namespace osu.Game.Modes.UI } } - private void onMiss(DrawableHitObject obj) + private void onMiss(DrawableHitObject obj, JudgementInfo judgement) { OnMiss?.Invoke(obj.HitObject); } - private void onHit(DrawableHitObject obj) + private void onHit(DrawableHitObject obj, JudgementInfo judgement) { OnHit?.Invoke(obj.HitObject); } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index a5bbf8c453..66cec7405e 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -86,17 +86,12 @@ namespace osu.Game.Screens.Play var scoreOverlay = ruleset.CreateScoreOverlay(); var hitRenderer = ruleset.CreateHitRendererWith(beatmap.HitObjects); - var hitJudgement = ruleset.CreateHitJudgement(); - hitRenderer.OnHit += delegate (HitObject h) { scoreOverlay.OnHit(h); }; hitRenderer.OnMiss += delegate (HitObject h) { scoreOverlay.OnMiss(h); }; if (Autoplay) hitRenderer.Schedule(() => hitRenderer.DrawableObjects.ForEach(h => h.State = ArmedState.Hit)); - //bind DrawableHitObjects to HitJudgement - hitRenderer.Schedule(() => hitRenderer.DrawableObjects.ForEach(h => h.CheckJudgement = hitJudgement.CheckJudgement)); - Children = new Drawable[] { new PlayerInputManager(game.Host) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 9c2bbf086a..00c46a7ce3 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -64,7 +64,6 @@ - From a1c3d15e6ca0021fa49f17d629b10dcc5bab2cfc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 26 Nov 2016 17:10:13 +0900 Subject: [PATCH 023/133] Add triangles to difficulty panels. --- osu.Game/Beatmaps/Drawables/BeatmapPanel.cs | 59 +++++++++++++++++++-- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/BeatmapPanel.cs b/osu.Game/Beatmaps/Drawables/BeatmapPanel.cs index 6de25a853b..0062ddf0e1 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapPanel.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapPanel.cs @@ -2,11 +2,14 @@ //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Framework.MathUtils; using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; @@ -22,6 +25,8 @@ namespace osu.Game.Beatmaps.Drawables public Action GainedSelection; + Color4 deselectedColour = new Color4(20, 43, 51, 255); + protected override void Selected() { base.Selected(); @@ -36,7 +41,7 @@ namespace osu.Game.Beatmaps.Drawables { base.Deselected(); - background.Colour = new Color4(20, 43, 51, 255); + background.Colour = deselectedColour; } public BeatmapPanel(BeatmapInfo beatmap) @@ -44,12 +49,18 @@ namespace osu.Game.Beatmaps.Drawables Beatmap = beatmap; Height *= 0.60f; - Children = new Framework.Graphics.Drawable[] + Children = new Drawable[] { background = new Box { RelativeSizeAxes = Axes.Both, }, + new Triangles + { + RelativeSizeAxes = Axes.Both, + BlendingMode = BlendingMode.Additive, + Colour = deselectedColour, + }, new FlowContainer { Padding = new MarginPadding(5), @@ -57,7 +68,7 @@ namespace osu.Game.Beatmaps.Drawables AutoSizeAxes = Axes.Both, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Children = new Framework.Graphics.Drawable[] + Children = new Drawable[] { new DifficultyIcon(FontAwesome.fa_dot_circle_o, new Color4(159, 198, 0, 255)) { @@ -71,7 +82,7 @@ namespace osu.Game.Beatmaps.Drawables Spacing = new Vector2(0, 5), Direction = FlowDirection.VerticalOnly, AutoSizeAxes = Axes.Both, - Children = new Framework.Graphics.Drawable[] + Children = new Drawable[] { new FlowContainer { @@ -113,5 +124,45 @@ namespace osu.Game.Beatmaps.Drawables } }; } + + public class Triangles : Container + { + private Texture triangle; + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + triangle = textures.Get(@"Play/osu/triangle@2x"); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + for (int i = 0; i < 10; i++) + { + Add(new Sprite + { + Texture = triangle, + Origin = Anchor.TopCentre, + RelativePositionAxes = Axes.Both, + Position = new Vector2(RNG.NextSingle(), RNG.NextSingle()), + Scale = new Vector2(RNG.NextSingle() * 0.4f + 0.2f), + Alpha = RNG.NextSingle() * 0.3f + }); + } + } + + protected override void Update() + { + base.Update(); + + foreach (Drawable d in Children) + { + d.Position -= new Vector2(0, (float)(d.Scale.X * (Time.Elapsed / 880))); + if (d.DrawPosition.Y + d.DrawSize.Y * d.Scale.Y < 0) + d.MoveToY(1); + } + } + } } } From f6bb5a2c492c3d896379972228246357ca5d89b2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 26 Nov 2016 17:17:56 +0900 Subject: [PATCH 024/133] Update framework. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 60e210c1aa..cc614047de 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 60e210c1aa62a114fb08e50797f8f839da326cc3 +Subproject commit cc614047de3471a2d2b4b988fed550fc946016b9 From 5764bf8093e75aa83052bf164c5134551326eec0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 26 Nov 2016 17:20:34 +0900 Subject: [PATCH 025/133] Improve IsAlive logic. --- osu.Game/Beatmaps/Drawables/Panel.cs | 4 ++-- osu.Game/Screens/Select/CarouselContainer.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/Panel.cs b/osu.Game/Beatmaps/Drawables/Panel.cs index cc8f5d4a55..f97a5260d8 100644 --- a/osu.Game/Beatmaps/Drawables/Panel.cs +++ b/osu.Game/Beatmaps/Drawables/Panel.cs @@ -17,9 +17,9 @@ namespace osu.Game.Beatmaps.Drawables public override bool RemoveWhenNotAlive => false; - public bool OnScreen; + public bool IsOnScreen; - public override bool IsAlive => OnScreen; + public override bool IsAlive => IsOnScreen && base.IsAlive; private Container nestedContainer; diff --git a/osu.Game/Screens/Select/CarouselContainer.cs b/osu.Game/Screens/Select/CarouselContainer.cs index b7ffbefec0..9ff950cc06 100644 --- a/osu.Game/Screens/Select/CarouselContainer.cs +++ b/osu.Game/Screens/Select/CarouselContainer.cs @@ -199,7 +199,7 @@ namespace osu.Game.Screens.Select Lifetime.AliveItems.ForEach(delegate (Panel p) { float panelPosY = p.Position.Y; - p.OnScreen = panelPosY >= Current - p.DrawHeight && panelPosY <= Current + drawHeight; + p.IsOnScreen = panelPosY >= Current - p.DrawHeight && panelPosY <= Current + drawHeight; }); int firstIndex = yPositions.BinarySearch(Current - Panel.MAX_HEIGHT); @@ -216,7 +216,7 @@ namespace osu.Game.Screens.Select { var panel = Lifetime[i]; - panel.OnScreen = true; + panel.IsOnScreen = true; float panelDrawY = panel.Position.Y - Current + panel.DrawHeight / 2; float dist = Math.Abs(1f - panelDrawY / halfHeight); From af18d2535736f5b009f690479b18bf83ce9f54ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 26 Nov 2016 17:31:35 +0900 Subject: [PATCH 026/133] Move some styling inside BeatmapInfoWedge and fix initial transition happening too early. --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 21 +++++++++++++++++++-- osu.Game/Screens/Select/PlaySongSelect.cs | 12 ------------ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index c6ed202326..7e87194cf4 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -16,10 +16,27 @@ namespace osu.Game.Screens.Select { class BeatmapInfoWedge : Container { + private static readonly Vector2 wedged_container_shear = new Vector2(0.15f, 0); + private Container beatmapInfoContainer; private BaseGame game; + public BeatmapInfoWedge() + { + Shear = wedged_container_shear; + Masking = true; + BorderColour = new Color4(221, 255, 255, 255); + BorderThickness = 2.5f; + EdgeEffect = new EdgeEffect + { + Type = EdgeEffectType.Glow, + Colour = new Color4(130, 204, 255, 150), + Radius = 20, + Roundness = 15, + }; + } + [BackgroundDependencyLoader] private void load(BaseGame game) { @@ -35,8 +52,6 @@ namespace osu.Game.Screens.Select float newDepth = lastContainer?.Depth - 1 ?? 0; - FadeIn(250); - BeatmapSetInfo beatmapSetInfo = beatmap.BeatmapSetInfo; BeatmapInfo beatmapInfo = beatmap.BeatmapInfo; @@ -126,6 +141,8 @@ namespace osu.Game.Screens.Select } }).Preload(game, delegate(Drawable d) { + FadeIn(250); + lastContainer?.FadeOut(250); lastContainer?.Expire(); diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 371d014659..8c8ff39fba 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -38,7 +38,6 @@ namespace osu.Game.Screens.Select private TrackManager trackManager; private static readonly Vector2 wedged_container_size = new Vector2(0.5f, 225); - private static readonly Vector2 wedged_container_shear = new Vector2(0.15f, 0); private static readonly Vector2 wedged_container_start_position = new Vector2(0, 50); private BeatmapInfoWedge beatmapInfoWedge; @@ -105,18 +104,7 @@ namespace osu.Game.Screens.Select Position = wedged_container_start_position, Size = wedged_container_size, RelativeSizeAxes = Axes.X, - Shear = wedged_container_shear, Margin = new MarginPadding { Top = 20, Right = 20, }, - Masking = true, - BorderColour = new Color4(221, 255, 255, 255), - BorderThickness = 2.5f, - EdgeEffect = new EdgeEffect - { - Type = EdgeEffectType.Glow, - Colour = new Color4(130, 204, 255, 150), - Radius = 20, - Roundness = 15, - }, }, new Container { From c978a4c09186f0676d74d1f47b74ecfa381f3d8b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 26 Nov 2016 19:22:56 +0900 Subject: [PATCH 027/133] Tidy up code. Make trail smooth. --- osu.Game/Graphics/Cursor/CursorTrail.cs | 155 ++++++++++++++++++ .../Graphics/Cursor/OsuCursorContainer.cs | 15 +- osu.Game/osu.Game.csproj | 1 + 3 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Graphics/Cursor/CursorTrail.cs diff --git a/osu.Game/Graphics/Cursor/CursorTrail.cs b/osu.Game/Graphics/Cursor/CursorTrail.cs new file mode 100644 index 0000000000..741fdbad73 --- /dev/null +++ b/osu.Game/Graphics/Cursor/CursorTrail.cs @@ -0,0 +1,155 @@ +//Copyright (c) 2007-2016 ppy Pty Ltd . +//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Batches; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shaders; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Framework.Input; +using osu.Framework.MathUtils; +using OpenTK; + +namespace osu.Game.Graphics.Cursor +{ + class TrailSprite : Sprite + { + private Shader shader; + + public TrailSprite() + { + Origin = Anchor.Centre; + } + + protected override void ApplyDrawNode(DrawNode node) + { + base.ApplyDrawNode(node); + + SpriteDrawNode sNode = node as SpriteDrawNode; + sNode.RoundedTextureShader = sNode.TextureShader = shader; + } + + [BackgroundDependencyLoader] + private void load(ShaderManager shaders, TextureStore textures) + { + shader = shaders?.Load(@"CursorTrail", FragmentShaderDescriptor.Texture); + Texture = textures.Get(@"Cursor/cursortrail"); + } + } + + class CursorTrail : Container + { + public override bool Contains(Vector2 screenSpacePos) => true; + + int currentIndex; + + protected override bool CanBeFlattened => false; + + Shader shader; + + private double timeOffset; + + private float time; + + const int MAX_SPRITES = 2048; + + protected override DrawNode CreateDrawNode() => new TrailDrawNode(); + + protected override void ApplyDrawNode(DrawNode node) + { + base.ApplyDrawNode(node); + + TrailDrawNode tNode = node as TrailDrawNode; + tNode.Shader = shader; + tNode.Time = time; + } + + Vector2? last; + + protected override bool OnMouseMove(InputState state) + { + if (last == null) + { + last = state.Mouse.Position; + return base.OnMouseMove(state); + } + + Vector2 pos1 = last.Value; + Vector2 pos2 = state.Mouse.Position; + + Vector2 diff = (pos2 - pos1); + float distance = diff.Length; + Vector2 direction = diff / distance; + + float interval = this[0].DrawSize.X / 2; + + for (float d = interval; d < distance; d += interval) + { + last = pos1 + direction * d; + addPosition(last.Value); + } + + return base.OnMouseMove(state); + } + + private void addPosition(Vector2 pos) + { + var s = this[currentIndex]; + s.Position = pos; + s.Alpha = time + 1f; + + currentIndex = (currentIndex + 1) % MAX_SPRITES; + } + + public CursorTrail() + { + RelativeSizeAxes = Axes.Both; + + for (int i = 0; i < MAX_SPRITES; i++) + AddInternal(new TrailSprite()); + } + + [BackgroundDependencyLoader] + private void load(ShaderManager shaders) + { + shader = shaders?.Load(@"CursorTrail", FragmentShaderDescriptor.Texture); + } + + protected override void Update() + { + base.Update(); + + Invalidate(Invalidation.DrawNode); + + int fadeClockResetThreshold = 1000000; + + time = (float)(Time.Current - timeOffset) / 500f; + if (time > fadeClockResetThreshold) + ResetTime(); + } + + private void ResetTime() + { + foreach (var c in Children) + c.Alpha -= time; + + time = 0; + timeOffset = Time.Current; + } + + class TrailDrawNode : ContainerDrawNode + { + public Shader Shader; + public float Time; + + public override void Draw(IVertexBatch vertexBatch) + { + Shader.GetUniform("g_FadeClock").Value = Time; + base.Draw(vertexBatch); + } + } + } +} \ No newline at end of file diff --git a/osu.Game/Graphics/Cursor/OsuCursorContainer.cs b/osu.Game/Graphics/Cursor/OsuCursorContainer.cs index 081919feaf..bdf84e1d04 100644 --- a/osu.Game/Graphics/Cursor/OsuCursorContainer.cs +++ b/osu.Game/Graphics/Cursor/OsuCursorContainer.cs @@ -1,15 +1,22 @@ //Copyright (c) 2007-2016 ppy Pty Ltd . //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; +using OpenTK; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.OpenGL; +using osu.Framework.Graphics.OpenGL.Buffers; +using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Transformations; using osu.Framework.Input; +using OpenTK.Graphics; +using OpenTK.Graphics.ES30; namespace osu.Game.Graphics.Cursor { @@ -17,9 +24,14 @@ namespace osu.Game.Graphics.Cursor { protected override Drawable CreateCursor() => new OsuCursor(); + public OsuCursorContainer() + { + Add(new CursorTrail { Depth = -1 }); + } + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { - ActiveCursor.Scale = new OpenTK.Vector2(1); + ActiveCursor.Scale = new Vector2(1); ActiveCursor.ScaleTo(1.2f, 100, EasingTypes.OutQuad); return base.OnMouseDown(state, args); } @@ -52,5 +64,4 @@ namespace osu.Game.Graphics.Cursor } } } - } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 00c46a7ce3..c35bafb251 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -64,6 +64,7 @@ + From 0de4ec451f26c6f35d23c145136074d41782e41c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 26 Nov 2016 19:23:05 +0900 Subject: [PATCH 028/133] Update resources, framework. --- osu-framework | 2 +- osu-resources | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu-framework b/osu-framework index cc614047de..3dbd4a3109 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit cc614047de3471a2d2b4b988fed550fc946016b9 +Subproject commit 3dbd4a31095b99b8f69920afdbebeb4885061865 diff --git a/osu-resources b/osu-resources index 911564f95a..ab7b953ec9 160000 --- a/osu-resources +++ b/osu-resources @@ -1 +1 @@ -Subproject commit 911564f95a1b7820671cb17fadcd11bab8ba144e +Subproject commit ab7b953ec9393d8df5aeb23d23e8b1f8154601c1 From be0cc7badcb1669aff29a3e2cabc3468787ab67b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 26 Nov 2016 19:25:58 +0900 Subject: [PATCH 029/133] Code tidying. --- osu.Game/Graphics/Cursor/CursorTrail.cs | 76 ++++++++++++------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/osu.Game/Graphics/Cursor/CursorTrail.cs b/osu.Game/Graphics/Cursor/CursorTrail.cs index 741fdbad73..d65e20c47d 100644 --- a/osu.Game/Graphics/Cursor/CursorTrail.cs +++ b/osu.Game/Graphics/Cursor/CursorTrail.cs @@ -56,6 +56,8 @@ namespace osu.Game.Graphics.Cursor const int MAX_SPRITES = 2048; + Vector2? lastPosition; + protected override DrawNode CreateDrawNode() => new TrailDrawNode(); protected override void ApplyDrawNode(DrawNode node) @@ -67,43 +69,6 @@ namespace osu.Game.Graphics.Cursor tNode.Time = time; } - Vector2? last; - - protected override bool OnMouseMove(InputState state) - { - if (last == null) - { - last = state.Mouse.Position; - return base.OnMouseMove(state); - } - - Vector2 pos1 = last.Value; - Vector2 pos2 = state.Mouse.Position; - - Vector2 diff = (pos2 - pos1); - float distance = diff.Length; - Vector2 direction = diff / distance; - - float interval = this[0].DrawSize.X / 2; - - for (float d = interval; d < distance; d += interval) - { - last = pos1 + direction * d; - addPosition(last.Value); - } - - return base.OnMouseMove(state); - } - - private void addPosition(Vector2 pos) - { - var s = this[currentIndex]; - s.Position = pos; - s.Alpha = time + 1f; - - currentIndex = (currentIndex + 1) % MAX_SPRITES; - } - public CursorTrail() { RelativeSizeAxes = Axes.Both; @@ -140,9 +105,44 @@ namespace osu.Game.Graphics.Cursor timeOffset = Time.Current; } + protected override bool OnMouseMove(InputState state) + { + if (lastPosition == null) + { + lastPosition = state.Mouse.Position; + return base.OnMouseMove(state); + } + + Vector2 pos1 = lastPosition.Value; + Vector2 pos2 = state.Mouse.Position; + + Vector2 diff = pos2 - pos1; + float distance = diff.Length; + Vector2 direction = diff / distance; + + float interval = this[0].DrawSize.X / 2; + + for (float d = interval; d < distance; d += interval) + { + lastPosition = pos1 + direction * d; + addPosition(lastPosition.Value); + } + + return base.OnMouseMove(state); + } + + private void addPosition(Vector2 pos) + { + var s = this[currentIndex]; + s.Position = pos; + s.Alpha = time + 1f; + + currentIndex = (currentIndex + 1) % MAX_SPRITES; + } + class TrailDrawNode : ContainerDrawNode { - public Shader Shader; + public new Shader Shader; public float Time; public override void Draw(IVertexBatch vertexBatch) From 23d0e52d4f06ff1fbdca3b41367382d5bf970ae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Sat, 26 Nov 2016 14:08:43 +0100 Subject: [PATCH 030/133] Optimize draw portion of cursor trail. --- osu-framework | 2 +- osu.Game/Graphics/Cursor/CursorTrail.cs | 76 +++++++++++++++++++++++-- 2 files changed, 72 insertions(+), 6 deletions(-) diff --git a/osu-framework b/osu-framework index 3dbd4a3109..c0157172ef 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 3dbd4a31095b99b8f69920afdbebeb4885061865 +Subproject commit c0157172ef277b5c2fa1039be9ea895fa27ae20a diff --git a/osu.Game/Graphics/Cursor/CursorTrail.cs b/osu.Game/Graphics/Cursor/CursorTrail.cs index d65e20c47d..82281cae1f 100644 --- a/osu.Game/Graphics/Cursor/CursorTrail.cs +++ b/osu.Game/Graphics/Cursor/CursorTrail.cs @@ -12,6 +12,13 @@ using osu.Framework.Graphics.Textures; using osu.Framework.Input; using osu.Framework.MathUtils; using OpenTK; +using System; +using osu.Framework.Graphics.OpenGL; +using osu.Framework.Graphics.OpenGL.Buffers; +using System.Collections.Concurrent; +using OpenTK.Graphics.ES30; +using System.Collections.Generic; +using System.Diagnostics; namespace osu.Game.Graphics.Cursor { @@ -24,14 +31,19 @@ namespace osu.Game.Graphics.Cursor Origin = Anchor.Centre; } + protected override DrawNode CreateDrawNode() => new TrailSpriteDrawNode(); + protected override void ApplyDrawNode(DrawNode node) { base.ApplyDrawNode(node); - SpriteDrawNode sNode = node as SpriteDrawNode; + TrailSpriteDrawNode sNode = node as TrailSpriteDrawNode; sNode.RoundedTextureShader = sNode.TextureShader = shader; + sNode.NeedsUpdate = true; } + public override bool IsVisible => true; + [BackgroundDependencyLoader] private void load(ShaderManager shaders, TextureStore textures) { @@ -40,6 +52,11 @@ namespace osu.Game.Graphics.Cursor } } + class TrailSpriteDrawNode : SpriteDrawNode + { + public bool NeedsUpdate; + } + class CursorTrail : Container { public override bool Contains(Vector2 screenSpacePos) => true; @@ -53,7 +70,8 @@ namespace osu.Game.Graphics.Cursor private double timeOffset; private float time; - + + TrailDrawNodeSharedData trailDrawNodeSharedData = new TrailDrawNodeSharedData(); const int MAX_SPRITES = 2048; Vector2? lastPosition; @@ -67,6 +85,7 @@ namespace osu.Game.Graphics.Cursor TrailDrawNode tNode = node as TrailDrawNode; tNode.Shader = shader; tNode.Time = time; + tNode.Shared = trailDrawNodeSharedData; } public CursorTrail() @@ -87,7 +106,7 @@ namespace osu.Game.Graphics.Cursor { base.Update(); - Invalidate(Invalidation.DrawNode); + Invalidate(Invalidation.DrawNode, shallPropagate: false); int fadeClockResetThreshold = 1000000; @@ -140,15 +159,62 @@ namespace osu.Game.Graphics.Cursor currentIndex = (currentIndex + 1) % MAX_SPRITES; } + public class TrailDrawNodeSharedData + { + public VertexBuffer VertexBuffer; + } + class TrailDrawNode : ContainerDrawNode { public new Shader Shader; public float Time; + public TrailDrawNodeSharedData Shared; - public override void Draw(IVertexBatch vertexBatch) + public override void Draw(Action vertexAction) { + if (Shared.VertexBuffer == null) + Shared.VertexBuffer = new QuadVertexBuffer(MAX_SPRITES, BufferUsageHint.DynamicDraw); + Shader.GetUniform("g_FadeClock").Value = Time; - base.Draw(vertexBatch); + + int updateStart = -1, updateEnd = 0; + int test = 0; + for (int i = 0; i < Children.Count; ++i) + { + TrailSpriteDrawNode tNode = Children[i] as TrailSpriteDrawNode; + if (tNode.NeedsUpdate) + { + if (updateStart == -1) + updateStart = i; + updateEnd = i + 1; + + int start = i * 4; + int end = start; + tNode.Draw(delegate (TexturedVertex2D v) + { + Shared.VertexBuffer.Vertices[end++] = v; + }); + + tNode.NeedsUpdate = false; + } + else if (updateStart != -1) + { + Shared.VertexBuffer.UpdateRange(updateStart * 4, updateEnd * 4); + updateStart = -1; + } + } + + // Update all remaining vertices that have been changed. + if (updateStart != -1) + Shared.VertexBuffer.UpdateRange(updateStart * 4, updateEnd * 4); + + SpriteDrawNode sNode = Children[0] as SpriteDrawNode; + sNode.Texture.TextureGL.Bind(); + sNode.TextureShader.Bind(); + + Shared.VertexBuffer.Draw(); + + sNode.TextureShader.Unbind(); } } } From 069a19a916cec89476fefd9b17c955d8661da5e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Sat, 26 Nov 2016 18:01:24 +0100 Subject: [PATCH 031/133] Make CursorTrail efficient and add colouring and transparency support. --- osu.Game/Graphics/Cursor/CursorTrail.cs | 149 +++++++++--------- .../Graphics/Cursor/OsuCursorContainer.cs | 7 - 2 files changed, 78 insertions(+), 78 deletions(-) diff --git a/osu.Game/Graphics/Cursor/CursorTrail.cs b/osu.Game/Graphics/Cursor/CursorTrail.cs index 82281cae1f..2263c0a884 100644 --- a/osu.Game/Graphics/Cursor/CursorTrail.cs +++ b/osu.Game/Graphics/Cursor/CursorTrail.cs @@ -1,71 +1,33 @@ //Copyright (c) 2007-2016 ppy Pty Ltd . //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Batches; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shaders; -using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Input; -using osu.Framework.MathUtils; using OpenTK; using System; using osu.Framework.Graphics.OpenGL; using osu.Framework.Graphics.OpenGL.Buffers; -using System.Collections.Concurrent; using OpenTK.Graphics.ES30; -using System.Collections.Generic; -using System.Diagnostics; +using osu.Framework.Graphics.Primitives; +using osu.Framework.Graphics.Colour; namespace osu.Game.Graphics.Cursor { - class TrailSprite : Sprite - { - private Shader shader; - public TrailSprite() - { - Origin = Anchor.Centre; - } - - protected override DrawNode CreateDrawNode() => new TrailSpriteDrawNode(); - - protected override void ApplyDrawNode(DrawNode node) - { - base.ApplyDrawNode(node); - - TrailSpriteDrawNode sNode = node as TrailSpriteDrawNode; - sNode.RoundedTextureShader = sNode.TextureShader = shader; - sNode.NeedsUpdate = true; - } - - public override bool IsVisible => true; - - [BackgroundDependencyLoader] - private void load(ShaderManager shaders, TextureStore textures) - { - shader = shaders?.Load(@"CursorTrail", FragmentShaderDescriptor.Texture); - Texture = textures.Get(@"Cursor/cursortrail"); - } - } - - class TrailSpriteDrawNode : SpriteDrawNode - { - public bool NeedsUpdate; - } - - class CursorTrail : Container + class CursorTrail : Drawable { public override bool Contains(Vector2 screenSpacePos) => true; + public override bool HandleInput => true; int currentIndex; - protected override bool CanBeFlattened => false; - Shader shader; + Texture texture; + + Vector2 size => texture.Size * Scale; private double timeOffset; @@ -74,6 +36,8 @@ namespace osu.Game.Graphics.Cursor TrailDrawNodeSharedData trailDrawNodeSharedData = new TrailDrawNodeSharedData(); const int MAX_SPRITES = 2048; + private TrailPart[] parts = new TrailPart[MAX_SPRITES]; + Vector2? lastPosition; protected override DrawNode CreateDrawNode() => new TrailDrawNode(); @@ -84,8 +48,14 @@ namespace osu.Game.Graphics.Cursor TrailDrawNode tNode = node as TrailDrawNode; tNode.Shader = shader; + tNode.Texture = texture; + tNode.Size = size; tNode.Time = time; tNode.Shared = trailDrawNodeSharedData; + + for (int i = 0; i < parts.Length; ++i) + if (parts[i].InvalidationID > tNode.Parts[i].InvalidationID) + tNode.Parts[i] = parts[i]; } public CursorTrail() @@ -93,13 +63,17 @@ namespace osu.Game.Graphics.Cursor RelativeSizeAxes = Axes.Both; for (int i = 0; i < MAX_SPRITES; i++) - AddInternal(new TrailSprite()); + { + parts[i].InvalidationID = 0; + parts[i].WasUpdated = true; + } } [BackgroundDependencyLoader] - private void load(ShaderManager shaders) + private void load(ShaderManager shaders, TextureStore textures) { shader = shaders?.Load(@"CursorTrail", FragmentShaderDescriptor.Texture); + texture = textures.Get(@"Cursor/cursortrail"); } protected override void Update() @@ -117,8 +91,11 @@ namespace osu.Game.Graphics.Cursor private void ResetTime() { - foreach (var c in Children) - c.Alpha -= time; + for (int i = 0; i < parts.Length; ++i) + { + parts[i].Time -= time; + ++parts[i].InvalidationID; + } time = 0; timeOffset = Time.Current; @@ -128,18 +105,18 @@ namespace osu.Game.Graphics.Cursor { if (lastPosition == null) { - lastPosition = state.Mouse.Position; + lastPosition = state.Mouse.NativeState.Position; return base.OnMouseMove(state); } Vector2 pos1 = lastPosition.Value; - Vector2 pos2 = state.Mouse.Position; + Vector2 pos2 = state.Mouse.NativeState.Position; Vector2 diff = pos2 - pos1; float distance = diff.Length; Vector2 direction = diff / distance; - float interval = this[0].DrawSize.X / 2; + float interval = size.X / 2; for (float d = interval; d < distance; d += interval) { @@ -152,24 +129,46 @@ namespace osu.Game.Graphics.Cursor private void addPosition(Vector2 pos) { - var s = this[currentIndex]; - s.Position = pos; - s.Alpha = time + 1f; + parts[currentIndex].Position = pos; + parts[currentIndex].Time = time; + ++parts[currentIndex].InvalidationID; currentIndex = (currentIndex + 1) % MAX_SPRITES; } - public class TrailDrawNodeSharedData + struct TrailPart + { + public Vector2 Position; + public float Time; + public long InvalidationID; + public bool WasUpdated; + } + + class TrailDrawNodeSharedData { public VertexBuffer VertexBuffer; } - class TrailDrawNode : ContainerDrawNode + class TrailDrawNode : DrawNode { - public new Shader Shader; + public Shader Shader; + public Texture Texture; + public float Time; public TrailDrawNodeSharedData Shared; + public TrailPart[] Parts = new TrailPart[MAX_SPRITES]; + public Vector2 Size; + + public TrailDrawNode() + { + for (int i = 0; i < MAX_SPRITES; i++) + { + Parts[i].InvalidationID = 0; + Parts[i].WasUpdated = false; + } + } + public override void Draw(Action vertexAction) { if (Shared.VertexBuffer == null) @@ -178,11 +177,9 @@ namespace osu.Game.Graphics.Cursor Shader.GetUniform("g_FadeClock").Value = Time; int updateStart = -1, updateEnd = 0; - int test = 0; - for (int i = 0; i < Children.Count; ++i) + for (int i = 0; i < Parts.Length; ++i) { - TrailSpriteDrawNode tNode = Children[i] as TrailSpriteDrawNode; - if (tNode.NeedsUpdate) + if (Parts[i].WasUpdated) { if (updateStart == -1) updateStart = i; @@ -190,12 +187,21 @@ namespace osu.Game.Graphics.Cursor int start = i * 4; int end = start; - tNode.Draw(delegate (TexturedVertex2D v) - { - Shared.VertexBuffer.Vertices[end++] = v; - }); - tNode.NeedsUpdate = false; + Vector2 pos = Parts[i].Position; + ColourInfo colour = DrawInfo.Colour; + colour.TopLeft.Linear.A = Parts[i].Time + colour.TopLeft.Linear.A; + colour.TopRight.Linear.A = Parts[i].Time + colour.TopRight.Linear.A; + colour.BottomLeft.Linear.A = Parts[i].Time + colour.BottomLeft.Linear.A; + colour.BottomRight.Linear.A = Parts[i].Time + colour.BottomRight.Linear.A; + + Texture.Draw( + new Quad(pos.X - Size.X / 2, pos.Y - Size.Y / 2, Size.X, Size.Y), + colour, + null, + v => Shared.VertexBuffer.Vertices[end++] = v); + + Parts[i].WasUpdated = false; } else if (updateStart != -1) { @@ -208,13 +214,14 @@ namespace osu.Game.Graphics.Cursor if (updateStart != -1) Shared.VertexBuffer.UpdateRange(updateStart * 4, updateEnd * 4); - SpriteDrawNode sNode = Children[0] as SpriteDrawNode; - sNode.Texture.TextureGL.Bind(); - sNode.TextureShader.Bind(); + base.Draw(vertexAction); + Shader.Bind(); + + Texture.TextureGL.Bind(); Shared.VertexBuffer.Draw(); - sNode.TextureShader.Unbind(); + Shader.Unbind(); } } } diff --git a/osu.Game/Graphics/Cursor/OsuCursorContainer.cs b/osu.Game/Graphics/Cursor/OsuCursorContainer.cs index bdf84e1d04..22d7af7dc8 100644 --- a/osu.Game/Graphics/Cursor/OsuCursorContainer.cs +++ b/osu.Game/Graphics/Cursor/OsuCursorContainer.cs @@ -1,22 +1,15 @@ //Copyright (c) 2007-2016 ppy Pty Ltd . //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; using OpenTK; -using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; -using osu.Framework.Graphics.OpenGL; -using osu.Framework.Graphics.OpenGL.Buffers; -using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Transformations; using osu.Framework.Input; -using OpenTK.Graphics; -using OpenTK.Graphics.ES30; namespace osu.Game.Graphics.Cursor { From 2b9cb83aa2ba37af108da773e6a7ed4ea9486d6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Sat, 26 Nov 2016 18:35:59 +0100 Subject: [PATCH 032/133] Update framework. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index c0157172ef..24af3b161d 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit c0157172ef277b5c2fa1039be9ea895fa27ae20a +Subproject commit 24af3b161da9447b678edd8ec32193df54f71e3b From e9343fe53dd6ffc1b81bbcf7c9f80b596307083c Mon Sep 17 00:00:00 2001 From: stanriders Date: Sun, 27 Nov 2016 04:21:12 +0300 Subject: [PATCH 033/133] Add stable-alike BackButton --- osu-framework | 2 +- osu.Game/Graphics/UserInterface/BackButton.cs | 84 +++++++++++++++++++ osu.Game/Screens/GameModeWhiteBox.cs | 11 ++- osu.Game/Screens/Select/PlaySongSelect.cs | 7 ++ osu.Game/osu.Game.csproj | 1 + 5 files changed, 98 insertions(+), 7 deletions(-) create mode 100644 osu.Game/Graphics/UserInterface/BackButton.cs diff --git a/osu-framework b/osu-framework index 24af3b161d..ea56eab4a2 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 24af3b161da9447b678edd8ec32193df54f71e3b +Subproject commit ea56eab4a2bb4c9723052586ed30c687898fecb0 diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs new file mode 100644 index 0000000000..f4190f3894 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -0,0 +1,84 @@ +// Copyright (c) 2007-2016 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using OpenTK; +using OpenTK.Graphics; +using osu.Framework.Graphics; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Graphics.Transformations; +using osu.Framework.Input; + +namespace osu.Game.Graphics.UserInterface +{ + // Basic back button as it was on stable (kinda). No skinning possible for now + class BackButton : ExtendableButton + { + private TextAwesome icon; + private Vector2 iconPos = new Vector2(20, 0); + + public BackButton() + { + InitialExtendLenght = new Vector2(40, 0); + ExtendLenght = new Vector2(60, 0); + + RelativeSizeAxes = Axes.Y; + Width = 80; + //Height = 40; // should be set or should be relative? + + Text = @"Back"; + + BGColour = new Color4(195, 40, 140, 255); + Colour = new Color4(238, 51, 153, 255); + + Children = new Drawable[] + { + icon = new TextAwesome + { + Anchor = Anchor.CentreLeft, + TextSize = 25, + Position = iconPos, + Icon = FontAwesome.fa_osu_left_o + } + }; + + // HACK: because it never uses InitialExtendLenght that we give to it on creation + textContainer.Position = Position + InitialExtendLenght; + } + protected override bool OnHover(InputState state) + { + bool result = base.OnHover(state); + + icon.ClearTransformations(); + + icon.MoveToX(iconPos.X + 10, 150, EasingTypes.OutElastic); + + int duration = 0; //(int)(Game.Audio.BeatLength / 2); + if (duration == 0) duration = 250; + + double offset = 0; //(1 - Game.Audio.SyncBeatProgress) * duration; + double startTime = Time.Current + offset; + + // basic pulse + icon.Transforms.Add(new TransformScale + { + StartValue = new Vector2(1.1f, 1.1f), + EndValue = Vector2.One, + StartTime = startTime, + EndTime = startTime + duration, + Easing = EasingTypes.Out, + LoopCount = -1, + LoopDelay = duration + }); + + return result; + } + + protected override void OnHoverLost(InputState state) + { + icon.ClearTransformations(); + icon.MoveToX(iconPos.X, 150, EasingTypes.OutElastic); + + base.OnHoverLost(state); + } + } +} diff --git a/osu.Game/Screens/GameModeWhiteBox.cs b/osu.Game/Screens/GameModeWhiteBox.cs index ac6cc5ece3..ef85f9e23e 100644 --- a/osu.Game/Screens/GameModeWhiteBox.cs +++ b/osu.Game/Screens/GameModeWhiteBox.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Transformations; using osu.Framework.Graphics.UserInterface; using osu.Game.Screens.Backgrounds; +using osu.Game.Graphics.UserInterface; using OpenTK; using OpenTK.Graphics; @@ -17,7 +18,7 @@ namespace osu.Game.Screens { public class GameModeWhiteBox : OsuGameMode { - private Button popButton; + private BackButton popButton; const int transition_time = 1000; @@ -113,14 +114,12 @@ namespace osu.Game.Screens }, } }, - popButton = new Button + popButton = new BackButton { - Text = @"Back", - RelativeSizeAxes = Axes.X, - Size = new Vector2(0.1f, 40), + RelativeSizeAxes = Axes.None, + Height = 40, Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - Colour = new Color4(235, 51, 153, 255), Alpha = 0, Action = delegate { Exit(); diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 8c8ff39fba..9688b36a99 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -19,6 +19,7 @@ using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Modes; using osu.Game.Screens.Backgrounds; +using osu.Game.Graphics.UserInterface; using OpenTK; using OpenTK.Graphics; using osu.Game.Screens.Play; @@ -120,6 +121,12 @@ namespace osu.Game.Screens.Select Size = Vector2.One, Colour = new Color4(0, 0, 0, 0.5f), }, + new BackButton + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Action = () => Exit() + }, new Button { Anchor = Anchor.CentreRight, diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index c35bafb251..f1bdd47b68 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -65,6 +65,7 @@ + From af57984d5c808ff667998d01a3dd42e69c9a8cb1 Mon Sep 17 00:00:00 2001 From: stanriders Date: Sun, 27 Nov 2016 04:41:17 +0300 Subject: [PATCH 034/133] Moved ExtendableButton out of framework --- osu.Game/Graphics/UserInterface/BackButton.cs | 1 - .../UserInterface/ExtendableButton.cs | 117 ++++++++++++++++++ osu.Game/osu.Game.csproj | 1 + 3 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Graphics/UserInterface/ExtendableButton.cs diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index f4190f3894..b42cb7fc4a 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -4,7 +4,6 @@ using OpenTK; using OpenTK.Graphics; using osu.Framework.Graphics; -using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics.Transformations; using osu.Framework.Input; diff --git a/osu.Game/Graphics/UserInterface/ExtendableButton.cs b/osu.Game/Graphics/UserInterface/ExtendableButton.cs new file mode 100644 index 0000000000..4b1b08cd7c --- /dev/null +++ b/osu.Game/Graphics/UserInterface/ExtendableButton.cs @@ -0,0 +1,117 @@ +// Copyright (c) 2007-2016 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using osu.Framework.Input; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Transformations; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Graphics.UserInterface +{ + public class ExtendableButton : ClickableContainer + { + public Color4 BGColour + { + get { return bgBox.Colour; } + set { bgBox.Colour = value; } + } + public new Color4 Colour + { + get { return textBox.Colour; } + set { textBox.Colour = value; } + } + public new Vector2 Shear + { + get { return textBox.Shear; } + set { textBox.Shear = value; } + } + public string Text + { + get { return spriteText?.Text; } + set + { + if (spriteText != null) + spriteText.Text = value; + } + } + + private Box bgBox; + private Box textBox; + public Container textContainer; + private SpriteText spriteText; + + public Vector2 ExtendLenght = new Vector2(80,0); // this one can be defaulted + public Vector2 InitialExtendLenght/* = new Vector2(40, 0)*/; // but this one unfortunately cant + + public ExtendableButton(float initialExtendLenghtX = 20, float initialExtendLenghtY = 0) + { + InitialExtendLenght = new Vector2(initialExtendLenghtX, initialExtendLenghtY); // because it just wont use defined settings when creating + + Children = new Drawable[] + { + bgBox = new Box + { + RelativeSizeAxes = Axes.Both, + }, + textContainer = new Container + { + Origin = Anchor.TopLeft, + Anchor = Anchor.TopLeft, + RelativeSizeAxes = Axes.Both, + Position = Position + InitialExtendLenght, + Children = new Drawable[] + { + textBox = new Box + { + Origin = Anchor.TopLeft, + Anchor = Anchor.TopLeft, + RelativeSizeAxes = Axes.Both, + Shear = new Vector2(0.1f, 0), // should be relative? + EdgeSmoothness = new Vector2(1, 1), // should be based on which side is being cut? + }, + spriteText = new SpriteText + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + } + } + } + }; + } + + protected override bool OnHover(InputState state) + { + textContainer.ClearTransformations(); + textContainer.MoveTo(Position + ExtendLenght, 150, EasingTypes.OutElastic); + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + base.OnHoverLost(state); + textContainer.ClearTransformations(); + textContainer.MoveTo(Position + InitialExtendLenght, 150, EasingTypes.OutElastic); + } + + protected override bool OnClick(InputState state) + { + var flash = new Box + { + RelativeSizeAxes = Axes.Both + }; + + Add(flash); + + flash.Colour = textBox.Colour; + flash.BlendingMode = BlendingMode.Additive; + flash.Alpha = 0.3f; + flash.FadeOutFromOne(200); + flash.Expire(); + + return base.OnClick(state); + } + } +} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index f1bdd47b68..ed7e83e0eb 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -66,6 +66,7 @@ + From ba18c9a3093cc6daed8d41f4a9e152961da9a56d Mon Sep 17 00:00:00 2001 From: stanriders Date: Sun, 27 Nov 2016 05:48:31 +0300 Subject: [PATCH 035/133] Merged ExtendableButton and BackButton --- osu-framework | 2 +- osu.Game/Graphics/UserInterface/BackButton.cs | 96 +++++++++++--- .../UserInterface/ExtendableButton.cs | 117 ------------------ osu.Game/Screens/Select/PlaySongSelect.cs | 5 +- osu.Game/osu.Game.csproj | 1 - 5 files changed, 81 insertions(+), 140 deletions(-) delete mode 100644 osu.Game/Graphics/UserInterface/ExtendableButton.cs diff --git a/osu-framework b/osu-framework index ea56eab4a2..24af3b161d 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit ea56eab4a2bb4c9723052586ed30c687898fecb0 +Subproject commit 24af3b161da9447b678edd8ec32193df54f71e3b diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index b42cb7fc4a..0cf442ff39 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -4,52 +4,91 @@ using OpenTK; using OpenTK.Graphics; using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Transformations; using osu.Framework.Input; namespace osu.Game.Graphics.UserInterface { // Basic back button as it was on stable (kinda). No skinning possible for now - class BackButton : ExtendableButton + class BackButton : ClickableContainer { private TextAwesome icon; - private Vector2 iconPos = new Vector2(20, 0); + private Vector2 iconPos; + + private Box bgBox; + private Box textBox; + private Container textContainer; + private SpriteText spriteText; + + public Vector2 ExtendLength; + public Vector2 InitialExtendLength; + + private const double transformTime = 300.0; public BackButton() { - InitialExtendLenght = new Vector2(40, 0); - ExtendLenght = new Vector2(60, 0); + // [ should be set or should be relative? + InitialExtendLength = new Vector2(40, 0); + ExtendLength = new Vector2(60, 0); + iconPos = new Vector2(20, 0); - RelativeSizeAxes = Axes.Y; Width = 80; - //Height = 40; // should be set or should be relative? - - Text = @"Back"; - - BGColour = new Color4(195, 40, 140, 255); - Colour = new Color4(238, 51, 153, 255); + //Height = 40; + // ] should be set or should be relative? Children = new Drawable[] { + bgBox = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = new Color4(195, 40, 140, 255), + }, icon = new TextAwesome { Anchor = Anchor.CentreLeft, TextSize = 25, Position = iconPos, Icon = FontAwesome.fa_osu_left_o + }, + textContainer = new Container + { + Origin = Anchor.TopLeft, + Anchor = Anchor.TopLeft, + RelativeSizeAxes = Axes.Both, + Position = Position + InitialExtendLength, + Children = new Drawable[] + { + textBox = new Box + { + Colour = new Color4(238, 51, 153, 255), + Origin = Anchor.TopLeft, + Anchor = Anchor.TopLeft, + RelativeSizeAxes = Axes.Both, + Shear = new Vector2(0.1f, 0), + EdgeSmoothness = new Vector2(1.5f, 0), + }, + spriteText = new SpriteText + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Text = @"Back", + } + } } }; - // HACK: because it never uses InitialExtendLenght that we give to it on creation - textContainer.Position = Position + InitialExtendLenght; + // HACK: because it never uses InitialExtendLength that we give to it on creation + textContainer.Position = Position + InitialExtendLength; } protected override bool OnHover(InputState state) { - bool result = base.OnHover(state); - icon.ClearTransformations(); + textContainer.ClearTransformations(); - icon.MoveToX(iconPos.X + 10, 150, EasingTypes.OutElastic); + textContainer.MoveTo(Position + ExtendLength, transformTime, EasingTypes.OutElastic); + icon.MoveToX(iconPos.X + 10, transformTime, EasingTypes.OutElastic); int duration = 0; //(int)(Game.Audio.BeatLength / 2); if (duration == 0) duration = 250; @@ -69,15 +108,34 @@ namespace osu.Game.Graphics.UserInterface LoopDelay = duration }); - return result; + return true; } protected override void OnHoverLost(InputState state) { icon.ClearTransformations(); - icon.MoveToX(iconPos.X, 150, EasingTypes.OutElastic); + textContainer.ClearTransformations(); - base.OnHoverLost(state); + textContainer.MoveTo(Position + InitialExtendLength, transformTime, EasingTypes.OutElastic); + icon.MoveToX(iconPos.X, transformTime, EasingTypes.OutElastic); + } + + protected override bool OnClick(InputState state) + { + var flash = new Box + { + RelativeSizeAxes = RelativeSizeAxes + }; + + Add(flash); + + flash.Colour = textBox.Colour; + flash.BlendingMode = BlendingMode.Additive; + flash.Alpha = 0.3f; + flash.FadeOutFromOne(200); + flash.Expire(); + + return base.OnClick(state); } } } diff --git a/osu.Game/Graphics/UserInterface/ExtendableButton.cs b/osu.Game/Graphics/UserInterface/ExtendableButton.cs deleted file mode 100644 index 4b1b08cd7c..0000000000 --- a/osu.Game/Graphics/UserInterface/ExtendableButton.cs +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) 2007-2016 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE - -using osu.Framework.Input; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Transformations; -using OpenTK; -using OpenTK.Graphics; - -namespace osu.Game.Graphics.UserInterface -{ - public class ExtendableButton : ClickableContainer - { - public Color4 BGColour - { - get { return bgBox.Colour; } - set { bgBox.Colour = value; } - } - public new Color4 Colour - { - get { return textBox.Colour; } - set { textBox.Colour = value; } - } - public new Vector2 Shear - { - get { return textBox.Shear; } - set { textBox.Shear = value; } - } - public string Text - { - get { return spriteText?.Text; } - set - { - if (spriteText != null) - spriteText.Text = value; - } - } - - private Box bgBox; - private Box textBox; - public Container textContainer; - private SpriteText spriteText; - - public Vector2 ExtendLenght = new Vector2(80,0); // this one can be defaulted - public Vector2 InitialExtendLenght/* = new Vector2(40, 0)*/; // but this one unfortunately cant - - public ExtendableButton(float initialExtendLenghtX = 20, float initialExtendLenghtY = 0) - { - InitialExtendLenght = new Vector2(initialExtendLenghtX, initialExtendLenghtY); // because it just wont use defined settings when creating - - Children = new Drawable[] - { - bgBox = new Box - { - RelativeSizeAxes = Axes.Both, - }, - textContainer = new Container - { - Origin = Anchor.TopLeft, - Anchor = Anchor.TopLeft, - RelativeSizeAxes = Axes.Both, - Position = Position + InitialExtendLenght, - Children = new Drawable[] - { - textBox = new Box - { - Origin = Anchor.TopLeft, - Anchor = Anchor.TopLeft, - RelativeSizeAxes = Axes.Both, - Shear = new Vector2(0.1f, 0), // should be relative? - EdgeSmoothness = new Vector2(1, 1), // should be based on which side is being cut? - }, - spriteText = new SpriteText - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - } - } - } - }; - } - - protected override bool OnHover(InputState state) - { - textContainer.ClearTransformations(); - textContainer.MoveTo(Position + ExtendLenght, 150, EasingTypes.OutElastic); - return base.OnHover(state); - } - - protected override void OnHoverLost(InputState state) - { - base.OnHoverLost(state); - textContainer.ClearTransformations(); - textContainer.MoveTo(Position + InitialExtendLenght, 150, EasingTypes.OutElastic); - } - - protected override bool OnClick(InputState state) - { - var flash = new Box - { - RelativeSizeAxes = Axes.Both - }; - - Add(flash); - - flash.Colour = textBox.Colour; - flash.BlendingMode = BlendingMode.Additive; - flash.Alpha = 0.3f; - flash.FadeOutFromOne(200); - flash.Expire(); - - return base.OnClick(state); - } - } -} diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 9688b36a99..66f6e9c2d8 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -123,8 +123,9 @@ namespace osu.Game.Screens.Select }, new BackButton { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.Y, Action = () => Exit() }, new Button diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index ed7e83e0eb..f1bdd47b68 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -66,7 +66,6 @@ - From 88ead18929566718b9ec6c6973f2987afc223e35 Mon Sep 17 00:00:00 2001 From: stanriders Date: Sun, 27 Nov 2016 06:50:36 +0300 Subject: [PATCH 036/133] Backbutton improvements --- osu.Game/Graphics/UserInterface/BackButton.cs | 56 ++++++++++--------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index 0cf442ff39..f757d61aa8 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -15,12 +15,10 @@ namespace osu.Game.Graphics.UserInterface class BackButton : ClickableContainer { private TextAwesome icon; - private Vector2 iconPos; - private Box bgBox; + private Container leftContainer; + private Container rightContainer; private Box textBox; - private Container textContainer; - private SpriteText spriteText; public Vector2 ExtendLength; public Vector2 InitialExtendLength; @@ -32,7 +30,6 @@ namespace osu.Game.Graphics.UserInterface // [ should be set or should be relative? InitialExtendLength = new Vector2(40, 0); ExtendLength = new Vector2(60, 0); - iconPos = new Vector2(20, 0); Width = 80; //Height = 40; @@ -40,19 +37,27 @@ namespace osu.Game.Graphics.UserInterface Children = new Drawable[] { - bgBox = new Box + leftContainer = new Container { - RelativeSizeAxes = Axes.Both, - Colour = new Color4(195, 40, 140, 255), + RelativeSizeAxes = Axes.Y, + Width = InitialExtendLength.X, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = new Color4(195, 40, 140, 255), + Shear = new Vector2(0.1f, 0), + }, + icon = new TextAwesome + { + Anchor = Anchor.Centre, + TextSize = 25, + Icon = FontAwesome.fa_osu_left_o + }, + } }, - icon = new TextAwesome - { - Anchor = Anchor.CentreLeft, - TextSize = 25, - Position = iconPos, - Icon = FontAwesome.fa_osu_left_o - }, - textContainer = new Container + rightContainer = new Container { Origin = Anchor.TopLeft, Anchor = Anchor.TopLeft, @@ -69,7 +74,7 @@ namespace osu.Game.Graphics.UserInterface Shear = new Vector2(0.1f, 0), EdgeSmoothness = new Vector2(1.5f, 0), }, - spriteText = new SpriteText + new SpriteText { Origin = Anchor.Centre, Anchor = Anchor.Centre, @@ -78,17 +83,15 @@ namespace osu.Game.Graphics.UserInterface } } }; - - // HACK: because it never uses InitialExtendLength that we give to it on creation - textContainer.Position = Position + InitialExtendLength; } protected override bool OnHover(InputState state) { icon.ClearTransformations(); - textContainer.ClearTransformations(); + rightContainer.ClearTransformations(); + leftContainer.ClearTransformations(); - textContainer.MoveTo(Position + ExtendLength, transformTime, EasingTypes.OutElastic); - icon.MoveToX(iconPos.X + 10, transformTime, EasingTypes.OutElastic); + rightContainer.MoveTo(Position + ExtendLength, transformTime, EasingTypes.OutElastic); + leftContainer.ResizeTo(new Vector2(ExtendLength.X, 1.0f), transformTime, EasingTypes.OutElastic); int duration = 0; //(int)(Game.Audio.BeatLength / 2); if (duration == 0) duration = 250; @@ -114,10 +117,11 @@ namespace osu.Game.Graphics.UserInterface protected override void OnHoverLost(InputState state) { icon.ClearTransformations(); - textContainer.ClearTransformations(); + rightContainer.ClearTransformations(); + leftContainer.ClearTransformations(); - textContainer.MoveTo(Position + InitialExtendLength, transformTime, EasingTypes.OutElastic); - icon.MoveToX(iconPos.X, transformTime, EasingTypes.OutElastic); + rightContainer.MoveTo(Position + InitialExtendLength, transformTime, EasingTypes.OutElastic); + leftContainer.ResizeTo(new Vector2(InitialExtendLength.X, 1.0f), transformTime, EasingTypes.OutElastic); } protected override bool OnClick(InputState state) From a3ceef48a6db3e91c4630acd0331217a066c0b78 Mon Sep 17 00:00:00 2001 From: stanriders Date: Sun, 27 Nov 2016 07:06:50 +0300 Subject: [PATCH 037/133] More backbutton --- osu.Game/Graphics/UserInterface/BackButton.cs | 45 ++++++++++++------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index f757d61aa8..35d07fdc6a 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -18,12 +18,14 @@ namespace osu.Game.Graphics.UserInterface private Container leftContainer; private Container rightContainer; - private Box textBox; public Vector2 ExtendLength; public Vector2 InitialExtendLength; + private Color4 colorBright = new Color4(238, 51, 153, 255); + private Color4 colorDark = new Color4(195, 40, 140, 255); private const double transformTime = 300.0; + private const int pulseLength = 250; // FIXME: remove when bpm-based pulsing will be possible public BackButton() { @@ -46,7 +48,7 @@ namespace osu.Game.Graphics.UserInterface new Box { RelativeSizeAxes = Axes.Both, - Colour = new Color4(195, 40, 140, 255), + Colour = colorDark, Shear = new Vector2(0.1f, 0), }, icon = new TextAwesome @@ -65,9 +67,9 @@ namespace osu.Game.Graphics.UserInterface Position = Position + InitialExtendLength, Children = new Drawable[] { - textBox = new Box + new Box { - Colour = new Color4(238, 51, 153, 255), + Colour = colorBright, Origin = Anchor.TopLeft, Anchor = Anchor.TopLeft, RelativeSizeAxes = Axes.Both, @@ -87,14 +89,12 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnHover(InputState state) { icon.ClearTransformations(); - rightContainer.ClearTransformations(); - leftContainer.ClearTransformations(); rightContainer.MoveTo(Position + ExtendLength, transformTime, EasingTypes.OutElastic); leftContainer.ResizeTo(new Vector2(ExtendLength.X, 1.0f), transformTime, EasingTypes.OutElastic); int duration = 0; //(int)(Game.Audio.BeatLength / 2); - if (duration == 0) duration = 250; + if (duration == 0) duration = pulseLength; double offset = 0; //(1 - Game.Audio.SyncBeatProgress) * duration; double startTime = Time.Current + offset; @@ -102,7 +102,7 @@ namespace osu.Game.Graphics.UserInterface // basic pulse icon.Transforms.Add(new TransformScale { - StartValue = new Vector2(1.1f, 1.1f), + StartValue = new Vector2(1.1f), EndValue = Vector2.One, StartTime = startTime, EndTime = startTime + duration, @@ -117,25 +117,40 @@ namespace osu.Game.Graphics.UserInterface protected override void OnHoverLost(InputState state) { icon.ClearTransformations(); - rightContainer.ClearTransformations(); - leftContainer.ClearTransformations(); rightContainer.MoveTo(Position + InitialExtendLength, transformTime, EasingTypes.OutElastic); leftContainer.ResizeTo(new Vector2(InitialExtendLength.X, 1.0f), transformTime, EasingTypes.OutElastic); + + int duration = 0; //(int)(Game.Audio.BeatLength / 2); + if (duration == 0) duration = pulseLength * 2; + + double offset = 0; //(1 - Game.Audio.SyncBeatProgress) * duration; + double startTime = Time.Current + offset; + + // slow pulse + icon.Transforms.Add(new TransformScale + { + StartValue = new Vector2(1.1f), + EndValue = Vector2.One, + StartTime = startTime, + EndTime = startTime + duration, + Easing = EasingTypes.Out, + LoopCount = -1, + LoopDelay = duration + }); } protected override bool OnClick(InputState state) { var flash = new Box { - RelativeSizeAxes = RelativeSizeAxes + RelativeSizeAxes = RelativeSizeAxes, + Colour = colorBright, + BlendingMode = BlendingMode.Additive, + Alpha = 0.3f }; - Add(flash); - flash.Colour = textBox.Colour; - flash.BlendingMode = BlendingMode.Additive; - flash.Alpha = 0.3f; flash.FadeOutFromOne(200); flash.Expire(); From fb3d5a3b7904cd1a8e1a6b4516bb44d0da1b048e Mon Sep 17 00:00:00 2001 From: stanriders Date: Sun, 27 Nov 2016 07:18:56 +0300 Subject: [PATCH 038/133] One more --- osu.Game/Graphics/UserInterface/BackButton.cs | 27 +++++++------------ 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index 35d07fdc6a..7cba17bf91 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -19,24 +19,17 @@ namespace osu.Game.Graphics.UserInterface private Container leftContainer; private Container rightContainer; - public Vector2 ExtendLength; - public Vector2 InitialExtendLength; + public Vector2 ExtendLength = new Vector2(60, 0); + public Vector2 InitialExtendLength = new Vector2(40, 0); private Color4 colorBright = new Color4(238, 51, 153, 255); private Color4 colorDark = new Color4(195, 40, 140, 255); - private const double transformTime = 300.0; - private const int pulseLength = 250; // FIXME: remove when bpm-based pulsing will be possible + private const double transform_time = 300.0; + private const int pulse_length = 250; public BackButton() { - // [ should be set or should be relative? - InitialExtendLength = new Vector2(40, 0); - ExtendLength = new Vector2(60, 0); - Width = 80; - //Height = 40; - // ] should be set or should be relative? - Children = new Drawable[] { leftContainer = new Container @@ -90,11 +83,11 @@ namespace osu.Game.Graphics.UserInterface { icon.ClearTransformations(); - rightContainer.MoveTo(Position + ExtendLength, transformTime, EasingTypes.OutElastic); - leftContainer.ResizeTo(new Vector2(ExtendLength.X, 1.0f), transformTime, EasingTypes.OutElastic); + rightContainer.MoveTo(Position + ExtendLength, transform_time, EasingTypes.OutElastic); + leftContainer.ResizeTo(new Vector2(ExtendLength.X, 1.0f), transform_time, EasingTypes.OutElastic); int duration = 0; //(int)(Game.Audio.BeatLength / 2); - if (duration == 0) duration = pulseLength; + if (duration == 0) duration = pulse_length; double offset = 0; //(1 - Game.Audio.SyncBeatProgress) * duration; double startTime = Time.Current + offset; @@ -118,11 +111,11 @@ namespace osu.Game.Graphics.UserInterface { icon.ClearTransformations(); - rightContainer.MoveTo(Position + InitialExtendLength, transformTime, EasingTypes.OutElastic); - leftContainer.ResizeTo(new Vector2(InitialExtendLength.X, 1.0f), transformTime, EasingTypes.OutElastic); + rightContainer.MoveTo(Position + InitialExtendLength, transform_time, EasingTypes.OutElastic); + leftContainer.ResizeTo(new Vector2(InitialExtendLength.X, 1.0f), transform_time, EasingTypes.OutElastic); int duration = 0; //(int)(Game.Audio.BeatLength / 2); - if (duration == 0) duration = pulseLength * 2; + if (duration == 0) duration = pulse_length * 2; double offset = 0; //(1 - Game.Audio.SyncBeatProgress) * duration; double startTime = Time.Current + offset; From 724f849543349f2f6452a834e09721986eca984e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Sun, 27 Nov 2016 11:49:51 +0100 Subject: [PATCH 039/133] Fix incorrect BeatmapPanel border caused by triangles. --- osu-framework | 2 +- osu.Game/Beatmaps/Drawables/BeatmapPanel.cs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 24af3b161d..744ed65bbc 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 24af3b161da9447b678edd8ec32193df54f71e3b +Subproject commit 744ed65bbc3b2ca96135abecddad2d069a1fe817 diff --git a/osu.Game/Beatmaps/Drawables/BeatmapPanel.cs b/osu.Game/Beatmaps/Drawables/BeatmapPanel.cs index 0062ddf0e1..99ba31ab6a 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapPanel.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapPanel.cs @@ -57,6 +57,10 @@ namespace osu.Game.Beatmaps.Drawables }, new Triangles { + // The border is drawn in the shader of the children. Being additive, triangles would over-emphasize + // the border wherever they cross it, and thus they get their own masking container without a border. + Masking = true, + CornerRadius = Content.CornerRadius, RelativeSizeAxes = Axes.Both, BlendingMode = BlendingMode.Additive, Colour = deselectedColour, From bd872f6ab812c86b6f41bb91935f357acbff8961 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Sun, 27 Nov 2016 15:04:56 +0100 Subject: [PATCH 040/133] Explicitly make various member variabled of CursorTrail private. --- osu.Game/Graphics/Cursor/CursorTrail.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Graphics/Cursor/CursorTrail.cs b/osu.Game/Graphics/Cursor/CursorTrail.cs index 2263c0a884..2fcc11d5ae 100644 --- a/osu.Game/Graphics/Cursor/CursorTrail.cs +++ b/osu.Game/Graphics/Cursor/CursorTrail.cs @@ -22,23 +22,23 @@ namespace osu.Game.Graphics.Cursor public override bool Contains(Vector2 screenSpacePos) => true; public override bool HandleInput => true; - int currentIndex; + private int currentIndex; - Shader shader; - Texture texture; + private Shader shader; + private Texture texture; - Vector2 size => texture.Size * Scale; + private Vector2 size => texture.Size * Scale; private double timeOffset; private float time; - TrailDrawNodeSharedData trailDrawNodeSharedData = new TrailDrawNodeSharedData(); - const int MAX_SPRITES = 2048; + private TrailDrawNodeSharedData trailDrawNodeSharedData = new TrailDrawNodeSharedData(); + private const int MAX_SPRITES = 2048; private TrailPart[] parts = new TrailPart[MAX_SPRITES]; - Vector2? lastPosition; + private Vector2? lastPosition; protected override DrawNode CreateDrawNode() => new TrailDrawNode(); From 0cd0c4564f1c56331a2957dc34e5e129cf1c820a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Sun, 27 Nov 2016 15:36:31 +0100 Subject: [PATCH 041/133] Make sliders slightly nicer by using the new path drawable. --- osu-framework | 2 +- .../Objects/Drawables/DrawableHitCircle.cs | 2 +- .../Objects/Drawables/DrawableSlider.cs | 24 +++++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/osu-framework b/osu-framework index 24af3b161d..e4be270dd0 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 24af3b161da9447b678edd8ec32193df54f71e3b +Subproject commit e4be270dd0bc83fea058351eface27f4128d7121 diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs index dc5d5bf2a6..8bead0fe53 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -24,7 +24,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables private GlowPiece glow; private HitExplosion explosion; - public DrawableHitCircle(HitCircle h) : base(h) + public DrawableHitCircle(OsuHitObject h) : base(h) { osuObject = h; diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index 55e4781cd3..f779f9948f 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -2,6 +2,7 @@ using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Osu.Objects.Drawables.Pieces; using OpenTK; +using osu.Framework.Graphics.Sprites; namespace osu.Game.Modes.Osu.Objects.Drawables { @@ -10,17 +11,16 @@ namespace osu.Game.Modes.Osu.Objects.Drawables public DrawableSlider(Slider h) : base(h) { Origin = Anchor.Centre; - RelativePositionAxes = Axes.Both; - Position = new Vector2(h.Position.X / 512, h.Position.Y / 384); + Position = new Vector2(h.Position.X, h.Position.Y); - for (float i = 0; i <= 1; i += 0.1f) - { - Add(new CirclePiece - { - Colour = h.Colour, - Position = h.Curve.PositionAt(i) - h.Position //non-relative? - }); - } + Path sliderPath; + Add(sliderPath = new Path()); + + for (int i = 0; i < h.Curve.Path.Count; ++i) + sliderPath.Positions.Add(h.Curve.Path[i] - h.Position); + + h.Position = Vector2.Zero; + Add(new DrawableHitCircle(h)); } protected override void LoadComplete() @@ -39,10 +39,10 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Alpha = 0; - Delay(HitObject.StartTime - 200 - Time.Current, true); + Delay(HitObject.StartTime - 450 - Time.Current, true); FadeIn(200); - Delay(200 + HitObject.Duration); + Delay(450 + HitObject.Duration); FadeOut(200); } } From 775e8ac5d6491ee79c895a4de295ebf6c2b0c9da Mon Sep 17 00:00:00 2001 From: stanriders Date: Sun, 27 Nov 2016 18:56:05 +0300 Subject: [PATCH 042/133] Hardcoded button size, fixed input handling, fixed flash not being visible --- osu.Game/Graphics/UserInterface/BackButton.cs | 20 +++++++++++++++---- osu.Game/Screens/GameModeWhiteBox.cs | 2 -- osu.Game/Screens/Select/PlaySongSelect.cs | 2 +- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index 7cba17bf91..06aa21f2b0 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -29,7 +29,10 @@ namespace osu.Game.Graphics.UserInterface public BackButton() { - Width = 80; + RelativeSizeAxes = Axes.None; + Width = 120; + Height = 50; // same as bottomToolHeight in PlaySongSelect + Children = new Drawable[] { leftContainer = new Container @@ -56,7 +59,8 @@ namespace osu.Game.Graphics.UserInterface { Origin = Anchor.TopLeft, Anchor = Anchor.TopLeft, - RelativeSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.Y, + Width = 80, Position = Position + InitialExtendLength, Children = new Drawable[] { @@ -86,6 +90,8 @@ namespace osu.Game.Graphics.UserInterface rightContainer.MoveTo(Position + ExtendLength, transform_time, EasingTypes.OutElastic); leftContainer.ResizeTo(new Vector2(ExtendLength.X, 1.0f), transform_time, EasingTypes.OutElastic); + Width = 140; // right container + ExtendLength + int duration = 0; //(int)(Game.Audio.BeatLength / 2); if (duration == 0) duration = pulse_length; @@ -114,6 +120,8 @@ namespace osu.Game.Graphics.UserInterface rightContainer.MoveTo(Position + InitialExtendLength, transform_time, EasingTypes.OutElastic); leftContainer.ResizeTo(new Vector2(InitialExtendLength.X, 1.0f), transform_time, EasingTypes.OutElastic); + Width = 120; // right container + InitialExtendLength + int duration = 0; //(int)(Game.Audio.BeatLength / 2); if (duration == 0) duration = pulse_length * 2; @@ -137,13 +145,17 @@ namespace osu.Game.Graphics.UserInterface { var flash = new Box { - RelativeSizeAxes = RelativeSizeAxes, - Colour = colorBright, + RelativeSizeAxes = Axes.None, + Width = 140, + Height = 50, + Shear = new Vector2(0.1f, 0), + Colour = new Color4(255,255,255,255), BlendingMode = BlendingMode.Additive, Alpha = 0.3f }; Add(flash); + flash.ResizeTo(new Vector2(120, 50), transform_time, EasingTypes.OutElastic); flash.FadeOutFromOne(200); flash.Expire(); diff --git a/osu.Game/Screens/GameModeWhiteBox.cs b/osu.Game/Screens/GameModeWhiteBox.cs index ef85f9e23e..b05ac614c6 100644 --- a/osu.Game/Screens/GameModeWhiteBox.cs +++ b/osu.Game/Screens/GameModeWhiteBox.cs @@ -116,8 +116,6 @@ namespace osu.Game.Screens }, popButton = new BackButton { - RelativeSizeAxes = Axes.None, - Height = 40, Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Alpha = 0, diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 66f6e9c2d8..983d5008df 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -125,7 +125,7 @@ namespace osu.Game.Screens.Select { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.Y, + //RelativeSizeAxes = Axes.Y, Action = () => Exit() }, new Button From 723f734e13f0c350e6f9e58eb22d78c04c6c09bb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 09:21:24 +0900 Subject: [PATCH 043/133] Framework update. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index e4be270dd0..fdea70aee3 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit e4be270dd0bc83fea058351eface27f4128d7121 +Subproject commit fdea70aee37b040d56fac5e9b27a18ed77f2bfb9 From cfb22853128acc4d4f10a4ed49e53a65ab3681f0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 11:38:32 +0900 Subject: [PATCH 044/133] TestCasePlayer uses an actual beatmap if available. --- .../Tests/TestCasePlayer.cs | 59 ++++++++++++------- 1 file changed, 38 insertions(+), 21 deletions(-) diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs index da21b38ec8..7d67e5aad3 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs @@ -2,6 +2,7 @@ //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using osu.Framework.Allocation; using osu.Framework.GameModes.Testing; using osu.Framework.MathUtils; using osu.Framework.Timing; @@ -9,6 +10,8 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; using OpenTK; using osu.Framework.Graphics.Sprites; +using osu.Game.Database; +using osu.Game.Modes; using osu.Game.Modes.Objects; using osu.Game.Modes.Osu.Objects; using osu.Game.Screens.Play; @@ -18,10 +21,17 @@ namespace osu.Desktop.VisualTests.Tests { class TestCasePlayer : TestCase { + private WorkingBeatmap beatmap; public override string Name => @"Player"; public override string Description => @"Showing everything to play the game."; + [BackgroundDependencyLoader] + private void load(BeatmapDatabase db) + { + beatmap = db?.GetWorkingBeatmap(db.Query().Where(b => b.Mode == PlayMode.Osu).FirstOrDefault()); + } + public override void Reset() { base.Reset(); @@ -29,31 +39,37 @@ namespace osu.Desktop.VisualTests.Tests //ensure we are at offset 0 Clock = new FramedClock(); - var objects = new List(); - - int time = 1500; - for (int i = 0; i < 50; i++) + if (beatmap == null) { - objects.Add(new HitCircle() + + var objects = new List(); + + int time = 1500; + for (int i = 0; i < 50; i++) { - StartTime = time, - Position = new Vector2(i % 4 == 0 || i % 4 == 2 ? 0 : 512, - i % 4 < 2 ? 0 : 384), - NewCombo = i % 4 == 0 - }); + objects.Add(new HitCircle() + { + StartTime = time, + Position = new Vector2(i % 4 == 0 || i % 4 == 2 ? 0 : 512, + i % 4 < 2 ? 0 : 384), + NewCombo = i % 4 == 0 + }); - time += 500; + time += 500; + } + + var decoder = new ConstructableBeatmapDecoder(); + + Beatmap b = new Beatmap + { + HitObjects = objects + }; + + decoder.Process(b); + + beatmap = new WorkingBeatmap(b); } - var decoder = new ConstructableBeatmapDecoder(); - - Beatmap b = new Beatmap - { - HitObjects = objects - }; - - decoder.Process(b); - Add(new Box { RelativeSizeAxes = Framework.Graphics.Axes.Both, @@ -62,7 +78,8 @@ namespace osu.Desktop.VisualTests.Tests Add(new Player { - Beatmap = new WorkingBeatmap(b) + PreferredPlayMode = PlayMode.Osu, + Beatmap = beatmap }); } From 97e465373579ae3b0d5b6265efb21a94f0c1ca97 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 12:15:25 +0900 Subject: [PATCH 045/133] Fix circle depth and explicitly create a hitcircle for now. --- .../Objects/Drawables/DrawableSlider.cs | 18 ++++++++++++------ osu.Game.Mode.Osu/Objects/Slider.cs | 2 +- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index f779f9948f..5a67a849d8 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -8,19 +8,25 @@ namespace osu.Game.Modes.Osu.Objects.Drawables { class DrawableSlider : DrawableOsuHitObject { - public DrawableSlider(Slider h) : base(h) + public DrawableSlider(Slider s) : base(s) { Origin = Anchor.Centre; - Position = new Vector2(h.Position.X, h.Position.Y); + Position = new Vector2(s.Position.X, s.Position.Y); Path sliderPath; Add(sliderPath = new Path()); - for (int i = 0; i < h.Curve.Path.Count; ++i) - sliderPath.Positions.Add(h.Curve.Path[i] - h.Position); + for (int i = 0; i < s.Curve.Path.Count; ++i) + sliderPath.Positions.Add(s.Curve.Path[i] - s.Position); - h.Position = Vector2.Zero; - Add(new DrawableHitCircle(h)); + Add(new DrawableHitCircle(new HitCircle + { + StartTime = s.StartTime, + Position = sliderPath.Positions[0] - s.Position, + }) + { + Depth = 1 + }); } protected override void LoadComplete() diff --git a/osu.Game.Mode.Osu/Objects/Slider.cs b/osu.Game.Mode.Osu/Objects/Slider.cs index b52a7c7623..3e0d899745 100644 --- a/osu.Game.Mode.Osu/Objects/Slider.cs +++ b/osu.Game.Mode.Osu/Objects/Slider.cs @@ -201,5 +201,5 @@ namespace osu.Game.Modes.Osu.Objects Bezier, Linear, PerfectCurve - }; + } } From 54fc25e16308563f055542a0d72bee9d832cafc4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 12:25:20 +0900 Subject: [PATCH 046/133] Fix disposal logic. --- osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs index 5d85bf0a5d..a291f4f65f 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs @@ -40,7 +40,8 @@ namespace osu.Desktop.VisualTests.Tests protected override void Dispose(bool isDisposing) { - Dependencies.Cache(oldDb, true); + if (oldDb != null) + Dependencies.Cache(oldDb, true); base.Dispose(isDisposing); } From e271bcec635da3309f266c3ecd96222bcae004dc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 12:40:24 +0900 Subject: [PATCH 047/133] General fix-ups for slider class. --- .../Objects/Drawables/DrawableHitCircle.cs | 6 +-- .../Objects/Drawables/DrawableSlider.cs | 43 +++++++++++++------ 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs index 8bead0fe53..47657eea80 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -59,15 +59,15 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Colour = osuObject.Colour, } }; + + //may not be so correct + Size = circle.DrawSize; } protected override void LoadComplete() { base.LoadComplete(); - //may not be so correct - Size = circle.DrawSize; - //force application of the state that was set before we loaded. UpdateState(State); } diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index 5a67a849d8..672867c607 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -1,38 +1,53 @@ using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Osu.Objects.Drawables.Pieces; using OpenTK; using osu.Framework.Graphics.Sprites; +using OpenTK.Graphics; namespace osu.Game.Modes.Osu.Objects.Drawables { class DrawableSlider : DrawableOsuHitObject { + private Path path; + private DrawableHitCircle startCircle; + private Slider slider; + public DrawableSlider(Slider s) : base(s) { - Origin = Anchor.Centre; - Position = new Vector2(s.Position.X, s.Position.Y); + slider = s; - Path sliderPath; - Add(sliderPath = new Path()); + Origin = Anchor.TopLeft; + Position = Vector2.Zero; - for (int i = 0; i < s.Curve.Path.Count; ++i) - sliderPath.Positions.Add(s.Curve.Path[i] - s.Position); - - Add(new DrawableHitCircle(new HitCircle + Children = new Drawable[] { - StartTime = s.StartTime, - Position = sliderPath.Positions[0] - s.Position, - }) - { - Depth = 1 - }); + startCircle = new DrawableHitCircle(new HitCircle + { + StartTime = s.StartTime, + Position = s.Position, + Colour = s.Colour, + }) + { + Depth = 1 //override time-based depth. + }, + path = new Path + { + Colour = s.Colour, + } + }; } protected override void LoadComplete() { base.LoadComplete(); + for (int i = 0; i < slider.Curve.Path.Count; ++i) + path.Positions.Add(slider.Curve.Path[i]); + + path.PathWidth = startCircle.DrawWidth / 4; + //force application of the state that was set before we loaded. UpdateState(State); } From a5651427f6fa2f19e93d27e7e3adcb59360aa42c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 15:12:11 +0900 Subject: [PATCH 048/133] Add basic ControlPoint parsing. --- osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs | 25 ++++++++++++++++--- osu.Game/Beatmaps/Timing/ControlPoint.cs | 9 +++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index 5468e616f0..ebb718af1b 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -10,6 +10,7 @@ using osu.Game.Beatmaps.Timing; using osu.Game.Modes; using osu.Game.Modes.Objects; using osu.Game.Screens.Play; +using static System.Double; namespace osu.Game.Beatmaps.Formats { @@ -85,7 +86,7 @@ namespace osu.Game.Beatmaps.Formats beatmap.BeatmapInfo.StoredBookmarks = val; break; case @"DistanceSpacing": - beatmap.BeatmapInfo.DistanceSpacing = double.Parse(val, NumberFormatInfo.InvariantInfo); + beatmap.BeatmapInfo.DistanceSpacing = Parse(val, NumberFormatInfo.InvariantInfo); break; case @"BeatDivisor": beatmap.BeatmapInfo.BeatDivisor = int.Parse(val); @@ -94,7 +95,7 @@ namespace osu.Game.Beatmaps.Formats beatmap.BeatmapInfo.GridSize = int.Parse(val); break; case @"TimelineZoom": - beatmap.BeatmapInfo.TimelineZoom = double.Parse(val, NumberFormatInfo.InvariantInfo); + beatmap.BeatmapInfo.TimelineZoom = Parse(val, NumberFormatInfo.InvariantInfo); break; } } @@ -187,7 +188,25 @@ namespace osu.Game.Beatmaps.Formats private void handleTimingPoints(Beatmap beatmap, string val) { - // TODO + ControlPoint cp = null; + + string[] split = val.Split(','); + + if (split.Length > 2) + { + int kiai_flags = split.Length > 7 ? Convert.ToInt32(split[7], NumberFormatInfo.InvariantInfo) : 0; + double beatLength = Parse(split[1].Trim(), NumberFormatInfo.InvariantInfo); + cp = new ControlPoint + { + Time = Parse(split[0].Trim(), NumberFormatInfo.InvariantInfo), + BeatLength = beatLength > 0 ? beatLength : 0, + VelocityAdjustment = beatLength < 0 ? -beatLength / 100.0 : 1, + TimingChange = split.Length <= 6 || split[6][0] == '1', + }; + } + + if (cp != null) + beatmap.ControlPoints.Add(cp); } private void handleColours(Beatmap beatmap, string key, string val) diff --git a/osu.Game/Beatmaps/Timing/ControlPoint.cs b/osu.Game/Beatmaps/Timing/ControlPoint.cs index 89eac572ec..6e83760c8d 100644 --- a/osu.Game/Beatmaps/Timing/ControlPoint.cs +++ b/osu.Game/Beatmaps/Timing/ControlPoint.cs @@ -12,5 +12,14 @@ namespace osu.Game.Beatmaps.Timing public class ControlPoint { public double Time; + public double BeatLength; + public double VelocityAdjustment; + public bool TimingChange; + } + + internal enum TimeSignatures + { + SimpleQuadruple = 4, + SimpleTriple = 3 } } From bf63be06021b3032dcd94d1c26d0f74668c993cd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 15:31:54 +0900 Subject: [PATCH 049/133] Add better slider duration calculation using bpm and difficulty information. --- osu.Game.Mode.Osu/Objects/Slider.cs | 6 +++-- osu.Game/Beatmaps/Beatmap.cs | 22 +++++++++++++++++++ osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs | 4 ++++ osu.Game/Modes/Objects/HitObject.cs | 3 +++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/osu.Game.Mode.Osu/Objects/Slider.cs b/osu.Game.Mode.Osu/Objects/Slider.cs index 3e0d899745..114b87eaaf 100644 --- a/osu.Game.Mode.Osu/Objects/Slider.cs +++ b/osu.Game.Mode.Osu/Objects/Slider.cs @@ -2,18 +2,20 @@ //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using osu.Game.Database; using OpenTK; namespace osu.Game.Modes.Osu.Objects { public class Slider : OsuHitObject { - public override double EndTime => StartTime + (RepeatCount + 1) * Curve.Length; + public override double EndTime => StartTime + (RepeatCount + 1) * Curve.Length / VelocityAt(StartTime); + + public double VelocityAt(double time) => 10000 / Beatmap.BeatLengthAt(time, true) * Beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier; public int RepeatCount; public SliderCurve Curve; - } public class SliderCurve diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 4d6c6a8056..3f8ae0e33a 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -16,5 +16,27 @@ namespace osu.Game.Beatmaps public List HitObjects { get; set; } public List ControlPoints { get; set; } public List ComboColors { get; set; } + + public double BeatLengthAt(double time, bool applyMultipliers = false) + { + int point = 0; + int samplePoint = 0; + + for (int i = 0; i < ControlPoints.Count; i++) + if (ControlPoints[i].Time <= time) + { + if (ControlPoints[i].TimingChange) + point = i; + else + samplePoint = i; + } + + double mult = 1; + + if (applyMultipliers && samplePoint > point && ControlPoints[samplePoint].BeatLength < 0) + mult = ControlPoints[samplePoint].VelocityAdjustment; + + return ControlPoints[point].BeatLength * mult; + } } } diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index ebb718af1b..7297a78c63 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -294,8 +294,12 @@ namespace osu.Game.Beatmaps.Formats break; case Section.HitObjects: var obj = parser?.Parse(val); + if (obj != null) + { + obj.Beatmap = beatmap; beatmap.HitObjects.Add(obj); + } break; } } diff --git a/osu.Game/Modes/Objects/HitObject.cs b/osu.Game/Modes/Objects/HitObject.cs index abb88726b6..ff352f9321 100644 --- a/osu.Game/Modes/Objects/HitObject.cs +++ b/osu.Game/Modes/Objects/HitObject.cs @@ -1,6 +1,7 @@ //Copyright (c) 2007-2016 ppy Pty Ltd . //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Beatmaps; using osu.Game.Beatmaps.Samples; using OpenTK.Graphics; @@ -20,6 +21,8 @@ namespace osu.Game.Modes.Objects public double Duration => EndTime - StartTime; + public Beatmap Beatmap; + public HitSampleInfo Sample; } } From b999d92ffb034de7df3130c4b3c791bbbd89cf9a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 16:28:47 +0900 Subject: [PATCH 050/133] Improve curve visualisation. --- osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs | 4 ++-- osu.Game.Mode.Osu/Objects/Slider.cs | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index 672867c607..983373f826 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -43,8 +43,8 @@ namespace osu.Game.Modes.Osu.Objects.Drawables { base.LoadComplete(); - for (int i = 0; i < slider.Curve.Path.Count; ++i) - path.Positions.Add(slider.Curve.Path[i]); + for (int i = 0; i < slider.Curve.Length; i += 10) + path.Positions.Add(slider.Curve.PositionAt(i / slider.Curve.Length)); path.PathWidth = startCircle.DrawWidth / 4; diff --git a/osu.Game.Mode.Osu/Objects/Slider.cs b/osu.Game.Mode.Osu/Objects/Slider.cs index 114b87eaaf..08ee732cd2 100644 --- a/osu.Game.Mode.Osu/Objects/Slider.cs +++ b/osu.Game.Mode.Osu/Objects/Slider.cs @@ -44,11 +44,13 @@ namespace osu.Game.Modes.Osu.Objects public Vector2 PositionAt(double progress) { - int index = (int)(progress * (calculatedPath.Count - 1)); + progress = MathHelper.Clamp(progress, 0, 1); - Vector2 pos = calculatedPath[index]; - if (index != progress) - pos += (calculatedPath[index + 1] - pos) * (float)(progress - index); + double index = progress * (calculatedPath.Count - 1); + + Vector2 pos = calculatedPath[(int)index]; + if (index != (int)index) + pos += (calculatedPath[(int)index + 1] - pos) * (float)(index - (int)index); return pos; } From b1f141e1a0db8d7854cff88ac7c5d4221de7ee32 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 16:31:19 +0900 Subject: [PATCH 051/133] Add basic slider ball logic. --- .../Objects/Drawables/DrawableSlider.cs | 46 +++++++++++++++++-- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index 983373f826..b311e0b15f 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -13,6 +13,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables private Path path; private DrawableHitCircle startCircle; private Slider slider; + private Container ball; public DrawableSlider(Slider s) : base(s) { @@ -23,6 +24,26 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Children = new Drawable[] { + path = new Path + { + Colour = s.Colour, + }, + ball = new Container + { + Masking = true, + CornerRadius = 20, + AutoSizeAxes = Axes.Both, + Colour = Color4.Red, + Origin = Anchor.Centre, + Children = new [] + { + new Box + { + Width = 40, + Height = 40, + } + } + }, startCircle = new DrawableHitCircle(new HitCircle { StartTime = s.StartTime, @@ -32,10 +53,6 @@ namespace osu.Game.Modes.Osu.Objects.Drawables { Depth = 1 //override time-based depth. }, - path = new Path - { - Colour = s.Colour, - } }; } @@ -52,6 +69,25 @@ namespace osu.Game.Modes.Osu.Objects.Drawables UpdateState(State); } + protected override void Update() + { + base.Update(); + + ball.Alpha = Time.Current >= slider.StartTime && Time.Current <= slider.EndTime ? 1 : 0; + + double t = (Time.Current - slider.StartTime) / slider.Duration; + if (slider.RepeatCount > 1) + { + double currentRepeat = (int)(t * slider.RepeatCount); + t = (t * slider.RepeatCount) % 1; + if (currentRepeat % 2 == 1) + t = 1 - t; + } + + ball.Position = slider.Curve.PositionAt(t); + + } + protected override void UpdateState(ArmedState state) { if (!IsLoaded) return; @@ -64,7 +100,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables FadeIn(200); Delay(450 + HitObject.Duration); - FadeOut(200); + FadeOut(100); } } } From 2616d05767b46c1b4899de2a6707183a4bb183f6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 16:31:31 +0900 Subject: [PATCH 052/133] Adjust velocity calculation. --- osu.Game.Mode.Osu/Objects/Slider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Mode.Osu/Objects/Slider.cs b/osu.Game.Mode.Osu/Objects/Slider.cs index 08ee732cd2..fcca305369 100644 --- a/osu.Game.Mode.Osu/Objects/Slider.cs +++ b/osu.Game.Mode.Osu/Objects/Slider.cs @@ -11,7 +11,7 @@ namespace osu.Game.Modes.Osu.Objects { public override double EndTime => StartTime + (RepeatCount + 1) * Curve.Length / VelocityAt(StartTime); - public double VelocityAt(double time) => 10000 / Beatmap.BeatLengthAt(time, true) * Beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier; + public double VelocityAt(double time) => 100 / Beatmap.BeatLengthAt(time, true) * Beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier; public int RepeatCount; From 622c90daf7f5a0d96b8f13f7d9079720df6cd625 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 16:52:57 +0900 Subject: [PATCH 053/133] Add basic snaking. --- .../Objects/Drawables/DrawableSlider.cs | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index b311e0b15f..13401eb6d3 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -1,4 +1,5 @@ -using osu.Framework.Graphics; +using System.Collections.Generic; +using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Osu.Objects.Drawables.Pieces; @@ -60,15 +61,14 @@ namespace osu.Game.Modes.Osu.Objects.Drawables { base.LoadComplete(); - for (int i = 0; i < slider.Curve.Length; i += 10) - path.Positions.Add(slider.Curve.PositionAt(i / slider.Curve.Length)); - path.PathWidth = startCircle.DrawWidth / 4; //force application of the state that was set before we loaded. UpdateState(State); } + double snakeDrawn = 0; + protected override void Update() { base.Update(); @@ -83,9 +83,30 @@ namespace osu.Game.Modes.Osu.Objects.Drawables if (currentRepeat % 2 == 1) t = 1 - t; } - - ball.Position = slider.Curve.PositionAt(t); + double snake = MathHelper.Clamp((Time.Current - slider.StartTime + 450) / 200, 0, 1); + if (snake != snakeDrawn) + { + if (snake < snakeDrawn) + { + //if we have gone backwards, just clear the path for now. + snakeDrawn = 0; + path.Positions.Clear(); + } + + const double segment_size = 10; + + while (snakeDrawn < snake) + { + snakeDrawn += segment_size; + path.Positions.Add(slider.Curve.PositionAt(snake)); + } + + snakeDrawn = snake; + path.Positions.Add(slider.Curve.PositionAt(snake)); + } + + ball.Position = slider.Curve.PositionAt(t); } protected override void UpdateState(ArmedState state) From 9eb3e1168e09e2fca1d5988550a22d5d5e01cd8e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 17:05:30 +0900 Subject: [PATCH 054/133] Refactor SliderBody into its own class. --- .../Objects/Drawables/DrawableSlider.cs | 100 ++++++++++++------ 1 file changed, 67 insertions(+), 33 deletions(-) diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index 13401eb6d3..e84633bec6 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -11,10 +11,11 @@ namespace osu.Game.Modes.Osu.Objects.Drawables { class DrawableSlider : DrawableOsuHitObject { - private Path path; - private DrawableHitCircle startCircle; private Slider slider; + + private DrawableHitCircle startCircle; private Container ball; + private SliderBody body; public DrawableSlider(Slider s) : base(s) { @@ -25,10 +26,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Children = new Drawable[] { - path = new Path - { - Colour = s.Colour, - }, + body = new SliderBody(s), ball = new Container { Masking = true, @@ -61,14 +59,10 @@ namespace osu.Game.Modes.Osu.Objects.Drawables { base.LoadComplete(); - path.PathWidth = startCircle.DrawWidth / 4; - //force application of the state that was set before we loaded. UpdateState(State); } - double snakeDrawn = 0; - protected override void Update() { base.Update(); @@ -84,28 +78,6 @@ namespace osu.Game.Modes.Osu.Objects.Drawables t = 1 - t; } - double snake = MathHelper.Clamp((Time.Current - slider.StartTime + 450) / 200, 0, 1); - if (snake != snakeDrawn) - { - if (snake < snakeDrawn) - { - //if we have gone backwards, just clear the path for now. - snakeDrawn = 0; - path.Positions.Clear(); - } - - const double segment_size = 10; - - while (snakeDrawn < snake) - { - snakeDrawn += segment_size; - path.Positions.Add(slider.Curve.PositionAt(snake)); - } - - snakeDrawn = snake; - path.Positions.Add(slider.Curve.PositionAt(snake)); - } - ball.Position = slider.Curve.PositionAt(t); } @@ -119,9 +91,71 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Delay(HitObject.StartTime - 450 - Time.Current, true); - FadeIn(200); + FadeIn(300); Delay(450 + HitObject.Duration); FadeOut(100); } + + class SliderBody : Container + { + private Path path; + + double snakeDrawn = 0; + + Slider slider; + + public SliderBody(Slider s) + { + slider = s; + + Children = new Drawable[] + { + //new BufferedContainer + //{ + // RelativeSizeAxes = Axes.Both, + // Children = new Drawable[] + // { + path = new Path + { + Colour = s.Colour, + }, + // } + //} + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + path.PathWidth = 50; + } + + protected override void Update() + { + base.Update(); + + double snake = MathHelper.Clamp((Time.Current - slider.StartTime + 450) / 200, 0, 1); + if (snake != snakeDrawn) + { + if (snake < snakeDrawn) + { + //if we have gone backwards, just clear the path for now. + snakeDrawn = 0; + path.Positions.Clear(); + } + + const double segment_size = 10; + + while (snakeDrawn < snake) + { + snakeDrawn += segment_size; + path.Positions.Add(slider.Curve.PositionAt(snake)); + } + + snakeDrawn = snake; + path.Positions.Add(slider.Curve.PositionAt(snake)); + } + } + } } } From 899c341fd3970418dba01dc8f13f5158356e0eb3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 17:55:19 +0900 Subject: [PATCH 055/133] Fix incorrect slider duration calculation. --- osu.Game.Mode.Osu/Objects/Slider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Mode.Osu/Objects/Slider.cs b/osu.Game.Mode.Osu/Objects/Slider.cs index fcca305369..90a9ac1f14 100644 --- a/osu.Game.Mode.Osu/Objects/Slider.cs +++ b/osu.Game.Mode.Osu/Objects/Slider.cs @@ -9,7 +9,7 @@ namespace osu.Game.Modes.Osu.Objects { public class Slider : OsuHitObject { - public override double EndTime => StartTime + (RepeatCount + 1) * Curve.Length / VelocityAt(StartTime); + public override double EndTime => StartTime + RepeatCount * Curve.Length / VelocityAt(StartTime); public double VelocityAt(double time) => 100 / Beatmap.BeatLengthAt(time, true) * Beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier; From 15096c2f00efeb79ef6fab2f929bad1281c48326 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 18:40:38 +0900 Subject: [PATCH 056/133] Improve snaking logic. --- .../Objects/Drawables/DrawableSlider.cs | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index e84633bec6..147d4a3c7b 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -100,7 +100,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables { private Path path; - double snakeDrawn = 0; + double? drawnProgress; Slider slider; @@ -134,26 +134,37 @@ namespace osu.Game.Modes.Osu.Objects.Drawables { base.Update(); - double snake = MathHelper.Clamp((Time.Current - slider.StartTime + 450) / 200, 0, 1); - if (snake != snakeDrawn) + double segmentSize = 1 / (slider.Curve.Length / 5); + double progress = MathHelper.Clamp((Time.Current - slider.StartTime + TIME_PREEMPT) / TIME_FADEIN, 0, 1); + + if (progress != drawnProgress) { - if (snake < snakeDrawn) + if (progress == 0) { //if we have gone backwards, just clear the path for now. - snakeDrawn = 0; + drawnProgress = 0; path.Positions.Clear(); } - const double segment_size = 10; - - while (snakeDrawn < snake) + if (drawnProgress == null) { - snakeDrawn += segment_size; - path.Positions.Add(slider.Curve.PositionAt(snake)); + drawnProgress = 0; + path.Positions.Add(slider.Curve.PositionAt(drawnProgress.Value)); } - snakeDrawn = snake; - path.Positions.Add(slider.Curve.PositionAt(snake)); + while (drawnProgress + segmentSize < progress) + { + drawnProgress += segmentSize; + path.Positions.Add(slider.Curve.PositionAt(drawnProgress.Value)); + } + + if (progress == 1 && drawnProgress != progress) + { + drawnProgress = progress; + path.Positions.Add(slider.Curve.PositionAt(drawnProgress.Value)); + } + + path.Invalidate(Invalidation.DrawNode); } } } From c376f8436c9437538438ee165ceb22f6783aabc8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 18:40:54 +0900 Subject: [PATCH 057/133] Centralise common state setting for osu HitObjects. --- .../Objects/Drawables/DrawableHitCircle.cs | 36 ++++++++----------- .../Objects/Drawables/DrawableOsuHitObject.cs | 28 ++++++++++++++- .../Objects/Drawables/DrawableSlider.cs | 11 ++---- 3 files changed, 44 insertions(+), 31 deletions(-) diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs index 47657eea80..94e9a41c5a 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -104,16 +104,9 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Judgement.Result = HitResult.Miss; } - protected override void UpdateState(ArmedState state) + protected override void UpdateInitialState() { - if (!IsLoaded) return; - - Flush(true); //move to DrawableHitObject - ApproachCircle.Flush(true); - - double t = osuObject.EndTime + Judgement.TimeOffset; - - Alpha = 0; + base.UpdateInitialState(); //sane defaults ring.Alpha = circle.Alpha = number.Alpha = glow.Alpha = 1; @@ -121,29 +114,30 @@ namespace osu.Game.Modes.Osu.Objects.Drawables ApproachCircle.Scale = new Vector2(2); explode.Alpha = 0; Scale = new Vector2(0.5f); //this will probably need to be moved to DrawableHitObject at some point. + } - const float preempt = 600; + protected override void UpdatePreemptState() + { + base.UpdatePreemptState(); - const float fadein = 400; + ApproachCircle.FadeIn(Math.Min(TIME_FADEIN * 2, TIME_PREEMPT)); + ApproachCircle.ScaleTo(0.6f, TIME_PREEMPT); + } - Delay(t - Time.Current - preempt, true); + protected override void UpdateState(ArmedState state) + { + if (!IsLoaded) return; - FadeIn(fadein); - - ApproachCircle.FadeIn(Math.Min(fadein * 2, preempt)); - ApproachCircle.ScaleTo(0.6f, preempt); - - Delay(preempt, true); + base.UpdateState(state); ApproachCircle.FadeOut(); - glow.FadeOut(400); switch (state) { case ArmedState.Idle: - Delay(osuObject.Duration + 500); - FadeOut(500); + Delay(osuObject.Duration + TIME_PREEMPT); + FadeOut(TIME_FADEOUT); explosion?.Expire(); explosion = null; diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableOsuHitObject.cs index d416732327..51e1f06de0 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -11,6 +11,10 @@ namespace osu.Game.Modes.Osu.Objects.Drawables { public class DrawableOsuHitObject : DrawableHitObject { + protected const float TIME_PREEMPT = 600; + protected const float TIME_FADEIN = 400; + protected const float TIME_FADEOUT = 500; + public DrawableOsuHitObject(OsuHitObject hitObject) : base(hitObject) { @@ -20,7 +24,29 @@ namespace osu.Game.Modes.Osu.Objects.Drawables protected override void UpdateState(ArmedState state) { - throw new NotImplementedException(); + if (!IsLoaded) return; + + Flush(true); + + double t = HitObject.EndTime + Judgement.TimeOffset; + + UpdateInitialState(); + + Delay(t - Time.Current - TIME_PREEMPT, true); + + UpdatePreemptState(); + + Delay(TIME_PREEMPT, true); + } + + protected virtual void UpdatePreemptState() + { + FadeIn(TIME_FADEIN); + } + + protected virtual void UpdateInitialState() + { + Alpha = 0; } } diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index 147d4a3c7b..93d398de4f 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -83,16 +83,9 @@ namespace osu.Game.Modes.Osu.Objects.Drawables protected override void UpdateState(ArmedState state) { - if (!IsLoaded) return; + base.UpdateState(state); - Flush(true); //move to DrawableHitObject - - Alpha = 0; - - Delay(HitObject.StartTime - 450 - Time.Current, true); - - FadeIn(300); - Delay(450 + HitObject.Duration); + Delay(HitObject.Duration); FadeOut(100); } From 187a8bbfa766d2c0b93061d48f594c8c9cbd98d9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 18:45:50 +0900 Subject: [PATCH 058/133] Don't store beatmap reference in hitobjects. --- osu.Game.Mode.Osu/Objects/Slider.cs | 11 +++++++++-- osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs | 2 +- osu.Game/Modes/Objects/HitObject.cs | 4 ++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/osu.Game.Mode.Osu/Objects/Slider.cs b/osu.Game.Mode.Osu/Objects/Slider.cs index 90a9ac1f14..b06ae398f4 100644 --- a/osu.Game.Mode.Osu/Objects/Slider.cs +++ b/osu.Game.Mode.Osu/Objects/Slider.cs @@ -4,14 +4,21 @@ using System.Collections.Generic; using osu.Game.Database; using OpenTK; +using osu.Game.Beatmaps; +using System; namespace osu.Game.Modes.Osu.Objects { public class Slider : OsuHitObject { - public override double EndTime => StartTime + RepeatCount * Curve.Length / VelocityAt(StartTime); + public override double EndTime => StartTime + RepeatCount * Curve.Length / Velocity; - public double VelocityAt(double time) => 100 / Beatmap.BeatLengthAt(time, true) * Beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier; + public double Velocity; + + public override void SetDefaultsFromBeatmap(Beatmap beatmap) + { + Velocity = 100 / beatmap.BeatLengthAt(StartTime, true) * beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier; + } public int RepeatCount; diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index 7297a78c63..510ba43d4a 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -297,7 +297,7 @@ namespace osu.Game.Beatmaps.Formats if (obj != null) { - obj.Beatmap = beatmap; + obj.SetDefaultsFromBeatmap(beatmap); beatmap.HitObjects.Add(obj); } break; diff --git a/osu.Game/Modes/Objects/HitObject.cs b/osu.Game/Modes/Objects/HitObject.cs index ff352f9321..71839e7036 100644 --- a/osu.Game/Modes/Objects/HitObject.cs +++ b/osu.Game/Modes/Objects/HitObject.cs @@ -21,8 +21,8 @@ namespace osu.Game.Modes.Objects public double Duration => EndTime - StartTime; - public Beatmap Beatmap; - public HitSampleInfo Sample; + + public virtual void SetDefaultsFromBeatmap(Beatmap beatmap) { } } } From 907e8e83ce9e64b489feeeb308b3593fb01fd969 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 18:53:59 +0900 Subject: [PATCH 059/133] Delay snaking slightly. --- osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index 93d398de4f..48c5e3bb61 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -128,7 +128,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables base.Update(); double segmentSize = 1 / (slider.Curve.Length / 5); - double progress = MathHelper.Clamp((Time.Current - slider.StartTime + TIME_PREEMPT) / TIME_FADEIN, 0, 1); + double progress = MathHelper.Clamp((Time.Current - slider.StartTime + TIME_PREEMPT / 2) / TIME_FADEIN, 0, 1); if (progress != drawnProgress) { From c7ffd56a1080c3efbea567b972fb6c2b736b5bb3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 19:42:45 +0900 Subject: [PATCH 060/133] Add interactivity to sliders, follow circle etc. --- .../Objects/Drawables/DrawableOsuHitObject.cs | 4 +- .../Objects/Drawables/DrawableSlider.cs | 180 +++++++++++++----- 2 files changed, 131 insertions(+), 53 deletions(-) diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 51e1f06de0..0e3a03665c 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -28,11 +28,9 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Flush(true); - double t = HitObject.EndTime + Judgement.TimeOffset; - UpdateInitialState(); - Delay(t - Time.Current - TIME_PREEMPT, true); + Delay(HitObject.StartTime - Time.Current - TIME_PREEMPT + Judgement.TimeOffset, true); UpdatePreemptState(); diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index 48c5e3bb61..000da2de53 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -5,7 +5,9 @@ using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Osu.Objects.Drawables.Pieces; using OpenTK; using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Transformations; using OpenTK.Graphics; +using osu.Framework.Input; namespace osu.Game.Modes.Osu.Objects.Drawables { @@ -15,7 +17,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables private DrawableHitCircle startCircle; private Container ball; - private SliderBody body; + private Body body; public DrawableSlider(Slider s) : base(s) { @@ -23,26 +25,12 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Origin = Anchor.TopLeft; Position = Vector2.Zero; + RelativeSizeAxes = Axes.Both; Children = new Drawable[] { - body = new SliderBody(s), - ball = new Container - { - Masking = true, - CornerRadius = 20, - AutoSizeAxes = Axes.Both, - Colour = Color4.Red, - Origin = Anchor.Centre, - Children = new [] - { - new Box - { - Width = 40, - Height = 40, - } - } - }, + body = new Body(s), + ball = new Ball(), startCircle = new DrawableHitCircle(new HitCircle { StartTime = s.StartTime, @@ -89,15 +77,102 @@ namespace osu.Game.Modes.Osu.Objects.Drawables FadeOut(100); } - class SliderBody : Container + private class Ball : Container + { + private Box follow; + + public Ball() + { + Masking = true; + AutoSizeAxes = Axes.Both; + BlendingMode = BlendingMode.Additive; + Origin = Anchor.Centre; + + Children = new Drawable[] + { + follow = new Box + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Colour = Color4.Orange, + Width = 64, + Height = 64, + }, + new Container + { + Masking = true, + AutoSizeAxes = Axes.Both, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Colour = Color4.Cyan, + CornerRadius = 32, + Children = new[] + { + new Box + { + + Width = 64, + Height = 64, + }, + } + } + + }; + } + + private InputState lastState; + + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + { + lastState = state; + return base.OnMouseDown(state, args); + } + + protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) + { + lastState = state; + return base.OnMouseUp(state, args); + } + + protected override bool OnMouseMove(InputState state) + { + lastState = state; + return base.OnMouseMove(state); + } + + bool tracking; + protected bool Tracking + { + get { return tracking; } + set + { + if (value == tracking) return; + + tracking = value; + + follow.ScaleTo(tracking ? 2 : 1, 140, EasingTypes.Out); + follow.FadeTo(tracking ? 0.8f : 0, 140, EasingTypes.Out); + } + } + + protected override void Update() + { + base.Update(); + + CornerRadius = DrawWidth / 2; + Tracking = lastState != null && Contains(lastState.Mouse.NativeState.Position) && lastState.Mouse.HasMainButtonPressed; + } + } + + private class Body : Container { private Path path; - double? drawnProgress; + private double? drawnProgress; - Slider slider; + private Slider slider; - public SliderBody(Slider s) + public Body(Slider s) { slider = s; @@ -127,38 +202,43 @@ namespace osu.Game.Modes.Osu.Objects.Drawables { base.Update(); - double segmentSize = 1 / (slider.Curve.Length / 5); + updateSnaking(); + } + + private void updateSnaking() + { double progress = MathHelper.Clamp((Time.Current - slider.StartTime + TIME_PREEMPT / 2) / TIME_FADEIN, 0, 1); - if (progress != drawnProgress) + if (progress == drawnProgress) return; + + if (progress == 0) { - if (progress == 0) - { - //if we have gone backwards, just clear the path for now. - drawnProgress = 0; - path.Positions.Clear(); - } - - if (drawnProgress == null) - { - drawnProgress = 0; - path.Positions.Add(slider.Curve.PositionAt(drawnProgress.Value)); - } - - while (drawnProgress + segmentSize < progress) - { - drawnProgress += segmentSize; - path.Positions.Add(slider.Curve.PositionAt(drawnProgress.Value)); - } - - if (progress == 1 && drawnProgress != progress) - { - drawnProgress = progress; - path.Positions.Add(slider.Curve.PositionAt(drawnProgress.Value)); - } - - path.Invalidate(Invalidation.DrawNode); + //if we have gone backwards, just clear the path for now. + drawnProgress = 0; + path.Positions.Clear(); } + + if (drawnProgress == null) + { + drawnProgress = 0; + path.Positions.Add(slider.Curve.PositionAt(drawnProgress.Value)); + } + + double segmentSize = 1 / (slider.Curve.Length / 5); + + while (drawnProgress + segmentSize < progress) + { + drawnProgress += segmentSize; + path.Positions.Add(slider.Curve.PositionAt(drawnProgress.Value)); + } + + if (progress == 1 && drawnProgress != progress) + { + drawnProgress = progress; + path.Positions.Add(slider.Curve.PositionAt(drawnProgress.Value)); + } + + path.Invalidate(Invalidation.DrawNode); } } } From ad761eb66af4662173640369eee4632f48439c74 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 19:51:50 +0900 Subject: [PATCH 061/133] Make tracking area larger. --- osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index 000da2de53..cbf11522e4 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -150,7 +150,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables tracking = value; - follow.ScaleTo(tracking ? 2 : 1, 140, EasingTypes.Out); + follow.ScaleTo(tracking ? 2.4f : 1, 140, EasingTypes.Out); follow.FadeTo(tracking ? 0.8f : 0, 140, EasingTypes.Out); } } From f2249604290dbb822b1900d09220d896aac64825 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 20:09:20 +0900 Subject: [PATCH 062/133] Update framework. --- osu-framework | 2 +- osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu-framework b/osu-framework index fdea70aee3..cc28af53d9 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit fdea70aee37b040d56fac5e9b27a18ed77f2bfb9 +Subproject commit cc28af53d93e2f1c5f0707c5616ed601e0cf9339 diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index cbf11522e4..d43422cebc 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -195,7 +195,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables protected override void LoadComplete() { base.LoadComplete(); - path.PathWidth = 50; + path.PathWidth = 32; } protected override void Update() @@ -215,13 +215,13 @@ namespace osu.Game.Modes.Osu.Objects.Drawables { //if we have gone backwards, just clear the path for now. drawnProgress = 0; - path.Positions.Clear(); + path.ClearVertices(); } if (drawnProgress == null) { drawnProgress = 0; - path.Positions.Add(slider.Curve.PositionAt(drawnProgress.Value)); + path.AddVertex(slider.Curve.PositionAt(drawnProgress.Value)); } double segmentSize = 1 / (slider.Curve.Length / 5); @@ -229,13 +229,13 @@ namespace osu.Game.Modes.Osu.Objects.Drawables while (drawnProgress + segmentSize < progress) { drawnProgress += segmentSize; - path.Positions.Add(slider.Curve.PositionAt(drawnProgress.Value)); + path.AddVertex(slider.Curve.PositionAt(drawnProgress.Value)); } if (progress == 1 && drawnProgress != progress) { drawnProgress = progress; - path.Positions.Add(slider.Curve.PositionAt(drawnProgress.Value)); + path.AddVertex(slider.Curve.PositionAt(drawnProgress.Value)); } path.Invalidate(Invalidation.DrawNode); From ce13d813b74c65e7ac34703fa409b4ba73e27386 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 22:46:07 +0900 Subject: [PATCH 063/133] Remove unnecessary null check. --- osu.Desktop.VisualTests/Tests/TestCasePlayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs index 7d67e5aad3..89bacb9b97 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs @@ -29,7 +29,7 @@ namespace osu.Desktop.VisualTests.Tests [BackgroundDependencyLoader] private void load(BeatmapDatabase db) { - beatmap = db?.GetWorkingBeatmap(db.Query().Where(b => b.Mode == PlayMode.Osu).FirstOrDefault()); + beatmap = db.GetWorkingBeatmap(db.Query().Where(b => b.Mode == PlayMode.Osu).FirstOrDefault()); } public override void Reset() From 9114c9dec4e4fe3e6daf4b2f6a95c4ddcb39e1e7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 22:46:52 +0900 Subject: [PATCH 064/133] Change double to int. --- osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index d43422cebc..3a8db60d61 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -60,7 +60,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables double t = (Time.Current - slider.StartTime) / slider.Duration; if (slider.RepeatCount > 1) { - double currentRepeat = (int)(t * slider.RepeatCount); + int currentRepeat = (int)(t * slider.RepeatCount); t = (t * slider.RepeatCount) % 1; if (currentRepeat % 2 == 1) t = 1 - t; From 785ae892f473393d3d61074548fe958656f1da9d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 22:47:50 +0900 Subject: [PATCH 065/133] Cast less. --- osu.Game.Mode.Osu/Objects/Slider.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Mode.Osu/Objects/Slider.cs b/osu.Game.Mode.Osu/Objects/Slider.cs index b06ae398f4..7ee131659a 100644 --- a/osu.Game.Mode.Osu/Objects/Slider.cs +++ b/osu.Game.Mode.Osu/Objects/Slider.cs @@ -54,10 +54,11 @@ namespace osu.Game.Modes.Osu.Objects progress = MathHelper.Clamp(progress, 0, 1); double index = progress * (calculatedPath.Count - 1); + int flooredIndex = (int)index; - Vector2 pos = calculatedPath[(int)index]; - if (index != (int)index) - pos += (calculatedPath[(int)index + 1] - pos) * (float)(index - (int)index); + Vector2 pos = calculatedPath[flooredIndex]; + if (index != flooredIndex) + pos += (calculatedPath[flooredIndex + 1] - pos) * (float)(index - flooredIndex); return pos; } From 49470318f209f30bc11e96ab95907d538380fda4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 22:48:28 +0900 Subject: [PATCH 066/133] Remove silly static using statement. --- osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index 510ba43d4a..36f2efaad6 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -10,7 +10,6 @@ using osu.Game.Beatmaps.Timing; using osu.Game.Modes; using osu.Game.Modes.Objects; using osu.Game.Screens.Play; -using static System.Double; namespace osu.Game.Beatmaps.Formats { @@ -86,7 +85,7 @@ namespace osu.Game.Beatmaps.Formats beatmap.BeatmapInfo.StoredBookmarks = val; break; case @"DistanceSpacing": - beatmap.BeatmapInfo.DistanceSpacing = Parse(val, NumberFormatInfo.InvariantInfo); + beatmap.BeatmapInfo.DistanceSpacing = double.Parse(val, NumberFormatInfo.InvariantInfo); break; case @"BeatDivisor": beatmap.BeatmapInfo.BeatDivisor = int.Parse(val); @@ -95,7 +94,7 @@ namespace osu.Game.Beatmaps.Formats beatmap.BeatmapInfo.GridSize = int.Parse(val); break; case @"TimelineZoom": - beatmap.BeatmapInfo.TimelineZoom = Parse(val, NumberFormatInfo.InvariantInfo); + beatmap.BeatmapInfo.TimelineZoom = double.Parse(val, NumberFormatInfo.InvariantInfo); break; } } From a506e91b7c8fde614bbad8f5553e26a86df223e6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Nov 2016 23:05:05 +0900 Subject: [PATCH 067/133] Fix compile issues. --- osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index 36f2efaad6..b1eaeb467d 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -194,10 +194,10 @@ namespace osu.Game.Beatmaps.Formats if (split.Length > 2) { int kiai_flags = split.Length > 7 ? Convert.ToInt32(split[7], NumberFormatInfo.InvariantInfo) : 0; - double beatLength = Parse(split[1].Trim(), NumberFormatInfo.InvariantInfo); + double beatLength = double.Parse(split[1].Trim(), NumberFormatInfo.InvariantInfo); cp = new ControlPoint { - Time = Parse(split[0].Trim(), NumberFormatInfo.InvariantInfo), + Time = double.Parse(split[0].Trim(), NumberFormatInfo.InvariantInfo), BeatLength = beatLength > 0 ? beatLength : 0, VelocityAdjustment = beatLength < 0 ? -beatLength / 100.0 : 1, TimingChange = split.Length <= 6 || split[6][0] == '1', From 0b8e37fb1d15156a721268df40ab2510386ffc68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Mon, 28 Nov 2016 19:04:03 +0100 Subject: [PATCH 068/133] Improve slider rendering by using a buffered container (with depth attachment) and proper alpha blending. --- osu-framework | 2 +- .../Objects/Drawables/DrawableSlider.cs | 67 ++++++++++++++----- 2 files changed, 51 insertions(+), 18 deletions(-) diff --git a/osu-framework b/osu-framework index cc28af53d9..e125c03d8c 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit cc28af53d93e2f1c5f0707c5616ed601e0cf9339 +Subproject commit e125c03d8c39fd86e02e872a8d46654d2ea2759f diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index 3a8db60d61..1d55d704c4 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -8,6 +8,9 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Transformations; using OpenTK.Graphics; using osu.Framework.Input; +using OpenTK.Graphics.ES30; +using osu.Framework.Allocation; +using osu.Framework.Graphics.Textures; namespace osu.Game.Modes.Osu.Objects.Drawables { @@ -29,7 +32,10 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Children = new Drawable[] { - body = new Body(s), + body = new Body(s) + { + Position = s.Position, + }, ball = new Ball(), startCircle = new DrawableHitCircle(new HitCircle { @@ -167,29 +173,40 @@ namespace osu.Game.Modes.Osu.Objects.Drawables private class Body : Container { private Path path; + private BufferedContainer container; private double? drawnProgress; private Slider slider; - public Body(Slider s) { slider = s; Children = new Drawable[] { - //new BufferedContainer - //{ - // RelativeSizeAxes = Axes.Both, - // Children = new Drawable[] - // { + container = new BufferedContainer + { + CacheDrawnFrameBuffer = true, + Children = new Drawable[] + { path = new Path { Colour = s.Colour, + BlendingMode = BlendingMode.None, }, - // } - //} + } + } }; + + container.Attach(RenderbufferInternalFormat.DepthComponent16); + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + // Surprisingly, this looks somewhat okay and works well as a test for self-overlaps. + // TODO: Don't do this. + path.Texture = textures.Get(@"Menu/logo"); } protected override void LoadComplete() @@ -202,26 +219,40 @@ namespace osu.Game.Modes.Osu.Objects.Drawables { base.Update(); - updateSnaking(); + if (updateSnaking()) + { + // Autosizing does not give us the desired behaviour here. + // We want the container to have the same size as the slider, + // and to be positioned such that the slider head is at (0,0). + container.Size = path.Size; + container.Position = -path.HeadPosition; + + container.ForceRedraw(); + } } - private void updateSnaking() + private bool updateSnaking() { - double progress = MathHelper.Clamp((Time.Current - slider.StartTime + TIME_PREEMPT / 2) / TIME_FADEIN, 0, 1); + double progress = MathHelper.Clamp((Time.Current - slider.StartTime + TIME_PREEMPT) / TIME_FADEIN, 0, 1); - if (progress == drawnProgress) return; + if (progress == drawnProgress) return false; + bool madeChanges = false; if (progress == 0) { //if we have gone backwards, just clear the path for now. drawnProgress = 0; path.ClearVertices(); + madeChanges = true; } + Vector2 startPosition = slider.Curve.PositionAt(0); + if (drawnProgress == null) { drawnProgress = 0; - path.AddVertex(slider.Curve.PositionAt(drawnProgress.Value)); + path.AddVertex(slider.Curve.PositionAt(drawnProgress.Value) - startPosition); + madeChanges = true; } double segmentSize = 1 / (slider.Curve.Length / 5); @@ -229,16 +260,18 @@ namespace osu.Game.Modes.Osu.Objects.Drawables while (drawnProgress + segmentSize < progress) { drawnProgress += segmentSize; - path.AddVertex(slider.Curve.PositionAt(drawnProgress.Value)); + path.AddVertex(slider.Curve.PositionAt(drawnProgress.Value) - startPosition); + madeChanges = true; } if (progress == 1 && drawnProgress != progress) { drawnProgress = progress; - path.AddVertex(slider.Curve.PositionAt(drawnProgress.Value)); + path.AddVertex(slider.Curve.PositionAt(drawnProgress.Value) - startPosition); + madeChanges = true; } - path.Invalidate(Invalidation.DrawNode); + return madeChanges; } } } From 2ecf72d0d7f3fa439d41c750afb935e5adaba71d Mon Sep 17 00:00:00 2001 From: stanriders Date: Tue, 29 Nov 2016 05:36:48 +0300 Subject: [PATCH 069/133] More consts, less crap (probably) --- osu-framework | 2 +- osu.Game/Graphics/UserInterface/BackButton.cs | 60 +++++++++---------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/osu-framework b/osu-framework index 24af3b161d..cc28af53d9 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 24af3b161da9447b678edd8ec32193df54f71e3b +Subproject commit cc28af53d93e2f1c5f0707c5616ed601e0cf9339 diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index 06aa21f2b0..f87e469b4a 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -12,40 +12,45 @@ using osu.Framework.Input; namespace osu.Game.Graphics.UserInterface { // Basic back button as it was on stable (kinda). No skinning possible for now - class BackButton : ClickableContainer + public class BackButton : ClickableContainer { private TextAwesome icon; - private Container leftContainer; - private Container rightContainer; + private Container leftContainer; + private Container rightContainer; - public Vector2 ExtendLength = new Vector2(60, 0); - public Vector2 InitialExtendLength = new Vector2(40, 0); - - private Color4 colorBright = new Color4(238, 51, 153, 255); - private Color4 colorDark = new Color4(195, 40, 140, 255); private const double transform_time = 300.0; - private const int pulse_length = 250; + private const int pulse_length = 250; + + private const float shear = 0.1f; + + private const int extend_length = 60; + private const int initial_extend_length = 40; + + private const int width_extended = 140; + private const int width_retracted = 120; public BackButton() { RelativeSizeAxes = Axes.None; - Width = 120; + Width = width_retracted; Height = 50; // same as bottomToolHeight in PlaySongSelect Children = new Drawable[] { leftContainer = new Container { + Origin = Anchor.TopLeft, + Anchor = Anchor.TopLeft, RelativeSizeAxes = Axes.Y, - Width = InitialExtendLength.X, + Width = initial_extend_length, Children = new Drawable[] { new Box { RelativeSizeAxes = Axes.Both, - Colour = colorDark, - Shear = new Vector2(0.1f, 0), + Colour = new Color4(195, 40, 140, 255), + Shear = new Vector2(shear, 0), }, icon = new TextAwesome { @@ -61,16 +66,16 @@ namespace osu.Game.Graphics.UserInterface Anchor = Anchor.TopLeft, RelativeSizeAxes = Axes.Y, Width = 80, - Position = Position + InitialExtendLength, + Position = Position + new Vector2(initial_extend_length, 0), Children = new Drawable[] { new Box { - Colour = colorBright, + Colour = new Color4(238, 51, 153, 255), Origin = Anchor.TopLeft, Anchor = Anchor.TopLeft, RelativeSizeAxes = Axes.Both, - Shear = new Vector2(0.1f, 0), + Shear = new Vector2(shear, 0), EdgeSmoothness = new Vector2(1.5f, 0), }, new SpriteText @@ -87,10 +92,10 @@ namespace osu.Game.Graphics.UserInterface { icon.ClearTransformations(); - rightContainer.MoveTo(Position + ExtendLength, transform_time, EasingTypes.OutElastic); - leftContainer.ResizeTo(new Vector2(ExtendLength.X, 1.0f), transform_time, EasingTypes.OutElastic); + rightContainer.MoveToX(Position.X + extend_length, transform_time, EasingTypes.OutElastic); + leftContainer.ResizeTo(new Vector2(extend_length, 1.0f), transform_time, EasingTypes.OutElastic); - Width = 140; // right container + ExtendLength + Width = width_extended; // right container + ExtendLength int duration = 0; //(int)(Game.Audio.BeatLength / 2); if (duration == 0) duration = pulse_length; @@ -117,10 +122,10 @@ namespace osu.Game.Graphics.UserInterface { icon.ClearTransformations(); - rightContainer.MoveTo(Position + InitialExtendLength, transform_time, EasingTypes.OutElastic); - leftContainer.ResizeTo(new Vector2(InitialExtendLength.X, 1.0f), transform_time, EasingTypes.OutElastic); + rightContainer.MoveToX(Position.X + initial_extend_length, transform_time, EasingTypes.OutElastic); + leftContainer.ResizeTo(new Vector2(initial_extend_length, 1.0f), transform_time, EasingTypes.OutElastic); - Width = 120; // right container + InitialExtendLength + Width = width_retracted; // right container + InitialExtendLength int duration = 0; //(int)(Game.Audio.BeatLength / 2); if (duration == 0) duration = pulse_length * 2; @@ -145,17 +150,12 @@ namespace osu.Game.Graphics.UserInterface { var flash = new Box { - RelativeSizeAxes = Axes.None, - Width = 140, - Height = 50, - Shear = new Vector2(0.1f, 0), - Colour = new Color4(255,255,255,255), - BlendingMode = BlendingMode.Additive, - Alpha = 0.3f + RelativeSizeAxes = Axes.Both, + Shear = new Vector2(shear, 0), + Colour = new Color4(255,255,255,128), }; Add(flash); - flash.ResizeTo(new Vector2(120, 50), transform_time, EasingTypes.OutElastic); flash.FadeOutFromOne(200); flash.Expire(); From 3526c299ecdd0625d10ff0b63fa5f6a3e426d242 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Nov 2016 16:24:37 +0900 Subject: [PATCH 070/133] Reformat code. --- osu.Game/Graphics/UserInterface/BackButton.cs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index f87e469b4a..0f904eec77 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -16,19 +16,19 @@ namespace osu.Game.Graphics.UserInterface { private TextAwesome icon; - private Container leftContainer; - private Container rightContainer; + private Container leftContainer; + private Container rightContainer; private const double transform_time = 300.0; - private const int pulse_length = 250; + private const int pulse_length = 250; private const float shear = 0.1f; - private const int extend_length = 60; - private const int initial_extend_length = 40; + private const int extend_length = 60; + private const int initial_extend_length = 40; - private const int width_extended = 140; - private const int width_retracted = 120; + private const int width_extended = 140; + private const int width_retracted = 120; public BackButton() { @@ -44,7 +44,7 @@ namespace osu.Game.Graphics.UserInterface Anchor = Anchor.TopLeft, RelativeSizeAxes = Axes.Y, Width = initial_extend_length, - Children = new Drawable[] + Children = new Drawable[] { new Box { @@ -75,8 +75,8 @@ namespace osu.Game.Graphics.UserInterface Origin = Anchor.TopLeft, Anchor = Anchor.TopLeft, RelativeSizeAxes = Axes.Both, - Shear = new Vector2(shear, 0), - EdgeSmoothness = new Vector2(1.5f, 0), + Shear = new Vector2(shear, 0), + EdgeSmoothness = new Vector2(1.5f, 0), }, new SpriteText { @@ -152,7 +152,7 @@ namespace osu.Game.Graphics.UserInterface { RelativeSizeAxes = Axes.Both, Shear = new Vector2(shear, 0), - Colour = new Color4(255,255,255,128), + Colour = new Color4(255, 255, 255, 128), }; Add(flash); From 1c2770ab36784cd240b3c5d24d9d1fbfd1825bbf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Nov 2016 16:25:06 +0900 Subject: [PATCH 071/133] Reset framework to sane version. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index cc28af53d9..e125c03d8c 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit cc28af53d93e2f1c5f0707c5616ed601e0cf9339 +Subproject commit e125c03d8c39fd86e02e872a8d46654d2ea2759f From a47507fff3e7f433f7dbc06d9cf10c492b9663ff Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Nov 2016 16:54:54 +0900 Subject: [PATCH 072/133] Remove redundant property assignments. --- osu.Game/Graphics/UserInterface/BackButton.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index 0f904eec77..7b3d011a7c 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -32,7 +32,6 @@ namespace osu.Game.Graphics.UserInterface public BackButton() { - RelativeSizeAxes = Axes.None; Width = width_retracted; Height = 50; // same as bottomToolHeight in PlaySongSelect @@ -40,8 +39,6 @@ namespace osu.Game.Graphics.UserInterface { leftContainer = new Container { - Origin = Anchor.TopLeft, - Anchor = Anchor.TopLeft, RelativeSizeAxes = Axes.Y, Width = initial_extend_length, Children = new Drawable[] From 987196011230f95b7c50f29eba4108283bd41d4d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Nov 2016 15:41:48 +0900 Subject: [PATCH 073/133] Basic score flow. --- osu.Game.Mode.Osu/OsuRuleset.cs | 2 ++ osu.Game.Mode.Osu/OsuScore.cs | 12 ++++++++++++ osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj | 1 + osu.Game.Modes.Catch/CatchRuleset.cs | 2 ++ osu.Game.Modes.Mania/ManiaRuleset.cs | 2 ++ osu.Game.Modes.Taiko/TaikoRuleset.cs | 3 +++ osu.Game/Modes/Ruleset.cs | 2 ++ osu.Game/Modes/Score.cs | 17 +++++++++++++++++ osu.Game/Modes/UI/ScoreOverlay.cs | 1 + osu.Game/Screens/Play/Player.cs | 11 +++++++++++ osu.Game/Screens/Ranking/Results.cs | 3 +++ osu.Game/osu.Game.csproj | 1 + 12 files changed, 57 insertions(+) create mode 100644 osu.Game.Mode.Osu/OsuScore.cs create mode 100644 osu.Game/Modes/Score.cs diff --git a/osu.Game.Mode.Osu/OsuRuleset.cs b/osu.Game.Mode.Osu/OsuRuleset.cs index ac43e5501c..c7cfd63297 100644 --- a/osu.Game.Mode.Osu/OsuRuleset.cs +++ b/osu.Game.Mode.Osu/OsuRuleset.cs @@ -17,6 +17,8 @@ namespace osu.Game.Modes.Osu public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser(); + public override Score CreateScore() => new OsuScore(); + protected override PlayMode PlayMode => PlayMode.Osu; } } diff --git a/osu.Game.Mode.Osu/OsuScore.cs b/osu.Game.Mode.Osu/OsuScore.cs new file mode 100644 index 0000000000..5a70cea434 --- /dev/null +++ b/osu.Game.Mode.Osu/OsuScore.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace osu.Game.Modes.Osu +{ + class OsuScore : Score + { + } +} diff --git a/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj b/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj index 97b4ebcb99..c27f75f9c5 100644 --- a/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj +++ b/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj @@ -53,6 +53,7 @@ + diff --git a/osu.Game.Modes.Catch/CatchRuleset.cs b/osu.Game.Modes.Catch/CatchRuleset.cs index 0195859cb7..08b472f1e2 100644 --- a/osu.Game.Modes.Catch/CatchRuleset.cs +++ b/osu.Game.Modes.Catch/CatchRuleset.cs @@ -18,6 +18,8 @@ namespace osu.Game.Modes.Catch protected override PlayMode PlayMode => PlayMode.Catch; + public override Score CreateScore() => new Score(); + public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser(); } } diff --git a/osu.Game.Modes.Mania/ManiaRuleset.cs b/osu.Game.Modes.Mania/ManiaRuleset.cs index cb122084df..85e50b661e 100644 --- a/osu.Game.Modes.Mania/ManiaRuleset.cs +++ b/osu.Game.Modes.Mania/ManiaRuleset.cs @@ -19,6 +19,8 @@ namespace osu.Game.Modes.Mania protected override PlayMode PlayMode => PlayMode.Mania; + public override Score CreateScore() => new Score(); + public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser(); } } diff --git a/osu.Game.Modes.Taiko/TaikoRuleset.cs b/osu.Game.Modes.Taiko/TaikoRuleset.cs index fa9d0862c7..51be717e04 100644 --- a/osu.Game.Modes.Taiko/TaikoRuleset.cs +++ b/osu.Game.Modes.Taiko/TaikoRuleset.cs @@ -1,6 +1,7 @@ //Copyright (c) 2007-2016 ppy Pty Ltd . //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Collections.Generic; using osu.Game.Modes.Objects; using osu.Game.Modes.Osu.Objects; @@ -18,6 +19,8 @@ namespace osu.Game.Modes.Taiko protected override PlayMode PlayMode => PlayMode.Taiko; + public override Score CreateScore() => new Score(); + public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser(); } } diff --git a/osu.Game/Modes/Ruleset.cs b/osu.Game/Modes/Ruleset.cs index d35aab6568..2b52bbc1b1 100644 --- a/osu.Game/Modes/Ruleset.cs +++ b/osu.Game/Modes/Ruleset.cs @@ -18,6 +18,8 @@ namespace osu.Game.Modes public abstract ScoreOverlay CreateScoreOverlay(); + public abstract Score CreateScore(); + public abstract HitRenderer CreateHitRendererWith(List objects); public abstract HitObjectParser CreateHitObjectParser(); diff --git a/osu.Game/Modes/Score.cs b/osu.Game/Modes/Score.cs new file mode 100644 index 0000000000..88d79f94dd --- /dev/null +++ b/osu.Game/Modes/Score.cs @@ -0,0 +1,17 @@ +//Copyright (c) 2007-2016 ppy Pty Ltd . +//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace osu.Game.Modes +{ + public class Score + { + public double TotalScore { get; } + public double Accuracy { get; } + } +} diff --git a/osu.Game/Modes/UI/ScoreOverlay.cs b/osu.Game/Modes/UI/ScoreOverlay.cs index 2270533d47..31f6ebdcca 100644 --- a/osu.Game/Modes/UI/ScoreOverlay.cs +++ b/osu.Game/Modes/UI/ScoreOverlay.cs @@ -15,6 +15,7 @@ namespace osu.Game.Modes.UI public ComboCounter ComboCounter; public ScoreCounter ScoreCounter; public PercentageCounter AccuracyCounter; + public Score Score { get; set; } protected abstract KeyCounterCollection CreateKeyCounter(); protected abstract ComboCounter CreateComboCounter(); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 66cec7405e..590412b83a 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -19,6 +19,7 @@ using OpenTK.Input; using MouseState = osu.Framework.Input.MouseState; using OpenTK; using osu.Framework.GameModes; +using osu.Game.Screens.Ranking; namespace osu.Game.Screens.Play { @@ -36,6 +37,8 @@ namespace osu.Game.Screens.Play private IAdjustableClock sourceClock; + private Score score; + private Ruleset ruleset; [BackgroundDependencyLoader] @@ -84,6 +87,8 @@ namespace osu.Game.Screens.Play ruleset = Ruleset.GetRuleset(usablePlayMode); var scoreOverlay = ruleset.CreateScoreOverlay(); + scoreOverlay.Score = (score = ruleset.CreateScore()); + var hitRenderer = ruleset.CreateHitRendererWith(beatmap.HitObjects); hitRenderer.OnHit += delegate (HitObject h) { scoreOverlay.OnHit(h); }; @@ -117,6 +122,12 @@ namespace osu.Game.Screens.Play { base.Update(); Clock.ProcessFrame(); + + if (Beatmap.Track.HasCompleted) + Push(new Results + { + Score = score + }); } class PlayerInputManager : UserInputManager diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index b1d55ab54a..55f2d4fe2b 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -2,6 +2,7 @@ //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.GameModes; +using osu.Game.Modes; using osu.Game.Screens.Backgrounds; using OpenTK.Graphics; @@ -22,5 +23,7 @@ namespace osu.Game.Screens.Ranking Background.Schedule(() => Background.FadeColour(Color4.White, 500)); return base.OnExiting(next); } + + public Score Score { get; set; } } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index c35bafb251..90bea8c033 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -66,6 +66,7 @@ + From 139fe873f3d3833325a90d400926100595fef70f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Nov 2016 18:35:40 +0900 Subject: [PATCH 074/133] Remove silly weld weld weld. --- .../UserInterface/Volume/VolumeControl.cs | 27 +++++++------------ 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs b/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs index c94eb40c17..13accc4914 100644 --- a/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs +++ b/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs @@ -14,10 +14,6 @@ namespace osu.Game.Graphics.UserInterface.Volume { internal class VolumeControl : OverlayContainer { - private BindableDouble volumeGlobal = new BindableDouble(); - private BindableDouble volumeSample = new BindableDouble(); - private BindableDouble volumeTrack = new BindableDouble(); - private VolumeMeter volumeMeterMaster; private void volumeChanged(object sender, EventArgs e) @@ -55,21 +51,18 @@ namespace osu.Game.Graphics.UserInterface.Volume { base.LoadComplete(); - volumeGlobal.ValueChanged += volumeChanged; - volumeSample.ValueChanged += volumeChanged; - volumeTrack.ValueChanged += volumeChanged; - - volumeMeterMaster.Bindable.Weld(volumeGlobal); - volumeMeterEffect.Bindable.Weld(volumeSample); - volumeMeterMusic.Bindable.Weld(volumeTrack); + volumeMeterMaster.Bindable.ValueChanged += volumeChanged; + volumeMeterEffect.Bindable.ValueChanged += volumeChanged; + volumeMeterMusic.Bindable.ValueChanged += volumeChanged; } protected override void Dispose(bool isDisposing) { - volumeGlobal.ValueChanged -= volumeChanged; - volumeSample.ValueChanged -= volumeChanged; - volumeTrack.ValueChanged -= volumeChanged; base.Dispose(isDisposing); + + volumeMeterMaster.Bindable.ValueChanged -= volumeChanged; + volumeMeterEffect.Bindable.ValueChanged -= volumeChanged; + volumeMeterMusic.Bindable.ValueChanged -= volumeChanged; } public void Adjust(InputState state) @@ -86,9 +79,9 @@ namespace osu.Game.Graphics.UserInterface.Volume [BackgroundDependencyLoader] private void load(AudioManager audio) { - volumeGlobal.Weld(audio.Volume); - volumeSample.Weld(audio.VolumeSample); - volumeTrack.Weld(audio.VolumeTrack); + volumeMeterMaster.Bindable.Weld(audio.Volume); + volumeMeterEffect.Bindable.Weld(audio.VolumeSample); + volumeMeterMusic.Bindable.Weld(audio.VolumeTrack); } ScheduledDelegate popOutDelegate; From fa80cc84f83e4af868e61dc666dd144f6be1c63d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Nov 2016 18:35:59 +0900 Subject: [PATCH 075/133] Fix volume control fill being incorrect on first display. --- osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs b/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs index 230066cf9b..4416a1da80 100644 --- a/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs +++ b/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs @@ -41,6 +41,7 @@ namespace osu.Game.Graphics.UserInterface.Volume meterFill = new Box { Colour = Color4.White, + Scale = new Vector2(1, 0), RelativeSizeAxes = Axes.Both, Origin = Anchor.BottomCentre, Anchor = Anchor.BottomCentre @@ -54,6 +55,8 @@ namespace osu.Game.Graphics.UserInterface.Volume Origin = Anchor.TopCentre } }; + + Bindable.ValueChanged += delegate { updateFill(); }; } protected override void LoadComplete() @@ -68,7 +71,6 @@ namespace osu.Game.Graphics.UserInterface.Volume private set { Bindable.Value = value; - updateFill(); } } From fbf35c904d503ff4b9be4317f0b7bc74bbbee373 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Nov 2016 18:49:03 +0900 Subject: [PATCH 076/133] Fix Config regression with DI. --- osu.Game/OsuGameBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 2f3e5025b7..f58e868e1c 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -41,7 +41,7 @@ namespace osu.Game private void load() { Dependencies.Cache(this); - Dependencies.Cache(new OsuConfigManager(Host.Storage)); + Dependencies.Cache(Config); Dependencies.Cache(new BeatmapDatabase(Host.Storage, Host)); //this completely overrides the framework default. will need to change once we make a proper FontStore. From 9d2a69f1e2139bd61a5750b9b9a83a9d99db1f9b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Nov 2016 20:30:16 +0900 Subject: [PATCH 077/133] Add concept of ScoreProcessor. --- osu.Game.Mode.Osu/OsuRuleset.cs | 2 +- osu.Game.Mode.Osu/OsuScoreProcessor.cs | 12 ++++++++++++ osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj | 1 + osu.Game.Modes.Catch/CatchRuleset.cs | 2 +- osu.Game.Modes.Mania/ManiaRuleset.cs | 2 +- osu.Game.Modes.Taiko/TaikoRuleset.cs | 2 +- osu.Game/Modes/Ruleset.cs | 2 +- osu.Game/Modes/ScoreProcesssor.cs | 16 ++++++++++++++++ osu.Game/Modes/UI/ScoreOverlay.cs | 5 +++++ osu.Game/Screens/Play/Player.cs | 8 ++++---- osu.Game/osu.Game.csproj | 1 + 11 files changed, 44 insertions(+), 9 deletions(-) create mode 100644 osu.Game.Mode.Osu/OsuScoreProcessor.cs create mode 100644 osu.Game/Modes/ScoreProcesssor.cs diff --git a/osu.Game.Mode.Osu/OsuRuleset.cs b/osu.Game.Mode.Osu/OsuRuleset.cs index c7cfd63297..15799b134a 100644 --- a/osu.Game.Mode.Osu/OsuRuleset.cs +++ b/osu.Game.Mode.Osu/OsuRuleset.cs @@ -17,7 +17,7 @@ namespace osu.Game.Modes.Osu public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser(); - public override Score CreateScore() => new OsuScore(); + public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor(); protected override PlayMode PlayMode => PlayMode.Osu; } diff --git a/osu.Game.Mode.Osu/OsuScoreProcessor.cs b/osu.Game.Mode.Osu/OsuScoreProcessor.cs new file mode 100644 index 0000000000..8ff053f96f --- /dev/null +++ b/osu.Game.Mode.Osu/OsuScoreProcessor.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace osu.Game.Modes.Osu +{ + class OsuScoreProcessor : ScoreProcessor + { + } +} diff --git a/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj b/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj index c27f75f9c5..cca903643b 100644 --- a/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj +++ b/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj @@ -54,6 +54,7 @@ + diff --git a/osu.Game.Modes.Catch/CatchRuleset.cs b/osu.Game.Modes.Catch/CatchRuleset.cs index 08b472f1e2..695bca2593 100644 --- a/osu.Game.Modes.Catch/CatchRuleset.cs +++ b/osu.Game.Modes.Catch/CatchRuleset.cs @@ -18,7 +18,7 @@ namespace osu.Game.Modes.Catch protected override PlayMode PlayMode => PlayMode.Catch; - public override Score CreateScore() => new Score(); + public override ScoreProcessor CreateScoreProcessor() => new ScoreProcessor(); public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser(); } diff --git a/osu.Game.Modes.Mania/ManiaRuleset.cs b/osu.Game.Modes.Mania/ManiaRuleset.cs index 85e50b661e..0e7761e8fb 100644 --- a/osu.Game.Modes.Mania/ManiaRuleset.cs +++ b/osu.Game.Modes.Mania/ManiaRuleset.cs @@ -19,7 +19,7 @@ namespace osu.Game.Modes.Mania protected override PlayMode PlayMode => PlayMode.Mania; - public override Score CreateScore() => new Score(); + public override ScoreProcessor CreateScoreProcessor() => new ScoreProcessor(); public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser(); } diff --git a/osu.Game.Modes.Taiko/TaikoRuleset.cs b/osu.Game.Modes.Taiko/TaikoRuleset.cs index 51be717e04..3e697e48ea 100644 --- a/osu.Game.Modes.Taiko/TaikoRuleset.cs +++ b/osu.Game.Modes.Taiko/TaikoRuleset.cs @@ -19,7 +19,7 @@ namespace osu.Game.Modes.Taiko protected override PlayMode PlayMode => PlayMode.Taiko; - public override Score CreateScore() => new Score(); + public override ScoreProcessor CreateScoreProcessor() => new ScoreProcessor(); public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser(); } diff --git a/osu.Game/Modes/Ruleset.cs b/osu.Game/Modes/Ruleset.cs index 2b52bbc1b1..b0304f6576 100644 --- a/osu.Game/Modes/Ruleset.cs +++ b/osu.Game/Modes/Ruleset.cs @@ -18,7 +18,7 @@ namespace osu.Game.Modes public abstract ScoreOverlay CreateScoreOverlay(); - public abstract Score CreateScore(); + public abstract ScoreProcessor CreateScoreProcessor(); public abstract HitRenderer CreateHitRendererWith(List objects); diff --git a/osu.Game/Modes/ScoreProcesssor.cs b/osu.Game/Modes/ScoreProcesssor.cs new file mode 100644 index 0000000000..9d7eace60e --- /dev/null +++ b/osu.Game/Modes/ScoreProcesssor.cs @@ -0,0 +1,16 @@ +//Copyright (c) 2007-2016 ppy Pty Ltd . +//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace osu.Game.Modes +{ + public class ScoreProcessor + { + public virtual Score GetScore() => new Score(); + } +} diff --git a/osu.Game/Modes/UI/ScoreOverlay.cs b/osu.Game/Modes/UI/ScoreOverlay.cs index 31f6ebdcca..9f29ff63ff 100644 --- a/osu.Game/Modes/UI/ScoreOverlay.cs +++ b/osu.Game/Modes/UI/ScoreOverlay.cs @@ -46,5 +46,10 @@ namespace osu.Game.Modes.UI AccuracyCounter = CreateAccuracyCounter(), }; } + + public void BindProcessor(ScoreProcessor processor) + { + + } } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 590412b83a..262e5c5fbc 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -37,10 +37,10 @@ namespace osu.Game.Screens.Play private IAdjustableClock sourceClock; - private Score score; - private Ruleset ruleset; + private ScoreProcessor scoreProcessor; + [BackgroundDependencyLoader] private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuGameBase game) { @@ -87,7 +87,7 @@ namespace osu.Game.Screens.Play ruleset = Ruleset.GetRuleset(usablePlayMode); var scoreOverlay = ruleset.CreateScoreOverlay(); - scoreOverlay.Score = (score = ruleset.CreateScore()); + scoreOverlay.BindProcessor(scoreProcessor = ruleset.CreateScoreProcessor()); var hitRenderer = ruleset.CreateHitRendererWith(beatmap.HitObjects); @@ -126,7 +126,7 @@ namespace osu.Game.Screens.Play if (Beatmap.Track.HasCompleted) Push(new Results { - Score = score + Score = scoreProcessor.GetScore() }); } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 90bea8c033..af8feebe9a 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -67,6 +67,7 @@ + From 9b243ccc2346dfc134d6dbf62251765e3471dbc7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Nov 2016 21:28:22 +0900 Subject: [PATCH 078/133] Remove Hit500. --- osu.Game.Mode.Osu/Objects/Drawables/DrawableOsuHitObject.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 0e3a03665c..80e1f2bb7f 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -74,7 +74,5 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Hit100, [Description(@"300")] Hit300, - [Description(@"500")] - Hit500 } } From 2947121e482c035cb7c2bdd6e24abc659b93d8d8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Nov 2016 21:28:43 +0900 Subject: [PATCH 079/133] Hook up ScoreProcessor to Scoreoverlay etc. --- osu.Game.Mode.Osu/OsuScoreProcessor.cs | 50 +++++++++++++++++++ .../Objects/Drawables/DrawableHitObject.cs | 8 ++- osu.Game/Modes/ScoreProcesssor.cs | 24 +++++++++ osu.Game/Modes/UI/ComboCounter.cs | 8 +++ osu.Game/Modes/UI/HitRenderer.cs | 18 ++----- osu.Game/Modes/UI/ScoreOverlay.cs | 5 +- osu.Game/Screens/Play/Player.cs | 3 +- 7 files changed, 95 insertions(+), 21 deletions(-) diff --git a/osu.Game.Mode.Osu/OsuScoreProcessor.cs b/osu.Game.Mode.Osu/OsuScoreProcessor.cs index 8ff053f96f..177844297e 100644 --- a/osu.Game.Mode.Osu/OsuScoreProcessor.cs +++ b/osu.Game.Mode.Osu/OsuScoreProcessor.cs @@ -3,10 +3,60 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using osu.Game.Modes.Objects.Drawables; +using osu.Game.Modes.Osu.Objects.Drawables; namespace osu.Game.Modes.Osu { class OsuScoreProcessor : ScoreProcessor { + public override void AddJudgement(JudgementInfo judgement) + { + base.AddJudgement(judgement); + + switch (judgement.Result) + { + case HitResult.Hit: + Combo.Value++; + break; + case HitResult.Miss: + Combo.Value = 0; + break; + } + } + protected override void UpdateCalculations() + { + base.UpdateCalculations(); + + int score = 0; + int maxScore = 0; + + foreach (OsuJudgementInfo j in Judgements) + { + switch (j.Score) + { + case OsuScoreResult.Miss: + maxScore += 300; + break; + case OsuScoreResult.Hit50: + score += 50; + maxScore += 300; + break; + case OsuScoreResult.Hit100: + score += 100; + maxScore += 300; + break; + case OsuScoreResult.Hit300: + score += 300; + maxScore += 300; + break; + } + + + } + + TotalScore.Value = score; + Accuracy.Value = (double)score / maxScore; + } } } diff --git a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs index 3508d6c3a6..f00a24d79e 100644 --- a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs @@ -13,9 +13,7 @@ namespace osu.Game.Modes.Objects.Drawables { public abstract class DrawableHitObject : Container, IStateful { - //todo: move to a more central implementation. this logic should not be at a drawable level. - public Action OnHit; - public Action OnMiss; + public event Action OnJudgement; public Container ChildObjects; @@ -73,14 +71,14 @@ namespace osu.Game.Modes.Objects.Drawables { default: State = ArmedState.Hit; - OnHit?.Invoke(this, Judgement); break; case HitResult.Miss: State = ArmedState.Miss; - OnMiss?.Invoke(this, Judgement); break; } + OnJudgement?.Invoke(this, Judgement); + return true; } diff --git a/osu.Game/Modes/ScoreProcesssor.cs b/osu.Game/Modes/ScoreProcesssor.cs index 9d7eace60e..efae0bd40b 100644 --- a/osu.Game/Modes/ScoreProcesssor.cs +++ b/osu.Game/Modes/ScoreProcesssor.cs @@ -6,11 +6,35 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using osu.Framework.Configuration; +using osu.Game.Modes.Objects.Drawables; namespace osu.Game.Modes { public class ScoreProcessor { public virtual Score GetScore() => new Score(); + + public BindableDouble TotalScore = new BindableDouble { MinValue = 0 }; + + public BindableDouble Accuracy = new BindableDouble { MinValue = 0, MaxValue = 1 }; + + public BindableInt Combo = new BindableInt(); + + public List Judgements = new List(); + + public virtual void AddJudgement(JudgementInfo judgement) + { + Judgements.Add(judgement); + UpdateCalculations(); + } + + /// + /// Update any values that potentially need post-processing on a judgement change. + /// + protected virtual void UpdateCalculations() + { + + } } } diff --git a/osu.Game/Modes/UI/ComboCounter.cs b/osu.Game/Modes/UI/ComboCounter.cs index 0d34d5dd9a..b150111387 100644 --- a/osu.Game/Modes/UI/ComboCounter.cs +++ b/osu.Game/Modes/UI/ComboCounter.cs @@ -262,5 +262,13 @@ namespace osu.Game.Modes.UI (d as ComboCounter).DisplayedCount = CurrentValue; } } + + public void Set(ulong value) + { + if (value == 0) + Roll(); + else + Count = value; + } } } diff --git a/osu.Game/Modes/UI/HitRenderer.cs b/osu.Game/Modes/UI/HitRenderer.cs index d37cf545a8..5d70fd71a0 100644 --- a/osu.Game/Modes/UI/HitRenderer.cs +++ b/osu.Game/Modes/UI/HitRenderer.cs @@ -14,8 +14,9 @@ namespace osu.Game.Modes.UI { public abstract class HitRenderer : Container { - public Action OnHit; - public Action OnMiss; + public event Action OnJudgement; + + protected void TriggerOnJudgement(JudgementInfo j) => OnJudgement?.Invoke(j); protected Playfield Playfield; @@ -68,22 +69,13 @@ namespace osu.Game.Modes.UI if (drawableObject == null) continue; - drawableObject.OnHit = onHit; - drawableObject.OnMiss = onMiss; + drawableObject.OnJudgement += onJudgement; Playfield.Add(drawableObject); } } - private void onMiss(DrawableHitObject obj, JudgementInfo judgement) - { - OnMiss?.Invoke(obj.HitObject); - } - - private void onHit(DrawableHitObject obj, JudgementInfo judgement) - { - OnHit?.Invoke(obj.HitObject); - } + private void onJudgement(DrawableHitObject o, JudgementInfo j) => TriggerOnJudgement(j); protected abstract DrawableHitObject GetVisualRepresentation(T h); } diff --git a/osu.Game/Modes/UI/ScoreOverlay.cs b/osu.Game/Modes/UI/ScoreOverlay.cs index 9f29ff63ff..c7441483f8 100644 --- a/osu.Game/Modes/UI/ScoreOverlay.cs +++ b/osu.Game/Modes/UI/ScoreOverlay.cs @@ -49,7 +49,10 @@ namespace osu.Game.Modes.UI public void BindProcessor(ScoreProcessor processor) { - + //bind processor bindables to combocounter, score display etc. + processor.TotalScore.ValueChanged += delegate { ScoreCounter?.Set((ulong)processor.TotalScore.Value); }; + processor.Accuracy.ValueChanged += delegate { AccuracyCounter?.Set((float)processor.Accuracy.Value); }; + processor.Combo.ValueChanged += delegate { ComboCounter?.Set((ulong)processor.Combo.Value); }; } } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 262e5c5fbc..1fa652afec 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -91,8 +91,7 @@ namespace osu.Game.Screens.Play var hitRenderer = ruleset.CreateHitRendererWith(beatmap.HitObjects); - hitRenderer.OnHit += delegate (HitObject h) { scoreOverlay.OnHit(h); }; - hitRenderer.OnMiss += delegate (HitObject h) { scoreOverlay.OnMiss(h); }; + hitRenderer.OnJudgement += scoreProcessor.AddJudgement; if (Autoplay) hitRenderer.Schedule(() => hitRenderer.DrawableObjects.ForEach(h => h.State = ArmedState.Hit)); From a0503bd13fac41f8ddb4348b295a1abbc148f8aa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Nov 2016 21:29:53 +0900 Subject: [PATCH 080/133] Tidy up Slider class. --- .../Objects/BezierApproximator.cs | 148 ++++++++++++++ osu.Game.Mode.Osu/Objects/Slider.cs | 184 ------------------ osu.Game.Mode.Osu/Objects/SliderCurve.cs | 44 +++++ osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj | 2 + 4 files changed, 194 insertions(+), 184 deletions(-) create mode 100644 osu.Game.Mode.Osu/Objects/BezierApproximator.cs create mode 100644 osu.Game.Mode.Osu/Objects/SliderCurve.cs diff --git a/osu.Game.Mode.Osu/Objects/BezierApproximator.cs b/osu.Game.Mode.Osu/Objects/BezierApproximator.cs new file mode 100644 index 0000000000..f08b7aa377 --- /dev/null +++ b/osu.Game.Mode.Osu/Objects/BezierApproximator.cs @@ -0,0 +1,148 @@ +using System.Collections.Generic; +using OpenTK; + +namespace osu.Game.Modes.Osu.Objects +{ + public class BezierApproximator + { + private int count; + private List controlPoints; + private Vector2[] subdivisionBuffer1; + private Vector2[] subdivisionBuffer2; + + private const float TOLERANCE = 0.5f; + private const float TOLERANCE_SQ = TOLERANCE * TOLERANCE; + + public BezierApproximator(List controlPoints) + { + this.controlPoints = controlPoints; + count = controlPoints.Count; + + subdivisionBuffer1 = new Vector2[count]; + subdivisionBuffer2 = new Vector2[count * 2 - 1]; + } + + /// + /// Make sure the 2nd order derivative (approximated using finite elements) is within tolerable bounds. + /// NOTE: The 2nd order derivative of a 2d curve represents its curvature, so intuitively this function + /// checks (as the name suggests) whether our approximation is _locally_ "flat". More curvy parts + /// need to have a denser approximation to be more "flat". + /// + /// The control points to check for flatness. + /// Whether the control points are flat enough. + private static bool IsFlatEnough(Vector2[] controlPoints) + { + for (int i = 1; i < controlPoints.Length - 1; i++) + if ((controlPoints[i - 1] - 2 * controlPoints[i] + controlPoints[i + 1]).LengthSquared > TOLERANCE_SQ) + return false; + + return true; + } + + /// + /// Subdivides n control points representing a bezier curve into 2 sets of n control points, each + /// describing a bezier curve equivalent to a half of the original curve. Effectively this splits + /// the original curve into 2 curves which result in the original curve when pieced back together. + /// + /// The control points to split. + /// Output: The control points corresponding to the left half of the curve. + /// Output: The control points corresponding to the right half of the curve. + private void Subdivide(Vector2[] controlPoints, Vector2[] l, Vector2[] r) + { + Vector2[] midpoints = subdivisionBuffer1; + + for (int i = 0; i < count; ++i) + midpoints[i] = controlPoints[i]; + + for (int i = 0; i < count; i++) + { + l[i] = midpoints[0]; + r[count - i - 1] = midpoints[count - i - 1]; + + for (int j = 0; j < count - i - 1; j++) + midpoints[j] = (midpoints[j] + midpoints[j + 1]) / 2; + } + } + + /// + /// This uses De Casteljau's algorithm to obtain an optimal + /// piecewise-linear approximation of the bezier curve with the same amount of points as there are control points. + /// + /// The control points describing the bezier curve to be approximated. + /// The points representing the resulting piecewise-linear approximation. + private void Approximate(Vector2[] controlPoints, List output) + { + Vector2[] l = subdivisionBuffer2; + Vector2[] r = subdivisionBuffer1; + + Subdivide(controlPoints, l, r); + + for (int i = 0; i < count - 1; ++i) + l[count + i] = r[i + 1]; + + output.Add(controlPoints[0]); + for (int i = 1; i < count - 1; ++i) + { + int index = 2 * i; + Vector2 p = 0.25f * (l[index - 1] + 2 * l[index] + l[index + 1]); + output.Add(p); + } + } + + /// + /// Creates a piecewise-linear approximation of a bezier curve, by adaptively repeatedly subdividing + /// the control points until their approximation error vanishes below a given threshold. + /// + /// The control points describing the curve. + /// A list of vectors representing the piecewise-linear approximation. + public List CreateBezier() + { + List output = new List(); + + if (count == 0) + return output; + + Stack toFlatten = new Stack(); + Stack freeBuffers = new Stack(); + + // "toFlatten" contains all the curves which are not yet approximated well enough. + // We use a stack to emulate recursion without the risk of running into a stack overflow. + // (More specifically, we iteratively and adaptively refine our curve with a + // Depth-first search + // over the tree resulting from the subdivisions we make.) + toFlatten.Push(controlPoints.ToArray()); + + Vector2[] leftChild = subdivisionBuffer2; + + while (toFlatten.Count > 0) + { + Vector2[] parent = toFlatten.Pop(); + if (IsFlatEnough(parent)) + { + // If the control points we currently operate on are sufficiently "flat", we use + // an extension to De Casteljau's algorithm to obtain a piecewise-linear approximation + // of the bezier curve represented by our control points, consisting of the same amount + // of points as there are control points. + Approximate(parent, output); + freeBuffers.Push(parent); + continue; + } + + // If we do not yet have a sufficiently "flat" (in other words, detailed) approximation we keep + // subdividing the curve we are currently operating on. + Vector2[] rightChild = freeBuffers.Count > 0 ? freeBuffers.Pop() : new Vector2[count]; + Subdivide(parent, leftChild, rightChild); + + // We re-use the buffer of the parent for one of the children, so that we save one allocation per iteration. + for (int i = 0; i < count; ++i) + parent[i] = leftChild[i]; + + toFlatten.Push(rightChild); + toFlatten.Push(parent); + } + + output.Add(controlPoints[count - 1]); + return output; + } + } +} \ No newline at end of file diff --git a/osu.Game.Mode.Osu/Objects/Slider.cs b/osu.Game.Mode.Osu/Objects/Slider.cs index 7ee131659a..a0cdbeae7c 100644 --- a/osu.Game.Mode.Osu/Objects/Slider.cs +++ b/osu.Game.Mode.Osu/Objects/Slider.cs @@ -1,9 +1,7 @@ //Copyright (c) 2007-2016 ppy Pty Ltd . //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; using osu.Game.Database; -using OpenTK; using osu.Game.Beatmaps; using System; @@ -25,188 +23,6 @@ namespace osu.Game.Modes.Osu.Objects public SliderCurve Curve; } - public class SliderCurve - { - public double Length; - - public List Path; - - public CurveTypes CurveType; - - private List calculatedPath; - - public void Calculate() - { - switch (CurveType) - { - case CurveTypes.Linear: - calculatedPath = Path; - break; - default: - var bezier = new BezierApproximator(Path); - calculatedPath = bezier.CreateBezier(); - break; - } - } - - public Vector2 PositionAt(double progress) - { - progress = MathHelper.Clamp(progress, 0, 1); - - double index = progress * (calculatedPath.Count - 1); - int flooredIndex = (int)index; - - Vector2 pos = calculatedPath[flooredIndex]; - if (index != flooredIndex) - pos += (calculatedPath[flooredIndex + 1] - pos) * (float)(index - flooredIndex); - - return pos; - } - } - - public class BezierApproximator - { - private int count; - private List controlPoints; - private Vector2[] subdivisionBuffer1; - private Vector2[] subdivisionBuffer2; - - private const float TOLERANCE = 0.5f; - private const float TOLERANCE_SQ = TOLERANCE * TOLERANCE; - - public BezierApproximator(List controlPoints) - { - this.controlPoints = controlPoints; - count = controlPoints.Count; - - subdivisionBuffer1 = new Vector2[count]; - subdivisionBuffer2 = new Vector2[count * 2 - 1]; - } - - /// - /// Make sure the 2nd order derivative (approximated using finite elements) is within tolerable bounds. - /// NOTE: The 2nd order derivative of a 2d curve represents its curvature, so intuitively this function - /// checks (as the name suggests) whether our approximation is _locally_ "flat". More curvy parts - /// need to have a denser approximation to be more "flat". - /// - /// The control points to check for flatness. - /// Whether the control points are flat enough. - private static bool IsFlatEnough(Vector2[] controlPoints) - { - for (int i = 1; i < controlPoints.Length - 1; i++) - if ((controlPoints[i - 1] - 2 * controlPoints[i] + controlPoints[i + 1]).LengthSquared > TOLERANCE_SQ) - return false; - - return true; - } - - /// - /// Subdivides n control points representing a bezier curve into 2 sets of n control points, each - /// describing a bezier curve equivalent to a half of the original curve. Effectively this splits - /// the original curve into 2 curves which result in the original curve when pieced back together. - /// - /// The control points to split. - /// Output: The control points corresponding to the left half of the curve. - /// Output: The control points corresponding to the right half of the curve. - private void Subdivide(Vector2[] controlPoints, Vector2[] l, Vector2[] r) - { - Vector2[] midpoints = subdivisionBuffer1; - - for (int i = 0; i < count; ++i) - midpoints[i] = controlPoints[i]; - - for (int i = 0; i < count; i++) - { - l[i] = midpoints[0]; - r[count - i - 1] = midpoints[count - i - 1]; - - for (int j = 0; j < count - i - 1; j++) - midpoints[j] = (midpoints[j] + midpoints[j + 1]) / 2; - } - } - - /// - /// This uses De Casteljau's algorithm to obtain an optimal - /// piecewise-linear approximation of the bezier curve with the same amount of points as there are control points. - /// - /// The control points describing the bezier curve to be approximated. - /// The points representing the resulting piecewise-linear approximation. - private void Approximate(Vector2[] controlPoints, List output) - { - Vector2[] l = subdivisionBuffer2; - Vector2[] r = subdivisionBuffer1; - - Subdivide(controlPoints, l, r); - - for (int i = 0; i < count - 1; ++i) - l[count + i] = r[i + 1]; - - output.Add(controlPoints[0]); - for (int i = 1; i < count - 1; ++i) - { - int index = 2 * i; - Vector2 p = 0.25f * (l[index - 1] + 2 * l[index] + l[index + 1]); - output.Add(p); - } - } - - /// - /// Creates a piecewise-linear approximation of a bezier curve, by adaptively repeatedly subdividing - /// the control points until their approximation error vanishes below a given threshold. - /// - /// The control points describing the curve. - /// A list of vectors representing the piecewise-linear approximation. - public List CreateBezier() - { - List output = new List(); - - if (count == 0) - return output; - - Stack toFlatten = new Stack(); - Stack freeBuffers = new Stack(); - - // "toFlatten" contains all the curves which are not yet approximated well enough. - // We use a stack to emulate recursion without the risk of running into a stack overflow. - // (More specifically, we iteratively and adaptively refine our curve with a - // Depth-first search - // over the tree resulting from the subdivisions we make.) - toFlatten.Push(controlPoints.ToArray()); - - Vector2[] leftChild = subdivisionBuffer2; - - while (toFlatten.Count > 0) - { - Vector2[] parent = toFlatten.Pop(); - if (IsFlatEnough(parent)) - { - // If the control points we currently operate on are sufficiently "flat", we use - // an extension to De Casteljau's algorithm to obtain a piecewise-linear approximation - // of the bezier curve represented by our control points, consisting of the same amount - // of points as there are control points. - Approximate(parent, output); - freeBuffers.Push(parent); - continue; - } - - // If we do not yet have a sufficiently "flat" (in other words, detailed) approximation we keep - // subdividing the curve we are currently operating on. - Vector2[] rightChild = freeBuffers.Count > 0 ? freeBuffers.Pop() : new Vector2[count]; - Subdivide(parent, leftChild, rightChild); - - // We re-use the buffer of the parent for one of the children, so that we save one allocation per iteration. - for (int i = 0; i < count; ++i) - parent[i] = leftChild[i]; - - toFlatten.Push(rightChild); - toFlatten.Push(parent); - } - - output.Add(controlPoints[count - 1]); - return output; - } - } - public enum CurveTypes { Catmull, diff --git a/osu.Game.Mode.Osu/Objects/SliderCurve.cs b/osu.Game.Mode.Osu/Objects/SliderCurve.cs new file mode 100644 index 0000000000..98e25524da --- /dev/null +++ b/osu.Game.Mode.Osu/Objects/SliderCurve.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; +using OpenTK; + +namespace osu.Game.Modes.Osu.Objects +{ + public class SliderCurve + { + public double Length; + + public List Path; + + public CurveTypes CurveType; + + private List calculatedPath; + + public void Calculate() + { + switch (CurveType) + { + case CurveTypes.Linear: + calculatedPath = Path; + break; + default: + var bezier = new BezierApproximator(Path); + calculatedPath = bezier.CreateBezier(); + break; + } + } + + public Vector2 PositionAt(double progress) + { + progress = MathHelper.Clamp(progress, 0, 1); + + double index = progress * (calculatedPath.Count - 1); + int flooredIndex = (int)index; + + Vector2 pos = calculatedPath[flooredIndex]; + if (index != flooredIndex) + pos += (calculatedPath[flooredIndex + 1] - pos) * (float)(index - flooredIndex); + + return pos; + } + } +} \ No newline at end of file diff --git a/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj b/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj index cca903643b..ba6e714e0a 100644 --- a/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj +++ b/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj @@ -41,6 +41,7 @@ + @@ -53,6 +54,7 @@ + From f8c1f4dd582ea573060fee5fbb6e66cc1a9bb531 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Nov 2016 21:40:24 +0900 Subject: [PATCH 081/133] Add basic slider judgement handling. --- .../Objects/Drawables/DrawableSlider.cs | 12 ++++++++++++ .../Modes/Objects/Drawables/DrawableHitObject.cs | 4 ++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index 1d55d704c4..df79953eae 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -75,6 +75,18 @@ namespace osu.Game.Modes.Osu.Objects.Drawables ball.Position = slider.Curve.PositionAt(t); } + protected override void CheckJudgement(bool userTriggered) + { + var j = Judgement as OsuJudgementInfo; + var sc = startCircle.Judgement as OsuJudgementInfo; + + if (!userTriggered && Time.Current >= HitObject.EndTime) + { + j.Score = sc.Score; + j.Result = sc.Result; + } + } + protected override void UpdateState(ArmedState state) { base.UpdateState(state); diff --git a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs index f00a24d79e..53d3b1bafc 100644 --- a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs @@ -17,7 +17,7 @@ namespace osu.Game.Modes.Objects.Drawables public Container ChildObjects; - protected JudgementInfo Judgement; + public JudgementInfo Judgement; public abstract JudgementInfo CreateJudgementInfo(); @@ -84,7 +84,7 @@ namespace osu.Game.Modes.Objects.Drawables protected virtual void CheckJudgement(bool userTriggered) { - + //todo: consider making abstract. } protected override void Update() From 18d331f869026557df46ad9dfc6e1ac36f5924b6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Nov 2016 21:46:30 +0900 Subject: [PATCH 082/133] Add combo info to JudgementInfo. --- osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs | 1 + osu.Game/Modes/ScoreProcesssor.cs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs index 53d3b1bafc..a10f8df27a 100644 --- a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs @@ -111,6 +111,7 @@ namespace osu.Game.Modes.Objects.Drawables public class JudgementInfo { + public ulong? ComboAtHit; public HitResult? Result; public double TimeOffset; } diff --git a/osu.Game/Modes/ScoreProcesssor.cs b/osu.Game/Modes/ScoreProcesssor.cs index efae0bd40b..fd9b5ba0fe 100644 --- a/osu.Game/Modes/ScoreProcesssor.cs +++ b/osu.Game/Modes/ScoreProcesssor.cs @@ -27,6 +27,8 @@ namespace osu.Game.Modes { Judgements.Add(judgement); UpdateCalculations(); + + judgement.ComboAtHit = (ulong)Combo.Value; } /// From eb70ae788c9e037edca47f767265621d2af5b80e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Nov 2016 21:57:53 +0900 Subject: [PATCH 083/133] Store max combo in ScoreProcessor. --- osu.Game/Modes/ScoreProcesssor.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Modes/ScoreProcesssor.cs b/osu.Game/Modes/ScoreProcesssor.cs index fd9b5ba0fe..7dfd7d04ce 100644 --- a/osu.Game/Modes/ScoreProcesssor.cs +++ b/osu.Game/Modes/ScoreProcesssor.cs @@ -21,6 +21,8 @@ namespace osu.Game.Modes public BindableInt Combo = new BindableInt(); + public BindableInt MaximumCombo = new BindableInt(); + public List Judgements = new List(); public virtual void AddJudgement(JudgementInfo judgement) @@ -29,6 +31,9 @@ namespace osu.Game.Modes UpdateCalculations(); judgement.ComboAtHit = (ulong)Combo.Value; + + if (Combo.Value > MaximumCombo.Value) + MaximumCombo.Value = Combo.Value; } /// From d71b284642cb018be767116492036e02063bda21 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Nov 2016 22:02:37 +0900 Subject: [PATCH 084/133] Make ScoreProcessor abstract and avoid making AddJudgement virtual. --- osu.Game.Mode.Osu/OsuScoreProcessor.cs | 27 +++++++++------------- osu.Game.Modes.Catch/CatchRuleset.cs | 2 +- osu.Game.Modes.Mania/ManiaRuleset.cs | 2 +- osu.Game.Modes.Taiko/TaikoRuleset.cs | 2 +- osu.Game/Modes/ScoreProcesssor.cs | 31 +++++++++++++------------- 5 files changed, 30 insertions(+), 34 deletions(-) diff --git a/osu.Game.Mode.Osu/OsuScoreProcessor.cs b/osu.Game.Mode.Osu/OsuScoreProcessor.cs index 177844297e..a5ebda6834 100644 --- a/osu.Game.Mode.Osu/OsuScoreProcessor.cs +++ b/osu.Game.Mode.Osu/OsuScoreProcessor.cs @@ -10,23 +10,20 @@ namespace osu.Game.Modes.Osu { class OsuScoreProcessor : ScoreProcessor { - public override void AddJudgement(JudgementInfo judgement) + protected override void UpdateCalculations(JudgementInfo judgement) { - base.AddJudgement(judgement); - - switch (judgement.Result) + if (judgement != null) { - case HitResult.Hit: - Combo.Value++; - break; - case HitResult.Miss: - Combo.Value = 0; - break; + switch (judgement.Result) + { + case HitResult.Hit: + Combo.Value++; + break; + case HitResult.Miss: + Combo.Value = 0; + break; + } } - } - protected override void UpdateCalculations() - { - base.UpdateCalculations(); int score = 0; int maxScore = 0; @@ -51,8 +48,6 @@ namespace osu.Game.Modes.Osu maxScore += 300; break; } - - } TotalScore.Value = score; diff --git a/osu.Game.Modes.Catch/CatchRuleset.cs b/osu.Game.Modes.Catch/CatchRuleset.cs index 695bca2593..eac762b4a0 100644 --- a/osu.Game.Modes.Catch/CatchRuleset.cs +++ b/osu.Game.Modes.Catch/CatchRuleset.cs @@ -18,7 +18,7 @@ namespace osu.Game.Modes.Catch protected override PlayMode PlayMode => PlayMode.Catch; - public override ScoreProcessor CreateScoreProcessor() => new ScoreProcessor(); + public override ScoreProcessor CreateScoreProcessor() => null; public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser(); } diff --git a/osu.Game.Modes.Mania/ManiaRuleset.cs b/osu.Game.Modes.Mania/ManiaRuleset.cs index 0e7761e8fb..e91b2ed02e 100644 --- a/osu.Game.Modes.Mania/ManiaRuleset.cs +++ b/osu.Game.Modes.Mania/ManiaRuleset.cs @@ -19,7 +19,7 @@ namespace osu.Game.Modes.Mania protected override PlayMode PlayMode => PlayMode.Mania; - public override ScoreProcessor CreateScoreProcessor() => new ScoreProcessor(); + public override ScoreProcessor CreateScoreProcessor() => null; public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser(); } diff --git a/osu.Game.Modes.Taiko/TaikoRuleset.cs b/osu.Game.Modes.Taiko/TaikoRuleset.cs index 3e697e48ea..e706387aaa 100644 --- a/osu.Game.Modes.Taiko/TaikoRuleset.cs +++ b/osu.Game.Modes.Taiko/TaikoRuleset.cs @@ -19,7 +19,7 @@ namespace osu.Game.Modes.Taiko protected override PlayMode PlayMode => PlayMode.Taiko; - public override ScoreProcessor CreateScoreProcessor() => new ScoreProcessor(); + public override ScoreProcessor CreateScoreProcessor() => null; public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser(); } diff --git a/osu.Game/Modes/ScoreProcesssor.cs b/osu.Game/Modes/ScoreProcesssor.cs index 7dfd7d04ce..63a1ed1528 100644 --- a/osu.Game/Modes/ScoreProcesssor.cs +++ b/osu.Game/Modes/ScoreProcesssor.cs @@ -11,37 +11,38 @@ using osu.Game.Modes.Objects.Drawables; namespace osu.Game.Modes { - public class ScoreProcessor + public abstract class ScoreProcessor { public virtual Score GetScore() => new Score(); - public BindableDouble TotalScore = new BindableDouble { MinValue = 0 }; + public readonly BindableDouble TotalScore = new BindableDouble { MinValue = 0 }; - public BindableDouble Accuracy = new BindableDouble { MinValue = 0, MaxValue = 1 }; + public readonly BindableDouble Accuracy = new BindableDouble { MinValue = 0, MaxValue = 1 }; - public BindableInt Combo = new BindableInt(); + public readonly BindableInt Combo = new BindableInt(); - public BindableInt MaximumCombo = new BindableInt(); + public readonly BindableInt MaximumCombo = new BindableInt(); - public List Judgements = new List(); + public readonly List Judgements = new List(); - public virtual void AddJudgement(JudgementInfo judgement) + public ScoreProcessor() + { + Combo.ValueChanged += delegate { MaximumCombo.Value = Math.Max(MaximumCombo.Value, Combo.Value); }; + } + + public void AddJudgement(JudgementInfo judgement) { Judgements.Add(judgement); - UpdateCalculations(); + + UpdateCalculations(judgement); judgement.ComboAtHit = (ulong)Combo.Value; - - if (Combo.Value > MaximumCombo.Value) - MaximumCombo.Value = Combo.Value; } /// /// Update any values that potentially need post-processing on a judgement change. /// - protected virtual void UpdateCalculations() - { - - } + /// A new JudgementInfo that triggered this calculation. May be null. + protected abstract void UpdateCalculations(JudgementInfo newJudgement); } } From ca0bea753439ce81ddb5eb86ef32fb6cc369c110 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Nov 2016 22:05:21 +0900 Subject: [PATCH 085/133] Rename MaximumCombo to HighestCombo. --- osu.Game/Modes/ScoreProcesssor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Modes/ScoreProcesssor.cs b/osu.Game/Modes/ScoreProcesssor.cs index 63a1ed1528..d94a424098 100644 --- a/osu.Game/Modes/ScoreProcesssor.cs +++ b/osu.Game/Modes/ScoreProcesssor.cs @@ -21,13 +21,13 @@ namespace osu.Game.Modes public readonly BindableInt Combo = new BindableInt(); - public readonly BindableInt MaximumCombo = new BindableInt(); + public readonly BindableInt HighestCombo = new BindableInt(); public readonly List Judgements = new List(); public ScoreProcessor() { - Combo.ValueChanged += delegate { MaximumCombo.Value = Math.Max(MaximumCombo.Value, Combo.Value); }; + Combo.ValueChanged += delegate { HighestCombo.Value = Math.Max(HighestCombo.Value, Combo.Value); }; } public void AddJudgement(JudgementInfo judgement) From 30e62eb53c652da524cee8fa0d2ee2a1562b5faf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Nov 2016 22:14:56 +0900 Subject: [PATCH 086/133] Adjust slider fadeout slightly. --- osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index df79953eae..c87bceb1d0 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -92,7 +92,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables base.UpdateState(state); Delay(HitObject.Duration); - FadeOut(100); + FadeOut(300); } private class Ball : Container From 74e3a87f7874d2d3e90fe0622eb9a308c44dc10e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Nov 2016 23:59:56 +0900 Subject: [PATCH 087/133] Add *very* basic ranking screen. --- osu.Game/Modes/Score.cs | 6 ++- osu.Game/Modes/ScoreProcesssor.cs | 8 +++- osu.Game/Modes/UI/HitRenderer.cs | 11 ++++- osu.Game/Screens/Play/Player.cs | 23 ++++++--- osu.Game/Screens/Ranking/Results.cs | 73 +++++++++++++++++++++++++++-- 5 files changed, 106 insertions(+), 15 deletions(-) diff --git a/osu.Game/Modes/Score.cs b/osu.Game/Modes/Score.cs index 88d79f94dd..ee90a9a0f9 100644 --- a/osu.Game/Modes/Score.cs +++ b/osu.Game/Modes/Score.cs @@ -11,7 +11,9 @@ namespace osu.Game.Modes { public class Score { - public double TotalScore { get; } - public double Accuracy { get; } + public double TotalScore { get; set; } + public double Accuracy { get; set; } + public double Combo { get; set; } + public double MaxCombo { get; set; } } } diff --git a/osu.Game/Modes/ScoreProcesssor.cs b/osu.Game/Modes/ScoreProcesssor.cs index d94a424098..a34915eaef 100644 --- a/osu.Game/Modes/ScoreProcesssor.cs +++ b/osu.Game/Modes/ScoreProcesssor.cs @@ -13,7 +13,13 @@ namespace osu.Game.Modes { public abstract class ScoreProcessor { - public virtual Score GetScore() => new Score(); + public virtual Score GetScore() => new Score() + { + TotalScore = TotalScore, + Combo = Combo, + MaxCombo = HighestCombo, + Accuracy = Accuracy + }; public readonly BindableDouble TotalScore = new BindableDouble { MinValue = 0 }; diff --git a/osu.Game/Modes/UI/HitRenderer.cs b/osu.Game/Modes/UI/HitRenderer.cs index 5d70fd71a0..bd191a47a3 100644 --- a/osu.Game/Modes/UI/HitRenderer.cs +++ b/osu.Game/Modes/UI/HitRenderer.cs @@ -16,10 +16,19 @@ namespace osu.Game.Modes.UI { public event Action OnJudgement; - protected void TriggerOnJudgement(JudgementInfo j) => OnJudgement?.Invoke(j); + public event Action OnAllJudged; + + protected void TriggerOnJudgement(JudgementInfo j) + { + OnJudgement?.Invoke(j); + if (AllObjectsJudged) + OnAllJudged?.Invoke(); + } protected Playfield Playfield; + public bool AllObjectsJudged => Playfield.HitObjects.Children.First()?.Judgement.Result != null; //reverse depth sort means First() instead of Last(). + public IEnumerable DrawableObjects => Playfield.HitObjects.Children; } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 1fa652afec..2f35f1b5d5 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -19,6 +19,7 @@ using OpenTK.Input; using MouseState = osu.Framework.Input.MouseState; using OpenTK; using osu.Framework.GameModes; +using osu.Game.Modes.UI; using osu.Game.Screens.Ranking; namespace osu.Game.Screens.Play @@ -40,6 +41,7 @@ namespace osu.Game.Screens.Play private Ruleset ruleset; private ScoreProcessor scoreProcessor; + private HitRenderer hitRenderer; [BackgroundDependencyLoader] private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuGameBase game) @@ -89,9 +91,10 @@ namespace osu.Game.Screens.Play var scoreOverlay = ruleset.CreateScoreOverlay(); scoreOverlay.BindProcessor(scoreProcessor = ruleset.CreateScoreProcessor()); - var hitRenderer = ruleset.CreateHitRendererWith(beatmap.HitObjects); + hitRenderer = ruleset.CreateHitRendererWith(beatmap.HitObjects); hitRenderer.OnJudgement += scoreProcessor.AddJudgement; + hitRenderer.OnAllJudged += hitRenderer_OnAllJudged; if (Autoplay) hitRenderer.Schedule(() => hitRenderer.DrawableObjects.ForEach(h => h.State = ArmedState.Hit)); @@ -110,6 +113,18 @@ namespace osu.Game.Screens.Play }; } + private void hitRenderer_OnAllJudged() + { + Delay(1000); + Schedule(delegate + { + Push(new Results + { + Score = scoreProcessor.GetScore() + }); + }); + } + protected override void OnEntering(GameMode last) { base.OnEntering(last); @@ -121,12 +136,6 @@ namespace osu.Game.Screens.Play { base.Update(); Clock.ProcessFrame(); - - if (Beatmap.Track.HasCompleted) - Push(new Results - { - Score = scoreProcessor.GetScore() - }); } class PlayerInputManager : UserInputManager diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index 55f2d4fe2b..a4219daf54 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -2,20 +2,29 @@ //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.GameModes; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Transformations; using osu.Game.Modes; using osu.Game.Screens.Backgrounds; +using OpenTK; using OpenTK.Graphics; namespace osu.Game.Screens.Ranking { - class Results : GameModeWhiteBox + class Results : OsuGameMode { - protected override BackgroundMode CreateBackground() => new BackgroundModeCustom(@"Backgrounds/bg4"); + protected override BackgroundMode CreateBackground() => new BackgroundModeBeatmap(Beatmap); + + private static readonly Vector2 BACKGROUND_BLUR = new Vector2(20); + + ScoreDisplay scoreDisplay; protected override void OnEntering(GameMode last) { base.OnEntering(last); - Background.Schedule(() => Background.FadeColour(Color4.DarkGray, 500)); + Background.Schedule(() => (Background as BackgroundModeBeatmap)?.BlurTo(BACKGROUND_BLUR, 1000)); } protected override bool OnExiting(GameMode next) @@ -24,6 +33,62 @@ namespace osu.Game.Screens.Ranking return base.OnExiting(next); } - public Score Score { get; set; } + public Score Score + { + set + { + scoreDisplay?.FadeOut(500); + scoreDisplay?.Expire(); + + scoreDisplay = new ScoreDisplay(value) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }; + + Add(scoreDisplay); + + scoreDisplay.FadeIn(500); + scoreDisplay.ScaleTo(0.1f); + scoreDisplay.ScaleTo(1, 1000, EasingTypes.OutElastic); + scoreDisplay.RotateTo(360 * 5, 1000, EasingTypes.OutElastic); + + } + } + } + + class ScoreDisplay : Container + { + public ScoreDisplay(Score s) + { + AutoSizeAxes = Axes.Both; + + Children = new Drawable[] + { + new FlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FlowDirection.VerticalOnly, + Children = new Drawable[] + { + new SpriteText + { + TextSize = 40, + Text = $@"Accuracy: {s.Accuracy:#0.00%}", + }, + new SpriteText + { + TextSize = 40, + Text = $@"Score: {s.TotalScore}", + }, + new SpriteText + { + TextSize = 40, + Text = $@"MaxCombo: {s.MaxCombo}", + } + } + } + }; + } } } From 988a9bbaad88d86805fece5e6f8851a4b358025a Mon Sep 17 00:00:00 2001 From: stanriders Date: Tue, 29 Nov 2016 20:27:59 +0300 Subject: [PATCH 088/133] Switch to relative sizes --- osu.Game/Graphics/UserInterface/BackButton.cs | 35 +++++++------------ 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index 7b3d011a7c..5de8537c17 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -24,23 +24,19 @@ namespace osu.Game.Graphics.UserInterface private const float shear = 0.1f; - private const int extend_length = 60; - private const int initial_extend_length = 40; - - private const int width_extended = 140; - private const int width_retracted = 120; + private static readonly Vector2 size_extended = new Vector2(140, 50); + private static readonly Vector2 size_retracted = new Vector2(100, 50); public BackButton() { - Width = width_retracted; - Height = 50; // same as bottomToolHeight in PlaySongSelect + Size = size_retracted; Children = new Drawable[] { leftContainer = new Container { - RelativeSizeAxes = Axes.Y, - Width = initial_extend_length, + RelativeSizeAxes = Axes.Both, + Width = 0.4f, Children = new Drawable[] { new Box @@ -59,11 +55,10 @@ namespace osu.Game.Graphics.UserInterface }, rightContainer = new Container { - Origin = Anchor.TopLeft, - Anchor = Anchor.TopLeft, - RelativeSizeAxes = Axes.Y, - Width = 80, - Position = Position + new Vector2(initial_extend_length, 0), + Origin = Anchor.TopRight, + Anchor = Anchor.TopRight, + RelativeSizeAxes = Axes.Both, + Width = 0.6f, Children = new Drawable[] { new Box @@ -89,10 +84,7 @@ namespace osu.Game.Graphics.UserInterface { icon.ClearTransformations(); - rightContainer.MoveToX(Position.X + extend_length, transform_time, EasingTypes.OutElastic); - leftContainer.ResizeTo(new Vector2(extend_length, 1.0f), transform_time, EasingTypes.OutElastic); - - Width = width_extended; // right container + ExtendLength + ResizeTo(size_extended, transform_time, EasingTypes.OutElastic); int duration = 0; //(int)(Game.Audio.BeatLength / 2); if (duration == 0) duration = pulse_length; @@ -119,12 +111,9 @@ namespace osu.Game.Graphics.UserInterface { icon.ClearTransformations(); - rightContainer.MoveToX(Position.X + initial_extend_length, transform_time, EasingTypes.OutElastic); - leftContainer.ResizeTo(new Vector2(initial_extend_length, 1.0f), transform_time, EasingTypes.OutElastic); + ResizeTo(size_retracted, transform_time, EasingTypes.OutElastic); - Width = width_retracted; // right container + InitialExtendLength - - int duration = 0; //(int)(Game.Audio.BeatLength / 2); + int duration = 0; //(int)(Game.Audio.BeatLength); if (duration == 0) duration = pulse_length * 2; double offset = 0; //(1 - Game.Audio.SyncBeatProgress) * duration; From b12b82fdd38b359437c63dbd152dc001860cf3c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Tue, 29 Nov 2016 20:50:12 +0100 Subject: [PATCH 089/133] Fix depth values. --- osu-framework | 2 +- osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs | 4 ++-- osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs | 2 +- osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs | 2 +- osu.Game/Graphics/Backgrounds/Background.cs | 2 +- osu.Game/Graphics/Cursor/OsuCursorContainer.cs | 2 +- osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs | 2 +- osu.Game/OsuGame.cs | 6 +++--- osu.Game/OsuGameBase.cs | 2 +- osu.Game/Overlays/ChatConsole.cs | 2 +- osu.Game/Overlays/MusicController.cs | 2 +- osu.Game/Screens/Backgrounds/BackgroundModeBeatmap.cs | 2 +- osu.Game/Screens/OsuGameMode.cs | 2 +- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 2 +- osu.Game/Screens/Select/CarouselContainer.cs | 4 ++-- 15 files changed, 19 insertions(+), 19 deletions(-) diff --git a/osu-framework b/osu-framework index e125c03d8c..7ec4902fe8 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit e125c03d8c39fd86e02e872a8d46654d2ea2759f +Subproject commit 7ec4902fe8b90f82e8e24dea98a69d2c4b37ac1e diff --git a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs index 0569fcf3c3..1e18ae4117 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs @@ -32,7 +32,7 @@ namespace osu.Desktop.VisualTests.Tests Clock.ProcessFrame(); - Container approachContainer = new Container { Depth = float.MaxValue, }; + Container approachContainer = new Container { Depth = float.MinValue, }; Add(approachContainer); @@ -50,7 +50,7 @@ namespace osu.Desktop.VisualTests.Tests { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Depth = -i, + Depth = i, State = ArmedState.Hit, }; diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index 1d55d704c4..f9fc866414 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -44,7 +44,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Colour = s.Colour, }) { - Depth = 1 //override time-based depth. + Depth = -1 //override time-based depth. }, }; } diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs index bd36ad5149..7234e2ad8b 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs @@ -119,7 +119,7 @@ namespace osu.Game.Beatmaps.Drawables { new FlowContainer { - Depth = 1, + Depth = -1, Direction = FlowDirection.HorizontalOnly, RelativeSizeAxes = Axes.Both, // This makes the gradient not be perfectly horizontal, but diagonal at a ~40° angle diff --git a/osu.Game/Graphics/Backgrounds/Background.cs b/osu.Game/Graphics/Backgrounds/Background.cs index 368bb7d723..ebb9348af7 100644 --- a/osu.Game/Graphics/Backgrounds/Background.cs +++ b/osu.Game/Graphics/Backgrounds/Background.cs @@ -22,7 +22,7 @@ namespace osu.Game.Graphics.Backgrounds { this.textureName = textureName; RelativeSizeAxes = Axes.Both; - Depth = float.MinValue; + Depth = float.MaxValue; Add(Sprite = new Sprite { diff --git a/osu.Game/Graphics/Cursor/OsuCursorContainer.cs b/osu.Game/Graphics/Cursor/OsuCursorContainer.cs index 22d7af7dc8..0b36e006fd 100644 --- a/osu.Game/Graphics/Cursor/OsuCursorContainer.cs +++ b/osu.Game/Graphics/Cursor/OsuCursorContainer.cs @@ -19,7 +19,7 @@ namespace osu.Game.Graphics.Cursor public OsuCursorContainer() { - Add(new CursorTrail { Depth = -1 }); + Add(new CursorTrail { Depth = 1 }); } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) diff --git a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs index 3508d6c3a6..a534c4b296 100644 --- a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs @@ -28,7 +28,7 @@ namespace osu.Game.Modes.Objects.Drawables public DrawableHitObject(HitObject hitObject) { HitObject = hitObject; - Depth = -(float)hitObject.StartTime; + Depth = (float)hitObject.StartTime; } private ArmedState state; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 7bf7e4cd2a..3c5c27ecb9 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -116,11 +116,11 @@ namespace osu.Game //overlay elements (chat = new ChatConsole(API) { Depth = 0 }).Preload(this, overlayContent.Add); - (Options = new OptionsOverlay { Depth = 1 }).Preload(this, overlayContent.Add); - (musicController = new MusicController() { Depth = 3 }).Preload(this, overlayContent.Add); + (Options = new OptionsOverlay { Depth = -1 }).Preload(this, overlayContent.Add); + (musicController = new MusicController() { Depth = -3 }).Preload(this, overlayContent.Add); (Toolbar = new Toolbar { - Depth = 2, + Depth = -2, OnHome = delegate { mainMenu?.MakeCurrent(); }, OnSettings = Options.ToggleVisibility, OnPlayModeChange = delegate (PlayMode m) { PlayMode.Value = m; }, diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index f58e868e1c..4399a9f0c3 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -83,7 +83,7 @@ namespace osu.Game { Children = new[] { - Cursor = new OsuCursorContainer { Depth = float.MaxValue } + Cursor = new OsuCursorContainer { Depth = float.MinValue } } }); } diff --git a/osu.Game/Overlays/ChatConsole.cs b/osu.Game/Overlays/ChatConsole.cs index ee06e29877..8913041fe1 100644 --- a/osu.Game/Overlays/ChatConsole.cs +++ b/osu.Game/Overlays/ChatConsole.cs @@ -45,7 +45,7 @@ namespace osu.Game.Overlays { new Box { - Depth = float.MinValue, + Depth = float.MaxValue, RelativeSizeAxes = Axes.Both, Colour = new Color4(0.1f, 0.1f, 0.1f, 0.4f), }, diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 27080c8db4..e8be9efb1b 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -386,7 +386,7 @@ namespace osu.Game.Overlays this.beatmap = beatmap; CacheDrawnFrameBuffer = true; RelativeSizeAxes = Axes.Both; - Depth = float.MinValue; + Depth = float.MaxValue; Children = new Drawable[] { diff --git a/osu.Game/Screens/Backgrounds/BackgroundModeBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundModeBeatmap.cs index 1a4ce2eec2..1c25fcfb0e 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundModeBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundModeBeatmap.cs @@ -39,7 +39,7 @@ namespace osu.Game.Screens.Backgrounds float newDepth = 0; if (background != null) { - newDepth = background.Depth - 1; + newDepth = background.Depth + 1; background.Flush(); background.FadeOut(250); background.Expire(); diff --git a/osu.Game/Screens/OsuGameMode.cs b/osu.Game/Screens/OsuGameMode.cs index 51b8c7d7cf..b5e45f2097 100644 --- a/osu.Game/Screens/OsuGameMode.cs +++ b/osu.Game/Screens/OsuGameMode.cs @@ -111,7 +111,7 @@ namespace osu.Game.Screens { AddInternal(new ParallaxContainer { - Depth = float.MinValue, + Depth = float.MaxValue, Children = new[] { Background = bg diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 7e87194cf4..203d290fc3 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -50,7 +50,7 @@ namespace osu.Game.Screens.Select var lastContainer = beatmapInfoContainer; - float newDepth = lastContainer?.Depth - 1 ?? 0; + float newDepth = lastContainer?.Depth + 1 ?? 0; BeatmapSetInfo beatmapSetInfo = beatmap.BeatmapSetInfo; BeatmapInfo beatmapInfo = beatmap.BeatmapInfo; diff --git a/osu.Game/Screens/Select/CarouselContainer.cs b/osu.Game/Screens/Select/CarouselContainer.cs index 9ff950cc06..98bcf093af 100644 --- a/osu.Game/Screens/Select/CarouselContainer.cs +++ b/osu.Game/Screens/Select/CarouselContainer.cs @@ -81,12 +81,12 @@ namespace osu.Game.Screens.Select group.State = BeatmapGroupState.Collapsed; groups.Add(group); - group.Header.Depth = scrollableContent.Children.Count(); + group.Header.Depth = -scrollableContent.Children.Count(); scrollableContent.Add(group.Header); foreach (BeatmapPanel panel in group.BeatmapPanels) { - panel.Depth = scrollableContent.Children.Count(); + panel.Depth = -scrollableContent.Children.Count(); scrollableContent.Add(panel); } From a456eb6f1b6d704e3ecaf64ddbb41c8221211abb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Tue, 29 Nov 2016 21:12:49 +0100 Subject: [PATCH 090/133] Fix being able to hover the back button from outside of its shape. Could alternatively done by shearing the entire button, but then you would need a positional x-offset depending on whether the anchor is top or bottom. --- osu.Game/Graphics/UserInterface/BackButton.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index 5de8537c17..7ccc5c061b 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -19,6 +19,9 @@ namespace osu.Game.Graphics.UserInterface private Container leftContainer; private Container rightContainer; + private Box leftBox; + private Box rightBox; + private const double transform_time = 300.0; private const int pulse_length = 250; @@ -39,7 +42,7 @@ namespace osu.Game.Graphics.UserInterface Width = 0.4f, Children = new Drawable[] { - new Box + leftBox = new Box { RelativeSizeAxes = Axes.Both, Colour = new Color4(195, 40, 140, 255), @@ -61,7 +64,7 @@ namespace osu.Game.Graphics.UserInterface Width = 0.6f, Children = new Drawable[] { - new Box + rightBox = new Box { Colour = new Color4(238, 51, 153, 255), Origin = Anchor.TopLeft, @@ -80,6 +83,12 @@ namespace osu.Game.Graphics.UserInterface } }; } + + public override bool Contains(Vector2 screenSpacePos) + { + return leftBox.Contains(screenSpacePos) || rightBox.Contains(screenSpacePos); + } + protected override bool OnHover(InputState state) { icon.ClearTransformations(); From d56e23195de665bc7125610a9dd33d4df7b25f68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Tue, 29 Nov 2016 21:31:01 +0100 Subject: [PATCH 091/133] Add treatment of slider segments encoded by the same vertex appearing twice in succession. --- osu.Game.Mode.Osu/Objects/Slider.cs | 31 +++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/osu.Game.Mode.Osu/Objects/Slider.cs b/osu.Game.Mode.Osu/Objects/Slider.cs index 7ee131659a..c79d52d0dd 100644 --- a/osu.Game.Mode.Osu/Objects/Slider.cs +++ b/osu.Game.Mode.Osu/Objects/Slider.cs @@ -35,20 +35,43 @@ namespace osu.Game.Modes.Osu.Objects private List calculatedPath; - public void Calculate() + private void calculateSubpath(List subpath) { + // If we already constructed a subpath previously, then the new subpath + // will have as starting position the end position of the previous subpath. + // Hence we can and should remove the previous endpoint to avoid a segment + // with 0 length. + if (calculatedPath.Count > 0) + calculatedPath.RemoveAt(calculatedPath.Count - 1); + switch (CurveType) { case CurveTypes.Linear: - calculatedPath = Path; + calculatedPath.AddRange(subpath); break; default: - var bezier = new BezierApproximator(Path); - calculatedPath = bezier.CreateBezier(); + var bezier = new BezierApproximator(subpath); + calculatedPath.AddRange(bezier.CreateBezier()); break; } } + public void Calculate() + { + calculatedPath = new List(); + List subpath = new List(); + + for (int i = 0; i < Path.Count; ++i) + { + subpath.Add(Path[i]); + if (i == Path.Count-1 || Path[i] == Path[i+1]) + { + calculateSubpath(subpath); + subpath.Clear(); + } + } + } + public Vector2 PositionAt(double progress) { progress = MathHelper.Clamp(progress, 0, 1); From 62bd7e15ad9e8cc0fd068f2cfe501252e0a12786 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Nov 2016 12:21:32 +0900 Subject: [PATCH 092/133] Update framework. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 7ec4902fe8..4fd477755a 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 7ec4902fe8b90f82e8e24dea98a69d2c4b37ac1e +Subproject commit 4fd477755a640a497c04fc8e540e8641278aa056 From 476168eec2db4db5f04700734b860a2bfea5b420 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Nov 2016 13:15:34 +0900 Subject: [PATCH 093/133] Add shadow to main menu button/icon text. --- osu.Game/Screens/Menu/Button.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Menu/Button.cs b/osu.Game/Screens/Menu/Button.cs index fa5dbb3b99..37bcc89a9a 100644 --- a/osu.Game/Screens/Menu/Button.cs +++ b/osu.Game/Screens/Menu/Button.cs @@ -71,6 +71,7 @@ namespace osu.Game.Screens.Menu { icon = new TextAwesome { + Shadow = true, Anchor = Anchor.Centre, TextSize = 30, Position = new Vector2(0, 0), @@ -78,6 +79,7 @@ namespace osu.Game.Screens.Menu }, new SpriteText { + Shadow = true, Direction = FlowDirection.HorizontalOnly, Anchor = Anchor.Centre, Origin = Anchor.Centre, From d65a275e323365ea5a2241ea5d098fc8d6c607f3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Nov 2016 13:50:30 +0900 Subject: [PATCH 094/133] Improve transition of toolbar when hovering. --- osu.Game/Overlays/Toolbar.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Toolbar.cs b/osu.Game/Overlays/Toolbar.cs index 190615de29..d70da2b191 100644 --- a/osu.Game/Overlays/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar.cs @@ -30,9 +30,14 @@ namespace osu.Game.Overlays private ToolbarModeSelector modeSelector; private ToolbarButton userButton; + private Box solidBackground; private Box gradientBackground; - private const int transition_time = 200; + private const int transition_time = 250; + + private const float alpha_hovering = 0.8f; + private const float alpha_normal = 0.6f; + protected override void PopIn() { @@ -48,23 +53,26 @@ namespace osu.Game.Overlays protected override bool OnHover(InputState state) { - gradientBackground.FadeIn(200); + solidBackground.FadeTo(alpha_hovering, transition_time, EasingTypes.OutQuint); + gradientBackground.FadeIn(transition_time, EasingTypes.OutQuint); return true; } protected override void OnHoverLost(InputState state) { - gradientBackground.FadeOut(200); + solidBackground.FadeTo(alpha_normal, transition_time, EasingTypes.OutQuint); + gradientBackground.FadeOut(transition_time, EasingTypes.OutQuint); } public Toolbar() { Children = new Drawable[] { - new Box + solidBackground = new Box { RelativeSizeAxes = Axes.Both, - Colour = new Color4(0.1f, 0.1f, 0.1f, 0.6f) + Colour = new Color4(0.1f, 0.1f, 0.1f, 1), + Alpha = alpha_normal, }, gradientBackground = new Box { From 5101297f53038b2dbb99ff1f31ef41f6ba8b9eb6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Nov 2016 14:38:45 +0900 Subject: [PATCH 095/133] Add drop shadows to main menu buttons. --- .../Tests/TestCaseMenuButtonSystem.cs | 8 +++++++ osu.Game/Screens/Menu/Button.cs | 22 ++++++++++++++++--- .../Screens/Menu/FlowContainerWithOrigin.cs | 6 +++++ 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/osu.Desktop.VisualTests/Tests/TestCaseMenuButtonSystem.cs b/osu.Desktop.VisualTests/Tests/TestCaseMenuButtonSystem.cs index c7889134bb..6579e8109c 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseMenuButtonSystem.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseMenuButtonSystem.cs @@ -2,7 +2,10 @@ //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.GameModes.Testing; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Sprites; using osu.Game.Screens.Menu; +using OpenTK.Graphics; namespace osu.Desktop.VisualTests.Tests { @@ -15,6 +18,11 @@ namespace osu.Desktop.VisualTests.Tests { base.Reset(); + Add(new Box + { + ColourInfo = ColourInfo.GradientVertical(Color4.Gray, Color4.WhiteSmoke), + RelativeSizeAxes = Framework.Graphics.Axes.Both, + }); Add(new ButtonSystem()); } } diff --git a/osu.Game/Screens/Menu/Button.cs b/osu.Game/Screens/Menu/Button.cs index 37bcc89a9a..f0de6e7f74 100644 --- a/osu.Game/Screens/Menu/Button.cs +++ b/osu.Game/Screens/Menu/Button.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Menu public class Button : Container, IStateful { private Container iconText; - private Box box; + private Container box; private Color4 colour; private TextAwesome icon; private string internalName; @@ -51,15 +51,31 @@ namespace osu.Game.Screens.Menu Children = new Drawable[] { - box = new Box + box = new Container { + Masking = true, + EdgeEffect = new EdgeEffect + { + Type = EdgeEffectType.Shadow, + Colour = new Color4(0, 0, 0, 0.2f), + Roundness = 5, + Radius = 8, + }, Anchor = Anchor.Centre, Origin = Anchor.Centre, Colour = colour, Scale = new Vector2(0, 1), Size = boxSize, Shear = new Vector2(ButtonSystem.wedge_width / boxSize.Y, 0), - EdgeSmoothness = new Vector2(2, 0), + + Children = new Drawable[] + { + new Box + { + EdgeSmoothness = new Vector2(2, 0), + RelativeSizeAxes = Axes.Both, + }, + } }, iconText = new Container { diff --git a/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs b/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs index fc72365812..7a194d1d07 100644 --- a/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs +++ b/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs @@ -1,6 +1,8 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using OpenTK; +using System.Collections.Generic; +using System.Linq; namespace osu.Game.Screens.Menu { @@ -15,6 +17,10 @@ namespace osu.Game.Screens.Menu /// public Drawable CentreTarget; + protected override IComparer DepthComparer => new ReverseDepthComparer(); + + protected override IEnumerable SortedChildren => base.SortedChildren.Reverse(); + public override Anchor Origin => Anchor.Custom; public override Vector2 OriginPosition From c26587ec3a716f59f302401725bcc281ab020d15 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Nov 2016 15:49:26 +0900 Subject: [PATCH 096/133] Update depth comparer name. --- osu.Game/Screens/Menu/FlowContainerWithOrigin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs b/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs index 7a194d1d07..cb6bc26b8a 100644 --- a/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs +++ b/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens.Menu /// public Drawable CentreTarget; - protected override IComparer DepthComparer => new ReverseDepthComparer(); + protected override IComparer DepthComparer => new ReverseCreationOrderDepthComparer(); protected override IEnumerable SortedChildren => base.SortedChildren.Reverse(); From 6809e2ce0ae1f6328bf58751a6c426bff8e6f540 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Nov 2016 14:52:24 +0900 Subject: [PATCH 097/133] Use DI to get api for ChatConsole. --- osu.Game/Overlays/ChatConsole.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/ChatConsole.cs b/osu.Game/Overlays/ChatConsole.cs index 8913041fe1..255cf4589c 100644 --- a/osu.Game/Overlays/ChatConsole.cs +++ b/osu.Game/Overlays/ChatConsole.cs @@ -32,10 +32,8 @@ namespace osu.Game.Overlays private APIAccess api; - public ChatConsole(APIAccess api) + public ChatConsole() { - this.api = api; - RelativeSizeAxes = Axes.X; Size = new Vector2(1, 300); Anchor = Anchor.BottomLeft; @@ -57,8 +55,10 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load() + private void load(APIAccess api) { + this.api = api; + initializeChannels(); } @@ -145,8 +145,8 @@ namespace osu.Game.Overlays protected override void PopOut() { - MoveToY(DrawSize.Y, transition_length, EasingTypes.InQuint); - FadeOut(transition_length, EasingTypes.InQuint); + MoveToY(DrawSize.Y, transition_length, EasingTypes.InSine); + FadeOut(transition_length, EasingTypes.InSine); } } } From 481b9d3208986210f8e76a3d4d9396f1f7cc4f55 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Nov 2016 18:28:08 +0900 Subject: [PATCH 098/133] Make opening options shift the rest of the screen as per design. --- osu.Game/OsuGame.cs | 14 ++++++++++++++ osu.Game/Overlays/OptionsOverlay.cs | 22 +++++++++++++--------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 3c5c27ecb9..b979501b26 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -19,6 +19,7 @@ using osu.Framework.Logging; using osu.Game.Graphics.UserInterface.Volume; using osu.Game.Database; using osu.Framework.Allocation; +using osu.Framework.Graphics.Transformations; using osu.Game.Modes; using osu.Game.Screens; using osu.Game.Screens.Menu; @@ -132,6 +133,19 @@ namespace osu.Game overlayContent.Add(Toolbar); }); + Options.StateChanged += delegate + { + switch (Options.State) + { + case Visibility.Hidden: + intro.MoveToX(0, OptionsOverlay.TRANSITION_LENGTH, EasingTypes.OutQuint); + break; + case Visibility.Visible: + intro.MoveToX(OptionsOverlay.SIDEBAR_WIDTH / 2, OptionsOverlay.TRANSITION_LENGTH, EasingTypes.OutQuint); + break; + } + }; + Cursor.Alpha = 0; } diff --git a/osu.Game/Overlays/OptionsOverlay.cs b/osu.Game/Overlays/OptionsOverlay.cs index e3039ad781..33677799f1 100644 --- a/osu.Game/Overlays/OptionsOverlay.cs +++ b/osu.Game/Overlays/OptionsOverlay.cs @@ -30,8 +30,12 @@ namespace osu.Game.Overlays { internal const float CONTENT_MARGINS = 10; + public const float TRANSITION_LENGTH = 600; + + public const float SIDEBAR_WIDTH = OptionsSidebar.default_width; + private const float width = 400; - private const float sidebar_width = OptionsSidebar.default_width; + private const float sidebar_padding = 10; private ScrollContainer scrollContainer; @@ -71,7 +75,7 @@ namespace osu.Game.Overlays ScrollDraggerVisible = false, RelativeSizeAxes = Axes.Y, Width = width, - Margin = new MarginPadding { Left = sidebar_width }, + Margin = new MarginPadding { Left = SIDEBAR_WIDTH }, Children = new[] { new FlowContainer @@ -108,7 +112,7 @@ namespace osu.Game.Overlays }, sidebar = new OptionsSidebar { - Width = sidebar_width, + Width = SIDEBAR_WIDTH, Children = sidebarButtons = sections.Select(section => new SidebarButton { @@ -175,16 +179,16 @@ namespace osu.Game.Overlays protected override void PopIn() { - scrollContainer.MoveToX(0, 600, EasingTypes.OutQuint); - sidebar.MoveToX(0, 800, EasingTypes.OutQuint); - FadeTo(1, 300); + scrollContainer.MoveToX(0, TRANSITION_LENGTH, EasingTypes.OutQuint); + sidebar.MoveToX(0, TRANSITION_LENGTH, EasingTypes.OutQuint); + FadeTo(1, TRANSITION_LENGTH / 2); } protected override void PopOut() { - scrollContainer.MoveToX(-width, 600, EasingTypes.OutQuint); - sidebar.MoveToX(-sidebar_width, 600, EasingTypes.OutQuint); - FadeTo(0, 300); + scrollContainer.MoveToX(-width, TRANSITION_LENGTH, EasingTypes.OutQuint); + sidebar.MoveToX(-SIDEBAR_WIDTH, TRANSITION_LENGTH, EasingTypes.OutQuint); + FadeTo(0, TRANSITION_LENGTH / 2); } } } From 34e91c8474a53fdc9380359b62ffe17b994a80b5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Nov 2016 15:15:07 +0900 Subject: [PATCH 099/133] Add the concept of IOnlineComponents, registered tot he API for handling state changes. --- .../Tests/TestCaseChatDisplay.cs | 4 +- osu.Game/Online/API/APIAccess.cs | 60 ++++++++++++------- osu.Game/Online/API/IOnlineComponent.cs | 16 +++++ osu.Game/osu.Game.csproj | 1 + 4 files changed, 56 insertions(+), 25 deletions(-) create mode 100644 osu.Game/Online/API/IOnlineComponent.cs diff --git a/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs b/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs index cb412f8c97..83627a519a 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs @@ -45,7 +45,7 @@ namespace osu.Desktop.VisualTests.Tests { base.Reset(); - if (api.State != APIAccess.APIState.Online) + if (api.State != APIState.Online) api.OnStateChange += delegate { initializeChannels(); }; else initializeChannels(); @@ -65,7 +65,7 @@ namespace osu.Desktop.VisualTests.Tests { careChannels = new List(); - if (api.State != APIAccess.APIState.Online) + if (api.State != APIState.Online) return; Add(flow = new FlowContainer diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index a7b2239355..578386c4f8 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Concurrent; +using System.Collections.Generic; using System.Net; using System.Threading; using osu.Framework; @@ -65,6 +66,18 @@ namespace osu.Game.Online.API thread.Start(); } + private List components = new List(); + + public void Register(IOnlineComponent component) + { + components.Add(component); + } + + public void Unregister(IOnlineComponent component) + { + components.Remove(component); + } + public string AccessToken => authentication.RequestAccessToken(); /// @@ -221,6 +234,7 @@ namespace osu.Game.Online.API log.Add($@"We just went {newState}!"); Scheduler.Add(delegate { + components.ForEach(c => c.APIStateChanged(this, newState)); OnStateChange?.Invoke(oldState, newState); }); } @@ -237,29 +251,6 @@ namespace osu.Game.Online.API public delegate void StateChangeDelegate(APIState oldState, APIState newState); - public enum APIState - { - /// - /// We cannot login (not enough credentials). - /// - Offline, - - /// - /// We are having connectivity issues. - /// - Failing, - - /// - /// We are in the process of (re-)connecting. - /// - Connecting, - - /// - /// We are online. - /// - Online - } - private void flushQueue(bool failOldRequests = true) { var oldQueue = queue; @@ -286,4 +277,27 @@ namespace osu.Game.Online.API Scheduler.Update(); } } + + public enum APIState + { + /// + /// We cannot login (not enough credentials). + /// + Offline, + + /// + /// We are having connectivity issues. + /// + Failing, + + /// + /// We are in the process of (re-)connecting. + /// + Connecting, + + /// + /// We are online. + /// + Online + } } diff --git a/osu.Game/Online/API/IOnlineComponent.cs b/osu.Game/Online/API/IOnlineComponent.cs new file mode 100644 index 0000000000..0208384921 --- /dev/null +++ b/osu.Game/Online/API/IOnlineComponent.cs @@ -0,0 +1,16 @@ +//Copyright (c) 2007-2016 ppy Pty Ltd . +//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace osu.Game.Online.API +{ + public interface IOnlineComponent + { + void APIStateChanged(APIAccess api, APIState state); + } +} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index f4d0749080..2c28be06b1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -69,6 +69,7 @@ + From 18509e6a608c2adc574933fc718bd6ab11f726fc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Nov 2016 15:15:43 +0900 Subject: [PATCH 100/133] ChatConsole -> ChatOverlay. Namespace tidying. --- osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs | 2 +- .../Chat/{Display => Drawables}/ChannelDisplay.cs | 6 ++---- .../Online/Chat/{Display => Drawables}/ChatLine.cs | 2 +- osu.Game/OsuGame.cs | 4 ++-- osu.Game/Overlays/{ChatConsole.cs => ChatOverlay.cs} | 12 ++++++++---- osu.Game/osu.Game.csproj | 6 +++--- 6 files changed, 17 insertions(+), 15 deletions(-) rename osu.Game/Online/Chat/{Display => Drawables}/ChannelDisplay.cs (92%) rename osu.Game/Online/Chat/{Display => Drawables}/ChatLine.cs (95%) rename osu.Game/Overlays/{ChatConsole.cs => ChatOverlay.cs} (90%) diff --git a/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs b/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs index 83627a519a..9e8083310c 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs @@ -14,9 +14,9 @@ using osu.Game; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.Chat; -using osu.Game.Online.Chat.Display; using OpenTK; using osu.Framework.Allocation; +using osu.Game.Online.Chat.Drawables; namespace osu.Desktop.VisualTests.Tests { diff --git a/osu.Game/Online/Chat/Display/ChannelDisplay.cs b/osu.Game/Online/Chat/Drawables/ChannelDisplay.cs similarity index 92% rename from osu.Game/Online/Chat/Display/ChannelDisplay.cs rename to osu.Game/Online/Chat/Drawables/ChannelDisplay.cs index 93e235f3f3..041163b19a 100644 --- a/osu.Game/Online/Chat/Display/ChannelDisplay.cs +++ b/osu.Game/Online/Chat/Drawables/ChannelDisplay.cs @@ -4,15 +4,13 @@ using System; using System.Collections.Generic; using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Transformations; using OpenTK; -using osu.Framework; -using osu.Framework.Allocation; -namespace osu.Game.Online.Chat.Display +namespace osu.Game.Online.Chat.Drawables { public class ChannelDisplay : Container { diff --git a/osu.Game/Online/Chat/Display/ChatLine.cs b/osu.Game/Online/Chat/Drawables/ChatLine.cs similarity index 95% rename from osu.Game/Online/Chat/Display/ChatLine.cs rename to osu.Game/Online/Chat/Drawables/ChatLine.cs index b582bc5a6d..454f7beed7 100644 --- a/osu.Game/Online/Chat/Display/ChatLine.cs +++ b/osu.Game/Online/Chat/Drawables/ChatLine.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Sprites; using OpenTK; using OpenTK.Graphics; -namespace osu.Game.Online.Chat.Display +namespace osu.Game.Online.Chat.Drawables { public class ChatLine : Container { diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 3c5c27ecb9..1067f271ba 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -30,7 +30,7 @@ namespace osu.Game { public Toolbar Toolbar; - private ChatConsole chat; + private ChatOverlay chat; private MusicController musicController; @@ -115,7 +115,7 @@ namespace osu.Game }); //overlay elements - (chat = new ChatConsole(API) { Depth = 0 }).Preload(this, overlayContent.Add); + (chat = new ChatOverlay { Depth = 0 }).Preload(this, overlayContent.Add); (Options = new OptionsOverlay { Depth = -1 }).Preload(this, overlayContent.Add); (musicController = new MusicController() { Depth = -3 }).Preload(this, overlayContent.Add); (Toolbar = new Toolbar diff --git a/osu.Game/Overlays/ChatConsole.cs b/osu.Game/Overlays/ChatOverlay.cs similarity index 90% rename from osu.Game/Overlays/ChatConsole.cs rename to osu.Game/Overlays/ChatOverlay.cs index 255cf4589c..a0d7384583 100644 --- a/osu.Game/Overlays/ChatConsole.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -6,7 +6,6 @@ using System.Diagnostics; using System.Linq; using OpenTK; using OpenTK.Graphics; -using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -16,11 +15,11 @@ using osu.Framework.Threading; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.Chat; -using osu.Game.Online.Chat.Display; +using osu.Game.Online.Chat.Drawables; namespace osu.Game.Overlays { - public class ChatConsole : OverlayContainer + public class ChatOverlay : OverlayContainer, IOnlineComponent { private ChannelDisplay channelDisplay; @@ -32,7 +31,7 @@ namespace osu.Game.Overlays private APIAccess api; - public ChatConsole() + public ChatOverlay() { RelativeSizeAxes = Axes.X; Size = new Vector2(1, 300); @@ -148,5 +147,10 @@ namespace osu.Game.Overlays MoveToY(DrawSize.Y, transition_length, EasingTypes.InSine); FadeOut(transition_length, EasingTypes.InSine); } + + public void APIStateChanged(APIAccess api, APIState state) + { + throw new System.NotImplementedException(); + } } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 2c28be06b1..581ab7916d 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -151,13 +151,13 @@ - - + + - + From 88748499fa681998262f152508c4776b0e7d799a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Nov 2016 15:49:15 +0900 Subject: [PATCH 101/133] Register chat overlay with API. --- osu.Game/Overlays/ChatOverlay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index a0d7384583..8ce24e1725 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -57,6 +57,7 @@ namespace osu.Game.Overlays private void load(APIAccess api) { this.api = api; + api.Register(this); initializeChannels(); } From 11f726ad45822836de9556056bd5b8eeccb43754 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Nov 2016 16:54:15 +0900 Subject: [PATCH 102/133] Add basic login flow. --- osu.Game/Online/API/APIAccess.cs | 13 ++++ .../Overlays/Options/General/LoginOptions.cs | 73 ++++++++++++++++--- 2 files changed, 76 insertions(+), 10 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 578386c4f8..0f16d103e2 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Diagnostics; using System.Net; using System.Threading; using osu.Framework; @@ -71,6 +72,7 @@ namespace osu.Game.Online.API public void Register(IOnlineComponent component) { components.Add(component); + component.APIStateChanged(this, state); } public void Unregister(IOnlineComponent component) @@ -158,6 +160,16 @@ namespace osu.Game.Online.API password = null; } + public void Login(string username, string password) + { + Debug.Assert(State == APIState.Offline); + + Username = username; + Password = password; + + State = APIState.Connecting; + } + /// /// Handle a single API request. /// @@ -167,6 +179,7 @@ namespace osu.Game.Online.API { try { + Logger.Log($@"Performing request {req}", LoggingTarget.Network); req.Perform(this); State = APIState.Online; diff --git a/osu.Game/Overlays/Options/General/LoginOptions.cs b/osu.Game/Overlays/Options/General/LoginOptions.cs index 2dc8bb5976..c978a8c7ba 100644 --- a/osu.Game/Overlays/Options/General/LoginOptions.cs +++ b/osu.Game/Overlays/Options/General/LoginOptions.cs @@ -1,4 +1,5 @@ -using OpenTK; +using System; +using OpenTK; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -10,7 +11,7 @@ using osu.Game.Online.API; namespace osu.Game.Overlays.Options.General { - public class LoginOptions : OptionsSubsection + public class LoginOptions : OptionsSubsection, IOnlineComponent { private Container loginForm; protected override string Header => "Sign In"; @@ -31,16 +32,56 @@ namespace osu.Game.Overlays.Options.General [BackgroundDependencyLoader(permitNulls: true)] private void load(APIAccess api) { - if (api == null) - return; - loginForm.Children = new Drawable[] - { - new LoginForm(api) - }; + api?.Register(this); } + public void APIStateChanged(APIAccess api, APIState state) + { + switch (state) + { + case APIState.Offline: + loginForm.Children = new Drawable[] + { + new LoginForm(api) + }; + break; + case APIState.Failing: + loginForm.Children = new Drawable[] + { + new SpriteText + { + Text = @"Connection failing :(", + }, + }; + break; + case APIState.Connecting: + loginForm.Children = new Drawable[] + { + new SpriteText + { + Text = @"Connecting...", + }, + }; + break; + case APIState.Online: + loginForm.Children = new Drawable[] + { + new SpriteText + { + Text = $@"Connected as {api.Username}!", + }, + }; + break; + } + } + class LoginForm : FlowContainer { + private APIAccess api; + + private TextBox username; + private TextBox password; + public LoginForm(APIAccess api) { Direction = FlowDirection.VerticalOnly; @@ -51,16 +92,28 @@ namespace osu.Game.Overlays.Options.General Children = new Drawable[] { new SpriteText { Text = "Username" }, - new TextBox { Height = 20, RelativeSizeAxes = Axes.X, Text = api?.Username ?? string.Empty }, + username = new TextBox { Height = 20, RelativeSizeAxes = Axes.X, Text = api?.Username ?? string.Empty }, new SpriteText { Text = "Password" }, - new TextBox { Height = 20, RelativeSizeAxes = Axes.X }, + password = new PasswordTextBox { Height = 20, RelativeSizeAxes = Axes.X }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Log in", + Action = performLogin } }; } + + private void performLogin() + { + api.Login(username.Text, password.Text); + } + + [BackgroundDependencyLoader(permitNulls: true)] + private void load(APIAccess api) + { + this.api = api; + } } } } From a980671c54a80bf489ddca46fb60f4720fc321c5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Nov 2016 17:07:09 +0900 Subject: [PATCH 103/133] Add basic ChatOverlay state handling. --- osu.Game/Overlays/ChatOverlay.cs | 85 ++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 8ce24e1725..22f7a3a78f 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -1,6 +1,7 @@ //Copyright (c) 2007-2016 ppy Pty Ltd . //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -58,49 +59,12 @@ namespace osu.Game.Overlays { this.api = api; api.Register(this); - - initializeChannels(); } private long? lastMessageId; private List careChannels; - private void initializeChannels() - { - careChannels = new List(); - - //if (api.State != APIAccess.APIState.Online) - // return; - - SpriteText loading; - Add(loading = new SpriteText - { - Text = @"Loading available channels...", - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - TextSize = 40, - }); - - messageRequest?.Cancel(); - - ListChannelsRequest req = new ListChannelsRequest(); - req.Success += delegate (List channels) - { - Scheduler.Add(delegate - { - loading.FadeOut(100); - addChannel(channels.Find(c => c.Name == @"#osu")); - }); - - //addChannel(channels.Find(c => c.Name == @"#lobby")); - //addChannel(channels.Find(c => c.Name == @"#english")); - - messageRequest = Scheduler.AddDelayed(() => FetchNewMessages(api), 1000, true); - }; - api.Queue(req); - } - private void addChannel(Channel channel) { Add(channelDisplay = new ChannelDisplay(channel)); @@ -151,7 +115,52 @@ namespace osu.Game.Overlays public void APIStateChanged(APIAccess api, APIState state) { - throw new System.NotImplementedException(); + switch (state) + { + case APIState.Online: + initializeChannels(); + break; + default: + messageRequest?.Cancel(); + break; + } + } + + private void initializeChannels() + { + Clear(); + + careChannels = new List(); + + //if (api.State != APIAccess.APIState.Online) + // return; + + SpriteText loading; + Add(loading = new SpriteText + { + Text = @"Loading available channels...", + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + TextSize = 40, + }); + + messageRequest?.Cancel(); + + ListChannelsRequest req = new ListChannelsRequest(); + req.Success += delegate (List channels) + { + Scheduler.Add(delegate + { + loading.FadeOut(100); + addChannel(channels.Find(c => c.Name == @"#osu")); + }); + + //addChannel(channels.Find(c => c.Name == @"#lobby")); + //addChannel(channels.Find(c => c.Name == @"#english")); + + messageRequest = Scheduler.AddDelayed(() => FetchNewMessages(api), 1000, true); + }; + api.Queue(req); } } } From 3fa80d2376de74aab3580f5157b98829c43b8160 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Nov 2016 17:47:40 +0900 Subject: [PATCH 104/133] Update client id/secret and bring API endpoints up-to-date. --- osu.Game/Online/API/APIAccess.cs | 4 ++-- osu.Game/Online/API/OAuth.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 0f16d103e2..a6717b99db 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -19,8 +19,8 @@ namespace osu.Game.Online.API private OAuth authentication; public string Endpoint = @"https://new.ppy.sh"; - const string ClientId = @"daNBnfdv7SppRVc61z0XuOI13y6Hroiz"; - const string ClientSecret = @"d6fgZuZeQ0eSXkEj5igdqQX6ztdtS6Ow"; + const string ClientId = @"5"; + const string ClientSecret = @"FGc9GAtyHzeQDshWP5Ah7dega8hJACAJpQtw6OXk"; ConcurrentQueue queue = new ConcurrentQueue(); diff --git a/osu.Game/Online/API/OAuth.cs b/osu.Game/Online/API/OAuth.cs index 3358fac0e8..0aa1ed84e1 100644 --- a/osu.Game/Online/API/OAuth.cs +++ b/osu.Game/Online/API/OAuth.cs @@ -30,7 +30,7 @@ namespace osu.Game.Online.API { var req = new AccessTokenRequestPassword(username, password) { - Url = $@"{endpoint}/oauth/access_token", + Url = $@"{endpoint}/oauth/token", Method = HttpMethod.POST, ClientId = clientId, ClientSecret = clientSecret @@ -55,7 +55,7 @@ namespace osu.Game.Online.API { var req = new AccessTokenRequestRefresh(refresh) { - Url = $@"{endpoint}/oauth/access_token", + Url = $@"{endpoint}/oauth/token", Method = HttpMethod.POST, ClientId = clientId, ClientSecret = clientSecret From 01dc7cb5c281146f810087ea2a8058a92d20d291 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Nov 2016 19:22:36 +0900 Subject: [PATCH 105/133] Thread safety, username saving correctly etc. --- osu.Game/Configuration/OsuConfigManager.cs | 2 +- osu.Game/Online/API/APIAccess.cs | 28 +++++++++++----------- osu.Game/OsuGameBase.cs | 13 ++++++++++ osu.Game/Overlays/Toolbar.cs | 4 ++++ 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 86e26048ab..8657f74d87 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -156,7 +156,7 @@ namespace osu.Game.Configuration Set(OsuConfig.AudioDevice, string.Empty); //Set(OsuConfig.ReleaseStream, ReleaseStream.Lazer, true); Set(OsuConfig.UpdateFailCount, 0); - //Set(OsuConfig.SavePassword, Password != null); + Set(OsuConfig.SavePassword, false); Set(OsuConfig.SaveUsername, true); //Set(OsuConfig.TreeSortMode, TreeGroupMode.Show_All); //Set(OsuConfig.TreeSortMode2, TreeSortMode.Title); diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index a6717b99db..2af10e44e8 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -28,15 +28,9 @@ namespace osu.Game.Online.API public string Username; - private SecurePassword password; + //private SecurePassword password; - public string Password - { - set - { - password = string.IsNullOrEmpty(value) ? null : new SecurePassword(value); - } - } + public string Password; public string Token { @@ -52,7 +46,7 @@ namespace osu.Game.Online.API } } - protected bool HasLogin => Token != null || (!string.IsNullOrEmpty(Username) && password != null); + protected bool HasLogin => Token != null || (!string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password)); private Thread thread; @@ -71,13 +65,19 @@ namespace osu.Game.Online.API public void Register(IOnlineComponent component) { - components.Add(component); - component.APIStateChanged(this, state); + Scheduler.Add(delegate + { + components.Add(component); + component.APIStateChanged(this, state); + }); } public void Unregister(IOnlineComponent component) { - components.Remove(component); + Scheduler.Add(delegate + { + components.Remove(component); + }); } public string AccessToken => authentication.RequestAccessToken(); @@ -117,7 +117,7 @@ namespace osu.Game.Online.API if (State < APIState.Connecting) State = APIState.Connecting; - if (!authentication.HasValidAccessToken && !authentication.AuthenticateWithLogin(Username, password.Get(Representation.Raw))) + if (!authentication.HasValidAccessToken && !authentication.AuthenticateWithLogin(Username, Password)) { //todo: this fails even on network-related issues. we should probably handle those differently. //NotificationManager.ShowMessage("Login failed!"); @@ -157,7 +157,7 @@ namespace osu.Game.Online.API private void ClearCredentials() { Username = null; - password = null; + Password = null; } public void Login(string username, string password) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 4399a9f0c3..530f380305 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -73,6 +73,19 @@ namespace osu.Game Password = Config.Get(OsuConfig.Password), Token = Config.Get(OsuConfig.Token) }); + + API.OnStateChange += apiStateChanged; + } + + private void apiStateChanged(APIState oldState, APIState newState) + { + switch (newState) + { + case APIState.Online: + Config.Set(OsuConfig.Username, Config.Get(OsuConfig.SaveUsername) ? API.Username : string.Empty); + Config.Set(OsuConfig.Password, Config.Get(OsuConfig.SavePassword) ? API.Password : string.Empty); + break; + } } protected override void LoadComplete() diff --git a/osu.Game/Overlays/Toolbar.cs b/osu.Game/Overlays/Toolbar.cs index 190615de29..65d1017d1c 100644 --- a/osu.Game/Overlays/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar.cs @@ -139,6 +139,10 @@ namespace osu.Game.Overlays private void load(OsuConfigManager config) { userButton.Text = config.Get(OsuConfig.Username); + config.GetBindable(OsuConfig.Username).ValueChanged += delegate + { + userButton.Text = config.Get(OsuConfig.Username); + }; } public void SetGameMode(PlayMode mode) => modeSelector.SetGameMode(mode); From ed879f33df7548759595dcda138eaa0438b2bf57 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Nov 2016 19:43:03 +0900 Subject: [PATCH 106/133] Add logout button and check for inputs before allowing login. --- osu.Game/Online/API/APIAccess.cs | 1 + .../Overlays/Options/General/LoginOptions.cs | 38 +++++++++++++------ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 2af10e44e8..195042ddb9 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -281,6 +281,7 @@ namespace osu.Game.Online.API public void Logout() { + ClearCredentials(); authentication.Clear(); State = APIState.Offline; } diff --git a/osu.Game/Overlays/Options/General/LoginOptions.cs b/osu.Game/Overlays/Options/General/LoginOptions.cs index c978a8c7ba..0bca31d2c1 100644 --- a/osu.Game/Overlays/Options/General/LoginOptions.cs +++ b/osu.Game/Overlays/Options/General/LoginOptions.cs @@ -14,6 +14,7 @@ namespace osu.Game.Overlays.Options.General public class LoginOptions : OptionsSubsection, IOnlineComponent { private Container loginForm; + private APIAccess api; protected override string Header => "Sign In"; public LoginOptions() @@ -32,6 +33,7 @@ namespace osu.Game.Overlays.Options.General [BackgroundDependencyLoader(permitNulls: true)] private void load(APIAccess api) { + this.api = api; api?.Register(this); } @@ -48,33 +50,44 @@ namespace osu.Game.Overlays.Options.General case APIState.Failing: loginForm.Children = new Drawable[] { - new SpriteText - { - Text = @"Connection failing :(", + new SpriteText + { + Text = @"Connection failing :(", }, }; break; case APIState.Connecting: loginForm.Children = new Drawable[] { - new SpriteText - { - Text = @"Connecting...", + new SpriteText + { + Text = @"Connecting...", }, }; break; case APIState.Online: loginForm.Children = new Drawable[] { - new SpriteText - { - Text = $@"Connected as {api.Username}!", + new SpriteText + { + Text = $@"Connected as {api.Username}!", }, + new OsuButton + { + RelativeSizeAxes = Axes.X, + Text = "Sign out", + Action = performLogout + } }; break; } - } - + } + + private void performLogout() + { + api.Logout(); + } + class LoginForm : FlowContainer { private APIAccess api; @@ -106,7 +119,8 @@ namespace osu.Game.Overlays.Options.General private void performLogin() { - api.Login(username.Text, password.Text); + if (!string.IsNullOrEmpty(username.Text) && !string.IsNullOrEmpty(password.Text)) + api.Login(username.Text, password.Text); } [BackgroundDependencyLoader(permitNulls: true)] From 27a13eec97a292d828aa2e8e440d0bef2d4d7194 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Wed, 30 Nov 2016 20:22:23 +0100 Subject: [PATCH 107/133] Fix options sidebar being transparent when moving in from the side, showing a view of the broken region left of the gamemode stack. --- osu.Game/Overlays/OptionsOverlay.cs | 82 +++++++++++++++++------------ 1 file changed, 47 insertions(+), 35 deletions(-) diff --git a/osu.Game/Overlays/OptionsOverlay.cs b/osu.Game/Overlays/OptionsOverlay.cs index 33677799f1..e9b7a1cc50 100644 --- a/osu.Game/Overlays/OptionsOverlay.cs +++ b/osu.Game/Overlays/OptionsOverlay.cs @@ -38,6 +38,7 @@ namespace osu.Game.Overlays private const float sidebar_padding = 10; + private Container scrollableSection; private ScrollContainer scrollContainer; private OptionsSidebar sidebar; private SidebarButton[] sidebarButtons; @@ -64,50 +65,59 @@ namespace osu.Game.Overlays Children = new Drawable[] { - new Box + scrollableSection = new Container() { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Alpha = 0.6f, - }, - scrollContainer = new ScrollContainer - { - ScrollDraggerVisible = false, RelativeSizeAxes = Axes.Y, - Width = width, - Margin = new MarginPadding { Left = SIDEBAR_WIDTH }, - Children = new[] - { - new FlowContainer - { - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - Direction = FlowDirection.VerticalOnly, + AutoSizeAxes = Axes.X, - Children = new Drawable[] + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + Alpha = 0.6f, + }, + scrollContainer = new ScrollContainer + { + ScrollDraggerVisible = false, + RelativeSizeAxes = Axes.Y, + Width = width, + Margin = new MarginPadding { Left = SIDEBAR_WIDTH }, + Children = new[] { - new SpriteText - { - Text = "settings", - TextSize = 40, - Margin = new MarginPadding { Left = CONTENT_MARGINS, Top = 30 }, - }, - new SpriteText - { - Colour = new Color4(255, 102, 170, 255), - Text = "Change the way osu! behaves", - TextSize = 18, - Margin = new MarginPadding { Left = CONTENT_MARGINS, Bottom = 30 }, - }, new FlowContainer { AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, Direction = FlowDirection.VerticalOnly, - Children = sections, + + Children = new Drawable[] + { + new SpriteText + { + Text = "settings", + TextSize = 40, + Margin = new MarginPadding { Left = CONTENT_MARGINS, Top = 30 }, + }, + new SpriteText + { + Colour = new Color4(255, 102, 170, 255), + Text = "Change the way osu! behaves", + TextSize = 18, + Margin = new MarginPadding { Left = CONTENT_MARGINS, Bottom = 30 }, + }, + new FlowContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Direction = FlowDirection.VerticalOnly, + Children = sections, + } + } } } - } + }, } }, sidebar = new OptionsSidebar @@ -181,14 +191,16 @@ namespace osu.Game.Overlays { scrollContainer.MoveToX(0, TRANSITION_LENGTH, EasingTypes.OutQuint); sidebar.MoveToX(0, TRANSITION_LENGTH, EasingTypes.OutQuint); - FadeTo(1, TRANSITION_LENGTH / 2); + + scrollableSection.FadeTo(1, TRANSITION_LENGTH / 2); } protected override void PopOut() { scrollContainer.MoveToX(-width, TRANSITION_LENGTH, EasingTypes.OutQuint); sidebar.MoveToX(-SIDEBAR_WIDTH, TRANSITION_LENGTH, EasingTypes.OutQuint); - FadeTo(0, TRANSITION_LENGTH / 2); + + scrollableSection.FadeTo(0, TRANSITION_LENGTH / 2); } } } From 380303902d7b20013a2bdbd56b4c870c7000eb11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Wed, 30 Nov 2016 20:22:47 +0100 Subject: [PATCH 108/133] Update framework. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 4fd477755a..976d7833e8 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 4fd477755a640a497c04fc8e540e8641278aa056 +Subproject commit 976d7833e85ff880e9b00e8c121747f59becb2d8 From 579b8328dcbc7e604d85175c6f1e1ef1beead44e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Wed, 30 Nov 2016 20:50:41 +0100 Subject: [PATCH 109/133] Revert "Fix options sidebar being transparent when moving in from the side, showing a view of the broken region left of the gamemode stack." This reverts commit 27a13eec97a292d828aa2e8e440d0bef2d4d7194. --- osu.Game/Overlays/OptionsOverlay.cs | 80 ++++++++++++----------------- 1 file changed, 34 insertions(+), 46 deletions(-) diff --git a/osu.Game/Overlays/OptionsOverlay.cs b/osu.Game/Overlays/OptionsOverlay.cs index e9b7a1cc50..33677799f1 100644 --- a/osu.Game/Overlays/OptionsOverlay.cs +++ b/osu.Game/Overlays/OptionsOverlay.cs @@ -38,7 +38,6 @@ namespace osu.Game.Overlays private const float sidebar_padding = 10; - private Container scrollableSection; private ScrollContainer scrollContainer; private OptionsSidebar sidebar; private SidebarButton[] sidebarButtons; @@ -65,59 +64,50 @@ namespace osu.Game.Overlays Children = new Drawable[] { - scrollableSection = new Container() + new Box { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + Alpha = 0.6f, + }, + scrollContainer = new ScrollContainer + { + ScrollDraggerVisible = false, RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - - Children = new Drawable[] + Width = width, + Margin = new MarginPadding { Left = SIDEBAR_WIDTH }, + Children = new[] { - new Box + new FlowContainer { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Alpha = 0.6f, - }, - scrollContainer = new ScrollContainer - { - ScrollDraggerVisible = false, - RelativeSizeAxes = Axes.Y, - Width = width, - Margin = new MarginPadding { Left = SIDEBAR_WIDTH }, - Children = new[] + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Direction = FlowDirection.VerticalOnly, + + Children = new Drawable[] { + new SpriteText + { + Text = "settings", + TextSize = 40, + Margin = new MarginPadding { Left = CONTENT_MARGINS, Top = 30 }, + }, + new SpriteText + { + Colour = new Color4(255, 102, 170, 255), + Text = "Change the way osu! behaves", + TextSize = 18, + Margin = new MarginPadding { Left = CONTENT_MARGINS, Bottom = 30 }, + }, new FlowContainer { AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, Direction = FlowDirection.VerticalOnly, - - Children = new Drawable[] - { - new SpriteText - { - Text = "settings", - TextSize = 40, - Margin = new MarginPadding { Left = CONTENT_MARGINS, Top = 30 }, - }, - new SpriteText - { - Colour = new Color4(255, 102, 170, 255), - Text = "Change the way osu! behaves", - TextSize = 18, - Margin = new MarginPadding { Left = CONTENT_MARGINS, Bottom = 30 }, - }, - new FlowContainer - { - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - Direction = FlowDirection.VerticalOnly, - Children = sections, - } - } + Children = sections, } } - }, + } } }, sidebar = new OptionsSidebar @@ -191,16 +181,14 @@ namespace osu.Game.Overlays { scrollContainer.MoveToX(0, TRANSITION_LENGTH, EasingTypes.OutQuint); sidebar.MoveToX(0, TRANSITION_LENGTH, EasingTypes.OutQuint); - - scrollableSection.FadeTo(1, TRANSITION_LENGTH / 2); + FadeTo(1, TRANSITION_LENGTH / 2); } protected override void PopOut() { scrollContainer.MoveToX(-width, TRANSITION_LENGTH, EasingTypes.OutQuint); sidebar.MoveToX(-SIDEBAR_WIDTH, TRANSITION_LENGTH, EasingTypes.OutQuint); - - scrollableSection.FadeTo(0, TRANSITION_LENGTH / 2); + FadeTo(0, TRANSITION_LENGTH / 2); } } } From 3a4fb2ffedd25cf4945771673b45747dfef4142c Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 1 Dec 2016 08:20:24 +0800 Subject: [PATCH 110/133] IsEnabled property for drag bar of music controller. --- osu.Game/Overlays/DragBar.cs | 15 ++++++++++++++- osu.Game/Overlays/MusicController.cs | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/DragBar.cs b/osu.Game/Overlays/DragBar.cs index ee54d21d74..32a1ed4933 100644 --- a/osu.Game/Overlays/DragBar.cs +++ b/osu.Game/Overlays/DragBar.cs @@ -16,6 +16,18 @@ namespace osu.Game.Overlays public Action SeekRequested; private bool isDragging; + private bool enabled; + public bool IsEnabled + { + get { return enabled; } + set + { + enabled = value; + if (!enabled) + fill.Width = 0; + } + } + public DragBar() { RelativeSizeAxes = Axes.X; @@ -34,13 +46,14 @@ namespace osu.Game.Overlays public void UpdatePosition(float position) { - if (isDragging) return; + if (isDragging || !IsEnabled) return; fill.Width = position; } private void seek(InputState state) { + if (!IsEnabled) return; float seekLocation = state.Mouse.Position.X / DrawWidth; SeekRequested?.Invoke(seekLocation); fill.Width = seekLocation; diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index e8be9efb1b..c69624bfda 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -240,6 +240,7 @@ namespace osu.Game.Overlays private void workingChanged(object sender = null, EventArgs e = null) { + progress.IsEnabled = (beatmapSource.Value != null); if (beatmapSource.Value == current) return; bool audioEquals = current?.BeatmapInfo.AudioEquals(beatmapSource.Value.BeatmapInfo) ?? false; current = beatmapSource.Value; From 9d05c132e85ae4ec96963de293379c39129474b7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Dec 2016 13:03:40 +0900 Subject: [PATCH 111/133] Make Toolbar an IOnlineComponent to tidy up state change logic. --- osu.Game/Overlays/Toolbar.cs | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Toolbar.cs b/osu.Game/Overlays/Toolbar.cs index 7f43d4058c..3404263486 100644 --- a/osu.Game/Overlays/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar.cs @@ -16,10 +16,11 @@ using osu.Framework.Graphics.Colour; using osu.Game.Modes; using osu.Game.Screens.Play; using osu.Framework.Input; +using osu.Game.Online.API; namespace osu.Game.Overlays { - public class Toolbar : OverlayContainer + public class Toolbar : OverlayContainer, IOnlineComponent { private const float height = 50; @@ -144,15 +145,24 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(OsuConfigManager config) + private void load(APIAccess api, OsuConfigManager config) { - userButton.Text = config.Get(OsuConfig.Username); - config.GetBindable(OsuConfig.Username).ValueChanged += delegate - { - userButton.Text = config.Get(OsuConfig.Username); - }; + api.Register(this); } public void SetGameMode(PlayMode mode) => modeSelector.SetGameMode(mode); + + public void APIStateChanged(APIAccess api, APIState state) + { + switch (state) + { + default: + userButton.Text = @"Guest"; + break; + case APIState.Online: + userButton.Text = api.Username; + break; + } + } } } From 13d26d0601ced67b0456b19ebde0622439ff4dbc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Dec 2016 13:07:19 +0900 Subject: [PATCH 112/133] Tidy up options login section code; fix incorrect flow logic for online state. --- .../Overlays/Options/General/LoginOptions.cs | 43 ++++++------------- 1 file changed, 12 insertions(+), 31 deletions(-) diff --git a/osu.Game/Overlays/Options/General/LoginOptions.cs b/osu.Game/Overlays/Options/General/LoginOptions.cs index 0bca31d2c1..4025b3f47a 100644 --- a/osu.Game/Overlays/Options/General/LoginOptions.cs +++ b/osu.Game/Overlays/Options/General/LoginOptions.cs @@ -14,27 +14,14 @@ namespace osu.Game.Overlays.Options.General public class LoginOptions : OptionsSubsection, IOnlineComponent { private Container loginForm; - private APIAccess api; - protected override string Header => "Sign In"; - public LoginOptions() - { - Children = new[] - { - loginForm = new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new[] { new LoadingAnimation() } - } - }; - } + private Action performLogout; + protected override string Header => "Sign In"; [BackgroundDependencyLoader(permitNulls: true)] private void load(APIAccess api) - { - this.api = api; - api?.Register(this); + { + api?.Register(this); } public void APIStateChanged(APIAccess api, APIState state) @@ -42,13 +29,13 @@ namespace osu.Game.Overlays.Options.General switch (state) { case APIState.Offline: - loginForm.Children = new Drawable[] + Children = new Drawable[] { - new LoginForm(api) + new LoginForm() }; break; case APIState.Failing: - loginForm.Children = new Drawable[] + Children = new Drawable[] { new SpriteText { @@ -57,7 +44,7 @@ namespace osu.Game.Overlays.Options.General }; break; case APIState.Connecting: - loginForm.Children = new Drawable[] + Children = new Drawable[] { new SpriteText { @@ -66,7 +53,7 @@ namespace osu.Game.Overlays.Options.General }; break; case APIState.Online: - loginForm.Children = new Drawable[] + Children = new Drawable[] { new SpriteText { @@ -76,26 +63,20 @@ namespace osu.Game.Overlays.Options.General { RelativeSizeAxes = Axes.X, Text = "Sign out", - Action = performLogout + Action = api.Logout } }; break; } } - private void performLogout() - { - api.Logout(); - } - class LoginForm : FlowContainer { - private APIAccess api; - private TextBox username; private TextBox password; + private APIAccess api; - public LoginForm(APIAccess api) + public LoginForm() { Direction = FlowDirection.VerticalOnly; AutoSizeAxes = Axes.Y; From 167b559a9512f8e09fd50368b4ead90c1bb9e3dd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Dec 2016 14:22:29 +0900 Subject: [PATCH 113/133] Move toolbar to own namespace. --- osu.Game/OsuGame.cs | 1 + osu.Game/Overlays/{ => Toolbar}/Toolbar.cs | 16 +++++++--------- osu.Game/Overlays/{ => Toolbar}/ToolbarButton.cs | 5 ++--- .../Overlays/{ => Toolbar}/ToolbarModeButton.cs | 6 +----- .../{ => Toolbar}/ToolbarModeSelector.cs | 11 ++++------- osu.Game/osu.Game.csproj | 8 ++++---- 6 files changed, 19 insertions(+), 28 deletions(-) rename osu.Game/Overlays/{ => Toolbar}/Toolbar.cs (95%) rename osu.Game/Overlays/{ => Toolbar}/ToolbarButton.cs (95%) rename osu.Game/Overlays/{ => Toolbar}/ToolbarModeButton.cs (88%) rename osu.Game/Overlays/{ => Toolbar}/ToolbarModeSelector.cs (93%) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 733cb83aa8..d481a446b8 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -21,6 +21,7 @@ using osu.Game.Database; using osu.Framework.Allocation; using osu.Framework.Graphics.Transformations; using osu.Game.Modes; +using osu.Game.Overlays.Toolbar; using osu.Game.Screens; using osu.Game.Screens.Menu; using osu.Game.Screens.Play; diff --git a/osu.Game/Overlays/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs similarity index 95% rename from osu.Game/Overlays/Toolbar.cs rename to osu.Game/Overlays/Toolbar/Toolbar.cs index 3404263486..966a0d3617 100644 --- a/osu.Game/Overlays/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -2,23 +2,21 @@ //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using OpenTK; -using OpenTK.Graphics; -using osu.Framework; +using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Transformations; +using osu.Framework.Input; using osu.Game.Configuration; using osu.Game.Graphics; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Allocation; -using osu.Framework.Graphics.Colour; using osu.Game.Modes; -using osu.Game.Screens.Play; -using osu.Framework.Input; using osu.Game.Online.API; +using OpenTK; +using OpenTK.Graphics; -namespace osu.Game.Overlays +namespace osu.Game.Overlays.Toolbar { public class Toolbar : OverlayContainer, IOnlineComponent { diff --git a/osu.Game/Overlays/ToolbarButton.cs b/osu.Game/Overlays/Toolbar/ToolbarButton.cs similarity index 95% rename from osu.Game/Overlays/ToolbarButton.cs rename to osu.Game/Overlays/Toolbar/ToolbarButton.cs index 1d8bf51795..798dcc214f 100644 --- a/osu.Game/Overlays/ToolbarButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarButton.cs @@ -4,15 +4,14 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Sprites; using osu.Framework.Input; using osu.Game.Graphics; using OpenTK; using OpenTK.Graphics; -using osu.Framework; -using osu.Framework.Graphics.Primitives; -namespace osu.Game.Overlays +namespace osu.Game.Overlays.Toolbar { public class ToolbarButton : Container { diff --git a/osu.Game/Overlays/ToolbarModeButton.cs b/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs similarity index 88% rename from osu.Game/Overlays/ToolbarModeButton.cs rename to osu.Game/Overlays/Toolbar/ToolbarModeButton.cs index c10b8514db..e0b384c333 100644 --- a/osu.Game/Overlays/ToolbarModeButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs @@ -3,13 +3,9 @@ using osu.Framework.Extensions; using osu.Game.Graphics; -using OpenTK.Graphics; -using osu.Framework; -using osu.Framework.Allocation; using osu.Game.Modes; -using osu.Game.Screens.Play; -namespace osu.Game.Overlays +namespace osu.Game.Overlays.Toolbar { public class ToolbarModeButton : ToolbarButton { diff --git a/osu.Game/Overlays/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs similarity index 93% rename from osu.Game/Overlays/ToolbarModeSelector.cs rename to osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs index 9b6d8a7fe1..1a0683c571 100644 --- a/osu.Game/Overlays/ToolbarModeSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs @@ -3,19 +3,16 @@ using System; using System.Linq; +using osu.Framework.Caching; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Transformations; +using osu.Game.Modes; using OpenTK; using OpenTK.Graphics; -using osu.Framework; -using osu.Framework.Caching; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Allocation; -using osu.Game.Modes; -using osu.Game.Screens.Play; -namespace osu.Game.Overlays +namespace osu.Game.Overlays.Toolbar { class ToolbarModeSelector : Container { diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 581ab7916d..e51abbed5a 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -159,10 +159,10 @@ - - - - + + + + From 0b0fe2a857f6969156547cbd591e7e6e1d3f8b18 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Dec 2016 16:04:58 +0900 Subject: [PATCH 114/133] Remove incorrect verbatim string specifications. --- osu.Game/Overlays/Options/General/LoginOptions.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Options/General/LoginOptions.cs b/osu.Game/Overlays/Options/General/LoginOptions.cs index 4025b3f47a..94eb6b1c01 100644 --- a/osu.Game/Overlays/Options/General/LoginOptions.cs +++ b/osu.Game/Overlays/Options/General/LoginOptions.cs @@ -39,7 +39,7 @@ namespace osu.Game.Overlays.Options.General { new SpriteText { - Text = @"Connection failing :(", + Text = "Connection failing :(", }, }; break; @@ -48,7 +48,7 @@ namespace osu.Game.Overlays.Options.General { new SpriteText { - Text = @"Connecting...", + Text = "Connecting...", }, }; break; @@ -57,7 +57,7 @@ namespace osu.Game.Overlays.Options.General { new SpriteText { - Text = $@"Connected as {api.Username}!", + Text = $"Connected as {api.Username}!", }, new OsuButton { From d7ab74363d19be47723777fd59ca993d09b21372 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Dec 2016 16:05:54 +0900 Subject: [PATCH 115/133] Simplify toolbar width/padding calculations. Add avatar display (incorrect user id). --- osu-resources | 2 +- osu.Game/Overlays/Toolbar/Toolbar.cs | 27 +--- osu.Game/Overlays/Toolbar/ToolbarButton.cs | 12 +- .../Overlays/Toolbar/ToolbarModeSelector.cs | 10 +- .../Overlays/Toolbar/ToolbarUserButton.cs | 138 ++++++++++++++++++ osu.Game/osu.Game.csproj | 1 + 6 files changed, 155 insertions(+), 35 deletions(-) create mode 100644 osu.Game/Overlays/Toolbar/ToolbarUserButton.cs diff --git a/osu-resources b/osu-resources index ab7b953ec9..14813bc7b6 160000 --- a/osu-resources +++ b/osu-resources @@ -1 +1 @@ -Subproject commit ab7b953ec9393d8df5aeb23d23e8b1f8154601c1 +Subproject commit 14813bc7b6a570b2d727ee1f4bf4265d150a20fc diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index 966a0d3617..a1af1d3293 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -18,7 +18,7 @@ using OpenTK.Graphics; namespace osu.Game.Overlays.Toolbar { - public class Toolbar : OverlayContainer, IOnlineComponent + public class Toolbar : OverlayContainer { private const float height = 50; @@ -28,7 +28,6 @@ namespace osu.Game.Overlays.Toolbar public Action OnMusicController; private ToolbarModeSelector modeSelector; - private ToolbarButton userButton; private Box solidBackground; private Box gradientBackground; @@ -126,10 +125,7 @@ namespace osu.Game.Overlays.Toolbar { Icon = FontAwesome.fa_search }, - userButton = new ToolbarButton - { - Icon = FontAwesome.fa_user, - }, + new ToolbarUserButton(), new ToolbarButton { Icon = FontAwesome.fa_bars @@ -142,25 +138,6 @@ namespace osu.Game.Overlays.Toolbar Size = new Vector2(1, height); } - [BackgroundDependencyLoader] - private void load(APIAccess api, OsuConfigManager config) - { - api.Register(this); - } - public void SetGameMode(PlayMode mode) => modeSelector.SetGameMode(mode); - - public void APIStateChanged(APIAccess api, APIState state) - { - switch (state) - { - default: - userButton.Text = @"Guest"; - break; - case APIState.Online: - userButton.Text = api.Username; - break; - } - } } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarButton.cs b/osu.Game/Overlays/Toolbar/ToolbarButton.cs index 798dcc214f..84bf671631 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarButton.cs @@ -15,8 +15,6 @@ namespace osu.Game.Overlays.Toolbar { public class ToolbarButton : Container { - public const float WIDTH = 60; - public FontAwesome Icon { get { return DrawableIcon.Icon; } @@ -57,6 +55,7 @@ namespace osu.Game.Overlays.Toolbar private FlowContainer tooltipContainer; private SpriteText tooltip1; private SpriteText tooltip2; + protected FlowContainer Flow; public ToolbarButton() { @@ -69,12 +68,13 @@ namespace osu.Game.Overlays.Toolbar Colour = new Color4(60, 60, 60, 255), Alpha = 0, }, - new FlowContainer + Flow = new FlowContainer { Direction = FlowDirection.HorizontalOnly, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Padding = new MarginPadding { Left = 5, Right = 5 }, + Padding = new MarginPadding { Left = 15, Right = 15 }, + Spacing = new Vector2(5), RelativeSizeAxes = Axes.Y, AutoSizeAxes = Axes.X, Children = new Drawable[] @@ -86,7 +86,6 @@ namespace osu.Game.Overlays.Toolbar }, DrawableText = new SpriteText { - Margin = new MarginPadding { Left = 5 }, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, }, @@ -117,7 +116,6 @@ namespace osu.Game.Overlays.Toolbar }; RelativeSizeAxes = Axes.Y; - Size = new Vector2(WIDTH, 1); } protected override void Update() @@ -125,7 +123,7 @@ namespace osu.Game.Overlays.Toolbar base.Update(); //todo: find a way to avoid using this (autosize needs to be able to ignore certain drawables.. in this case the tooltip) - Size = new Vector2(WIDTH + (DrawableText.IsVisible ? DrawableText.DrawSize.X : 0), 1); + Size = new Vector2(Flow.DrawSize.X, 1); } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true; diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs index 1a0683c571..635fedb781 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs @@ -6,6 +6,7 @@ using System.Linq; using osu.Framework.Caching; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Transformations; using osu.Game.Modes; @@ -42,6 +43,7 @@ namespace osu.Game.Overlays.Toolbar Direction = FlowDirection.HorizontalOnly, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, + Padding = new MarginPadding { Left = 10, Right = 10 }, }, modeButtonLine = new Box { @@ -69,9 +71,13 @@ namespace osu.Game.Overlays.Toolbar } }); } + } - // We need to set the size within LoadComplete, because - Size = new Vector2(amountButtons * ToolbarButton.WIDTH + padding * 2, 1); + protected override void Update() + { + base.Update(); + + Size = new Vector2(modeButtons.DrawSize.X, 1); } public void SetGameMode(PlayMode mode) diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs new file mode 100644 index 0000000000..375074ad9e --- /dev/null +++ b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs @@ -0,0 +1,138 @@ +//Copyright (c) 2007-2016 ppy Pty Ltd . +//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +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.Configuration; +using osu.Game.Online.API; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Overlays.Toolbar +{ + class ToolbarUserButton : ToolbarButton, IOnlineComponent + { + private Avatar avatar; + + public ToolbarUserButton() + { + DrawableText.Font = @"Exo2.0-MediumItalic"; + + Flow.Add(avatar = new Avatar()); + } + + [BackgroundDependencyLoader] + private void load(APIAccess api, OsuConfigManager config) + { + api.Register(this); + } + + public void APIStateChanged(APIAccess api, APIState state) + { + switch (state) + { + default: + Text = @"Guest"; + avatar.UserId = 1; + break; + case APIState.Online: + Text = api.Username; + avatar.UserId = 2; + break; + } + } + + public class Avatar : Container + { + public Drawable Sprite; + + private int userId; + private OsuGame game; + private Texture guestTexture; + + public Avatar() + { + Size = new Vector2(32); + Anchor = Anchor.CentreLeft; + Origin = Anchor.CentreLeft; + + CornerRadius = Size.X / 8; + + EdgeEffect = new EdgeEffect + { + Type = EdgeEffectType.Shadow, + Radius = 4, + Colour = new Color4(0, 0, 0, 25), + }; + + Masking = true; + } + + [BackgroundDependencyLoader] + private void load(OsuGame game, TextureStore textures) + { + this.game = game; + + guestTexture = textures.Get(@"Online/avatar-guest@2x"); + } + + public int UserId + { + get { return userId; } + set + { + if (userId == value) + return; + + userId = value; + + Sprite newSprite; + if (userId > 1) + newSprite = new OnlineSprite($@"https://a.ppy.sh/{userId}"); + else + newSprite = new Sprite { Texture = guestTexture }; + + newSprite.FillMode = FillMode.Fit; + + newSprite.Preload(game, s => + { + Sprite?.FadeOut(); + Sprite?.Expire(); + Sprite = s; + + Add(s); + + s.FadeInFromZero(200); + }); + } + } + + public class OnlineSprite : Sprite + { + private readonly string url; + private readonly int userId; + + public OnlineSprite(string url) + { + Debug.Assert(url != null); + this.url = url; + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + Texture = textures.Get(url); + } + } + } + } +} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index e51abbed5a..76e59db76f 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -90,6 +90,7 @@ + From 6ccce88a0e434bbc5f5ae6d9c849d5a4b59d003f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Dec 2016 16:44:24 +0900 Subject: [PATCH 116/133] Add proper user data retrieval on connect. --- osu.Game/Online/API/APIAccess.cs | 14 ++++++++++++++ osu.Game/Online/API/Requests/GetUserRequest.cs | 18 ++++++++++++++++++ osu.Game/Online/User.cs | 3 +++ osu.Game/OsuGameBase.cs | 12 +++++++----- osu.Game/Overlays/Toolbar/ToolbarUserButton.cs | 2 +- osu.Game/osu.Game.csproj | 1 + 6 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 osu.Game/Online/API/Requests/GetUserRequest.cs diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 195042ddb9..68557f63f2 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -8,6 +8,7 @@ using System.Diagnostics; using System.Net; using System.Threading; using osu.Framework; +using osu.Framework.Configuration; using osu.Framework.Logging; using osu.Framework.Threading; using osu.Game.Online.API.Requests; @@ -32,6 +33,8 @@ namespace osu.Game.Online.API public string Password; + public Bindable LocalUser = new Bindable(); + public string Token { get { return authentication.Token?.ToString(); } @@ -126,6 +129,17 @@ namespace osu.Game.Online.API continue; } + + var userReq = new GetUserRequest(); + userReq.Success += (u) => { + LocalUser.Value = u; + }; + if (!handleRequest(userReq)) + { + State = APIState.Failing; + continue; + } + //we're connected! State = APIState.Online; failureCount = 0; diff --git a/osu.Game/Online/API/Requests/GetUserRequest.cs b/osu.Game/Online/API/Requests/GetUserRequest.cs new file mode 100644 index 0000000000..1f6da1e1de --- /dev/null +++ b/osu.Game/Online/API/Requests/GetUserRequest.cs @@ -0,0 +1,18 @@ +//Copyright (c) 2007-2016 ppy Pty Ltd . +//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + + +namespace osu.Game.Online.API.Requests +{ + public class GetUserRequest : APIRequest + { + private int? userId; + + public GetUserRequest(int? userId = null) + { + this.userId = userId; + } + + protected override string Target => userId.HasValue ? $@"users/{userId}" : @"me"; + } +} diff --git a/osu.Game/Online/User.cs b/osu.Game/Online/User.cs index 27de5d8dc2..134167e868 100644 --- a/osu.Game/Online/User.cs +++ b/osu.Game/Online/User.cs @@ -10,6 +10,9 @@ namespace osu.Game.Online [JsonProperty(@"username")] public string Name; + [JsonProperty(@"id")] + public int Id; + [JsonProperty(@"colour")] public string Colour; } diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 530f380305..5b35b1e672 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -16,12 +16,14 @@ using osu.Game.Database; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.Processing; using osu.Game.IPC; +using osu.Game.Online; using osu.Game.Online.API; using osu.Game.Overlays; +using osu.Game.Online.API.Requests; namespace osu.Game { - public class OsuGameBase : BaseGame + public class OsuGameBase : BaseGame, IOnlineComponent { internal OsuConfigManager Config; @@ -43,7 +45,7 @@ namespace osu.Game Dependencies.Cache(this); Dependencies.Cache(Config); Dependencies.Cache(new BeatmapDatabase(Host.Storage, Host)); - + //this completely overrides the framework default. will need to change once we make a proper FontStore. Dependencies.Cache(Fonts = new FontStore { ScaleAdjust = 0.01f }, true); @@ -74,12 +76,12 @@ namespace osu.Game Token = Config.Get(OsuConfig.Token) }); - API.OnStateChange += apiStateChanged; + API.Register(this); } - private void apiStateChanged(APIState oldState, APIState newState) + public void APIStateChanged(APIAccess api, APIState state) { - switch (newState) + switch (state) { case APIState.Online: Config.Set(OsuConfig.Username, Config.Get(OsuConfig.SaveUsername) ? API.Username : string.Empty); diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs index 375074ad9e..0c7ea7b797 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs @@ -46,7 +46,7 @@ namespace osu.Game.Overlays.Toolbar break; case APIState.Online: Text = api.Username; - avatar.UserId = 2; + avatar.UserId = api.LocalUser.Value.Id; break; } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 76e59db76f..001eae8432 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -70,6 +70,7 @@ + From 25d3818e7a1b326bec5ab62dcc6f8f46d7c618e7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Dec 2016 17:45:21 +0900 Subject: [PATCH 117/133] Fix game mode selector line regression. --- osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs index 635fedb781..9eca18e9c9 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs @@ -50,7 +50,7 @@ namespace osu.Game.Overlays.Toolbar RelativeSizeAxes = Axes.X, Size = new Vector2(0.3f, 3), Anchor = Anchor.BottomLeft, - Origin = Anchor.TopCentre, + Origin = Anchor.TopLeft, Colour = Color4.White } }; @@ -100,7 +100,7 @@ namespace osu.Game.Overlays.Toolbar base.UpdateLayout(); if (!activeMode.EnsureValid()) - activeMode.Refresh(() => modeButtonLine.MoveToX(activeButton.DrawPosition.X + activeButton.DrawSize.X / 2 + padding, 200, EasingTypes.OutQuint)); + activeMode.Refresh(() => modeButtonLine.MoveToX(activeButton.DrawPosition.X, 200, EasingTypes.OutQuint)); } } } From 6554a4ea58dc7714fa8bd58ddd00e1fddde15e45 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Dec 2016 17:45:32 +0900 Subject: [PATCH 118/133] Fix shadow not displaying around avatar. --- osu.Game/Overlays/Toolbar/ToolbarUserButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs index 0c7ea7b797..d0bae1dbf8 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs @@ -71,7 +71,7 @@ namespace osu.Game.Overlays.Toolbar { Type = EdgeEffectType.Shadow, Radius = 4, - Colour = new Color4(0, 0, 0, 25), + Colour = new Color4(0, 0, 0, 0.1f), }; Masking = true; From 11f958030f5addac6c04e783668698e3fca68501 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Dec 2016 18:53:13 +0900 Subject: [PATCH 119/133] Make Triangles more flexible and more random. --- osu.Game/Beatmaps/Drawables/BeatmapPanel.cs | 41 +----------- osu.Game/Graphics/Backgrounds/Triangles.cs | 63 +++++++++++++++++++ osu.Game/Overlays/Toolbar/ToolbarButton.cs | 33 ++++++++-- .../Overlays/Toolbar/ToolbarModeSelector.cs | 7 +-- .../Overlays/Toolbar/ToolbarUserButton.cs | 2 + osu.Game/osu.Game.csproj | 1 + 6 files changed, 97 insertions(+), 50 deletions(-) create mode 100644 osu.Game/Graphics/Backgrounds/Triangles.cs diff --git a/osu.Game/Beatmaps/Drawables/BeatmapPanel.cs b/osu.Game/Beatmaps/Drawables/BeatmapPanel.cs index 99ba31ab6a..72d1e2f05d 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapPanel.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapPanel.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.Textures; using osu.Framework.MathUtils; using osu.Game.Database; using osu.Game.Graphics; +using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.UserInterface; using OpenTK; using OpenTK.Graphics; @@ -128,45 +129,5 @@ namespace osu.Game.Beatmaps.Drawables } }; } - - public class Triangles : Container - { - private Texture triangle; - - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - triangle = textures.Get(@"Play/osu/triangle@2x"); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - for (int i = 0; i < 10; i++) - { - Add(new Sprite - { - Texture = triangle, - Origin = Anchor.TopCentre, - RelativePositionAxes = Axes.Both, - Position = new Vector2(RNG.NextSingle(), RNG.NextSingle()), - Scale = new Vector2(RNG.NextSingle() * 0.4f + 0.2f), - Alpha = RNG.NextSingle() * 0.3f - }); - } - } - - protected override void Update() - { - base.Update(); - - foreach (Drawable d in Children) - { - d.Position -= new Vector2(0, (float)(d.Scale.X * (Time.Elapsed / 880))); - if (d.DrawPosition.Y + d.DrawSize.Y * d.Scale.Y < 0) - d.MoveToY(1); - } - } - } } } diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs new file mode 100644 index 0000000000..b4afb84114 --- /dev/null +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -0,0 +1,63 @@ +//Copyright (c) 2007-2016 ppy Pty Ltd . +//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Linq; +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.Framework.MathUtils; +using OpenTK; + +namespace osu.Game.Graphics.Backgrounds +{ + public class Triangles : Container + { + private Texture triangle; + + public Triangles() + { + Masking = true; + Alpha = 0.3f; + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + triangle = textures.Get(@"Play/osu/triangle@2x"); + } + + private int aimTriangleCount => (int)((DrawWidth * DrawHeight) / 800); + + protected override void Update() + { + base.Update(); + + foreach (Drawable d in Children) + { + d.Position -= new Vector2(0, (float)(d.Scale.X * (Time.Elapsed / 880))); + if (d.DrawPosition.Y + d.DrawSize.Y * d.Scale.Y < 0) + d.Expire(); + } + + bool useRandomX = Children.Count() < aimTriangleCount / 2; + while (Children.Count() < aimTriangleCount) + addTriangle(useRandomX); + + } + + private void addTriangle(bool randomX) + { + Add(new Sprite + { + Texture = triangle, + Origin = Anchor.TopCentre, + RelativePositionAxes = Axes.Both, + Position = new Vector2(RNG.NextSingle(), randomX ? RNG.NextSingle() : 1), + Scale = new Vector2(RNG.NextSingle() * 0.4f + 0.2f), + Alpha = RNG.NextSingle() + }); + } + } +} diff --git a/osu.Game/Overlays/Toolbar/ToolbarButton.cs b/osu.Game/Overlays/Toolbar/ToolbarButton.cs index 84bf671631..0603fe2b7b 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarButton.cs @@ -6,8 +6,10 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Transformations; using osu.Framework.Input; using osu.Game.Graphics; +using osu.Game.Graphics.Backgrounds; using OpenTK; using OpenTK.Graphics; @@ -64,8 +66,7 @@ namespace osu.Game.Overlays.Toolbar HoverBackground = new Box { RelativeSizeAxes = Axes.Both, - BlendingMode = BlendingMode.Additive, - Colour = new Color4(60, 60, 60, 255), + Colour = new Color4(80, 80, 80, 180), Alpha = 0, }, Flow = new FlowContainer @@ -131,21 +132,43 @@ namespace osu.Game.Overlays.Toolbar protected override bool OnClick(InputState state) { Action?.Invoke(); - HoverBackground.FlashColour(Color4.White, 400); + HoverBackground.FlashColour(new Color4(255, 255, 255, 180), 800, EasingTypes.OutQuint); return true; } protected override bool OnHover(InputState state) { - HoverBackground.FadeTo(0.4f, 200); + HoverBackground.FadeIn(200); tooltipContainer.FadeIn(100); return false; } protected override void OnHoverLost(InputState state) { - HoverBackground.FadeTo(0, 200); + HoverBackground.FadeOut(200); tooltipContainer.FadeOut(100); } } + + public class OpaqueBackground : Container + { + public OpaqueBackground() + { + RelativeSizeAxes = Axes.Both; + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = new Color4(30, 30, 30, 255) + }, + new Triangles + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.05f, + }, + }; + } + } } \ No newline at end of file diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs index 9eca18e9c9..be34359df4 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Transformations; +using osu.Game.Graphics.Backgrounds; using osu.Game.Modes; using OpenTK; using OpenTK.Graphics; @@ -31,11 +32,7 @@ namespace osu.Game.Overlays.Toolbar Children = new Drawable[] { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = new Color4(20, 20, 20, 255) - }, + new OpaqueBackground(), modeButtons = new FlowContainer { RelativeSizeAxes = Axes.Y, diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs index d0bae1dbf8..3a91a007ff 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs @@ -27,6 +27,8 @@ namespace osu.Game.Overlays.Toolbar { DrawableText.Font = @"Exo2.0-MediumItalic"; + Add(new OpaqueBackground { Depth = 1 }); + Flow.Add(avatar = new Avatar()); } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 001eae8432..6f56037026 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -64,6 +64,7 @@ + From 3a5c41b970f8f0ed5c912c24672098640dc1a86e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Dec 2016 18:54:32 +0900 Subject: [PATCH 120/133] Restore additive blending for toolbar button backgrounds. --- osu.Game/Overlays/Toolbar/ToolbarButton.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/Toolbar/ToolbarButton.cs b/osu.Game/Overlays/Toolbar/ToolbarButton.cs index 0603fe2b7b..b0d8135ef4 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarButton.cs @@ -67,6 +67,7 @@ namespace osu.Game.Overlays.Toolbar { RelativeSizeAxes = Axes.Both, Colour = new Color4(80, 80, 80, 180), + BlendingMode = BlendingMode.Additive, Alpha = 0, }, Flow = new FlowContainer From 918a3bc74fbf03b1298531b30164bf63a6b86c9c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Dec 2016 19:15:34 +0900 Subject: [PATCH 121/133] Add glow and bling to game mode selector. --- .../Overlays/Toolbar/ToolbarModeButton.cs | 20 ++++++++++++++++++- .../Overlays/Toolbar/ToolbarModeSelector.cs | 20 ++++++++++++++++--- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs b/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs index e0b384c333..60ce228164 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs @@ -2,8 +2,10 @@ //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Extensions; +using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Modes; +using OpenTK.Graphics; namespace osu.Game.Overlays.Toolbar { @@ -26,7 +28,23 @@ namespace osu.Game.Overlays.Toolbar { set { - //Background.Colour = value ? new Color4(100, 100, 100, 255) : new Color4(20, 20, 20, 255); + if (value) + { + DrawableIcon.Colour = Color4.White; + DrawableIcon.Masking = true; + DrawableIcon.EdgeEffect = new EdgeEffect + { + Type = EdgeEffectType.Glow, + Colour = new Color4(255, 194, 224, 100), + Radius = 15, + Roundness = 15, + }; + } + else + { + DrawableIcon.Masking = false; + DrawableIcon.Colour = new Color4(255, 194, 224, 255); + } } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs index be34359df4..bc60123c02 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs @@ -21,7 +21,7 @@ namespace osu.Game.Overlays.Toolbar const float padding = 10; private FlowContainer modeButtons; - private Box modeButtonLine; + private Drawable modeButtonLine; private ToolbarModeButton activeButton; public Action OnPlayModeChange; @@ -42,13 +42,27 @@ namespace osu.Game.Overlays.Toolbar Origin = Anchor.TopCentre, Padding = new MarginPadding { Left = 10, Right = 10 }, }, - modeButtonLine = new Box + modeButtonLine = new Container { RelativeSizeAxes = Axes.X, Size = new Vector2(0.3f, 3), Anchor = Anchor.BottomLeft, Origin = Anchor.TopLeft, - Colour = Color4.White + Masking = true, + EdgeEffect = new EdgeEffect + { + Type = EdgeEffectType.Glow, + Colour = new Color4(255, 194, 224, 100), + Radius = 15, + Roundness = 15, + }, + Children = new [] + { + new Box + { + RelativeSizeAxes = Axes.Both, + } + } } }; From 1f370fe29cc87f4476786139153c11523111bd49 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Dec 2016 20:21:14 +0900 Subject: [PATCH 122/133] Add animated osu! logo. --- osu-resources | 2 +- osu.Game/Graphics/Backgrounds/Triangles.cs | 39 ++++++++-- osu.Game/Screens/Menu/Intro.cs | 3 +- osu.Game/Screens/Menu/OsuLogo.cs | 87 ++++++++++++++++++++-- 4 files changed, 115 insertions(+), 16 deletions(-) diff --git a/osu-resources b/osu-resources index 14813bc7b6..6edd5eacdd 160000 --- a/osu-resources +++ b/osu-resources @@ -1 +1 @@ -Subproject commit 14813bc7b6a570b2d727ee1f4bf4265d150a20fc +Subproject commit 6edd5eacdd25cc8c4f4dbca3414678c0b7dc5deb diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index b4afb84114..88f3a7d41a 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -3,6 +3,7 @@ using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -22,13 +23,26 @@ namespace osu.Game.Graphics.Backgrounds Alpha = 0.3f; } + private float triangleScale = 1; + + public float TriangleScale + { + get { return triangleScale; } + set + { + triangleScale = value; + + Children.ForEach(t => t.ScaleTo(triangleScale)); + } + } + [BackgroundDependencyLoader] private void load(TextureStore textures) { triangle = textures.Get(@"Play/osu/triangle@2x"); } - private int aimTriangleCount => (int)((DrawWidth * DrawHeight) / 800); + private int aimTriangleCount => (int)((DrawWidth * DrawHeight) / 800 / triangleScale); protected override void Update() { @@ -36,7 +50,7 @@ namespace osu.Game.Graphics.Backgrounds foreach (Drawable d in Children) { - d.Position -= new Vector2(0, (float)(d.Scale.X * (Time.Elapsed / 880))); + d.Position -= new Vector2(0, (float)(d.Scale.X * (50 / DrawHeight) * (Time.Elapsed / 880)) / triangleScale); if (d.DrawPosition.Y + d.DrawSize.Y * d.Scale.Y < 0) d.Expire(); } @@ -47,17 +61,26 @@ namespace osu.Game.Graphics.Backgrounds } - private void addTriangle(bool randomX) + protected virtual Sprite CreateTriangle() { - Add(new Sprite + var scale = triangleScale * RNG.NextSingle() * 0.4f + 0.2f; + + return new Sprite { Texture = triangle, Origin = Anchor.TopCentre, RelativePositionAxes = Axes.Both, - Position = new Vector2(RNG.NextSingle(), randomX ? RNG.NextSingle() : 1), - Scale = new Vector2(RNG.NextSingle() * 0.4f + 0.2f), - Alpha = RNG.NextSingle() - }); + Scale = new Vector2(scale), + Alpha = RNG.NextSingle(), + Depth = scale, + }; + } + + private void addTriangle(bool randomX) + { + var sprite = CreateTriangle(); + sprite.Position = new Vector2(RNG.NextSingle(), randomX ? RNG.NextSingle() : 1); + Add(sprite); } } } diff --git a/osu.Game/Screens/Menu/Intro.cs b/osu.Game/Screens/Menu/Intro.cs index 4474ee8024..5fd02e817d 100644 --- a/osu.Game/Screens/Menu/Intro.cs +++ b/osu.Game/Screens/Menu/Intro.cs @@ -34,9 +34,10 @@ namespace osu.Game.Screens.Menu { Children = new Drawable[] { - logo = new OsuLogo() + logo = new OsuLogo { Alpha = 0, + Triangles = false, BlendingMode = BlendingMode.Additive, Interactive = false, Colour = Color4.DarkGray, diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index 6047339b25..441050abef 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -2,35 +2,50 @@ //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Transformations; using osu.Framework.Input; +using osu.Framework.MathUtils; +using osu.Game.Graphics.Backgrounds; using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Screens.Menu { /// /// osu! logo and its attachments (pulsing, visualiser etc.) /// - public partial class OsuLogo : Container + public partial class OsuLogo : BufferedContainer { private Sprite logo; private CircularContainer logoContainer; private Container logoBounceContainer; private MenuVisualisation vis; + private CircularContainer colourAndTriangles; + public Action Action; - public float SizeForFlow => logo == null ? 0 : logo.DrawSize.X * logo.Scale.X * logoBounceContainer.Scale.X * 0.8f; + public float SizeForFlow => logo == null ? 0 : logo.DrawSize.X * logo.Scale.X * logoBounceContainer.Scale.X * 0.78f; private Sprite ripple; private Container rippleContainer; + public bool Triangles + { + set + { + colourAndTriangles.Alpha = value ? 1 : 0; + } + } + public override bool Contains(Vector2 screenSpacePos) { return logoContainer.Contains(screenSpacePos); @@ -65,12 +80,32 @@ namespace osu.Game.Screens.Menu { AutoSizeAxes = Axes.Both, Anchor = Anchor.Centre, - Children = new[] + Children = new Drawable[] { + colourAndTriangles = new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Scale = new Vector2(0.78f), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = new Color4(233, 103, 161, 255), + }, + new OsuLogoTriangles + { + RelativeSizeAxes = Axes.Both, + }, + } + }, logo = new Sprite { Anchor = Anchor.Centre, Origin = Anchor.Centre, + Scale = new Vector2(0.5f), }, }, }, @@ -85,6 +120,7 @@ namespace osu.Game.Screens.Menu Anchor = Anchor.Centre, Origin = Anchor.Centre, BlendingMode = BlendingMode.Additive, + Scale = new Vector2(0.5f), Alpha = 0.05f } } @@ -105,15 +141,15 @@ namespace osu.Game.Screens.Menu [BackgroundDependencyLoader] private void load(TextureStore textures) { - logo.Texture = textures.Get(@"Menu/logo"); - ripple.Texture = textures.Get(@"Menu/logo"); + logo.Texture = textures.Get(@"Menu/logo@2x"); + ripple.Texture = textures.Get(@"Menu/logo@2x"); } protected override void LoadComplete() { base.LoadComplete(); - ripple.ScaleTo(1.1f, 500); + ripple.ScaleTo(ripple.Scale * 1.1f, 500); ripple.FadeOut(500); ripple.Loop(300); } @@ -152,5 +188,44 @@ namespace osu.Game.Screens.Menu { logoBounceContainer.ScaleTo(1, 500, EasingTypes.OutElastic); } + + class OsuLogoTriangles : Triangles + { + public OsuLogoTriangles() + { + TriangleScale = 4; + Alpha = 1; + } + + public override float CornerRadius + { + get + { + return DrawSize.X / 2f; + } + + set + { + Debug.Assert(false, "Cannot manually set CornerRadius of CircularContainer."); + } + } + + protected override Sprite CreateTriangle() + { + var triangle = base.CreateTriangle(); + triangle.Alpha = 1; + triangle.Colour = getTriangleShade(); + return triangle; + } + + private Color4 getTriangleShade() + { + float val = RNG.NextSingle(); + return Interpolation.ValueAt(val, + new Color4(222, 91, 149, 255), + new Color4(255, 125, 183, 255), + 0, 1); + } + } } } \ No newline at end of file From 6909dbf60c7b203a5cb52908a2f79f3d86230830 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Dec 2016 20:44:17 +0900 Subject: [PATCH 123/133] Increase cursor trail density a bit. --- osu.Game/Graphics/Cursor/CursorTrail.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Cursor/CursorTrail.cs b/osu.Game/Graphics/Cursor/CursorTrail.cs index 2fcc11d5ae..b724f71c13 100644 --- a/osu.Game/Graphics/Cursor/CursorTrail.cs +++ b/osu.Game/Graphics/Cursor/CursorTrail.cs @@ -116,7 +116,7 @@ namespace osu.Game.Graphics.Cursor float distance = diff.Length; Vector2 direction = diff / distance; - float interval = size.X / 2; + float interval = (size.X / 2) * 0.9f; for (float d = interval; d < distance; d += interval) { From 4b74ea7586a488578e730e3565190f391cb3d56e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Dec 2016 20:52:26 +0900 Subject: [PATCH 124/133] Separate logo hover and bounce into separate containers to fix consecutive actions. --- osu.Game/Screens/Menu/OsuLogo.cs | 94 +++++++++++++++++--------------- 1 file changed, 51 insertions(+), 43 deletions(-) diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index 441050abef..d121847c59 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -26,13 +26,14 @@ namespace osu.Game.Screens.Menu private Sprite logo; private CircularContainer logoContainer; private Container logoBounceContainer; + private Container logoHoverContainer; private MenuVisualisation vis; private CircularContainer colourAndTriangles; public Action Action; - public float SizeForFlow => logo == null ? 0 : logo.DrawSize.X * logo.Scale.X * logoBounceContainer.Scale.X * 0.78f; + public float SizeForFlow => logo == null ? 0 : logo.DrawSize.X * logo.Scale.X * logoBounceContainer.Scale.X * logoHoverContainer.Scale.X * 0.78f; private Sprite ripple; @@ -76,62 +77,69 @@ namespace osu.Game.Screens.Menu AutoSizeAxes = Axes.Both, Children = new Drawable[] { - logoContainer = new CircularContainer + logoHoverContainer = new Container { AutoSizeAxes = Axes.Both, - Anchor = Anchor.Centre, Children = new Drawable[] { - colourAndTriangles = new CircularContainer + logoContainer = new CircularContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Children = new Drawable[] + { + colourAndTriangles = new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Scale = new Vector2(0.78f), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = new Color4(233, 103, 161, 255), + }, + new OsuLogoTriangles + { + RelativeSizeAxes = Axes.Both, + }, + } + }, + logo = new Sprite + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(0.5f), + }, + }, + }, + rippleContainer = new Container { - RelativeSizeAxes = Axes.Both, - Scale = new Vector2(0.78f), Anchor = Anchor.Centre, Origin = Anchor.Centre, Children = new Drawable[] { - new Box + ripple = new Sprite() { - RelativeSizeAxes = Axes.Both, - Colour = new Color4(233, 103, 161, 255), - }, - new OsuLogoTriangles - { - RelativeSizeAxes = Axes.Both, - }, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + BlendingMode = BlendingMode.Additive, + Scale = new Vector2(0.5f), + Alpha = 0.05f + } } }, - logo = new Sprite - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(0.5f), - }, - }, - }, - rippleContainer = new Container - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Children = new Drawable[] - { - ripple = new Sprite() + vis = new MenuVisualisation { Anchor = Anchor.Centre, Origin = Anchor.Centre, + Size = logo.Size, BlendingMode = BlendingMode.Additive, - Scale = new Vector2(0.5f), - Alpha = 0.05f + Alpha = 0.2f, } } - }, - vis = new MenuVisualisation - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = logo.Size, - BlendingMode = BlendingMode.Additive, - Alpha = 0.2f, } } } @@ -158,14 +166,14 @@ namespace osu.Game.Screens.Menu { if (!Interactive) return false; - logoBounceContainer.ScaleTo(1.1f, 1000, EasingTypes.Out); + logoBounceContainer.ScaleTo(0.9f, 1000, EasingTypes.Out); return true; } protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { - logoBounceContainer.ScaleTo(1.2f, 500, EasingTypes.OutElastic); + logoBounceContainer.ScaleTo(1f, 500, EasingTypes.OutElastic); return true; } @@ -180,13 +188,13 @@ namespace osu.Game.Screens.Menu protected override bool OnHover(InputState state) { if (!Interactive) return false; - logoBounceContainer.ScaleTo(1.2f, 500, EasingTypes.OutElastic); + logoHoverContainer.ScaleTo(1.2f, 500, EasingTypes.OutElastic); return true; } protected override void OnHoverLost(InputState state) { - logoBounceContainer.ScaleTo(1, 500, EasingTypes.OutElastic); + logoHoverContainer.ScaleTo(1, 500, EasingTypes.OutElastic); } class OsuLogoTriangles : Triangles From 511dab32efcde3fb0f4620d183051137d53a7bbd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Dec 2016 21:12:37 +0900 Subject: [PATCH 125/133] Remove masking from Triangles to simplify OsuLogo masking hierarchy. --- osu.Game/Graphics/Backgrounds/Triangles.cs | 1 - osu.Game/Overlays/Toolbar/ToolbarButton.cs | 1 + osu.Game/Screens/Menu/OsuLogo.cs | 34 +++++++--------------- 3 files changed, 12 insertions(+), 24 deletions(-) diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index 88f3a7d41a..514ffb9497 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -19,7 +19,6 @@ namespace osu.Game.Graphics.Backgrounds public Triangles() { - Masking = true; Alpha = 0.3f; } diff --git a/osu.Game/Overlays/Toolbar/ToolbarButton.cs b/osu.Game/Overlays/Toolbar/ToolbarButton.cs index b0d8135ef4..9949a81c89 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarButton.cs @@ -156,6 +156,7 @@ namespace osu.Game.Overlays.Toolbar public OpaqueBackground() { RelativeSizeAxes = Axes.Both; + Masking = true; Children = new Drawable[] { diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index d121847c59..50ef033942 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Menu private Container logoHoverContainer; private MenuVisualisation vis; - private CircularContainer colourAndTriangles; + private Container colourAndTriangles; public Action Action; @@ -84,14 +84,14 @@ namespace osu.Game.Screens.Menu { logoContainer = new CircularContainer { - AutoSizeAxes = Axes.Both, Anchor = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Scale = new Vector2(0.8f), Children = new Drawable[] { - colourAndTriangles = new CircularContainer + colourAndTriangles = new Container { RelativeSizeAxes = Axes.Both, - Scale = new Vector2(0.78f), Anchor = Anchor.Centre, Origin = Anchor.Centre, Children = new Drawable[] @@ -107,14 +107,15 @@ namespace osu.Game.Screens.Menu }, } }, - logo = new Sprite - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(0.5f), - }, + }, }, + logo = new Sprite + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(0.5f), + }, rippleContainer = new Container { Anchor = Anchor.Centre, @@ -205,19 +206,6 @@ namespace osu.Game.Screens.Menu Alpha = 1; } - public override float CornerRadius - { - get - { - return DrawSize.X / 2f; - } - - set - { - Debug.Assert(false, "Cannot manually set CornerRadius of CircularContainer."); - } - } - protected override Sprite CreateTriangle() { var triangle = base.CreateTriangle(); From 2342a17dbcdd3a6c4b681b5d17d1edcbbbd7e1be Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Dec 2016 21:29:14 +0900 Subject: [PATCH 126/133] Move BufferedContainer usage to allow ripple to blend correctly with the background layer. --- osu.Game/Screens/Menu/OsuLogo.cs | 55 ++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index 50ef033942..c0d3b94737 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -21,7 +21,7 @@ namespace osu.Game.Screens.Menu /// /// osu! logo and its attachments (pulsing, visualiser etc.) /// - public partial class OsuLogo : BufferedContainer + public partial class OsuLogo : Container { private Sprite logo; private CircularContainer logoContainer; @@ -82,39 +82,46 @@ namespace osu.Game.Screens.Menu AutoSizeAxes = Axes.Both, Children = new Drawable[] { - logoContainer = new CircularContainer + new BufferedContainer { - Anchor = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Scale = new Vector2(0.8f), + AutoSizeAxes = Axes.Both, Children = new Drawable[] { - colourAndTriangles = new Container + logoContainer = new CircularContainer { - RelativeSizeAxes = Axes.Both, Anchor = Anchor.Centre, - Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Scale = new Vector2(0.8f), Children = new Drawable[] { - new Box + colourAndTriangles = new Container { RelativeSizeAxes = Axes.Both, - Colour = new Color4(233, 103, 161, 255), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = new Color4(233, 103, 161, 255), + }, + new OsuLogoTriangles + { + RelativeSizeAxes = Axes.Both, + }, + } }, - new OsuLogoTriangles - { - RelativeSizeAxes = Axes.Both, - }, - } - }, - }, - }, - logo = new Sprite - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(0.5f), + }, + }, + logo = new Sprite + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(0.5f), + }, + } }, rippleContainer = new Container { @@ -128,7 +135,7 @@ namespace osu.Game.Screens.Menu Origin = Anchor.Centre, BlendingMode = BlendingMode.Additive, Scale = new Vector2(0.5f), - Alpha = 0.05f + Alpha = 0.15f } } }, From 413138abe55b42eef82c04260ad99187f8979a91 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Dec 2016 21:45:40 +0900 Subject: [PATCH 127/133] Delay movement of ParallaxContainers slightly. --- osu.Game/Graphics/Containers/ParallaxContainer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index cf61529cd2..f1d3067137 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -4,6 +4,7 @@ using osu.Framework.Input; using OpenTK; using osu.Framework; using osu.Framework.Allocation; +using osu.Framework.Graphics.Transformations; namespace osu.Game.Graphics.Containers { @@ -38,7 +39,7 @@ namespace osu.Game.Graphics.Containers protected override void Update() { base.Update(); - content.Position = (ToLocalSpace(input.CurrentState.Mouse.NativeState.Position) - DrawSize / 2) * ParallaxAmount; + content.MoveTo((ToLocalSpace(input.CurrentState.Mouse.NativeState.Position) - DrawSize / 2) * ParallaxAmount, 1000, EasingTypes.OutQuint); content.Scale = new Vector2(1 + ParallaxAmount); } } From 22905d2033edff2186dc3b2d74eec1e1c9ede614 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Dec 2016 21:59:32 +0900 Subject: [PATCH 128/133] Align logo correctly between intro and main menu. Kinda hacky but will do for now. --- .../Graphics/Containers/ParallaxContainer.cs | 7 +++++- osu.Game/Screens/Menu/Intro.cs | 22 +++++++++++++------ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index f1d3067137..5cc8a4097b 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -36,11 +36,16 @@ namespace osu.Game.Graphics.Containers this.input = input; } + bool firstUpdate = true; + protected override void Update() { base.Update(); - content.MoveTo((ToLocalSpace(input.CurrentState.Mouse.NativeState.Position) - DrawSize / 2) * ParallaxAmount, 1000, EasingTypes.OutQuint); + + content.MoveTo((ToLocalSpace(input.CurrentState.Mouse.NativeState.Position) - DrawSize / 2) * ParallaxAmount, firstUpdate ? 0 : 1000, EasingTypes.OutQuint); content.Scale = new Vector2(1 + ParallaxAmount); + + firstUpdate = false; } } } diff --git a/osu.Game/Screens/Menu/Intro.cs b/osu.Game/Screens/Menu/Intro.cs index 5fd02e817d..ed7c0fa7e9 100644 --- a/osu.Game/Screens/Menu/Intro.cs +++ b/osu.Game/Screens/Menu/Intro.cs @@ -8,6 +8,7 @@ using osu.Framework.Audio.Track; using osu.Framework.GameModes; using osu.Framework.Graphics; using osu.Framework.Graphics.Transformations; +using osu.Game.Graphics.Containers; using osu.Game.Screens.Backgrounds; using OpenTK.Graphics; @@ -34,14 +35,21 @@ namespace osu.Game.Screens.Menu { Children = new Drawable[] { - logo = new OsuLogo + new ParallaxContainer { - Alpha = 0, - Triangles = false, - BlendingMode = BlendingMode.Additive, - Interactive = false, - Colour = Color4.DarkGray, - Ripple = false + ParallaxAmount = 0.01f, + Children = new Drawable[] + { + logo = new OsuLogo + { + Alpha = 0, + Triangles = false, + BlendingMode = BlendingMode.Additive, + Interactive = false, + Colour = Color4.DarkGray, + Ripple = false + } + } } }; } From 1e8dc780ab844fb39684d5b7387271fa527d85c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Thu, 1 Dec 2016 19:12:35 +0100 Subject: [PATCH 129/133] Use new framework-level triangles. --- osu-framework | 2 +- .../Objects/Drawables/Pieces/Triangles.cs | 19 +++++++------------ osu.Game/Graphics/Backgrounds/Triangles.cs | 18 ++++++------------ osu.Game/Graphics/Cursor/CursorTrail.cs | 2 +- osu.Game/Screens/Menu/OsuLogo.cs | 2 +- 5 files changed, 16 insertions(+), 27 deletions(-) diff --git a/osu-framework b/osu-framework index 976d7833e8..c7e33572ce 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 976d7833e85ff880e9b00e8c121747f59becb2d8 +Subproject commit c7e33572ceb96df9f0345dc63f689f7d433bf7b0 diff --git a/osu.Game.Mode.Osu/Objects/Drawables/Pieces/Triangles.cs b/osu.Game.Mode.Osu/Objects/Drawables/Pieces/Triangles.cs index 94aa185772..3ef13792de 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/Pieces/Triangles.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/Pieces/Triangles.cs @@ -8,29 +8,24 @@ using OpenTK; namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces { - public class Triangles : Container + public class Triangles : Container { - private Texture triangle; - - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - triangle = textures.Get(@"Play/osu/triangle@2x"); - } - protected override void LoadComplete() { base.LoadComplete(); + + const float size = 100; for (int i = 0; i < 10; i++) { - Add(new Sprite + Add(new Triangle { - Texture = triangle, Origin = Anchor.Centre, RelativePositionAxes = Axes.Both, Position = new Vector2(RNG.NextSingle(), RNG.NextSingle()), Scale = new Vector2(RNG.NextSingle() * 0.4f + 0.2f), - Alpha = RNG.NextSingle() * 0.3f + // Scaling height by 0.866 results in equiangular triangles (== 60° and equal side length) + Size = new Vector2(size, 0.866f * size), + Alpha = RNG.NextSingle() * 0.3f, }); } } diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index 514ffb9497..34e65f0b2a 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -13,10 +13,8 @@ using OpenTK; namespace osu.Game.Graphics.Backgrounds { - public class Triangles : Container + public class Triangles : Container { - private Texture triangle; - public Triangles() { Alpha = 0.3f; @@ -35,12 +33,6 @@ namespace osu.Game.Graphics.Backgrounds } } - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - triangle = textures.Get(@"Play/osu/triangle@2x"); - } - private int aimTriangleCount => (int)((DrawWidth * DrawHeight) / 800 / triangleScale); protected override void Update() @@ -60,16 +52,18 @@ namespace osu.Game.Graphics.Backgrounds } - protected virtual Sprite CreateTriangle() + protected virtual Triangle CreateTriangle() { var scale = triangleScale * RNG.NextSingle() * 0.4f + 0.2f; + const float size = 100; - return new Sprite + return new Triangle { - Texture = triangle, Origin = Anchor.TopCentre, RelativePositionAxes = Axes.Both, Scale = new Vector2(scale), + // Scaling height by 0.866 results in equiangular triangles (== 60° and equal side length) + Size = new Vector2(size, 0.866f * size), Alpha = RNG.NextSingle(), Depth = scale, }; diff --git a/osu.Game/Graphics/Cursor/CursorTrail.cs b/osu.Game/Graphics/Cursor/CursorTrail.cs index b724f71c13..f2060bf8a3 100644 --- a/osu.Game/Graphics/Cursor/CursorTrail.cs +++ b/osu.Game/Graphics/Cursor/CursorTrail.cs @@ -195,7 +195,7 @@ namespace osu.Game.Graphics.Cursor colour.BottomLeft.Linear.A = Parts[i].Time + colour.BottomLeft.Linear.A; colour.BottomRight.Linear.A = Parts[i].Time + colour.BottomRight.Linear.A; - Texture.Draw( + Texture.DrawQuad( new Quad(pos.X - Size.X / 2, pos.Y - Size.Y / 2, Size.X, Size.Y), colour, null, diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index c0d3b94737..323b23b920 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -213,7 +213,7 @@ namespace osu.Game.Screens.Menu Alpha = 1; } - protected override Sprite CreateTriangle() + protected override Triangle CreateTriangle() { var triangle = base.CreateTriangle(); triangle.Alpha = 1; From d7d4480dde06f14980ded1bf72ef3cdb5b76a979 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Dec 2016 12:42:44 +0900 Subject: [PATCH 130/133] Update framework. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index c7e33572ce..b5efbe6d53 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit c7e33572ceb96df9f0345dc63f689f7d433bf7b0 +Subproject commit b5efbe6d53cb6895163731e2a934a1c6518d9d7d From 9bf36418a07324ee6d25cf88112f0a04433ce54e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Dec 2016 18:43:01 +0900 Subject: [PATCH 131/133] Make toolbar buttons more independent logic-wise. Also adds visual toggle state for toggleable buttons. --- osu.Game/OsuGame.cs | 18 ++--- osu.Game/Overlays/Toolbar/Toolbar.cs | 22 +----- osu.Game/Overlays/Toolbar/ToolbarButton.cs | 2 +- .../Overlays/Toolbar/ToolbarHomeButton.cs | 19 +++++ .../Overlays/Toolbar/ToolbarMusicButton.cs | 23 ++++++ .../Overlays/Toolbar/ToolbarSettingsButton.cs | 25 +++++++ .../Overlays/Toolbar/ToolbarToggleButton.cs | 71 +++++++++++++++++++ osu.Game/osu.Game.csproj | 4 ++ 8 files changed, 156 insertions(+), 28 deletions(-) create mode 100644 osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs create mode 100644 osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs create mode 100644 osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs create mode 100644 osu.Game/Overlays/Toolbar/ToolbarToggleButton.cs diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index d481a446b8..c6e07c3a79 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -47,7 +47,7 @@ namespace osu.Game string[] args; - public OptionsOverlay Options; + private OptionsOverlay options; public OsuGame(string[] args = null) { @@ -61,7 +61,7 @@ namespace osu.Game host.Size = new Vector2(Config.Get(OsuConfig.Width), Config.Get(OsuConfig.Height)); } - public void ToggleOptions() => Options.ToggleVisibility(); + public void ToggleOptions() => options.ToggleVisibility(); [BackgroundDependencyLoader] private void load() @@ -118,15 +118,17 @@ namespace osu.Game //overlay elements (chat = new ChatOverlay { Depth = 0 }).Preload(this, overlayContent.Add); - (Options = new OptionsOverlay { Depth = -1 }).Preload(this, overlayContent.Add); + (options = new OptionsOverlay { Depth = -1 }).Preload(this, overlayContent.Add); (musicController = new MusicController() { Depth = -3 }).Preload(this, overlayContent.Add); + + Dependencies.Cache(options); + Dependencies.Cache(musicController); + (Toolbar = new Toolbar { Depth = -2, OnHome = delegate { mainMenu?.MakeCurrent(); }, - OnSettings = Options.ToggleVisibility, OnPlayModeChange = delegate (PlayMode m) { PlayMode.Value = m; }, - OnMusicController = musicController.ToggleVisibility }).Preload(this, t => { PlayMode.ValueChanged += delegate { Toolbar.SetGameMode(PlayMode.Value); }; @@ -134,9 +136,9 @@ namespace osu.Game overlayContent.Add(Toolbar); }); - Options.StateChanged += delegate + options.StateChanged += delegate { - switch (Options.State) + switch (options.State) { case Visibility.Hidden: intro.MoveToX(0, OptionsOverlay.TRANSITION_LENGTH, EasingTypes.OutQuint); @@ -164,7 +166,7 @@ namespace osu.Game switch (args.Key) { case Key.O: - Options.ToggleVisibility(); + options.ToggleVisibility(); return true; } } diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index a1af1d3293..df6168b6c5 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -2,7 +2,6 @@ //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; @@ -22,10 +21,8 @@ namespace osu.Game.Overlays.Toolbar { private const float height = 50; - public Action OnSettings; public Action OnHome; public Action OnPlayModeChange; - public Action OnMusicController; private ToolbarModeSelector modeSelector; private Box solidBackground; @@ -87,18 +84,9 @@ namespace osu.Game.Overlays.Toolbar AutoSizeAxes = Axes.X, Children = new Drawable[] { - new ToolbarButton + new ToolbarSettingsButton(), + new ToolbarHomeButton() { - Icon = FontAwesome.fa_gear, - TooltipMain = "Settings", - TooltipSub = "Change your settings", - Action = () => OnSettings?.Invoke() - }, - new ToolbarButton - { - Icon = FontAwesome.fa_home, - TooltipMain = "Home", - TooltipSub = "Return to the main menu", Action = () => OnHome?.Invoke() }, modeSelector = new ToolbarModeSelector @@ -116,11 +104,7 @@ namespace osu.Game.Overlays.Toolbar AutoSizeAxes = Axes.X, Children = new [] { - new ToolbarButton - { - Icon = FontAwesome.fa_music, - Action = () => OnMusicController?.Invoke() - }, + new ToolbarMusicButton(), new ToolbarButton { Icon = FontAwesome.fa_search diff --git a/osu.Game/Overlays/Toolbar/ToolbarButton.cs b/osu.Game/Overlays/Toolbar/ToolbarButton.cs index 9949a81c89..70462fa5fe 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarButton.cs @@ -133,7 +133,7 @@ namespace osu.Game.Overlays.Toolbar protected override bool OnClick(InputState state) { Action?.Invoke(); - HoverBackground.FlashColour(new Color4(255, 255, 255, 180), 800, EasingTypes.OutQuint); + HoverBackground.FlashColour(new Color4(255, 255, 255, 100), 500, EasingTypes.OutQuint); return true; } diff --git a/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs b/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs new file mode 100644 index 0000000000..259abc0739 --- /dev/null +++ b/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs @@ -0,0 +1,19 @@ +//Copyright (c) 2007-2016 ppy Pty Ltd . +//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Game.Graphics; +using osu.Game.Screens.Menu; + +namespace osu.Game.Overlays.Toolbar +{ + class ToolbarHomeButton : ToolbarButton + { + public ToolbarHomeButton() + { + Icon = FontAwesome.fa_home; + TooltipMain = "Home"; + TooltipSub = "Return to the main menu"; + } + } +} \ No newline at end of file diff --git a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs new file mode 100644 index 0000000000..9409532df8 --- /dev/null +++ b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs @@ -0,0 +1,23 @@ +//Copyright (c) 2007-2016 ppy Pty Ltd . +//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Game.Graphics; + +namespace osu.Game.Overlays.Toolbar +{ + class ToolbarMusicButton : ToolbarToggleButton + { + public ToolbarMusicButton() + { + Icon = FontAwesome.fa_music; + } + + [BackgroundDependencyLoader] + private void load(MusicController music) + { + StateContainer = music; + Action = music.ToggleVisibility; + } + } +} \ No newline at end of file diff --git a/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs new file mode 100644 index 0000000000..67fb4feb6f --- /dev/null +++ b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs @@ -0,0 +1,25 @@ +//Copyright (c) 2007-2016 ppy Pty Ltd . +//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Game.Graphics; + +namespace osu.Game.Overlays.Toolbar +{ + class ToolbarSettingsButton : ToolbarToggleButton + { + public ToolbarSettingsButton() + { + Icon = FontAwesome.fa_gear; + TooltipMain = "Settings"; + TooltipSub = "Change your settings"; + } + + [BackgroundDependencyLoader] + private void load(OptionsOverlay options) + { + StateContainer = options; + Action = options.ToggleVisibility; + } + } +} \ No newline at end of file diff --git a/osu.Game/Overlays/Toolbar/ToolbarToggleButton.cs b/osu.Game/Overlays/Toolbar/ToolbarToggleButton.cs new file mode 100644 index 0000000000..72fc87b310 --- /dev/null +++ b/osu.Game/Overlays/Toolbar/ToolbarToggleButton.cs @@ -0,0 +1,71 @@ +//Copyright (c) 2007-2016 ppy Pty Ltd . +//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using osu.Framework; +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.Configuration; +using osu.Game.Online.API; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Overlays.Toolbar +{ + class ToolbarToggleButton : ToolbarButton + { + private Box StateBackground; + + private OverlayContainer stateContainer; + + public OverlayContainer StateContainer + { + get { return stateContainer; } + set + { + stateContainer = value; + stateContainer.StateChanged += stateChanged; + } + } + + public ToolbarToggleButton() + { + Add(StateBackground = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = new Color4(150, 150, 150, 180), + BlendingMode = BlendingMode.Additive, + Depth = 2, + Alpha = 0, + }); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + if (stateContainer != null) + stateContainer.StateChanged -= stateChanged; + } + + private void stateChanged(OverlayContainer c, Visibility state) + { + switch (state) + { + case Visibility.Hidden: + StateBackground.FadeOut(200); + break; + case Visibility.Visible: + StateBackground.FadeIn(200); + break; + } + } + } +} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 6f56037026..4478590e42 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -92,6 +92,10 @@ + + + + From ebde5fa97feb10d01e4f044dcde4f2c1342a6f85 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Dec 2016 20:56:05 +0900 Subject: [PATCH 132/133] Update framework. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index b5efbe6d53..e611e186e3 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit b5efbe6d53cb6895163731e2a934a1c6518d9d7d +Subproject commit e611e186e3c8951d7e58a6c92c75e1b587e825a2 From a80c28ca37a007bca6746cc981b14ab43a0fad24 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Dec 2016 21:28:23 +0900 Subject: [PATCH 133/133] ToolbarOverlayToggleButton --- osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs | 2 +- .../{ToolbarToggleButton.cs => ToolbarOverlayToggleButton.cs} | 4 ++-- osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs | 2 +- osu.Game/osu.Game.csproj | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename osu.Game/Overlays/Toolbar/{ToolbarToggleButton.cs => ToolbarOverlayToggleButton.cs} (91%) diff --git a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs index 9409532df8..67ec2aed26 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs @@ -6,7 +6,7 @@ using osu.Game.Graphics; namespace osu.Game.Overlays.Toolbar { - class ToolbarMusicButton : ToolbarToggleButton + class ToolbarMusicButton : ToolbarOverlayToggleButton { public ToolbarMusicButton() { diff --git a/osu.Game/Overlays/Toolbar/ToolbarToggleButton.cs b/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs similarity index 91% rename from osu.Game/Overlays/Toolbar/ToolbarToggleButton.cs rename to osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs index 72fc87b310..b72a358456 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarToggleButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs @@ -20,7 +20,7 @@ using OpenTK.Graphics; namespace osu.Game.Overlays.Toolbar { - class ToolbarToggleButton : ToolbarButton + class ToolbarOverlayToggleButton : ToolbarButton { private Box StateBackground; @@ -36,7 +36,7 @@ namespace osu.Game.Overlays.Toolbar } } - public ToolbarToggleButton() + public ToolbarOverlayToggleButton() { Add(StateBackground = new Box { diff --git a/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs index 67fb4feb6f..4bc3964716 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs @@ -6,7 +6,7 @@ using osu.Game.Graphics; namespace osu.Game.Overlays.Toolbar { - class ToolbarSettingsButton : ToolbarToggleButton + class ToolbarSettingsButton : ToolbarOverlayToggleButton { public ToolbarSettingsButton() { diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 4478590e42..c4915b7567 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -95,7 +95,7 @@ - +