From 545c375199703de17ccdecbd38b87427fb85bc71 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 27 Sep 2017 21:53:33 +0900 Subject: [PATCH 01/16] Update design of EditorMenuBar to match flyte's design more closely --- osu-framework | 2 +- osu.Game/Screens/Edit/Editor.cs | 7 +- osu.Game/Screens/Edit/Menus/EditorMenuBar.cs | 55 +++++++- .../Tests/Visual/TestCaseEditorMenuBar.cs | 125 ++++++++++-------- 4 files changed, 124 insertions(+), 65 deletions(-) diff --git a/osu-framework b/osu-framework index cdb031c3a8..a24fd77ad5 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit cdb031c3a8ef693cd71458c5e19c68127ab72938 +Subproject commit a24fd77ad5f69e133a84175ef79c4ab7f600316b diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 3ffd7754c1..d85026bb27 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -32,16 +32,11 @@ namespace osu.Game.Screens.Edit Height = 40, Children = new Drawable[] { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex("111") - }, new EditorMenuBar { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - X = 100, + RelativeSizeAxes = Axes.Both, Items = new[] { new EditorMenuBarItem("File") diff --git a/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs b/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs index bb349b1531..818eb37bfb 100644 --- a/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs +++ b/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs @@ -19,8 +19,20 @@ namespace osu.Game.Screens.Edit.Menus public EditorMenuBar() : base(Direction.Horizontal, true) { - ItemsContainer.Padding = new MarginPadding(0); + RelativeSizeAxes = Axes.X; + + ItemsContainer.Padding = new MarginPadding { Left = 100 }; BackgroundColour = Color4.Transparent; + + AddRangeInternal(new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex("111"), + Depth = float.MaxValue + }, + }); } protected override Framework.Graphics.UserInterface.Menu CreateSubMenu() => new SubMenu(); @@ -32,9 +44,32 @@ namespace osu.Game.Screens.Edit.Menus private Color4 openedForegroundColour; private Color4 openedBackgroundColour; + public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => parentSizedBox.ReceiveMouseInputAt(screenSpacePos); + + /// + /// A box with width equal to this 's width, and height equal to the parent height. + /// + private readonly Box parentSizedBox; + public DrawableEditorBarMenuItem(MenuItem item) : base(item) { + Anchor = Anchor.CentreLeft; + Origin = Anchor.CentreLeft; + + AddInternal(parentSizedBox = new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + BypassAutoSizeAxes = Axes.Both, + Alpha = 0, + }); + } + + public override void SetFlowDirection(Direction direction) + { + AutoSizeAxes = Axes.Both; } [BackgroundDependencyLoader] @@ -62,6 +97,13 @@ namespace osu.Game.Screens.Edit.Menus base.UpdateForegroundColour(); } + protected override void Update() + { + base.Update(); + + parentSizedBox.Height = Parent.DrawHeight; + } + protected override Drawable CreateBackground() => new Container { RelativeSizeAxes = Axes.Both, @@ -75,6 +117,17 @@ namespace osu.Game.Screens.Edit.Menus Child = new Box { RelativeSizeAxes = Axes.Both } } }; + + protected override DrawableOsuMenuItem.TextContainer CreateTextContainer() => new TextContainer(); + + private new class TextContainer : DrawableOsuMenuItem.TextContainer + { + public TextContainer() + { + NormalText.TextSize = BoldText.TextSize = 14; + NormalText.Margin = BoldText.Margin = new MarginPadding { Horizontal = 10, Vertical = MARGIN_VERTICAL }; + } + } } private class SubMenu : OsuMenu diff --git a/osu.Game/Tests/Visual/TestCaseEditorMenuBar.cs b/osu.Game/Tests/Visual/TestCaseEditorMenuBar.cs index 8b5132fe08..b0c21b6b8c 100644 --- a/osu.Game/Tests/Visual/TestCaseEditorMenuBar.cs +++ b/osu.Game/Tests/Visual/TestCaseEditorMenuBar.cs @@ -1,7 +1,10 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.Collections.Generic; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Edit.Menus; @@ -9,74 +12,82 @@ namespace osu.Game.Tests.Visual { public class TestCaseEditorMenuBar : OsuTestCase { + public override IReadOnlyList RequiredTypes => new[] { typeof(EditorMenuBar), typeof(ScreenSelectionTabControl) }; + public TestCaseEditorMenuBar() { - Add(new EditorMenuBar + Add(new Container { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + Height = 50, Y = 50, - Items = new[] + Child = new EditorMenuBar { - new EditorMenuBarItem("File") + RelativeSizeAxes = Axes.Both, + Items = new[] { - Items = new[] + new EditorMenuBarItem("File") { - new EditorMenuItem("Clear All Notes"), - new EditorMenuItem("Open Difficulty..."), - new EditorMenuItem("Save"), - new EditorMenuItem("Create a new Difficulty..."), - new EditorMenuItemSpacer(), - new EditorMenuItem("Revert to Saved"), - new EditorMenuItem("Revert to Saved (Full)"), - new EditorMenuItemSpacer(), - new EditorMenuItem("Test Beatmap"), - new EditorMenuItem("Open AiMod"), - new EditorMenuItemSpacer(), - new EditorMenuItem("Upload Beatmap..."), - new EditorMenuItem("Export Package"), - new EditorMenuItem("Export Map Package"), - new EditorMenuItem("Import from..."), - new EditorMenuItemSpacer(), - new EditorMenuItem("Open Song Folder"), - new EditorMenuItem("Open .osu in Notepad"), - new EditorMenuItem("Open .osb in Notepad"), - new EditorMenuItemSpacer(), - new EditorMenuItem("Exit"), - } - }, - new EditorMenuBarItem("Timing") - { - Items = new[] + Items = new[] + { + new EditorMenuItem("Clear All Notes"), + new EditorMenuItem("Open Difficulty..."), + new EditorMenuItem("Save"), + new EditorMenuItem("Create a new Difficulty..."), + new EditorMenuItemSpacer(), + new EditorMenuItem("Revert to Saved"), + new EditorMenuItem("Revert to Saved (Full)"), + new EditorMenuItemSpacer(), + new EditorMenuItem("Test Beatmap"), + new EditorMenuItem("Open AiMod"), + new EditorMenuItemSpacer(), + new EditorMenuItem("Upload Beatmap..."), + new EditorMenuItem("Export Package"), + new EditorMenuItem("Export Map Package"), + new EditorMenuItem("Import from..."), + new EditorMenuItemSpacer(), + new EditorMenuItem("Open Song Folder"), + new EditorMenuItem("Open .osu in Notepad"), + new EditorMenuItem("Open .osb in Notepad"), + new EditorMenuItemSpacer(), + new EditorMenuItem("Exit"), + } + }, + new EditorMenuBarItem("Timing") { - new EditorMenuItem("Time Signature"), - new EditorMenuItem("Metronome Clicks"), - new EditorMenuItemSpacer(), - new EditorMenuItem("Add Timing Section"), - new EditorMenuItem("Add Inheriting Section"), - new EditorMenuItem("Reset Current Section"), - new EditorMenuItem("Delete Timing Section"), - new EditorMenuItem("Resnap Current Section"), - new EditorMenuItemSpacer(), - new EditorMenuItem("Timing Setup"), - new EditorMenuItemSpacer(), - new EditorMenuItem("Resnap All Notes", MenuItemType.Destructive), - new EditorMenuItem("Move all notes in time...", MenuItemType.Destructive), - new EditorMenuItem("Recalculate Slider Lengths", MenuItemType.Destructive), - new EditorMenuItem("Delete All Timing Sections", MenuItemType.Destructive), - new EditorMenuItemSpacer(), - new EditorMenuItem("Set Current Position as Preview Point"), - } - }, - new EditorMenuBarItem("Testing") - { - Items = new[] + Items = new[] + { + new EditorMenuItem("Time Signature"), + new EditorMenuItem("Metronome Clicks"), + new EditorMenuItemSpacer(), + new EditorMenuItem("Add Timing Section"), + new EditorMenuItem("Add Inheriting Section"), + new EditorMenuItem("Reset Current Section"), + new EditorMenuItem("Delete Timing Section"), + new EditorMenuItem("Resnap Current Section"), + new EditorMenuItemSpacer(), + new EditorMenuItem("Timing Setup"), + new EditorMenuItemSpacer(), + new EditorMenuItem("Resnap All Notes", MenuItemType.Destructive), + new EditorMenuItem("Move all notes in time...", MenuItemType.Destructive), + new EditorMenuItem("Recalculate Slider Lengths", MenuItemType.Destructive), + new EditorMenuItem("Delete All Timing Sections", MenuItemType.Destructive), + new EditorMenuItemSpacer(), + new EditorMenuItem("Set Current Position as Preview Point"), + } + }, + new EditorMenuBarItem("Testing") { - new EditorMenuItem("Item 1"), - new EditorMenuItem("Item 2"), - new EditorMenuItem("Item 3"), - } - }, + Items = new[] + { + new EditorMenuItem("Item 1"), + new EditorMenuItem("Item 2"), + new EditorMenuItem("Item 3"), + } + }, + } } }); } From ba8bf6cbd51bb6a7a6c48a4aa1d03fb459372742 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 27 Sep 2017 22:01:53 +0900 Subject: [PATCH 02/16] Add ScreenSelectionTabControl to EditorMenuBar --- .../Graphics/UserInterface/OsuTabControl.cs | 8 +- osu.Game/Screens/Edit/Menus/EditorMenuBar.cs | 6 ++ .../Edit/Menus/ScreenSelectionTabControl.cs | 84 +++++++++++++++++++ osu.Game/osu.Game.csproj | 1 + 4 files changed, 95 insertions(+), 4 deletions(-) create mode 100644 osu.Game/Screens/Edit/Menus/ScreenSelectionTabControl.cs diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index 89b1f4124b..b053195030 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -59,7 +59,7 @@ namespace osu.Game.Graphics.UserInterface public class OsuTabItem : TabItem, IHasAccentColour { protected readonly SpriteText Text; - private readonly Box box; + protected readonly Box Bar; private Color4 accentColour; public Color4 AccentColour @@ -77,13 +77,13 @@ namespace osu.Game.Graphics.UserInterface private void fadeActive() { - box.FadeIn(transition_length, Easing.OutQuint); + Bar.FadeIn(transition_length, Easing.OutQuint); Text.FadeColour(Color4.White, transition_length, Easing.OutQuint); } private void fadeInactive() { - box.FadeOut(transition_length, Easing.OutQuint); + Bar.FadeOut(transition_length, Easing.OutQuint); Text.FadeColour(AccentColour, transition_length, Easing.OutQuint); } @@ -123,7 +123,7 @@ namespace osu.Game.Graphics.UserInterface TextSize = 14, Font = @"Exo2.0-Bold", // Font should only turn bold when active? }, - box = new Box + Bar = new Box { RelativeSizeAxes = Axes.X, Height = 1, diff --git a/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs b/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs index 818eb37bfb..a3b48d8c70 100644 --- a/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs +++ b/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs @@ -32,6 +32,12 @@ namespace osu.Game.Screens.Edit.Menus Colour = OsuColour.FromHex("111"), Depth = float.MaxValue }, + new ScreenSelectionTabControl + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + X = -15 + } }); } diff --git a/osu.Game/Screens/Edit/Menus/ScreenSelectionTabControl.cs b/osu.Game/Screens/Edit/Menus/ScreenSelectionTabControl.cs new file mode 100644 index 0000000000..a455fa8d71 --- /dev/null +++ b/osu.Game/Screens/Edit/Menus/ScreenSelectionTabControl.cs @@ -0,0 +1,84 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; +using OpenTK; + +namespace osu.Game.Screens.Edit.Menus +{ + public class ScreenSelectionTabControl : OsuTabControl + { + public ScreenSelectionTabControl() + { + AutoSizeAxes = Axes.X; + RelativeSizeAxes = Axes.Y; + + TabContainer.RelativeSizeAxes &= ~Axes.X; + TabContainer.AutoSizeAxes = Axes.X; + TabContainer.Padding = new MarginPadding(); + + Add(new Box + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Height = 1, + Colour = Color4.White.Opacity(0.2f), + }); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AccentColour = colours.Yellow; + } + + protected override Dropdown CreateDropdown() => null; + + protected override TabItem CreateTabItem(EditorScreenMode value) => new TabItem(value); + + private new class TabItem : OsuTabItem + { + private const float transition_length = 250; + + public TabItem(EditorScreenMode value) + : base(value) + { + Text.Margin = new MarginPadding(); + Text.Anchor = Anchor.CentreLeft; + Text.Origin = Anchor.CentreLeft; + } + + protected override void OnActivated() + { + base.OnActivated(); + Bar.ScaleTo(new Vector2(1, 5), transition_length, Easing.OutQuint); + } + + protected override void OnDeactivated() + { + base.OnDeactivated(); + Bar.ScaleTo(Vector2.One, transition_length, Easing.OutQuint); + } + } + } + + public enum EditorScreenMode + { + [System.ComponentModel.Description("compose")] + Compose, + [System.ComponentModel.Description("design")] + Design, + [System.ComponentModel.Description("timing")] + Timing, + [System.ComponentModel.Description("song")] + SongSetup + } +} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index a6860e4e8c..0afb0247df 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -618,6 +618,7 @@ + From 95364d0173cdc6db99b3ada2f20cdab6f4e8221c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 27 Sep 2017 22:15:11 +0900 Subject: [PATCH 03/16] No more box background --- osu.Game/Screens/Edit/Menus/EditorMenuBar.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs b/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs index a3b48d8c70..3142e3d6bc 100644 --- a/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs +++ b/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs @@ -22,16 +22,10 @@ namespace osu.Game.Screens.Edit.Menus RelativeSizeAxes = Axes.X; ItemsContainer.Padding = new MarginPadding { Left = 100 }; - BackgroundColour = Color4.Transparent; + BackgroundColour = OsuColour.FromHex("111"); AddRangeInternal(new Drawable[] { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex("111"), - Depth = float.MaxValue - }, new ScreenSelectionTabControl { Anchor = Anchor.BottomRight, From 8688d63a9e23117dec10cf3bc19c06e51b56b42f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 28 Sep 2017 00:48:21 +0900 Subject: [PATCH 04/16] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index a24fd77ad5..9d142a8e00 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit a24fd77ad5f69e133a84175ef79c4ab7f600316b +Subproject commit 9d142a8e009794dfee828392e36025d08577131d From 6bb5210c7cf6c97ec96f2094e62af0f41aa74efd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 29 Sep 2017 15:09:28 +0900 Subject: [PATCH 05/16] Remove the parentSizedBox --- osu.Game/Screens/Edit/Menus/EditorMenuBar.cs | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs b/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs index 3142e3d6bc..329471fd0a 100644 --- a/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs +++ b/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs @@ -44,27 +44,12 @@ namespace osu.Game.Screens.Edit.Menus private Color4 openedForegroundColour; private Color4 openedBackgroundColour; - public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => parentSizedBox.ReceiveMouseInputAt(screenSpacePos); - - /// - /// A box with width equal to this 's width, and height equal to the parent height. - /// - private readonly Box parentSizedBox; public DrawableEditorBarMenuItem(MenuItem item) : base(item) { Anchor = Anchor.CentreLeft; Origin = Anchor.CentreLeft; - - AddInternal(parentSizedBox = new Box - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.X, - BypassAutoSizeAxes = Axes.Both, - Alpha = 0, - }); } public override void SetFlowDirection(Direction direction) @@ -100,8 +85,6 @@ namespace osu.Game.Screens.Edit.Menus protected override void Update() { base.Update(); - - parentSizedBox.Height = Parent.DrawHeight; } protected override Drawable CreateBackground() => new Container From b2eab1f4351ad2b84a19706c35835ae9f98aad71 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 29 Sep 2017 15:09:56 +0900 Subject: [PATCH 06/16] Set the hover background colour as dictated by flyte --- osu.Game/Screens/Edit/Menus/EditorMenuBar.cs | 25 +++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs b/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs index 329471fd0a..488ba220a2 100644 --- a/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs +++ b/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs @@ -41,9 +41,6 @@ namespace osu.Game.Screens.Edit.Menus private class DrawableEditorBarMenuItem : DrawableOsuMenuItem { - private Color4 openedForegroundColour; - private Color4 openedBackgroundColour; - public DrawableEditorBarMenuItem(MenuItem item) : base(item) @@ -52,24 +49,24 @@ namespace osu.Game.Screens.Edit.Menus Origin = Anchor.CentreLeft; } + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + ForegroundColour = colours.BlueLight; + BackgroundColour = Color4.Transparent; + ForegroundColourHover = Color4.White; + BackgroundColourHover = colours.Gray3; + } + public override void SetFlowDirection(Direction direction) { AutoSizeAxes = Axes.Both; } - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - ForegroundColour = ForegroundColourHover = colours.BlueLight; - BackgroundColour = BackgroundColourHover = Color4.Transparent; - openedForegroundColour = Color4.White; - openedBackgroundColour = colours.Gray3; - } - protected override void UpdateBackgroundColour() { if (State == MenuItemState.Selected) - Background.FadeColour(openedBackgroundColour); + Background.FadeColour(BackgroundColourHover); else base.UpdateBackgroundColour(); } @@ -77,7 +74,7 @@ namespace osu.Game.Screens.Edit.Menus protected override void UpdateForegroundColour() { if (State == MenuItemState.Selected) - Foreground.FadeColour(openedForegroundColour); + Foreground.FadeColour(ForegroundColourHover); else base.UpdateForegroundColour(); } From 775e8bada5e742a0ac62423fa1d61b6f3aa44047 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 29 Sep 2017 15:10:24 +0900 Subject: [PATCH 07/16] Make the background bottom corners look nice with the new hover functionality --- osu.Game/Screens/Edit/Menus/EditorMenuBar.cs | 53 ++++++++++++++------ 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs b/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs index 488ba220a2..616cabbab2 100644 --- a/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs +++ b/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs @@ -41,12 +41,15 @@ namespace osu.Game.Screens.Edit.Menus private class DrawableEditorBarMenuItem : DrawableOsuMenuItem { + private BackgroundBox background; public DrawableEditorBarMenuItem(MenuItem item) : base(item) { Anchor = Anchor.CentreLeft; Origin = Anchor.CentreLeft; + + StateChanged += stateChanged; } [BackgroundDependencyLoader] @@ -79,25 +82,15 @@ namespace osu.Game.Screens.Edit.Menus base.UpdateForegroundColour(); } - protected override void Update() + private void stateChanged(MenuItemState newState) { - base.Update(); + if (newState == MenuItemState.Selected) + background.Expand(); + else + background.Contract(); } - protected override Drawable CreateBackground() => new Container - { - RelativeSizeAxes = Axes.Both, - Masking = true, - Child = new Container - { - RelativeSizeAxes = Axes.Both, - Height = 2, - Masking = true, - CornerRadius = 4, - Child = new Box { RelativeSizeAxes = Axes.Both } - } - }; - + protected override Drawable CreateBackground() => background = new BackgroundBox(); protected override DrawableOsuMenuItem.TextContainer CreateTextContainer() => new TextContainer(); private new class TextContainer : DrawableOsuMenuItem.TextContainer @@ -108,6 +101,34 @@ namespace osu.Game.Screens.Edit.Menus NormalText.Margin = BoldText.Margin = new MarginPadding { Horizontal = 10, Vertical = MARGIN_VERTICAL }; } } + + private class BackgroundBox : CompositeDrawable + { + private readonly Container innerBackground; + + public BackgroundBox() + { + RelativeSizeAxes = Axes.Both; + Masking = true; + InternalChild = innerBackground = new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + CornerRadius = 4, + Child = new Box { RelativeSizeAxes = Axes.Both } + }; + } + + /// + /// Expands the background such that it doesn't show the bottom corners. + /// + public void Expand() => innerBackground.Height = 2; + + /// + /// Contracts the background such that it shows the bottom corners. + /// + public void Contract() => innerBackground.Height = 1; + } } private class SubMenu : OsuMenu From 7b4348254c47d60aeb76a7ff7b8c695f36da4564 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 29 Sep 2017 20:02:55 +0900 Subject: [PATCH 08/16] Don't use new --- osu.Game/Screens/Edit/Menus/ScreenSelectionTabControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Menus/ScreenSelectionTabControl.cs b/osu.Game/Screens/Edit/Menus/ScreenSelectionTabControl.cs index a455fa8d71..516b954e44 100644 --- a/osu.Game/Screens/Edit/Menus/ScreenSelectionTabControl.cs +++ b/osu.Game/Screens/Edit/Menus/ScreenSelectionTabControl.cs @@ -44,7 +44,7 @@ namespace osu.Game.Screens.Edit.Menus protected override TabItem CreateTabItem(EditorScreenMode value) => new TabItem(value); - private new class TabItem : OsuTabItem + private class TabItem : OsuTabItem { private const float transition_length = 250; From 21c6a63fa1bc50e4ec5caf11618fd892cefda8ea Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 29 Sep 2017 20:03:09 +0900 Subject: [PATCH 09/16] Use using for Description --- osu.Game/Screens/Edit/Menus/ScreenSelectionTabControl.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/Menus/ScreenSelectionTabControl.cs b/osu.Game/Screens/Edit/Menus/ScreenSelectionTabControl.cs index 516b954e44..652ef1d61f 100644 --- a/osu.Game/Screens/Edit/Menus/ScreenSelectionTabControl.cs +++ b/osu.Game/Screens/Edit/Menus/ScreenSelectionTabControl.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using OpenTK; +using System.ComponentModel; namespace osu.Game.Screens.Edit.Menus { @@ -72,13 +73,13 @@ namespace osu.Game.Screens.Edit.Menus public enum EditorScreenMode { - [System.ComponentModel.Description("compose")] + [Description("compose")] Compose, - [System.ComponentModel.Description("design")] + [Description("design")] Design, - [System.ComponentModel.Description("timing")] + [Description("timing")] Timing, - [System.ComponentModel.Description("song")] + [Description("song")] SongSetup } } From 92c3d722b4140020088fa8a471b6e24a2b8ad0b0 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Sat, 30 Sep 2017 05:41:32 +0300 Subject: [PATCH 10/16] Show mapper's profile when clicking on avatar in BeatmapSetOverlay --- osu.Game/OsuGame.cs | 6 ++--- osu.Game/Overlays/BeatmapSet/AuthorInfo.cs | 28 ++++++++++++++++++++-- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index c137b8f6f5..75a1d61371 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -188,11 +188,11 @@ namespace osu.Game GetToolbarHeight = () => ToolbarOffset, Depth = -1 }, overlayContent.Add); - LoadComponentAsync(userProfile = new UserProfileOverlay { Depth = -2 }, mainContent.Add); LoadComponentAsync(beatmapSetOverlay = new BeatmapSetOverlay { Depth = -2 }, mainContent.Add); + LoadComponentAsync(userProfile = new UserProfileOverlay { Depth = -3 }, mainContent.Add); LoadComponentAsync(musicController = new MusicController { - Depth = -3, + Depth = -4, Position = new Vector2(0, Toolbar.HEIGHT), Anchor = Anchor.TopRight, Origin = Anchor.TopRight, @@ -200,7 +200,7 @@ namespace osu.Game LoadComponentAsync(notificationOverlay = new NotificationOverlay { - Depth = -3, + Depth = -4, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, }, overlayContent.Add); diff --git a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs index b0e4e49e31..fc9fd1e614 100644 --- a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs +++ b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs @@ -9,6 +9,9 @@ using osu.Game.Graphics.Sprites; using osu.Game.Users; using OpenTK; using OpenTK.Graphics; +using osu.Framework.Allocation; +using osu.Game.Graphics.Containers; +using osu.Framework.Graphics.Cursor; namespace osu.Game.Overlays.BeatmapSet { @@ -17,8 +20,11 @@ namespace osu.Game.Overlays.BeatmapSet private const float height = 50; private readonly UpdateableAvatar avatar; + private readonly ClickableArea clickableArea; private readonly FillFlowContainer fields; + private UserProfileOverlay profile; + private BeatmapSetInfo beatmapSet; public BeatmapSetInfo BeatmapSet { @@ -31,6 +37,8 @@ namespace osu.Game.Overlays.BeatmapSet var i = BeatmapSet.OnlineInfo; avatar.User = i.Author; + clickableArea.Action = () => profile?.ShowUser(avatar.User); + fields.Children = new Drawable[] { new Field("made by", i.Author.Username, @"Exo2.0-RegularItalic"), @@ -58,11 +66,15 @@ namespace osu.Game.Overlays.BeatmapSet Children = new Drawable[] { - avatar = new UpdateableAvatar + clickableArea = new ClickableArea { - Size = new Vector2(height), + AutoSizeAxes = Axes.Both, CornerRadius = 3, Masking = true, + Child = avatar = new UpdateableAvatar + { + Size = new Vector2(height), + }, EdgeEffect = new EdgeEffectParameters { Colour = Color4.Black.Opacity(0.25f), @@ -80,6 +92,13 @@ namespace osu.Game.Overlays.BeatmapSet }; } + [BackgroundDependencyLoader(true)] + private void load(UserProfileOverlay profile) + { + this.profile = profile; + clickableArea.Action = () => profile?.ShowUser(avatar.User); + } + private class Field : FillFlowContainer { public Field(string first, string second, string secondFont) @@ -103,5 +122,10 @@ namespace osu.Game.Overlays.BeatmapSet }; } } + + private class ClickableArea : OsuClickableContainer, IHasTooltip + { + public string TooltipText => @"View Profile"; + } } } From 5e751ea0ec38aabdf24bb80be772ee88eaf5274e Mon Sep 17 00:00:00 2001 From: "Franc[e]sco" Date: Sun, 1 Oct 2017 00:15:23 +0200 Subject: [PATCH 11/16] Only convert chords into strong hits for mania -> taiko --- .../Beatmaps/TaikoBeatmapConverter.cs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 4f2707ff88..ceaecbb555 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -55,14 +55,17 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps Beatmap converted = base.ConvertBeatmap(original); - // Post processing step to transform hit objects with the same start time into strong hits - converted.HitObjects = converted.HitObjects.GroupBy(t => t.StartTime).Select(x => + if (original.BeatmapInfo.RulesetID == 3) { - TaikoHitObject first = x.First(); - if (x.Skip(1).Any()) - first.IsStrong = true; - return first; - }).ToList(); + // Post processing step to transform mania hit objects with the same start time into strong hits + converted.HitObjects = converted.HitObjects.GroupBy(t => t.StartTime).Select(x => + { + TaikoHitObject first = x.First(); + if (x.Skip(1).Any()) + first.IsStrong = true; + return first; + }).ToList(); + } return converted; } From 66afba62190f56c698678a4fb4ad03e280ed8318 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Oct 2017 17:38:48 +0800 Subject: [PATCH 12/16] Allow TestCasePlayer to instantiate only one ruleset type --- .../Tests/TestCaseCatchPlayer.cs | 4 +++ osu.Game/Rulesets/RulesetStore.cs | 1 - osu.Game/Tests/Visual/TestCasePlayer.cs | 31 ++++++++++++------- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs index 8d18a712d8..45ab8ac300 100644 --- a/osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs +++ b/osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs @@ -10,6 +10,10 @@ namespace osu.Game.Rulesets.Catch.Tests [TestFixture] public class TestCaseCatchPlayer : Game.Tests.Visual.TestCasePlayer { + public TestCaseCatchPlayer() : base(typeof(CatchRuleset)) + { + + } protected override Beatmap CreateBeatmap() { var beatmap = new Beatmap(); diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 5eef4a8470..407a5f7c3c 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -38,7 +38,6 @@ namespace osu.Game.Rulesets protected override void Prepare(bool reset = false) { - Connection.CreateTable(); if (reset) diff --git a/osu.Game/Tests/Visual/TestCasePlayer.cs b/osu.Game/Tests/Visual/TestCasePlayer.cs index 4a25a52e36..b0953ceb7e 100644 --- a/osu.Game/Tests/Visual/TestCasePlayer.cs +++ b/osu.Game/Tests/Visual/TestCasePlayer.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.IO; using System.Linq; using System.Text; @@ -18,31 +19,39 @@ namespace osu.Game.Tests.Visual { public class TestCasePlayer : OsuTestCase { + private readonly Type ruleset; + protected Player Player; - private RulesetStore rulesets; public override string Description => @"Showing everything to play the game."; + /// + /// Create a TestCase which runs through the Player screen. + /// + /// An optional ruleset type which we want to target. If not provided we'll allow all rulesets to be tested. + protected TestCasePlayer(Type ruleset) + { + this.ruleset = ruleset; + } + + public TestCasePlayer() + { + + } + [BackgroundDependencyLoader] private void load(RulesetStore rulesets) { - this.rulesets = rulesets; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - Add(new Box { RelativeSizeAxes = Framework.Graphics.Axes.Both, Colour = Color4.Black, }); - foreach (var r in rulesets.Query()) - AddStep(r.Name, () => loadPlayerFor(r)); + string instantiation = ruleset?.AssemblyQualifiedName; - loadPlayerFor(rulesets.Query().First()); + foreach (var r in rulesets.Query(rs => rs.Available && (instantiation == null || rs.InstantiationInfo == instantiation))) + AddStep(r.Name, () => loadPlayerFor(r)); } protected virtual Beatmap CreateBeatmap() From 12a9cbad56b84960226b21204ee2e6453d67d9a0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Oct 2017 21:54:26 +0800 Subject: [PATCH 13/16] Allow Beatmap to populate some metadata defaults if they aren't provided via BetamapInfo --- osu.Game/Beatmaps/Beatmap.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 458c2304f2..383a331eb4 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -58,6 +58,23 @@ namespace osu.Game.Beatmaps ComboColors = original?.ComboColors ?? ComboColors; HitObjects = original?.HitObjects ?? HitObjects; Storyboard = original?.Storyboard ?? Storyboard; + + if (original == null && Metadata == null) + { + // we may have no metadata in cases we weren't sourced from the database. + // let's fill it (and other related fields) so we don't need to null-check it in future usages. + BeatmapInfo = new BeatmapInfo + { + Metadata = new BeatmapMetadata + { + Artist = @"Unknown", + Title = @"Unknown", + Author = @"Unknown Creator", + }, + Version = @"Normal", + Difficulty = new BeatmapDifficulty() + }; + } } } From 7168629b2a28f59a121a844b45f481b138e3df0d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Oct 2017 21:55:37 +0800 Subject: [PATCH 14/16] Remove CatcherArea abstraction Also fixes catcher size being relative to aspect ratio. --- .../Tests/TestCaseCatcher.cs | 4 +- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 34 ++- osu.Game.Rulesets.Catch/UI/Catcher.cs | 193 +++++++++++++++ osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 229 ------------------ .../osu.Game.Rulesets.Catch.csproj | 2 +- 5 files changed, 225 insertions(+), 237 deletions(-) create mode 100644 osu.Game.Rulesets.Catch/UI/Catcher.cs delete mode 100644 osu.Game.Rulesets.Catch/UI/CatcherArea.cs diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseCatcher.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseCatcher.cs index 6a065e197d..21a9bdec51 100644 --- a/osu.Game.Rulesets.Catch/Tests/TestCaseCatcher.cs +++ b/osu.Game.Rulesets.Catch/Tests/TestCaseCatcher.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Catch.Tests { public override IReadOnlyList RequiredTypes => new[] { - typeof(CatcherArea), + typeof(Catcher), }; [BackgroundDependencyLoader] @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Catch.Tests new CatchInputManager(rulesets.GetRuleset(2)) { RelativeSizeAxes = Axes.Both, - Child = new CatcherArea + Child = new Catcher { RelativePositionAxes = Axes.Both, RelativeSizeAxes = Axes.Both, diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 2b6f9bbf5a..38f3273055 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -1,10 +1,12 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using osu.Framework.Graphics; using osu.Game.Rulesets.UI; using OpenTK; using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; @@ -15,11 +17,15 @@ namespace osu.Game.Rulesets.Catch.UI { protected override Container Content => content; private readonly Container content; - private readonly CatcherArea catcherArea; + + private readonly Container catcherContainer; + private readonly Catcher catcher; public CatchPlayfield() : base(Axes.Y) { + Container explodingFruitContainer; + Reversed.Value = true; Size = new Vector2(1); @@ -33,16 +39,34 @@ namespace osu.Game.Rulesets.Catch.UI { RelativeSizeAxes = Axes.Both, }, - catcherArea = new CatcherArea + explodingFruitContainer = new Container { RelativeSizeAxes = Axes.Both, + }, + catcherContainer = new Container { + RelativeSizeAxes = Axes.X, Anchor = Anchor.BottomLeft, Origin = Anchor.TopLeft, - Height = 0.3f + Height = 180, + Child = catcher = new Catcher + { + ExplodingFruitTarget = explodingFruitContainer, + RelativePositionAxes = Axes.Both, + Origin = Anchor.TopCentre, + X = 0.5f, + } } }; } + protected override void Update() + { + base.Update(); + catcher.Size = new Vector2(catcherContainer.DrawSize.Y); + } + + public bool CheckIfWeCanCatch(CatchBaseHit obj) => Math.Abs(catcher.Position.X - obj.X) < catcher.DrawSize.X / DrawSize.X / 2; + public override void Add(DrawableHitObject h) { h.Depth = (float)h.HitObject.StartTime; @@ -50,7 +74,7 @@ namespace osu.Game.Rulesets.Catch.UI base.Add(h); var fruit = (DrawableFruit)h; - fruit.CheckPosition = catcherArea.CheckIfWeCanCatch; + fruit.CheckPosition = CheckIfWeCanCatch; } public override void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) @@ -59,7 +83,7 @@ namespace osu.Game.Rulesets.Catch.UI { Vector2 screenPosition = judgedObject.ScreenSpaceDrawQuad.Centre; Remove(judgedObject); - catcherArea.Add(judgedObject, screenPosition); + catcher.Add(judgedObject, screenPosition); } } } diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs new file mode 100644 index 0000000000..87fe95ed2f --- /dev/null +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -0,0 +1,193 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +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.Input.Bindings; +using osu.Framework.MathUtils; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Objects.Drawables; +using OpenTK; + +namespace osu.Game.Rulesets.Catch.UI +{ + public class Catcher : Container, IKeyBindingHandler + { + private Texture texture; + + private Container caughtFruit; + + public Container ExplodingFruitTarget; + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + texture = textures.Get(@"Play/Catch/fruit-catcher-idle"); + + Children = new Drawable[] + { + createCatcherSprite(), + caughtFruit = new Container + { + Anchor = Anchor.TopCentre, + Origin = Anchor.BottomCentre, + } + }; + } + + private int currentDirection; + + private bool dashing; + + protected bool Dashing + { + get { return dashing; } + set + { + if (value == dashing) return; + + dashing = value; + + if (dashing) + Schedule(addAdditiveSprite); + } + } + + private void addAdditiveSprite() + { + if (!dashing) return; + + var additive = createCatcherSprite(); + + additive.RelativePositionAxes = Axes.Both; + additive.Blending = BlendingMode.Additive; + additive.Position = Position; + additive.Scale = Scale; + + ((Container)Parent).Add(additive); + + additive.FadeTo(0.4f).FadeOut(800, Easing.OutQuint).Expire(); + + Scheduler.AddDelayed(addAdditiveSprite, 50); + } + + private Sprite createCatcherSprite() => new Sprite + { + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fit, + Texture = texture, + OriginPosition = new Vector2(DrawWidth / 2, 10) //temporary until the sprite is aligned correctly. + }; + + public bool OnPressed(CatchAction action) + { + switch (action) + { + case CatchAction.MoveLeft: + currentDirection--; + return true; + case CatchAction.MoveRight: + currentDirection++; + return true; + case CatchAction.Dash: + Dashing = true; + return true; + } + + return false; + } + + public bool OnReleased(CatchAction action) + { + switch (action) + { + case CatchAction.MoveLeft: + currentDirection++; + return true; + case CatchAction.MoveRight: + currentDirection--; + return true; + case CatchAction.Dash: + Dashing = false; + return true; + } + + return false; + } + + /// + /// The relative space to cover in 1 millisecond. based on 1 game pixel per millisecond as in osu-stable. + /// + private const double base_speed = 1.0 / 512; + + protected override void Update() + { + base.Update(); + + if (currentDirection == 0) return; + + double dashModifier = Dashing ? 1 : 0.5; + + Scale = new Vector2(Math.Sign(currentDirection), 1); + X = (float)MathHelper.Clamp(X + Math.Sign(currentDirection) * Clock.ElapsedFrameTime * base_speed * dashModifier, 0, 1); + } + + public void Add(DrawableHitObject fruit, Vector2 absolutePosition) + { + fruit.RelativePositionAxes = Axes.None; + fruit.Position = new Vector2(ToLocalSpace(absolutePosition).X - DrawSize.X / 2, 0); + + fruit.Anchor = Anchor.TopCentre; + fruit.Origin = Anchor.BottomCentre; + fruit.Scale *= 0.7f; + fruit.LifetimeEnd = double.MaxValue; + + float distance = fruit.DrawSize.X / 2 * fruit.Scale.X; + + while (caughtFruit.Any(f => f.LifetimeEnd == double.MaxValue && Vector2Extensions.DistanceSquared(f.Position, fruit.Position) < distance * distance)) + { + fruit.X += RNG.Next(-5, 5); + fruit.Y -= RNG.Next(0, 5); + } + + caughtFruit.Add(fruit); + + if (((CatchBaseHit)fruit.HitObject).LastInCombo) + explode(); + } + + private void explode() + { + var fruit = caughtFruit.ToArray(); + + foreach (var f in fruit) + { + var originalX = f.X * Scale.X; + + if (ExplodingFruitTarget != null) + { + f.Anchor = Anchor.TopLeft; + f.Position = caughtFruit.ToSpaceOfOtherDrawable(f.DrawPosition, ExplodingFruitTarget); + + caughtFruit.Remove(f); + + ExplodingFruitTarget.Add(f); + } + + f.MoveToY(f.Y - 50, 250, Easing.OutSine) + .Then() + .MoveToY(f.Y + 50, 500, Easing.InSine); + + f.MoveToX(f.X + originalX * 6, 1000); + f.FadeOut(750); + + f.Expire(); + } + } + } +} diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs deleted file mode 100644 index 2930dbb7cc..0000000000 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ /dev/null @@ -1,229 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -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.Input.Bindings; -using osu.Framework.MathUtils; -using osu.Game.Rulesets.Catch.Objects; -using osu.Game.Rulesets.Objects.Drawables; -using OpenTK; - -namespace osu.Game.Rulesets.Catch.UI -{ - public class CatcherArea : Container - { - private Catcher catcher; - private Container explodingFruitContainer; - - public void Add(DrawableHitObject fruit, Vector2 screenPosition) => catcher.AddToStack(fruit, screenPosition); - - public bool CheckIfWeCanCatch(CatchBaseHit obj) => Math.Abs(catcher.Position.X - obj.X) < catcher.DrawSize.X / DrawSize.X / 2; - - [BackgroundDependencyLoader] - private void load() - { - Children = new Drawable[] - { - explodingFruitContainer = new Container - { - RelativeSizeAxes = Axes.Both, - }, - catcher = new Catcher - { - RelativePositionAxes = Axes.Both, - ExplodingFruitTarget = explodingFruitContainer, - Origin = Anchor.TopCentre, - X = 0.5f, - } - }; - } - - protected override void Update() - { - base.Update(); - - catcher.Size = new Vector2(DrawSize.Y); - } - - private class Catcher : Container, IKeyBindingHandler - { - private Texture texture; - - private Container caughtFruit; - - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - texture = textures.Get(@"Play/Catch/fruit-catcher-idle"); - - Children = new Drawable[] - { - createCatcherSprite(), - caughtFruit = new Container - { - Anchor = Anchor.TopCentre, - Origin = Anchor.BottomCentre, - } - }; - } - - private int currentDirection; - - private bool dashing; - - public Container ExplodingFruitTarget; - - protected bool Dashing - { - get { return dashing; } - set - { - if (value == dashing) return; - - dashing = value; - - if (dashing) - Schedule(addAdditiveSprite); - } - } - - private void addAdditiveSprite() - { - if (!dashing) return; - - var additive = createCatcherSprite(); - - additive.RelativePositionAxes = Axes.Both; - additive.Blending = BlendingMode.Additive; - additive.Position = Position; - additive.Scale = Scale; - - ((CatcherArea)Parent).Add(additive); - - additive.FadeTo(0.4f).FadeOut(800, Easing.OutQuint).Expire(); - - Scheduler.AddDelayed(addAdditiveSprite, 50); - } - - private Sprite createCatcherSprite() => new Sprite - { - RelativeSizeAxes = Axes.Both, - FillMode = FillMode.Fit, - Texture = texture, - OriginPosition = new Vector2(DrawWidth / 2, 10) //temporary until the sprite is aligned correctly. - }; - - public bool OnPressed(CatchAction action) - { - switch (action) - { - case CatchAction.MoveLeft: - currentDirection--; - return true; - case CatchAction.MoveRight: - currentDirection++; - return true; - case CatchAction.Dash: - Dashing = true; - return true; - } - - return false; - } - - public bool OnReleased(CatchAction action) - { - switch (action) - { - case CatchAction.MoveLeft: - currentDirection++; - return true; - case CatchAction.MoveRight: - currentDirection--; - return true; - case CatchAction.Dash: - Dashing = false; - return true; - } - - return false; - } - - /// - /// The relative space to cover in 1 millisecond. based on 1 game pixel per millisecond as in osu-stable. - /// - private const double base_speed = 1.0 / 512; - - protected override void Update() - { - base.Update(); - - if (currentDirection == 0) return; - - double dashModifier = Dashing ? 1 : 0.5; - - Scale = new Vector2(Math.Sign(currentDirection), 1); - X = (float)MathHelper.Clamp(X + Math.Sign(currentDirection) * Clock.ElapsedFrameTime * base_speed * dashModifier, 0, 1); - } - - public void AddToStack(DrawableHitObject fruit, Vector2 absolutePosition) - { - fruit.RelativePositionAxes = Axes.None; - fruit.Position = new Vector2(ToLocalSpace(absolutePosition).X - DrawSize.X / 2, 0); - - fruit.Anchor = Anchor.TopCentre; - fruit.Origin = Anchor.BottomCentre; - fruit.Scale *= 0.7f; - fruit.LifetimeEnd = double.MaxValue; - - float distance = fruit.DrawSize.X / 2 * fruit.Scale.X; - - while (caughtFruit.Any(f => f.LifetimeEnd == double.MaxValue && Vector2Extensions.DistanceSquared(f.Position, fruit.Position) < distance * distance)) - { - fruit.X += RNG.Next(-5, 5); - fruit.Y -= RNG.Next(0, 5); - } - - caughtFruit.Add(fruit); - - if (((CatchBaseHit)fruit.HitObject).LastInCombo) - explode(); - } - - private void explode() - { - var fruit = caughtFruit.ToArray(); - - foreach (var f in fruit) - { - var originalX = f.X * Scale.X; - - if (ExplodingFruitTarget != null) - { - f.Anchor = Anchor.TopLeft; - f.Position = caughtFruit.ToSpaceOfOtherDrawable(f.DrawPosition, ExplodingFruitTarget); - - caughtFruit.Remove(f); - - ExplodingFruitTarget.Add(f); - } - - f.MoveToY(f.Y - 50, 250, Easing.OutSine) - .Then() - .MoveToY(f.Y + 50, 500, Easing.InSine); - - f.MoveToX(f.X + originalX * 6, 1000); - f.FadeOut(750); - - f.Expire(); - } - } - } - } -} diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index 787825d482..718ae32a17 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -59,7 +59,7 @@ - + From 3338024c17b6febbf5aa47acc41b021e1f25c83c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Oct 2017 22:12:53 +0800 Subject: [PATCH 15/16] Fix incorrect whitespace --- osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs index 45ab8ac300..5be07e94c0 100644 --- a/osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs +++ b/osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs @@ -12,8 +12,8 @@ namespace osu.Game.Rulesets.Catch.Tests { public TestCaseCatchPlayer() : base(typeof(CatchRuleset)) { - } + protected override Beatmap CreateBeatmap() { var beatmap = new Beatmap(); From 37393ab2c946bfb236e7ae0514efcf895ffcec4a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Oct 2017 22:24:22 +0800 Subject: [PATCH 16/16] Move brace --- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 38f3273055..c4033b562d 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -43,7 +43,8 @@ namespace osu.Game.Rulesets.Catch.UI { RelativeSizeAxes = Axes.Both, }, - catcherContainer = new Container { + catcherContainer = new Container + { RelativeSizeAxes = Axes.X, Anchor = Anchor.BottomLeft, Origin = Anchor.TopLeft,