mirror of
https://github.com/SK-la/Ez2Lazer.git
synced 2026-03-13 11:20:28 +00:00
[同步官方更新]
This commit is contained in:
@@ -21,7 +21,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"ppy.localisationanalyser.tools": {
|
"ppy.localisationanalyser.tools": {
|
||||||
"version": "2024.802.0",
|
"version": "2025.1208.0",
|
||||||
"commands": [
|
"commands": [
|
||||||
"localisation"
|
"localisation"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ using System.Linq;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Humanizer;
|
using Humanizer;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Input;
|
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Audio;
|
using osu.Game.Audio;
|
||||||
@@ -196,11 +195,6 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
clickSamplePiece(1);
|
clickSamplePiece(1);
|
||||||
samplePopoverHasSingleBank(HitSampleInfo.BANK_SOFT);
|
samplePopoverHasSingleBank(HitSampleInfo.BANK_SOFT);
|
||||||
|
|
||||||
setBankViaPopover(string.Empty);
|
|
||||||
hitObjectHasSampleBank(0, HitSampleInfo.BANK_SOFT);
|
|
||||||
hitObjectHasSampleBank(1, HitSampleInfo.BANK_SOFT);
|
|
||||||
samplePopoverHasSingleBank(HitSampleInfo.BANK_SOFT);
|
|
||||||
|
|
||||||
setBankViaPopover(HitSampleInfo.BANK_DRUM);
|
setBankViaPopover(HitSampleInfo.BANK_DRUM);
|
||||||
hitObjectHasSampleBank(0, HitSampleInfo.BANK_DRUM);
|
hitObjectHasSampleBank(0, HitSampleInfo.BANK_DRUM);
|
||||||
hitObjectHasSampleBank(1, HitSampleInfo.BANK_DRUM);
|
hitObjectHasSampleBank(1, HitSampleInfo.BANK_DRUM);
|
||||||
@@ -219,11 +213,6 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
clickSamplePiece(1);
|
clickSamplePiece(1);
|
||||||
samplePopoverHasIndeterminateBank();
|
samplePopoverHasIndeterminateBank();
|
||||||
|
|
||||||
setBankViaPopover(string.Empty);
|
|
||||||
hitObjectHasSampleBank(0, HitSampleInfo.BANK_NORMAL);
|
|
||||||
hitObjectHasSampleBank(1, HitSampleInfo.BANK_SOFT);
|
|
||||||
samplePopoverHasIndeterminateBank();
|
|
||||||
|
|
||||||
setBankViaPopover(HitSampleInfo.BANK_NORMAL);
|
setBankViaPopover(HitSampleInfo.BANK_NORMAL);
|
||||||
hitObjectHasSampleBank(0, HitSampleInfo.BANK_NORMAL);
|
hitObjectHasSampleBank(0, HitSampleInfo.BANK_NORMAL);
|
||||||
hitObjectHasSampleBank(1, HitSampleInfo.BANK_NORMAL);
|
hitObjectHasSampleBank(1, HitSampleInfo.BANK_NORMAL);
|
||||||
@@ -878,17 +867,17 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
private void samplePopoverHasSingleBank(string bank) => AddUntilStep($"sample popover has bank {bank}", () =>
|
private void samplePopoverHasSingleBank(string bank) => AddUntilStep($"sample popover has bank {bank}", () =>
|
||||||
{
|
{
|
||||||
var popover = this.ChildrenOfType<SamplePointPiece.SampleEditPopover>().SingleOrDefault();
|
var popover = this.ChildrenOfType<SamplePointPiece.SampleEditPopover>().SingleOrDefault();
|
||||||
var textBox = popover?.ChildrenOfType<OsuTextBox>().First();
|
var dropdown = popover?.ChildrenOfType<LabelledDropdown<string>>().First();
|
||||||
|
|
||||||
return textBox?.Current.Value == bank && string.IsNullOrEmpty(textBox.PlaceholderText.ToString());
|
return dropdown?.Current.Value == bank;
|
||||||
});
|
});
|
||||||
|
|
||||||
private void samplePopoverHasIndeterminateBank() => AddUntilStep("sample popover has indeterminate bank", () =>
|
private void samplePopoverHasIndeterminateBank() => AddUntilStep("sample popover has indeterminate bank", () =>
|
||||||
{
|
{
|
||||||
var popover = this.ChildrenOfType<SamplePointPiece.SampleEditPopover>().SingleOrDefault();
|
var popover = this.ChildrenOfType<SamplePointPiece.SampleEditPopover>().SingleOrDefault();
|
||||||
var textBox = popover?.ChildrenOfType<OsuTextBox>().First();
|
var dropdown = popover?.ChildrenOfType<LabelledDropdown<string>>().First();
|
||||||
|
|
||||||
return textBox != null && string.IsNullOrEmpty(textBox.Current.Value) && !string.IsNullOrEmpty(textBox.PlaceholderText.ToString());
|
return dropdown?.Current.Value == "(multiple)";
|
||||||
});
|
});
|
||||||
|
|
||||||
private void dismissPopover()
|
private void dismissPopover()
|
||||||
@@ -920,23 +909,15 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
private void setBankViaPopover(string bank) => AddStep($"set bank {bank} via popover", () =>
|
private void setBankViaPopover(string bank) => AddStep($"set bank {bank} via popover", () =>
|
||||||
{
|
{
|
||||||
var popover = this.ChildrenOfType<SamplePointPiece.SampleEditPopover>().Single();
|
var popover = this.ChildrenOfType<SamplePointPiece.SampleEditPopover>().Single();
|
||||||
var textBox = popover.ChildrenOfType<LabelledTextBox>().First();
|
var textBox = popover.ChildrenOfType<LabelledDropdown<string>>().First();
|
||||||
textBox.Current.Value = bank;
|
textBox.Current.Value = bank;
|
||||||
// force a commit via keyboard.
|
|
||||||
// this is needed when testing attempting to set empty bank - which should revert to the previous value, but only on commit.
|
|
||||||
((IFocusManager)InputManager).ChangeFocus(textBox);
|
|
||||||
InputManager.Key(Key.Enter);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
private void setAdditionBankViaPopover(string bank) => AddStep($"set addition bank {bank} via popover", () =>
|
private void setAdditionBankViaPopover(string bank) => AddStep($"set addition bank {bank} via popover", () =>
|
||||||
{
|
{
|
||||||
var popover = this.ChildrenOfType<SamplePointPiece.SampleEditPopover>().Single();
|
var popover = this.ChildrenOfType<SamplePointPiece.SampleEditPopover>().Single();
|
||||||
var textBox = popover.ChildrenOfType<LabelledTextBox>().ToArray()[1];
|
var textBox = popover.ChildrenOfType<LabelledDropdown<string>>().ToArray()[1];
|
||||||
textBox.Current.Value = bank;
|
textBox.Current.Value = bank;
|
||||||
// force a commit via keyboard.
|
|
||||||
// this is needed when testing attempting to set empty bank - which should revert to the previous value, but only on commit.
|
|
||||||
((IFocusManager)InputManager).ChangeFocus(textBox);
|
|
||||||
InputManager.Key(Key.Enter);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
private void toggleAdditionViaPopover(int index) => AddStep($"toggle addition {index} via popover", () =>
|
private void toggleAdditionViaPopover(int index) => AddStep($"toggle addition {index} via popover", () =>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
public void TestLabelledDropdown()
|
public void TestLabelledDropdown()
|
||||||
=> AddStep(@"create dropdown", () => Child = new LabelledDropdown<string>
|
=> AddStep(@"create dropdown", () => Child = new LabelledDropdown<string>(true)
|
||||||
{
|
{
|
||||||
Label = @"Countdown speed",
|
Label = @"Countdown speed",
|
||||||
Items = new[]
|
Items = new[]
|
||||||
@@ -25,7 +25,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestLabelledEnumDropdown()
|
public void TestLabelledEnumDropdown()
|
||||||
=> AddStep(@"create dropdown", () => Child = new LabelledEnumDropdown<BeatmapOnlineStatus>
|
=> AddStep(@"create dropdown", () => Child = new LabelledEnumDropdown<BeatmapOnlineStatus>(true)
|
||||||
{
|
{
|
||||||
Label = @"Beatmap status",
|
Label = @"Beatmap status",
|
||||||
Description = @"This is a description"
|
Description = @"This is a description"
|
||||||
|
|||||||
@@ -116,12 +116,13 @@ namespace osu.Game.Tournament.Screens.Setup
|
|||||||
Failing = api.IsLoggedIn != true,
|
Failing = api.IsLoggedIn != true,
|
||||||
Description = "In order to access the API and display metadata, signing in is required."
|
Description = "In order to access the API and display metadata, signing in is required."
|
||||||
},
|
},
|
||||||
new LabelledDropdown<RulesetInfo?>
|
new LabelledDropdown<RulesetInfo?>(padded: true)
|
||||||
{
|
{
|
||||||
Label = "Ruleset",
|
Label = "Ruleset",
|
||||||
Description = "Decides what stats are displayed and which ranks are retrieved for players. This requires a restart to reload data for an existing bracket.",
|
Description = "Decides what stats are displayed and which ranks are retrieved for players. This requires a restart to reload data for an existing bracket.",
|
||||||
Items = rulesets.AvailableRulesets,
|
Items = rulesets.AvailableRulesets,
|
||||||
Current = LadderInfo.Ruleset,
|
Current = LadderInfo.Ruleset,
|
||||||
|
DropdownWidth = 0.5f,
|
||||||
},
|
},
|
||||||
new TournamentSwitcher
|
new TournamentSwitcher
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
@@ -72,7 +71,9 @@ namespace osu.Game.Collections
|
|||||||
var createdItem = flow.Children.SingleOrDefault(item => item.Model.Value.ID == lastCreated);
|
var createdItem = flow.Children.SingleOrDefault(item => item.Model.Value.ID == lastCreated);
|
||||||
|
|
||||||
if (createdItem != null)
|
if (createdItem != null)
|
||||||
scroll.ScrollTo(createdItem);
|
{
|
||||||
|
ScheduleAfterChildren(() => scroll.ScrollIntoView(createdItem));
|
||||||
|
}
|
||||||
|
|
||||||
lastCreated = null;
|
lastCreated = null;
|
||||||
}
|
}
|
||||||
@@ -104,13 +105,8 @@ namespace osu.Game.Collections
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override OsuRearrangeableListItem<Live<BeatmapCollection>> CreateOsuDrawable(Live<BeatmapCollection> item)
|
protected override OsuRearrangeableListItem<Live<BeatmapCollection>> CreateOsuDrawable(Live<BeatmapCollection> item) =>
|
||||||
{
|
new DrawableCollectionListItem(item, true);
|
||||||
if (item.ID == scroll.PlaceholderItem.Model.ID)
|
|
||||||
return scroll.ReplacePlaceholder();
|
|
||||||
|
|
||||||
return new DrawableCollectionListItem(item, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
@@ -122,91 +118,22 @@ namespace osu.Game.Collections
|
|||||||
/// The scroll container for this <see cref="DrawableCollectionList"/>.
|
/// The scroll container for this <see cref="DrawableCollectionList"/>.
|
||||||
/// Contains the main flow of <see cref="DrawableCollectionListItem"/> and attaches a placeholder item to the end of the list.
|
/// Contains the main flow of <see cref="DrawableCollectionListItem"/> and attaches a placeholder item to the end of the list.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
|
||||||
/// Use <see cref="ReplacePlaceholder"/> to transfer the placeholder into the main list.
|
|
||||||
/// </remarks>
|
|
||||||
private partial class Scroll : OsuScrollContainer
|
private partial class Scroll : OsuScrollContainer
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// The currently-displayed placeholder item.
|
|
||||||
/// </summary>
|
|
||||||
public DrawableCollectionListItem PlaceholderItem { get; private set; } = null!;
|
|
||||||
|
|
||||||
protected override Container<Drawable> Content => content;
|
protected override Container<Drawable> Content => content;
|
||||||
private readonly Container content;
|
private readonly FillFlowContainer content;
|
||||||
|
|
||||||
private readonly Container<DrawableCollectionListItem> placeholderContainer;
|
|
||||||
|
|
||||||
public Scroll()
|
public Scroll()
|
||||||
{
|
{
|
||||||
ScrollbarOverlapsContent = false;
|
ScrollbarOverlapsContent = false;
|
||||||
|
|
||||||
base.Content.Add(new FillFlowContainer
|
base.Content.Add(content = new FillFlowContainer
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
LayoutDuration = 200,
|
LayoutDuration = 200,
|
||||||
LayoutEasing = Easing.OutQuint,
|
LayoutEasing = Easing.OutQuint,
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
content = new Container { RelativeSizeAxes = Axes.X },
|
|
||||||
placeholderContainer = new Container<DrawableCollectionListItem>
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
AutoSizeAxes = Axes.Y
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ReplacePlaceholder();
|
|
||||||
Debug.Assert(PlaceholderItem != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Update()
|
|
||||||
{
|
|
||||||
base.Update();
|
|
||||||
|
|
||||||
// AutoSizeAxes cannot be used as the height should represent the post-layout-transform height at all times, so that the placeholder doesn't bounce around.
|
|
||||||
content.Height = ((Flow)Child).Children.Sum(c => c.IsPresent ? c.DrawHeight + 5 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Replaces the current <see cref="PlaceholderItem"/> with a new one, and returns the previous.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The current <see cref="PlaceholderItem"/>.</returns>
|
|
||||||
public DrawableCollectionListItem ReplacePlaceholder()
|
|
||||||
{
|
|
||||||
var previous = PlaceholderItem;
|
|
||||||
|
|
||||||
placeholderContainer.Clear(false);
|
|
||||||
placeholderContainer.Add(PlaceholderItem = new NewCollectionEntryItem());
|
|
||||||
|
|
||||||
return previous;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private partial class NewCollectionEntryItem : DrawableCollectionListItem
|
|
||||||
{
|
|
||||||
[Resolved]
|
|
||||||
private RealmAccess realm { get; set; } = null!;
|
|
||||||
|
|
||||||
public NewCollectionEntryItem()
|
|
||||||
: base(new BeatmapCollection().ToLiveUnmanaged(), false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
|
|
||||||
TextBox.OnCommit += (sender, newText) =>
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(TextBox.Text))
|
|
||||||
return;
|
|
||||||
|
|
||||||
realm.Write(r => r.Add(new BeatmapCollection(TextBox.Text)));
|
|
||||||
TextBox.Text = string.Empty;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,11 @@ namespace osu.Game.Collections
|
|||||||
ShowDragHandle.Value = false;
|
ShowDragHandle.Value = false;
|
||||||
|
|
||||||
Masking = true;
|
Masking = true;
|
||||||
CornerRadius = item_height / 2;
|
|
||||||
|
// This doesn't match the latest design spec (should be 5) but is an in-between that feels right to the eye
|
||||||
|
// until we move everything over to Form controls.
|
||||||
|
CornerRadius = 10;
|
||||||
|
CornerExponent = 2.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Drawable CreateContent() => content = new ItemContent(Model);
|
protected override Drawable CreateContent() => content = new ItemContent(Model);
|
||||||
@@ -135,7 +139,8 @@ namespace osu.Game.Collections
|
|||||||
{
|
{
|
||||||
this.collection = collection;
|
this.collection = collection;
|
||||||
|
|
||||||
CornerRadius = item_height / 2;
|
CornerRadius = 10;
|
||||||
|
CornerExponent = 2.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Game.Database;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
@@ -102,12 +103,13 @@ namespace osu.Game.Collections
|
|||||||
new Container
|
new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Masking = true,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new Box
|
new Box
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Colour = colours.GreySeaFoamDarker
|
Colour = colours.GreySeaFoamDarker,
|
||||||
},
|
},
|
||||||
new Container
|
new Container
|
||||||
{
|
{
|
||||||
@@ -115,23 +117,30 @@ namespace osu.Game.Collections
|
|||||||
Padding = new MarginPadding(10),
|
Padding = new MarginPadding(10),
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
|
list = new DrawableCollectionList
|
||||||
|
{
|
||||||
|
Padding = new MarginPadding { Vertical = 50 },
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
},
|
||||||
searchTextBox = new BasicSearchTextBox
|
searchTextBox = new BasicSearchTextBox
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Y = 10,
|
|
||||||
Height = 40,
|
Height = 40,
|
||||||
ReleaseFocusOnCommit = false,
|
ReleaseFocusOnCommit = false,
|
||||||
HoldFocus = true,
|
HoldFocus = true,
|
||||||
PlaceholderText = HomeStrings.SearchPlaceholder,
|
PlaceholderText = HomeStrings.SearchPlaceholder,
|
||||||
},
|
},
|
||||||
list = new DrawableCollectionList
|
new Container
|
||||||
{
|
{
|
||||||
Padding = new MarginPadding
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Anchor = Anchor.BottomLeft,
|
||||||
|
Origin = Anchor.BottomLeft,
|
||||||
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
Top = 60,
|
new NewCollectionEntryItem()
|
||||||
},
|
}
|
||||||
RelativeSizeAxes = Axes.Both,
|
},
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -184,5 +193,30 @@ namespace osu.Game.Collections
|
|||||||
// Ensure that textboxes commit
|
// Ensure that textboxes commit
|
||||||
GetContainingFocusManager()?.TriggerFocusContention(this);
|
GetContainingFocusManager()?.TriggerFocusContention(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private partial class NewCollectionEntryItem : DrawableCollectionListItem
|
||||||
|
{
|
||||||
|
[Resolved]
|
||||||
|
private RealmAccess realm { get; set; } = null!;
|
||||||
|
|
||||||
|
public NewCollectionEntryItem()
|
||||||
|
: base(new BeatmapCollection().ToLiveUnmanaged(), false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
TextBox.OnCommit += (_, _) =>
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(TextBox.Text))
|
||||||
|
return;
|
||||||
|
|
||||||
|
realm.Write(r => r.Add(new BeatmapCollection(TextBox.Text)));
|
||||||
|
TextBox.Text = string.Empty;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
|||||||
{
|
{
|
||||||
public partial class LabelledDropdown<TItem> : LabelledComponent<OsuDropdown<TItem>, TItem>
|
public partial class LabelledDropdown<TItem> : LabelledComponent<OsuDropdown<TItem>, TItem>
|
||||||
{
|
{
|
||||||
public LabelledDropdown()
|
public LabelledDropdown(bool padded)
|
||||||
: base(true)
|
: base(padded)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,12 +20,22 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
|||||||
set => Component.Items = value;
|
set => Component.Items = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float DropdownWidth
|
||||||
|
{
|
||||||
|
get => Component.Width;
|
||||||
|
set => Component.Width = value;
|
||||||
|
}
|
||||||
|
|
||||||
protected sealed override OsuDropdown<TItem> CreateComponent() => CreateDropdown().With(d =>
|
protected sealed override OsuDropdown<TItem> CreateComponent() => CreateDropdown().With(d =>
|
||||||
{
|
{
|
||||||
d.RelativeSizeAxes = Axes.X;
|
d.RelativeSizeAxes = Axes.X;
|
||||||
d.Width = 0.5f;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
protected virtual OsuDropdown<TItem> CreateDropdown() => new OsuDropdown<TItem>();
|
protected virtual OsuDropdown<TItem> CreateDropdown() => new Dropdown();
|
||||||
|
|
||||||
|
private partial class Dropdown : OsuDropdown<TItem>
|
||||||
|
{
|
||||||
|
protected override DropdownMenu CreateMenu() => base.CreateMenu().With(menu => menu.MaxHeight = 200);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,11 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
|||||||
public partial class LabelledEnumDropdown<TEnum> : LabelledDropdown<TEnum>
|
public partial class LabelledEnumDropdown<TEnum> : LabelledDropdown<TEnum>
|
||||||
where TEnum : struct, Enum
|
where TEnum : struct, Enum
|
||||||
{
|
{
|
||||||
|
public LabelledEnumDropdown(bool padded)
|
||||||
|
: base(padded)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
protected override OsuDropdown<TEnum> CreateDropdown() => new OsuEnumDropdown<TEnum>();
|
protected override OsuDropdown<TEnum> CreateDropdown() => new OsuEnumDropdown<TEnum>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,6 @@ using osu.Game.Resources;
|
|||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Screens;
|
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osu.Game.Utils;
|
using osu.Game.Utils;
|
||||||
using RuntimeInfo = osu.Framework.RuntimeInfo;
|
using RuntimeInfo = osu.Framework.RuntimeInfo;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace osu.Game.Overlays
|
|||||||
Origin = Anchor.BottomCentre,
|
Origin = Anchor.BottomCentre,
|
||||||
Font = OsuFont.Numeric.With(weight: FontWeight.Bold, size: 12),
|
Font = OsuFont.Numeric.With(weight: FontWeight.Bold, size: 12),
|
||||||
Colour = colours.YellowDark,
|
Colour = colours.YellowDark,
|
||||||
Text = @"DEVELOPER BUILD For Ez2Lazer",
|
Text = @"DEVELOPER BUILD",
|
||||||
},
|
},
|
||||||
new Sprite
|
new Sprite
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ using osu.Game.Screens.Edit.Components.Menus;
|
|||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osu.Framework.Graphics.Cursor;
|
using osu.Framework.Graphics.Cursor;
|
||||||
using osu.Game.Input.Bindings;
|
using osu.Game.Input.Bindings;
|
||||||
using osu.Game.LAsEzExtensions.Configuration;
|
|
||||||
using osu.Game.LAsEzExtensions.Screens;
|
using osu.Game.LAsEzExtensions.Screens;
|
||||||
using osu.Game.Utils;
|
using osu.Game.Utils;
|
||||||
|
|
||||||
|
|||||||
@@ -129,8 +129,11 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
// Inherit the bank from the previous hit object
|
// Inherit the bank from the previous hit object
|
||||||
HitObject.Samples = HitObject.Samples.Select(s => s.Name == HitSampleInfo.HIT_NORMAL ? s.With(newBank: lastHitNormal.Bank) : s).ToList();
|
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
|
// Inherit the volume and sample set info from the previous hit object
|
||||||
HitObject.Samples = HitObject.Samples.Select(s => s.With(newVolume: lastHitNormal.Volume)).ToList();
|
HitObject.Samples = HitObject.Samples.Select(s => s.With(
|
||||||
|
newVolume: lastHitNormal.Volume,
|
||||||
|
newSuffix: lastHitNormal.Suffix,
|
||||||
|
newUseBeatmapSamples: lastHitNormal.UseBeatmapSamples)).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HitObject is IHasRepeats hasRepeats)
|
if (HitObject is IHasRepeats hasRepeats)
|
||||||
|
|||||||
@@ -49,7 +49,8 @@ namespace osu.Game.Screens.Edit.Components.TernaryButtons
|
|||||||
|
|
||||||
public Drawable Icon { get; private set; } = null!;
|
public Drawable Icon { get; private set; } = null!;
|
||||||
|
|
||||||
public DrawableTernaryButton()
|
public DrawableTernaryButton(HoverSampleSet? hoverSampleSet = HoverSampleSet.Button)
|
||||||
|
: base(hoverSampleSet)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
// 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.Graphics;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Edit.Components.TernaryButtons
|
||||||
|
{
|
||||||
|
public partial class SampleSetTernaryButton : DrawableTernaryButton
|
||||||
|
{
|
||||||
|
public EditorBeatmapSkin.SampleSet SampleSet { get; }
|
||||||
|
|
||||||
|
public SampleSetTernaryButton(EditorBeatmapSkin.SampleSet sampleSet)
|
||||||
|
: base(null)
|
||||||
|
{
|
||||||
|
SampleSet = sampleSet;
|
||||||
|
CreateIcon = () => sampleSet.SampleSetIndex == 0
|
||||||
|
? new SpriteIcon { Icon = OsuIcon.SkinA }
|
||||||
|
: new Container
|
||||||
|
{
|
||||||
|
Child = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Text = sampleSet.SampleSetIndex.ToString(),
|
||||||
|
Font = OsuFont.Style.Body.With(weight: FontWeight.Bold),
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (sampleSet.SampleSetIndex)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
Width = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
RelativeSizeAxes = Axes.None;
|
||||||
|
Width = Height;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
AddRangeInternal(new Drawable[]
|
||||||
|
{
|
||||||
|
new HoverSounds(HoverSampleSet.Button),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,13 +36,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
|
|||||||
|
|
||||||
private double? lastSeekTime;
|
private double? lastSeekTime;
|
||||||
|
|
||||||
protected override bool OnDragStart(DragStartEvent e)
|
protected override bool OnDragStart(DragStartEvent e) => true;
|
||||||
{
|
|
||||||
var localPos = ToLocalSpace(e.ScreenSpaceMousePosition);
|
|
||||||
if (localPos.Y <= DrawHeight / 2) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnDrag(DragEvent e)
|
protected override void OnDrag(DragEvent e)
|
||||||
{
|
{
|
||||||
@@ -58,9 +52,6 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
|
|||||||
|
|
||||||
protected override bool OnMouseDown(MouseDownEvent e)
|
protected override bool OnMouseDown(MouseDownEvent e)
|
||||||
{
|
{
|
||||||
var localPos = ToLocalSpace(e.ScreenSpaceMousePosition);
|
|
||||||
if (localPos.Y <= DrawHeight / 2) return false; // only lower half
|
|
||||||
|
|
||||||
seekToPosition(e.ScreenSpaceMousePosition, instant: true);
|
seekToPosition(e.ScreenSpaceMousePosition, instant: true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,11 @@ using osu.Game.Graphics;
|
|||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Graphics.UserInterfaceV2;
|
using osu.Game.Graphics.UserInterfaceV2;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Screens.Edit.Components.TernaryButtons;
|
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
|
using osu.Game.Screens.Edit.Components.TernaryButtons;
|
||||||
using osu.Game.Screens.Edit.Timing;
|
using osu.Game.Screens.Edit.Timing;
|
||||||
|
using osu.Game.Skinning;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
using osuTK.Input;
|
using osuTK.Input;
|
||||||
@@ -127,7 +128,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
|
|
||||||
private void updateText()
|
private void updateText()
|
||||||
{
|
{
|
||||||
Label.Text = $"{abbreviateBank(GetBankValue(GetSamples()))} {GetVolumeValue(GetSamples())}";
|
Label.Text = $"{abbreviateBank(GetBankValue(GetSamples()))}{GetSuffix(GetSamples())} {GetVolumeValue(GetSamples())}";
|
||||||
|
|
||||||
if (!contracted.Value)
|
if (!contracted.Value)
|
||||||
LabelContainer.ResizeWidthTo(Label.Width, 200, Easing.OutQuint);
|
LabelContainer.ResizeWidthTo(Label.Width, 200, Easing.OutQuint);
|
||||||
@@ -149,6 +150,17 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
return samples.FirstOrDefault(o => o.Name == HitSampleInfo.HIT_NORMAL)?.Bank;
|
return samples.FirstOrDefault(o => o.Name == HitSampleInfo.HIT_NORMAL)?.Bank;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string GetSuffix(IEnumerable<HitSampleInfo> samples)
|
||||||
|
{
|
||||||
|
var suffixes = samples.Select(o => o.Suffix).Distinct().ToList();
|
||||||
|
|
||||||
|
// having multiple values should never happen, but just for safety...
|
||||||
|
if (suffixes.Count != 1 || suffixes.Single() is not string commonSuffix)
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
return $@":{commonSuffix}";
|
||||||
|
}
|
||||||
|
|
||||||
public static string? GetAdditionBankValue(IEnumerable<HitSampleInfo> samples)
|
public static string? GetAdditionBankValue(IEnumerable<HitSampleInfo> samples)
|
||||||
{
|
{
|
||||||
var firstAddition = samples.FirstOrDefault(o => o.Name != HitSampleInfo.HIT_NORMAL);
|
var firstAddition = samples.FirstOrDefault(o => o.Name != HitSampleInfo.HIT_NORMAL);
|
||||||
@@ -176,9 +188,12 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
{
|
{
|
||||||
private readonly HitObject hitObject;
|
private readonly HitObject hitObject;
|
||||||
|
|
||||||
private LabelledTextBox bank = null!;
|
private LabelledDropdown<string> bank = null!;
|
||||||
private LabelledTextBox additionBank = null!;
|
private LabelledDropdown<string> additionBank = null!;
|
||||||
|
private FillFlowContainer<SampleSetTernaryButton>? sampleSetsFlow;
|
||||||
|
private LabelledDropdown<EditorBeatmapSkin.SampleSet>? sampleSetDropdown;
|
||||||
private IndeterminateSliderWithTextBoxInput<int> volume = null!;
|
private IndeterminateSliderWithTextBoxInput<int> volume = null!;
|
||||||
|
private SkinnableSound demoSample = null!;
|
||||||
|
|
||||||
private FillFlowContainer togglesCollection = null!;
|
private FillFlowContainer togglesCollection = null!;
|
||||||
|
|
||||||
@@ -229,11 +244,11 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
{
|
{
|
||||||
flow = new FillFlowContainer
|
flow = new FillFlowContainer
|
||||||
{
|
{
|
||||||
Width = 200,
|
Width = 220,
|
||||||
Direction = FillDirection.Vertical,
|
Direction = FillDirection.Vertical,
|
||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
Spacing = new Vector2(0, 10),
|
Spacing = new Vector2(0, 10),
|
||||||
Children = new Drawable[]
|
Children = new[]
|
||||||
{
|
{
|
||||||
togglesCollection = new FillFlowContainer
|
togglesCollection = new FillFlowContainer
|
||||||
{
|
{
|
||||||
@@ -242,27 +257,30 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
Direction = FillDirection.Horizontal,
|
Direction = FillDirection.Horizontal,
|
||||||
Spacing = new Vector2(5, 5),
|
Spacing = new Vector2(5, 5),
|
||||||
},
|
},
|
||||||
bank = new LabelledTextBox
|
bank = new LabelledDropdown<string>(padded: false)
|
||||||
{
|
{
|
||||||
Label = "Bank Name",
|
Label = "Normal Bank",
|
||||||
SelectAllOnFocus = true,
|
Items = HitSampleInfo.ALL_BANKS,
|
||||||
},
|
},
|
||||||
additionBank = new LabelledTextBox
|
additionBank = new LabelledDropdown<string>(padded: false)
|
||||||
{
|
{
|
||||||
Label = "Addition Bank",
|
Label = "Addition Bank",
|
||||||
SelectAllOnFocus = true,
|
Items = HitSampleInfo.ALL_BANKS,
|
||||||
},
|
},
|
||||||
|
createSampleSetContent(),
|
||||||
volume = new IndeterminateSliderWithTextBoxInput<int>("Volume", new BindableInt(100)
|
volume = new IndeterminateSliderWithTextBoxInput<int>("Volume", new BindableInt(100)
|
||||||
{
|
{
|
||||||
MinValue = DrawableHitObject.MINIMUM_SAMPLE_VOLUME,
|
MinValue = DrawableHitObject.MINIMUM_SAMPLE_VOLUME,
|
||||||
MaxValue = 100,
|
MaxValue = 100,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
new EditorSkinProvidingContainer(beatmap)
|
||||||
|
{
|
||||||
|
Child = demoSample = new SkinnableSound()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
bank.TabbableContentContainer = flow;
|
|
||||||
additionBank.TabbableContentContainer = flow;
|
|
||||||
volume.TabbableContentContainer = flow;
|
volume.TabbableContentContainer = flow;
|
||||||
|
|
||||||
// if the piece belongs to a currently selected object, assume that the user wants to change all selected objects.
|
// if the piece belongs to a currently selected object, assume that the user wants to change all selected objects.
|
||||||
@@ -283,10 +301,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
|
|
||||||
setBank(val.NewValue);
|
setBank(val.NewValue);
|
||||||
updatePrimaryBankState();
|
updatePrimaryBankState();
|
||||||
|
playDemoSample();
|
||||||
});
|
});
|
||||||
// on commit, ensure that the value is correct by sourcing it from the objects' samples again.
|
|
||||||
// this ensures that committing empty text causes a revert to the previous value.
|
|
||||||
bank.OnCommit += (_, _) => updatePrimaryBankState();
|
|
||||||
|
|
||||||
updateAdditionBankState();
|
updateAdditionBankState();
|
||||||
additionBank.Current.BindValueChanged(val =>
|
additionBank.Current.BindValueChanged(val =>
|
||||||
@@ -296,8 +312,10 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
|
|
||||||
setAdditionBank(val.NewValue);
|
setAdditionBank(val.NewValue);
|
||||||
updateAdditionBankState();
|
updateAdditionBankState();
|
||||||
|
playDemoSample();
|
||||||
});
|
});
|
||||||
additionBank.OnCommit += (_, _) => updateAdditionBankState();
|
|
||||||
|
updateSampleSetState();
|
||||||
|
|
||||||
volume.Current.BindValueChanged(val =>
|
volume.Current.BindValueChanged(val =>
|
||||||
{
|
{
|
||||||
@@ -310,6 +328,58 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
togglesCollection.AddRange(createTernaryButtons());
|
togglesCollection.AddRange(createTernaryButtons());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Drawable createSampleSetContent()
|
||||||
|
{
|
||||||
|
if (beatmap.BeatmapSkin == null)
|
||||||
|
return Empty();
|
||||||
|
|
||||||
|
var sampleSets = beatmap.BeatmapSkin.GetAvailableSampleSets().ToList();
|
||||||
|
|
||||||
|
if (sampleSets.Count == 0)
|
||||||
|
return Empty();
|
||||||
|
|
||||||
|
sampleSets.Insert(0, new EditorBeatmapSkin.SampleSet(0, "User skin"));
|
||||||
|
|
||||||
|
if (sampleSets.Count < 20)
|
||||||
|
{
|
||||||
|
sampleSetsFlow = new FillFlowContainer<SampleSetTernaryButton>
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Spacing = new Vector2(5),
|
||||||
|
ChildrenEnumerable = sampleSets.Select(set => new SampleSetTernaryButton(set) { Description = set.Name }),
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var ternary in sampleSetsFlow)
|
||||||
|
{
|
||||||
|
ternary.Current.BindValueChanged(val =>
|
||||||
|
{
|
||||||
|
if (val.NewValue == TernaryState.True)
|
||||||
|
setSampleSet(ternary.SampleSet);
|
||||||
|
|
||||||
|
updateSampleSetState();
|
||||||
|
playDemoSample();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return sampleSetsFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
sampleSetDropdown = new LabelledDropdown<EditorBeatmapSkin.SampleSet>(padded: false)
|
||||||
|
{
|
||||||
|
Label = "Sample Set",
|
||||||
|
Items = sampleSets,
|
||||||
|
};
|
||||||
|
sampleSetDropdown.Current.BindValueChanged(val =>
|
||||||
|
{
|
||||||
|
setSampleSet(val.NewValue);
|
||||||
|
updateSampleSetState();
|
||||||
|
playDemoSample();
|
||||||
|
});
|
||||||
|
|
||||||
|
return sampleSetDropdown;
|
||||||
|
}
|
||||||
|
|
||||||
private string? getCommonBank() => allRelevantSamples.Select(h => GetBankValue(h.samples)).Distinct().Count() == 1
|
private string? getCommonBank() => allRelevantSamples.Select(h => GetBankValue(h.samples)).Distinct().Count() == 1
|
||||||
? GetBankValue(allRelevantSamples.First().samples)
|
? GetBankValue(allRelevantSamples.First().samples)
|
||||||
: null;
|
: null;
|
||||||
@@ -327,15 +397,13 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
private void updatePrimaryBankState()
|
private void updatePrimaryBankState()
|
||||||
{
|
{
|
||||||
string? commonBank = getCommonBank();
|
string? commonBank = getCommonBank();
|
||||||
bank.Current.Value = commonBank;
|
bank.Current.Value = !string.IsNullOrEmpty(commonBank) ? commonBank : "(multiple)";
|
||||||
bank.PlaceholderText = string.IsNullOrEmpty(commonBank) ? "(multiple)" : string.Empty;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateAdditionBankState()
|
private void updateAdditionBankState()
|
||||||
{
|
{
|
||||||
string? commonAdditionBank = getCommonAdditionBank();
|
string? commonAdditionBank = getCommonAdditionBank();
|
||||||
additionBank.PlaceholderText = string.IsNullOrEmpty(commonAdditionBank) ? "(multiple)" : string.Empty;
|
additionBank.Current.Value = !string.IsNullOrEmpty(commonAdditionBank) ? commonAdditionBank : "(multiple)";
|
||||||
additionBank.Current.Value = commonAdditionBank;
|
|
||||||
|
|
||||||
bool anyAdditions = allRelevantSamples.Any(o => o.samples.Any(s => s.Name != HitSampleInfo.HIT_NORMAL));
|
bool anyAdditions = allRelevantSamples.Any(o => o.samples.Any(s => s.Name != HitSampleInfo.HIT_NORMAL));
|
||||||
if (anyAdditions)
|
if (anyAdditions)
|
||||||
@@ -344,6 +412,40 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
additionBank.Hide();
|
additionBank.Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateSampleSetState()
|
||||||
|
{
|
||||||
|
HashSet<int> activeSets = new HashSet<int>();
|
||||||
|
|
||||||
|
foreach (var sample in allRelevantSamples.SelectMany(h => h.samples))
|
||||||
|
{
|
||||||
|
if (sample.Suffix == null)
|
||||||
|
activeSets.Add(sample.UseBeatmapSamples ? 1 : 0);
|
||||||
|
else if (int.TryParse(sample.Suffix, out int suffix))
|
||||||
|
activeSets.Add(suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sampleSetsFlow != null)
|
||||||
|
{
|
||||||
|
var onState = activeSets.Count > 1 ? TernaryState.Indeterminate : TernaryState.True;
|
||||||
|
|
||||||
|
foreach (var ternary in sampleSetsFlow)
|
||||||
|
ternary.Current.Value = activeSets.Contains(ternary.SampleSet.SampleSetIndex) ? onState : TernaryState.False;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sampleSetDropdown != null)
|
||||||
|
{
|
||||||
|
sampleSetDropdown.Current.Value = activeSets.Count == 1
|
||||||
|
? sampleSetDropdown.Items.Single(i => i.SampleSetIndex == activeSets.Single())
|
||||||
|
: new EditorBeatmapSkin.SampleSet(-1, "(multiple)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void playDemoSample() => Scheduler.AddOnce(() =>
|
||||||
|
{
|
||||||
|
demoSample.Samples = allRelevantSamples.First().samples.Cast<ISampleInfo>().ToArray();
|
||||||
|
demoSample.Play();
|
||||||
|
});
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Applies the given update action on all samples of <see cref="allRelevantSamples"/>
|
/// Applies the given update action on all samples of <see cref="allRelevantSamples"/>
|
||||||
/// and invokes the necessary update notifiers for the beatmap and hit objects.
|
/// and invokes the necessary update notifiers for the beatmap and hit objects.
|
||||||
@@ -397,6 +499,19 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setSampleSet(EditorBeatmapSkin.SampleSet newSampleSet)
|
||||||
|
{
|
||||||
|
updateAllRelevantSamples((_, relevantSamples) =>
|
||||||
|
{
|
||||||
|
for (int i = 0; i < relevantSamples.Count; i++)
|
||||||
|
{
|
||||||
|
relevantSamples[i] = relevantSamples[i].With(
|
||||||
|
newSuffix: newSampleSet.SampleSetIndex >= 2 ? newSampleSet.SampleSetIndex.ToString() : null,
|
||||||
|
newUseBeatmapSamples: newSampleSet.SampleSetIndex >= 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void setVolume(int newVolume)
|
private void setVolume(int newVolume)
|
||||||
{
|
{
|
||||||
updateAllRelevantSamples((_, relevantSamples) =>
|
updateAllRelevantSamples((_, relevantSamples) =>
|
||||||
@@ -435,6 +550,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
addHitSample(sampleName);
|
addHitSample(sampleName);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
playDemoSample();
|
||||||
};
|
};
|
||||||
|
|
||||||
selectionSampleStates[sampleName] = bindable;
|
selectionSampleStates[sampleName] = bindable;
|
||||||
@@ -455,7 +572,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
{
|
{
|
||||||
foreach ((string sampleName, var bindable) in selectionSampleStates)
|
foreach ((string sampleName, var bindable) in selectionSampleStates)
|
||||||
{
|
{
|
||||||
yield return new DrawableTernaryButton
|
yield return new DrawableTernaryButton(null)
|
||||||
{
|
{
|
||||||
Current = bindable,
|
Current = bindable,
|
||||||
Description = string.Empty,
|
Description = string.Empty,
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using osu.Framework.Audio.Sample;
|
using osu.Framework.Audio.Sample;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@@ -61,6 +63,46 @@ namespace osu.Game.Screens.Edit
|
|||||||
invokeSkinChanged();
|
invokeSkinChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public record SampleSet(int SampleSetIndex, string Name)
|
||||||
|
{
|
||||||
|
public SampleSet(int sampleSetIndex)
|
||||||
|
: this(sampleSetIndex, $@"Custom #{sampleSetIndex}")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString() => Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<SampleSet> GetAvailableSampleSets()
|
||||||
|
{
|
||||||
|
string[] possibleSounds = HitSampleInfo.ALL_ADDITIONS.Prepend(HitSampleInfo.HIT_NORMAL).ToArray();
|
||||||
|
string[] possibleBanks = HitSampleInfo.ALL_BANKS;
|
||||||
|
|
||||||
|
string[] possiblePrefixes = possibleSounds.SelectMany(sound => possibleBanks.Select(bank => $@"{bank}-{sound}")).ToArray();
|
||||||
|
|
||||||
|
HashSet<int> indices = new HashSet<int>();
|
||||||
|
|
||||||
|
if (Skin.Samples != null)
|
||||||
|
{
|
||||||
|
foreach (string sample in Skin.Samples.GetAvailableResources())
|
||||||
|
{
|
||||||
|
foreach (string possiblePrefix in possiblePrefixes)
|
||||||
|
{
|
||||||
|
if (!sample.StartsWith(possiblePrefix, StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
string indexString = Path.GetFileNameWithoutExtension(sample)[possiblePrefix.Length..];
|
||||||
|
if (string.IsNullOrEmpty(indexString))
|
||||||
|
indices.Add(1);
|
||||||
|
if (int.TryParse(indexString, out int index))
|
||||||
|
indices.Add(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return indices.OrderBy(i => i).Select(i => new SampleSet(i));
|
||||||
|
}
|
||||||
|
|
||||||
#region Delegated ISkin implementation
|
#region Delegated ISkin implementation
|
||||||
|
|
||||||
public Drawable? GetDrawableComponent(ISkinComponentLookup lookup) => Skin.GetDrawableComponent(lookup);
|
public Drawable? GetDrawableComponent(ISkinComponentLookup lookup) => Skin.GetDrawableComponent(lookup);
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace osu.Game.Skinning
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A sample store which can be used to perform user file lookups for this skin.
|
/// A sample store which can be used to perform user file lookups for this skin.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected ISampleStore? Samples { get; }
|
protected internal ISampleStore? Samples { get; }
|
||||||
|
|
||||||
public readonly Live<SkinInfo> SkinInfo;
|
public readonly Live<SkinInfo> SkinInfo;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user