1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-13 15:27:30 +08:00

Make BreakPeriod a struct

This commit is contained in:
Bartłomiej Dach 2024-06-19 09:01:33 +02:00
parent 6a6ccbc09f
commit 1f692f5fc7
No known key found for this signature in database
3 changed files with 43 additions and 45 deletions

View File

@ -1,11 +1,12 @@
// 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 System;
using osu.Game.Screens.Play;
namespace osu.Game.Beatmaps.Timing
{
public class BreakPeriod
public readonly struct BreakPeriod : IEquatable<BreakPeriod>
{
/// <summary>
/// The minimum duration required for a break to have any effect.
@ -15,12 +16,12 @@ namespace osu.Game.Beatmaps.Timing
/// <summary>
/// The break start time.
/// </summary>
public double StartTime;
public double StartTime { get; init; }
/// <summary>
/// The break end time.
/// </summary>
public double EndTime;
public double EndTime { get; init; }
/// <summary>
/// The break duration.
@ -49,5 +50,9 @@ namespace osu.Game.Beatmaps.Timing
/// <param name="time">The time to check in milliseconds.</param>
/// <returns>Whether the time falls within this <see cref="BreakPeriod"/>.</returns>
public bool Contains(double time) => time >= StartTime && time <= EndTime - BreakOverlay.BREAK_FADE_DURATION;
public bool Equals(BreakPeriod other) => StartTime.Equals(other.StartTime) && EndTime.Equals(other.EndTime);
public override bool Equals(object? obj) => obj is BreakPeriod other && Equals(other);
public override int GetHashCode() => HashCode.Combine(StartTime, EndTime);
}
}

View File

@ -5,6 +5,7 @@ using System;
using System.Diagnostics;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
@ -20,11 +21,11 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
{
public partial class TimelineBreak : CompositeDrawable
{
public BreakPeriod Break { get; }
public Bindable<BreakPeriod> Break { get; } = new Bindable<BreakPeriod>();
public TimelineBreak(BreakPeriod b)
{
Break = b;
Break.Value = b;
}
[BackgroundDependencyLoader]
@ -48,40 +49,46 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
Alpha = 0.4f,
},
},
new DragHandle(Break, isStartHandle: true)
new DragHandle(isStartHandle: true)
{
Break = { BindTarget = Break },
Anchor = Anchor.TopLeft,
Origin = Anchor.TopLeft,
Action = (time, breakPeriod) => breakPeriod.StartTime = time,
Action = (time, breakPeriod) => breakPeriod with { StartTime = time },
},
new DragHandle(Break, isStartHandle: false)
new DragHandle(isStartHandle: false)
{
Break = { BindTarget = Break },
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
Action = (time, breakPeriod) => breakPeriod.EndTime = time,
Action = (time, breakPeriod) => breakPeriod with { EndTime = time },
},
};
}
protected override void Update()
protected override void LoadComplete()
{
base.Update();
base.LoadComplete();
X = (float)Break.StartTime;
Width = (float)Break.Duration;
Break.BindValueChanged(_ =>
{
X = (float)Break.Value.StartTime;
Width = (float)Break.Value.Duration;
}, true);
}
private partial class DragHandle : FillFlowContainer
{
public Bindable<BreakPeriod> Break { get; } = new Bindable<BreakPeriod>();
public new Anchor Anchor
{
get => base.Anchor;
init => base.Anchor = value;
}
public Action<double, BreakPeriod>? Action { get; init; }
public Func<double, BreakPeriod, BreakPeriod>? Action { get; init; }
private readonly BreakPeriod breakPeriod;
private readonly bool isStartHandle;
private Container handle = null!;
@ -99,9 +106,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
[Resolved]
private OsuColour colours { get; set; } = null!;
public DragHandle(BreakPeriod breakPeriod, bool isStartHandle)
public DragHandle(bool isStartHandle)
{
this.breakPeriod = breakPeriod;
this.isStartHandle = isStartHandle;
}
@ -164,13 +170,13 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
changeHandler?.BeginChange();
updateState();
double min = beatmap.HitObjects.Last(ho => ho.GetEndTime() <= breakPeriod.StartTime).GetEndTime();
double max = beatmap.HitObjects.First(ho => ho.StartTime >= breakPeriod.EndTime).StartTime;
double min = beatmap.HitObjects.Last(ho => ho.GetEndTime() <= Break.Value.StartTime).GetEndTime();
double max = beatmap.HitObjects.First(ho => ho.StartTime >= Break.Value.EndTime).StartTime;
if (isStartHandle)
max = Math.Min(max, breakPeriod.EndTime - BreakPeriod.MIN_BREAK_DURATION);
max = Math.Min(max, Break.Value.EndTime - BreakPeriod.MIN_BREAK_DURATION);
else
min = Math.Max(min, breakPeriod.StartTime + BreakPeriod.MIN_BREAK_DURATION);
min = Math.Max(min, Break.Value.StartTime + BreakPeriod.MIN_BREAK_DURATION);
allowedDragRange = (min, max);
@ -183,11 +189,13 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
Debug.Assert(allowedDragRange != null);
if (timeline.FindSnappedPositionAndTime(e.ScreenSpaceMousePosition).Time is double time
if (Action != null
&& timeline.FindSnappedPositionAndTime(e.ScreenSpaceMousePosition).Time is double time
&& time > allowedDragRange.Value.min
&& time < allowedDragRange.Value.max)
{
Action?.Invoke(time, breakPeriod);
int index = beatmap.Breaks.IndexOf(Break.Value);
beatmap.Breaks[index] = Break.Value = Action.Invoke(time, Break.Value);
}
updateState();

View File

@ -1,6 +1,7 @@
// 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 System.Collections.Specialized;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Caching;
@ -29,7 +30,11 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
breaks.UnbindAll();
breaks.BindTo(beatmap.Breaks);
breaks.BindCollectionChanged((_, _) => breakCache.Invalidate());
breaks.BindCollectionChanged((_, e) =>
{
if (e.Action != NotifyCollectionChangedAction.Replace)
breakCache.Invalidate();
});
}
protected override void Update()
@ -57,14 +62,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
private void recreateBreaks()
{
// Remove groups outside the visible range
foreach (TimelineBreak drawableBreak in this)
{
if (!shouldBeVisible(drawableBreak.Break))
drawableBreak.Expire();
}
Clear();
// Add remaining ones
for (int i = 0; i < breaks.Count; i++)
{
var breakPeriod = breaks[i];
@ -72,20 +71,6 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
if (!shouldBeVisible(breakPeriod))
continue;
bool alreadyVisible = false;
foreach (var b in this)
{
if (ReferenceEquals(b.Break, breakPeriod))
{
alreadyVisible = true;
break;
}
}
if (alreadyVisible)
continue;
Add(new TimelineBreak(breakPeriod));
}
}