summaryrefslogtreecommitdiff
path: root/src/mainwin.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/mainwin.cc')
-rw-r--r--src/mainwin.cc161
1 files changed, 86 insertions, 75 deletions
diff --git a/src/mainwin.cc b/src/mainwin.cc
index 89d17c5..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"
@@ -46,8 +47,6 @@
#ifdef USE_PROGRESSWIDGET
#include "ProgressWidget.h"
#endif
-#include "CGALEvaluator.h"
-#include "PolySetCGALEvaluator.h"
#include "ThrownTogetherRenderer.h"
#include <QMenu>
@@ -77,14 +76,22 @@
#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
@@ -335,6 +342,7 @@ MainWindow::MainWindow(const QString &filename)
} else {
setFileName("");
}
+ updateRecentFileActions();
connect(editor->document(), SIGNAL(contentsChanged()), this, SLOT(animateUpdateDocChanged()));
#ifdef _QCODE_EDIT_
@@ -486,6 +494,7 @@ MainWindow::openFile(const QString &new_filename)
setFileName(new_filename);
load();
+ updateRecentFiles();
}
void
@@ -493,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 {
@@ -505,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) {
@@ -528,6 +545,7 @@ MainWindow::setFileName(const QString &filename)
}
}
+
void MainWindow::updatedFps()
{
bool fps_ok;
@@ -576,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;
}
@@ -665,7 +683,7 @@ void MainWindow::compile(bool procevents)
// Parse
this->last_compiled_doc = editor->toPlainText();
this->root_module = parse((this->last_compiled_doc + "\n" +
- commandline_commands).toAscii().data(),
+ QString::fromStdString(commandline_commands)).toAscii().data(),
this->fileName.isEmpty() ?
"" :
QFileInfo(this->fileName).absolutePath().toLocal8Bit(),
@@ -725,18 +743,7 @@ fail:
if (parser_error_pos < 0) {
PRINT("ERROR: Compilation failed! (no top level object found)");
} else {
- int line = 1;
- QByteArray pb = this->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();
@@ -774,9 +781,7 @@ void MainWindow::compileCSG(bool procevents)
progress_report_prep(root_node, report_func, pd);
try {
- // FIXME: put cache somewhere else as it's pretty useless now
- QHash<std::string, CGAL_Nef_polyhedron> cache;
- CGALEvaluator cgalevaluator(cache, this->tree);
+ CGALEvaluator cgalevaluator(this->tree);
PolySetCGALEvaluator psevaluator(cgalevaluator);
CSGTermEvaluator csgrenderer(this->tree, &psevaluator);
root_raw_term = csgrenderer.evaluateCSGTerm(*root_node, highlight_terms, background_terms);
@@ -785,6 +790,8 @@ void MainWindow::compileCSG(bool procevents)
if (procevents)
QApplication::processEvents();
}
+ PolySetCache::instance()->print();
+ CGALCache::instance()->print();
}
catch (ProgressCancelException e) {
PRINT("CSG generation cancelled.");
@@ -859,6 +866,7 @@ 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,
@@ -893,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())
@@ -991,6 +1001,7 @@ void MainWindow::actionSave()
this->editor->setContentModified(false);
}
clearCurrentOutput();
+ updateRecentFiles();
}
}
@@ -1212,10 +1223,10 @@ void MainWindow::actionRenderCGAL()
progress_report_prep(this->root_node, report_func, pd);
try {
- // FIXME: put cache somewhere else as it's pretty useless now
- QHash<std::string, CGAL_Nef_polyhedron> cache;
- CGALEvaluator evaluator(cache, this->tree);
+ 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.");
@@ -1232,57 +1243,62 @@ void MainWindow::actionRenderCGAL()
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
@@ -1303,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...");
}
@@ -1338,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();
@@ -1367,7 +1383,7 @@ 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;
@@ -1386,21 +1402,20 @@ 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();
- QFile file(stl_filename);
- if (!file.open(QIODevice::ReadWrite)) {
+ std::ofstream fstream(stl_filename.toUtf8());
+ if (!fstream.is_open()) {
PRINTA("Can't open file \"%1\" for export", stl_filename);
}
else {
- QTextStream fstream(&file);
if (stl_mode) export_stl(this->root_N, fstream, pd);
else export_off(this->root_N, fstream, pd);
- file.close();
+ fstream.close();
PRINTF("%s export finished.", stl_mode ? "STL" : "OFF");
}
@@ -1447,14 +1462,13 @@ void MainWindow::actionExportDXF()
return;
}
- QFile file(dxf_filename);
- if (!file.open(QIODevice::ReadWrite)) {
- PRINTA("Can't open file \"%1\" for export", dxf_filename);
+ std::ofstream fstream(dxf_filename.toUtf8());
+ if (!fstream.is_open()) {
+ PRINTA("Can't open file \"%s\" for export", dxf_filename);
}
else {
- QTextStream fstream(&file);
export_dxf(this->root_N, fstream, NULL);
- file.close();
+ fstream.close();
PRINTF("DXF export finished.");
}
@@ -1482,12 +1496,9 @@ void MainWindow::actionExportImage()
void MainWindow::actionFlushCaches()
{
-// FIXME: Polycache -> PolySetEvaluator
-// FIXME: PolySetEvaluator->clearCache();
+ PolySetCache::instance()->clear();
#ifdef ENABLE_CGAL
-// FIXME: Flush caches through whatever channels we have
- // CGALEvaluator::evaluator()->getCache().clear();
- // this->dumper->clearCache();
+ CGALCache::instance()->clear();
#endif
dxf_dim_cache.clear();
dxf_cross_cache.clear();
@@ -1660,7 +1671,7 @@ void MainWindow::viewAngleDiagonal()
{
this->glview->object_rot_x = 35;
this->glview->object_rot_y = 0;
- this->glview->object_rot_z = 25;
+ this->glview->object_rot_z = -25;
this->glview->updateGL();
}
contact: Jan Huwald // Impressum