From 3edc428c3a084896ec6fcb4f09528cdd0668c0ef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 31 Mar 2026 19:42:42 +0900 Subject: [PATCH] Update resources --- osu.Game/Overlays/AfToggleSection.cs | 473 +++++++++++++++++++++++++++ osu.Game/Overlays/SettingsOverlay.cs | 9 +- osu.Game/osu.Game.csproj | 2 +- 3 files changed, 482 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Overlays/AfToggleSection.cs diff --git a/osu.Game/Overlays/AfToggleSection.cs b/osu.Game/Overlays/AfToggleSection.cs new file mode 100644 index 0000000000..b9a8d8fcf9 --- /dev/null +++ b/osu.Game/Overlays/AfToggleSection.cs @@ -0,0 +1,473 @@ +// 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 System.Collections.Generic; +using System.Linq; +using ManagedBass.Fx; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Framework.Localisation; +using osu.Framework.Platform; +using osu.Framework.Testing; +using osu.Framework.Threading; +using osu.Framework.Utils; +using osu.Game.Audio.Effects; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Input.Bindings; +using osu.Game.Overlays.Settings; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays +{ + public partial class AfToggleSection : SettingsSection + { + public override LocalisableString Header => "Toggles"; + + public override Drawable CreateIcon() => new SpriteIcon + { + Icon = FontAwesome.Regular.Dizzy, + }; + + [BackgroundDependencyLoader] + private void load() + { + Children = new Drawable[] + { + new ToggleSettings(), + }; + } + + public partial class ToggleSettings : SettingsSubsection + { + [Resolved] + private OsuGameBase game { get; set; } = null!; + + [Resolved] + private GameHost host { get; set; } = null!; + + [Resolved] + private MusicController musicController { get; set; } = null!; + + protected override LocalisableString Header => "You wanted toggles, we give you toggles"; + + private List words = new List(); + + private List>> heroActions = new List>>(); + + private readonly List tasks = new List(); + + private GlobalActionContainer target = null!; + + private AutoWahParameters autoWahParameters = null!; + private ChorusParameters chorusParameters = null!; + private PhaserParameters phaserParameters = null!; + private Bindable balanceAdjustment = null!; + + private Sprite? dvdLogo; + private Vector2 dvdLogoVelocity = new Vector2(0.005f); + + private ScheduledDelegate? dvdLogoMovement; + + private AudioManager audio = null!; + + private double lastUpdate; + + [Resolved] + private TextureStore textures { get; set; } = null!; + + [BackgroundDependencyLoader] + private void load() + { + autoWahParameters = new AutoWahParameters { fDryMix = 0.5f, fWetMix = 0.5f }; + chorusParameters = new ChorusParameters { fDryMix = 0.5f, fWetMix = 0.5f }; + phaserParameters = new PhaserParameters { fDryMix = 0.5f, fWetMix = 0.5f }; + balanceAdjustment = new Bindable(1); + + audio = game.Audio; + + target = game.ChildrenOfType().First(); + target.Anchor = Anchor.Centre; + target.Origin = Anchor.Centre; + + reset(); + } + + protected override void Update() + { + base.Update(); + + lastUpdate = Clock.CurrentTime; + + tasks.RemoveAll(t => t.Cancelled || t.Completed); + + if (tasks.Count > 40) + explode(); + } + + private void explode() + { + foreach (var t in tasks) + t.Cancel(); + + target.FadeColour(Color4.Black, 2000); + target.ScaleTo(1) + .ScaleTo(10, 4000); + + audio.Samples.Get("Gameplay/Argon/failsound-alt")?.Play(); + musicController.DuckMomentarily(2000, new DuckParameters + { + DuckDuration = 0, + DuckVolumeTo = 0, + DuckCutoffTo = AudioFilter.MAX_LOWPASS_CUTOFF, + RestoreDuration = 3000, + RestoreEasing = Easing.InQuint, + }); + + host.UpdateThread.Scheduler.AddDelayed(() => + { + foreach (var c in getCheckboxes()) + { + c.Current.Disabled = false; + c.Current.Value = false; + } + + target.FinishTransforms(); + target.ScaleTo(1) + .FadeColour(Color4.White, 2000, Easing.OutQuint); + + Schedule(() => + { + var settingsOverlay = game.ChildrenOfType().First(); + + settingsOverlay.SectionsContainer.ScrollTo(settingsOverlay.ChildrenOfType().Single()); + }); + + Clear(); + + AddRange(new Drawable[] + { + new OsuTextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + TextAnchor = Anchor.TopCentre, + Text = "..on second thought, no more toggles for you." + }, + new SettingsButtonV2 + { + Text = "But please peppy", + Action = () => + { + if (Children.Count < 5 || RNG.NextSingle() > 0.08f) + { + audio.Samples.Get("Gameplay/sectionfail")?.Play(); + Add(new OsuTextFlowContainer(p => p.Font = OsuFont.Default.With(size: RNG.Next(10, 30))) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + TextAnchor = Anchor.TopCentre, + Text = "no" + }); + } + else + { + audio.Samples.Get("Gameplay/sectionpass")?.Play(); + reset(); + } + } + } + }); + }, 3000); + } + + private void reset() + { + Clear(); + + words = new List( + [ + "toggle", "toggleability", "inversion", "momentum", "uncertainty", "viscosity", "gravity", "shyness", "peer pressure", "amnesia", "rebellion", "telepathy", "commitment issues", + "democracy", "entropy", "recursion", "quantum superposition", "paperclips", "stubbornness", "existentialism", "nostalgia", "anxiety", "procrastination", "synesthesia", + "narcissism", + "chaos", + "determinism", "nihilism", "optimism", "pessimism", "apathy", "enthusiasm", "seven twenty seven", "lethargy", "hyperactivity", "confusion", "clarity", "ambiguity", "precision", + "vagueness", + "specificity", "generality", "locality", "annihilation", "nonlocality", "causality", "acausality", "reversibility", "irreversibility", "coherence", "decoherence", "entanglement", + "disentanglement", "superposition" + ]); + + heroActions = new List>> + { + val => target.FadeColour(OsuColour.Gray(val.NewValue ? 0.5f : 1), 2500, Easing.OutPow10), + val => + { + if (val.NewValue) + { + target.ScaleTo(new Vector2(RNG.NextBool() ? -1 : 1, RNG.NextBool() ? -1 : 1)) + .Delay(1500) + .ScaleTo(Vector2.One); + } + }, + val => + { + if (val.NewValue) + { + target.FadeColour(new Color4( + (byte)RNG.Next(200, 255), + (byte)RNG.Next(200, 255), + (byte)RNG.Next(200, 255), + 255), 1500, Easing.OutQuint); + } + else + target.FadeColour(Color4.White, 2000); + }, + val => + { + if (val.NewValue) + target.RotateTo(RNG.NextSingle(-2f, 2f), 4000, Easing.InOutSine); + else + target.RotateTo(0, 4000, Easing.InOutSine); + }, + val => target.ScaleTo(val.NewValue ? 1.05f : 1f, 3000, Easing.OutQuint), + val => + { + if (val.NewValue) + target.ScaleTo(1.02f, 2000, Easing.InOutSine).Then().ScaleTo(0.98f, 2000, Easing.InOutSine).Loop(); + else + target.ScaleTo(1f, 1000); + }, + val => + { + if (val.NewValue) + { + var colours = new[] { new Color4(255, 230, 230, 255), new Color4(230, 255, 230, 255), new Color4(230, 230, 255, 255) }; + target.FadeColour(colours[RNG.Next(0, colours.Length)], 300).Loop(); + } + else + target.FadeColour(Color4.White, 3000); + }, + val => + { + if (val.NewValue) + target.MoveToX(10, 500, Easing.OutQuad).Then().MoveToY(0, 500, Easing.InQuad); + }, + val => + { + if (val.NewValue) + target.MoveToY(-10, 500, Easing.OutQuad).Then().MoveToY(0, 500, Easing.InQuad); + }, + _ => game.ChildrenOfType().FirstOrDefault()?.ToggleVisibility(), + val => + { + if (val.NewValue) + audio.TrackMixer.AddEffect(chorusParameters); + else + audio.TrackMixer.RemoveEffect(chorusParameters); + }, + val => + { + if (val.NewValue) + audio.TrackMixer.AddEffect(autoWahParameters); + else + audio.TrackMixer.RemoveEffect(autoWahParameters); + }, + val => + { + if (val.NewValue) + audio.TrackMixer.AddEffect(phaserParameters); + else + audio.TrackMixer.RemoveEffect(phaserParameters); + }, + + // game blinks at you + val => + { + if (val.NewValue) + { + target.ScaleTo(new Vector2(1, 0), 50, Easing.OutQuint) + .Then().ScaleTo(Vector2.One, 50, Easing.OutQuint); + } + }, + + // messing with balance + val => + { + if (val.NewValue) + { + audio.AddAdjustment(AdjustableProperty.Balance, balanceAdjustment); + this.TransformBindableTo(balanceAdjustment, 0.3f, 5_000) + .Then().TransformBindableTo(balanceAdjustment, 0.7f, 10_000) + .Then().TransformBindableTo(balanceAdjustment, 0.5f, 5_000) + .Loop(); + } + else + { + audio.RemoveAdjustment(AdjustableProperty.Balance, balanceAdjustment); + } + }, + + // do a barrel roll! (press Z or R twice) + val => + { + if (val.NewValue) + { + target.RotateTo(360, 1000) + .Then().RotateTo(0); + } + }, + val => + { + if (val.NewValue) + { + if (dvdLogo == null) + { + target.Add(dvdLogo = new Sprite + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Depth = float.MinValue, + Size = new Vector2(30), + Texture = textures.Get(@"Menu/logo"), + RelativePositionAxes = Axes.Both, + Position = new Vector2(RNG.NextSingle(), RNG.NextSingle()), + Alpha = 0, + }); + } + + dvdLogo.Alpha = 1; + dvdLogoMovement = host.UpdateThread.Scheduler.AddDelayed(() => + { + var logoPosition = dvdLogo.ScreenSpaceDrawQuad; + var bounds = target.ScreenSpaceDrawQuad; + + if (logoPosition.TopLeft.X < bounds.TopLeft.X) + dvdLogoVelocity = new Vector2(0.005f, dvdLogoVelocity.Y); + else if (logoPosition.BottomRight.X > bounds.BottomRight.X) + dvdLogoVelocity = new Vector2(-0.005f, dvdLogoVelocity.Y); + + if (logoPosition.TopLeft.Y < bounds.TopLeft.Y) + dvdLogoVelocity = new Vector2(dvdLogoVelocity.X, 0.005f); + else if (logoPosition.BottomRight.Y > bounds.BottomRight.Y) + dvdLogoVelocity = new Vector2(dvdLogoVelocity.X, -0.005f); + + dvdLogo.Position += dvdLogoVelocity; + }, 15, true); + } + else + { + dvdLogo?.Hide(); + dvdLogoMovement?.Cancel(); + } + }, + val => + { + if (val.NewValue) + { + string[] samples = + [ + "Keyboard/key-caps.mp3", + "Keyboard/key-confirm.mp3", + "Keyboard/key-delete.mp3", + "Keyboard/key-movement.mp3", + "Keyboard/key-press-1.mp3", + "Keyboard/key-press-2.mp3", + "Keyboard/key-press-3.mp3", + "Keyboard/key-press-4.mp3", + "Keyboard/deselect.wav", + "Keyboard/key-invalid.wav", + "Keyboard/select-all.wav", + "Keyboard/select-char.wav", + "Keyboard/select-word.wav" + ]; + + var repeat = Scheduler.AddDelayed(() => + { + audio.Samples.Get(samples[RNG.Next(0, samples.Length)])?.Play(); + }, 100, true); + + Scheduler.AddDelayed(repeat.Cancel, 1000); + } + } + }; + + addNewToggle(); + } + + private void doRandomThing() + { + // avoid runaway if settings panel closes + if (Math.Abs(Clock.CurrentTime - lastUpdate) > 100) + return; + + tasks.Add(host.UpdateThread.Scheduler.AddDelayed(() => + { + var formCheckBoxes = getCheckboxes(); + + if (heroActions.Count > 0 && RNG.NextSingle() > 0.5f) + { + addNewToggle(); + return; + } + + foreach (var c in formCheckBoxes.Take(Math.Max(1, formCheckBoxes.Length / 8))) + { + if (RNG.NextSingle() > 0.5f && formCheckBoxes.Count(b => !b.Current.Disabled) > 5) + c.Current.Disabled = !c.Current.Disabled; + + if (c.Current.Disabled && RNG.NextSingle() > 0.4f) + c.Current.Disabled = false; + + if (RNG.NextSingle() > 0.3f) + c.TriggerClick(); + } + }, RNG.Next(400, 2000))); + } + + private FormCheckBox[] getCheckboxes() => + Children.OfType().Select(s => s.Control) + .OfType() + .OrderBy(_ => RNG.Next(-1, 1)) + .ToArray(); + + private void addNewToggle() + { + if (words.Count == 0) + return; + + FormCheckBox checkbox; + + string word = words[RNG.Next(0, words.Count)]; + words.Remove(word); + + Add(new SettingsItemV2(checkbox = new FormCheckBox + { + Caption = $"Toggle {word}" + }) + { + Depth = RNG.NextSingle(), + }); + + checkbox.Current.BindValueChanged(val => + { + if (val.NewValue) + doRandomThing(); + }); + + if (RNG.NextSingle() > 0.6f) + { + int i = RNG.Next(0, heroActions.Count); + checkbox.Current.BindValueChanged(heroActions[i]); + heroActions.RemoveAt(i); + } + } + } + } +} diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index 3065a4d1bd..e625afe941 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -3,6 +3,7 @@ #nullable disable +using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -30,7 +31,7 @@ namespace osu.Game.Overlays protected override IEnumerable CreateSections() { - return new List + var sections = new List { // This list should be kept in sync with ScreenBehaviour. new GeneralSection(), @@ -45,6 +46,12 @@ namespace osu.Game.Overlays new MaintenanceSection(), new DebugSection() }; + + var today = DateTimeOffset.Now; + if (today.Month == 4 && today.Day == 1) + sections.Insert(9, new AfToggleSection()); + + return sections; } private readonly List subPanels = new List(); diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 4ca602fcf9..8850de3a7c 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -40,7 +40,7 @@ - +