mirror of
https://github.com/ppy/osu.git
synced 2025-01-15 00:02:54 +08:00
Allow unstacking mods
This commit is contained in:
parent
230b347c1e
commit
797a810287
@ -22,6 +22,7 @@ using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Utils;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osuTK.Input;
|
||||
@ -46,9 +47,27 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
protected readonly ModSettingsContainer ModSettingsContainer;
|
||||
|
||||
private bool stacked = true;
|
||||
|
||||
/// <summary>
|
||||
/// Whether mod icons should be stacked, or appear as individual buttons.
|
||||
/// </summary>
|
||||
public bool Stacked
|
||||
{
|
||||
get => stacked;
|
||||
set
|
||||
{
|
||||
stacked = value;
|
||||
updateAvailableMods();
|
||||
}
|
||||
}
|
||||
|
||||
[NotNull]
|
||||
private Func<Mod, bool> isValidMod = m => true;
|
||||
|
||||
/// <summary>
|
||||
/// A function that checks whether a given mod is valid.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public Func<Mod, bool> IsValidMod
|
||||
{
|
||||
@ -419,11 +438,18 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
private void updateAvailableMods()
|
||||
{
|
||||
if (availableMods.Value == null)
|
||||
if (availableMods?.Value == null)
|
||||
return;
|
||||
|
||||
foreach (var section in ModSectionsContainer.Children)
|
||||
section.Mods = availableMods.Value[section.ModType].Where(IsValidMod);
|
||||
{
|
||||
IEnumerable<Mod> modEnumeration = availableMods.Value[section.ModType];
|
||||
|
||||
if (!stacked)
|
||||
modEnumeration = ModValidation.FlattenMods(modEnumeration);
|
||||
|
||||
section.Mods = modEnumeration.Where(IsValidMod);
|
||||
}
|
||||
}
|
||||
|
||||
private void selectedModsChanged(ValueChangedEvent<IReadOnlyList<Mod>> mods)
|
||||
|
@ -14,6 +14,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
{
|
||||
public class FreeModSelectOverlay : ModSelectOverlay
|
||||
{
|
||||
public FreeModSelectOverlay()
|
||||
{
|
||||
Stacked = false;
|
||||
}
|
||||
|
||||
protected override ModSection CreateModSection(ModType type) => new FreeModSection(type);
|
||||
|
||||
private class FreeModSection : ModSection
|
||||
|
@ -42,7 +42,7 @@ namespace osu.Game.Utils
|
||||
var incompatibleTypes = new HashSet<Type>();
|
||||
var incomingTypes = new HashSet<Type>();
|
||||
|
||||
foreach (var mod in combination.SelectMany(flattenMod))
|
||||
foreach (var mod in combination.SelectMany(FlattenMod))
|
||||
{
|
||||
// Add the new mod incompatibilities, checking whether any match the existing mod types.
|
||||
foreach (var t in mod.IncompatibleMods)
|
||||
@ -79,7 +79,7 @@ namespace osu.Game.Utils
|
||||
{
|
||||
var allowedSet = new HashSet<Type>(allowedTypes);
|
||||
|
||||
return combination.SelectMany(flattenMod)
|
||||
return combination.SelectMany(FlattenMod)
|
||||
.All(m => allowedSet.Contains(m.GetType()));
|
||||
}
|
||||
|
||||
@ -93,20 +93,27 @@ namespace osu.Game.Utils
|
||||
/// <param name="incompatibleTypes">The set of incompatible <see cref="Mod"/> types.</param>
|
||||
/// <returns>Whether the given <see cref="Mod"/> is incompatible.</returns>
|
||||
private static bool isModIncompatible(Mod mod, ICollection<Type> incompatibleTypes)
|
||||
=> flattenMod(mod)
|
||||
=> FlattenMod(mod)
|
||||
.SelectMany(m => m.GetType().EnumerateBaseTypes())
|
||||
.Any(incompatibleTypes.Contains);
|
||||
|
||||
/// <summary>
|
||||
/// Flattens a set of <see cref="Mod"/>s, returning a new set with all <see cref="MultiMod"/>s removed.
|
||||
/// </summary>
|
||||
/// <param name="mods">The set of <see cref="Mod"/>s to flatten.</param>
|
||||
/// <returns>The new set, containing all <see cref="Mod"/>s in <paramref name="mods"/> recursively with all <see cref="MultiMod"/>s removed.</returns>
|
||||
public static IEnumerable<Mod> FlattenMods(IEnumerable<Mod> mods) => mods.SelectMany(FlattenMod);
|
||||
|
||||
/// <summary>
|
||||
/// Flattens a <see cref="Mod"/>, returning a set of <see cref="Mod"/>s in-place of any <see cref="MultiMod"/>s.
|
||||
/// </summary>
|
||||
/// <param name="mod">The <see cref="Mod"/> to flatten.</param>
|
||||
/// <returns>A set of singular "flattened" <see cref="Mod"/>s</returns>
|
||||
private static IEnumerable<Mod> flattenMod(Mod mod)
|
||||
public static IEnumerable<Mod> FlattenMod(Mod mod)
|
||||
{
|
||||
if (mod is MultiMod multi)
|
||||
{
|
||||
foreach (var m in multi.Mods.SelectMany(flattenMod))
|
||||
foreach (var m in multi.Mods.SelectMany(FlattenMod))
|
||||
yield return m;
|
||||
}
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user