Include gmqcc binaries for Windows and Linux
[voretournament/voretournament.git] / data / qcsrc / menu / item / container.c
1 #ifdef INTERFACE\r
2 CLASS(Container) EXTENDS(Item)\r
3         METHOD(Container, draw, void(entity))\r
4         METHOD(Container, keyUp, float(entity, float, float, float))\r
5         METHOD(Container, keyDown, float(entity, float, float, float))\r
6         METHOD(Container, mouseMove, float(entity, vector))\r
7         METHOD(Container, mousePress, float(entity, vector))\r
8         METHOD(Container, mouseDrag, float(entity, vector))\r
9         METHOD(Container, mouseRelease, float(entity, vector))\r
10         METHOD(Container, focusLeave, void(entity))\r
11         METHOD(Container, resizeNotify, void(entity, vector, vector, vector, vector))\r
12         METHOD(Container, resizeNotifyLie, void(entity, vector, vector, vector, vector, .vector, .vector))\r
13         METHOD(Container, addItem, void(entity, entity, vector, vector, float))\r
14         METHOD(Container, addItemCentered, void(entity, entity, vector, float))\r
15         METHOD(Container, moveItemAfter, void(entity, entity, entity))\r
16         METHOD(Container, removeItem, void(entity, entity))\r
17         METHOD(Container, setFocus, void(entity, entity))\r
18         METHOD(Container, setAlphaOf, void(entity, entity, float))\r
19         METHOD(Container, itemFromPoint, entity(entity, vector))\r
20         METHOD(Container, showNotify, void(entity))\r
21         METHOD(Container, hideNotify, void(entity))\r
22         METHOD(Container, preferredFocusedGrandChild, entity(entity))\r
23         ATTRIB(Container, focusable, float, 0)\r
24         ATTRIB(Container, firstChild, entity, NULL)\r
25         ATTRIB(Container, lastChild, entity, NULL)\r
26         ATTRIB(Container, focusedChild, entity, NULL)\r
27         ATTRIB(Container, shown, float, 0)\r
28 ENDCLASS(Container)\r
29 .entity nextSibling;\r
30 .entity prevSibling;\r
31 .float resized;\r
32 .vector Container_origin;\r
33 .vector Container_size;\r
34 .vector Container_fontscale;\r
35 .float Container_alpha;\r
36 #endif\r
37 \r
38 #ifdef IMPLEMENTATION\r
39 void showNotifyContainer(entity me)\r
40 {\r
41         entity e;\r
42         if(me.shown)\r
43                 return;\r
44         me.shown = 1;\r
45         for(e = me.firstChild; e; e = e.nextSibling)\r
46                 if(e.Container_alpha > 0)\r
47                         e.showNotify(e);\r
48 }\r
49 \r
50 void hideNotifyContainer(entity me)\r
51 {\r
52         entity e;\r
53         if not(me.shown)\r
54                 return;\r
55         me.shown = 0;\r
56         for(e = me.firstChild; e; e = e.nextSibling)\r
57                 if(e.Container_alpha > 0)\r
58                         e.hideNotify(e);\r
59 }\r
60 \r
61 void setAlphaOfContainer(entity me, entity other, float theAlpha)\r
62 {\r
63         if(theAlpha <= 0)\r
64         {\r
65                 if(other.Container_alpha > 0)\r
66                         other.hideNotify(other);\r
67         }\r
68         else // value > 0\r
69         {\r
70                 if(other.Container_alpha <= 0)\r
71                         other.showNotify(other);\r
72         }\r
73         other.Container_alpha = theAlpha;\r
74 }\r
75 \r
76 void resizeNotifyLieContainer(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize, .vector originField, .vector sizeField)\r
77 {\r
78         entity e;\r
79         vector o, s;\r
80         float d;\r
81         for(e = me.firstChild; e; e = e.nextSibling)\r
82         {\r
83                 o = e.originField;\r
84                 s = e.sizeField;\r
85                 e.resizeNotify(e, o, s, boxToGlobal(o, absOrigin, absSize), boxToGlobalSize(s, absSize));\r
86         }\r
87         do\r
88         {\r
89                 d = 0;\r
90                 for(e = me.firstChild; e; e = e.nextSibling)\r
91                         if(e.resized)\r
92                         {\r
93                                 e.resized = 0;\r
94                                 d = 1;\r
95                                 o = e.originField;\r
96                                 s = e.sizeField;\r
97                                 e.resizeNotify(e, o, s, boxToGlobal(o, absOrigin, absSize), boxToGlobalSize(s, absSize));\r
98                         }\r
99         }\r
100         while(d);\r
101         resizeNotifyItem(me, relOrigin, relSize, absOrigin, absSize);\r
102 }\r
103 \r
104 void resizeNotifyContainer(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)\r
105 {\r
106         me.resizeNotifyLie(me, relOrigin, relSize, absOrigin, absSize, Container_origin, Container_size);\r
107 }\r
108 \r
109 entity itemFromPointContainer(entity me, vector pos)\r
110 {\r
111         entity e;\r
112         vector o, s;\r
113         for(e = me.lastChild; e; e = e.prevSibling)\r
114         {\r
115                 o = e.Container_origin;\r
116                 s = e.Container_size;\r
117                 if(pos_x < o_x) continue;\r
118                 if(pos_y < o_y) continue;\r
119                 if(pos_x >= o_x + s_x) continue;\r
120                 if(pos_y >= o_y + s_y) continue;\r
121                 return e;\r
122         }\r
123         return NULL;\r
124 }\r
125 \r
126 void drawContainer(entity me)\r
127 {\r
128         vector oldshift;\r
129         vector oldscale;\r
130         float oldalpha;\r
131         vector oldfontscale;\r
132         entity e;\r
133 \r
134         oldshift = draw_shift;\r
135         oldscale = draw_scale;\r
136         oldalpha = draw_alpha;\r
137         oldfontscale = draw_fontscale;\r
138         me.focusable = 0;\r
139         for(e = me.firstChild; e; e = e.nextSibling)\r
140         {\r
141                 if(e.focusable)\r
142                         me.focusable += 1;\r
143                 if(e.Container_alpha < 0.003) // can't change color values anyway\r
144                         continue;\r
145                 draw_shift = boxToGlobal(e.Container_origin, oldshift, oldscale);\r
146                 draw_scale = boxToGlobalSize(e.Container_size, oldscale);\r
147                 if(e.Container_fontscale != '0 0 0')\r
148                         draw_fontscale = boxToGlobalSize(e.Container_fontscale, oldfontscale);\r
149                 draw_alpha *= e.Container_alpha;\r
150                 e.draw(e);\r
151                 draw_shift = oldshift;\r
152                 draw_scale = oldscale;\r
153                 draw_fontscale = oldfontscale;\r
154                 draw_alpha = oldalpha;\r
155         }\r
156 };\r
157 \r
158 void focusLeaveContainer(entity me)\r
159 {\r
160         me.setFocus(me, NULL);\r
161 }\r
162 \r
163 float keyUpContainer(entity me, float scan, float ascii, float shift)\r
164 {\r
165         entity f;\r
166         f = me.focusedChild;\r
167         if(f)\r
168                 return f.keyUp(f, scan, ascii, shift);\r
169         return 0;\r
170 }\r
171 \r
172 float keyDownContainer(entity me, float scan, float ascii, float shift)\r
173 {\r
174         entity f;\r
175         f = me.focusedChild;\r
176         if(f)\r
177                 return f.keyDown(f, scan, ascii, shift);\r
178         return 0;\r
179 }\r
180 \r
181 float mouseMoveContainer(entity me, vector pos)\r
182 {\r
183         entity f;\r
184         f = me.focusedChild;\r
185         if(f)\r
186                 return f.mouseMove(f, globalToBox(pos, f.Container_origin, f.Container_size));\r
187         return 0;\r
188 }\r
189 float mousePressContainer(entity me, vector pos)\r
190 {\r
191         entity f;\r
192         f = me.focusedChild;\r
193         if(f)\r
194                 return f.mousePress(f, globalToBox(pos, f.Container_origin, f.Container_size));\r
195         return 0;\r
196 }\r
197 float mouseDragContainer(entity me, vector pos)\r
198 {\r
199         entity f;\r
200         f = me.focusedChild;\r
201         if(f)\r
202                 return f.mouseDrag(f, globalToBox(pos, f.Container_origin, f.Container_size));\r
203         return 0;\r
204 }\r
205 float mouseReleaseContainer(entity me, vector pos)\r
206 {\r
207         entity f;\r
208         f = me.focusedChild;\r
209         if(f)\r
210                 return f.mouseRelease(f, globalToBox(pos, f.Container_origin, f.Container_size));\r
211         return 0;\r
212 }\r
213 \r
214 void addItemCenteredContainer(entity me, entity other, vector theSize, float theAlpha)\r
215 {\r
216         me.addItem(me, other, '0.5 0.5 0' - 0.5 * theSize, theSize, theAlpha);\r
217 }\r
218 \r
219 void addItemContainer(entity me, entity other, vector theOrigin, vector theSize, float theAlpha)\r
220 {\r
221         if(other.parent)\r
222                 error("Can't add already added item!");\r
223 \r
224         if(other.focusable)\r
225                 me.focusable += 1;\r
226 \r
227         if(theSize_x > 1)\r
228         {\r
229                 theOrigin_x -= 0.5 * (theSize_x - 1);\r
230                 theSize_x = 1;\r
231         }\r
232         if(theSize_y > 1)\r
233         {\r
234                 theOrigin_y -= 0.5 * (theSize_y - 1);\r
235                 theSize_y = 1;\r
236         }\r
237         theOrigin_x = bound(0, theOrigin_x, 1 - theSize_x);\r
238         theOrigin_y = bound(0, theOrigin_y, 1 - theSize_y);\r
239 \r
240         other.parent = me;\r
241         other.Container_origin = theOrigin;\r
242         other.Container_size = theSize;\r
243         me.setAlphaOf(me, other, theAlpha);\r
244 \r
245         entity f, l;\r
246         f = me.firstChild;\r
247         l = me.lastChild;\r
248 \r
249         if(l)\r
250                 l.nextSibling = other;\r
251         else\r
252                 me.firstChild = other;\r
253 \r
254         other.prevSibling = l;\r
255         other.nextSibling = NULL;\r
256         me.lastChild = other;\r
257 \r
258         draw_NeedResizeNotify = 1;\r
259 }\r
260 \r
261 void removeItemContainer(entity me, entity other)\r
262 {\r
263         if(other.parent != me)\r
264                 error("Can't remove from wrong container!");\r
265 \r
266         if(other.focusable)\r
267                 me.focusable -= 1;\r
268 \r
269         other.parent = NULL;\r
270 \r
271         entity n, p, f, l;\r
272         f = me.firstChild;\r
273         l = me.lastChild;\r
274         n = other.nextSibling;\r
275         p = other.prevSibling;\r
276 \r
277         if(p)\r
278                 p.nextSibling = n;\r
279         else\r
280                 me.firstChild = n;\r
281 \r
282         if(n)\r
283                 n.prevSibling = p;\r
284         else\r
285                 me.lastChild = p;\r
286 }\r
287 \r
288 void setFocusContainer(entity me, entity other)\r
289 {\r
290         if(other)\r
291                 if not(me.focused)\r
292                         error("Trying to set focus in a non-focused control!");\r
293         if(me.focusedChild == other)\r
294                 return;\r
295         //print(etos(me), ": focus changes from ", etos(me.focusedChild), " to ", etos(other), "\n");\r
296         if(me.focusedChild)\r
297         {\r
298                 me.focusedChild.focused = 0;\r
299                 me.focusedChild.focusLeave(me.focusedChild);\r
300         }\r
301         if(other)\r
302         {\r
303                 other.focused = 1;\r
304                 other.focusEnter(other);\r
305         }\r
306         me.focusedChild = other;\r
307 }\r
308 \r
309 void moveItemAfterContainer(entity me, entity other, entity dest)\r
310 {\r
311         // first: remove other from the chain\r
312         entity n, p, f, l;\r
313 \r
314         if(other.parent != me)\r
315                 error("Can't move in wrong container!");\r
316 \r
317         f = me.firstChild;\r
318         l = me.lastChild;\r
319         n = other.nextSibling;\r
320         p = other.prevSibling;\r
321 \r
322         if(p)\r
323                 p.nextSibling = n;\r
324         else\r
325                 me.firstChild = n;\r
326 \r
327         if(n)\r
328                 n.prevSibling = p;\r
329         else\r
330                 me.lastChild = p;\r
331         \r
332         // now other got removed. Insert it behind dest now.\r
333         other.prevSibling = dest;\r
334         if(dest)\r
335                 other.nextSibling = dest.nextSibling;\r
336         else\r
337                 other.nextSibling = me.firstChild;\r
338 \r
339         if(dest)\r
340                 dest.nextSibling = other;\r
341         else\r
342                 me.firstChild = other;\r
343 \r
344         if(other.nextSibling)\r
345                 other.nextSibling.prevSibling = other;\r
346         else\r
347                 me.lastChild = other;\r
348 }\r
349 \r
350 entity preferredFocusedGrandChildContainer(entity me)\r
351 {\r
352         entity e, e2;\r
353         entity best;\r
354 \r
355         best = NULL;\r
356 \r
357         for(e = me.firstChild; e; e = e.nextSibling)\r
358         {\r
359                 if(e.instanceOfContainer)\r
360                 {\r
361                         e2 = e.preferredFocusedGrandChild(e);\r
362                         if(e2)\r
363                                 if(!best || best.preferredFocusPriority < e2.preferredFocusPriority)\r
364                                         best = e2;\r
365                 }\r
366                 if(e)\r
367                         if(!best || best.preferredFocusPriority < e.preferredFocusPriority)\r
368                                 best = e;\r
369         }\r
370 \r
371         return best;\r
372 }\r
373 #endif\r