mirror of
https://github.com/ppy/osu
synced 2024-12-14 19:06:07 +00:00
Make sample popover change properties of all samples in multiple selection
Closes https://github.com/ppy/osu/issues/28916. The previous behaviour *may* have been intended, but it was honestly quite baffling. This seems like a saner variant.
This commit is contained in:
parent
55382a4ba6
commit
1ed7e4b075
@ -34,12 +34,12 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
{
|
||||
private readonly int nodeIndex;
|
||||
|
||||
protected override IList<HitSampleInfo> GetRelevantSamples(HitObject ho)
|
||||
protected override IEnumerable<(HitObject hitObject, IList<HitSampleInfo> samples)> GetRelevantSamples(HitObject[] hitObjects)
|
||||
{
|
||||
if (ho is not IHasRepeats hasRepeats)
|
||||
return ho.Samples;
|
||||
if (hitObjects.Length > 1 || hitObjects[0] is not IHasRepeats hasRepeats)
|
||||
return base.GetRelevantSamples(hitObjects);
|
||||
|
||||
return nodeIndex < hasRepeats.NodeSamples.Count ? hasRepeats.NodeSamples[nodeIndex] : ho.Samples;
|
||||
return [(hitObjects[0], nodeIndex < hasRepeats.NodeSamples.Count ? hasRepeats.NodeSamples[nodeIndex] : hitObjects[0].Samples)];
|
||||
}
|
||||
|
||||
public NodeSampleEditPopover(HitObject hitObject, int nodeIndex)
|
||||
|
@ -21,6 +21,7 @@ using osu.Game.Graphics.UserInterfaceV2;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Screens.Edit.Components.TernaryButtons;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Screens.Edit.Timing;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
@ -106,15 +107,34 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
private FillFlowContainer togglesCollection = null!;
|
||||
|
||||
private HitObject[] relevantObjects = null!;
|
||||
private IList<HitSampleInfo>[] allRelevantSamples = null!;
|
||||
private (HitObject hitObject, IList<HitSampleInfo> samples)[] allRelevantSamples = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sub-set of samples relevant to this sample point piece.
|
||||
/// For example, to edit node samples this should return the samples at the index of the node.
|
||||
/// </summary>
|
||||
/// <param name="ho">The hit object to get the relevant samples from.</param>
|
||||
/// <param name="hitObjects">The hit objects to get the relevant samples from.</param>
|
||||
/// <returns>The relevant list of samples.</returns>
|
||||
protected virtual IList<HitSampleInfo> GetRelevantSamples(HitObject ho) => ho.Samples;
|
||||
protected virtual IEnumerable<(HitObject hitObject, IList<HitSampleInfo> samples)> GetRelevantSamples(HitObject[] hitObjects)
|
||||
{
|
||||
if (hitObjects.Length == 1)
|
||||
{
|
||||
yield return (hitObjects[0], hitObjects[0].Samples);
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
foreach (var ho in hitObjects)
|
||||
{
|
||||
yield return (ho, ho.Samples);
|
||||
|
||||
if (ho is IHasRepeats hasRepeats)
|
||||
{
|
||||
foreach (var node in hasRepeats.NodeSamples)
|
||||
yield return (ho, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Resolved(canBeNull: true)]
|
||||
private EditorBeatmap beatmap { get; set; } = null!;
|
||||
@ -172,7 +192,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
// if the piece belongs to a currently selected object, assume that the user wants to change all selected objects.
|
||||
// if the piece belongs to an unselected object, operate on that object alone, independently of the selection.
|
||||
relevantObjects = (beatmap.SelectedHitObjects.Contains(hitObject) ? beatmap.SelectedHitObjects : hitObject.Yield()).ToArray();
|
||||
allRelevantSamples = relevantObjects.Select(GetRelevantSamples).ToArray();
|
||||
allRelevantSamples = GetRelevantSamples(relevantObjects).ToArray();
|
||||
|
||||
// even if there are multiple objects selected, we can still display sample volume or bank if they all have the same value.
|
||||
int? commonVolume = getCommonVolume();
|
||||
@ -214,9 +234,19 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
togglesCollection.AddRange(createTernaryButtons().Select(b => new DrawableTernaryButton(b) { RelativeSizeAxes = Axes.None, Size = new Vector2(40, 40) }));
|
||||
}
|
||||
|
||||
private string? getCommonBank() => allRelevantSamples.Select(GetBankValue).Distinct().Count() == 1 ? GetBankValue(allRelevantSamples.First()) : null;
|
||||
private string? getCommonAdditionBank() => allRelevantSamples.Select(GetAdditionBankValue).Where(o => o is not null).Distinct().Count() == 1 ? GetAdditionBankValue(allRelevantSamples.First()) : null;
|
||||
private int? getCommonVolume() => allRelevantSamples.Select(GetVolumeValue).Distinct().Count() == 1 ? GetVolumeValue(allRelevantSamples.First()) : null;
|
||||
private string? getCommonBank() => allRelevantSamples.Select(h => GetBankValue(h.samples)).Distinct().Count() == 1
|
||||
? GetBankValue(allRelevantSamples.First().samples)
|
||||
: null;
|
||||
|
||||
private string? getCommonAdditionBank()
|
||||
{
|
||||
string[] additionBanks = allRelevantSamples.Select(h => GetAdditionBankValue(h.samples)).Where(o => o is not null).Cast<string>().Distinct().ToArray();
|
||||
return additionBanks.Length == 1 ? additionBanks[0] : null;
|
||||
}
|
||||
|
||||
private int? getCommonVolume() => allRelevantSamples.Select(h => GetVolumeValue(h.samples)).Distinct().Count() == 1
|
||||
? GetVolumeValue(allRelevantSamples.First().samples)
|
||||
: null;
|
||||
|
||||
private void updatePrimaryBankState()
|
||||
{
|
||||
@ -231,7 +261,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
additionBank.PlaceholderText = string.IsNullOrEmpty(commonAdditionBank) ? "(multiple)" : string.Empty;
|
||||
additionBank.Current.Value = commonAdditionBank;
|
||||
|
||||
bool anyAdditions = allRelevantSamples.Any(o => o.Any(s => s.Name != HitSampleInfo.HIT_NORMAL));
|
||||
bool anyAdditions = allRelevantSamples.Any(o => o.samples.Any(s => s.Name != HitSampleInfo.HIT_NORMAL));
|
||||
if (anyAdditions)
|
||||
additionBank.Show();
|
||||
else
|
||||
@ -247,9 +277,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
{
|
||||
beatmap.BeginChange();
|
||||
|
||||
foreach (var relevantHitObject in relevantObjects)
|
||||
foreach (var (relevantHitObject, relevantSamples) in GetRelevantSamples(relevantObjects))
|
||||
{
|
||||
var relevantSamples = GetRelevantSamples(relevantHitObject);
|
||||
updateAction(relevantHitObject, relevantSamples);
|
||||
beatmap.Update(relevantHitObject);
|
||||
}
|
||||
@ -333,7 +362,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
{
|
||||
foreach ((string sampleName, var bindable) in selectionSampleStates)
|
||||
{
|
||||
bindable.Value = SelectionHandler<HitObject>.GetStateFromSelection(relevantObjects, h => GetRelevantSamples(h).Any(s => s.Name == sampleName));
|
||||
bindable.Value = SelectionHandler<HitObject>.GetStateFromSelection(GetRelevantSamples(relevantObjects), h => h.samples.Any(s => s.Name == sampleName));
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user