Prevent overrides from messing with application/freeing

This commit is contained in:
smoogipoo 2020-11-07 00:40:26 +09:00
parent 3a4bd73823
commit b1e039bcec
3 changed files with 49 additions and 28 deletions

View File

@ -52,19 +52,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
}); });
} }
public override void Free() protected override void OnApply(HitObject hitObject)
{ {
IndexInCurrentComboBindable.UnbindFrom(HitObject.IndexInCurrentComboBindable); base.OnApply(hitObject);
PositionBindable.UnbindFrom(HitObject.PositionBindable);
StackHeightBindable.UnbindFrom(HitObject.StackHeightBindable);
ScaleBindable.UnbindFrom(HitObject.ScaleBindable);
base.Free();
}
public override void Apply(HitObject hitObject)
{
base.Apply(hitObject);
IndexInCurrentComboBindable.BindTo(HitObject.IndexInCurrentComboBindable); IndexInCurrentComboBindable.BindTo(HitObject.IndexInCurrentComboBindable);
PositionBindable.BindTo(HitObject.PositionBindable); PositionBindable.BindTo(HitObject.PositionBindable);
@ -72,6 +62,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
ScaleBindable.BindTo(HitObject.ScaleBindable); ScaleBindable.BindTo(HitObject.ScaleBindable);
} }
protected override void OnFree(HitObject hitObject)
{
base.OnFree(hitObject);
IndexInCurrentComboBindable.UnbindFrom(HitObject.IndexInCurrentComboBindable);
PositionBindable.UnbindFrom(HitObject.PositionBindable);
StackHeightBindable.UnbindFrom(HitObject.StackHeightBindable);
ScaleBindable.UnbindFrom(HitObject.ScaleBindable);
}
// Forward all internal management to shakeContainer. // Forward all internal management to shakeContainer.
// This is a bit ugly but we don't have the concept of InternalContent so it'll have to do for now. (https://github.com/ppy/osu-framework/issues/1690) // This is a bit ugly but we don't have the concept of InternalContent so it'll have to do for now. (https://github.com/ppy/osu-framework/issues/1690)
protected override void AddInternal(Drawable drawable) => shakeContainer.Add(drawable); protected override void AddInternal(Drawable drawable) => shakeContainer.Add(drawable);

View File

@ -78,22 +78,22 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
Tracking.BindValueChanged(updateSlidingSample); Tracking.BindValueChanged(updateSlidingSample);
} }
public override void Free() protected override void OnApply(HitObject hitObject)
{ {
PathVersion.UnbindFrom(HitObject.Path.Version); base.OnApply(hitObject);
base.Free();
}
public override void Apply(HitObject hitObject)
{
base.Apply(hitObject);
// Ensure that the version will change after the upcoming BindTo(). // Ensure that the version will change after the upcoming BindTo().
pathVersion.Value = int.MaxValue; pathVersion.Value = int.MaxValue;
PathVersion.BindTo(HitObject.Path.Version); PathVersion.BindTo(HitObject.Path.Version);
} }
protected override void OnFree(HitObject hitObject)
{
base.OnFree(hitObject);
PathVersion.UnbindFrom(HitObject.Path.Version);
}
private PausableSkinnableSound slidingSample; private PausableSkinnableSound slidingSample;
protected override void LoadSamples() protected override void LoadSamples()

View File

@ -160,10 +160,9 @@ namespace osu.Game.Rulesets.Objects.Drawables
/// Applies a new <see cref="HitObject"/> to be represented by this <see cref="DrawableHitObject"/>. /// Applies a new <see cref="HitObject"/> to be represented by this <see cref="DrawableHitObject"/>.
/// </summary> /// </summary>
/// <param name="hitObject">The <see cref="HitObject"/> to apply.</param> /// <param name="hitObject">The <see cref="HitObject"/> to apply.</param>
public virtual void Apply(HitObject hitObject) public void Apply(HitObject hitObject)
{ {
if (hasHitObjectApplied) free();
Free();
HitObject = hitObject ?? throw new InvalidOperationException($"Cannot apply a null {nameof(HitObject)}."); HitObject = hitObject ?? throw new InvalidOperationException($"Cannot apply a null {nameof(HitObject)}.");
@ -202,14 +201,18 @@ namespace osu.Game.Rulesets.Objects.Drawables
if (IsLoaded) if (IsLoaded)
Schedule(() => updateState(ArmedState.Idle, true)); Schedule(() => updateState(ArmedState.Idle, true));
OnApply(hitObject);
hasHitObjectApplied = true; hasHitObjectApplied = true;
} }
/// <summary> /// <summary>
/// Removes the currently applied <see cref="HitObject"/> /// Removes the currently applied <see cref="HitObject"/>
/// </summary> /// </summary>
public virtual void Free() private void free()
{ {
if (!hasHitObjectApplied)
return;
StartTimeBindable.UnbindFrom(HitObject.StartTimeBindable); StartTimeBindable.UnbindFrom(HitObject.StartTimeBindable);
if (HitObject is IHasComboInformation combo) if (HitObject is IHasComboInformation combo)
comboIndexBindable.UnbindFrom(combo.ComboIndexBindable); comboIndexBindable.UnbindFrom(combo.ComboIndexBindable);
@ -234,8 +237,10 @@ namespace osu.Game.Rulesets.Objects.Drawables
} }
HitObject.DefaultsApplied -= onDefaultsApplied; HitObject.DefaultsApplied -= onDefaultsApplied;
HitObject = null;
OnFree(HitObject);
HitObject = null;
hasHitObjectApplied = false; hasHitObjectApplied = false;
} }
@ -243,10 +248,27 @@ namespace osu.Game.Rulesets.Objects.Drawables
{ {
base.FreeAfterUse(); base.FreeAfterUse();
// Freeing while not in a pool would cause the DHO to not be usable elsewhere in the hierarchy without being re-applied.
if (!IsInPool) if (!IsInPool)
return; return;
Free(); free();
}
/// <summary>
/// Invoked for this <see cref="DrawableHitObject"/> to take on any values from a newly-applied <see cref="HitObject"/>.
/// </summary>
/// <param name="hitObject">The <see cref="HitObject"/> being applied.</param>
protected virtual void OnApply(HitObject hitObject)
{
}
/// <summary>
/// Invoked for this <see cref="DrawableHitObject"/> to revert any values previously taken on from the currently-applied <see cref="HitObject"/>.
/// </summary>
/// <param name="hitObject">The currently-applied <see cref="HitObject"/>.</param>
protected virtual void OnFree(HitObject hitObject)
{
} }
/// <summary> /// <summary>
@ -285,7 +307,6 @@ namespace osu.Game.Rulesets.Objects.Drawables
private void onDefaultsApplied(HitObject hitObject) private void onDefaultsApplied(HitObject hitObject)
{ {
Free();
Apply(hitObject); Apply(hitObject);
DefaultsApplied?.Invoke(this); DefaultsApplied?.Invoke(this);
} }