mirror of
https://github.com/ppy/osu.git
synced 2024-11-16 07:20:24 +08:00
a33294ac42
- On entering the screen, the timing point active at the current instant of the map is selected. This is the *only* time where the selected point is changed automatically for the user. - The ongoing automatic tracking of the relevant point after the initial selection is *gone*. Even knowing the fact that it was supposed to track the supposedly relevant "last selected type" of control point, I always found the tracking to be fairly arbitrary in how it works. Removing this behaviour also incidentally fixes https://github.com/ppy/osu/issues/23147. In its stead, to indicate which timing groups are having an effect, they receive an indicator line on the left (coloured using the relevant control points' representing colours), as well as a slight highlight effect. - If there is no control point selected, the table will autoscroll to the latest timing group, unless the user manually scrolled the table before. - If the selected control point changes, the table will autoscroll to the newly selected point, *regardless* of whether the user manually scrolled the table before. - A new button is added which permits the user to select the latest timing group. As per the point above, this will autoscroll the user to that group at the same time.
157 lines
5.2 KiB
C#
157 lines
5.2 KiB
C#
// 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 System.Linq;
|
|
using osu.Framework.Allocation;
|
|
using osu.Framework.Bindables;
|
|
using osu.Framework.Graphics;
|
|
using osu.Framework.Graphics.Containers;
|
|
using osu.Framework.Input.Events;
|
|
using osu.Game.Beatmaps.ControlPoints;
|
|
using osu.Game.Graphics.UserInterface;
|
|
using osu.Game.Graphics.UserInterfaceV2;
|
|
using osuTK;
|
|
|
|
namespace osu.Game.Screens.Edit.Timing
|
|
{
|
|
public partial class ControlPointList : CompositeDrawable
|
|
{
|
|
private OsuButton deleteButton = null!;
|
|
private RoundedButton addButton = null!;
|
|
|
|
[Resolved]
|
|
private EditorClock clock { get; set; } = null!;
|
|
|
|
[Resolved]
|
|
protected EditorBeatmap Beatmap { get; private set; } = null!;
|
|
|
|
[Resolved]
|
|
private Bindable<ControlPointGroup?> selectedGroup { get; set; } = null!;
|
|
|
|
[BackgroundDependencyLoader]
|
|
private void load()
|
|
{
|
|
RelativeSizeAxes = Axes.Both;
|
|
|
|
const float margins = 10;
|
|
InternalChildren = new Drawable[]
|
|
{
|
|
new ControlPointTable
|
|
{
|
|
RelativeSizeAxes = Axes.Both,
|
|
Groups = { BindTarget = Beatmap.ControlPointInfo.Groups, },
|
|
},
|
|
new FillFlowContainer
|
|
{
|
|
AutoSizeAxes = Axes.Both,
|
|
Anchor = Anchor.BottomRight,
|
|
Origin = Anchor.BottomRight,
|
|
Direction = FillDirection.Horizontal,
|
|
Margin = new MarginPadding(margins),
|
|
Spacing = new Vector2(5),
|
|
Children = new Drawable[]
|
|
{
|
|
deleteButton = new RoundedButton
|
|
{
|
|
Text = "-",
|
|
Size = new Vector2(30, 30),
|
|
Action = delete,
|
|
Anchor = Anchor.BottomRight,
|
|
Origin = Anchor.BottomRight,
|
|
},
|
|
addButton = new RoundedButton
|
|
{
|
|
Action = addNew,
|
|
Size = new Vector2(160, 30),
|
|
Anchor = Anchor.BottomRight,
|
|
Origin = Anchor.BottomRight,
|
|
},
|
|
new RoundedButton
|
|
{
|
|
Text = "Go to current time",
|
|
Action = goToCurrentGroup,
|
|
Size = new Vector2(140, 30),
|
|
Anchor = Anchor.BottomRight,
|
|
Origin = Anchor.BottomRight,
|
|
},
|
|
}
|
|
},
|
|
};
|
|
}
|
|
|
|
protected override void LoadComplete()
|
|
{
|
|
base.LoadComplete();
|
|
|
|
selectedGroup.BindValueChanged(selected =>
|
|
{
|
|
deleteButton.Enabled.Value = selected.NewValue != null;
|
|
|
|
addButton.Text = selected.NewValue != null
|
|
? "+ Clone to current time"
|
|
: "+ Add at current time";
|
|
}, true);
|
|
}
|
|
|
|
protected override bool OnClick(ClickEvent e)
|
|
{
|
|
selectedGroup.Value = null;
|
|
return true;
|
|
}
|
|
|
|
protected override void Update()
|
|
{
|
|
base.Update();
|
|
|
|
addButton.Enabled.Value = clock.CurrentTimeAccurate != selectedGroup.Value?.Time;
|
|
}
|
|
|
|
private void goToCurrentGroup()
|
|
{
|
|
double accurateTime = clock.CurrentTimeAccurate;
|
|
|
|
var activeTimingPoint = Beatmap.ControlPointInfo.TimingPointAt(accurateTime);
|
|
var activeEffectPoint = Beatmap.ControlPointInfo.EffectPointAt(accurateTime);
|
|
|
|
double latestActiveTime = Math.Max(activeTimingPoint.Time, activeEffectPoint.Time);
|
|
selectedGroup.Value = Beatmap.ControlPointInfo.GroupAt(latestActiveTime);
|
|
}
|
|
|
|
private void delete()
|
|
{
|
|
if (selectedGroup.Value == null)
|
|
return;
|
|
|
|
Beatmap.ControlPointInfo.RemoveGroup(selectedGroup.Value);
|
|
|
|
selectedGroup.Value = Beatmap.ControlPointInfo.Groups.FirstOrDefault(g => g.Time >= clock.CurrentTime);
|
|
}
|
|
|
|
private void addNew()
|
|
{
|
|
bool isFirstControlPoint = !Beatmap.ControlPointInfo.TimingPoints.Any();
|
|
|
|
var group = Beatmap.ControlPointInfo.GroupAt(clock.CurrentTime, true);
|
|
|
|
if (isFirstControlPoint)
|
|
group.Add(new TimingControlPoint());
|
|
else
|
|
{
|
|
// Try and create matching types from the currently selected control point.
|
|
var selected = selectedGroup.Value;
|
|
|
|
if (selected != null && !ReferenceEquals(selected, group))
|
|
{
|
|
foreach (var controlPoint in selected.ControlPoints)
|
|
{
|
|
group.Add(controlPoint.DeepClone());
|
|
}
|
|
}
|
|
}
|
|
|
|
selectedGroup.Value = group;
|
|
}
|
|
}
|
|
}
|