Etterna 0.74.4
Loading...
Searching...
No Matches
ThemeMetric.h
1/* ThemeMetric - Theme specific data. */
2
3#ifndef THEME_METRIC_H
4#define THEME_METRIC_H
5
6#include "Etterna/Singletons/ThemeManager.h"
7
8#include <map>
9
12{
13 public:
14 virtual ~IThemeMetric() = default;
15 virtual void Read() = 0;
16 virtual void Clear() = 0;
17};
18
19template<class T>
21{
22 enum
23 {
24 Callable = 1
25 };
26};
27
28/* LuaReference and apActorCommands return the function directly without calling
29 * it. */
30template<>
32{
33 enum
34 {
35 Callable = 0
36 };
37};
38template<>
39struct ThemeMetricTypeTraits<apActorCommands>
40{
41 enum
42 {
43 Callable = 0
44 };
45};
46
50template<class T>
52{
53 protected:
57 std::string m_sGroup;
59 std::string m_sName;
62 mutable T m_currentValue;
63 bool m_bCallEachTime{ false };
64
65 public:
66 /* Initializing with no group and name is allowed; if you do this, you must
67 * call Load() to set them. This is done to allow initializing cached
68 * metrics in one place for classes that don't receive their m_sName in the
69 * constructor (everything except screens). */
70 ThemeMetric(std::string sGroup = "", std::string sName = "")
71 : m_sGroup(std::move(sGroup))
72 , m_sName(std::move(sName))
73 , m_currentValue(T())
74 {
75 ThemeManager::Subscribe(this);
76 }
77
78 ThemeMetric(const ThemeMetric<T>& cpy)
79 : IThemeMetric(cpy)
80 , m_sGroup(cpy.m_sGroup)
81 , m_sName(cpy.m_sName)
82 , m_Value(cpy.m_Value)
83 // do we transfer the current value or bCallEachTime?
84 {
85 m_currentValue = T();
86 m_bCallEachTime = false;
87 ThemeManager::Subscribe(this);
88 }
89
90 ~ThemeMetric() override { ThemeManager::Unsubscribe(this); }
95 void Load(const std::string& sGroup, const std::string& sName)
96 {
97 m_sGroup = sGroup;
98 m_sName = sName;
99 Read();
100 }
101
102 void ChangeGroup(const std::string& sGroup)
103 {
104 m_sGroup = sGroup;
105 Read();
106 }
109 void Read() override
110 {
111 if (!m_sName.empty() && (THEME != nullptr) && THEME->IsThemeLoaded()) {
112 auto L = LUA->Get();
113 THEME->GetMetric(m_sGroup, m_sName, m_Value);
114 m_Value.PushSelf(L);
115 LuaHelpers::FromStack(L, m_currentValue, -1);
116 lua_pop(L, 1);
117 LUA->Release(L);
118
119 /* If the value is a function, evaluate it every time. */
120 m_bCallEachTime = ThemeMetricTypeTraits<T>::Callable &&
121 m_Value.GetLuaType() == LUA_TFUNCTION;
122 } else {
123 m_Value.Unset();
124 m_bCallEachTime = false;
125 }
126 }
127
128 void PushSelf(Lua* L)
129 {
130 ASSERT(m_Value.IsSet());
131 m_Value.PushSelf(L);
132 }
133
134 void Clear() override { m_Value.Unset(); }
135
139 auto GetName() const -> const std::string& { return m_sName; }
143 auto GetGroup() const -> const std::string& { return m_sGroup; }
144
148 auto GetValue() const -> const T&
149 {
150 ASSERT(!m_sName.empty());
151 ASSERT_M(m_Value.IsSet(), m_sGroup + " " + m_sName);
152
153 if (m_bCallEachTime) {
154 auto L = LUA->Get();
155
156 // call function with 0 arguments and 1 result
157 m_Value.PushSelf(L);
158 auto error = m_sGroup + ": " + m_sName + ": ";
159 LuaHelpers::RunScriptOnStack(L, error, 0, 1, true);
160 if (!lua_isnil(L, -1)) {
161 LuaHelpers::Pop(L, m_currentValue);
162 } else {
163 lua_pop(L, 1);
164 }
165 LUA->Release(L);
166 }
167
168 return m_currentValue;
169 }
170
171 operator const T&() const { return GetValue(); }
172
173 auto IsLoaded() const -> bool { return m_Value.IsSet(); }
174
175 // Hacks for VC6 for all boolean operators.
176 // These three no longer appear to be required:
177 // bool operator ! () const { return !GetValue(); }
178 // bool operator && ( const T& input ) const { return GetValue() && input; }
179 // bool operator || ( const T& input ) const { return GetValue() || input; }
180
181 // This one is still required in at least Visual Studio 2008:
182 auto operator==(const T& input) const -> bool
183 {
184 return GetValue() == input;
185 }
186};
187
188using MetricName1D = std::string (*)(size_t);
189
190template<class T>
192{
193 using ThemeMetricT = ThemeMetric<T>;
194 std::vector<ThemeMetricT> m_metric;
195
196 public:
197 ThemeMetric1D(const std::string& sGroup, MetricName1D pfn, size_t N)
198 {
199 Load(sGroup, pfn, N);
200 }
201 ThemeMetric1D() { Load(std::string(), nullptr, 0); }
202 void Load(const std::string& sGroup, MetricName1D pfn, size_t N)
203 {
204 m_metric.resize(N);
205 for (unsigned i = 0; i < N; i++) {
206 m_metric[i].Load(sGroup, pfn(i));
207 }
208 }
209 void Read() override
210 {
211 for (unsigned i = 0; i < m_metric.size(); i++) {
212 m_metric[i].Read();
213 }
214 }
215 void Clear() override
216 {
217 for (unsigned i = 0; i < m_metric.size(); i++) {
218 m_metric[i].Clear();
219 }
220 }
221
222 [[nodiscard]] auto GetValue(size_t i) const -> const T&
223 {
224 return m_metric[i].GetValue();
225 }
226};
227
228using MetricName2D = std::string (*)(size_t, size_t);
229
230template<class T>
232{
233 using ThemeMetricT = ThemeMetric<T>;
234 using ThemeMetricTVector = std::vector<ThemeMetricT>;
235 std::vector<ThemeMetricTVector> m_metric;
236
237 public:
238 ThemeMetric2D(const std::string& sGroup = "",
239 MetricName2D pfn = nullptr,
240 size_t N = 0,
241 size_t M = 0)
242 {
243 Load(sGroup, pfn, N, M);
244 }
245 void Load(const std::string& sGroup, MetricName2D pfn, size_t N, size_t M)
246 {
247 m_metric.resize(N);
248 for (unsigned i = 0; i < N; i++) {
249 m_metric[i].resize(M);
250 for (unsigned j = 0; j < M; j++)
251 m_metric[i][j].Load(sGroup, pfn(i, j));
252 }
253 }
254 void Read() override
255 {
256 for (unsigned i = 0; i < m_metric.size(); i++)
257 for (unsigned j = 0; j < m_metric[i].size(); j++)
258 m_metric[i][j].Read();
259 }
260 void Clear() override
261 {
262 for (unsigned i = 0; i < m_metric.size(); i++)
263 for (unsigned j = 0; j < m_metric[i].size(); j++)
264 m_metric[i][j].Clear();
265 }
266 auto GetValue(size_t i, size_t j) const -> const T&
267 {
268 return m_metric[i][j].GetValue();
269 }
270};
271
272using MetricNameMap = std::string (*)(std::string);
273
274template<class T>
276{
277 using ThemeMetricT = ThemeMetric<T>;
278 std::map<std::string, ThemeMetricT> m_metric;
279
280 public:
282 const std::string& sGroup = "",
283 MetricNameMap pfn = nullptr,
284 const std::vector<std::string>& vsValueNames = std::vector<std::string>())
285 {
286 Load(sGroup, pfn, vsValueNames);
287 }
288 void Load(const std::string& sGroup,
289 MetricNameMap pfn,
290 const std::vector<std::string>& vsValueNames)
291 {
292 m_metric.clear();
293 for (auto& s : vsValueNames) {
294 m_metric[s].Load(sGroup, pfn(s));
295 }
296 }
297 void Read() override
298 {
299 // HACK: GCC (3.4) takes this and pretty much nothing else.
300 // I don't know why.
301 for (typename std::map<std::string, ThemeMetric<T>>::iterator m =
302 m_metric.begin();
303 m != m_metric.end();
304 ++m) {
305 m->second.Read();
306 }
307 }
308 void Clear() override
309 {
310 for (typename std::map<std::string, ThemeMetric<T>>::iterator m =
311 m_metric.begin();
312 m != m_metric.end();
313 ++m) {
314 m->second.Clear();
315 }
316 }
317 [[nodiscard]] auto GetValue(const std::string& s) const -> const T&
318 {
319 // HACK: GCC (3.4) takes this and pretty much nothing else.
320 // I don't know why.
321 typename std::map<std::string, ThemeMetric<T>>::const_iterator iter =
322 m_metric.find(s);
323 ASSERT(iter != m_metric.end());
324 return iter->second.GetValue();
325 }
326};
327
328#endif
The general interface for reading ThemeMetrics.
Definition ThemeMetric.h:12
A self-cleaning Lua reference.
Definition LuaReference.h:10
auto IsSet() const -> bool
Determine if the reference is set.
Definition LuaReference.cpp:97
Definition ThemeMetric.h:192
Definition ThemeMetric.h:232
Definition ThemeMetric.h:276
The theme specific data.
Definition ThemeMetric.h:52
auto GetName() const -> const std::string &
Retrieve the metric's name.
Definition ThemeMetric.h:139
LuaReference m_Value
the metric's value.
Definition ThemeMetric.h:61
auto GetGroup() const -> const std::string &
Retrieve the metric's group.
Definition ThemeMetric.h:143
void Read() override
Actually read the metric and get its data.
Definition ThemeMetric.h:109
std::string m_sName
the metric's name.
Definition ThemeMetric.h:59
std::string m_sGroup
the metric's group.
Definition ThemeMetric.h:57
auto GetValue() const -> const T &
Retrieve the metric's value.
Definition ThemeMetric.h:148
void Load(const std::string &sGroup, const std::string &sName)
Load the chosen metric from the .ini file.
Definition ThemeMetric.h:95
Definition ThemeMetric.h:21