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