]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/menu/item/nexposee.qc
Merge branch 'master' into terencehill/bot_fixes
[xonotic/xonotic-data.pk3dir.git] / qcsrc / menu / item / nexposee.qc
1 #ifndef ITEM_NEXPOSEE_H
2 #define ITEM_NEXPOSEE_H
3 #include "container.qc"
4 CLASS(Nexposee, Container)
5         METHOD(Nexposee, draw, void(entity));
6         METHOD(Nexposee, keyDown, float(entity, float, float, float));
7         METHOD(Nexposee, keyUp, float(entity, float, float, float));
8         METHOD(Nexposee, mousePress, float(entity, vector));
9         METHOD(Nexposee, mouseMove, float(entity, vector));
10         METHOD(Nexposee, mouseRelease, float(entity, vector));
11         METHOD(Nexposee, mouseDrag, float(entity, vector));
12         METHOD(Nexposee, resizeNotify, void(entity, vector, vector, vector, vector));
13         METHOD(Nexposee, focusEnter, void(entity));
14         METHOD(Nexposee, close, void(entity));
15
16         ATTRIB(Nexposee, animationState, float, -1)
17         ATTRIB(Nexposee, animationFactor, float, 0)
18         ATTRIB(Nexposee, selectedChild, entity, NULL)
19         ATTRIB(Nexposee, mouseFocusedChild, entity, NULL)
20         METHOD(Nexposee, addItem, void(entity, entity, vector, vector, float));
21         METHOD(Nexposee, calc, void(entity));
22         METHOD(Nexposee, setNexposee, void(entity, entity, vector, float, float));
23         ATTRIB(Nexposee, mousePosition, vector, '0 0 0')
24         METHOD(Nexposee, pullNexposee, void(entity, entity, vector));
25 ENDCLASS(Nexposee)
26
27 void ExposeeCloseButton_Click(entity button, entity other); // un-exposees the current state
28
29 // animation states:
30 //   0 = thumbnails seen
31 //   1 = zooming in
32 //   2 = zoomed in
33 //   3 = zooming out
34 // animation factor: 0 = minimum theSize, 1 = maximum theSize
35 .vector Nexposee_initialSize;
36 .vector Nexposee_initialFontScale;
37 .vector Nexposee_initialOrigin;
38 .float Nexposee_initialAlpha;
39
40 .vector Nexposee_smallSize;
41 .vector Nexposee_smallOrigin;
42 .float Nexposee_smallAlpha;
43 .float Nexposee_mediumAlpha;
44 .vector Nexposee_scaleCenter;
45 .vector Nexposee_align;
46 .float Nexposee_animationFactor;
47
48 #endif
49
50 #ifdef IMPLEMENTATION
51 void Nexposee_close(entity me)
52 {
53         // user must override this
54 }
55
56 void ExposeeCloseButton_Click(entity button, entity other)
57 {
58         other.selectedChild = other.focusedChild;
59         other.setFocus(other, NULL);
60         other.animationState = 3;
61 }
62
63 void Nexposee_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
64 {
65         me.calc(me);
66         me.resizeNotifyLie(me, relOrigin, relSize, absOrigin, absSize, Nexposee_initialOrigin, Nexposee_initialSize, Nexposee_initialFontScale);
67 }
68
69 void Nexposee_Calc_Scale(entity me, float scale)
70 {
71         entity e;
72         for(e = me.firstChild; e; e = e.nextSibling)
73         {
74                 e.Nexposee_smallOrigin = (e.Nexposee_initialOrigin - e.Nexposee_scaleCenter) * scale + e.Nexposee_scaleCenter;
75                 e.Nexposee_smallSize = e.Nexposee_initialSize * scale;
76                 if(e.Nexposee_align.x > 0)
77                         e.Nexposee_smallOrigin_x = 1 - e.Nexposee_align.x * scale;
78                 if(e.Nexposee_align.x < 0)
79                         e.Nexposee_smallOrigin_x = -e.Nexposee_smallSize.x + e.Nexposee_align.x * scale;
80                 if(e.Nexposee_align.y > 0)
81                         e.Nexposee_smallOrigin_y = 1 - e.Nexposee_align.y * scale;
82                 if(e.Nexposee_align.y < 0)
83                         e.Nexposee_smallOrigin_y = -e.Nexposee_smallSize.y + e.Nexposee_align.y * scale;
84         }
85 }
86
87 void Nexposee_calc(entity me)
88 {
89         /*
90          * patented by Apple
91          * can't put that here ;)
92          */
93         float scale;
94         entity e, e2;
95         vector emins, emaxs, e2mins, e2maxs;
96
97         for(scale = 0.7;; scale *= 0.99)
98         {
99                 Nexposee_Calc_Scale(me, scale);
100
101                 for(e = me.firstChild; e; e = e.nextSibling)
102                 {
103                         emins = e.Nexposee_smallOrigin;
104                         emaxs = emins + e.Nexposee_smallSize;
105                         for(e2 = e.nextSibling; e2; e2 = e2.nextSibling)
106                         {
107                                 e2mins = e2.Nexposee_smallOrigin;
108                                 e2maxs = e2mins + e2.Nexposee_smallSize;
109
110                                 // two intervals [amins, amaxs] and [bmins, bmaxs] overlap if:
111                                 //   amins < bmins < amaxs < bmaxs
112                                 // for which suffices
113                                 //   bmins < amaxs
114                                 //   amins < bmaxs
115                                 if((e2mins.x - emaxs.x) * (emins.x - e2maxs.x) > 0) // x overlap
116                                         if((e2mins.y - emaxs.y) * (emins.y - e2maxs.y) > 0) // y overlap
117                                         {
118                                                 goto have_overlap;
119                                         }
120                         }
121                 }
122
123                 break;
124 :have_overlap
125         }
126
127         scale *= 0.95;
128
129         Nexposee_Calc_Scale(me, scale);
130 }
131
132 void Nexposee_setNexposee(entity me, entity other, vector scalecenter, float a0, float a1)
133 {
134         other.Nexposee_scaleCenter = scalecenter;
135         other.Nexposee_smallAlpha = a0;
136         me.setAlphaOf(me, other, a0);
137         other.Nexposee_mediumAlpha = a1;
138 }
139
140 void Nexposee_draw(entity me)
141 {
142         float a;
143         float a0;
144         entity e;
145         float f;
146         vector fs;
147
148         if(me.animationState == -1)
149         {
150                 me.animationState = 0;
151         }
152
153         f = min(1, frametime * 5);
154         switch(me.animationState)
155         {
156                 case 0:
157                         me.animationFactor = 0;
158                         break;
159                 case 1:
160                         me.animationFactor += f;
161                         if(me.animationFactor >= 1)
162                         {
163                                 me.animationFactor = 1;
164                                 me.animationState = 2;
165                                 SUPER(Nexposee).setFocus(me, me.selectedChild);
166                         }
167                         break;
168                 case 2:
169                         me.animationFactor = 1;
170                         break;
171                 case 3:
172                         me.animationFactor -= f;
173                         me.mouseFocusedChild = me.itemFromPoint(me, me.mousePosition);
174                         if(me.animationFactor <= 0)
175                         {
176                                 me.animationFactor = 0;
177                                 me.animationState = 0;
178                                 me.selectedChild = me.mouseFocusedChild;
179                         }
180                         break;
181         }
182
183         f = min(1, frametime * 10);
184         for(e = me.firstChild; e; e = e.nextSibling)
185         {
186                 if(e == me.selectedChild)
187                 {
188                         e.Container_origin = e.Nexposee_smallOrigin * (1 - me.animationFactor) + e.Nexposee_initialOrigin * me.animationFactor;
189                         e.Container_size = e.Nexposee_smallSize * (1 - me.animationFactor) + e.Nexposee_initialSize * me.animationFactor;
190                         e.Nexposee_animationFactor = me.animationFactor;
191                         a0 = e.Nexposee_mediumAlpha;
192                         if(me.animationState == 3)
193                                 if(e != me.mouseFocusedChild)
194                                         a0 = e.Nexposee_smallAlpha;
195                         a = a0 * (1 - me.animationFactor) + me.animationFactor;
196                 }
197                 else
198                 {
199                         // minimum theSize counts
200                         e.Container_origin = e.Nexposee_smallOrigin;
201                         e.Container_size = e.Nexposee_smallSize;
202                         e.Nexposee_animationFactor = 0;
203                         a = e.Nexposee_smallAlpha * (1 - me.animationFactor);
204                 }
205                 me.setAlphaOf(me, e, e.Container_alpha * (1 - f) + a * f);
206
207                 fs = globalToBoxSize(e.Container_size, e.Nexposee_initialSize);
208                 e.Container_fontscale_x = fs.x * e.Nexposee_initialFontScale.x;
209                 e.Container_fontscale_y = fs.y * e.Nexposee_initialFontScale.y;
210         }
211
212         SUPER(Nexposee).draw(me);
213 }
214
215 float Nexposee_mousePress(entity me, vector pos)
216 {
217         if(me.animationState == 0)
218         {
219                 me.mouseFocusedChild = NULL;
220                 Nexposee_mouseMove(me, pos);
221                 if(me.mouseFocusedChild)
222                 {
223                         m_play_click_sound(MENU_SOUND_OPEN);
224                         me.animationState = 1;
225                         SUPER(Nexposee).setFocus(me, NULL);
226                 }
227                 else
228                         me.close(me);
229                 return 1;
230         }
231         else if(me.animationState == 2)
232         {
233                 if (!(SUPER(Nexposee).mousePress(me, pos)))
234                 {
235                         m_play_click_sound(MENU_SOUND_CLOSE);
236                         me.animationState = 3;
237                         SUPER(Nexposee).setFocus(me, NULL);
238                 }
239                 return 1;
240         }
241         return 0;
242 }
243
244 float Nexposee_mouseRelease(entity me, vector pos)
245 {
246         if(me.animationState == 2)
247                 return SUPER(Nexposee).mouseRelease(me, pos);
248         return 0;
249 }
250
251 float Nexposee_mouseDrag(entity me, vector pos)
252 {
253         if(me.animationState == 2)
254                 return SUPER(Nexposee).mouseDrag(me, pos);
255         return 0;
256 }
257
258 float Nexposee_mouseMove(entity me, vector pos)
259 {
260         entity e;
261         me.mousePosition = pos;
262         e = me.mouseFocusedChild;
263         me.mouseFocusedChild = me.itemFromPoint(me, pos);
264         if(me.animationState == 2)
265                 return SUPER(Nexposee).mouseMove(me, pos);
266         if(me.animationState == 0)
267         {
268                 if(me.mouseFocusedChild)
269                         if(me.mouseFocusedChild != e || me.mouseFocusedChild != me.selectedChild)
270                                 me.selectedChild = me.mouseFocusedChild;
271                 return 1;
272         }
273         return 0;
274 }
275
276 float Nexposee_keyUp(entity me, float scan, float ascii, float shift)
277 {
278         if(me.animationState == 2)
279                 return SUPER(Nexposee).keyUp(me, scan, ascii, shift);
280         return 0;
281 }
282
283 float Nexposee_keyDown(entity me, float scan, float ascii, float shift)
284 {
285         float nexposeeKey = 0;
286         if(me.animationState == 2)
287                 if(SUPER(Nexposee).keyDown(me, scan, ascii, shift))
288                         return 1;
289         if(scan == K_TAB)
290         {
291                 if(me.animationState == 0)
292                 {
293                         if(shift & S_SHIFT)
294                         {
295                                 if(me.selectedChild)
296                                         me.selectedChild = me.selectedChild.prevSibling;
297                                 if (!me.selectedChild)
298                                         me.selectedChild = me.lastChild;
299                         }
300                         else
301                         {
302                                 if(me.selectedChild)
303                                         me.selectedChild = me.selectedChild.nextSibling;
304                                 if (!me.selectedChild)
305                                         me.selectedChild = me.firstChild;
306                         }
307                 }
308         }
309         switch(me.animationState)
310         {
311                 default:
312                 case 0:
313                 case 3:
314                         nexposeeKey = ((scan == K_SPACE) || (scan == K_ENTER) || (scan == K_KP_ENTER));
315                         break;
316                 case 1:
317                 case 2:
318                         nexposeeKey = (scan == K_ESCAPE);
319                         break;
320         }
321         if(nexposeeKey)
322         {
323                 switch(me.animationState)
324                 {
325                         default:
326                         case 0:
327                         case 3:
328                                 m_play_click_sound(MENU_SOUND_OPEN);
329                                 me.animationState = 1;
330                                 break;
331                         case 1:
332                         case 2:
333                                 m_play_click_sound(MENU_SOUND_CLOSE);
334                                 me.animationState = 3;
335                                 break;
336                 }
337                 if(me.focusedChild)
338                         me.selectedChild = me.focusedChild;
339                 if (!me.selectedChild)
340                         me.animationState = 0;
341                 SUPER(Nexposee).setFocus(me, NULL);
342                 return 1;
343         }
344         return 0;
345 }
346
347 void Nexposee_addItem(entity me, entity other, vector theOrigin, vector theSize, float theAlpha)
348 {
349         SUPER(Nexposee).addItem(me, other, theOrigin, theSize, theAlpha);
350         other.Nexposee_initialFontScale = other.Container_fontscale;
351         other.Nexposee_initialSize = other.Container_size;
352         other.Nexposee_initialOrigin = other.Container_origin;
353         other.Nexposee_initialAlpha = other.Container_alpha;
354         if(other.Nexposee_initialFontScale == '0 0 0')
355                 other.Nexposee_initialFontScale = '1 1 0';
356 }
357
358 void Nexposee_focusEnter(entity me)
359 {
360         if(me.animationState == 2)
361                 SUPER(Nexposee).setFocus(me, me.selectedChild);
362 }
363
364 void Nexposee_pullNexposee(entity me, entity other, vector theAlign)
365 {
366         other.Nexposee_align = theAlign;
367 }
368 #endif