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