]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/menu/item/nexposee.qc
Uncrustify menu/{anim,item}/*
[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) e.Nexposee_smallOrigin_x = 1 - e.Nexposee_align.x * scale;
77                         if (e.Nexposee_align.x < 0) e.Nexposee_smallOrigin_x = -e.Nexposee_smallSize.x + e.Nexposee_align.x * scale;
78                         if (e.Nexposee_align.y > 0) e.Nexposee_smallOrigin_y = 1 - e.Nexposee_align.y * scale;
79                         if (e.Nexposee_align.y < 0) e.Nexposee_smallOrigin_y = -e.Nexposee_smallSize.y + e.Nexposee_align.y * scale;
80                 }
81         }
82
83         void Nexposee_calc(entity me)
84         {
85                 /*
86                  * patented by Apple
87                  * can't put that here ;)
88                  */
89                 float scale;
90                 entity e, e2;
91                 vector emins, emaxs, e2mins, e2maxs;
92
93                 for (scale = 0.7; ; scale *= 0.99)
94                 {
95                         Nexposee_Calc_Scale(me, scale);
96
97                         for (e = me.firstChild; e; e = e.nextSibling)
98                         {
99                                 emins = e.Nexposee_smallOrigin;
100                                 emaxs = emins + e.Nexposee_smallSize;
101                                 for (e2 = e.nextSibling; e2; e2 = e2.nextSibling)
102                                 {
103                                         e2mins = e2.Nexposee_smallOrigin;
104                                         e2maxs = e2mins + e2.Nexposee_smallSize;
105
106                                         // two intervals [amins, amaxs] and [bmins, bmaxs] overlap if:
107                                         //   amins < bmins < amaxs < bmaxs
108                                         // for which suffices
109                                         //   bmins < amaxs
110                                         //   amins < bmaxs
111                                         if ((e2mins.x - emaxs.x) * (emins.x - e2maxs.x) > 0)     // x overlap
112                                                 if ((e2mins.y - emaxs.y) * (emins.y - e2maxs.y) > 0) // y overlap
113                                                         goto have_overlap;
114                                 }
115                         }
116
117                         break;
118                         : have_overlap
119                 }
120
121                 scale *= 0.95;
122
123                 Nexposee_Calc_Scale(me, scale);
124         }
125
126         void Nexposee_setNexposee(entity me, entity other, vector scalecenter, float a0, float a1)
127         {
128                 other.Nexposee_scaleCenter = scalecenter;
129                 other.Nexposee_smallAlpha = a0;
130                 me.setAlphaOf(me, other, a0);
131                 other.Nexposee_mediumAlpha = a1;
132         }
133
134         void Nexposee_draw(entity me)
135         {
136                 float a;
137                 float a0;
138                 entity e;
139                 float f;
140                 vector fs;
141
142                 if (me.animationState == -1) me.animationState = 0;
143
144                 f = min(1, frametime * 5);
145                 switch (me.animationState)
146                 {
147                         case 0:
148                                 me.animationFactor = 0;
149                                 break;
150                         case 1:
151                                 me.animationFactor += f;
152                                 if (me.animationFactor >= 1)
153                                 {
154                                         me.animationFactor = 1;
155                                         me.animationState = 2;
156                                         SUPER(Nexposee).setFocus(me, me.selectedChild);
157                                 }
158                                 break;
159                         case 2:
160                                 me.animationFactor = 1;
161                                 break;
162                         case 3:
163                                 me.animationFactor -= f;
164                                 me.mouseFocusedChild = me.itemFromPoint(me, me.mousePosition);
165                                 if (me.animationFactor <= 0)
166                                 {
167                                         me.animationFactor = 0;
168                                         me.animationState = 0;
169                                         me.selectedChild = me.mouseFocusedChild;
170                                 }
171                                 break;
172                 }
173
174                 f = min(1, frametime * 10);
175                 for (e = me.firstChild; e; e = e.nextSibling)
176                 {
177                         if (e == me.selectedChild)
178                         {
179                                 e.Container_origin = e.Nexposee_smallOrigin * (1 - me.animationFactor) + e.Nexposee_initialOrigin * me.animationFactor;
180                                 e.Container_size = e.Nexposee_smallSize * (1 - me.animationFactor) + e.Nexposee_initialSize * me.animationFactor;
181                                 e.Nexposee_animationFactor = me.animationFactor;
182                                 a0 = e.Nexposee_mediumAlpha;
183                                 if (me.animationState == 3)
184                                         if (e != me.mouseFocusedChild) a0 = e.Nexposee_smallAlpha;
185                                 a = a0 * (1 - me.animationFactor) + me.animationFactor;
186                         }
187                         else
188                         {
189                                 // minimum theSize counts
190                                 e.Container_origin = e.Nexposee_smallOrigin;
191                                 e.Container_size = e.Nexposee_smallSize;
192                                 e.Nexposee_animationFactor = 0;
193                                 a = e.Nexposee_smallAlpha * (1 - me.animationFactor);
194                         }
195                         me.setAlphaOf(me, e, e.Container_alpha * (1 - f) + a * f);
196
197                         fs = globalToBoxSize(e.Container_size, e.Nexposee_initialSize);
198                         e.Container_fontscale_x = fs.x * e.Nexposee_initialFontScale.x;
199                         e.Container_fontscale_y = fs.y * e.Nexposee_initialFontScale.y;
200                 }
201
202                 SUPER(Nexposee).draw(me);
203         }
204
205         float Nexposee_mousePress(entity me, vector pos)
206         {
207                 if (me.animationState == 0)
208                 {
209                         me.mouseFocusedChild = NULL;
210                         Nexposee_mouseMove(me, pos);
211                         if (me.mouseFocusedChild)
212                         {
213                                 m_play_click_sound(MENU_SOUND_OPEN);
214                                 me.animationState = 1;
215                                 SUPER(Nexposee).setFocus(me, NULL);
216                         }
217                         else
218                         {
219                                 me.close(me);
220                         }
221                         return 1;
222                 }
223                 else if (me.animationState == 2)
224                 {
225                         if (!(SUPER(Nexposee).mousePress(me, pos)))
226                         {
227                                 m_play_click_sound(MENU_SOUND_CLOSE);
228                                 me.animationState = 3;
229                                 SUPER(Nexposee).setFocus(me, NULL);
230                         }
231                         return 1;
232                 }
233                 return 0;
234         }
235
236         float Nexposee_mouseRelease(entity me, vector pos)
237         {
238                 if (me.animationState == 2) return SUPER(Nexposee).mouseRelease(me, pos);
239                 return 0;
240         }
241
242         float Nexposee_mouseDrag(entity me, vector pos)
243         {
244                 if (me.animationState == 2) return SUPER(Nexposee).mouseDrag(me, pos);
245                 return 0;
246         }
247
248         float Nexposee_mouseMove(entity me, vector pos)
249         {
250                 entity e;
251                 me.mousePosition = pos;
252                 e = me.mouseFocusedChild;
253                 me.mouseFocusedChild = me.itemFromPoint(me, pos);
254                 if (me.animationState == 2) return SUPER(Nexposee).mouseMove(me, pos);
255                 if (me.animationState == 0)
256                 {
257                         if (me.mouseFocusedChild)
258                                 if (me.mouseFocusedChild != e || me.mouseFocusedChild != me.selectedChild) me.selectedChild = me.mouseFocusedChild;
259                         return 1;
260                 }
261                 return 0;
262         }
263
264         float Nexposee_keyUp(entity me, float scan, float ascii, float shift)
265         {
266                 if (me.animationState == 2) return SUPER(Nexposee).keyUp(me, scan, ascii, shift);
267                 return 0;
268         }
269
270         float Nexposee_keyDown(entity me, float scan, float ascii, float shift)
271         {
272                 float nexposeeKey = 0;
273                 if (me.animationState == 2)
274                         if (SUPER(Nexposee).keyDown(me, scan, ascii, shift)) return 1;
275                 if (scan == K_TAB)
276                 {
277                         if (me.animationState == 0)
278                         {
279                                 if (shift & S_SHIFT)
280                                 {
281                                         if (me.selectedChild) me.selectedChild = me.selectedChild.prevSibling;
282                                         if (!me.selectedChild) me.selectedChild = me.lastChild;
283                                 }
284                                 else
285                                 {
286                                         if (me.selectedChild) me.selectedChild = me.selectedChild.nextSibling;
287                                         if (!me.selectedChild) me.selectedChild = me.firstChild;
288                                 }
289                         }
290                 }
291                 switch (me.animationState)
292                 {
293                         default:
294                         case 0:
295                         case 3:
296                                 nexposeeKey = ((scan == K_SPACE) || (scan == K_ENTER) || (scan == K_KP_ENTER));
297                                 break;
298                         case 1:
299                         case 2:
300                                 nexposeeKey = (scan == K_ESCAPE);
301                                 break;
302                 }
303                 if (nexposeeKey)
304                 {
305                         switch (me.animationState)
306                         {
307                                 default:
308                                 case 0:
309                                 case 3:
310                                         m_play_click_sound(MENU_SOUND_OPEN);
311                                         me.animationState = 1;
312                                         break;
313                                 case 1:
314                                 case 2:
315                                         m_play_click_sound(MENU_SOUND_CLOSE);
316                                         me.animationState = 3;
317                                         break;
318                         }
319                         if (me.focusedChild) me.selectedChild = me.focusedChild;
320                         if (!me.selectedChild) me.animationState = 0;
321                         SUPER(Nexposee).setFocus(me, NULL);
322                         return 1;
323                 }
324                 return 0;
325         }
326
327         void Nexposee_addItem(entity me, entity other, vector theOrigin, vector theSize, float theAlpha)
328         {
329                 SUPER(Nexposee).addItem(me, other, theOrigin, theSize, theAlpha);
330                 other.Nexposee_initialFontScale = other.Container_fontscale;
331                 other.Nexposee_initialSize = other.Container_size;
332                 other.Nexposee_initialOrigin = other.Container_origin;
333                 other.Nexposee_initialAlpha = other.Container_alpha;
334                 if (other.Nexposee_initialFontScale == '0 0 0') other.Nexposee_initialFontScale = '1 1 0';
335         }
336
337         void Nexposee_focusEnter(entity me)
338         {
339                 if (me.animationState == 2) SUPER(Nexposee).setFocus(me, me.selectedChild);
340         }
341
342         void Nexposee_pullNexposee(entity me, entity other, vector theAlign)
343         {
344                 other.Nexposee_align = theAlign;
345         }
346 #endif