diff --git a/openscad.pro b/openscad.pro
index c90942ea..d9b99c73 100644
--- a/openscad.pro
+++ b/openscad.pro
@@ -259,6 +259,7 @@ HEADERS += src/typedefs.h \
src/OpenCSGWarningDialog.h \
src/AboutDialog.h \
src/FontListDialog.h \
+ src/FontListTableView.h \
src/builtin.h \
src/calc.h \
src/context.h \
@@ -428,6 +429,7 @@ SOURCES += src/version_check.cc \
src/UIUtils.cc \
src/Dock.cc \
src/FontListDialog.cc \
+ src/FontListTableView.cc \
src/launchingscreen.cc \
src/legacyeditor.cc \
src/LibraryInfoDialog.cc
@@ -554,7 +556,3 @@ INSTALLS += icons
man.path = $$PREFIX/share/man/man1
man.extra = cp -f doc/openscad.1 \"\$(INSTALL_ROOT)$${man.path}/$${FULLNAME}.1\"
INSTALLS += man
-
-CONFIG(winconsole) {
- include(winconsole.pri)
-}
diff --git a/scripts/release-common.sh b/scripts/release-common.sh
index f9faf8a6..709d508a 100755
--- a/scripts/release-common.sh
+++ b/scripts/release-common.sh
@@ -254,8 +254,8 @@ case $OS in
echo "cant find $TARGET/openscad.exe. build failed. stopping."
exit
fi
- # make console pipe-able openscad.com - see winconsole.pri for info
- qmake CONFIG+=winconsole ../openscad.pro
+ # make console pipe-able openscad.com - see winconsole.pro for info
+ qmake ../winconsole.pro
make
if [ ! -e $TARGET/openscad.com ]; then
echo "cant find $TARGET/openscad.com. build failed. stopping."
diff --git a/scripts/translation-make.sh b/scripts/translation-make.sh
index 89ebd91e..5fadf01d 100755
--- a/scripts/translation-make.sh
+++ b/scripts/translation-make.sh
@@ -11,5 +11,3 @@ cd "$TOPDIR" || exit 1
echo "Compiling language files..."
./scripts/translation-update.sh updatemo
-
-echo "Done."
diff --git a/src/FontListDialog.cc b/src/FontListDialog.cc
index 0ee7ef59..474c2ef3 100644
--- a/src/FontListDialog.cc
+++ b/src/FontListDialog.cc
@@ -60,14 +60,16 @@ void FontListDialog::selection_changed(const QItemSelection ¤t, const QIte
{
if (current.count() == 0) {
copyButton->setEnabled(false);
+ tableView->setDragText("");
return;
}
const QModelIndex &idx = proxy->mapToSource(current.indexes().at(0));
const QString name = model->item(idx.row(), 0)->text();
const QString style = model->item(idx.row(), 1)->text();
- selection = QString("\"%1:style=%2\"").arg(name).arg(style);
+ selection = QString("\"%1:style=%2\"").arg(quote(name)).arg(quote(style));
copyButton->setEnabled(true);
+ tableView->setDragText(selection);
}
void FontListDialog::update_font_list()
@@ -117,3 +119,28 @@ void FontListDialog::update_font_list()
delete list;
}
+
+/**
+ * Quote a string according to the requirements of font-config.
+ * See http://www.freedesktop.org/software/fontconfig/fontconfig-user.html
+ *
+ * The '\', '-', ':' and ',' characters in family names must be preceded
+ * by a '\' character to avoid having them misinterpreted. Similarly, values
+ * containing '\', '=', '_', ':' and ',' must also have them preceded by a
+ * '\' character. The '\' characters are stripped out of the family name and
+ * values as the font name is read.
+ *
+ * @param text unquoted string
+ * @return quoted text
+ */
+QString FontListDialog::quote(const QString& text)
+{
+ QString result = text;
+ result.replace('\\', "\\\\")
+ .replace('-', "\\-")
+ .replace(':', "\\:")
+ .replace(',', "\\,")
+ .replace('=', "\\=")
+ .replace('_', "\\_");
+ return result;
+}
diff --git a/src/FontListDialog.h b/src/FontListDialog.h
index 9f9a2532..d1927631 100644
--- a/src/FontListDialog.h
+++ b/src/FontListDialog.h
@@ -6,9 +6,6 @@
#include "qtgettext.h"
#include "ui_FontListDialog.h"
-#define STRINGIFY(x) #x
-#define TOSTRING(x) STRINGIFY(x)
-
class FontListDialog : public QDialog, public Ui::FontListDialog
{
Q_OBJECT;
@@ -27,6 +24,8 @@ signals:
void font_selected(const QString font);
private:
+ QString quote(const QString& text);
+
QString selection;
QStandardItemModel *model;
QSortFilterProxyModel *proxy;
diff --git a/src/FontListDialog.ui b/src/FontListDialog.ui
index dda5eb1b..70ff4fff 100644
--- a/src/FontListDialog.ui
+++ b/src/FontListDialog.ui
@@ -67,7 +67,17 @@
-
-
+
+
+ true
+
+
+ QAbstractItemView::DragOnly
+
+
+ QAbstractItemView::SelectRows
+
+
-
@@ -100,6 +110,13 @@
+
+
+ FontListTableView
+ QTableView
+
+
+
diff --git a/src/FontListTableView.cc b/src/FontListTableView.cc
new file mode 100644
index 00000000..b013d81f
--- /dev/null
+++ b/src/FontListTableView.cc
@@ -0,0 +1,66 @@
+/*
+ * OpenSCAD (www.openscad.org)
+ * Copyright (C) 2009-2011 Clifford Wolf and
+ * Marius Kintel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * As a special exception, you have permission to link this program
+ * with the CGAL library and distribute executables, as long as you
+ * follow the requirements of the GNU GPL in regard to all of the
+ * software in the executable aside from CGAL.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#include
+#include
+#include
+#include
+
+#include "qtgettext.h"
+#include "FontListDialog.h"
+
+FontListTableView::FontListTableView(QWidget *parent) : QTableView(parent)
+{
+}
+
+void FontListTableView::setDragText(const QString &text)
+{
+ this->text = text.trimmed();
+}
+
+void FontListTableView::startDrag(Qt::DropActions supportedActions)
+{
+ if (text.isEmpty()) {
+ return;
+ }
+
+ QMimeData *mimeData = new QMimeData;
+ mimeData->setText(text);
+
+ QFontMetrics fm(font());
+ QRect rect(0, 0, fm.width(text), fm.height());
+ QPixmap pixmap(rect.width(), rect.height());
+ pixmap.fill(Qt::transparent);
+
+ QPainter painter(&pixmap);
+ painter.setFont(font());
+ painter.drawText(rect, Qt::AlignCenter, text);
+
+ QDrag *drag = new QDrag(this);
+ drag->setPixmap(pixmap);
+ drag->setMimeData(mimeData);
+ drag->setHotSpot(QPoint(-10, rect.height() + 6));
+ drag->exec(supportedActions, Qt::CopyAction);
+}
diff --git a/src/FontListTableView.h b/src/FontListTableView.h
new file mode 100644
index 00000000..70348c46
--- /dev/null
+++ b/src/FontListTableView.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include
+
+class FontListTableView : public QTableView
+{
+ Q_OBJECT;
+
+public:
+ FontListTableView(QWidget *parent = NULL);
+ void setDragText(const QString &text);
+
+protected:
+ void startDrag(Qt::DropActions supportedActions);
+
+private:
+ QString text;
+};
diff --git a/src/MainWindow.h b/src/MainWindow.h
index 5d415734..50d4bb6d 100644
--- a/src/MainWindow.h
+++ b/src/MainWindow.h
@@ -71,6 +71,7 @@ public:
QAction *actionRecentFile[UIUtils::maxRecentFiles];
QMap knownFileExtensions;
+ QLabel *versionLabel;
QWidget *editorDockTitleWidget;
QWidget *consoleDockTitleWidget;
@@ -116,6 +117,7 @@ private:
void show_examples();
void setDockWidgetTitle(QDockWidget *dockWidget, QString prefix, bool topLevel);
void addKeyboardShortCut(const QList &actions);
+ void updateStatusBar(class ProgressWidget *progressWidget);
EditorInterface *editor;
diff --git a/src/OpenCSGRenderer.cc b/src/OpenCSGRenderer.cc
index 3c6f0b48..aa2d6bbb 100644
--- a/src/OpenCSGRenderer.cc
+++ b/src/OpenCSGRenderer.cc
@@ -90,7 +90,12 @@ void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo,
const Color4f &c = j_obj.color;
glPushMatrix();
glMultMatrixd(j_obj.matrix.data());
- csgmode_e csgmode = j_obj.type == CSGTerm::TYPE_DIFFERENCE ? CSGMODE_DIFFERENCE : CSGMODE_NORMAL;
+ csgmode_e csgmode = csgmode_e(
+ (highlight ?
+ CSGMODE_HIGHLIGHT :
+ (background ? CSGMODE_BACKGROUND : CSGMODE_NORMAL)) |
+ (j_obj.type == CSGTerm::TYPE_DIFFERENCE ? CSGMODE_DIFFERENCE : 0));
+
ColorMode colormode = COLORMODE_NONE;
if (background) {
if (j_obj.flag & CSGTerm::FLAG_HIGHLIGHT) {
@@ -99,11 +104,9 @@ void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo,
else {
colormode = COLORMODE_BACKGROUND;
}
- csgmode = csgmode_e(csgmode + 10);
} else if (j_obj.type == CSGTerm::TYPE_DIFFERENCE) {
if (j_obj.flag & CSGTerm::FLAG_HIGHLIGHT) {
colormode = COLORMODE_HIGHLIGHT;
- csgmode = csgmode_e(csgmode + 20);
}
else {
colormode = COLORMODE_CUTOUT;
@@ -111,7 +114,6 @@ void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo,
} else {
if (j_obj.flag & CSGTerm::FLAG_HIGHLIGHT) {
colormode = COLORMODE_HIGHLIGHT;
- csgmode = csgmode_e(csgmode + 20);
}
else {
colormode = COLORMODE_MATERIAL;
@@ -139,9 +141,12 @@ void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo,
prim->geom = i_obj.geom;
prim->m = i_obj.matrix;
- prim->csgmode = i_obj.type == CSGTerm::TYPE_DIFFERENCE ? CSGMODE_DIFFERENCE : CSGMODE_NORMAL;
- if (highlight) prim->csgmode = csgmode_e(prim->csgmode + 20);
- else if (background) prim->csgmode = csgmode_e(prim->csgmode + 10);
+ prim->csgmode = csgmode_e(
+ (highlight ?
+ CSGMODE_HIGHLIGHT :
+ (background ? CSGMODE_BACKGROUND : CSGMODE_NORMAL)) |
+ (i_obj.type == CSGTerm::TYPE_DIFFERENCE ? CSGMODE_DIFFERENCE : 0));
+
primitives.push_back(prim);
}
}
diff --git a/src/ThrownTogetherRenderer.cc b/src/ThrownTogetherRenderer.cc
index 4b114041..dbdf527c 100644
--- a/src/ThrownTogetherRenderer.cc
+++ b/src/ThrownTogetherRenderer.cc
@@ -74,12 +74,15 @@ void ThrownTogetherRenderer::renderCSGChain(CSGChain *chain, bool highlight,
const Color4f &c = obj.color;
glPushMatrix();
glMultMatrixd(m.data());
- csgmode_e csgmode = obj.type == CSGTerm::TYPE_DIFFERENCE ? CSGMODE_DIFFERENCE : CSGMODE_NORMAL;
+ csgmode_e csgmode = csgmode_e(
+ (highlight ?
+ CSGMODE_HIGHLIGHT :
+ (background ? CSGMODE_BACKGROUND : CSGMODE_NORMAL)) |
+ (obj.type == CSGTerm::TYPE_DIFFERENCE ? CSGMODE_DIFFERENCE : 0));
ColorMode colormode = COLORMODE_NONE;
ColorMode edge_colormode = COLORMODE_NONE;
if (highlight) {
- csgmode = csgmode_e(csgmode + 20);
colormode = COLORMODE_HIGHLIGHT;
edge_colormode = COLORMODE_HIGHLIGHT_EDGES;
} else if (background) {
@@ -89,16 +92,11 @@ void ThrownTogetherRenderer::renderCSGChain(CSGChain *chain, bool highlight,
else {
colormode = COLORMODE_BACKGROUND;
}
- csgmode = csgmode_e(csgmode + 10);
edge_colormode = COLORMODE_BACKGROUND_EDGES;
} else if (fberror) {
- if (highlight) csgmode = csgmode_e(csgmode + 20);
- else if (background) csgmode = csgmode_e(csgmode + 10);
- else csgmode = csgmode_e(csgmode);
} else if (obj.type == CSGTerm::TYPE_DIFFERENCE) {
if (obj.flag & CSGTerm::FLAG_HIGHLIGHT) {
colormode = COLORMODE_HIGHLIGHT;
- csgmode = csgmode_e(csgmode + 20);
}
else {
colormode = COLORMODE_CUTOUT;
@@ -107,7 +105,6 @@ void ThrownTogetherRenderer::renderCSGChain(CSGChain *chain, bool highlight,
} else {
if (obj.flag & CSGTerm::FLAG_HIGHLIGHT) {
colormode = COLORMODE_HIGHLIGHT;
- csgmode = csgmode_e(csgmode + 20);
}
else {
colormode = COLORMODE_MATERIAL;
diff --git a/src/launchingscreen.cc b/src/launchingscreen.cc
index 4f08b7d0..3a27f7e4 100644
--- a/src/launchingscreen.cc
+++ b/src/launchingscreen.cc
@@ -2,6 +2,7 @@
#include
#include
+#include "openscad.h"
#include "launchingscreen.h"
#include "ui_launchingscreen.h"
@@ -26,7 +27,9 @@ LaunchingScreen::LaunchingScreen(QWidget *parent) : QDialog(parent)
setupUi(this);
this->setStyleSheet("QDialog {background-image:url(':/icons/background.png')}"
"QPushButton {color:white;}");
-
+
+ this->versionNumberLabel->setText(openscad_version.c_str());
+
QStringList recentFiles = UIUtils::recentFiles();
for (int a = 0;a < recentFiles.size();a++) {
QFileInfo fileInfo(recentFiles[a]);
@@ -75,7 +78,7 @@ QString LaunchingScreen::selectedFile()
return this->selection;
}
-void LaunchingScreen::enableRecentButton(const QModelIndex & current, const QModelIndex & previous)
+void LaunchingScreen::enableRecentButton(const QModelIndex &, const QModelIndex &)
{
this->openRecentButton->setEnabled(true);
this->openRecentButton->setDefault(true);
@@ -91,7 +94,7 @@ void LaunchingScreen::openRecent()
checkOpen(item->data(Qt::UserRole));
}
-void LaunchingScreen::enableExampleButton(QTreeWidgetItem *current, QTreeWidgetItem *previous)
+void LaunchingScreen::enableExampleButton(QTreeWidgetItem *current, QTreeWidgetItem *)
{
const bool enable = current->childCount() == 0;
this->openExampleButton->setEnabled(enable);
diff --git a/src/launchingscreen.ui b/src/launchingscreen.ui
index 67a7d1ea..cd4c8cd8 100644
--- a/src/launchingscreen.ui
+++ b/src/launchingscreen.ui
@@ -6,10 +6,16 @@
0
0
- 618
+ 620
418
+
+
+ 600
+ 0
+
+
Welcome to OpenSCAD
@@ -331,16 +337,32 @@ QPushButton:pressed {
- -
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Version
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
true
-
-
- 600
- 0
-
+
+
+ 0
+ 0
+
false
diff --git a/src/mainwin.cc b/src/mainwin.cc
index 8f399c21..8841349a 100644
--- a/src/mainwin.cc
+++ b/src/mainwin.cc
@@ -24,6 +24,7 @@
*
*/
#include
+#include "openscad.h"
#include "GeometryCache.h"
#include "ModuleCache.h"
#include "MainWindow.h"
@@ -124,15 +125,6 @@ QSet *MainWindow::getWindows()
// 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)
-#ifdef OPENSCAD_COMMIT
- " (git " QUOTED(OPENSCAD_COMMIT) ")"
-#endif
- "\nhttp://www.openscad.org\n\n";
static char copyrighttext[] =
"Copyright (C) 2009-2014 The OpenSCAD Developers\n"
"\n"
@@ -189,6 +181,9 @@ MainWindow::MainWindow(const QString &filename)
this->consoleDock->setConfigKey("view/hideConsole");
this->consoleDock->setAction(this->viewActionHideConsole);
+ this->versionLabel = NULL; // must be initialized before calling updateStatusBar()
+ updateStatusBar(NULL);
+
QSettings settings;
editortype = settings.value("editor/editortype").toString();
useScintilla = (editortype != "Simple Editor");
@@ -407,6 +402,7 @@ MainWindow::MainWindow(const QString &filename)
setCurrentOutput();
+ std::string helptitle = openscad_version + "\nhttp://www.openscad.org\n\n";
PRINT(helptitle);
PRINT(copyrighttext);
PRINT("");
@@ -687,7 +683,7 @@ MainWindow::~MainWindow()
void MainWindow::showProgress()
{
- this->statusBar()->addPermanentWidget(qobject_cast(sender()));
+ updateStatusBar(qobject_cast(sender()));
}
void MainWindow::report_func(const class AbstractNode*, void *vp, int mark)
@@ -1060,9 +1056,7 @@ void MainWindow::compileCSG(bool procevents)
PRINT("CSG generation cancelled.");
}
progress_report_fin();
- this->statusBar()->removeWidget(this->progresswidget);
- delete this->progresswidget;
- this->progresswidget = NULL;
+ updateStatusBar(NULL);
PRINT("Compiling design (CSG Products normalization)...");
if (procevents) QApplication::processEvents();
@@ -1800,15 +1794,47 @@ void MainWindow::actionRenderDone(shared_ptr root_geom)
PRINT("WARNING: No top level geometry to render");
}
- this->statusBar()->removeWidget(this->progresswidget);
- delete this->progresswidget;
- this->progresswidget = NULL;
+ updateStatusBar(NULL);
+
this->contentschanged = false;
compileEnded();
}
#endif /* ENABLE_CGAL */
+/**
+ * Switch version label and progress widget. When switching to the progress
+ * widget, the new instance is passed by the caller.
+ * In case of resetting back to the version label, NULL will be passed and
+ * multiple calls can happen. So this method must guard against adding the
+ * version label multiple times.
+ *
+ * @param progressWidget a pointer to the progress widget to show or NULL in
+ * case the display should switch back to the version label.
+ */
+void MainWindow::updateStatusBar(ProgressWidget *progressWidget)
+{
+ QStatusBar *sb = this->statusBar();
+ if (progressWidget == NULL) {
+ if (this->progresswidget != NULL) {
+ sb->removeWidget(this->progresswidget);
+ delete this->progresswidget;
+ this->progresswidget = NULL;
+ }
+ if (versionLabel == NULL) {
+ versionLabel = new QLabel(openscad_version.c_str());
+ sb->addPermanentWidget(this->versionLabel);
+ }
+ } else {
+ if (this->versionLabel != NULL) {
+ sb->removeWidget(this->versionLabel);
+ delete this->versionLabel;
+ this->versionLabel = NULL;
+ }
+ sb->addPermanentWidget(progressWidget);
+ }
+}
+
void MainWindow::actionDisplayAST()
{
setCurrentOutput();
@@ -2403,7 +2429,6 @@ void MainWindow::helpAbout()
qApp->setWindowIcon(QApplication::windowIcon());
AboutDialog *dialog = new AboutDialog(this);
dialog->exec();
- //QMessageBox::information(this, "About OpenSCAD", QString(helptitle) + QString(copyrighttext));
}
void MainWindow::helpHomepage()
diff --git a/src/openscad.cc b/src/openscad.cc
index 531ccf15..034eced5 100644
--- a/src/openscad.cc
+++ b/src/openscad.cc
@@ -90,6 +90,17 @@ std::string currentdir;
static bool arg_info = false;
static std::string arg_colorscheme;
+#define QUOTE(x__) # x__
+#define QUOTED(x__) QUOTE(x__)
+
+std::string openscad_versionnumber = QUOTED(OPENSCAD_VERSION)
+#ifdef OPENSCAD_COMMIT
+ " (git " QUOTED(OPENSCAD_COMMIT) ")"
+#endif
+;
+
+std::string openscad_version = "OpenSCAD " + openscad_versionnumber;
+
class Echostream : public std::ofstream
{
public:
@@ -590,7 +601,9 @@ void dialogThreadFunc(FontCacheInitializer *initializer)
void dialogInitHandler(FontCacheInitializer *initializer, void *)
{
QProgressDialog dialog;
- dialog.setLabelText("Fontconfig needs to update its font cache.\nThis can take up to a couple of minutes.");
+ dialog.setLabelText(_("Fontconfig needs to update its font cache.\nThis can take up to a couple of minutes."));
+ dialog.setMinimum(0);
+ dialog.setMaximum(0);
dialog.setCancelButton(0);
QFutureWatcher futureWatcher;
@@ -617,6 +630,9 @@ int gui(vector &inputFiles, const fs::path &original_path, int argc, cha
}
#endif
QApplication app(argc, argv, true); //useGUI);
+ // remove ugly frames in the QStatusBar when using additional widgets
+ app.setStyleSheet("QStatusBar::item { border: 0px solid black }; ");
+
#ifdef Q_OS_MAC
app.installEventFilter(new EventFilter(&app));
#endif
diff --git a/src/openscad.h b/src/openscad.h
index 0e979659..f37f0253 100644
--- a/src/openscad.h
+++ b/src/openscad.h
@@ -34,3 +34,11 @@ extern std::string commandline_commands;
// The CWD when application started. We shouldn't change CWD, but until we stop
// doing this, use currentdir to get the original CWD.
extern std::string currentdir;
+
+extern std::string versionnumber;
+
+// Just the number (might have the git commit as suffix), e.g. 2014.12.23.
+extern std::string openscad_versionnumber;
+
+// The string "OpenSCAD " and the version number.
+extern std::string openscad_version;
diff --git a/src/polyset.cc b/src/polyset.cc
index ad6b6e59..00ae963f 100644
--- a/src/polyset.cc
+++ b/src/polyset.cc
@@ -240,7 +240,7 @@ void PolySet::render_surface(Renderer::csgmode_e csgmode, const Transform3d &m,
#endif /* ENABLE_OPENCSG */
if (this->dim == 2) {
// Render 2D objects 1mm thick, but differences slightly larger
- double zbase = 1 + (csgmode & CSGMODE_DIFFERENCE_FLAG) * 0.1;
+ double zbase = 1 + ((csgmode & CSGMODE_DIFFERENCE_FLAG) ? 0.1 : 0);
glBegin(GL_TRIANGLES);
// Render top+bottom
@@ -369,7 +369,7 @@ void PolySet::render_edges(Renderer::csgmode_e csgmode) const
}
else {
// Render 2D objects 1mm thick, but differences slightly larger
- double zbase = 1 + (csgmode & CSGMODE_DIFFERENCE_FLAG) * 0.1;
+ double zbase = 1 + ((csgmode & CSGMODE_DIFFERENCE_FLAG) ? 0.1 : 0);
BOOST_FOREACH(const Outline2d &o, polygon.outlines()) {
// Render top+bottom outlines
diff --git a/testdata/scad/2D/features/highlight-modifier-2d.scad b/testdata/scad/2D/features/highlight-modifier-2d.scad
new file mode 100644
index 00000000..7779fd69
--- /dev/null
+++ b/testdata/scad/2D/features/highlight-modifier-2d.scad
@@ -0,0 +1,10 @@
+difference() {
+ square(10, center=true);
+ #circle(3);
+}
+#if (true) square([11,12]);
+
+#translate([0,-12]) difference() {
+ square(10, center = true);
+ square(5, center = true);
+}
diff --git a/tests/regression/cgalpngtest/highlight-modifier-2d-expected.png b/tests/regression/cgalpngtest/highlight-modifier-2d-expected.png
new file mode 100644
index 00000000..9c2cedf1
Binary files /dev/null and b/tests/regression/cgalpngtest/highlight-modifier-2d-expected.png differ
diff --git a/tests/regression/cgalpngtest/offset-tests-expected.png b/tests/regression/cgalpngtest/offset-tests-expected.png
index fbcd7248..3da4452b 100644
Binary files a/tests/regression/cgalpngtest/offset-tests-expected.png and b/tests/regression/cgalpngtest/offset-tests-expected.png differ
diff --git a/tests/regression/dumptest/highlight-modifier-2d-expected.csg b/tests/regression/dumptest/highlight-modifier-2d-expected.csg
new file mode 100644
index 00000000..833d1ea4
--- /dev/null
+++ b/tests/regression/dumptest/highlight-modifier-2d-expected.csg
@@ -0,0 +1,15 @@
+group() {
+ difference() {
+ square(size = [10, 10], center = true);
+# circle($fn = 0, $fa = 12, $fs = 2, r = 3);
+ }
+# group() {
+ square(size = [11, 12], center = false);
+ }
+# multmatrix([[1, 0, 0, 0], [0, 1, 0, -12], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ difference() {
+ square(size = [10, 10], center = true);
+ square(size = [5, 5], center = true);
+ }
+ }
+}
diff --git a/tests/regression/opencsgtest/difference-tests-expected.png b/tests/regression/opencsgtest/difference-tests-expected.png
index 69a4ac2e..4ffb06fd 100644
Binary files a/tests/regression/opencsgtest/difference-tests-expected.png and b/tests/regression/opencsgtest/difference-tests-expected.png differ
diff --git a/tests/regression/opencsgtest/highlight-modifier-2d-expected.png b/tests/regression/opencsgtest/highlight-modifier-2d-expected.png
new file mode 100644
index 00000000..24342191
Binary files /dev/null and b/tests/regression/opencsgtest/highlight-modifier-2d-expected.png differ
diff --git a/tests/regression/opencsgtest/offset-tests-expected.png b/tests/regression/opencsgtest/offset-tests-expected.png
index a671a091..d1f6f921 100644
Binary files a/tests/regression/opencsgtest/offset-tests-expected.png and b/tests/regression/opencsgtest/offset-tests-expected.png differ
diff --git a/tests/regression/throwntogethertest/difference-tests-expected.png b/tests/regression/throwntogethertest/difference-tests-expected.png
index 4702fbff..fb1753c5 100644
Binary files a/tests/regression/throwntogethertest/difference-tests-expected.png and b/tests/regression/throwntogethertest/difference-tests-expected.png differ
diff --git a/tests/regression/throwntogethertest/highlight-modifier-2d-expected.png b/tests/regression/throwntogethertest/highlight-modifier-2d-expected.png
new file mode 100644
index 00000000..404d9e18
Binary files /dev/null and b/tests/regression/throwntogethertest/highlight-modifier-2d-expected.png differ
diff --git a/tests/regression/throwntogethertest/offset-tests-expected.png b/tests/regression/throwntogethertest/offset-tests-expected.png
index cd845049..2c25d292 100644
Binary files a/tests/regression/throwntogethertest/offset-tests-expected.png and b/tests/regression/throwntogethertest/offset-tests-expected.png differ
diff --git a/winconsole.pri b/winconsole.pri
deleted file mode 100644
index a3991ae7..00000000
--- a/winconsole.pri
+++ /dev/null
@@ -1,28 +0,0 @@
-# Windows console issues workaround stub.
-#
-# Usage: put at the end of .pro file, then run qmake CONFIG+=winconsole
-#
-# This attempts to solve the problem of piping OpenSCAD under windows
-# command line (GUI mode programs in Windows dont allow this). We use
-# the 'devenv' solution, which means building two binaries:
-# openscad.exe, and openscad.com, the latter being a wrapper for the
-# former. See src/winconsole.c for more details.
-#
-# Qmake doesn't like building two binaries in the same directory so we
-# depend on release-common.sh to call qmake twice and package the file properly
-
-CONFIG(winconsole) {
- TEMPLATE = app
- TARGET = openscad_winconsole
- FORMS =
- HEADERS =
- FLEXSOURCES =
- BISONSOURCES =
- RESOURCES =
- SOURCES = src/winconsole.c
- CONFIG += console # sets IMAGE_SUBSYSTEM_WINDOWS_CUI in binary
- LIBS -= $$LIBS
- RC_FILE -= $$RC_FILE
- QMAKE_POST_LINK = cd $(DESTDIR) && mv openscad_winconsole.exe openscad.com
-}
-
diff --git a/winconsole.pro b/winconsole.pro
new file mode 100644
index 00000000..11078f36
--- /dev/null
+++ b/winconsole.pro
@@ -0,0 +1,23 @@
+# Windows console issues workaround stub.
+#
+# This attempts to solve the problem of piping OpenSCAD under windows
+# command line (GUI mode programs in Windows dont allow this). We use
+# the 'devenv' solution, which means building two binaries:
+# openscad.exe, and openscad.com, the latter being a wrapper for the
+# former. See src/winconsole.c for more details.
+#
+# Qmake doesn't like building two binaries in the same directory so we
+# depend on release-common.sh to call qmake twice and package the file
+# properly
+
+TEMPLATE = app
+TARGET = openscad_winconsole
+FORMS =
+HEADERS =
+FLEXSOURCES =
+BISONSOURCES =
+RESOURCES =
+SOURCES = src/winconsole.c
+CONFIG -= qt
+CONFIG += console # sets IMAGE_SUBSYSTEM_WINDOWS_CUI in binary
+QMAKE_POST_LINK = cd $(DESTDIR) && mv openscad_winconsole.exe openscad.com