]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/menu/item/slider.c
stop old slider animation before starting a new one
[xonotic/xonotic-data.pk3dir.git] / qcsrc / menu / item / slider.c
1 // Note:
2 //   to use this, you FIRST call configureSliderVisuals, then configureSliderValues
3 #ifdef INTERFACE
4 CLASS(Slider) EXTENDS(Label)
5         METHOD(Slider, resizeNotify, void(entity, vector, vector, vector, vector))
6         METHOD(Slider, configureSliderVisuals, void(entity, float, float, float, string))
7         METHOD(Slider, configureSliderValues, void(entity, float, float, float, float, float, float))
8         METHOD(Slider, draw, void(entity))
9         METHOD(Slider, keyDown, float(entity, float, float, float))
10         METHOD(Slider, mousePress, float(entity, vector))
11         METHOD(Slider, mouseDrag, float(entity, vector))
12         METHOD(Slider, mouseRelease, float(entity, vector))
13         METHOD(Slider, valueToText, string(entity, float))
14         METHOD(Slider, toString, string(entity))
15         METHOD(Slider, setValue, void(entity, float))
16         METHOD(Slider, setSliderValue, void(entity, float))
17         METHOD(Slider, showNotify, void(entity))
18         ATTRIB(Slider, src, string, string_null)
19         ATTRIB(Slider, focusable, float, 1)
20         ATTRIB(Slider, value, float, 0)
21         ATTRIB(Slider, animated, float, 1)
22         ATTRIB(Slider, sliderValue, float, 0)
23         ATTRIB(Slider, valueMin, float, 0)
24         ATTRIB(Slider, valueMax, float, 0)
25         ATTRIB(Slider, valueStep, float, 0)
26         ATTRIB(Slider, valueDigits, float, 0)
27         ATTRIB(Slider, valueKeyStep, float, 0)
28         ATTRIB(Slider, valuePageStep, float, 0)
29         ATTRIB(Slider, valueDisplayMultiplier, float, 1.0)
30         ATTRIB(Slider, textSpace, float, 0)
31         ATTRIB(Slider, controlWidth, float, 0)
32         ATTRIB(Slider, pressed, float, 0)
33         ATTRIB(Slider, pressOffset, float, 0)
34         ATTRIB(Slider, previousValue, float, 0)
35         ATTRIB(Slider, tolerance, vector, '0 0 0')
36         ATTRIB(Slider, disabled, float, 0)
37         ATTRIB(Slider, color, vector, '1 1 1')
38         ATTRIB(Slider, color2, vector, '1 1 1')
39         ATTRIB(Slider, colorD, vector, '1 1 1')
40         ATTRIB(Slider, colorC, vector, '1 1 1')
41         ATTRIB(Slider, colorF, vector, '1 1 1')
42         ATTRIB(Slider, disabledAlpha, float, 0.3)
43 ENDCLASS(Slider)
44 #endif
45
46 #ifdef IMPLEMENTATION
47 void setValueSlider(entity me, float val)
48 {
49         if (me.animated) {
50                 anim.finishObjAnim(anim, me);
51                 makeHostedEasing(me, setSliderValueSlider, easingQuadInOut, 1, me.sliderValue, val);
52         } else {
53                 me.setSliderValue(me, val);
54         }
55         me.value = val;
56 }
57 void setSliderValueSlider(entity me, float val)
58 {
59         me.sliderValue = val;
60 }
61 string toStringSlider(entity me)
62 {
63         return strcat(ftos(me.value), " (", me.valueToText(me, me.value), ")");
64 }
65 void resizeNotifySlider(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
66 {
67         resizeNotifyLabel(me, relOrigin, relSize, absOrigin, absSize);
68         me.controlWidth = absSize_y / absSize_x;
69 }
70 string valueToTextSlider(entity me, float val)
71 {
72         if(almost_in_bounds(me.valueMin, val, me.valueMax))
73                 return ftos_decimals(val * me.valueDisplayMultiplier, me.valueDigits);
74         return "";
75 }
76 void configureSliderVisualsSlider(entity me, float sz, float theAlign, float theTextSpace, string gfx)
77 {
78         configureLabelLabel(me, string_null, sz, theAlign);
79         me.textSpace = theTextSpace;
80         me.keepspaceLeft = (theTextSpace == 0) ? 0 : (1 - theTextSpace);
81         me.src = gfx;
82 }
83 void configureSliderValuesSlider(entity me, float theValueMin, float theValue, float theValueMax, float theValueStep, float theValueKeyStep, float theValuePageStep)
84 {
85         me.value = theValue;
86         me.sliderValue = theValue;
87         me.valueStep = theValueStep;
88         me.valueMin = theValueMin;
89         me.valueMax = theValueMax;
90         me.valueKeyStep = theValueKeyStep;
91         me.valuePageStep = theValuePageStep;
92         me.valueDigits = 3;
93         if(fabs(floor(me.valueStep * 100 + 0.5) - (me.valueStep * 100)) < 0.01) // about a whole number of 100ths
94                 me.valueDigits = 2;
95         if(fabs(floor(me.valueStep * 10 + 0.5) - (me.valueStep * 10)) < 0.01) // about a whole number of 10ths
96                 me.valueDigits = 1;
97         if(fabs(floor(me.valueStep * 1 + 0.5) - (me.valueStep * 1)) < 0.01) // about a whole number
98                 me.valueDigits = 0;
99 }
100 float keyDownSlider(entity me, float key, float ascii, float shift)
101 {
102         float inRange;
103         if(me.disabled)
104                 return 0;
105         inRange = (almost_in_bounds(me.valueMin, me.value, me.valueMax));
106         if(key == K_LEFTARROW)
107         {
108                 if(inRange)
109                         me.setValue(me, median(me.valueMin, me.value - me.valueKeyStep, me.valueMax));
110                 else
111                         me.setValue(me, me.valueMax);
112                 return 1;
113         }
114         if(key == K_RIGHTARROW)
115         {
116                 if(inRange)
117                         me.setValue(me, median(me.valueMin, me.value + me.valueKeyStep, me.valueMax));
118                 else
119                         me.setValue(me, me.valueMin);
120                 return 1;
121         }
122         if(key == K_PGUP)
123         {
124                 if(inRange)
125                         me.setValue(me, median(me.valueMin, me.value - me.valuePageStep, me.valueMax));
126                 else
127                         me.setValue(me, me.valueMax);
128                 return 1;
129         }
130         if(key == K_PGDN)
131         {
132                 if(inRange)
133                         me.setValue(me, median(me.valueMin, me.value + me.valuePageStep, me.valueMax));
134                 else
135                         me.setValue(me, me.valueMin);
136                 return 1;
137         }
138         if(key == K_HOME)
139         {
140                 me.setValue(me, me.valueMin);
141                 return 1;
142         }
143         if(key == K_END)
144         {
145                 me.setValue(me, me.valueMax);
146                 return 1;
147         }
148         // TODO more keys
149         return 0;
150 }
151 float mouseDragSlider(entity me, vector pos)
152 {
153         float hit;
154         float v, animed;
155         if(me.disabled)
156                 return 0;
157         animed = me.animated;
158         me.animated = false;
159         if(me.pressed)
160         {
161                 hit = 1;
162                 if(pos_x < 0 - me.tolerance_x) hit = 0;
163                 if(pos_y < 0 - me.tolerance_y) hit = 0;
164                 if(pos_x >= 1 - me.textSpace + me.tolerance_x) hit = 0;
165                 if(pos_y >= 1 + me.tolerance_y) hit = 0;
166                 if(hit)
167                 {
168                         v = median(0, (pos_x - me.pressOffset - 0.5 * me.controlWidth) / (1 - me.textSpace - me.controlWidth), 1) * (me.valueMax - me.valueMin) + me.valueMin;
169                         if(me.valueStep)
170                                 v = floor(0.5 + v / me.valueStep) * me.valueStep;
171                         me.setValue(me, v);
172                 }
173                 else
174                         me.setValue(me, me.previousValue);
175         }
176         me.animated = animed;
177         return 1;
178 }
179 float mousePressSlider(entity me, vector pos)
180 {
181         float controlCenter;
182         if(me.disabled)
183                 return 0;
184         if(pos_x < 0) return 0;
185         if(pos_y < 0) return 0;
186         if(pos_x >= 1 - me.textSpace) return 0;
187         if(pos_y >= 1) return 0;
188         controlCenter = (me.value - me.valueMin) / (me.valueMax - me.valueMin) * (1 - me.textSpace - me.controlWidth) + 0.5 * me.controlWidth;
189         if(fabs(pos_x - controlCenter) <= 0.5 * me.controlWidth)
190         {
191                 me.pressed = 1;
192                 me.pressOffset = pos_x - controlCenter;
193                 me.previousValue = me.value;
194                 //me.mouseDrag(me, pos);
195         }
196         else
197         {
198                 float clickValue, pageValue, inRange;
199                 clickValue = median(0, (pos_x - me.pressOffset - 0.5 * me.controlWidth) / (1 - me.textSpace - me.controlWidth), 1) * (me.valueMax - me.valueMin) + me.valueMin;
200                 inRange = (almost_in_bounds(me.valueMin, me.value, me.valueMax));
201                 if(pos_x < controlCenter)
202                 {
203                         pageValue = me.value - me.valuePageStep;
204                         if(me.valueStep)
205                                 clickValue = floor(clickValue / me.valueStep) * me.valueStep;
206                         pageValue = max(pageValue, clickValue);
207                         if(inRange)
208                                 me.setValue(me, median(me.valueMin, pageValue, me.valueMax));
209                         else
210                                 me.setValue(me, me.valueMax);
211                 }
212                 else
213                 {
214                         pageValue = me.value + me.valuePageStep;
215                         if(me.valueStep)
216                                 clickValue = ceil(clickValue / me.valueStep) * me.valueStep;
217                         pageValue = min(pageValue, clickValue);
218                         if(inRange)
219                                 me.setValue(me, median(me.valueMin, pageValue, me.valueMax));
220                         else
221                                 me.setValue(me, me.valueMax);
222                 }
223                 if(pageValue == clickValue)
224                 {
225                         controlCenter = (me.value - me.valueMin) / (me.valueMax - me.valueMin) * (1 - me.textSpace - me.controlWidth) + 0.5 * me.controlWidth;
226                         me.pressed = 1;
227                         me.pressOffset = pos_x - controlCenter;
228                         me.previousValue = me.value;
229                         //me.mouseDrag(me, pos);
230                 }
231         }
232         if(cvar("menu_sounds"))
233                 localsound("sound/misc/menu2.wav");
234         return 1;
235 }
236 float mouseReleaseSlider(entity me, vector pos)
237 {
238         me.pressed = 0;
239         if(me.disabled)
240                 return 0;
241         return 1;
242 }
243 void showNotifySlider(entity me)
244 {
245         me.focusable = !me.disabled;
246 }
247 void drawSlider(entity me)
248 {
249         float controlLeft;
250         float save;
251         me.focusable = !me.disabled;
252         save = draw_alpha;
253         if(me.disabled)
254                 draw_alpha *= me.disabledAlpha;
255         draw_ButtonPicture('0 0 0', strcat(me.src, "_s"), eX * (1 - me.textSpace) + eY, me.color2, 1);
256         if(almost_in_bounds(me.valueMin, me.sliderValue, me.valueMax))
257         {
258                 controlLeft = (me.sliderValue - me.valueMin) / (me.valueMax - me.valueMin) * (1 - me.textSpace - me.controlWidth);
259                 if(me.disabled)
260                         draw_Picture(eX * controlLeft, strcat(me.src, "_d"), eX * me.controlWidth + eY, me.colorD, 1);
261                 else if(me.pressed)
262                         draw_Picture(eX * controlLeft, strcat(me.src, "_c"), eX * me.controlWidth + eY, me.colorC, 1);
263                 else if(me.focused)
264                         draw_Picture(eX * controlLeft, strcat(me.src, "_f"), eX * me.controlWidth + eY, me.colorF, 1);
265                 else
266                         draw_Picture(eX * controlLeft, strcat(me.src, "_n"), eX * me.controlWidth + eY, me.color, 1);
267         }
268         me.setText(me, me.valueToText(me, me.value));
269         draw_alpha = save;
270         drawLabel(me);
271         me.text = string_null; // TEMPSTRING!
272 }
273 #endif