Move IScrollAlgorithm to ScrollingRulesetContainer + use DI

This commit is contained in:
smoogipoo
2018-11-06 12:01:54 +09:00
parent aee7a80e71
commit 7f0f143a1b
8 changed files with 97 additions and 56 deletions

View File

@ -5,7 +5,6 @@ using System;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Catch.Objects.Drawable;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
@ -23,7 +22,6 @@ namespace osu.Game.Rulesets.Catch.UI
protected override bool UserScrollSpeedAdjustment => false; protected override bool UserScrollSpeedAdjustment => false;
protected override ScrollVisualisationMethod VisualisationMethod => ScrollVisualisationMethod.Constant;
public CatchPlayfield(BeatmapDifficulty difficulty, Func<CatchHitObject, DrawableHitObject<CatchHitObject>> getVisualRepresentation) public CatchPlayfield(BeatmapDifficulty difficulty, Func<CatchHitObject, DrawableHitObject<CatchHitObject>> getVisualRepresentation)
{ {

View File

@ -3,6 +3,7 @@
using osu.Framework.Input; using osu.Framework.Input;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Input.Handlers; using osu.Game.Input.Handlers;
using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Catch.Objects.Drawable;
@ -18,6 +19,8 @@ namespace osu.Game.Rulesets.Catch.UI
{ {
public class CatchRulesetContainer : ScrollingRulesetContainer<CatchPlayfield, CatchHitObject> public class CatchRulesetContainer : ScrollingRulesetContainer<CatchPlayfield, CatchHitObject>
{ {
protected override ScrollAlgorithm ScrollAlgorithm => ScrollAlgorithm.Constant;
public CatchRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) public CatchRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap)
: base(ruleset, beatmap) : base(ruleset, beatmap)
{ {

View File

@ -8,7 +8,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Configuration;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
@ -41,8 +40,6 @@ namespace osu.Game.Rulesets.Taiko.UI
protected override bool UserScrollSpeedAdjustment => false; protected override bool UserScrollSpeedAdjustment => false;
protected override ScrollVisualisationMethod VisualisationMethod => ScrollVisualisationMethod.Overlapping;
private readonly Container<HitExplosion> hitExplosionContainer; private readonly Container<HitExplosion> hitExplosionContainer;
private readonly Container<KiaiHitExplosion> kiaiExplosionContainer; private readonly Container<KiaiHitExplosion> kiaiExplosionContainer;
private readonly JudgementContainer<DrawableTaikoJudgement> judgementContainer; private readonly JudgementContainer<DrawableTaikoJudgement> judgementContainer;

View File

@ -14,6 +14,7 @@ using osu.Game.Rulesets.UI;
using osu.Game.Rulesets.Taiko.Replays; using osu.Game.Rulesets.Taiko.Replays;
using System.Linq; using System.Linq;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Game.Configuration;
using osu.Game.Input.Handlers; using osu.Game.Input.Handlers;
using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Rulesets.UI.Scrolling;
@ -21,6 +22,8 @@ namespace osu.Game.Rulesets.Taiko.UI
{ {
public class TaikoRulesetContainer : ScrollingRulesetContainer<TaikoPlayfield, TaikoHitObject> public class TaikoRulesetContainer : ScrollingRulesetContainer<TaikoPlayfield, TaikoHitObject>
{ {
protected override ScrollAlgorithm ScrollAlgorithm => ScrollAlgorithm.Overlapping;
public TaikoRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) public TaikoRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap)
: base(ruleset, beatmap) : base(ruleset, beatmap)
{ {

View File

@ -4,16 +4,20 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.IEnumerableExtensions;
using OpenTK; using OpenTK;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Lists;
using osu.Game.Configuration;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.Timing;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Rulesets.UI.Scrolling;
using osu.Game.Rulesets.UI.Scrolling.Algorithms;
namespace osu.Game.Tests.Visual namespace osu.Game.Tests.Visual
{ {
@ -44,6 +48,10 @@ namespace osu.Game.Tests.Visual
} }
}); });
AddStep("Constant scroll", () => setScrollAlgorithm(ScrollAlgorithm.Constant));
AddStep("Overlapping scroll", () => setScrollAlgorithm(ScrollAlgorithm.Overlapping));
AddStep("Sequential scroll", () => setScrollAlgorithm(ScrollAlgorithm.Sequential));
AddSliderStep("Time range", 100, 10000, 5000, v => playfields.ForEach(p => p.VisibleTimeRange.Value = v)); AddSliderStep("Time range", 100, 10000, 5000, v => playfields.ForEach(p => p.VisibleTimeRange.Value = v));
AddStep("Add control point", () => addControlPoint(Time.Current + 5000)); AddStep("Add control point", () => addControlPoint(Time.Current + 5000));
} }
@ -52,7 +60,7 @@ namespace osu.Game.Tests.Visual
{ {
base.LoadComplete(); base.LoadComplete();
playfields.ForEach(p => p.HitObjects.AddControlPoint(new MultiplierControlPoint(0))); playfields.ForEach(p => p.ControlPoints.Add(new MultiplierControlPoint(0)));
for (int i = 0; i <= 5000; i += 1000) for (int i = 0; i <= 5000; i += 1000)
addHitObject(Time.Current + i); addHitObject(Time.Current + i);
@ -75,9 +83,9 @@ namespace osu.Game.Tests.Visual
{ {
playfields.ForEach(p => playfields.ForEach(p =>
{ {
p.HitObjects.AddControlPoint(new MultiplierControlPoint(time) { DifficultyPoint = { SpeedMultiplier = 3 } }); p.ControlPoints.Add(new MultiplierControlPoint(time) { DifficultyPoint = { SpeedMultiplier = 3 } });
p.HitObjects.AddControlPoint(new MultiplierControlPoint(time + 2000) { DifficultyPoint = { SpeedMultiplier = 2 } }); p.ControlPoints.Add(new MultiplierControlPoint(time + 2000) { DifficultyPoint = { SpeedMultiplier = 2 } });
p.HitObjects.AddControlPoint(new MultiplierControlPoint(time + 3000) { DifficultyPoint = { SpeedMultiplier = 1 } }); p.ControlPoints.Add(new MultiplierControlPoint(time + 3000) { DifficultyPoint = { SpeedMultiplier = 1 } });
TestDrawableControlPoint createDrawablePoint(double t) TestDrawableControlPoint createDrawablePoint(double t)
{ {
@ -111,11 +119,19 @@ namespace osu.Game.Tests.Visual
} }
} }
private void setScrollAlgorithm(ScrollAlgorithm algorithm) => playfields.ForEach(p => p.ScrollAlgorithm = algorithm);
private class TestPlayfield : ScrollingPlayfield private class TestPlayfield : ScrollingPlayfield
{ {
public new ScrollingDirection Direction => base.Direction; public new ScrollingDirection Direction => base.Direction;
public SortedList<MultiplierControlPoint> ControlPoints => algorithm.ControlPoints;
public ScrollAlgorithm ScrollAlgorithm { set => algorithm.Algorithm = value; }
[Cached(Type = typeof(IScrollAlgorithm))]
private readonly TestScrollAlgorithm algorithm = new TestScrollAlgorithm();
public TestPlayfield(ScrollingDirection direction) public TestPlayfield(ScrollingDirection direction)
{ {
base.Direction.Value = direction; base.Direction.Value = direction;
@ -139,6 +155,49 @@ namespace osu.Game.Tests.Visual
} }
} }
private class TestScrollAlgorithm : IScrollAlgorithm
{
public readonly SortedList<MultiplierControlPoint> ControlPoints = new SortedList<MultiplierControlPoint>();
private IScrollAlgorithm implementation;
public TestScrollAlgorithm()
{
Algorithm = ScrollAlgorithm.Constant;
}
public ScrollAlgorithm Algorithm
{
set
{
switch (value)
{
case ScrollAlgorithm.Constant:
implementation = new ConstantScrollAlgorithm();
break;
case ScrollAlgorithm.Overlapping:
implementation = new OverlappingScrollAlgorithm(ControlPoints);
break;
case ScrollAlgorithm.Sequential:
implementation = new SequentialScrollAlgorithm(ControlPoints);
break;
}
}
}
public double GetDisplayStartTime(double time, double timeRange)
=> implementation.GetDisplayStartTime(time, timeRange);
public float GetLength(double startTime, double endTime, double timeRange, float scrollLength)
=> implementation.GetLength(startTime, endTime, timeRange, scrollLength);
public float PositionAt(double time, double currentTime, double timeRange, float scrollLength)
=> implementation.PositionAt(time, currentTime, timeRange, scrollLength);
public void Reset()
=> implementation.Reset();
}
private class TestDrawableControlPoint : DrawableHitObject<HitObject> private class TestDrawableControlPoint : DrawableHitObject<HitObject>
{ {
public TestDrawableControlPoint(ScrollingDirection direction, double time) public TestDrawableControlPoint(ScrollingDirection direction, double time)

View File

@ -1,11 +1,11 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Allocation;
using osu.Framework.Caching; using osu.Framework.Caching;
using osu.Framework.Configuration; using osu.Framework.Configuration;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Lists; using osu.Framework.Lists;
using osu.Game.Configuration;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.Timing;
@ -31,29 +31,17 @@ namespace osu.Game.Rulesets.UI.Scrolling
public readonly Bindable<ScrollingDirection> Direction = new Bindable<ScrollingDirection>(); public readonly Bindable<ScrollingDirection> Direction = new Bindable<ScrollingDirection>();
private readonly IScrollAlgorithm algorithm; [Resolved]
private IScrollAlgorithm algorithm { get; set; }
private Cached initialStateCache = new Cached(); private Cached initialStateCache = new Cached();
public ScrollingHitObjectContainer(ScrollVisualisationMethod visualisationMethod) public ScrollingHitObjectContainer()
{ {
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
TimeRange.ValueChanged += _ => initialStateCache.Invalidate(); TimeRange.ValueChanged += _ => initialStateCache.Invalidate();
Direction.ValueChanged += _ => initialStateCache.Invalidate(); Direction.ValueChanged += _ => initialStateCache.Invalidate();
switch (visualisationMethod)
{
case ScrollVisualisationMethod.Sequential:
algorithm = new SequentialScrollAlgorithm(ControlPoints);
break;
case ScrollVisualisationMethod.Overlapping:
algorithm = new OverlappingScrollAlgorithm(ControlPoints);
break;
case ScrollVisualisationMethod.Constant:
algorithm = new ConstantScrollAlgorithm();
break;
}
} }
public override void Add(DrawableHitObject hitObject) public override void Add(DrawableHitObject hitObject)
@ -70,20 +58,6 @@ namespace osu.Game.Rulesets.UI.Scrolling
return result; return result;
} }
public void AddControlPoint(MultiplierControlPoint controlPoint)
{
ControlPoints.Add(controlPoint);
initialStateCache.Invalidate();
}
public bool RemoveControlPoint(MultiplierControlPoint controlPoint)
{
var result = ControlPoints.Remove(controlPoint);
if (result)
initialStateCache.Invalidate();
return result;
}
public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true)
{ {
if ((invalidation & (Invalidation.RequiredParentSizeToFit | Invalidation.DrawInfo)) > 0) if ((invalidation & (Invalidation.RequiredParentSizeToFit | Invalidation.DrawInfo)) > 0)

View File

@ -5,7 +5,6 @@ using osu.Framework.Allocation;
using osu.Framework.Configuration; using osu.Framework.Configuration;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Game.Configuration;
using osu.Game.Input.Bindings; using osu.Game.Input.Bindings;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
@ -63,8 +62,6 @@ namespace osu.Game.Rulesets.UI.Scrolling
/// </summary> /// </summary>
protected readonly Bindable<ScrollingDirection> Direction = new Bindable<ScrollingDirection>(); protected readonly Bindable<ScrollingDirection> Direction = new Bindable<ScrollingDirection>();
protected virtual ScrollVisualisationMethod VisualisationMethod => ScrollVisualisationMethod.Sequential;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
@ -93,7 +90,7 @@ namespace osu.Game.Rulesets.UI.Scrolling
protected sealed override HitObjectContainer CreateHitObjectContainer() protected sealed override HitObjectContainer CreateHitObjectContainer()
{ {
var container = new ScrollingHitObjectContainer(VisualisationMethod); var container = new ScrollingHitObjectContainer();
container.Direction.BindTo(Direction); container.Direction.BindTo(Direction);
return container; return container;
} }

View File

@ -4,13 +4,14 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Lists; using osu.Framework.Lists;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Configuration;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.Timing;
using osu.Game.Rulesets.UI.Scrolling.Algorithms;
namespace osu.Game.Rulesets.UI.Scrolling namespace osu.Game.Rulesets.UI.Scrolling
{ {
@ -27,11 +28,28 @@ namespace osu.Game.Rulesets.UI.Scrolling
/// inside this <see cref="RulesetContainer{TPlayfield,TObject}"/>. /// inside this <see cref="RulesetContainer{TPlayfield,TObject}"/>.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
protected readonly SortedList<MultiplierControlPoint> DefaultControlPoints = new SortedList<MultiplierControlPoint>(Comparer<MultiplierControlPoint>.Default); private readonly SortedList<MultiplierControlPoint> controlPoints = new SortedList<MultiplierControlPoint>(Comparer<MultiplierControlPoint>.Default);
protected virtual ScrollAlgorithm ScrollAlgorithm => ScrollAlgorithm.Sequential;
[Cached(Type = typeof(IScrollAlgorithm))]
private readonly IScrollAlgorithm algorithm;
protected ScrollingRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) protected ScrollingRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap)
: base(ruleset, beatmap) : base(ruleset, beatmap)
{ {
switch (ScrollAlgorithm)
{
case ScrollAlgorithm.Sequential:
algorithm = new SequentialScrollAlgorithm(controlPoints);
break;
case ScrollAlgorithm.Overlapping:
algorithm = new OverlappingScrollAlgorithm(controlPoints);
break;
case ScrollAlgorithm.Constant:
algorithm = new ConstantScrollAlgorithm();
break;
}
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -75,19 +93,11 @@ namespace osu.Game.Rulesets.UI.Scrolling
// Collapse sections with the same start time // Collapse sections with the same start time
.GroupBy(s => s.StartTime).Select(g => g.Last()).OrderBy(s => s.StartTime); .GroupBy(s => s.StartTime).Select(g => g.Last()).OrderBy(s => s.StartTime);
DefaultControlPoints.AddRange(timingChanges); controlPoints.AddRange(timingChanges);
// If we have no control points, add a default one // If we have no control points, add a default one
if (DefaultControlPoints.Count == 0) if (controlPoints.Count == 0)
DefaultControlPoints.Add(new MultiplierControlPoint { Velocity = Beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier }); controlPoints.Add(new MultiplierControlPoint { Velocity = Beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier });
DefaultControlPoints.ForEach(c => applySpeedAdjustment(c, Playfield));
}
private void applySpeedAdjustment(MultiplierControlPoint controlPoint, ScrollingPlayfield playfield)
{
playfield.HitObjects.AddControlPoint(controlPoint);
playfield.NestedPlayfields?.OfType<ScrollingPlayfield>().ForEach(p => applySpeedAdjustment(controlPoint, p));
} }
} }
} }