mirror of
https://github.com/ppy/osu.git
synced 2025-02-13 11:12:54 +08:00
Merge pull request #14533 from frenzibyte/move-incompatibility-icon
Move mod incompatibility logic to "local player" mod select overlays
This commit is contained in:
commit
ef64c05af8
@ -529,7 +529,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
AddStep("invoke on back button", () => multiplayerScreen.OnBackButton());
|
||||
|
||||
AddAssert("mod overlay is hidden", () => this.ChildrenOfType<LocalPlayerModSelectOverlay>().Single().State.Value == Visibility.Hidden);
|
||||
AddAssert("mod overlay is hidden", () => this.ChildrenOfType<UserModSelectOverlay>().Single().State.Value == Visibility.Hidden);
|
||||
|
||||
AddAssert("dialog overlay is hidden", () => DialogOverlay.State.Value == Visibility.Hidden);
|
||||
|
||||
|
@ -422,7 +422,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
};
|
||||
}
|
||||
|
||||
private class TestModSelectOverlay : LocalPlayerModSelectOverlay
|
||||
private class TestModSelectOverlay : UserModSelectOverlay
|
||||
{
|
||||
public new Bindable<IReadOnlyList<Mod>> SelectedMods => base.SelectedMods;
|
||||
|
||||
|
@ -151,7 +151,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
AddUntilStep("wait for ready", () => modSelect.State.Value == Visibility.Visible && modSelect.ButtonsLoaded);
|
||||
}
|
||||
|
||||
private class TestModSelectOverlay : LocalPlayerModSelectOverlay
|
||||
private class TestModSelectOverlay : UserModSelectOverlay
|
||||
{
|
||||
public new VisibilityContainer ModSettingsContainer => base.ModSettingsContainer;
|
||||
public new TriangleButton CustomiseButton => base.CustomiseButton;
|
||||
|
117
osu.Game/Overlays/Mods/IncompatibilityDisplayingModButton.cs
Normal file
117
osu.Game/Overlays/Mods/IncompatibilityDisplayingModButton.cs
Normal file
@ -0,0 +1,117 @@
|
||||
// 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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Utils;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
public class IncompatibilityDisplayingModButton : ModButton
|
||||
{
|
||||
private readonly CompositeDrawable incompatibleIcon;
|
||||
|
||||
[Resolved]
|
||||
private Bindable<IReadOnlyList<Mod>> selectedMods { get; set; }
|
||||
|
||||
public IncompatibilityDisplayingModButton(Mod mod)
|
||||
: base(mod)
|
||||
{
|
||||
ButtonContent.Add(incompatibleIcon = new IncompatibleIcon
|
||||
{
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.Centre,
|
||||
Position = new Vector2(-13),
|
||||
});
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
selectedMods.BindValueChanged(_ => Scheduler.AddOnce(updateCompatibility), true);
|
||||
}
|
||||
|
||||
protected override void DisplayMod(Mod mod)
|
||||
{
|
||||
base.DisplayMod(mod);
|
||||
|
||||
Scheduler.AddOnce(updateCompatibility);
|
||||
}
|
||||
|
||||
private void updateCompatibility()
|
||||
{
|
||||
var m = SelectedMod ?? Mods.First();
|
||||
|
||||
bool isIncompatible = false;
|
||||
|
||||
if (selectedMods.Value.Count > 0 && !selectedMods.Value.Contains(m))
|
||||
isIncompatible = !ModUtils.CheckCompatibleSet(selectedMods.Value.Append(m));
|
||||
|
||||
if (isIncompatible)
|
||||
incompatibleIcon.Show();
|
||||
else
|
||||
incompatibleIcon.Hide();
|
||||
}
|
||||
|
||||
public override ITooltip<Mod> GetCustomTooltip() => new IncompatibilityDisplayingTooltip();
|
||||
|
||||
private class IncompatibilityDisplayingTooltip : ModButtonTooltip
|
||||
{
|
||||
private readonly OsuSpriteText incompatibleText;
|
||||
|
||||
private readonly Bindable<IReadOnlyList<Mod>> incompatibleMods = new Bindable<IReadOnlyList<Mod>>();
|
||||
|
||||
[Resolved]
|
||||
private Bindable<RulesetInfo> ruleset { get; set; }
|
||||
|
||||
public IncompatibilityDisplayingTooltip()
|
||||
{
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
incompatibleText = new OsuSpriteText
|
||||
{
|
||||
Margin = new MarginPadding { Top = 5 },
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Regular),
|
||||
Text = "Incompatible with:"
|
||||
},
|
||||
new ModDisplay
|
||||
{
|
||||
Current = incompatibleMods,
|
||||
ExpansionMode = ExpansionMode.AlwaysExpanded,
|
||||
Scale = new Vector2(0.7f)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
incompatibleText.Colour = colours.BlueLight;
|
||||
}
|
||||
|
||||
protected override void UpdateDisplay(Mod mod)
|
||||
{
|
||||
base.UpdateDisplay(mod);
|
||||
|
||||
var incompatibleTypes = mod.IncompatibleMods;
|
||||
|
||||
var allMods = ruleset.Value.CreateInstance().GetAllMods();
|
||||
|
||||
incompatibleMods.Value = allMods.Where(m => m.GetType() != mod.GetType() && incompatibleTypes.Any(t => t.IsInstanceOfType(m))).ToList();
|
||||
incompatibleText.Text = incompatibleMods.Value.Any() ? "Incompatible with:" : "Compatible with all mods";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -11,29 +11,24 @@ using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Utils;
|
||||
|
||||
namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a clickable button which can cycle through one of more mods.
|
||||
/// </summary>
|
||||
public class ModButton : ModButtonEmpty, IHasCustomTooltip
|
||||
public class ModButton : ModButtonEmpty, IHasCustomTooltip<Mod>
|
||||
{
|
||||
private ModIcon foregroundIcon;
|
||||
private ModIcon backgroundIcon;
|
||||
private readonly SpriteText text;
|
||||
private readonly Container<ModIcon> iconsContainer;
|
||||
private readonly CompositeDrawable incompatibleIcon;
|
||||
|
||||
/// <summary>
|
||||
/// Fired when the selection changes.
|
||||
@ -48,9 +43,6 @@ namespace osu.Game.Overlays.Mods
|
||||
// A selected index of -1 means not selected.
|
||||
private int selectedIndex = -1;
|
||||
|
||||
[Resolved]
|
||||
private Bindable<IReadOnlyList<Mod>> selectedMods { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Change the selected mod index of this button.
|
||||
/// </summary>
|
||||
@ -109,7 +101,7 @@ namespace osu.Game.Overlays.Mods
|
||||
.RotateTo(rotate_angle * direction)
|
||||
.RotateTo(0f, mod_switch_duration, mod_switch_easing);
|
||||
|
||||
Schedule(() => displayMod(newSelection));
|
||||
Schedule(() => DisplayMod(newSelection));
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,7 +130,8 @@ namespace osu.Game.Overlays.Mods
|
||||
}
|
||||
|
||||
private Mod mod;
|
||||
private readonly Container scaleContainer;
|
||||
|
||||
protected readonly Container ButtonContent;
|
||||
|
||||
public Mod Mod
|
||||
{
|
||||
@ -162,7 +155,7 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
if (Mods.Length > 0)
|
||||
{
|
||||
displayMod(Mods[0]);
|
||||
DisplayMod(Mods[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -173,13 +166,13 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
protected override bool OnMouseDown(MouseDownEvent e)
|
||||
{
|
||||
scaleContainer.ScaleTo(0.9f, 800, Easing.Out);
|
||||
ButtonContent.ScaleTo(0.9f, 800, Easing.Out);
|
||||
return base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
protected override void OnMouseUp(MouseUpEvent e)
|
||||
{
|
||||
scaleContainer.ScaleTo(1, 500, Easing.OutElastic);
|
||||
ButtonContent.ScaleTo(1, 500, Easing.OutElastic);
|
||||
|
||||
// only trigger the event if we are inside the area of the button
|
||||
if (Contains(e.ScreenSpaceMousePosition))
|
||||
@ -238,30 +231,13 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
public void Deselect() => changeSelectedIndex(-1);
|
||||
|
||||
private void displayMod(Mod mod)
|
||||
protected virtual void DisplayMod(Mod mod)
|
||||
{
|
||||
if (backgroundIcon != null)
|
||||
backgroundIcon.Mod = foregroundIcon.Mod;
|
||||
foregroundIcon.Mod = mod;
|
||||
text.Text = mod.Name;
|
||||
Colour = mod.HasImplementation ? Color4.White : Color4.Gray;
|
||||
|
||||
Scheduler.AddOnce(updateCompatibility);
|
||||
}
|
||||
|
||||
private void updateCompatibility()
|
||||
{
|
||||
var m = SelectedMod ?? Mods.First();
|
||||
|
||||
bool isIncompatible = false;
|
||||
|
||||
if (selectedMods.Value.Count > 0 && !selectedMods.Value.Contains(m))
|
||||
isIncompatible = !ModUtils.CheckCompatibleSet(selectedMods.Value.Append(m));
|
||||
|
||||
if (isIncompatible)
|
||||
incompatibleIcon.Show();
|
||||
else
|
||||
incompatibleIcon.Hide();
|
||||
}
|
||||
|
||||
private void createIcons()
|
||||
@ -307,7 +283,7 @@ namespace osu.Game.Overlays.Mods
|
||||
Anchor = Anchor.TopCentre,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
scaleContainer = new Container
|
||||
ButtonContent = new Container
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
@ -317,12 +293,6 @@ namespace osu.Game.Overlays.Mods
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
},
|
||||
incompatibleIcon = new IncompatibleIcon
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.BottomRight,
|
||||
Position = new Vector2(-13),
|
||||
}
|
||||
},
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Origin = Anchor.Centre,
|
||||
@ -342,15 +312,8 @@ namespace osu.Game.Overlays.Mods
|
||||
Mod = mod;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
public virtual ITooltip<Mod> GetCustomTooltip() => new ModButtonTooltip();
|
||||
|
||||
selectedMods.BindValueChanged(_ => Scheduler.AddOnce(updateCompatibility), true);
|
||||
}
|
||||
|
||||
public ITooltip GetCustomTooltip() => new ModButtonTooltip();
|
||||
|
||||
public object TooltipContent => SelectedMod ?? Mods.FirstOrDefault();
|
||||
public Mod TooltipContent => SelectedMod ?? Mods.FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,14 @@
|
||||
// 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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Overlays.Mods
|
||||
@ -22,12 +17,8 @@ namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
private readonly OsuSpriteText descriptionText;
|
||||
private readonly Box background;
|
||||
private readonly OsuSpriteText incompatibleText;
|
||||
|
||||
private readonly Bindable<IReadOnlyList<Mod>> incompatibleMods = new Bindable<IReadOnlyList<Mod>>();
|
||||
|
||||
[Resolved]
|
||||
private Bindable<RulesetInfo> ruleset { get; set; }
|
||||
protected override Container<Drawable> Content { get; }
|
||||
|
||||
public ModButtonTooltip()
|
||||
{
|
||||
@ -35,13 +26,13 @@ namespace osu.Game.Overlays.Mods
|
||||
Masking = true;
|
||||
CornerRadius = 5;
|
||||
|
||||
Children = new Drawable[]
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
background = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
new FillFlowContainer
|
||||
Content = new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
@ -51,19 +42,7 @@ namespace osu.Game.Overlays.Mods
|
||||
descriptionText = new OsuSpriteText
|
||||
{
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Regular),
|
||||
Margin = new MarginPadding { Bottom = 5 }
|
||||
},
|
||||
incompatibleText = new OsuSpriteText
|
||||
{
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Regular),
|
||||
Text = "Incompatible with:"
|
||||
},
|
||||
new ModDisplay
|
||||
{
|
||||
Current = incompatibleMods,
|
||||
ExpansionMode = ExpansionMode.AlwaysExpanded,
|
||||
Scale = new Vector2(0.7f)
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
@ -74,7 +53,6 @@ namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
background.Colour = colours.Gray3;
|
||||
descriptionText.Colour = colours.BlueLighter;
|
||||
incompatibleText.Colour = colours.BlueLight;
|
||||
}
|
||||
|
||||
protected override void PopIn() => this.FadeIn(200, Easing.OutQuint);
|
||||
@ -84,19 +62,17 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
public void SetContent(Mod mod)
|
||||
{
|
||||
if (mod.Equals(lastMod)) return;
|
||||
if (mod.Equals(lastMod))
|
||||
return;
|
||||
|
||||
lastMod = mod;
|
||||
|
||||
UpdateDisplay(mod);
|
||||
}
|
||||
|
||||
protected virtual void UpdateDisplay(Mod mod)
|
||||
{
|
||||
descriptionText.Text = mod.Description;
|
||||
|
||||
var incompatibleTypes = mod.IncompatibleMods;
|
||||
|
||||
var allMods = ruleset.Value.CreateInstance().GetAllMods();
|
||||
|
||||
incompatibleMods.Value = allMods.Where(m => m.GetType() != mod.GetType() && incompatibleTypes.Any(t => t.IsInstanceOfType(m))).ToList();
|
||||
|
||||
incompatibleText.Text = !incompatibleMods.Value.Any() ? "Compatible with all mods" : "Incompatible with:";
|
||||
}
|
||||
|
||||
public void Move(Vector2 pos) => Position = pos;
|
||||
|
@ -51,14 +51,14 @@ namespace osu.Game.Overlays.Mods
|
||||
if (m == null)
|
||||
return new ModButtonEmpty();
|
||||
|
||||
return new ModButton(m)
|
||||
return CreateModButton(m).With(b =>
|
||||
{
|
||||
SelectionChanged = mod =>
|
||||
b.SelectionChanged = mod =>
|
||||
{
|
||||
ModButtonStateChanged(mod);
|
||||
Action?.Invoke(mod);
|
||||
},
|
||||
};
|
||||
};
|
||||
});
|
||||
}).ToArray();
|
||||
|
||||
modsLoadCts?.Cancel();
|
||||
@ -247,6 +247,8 @@ namespace osu.Game.Overlays.Mods
|
||||
Text = text
|
||||
};
|
||||
|
||||
protected virtual ModButton CreateModButton(Mod mod) => new ModButton(mod);
|
||||
|
||||
/// <summary>
|
||||
/// Play out all remaining animations immediately to leave mods in a good (final) state.
|
||||
/// </summary>
|
||||
|
@ -5,7 +5,7 @@ using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
public class LocalPlayerModSelectOverlay : ModSelectOverlay
|
||||
public class UserModSelectOverlay : ModSelectOverlay
|
||||
{
|
||||
protected override void OnModSelected(Mod mod)
|
||||
{
|
||||
@ -14,5 +14,17 @@ namespace osu.Game.Overlays.Mods
|
||||
foreach (var section in ModSectionsContainer.Children)
|
||||
section.DeselectTypes(mod.IncompatibleMods, true, mod);
|
||||
}
|
||||
|
||||
protected override ModSection CreateModSection(ModType type) => new UserModSection(type);
|
||||
|
||||
private class UserModSection : ModSection
|
||||
{
|
||||
public UserModSection(ModType type)
|
||||
: base(type)
|
||||
{
|
||||
}
|
||||
|
||||
protected override ModButton CreateModButton(Mod mod) => new IncompatibilityDisplayingModButton(mod);
|
||||
}
|
||||
}
|
||||
}
|
@ -429,10 +429,6 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
/// <param name="room">The room to change the settings of.</param>
|
||||
protected abstract RoomSettingsOverlay CreateRoomSettingsOverlay(Room room);
|
||||
|
||||
private class UserModSelectOverlay : LocalPlayerModSelectOverlay
|
||||
{
|
||||
}
|
||||
|
||||
public class UserModSelectButton : PurpleTriangleButton
|
||||
{
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
return base.OnExiting(next);
|
||||
}
|
||||
|
||||
protected override ModSelectOverlay CreateModSelectOverlay() => new LocalPlayerModSelectOverlay
|
||||
protected override ModSelectOverlay CreateModSelectOverlay() => new UserModSelectOverlay
|
||||
{
|
||||
IsValidMod = IsValidMod
|
||||
};
|
||||
|
@ -315,7 +315,7 @@ namespace osu.Game.Screens.Select
|
||||
(new FooterButtonOptions(), BeatmapOptions)
|
||||
};
|
||||
|
||||
protected virtual ModSelectOverlay CreateModSelectOverlay() => new LocalPlayerModSelectOverlay();
|
||||
protected virtual ModSelectOverlay CreateModSelectOverlay() => new UserModSelectOverlay();
|
||||
|
||||
protected virtual void ApplyFilterToCarousel(FilterCriteria criteria)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user