Tue, 11 Apr 2023 20:27:04 +0300
Simplify signature of updateRenderPreferences
#include "src/circularprimitive.h" #include "src/documentmanager.h" #include "src/invert.h" #include "src/polygoncache.h" #include "src/parser.h" QTextDocument* resolve(const QString& name, const ModelId callingModelId, DocumentManager* documents) { return documents->findDependencyByName(callingModelId, name); } static PolygonElement transformed( PolygonElement coloredElement, const glm::mat4& transform) { visitPoints([&transform](glm::vec3& p) { p = transform * glm::vec4{p, 1}; }, coloredElement.element); return coloredElement; } PolygonCache* findPolygonCacheForModel(QTextDocument* model, DocumentManager* context) { std::optional<ModelId> modelId = context->findIdForModel(model); if (modelId.has_value()) { return context->getPolygonCacheForModel(modelId.value()); } else { return nullptr; } } constexpr bool n_xor(bool a) { return a; } template<typename... Args> constexpr bool n_xor(bool a, Args&&... rest) { return a xor n_xor(rest...); } namespace { struct GetPolygonsContext { bool invertnext = false; ModelId modelId; class DocumentManager* documents; }; } template<typename Fn, typename Fn2> static void inlineSubfileReference( const PolygonCache::vector_type& polygons, const Colored<SubfileReference>& ref, GetPolygonsContext* context, Fn&& add, Fn2&& reserve) { const bool needInverting = 0 ^ (glm::determinant(ref.element.transformation) < 0) ^ (context->invertnext); reserve(polygons.size()); for (const PolygonElement& cacheElement : polygons) { PolygonElement polygon = transformed(cacheElement, ref.element.transformation); if (needInverting) { gl::invert(polygon.element); } if (polygon.color == MAIN_COLOR) { polygon.color = ref.color; } add(1, polygon); } } static QTextDocument* findDependency(const SubfileReference& ref, GetPolygonsContext* context) { return context->documents->findDependencyByName(context->modelId, ref.name); } template<typename Fn, typename Fn2> static void collectPolygons( const ParsedLine& element, winding_e& winding, GetPolygonsContext* context, Fn&& add, Fn2&& reserve) { bool foundinvertnext = false; std::visit<void>(overloaded{ [&](const LineType0& line0) { const QString text = line0.value.text.simplified(); if (text == QStringLiteral("BFC INVERTNEXT")) { context->invertnext = true; foundinvertnext = true; } else if (text == QStringLiteral("BFC CERTIFY CW")) { winding = winding_e::clockwise; } else if (text == QStringLiteral("BFC CERTIFY CCW")) { winding = winding_e::anticlockwise; } else if (text == QStringLiteral("BFC NOCERTIFY")) { winding = winding_e::none; } }, [&](const LineType2& line2) { add(2, {line2.value.element, line2.value.color}); }, [&](const LineType3& line3) { add(3, {line3.value.element, line3.value.color}); }, [&](const LineType4& line4) { add(4, {line4.value.element, line4.value.color}); }, [&](const LineType5& line5) { add(5, {line5.value.element, line5.value.color}); }, [&add, context, &reserve](const LineType1& line1) { QTextDocument* const dependency = findDependency(line1.value.element, context); if (PolygonCache* cache = (dependency != nullptr) ? findPolygonCacheForModel(dependency, context->documents) : nullptr ) { recacheIfNeeded(cache, dependency, context->documents); inlineSubfileReference(cache->polygons, line1.value, context, add, reserve); } }, #if 0 [&add](const Colored<CircularPrimitive>& circ) { rasterize(circ, [&](const PlainPolygonElement& polygon, ColorIndex color){ if (color == MAIN_COLOR) { color = circ.color; } add(PolygonElement{polygon, color}); }); }, #endif }, element); if (not foundinvertnext) { context->invertnext = false; } } static std::vector<WithId<PolygonElement>> inlinePolygons( const QTextDocument* model, GetPolygonsContext* context) { winding_e winding = winding_e::none; std::vector<WithId<PolygonElement>> result; int i = 0; const auto add = [&result, &winding, &i](int lineno, const PolygonElement& poly){ result.push_back({poly, i}); if (lineno != 1 and winding == winding_e::clockwise) { gl::invert(result.back().element); } }; const auto reserve = [&result](std::size_t incomingsize){ reserveMore(result, incomingsize); }; for (const QString& line : model->toPlainText().split("\n")) { const opt<ParsedLine> parsedline = parse(line); if (parsedline.has_value()) { collectPolygons(*parsedline, winding, context, add, reserve); } ++i; } return result; } void recacheIfNeeded(PolygonCache *cache, QTextDocument *model, DocumentManager *documents) { if (cache->needRecache) { cache->polygons.clear(); const std::optional<ModelId> modelId = documents->findIdForModel(model); if (modelId.has_value()) { GetPolygonsContext context{ .invertnext = false, .modelId = *modelId, .documents = documents, }; cache->polygons = inlinePolygons(model, &context); } cache->needRecache = false; } }