mirror of
https://github.com/ppy/osu
synced 2024-12-25 08:12:41 +00:00
Migrate mod select overlay footer content
This commit is contained in:
parent
467d7c4f54
commit
48bf3f1385
@ -24,6 +24,7 @@ using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Rulesets.Taiko.Mods;
|
||||
using osu.Game.Screens.Footer;
|
||||
using osu.Game.Tests.Mods;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
@ -93,12 +94,28 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
|
||||
private void createScreen()
|
||||
{
|
||||
AddStep("create screen", () => Child = modSelectOverlay = new TestModSelectOverlay
|
||||
AddStep("create screen", () =>
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
State = { Value = Visibility.Visible },
|
||||
Beatmap = Beatmap.Value,
|
||||
SelectedMods = { BindTarget = SelectedMods }
|
||||
var receptor = new ScreenFooter.BackReceptor();
|
||||
var footer = new ScreenFooter(receptor);
|
||||
|
||||
Child = new DependencyProvidingContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
CachedDependencies = new[] { (typeof(ScreenFooter), (object)footer) },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
receptor,
|
||||
modSelectOverlay = new TestModSelectOverlay
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
State = { Value = Visibility.Visible },
|
||||
Beatmap = { Value = Beatmap.Value },
|
||||
SelectedMods = { BindTarget = SelectedMods },
|
||||
},
|
||||
footer,
|
||||
}
|
||||
};
|
||||
});
|
||||
waitForColumnLoad();
|
||||
}
|
||||
@ -119,7 +136,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
AddAssert("mod multiplier correct", () =>
|
||||
{
|
||||
double multiplier = SelectedMods.Value.Aggregate(1d, (m, mod) => m * mod.ScoreMultiplier);
|
||||
return Precision.AlmostEquals(multiplier, modSelectOverlay.ChildrenOfType<RankingInformationDisplay>().Single().ModMultiplier.Value);
|
||||
return Precision.AlmostEquals(multiplier, this.ChildrenOfType<RankingInformationDisplay>().Single().ModMultiplier.Value);
|
||||
});
|
||||
assertCustomisationToggleState(disabled: false, active: false);
|
||||
AddAssert("setting items created", () => modSelectOverlay.ChildrenOfType<ISettingsItem>().Any());
|
||||
@ -134,7 +151,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
AddAssert("mod multiplier correct", () =>
|
||||
{
|
||||
double multiplier = SelectedMods.Value.Aggregate(1d, (m, mod) => m * mod.ScoreMultiplier);
|
||||
return Precision.AlmostEquals(multiplier, modSelectOverlay.ChildrenOfType<RankingInformationDisplay>().Single().ModMultiplier.Value);
|
||||
return Precision.AlmostEquals(multiplier, this.ChildrenOfType<RankingInformationDisplay>().Single().ModMultiplier.Value);
|
||||
});
|
||||
assertCustomisationToggleState(disabled: false, active: false);
|
||||
AddAssert("setting items created", () => modSelectOverlay.ChildrenOfType<ISettingsItem>().Any());
|
||||
@ -756,7 +773,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
|
||||
AddStep("click back button", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(modSelectOverlay.BackButton);
|
||||
InputManager.MoveMouseTo(this.ChildrenOfType<ScreenBackButton>().Single());
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
AddAssert("mod select hidden", () => modSelectOverlay.State.Value == Visibility.Hidden);
|
||||
@ -884,7 +901,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
AddAssert("difficulty multiplier display shows correct value",
|
||||
() => modSelectOverlay.ChildrenOfType<RankingInformationDisplay>().Single().ModMultiplier.Value, () => Is.EqualTo(0.1).Within(Precision.DOUBLE_EPSILON));
|
||||
() => this.ChildrenOfType<RankingInformationDisplay>().Single().ModMultiplier.Value, () => Is.EqualTo(0.1).Within(Precision.DOUBLE_EPSILON));
|
||||
|
||||
// this is highly unorthodox in a test, but because the `ModSettingChangeTracker` machinery heavily leans on events and object disposal and re-creation,
|
||||
// it is instrumental in the reproduction of the failure scenario that this test is supposed to cover.
|
||||
@ -894,7 +911,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
AddStep("reset half time speed to default", () => modSelectOverlay.ChildrenOfType<ModCustomisationPanel>().Single()
|
||||
.ChildrenOfType<RevertToDefaultButton<double>>().Single().TriggerClick());
|
||||
AddUntilStep("difficulty multiplier display shows correct value",
|
||||
() => modSelectOverlay.ChildrenOfType<RankingInformationDisplay>().Single().ModMultiplier.Value, () => Is.EqualTo(0.3).Within(Precision.DOUBLE_EPSILON));
|
||||
() => this.ChildrenOfType<RankingInformationDisplay>().Single().ModMultiplier.Value, () => Is.EqualTo(0.3).Within(Precision.DOUBLE_EPSILON));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -1014,8 +1031,6 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
private partial class TestModSelectOverlay : UserModSelectOverlay
|
||||
{
|
||||
protected override bool ShowPresets => true;
|
||||
|
||||
public new ShearedButton BackButton => base.BackButton;
|
||||
}
|
||||
|
||||
private class TestUnimplementedMod : Mod
|
||||
|
177
osu.Game/Overlays/Mods/ModSelectFooterContent.cs
Normal file
177
osu.Game/Overlays/Mods/ModSelectFooterContent.cs
Normal file
@ -0,0 +1,177 @@
|
||||
// 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.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
public partial class ModSelectFooterContent : VisibilityContainer
|
||||
{
|
||||
private readonly ModSelectOverlay overlay;
|
||||
|
||||
private RankingInformationDisplay? rankingInformationDisplay;
|
||||
private BeatmapAttributesDisplay? beatmapAttributesDisplay;
|
||||
private FillFlowContainer<ShearedButton> buttonFlow = null!;
|
||||
private FillFlowContainer contentFlow = null!;
|
||||
|
||||
public DeselectAllModsButton? DeselectAllModsButton { get; set; }
|
||||
|
||||
public readonly IBindable<WorkingBeatmap?> Beatmap = new Bindable<WorkingBeatmap?>();
|
||||
public readonly IBindable<IReadOnlyList<Mod>> ActiveMods = new Bindable<IReadOnlyList<Mod>>();
|
||||
|
||||
/// <summary>
|
||||
/// Whether the effects (on score multiplier, on or beatmap difficulty) of the current selected set of mods should be shown.
|
||||
/// </summary>
|
||||
protected virtual bool ShowModEffects => true;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the ranking information and beatmap attributes displays are stacked vertically due to small space.
|
||||
/// </summary>
|
||||
public bool DisplaysStackedVertically { get; private set; }
|
||||
|
||||
public ModSelectFooterContent(ModSelectOverlay overlay)
|
||||
{
|
||||
this.overlay = overlay;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
InternalChild = buttonFlow = new FillFlowContainer<ShearedButton>
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
Padding = new MarginPadding { Horizontal = 20 },
|
||||
Spacing = new Vector2(10),
|
||||
ChildrenEnumerable = CreateButtons(),
|
||||
};
|
||||
|
||||
if (ShowModEffects)
|
||||
{
|
||||
AddInternal(contentFlow = new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(30, 10),
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight,
|
||||
Margin = new MarginPadding { Horizontal = 20 },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
rankingInformationDisplay = new RankingInformationDisplay
|
||||
{
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight
|
||||
},
|
||||
beatmapAttributesDisplay = new BeatmapAttributesDisplay
|
||||
{
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight,
|
||||
BeatmapInfo = { Value = Beatmap.Value?.BeatmapInfo },
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private ModSettingChangeTracker? modSettingChangeTracker;
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Beatmap.BindValueChanged(b =>
|
||||
{
|
||||
if (beatmapAttributesDisplay != null)
|
||||
beatmapAttributesDisplay.BeatmapInfo.Value = b.NewValue?.BeatmapInfo;
|
||||
}, true);
|
||||
|
||||
ActiveMods.BindValueChanged(m =>
|
||||
{
|
||||
updateInformation();
|
||||
|
||||
modSettingChangeTracker?.Dispose();
|
||||
|
||||
// Importantly, use ActiveMods.Value here (and not the ValueChanged NewValue) as the latter can
|
||||
// potentially be stale, due to complexities in the way change trackers work.
|
||||
//
|
||||
// See https://github.com/ppy/osu/pull/23284#issuecomment-1529056988
|
||||
modSettingChangeTracker = new ModSettingChangeTracker(ActiveMods.Value);
|
||||
modSettingChangeTracker.SettingChanged += _ => updateInformation();
|
||||
}, true);
|
||||
}
|
||||
|
||||
private void updateInformation()
|
||||
{
|
||||
if (rankingInformationDisplay != null)
|
||||
{
|
||||
double multiplier = 1.0;
|
||||
|
||||
foreach (var mod in ActiveMods.Value)
|
||||
multiplier *= mod.ScoreMultiplier;
|
||||
|
||||
rankingInformationDisplay.ModMultiplier.Value = multiplier;
|
||||
rankingInformationDisplay.Ranked.Value = ActiveMods.Value.All(m => m.Ranked);
|
||||
}
|
||||
|
||||
if (beatmapAttributesDisplay != null)
|
||||
beatmapAttributesDisplay.Mods.Value = ActiveMods.Value;
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (beatmapAttributesDisplay != null)
|
||||
{
|
||||
float rightEdgeOfLastButton = buttonFlow[^1].ScreenSpaceDrawQuad.TopRight.X;
|
||||
|
||||
// this is cheating a bit; the 640 value is hardcoded based on how wide the expanded panel _generally_ is.
|
||||
// due to the transition applied, the raw screenspace quad of the panel cannot be used, as it will trigger an ugly feedback cycle of expanding and collapsing.
|
||||
float projectedLeftEdgeOfExpandedBeatmapAttributesDisplay = buttonFlow.ToScreenSpace(buttonFlow.DrawSize - new Vector2(640, 0)).X;
|
||||
|
||||
DisplaysStackedVertically = rightEdgeOfLastButton > projectedLeftEdgeOfExpandedBeatmapAttributesDisplay;
|
||||
|
||||
// only update preview panel's collapsed state after we are fully visible, to ensure all the buttons are where we expect them to be.
|
||||
if (Alpha == 1)
|
||||
beatmapAttributesDisplay.Collapsed.Value = DisplaysStackedVertically;
|
||||
|
||||
contentFlow.LayoutDuration = 200;
|
||||
contentFlow.LayoutEasing = Easing.OutQuint;
|
||||
contentFlow.Direction = DisplaysStackedVertically ? FillDirection.Vertical : FillDirection.Horizontal;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual IEnumerable<ShearedButton> CreateButtons() => new[]
|
||||
{
|
||||
DeselectAllModsButton = new DeselectAllModsButton(overlay)
|
||||
};
|
||||
|
||||
protected override void PopIn()
|
||||
{
|
||||
this.MoveToY(0, 400, Easing.OutQuint)
|
||||
.FadeIn(400, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override void PopOut()
|
||||
{
|
||||
this.MoveToY(-20f, 200, Easing.OutQuint)
|
||||
.FadeOut(200, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
}
|
@ -27,6 +27,7 @@ using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens.Footer;
|
||||
using osu.Game.Utils;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
@ -87,11 +88,6 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
public ShearedSearchTextBox SearchTextBox { get; private set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the effects (on score multiplier, on or beatmap difficulty) of the current selected set of mods should be shown.
|
||||
/// </summary>
|
||||
protected virtual bool ShowModEffects => true;
|
||||
|
||||
/// <summary>
|
||||
/// Whether per-mod customisation controls are visible.
|
||||
/// </summary>
|
||||
@ -108,11 +104,6 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
protected virtual IReadOnlyList<Mod> ComputeActiveMods() => SelectedMods.Value;
|
||||
|
||||
protected virtual IEnumerable<ShearedButton> CreateFooterButtons()
|
||||
{
|
||||
yield return deselectAllModsButton = new DeselectAllModsButton(this);
|
||||
}
|
||||
|
||||
private readonly Bindable<Dictionary<ModType, IReadOnlyList<Mod>>> globalAvailableMods = new Bindable<Dictionary<ModType, IReadOnlyList<Mod>>>();
|
||||
|
||||
public IEnumerable<ModState> AllAvailableMods => AvailableMods.Value.SelectMany(pair => pair.Value);
|
||||
@ -121,34 +112,18 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
private ColumnScrollContainer columnScroll = null!;
|
||||
private ColumnFlowContainer columnFlow = null!;
|
||||
private FillFlowContainer<ShearedButton> footerButtonFlow = null!;
|
||||
private FillFlowContainer footerContentFlow = null!;
|
||||
private DeselectAllModsButton deselectAllModsButton = null!;
|
||||
|
||||
private Container aboveColumnsContent = null!;
|
||||
private RankingInformationDisplay? rankingInformationDisplay;
|
||||
private BeatmapAttributesDisplay? beatmapAttributesDisplay;
|
||||
private ModCustomisationPanel customisationPanel = null!;
|
||||
|
||||
protected ShearedButton BackButton { get; private set; } = null!;
|
||||
protected SelectAllModsButton? SelectAllModsButton { get; set; }
|
||||
protected virtual SelectAllModsButton? SelectAllModsButton => null;
|
||||
|
||||
private Sample? columnAppearSample;
|
||||
|
||||
private WorkingBeatmap? beatmap;
|
||||
public readonly Bindable<WorkingBeatmap?> Beatmap = new Bindable<WorkingBeatmap?>();
|
||||
|
||||
public WorkingBeatmap? Beatmap
|
||||
{
|
||||
get => beatmap;
|
||||
set
|
||||
{
|
||||
if (beatmap == value) return;
|
||||
|
||||
beatmap = value;
|
||||
if (IsLoaded && beatmapAttributesDisplay != null)
|
||||
beatmapAttributesDisplay.BeatmapInfo.Value = beatmap?.BeatmapInfo;
|
||||
}
|
||||
}
|
||||
[Resolved]
|
||||
private ScreenFooter? footer { get; set; }
|
||||
|
||||
protected ModSelectOverlay(OverlayColourScheme colourScheme = OverlayColourScheme.Green)
|
||||
: base(colourScheme)
|
||||
@ -226,59 +201,6 @@ namespace osu.Game.Overlays.Mods
|
||||
}
|
||||
});
|
||||
|
||||
FooterContent.Add(footerButtonFlow = new FillFlowContainer<ShearedButton>
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
Padding = new MarginPadding
|
||||
{
|
||||
Vertical = PADDING,
|
||||
Horizontal = 70
|
||||
},
|
||||
Spacing = new Vector2(10),
|
||||
ChildrenEnumerable = CreateFooterButtons().Prepend(BackButton = new ShearedButton(BUTTON_WIDTH)
|
||||
{
|
||||
Text = CommonStrings.Back,
|
||||
Action = Hide,
|
||||
DarkerColour = colours.Pink2,
|
||||
LighterColour = colours.Pink1
|
||||
})
|
||||
});
|
||||
|
||||
if (ShowModEffects)
|
||||
{
|
||||
FooterContent.Add(footerContentFlow = new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(30, 10),
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight,
|
||||
Margin = new MarginPadding
|
||||
{
|
||||
Vertical = PADDING,
|
||||
Horizontal = 20
|
||||
},
|
||||
Children = new Drawable[]
|
||||
{
|
||||
rankingInformationDisplay = new RankingInformationDisplay
|
||||
{
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight
|
||||
},
|
||||
beatmapAttributesDisplay = new BeatmapAttributesDisplay
|
||||
{
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight,
|
||||
BeatmapInfo = { Value = Beatmap?.BeatmapInfo },
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
globalAvailableMods.BindTo(game.AvailableMods);
|
||||
|
||||
textSearchStartsActive = configManager.GetBindable<bool>(OsuSetting.ModSelectTextSearchStartsActive);
|
||||
@ -292,8 +214,6 @@ namespace osu.Game.Overlays.Mods
|
||||
SearchTextBox.Current.Value = string.Empty;
|
||||
}
|
||||
|
||||
private ModSettingChangeTracker? modSettingChangeTracker;
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
// this is called before base call so that the mod state is populated early, and the transition in `PopIn()` can play out properly.
|
||||
@ -316,23 +236,6 @@ namespace osu.Game.Overlays.Mods
|
||||
ActiveMods.Value = ComputeActiveMods();
|
||||
}, true);
|
||||
|
||||
ActiveMods.BindValueChanged(_ =>
|
||||
{
|
||||
updateOverlayInformation();
|
||||
|
||||
modSettingChangeTracker?.Dispose();
|
||||
|
||||
if (AllowCustomisation)
|
||||
{
|
||||
// Importantly, use ActiveMods.Value here (and not the ValueChanged NewValue) as the latter can
|
||||
// potentially be stale, due to complexities in the way change trackers work.
|
||||
//
|
||||
// See https://github.com/ppy/osu/pull/23284#issuecomment-1529056988
|
||||
modSettingChangeTracker = new ModSettingChangeTracker(ActiveMods.Value);
|
||||
modSettingChangeTracker.SettingChanged += _ => updateOverlayInformation();
|
||||
}
|
||||
}, true);
|
||||
|
||||
customisationPanel.Expanded.BindValueChanged(_ => updateCustomisationVisualState(), true);
|
||||
|
||||
SearchTextBox.Current.BindValueChanged(query =>
|
||||
@ -350,6 +253,16 @@ namespace osu.Game.Overlays.Mods
|
||||
});
|
||||
}
|
||||
|
||||
private ModSelectFooterContent? currentFooterContent;
|
||||
|
||||
public override bool UseNewFooter => true;
|
||||
|
||||
public override Drawable CreateFooterContent() => currentFooterContent = new ModSelectFooterContent(this)
|
||||
{
|
||||
Beatmap = { BindTarget = Beatmap },
|
||||
ActiveMods = { BindTarget = ActiveMods },
|
||||
};
|
||||
|
||||
private static readonly LocalisableString input_search_placeholder = Resources.Localisation.Web.CommonStrings.InputSearch;
|
||||
private static readonly LocalisableString tab_to_search_placeholder = ModSelectOverlayStrings.TabToSearch;
|
||||
|
||||
@ -358,26 +271,7 @@ namespace osu.Game.Overlays.Mods
|
||||
base.Update();
|
||||
|
||||
SearchTextBox.PlaceholderText = SearchTextBox.HasFocus ? input_search_placeholder : tab_to_search_placeholder;
|
||||
|
||||
if (beatmapAttributesDisplay != null)
|
||||
{
|
||||
float rightEdgeOfLastButton = footerButtonFlow[^1].ScreenSpaceDrawQuad.TopRight.X;
|
||||
|
||||
// this is cheating a bit; the 640 value is hardcoded based on how wide the expanded panel _generally_ is.
|
||||
// due to the transition applied, the raw screenspace quad of the panel cannot be used, as it will trigger an ugly feedback cycle of expanding and collapsing.
|
||||
float projectedLeftEdgeOfExpandedBeatmapAttributesDisplay = footerButtonFlow.ToScreenSpace(footerButtonFlow.DrawSize - new Vector2(640, 0)).X;
|
||||
|
||||
bool screenIsntWideEnough = rightEdgeOfLastButton > projectedLeftEdgeOfExpandedBeatmapAttributesDisplay;
|
||||
|
||||
// only update preview panel's collapsed state after we are fully visible, to ensure all the buttons are where we expect them to be.
|
||||
if (Alpha == 1)
|
||||
beatmapAttributesDisplay.Collapsed.Value = screenIsntWideEnough;
|
||||
|
||||
footerContentFlow.LayoutDuration = 200;
|
||||
footerContentFlow.LayoutEasing = Easing.OutQuint;
|
||||
footerContentFlow.Direction = screenIsntWideEnough ? FillDirection.Vertical : FillDirection.Horizontal;
|
||||
aboveColumnsContent.Padding = aboveColumnsContent.Padding with { Bottom = screenIsntWideEnough ? 70f : 15f };
|
||||
}
|
||||
aboveColumnsContent.Padding = aboveColumnsContent.Padding with { Bottom = currentFooterContent?.DisplaysStackedVertically == true ? 75f : 15f };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -455,27 +349,6 @@ namespace osu.Game.Overlays.Mods
|
||||
modState.ValidForSelection.Value = modState.Mod.Type != ModType.System && modState.Mod.HasImplementation && IsValidMod.Invoke(modState.Mod);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates any information displayed on the overlay regarding the effects of the active mods.
|
||||
/// This reads from <see cref="ActiveMods"/> instead of <see cref="SelectedMods"/>.
|
||||
/// </summary>
|
||||
private void updateOverlayInformation()
|
||||
{
|
||||
if (rankingInformationDisplay != null)
|
||||
{
|
||||
double multiplier = 1.0;
|
||||
|
||||
foreach (var mod in ActiveMods.Value)
|
||||
multiplier *= mod.ScoreMultiplier;
|
||||
|
||||
rankingInformationDisplay.ModMultiplier.Value = multiplier;
|
||||
rankingInformationDisplay.Ranked.Value = ActiveMods.Value.All(m => m.Ranked);
|
||||
}
|
||||
|
||||
if (beatmapAttributesDisplay != null)
|
||||
beatmapAttributesDisplay.Mods.Value = ActiveMods.Value;
|
||||
}
|
||||
|
||||
private void updateCustomisation()
|
||||
{
|
||||
if (!AllowCustomisation)
|
||||
@ -701,7 +574,7 @@ namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
if (!SearchTextBox.HasFocus && !customisationPanel.Expanded.Value)
|
||||
{
|
||||
deselectAllModsButton.TriggerClick();
|
||||
currentFooterContent?.DeselectAllModsButton?.TriggerClick();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -732,7 +605,7 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
return base.OnPressed(e);
|
||||
|
||||
void hideOverlay() => BackButton.TriggerClick();
|
||||
void hideOverlay() => footer?.BackButton.TriggerClick();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IKeyBindingHandler{PlatformAction}"/>
|
||||
@ -740,7 +613,7 @@ namespace osu.Game.Overlays.Mods
|
||||
/// This is handled locally here due to conflicts in input handling between the search text box and the select all mods button.
|
||||
/// Attempting to handle this action locally in both places leads to a possible scenario
|
||||
/// wherein activating the "select all" platform binding will both select all text in the search box and select all mods.
|
||||
/// </remarks>>
|
||||
/// </remarks>
|
||||
public bool OnPressed(KeyBindingPressEvent<PlatformAction> e)
|
||||
{
|
||||
if (e.Repeat || e.Action != PlatformAction.SelectAll || SelectAllModsButton == null)
|
||||
|
@ -14,8 +14,6 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
{
|
||||
public partial class FreeModSelectOverlay : ModSelectOverlay
|
||||
{
|
||||
protected override bool ShowModEffects => false;
|
||||
|
||||
protected override bool AllowCustomisation => false;
|
||||
|
||||
public new Func<Mod, bool> IsValidMod
|
||||
@ -24,6 +22,10 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
set => base.IsValidMod = m => m.UserPlayable && value.Invoke(m);
|
||||
}
|
||||
|
||||
private FreeModSelectFooterContent? currentFooterContent;
|
||||
|
||||
protected override SelectAllModsButton? SelectAllModsButton => currentFooterContent?.SelectAllModsButton;
|
||||
|
||||
public FreeModSelectOverlay()
|
||||
: base(OverlayColourScheme.Plum)
|
||||
{
|
||||
@ -32,12 +34,33 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
|
||||
protected override ModColumn CreateModColumn(ModType modType) => new ModColumn(modType, true);
|
||||
|
||||
protected override IEnumerable<ShearedButton> CreateFooterButtons()
|
||||
=> base.CreateFooterButtons()
|
||||
.Prepend(SelectAllModsButton = new SelectAllModsButton(this)
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
});
|
||||
public override Drawable CreateFooterContent() => currentFooterContent = new FreeModSelectFooterContent(this)
|
||||
{
|
||||
Beatmap = { BindTarget = Beatmap },
|
||||
ActiveMods = { BindTarget = ActiveMods },
|
||||
};
|
||||
|
||||
private partial class FreeModSelectFooterContent : ModSelectFooterContent
|
||||
{
|
||||
private readonly FreeModSelectOverlay overlay;
|
||||
|
||||
protected override bool ShowModEffects => false;
|
||||
|
||||
public SelectAllModsButton? SelectAllModsButton;
|
||||
|
||||
public FreeModSelectFooterContent(FreeModSelectOverlay overlay)
|
||||
: base(overlay)
|
||||
{
|
||||
this.overlay = overlay;
|
||||
}
|
||||
|
||||
protected override IEnumerable<ShearedButton> CreateButtons()
|
||||
=> base.CreateButtons()
|
||||
.Prepend(SelectAllModsButton = new SelectAllModsButton(overlay)
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -453,7 +453,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
// Retrieve the corresponding local beatmap, since we can't directly use the playlist's beatmap info
|
||||
var localBeatmap = beatmap == null ? null : beatmapManager.QueryBeatmap(b => b.OnlineID == beatmap.OnlineID);
|
||||
|
||||
UserModsSelectOverlay.Beatmap = Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap);
|
||||
UserModsSelectOverlay.Beatmap.Value = Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap);
|
||||
}
|
||||
|
||||
protected virtual void UpdateMods()
|
||||
|
@ -851,7 +851,7 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
BeatmapDetails.Beatmap = beatmap;
|
||||
|
||||
ModSelect.Beatmap = beatmap;
|
||||
ModSelect.Beatmap.Value = beatmap;
|
||||
|
||||
advancedStats.BeatmapInfo = beatmap.BeatmapInfo;
|
||||
|
||||
|
@ -658,7 +658,6 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
private partial class TestModSelectOverlay : UserModSelectOverlay
|
||||
{
|
||||
protected override bool ShowModEffects => true;
|
||||
protected override bool ShowPresets => false;
|
||||
|
||||
public TestModSelectOverlay()
|
||||
|
Loading…
Reference in New Issue
Block a user