]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/menu/item/slider.qc
Enable log timestamps during serverbench.
[xonotic/xonotic-data.pk3dir.git] / qcsrc / menu / item / slider.qc
1 #include "slider.qh"
2
3 #include "../anim/easing.qh"
4 #include "../anim/animhost.qh"
5
6 .entity applyButton;
7
8         void Slider_setValue_allowAnim(entity me, float val, bool allowAnim)
9         {
10                 if (allowAnim && me.animated)
11                 {
12                         float t = 0.5;
13                         if (!me.sliderAnim) me.sliderAnim = makeHostedEasing(me, Slider_setSliderValue, easingQuadOut, t, me.sliderValue, val);
14                         else me.sliderAnim.update(me.sliderAnim, t, me.sliderValue, val);
15                 }
16                 else
17                 {
18                         me.setSliderValue(me, val);
19                 }
20                 me.value = val;
21         }
22         void Slider_setValue_noAnim(entity me, float val)
23         {
24                 Slider_setValue_allowAnim(me, val, false);
25         }
26         void Slider_setValue(entity me, float val)
27         {
28                 Slider_setValue_allowAnim(me, val, true);
29         }
30         void Slider_setSliderValue(entity me, float val)
31         {
32                 me.sliderValue = val;
33         }
34         string Slider_toString(entity me)
35         {
36                 return sprintf("%d (%s)", me.value, me.valueToText(me, me.value));
37         }
38         void Slider_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
39         {
40                 SUPER(Slider).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
41                 me.controlWidth = absSize.x == 0 ? 0 : (absSize.y / absSize.x);
42         }
43         string Slider_valueToText(entity me, float val)
44         {
45                 if (almost_in_bounds(me.valueMin, val, me.valueMax)) return ftos_decimals(val * me.valueDisplayMultiplier, me.valueDigits);
46                 return "";
47         }
48         void Slider_configureSliderVisuals(entity me, float sz, float theAlign, float theTextSpace, string gfx)
49         {
50                 SUPER(Slider).configureLabel(me, string_null, sz, theAlign);
51                 me.textSpace = theTextSpace;
52                 me.keepspaceLeft = (theTextSpace == 0) ? 0 : (1 - theTextSpace);
53                 me.src = gfx;
54         }
55         void Slider_configureSliderValues(entity me, float theValueMin, float theValue, float theValueMax, float theValueStep, float theValueKeyStep, float theValuePageStep)
56         {
57                 me.value = theValue;
58                 me.sliderValue = theValue;
59                 me.valueStep = theValueStep;
60                 me.valueMin = theValueMin;
61                 me.valueMax = theValueMax;
62                 me.valueKeyStep = theValueKeyStep;
63                 me.valuePageStep = theValuePageStep;
64                 me.valueDigits = 3;
65                 if (fabs(floor(me.valueStep * 100 + 0.5) - (me.valueStep * 100)) < 0.01) // about a whole number of 100ths
66                         me.valueDigits = 2;
67                 if (fabs(floor(me.valueStep * 10 + 0.5) - (me.valueStep * 10)) < 0.01)   // about a whole number of 10ths
68                         me.valueDigits = 1;
69                 if (fabs(floor(me.valueStep * 1 + 0.5) - (me.valueStep * 1)) < 0.01)     // about a whole number
70                         me.valueDigits = 0;
71         }
72         float Slider_keyDown(entity me, float key, float ascii, float shift)
73         {
74                 float inRange;
75                 float ret_value = 0;
76                 if (me.disabled) return 0;
77                 inRange = (almost_in_bounds(me.valueMin, me.value, me.valueMax));
78                 if (key == K_LEFTARROW || key == K_KP_LEFTARROW || key == K_MWHEELDOWN)
79                 {
80                         if (inRange) me.setValue(me, median(me.valueMin, me.value - me.valueKeyStep, me.valueMax));
81                         else me.setValue(me, me.valueMax);
82                         ret_value = 1;
83                 }
84                 if (key == K_RIGHTARROW || key == K_KP_RIGHTARROW || key == K_MWHEELUP)
85                 {
86                         if (inRange) me.setValue(me, median(me.valueMin, me.value + me.valueKeyStep, me.valueMax));
87                         else me.setValue(me, me.valueMin);
88                         ret_value = 1;
89                 }
90                 if (key == K_PGDN || key == K_KP_PGDN)
91                 {
92                         if (inRange) me.setValue(me, median(me.valueMin, me.value - me.valuePageStep, me.valueMax));
93                         else me.setValue(me, me.valueMax);
94                         ret_value = 1;
95                 }
96                 if (key == K_PGUP || key == K_KP_PGUP)
97                 {
98                         if (inRange) me.setValue(me, median(me.valueMin, me.value + me.valuePageStep, me.valueMax));
99                         else me.setValue(me, me.valueMin);
100                         ret_value = 1;
101                 }
102                 if (key == K_HOME || key == K_KP_HOME)
103                 {
104                         me.setValue(me, me.valueMin);
105                         ret_value = 1;
106                 }
107                 if (key == K_END || key == K_KP_END)
108                 {
109                         me.setValue(me, me.valueMax);
110                         ret_value = 1;
111                 }
112                 if(ret_value == 1)
113                 {
114                         if(me.applyButton)
115                                 me.applyButton.disabled = false;
116                         return 1;
117                 }
118                 // TODO more keys (NOTE also add them to Slider_keyUp)
119                 return 0;
120         }
121         float Slider_keyUp(entity me, float key, float ascii, float shift)
122         {
123                 if (me.disabled) return 0;
124                 switch (key)
125                 {
126                         case K_LEFTARROW:
127                         case K_KP_LEFTARROW:
128                         case K_RIGHTARROW:
129                         case K_KP_RIGHTARROW:
130                         case K_PGUP:
131                         case K_KP_PGUP:
132                         case K_PGDN:
133                         case K_KP_PGDN:
134                         case K_HOME:
135                         case K_KP_HOME:
136                         case K_END:
137                         case K_KP_END:
138                                 m_play_click_sound(MENU_SOUND_SLIDE);
139                 }
140                 return 0;
141         }
142         float Slider_mouseDrag(entity me, vector pos)
143         {
144                 float hit;
145                 float v;
146                 if (me.disabled) return 0;
147
148                 if (me.pressed)
149                 {
150                         hit = 1;
151                         if (pos.x < 0 - me.tolerance.x) hit = 0;
152                         if (pos.y < 0 - me.tolerance.y) hit = 0;
153                         if (pos.x >= 1 - me.textSpace + me.tolerance.x) hit = 0;
154                         if (pos.y >= 1 + me.tolerance.y) hit = 0;
155                         if (hit)
156                         {
157                                 // handle dragging
158                                 me.pressed = 2;
159
160                                 float f = bound(0, (pos.x - me.pressOffset - 0.5 * me.controlWidth) / (1 - me.textSpace - me.controlWidth), 1);
161                                 v = f * (me.valueMax - me.valueMin) + me.valueMin;
162                                 // there's no need to round min and max value... also if we did, v could be set
163                                 // to an out of bounds value due to precision errors
164                                 if (f > 0 && f < 1 && me.valueStep)
165                                         v = floor(0.5 + v / me.valueStep) * me.valueStep;
166                                 me.setValue_noAnim(me, v);
167                                 if(me.applyButton)
168                                 if(me.previousValue != me.value)
169                                         me.applyButton.disabled = false;
170                         }
171                         else
172                         {
173                                 me.setValue(me, me.previousValue);
174                         }
175                 }
176
177                 return 1;
178         }
179         METHOD(Slider, mousePress, bool(Slider this, vector pos))
180         {
181                 float controlCenter;
182                 if (this.disabled) return false;
183                 if (pos.x < 0) return false;
184                 if (pos.y < 0) return false;
185                 if (pos.x >= 1 - this.textSpace) return false;
186                 if (pos.y >= 1) return false;
187                 controlCenter = (this.value - this.valueMin) / (this.valueMax - this.valueMin) * (1 - this.textSpace - this.controlWidth) + 0.5 * this.controlWidth;
188                 if (fabs(pos.x - controlCenter) <= 0.5 * this.controlWidth)
189                 {
190                         this.pressed = 1;
191                         this.pressOffset = pos.x - controlCenter;
192                         this.previousValue = this.value;
193                         // this.mouseDrag(this, pos);
194                 }
195                 else
196                 {
197                         float clickValue, pageValue, inRange;
198                         clickValue = median(0, (pos.x - this.pressOffset - 0.5 * this.controlWidth) / (1 - this.textSpace - this.controlWidth), 1) * (this.valueMax - this.valueMin) + this.valueMin;
199                         inRange = (almost_in_bounds(this.valueMin, this.value, this.valueMax));
200                         if (pos.x < controlCenter)
201                         {
202                                 pageValue = this.value - this.valuePageStep;
203                                 if (this.valueStep) clickValue = floor(clickValue / this.valueStep) * this.valueStep;
204                                 pageValue = max(pageValue, clickValue);
205                         }
206                         else
207                         {
208                                 pageValue = this.value + this.valuePageStep;
209                                 if (this.valueStep) clickValue = ceil(clickValue / this.valueStep) * this.valueStep;
210                                 pageValue = min(pageValue, clickValue);
211                         }
212                         if (inRange) this.setValue(this, median(this.valueMin, pageValue, this.valueMax));
213                         else this.setValue(this, this.valueMax);
214                         if(this.applyButton)
215                                 this.applyButton.disabled = false;
216                         if (pageValue == clickValue)
217                         {
218                                 controlCenter = (this.value - this.valueMin) / (this.valueMax - this.valueMin) * (1 - this.textSpace - this.controlWidth) + 0.5 * this.controlWidth;
219                                 this.pressed = 1;
220                                 this.pressOffset = pos.x - controlCenter;
221                                 this.previousValue = this.value;
222                                 // this.mouseDrag(this, pos);
223                         }
224                 }
225                 return true;
226         }
227         float Slider_mouseRelease(entity me, vector pos)
228         {
229                 me.pressed = 0;
230                 if (me.disabled) return 0;
231                 m_play_click_sound(MENU_SOUND_SLIDE);
232                 return 1;
233         }
234         void Slider_showNotify(entity me)
235         {
236                 me.focusable = !me.disabled;
237         }
238         void Slider_draw(entity me)
239         {
240                 float controlLeft;
241                 float save;
242                 me.focusable = !me.disabled;
243                 save = draw_alpha;
244                 if (me.disabled) draw_alpha *= me.disabledAlpha;
245                 draw_ButtonPicture('0 0 0', strcat(me.src, "_s"), eX * (1 - me.textSpace) + eY, me.color2, 1);
246                 if (me.valueMax > me.valueMin) // valid?
247                 if (almost_in_bounds(me.valueMin, me.sliderValue, me.valueMax))
248                 {
249                         controlLeft = (me.sliderValue - me.valueMin) / (me.valueMax - me.valueMin) * (1 - me.textSpace - me.controlWidth);
250                         if (me.disabled) draw_Picture(eX * controlLeft, strcat(me.src, "_d"), eX * me.controlWidth + eY, me.colorD, 1);
251                         else if (me.pressed) draw_Picture(eX * controlLeft, strcat(me.src, "_c"), eX * me.controlWidth + eY, me.colorC, 1);
252                         else if (me.focused) draw_Picture(eX * controlLeft, strcat(me.src, "_f"), eX * me.controlWidth + eY, me.colorF, 1);
253                         else draw_Picture(eX * controlLeft, strcat(me.src, "_n"), eX * me.controlWidth + eY, me.color, 1);
254                 }
255
256                 if (me.sliderAnim)
257                         if (me.sliderAnim.isFinished(me.sliderAnim))
258                         {
259                                 anim.removeObjAnim(anim, me);
260                                 me.sliderAnim = NULL;
261                         }
262
263                 if (me.valueMax > me.valueMin) // valid?
264                         me.setText(me, me.valueToText(me, me.value));
265                 draw_alpha = save;
266                 SUPER(Slider).draw(me);
267                 me.text = string_null;  // TEMPSTRING!
268         }