Thu, 15 Jun 2023 16:18:03 +0300
Refactor, make selecting elements from the model select the corresponding line from the editor as well
/* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 - 2020 Teemu Piippo * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #pragma once #include <QAbstractListModel> #include <memory> #include "src/basics.h" #include "src/colors.h" #include <QTextDocument> struct SubfileReference { QString name; glm::mat4 transformation; }; template<typename T> struct Colored { T element; ldraw::Color color; }; struct Comment { QString text; }; struct ParseError { QString code; }; struct Empty {}; struct CircularFraction { unsigned int segments; unsigned int divisions; }; constexpr bool operator<(const CircularFraction& p, const CircularFraction& q) { // a/b < c/d // a < c * b / d // a * d < c * b return p.segments * q.divisions < q.segments / p.divisions; } enum class circular_primitive_type_e { circle, disc, cylinder, cylinder_open, cylinder_closed, disc_negative, chord, }; struct circular_primitive { static constexpr int NUM_TYPES = static_cast<int>(circular_primitive_type_e::chord) + 1; circular_primitive_type_e type; CircularFraction fraction; glm::mat4 transformation; bool inverted = false; }; constexpr char circularPrimitiveStems[circular_primitive::NUM_TYPES][5] = { "edge", "disc", "cyli", "cylo", "cylc", "ndis", "chrd", }; Q_DECLARE_METATYPE(circular_primitive_type_e) struct CircleToolOptions { CircularFraction fraction; circular_primitive_type_e type; }; using ModelElement = std::variant< Colored<SubfileReference>, Colored<LineSegment>, Colored<Triangle>, Colored<Quadrilateral>, Colored<ConditionalEdge>, Colored<circular_primitive>, Comment, Empty, ParseError>; using PlainPolygonElement = std::variant< LineSegment, Triangle, Quadrilateral, ConditionalEdge>; using PolygonElement = Colored<PlainPolygonElement>; template<typename Ret, typename Fn1, typename Fn2, typename Fn3, typename Fn4, typename T> constexpr auto visitPolygon(Fn1&& f1, Fn2&& f2, Fn3&& f3, Fn4&& f4, T&& element) { if (std::holds_alternative<LineSegment>(element)) { return f1(std::get<LineSegment>(element)); } else if (std::holds_alternative<Triangle>(element)) { return f2(std::get<Triangle>(element)); } else if (std::holds_alternative<Quadrilateral>(element)) { return f3(std::get<Quadrilateral>(element)); } else { return f4(std::get<ConditionalEdge>(element)); } } template<typename T, typename Fn> constexpr void visitPoints(Fn&& func, T&& element) { visitPolygon<void>( [&func](transfer_cvref_t<T&&, LineSegment> edge) { func(edge.p1); func(edge.p2); }, [&func](transfer_cvref_t<T&&, Triangle>& tri) { func(tri.p1); func(tri.p2); func(tri.p3); }, [&func](transfer_cvref_t<T&&, Quadrilateral>& quad) { func(quad.p1); func(quad.p2); func(quad.p3); func(quad.p4); }, [&func](transfer_cvref_t<T&&, ConditionalEdge>& cedge) { func(cedge.p1); func(cedge.p2); func(cedge.c1); func(cedge.c2); }, element); } constexpr Colored<LineSegment> edge(const glm::vec3& p1, const glm::vec3& p2) { return Colored<LineSegment>{{.p1 = p1, .p2 = p2}, EDGE_COLOR}; } constexpr Colored<Triangle> triangle(const glm::vec3& p1, const glm::vec3& p2, const glm::vec3& p3) { return Colored<Triangle>{{.p1 = p1, .p2 = p2, .p3 = p3}, MAIN_COLOR}; } constexpr Colored<Quadrilateral> quadrilateral( const glm::vec3& p1, const glm::vec3& p2, const glm::vec3& p3, const glm::vec3& p4) { return Colored<Quadrilateral>{{.p1 = p1, .p2 = p2, .p3 = p3, .p4 = p4}, MAIN_COLOR}; } struct AppendToModel { ModelElement newElement; }; struct DeleteFromModel { std::size_t position; }; struct ModifyModel { std::size_t position; ModelElement newElement; }; struct SelectInModel { std::size_t position; }; using ModelAction = std::variant< AppendToModel, DeleteFromModel, ModifyModel, SelectInModel>; QString modelElementToString(const ModelElement &element);