1 /**
2 * @file
3 */
4
5 /*
6 Copyright (C) 2002-2013 UFO: Alien Invasion.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
17 See the GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23 */
24
25 #include "ui_main.h"
26 #include "ui_internal.h"
27 #include "ui_input.h"
28 #include "ui_node.h"
29 #include "ui_popup.h"
30 #include "node/ui_node_abstractnode.h"
31 #include "node/ui_node_window.h"
32 #include "node/ui_node_battlescape.h"
33
34 #include "../cl_video.h"
35 #include "../input/cl_input.h"
36 #include "../input/cl_keys.h"
37
38 #define WINDOWEXTRADATA(node) UI_EXTRADATA(node, windowExtraData_t)
39 #define WINDOWEXTRADATACONST(node) UI_EXTRADATACONST(node, windowExtraData_t)
40
41 /**
42 * @brief Window name use as alternative for option
43 */
44 static cvar_t* ui_sys_main;
45
46 /**
47 * @brief Main window of a stack
48 */
49 static cvar_t* ui_sys_active;
50
51 /**
52 * @brief Returns the ID of the last fullscreen ID. Before this, window should be hidden.
53 * @return The last full screen window on the screen, else 0. If the stack is empty, return -1
54 */
UI_GetLastFullScreenWindow(void)55 int UI_GetLastFullScreenWindow (void)
56 {
57 /* stack pos */
58 int pos = ui_global.windowStackPos - 1;
59 while (pos > 0) {
60 if (UI_WindowIsFullScreen(ui_global.windowStack[pos]))
61 break;
62 pos--;
63 }
64 /* if we find nothing we return 0 */
65 return pos;
66 }
67
68 /**
69 * @brief Move the window on top of compatible windows.
70 * "Compatible" mean non full screen windows, and windows
71 * with the same window parent.
72 * @param window Window we want to move
73 */
UI_MoveWindowOnTop(uiNode_t * window)74 void UI_MoveWindowOnTop (uiNode_t* window)
75 {
76 int i, j;
77
78 if (UI_WindowIsFullScreen(window))
79 return;
80
81 /* get window index */
82 for (i = 0; i < ui_global.windowStackPos; i++) {
83 if (ui_global.windowStack[i] == window)
84 break;
85 }
86
87 /* search the last compatible window */
88 for (j = i; j < ui_global.windowStackPos; j++) {
89 if (UI_WindowIsFullScreen(ui_global.windowStack[j]))
90 break;
91 if (WINDOWEXTRADATA(window).parent != WINDOWEXTRADATA(ui_global.windowStack[j]).parent)
92 break;
93 }
94 if (i + 1 == j)
95 return;
96
97 /* translate windows */
98 for (; i < j - 1; i++) {
99 ui_global.windowStack[i] = ui_global.windowStack[i+1];
100 }
101 /* add the current window on top */
102 ui_global.windowStack[i] = window;
103 }
104
105 /**
106 * @brief Remove the window from the window stack
107 * @param[in] window The window to remove from the stack
108 * @todo Why dont we call onClose?
109 */
UI_DeleteWindowFromStack(uiNode_t * window)110 static void UI_DeleteWindowFromStack (uiNode_t* window)
111 {
112 int i;
113
114 /* get window index */
115 for (i = 0; i < ui_global.windowStackPos; i++) {
116 if (ui_global.windowStack[i] == window)
117 break;
118 }
119
120 /* update stack */
121 if (i < ui_global.windowStackPos) {
122 ui_global.windowStackPos--;
123 for (; i < ui_global.windowStackPos; i++)
124 ui_global.windowStack[i] = ui_global.windowStack[i + 1];
125 UI_InvalidateMouse();
126 }
127 }
128
129 /**
130 * @brief Searches the position in the current window stack for a given window id
131 * @return -1 if the window is not on the stack
132 */
UI_GetWindowPositionFromStackByName(const char * name)133 static inline int UI_GetWindowPositionFromStackByName (const char* name)
134 {
135 for (int i = 0; i < ui_global.windowStackPos; i++)
136 if (Q_streq(ui_global.windowStack[i]->name, name))
137 return i;
138
139 return -1;
140 }
141
142 /**
143 * @brief Insert a window at a position of the stack
144 * @param[in] window The window to insert
145 * @param[in] position Where we want to add the window (0 is the deeper element of the stack)
146 */
UI_InsertWindowIntoStack(uiNode_t * window,int position)147 static inline void UI_InsertWindowIntoStack (uiNode_t* window, int position)
148 {
149 assert(position <= ui_global.windowStackPos);
150 assert(position > 0);
151 assert(window != nullptr);
152
153 /* create space for the new window */
154 for (int i = ui_global.windowStackPos; i > position; i--) {
155 ui_global.windowStack[i] = ui_global.windowStack[i - 1];
156 }
157 /* insert */
158 ui_global.windowStack[position] = window;
159 ui_global.windowStackPos++;
160 }
161
162 /**
163 * @brief Push a window onto the window stack
164 * @param[in] name Name of the window to push onto window stack
165 * @param[in] parentName Window name to link as parent-child (else nullptr)
166 * @param[in] params List of string parameters to send to the onWindowOpened method.
167 * It can be nullptr when there is no parameters, else this object must be freed by the caller.
168 * @return A pointer to @c uiNode_t
169 */
UI_PushWindow(const char * name,const char * parentName,linkedList_t * params)170 uiNode_t* UI_PushWindow (const char* name, const char* parentName, linkedList_t* params)
171 {
172 UI_ReleaseInput();
173
174 uiNode_t* window = UI_GetWindow(name);
175 if (window == nullptr) {
176 Com_Printf("Window \"%s\" not found.\n", name);
177 return nullptr;
178 }
179
180 UI_DeleteWindowFromStack(window);
181
182 if (ui_global.windowStackPos < UI_MAX_WINDOWSTACK)
183 if (parentName) {
184 const int parentPos = UI_GetWindowPositionFromStackByName(parentName);
185 if (parentPos == -1) {
186 Com_Printf("Didn't find parent window \"%s\" for window push of \"%s\"\n", parentName, name);
187 return nullptr;
188 }
189 UI_InsertWindowIntoStack(window, parentPos + 1);
190 WINDOWEXTRADATA(window).parent = ui_global.windowStack[parentPos];
191 } else
192 ui_global.windowStack[ui_global.windowStackPos++] = window;
193 else
194 Com_Printf("Window stack overflow\n");
195
196 UI_Node_WindowOpened(window, params);
197
198 /* change from e.g. console mode to game input mode (fetch input) */
199 Key_SetDest(key_game);
200
201 UI_InvalidateMouse();
202 return window;
203 }
204
205 /**
206 * @brief Complete function for ui_push
207 * @sa Cmd_AddParamCompleteFunction
208 * @sa UI_PushWindow
209 * @note Does not really complete the input - but shows at least all parsed windows
210 */
UI_CompleteWithWindow(const char * partial,const char ** match)211 int UI_CompleteWithWindow (const char* partial, const char** match)
212 {
213 int n = 0;
214 for (uiNode_t** i = ui_global.windows, ** const end = i + ui_global.numWindows; i != end; ++i) {
215 char const* const name = (*i)->name;
216 if (Cmd_GenericCompleteFunction(name, partial, match)) {
217 Com_Printf("%s\n", name);
218 ++n;
219 }
220 }
221 return n;
222 }
223
224 /**
225 * @brief Console function to push a child window onto the window stack
226 * @sa UI_PushWindow
227 */
UI_PushChildWindow_f(void)228 static void UI_PushChildWindow_f (void)
229 {
230 if (Cmd_Argc() > 1)
231 UI_PushWindow(Cmd_Argv(1), Cmd_Argv(2));
232 else
233 Com_Printf("Usage: %s <name> <parentname>\n", Cmd_Argv(0));
234 }
235
236 /**
237 * @brief Console function to push a window onto the window stack
238 * @sa UI_PushWindow
239 */
UI_PushWindow_f(void)240 static void UI_PushWindow_f (void)
241 {
242 if (Cmd_Argc() == 0) {
243 Com_Printf("Usage: %s <name> <params>\n", Cmd_Argv(0));
244 return;
245 }
246
247 linkedList_t* params = nullptr;
248 for (int i = 2; i < Cmd_Argc(); i++) {
249 LIST_AddString(¶ms, Cmd_Argv(i));
250 }
251 UI_PushWindow(Cmd_Argv(1), nullptr, params);
252 LIST_Delete(¶ms);
253 }
254
255 /**
256 * @brief Console function to push a dropdown window at a position. It work like UI_PushWindow but move the window at the right position
257 * @sa UI_PushWindow
258 * @note The usage is "ui_push_dropdown sourcenode pointposition destinationnode pointposition"
259 * sourcenode must be a node into the window we want to push,
260 * we will move the window to have sourcenode over destinationnode
261 * pointposition select for each node a position (like a corner).
262 */
UI_PushDropDownWindow_f(void)263 static void UI_PushDropDownWindow_f (void)
264 {
265 if (Cmd_Argc() != 4 && Cmd_Argc() != 5) {
266 Com_Printf("Usage: %s <source-anchor> <point-in-source-anchor> <dest-anchor> <point-in-dest-anchor>\n", Cmd_Argv(0));
267 return;
268 }
269
270 /* get the source anchor */
271 uiNode_t* node = UI_GetNodeByPath(Cmd_Argv(1));
272 if (node == nullptr) {
273 Com_Printf("UI_PushDropDownWindow_f: Node '%s' doesn't exist\n", Cmd_Argv(1));
274 return;
275 }
276 size_t writtenBytes;
277 int direction;
278 int result = Com_ParseValue(&direction, Cmd_Argv(2), V_INT, 0, sizeof(direction), &writtenBytes);
279 if (result != RESULT_OK) {
280 Com_Printf("UI_PushDropDownWindow_f: '%s' in not a V_INT\n", Cmd_Argv(2));
281 return;
282 }
283 vec2_t source;
284 vec2_t destination;
285 UI_NodeGetPoint(node, source, direction);
286 UI_NodeRelativeToAbsolutePoint(node, source);
287
288 /* get the destination anchor */
289 if (Q_streq(Cmd_Argv(4), "mouse")) {
290 destination[0] = mousePosX;
291 destination[1] = mousePosY;
292 } else {
293 /* get the source anchor */
294 node = UI_GetNodeByPath(Cmd_Argv(3));
295 if (node == nullptr) {
296 Com_Printf("UI_PushDropDownWindow_f: Node '%s' doesn't exist\n", Cmd_Argv(3));
297 return;
298 }
299 result = Com_ParseValue(&direction, Cmd_Argv(4), V_INT, 0, sizeof(direction), &writtenBytes);
300 if (result != RESULT_OK) {
301 Com_Printf("UI_PushDropDownWindow_f: '%s' in not a V_INT\n", Cmd_Argv(4));
302 return;
303 }
304 UI_NodeGetPoint(node, destination, direction);
305 UI_NodeRelativeToAbsolutePoint(node, destination);
306 }
307
308 /* update the window and push it */
309 node = UI_GetNodeByPath(Cmd_Argv(1));
310 if (node == nullptr) {
311 Com_Printf("UI_PushDropDownWindow_f: Node '%s' doesn't exist\n", Cmd_Argv(1));
312 return;
313 }
314 node = node->root;
315 node->box.pos[0] += destination[0] - source[0];
316 node->box.pos[1] += destination[1] - source[1];
317 UI_PushWindow(node->name);
318 }
319
UI_RemoveWindowAtPositionFromStack(int position)320 static void UI_RemoveWindowAtPositionFromStack (int position)
321 {
322 assert(position < ui_global.windowStackPos);
323 assert(position >= 0);
324
325 /* create space for the new window */
326 for (int i = position; i < ui_global.windowStackPos; i++) {
327 ui_global.windowStack[i] = ui_global.windowStack[i + 1];
328 }
329 ui_global.windowStack[ui_global.windowStackPos--] = nullptr;
330 }
331
UI_CloseAllWindow(void)332 static void UI_CloseAllWindow (void)
333 {
334 for (int i = ui_global.windowStackPos - 1; i >= 0; i--) {
335 uiNode_t* window = ui_global.windowStack[i];
336
337 UI_Node_WindowClosed(window);
338
339 /* safe: unlink window */
340 WINDOWEXTRADATA(window).parent = nullptr;
341 ui_global.windowStackPos--;
342 ui_global.windowStack[ui_global.windowStackPos] = nullptr;
343 }
344 }
345
346 /**
347 * @brief Init the stack to start with a window, and have an alternative window with ESC
348 * @note Illustration about when/how we should use this http://ufoai.org/wiki/index.php/Image:UI_InitStack.jpg
349 * @param[in] activeWindow The first active window of the stack, else nullptr
350 * @param[in] mainWindow The alternative window, else nullptr if nothing
351 * @todo remove Cvar_Set we have direct access to the cvar
352 * @todo We should only call it a very few time. When we switch from/to this different par of the game: main-option-interface / geoscape-and-base / battlescape
353 */
UI_InitStack(const char * activeWindow,const char * mainWindow)354 void UI_InitStack (const char* activeWindow, const char* mainWindow)
355 {
356 UI_FinishInit();
357 UI_PopWindow(true);
358
359 assert(activeWindow != nullptr);
360 Cvar_Set("ui_sys_active", "%s", activeWindow);
361 /* prevent calls before UI script initialization */
362 if (ui_global.numWindows != 0) {
363 UI_PushWindow(activeWindow);
364 }
365
366 if (mainWindow)
367 Cvar_Set("ui_sys_main", "%s", mainWindow);
368 }
369
370 /**
371 * @brief Check if a named window is on the stack if active windows
372 */
UI_IsWindowOnStack(const char * name)373 bool UI_IsWindowOnStack (const char* name)
374 {
375 return UI_GetWindowPositionFromStackByName(name) != -1;
376 }
377
378 /**
379 * @todo Find better name
380 */
UI_CloseWindowByRef(uiNode_t * window)381 static void UI_CloseWindowByRef (uiNode_t* window)
382 {
383 /** @todo If the focus is not on the window we close, we don't need to remove it */
384 UI_ReleaseInput();
385
386 assert(ui_global.windowStackPos);
387 int i = UI_GetWindowPositionFromStackByName(window->name);
388 if (i == -1) {
389 Com_Printf("Window '%s' is not on the active stack\n", window->name);
390 return;
391 }
392
393 /* close child */
394 while (i + 1 < ui_global.windowStackPos) {
395 uiNode_t* m = ui_global.windowStack[i + 1];
396 if (WINDOWEXTRADATA(m).parent != window) {
397 break;
398 }
399
400 UI_Node_WindowClosed(window);
401 WINDOWEXTRADATA(m).parent = nullptr;
402 UI_RemoveWindowAtPositionFromStack(i + 1);
403 }
404
405 /* close the window */
406 UI_Node_WindowClosed(window);
407 WINDOWEXTRADATA(window).parent = nullptr;
408 UI_RemoveWindowAtPositionFromStack(i);
409
410 UI_InvalidateMouse();
411 }
412
UI_CloseWindow(const char * name)413 void UI_CloseWindow (const char* name)
414 {
415 uiNode_t* window = UI_GetWindow(name);
416 if (window == nullptr) {
417 Com_Printf("Window '%s' not found\n", name);
418 return;
419 }
420
421 /* found the correct add it to stack or bring it on top */
422 UI_CloseWindowByRef(window);
423 }
424
425 /**
426 * @brief Pops a window from the window stack
427 * @param[in] all If true pop all windows from stack
428 * @sa UI_PopWindow_f
429 */
UI_PopWindow(bool all)430 void UI_PopWindow (bool all)
431 {
432 uiNode_t* oldfirst = ui_global.windowStack[0];
433
434 if (all) {
435 UI_CloseAllWindow();
436 } else {
437 uiNode_t* mainWindow = ui_global.windowStack[ui_global.windowStackPos - 1];
438 if (!ui_global.windowStackPos)
439 return;
440 if (WINDOWEXTRADATA(mainWindow).parent)
441 mainWindow = WINDOWEXTRADATA(mainWindow).parent;
442 UI_CloseWindowByRef(mainWindow);
443
444 if (ui_global.windowStackPos == 0) {
445 /* ui_sys_main contains the window that is the very first window and should be
446 * pushed back onto the stack (otherwise there would be no window at all
447 * right now) */
448 if (Q_streq(oldfirst->name, ui_sys_main->string)) {
449 if (ui_sys_active->string[0] != '\0')
450 UI_PushWindow(ui_sys_active->string);
451 if (!ui_global.windowStackPos)
452 UI_PushWindow(ui_sys_main->string);
453 } else {
454 if (ui_sys_main->string[0] != '\0')
455 UI_PushWindow(ui_sys_main->string);
456 if (!ui_global.windowStackPos)
457 UI_PushWindow(ui_sys_active->string);
458 }
459 }
460
461 uiNode_t* activeWindow = UI_GetActiveWindow();
462 UI_Node_WindowActivate(activeWindow);
463 }
464
465 /* change from e.g. console mode to game input mode (fetch input) */
466 Key_SetDest(key_game);
467 }
468
469 /**
470 * @brief Console function to close a named window
471 * @sa UI_PushWindow
472 */
UI_CloseWindow_f(void)473 static void UI_CloseWindow_f (void)
474 {
475 if (Cmd_Argc() != 2) {
476 Com_Printf("Usage: %s <name>\n", Cmd_Argv(0));
477 return;
478 }
479
480 UI_CloseWindow(Cmd_Argv(1));
481 }
482
UI_PopWindowWithEscKey(void)483 void UI_PopWindowWithEscKey (void)
484 {
485 /* nothing if stack is empty */
486 if (ui_global.windowStackPos == 0)
487 return;
488
489 /* some window can prevent escape */
490 const uiNode_t* window = ui_global.windowStack[ui_global.windowStackPos - 1];
491 if (WINDOWEXTRADATACONST(window).preventTypingEscape)
492 return;
493
494 UI_PopWindow();
495 }
496
497 /**
498 * @brief Console function to pop a window from the window stack
499 * @sa UI_PopWindow
500 */
UI_PopWindow_f(void)501 static void UI_PopWindow_f (void)
502 {
503 if (Cmd_Argc() > 1) {
504 Com_Printf("Usage: %s\n", Cmd_Argv(0));
505 return;
506 }
507
508 UI_PopWindow();
509 }
510
511 /**
512 * @brief Returns the current active window from the window stack or nullptr if there is none
513 * @return uiNode_t pointer from window stack
514 * @sa UI_GetWindow
515 */
UI_GetActiveWindow(void)516 uiNode_t* UI_GetActiveWindow (void)
517 {
518 return (ui_global.windowStackPos > 0 ? ui_global.windowStack[ui_global.windowStackPos - 1] : nullptr);
519 }
520
521 /**
522 * @brief Returns the name of the current window
523 * @return Active window name, else empty string
524 * @sa UI_GetActiveWIndow
525 */
UI_GetActiveWindowName(void)526 const char* UI_GetActiveWindowName (void)
527 {
528 const uiNode_t* window = UI_GetActiveWindow();
529 if (window == nullptr)
530 return "";
531 return window->name;
532 }
533
534 /**
535 * @brief Check if a point is over a window from the stack
536 * @sa IN_Parse
537 */
UI_IsMouseOnWindow(void)538 bool UI_IsMouseOnWindow (void)
539 {
540 if (UI_GetMouseCapture() != nullptr)
541 return true;
542
543 if (ui_global.windowStackPos != 0) {
544 if (WINDOWEXTRADATA(ui_global.windowStack[ui_global.windowStackPos - 1]).dropdown)
545 return true;
546 }
547
548 const uiNode_t* hovered = UI_GetHoveredNode();
549 if (hovered) {
550 /* else if it is a render node */
551 if (UI_Node_IsBattleScape(hovered)) {
552 return false;
553 }
554 return true;
555 }
556
557 return true;
558 }
559
560 /**
561 * @brief Searches all windows for the specified one
562 * @param[in] name Name of the window we search
563 * @return The window found, else nullptr
564 * @note Use dichotomic search
565 * @sa UI_GetActiveWindow
566 */
UI_GetWindow(const char * name)567 uiNode_t* UI_GetWindow (const char* name)
568 {
569 unsigned char min = 0;
570 unsigned char max = ui_global.numWindows;
571
572 while (min != max) {
573 const int mid = (min + max) >> 1;
574 const int diff = strcmp(ui_global.windows[mid]->name, name);
575 assert(mid < max);
576 assert(mid >= min);
577
578 if (diff == 0)
579 return ui_global.windows[mid];
580
581 if (diff > 0)
582 max = mid;
583 else
584 min = mid + 1;
585 }
586
587 return nullptr;
588 }
589
590 /**
591 * @brief Invalidate all windows of the current stack.
592 */
UI_InvalidateStack(void)593 void UI_InvalidateStack (void)
594 {
595 for (int pos = 0; pos < ui_global.windowStackPos; pos++) {
596 UI_Invalidate(ui_global.windowStack[pos]);
597 }
598 Cvar_SetValue("ui_sys_screenwidth", viddef.virtualWidth);
599 Cvar_SetValue("ui_sys_screenheight", viddef.virtualHeight);
600 }
601
602 /**
603 * @brief Sets new x and y coordinates for a given window
604 * @todo remove that
605 */
UI_SetNewWindowPos(uiNode_t * window,int x,int y)606 void UI_SetNewWindowPos (uiNode_t* window, int x, int y)
607 {
608 if (window)
609 Vector2Set(window->box.pos, x, y);
610 }
611
612 /**
613 * @brief Add a new window to the list of all windows
614 * @note Sort windows by alphabet
615 */
UI_InsertWindow(uiNode_t * window)616 void UI_InsertWindow (uiNode_t* window)
617 {
618
619 if (ui_global.numWindows >= UI_MAX_WINDOWS)
620 Com_Error(ERR_FATAL, "UI_InsertWindow: hit UI_MAX_WINDOWS");
621
622 /* search the insertion position */
623 int pos;
624 for (pos = 0; pos < ui_global.numWindows; pos++) {
625 const uiNode_t* node = ui_global.windows[pos];
626 if (strcmp(window->name, node->name) < 0)
627 break;
628 }
629
630 /* create the space */
631 for (int i = ui_global.numWindows - 1; i >= pos; i--)
632 ui_global.windows[i + 1] = ui_global.windows[i];
633
634 /* insert */
635 ui_global.windows[pos] = window;
636 ui_global.numWindows++;
637 }
638
639 /**
640 * @brief Finish windows initialization
641 * @note private function
642 */
UI_FinishWindowsInit(void)643 void UI_FinishWindowsInit (void)
644 {
645 for (int i = 0; i < ui_global.numWindows; i++) {
646 uiNode_t* window = ui_global.windows[i];
647 if (WINDOWEXTRADATA(window).onScriptLoaded)
648 UI_ExecuteEventActions(window, WINDOWEXTRADATA(window).onScriptLoaded);
649 }
650 }
651
UI_InitStack_f(void)652 static void UI_InitStack_f (void)
653 {
654 if (Cmd_Argc() < 2) {
655 Com_Printf("Usage: %s <mainwindow> [<optionwindow>]\n", Cmd_Argv(0));
656 return;
657 }
658
659 const char* mainWindow = Cmd_Argv(1);
660 const char* optionWindow = nullptr;
661 if (Cmd_Argc() == 3) {
662 optionWindow = Cmd_Argv(2);
663 }
664
665 UI_InitStack(mainWindow, optionWindow);
666 }
667
668 /**
669 * @brief Display in the conde the tree of nodes
670 */
UI_DebugTree(const uiNode_t * node,int depth)671 static void UI_DebugTree (const uiNode_t* node, int depth)
672 {
673 for (int i = 0; i < depth; i++) {
674 Com_Printf(" ");
675 }
676 Com_Printf("+ %s %s\n", UI_Node_GetWidgetName(node), node->name);
677
678 const uiNode_t* child = node->firstChild;
679 while (child) {
680 UI_DebugTree(child, depth + 1);
681 child = child->next;
682 }
683 }
684
UI_DebugTree_f(void)685 static void UI_DebugTree_f (void)
686 {
687 if (Cmd_Argc() != 2) {
688 Com_Printf("Usage: %s <mainwindow>\n", Cmd_Argv(0));
689 return;
690 }
691
692 const char* window = Cmd_Argv(1);
693 const uiNode_t* node = UI_GetWindow(window);
694 UI_DebugTree(node, 0);
695 }
696
UI_Popup_f(void)697 static void UI_Popup_f (void)
698 {
699 if (Cmd_Argc() != 3) {
700 Com_Printf("Usage: %s <header> <body>\n", Cmd_Argv(0));
701 return;
702 }
703
704 const char* header = Cmd_Argv(1);
705 const char* body = Cmd_Argv(2);
706 UI_Popup(header, body);
707 }
708
UI_InitWindows(void)709 void UI_InitWindows (void)
710 {
711 ui_sys_main = Cvar_Get("ui_sys_main", "", 0, "This is the main window id that is at the very first window stack - also see ui_sys_active");
712 ui_sys_active = Cvar_Get("ui_sys_active", "", 0, "The active window we will return to when hitting esc once - also see ui_sys_main");
713
714 /* add command */
715 Cmd_AddCommand("ui_push", UI_PushWindow_f, "Push a window to the window stack");
716 Cmd_AddParamCompleteFunction("ui_push", UI_CompleteWithWindow);
717 Cmd_AddCommand("ui_push_dropdown", UI_PushDropDownWindow_f, "Push a dropdown window at a position");
718 Cmd_AddCommand("ui_push_child", UI_PushChildWindow_f, "Push a window to the windowstack with a big dependency to a parent window");
719 Cmd_AddCommand("ui_pop", UI_PopWindow_f, "Pops the current window from the stack");
720 Cmd_AddCommand("ui_close", UI_CloseWindow_f, "Close a window");
721 Cmd_AddCommand("ui_initstack", UI_InitStack_f, "Initialize the window stack with a main and an option window.");
722 Cmd_AddCommand("ui_tree", UI_DebugTree_f, "Display a tree of nodes from a window into the console.");
723 Cmd_AddCommand("ui_popup", UI_Popup_f, "Shows a popup window");
724 Cmd_AddParamCompleteFunction("ui_tree", UI_CompleteWithWindow);
725 }
726