mirror of
https://github.com/ppy/osu.git
synced 2025-01-15 15:53:21 +08:00
Merge remote-tracking branch 'smoogipooo/timingchange-improvements' into catch
This commit is contained in:
commit
41fa961571
@ -24,8 +24,6 @@ namespace osu.Desktop.Tests.Visual
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class TestCaseScrollingPlayfield : OsuTestCase
|
public class TestCaseScrollingPlayfield : OsuTestCase
|
||||||
{
|
{
|
||||||
private readonly TestHitRenderer hitRenderer;
|
|
||||||
|
|
||||||
public TestCaseScrollingPlayfield()
|
public TestCaseScrollingPlayfield()
|
||||||
{
|
{
|
||||||
Clock = new FramedClock();
|
Clock = new FramedClock();
|
||||||
@ -52,6 +50,7 @@ namespace osu.Desktop.Tests.Visual
|
|||||||
|
|
||||||
WorkingBeatmap beatmap = new TestWorkingBeatmap(b);
|
WorkingBeatmap beatmap = new TestWorkingBeatmap(b);
|
||||||
|
|
||||||
|
TestHitRenderer hitRenderer;
|
||||||
Add(hitRenderer = new TestHitRenderer(beatmap, true));
|
Add(hitRenderer = new TestHitRenderer(beatmap, true));
|
||||||
|
|
||||||
AddStep("Reverse direction", () => hitRenderer.Playfield.Reversed.Value = !hitRenderer.Playfield.Reversed);
|
AddStep("Reverse direction", () => hitRenderer.Playfield.Reversed.Value = !hitRenderer.Playfield.Reversed);
|
||||||
|
@ -80,9 +80,9 @@ namespace osu.Game.Rulesets.Osu.UI
|
|||||||
|
|
||||||
public override void PostProcess()
|
public override void PostProcess()
|
||||||
{
|
{
|
||||||
connectionLayer.HitObjects = HitObjects.Children
|
connectionLayer.HitObjects = HitObjects.Objects
|
||||||
.Select(d => d.HitObject)
|
.Select(d => d.HitObject)
|
||||||
.OrderBy(h => h.StartTime);
|
.OrderBy(h => h.StartTime).OfType<OsuHitObject>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnJudgement(DrawableHitObject<OsuHitObject, OsuJudgement> judgedObject)
|
public override void OnJudgement(DrawableHitObject<OsuHitObject, OsuJudgement> judgedObject)
|
||||||
|
@ -85,11 +85,13 @@ namespace osu.Game.Rulesets.Timing
|
|||||||
{
|
{
|
||||||
RelativeChildSize = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)-VisibleTimeRange : 1, (ScrollingAxes & Axes.Y) > 0 ? (float)-VisibleTimeRange : 1);
|
RelativeChildSize = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)-VisibleTimeRange : 1, (ScrollingAxes & Axes.Y) > 0 ? (float)-VisibleTimeRange : 1);
|
||||||
RelativeChildOffset = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)VisibleTimeRange : 0, (ScrollingAxes & Axes.Y) > 0 ? (float)VisibleTimeRange : 0);
|
RelativeChildOffset = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)VisibleTimeRange : 0, (ScrollingAxes & Axes.Y) > 0 ? (float)VisibleTimeRange : 0);
|
||||||
|
Origin = Anchor = Anchor.BottomLeft;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RelativeChildSize = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)VisibleTimeRange : 1, (ScrollingAxes & Axes.Y) > 0 ? (float)VisibleTimeRange : 1);
|
RelativeChildSize = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)VisibleTimeRange : 1, (ScrollingAxes & Axes.Y) > 0 ? (float)VisibleTimeRange : 1);
|
||||||
RelativeChildOffset = Vector2.Zero;
|
RelativeChildOffset = Vector2.Zero;
|
||||||
|
Anchor = Anchor = Anchor.TopLeft;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@ using osu.Game.Rulesets.Objects.Drawables;
|
|||||||
using OpenTK;
|
using OpenTK;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.UI
|
namespace osu.Game.Rulesets.UI
|
||||||
{
|
{
|
||||||
@ -19,7 +21,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The HitObjects contained in this Playfield.
|
/// The HitObjects contained in this Playfield.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public HitObjectContainer<DrawableHitObject<TObject, TJudgement>> HitObjects { get; protected set; }
|
public HitObjectContainer HitObjects { get; protected set; }
|
||||||
|
|
||||||
internal Container<Drawable> ScaledContent;
|
internal Container<Drawable> ScaledContent;
|
||||||
|
|
||||||
@ -53,7 +55,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
HitObjects = new HitObjectContainer<DrawableHitObject<TObject, TJudgement>>
|
HitObjects = new HitObjectContainer
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
};
|
};
|
||||||
@ -94,6 +96,13 @@ namespace osu.Game.Rulesets.UI
|
|||||||
/// <param name="judgedObject">The object that Judgement has been updated for.</param>
|
/// <param name="judgedObject">The object that Judgement has been updated for.</param>
|
||||||
public virtual void OnJudgement(DrawableHitObject<TObject, TJudgement> judgedObject) { }
|
public virtual void OnJudgement(DrawableHitObject<TObject, TJudgement> judgedObject) { }
|
||||||
|
|
||||||
|
public class HitObjectContainer : CompositeDrawable
|
||||||
|
{
|
||||||
|
public virtual IEnumerable<DrawableHitObject> Objects => InternalChildren.OfType<DrawableHitObject>();
|
||||||
|
public virtual void Add(DrawableHitObject hitObject) => AddInternal(hitObject);
|
||||||
|
public virtual bool Remove(DrawableHitObject hitObject) => RemoveInternal(hitObject);
|
||||||
|
}
|
||||||
|
|
||||||
private class ScaledContainer : Container
|
private class ScaledContainer : Container
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -104,10 +113,5 @@ namespace osu.Game.Rulesets.UI
|
|||||||
//dividing by the customwidth will effectively scale our content to the required container size.
|
//dividing by the customwidth will effectively scale our content to the required container size.
|
||||||
protected override Vector2 DrawScale => CustomWidth.HasValue ? new Vector2(DrawSize.X / CustomWidth.Value) : base.DrawScale;
|
protected override Vector2 DrawScale => CustomWidth.HasValue ? new Vector2(DrawSize.X / CustomWidth.Value) : base.DrawScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class HitObjectContainer<U> : Container<U>
|
|
||||||
where U : Drawable
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A container that provides the foundation for sorting <see cref="DrawableHitObject"/>s into <see cref="SpeedAdjustmentContainer"/>s.
|
/// A container that provides the foundation for sorting <see cref="DrawableHitObject"/>s into <see cref="SpeedAdjustmentContainer"/>s.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class ScrollingHitObjectContainer : HitObjectContainer<DrawableHitObject<TObject, TJudgement>>
|
internal class ScrollingHitObjectContainer : HitObjectContainer
|
||||||
{
|
{
|
||||||
private readonly BindableDouble visibleTimeRange = new BindableDouble { Default = 1000 };
|
private readonly BindableDouble visibleTimeRange = new BindableDouble { Default = 1000 };
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -164,13 +164,11 @@ namespace osu.Game.Rulesets.UI
|
|||||||
set { reversed.BindTo(value); }
|
set { reversed.BindTo(value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Container<DrawableHitObject<TObject, TJudgement>> Content => content;
|
|
||||||
private readonly Container<DrawableHitObject<TObject, TJudgement>> content;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Hit objects that are to be re-processed on the next update.
|
/// Hit objects that are to be re-processed on the next update.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly List<DrawableHitObject<TObject, TJudgement>> queuedHitObjects = new List<DrawableHitObject<TObject, TJudgement>>();
|
private readonly List<DrawableHitObject> queuedHitObjects = new List<DrawableHitObject>();
|
||||||
|
private readonly Container<SpeedAdjustmentContainer> speedAdjustments;
|
||||||
|
|
||||||
private readonly Axes scrollingAxes;
|
private readonly Axes scrollingAxes;
|
||||||
|
|
||||||
@ -182,8 +180,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
{
|
{
|
||||||
this.scrollingAxes = scrollingAxes;
|
this.scrollingAxes = scrollingAxes;
|
||||||
|
|
||||||
// The following is never used - it only exists for the purpose of being able to use AddInternal below.
|
AddInternal(speedAdjustments = new Container<SpeedAdjustmentContainer> { RelativeSizeAxes = Axes.Both });
|
||||||
content = new Container<DrawableHitObject<TObject, TJudgement>>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -195,15 +192,17 @@ namespace osu.Game.Rulesets.UI
|
|||||||
speedAdjustment.VisibleTimeRange.BindTo(VisibleTimeRange);
|
speedAdjustment.VisibleTimeRange.BindTo(VisibleTimeRange);
|
||||||
speedAdjustment.ScrollingAxes = scrollingAxes;
|
speedAdjustment.ScrollingAxes = scrollingAxes;
|
||||||
speedAdjustment.Reversed = Reversed;
|
speedAdjustment.Reversed = Reversed;
|
||||||
AddInternal(speedAdjustment);
|
speedAdjustments.Add(speedAdjustment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<DrawableHitObject> Objects => speedAdjustments.SelectMany(s => s.Children);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a hit object to this <see cref="ScrollingHitObjectContainer"/>. The hit objects will be queued to be processed
|
/// Adds a hit object to this <see cref="ScrollingHitObjectContainer"/>. The hit objects will be queued to be processed
|
||||||
/// new <see cref="SpeedAdjustmentContainer"/>s are added to this <see cref="ScrollingHitObjectContainer"/>.
|
/// new <see cref="SpeedAdjustmentContainer"/>s are added to this <see cref="ScrollingHitObjectContainer"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="hitObject">The hit object to add.</param>
|
/// <param name="hitObject">The hit object to add.</param>
|
||||||
public override void Add(DrawableHitObject<TObject, TJudgement> hitObject)
|
public override void Add(DrawableHitObject hitObject)
|
||||||
{
|
{
|
||||||
if (!(hitObject is IScrollingHitObject))
|
if (!(hitObject is IScrollingHitObject))
|
||||||
throw new InvalidOperationException($"Hit objects added to a {nameof(ScrollingHitObjectContainer)} must implement {nameof(IScrollingHitObject)}.");
|
throw new InvalidOperationException($"Hit objects added to a {nameof(ScrollingHitObjectContainer)} must implement {nameof(IScrollingHitObject)}.");
|
||||||
@ -211,13 +210,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
queuedHitObjects.Add(hitObject);
|
queuedHitObjects.Add(hitObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Remove(DrawableHitObject<TObject, TJudgement> hitObject)
|
public override bool Remove(DrawableHitObject hitObject) => speedAdjustments.Any(s => s.Remove(hitObject)) || queuedHitObjects.Remove(hitObject);
|
||||||
{
|
|
||||||
bool removed = InternalChildren.OfType<SpeedAdjustmentContainer>().Any(c => c.Remove(hitObject));
|
|
||||||
removed = removed || queuedHitObjects.Remove(hitObject);
|
|
||||||
|
|
||||||
return removed;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
@ -246,7 +239,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="hitObject">The hit object to find the active <see cref="SpeedAdjustmentContainer"/> for.</param>
|
/// <param name="hitObject">The hit object to find the active <see cref="SpeedAdjustmentContainer"/> for.</param>
|
||||||
/// <returns>The <see cref="SpeedAdjustmentContainer"/> active at <paramref name="hitObject"/>'s start time. Null if there are no speed adjustments.</returns>
|
/// <returns>The <see cref="SpeedAdjustmentContainer"/> active at <paramref name="hitObject"/>'s start time. Null if there are no speed adjustments.</returns>
|
||||||
private SpeedAdjustmentContainer adjustmentContainerFor(DrawableHitObject hitObject) => InternalChildren.OfType<SpeedAdjustmentContainer>().FirstOrDefault(c => c.CanContain(hitObject)) ?? InternalChildren.OfType<SpeedAdjustmentContainer>().LastOrDefault();
|
private SpeedAdjustmentContainer adjustmentContainerFor(DrawableHitObject hitObject) => speedAdjustments.FirstOrDefault(c => c.CanContain(hitObject)) ?? speedAdjustments.LastOrDefault();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finds the <see cref="SpeedAdjustmentContainer"/> which provides the speed adjustment active at a time.
|
/// Finds the <see cref="SpeedAdjustmentContainer"/> which provides the speed adjustment active at a time.
|
||||||
@ -254,7 +247,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="time">The time to find the active <see cref="SpeedAdjustmentContainer"/> at.</param>
|
/// <param name="time">The time to find the active <see cref="SpeedAdjustmentContainer"/> at.</param>
|
||||||
/// <returns>The <see cref="SpeedAdjustmentContainer"/> active at <paramref name="time"/>. Null if there are no speed adjustments.</returns>
|
/// <returns>The <see cref="SpeedAdjustmentContainer"/> active at <paramref name="time"/>. Null if there are no speed adjustments.</returns>
|
||||||
private SpeedAdjustmentContainer adjustmentContainerAt(double time) => InternalChildren.OfType<SpeedAdjustmentContainer>().FirstOrDefault(c => c.CanContain(time)) ?? InternalChildren.OfType<SpeedAdjustmentContainer>().LastOrDefault();
|
private SpeedAdjustmentContainer adjustmentContainerAt(double time) => speedAdjustments.FirstOrDefault(c => c.CanContain(time)) ?? speedAdjustments.LastOrDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user