diff options
Diffstat (limited to 'src/mainwin.cc')
-rw-r--r-- | src/mainwin.cc | 478 |
1 files changed, 271 insertions, 207 deletions
diff --git a/src/mainwin.cc b/src/mainwin.cc index 44c5cff..56502f2 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -24,6 +24,7 @@ * */ +#include "PolySetCache.h" #include "MainWindow.h" #include "openscad.h" // examplesdir #include "Preferences.h" @@ -40,6 +41,7 @@ #include "dxftess.h" #include "progress.h" #ifdef ENABLE_OPENCSG +#include "CSGTermEvaluator.h" #include "OpenCSGRenderer.h" #endif #ifdef USE_PROGRESSWIDGET @@ -74,19 +76,34 @@ #include "qlanguagefactory.h" #endif +#include <fstream> + +#include <algorithm> +#include <boost/foreach.hpp> +#include <boost/lambda/lambda.hpp> +#include <boost/lambda/bind.hpp> +using namespace boost::lambda; + #ifdef ENABLE_CGAL -#include "cgalrenderer.h" +#include "CGALCache.h" +#include "CGALEvaluator.h" +#include "PolySetCGALEvaluator.h" +#include "CGALRenderer.h" +#include "CGAL_Nef_polyhedron.h" +#include "cgal.h" #endif // ENABLE_CGAL +// Global application state +unsigned int GuiLocker::gui_locked = 0; + #define QUOTE(x__) # x__ #define QUOTED(x__) QUOTE(x__) static char helptitle[] = - "OpenSCAD " - QUOTED(OPENSCAD_VERSION) - " (www.openscad.org)\n"; + "OpenSCAD " QUOTED(OPENSCAD_VERSION) " (www.openscad.org)\n" + "Visitor refactored version\n"; static char copyrighttext[] = "Copyright (C) 2009-2011 Marius Kintel <marius@kintel.net> and Clifford Wolf <clifford@clifford.at>\n" "\n" @@ -137,11 +154,13 @@ MainWindow::MainWindow(const QString &filename) root_ctx.set_variable("$fa", Value(12.0)); root_ctx.set_variable("$t", Value(0.0)); + root_ctx.set_constant("PI",Value(M_PI)); + Value zero3; zero3.type = Value::VECTOR; - zero3.vec.append(new Value(0.0)); - zero3.vec.append(new Value(0.0)); - zero3.vec.append(new Value(0.0)); + zero3.append(new Value(0.0)); + zero3.append(new Value(0.0)); + zero3.append(new Value(0.0)); root_ctx.set_variable("$vpt", zero3); root_ctx.set_variable("$vpr", zero3); @@ -180,8 +199,8 @@ MainWindow::MainWindow(const QString &filename) editor->setLineWrapping(true); // Not designable setFont("", 0); // Init default font - screen->statusLabel = new QLabel(this); - statusBar()->addWidget(screen->statusLabel); + this->glview->statusLabel = new QLabel(this); + statusBar()->addWidget(this->glview->statusLabel); animate_timer = new QTimer(this); connect(animate_timer, SIGNAL(timeout()), this, SLOT(updateTVal())); @@ -276,7 +295,7 @@ MainWindow::MainWindow(const QString &filename) this->viewActionOpenCSG->setVisible(false); #else connect(this->viewActionOpenCSG, SIGNAL(triggered()), this, SLOT(viewModeOpenCSG())); - if (!screen->hasOpenCSGSupport()) { + if (!this->glview->hasOpenCSGSupport()) { this->viewActionOpenCSG->setEnabled(false); } #endif @@ -323,6 +342,7 @@ MainWindow::MainWindow(const QString &filename) } else { setFileName(""); } + updateRecentFileActions(); connect(editor->document(), SIGNAL(contentsChanged()), this, SLOT(animateUpdateDocChanged())); #ifdef _QCODE_EDIT_ @@ -332,9 +352,9 @@ MainWindow::MainWindow(const QString &filename) connect(editor->document(), SIGNAL(modificationChanged(bool)), this, SLOT(setWindowModified(bool))); connect(editor->document(), SIGNAL(modificationChanged(bool)), fileActionSave, SLOT(setEnabled(bool))); #endif - connect(screen, SIGNAL(doAnimateUpdate()), this, SLOT(animateUpdate())); + connect(this->glview, SIGNAL(doAnimateUpdate()), this, SLOT(animateUpdate())); - connect(Preferences::inst(), SIGNAL(requestRedraw()), this->screen, SLOT(updateGL())); + connect(Preferences::inst(), SIGNAL(requestRedraw()), this->glview, SLOT(updateGL())); connect(Preferences::inst(), SIGNAL(fontChanged(const QString&,uint)), this, SLOT(setFont(const QString&,uint))); Preferences::inst()->apply(); @@ -474,6 +494,7 @@ MainWindow::openFile(const QString &new_filename) setFileName(new_filename); load(); + updateRecentFiles(); } void @@ -481,7 +502,7 @@ MainWindow::setFileName(const QString &filename) { if (filename.isEmpty()) { this->fileName.clear(); - this->root_ctx.document_path = currentdir; + this->root_ctx.setDocumentPath(currentdir.toStdString()); setWindowTitle("OpenSCAD - New Document[*]"); } else { @@ -493,21 +514,29 @@ MainWindow::setFileName(const QString &filename) QString infoFileName = fileinfo.absoluteFilePath(); if (!infoFileName.isEmpty()) { this->fileName = infoFileName; - QSettings settings; // already set up properly via main.cpp - QStringList files = settings.value("recentFileList").toStringList(); - files.removeAll(this->fileName); - files.prepend(this->fileName); - while (files.size() > maxRecentFiles) - files.removeLast(); - settings.setValue("recentFileList", files); } else { this->fileName = fileinfo.fileName(); } - this->root_ctx.document_path = fileinfo.dir().absolutePath(); + this->root_ctx.setDocumentPath(fileinfo.dir().absolutePath().toStdString()); QDir::setCurrent(fileinfo.dir().absolutePath()); } +} + +void MainWindow::updateRecentFiles() +{ + // Check that the canonical file path exists - only update recent files + // if it does. Should prevent empty list items on initial open etc. + QFileInfo fileinfo(this->fileName); + QString infoFileName = fileinfo.absoluteFilePath(); + QSettings settings; // already set up properly via main.cpp + QStringList files = settings.value("recentFileList").toStringList(); + files.removeAll(infoFileName); + files.prepend(infoFileName); + while (files.size() > maxRecentFiles) files.removeLast(); + settings.setValue("recentFileList", files); + foreach(QWidget *widget, QApplication::topLevelWidgets()) { MainWindow *mainWin = qobject_cast<MainWindow *>(widget); if (mainWin) { @@ -516,6 +545,7 @@ MainWindow::setFileName(const QString &filename) } } + void MainWindow::updatedFps() { bool fps_ok; @@ -564,7 +594,7 @@ void MainWindow::load() AbstractNode *MainWindow::find_root_tag(AbstractNode *n) { - foreach(AbstractNode *v, n->children) { + BOOST_FOREACH (AbstractNode *v, n->children) { if (v->modinst->tag_root) return v; if (AbstractNode *vroot = find_root_tag(v)) return vroot; } @@ -572,7 +602,7 @@ AbstractNode *MainWindow::find_root_tag(AbstractNode *n) } /*! - Parse and evaluate the design -> this->root_node + Parse and evaluate the design => this->root_node */ void MainWindow::compile(bool procevents) { @@ -581,7 +611,7 @@ void MainWindow::compile(bool procevents) QApplication::processEvents(); // Invalidate renderers before we kill the CSG tree - screen->setRenderer(NULL); + this->glview->setRenderer(NULL); if (this->opencsgRenderer) { delete this->opencsgRenderer; this->opencsgRenderer = NULL; @@ -592,80 +622,83 @@ void MainWindow::compile(bool procevents) } // Remove previous CSG tree - if (root_module) { - delete root_module; - root_module = NULL; + if (this->root_module) { + delete this->root_module; + this->root_module = NULL; } - if (absolute_root_node) { - delete absolute_root_node; - absolute_root_node = NULL; + if (this->absolute_root_node) { + delete this->absolute_root_node; + this->absolute_root_node = NULL; } - if (root_raw_term) { - root_raw_term->unlink(); - root_raw_term = NULL; + if (this->root_raw_term) { + this->root_raw_term->unlink(); + this->root_raw_term = NULL; } - if (root_norm_term) { - root_norm_term->unlink(); - root_norm_term = NULL; + if (this->root_norm_term) { + this->root_norm_term->unlink(); + this->root_norm_term = NULL; } - if (root_chain) { - delete root_chain; - root_chain = NULL; + if (this->root_chain) { + delete this->root_chain; + this->root_chain = NULL; } - foreach(CSGTerm *v, highlight_terms) { - v->unlink(); - } - highlight_terms.clear(); - if (highlights_chain) { - delete highlights_chain; - highlights_chain = NULL; - } - foreach(CSGTerm *v, background_terms) { - v->unlink(); - } - background_terms.clear(); - if (background_chain) { - delete background_chain; - background_chain = NULL; - } - root_node = NULL; + std::for_each(this->highlight_terms.begin(), this->highlight_terms.end(), + bind(&CSGTerm::unlink, _1)); + + this->highlight_terms.clear(); + delete this->highlights_chain; + this->highlights_chain = NULL; + + std::for_each(this->background_terms.begin(), this->background_terms.end(), + bind(&CSGTerm::unlink, _1)); + this->background_terms.clear(); + delete this->background_chain; + this->background_chain = NULL; + + this->root_node = NULL; + this->tree.setRoot(NULL); // Initialize special variables - root_ctx.set_variable("$t", Value(e_tval->text().toDouble())); + this->root_ctx.set_variable("$t", Value(e_tval->text().toDouble())); Value vpt; vpt.type = Value::VECTOR; - vpt.vec.append(new Value(-screen->object_trans_x)); - vpt.vec.append(new Value(-screen->object_trans_y)); - vpt.vec.append(new Value(-screen->object_trans_z)); - root_ctx.set_variable("$vpt", vpt); + vpt.append(new Value(-this->glview->object_trans_x)); + vpt.append(new Value(-this->glview->object_trans_y)); + vpt.append(new Value(-this->glview->object_trans_z)); + this->root_ctx.set_variable("$vpt", vpt); Value vpr; vpr.type = Value::VECTOR; - vpr.vec.append(new Value(fmodf(360 - screen->object_rot_x + 90, 360))); - vpr.vec.append(new Value(fmodf(360 - screen->object_rot_y, 360))); - vpr.vec.append(new Value(fmodf(360 - screen->object_rot_z, 360))); + vpr.append(new Value(fmodf(360 - this->glview->object_rot_x + 90, 360))); + vpr.append(new Value(fmodf(360 - this->glview->object_rot_y, 360))); + vpr.append(new Value(fmodf(360 - this->glview->object_rot_z, 360))); root_ctx.set_variable("$vpr", vpr); // Parse - last_compiled_doc = editor->toPlainText(); - root_module = parse((last_compiled_doc + "\n" + commandline_commands).toAscii().data(), this->fileName.isEmpty() ? "" : QFileInfo(this->fileName).absolutePath().toLocal8Bit(), false); + this->last_compiled_doc = editor->toPlainText(); + this->root_module = parse((this->last_compiled_doc + "\n" + + QString::fromStdString(commandline_commands)).toAscii().data(), + this->fileName.isEmpty() ? + "" : + QFileInfo(this->fileName).absolutePath().toLocal8Bit(), + false); // Error highlighting - if (highlighter) { - delete highlighter; - highlighter = NULL; + if (this->highlighter) { + delete this->highlighter; + this->highlighter = NULL; } if (parser_error_pos >= 0) { - highlighter = new Highlighter(editor->document()); + this->highlighter = new Highlighter(editor->document()); } - if (!root_module) { + if (!this->root_module) { if (!animate_panel->isVisible()) { #ifdef _QCODE_EDIT_ QDocumentCursor cursor = editor->cursor(); @@ -685,19 +718,23 @@ void MainWindow::compile(bool procevents) QApplication::processEvents(); AbstractNode::resetIndexCounter(); - root_inst = ModuleInstantiation(); - absolute_root_node = root_module->evaluate(&root_ctx, &root_inst); + this->root_inst = ModuleInstantiation(); + this->absolute_root_node = this->root_module->evaluate(&this->root_ctx, &this->root_inst); - if (!absolute_root_node) + if (!this->absolute_root_node) goto fail; // Do we have an explicit root node (! modifier)? - if (!(this->root_node = find_root_tag(absolute_root_node))) { - this->root_node = absolute_root_node; + if (!(this->root_node = find_root_tag(this->absolute_root_node))) { + this->root_node = this->absolute_root_node; } - root_node->dump(""); + // FIXME: Consider giving away ownership of root_node to the Tree, or use reference counted pointers + this->tree.setRoot(this->root_node); + // Dump the tree (to initialize caches). + // FIXME: We shouldn't really need to do this explicitly.. + this->tree.getString(*this->root_node); - if (1) { + if (1) { PRINT("Compilation finished."); if (procevents) QApplication::processEvents(); @@ -706,18 +743,7 @@ fail: if (parser_error_pos < 0) { PRINT("ERROR: Compilation failed! (no top level object found)"); } else { - int line = 1; - QByteArray pb = last_compiled_doc.toAscii(); - char *p = pb.data(); - for (int i = 0; i < parser_error_pos; i++) { - if (p[i] == '\n') - line++; - if (p[i] == 0) { - line = -1; - break; - } - } - PRINTF("ERROR: Compilation failed! (parser error in line %d)", line); + PRINT("ERROR: Compilation failed!"); } if (procevents) QApplication::processEvents(); @@ -735,13 +761,6 @@ void MainWindow::compileCSG(bool procevents) if (procevents) QApplication::processEvents(); - double m[20]; - - for (int i = 0; i < 16; i++) - m[i] = i % 5 == 0 ? 1.0 : 0.0; - for (int i = 16; i < 20; i++) - m[i] = -1; - // Main CSG evaluation QTime t; t.start(); @@ -762,12 +781,17 @@ void MainWindow::compileCSG(bool procevents) progress_report_prep(root_node, report_func, pd); try { - root_raw_term = root_node->render_csg_term(m, &highlight_terms, &background_terms); + CGALEvaluator cgalevaluator(this->tree); + PolySetCGALEvaluator psevaluator(cgalevaluator); + CSGTermEvaluator csgrenderer(this->tree, &psevaluator); + root_raw_term = csgrenderer.evaluateCSGTerm(*root_node, highlight_terms, background_terms); if (!root_raw_term) { PRINT("ERROR: CSG generation failed! (no top level object found)"); if (procevents) QApplication::processEvents(); } + PolySetCache::instance()->print(); + CGALCache::instance()->print(); } catch (ProgressCancelException e) { PRINT("CSG generation cancelled."); @@ -801,12 +825,12 @@ void MainWindow::compileCSG(bool procevents) if (highlight_terms.size() > 0) { - PRINTF("Compiling highlights (%d CSG Trees)...", highlight_terms.size()); + PRINTF("Compiling highlights (%zu CSG Trees)...", highlight_terms.size()); if (procevents) QApplication::processEvents(); highlights_chain = new CSGChain(); - for (int i = 0; i < highlight_terms.size(); i++) { + for (unsigned int i = 0; i < highlight_terms.size(); i++) { while (1) { CSGTerm *n = highlight_terms[i]->normalize(); highlight_terms[i]->unlink(); @@ -820,12 +844,12 @@ void MainWindow::compileCSG(bool procevents) if (background_terms.size() > 0) { - PRINTF("Compiling background (%d CSG Trees)...", background_terms.size()); + PRINTF("Compiling background (%zu CSG Trees)...", background_terms.size()); if (procevents) QApplication::processEvents(); background_chain = new CSGChain(); - for (int i = 0; i < background_terms.size(); i++) { + for (unsigned int i = 0; i < background_terms.size(); i++) { while (1) { CSGTerm *n = background_terms[i]->normalize(); background_terms[i]->unlink(); @@ -842,10 +866,11 @@ void MainWindow::compileCSG(bool procevents) PRINTF("WARNING: OpenCSG rendering has been disabled."); } else { + PRINTF("Normalized CSG tree has %d elements", root_chain->polysets.size()); this->opencsgRenderer = new OpenCSGRenderer(this->root_chain, this->highlights_chain, this->background_chain, - this->screen->shaderinfo); + this->glview->shaderinfo); } this->thrownTogetherRenderer = new ThrownTogetherRenderer(this->root_chain, this->highlights_chain, @@ -876,7 +901,9 @@ void MainWindow::actionOpen() { QString new_filename = QFileDialog::getOpenFileName(this, "Open File", "", "OpenSCAD Designs (*.scad)"); #ifdef ENABLE_MDI - new MainWindow(new_filename); + if (!new_filename.isEmpty()) { + new MainWindow(new_filename); + } #else if (!new_filename.isEmpty()) { if (!maybeSave()) @@ -974,6 +1001,7 @@ void MainWindow::actionSave() this->editor->setContentModified(false); } clearCurrentOutput(); + updateRecentFiles(); } } @@ -1027,7 +1055,7 @@ void MainWindow::pasteViewportTranslation() QTextCursor cursor = editor->textCursor(); #endif QString txt; - txt.sprintf("[ %.2f, %.2f, %.2f ]", -screen->object_trans_x, -screen->object_trans_y, -screen->object_trans_z); + txt.sprintf("[ %.2f, %.2f, %.2f ]", -this->glview->object_trans_x, -this->glview->object_trans_y, -this->glview->object_trans_z); cursor.insertText(txt); } @@ -1040,7 +1068,7 @@ void MainWindow::pasteViewportRotation() #endif QString txt; txt.sprintf("[ %.2f, %.2f, %.2f ]", - fmodf(360 - screen->object_rot_x + 90, 360), fmodf(360 - screen->object_rot_y, 360), fmodf(360 - screen->object_rot_z, 360)); + fmodf(360 - this->glview->object_rot_x + 90, 360), fmodf(360 - this->glview->object_rot_y, 360), fmodf(360 - this->glview->object_rot_z, 360)); cursor.insertText(txt); } @@ -1084,6 +1112,9 @@ bool MainWindow::checkModified() void MainWindow::actionReloadCompile() { + if (GuiLocker::isLocked()) return; + GuiLocker lock; + if (!checkModified()) return; console->clear(); @@ -1111,6 +1142,9 @@ void MainWindow::actionReloadCompile() void MainWindow::actionCompile() { + if (GuiLocker::isLocked()) return; + GuiLocker lock; + setCurrentOutput(); console->clear(); @@ -1130,7 +1164,7 @@ void MainWindow::actionCompile() } if (viewActionAnimate->isChecked() && e_dump->isChecked()) { - QImage img = screen->grabFrameBuffer(); + QImage img = this->glview->grabFrameBuffer(); QString filename; double s = e_fsteps->text().toDouble(); double t = e_tval->text().toDouble(); @@ -1145,15 +1179,19 @@ void MainWindow::actionCompile() void MainWindow::actionRenderCGAL() { + if (GuiLocker::isLocked()) return; + GuiLocker lock; + setCurrentOutput(); console->clear(); compile(true); - if (!root_module || !root_node) + if (!this->root_module || !this->root_node) { return; + } - this->screen->setRenderer(NULL); + this->glview->setRenderer(NULL); delete this->cgalRenderer; this->cgalRenderer = NULL; if (this->root_N) { @@ -1183,9 +1221,12 @@ void MainWindow::actionRenderCGAL() QApplication::processEvents(); - progress_report_prep(root_node, report_func, pd); + progress_report_prep(this->root_node, report_func, pd); try { - this->root_N = new CGAL_Nef_polyhedron(root_node->render_cgal_nef_polyhedron()); + CGALEvaluator evaluator(this->tree); + this->root_N = new CGAL_Nef_polyhedron(evaluator.evaluateCGALMesh(*this->root_node)); + PolySetCache::instance()->print(); + CGALCache::instance()->print(); } catch (ProgressCancelException e) { PRINT("Rendering cancelled."); @@ -1194,64 +1235,70 @@ void MainWindow::actionRenderCGAL() if (this->root_N) { - PRINTF("Number of vertices currently in CGAL cache: %d", AbstractNode::cgal_nef_cache.totalCost()); - PRINTF("Number of objects currently in CGAL cache: %d", AbstractNode::cgal_nef_cache.size()); + // FIXME: Reenable cache cost info +// PRINTF("Number of vertices currently in CGAL cache: %d", AbstractNode::cgal_nef_cache.totalCost()); +// PRINTF("Number of objects currently in CGAL cache: %d", AbstractNode::cgal_nef_cache.size()); QApplication::processEvents(); if (this->root_N->dim == 2) { PRINTF(" Top level object is a 2D object:"); QApplication::processEvents(); - PRINTF(" Empty: %6s", this->root_N->p2.is_empty() ? "yes" : "no"); + PRINTF(" Empty: %6s", this->root_N->p2->is_empty() ? "yes" : "no"); QApplication::processEvents(); - PRINTF(" Plane: %6s", this->root_N->p2.is_plane() ? "yes" : "no"); + PRINTF(" Plane: %6s", this->root_N->p2->is_plane() ? "yes" : "no"); QApplication::processEvents(); - PRINTF(" Vertices: %6d", (int)this->root_N->p2.explorer().number_of_vertices()); + PRINTF(" Vertices: %6d", (int)this->root_N->p2->explorer().number_of_vertices()); QApplication::processEvents(); - PRINTF(" Halfedges: %6d", (int)this->root_N->p2.explorer().number_of_halfedges()); + PRINTF(" Halfedges: %6d", (int)this->root_N->p2->explorer().number_of_halfedges()); QApplication::processEvents(); - PRINTF(" Edges: %6d", (int)this->root_N->p2.explorer().number_of_edges()); + PRINTF(" Edges: %6d", (int)this->root_N->p2->explorer().number_of_edges()); QApplication::processEvents(); - PRINTF(" Faces: %6d", (int)this->root_N->p2.explorer().number_of_faces()); + PRINTF(" Faces: %6d", (int)this->root_N->p2->explorer().number_of_faces()); QApplication::processEvents(); - PRINTF(" FaceCycles: %6d", (int)this->root_N->p2.explorer().number_of_face_cycles()); + PRINTF(" FaceCycles: %6d", (int)this->root_N->p2->explorer().number_of_face_cycles()); QApplication::processEvents(); - PRINTF(" ConnComp: %6d", (int)this->root_N->p2.explorer().number_of_connected_components()); + PRINTF(" ConnComp: %6d", (int)this->root_N->p2->explorer().number_of_connected_components()); QApplication::processEvents(); } if (this->root_N->dim == 3) { PRINTF(" Top level object is a 3D object:"); - PRINTF(" Simple: %6s", this->root_N->p3.is_simple() ? "yes" : "no"); + PRINTF(" Simple: %6s", this->root_N->p3->is_simple() ? "yes" : "no"); QApplication::processEvents(); - PRINTF(" Valid: %6s", this->root_N->p3.is_valid() ? "yes" : "no"); + PRINTF(" Valid: %6s", this->root_N->p3->is_valid() ? "yes" : "no"); QApplication::processEvents(); - PRINTF(" Vertices: %6d", (int)this->root_N->p3.number_of_vertices()); + PRINTF(" Vertices: %6d", (int)this->root_N->p3->number_of_vertices()); QApplication::processEvents(); - PRINTF(" Halfedges: %6d", (int)this->root_N->p3.number_of_halfedges()); + PRINTF(" Halfedges: %6d", (int)this->root_N->p3->number_of_halfedges()); QApplication::processEvents(); - PRINTF(" Edges: %6d", (int)this->root_N->p3.number_of_edges()); + PRINTF(" Edges: %6d", (int)this->root_N->p3->number_of_edges()); QApplication::processEvents(); - PRINTF(" Halffacets: %6d", (int)this->root_N->p3.number_of_halffacets()); + PRINTF(" Halffacets: %6d", (int)this->root_N->p3->number_of_halffacets()); QApplication::processEvents(); - PRINTF(" Facets: %6d", (int)this->root_N->p3.number_of_facets()); + PRINTF(" Facets: %6d", (int)this->root_N->p3->number_of_facets()); QApplication::processEvents(); - PRINTF(" Volumes: %6d", (int)this->root_N->p3.number_of_volumes()); + PRINTF(" Volumes: %6d", (int)this->root_N->p3->number_of_volumes()); QApplication::processEvents(); } int s = t.elapsed() / 1000; PRINTF("Total rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60); - this->cgalRenderer = new CGALRenderer(*this->root_N); - // Go to CGAL view mode - if (viewActionCGALGrid->isChecked()) { - viewModeCGALGrid(); + if (!this->root_N->empty()) { + this->cgalRenderer = new CGALRenderer(*this->root_N); + // Go to CGAL view mode + if (viewActionCGALGrid->isChecked()) { + viewModeCGALGrid(); + } + else { + viewModeCGALSurface(); + } + + PRINT("Rendering finished."); } else { - viewModeCGALSurface(); + PRINT("WARNING: No top level geometry to render"); } - - PRINT("Rendering finished."); } #ifdef USE_PROGRESSWIDGET @@ -1272,7 +1319,7 @@ void MainWindow::actionDisplayAST() e->setWindowTitle("AST Dump"); e->setReadOnly(true); if (root_module) { - e->setPlainText(root_module->dump("", "")); + e->setPlainText(QString::fromStdString(root_module->dump("", ""))); } else { e->setPlainText("No AST to dump. Please try compiling first..."); } @@ -1289,8 +1336,8 @@ void MainWindow::actionDisplayCSGTree() e->setTabStopWidth(30); e->setWindowTitle("CSG Tree Dump"); e->setReadOnly(true); - if (root_node) { - e->setPlainText(root_node->dump("")); + if (this->root_node) { + e->setPlainText(QString::fromStdString(this->tree.getString(*this->root_node))); } else { e->setPlainText("No CSG to dump. Please try compiling first..."); } @@ -1307,7 +1354,7 @@ void MainWindow::actionDisplayCSGProducts() e->setTabStopWidth(30); e->setWindowTitle("CSG Products Dump"); e->setReadOnly(true); - e->setPlainText(QString("\nCSG before normalization:\n%1\n\n\nCSG after normalization:\n%2\n\n\nCSG rendering chain:\n%3\n\n\nHighlights CSG rendering chain:\n%4\n\n\nBackground CSG rendering chain:\n%5\n").arg(root_raw_term ? root_raw_term->dump() : "N/A", root_norm_term ? root_norm_term->dump() : "N/A", root_chain ? root_chain->dump() : "N/A", highlights_chain ? highlights_chain->dump() : "N/A", background_chain ? background_chain->dump() : "N/A")); + e->setPlainText(QString("\nCSG before normalization:\n%1\n\n\nCSG after normalization:\n%2\n\n\nCSG rendering chain:\n%3\n\n\nHighlights CSG rendering chain:\n%4\n\n\nBackground CSG rendering chain:\n%5\n").arg(root_raw_term ? QString::fromStdString(root_raw_term->dump()) : "N/A", root_norm_term ? QString::fromStdString(root_norm_term->dump()) : "N/A", root_chain ? QString::fromStdString(root_chain->dump()) : "N/A", highlights_chain ? QString::fromStdString(highlights_chain->dump()) : "N/A", background_chain ? QString::fromStdString(background_chain->dump()) : "N/A")); e->show(); e->resize(600, 400); clearCurrentOutput(); @@ -1319,6 +1366,8 @@ void MainWindow::actionExportSTLorOFF(bool stl_mode) void MainWindow::actionExportSTLorOFF(bool) #endif { + if (GuiLocker::isLocked()) return; + GuiLocker lock; #ifdef ENABLE_CGAL setCurrentOutput(); @@ -1334,14 +1383,16 @@ void MainWindow::actionExportSTLorOFF(bool) return; } - if (!this->root_N->p3.is_simple()) { + if (!this->root_N->p3->is_simple()) { PRINT("Object isn't a valid 2-manifold! Modify your design.."); clearCurrentOutput(); return; } + QString suffix = stl_mode ? ".stl" : ".off"; QString stl_filename = QFileDialog::getSaveFileName(this, - stl_mode ? "Export STL File" : "Export OFF File", "", + stl_mode ? "Export STL File" : "Export OFF File", + this->fileName.isEmpty() ? "Untitled"+suffix : QFileInfo(this->fileName).baseName()+suffix, stl_mode ? "STL Files (*.stl)" : "OFF Files (*.off)"); if (stl_filename.isEmpty()) { PRINTF("No filename specified. %s export aborted.", stl_mode ? "STL" : "OFF"); @@ -1351,19 +1402,23 @@ void MainWindow::actionExportSTLorOFF(bool) QProgressDialog *pd = new QProgressDialog( stl_mode ? "Exporting object to STL file..." : "Exporting object to OFF file...", - QString(), 0, this->root_N->p3.number_of_facets() + 1); + QString(), 0, this->root_N->p3->number_of_facets() + 1); pd->setValue(0); pd->setAutoClose(false); pd->show(); QApplication::processEvents(); - if (stl_mode) - export_stl(this->root_N, stl_filename, pd); - else - export_off(this->root_N, stl_filename, pd); - - PRINTF("%s export finished.", stl_mode ? "STL" : "OFF"); + std::ofstream fstream(stl_filename.toUtf8()); + if (!fstream.is_open()) { + PRINTA("Can't open file \"%1\" for export", stl_filename); + } + else { + if (stl_mode) export_stl(this->root_N, fstream, pd); + else export_off(this->root_N, fstream, pd); + fstream.close(); + PRINTF("%s export finished.", stl_mode ? "STL" : "OFF"); + } delete pd; clearCurrentOutput(); @@ -1397,16 +1452,25 @@ void MainWindow::actionExportDXF() return; } - QString stl_filename = QFileDialog::getSaveFileName(this, - "Export DXF File", "", "DXF Files (*.dxf)"); - if (stl_filename.isEmpty()) { + QString dxf_filename = QFileDialog::getSaveFileName(this, + "Export DXF File", + this->fileName.isEmpty() ? "Untitled.dxf" : QFileInfo(this->fileName).baseName()+".dxf", + "DXF Files (*.dxf)"); + if (dxf_filename.isEmpty()) { PRINTF("No filename specified. DXF export aborted."); clearCurrentOutput(); return; } - export_dxf(this->root_N, stl_filename, NULL); - PRINTF("DXF export finished."); + std::ofstream fstream(dxf_filename.toUtf8()); + if (!fstream.is_open()) { + PRINTA("Can't open file \"%s\" for export", dxf_filename); + } + else { + export_dxf(this->root_N, fstream, NULL); + fstream.close(); + PRINTF("DXF export finished."); + } clearCurrentOutput(); #endif /* ENABLE_CGAL */ @@ -1414,7 +1478,7 @@ void MainWindow::actionExportDXF() void MainWindow::actionExportImage() { - QImage img = screen->grabFrameBuffer(); + QImage img = this->glview->grabFrameBuffer(); setCurrentOutput(); QString img_filename = QFileDialog::getSaveFileName(this, @@ -1432,9 +1496,9 @@ void MainWindow::actionExportImage() void MainWindow::actionFlushCaches() { - PolySet::ps_cache.clear(); + PolySetCache::instance()->clear(); #ifdef ENABLE_CGAL - AbstractNode::cgal_nef_cache.clear(); + CGALCache::instance()->clear(); #endif dxf_dim_cache.clear(); dxf_cross_cache.clear(); @@ -1459,10 +1523,10 @@ void MainWindow::viewModeActionsUncheck() */ void MainWindow::viewModeOpenCSG() { - if (screen->hasOpenCSGSupport()) { + if (this->glview->hasOpenCSGSupport()) { viewModeActionsUncheck(); viewActionOpenCSG->setChecked(true); - screen->setRenderer(this->opencsgRenderer ? (Renderer *)this->opencsgRenderer : (Renderer *)this->thrownTogetherRenderer); + this->glview->setRenderer(this->opencsgRenderer ? (Renderer *)this->opencsgRenderer : (Renderer *)this->thrownTogetherRenderer); } else { viewModeThrownTogether(); } @@ -1476,17 +1540,17 @@ void MainWindow::viewModeCGALSurface() { viewModeActionsUncheck(); viewActionCGALSurfaces->setChecked(true); - screen->setShowFaces(true); - screen->setRenderer(this->cgalRenderer); - screen->updateGL(); + this->glview->setShowFaces(true); + this->glview->setRenderer(this->cgalRenderer); + this->glview->updateGL(); } void MainWindow::viewModeCGALGrid() { viewModeActionsUncheck(); viewActionCGALGrid->setChecked(true); - screen->setShowFaces(false); - screen->setRenderer(this->cgalRenderer); + this->glview->setShowFaces(false); + this->glview->setRenderer(this->cgalRenderer); } #endif /* ENABLE_CGAL */ @@ -1495,31 +1559,31 @@ void MainWindow::viewModeThrownTogether() { viewModeActionsUncheck(); viewActionThrownTogether->setChecked(true); - screen->setRenderer(this->thrownTogetherRenderer); + this->glview->setRenderer(this->thrownTogetherRenderer); } void MainWindow::viewModeShowEdges() { QSettings settings; settings.setValue("view/showEdges",viewActionShowEdges->isChecked()); - screen->setShowEdges(viewActionShowEdges->isChecked()); - screen->updateGL(); + this->glview->setShowEdges(viewActionShowEdges->isChecked()); + this->glview->updateGL(); } void MainWindow::viewModeShowAxes() { QSettings settings; settings.setValue("view/showAxes",viewActionShowAxes->isChecked()); - screen->setShowAxes(viewActionShowAxes->isChecked()); - screen->updateGL(); + this->glview->setShowAxes(viewActionShowAxes->isChecked()); + this->glview->updateGL(); } void MainWindow::viewModeShowCrosshairs() { QSettings settings; settings.setValue("view/showCrosshairs",viewActionShowCrosshairs->isChecked()); - screen->setShowCrosshairs(viewActionShowCrosshairs->isChecked()); - screen->updateGL(); + this->glview->setShowCrosshairs(viewActionShowCrosshairs->isChecked()); + this->glview->updateGL(); } void MainWindow::viewModeAnimate() @@ -1557,66 +1621,66 @@ void MainWindow::animateUpdate() void MainWindow::viewAngleTop() { - screen->object_rot_x = 90; - screen->object_rot_y = 0; - screen->object_rot_z = 0; - screen->updateGL(); + this->glview->object_rot_x = 90; + this->glview->object_rot_y = 0; + this->glview->object_rot_z = 0; + this->glview->updateGL(); } void MainWindow::viewAngleBottom() { - screen->object_rot_x = 270; - screen->object_rot_y = 0; - screen->object_rot_z = 0; - screen->updateGL(); + this->glview->object_rot_x = 270; + this->glview->object_rot_y = 0; + this->glview->object_rot_z = 0; + this->glview->updateGL(); } void MainWindow::viewAngleLeft() { - screen->object_rot_x = 0; - screen->object_rot_y = 0; - screen->object_rot_z = 90; - screen->updateGL(); + this->glview->object_rot_x = 0; + this->glview->object_rot_y = 0; + this->glview->object_rot_z = 90; + this->glview->updateGL(); } void MainWindow::viewAngleRight() { - screen->object_rot_x = 0; - screen->object_rot_y = 0; - screen->object_rot_z = 270; - screen->updateGL(); + this->glview->object_rot_x = 0; + this->glview->object_rot_y = 0; + this->glview->object_rot_z = 270; + this->glview->updateGL(); } void MainWindow::viewAngleFront() { - screen->object_rot_x = 0; - screen->object_rot_y = 0; - screen->object_rot_z = 0; - screen->updateGL(); + this->glview->object_rot_x = 0; + this->glview->object_rot_y = 0; + this->glview->object_rot_z = 0; + this->glview->updateGL(); } void MainWindow::viewAngleBack() { - screen->object_rot_x = 0; - screen->object_rot_y = 0; - screen->object_rot_z = 180; - screen->updateGL(); + this->glview->object_rot_x = 0; + this->glview->object_rot_y = 0; + this->glview->object_rot_z = 180; + this->glview->updateGL(); } void MainWindow::viewAngleDiagonal() { - screen->object_rot_x = 35; - screen->object_rot_y = 0; - screen->object_rot_z = 25; - screen->updateGL(); + this->glview->object_rot_x = 35; + this->glview->object_rot_y = 0; + this->glview->object_rot_z = -25; + this->glview->updateGL(); } void MainWindow::viewCenter() { - screen->object_trans_x = 0; - screen->object_trans_y = 0; - screen->object_trans_z = 0; - screen->updateGL(); + this->glview->object_trans_x = 0; + this->glview->object_trans_y = 0; + this->glview->object_trans_z = 0; + this->glview->updateGL(); } void MainWindow::viewPerspective() @@ -1625,8 +1689,8 @@ void MainWindow::viewPerspective() settings.setValue("view/orthogonalProjection",false); viewActionPerspective->setChecked(true); viewActionOrthogonal->setChecked(false); - screen->setOrthoMode(false); - screen->updateGL(); + this->glview->setOrthoMode(false); + this->glview->updateGL(); } void MainWindow::viewOrthogonal() @@ -1635,8 +1699,8 @@ void MainWindow::viewOrthogonal() settings.setValue("view/orthogonalProjection",true); viewActionPerspective->setChecked(false); viewActionOrthogonal->setChecked(true); - screen->setOrthoMode(true); - screen->updateGL(); + this->glview->setOrthoMode(true); + this->glview->updateGL(); } void MainWindow::hideConsole() |