15 * You should have received a copy of the GNU General Public License |
15 * You should have received a copy of the GNU General Public License |
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 */ |
17 */ |
18 |
18 |
19 #pragma once |
19 #pragma once |
20 #include <QString> |
|
21 #include <QObject> |
|
22 #include <QStringList> |
|
23 #include <QMetaType> |
|
24 #include <QSet> |
|
25 #include <QVector3D> |
|
26 #include <QVector> |
|
27 #include <QFile> |
20 #include <QFile> |
28 #include <QMatrix4x4> |
21 #include <QMatrix4x4> |
29 #include <functional> |
22 #include <QMetaType> |
30 #include <type_traits> |
23 #include <QObject> |
31 #include <math.h> |
24 #include <QSet> |
32 #include "macros.h" |
25 #include <QString> |
33 #include "transform.h" |
26 #include <QStringList> |
|
27 #include <QVector> |
|
28 #include <QVector3D> |
|
29 #include "generics/functions.h" |
34 |
30 |
35 #if (QT_VERSION < QT_VERSION_CHECK(5, 7, 0)) |
31 #ifndef __GNUC__ |
36 template <typename... Args> |
32 # define __attribute__(X) |
37 struct QNonConstOverload |
|
38 { |
|
39 template <typename R, typename T> |
|
40 Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...)) const Q_DECL_NOTHROW -> decltype(ptr) |
|
41 { return ptr; } |
|
42 template <typename R, typename T> |
|
43 static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...)) Q_DECL_NOTHROW -> decltype(ptr) |
|
44 { return ptr; } |
|
45 }; |
|
46 template <typename... Args> |
|
47 struct QConstOverload |
|
48 { |
|
49 template <typename R, typename T> |
|
50 Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...) const) const Q_DECL_NOTHROW -> decltype(ptr) |
|
51 { return ptr; } |
|
52 template <typename R, typename T> |
|
53 static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...) const) Q_DECL_NOTHROW -> decltype(ptr) |
|
54 { return ptr; } |
|
55 }; |
|
56 template <typename... Args> |
|
57 struct QOverload : QConstOverload<Args...>, QNonConstOverload<Args...> |
|
58 { |
|
59 using QConstOverload<Args...>::of; |
|
60 using QConstOverload<Args...>::operator(); |
|
61 using QNonConstOverload<Args...>::of; |
|
62 using QNonConstOverload<Args...>::operator(); |
|
63 template <typename R> |
|
64 Q_DECL_CONSTEXPR auto operator()(R (*ptr)(Args...)) const Q_DECL_NOTHROW -> decltype(ptr) |
|
65 { return ptr; } |
|
66 template <typename R> |
|
67 static Q_DECL_CONSTEXPR auto of(R (*ptr)(Args...)) Q_DECL_NOTHROW -> decltype(ptr) |
|
68 { return ptr; } |
|
69 }; |
|
70 template <typename... Args> Q_CONSTEXPR Q_DECL_UNUSED QOverload<Args...> qOverload = {}; |
|
71 template <typename... Args> Q_CONSTEXPR Q_DECL_UNUSED QConstOverload<Args...> qConstOverload = {}; |
|
72 template <typename... Args> Q_CONSTEXPR Q_DECL_UNUSED QNonConstOverload<Args...> qNonConstOverload = {}; |
|
73 #endif |
33 #endif |
74 |
34 |
75 class Matrix; |
35 #define DEFINE_CLASS(SELF, SUPER) \ |
76 struct Vertex; |
36 public: \ |
|
37 using Self = SELF; \ |
|
38 using Super = SUPER; |
|
39 |
|
40 // TODO: get rid of this |
|
41 #ifdef WIN32 |
|
42 # define DIRSLASH "\\" |
|
43 # define DIRSLASH_CHAR '\\' |
|
44 #else // WIN32 |
|
45 # define DIRSLASH "/" |
|
46 # define DIRSLASH_CHAR '/' |
|
47 #endif // WIN32 |
|
48 |
77 using GLRotationMatrix = QMatrix4x4; |
49 using GLRotationMatrix = QMatrix4x4; |
78 |
|
79 template<typename T, typename R> |
|
80 using Pair = std::pair<T, R>; |
|
81 |
50 |
82 enum Axis |
51 enum Axis |
83 { |
52 { |
84 X, |
53 X, |
85 Y, |
54 Y, |
91 NoWinding, |
60 NoWinding, |
92 CounterClockwise, |
61 CounterClockwise, |
93 Clockwise, |
62 Clockwise, |
94 }; |
63 }; |
95 |
64 |
96 Winding operator^(Winding one, Winding other); |
65 /* |
97 Winding& operator^=(Winding& one, Winding other); |
66 * Special operator definition that implements the XOR operator for windings. |
|
67 * However, if either winding is NoWinding, then this function returns NoWinding. |
|
68 */ |
|
69 inline Winding operator^(Winding one, Winding other) |
|
70 { |
|
71 if (one == NoWinding or other == NoWinding) |
|
72 return NoWinding; |
|
73 else |
|
74 return static_cast<Winding>(static_cast<int>(one) ^ static_cast<int>(other)); |
|
75 } |
98 |
76 |
|
77 inline Winding& operator^=(Winding& one, Winding other) |
|
78 { |
|
79 one = one ^ other; |
|
80 return one; |
|
81 } |
|
82 |
|
83 static const double pi = 3.14159265358979323846; |
|
84 |
|
85 /* |
|
86 * Returns the norm of a vector. |
|
87 */ |
99 static inline qreal abs(const QVector3D &vector) |
88 static inline qreal abs(const QVector3D &vector) |
100 { |
89 { |
101 return vector.length(); |
90 return vector.length(); |
102 } |
91 } |
103 |
92 |
104 static const double pi = 3.14159265358979323846; |
93 using ApplyToMatrixFunction = std::function<void(int, double&)>; |
|
94 using ApplyToMatrixConstFunction = std::function<void(int, double)>; |
105 |
95 |
106 |
96 void applyToMatrix(class Matrix& a, ApplyToMatrixFunction func); |
107 // ============================================================================= |
97 void applyToMatrix(const class Matrix& a, ApplyToMatrixConstFunction func); |
108 // Plural expression |
98 QString formatFileSize(qint64 size); |
109 template<typename T> |
99 int gcd(int a, int b); |
110 static inline const char* plural (T n) |
100 QString joinStrings(const QList<class StringFormatArg>& values, QString delimeter = " "); |
111 { |
101 void roundToDecimals(double& value, int decimals); |
112 return (n != 1) ? "s" : ""; |
102 void simplify(int& numerator, int& denominator); |
113 } |
|
114 |
|
115 template<typename T> |
|
116 bool isZero (T a) |
|
117 { |
|
118 return qFuzzyCompare (a + 1.0, 1.0); |
|
119 } |
|
120 |
|
121 template<typename T> |
|
122 bool isInteger (T a) |
|
123 { |
|
124 return (qAbs (a - floor(a)) < 0.00001) or (qAbs (a - ceil(a)) < 0.00001); |
|
125 } |
|
126 |
|
127 // |
|
128 // Returns true if first arg is equal to any of the other args |
|
129 // |
|
130 template<typename T, typename Arg, typename... Args> |
|
131 bool isOneOf (T const& a, Arg const& arg, Args const&... args) |
|
132 { |
|
133 if (a == arg) |
|
134 return true; |
|
135 |
|
136 return isOneOf (a, args...); |
|
137 } |
|
138 |
|
139 template<typename T> |
|
140 bool isOneOf (T const&) |
|
141 { |
|
142 return false; |
|
143 } |
|
144 |
|
145 inline void toggle (bool& a) |
|
146 { |
|
147 a = not a; |
|
148 } |
|
149 |
|
150 // |
|
151 // Iterates an enum |
|
152 // |
|
153 template<typename Enum> |
|
154 struct EnumIterShell |
|
155 { |
|
156 struct Iterator |
|
157 { |
|
158 Iterator(typename std::underlying_type<Enum>::type i) : |
|
159 i(i) {} |
|
160 |
|
161 Iterator& operator++() { ++i; return *this; } |
|
162 bool operator==(Iterator other) { return i == other.i; } |
|
163 bool operator!=(Iterator other) { return i != other.i; } |
|
164 Enum operator*() const { return Enum(i); } |
|
165 |
|
166 typename std::underlying_type<Enum>::type i; |
|
167 }; |
|
168 |
|
169 Iterator begin() |
|
170 { |
|
171 return Iterator(EnumLimits<Enum>::First); |
|
172 }; |
|
173 |
|
174 Iterator end() |
|
175 { |
|
176 return Iterator(EnumLimits<Enum>::Last + 1); |
|
177 } |
|
178 }; |
|
179 |
|
180 template<typename Enum> |
|
181 EnumIterShell<Enum> iterateEnum() |
|
182 { |
|
183 return EnumIterShell<Enum>(); |
|
184 } |
|
185 |
|
186 // Is a value inside an enum? |
|
187 template<typename Enum> |
|
188 bool valueInEnum(Enum enumerator) |
|
189 { |
|
190 typename std::underlying_type<Enum>::type index = static_cast<typename std::underlying_type<Enum>::type>(enumerator); |
|
191 return index >= EnumLimits<Enum>::First and index <= EnumLimits<Enum>::Last; |
|
192 } |
|
193 |
|
194 double getRadialPoint(int segment, int divisions, double(*func)(double)); |
|
195 QVector<QLineF> makeCircle(int segments, int divisions, double radius); |
|
196 qreal distanceFromPointToRectangle(const QPointF& point, const QRectF& rectangle); |
|
197 |
|
198 /* |
|
199 * Implements a ring adapter over T. This class corrects indices given to the element-operator so that they're within bounds. |
|
200 * The maximum amount can be specified manually. |
|
201 * |
|
202 * Example: |
|
203 * |
|
204 * int A[] = {10,20,30,40}; |
|
205 * ring(A)[0] == A[0 % 4] == A[0] |
|
206 * ring(A)[5] == A[5 % 4] == A[1] |
|
207 * ring(A)[-1] == ring(A)[-1 + 4] == A[3] |
|
208 */ |
|
209 template<typename T> |
|
210 class RingAdapter |
|
211 { |
|
212 private: |
|
213 // The private section must come first because _collection is used in decltype() below. |
|
214 T& _collection; |
|
215 const int _count; |
|
216 |
|
217 public: |
|
218 RingAdapter(T& collection, int count) : |
|
219 _collection {collection}, |
|
220 _count {count} {} |
|
221 |
|
222 template<typename IndexType> |
|
223 decltype(_collection[IndexType()]) operator[](IndexType index) |
|
224 { |
|
225 if (_count == 0) |
|
226 { |
|
227 // Argh! ...let the collection deal with this case. |
|
228 return _collection[0]; |
|
229 } |
|
230 else |
|
231 { |
|
232 index %= _count; |
|
233 |
|
234 // Fix negative modulus... |
|
235 if (index < 0) |
|
236 index += _count; |
|
237 |
|
238 return _collection[index]; |
|
239 } |
|
240 } |
|
241 |
|
242 int size() const |
|
243 { |
|
244 return _count; |
|
245 } |
|
246 }; |
|
247 |
|
248 /* |
|
249 * Casts a reference to an enum into a reference to its underlying integer type. |
|
250 */ |
|
251 template<typename T> |
|
252 typename std::underlying_type<T>::type& enum_cast(T& enu) |
|
253 { |
|
254 return *reinterpret_cast<typename std::underlying_type<T>::type*>(&enu); |
|
255 } |
|
256 |
|
257 /* |
|
258 * Convenience function for RingAdapter so that the template parameter does not have to be provided. The ring amount is assumed |
|
259 * to be the amount of elements in the collection. |
|
260 */ |
|
261 template<typename T> |
|
262 RingAdapter<T> ring(T& collection) |
|
263 { |
|
264 return RingAdapter<T> {collection, countof(collection)}; |
|
265 } |
|
266 |
|
267 /* |
|
268 * Version of ring() that allows manual specification of the count. |
|
269 */ |
|
270 template<typename T> |
|
271 RingAdapter<T> ring(T& collection, int count) |
|
272 { |
|
273 return RingAdapter<T> {collection, count}; |
|
274 } |
|
275 |
|
276 struct Library |
|
277 { |
|
278 QString path; |
|
279 enum |
|
280 { |
|
281 ReadOnlyStorage, // for official files, etc |
|
282 UnofficialFiles, // put downloaded files here |
|
283 WorkingDirectory, // for editable documents |
|
284 } role = ReadOnlyStorage; |
|
285 |
|
286 bool operator==(const Library& other) const |
|
287 { |
|
288 return (this->path == other.path) and (this->role == other.role); |
|
289 } |
|
290 }; |
|
291 |
|
292 Q_DECLARE_METATYPE(Library) |
|
293 using Libraries = QVector<Library>; |
|
294 |
|
295 QDataStream& operator<<(QDataStream& out, const Library& library); |
|
296 QDataStream& operator>>(QDataStream& in, Library& library); |
|
297 |
|
298 // |
|
299 // Get the amount of elements in something. |
|
300 // |
|
301 template<typename T, size_t N> |
|
302 int countof(T(&)[N]) |
|
303 { |
|
304 return N; |
|
305 } |
|
306 |
|
307 static inline int countof(const QString& string) |
|
308 { |
|
309 return string.length(); |
|
310 } |
|
311 |
|
312 template<typename T> |
|
313 int countof(const QVector<T>& vector) |
|
314 { |
|
315 return vector.size(); |
|
316 } |
|
317 |
|
318 template<typename T> |
|
319 int countof(const QList<T>& vector) |
|
320 { |
|
321 return vector.size(); |
|
322 } |
|
323 |
|
324 template<typename T> |
|
325 int countof(const QSet<T>& set) |
|
326 { |
|
327 return set.size(); |
|
328 } |
|
329 |
|
330 template<typename T> |
|
331 int countof(const std::initializer_list<T>& vector) |
|
332 { |
|
333 return vector.size(); |
|
334 } |
|
335 |
|
336 template<typename T> |
|
337 int countof(const RingAdapter<T>& ring) |
|
338 { |
|
339 return ring.size(); |
|
340 } |
|
341 |
|
342 /* |
|
343 * Extracts the sign of x. |
|
344 */ |
|
345 template<typename T> |
|
346 T sign(T x) |
|
347 { |
|
348 if (isZero(x)) |
|
349 return {}; |
|
350 else |
|
351 return x / qAbs(x); |
|
352 } |
|
353 |
|
354 template<> |
|
355 inline int sign(int x) |
|
356 { |
|
357 if (x == 0) |
|
358 return 0; |
|
359 else |
|
360 return x / qAbs(x); |
|
361 } |
|
362 |
|
363 /* |
|
364 * Returns the maximum of a single parameter (the parameter itself). |
|
365 */ |
|
366 template <typename T> |
|
367 T max(T a) |
|
368 { |
|
369 return a; |
|
370 } |
|
371 |
|
372 /* |
|
373 * Returns the maximum of two parameters. |
|
374 */ |
|
375 template <typename T> |
|
376 T max(T a, T b) |
|
377 { |
|
378 return a > b ? a : b; |
|
379 } |
|
380 |
|
381 /* |
|
382 * Returns the maximum of n parameters. |
|
383 */ |
|
384 template <typename T, typename... Rest> |
|
385 T max(T a, Rest&&... rest) |
|
386 { |
|
387 return max(a, max(rest...)); |
|
388 } |
|
389 |
|
390 /* |
|
391 * Returns the minimum of a single parameter (the parameter itself). |
|
392 */ |
|
393 template <typename T> |
|
394 T min(T a) |
|
395 { |
|
396 return a; |
|
397 } |
|
398 |
|
399 /* |
|
400 * Returns the minimum of two parameters. |
|
401 */ |
|
402 template <typename T> |
|
403 T min(T a, T b) |
|
404 { |
|
405 return a < b ? a : b; |
|
406 } |
|
407 |
|
408 /* |
|
409 * Returns the minimum of n parameters. |
|
410 */ |
|
411 template <typename T, typename... Rest> |
|
412 T min(T a, Rest&&... rest) |
|
413 { |
|
414 return min(a, min(rest...)); |
|
415 } |
|
416 |
|
417 /* |
|
418 * Assigns the value of a single flag in a flagset |
|
419 */ |
|
420 template<int Flag, typename T> |
|
421 void assignFlag(QFlags<T>& flagset, bool value) |
|
422 { |
|
423 if (value) |
|
424 flagset |= static_cast<T>(Flag); |
|
425 else |
|
426 flagset &= ~static_cast<T>(Flag); |
|
427 } |
|
428 |
|
429 /* |
|
430 * Returns a singleton of type T, useful for providing a valid but unused |
|
431 * pointer. |
|
432 */ |
|
433 template<typename T> |
|
434 inline T& sink() |
|
435 { |
|
436 static T result; |
|
437 return result; |
|
438 } |
|