mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 10:12:54 +08:00
Fix sample control point time being calculated before defaults applied
In editor contexts, the `StartTimeBindable` subscription in `HitObject` was firing before defaults were applied, which in the case of sliders manifested in an infinite end time. `ApplyDefaults()` also did not always set the time of the control point to the correct value, which matters when the beatmap is encoded. Ensure that the control points receive the correct time values during default application, and only register the `StartTimeBindable` change callback after defaults have been successfully applied.
This commit is contained in:
parent
e91d3dd8b4
commit
7a25fe79b7
@ -87,23 +87,6 @@ namespace osu.Game.Rulesets.Objects
|
||||
[JsonIgnore]
|
||||
public SlimReadOnlyListWrapper<HitObject> NestedHitObjects => nestedHitObjects.AsSlimReadOnly();
|
||||
|
||||
public HitObject()
|
||||
{
|
||||
StartTimeBindable.ValueChanged += time =>
|
||||
{
|
||||
double offset = time.NewValue - time.OldValue;
|
||||
|
||||
foreach (var nested in nestedHitObjects)
|
||||
nested.StartTime += offset;
|
||||
|
||||
if (DifficultyControlPoint != DifficultyControlPoint.DEFAULT)
|
||||
DifficultyControlPoint.Time = time.NewValue;
|
||||
|
||||
if (SampleControlPoint != SampleControlPoint.DEFAULT)
|
||||
SampleControlPoint.Time = this.GetEndTime() + control_point_leniency;
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies default values to this HitObject.
|
||||
/// </summary>
|
||||
@ -115,24 +98,22 @@ namespace osu.Game.Rulesets.Objects
|
||||
var legacyInfo = controlPointInfo as LegacyControlPointInfo;
|
||||
|
||||
if (legacyInfo != null)
|
||||
{
|
||||
DifficultyControlPoint = (DifficultyControlPoint)legacyInfo.DifficultyPointAt(StartTime).DeepClone();
|
||||
DifficultyControlPoint.Time = StartTime;
|
||||
}
|
||||
else if (DifficultyControlPoint == DifficultyControlPoint.DEFAULT)
|
||||
DifficultyControlPoint = new DifficultyControlPoint();
|
||||
|
||||
DifficultyControlPoint.Time = StartTime;
|
||||
|
||||
ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||
|
||||
// This is done here after ApplyDefaultsToSelf as we may require custom defaults to be applied to have an accurate end time.
|
||||
if (legacyInfo != null)
|
||||
{
|
||||
SampleControlPoint = (SampleControlPoint)legacyInfo.SamplePointAt(this.GetEndTime() + control_point_leniency).DeepClone();
|
||||
SampleControlPoint.Time = this.GetEndTime() + control_point_leniency;
|
||||
}
|
||||
else if (SampleControlPoint == SampleControlPoint.DEFAULT)
|
||||
SampleControlPoint = new SampleControlPoint();
|
||||
|
||||
SampleControlPoint.Time = this.GetEndTime() + control_point_leniency;
|
||||
|
||||
nestedHitObjects.Clear();
|
||||
|
||||
CreateNestedHitObjects(cancellationToken);
|
||||
@ -155,6 +136,23 @@ namespace osu.Game.Rulesets.Objects
|
||||
foreach (var h in nestedHitObjects)
|
||||
h.ApplyDefaults(controlPointInfo, difficulty, cancellationToken);
|
||||
|
||||
// importantly, this callback is only registered after default application
|
||||
// to ensure that the read of `this.GetEndTime()` within doesn't return an invalid value
|
||||
// if `StartTimeBindable` is changed prior to default application.
|
||||
StartTimeBindable.ValueChanged += time =>
|
||||
{
|
||||
double offset = time.NewValue - time.OldValue;
|
||||
|
||||
foreach (var nested in nestedHitObjects)
|
||||
nested.StartTime += offset;
|
||||
|
||||
if (DifficultyControlPoint != DifficultyControlPoint.DEFAULT)
|
||||
DifficultyControlPoint.Time = time.NewValue;
|
||||
|
||||
if (SampleControlPoint != SampleControlPoint.DEFAULT)
|
||||
SampleControlPoint.Time = this.GetEndTime() + control_point_leniency;
|
||||
};
|
||||
|
||||
DefaultsApplied?.Invoke(this);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user