diff options
-rw-r--r-- | RELEASE_NOTES | 19 | ||||
-rw-r--r-- | cgal.pri | 2 | ||||
-rw-r--r-- | doc/TODO.txt | 5 | ||||
-rw-r--r-- | doc/release-checklist.txt | 9 | ||||
-rw-r--r-- | flex.pri | 2 | ||||
-rw-r--r-- | scripts/installer.nsi | 30 | ||||
-rwxr-xr-x | scripts/macosx-build-dependencies.sh | 4 | ||||
-rwxr-xr-x | scripts/publish-macosx.sh | 2 | ||||
-rwxr-xr-x | scripts/release-linux.sh | 2 | ||||
-rw-r--r-- | src/MainWindow.h | 3 | ||||
-rw-r--r-- | src/MainWindow.ui | 8 | ||||
-rw-r--r-- | src/Preferences.cc | 16 | ||||
-rw-r--r-- | src/Preferences.h | 1 | ||||
-rw-r--r-- | src/Preferences.ui | 56 | ||||
-rw-r--r-- | src/cgaladv_minkowski2.cc | 2 | ||||
-rw-r--r-- | src/export.cc | 53 | ||||
-rw-r--r-- | src/glview.cc | 52 | ||||
-rw-r--r-- | src/mainwin.cc | 127 | ||||
-rw-r--r-- | src/primitives.cc | 17 | ||||
-rw-r--r-- | src/transform.cc | 49 | ||||
-rw-r--r-- | testdata/scad/non-aff-matrix.scad | 6 | ||||
-rw-r--r-- | testdata/scad/testcolornames.scad | 159 |
22 files changed, 507 insertions, 117 deletions
diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 81bf603..5364e0a 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -1,3 +1,22 @@ +OpenSCAD 20xx.yy +================ + + +OpenSCAD 2011.06 +================ + +o Added "Export as Image" menu. + +Bugfixes: +o Cylinder tesselation broke existing models which are using cylinders + for e.g. captured nut slots and are dependent on the orientation not + changing. +o DXF output couldn't be imported into e.g. AutoCAD and Solidworks after updating + to using the AutoCAD 2000 (AC1015) format. Reverted to the old entity-only output, + causing LWPOLYLINES to not exported allowed anymore. + + + OpenSCAD 2011.04 ================ @@ -14,7 +14,7 @@ cgal { } win32 { - LIBS += $$CGAL_DIR/auxiliary/gmp/lib/libmpfr-4.lib -lCGAL-vc90-mt-gd + LIBS += $$CGAL_DIR/auxiliary/gmp/lib/libmpfr-4.lib -lCGAL-vc90-mt-s } else { LIBS += -lgmp -lmpfr -lCGAL } diff --git a/doc/TODO.txt b/doc/TODO.txt index 7612d86..c0772f6 100644 --- a/doc/TODO.txt +++ b/doc/TODO.txt @@ -5,6 +5,7 @@ o Some invalid DXF data gets pass the import checks and breaks the tessing code o Tesselation via GLU sometimes produces strange results o Export STL: Exports existing CGAL model even though the current model is changed, but not CGAL rendered o Look into the polygon winding and rotate_extrude() problem reported by Britton +o CGAL Aff_transformation_3 doesn't support non-affine transformations (non-aff-matrix.scad) STL Import BUGS --------------- @@ -148,7 +149,7 @@ o Language Frontend - Rethink for vs. intersection_for vs. group. Should for loops generate child lists instead, and make these passable to other modules or accessible by child()? - - constants: PI + - constants: PI, OpenSCAD version o DXF Import/Export - Use dxflib from RibbonSoft for import/export? -> investigate - Import @@ -161,7 +162,6 @@ o Mesh optimization on STL export - Remove super small triangles (all sides are short) - Replace super thin triangles (one h is short) o Misc - - Add symbolic colors to the color() statement - When specifying a transparency with the color() statement, the object is not sorted and will be rendered wrongly - Go through default values of parameters (e.g. cube() has x,y,z=1 while linear_extrude() has height=100) @@ -230,6 +230,7 @@ o Collect "all" available OpenSCAD scripts from the internets and run the integr tests on them all o dumptest tests: - filename are dumped as absolute filenames - this will fail on other systems +o Write a regression test for the hexagonal cylinder orientation issue INFRASTRUCTURE -------------- diff --git a/doc/release-checklist.txt b/doc/release-checklist.txt index 45e84fb..a455ca9 100644 --- a/doc/release-checklist.txt +++ b/doc/release-checklist.txt @@ -15,16 +15,21 @@ o build source package git archive --format=tar openscad-2011.01 --prefix=openscad-2011.01/ | gzip > openscad-2011.01.src.tar.gz o build binaries + tar xzf openscad-2011.01.src.tar.gz + cd openscad-2011.01 Mac OS X - - publish-macosx.sh -> OpenSCAD-2011.01.dmg + For Qt-4.7.3: Remove /Developers/Applications/Qt/plugins/qmltooling + ./scripts/publish-macosx.sh -> OpenSCAD-2011.01.dmg Linux: FIXME 32 vs. 64 bit - - release-linux.sh + ./scripts/release-linux.sh Windows: FIXME 32 vs. 64 bit o FIXME: Run some tests o Set back version: release-linux.sh, publish-macosx.sh, FIXME: Windows +o git push --tags + o Upload - Github Upload manually here: https://github.com/openscad/openscad/downloads @@ -3,7 +3,7 @@ flex.name = Flex ${QMAKE_FILE_IN}
flex.input = FLEXSOURCES
flex.output = ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}.lexer.cpp
-flex.commands = flex -P ${QMAKE_FILE_BASE} -o ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}.lexer.cpp ${QMAKE_FILE_IN}
+flex.commands = flex -P ${QMAKE_FILE_BASE} -o${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}.lexer.cpp ${QMAKE_FILE_IN}
flex.CONFIG += target_predeps
flex.variable_out = GENERATED_SOURCES
silent:flex.commands = @echo Lex ${QMAKE_FILE_IN} && $$flex.commands
diff --git a/scripts/installer.nsi b/scripts/installer.nsi new file mode 100644 index 0000000..269a30c --- /dev/null +++ b/scripts/installer.nsi @@ -0,0 +1,30 @@ +!include "FileAssociation.nsh" +Name "OpenSCAD" +OutFile "openscad_setup.exe" +InstallDir $PROGRAMFILES\OpenSCAD +DirText "This will install OpenSCAD on your computer. Choose a directory" +Section "install" +SetOutPath $INSTDIR +File openscad.exe +File /r examples +File /r libraries +${registerExtension} "$INSTDIR\openscad.exe" ".scad" "OpenSCAD_File" +CreateShortCut $SMPROGRAMS\OpenSCAD.lnk $INSTDIR\openscad.exe +WriteUninstaller $INSTDIR\Uninstall.exe +WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenSCAD" "DisplayName" "OpenSCAD (remove only)" +WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenSCAD" "UninstallString" "$INSTDIR\Uninstall.exe" +SectionEnd +Section "Uninstall" +${unregisterExtension} ".scad" "OpenSCAD_File" +Delete $INSTDIR\Uninstall.exe +Delete $INSTDIR\MyProg.exe +Delete $SMPROGRAMS\OpenSCAD.lnk +DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenSCAD" +RMDir /r $INSTDIR\examples +RMDir /r $INSTDIR\libraries\mcad +Delete $INSTDIR\libraries\boxes.scad +Delete $INSTDIR\libraries\shapes.scad +RMDir $INSTDIR\libraries +Delete $INSTDIR\openscad.exe +RMDir $INSTDIR +SectionEnd diff --git a/scripts/macosx-build-dependencies.sh b/scripts/macosx-build-dependencies.sh index 92552a2..9a59789 100755 --- a/scripts/macosx-build-dependencies.sh +++ b/scripts/macosx-build-dependencies.sh @@ -17,8 +17,8 @@ # o Port to other platforms? # -BASEDIR=/Users/kintel/code/metalab/checkout/OpenSCAD/libraries -OPENSCADDIR=/Users/kintel/code/metalab/checkout/OpenSCAD/openscad-release +BASEDIR=/Users/kintel/code/OpenSCAD/libraries +OPENSCADDIR=/Users/kintel/code/OpenSCAD/openscad SRCDIR=$BASEDIR/src DEPLOYDIR=$BASEDIR/install diff --git a/scripts/publish-macosx.sh b/scripts/publish-macosx.sh index 6586525..6415b52 100755 --- a/scripts/publish-macosx.sh +++ b/scripts/publish-macosx.sh @@ -1,7 +1,7 @@ #!/bin/sh VERSION=`date "+%Y.%m.%d"` -#VERSION=2011.04 +#VERSION=2011.06 # This is the same location as DEPLOYDIR in macosx-build-dependencies.sh export MACOSX_DEPLOY_DIR=$PWD/../libraries/install diff --git a/scripts/release-linux.sh b/scripts/release-linux.sh index e576faa..35d177f 100755 --- a/scripts/release-linux.sh +++ b/scripts/release-linux.sh @@ -2,7 +2,7 @@ # WARNING: This script might only work with the authors setup... VERSION=`date "+%Y.%m.%d"` -#VERSION=2011.04 +#VERSION=2011.06 set -ex diff --git a/src/MainWindow.h b/src/MainWindow.h index 2c43856..a44644a 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -83,6 +83,8 @@ private: static void consoleOutput(const QString &msg, void *userdata) { static_cast<MainWindow*>(userdata)->console->append(msg); } + void loadViewSettings(); + void loadDesignSettings(); private slots: void actionNew(); @@ -113,6 +115,7 @@ private slots: void actionExportSTL(); void actionExportOFF(); void actionExportDXF(); + void actionExportImage(); void actionFlushCaches(); public: diff --git a/src/MainWindow.ui b/src/MainWindow.ui index 8d5bbb9..1741557 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -112,7 +112,7 @@ <x>0</x> <y>0</y> <width>681</width> - <height>25</height> + <height>22</height> </rect> </property> <widget class="QMenu" name="menu_File"> @@ -178,6 +178,7 @@ <addaction name="designActionExportSTL"/> <addaction name="designActionExportOFF"/> <addaction name="designActionExportDXF"/> + <addaction name="designActionExportImage"/> <addaction name="designActionFlushCaches"/> </widget> <widget class="QMenu" name="menu_View"> @@ -651,6 +652,11 @@ <string>Automatic Reload and Compile</string> </property> </action> + <action name="designActionExportImage"> + <property name="text"> + <string>Export as Image...</string> + </property> + </action> </widget> <customwidgets> <customwidget> diff --git a/src/Preferences.cc b/src/Preferences.cc index 6419944..eb6af61 100644 --- a/src/Preferences.cc +++ b/src/Preferences.cc @@ -40,6 +40,7 @@ Preferences::Preferences(QWidget *parent) : QMainWindow(parent) this->defaultmap["3dview/colorscheme"] = this->colorSchemeChooser->currentItem()->text(); this->defaultmap["editor/fontfamily"] = this->fontChooser->currentText(); this->defaultmap["editor/fontsize"] = this->fontSize->currentText().toUInt(); + this->defaultmap["editor/opengl20_warning_show"] = true; // Toolbar QActionGroup *group = new QActionGroup(this); @@ -97,7 +98,8 @@ Preferences::Preferences(QWidget *parent) : QMainWindow(parent) this, SLOT(fontFamilyChanged(const QString &))); connect(this->fontSize, SIGNAL(editTextChanged(const QString &)), this, SLOT(fontSizeChanged(const QString &))); - + connect(this->OpenGL20WarningCheckbox, SIGNAL(clicked(bool)), + this, SLOT(OpenGL20WarningChanged(bool))); updateGUI(); } @@ -148,6 +150,13 @@ void Preferences::fontSizeChanged(const QString &size) emit fontChanged(getValue("editor/fontfamily").toString(), intsize); } +void +Preferences::OpenGL20WarningChanged(bool state) +{ + QSettings settings; + settings.setValue("editor/opengl20_warning_show",state); +} + void Preferences::keyPressEvent(QKeyEvent *e) { #ifdef Q_WS_MAC @@ -185,6 +194,7 @@ QVariant Preferences::getValue(const QString &key) const void Preferences::updateGUI() { + QSettings settings; QList<QListWidgetItem *> found = this->colorSchemeChooser->findItems(getValue("3dview/colorscheme").toString(), Qt::MatchExactly); @@ -204,6 +214,9 @@ void Preferences::updateGUI() else { this->fontSize->setEditText(fontsize); } + + bool opengl20_warning_show = getValue("editor/opengl20_warning_show").toBool(); + this->OpenGL20WarningCheckbox->setChecked(opengl20_warning_show); } void Preferences::apply() const @@ -211,4 +224,3 @@ void Preferences::apply() const emit fontChanged(getValue("editor/fontfamily").toString(), getValue("editor/fontsize").toUInt()); emit requestRedraw(); } - diff --git a/src/Preferences.h b/src/Preferences.h index 39599fd..79fa7ab 100644 --- a/src/Preferences.h +++ b/src/Preferences.h @@ -34,6 +34,7 @@ public slots: void colorSchemeChanged(); void fontFamilyChanged(const QString &); void fontSizeChanged(const QString &); + void OpenGL20WarningChanged(bool); signals: void requestRedraw() const; diff --git a/src/Preferences.ui b/src/Preferences.ui index 13db9f3..2ab7646 100644 --- a/src/Preferences.ui +++ b/src/Preferences.ui @@ -179,71 +179,29 @@ <number>0</number> </property> <item> - <spacer name="verticalSpacer_2"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>120</height> - </size> - </property> - </spacer> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> + <layout class="QVBoxLayout" name="verticalLayout_6"> <item> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="label_2"> - <property name="enabled"> - <bool>false</bool> - </property> + <widget class="QCheckBox" name="OpenGL20WarningCheckbox"> <property name="text"> - <string>advanced</string> + <string>Show OpenGL 2.0 warning && rendering info</string> </property> </widget> </item> <item> - <spacer name="horizontalSpacer_3"> + <spacer name="verticalSpacer_2"> <property name="orientation"> - <enum>Qt::Horizontal</enum> + <enum>Qt::Vertical</enum> </property> <property name="sizeHint" stdset="0"> <size> - <width>40</width> - <height>20</height> + <width>20</width> + <height>40</height> </size> </property> </spacer> </item> </layout> </item> - <item> - <spacer name="verticalSpacer_3"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>120</height> - </size> - </property> - </spacer> - </item> </layout> </widget> </widget> diff --git a/src/cgaladv_minkowski2.cc b/src/cgaladv_minkowski2.cc index 8d0bf62..b722708 100644 --- a/src/cgaladv_minkowski2.cc +++ b/src/cgaladv_minkowski2.cc @@ -85,7 +85,7 @@ CGAL_Poly2 nef2p2(CGAL_Nef_polyhedron2 p) typedef Explorer::Halfedge_around_face_const_circulator heafcc_t; Explorer E = p.explorer(); - for (fci_t fit = E.faces_begin(), fend = E.faces_end(); fit != fend; ++fit) + for (fci_t fit = E.faces_begin(), facesend = E.faces_end(); fit != facesend; ++fit) { if (!E.mark(fit)) { continue; diff --git a/src/export.cc b/src/export.cc index f4572bc..1f9046e 100644 --- a/src/export.cc +++ b/src/export.cc @@ -155,20 +155,6 @@ void export_off(CGAL_Nef_polyhedron*, QTextStream&, QProgressDialog*) void export_dxf(CGAL_Nef_polyhedron *root_N, QTextStream &output, QProgressDialog *) { setlocale(LC_NUMERIC, "C"); // Ensure radix is . (not ,) in output - - // Some importers (e.g. QCAD) needs a HEADER section specifying AutoCAD 2000 as - // the file format for LWPOLYLINE entities to work - output << " 0\n" - << "SECTION\n" - << " 2\n" - << "HEADER\n" - << " 9\n" - << "$ACADVER\n" - << " 1\n" - << "AC1015\n" - << " 0\n" - << "ENDSEC\n"; - // Some importers (e.g. Inkscape) needs a BLOCKS section to be present output << " 0\n" << "SECTION\n" @@ -184,27 +170,26 @@ void export_dxf(CGAL_Nef_polyhedron *root_N, QTextStream &output, QProgressDialo DxfData dd(*root_N); for (int i=0; i<dd.paths.size(); i++) { - if (dd.paths[i].points.size() < 2) { - // not a valid polygon - continue; - } - // Use the LWPOLYLINE class - this makes it easier to handle complete - // objects (as paths) in Inkscape. - output << " 0\n" - << "LWPOLYLINE\n" - << " 8\n" // Some importers (e.g. Inkscape) need a layer to be specified - << "0\n" - << " 90\n" // number of vertices - << dd.paths[i].points.size() << "\n" - << " 70\n" // polygon flag (closed, ...) - << (dd.paths[i].is_closed ? 1 : 0) << "\n"; - // add all points - for (int j=0; j<dd.paths[i].points.size(); j++) { - DxfData::Point *p = dd.paths[i].points[j]; - output <<" 10\n" - << p->x << "\n" + for (int j=1; j<dd.paths[i].points.size(); j++) { + DxfData::Point *p1 = dd.paths[i].points[j-1]; + DxfData::Point *p2 = dd.paths[i].points[j]; + double x1 = p1->x; + double y1 = p1->y; + double x2 = p2->x; + double y2 = p2->y; + output << " 0\n" + << "LINE\n"; + // Some importers (e.g. Inkscape) needs a layer to be specified + output << " 8\n" + << "0\n" + << " 10\n" + << x1 << "\n" + << " 11\n" + << x2 << "\n" << " 20\n" - << p->y << "\n"; + << y1 << "\n" + << " 21\n" + << y2 << "\n"; } } diff --git a/src/glview.cc b/src/glview.cc index a7f3cd9..a76f6e9 100644 --- a/src/glview.cc +++ b/src/glview.cc @@ -30,9 +30,15 @@ #include <QApplication> #include <QWheelEvent> +#include <QCheckBox> +#include <QDialogButtonBox> #include <QMouseEvent> #include <QMessageBox> +#include <QPushButton> +#include <QSettings> #include <QTimer> +#include <QTextEdit> +#include <QVBoxLayout> #include "mathc99.h" #include <stdio.h> @@ -191,7 +197,10 @@ void GLView::initializeGL() } } else { opencsg_support = false; - QTimer::singleShot(0, this, SLOT(display_opengl20_warning())); + QSettings settings; + if (settings.value("editor/opengl20_warning_show",true).toBool()) { + QTimer::singleShot(0, this, SLOT(display_opengl20_warning())); + } } #endif /* ENABLE_OPENCSG */ } @@ -199,6 +208,9 @@ void GLView::initializeGL() #ifdef ENABLE_OPENCSG void GLView::display_opengl20_warning() { + // data + QString title = QString("GLEW: GL_VERSION_2_0 is not supported!"); + QString rendererinfo; rendererinfo.sprintf("GLEW version %s\n" "%s (%s)\n" @@ -207,11 +219,43 @@ void GLView::display_opengl20_warning() glGetString(GL_RENDERER), glGetString(GL_VENDOR), glGetString(GL_VERSION)); - QMessageBox::warning(NULL, "GLEW: GL_VERSION_2_0 is not supported!", - QString("Warning: No support for OpenGL 2.0 found! OpenCSG View has been disabled.\n\n" + QString message = QString("Warning: No support for OpenGL 2.0 found! OpenCSG View has been disabled.\n\n" "It is highly recommended to use OpenSCAD on a system with OpenGL 2.0 " "support. Please check if OpenGL 2.0 drivers are available for your " - "graphics hardware.\n\n%1").arg(rendererinfo)); + "graphics hardware. Your renderer information is as follows:\n\n%1").arg(rendererinfo); + + QString note = QString("Uncheck to hide this message in the future"); + + // presentation + QDialog *dialog = new QDialog(this); + dialog->setSizeGripEnabled(true); + dialog->setWindowTitle(title); + dialog->resize(500,300); + + QVBoxLayout *layout = new QVBoxLayout(dialog); + dialog->setLayout(layout); + + QTextEdit *textEdit = new QTextEdit(dialog); + textEdit->setPlainText(message); + layout->addWidget(textEdit); + + QCheckBox *checkbox = new QCheckBox(note,dialog); + checkbox->setCheckState(Qt::Checked); + layout->addWidget(checkbox); + + QDialogButtonBox *buttonbox = + new QDialogButtonBox( QDialogButtonBox::Ok, Qt::Horizontal,dialog); + layout->addWidget(buttonbox); + buttonbox->button(QDialogButtonBox::Ok)->setFocus(); + buttonbox->button(QDialogButtonBox::Ok)->setDefault(true); + + // action + connect(buttonbox, SIGNAL(accepted()), dialog, SLOT(accept())); + connect(checkbox, SIGNAL(clicked(bool)), + Preferences::inst()->OpenGL20WarningCheckbox, SLOT(setChecked(bool))); + connect(checkbox, SIGNAL(clicked(bool)), + Preferences::inst(), SLOT(OpenGL20WarningChanged(bool))); + dialog->exec(); } #endif diff --git a/src/mainwin.cc b/src/mainwin.cc index 0e851c8..1f5644c 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -128,6 +128,37 @@ static char copyrighttext[] = "the Free Software Foundation; either version 2 of the License, or" "(at your option) any later version."; +static void +settings_setValueList(const QString &key,const QList<int> &list) +{ + QSettings settings; + settings.beginWriteArray(key); + for (int i=0;i<list.size(); ++i) { + settings.setArrayIndex(i); + settings.setValue("entry",list[i]); + } + settings.endArray(); +} + +QList<int> +settings_valueList(const QString &key, const QList<int> &defaultList = QList<int>()) +{ + QSettings settings; + QList<int> result; + if (settings.contains(key+"/size")){ + int length = settings.beginReadArray(key); + for (int i = 0; i < length; ++i) { + settings.setArrayIndex(i); + result += settings.value("entry").toInt(); + } + settings.endArray(); + return result; + } else { + return defaultList; + } + +} + MainWindow::MainWindow(const QString &filename) { setupUi(this); @@ -271,6 +302,7 @@ MainWindow::MainWindow(const QString &filename) connect(this->designActionExportSTL, SIGNAL(triggered()), this, SLOT(actionExportSTL())); connect(this->designActionExportOFF, SIGNAL(triggered()), this, SLOT(actionExportOFF())); connect(this->designActionExportDXF, SIGNAL(triggered()), this, SLOT(actionExportDXF())); + connect(this->designActionExportImage, SIGNAL(triggered()), this, SLOT(actionExportImage())); connect(this->designActionFlushCaches, SIGNAL(triggered()), this, SLOT(actionFlushCaches())); // View menu @@ -346,27 +378,69 @@ MainWindow::MainWindow(const QString &filename) this, SLOT(setFont(const QString&,uint))); Preferences::inst()->apply(); + // make sure it looks nice.. + QSettings settings; + resize(settings.value("window/size", QSize(800, 600)).toSize()); + move(settings.value("window/position", QPoint(0, 0)).toPoint()); + QList<int> s1sizes = settings_valueList("window/splitter1sizes",QList<int>()<<400<<400); + QList<int> s2sizes = settings_valueList("window/splitter2sizes",QList<int>()<<400<<200); + splitter1->setSizes(s1sizes); + splitter2->setSizes(s2sizes); // display this window and check for OpenGL 2.0 (OpenCSG) support viewModeThrownTogether(); show(); - // make sure it looks nice.. - resize(800, 600); - splitter1->setSizes(QList<int>() << 400 << 400); - splitter2->setSizes(QList<int>() << 400 << 200); - #ifdef ENABLE_OPENCSG viewModeOpenCSG(); #else viewModeThrownTogether(); #endif - viewPerspective(); + loadViewSettings(); + loadDesignSettings(); setAcceptDrops(true); clearCurrentOutput(); } +void +MainWindow::loadViewSettings(){ + QSettings settings; + if (settings.value("view/showEdges").toBool()) { + viewActionShowEdges->setChecked(true); + viewModeShowEdges(); + } + if (settings.value("view/showAxes").toBool()) { + viewActionShowAxes->setChecked(true); + viewModeShowAxes(); + } + if (settings.value("view/showCrosshairs").toBool()) { + viewActionShowCrosshairs->setChecked(true); + viewModeShowCrosshairs(); + } + if (settings.value("view/orthogonalProjection").toBool()) { + viewOrthogonal(); + } else { + viewPerspective(); + } + if (settings.value("view/hideConsole").toBool()) { + viewActionHide->setChecked(true); + hideConsole(); + } + if (settings.value("view/hideEditor").toBool()) { + editActionHide->setChecked(true); + hideEditor(); + } +} + +void +MainWindow::loadDesignSettings() +{ + QSettings settings; + if (settings.value("design/autoReload").toBool()) + designActionAutoReload->setChecked(true); +} + MainWindow::~MainWindow() { if (root_module) @@ -968,10 +1042,13 @@ void MainWindow::actionReload() void MainWindow::hideEditor() { + QSettings settings; if (editActionHide->isChecked()) { editor->hide(); + settings.setValue("view/hideEditor",true); } else { editor->show(); + settings.setValue("view/hideEditor",false); } } @@ -1012,6 +1089,8 @@ void MainWindow::checkAutoReload() void MainWindow::autoReloadSet(bool on) { + QSettings settings; + settings.setValue("design/autoReload",designActionAutoReload->isChecked()); if (on) { autoReloadInfo = QString(); autoReloadTimer->start(200); @@ -1392,6 +1471,24 @@ void MainWindow::actionExportDXF() #endif /* ENABLE_CGAL */ } +void MainWindow::actionExportImage() +{ + QImage img = this->glview->grabFrameBuffer(); + setCurrentOutput(); + + QString img_filename = QFileDialog::getSaveFileName(this, + "Export Image", "", "PNG Files (*.png)"); + if (img_filename.isEmpty()) { + PRINTF("No filename specified. Image export aborted."); + clearCurrentOutput(); + return; + } + + img.save(img_filename, "PNG"); + + clearCurrentOutput(); +} + void MainWindow::actionFlushCaches() { // FIXME: Polycache -> PolySetRenderer @@ -1690,17 +1787,23 @@ void MainWindow::viewModeThrownTogether() void MainWindow::viewModeShowEdges() { + QSettings settings; + settings.setValue("view/showEdges",viewActionShowEdges->isChecked()); this->glview->updateGL(); } void MainWindow::viewModeShowAxes() { + QSettings settings; + settings.setValue("view/showAxes",viewActionShowAxes->isChecked()); this->glview->setShowAxes(viewActionShowAxes->isChecked()); this->glview->updateGL(); } void MainWindow::viewModeShowCrosshairs() { + QSettings settings; + settings.setValue("view/showCrosshairs",viewActionShowCrosshairs->isChecked()); this->glview->setShowCrosshairs(viewActionShowCrosshairs->isChecked()); this->glview->updateGL(); } @@ -1804,6 +1907,8 @@ void MainWindow::viewCenter() void MainWindow::viewPerspective() { + QSettings settings; + settings.setValue("view/orthogonalProjection",false); viewActionPerspective->setChecked(true); viewActionOrthogonal->setChecked(false); this->glview->setOrthoMode(false); @@ -1812,6 +1917,8 @@ void MainWindow::viewPerspective() void MainWindow::viewOrthogonal() { + QSettings settings; + settings.setValue("view/orthogonalProjection",true); viewActionPerspective->setChecked(false); viewActionOrthogonal->setChecked(true); this->glview->setOrthoMode(true); @@ -1820,10 +1927,13 @@ void MainWindow::viewOrthogonal() void MainWindow::hideConsole() { + QSettings settings; if (viewActionHide->isChecked()) { console->hide(); + settings.setValue("view/hideConsole",true); } else { console->show(); + settings.setValue("view/hideConsole",false); } } @@ -1890,6 +2000,11 @@ MainWindow::maybeSave() void MainWindow::closeEvent(QCloseEvent *event) { if (maybeSave()) { + QSettings settings; + settings.setValue("window/size", size()); + settings.setValue("window/position", pos()); + settings_setValueList("window/splitter1sizes",splitter1->sizes()); + settings_setValueList("window/splitter2sizes",splitter2->sizes()); event->accept(); } else { event->ignore(); diff --git a/src/primitives.cc b/src/primitives.cc index def90c9..7e399dc 100644 --- a/src/primitives.cc +++ b/src/primitives.cc @@ -37,6 +37,8 @@ #include <sstream> #include <assert.h> +#define F_MINIMUM 0.01 + enum primitive_type_e { CUBE, SPHERE, @@ -94,7 +96,6 @@ public: bool center; double x, y, z, h, r1, r2; - static const double F_MINIMUM = 0.01; double fn, fs, fa; primitive_type_e type; int convexity; @@ -145,13 +146,13 @@ AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const ModuleInstanti node->fs = c.lookup_variable("$fs").num; node->fa = c.lookup_variable("$fa").num; - if (node->fs < PrimitiveNode::F_MINIMUM) { - PRINTF("WARNING: $fs too small - clamping to %f", PrimitiveNode::F_MINIMUM); - node->fs = PrimitiveNode::F_MINIMUM; + if (node->fs < F_MINIMUM) { + PRINTF("WARNING: $fs too small - clamping to %f", F_MINIMUM); + node->fs = F_MINIMUM; } - if (node->fa < PrimitiveNode::F_MINIMUM) { - PRINTF("WARNING: $fa too small - clamping to %f", PrimitiveNode::F_MINIMUM); - node->fa = PrimitiveNode::F_MINIMUM; + if (node->fa < F_MINIMUM) { + PRINTF("WARNING: $fa too small - clamping to %f", F_MINIMUM); + node->fa = F_MINIMUM; } @@ -265,7 +266,7 @@ struct point2d { static void generate_circle(point2d *circle, double r, int fragments) { for (int i=0; i<fragments; i++) { - double phi = (M_PI*2* (i + 0.5)) / fragments; + double phi = (M_PI*2*i) / fragments; circle[i].x = r*cos(phi); circle[i].y = r*sin(phi); } diff --git a/src/transform.cc b/src/transform.cc index 4238250..d75c6a7 100644 --- a/src/transform.cc +++ b/src/transform.cc @@ -35,6 +35,7 @@ #include "printutils.h" #include "visitor.h" #include <sstream> +#include <vector> #include <assert.h> enum transform_type_e { @@ -54,6 +55,31 @@ public: virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const; }; +using std::string; +using std::vector; + +static vector<string> split(const string &str, const string &delim) +{ + assert(delim.size() > 0); + + vector<string> strvec; + size_t start = 0, end = 0; + while (end != string::npos) { + end = str.find(delim, start); + // If at end, use length=maxLength. Else use length=end-start. + strvec.push_back(str.substr(start, (end == string::npos) ? string::npos : end - start)); + // If at end, use start=maxSize. Else use start=end+delimiter. + start = ((end > (string::npos - delim.size())) ? string::npos : end + delim.size()); + } + return strvec; +} + +template <class T> static bool from_string(T &t, const string &s) +{ + std::istringstream iss(s); + return !(iss >> t).fail(); +} + AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const { TransformNode *node = new TransformNode(inst); @@ -222,6 +248,25 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti if (v.type == Value::VECTOR) { for (int i = 0; i < 4; i++) node->matrix[16+i] = i < v.vec.size() ? v.vec[i]->num : 1.0; +// FIXME: Port to non-Qt +#if 0 + } else if (v.type == Value::STRING) { + double alpha = 1.0; + vector<string> chunks = split(v.text, ","); + string colorname = chunks[0]; + if (chunks.size() < 2 || !from_string(alpha, chunks[1])) alpha = 1.0; + QColor color; + color.setNamedColor(colorname); + if (color.isValid()) { + node->m[16+0] = color.redF(); + node->m[16+1] = color.greenF(); + node->m[16+2] = color.blueF(); + node->m[16+3] = alpha; + } else { + PRINTF_NOCACHE("WARNING: Color name \"%s\" unknown. Please see",v.text.toUtf8().data()); + PRINTF_NOCACHE("WARNING: http://en.wikipedia.org/wiki/Web_colors"); + } +#endif } } @@ -234,7 +279,7 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti return node; } -std::string TransformNode::toString() const +string TransformNode::toString() const { std::stringstream stream; @@ -259,7 +304,7 @@ std::string TransformNode::toString() const return stream.str(); } -std::string TransformNode::name() const +string TransformNode::name() const { return "transform"; } diff --git a/testdata/scad/non-aff-matrix.scad b/testdata/scad/non-aff-matrix.scad new file mode 100644 index 0000000..7dbced1 --- /dev/null +++ b/testdata/scad/non-aff-matrix.scad @@ -0,0 +1,6 @@ +multmatrix(m = [[1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, -0.02, 1]]) + linear_extrude(height=20) circle(r=10); + diff --git a/testdata/scad/testcolornames.scad b/testdata/scad/testcolornames.scad new file mode 100644 index 0000000..b9ad334 --- /dev/null +++ b/testdata/scad/testcolornames.scad @@ -0,0 +1,159 @@ +/* color samples for SVG named colors, for OpenSCAD +Please see http://en.wikipedia.org/wiki/Web_colors +and http://www.w3.org/TR/SVG/types.html#ColorKeywords +for more information. */ + +$fn=5; +radius=0.8; +//translate([0,0]) color("Red colors") sphere(radius); +translate([1,0]) color("IndianRed") sphere(radius); +translate([2,0]) color("LightCoral") sphere(radius); +translate([3,0]) color("Salmon") sphere(radius); +translate([4,0]) color("DarkSalmon") sphere(radius); +translate([5,0]) color("LightSalmon") sphere(radius); +translate([6,0]) color("Red") sphere(radius); +translate([7,0]) color("Crimson") sphere(radius); +translate([8,0]) color("FireBrick") sphere(radius); +translate([9,0]) color("DarkRed") sphere(radius); +//translate([10,0]) color("Pink colors") sphere(radius); +translate([0,1]) color("Pink") sphere(radius); +translate([1,1]) color("LightPink") sphere(radius); +translate([2,1]) color("HotPink") sphere(radius); +translate([3,1]) color("DeepPink") sphere(radius); +translate([4,1]) color("MediumVioletRed") sphere(radius); +translate([5,1]) color("PaleVioletRed") sphere(radius); +//translate([6,1]) color("Orange colors") sphere(radius); +translate([7,1]) color("LightSalmon") sphere(radius); +translate([8,1]) color("Coral") sphere(radius); +translate([9,1]) color("Tomato") sphere(radius); +translate([10,1]) color("OrangeRed") sphere(radius); +translate([0,2]) color("DarkOrange") sphere(radius); +translate([1,2]) color("Orange") sphere(radius); +//translate([2,2]) color("Yellow colors") sphere(radius); +translate([3,2]) color("Gold") sphere(radius); +translate([4,2]) color("Yellow") sphere(radius); +translate([5,2]) color("LightYellow") sphere(radius); +translate([6,2]) color("LemonChiffon") sphere(radius); +translate([7,2]) color("LightGoldenrodYellow") sphere(radius); +translate([8,2]) color("PapayaWhip") sphere(radius); +translate([9,2]) color("Moccasin") sphere(radius); +translate([10,2]) color("PeachPuff") sphere(radius); +translate([0,3]) color("PaleGoldenrod") sphere(radius); +translate([1,3]) color("Khaki") sphere(radius); +translate([2,3]) color("DarkKhaki") sphere(radius); +//translate([3,3]) color("Purple colors") sphere(radius); +translate([4,3]) color("Lavender") sphere(radius); +translate([5,3]) color("Thistle") sphere(radius); +translate([6,3]) color("Plum") sphere(radius); +translate([7,3]) color("Violet") sphere(radius); +translate([8,3]) color("Orchid") sphere(radius); +translate([9,3]) color("Fuchsia") sphere(radius); +translate([10,3]) color("Magenta") sphere(radius); +translate([0,4]) color("MediumOrchid") sphere(radius); +translate([1,4]) color("MediumPurple") sphere(radius); +translate([2,4]) color("BlueViolet") sphere(radius); +translate([3,4]) color("DarkViolet") sphere(radius); +translate([4,4]) color("DarkOrchid") sphere(radius); +translate([5,4]) color("DarkMagenta") sphere(radius); +translate([6,4]) color("Purple") sphere(radius); +translate([7,4]) color("Indigo") sphere(radius); +translate([8,4]) color("DarkSlateBlue") sphere(radius); +translate([9,4]) color("SlateBlue") sphere(radius); +translate([10,4]) color("MediumSlateBlue") sphere(radius); +//translate([0,5]) color("Green colors") sphere(radius); +translate([1,5]) color("GreenYellow") sphere(radius); +translate([2,5]) color("Chartreuse") sphere(radius); +translate([3,5]) color("LawnGreen") sphere(radius); +translate([4,5]) color("Lime") sphere(radius); +translate([5,5]) color("LimeGreen") sphere(radius); +translate([6,5]) color("PaleGreen") sphere(radius); +translate([7,5]) color("LightGreen") sphere(radius); +translate([8,5]) color("MediumSpringGreen") sphere(radius); +translate([9,5]) color("SpringGreen") sphere(radius); +translate([10,5]) color("MediumSeaGreen") sphere(radius); +translate([0,6]) color("SeaGreen") sphere(radius); +translate([1,6]) color("ForestGreen") sphere(radius); +translate([2,6]) color("Green") sphere(radius); +translate([3,6]) color("DarkGreen") sphere(radius); +translate([4,6]) color("YellowGreen") sphere(radius); +translate([5,6]) color("OliveDrab") sphere(radius); +translate([6,6]) color("Olive") sphere(radius); +translate([7,6]) color("DarkOliveGreen") sphere(radius); +translate([8,6]) color("MediumAquamarine") sphere(radius); +translate([9,6]) color("DarkSeaGreen") sphere(radius); +translate([10,6]) color("LightSeaGreen") sphere(radius); +translate([0,7]) color("DarkCyan") sphere(radius); +translate([1,7]) color("Teal") sphere(radius); +//translate([2,7]) color("Blue/Cyan colors") sphere(radius); +translate([3,7]) color("Aqua") sphere(radius); +translate([4,7]) color("Cyan") sphere(radius); +translate([5,7]) color("LightCyan") sphere(radius); +translate([6,7]) color("PaleTurquoise") sphere(radius); +translate([7,7]) color("Aquamarine") sphere(radius); +translate([8,7]) color("Turquoise") sphere(radius); +translate([9,7]) color("MediumTurquoise") sphere(radius); +translate([10,7]) color("DarkTurquoise") sphere(radius); +translate([0,8]) color("CadetBlue") sphere(radius); +translate([1,8]) color("SteelBlue") sphere(radius); +translate([2,8]) color("LightSteelBlue") sphere(radius); +translate([3,8]) color("PowderBlue") sphere(radius); +translate([4,8]) color("LightBlue") sphere(radius); +translate([5,8]) color("SkyBlue") sphere(radius); +translate([6,8]) color("LightSkyBlue") sphere(radius); +translate([7,8]) color("DeepSkyBlue") sphere(radius); +translate([8,8]) color("DodgerBlue") sphere(radius); +translate([9,8]) color("CornflowerBlue") sphere(radius); +translate([10,8]) color("RoyalBlue") sphere(radius); +translate([0,9]) color("Blue") sphere(radius); +translate([1,9]) color("MediumBlue") sphere(radius); +translate([2,9]) color("DarkBlue") sphere(radius); +translate([3,9]) color("Navy") sphere(radius); +translate([4,9]) color("MidnightBlue") sphere(radius); +//translate([5,9]) color("Brown colors") sphere(radius); +translate([6,9]) color("Cornsilk") sphere(radius); +translate([7,9]) color("BlanchedAlmond") sphere(radius); +translate([8,9]) color("Bisque") sphere(radius); +translate([9,9]) color("NavajoWhite") sphere(radius); +translate([10,9]) color("Wheat") sphere(radius); +translate([0,10]) color("BurlyWood") sphere(radius); +translate([1,10]) color("Tan") sphere(radius); +translate([2,10]) color("RosyBrown") sphere(radius); +translate([3,10]) color("SandyBrown") sphere(radius); +translate([4,10]) color("Goldenrod") sphere(radius); +translate([5,10]) color("DarkGoldenrod") sphere(radius); +translate([6,10]) color("Peru") sphere(radius); +translate([7,10]) color("Chocolate") sphere(radius); +translate([8,10]) color("SaddleBrown") sphere(radius); +translate([9,10]) color("Sienna") sphere(radius); +translate([10,10]) color("Brown") sphere(radius); +translate([0,11]) color("Maroon") sphere(radius); +//translate([1,11]) color("White colors") sphere(radius); +translate([2,11]) color("White") sphere(radius); +translate([3,11]) color("Snow") sphere(radius); +translate([4,11]) color("Honeydew") sphere(radius); +translate([5,11]) color("MintCream") sphere(radius); +translate([6,11]) color("Azure") sphere(radius); +translate([7,11]) color("AliceBlue") sphere(radius); +translate([8,11]) color("GhostWhite") sphere(radius); +translate([9,11]) color("WhiteSmoke") sphere(radius); +translate([10,11]) color("Seashell") sphere(radius); +translate([0,12]) color("Beige") sphere(radius); +translate([1,12]) color("OldLace") sphere(radius); +translate([2,12]) color("FloralWhite") sphere(radius); +translate([3,12]) color("Ivory") sphere(radius); +translate([4,12]) color("AntiqueWhite") sphere(radius); +translate([5,12]) color("Linen") sphere(radius); +translate([6,12]) color("LavenderBlush") sphere(radius); +translate([7,12]) color("MistyRose") sphere(radius); +//translate([8,12]) color("Gray colors") sphere(radius); +translate([9,12]) color("Gainsboro") sphere(radius); +translate([10,12]) color("LightGrey") sphere(radius); +translate([0,13]) color("Silver") sphere(radius); +translate([1,13]) color("DarkGray") sphere(radius); +translate([2,13]) color("Gray") sphere(radius); +translate([3,13]) color("DimGray") sphere(radius); +translate([4,13]) color("LightSlateGray") sphere(radius); +translate([5,13]) color("SlateGray") sphere(radius); +translate([6,13]) color("DarkSlateGray") sphere(radius); +translate([7,13]) color("Black") sphere(radius); + |