1
0
mirror of https://github.com/ppy/osu.git synced 2025-03-23 04:27:18 +08:00

Cleanups + xmldoc rewordings/improvements.

This commit is contained in:
smoogipooo 2017-06-12 15:20:34 +09:00
parent 419682b740
commit ba8014bbd9
9 changed files with 108 additions and 66 deletions

@ -7,8 +7,17 @@ using osu.Game.Rulesets.Timing;
namespace osu.Game.Rulesets.Mania.Mods
{
/// <summary>
/// A type of mod which generates speed adjustments that scroll the hit objects and bar lines.
/// </summary>
internal interface IGenerateSpeedAdjustments
{
/// <summary>
/// Applies this mod to a hit renderer.
/// </summary>
/// <param name="hitRenderer">The hit renderer to apply to.</param>
/// <param name="hitObjectTimingChanges">The per-column list of speed adjustments for hit objects.</param>
/// <param name="barlineTimingChanges">The list of speed adjustments for bar lines.</param>
void ApplyToHitRenderer(ManiaHitRenderer hitRenderer, ref List<SpeedAdjustmentContainer>[] hitObjectTimingChanges, ref List<SpeedAdjustmentContainer> barlineTimingChanges);
}
}

@ -7,7 +7,6 @@ using osu.Game.Rulesets.Mania.UI;
using osu.Game.Rulesets.Mods;
using osu.Game.Graphics;
using osu.Game.Rulesets.Mania.Timing;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Timing;
using osu.Game.Rulesets.Mania.Objects.Drawables;
@ -23,21 +22,21 @@ namespace osu.Game.Rulesets.Mania.Mods
public void ApplyToHitRenderer(ManiaHitRenderer hitRenderer, ref List<SpeedAdjustmentContainer>[] hitObjectTimingChanges, ref List<SpeedAdjustmentContainer> barlineTimingChanges)
{
foreach (HitObject obj in hitRenderer.Objects)
// We have to generate one speed adjustment per hit object for gravity
foreach (ManiaHitObject obj in hitRenderer.Objects)
{
var maniaObject = obj as ManiaHitObject;
if (maniaObject == null)
continue;
MultiplierControlPoint controlPoint = hitRenderer.CreateControlPointAt(obj.StartTime);
// Beat length has too large of an effect for gravity, so we'll force it to a constant value for now
controlPoint.TimingPoint.BeatLength = 1000;
hitObjectTimingChanges[maniaObject.Column].Add(new ManiaSpeedAdjustmentContainer(controlPoint, ScrollingAlgorithm.Gravity));
hitObjectTimingChanges[obj.Column].Add(new ManiaSpeedAdjustmentContainer(controlPoint, ScrollingAlgorithm.Gravity));
}
// Like with hit objects, we need to generate one speed adjustment per bar line
foreach (DrawableBarLine barLine in hitRenderer.BarLines)
{
var controlPoint = hitRenderer.CreateControlPointAt(barLine.HitObject.StartTime);
// Beat length has too large of an effect for gravity, so we'll force it to a constant value for now
controlPoint.TimingPoint.BeatLength = 1000;
barlineTimingChanges.Add(new ManiaSpeedAdjustmentContainer(controlPoint, ScrollingAlgorithm.Gravity));

@ -6,21 +6,24 @@ using osu.Game.Rulesets.Timing;
namespace osu.Game.Rulesets.Mania.Timing
{
/// <summary>
/// A <see cref="DrawableTimingSection"/> which scrolls relative to the control point start time.
/// </summary>
internal class BasicScrollingDrawableTimingSection : DrawableTimingSection
{
private readonly MultiplierControlPoint timingSection;
private readonly MultiplierControlPoint controlPoint;
public BasicScrollingDrawableTimingSection(MultiplierControlPoint timingSection)
public BasicScrollingDrawableTimingSection(MultiplierControlPoint controlPoint)
: base(Axes.Y)
{
this.timingSection = timingSection;
this.controlPoint = controlPoint;
}
protected override void Update()
{
base.Update();
Y = (float)(timingSection.StartTime - Time.Current);
Y = (float)(controlPoint.StartTime - Time.Current);
}
}
}

@ -6,14 +6,17 @@ using osu.Game.Rulesets.Timing;
namespace osu.Game.Rulesets.Mania.Timing
{
/// <summary>
/// A <see cref="DrawableTimingSection"/> that emulates a form of gravity where hit objects speed up over time.
/// </summary>
internal class GravityScrollingDrawableTimingSection : DrawableTimingSection
{
private readonly MultiplierControlPoint timingSection;
private readonly MultiplierControlPoint controlPoint;
public GravityScrollingDrawableTimingSection(MultiplierControlPoint timingSection)
public GravityScrollingDrawableTimingSection(MultiplierControlPoint controlPoint)
: base(Axes.Y)
{
this.timingSection = timingSection;
this.controlPoint = controlPoint;
}
protected override void UpdateAfterChildren()
@ -21,9 +24,9 @@ namespace osu.Game.Rulesets.Mania.Timing
base.UpdateAfterChildren();
// The gravity-adjusted start position
float startPos = (float)computeGravityTime(timingSection.StartTime);
float startPos = (float)computeGravityTime(controlPoint.StartTime);
// The gravity-adjusted end position
float endPos = (float)computeGravityTime(timingSection.StartTime + RelativeChildSize.Y);
float endPos = (float)computeGravityTime(controlPoint.StartTime + RelativeChildSize.Y);
Y = startPos;
Height = endPos - startPos;

@ -1,7 +1,6 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// 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.Caching;
@ -24,19 +23,21 @@ namespace osu.Game.Rulesets.Timing
/// </para>
///
/// <para>
/// This container will auto-size to the total size of its children along the desired auto-sizing axes such that the reasulting size
/// of this container will also be a time value.
/// This container will auto-size to the total duration of the contained hit objects along the desired auto-sizing axes such that the resulting size
/// of this container will be a value representing the total duration of all contained hit objects.
/// </para>
///
/// <para>
/// This container is and must always be relatively-sized and positioned to its such that the parent can utilise
/// <see cref="Container{T}.RelativeChildSize"/> and <see cref="Container{T}.RelativeChildOffset"/> to apply further time offsets
/// to this collection of hit objects.
/// This container is and must always be relatively-sized and positioned to its such that the parent can utilise <see cref="Container{T}.RelativeChildSize"/>
/// and <see cref="Container{T}.RelativeChildOffset"/> to apply further time offsets to this collection of hit objects.
/// </para>
/// </summary>
public abstract class DrawableTimingSection : Container<DrawableHitObject>
{
private readonly BindableDouble visibleTimeRange = new BindableDouble();
/// <summary>
/// Gets or sets the range of time that is visible by the length of this container.
/// </summary>
public BindableDouble VisibleTimeRange
{
get { return visibleTimeRange; }
@ -57,18 +58,8 @@ namespace osu.Game.Rulesets.Timing
{
this.autoSizingAxes = autoSizingAxes;
RelativeSizeAxes = Axes.Both;
RelativePositionAxes = Axes.Both;
// We need a default size since RelativeSizeAxes is overridden
Size = Vector2.One;
}
public override Axes AutoSizeAxes { set { throw new InvalidOperationException($"{nameof(DrawableTimingSection)} must always be relatively-sized."); } }
public override Axes RelativeSizeAxes
{
get { return Axes.Both; }
set { throw new InvalidOperationException($"{nameof(DrawableTimingSection)} must always be relatively-sized."); }
}
public override void InvalidateFromChild(Invalidation invalidation)

@ -10,27 +10,46 @@ namespace osu.Game.Rulesets.Timing
public class MultiplierControlPoint : IJsonSerializable, IComparable<MultiplierControlPoint>
{
/// <summary>
/// The time in milliseconds at which this control point starts.
/// The time in milliseconds at which this <see cref="MultiplierControlPoint"/> starts.
/// </summary>
public readonly double StartTime;
/// <summary>
/// The multiplier which this control point provides.
/// The multiplier which this <see cref="MultiplierControlPoint"/> provides.
/// </summary>
public double Multiplier => 1000 / TimingPoint.BeatLength / DifficultyPoint.SpeedMultiplier;
/// <summary>
/// The <see cref="TimingControlPoint"/> that provides the timing information for this <see cref="MultiplierControlPoint"/>.
/// </summary>
public TimingControlPoint TimingPoint = new TimingControlPoint();
/// <summary>
/// The <see cref="DifficultyControlPoint"/> that provides additional difficulty information for this <see cref="MultiplierControlPoint"/>.
/// </summary>
public DifficultyControlPoint DifficultyPoint = new DifficultyControlPoint();
/// <summary>
/// Creates a <see cref="MultiplierControlPoint"/>. This is required for JSON serialization
/// </summary>
public MultiplierControlPoint()
{
}
/// <summary>
/// Creates a <see cref="MultiplierControlPoint"/>.
/// </summary>
/// <param name="startTime">The start time of this <see cref="MultiplierControlPoint"/>.</param>
public MultiplierControlPoint(double startTime)
{
StartTime = startTime;
}
/// <summary>
/// Creates a <see cref="MultiplierControlPoint"/> by copying another <see cref="MultiplierControlPoint"/>.
/// </summary>
/// <param name="startTime">The start time of this <see cref="MultiplierControlPoint"/>.</param>
/// <param name="other">The <see cref="MultiplierControlPoint"/> to copy.</param>
public MultiplierControlPoint(double startTime, MultiplierControlPoint other)
: this(startTime)
{

@ -15,14 +15,16 @@ namespace osu.Game.Rulesets.Timing
/// A collection of <see cref="SpeedAdjustmentContainer"/>s.
///
/// <para>
/// This container provides <see cref="VisibleTimeRange"/> for the <see cref="SpeedAdjustmentContainer"/>s.
/// This container redirects any <see cref="DrawableHitObject"/>'s added to it to the <see cref="SpeedAdjustmentContainer"/>
/// which provides the speed adjustment active at the start time of the hit object. Furthermore, this container provides the
/// necessary <see cref="VisibleTimeRange"/> for the contained <see cref="SpeedAdjustmentContainer"/>s.
/// </para>
/// </summary>
public class SpeedAdjustmentCollection : Container<SpeedAdjustmentContainer>
{
private readonly BindableDouble visibleTimeRange = new BindableDouble();
/// <summary>
/// The amount of time visible by span of this container.
/// Gets or sets the range of time that is visible by the length of this container.
/// For example, only hit objects with start time less than or equal to 1000 will be visible with <see cref="VisibleTimeRange"/> = 1000.
/// </summary>
public Bindable<double> VisibleTimeRange
@ -32,15 +34,16 @@ namespace osu.Game.Rulesets.Timing
}
/// <summary>
/// Adds a hit object to the most applicable timing section in this container.
/// Adds a hit object to the <see cref="SpeedAdjustmentContainer"/> which provides the speed adjustment
/// active at the start time of the hit object.
/// </summary>
/// <param name="hitObject">The hit object to add.</param>
public void Add(DrawableHitObject hitObject)
{
var target = timingSectionFor(hitObject);
var target = adjustmentContainerFor(hitObject);
if (target == null)
throw new ArgumentException("No timing section could be found that can contain the hit object.", nameof(hitObject));
throw new ArgumentException("No speed adjustment could be found that can contain the hit object.", nameof(hitObject));
target.Add(hitObject);
}
@ -51,33 +54,34 @@ namespace osu.Game.Rulesets.Timing
base.Add(speedAdjustment);
}
protected override IComparer<Drawable> DepthComparer => new TimingSectionReverseStartTimeComparer();
protected override IComparer<Drawable> DepthComparer => new SpeedAdjustmentContainerReverseStartTimeComparer();
/// <summary>
/// Finds the most applicable timing section that can contain a hit object. If the hit object occurs before the first (time-wise)
/// timing section, then the timing section returned is the first (time-wise) timing section.
/// Finds the <see cref="SpeedAdjustmentContainer"/> which provides the speed adjustment active at the start time
/// of a hit object. If there is no <see cref="SpeedAdjustmentContainer"/> active at the start time of the hit object,
/// then the first (time-wise) speed adjustment is returned.
/// </summary>
/// <param name="hitObject">The hit object to contain.</param>
/// <returns>The last (time-wise) timing section which can contain <paramref name="hitObject"/>. Null if no timing section exists.</returns>
private SpeedAdjustmentContainer timingSectionFor(DrawableHitObject hitObject) => Children.FirstOrDefault(c => c.CanContain(hitObject)) ?? Children.LastOrDefault();
/// <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>
private SpeedAdjustmentContainer adjustmentContainerFor(DrawableHitObject hitObject) => Children.FirstOrDefault(c => c.CanContain(hitObject)) ?? Children.LastOrDefault();
/// <summary>
/// Compares two timing sections by their start time, falling back to creation order if their start time is equal.
/// This will compare the two timing sections in reverse order.
/// Compares two speed adjustment containers by their control point start time, falling back to creation order
// if their control point start time is equal. This will compare the two speed adjustment containers in reverse order.
/// </summary>
private class TimingSectionReverseStartTimeComparer : ReverseCreationOrderDepthComparer
private class SpeedAdjustmentContainerReverseStartTimeComparer : ReverseCreationOrderDepthComparer
{
public override int Compare(Drawable x, Drawable y)
{
var timingChangeX = x as SpeedAdjustmentContainer;
var timingChangeY = y as SpeedAdjustmentContainer;
var speedAdjustmentX = x as SpeedAdjustmentContainer;
var speedAdjustmentY = y as SpeedAdjustmentContainer;
// If either of the two drawables are not hit objects, fall back to the base comparer
if (timingChangeX?.MultiplierControlPoint == null || timingChangeY?.MultiplierControlPoint == null)
if (speedAdjustmentX?.MultiplierControlPoint == null || speedAdjustmentY?.MultiplierControlPoint == null)
return base.Compare(x, y);
// Compare by start time
int i = timingChangeY.MultiplierControlPoint.StartTime.CompareTo(timingChangeX.MultiplierControlPoint.StartTime);
int i = speedAdjustmentY.MultiplierControlPoint.StartTime.CompareTo(speedAdjustmentX.MultiplierControlPoint.StartTime);
return i != 0 ? i : base.Compare(x, y);
}

@ -1,7 +1,6 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Graphics;
@ -12,18 +11,29 @@ using OpenTK;
namespace osu.Game.Rulesets.Timing
{
/// <summary>
/// A container for hit objects which applies applies the speed adjustments defined by the <see cref="Timing.MultiplierControlPoint"/> properties
/// to its <see cref="Container{T}.Content"/> to affect the <see cref="DrawableTimingSection"/> scroll speed.
/// A container for hit objects which applies applies the speed adjustments defined by the properties of a <see cref="Timing.MultiplierControlPoint"/>
/// to affect the scroll speed of the contained <see cref="DrawableTimingSection"/>.
///
/// <para>
/// This container must always be relatively-sized to its parent to provide the speed adjustments. This container will provide the speed adjustments
/// by modifying its size while maintaining a constant <see cref="Container{T}.RelativeChildSize"/> for its children
/// </para>
/// </summary>
public abstract class SpeedAdjustmentContainer : Container<DrawableHitObject>
{
private readonly Bindable<double> visibleTimeRange = new Bindable<double>();
/// <summary>
/// Gets or sets the range of time that is visible by the length of this container.
/// </summary>
public Bindable<double> VisibleTimeRange
{
get { return visibleTimeRange; }
set { visibleTimeRange.BindTo(value); }
}
/// <summary>
/// The <see cref="MultiplierControlPoint"/> which provides the speed adjustments for this container.
/// </summary>
public readonly MultiplierControlPoint MultiplierControlPoint;
protected override Container<DrawableHitObject> Content => content;
@ -34,12 +44,14 @@ namespace osu.Game.Rulesets.Timing
/// <summary>
/// Creates a new <see cref="SpeedAdjustmentContainer"/>.
/// </summary>
/// <param name="multiplierControlPoint">The multiplier control point that provides the speed adjustments for this container.</param>
/// <param name="scrollingAxes">The axes through which this drawable timing section scrolls through.</param>
/// <param name="multiplierControlPoint">The <see cref="MultiplierControlPoint"/> which provides the speed adjustments for this container.</param>
/// <param name="scrollingAxes">The axes through which the content of this container should scroll through.</param>
protected SpeedAdjustmentContainer(MultiplierControlPoint multiplierControlPoint, Axes scrollingAxes)
{
this.scrollingAxes = scrollingAxes;
RelativeSizeAxes = Axes.Both;
MultiplierControlPoint = multiplierControlPoint;
}
@ -54,12 +66,6 @@ namespace osu.Game.Rulesets.Timing
AddInternal(content = timingSection);
}
public override Axes RelativeSizeAxes
{
get { return Axes.Both; }
set { throw new InvalidOperationException($"{nameof(SpeedAdjustmentContainer)} must always be relatively-sized."); }
}
protected override void Update()
{
float multiplier = (float)MultiplierControlPoint.Multiplier;
@ -77,7 +83,7 @@ namespace osu.Game.Rulesets.Timing
/// <summary>
/// Creates the container which handles the movement of a collection of hit objects.
/// </summary>
/// <returns>The drawable timing section.</returns>
/// <returns>The <see cref="DrawableTimingSection"/>.</returns>
protected abstract DrawableTimingSection CreateTimingSection();
}
}

@ -120,6 +120,11 @@ namespace osu.Game.Rulesets.UI
/// </summary>
public Beatmap<TObject> Beatmap;
/// <summary>
/// All the converted hit objects contained by this hit renderer.
/// </summary>
public override IEnumerable<HitObject> Objects => Beatmap.HitObjects;
/// <summary>
/// The mods which are to be applied.
/// </summary>
@ -206,7 +211,10 @@ namespace osu.Game.Rulesets.UI
public sealed override bool ProvidingUserCursor => !HasReplayLoaded && Playfield.ProvidingUserCursor;
public override IEnumerable<HitObject> Objects => Beatmap.HitObjects;
/// <summary>
/// All the converted hit objects contained by this hit renderer.
/// </summary>
public new IEnumerable<TObject> Objects => Beatmap.HitObjects;
protected override bool AllObjectsJudged => drawableObjects.All(h => h.Judged);