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