Mon, 11 May 2020 12:18:04 +0300
finetuning in multiplyfactordialog
#pragma once #include <QPointF> #include <QString> #include <QStringView> #include "main.h" #include "colors.h" #include "gl/common.h" namespace ldraw { struct GetPolygonsContext; enum class Property; class Object; class ColoredObject; class Empty; class UnhandledProperty; template<int N> class PolygonObject; } class DocumentManager; struct ldraw::GetPolygonsContext { ::DocumentManager* documents; }; /** * @brief Different properties that can be queried with getProperty */ enum class ldraw::Property { Color, // Color of the object Text, // Text contained in a comment Point0, // First vertex in a polygon or edge line Point1, // Second vertex in a polygon or edge line Point2, // Third vertex in a polygon Point3, // Fourth vertex in a quadrilateral Transformation, // 4x4 transformation matrix of a subfile reference ReferenceName, // Subfile reference name IsInverted, // Whether or not the object has been inverted with BFC INVERTNEXT ErrorMessage // For error lines, why parsing failed }; // Mapping of properties to types #define LDFORGE_DEFINE_PROPERTY_TYPE(PROPERTY, TYPE) \ namespace ldraw { \ template<> struct PropertyType<ldraw::Property::PROPERTY> { using type = TYPE; }; \ } namespace ldraw { template<ldraw::Property property> struct PropertyType { }; template<ldraw::Property property> using PropertyType_t = typename PropertyType<property>::type; struct PropertyKeyValue { Property key; QVariant value; }; constexpr Property pointProperty(int n) { Q_ASSERT(n >= 0 and n < 4); return static_cast<Property>(static_cast<int>(Property::Point0) + n); } } LDFORGE_DEFINE_PROPERTY_TYPE(Color, int) LDFORGE_DEFINE_PROPERTY_TYPE(Text, QString) LDFORGE_DEFINE_PROPERTY_TYPE(Point0, glm::vec3) LDFORGE_DEFINE_PROPERTY_TYPE(Point1, glm::vec3) LDFORGE_DEFINE_PROPERTY_TYPE(Point2, glm::vec3) LDFORGE_DEFINE_PROPERTY_TYPE(Point3, glm::vec3) LDFORGE_DEFINE_PROPERTY_TYPE(Transformation, glm::mat4) LDFORGE_DEFINE_PROPERTY_TYPE(ReferenceName, QString) LDFORGE_DEFINE_PROPERTY_TYPE(IsInverted, bool) LDFORGE_DEFINE_PROPERTY_TYPE(ErrorMessage, QString) #define LDRAW_OBJECT_HANDLE_SET_PROPERTY(PROPERTY, HANDLER) \ {this->handle<ldraw::Property::PROPERTY>(result, pair, \ [&](const ldraw::PropertyType_t<ldraw::Property::PROPERTY>& value) HANDLER);} class ldraw::Object { public: enum class SetPropertyResult { Success = 0, PropertyNotHandled }; friend bool handled(SetPropertyResult result) { return result == SetPropertyResult::Success; } class BadPointIndex : public std::exception { }; Object(); Object(const Object&) = delete; virtual ~Object(); const id_t id; virtual bool hasColor() const; virtual QVariant getProperty(Property id) const; template<ldraw::Property property> SetPropertyResult setProperty(const PropertyType_t<property>& value); SetPropertyResult setProperty(const PropertyKeyValue& pair); virtual QString textRepresentation() const = 0; virtual QBrush textRepresentationForeground() const; virtual QBrush textRepresentationBackground() const; virtual QFont textRepresentationFont() const; virtual void getPolygons(std::vector<gl::Polygon>& polygons, GetPolygonsContext* context) const; virtual void invert() {} virtual int numPoints() const { return 0; } virtual const glm::vec3& getPoint(int index) const; protected: template<Property property, typename Function> void handle(SetPropertyResult* result, const PropertyKeyValue& pair, Function function); virtual void setProperty(SetPropertyResult* result, const PropertyKeyValue& pair); }; template<ldraw::Property property> ldraw::Object::SetPropertyResult ldraw::Object::setProperty(const PropertyType_t<property>& value) { SetPropertyResult result = SetPropertyResult::PropertyNotHandled; this->setProperty(&result, PropertyKeyValue{property, QVariant::fromValue(value)}); return result; } template<ldraw::Property property, typename Function> void ldraw::Object::handle(SetPropertyResult* result, const PropertyKeyValue& pair, Function function) { if (pair.key == property) { function(pair.value.value<ldraw::PropertyType_t<property>>()); *result = SetPropertyResult::Success; } } class ldraw::ColoredObject : public Object { public: ColoredObject(const Color colorIndex = ldraw::mainColor); bool hasColor() const override final; QVariant getProperty(Property id) const override; Color colorIndex = ldraw::mainColor; protected: void setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) override; }; template<int N> class ldraw::PolygonObject : public ColoredObject { public: PolygonObject(const std::array<glm::vec3, N>& points, const Color color) : ColoredObject{color}, points{points} {} int numPoints() const override { return N; } const glm::vec3& getPoint(int index) const override { Q_ASSERT(index >= 0 and index < N); return this->points[index]; } QVariant getProperty(const Property id) const override { switch (id) { case Property::Point0: return QVariant::fromValue(points[0]); case Property::Point1: return QVariant::fromValue(points[1]); case Property::Point2: if (N >= 3) { return QVariant::fromValue(points[2]); } break; case Property::Point3: if (N >= 4) { return QVariant::fromValue(points[3]); } break; default: break; } return ColoredObject::getProperty(id); } void setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) { LDRAW_OBJECT_HANDLE_SET_PROPERTY(Point0, {points[0] = value;}) LDRAW_OBJECT_HANDLE_SET_PROPERTY(Point1, {points[1] = value;}) if constexpr (N >= 3) { LDRAW_OBJECT_HANDLE_SET_PROPERTY(Point2, {points[2] = value;}) } if constexpr (N >= 4) { LDRAW_OBJECT_HANDLE_SET_PROPERTY(Point3, {points[2] = value;}) } ColoredObject::setProperty(result, pair); } std::array<std::enable_if_t<(N > 0 and N <= 4), glm::vec3>, N> points; }; /** * @brief Represents an empty line. */ class ldraw::Empty : public Object { QString textRepresentation() const override; };