1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-11 13:37:25 +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}", () => private void samplePopoverHasSingleVolume(int volume) => AddUntilStep($"sample popover has volume {volume}", () =>
{ {
var popover = this.ChildrenOfType<SamplePointPiece.SampleEditPopover>().SingleOrDefault(); 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; 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 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; 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 popover = this.ChildrenOfType<SamplePointPiece.SampleEditPopover>().SingleOrDefault();
var textBox = popover?.ChildrenOfType<LabelledTextBox>().First(); var textBox = popover?.ChildrenOfType<LabelledTextBox>().First();
return textBox != null && textBox.Current.Value == null; return textBox != null && string.IsNullOrEmpty(textBox.Current.Value);
}); });
private void dismissPopover() private void dismissPopover()
@ -209,7 +209,7 @@ namespace osu.Game.Tests.Visual.Editing
private void setVolumeViaPopover(int volume) => AddStep($"set volume {volume} via popover", () => private void setVolumeViaPopover(int volume) => AddStep($"set volume {volume} via popover", () =>
{ {
var popover = this.ChildrenOfType<SamplePointPiece.SampleEditPopover>().Single(); 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; slider.Current.Value = volume;
}); });

View File

@ -1,9 +1,14 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // 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.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Extensions; using osu.Framework.Extensions;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Cursor;
@ -55,18 +60,16 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
public class SampleEditPopover : OsuPopover public class SampleEditPopover : OsuPopover
{ {
private readonly HitObject hitObject; private readonly HitObject hitObject;
private readonly SampleControlPoint point;
private LabelledTextBox bank; private LabelledTextBox bank = null!;
private SliderWithTextBoxInput<int> volume; private IndeterminateSliderWithTextBoxInput<int> volume = null!;
[Resolved(canBeNull: true)] [Resolved(canBeNull: true)]
private EditorBeatmap beatmap { get; set; } private EditorBeatmap beatmap { get; set; } = null!;
public SampleEditPopover(HitObject hitObject) public SampleEditPopover(HitObject hitObject)
{ {
this.hitObject = hitObject; this.hitObject = hitObject;
point = hitObject.SampleControlPoint;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -85,19 +88,61 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
{ {
Label = "Bank Name", Label = "Bank Name",
}, },
volume = new SliderWithTextBoxInput<int>("Volume") volume = new IndeterminateSliderWithTextBoxInput<int>("Volume", new SampleControlPoint().SampleVolumeBindable)
{
Current = new SampleControlPoint().SampleVolumeBindable,
}
} }
} }
}; };
bank.Current = point.SampleBankBindable; // if the piece belongs to a currently selected object, assume that the user wants to change all selected objects.
bank.Current.BindValueChanged(_ => beatmap.Update(hitObject)); // 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; // even if there are multiple objects selected, we can still display sample volume or bank if they all have the same value.
volume.Current.BindValueChanged(_ => beatmap.Update(hitObject)); 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();
} }
} }
} }