1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-14 04:02:59 +08:00

Merge pull request #11221 from bdach/taiko-hitobject-application

Add support for hitobject application to taiko DHOs
This commit is contained in:
Dean Herbert 2020-12-21 16:23:40 +09:00 committed by GitHub
commit 06d4b323d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 242 additions and 79 deletions

View File

@ -25,16 +25,22 @@ namespace osu.Game.Rulesets.Taiko.Tests
private ScrollingHitObjectContainer hitObjectContainer; private ScrollingHitObjectContainer hitObjectContainer;
[SetUpSteps] [BackgroundDependencyLoader]
public void SetUp() private void load()
=> AddStep("create SHOC", () => Child = hitObjectContainer = new ScrollingHitObjectContainer {
Child = hitObjectContainer = new ScrollingHitObjectContainer
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Height = 200, Height = 200,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Clock = new FramedClock(new StopwatchClock()) Clock = new FramedClock(new StopwatchClock())
}); };
}
[SetUpSteps]
public void SetUp()
=> AddStep("clear SHOC", () => hitObjectContainer.Clear(false));
protected void AddHitObject(DrawableHitObject hitObject) protected void AddHitObject(DrawableHitObject hitObject)
=> AddStep("add to SHOC", () => hitObjectContainer.Add(hitObject)); => AddStep("add to SHOC", () => hitObjectContainer.Add(hitObject));

View File

