mirror of
https://github.com/ppy/osu.git
synced 2026-06-08 02:53:40 +08:00
Allow changing addition bank button state when objects are selected even if the selection has no addition sounds (#36808)
Before: https://github.com/user-attachments/assets/d87bd7e3-37f8-4634-9e6a-5859d5bade57 After: https://github.com/user-attachments/assets/4de940af-1e30-4266-9aac-5ccd12f38742 --- The title is convoluted but basically I'm angling to close https://github.com/ppy/osu/issues/36705 with this. The point is that on current `master`, the keyboard-hotkey-based toggles on the left of the screen get disabled if you select a range of objects which contains no addition samples. The report linked above finds this annoying because it means you basically always need to add an addition sound *first* and *then* pick a bank. This is not necessary, and this commit changes the behaviour such that the bank selection toggles are no longer blocked when you select a range of objects without additions. Choosing an addition bank when there are no additions still does nothing to the selected object, *but* adding a sound *after* that bank preselection will use the preselected bank rather than auto.
This commit is contained in:
committed by
GitHub
Unverified
parent
0d74983551
commit
16bc1de9fd
@@ -1046,6 +1046,174 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAddSoundBeforeSettingNonAutoAdditionBankOnSelectedObject()
|
||||
{
|
||||
AddStep("select first object", () =>
|
||||
{
|
||||
EditorBeatmap.SelectedHitObjects.Clear();
|
||||
EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects[0]);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
|
||||
AddStep("add finish sound", () => InputManager.Key(Key.E));
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasAutoAdditionBankFlag(0, true);
|
||||
|
||||
AddStep("set drum addition bank", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.AltLeft);
|
||||
InputManager.Key(Key.R);
|
||||
InputManager.ReleaseKey(Key.AltLeft);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasAutoAdditionBankFlag(0, false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAddSoundAfterSettingNonAutoAdditionBankOnSelectedObject()
|
||||
{
|
||||
AddStep("select first object", () =>
|
||||
{
|
||||
EditorBeatmap.SelectedHitObjects.Clear();
|
||||
EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects[0]);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
|
||||
AddStep("set drum addition bank", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.AltLeft);
|
||||
InputManager.Key(Key.R);
|
||||
InputManager.ReleaseKey(Key.AltLeft);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
|
||||
AddStep("add finish sound", () => InputManager.Key(Key.E));
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasAutoAdditionBankFlag(0, false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSwitchSoundAfterSettingNonAutoAdditionBankOnSelectedObject()
|
||||
{
|
||||
AddStep("select first object", () =>
|
||||
{
|
||||
EditorBeatmap.SelectedHitObjects.Clear();
|
||||
EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects[0]);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
|
||||
AddStep("set drum addition bank", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.AltLeft);
|
||||
InputManager.Key(Key.R);
|
||||
InputManager.ReleaseKey(Key.AltLeft);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
|
||||
AddStep("add finish sound", () => InputManager.Key(Key.E));
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasAutoAdditionBankFlag(0, false);
|
||||
|
||||
AddStep("remove finish sound", () => InputManager.Key(Key.E));
|
||||
AddStep("add whistle sound", () => InputManager.Key(Key.W));
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_WHISTLE);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasAutoAdditionBankFlag(0, false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAddSoundBeforeSettingAutoAdditionBankOnSelectedObject()
|
||||
{
|
||||
AddStep("select first object", () =>
|
||||
{
|
||||
EditorBeatmap.SelectedHitObjects.Clear();
|
||||
EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects[0]);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
|
||||
AddStep("add finish sound", () => InputManager.Key(Key.E));
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasAutoAdditionBankFlag(0, true);
|
||||
|
||||
AddStep("set auto addition bank", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.AltLeft);
|
||||
InputManager.Key(Key.Q);
|
||||
InputManager.ReleaseKey(Key.AltLeft);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasAutoAdditionBankFlag(0, true);
|
||||
|
||||
AddStep("set drum normal bank", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.ShiftLeft);
|
||||
InputManager.Key(Key.R);
|
||||
InputManager.ReleaseKey(Key.ShiftLeft);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasAutoAdditionBankFlag(0, true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAddSoundAfterSettingAutoAdditionBankOnSelectedObject()
|
||||
{
|
||||
AddStep("select first object", () =>
|
||||
{
|
||||
EditorBeatmap.SelectedHitObjects.Clear();
|
||||
EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects[0]);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
|
||||
AddStep("set auto addition bank", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.AltLeft);
|
||||
InputManager.Key(Key.Q);
|
||||
InputManager.ReleaseKey(Key.AltLeft);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
|
||||
AddStep("add finish sound", () => InputManager.Key(Key.E));
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasAutoAdditionBankFlag(0, true);
|
||||
|
||||
AddStep("set drum normal bank", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.ShiftLeft);
|
||||
InputManager.Key(Key.R);
|
||||
InputManager.ReleaseKey(Key.ShiftLeft);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasAutoAdditionBankFlag(0, true);
|
||||
}
|
||||
|
||||
private void clickSamplePiece(int objectIndex) => AddStep($"click {objectIndex.ToOrdinalWords()} sample piece", () =>
|
||||
{
|
||||
var samplePiece = this.ChildrenOfType<SamplePointPiece>().Single(piece => piece is not NodeSamplePointPiece && piece.HitObject == EditorBeatmap.HitObjects.ElementAt(objectIndex));
|
||||
|
||||
@@ -100,7 +100,6 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
kvp.Value.BindValueChanged(_ => updatePlacementSamples());
|
||||
|
||||
SelectionHandler.AutoSelectionBankEnabled.BindValueChanged(_ => updateAutoBankTernaryButtonTooltip(), true);
|
||||
SelectionHandler.SelectionAdditionBanksEnabled.BindValueChanged(_ => updateAdditionBankTernaryButtonTooltips(), true);
|
||||
}
|
||||
|
||||
protected override void TransferBlueprintFor(HitObject hitObject, DrawableHitObject drawableObject)
|
||||
@@ -252,17 +251,6 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
autoBankButton.NormalButton.TooltipText = !enabled ? "Auto normal bank can only be used during hit object placement" : string.Empty;
|
||||
}
|
||||
|
||||
private void updateAdditionBankTernaryButtonTooltips()
|
||||
{
|
||||
bool enabled = SelectionHandler.SelectionAdditionBanksEnabled.Value;
|
||||
|
||||
foreach (var ternaryButton in SampleBankTernaryStates)
|
||||
{
|
||||
ternaryButton.AdditionsButton.Enabled.Value = enabled;
|
||||
ternaryButton.AdditionsButton.TooltipText = !enabled ? "Add an addition sample first to be able to set a bank" : string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
#region Placement
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -85,11 +85,6 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
/// </summary>
|
||||
public readonly Bindable<bool> AutoSelectionBankEnabled = new Bindable<bool>();
|
||||
|
||||
/// <summary>
|
||||
/// Whether the selection contains any addition samples and the <see cref="SelectionAdditionBankStates"/> can be used.
|
||||
/// </summary>
|
||||
public readonly Bindable<bool> SelectionAdditionBanksEnabled = new Bindable<bool>();
|
||||
|
||||
/// <summary>
|
||||
/// Set up ternary state bindables and bind them to selection/hitobject changes (in both directions)
|
||||
/// </summary>
|
||||
@@ -201,26 +196,18 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
break;
|
||||
|
||||
case TernaryState.True:
|
||||
if (SelectedItems.Count == 0)
|
||||
{
|
||||
// Ensure the user can't stack multiple bank selections when there's no hitobject selection.
|
||||
// Note that in normal scenarios this is sorted out by the feedback from applying the bank to the selected objects.
|
||||
foreach (var other in SelectionAdditionBankStates.Values)
|
||||
{
|
||||
if (other != bindable)
|
||||
other.Value = TernaryState.False;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If none of the selected objects have any addition samples, we should not apply the addition bank.
|
||||
if (SelectedItems.SelectMany(enumerateAllSamples).All(h => h.All(o => o.Name == HitSampleInfo.HIT_NORMAL)))
|
||||
{
|
||||
bindable.Value = TernaryState.False;
|
||||
break;
|
||||
}
|
||||
|
||||
// If any of the selected objects have any addition samples, we should apply the addition bank.
|
||||
if (SelectedItems.SelectMany(enumerateAllSamples).Any(h => h.Any(o => o.Name != HitSampleInfo.HIT_NORMAL)))
|
||||
SetSampleAdditionBank(bankName);
|
||||
|
||||
// There are either no selected items, or none of the selected items have addition sounds.
|
||||
// This state is basically the user pre-selecting an addition bank before actually adding an addition.
|
||||
// Ensure the user can't stack multiple bank selections in this state.
|
||||
// Note that in normal scenarios this is sorted out by the feedback from applying the bank to the selected objects.
|
||||
foreach (var other in SelectionAdditionBankStates.Values)
|
||||
{
|
||||
if (other != bindable)
|
||||
other.Value = TernaryState.False;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -279,7 +266,6 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
|
||||
SelectionNewComboState.Value = TernaryState.False;
|
||||
AutoSelectionBankEnabled.Value = true;
|
||||
SelectionAdditionBanksEnabled.Value = true;
|
||||
SelectionBankStates[HIT_BANK_AUTO].Value = TernaryState.True;
|
||||
SelectionAdditionBankStates[HIT_BANK_AUTO].Value = TernaryState.True;
|
||||
foreach (var (_, sampleState) in SelectionSampleStates)
|
||||
@@ -309,12 +295,17 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
bindable.Value = GetStateFromSelection(samplesInSelection.SelectMany(s => s).Where(o => o.Name == HitSampleInfo.HIT_NORMAL), h => h.Bank == bankName);
|
||||
}
|
||||
|
||||
SelectionAdditionBanksEnabled.Value = samplesInSelection.SelectMany(s => s).Any(o => o.Name != HitSampleInfo.HIT_NORMAL);
|
||||
|
||||
foreach ((string bankName, var bindable) in SelectionAdditionBankStates)
|
||||
// if there are no addition samples in the selection, do not touch the state of addition bank bindables.
|
||||
// this is to reduce annoyance from the bank resetting if the user wants to e.g. remove the only addition sound on an object, but then add another addition sound
|
||||
// while keeping the bank the same.
|
||||
// note that deselecting all objects will still reset the addition bank selection to auto via `ResetTernaryStates()`. this may need to be reconsidered later.
|
||||
if (samplesInSelection.SelectMany(s => s).Any(o => o.Name != HitSampleInfo.HIT_NORMAL))
|
||||
{
|
||||
bindable.Value = GetStateFromSelection(samplesInSelection.SelectMany(s => s).Where(o => o.Name != HitSampleInfo.HIT_NORMAL),
|
||||
h => (bankName != HIT_BANK_AUTO && h.Bank == bankName && !h.EditorAutoBank) || (bankName == HIT_BANK_AUTO && h.EditorAutoBank));
|
||||
foreach ((string bankName, var bindable) in SelectionAdditionBankStates)
|
||||
{
|
||||
bindable.Value = GetStateFromSelection(samplesInSelection.SelectMany(s => s).Where(o => o.Name != HitSampleInfo.HIT_NORMAL),
|
||||
h => (bankName != HIT_BANK_AUTO && h.Bank == bankName && !h.EditorAutoBank) || (bankName == HIT_BANK_AUTO && h.EditorAutoBank));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -453,9 +444,24 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
|
||||
EditorBeatmap.PerformOnSelection(h =>
|
||||
{
|
||||
string? forcedBank = null;
|
||||
// if the selected object(s) only have normal samples, check whether the user has preselected a singular non-auto bank using `SelectionAdditionBankStates`.
|
||||
// other scenarios are already handled by `CreateHitSampleInfo()`:
|
||||
// - if the selected object(s) already have addition samples, `CreateHitSampleInfo()` will copy the bank from said addition samples.
|
||||
// - if the selected object(s) do not have addition samples but the user has preselected auto bank, `CreateHitSampleInfo()` will use the auto bank anyway.
|
||||
if (h.Samples.All(s => s.Name == HitSampleInfo.HIT_NORMAL))
|
||||
forcedBank = SelectionAdditionBankStates.SingleOrDefault(kv => kv.Value.Value == TernaryState.True).Key;
|
||||
|
||||
// Make sure there isn't already an existing sample
|
||||
if (h.Samples.All(s => s.Name != sampleName))
|
||||
h.Samples.Add(h.CreateHitSampleInfo(sampleName));
|
||||
{
|
||||
var hitSample = h.CreateHitSampleInfo(sampleName);
|
||||
|
||||
if (forcedBank != null && forcedBank != HIT_BANK_AUTO)
|
||||
hitSample = hitSample.With(newBank: forcedBank, newEditorAutoBank: false);
|
||||
|
||||
h.Samples.Add(hitSample);
|
||||
}
|
||||
|
||||
if (h is IHasRepeats hasRepeats)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user