2 CLASS(ModalController) EXTENDS(Container)
\r
3 METHOD(ModalController, resizeNotify, void(entity, vector, vector, vector, vector))
\r
4 METHOD(ModalController, draw, void(entity))
\r
5 METHOD(ModalController, addItem, void(entity, entity, vector, vector, float))
\r
6 METHOD(ModalController, showChild, void(entity, entity, vector, vector, float))
\r
7 METHOD(ModalController, hideChild, void(entity, entity, float))
\r
8 METHOD(ModalController, hideAll, void(entity, float))
\r
9 METHOD(ModalController, addItem, void(entity, entity, vector, vector, float))
\r
10 METHOD(ModalController, addTab, void(entity, entity, entity))
\r
12 METHOD(ModalController, initializeDialog, void(entity, entity))
\r
14 METHOD(ModalController, switchState, void(entity, entity, float, float))
\r
15 ATTRIB(ModalController, origin, vector, '0 0 0')
\r
16 ATTRIB(ModalController, size, vector, '0 0 0')
\r
17 ATTRIB(ModalController, previousButton, entity, NULL)
\r
18 ATTRIB(ModalController, fadedAlpha, float, 0.3)
\r
19 ENDCLASS(ModalController)
\r
21 .entity tabSelectingButton;
\r
24 void TabButton_Click(entity button, entity tab); // assumes a button has set the above fields to its own absolute origin, its size, and the tab to activate
\r
25 void DialogOpenButton_Click(entity button, entity tab); // assumes a button has set the above fields to its own absolute origin, its size, and the tab to activate
\r
26 void DialogOpenButton_Click_withCoords(entity button, entity tab, vector theOrigin, vector theSize);
\r
27 void DialogCloseButton_Click(entity button, entity tab); // assumes a button has set the above fields to the tab to close
\r
30 #ifdef IMPLEMENTATION
\r
32 // modal dialog controller
\r
33 // handles a stack of dialog elements
\r
34 // each element can have one of the following states:
\r
35 // 0: hidden (fading out)
\r
36 // 1: visible (zooming in)
\r
37 // 2: greyed out (inactive)
\r
38 // While an animation is running, no item has focus. When an animation is done,
\r
39 // the topmost item gets focus.
\r
40 // The items are assumed to be added in overlapping order, that is, the lowest
\r
41 // window must get added first.
\r
44 // - to control a modal dialog:
\r
45 // - show modal dialog: me.showChild(me, childItem, buttonAbsOrigin, buttonAbsSize, 0) // childItem also gets focus
\r
46 // - dismiss modal dialog: me.hideChild(me, childItem, 0) // childItem fades out and relinquishes focus
\r
47 // - show first screen in m_show: me.hideAll(me, 1); me.showChild(me, me.firstChild, '0 0 0', '0 0 0', 1);
\r
48 // - to show a temporary dialog instead of the menu (teamselect): me.hideAll(me, 1); me.showChild(me, teamSelectDialog, '0 0 0', '0 0 0', 1);
\r
49 // - as a tabbed dialog control:
\r
50 // - to initialize: me.hideAll(me, 1); me.showChild(me, me.firstChild, '0 0 0', '0 0 0', 1);
\r
51 // - to show a tab: me.hideChild(me, currentTab, 0); me.showChild(me, newTab, buttonAbsOrigin, buttonAbsSize, 0);
\r
53 .vector ModalController_initialSize;
\r
54 .vector ModalController_initialOrigin;
\r
55 .float ModalController_initialAlpha;
\r
56 .vector ModalController_buttonSize;
\r
57 .vector ModalController_buttonOrigin;
\r
58 .float ModalController_state;
\r
59 .float ModalController_factor;
\r
60 .entity ModalController_controllingButton;
\r
62 void initializeDialogModalController(entity me, entity root)
\r
65 me.showChild(me, root, '0 0 0', '0 0 0', 1); // someone else animates for us
\r
68 void TabButton_Click(entity button, entity tab)
\r
70 if(tab.ModalController_state == 1)
\r
72 tab.parent.hideAll(tab.parent, 0);
\r
73 button.forcePressed = 1;
\r
74 tab.ModalController_controllingButton = button;
\r
75 tab.parent.showChild(tab.parent, tab, button.origin, button.size, 0);
\r
78 void DialogOpenButton_Click(entity button, entity tab)
\r
80 DialogOpenButton_Click_withCoords(button, tab, button.origin, button.size);
\r
83 void DialogOpenButton_Click_withCoords(entity button, entity tab, vector theOrigin, vector theSize)
\r
85 if(tab.ModalController_state)
\r
88 button.forcePressed = 1;
\r
89 tab.ModalController_controllingButton = button;
\r
90 tab.parent.showChild(tab.parent, tab, theOrigin, theSize, 0);
\r
93 void DialogCloseButton_Click(entity button, entity tab)
\r
95 tab.parent.hideChild(tab.parent, tab, 0);
\r
98 void resizeNotifyModalController(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
\r
100 me.resizeNotifyLie(me, relOrigin, relSize, absOrigin, absSize, ModalController_initialOrigin, ModalController_initialSize);
\r
103 void switchStateModalController(entity me, entity other, float state, float skipAnimation)
\r
105 float previousState;
\r
106 previousState = other.ModalController_state;
\r
107 if(state == previousState && !skipAnimation)
\r
109 other.ModalController_state = state;
\r
113 other.ModalController_factor = 1 - other.Container_alpha / other.ModalController_initialAlpha;
\r
117 other.ModalController_factor = other.Container_alpha / other.ModalController_initialAlpha;
\r
118 if(previousState == 0 && !skipAnimation)
\r
120 other.Container_origin = other.ModalController_buttonOrigin;
\r
121 other.Container_size = other.ModalController_buttonSize;
\r
126 other.ModalController_factor = bound(0, (1 - other.Container_alpha / other.ModalController_initialAlpha) / me.fadedAlpha, 1);
\r
127 // fading out halfway
\r
131 other.ModalController_factor = 1;
\r
134 void drawModalController(entity me)
\r
139 float f; // animation factor
\r
140 float df; // animation step size
\r
141 float prevFactor, targetFactor;
\r
142 vector targetOrigin, targetSize; float targetAlpha;
\r
145 for(e = me.firstChild; e; e = e.nextSibling)
\r
146 if(e.ModalController_state)
\r
149 me.switchState(me, front, 2, 0);
\r
153 me.switchState(me, front, 1, 0);
\r
155 df = frametime * 3; // animation speed
\r
157 for(e = me.firstChild; e; e = e.nextSibling)
\r
159 f = (e.ModalController_factor = min(1, e.ModalController_factor + df));
\r
160 if(e.ModalController_state)
\r
166 prevFactor = (1 - f) / (1 - f + df);
\r
167 targetFactor = df / (1 - f + df);
\r
175 if(e.ModalController_state == 2)
\r
177 // fading out partially
\r
178 targetOrigin = e.Container_origin; // stay as is
\r
179 targetSize = e.Container_size; // stay as is
\r
180 targetAlpha = me.fadedAlpha * e.ModalController_initialAlpha;
\r
182 else if(e.ModalController_state == 1)
\r
185 targetOrigin = e.ModalController_initialOrigin;
\r
186 targetSize = e.ModalController_initialSize;
\r
187 targetAlpha = e.ModalController_initialAlpha;
\r
194 targetOrigin = e.Container_origin; // stay as is
\r
195 targetSize = e.Container_size; // stay as is
\r
201 e.Container_origin = targetOrigin;
\r
202 e.Container_size = targetSize;
\r
203 me.setAlphaOf(me, e, targetAlpha);
\r
207 e.Container_origin = e.Container_origin * prevFactor + targetOrigin * targetFactor;
\r
208 e.Container_size = e.Container_size * prevFactor + targetSize * targetFactor;
\r
209 me.setAlphaOf(me, e, e.Container_alpha * prevFactor + targetAlpha * targetFactor);
\r
211 // assume: o == to * f_prev + X * (1 - f_prev)
\r
212 // make: o' = to * f + X * (1 - f)
\r
214 // X == (o - to * f_prev) / (1 - f_prev)
\r
215 // o' = to * f + (o - to * f_prev) / (1 - f_prev) * (1 - f)
\r
217 // o' = (to * (f - f_prev) + o * (1 - f)) / (1 - f_prev)
\r
219 e.Container_fontscale = globalToBoxSize(e.Container_size, e.ModalController_initialSize);
\r
221 if(animating || !me.focused)
\r
222 me.setFocus(me, NULL);
\r
224 me.setFocus(me, front);
\r
228 void addTabModalController(entity me, entity other, entity tabButton)
\r
230 me.addItem(me, other, '0 0 0', '1 1 1', 1);
\r
231 tabButton.onClick = TabButton_Click;
\r
232 tabButton.onClickEntity = other;
\r
233 other.tabSelectingButton = tabButton;
\r
234 if(other == me.firstChild)
\r
236 tabButton.forcePressed = 1;
\r
237 other.ModalController_controllingButton = tabButton;
\r
238 me.showChild(me, other, '0 0 0', '0 0 0', 1);
\r
242 void addItemModalController(entity me, entity other, vector theOrigin, vector theSize, float theAlpha)
\r
244 addItemContainer(me, other, theOrigin, theSize, (other == me.firstChild) ? theAlpha : 0);
\r
245 other.ModalController_initialSize = other.Container_size;
\r
246 other.ModalController_initialOrigin = other.Container_origin;
\r
247 other.ModalController_initialAlpha = theAlpha; // hope Container never modifies this
\r
250 void showChildModalController(entity me, entity other, vector theOrigin, vector theSize, float skipAnimation)
\r
252 if(other.ModalController_state == 0 || skipAnimation)
\r
254 me.setFocus(me, NULL);
\r
257 other.ModalController_buttonOrigin = globalToBox(theOrigin, me.origin, me.size);
\r
258 other.ModalController_buttonSize = globalToBoxSize(theSize, me.size);
\r
260 me.switchState(me, other, 1, skipAnimation);
\r
261 } // zoom in from button (factor increases)
\r
264 void hideAllModalController(entity me, float skipAnimation)
\r
267 for(e = me.firstChild; e; e = e.nextSibling)
\r
268 me.hideChild(me, e, skipAnimation);
\r
271 void hideChildModalController(entity me, entity other, float skipAnimation)
\r
273 if(other.ModalController_state || skipAnimation)
\r
275 me.setFocus(me, NULL);
\r
276 me.switchState(me, other, 0, skipAnimation);
\r
277 if(other.ModalController_controllingButton)
\r
279 other.ModalController_controllingButton.forcePressed = 0;
\r
280 other.ModalController_controllingButton = NULL;
\r
282 } // just alpha fade out (factor increases and decreases alpha)
\r