252 if (line == "0 BFC INVERTNEXT" or line == "0 BFC CERTIFY INVERTNEXT") |
252 if (line == "0 BFC INVERTNEXT" or line == "0 BFC CERTIFY INVERTNEXT") |
253 { |
253 { |
254 invertNext = true; |
254 invertNext = true; |
255 continue; |
255 continue; |
256 } |
256 } |
257 std::unique_ptr<modelobjects::BaseObject> object = parseFromString(line); |
257 std::unique_ptr<linetypes::Object> object = parseFromString(line); |
258 if (invertNext) |
258 if (invertNext) |
259 { |
259 { |
260 editor.setObjectProperty(object.get(), modelobjects::Property::IsInverted, true); |
260 editor.setObjectProperty(object.get(), linetypes::Property::IsInverted, true); |
261 } |
261 } |
262 editor.append(std::move(object)); |
262 editor.append(std::move(object)); |
263 invertNext = false; |
263 invertNext = false; |
264 } |
264 } |
265 } |
265 } |
315 } |
315 } |
316 } |
316 } |
317 return result; |
317 return result; |
318 } |
318 } |
319 |
319 |
320 static std::unique_ptr<modelobjects::BaseObject> parseType0Line( |
320 static std::unique_ptr<linetypes::Object> parseType0Line( |
321 const QString& line, |
321 const QString& line, |
322 const QStringList& tokens) |
322 const QStringList& tokens) |
323 { |
323 { |
324 Q_UNUSED(tokens) |
324 Q_UNUSED(tokens) |
325 if (line.startsWith("0 //")) |
325 if (line.startsWith("0 //")) |
326 { |
326 { |
327 return std::make_unique<modelobjects::Comment>(line.mid(std::strlen("0 //")).simplified()); |
327 return std::make_unique<linetypes::Comment>(line.mid(std::strlen("0 //")).simplified()); |
328 } |
328 } |
329 else |
329 else |
330 { |
330 { |
331 return std::make_unique<modelobjects::MetaCommand>(line.mid(1).simplified()); |
331 return std::make_unique<linetypes::MetaCommand>(line.mid(1).simplified()); |
332 } |
332 } |
333 } |
333 } |
334 |
334 |
335 static std::unique_ptr<modelobjects::SubfileReference> parseType1Line( |
335 static std::unique_ptr<linetypes::SubfileReference> parseType1Line( |
336 const QString& line, |
336 const QString& line, |
337 const QStringList& tokens) |
337 const QStringList& tokens) |
338 { |
338 { |
339 Q_UNUSED(line) |
339 Q_UNUSED(line) |
340 constexpr int colorPosition = 1; |
340 constexpr int colorPosition = 1; |
347 } |
347 } |
348 const Color color = colorFromString(tokens[colorPosition]); |
348 const Color color = colorFromString(tokens[colorPosition]); |
349 const Vertex position = vertexFromStrings(tokens, positionPosition); |
349 const Vertex position = vertexFromStrings(tokens, positionPosition); |
350 const Matrix3x3 transform = matrixFromStrings(tokens, transformPosition); |
350 const Matrix3x3 transform = matrixFromStrings(tokens, transformPosition); |
351 const QString& name = tokens[namePosition]; |
351 const QString& name = tokens[namePosition]; |
352 return std::make_unique<modelobjects::SubfileReference>(position, transform, name, color); |
352 return std::make_unique<linetypes::SubfileReference>(position, transform, name, color); |
353 } |
353 } |
354 |
354 |
355 template<typename T, int NumVertices> |
355 template<typename T, int NumVertices> |
356 static std::unique_ptr<T> parsePolygon( |
356 static std::unique_ptr<T> parsePolygon( |
357 const QString& line, |
357 const QString& line, |
372 vertices.append(vertexFromStrings(tokens, vertexPosition(i))); |
372 vertices.append(vertexFromStrings(tokens, vertexPosition(i))); |
373 } |
373 } |
374 return std::make_unique<T>(vertices, color); |
374 return std::make_unique<T>(vertices, color); |
375 } |
375 } |
376 |
376 |
377 std::unique_ptr<modelobjects::BaseObject> Parser::parseFromString(QString line) |
377 std::unique_ptr<linetypes::Object> Parser::parseFromString(QString line) |
378 { |
378 { |
379 line = line.simplified(); |
379 line = line.simplified(); |
380 try |
380 try |
381 { |
381 { |
382 const QStringList tokens = line.split(QRegExp{R"(\s+)"}); |
382 const QStringList tokens = line.split(QRegExp{R"(\s+)"}); |
383 if (tokens.empty() or tokens == QStringList{{""}}) |
383 if (tokens.empty() or tokens == QStringList{{""}}) |
384 { |
384 { |
385 return std::make_unique<modelobjects::Empty>(); |
385 return std::make_unique<linetypes::Empty>(); |
386 } |
386 } |
387 bool ok_code; |
387 bool ok_code; |
388 const int code = tokens[0].toInt(&ok_code); |
388 const int code = tokens[0].toInt(&ok_code); |
389 if (not ok_code) |
389 if (not ok_code) |
390 { |
390 { |
395 case 0: |
395 case 0: |
396 return parseType0Line(line, tokens); |
396 return parseType0Line(line, tokens); |
397 case 1: |
397 case 1: |
398 return parseType1Line(line, tokens); |
398 return parseType1Line(line, tokens); |
399 case 2: |
399 case 2: |
400 return parsePolygon<modelobjects::Edge, 2>(line, tokens); |
400 return parsePolygon<linetypes::Edge, 2>(line, tokens); |
401 case 3: |
401 case 3: |
402 return parsePolygon<modelobjects::Triangle, 3>(line, tokens); |
402 return parsePolygon<linetypes::Triangle, 3>(line, tokens); |
403 case 4: |
403 case 4: |
404 return parsePolygon<modelobjects::Quadrilateral, 4>(line, tokens); |
404 return parsePolygon<linetypes::Quadrilateral, 4>(line, tokens); |
405 case 5: |
405 case 5: |
406 return parsePolygon<modelobjects::ConditionalEdge, 4>(line, tokens); |
406 return parsePolygon<linetypes::ConditionalEdge, 4>(line, tokens); |
407 default: |
407 default: |
408 throw BodyParseError{utility::format("bad line type '%1'", code)}; |
408 throw BodyParseError{utility::format("bad line type '%1'", code)}; |
409 } |
409 } |
410 } |
410 } |
411 catch(const BodyParseError& error) |
411 catch(const BodyParseError& error) |
412 { |
412 { |
413 return std::make_unique<modelobjects::ErrorLine>(line, error.message); |
413 return std::make_unique<linetypes::ErrorLine>(line, error.message); |
414 } |
414 } |
415 } |
415 } |