mirror of
https://github.com/ppy/osu.git
synced 2025-01-21 14:52:56 +08:00
Merge pull request #28863 from OliBomby/additions
Add toggles and hotkeys for configuring sample addition bank
This commit is contained in:
commit
2103b3e186
@ -362,6 +362,12 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
AddStep("add whistle addition", () =>
|
||||||
|
{
|
||||||
|
foreach (var h in EditorBeatmap.HitObjects)
|
||||||
|
h.Samples.Add(new HitSampleInfo(HitSampleInfo.HIT_WHISTLE, HitSampleInfo.BANK_SOFT));
|
||||||
|
});
|
||||||
|
|
||||||
AddStep("select both objects", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects));
|
AddStep("select both objects", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects));
|
||||||
|
|
||||||
hitObjectHasSampleBank(0, HitSampleInfo.BANK_SOFT);
|
hitObjectHasSampleBank(0, HitSampleInfo.BANK_SOFT);
|
||||||
@ -374,8 +380,10 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
InputManager.ReleaseKey(Key.ShiftLeft);
|
InputManager.ReleaseKey(Key.ShiftLeft);
|
||||||
});
|
});
|
||||||
|
|
||||||
hitObjectHasSampleBank(0, HitSampleInfo.BANK_NORMAL);
|
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||||
hitObjectHasSampleBank(1, HitSampleInfo.BANK_NORMAL);
|
hitObjectHasSampleNormalBank(1, HitSampleInfo.BANK_NORMAL);
|
||||||
|
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_SOFT);
|
||||||
|
hitObjectHasSampleAdditionBank(1, HitSampleInfo.BANK_SOFT);
|
||||||
|
|
||||||
AddStep("Press drum bank shortcut", () =>
|
AddStep("Press drum bank shortcut", () =>
|
||||||
{
|
{
|
||||||
@ -384,8 +392,10 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
InputManager.ReleaseKey(Key.ShiftLeft);
|
InputManager.ReleaseKey(Key.ShiftLeft);
|
||||||
});
|
});
|
||||||
|
|
||||||
hitObjectHasSampleBank(0, HitSampleInfo.BANK_DRUM);
|
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_DRUM);
|
||||||
hitObjectHasSampleBank(1, HitSampleInfo.BANK_DRUM);
|
hitObjectHasSampleNormalBank(1, HitSampleInfo.BANK_DRUM);
|
||||||
|
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_SOFT);
|
||||||
|
hitObjectHasSampleAdditionBank(1, HitSampleInfo.BANK_SOFT);
|
||||||
|
|
||||||
AddStep("Press auto bank shortcut", () =>
|
AddStep("Press auto bank shortcut", () =>
|
||||||
{
|
{
|
||||||
@ -395,8 +405,47 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Should be a noop.
|
// Should be a noop.
|
||||||
hitObjectHasSampleBank(0, HitSampleInfo.BANK_DRUM);
|
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_DRUM);
|
||||||
hitObjectHasSampleBank(1, HitSampleInfo.BANK_DRUM);
|
hitObjectHasSampleNormalBank(1, HitSampleInfo.BANK_DRUM);
|
||||||
|
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_SOFT);
|
||||||
|
hitObjectHasSampleAdditionBank(1, HitSampleInfo.BANK_SOFT);
|
||||||
|
|
||||||
|
AddStep("Press addition normal bank shortcut", () =>
|
||||||
|
{
|
||||||
|
InputManager.PressKey(Key.AltLeft);
|
||||||
|
InputManager.Key(Key.W);
|
||||||
|
InputManager.ReleaseKey(Key.AltLeft);
|
||||||
|
});
|
||||||
|
|
||||||
|
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_DRUM);
|
||||||
|
hitObjectHasSampleNormalBank(1, HitSampleInfo.BANK_DRUM);
|
||||||
|
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_NORMAL);
|
||||||
|
hitObjectHasSampleAdditionBank(1, HitSampleInfo.BANK_NORMAL);
|
||||||
|
|
||||||
|
AddStep("Press addition drum bank shortcut", () =>
|
||||||
|
{
|
||||||
|
InputManager.PressKey(Key.AltLeft);
|
||||||
|
InputManager.Key(Key.R);
|
||||||
|
InputManager.ReleaseKey(Key.AltLeft);
|
||||||
|
});
|
||||||
|
|
||||||
|
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_DRUM);
|
||||||
|
hitObjectHasSampleNormalBank(1, HitSampleInfo.BANK_DRUM);
|
||||||
|
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_DRUM);
|
||||||
|
hitObjectHasSampleAdditionBank(1, HitSampleInfo.BANK_DRUM);
|
||||||
|
|
||||||
|
AddStep("Press auto bank shortcut", () =>
|
||||||
|
{
|
||||||
|
InputManager.PressKey(Key.AltLeft);
|
||||||
|
InputManager.Key(Key.Q);
|
||||||
|
InputManager.ReleaseKey(Key.AltLeft);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Should be a noop.
|
||||||
|
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_DRUM);
|
||||||
|
hitObjectHasSampleNormalBank(1, HitSampleInfo.BANK_DRUM);
|
||||||
|
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_DRUM);
|
||||||
|
hitObjectHasSampleAdditionBank(1, HitSampleInfo.BANK_DRUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -414,7 +463,21 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
InputManager.ReleaseKey(Key.ShiftLeft);
|
InputManager.ReleaseKey(Key.ShiftLeft);
|
||||||
});
|
});
|
||||||
|
|
||||||
checkPlacementSample(HitSampleInfo.BANK_NORMAL);
|
AddStep("Press soft addition bank shortcut", () =>
|
||||||
|
{
|
||||||
|
InputManager.PressKey(Key.AltLeft);
|
||||||
|
InputManager.Key(Key.E);
|
||||||
|
InputManager.ReleaseKey(Key.AltLeft);
|
||||||
|
});
|
||||||
|
|
||||||
|
checkPlacementSampleBank(HitSampleInfo.BANK_NORMAL);
|
||||||
|
|
||||||
|
AddStep("Press finish sample shortcut", () =>
|
||||||
|
{
|
||||||
|
InputManager.Key(Key.E);
|
||||||
|
});
|
||||||
|
|
||||||
|
checkPlacementSampleAdditionBank(HitSampleInfo.BANK_SOFT);
|
||||||
|
|
||||||
AddStep("Press drum bank shortcut", () =>
|
AddStep("Press drum bank shortcut", () =>
|
||||||
{
|
{
|
||||||
@ -423,7 +486,18 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
InputManager.ReleaseKey(Key.ShiftLeft);
|
InputManager.ReleaseKey(Key.ShiftLeft);
|
||||||
});
|
});
|
||||||
|
|
||||||
checkPlacementSample(HitSampleInfo.BANK_DRUM);
|
checkPlacementSampleBank(HitSampleInfo.BANK_DRUM);
|
||||||
|
checkPlacementSampleAdditionBank(HitSampleInfo.BANK_SOFT);
|
||||||
|
|
||||||
|
AddStep("Press drum addition bank shortcut", () =>
|
||||||
|
{
|
||||||
|
InputManager.PressKey(Key.AltLeft);
|
||||||
|
InputManager.Key(Key.R);
|
||||||
|
InputManager.ReleaseKey(Key.AltLeft);
|
||||||
|
});
|
||||||
|
|
||||||
|
checkPlacementSampleBank(HitSampleInfo.BANK_DRUM);
|
||||||
|
checkPlacementSampleAdditionBank(HitSampleInfo.BANK_DRUM);
|
||||||
|
|
||||||
AddStep("Press auto bank shortcut", () =>
|
AddStep("Press auto bank shortcut", () =>
|
||||||
{
|
{
|
||||||
@ -432,15 +506,29 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
InputManager.ReleaseKey(Key.ShiftLeft);
|
InputManager.ReleaseKey(Key.ShiftLeft);
|
||||||
});
|
});
|
||||||
|
|
||||||
checkPlacementSample(HitSampleInfo.BANK_NORMAL);
|
checkPlacementSampleBank(HitSampleInfo.BANK_NORMAL);
|
||||||
|
checkPlacementSampleAdditionBank(HitSampleInfo.BANK_DRUM);
|
||||||
|
|
||||||
|
AddStep("Press auto addition bank shortcut", () =>
|
||||||
|
{
|
||||||
|
InputManager.PressKey(Key.AltLeft);
|
||||||
|
InputManager.Key(Key.Q);
|
||||||
|
InputManager.ReleaseKey(Key.AltLeft);
|
||||||
|
});
|
||||||
|
|
||||||
|
checkPlacementSampleBank(HitSampleInfo.BANK_NORMAL);
|
||||||
|
checkPlacementSampleAdditionBank(HitSampleInfo.BANK_NORMAL);
|
||||||
|
|
||||||
AddStep("Move after second object", () => EditorClock.Seek(750));
|
AddStep("Move after second object", () => EditorClock.Seek(750));
|
||||||
checkPlacementSample(HitSampleInfo.BANK_SOFT);
|
checkPlacementSampleBank(HitSampleInfo.BANK_SOFT);
|
||||||
|
checkPlacementSampleAdditionBank(HitSampleInfo.BANK_SOFT);
|
||||||
|
|
||||||
AddStep("Move to first object", () => EditorClock.Seek(0));
|
AddStep("Move to first object", () => EditorClock.Seek(0));
|
||||||
checkPlacementSample(HitSampleInfo.BANK_NORMAL);
|
checkPlacementSampleBank(HitSampleInfo.BANK_NORMAL);
|
||||||
|
checkPlacementSampleAdditionBank(HitSampleInfo.BANK_NORMAL);
|
||||||
|
|
||||||
void checkPlacementSample(string expected) => AddAssert($"Placement sample is {expected}", () => EditorBeatmap.PlacementObject.Value.Samples.First().Bank, () => Is.EqualTo(expected));
|
void checkPlacementSampleBank(string expected) => AddAssert($"Placement sample is {expected}", () => EditorBeatmap.PlacementObject.Value.Samples.First(s => s.Name == HitSampleInfo.HIT_NORMAL).Bank, () => Is.EqualTo(expected));
|
||||||
|
void checkPlacementSampleAdditionBank(string expected) => AddAssert($"Placement sample addition is {expected}", () => EditorBeatmap.PlacementObject.Value.Samples.First(s => s.Name != HitSampleInfo.HIT_NORMAL).Bank, () => Is.EqualTo(expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -585,7 +673,29 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
hitObjectHasSamples(2, HitSampleInfo.HIT_NORMAL);
|
hitObjectHasSamples(2, HitSampleInfo.HIT_NORMAL);
|
||||||
hitObjectNodeHasSampleBank(2, 0, HitSampleInfo.BANK_DRUM);
|
hitObjectNodeHasSampleBank(2, 0, HitSampleInfo.BANK_DRUM);
|
||||||
hitObjectNodeHasSamples(2, 0, HitSampleInfo.HIT_NORMAL);
|
hitObjectNodeHasSamples(2, 0, HitSampleInfo.HIT_NORMAL);
|
||||||
hitObjectNodeHasSampleBank(2, 1, HitSampleInfo.BANK_DRUM);
|
hitObjectNodeHasSampleNormalBank(2, 1, HitSampleInfo.BANK_DRUM);
|
||||||
|
hitObjectNodeHasSampleAdditionBank(2, 1, HitSampleInfo.BANK_SOFT);
|
||||||
|
hitObjectNodeHasSamples(2, 1, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_WHISTLE);
|
||||||
|
|
||||||
|
AddStep("set normal addition bank", () =>
|
||||||
|
{
|
||||||
|
InputManager.PressKey(Key.LAlt);
|
||||||
|
InputManager.Key(Key.W);
|
||||||
|
InputManager.ReleaseKey(Key.LAlt);
|
||||||
|
});
|
||||||
|
|
||||||
|
hitObjectHasSampleBank(0, HitSampleInfo.BANK_DRUM);
|
||||||
|
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL);
|
||||||
|
|
||||||
|
hitObjectHasSampleBank(1, HitSampleInfo.BANK_DRUM);
|
||||||
|
hitObjectHasSamples(1, HitSampleInfo.HIT_NORMAL);
|
||||||
|
|
||||||
|
hitObjectHasSampleBank(2, HitSampleInfo.BANK_DRUM);
|
||||||
|
hitObjectHasSamples(2, HitSampleInfo.HIT_NORMAL);
|
||||||
|
hitObjectNodeHasSampleBank(2, 0, HitSampleInfo.BANK_DRUM);
|
||||||
|
hitObjectNodeHasSamples(2, 0, HitSampleInfo.HIT_NORMAL);
|
||||||
|
hitObjectNodeHasSampleNormalBank(2, 1, HitSampleInfo.BANK_DRUM);
|
||||||
|
hitObjectNodeHasSampleAdditionBank(2, 1, HitSampleInfo.BANK_NORMAL);
|
||||||
hitObjectNodeHasSamples(2, 1, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_WHISTLE);
|
hitObjectNodeHasSamples(2, 1, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_WHISTLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -629,20 +739,37 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
InputManager.ReleaseKey(Key.LShift);
|
InputManager.ReleaseKey(Key.LShift);
|
||||||
});
|
});
|
||||||
|
|
||||||
hitObjectHasSampleBank(0, HitSampleInfo.BANK_SOFT);
|
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_SOFT);
|
||||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_WHISTLE);
|
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_WHISTLE);
|
||||||
hitObjectNodeHasSampleBank(0, 0, HitSampleInfo.BANK_SOFT);
|
hitObjectNodeHasSampleNormalBank(0, 0, HitSampleInfo.BANK_SOFT);
|
||||||
hitObjectNodeHasSamples(0, 0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_CLAP);
|
hitObjectNodeHasSamples(0, 0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_CLAP);
|
||||||
hitObjectNodeHasSampleBank(0, 1, HitSampleInfo.BANK_SOFT);
|
hitObjectNodeHasSampleNormalBank(0, 1, HitSampleInfo.BANK_SOFT);
|
||||||
hitObjectNodeHasSamples(0, 1, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_WHISTLE);
|
hitObjectNodeHasSamples(0, 1, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_WHISTLE);
|
||||||
|
|
||||||
AddStep("unify whistle addition", () => InputManager.Key(Key.W));
|
AddStep("unify whistle addition", () => InputManager.Key(Key.W));
|
||||||
|
|
||||||
hitObjectHasSampleBank(0, HitSampleInfo.BANK_SOFT);
|
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_SOFT);
|
||||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_WHISTLE);
|
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_WHISTLE);
|
||||||
hitObjectNodeHasSampleBank(0, 0, HitSampleInfo.BANK_SOFT);
|
hitObjectNodeHasSampleNormalBank(0, 0, HitSampleInfo.BANK_SOFT);
|
||||||
hitObjectNodeHasSamples(0, 0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_CLAP, HitSampleInfo.HIT_WHISTLE);
|
hitObjectNodeHasSamples(0, 0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_CLAP, HitSampleInfo.HIT_WHISTLE);
|
||||||
hitObjectNodeHasSampleBank(0, 1, HitSampleInfo.BANK_SOFT);
|
hitObjectNodeHasSampleNormalBank(0, 1, HitSampleInfo.BANK_SOFT);
|
||||||
|
hitObjectNodeHasSamples(0, 1, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_WHISTLE);
|
||||||
|
|
||||||
|
AddStep("set drum addition bank", () =>
|
||||||
|
{
|
||||||
|
InputManager.PressKey(Key.LAlt);
|
||||||
|
InputManager.Key(Key.R);
|
||||||
|
InputManager.ReleaseKey(Key.LAlt);
|
||||||
|
});
|
||||||
|
|
||||||
|
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_SOFT);
|
||||||
|
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_DRUM);
|
||||||
|
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_WHISTLE);
|
||||||
|
hitObjectNodeHasSampleNormalBank(0, 0, HitSampleInfo.BANK_SOFT);
|
||||||
|
hitObjectNodeHasSampleAdditionBank(0, 0, HitSampleInfo.BANK_DRUM);
|
||||||
|
hitObjectNodeHasSamples(0, 0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_CLAP, HitSampleInfo.HIT_WHISTLE);
|
||||||
|
hitObjectNodeHasSampleNormalBank(0, 1, HitSampleInfo.BANK_SOFT);
|
||||||
|
hitObjectNodeHasSampleAdditionBank(0, 1, HitSampleInfo.BANK_DRUM);
|
||||||
hitObjectNodeHasSamples(0, 1, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_WHISTLE);
|
hitObjectNodeHasSamples(0, 1, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_WHISTLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +165,9 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
AddStep("enable automatic bank assignment", () =>
|
AddStep("enable automatic bank assignment", () =>
|
||||||
{
|
{
|
||||||
InputManager.PressKey(Key.LShift);
|
InputManager.PressKey(Key.LShift);
|
||||||
|
InputManager.PressKey(Key.LAlt);
|
||||||
InputManager.Key(Key.Q);
|
InputManager.Key(Key.Q);
|
||||||
|
InputManager.ReleaseKey(Key.LAlt);
|
||||||
InputManager.ReleaseKey(Key.LShift);
|
InputManager.ReleaseKey(Key.LShift);
|
||||||
});
|
});
|
||||||
AddStep("select circle placement tool", () => InputManager.Key(Key.Number2));
|
AddStep("select circle placement tool", () => InputManager.Key(Key.Number2));
|
||||||
@ -228,7 +230,9 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
AddStep("select drum bank", () =>
|
AddStep("select drum bank", () =>
|
||||||
{
|
{
|
||||||
InputManager.PressKey(Key.LShift);
|
InputManager.PressKey(Key.LShift);
|
||||||
|
InputManager.PressKey(Key.LAlt);
|
||||||
InputManager.Key(Key.R);
|
InputManager.Key(Key.R);
|
||||||
|
InputManager.ReleaseKey(Key.LAlt);
|
||||||
InputManager.ReleaseKey(Key.LShift);
|
InputManager.ReleaseKey(Key.LShift);
|
||||||
});
|
});
|
||||||
AddStep("enable clap addition", () => InputManager.Key(Key.R));
|
AddStep("enable clap addition", () => InputManager.Key(Key.R));
|
||||||
|
34
osu.Game/Rulesets/Edit/ExpandableSpriteText.cs
Normal file
34
osu.Game/Rulesets/Edit/ExpandableSpriteText.cs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Edit
|
||||||
|
{
|
||||||
|
internal partial class ExpandableSpriteText : OsuSpriteText, IExpandable
|
||||||
|
{
|
||||||
|
public BindableBool Expanded { get; } = new BindableBool();
|
||||||
|
|
||||||
|
[Resolved(canBeNull: true)]
|
||||||
|
private IExpandingContainer? expandingContainer { get; set; }
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
expandingContainer?.Expanded.BindValueChanged(containerExpanded =>
|
||||||
|
{
|
||||||
|
Expanded.Value = containerExpanded.NewValue;
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
Expanded.BindValueChanged(expanded =>
|
||||||
|
{
|
||||||
|
this.FadeTo(expanded.NewValue ? 1 : 0, 150, Easing.OutQuint);
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,6 +18,7 @@ using osu.Framework.Input.Events;
|
|||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Rulesets.Configuration;
|
using osu.Game.Rulesets.Configuration;
|
||||||
using osu.Game.Rulesets.Edit.Tools;
|
using osu.Game.Rulesets.Edit.Tools;
|
||||||
@ -178,9 +179,47 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
Spacing = new Vector2(0, 5),
|
Spacing = new Vector2(0, 5),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
new EditorToolboxGroup("bank (Shift-Q~R)")
|
new EditorToolboxGroup("bank (Shift/Alt-Q~R)")
|
||||||
{
|
{
|
||||||
Child = sampleBankTogglesCollection = new FillFlowContainer
|
Child = new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Spacing = new Vector2(0, 5),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new ExpandableSpriteText
|
||||||
|
{
|
||||||
|
Text = "Normal",
|
||||||
|
AlwaysPresent = true,
|
||||||
|
AllowMultiline = false,
|
||||||
|
RelativePositionAxes = Axes.X,
|
||||||
|
X = 0.25f,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Anchor = Anchor.TopLeft,
|
||||||
|
Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 17),
|
||||||
|
},
|
||||||
|
new ExpandableSpriteText
|
||||||
|
{
|
||||||
|
Text = "Addition",
|
||||||
|
AlwaysPresent = true,
|
||||||
|
AllowMultiline = false,
|
||||||
|
RelativePositionAxes = Axes.X,
|
||||||
|
X = 0.75f,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Anchor = Anchor.TopLeft,
|
||||||
|
Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 17),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sampleBankTogglesCollection = new FillFlowContainer
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
@ -192,6 +231,8 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
new Container
|
new Container
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopRight,
|
Anchor = Anchor.TopRight,
|
||||||
@ -231,7 +272,7 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
TernaryStates = CreateTernaryButtons().ToArray();
|
TernaryStates = CreateTernaryButtons().ToArray();
|
||||||
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.Zip(BlueprintContainer.SampleAdditionBankTernaryStates).Select(b => new SampleBankTernaryButton(b.First, b.Second)));
|
||||||
|
|
||||||
SetSelectTool();
|
SetSelectTool();
|
||||||
|
|
||||||
@ -362,7 +403,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 (checkToolboxMappingFromKey(e.Key, out int leftIndex))
|
if (checkToolboxMappingFromKey(e.Key, out int leftIndex))
|
||||||
@ -379,16 +420,28 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
|
|
||||||
if (checkToggleMappingFromKey(e.Key, out int rightIndex))
|
if (checkToggleMappingFromKey(e.Key, out int rightIndex))
|
||||||
{
|
{
|
||||||
var item = e.ShiftPressed
|
if (e.ShiftPressed || e.AltPressed)
|
||||||
? sampleBankTogglesCollection.ElementAtOrDefault(rightIndex)
|
{
|
||||||
: togglesCollection.ElementAtOrDefault(rightIndex);
|
if (sampleBankTogglesCollection.ElementAtOrDefault(rightIndex) is SampleBankTernaryButton sampleBankTernaryButton)
|
||||||
|
{
|
||||||
|
if (e.ShiftPressed)
|
||||||
|
sampleBankTernaryButton.NormalButton.Toggle();
|
||||||
|
|
||||||
if (item is DrawableTernaryButton button)
|
if (e.AltPressed)
|
||||||
|
sampleBankTernaryButton.AdditionsButton.Toggle();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (togglesCollection.ElementAtOrDefault(rightIndex) is DrawableTernaryButton button)
|
||||||
{
|
{
|
||||||
button.Button.Toggle();
|
button.Button.Toggle();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return base.OnKeyDown(e);
|
return base.OnKeyDown(e);
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,11 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool AutomaticBankAssignment { get; set; }
|
public bool AutomaticBankAssignment { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the sample addition bank should be taken from the previous hit objects.
|
||||||
|
/// </summary>
|
||||||
|
public bool AutomaticAdditionBankAssignment { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="HitObject"/> that is being placed.
|
/// The <see cref="HitObject"/> that is being placed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -73,7 +78,7 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the time and position of this <see cref="HitObjectPlacementBlueprint"/> based on the provided snap information.
|
/// Updates the time and position of this <see cref="PlacementBlueprint"/> based on the provided snap information.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="result">The snap result information.</param>
|
/// <param name="result">The snap result information.</param>
|
||||||
public override void UpdateTimeAndPosition(SnapResult result)
|
public override void UpdateTimeAndPosition(SnapResult result)
|
||||||
@ -87,26 +92,26 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
}
|
}
|
||||||
|
|
||||||
var lastHitObject = getPreviousHitObject();
|
var lastHitObject = getPreviousHitObject();
|
||||||
|
|
||||||
if (AutomaticBankAssignment)
|
|
||||||
{
|
|
||||||
// Create samples based on the sample settings of the previous hit object
|
|
||||||
if (lastHitObject != null)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < HitObject.Samples.Count; i++)
|
|
||||||
HitObject.Samples[i] = lastHitObject.CreateHitSampleInfo(HitObject.Samples[i].Name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var lastHitNormal = lastHitObject?.Samples?.FirstOrDefault(o => o.Name == HitSampleInfo.HIT_NORMAL);
|
var lastHitNormal = lastHitObject?.Samples?.FirstOrDefault(o => o.Name == HitSampleInfo.HIT_NORMAL);
|
||||||
|
|
||||||
|
if (AutomaticAdditionBankAssignment)
|
||||||
|
{
|
||||||
|
// Inherit the addition bank from the previous hit object
|
||||||
|
// If there is no previous addition, inherit from the normal sample
|
||||||
|
var lastAddition = lastHitObject?.Samples?.FirstOrDefault(o => o.Name != HitSampleInfo.HIT_NORMAL) ?? lastHitNormal;
|
||||||
|
|
||||||
|
if (lastAddition != null)
|
||||||
|
HitObject.Samples = HitObject.Samples.Select(s => s.Name != HitSampleInfo.HIT_NORMAL ? s.With(newBank: lastAddition.Bank) : s).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
if (lastHitNormal != null)
|
if (lastHitNormal != null)
|
||||||
{
|
{
|
||||||
// Only inherit the volume from the previous hit object
|
if (AutomaticBankAssignment)
|
||||||
for (int i = 0; i < HitObject.Samples.Count; i++)
|
// Inherit the bank from the previous hit object
|
||||||
HitObject.Samples[i] = HitObject.Samples[i].With(newVolume: lastHitNormal.Volume);
|
HitObject.Samples = HitObject.Samples.Select(s => s.Name == HitSampleInfo.HIT_NORMAL ? s.With(newBank: lastHitNormal.Bank) : s).ToList();
|
||||||
}
|
|
||||||
|
// Inherit the volume from the previous hit object
|
||||||
|
HitObject.Samples = HitObject.Samples.Select(s => s.With(newVolume: lastHitNormal.Volume)).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HitObject is IHasRepeats hasRepeats)
|
if (HitObject is IHasRepeats hasRepeats)
|
||||||
|
@ -21,7 +21,7 @@ namespace osu.Game.Screens.Edit.Components.TernaryButtons
|
|||||||
private Color4 selectedBackgroundColour;
|
private Color4 selectedBackgroundColour;
|
||||||
private Color4 selectedIconColour;
|
private Color4 selectedIconColour;
|
||||||
|
|
||||||
private Drawable icon = null!;
|
protected Drawable Icon { get; private set; } = null!;
|
||||||
|
|
||||||
public readonly TernaryButton Button;
|
public readonly TernaryButton Button;
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ namespace osu.Game.Screens.Edit.Components.TernaryButtons
|
|||||||
defaultIconColour = defaultBackgroundColour.Darken(0.5f);
|
defaultIconColour = defaultBackgroundColour.Darken(0.5f);
|
||||||
selectedIconColour = selectedBackgroundColour.Lighten(0.5f);
|
selectedIconColour = selectedBackgroundColour.Lighten(0.5f);
|
||||||
|
|
||||||
Add(icon = (Button.CreateIcon?.Invoke() ?? new Circle()).With(b =>
|
Add(Icon = (Button.CreateIcon?.Invoke() ?? new Circle()).With(b =>
|
||||||
{
|
{
|
||||||
b.Blending = BlendingParameters.Additive;
|
b.Blending = BlendingParameters.Additive;
|
||||||
b.Anchor = Anchor.CentreLeft;
|
b.Anchor = Anchor.CentreLeft;
|
||||||
@ -75,17 +75,17 @@ namespace osu.Game.Screens.Edit.Components.TernaryButtons
|
|||||||
switch (Button.Bindable.Value)
|
switch (Button.Bindable.Value)
|
||||||
{
|
{
|
||||||
case TernaryState.Indeterminate:
|
case TernaryState.Indeterminate:
|
||||||
icon.Colour = selectedIconColour.Darken(0.5f);
|
Icon.Colour = selectedIconColour.Darken(0.5f);
|
||||||
BackgroundColour = selectedBackgroundColour.Darken(0.5f);
|
BackgroundColour = selectedBackgroundColour.Darken(0.5f);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TernaryState.False:
|
case TernaryState.False:
|
||||||
icon.Colour = defaultIconColour;
|
Icon.Colour = defaultIconColour;
|
||||||
BackgroundColour = defaultBackgroundColour;
|
BackgroundColour = defaultBackgroundColour;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TernaryState.True:
|
case TernaryState.True:
|
||||||
icon.Colour = selectedIconColour;
|
Icon.Colour = selectedIconColour;
|
||||||
BackgroundColour = selectedBackgroundColour;
|
BackgroundColour = selectedBackgroundColour;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,78 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Game.Rulesets.Edit;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Edit.Components.TernaryButtons
|
||||||
|
{
|
||||||
|
public partial class SampleBankTernaryButton : CompositeDrawable
|
||||||
|
{
|
||||||
|
public readonly TernaryButton NormalButton;
|
||||||
|
public readonly TernaryButton AdditionsButton;
|
||||||
|
|
||||||
|
public SampleBankTernaryButton(TernaryButton normalButton, TernaryButton additionsButton)
|
||||||
|
{
|
||||||
|
NormalButton = normalButton;
|
||||||
|
AdditionsButton = additionsButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
AutoSizeAxes = Axes.Y;
|
||||||
|
Masking = true;
|
||||||
|
CornerRadius = 5;
|
||||||
|
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Width = 0.5f,
|
||||||
|
Padding = new MarginPadding { Right = 1 },
|
||||||
|
Child = new InlineDrawableTernaryButton(NormalButton),
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopRight,
|
||||||
|
Origin = Anchor.TopRight,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Width = 0.5f,
|
||||||
|
Padding = new MarginPadding { Left = 1 },
|
||||||
|
Child = new InlineDrawableTernaryButton(AdditionsButton),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private partial class InlineDrawableTernaryButton : DrawableTernaryButton
|
||||||
|
{
|
||||||
|
public InlineDrawableTernaryButton(TernaryButton button)
|
||||||
|
: base(button)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
Content.Masking = false;
|
||||||
|
Content.CornerRadius = 0;
|
||||||
|
Icon.X = 4.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override SpriteText CreateText() => new ExpandableSpriteText
|
||||||
|
{
|
||||||
|
Depth = -1,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
X = 31f
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -65,7 +65,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)
|
||||||
{
|
{
|
||||||
@ -91,6 +92,9 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
|
|
||||||
foreach (var kvp in SelectionHandler.SelectionBankStates)
|
foreach (var kvp in SelectionHandler.SelectionBankStates)
|
||||||
kvp.Value.BindValueChanged(_ => updatePlacementSamples());
|
kvp.Value.BindValueChanged(_ => updatePlacementSamples());
|
||||||
|
|
||||||
|
foreach (var kvp in SelectionHandler.SelectionAdditionBankStates)
|
||||||
|
kvp.Value.BindValueChanged(_ => updatePlacementSamples());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void TransferBlueprintFor(HitObject hitObject, DrawableHitObject drawableObject)
|
protected override void TransferBlueprintFor(HitObject hitObject, DrawableHitObject drawableObject)
|
||||||
@ -179,6 +183,9 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
|
|
||||||
foreach (var kvp in SelectionHandler.SelectionBankStates)
|
foreach (var kvp in SelectionHandler.SelectionBankStates)
|
||||||
bankChanged(kvp.Key, kvp.Value.Value);
|
bankChanged(kvp.Key, kvp.Value.Value);
|
||||||
|
|
||||||
|
foreach (var kvp in SelectionHandler.SelectionAdditionBankStates)
|
||||||
|
additionBankChanged(kvp.Key, kvp.Value.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sampleChanged(string sampleName, TernaryState state)
|
private void sampleChanged(string sampleName, TernaryState state)
|
||||||
@ -210,7 +217,17 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
if (bankName == EditorSelectionHandler.HIT_BANK_AUTO)
|
if (bankName == EditorSelectionHandler.HIT_BANK_AUTO)
|
||||||
CurrentHitObjectPlacement.AutomaticBankAssignment = state == TernaryState.True;
|
CurrentHitObjectPlacement.AutomaticBankAssignment = state == TernaryState.True;
|
||||||
else if (state == TernaryState.True)
|
else if (state == TernaryState.True)
|
||||||
CurrentHitObjectPlacement.HitObject.Samples = CurrentHitObjectPlacement.HitObject.Samples.Select(s => s.With(newBank: bankName)).ToList();
|
CurrentHitObjectPlacement.HitObject.Samples = CurrentHitObjectPlacement.HitObject.Samples.Select(s => s.Name == HitSampleInfo.HIT_NORMAL ? s.With(newBank: bankName) : s).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void additionBankChanged(string bankName, TernaryState state)
|
||||||
|
{
|
||||||
|
if (CurrentHitObjectPlacement == null) return;
|
||||||
|
|
||||||
|
if (bankName == EditorSelectionHandler.HIT_BANK_AUTO)
|
||||||
|
CurrentHitObjectPlacement.AutomaticAdditionBankAssignment = state == TernaryState.True;
|
||||||
|
else if (state == TernaryState.True)
|
||||||
|
CurrentHitObjectPlacement.HitObject.Samples = CurrentHitObjectPlacement.HitObject.Samples.Select(s => s.Name != HitSampleInfo.HIT_NORMAL ? s.With(newBank: bankName) : s).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly Bindable<TernaryState> NewCombo = new Bindable<TernaryState> { Description = "New Combo" };
|
public readonly Bindable<TernaryState> NewCombo = new Bindable<TernaryState> { Description = "New Combo" };
|
||||||
@ -222,6 +239,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>
|
||||||
@ -234,36 +253,21 @@ 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Drawable getIconForBank(string sampleName)
|
private Drawable getIconForBank(string sampleName)
|
||||||
{
|
{
|
||||||
return new Container
|
return new OsuSpriteText
|
||||||
{
|
{
|
||||||
Size = new Vector2(30, 20),
|
Anchor = Anchor.Centre,
|
||||||
Children = new Drawable[]
|
Origin = Anchor.Centre,
|
||||||
{
|
|
||||||
new SpriteIcon
|
|
||||||
{
|
|
||||||
Size = new Vector2(8),
|
|
||||||
Anchor = Anchor.CentreLeft,
|
|
||||||
Origin = Anchor.CentreLeft,
|
|
||||||
Icon = FontAwesome.Solid.VolumeOff
|
|
||||||
},
|
|
||||||
new OsuSpriteText
|
|
||||||
{
|
|
||||||
Anchor = Anchor.CentreLeft,
|
|
||||||
Origin = Anchor.CentreLeft,
|
|
||||||
X = 10,
|
|
||||||
Y = -1,
|
Y = -1,
|
||||||
Font = OsuFont.Default.With(weight: FontWeight.Bold, size: 20),
|
Font = OsuFont.Default.With(weight: FontWeight.Bold, size: 20),
|
||||||
Text = $"{char.ToUpperInvariant(sampleName.First())}"
|
Text = $"{char.ToUpperInvariant(sampleName.First())}"
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +59,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>
|
||||||
@ -91,7 +96,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,8 +133,84 @@ 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;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Auto should never apply when there is a selection made.
|
||||||
|
if (bankName == HIT_BANK_AUTO)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Completely empty selections should be allowed in the case that none of the selected objects have any addition samples.
|
||||||
|
// This is also required to stop a bindable feedback loop when a HitObject has zero addition samples (and LINQ `All` below becomes true).
|
||||||
|
if (SelectedItems.SelectMany(enumerateAllSamples).All(h => h.All(o => o.Name == HitSampleInfo.HIT_NORMAL)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Never remove a sample bank.
|
||||||
|
// These are basically radio buttons, not toggles.
|
||||||
|
if (SelectedItems.SelectMany(enumerateAllSamples).All(h => h.Where(o => o.Name != HitSampleInfo.HIT_NORMAL).All(s => s.Bank == bankName)))
|
||||||
|
bindable.Value = TernaryState.True;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 addition bank.
|
||||||
|
if (SelectedItems.SelectMany(enumerateAllSamples).All(h => h.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)
|
||||||
{
|
{
|
||||||
@ -187,10 +268,16 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<IList<HitSampleInfo>> enumerateAllSamples(HitObject hitObject)
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<IList<HitSampleInfo>> enumerateAllSamples(HitObject hitObject)
|
||||||
{
|
{
|
||||||
yield return hitObject.Samples;
|
yield return hitObject.Samples;
|
||||||
|
|
||||||
@ -200,7 +287,6 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
yield return node;
|
yield return node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -214,12 +300,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;
|
||||||
@ -233,12 +319,51 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
if (hasRelevantBank(h))
|
if (hasRelevantBank(h))
|
||||||
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 (enumerateAllSamples(h).SelectMany(o => o).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);
|
||||||
@ -415,6 +540,12 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
State = { BindTarget = drum },
|
State = { BindTarget = drum },
|
||||||
Hotkey = new Hotkey(new KeyCombination(InputKey.Shift, InputKey.R))
|
Hotkey = new Hotkey(new KeyCombination(InputKey.Shift, InputKey.R))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
yield return new OsuMenuItem("Addition bank")
|
||||||
|
{
|
||||||
|
Items = SelectionAdditionBankStates.Select(kvp =>
|
||||||
|
new TernaryStateToggleMenuItem(kvp.Value.Description) { State = { BindTarget = kvp.Value } }).ToArray()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -438,21 +438,28 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
|
|
||||||
protected override bool OnKeyDown(KeyDownEvent e)
|
protected override bool OnKeyDown(KeyDownEvent e)
|
||||||
{
|
{
|
||||||
if (e.ControlPressed || e.AltPressed || e.SuperPressed || !checkRightToggleFromKey(e.Key, out int rightIndex))
|
if (e.ControlPressed || e.SuperPressed || !checkRightToggleFromKey(e.Key, out int rightIndex))
|
||||||
return base.OnKeyDown(e);
|
return base.OnKeyDown(e);
|
||||||
|
|
||||||
if (e.ShiftPressed)
|
if (e.ShiftPressed || e.AltPressed)
|
||||||
{
|
{
|
||||||
string? newBank = banks.ElementAtOrDefault(rightIndex);
|
string? newBank = banks.ElementAtOrDefault(rightIndex);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(newBank))
|
if (string.IsNullOrEmpty(newBank))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (e.ShiftPressed)
|
||||||
|
{
|
||||||
setBank(newBank);
|
setBank(newBank);
|
||||||
updatePrimaryBankState();
|
updatePrimaryBankState();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.AltPressed)
|
||||||
|
{
|
||||||
setAdditionBank(newBank);
|
setAdditionBank(newBank);
|
||||||
updateAdditionBankState();
|
updateAdditionBankState();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var item = togglesCollection.ElementAtOrDefault(rightIndex);
|
var item = togglesCollection.ElementAtOrDefault(rightIndex);
|
||||||
|
Loading…
Reference in New Issue
Block a user