32 { |
32 { |
33 // List of setting groups |
33 // List of setting groups |
34 constexpr char mainwindow[] = "mainwindow"; |
34 constexpr char mainwindow[] = "mainwindow"; |
35 } |
35 } |
36 |
36 |
37 namespace ldraw |
|
38 { |
|
39 class Object; |
|
40 |
|
41 // Uniquely identifies a model body object |
|
42 template<typename T> |
|
43 struct Id |
|
44 { |
|
45 std::int32_t value; |
|
46 template<typename A, typename B> |
|
47 static constexpr bool is_base_or_base_of = std::disjunction_v<std::is_base_of<A, B>, std::is_base_of<B, A>>; |
|
48 template<typename R, typename = std::enable_if_t<is_base_or_base_of<T, R>>> |
|
49 constexpr bool operator<(ldraw::Id<R> other) const |
|
50 { |
|
51 return this->value < other.value; |
|
52 } |
|
53 friend constexpr unsigned int qHash(ldraw::Id<T> id) |
|
54 { |
|
55 return qHash(id.value); |
|
56 } |
|
57 // Allow comparing ids as long as they are related |
|
58 template<typename R, typename = std::enable_if_t<is_base_or_base_of<T, R>>> |
|
59 friend bool operator==(ldraw::Id<T> one, ldraw::Id<R> other) |
|
60 { |
|
61 return one.value == other.value; |
|
62 } |
|
63 // Allow upcasting |
|
64 template<typename R, typename = std::enable_if_t<std::is_base_of_v<R, T>>> |
|
65 constexpr operator Id<R>() const |
|
66 { |
|
67 return Id<R>{this->value}; |
|
68 } |
|
69 }; |
|
70 |
|
71 using id_t = Id<Object>; |
|
72 using triangleid_t = Id<class Triangle>; |
|
73 using quadrilateralid_t = Id<class Quadrilateral>; |
|
74 using edgeid_t = Id<class EdgeLine>; |
|
75 using conditionaledgeid_t = Id<class ConditionalEdge>; |
|
76 using subfileid_t = Id<class SubfileReference>; |
|
77 using commentid_t = Id<class Comment>; |
|
78 using metacommandid_t = Id<class MetaCommand>; |
|
79 |
|
80 constexpr struct NullId |
|
81 { |
|
82 template<typename T> |
|
83 constexpr operator Id<T>() const |
|
84 { |
|
85 return Id<T>{0}; |
|
86 } |
|
87 static constexpr decltype(ldraw::id_t::value) value = 0; |
|
88 } NULL_ID = {}; |
|
89 |
|
90 template<typename T> |
|
91 inline bool operator==(Id<T> one, decltype(NULL_ID)) |
|
92 { |
|
93 return one.value == 0; |
|
94 } |
|
95 |
|
96 template<typename T> |
|
97 inline bool operator!=(Id<T> one, decltype(NULL_ID)) |
|
98 { |
|
99 return one.value != 0; |
|
100 } |
|
101 |
|
102 template<typename T> |
|
103 inline bool operator<(Id<T> one, decltype(NULL_ID)) |
|
104 { |
|
105 return one.value < 0; |
|
106 } |
|
107 } |
|
108 |
|
109 constexpr std::size_t operator""_z(const unsigned long long int x) |
37 constexpr std::size_t operator""_z(const unsigned long long int x) |
110 { |
38 { |
111 return static_cast<std::size_t>(x); |
39 return static_cast<std::size_t>(x); |
112 } |
40 } |
113 |
41 |
260 int qHash(TypeValue<T, R> value) |
188 int qHash(TypeValue<T, R> value) |
261 { |
189 { |
262 return qHash(value.value); |
190 return qHash(value.value); |
263 } |
191 } |
264 |
192 |
265 using ModelId = TypeValue<int, struct TypeValueModelId>; |
|
266 |
|
267 /** |
193 /** |
268 * Iterates a @c glm::mat |
194 * Iterates a @c glm::mat |
269 */ |
195 */ |
270 template<int X, int Y, typename T, glm::qualifier Q, typename Fn> |
196 template<int X, int Y, typename T, glm::qualifier Q, typename Fn> |
271 void iter_matrix(const glm::mat<X, Y, T, Q>& matrix, Fn&& fn) |
197 void iter_matrix(const glm::mat<X, Y, T, Q>& matrix, Fn&& fn) |
277 fn(i, j, matrix[i][j]); |
203 fn(i, j, matrix[i][j]); |
278 } |
204 } |
279 } |
205 } |
280 } |
206 } |
281 |
207 |
282 QDataStream& operator<<(QDataStream&, const glm::vec3&); |
208 inline QDataStream& operator<<(QDataStream& stream, const glm::vec3& vec) |
283 QDataStream& operator>>(QDataStream&, glm::vec3&); |
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 } |
284 |
217 |
285 template<int X, int Y, typename T, glm::qualifier Q> |
218 template<int X, int Y, typename T, glm::qualifier Q> |
286 QDataStream& operator<<(QDataStream& stream, const glm::mat<X, Y, T, Q>& mat) |
219 QDataStream& operator<<(QDataStream& stream, const glm::mat<X, Y, T, Q>& mat) |
287 { |
220 { |
288 iter_matrix(mat, [&stream](int, int, float x) |
221 iter_matrix(mat, [&stream](int, int, float x) |
310 { |
243 { |
311 result[i] = x[i]; |
244 result[i] = x[i]; |
312 } |
245 } |
313 return result; |
246 return result; |
314 } |
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 // some magic code from https://en.cppreference.com/w/cpp/utility/variant/visit |
|
269 // for use with std::visit |
|
270 template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; }; |
|
271 template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>; |