Mon, 27 Sep 2021 21:04:45 +0300
work on saving
3 | 1 | /* |
2 | * LDForge: LDraw parts authoring CAD | |
24 | 3 | * Copyright (C) 2013 - 2020 Teemu Piippo |
3 | 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 | #include "model.h" | |
20 | #include "parser.h" | |
14 | 21 | #include "linetypes/comment.h" |
22 | #include "linetypes/conditionaledge.h" | |
23 | #include "linetypes/edge.h" | |
24 | #include "linetypes/errorline.h" | |
25 | #include "linetypes/metacommand.h" | |
26 | #include "linetypes/object.h" | |
15
9e18ec63eec3
split quadrilateral and triangle into their own source files
Teemu Piippo <teemu@hecknology.net>
parents:
14
diff
changeset
|
27 | #include "linetypes/quadrilateral.h" |
14 | 28 | #include "linetypes/subfilereference.h" |
15
9e18ec63eec3
split quadrilateral and triangle into their own source files
Teemu Piippo <teemu@hecknology.net>
parents:
14
diff
changeset
|
29 | #include "linetypes/triangle.h" |
3 | 30 | |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
31 | struct BodyParseError |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
32 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
33 | QString message; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
34 | }; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
35 | |
3 | 36 | /* |
37 | * Constructs an LDraw parser | |
38 | */ | |
39 | Parser::Parser(QIODevice& device, QObject* parent) : | |
40 | QObject {parent}, | |
41 | device {device} {} | |
42 | ||
43 | /* | |
44 | * Reads a single line from the device. | |
45 | */ | |
46 | QString Parser::readLine() | |
47 | { | |
48 | return QString::fromUtf8(this->device.readLine()).trimmed(); | |
49 | } | |
50 | ||
51 | /* | |
52 | * Parses a single line of the header. | |
53 | * Possible parse results: | |
54 | * · ParseSuccess: the header line was parsed successfully. | |
55 | * · ParseFailure: the header line was parsed incorrectly and needs to be handled otherwise. | |
56 | * · StopParsing: the line does not belong in the header and header parsing needs to stop. | |
57 | */ | |
58 | Parser::HeaderParseResult Parser::parseHeaderLine( | |
59 | LDHeader& header, | |
60 | Winding& winding, | |
61 | const QString& line | |
62 | ) { | |
63 | if (line.isEmpty()) | |
64 | { | |
65 | return ParseSuccess; | |
66 | } | |
67 | else if (not line.startsWith("0") or line.startsWith("0 //")) | |
68 | { | |
69 | return StopParsing; | |
70 | } | |
71 | else if (line.startsWith("0 !LDRAW_ORG ")) | |
72 | { | |
73 | QStringList tokens = line | |
74 | .mid(strlen("0 !LDRAW_ORG ")) | |
105
6ca6e8c647d4
added preview layer code and fixed build warnings
Teemu Piippo <teemu@hecknology.net>
parents:
77
diff
changeset
|
75 | .split(" ", Qt::SkipEmptyParts); |
3 | 76 | if (not tokens.isEmpty()) |
77 | { | |
78 | QString partTypeString = tokens[0]; | |
79 | // Anything that enters LDForge becomes unofficial in any case if saved. | |
80 | // Therefore we don't need to give the Unofficial type any special | |
81 | // consideration. | |
82 | if (partTypeString.startsWith("Unofficial_")) | |
83 | partTypeString = partTypeString.mid(strlen("Unofficial_")); | |
140 | 84 | header.type = headerTypeFromString(partTypeString); |
33
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
85 | header.qualfiers = {}; |
3 | 86 | if (tokens.contains("Alias")) |
87 | header.qualfiers |= LDHeader::Alias; | |
88 | if (tokens.contains("Physical_Color")) | |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
89 | header.qualfiers |= LDHeader::PhysicalColour; |
3 | 90 | if (tokens.contains("Flexible_Section")) |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
91 | header.qualfiers |= LDHeader::FlexibleSection; |
3 | 92 | return ParseSuccess; |
93 | } | |
94 | else | |
95 | { | |
96 | return ParseFailure; | |
97 | } | |
98 | } | |
99 | else if (line == "0 BFC CERTIFY CCW") | |
100 | { | |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
101 | winding = Anticlockwise; |
3 | 102 | return ParseSuccess; |
103 | } | |
104 | else if (line == "0 BFC CERTIFY CW") | |
105 | { | |
106 | winding = Clockwise; | |
107 | return ParseSuccess; | |
108 | } | |
109 | else if (line == "0 BFC NOCERTIFY") | |
110 | { | |
111 | winding = NoWinding; | |
112 | return ParseSuccess; | |
113 | } | |
114 | else if (line.startsWith("0 !HISTORY ")) | |
115 | { | |
116 | static const QRegExp historyRegexp { | |
117 | R"(0 !HISTORY\s+(\d{4}-\d{2}-\d{2})\s+)" | |
118 | R"((\{[^}]+|\[[^]]+)[\]}]\s+(.+))" | |
119 | }; | |
120 | if (historyRegexp.exactMatch(line)) | |
121 | { | |
122 | QString dateString = historyRegexp.capturedTexts().value(1); | |
123 | QString authorWithPrefix = historyRegexp.capturedTexts().value(2); | |
124 | QString description = historyRegexp.capturedTexts().value(3); | |
125 | LDHeader::HistoryEntry historyEntry; | |
126 | historyEntry.date = QDate::fromString(dateString, Qt::ISODate); | |
127 | historyEntry.description = description; | |
128 | ||
129 | if (authorWithPrefix[0] == '{') | |
130 | historyEntry.author = authorWithPrefix + "}"; | |
131 | else | |
132 | historyEntry.author = authorWithPrefix.mid(1); | |
133 | ||
134 | header.history.append(historyEntry); | |
135 | return ParseSuccess; | |
136 | } | |
137 | else | |
138 | { | |
139 | return ParseFailure; | |
140 | } | |
141 | } | |
142 | else if (line.startsWith("0 Author: ")) | |
143 | { | |
144 | header.author = line.mid(strlen("0 Author: ")); | |
145 | return ParseSuccess; | |
146 | } | |
147 | else if (line.startsWith("0 Name: ")) | |
148 | { | |
149 | header.name = line.mid(strlen("0 Name: ")); | |
150 | return ParseSuccess; | |
151 | } | |
152 | else if (line.startsWith("0 !HELP ")) | |
153 | { | |
154 | if (not header.help.isEmpty()) | |
155 | header.help += "\n"; | |
156 | header.help += line.mid(strlen("0 !HELP ")); | |
157 | return ParseSuccess; | |
158 | } | |
159 | else if (line.startsWith("0 !KEYWORDS ")) | |
160 | { | |
161 | if (not header.keywords.isEmpty()) | |
162 | header.keywords += "\n"; | |
163 | header.keywords += line.mid(strlen("0 !KEYWORDS ")); | |
164 | return ParseSuccess; | |
165 | } | |
166 | else if (line.startsWith("0 !CATEGORY ")) | |
167 | { | |
168 | header.category = line.mid(strlen("0 !CATEGORY ")); | |
169 | return ParseSuccess; | |
170 | } | |
171 | else if (line.startsWith("0 !CMDLINE ")) | |
172 | { | |
173 | header.cmdline = line.mid(strlen("0 !CMDLINE ")); | |
174 | return ParseSuccess; | |
175 | } | |
140 | 176 | else if (line.startsWith(LDHeader::caLicenseString)) |
3 | 177 | { |
178 | header.license = LDHeader::CaLicense; | |
179 | return ParseSuccess; | |
180 | } | |
140 | 181 | else if (line.startsWith(LDHeader::nonCaLicenseString)) |
3 | 182 | { |
183 | header.license = LDHeader::NonCaLicense; | |
184 | return ParseSuccess; | |
185 | } | |
186 | else | |
187 | { | |
188 | return ParseFailure; | |
189 | } | |
190 | } | |
191 | ||
192 | /* | |
193 | * Parses the header from the device given at construction and returns | |
194 | * the resulting header structure. | |
195 | */ | |
196 | LDHeader Parser::parseHeader(Winding& winding) | |
197 | { | |
198 | LDHeader header = {}; | |
199 | if (not this->device.atEnd()) | |
200 | { | |
201 | // Parse the description | |
202 | QString descriptionLine = this->readLine(); | |
203 | if (descriptionLine.startsWith("0 ")) | |
204 | { | |
205 | header.description = descriptionLine.mid(strlen("0 ")).trimmed(); | |
206 | // Parse the rest of the header | |
207 | while (not this->device.atEnd()) | |
208 | { | |
209 | const QString& line = this->readLine(); | |
210 | auto result = parseHeaderLine(header, winding, line); | |
211 | if (result == ParseFailure) | |
212 | { | |
213 | // Failed to parse this header line, add it as a comment into the body later. | |
214 | this->bag.append(line); | |
215 | } | |
216 | else if (result == StopParsing) | |
217 | { | |
218 | // Header parsing stops, add this line to the body. | |
219 | this->bag.append(line); | |
220 | break; | |
221 | } | |
222 | } | |
223 | } | |
224 | else | |
225 | { | |
226 | this->bag.append(descriptionLine); | |
227 | } | |
228 | } | |
229 | return header; | |
230 | } | |
231 | ||
232 | /** | |
233 | * @brief Parses the model body into the given model. | |
234 | * @param editor Handle to model edit context | |
235 | */ | |
236 | void Parser::parseBody(Model::EditContext& editor) | |
237 | { | |
238 | bool invertNext = false; | |
239 | while (not this->device.atEnd()) | |
240 | this->bag.append(this->readLine()); | |
241 | for (const QString& line : this->bag) | |
242 | { | |
243 | if (line == "0 BFC INVERTNEXT" or line == "0 BFC CERTIFY INVERTNEXT") | |
244 | { | |
245 | invertNext = true; | |
246 | continue; | |
247 | } | |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
248 | std::unique_ptr<ldraw::Object> object = parseFromString(line); |
26 | 249 | auto id = editor.append(std::move(object)); |
3 | 250 | if (invertNext) |
251 | { | |
26 | 252 | editor.invertObject(id); |
3 | 253 | } |
254 | invertNext = false; | |
255 | } | |
77
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
256 | // Test quadrilateral splitting by splitting all the quadrilaterals |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
257 | QVector<ldraw::quadrilateralid_t> quadrilateral_ids; |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
258 | for (int i = 0; i < editor.model().size(); i += 1) |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
259 | { |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
260 | const ldraw::id_t id = editor.model().resolve(editor.model().index(i)); |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
261 | const ldraw::quadrilateralid_t quad_id = editor.model().checkType<ldraw::Quadrilateral>(id); |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
262 | if (not(quad_id == ldraw::NULL_ID)) |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
263 | { |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
264 | quadrilateral_ids.push_back(quad_id); |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
265 | } |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
266 | } |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
267 | for (const ldraw::quadrilateralid_t id : quadrilateral_ids) |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
268 | { |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
269 | ldraw::splitQuadrilateral(editor, id); |
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
270 | } |
3 | 271 | } |
272 | ||
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
273 | static ldraw::Color colorFromString(const QString& colorString) |
4
68988ebc2a68
added regular expressions for the parser
Teemu Piippo <teemu@hecknology.net>
parents:
3
diff
changeset
|
274 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
275 | bool colorSucceeded; |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
276 | const ldraw::Color color = {colorString.toInt(&colorSucceeded)}; |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
277 | if (colorSucceeded) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
278 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
279 | return color; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
280 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
281 | else |
4
68988ebc2a68
added regular expressions for the parser
Teemu Piippo <teemu@hecknology.net>
parents:
3
diff
changeset
|
282 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
283 | throw BodyParseError{"colour was not an integer value"}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
284 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
285 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
286 | |
33
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
287 | static glm::vec3 vertexFromStrings( |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
288 | const QStringList& tokens, |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
289 | const int startingPosition) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
290 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
291 | bool ok_x; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
292 | const float x = tokens[startingPosition].toFloat(&ok_x); |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
293 | bool ok_y; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
294 | const float y = tokens[startingPosition + 1].toFloat(&ok_y); |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
295 | bool ok_z; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
296 | const float z = tokens[startingPosition + 2].toFloat(&ok_z); |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
297 | if (not ok_x or not ok_y or not ok_z) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
298 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
299 | throw BodyParseError{"vertex contained illegal co-ordinates"}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
300 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
301 | return {x, y, z}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
302 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
303 | |
115 | 304 | static glm::mat4 matrixFromStrings( |
305 | const QStringList& tokens, | |
306 | const int startingPosition, | |
307 | const int positionStartingIndex) | |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
308 | { |
33
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
309 | glm::mat4 result = glm::mat4{1}; |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
310 | for (int i = 0; i < 9; i += 1) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
311 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
312 | const int row = i / 3; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
313 | const int column = i % 3; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
314 | const int index = i + startingPosition; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
315 | if (index >= tokens.size()) |
4
68988ebc2a68
added regular expressions for the parser
Teemu Piippo <teemu@hecknology.net>
parents:
3
diff
changeset
|
316 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
317 | throw BodyParseError{"too few tokens available"}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
318 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
319 | bool ok; |
33
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
320 | // note that glm::mat4 is column-major |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
321 | result[column][row] = tokens[index].toFloat(&ok); |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
322 | if (not ok) |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
323 | { |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
324 | throw BodyParseError{"non-numeric values for matrix"}; |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
325 | } |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
326 | } |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
327 | for (int i = 0; i < 3; i += 1) |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
328 | { |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
329 | bool ok; |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
330 | const auto value = tokens[i + positionStartingIndex].toFloat(&ok); |
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
331 | result[3][i] = value; |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
332 | if (not ok) |
4
68988ebc2a68
added regular expressions for the parser
Teemu Piippo <teemu@hecknology.net>
parents:
3
diff
changeset
|
333 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
334 | throw BodyParseError{"non-numeric values for matrix"}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
335 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
336 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
337 | return result; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
338 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
339 | |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
340 | static std::unique_ptr<ldraw::Object> parseType0Line( |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
341 | const QString& line, |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
342 | const QStringList& tokens) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
343 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
344 | Q_UNUSED(tokens) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
345 | if (line.startsWith("0 //")) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
346 | { |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
347 | return std::make_unique<ldraw::Comment>(line.mid(std::strlen("0 //")).simplified()); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
348 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
349 | else |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
350 | { |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
351 | return std::make_unique<ldraw::MetaCommand>(line.mid(1).simplified()); |
4
68988ebc2a68
added regular expressions for the parser
Teemu Piippo <teemu@hecknology.net>
parents:
3
diff
changeset
|
352 | } |
68988ebc2a68
added regular expressions for the parser
Teemu Piippo <teemu@hecknology.net>
parents:
3
diff
changeset
|
353 | } |
68988ebc2a68
added regular expressions for the parser
Teemu Piippo <teemu@hecknology.net>
parents:
3
diff
changeset
|
354 | |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
355 | static std::unique_ptr<ldraw::SubfileReference> parseType1Line( |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
356 | const QString& line, |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
357 | const QStringList& tokens) |
5 | 358 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
359 | Q_UNUSED(line) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
360 | constexpr int colorPosition = 1; |
23
3387a84ddaba
fixed a pile of nonsense that caused subfiles to go haywire
Teemu Piippo <teemu@hecknology.net>
parents:
21
diff
changeset
|
361 | constexpr int positionPosition = 2; // 2..4 |
3387a84ddaba
fixed a pile of nonsense that caused subfiles to go haywire
Teemu Piippo <teemu@hecknology.net>
parents:
21
diff
changeset
|
362 | constexpr int transformPosition = 5; // 5..13 |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
363 | constexpr int namePosition = 14; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
364 | if (tokens.size() != 15) |
5 | 365 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
366 | throw BodyParseError{"wrong amount of tokens in a type-1 line"}; |
5 | 367 | } |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
368 | const ldraw::Color color = colorFromString(tokens[colorPosition]); |
33
4c41bfe2ec6e
replaced matrix and vertex classes with glm
Teemu Piippo <teemu@hecknology.net>
parents:
26
diff
changeset
|
369 | const glm::mat4 transform = matrixFromStrings(tokens, transformPosition, positionPosition); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
370 | const QString& name = tokens[namePosition]; |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
371 | return std::make_unique<ldraw::SubfileReference>(transform, name, color); |
5 | 372 | } |
373 | ||
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
374 | template<typename T, int NumVertices> |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
375 | static std::unique_ptr<T> parsePolygon( |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
376 | const QString& line, |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
377 | const QStringList& tokens) |
5 | 378 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
379 | Q_UNUSED(line) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
380 | constexpr int colorPosition = 1; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
381 | auto vertexPosition = [](int n) { return 2 + 3*n; }; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
382 | if (tokens.size() != 2 + 3 * NumVertices) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
383 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
384 | throw BodyParseError{"wrong amount of tokens"}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
385 | } |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
386 | const ldraw::Color color = colorFromString(tokens[colorPosition]); |
77
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
387 | std::array<glm::vec3, NumVertices> vertices; |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
388 | for (int i = 0; i < NumVertices; i += 1) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
389 | { |
77
028798a72591
added some meta stuff, simplified quadrilateral splitting and tested it
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
390 | vertices[unsigned_cast(i)] = vertexFromStrings(tokens, vertexPosition(i)); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
391 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
392 | return std::make_unique<T>(vertices, color); |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
393 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
394 | |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
395 | std::unique_ptr<ldraw::Object> Parser::parseFromString(QString line) |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
396 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
397 | line = line.simplified(); |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
398 | try |
5 | 399 | { |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
400 | const QStringList tokens = line.split(QRegExp{R"(\s+)"}); |
12 | 401 | if (tokens.empty() or tokens == QStringList{{""}}) |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
402 | { |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
403 | return std::make_unique<ldraw::Empty>(); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
404 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
405 | bool ok_code; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
406 | const int code = tokens[0].toInt(&ok_code); |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
407 | if (not ok_code) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
408 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
409 | throw BodyParseError{"line type was not an integer"}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
410 | } |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
411 | switch (code) |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
412 | { |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
413 | case 0: |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
414 | return parseType0Line(line, tokens); |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
415 | case 1: |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
416 | return parseType1Line(line, tokens); |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
417 | case 2: |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
418 | return parsePolygon<ldraw::Edge, 2>(line, tokens); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
419 | case 3: |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
420 | return parsePolygon<ldraw::Triangle, 3>(line, tokens); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
421 | case 4: |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
422 | return parsePolygon<ldraw::Quadrilateral, 4>(line, tokens); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
423 | case 5: |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
424 | return parsePolygon<ldraw::ConditionalEdge, 4>(line, tokens); |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
425 | default: |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
426 | throw BodyParseError{utility::format("bad line type '%1'", code)}; |
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
427 | } |
5 | 428 | } |
8
44679e468ba9
major update with many things
Teemu Piippo <teemu@hecknology.net>
parents:
5
diff
changeset
|
429 | catch(const BodyParseError& error) |
5 | 430 | { |
35
98906a94732f
renamed the linetypes namespace to ldraw namespace and added more structures to it
Teemu Piippo <teemu@hecknology.net>
parents:
33
diff
changeset
|
431 | return std::make_unique<ldraw::ErrorLine>(line, error.message); |
5 | 432 | } |
433 | } |