@ -12,12 +12,13 @@ namespace osu.Game.Rulesets.Taiko.Tests
[Test] [Test]
public void TestApplyNewBarLine() public void TestApplyNewBarLine()
{ {
DrawableBarLine barLine = new DrawableBarLine(PrepareObject(new BarLine DrawableBarLine barLine = new DrawableBarLine();
AddStep("apply new bar line", () => barLine.Apply(PrepareObject(new BarLine
{ {
StartTime = 400, StartTime = 400,
Major = true Major = true
})); }), null));
AddHitObject(barLine); AddHitObject(barLine);
RemoveHitObject(barLine); RemoveHitObject(barLine);

View File

@ -0,0 +1,39 @@
// 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 NUnit.Framework;
using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.Objects.Drawables;
namespace osu.Game.Rulesets.Taiko.Tests
{
public class TestSceneDrumRollApplication : HitObjectApplicationTestScene
{
[Test]
public void TestApplyNewDrumRoll()
{
var drumRoll = new DrawableDrumRoll();
AddStep("apply new drum roll", () => drumRoll.Apply(PrepareObject(new DrumRoll
{
StartTime = 300,
Duration = 500,
IsStrong = false,
TickRate = 2
}), null));
AddHitObject(drumRoll);
RemoveHitObject(drumRoll);
AddStep("apply new drum roll", () => drumRoll.Apply(PrepareObject(new DrumRoll
{
StartTime = 150,
Duration = 400,
IsStrong = true,
TickRate = 16
}), null));
AddHitObject(drumRoll);
}
}
}

View File

@ -0,0 +1,37 @@
// 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 NUnit.Framework;
using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.Objects.Drawables;
namespace osu.Game.Rulesets.Taiko.Tests
{
public class TestSceneHitApplication : HitObjectApplicationTestScene
{
[Test]
public void TestApplyNewHit()
{
var hit = new DrawableHit();
AddStep("apply new hit", () => hit.Apply(PrepareObject(new Hit
{
Type = HitType.Rim,
IsStrong = false,
StartTime = 300
}), null));
AddHitObject(hit);
RemoveHitObject(hit);
AddStep("apply new hit", () => hit.Apply(PrepareObject(new Hit
{
Type = HitType.Centre,
IsStrong = true,
StartTime = 500
}), null));
AddHitObject(hit);
}
}
}

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Linq; using System.Linq;
using JetBrains.Annotations;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Utils; using osu.Framework.Utils;
using osu.Game.Graphics; using osu.Game.Graphics;
@ -31,15 +32,26 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
/// </summary> /// </summary>
private int rollingHits; private int rollingHits;
private Container tickContainer; private readonly Container tickContainer;
private Color4 colourIdle; private Color4 colourIdle;
private Color4 colourEngaged; private Color4 colourEngaged;
public DrawableDrumRoll(DrumRoll drumRoll) public DrawableDrumRoll()
: this(null)
{
}
public DrawableDrumRoll([CanBeNull] DrumRoll drumRoll)
: base(drumRoll) : base(drumRoll)
{ {
RelativeSizeAxes = Axes.Y; RelativeSizeAxes = Axes.Y;
Content.Add(tickContainer = new Container
{
RelativeSizeAxes = Axes.Both,
Depth = float.MinValue
});
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -47,12 +59,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
{ {
colourIdle = colours.YellowDark; colourIdle = colours.YellowDark;
colourEngaged = colours.YellowDarker; colourEngaged = colours.YellowDarker;
Content.Add(tickContainer = new Container
{
RelativeSizeAxes = Axes.Both,
Depth = float.MinValue
});
} }
protected override void LoadComplete() protected override void LoadComplete()
@ -68,6 +74,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
updateColour(); updateColour();
} }
protected override void OnFree()
{
base.OnFree();
rollingHits = 0;
}
protected override void AddNestedHitObject(DrawableHitObject hitObject) protected override void AddNestedHitObject(DrawableHitObject hitObject)
{ {
base.AddNestedHitObject(hitObject); base.AddNestedHitObject(hitObject);
@ -114,7 +126,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
rollingHits = Math.Clamp(rollingHits, 0, rolling_hits_for_engaged_colour); rollingHits = Math.Clamp(rollingHits, 0, rolling_hits_for_engaged_colour);
updateColour(); updateColour(100);
} }
protected override void CheckForResult(bool userTriggered, double timeOffset) protected override void CheckForResult(bool userTriggered, double timeOffset)
@ -154,27 +166,34 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
Content.X = DrawHeight / 2; Content.X = DrawHeight / 2;
} }
protected override DrawableStrongNestedHit CreateStrongNestedHit(DrumRoll.StrongNestedHit hitObject) => new StrongNestedHit(hitObject, this); protected override DrawableStrongNestedHit CreateStrongNestedHit(DrumRoll.StrongNestedHit hitObject) => new StrongNestedHit(hitObject);
private void updateColour() private void updateColour(double fadeDuration = 0)
{ {
Color4 newColour = Interpolation.ValueAt((float)rollingHits / rolling_hits_for_engaged_colour, colourIdle, colourEngaged, 0, 1); Color4 newColour = Interpolation.ValueAt((float)rollingHits / rolling_hits_for_engaged_colour, colourIdle, colourEngaged, 0, 1);
(MainPiece.Drawable as IHasAccentColour)?.FadeAccent(newColour, 100); (MainPiece.Drawable as IHasAccentColour)?.FadeAccent(newColour, fadeDuration);
} }
private class StrongNestedHit : DrawableStrongNestedHit private class StrongNestedHit : DrawableStrongNestedHit
{ {
public StrongNestedHit(DrumRoll.StrongNestedHit nestedHit, DrawableDrumRoll drumRoll) public new DrawableDrumRoll ParentHitObject => (DrawableDrumRoll)base.ParentHitObject;
: base(nestedHit, drumRoll)
public StrongNestedHit()
: this(null)
{
}
public StrongNestedHit([CanBeNull] DrumRoll.StrongNestedHit nestedHit)
: base(nestedHit)
{ {
} }
protected override void CheckForResult(bool userTriggered, double timeOffset) protected override void CheckForResult(bool userTriggered, double timeOffset)
{ {
if (!MainObject.Judged) if (!ParentHitObject.Judged)
return; return;
ApplyResult(r => r.Type = MainObject.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult); ApplyResult(r => r.Type = ParentHitObject.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult);
} }
public override bool OnPressed(TaikoAction action) => false; public override bool OnPressed(TaikoAction action) => false;

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using JetBrains.Annotations;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Taiko.Skinning.Default; using osu.Game.Rulesets.Taiko.Skinning.Default;
@ -16,7 +17,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
/// </summary> /// </summary>
public HitType JudgementType; public HitType JudgementType;
public DrawableDrumRollTick(DrumRollTick tick) public DrawableDrumRollTick()
: this(null)
{
}
public DrawableDrumRollTick([CanBeNull] DrumRollTick tick)
: base(tick) : base(tick)
{ {
FillMode = FillMode.Fit; FillMode = FillMode.Fit;
@ -61,21 +67,28 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
return UpdateResult(true); return UpdateResult(true);
} }
protected override DrawableStrongNestedHit CreateStrongNestedHit(DrumRollTick.StrongNestedHit hitObject) => new StrongNestedHit(hitObject, this); protected override DrawableStrongNestedHit CreateStrongNestedHit(DrumRollTick.StrongNestedHit hitObject) => new StrongNestedHit(hitObject);
private class StrongNestedHit : DrawableStrongNestedHit private class StrongNestedHit : DrawableStrongNestedHit
{ {
public StrongNestedHit(DrumRollTick.StrongNestedHit nestedHit, DrawableDrumRollTick tick) public new DrawableDrumRollTick ParentHitObject => (DrawableDrumRollTick)base.ParentHitObject;
: base(nestedHit, tick)
public StrongNestedHit()
: this(null)
{
}
public StrongNestedHit([CanBeNull] DrumRollTick.StrongNestedHit nestedHit)
: base(nestedHit)
{ {
} }
protected override void CheckForResult(bool userTriggered, double timeOffset) protected override void CheckForResult(bool userTriggered, double timeOffset)
{ {
if (!MainObject.Judged) if (!ParentHitObject.Judged)
return; return;
ApplyResult(r => r.Type = MainObject.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult); ApplyResult(r => r.Type = ParentHitObject.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult);
} }
public override bool OnPressed(TaikoAction action) => false; public override bool OnPressed(TaikoAction action) => false;

View File

@ -5,7 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using osu.Framework.Allocation; using JetBrains.Annotations;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Audio; using osu.Game.Audio;
@ -36,29 +36,51 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
private bool pressHandledThisFrame; private bool pressHandledThisFrame;
private readonly Bindable<HitType> type; private readonly Bindable<HitType> type = new Bindable<HitType>();
public DrawableHit(Hit hit) public DrawableHit()
: base(hit) : this(null)
{ {
type = HitObject.TypeBindable.GetBoundCopy();
FillMode = FillMode.Fit;
updateActionsFromType();
} }
[BackgroundDependencyLoader] public DrawableHit([CanBeNull] Hit hit)
private void load() : base(hit)
{ {
FillMode = FillMode.Fit;
}
protected override void OnApply()
{
type.BindTo(HitObject.TypeBindable);
type.BindValueChanged(_ => type.BindValueChanged(_ =>
{ {
updateActionsFromType(); updateActionsFromType();
// will overwrite samples, should only be called on change. // will overwrite samples, should only be called on subsequent changes
// after the initial application.
updateSamplesFromTypeChange(); updateSamplesFromTypeChange();
RecreatePieces(); RecreatePieces();
}); });
// action update also has to happen immediately on application.
updateActionsFromType();
base.OnApply();
}
protected override void OnFree()
{
base.OnFree();
type.UnbindFrom(HitObject.TypeBindable);
type.UnbindEvents();
UnproxyContent();
HitActions = null;
HitAction = null;
validActionPressed = pressHandledThisFrame = false;
} }
private HitSampleInfo[] getRimSamples() => HitObject.Samples.Where(s => s.Name == HitSampleInfo.HIT_CLAP || s.Name == HitSampleInfo.HIT_WHISTLE).ToArray(); private HitSampleInfo[] getRimSamples() => HitObject.Samples.Where(s => s.Name == HitSampleInfo.HIT_CLAP || s.Name == HitSampleInfo.HIT_WHISTLE).ToArray();
@ -228,32 +250,37 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
} }
} }
protected override DrawableStrongNestedHit CreateStrongNestedHit(Hit.StrongNestedHit hitObject) => new StrongNestedHit(hitObject, this); protected override DrawableStrongNestedHit CreateStrongNestedHit(Hit.StrongNestedHit hitObject) => new StrongNestedHit(hitObject);
private class StrongNestedHit : DrawableStrongNestedHit private class StrongNestedHit : DrawableStrongNestedHit
{ {
public new DrawableHit ParentHitObject => (DrawableHit)base.ParentHitObject;
/// <summary> /// <summary>
/// The lenience for the second key press. /// The lenience for the second key press.
/// This does not adjust by map difficulty in ScoreV2 yet. /// This does not adjust by map difficulty in ScoreV2 yet.
/// </summary> /// </summary>
private const double second_hit_window = 30; private const double second_hit_window = 30;
public new DrawableHit MainObject => (DrawableHit)base.MainObject; public StrongNestedHit()
: this(null)
{
}
public StrongNestedHit(Hit.StrongNestedHit nestedHit, DrawableHit hit) public StrongNestedHit([CanBeNull] Hit.StrongNestedHit nestedHit)
: base(nestedHit, hit) : base(nestedHit)
{ {
} }
protected override void CheckForResult(bool userTriggered, double timeOffset) protected override void CheckForResult(bool userTriggered, double timeOffset)
{ {
if (!MainObject.Result.HasResult) if (!ParentHitObject.Result.HasResult)
{ {
base.CheckForResult(userTriggered, timeOffset); base.CheckForResult(userTriggered, timeOffset);
return; return;
} }
if (!MainObject.Result.IsHit) if (!ParentHitObject.Result.IsHit)
{ {
ApplyResult(r => r.Type = r.Judgement.MinResult); ApplyResult(r => r.Type = r.Judgement.MinResult);
return; return;
@ -261,27 +288,27 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
if (!userTriggered) if (!userTriggered)
{ {
if (timeOffset - MainObject.Result.TimeOffset > second_hit_window) if (timeOffset - ParentHitObject.Result.TimeOffset > second_hit_window)
ApplyResult(r => r.Type = r.Judgement.MinResult); ApplyResult(r => r.Type = r.Judgement.MinResult);
return; return;
} }
if (Math.Abs(timeOffset - MainObject.Result.TimeOffset) <= second_hit_window) if (Math.Abs(timeOffset - ParentHitObject.Result.TimeOffset) <= second_hit_window)
ApplyResult(r => r.Type = r.Judgement.MaxResult); ApplyResult(r => r.Type = r.Judgement.MaxResult);
} }
public override bool OnPressed(TaikoAction action) public override bool OnPressed(TaikoAction action)
{ {
// Don't process actions until the main hitobject is hit // Don't process actions until the main hitobject is hit
if (!MainObject.IsHit) if (!ParentHitObject.IsHit)
return false; return false;
// Don't process actions if the pressed button was released // Don't process actions if the pressed button was released
if (MainObject.HitAction == null) if (ParentHitObject.HitAction == null)
return false; return false;
// Don't handle invalid hit action presses // Don't handle invalid hit action presses
if (!MainObject.HitActions.Contains(action)) if (!ParentHitObject.HitActions.Contains(action))
return false; return false;
return UpdateResult(true); return UpdateResult(true);

View File

@ -1,7 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Objects.Drawables; using JetBrains.Annotations;
using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Judgements;
namespace osu.Game.Rulesets.Taiko.Objects.Drawables namespace osu.Game.Rulesets.Taiko.Objects.Drawables
@ -11,12 +11,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
/// </summary> /// </summary>
public abstract class DrawableStrongNestedHit : DrawableTaikoHitObject public abstract class DrawableStrongNestedHit : DrawableTaikoHitObject
{ {
public readonly DrawableHitObject MainObject; public new DrawableTaikoHitObject ParentHitObject => (DrawableTaikoHitObject)base.ParentHitObject;
protected DrawableStrongNestedHit(StrongNestedHitObject nestedHit, DrawableHitObject mainObject) protected DrawableStrongNestedHit([CanBeNull] StrongNestedHitObject nestedHit)
: base(nestedHit) : base(nestedHit)
{ {
MainObject = mainObject;
} }
} }
} }

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Linq; using System.Linq;
using JetBrains.Annotations;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -35,7 +36,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
private readonly CircularContainer targetRing; private readonly CircularContainer targetRing;
private readonly CircularContainer expandingRing; private readonly CircularContainer expandingRing;
public DrawableSwell(Swell swell) public DrawableSwell()
: this(null)
{
}
public DrawableSwell([CanBeNull] Swell swell)
: base(swell) : base(swell)
{ {
FillMode = FillMode.Fit; FillMode = FillMode.Fit;
@ -123,12 +129,13 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
Origin = Anchor.Centre, Origin = Anchor.Centre,
}); });
protected override void LoadComplete() protected override void OnFree()
{ {
base.LoadComplete(); base.OnFree();
// We need to set this here because RelativeSizeAxes won't/can't set our size by default with a different RelativeChildSize UnproxyContent();
Width *= Parent.RelativeChildSize.X;
lastWasCentre = null;
} }
protected override void AddNestedHitObject(DrawableHitObject hitObject) protected override void AddNestedHitObject(DrawableHitObject hitObject)

View File

@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using JetBrains.Annotations;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.Taiko.Skinning.Default; using osu.Game.Rulesets.Taiko.Skinning.Default;
using osu.Game.Skinning; using osu.Game.Skinning;
@ -11,7 +12,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
{ {
public override bool DisplayResult => false; public override bool DisplayResult => false;
public DrawableSwellTick(SwellTick hitObject) public DrawableSwellTick()
: this(null)
{
}
public DrawableSwellTick([CanBeNull] SwellTick hitObject)
: base(hitObject) : base(hitObject)
{ {
} }

View File

@ -3,7 +3,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Allocation; using JetBrains.Annotations;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Primitives;
@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
private readonly Container nonProxiedContent; private readonly Container nonProxiedContent;
protected DrawableTaikoHitObject(TaikoHitObject hitObject) protected DrawableTaikoHitObject([CanBeNull] TaikoHitObject hitObject)
: base(hitObject) : base(hitObject)
{ {
AddRangeInternal(new[] AddRangeInternal(new[]
@ -113,25 +113,23 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
{ {
public override Vector2 OriginPosition => new Vector2(DrawHeight / 2); public override Vector2 OriginPosition => new Vector2(DrawHeight / 2);
public new TObject HitObject; public new TObject HitObject => (TObject)base.HitObject;
protected Vector2 BaseSize; protected Vector2 BaseSize;
protected SkinnableDrawable MainPiece; protected SkinnableDrawable MainPiece;
protected DrawableTaikoHitObject(TObject hitObject) protected DrawableTaikoHitObject([CanBeNull] TObject hitObject)
: base(hitObject) : base(hitObject)
{ {
HitObject = hitObject;
Anchor = Anchor.CentreLeft; Anchor = Anchor.CentreLeft;
Origin = Anchor.Custom; Origin = Anchor.Custom;
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
} }
[BackgroundDependencyLoader] protected override void OnApply()
private void load()
{ {
base.OnApply();
RecreatePieces(); RecreatePieces();
} }

View File

@ -2,7 +2,7 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Linq; using System.Linq;
using osu.Framework.Allocation; using JetBrains.Annotations;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Audio; using osu.Game.Audio;
@ -16,28 +16,38 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
where TObject : TaikoStrongableHitObject where TObject : TaikoStrongableHitObject
where TStrongNestedObject : StrongNestedHitObject where TStrongNestedObject : StrongNestedHitObject
{ {
private readonly Bindable<bool> isStrong; private readonly Bindable<bool> isStrong = new BindableBool();
private readonly Container<DrawableStrongNestedHit> strongHitContainer; private readonly Container<DrawableStrongNestedHit> strongHitContainer;
protected DrawableTaikoStrongableHitObject(TObject hitObject) protected DrawableTaikoStrongableHitObject([CanBeNull] TObject hitObject)
: base(hitObject) : base(hitObject)
{ {
isStrong = HitObject.IsStrongBindable.GetBoundCopy();
AddInternal(strongHitContainer = new Container<DrawableStrongNestedHit>()); AddInternal(strongHitContainer = new Container<DrawableStrongNestedHit>());
} }
[BackgroundDependencyLoader] protected override void OnApply()
private void load()
{ {
isStrong.BindTo(HitObject.IsStrongBindable);
isStrong.BindValueChanged(_ => isStrong.BindValueChanged(_ =>
{ {
// will overwrite samples, should only be called on change. // will overwrite samples, should only be called on subsequent changes
// after the initial application.
updateSamplesFromStrong(); updateSamplesFromStrong();
RecreatePieces(); RecreatePieces();
}); });
base.OnApply();
}
protected override void OnFree()
{
base.OnFree();
isStrong.UnbindFrom(HitObject.IsStrongBindable);
// ensure the next application does not accidentally overwrite samples.
isStrong.UnbindEvents();
} }
private HitSampleInfo[] getStrongSamples() => HitObject.Samples.Where(s => s.Name == HitSampleInfo.HIT_FINISH).ToArray(); private HitSampleInfo[] getStrongSamples() => HitObject.Samples.Where(s => s.Name == HitSampleInfo.HIT_FINISH).ToArray();

View File

@ -248,7 +248,7 @@ namespace osu.Game.Rulesets.Taiko.UI
{ {
case TaikoStrongJudgement _: case TaikoStrongJudgement _:
if (result.IsHit) if (result.IsHit)
hitExplosionContainer.Children.FirstOrDefault(e => e.JudgedObject == ((DrawableStrongNestedHit)judgedObject).MainObject)?.VisualiseSecondHit(); hitExplosionContainer.Children.FirstOrDefault(e => e.JudgedObject == ((DrawableStrongNestedHit)judgedObject).ParentHitObject)?.VisualiseSecondHit();
break; break;
case TaikoDrumRollTickJudgement _: case TaikoDrumRollTickJudgement _:

View File

@ -303,7 +303,8 @@ namespace osu.Game.Rulesets.Objects.Drawables
samplesBindable.CollectionChanged -= onSamplesChanged; samplesBindable.CollectionChanged -= onSamplesChanged;
// Release the samples for other hitobjects to use. // Release the samples for other hitobjects to use.
Samples.Samples = null; if (Samples != null)
Samples.Samples = null;
if (nestedHitObjects.IsValueCreated) if (nestedHitObjects.IsValueCreated)
{ {