Thu, 19 Mar 2020 21:06:06 +0200
PolygonObjectEditor can now modify the object properly
--- a/locale/fi.ts Wed Mar 18 17:11:23 2020 +0200 +++ b/locale/fi.ts Thu Mar 19 21:06:06 2020 +0200 @@ -212,6 +212,22 @@ </message> </context> <context> + <name>MatrixEditor</name> + <message> + <location filename="../src/widgets/matrixeditor.ui" line="14"/> + <source>Form</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/widgets/matrixeditor.ui" line="87"/> + <location filename="../src/widgets/matrixeditor.ui" line="94"/> + <location filename="../src/widgets/matrixeditor.ui" line="101"/> + <location filename="../src/widgets/matrixeditor.ui" line="108"/> + <source>×</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> <name>MultiplyFactorDialog</name> <message> <location filename="../src/ui/multiplyfactordialog.ui" line="14"/> @@ -237,17 +253,17 @@ <context> <name>QObject</name> <message> - <location filename="../src/gl/partrenderer.cpp" line="244"/> + <location filename="../src/gl/partrenderer.cpp" line="250"/> <source>OpenGL error: %1</source> <translation>OpenGL-virhe: %1</translation> </message> <message> - <location filename="../src/gl/partrenderer.cpp" line="245"/> + <location filename="../src/gl/partrenderer.cpp" line="251"/> <source>OpenGL error</source> <translation>OpenGL-virhe</translation> </message> <message> - <location filename="../src/gl/partrenderer.cpp" line="247"/> + <location filename="../src/gl/partrenderer.cpp" line="253"/> <source>Damn it</source> <translation>Hemmetti</translation> </message>
--- a/locale/sv.ts Wed Mar 18 17:11:23 2020 +0200 +++ b/locale/sv.ts Thu Mar 19 21:06:06 2020 +0200 @@ -230,6 +230,17 @@ </message> </context> <context> + <name>MatrixEditor</name> + <message> + <source>Form</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>×</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> <name>MultiplyFactorDialog</name> <message> <source>Multiply with a scalar</source>
--- a/src/document.cpp Wed Mar 18 17:11:23 2020 +0200 +++ b/src/document.cpp Thu Mar 19 21:06:06 2020 +0200 @@ -70,6 +70,7 @@ this->renderer->handleSelectionChange(resolve(selected), resolve(deselected)); this->selectionChanged(resolve(this->ui.listView->selectionModel()->selection())); }); + connect(this->model, &Model::dataChanged, this->renderer, qOverload<>(&Canvas::update)); } Document::~Document()
--- a/src/gl/partrenderer.cpp Wed Mar 18 17:11:23 2020 +0200 +++ b/src/gl/partrenderer.cpp Thu Mar 19 21:06:06 2020 +0200 @@ -61,11 +61,7 @@ abort(); } this->compiler->initialize(); - this->compiler->build(this->model, this->documents, this->renderPreferences); - connect(this->model, &Model::dataChanged, [&]() - { - this->compiler->build(this->model, this->documents, this->renderPreferences); - }); + connect(this->model, &Model::dataChanged, this, &PartRenderer::build); this->initialized = true; this->modelQuaternion = glm::angleAxis(glm::radians(30.0f), glm::vec3{-1, 0, 0}); this->modelQuaternion *= glm::angleAxis(glm::radians(225.0f), glm::vec3{-0, 1, 0}); @@ -112,6 +108,11 @@ void PartRenderer::renderScene() { + if (this->needBuild) + { + this->compiler->build(this->model, this->documents, this->renderPreferences); + this->needBuild = false; + } this->checkForGLErrors(); if (this->renderPreferences.lineAntiAliasing && this->renderPreferences.style != gl::RenderStyle::PickScene) { @@ -212,6 +213,11 @@ { } +void PartRenderer::build() +{ + this->needBuild = true; +} + void PartRenderer::renderVao(const gl::ArrayClass arrayClass) { this->compiler->bindVertexArray(arrayClass); @@ -370,7 +376,7 @@ this->renderPreferences = newPreferences; if (mainColorChanged or backgroundColorChanged) { - this->compiler->build(this->model, this->documents, this->renderPreferences); + this->build(); this->setupBackgroundColor(); } emit this->renderPreferencesChanged();
--- a/src/gl/partrenderer.h Wed Mar 18 17:11:23 2020 +0200 +++ b/src/gl/partrenderer.h Thu Mar 19 21:06:06 2020 +0200 @@ -57,10 +57,12 @@ void updateViewMatrix(); void updateModelMatrix(); void setupBackgroundColor(); + Q_SLOT void build(); static constexpr double MIN_ZOOM = 0.0; static constexpr double MAX_ZOOM = 3.0; double zoom = 1.0; bool initialized = false; + bool needBuild = true; void renderVao(const gl::ArrayClass arrayClass); void checkForGLErrors(); };
--- a/src/linetypes/conditionaledge.cpp Wed Mar 18 17:11:23 2020 +0200 +++ b/src/linetypes/conditionaledge.cpp Thu Mar 19 21:06:06 2020 +0200 @@ -23,29 +23,20 @@ { switch (property) { - case Property::ControlPoint1: + case Property::ControlPoint0: return QVariant::fromValue(controlPoint_1); - case Property::ControlPoint2: + case Property::ControlPoint1: return QVariant::fromValue(controlPoint_2); default: return Edge::getProperty(property); } } -auto ldraw::ConditionalEdge::setProperty( - Property property, - const QVariant& value) - -> SetPropertyResult +void ldraw::ConditionalEdge::setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) { - switch (property) - { - case Property::ControlPoint1: - controlPoint_1 = value.value<glm::vec3>(); - case Property::ControlPoint2: - controlPoint_2 = value.value<glm::vec3>(); - default: - return Edge::setProperty(property, value); - } + LDRAW_OBJECT_HANDLE_SET_PROPERTY(ControlPoint0, {this->controlPoint_1 = value;}) + LDRAW_OBJECT_HANDLE_SET_PROPERTY(ControlPoint1, {this->controlPoint_2 = value;}) + BaseClass::setProperty(result, pair); } QString ldraw::ConditionalEdge::textRepresentation() const
--- a/src/linetypes/conditionaledge.h Wed Mar 18 17:11:23 2020 +0200 +++ b/src/linetypes/conditionaledge.h Thu Mar 19 21:06:06 2020 +0200 @@ -18,12 +18,11 @@ const Color colorIndex = ldraw::edgeColor); ConditionalEdge(const std::array<glm::vec3, 4>& vertices, const Color color); QVariant getProperty(Property property) const override; - SetPropertyResult setProperty( - Property property, - const QVariant& value) override; QString textRepresentation() const override; int numPoints() const override; const glm::vec3& getPoint(int index) const override; glm::vec3 controlPoint_1 = {}; glm::vec3 controlPoint_2 = {}; +protected: + void setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) override; };
--- a/src/linetypes/edge.cpp Wed Mar 18 17:11:23 2020 +0200 +++ b/src/linetypes/edge.cpp Thu Mar 19 21:06:06 2020 +0200 @@ -19,29 +19,20 @@ { switch (property) { - case Property::Point1: + case Property::Point0: return QVariant::fromValue(point_1); - case Property::Point2: + case Property::Point1: return QVariant::fromValue(point_2); default: return BaseClass::getProperty(property); } } -auto ldraw::Edge::setProperty(Property property, const QVariant& value) - -> SetPropertyResult +void ldraw::Edge::setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) { - switch (property) - { - case Property::Point1: - point_1 = value.value<glm::vec3>(); - return SetPropertyResult::Success; - case Property::Point2: - point_2 = value.value<glm::vec3>(); - return SetPropertyResult::Success; - default: - return BaseClass::setProperty(property, value); - } + LDRAW_OBJECT_HANDLE_SET_PROPERTY(Point0, {this->point_1 = value;}) + LDRAW_OBJECT_HANDLE_SET_PROPERTY(Point1, {this->point_2 = value;}) + BaseClass::setProperty(result, pair); } QString ldraw::Edge::textRepresentation() const
--- a/src/linetypes/edge.h Wed Mar 18 17:11:23 2020 +0200 +++ b/src/linetypes/edge.h Thu Mar 19 21:06:06 2020 +0200 @@ -15,13 +15,12 @@ const Color colorIndex = ldraw::edgeColor); Edge(const std::array<glm::vec3, 2>& vertices, const Color color); QVariant getProperty(Property property) const override; - SetPropertyResult setProperty( - Property property, - const QVariant& value) override; QString textRepresentation() const override; void getPolygons(std::vector<gl::Polygon>& polygons, GetPolygonsContext* context) const override; int numPoints() const override; const glm::vec3& getPoint(int index) const override; glm::vec3 point_1 = {}; glm::vec3 point_2 = {}; +protected: + void setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) override; };
--- a/src/linetypes/errorline.cpp Wed Mar 18 17:11:23 2020 +0200 +++ b/src/linetypes/errorline.cpp Thu Mar 19 21:06:06 2020 +0200 @@ -20,22 +20,11 @@ } } -auto ldraw::ErrorLine::setProperty( - Property property, - const QVariant& value) - -> SetPropertyResult +void ldraw::ErrorLine::setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) { - switch (property) - { - case Property::Text: - this->text = value.toString(); - return SetPropertyResult::Success; - case Property::ErrorMessage: - this->message = value.toString(); - return SetPropertyResult::Success; - default: - return Object::setProperty(property, value); - } + LDRAW_OBJECT_HANDLE_SET_PROPERTY(Text, {this->text = value;}); + LDRAW_OBJECT_HANDLE_SET_PROPERTY(ErrorMessage, {this->message = value;}); + BaseClass::setProperty(result, pair); } QString ldraw::ErrorLine::textRepresentation() const
--- a/src/linetypes/errorline.h Wed Mar 18 17:11:23 2020 +0200 +++ b/src/linetypes/errorline.h Thu Mar 19 21:06:06 2020 +0200 @@ -9,14 +9,14 @@ class ldraw::ErrorLine : public Object { public: + using BaseClass = Object; ErrorLine(QStringView text = u"", QStringView message = u""); QVariant getProperty(Property property) const override; - SetPropertyResult setProperty( - Property property, - const QVariant& value) override; QString textRepresentation() const override; QBrush textRepresentationForeground() const override; QBrush textRepresentationBackground() const override; QString text; QString message; +protected: + void setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) override; };
--- a/src/linetypes/metacommand.cpp Wed Mar 18 17:11:23 2020 +0200 +++ b/src/linetypes/metacommand.cpp Thu Mar 19 21:06:06 2020 +0200 @@ -15,20 +15,14 @@ } } -auto ldraw::MetaCommand::setProperty(Property property, const QVariant& value) - -> SetPropertyResult +void ldraw::MetaCommand::setProperty(ldraw::Object::SetPropertyResult* result, const PropertyKeyValue& pair) { - switch (property) - { - case Property::Text: - storedText = value.toString(); - return SetPropertyResult::Success; - default: - return Object::setProperty(property, value); - } + LDRAW_OBJECT_HANDLE_SET_PROPERTY(Text, {this->storedText = value;}); + BaseClass::setProperty(result, pair); } QString ldraw::MetaCommand::textRepresentation() const { return this->storedText; } +
--- a/src/linetypes/metacommand.h Wed Mar 18 17:11:23 2020 +0200 +++ b/src/linetypes/metacommand.h Thu Mar 19 21:06:06 2020 +0200 @@ -8,12 +8,12 @@ class ldraw::MetaCommand : public Object { public: + using BaseClass = Object; MetaCommand() = default; MetaCommand(QStringView text); QVariant getProperty(Property property) const override; - SetPropertyResult setProperty( - Property property, - const QVariant& value) override; QString textRepresentation() const override; QString storedText = ""; +protected: + void setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) override; };
--- a/src/linetypes/object.cpp Wed Mar 18 17:11:23 2020 +0200 +++ b/src/linetypes/object.cpp Thu Mar 19 21:06:06 2020 +0200 @@ -29,12 +29,20 @@ return {}; } -auto ldraw::Object::setProperty(Property id, const QVariant& value) - -> SetPropertyResult +void ldraw::Object::setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) { - Q_UNUSED(id) - Q_UNUSED(value) - return SetPropertyResult::PropertyNotHandled; + Q_UNUSED(result) + Q_UNUSED(pair) +} + +/** + * @brief public interface to setProperty + */ +ldraw::Object::SetPropertyResult ldraw::Object::setProperty(const PropertyKeyValue& pair) +{ + SetPropertyResult result; + this->setProperty(&result, pair); + return result; } QBrush ldraw::Object::textRepresentationForeground() const @@ -60,6 +68,7 @@ const glm::vec3& ldraw::Object::getPoint(int index) const { + Q_UNUSED(index); throw BadPointIndex{}; } @@ -84,28 +93,10 @@ } } -auto ldraw::ColoredObject::setProperty(Property id, const QVariant& value) - -> SetPropertyResult +void ldraw::ColoredObject::setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) { - switch (id) - { - case Property::Color: - { - bool ok; - const int value_int = value.toInt(&ok); - if (ok) - { - colorIndex.index = value_int; - return SetPropertyResult::Success; - } - else - { - return SetPropertyResult::InvalidValue; - } - } - default: - return Object::setProperty(id, value); - } + LDRAW_OBJECT_HANDLE_SET_PROPERTY(Color, {colorIndex.index = value;}); + Object::setProperty(result, pair); } QString ldraw::Empty::textRepresentation() const
--- a/src/linetypes/object.h Wed Mar 18 17:11:23 2020 +0200 +++ b/src/linetypes/object.h Thu Mar 19 21:06:06 2020 +0200 @@ -30,12 +30,12 @@ { Color, // Color of the object Text, // Text contained in a comment - Point1, // First vertex in a polygon or edge line - Point2, // Second vertex in a polygon or edge line - Point3, // Third vertex in a polygon - Point4, // Fourth vertex in a quadrilateral - ControlPoint1, // First control point in a conditional edge line - ControlPoint2, // Second control point in a conditional edge line + 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 + ControlPoint0, // First control point in a conditional edge line + ControlPoint1, // Second control point in a conditional edge line Transformation, // 4x4 transformation matrix of a subfile reference ReferenceName, // Subfile reference name IsInverted, // Whether or not the object has been inverted with BFC INVERTNEXT @@ -57,30 +57,49 @@ 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(Point4, glm::vec3) +LDFORGE_DEFINE_PROPERTY_TYPE(ControlPoint0, glm::vec3) LDFORGE_DEFINE_PROPERTY_TYPE(ControlPoint1, glm::vec3) -LDFORGE_DEFINE_PROPERTY_TYPE(ControlPoint2, 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, - InvalidValue + PropertyNotHandled }; + friend bool handled(SetPropertyResult result) + { + return result == SetPropertyResult::Success; + } class BadPointIndex : public std::exception { }; @@ -88,10 +107,11 @@ Object(const Object&) = delete; virtual ~Object(); const id_t id; - //virtual void toString(QTextStream &out) = 0; virtual bool hasColor() const; virtual QVariant getProperty(Property id) const; - virtual SetPropertyResult setProperty(Property id, const QVariant& value); + 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; @@ -100,16 +120,39 @@ 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; - SetPropertyResult setProperty(Property id, const QVariant& value) override; Color colorIndex = ldraw::mainColor; +protected: + void setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) override; }; /**
--- a/src/linetypes/quadrilateral.cpp Wed Mar 18 17:11:23 2020 +0200 +++ b/src/linetypes/quadrilateral.cpp Thu Mar 19 21:06:06 2020 +0200 @@ -1,17 +1,23 @@ #include "quadrilateral.h" -ldraw::Quadrilateral::Quadrilateral( +ldraw::Quadrilateral::Quadrilateral +( const glm::vec3& point_1, const glm::vec3& point_2, const glm::vec3& point_3, const glm::vec3& point_4, - Color color_index) : + Color color_index +) : ColoredObject{color_index}, points{point_1, point_2, point_3, point_4} { } -ldraw::Quadrilateral::Quadrilateral(const std::array<glm::vec3, 4>& vertices, const Color color) : +ldraw::Quadrilateral::Quadrilateral +( + const std::array<glm::vec3, 4>& vertices, + const Color color +) : ColoredObject{color}, points{vertices[0], vertices[1], vertices[2], vertices[3]} { @@ -21,41 +27,26 @@ { switch (id) { - case Property::Point1: + case Property::Point0: return QVariant::fromValue(points[0]); - case Property::Point2: + case Property::Point1: return QVariant::fromValue(points[1]); - case Property::Point3: + case Property::Point2: return QVariant::fromValue(points[2]); - case Property::Point4: + case Property::Point3: return QVariant::fromValue(points[3]); default: return ColoredObject::getProperty(id); } } -auto ldraw::Quadrilateral::setProperty( - const Property id, - const QVariant& value) - -> SetPropertyResult +void ldraw::Quadrilateral::setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) { - switch (id) - { - case Property::Point1: - points[0] = value.value<glm::vec3>(); - return SetPropertyResult::Success; - case Property::Point2: - points[1] = value.value<glm::vec3>(); - return SetPropertyResult::Success; - case Property::Point3: - points[2] = value.value<glm::vec3>(); - return SetPropertyResult::Success; - case Property::Point4: - points[3] = value.value<glm::vec3>(); - return SetPropertyResult::Success; - default: - return ColoredObject::setProperty(id, value); - } + LDRAW_OBJECT_HANDLE_SET_PROPERTY(Point0, {points[0] = value;}) + LDRAW_OBJECT_HANDLE_SET_PROPERTY(Point1, {points[1] = value;}) + LDRAW_OBJECT_HANDLE_SET_PROPERTY(Point2, {points[2] = value;}) + LDRAW_OBJECT_HANDLE_SET_PROPERTY(Point3, {points[3] = value;}) + ColoredObject::setProperty(result, pair); } QString ldraw::Quadrilateral::textRepresentation() const
--- a/src/linetypes/quadrilateral.h Wed Mar 18 17:11:23 2020 +0200 +++ b/src/linetypes/quadrilateral.h Thu Mar 19 21:06:06 2020 +0200 @@ -18,11 +18,12 @@ Color colorIndex = ldraw::mainColor); Quadrilateral(const std::array<glm::vec3, 4>& vertices, const Color color); QVariant getProperty(Property id) const override; - SetPropertyResult setProperty(Property id, const QVariant& value) override; QString textRepresentation() const override; void getPolygons(std::vector<gl::Polygon>& polygons, GetPolygonsContext* context) const override; void invert() override; int numPoints() const override; const glm::vec3& getPoint(int index) const override; glm::vec3 points[4] = {{}}; +protected: + void setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) override; };
--- a/src/linetypes/subfilereference.cpp Wed Mar 18 17:11:23 2020 +0200 +++ b/src/linetypes/subfilereference.cpp Thu Mar 19 21:06:06 2020 +0200 @@ -2,9 +2,12 @@ #include "documentmanager.h" #include "invert.h" -ldraw::SubfileReference::SubfileReference(const glm::mat4& transformation, +ldraw::SubfileReference::SubfileReference +( + const glm::mat4& transformation, const QString& referenceName, - const Color color) : + const Color color +) : ColoredObject{color}, transformation{transformation}, referenceName{referenceName} @@ -24,22 +27,11 @@ } } -auto ldraw::SubfileReference::setProperty( - Property property, - const QVariant& value) - -> SetPropertyResult +void ldraw::SubfileReference::setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) { - switch (property) - { - case Property::Transformation: - this->transformation = value.value<glm::mat4>(); - return SetPropertyResult::Success; - case Property::ReferenceName: - this->referenceName = value.toString(); - return SetPropertyResult::Success; - default: - return ColoredObject::setProperty(property, value); - } + LDRAW_OBJECT_HANDLE_SET_PROPERTY(Transformation, {this->transformation = value;}); + LDRAW_OBJECT_HANDLE_SET_PROPERTY(ReferenceName, {this->referenceName = value;}); + ldraw::ColoredObject::setProperty(result, pair); } QString ldraw::SubfileReference::textRepresentation() const @@ -47,9 +39,11 @@ return referenceName + " " + utility::vertexToStringParens(this->position()); } -void ldraw::SubfileReference::getPolygons( +void ldraw::SubfileReference::getPolygons +( std::vector<gl::Polygon>& polygons, - GetPolygonsContext* context) const + GetPolygonsContext* context +) const { Model* model = this->resolve(context->documents); if (model != nullptr)
--- a/src/linetypes/subfilereference.h Wed Mar 18 17:11:23 2020 +0200 +++ b/src/linetypes/subfilereference.h Thu Mar 19 21:06:06 2020 +0200 @@ -17,7 +17,6 @@ const QString &referenceName, const Color color = ldraw::mainColor); QVariant getProperty(Property property) const override; - SetPropertyResult setProperty(Property property, const QVariant& value) override; QString textRepresentation() const override; void getPolygons(std::vector<gl::Polygon>& polygons, GetPolygonsContext* context) const override; glm::vec3 position() const; @@ -26,4 +25,6 @@ glm::mat4 transformation; QString referenceName; bool isInverted = false; +protected: + void setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) override; };
--- a/src/linetypes/triangle.cpp Wed Mar 18 17:11:23 2020 +0200 +++ b/src/linetypes/triangle.cpp Thu Mar 19 21:06:06 2020 +0200 @@ -26,34 +26,23 @@ { switch (id) { + case Property::Point0: + return QVariant::fromValue(points[0]); case Property::Point1: - return QVariant::fromValue(points[0]); + return QVariant::fromValue(points[1]); case Property::Point2: - return QVariant::fromValue(points[1]); - case Property::Point3: return QVariant::fromValue(points[2]); default: return ColoredObject::getProperty(id); } } -auto ldraw::Triangle::setProperty(Property id, const QVariant& value) - -> SetPropertyResult +void ldraw::Triangle::setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) { - switch (id) - { - case Property::Point1: - points[0] = value.value<glm::vec3>(); - return SetPropertyResult::Success; - case Property::Point2: - points[1] = value.value<glm::vec3>(); - return SetPropertyResult::Success; - case Property::Point3: - points[2] = value.value<glm::vec3>(); - return SetPropertyResult::Success; - default: - return ColoredObject::setProperty(id, value); - } + LDRAW_OBJECT_HANDLE_SET_PROPERTY(Point0, {points[0] = value;}) + LDRAW_OBJECT_HANDLE_SET_PROPERTY(Point1, {points[1] = value;}) + LDRAW_OBJECT_HANDLE_SET_PROPERTY(Point2, {points[2] = value;}) + ColoredObject::setProperty(result, pair); } QString ldraw::Triangle::textRepresentation() const
--- a/src/linetypes/triangle.h Wed Mar 18 17:11:23 2020 +0200 +++ b/src/linetypes/triangle.h Thu Mar 19 21:06:06 2020 +0200 @@ -18,12 +18,13 @@ Triangle(const std::array<glm::vec3, 3>& vertices, const Color color); Triangle(const glm::vec3 (&vertices)[3], const Color color); QVariant getProperty(Property id) const override; - SetPropertyResult setProperty(Property id, const QVariant& value) override; QString textRepresentation() const override; void getPolygons(std::vector<gl::Polygon>& polygons, GetPolygonsContext* context) const override; void invert() override; int numPoints() const override; const glm::vec3& getPoint(int index) const override; glm::vec3 points[3] = {{}}; +protected: + void setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) override; };
--- a/src/model.cpp Wed Mar 18 17:11:23 2020 +0200 +++ b/src/model.cpp Thu Mar 19 21:06:06 2020 +0200 @@ -22,7 +22,10 @@ #include "modeleditcontext.h" Model::Model(QObject* parent) : - QAbstractListModel{parent} {} + QAbstractListModel{parent} +{ + connect(this, &Model::dataChanged, [&](){ this->needRecache = true; }); +} int Model::size() const {
--- a/src/modeleditcontext.cpp Wed Mar 18 17:11:23 2020 +0200 +++ b/src/modeleditcontext.cpp Thu Mar 19 21:06:06 2020 +0200 @@ -23,6 +23,15 @@ { } +Model::EditContext::~EditContext() +{ + for (ldraw::id_t id : this->modifiedObjects) + { + const QModelIndex index = this->model().lookup(id); + emit this->model().dataChanged(index, index); + } +} + ldraw::id_t Model::EditContext::append(std::unique_ptr<ldraw::Object>&& object) { const ldraw::id_t id = object->id; @@ -36,15 +45,13 @@ this->model().remove(position); } -void Model::EditContext::setObjectProperty( - ldraw::id_t id, - ldraw::Property property, - const QVariant& value) +void Model::EditContext::setObjectPoint(ldraw::id_t id, int pointId, const glm::vec3& value) { ldraw::Object* object = this->model().objectAt(id); if (object != nullptr) { - object->setProperty(property, value); + object->setProperty(ldraw::PropertyKeyValue{ldraw::pointProperty(pointId), QVariant::fromValue(value)}); + modifiedObjects.insert(id); } }
--- a/src/modeleditcontext.h Wed Mar 18 17:11:23 2020 +0200 +++ b/src/modeleditcontext.h Thu Mar 19 21:06:06 2020 +0200 @@ -25,21 +25,30 @@ class Model::EditContext { public: + ~EditContext(); template<typename T, typename... Args> ldraw::Id<T> append(Args&&... args); ldraw::id_t append(std::unique_ptr<ldraw::Object>&& object); template<typename T, typename... Args> ldraw::Id<T> insert(int position, Args&&... args); void remove(int position); - void setObjectProperty( - ldraw::id_t object, - ldraw::Property property, - const QVariant &value); + template<ldraw::Property property> + void setObjectProperty(ldraw::id_t id, const ldraw::PropertyType_t<property>& value) + { + ldraw::Object* object = this->model().objectAt(id); + if (object != nullptr) + { + object->setProperty<property>(value); + modifiedObjects.insert(id); + } + } + void setObjectPoint(ldraw::id_t id, int pointId, const glm::vec3& value); void invertObject(ldraw::id_t id); Model& model(); private: EditContext(Model& model); friend class Model; + QSet<ldraw::id_t> modifiedObjects; Model& storedModel; };
--- a/src/ui/polygonobjecteditor.cpp Wed Mar 18 17:11:23 2020 +0200 +++ b/src/ui/polygonobjecteditor.cpp Thu Mar 19 21:06:06 2020 +0200 @@ -1,8 +1,11 @@ #include <QVBoxLayout> #include <QSplitter> #include "model.h" +#include "modeleditcontext.h" #include "widgets/vec3editor.h" -#include "polygonobjecteditor.h" +#include "ui/polygonobjecteditor.h" + +constexpr char COLUMN_PROPERTY[] = "_ldforge_column"; PolygonObjectEditor::PolygonObjectEditor(Model* model, ldraw::id_t id, QWidget* parent) : QWidget{parent}, @@ -10,10 +13,13 @@ storedObjectId{ldraw::NULL_ID.value} { this->setLayout(new QVBoxLayout{this}); - for (std::optional<Vec3Editor>& editorPointer : this->vec3Editors) + for (int i = 0; i < countof(this->vec3Editors); i += 1) { + std::optional<Vec3Editor>& editorPointer = this->vec3Editors[i]; editorPointer.emplace(glm::vec3{}, this); + editorPointer->setProperty(COLUMN_PROPERTY, QVariant::fromValue(i)); this->layout()->addWidget(&*editorPointer); + connect(&*editorPointer, &Vec3Editor::valueChanged, this, &PolygonObjectEditor::vectorChanged); } this->layout()->addWidget(new QSplitter{Qt::Vertical, this}); this->setObjectId(id); @@ -35,6 +41,17 @@ this->updateNumRows(); } +void PolygonObjectEditor::vectorChanged(const glm::vec3& value) +{ + bool ok; + const int num = sender()->property(COLUMN_PROPERTY).toInt(&ok); + if (ok and num >= 0 and num < countof(this->vec3Editors)) + { + Model::EditContext editor = this->model->edit(); + editor.setObjectPoint(this->objectId(), num, value); + } +} + void PolygonObjectEditor::updateNumRows() { const ldraw::Object* object = model->get(this->storedObjectId); @@ -42,6 +59,7 @@ for (int i = 0; i < countof(this->vec3Editors); i += 1) { Vec3Editor& editor = *this->vec3Editors[i]; + QSignalBlocker blocker{&editor}; if (i < numPoints) { editor.setVisible(true);
--- a/src/ui/polygonobjecteditor.h Wed Mar 18 17:11:23 2020 +0200 +++ b/src/ui/polygonobjecteditor.h Thu Mar 19 21:06:06 2020 +0200 @@ -13,6 +13,7 @@ ldraw::id_t objectId() const; void setObjectId(ldraw::id_t id); private: + Q_SLOT void vectorChanged(const glm::vec3& value); void updateNumRows(); Model* model; ldraw::id_t storedObjectId;
--- a/src/widgets/vec3editor.cpp Wed Mar 18 17:11:23 2020 +0200 +++ b/src/widgets/vec3editor.cpp Thu Mar 19 21:06:06 2020 +0200 @@ -19,6 +19,13 @@ { connect(this->ui->multiply, &QPushButton::clicked, this, &Vec3Editor::multiplyPressed); } + for (QDoubleSpinBox* spinbox : this->spinboxes()) + { + connect(spinbox, qOverload<double>(&QDoubleSpinBox::valueChanged), [&](double) + { + Q_EMIT this->valueChanged(this->value()); + }); + } } Vec3Editor::~Vec3Editor()