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