1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-21 20:47:28 +08:00

Add support for setting sample bank & volume for multiple objects at once

This commit is contained in:
Bartłomiej Dach 2021-11-13 17:21:48 +01:00
parent 9cf45e418a
commit 3fee6b0938
No known key found for this signature in database
GPG Key ID: BCECCD4FA41F6497
2 changed files with 63 additions and 18 deletions

View File

@ -171,15 +171,15 @@ namespace osu.Game.Tests.Visual.Editing
private void samplePopoverHasSingleVolume(int volume) => AddUntilStep($"sample popover has volume {volume}", () =>
{
var popover = this.ChildrenOfType<SamplePointPiece.SampleEditPopover>().SingleOrDefault();
var slider = popover?.ChildrenOfType<SliderWithTextBoxInput<int>>().Single();
var slider = popover?.ChildrenOfType<IndeterminateSliderWithTextBoxInput<int>>().Single();
return slider?.Current.Value == volume;
});
private void samplePopoverHasIndeterminateVolume() => AddUntilStep($"sample popover has indeterminate volume", () =>
private void samplePopoverHasIndeterminateVolume() => AddUntilStep("sample popover has indeterminate volume", () =>
{
var popover = this.ChildrenOfType<SamplePointPiece.SampleEditPopover>().SingleOrDefault();
var slider = popover?.ChildrenOfType<SliderWithTextBoxInput<int>>().Single();
var slider = popover?.ChildrenOfType<IndeterminateSliderWithTextBoxInput<int>>().Single();
return slider != null && slider.Current.Value == null;
});
@ -197,7 +197,7 @@ namespace osu.Game.Tests.Visual.Editing
var popover = this.ChildrenOfType<SamplePointPiece.SampleEditPopover>().SingleOrDefault();
var textBox = popover?.ChildrenOfType<LabelledTextBox>().First();
return textBox != null && textBox.Current.Value == null;
return textBox != null && string.IsNullOrEmpty(textBox.Current.Value);
});
private void dismissPopover()
@ -209,7 +209,7 @@ namespace osu.Game.Tests.Visual.Editing
private void setVolumeViaPopover(int volume) => AddStep($"set volume {volume} via popover", () =>
{
var popover = this.ChildrenOfType<SamplePointPiece.SampleEditPopover>().Single();
var slider = popover.ChildrenOfType<SliderWithTextBoxInput<int>>().Single();
var slider = popover.ChildrenOfType<IndeterminateSliderWithTextBoxInput<int>>().Single();
slider.Current.Value = volume;
});

View File

@ -1,9 +1,14 @@
// 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.
#nullable enable
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
@ -55,18 +60,16 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
public class SampleEditPopover : OsuPopover
{
private readonly HitObject hitObject;
private readonly SampleControlPoint point;
private LabelledTextBox bank;
private SliderWithTextBoxInput<int> volume;
private LabelledTextBox bank = null!;
private IndeterminateSliderWithTextBoxInput<int> volume = null!;
[Resolved(canBeNull: true)]
private EditorBeatmap beatmap { get; set; }
private EditorBeatmap beatmap { get; set; } = null!;
public SampleEditPopover(HitObject hitObject)
{
this.hitObject = hitObject;
point = hitObject.SampleControlPoint;
}
[BackgroundDependencyLoader]
@ -85,19 +88,61 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
{
Label = "Bank Name",
},
volume = new SliderWithTextBoxInput<int>("Volume")
{
Current = new SampleControlPoint().SampleVolumeBindable,
}
volume = new IndeterminateSliderWithTextBoxInput<int>("Volume", new SampleControlPoint().SampleVolumeBindable)
}
}
};
bank.Current = point.SampleBankBindable;
bank.Current.BindValueChanged(_ => beatmap.Update(hitObject));
// 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.
var relevantObjects = (beatmap.SelectedHitObjects.Contains(hitObject) ? beatmap.SelectedHitObjects : hitObject.Yield()).ToArray();
var relevantControlPoints = relevantObjects.Select(h => h.SampleControlPoint).ToArray();
volume.Current = point.SampleVolumeBindable;
volume.Current.BindValueChanged(_ => beatmap.Update(hitObject));
// even if there are multiple objects selected, we can still display sample volume or bank if they all have the same value.
string? commonBank = relevantControlPoints.Select(point => point.SampleBank).Distinct().Count() == 1 ? relevantControlPoints.First().SampleBank : null;
if (!string.IsNullOrEmpty(commonBank))
bank.Current.Value = commonBank;
int? commonVolume = relevantControlPoints.Select(point => point.SampleVolume).Distinct().Count() == 1 ? (int?)relevantControlPoints.First().SampleVolume : null;
if (commonVolume != null)
volume.Current.Value = commonVolume.Value;
bank.Current.BindValueChanged(val => updateBankFor(relevantObjects, val.NewValue));
volume.Current.BindValueChanged(val => updateVolumeFor(relevantObjects, val.NewValue));
}
private void updateBankFor(IEnumerable<HitObject> objects, string? newBank)
{
if (string.IsNullOrEmpty(newBank))
return;
beatmap.BeginChange();
foreach (var h in objects)
{
h.SampleControlPoint.SampleBank = newBank;
beatmap.Update(h);
}
beatmap.EndChange();
}
private void updateVolumeFor(IEnumerable<HitObject> objects, int? newVolume)
{
if (newVolume == null)
return;
beatmap.BeginChange();
foreach (var h in objects)
{
h.SampleControlPoint.SampleVolume = newVolume.Value;
beatmap.Update(h);
}
beatmap.EndChange();
}
}
}