mirror of
https://github.com/ppy/osu.git
synced 2024-12-13 08:32:57 +08:00
Remove IContext & add IHasGenerateTicks
This commit is contained in:
parent
e27c4dfa10
commit
6c70948681
@ -51,8 +51,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(hitObject.StartTime);
|
TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(hitObject.StartTime);
|
||||||
|
|
||||||
double beatLength;
|
double beatLength;
|
||||||
if (hitObject.HasContext<LegacyContext>())
|
if (hitObject.LegacyBpmMultiplier.HasValue)
|
||||||
beatLength = timingPoint.BeatLength * hitObject.GetContext<LegacyContext>().BpmMultiplier;
|
beatLength = timingPoint.BeatLength * hitObject.LegacyBpmMultiplier.Value;
|
||||||
else if (hitObject is IHasSliderVelocity hasSliderVelocity)
|
else if (hitObject is IHasSliderVelocity hasSliderVelocity)
|
||||||
beatLength = timingPoint.BeatLength / hasSliderVelocity.SliderVelocity;
|
beatLength = timingPoint.BeatLength / hasSliderVelocity.SliderVelocity;
|
||||||
else
|
else
|
||||||
|
@ -15,14 +15,13 @@ using osu.Framework.Caching;
|
|||||||
using osu.Game.Audio;
|
using osu.Game.Audio;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Beatmaps.Legacy;
|
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Osu.Judgements;
|
using osu.Game.Rulesets.Osu.Judgements;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Objects
|
namespace osu.Game.Rulesets.Osu.Objects
|
||||||
{
|
{
|
||||||
public class Slider : OsuHitObject, IHasPathWithRepeats, IHasSliderVelocity
|
public class Slider : OsuHitObject, IHasPathWithRepeats, IHasSliderVelocity, IHasGenerateTicks
|
||||||
{
|
{
|
||||||
public double EndTime => StartTime + this.SpanCount() * Path.Distance / Velocity;
|
public double EndTime => StartTime + this.SpanCount() * Path.Distance / Velocity;
|
||||||
|
|
||||||
@ -143,6 +142,8 @@ namespace osu.Game.Rulesets.Osu.Objects
|
|||||||
set => SliderVelocityBindable.Value = value;
|
set => SliderVelocityBindable.Value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool GenerateTicks { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public SliderHeadCircle HeadCircle { get; protected set; }
|
public SliderHeadCircle HeadCircle { get; protected set; }
|
||||||
|
|
||||||
@ -162,10 +163,9 @@ namespace osu.Game.Rulesets.Osu.Objects
|
|||||||
TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime);
|
TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime);
|
||||||
|
|
||||||
double scoringDistance = BASE_SCORING_DISTANCE * difficulty.SliderMultiplier * SliderVelocity;
|
double scoringDistance = BASE_SCORING_DISTANCE * difficulty.SliderMultiplier * SliderVelocity;
|
||||||
bool generateTicks = !HasContext<LegacyContext>() || GetContext<LegacyContext>().GenerateTicks;
|
|
||||||
|
|
||||||
Velocity = scoringDistance / timingPoint.BeatLength;
|
Velocity = scoringDistance / timingPoint.BeatLength;
|
||||||
TickDistance = generateTicks ? (scoringDistance / difficulty.SliderTickRate * TickDistanceMultiplier) : double.PositiveInfinity;
|
TickDistance = GenerateTicks ? (scoringDistance / difficulty.SliderTickRate * TickDistanceMultiplier) : double.PositiveInfinity;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void CreateNestedHitObjects(CancellationToken cancellationToken)
|
protected override void CreateNestedHitObjects(CancellationToken cancellationToken)
|
||||||
|
@ -180,8 +180,8 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
|||||||
TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(obj.StartTime);
|
TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(obj.StartTime);
|
||||||
|
|
||||||
double beatLength;
|
double beatLength;
|
||||||
if (obj.HasContext<LegacyContext>())
|
if (obj.LegacyBpmMultiplier.HasValue)
|
||||||
beatLength = timingPoint.BeatLength * obj.GetContext<LegacyContext>().BpmMultiplier;
|
beatLength = timingPoint.BeatLength * obj.LegacyBpmMultiplier.Value;
|
||||||
else if (obj is IHasSliderVelocity hasSliderVelocity)
|
else if (obj is IHasSliderVelocity hasSliderVelocity)
|
||||||
beatLength = timingPoint.BeatLength / hasSliderVelocity.SliderVelocity;
|
beatLength = timingPoint.BeatLength / hasSliderVelocity.SliderVelocity;
|
||||||
else
|
else
|
||||||
|
@ -105,7 +105,11 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
#pragma warning disable 618
|
#pragma warning disable 618
|
||||||
if (difficultyControlPoint is LegacyDifficultyControlPoint legacyDifficultyControlPoint)
|
if (difficultyControlPoint is LegacyDifficultyControlPoint legacyDifficultyControlPoint)
|
||||||
#pragma warning restore 618
|
#pragma warning restore 618
|
||||||
hitObject.SetContext(new LegacyContext(legacyDifficultyControlPoint.BpmMultiplier, legacyDifficultyControlPoint.GenerateTicks));
|
{
|
||||||
|
hitObject.LegacyBpmMultiplier = legacyDifficultyControlPoint.BpmMultiplier;
|
||||||
|
if (hitObject is IHasGenerateTicks hasGenerateTicks)
|
||||||
|
hasGenerateTicks.GenerateTicks = legacyDifficultyControlPoint.GenerateTicks;
|
||||||
|
}
|
||||||
|
|
||||||
if (hitObject is IHasSliderVelocity hasSliderVelocity)
|
if (hitObject is IHasSliderVelocity hasSliderVelocity)
|
||||||
hasSliderVelocity.SliderVelocity = difficultyControlPoint.SliderVelocity;
|
hasSliderVelocity.SliderVelocity = difficultyControlPoint.SliderVelocity;
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
|
||||||
|
|
||||||
using osu.Game.Context;
|
|
||||||
|
|
||||||
namespace osu.Game.Beatmaps.Legacy;
|
|
||||||
|
|
||||||
public class LegacyContext : IContext
|
|
||||||
{
|
|
||||||
public LegacyContext(double bpmMultiplier, bool generateTicks)
|
|
||||||
{
|
|
||||||
BpmMultiplier = bpmMultiplier;
|
|
||||||
GenerateTicks = generateTicks;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Legacy BPM multiplier that introduces floating-point errors for rulesets that depend on it.
|
|
||||||
/// DO NOT USE THIS UNLESS 100% SURE.
|
|
||||||
/// </summary>
|
|
||||||
public double BpmMultiplier { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether or not slider ticks should be generated at this control point.
|
|
||||||
/// This exists for backwards compatibility with maps that abuse NaN slider velocity behavior on osu!stable (e.g. /b/2628991).
|
|
||||||
/// </summary>
|
|
||||||
public bool GenerateTicks { get; }
|
|
||||||
|
|
||||||
public IContext Copy()
|
|
||||||
{
|
|
||||||
return new LegacyContext(BpmMultiplier, GenerateTicks);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,91 +0,0 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace osu.Game.Context
|
|
||||||
{
|
|
||||||
public abstract class ContextContainer
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The contexts of this container.
|
|
||||||
/// The objects always have the type of their key.
|
|
||||||
/// </summary>
|
|
||||||
private readonly Dictionary<Type, IContext> contexts;
|
|
||||||
|
|
||||||
protected ContextContainer()
|
|
||||||
{
|
|
||||||
contexts = new Dictionary<Type, IContext>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks whether this object has the context with type T.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">The type to check the context of.</typeparam>
|
|
||||||
/// <returns>Whether the context object with type T exists in this object.</returns>
|
|
||||||
public bool HasContext<T>() where T : IContext
|
|
||||||
{
|
|
||||||
return contexts.ContainsKey(typeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the context with type T.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">The type to get the context of.</typeparam>
|
|
||||||
/// <exception cref="KeyNotFoundException">If the context does not exist in this hit object.</exception>
|
|
||||||
/// <returns>The context object with type T.</returns>
|
|
||||||
public T GetContext<T>() where T : IContext
|
|
||||||
{
|
|
||||||
return (T)contexts[typeof(T)];
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tries to get the context with type T.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="context">The found context with type T.</param>
|
|
||||||
/// <typeparam name="T">The type to get the context of.</typeparam>
|
|
||||||
/// <returns>Whether the context exists in this object.</returns>
|
|
||||||
public bool TryGetContext<T>(out T context) where T : IContext
|
|
||||||
{
|
|
||||||
if (contexts.TryGetValue(typeof(T), out var context2))
|
|
||||||
{
|
|
||||||
context = (T)context2;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
context = default!;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the context object of type T.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">The context type to set.</typeparam>
|
|
||||||
/// <param name="context">The context object to store in this object.</param>
|
|
||||||
public void SetContext<T>(T context) where T : IContext
|
|
||||||
{
|
|
||||||
contexts[typeof(T)] = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes the context of type T from this object.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">The type to remove the context of.</typeparam>
|
|
||||||
/// <returns>Whether a context was removed.</returns>
|
|
||||||
public bool RemoveContext<T>() where T : IContext
|
|
||||||
{
|
|
||||||
return RemoveContext(typeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes the context of type T from this object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="t">The type to remove the context of.</param>
|
|
||||||
/// <returns>Whether a context was removed.</returns>
|
|
||||||
public bool RemoveContext(Type t)
|
|
||||||
{
|
|
||||||
return contexts.Remove(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
|
||||||
|
|
||||||
namespace osu.Game.Context;
|
|
||||||
|
|
||||||
public interface IContext
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Makes a deep copy of this context.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The deep copy of this context.</returns>
|
|
||||||
public IContext Copy();
|
|
||||||
}
|
|
@ -16,7 +16,6 @@ using osu.Framework.Lists;
|
|||||||
using osu.Game.Audio;
|
using osu.Game.Audio;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Context;
|
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
@ -29,7 +28,7 @@ namespace osu.Game.Rulesets.Objects
|
|||||||
/// HitObjects may contain more properties for which you should be checking through the IHas* types.
|
/// HitObjects may contain more properties for which you should be checking through the IHas* types.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class HitObject : ContextContainer
|
public class HitObject
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A small adjustment to the start time of control points to account for rounding/precision errors.
|
/// A small adjustment to the start time of control points to account for rounding/precision errors.
|
||||||
@ -80,6 +79,12 @@ namespace osu.Game.Rulesets.Objects
|
|||||||
public SampleControlPoint SampleControlPoint = SampleControlPoint.DEFAULT;
|
public SampleControlPoint SampleControlPoint = SampleControlPoint.DEFAULT;
|
||||||
public DifficultyControlPoint DifficultyControlPoint = DifficultyControlPoint.DEFAULT;
|
public DifficultyControlPoint DifficultyControlPoint = DifficultyControlPoint.DEFAULT;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Legacy BPM multiplier that introduces floating-point errors for rulesets that depend on it.
|
||||||
|
/// DO NOT USE THIS UNLESS 100% SURE.
|
||||||
|
/// </summary>
|
||||||
|
public double? LegacyBpmMultiplier { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether this <see cref="HitObject"/> is in Kiai time.
|
/// Whether this <see cref="HitObject"/> is in Kiai time.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
17
osu.Game/Rulesets/Objects/Types/IHasGenerateTicks.cs
Normal file
17
osu.Game/Rulesets/Objects/Types/IHasGenerateTicks.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Objects.Types
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A type of <see cref="HitObject"/> which may or may not generate ticks.
|
||||||
|
/// </summary>
|
||||||
|
public interface IHasGenerateTicks
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Whether or not slider ticks should be generated at this control point.
|
||||||
|
/// This exists for backwards compatibility with maps that abuse NaN slider velocity behavior on osu!stable (e.g. /b/2628991).
|
||||||
|
/// </summary>
|
||||||
|
public bool GenerateTicks { get; set; }
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user