From 8c30fd490c373492e219bead97d5ae9fc7e57bf9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 29 Nov 2017 16:22:11 +0900 Subject: [PATCH 01/49] Add HitObjectComposer class --- osu.Game.Rulesets.Catch/Edit/HitObjectComposer.cs | 10 ++++++++++ osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj | 1 + osu.Game.Rulesets.Mania/Edit/HitObjectComposer.cs | 10 ++++++++++ osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj | 1 + osu.Game.Rulesets.Osu/Edit/HitObjectComposer.cs | 10 ++++++++++ osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj | 1 + osu.Game.Rulesets.Taiko/Edit/HitObjectComposer.cs | 10 ++++++++++ osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj | 1 + osu.Game/Rulesets/Edit/HitObjectComposer.cs | 10 ++++++++++ osu.Game/osu.Game.csproj | 1 + 10 files changed, 55 insertions(+) create mode 100644 osu.Game.Rulesets.Catch/Edit/HitObjectComposer.cs create mode 100644 osu.Game.Rulesets.Mania/Edit/HitObjectComposer.cs create mode 100644 osu.Game.Rulesets.Osu/Edit/HitObjectComposer.cs create mode 100644 osu.Game.Rulesets.Taiko/Edit/HitObjectComposer.cs create mode 100644 osu.Game/Rulesets/Edit/HitObjectComposer.cs diff --git a/osu.Game.Rulesets.Catch/Edit/HitObjectComposer.cs b/osu.Game.Rulesets.Catch/Edit/HitObjectComposer.cs new file mode 100644 index 0000000000..01351fd00c --- /dev/null +++ b/osu.Game.Rulesets.Catch/Edit/HitObjectComposer.cs @@ -0,0 +1,10 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Catch.Edit +{ + public class HitObjectComposer : Rulesets.Edit.HitObjectComposer + { + + } +} diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index bf60bc01bb..30c088ac85 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -48,6 +48,7 @@ + diff --git a/osu.Game.Rulesets.Mania/Edit/HitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/HitObjectComposer.cs new file mode 100644 index 0000000000..aa0d43dc75 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/HitObjectComposer.cs @@ -0,0 +1,10 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Mania.Edit +{ + public class HitObjectComposer : Rulesets.Edit.HitObjectComposer + { + + } +} diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 6f45a64d92..1470ee57b1 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -53,6 +53,7 @@ + diff --git a/osu.Game.Rulesets.Osu/Edit/HitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/HitObjectComposer.cs new file mode 100644 index 0000000000..921fb72fdf --- /dev/null +++ b/osu.Game.Rulesets.Osu/Edit/HitObjectComposer.cs @@ -0,0 +1,10 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Osu.Edit +{ + public class HitObjectComposer : Rulesets.Edit.HitObjectComposer + { + + } +} diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index 3c90749777..32a0a34ff2 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -49,6 +49,7 @@ + diff --git a/osu.Game.Rulesets.Taiko/Edit/HitObjectComposer.cs b/osu.Game.Rulesets.Taiko/Edit/HitObjectComposer.cs new file mode 100644 index 0000000000..e524b4cdc7 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Edit/HitObjectComposer.cs @@ -0,0 +1,10 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Taiko.Edit +{ + public class HitObjectComposer : Rulesets.Edit.HitObjectComposer + { + + } +} diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index bf627d205a..41881fc250 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -46,6 +46,7 @@ + diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs new file mode 100644 index 0000000000..2724334ed4 --- /dev/null +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -0,0 +1,10 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Edit +{ + public class HitObjectComposer + { + + } +} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index ce9e8eff9c..b707a3382e 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -559,6 +559,7 @@ + From 2ec24f58c8e5c30e9c3cd681f55869f971b4f80e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 29 Nov 2017 16:30:59 +0900 Subject: [PATCH 02/49] Add testcase for editor compose --- .../Visual/TestCaseEditorCompose.cs | 47 +++++++++++++++++++ osu.Game.Tests/osu.Game.Tests.csproj | 1 + 2 files changed, 48 insertions(+) create mode 100644 osu.Game.Tests/Visual/TestCaseEditorCompose.cs diff --git a/osu.Game.Tests/Visual/TestCaseEditorCompose.cs b/osu.Game.Tests/Visual/TestCaseEditorCompose.cs new file mode 100644 index 0000000000..9f060a9ec4 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseEditorCompose.cs @@ -0,0 +1,47 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Allocation; +using osu.Game.Beatmaps; +using osu.Game.Screens.Edit.Screens.Compose; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseEditorCompose : OsuTestCase + { + private readonly Random random; + private readonly Compose compose; + + public TestCaseEditorCompose() + { + random = new Random(1337); + + Add(compose = new Compose()); + AddStep("Next beatmap", nextBeatmap); + } + + private OsuGameBase osuGame; + private BeatmapManager beatmaps; + + [BackgroundDependencyLoader] + private void load(OsuGameBase osuGame, BeatmapManager beatmaps) + { + this.osuGame = osuGame; + this.beatmaps = beatmaps; + + compose.Beatmap.BindTo(osuGame.Beatmap); + nextBeatmap(); + } + + private void nextBeatmap() + { + var sets = beatmaps.GetAllUsableBeatmapSets(); + if (sets.Count == 0) + return; + + var b = sets[random.Next(0, sets.Count)].Beatmaps[0]; + osuGame.Beatmap.Value = beatmaps.GetWorkingBeatmap(b); + } + } +} diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 312a564f71..34f79987c5 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -105,6 +105,7 @@ + From f586cbac3285e2b2a8e8586276bd660e9736ddb0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 29 Nov 2017 16:47:36 +0900 Subject: [PATCH 03/49] Restructure Compose to use grids and eventually support HitObjectContainer --- .../Screens/Edit/Screens/Compose/Compose.cs | 66 ++++++++++++------- 1 file changed, 44 insertions(+), 22 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Compose.cs b/osu.Game/Screens/Edit/Screens/Compose/Compose.cs index 2349c261cf..67e66eecdf 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Compose.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Compose.cs @@ -12,40 +12,62 @@ namespace osu.Game.Screens.Edit.Screens.Compose { public class Compose : EditorScreen { + private const float vertical_margins = 10; + private const float horizontal_margins = 20; + public Compose() { ScrollableTimeline timeline; - Children = new[] + Children = new Drawable[] { - new Container + new GridContainer { - Name = "Timeline", - RelativeSizeAxes = Axes.X, - Height = 110, - Children = new Drawable[] + RelativeSizeAxes = Axes.Both, + Content = new[] { - new Box + new Drawable[] { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black.Opacity(0.5f) - }, - new Container - { - Name = "Content", - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = 17, Vertical = 10 }, - Children = new Drawable[] + new Container { - new Container + Name = "Timeline", + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Right = 115 }, - Child = timeline = new ScrollableTimeline { RelativeSizeAxes = Axes.Both } + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black.Opacity(0.5f) + }, + new Container + { + Name = "Timeline content", + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = horizontal_margins, Vertical = vertical_margins }, + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Right = 115 }, + Child = timeline = new ScrollableTimeline { RelativeSizeAxes = Axes.Both } + } + } + } } } + }, + new Drawable[] + { + new Container + { + Name = "Composer content", + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = horizontal_margins, Vertical = vertical_margins }, + } } - } - } + }, + RowDimensions = new[] { new Dimension(GridSizeMode.Absolute, 110) } + }, }; timeline.Beatmap.BindTo(Beatmap); From 309eb4edd752b95d108770f2df55f6efdcd6ac2c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 29 Nov 2017 17:46:12 +0900 Subject: [PATCH 04/49] Integrate HitObjectComposer into Compose Also removes the other rulesets' HitObjectComposers for now. --- .../Edit/HitObjectComposer.cs | 10 -------- .../osu.Game.Rulesets.Catch.csproj | 1 - .../Edit/HitObjectComposer.cs | 10 -------- .../osu.Game.Rulesets.Mania.csproj | 1 - ...ectComposer.cs => OsuHitObjectComposer.cs} | 7 ++++-- osu.Game.Rulesets.Osu/OsuRuleset.cs | 4 ++++ .../osu.Game.Rulesets.Osu.csproj | 2 +- .../Edit/HitObjectComposer.cs | 10 -------- .../osu.Game.Rulesets.Taiko.csproj | 1 - osu.Game/Rulesets/Edit/HitObjectComposer.cs | 23 +++++++++++++++++- osu.Game/Rulesets/Ruleset.cs | 3 +++ .../Screens/Edit/Screens/Compose/Compose.cs | 24 ++++++++++++++++++- 12 files changed, 58 insertions(+), 38 deletions(-) delete mode 100644 osu.Game.Rulesets.Catch/Edit/HitObjectComposer.cs delete mode 100644 osu.Game.Rulesets.Mania/Edit/HitObjectComposer.cs rename osu.Game.Rulesets.Osu/Edit/{HitObjectComposer.cs => OsuHitObjectComposer.cs} (52%) delete mode 100644 osu.Game.Rulesets.Taiko/Edit/HitObjectComposer.cs diff --git a/osu.Game.Rulesets.Catch/Edit/HitObjectComposer.cs b/osu.Game.Rulesets.Catch/Edit/HitObjectComposer.cs deleted file mode 100644 index 01351fd00c..0000000000 --- a/osu.Game.Rulesets.Catch/Edit/HitObjectComposer.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -namespace osu.Game.Rulesets.Catch.Edit -{ - public class HitObjectComposer : Rulesets.Edit.HitObjectComposer - { - - } -} diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index 30c088ac85..bf60bc01bb 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -48,7 +48,6 @@ - diff --git a/osu.Game.Rulesets.Mania/Edit/HitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/HitObjectComposer.cs deleted file mode 100644 index aa0d43dc75..0000000000 --- a/osu.Game.Rulesets.Mania/Edit/HitObjectComposer.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -namespace osu.Game.Rulesets.Mania.Edit -{ - public class HitObjectComposer : Rulesets.Edit.HitObjectComposer - { - - } -} diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 1470ee57b1..6f45a64d92 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -53,7 +53,6 @@ - diff --git a/osu.Game.Rulesets.Osu/Edit/HitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs similarity index 52% rename from osu.Game.Rulesets.Osu/Edit/HitObjectComposer.cs rename to osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 921fb72fdf..18dfbb6711 100644 --- a/osu.Game.Rulesets.Osu/Edit/HitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -3,8 +3,11 @@ namespace osu.Game.Rulesets.Osu.Edit { - public class HitObjectComposer : Rulesets.Edit.HitObjectComposer + public class OsuHitObjectComposer : Rulesets.Edit.HitObjectComposer { - + public OsuHitObjectComposer(Ruleset ruleset) + : base(ruleset) + { + } } } diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index c87328d87c..64e76d6022 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -14,6 +14,8 @@ using System.Linq; using osu.Framework.Graphics; using osu.Game.Overlays.Settings; using osu.Framework.Input.Bindings; +using osu.Game.Rulesets.Osu.Edit; +using osu.Game.Rulesets.Edit; namespace osu.Game.Rulesets.Osu { @@ -114,6 +116,8 @@ namespace osu.Game.Rulesets.Osu public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new OsuDifficultyCalculator(beatmap, mods); + public override HitObjectComposer CreateHitObjectComposer() => new OsuHitObjectComposer(this); + public override string Description => "osu!"; public override SettingsSubsection CreateSettings() => new OsuSettings(); diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index 32a0a34ff2..34f9bdf972 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -49,7 +49,7 @@ - + diff --git a/osu.Game.Rulesets.Taiko/Edit/HitObjectComposer.cs b/osu.Game.Rulesets.Taiko/Edit/HitObjectComposer.cs deleted file mode 100644 index e524b4cdc7..0000000000 --- a/osu.Game.Rulesets.Taiko/Edit/HitObjectComposer.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -namespace osu.Game.Rulesets.Taiko.Edit -{ - public class HitObjectComposer : Rulesets.Edit.HitObjectComposer - { - - } -} diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index 41881fc250..bf627d205a 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -46,7 +46,6 @@ - diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 2724334ed4..da31f6ba66 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -1,10 +1,31 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; + namespace osu.Game.Rulesets.Edit { - public class HitObjectComposer + public abstract class HitObjectComposer : CompositeDrawable { + private readonly Ruleset ruleset; + public HitObjectComposer(Ruleset ruleset) + { + this.ruleset = ruleset; + + RelativeSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader] + private void load(OsuGameBase osuGame) + { + try + { + InternalChild = ruleset.CreateRulesetContainerWith(osuGame.Beatmap.Value, true); + } + catch { } + } } } diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index ed2fdf4157..dfa9ea5125 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -9,6 +9,7 @@ using osu.Framework.Input.Bindings; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Overlays.Settings; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; @@ -49,6 +50,8 @@ namespace osu.Game.Rulesets public abstract DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null); + public virtual HitObjectComposer CreateHitObjectComposer() => null; + public virtual Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_question_circle }; public abstract string Description { get; } diff --git a/osu.Game/Screens/Edit/Screens/Compose/Compose.cs b/osu.Game/Screens/Edit/Screens/Compose/Compose.cs index 67e66eecdf..8cfb04da06 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Compose.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Compose.cs @@ -1,11 +1,14 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using OpenTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Timing; +using osu.Game.Beatmaps; using osu.Game.Screens.Edit.Screens.Compose.Timeline; namespace osu.Game.Screens.Edit.Screens.Compose @@ -15,6 +18,8 @@ namespace osu.Game.Screens.Edit.Screens.Compose private const float vertical_margins = 10; private const float horizontal_margins = 20; + private readonly Container composerContainer; + public Compose() { ScrollableTimeline timeline; @@ -58,7 +63,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose }, new Drawable[] { - new Container + composerContainer = new Container { Name = "Composer content", RelativeSizeAxes = Axes.Both, @@ -71,6 +76,23 @@ namespace osu.Game.Screens.Edit.Screens.Compose }; timeline.Beatmap.BindTo(Beatmap); + + Beatmap.ValueChanged += beatmapChanged; + } + + private void beatmapChanged(WorkingBeatmap newBeatmap) + { + var ruleset = newBeatmap.BeatmapInfo.Ruleset.CreateInstance(); + var composer = ruleset.CreateHitObjectComposer(); + if (composer == null) + { + // Todo: Handle this + //throw new InvalidOperationException($"Ruleset {ruleset.Description} doesn't support hitobject composition."); + return; + } + + composerContainer.Add(composer); + composerContainer.Clock = new InterpolatingFramedClock((IAdjustableClock)newBeatmap.Track ?? new StopwatchClock()); } } } From ee35422efc0396ec7800933ae4e2e51abfb45140 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 29 Nov 2017 18:38:12 +0900 Subject: [PATCH 05/49] Handle rulesets that don't support composition a bit better --- osu.Game/Screens/Edit/Editor.cs | 1 + osu.Game/Screens/Edit/Screens/Compose/Compose.cs | 10 +++++----- osu.Game/Screens/Edit/Screens/EditorScreen.cs | 3 +++ 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 607ff792d8..bc86c683c7 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -154,6 +154,7 @@ namespace osu.Game.Screens.Edit } currentScreen.Beatmap.BindTo(Beatmap); + currentScreen.ExitRequested = Exit; screenContainer.Add(currentScreen); } diff --git a/osu.Game/Screens/Edit/Screens/Compose/Compose.cs b/osu.Game/Screens/Edit/Screens/Compose/Compose.cs index 8cfb04da06..6954995340 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Compose.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Compose.cs @@ -7,6 +7,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Logging; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Screens.Edit.Screens.Compose.Timeline; @@ -76,18 +77,17 @@ namespace osu.Game.Screens.Edit.Screens.Compose }; timeline.Beatmap.BindTo(Beatmap); - Beatmap.ValueChanged += beatmapChanged; } private void beatmapChanged(WorkingBeatmap newBeatmap) { - var ruleset = newBeatmap.BeatmapInfo.Ruleset.CreateInstance(); - var composer = ruleset.CreateHitObjectComposer(); + var ruleset = newBeatmap.BeatmapInfo.Ruleset?.CreateInstance(); + var composer = ruleset?.CreateHitObjectComposer(); if (composer == null) { - // Todo: Handle this - //throw new InvalidOperationException($"Ruleset {ruleset.Description} doesn't support hitobject composition."); + Logger.Log($"Ruleset {ruleset.Description} doesn't support hitobject composition."); + ExitRequested?.Invoke(); return; } diff --git a/osu.Game/Screens/Edit/Screens/EditorScreen.cs b/osu.Game/Screens/Edit/Screens/EditorScreen.cs index ac248930d8..9a158d20f1 100644 --- a/osu.Game/Screens/Edit/Screens/EditorScreen.cs +++ b/osu.Game/Screens/Edit/Screens/EditorScreen.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 osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -10,6 +11,8 @@ namespace osu.Game.Screens.Edit.Screens { public class EditorScreen : Container { + public Action ExitRequested; + public readonly Bindable Beatmap = new Bindable(); protected override Container Content => content; From a7a9569aee3c4f8e9adfdfb754d39f2a47aa656b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 30 Nov 2017 13:53:57 +0900 Subject: [PATCH 06/49] Don't exit when we don't have composer for now --- osu.Game/Screens/Edit/Screens/Compose/Compose.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Compose.cs b/osu.Game/Screens/Edit/Screens/Compose/Compose.cs index 6954995340..fea439bfb8 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Compose.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Compose.cs @@ -87,7 +87,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose if (composer == null) { Logger.Log($"Ruleset {ruleset.Description} doesn't support hitobject composition."); - ExitRequested?.Invoke(); + // ExitRequested?.Invoke(); return; } From abd61256911a9ff7e52cc5390895ec3c9e226fd1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 30 Nov 2017 14:00:17 +0900 Subject: [PATCH 07/49] Make sure that composerContainer is cleared for testing purposes --- osu.Game/Screens/Edit/Screens/Compose/Compose.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Compose.cs b/osu.Game/Screens/Edit/Screens/Compose/Compose.cs index fea439bfb8..7e4ce74c5c 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Compose.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Compose.cs @@ -82,6 +82,8 @@ namespace osu.Game.Screens.Edit.Screens.Compose private void beatmapChanged(WorkingBeatmap newBeatmap) { + composerContainer.Clear(); + var ruleset = newBeatmap.BeatmapInfo.Ruleset?.CreateInstance(); var composer = ruleset?.CreateHitObjectComposer(); if (composer == null) @@ -91,7 +93,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose return; } - composerContainer.Add(composer); + composerContainer.Child = composer; composerContainer.Clock = new InterpolatingFramedClock((IAdjustableClock)newBeatmap.Track ?? new StopwatchClock()); } } From ead745697875d10bb96fd786c72cbf2e074bac41 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 30 Nov 2017 15:43:19 +0900 Subject: [PATCH 08/49] Add compose radio buttons + testcase --- .../TestCaseEditorComposeRadioButtons.cs | 34 ++++++ osu.Game.Tests/osu.Game.Tests.csproj | 1 + .../RadioButtons/DrawableRadioButton.cs | 107 ++++++++++++++++++ .../Compose/RadioButtons/RadioButton.cs | 20 ++++ .../RadioButtons/RadioButtonCollection.cs | 48 ++++++++ osu.Game/osu.Game.csproj | 5 +- 6 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs create mode 100644 osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs create mode 100644 osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButton.cs create mode 100644 osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs diff --git a/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs b/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs new file mode 100644 index 0000000000..55ceac6fd8 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs @@ -0,0 +1,34 @@ +// 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.UserInterface; +using osu.Game.Screens.Edit.Screens.Compose.RadioButtons; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseEditorComposeRadioButtons : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] { typeof(DrawableRadioButton) }; + + public TestCaseEditorComposeRadioButtons() + { + Add(new RadioButtonCollection + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 150, + Items = new[] + { + new RadioButton { Text = "Item 1", Action = () => { } }, + new RadioButton { Text = "Item 2", Action = () => { } }, + new RadioButton { Text = "Item 3", Action = () => { } }, + new RadioButton { Text = "Item 4", Action = () => { } }, + new RadioButton { Text = "Item 5", Action = () => { } } + } + }); + } + } +} diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 34f79987c5..ae88fb004f 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -106,6 +106,7 @@ + diff --git a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs new file mode 100644 index 0000000000..4ac36cc07e --- /dev/null +++ b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs @@ -0,0 +1,107 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using OpenTK; +using OpenTK.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons +{ + public class DrawableRadioButton : TriangleButton + { + private static readonly Color4 DefaultBackgroundColour = OsuColour.FromHex("333"); + private static readonly Color4 DefaultBubbleColour = DefaultBackgroundColour.Darken(0.5f); + private static readonly Color4 SelectedBackgroundColour = OsuColour.FromHex("1188aa"); + private static readonly Color4 SelectedBubbleColour = SelectedBackgroundColour.Lighten(0.5f); + + /// + /// Invoked when this has been selected. + /// + public Action Selected; + + private Drawable bubble; + + public DrawableRadioButton(RadioButton button) + { + Text = button.Text; + Action = button.Action; + + RelativeSizeAxes = Axes.X; + } + + [BackgroundDependencyLoader] + private void load() + { + Triangles.Alpha = 0; + BackgroundColour = DefaultBackgroundColour; + + Add(bubble = new CircularContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fit, + Scale = new Vector2(0.5f), + X = 10, + Masking = true, + Colour = DefaultBubbleColour, + Blending = BlendingMode.Additive, + Child = new Box { RelativeSizeAxes = Axes.Both } + }); + } + + private bool isSelected; + + public void Deselect() + { + if (!isSelected) + return; + isSelected = false; + + BackgroundColour = DefaultBackgroundColour; + bubble.Colour = DefaultBubbleColour; + } + + public void Select() + { + if (isSelected) + return; + isSelected = true; + Selected?.Invoke(this); + + BackgroundColour = SelectedBackgroundColour; + bubble.Colour = SelectedBubbleColour; + } + + protected override bool OnClick(InputState state) + { + if (isSelected) + return true; + + if (!Enabled) + return true; + + Select(); + + return base.OnClick(state); + } + + protected override SpriteText CreateText() => new OsuSpriteText + { + Depth = -1, + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + X = 40f + }; + } +} diff --git a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButton.cs b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButton.cs new file mode 100644 index 0000000000..3ef89d2a2b --- /dev/null +++ b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButton.cs @@ -0,0 +1,20 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; + +namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons +{ + public class RadioButton + { + /// + /// The text that should be displayed in this button. + /// + public string Text; + + /// + /// The that should be invoked when this button is selected. + /// + public Action Action; + } +} diff --git a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs new file mode 100644 index 0000000000..557e8e1ee8 --- /dev/null +++ b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs @@ -0,0 +1,48 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using System.Linq; +using OpenTK; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; + +namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons +{ + public class RadioButtonCollection : CompositeDrawable + { + public IReadOnlyList Items + { + set + { + buttonContainer.Clear(); + value.ForEach(addButton); + } + } + + private readonly FlowContainer buttonContainer; + + public RadioButtonCollection() + { + AutoSizeAxes = Axes.Y; + + InternalChild = buttonContainer = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5) + }; + } + + private void addButton(RadioButton button) => buttonContainer.Add(new DrawableRadioButton(button) { Selected = buttonSelected }); + + private DrawableRadioButton currentlySelected; + private void buttonSelected(DrawableRadioButton drawableButton) + { + currentlySelected?.Deselect(); + currentlySelected = drawableButton; + } + } +} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b4ab8a4cf2..1064665a0e 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -306,7 +306,6 @@ - @@ -316,6 +315,10 @@ + + + + From 73e41f9dded5128bb4df51efc5ffc74e107828fe Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 30 Nov 2017 16:57:30 +0900 Subject: [PATCH 09/49] Add constructors to RadioButton --- .../Visual/TestCaseEditorComposeRadioButtons.cs | 10 +++++----- .../Screens/Compose/RadioButtons/RadioButton.cs | 14 +++++++++++++- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs b/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs index 55ceac6fd8..c259ca666e 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs @@ -22,11 +22,11 @@ namespace osu.Game.Tests.Visual Width = 150, Items = new[] { - new RadioButton { Text = "Item 1", Action = () => { } }, - new RadioButton { Text = "Item 2", Action = () => { } }, - new RadioButton { Text = "Item 3", Action = () => { } }, - new RadioButton { Text = "Item 4", Action = () => { } }, - new RadioButton { Text = "Item 5", Action = () => { } } + new RadioButton("Item 1", () => { }), + new RadioButton("Item 2", () => { }), + new RadioButton("Item 3", () => { }), + new RadioButton("Item 4", () => { }), + new RadioButton("Item 5", () => { }) } }); } diff --git a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButton.cs b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButton.cs index 3ef89d2a2b..bec2d1903d 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButton.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButton.cs @@ -5,7 +5,7 @@ using System; namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons { - public class RadioButton + public struct RadioButton { /// /// The text that should be displayed in this button. @@ -16,5 +16,17 @@ namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons /// The that should be invoked when this button is selected. /// public Action Action; + + public RadioButton(string text) + { + Text = text; + Action = null; + } + + public RadioButton(string text, Action action) + { + Text = text; + Action = action; + } } } From 456bbe25f38e34253cf77b9057e20022add7e9e5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 30 Nov 2017 16:58:14 +0900 Subject: [PATCH 10/49] Implement toolbox into HitObjectComposer --- .../Edit/OsuHitObjectComposer.cs | 11 +++ osu.Game/Rulesets/Edit/HitObjectComposer.cs | 67 ++++++++++++++++++- osu.Game/Rulesets/Edit/ToolboxGroup.cs | 19 ++++++ .../Edit/Tools/HitObjectCompositionTool.cs | 10 +++ .../Rulesets/Edit/Tools/ICompositionTool.cs | 10 +++ osu.Game/Rulesets/Edit/Tools/SelectionTool.cs | 7 ++ .../Screens/Edit/Screens/Compose/Compose.cs | 1 - osu.Game/osu.Game.csproj | 4 ++ 8 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 osu.Game/Rulesets/Edit/ToolboxGroup.cs create mode 100644 osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs create mode 100644 osu.Game/Rulesets/Edit/Tools/ICompositionTool.cs create mode 100644 osu.Game/Rulesets/Edit/Tools/SelectionTool.cs diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 18dfbb6711..851e572163 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -1,6 +1,10 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; +using osu.Game.Rulesets.Edit.Tools; +using osu.Game.Rulesets.Osu.Objects; + namespace osu.Game.Rulesets.Osu.Edit { public class OsuHitObjectComposer : Rulesets.Edit.HitObjectComposer @@ -9,5 +13,12 @@ namespace osu.Game.Rulesets.Osu.Edit : base(ruleset) { } + + protected override IReadOnlyList CompositionTools => new ICompositionTool[] + { + new HitObjectCompositionTool(), + new HitObjectCompositionTool(), + new HitObjectCompositionTool() + }; } } diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index da31f6ba66..8c4969cec5 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -1,9 +1,20 @@ // 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 System.Linq; using osu.Framework.Allocation; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Logging; +using osu.Framework.Timing; +using osu.Game.Rulesets.Edit.Tools; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.UI; +using osu.Game.Screens.Edit.Screens.Compose.RadioButtons; +using osu.Game.Screens.Play.ReplaySettings; namespace osu.Game.Rulesets.Edit { @@ -21,11 +32,63 @@ namespace osu.Game.Rulesets.Edit [BackgroundDependencyLoader] private void load(OsuGameBase osuGame) { + RulesetContainer rulesetContainer; try { - InternalChild = ruleset.CreateRulesetContainerWith(osuGame.Beatmap.Value, true); + rulesetContainer = ruleset.CreateRulesetContainerWith(osuGame.Beatmap.Value, true); } - catch { } + catch (Exception e) + { + Logger.Log($"Could not load this beatmap sucessfully ({e})!", LoggingTarget.Runtime, LogLevel.Error); + return; + } + + RadioButtonCollection toolboxCollection; + InternalChild = new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] + { + new FillFlowContainer + { + Name = "Sidebar", + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Right = 10 }, + Children = new Drawable[] + { + new ToolboxGroup { Child = toolboxCollection = new RadioButtonCollection { RelativeSizeAxes = Axes.X } } + } + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + Child = rulesetContainer + } + }, + }, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.Absolute, 200), + } + }; + + rulesetContainer.Clock = new InterpolatingFramedClock((IAdjustableClock)osuGame.Beatmap.Value.Track ?? new StopwatchClock()); + + toolboxCollection.Items = + new[] { new RadioButton("Select", () => setCompositionTool(new SelectionTool())) } + .Concat( + CompositionTools.Select(t => new RadioButton(t.Name, () => setCompositionTool(t))) + ) + .ToList(); } + + private void setCompositionTool(ICompositionTool tool) + { + } + + protected abstract IReadOnlyList CompositionTools { get; } } } diff --git a/osu.Game/Rulesets/Edit/ToolboxGroup.cs b/osu.Game/Rulesets/Edit/ToolboxGroup.cs new file mode 100644 index 0000000000..70e4d3a0c5 --- /dev/null +++ b/osu.Game/Rulesets/Edit/ToolboxGroup.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Game.Screens.Play.ReplaySettings; + +namespace osu.Game.Rulesets.Edit +{ + public class ToolboxGroup : ReplayGroup + { + protected override string Title => "toolbox"; + + public ToolboxGroup() + { + RelativeSizeAxes = Axes.X; + Width = 1; + } + } +} diff --git a/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs b/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs new file mode 100644 index 0000000000..914cbd11ca --- /dev/null +++ b/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs @@ -0,0 +1,10 @@ +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Rulesets.Edit.Tools +{ + public class HitObjectCompositionTool : ICompositionTool + where T : HitObject + { + public string Name => typeof(T).Name; + } +} diff --git a/osu.Game/Rulesets/Edit/Tools/ICompositionTool.cs b/osu.Game/Rulesets/Edit/Tools/ICompositionTool.cs new file mode 100644 index 0000000000..eba873f0cf --- /dev/null +++ b/osu.Game/Rulesets/Edit/Tools/ICompositionTool.cs @@ -0,0 +1,10 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Edit.Tools +{ + public interface ICompositionTool + { + string Name { get; } + } +} diff --git a/osu.Game/Rulesets/Edit/Tools/SelectionTool.cs b/osu.Game/Rulesets/Edit/Tools/SelectionTool.cs new file mode 100644 index 0000000000..9f3ef78a02 --- /dev/null +++ b/osu.Game/Rulesets/Edit/Tools/SelectionTool.cs @@ -0,0 +1,7 @@ +namespace osu.Game.Rulesets.Edit.Tools +{ + public class SelectionTool : ICompositionTool + { + public string Name => "Select"; + } +} diff --git a/osu.Game/Screens/Edit/Screens/Compose/Compose.cs b/osu.Game/Screens/Edit/Screens/Compose/Compose.cs index 7e4ce74c5c..5eeaf3205d 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Compose.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Compose.cs @@ -94,7 +94,6 @@ namespace osu.Game.Screens.Edit.Screens.Compose } composerContainer.Child = composer; - composerContainer.Clock = new InterpolatingFramedClock((IAdjustableClock)newBeatmap.Track ?? new StopwatchClock()); } } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 1064665a0e..886d3313c6 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -562,7 +562,11 @@ + + + + From e5353bb53e2a898a523c542854b6911ed30687ea Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 30 Nov 2017 17:38:55 +0900 Subject: [PATCH 11/49] Add border to playfield, add shadow to toolbox buttons --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 15 ++++++++++++++- .../Compose/RadioButtons/DrawableRadioButton.cs | 8 ++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 8c4969cec5..ed057dbb03 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -4,10 +4,12 @@ using System; using System.Collections.Generic; using System.Linq; +using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Logging; using osu.Framework.Timing; using osu.Game.Rulesets.Edit.Tools; @@ -65,7 +67,18 @@ namespace osu.Game.Rulesets.Edit { RelativeSizeAxes = Axes.Both, Masking = true, - Child = rulesetContainer + BorderColour = Color4.White, + BorderThickness = 2, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true, + }, + rulesetContainer + } } }, }, diff --git a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs index 4ac36cc07e..690a50bb11 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs @@ -45,6 +45,14 @@ namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons Triangles.Alpha = 0; BackgroundColour = DefaultBackgroundColour; + Content.EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Radius = 2, + Offset = new Vector2(0, 1), + Colour = Color4.Black.Opacity(0.5f) + }; + Add(bubble = new CircularContainer { Anchor = Anchor.CentreLeft, From 33adf569a4d825ac3ffd90d251785ada52ec4b5c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 30 Nov 2017 17:39:06 +0900 Subject: [PATCH 12/49] Don't select a new beatmap in load() --- osu.Game.Tests/Visual/TestCaseEditorCompose.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseEditorCompose.cs b/osu.Game.Tests/Visual/TestCaseEditorCompose.cs index 9f060a9ec4..d52f27f4ab 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorCompose.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorCompose.cs @@ -31,7 +31,6 @@ namespace osu.Game.Tests.Visual this.beatmaps = beatmaps; compose.Beatmap.BindTo(osuGame.Beatmap); - nextBeatmap(); } private void nextBeatmap() From efa39f38ca1fbd03ad880f010670111f6a7f52f2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 30 Nov 2017 18:48:00 +0900 Subject: [PATCH 13/49] CI fixes --- .../Edit/OsuHitObjectComposer.cs | 3 ++- .../TestCaseEditorComposeRadioButtons.cs | 1 - osu.Game/Rulesets/Edit/HitObjectComposer.cs | 5 +---- .../Screens/Edit/Screens/Compose/Compose.cs | 11 +++++++--- .../RadioButtons/DrawableRadioButton.cs | 20 +++++++++---------- .../RadioButtons/RadioButtonCollection.cs | 1 - 6 files changed, 21 insertions(+), 20 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 851e572163..8a919e0178 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -2,12 +2,13 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Osu.Objects; namespace osu.Game.Rulesets.Osu.Edit { - public class OsuHitObjectComposer : Rulesets.Edit.HitObjectComposer + public class OsuHitObjectComposer : HitObjectComposer { public OsuHitObjectComposer(Ruleset ruleset) : base(ruleset) diff --git a/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs b/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs index c259ca666e..8c2a07b536 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using osu.Framework.Graphics; -using osu.Framework.Graphics.UserInterface; using osu.Game.Screens.Edit.Screens.Compose.RadioButtons; namespace osu.Game.Tests.Visual diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index ed057dbb03..9297c82ba4 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -6,17 +6,14 @@ using System.Collections.Generic; using System.Linq; using OpenTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Logging; using osu.Framework.Timing; using osu.Game.Rulesets.Edit.Tools; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI; using osu.Game.Screens.Edit.Screens.Compose.RadioButtons; -using osu.Game.Screens.Play.ReplaySettings; namespace osu.Game.Rulesets.Edit { @@ -24,7 +21,7 @@ namespace osu.Game.Rulesets.Edit { private readonly Ruleset ruleset; - public HitObjectComposer(Ruleset ruleset) + protected HitObjectComposer(Ruleset ruleset) { this.ruleset = ruleset; diff --git a/osu.Game/Screens/Edit/Screens/Compose/Compose.cs b/osu.Game/Screens/Edit/Screens/Compose/Compose.cs index 5eeaf3205d..6bc7356f26 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Compose.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Compose.cs @@ -1,14 +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 OpenTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Logging; -using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Screens.Edit.Screens.Compose.Timeline; @@ -85,7 +83,14 @@ namespace osu.Game.Screens.Edit.Screens.Compose composerContainer.Clear(); var ruleset = newBeatmap.BeatmapInfo.Ruleset?.CreateInstance(); - var composer = ruleset?.CreateHitObjectComposer(); + if (ruleset == null) + { + Logger.Log("Beatmap doesn't have a ruleset assigned."); + // ExitRequested?.Invoke(); + return; + } + + var composer = ruleset.CreateHitObjectComposer(); if (composer == null) { Logger.Log($"Ruleset {ruleset.Description} doesn't support hitobject composition."); diff --git a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs index 690a50bb11..b3c9983db9 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs @@ -19,10 +19,10 @@ namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons { public class DrawableRadioButton : TriangleButton { - private static readonly Color4 DefaultBackgroundColour = OsuColour.FromHex("333"); - private static readonly Color4 DefaultBubbleColour = DefaultBackgroundColour.Darken(0.5f); - private static readonly Color4 SelectedBackgroundColour = OsuColour.FromHex("1188aa"); - private static readonly Color4 SelectedBubbleColour = SelectedBackgroundColour.Lighten(0.5f); + private static readonly Color4 default_background_colour = OsuColour.FromHex("333"); + private static readonly Color4 default_bubble_colour = default_background_colour.Darken(0.5f); + private static readonly Color4 selected_background_colour = OsuColour.FromHex("1188aa"); + private static readonly Color4 selected_bubble_colour = selected_background_colour.Lighten(0.5f); /// /// Invoked when this has been selected. @@ -43,7 +43,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons private void load() { Triangles.Alpha = 0; - BackgroundColour = DefaultBackgroundColour; + BackgroundColour = default_background_colour; Content.EdgeEffect = new EdgeEffectParameters { @@ -62,7 +62,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons Scale = new Vector2(0.5f), X = 10, Masking = true, - Colour = DefaultBubbleColour, + Colour = default_bubble_colour, Blending = BlendingMode.Additive, Child = new Box { RelativeSizeAxes = Axes.Both } }); @@ -76,8 +76,8 @@ namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons return; isSelected = false; - BackgroundColour = DefaultBackgroundColour; - bubble.Colour = DefaultBubbleColour; + BackgroundColour = default_background_colour; + bubble.Colour = default_bubble_colour; } public void Select() @@ -87,8 +87,8 @@ namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons isSelected = true; Selected?.Invoke(this); - BackgroundColour = SelectedBackgroundColour; - bubble.Colour = SelectedBubbleColour; + BackgroundColour = selected_background_colour; + bubble.Colour = selected_bubble_colour; } protected override bool OnClick(InputState state) diff --git a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs index 557e8e1ee8..8a3194b72e 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; -using System.Linq; using OpenTK; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; From 677f3653eb04ed29b7c99f7c21079691ccc6ce67 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 30 Nov 2017 19:19:34 +0900 Subject: [PATCH 14/49] Hide osu! playfield cursor --- .../Edit/OsuEditPlayfield.cs | 13 +++++++++++++ .../Edit/OsuEditRulesetContainer.cs | 19 +++++++++++++++++++ .../Edit/OsuHitObjectComposer.cs | 4 ++++ osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 8 +++++++- .../osu.Game.Rulesets.Osu.csproj | 2 ++ osu.Game/Rulesets/Edit/HitObjectComposer.cs | 5 ++++- 6 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Edit/OsuEditPlayfield.cs create mode 100644 osu.Game.Rulesets.Osu/Edit/OsuEditRulesetContainer.cs diff --git a/osu.Game.Rulesets.Osu/Edit/OsuEditPlayfield.cs b/osu.Game.Rulesets.Osu/Edit/OsuEditPlayfield.cs new file mode 100644 index 0000000000..d5fc1b606b --- /dev/null +++ b/osu.Game.Rulesets.Osu/Edit/OsuEditPlayfield.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics.Cursor; +using osu.Game.Rulesets.Osu.UI; + +namespace osu.Game.Rulesets.Osu.Edit +{ + public class OsuEditPlayfield : OsuPlayfield + { + protected override CursorContainer CreateCursor() => null; + } +} diff --git a/osu.Game.Rulesets.Osu/Edit/OsuEditRulesetContainer.cs b/osu.Game.Rulesets.Osu/Edit/OsuEditRulesetContainer.cs new file mode 100644 index 0000000000..1e9e4b4686 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Edit/OsuEditRulesetContainer.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Osu.UI; +using osu.Game.Rulesets.UI; + +namespace osu.Game.Rulesets.Osu.Edit +{ + public class OsuEditRulesetContainer : OsuRulesetContainer + { + public OsuEditRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) + : base(ruleset, beatmap, isForCurrentRuleset) + { + } + + protected override Playfield CreatePlayfield() => new OsuEditPlayfield(); + } +} diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 8a919e0178..ec3aa4661c 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -2,9 +2,11 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Osu.Edit { @@ -15,6 +17,8 @@ namespace osu.Game.Rulesets.Osu.Edit { } + protected override RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => new OsuEditRulesetContainer(ruleset, beatmap, true); + protected override IReadOnlyList CompositionTools => new ICompositionTool[] { new HitObjectCompositionTool(), diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 89f6a4e255..387a098a5a 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -13,6 +13,7 @@ using System.Linq; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.UI.Cursor; +using osu.Framework.Graphics.Cursor; namespace osu.Game.Rulesets.Osu.UI { @@ -65,7 +66,10 @@ namespace osu.Game.Rulesets.Osu.UI protected override void LoadComplete() { base.LoadComplete(); - AddInternal(new GameplayCursor()); + + var cursor = CreateCursor(); + if (cursor != null) + AddInternal(cursor); } public override void Add(DrawableHitObject h) @@ -102,5 +106,7 @@ namespace osu.Game.Rulesets.Osu.UI judgementLayer.Add(explosion); } + + protected virtual CursorContainer CreateCursor() => new GameplayCursor(); } } diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index c527265c40..bc343ece05 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -49,6 +49,8 @@ + + diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 9297c82ba4..1e47ea4e63 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Logging; using osu.Framework.Timing; +using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.UI; using osu.Game.Screens.Edit.Screens.Compose.RadioButtons; @@ -34,7 +35,7 @@ namespace osu.Game.Rulesets.Edit RulesetContainer rulesetContainer; try { - rulesetContainer = ruleset.CreateRulesetContainerWith(osuGame.Beatmap.Value, true); + rulesetContainer = CreateRulesetContainer(ruleset, osuGame.Beatmap.Value); } catch (Exception e) { @@ -99,6 +100,8 @@ namespace osu.Game.Rulesets.Edit { } + protected virtual RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => ruleset.CreateRulesetContainerWith(beatmap, true); + protected abstract IReadOnlyList CompositionTools { get; } } } From e9cbef88f17021032a5cce26d6a616b4648c5a6b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 30 Nov 2017 19:49:55 +0900 Subject: [PATCH 15/49] Improve selection/deselection behaviour of RadioButtonCollections --- .../TestCaseEditorComposeRadioButtons.cs | 10 ++- .../RadioButtons/DrawableRadioButton.cs | 72 ++++++++++--------- .../Compose/RadioButtons/RadioButton.cs | 31 ++++++-- .../RadioButtons/RadioButtonCollection.cs | 26 +++++-- 4 files changed, 93 insertions(+), 46 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs b/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs index 8c2a07b536..f8669cde4b 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs @@ -14,7 +14,8 @@ namespace osu.Game.Tests.Visual public TestCaseEditorComposeRadioButtons() { - Add(new RadioButtonCollection + RadioButtonCollection collection; + Add(collection = new RadioButtonCollection { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -28,6 +29,13 @@ namespace osu.Game.Tests.Visual new RadioButton("Item 5", () => { }) } }); + + for (int i = 0; i < collection.Items.Count; i++) + { + int l = i; + AddStep($"Select item {l + 1}", () => collection.Items[l].Select()); + AddStep($"Deselect item {l + 1}", () => collection.Items[l].Deselect()); + } } } } diff --git a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs index b3c9983db9..a6c0f48f1f 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs @@ -27,16 +27,34 @@ namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons /// /// Invoked when this has been selected. /// - public Action Selected; + public Action Selected; private Drawable bubble; + private readonly RadioButton button; + public DrawableRadioButton(RadioButton button) { + this.button = button; + Text = button.Text; Action = button.Action; RelativeSizeAxes = Axes.X; + + bubble = new CircularContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fit, + Scale = new Vector2(0.5f), + X = 10, + Masking = true, + Colour = default_bubble_colour, + Blending = BlendingMode.Additive, + Child = new Box { RelativeSizeAxes = Axes.Both } + }; } [BackgroundDependencyLoader] @@ -53,53 +71,41 @@ namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons Colour = Color4.Black.Opacity(0.5f) }; - Add(bubble = new CircularContainer + Add(bubble); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + button.Selected.ValueChanged += v => { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - RelativeSizeAxes = Axes.Both, - FillMode = FillMode.Fit, - Scale = new Vector2(0.5f), - X = 10, - Masking = true, - Colour = default_bubble_colour, - Blending = BlendingMode.Additive, - Child = new Box { RelativeSizeAxes = Axes.Both } - }); + updateSelectionState(); + if (v) + Selected?.Invoke(button); + }; + + updateSelectionState(); } - private bool isSelected; - - public void Deselect() + private void updateSelectionState() { - if (!isSelected) + if (!IsLoaded) return; - isSelected = false; - BackgroundColour = default_background_colour; - bubble.Colour = default_bubble_colour; - } - - public void Select() - { - if (isSelected) - return; - isSelected = true; - Selected?.Invoke(this); - - BackgroundColour = selected_background_colour; - bubble.Colour = selected_bubble_colour; + BackgroundColour = button.Selected ? selected_background_colour : default_background_colour; + bubble.Colour = button.Selected ? selected_bubble_colour : default_bubble_colour; } protected override bool OnClick(InputState state) { - if (isSelected) + if (button.Selected) return true; if (!Enabled) return true; - Select(); + button.Selected.Value = true; return base.OnClick(state); } diff --git a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButton.cs b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButton.cs index bec2d1903d..055362d9e1 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButton.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButton.cs @@ -2,11 +2,18 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using osu.Framework.Configuration; namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons { - public struct RadioButton + public class RadioButton { + /// + /// Whether this is selected. + /// + /// + public readonly BindableBool Selected; + /// /// The text that should be displayed in this button. /// @@ -17,16 +24,28 @@ namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons /// public Action Action; + public RadioButton(string text, Action action) + { + Text = text; + Action = action; + Selected = new BindableBool(); + } + public RadioButton(string text) + : this(text, null) { Text = text; Action = null; } - public RadioButton(string text, Action action) - { - Text = text; - Action = action; - } + /// + /// Selects this . + /// + public void Select() => Selected.Value = true; + + /// + /// Deselects this . + /// + public void Deselect() => Selected.Value = false; } } diff --git a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs index 8a3194b72e..ad24a1da52 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs @@ -11,10 +11,16 @@ namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons { public class RadioButtonCollection : CompositeDrawable { + private IReadOnlyList items; public IReadOnlyList Items { + get { return items; } set { + if (items == value) + return; + items = value; + buttonContainer.Clear(); value.ForEach(addButton); } @@ -35,13 +41,21 @@ namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons }; } - private void addButton(RadioButton button) => buttonContainer.Add(new DrawableRadioButton(button) { Selected = buttonSelected }); - - private DrawableRadioButton currentlySelected; - private void buttonSelected(DrawableRadioButton drawableButton) + private RadioButton currentlySelected; + private void addButton(RadioButton button) { - currentlySelected?.Deselect(); - currentlySelected = drawableButton; + button.Selected.ValueChanged += v => + { + if (v) + { + currentlySelected?.Deselect(); + currentlySelected = button; + } + else + currentlySelected = null; + }; + + buttonContainer.Add(new DrawableRadioButton(button)); } } } From 7e34b0f08dcc504b81833487530111117eada6c9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 30 Nov 2017 19:53:52 +0900 Subject: [PATCH 16/49] Remove SelectionTool, make Select the default tool --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 4 +++- osu.Game/Rulesets/Edit/Tools/SelectionTool.cs | 7 ------- 2 files changed, 3 insertions(+), 8 deletions(-) delete mode 100644 osu.Game/Rulesets/Edit/Tools/SelectionTool.cs diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 1e47ea4e63..b06af84ec8 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -89,11 +89,13 @@ namespace osu.Game.Rulesets.Edit rulesetContainer.Clock = new InterpolatingFramedClock((IAdjustableClock)osuGame.Beatmap.Value.Track ?? new StopwatchClock()); toolboxCollection.Items = - new[] { new RadioButton("Select", () => setCompositionTool(new SelectionTool())) } + new[] { new RadioButton("Select", () => setCompositionTool(null)) } .Concat( CompositionTools.Select(t => new RadioButton(t.Name, () => setCompositionTool(t))) ) .ToList(); + + toolboxCollection.Items[0].Select(); } private void setCompositionTool(ICompositionTool tool) diff --git a/osu.Game/Rulesets/Edit/Tools/SelectionTool.cs b/osu.Game/Rulesets/Edit/Tools/SelectionTool.cs deleted file mode 100644 index 9f3ef78a02..0000000000 --- a/osu.Game/Rulesets/Edit/Tools/SelectionTool.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace osu.Game.Rulesets.Edit.Tools -{ - public class SelectionTool : ICompositionTool - { - public string Name => "Select"; - } -} From 89772f4efd889836f60480ba3de93cd73598caf9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 30 Nov 2017 19:54:58 +0900 Subject: [PATCH 17/49] A few resharper fixes --- .../Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs | 3 +-- .../Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs | 2 +- osu.Game/osu.Game.csproj | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs index a6c0f48f1f..48cc7f3379 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs @@ -29,8 +29,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons /// public Action Selected; - private Drawable bubble; - + private readonly Drawable bubble; private readonly RadioButton button; public DrawableRadioButton(RadioButton button) diff --git a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs index ad24a1da52..08473eaeba 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons get { return items; } set { - if (items == value) + if (ReferenceEquals(items, value)) return; items = value; diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 886d3313c6..e1425ff8b8 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -564,7 +564,6 @@ - From e8cbde3ae18746e0b96f17e6ddea0114590085b0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 30 Nov 2017 21:56:12 +0900 Subject: [PATCH 18/49] Add overlay/underlay --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 14 ++++++++---- osu.Game/Rulesets/Edit/PlayfieldOverlay.cs | 24 +++++++++++++++++++++ osu.Game/Rulesets/Edit/PlayfieldUnderlay.cs | 21 ++++++++++++++++++ osu.Game/Rulesets/UI/RulesetContainer.cs | 10 ++++----- osu.Game/osu.Game.csproj | 2 ++ 5 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 osu.Game/Rulesets/Edit/PlayfieldOverlay.cs create mode 100644 osu.Game/Rulesets/Edit/PlayfieldUnderlay.cs diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index b06af84ec8..3aa633115b 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -22,6 +22,8 @@ namespace osu.Game.Rulesets.Edit { private readonly Ruleset ruleset; + protected ICompositionTool CurrentTool { get; private set; } + protected HitObjectComposer(Ruleset ruleset) { this.ruleset = ruleset; @@ -75,7 +77,9 @@ namespace osu.Game.Rulesets.Edit Alpha = 0, AlwaysPresent = true, }, - rulesetContainer + CreateUnderlay(rulesetContainer.Playfield), + rulesetContainer, + CreateOverlay(rulesetContainer.Playfield) } } }, @@ -98,12 +102,14 @@ namespace osu.Game.Rulesets.Edit toolboxCollection.Items[0].Select(); } - private void setCompositionTool(ICompositionTool tool) - { - } + private void setCompositionTool(ICompositionTool tool) => CurrentTool = tool; protected virtual RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => ruleset.CreateRulesetContainerWith(beatmap, true); + protected virtual PlayfieldUnderlay CreateUnderlay(Playfield playfield) => new PlayfieldUnderlay(playfield); + + protected virtual PlayfieldOverlay CreateOverlay(Playfield playfield) => new PlayfieldOverlay(playfield); + protected abstract IReadOnlyList CompositionTools { get; } } } diff --git a/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs b/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs new file mode 100644 index 0000000000..2138079784 --- /dev/null +++ b/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs @@ -0,0 +1,24 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.UI; + +namespace osu.Game.Rulesets.Edit +{ + public class PlayfieldOverlay : CompositeDrawable + { + + private Playfield playfield; + + public PlayfieldOverlay(Playfield playfield) + { + this.playfield = playfield; + + RelativeSizeAxes = Axes.Both; + + } + + } +} diff --git a/osu.Game/Rulesets/Edit/PlayfieldUnderlay.cs b/osu.Game/Rulesets/Edit/PlayfieldUnderlay.cs new file mode 100644 index 0000000000..7a18c59613 --- /dev/null +++ b/osu.Game/Rulesets/Edit/PlayfieldUnderlay.cs @@ -0,0 +1,21 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.UI; + +namespace osu.Game.Rulesets.Edit +{ + public class PlayfieldUnderlay : CompositeDrawable + { + private readonly Playfield playfield; + + public PlayfieldUnderlay(Playfield playfield) + { + this.playfield = playfield; + + RelativeSizeAxes = Axes.Both; + } + } +} diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index ec26f6f310..69bf6bba29 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -55,6 +55,11 @@ namespace osu.Game.Rulesets.UI public abstract IEnumerable Objects { get; } + /// + /// The playfield. + /// + public Playfield Playfield { get; protected set; } + protected readonly Ruleset Ruleset; /// @@ -135,11 +140,6 @@ namespace osu.Game.Rulesets.UI public override ScoreProcessor CreateScoreProcessor() => new ScoreProcessor(this); - /// - /// The playfield. - /// - public Playfield Playfield { get; private set; } - protected override Container Content => content; private Container content; diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index e1425ff8b8..ad1370890f 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -302,6 +302,8 @@ + + From c0c051aa32166fc378e7d13051ecfd932cc04cc7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 30 Nov 2017 21:58:41 +0900 Subject: [PATCH 19/49] Remove unused parameter for now --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 4 ++-- osu.Game/Rulesets/Edit/PlayfieldOverlay.cs | 9 ++------- osu.Game/Rulesets/Edit/PlayfieldUnderlay.cs | 7 +------ 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 3aa633115b..f55b7b0531 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -106,9 +106,9 @@ namespace osu.Game.Rulesets.Edit protected virtual RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => ruleset.CreateRulesetContainerWith(beatmap, true); - protected virtual PlayfieldUnderlay CreateUnderlay(Playfield playfield) => new PlayfieldUnderlay(playfield); + protected virtual PlayfieldUnderlay CreateUnderlay(Playfield playfield) => new PlayfieldUnderlay(); - protected virtual PlayfieldOverlay CreateOverlay(Playfield playfield) => new PlayfieldOverlay(playfield); + protected virtual PlayfieldOverlay CreateOverlay(Playfield playfield) => new PlayfieldOverlay(); protected abstract IReadOnlyList CompositionTools { get; } } diff --git a/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs b/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs index 2138079784..4f5658e39c 100644 --- a/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs +++ b/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs @@ -3,22 +3,17 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Edit { public class PlayfieldOverlay : CompositeDrawable { - - private Playfield playfield; - - public PlayfieldOverlay(Playfield playfield) + public PlayfieldOverlay() { - this.playfield = playfield; - RelativeSizeAxes = Axes.Both; } + } } diff --git a/osu.Game/Rulesets/Edit/PlayfieldUnderlay.cs b/osu.Game/Rulesets/Edit/PlayfieldUnderlay.cs index 7a18c59613..e9198c71c6 100644 --- a/osu.Game/Rulesets/Edit/PlayfieldUnderlay.cs +++ b/osu.Game/Rulesets/Edit/PlayfieldUnderlay.cs @@ -3,18 +3,13 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Edit { public class PlayfieldUnderlay : CompositeDrawable { - private readonly Playfield playfield; - - public PlayfieldUnderlay(Playfield playfield) + public PlayfieldUnderlay() { - this.playfield = playfield; - RelativeSizeAxes = Axes.Both; } } From 52ba68e25dd1fb873608d548507b7f4cd7945445 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 30 Nov 2017 22:21:02 +0900 Subject: [PATCH 20/49] Add/fix up license headers --- osu.Game/Rulesets/Edit/PlayfieldOverlay.cs | 2 +- osu.Game/Rulesets/Edit/PlayfieldUnderlay.cs | 2 +- osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs b/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs index 4f5658e39c..58b15e3de2 100644 --- a/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs +++ b/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs @@ -1,5 +1,5 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Rulesets/Edit/PlayfieldUnderlay.cs b/osu.Game/Rulesets/Edit/PlayfieldUnderlay.cs index e9198c71c6..bace5258f8 100644 --- a/osu.Game/Rulesets/Edit/PlayfieldUnderlay.cs +++ b/osu.Game/Rulesets/Edit/PlayfieldUnderlay.cs @@ -1,5 +1,5 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs b/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs index 914cbd11ca..dd182dcbdb 100644 --- a/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs +++ b/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Edit.Tools From 76a1c7db3b68318229daca40cd06385088e6ca62 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 28 Nov 2017 21:22:57 +0900 Subject: [PATCH 21/49] Hyperdash preparation --- .../Beatmaps/CatchBeatmapProcessor.cs | 8 +++++ .../Tests/TestCaseFruit.cs | 36 +++++++++++++++++++ .../Tests/TestCaseHyperdash.cs | 26 ++++++++++++++ .../osu.Game.Rulesets.Catch.csproj | 2 ++ 4 files changed, 72 insertions(+) create mode 100644 osu.Game.Rulesets.Catch/Tests/TestCaseFruit.cs create mode 100644 osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index b2f7fdabfc..8a19afcd39 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.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.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; @@ -18,6 +19,8 @@ namespace osu.Game.Rulesets.Catch.Beatmaps CatchHitObject lastObj = null; + convertHyperDash(beatmap.HitObjects); + foreach (var obj in beatmap.HitObjects) { if (obj.NewCombo) @@ -34,5 +37,10 @@ namespace osu.Game.Rulesets.Catch.Beatmaps lastObj = obj; } } + + private void convertHyperDash(List objects) + { + + } } } diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseFruit.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseFruit.cs new file mode 100644 index 0000000000..0ced95edf9 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Tests/TestCaseFruit.cs @@ -0,0 +1,36 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.Objects.Drawable; +using osu.Game.Tests.Visual; +using OpenTK; + +namespace osu.Game.Rulesets.Catch.Tests +{ + public class TestCaseFruit : OsuTestCase + { + public TestCaseFruit() + { + Add(new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] + { + new DrawableFruit(new Fruit()) { Position = new Vector2(0.5f) }, + new DrawableFruit(new Fruit()) { Position = new Vector2(0.5f) }, + }, + new Drawable[] + { + new DrawableFruit(new Fruit()) { Position = new Vector2(0.5f) }, + new DrawableFruit(new Fruit()) { Position = new Vector2(0.5f) }, + } + } + }); + } + } +} diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs new file mode 100644 index 0000000000..822743debc --- /dev/null +++ b/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs @@ -0,0 +1,26 @@ +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Catch.Objects; + +namespace osu.Game.Rulesets.Catch.Tests +{ + [TestFixture] + [Ignore("getting CI working")] + public class TestCaseHyperdash : Game.Tests.Visual.TestCasePlayer + { + public TestCaseHyperdash() + : base(typeof(CatchRuleset)) + { + } + + protected override Beatmap CreateBeatmap() + { + var beatmap = new Beatmap(); + + for (int i = 0; i < 512; i++) + beatmap.HitObjects.Add(new Fruit { X = 0.5f + (i % 2 == 0 ? -0.4f : 0.4f), StartTime = i * 100, NewCombo = i % 8 == 0 }); + + return beatmap; + } + } +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index b7916f674e..4e819fb58b 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -67,6 +67,8 @@ + + From 881745d7561bb25a67c03978a33ee214b09fbc20 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Dec 2017 15:08:12 +0900 Subject: [PATCH 22/49] Initial implementation of hyperdash calculation --- .../Beatmaps/CatchBeatmapProcessor.cs | 43 +++++++++++++++ .../Objects/CatchHitObject.cs | 2 + .../Objects/Drawable/DrawableFruit.cs | 15 ++++++ .../Tests/TestCaseHyperdash.cs | 52 +++++++++---------- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 2 +- 5 files changed, 87 insertions(+), 27 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 8a19afcd39..d225cdca55 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -1,9 +1,13 @@ // 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.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.Objects.Types; +using OpenTK; namespace osu.Game.Rulesets.Catch.Beatmaps { @@ -40,7 +44,46 @@ namespace osu.Game.Rulesets.Catch.Beatmaps private void convertHyperDash(List objects) { + // todo: add difficulty adjust. + const double catcher_width = CatcherArea.CATCHER_SIZE / CatchPlayfield.BASE_WIDTH; + const double catcher_width_half = catcher_width / 2; + int lastDirection = 0; + double lastExcess = catcher_width_half; + + int objCount = objects.Count; + + for (int i = 0; i < objCount - 1; i++) + { + CatchHitObject currentObject = objects[i]; + + // not needed? + if (currentObject is TinyDroplet) continue; + + CatchHitObject nextObject = objects[i + 1]; + while (nextObject is TinyDroplet) + { + if (++i == objCount - 1) break; + nextObject = objects[i + 1]; + } + + int thisDirection = nextObject.X > currentObject.X ? 1 : -1; + double timeToNext = nextObject.StartTime - ((currentObject as IHasEndTime)?.EndTime ?? currentObject.StartTime) - 4; + double distanceToNext = Math.Abs(nextObject.X - currentObject.X) - (lastDirection == thisDirection ? lastExcess : catcher_width_half); + + if (timeToNext * CatcherArea.Catcher.BASE_SPEED < distanceToNext) + { + currentObject.HyperDash = true; + lastExcess = catcher_width_half; + } + else + { + //currentObject.DistanceToHyperDash = timeToNext - distanceToNext; + lastExcess = MathHelper.Clamp(timeToNext - distanceToNext, 0, catcher_width_half); + } + + lastDirection = thisDirection; + } } } } diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs index cb4e6453ce..bae2edd055 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs @@ -27,6 +27,8 @@ namespace osu.Game.Rulesets.Catch.Objects public float Scale { get; set; } = 1; + public bool HyperDash { get; set; } + public override void ApplyDefaults(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { base.ApplyDefaults(controlPointInfo, difficulty); diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 4c28a9d021..9f46bbd3a4 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.MathUtils; using osu.Game.Rulesets.Catch.Objects.Drawable.Pieces; using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects.Drawable { @@ -70,6 +71,20 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable } } }; + + if (HitObject.HyperDash) + { + Add(new Pulp + { + RelativePositionAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AccentColour = Color4.Red, + Blending = BlendingMode.Additive, + Alpha = 0.5f, + Scale = new Vector2(2) + }); + } } } } diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs index 822743debc..5b0e1fb93c 100644 --- a/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs +++ b/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs @@ -1,26 +1,26 @@ -using NUnit.Framework; -using osu.Game.Beatmaps; -using osu.Game.Rulesets.Catch.Objects; - -namespace osu.Game.Rulesets.Catch.Tests -{ - [TestFixture] - [Ignore("getting CI working")] - public class TestCaseHyperdash : Game.Tests.Visual.TestCasePlayer - { - public TestCaseHyperdash() - : base(typeof(CatchRuleset)) - { - } - - protected override Beatmap CreateBeatmap() - { - var beatmap = new Beatmap(); - - for (int i = 0; i < 512; i++) - beatmap.HitObjects.Add(new Fruit { X = 0.5f + (i % 2 == 0 ? -0.4f : 0.4f), StartTime = i * 100, NewCombo = i % 8 == 0 }); - - return beatmap; - } - } -} \ No newline at end of file +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Catch.Objects; + +namespace osu.Game.Rulesets.Catch.Tests +{ + [TestFixture] + [Ignore("getting CI working")] + public class TestCaseHyperdash : Game.Tests.Visual.TestCasePlayer + { + public TestCaseHyperdash() + : base(typeof(CatchRuleset)) + { + } + + protected override Beatmap CreateBeatmap() + { + var beatmap = new Beatmap(); + + for (int i = 0; i < 512; i++) + beatmap.HitObjects.Add(new Fruit { X = 0.5f + (i % 8 < 4 ? -0.4f : 0.4f), StartTime = i * 100, NewCombo = i % 8 == 0 }); + + return beatmap; + } + } +} diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 6fd0793500..3cfdcafc48 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Catch.UI { public class CatchPlayfield : ScrollingPlayfield { - public static readonly float BASE_WIDTH = 512; + public const float BASE_WIDTH = 512; protected override Container Content => content; private readonly Container content; From 51cae24a26933ce468b858ae91dd13382039b837 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Dec 2017 19:24:48 +0900 Subject: [PATCH 23/49] Add basic hyperdash movement Doesn't restrict direction yet. Also improves readability of fruit catch detection. --- .../Beatmaps/CatchBeatmapProcessor.cs | 2 +- .../Objects/CatchHitObject.cs | 10 +- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 104 ++++++++++++++++-- 4 files changed, 108 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index d225cdca55..e12d7f3fd3 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -73,7 +73,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps if (timeToNext * CatcherArea.Catcher.BASE_SPEED < distanceToNext) { - currentObject.HyperDash = true; + currentObject.HyperDashTarget = nextObject; lastExcess = catcher_width_half; } else diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs index bae2edd055..38757d4928 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs @@ -27,7 +27,15 @@ namespace osu.Game.Rulesets.Catch.Objects public float Scale { get; set; } = 1; - public bool HyperDash { get; set; } + /// + /// Whether this fruit can initiate a hyperdash. + /// + public bool HyperDash => HyperDashTarget != null; + + /// + /// The target fruit if we are to initiate a hyperdash. + /// + public CatchHitObject HyperDashTarget; public override void ApplyDefaults(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 3cfdcafc48..76dbfa77c6 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Catch.UI }; } - public bool CheckIfWeCanCatch(CatchHitObject obj) => catcherArea.CanCatch(obj); + public bool CheckIfWeCanCatch(CatchHitObject obj) => catcherArea.AttemptCatch(obj); public override void Add(DrawableHitObject h) { diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 203db1bb8c..2785647cbd 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -14,6 +14,7 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Objects.Drawables; using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Rulesets.Catch.UI { @@ -51,7 +52,7 @@ namespace osu.Game.Rulesets.Catch.UI catcher.Add(fruit); } - public bool CanCatch(CatchHitObject obj) => Math.Abs(catcher.Position.X - obj.X) < catcher.DrawSize.X * Math.Abs(catcher.Scale.X) / DrawSize.X / 2; + public bool AttemptCatch(CatchHitObject obj) => catcher.AttemptCatch(obj); public class Catcher : Container, IKeyBindingHandler { @@ -105,14 +106,35 @@ namespace osu.Game.Rulesets.Catch.UI dashing = value; - if (dashing) - Schedule(addAdditiveSprite); + Trail |= dashing; } } - private void addAdditiveSprite() + private bool trail; + + /// + /// Activate or deactive the trail. Will be automatically deactivated when conditions to keep the trail displayed are no longer met. + /// + protected bool Trail { - if (!dashing || AdditiveTarget == null) return; + get { return trail; } + set + { + if (value == trail) return; + + trail = value; + + if (Trail) + beginTrail(); + } + } + + private void beginTrail() + { + Trail &= dashing || HyperDashing; + Trail &= AdditiveTarget != null; + + if (!Trail) return; var additive = createCatcherSprite(); @@ -120,6 +142,7 @@ namespace osu.Game.Rulesets.Catch.UI additive.OriginPosition = additive.OriginPosition + new Vector2(DrawWidth / 2, 0); // also temporary to align sprite correctly. additive.Position = Position; additive.Scale = Scale; + additive.Colour = HyperDashing ? Color4.Red : Color4.White; additive.RelativePositionAxes = RelativePositionAxes; additive.Blending = BlendingMode.Additive; @@ -127,7 +150,7 @@ namespace osu.Game.Rulesets.Catch.UI additive.FadeTo(0.4f).FadeOut(800, Easing.OutQuint).Expire(); - Scheduler.AddDelayed(addAdditiveSprite, 50); + Scheduler.AddDelayed(beginTrail, HyperDashing ? 25 : 50); } private Sprite createCatcherSprite() => new Sprite @@ -138,6 +161,10 @@ namespace osu.Game.Rulesets.Catch.UI OriginPosition = new Vector2(-3, 10) // temporary until the sprite is aligned correctly. }; + /// + /// Add a caught fruit to the catcher's stack. + /// + /// The fruit that was caught. public void Add(DrawableHitObject fruit) { float distance = fruit.DrawSize.X / 2 * fruit.Scale.X; @@ -150,8 +177,35 @@ namespace osu.Game.Rulesets.Catch.UI caughtFruit.Add(fruit); - if (((CatchHitObject)fruit.HitObject).LastInCombo) + var catchObject = (CatchHitObject)fruit.HitObject; + + if (catchObject.LastInCombo) explode(); + + updateHyperDashState(catchObject, true); + } + + /// + /// Let the catcher attempt to catch a fruit. + /// + /// The fruit to catch. + /// Whether the catch is possible. + public bool AttemptCatch(CatchHitObject fruit) + { + const double relative_catcher_width = CATCHER_SIZE / 2; + + // this stuff wil disappear once we move fruit to non-relative coordinate space in the future. + var catchObjectPosition = fruit.X * CatchPlayfield.BASE_WIDTH; + var catcherPosition = Position.X * CatchPlayfield.BASE_WIDTH; + + var validCatch = + catchObjectPosition >= catcherPosition - relative_catcher_width / 2 && + catchObjectPosition <= catcherPosition + relative_catcher_width / 2; + + // if we are hypderdashing in teh next hit is not, let's change our state here (it's our only opportunity to handle missed fruit currently). + updateHyperDashState(fruit, false); + + return validCatch; } public bool OnPressed(CatchAction action) @@ -203,10 +257,46 @@ namespace osu.Game.Rulesets.Catch.UI double dashModifier = Dashing ? 1 : 0.5; + if (hyperDashModifier != 1) + dashModifier = hyperDashModifier; + Scale = new Vector2(Math.Abs(Scale.X) * Math.Sign(currentDirection), Scale.Y); X = (float)MathHelper.Clamp(X + Math.Sign(currentDirection) * Clock.ElapsedFrameTime * BASE_SPEED * dashModifier, 0, 1); } + /// + /// Whether we are hypderdashing or not. + /// + protected bool HyperDashing => hyperDashModifier != 1; + + private double hyperDashModifier = 1; + + /// + /// Update whether we are hyper or not. + /// + /// The fruit to use as a condition for deciding our new state. + /// Whether to allow entering hyperdash or not. If false, we will only exit if required, but never enter. + private void updateHyperDashState(CatchHitObject fruit, bool allowBegin) + { + const float transition_length = 180; + + if (!fruit.HyperDash) + { + hyperDashModifier = 1; + this.FadeColour(Color4.White, transition_length, Easing.OutQuint); + this.FadeTo(1, transition_length, Easing.OutQuint); + return; + } + + if (allowBegin) + { + hyperDashModifier = Math.Abs(fruit.HyperDashTarget.X - fruit.X) / Math.Abs(fruit.HyperDashTarget.StartTime - fruit.StartTime) / BASE_SPEED; + this.FadeColour(Color4.AliceBlue, transition_length, Easing.OutQuint); + this.FadeTo(0.5f, transition_length, Easing.OutQuint); + Trail = true; + } + } + private void explode() { var fruit = caughtFruit.ToArray(); From 07081f400cfcc68846d64f268880d5994b1763cb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Dec 2017 19:33:20 +0900 Subject: [PATCH 24/49] Make hyperdash testcase easier to win --- osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs index 5b0e1fb93c..a39c727a61 100644 --- a/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs +++ b/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Catch.Tests var beatmap = new Beatmap(); for (int i = 0; i < 512; i++) - beatmap.HitObjects.Add(new Fruit { X = 0.5f + (i % 8 < 4 ? -0.4f : 0.4f), StartTime = i * 100, NewCombo = i % 8 == 0 }); + beatmap.HitObjects.Add(new Fruit { X = i % 8 < 4 ? 0.02f : 0.98f, StartTime = i * 100, NewCombo = i % 8 == 0 }); return beatmap; } From 445bb70ef5b2d70a9c1552d72d4b5439209a3d4d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Dec 2017 19:58:00 +0900 Subject: [PATCH 25/49] Add hyperdash visual testing to TestCaseCatcherArea Also tidies up hyperdash state logic --- .../Tests/TestCaseCatcherArea.cs | 14 +++- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 84 +++++++++---------- 2 files changed, 54 insertions(+), 44 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseCatcherArea.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseCatcherArea.cs index 538f6930ed..daa3e12800 100644 --- a/osu.Game.Rulesets.Catch/Tests/TestCaseCatcherArea.cs +++ b/osu.Game.Rulesets.Catch/Tests/TestCaseCatcherArea.cs @@ -17,6 +17,7 @@ namespace osu.Game.Rulesets.Catch.Tests internal class TestCaseCatcherArea : OsuTestCase { private RulesetInfo catchRuleset; + private TestCatcherArea catcherArea; public override IReadOnlyList RequiredTypes => new[] { @@ -26,6 +27,7 @@ namespace osu.Game.Rulesets.Catch.Tests public TestCaseCatcherArea() { AddSliderStep("CircleSize", 0, 8, 5, createCatcher); + AddToggleStep("Hyperdash", t => catcherArea.ToggleHyperDash(t)); } private void createCatcher(float size) @@ -33,7 +35,7 @@ namespace osu.Game.Rulesets.Catch.Tests Child = new CatchInputManager(catchRuleset) { RelativeSizeAxes = Axes.Both, - Child = new CatcherArea(new BeatmapDifficulty { CircleSize = size }) + Child = catcherArea = new TestCatcherArea(new BeatmapDifficulty { CircleSize = size }) { Anchor = Anchor.CentreLeft, Origin = Anchor.BottomLeft @@ -46,5 +48,15 @@ namespace osu.Game.Rulesets.Catch.Tests { catchRuleset = rulesets.GetRuleset(2); } + + private class TestCatcherArea : CatcherArea + { + public TestCatcherArea(BeatmapDifficulty beatmapDifficulty) + : base(beatmapDifficulty) + { + } + + public void ToggleHyperDash(bool status) => MovableCatcher.HyperDashModifier = status ? 2 : 1; + } } } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 2785647cbd..52f06d4396 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -22,18 +22,18 @@ namespace osu.Game.Rulesets.Catch.UI { public const float CATCHER_SIZE = 172; - private readonly Catcher catcher; + protected readonly Catcher MovableCatcher; public Container ExplodingFruitTarget { - set { catcher.ExplodingFruitTarget = value; } + set { MovableCatcher.ExplodingFruitTarget = value; } } public CatcherArea(BeatmapDifficulty difficulty = null) { RelativeSizeAxes = Axes.X; Height = CATCHER_SIZE; - Child = catcher = new Catcher(difficulty) + Child = MovableCatcher = new Catcher(difficulty) { AdditiveTarget = this, }; @@ -42,17 +42,17 @@ namespace osu.Game.Rulesets.Catch.UI public void Add(DrawableHitObject fruit, Vector2 absolutePosition) { fruit.RelativePositionAxes = Axes.None; - fruit.Position = new Vector2(catcher.ToLocalSpace(absolutePosition).X - catcher.DrawSize.X / 2, 0); + fruit.Position = new Vector2(MovableCatcher.ToLocalSpace(absolutePosition).X - MovableCatcher.DrawSize.X / 2, 0); fruit.Anchor = Anchor.TopCentre; fruit.Origin = Anchor.BottomCentre; fruit.Scale *= 0.7f; fruit.LifetimeEnd = double.MaxValue; - catcher.Add(fruit); + MovableCatcher.Add(fruit); } - public bool AttemptCatch(CatchHitObject obj) => catcher.AttemptCatch(obj); + public bool AttemptCatch(CatchHitObject obj) => MovableCatcher.AttemptCatch(obj); public class Catcher : Container, IKeyBindingHandler { @@ -181,8 +181,6 @@ namespace osu.Game.Rulesets.Catch.UI if (catchObject.LastInCombo) explode(); - - updateHyperDashState(catchObject, true); } /// @@ -202,12 +200,45 @@ namespace osu.Game.Rulesets.Catch.UI catchObjectPosition >= catcherPosition - relative_catcher_width / 2 && catchObjectPosition <= catcherPosition + relative_catcher_width / 2; - // if we are hypderdashing in teh next hit is not, let's change our state here (it's our only opportunity to handle missed fruit currently). - updateHyperDashState(fruit, false); + if (validCatch && fruit.HyperDash) + HyperDashModifier = Math.Abs(fruit.HyperDashTarget.X - fruit.X) / Math.Abs(fruit.HyperDashTarget.StartTime - fruit.StartTime) / BASE_SPEED; + else + HyperDashModifier = 1; return validCatch; } + /// + /// Whether we are hypderdashing or not. + /// + public bool HyperDashing => hyperDashModifier != 1; + + private double hyperDashModifier = 1; + + public double HyperDashModifier + { + get { return hyperDashModifier; } + set + { + if (value == hyperDashModifier) return; + hyperDashModifier = value; + + const float transition_length = 180; + + if (HyperDashing) + { + this.FadeColour(Color4.Yellow, transition_length, Easing.OutQuint); + this.FadeTo(0.2f, transition_length, Easing.OutQuint); + Trail = true; + } + else + { + this.FadeColour(Color4.White, transition_length, Easing.OutQuint); + this.FadeTo(1, transition_length, Easing.OutQuint); + } + } + } + public bool OnPressed(CatchAction action) { switch (action) @@ -264,39 +295,6 @@ namespace osu.Game.Rulesets.Catch.UI X = (float)MathHelper.Clamp(X + Math.Sign(currentDirection) * Clock.ElapsedFrameTime * BASE_SPEED * dashModifier, 0, 1); } - /// - /// Whether we are hypderdashing or not. - /// - protected bool HyperDashing => hyperDashModifier != 1; - - private double hyperDashModifier = 1; - - /// - /// Update whether we are hyper or not. - /// - /// The fruit to use as a condition for deciding our new state. - /// Whether to allow entering hyperdash or not. If false, we will only exit if required, but never enter. - private void updateHyperDashState(CatchHitObject fruit, bool allowBegin) - { - const float transition_length = 180; - - if (!fruit.HyperDash) - { - hyperDashModifier = 1; - this.FadeColour(Color4.White, transition_length, Easing.OutQuint); - this.FadeTo(1, transition_length, Easing.OutQuint); - return; - } - - if (allowBegin) - { - hyperDashModifier = Math.Abs(fruit.HyperDashTarget.X - fruit.X) / Math.Abs(fruit.HyperDashTarget.StartTime - fruit.StartTime) / BASE_SPEED; - this.FadeColour(Color4.AliceBlue, transition_length, Easing.OutQuint); - this.FadeTo(0.5f, transition_length, Easing.OutQuint); - Trail = true; - } - } - private void explode() { var fruit = caughtFruit.ToArray(); From 25207c51b5ed04bf50c38f94527d4448d41506aa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Dec 2017 20:07:28 +0900 Subject: [PATCH 26/49] Add directionality --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 52f06d4396..265f19c744 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -201,7 +201,10 @@ namespace osu.Game.Rulesets.Catch.UI catchObjectPosition <= catcherPosition + relative_catcher_width / 2; if (validCatch && fruit.HyperDash) + { HyperDashModifier = Math.Abs(fruit.HyperDashTarget.X - fruit.X) / Math.Abs(fruit.HyperDashTarget.StartTime - fruit.StartTime) / BASE_SPEED; + HyperDashDirection = fruit.HyperDashTarget.X - fruit.X; + } else HyperDashModifier = 1; @@ -215,6 +218,8 @@ namespace osu.Game.Rulesets.Catch.UI private double hyperDashModifier = 1; + public double HyperDashDirection; + public double HyperDashModifier { get { return hyperDashModifier; } @@ -233,6 +238,7 @@ namespace osu.Game.Rulesets.Catch.UI } else { + HyperDashDirection = 0; this.FadeColour(Color4.White, transition_length, Easing.OutQuint); this.FadeTo(1, transition_length, Easing.OutQuint); } @@ -286,13 +292,15 @@ namespace osu.Game.Rulesets.Catch.UI if (currentDirection == 0) return; + var direction = Math.Sign(currentDirection); + double dashModifier = Dashing ? 1 : 0.5; - if (hyperDashModifier != 1) + if (hyperDashModifier != 1 && (HyperDashDirection == 0 || direction == Math.Sign(HyperDashDirection))) dashModifier = hyperDashModifier; - Scale = new Vector2(Math.Abs(Scale.X) * Math.Sign(currentDirection), Scale.Y); - X = (float)MathHelper.Clamp(X + Math.Sign(currentDirection) * Clock.ElapsedFrameTime * BASE_SPEED * dashModifier, 0, 1); + Scale = new Vector2(Math.Abs(Scale.X) * direction, Scale.Y); + X = (float)MathHelper.Clamp(X + direction * Clock.ElapsedFrameTime * BASE_SPEED * dashModifier, 0, 1); } private void explode() From 273793f1852d5ee0792c39bcbb1414f5806c428e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Dec 2017 20:08:49 +0900 Subject: [PATCH 27/49] Add comments --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 265f19c744..984aaf98ee 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -218,8 +218,14 @@ namespace osu.Game.Rulesets.Catch.UI private double hyperDashModifier = 1; + /// + /// The direction in which hyperdash is allowed. 0 allows both directions. + /// public double HyperDashDirection; + /// + /// The speed modifier resultant from hyperdash. Will trigger hyperdash when not equal to 1. + /// public double HyperDashModifier { get { return hyperDashModifier; } From bf606522c1c3cd33ec90d70d1290fbfd5114d3aa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Dec 2017 20:13:32 +0900 Subject: [PATCH 28/49] Make hyperdash testcase easier to win again --- osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs index a39c727a61..a0eb5f0054 100644 --- a/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs +++ b/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs @@ -18,7 +18,8 @@ namespace osu.Game.Rulesets.Catch.Tests var beatmap = new Beatmap(); for (int i = 0; i < 512; i++) - beatmap.HitObjects.Add(new Fruit { X = i % 8 < 4 ? 0.02f : 0.98f, StartTime = i * 100, NewCombo = i % 8 == 0 }); + if (i % 5 < 3) + beatmap.HitObjects.Add(new Fruit { X = i % 10 < 5 ? 0.02f : 0.98f, StartTime = i * 100, NewCombo = i % 8 == 0 }); return beatmap; } From e75d73ac1cb8b86ee16d679a59b80e8b98999a2d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Dec 2017 20:13:46 +0900 Subject: [PATCH 29/49] Change hyperdash colour again --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 984aaf98ee..2bb0f3cd18 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -238,7 +238,7 @@ namespace osu.Game.Rulesets.Catch.UI if (HyperDashing) { - this.FadeColour(Color4.Yellow, transition_length, Easing.OutQuint); + this.FadeColour(Color4.OrangeRed, transition_length, Easing.OutQuint); this.FadeTo(0.2f, transition_length, Easing.OutQuint); Trail = true; } From 79e1bf3394f696df2c88742bb0943d3b01051125 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Dec 2017 20:14:42 +0900 Subject: [PATCH 30/49] Remove unused testcase --- .../Tests/TestCaseFruit.cs | 36 ------------------- .../osu.Game.Rulesets.Catch.csproj | 1 - 2 files changed, 37 deletions(-) delete mode 100644 osu.Game.Rulesets.Catch/Tests/TestCaseFruit.cs diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseFruit.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseFruit.cs deleted file mode 100644 index 0ced95edf9..0000000000 --- a/osu.Game.Rulesets.Catch/Tests/TestCaseFruit.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE - -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Catch.Objects; -using osu.Game.Rulesets.Catch.Objects.Drawable; -using osu.Game.Tests.Visual; -using OpenTK; - -namespace osu.Game.Rulesets.Catch.Tests -{ - public class TestCaseFruit : OsuTestCase - { - public TestCaseFruit() - { - Add(new GridContainer - { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] - { - new DrawableFruit(new Fruit()) { Position = new Vector2(0.5f) }, - new DrawableFruit(new Fruit()) { Position = new Vector2(0.5f) }, - }, - new Drawable[] - { - new DrawableFruit(new Fruit()) { Position = new Vector2(0.5f) }, - new DrawableFruit(new Fruit()) { Position = new Vector2(0.5f) }, - } - } - }); - } - } -} diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index 4e819fb58b..264f5c41be 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -67,7 +67,6 @@ - From 997cdfaee42ebb67e15bc0bcbe1162c89b0bbe6c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Dec 2017 20:31:54 +0900 Subject: [PATCH 31/49] Add missing licence header --- osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs index a0eb5f0054..ce3f79bae2 100644 --- a/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs +++ b/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs @@ -1,4 +1,7 @@ -using NUnit.Framework; +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; From 8c3ae9430b53273b95f258279560b6396d9a7b41 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Dec 2017 20:39:58 +0900 Subject: [PATCH 32/49] Add difficulty scaling considerations to hyperdash initialisation --- .../Beatmaps/CatchBeatmapProcessor.cs | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index e12d7f3fd3..9901dbde18 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; @@ -23,7 +24,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps CatchHitObject lastObj = null; - convertHyperDash(beatmap.HitObjects); + initialiseHyperDash(beatmap.HitObjects); foreach (var obj in beatmap.HitObjects) { @@ -42,14 +43,13 @@ namespace osu.Game.Rulesets.Catch.Beatmaps } } - private void convertHyperDash(List objects) + private void initialiseHyperDash(List objects) { // todo: add difficulty adjust. - const double catcher_width = CatcherArea.CATCHER_SIZE / CatchPlayfield.BASE_WIDTH; - const double catcher_width_half = catcher_width / 2; + double halfCatcherWidth = CatcherArea.CATCHER_SIZE * (objects.FirstOrDefault()?.Scale ?? 1) / CatchPlayfield.BASE_WIDTH / 2; int lastDirection = 0; - double lastExcess = catcher_width_half; + double lastExcess = halfCatcherWidth; int objCount = objects.Count; @@ -58,28 +58,29 @@ namespace osu.Game.Rulesets.Catch.Beatmaps CatchHitObject currentObject = objects[i]; // not needed? - if (currentObject is TinyDroplet) continue; + // if (currentObject is TinyDroplet) continue; CatchHitObject nextObject = objects[i + 1]; - while (nextObject is TinyDroplet) - { - if (++i == objCount - 1) break; - nextObject = objects[i + 1]; - } + + // while (nextObject is TinyDroplet) + // { + // if (++i == objCount - 1) break; + // nextObject = objects[i + 1]; + // } int thisDirection = nextObject.X > currentObject.X ? 1 : -1; double timeToNext = nextObject.StartTime - ((currentObject as IHasEndTime)?.EndTime ?? currentObject.StartTime) - 4; - double distanceToNext = Math.Abs(nextObject.X - currentObject.X) - (lastDirection == thisDirection ? lastExcess : catcher_width_half); + double distanceToNext = Math.Abs(nextObject.X - currentObject.X) - (lastDirection == thisDirection ? lastExcess : halfCatcherWidth); if (timeToNext * CatcherArea.Catcher.BASE_SPEED < distanceToNext) { currentObject.HyperDashTarget = nextObject; - lastExcess = catcher_width_half; + lastExcess = halfCatcherWidth; } else { //currentObject.DistanceToHyperDash = timeToNext - distanceToNext; - lastExcess = MathHelper.Clamp(timeToNext - distanceToNext, 0, catcher_width_half); + lastExcess = MathHelper.Clamp(timeToNext - distanceToNext, 0, halfCatcherWidth); } lastDirection = thisDirection; From 5a7c4772bd57453466f9cc2f3599f54b7882ce22 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 2 Dec 2017 19:53:11 +0900 Subject: [PATCH 33/49] Remove PlayfieldUnderlay for now --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 3 --- osu.Game/Rulesets/Edit/PlayfieldUnderlay.cs | 16 ---------------- osu.Game/osu.Game.csproj | 1 - 3 files changed, 20 deletions(-) delete mode 100644 osu.Game/Rulesets/Edit/PlayfieldUnderlay.cs diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index f55b7b0531..767e8ade46 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -77,7 +77,6 @@ namespace osu.Game.Rulesets.Edit Alpha = 0, AlwaysPresent = true, }, - CreateUnderlay(rulesetContainer.Playfield), rulesetContainer, CreateOverlay(rulesetContainer.Playfield) } @@ -106,8 +105,6 @@ namespace osu.Game.Rulesets.Edit protected virtual RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => ruleset.CreateRulesetContainerWith(beatmap, true); - protected virtual PlayfieldUnderlay CreateUnderlay(Playfield playfield) => new PlayfieldUnderlay(); - protected virtual PlayfieldOverlay CreateOverlay(Playfield playfield) => new PlayfieldOverlay(); protected abstract IReadOnlyList CompositionTools { get; } diff --git a/osu.Game/Rulesets/Edit/PlayfieldUnderlay.cs b/osu.Game/Rulesets/Edit/PlayfieldUnderlay.cs deleted file mode 100644 index bace5258f8..0000000000 --- a/osu.Game/Rulesets/Edit/PlayfieldUnderlay.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; - -namespace osu.Game.Rulesets.Edit -{ - public class PlayfieldUnderlay : CompositeDrawable - { - public PlayfieldUnderlay() - { - RelativeSizeAxes = Axes.Both; - } - } -} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index ad1370890f..ee5834890f 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -303,7 +303,6 @@ - From a80059032cdc94a37a83b78fd86b4466be095c61 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 2 Dec 2017 20:24:10 +0900 Subject: [PATCH 34/49] Remove PlayfieldOverlay --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 5 +---- osu.Game/Rulesets/Edit/PlayfieldOverlay.cs | 19 ------------------- osu.Game/osu.Game.csproj | 1 - 3 files changed, 1 insertion(+), 24 deletions(-) delete mode 100644 osu.Game/Rulesets/Edit/PlayfieldOverlay.cs diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 767e8ade46..3184b84e98 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -77,8 +77,7 @@ namespace osu.Game.Rulesets.Edit Alpha = 0, AlwaysPresent = true, }, - rulesetContainer, - CreateOverlay(rulesetContainer.Playfield) + rulesetContainer } } }, @@ -105,8 +104,6 @@ namespace osu.Game.Rulesets.Edit protected virtual RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => ruleset.CreateRulesetContainerWith(beatmap, true); - protected virtual PlayfieldOverlay CreateOverlay(Playfield playfield) => new PlayfieldOverlay(); - protected abstract IReadOnlyList CompositionTools { get; } } } diff --git a/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs b/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs deleted file mode 100644 index 58b15e3de2..0000000000 --- a/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; - -namespace osu.Game.Rulesets.Edit -{ - public class PlayfieldOverlay : CompositeDrawable - { - public PlayfieldOverlay() - { - RelativeSizeAxes = Axes.Both; - - } - - - } -} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index ee5834890f..e1425ff8b8 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -302,7 +302,6 @@ - From c14d68e685143e00f8d37a2c1bc3d4f9d883378e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 2 Dec 2017 20:30:18 +0900 Subject: [PATCH 35/49] Use OsuColour for radio buttons --- .../RadioButtons/DrawableRadioButton.cs | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs index 48cc7f3379..10b6c07f3d 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs @@ -19,16 +19,16 @@ namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons { public class DrawableRadioButton : TriangleButton { - private static readonly Color4 default_background_colour = OsuColour.FromHex("333"); - private static readonly Color4 default_bubble_colour = default_background_colour.Darken(0.5f); - private static readonly Color4 selected_background_colour = OsuColour.FromHex("1188aa"); - private static readonly Color4 selected_bubble_colour = selected_background_colour.Lighten(0.5f); - /// /// Invoked when this has been selected. /// public Action Selected; + private Color4 defaultBackgroundColour; + private Color4 defaultBubbleColour; + private Color4 selectedBackgroundColour; + private Color4 selectedBubbleColour; + private readonly Drawable bubble; private readonly RadioButton button; @@ -50,17 +50,20 @@ namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons Scale = new Vector2(0.5f), X = 10, Masking = true, - Colour = default_bubble_colour, Blending = BlendingMode.Additive, Child = new Box { RelativeSizeAxes = Axes.Both } }; } [BackgroundDependencyLoader] - private void load() + private void load(OsuColour colours) { + defaultBackgroundColour = colours.Gray3; + defaultBubbleColour = defaultBackgroundColour.Darken(0.5f); + selectedBackgroundColour = colours.BlueDark; + selectedBubbleColour = selectedBackgroundColour.Lighten(0.5f); + Triangles.Alpha = 0; - BackgroundColour = default_background_colour; Content.EdgeEffect = new EdgeEffectParameters { @@ -92,8 +95,8 @@ namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons if (!IsLoaded) return; - BackgroundColour = button.Selected ? selected_background_colour : default_background_colour; - bubble.Colour = button.Selected ? selected_bubble_colour : default_bubble_colour; + BackgroundColour = button.Selected ? selectedBackgroundColour : defaultBackgroundColour; + bubble.Colour = button.Selected ? selectedBubbleColour : defaultBubbleColour; } protected override bool OnClick(InputState state) From cd20d6df160b1b4617b4f8035dc31ee52063588f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 2 Dec 2017 20:31:10 +0900 Subject: [PATCH 36/49] Apply suggested changes --- osu.Game/Screens/Edit/Editor.cs | 1 - .../Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs | 2 +- osu.Game/Screens/Edit/Screens/EditorScreen.cs | 2 -- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index bc86c683c7..607ff792d8 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -154,7 +154,6 @@ namespace osu.Game.Screens.Edit } currentScreen.Beatmap.BindTo(Beatmap); - currentScreen.ExitRequested = Exit; screenContainer.Add(currentScreen); } diff --git a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs index 08473eaeba..5f1def4a2e 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs @@ -22,7 +22,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons items = value; buttonContainer.Clear(); - value.ForEach(addButton); + items.ForEach(addButton); } } diff --git a/osu.Game/Screens/Edit/Screens/EditorScreen.cs b/osu.Game/Screens/Edit/Screens/EditorScreen.cs index 9a158d20f1..773975d493 100644 --- a/osu.Game/Screens/Edit/Screens/EditorScreen.cs +++ b/osu.Game/Screens/Edit/Screens/EditorScreen.cs @@ -11,8 +11,6 @@ namespace osu.Game.Screens.Edit.Screens { public class EditorScreen : Container { - public Action ExitRequested; - public readonly Bindable Beatmap = new Bindable(); protected override Container Content => content; From 2852337b04c0160a6b52e5376acdf73e09af4fd8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 2 Dec 2017 20:35:47 +0900 Subject: [PATCH 37/49] Remove unused using --- osu.Game/Screens/Edit/Screens/EditorScreen.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Screens/EditorScreen.cs b/osu.Game/Screens/Edit/Screens/EditorScreen.cs index 773975d493..ac248930d8 100644 --- a/osu.Game/Screens/Edit/Screens/EditorScreen.cs +++ b/osu.Game/Screens/Edit/Screens/EditorScreen.cs @@ -1,7 +1,6 @@ // 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.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; From a1dbd7916b8a890e8a241b0d43f55aed39a1cd2a Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Sun, 3 Dec 2017 14:03:43 +0100 Subject: [PATCH 38/49] fixes MusicController constantly trying to start a track In Detail: It tried to start a track if the current one ended even if no BeatmapSets were present. Also if only one BeatmapSet is present if will loop by itself now. --- osu.Game/Overlays/Music/PlaylistOverlay.cs | 6 ++++++ osu.Game/Overlays/MusicController.cs | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index d05ad85726..eeb1982d91 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -149,6 +149,12 @@ namespace osu.Game.Overlays.Music private void playSpecified(BeatmapInfo info) { beatmapBacking.Value = beatmaps.GetWorkingBeatmap(info, beatmapBacking); + + if (BeatmapSets.Count() == 1) + beatmapBacking.Value.Track.Looping = true; + else + beatmapBacking.Value.Track.Looping = false; + beatmapBacking.Value.Track.Start(); } } diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 4f57ea1bcd..b30ee8f6fc 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -251,7 +251,7 @@ namespace osu.Game.Overlays playButton.Icon = track.IsRunning ? FontAwesome.fa_pause_circle_o : FontAwesome.fa_play_circle_o; - if (track.HasCompleted && !track.Looping && !beatmapBacking.Disabled) + if (track.HasCompleted && !beatmapBacking.Disabled && playlist.BeatmapSets.Any()) next(); } else From 0c9ebcd58c2393910b9a07b407a5c45e31ccccda Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Sun, 3 Dec 2017 14:15:08 +0100 Subject: [PATCH 39/49] fix possible NullRef --- osu.Game/Overlays/Music/PlaylistOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index eeb1982d91..4bac91edb8 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -150,7 +150,7 @@ namespace osu.Game.Overlays.Music { beatmapBacking.Value = beatmaps.GetWorkingBeatmap(info, beatmapBacking); - if (BeatmapSets.Count() == 1) + if (BeatmapSets?.Count() == 1) beatmapBacking.Value.Track.Looping = true; else beatmapBacking.Value.Track.Looping = false; From dfa74487162de873d71da25c5698561f1677a120 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Sun, 3 Dec 2017 14:25:12 +0100 Subject: [PATCH 40/49] use ?: expression --- osu.Game/Overlays/Music/PlaylistOverlay.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index 4bac91edb8..1874b7ead8 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -149,12 +149,7 @@ namespace osu.Game.Overlays.Music private void playSpecified(BeatmapInfo info) { beatmapBacking.Value = beatmaps.GetWorkingBeatmap(info, beatmapBacking); - - if (BeatmapSets?.Count() == 1) - beatmapBacking.Value.Track.Looping = true; - else - beatmapBacking.Value.Track.Looping = false; - + beatmapBacking.Value.Track.Looping = BeatmapSets?.Count() == 1 ? true : false; beatmapBacking.Value.Track.Start(); } } From 9d13bf36025a8c355a4f5891007fffe62ab8a99a Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Sun, 3 Dec 2017 14:35:23 +0100 Subject: [PATCH 41/49] remove redundant expression --- osu.Game/Overlays/Music/PlaylistOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index 1874b7ead8..75798bab2d 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -149,7 +149,7 @@ namespace osu.Game.Overlays.Music private void playSpecified(BeatmapInfo info) { beatmapBacking.Value = beatmaps.GetWorkingBeatmap(info, beatmapBacking); - beatmapBacking.Value.Track.Looping = BeatmapSets?.Count() == 1 ? true : false; + beatmapBacking.Value.Track.Looping = BeatmapSets?.Count() == 1; beatmapBacking.Value.Track.Start(); } } From 14096c90cc73a03811c58d305ab8db0f6b22c42a Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Sun, 3 Dec 2017 16:41:21 +0100 Subject: [PATCH 42/49] removed looping if only one song is in the list (temporarily) It had one problem in relation to SongSelect disabling it when left and in general that topic belongs to another PR. --- osu.Game/Overlays/Music/PlaylistList.cs | 7 ++++++- osu.Game/Overlays/Music/PlaylistOverlay.cs | 16 +++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index af01cdc451..8db4af6fb2 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -35,7 +35,11 @@ namespace osu.Game.Overlays.Music set { base.Padding = value; } } - public IEnumerable BeatmapSets { set { items.Sets = value; } } + public IEnumerable BeatmapSets + { + get { return items.Sets; } + set { items.Sets = value; } + } public BeatmapSetInfo FirstVisibleSet => items.FirstVisibleSet; public BeatmapSetInfo NextSet => items.NextSet; @@ -81,6 +85,7 @@ namespace osu.Game.Overlays.Music public IEnumerable Sets { + get { return items.Select(x => x.BeatmapSetInfo).ToList(); } set { items.Clear(); diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index 75798bab2d..54b34aaead 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -29,7 +29,7 @@ namespace osu.Game.Overlays.Music private readonly Bindable beatmapBacking = new Bindable(); - public IEnumerable BeatmapSets; + public IEnumerable BeatmapSets => list.BeatmapSets; [BackgroundDependencyLoader] private void load(OsuGameBase game, BeatmapManager beatmaps, OsuColour colours) @@ -74,11 +74,10 @@ namespace osu.Game.Overlays.Music }, }; - beatmaps.BeatmapSetAdded += s => Schedule(() => list.AddBeatmapSet(s)); - beatmaps.BeatmapSetRemoved += s => Schedule(() => list.RemoveBeatmapSet(s)); - - list.BeatmapSets = BeatmapSets = beatmaps.GetAllUsableBeatmapSets(); + beatmaps.BeatmapSetAdded += delegate (BeatmapSetInfo set) { list.AddBeatmapSet(set); }; + beatmaps.BeatmapSetRemoved += delegate (BeatmapSetInfo set) { list.RemoveBeatmapSet(set); }; + list.BeatmapSets = beatmaps.GetAllUsableBeatmapSets(); beatmapBacking.BindTo(game.Beatmap); @@ -121,7 +120,7 @@ namespace osu.Game.Overlays.Music return; } - playSpecified(set.Beatmaps[0]); + playSpecified(set.Beatmaps.First()); } public void PlayPrevious() @@ -130,7 +129,7 @@ namespace osu.Game.Overlays.Music if (playable != null) { - playSpecified(playable.Beatmaps[0]); + playSpecified(playable.Beatmaps.First()); list.SelectedSet = playable; } } @@ -141,7 +140,7 @@ namespace osu.Game.Overlays.Music if (playable != null) { - playSpecified(playable.Beatmaps[0]); + playSpecified(playable.Beatmaps.First()); list.SelectedSet = playable; } } @@ -149,7 +148,6 @@ namespace osu.Game.Overlays.Music private void playSpecified(BeatmapInfo info) { beatmapBacking.Value = beatmaps.GetWorkingBeatmap(info, beatmapBacking); - beatmapBacking.Value.Track.Looping = BeatmapSets?.Count() == 1; beatmapBacking.Value.Track.Start(); } } From 5f9de399e40d6748a14657fa97da77aa3f916323 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 4 Dec 2017 11:30:25 +0900 Subject: [PATCH 43/49] Add keydown override --- osu.Game/Screens/OsuScreen.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 76ee4a607e..4a27c7f1ea 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -13,6 +13,8 @@ using osu.Framework.Audio; using osu.Framework.Graphics; using osu.Game.Rulesets; using osu.Game.Screens.Menu; +using osu.Framework.Input; +using OpenTK.Input; namespace osu.Game.Screens { @@ -73,6 +75,20 @@ namespace osu.Game.Screens sampleExit = audio.Sample.Get(@"UI/screen-back"); } + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (args.Repeat || !IsCurrentScreen) return false; + + switch (args.Key) + { + case Key.Escape: + Exit(); + return true; + } + + return base.OnKeyDown(state, args); + } + protected override void OnResuming(Screen last) { base.OnResuming(last); From 7cfe694a3fd63ac1dd54caddcb87bce80f09e8cb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 4 Dec 2017 11:37:19 +0900 Subject: [PATCH 44/49] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index cc013fc406..8c16e6244d 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit cc013fc4063dda0843f38c1c73568a413abcf229 +Subproject commit 8c16e6244d8ca884a743a0d5a1f1ee485f18655c From a83add8540d59d40ac19003de9ca1b29a2011512 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 4 Dec 2017 20:30:56 +0900 Subject: [PATCH 45/49] Tidy up events --- osu.Game/Overlays/Music/PlaylistList.cs | 10 +++++----- osu.Game/Overlays/Music/PlaylistOverlay.cs | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index 8db4af6fb2..245b2d36ce 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -52,7 +52,7 @@ namespace osu.Game.Overlays.Music } public void AddBeatmapSet(BeatmapSetInfo beatmapSet) => items.AddBeatmapSet(beatmapSet); - public bool RemoveBeatmapSet(BeatmapSetInfo beatmapSet) => items.RemoveBeatmapSet(beatmapSet); + public void RemoveBeatmapSet(BeatmapSetInfo beatmapSet) => items.RemoveBeatmapSet(beatmapSet); public void Filter(string searchTerm) => items.SearchTerm = searchTerm; @@ -108,12 +108,11 @@ namespace osu.Game.Overlays.Music }); } - public bool RemoveBeatmapSet(BeatmapSetInfo beatmapSet) + public void RemoveBeatmapSet(BeatmapSetInfo beatmapSet) { var itemToRemove = items.FirstOrDefault(i => i.BeatmapSetInfo.ID == beatmapSet.ID); - if (itemToRemove == null) - return false; - return items.Remove(itemToRemove); + if (itemToRemove != null) + items.Remove(itemToRemove); } public BeatmapSetInfo SelectedSet @@ -235,6 +234,7 @@ namespace osu.Game.Overlays.Music private class ItemSearchContainer : FillFlowContainer, IHasFilterableChildren { public IEnumerable FilterTerms => new string[] { }; + public bool MatchingFilter { set diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index 54b34aaead..2c7c097be2 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -74,8 +74,8 @@ namespace osu.Game.Overlays.Music }, }; - beatmaps.BeatmapSetAdded += delegate (BeatmapSetInfo set) { list.AddBeatmapSet(set); }; - beatmaps.BeatmapSetRemoved += delegate (BeatmapSetInfo set) { list.RemoveBeatmapSet(set); }; + beatmaps.BeatmapSetAdded += list.AddBeatmapSet; + beatmaps.BeatmapSetRemoved += list.RemoveBeatmapSet; list.BeatmapSets = beatmaps.GetAllUsableBeatmapSets(); From 7649a3115704dfae6c3947917f294ad97177b181 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 4 Dec 2017 20:32:50 +0900 Subject: [PATCH 46/49] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 8c16e6244d..e21fc5e170 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 8c16e6244d8ca884a743a0d5a1f1ee485f18655c +Subproject commit e21fc5e1705593151a323007fd66e90044332398 From caee6c1cf1163407734edf6fd68226849aafba66 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 4 Dec 2017 21:40:26 +0900 Subject: [PATCH 47/49] Use Restart instead of Start --- osu.Game/Overlays/Music/PlaylistOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index 2c7c097be2..cc55a72f24 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -148,7 +148,7 @@ namespace osu.Game.Overlays.Music private void playSpecified(BeatmapInfo info) { beatmapBacking.Value = beatmaps.GetWorkingBeatmap(info, beatmapBacking); - beatmapBacking.Value.Track.Start(); + beatmapBacking.Value.Track.Restart(); } } From b4641142a8e6205a25b175f3c4bae90b40d17e9d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 5 Dec 2017 01:00:06 +0900 Subject: [PATCH 48/49] Update framework once more --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index e21fc5e170..d2c6d11f3b 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit e21fc5e1705593151a323007fd66e90044332398 +Subproject commit d2c6d11f3bcc54a5aeb5a16d6563036c7e1f4759 From c1b607fed926eeb2051b8d0ebb6e3869efb9dcc9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 5 Dec 2017 09:56:24 +0900 Subject: [PATCH 49/49] Wait until track has restarted before continuing operation I removed this from my previous PR thinking it was not required, but it turned out to be required after all. Just isn't so noticeable when it fails. --- osu.Game/Overlays/Music/PlaylistOverlay.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index cc55a72f24..23bec53014 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -13,6 +13,7 @@ using osu.Game.Beatmaps; using osu.Game.Graphics; using OpenTK; using OpenTK.Graphics; +using System.Threading; namespace osu.Game.Overlays.Music { @@ -148,7 +149,15 @@ namespace osu.Game.Overlays.Music private void playSpecified(BeatmapInfo info) { beatmapBacking.Value = beatmaps.GetWorkingBeatmap(info, beatmapBacking); - beatmapBacking.Value.Track.Restart(); + + var track = beatmapBacking.Value.Track; + + track.Restart(); + + // this is temporary until we have blocking (async.Wait()) audio component methods. + // then we can call RestartAsync().Wait() or the blocking version above. + while (!track.IsRunning) + Thread.Sleep(1); } }