Author Topic: UISlider OnValueChange events  (Read 7211 times)

Arcanor

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 0
  • Posts: 46
    • View Profile
UISlider OnValueChange events
« on: February 22, 2014, 11:14:32 PM »
I've got a UISlider, set to have some number of discrete steps.  When I drag the slider, why am I getting multiple OnValueChange events triggering, even if the drag doesn't actually change the UISlider's value to a new step?  How can I keep those events from triggering in all cases where the value hasn't actually changed?

Thanks!

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: UISlider OnValueChange events
« Reply #1 on: February 23, 2014, 12:19:37 PM »
The steps affect how the slider's value is retrieved, but the actual stored value of the slider may not match. The OnChange notification tells you that the internal value changed. Whether it affected the retrieved step-affected value is different.

Arcanor

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 0
  • Posts: 46
    • View Profile
Re: UISlider OnValueChange events
« Reply #2 on: February 23, 2014, 12:25:36 PM »
Thanks.  Okay, so then how can I only trigger events when the value steps up?  I don't want events happening for irrelevant changes.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: UISlider OnValueChange events
« Reply #3 on: February 23, 2014, 12:45:22 PM »
You retrieve the step-affected value via UIProgressBar.value, and whether it actually changed or not shouldn't matter. Why does it matter in your case?

Arcanor

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 0
  • Posts: 46
    • View Profile
Re: UISlider OnValueChange events
« Reply #4 on: February 23, 2014, 01:54:39 PM »
It matters because I'm using the slider to control a character avatar editor.  Every time the value changes I need to rebuild the avatar from its many various components, which is expensive.

I tried using the UIProgressBar.value as you suggested, but it still updates the same number of times.

I still don't understand why the value change event is triggered in this case.  The idea of a stepped value on the control implies that if the value doesn't change the event shouldn't be triggered.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: UISlider OnValueChange events
« Reply #5 on: February 23, 2014, 06:04:42 PM »
Change UIProgressBar.value function to this and it won't:
  1.         public float value
  2.         {
  3.                 get
  4.                 {
  5.                         if (numberOfSteps > 1) return Mathf.Round(mValue * (numberOfSteps - 1)) / (numberOfSteps - 1);
  6.                         return mValue;
  7.                 }
  8.                 set
  9.                 {
  10.                         float val = Mathf.Clamp01(value);
  11.  
  12.                         if (mValue != val)
  13.                         {
  14.                                 float before = this.value;
  15.                                 mValue = val;
  16.  
  17.                                 if (NGUITools.GetActive(this))
  18.                                 {
  19.                                         if (before != this.value)
  20.                                         {
  21.                                                 if (EventDelegate.IsValid(onChange))
  22.                                                 {
  23.                                                         current = this;
  24.                                                         EventDelegate.Execute(onChange);
  25.                                                         current = null;
  26.                                                 }
  27.                                                 ForceUpdate();
  28.                                         }
  29. #if UNITY_EDITOR
  30.                                         if (!Application.isPlaying)
  31.                                                 NGUITools.SetDirty(this);
  32. #endif
  33.                                 }
  34.                         }
  35.                 }
  36.         }

Arcanor

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 0
  • Posts: 46
    • View Profile
Re: UISlider OnValueChange events
« Reply #6 on: February 23, 2014, 09:29:47 PM »
Thanks Michael.  Your code almost worked, but failed due to floating point compare error.  Rounding fixed it.  I figured that since there can't be more than 20 steps, it was safe enough to compare after multiplying the floats by 1000 and then casting to int.  Here's the updated code FYI:

  1.     public float value
  2.     {
  3.         get
  4.         {
  5.             if (numberOfSteps > 1) return Mathf.Round(mValue * (numberOfSteps - 1)) / (numberOfSteps - 1);
  6.             return mValue;
  7.         }
  8.         set
  9.         {
  10.             float val = Mathf.Clamp01(value);
  11.  
  12.             if (mValue != val)
  13.             {
  14.                 int before = (int)Mathf.Round(this.value * 1000);
  15.                 mValue = val;
  16.  
  17.                 if (NGUITools.GetActive(this))
  18.                 {
  19.                     if (before != Mathf.Round(this.value * 1000))
  20.                     {
  21.                         if (EventDelegate.IsValid(onChange))
  22.                         {
  23.                             current = this;
  24.                             EventDelegate.Execute(onChange);
  25.                             current = null;
  26.                         }
  27.                         ForceUpdate();
  28.                     }
  29. #if UNITY_EDITOR
  30.                     if (!Application.isPlaying)
  31.                         NGUITools.SetDirty(this);
  32. #endif
  33.                 }
  34.             }
  35.         }
  36.     }
  37.