diff --git a/osu.Game.Rulesets.Catch/Edit/CatchEditorPlayfield.cs b/osu.Game.Rulesets.Catch/Edit/CatchEditorPlayfield.cs index c9481c2757..3967c54f4b 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchEditorPlayfield.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchEditorPlayfield.cs @@ -8,7 +8,6 @@ namespace osu.Game.Rulesets.Catch.Edit { public partial class CatchEditorPlayfield : CatchPlayfield { - // TODO fixme: the size of the catcher is not changed when circle size is changed in setup screen. public CatchEditorPlayfield(IBeatmapDifficultyInfo difficulty) : base(difficulty) { diff --git a/osu.Game.Rulesets.Catch/Edit/DrawableCatchEditorRuleset.cs b/osu.Game.Rulesets.Catch/Edit/DrawableCatchEditorRuleset.cs index 7ad2106ab9..86cdc2df5c 100644 --- a/osu.Game.Rulesets.Catch/Edit/DrawableCatchEditorRuleset.cs +++ b/osu.Game.Rulesets.Catch/Edit/DrawableCatchEditorRuleset.cs @@ -2,16 +2,22 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.ObjectExtensions; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; +using osu.Game.Screens.Edit; namespace osu.Game.Rulesets.Catch.Edit { public partial class DrawableCatchEditorRuleset : DrawableCatchRuleset { + [Resolved] + private EditorBeatmap editorBeatmap { get; set; } = null!; + public readonly BindableDouble TimeRangeMultiplier = new BindableDouble(1); public DrawableCatchEditorRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList? mods = null) @@ -28,6 +34,30 @@ namespace osu.Game.Rulesets.Catch.Edit TimeRange.Value = gamePlayTimeRange * TimeRangeMultiplier.Value * playfieldStretch; } + protected override void LoadComplete() + { + base.LoadComplete(); + + editorBeatmap.BeatmapReprocessed += onBeatmapReprocessed; + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (editorBeatmap.IsNotNull()) + editorBeatmap.BeatmapReprocessed -= onBeatmapReprocessed; + } + + private void onBeatmapReprocessed() + { + if (Playfield is CatchEditorPlayfield catchPlayfield) + { + catchPlayfield.Catcher.ApplyDifficulty(editorBeatmap.Difficulty); + catchPlayfield.CatcherArea.CatcherTrails.UpdateCatcherTrailsScale(catchPlayfield.Catcher.BodyScale); + } + } + protected override Playfield CreatePlayfield() => new CatchEditorPlayfield(Beatmap.Difficulty); public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new CatchEditorPlayfieldAdjustmentContainer(); diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 6a1b251d60..ebf3e47fd7 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -116,7 +116,7 @@ namespace osu.Game.Rulesets.Catch.UI /// /// Width of the area that can be used to attempt catches during gameplay. /// - public readonly float CatchWidth; + public float CatchWidth { get; private set; } private readonly SkinnableCatcher body; @@ -142,10 +142,7 @@ namespace osu.Game.Rulesets.Catch.UI Size = new Vector2(BASE_SIZE); - if (difficulty != null) - Scale = calculateScale(difficulty); - - CatchWidth = CalculateCatchWidth(Scale); + ApplyDifficulty(difficulty); InternalChildren = new Drawable[] { @@ -312,6 +309,17 @@ namespace osu.Game.Rulesets.Catch.UI } } + /// + /// Set the scale and catch width. + /// + public void ApplyDifficulty(IBeatmapDifficultyInfo? difficulty) + { + if (difficulty != null) + Scale = calculateScale(difficulty); + + CatchWidth = CalculateCatchWidth(Scale); + } + /// /// Drop any fruit off the plate. /// diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 338e1364a9..7f0a79ef49 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Catch.UI private readonly CatchComboDisplay comboDisplay; - private readonly CatcherTrailDisplay catcherTrails; + public readonly CatcherTrailDisplay CatcherTrails; private Catcher catcher = null!; @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Catch.UI Children = new Drawable[] { catcherContainer = new Container { RelativeSizeAxes = Axes.Both }, - catcherTrails = new CatcherTrailDisplay(), + CatcherTrails = new CatcherTrailDisplay(), comboDisplay = new CatchComboDisplay { RelativeSizeAxes = Axes.None, @@ -112,7 +112,7 @@ namespace osu.Game.Rulesets.Catch.UI { const double trail_generation_interval = 16; - if (Time.Current - catcherTrails.LastDashTrailTime >= trail_generation_interval) + if (Time.Current - CatcherTrails.LastDashTrailTime >= trail_generation_interval) displayCatcherTrail(Catcher.HyperDashing ? CatcherTrailAnimation.HyperDashing : CatcherTrailAnimation.Dashing); } @@ -170,6 +170,6 @@ namespace osu.Game.Rulesets.Catch.UI } } - private void displayCatcherTrail(CatcherTrailAnimation animation) => catcherTrails.Add(new CatcherTrailEntry(Time.Current, Catcher.CurrentState, Catcher.X, Catcher.BodyScale, animation)); + private void displayCatcherTrail(CatcherTrailAnimation animation) => CatcherTrails.Add(new CatcherTrailEntry(Time.Current, Catcher.CurrentState, Catcher.X, Catcher.BodyScale, animation)); } } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs index e3e01c1b39..6b888be961 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; @@ -10,6 +11,7 @@ using osu.Framework.Graphics.Pooling; using osu.Game.Rulesets.Catch.Skinning; using osu.Game.Rulesets.Objects.Pooling; using osu.Game.Skinning; +using osuTK; using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.UI @@ -55,6 +57,25 @@ namespace osu.Game.Rulesets.Catch.UI }; } + /// + /// Update the scale of all trails. + /// + /// The new body scale of the Catcher + public void UpdateCatcherTrailsScale(Vector2 scale) + { + var oldEntries = Entries.ToList(); + + Clear(); + + foreach (var oldEntry in oldEntries) + { + // use magnitude of the new scale while preserving the sign of the old one in the X direction. + // the end effect is preserving the direction in which the trail sprites face, which is important. + var targetScale = new Vector2(Math.Abs(scale.X) * Math.Sign(oldEntry.Scale.X), Math.Abs(scale.Y)); + Add(new CatcherTrailEntry(oldEntry.LifetimeStart, oldEntry.CatcherState, oldEntry.Position, targetScale, oldEntry.Animation)); + } + } + protected override void LoadComplete() { base.LoadComplete();