From e225b0032aa092c79322fb948fd7e3adb7aac2b4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Dec 2019 19:31:40 +0900 Subject: [PATCH 01/16] Add basic hitobject display to timeline --- .../Editor/TestSceneEditorComposeTimeline.cs | 16 ++++ .../Compose/Components/Timeline/Timeline.cs | 21 +++-- .../Timeline/TimelineHitObjectDisplay.cs | 85 +++++++++++++++++++ 3 files changed, 115 insertions(+), 7 deletions(-) create mode 100644 osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs diff --git a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs index 6e5b3b93e9..b67ea798a0 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs @@ -13,6 +13,10 @@ using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Compose.Components.Timeline; using osuTK; using osuTK.Graphics; @@ -25,11 +29,23 @@ public class TestSceneEditorComposeTimeline : EditorClockTestScene public override IReadOnlyList RequiredTypes => new[] { typeof(TimelineArea), + typeof(TimelineHitObjectDisplay), typeof(Timeline), typeof(TimelineButton), typeof(CentreMarker) }; + [Cached(typeof(IEditorBeatmap))] + private readonly EditorBeatmap editorBeatmap; + + public TestSceneEditorComposeTimeline() + { + editorBeatmap = new EditorBeatmap( + (Beatmap) + CreateWorkingBeatmap(new OsuRuleset().RulesetInfo).GetPlayableBeatmap(new OsuRuleset().RulesetInfo, new Mod[] { }) + ); + } + [BackgroundDependencyLoader] private void load(AudioManager audio) { diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs index 748c9e2ba3..1f8c134d84 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs @@ -36,14 +36,21 @@ private void load(IBindable beatmap, IAdjustableClock adjustable { this.adjustableClock = adjustableClock; - Child = waveform = new WaveformGraph + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Colour = colours.Blue.Opacity(0.2f), - LowColour = colours.BlueLighter, - MidColour = colours.BlueDark, - HighColour = colours.BlueDarker, - Depth = float.MaxValue + waveform = new WaveformGraph + { + RelativeSizeAxes = Axes.Both, + Colour = colours.Blue.Opacity(0.2f), + LowColour = colours.BlueLighter, + MidColour = colours.BlueDark, + HighColour = colours.BlueDarker, + Depth = float.MaxValue + }, + new TimelineHitObjectDisplay + { + RelativeSizeAxes = Axes.Both, + }, }; // We don't want the centre marker to scroll diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs new file mode 100644 index 0000000000..8bc0bf1a86 --- /dev/null +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs @@ -0,0 +1,85 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Screens.Edit.Components.Timelines.Summary.Parts; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Screens.Edit.Compose.Components.Timeline +{ + internal class TimelineHitObjectDisplay : TimelinePart + { + [Resolved] + private IEditorBeatmap beatmap { get; set; } + + [BackgroundDependencyLoader] + private void load() + { + foreach (var h in beatmap.HitObjects) + add(h); + + beatmap.HitObjectAdded += add; + beatmap.HitObjectRemoved += remove; + } + + private void remove(HitObject h) + { + foreach (var d in InternalChildren.OfType().Where(c => c.HitObject == h)) + d.Expire(); + } + + private void add(HitObject h) + { + Add(new TimelineHitObjectRepresentation(h)); + } + + private class TimelineHitObjectRepresentation : CompositeDrawable + { + public readonly HitObject HitObject; + + public TimelineHitObjectRepresentation(HitObject hitObject) + { + this.HitObject = hitObject; + Anchor = Anchor.CentreLeft; + Origin = Anchor.CentreLeft; + + Width = (float)(hitObject.GetEndTime() - hitObject.StartTime); + + X = (float)hitObject.StartTime; + + RelativePositionAxes = Axes.X; + RelativeSizeAxes = Axes.X; + + AddInternal(new Circle + { + Size = new Vector2(16), + Anchor = Anchor.CentreLeft, + Origin = Anchor.Centre, + RelativePositionAxes = Axes.X, + AlwaysPresent = true, + Colour = Color4.White, + }); + + if (hitObject is IHasEndTime) + { + AddInternal(new Box + { + Size = new Vector2(1, 5), + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativePositionAxes = Axes.X, + RelativeSizeAxes = Axes.X, + Colour = Color4.White, + }); + } + } + } + } +} From d8620a70fbbb7bbc9f983126a98478447fba9dc5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Dec 2019 20:12:25 +0900 Subject: [PATCH 02/16] Make work in editor --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 8 ++++++-- .../Timelines/Summary/Parts/TimelinePart.cs | 6 +++--- .../Compose/Components/Timeline/Timeline.cs | 4 ---- .../Components/Timeline/TimelineArea.cs | 10 +++++++--- .../Timeline/TimelineHitObjectDisplay.cs | 20 ++++++++++++------- .../Screens/Edit/Compose/ComposeScreen.cs | 13 ++++++++++-- .../Screens/Edit/EditorScreenWithTimeline.cs | 10 ++++++++-- osu.Game/Screens/Edit/IEditorBeatmap.cs | 5 +++++ 8 files changed, 53 insertions(+), 23 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 805fc2b46f..368520ba43 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -34,7 +34,9 @@ public abstract class HitObjectComposer : HitObjectComposer, IPlacement where TObject : HitObject { protected IRulesetConfigManager Config { get; private set; } - protected EditorBeatmap EditorBeatmap { get; private set; } + + protected new EditorBeatmap EditorBeatmap { get; private set; } + protected readonly Ruleset Ruleset; [Resolved] @@ -148,7 +150,7 @@ protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnl beatmapProcessor = Ruleset.CreateBeatmapProcessor(playableBeatmap); - EditorBeatmap = new EditorBeatmap(playableBeatmap); + base.EditorBeatmap = EditorBeatmap = new EditorBeatmap(playableBeatmap); EditorBeatmap.HitObjectAdded += addHitObject; EditorBeatmap.HitObjectRemoved += removeHitObject; EditorBeatmap.StartTimeChanged += UpdateHitObject; @@ -333,6 +335,8 @@ internal HitObjectComposer() /// public abstract IEnumerable HitObjects { get; } + public IEditorBeatmap EditorBeatmap { get; protected set; } + /// /// Whether the user's cursor is currently in an area of the that is valid for placement. /// diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs index 26d9614631..7706e33179 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs @@ -14,12 +14,14 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts /// /// Represents a part of the summary timeline.. /// - public abstract class TimelinePart : CompositeDrawable + public abstract class TimelinePart : Container { protected readonly IBindable Beatmap = new Bindable(); private readonly Container timeline; + protected override Container Content => timeline; + protected TimelinePart() { AddInternal(timeline = new Container { RelativeSizeAxes = Axes.Both }); @@ -50,8 +52,6 @@ private void updateRelativeChildSize() timeline.RelativeChildSize = new Vector2((float)Math.Max(1, Beatmap.Value.Track.Length), 1); } - protected void Add(Drawable visualisation) => timeline.Add(visualisation); - protected virtual void LoadBeatmap(WorkingBeatmap beatmap) { timeline.Clear(); diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs index 1f8c134d84..2a565d028f 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs @@ -47,10 +47,6 @@ private void load(IBindable beatmap, IAdjustableClock adjustable HighColour = colours.BlueDarker, Depth = float.MaxValue }, - new TimelineHitObjectDisplay - { - RelativeSizeAxes = Axes.Both, - }, }; // We don't want the centre marker to scroll diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs index 863a120fc3..93dac059e3 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -11,11 +12,14 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { - public class TimelineArea : CompositeDrawable + public class TimelineArea : Container { - private readonly Timeline timeline; + private Timeline timeline; - public TimelineArea() + protected override Container Content => timeline; + + [BackgroundDependencyLoader] + private void load() { Masking = true; CornerRadius = 5; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs index 8bc0bf1a86..fc16d29639 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs @@ -16,8 +16,12 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { internal class TimelineHitObjectDisplay : TimelinePart { - [Resolved] - private IEditorBeatmap beatmap { get; set; } + private IEditorBeatmap beatmap { get; } + + public TimelineHitObjectDisplay(IEditorBeatmap beatmap) + { + this.beatmap = beatmap; + } [BackgroundDependencyLoader] private void load() @@ -27,18 +31,20 @@ private void load() beatmap.HitObjectAdded += add; beatmap.HitObjectRemoved += remove; + beatmap.StartTimeChanged += h => + { + remove(h); + add(h); + }; } private void remove(HitObject h) { - foreach (var d in InternalChildren.OfType().Where(c => c.HitObject == h)) + foreach (var d in Children.OfType().Where(c => c.HitObject == h)) d.Expire(); } - private void add(HitObject h) - { - Add(new TimelineHitObjectRepresentation(h)); - } + private void add(HitObject h) => Add(new TimelineHitObjectRepresentation(h)); private class TimelineHitObjectRepresentation : CompositeDrawable { diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index 2e9094ebe6..8511bc3242 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -3,17 +3,21 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Edit; +using osu.Game.Screens.Edit.Compose.Components.Timeline; using osu.Game.Skinning; namespace osu.Game.Screens.Edit.Compose { public class ComposeScreen : EditorScreenWithTimeline { + private HitObjectComposer composer; + protected override Drawable CreateMainContent() { var ruleset = Beatmap.Value.BeatmapInfo.Ruleset?.CreateInstance(); - var composer = ruleset?.CreateHitObjectComposer(); + composer = ruleset?.CreateHitObjectComposer(); if (composer != null) { @@ -25,10 +29,15 @@ protected override Drawable CreateMainContent() // load the skinning hierarchy first. // this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources. - return beatmapSkinProvider.WithChild(rulesetSkinProvider.WithChild(ruleset.CreateHitObjectComposer())); + return beatmapSkinProvider.WithChild(rulesetSkinProvider.WithChild(composer)); } return new ScreenWhiteBox.UnderConstructionMessage(ruleset == null ? "This beatmap" : $"{ruleset.Description}'s composer"); } + + protected override Drawable CreateTimelineContent() => new TimelineHitObjectDisplay(composer.EditorBeatmap) + { + RelativeSizeAxes = Axes.Both, + }; } } diff --git a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs index 752356e8c4..1b9d1be4f8 100644 --- a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs +++ b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs @@ -20,6 +20,8 @@ public abstract class EditorScreenWithTimeline : EditorScreen private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor(); + private TimelineArea timelineArea; + [BackgroundDependencyLoader(true)] private void load([CanBeNull] BindableBeatDivisor beatDivisor) { @@ -64,7 +66,7 @@ private void load([CanBeNull] BindableBeatDivisor beatDivisor) { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Right = 5 }, - Child = CreateTimeline() + Child = timelineArea = CreateTimelineArea() }, new BeatDivisorControl(beatDivisor) { RelativeSizeAxes = Axes.Both } }, @@ -97,11 +99,15 @@ private void load([CanBeNull] BindableBeatDivisor beatDivisor) { mainContent.Add(content); content.FadeInFromZero(300, Easing.OutQuint); + + LoadComponentAsync(CreateTimelineContent(), timelineArea.Add); }); } protected abstract Drawable CreateMainContent(); - protected virtual Drawable CreateTimeline() => new TimelineArea { RelativeSizeAxes = Axes.Both }; + protected virtual Drawable CreateTimelineContent() => new Container { }; + + protected TimelineArea CreateTimelineArea() => new TimelineArea { RelativeSizeAxes = Axes.Both }; } } diff --git a/osu.Game/Screens/Edit/IEditorBeatmap.cs b/osu.Game/Screens/Edit/IEditorBeatmap.cs index 2f250ba446..3e3418ef79 100644 --- a/osu.Game/Screens/Edit/IEditorBeatmap.cs +++ b/osu.Game/Screens/Edit/IEditorBeatmap.cs @@ -23,6 +23,11 @@ public interface IEditorBeatmap : IBeatmap /// Invoked when a is removed from this . /// event Action HitObjectRemoved; + + /// + /// Invoked when the start time of a in this was changed. + /// + event Action StartTimeChanged; } /// From e76f8bdd6414542de669ea0301bebf921cf0be06 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Dec 2019 23:31:21 +0900 Subject: [PATCH 03/16] Fix warnings --- .../Editor/TestSceneEditorComposeTimeline.cs | 16 +++---- .../Timeline/TimelineHitObjectDisplay.cs | 43 ++++++++++++------- .../Screens/Edit/EditorScreenWithTimeline.cs | 2 +- 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs index b67ea798a0..2b46418659 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs @@ -35,20 +35,14 @@ public class TestSceneEditorComposeTimeline : EditorClockTestScene typeof(CentreMarker) }; - [Cached(typeof(IEditorBeatmap))] - private readonly EditorBeatmap editorBeatmap; - - public TestSceneEditorComposeTimeline() - { - editorBeatmap = new EditorBeatmap( - (Beatmap) - CreateWorkingBeatmap(new OsuRuleset().RulesetInfo).GetPlayableBeatmap(new OsuRuleset().RulesetInfo, new Mod[] { }) - ); - } - [BackgroundDependencyLoader] private void load(AudioManager audio) { + var editorBeatmap = new EditorBeatmap( + (Beatmap) + CreateWorkingBeatmap(new OsuRuleset().RulesetInfo).GetPlayableBeatmap(new OsuRuleset().RulesetInfo, new Mod[] { }) + ); + Beatmap.Value = new WaveformTestBeatmap(audio); Children = new Drawable[] diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs index fc16d29639..337fd9a6b2 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs @@ -44,7 +44,12 @@ private void remove(HitObject h) d.Expire(); } - private void add(HitObject h) => Add(new TimelineHitObjectRepresentation(h)); + private void add(HitObject h) + { + var yOffset = Children.Count(d => d.X == h.StartTime); + + Add(new TimelineHitObjectRepresentation(h) { Y = -yOffset * 4 }); + } private class TimelineHitObjectRepresentation : CompositeDrawable { @@ -52,7 +57,7 @@ private class TimelineHitObjectRepresentation : CompositeDrawable public TimelineHitObjectRepresentation(HitObject hitObject) { - this.HitObject = hitObject; + HitObject = hitObject; Anchor = Anchor.CentreLeft; Origin = Anchor.CentreLeft; @@ -63,6 +68,25 @@ public TimelineHitObjectRepresentation(HitObject hitObject) RelativePositionAxes = Axes.X; RelativeSizeAxes = Axes.X; + if (hitObject is IHasEndTime) + { + AddInternal(new Container + { + CornerRadius = 2, + Masking = true, + Size = new Vector2(1, 3), + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativePositionAxes = Axes.X, + RelativeSizeAxes = Axes.X, + Colour = Color4.Black, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + } + }); + } + AddInternal(new Circle { Size = new Vector2(16), @@ -71,20 +95,9 @@ public TimelineHitObjectRepresentation(HitObject hitObject) RelativePositionAxes = Axes.X, AlwaysPresent = true, Colour = Color4.White, + BorderColour = Color4.Black, + BorderThickness = 3, }); - - if (hitObject is IHasEndTime) - { - AddInternal(new Box - { - Size = new Vector2(1, 5), - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - RelativePositionAxes = Axes.X, - RelativeSizeAxes = Axes.X, - Colour = Color4.White, - }); - } } } } diff --git a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs index 1b9d1be4f8..aa8d99b517 100644 --- a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs +++ b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs @@ -106,7 +106,7 @@ private void load([CanBeNull] BindableBeatDivisor beatDivisor) protected abstract Drawable CreateMainContent(); - protected virtual Drawable CreateTimelineContent() => new Container { }; + protected virtual Drawable CreateTimelineContent() => new Container(); protected TimelineArea CreateTimelineArea() => new TimelineArea { RelativeSizeAxes = Axes.Both }; } From 12a98438353fbec5966e234dad10ab8d7f4a1dc9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 10:48:18 +0900 Subject: [PATCH 04/16] Move thickness to a constant --- .../Components/Timeline/TimelineHitObjectDisplay.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs index 337fd9a6b2..7d6d8fd729 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs @@ -48,11 +48,13 @@ private void add(HitObject h) { var yOffset = Children.Count(d => d.X == h.StartTime); - Add(new TimelineHitObjectRepresentation(h) { Y = -yOffset * 4 }); + Add(new TimelineHitObjectRepresentation(h) { Y = -yOffset * TimelineHitObjectRepresentation.THICKNESS }); } private class TimelineHitObjectRepresentation : CompositeDrawable { + public const float THICKNESS = 3; + public readonly HitObject HitObject; public TimelineHitObjectRepresentation(HitObject hitObject) @@ -74,7 +76,7 @@ public TimelineHitObjectRepresentation(HitObject hitObject) { CornerRadius = 2, Masking = true, - Size = new Vector2(1, 3), + Size = new Vector2(1, THICKNESS), Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, RelativePositionAxes = Axes.X, @@ -96,7 +98,7 @@ public TimelineHitObjectRepresentation(HitObject hitObject) AlwaysPresent = true, Colour = Color4.White, BorderColour = Color4.Black, - BorderThickness = 3, + BorderThickness = THICKNESS, }); } } From 28400aa865d4727eb885d50ffe0b0a1a553cff6c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 11:26:50 +0900 Subject: [PATCH 05/16] Update test scene --- .../Editor/TestSceneEditorComposeTimeline.cs | 12 ++++-------- .../Compose/Components/Timeline/Timeline.cs | 19 ++++++++----------- .../Components/Timeline/TimelineArea.cs | 4 ++-- .../Timeline/TimelineHitObjectDisplay.cs | 2 ++ .../Screens/Edit/Compose/ComposeScreen.cs | 5 +---- 5 files changed, 17 insertions(+), 25 deletions(-) diff --git a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs index 2b46418659..e618256c03 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs @@ -13,9 +13,7 @@ using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Osu; -using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Objects; using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Compose.Components.Timeline; using osuTK; @@ -38,13 +36,10 @@ public class TestSceneEditorComposeTimeline : EditorClockTestScene [BackgroundDependencyLoader] private void load(AudioManager audio) { - var editorBeatmap = new EditorBeatmap( - (Beatmap) - CreateWorkingBeatmap(new OsuRuleset().RulesetInfo).GetPlayableBeatmap(new OsuRuleset().RulesetInfo, new Mod[] { }) - ); - Beatmap.Value = new WaveformTestBeatmap(audio); + var editorBeatmap = new EditorBeatmap((Beatmap)Beatmap.Value.Beatmap); + Children = new Drawable[] { new FillFlowContainer @@ -60,6 +55,7 @@ private void load(AudioManager audio) }, new TimelineArea { + Child = new TimelineHitObjectDisplay(editorBeatmap), Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.X, diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs index 2a565d028f..b4f3b1f610 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs @@ -36,18 +36,15 @@ private void load(IBindable beatmap, IAdjustableClock adjustable { this.adjustableClock = adjustableClock; - Children = new Drawable[] + Add(waveform = new WaveformGraph { - waveform = new WaveformGraph - { - RelativeSizeAxes = Axes.Both, - Colour = colours.Blue.Opacity(0.2f), - LowColour = colours.BlueLighter, - MidColour = colours.BlueDark, - HighColour = colours.BlueDarker, - Depth = float.MaxValue - }, - }; + RelativeSizeAxes = Axes.Both, + Colour = colours.Blue.Opacity(0.2f), + LowColour = colours.BlueLighter, + MidColour = colours.BlueDark, + HighColour = colours.BlueDarker, + Depth = float.MaxValue + }); // We don't want the centre marker to scroll AddInternal(new CentreMarker()); diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs index 93dac059e3..8909b3d422 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs @@ -14,7 +14,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { public class TimelineArea : Container { - private Timeline timeline; + private readonly Timeline timeline = new Timeline { RelativeSizeAxes = Axes.Both }; protected override Container Content => timeline; @@ -111,7 +111,7 @@ private void load() } } }, - timeline = new Timeline { RelativeSizeAxes = Axes.Both } + timeline }, }, ColumnDimensions = new[] diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs index 7d6d8fd729..db4aca75e5 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs @@ -20,6 +20,8 @@ internal class TimelineHitObjectDisplay : TimelinePart public TimelineHitObjectDisplay(IEditorBeatmap beatmap) { + RelativeSizeAxes = Axes.Both; + this.beatmap = beatmap; } diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index 8511bc3242..cb8f2b2caa 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -35,9 +35,6 @@ protected override Drawable CreateMainContent() return new ScreenWhiteBox.UnderConstructionMessage(ruleset == null ? "This beatmap" : $"{ruleset.Description}'s composer"); } - protected override Drawable CreateTimelineContent() => new TimelineHitObjectDisplay(composer.EditorBeatmap) - { - RelativeSizeAxes = Axes.Both, - }; + protected override Drawable CreateTimelineContent() => new TimelineHitObjectDisplay(composer.EditorBeatmap); } } From 9f4c8db39508f52fe377d07d58cee38682dc1087 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 12:17:41 +0900 Subject: [PATCH 06/16] Add xmldoc --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 368520ba43..9ac967ef74 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -335,6 +335,9 @@ internal HitObjectComposer() /// public abstract IEnumerable HitObjects { get; } + /// + /// An editor-specific beatmap, exposing mutation events. + /// public IEditorBeatmap EditorBeatmap { get; protected set; } /// From 9248fbe881f81a0d0d0516ad1e770179fb71a5d0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 12:22:44 +0900 Subject: [PATCH 07/16] Remove extra checkboxes for now --- .../Edit/Compose/Components/Timeline/TimelineArea.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs index 8909b3d422..02e5db306d 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs @@ -24,8 +24,6 @@ private void load() Masking = true; CornerRadius = 5; - OsuCheckbox hitObjectsCheckbox; - OsuCheckbox hitSoundsCheckbox; OsuCheckbox waveformCheckbox; InternalChildren = new Drawable[] @@ -64,8 +62,6 @@ private void load() Spacing = new Vector2(0, 4), Children = new[] { - hitObjectsCheckbox = new OsuCheckbox { LabelText = "Hit objects" }, - hitSoundsCheckbox = new OsuCheckbox { LabelText = "Hit sounds" }, waveformCheckbox = new OsuCheckbox { LabelText = "Waveform" } } } @@ -123,8 +119,6 @@ private void load() } }; - hitObjectsCheckbox.Current.Value = true; - hitSoundsCheckbox.Current.Value = true; waveformCheckbox.Current.Value = true; timeline.WaveformVisible.BindTo(waveformCheckbox.Current); From b1426d1b22fe9789dd99df497ae2f315b1ac2c2a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 12:51:43 +0900 Subject: [PATCH 08/16] Full impossible nullref --- .../Screens/Edit/Compose/ComposeScreen.cs | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index cb8f2b2caa..6984716a2c 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -16,23 +16,20 @@ public class ComposeScreen : EditorScreenWithTimeline protected override Drawable CreateMainContent() { var ruleset = Beatmap.Value.BeatmapInfo.Ruleset?.CreateInstance(); - composer = ruleset?.CreateHitObjectComposer(); - if (composer != null) - { - var beatmapSkinProvider = new BeatmapSkinProvidingContainer(Beatmap.Value.Skin); + if (ruleset == null || composer == null) + return new ScreenWhiteBox.UnderConstructionMessage(ruleset == null ? "This beatmap" : $"{ruleset.Description}'s composer"); - // the beatmapSkinProvider is used as the fallback source here to allow the ruleset-specific skin implementation - // full access to all skin sources. - var rulesetSkinProvider = new SkinProvidingContainer(ruleset.CreateLegacySkinProvider(beatmapSkinProvider)); + var beatmapSkinProvider = new BeatmapSkinProvidingContainer(Beatmap.Value.Skin); - // load the skinning hierarchy first. - // this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources. - return beatmapSkinProvider.WithChild(rulesetSkinProvider.WithChild(composer)); - } + // the beatmapSkinProvider is used as the fallback source here to allow the ruleset-specific skin implementation + // full access to all skin sources. + var rulesetSkinProvider = new SkinProvidingContainer(ruleset.CreateLegacySkinProvider(beatmapSkinProvider)); - return new ScreenWhiteBox.UnderConstructionMessage(ruleset == null ? "This beatmap" : $"{ruleset.Description}'s composer"); + // load the skinning hierarchy first. + // this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources. + return beatmapSkinProvider.WithChild(rulesetSkinProvider.WithChild(composer)); } protected override Drawable CreateTimelineContent() => new TimelineHitObjectDisplay(composer.EditorBeatmap); From 13b891f3f4ed6eae1c572737238a005e199efbd1 Mon Sep 17 00:00:00 2001 From: mcendu Date: Sun, 8 Dec 2019 20:05:02 +0800 Subject: [PATCH 09/16] Crude legacy cursor rotation support --- osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs index 470ba3acae..6bef90fbaa 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs @@ -19,6 +19,8 @@ public LegacyCursor() Origin = Anchor.Centre; } + private NonPlayfieldSprite cursor; + [BackgroundDependencyLoader] private void load(ISkinSource skin) { @@ -30,13 +32,14 @@ private void load(ISkinSource skin) Anchor = Anchor.Centre, Origin = Anchor.Centre, }, - new NonPlayfieldSprite + cursor = new NonPlayfieldSprite { Texture = skin.GetTexture("cursor"), Anchor = Anchor.Centre, Origin = Anchor.Centre, } }; + cursor.Spin(10000, RotationDirection.Clockwise); } } } From 4cd0dd7856e8b553a9698d86dc114f0ca0768a92 Mon Sep 17 00:00:00 2001 From: mcendu Date: Sun, 8 Dec 2019 20:47:28 +0800 Subject: [PATCH 10/16] Move transformation to LoadComplete --- osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs index 6bef90fbaa..11039227c6 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs @@ -39,6 +39,10 @@ private void load(ISkinSource skin) Origin = Anchor.Centre, } }; + } + + protected override void LoadComplete() + { cursor.Spin(10000, RotationDirection.Clockwise); } } From b2b252a1cc446f96c306129fe6d6011b07dafe66 Mon Sep 17 00:00:00 2001 From: mcendu Date: Mon, 9 Dec 2019 08:36:07 +0800 Subject: [PATCH 11/16] Allow skin to disable spin --- osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs | 8 ++++++-- .../Skinning/OsuLegacySkinTransformer.cs | 4 +++- osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs | 1 + 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs index 11039227c6..68cf99caf1 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs @@ -11,15 +11,18 @@ namespace osu.Game.Rulesets.Osu.Skinning { public class LegacyCursor : CompositeDrawable { - public LegacyCursor() + public LegacyCursor(bool spin = true) { Size = new Vector2(50); Anchor = Anchor.Centre; Origin = Anchor.Centre; + + rotate = spin; } private NonPlayfieldSprite cursor; + private bool rotate; [BackgroundDependencyLoader] private void load(ISkinSource skin) @@ -43,7 +46,8 @@ private void load(ISkinSource skin) protected override void LoadComplete() { - cursor.Spin(10000, RotationDirection.Clockwise); + if (rotate) + cursor.Spin(10000, RotationDirection.Clockwise); } } } diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index f5b7d9166f..f58b96844e 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -81,7 +81,9 @@ public Drawable GetDrawableComponent(ISkinComponent component) case OsuSkinComponents.Cursor: if (source.GetTexture("cursor") != null) - return new LegacyCursor(); + { + return new LegacyCursor(GetConfig(OsuSkinConfiguration.CursorRotate)?.Value ?? true); + } return null; diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs b/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs index 98219cafe8..5d99960f10 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs @@ -11,5 +11,6 @@ public enum OsuSkinConfiguration SliderPathRadius, AllowSliderBallTint, CursorExpand, + CursorRotate } } From 1cf81c49066dbf3fdafc3d029c187ad012b26d0d Mon Sep 17 00:00:00 2001 From: mcendu Date: Mon, 9 Dec 2019 08:37:32 +0800 Subject: [PATCH 12/16] rm unnecessary curlies --- osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index f58b96844e..56c8e74509 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -81,9 +81,7 @@ public Drawable GetDrawableComponent(ISkinComponent component) case OsuSkinComponents.Cursor: if (source.GetTexture("cursor") != null) - { return new LegacyCursor(GetConfig(OsuSkinConfiguration.CursorRotate)?.Value ?? true); - } return null; From eb065286ae5b17081910d708fc1deb2421c969bd Mon Sep 17 00:00:00 2001 From: mcendu Date: Mon, 9 Dec 2019 08:49:44 +0800 Subject: [PATCH 13/16] fix ci --- osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs index 68cf99caf1..85ae9d0fc4 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs @@ -22,7 +22,7 @@ public LegacyCursor(bool spin = true) } private NonPlayfieldSprite cursor; - private bool rotate; + private readonly bool rotate; [BackgroundDependencyLoader] private void load(ISkinSource skin) From 76aabdd2971effca216074ee33e7399b8e8b92b0 Mon Sep 17 00:00:00 2001 From: mcendu Date: Mon, 9 Dec 2019 12:11:04 +0800 Subject: [PATCH 14/16] rename field rotate to spin --- osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs index 85ae9d0fc4..d0d11b9157 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs @@ -18,11 +18,11 @@ public LegacyCursor(bool spin = true) Anchor = Anchor.Centre; Origin = Anchor.Centre; - rotate = spin; + this.spin = spin; } private NonPlayfieldSprite cursor; - private readonly bool rotate; + private readonly bool spin; [BackgroundDependencyLoader] private void load(ISkinSource skin) @@ -46,7 +46,7 @@ private void load(ISkinSource skin) protected override void LoadComplete() { - if (rotate) + if (spin) cursor.Spin(10000, RotationDirection.Clockwise); } } From 69deb0ca96f2ef4d22233fd8333311c290b965b0 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 9 Dec 2019 07:19:55 +0300 Subject: [PATCH 15/16] Fix unavailable replays can be accessed via leaderboard --- osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs index 79ce04ed66..b941cd8973 100644 --- a/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs +++ b/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs @@ -34,7 +34,7 @@ public ScoreInfo CreateScoreInfo(RulesetStore rulesets) PP = PP, Beatmap = Beatmap, RulesetID = OnlineRulesetID, - Hash = "online", // todo: temporary? + Hash = Replay ? "online" : string.Empty, // todo: temporary? Rank = Rank, Ruleset = ruleset, Mods = mods, From aff1b93a0790672311926a9e0f6bec711c1ce011 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Dec 2019 14:43:23 +0900 Subject: [PATCH 16/16] Move config retrieval into LegacySliderBall --- osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs | 12 ++++++------ .../Skinning/OsuLegacySkinTransformer.cs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs index d0d11b9157..05b38ae195 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs @@ -11,22 +11,22 @@ namespace osu.Game.Rulesets.Osu.Skinning { public class LegacyCursor : CompositeDrawable { - public LegacyCursor(bool spin = true) + private NonPlayfieldSprite cursor; + private bool spin; + + public LegacyCursor() { Size = new Vector2(50); Anchor = Anchor.Centre; Origin = Anchor.Centre; - - this.spin = spin; } - private NonPlayfieldSprite cursor; - private readonly bool spin; - [BackgroundDependencyLoader] private void load(ISkinSource skin) { + spin = skin.GetConfig(OsuSkinConfiguration.CursorRotate)?.Value ?? true; + InternalChildren = new Drawable[] { new NonPlayfieldSprite diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index 56c8e74509..f5b7d9166f 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -81,7 +81,7 @@ public Drawable GetDrawableComponent(ISkinComponent component) case OsuSkinComponents.Cursor: if (source.GetTexture("cursor") != null) - return new LegacyCursor(GetConfig(OsuSkinConfiguration.CursorRotate)?.Value ?? true); + return new LegacyCursor(); return null;