src/basics.h

changeset 1319
39d7a9642eea
parent 1315
23d48a709ffc
child 1320
bdb4804bc09c
equal deleted inserted replaced
1318:568fcfc6da71 1319:39d7a9642eea
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 }

mercurial