From 2edc39ae163b89f63dcd07b3220f75d29c737df4 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 10 May 2017 14:56:39 +0900 Subject: [PATCH 01/40] Add timing sections. --- osu.Game.Rulesets.Mania/UI/Column.cs | 44 ++++++++++++- .../UI/ManiaHitRenderer.cs | 61 +++++++++++++++++++ osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 6 ++ .../Timing/DrawableTimingSection.cs | 27 ++++++++ .../Timing/TimingSection.cs | 15 +++++ .../osu.Game.Rulesets.Taiko.csproj | 2 + 6 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Rulesets.Taiko/Timing/DrawableTimingSection.cs create mode 100644 osu.Game.Rulesets.Taiko/Timing/TimingSection.cs diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index d2fccb2c58..681c5a5ef2 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Colour; using osu.Framework.Input; using osu.Game.Graphics; +using osu.Game.Rulesets.Taiko.Timing; namespace osu.Game.Rulesets.Mania.UI { @@ -29,11 +30,17 @@ namespace osu.Game.Rulesets.Mania.UI private const float column_width = 45; private const float special_column_width = 70; + private const double time_span_default = 2000; + private const double time_span_min = 10; + private const double time_span_max = 20000; + private const double time_span_step = 100; + public Key Key; private readonly Box background; private readonly Container hitTargetBar; private readonly Container keyIcon; + private readonly Container timingSectionContainer; public Column() { @@ -130,6 +137,14 @@ namespace osu.Game.Rulesets.Mania.UI } } } + }, + timingSectionContainer = new Container + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.Both, + Y = -hit_target_bar_height, + RelativeCoordinateSpace = new Vector2(1, (float)time_span_default) } }; } @@ -176,14 +191,32 @@ namespace osu.Game.Rulesets.Mania.UI } } + public void AddTimingSection(TimingSection timingSection) => timingSectionContainer.Add(new DrawableTimingSection(timingSection)); + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) { - if (args.Key == Key && !args.Repeat) + if (args.Repeat) + return false; + + if (args.Key == Key) { background.FadeTo(background.Alpha + 0.2f, 50, EasingTypes.OutQuint); keyIcon.ScaleTo(1.4f, 50, EasingTypes.OutQuint); } + if (state.Keyboard.ControlPressed) + { + switch (args.Key) + { + case Key.Minus: + timeSpan += time_span_step; + break; + case Key.Plus: + timeSpan -= time_span_step; + break; + } + } + return false; } @@ -197,6 +230,15 @@ namespace osu.Game.Rulesets.Mania.UI return false; } + + /// + /// The amount of time which the length of this column spans. + /// + private double timeSpan + { + get { return timingSectionContainer.RelativeCoordinateSpace.Y; } + set { timingSectionContainer.RelativeCoordinateSpace = new Vector2(1, (float)MathHelper.Clamp(value, time_span_min, time_span_max)); } + } } } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs index c007cdc80e..f72ddf3227 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs @@ -1,14 +1,21 @@ // 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.Game.Beatmaps; +using osu.Game.Beatmaps.Timing; using osu.Game.Rulesets.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Taiko.Timing; using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Mania.UI @@ -21,6 +28,60 @@ namespace osu.Game.Rulesets.Mania.UI : base(beatmap) { this.columns = columns; + // Has to be done before drawable hit objects are generated in load() + loadTimingSections(); + } + + private void loadTimingSections() + { + var maniaPlayfield = Playfield as ManiaPlayfield; + if (maniaPlayfield == null) + return; + + var sections = new List(); + + // Construct all the relevant timing sections + ControlPoint lastTimingChange = null; + foreach (ControlPoint point in Beatmap.TimingInfo.ControlPoints) + { + if (point.TimingChange) + lastTimingChange = point; + + sections.Add(new TimingSection + { + StartTime = point.Time, + // Todo: Should this be dividing by beatlength? + BeatLength = point.SpeedMultiplier * lastTimingChange.BeatLength, + TimeSignature = point.TimeSignature + }); + } + + double lastObjectTime = (Objects.Last() as IHasEndTime)?.EndTime ?? Objects.Last().StartTime; + + // Perform some post processing of the timing sections + sections = sections + // Collapse sections after the last hit object + .Where(s => s.StartTime <= lastObjectTime) + // Collapse sections with the same start time + .GroupBy(s => s.StartTime).Select(g => g.Last()).OrderBy(s => s.StartTime) + // Collapse sections with the same beat length + .GroupBy(s => s.BeatLength).Select(g => g.First()) + .ToList(); + + // Determine duration of timing sections + for (int i = 0; i < sections.Count; i++) + { + if (i < sections.Count - 1) + sections[i].Duration = sections[i + 1].StartTime - sections[i].StartTime; + else + { + // Extra length added for the last timing section to extend past the last hitobject + double extraLength = sections[i].BeatLength * (int)sections[i].TimeSignature; + sections[i].Duration = lastObjectTime + extraLength - sections[i].StartTime; + } + } + + sections.ForEach(s => maniaPlayfield.Columns.Children.ForEach(c => c.AddTimingSection(s))); } public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(this); diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 438c1f4b5f..6999ae3952 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -16,6 +16,10 @@ using osu.Framework.Allocation; using OpenTK.Input; using System.Linq; using System.Collections.Generic; +using osu.Game.Rulesets.Taiko.Timing; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Mania.Objects.Drawables; namespace osu.Game.Rulesets.Mania.UI { @@ -156,5 +160,7 @@ namespace osu.Game.Rulesets.Mania.UI return column == columnCount - 1; } } + + public void Add(TimingSection timingSection) => columns.Children.ForEach(c => c.Add(timingSection)); } } diff --git a/osu.Game.Rulesets.Taiko/Timing/DrawableTimingSection.cs b/osu.Game.Rulesets.Taiko/Timing/DrawableTimingSection.cs new file mode 100644 index 0000000000..e9c403302c --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Timing/DrawableTimingSection.cs @@ -0,0 +1,27 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; + +namespace osu.Game.Rulesets.Taiko.Timing +{ + public class DrawableTimingSection : Container + { + private readonly TimingSection section; + + public DrawableTimingSection(TimingSection section) + { + this.section = section; + + RelativePositionAxes = Axes.Y; + Y = -(float)section.StartTime; + + RelativeSizeAxes = Axes.Both; + Height = (float)section.Duration; + + RelativeCoordinateSpace = new Vector2(1, Height); + } + } +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko/Timing/TimingSection.cs b/osu.Game.Rulesets.Taiko/Timing/TimingSection.cs new file mode 100644 index 0000000000..418ccac8c8 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Timing/TimingSection.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Beatmaps.Timing; + +namespace osu.Game.Rulesets.Taiko.Timing +{ + public class TimingSection + { + public double StartTime; + public double Duration; + public double BeatLength; + public TimeSignatures TimeSignature; + } +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index 983dc72d9e..5308de741a 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -85,6 +85,8 @@ + + From bcc8a94e36e4f68cf08455c8449a8d779439252e Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 10 May 2017 16:32:11 +0900 Subject: [PATCH 02/40] Construct mania playfield with proper column count. --- osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs | 7 ++++++- osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs | 8 ++++---- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 10bebbdba7..94984146f7 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -8,6 +8,7 @@ using System; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Beatmaps; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Mania.Objects.Drawables; namespace osu.Game.Rulesets.Mania.Beatmaps { @@ -17,7 +18,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps protected override IEnumerable ConvertHitObject(HitObject original, Beatmap beatmap) { - yield return null; + yield return new Note + { + StartTime = original.StartTime, + Column = 1, + }; } } } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs index f72ddf3227..b34442b1e1 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Timing; using osu.Game.Rulesets.Beatmaps; @@ -22,12 +23,11 @@ namespace osu.Game.Rulesets.Mania.UI { public class ManiaHitRenderer : HitRenderer { - private readonly int columns; + public int? Columns; - public ManiaHitRenderer(WorkingBeatmap beatmap, int columns = 5) + public ManiaHitRenderer(WorkingBeatmap beatmap) : base(beatmap) { - this.columns = columns; // Has to be done before drawable hit objects are generated in load() loadTimingSections(); } @@ -88,7 +88,7 @@ namespace osu.Game.Rulesets.Mania.UI protected override BeatmapConverter CreateBeatmapConverter() => new ManiaBeatmapConverter(); - protected override Playfield CreatePlayfield() => new ManiaPlayfield(columns); + protected override Playfield CreatePlayfield() => new ManiaPlayfield(Columns ?? (int)Math.Round(Beatmap.BeatmapInfo.Difficulty.CircleSize)); protected override DrawableHitObject GetVisualRepresentation(ManiaHitObject h) => null; } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 6999ae3952..e468d6f533 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -161,6 +161,6 @@ namespace osu.Game.Rulesets.Mania.UI } } - public void Add(TimingSection timingSection) => columns.Children.ForEach(c => c.Add(timingSection)); + public override void Add(DrawableHitObject h) => Columns.Children.ElementAt(h.HitObject.Column).Add(h); } } From 11c47454ad02b40d9657e62704a7d0122e7b692f Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 10 May 2017 17:13:33 +0900 Subject: [PATCH 03/40] Update framework. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index cd37a9cad9..d4a40115e7 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit cd37a9cad9aaede267152cf3753cd31fe697cec4 +Subproject commit d4a40115e704656191ae875ec742db6427767329 From 2867606913e2c4ea5443d39cedf9088ef522dedb Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 10 May 2017 17:34:43 +0900 Subject: [PATCH 04/40] Whoops wrong project. --- .../Timing/DrawableTimingSection.cs | 2 +- .../Timing/TimingSection.cs | 2 +- osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj | 2 ++ osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj | 2 -- 4 files changed, 4 insertions(+), 4 deletions(-) rename {osu.Game.Rulesets.Taiko => osu.Game.Rulesets.Mania}/Timing/DrawableTimingSection.cs (94%) rename {osu.Game.Rulesets.Taiko => osu.Game.Rulesets.Mania}/Timing/TimingSection.cs (89%) diff --git a/osu.Game.Rulesets.Taiko/Timing/DrawableTimingSection.cs b/osu.Game.Rulesets.Mania/Timing/DrawableTimingSection.cs similarity index 94% rename from osu.Game.Rulesets.Taiko/Timing/DrawableTimingSection.cs rename to osu.Game.Rulesets.Mania/Timing/DrawableTimingSection.cs index e9c403302c..8dcb39ae0d 100644 --- a/osu.Game.Rulesets.Taiko/Timing/DrawableTimingSection.cs +++ b/osu.Game.Rulesets.Mania/Timing/DrawableTimingSection.cs @@ -5,7 +5,7 @@ using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -namespace osu.Game.Rulesets.Taiko.Timing +namespace osu.Game.Rulesets.Mania.Timing { public class DrawableTimingSection : Container { diff --git a/osu.Game.Rulesets.Taiko/Timing/TimingSection.cs b/osu.Game.Rulesets.Mania/Timing/TimingSection.cs similarity index 89% rename from osu.Game.Rulesets.Taiko/Timing/TimingSection.cs rename to osu.Game.Rulesets.Mania/Timing/TimingSection.cs index 418ccac8c8..fdc367de11 100644 --- a/osu.Game.Rulesets.Taiko/Timing/TimingSection.cs +++ b/osu.Game.Rulesets.Mania/Timing/TimingSection.cs @@ -3,7 +3,7 @@ using osu.Game.Beatmaps.Timing; -namespace osu.Game.Rulesets.Taiko.Timing +namespace osu.Game.Rulesets.Mania.Timing { public class TimingSection { diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 0f2d7e7c1c..f745845f6e 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -58,6 +58,8 @@ + + diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index 5308de741a..983dc72d9e 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -85,8 +85,6 @@ - - From ba998035a891bfdfaa4ccf14cbccf2c1d9590bdd Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 10 May 2017 17:53:51 +0900 Subject: [PATCH 05/40] More concrete way to determine whether all hit objects have been judged. --- .../Objects/Drawables/DrawableHitObject.cs | 17 ++++++++++++----- osu.Game/Rulesets/UI/HitRenderer.cs | 2 +- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 21eca346c4..f443b5e279 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -12,6 +12,7 @@ using Container = osu.Framework.Graphics.Containers.Container; using osu.Game.Rulesets.Objects.Types; using OpenTK.Graphics; using osu.Game.Audio; +using System.Linq; namespace osu.Game.Rulesets.Objects.Drawables { @@ -24,6 +25,11 @@ namespace osu.Game.Rulesets.Objects.Drawables public TJudgement Judgement; + /// + /// Whether this hit object has been judged. + /// + public virtual bool Judged => (Judgement?.Result ?? HitResult.None) != HitResult.None; + protected abstract TJudgement CreateJudgement(); protected abstract void UpdateState(ArmedState state); @@ -90,6 +96,11 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public virtual Color4 AccentColour { get; set; } + /// + /// Whether this hit object and all of its nested hit objects have been judged. + /// + public sealed override bool Judged => base.Judged && NestedHitObjects.All(h => h.Judged); + protected DrawableHitObject(TObject hitObject) { HitObject = hitObject; @@ -172,15 +183,11 @@ namespace osu.Game.Rulesets.Objects.Drawables } } - private List> nestedHitObjects; - + private List> nestedHitObjects = new List>(); protected IEnumerable> NestedHitObjects => nestedHitObjects; protected void AddNested(DrawableHitObject h) { - if (nestedHitObjects == null) - nestedHitObjects = new List>(); - h.OnJudgement += d => OnJudgement?.Invoke(d); nestedHitObjects.Add(h); } diff --git a/osu.Game/Rulesets/UI/HitRenderer.cs b/osu.Game/Rulesets/UI/HitRenderer.cs index 8ee67df95a..bae8c5e75b 100644 --- a/osu.Game/Rulesets/UI/HitRenderer.cs +++ b/osu.Game/Rulesets/UI/HitRenderer.cs @@ -188,7 +188,7 @@ namespace osu.Game.Rulesets.UI public sealed override bool ProvidingUserCursor => !HasReplayLoaded && Playfield.ProvidingUserCursor; protected override Container Content => content; - protected override bool AllObjectsJudged => Playfield.HitObjects.Children.All(h => h.Judgement.Result != HitResult.None); + protected override bool AllObjectsJudged => Playfield.HitObjects.Children.All(h => h.Judged); /// /// The playfield. From 62656b98dffd155d752a37fa86ca6ec2f6d1aa1b Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 10 May 2017 20:39:13 +0900 Subject: [PATCH 06/40] Internalize HitObjects to playfields, since some playfields may not use that container. --- osu.Game/Rulesets/UI/HitRenderer.cs | 11 ++++++++--- osu.Game/Rulesets/UI/Playfield.cs | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/UI/HitRenderer.cs b/osu.Game/Rulesets/UI/HitRenderer.cs index bae8c5e75b..cbca4fbfa2 100644 --- a/osu.Game/Rulesets/UI/HitRenderer.cs +++ b/osu.Game/Rulesets/UI/HitRenderer.cs @@ -187,17 +187,19 @@ namespace osu.Game.Rulesets.UI public sealed override bool ProvidingUserCursor => !HasReplayLoaded && Playfield.ProvidingUserCursor; - protected override Container Content => content; - protected override bool AllObjectsJudged => Playfield.HitObjects.Children.All(h => h.Judged); + public override IEnumerable Objects => Beatmap.HitObjects; + + protected override bool AllObjectsJudged => drawableObjects.All(o => o.Judged); /// /// The playfield. /// protected Playfield Playfield; + protected override Container Content => content; private readonly Container content; - public override IEnumerable Objects => Beatmap.HitObjects; + private List> drawableObjects = new List>(); protected HitRenderer(WorkingBeatmap beatmap) : base(beatmap) @@ -224,6 +226,8 @@ namespace osu.Game.Rulesets.UI private void loadObjects() { + drawableObjects.Clear(); + foreach (TObject h in Beatmap.HitObjects) { var drawableObject = GetVisualRepresentation(h); @@ -233,6 +237,7 @@ namespace osu.Game.Rulesets.UI drawableObject.OnJudgement += onJudgement; + drawableObjects.Add(drawableObject); Playfield.Add(drawableObject); } diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 0586c0385a..612569a9ae 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.UI /// /// The HitObjects contained in this Playfield. /// - public HitObjectContainer> HitObjects; + protected HitObjectContainer> HitObjects; internal Container ScaledContent; From 185e98aa14cd906a0d7fe6c5c9bf422b5b505688 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 11 May 2017 12:32:30 +0900 Subject: [PATCH 07/40] Add basic column conversion to ManiaBeatmapConverter. --- .../Beatmaps/ManiaBeatmapConverter.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 94984146f7..8e4fd83956 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -18,10 +18,17 @@ namespace osu.Game.Rulesets.Mania.Beatmaps protected override IEnumerable ConvertHitObject(HitObject original, Beatmap beatmap) { + int columns = (int)Math.Round(beatmap.BeatmapInfo.Difficulty.CircleSize); + + var positionData = original as IHasXPosition; + + float localWDivisor = 512.0f / columns; + int column = Math.Min((int)Math.Floor(positionData.X / localWDivisor), columns - 1); + yield return new Note { StartTime = original.StartTime, - Column = 1, + Column = column, }; } } From b10df740797f9bb9ece12cb5cd147fa9929995cd Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 11 May 2017 12:33:19 +0900 Subject: [PATCH 08/40] Full rewrite of timing section code, partially working for now. --- .../Tests/TestCaseManiaPlayfield.cs | 4 +- .../Timing/DrawableTimingSection.cs | 17 +- osu.Game.Rulesets.Mania/UI/Column.cs | 179 ++++++++---------- .../UI/ManiaHitRenderer.cs | 42 ++-- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 67 ++++++- .../UI/TimingSectionContainer.cs | 39 ++++ .../osu.Game.Rulesets.Mania.csproj | 1 + 7 files changed, 219 insertions(+), 130 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/UI/TimingSectionContainer.cs diff --git a/osu.Desktop.VisualTests/Tests/TestCaseManiaPlayfield.cs b/osu.Desktop.VisualTests/Tests/TestCaseManiaPlayfield.cs index 2d4414d19f..459f4589b5 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseManiaPlayfield.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseManiaPlayfield.cs @@ -8,6 +8,8 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.UI; using System.Linq; using System; +using System.Collections.Generic; +using osu.Game.Rulesets.Mania.Timing; namespace osu.Desktop.VisualTests.Tests { @@ -26,7 +28,7 @@ namespace osu.Desktop.VisualTests.Tests Action createPlayfield = (cols, pos) => { Clear(); - Add(new ManiaPlayfield(cols) + Add(new ManiaPlayfield(cols, new List()) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Rulesets.Mania/Timing/DrawableTimingSection.cs b/osu.Game.Rulesets.Mania/Timing/DrawableTimingSection.cs index 8dcb39ae0d..b5943c272a 100644 --- a/osu.Game.Rulesets.Mania/Timing/DrawableTimingSection.cs +++ b/osu.Game.Rulesets.Mania/Timing/DrawableTimingSection.cs @@ -1,19 +1,27 @@ // 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 osu.Framework.Graphics; using osu.Framework.Graphics.Containers; + namespace osu.Game.Rulesets.Mania.Timing { + /// + /// A container that contains hit objects within the time span of a timing section. + /// public class DrawableTimingSection : Container { - private readonly TimingSection section; + public readonly TimingSection TimingSection; public DrawableTimingSection(TimingSection section) { - this.section = section; + TimingSection = section; + + Anchor = Anchor.BottomCentre; + Origin = Anchor.BottomCentre; RelativePositionAxes = Axes.Y; Y = -(float)section.StartTime; @@ -23,5 +31,10 @@ namespace osu.Game.Rulesets.Mania.Timing RelativeCoordinateSpace = new Vector2(1, Height); } + + protected override void Update() + { + Y = (float)(Time.Current - TimingSection.StartTime); + } } } \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 681c5a5ef2..a140fa1984 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -12,14 +12,18 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Colour; using osu.Framework.Input; using osu.Game.Graphics; -using osu.Game.Rulesets.Taiko.Timing; +using osu.Game.Rulesets.Mania.Timing; +using System.Collections.Generic; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics.Primitives; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Judgements; namespace osu.Game.Rulesets.Mania.UI { public class Column : Container, IHasAccentColour { - private const float key_size = 50; - private const float key_icon_size = 10; private const float key_icon_corner_radius = 3; private const float key_icon_border_radius = 2; @@ -30,24 +34,20 @@ namespace osu.Game.Rulesets.Mania.UI private const float column_width = 45; private const float special_column_width = 70; - private const double time_span_default = 2000; - private const double time_span_min = 10; - private const double time_span_max = 20000; - private const double time_span_step = 100; - public Key Key; private readonly Box background; private readonly Container hitTargetBar; private readonly Container keyIcon; - private readonly Container timingSectionContainer; - public Column() + public readonly TimingSectionContainer TimingSectionContainer; + + public Column(IEnumerable timingSections) { RelativeSizeAxes = Axes.Y; Width = column_width; - Children = new Drawable[] + InternalChildren = new Drawable[] { background = new Box { @@ -55,96 +55,85 @@ namespace osu.Game.Rulesets.Mania.UI RelativeSizeAxes = Axes.Both, Alpha = 0.2f }, - new FillFlowContainer + new Container { - Name = "Key + hit target", + Name = "Key", Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Children = new[] + Height = ManiaPlayfield.HIT_TARGET_POSITION, + Children = new Drawable[] { - new Container + new Box { - Name = "Key", - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - RelativeSizeAxes = Axes.X, - Height = key_size, - Children = new Drawable[] - { - new Box - { - Name = "Key gradient", - RelativeSizeAxes = Axes.Both, - ColourInfo = ColourInfo.GradientVertical(Color4.Black, Color4.Black.Opacity(0)), - Alpha = 0.5f - }, - keyIcon = new Container - { - Name = "Key icon", - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(key_icon_size), - Masking = true, - CornerRadius = key_icon_corner_radius, - BorderThickness = 2, - BorderColour = Color4.White, // Not true - Children = new[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true - } - } - } - } + Name = "Key gradient", + RelativeSizeAxes = Axes.Both, + ColourInfo = ColourInfo.GradientVertical(Color4.Black, Color4.Black.Opacity(0)), + Alpha = 0.5f }, - new Container + keyIcon = new Container { - Name = "Hit target", - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - RelativeSizeAxes = Axes.X, - Height = hit_target_height, - Children = new Drawable[] + Name = "Key icon", + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(key_icon_size), + Masking = true, + CornerRadius = key_icon_corner_radius, + BorderThickness = 2, + BorderColour = Color4.White, // Not true + Children = new[] { new Box { - Name = "Background", RelativeSizeAxes = Axes.Both, - Colour = Color4.Black - }, - hitTargetBar = new Container - { - Name = "Bar", - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - RelativeSizeAxes = Axes.X, - Height = hit_target_bar_height, - Masking = true, - Children = new[] - { - new Box - { - RelativeSizeAxes = Axes.Both - } - } + Alpha = 0, + AlwaysPresent = true } } } } }, - timingSectionContainer = new Container + TimingSectionContainer = new TimingSectionContainer(timingSections) { + Name = "Hit objects", + RelativeSizeAxes = Axes.Both, Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, - RelativeSizeAxes = Axes.Both, - Y = -hit_target_bar_height, - RelativeCoordinateSpace = new Vector2(1, (float)time_span_default) + Y = -ManiaPlayfield.HIT_TARGET_POSITION + }, + new Container + { + Name = "Hit target", + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.X, + Height = hit_target_height, + Y = -ManiaPlayfield.HIT_TARGET_POSITION, + Children = new Drawable[] + { + new Box + { + Name = "Background", + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black + }, + hitTargetBar = new Container + { + Name = "Bar", + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.X, + Height = hit_target_bar_height, + Masking = true, + Children = new[] + { + new Box + { + RelativeSizeAxes = Axes.Both + } + } + } + } } }; } @@ -191,7 +180,10 @@ namespace osu.Game.Rulesets.Mania.UI } } - public void AddTimingSection(TimingSection timingSection) => timingSectionContainer.Add(new DrawableTimingSection(timingSection)); + public void Add(DrawableHitObject hitObject) + { + TimingSectionContainer.Add(hitObject); + } protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) { @@ -204,19 +196,6 @@ namespace osu.Game.Rulesets.Mania.UI keyIcon.ScaleTo(1.4f, 50, EasingTypes.OutQuint); } - if (state.Keyboard.ControlPressed) - { - switch (args.Key) - { - case Key.Minus: - timeSpan += time_span_step; - break; - case Key.Plus: - timeSpan -= time_span_step; - break; - } - } - return false; } @@ -230,15 +209,5 @@ namespace osu.Game.Rulesets.Mania.UI return false; } - - /// - /// The amount of time which the length of this column spans. - /// - private double timeSpan - { - get { return timingSectionContainer.RelativeCoordinateSpace.Y; } - set { timingSectionContainer.RelativeCoordinateSpace = new Vector2(1, (float)MathHelper.Clamp(value, time_span_min, time_span_max)); } - } } - } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs index b34442b1e1..20a7d9983e 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs @@ -12,11 +12,12 @@ using osu.Game.Rulesets.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Scoring; +using osu.Game.Rulesets.Mania.Timing; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Taiko.Timing; using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Mania.UI @@ -28,17 +29,11 @@ namespace osu.Game.Rulesets.Mania.UI public ManiaHitRenderer(WorkingBeatmap beatmap) : base(beatmap) { - // Has to be done before drawable hit objects are generated in load() - loadTimingSections(); } - private void loadTimingSections() + protected override Playfield CreatePlayfield() { - var maniaPlayfield = Playfield as ManiaPlayfield; - if (maniaPlayfield == null) - return; - - var sections = new List(); + List timingSections = new List(); // Construct all the relevant timing sections ControlPoint lastTimingChange = null; @@ -47,7 +42,7 @@ namespace osu.Game.Rulesets.Mania.UI if (point.TimingChange) lastTimingChange = point; - sections.Add(new TimingSection + timingSections.Add(new TimingSection { StartTime = point.Time, // Todo: Should this be dividing by beatlength? @@ -59,7 +54,7 @@ namespace osu.Game.Rulesets.Mania.UI double lastObjectTime = (Objects.Last() as IHasEndTime)?.EndTime ?? Objects.Last().StartTime; // Perform some post processing of the timing sections - sections = sections + timingSections = timingSections // Collapse sections after the last hit object .Where(s => s.StartTime <= lastObjectTime) // Collapse sections with the same start time @@ -69,27 +64,36 @@ namespace osu.Game.Rulesets.Mania.UI .ToList(); // Determine duration of timing sections - for (int i = 0; i < sections.Count; i++) + for (int i = 0; i < timingSections.Count; i++) { - if (i < sections.Count - 1) - sections[i].Duration = sections[i + 1].StartTime - sections[i].StartTime; + if (i < timingSections.Count - 1) + timingSections[i].Duration = timingSections[i + 1].StartTime - timingSections[i].StartTime; else { // Extra length added for the last timing section to extend past the last hitobject - double extraLength = sections[i].BeatLength * (int)sections[i].TimeSignature; - sections[i].Duration = lastObjectTime + extraLength - sections[i].StartTime; + double extraLength = timingSections[i].BeatLength * (int)timingSections[i].TimeSignature; + timingSections[i].Duration = lastObjectTime + extraLength - timingSections[i].StartTime; } } - sections.ForEach(s => maniaPlayfield.Columns.Children.ForEach(c => c.AddTimingSection(s))); + return new ManiaPlayfield(Columns ?? (int)Math.Round(Beatmap.BeatmapInfo.Difficulty.CircleSize), timingSections); } public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(this); protected override BeatmapConverter CreateBeatmapConverter() => new ManiaBeatmapConverter(); - protected override Playfield CreatePlayfield() => new ManiaPlayfield(Columns ?? (int)Math.Round(Beatmap.BeatmapInfo.Difficulty.CircleSize)); + protected override DrawableHitObject GetVisualRepresentation(ManiaHitObject h) + { + var note = h as Note; + if (note != null) + return new DrawableNote(note); - protected override DrawableHitObject GetVisualRepresentation(ManiaHitObject h) => null; + var holdNote = h as HoldNote; + if (holdNote != null) + return new DrawableHoldNote(holdNote); + + return null; + } } } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index e468d6f533..4572239b55 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -16,15 +16,23 @@ using osu.Framework.Allocation; using OpenTK.Input; using System.Linq; using System.Collections.Generic; -using osu.Game.Rulesets.Taiko.Timing; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Mania.Timing; +using osu.Framework.Input; namespace osu.Game.Rulesets.Mania.UI { public class ManiaPlayfield : Playfield { + public const float HIT_TARGET_POSITION = 50; + + private const float time_span_default = 500; + private const float time_span_min = 10; + private const float time_span_max = 20000; + private const float time_span_step = 100; + /// /// Default column keys, expanding outwards from the middle as more column are added. /// E.g. 2 columns use FJ, 4 columns use DFJK, 6 use SDFJKL, etc... @@ -48,12 +56,14 @@ namespace osu.Game.Rulesets.Mania.UI public readonly FlowContainer Columns; + private readonly TimingSectionContainer barlineContainer; + private List normalColumnColours = new List(); private Color4 specialColumnColour; private readonly int columnCount; - public ManiaPlayfield(int columnCount) + public ManiaPlayfield(int columnCount, IEnumerable timingSections) { this.columnCount = columnCount; @@ -77,18 +87,29 @@ namespace osu.Game.Rulesets.Mania.UI }, Columns = new FillFlowContainer { + Name = "Columns", RelativeSizeAxes = Axes.Y, AutoSizeAxes = Axes.X, Direction = FillDirection.Horizontal, Padding = new MarginPadding { Left = 1, Right = 1 }, Spacing = new Vector2(1, 0) + }, + barlineContainer = new TimingSectionContainer(timingSections) + { + Name = "Barlines", + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Bottom = HIT_TARGET_POSITION } } } } }; for (int i = 0; i < columnCount; i++) - Columns.Add(new Column()); + Columns.Add(new Column(timingSections)); + + TimeSpan = time_span_default; } [BackgroundDependencyLoader] @@ -162,5 +183,45 @@ namespace osu.Game.Rulesets.Mania.UI } public override void Add(DrawableHitObject h) => Columns.Children.ElementAt(h.HitObject.Column).Add(h); + + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (args.Repeat) + return false; + + if (state.Keyboard.ControlPressed) + { + switch (args.Key) + { + case Key.Minus: + TimeSpan += time_span_step; + break; + case Key.Plus: + TimeSpan -= time_span_step; + break; + } + } + + return false; + } + + private double timeSpan; + /// + /// The amount of time which the length of the playfield spans. + /// + public double TimeSpan + { + get { return timeSpan; } + set + { + if (timeSpan == value) + return; + timeSpan = value; + + barlineContainer.TimeSpan = value; + Columns.Children.ForEach(c => c.TimingSectionContainer.TimeSpan = value); + } + } + } } diff --git a/osu.Game.Rulesets.Mania/UI/TimingSectionContainer.cs b/osu.Game.Rulesets.Mania/UI/TimingSectionContainer.cs new file mode 100644 index 0000000000..378d4279e5 --- /dev/null +++ b/osu.Game.Rulesets.Mania/UI/TimingSectionContainer.cs @@ -0,0 +1,39 @@ +// 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.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Mania.Judgements; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Timing; +using osu.Game.Rulesets.Objects.Drawables; + +namespace osu.Game.Rulesets.Mania.UI +{ + public class TimingSectionContainer : Container + { + /// + /// The amount of time which the length of this container spans. + /// + public double TimeSpan + { + get { return RelativeCoordinateSpace.Y; } + set { RelativeCoordinateSpace = new Vector2(1, (float)value); } + } + + public TimingSectionContainer(IEnumerable timingSections) + { + Children = timingSections.Select(t => new DrawableTimingSection(t)); + } + + public void Add(Drawable drawable) + { + var section = Children.LastOrDefault(t => t.TimingSection.StartTime <= drawable.Y) ?? Children.First(); + drawable.Y -= (float)section.TimingSection.StartTime; + section.Add(drawable); + } + } +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index f745845f6e..e1d033c214 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -70,6 +70,7 @@ + From 8160f36a48b39f051180e6db1e0d9c463497a178 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 11 May 2017 12:56:51 +0900 Subject: [PATCH 09/40] Fix notes scrolling from end of map -> start of map. --- .../Objects/Drawables/DrawableManiaHitObject.cs | 4 ++-- osu.Game.Rulesets.Mania/UI/TimingSectionContainer.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index f33a6fe699..14d930893f 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -23,11 +23,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { HitObject = hitObject; - Anchor = Anchor.TopCentre; + Anchor = Anchor.BottomCentre; Origin = Anchor.BottomCentre; RelativePositionAxes = Axes.Y; - Y = (float)HitObject.StartTime; + Y = (float)-HitObject.StartTime; Add(glowContainer = new Container { diff --git a/osu.Game.Rulesets.Mania/UI/TimingSectionContainer.cs b/osu.Game.Rulesets.Mania/UI/TimingSectionContainer.cs index 378d4279e5..a43d107341 100644 --- a/osu.Game.Rulesets.Mania/UI/TimingSectionContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/TimingSectionContainer.cs @@ -31,8 +31,8 @@ namespace osu.Game.Rulesets.Mania.UI public void Add(Drawable drawable) { - var section = Children.LastOrDefault(t => t.TimingSection.StartTime <= drawable.Y) ?? Children.First(); - drawable.Y -= (float)section.TimingSection.StartTime; + var section = Children.LastOrDefault(t => t.Y >= drawable.Y) ?? Children.First(); + drawable.Y -= (float)section.Y; section.Add(drawable); } } From 7fcbf2d8d4dfc8c472f056352ce9bfea82cd3bb2 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 11 May 2017 12:57:07 +0900 Subject: [PATCH 10/40] Add t=0 display to notes. --- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 57990f2738..393ddfb3e0 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -41,6 +41,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables } } + protected override void Update() + { + if (Time.Current > HitObject.StartTime) + Colour = Color4.Green; + } + protected override void UpdateState(ArmedState state) { } From a6b71f8ccbe5c7442be11b5dd3351fbeab25fdb6 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 11 May 2017 14:11:52 +0900 Subject: [PATCH 11/40] Resharper fixes. --- .../Tests/TestCaseManiaHitObjects.cs | 5 ----- .../Beatmaps/ManiaBeatmapConverter.cs | 1 - .../Objects/Drawables/DrawableHoldNote.cs | 11 ++++------- .../Objects/Drawables/DrawableManiaHitObject.cs | 3 +-- .../Objects/Drawables/DrawableNote.cs | 7 ++----- .../Objects/Drawables/Pieces/BodyPiece.cs | 3 +-- .../Objects/Drawables/Pieces/NotePiece.cs | 2 +- .../Timing/DrawableTimingSection.cs | 2 -- osu.Game.Rulesets.Mania/UI/Column.cs | 2 -- osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs | 2 -- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 1 - osu.Game.Rulesets.Mania/UI/TimingSectionContainer.cs | 5 +---- .../Rulesets/Objects/Drawables/DrawableHitObject.cs | 2 +- osu.Game/Rulesets/UI/HitRenderer.cs | 2 +- 14 files changed, 12 insertions(+), 36 deletions(-) diff --git a/osu.Desktop.VisualTests/Tests/TestCaseManiaHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseManiaHitObjects.cs index 97c65b799b..4368e8488c 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseManiaHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseManiaHitObjects.cs @@ -6,11 +6,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using OpenTK.Graphics; using OpenTK; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 8e4fd83956..08ee8c0bf8 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -8,7 +8,6 @@ using System; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Beatmaps; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Mania.Objects.Drawables; namespace osu.Game.Rulesets.Mania.Beatmaps { diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index b6943a95ce..61dc2638a6 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -1,21 +1,18 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Graphics; -using osu.Framework.Allocation; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using OpenTK.Graphics; -using osu.Framework.Graphics.Containers; namespace osu.Game.Rulesets.Mania.Objects.Drawables { public class DrawableHoldNote : DrawableManiaHitObject { - private NotePiece headPiece; - private BodyPiece bodyPiece; - private NotePiece tailPiece; + private readonly NotePiece headPiece; + private readonly BodyPiece bodyPiece; + private readonly NotePiece tailPiece; public DrawableHoldNote(HoldNote hitObject) : base(hitObject) @@ -52,7 +49,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables public override Color4 AccentColour { - get { return AccentColour; } + get { return base.AccentColour; } set { if (base.AccentColour == value) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 14d930893f..e3b28c8aca 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -18,7 +17,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables private readonly Container glowContainer; - public DrawableManiaHitObject(TObject hitObject) + protected DrawableManiaHitObject(TObject hitObject) : base(hitObject) { HitObject = hitObject; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 393ddfb3e0..8832fc8d48 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -2,10 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; -using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Objects.Drawables; @@ -13,7 +10,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { public class DrawableNote : DrawableManiaHitObject { - private NotePiece headPiece; + private readonly NotePiece headPiece; public DrawableNote(Note hitObject) : base(hitObject) @@ -30,7 +27,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables public override Color4 AccentColour { - get { return AccentColour; } + get { return base.AccentColour; } set { if (base.AccentColour == value) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs index ac2b7df06f..ce61a7a86f 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.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 OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -15,7 +14,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces /// internal class BodyPiece : Container, IHasAccentColour { - private Box box; + private readonly Box box; public BodyPiece() { diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs index 2584682833..e01199e929 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces private const float head_height = 10; private const float head_colour_height = 6; - private Box colouredBox; + private readonly Box colouredBox; public NotePiece() { diff --git a/osu.Game.Rulesets.Mania/Timing/DrawableTimingSection.cs b/osu.Game.Rulesets.Mania/Timing/DrawableTimingSection.cs index b5943c272a..2225a63cdf 100644 --- a/osu.Game.Rulesets.Mania/Timing/DrawableTimingSection.cs +++ b/osu.Game.Rulesets.Mania/Timing/DrawableTimingSection.cs @@ -1,12 +1,10 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; - namespace osu.Game.Rulesets.Mania.Timing { /// diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index a140fa1984..abfa3c921b 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -14,8 +14,6 @@ using osu.Framework.Input; using osu.Game.Graphics; using osu.Game.Rulesets.Mania.Timing; using System.Collections.Generic; -using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.Graphics.Primitives; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Judgements; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs index 20a7d9983e..b6dae3dfe9 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs @@ -4,8 +4,6 @@ using System; using System.Collections.Generic; using System.Linq; -using osu.Framework.Allocation; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Timing; using osu.Game.Rulesets.Beatmaps; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 4572239b55..8cf792dbb0 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -18,7 +18,6 @@ using System.Linq; using System.Collections.Generic; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Timing; using osu.Framework.Input; diff --git a/osu.Game.Rulesets.Mania/UI/TimingSectionContainer.cs b/osu.Game.Rulesets.Mania/UI/TimingSectionContainer.cs index a43d107341..9a63c17c59 100644 --- a/osu.Game.Rulesets.Mania/UI/TimingSectionContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/TimingSectionContainer.cs @@ -6,10 +6,7 @@ using System.Linq; using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Mania.Judgements; -using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Timing; -using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Mania.UI { @@ -32,7 +29,7 @@ namespace osu.Game.Rulesets.Mania.UI public void Add(Drawable drawable) { var section = Children.LastOrDefault(t => t.Y >= drawable.Y) ?? Children.First(); - drawable.Y -= (float)section.Y; + drawable.Y -= section.Y; section.Add(drawable); } } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index f443b5e279..8e153415c7 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -183,7 +183,7 @@ namespace osu.Game.Rulesets.Objects.Drawables } } - private List> nestedHitObjects = new List>(); + private readonly List> nestedHitObjects = new List>(); protected IEnumerable> NestedHitObjects => nestedHitObjects; protected void AddNested(DrawableHitObject h) diff --git a/osu.Game/Rulesets/UI/HitRenderer.cs b/osu.Game/Rulesets/UI/HitRenderer.cs index cbca4fbfa2..52b7a2766a 100644 --- a/osu.Game/Rulesets/UI/HitRenderer.cs +++ b/osu.Game/Rulesets/UI/HitRenderer.cs @@ -199,7 +199,7 @@ namespace osu.Game.Rulesets.UI protected override Container Content => content; private readonly Container content; - private List> drawableObjects = new List>(); + private readonly List> drawableObjects = new List>(); protected HitRenderer(WorkingBeatmap beatmap) : base(beatmap) From 623912b40a0f5b246cbdcd5caa155c0ca9546fcf Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 11 May 2017 14:26:00 +0900 Subject: [PATCH 12/40] Fix playfield position. --- osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs | 12 ++++++++++-- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 4 ++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs index b6dae3dfe9..6a047b4997 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs @@ -4,6 +4,8 @@ using System; using System.Collections.Generic; using System.Linq; +using OpenTK; +using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Timing; using osu.Game.Rulesets.Beatmaps; @@ -31,7 +33,7 @@ namespace osu.Game.Rulesets.Mania.UI protected override Playfield CreatePlayfield() { - List timingSections = new List(); + var timingSections = new List(); // Construct all the relevant timing sections ControlPoint lastTimingChange = null; @@ -74,7 +76,11 @@ namespace osu.Game.Rulesets.Mania.UI } } - return new ManiaPlayfield(Columns ?? (int)Math.Round(Beatmap.BeatmapInfo.Difficulty.CircleSize), timingSections); + return new ManiaPlayfield(Columns ?? (int)Math.Round(Beatmap.BeatmapInfo.Difficulty.CircleSize), timingSections) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }; } public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(this); @@ -93,5 +99,7 @@ namespace osu.Game.Rulesets.Mania.UI return null; } + + protected override Vector2 GetPlayfieldAspectAdjust() => new Vector2(1, 0.8f); } } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 8cf792dbb0..75c1140a9a 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -73,8 +73,8 @@ namespace osu.Game.Rulesets.Mania.UI { new Container { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, RelativeSizeAxes = Axes.Y, AutoSizeAxes = Axes.X, Children = new Drawable[] From da4be2f9d614f31ec845486285f7fd2a25ecd112 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 11 May 2017 14:32:31 +0900 Subject: [PATCH 13/40] Move notes above judgement area but below keys. --- osu.Game.Rulesets.Mania/UI/Column.cs | 84 ++++++++++++++-------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index abfa3c921b..4f89d3b634 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -54,6 +54,48 @@ namespace osu.Game.Rulesets.Mania.UI Alpha = 0.2f }, new Container + { + Name = "Hit target", + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.X, + Height = hit_target_height, + Y = -ManiaPlayfield.HIT_TARGET_POSITION, + Children = new Drawable[] + { + new Box + { + Name = "Background", + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black + }, + hitTargetBar = new Container + { + Name = "Bar", + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.X, + Height = hit_target_bar_height, + Masking = true, + Children = new[] + { + new Box + { + RelativeSizeAxes = Axes.Both + } + } + } + } + }, + TimingSectionContainer = new TimingSectionContainer(timingSections) + { + Name = "Hit objects", + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Y = -ManiaPlayfield.HIT_TARGET_POSITION + }, + new Container { Name = "Key", Anchor = Anchor.BottomCentre, @@ -90,48 +132,6 @@ namespace osu.Game.Rulesets.Mania.UI } } } - }, - TimingSectionContainer = new TimingSectionContainer(timingSections) - { - Name = "Hit objects", - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Y = -ManiaPlayfield.HIT_TARGET_POSITION - }, - new Container - { - Name = "Hit target", - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - RelativeSizeAxes = Axes.X, - Height = hit_target_height, - Y = -ManiaPlayfield.HIT_TARGET_POSITION, - Children = new Drawable[] - { - new Box - { - Name = "Background", - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black - }, - hitTargetBar = new Container - { - Name = "Bar", - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - RelativeSizeAxes = Axes.X, - Height = hit_target_bar_height, - Masking = true, - Children = new[] - { - new Box - { - RelativeSizeAxes = Axes.Both - } - } - } - } } }; } From 3118dad52b2aa7173f10858f201dd9cea9e42733 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 11 May 2017 15:05:21 +0900 Subject: [PATCH 14/40] Subtract out playfield/hitrenderer/drawablehitobject changes. --- .../Objects/Drawables/DrawableHitObject.cs | 23 +++++-------------- osu.Game/Rulesets/UI/HitRenderer.cs | 11 +++------ osu.Game/Rulesets/UI/Playfield.cs | 2 +- 3 files changed, 10 insertions(+), 26 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 8e153415c7..a300eeab31 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -12,7 +12,6 @@ using Container = osu.Framework.Graphics.Containers.Container; using osu.Game.Rulesets.Objects.Types; using OpenTK.Graphics; using osu.Game.Audio; -using System.Linq; namespace osu.Game.Rulesets.Objects.Drawables { @@ -25,11 +24,6 @@ namespace osu.Game.Rulesets.Objects.Drawables public TJudgement Judgement; - /// - /// Whether this hit object has been judged. - /// - public virtual bool Judged => (Judgement?.Result ?? HitResult.None) != HitResult.None; - protected abstract TJudgement CreateJudgement(); protected abstract void UpdateState(ArmedState state); @@ -55,10 +49,6 @@ namespace osu.Game.Rulesets.Objects.Drawables } } - internal DrawableHitObject() - { - } - protected List Samples = new List(); protected void PlaySamples() @@ -94,12 +84,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// The colour used for various elements of this DrawableHitObject. /// - public virtual Color4 AccentColour { get; set; } - - /// - /// Whether this hit object and all of its nested hit objects have been judged. - /// - public sealed override bool Judged => base.Judged && NestedHitObjects.All(h => h.Judged); + public Color4 AccentColour { get; protected set; } protected DrawableHitObject(TObject hitObject) { @@ -183,11 +168,15 @@ namespace osu.Game.Rulesets.Objects.Drawables } } - private readonly List> nestedHitObjects = new List>(); + private List> nestedHitObjects; + protected IEnumerable> NestedHitObjects => nestedHitObjects; protected void AddNested(DrawableHitObject h) { + if (nestedHitObjects == null) + nestedHitObjects = new List>(); + h.OnJudgement += d => OnJudgement?.Invoke(d); nestedHitObjects.Add(h); } diff --git a/osu.Game/Rulesets/UI/HitRenderer.cs b/osu.Game/Rulesets/UI/HitRenderer.cs index 52b7a2766a..8ee67df95a 100644 --- a/osu.Game/Rulesets/UI/HitRenderer.cs +++ b/osu.Game/Rulesets/UI/HitRenderer.cs @@ -187,19 +187,17 @@ namespace osu.Game.Rulesets.UI public sealed override bool ProvidingUserCursor => !HasReplayLoaded && Playfield.ProvidingUserCursor; - public override IEnumerable Objects => Beatmap.HitObjects; - - protected override bool AllObjectsJudged => drawableObjects.All(o => o.Judged); + protected override Container Content => content; + protected override bool AllObjectsJudged => Playfield.HitObjects.Children.All(h => h.Judgement.Result != HitResult.None); /// /// The playfield. /// protected Playfield Playfield; - protected override Container Content => content; private readonly Container content; - private readonly List> drawableObjects = new List>(); + public override IEnumerable Objects => Beatmap.HitObjects; protected HitRenderer(WorkingBeatmap beatmap) : base(beatmap) @@ -226,8 +224,6 @@ namespace osu.Game.Rulesets.UI private void loadObjects() { - drawableObjects.Clear(); - foreach (TObject h in Beatmap.HitObjects) { var drawableObject = GetVisualRepresentation(h); @@ -237,7 +233,6 @@ namespace osu.Game.Rulesets.UI drawableObject.OnJudgement += onJudgement; - drawableObjects.Add(drawableObject); Playfield.Add(drawableObject); } diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 612569a9ae..0586c0385a 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.UI /// /// The HitObjects contained in this Playfield. /// - protected HitObjectContainer> HitObjects; + public HitObjectContainer> HitObjects; internal Container ScaledContent; From c0c33c09abbe851165eadca6ef962fcb9e5dd7a1 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 11 May 2017 15:40:51 +0900 Subject: [PATCH 15/40] Fix merge error. --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 45ef2553b5..f671e2af60 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -90,7 +90,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// The colour used for various elements of this DrawableHitObject. /// - public Color4 AccentColour { get; protected set; } + public virtual Color4 AccentColour { get; set; } /// /// Whether this hit object and all of its nested hit objects have been judged. From 5f30a89f763f4289653a184f6d8ef35fe650d182 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 11 May 2017 16:09:48 +0900 Subject: [PATCH 16/40] General refactoring + renaming of TimingSectionContainer. --- .../Timing/DrawableTimingSection.cs | 27 ----- .../Timing/TimeRelativeContainer.cs | 102 ++++++++++++++++++ osu.Game.Rulesets.Mania/UI/Column.cs | 4 +- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 4 +- .../UI/TimingSectionContainer.cs | 36 ------- .../osu.Game.Rulesets.Mania.csproj | 2 +- 6 files changed, 107 insertions(+), 68 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs delete mode 100644 osu.Game.Rulesets.Mania/UI/TimingSectionContainer.cs diff --git a/osu.Game.Rulesets.Mania/Timing/DrawableTimingSection.cs b/osu.Game.Rulesets.Mania/Timing/DrawableTimingSection.cs index 2225a63cdf..0ffdb837f2 100644 --- a/osu.Game.Rulesets.Mania/Timing/DrawableTimingSection.cs +++ b/osu.Game.Rulesets.Mania/Timing/DrawableTimingSection.cs @@ -7,32 +7,5 @@ using osu.Framework.Graphics.Containers; namespace osu.Game.Rulesets.Mania.Timing { - /// - /// A container that contains hit objects within the time span of a timing section. - /// - public class DrawableTimingSection : Container - { - public readonly TimingSection TimingSection; - public DrawableTimingSection(TimingSection section) - { - TimingSection = section; - - Anchor = Anchor.BottomCentre; - Origin = Anchor.BottomCentre; - - RelativePositionAxes = Axes.Y; - Y = -(float)section.StartTime; - - RelativeSizeAxes = Axes.Both; - Height = (float)section.Duration; - - RelativeCoordinateSpace = new Vector2(1, Height); - } - - protected override void Update() - { - Y = (float)(Time.Current - TimingSection.StartTime); - } - } } \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs b/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs new file mode 100644 index 0000000000..d3fcb56174 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs @@ -0,0 +1,102 @@ +// 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.Graphics; +using osu.Framework.Graphics.Containers; +using OpenTK; + +namespace osu.Game.Rulesets.Mania.Timing +{ + /// + /// A container in which the Y-relative coordinate space is spanned by a length of time. + /// + /// This container contains s which scroll inside this container. + /// Drawables added to this container are moved inside the relevant , + /// and as such, will scroll along with the s. + /// + /// + public class TimeRelativeContainer : Container + { + /// + /// The amount of time which the height of this container spans. + /// + public double TimeSpan + { + get { return RelativeCoordinateSpace.Y; } + set { RelativeCoordinateSpace = new Vector2(1, (float)value); } + } + + public TimeRelativeContainer(IEnumerable timingSections) + { + Children = timingSections.Select(t => new DrawableTimingSection(t)); + } + + /// + /// Adds a drawable to this container. Note that the drawable added must have a + /// Y-position as a time relative to this container. + /// + /// The drawable to add. + public override void Add(Drawable drawable) + { + // Always add timing sections to ourselves + if (drawable is DrawableTimingSection) + { + base.Add(drawable); + return; + } + + var section = (Children.LastOrDefault(t => t.Y >= drawable.Y) ?? Children.First()) as DrawableTimingSection; + + if (section == null) + throw new Exception("Could not find suitable timing section to add object to."); + + section.Add(drawable); + } + + /// + /// A container that contains drawables within the time span of a timing section. + /// + /// Scrolls relative to the current time. + /// + /// + private class DrawableTimingSection : Container + { + private readonly TimingSection section; + + public DrawableTimingSection(TimingSection section) + { + this.section = section; + + Anchor = Anchor.BottomCentre; + Origin = Anchor.BottomCentre; + + RelativePositionAxes = Axes.Y; + Y = -(float)section.StartTime; + + RelativeSizeAxes = Axes.Both; + Height = (float)section.Duration; + + RelativeCoordinateSpace = new Vector2(1, Height); + } + + protected override void Update() + { + Y = (float)(Time.Current - section.StartTime); + } + + public override void Add(Drawable drawable) + { + // The previously relatively-positioned drawable will now become relative to us, but since the drawable has no knowledge of us, + // we need to offset it back by our position so that it becomes correctly relatively-positioned to us + // This can be removed if hit objects were stored such that either their StartTime or their "beat offset" was relative to the timing section + // they belonged to, but this requires a radical change to the beatmap format which we're not ready to do just yet + drawable.Y -= Y; + + base.Add(drawable); + } + } + } +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 4f89d3b634..96f4b17ff8 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Mania.UI private readonly Container hitTargetBar; private readonly Container keyIcon; - public readonly TimingSectionContainer TimingSectionContainer; + public readonly TimeRelativeContainer TimingSectionContainer; public Column(IEnumerable timingSections) { @@ -87,7 +87,7 @@ namespace osu.Game.Rulesets.Mania.UI } } }, - TimingSectionContainer = new TimingSectionContainer(timingSections) + TimingSectionContainer = new TimeRelativeContainer(timingSections) { Name = "Hit objects", RelativeSizeAxes = Axes.Both, diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 75c1140a9a..826f7262f6 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Mania.UI public readonly FlowContainer Columns; - private readonly TimingSectionContainer barlineContainer; + private readonly TimeRelativeContainer barlineContainer; private List normalColumnColours = new List(); private Color4 specialColumnColour; @@ -93,7 +93,7 @@ namespace osu.Game.Rulesets.Mania.UI Padding = new MarginPadding { Left = 1, Right = 1 }, Spacing = new Vector2(1, 0) }, - barlineContainer = new TimingSectionContainer(timingSections) + barlineContainer = new TimeRelativeContainer(timingSections) { Name = "Barlines", Anchor = Anchor.BottomCentre, diff --git a/osu.Game.Rulesets.Mania/UI/TimingSectionContainer.cs b/osu.Game.Rulesets.Mania/UI/TimingSectionContainer.cs deleted file mode 100644 index 9a63c17c59..0000000000 --- a/osu.Game.Rulesets.Mania/UI/TimingSectionContainer.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/master/LICENCE - -using System.Collections.Generic; -using System.Linq; -using OpenTK; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Mania.Timing; - -namespace osu.Game.Rulesets.Mania.UI -{ - public class TimingSectionContainer : Container - { - /// - /// The amount of time which the length of this container spans. - /// - public double TimeSpan - { - get { return RelativeCoordinateSpace.Y; } - set { RelativeCoordinateSpace = new Vector2(1, (float)value); } - } - - public TimingSectionContainer(IEnumerable timingSections) - { - Children = timingSections.Select(t => new DrawableTimingSection(t)); - } - - public void Add(Drawable drawable) - { - var section = Children.LastOrDefault(t => t.Y >= drawable.Y) ?? Children.First(); - drawable.Y -= section.Y; - section.Add(drawable); - } - } -} \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index e1d033c214..948f25a80b 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -70,7 +70,7 @@ - + From 5dd83067ee7f7bd39f21b67bded173f6a0cc5bc5 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 11 May 2017 17:41:00 +0900 Subject: [PATCH 17/40] Fix line endings. --- .../Timing/TimeRelativeContainer.cs | 100 +++++++++--------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs b/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs index d3fcb56174..d4705c2352 100644 --- a/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs +++ b/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs @@ -1,67 +1,67 @@ -// 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.Graphics; -using osu.Framework.Graphics.Containers; -using OpenTK; - -namespace osu.Game.Rulesets.Mania.Timing +// 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.Graphics; +using osu.Framework.Graphics.Containers; +using OpenTK; + +namespace osu.Game.Rulesets.Mania.Timing { /// - /// A container in which the Y-relative coordinate space is spanned by a length of time. - /// - /// This container contains s which scroll inside this container. + /// A container in which the Y-relative coordinate space is spanned by a length of time. + /// + /// This container contains s which scroll inside this container. /// Drawables added to this container are moved inside the relevant , - /// and as such, will scroll along with the s. + /// and as such, will scroll along with the s. /// /// public class TimeRelativeContainer : Container - { - /// - /// The amount of time which the height of this container spans. - /// - public double TimeSpan - { - get { return RelativeCoordinateSpace.Y; } - set { RelativeCoordinateSpace = new Vector2(1, (float)value); } - } - - public TimeRelativeContainer(IEnumerable timingSections) + { + /// + /// The amount of time which the height of this container spans. + /// + public double TimeSpan { - Children = timingSections.Select(t => new DrawableTimingSection(t)); + get { return RelativeCoordinateSpace.Y; } + set { RelativeCoordinateSpace = new Vector2(1, (float)value); } } - /// - /// Adds a drawable to this container. Note that the drawable added must have a - /// Y-position as a time relative to this container. - /// - /// The drawable to add. - public override void Add(Drawable drawable) + public TimeRelativeContainer(IEnumerable timingSections) + { + Children = timingSections.Select(t => new DrawableTimingSection(t)); + } + + /// + /// Adds a drawable to this container. Note that the drawable added must have a + /// Y-position as a time relative to this container. + /// + /// The drawable to add. + public override void Add(Drawable drawable) { // Always add timing sections to ourselves - if (drawable is DrawableTimingSection) - { + if (drawable is DrawableTimingSection) + { base.Add(drawable); - return; + return; } - - var section = (Children.LastOrDefault(t => t.Y >= drawable.Y) ?? Children.First()) as DrawableTimingSection; - - if (section == null) + + var section = (Children.LastOrDefault(t => t.Y >= drawable.Y) ?? Children.First()) as DrawableTimingSection; + + if (section == null) throw new Exception("Could not find suitable timing section to add object to."); - - section.Add(drawable); + + section.Add(drawable); } - /// + /// /// A container that contains drawables within the time span of a timing section. /// /// Scrolls relative to the current time. - /// - /// + /// + /// private class DrawableTimingSection : Container { private readonly TimingSection section; @@ -93,10 +93,10 @@ namespace osu.Game.Rulesets.Mania.Timing // we need to offset it back by our position so that it becomes correctly relatively-positioned to us // This can be removed if hit objects were stored such that either their StartTime or their "beat offset" was relative to the timing section // they belonged to, but this requires a radical change to the beatmap format which we're not ready to do just yet - drawable.Y -= Y; - - base.Add(drawable); + drawable.Y -= Y; + + base.Add(drawable); } - } - } + } + } } \ No newline at end of file From 6a79c8b66c2595b0a1d5a3766e0ea2bff21db035 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 11 May 2017 19:57:24 +0900 Subject: [PATCH 18/40] Make notes scroll with beat length. --- .../Timing/TimeRelativeContainer.cs | 53 +++++++++++++++---- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 6 +-- 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs b/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs index d4705c2352..06e7cd1f53 100644 --- a/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs +++ b/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs @@ -29,9 +29,13 @@ namespace osu.Game.Rulesets.Mania.Timing set { RelativeCoordinateSpace = new Vector2(1, (float)value); } } + private readonly List drawableTimingSections; + public TimeRelativeContainer(IEnumerable timingSections) { - Children = timingSections.Select(t => new DrawableTimingSection(t)); + drawableTimingSections = timingSections.Select(t => new DrawableTimingSection(t)).ToList(); + + Children = drawableTimingSections; } /// @@ -48,7 +52,7 @@ namespace osu.Game.Rulesets.Mania.Timing return; } - var section = (Children.LastOrDefault(t => t.Y >= drawable.Y) ?? Children.First()) as DrawableTimingSection; + var section = drawableTimingSections.LastOrDefault(t => t.CanContain(drawable)) ?? drawableTimingSections.First(); if (section == null) throw new Exception("Could not find suitable timing section to add object to."); @@ -59,13 +63,28 @@ namespace osu.Game.Rulesets.Mania.Timing /// /// A container that contains drawables within the time span of a timing section. /// - /// Scrolls relative to the current time. + /// The content of this container will scroll relative to the current time. /// /// private class DrawableTimingSection : Container { + protected override Container Content => content; + /// + /// The container which will scroll relative to the current time. + /// + private readonly Container content; + private readonly TimingSection section; + /// + /// Creates a drawable timing section. The height of this container will be proportional + /// to the beat length of the timing section and the timespan of its parent at all times. + /// + /// This is so that, e.g. a beat length of 500ms results in this container being twice as high as its parent, + /// which means that the content container will scroll at twice the normal rate. + /// + /// + /// The section to create the drawable timing section for. public DrawableTimingSection(TimingSection section) { this.section = section; @@ -73,18 +92,30 @@ namespace osu.Game.Rulesets.Mania.Timing Anchor = Anchor.BottomCentre; Origin = Anchor.BottomCentre; - RelativePositionAxes = Axes.Y; - Y = -(float)section.StartTime; - RelativeSizeAxes = Axes.Both; - Height = (float)section.Duration; - RelativeCoordinateSpace = new Vector2(1, Height); + AddInternal(content = new Container + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + RelativePositionAxes = Axes.Both, + RelativeSizeAxes = Axes.Both, + Y = -(float)section.StartTime, + Height = (float)section.Duration, + RelativeCoordinateSpace = new Vector2(1, (float)section.Duration) + }); } protected override void Update() { - Y = (float)(Time.Current - section.StartTime); + var parent = (TimeRelativeContainer)Parent; + + // Adjust our height to account for the speed changes + Height = (float)(parent.TimeSpan * 1000 / section.BeatLength); + RelativeCoordinateSpace = new Vector2(1, (float)parent.TimeSpan); + + // Scroll the content + content.Y = (float)(Time.Current - section.StartTime); } public override void Add(Drawable drawable) @@ -93,10 +124,12 @@ namespace osu.Game.Rulesets.Mania.Timing // we need to offset it back by our position so that it becomes correctly relatively-positioned to us // This can be removed if hit objects were stored such that either their StartTime or their "beat offset" was relative to the timing section // they belonged to, but this requires a radical change to the beatmap format which we're not ready to do just yet - drawable.Y -= Y; + drawable.Y += (float)section.StartTime; base.Add(drawable); } + + public bool CanContain(Drawable drawable) => content.Y >= drawable.Y; } } } \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 826f7262f6..7636e41099 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -27,10 +27,10 @@ namespace osu.Game.Rulesets.Mania.UI { public const float HIT_TARGET_POSITION = 50; - private const float time_span_default = 500; + private const float time_span_default = 20000; private const float time_span_min = 10; - private const float time_span_max = 20000; - private const float time_span_step = 100; + private const float time_span_max = 50000; + private const float time_span_step = 1000; /// /// Default column keys, expanding outwards from the middle as more column are added. From ee219c18db8afdc382cf83a5b585fcbbbafed19a Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 11 May 2017 20:04:28 +0900 Subject: [PATCH 19/40] Make the playfield mask for now. --- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 7636e41099..a3b1a49c9c 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -77,6 +77,7 @@ namespace osu.Game.Rulesets.Mania.UI Origin = Anchor.BottomCentre, RelativeSizeAxes = Axes.Y, AutoSizeAxes = Axes.X, + Masking = true, Children = new Drawable[] { new Box From 0739a764974d999e07bf261a2d544e477c35bba4 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 11 May 2017 20:04:45 +0900 Subject: [PATCH 20/40] Make the playfield work in TestCaseGamefield. --- osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs | 12 ++++++++++-- .../Timing/TimeRelativeContainer.cs | 2 +- osu.Game/Beatmaps/Timing/ControlPoint.cs | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs b/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs index cb15558ec3..1049a8818a 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs @@ -18,6 +18,7 @@ using osu.Game.Rulesets.Taiko.UI; using System.Collections.Generic; using osu.Desktop.VisualTests.Beatmaps; using osu.Framework.Allocation; +using osu.Game.Beatmaps.Timing; namespace osu.Desktop.VisualTests.Tests { @@ -52,6 +53,12 @@ namespace osu.Desktop.VisualTests.Tests time += RNG.Next(50, 500); } + TimingInfo timing = new TimingInfo(); + timing.ControlPoints.Add(new ControlPoint + { + BeatLength = 200 + }); + WorkingBeatmap beatmap = new TestWorkingBeatmap(new Beatmap { HitObjects = objects, @@ -64,8 +71,9 @@ namespace osu.Desktop.VisualTests.Tests Artist = @"Unknown", Title = @"Sample Beatmap", Author = @"peppy", - } - } + }, + }, + TimingInfo = timing }); Add(new Drawable[] diff --git a/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs b/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs index 06e7cd1f53..466639fc02 100644 --- a/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs +++ b/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs @@ -52,7 +52,7 @@ namespace osu.Game.Rulesets.Mania.Timing return; } - var section = drawableTimingSections.LastOrDefault(t => t.CanContain(drawable)) ?? drawableTimingSections.First(); + var section = drawableTimingSections.LastOrDefault(t => t.CanContain(drawable)) ?? drawableTimingSections.FirstOrDefault(); if (section == null) throw new Exception("Could not find suitable timing section to add object to."); diff --git a/osu.Game/Beatmaps/Timing/ControlPoint.cs b/osu.Game/Beatmaps/Timing/ControlPoint.cs index ea152ccb39..fbae7d9614 100644 --- a/osu.Game/Beatmaps/Timing/ControlPoint.cs +++ b/osu.Game/Beatmaps/Timing/ControlPoint.cs @@ -7,7 +7,7 @@ namespace osu.Game.Beatmaps.Timing { public string SampleBank; public int SampleVolume; - public TimeSignatures TimeSignature; + public TimeSignatures TimeSignature = TimeSignatures.SimpleQuadruple; public double Time; public double BeatLength = 500; public double SpeedMultiplier = 1; From f764ed89037b05eef9ed0e8801d18561ad2296b5 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 11 May 2017 20:05:11 +0900 Subject: [PATCH 21/40] Remove unused class. --- .../Timing/DrawableTimingSection.cs | 11 ----------- .../osu.Game.Rulesets.Mania.csproj | 1 - 2 files changed, 12 deletions(-) delete mode 100644 osu.Game.Rulesets.Mania/Timing/DrawableTimingSection.cs diff --git a/osu.Game.Rulesets.Mania/Timing/DrawableTimingSection.cs b/osu.Game.Rulesets.Mania/Timing/DrawableTimingSection.cs deleted file mode 100644 index 0ffdb837f2..0000000000 --- a/osu.Game.Rulesets.Mania/Timing/DrawableTimingSection.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using OpenTK; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; - -namespace osu.Game.Rulesets.Mania.Timing -{ - -} \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 948f25a80b..7ee397e0ea 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -59,7 +59,6 @@ - From 7b49ed141940128d33934d4f7100aeda830b630d Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 11 May 2017 21:57:28 +0900 Subject: [PATCH 22/40] Fix up todo. --- osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs index 6a047b4997..79fb6f8615 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs @@ -45,8 +45,7 @@ namespace osu.Game.Rulesets.Mania.UI timingSections.Add(new TimingSection { StartTime = point.Time, - // Todo: Should this be dividing by beatlength? - BeatLength = point.SpeedMultiplier * lastTimingChange.BeatLength, + BeatLength = lastTimingChange.BeatLength / point.SpeedMultiplier, TimeSignature = point.TimeSignature }); } From d57bb7e5fda5f5eeb790a04f37114451fb64917f Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 11 May 2017 22:01:37 +0900 Subject: [PATCH 23/40] General cleanups. --- .../Timing/TimeRelativeContainer.cs | 5 +++ .../Timing/TimingSection.cs | 43 +++++++++++++------ osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 2 +- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs b/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs index 466639fc02..c5060eabbb 100644 --- a/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs +++ b/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs @@ -129,6 +129,11 @@ namespace osu.Game.Rulesets.Mania.Timing base.Add(drawable); } + /// + /// Whether this timing section can contain a drawable. A timing section can contain a drawable if the drawable + /// can be placed within the timing section's bounds (in this case, from the start of the timing section up to infinity). + /// + /// The drawable to check. public bool CanContain(Drawable drawable) => content.Y >= drawable.Y; } } diff --git a/osu.Game.Rulesets.Mania/Timing/TimingSection.cs b/osu.Game.Rulesets.Mania/Timing/TimingSection.cs index fdc367de11..65a2094c46 100644 --- a/osu.Game.Rulesets.Mania/Timing/TimingSection.cs +++ b/osu.Game.Rulesets.Mania/Timing/TimingSection.cs @@ -1,15 +1,30 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Beatmaps.Timing; - -namespace osu.Game.Rulesets.Mania.Timing -{ - public class TimingSection - { - public double StartTime; - public double Duration; - public double BeatLength; - public TimeSignatures TimeSignature; - } +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Beatmaps.Timing; + +namespace osu.Game.Rulesets.Mania.Timing +{ + /// + /// A point in the map where the beat length or speed multiplier has changed . + /// + public class TimingSection + { + /// + /// The time at which the change occurred. + /// + public double StartTime; + /// + /// The duration of this timing section - lasts until the next timing section. + /// + public double Duration; + /// + /// The beat length, includes any speed multiplier. + /// + public double BeatLength; + /// + /// The time signature of this timing section. + /// + public TimeSignatures TimeSignature; + } } \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index a3b1a49c9c..46fe64ff66 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -96,7 +96,7 @@ namespace osu.Game.Rulesets.Mania.UI }, barlineContainer = new TimeRelativeContainer(timingSections) { - Name = "Barlines", + Name = "Bar lines", Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, RelativeSizeAxes = Axes.Both, From 0597a95db09c4b38baa2b2cfae8f994110898c9d Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 11 May 2017 22:16:50 +0900 Subject: [PATCH 24/40] Resharper is too smart. --- .../Beatmaps/ManiaBeatmapConverter.cs | 7 ++++--- osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs | 10 +++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 08ee8c0bf8..e51bbcdc13 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -8,6 +8,7 @@ using System; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Beatmaps; using osu.Game.Rulesets.Objects; +using OpenTK; namespace osu.Game.Rulesets.Mania.Beatmaps { @@ -17,12 +18,12 @@ namespace osu.Game.Rulesets.Mania.Beatmaps protected override IEnumerable ConvertHitObject(HitObject original, Beatmap beatmap) { - int columns = (int)Math.Round(beatmap.BeatmapInfo.Difficulty.CircleSize); + int availableColumns = (int)Math.Round(beatmap.BeatmapInfo.Difficulty.CircleSize); var positionData = original as IHasXPosition; - float localWDivisor = 512.0f / columns; - int column = Math.Min((int)Math.Floor(positionData.X / localWDivisor), columns - 1); + float localWDivisor = 512.0f / availableColumns; + int column = MathHelper.Clamp((int)Math.Floor((positionData?.X ?? 1) / localWDivisor), 0, availableColumns - 1); yield return new Note { diff --git a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs index 79fb6f8615..4cb5b8853b 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs @@ -36,7 +36,11 @@ namespace osu.Game.Rulesets.Mania.UI var timingSections = new List(); // Construct all the relevant timing sections - ControlPoint lastTimingChange = null; + ControlPoint lastTimingChange = Beatmap.TimingInfo.ControlPoints.FirstOrDefault(t => t.TimingChange); + + if (lastTimingChange == null) + throw new Exception("The Beatmap contains no timing points!"); + foreach (ControlPoint point in Beatmap.TimingInfo.ControlPoints) { if (point.TimingChange) @@ -92,10 +96,6 @@ namespace osu.Game.Rulesets.Mania.UI if (note != null) return new DrawableNote(note); - var holdNote = h as HoldNote; - if (holdNote != null) - return new DrawableHoldNote(holdNote); - return null; } From a25f11e8099ff509f7fcd6d3a655db2cd9aed3ee Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 12 May 2017 22:23:32 +0900 Subject: [PATCH 25/40] Initial removal of TimingSection. --- .../Timing/TimeRelativeContainer.cs | 44 ++++++---------- .../Timing/TimingSection.cs | 30 ----------- osu.Game.Rulesets.Mania/UI/Column.cs | 5 +- .../UI/ManiaHitRenderer.cs | 52 +++++++------------ osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 7 +-- .../osu.Game.Rulesets.Mania.csproj | 1 - 6 files changed, 40 insertions(+), 99 deletions(-) delete mode 100644 osu.Game.Rulesets.Mania/Timing/TimingSection.cs diff --git a/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs b/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs index c5060eabbb..8ca30488ff 100644 --- a/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs +++ b/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs @@ -7,15 +7,16 @@ using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using OpenTK; +using osu.Game.Beatmaps.Timing; namespace osu.Game.Rulesets.Mania.Timing { /// /// A container in which the Y-relative coordinate space is spanned by a length of time. /// - /// This container contains s which scroll inside this container. - /// Drawables added to this container are moved inside the relevant , - /// and as such, will scroll along with the s. + /// This container contains s which scroll inside this container. + /// Drawables added to this container are moved inside the relevant , + /// and as such, will scroll along with the s. /// /// public class TimeRelativeContainer : Container @@ -31,9 +32,9 @@ namespace osu.Game.Rulesets.Mania.Timing private readonly List drawableTimingSections; - public TimeRelativeContainer(IEnumerable timingSections) + public TimeRelativeContainer(IEnumerable timingChanges) { - drawableTimingSections = timingSections.Select(t => new DrawableTimingSection(t)).ToList(); + drawableTimingSections = timingChanges.Select(t => new DrawableTimingSection(t)).ToList(); Children = drawableTimingSections; } @@ -68,13 +69,7 @@ namespace osu.Game.Rulesets.Mania.Timing /// private class DrawableTimingSection : Container { - protected override Container Content => content; - /// - /// The container which will scroll relative to the current time. - /// - private readonly Container content; - - private readonly TimingSection section; + private readonly ControlPoint timingChange; /// /// Creates a drawable timing section. The height of this container will be proportional @@ -84,26 +79,17 @@ namespace osu.Game.Rulesets.Mania.Timing /// which means that the content container will scroll at twice the normal rate. /// /// - /// The section to create the drawable timing section for. - public DrawableTimingSection(TimingSection section) + /// The timing change to create the drawable timing section for. + public DrawableTimingSection(ControlPoint timingChange) { - this.section = section; + this.timingChange = timingChange; Anchor = Anchor.BottomCentre; Origin = Anchor.BottomCentre; RelativeSizeAxes = Axes.Both; - AddInternal(content = new Container - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - RelativePositionAxes = Axes.Both, - RelativeSizeAxes = Axes.Both, - Y = -(float)section.StartTime, - Height = (float)section.Duration, - RelativeCoordinateSpace = new Vector2(1, (float)section.Duration) - }); + Y = -(float)timingChange.Time; } protected override void Update() @@ -111,11 +97,11 @@ namespace osu.Game.Rulesets.Mania.Timing var parent = (TimeRelativeContainer)Parent; // Adjust our height to account for the speed changes - Height = (float)(parent.TimeSpan * 1000 / section.BeatLength); + Height = (float)(parent.TimeSpan * 1000 / timingChange.BeatLength / timingChange.SpeedMultiplier); RelativeCoordinateSpace = new Vector2(1, (float)parent.TimeSpan); // Scroll the content - content.Y = (float)(Time.Current - section.StartTime); + Y = (float)(Time.Current - timingChange.Time); } public override void Add(Drawable drawable) @@ -124,7 +110,7 @@ namespace osu.Game.Rulesets.Mania.Timing // we need to offset it back by our position so that it becomes correctly relatively-positioned to us // This can be removed if hit objects were stored such that either their StartTime or their "beat offset" was relative to the timing section // they belonged to, but this requires a radical change to the beatmap format which we're not ready to do just yet - drawable.Y += (float)section.StartTime; + drawable.Y += (float)timingChange.Time; base.Add(drawable); } @@ -134,7 +120,7 @@ namespace osu.Game.Rulesets.Mania.Timing /// can be placed within the timing section's bounds (in this case, from the start of the timing section up to infinity). /// /// The drawable to check. - public bool CanContain(Drawable drawable) => content.Y >= drawable.Y; + public bool CanContain(Drawable drawable) => Y >= drawable.Y; } } } \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/Timing/TimingSection.cs b/osu.Game.Rulesets.Mania/Timing/TimingSection.cs deleted file mode 100644 index 65a2094c46..0000000000 --- a/osu.Game.Rulesets.Mania/Timing/TimingSection.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Beatmaps.Timing; - -namespace osu.Game.Rulesets.Mania.Timing -{ - /// - /// A point in the map where the beat length or speed multiplier has changed . - /// - public class TimingSection - { - /// - /// The time at which the change occurred. - /// - public double StartTime; - /// - /// The duration of this timing section - lasts until the next timing section. - /// - public double Duration; - /// - /// The beat length, includes any speed multiplier. - /// - public double BeatLength; - /// - /// The time signature of this timing section. - /// - public TimeSignatures TimeSignature; - } -} \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 96f4b17ff8..34d241485c 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -17,6 +17,7 @@ using System.Collections.Generic; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Judgements; +using osu.Game.Beatmaps.Timing; namespace osu.Game.Rulesets.Mania.UI { @@ -40,7 +41,7 @@ namespace osu.Game.Rulesets.Mania.UI public readonly TimeRelativeContainer TimingSectionContainer; - public Column(IEnumerable timingSections) + public Column(IEnumerable timingChanges) { RelativeSizeAxes = Axes.Y; Width = column_width; @@ -87,7 +88,7 @@ namespace osu.Game.Rulesets.Mania.UI } } }, - TimingSectionContainer = new TimeRelativeContainer(timingSections) + TimingSectionContainer = new TimeRelativeContainer(timingChanges) { Name = "Hit objects", RelativeSizeAxes = Axes.Both, diff --git a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs index 4cb5b8853b..9b476c4c1a 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs @@ -33,53 +33,37 @@ namespace osu.Game.Rulesets.Mania.UI protected override Playfield CreatePlayfield() { - var timingSections = new List(); + ControlPoint firstTimingChange = Beatmap.TimingInfo.ControlPoints.FirstOrDefault(t => t.TimingChange); - // Construct all the relevant timing sections - ControlPoint lastTimingChange = Beatmap.TimingInfo.ControlPoints.FirstOrDefault(t => t.TimingChange); - - if (lastTimingChange == null) + if (firstTimingChange == null) throw new Exception("The Beatmap contains no timing points!"); - foreach (ControlPoint point in Beatmap.TimingInfo.ControlPoints) + // Generate the timing points, making non-timing changes use the previous timing change + var timingChanges = Beatmap.TimingInfo.ControlPoints.Select(c => { - if (point.TimingChange) - lastTimingChange = point; + ControlPoint t = c.Clone(); - timingSections.Add(new TimingSection - { - StartTime = point.Time, - BeatLength = lastTimingChange.BeatLength / point.SpeedMultiplier, - TimeSignature = point.TimeSignature - }); - } + if (c.TimingChange) + firstTimingChange = c; + else + t.BeatLength = firstTimingChange.BeatLength; + + return t; + }); double lastObjectTime = (Objects.Last() as IHasEndTime)?.EndTime ?? Objects.Last().StartTime; - // Perform some post processing of the timing sections - timingSections = timingSections + // Perform some post processing of the timing changes + timingChanges = timingChanges // Collapse sections after the last hit object - .Where(s => s.StartTime <= lastObjectTime) + .Where(s => s.Time <= lastObjectTime) // Collapse sections with the same start time - .GroupBy(s => s.StartTime).Select(g => g.Last()).OrderBy(s => s.StartTime) + .GroupBy(s => s.Time).Select(g => g.Last()).OrderBy(s => s.Time) // Collapse sections with the same beat length - .GroupBy(s => s.BeatLength).Select(g => g.First()) + .GroupBy(s => s.BeatLength * s.SpeedMultiplier).Select(g => g.First()) .ToList(); - // Determine duration of timing sections - for (int i = 0; i < timingSections.Count; i++) - { - if (i < timingSections.Count - 1) - timingSections[i].Duration = timingSections[i + 1].StartTime - timingSections[i].StartTime; - else - { - // Extra length added for the last timing section to extend past the last hitobject - double extraLength = timingSections[i].BeatLength * (int)timingSections[i].TimeSignature; - timingSections[i].Duration = lastObjectTime + extraLength - timingSections[i].StartTime; - } - } - - return new ManiaPlayfield(Columns ?? (int)Math.Round(Beatmap.BeatmapInfo.Difficulty.CircleSize), timingSections) + return new ManiaPlayfield(Columns ?? (int)Math.Round(Beatmap.BeatmapInfo.Difficulty.CircleSize), timingChanges) { Anchor = Anchor.Centre, Origin = Anchor.Centre diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 46fe64ff66..2461ed458f 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -20,6 +20,7 @@ using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Mania.Timing; using osu.Framework.Input; +using osu.Game.Beatmaps.Timing; namespace osu.Game.Rulesets.Mania.UI { @@ -62,7 +63,7 @@ namespace osu.Game.Rulesets.Mania.UI private readonly int columnCount; - public ManiaPlayfield(int columnCount, IEnumerable timingSections) + public ManiaPlayfield(int columnCount, IEnumerable timingChanges) { this.columnCount = columnCount; @@ -94,7 +95,7 @@ namespace osu.Game.Rulesets.Mania.UI Padding = new MarginPadding { Left = 1, Right = 1 }, Spacing = new Vector2(1, 0) }, - barlineContainer = new TimeRelativeContainer(timingSections) + barlineContainer = new TimeRelativeContainer(timingChanges) { Name = "Bar lines", Anchor = Anchor.BottomCentre, @@ -107,7 +108,7 @@ namespace osu.Game.Rulesets.Mania.UI }; for (int i = 0; i < columnCount; i++) - Columns.Add(new Column(timingSections)); + Columns.Add(new Column(timingChanges)); TimeSpan = time_span_default; } diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 7ee397e0ea..70c875fd34 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -58,7 +58,6 @@ - From da932276e87c89a8a533f1b009818aed01264be8 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 16 May 2017 17:03:43 +0900 Subject: [PATCH 26/40] Make timing sections scroll again. --- .../Objects/Drawables/DrawableHoldNote.cs | 4 -- .../Objects/Drawables/DrawableNote.cs | 4 +- .../Timing/TimeRelativeContainer.cs | 37 +++++++++++++++++-- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 61dc2638a6..f943d817a8 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -41,10 +41,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Origin = Anchor.TopCentre } }); - - // The "length" of the hold note stops at the "base" of the tail piece - // but we want to contain the tail piece within our bounds - Height += (float)HitObject.Duration / headPiece.Height; } public override Color4 AccentColour diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 8832fc8d48..a105c21e43 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -15,8 +15,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables public DrawableNote(Note hitObject) : base(hitObject) { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; + RelativeSizeAxes = Axes.Both; + Height = 100; Add(headPiece = new NotePiece { diff --git a/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs b/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs index 8ca30488ff..64b5b4e5ef 100644 --- a/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs +++ b/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs @@ -71,6 +71,9 @@ namespace osu.Game.Rulesets.Mania.Timing { private readonly ControlPoint timingChange; + protected override Container Content => content; + private readonly Container content; + /// /// Creates a drawable timing section. The height of this container will be proportional /// to the beat length of the timing section and the timespan of its parent at all times. @@ -89,7 +92,14 @@ namespace osu.Game.Rulesets.Mania.Timing RelativeSizeAxes = Axes.Both; - Y = -(float)timingChange.Time; + AddInternal(content = new AutoTimeRelativeContainer + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.Both, + RelativePositionAxes = Axes.Both, + Y = -(float)timingChange.Time + }); } protected override void Update() @@ -101,7 +111,7 @@ namespace osu.Game.Rulesets.Mania.Timing RelativeCoordinateSpace = new Vector2(1, (float)parent.TimeSpan); // Scroll the content - Y = (float)(Time.Current - timingChange.Time); + content.Y = (float)(Time.Current - timingChange.Time); } public override void Add(Drawable drawable) @@ -120,7 +130,28 @@ namespace osu.Game.Rulesets.Mania.Timing /// can be placed within the timing section's bounds (in this case, from the start of the timing section up to infinity). /// /// The drawable to check. - public bool CanContain(Drawable drawable) => Y >= drawable.Y; + public bool CanContain(Drawable drawable) => content.Y >= drawable.Y; + + private class AutoTimeRelativeContainer : Container + { + public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) + { + float height = 0; + + foreach (Drawable child in Children) + { + // Todo: This is wrong, it won't work for absolute-y-sized children + float childEndPos = -child.Y + child.Height; + if (childEndPos > height) + height = childEndPos; + } + + Height = height; + RelativeCoordinateSpace = new Vector2(1, height); + + return base.Invalidate(invalidation, source, shallPropagate); + } + } } } } \ No newline at end of file From 8d19bafc19c99e42ef431e827391369b9176ab83 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 16 May 2017 17:04:05 +0900 Subject: [PATCH 27/40] Add ability to hold down speed-changing keys. --- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 2461ed458f..2d99b4dac7 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -28,10 +28,10 @@ namespace osu.Game.Rulesets.Mania.UI { public const float HIT_TARGET_POSITION = 50; - private const float time_span_default = 20000; + private const float time_span_default = 5000; private const float time_span_min = 10; private const float time_span_max = 50000; - private const float time_span_step = 1000; + private const float time_span_step = 200; /// /// Default column keys, expanding outwards from the middle as more column are added. @@ -187,9 +187,6 @@ namespace osu.Game.Rulesets.Mania.UI protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) { - if (args.Repeat) - return false; - if (state.Keyboard.ControlPressed) { switch (args.Key) From 62139015fba89b5b835275edbd68fc89d25b7e25 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 16 May 2017 17:06:54 +0900 Subject: [PATCH 28/40] Clamp TimeSpan. --- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 2d99b4dac7..118cf610dc 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -216,6 +216,8 @@ namespace osu.Game.Rulesets.Mania.UI return; timeSpan = value; + timeSpan = MathHelper.Clamp(timeSpan, time_span_min, time_span_max); + barlineContainer.TimeSpan = value; Columns.Children.ForEach(c => c.TimingSectionContainer.TimeSpan = value); } From 703920536346066233249fa84d247c4f3f399a4f Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 16 May 2017 17:34:41 +0900 Subject: [PATCH 29/40] Invert the playfield by default to make calculations a bit simpler and clean up a lot of code. --- .../Objects/Drawables/DrawableHoldNote.cs | 12 ++-- .../Drawables/DrawableManiaHitObject.cs | 5 +- .../Objects/Drawables/DrawableNote.cs | 4 +- .../Timing/TimeRelativeContainer.cs | 16 ++--- osu.Game.Rulesets.Mania/UI/Column.cs | 62 +++++++++---------- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 19 +++--- 6 files changed, 57 insertions(+), 61 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index f943d817a8..767a2b3458 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -27,18 +27,18 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables // This will be fixed when new designs are given or the current design is finalized. bodyPiece = new BodyPiece { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, }, headPiece = new NotePiece { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre }, tailPiece = new NotePiece { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre } }); } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index e3b28c8aca..0307e9162a 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -22,11 +22,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { HitObject = hitObject; - Anchor = Anchor.BottomCentre; - Origin = Anchor.BottomCentre; - RelativePositionAxes = Axes.Y; - Y = (float)-HitObject.StartTime; + Y = (float)HitObject.StartTime; Add(glowContainer = new Container { diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index a105c21e43..b216c362f5 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -20,8 +20,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Add(headPiece = new NotePiece { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre }); } diff --git a/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs b/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs index 64b5b4e5ef..5407b083df 100644 --- a/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs +++ b/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs @@ -87,18 +87,13 @@ namespace osu.Game.Rulesets.Mania.Timing { this.timingChange = timingChange; - Anchor = Anchor.BottomCentre; - Origin = Anchor.BottomCentre; - RelativeSizeAxes = Axes.Both; AddInternal(content = new AutoTimeRelativeContainer { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, RelativeSizeAxes = Axes.Both, RelativePositionAxes = Axes.Both, - Y = -(float)timingChange.Time + Y = (float)timingChange.Time }); } @@ -111,7 +106,7 @@ namespace osu.Game.Rulesets.Mania.Timing RelativeCoordinateSpace = new Vector2(1, (float)parent.TimeSpan); // Scroll the content - content.Y = (float)(Time.Current - timingChange.Time); + content.Y = (float)(timingChange.Time - Time.Current); } public override void Add(Drawable drawable) @@ -120,7 +115,7 @@ namespace osu.Game.Rulesets.Mania.Timing // we need to offset it back by our position so that it becomes correctly relatively-positioned to us // This can be removed if hit objects were stored such that either their StartTime or their "beat offset" was relative to the timing section // they belonged to, but this requires a radical change to the beatmap format which we're not ready to do just yet - drawable.Y += (float)timingChange.Time; + drawable.Y -= (float)timingChange.Time; base.Add(drawable); } @@ -130,7 +125,7 @@ namespace osu.Game.Rulesets.Mania.Timing /// can be placed within the timing section's bounds (in this case, from the start of the timing section up to infinity). /// /// The drawable to check. - public bool CanContain(Drawable drawable) => content.Y >= drawable.Y; + public bool CanContain(Drawable drawable) => content.Y <= drawable.Y; private class AutoTimeRelativeContainer : Container { @@ -140,8 +135,7 @@ namespace osu.Game.Rulesets.Mania.Timing foreach (Drawable child in Children) { - // Todo: This is wrong, it won't work for absolute-y-sized children - float childEndPos = -child.Y + child.Height; + float childEndPos = child.Y + child.Height; if (childEndPos > height) height = childEndPos; } diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 34d241485c..8491b631c5 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -18,6 +18,7 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Beatmaps.Timing; +using osu.Framework.Graphics.Primitives; namespace osu.Game.Rulesets.Mania.UI { @@ -56,51 +57,50 @@ namespace osu.Game.Rulesets.Mania.UI }, new Container { - Name = "Hit target", - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - RelativeSizeAxes = Axes.X, - Height = hit_target_height, - Y = -ManiaPlayfield.HIT_TARGET_POSITION, + Name = "Hit target + hit objects", + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Top = ManiaPlayfield.HIT_TARGET_POSITION}, Children = new Drawable[] { - new Box + new Container { - Name = "Background", - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black - }, - hitTargetBar = new Container - { - Name = "Bar", - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, + Name = "Hit target", RelativeSizeAxes = Axes.X, - Height = hit_target_bar_height, - Masking = true, - Children = new[] + Height = hit_target_height, + Children = new Drawable[] { new Box { - RelativeSizeAxes = Axes.Both + Name = "Background", + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black + }, + hitTargetBar = new Container + { + Name = "Bar", + RelativeSizeAxes = Axes.X, + Height = hit_target_bar_height, + Masking = true, + Children = new[] + { + new Box + { + RelativeSizeAxes = Axes.Both + } + } } } - } + }, + TimingSectionContainer = new TimeRelativeContainer(timingChanges) + { + Name = "Hit objects", + RelativeSizeAxes = Axes.Both, + }, } }, - TimingSectionContainer = new TimeRelativeContainer(timingChanges) - { - Name = "Hit objects", - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Y = -ManiaPlayfield.HIT_TARGET_POSITION - }, new Container { Name = "Key", - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, RelativeSizeAxes = Axes.X, Height = ManiaPlayfield.HIT_TARGET_POSITION, Children = new Drawable[] diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 118cf610dc..1929bfdf7d 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -74,8 +74,8 @@ namespace osu.Game.Rulesets.Mania.UI { new Container { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.Y, AutoSizeAxes = Axes.X, Masking = true, @@ -95,13 +95,18 @@ namespace osu.Game.Rulesets.Mania.UI Padding = new MarginPadding { Left = 1, Right = 1 }, Spacing = new Vector2(1, 0) }, - barlineContainer = new TimeRelativeContainer(timingChanges) + new Container { - Name = "Bar lines", - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Bottom = HIT_TARGET_POSITION } + Padding = new MarginPadding { Top = HIT_TARGET_POSITION }, + Children = new[] + { + barlineContainer = new TimeRelativeContainer(timingChanges) + { + Name = "Bar lines", + RelativeSizeAxes = Axes.Both, + } + } } } } From ac02d1ab10a694da73f59f3f60eb5de33f16ba29 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 16 May 2017 17:50:09 +0900 Subject: [PATCH 30/40] TimeRelativeContainer -> ControlPointContainer, optimize AutoTimeRelativeContainer a little bit (only recompute on invalidation). --- .../Tests/TestCaseManiaPlayfield.cs | 4 +-- ...eContainer.cs => ControlPointContainer.cs} | 27 +++++++++++-------- osu.Game.Rulesets.Mania/UI/Column.cs | 4 +-- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 4 +-- .../osu.Game.Rulesets.Mania.csproj | 2 +- 5 files changed, 23 insertions(+), 18 deletions(-) rename osu.Game.Rulesets.Mania/Timing/{TimeRelativeContainer.cs => ControlPointContainer.cs} (84%) diff --git a/osu.Desktop.VisualTests/Tests/TestCaseManiaPlayfield.cs b/osu.Desktop.VisualTests/Tests/TestCaseManiaPlayfield.cs index 459f4589b5..4b7efa7499 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseManiaPlayfield.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseManiaPlayfield.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Mania.UI; using System.Linq; using System; using System.Collections.Generic; -using osu.Game.Rulesets.Mania.Timing; +using osu.Game.Beatmaps.Timing; namespace osu.Desktop.VisualTests.Tests { @@ -28,7 +28,7 @@ namespace osu.Desktop.VisualTests.Tests Action createPlayfield = (cols, pos) => { Clear(); - Add(new ManiaPlayfield(cols, new List()) + Add(new ManiaPlayfield(cols, new List()) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs b/osu.Game.Rulesets.Mania/Timing/ControlPointContainer.cs similarity index 84% rename from osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs rename to osu.Game.Rulesets.Mania/Timing/ControlPointContainer.cs index 5407b083df..769164a761 100644 --- a/osu.Game.Rulesets.Mania/Timing/TimeRelativeContainer.cs +++ b/osu.Game.Rulesets.Mania/Timing/ControlPointContainer.cs @@ -19,20 +19,16 @@ namespace osu.Game.Rulesets.Mania.Timing /// and as such, will scroll along with the s. /// /// - public class TimeRelativeContainer : Container + public class ControlPointContainer : Container { /// /// The amount of time which the height of this container spans. /// - public double TimeSpan - { - get { return RelativeCoordinateSpace.Y; } - set { RelativeCoordinateSpace = new Vector2(1, (float)value); } - } + public double TimeSpan { get; set; } private readonly List drawableTimingSections; - public TimeRelativeContainer(IEnumerable timingChanges) + public ControlPointContainer(IEnumerable timingChanges) { drawableTimingSections = timingChanges.Select(t => new DrawableTimingSection(t)).ToList(); @@ -99,10 +95,10 @@ namespace osu.Game.Rulesets.Mania.Timing protected override void Update() { - var parent = (TimeRelativeContainer)Parent; + var parent = (ControlPointContainer)Parent; // Adjust our height to account for the speed changes - Height = (float)(parent.TimeSpan * 1000 / timingChange.BeatLength / timingChange.SpeedMultiplier); + Height = (float)(1000 / timingChange.BeatLength / timingChange.SpeedMultiplier); RelativeCoordinateSpace = new Vector2(1, (float)parent.TimeSpan); // Scroll the content @@ -127,10 +123,19 @@ namespace osu.Game.Rulesets.Mania.Timing /// The drawable to check. public bool CanContain(Drawable drawable) => content.Y <= drawable.Y; + /// + /// A container which always keeps its height and relative coordinate space "auto-sized" to its children. + /// private class AutoTimeRelativeContainer : Container { - public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) + public override void InvalidateFromChild(Invalidation invalidation) { + if ((invalidation & Invalidation.Geometry) == 0) + { + base.InvalidateFromChild(invalidation); + return; + } + float height = 0; foreach (Drawable child in Children) @@ -143,7 +148,7 @@ namespace osu.Game.Rulesets.Mania.Timing Height = height; RelativeCoordinateSpace = new Vector2(1, height); - return base.Invalidate(invalidation, source, shallPropagate); + base.InvalidateFromChild(invalidation); } } } diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 8491b631c5..b8a88263b9 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Mania.UI private readonly Container hitTargetBar; private readonly Container keyIcon; - public readonly TimeRelativeContainer TimingSectionContainer; + public readonly ControlPointContainer TimingSectionContainer; public Column(IEnumerable timingChanges) { @@ -91,7 +91,7 @@ namespace osu.Game.Rulesets.Mania.UI } } }, - TimingSectionContainer = new TimeRelativeContainer(timingChanges) + TimingSectionContainer = new ControlPointContainer(timingChanges) { Name = "Hit objects", RelativeSizeAxes = Axes.Both, diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 1929bfdf7d..9caa852c9c 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Mania.UI public readonly FlowContainer Columns; - private readonly TimeRelativeContainer barlineContainer; + private readonly ControlPointContainer barlineContainer; private List normalColumnColours = new List(); private Color4 specialColumnColour; @@ -101,7 +101,7 @@ namespace osu.Game.Rulesets.Mania.UI Padding = new MarginPadding { Top = HIT_TARGET_POSITION }, Children = new[] { - barlineContainer = new TimeRelativeContainer(timingChanges) + barlineContainer = new ControlPointContainer(timingChanges) { Name = "Bar lines", RelativeSizeAxes = Axes.Both, diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 70c875fd34..00deaba85d 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -68,7 +68,7 @@ - + From 8ed97a833568bb8adebab1d4a6a0ba0e4282b38e Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 16 May 2017 18:02:54 +0900 Subject: [PATCH 31/40] Let's invert the playfield by default for now. --- osu.Desktop.VisualTests/Tests/TestCaseManiaPlayfield.cs | 4 +++- osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Desktop.VisualTests/Tests/TestCaseManiaPlayfield.cs b/osu.Desktop.VisualTests/Tests/TestCaseManiaPlayfield.cs index 4b7efa7499..1f572f6c2c 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseManiaPlayfield.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseManiaPlayfield.cs @@ -10,6 +10,7 @@ using System.Linq; using System; using System.Collections.Generic; using osu.Game.Beatmaps.Timing; +using OpenTK; namespace osu.Desktop.VisualTests.Tests { @@ -32,7 +33,8 @@ namespace osu.Desktop.VisualTests.Tests { Anchor = Anchor.Centre, Origin = Anchor.Centre, - SpecialColumnPosition = pos + SpecialColumnPosition = pos, + Scale = new Vector2(1, -1) }); }; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs index 9b476c4c1a..518917ed8e 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs @@ -66,7 +66,9 @@ namespace osu.Game.Rulesets.Mania.UI return new ManiaPlayfield(Columns ?? (int)Math.Round(Beatmap.BeatmapInfo.Difficulty.CircleSize), timingChanges) { Anchor = Anchor.Centre, - Origin = Anchor.Centre + Origin = Anchor.Centre, + // Invert by default for now (should be moved to config/skin later) + Scale = new Vector2(1, -1) }; } From f4a03ec1cff255fe6285f6d950266a3ea5eaa22a Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 16 May 2017 18:03:30 +0900 Subject: [PATCH 32/40] Fix usings. --- osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs index 518917ed8e..986aefb2bd 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Collections.Generic; using System.Linq; using OpenTK; using osu.Framework.Graphics; @@ -14,7 +13,6 @@ using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Scoring; -using osu.Game.Rulesets.Mania.Timing; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; From 60666dc8248206c732a2ed2224b869c856fad988 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 16 May 2017 18:05:09 +0900 Subject: [PATCH 33/40] Rename. --- osu.Game.Rulesets.Mania/UI/Column.cs | 6 +++--- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index b8a88263b9..172533f889 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Mania.UI private readonly Container hitTargetBar; private readonly Container keyIcon; - public readonly ControlPointContainer TimingSectionContainer; + public readonly ControlPointContainer ControlPointContainer; public Column(IEnumerable timingChanges) { @@ -91,7 +91,7 @@ namespace osu.Game.Rulesets.Mania.UI } } }, - TimingSectionContainer = new ControlPointContainer(timingChanges) + ControlPointContainer = new ControlPointContainer(timingChanges) { Name = "Hit objects", RelativeSizeAxes = Axes.Both, @@ -181,7 +181,7 @@ namespace osu.Game.Rulesets.Mania.UI public void Add(DrawableHitObject hitObject) { - TimingSectionContainer.Add(hitObject); + ControlPointContainer.Add(hitObject); } protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 9caa852c9c..8709e039ec 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -224,7 +224,7 @@ namespace osu.Game.Rulesets.Mania.UI timeSpan = MathHelper.Clamp(timeSpan, time_span_min, time_span_max); barlineContainer.TimeSpan = value; - Columns.Children.ForEach(c => c.TimingSectionContainer.TimeSpan = value); + Columns.Children.ForEach(c => c.ControlPointContainer.TimeSpan = value); } } From 620b4bf863a682c0879a4d0b99a20204442643ba Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 16 May 2017 18:17:34 +0900 Subject: [PATCH 34/40] Cleanup. --- .../Timing/ControlPointContainer.cs | 57 ++++++++----------- 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Timing/ControlPointContainer.cs b/osu.Game.Rulesets.Mania/Timing/ControlPointContainer.cs index 769164a761..e84fe0115e 100644 --- a/osu.Game.Rulesets.Mania/Timing/ControlPointContainer.cs +++ b/osu.Game.Rulesets.Mania/Timing/ControlPointContainer.cs @@ -12,7 +12,7 @@ using osu.Game.Beatmaps.Timing; namespace osu.Game.Rulesets.Mania.Timing { /// - /// A container in which the Y-relative coordinate space is spanned by a length of time. + /// A container in which added drawables are put into a relative coordinate space spanned by a length of time. /// /// This container contains s which scroll inside this container. /// Drawables added to this container are moved inside the relevant , @@ -22,39 +22,38 @@ namespace osu.Game.Rulesets.Mania.Timing public class ControlPointContainer : Container { /// - /// The amount of time which the height of this container spans. + /// The amount of time which this container spans. /// public double TimeSpan { get; set; } - private readonly List drawableTimingSections; + private readonly List drawableControlPoints; public ControlPointContainer(IEnumerable timingChanges) { - drawableTimingSections = timingChanges.Select(t => new DrawableTimingSection(t)).ToList(); - - Children = drawableTimingSections; + drawableControlPoints = timingChanges.Select(t => new DrawableControlPoint(t)).ToList(); + Children = drawableControlPoints; } /// - /// Adds a drawable to this container. Note that the drawable added must have a - /// Y-position as a time relative to this container. + /// Adds a drawable to this container. Note that the drawable added must have its Y-position be + /// an absolute unit of time that is _not_ relative to . /// /// The drawable to add. public override void Add(Drawable drawable) { // Always add timing sections to ourselves - if (drawable is DrawableTimingSection) + if (drawable is DrawableControlPoint) { base.Add(drawable); return; } - var section = drawableTimingSections.LastOrDefault(t => t.CanContain(drawable)) ?? drawableTimingSections.FirstOrDefault(); + var controlPoint = drawableControlPoints.LastOrDefault(t => t.CanContain(drawable)) ?? drawableControlPoints.FirstOrDefault(); - if (section == null) + if (controlPoint == null) throw new Exception("Could not find suitable timing section to add object to."); - section.Add(drawable); + controlPoint.Add(drawable); } /// @@ -63,7 +62,7 @@ namespace osu.Game.Rulesets.Mania.Timing /// The content of this container will scroll relative to the current time. /// /// - private class DrawableTimingSection : Container + private class DrawableControlPoint : Container { private readonly ControlPoint timingChange; @@ -71,15 +70,13 @@ namespace osu.Game.Rulesets.Mania.Timing private readonly Container content; /// - /// Creates a drawable timing section. The height of this container will be proportional - /// to the beat length of the timing section and the timespan of its parent at all times. - /// - /// This is so that, e.g. a beat length of 500ms results in this container being twice as high as its parent, - /// which means that the content container will scroll at twice the normal rate. - /// + /// Creates a drawable control point. The height of this container will be proportional + /// to the beat length of the control point it is initialized with such that, e.g. a beat length + /// of 500ms results in this container being twice as high as its parent, which further means that + /// the content container will scroll at twice the normal rate. /// - /// The timing change to create the drawable timing section for. - public DrawableTimingSection(ControlPoint timingChange) + /// The control point to create the drawable control point for. + public DrawableControlPoint(ControlPoint timingChange) { this.timingChange = timingChange; @@ -107,9 +104,9 @@ namespace osu.Game.Rulesets.Mania.Timing public override void Add(Drawable drawable) { - // The previously relatively-positioned drawable will now become relative to us, but since the drawable has no knowledge of us, - // we need to offset it back by our position so that it becomes correctly relatively-positioned to us - // This can be removed if hit objects were stored such that either their StartTime or their "beat offset" was relative to the timing section + // The previously relatively-positioned drawable will now become relative to content, but since the drawable has no knowledge of content, + // we need to offset it back by content's position position so that it becomes correctly relatively-positioned to content + // This can be removed if hit objects were stored such that either their StartTime or their "beat offset" was relative to the timing change // they belonged to, but this requires a radical change to the beatmap format which we're not ready to do just yet drawable.Y -= (float)timingChange.Time; @@ -117,8 +114,7 @@ namespace osu.Game.Rulesets.Mania.Timing } /// - /// Whether this timing section can contain a drawable. A timing section can contain a drawable if the drawable - /// can be placed within the timing section's bounds (in this case, from the start of the timing section up to infinity). + /// Whether this control point can contain a drawable. This control point can contain a drawable if the drawable is positioned "after" this control point. /// /// The drawable to check. public bool CanContain(Drawable drawable) => content.Y <= drawable.Y; @@ -136,14 +132,7 @@ namespace osu.Game.Rulesets.Mania.Timing return; } - float height = 0; - - foreach (Drawable child in Children) - { - float childEndPos = child.Y + child.Height; - if (childEndPos > height) - height = childEndPos; - } + float height = Children.Select(child => child.Y + child.Height).Max(); Height = height; RelativeCoordinateSpace = new Vector2(1, height); From be4ff5c038dbfeb1cead8f2ced650b635c426918 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 16 May 2017 18:26:49 +0900 Subject: [PATCH 35/40] Fix possible no-children-in-sequence exception. --- osu.Game.Rulesets.Mania/Timing/ControlPointContainer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Timing/ControlPointContainer.cs b/osu.Game.Rulesets.Mania/Timing/ControlPointContainer.cs index e84fe0115e..40903f9213 100644 --- a/osu.Game.Rulesets.Mania/Timing/ControlPointContainer.cs +++ b/osu.Game.Rulesets.Mania/Timing/ControlPointContainer.cs @@ -132,6 +132,9 @@ namespace osu.Game.Rulesets.Mania.Timing return; } + if (!Children.Any()) + return; + float height = Children.Select(child => child.Y + child.Height).Max(); Height = height; From 235a5b1dff446d58e253453c1281e1cf101d2ffe Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 16 May 2017 18:27:33 +0900 Subject: [PATCH 36/40] Add notes to test case. --- .../Tests/TestCaseManiaPlayfield.cs | 50 ++++++++++++++----- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/osu.Desktop.VisualTests/Tests/TestCaseManiaPlayfield.cs b/osu.Desktop.VisualTests/Tests/TestCaseManiaPlayfield.cs index 1f572f6c2c..04fcd8e94a 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseManiaPlayfield.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseManiaPlayfield.cs @@ -1,16 +1,16 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Input; using osu.Framework.Testing; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.UI; -using System.Linq; using System; using System.Collections.Generic; using osu.Game.Beatmaps.Timing; using OpenTK; +using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Mania.Objects; namespace osu.Desktop.VisualTests.Tests { @@ -24,8 +24,6 @@ namespace osu.Desktop.VisualTests.Tests { base.Reset(); - const int max_columns = 10; - Action createPlayfield = (cols, pos) => { Clear(); @@ -38,20 +36,46 @@ namespace osu.Desktop.VisualTests.Tests }); }; - for (int i = 1; i <= max_columns; i++) + Action createPlayfieldWithNotes = (cols, pos) => { - int tempI = i; + Clear(); - AddStep($"{i} column" + (i > 1 ? "s" : ""), () => createPlayfield(tempI, SpecialColumnPosition.Normal)); + ManiaPlayfield playField; + Add(playField = new ManiaPlayfield(cols, new List { new ControlPoint { BeatLength = 200 } }) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + SpecialColumnPosition = pos, + Scale = new Vector2(1, -1) + }); - AddStep("Trigger keys down", () => ((ManiaPlayfield)Children.First()).Columns.Children.ForEach(triggerKeyDown)); - AddStep("Trigger keys up", () => ((ManiaPlayfield)Children.First()).Columns.Children.ForEach(triggerKeyUp)); + for (int i = 0; i < cols; i++) + { + playField.Add(new DrawableNote(new Note + { + StartTime = Time.Current + 1000, + Column = i + })); + } + }; - AddStep("Left special style", () => createPlayfield(tempI, SpecialColumnPosition.Left)); - AddStep("Right special style", () => createPlayfield(tempI, SpecialColumnPosition.Right)); - } + AddStep("1 column", () => createPlayfield(1, SpecialColumnPosition.Normal)); + AddStep("4 columns", () => createPlayfield(4, SpecialColumnPosition.Normal)); + AddStep("Left special style", () => createPlayfield(4, SpecialColumnPosition.Left)); + AddStep("Right special style", () => createPlayfield(4, SpecialColumnPosition.Right)); + AddStep("5 columns", () => createPlayfield(5, SpecialColumnPosition.Normal)); + AddStep("8 columns", () => createPlayfield(8, SpecialColumnPosition.Normal)); + AddStep("Left special style", () => createPlayfield(8, SpecialColumnPosition.Left)); + AddStep("Right special style", () => createPlayfield(8, SpecialColumnPosition.Right)); - AddStep("Normal special style", () => createPlayfield(max_columns, SpecialColumnPosition.Normal)); + AddStep("Normal special style", () => createPlayfield(4, SpecialColumnPosition.Normal)); + + AddStep("Notes", () => createPlayfieldWithNotes(4, SpecialColumnPosition.Normal)); + AddWaitStep(10); + AddStep("Left special style", () => createPlayfieldWithNotes(4, SpecialColumnPosition.Left)); + AddWaitStep(10); + AddStep("Right special style", () => createPlayfieldWithNotes(4, SpecialColumnPosition.Right)); + AddWaitStep(10); } private void triggerKeyDown(Column column) From 3c8d75effb15c4141ef2646ec9494ca884f955da Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 16 May 2017 18:36:38 +0900 Subject: [PATCH 37/40] Fix unused directive. --- osu.Game.Rulesets.Mania/UI/Column.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 172533f889..6663f3bc4c 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -18,7 +18,6 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Beatmaps.Timing; -using osu.Framework.Graphics.Primitives; namespace osu.Game.Rulesets.Mania.UI { From 9b0aed7c4827d20186560ed12fd0267c2e4fe194 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 16 May 2017 19:14:27 +0900 Subject: [PATCH 38/40] Add tween to time span changing. --- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 33 ++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 22c190e07b..56a86873e9 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -20,6 +20,8 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Mania.Timing; using osu.Framework.Input; using osu.Game.Beatmaps.Timing; +using osu.Framework.Graphics.Transforms; +using osu.Framework.MathUtils; namespace osu.Game.Rulesets.Mania.UI { @@ -196,10 +198,10 @@ namespace osu.Game.Rulesets.Mania.UI switch (args.Key) { case Key.Minus: - TimeSpan += time_span_step; + transformTimeSpanTo(TimeSpan + time_span_step, 200, EasingTypes.OutQuint); break; case Key.Plus: - TimeSpan -= time_span_step; + transformTimeSpanTo(TimeSpan - time_span_step, 200, EasingTypes.OutQuint); break; } } @@ -227,5 +229,32 @@ namespace osu.Game.Rulesets.Mania.UI } } + private void transformTimeSpanTo(double newTimeSpan, double duration = 0, EasingTypes easing = EasingTypes.None) + { + TransformTo(() => TimeSpan, newTimeSpan, duration, easing, new TransformTimeSpan()); + } + + private class TransformTimeSpan : Transform + { + public override double CurrentValue + { + get + { + double time = Time?.Current ?? 0; + if (time < StartTime) return StartValue; + if (time >= EndTime) return EndValue; + + return Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing); + } + } + + public override void Apply(Drawable d) + { + base.Apply(d); + + var p = (ManiaPlayfield)d; + p.TimeSpan = CurrentValue; + } + } } } From bc629d193d47f0f48cbb1de8c29eaefa231f658d Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 16 May 2017 19:26:46 +0900 Subject: [PATCH 39/40] InternalChildren -> Children. --- osu.Game.Rulesets.Mania/UI/Column.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 6663f3bc4c..dea00433e6 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Mania.UI RelativeSizeAxes = Axes.Y; Width = column_width; - InternalChildren = new Drawable[] + Children = new Drawable[] { background = new Box { From 0eba5531382155a850453ea37d03a40176f0cdc0 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 16 May 2017 19:33:56 +0900 Subject: [PATCH 40/40] Comments? --- osu.Game.Rulesets.Mania/Timing/ControlPointContainer.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Timing/ControlPointContainer.cs b/osu.Game.Rulesets.Mania/Timing/ControlPointContainer.cs index 40903f9213..6c39ba40f9 100644 --- a/osu.Game.Rulesets.Mania/Timing/ControlPointContainer.cs +++ b/osu.Game.Rulesets.Mania/Timing/ControlPointContainer.cs @@ -121,11 +121,16 @@ namespace osu.Game.Rulesets.Mania.Timing /// /// A container which always keeps its height and relative coordinate space "auto-sized" to its children. + /// + /// This is used in the case where children are relatively positioned/sized to time values (e.g. notes/bar lines) to keep + /// such children wrapped inside a container, otherwise they would disappear due to container flattening. + /// /// private class AutoTimeRelativeContainer : Container { public override void InvalidateFromChild(Invalidation invalidation) { + // We only want to re-compute our size when a child's size or position has changed if ((invalidation & Invalidation.Geometry) == 0) { base.InvalidateFromChild(invalidation);