From b8899ee3e16763b1c41c2e338df4dcc027abb8f7 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Tue, 21 Jul 2026 15:52:12 +0800 Subject: [PATCH 1/4] add interface IAdjustableWhenReplay and HudModDisplay, make ModIcon clickable --- .../Rulesets/Mods/IAdjustableWhenReplay.cs | 12 +++++ osu.Game/Rulesets/UI/ModIcon.cs | 3 +- osu.Game/Screens/Play/HUD/HudModDisplay.cs | 44 +++++++++++++++++++ osu.Game/Screens/Play/HUD/ModDisplay.cs | 22 +++++----- osu.Game/Screens/Play/HUDOverlay.cs | 2 +- 5 files changed, 70 insertions(+), 13 deletions(-) create mode 100644 osu.Game/Rulesets/Mods/IAdjustableWhenReplay.cs create mode 100644 osu.Game/Screens/Play/HUD/HudModDisplay.cs diff --git a/osu.Game/Rulesets/Mods/IAdjustableWhenReplay.cs b/osu.Game/Rulesets/Mods/IAdjustableWhenReplay.cs new file mode 100644 index 000000000000..11615181a76c --- /dev/null +++ b/osu.Game/Rulesets/Mods/IAdjustableWhenReplay.cs @@ -0,0 +1,12 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; + +namespace osu.Game.Rulesets.Mods +{ + public interface IAdjustableWhenReplay : IApplicableMod + { + BindableBool IsDisabled { get; } + } +} diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index 79cf073a42be..6b3ac7d36a97 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -13,6 +13,7 @@ using osu.Framework.Utils; using osu.Game.Configuration; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Overlays; using osu.Game.Rulesets.Mods; @@ -24,7 +25,7 @@ namespace osu.Game.Rulesets.UI /// /// Display the specified mod at a fixed size. /// - public partial class ModIcon : Container, IHasCustomTooltip + public partial class ModIcon : OsuClickableContainer, IHasCustomTooltip { public readonly BindableBool Selected = new BindableBool(); diff --git a/osu.Game/Screens/Play/HUD/HudModDisplay.cs b/osu.Game/Screens/Play/HUD/HudModDisplay.cs new file mode 100644 index 000000000000..b82dcd33a8a2 --- /dev/null +++ b/osu.Game/Screens/Play/HUD/HudModDisplay.cs @@ -0,0 +1,44 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using osu.Framework.Bindables; +using osu.Game.Graphics; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.UI; +using osuTK.Graphics; + +namespace osu.Game.Screens.Play.HUD +{ + public partial class HudModDisplay : ModDisplay + { + private readonly Bindable replayLoaded = new Bindable(); + + public HudModDisplay(Bindable replayLoaded, bool showExtendedInformation = true) + : base(showExtendedInformation) + { + this.replayLoaded.BindTo(replayLoaded); + } + + protected override void UpdateDisplay(ValueChangedEvent> mods) + { + base.UpdateDisplay(mods); + + foreach (ModIcon modIcon in IconsContainer) + { + if (modIcon.Mod is not IAdjustableWhenReplay dmod) + continue; + + dmod.IsDisabled.BindValueChanged(_ => modIcon.Colour = dmod.IsDisabled.Value ? OsuColour.Gray(0.7f) : Color4.White, true); + + modIcon.Action = () => + { + if (!replayLoaded.Value) + return; + + dmod.IsDisabled.Toggle(); + }; + } + } + } +} diff --git a/osu.Game/Screens/Play/HUD/ModDisplay.cs b/osu.Game/Screens/Play/HUD/ModDisplay.cs index 986bc525ccd3..fc2d357579c4 100644 --- a/osu.Game/Screens/Play/HUD/ModDisplay.cs +++ b/osu.Game/Screens/Play/HUD/ModDisplay.cs @@ -62,18 +62,18 @@ public bool ShowExtendedInformation set { showExtendedInformation = value; - foreach (var icon in iconsContainer) + foreach (var icon in IconsContainer) icon.ShowExtendedInformation = value; } } public FillDirection FillDirection { - get => iconsContainer.Direction; - set => iconsContainer.Direction = value; + get => IconsContainer.Direction; + set => IconsContainer.Direction = value; } - private readonly FillFlowContainer iconsContainer; + protected readonly FillFlowContainer IconsContainer; public ModDisplay(bool showExtendedInformation = true) { @@ -81,7 +81,7 @@ public ModDisplay(bool showExtendedInformation = true) AutoSizeAxes = Axes.Both; - InternalChild = iconsContainer = new ReverseChildIDFillFlowContainer + InternalChild = IconsContainer = new ReverseChildIDFillFlowContainer { AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, @@ -92,16 +92,16 @@ protected override void LoadComplete() { base.LoadComplete(); - Current.BindValueChanged(updateDisplay, true); + Current.BindValueChanged(UpdateDisplay, true); updateExpansionMode(0); } - private void updateDisplay(ValueChangedEvent> mods) + protected virtual void UpdateDisplay(ValueChangedEvent> mods) { - iconsContainer.Clear(); + IconsContainer.Clear(); foreach (Mod mod in mods.NewValue.AsOrdered()) - iconsContainer.Add(new ModIcon(mod, showExtendedInformation: showExtendedInformation) { Scale = new Vector2(MOD_ICON_SCALE) }); + IconsContainer.Add(new ModIcon(mod, showExtendedInformation: showExtendedInformation) { Scale = new Vector2(MOD_ICON_SCALE) }); } private void updateExpansionMode(double duration = 500) @@ -128,13 +128,13 @@ private void updateExpansionMode(double duration = 500) private void expand(double duration = 500) { if (ExpansionMode != ExpansionMode.AlwaysContracted) - iconsContainer.TransformSpacingTo(new Vector2(5, -10), duration, Easing.OutQuint); + IconsContainer.TransformSpacingTo(new Vector2(5, -10), duration, Easing.OutQuint); } private void contract(double duration = 500) { if (ExpansionMode != ExpansionMode.AlwaysExpanded) - iconsContainer.TransformSpacingTo(new Vector2(-25), duration, Easing.OutQuint); + IconsContainer.TransformSpacingTo(new Vector2(-25), duration, Easing.OutQuint); } protected override bool OnHover(HoverEvent e) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 7da996c20897..3fc334e1fb38 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -380,7 +380,7 @@ protected virtual void BindDrawableRuleset(DrawableRuleset drawableRuleset) Origin = Anchor.BottomRight, }; - protected ModDisplay CreateModsContainer() => new ModDisplay + protected ModDisplay CreateModsContainer() => new HudModDisplay(replayLoaded) { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, From 68638c2df769042404c72cdd20933cbe84cc2c28 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Tue, 21 Jul 2026 15:57:39 +0800 Subject: [PATCH 2/4] implement for dt ht hd fl --- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 7 ++++++- osu.Game/Rulesets/Mods/ModDoubleTime.cs | 5 ++++- osu.Game/Rulesets/Mods/ModFlashlight.cs | 9 ++++++++- osu.Game/Rulesets/Mods/ModHalfTime.cs | 5 ++++- osu.Game/Rulesets/Mods/RateAdjustModHelper.cs | 20 +++++++++++++++++-- 5 files changed, 40 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index d3ac5ce50c36..d2f9cc0bad37 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModHidden : ModHidden, IHidesApproachCircles + public class OsuModHidden : ModHidden, IHidesApproachCircles, IAdjustableWhenReplay { [SettingSource("Only fade approach circles", "The main object body will not fade when enabled.")] public Bindable OnlyFadeApproachCircles { get; } = new BindableBool(); @@ -30,6 +30,8 @@ public class OsuModHidden : ModHidden, IHidesApproachCircles public const double FADE_IN_DURATION_MULTIPLIER = 0.4; public const double FADE_OUT_DURATION_MULTIPLIER = 0.3; + public BindableBool IsDisabled { get; } = new BindableBool(); + protected override bool IsFirstAdjustableObject(HitObject hitObject) => !(hitObject is Spinner || hitObject is SpinnerTick); public override void ApplyToBeatmap(IBeatmap beatmap) @@ -62,6 +64,9 @@ protected override void ApplyNormalVisibilityState(DrawableHitObject hitObject, private void applyHiddenState(DrawableHitObject drawableObject, bool increaseVisibility) { + if (IsDisabled.Value) + return; + if (!(drawableObject is DrawableOsuHitObject drawableOsuObject)) return; diff --git a/osu.Game/Rulesets/Mods/ModDoubleTime.cs b/osu.Game/Rulesets/Mods/ModDoubleTime.cs index 794be5c134ba..84c757ddc653 100644 --- a/osu.Game/Rulesets/Mods/ModDoubleTime.cs +++ b/osu.Game/Rulesets/Mods/ModDoubleTime.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Mods { - public abstract class ModDoubleTime : ModRateAdjust + public abstract class ModDoubleTime : ModRateAdjust, IAdjustableWhenReplay { public override string Name => "Double Time"; public override string Acronym => "DT"; @@ -44,12 +44,15 @@ public abstract class ModDoubleTime : ModRateAdjust } } + public BindableBool IsDisabled { get; } = new BindableBool(); + private readonly RateAdjustModHelper rateAdjustHelper; protected ModDoubleTime() { rateAdjustHelper = new RateAdjustModHelper(SpeedChange); rateAdjustHelper.HandleAudioAdjustments(AdjustPitch); + rateAdjustHelper.DisableSpeedChange.BindTo(IsDisabled); } public override void ApplyToTrack(IAdjustableAudioComponent track) diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index 884066d7ab74..853ac3cfebcf 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -50,7 +50,7 @@ public abstract class ModFlashlight : Mod public abstract float DefaultFlashlightSize { get; } } - public abstract partial class ModFlashlight : ModFlashlight, IApplicableToDrawableRuleset, IApplicableToScoreProcessor + public abstract partial class ModFlashlight : ModFlashlight, IApplicableToDrawableRuleset, IApplicableToScoreProcessor, IAdjustableWhenReplay where T : HitObject { public const double FLASHLIGHT_FADE_DURATION = 800; @@ -100,10 +100,17 @@ public virtual void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) // NegativeInfinity is not used to allow one more thing drawn on top (used in replay analysis overlay in osu!). Depth = float.MinValue, }); + + IsDisabled.BindValueChanged(_ => + { + flashlight.FadeTo(IsDisabled.Value ? 0.3f : 1.0f, 50); + }, true); } protected abstract Flashlight CreateFlashlight(); + public BindableBool IsDisabled { get; } = new BindableBool(); + public abstract partial class Flashlight : Drawable { public readonly BindableInt Combo = new BindableInt(); diff --git a/osu.Game/Rulesets/Mods/ModHalfTime.cs b/osu.Game/Rulesets/Mods/ModHalfTime.cs index ae15ea5179a6..130cb65ff80d 100644 --- a/osu.Game/Rulesets/Mods/ModHalfTime.cs +++ b/osu.Game/Rulesets/Mods/ModHalfTime.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Mods { - public abstract class ModHalfTime : ModRateAdjust + public abstract class ModHalfTime : ModRateAdjust, IAdjustableWhenReplay { public override string Name => "Half Time"; public override string Acronym => "HT"; @@ -44,12 +44,15 @@ public abstract class ModHalfTime : ModRateAdjust } } + public BindableBool IsDisabled { get; } = new BindableBool(); + private readonly RateAdjustModHelper rateAdjustHelper; protected ModHalfTime() { rateAdjustHelper = new RateAdjustModHelper(SpeedChange); rateAdjustHelper.HandleAudioAdjustments(AdjustPitch); + rateAdjustHelper.DisableSpeedChange.BindTo(IsDisabled); } public override void ApplyToTrack(IAdjustableAudioComponent track) diff --git a/osu.Game/Rulesets/Mods/RateAdjustModHelper.cs b/osu.Game/Rulesets/Mods/RateAdjustModHelper.cs index 8a647dd25aef..4748182a85c8 100644 --- a/osu.Game/Rulesets/Mods/RateAdjustModHelper.cs +++ b/osu.Game/Rulesets/Mods/RateAdjustModHelper.cs @@ -14,6 +14,14 @@ public class RateAdjustModHelper : IApplicableToTrack { public readonly IBindableNumber SpeedChange; + private readonly BindableNumber speedChange = new BindableNumber(); + + /// + /// Use with mods containing . + /// When it set to true, speed change will be 1.0. + /// + public BindableBool DisableSpeedChange = new BindableBool(); + private IAdjustableAudioComponent? track; private BindableBool? adjustPitch; @@ -25,6 +33,14 @@ public class RateAdjustModHelper : IApplicableToTrack public RateAdjustModHelper(IBindableNumber speedChange) { SpeedChange = speedChange; + + SpeedChange.BindValueChanged(_ => updateSpeedChange(), true); + DisableSpeedChange.BindValueChanged(_ => updateSpeedChange(), true); + } + + private void updateSpeedChange() + { + speedChange.Value = DisableSpeedChange.Value ? 1 : SpeedChange.Value; } /// @@ -39,8 +55,8 @@ public void HandleAudioAdjustments(BindableBool adjustPitch) // When switching between pitch adjust, we need to update adjustments to time-shift or frequency-scale. adjustPitch.BindValueChanged(adjustPitchSetting => { - track?.RemoveAdjustment(adjustmentForPitchSetting(adjustPitchSetting.OldValue), SpeedChange); - track?.AddAdjustment(adjustmentForPitchSetting(adjustPitchSetting.NewValue), SpeedChange); + track?.RemoveAdjustment(adjustmentForPitchSetting(adjustPitchSetting.OldValue), speedChange); + track?.AddAdjustment(adjustmentForPitchSetting(adjustPitchSetting.NewValue), speedChange); AdjustableProperty adjustmentForPitchSetting(bool adjustPitchSettingValue) => adjustPitchSettingValue ? AdjustableProperty.Frequency : AdjustableProperty.Tempo; From 363ac8df96921abbed5bf26813892c5e7d05592d Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Tue, 21 Jul 2026 16:07:50 +0800 Subject: [PATCH 3/4] add test --- .../Visual/Mods/TestSceneModDisable.cs | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 osu.Game.Tests/Visual/Mods/TestSceneModDisable.cs diff --git a/osu.Game.Tests/Visual/Mods/TestSceneModDisable.cs b/osu.Game.Tests/Visual/Mods/TestSceneModDisable.cs new file mode 100644 index 000000000000..b16ef70f84a1 --- /dev/null +++ b/osu.Game.Tests/Visual/Mods/TestSceneModDisable.cs @@ -0,0 +1,55 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Framework.Testing; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Rulesets.UI; + +namespace osu.Game.Tests.Visual.Mods +{ + public partial class TestSceneModDisable : ModTestScene + { + protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); + + [Test] + public void TestDisableAvailableInReplay() + { + CreateModTest(new ModTestData + { + Autoplay = true, + Mod = new OsuModFlashlight(), + PassCondition = () => getMod().IsDisabled.Value, + }); + + clickMod(); + } + + [Test] + public void TestDisableAvailableNotInReplay() + { + CreateModTest(new ModTestData + { + Autoplay = false, + Mod = new OsuModFlashlight(), + PassCondition = () => !getMod().IsDisabled.Value, + }); + + clickMod(); + } + + private void clickMod() + where T : IAdjustableWhenReplay + { + AddStep("click mod", () => Player.ChildrenOfType().Single(icon => icon.Mod is T).TriggerClick()); + } + + private T getMod() + where T : IAdjustableWhenReplay + => (T)Player.ChildrenOfType().Single(icon => icon.Mod is T).Mod; + } +} From 086a62b7a87dcb78829b406490ce5b2b98579afa Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Tue, 21 Jul 2026 16:34:23 +0800 Subject: [PATCH 4/4] do not use OsuClickableContainer --- osu.Game/Rulesets/UI/ClickableModIcon.cs | 28 ++++++++++++++++++++++ osu.Game/Rulesets/UI/ModIcon.cs | 3 +-- osu.Game/Screens/Play/HUD/HudModDisplay.cs | 12 ++++------ osu.Game/Screens/Play/HUD/ModDisplay.cs | 24 ++++++++++--------- 4 files changed, 47 insertions(+), 20 deletions(-) create mode 100644 osu.Game/Rulesets/UI/ClickableModIcon.cs diff --git a/osu.Game/Rulesets/UI/ClickableModIcon.cs b/osu.Game/Rulesets/UI/ClickableModIcon.cs new file mode 100644 index 000000000000..a93cb6eab123 --- /dev/null +++ b/osu.Game/Rulesets/UI/ClickableModIcon.cs @@ -0,0 +1,28 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Game.Rulesets.Mods; +using osu.Framework.Input.Events; + +namespace osu.Game.Rulesets.UI +{ + /// + /// Display the specified mod at a fixed size. + /// + public partial class ClickableModIcon : ModIcon + { + public Action? Action; + + public ClickableModIcon(IMod mod, bool showTooltip = true, bool showExtendedInformation = true) + : base(mod, showTooltip, showExtendedInformation) + { + } + + protected override bool OnClick(ClickEvent e) + { + Action?.Invoke(); + return true; + } + } +} diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index 6b3ac7d36a97..79cf073a42be 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -13,7 +13,6 @@ using osu.Framework.Utils; using osu.Game.Configuration; using osu.Game.Graphics; -using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Overlays; using osu.Game.Rulesets.Mods; @@ -25,7 +24,7 @@ namespace osu.Game.Rulesets.UI /// /// Display the specified mod at a fixed size. /// - public partial class ModIcon : OsuClickableContainer, IHasCustomTooltip + public partial class ModIcon : Container, IHasCustomTooltip { public readonly BindableBool Selected = new BindableBool(); diff --git a/osu.Game/Screens/Play/HUD/HudModDisplay.cs b/osu.Game/Screens/Play/HUD/HudModDisplay.cs index b82dcd33a8a2..df2898257b68 100644 --- a/osu.Game/Screens/Play/HUD/HudModDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HudModDisplay.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; using osu.Framework.Bindables; using osu.Game.Graphics; using osu.Game.Rulesets.Mods; @@ -20,15 +19,12 @@ public HudModDisplay(Bindable replayLoaded, bool showExtendedInformation = this.replayLoaded.BindTo(replayLoaded); } - protected override void UpdateDisplay(ValueChangedEvent> mods) + protected override ModIcon CreateModIcon(Mod mod, bool showExtendedInformation) { - base.UpdateDisplay(mods); + var modIcon = new ClickableModIcon(mod, showExtendedInformation); - foreach (ModIcon modIcon in IconsContainer) + if (modIcon.Mod is IAdjustableWhenReplay dmod) { - if (modIcon.Mod is not IAdjustableWhenReplay dmod) - continue; - dmod.IsDisabled.BindValueChanged(_ => modIcon.Colour = dmod.IsDisabled.Value ? OsuColour.Gray(0.7f) : Color4.White, true); modIcon.Action = () => @@ -39,6 +35,8 @@ protected override void UpdateDisplay(ValueChangedEvent> mods dmod.IsDisabled.Toggle(); }; } + + return modIcon; } } } diff --git a/osu.Game/Screens/Play/HUD/ModDisplay.cs b/osu.Game/Screens/Play/HUD/ModDisplay.cs index fc2d357579c4..94d1ac835115 100644 --- a/osu.Game/Screens/Play/HUD/ModDisplay.cs +++ b/osu.Game/Screens/Play/HUD/ModDisplay.cs @@ -62,18 +62,18 @@ public bool ShowExtendedInformation set { showExtendedInformation = value; - foreach (var icon in IconsContainer) + foreach (var icon in iconsContainer) icon.ShowExtendedInformation = value; } } public FillDirection FillDirection { - get => IconsContainer.Direction; - set => IconsContainer.Direction = value; + get => iconsContainer.Direction; + set => iconsContainer.Direction = value; } - protected readonly FillFlowContainer IconsContainer; + private readonly FillFlowContainer iconsContainer; public ModDisplay(bool showExtendedInformation = true) { @@ -81,7 +81,7 @@ public ModDisplay(bool showExtendedInformation = true) AutoSizeAxes = Axes.Both; - InternalChild = IconsContainer = new ReverseChildIDFillFlowContainer + InternalChild = iconsContainer = new ReverseChildIDFillFlowContainer { AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, @@ -92,18 +92,20 @@ protected override void LoadComplete() { base.LoadComplete(); - Current.BindValueChanged(UpdateDisplay, true); + Current.BindValueChanged(updateDisplay, true); updateExpansionMode(0); } - protected virtual void UpdateDisplay(ValueChangedEvent> mods) + private void updateDisplay(ValueChangedEvent> mods) { - IconsContainer.Clear(); + iconsContainer.Clear(); foreach (Mod mod in mods.NewValue.AsOrdered()) - IconsContainer.Add(new ModIcon(mod, showExtendedInformation: showExtendedInformation) { Scale = new Vector2(MOD_ICON_SCALE) }); + iconsContainer.Add(CreateModIcon(mod, showExtendedInformation).With(m => m.Scale = new Vector2(MOD_ICON_SCALE))); } + protected virtual ModIcon CreateModIcon(Mod mod, bool showExtendedInformation) => new ModIcon(mod, showExtendedInformation); + private void updateExpansionMode(double duration = 500) { switch (expansionMode) @@ -128,13 +130,13 @@ private void updateExpansionMode(double duration = 500) private void expand(double duration = 500) { if (ExpansionMode != ExpansionMode.AlwaysContracted) - IconsContainer.TransformSpacingTo(new Vector2(5, -10), duration, Easing.OutQuint); + iconsContainer.TransformSpacingTo(new Vector2(5, -10), duration, Easing.OutQuint); } private void contract(double duration = 500) { if (ExpansionMode != ExpansionMode.AlwaysExpanded) - IconsContainer.TransformSpacingTo(new Vector2(-25), duration, Easing.OutQuint); + iconsContainer.TransformSpacingTo(new Vector2(-25), duration, Easing.OutQuint); } protected override bool OnHover(HoverEvent e)