11# ruff: noqa: D103
22from __future__ import annotations
33
4+ import math
45import re
56from typing import TYPE_CHECKING , Any
67
78import unrealsdk
9+ from unrealsdk import logging
810from unrealsdk .hooks import Block , Type
9- from unrealsdk .unreal import BoundFunction , UFunction , UObject , WrappedStruct
11+ from unrealsdk .unreal import BoundFunction , UFunction , UObject , WeakPointer , WrappedStruct
1012
1113from mods_base import Mod , NestedOption , hook , html_to_plain_text
1214
@@ -189,6 +191,9 @@ def get_selected_idx(menu: WillowGFxMenu) -> int | None:
189191 return None
190192
191193
194+ slider_spinner_next_tick_info : tuple [WeakPointer , str , Populator , int ] | None = None
195+
196+
192197# Similarly to the lobby menu, we need to use sounds to detect when you click an option/adjust a
193198# slider, since we can't safely pass callback names to ActionScript
194199@hook ("GearboxFramework.GearboxGFxMovie:PlaySpecialUISound" )
@@ -210,9 +215,44 @@ def play_sound(
210215
211216 if args .SoundString == "Confirm" :
212217 populator .on_activate (obj , idx )
218+ return
219+
220+ # Sliders have the same problem as in the lobby movie, for kb input they plays the sound after
221+ # updating the value, and we could run our callbacks here, but for mouse input they play the
222+ # sound before. Wait for next tick before updating.
223+
224+ # Save a bunch of data we already have
225+ global slider_spinner_next_tick_info
226+ slider_spinner_next_tick_info = (
227+ WeakPointer (obj ),
228+ find_focused_item (obj ) + ".mValue" ,
229+ populator ,
230+ idx ,
231+ )
232+
233+ slider_spinner_next_tick .enable ()
234+
235+
236+ @hook ("WillowGame.WillowUIInteraction:TickImp" )
237+ def slider_spinner_next_tick (* _ : Any ) -> None :
238+ slider_spinner_next_tick .disable ()
239+
240+ global slider_spinner_next_tick_info
241+ if slider_spinner_next_tick_info is None :
242+ return
243+ weak_menu , path , populator , idx = slider_spinner_next_tick_info
244+ slider_spinner_next_tick_info = None
245+
246+ if (menu := weak_menu ()) is None :
247+ return
248+ value = menu .GetVariableNumber (path )
249+
250+ if math .isnan (value ):
251+ # We really don't want to set an option's value to NaN since it becomes essentially
252+ # unrecoverable without manually editing settings
253+ logging .error ("Got NaN after changing spinner/slide!" )
213254 else :
214- value = obj .GetVariableNumber (find_focused_item (obj ) + ".Value" )
215- populator .on_slider_spinner_change (obj , idx , value )
255+ populator .on_slider_spinner_change (menu , idx , value )
216256
217257
218258@hook ("WillowGame.WillowGFxMenuScreenGeneric:Screen_Deactivate" , immediately_enable = True )
0 commit comments