andrewgu / ModConfigMenu

XCOM 2 Mod Config Menu: a project to build a shared settings menu for Xcom 2 mods.
11 stars 13 forks source link

MCM_Slider.SetBounds sometimes misplaces slider knob when changing step size. #22

Closed andrewgu closed 8 years ago

andrewgu commented 8 years ago

This is a weird one. MCM_Slider uses UISlider to do its slider rendering. UISlider.SetStepSize() seems to jump the slider knob to one full step from the left edge regardless of the current value/position of the slider knob.

The fix seems to be to set the value both before and after calling SetStepSize(). However, this seems to fail on rare occasions, not reliably reproduced.

Even though the knob is visually misplaced, the correct value is still stored, so if the value was originally 100 with a min of 0 and max of 100 and step of 20, even though the knob looks like it's at 20, hitting the right arrow won't do anything and hitting the left arrow will move the knob to 80.

Seems to me like UISlider.SetStepSize() is just bugged, but this does in turn affect MCM_Slider's behavior.

andrewgu commented 8 years ago

Extra note for the record: currently MCM_Slider gets around this using a magic incantation. It works the vast majority of the time, but I have no idea why this one seems to work better than other magic incantations.

andrewgu commented 8 years ago

Finally found the real problem!

Two-fold fix. The first is piggybacking on the "after the slider is visible" event to update the slider position again once the viewer is seeing it.

The bigger issue is that UISlider.SetStepSize seems to always move the slider to one step above the minimum value. A subsequent call to UISlider.SetPercent doesn't seem to work unless it's changing the actual position (not the wrong one-step-above-minimum position).

So the new magical incantation to work around this problem is, after calling SetStepSize, to call SetPercent on two arbitrary but distinct positions, before calling for the actual position where you want the slider to go. I chose 1 and 100 (min and max) in the code, but I don't think it has to be those two.

Going to bundle this in an update.