Tue, 17 Mar 2020 23:13:29 +0200
object editor widgets start to form up
--- a/CMakeLists.txt Wed Mar 11 19:05:34 2020 +0200 +++ b/CMakeLists.txt Tue Mar 17 23:13:29 2020 +0200 @@ -54,7 +54,12 @@ src/settingseditor/settingseditor.cpp src/types/boundingbox.cpp src/ui/canvas.cpp + src/ui/multiplyfactordialog.cpp + src/ui/objecteditor.cpp + src/ui/polygonobjecteditor.cpp src/widgets/colorbutton.cpp + src/widgets/doublespinbox.cpp + src/widgets/vec3editor.cpp ) set (LDFORGE_HEADERS src/basics.h @@ -96,13 +101,20 @@ src/settingseditor/settingseditor.h src/types/boundingbox.h src/ui/canvas.h + src/ui/multiplyfactordialog.h + src/ui/objecteditor.h + src/ui/polygonobjecteditor.h src/widgets/colorbutton.h + src/widgets/doublespinbox.h + src/widgets/vec3editor.h ) set (LDFORGE_FORMS src/document.ui src/mainwindow.ui src/settingseditor/librarieseditor.ui src/settingseditor/settingseditor.ui + src/ui/multiplyfactordialog.ui + src/widgets/vec3editor.ui ) set(LDFORGE_LOCALES
--- a/locale/fi.ts Wed Mar 11 19:05:34 2020 +0200 +++ b/locale/fi.ts Tue Mar 17 23:13:29 2020 +0200 @@ -136,77 +136,105 @@ <translation>Näkymä</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="63"/> + <location filename="../src/mainwindow.ui" line="64"/> <source>Quit</source> <translation>Lopeta</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="68"/> + <location filename="../src/mainwindow.ui" line="69"/> <source>Open…</source> <translation>Avaa...</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="71"/> + <location filename="../src/mainwindow.ui" line="72"/> <source>Ctrl+O</source> <translation>Ctrl+O</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="76"/> + <location filename="../src/mainwindow.ui" line="77"/> <source>New</source> <translation>Uusi</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="79"/> + <location filename="../src/mainwindow.ui" line="80"/> <source>Ctrl+N</source> <translation>Ctrl+N</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="84"/> + <location filename="../src/mainwindow.ui" line="85"/> <source>Preferences…</source> <translation>Asetukset...</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="92"/> + <location filename="../src/mainwindow.ui" line="93"/> <source>Normal colours</source> <translation type="unfinished">Perusvärit</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="100"/> + <location filename="../src/mainwindow.ui" line="101"/> <source>BFC color coding</source> <translation type="unfinished">BFC-värikoodaus</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="108"/> + <location filename="../src/mainwindow.ui" line="109"/> <source>Random colours</source> <translation type="unfinished">Satunnaiset värit</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="97"/> + <location filename="../src/mainwindow.ui" line="117"/> + <source>Pick scene colours</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/mainwindow.cpp" line="98"/> <source>Open model</source> <translation>Avaa malli</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="99"/> + <location filename="../src/mainwindow.cpp" line="100"/> <source>LDraw models (*.ldr *.dat)</source> <translation>LDraw-mallit (*.ldr *.dat)</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="118"/> + <location filename="../src/mainwindow.cpp" line="119"/> <source>Problem loading references</source> <translation type="unfinished">Ongelma viitteiden lataamisessa</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="128"/> + <location filename="../src/mainwindow.cpp" line="129"/> <source>Problem opening file</source> <translation>Ongelma tiedoston avaamisessa</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="130"/> + <location filename="../src/mainwindow.cpp" line="131"/> <source>Could not open %1: %2</source> <translation>Ei voitu avata %1: %2</translation> </message> </context> <context> + <name>MultiplyFactorDialog</name> + <message> + <location filename="../src/ui/multiplyfactordialog.ui" line="14"/> + <source>Multiply with a scalar</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/ui/multiplyfactordialog.ui" line="24"/> + <source>Factor:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/ui/multiplyfactordialog.ui" line="34"/> + <source>Invert</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/ui/multiplyfactordialog.ui" line="43"/> + <source>Preview</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> <name>QObject</name> <message> <location filename="../src/gl/partrenderer.cpp" line="244"/> @@ -328,4 +356,32 @@ <translation>Näppäinyhdistelmät</translation> </message> </context> +<context> + <name>Vec3Editor</name> + <message> + <location filename="../src/widgets/vec3editor.ui" line="14"/> + <source>Form</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/widgets/vec3editor.ui" line="20"/> + <source>x = </source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/widgets/vec3editor.ui" line="36"/> + <source>y = </source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/widgets/vec3editor.ui" line="52"/> + <source>z = </source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/widgets/vec3editor.ui" line="68"/> + <source>×</source> + <translation type="unfinished"></translation> + </message> +</context> </TS>
--- a/locale/sv.ts Wed Mar 11 19:05:34 2020 +0200 +++ b/locale/sv.ts Tue Mar 17 23:13:29 2020 +0200 @@ -224,6 +224,29 @@ <source>Random colours</source> <translation>Slumpmässiga färger</translation> </message> + <message> + <source>Pick scene colours</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>MultiplyFactorDialog</name> + <message> + <source>Multiply with a scalar</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Factor:</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Invert</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Preview</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>PartRenderer</name> @@ -335,6 +358,29 @@ </message> </context> <context> + <name>Vec3Editor</name> + <message> + <source>Form</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>x = </source> + <translation type="unfinished"></translation> + </message> + <message> + <source>y = </source> + <translation type="unfinished"></translation> + </message> + <message> + <source>z = </source> + <translation type="unfinished"></translation> + </message> + <message> + <source>×</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> <name>gl::Compiler</name> <message> <source>Vertex shader:</source>
--- a/src/basics.h Wed Mar 11 19:05:34 2020 +0200 +++ b/src/basics.h Tue Mar 17 23:13:29 2020 +0200 @@ -129,6 +129,17 @@ return static_cast<double>(x); } +/** +* @brief casts floating point values to qreal, converting non-floating point values causes an error +* @param[in] x floating point value to cast +* @returns qreal +*/ +template<typename T> +auto toQreal(T x) -> std::enable_if_t<std::is_floating_point_v<T>, qreal> +{ + return static_cast<qreal>(x); +} + template<int N, typename T, glm::qualifier Q> inline QPoint toQPoint(const glm::vec<N, T, Q>& vec) {
--- a/src/document.cpp Wed Mar 11 19:05:34 2020 +0200 +++ b/src/document.cpp Tue Mar 17 23:13:29 2020 +0200 @@ -31,13 +31,15 @@ documents{documents}, colorTable{colorTable}, renderer{new Canvas{model, documents, colorTable, this}}, - ui{*new Ui::Document} + ui{*new Ui::Document}, + objectEditor{model, ldraw::NULL_ID, this} { this->ui.setupUi(this); this->ui.listView->setModel(model); - QVBoxLayout* layout = new QVBoxLayout; - layout->addWidget(this->renderer); - this->ui.viewportFrame->setLayout(layout); + this->ui.viewportFrame->setLayout(new QVBoxLayout{this->ui.listView}); + this->ui.viewportFrame->layout()->addWidget(this->renderer); + this->ui.objectEditorFrame->setLayout(new QVBoxLayout{this->ui.objectEditorFrame}); + this->ui.objectEditorFrame->layout()->addWidget(&this->objectEditor); this->setMouseTracking(true); connect(this->ui.splitter, &QSplitter::splitterMoved, this, &Document::splitterChanged); connect(this->renderer, &Canvas::newStatusText, this, &Document::newStatusText); @@ -53,7 +55,9 @@ selection.select(index, index); } } + QSignalBlocker blocker{this}; selectionModel->select(selection, QItemSelectionModel::ClearAndSelect); + this->selectionChanged(newSelection); }); connect(this->ui.listView->selectionModel(), &QItemSelectionModel::selectionChanged, [&](const QItemSelection& selected, const QItemSelection& deselected) @@ -64,6 +68,7 @@ return fn::map<QSet<ldraw::id_t>>(selection.indexes(), resolveIndex); }; this->renderer->handleSelectionChange(resolve(selected), resolve(deselected)); + this->selectionChanged(resolve(this->ui.listView->selectionModel()->selection())); }); } @@ -86,3 +91,15 @@ { this->renderer->setRenderPreferences(newPreferences); } + +void Document::selectionChanged(const QSet<ldraw::id_t>& newSelection) +{ + if (newSelection.size() == 1) + { + this->objectEditor.setObjectId(*newSelection.begin()); + } + else + { + this->objectEditor.setObjectId(ldraw::NULL_ID); + } +}
--- a/src/document.h Wed Mar 11 19:05:34 2020 +0200 +++ b/src/document.h Tue Mar 17 23:13:29 2020 +0200 @@ -20,6 +20,7 @@ #include <memory> #include <QWidget> #include "ui/canvas.h" +#include "ui/objecteditor.h" namespace Ui { @@ -45,9 +46,11 @@ void newStatusText(const QString& newStatusText); void splitterChanged(); private: + void selectionChanged(const QSet<ldraw::id_t>& newSelection); Model* model; DocumentManager* const documents; const ldraw::ColorTable& colorTable; Canvas* renderer; Ui::Document& ui; + ObjectEditor objectEditor; };
--- a/src/document.ui Wed Mar 11 19:05:34 2020 +0200 +++ b/src/document.ui Tue Mar 17 23:13:29 2020 +0200 @@ -19,6 +19,14 @@ <property name="orientation"> <enum>Qt::Horizontal</enum> </property> + <widget class="QFrame" name="viewportFrame"> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + </widget> <widget class="QListView" name="listView"> <property name="alternatingRowColors"> <bool>true</bool> @@ -30,7 +38,7 @@ <enum>QAbstractItemView::SelectRows</enum> </property> </widget> - <widget class="QFrame" name="viewportFrame"> + <widget class="QFrame" name="objectEditorFrame"> <property name="frameShape"> <enum>QFrame::StyledPanel</enum> </property>
--- a/src/linetypes/conditionaledge.cpp Wed Mar 11 19:05:34 2020 +0200 +++ b/src/linetypes/conditionaledge.cpp Tue Mar 17 23:13:29 2020 +0200 @@ -54,3 +54,21 @@ utility::vertexToStringParens(controlPoint_1), utility::vertexToStringParens(controlPoint_2)); } + +int ldraw::ConditionalEdge::numPoints() const +{ + return 4; +} + +const glm::vec3& ldraw::ConditionalEdge::getPoint(int index) const +{ + switch(index) + { + case 3: + return this->controlPoint_1; + case 4: + return this->controlPoint_2; + default: + return ldraw::Edge::getPoint(index); + } +}
--- a/src/linetypes/conditionaledge.h Wed Mar 11 19:05:34 2020 +0200 +++ b/src/linetypes/conditionaledge.h Tue Mar 17 23:13:29 2020 +0200 @@ -22,6 +22,8 @@ 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 = {}; };
--- a/src/linetypes/edge.cpp Wed Mar 11 19:05:34 2020 +0200 +++ b/src/linetypes/edge.cpp Tue Mar 17 23:13:29 2020 +0200 @@ -56,3 +56,21 @@ Q_UNUSED(context) polygons.push_back(gl::edgeLine(this->point_1, this->point_2, this->colorIndex, this->id)); } + +int ldraw::Edge::numPoints() const +{ + return 2; +} + +const glm::vec3& ldraw::Edge::getPoint(int index) const +{ + switch (index) + { + case 0: + return this->point_1; + case 1: + return this->point_2; + default: + return ldraw::ColoredObject::getPoint(index); + } +}
--- a/src/linetypes/edge.h Wed Mar 11 19:05:34 2020 +0200 +++ b/src/linetypes/edge.h Tue Mar 17 23:13:29 2020 +0200 @@ -20,6 +20,8 @@ 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 = {}; };
--- a/src/linetypes/object.cpp Wed Mar 11 19:05:34 2020 +0200 +++ b/src/linetypes/object.cpp Tue Mar 17 23:13:29 2020 +0200 @@ -58,6 +58,11 @@ Q_UNUSED(context) } +const glm::vec3& ldraw::Object::getPoint(int index) const +{ + throw BadPointIndex{}; +} + ldraw::ColoredObject::ColoredObject(const Color color_index) : colorIndex{color_index} {
--- a/src/linetypes/object.h Wed Mar 11 19:05:34 2020 +0200 +++ b/src/linetypes/object.h Tue Mar 17 23:13:29 2020 +0200 @@ -81,6 +81,9 @@ PropertyNotHandled, InvalidValue }; + class BadPointIndex : public std::exception + { + }; Object(); Object(const Object&) = delete; virtual ~Object(); @@ -95,6 +98,8 @@ 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; }; class ldraw::ColoredObject : public Object
--- a/src/linetypes/quadrilateral.cpp Wed Mar 11 19:05:34 2020 +0200 +++ b/src/linetypes/quadrilateral.cpp Tue Mar 17 23:13:29 2020 +0200 @@ -87,3 +87,20 @@ // -> 2 1 0 3 std::swap(this->points[0], this->points[2]); } + +int ldraw::Quadrilateral::numPoints() const +{ + return 4; +} + +const glm::vec3& ldraw::Quadrilateral::getPoint(int index) const +{ + if (index >= 0 and index < 4) + { + return points[index]; + } + else + { + return ldraw::ColoredObject::getPoint(index); + } +}
--- a/src/linetypes/quadrilateral.h Wed Mar 11 19:05:34 2020 +0200 +++ b/src/linetypes/quadrilateral.h Tue Mar 17 23:13:29 2020 +0200 @@ -22,5 +22,7 @@ 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] = {{}}; };
--- a/src/linetypes/subfilereference.cpp Wed Mar 11 19:05:34 2020 +0200 +++ b/src/linetypes/subfilereference.cpp Tue Mar 17 23:13:29 2020 +0200 @@ -81,7 +81,7 @@ glm::vec3 ldraw::SubfileReference::position() const { - return {this->transformation[3][0], this->transformation[3][1], this->transformation[3][2]}; + return this->transformation[3]; } void ldraw::SubfileReference::invert()
--- a/src/linetypes/triangle.cpp Wed Mar 11 19:05:34 2020 +0200 +++ b/src/linetypes/triangle.cpp Tue Mar 17 23:13:29 2020 +0200 @@ -83,3 +83,20 @@ // -> 1 0 2 std::swap(this->points[0], this->points[1]); } + +int ldraw::Triangle::numPoints() const +{ + return 3; +} + +const glm::vec3& ldraw::Triangle::getPoint(int index) const +{ + if (index >= 0 and index < 3) + { + return this->points[index]; + } + else + { + return ldraw::ColoredObject::getPoint(index); + } +}
--- a/src/linetypes/triangle.h Wed Mar 11 19:05:34 2020 +0200 +++ b/src/linetypes/triangle.h Tue Mar 17 23:13:29 2020 +0200 @@ -22,6 +22,8 @@ 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] = {{}}; };
--- a/src/main.h Wed Mar 11 19:05:34 2020 +0200 +++ b/src/main.h Tue Mar 17 23:13:29 2020 +0200 @@ -74,13 +74,14 @@ using conditionaledgeid_t = Id<class ConditionalEdge>; using subfileid_t = Id<class SubfileReference>; - constexpr struct + constexpr struct NullId { template<typename T> constexpr operator Id<T>() const { return Id<T>{0}; } + static constexpr decltype(ldraw::id_t::value) value = 0; } NULL_ID = {}; template<typename T>
--- a/src/model.h Wed Mar 11 19:05:34 2020 +0200 +++ b/src/model.h Tue Mar 17 23:13:29 2020 +0200 @@ -135,5 +135,12 @@ { *index_out = index; } - return static_cast<const R*>(this->objectAt(index)); + if (index.isValid()) + { + return static_cast<const R*>(this->objectAt(index)); + } + else + { + return nullptr; + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ui/multiplyfactordialog.cpp Tue Mar 17 23:13:29 2020 +0200 @@ -0,0 +1,39 @@ +#include "multiplyfactordialog.h" +#include "ui_multiplyfactordialog.h" + +MultiplyFactorDialog::MultiplyFactorDialog(const glm::vec3& baseVector, QWidget* parent) : + QDialog{parent}, + baseVector{baseVector}, + preview{baseVector, parent, Vec3Editor::NoMultiplyButton} +{ + ui = std::make_unique<Ui::MultiplyFactorDialog>(); + ui->setupUi(this); + this->preview.setEnabled(false); + this->ui->previewGroupBox->setLayout(new QVBoxLayout{parent}); + this->ui->previewGroupBox->layout()->addWidget(&this->preview); + connect(this->ui->invert, &QCheckBox::clicked, this, &MultiplyFactorDialog::updatePreview); + connect(this->ui->factor, qOverload<double>(&DoubleSpinBox::valueChanged), this, &MultiplyFactorDialog::updatePreview); +} + +MultiplyFactorDialog::~MultiplyFactorDialog() +{ +} + +glm::vec3 MultiplyFactorDialog::value() const +{ + glm::vec3 result = baseVector; + if (this->ui->invert->isChecked()) + { + result /= this->ui->factor->value(); + } + else + { + result *= this->ui->factor->value(); + } + return result; +} + +void MultiplyFactorDialog::updatePreview() +{ + this->preview.setValue(this->value()); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ui/multiplyfactordialog.h Tue Mar 17 23:13:29 2020 +0200 @@ -0,0 +1,23 @@ +#pragma once +#include <QDialog> +#include "../main.h" +#include "../widgets/vec3editor.h" + +namespace Ui +{ + class MultiplyFactorDialog; +} + +class MultiplyFactorDialog : public QDialog +{ + Q_OBJECT +public: + explicit MultiplyFactorDialog(const glm::vec3& baseVector = glm::vec3{}, QWidget *parent = nullptr); + ~MultiplyFactorDialog(); + glm::vec3 value() const; +private: + Q_SLOT void updatePreview(); + std::unique_ptr<Ui::MultiplyFactorDialog> ui; + const glm::vec3 baseVector; + Vec3Editor preview; +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ui/multiplyfactordialog.ui Tue Mar 17 23:13:29 2020 +0200 @@ -0,0 +1,103 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MultiplyFactorDialog</class> + <widget class="QDialog" name="MultiplyFactorDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>436</width> + <height>128</height> + </rect> + </property> + <property name="windowTitle"> + <string>Multiply with a scalar</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1"> + <item> + <layout class="QFormLayout" name="formLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Factor:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="DoubleSpinBox" name="factor"/> + </item> + <item row="1" column="1"> + <widget class="QCheckBox" name="invert"> + <property name="text"> + <string>Invert</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QGroupBox" name="previewGroupBox"> + <property name="title"> + <string>Preview</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>DoubleSpinBox</class> + <extends>QDoubleSpinBox</extends> + <header>widgets/doublespinbox.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>MultiplyFactorDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>MultiplyFactorDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ui/objecteditor.cpp Tue Mar 17 23:13:29 2020 +0200 @@ -0,0 +1,32 @@ +#include <QVBoxLayout> +#include "objecteditor.h" + +ObjectEditor::ObjectEditor(Model* model, const ldraw::id_t id, QWidget *parent) : + QWidget{parent}, + model{model} +{ + this->setObjectId(id); + this->setLayout(new QVBoxLayout{this}); +} + +void ObjectEditor::setObjectId(const ldraw::id_t id) +{ + this->objectId = id; + const ldraw::Object* object = this->model->get(id); + if (object != nullptr and object->numPoints() > 0) + { + if (not this->polygonEditor.has_value()) + { + this->polygonEditor.emplace(this->model, id); + this->layout()->addWidget(&*this->polygonEditor); + } + else + { + this->polygonEditor->setObjectId(id); + } + } + else + { + this->polygonEditor.reset(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ui/objecteditor.h Tue Mar 17 23:13:29 2020 +0200 @@ -0,0 +1,17 @@ +#pragma once +#include <QWidget> +#include "../main.h" +#include "../model.h" +#include "polygonobjecteditor.h" + +class ObjectEditor : public QWidget +{ + Q_OBJECT +public: + explicit ObjectEditor(Model* model, ldraw::id_t id = ldraw::NULL_ID, QWidget* parent = nullptr); + void setObjectId(ldraw::id_t id); +private: + Model* const model; + ldraw::id_t objectId = ldraw::NULL_ID; + std::optional<PolygonObjectEditor> polygonEditor; +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ui/polygonobjecteditor.cpp Tue Mar 17 23:13:29 2020 +0200 @@ -0,0 +1,48 @@ +#include <QVBoxLayout> +#include "model.h" +#include "widgets/vec3editor.h" +#include "polygonobjecteditor.h" + +PolygonObjectEditor::PolygonObjectEditor(Model* model, ldraw::id_t id, QWidget* parent) : + QWidget{parent}, + model{model}, + storedObjectId{ldraw::NULL_ID.value} +{ + this->setLayout(new QVBoxLayout{this}); + this->setObjectId(id); +} + +// destructor needed for std::unique_ptr +PolygonObjectEditor::~PolygonObjectEditor() +{ +} + +ldraw::id_t PolygonObjectEditor::objectId() const +{ + return this->storedObjectId; +} + +void PolygonObjectEditor::setObjectId(ldraw::id_t id) +{ + this->storedObjectId = id; + this->updateNumRows(); +} + +void PolygonObjectEditor::updateNumRows() +{ + const ldraw::Object* object = model->get(this->storedObjectId); + const int number = object->numPoints(); + if (static_cast<int>(this->vec3Editors.size()) > number) + { + this->vec3Editors.resize(number); + } + else + { + while (static_cast<int>(this->vec3Editors.size()) < number) + { + const glm::vec3& value = object->getPoint(this->vec3Editors.size()); + this->vec3Editors.emplace_back(std::make_unique<Vec3Editor>(value, this)); + this->layout()->addWidget(this->vec3Editors.back().get()); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ui/polygonobjecteditor.h Tue Mar 17 23:13:29 2020 +0200 @@ -0,0 +1,19 @@ +#pragma once +#include <QWidget> +#include "main.h" + +class Model; + +class PolygonObjectEditor : public QWidget +{ +public: + PolygonObjectEditor(Model* model, ldraw::id_t id, QWidget* parent = nullptr); + ~PolygonObjectEditor(); + ldraw::id_t objectId() const; + void setObjectId(ldraw::id_t id); +private: + void updateNumRows(); + Model* model; + ldraw::id_t storedObjectId; + std::vector<std::unique_ptr<class Vec3Editor>> vec3Editors; +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/widgets/vec3editor.cpp Tue Mar 17 23:13:29 2020 +0200 @@ -0,0 +1,60 @@ +#include <QDialog> +#include <QCheckBox> +#include <QSignalBlocker> +#include "vec3editor.h" +#include "ui_vec3editor.h" +#include "../ui/multiplyfactordialog.h" + +Vec3Editor::Vec3Editor(const glm::vec3& value, QWidget *parent, QFlags<Flag> flags) : + QWidget{parent}, + ui{new Ui::Vec3Editor} +{ + this->ui->setupUi(this); + this->setValue(value); + if (flags.testFlag(NoMultiplyButton)) + { + this->ui->multiply->setVisible(false); + } + else + { + connect(this->ui->multiply, &QPushButton::clicked, this, &Vec3Editor::multiplyPressed); + } +} + +Vec3Editor::~Vec3Editor() +{ +} + +glm::vec3 Vec3Editor::value() const +{ + auto get = [](DoubleSpinBox* spinbox){ return toFloat(spinbox->value()); }; + return {get(this->ui->x), get(this->ui->y), get(this->ui->z)}; +} + +void Vec3Editor::setValue(const glm::vec3& value) +{ + auto set = [](DoubleSpinBox* spinbox, float value) + { + QSignalBlocker blocker{spinbox}; + spinbox->setValue(toQreal(value)); + }; + set(this->ui->x, value.x); + set(this->ui->y, value.y); + set(this->ui->z, value.z); + Q_EMIT this->valueChanged(value); +} + +std::array<DoubleSpinBox*, 3> Vec3Editor::spinboxes() +{ + return {this->ui->x, this->ui->y, this->ui->z}; +} + +void Vec3Editor::multiplyPressed() +{ + MultiplyFactorDialog dialog{this->value(), this}; + const int dialogResult = dialog.exec(); + if (dialogResult == QDialog::Accepted) + { + this->setValue(dialog.value()); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/widgets/vec3editor.h Tue Mar 17 23:13:29 2020 +0200 @@ -0,0 +1,30 @@ +#pragma once +#include <QWidget> +#include "main.h" + +namespace Ui +{ + class Vec3Editor; +} + +class Vec3Editor : public QWidget +{ + Q_OBJECT +public: + enum Flag + { + NoMultiplyButton = 0x1 + }; + explicit Vec3Editor(const glm::vec3& value = {}, QWidget* parent = nullptr, QFlags<Flag> flags = 0); + ~Vec3Editor(); + glm::vec3 value() const; + void setValue(const glm::vec3& value); +Q_SIGNALS: + void valueChanged(const glm::vec3& value); +private: + std::array<class DoubleSpinBox*, 3> spinboxes(); + Q_SLOT void multiplyPressed(); + std::unique_ptr<Ui::Vec3Editor> ui; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QFlags<Vec3Editor::Flag>)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/widgets/vec3editor.ui Tue Mar 17 23:13:29 2020 +0200 @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Vec3Editor</class> + <widget class="QWidget" name="Vec3Editor"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>613</width> + <height>46</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1,1,0"> + <item> + <widget class="DoubleSpinBox" name="x"> + <property name="prefix"> + <string>x = </string> + </property> + <property name="decimals"> + <number>4</number> + </property> + <property name="minimum"> + <double>-1000000.000000000000000</double> + </property> + <property name="maximum"> + <double>1000000.000000000000000</double> + </property> + </widget> + </item> + <item> + <widget class="DoubleSpinBox" name="y"> + <property name="prefix"> + <string>y = </string> + </property> + <property name="decimals"> + <number>4</number> + </property> + <property name="minimum"> + <double>-1000000.000000000000000</double> + </property> + <property name="maximum"> + <double>1000000.000000000000000</double> + </property> + </widget> + </item> + <item> + <widget class="DoubleSpinBox" name="z"> + <property name="prefix"> + <string>z = </string> + </property> + <property name="decimals"> + <number>4</number> + </property> + <property name="minimum"> + <double>-1000000.000000000000000</double> + </property> + <property name="maximum"> + <double>1000000.000000000000000</double> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="multiply"> + <property name="text"> + <string>×</string> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>DoubleSpinBox</class> + <extends>QDoubleSpinBox</extends> + <header>widgets/doublespinbox.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui>