Thu, 11 Jan 2018 15:09:44 +0200
begin rendering rework
--- a/src/basics.h Thu Jan 11 11:41:40 2018 +0200 +++ b/src/basics.h Thu Jan 11 15:09:44 2018 +0200 @@ -18,6 +18,7 @@ #pragma once #include <cmath> +#include <QSize> #include <QString> #include <QObject> #include <QStringList>
--- a/src/dialogs.cpp Thu Jan 11 11:41:40 2018 +0200 +++ b/src/dialogs.cpp Thu Jan 11 15:09:44 2018 +0200 @@ -60,7 +60,7 @@ { ui->right, ERightCamera } }; - ECamera cam = g_win->renderer()->camera(); + ECamera cam = g_win->currentRenderer()->camera(); if (cam == EFreeCamera) cam = ETopCamera; @@ -85,7 +85,7 @@ // ============================================================================= void OverlayDialog::fillDefaults(int newcam) { - LDGLOverlay& info = g_win->renderer()->getOverlay(newcam); + LDGLOverlay& info = g_win->currentRenderer()->getOverlay(newcam); RadioDefault<int>(newcam, m_cameraArgs); if (info.img)
--- a/src/dialogs/configdialog.cpp Thu Jan 11 11:41:40 2018 +0200 +++ b/src/dialogs/configdialog.cpp Thu Jan 11 15:09:44 2018 +0200 @@ -297,7 +297,7 @@ m_window->syncSettings(); currentDocument()->reloadAllSubfiles(); m_documents->loadLogoedStuds(); - m_window->renderer()->setBackground(); + m_window->currentRenderer()->setBackground(); m_window->doFullRefresh(); m_window->updateDocumentList(); }
--- a/src/documentmanager.cpp Thu Jan 11 11:41:40 2018 +0200 +++ b/src/documentmanager.cpp Thu Jan 11 15:09:44 2018 +0200 @@ -352,7 +352,6 @@ if (m_loadingMainFile) { m_window->changeDocument(load); - m_window->renderer()->setDocument(load); print(tr("File %1 parsed successfully(%2 errors)."), path, numWarnings); }
--- a/src/format.h Thu Jan 11 11:41:40 2018 +0200 +++ b/src/format.h Thu Jan 11 15:09:44 2018 +0200 @@ -162,6 +162,12 @@ } +inline QString toString(const QSize& size) +{ + return toString(size.width()) + " × " + toString(size.height()); +} + + /* * Formats the message with the given args using QString::arg(). */
--- a/src/glCompiler.cpp Thu Jan 11 11:41:40 2018 +0200 +++ b/src/glCompiler.cpp Thu Jan 11 15:09:44 2018 +0200 @@ -25,10 +25,12 @@ #include "ldDocument.h" #include "miscallenous.h" #include "glRenderer.h" -#include "dialogs.h" #include "guiutilities.h" #include "documentmanager.h" +static const QColor bfcFrontColor {64, 192, 80}; +static const QColor bfcBackColor {208, 64, 64}; + struct GLErrorInfo { GLenum value; @@ -49,8 +51,6 @@ ConfigOption(QString SelectColorBlend = "#0080FF") -// static QMap<LDObject*, String> g_objectOrigins; - void CheckGLErrorImpl(const char* file, int line) { QString errmsg; @@ -72,160 +72,160 @@ } -GLCompiler::GLCompiler(GLRenderer* renderer) : - HierarchyElement(renderer), - m_renderer(renderer) -{ - needMerge(); - memset(m_vboSizes, 0, sizeof m_vboSizes); -} +GLCompiler::GLCompiler(LDDocument* document, GLRenderer* renderer) : + document {document}, + renderer {renderer} {} void GLCompiler::initialize() { initializeOpenGLFunctions(); - glGenBuffers(NumVbos, &m_vbo[0]); + glGenBuffers(NumVbos, &vboIndices[0]); CHECK_GL_ERROR(); } GLCompiler::~GLCompiler() { - glDeleteBuffers(NumVbos, &m_vbo[0]); + glDeleteBuffers(NumVbos, &vboIndices[0]); CHECK_GL_ERROR(); } +/* + * Returns a color that represents this object index. There are 256³ possible + * colors, so that many indices can be bijectively addressed with colorss. + */ +QColor GLCompiler::indexColorForID(int id) const +{ + int red = (id / 0x10000) % 0x100; + int green = (id / 0x100) % 0x100; + int blue = id % 0x100; + + return {red, green, blue}; +} + -QColor GLCompiler::indexColorForID(int id) const +QColor blend(QColor baseColor, QColor blendColor, double intensity) { - // Calculate a color based from this index. This method caters for - // 16777216 objects. I don't think that will be exceeded anytime soon. :) - int r = (id / 0x10000) % 0x100, - g = (id / 0x100) % 0x100, - b = id % 0x100; - - return QColor(r, g, b); + double red = baseColor.redF(); + red += blendColor.redF() * intensity; + red /= (intensity + 1.0); + double green = baseColor.greenF(); + green += blendColor.greenF() * intensity; + green /= (intensity + 1.0); + double blue = baseColor.blueF(); + blue += blendColor.blueF() * intensity; + blue /= (intensity + 1.0); + return {int(round(red)), int(round(green)), int(round(blue))}; } QColor GLCompiler::getColorForPolygon(LDPolygon& poly, LDObject* topobj, ComplementVboType complement) const { - QColor qcol; - static const QColor bfcFrontColor(64, 192, 80); - static const QColor bfcBackColor(208, 64, 64); + QColor color; switch(complement) { case SurfacesVboComplement: case NumVboComplements: - return QColor(); + return {}; case BfcFrontColorsVboComplement: - qcol = bfcFrontColor; + color = bfcFrontColor; break; case BfcBackColorsVboComplement: - qcol = bfcBackColor; + color = bfcBackColor; break; case PickColorsVboComplement: return indexColorForID(topobj->id()); case RandomColorsVboComplement: - qcol = topobj->randomColor(); + color = topobj->randomColor(); break; case NormalColorsVboComplement: if (poly.color == MainColor) { if (topobj->color() == MainColor) - qcol = guiUtilities()->mainColorRepresentation(); + color = mainColorRepresentation(); else - qcol = topobj->color().faceColor(); + color = topobj->color().faceColor(); } else if (poly.color == EdgeColor) { - qcol = luma(QColor(config->backgroundColor())) > 40 ? Qt::black : Qt::white; + if (luma(config->backgroundColor()) > 40) + color = Qt::black; + else + color = Qt::white; } else { - LDColor col = poly.color; + LDColor colorInfo = poly.color; - if (col.isValid()) - qcol = col.faceColor(); + if (colorInfo.isValid()) + color = colorInfo.faceColor(); } break; } - if (not qcol.isValid()) + if (not color.isValid()) { // The color was unknown. Use main color to make the polygon at least // not appear pitch-black. if (poly.num != 2 and poly.num != 5) - qcol = guiUtilities()->mainColorRepresentation(); + color = mainColorRepresentation(); else - qcol = Qt::black; + color = Qt::black; // Warn about the unknown color, but only once. - static QList<int> warnedColors; + static QSet<int> warnedColors; if (not warnedColors.contains(poly.color)) { print("Unknown color %1!\n", poly.color); - warnedColors << poly.color; + warnedColors.insert(poly.color); } - return qcol; + return color; } double blendAlpha = 0.0; if (topobj->isSelected()) blendAlpha = 1.0; - else if (topobj == m_renderer->objectAtCursor()) + else if (topobj == renderer->objectAtCursor()) blendAlpha = 0.5; - if (blendAlpha != 0.0) - { - QColor selcolor(config->selectColorBlend()); - double denom = blendAlpha + 1.0; - qcol.setRed((qcol.red() +(selcolor.red() * blendAlpha)) / denom); - qcol.setGreen((qcol.green() +(selcolor.green() * blendAlpha)) / denom); - qcol.setBlue((qcol.blue() +(selcolor.blue() * blendAlpha)) / denom); - } - - return qcol; + color = blend(color, config->selectColorBlend(), blendAlpha); + return color; } void GLCompiler::needMerge() { - for (int i = 0; i < countof(m_vboChanged); ++i) - m_vboChanged[i] = true; + for (bool& changed_flag : this->vboChanged) + changed_flag = true; } void GLCompiler::stageForCompilation(LDObject* obj) { - /* - g_objectOrigins[obj] = format("%1:%2(%3)", - obj->document()->getDisplayName(), obj->lineNumber(), obj->typeName()); - */ - - m_staged << obj; + stagedObjects << obj; } void GLCompiler::unstage(LDObject* obj) { - m_staged.remove(obj); + stagedObjects.remove(obj); } -void GLCompiler::compileDocument(LDDocument* doc) +void GLCompiler::compileDocument(LDDocument* document) { - if (doc) + if (document) { - for (LDObject* obj : doc->objects()) + for (LDObject* obj : document->objects()) compileObject(obj); } } @@ -233,10 +233,10 @@ void GLCompiler::compileStaged() { - for (QSetIterator<LDObject*> it(m_staged); it.hasNext();) + for (QSetIterator<LDObject*> it(stagedObjects); it.hasNext();) compileObject(it.next()); - m_staged.clear(); + stagedObjects.clear(); } @@ -245,39 +245,45 @@ // Compile anything that still awaits it compileStaged(); - if (not m_vboChanged[vbonum]) - return; - - QVector<GLfloat> vbodata; + if (not vboChanged[vbonum]) + { + print("Merging %1", vbonum); + QVector<GLfloat> vbodata; - for (auto it = m_objectInfo.begin(); it != m_objectInfo.end();) - { - if (it.key() == nullptr) + for (auto it = objectInfo.begin(); it != objectInfo.end();) { - it = m_objectInfo.erase(it); - continue; + if (it.key() == nullptr) + { + it = objectInfo.erase(it); + } + else + { + if (not it.key()->isHidden()) + vbodata += it->data[vbonum]; + + ++it; + } } - if (it.key()->document() == currentDocument() and not it.key()->isHidden()) - vbodata += it->data[vbonum]; - - ++it; + glBindBuffer(GL_ARRAY_BUFFER, vboIndices[vbonum]); + glBufferData( + GL_ARRAY_BUFFER, + vbodata.size() * sizeof(GLfloat), + vbodata.constData(), + GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + CHECK_GL_ERROR(); + vboChanged[vbonum] = false; + vboSizes[vbonum] = vbodata.size(); } - - glBindBuffer(GL_ARRAY_BUFFER, m_vbo[vbonum]); - glBufferData(GL_ARRAY_BUFFER, vbodata.size() * sizeof(GLfloat), vbodata.constData(), GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - CHECK_GL_ERROR(); - m_vboChanged[vbonum] = false; - m_vboSizes[vbonum] = vbodata.size(); } void GLCompiler::dropObjectInfo(LDObject* obj) { - if (m_objectInfo.contains(obj)) + if (objectInfo.contains(obj)) { - m_objectInfo.remove(obj); + objectInfo.remove(obj); needMerge(); } } @@ -336,7 +342,7 @@ break; } - m_objectInfo[obj] = info; + objectInfo[obj] = info; needMerge(); } @@ -381,13 +387,6 @@ } } - -void GLCompiler::setRenderer(GLRenderer* renderer) -{ - m_renderer = renderer; -} - - int GLCompiler::vboNumber(SurfaceVboType surface, ComplementVboType complement) { return (surface * NumVboComplements) + complement; @@ -396,11 +395,11 @@ GLuint GLCompiler::vbo(int vbonum) const { - return m_vbo[vbonum]; + return vboIndices[vbonum]; } int GLCompiler::vboSize(int vbonum) const { - return m_vboSizes[vbonum]; -} \ No newline at end of file + return vboSizes[vbonum]; +}
--- a/src/glCompiler.h Thu Jan 11 11:41:40 2018 +0200 +++ b/src/glCompiler.h Thu Jan 11 15:09:44 2018 +0200 @@ -17,33 +17,22 @@ */ #pragma once +#include <QOpenGLFunctions> #include "main.h" -#include "glRenderer.h" #include "glShared.h" -#include <QMap> -#include <QSet> -// ============================================================================= -// -class GLCompiler : public HierarchyElement, protected QOpenGLFunctions +class GLCompiler : protected QOpenGLFunctions { public: - struct ObjectVBOInfo - { - QVector<GLfloat> data[NumVbos]; - bool isChanged; - }; - - GLCompiler(GLRenderer* renderer); + GLCompiler(LDDocument* document, class GLRenderer* renderer); ~GLCompiler(); - void compileDocument(LDDocument* doc); + void compileDocument(LDDocument* document); void dropObjectInfo(LDObject* obj); QColor getColorForPolygon(LDPolygon& poly, LDObject* topobj, ComplementVboType complement) const; QColor indexColorForID(int id) const; void initialize(); void needMerge(); void prepareVBO(int vbonum); - void setRenderer(GLRenderer* compiler); void stageForCompilation(LDObject* obj); void unstage(LDObject* obj); GLuint vbo(int vbonum) const; @@ -52,16 +41,23 @@ static int vboNumber(SurfaceVboType surface, ComplementVboType complement); private: + struct ObjectVBOInfo + { + QVector<GLfloat> data[NumVbos]; + bool isChanged = false; + }; + void compileStaged(); void compileObject(LDObject* obj); void compilePolygon(LDPolygon& poly, LDObject* topobj, ObjectVBOInfo* objinfo); - QMap<LDObject*, ObjectVBOInfo> m_objectInfo; - QSet<LDObject*> m_staged; // Objects that need to be compiled - GLuint m_vbo[NumVbos]; - bool m_vboChanged[NumVbos]; - int m_vboSizes[NumVbos]; - GLRenderer* m_renderer; + QMap<LDObject*, ObjectVBOInfo> objectInfo; + QSet<LDObject*> stagedObjects; // Objects that need to be compiled + LDDocument* const document; + GLuint vboIndices[NumVbos]; + bool vboChanged[NumVbos] = {true}; + int vboSizes[NumVbos] = {0}; + class GLRenderer* renderer; }; #define CHECK_GL_ERROR() { CheckGLErrorImpl(__FILE__, __LINE__); }
--- a/src/glRenderer.cpp Thu Jan 11 11:41:40 2018 +0200 +++ b/src/glRenderer.cpp Thu Jan 11 15:09:44 2018 +0200 @@ -71,10 +71,11 @@ // ============================================================================= // -GLRenderer::GLRenderer(QWidget* parent) : +GLRenderer::GLRenderer(LDDocument *document, QWidget* parent) : QGLWidget(parent), HierarchyElement(parent), - m_document(nullptr), + m_document(document), + m_compiler {document, this}, m_initialized(false) { m_isPicking = false; @@ -82,7 +83,6 @@ m_drawToolTip = false; m_currentEditMode = AbstractEditMode::createByType(this, EditModeType::Select); m_panning = false; - m_compiler = new GLCompiler(this); m_objectAtCursor = nullptr; setDrawOnly(false); m_messageLog = new MessageManager(this); @@ -128,8 +128,6 @@ if (messageLog()) messageLog()->setRenderer(nullptr); - m_compiler->setRenderer(nullptr); - delete m_compiler; delete m_currentEditMode; glDeleteBuffers(1, &m_axesVbo); glDeleteBuffers(1, &m_axesColorVbo); @@ -215,7 +213,7 @@ GLCompiler* GLRenderer::compiler() const { - return m_compiler; + return &m_compiler; } LDObject* GLRenderer::objectAtCursor() const @@ -506,13 +504,13 @@ return; } - int surfacenum = m_compiler->vboNumber(surface, SurfacesVboComplement); - int colornum = m_compiler->vboNumber(surface, colors); - m_compiler->prepareVBO(surfacenum); - m_compiler->prepareVBO(colornum); - GLuint surfacevbo = m_compiler->vbo(surfacenum); - GLuint colorvbo = m_compiler->vbo(colornum); - GLsizei count = m_compiler->vboSize(surfacenum) / 3; + int surfacenum = m_compiler.vboNumber(surface, SurfacesVboComplement); + int colornum = m_compiler.vboNumber(surface, colors); + m_compiler.prepareVBO(surfacenum); + m_compiler.prepareVBO(colornum); + GLuint surfacevbo = m_compiler.vbo(surfacenum); + GLuint colorvbo = m_compiler.vbo(colornum); + GLsizei count = m_compiler.vboSize(surfacenum) / 3; if (count > 0) { @@ -1059,26 +1057,6 @@ // ============================================================================= // -void GLRenderer::setDocument(LDDocument* document) -{ - m_document = document; - - if (document) - { - initOverlaysFromObjects(); - - if (not currentDocumentData().init) - { - resetAllAngles(); - currentDocumentData().init = true; - } - - currentDocumentData().needZoomToFit = true; - } -} - -// ============================================================================= -// void GLRenderer::setPicking(bool value) { m_isPicking = value; @@ -1525,7 +1503,7 @@ } } - if (m_window->renderer() == this) + if (m_window->currentRenderer() == this) m_window->refresh(); } @@ -1592,7 +1570,7 @@ currentDocument()->insertObj(m_window->suggestInsertPoint(), ref); ref->select(); m_window->buildObjectList(); - m_window->renderer()->refresh(); + m_window->currentRenderer()->refresh(); ev->acceptProposedAction(); } }
--- a/src/glRenderer.h Thu Jan 11 11:41:40 2018 +0200 +++ b/src/glRenderer.h Thu Jan 11 15:09:44 2018 +0200 @@ -22,6 +22,7 @@ #include "macros.h" #include "ldObject.h" #include "ldDocument.h" +#include "glCompiler.h" #include "glShared.h" #include "editmodes/abstractEditMode.h" @@ -136,7 +137,7 @@ Q_OBJECT public: - GLRenderer(QWidget* parent = nullptr); + GLRenderer(LDDocument* document, QWidget* parent = nullptr); ~GLRenderer(); ECamera camera() const; @@ -186,7 +187,6 @@ void setBackground(); void setCamera(const ECamera cam); void setDepthValue(double depth); - void setDocument(LDDocument* document); void setDrawOnly(bool value); void setEditMode(EditModeType type); void setPicking(bool a); @@ -213,8 +213,8 @@ private: MessageManager* m_messageLog; - LDDocument* m_document; - GLCompiler* m_compiler; + LDDocument* const m_document; + mutable GLCompiler m_compiler; LDObject* m_objectAtCursor; CameraIcon m_cameraIcons[7];
--- a/src/guiutilities.cpp Thu Jan 11 11:41:40 2018 +0200 +++ b/src/guiutilities.cpp Thu Jan 11 15:09:44 2018 +0200 @@ -82,7 +82,7 @@ } } -QColor GuiUtilities::mainColorRepresentation() +QColor mainColorRepresentation() { QColor col(config->mainColor());
--- a/src/guiutilities.h Thu Jan 11 11:41:40 2018 +0200 +++ b/src/guiutilities.h Thu Jan 11 15:09:44 2018 +0200 @@ -28,5 +28,6 @@ QIcon makeColorIcon(LDColor ldcolor, int size); void fillUsedColorsToComboBox(class QComboBox* box); - QColor mainColorRepresentation(); }; + +QColor mainColorRepresentation();
--- a/src/ldDocument.cpp Thu Jan 11 11:41:40 2018 +0200 +++ b/src/ldDocument.cpp Thu Jan 11 15:09:44 2018 +0200 @@ -131,11 +131,10 @@ if (m_isCache) { m_isCache = false; - print("Opened %1", name()); // Cache files are not compiled by the GL renderer. Now that this file is open for editing, it needs to be // compiled. - m_window->renderer()->compiler()->compileDocument(this); + m_window->currentRenderer()->compiler()->compileDocument(this); m_window->updateDocumentList(); } } @@ -177,10 +176,7 @@ m_isCache = true; print("Closed %1", name()); m_window->updateDocumentList(); - - // If the current document just became implicit(i.e. user closed it), we need to get a new one to show. - if (currentDocument() == this) - m_window->currentDocumentClosed(); + emit closed(); } } @@ -599,7 +595,7 @@ m_objects << obj; addKnownVertices(obj); obj->setDocument(this); - m_window->renderer()->compileObject(obj); + m_window->currentRenderer()->compileObject(obj); return getObjectCount() - 1; } @@ -621,7 +617,7 @@ history()->add(new AddHistoryEntry(pos, obj)); m_objects.insert(pos, obj); obj->setDocument(this); - m_window->renderer()->compileObject(obj); + m_window->currentRenderer()->compileObject(obj); #ifdef DEBUG @@ -686,7 +682,7 @@ m_objects[idx]->setDocument(nullptr); obj->setDocument(this); addKnownVertices(obj); - m_window->renderer()->compileObject(obj); + m_window->currentRenderer()->compileObject(obj); m_objects[idx] = obj; needVertexMerge(); } @@ -830,7 +826,7 @@ if (obj->isSelected() and obj->document() == this) { m_sel << obj; - m_window->renderer()->compileObject(obj); + m_window->currentRenderer()->compileObject(obj); } } @@ -841,7 +837,7 @@ if (not obj->isSelected() and obj->document() == this) { m_sel.removeOne(obj); - m_window->renderer()->compileObject(obj); + m_window->currentRenderer()->compileObject(obj); } } @@ -852,7 +848,7 @@ for (LDObject* obj : m_sel) { obj->deselect(); - m_window->renderer()->compileObject(obj); + m_window->currentRenderer()->compileObject(obj); } m_sel.clear(); @@ -909,4 +905,4 @@ void LDDocument::needVertexMerge() { m_needVertexMerge = true; -} \ No newline at end of file +}
--- a/src/ldDocument.h Thu Jan 11 11:41:40 2018 +0200 +++ b/src/ldDocument.h Thu Jan 11 15:09:44 2018 +0200 @@ -100,6 +100,9 @@ static QString shortenName(QString a); // Turns a full path into a relative path +signals: + void closed(); + private: QString m_name; QString m_fullPath;
--- a/src/ldObject.cpp Thu Jan 11 11:41:40 2018 +0200 +++ b/src/ldObject.cpp Thu Jan 11 15:09:44 2018 +0200 @@ -315,7 +315,7 @@ // Delete the GL lists if (g_win) - g_win->renderer()->forgetObject(this); + g_win->currentRenderer()->forgetObject(this); // Remove this object from the list of LDObjects g_allObjects.erase(g_allObjects.find(id())); @@ -481,7 +481,7 @@ // The objects need to be recompiled, otherwise their pick lists are left with // the wrong index colors which messes up selection. for (LDObject* obj : objsToCompile) - g_win->renderer()->compileObject(obj); + g_win->currentRenderer()->compileObject(obj); } // ============================================================================= @@ -848,7 +848,7 @@ if (before != after) { obj->document()->addToHistory(new EditHistoryEntry(idx, before, after)); - g_win->renderer()->compileObject(obj); + g_win->currentRenderer()->compileObject(obj); g_win->currentDocument()->redoVertices(); } }
--- a/src/main.h Thu Jan 11 11:41:40 2018 +0200 +++ b/src/main.h Thu Jan 11 15:09:44 2018 +0200 @@ -25,6 +25,7 @@ #include <stdlib.h> #include <stdint.h> #include <stdarg.h> +#include <QSet> #include <QString> #include <QTextFormat> #include "macros.h" @@ -33,4 +34,4 @@ #include "hierarchyelement.h" #include "configurationvaluebag.h" -extern ConfigurationValueBag* config; \ No newline at end of file +extern ConfigurationValueBag* config;
--- a/src/mainwindow.cpp Thu Jan 11 11:41:40 2018 +0200 +++ b/src/mainwindow.cpp Thu Jan 11 15:09:44 2018 +0200 @@ -77,17 +77,11 @@ g_win = this; ui.setupUi(this); m_updatingTabs = false; - m_renderer = new GLRenderer(this); m_tabs = new QTabBar; m_tabs->setTabsClosable(true); ui.verticalLayout->insertWidget(0, m_tabs); createBlankDocument(); - m_renderer->setDocument(m_currentDocument); - - // Stuff the renderer into its frame - QVBoxLayout* rendererLayout = new QVBoxLayout(ui.rendererFrame); - rendererLayout->addWidget(renderer()); connect(ui.objectList, SIGNAL(itemSelectionChanged()), this, SLOT(selectionChanged())); connect(ui.objectList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(objectListDoubleClicked(QListWidgetItem*))); @@ -117,7 +111,6 @@ updateTitle(); loadShortcuts(); setMinimumSize(300, 200); - connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(doLastSecondCleanup())); connect( ui.ringToolSegments, SIGNAL(valueChanged(int)), this, SLOT(circleToolSegmentsChanged()) @@ -186,6 +179,10 @@ MainWindow::~MainWindow() { + for (GLRenderer* renderer : m_renderers.values()) + delete renderer; + + delete &ui; g_win = nullptr; } @@ -222,14 +219,6 @@ // --------------------------------------------------------------------------------------------------------------------- // -void MainWindow::doLastSecondCleanup() -{ - delete m_renderer; - delete &ui; -} - -// --------------------------------------------------------------------------------------------------------------------- -// void MainWindow::updateRecentFilesMenu() { // First, clear any items in the recent files menu @@ -319,7 +308,7 @@ // Recompile all Bézier curves, the changing grid affects their precision. for (LDObjectIterator<LDBezierCurve> it(m_currentDocument); it.isValid(); ++it) - renderer()->compileObject(it); + currentRenderer()->compileObject(it); } // --------------------------------------------------------------------------------------------------------------------- @@ -457,7 +446,7 @@ case OBJ_Overlay: { LDOverlay* ovl = static_cast<LDOverlay*>(obj); - descr = format("[%1] %2(%3, %4), %5 x %6", renderer()->cameraName((ECamera) ovl->camera()), + descr = format("[%1] %2(%3, %4), %5 x %6", currentRenderer()->cameraName((ECamera) ovl->camera()), Basename(ovl->fileName()), ovl->x(), ovl->y(), ovl->width(), ovl->height()); break; @@ -553,9 +542,9 @@ removeDuplicates(compound); for (LDObject* obj : compound) - renderer()->compileObject(obj); + currentRenderer()->compileObject(obj); - renderer()->update(); + currentRenderer()->update(); } // --------------------------------------------------------------------------------------------------------------------- @@ -591,7 +580,7 @@ continue; // uncolored object obj->setColor(color); - renderer()->compileObject(obj); + currentRenderer()->compileObject(obj); } endAction(); @@ -616,8 +605,8 @@ // void MainWindow::doFullRefresh() { - buildObjectList(); - m_renderer->hardRefresh(); + this->buildObjectList(); + this->currentRenderer()->hardRefresh(); } // --------------------------------------------------------------------------------------------------------------------- @@ -627,7 +616,7 @@ void MainWindow::refresh() { buildObjectList(); - m_renderer->update(); + currentRenderer()->update(); } // --------------------------------------------------------------------------------------------------------------------- @@ -782,7 +771,7 @@ contextMenu->addAction(ui.actionSubfileSelection); } - if (renderer()->camera() != EFreeCamera) + if (currentRenderer()->camera() != EFreeCamera) { contextMenu->addSeparator(); contextMenu->addAction(ui.actionSetDrawDepth); @@ -813,7 +802,7 @@ // void MainWindow::updateEditModeActions() { - const EditModeType mode = renderer()->currentEditModeType(); + const EditModeType mode = currentRenderer()->currentEditModeType(); ui.actionModeSelect->setChecked(mode == EditModeType::Select); ui.actionModeDraw->setChecked(mode == EditModeType::Draw); ui.actionModeRectangle->setChecked(mode == EditModeType::Rectangle); @@ -894,7 +883,7 @@ // Adds a message to the renderer's message manager. void MainWindow::addMessage(QString msg) { - m_renderer->messageLog()->addLine(msg); + this->currentRenderer()->messageLog()->addLine(msg); } // ============================================================================ @@ -1058,9 +1047,9 @@ // --------------------------------------------------------------------------------------------------------------------- // -GLRenderer* MainWindow::renderer() +GLRenderer* MainWindow::currentRenderer() { - return m_renderer; + return m_renderers[m_currentDocument]; } // --------------------------------------------------------------------------------------------------------------------- @@ -1231,9 +1220,17 @@ connect(document->history(), SIGNAL(undone()), this, SLOT(historyTraversed())); connect(document->history(), SIGNAL(redone()), this, SLOT(historyTraversed())); connect(document->history(), SIGNAL(stepAdded()), this, SLOT(updateActions())); + connect(document, SIGNAL(closed()), this, SLOT(documentClosed())); + + GLRenderer* renderer = new GLRenderer {document, this}; + m_renderers[document] = renderer; + ui.rendererStack->addWidget(renderer); if (not cache) + { + changeDocument(document); document->openForEditing(); + } return document; } @@ -1251,7 +1248,8 @@ // void MainWindow::changeDocument(LDDocument* document) { - // Implicit files were loaded for caching purposes and may never be switched to. + // Implicit files were loaded for caching purposes and may + // not be switched to. if (document and document->isCache()) return; @@ -1263,8 +1261,7 @@ updateDocumentListItem(document); buildObjectList(); updateTitle(); - m_renderer->setDocument(document); - m_renderer->compiler()->needMerge(); + ui.rendererStack->setCurrentWidget(m_renderers[document]); print("Changed document to %1", document->getDisplayName()); } } @@ -1295,24 +1292,38 @@ // --------------------------------------------------------------------------------------------------------------------- // -void MainWindow::currentDocumentClosed() +void MainWindow::documentClosed() { - LDDocument* old = currentDocument(); + LDDocument* document = qobject_cast<LDDocument*>(sender()); + + if (not document) + return; + + if (document == currentDocument()) + { + LDDocument* previousCurrentDocument = currentDocument(); - // Find a replacement document to use - for (LDDocument* doc : m_documents->allDocuments()) - { - if (doc != old and not doc->isCache()) + // Find a replacement document to use + for (LDDocument* document : m_documents->allDocuments()) { - changeDocument(doc); - break; + if (document != previousCurrentDocument and not document->isCache()) + { + changeDocument(document); + break; + } + } + + if (currentDocument() == previousCurrentDocument) + { + // Failed to change to a suitable document, open a new one. + createBlankDocument(); } } - if (currentDocument() == old) + if (m_renderers.contains(document)) { - // Failed to change to a suitable document, open a new one. - createBlankDocument(); + delete m_renderers[document]; + m_renderers.remove(document); } }
--- a/src/mainwindow.h Thu Jan 11 11:41:40 2018 +0200 +++ b/src/mainwindow.h Thu Jan 11 15:09:44 2018 +0200 @@ -80,7 +80,6 @@ void closeInitialDocument(); void createBlankDocument(); LDDocument* currentDocument(); - void currentDocumentClosed(); QKeySequence defaultShortcut(QAction* act); void deleteByColor(LDColor color); int deleteSelection(); @@ -95,7 +94,7 @@ class GuiUtilities* guiUtilities(); void loadShortcuts(); LDDocument* newDocument(bool cache = false); - GLRenderer* renderer(); + GLRenderer* currentRenderer(); void refresh(); void refreshObjectList(); int ringToolDivisions() const; @@ -134,6 +133,7 @@ struct ToolInfo { QMetaMethod method; Toolset* object; }; class GuiUtilities* m_guiUtilities; + QMap<LDDocument*, GLRenderer*> m_renderers; GLRenderer* m_renderer; LDObjectList m_sel; QList<ColorToolbarItem> m_quickColors; @@ -157,8 +157,8 @@ void selectionChanged(); void recentFileClicked(); void quickColorClicked(); - void doLastSecondCleanup(); void objectListDoubleClicked(QListWidgetItem* listitem); + void documentClosed(); }; // Pointer to the instance of MainWindow.
--- a/src/mainwindow.ui Thu Jan 11 11:41:40 2018 +0200 +++ b/src/mainwindow.ui Thu Jan 11 15:09:44 2018 +0200 @@ -20,9 +20,9 @@ <widget class="QWidget" name="centralwidget"> <layout class="QVBoxLayout" name="verticalLayout"> <item> - <layout class="QHBoxLayout" name="horizontalLayout" stretch="3,1"> + <layout class="QHBoxLayout" name="horizontalLayout" stretch="2,1"> <item> - <widget class="QFrame" name="rendererFrame"> + <widget class="QStackedWidget" name="rendererStack"> <property name="sizePolicy"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <horstretch>0</horstretch> @@ -47,7 +47,7 @@ <rect> <x>0</x> <y>0</y> - <width>233</width> + <width>465</width> <height>371</height> </rect> </property> @@ -75,7 +75,7 @@ <rect> <x>0</x> <y>0</y> - <width>233</width> + <width>310</width> <height>371</height> </rect> </property> @@ -179,7 +179,7 @@ <rect> <x>0</x> <y>0</y> - <width>233</width> + <width>465</width> <height>371</height> </rect> </property>
--- a/src/toolsets/basictoolset.cpp Thu Jan 11 11:41:40 2018 +0200 +++ b/src/toolsets/basictoolset.cpp Thu Jan 11 15:09:44 2018 +0200 @@ -269,35 +269,35 @@ void BasicToolset::modeSelect() { - m_window->renderer()->setEditMode(EditModeType::Select); + m_window->currentRenderer()->setEditMode(EditModeType::Select); } void BasicToolset::modeCurve() { - m_window->renderer()->setEditMode(EditModeType::Curve); + m_window->currentRenderer()->setEditMode(EditModeType::Curve); } void BasicToolset::modeDraw() { - m_window->renderer()->setEditMode(EditModeType::Draw); + m_window->currentRenderer()->setEditMode(EditModeType::Draw); } void BasicToolset::modeRectangle() { - m_window->renderer()->setEditMode(EditModeType::Rectangle); + m_window->currentRenderer()->setEditMode(EditModeType::Rectangle); } void BasicToolset::modeCircle() { - m_window->renderer()->setEditMode(EditModeType::Circle); + m_window->currentRenderer()->setEditMode(EditModeType::Circle); } void BasicToolset::modeMagicWand() { - m_window->renderer()->setEditMode(EditModeType::MagicWand); + m_window->currentRenderer()->setEditMode(EditModeType::MagicWand); } void BasicToolset::modeLinePath() { - m_window->renderer()->setEditMode(EditModeType::LinePath); -} \ No newline at end of file + m_window->currentRenderer()->setEditMode(EditModeType::LinePath); +}
--- a/src/toolsets/filetoolset.cpp Thu Jan 11 11:41:40 2018 +0200 +++ b/src/toolsets/filetoolset.cpp Thu Jan 11 15:09:44 2018 +0200 @@ -134,7 +134,7 @@ { currentDocument()->insertObj(idx, obj); obj->select(); - m_window->renderer()->compileObject(obj); + m_window->currentRenderer()->compileObject(obj); idx++; } @@ -193,7 +193,7 @@ { m_window->changeDocument(dialog->primaryFile()); m_window->doFullRefresh(); - m_window->renderer()->resetAngles(); + m_window->currentRenderer()->resetAngles(); }); dialog->exec(); } @@ -234,4 +234,4 @@ void FileToolset::aboutQt() { QMessageBox::aboutQt(m_window); -} \ No newline at end of file +}
--- a/src/toolsets/viewtoolset.cpp Thu Jan 11 11:41:40 2018 +0200 +++ b/src/toolsets/viewtoolset.cpp Thu Jan 11 15:09:44 2018 +0200 @@ -98,17 +98,17 @@ void ViewToolset::resetView() { - m_window->renderer()->resetAngles(); - m_window->renderer()->update(); + m_window->currentRenderer()->resetAngles(); + m_window->currentRenderer()->update(); } void ViewToolset::screenshot() { const char* imageformats = "PNG images(*.png);;JPG images(*.jpg);;BMP images(*.bmp);;" "PPM images(*.ppm);;X11 Bitmaps(*.xbm);;X11 Pixmaps(*.xpm);;All Files(*.*)"; - int width = m_window->renderer()->width(); - int height = m_window->renderer()->height(); - QByteArray capture = m_window->renderer()->capturePixels(); + int width = m_window->currentRenderer()->width(); + int height = m_window->currentRenderer()->height(); + QByteArray capture = m_window->currentRenderer()->capturePixels(); const uchar* imagedata = reinterpret_cast<const uchar*>(capture.constData()); // GL and Qt formats have R and B swapped. Also, GL flips Y - correct it as well. QImage image = QImage(imagedata, width, height, QImage::Format_ARGB32).rgbSwapped().mirrored(); @@ -128,7 +128,7 @@ { config->setDrawAxes(not config->drawAxes()); m_window->updateActions(); - m_window->renderer()->update(); + m_window->currentRenderer()->update(); } void ViewToolset::visibilityToggle() @@ -152,7 +152,7 @@ void ViewToolset::wireframe() { config->setDrawWireframe(not config->drawWireframe()); - m_window->renderer()->refresh(); + m_window->currentRenderer()->refresh(); } void ViewToolset::setOverlay() @@ -162,33 +162,33 @@ if (not dlg.exec()) return; - m_window->renderer()->setupOverlay((ECamera) dlg.camera(), dlg.fpath(), dlg.ofsx(), + m_window->currentRenderer()->setupOverlay((ECamera) dlg.camera(), dlg.fpath(), dlg.ofsx(), dlg.ofsy(), dlg.lwidth(), dlg.lheight()); } void ViewToolset::clearOverlay() { - m_window->renderer()->clearOverlay(); + m_window->currentRenderer()->clearOverlay(); } void ViewToolset::drawAngles() { config->setDrawAngles(not config->drawAngles()); - m_window->renderer()->refresh(); + m_window->currentRenderer()->refresh(); } void ViewToolset::setDrawDepth() { - if (m_window->renderer()->camera() == EFreeCamera) + if (m_window->currentRenderer()->camera() == EFreeCamera) return; bool ok; double depth = QInputDialog::getDouble(m_window, "Set Draw Depth", - format("Depth value for %1:", m_window->renderer()->currentCameraName()), - m_window->renderer()->getDepthValue(), -10000.0f, 10000.0f, 3, &ok); + format("Depth value for %1:", m_window->currentRenderer()->currentCameraName()), + m_window->currentRenderer()->getDepthValue(), -10000.0f, 10000.0f, 3, &ok); if (ok) - m_window->renderer()->setDepthValue(depth); + m_window->currentRenderer()->setDepthValue(depth); } #if 0 @@ -248,7 +248,7 @@ config->setRandomColors(false); m_window->updateActions(); - m_window->renderer()->refresh(); + m_window->currentRenderer()->refresh(); } void ViewToolset::jumpTo() @@ -279,7 +279,7 @@ config->setBfcRedGreenView(false); m_window->updateActions(); - m_window->renderer()->refresh(); + m_window->currentRenderer()->refresh(); } void ViewToolset::drawSurfaces()