From c6e099d7256b2ad2198e63eaa3f705f5f49894fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Sat, 3 Dec 2016 10:41:03 +0100 Subject: [PATCH 01/10] Fix incorrect way of calculating SliderCurve.PositionAt. --- osu.Game.Mode.Osu/Objects/SliderCurve.cs | 44 +++++++++++++++++++----- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/osu.Game.Mode.Osu/Objects/SliderCurve.cs b/osu.Game.Mode.Osu/Objects/SliderCurve.cs index 4e691196f5..7556f44cda 100644 --- a/osu.Game.Mode.Osu/Objects/SliderCurve.cs +++ b/osu.Game.Mode.Osu/Objects/SliderCurve.cs @@ -1,5 +1,8 @@ using System.Collections.Generic; using OpenTK; +using System.Linq; +using System.Diagnostics; +using osu.Framework.MathUtils; namespace osu.Game.Modes.Osu.Objects { @@ -11,7 +14,8 @@ namespace osu.Game.Modes.Osu.Objects public CurveTypes CurveType; - private List calculatedPath; + private List calculatedPath = new List(); + private List cumulativeLength = new List(); private List calculateSubpath(List subpath) { @@ -26,7 +30,7 @@ namespace osu.Game.Modes.Osu.Objects public void Calculate() { - calculatedPath = new List(); + calculatedPath.Clear(); // Sliders may consist of various subpaths separated by two consecutive vertices // with the same position. The following loop parses these subpaths and computes @@ -48,20 +52,44 @@ namespace osu.Game.Modes.Osu.Objects subpath.Clear(); } } + + cumulativeLength.Clear(); + cumulativeLength.Add(Length = 0); + for (int i = 0; i < calculatedPath.Count - 1; ++i) + { + double d = (calculatedPath[i + 1] - calculatedPath[i]).Length; + + Debug.Assert(d >= 0, "Cumulative lengths have to be strictly increasing."); + cumulativeLength.Add(Length += d); + } } public Vector2 PositionAt(double progress) { progress = MathHelper.Clamp(progress, 0, 1); - double index = progress * (calculatedPath.Count - 1); - int flooredIndex = (int)index; + double d = progress * Length; + int i = cumulativeLength.BinarySearch(d); + if (i < 0) i = ~i; - Vector2 pos = calculatedPath[flooredIndex]; - if (index != flooredIndex) - pos += (calculatedPath[flooredIndex + 1] - pos) * (float)(index - flooredIndex); + if (i >= calculatedPath.Count) + return calculatedPath.Last(); - return pos; + if (i <= 0) + return calculatedPath.First(); + + Vector2 p0 = calculatedPath[i - 1]; + Vector2 p1 = calculatedPath[i]; + + double d0 = cumulativeLength[i - 1]; + double d1 = cumulativeLength[i]; + + // Avoid division by and almost-zero number in case two points are extremely close to each other. + if (Precision.AlmostEquals(d0, d1)) + return p0; + + double w = (d - d0) / (d1 - d0); + return p0 + (p1 - p0) * (float)w; } } } \ No newline at end of file From 4dbc6ad4d0e34c1560701be25b852a29eb678869 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Sat, 3 Dec 2016 11:43:56 +0100 Subject: [PATCH 02/10] Construct drawable slider paths smoothly using the optimized slider curve instead of by discrete individual re-sampled segments. --- .../Objects/Drawables/DrawableSlider.cs | 37 ++---------------- osu.Game.Mode.Osu/Objects/SliderCurve.cs | 39 ++++++++++++++++--- 2 files changed, 37 insertions(+), 39 deletions(-) diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index 8882049cbb..57f8d6055e 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -248,42 +248,13 @@ namespace osu.Game.Modes.Osu.Objects.Drawables double progress = MathHelper.Clamp((Time.Current - slider.StartTime + TIME_PREEMPT) / TIME_FADEIN, 0, 1); if (progress == drawnProgress) return false; - - bool madeChanges = false; - if (progress == 0) - { - //if we have gone backwards, just clear the path for now. - drawnProgress = 0; - path.ClearVertices(); - madeChanges = true; - } + drawnProgress = progress; Vector2 startPosition = slider.Curve.PositionAt(0); - if (drawnProgress == null) - { - drawnProgress = 0; - path.AddVertex(slider.Curve.PositionAt(drawnProgress.Value) - startPosition); - madeChanges = true; - } - - double segmentSize = 1 / (slider.Curve.Length / 5); - - while (drawnProgress + segmentSize < progress) - { - drawnProgress += segmentSize; - path.AddVertex(slider.Curve.PositionAt(drawnProgress.Value) - startPosition); - madeChanges = true; - } - - if (progress == 1 && drawnProgress != progress) - { - drawnProgress = progress; - path.AddVertex(slider.Curve.PositionAt(drawnProgress.Value) - startPosition); - madeChanges = true; - } - - return madeChanges; + path.ClearVertices(); + slider.Curve.FillCurveUntilProgress(p => path.AddVertex(p - startPosition), progress); + return true; } } } diff --git a/osu.Game.Mode.Osu/Objects/SliderCurve.cs b/osu.Game.Mode.Osu/Objects/SliderCurve.cs index 7556f44cda..8faccc1516 100644 --- a/osu.Game.Mode.Osu/Objects/SliderCurve.cs +++ b/osu.Game.Mode.Osu/Objects/SliderCurve.cs @@ -3,6 +3,7 @@ using OpenTK; using System.Linq; using System.Diagnostics; using osu.Framework.MathUtils; +using System; namespace osu.Game.Modes.Osu.Objects { @@ -64,19 +65,28 @@ namespace osu.Game.Modes.Osu.Objects } } - public Vector2 PositionAt(double progress) + private int indexOfDistance(double d) { - progress = MathHelper.Clamp(progress, 0, 1); - - double d = progress * Length; int i = cumulativeLength.BinarySearch(d); if (i < 0) i = ~i; - if (i >= calculatedPath.Count) - return calculatedPath.Last(); + return i; + } + + private double progressToDistance(double progress) + { + return MathHelper.Clamp(progress, 0, 1) * Length; + } + + private Vector2 interpolateVertices(int i, double d) + { + if (calculatedPath.Count == 0) + return Vector2.Zero; if (i <= 0) return calculatedPath.First(); + else if (i >= calculatedPath.Count) + return calculatedPath.Last(); Vector2 p0 = calculatedPath[i - 1]; Vector2 p1 = calculatedPath[i]; @@ -91,5 +101,22 @@ namespace osu.Game.Modes.Osu.Objects double w = (d - d0) / (d1 - d0); return p0 + (p1 - p0) * (float)w; } + + public void FillCurveUntilProgress(Action action, double progress) + { + double d = progressToDistance(progress); + + int i = 0; + for (; i < calculatedPath.Count && cumulativeLength[i] <= d; ++i) + action.Invoke(calculatedPath[i]); + + action.Invoke(interpolateVertices(i, d)); + } + + public Vector2 PositionAt(double progress) + { + double d = progressToDistance(progress); + return interpolateVertices(indexOfDistance(d), d); + } } } \ No newline at end of file From a1efd25ac19298f7cb5efb4f29c94a6fa088b84c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Sat, 3 Dec 2016 13:25:31 +0100 Subject: [PATCH 03/10] Improve code clarity and allow snaking "away" the beginning of the slider that has already been tracked. --- osu-framework | 2 +- .../Objects/Drawables/DrawableSlider.cs | 50 +++++++++++-------- osu.Game.Mode.Osu/Objects/SliderCurve.cs | 29 +++++++++-- 3 files changed, 55 insertions(+), 26 deletions(-) diff --git a/osu-framework b/osu-framework index 7ca1719b5c..3d9bf09831 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 7ca1719b5cdc8b0a9600abe6472b38a426abedb0 +Subproject commit 3d9bf098319583fc4fbbab5117702d000ad4fb9b diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index 57f8d6055e..b5b4ea0541 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -63,16 +63,21 @@ namespace osu.Game.Modes.Osu.Objects.Drawables ball.Alpha = Time.Current >= slider.StartTime && Time.Current <= slider.EndTime ? 1 : 0; - double t = (Time.Current - slider.StartTime) / slider.Duration; - if (slider.RepeatCount > 1) - { - int currentRepeat = (int)(t * slider.RepeatCount); - t = (t * slider.RepeatCount) % 1; - if (currentRepeat % 2 == 1) - t = 1 - t; - } + double currentProgress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); + double drawStartProgress = 0; - ball.Position = slider.Curve.PositionAt(t); + int currentRepeat = (int)(currentProgress * slider.RepeatCount); + currentProgress = (currentProgress * slider.RepeatCount) % 1; + if (currentRepeat % 2 == 1) + currentProgress = 1 - currentProgress; + + if (currentRepeat >= slider.RepeatCount - 1) + drawStartProgress = currentProgress; + + ball.Position = slider.Curve.PositionAt(currentProgress); + + double drawEndProgress = MathHelper.Clamp((Time.Current - slider.StartTime + TIME_PREEMPT) / TIME_FADEIN, 0, 1); + body.SetRange(drawStartProgress, drawEndProgress); } protected override void CheckJudgement(bool userTriggered) @@ -187,7 +192,8 @@ namespace osu.Game.Modes.Osu.Objects.Drawables private Path path; private BufferedContainer container; - private double? drawnProgress; + private double drawnProgressStart; + private double drawnProgressEnd; private Slider slider; public Body(Slider s) @@ -227,33 +233,37 @@ namespace osu.Game.Modes.Osu.Objects.Drawables path.PathWidth = 32; } - protected override void Update() + public void SetRange(double p0, double p1) { - base.Update(); + if (p0 > p1) + MathHelper.Swap(ref p0, ref p1); - if (updateSnaking()) + if (updateSnaking(p0, p1)) { // Autosizing does not give us the desired behaviour here. // We want the container to have the same size as the slider, // and to be positioned such that the slider head is at (0,0). container.Size = path.Size; - container.Position = -path.HeadPosition; + container.Position = -path.PositionInBoundingBox(slider.Curve.PositionAt(0) - currentCurve[0]); container.ForceRedraw(); } } - private bool updateSnaking() + private List currentCurve = new List(); + private bool updateSnaking(double p0, double p1) { - double progress = MathHelper.Clamp((Time.Current - slider.StartTime + TIME_PREEMPT) / TIME_FADEIN, 0, 1); + if (drawnProgressStart == p0 && drawnProgressEnd == p1) return false; - if (progress == drawnProgress) return false; - drawnProgress = progress; + drawnProgressStart = p0; + drawnProgressEnd = p1; - Vector2 startPosition = slider.Curve.PositionAt(0); + slider.Curve.GetPathToProgress(currentCurve, p0, p1); path.ClearVertices(); - slider.Curve.FillCurveUntilProgress(p => path.AddVertex(p - startPosition), progress); + foreach (Vector2 p in currentCurve) + path.AddVertex(p - currentCurve[0]); + return true; } } diff --git a/osu.Game.Mode.Osu/Objects/SliderCurve.cs b/osu.Game.Mode.Osu/Objects/SliderCurve.cs index 8faccc1516..92d5650403 100644 --- a/osu.Game.Mode.Osu/Objects/SliderCurve.cs +++ b/osu.Game.Mode.Osu/Objects/SliderCurve.cs @@ -102,17 +102,36 @@ namespace osu.Game.Modes.Osu.Objects return p0 + (p1 - p0) * (float)w; } - public void FillCurveUntilProgress(Action action, double progress) + /// + /// Computes the slider curve until a given progress that ranges from 0 (beginning of the slider) + /// to 1 (end of the slider) and stores the generated path in the given list. + /// + /// The list to be filled with the computed curve. + /// Ranges from 0 (beginning of the slider) to 1 (end of the slider). + public void GetPathToProgress(List path, double p0, double p1) { - double d = progressToDistance(progress); + double d0 = progressToDistance(p0); + double d1 = progressToDistance(p1); + + path.Clear(); int i = 0; - for (; i < calculatedPath.Count && cumulativeLength[i] <= d; ++i) - action.Invoke(calculatedPath[i]); + for (; i < calculatedPath.Count && cumulativeLength[i] < d0; ++i); - action.Invoke(interpolateVertices(i, d)); + path.Add(interpolateVertices(i, d0)); + + for (; i < calculatedPath.Count && cumulativeLength[i] <= d1; ++i) + path.Add(calculatedPath[i]); + + path.Add(interpolateVertices(i, d1)); } + /// + /// Computes the position on the slider at a given progress that ranges from 0 (beginning of the slider) + /// to 1 (end of the slider). + /// + /// Ranges from 0 (beginning of the slider) to 1 (end of the slider). + /// public Vector2 PositionAt(double progress) { double d = progressToDistance(progress); From c43b47da2ae79136aa7eb53f741630930c6acc94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Sat, 3 Dec 2016 13:56:19 +0100 Subject: [PATCH 04/10] Add option toggles and configuration for snaking in and out sliders. --- .../Objects/Drawables/DrawableSlider.cs | 34 ++++++++++++++----- osu.Game/Configuration/OsuConfigManager.cs | 11 +++--- .../Options/Graphics/DetailOptions.cs | 9 +++-- 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index b5b4ea0541..2c817e7074 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -11,6 +11,8 @@ using osu.Framework.Input; using OpenTK.Graphics.ES30; using osu.Framework.Allocation; using osu.Framework.Graphics.Textures; +using osu.Game.Configuration; +using osu.Framework.Configuration; namespace osu.Game.Modes.Osu.Objects.Drawables { @@ -49,12 +51,24 @@ namespace osu.Game.Modes.Osu.Objects.Drawables }; } + private Bindable snakingIn; + private Bindable snakingOut; + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + snakingIn = config.GetBindable(OsuConfig.SnakingInSliders); + snakingOut = config.GetBindable(OsuConfig.SnakingOutSliders); + } + protected override void LoadComplete() { base.LoadComplete(); //force application of the state that was set before we loaded. UpdateState(State); + + body.PathWidth = 32; } protected override void Update() @@ -77,7 +91,9 @@ namespace osu.Game.Modes.Osu.Objects.Drawables ball.Position = slider.Curve.PositionAt(currentProgress); double drawEndProgress = MathHelper.Clamp((Time.Current - slider.StartTime + TIME_PREEMPT) / TIME_FADEIN, 0, 1); - body.SetRange(drawStartProgress, drawEndProgress); + body.SetRange( + snakingOut ? drawStartProgress : 0, + snakingIn ? drawEndProgress : 1); } protected override void CheckJudgement(bool userTriggered) @@ -192,8 +208,14 @@ namespace osu.Game.Modes.Osu.Objects.Drawables private Path path; private BufferedContainer container; - private double drawnProgressStart; - private double drawnProgressEnd; + public float PathWidth + { + get { return path.PathWidth; } + set { path.PathWidth = value; } + } + + private double? drawnProgressStart; + private double? drawnProgressEnd; private Slider slider; public Body(Slider s) @@ -227,12 +249,6 @@ namespace osu.Game.Modes.Osu.Objects.Drawables path.Texture = textures.Get(@"Menu/logo"); } - protected override void LoadComplete() - { - base.LoadComplete(); - path.PathWidth = 32; - } - public void SetRange(double p0, double p1) { if (p0 > p1) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 8657f74d87..6f2175cb97 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -9,7 +9,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Configuration { - class OsuConfigManager : ConfigManager + public class OsuConfigManager : ConfigManager { protected override void InitialiseDefaults() { @@ -129,7 +129,8 @@ namespace osu.Game.Configuration //Set(OsuConfig.Skin, SkinManager.DEFAULT_SKIN); Set(OsuConfig.SkinSamples, true); Set(OsuConfig.SkipTablet, false); - Set(OsuConfig.SnakingSliders, true); + Set(OsuConfig.SnakingInSliders, true); + Set(OsuConfig.SnakingOutSliders, false); Set(OsuConfig.Tablet, false); Set(OsuConfig.UpdatePending, false); Set(OsuConfig.UseSkinCursor, false); @@ -189,7 +190,7 @@ namespace osu.Game.Configuration } } - enum OsuConfig + public enum OsuConfig { // New osu: PlayMode, @@ -303,7 +304,8 @@ namespace osu.Game.Configuration Skin, SkinSamples, SkipTablet, - SnakingSliders, + SnakingInSliders, + SnakingOutSliders, Tablet, UpdatePending, UserFilter, @@ -345,5 +347,6 @@ namespace osu.Game.Configuration Ticker, CompatibilityContext, CanForceOptimusCompatibility, + } } diff --git a/osu.Game/Overlays/Options/Graphics/DetailOptions.cs b/osu.Game/Overlays/Options/Graphics/DetailOptions.cs index 12df61f52b..1a947e4c13 100644 --- a/osu.Game/Overlays/Options/Graphics/DetailOptions.cs +++ b/osu.Game/Overlays/Options/Graphics/DetailOptions.cs @@ -18,8 +18,13 @@ namespace osu.Game.Overlays.Options.Graphics { new CheckBoxOption { - LabelText = "Snaking sliders", - Bindable = config.GetBindable(OsuConfig.SnakingSliders) + LabelText = "Snaking in sliders", + Bindable = config.GetBindable(OsuConfig.SnakingInSliders) + }, + new CheckBoxOption + { + LabelText = "Snaking out sliders", + Bindable = config.GetBindable(OsuConfig.SnakingOutSliders) }, new CheckBoxOption { From b81bf7085f6fd0f092cadf589db760ab695bfb11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Sat, 3 Dec 2016 13:56:35 +0100 Subject: [PATCH 05/10] Add missing licence headers and fixup using statements. --- osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs | 6 ++++-- osu.Game.Mode.Osu/Objects/SliderCurve.cs | 6 ++++-- osu.Game/Configuration/OsuConfigManager.cs | 2 -- osu.Game/OsuGameBase.cs | 10 +++------- osu.Game/Overlays/Options/Graphics/DetailOptions.cs | 5 +++-- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index 2c817e7074..5b3d91e7a3 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -1,8 +1,10 @@ -using System.Collections.Generic; +// Copyright (c) 2007-2016 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Osu.Objects.Drawables.Pieces; using OpenTK; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Transformations; diff --git a/osu.Game.Mode.Osu/Objects/SliderCurve.cs b/osu.Game.Mode.Osu/Objects/SliderCurve.cs index 92d5650403..1e6b0553c2 100644 --- a/osu.Game.Mode.Osu/Objects/SliderCurve.cs +++ b/osu.Game.Mode.Osu/Objects/SliderCurve.cs @@ -1,9 +1,11 @@ -using System.Collections.Generic; +// Copyright (c) 2007-2016 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using System.Collections.Generic; using OpenTK; using System.Linq; using System.Diagnostics; using osu.Framework.MathUtils; -using System; namespace osu.Game.Modes.Osu.Objects { diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 6f2175cb97..8e5fbfad42 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -4,8 +4,6 @@ using osu.Framework.Configuration; using osu.Framework.Platform; using osu.Game.Modes; -using osu.Game.Online.API; -using osu.Game.Screens.Play; namespace osu.Game.Configuration { diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 5b35b1e672..4db582d799 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -1,12 +1,12 @@ -using System; +// Copyright (c) 2007-2016 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Configuration; -using osu.Framework.GameModes; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; -using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; using osu.Framework.Platform; using osu.Game.Beatmaps; @@ -15,11 +15,7 @@ using osu.Game.Configuration; using osu.Game.Database; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.Processing; -using osu.Game.IPC; -using osu.Game.Online; using osu.Game.Online.API; -using osu.Game.Overlays; -using osu.Game.Online.API.Requests; namespace osu.Game { diff --git a/osu.Game/Overlays/Options/Graphics/DetailOptions.cs b/osu.Game/Overlays/Options/Graphics/DetailOptions.cs index 1a947e4c13..880677ff6a 100644 --- a/osu.Game/Overlays/Options/Graphics/DetailOptions.cs +++ b/osu.Game/Overlays/Options/Graphics/DetailOptions.cs @@ -1,8 +1,9 @@ -using osu.Framework; +// Copyright (c) 2007-2016 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.UserInterface; using osu.Game.Configuration; namespace osu.Game.Overlays.Options.Graphics From 773d64cd5e90a7a4c0e139e140d4494b1c7b0ac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Sat, 3 Dec 2016 14:40:15 +0100 Subject: [PATCH 06/10] Update judgement after children have been updated. --- osu-framework | 2 +- osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs | 4 ++-- osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu-framework b/osu-framework index 3d9bf09831..f4693d8812 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 3d9bf098319583fc4fbbab5117702d000ad4fb9b +Subproject commit f4693d8812e305a41037a3b90495d5db2ac32a16 diff --git a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs index 8e41fb6521..ed57f06e51 100644 --- a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs @@ -87,9 +87,9 @@ namespace osu.Game.Modes.Objects.Drawables //todo: consider making abstract. } - protected override void Update() + protected override void UpdateAfterChildren() { - base.Update(); + base.UpdateAfterChildren(); UpdateJudgement(false); } diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs index bc60123c02..22c214d82f 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs @@ -106,9 +106,9 @@ namespace osu.Game.Overlays.Toolbar private Cached activeMode = new Cached(); - protected override void UpdateLayout() + protected override void UpdateAfterChildren() { - base.UpdateLayout(); + base.UpdateAfterChildren(); if (!activeMode.EnsureValid()) activeMode.Refresh(() => modeButtonLine.MoveToX(activeButton.DrawPosition.X, 200, EasingTypes.OutQuint)); From 97c4807f0b6b8b7700084eb846a42f29fafef800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Sat, 3 Dec 2016 14:40:35 +0100 Subject: [PATCH 07/10] Fix incorrect slider snaking in repeat sliders. --- .../Objects/Drawables/DrawableSlider.cs | 65 ++++++++++++++----- 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index 5b3d91e7a3..cd907fc001 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -15,6 +15,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics.Textures; using osu.Game.Configuration; using osu.Framework.Configuration; +using System; namespace osu.Game.Modes.Osu.Objects.Drawables { @@ -73,29 +74,57 @@ namespace osu.Game.Modes.Osu.Objects.Drawables body.PathWidth = 32; } + private void computeProgress(out int repeat, out double progress) + { + progress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); + + repeat = (int)(progress * slider.RepeatCount); + progress = (progress * slider.RepeatCount) % 1; + + if (repeat % 2 == 1) + progress = 1 - progress; + } + + private void updateBall(double progress) + { + ball.Alpha = Time.Current >= slider.StartTime && Time.Current <= slider.EndTime ? 1 : 0; + ball.Position = slider.Curve.PositionAt(progress); + } + + private void updateBody(int repeat, double progress) + { + double drawStartProgress = 0; + double drawEndProgress = MathHelper.Clamp((Time.Current - slider.StartTime + TIME_PREEMPT) / TIME_FADEIN, 0, 1); + + if (repeat >= slider.RepeatCount - 1) + { + if (Math.Min(repeat, slider.RepeatCount - 1) % 2 == 1) + { + drawStartProgress = 0; + drawEndProgress = progress; + } + else + { + drawStartProgress = progress; + drawEndProgress = 1; + } + } + + body.SetRange( + snakingOut ? drawStartProgress : 0, + snakingIn ? drawEndProgress : 1); + } + protected override void Update() { base.Update(); - ball.Alpha = Time.Current >= slider.StartTime && Time.Current <= slider.EndTime ? 1 : 0; + double progress; + int repeat; + computeProgress(out repeat, out progress); - double currentProgress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); - double drawStartProgress = 0; - - int currentRepeat = (int)(currentProgress * slider.RepeatCount); - currentProgress = (currentProgress * slider.RepeatCount) % 1; - if (currentRepeat % 2 == 1) - currentProgress = 1 - currentProgress; - - if (currentRepeat >= slider.RepeatCount - 1) - drawStartProgress = currentProgress; - - ball.Position = slider.Curve.PositionAt(currentProgress); - - double drawEndProgress = MathHelper.Clamp((Time.Current - slider.StartTime + TIME_PREEMPT) / TIME_FADEIN, 0, 1); - body.SetRange( - snakingOut ? drawStartProgress : 0, - snakingIn ? drawEndProgress : 1); + updateBall(progress); + updateBody(repeat, progress); } protected override void CheckJudgement(bool userTriggered) From a0131b8b25a739de25dac928ec76715597ec8e36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Sat, 3 Dec 2016 14:52:51 +0100 Subject: [PATCH 08/10] Fix slider velocity not being applied. --- osu.Game/Beatmaps/Beatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 3f8ae0e33a..fcdef1ce39 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -33,7 +33,7 @@ namespace osu.Game.Beatmaps double mult = 1; - if (applyMultipliers && samplePoint > point && ControlPoints[samplePoint].BeatLength < 0) + if (applyMultipliers && samplePoint > point) mult = ControlPoints[samplePoint].VelocityAdjustment; return ControlPoints[point].BeatLength * mult; From 6ff4a2c27054b045d1ce8a9c437c581a3fe3f50f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Sat, 3 Dec 2016 15:19:23 +0100 Subject: [PATCH 09/10] Shorten and lengthen slider curves as needed to respect the length written in the .osu file. --- osu-framework | 2 +- osu.Game.Mode.Osu/Objects/SliderCurve.cs | 52 +++++++++++++++++++++--- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/osu-framework b/osu-framework index f4693d8812..a6d7641a29 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit f4693d8812e305a41037a3b90495d5db2ac32a16 +Subproject commit a6d7641a29a3c13fe6922649552730b1f9090a4a diff --git a/osu.Game.Mode.Osu/Objects/SliderCurve.cs b/osu.Game.Mode.Osu/Objects/SliderCurve.cs index 1e6b0553c2..d80a441daf 100644 --- a/osu.Game.Mode.Osu/Objects/SliderCurve.cs +++ b/osu.Game.Mode.Osu/Objects/SliderCurve.cs @@ -6,6 +6,7 @@ using OpenTK; using System.Linq; using System.Diagnostics; using osu.Framework.MathUtils; +using System; namespace osu.Game.Modes.Osu.Objects { @@ -31,7 +32,7 @@ namespace osu.Game.Modes.Osu.Objects } } - public void Calculate() + private void calculatePath() { calculatedPath.Clear(); @@ -55,16 +56,55 @@ namespace osu.Game.Modes.Osu.Objects subpath.Clear(); } } - + } + + private void calculateCumulativeLengthAndTrimPath() + { + double l = 0; + cumulativeLength.Clear(); - cumulativeLength.Add(Length = 0); + cumulativeLength.Add(l); + for (int i = 0; i < calculatedPath.Count - 1; ++i) { - double d = (calculatedPath[i + 1] - calculatedPath[i]).Length; + Vector2 diff = calculatedPath[i + 1] - calculatedPath[i]; + double d = diff.Length; - Debug.Assert(d >= 0, "Cumulative lengths have to be strictly increasing."); - cumulativeLength.Add(Length += d); + // Shorten slider curves that are too long compared to what's + // in the .osu file. + if (Length - l < d) + { + calculatedPath[i + 1] = calculatedPath[i] + diff * (float)((Length - l) / d); + calculatedPath.RemoveRange(i + 2, calculatedPath.Count - 2 - i); + + l = Length; + cumulativeLength.Add(l); + break; + } + + l += d; + cumulativeLength.Add(l); } + + // Lengthen slider curves that are too short compared to what's + // in the .osu file. + if (l < Length && calculatedPath.Count > 1) + { + Vector2 diff = calculatedPath[calculatedPath.Count - 1] - calculatedPath[calculatedPath.Count - 2]; + double d = diff.Length; + + if (d <= 0) + return; + + calculatedPath[calculatedPath.Count - 1] += diff * (float)((Length - l) / d); + cumulativeLength[calculatedPath.Count - 1] = Length; + } + } + + public void Calculate() + { + calculatePath(); + calculateCumulativeLengthAndTrimPath(); } private int indexOfDistance(double d) From 7c3be4eaba7c255e2f211255fd454b4a560fc5dd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 4 Dec 2016 11:47:32 +0900 Subject: [PATCH 10/10] Update framework. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index a6d7641a29..7b2f4dfce7 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit a6d7641a29a3c13fe6922649552730b1f9090a4a +Subproject commit 7b2f4dfce7894ca7dea7626dcc34bcc32df651b9