Line data Source code
1 : /**
2 : * @file menus.cpp
3 : * @brief UI triggers for menu functionality
4 : *
5 : * automatic triggers for certain UIs in game
6 : * does not implement menus, just some low level bindings for main menu functionality
7 : */
8 :
9 : #include "../libprimis-headers/cube.h"
10 :
11 : #include "control.h"
12 : #include "menus.h"
13 : #include "ui.h"
14 :
15 : #include "world/octaedit.h"
16 :
17 : //internally relevant functionality
18 : namespace
19 : {
20 : /**
21 : * @brief Object containing information about an event that requires a change.
22 : *
23 : * This stores events which will require the engine to restart some components
24 : * in order to apply them to the currently running application instance.
25 : *
26 : * Settings that are changed that will require some kind of update will enqueue
27 : * changes such that all relevant changes will be applied after prompting upon
28 : * closing of the settings menu.
29 : */
30 : struct Change final
31 : {
32 : int type; /// one of the values in control.h Control enum
33 : std::string desc; /// text description of the thing that is requesting a change
34 :
35 : Change() {}
36 3 : Change(int inittype, const char *initdesc) : type(inittype), desc(initdesc) {}
37 :
38 0 : bool operator==(const Change & c) const
39 : {
40 0 : return type == c.type && (desc == c.desc) == 0;
41 : }
42 : };
43 : std::vector<Change> needsapply;
44 :
45 : //toggles showing of dialog to apply engine changes
46 : // if 0, changes are not prompted and therefore never applied
47 : VARP(applydialog, 0, 1, 1);
48 :
49 : //when 1: change UI shows up whenever a pending change is added
50 : //when 0: change UI does not appear and applychanges must be used manually
51 : VAR(showchanges, 0, 1, 1);
52 :
53 : /**
54 : * @brief Applies enqueued changes that require reloading parts of the engine
55 : *
56 : * These are settings that cannot be applied immediately and require reloading
57 : * parts of the engine (disrupting the currently rendered scene). Settings that
58 : * require resetting the GL configuration, the shader configuration or sound
59 : * configuration are added to the change buffer and are flushed when this function
60 : * is called.
61 : */
62 1 : void applychanges()
63 : {
64 1 : int changetypes = 0;
65 2 : for(const Change &i : needsapply)
66 : {
67 1 : changetypes |= i.type;
68 : }
69 1 : if(changetypes&Change_Graphics)
70 : {
71 1 : execident("resetgl");
72 : }
73 0 : else if(changetypes&Change_Shaders)
74 : {
75 0 : execident("resetshaders");
76 : }
77 1 : if(changetypes&Change_Sound)
78 : {
79 0 : execident("resetsound");
80 : }
81 1 : }
82 :
83 : /**
84 : * @brief returns if there are pending changes or not enqueued
85 : *
86 : * If idx is specified, and specifies a valid pending change index, prints out
87 : * the description of that pending change to CubeScript. If no idx is specified,
88 : * prints out how many changes there are enqueued to CubeScript.
89 : *
90 : * @param idx index to query, or nullptr if querying number of pending changes
91 : */
92 1 : void pendingchanges(const int *idx)
93 : {
94 1 : if(idx)
95 : {
96 1 : if((needsapply.size()) > static_cast<uint>(*idx))
97 : {
98 0 : result(needsapply.at(*idx).desc.c_str());
99 : }
100 1 : else if(*idx < 0)
101 : {
102 1 : intret(needsapply.size());
103 : }
104 : }
105 1 : }
106 : }
107 :
108 : //externally relevant functionality
109 :
110 : //toggles if the main menu is shown
111 : VAR(mainmenu, 1, 1, 0);
112 :
113 1 : void addchange(const char *desc, int type)
114 : {
115 1 : if(!applydialog)
116 : {
117 0 : return;
118 : }
119 1 : for(const Change &i : needsapply)
120 : {
121 0 : if(!std::strcmp(i.desc.c_str(), desc))
122 : {
123 0 : return;
124 : }
125 : }
126 1 : needsapply.emplace_back(type, desc);
127 1 : if(showchanges)
128 : {
129 1 : UI::showui("changes");
130 : }
131 : }
132 :
133 0 : void notifywelcome()
134 : {
135 0 : UI::hideui("servers");
136 0 : }
137 :
138 0 : void clearchanges(int type)
139 : {
140 0 : for(int i = needsapply.size(); --i >=0;) //note reverse iteration
141 : {
142 0 : Change &c = needsapply[i];
143 0 : if(c.type&type)
144 : {
145 0 : c.type &= ~type;
146 0 : if(!c.type)
147 : {
148 0 : auto it = std::find(needsapply.begin(), needsapply.end(), needsapply[i]);
149 0 : needsapply.erase(it);
150 : }
151 : }
152 : }
153 0 : if(needsapply.empty())
154 : {
155 0 : UI::hideui("changes");
156 : }
157 0 : }
158 :
159 0 : void clearmainmenu()
160 : {
161 0 : showchanges = 1;
162 0 : if(mainmenu && multiplayer)
163 : {
164 0 : mainmenu = 0;
165 0 : UI::hideui(nullptr);
166 : }
167 0 : }
168 :
169 1 : void initmenuscmds()
170 : {
171 1 : addcommand("applychanges", reinterpret_cast<identfun>(applychanges), "", Id_Command);
172 1 : addcommand("pendingchanges", reinterpret_cast<identfun>(pendingchanges), "b", Id_Command);
173 1 : }
|