# HG changeset patch # User Teemu Piippo # Date 1524835634 -10800 # Node ID 2f18c0da749db306e2bef9effc32ed30a847a351 # Parent 4c134708be050bdf3a29701235e4ce20d844a7e2 added vertex rendering diff -r 4c134708be05 -r 2f18c0da749d CMakeLists.txt --- a/CMakeLists.txt Wed Apr 25 18:55:15 2018 +0300 +++ b/CMakeLists.txt Fri Apr 27 16:27:14 2018 +0300 @@ -58,6 +58,8 @@ src/serializer.cpp src/ringFinder.cpp src/version.cpp + src/vertexcompiler.cpp + src/vertexselection.cpp src/algorithms/geometry.cpp src/algorithms/invert.cpp src/dialogs/colorselector.cpp @@ -127,6 +129,8 @@ src/ringFinder.h src/serializer.h src/version.h + src/vertexcompiler.h + src/vertexselection.h src/algorithms/geometry.h src/algorithms/invert.h src/dialogs/colorselector.h diff -r 4c134708be05 -r 2f18c0da749d src/canvas.cpp --- a/src/canvas.cpp Wed Apr 25 18:55:15 2018 +0300 +++ b/src/canvas.cpp Fri Apr 27 16:27:14 2018 +0300 @@ -21,16 +21,19 @@ #include "grid.h" #include "lddocument.h" #include "primitives.h" +#include "vertexcompiler.h" #include "algorithms/geometry.h" #include "generics/ring.h" Canvas::Canvas(LDDocument* document, QWidget* parent) : GLRenderer {document, parent}, m_document {*document}, + m_vertexCompiler {new VertexCompiler {document, nullptr, this}}, m_currentEditMode {AbstractEditMode::createByType (this, EditModeType::Select)} {} Canvas::~Canvas() { + delete this->m_vertexCompiler; delete m_currentEditMode; } @@ -61,6 +64,36 @@ } } +void Canvas::initializeGL() +{ + GLRenderer::initializeGL(); + this->m_vertexCompiler->initialize(); +} + +void Canvas::drawScene() +{ + GLRenderer::drawScene(); + + if (not isDrawingSelectionScene()) + { + GLuint surfacesVbo = this->m_vertexCompiler->vbo(VertexCompiler::Surfaces); + GLuint colorsVbo = this->m_vertexCompiler->vbo(VertexCompiler::Colors); + GLuint normalsVbo = this->m_vertexCompiler->vbo(VertexCompiler::Normals); + GLsizei count = this->m_vertexCompiler->vboSize(VertexCompiler::Surfaces) / 3; + + if (count > 0) + { + glBindBuffer(GL_ARRAY_BUFFER, surfacesVbo); + glVertexPointer(3, GL_FLOAT, 0, nullptr); + glBindBuffer(GL_ARRAY_BUFFER, colorsVbo); + glColorPointer(4, GL_FLOAT, 0, nullptr); + glBindBuffer(GL_ARRAY_BUFFER, normalsVbo); + glNormalPointer(GL_FLOAT, 0, nullptr); + glDrawArrays(GL_TRIANGLES, 0, count); + } + } +} + /* * Assuming we're currently viewing from a fixed camera, draw a backdrop into it. Currently this means drawing the grid. */ diff -r 4c134708be05 -r 2f18c0da749d src/canvas.h --- a/src/canvas.h Wed Apr 25 18:55:15 2018 +0300 +++ b/src/canvas.h Fri Apr 27 16:27:14 2018 +0300 @@ -47,8 +47,10 @@ void contextMenuEvent(QContextMenuEvent* event) override; void dragEnterEvent(QDragEnterEvent* event) override; void drawFixedCameraBackdrop() override; + void drawScene() override; void dropEvent(QDropEvent* event) override; bool freeCameraAllowed() const override; + void initializeGL() override; void keyReleaseEvent(QKeyEvent* event) override; void mouseDoubleClickEvent(QMouseEvent* event) override; void mouseMoveEvent(QMouseEvent* event) override; @@ -58,6 +60,7 @@ private: LDDocument& m_document; + class VertexCompiler* m_vertexCompiler; AbstractEditMode* m_currentEditMode = nullptr; Vertex m_position3D; double m_depthValues[6] = {0}; diff -r 4c134708be05 -r 2f18c0da749d src/editmodes/selectMode.cpp --- a/src/editmodes/selectMode.cpp Wed Apr 25 18:55:15 2018 +0300 +++ b/src/editmodes/selectMode.cpp Fri Apr 27 16:27:14 2018 +0300 @@ -103,6 +103,7 @@ else mode = QItemSelectionModel::ClearAndSelect; +#warning fix crash here model->select(renderer()->pick(area), mode); } diff -r 4c134708be05 -r 2f18c0da749d src/glShared.h --- a/src/glShared.h Wed Apr 25 18:55:15 2018 +0300 +++ b/src/glShared.h Fri Apr 27 16:27:14 2018 +0300 @@ -78,6 +78,7 @@ BfcFrontColors, BfcBackColors, RandomColors, + BlackColors, Normals, InvertedNormals, _End diff -r 4c134708be05 -r 2f18c0da749d src/glcompiler.cpp --- a/src/glcompiler.cpp Wed Apr 25 18:55:15 2018 +0300 +++ b/src/glcompiler.cpp Fri Apr 27 16:27:14 2018 +0300 @@ -168,6 +168,10 @@ // Use the constant red color for BFC back colors return {208, 64, 64}; + case VboSubclass::BlackColors: + // Use a constant black color for black colors. + return Qt::black; + case VboSubclass::PickColors: // For the picking scene, use unique picking colors provided by the model. return m_renderer->model()->pickingColorForObject(polygonOwnerIndex); diff -r 4c134708be05 -r 2f18c0da749d src/glcompiler.h --- a/src/glcompiler.h Wed Apr 25 18:55:15 2018 +0300 +++ b/src/glcompiler.h Fri Apr 27 16:27:14 2018 +0300 @@ -67,7 +67,7 @@ Q_SLOT void compileObject (const QModelIndex &index); QColor getColorForPolygon( LDPolygon& poly, - const QModelIndex& polygonOwnerIndex, + const QModelIndex& polygonOwnereIndex, VboSubclass complement ); QColor indexColorForID (qint32 id) const; diff -r 4c134708be05 -r 2f18c0da749d src/glrenderer.cpp --- a/src/glrenderer.cpp Wed Apr 25 18:55:15 2018 +0300 +++ b/src/glrenderer.cpp Fri Apr 27 16:27:14 2018 +0300 @@ -356,6 +356,68 @@ camera.rendererResized(width, height); } +void GLRenderer::drawSelectionScene(VboSubclass subclass) +{ + this->drawVbos(VboClass::Triangles, subclass); + this->drawVbos(VboClass::Quads, subclass); + this->drawVbos(VboClass::Lines, subclass); + this->drawVbos(VboClass::ConditionalLines, subclass); +} + +void GLRenderer::drawScene() +{ + if (m_isDrawingSelectionScene) + { + this->drawSelectionScene(); + } + else + { + if (config::bfcRedGreenView()) + { + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + drawVbos(VboClass::Triangles, VboSubclass::BfcFrontColors); + drawVbos(VboClass::Quads, VboSubclass::BfcFrontColors); + glCullFace(GL_FRONT); + drawVbos(VboClass::Triangles, VboSubclass::BfcBackColors); + drawVbos(VboClass::Quads, VboSubclass::BfcBackColors); + glDisable(GL_CULL_FACE); + } + else + { + VboSubclass colors; + + if (config::randomColors()) + colors = VboSubclass::RandomColors; + else + colors = VboSubclass::RegularColors; + + drawVbos(VboClass::Triangles, colors); + drawVbos(VboClass::Quads, colors); + } + + drawVbos(VboClass::Lines, VboSubclass::RegularColors); + + if (config::useLineStipple()) + glEnable(GL_LINE_STIPPLE); + + drawVbos(VboClass::ConditionalLines, VboSubclass::RegularColors); + glDisable(GL_LINE_STIPPLE); + + if (config::drawAxes()) + { + glDisableClientState(GL_NORMAL_ARRAY); + glBindBuffer(GL_ARRAY_BUFFER, m_axesVbo); + glVertexPointer(3, GL_FLOAT, 0, NULL); + glBindBuffer(GL_ARRAY_BUFFER, m_axesVbo); + glColorPointer(3, GL_FLOAT, 0, NULL); + glDrawArrays(GL_LINES, 0, 6); + glEnableClientState(GL_NORMAL_ARRAY); + CHECK_GL_ERROR(); + } + } +} + // ============================================================================= // void GLRenderer::drawGLScene() @@ -400,61 +462,7 @@ glEnableClientState (GL_NORMAL_ARRAY); glEnableClientState (GL_VERTEX_ARRAY); glEnableClientState (GL_COLOR_ARRAY); - - if (m_isDrawingSelectionScene) - { - drawVbos (VboClass::Triangles, VboSubclass::PickColors); - drawVbos (VboClass::Quads, VboSubclass::PickColors); - drawVbos (VboClass::Lines, VboSubclass::PickColors); - drawVbos (VboClass::ConditionalLines, VboSubclass::PickColors); - } - else - { - if (config::bfcRedGreenView()) - { - glEnable (GL_CULL_FACE); - glCullFace (GL_BACK); - drawVbos (VboClass::Triangles, VboSubclass::BfcFrontColors); - drawVbos (VboClass::Quads, VboSubclass::BfcFrontColors); - glCullFace (GL_FRONT); - drawVbos (VboClass::Triangles, VboSubclass::BfcBackColors); - drawVbos (VboClass::Quads, VboSubclass::BfcBackColors); - glDisable (GL_CULL_FACE); - } - else - { - VboSubclass colors; - - if (config::randomColors()) - colors = VboSubclass::RandomColors; - else - colors = VboSubclass::RegularColors; - - drawVbos (VboClass::Triangles, colors); - drawVbos (VboClass::Quads, colors); - } - - drawVbos (VboClass::Lines, VboSubclass::RegularColors); - - if (config::useLineStipple()) - glEnable (GL_LINE_STIPPLE); - - drawVbos (VboClass::ConditionalLines, VboSubclass::RegularColors); - glDisable (GL_LINE_STIPPLE); - - if (config::drawAxes()) - { - glDisableClientState (GL_NORMAL_ARRAY); - glBindBuffer (GL_ARRAY_BUFFER, m_axesVbo); - glVertexPointer (3, GL_FLOAT, 0, NULL); - glBindBuffer (GL_ARRAY_BUFFER, m_axesVbo); - glColorPointer (3, GL_FLOAT, 0, NULL); - glDrawArrays (GL_LINES, 0, 6); - glEnableClientState (GL_NORMAL_ARRAY); - CHECK_GL_ERROR(); - } - } - + this->drawScene(); glPopMatrix(); glBindBuffer (GL_ARRAY_BUFFER, 0); glDisableClientState (GL_VERTEX_ARRAY); diff -r 4c134708be05 -r 2f18c0da749d src/glrenderer.h --- a/src/glrenderer.h Wed Apr 25 18:55:15 2018 +0300 +++ b/src/glrenderer.h Fri Apr 27 16:27:14 2018 +0300 @@ -107,6 +107,8 @@ QColor backgroundColor() const; virtual bool freeCameraAllowed() const; + virtual void drawScene(); + void drawSelectionScene(VboSubclass subclass = VboSubclass::PickColors); bool isDrawingSelectionScene() const; Qt::MouseButtons lastButtons() const; bool mouseHasMoved() const; diff -r 4c134708be05 -r 2f18c0da749d src/linetypes/modelobject.h --- a/src/linetypes/modelobject.h Wed Apr 25 18:55:15 2018 +0300 +++ b/src/linetypes/modelobject.h Fri Apr 27 16:27:14 2018 +0300 @@ -89,6 +89,7 @@ static LDObject* newFromType(LDObjectType type); signals: + void aboutToBeModified(); void modified(const LDObjectState& before, const LDObjectState& after); protected: @@ -233,6 +234,7 @@ if (*property != value) { Serializer::Archive before = Serializer::store(this); + emit aboutToBeModified(); *property = value; emit modified(before, Serializer::store(this)); } diff -r 4c134708be05 -r 2f18c0da749d src/vertexcompiler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/vertexcompiler.cpp Fri Apr 27 16:27:14 2018 +0300 @@ -0,0 +1,267 @@ +/* + * LDForge: LDraw parts authoring CAD + * Copyright (C) 2013 - 2018 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 . + */ + +#include "vertexcompiler.h" +#include "vertexselection.h" +#include "model.h" + +static const Vertex sphere[] = { + {1, 0, 0}, {0.7071, 0.7071, 0}, {0.7071, 0, 0.7071}, + {0, 0.7071, 0.7071}, {0, 0, 1}, {0.7071, 0, 0.7071}, + {0.7071, 0.7071, 0}, {0, 0.7071, 0.7071}, {0.7071, 0, 0.7071}, + {0, 1, 0}, {0, 0.7071, 0.7071}, {0.7071, 0.7071, 0}, + {0.7071, 0, -0.7071}, {0.7071, 0.7071, 0}, {1, 0, 0}, + {0.7071, 0, -0.7071}, {0, 0, -1}, {0, 0.7071, -0.7071}, + {0.7071, 0, -0.7071}, {0, 0.7071, -0.7071}, {0.7071, 0.7071, 0}, + {0.7071, 0.7071, 0}, {0, 0.7071, -0.7071}, {0, 1, 0}, + {-0.7071, 0, 0.7071}, {-0.7071, 0.7071, 0}, {-1, 0, 0}, + {-0.7071, 0, 0.7071}, {0, 0, 1}, {0, 0.7071, 0.7071}, + {-0.7071, 0, 0.7071}, {0, 0.7071, 0.7071}, {-0.7071, 0.7071, 0}, + {-0.7071, 0.7071, 0}, {0, 0.7071, 0.7071}, {0, 1, 0}, + {-1, 0, 0}, {-0.7071, 0.7071, 0}, {-0.7071, 0, -0.7071}, + {0, 0.7071, -0.7071}, {0, 0, -1}, {-0.7071, 0, -0.7071}, + {-0.7071, 0.7071, 0}, {0, 0.7071, -0.7071}, {-0.7071, 0, -0.7071}, + {0, 1, 0}, {0, 0.7071, -0.7071}, {-0.7071, 0.7071, 0}, + {-0.7071, 0, -0.7071}, {0, 0, -1}, {0, -0.7071, -0.7071}, + {0, -1, 0}, {0, -0.7071, 0.7071}, {-0.7071, -0.7071, 0}, + {0.7071, -0.7071, 0}, {0, -0.7071, -0.7071}, {0.7071, 0, -0.7071}, + {-1, 0, 0}, {-0.7071, -0.7071, 0}, {-0.7071, 0, 0.7071}, + {-0.7071, -0.7071, 0}, {0, -0.7071, -0.7071}, {0, -1, 0}, + {0, -1, 0}, {0, -0.7071, -0.7071}, {0.7071, -0.7071, 0}, + {0.7071, 0, 0.7071}, {0, -0.7071, 0.7071}, {0.7071, -0.7071, 0}, + {-0.7071, 0, -0.7071}, {-0.7071, -0.7071, 0}, {-1, 0, 0}, + {1, 0, 0}, {0.7071, -0.7071, 0}, {0.7071, 0, -0.7071}, + {0.7071, 0, 0.7071}, {0, 0, 1}, {0, -0.7071, 0.7071}, + {-0.7071, 0, -0.7071}, {0, -0.7071, -0.7071}, {-0.7071, -0.7071, 0}, + {0.7071, -0.7071, 0}, {0, -0.7071, 0.7071}, {0, -1, 0}, + {0.7071, 0, 0.7071}, {0.7071, -0.7071, 0}, {1, 0, 0}, + {-0.7071, -0.7071, 0}, {0, -0.7071, 0.7071}, {-0.7071, 0, 0.7071}, + {0, -0.7071, -0.7071}, {0, 0, -1}, {0.7071, 0, -0.7071}, + {0, -0.7071, 0.7071}, {0, 0, 1}, {-0.7071, 0, 0.7071}, +}; + +static const float sphereSize = 0.5; +static const QColor sphereColor {192, 192, 255}; + +VertexCompiler::VertexCompiler(Model* model, VertexSelection* selection, QObject* parent) : + QObject {parent}, + model {model} +{ + connect(model, &Model::objectAdded, this, &VertexCompiler::handleNewObject); + connect(model, &Model::aboutToRemoveObject, this, &VertexCompiler::handleRemovedObject); + + if (selection != nullptr) + { + this->connect( + selection, + &VertexSelection::vertexSelected, + this, + &VertexCompiler::updateVertex + ); + this->connect( + selection, + &VertexSelection::vertexDeselected, + this, + &VertexCompiler::updateVertex + ); + } +} + +VertexCompiler::~VertexCompiler() +{ + if (this->initialized) + { + GLuint buffers[NumVbos]; + + for (int i = 0; i < countof(this->vbos); i += 1) + buffers[i] = this->vbos[i].buffer; + + this->glDeleteBuffers(countof(buffers), &buffers[0]); + } +} + +void VertexCompiler::handleNewObject(const QModelIndex &index) +{ + LDObject* object = this->model->lookup(index); + this->addVerticesFromObject(object); + connect(object, &LDObject::aboutToBeModified, this, &VertexCompiler::handlePreModifiedObject); + connect(object, &LDObject::modified, this, &VertexCompiler::handleModifiedObject); +} + +void VertexCompiler::handleRemovedObject(const QModelIndex &index) +{ + LDObject* object = this->model->lookup(index); + this->removeVerticesFromObject(object); +} + +void VertexCompiler::handlePreModifiedObject() +{ + removeVerticesFromObject(qobject_cast(this->sender())); +} + +void VertexCompiler::handleModifiedObject() +{ + addVerticesFromObject(qobject_cast(this->sender())); +} + +void VertexCompiler::initialize() +{ + if (not this->initialized) + { + this->initializeOpenGLFunctions(); + this->initialized = true; + GLuint buffers[NumVbos]; + this->glGenBuffers(countof(buffers), &buffers[0]); + + for (int i = 0; i < countof(this->vbos); i += 1) + this->vbos[i].buffer = buffers[i]; + } +} + +void VertexCompiler::addVerticesFromObject(LDObject* object) +{ + for (int i = 0; i < object->numPolygonVertices(); i += 1) + this->addVertex(object->vertex(i)); + + this->needCompile = true; +} + +void VertexCompiler::removeVerticesFromObject(LDObject* object) +{ + for (int i = 0; i < object->numPolygonVertices(); i += 1) + this->removeVertex(object->vertex(i)); + + this->needCompile = true; +} + +void VertexCompiler::addVertex(const Vertex& vertex) +{ + auto iterator = this->vertices.find(vertex); + + if (iterator == this->vertices.end()) + this->vertices.insert(vertex, 1); + else + iterator.value() += 1; +} + +void VertexCompiler::removeVertex(const Vertex& vertex) +{ + auto iterator = this->vertices.find(vertex); + + if (iterator != this->vertices.end()) + { + if (iterator.value() > 1) + iterator.value() -= 1; + else + this->vertices.erase(iterator); + } +} + +void VertexCompiler::updateVertex(const Vertex&) +{ + this->needCompile = true; +} + +/* + * Returns the GL buffer for the given vbo. + */ +GLuint VertexCompiler::vbo(Vbo vboIndex) +{ + if (this->needCompile) + { + this->compile(); + this->upload(); + this->needCompile = false; + } + + return this->vbos[vboIndex].buffer; +} + +/* + * Returns the size of the given vbo. + */ +size_t VertexCompiler::vboSize(Vbo vboIndex) const +{ + return this->vbos[vboIndex].data.size(); +} + +/* + * Clears the vertex scene. + */ +void VertexCompiler::clear() +{ + for (auto& vbo : this->vbos) + vbo.data.clear(); +} + +/* + * Builds the vertex scene + */ +void VertexCompiler::compile() +{ + this->clear(); + QMapIterator iterator {this->vertices}; + + while (iterator.hasNext()) + { + iterator.next(); + this->compileVertex(iterator.key()); + } +} + +/* + * Adds a little sphere into the scene to represent the given vertex. + */ +void VertexCompiler::compileVertex(const Vertex& vertex) +{ + for (int i = 0; i < countof(::sphere); i += 1) + { + // Y and Z inverted like the rest of the scene + Vertex spherePoint = { + ::sphere[i][X] * ::sphereSize + vertex.x, + ::sphere[i][Y] * ::sphereSize - vertex.y, + ::sphere[i][Z] * ::sphereSize - vertex.z + }; + this->vbos[Surfaces].data << spherePoint.x << spherePoint.y << spherePoint.z; + // The points of the sphere are position vectors, which in this case are also unit normals. + this->vbos[Normals].data << ::sphere[i][X] << ::sphere[i][Y] << ::sphere[i][Z]; + this->vbos[Colors].data + << ::sphereColor.redF() + << ::sphereColor.greenF() + << ::sphereColor.blueF() + << ::sphereColor.alphaF(); + } +} + +/* + * Uploads VBO data to the graphics card. + */ +void VertexCompiler::upload() +{ + for (const auto& vbo : this->vbos) + { + glBindBuffer(GL_ARRAY_BUFFER, vbo.buffer); + glBufferData( + GL_ARRAY_BUFFER, + countof(vbo.data) * sizeof(GLfloat), + vbo.data.constData(), + GL_STATIC_DRAW + ); + } + glBindBuffer(GL_ARRAY_BUFFER, 0); +} diff -r 4c134708be05 -r 2f18c0da749d src/vertexcompiler.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/vertexcompiler.h Fri Apr 27 16:27:14 2018 +0300 @@ -0,0 +1,69 @@ +/* + * LDForge: LDraw parts authoring CAD + * Copyright (C) 2013 - 2018 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 . + */ + +#pragma once +#include "main.h" +#include "glShared.h" + +class Model; +class VertexSelection; + +/* + * Compiles a scene that contains a small sphere for every vertex. + */ +class VertexCompiler : public QObject, protected QOpenGLFunctions +{ + Q_OBJECT + +public: + enum Vbo { Surfaces, Normals, Colors, PickColors, VboCount }; + + VertexCompiler(Model* model, VertexSelection* selection, QObject* parent = nullptr); + ~VertexCompiler(); + + void initialize(); + GLuint vbo(Vbo vboIndex); + size_t vboSize(Vbo vboIndex) const; + +private: + bool initialized = false; + bool needCompile = true; + struct + { + GLuint buffer; + QVector data; + } vbos[VboCount]; + QMap vertices; + Model* model; + + void addVertex(const Vertex& vertex); + void addVerticesFromObject(LDObject* object); + void clear(); + void compile(); + void compileVertex(const Vertex& vertex); + void removeVertex(const Vertex& vertex); + void removeVerticesFromObject(LDObject* object); + void upload(); + +private slots: + void handleNewObject(const QModelIndex& index); + void handlePreModifiedObject(); + void handleRemovedObject(const QModelIndex& index); + void handleModifiedObject(); + void updateVertex(const Vertex& vertex); +}; diff -r 4c134708be05 -r 2f18c0da749d src/vertexselection.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/vertexselection.cpp Fri Apr 27 16:27:14 2018 +0300 @@ -0,0 +1,41 @@ +/* + * LDForge: LDraw parts authoring CAD + * Copyright (C) 2013 - 2018 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 . + */ + +#include "vertexselection.h" + +VertexSelection::VertexSelection(QObject *parent) : QObject(parent) {} + +void VertexSelection::select(const Vertex& vertex) +{ + if (not this->selectedVertices.contains(vertex)) + { + this->selectedVertices.insert(vertex); + emit this->vertexSelected(vertex); + } +} + +void VertexSelection::deselect(const Vertex& vertex) +{ + auto iterator = this->selectedVertices.find(vertex); + + if (iterator != this->selectedVertices.end()) + { + this->selectedVertices.erase(iterator); + emit this->vertexDeselected(vertex); + } +} diff -r 4c134708be05 -r 2f18c0da749d src/vertexselection.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/vertexselection.h Fri Apr 27 16:27:14 2018 +0300 @@ -0,0 +1,37 @@ +/* + * LDForge: LDraw parts authoring CAD + * Copyright (C) 2013 - 2018 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 . + */ + +#pragma once +#include "main.h" + +class VertexSelection : public QObject +{ + Q_OBJECT +public: + VertexSelection(QObject* parent = nullptr); + + void select(const Vertex& vertex); + void deselect(const Vertex& vertex); + +signals: + void vertexSelected(const Vertex& vertex); + void vertexDeselected(const Vertex& vertex); + +private: + QSet selectedVertices; +};