11// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
22// See the LICENCE file in the repository root for full licence text.
33
4- #nullable disable
54using System ;
65using System . Collections . Generic ;
76using System . Linq ;
8- using JetBrains . Annotations ;
97using ManagedBass . Fx ;
108using osu . Framework . Allocation ;
119using osu . Framework . Audio ;
1816using osu . Framework . Testing ;
1917using osu . Framework . Threading ;
2018using osu . Framework . Utils ;
19+ using osu . Game . Audio . Effects ;
2120using osu . Game . Graphics ;
2221using osu . Game . Graphics . Containers ;
2322using osu . Game . Graphics . UserInterfaceV2 ;
@@ -49,60 +48,54 @@ private void load()
4948 public partial class ToggleSettings : SettingsSubsection
5049 {
5150 [ Resolved ]
52- private OsuGameBase game { get ; set ; }
51+ private OsuGameBase game { get ; set ; } = null ! ;
5352
5453 [ Resolved ]
55- private GameHost host { get ; set ; }
54+ private GameHost host { get ; set ; } = null ! ;
55+
56+ [ Resolved ]
57+ private MusicController musicController { get ; set ; } = null ! ;
5658
5759 protected override LocalisableString Header => "You wanted toggles, we give you toggles" ;
5860
5961 private List < string > words = new List < string > ( ) ;
6062
61- private List < Action < ValueChangedEvent < bool > > > heroActions ;
63+ private List < Action < ValueChangedEvent < bool > > > heroActions = new List < Action < ValueChangedEvent < bool > > > ( ) ;
6264
6365 private readonly List < ScheduledDelegate > tasks = new List < ScheduledDelegate > ( ) ;
6466
65- private GlobalActionContainer target ;
67+ private GlobalActionContainer target = null ! ;
6668
67- private AutoWahParameters autoWahParameters ;
68- private ChorusParameters chorusParameters ;
69- private PhaserParameters phaserParameters ;
70- private Bindable < double > balanceAdjustment ;
69+ private AutoWahParameters autoWahParameters = null ! ;
70+ private ChorusParameters chorusParameters = null ! ;
71+ private PhaserParameters phaserParameters = null ! ;
72+ private Bindable < double > balanceAdjustment = null ! ;
7173
72- private Sprite dvdLogo ;
74+ private Sprite ? dvdLogo ;
7375 private Vector2 dvdLogoVelocity = new Vector2 ( 0.005f ) ;
7476
75- [ CanBeNull ]
76- private ScheduledDelegate dvdLogoMovement ;
77+ private ScheduledDelegate ? dvdLogoMovement ;
7778
78- private AudioManager audio ;
79+ private AudioManager audio = null ! ;
80+
81+ private double lastUpdate ;
82+
83+ [ Resolved ]
84+ private TextureStore textures { get ; set ; } = null ! ;
7985
8086 [ BackgroundDependencyLoader ]
81- private void load ( TextureStore textures )
87+ private void load ( )
8288 {
8389 autoWahParameters = new AutoWahParameters { fDryMix = 0.5f , fWetMix = 0.5f } ;
8490 chorusParameters = new ChorusParameters { fDryMix = 0.5f , fWetMix = 0.5f } ;
8591 phaserParameters = new PhaserParameters { fDryMix = 0.5f , fWetMix = 0.5f } ;
8692 balanceAdjustment = new Bindable < double > ( 1 ) ;
8793
88- dvdLogo = new Sprite
89- {
90- Anchor = Anchor . Centre ,
91- Origin = Anchor . Centre ,
92- Depth = float . MinValue ,
93- Size = new Vector2 ( 30 ) ,
94- Texture = textures . Get ( @"Menu/logo" ) ,
95- RelativePositionAxes = Axes . Both ,
96- Position = new Vector2 ( RNG . NextSingle ( ) , RNG . NextSingle ( ) ) ,
97- Alpha = 0 ,
98- } ;
99-
10094 audio = game . Audio ;
10195
10296 target = game . ChildrenOfType < GlobalActionContainer > ( ) . First ( ) ;
10397 target . Anchor = Anchor . Centre ;
10498 target . Origin = Anchor . Centre ;
105- Schedule ( ( ) => target . Add ( dvdLogo ) ) ;
10699
107100 reset ( ) ;
108101 }
@@ -111,70 +104,88 @@ protected override void Update()
111104 {
112105 base . Update ( ) ;
113106
107+ lastUpdate = Clock . CurrentTime ;
108+
114109 tasks . RemoveAll ( t => t . Cancelled || t . Completed ) ;
115110
116111 if ( tasks . Count > 40 )
112+ explode ( ) ;
113+ }
114+
115+ private void explode ( )
116+ {
117+ foreach ( var t in tasks )
118+ t . Cancel ( ) ;
119+
120+ target . FadeColour ( Color4 . Black , 2000 ) ;
121+ target . ScaleTo ( 1 )
122+ . ScaleTo ( 10 , 4000 ) ;
123+
124+ audio . Samples . Get ( "Gameplay/Argon/failsound-alt" ) ? . Play ( ) ;
125+ musicController . DuckMomentarily ( 2000 , new DuckParameters
117126 {
118- foreach ( var t in tasks )
119- t . Cancel ( ) ;
127+ DuckDuration = 0 ,
128+ DuckVolumeTo = 0 ,
129+ DuckCutoffTo = AudioFilter . MAX_LOWPASS_CUTOFF ,
130+ RestoreDuration = 3000 ,
131+ RestoreEasing = Easing . InQuint ,
132+ } ) ;
120133
121- target . FadeColour ( Color4 . Black , 2000 ) ;
134+ host . UpdateThread . Scheduler . AddDelayed ( ( ) =>
135+ {
136+ foreach ( var c in getCheckboxes ( ) )
137+ {
138+ c . Current . Disabled = false ;
139+ c . Current . Value = false ;
140+ }
141+
142+ target . FinishTransforms ( ) ;
122143 target . ScaleTo ( 1 )
123- . ScaleTo ( 10 , 4000 ) ;
144+ . FadeColour ( Color4 . White , 2000 , Easing . OutQuint ) ;
124145
125- host . UpdateThread . Scheduler . AddDelayed ( ( ) =>
146+ Schedule ( ( ) =>
126147 {
127- foreach ( var c in getCheckboxes ( ) )
128- {
129- c . Current . Disabled = false ;
130- c . Current . Value = false ;
131- }
148+ var settingsOverlay = game . ChildrenOfType < SettingsOverlay > ( ) . First ( ) ;
132149
133- target . FinishTransforms ( ) ;
134- target . ScaleTo ( 1 )
135- . FadeColour ( Color4 . White , 2000 , Easing . OutQuint ) ;
150+ settingsOverlay . SectionsContainer . ScrollTo ( settingsOverlay . ChildrenOfType < AfToggleSection > ( ) . Single ( ) ) ;
151+ } ) ;
136152
137- Clear ( ) ;
153+ Clear ( ) ;
138154
139- AddRange ( new Drawable [ ]
155+ AddRange ( new Drawable [ ]
156+ {
157+ new OsuTextFlowContainer
140158 {
141- new OsuTextFlowContainer
142- {
143- RelativeSizeAxes = Axes . X ,
144- AutoSizeAxes = Axes . Y ,
145- TextAnchor = Anchor . TopCentre ,
146- Text = "..on second thought, no more toggles for you."
147- } ,
148- new SettingsButtonV2
159+ RelativeSizeAxes = Axes . X ,
160+ AutoSizeAxes = Axes . Y ,
161+ TextAnchor = Anchor . TopCentre ,
162+ Text = "..on second thought, no more toggles for you."
163+ } ,
164+ new SettingsButtonV2
165+ {
166+ Text = "But please peppy" ,
167+ Action = ( ) =>
149168 {
150- Text = "But please peppy" ,
151- Action = ( ) =>
169+ if ( Children . Count < 5 || RNG . NextSingle ( ) > 0.08f )
152170 {
153- if ( Children . Count < 5 || RNG . NextSingle ( ) > 0.08f )
154- {
155- Add ( new OsuTextFlowContainer ( p => p . Font = OsuFont . Default . With ( size : RNG . Next ( 10 , 30 ) ) )
156- {
157- RelativeSizeAxes = Axes . X ,
158- AutoSizeAxes = Axes . Y ,
159- TextAnchor = Anchor . TopCentre ,
160- Text = "no"
161- } ) ;
162- }
163- else
171+ audio . Samples . Get ( "Gameplay/sectionfail" ) ? . Play ( ) ;
172+ Add ( new OsuTextFlowContainer ( p => p . Font = OsuFont . Default . With ( size : RNG . Next ( 10 , 30 ) ) )
164173 {
165- reset ( ) ;
166- host . UpdateThread . Scheduler . AddDelayed ( ( ) =>
167- {
168- // TODO: fix scroll not working..
169- var settingsOverlay = game . ChildrenOfType < SettingsOverlay > ( ) . First ( ) ;
170- settingsOverlay . SectionsContainer . ScrollTo ( settingsOverlay . ChildrenOfType < AfToggleSection > ( ) . Single ( ) ) ;
171- } , 500 ) ;
172- }
174+ RelativeSizeAxes = Axes . X ,
175+ AutoSizeAxes = Axes . Y ,
176+ TextAnchor = Anchor . TopCentre ,
177+ Text = "no"
178+ } ) ;
179+ }
180+ else
181+ {
182+ audio . Samples . Get ( "Gameplay/sectionpass" ) ? . Play ( ) ;
183+ reset ( ) ;
173184 }
174185 }
175- } ) ;
176- } , 3000 ) ;
177- }
186+ }
187+ } ) ;
188+ } , 3000 ) ;
178189 }
179190
180191 private void reset ( )
@@ -316,8 +327,23 @@ private void reset()
316327 {
317328 if ( val . NewValue )
318329 {
330+ if ( dvdLogo == null )
331+ {
332+ target . Add ( dvdLogo = new Sprite
333+ {
334+ Anchor = Anchor . Centre ,
335+ Origin = Anchor . Centre ,
336+ Depth = float . MinValue ,
337+ Size = new Vector2 ( 30 ) ,
338+ Texture = textures . Get ( @"Menu/logo" ) ,
339+ RelativePositionAxes = Axes . Both ,
340+ Position = new Vector2 ( RNG . NextSingle ( ) , RNG . NextSingle ( ) ) ,
341+ Alpha = 0 ,
342+ } ) ;
343+ }
344+
319345 dvdLogo . Alpha = 1 ;
320- dvdLogoMovement = Scheduler . AddDelayed ( ( ) =>
346+ dvdLogoMovement = host . UpdateThread . Scheduler . AddDelayed ( ( ) =>
321347 {
322348 var logoPosition = dvdLogo . ScreenSpaceDrawQuad ;
323349 var bounds = target . ScreenSpaceDrawQuad ;
@@ -337,37 +363,73 @@ private void reset()
337363 }
338364 else
339365 {
340- dvdLogo . Alpha = 0 ;
366+ dvdLogo ? . Hide ( ) ;
341367 dvdLogoMovement ? . Cancel ( ) ;
342368 }
369+ } ,
370+ val =>
371+ {
372+ if ( val . NewValue )
373+ {
374+ string [ ] samples =
375+ [
376+ "Keyboard/key-caps.mp3" ,
377+ "Keyboard/key-confirm.mp3" ,
378+ "Keyboard/key-delete.mp3" ,
379+ "Keyboard/key-movement.mp3" ,
380+ "Keyboard/key-press-1.mp3" ,
381+ "Keyboard/key-press-2.mp3" ,
382+ "Keyboard/key-press-3.mp3" ,
383+ "Keyboard/key-press-4.mp3" ,
384+ "Keyboard/deselect.wav" ,
385+ "Keyboard/key-invalid.wav" ,
386+ "Keyboard/select-all.wav" ,
387+ "Keyboard/select-char.wav" ,
388+ "Keyboard/select-word.wav"
389+ ] ;
390+
391+ var repeat = Scheduler . AddDelayed ( ( ) =>
392+ {
393+ audio . Samples . Get ( samples [ RNG . Next ( 0 , samples . Length ) ] ) ? . Play ( ) ;
394+ } , 100 , true ) ;
395+
396+ Scheduler . AddDelayed ( repeat . Cancel , 1000 ) ;
397+ }
343398 }
344399 } ;
345400
346401 addNewToggle ( ) ;
347402 }
348403
349- private void doRandomThing ( ) => tasks . Add ( host . UpdateThread . Scheduler . AddDelayed ( ( ) =>
404+ private void doRandomThing ( )
350405 {
351- var formCheckBoxes = getCheckboxes ( ) ;
352-
353- if ( heroActions . Count > 0 && RNG . NextSingle ( ) > 0.5f )
354- {
355- addNewToggle ( ) ;
406+ // avoid runaway if settings panel closes
407+ if ( Math . Abs ( Clock . CurrentTime - lastUpdate ) > 100 )
356408 return ;
357- }
358409
359- foreach ( var c in formCheckBoxes . Take ( Math . Max ( 1 , formCheckBoxes . Length / 8 ) ) )
410+ tasks . Add ( host . UpdateThread . Scheduler . AddDelayed ( ( ) =>
360411 {
361- if ( RNG . NextSingle ( ) > 0.5f && formCheckBoxes . Count ( b => ! b . Current . Disabled ) > 5 )
362- c . Current . Disabled = ! c . Current . Disabled ;
412+ var formCheckBoxes = getCheckboxes ( ) ;
363413
364- if ( c . Current . Disabled && RNG . NextSingle ( ) > 0.4f )
365- c . Current . Disabled = false ;
414+ if ( heroActions . Count > 0 && RNG . NextSingle ( ) > 0.5f )
415+ {
416+ addNewToggle ( ) ;
417+ return ;
418+ }
366419
367- if ( RNG . NextSingle ( ) > 0.3f )
368- c . TriggerClick ( ) ;
369- }
370- } , RNG . Next ( 400 , 2000 ) ) ) ;
420+ foreach ( var c in formCheckBoxes . Take ( Math . Max ( 1 , formCheckBoxes . Length / 8 ) ) )
421+ {
422+ if ( RNG . NextSingle ( ) > 0.5f && formCheckBoxes . Count ( b => ! b . Current . Disabled ) > 5 )
423+ c . Current . Disabled = ! c . Current . Disabled ;
424+
425+ if ( c . Current . Disabled && RNG . NextSingle ( ) > 0.4f )
426+ c . Current . Disabled = false ;
427+
428+ if ( RNG . NextSingle ( ) > 0.3f )
429+ c . TriggerClick ( ) ;
430+ }
431+ } , RNG . Next ( 400 , 2000 ) ) ) ;
432+ }
371433
372434 private FormCheckBox [ ] getCheckboxes ( ) =>
373435 Children . OfType < SettingsItemV2 > ( ) . Select ( s => s . Control )
0 commit comments