]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/menu/item/modalcontroller.qc
Merge branch 'master' into 'master'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / menu / item / modalcontroller.qc
1 #include "modalcontroller.qh"
2
3 #include "button.qh"
4
5         .vector ModalController_initialSize;
6         .vector ModalController_initialOrigin;
7         .vector ModalController_initialFontScale;
8         .float ModalController_initialAlpha;
9         .vector ModalController_buttonSize;
10         .vector ModalController_buttonOrigin;
11         .float ModalController_state;
12         .float ModalController_factor;
13         .entity ModalController_controllingButton;
14
15         void ModalController_initializeDialog(entity me, entity root)
16         {
17                 me.hideAll(me, 1);
18                 me.showChild(me, root, '0 0 0', '0 0 0', 1);  // someone else animates for us
19         }
20
21         void TabButton_Click(entity button, entity tab)
22         {
23                 if (tab.ModalController_state == 1) return;
24                 tab.parent.hideAll(tab.parent, 0);
25                 button.forcePressed = 1;
26                 tab.ModalController_controllingButton = button;
27                 tab.parent.showChild(tab.parent, tab, button.origin, button.size, 0);
28         }
29
30         void DialogOpenButton_Click(entity button, entity tab)
31         {
32                 DialogOpenButton_Click_withCoords(button, tab, button.origin, button.size);
33         }
34
35         void DialogOpenButton_Click_withCoords(entity button, entity tab, vector theOrigin, vector theSize)
36         {
37                 if (tab.ModalController_state) return;
38                 if (button) button.forcePressed = 1;
39                 if (tab.parent.focusedChild) tab.parent.focusedChild.saveFocus(tab.parent.focusedChild);
40                 tab.ModalController_controllingButton = button;
41                 tab.parent.showChild(tab.parent, tab, theOrigin, theSize, 0);
42         }
43
44         void DialogCloseButton_Click(entity button, entity tab)
45         {
46                 tab.parent.hideChild(tab.parent, tab, 0);
47         }
48
49         void ModalController_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
50         {
51                 me.resizeNotifyLie(me, relOrigin, relSize, absOrigin, absSize, ModalController_initialOrigin, ModalController_initialSize, ModalController_initialFontScale);
52         }
53
54         void ModalController_switchState(entity me, entity other, float state, float skipAnimation)
55         {
56                 float previousState;
57                 previousState = other.ModalController_state;
58                 if (state == previousState && !skipAnimation) return;
59                 other.ModalController_state = state;
60                 switch (state)
61                 {
62                         case 0:
63                                 other.ModalController_factor = 1 - other.Container_alpha / other.ModalController_initialAlpha;
64                                 // fading out
65                                 break;
66                         case 1:
67                                 other.ModalController_factor = other.Container_alpha / other.ModalController_initialAlpha;
68                                 if (previousState == 0 && !skipAnimation)
69                                 {
70                                         other.Container_origin = other.ModalController_buttonOrigin;
71                                         other.Container_size = other.ModalController_buttonSize;
72                                 }
73                                 // zooming in
74                                 break;
75                         case 2:
76                                 other.ModalController_factor = bound(0, (1 - other.Container_alpha / other.ModalController_initialAlpha) / me.fadedAlpha, 1);
77                                 // fading out halfway
78                                 break;
79                 }
80                 if (skipAnimation) other.ModalController_factor = 1;
81         }
82
83         void ModalController_draw(entity me)
84         {
85                 entity e;
86                 entity front;
87                 float animating;
88                 float f;  // animation factor
89                 float df; // animation step size
90                 float prevFactor, targetFactor;
91                 vector targetOrigin, targetSize;
92                 float targetAlpha;
93                 vector fs;
94                 animating = 0;
95
96                 front = NULL;
97                 for (e = me.firstChild; e; e = e.nextSibling)
98                         if (e.ModalController_state)
99                         {
100                                 if (front) me.switchState(me, front, 2, 0);
101                                 front = e;
102                         }
103                 if (front) me.switchState(me, front, 1, 0);
104
105                 df = frametime * 3;  // animation speed
106
107                 for (e = me.firstChild; e; e = e.nextSibling)
108                 {
109                         if (e.ModalController_state == 2)
110                         {
111                                 // fading out partially
112                                 targetOrigin = e.Container_origin; // stay as is
113                                 targetSize = e.Container_size;     // stay as is
114                                 targetAlpha = me.fadedAlpha * e.ModalController_initialAlpha;
115                         }
116                         else if (e.ModalController_state == 1)
117                         {
118                                 // zooming in
119                                 targetOrigin = e.ModalController_initialOrigin;
120                                 targetSize = e.ModalController_initialSize;
121                                 targetAlpha = e.ModalController_initialAlpha;
122                         }
123                         else
124                         {
125                                 // fading out
126                                 targetOrigin = e.Container_origin; // stay as is
127                                 targetSize = e.Container_size;     // stay as is
128                                 targetAlpha = 0;
129                         }
130
131                         f = (e.ModalController_factor = min(1, e.ModalController_factor + df));
132                         if (f == 1)
133                         {
134                                 prevFactor = 0;
135                                 targetFactor = 1;
136                                 e.Container_origin = targetOrigin;
137                                 e.Container_size = targetSize;
138                                 me.setAlphaOf(me, e, targetAlpha);
139                         }
140                         else
141                         {
142                                 prevFactor = (1 - f) / (1 - f + df);
143                                 if (!e.ModalController_state)  // optimize code and avoid precision errors
144                                 {
145                                         me.setAlphaOf(me, e, e.Container_alpha  * prevFactor);
146                                 }
147                                 else
148                                 {
149                                         animating = 1;
150                                         targetFactor = df / (1 - f + df);
151
152                                         if (e.ModalController_state == 1)
153                                         {
154                                                 e.Container_origin = e.Container_origin * prevFactor + targetOrigin * targetFactor;
155                                                 e.Container_size   = e.Container_size   * prevFactor + targetSize   * targetFactor;
156                                         }
157                                         me.setAlphaOf(me, e, e.Container_alpha  * prevFactor + targetAlpha  * targetFactor);
158                                 }
159                         }
160                         // assume: o == to * f_prev + X * (1 - f_prev)
161                         // make:   o' = to * f  + X * (1 - f)
162                         // -->
163                         // X == (o - to * f_prev) / (1 - f_prev)
164                         // o' = to * f + (o - to * f_prev) / (1 - f_prev) * (1 - f)
165                         // --> (maxima)
166                         // o' = (to * (f - f_prev) + o * (1 - f)) / (1 - f_prev)
167
168                         if (e.ModalController_state == 1)
169                         {
170                                 fs = globalToBoxSize(e.Container_size, e.ModalController_initialSize);
171                                 e.Container_fontscale_x = fs.x * e.ModalController_initialFontScale.x;
172                                 e.Container_fontscale_y = fs.y * e.ModalController_initialFontScale.y;
173                         }
174                 }
175
176                 if (animating || !me.focused) me.setFocus(me, NULL);
177                 else me.setFocus(me, front);
178                 SUPER(ModalController).draw(me);
179         }
180
181         void ModalController_addTab(entity me, entity other, entity tabButton)
182         {
183                 me.addItem(me, other, '0 0 0', '1 1 1', 1);
184                 tabButton.onClick = TabButton_Click;
185                 tabButton.onClickEntity = other;
186                 other.tabSelectingButton = tabButton;
187                 if (other == me.firstChild)
188                 {
189                         tabButton.forcePressed = 1;
190                         other.ModalController_controllingButton = tabButton;
191                         me.showChild(me, other, '0 0 0', '0 0 0', 1);
192                 }
193         }
194
195         void ModalController_addItem(entity me, entity other, vector theOrigin, vector theSize, float theAlpha)
196         {
197                 SUPER(ModalController).addItem(me, other, theOrigin, theSize, (other == me.firstChild) ? theAlpha : 0);
198                 other.ModalController_initialFontScale = other.Container_fontscale;
199                 other.ModalController_initialSize = other.Container_size;
200                 other.ModalController_initialOrigin = other.Container_origin;
201                 other.ModalController_initialAlpha = theAlpha;  // hope Container never modifies this
202                 if (other.ModalController_initialFontScale == '0 0 0') other.ModalController_initialFontScale = '1 1 0';
203         }
204
205         void ModalController_showChild(entity me, entity other, vector theOrigin, vector theSize, float skipAnimation)
206         {
207                 if (other.ModalController_state == 0 || skipAnimation)
208                 {
209                         me.setFocus(me, NULL);
210                         if (!skipAnimation)
211                         {
212                                 other.ModalController_buttonOrigin = globalToBox(theOrigin, me.origin, me.size);
213                                 other.ModalController_buttonSize = globalToBoxSize(theSize, me.size);
214                         }
215                         me.switchState(me, other, 1, skipAnimation);
216                 }  // zoom in from button (factor increases)
217         }
218
219         void ModalController_hideAll(entity me, float skipAnimation)
220         {
221                 entity e;
222                 for (e = me.firstChild; e; e = e.nextSibling)
223                         me.hideChild(me, e, skipAnimation);
224         }
225
226         void ModalController_hideChild(entity me, entity other, float skipAnimation)
227         {
228                 if (other.ModalController_state || skipAnimation)
229                 {
230                         me.setFocus(me, NULL);
231                         me.switchState(me, other, 0, skipAnimation);
232                         if (other.ModalController_controllingButton)
233                         {
234                                 other.ModalController_controllingButton.forcePressed = 0;
235                                 other.ModalController_controllingButton = NULL;
236                         }
237                 }  // just alpha fade out (factor increases and decreases alpha)
238         }