Skip to content

Commit

Permalink
Merge pull request #29648 from OliBomby/auto-addition2
Browse files Browse the repository at this point in the history
Add support for the auto sample addition bank in the editor
  • Loading branch information
peppy authored Oct 25, 2024
2 parents a039ee8 + 88e88bd commit 47aa2c2
Show file tree
Hide file tree
Showing 11 changed files with 157 additions and 67 deletions.
2 changes: 1 addition & 1 deletion osu.Game.Rulesets.Catch/Objects/Banana.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public BananaHitSampleInfo(int volume = 100)
{
}

public sealed override HitSampleInfo With(Optional<string> newName = default, Optional<string> newBank = default, Optional<string?> newSuffix = default, Optional<int> newVolume = default)
public sealed override HitSampleInfo With(Optional<string> newName = default, Optional<string> newBank = default, Optional<string?> newSuffix = default, Optional<int> newVolume = default, Optional<bool> newEditorAutoBank = default)
=> new BananaHitSampleInfo(newVolume.GetOr(Volume));

public bool Equals(BananaHitSampleInfo? other)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ public void TestSplitRetainsHitsounds()
{
if (slider == null) return;
sample = new HitSampleInfo("hitwhistle", HitSampleInfo.BANK_SOFT, volume: 70);
sample = new HitSampleInfo("hitwhistle", HitSampleInfo.BANK_SOFT, volume: 70, editorAutoBank: false);
slider.Samples.Add(sample.With());
});

Expand Down
13 changes: 10 additions & 3 deletions osu.Game/Audio/HitSampleInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,18 @@ public class HitSampleInfo : ISampleInfo, IEquatable<HitSampleInfo>
/// </summary>
public int Volume { get; }

public HitSampleInfo(string name, string bank = SampleControlPoint.DEFAULT_BANK, string? suffix = null, int volume = 100)
/// <summary>
/// Whether this sample should automatically assign the bank of the normal sample whenever it is set in the editor.
/// </summary>
public bool EditorAutoBank { get; }

public HitSampleInfo(string name, string bank = SampleControlPoint.DEFAULT_BANK, string? suffix = null, int volume = 100, bool editorAutoBank = true)
{
Name = name;
Bank = bank;
Suffix = suffix;
Volume = volume;
EditorAutoBank = editorAutoBank;
}

/// <summary>
Expand All @@ -92,9 +98,10 @@ public virtual IEnumerable<string> LookupNames
/// <param name="newBank">An optional new sample bank.</param>
/// <param name="newSuffix">An optional new lookup suffix.</param>
/// <param name="newVolume">An optional new volume.</param>
/// <param name="newEditorAutoBank">An optional new editor auto bank flag.</param>
/// <returns>The new <see cref="HitSampleInfo"/>.</returns>
public virtual HitSampleInfo With(Optional<string> newName = default, Optional<string> newBank = default, Optional<string?> newSuffix = default, Optional<int> newVolume = default)
=> new HitSampleInfo(newName.GetOr(Name), newBank.GetOr(Bank), newSuffix.GetOr(Suffix), newVolume.GetOr(Volume));
public virtual HitSampleInfo With(Optional<string> newName = default, Optional<string> newBank = default, Optional<string?> newSuffix = default, Optional<int> newVolume = default, Optional<bool> newEditorAutoBank = default)
=> new HitSampleInfo(newName.GetOr(Name), newBank.GetOr(Bank), newSuffix.GetOr(Suffix), newVolume.GetOr(Volume), newEditorAutoBank.GetOr(EditorAutoBank));

public virtual bool Equals(HitSampleInfo? other)
=> other != null && Name == other.Name && Bank == other.Bank && Suffix == other.Suffix;
Expand Down
2 changes: 1 addition & 1 deletion osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ private void addEndTimeData(TextWriter writer, HitObject hitObject)
private string getSampleBank(IList<HitSampleInfo> samples, bool banksOnly = false)
{
LegacySampleBank normalBank = toLegacySampleBank(samples.SingleOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL)?.Bank);
LegacySampleBank addBank = toLegacySampleBank(samples.FirstOrDefault(s => !string.IsNullOrEmpty(s.Name) && s.Name != HitSampleInfo.HIT_NORMAL)?.Bank);
LegacySampleBank addBank = toLegacySampleBank(samples.FirstOrDefault(s => !string.IsNullOrEmpty(s.Name) && s.Name != HitSampleInfo.HIT_NORMAL && !s.EditorAutoBank)?.Bank);

StringBuilder sb = new StringBuilder();

Expand Down
2 changes: 1 addition & 1 deletion osu.Game/Rulesets/Objects/HitObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ public HitSampleInfo CreateHitSampleInfo(string sampleName = HitSampleInfo.HIT_N

// Fall back to using the normal sample bank otherwise.
if (Samples.FirstOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL) is HitSampleInfo existingNormal)
return existingNormal.With(newName: sampleName);
return existingNormal.With(newName: sampleName, newEditorAutoBank: true);

