diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index bf9f0bd44b..4de8cd897f 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -12,6 +12,7 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using OpenTK; using osu.Framework.Lists; +using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Rulesets.Catch.Objects { @@ -29,9 +30,14 @@ namespace osu.Game.Rulesets.Catch.Objects public double Velocity; public double TickDistance; + private ControlPointInfo controlPointInfo; + private BeatmapDifficulty difficulty; + public override void ApplyDefaults(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { base.ApplyDefaults(controlPointInfo, difficulty); + this.controlPointInfo = controlPointInfo; + this.difficulty = difficulty; TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); DifficultyControlPoint difficultyPoint = controlPointInfo.DifficultyPointAt(StartTime); @@ -124,6 +130,8 @@ namespace osu.Game.Rulesets.Catch.Objects }); } + ticks.ForEach(t => t.ApplyDefaults(controlPointInfo, difficulty)); + return ticks; } } diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs index fc1331551e..2b68dcf62c 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -63,10 +63,16 @@ namespace osu.Game.Rulesets.Mania.Objects /// private double tickSpacing = 50; + private ControlPointInfo controlPointInfo; + private BeatmapDifficulty difficulty; + public override void ApplyDefaults(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { base.ApplyDefaults(controlPointInfo, difficulty); + this.controlPointInfo = controlPointInfo; + this.difficulty = difficulty; + TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); tickSpacing = timingPoint.BeatLength / difficulty.SliderTickRate; @@ -89,11 +95,15 @@ namespace osu.Game.Rulesets.Mania.Objects for (double t = StartTime + tickSpacing; t <= EndTime - tickSpacing; t += tickSpacing) { - ret.Add(new HoldNoteTick + var tick = new HoldNoteTick { StartTime = t, Column = Column - }); + }; + + tick.ApplyDefaults(controlPointInfo, difficulty); + + ret.Add(tick); } return ret; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 42f54af801..a91d846aa7 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -57,6 +57,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Scale = s.Scale, ComboColour = s.ComboColour, Samples = s.Samples, + SoundControlPoint = s.SoundControlPoint }) }; diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 39ec753fe1..ec1b146328 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -10,6 +10,7 @@ using System.Linq; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Rulesets.Osu.Objects { @@ -74,10 +75,16 @@ namespace osu.Game.Rulesets.Osu.Objects public double Velocity; public double TickDistance; + private ControlPointInfo controlPointInfo; + private BeatmapDifficulty difficulty; + public override void ApplyDefaults(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { base.ApplyDefaults(controlPointInfo, difficulty); + this.controlPointInfo = controlPointInfo; + this.difficulty = difficulty; + TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); DifficultyControlPoint difficultyPoint = controlPointInfo.DifficultyPointAt(StartTime); @@ -124,7 +131,7 @@ namespace osu.Game.Rulesets.Osu.Objects var distanceProgress = d / length; var timeProgress = reversed ? 1 - distanceProgress : distanceProgress; - yield return new SliderTick + var ret = new SliderTick { RepeatIndex = repeat, StartTime = repeatStartTime + timeProgress * repeatDuration, @@ -139,6 +146,10 @@ namespace osu.Game.Rulesets.Osu.Objects Volume = s.Volume })) }; + + ret.ApplyDefaults(controlPointInfo, difficulty); + + yield return ret; } } } @@ -158,7 +169,7 @@ namespace osu.Game.Rulesets.Osu.Objects var repeatStartTime = StartTime + repeat * repeatDuration; var distanceProgress = d / length; - yield return new RepeatPoint + var ret = new RepeatPoint { RepeatIndex = repeat, StartTime = repeatStartTime, @@ -167,6 +178,10 @@ namespace osu.Game.Rulesets.Osu.Objects Scale = Scale, ComboColour = ComboColour, }; + + ret.ApplyDefaults(controlPointInfo, difficulty); + + yield return ret; } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 526d23f51a..a2503b8060 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -55,9 +55,14 @@ namespace osu.Game.Rulesets.Taiko.Objects /// private double tickSpacing = 100; + private ControlPointInfo controlPointInfo; + private BeatmapDifficulty difficulty; + public override void ApplyDefaults(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { base.ApplyDefaults(controlPointInfo, difficulty); + this.controlPointInfo = controlPointInfo; + this.difficulty = difficulty; TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); @@ -77,7 +82,7 @@ namespace osu.Game.Rulesets.Taiko.Objects bool first = true; for (double t = StartTime; t < EndTime + tickSpacing / 2; t += tickSpacing) { - ret.Add(new DrumRollTick + var tick = new DrumRollTick { FirstTick = first, TickSpacing = tickSpacing, @@ -89,12 +94,15 @@ namespace osu.Game.Rulesets.Taiko.Objects Name = @"slidertick", Volume = s.Volume })) - }); + }; + tick.ApplyDefaults(controlPointInfo, difficulty); + + ret.Add(tick); first = false; } return ret; } } -} \ No newline at end of file +} diff --git a/osu.Game/Audio/SampleInfo.cs b/osu.Game/Audio/SampleInfo.cs index 3c3a64dbb2..2cde4e01ad 100644 --- a/osu.Game/Audio/SampleInfo.cs +++ b/osu.Game/Audio/SampleInfo.cs @@ -15,40 +15,19 @@ namespace osu.Game.Audio public const string HIT_NORMAL = @"hitnormal"; public const string HIT_CLAP = @"hitclap"; - /// - /// The that is used for and - /// if the values have not already been provided by the hitobject. - /// - [JsonIgnore] - public SoundControlPoint ControlPoint; - - private string bank; /// /// The bank to load the sample from. /// - public string Bank - { - get { return string.IsNullOrEmpty(bank) ? (ControlPoint?.SampleBank ?? "normal") : bank; } - set { bank = value; } - } - - public bool ShouldSerializeBank() => Bank != ControlPoint.SampleBank; + public string Bank; /// /// The name of the sample to load. /// - public string Name { get; set; } + public string Name; - private int volume; /// /// The sample volume. /// - public int Volume - { - get { return volume == 0 ? (ControlPoint?.SampleVolume ?? 0) : volume; } - set { volume = value; } - } - - public bool ShouldSerializeVolume() => Volume != ControlPoint.SampleVolume; + public int Volume; } } diff --git a/osu.Game/Beatmaps/ControlPoints/SoundControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SoundControlPoint.cs index 8084229382..b73a03b95a 100644 --- a/osu.Game/Beatmaps/ControlPoints/SoundControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SoundControlPoint.cs @@ -5,14 +5,16 @@ namespace osu.Game.Beatmaps.ControlPoints { public class SoundControlPoint : ControlPoint { + public const string DEFAULT_BANK = "normal"; + /// /// The default sample bank at this control point. /// - public string SampleBank; + public string SampleBank = DEFAULT_BANK; /// /// The default sample volume at this control point. /// public int SampleVolume; } -} \ No newline at end of file +} diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 57db36fda5..4f5f8898f8 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -86,12 +86,23 @@ namespace osu.Game.Rulesets.Objects.Drawables { foreach (SampleInfo sample in HitObject.Samples) { - SampleChannel channel = audio.Sample.Get($@"Gameplay/{sample.Bank}-{sample.Name}"); + if (HitObject.SoundControlPoint == null) + throw new ArgumentNullException(nameof(HitObject.SoundControlPoint), $"{nameof(HitObject)} must always have an attached {nameof(HitObject.SoundControlPoint)}."); + + var bank = sample.Bank; + if (string.IsNullOrEmpty(bank)) + bank = HitObject.SoundControlPoint.SampleBank; + + int volume = sample.Volume; + if (volume == 0) + volume = HitObject.SoundControlPoint.SampleVolume; + + SampleChannel channel = audio.Sample.Get($@"Gameplay/{bank}-{sample.Name}"); if (channel == null) continue; - channel.Volume.Value = sample.Volume; + channel.Volume.Value = volume; Samples.Add(channel); } } diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 0772e7707e..66e34eac32 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -31,6 +31,9 @@ namespace osu.Game.Rulesets.Objects /// public SampleInfoList Samples = new SampleInfoList(); + [JsonIgnore] + public SoundControlPoint SoundControlPoint; + /// /// Whether this is in Kiai time. /// @@ -48,13 +51,7 @@ namespace osu.Game.Rulesets.Objects EffectControlPoint effectPoint = controlPointInfo.EffectPointAt(StartTime); Kiai = effectPoint.KiaiMode; - - // Initialize first sample - Samples.ForEach(s => s.ControlPoint = soundPoint); - - // Initialize any repeat samples - var repeatData = this as IHasRepeats; - repeatData?.RepeatSamples?.ForEach(r => r.ForEach(s => s.ControlPoint = soundPoint)); + SoundControlPoint = soundPoint; } } }