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