1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-17 13:42:56 +08:00

addition bank toggles in compose

This commit is contained in:
OliBomby 2024-07-14 20:43:16 +02:00
parent c854dfd6fb
commit 952540024e
3 changed files with 149 additions and 15 deletions

View File

@ -85,6 +85,7 @@ namespace osu.Game.Rulesets.Edit
private EditorRadioButtonCollection toolboxCollection; private EditorRadioButtonCollection toolboxCollection;
private FillFlowContainer togglesCollection; private FillFlowContainer togglesCollection;
private FillFlowContainer sampleBankTogglesCollection; private FillFlowContainer sampleBankTogglesCollection;
private FillFlowContainer sampleAdditionBankTogglesCollection;
private IBindable<bool> hasTiming; private IBindable<bool> hasTiming;
private Bindable<bool> autoSeekOnPlacement; private Bindable<bool> autoSeekOnPlacement;
@ -184,7 +185,17 @@ namespace osu.Game.Rulesets.Edit
Direction = FillDirection.Vertical, Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 5), Spacing = new Vector2(0, 5),
}, },
} },
new EditorToolboxGroup("additions (Alt-Q~R)")
{
Child = sampleAdditionBankTogglesCollection = new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 5),
},
},
} }
}, },
} }
@ -230,6 +241,7 @@ namespace osu.Game.Rulesets.Edit
togglesCollection.AddRange(TernaryStates.Select(b => new DrawableTernaryButton(b))); togglesCollection.AddRange(TernaryStates.Select(b => new DrawableTernaryButton(b)));
sampleBankTogglesCollection.AddRange(BlueprintContainer.SampleBankTernaryStates.Select(b => new DrawableTernaryButton(b))); sampleBankTogglesCollection.AddRange(BlueprintContainer.SampleBankTernaryStates.Select(b => new DrawableTernaryButton(b)));
sampleAdditionBankTogglesCollection.AddRange(BlueprintContainer.SampleAdditionBankTernaryStates.Select(b => new DrawableTernaryButton(b)));
setSelectTool(); setSelectTool();
@ -358,7 +370,7 @@ namespace osu.Game.Rulesets.Edit
protected override bool OnKeyDown(KeyDownEvent e) protected override bool OnKeyDown(KeyDownEvent e)
{ {
if (e.ControlPressed || e.AltPressed || e.SuperPressed) if (e.ControlPressed || e.SuperPressed)
return false; return false;
if (checkLeftToggleFromKey(e.Key, out int leftIndex)) if (checkLeftToggleFromKey(e.Key, out int leftIndex))
@ -375,9 +387,11 @@ namespace osu.Game.Rulesets.Edit
if (checkRightToggleFromKey(e.Key, out int rightIndex)) if (checkRightToggleFromKey(e.Key, out int rightIndex))
{ {
var item = e.ShiftPressed var item = e.AltPressed
? sampleBankTogglesCollection.ElementAtOrDefault(rightIndex) ? sampleAdditionBankTogglesCollection.ElementAtOrDefault(rightIndex)
: togglesCollection.ElementAtOrDefault(rightIndex); : e.ShiftPressed
? sampleBankTogglesCollection.ElementAtOrDefault(rightIndex)
: togglesCollection.ElementAtOrDefault(rightIndex);
if (item is DrawableTernaryButton button) if (item is DrawableTernaryButton button)
{ {

View File

@ -62,7 +62,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
private void load() private void load()
{ {
MainTernaryStates = CreateTernaryButtons().ToArray(); MainTernaryStates = CreateTernaryButtons().ToArray();
SampleBankTernaryStates = createSampleBankTernaryButtons().ToArray(); SampleBankTernaryStates = createSampleBankTernaryButtons(SelectionHandler.SelectionBankStates).ToArray();
SampleAdditionBankTernaryStates = createSampleBankTernaryButtons(SelectionHandler.SelectionAdditionBankStates).ToArray();
AddInternal(new DrawableRulesetDependenciesProvidingContainer(Composer.Ruleset) AddInternal(new DrawableRulesetDependenciesProvidingContainer(Composer.Ruleset)
{ {
@ -219,6 +220,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
public TernaryButton[] SampleBankTernaryStates { get; private set; } public TernaryButton[] SampleBankTernaryStates { get; private set; }
public TernaryButton[] SampleAdditionBankTernaryStates { get; private set; }
/// <summary> /// <summary>
/// Create all ternary states required to be displayed to the user. /// Create all ternary states required to be displayed to the user.
/// </summary> /// </summary>
@ -231,9 +234,9 @@ namespace osu.Game.Screens.Edit.Compose.Components
yield return new TernaryButton(kvp.Value, kvp.Key.Replace("hit", string.Empty).Titleize(), () => GetIconForSample(kvp.Key)); yield return new TernaryButton(kvp.Value, kvp.Key.Replace("hit", string.Empty).Titleize(), () => GetIconForSample(kvp.Key));
} }
private IEnumerable<TernaryButton> createSampleBankTernaryButtons() private IEnumerable<TernaryButton> createSampleBankTernaryButtons(Dictionary<string, Bindable<TernaryState>> sampleBankStates)
{ {
foreach (var kvp in SelectionHandler.SelectionBankStates) foreach (var kvp in sampleBankStates)
yield return new TernaryButton(kvp.Value, kvp.Key.Titleize(), () => getIconForBank(kvp.Key)); yield return new TernaryButton(kvp.Value, kvp.Key.Titleize(), () => getIconForBank(kvp.Key));
} }

View File

@ -58,6 +58,11 @@ namespace osu.Game.Screens.Edit.Compose.Components
/// </summary> /// </summary>
public readonly Dictionary<string, Bindable<TernaryState>> SelectionBankStates = new Dictionary<string, Bindable<TernaryState>>(); public readonly Dictionary<string, Bindable<TernaryState>> SelectionBankStates = new Dictionary<string, Bindable<TernaryState>>();
/// <summary>
/// The state of each sample addition bank type for all selected hitobjects.
/// </summary>
public readonly Dictionary<string, Bindable<TernaryState>> SelectionAdditionBankStates = new Dictionary<string, Bindable<TernaryState>>();
/// <summary> /// <summary>
/// Set up ternary state bindables and bind them to selection/hitobject changes (in both directions) /// Set up ternary state bindables and bind them to selection/hitobject changes (in both directions)
/// </summary> /// </summary>
@ -90,7 +95,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
// Never remove a sample bank. // Never remove a sample bank.
// These are basically radio buttons, not toggles. // These are basically radio buttons, not toggles.
if (SelectedItems.All(h => h.Samples.All(s => s.Bank == bankName))) if (SelectedItems.All(h => h.Samples.Where(o => o.Name == HitSampleInfo.HIT_NORMAL).All(s => s.Bank == bankName)))
bindable.Value = TernaryState.True; bindable.Value = TernaryState.True;
} }
@ -127,8 +132,70 @@ namespace osu.Game.Screens.Edit.Compose.Components
SelectionBankStates[bankName] = bindable; SelectionBankStates[bankName] = bindable;
} }
foreach (string bankName in HitSampleInfo.AllBanks.Prepend(HIT_BANK_AUTO))
{
var bindable = new Bindable<TernaryState>
{
Description = bankName.Titleize()
};
bindable.ValueChanged += state =>
{
switch (state.NewValue)
{
case TernaryState.False:
if (SelectedItems.Count == 0)
{
// Ensure that if this is the last selected bank, it should remain selected.
if (SelectionAdditionBankStates.Values.All(b => b.Value == TernaryState.False))
bindable.Value = TernaryState.True;
}
// Auto should never apply when there is a selection made.
// Completely empty selections should be allowed in the case that none of the selected objects have any addition samples.
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
{
// Auto should just not apply if there's a selection already made.
// Maybe we could make it a disabled button in the future, but right now the editor buttons don't support disabled state.
if (bankName == HIT_BANK_AUTO)
{
bindable.Value = TernaryState.False;
break;
}
// If none of the selected objects have any addition samples, we should not apply the bank.
if (SelectedItems.All(h => h.Samples.All(o => o.Name == HitSampleInfo.HIT_NORMAL)))
{
bindable.Value = TernaryState.False;
break;
}
SetSampleAdditionBank(bankName);
}
break;
}
};
SelectionAdditionBankStates[bankName] = bindable;
}
// start with normal selected. // start with normal selected.
SelectionBankStates[SampleControlPoint.DEFAULT_BANK].Value = TernaryState.True; SelectionBankStates[SampleControlPoint.DEFAULT_BANK].Value = TernaryState.True;
SelectionAdditionBankStates[SampleControlPoint.DEFAULT_BANK].Value = TernaryState.True;
foreach (string sampleName in HitSampleInfo.AllAdditions) foreach (string sampleName in HitSampleInfo.AllAdditions)
{ {
@ -186,7 +253,12 @@ namespace osu.Game.Screens.Edit.Compose.Components
foreach ((string bankName, var bindable) in SelectionBankStates) foreach ((string bankName, var bindable) in SelectionBankStates)
{ {
bindable.Value = GetStateFromSelection(samplesInSelection.SelectMany(s => s), h => h.Bank == bankName); bindable.Value = GetStateFromSelection(samplesInSelection.SelectMany(s => s).Where(o => o.Name == HitSampleInfo.HIT_NORMAL), h => h.Bank == bankName);
}
foreach ((string bankName, var bindable) in SelectionAdditionBankStates)
{
bindable.Value = GetStateFromSelection(samplesInSelection.SelectMany(s => s).Where(o => o.Name != HitSampleInfo.HIT_NORMAL), h => h.Bank == bankName);
} }
IEnumerable<IList<HitSampleInfo>> enumerateAllSamples(HitObject hitObject) IEnumerable<IList<HitSampleInfo>> enumerateAllSamples(HitObject hitObject)
@ -213,12 +285,12 @@ namespace osu.Game.Screens.Edit.Compose.Components
{ {
bool hasRelevantBank(HitObject hitObject) bool hasRelevantBank(HitObject hitObject)
{ {
bool result = hitObject.Samples.All(s => s.Bank == bankName); bool result = hitObject.Samples.Where(o => o.Name == HitSampleInfo.HIT_NORMAL).All(s => s.Bank == bankName);
if (hitObject is IHasRepeats hasRepeats) if (hitObject is IHasRepeats hasRepeats)
{ {
foreach (var node in hasRepeats.NodeSamples) foreach (var node in hasRepeats.NodeSamples)
result &= node.All(s => s.Bank == bankName); result &= node.Where(o => o.Name == HitSampleInfo.HIT_NORMAL).All(s => s.Bank == bankName);
} }
return result; return result;
@ -229,15 +301,54 @@ namespace osu.Game.Screens.Edit.Compose.Components
EditorBeatmap.PerformOnSelection(h => EditorBeatmap.PerformOnSelection(h =>
{ {
if (h.Samples.All(s => s.Bank == bankName)) if (h.Samples.Where(o => o.Name == HitSampleInfo.HIT_NORMAL).All(s => s.Bank == bankName))
return; return;
h.Samples = h.Samples.Select(s => s.With(newBank: bankName)).ToList(); h.Samples = h.Samples.Select(s => s.Name == HitSampleInfo.HIT_NORMAL ? s.With(newBank: bankName) : s).ToList();
if (h is IHasRepeats hasRepeats) if (h is IHasRepeats hasRepeats)
{ {
for (int i = 0; i < hasRepeats.NodeSamples.Count; ++i) for (int i = 0; i < hasRepeats.NodeSamples.Count; ++i)
hasRepeats.NodeSamples[i] = hasRepeats.NodeSamples[i].Select(s => s.With(newBank: bankName)).ToList(); hasRepeats.NodeSamples[i] = hasRepeats.NodeSamples[i].Select(s => s.Name == HitSampleInfo.HIT_NORMAL ? s.With(newBank: bankName) : s).ToList();
}
EditorBeatmap.Update(h);
});
}
/// <summary>
/// Sets the sample addition bank for all selected <see cref="HitObject"/>s.
/// </summary>
/// <param name="bankName">The name of the sample bank.</param>
public void SetSampleAdditionBank(string bankName)
{
bool hasRelevantBank(HitObject hitObject)
{
bool result = hitObject.Samples.Where(o => o.Name != HitSampleInfo.HIT_NORMAL).All(s => s.Bank == bankName);
if (hitObject is IHasRepeats hasRepeats)
{
foreach (var node in hasRepeats.NodeSamples)
result &= node.Where(o => o.Name != HitSampleInfo.HIT_NORMAL).All(s => s.Bank == bankName);
}
return result;
}
if (SelectedItems.All(hasRelevantBank))
return;
EditorBeatmap.PerformOnSelection(h =>
{
if (h.Samples.Where(o => o.Name != HitSampleInfo.HIT_NORMAL).All(s => s.Bank == bankName))
return;
h.Samples = h.Samples.Select(s => s.Name != HitSampleInfo.HIT_NORMAL ? s.With(newBank: bankName) : s).ToList();
if (h is IHasRepeats hasRepeats)
{
for (int i = 0; i < hasRepeats.NodeSamples.Count; ++i)
hasRepeats.NodeSamples[i] = hasRepeats.NodeSamples[i].Select(s => s.Name != HitSampleInfo.HIT_NORMAL ? s.With(newBank: bankName) : s).ToList();
} }
EditorBeatmap.Update(h); EditorBeatmap.Update(h);
@ -366,6 +477,12 @@ namespace osu.Game.Screens.Edit.Compose.Components
Items = SelectionBankStates.Select(kvp => Items = SelectionBankStates.Select(kvp =>
new TernaryStateToggleMenuItem(kvp.Value.Description) { State = { BindTarget = kvp.Value } }).ToArray() new TernaryStateToggleMenuItem(kvp.Value.Description) { State = { BindTarget = kvp.Value } }).ToArray()
}; };
yield return new OsuMenuItem("Addition bank")
{
Items = SelectionAdditionBankStates.Select(kvp =>
new TernaryStateToggleMenuItem(kvp.Value.Description) { State = { BindTarget = kvp.Value } }).ToArray()
};
} }
#endregion #endregion