mirror of
https://github.com/ppy/osu.git
synced 2025-03-15 15:27:20 +08:00
Merge pull request #28444 from bdach/scrolling-ruleset-editor-reloads
Reload scrolling hitobject composer on control point changes
This commit is contained in:
commit
0eb533f2fd
@ -13,8 +13,28 @@ namespace osu.Game.Beatmaps.ControlPoints
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
|
||||
public abstract class ControlPoint : IComparable<ControlPoint>, IDeepCloneable<ControlPoint>, IEquatable<ControlPoint>, IControlPoint
|
||||
{
|
||||
/// <summary>
|
||||
/// Invoked when any of this <see cref="ControlPoint"/>'s properties have changed.
|
||||
/// </summary>
|
||||
public event Action<ControlPoint>? Changed;
|
||||
|
||||
protected void RaiseChanged() => Changed?.Invoke(this);
|
||||
|
||||
private double time;
|
||||
|
||||
[JsonIgnore]
|
||||
public double Time { get; set; }
|
||||
public double Time
|
||||
{
|
||||
get => time;
|
||||
set
|
||||
{
|
||||
if (time == value)
|
||||
return;
|
||||
|
||||
time = value;
|
||||
RaiseChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public void AttachGroup(ControlPointGroup pointGroup) => Time = pointGroup.Time;
|
||||
|
||||
|
@ -10,8 +10,11 @@ namespace osu.Game.Beatmaps.ControlPoints
|
||||
public class ControlPointGroup : IComparable<ControlPointGroup>, IEquatable<ControlPointGroup>
|
||||
{
|
||||
public event Action<ControlPoint>? ItemAdded;
|
||||
public event Action<ControlPoint>? ItemChanged;
|
||||
public event Action<ControlPoint>? ItemRemoved;
|
||||
|
||||
private void raiseItemChanged(ControlPoint controlPoint) => ItemChanged?.Invoke(controlPoint);
|
||||
|
||||
/// <summary>
|
||||
/// The time at which the control point takes effect.
|
||||
/// </summary>
|
||||
@ -39,12 +42,14 @@ namespace osu.Game.Beatmaps.ControlPoints
|
||||
|
||||
controlPoints.Add(point);
|
||||
ItemAdded?.Invoke(point);
|
||||
point.Changed += raiseItemChanged;
|
||||
}
|
||||
|
||||
public void Remove(ControlPoint point)
|
||||
{
|
||||
controlPoints.Remove(point);
|
||||
ItemRemoved?.Invoke(point);
|
||||
point.Changed -= raiseItemChanged;
|
||||
}
|
||||
|
||||
public sealed override bool Equals(object? obj)
|
||||
|
@ -20,6 +20,14 @@ namespace osu.Game.Beatmaps.ControlPoints
|
||||
[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
|
||||
public class ControlPointInfo : IDeepCloneable<ControlPointInfo>
|
||||
{
|
||||
/// <summary>
|
||||
/// Invoked on any change to the set of control points.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public event Action ControlPointsChanged;
|
||||
|
||||
private void raiseControlPointsChanged([CanBeNull] ControlPoint _ = null) => ControlPointsChanged?.Invoke();
|
||||
|
||||
/// <summary>
|
||||
/// All control points grouped by time.
|
||||
/// </summary>
|
||||
@ -117,6 +125,7 @@ namespace osu.Game.Beatmaps.ControlPoints
|
||||
if (addIfNotExisting)
|
||||
{
|
||||
newGroup.ItemAdded += GroupItemAdded;
|
||||
newGroup.ItemChanged += raiseControlPointsChanged;
|
||||
newGroup.ItemRemoved += GroupItemRemoved;
|
||||
|
||||
groups.Insert(~i, newGroup);
|
||||
@ -132,6 +141,7 @@ namespace osu.Game.Beatmaps.ControlPoints
|
||||
group.Remove(item);
|
||||
|
||||
group.ItemAdded -= GroupItemAdded;
|
||||
group.ItemChanged -= raiseControlPointsChanged;
|
||||
group.ItemRemoved -= GroupItemRemoved;
|
||||
|
||||
groups.Remove(group);
|
||||
@ -288,6 +298,8 @@ namespace osu.Game.Beatmaps.ControlPoints
|
||||
default:
|
||||
throw new ArgumentException($"A control point of unexpected type {controlPoint.GetType()} was added to this {nameof(ControlPointInfo)}");
|
||||
}
|
||||
|
||||
raiseControlPointsChanged();
|
||||
}
|
||||
|
||||
protected virtual void GroupItemRemoved(ControlPoint controlPoint)
|
||||
@ -302,6 +314,8 @@ namespace osu.Game.Beatmaps.ControlPoints
|
||||
effectPoints.Remove(typed);
|
||||
break;
|
||||
}
|
||||
|
||||
raiseControlPointsChanged();
|
||||
}
|
||||
|
||||
public ControlPointInfo DeepClone()
|
||||
|
@ -44,6 +44,11 @@ namespace osu.Game.Beatmaps.ControlPoints
|
||||
set => SliderVelocityBindable.Value = value;
|
||||
}
|
||||
|
||||
public DifficultyControlPoint()
|
||||
{
|
||||
SliderVelocityBindable.BindValueChanged(_ => RaiseChanged());
|
||||
}
|
||||
|
||||
public override bool IsRedundant(ControlPoint? existing)
|
||||
=> existing is DifficultyControlPoint existingDifficulty
|
||||
&& GenerateTicks == existingDifficulty.GenerateTicks
|
||||
|
@ -50,6 +50,12 @@ namespace osu.Game.Beatmaps.ControlPoints
|
||||
set => KiaiModeBindable.Value = value;
|
||||
}
|
||||
|
||||
public EffectControlPoint()
|
||||
{
|
||||
KiaiModeBindable.BindValueChanged(_ => RaiseChanged());
|
||||
ScrollSpeedBindable.BindValueChanged(_ => RaiseChanged());
|
||||
}
|
||||
|
||||
public override bool IsRedundant(ControlPoint? existing)
|
||||
=> existing is EffectControlPoint existingEffect
|
||||
&& KiaiMode == existingEffect.KiaiMode
|
||||
|
@ -56,6 +56,12 @@ namespace osu.Game.Beatmaps.ControlPoints
|
||||
set => SampleVolumeBindable.Value = value;
|
||||
}
|
||||
|
||||
public SampleControlPoint()
|
||||
{
|
||||
SampleBankBindable.BindValueChanged(_ => RaiseChanged());
|
||||
SampleVolumeBindable.BindValueChanged(_ => RaiseChanged());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a SampleInfo based on the sample settings in this control point.
|
||||
/// </summary>
|
||||
|
@ -82,6 +82,13 @@ namespace osu.Game.Beatmaps.ControlPoints
|
||||
/// </summary>
|
||||
public double BPM => 60000 / BeatLength;
|
||||
|
||||
public TimingControlPoint()
|
||||
{
|
||||
TimeSignatureBindable.BindValueChanged(_ => RaiseChanged());
|
||||
OmitFirstBarLineBindable.BindValueChanged(_ => RaiseChanged());
|
||||
BeatLengthBindable.BindValueChanged(_ => RaiseChanged());
|
||||
}
|
||||
|
||||
// Timing points are never redundant as they can change the time signature.
|
||||
public override bool IsRedundant(ControlPoint? existing) => false;
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
@ -12,6 +13,7 @@ using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Rulesets.Edit.Tools;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Screens.Edit;
|
||||
using osu.Game.Screens.Edit.Components.TernaryButtons;
|
||||
using osu.Game.Screens.Edit.Compose.Components;
|
||||
using osuTK;
|
||||
@ -21,6 +23,9 @@ namespace osu.Game.Rulesets.Edit
|
||||
public abstract partial class ScrollingHitObjectComposer<TObject> : HitObjectComposer<TObject>
|
||||
where TObject : HitObject
|
||||
{
|
||||
[Resolved]
|
||||
private Editor? editor { get; set; }
|
||||
|
||||
private readonly Bindable<TernaryState> showSpeedChanges = new Bindable<TernaryState>();
|
||||
private Bindable<bool> configShowSpeedChanges = null!;
|
||||
|
||||
@ -72,6 +77,8 @@ namespace osu.Game.Rulesets.Edit
|
||||
|
||||
if (beatSnapGrid != null)
|
||||
AddInternal(beatSnapGrid);
|
||||
|
||||
EditorBeatmap.ControlPointInfo.ControlPointsChanged += expireComposeScreenOnControlPointChange;
|
||||
}
|
||||
|
||||
protected override void UpdateAfterChildren()
|
||||
@ -104,5 +111,15 @@ namespace osu.Game.Rulesets.Edit
|
||||
beatSnapGrid.SelectionTimeRange = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
if (EditorBeatmap.IsNotNull())
|
||||
EditorBeatmap.ControlPointInfo.ControlPointsChanged -= expireComposeScreenOnControlPointChange;
|
||||
}
|
||||
|
||||
private void expireComposeScreenOnControlPointChange() => editor?.ReloadComposeScreen();
|
||||
}
|
||||
}
|
||||
|
@ -1019,6 +1019,15 @@ namespace osu.Game.Screens.Edit
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Forces a reload of the compose screen after significant configuration changes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This can be necessary for scrolling rulesets, as they do not easily support control points changing under them.
|
||||
/// The reason that this works is that <see cref="onModeChanged"/> will re-instantiate the screen whenever it is requested next.
|
||||
/// </remarks>
|
||||
public void ReloadComposeScreen() => screenContainer.SingleOrDefault(s => s.Type == EditorScreenMode.Compose)?.RemoveAndDisposeImmediately();
|
||||
|
||||
[CanBeNull]
|
||||
private ScheduledDelegate playbackDisabledDebounce;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user