return new HitSampleInfo(sampleName);
}
Expand Down
33 changes: 22 additions & 11 deletions osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,14 @@ private void readCustomSampleBanks(string str, SampleBankInfo bankInfo, bool ban
if (stringBank == @"none")
stringBank = null;
string stringAddBank = addBank.ToString().ToLowerInvariant();

if (stringAddBank == @"none")
{
bankInfo.EditorAutoBank = true;
stringAddBank = null;
}
else
bankInfo.EditorAutoBank = false;

bankInfo.BankForNormal = stringBank;
bankInfo.BankForAdditions = string.IsNullOrEmpty(stringAddBank) ? stringBank : stringAddBank;
Expand Down Expand Up @@ -477,7 +483,7 @@ private List<HitSampleInfo> convertSoundType(LegacyHitSoundType type, SampleBank

if (string.IsNullOrEmpty(bankInfo.Filename))
{
soundTypes.Add(new LegacyHitSampleInfo(HitSampleInfo.HIT_NORMAL, bankInfo.BankForNormal, bankInfo.Volume, bankInfo.CustomSampleBank,
soundTypes.Add(new LegacyHitSampleInfo(HitSampleInfo.HIT_NORMAL, bankInfo.BankForNormal, bankInfo.Volume, true, bankInfo.CustomSampleBank,
// if the sound type doesn't have the Normal flag set, attach it anyway as a layered sample.
// None also counts as a normal non-layered sample: https://osu.ppy.sh/help/wiki/osu!_File_Formats/Osu_(file_format)#hitsounds
type != LegacyHitSoundType.None && !type.HasFlag(LegacyHitSoundType.Normal)));
Expand All @@ -489,13 +495,13 @@ private List<HitSampleInfo> convertSoundType(LegacyHitSoundType type, SampleBank
}

if (type.HasFlag(LegacyHitSoundType.Finish))
soundTypes.Add(new LegacyHitSampleInfo(HitSampleInfo.HIT_FINISH, bankInfo.BankForAdditions, bankInfo.Volume, bankInfo.CustomSampleBank));
soundTypes.Add(new LegacyHitSampleInfo(HitSampleInfo.HIT_FINISH, bankInfo.BankForAdditions, bankInfo.Volume, bankInfo.EditorAutoBank, bankInfo.CustomSampleBank));

if (type.HasFlag(LegacyHitSoundType.Whistle))
soundTypes.Add(new LegacyHitSampleInfo(HitSampleInfo.HIT_WHISTLE, bankInfo.BankForAdditions, bankInfo.Volume, bankInfo.CustomSampleBank));
soundTypes.Add(new LegacyHitSampleInfo(HitSampleInfo.HIT_WHISTLE, bankInfo.BankForAdditions, bankInfo.Volume, bankInfo.EditorAutoBank, bankInfo.CustomSampleBank));

if (type.HasFlag(LegacyHitSoundType.Clap))
soundTypes.Add(new LegacyHitSampleInfo(HitSampleInfo.HIT_CLAP, bankInfo.BankForAdditions, bankInfo.Volume, bankInfo.CustomSampleBank));
soundTypes.Add(new LegacyHitSampleInfo(HitSampleInfo.HIT_CLAP, bankInfo.BankForAdditions, bankInfo.Volume, bankInfo.EditorAutoBank, bankInfo.CustomSampleBank));

return soundTypes;
}
Expand Down Expand Up @@ -534,6 +540,11 @@ private class SampleBankInfo
/// </summary>
public int CustomSampleBank;

/// <summary>
/// Whether the bank for additions should be inherited from the normal sample in edit.
/// </summary>
public bool EditorAutoBank = true;

public SampleBankInfo Clone() => (SampleBankInfo)MemberwiseClone();
}

Expand All @@ -558,21 +569,21 @@ public class LegacyHitSampleInfo : HitSampleInfo, IEquatable<LegacyHitSampleInfo
/// </summary>
public bool BankSpecified;

public LegacyHitSampleInfo(string name, string? bank = null, int volume = 0, int customSampleBank = 0, bool isLayered = false)
: base(name, bank ?? SampleControlPoint.DEFAULT_BANK, customSampleBank >= 2 ? customSampleBank.ToString() : null, volume)
public LegacyHitSampleInfo(string name, string? bank = null, int volume = 0, bool editorAutoBank = false, int customSampleBank = 0, bool isLayered = false)
: base(name, bank ?? SampleControlPoint.DEFAULT_BANK, customSampleBank >= 2 ? customSampleBank.ToString() : null, volume, editorAutoBank)
{
CustomSampleBank = customSampleBank;
BankSpecified = !string.IsNullOrEmpty(bank);
IsLayered = isLayered;
}

public sealed override HitSampleInfo With(Optional<string> newName = default, Optional<string> newBank = default, Optional<string?> newSuffix = default, Optional<int> newVolume = default)
=> With(newName, newBank, newVolume);
public sealed override HitSampleInfo With(Optional<string> newName = default, Optional<string> newBank = default, Optional<string?> newSuffix = default, Optional<int> newVolume = default, Optional<bool> newEditorAutoBank = default)
=> With(newName, newBank, newVolume, newEditorAutoBank);

public virtual LegacyHitSampleInfo With(Optional<string> newName = default, Optional<string> newBank = default, Optional<int> newVolume = default,
public virtual LegacyHitSampleInfo With(Optional<string> newName = default, Optional<string> newBank = default, Optional<int> newVolume = default, Optional<bool> newEditorAutoBank = default,
Optional<int> newCustomSampleBank = default,
Optional<bool> newIsLayered = default)
=> new LegacyHitSampleInfo(newName.GetOr(Name), newBank.GetOr(Bank), newVolume.GetOr(Volume), newCustomSampleBank.GetOr(CustomSampleBank), newIsLayered.GetOr(IsLayered));
=> new LegacyHitSampleInfo(newName.GetOr(Name), newBank.GetOr(Bank), newVolume.GetOr(Volume), newEditorAutoBank.GetOr(EditorAutoBank), newCustomSampleBank.GetOr(CustomSampleBank), newIsLayered.GetOr(IsLayered));

public bool Equals(LegacyHitSampleInfo? other)
// The additions to equality checks here are *required* to ensure that pooling works correctly.
Expand Down Expand Up @@ -604,7 +615,7 @@ public FileHitSampleInfo(string filename, int volume)
Path.ChangeExtension(Filename, null)
};

public sealed override LegacyHitSampleInfo With(Optional<string> newName = default, Optional<string> newBank = default, Optional<int> newVolume = default,
public sealed override LegacyHitSampleInfo With(Optional<string> newName = default, Optional<string> newBank = default, Optional<int> newVolume = default, Optional<bool> newEditorAutoBank = default,
Optional<int> newCustomSampleBank = default,
Optional<bool> newIsLayered = default)
=> new FileHitSampleInfo(Filename, newVolume.GetOr(Volume));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Overlays;
Expand All @@ -14,7 +16,7 @@

namespace osu.Game.Screens.Edit.Components.TernaryButtons
{
public partial class DrawableTernaryButton : OsuButton
public partial class DrawableTernaryButton : OsuButton, IHasTooltip
{
private Color4 defaultBackgroundColour;
private Color4 defaultIconColour;
Expand Down Expand Up @@ -58,12 +60,16 @@ protected override void LoadComplete()
base.LoadComplete();

Button.Bindable.BindValueChanged(_ => updateSelectionState(), true);
Button.Enabled.BindTo(Enabled);

Action = onAction;
}

private void onAction()
{
if (!Button.Enabled.Value)
return;

Button.Toggle();
}

Expand Down Expand Up @@ -98,5 +104,7 @@ private void updateSelectionState()
Anchor = Anchor.CentreLeft,
X = 40f
};

public LocalisableString TooltipText => Button.Tooltip;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@ public class TernaryButton
{
public readonly Bindable<TernaryState> Bindable;

public readonly Bindable<bool> Enabled = new Bindable<bool>(true);

public readonly string Description;

/// <summary>
/// A function which creates a drawable icon to represent this item. If null, a sane default should be used.
/// </summary>
public readonly Func<Drawable>? CreateIcon;

public string Tooltip { get; set; } = string.Empty;

public TernaryButton(Bindable<TernaryState> bindable, string description, Func<Drawable>? createIcon = null)
{
Bindable = bindable;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ private void load()
SampleBankTernaryStates = createSampleBankTernaryButtons(SelectionHandler.SelectionBankStates).ToArray();
SampleAdditionBankTernaryStates = createSampleBankTernaryButtons(SelectionHandler.SelectionAdditionBankStates).ToArray();

SelectionHandler.AutoSelectionBankEnabled.BindValueChanged(_ => updateAutoBankTernaryButtonTooltip(), true);
SelectionHandler.SelectionAdditionBanksEnabled.BindValueChanged(_ => updateAdditionBankTernaryButtonTooltips(), true);

AddInternal(new DrawableRulesetDependenciesProvidingContainer(Composer.Ruleset)
{
Child = placementBlueprintContainer
Expand Down Expand Up @@ -288,6 +291,26 @@ public static Drawable GetIconForSample(string sampleName)
return null;
}

private void updateAutoBankTernaryButtonTooltip()
{
bool enabled = SelectionHandler.AutoSelectionBankEnabled.Value;

var autoBankButton = SampleBankTernaryStates.Single(t => t.Bindable == SelectionHandler.SelectionBankStates[EditorSelectionHandler.HIT_BANK_AUTO]);
autoBankButton.Enabled.Value = enabled;
autoBankButton.Tooltip = !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 SampleAdditionBankTernaryStates)
{
ternaryButton.Enabled.Value = enabled;
ternaryButton.Tooltip = !enabled ? "Add an addition sample first to be able to set a bank" : string.Empty;
}
}

#region Placement

/// <summary>
Expand Down
Loading

0 comments on commit 47aa2c2

Please sign in to comment.