1 /* |
|
2 * LDForge: LDraw parts authoring CAD |
|
3 * Copyright (C) 2013 - 2020 Teemu Piippo |
|
4 * |
|
5 * This program is free software: you can redistribute it and/or modify |
|
6 * it under the terms of the GNU General Public License as published by |
|
7 * the Free Software Foundation, either version 3 of the License, or |
|
8 * (at your option) any later version. |
|
9 * |
|
10 * This program is distributed in the hope that it will be useful, |
|
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
13 * GNU General Public License for more details. |
|
14 * |
|
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/>. |
|
17 */ |
|
18 |
|
19 #pragma once |
|
20 #include <QString> |
|
21 #include <QVector> |
|
22 #include <QSet> |
|
23 #include <QDebug> |
|
24 #include <compare> |
|
25 #include <memory> |
|
26 #include "basics.h" |
|
27 #include "utility.h" |
|
28 #include "geometry.h" |
|
29 #include "functional.h" |
|
30 |
|
31 namespace settingGroups |
|
32 { |
|
33 // List of setting groups |
|
34 constexpr char mainwindow[] = "mainwindow"; |
|
35 } |
|
36 |
|
37 constexpr std::size_t operator""_z(const unsigned long long int x) |
|
38 { |
|
39 return static_cast<std::size_t>(x); |
|
40 } |
|
41 |
|
42 inline QString operator""_q(const char* string, const unsigned long int length) |
|
43 { |
|
44 Q_UNUSED(length) |
|
45 return QString{string}; |
|
46 } |
|
47 |
|
48 inline QPointF pointToPointF(const QPoint& point) |
|
49 { |
|
50 return {static_cast<qreal>(point.x()), static_cast<qreal>(point.y())}; |
|
51 } |
|
52 |
|
53 inline QPoint pointFToPoint(const QPointF& point) |
|
54 { |
|
55 return {static_cast<int>(std::round(point.x())), static_cast<int>(std::round(point.y()))}; |
|
56 } |
|
57 |
|
58 inline QSizeF sizeToSizeF(const QSize& size) |
|
59 { |
|
60 return {static_cast<qreal>(size.width()), static_cast<qreal>(size.height())}; |
|
61 } |
|
62 |
|
63 /** |
|
64 * \brief Hints to the specified vector that a certain amount of new elements are going to be added. |
|
65 * \param vector vector to consider |
|
66 * \param amount amount of new elements to expect |
|
67 */ |
|
68 template<typename T> |
|
69 void reserveMore(std::vector<T>& vector, std::size_t amount) |
|
70 { |
|
71 vector.reserve(vector.size() + amount); |
|
72 } |
|
73 |
|
74 inline QString vectorToString(const glm::vec2& vec) |
|
75 { |
|
76 return "(%1, %2)"_q |
|
77 .arg(toDouble(vec.x)) |
|
78 .arg(toDouble(vec.y)); |
|
79 } |
|
80 |
|
81 inline QString vectorToString(const glm::vec3& vec) |
|
82 { |
|
83 return "(%1, %2, %3)"_q |
|
84 .arg(toDouble(vec.x)) |
|
85 .arg(toDouble(vec.y)) |
|
86 .arg(toDouble(vec.z)); |
|
87 } |
|
88 |
|
89 inline QString vectorToString(const glm::vec4& vec) |
|
90 { |
|
91 return "(%1, %2, %3, %4)"_q |
|
92 .arg(toDouble(vec.x)) |
|
93 .arg(toDouble(vec.y)) |
|
94 .arg(toDouble(vec.z)) |
|
95 .arg(toDouble(vec.w)); |
|
96 } |
|
97 |
|
98 template<typename K, typename V> |
|
99 struct KeyValuePair |
|
100 { |
|
101 K key; |
|
102 V value; |
|
103 }; |
|
104 |
|
105 template<typename K, typename V, typename IteratorType> |
|
106 struct MapItemsIterator : IteratorType |
|
107 { |
|
108 template<typename... Ts> |
|
109 MapItemsIterator(Ts&&... args) : IteratorType{args...} {} |
|
110 auto operator*() const |
|
111 { |
|
112 return KeyValuePair<const K&, V&>{this->key(), this->value()}; |
|
113 } |
|
114 }; |
|
115 |
|
116 template<typename K, typename V, typename MapType, typename IteratorType> |
|
117 struct MapItems |
|
118 { |
|
119 MapType& map; |
|
120 IteratorType begin() |
|
121 { |
|
122 return IteratorType(this->map.begin()); |
|
123 } |
|
124 |
|
125 IteratorType end() |
|
126 { |
|
127 return IteratorType(this->map.end()); |
|
128 } |
|
129 }; |
|
130 |
|
131 /* |
|
132 * Python's dict.items for QMap: use in a for loop to iterate a map to |
|
133 * get both keys and values. Iteration yields KeyValuePairs. |
|
134 */ |
|
135 template<typename K, typename V> |
|
136 auto items(const QMap<K, V>& map) |
|
137 { |
|
138 return MapItems< |
|
139 const K&, |
|
140 const V&, |
|
141 const QMap<K, V>, |
|
142 MapItemsIterator<K, const V, typename QMap<K, V>::const_iterator> |
|
143 >{map}; |
|
144 } |
|
145 |
|
146 template<typename K, typename V> |
|
147 auto items(QMap<K, V>& map) |
|
148 { |
|
149 return MapItems< |
|
150 const K&, |
|
151 V&, |
|
152 QMap<K, V>, |
|
153 MapItemsIterator<K, const V, typename QMap<K, V>::iterator> |
|
154 >{map}; |
|
155 } |
|
156 |
|
157 template<typename T, typename IdentifierType> |
|
158 struct TypeValue |
|
159 { |
|
160 T value; |
|
161 bool operator==(TypeValue<T, IdentifierType> other) const |
|
162 { |
|
163 return value == other.value; |
|
164 } |
|
165 bool operator!=(TypeValue<T, IdentifierType> other) const |
|
166 { |
|
167 return value != other.value; |
|
168 } |
|
169 bool operator<(TypeValue<T, IdentifierType> other) const |
|
170 { |
|
171 return value < other.value; |
|
172 } |
|
173 bool operator>(TypeValue<T, IdentifierType> other) const |
|
174 { |
|
175 return value > other.value; |
|
176 } |
|
177 bool operator<=(TypeValue<T, IdentifierType> other) const |
|
178 { |
|
179 return value <= other.value; |
|
180 } |
|
181 bool operator>=(TypeValue<T, IdentifierType> other) const |
|
182 { |
|
183 return value >= other.value; |
|
184 } |
|
185 }; |
|
186 |
|
187 template<typename T, typename R> |
|
188 int qHash(TypeValue<T, R> value) |
|
189 { |
|
190 return qHash(value.value); |
|
191 } |
|
192 |
|
193 /** |
|
194 * Iterates a @c glm::mat |
|
195 */ |
|
196 template<int X, int Y, typename T, glm::qualifier Q, typename Fn> |
|
197 void iter_matrix(const glm::mat<X, Y, T, Q>& matrix, Fn&& fn) |
|
198 { |
|
199 for (int i = 0; i < X; ++i) |
|
200 { |
|
201 for (int j = 0; j < Y; ++j) |
|
202 { |
|
203 fn(i, j, matrix[i][j]); |
|
204 } |
|
205 } |
|
206 } |
|
207 |
|
208 inline QDataStream& operator<<(QDataStream& stream, const glm::vec3& vec) |
|
209 { |
|
210 return stream << vec.x << vec.y << vec.z; |
|
211 } |
|
212 |
|
213 inline QDataStream& operator>>(QDataStream& stream, glm::vec3& vec) |
|
214 { |
|
215 return stream >> vec.x >> vec.y >> vec.z; |
|
216 } |
|
217 |
|
218 template<int X, int Y, typename T, glm::qualifier Q> |
|
219 QDataStream& operator<<(QDataStream& stream, const glm::mat<X, Y, T, Q>& mat) |
|
220 { |
|
221 iter_matrix(mat, [&stream](int, int, float x) |
|
222 { |
|
223 stream << x; |
|
224 }); |
|
225 return stream; |
|
226 } |
|
227 |
|
228 template<int X, int Y, typename T, glm::qualifier Q> |
|
229 QDataStream& operator>>(QDataStream& stream, glm::mat<X, Y, T, Q>& mat) |
|
230 { |
|
231 iter_matrix(mat, [&stream](int, int, float x) |
|
232 { |
|
233 stream >> x; |
|
234 }); |
|
235 return stream; |
|
236 } |
|
237 |
|
238 template<std::size_t N, typename T> |
|
239 std::array<T, N> vectorToArray(const std::vector<T>& x) |
|
240 { |
|
241 std::array<T, N> result; |
|
242 for (std::size_t i = 0; i < x.size() and i < N; i += 1) |
|
243 { |
|
244 result[i] = x[i]; |
|
245 } |
|
246 return result; |
|
247 } |
|
248 |
|
249 template<typename T> |
|
250 std::optional<T> pointerToOptional(const T* p) |
|
251 { |
|
252 std::optional<T> result; |
|
253 if (p != nullptr) { |
|
254 result = *p; |
|
255 } |
|
256 return result; |
|
257 } |
|
258 |
|
259 template<typename T, typename R> |
|
260 void removeFromMap(std::map<T, R>& map, T&& key) |
|
261 { |
|
262 const auto it = map.find(key); |
|
263 if (it != map.end()) { |
|
264 map.erase(it); |
|
265 } |
|
266 } |
|
267 |
|
268 template<typename T> |
|
269 using opt = std::optional<T>; |
|
270 |
|
271 // some magic code from https://en.cppreference.com/w/cpp/utility/variant/visit |
|
272 // for use with std::visit |
|
273 template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; }; |
|
274 template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>; |
|