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