mirror of https://github.com/vitalif/openscad
Merge branch 'master' into unstable
Conflicts: src/CGALEvaluator.cc src/MainWindow.h src/MainWindow.ui src/import.cc src/mainwin.cc src/winconsole.c tests/CMakeLists.txtsvg-export
commit
bab951b344
|
@ -1,22 +1,23 @@
|
|||
OpenSCAD YYYY.MM
|
||||
OpenSCAD 2014.0X
|
||||
================
|
||||
|
||||
Language Features:
|
||||
o Added diameter argument: circle(d), cylinder(d, d1, d2) and sphere(d)
|
||||
o Added parent_module() and $parent_modules
|
||||
o Added children() as a replacement for child()
|
||||
o FIXME: Unicode support
|
||||
o FIXME: Ranges with negative steps
|
||||
o FIXME: Experimental concat()
|
||||
o Unicode strings (using UTF-8) are now correctly handled
|
||||
o Ranges can have a negative step value
|
||||
o Added experimental concat() function for concatenating vectors
|
||||
|
||||
Program Features:
|
||||
o Added --info parameter to the cmd-line for system/library info
|
||||
o Added --enable parameter to enable experimental features
|
||||
o Added --csglimit parameter to change CSG rendering limit
|
||||
o Added Reset View in GUI
|
||||
o Added Feature tab in Preferences
|
||||
o Cmd-line: --info parameter prints system/library info
|
||||
o Cmd-line: --enable parameter to enable experimental features
|
||||
o Cmd-line: --csglimit parameter to change CSG rendering limit
|
||||
o GUI: Added Reset View
|
||||
o GUI: Added Search&Replace in editor
|
||||
o GUI: Syntax highlighting now has a dark background theme
|
||||
|
||||
Bugfixes:
|
||||
Bugfixes/improvements:
|
||||
o polyhedron() is now much more robust handling almost planar polygons
|
||||
o Automatic reloads of large designs are more robust
|
||||
o Boolean logic in if() statements are now correctly short-circuited
|
||||
|
@ -25,20 +26,24 @@ o resize(, auto=true) didn't work when shrinking objects
|
|||
o The $children variable sometimes misbehaved due to dynamic scoping
|
||||
o The --camera cmd-line option behaved differently then the corresponding GUI function
|
||||
o PNG export now doesn't leak transparency settings into the target image
|
||||
o Improved performance of OpenCSG (F5) compilation in some cases
|
||||
o Improved performance of 3D hull() operations
|
||||
o Some editor misbehaviors were fixed
|
||||
o Stability fixes of CGAL-related crashes
|
||||
o Windows cmd-line can now handle spaces in filenames
|
||||
o Default CSG rendering limit is now 100K elements
|
||||
o Fixed a crash reading DXF files using comma as decimal separator
|
||||
o Fixed a crash running the cmd-line without a HOME env. variable
|
||||
o Intersecting something with nothing now correctly results in an empty object
|
||||
|
||||
Deprecations:
|
||||
o child() is no longer supported. Use children() instead.
|
||||
o polyhedron(triangles=[...]): Use polyhedron(faces=[...]) instead.
|
||||
|
||||
Misc:
|
||||
o We now use CGAL's EPEC kernel
|
||||
o Additional output formats: .ast, .term, null (these are most useful for testing)
|
||||
o Test framework now shares more code with the GUI app
|
||||
o Test report can now be automatically uploaded to dinkypage.com
|
||||
o Better compatibility with BSD systems
|
||||
o Qt5 support
|
||||
|
||||
OpenSCAD 2013.06
|
||||
================
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
module step(len, mod)
|
||||
{
|
||||
for (i = [0:$children-1])
|
||||
translate([ len*(i - ($children-1)/2), 0, 0 ]) child((i+mod) % $children);
|
||||
translate([ len*(i - ($children-1)/2), 0, 0 ]) children((i+mod) % $children);
|
||||
}
|
||||
|
||||
for (i = [1:4])
|
||||
|
|
|
@ -85,8 +85,14 @@ get_openscad_source_code()
|
|||
if [ "`echo $? | grep 0`" ]; then
|
||||
echo clone of source code is ok
|
||||
else
|
||||
echo clone of openscad source code failed. exiting
|
||||
exit 1
|
||||
if [ $DOUPLOAD ]; then
|
||||
if [ ! $DOBUILD ]; then
|
||||
echo upload only - skipping openscad git clone
|
||||
fi
|
||||
else
|
||||
echo clone of openscad source code failed. exiting
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
cd openscad
|
||||
git submodule update --init # MCAD
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
# NB! To build a release build, the VERSION and VERSIONDATE environment variables needs to be set.
|
||||
# See doc/release-checklist.txt
|
||||
|
||||
export NUMCPU=$(sysctl -n hw.ncpu)
|
||||
|
||||
human_filesize()
|
||||
{
|
||||
awk -v sum=$1 'BEGIN {
|
||||
|
@ -20,6 +22,7 @@ update_www_download_links()
|
|||
local $*
|
||||
filesize=$(human_filesize $filesize)
|
||||
webdir=../openscad.github.com
|
||||
# FIXME: release vs. snapshot
|
||||
incfile=inc/mac_snapshot_links.js
|
||||
BASEURL='http://files.openscad.org/'
|
||||
DATECODE=`date +"%Y.%m.%d"`
|
||||
|
@ -51,7 +54,7 @@ fi
|
|||
PATH=${PATH//\/opt\/local\/libexec\/ccache:}
|
||||
|
||||
# This is the same location as DEPLOYDIR in macosx-build-dependencies.sh
|
||||
export OPENSCAD_LIBRARIES=$PWD/../libraries/install
|
||||
export OPENSCAD_LIBRARIES=$PWD/../libraries/homebrew
|
||||
|
||||
# Make sure that the correct Qt tools are used
|
||||
export PATH=$OPENSCAD_LIBRARIES/bin:$PATH
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "memory.h"
|
||||
#include <vector>
|
||||
#include <QMutex>
|
||||
#include <QSet>
|
||||
|
||||
class MainWindow : public QMainWindow, public Ui::MainWindow
|
||||
{
|
||||
|
@ -88,6 +89,8 @@ private:
|
|||
static void consoleOutput(const std::string &msg, void *userdata);
|
||||
void loadViewSettings();
|
||||
void loadDesignSettings();
|
||||
void saveBackup();
|
||||
void writeBackup(class QFile *file);
|
||||
|
||||
class QMessageBox *openglbox;
|
||||
|
||||
|
@ -150,6 +153,7 @@ private slots:
|
|||
void actionFlushCaches();
|
||||
|
||||
public:
|
||||
static QSet<MainWindow*> *windows;
|
||||
static void setExamplesDir(const QString &dir) { MainWindow::qexamplesdir = dir; }
|
||||
void viewModeActionsUncheck();
|
||||
void setCurrentOutput();
|
||||
|
@ -196,13 +200,17 @@ public slots:
|
|||
|
||||
private:
|
||||
static void report_func(const class AbstractNode*, void *vp, int mark);
|
||||
|
||||
|
||||
char const * afterCompileSlot;
|
||||
bool procevents;
|
||||
|
||||
class QTemporaryFile *tempFile;
|
||||
|
||||
class ProgressWidget *progresswidget;
|
||||
class CGALWorker *cgalworker;
|
||||
QMutex consolemutex;
|
||||
signals:
|
||||
void highlightError(int);
|
||||
void unhighlightLastError();
|
||||
};
|
||||
|
||||
class GuiLocker
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>681</width>
|
||||
<width>846</width>
|
||||
<height>647</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
@ -15,16 +15,7 @@
|
|||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
|
@ -32,14 +23,14 @@
|
|||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="editorlayoutwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<widget class="QWidget" name="editorPane" native="true">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="find_panel">
|
||||
<property name="enabled">
|
||||
|
@ -60,72 +51,8 @@
|
|||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="1" column="3" colspan="2">
|
||||
<widget class="QPushButton" name="replaceButton">
|
||||
<property name="text">
|
||||
<string>Replace</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="5">
|
||||
<widget class="QPushButton" name="replaceAllButton">
|
||||
<property name="text">
|
||||
<string>All</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLineEdit" name="findInputField">
|
||||
<property name="placeholderText">
|
||||
<string>Search string</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLineEdit" name="replaceInputField">
|
||||
<property name="placeholderText">
|
||||
<string>Replacement string</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QPushButton" name="prevButton">
|
||||
<property name="text">
|
||||
<string><</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QPushButton" name="nextButton">
|
||||
<property name="text">
|
||||
<string>></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="5">
|
||||
<widget class="QPushButton" name="hideFindButton">
|
||||
<property name="text">
|
||||
<string>Done</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QComboBox" name="findTypeComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
|
@ -139,6 +66,55 @@
|
|||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="findInputField">
|
||||
<property name="placeholderText">
|
||||
<string>Search string</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="prevButton">
|
||||
<property name="text">
|
||||
<string><</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QPushButton" name="nextButton">
|
||||
<property name="text">
|
||||
<string>></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QPushButton" name="hideFindButton">
|
||||
<property name="text">
|
||||
<string>Done</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="replaceInputField">
|
||||
<property name="placeholderText">
|
||||
<string>Replacement string</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" colspan="2">
|
||||
<widget class="QPushButton" name="replaceButton">
|
||||
<property name="text">
|
||||
<string>Replace</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="QPushButton" name="replaceAllButton">
|
||||
<property name="text">
|
||||
<string>All</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -183,17 +159,8 @@
|
|||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<layout class="QHBoxLayout" name="horizontalLayoutAnimate">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
|
@ -247,7 +214,7 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>681</width>
|
||||
<width>846</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
@ -265,16 +232,31 @@
|
|||
<string>Examples</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuExport">
|
||||
<property name="title">
|
||||
<string>Export</string>
|
||||
</property>
|
||||
<addaction name="designActionExportSTL"/>
|
||||
<addaction name="designActionExportOFF"/>
|
||||
<addaction name="designActionExportDXF"/>
|
||||
<addaction name="designActionExportCSG"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="designActionExportImage"/>
|
||||
</widget>
|
||||
<addaction name="fileActionNew"/>
|
||||
<addaction name="fileActionOpen"/>
|
||||
<addaction name="menuOpenRecent"/>
|
||||
<addaction name="menuExamples"/>
|
||||
<addaction name="fileShowLibraryFolder"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="fileActionReload"/>
|
||||
<addaction name="fileActionClose"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="fileActionSave"/>
|
||||
<addaction name="fileActionSaveAs"/>
|
||||
<addaction name="fileActionReload"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="menuExport"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="fileShowLibraryFolder"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="fileActionQuit"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Edit">
|
||||
|
@ -316,17 +298,11 @@
|
|||
<addaction name="designActionPreview"/>
|
||||
<addaction name="designActionRender"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="designCheckValidity"/>
|
||||
<addaction name="designCheckValidity"/>
|
||||
<addaction name="designActionDisplayAST"/>
|
||||
<addaction name="designActionDisplayCSGTree"/>
|
||||
<addaction name="designActionDisplayCSGProducts"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="designActionExportSTL"/>
|
||||
<addaction name="designActionExportOFF"/>
|
||||
<addaction name="designActionExportDXF"/>
|
||||
<addaction name="designActionExportCSG"/>
|
||||
<addaction name="designActionExportImage"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="designActionFlushCaches"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_View">
|
||||
|
@ -559,9 +535,9 @@
|
|||
</property>
|
||||
</action>
|
||||
<action name="designCheckValidity">
|
||||
<property name="text">
|
||||
<string>Check Validity</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Check Validity</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="designActionDisplayAST">
|
||||
<property name="text">
|
||||
|
|
|
@ -22,51 +22,68 @@
|
|||
ModuleCache *ModuleCache::inst = NULL;
|
||||
|
||||
/*!
|
||||
Reevaluate the given file and recompile if necessary.
|
||||
Returns NULL on any error (e.g. compile error or file not found)
|
||||
Reevaluate the given file and all it's dependencies and recompile anything
|
||||
needing reevaluation.
|
||||
The given filename must be absolute.
|
||||
|
||||
If the given filename is relative, it means that the module hasn't been
|
||||
previously located.
|
||||
Sets the module reference to the new modile, or NULL on any error (e.g. compile
|
||||
error or file not found)
|
||||
|
||||
Returns true if anything was compiled (module or dependencies) and false otherwise.
|
||||
*/
|
||||
FileModule *ModuleCache::evaluate(const std::string &filename)
|
||||
bool ModuleCache::evaluate(const std::string &filename, FileModule *&module)
|
||||
{
|
||||
FileModule *lib_mod = (this->entries.find(filename) != this->entries.end()) ?
|
||||
&(*this->entries[filename].module) : NULL;
|
||||
|
||||
FileModule *lib_mod = NULL;
|
||||
bool found = false;
|
||||
if (this->entries.find(filename) != this->entries.end()) {
|
||||
found = true;
|
||||
lib_mod = this->entries[filename].module;
|
||||
}
|
||||
|
||||
// Don't try to recursively evaluate - if the file changes
|
||||
// during evaluation, that would be really bad.
|
||||
if (lib_mod && lib_mod->isHandlingDependencies()) return lib_mod;
|
||||
|
||||
bool shouldCompile = true;
|
||||
|
||||
// Create cache ID
|
||||
struct stat st;
|
||||
memset(&st, 0, sizeof(struct stat));
|
||||
bool valid = (stat(filename.c_str(), &st) == 0);
|
||||
|
||||
// If file isn't there, just return and let the cache retain the old module
|
||||
if (!valid) return NULL;
|
||||
|
||||
// If file isn't there, just return and let the cache retain the old module
|
||||
if (!valid) return false;
|
||||
|
||||
// If the file is present, we'll always cache some result
|
||||
std::string cache_id = str(boost::format("%x.%x") % st.st_mtime % st.st_size);
|
||||
|
||||
// Lookup in cache
|
||||
if (lib_mod) {
|
||||
if (this->entries[filename].cache_id == cache_id) {
|
||||
cache_entry &entry = this->entries[filename];
|
||||
// Initialize entry, if new
|
||||
if (!found) {
|
||||
entry.module = NULL;
|
||||
entry.cache_id = cache_id;
|
||||
}
|
||||
|
||||
bool shouldCompile = true;
|
||||
if (found) {
|
||||
// Files should only be recompiled if the cache ID changed
|
||||
if (entry.cache_id == cache_id) {
|
||||
shouldCompile = false;
|
||||
if (lib_mod->includesChanged()) {
|
||||
// Recompile if includes changed
|
||||
if (lib_mod && lib_mod->includesChanged()) {
|
||||
lib_mod = NULL;
|
||||
shouldCompile = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
shouldCompile = valid;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// Causes too much debug output
|
||||
//if (!shouldCompile) PRINTB("Using cached library: %s (%p)", filename % lib_mod);
|
||||
#endif
|
||||
|
||||
// If cache lookup failed (non-existing or old timestamp), compile module
|
||||
if (shouldCompile) {
|
||||
#ifdef DEBUG
|
||||
if (this->entries.find(filename) != this->entries.end()) {
|
||||
if (found) {
|
||||
PRINTB("Recompiling cached library: %s (%s)", filename % cache_id);
|
||||
}
|
||||
else {
|
||||
|
@ -79,42 +96,33 @@ FileModule *ModuleCache::evaluate(const std::string &filename)
|
|||
std::ifstream ifs(filename.c_str());
|
||||
if (!ifs.is_open()) {
|
||||
PRINTB("WARNING: Can't open library file '%s'\n", filename);
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
textbuf << ifs.rdbuf();
|
||||
}
|
||||
textbuf << "\n" << commandline_commands;
|
||||
|
||||
|
||||
print_messages_push();
|
||||
|
||||
FileModule *oldmodule = NULL;
|
||||
cache_entry e = { NULL, cache_id };
|
||||
if (this->entries.find(filename) != this->entries.end()) {
|
||||
oldmodule = this->entries[filename].module;
|
||||
}
|
||||
this->entries[filename] = e;
|
||||
|
||||
FileModule *oldmodule = lib_mod;
|
||||
|
||||
std::string pathname = boosty::stringy(fs::path(filename).parent_path());
|
||||
lib_mod = dynamic_cast<FileModule*>(parse(textbuf.str().c_str(), pathname.c_str(), false));
|
||||
PRINTB_NOCACHE(" compiled module: %p", lib_mod);
|
||||
|
||||
if (lib_mod) {
|
||||
// We defer deletion so we can ensure that the new module won't
|
||||
// have the same address as the old
|
||||
delete oldmodule;
|
||||
this->entries[filename].module = lib_mod;
|
||||
} else {
|
||||
this->entries.erase(filename);
|
||||
}
|
||||
// We defer deletion so we can ensure that the new module won't
|
||||
// have the same address as the old
|
||||
if (oldmodule) delete oldmodule;
|
||||
entry.module = lib_mod;
|
||||
entry.cache_id = cache_id;
|
||||
|
||||
print_messages_pop();
|
||||
}
|
||||
|
||||
module = lib_mod;
|
||||
bool depschanged = lib_mod ? lib_mod->handleDependencies() : false;
|
||||
|
||||
if (lib_mod) {
|
||||
lib_mod->handleDependencies();
|
||||
}
|
||||
|
||||
return lib_mod;
|
||||
return shouldCompile || depschanged;
|
||||
}
|
||||
|
||||
void ModuleCache::clear()
|
||||
|
@ -124,7 +132,11 @@ void ModuleCache::clear()
|
|||
|
||||
FileModule *ModuleCache::lookup(const std::string &filename)
|
||||
{
|
||||
return (this->entries.find(filename) != this->entries.end()) ?
|
||||
&(*this->entries[filename].module) : NULL;
|
||||
return isCached(filename) ? this->entries[filename].module : NULL;
|
||||
}
|
||||
|
||||
bool ModuleCache::isCached(const std::string &filename)
|
||||
{
|
||||
return this->entries.find(filename) != this->entries.end();
|
||||
}
|
||||
|
||||
|
|
|
@ -8,8 +8,9 @@ class ModuleCache
|
|||
{
|
||||
public:
|
||||
static ModuleCache *instance() { if (!inst) inst = new ModuleCache; return inst; }
|
||||
class FileModule *evaluate(const std::string &filename);
|
||||
bool evaluate(const std::string &filename, class FileModule *&module);
|
||||
class FileModule *lookup(const std::string &filename);
|
||||
bool isCached(const std::string &filename);
|
||||
size_t size() { return this->entries.size(); }
|
||||
void clear();
|
||||
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
#include "PlatformUtils.h"
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
std::string PlatformUtils::pathSeparatorChar()
|
||||
{
|
||||
return ":";
|
||||
}
|
||||
|
||||
std::string PlatformUtils::documentsPath()
|
||||
{
|
||||
return std::string([[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] UTF8String]);
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
#include "PlatformUtils.h"
|
||||
#include "boosty.h"
|
||||
|
||||
std::string PlatformUtils::pathSeparatorChar()
|
||||
{
|
||||
return ":";
|
||||
}
|
||||
|
||||
std::string PlatformUtils::documentsPath()
|
||||
{
|
||||
const char *home = getenv("HOME");
|
||||
|
|
|
@ -6,6 +6,11 @@
|
|||
#endif
|
||||
#include <shlobj.h>
|
||||
|
||||
std::string PlatformUtils::pathSeparatorChar()
|
||||
{
|
||||
return ";";
|
||||
}
|
||||
|
||||
// convert from windows api w_char strings (usually utf16) to utf8 std::string
|
||||
std::string winapi_wstr_to_utf8( std::wstring wstr )
|
||||
{
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#include <glib.h>
|
||||
|
||||
#include "PlatformUtils.h"
|
||||
#include "boosty.h"
|
||||
|
||||
#include <glib.h>
|
||||
extern std::vector<std::string> librarypath;
|
||||
|
||||
bool PlatformUtils::createLibraryPath()
|
||||
{
|
||||
|
@ -41,6 +43,40 @@ std::string PlatformUtils::libraryPath()
|
|||
return boosty::stringy( path );
|
||||
}
|
||||
|
||||
|
||||
std::string PlatformUtils::backupPath()
|
||||
{
|
||||
fs::path path;
|
||||
try {
|
||||
std::string pathstr = PlatformUtils::documentsPath();
|
||||
if (pathstr=="") return "";
|
||||
path = boosty::canonical(fs::path( pathstr ));
|
||||
if (path.empty()) return "";
|
||||
path /= "OpenSCAD";
|
||||
path /= "backups";
|
||||
} catch (const fs::filesystem_error& ex) {
|
||||
PRINTB("ERROR: %s",ex.what());
|
||||
}
|
||||
return boosty::stringy( path );
|
||||
}
|
||||
|
||||
bool PlatformUtils::createBackupPath()
|
||||
{
|
||||
std::string path = PlatformUtils::backupPath();
|
||||
bool OK = false;
|
||||
try {
|
||||
if (!fs::exists(fs::path(path))) {
|
||||
OK = fs::create_directories( path );
|
||||
}
|
||||
if (!OK) {
|
||||
PRINTB("ERROR: Cannot create %s", path );
|
||||
}
|
||||
} catch (const fs::filesystem_error& ex) {
|
||||
PRINTB("ERROR: %s",ex.what());
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
#include "version_check.h"
|
||||
#define STRINGIFY(x) #x
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
|
@ -108,6 +144,8 @@ std::string PlatformUtils::info()
|
|||
std::string cgal_2d_kernelEx = "";
|
||||
#endif // ENABLE_CGAL
|
||||
|
||||
const char *env_path = getenv("OPENSCADPATH");
|
||||
|
||||
s << "OpenSCAD Version: " << TOSTRING(OPENSCAD_VERSION)
|
||||
<< "\nCompiler, build date: " << compiler_info << ", " << __DATE__
|
||||
<< "\nBoost version: " << BOOST_LIB_VERSION
|
||||
|
@ -117,8 +155,12 @@ std::string PlatformUtils::info()
|
|||
<< "\nQt version: " << qtVersion
|
||||
<< "\nMingW build: " << mingwstatus
|
||||
<< "\nGLib version: " << GLIB_MAJOR_VERSION << "." << GLIB_MINOR_VERSION << "." << GLIB_MICRO_VERSION
|
||||
<< "\nOPENSCADPATH: " << getenv("OPENSCADPATH") << "\n"
|
||||
;
|
||||
<< "\nOPENSCADPATH: " << (env_path == NULL ? "<not set>" : env_path)
|
||||
<< "\nOpenSCAD library path:\n";
|
||||
|
||||
for (std::vector<std::string>::iterator it = librarypath.begin();it != librarypath.end();it++) {
|
||||
s << " " << *it << "\n";
|
||||
}
|
||||
|
||||
return s.str();
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,18 @@ namespace PlatformUtils {
|
|||
std::string documentsPath();
|
||||
std::string libraryPath();
|
||||
bool createLibraryPath();
|
||||
std::string backupPath();
|
||||
bool createBackupPath();
|
||||
std::string info();
|
||||
|
||||
/**
|
||||
* Single character separating path specifications in a list
|
||||
* (e.g. OPENSCADPATH). On Windows that's ';' and on most other
|
||||
* systems ':'.
|
||||
*
|
||||
* @return the path separator
|
||||
*/
|
||||
std::string pathSeparatorChar();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -417,8 +417,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>803</width>
|
||||
<height>311</height>
|
||||
<width>98</width>
|
||||
<height>36</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||
|
@ -577,6 +577,12 @@
|
|||
<property name="allowedAreas">
|
||||
<set>Qt::TopToolBarArea</set>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextUnderIcon</enum>
|
||||
</property>
|
||||
|
|
|
@ -161,6 +161,7 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
|
|||
|
||||
if (type == CHILD)
|
||||
{
|
||||
PRINT("DEPRECATED: child() will be removed in future releases. Use children() instead.");
|
||||
int n = 0;
|
||||
if (evalctx->numArgs() > 0) {
|
||||
double v;
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
#include "editor.h"
|
||||
#include "Preferences.h"
|
||||
|
||||
Editor::Editor(QWidget *parent) : QTextEdit(parent)
|
||||
{
|
||||
setAcceptRichText(false);
|
||||
this->highlighter = new Highlighter(this->document());
|
||||
}
|
||||
|
||||
void Editor::indentSelection()
|
||||
{
|
||||
QTextCursor cursor = textCursor();
|
||||
|
@ -122,3 +128,21 @@ void Editor::setPlainText(const QString &text)
|
|||
verticalScrollBar()->setSliderPosition(y);
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::highlightError(int error_pos)
|
||||
{
|
||||
highlighter->highlightError( error_pos );
|
||||
QTextCursor cursor = this->textCursor();
|
||||
cursor.setPosition( error_pos );
|
||||
this->setTextCursor( cursor );
|
||||
}
|
||||
|
||||
void Editor::unhighlightLastError()
|
||||
{
|
||||
highlighter->unhighlightLastError();
|
||||
}
|
||||
|
||||
Editor::~Editor()
|
||||
{
|
||||
delete highlighter;
|
||||
}
|
||||
|
|
12
src/editor.h
12
src/editor.h
|
@ -3,14 +3,15 @@
|
|||
#include <QWidget>
|
||||
#include <QWheelEvent>
|
||||
#include <QScrollBar>
|
||||
|
||||
#include <QTextEdit>
|
||||
#include "highlighter.h"
|
||||
|
||||
class Editor : public QTextEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Editor(QWidget *parent) : QTextEdit(parent) { setAcceptRichText(false); }
|
||||
void setPlainText(const QString &text);
|
||||
Editor(QWidget *parent);
|
||||
~Editor();
|
||||
public slots:
|
||||
void zoomIn();
|
||||
void zoomOut();
|
||||
|
@ -21,6 +22,11 @@ public slots:
|
|||
void unindentSelection();
|
||||
void commentSelection();
|
||||
void uncommentSelection();
|
||||
void setPlainText(const QString &text);
|
||||
void highlightError(int error_pos);
|
||||
void unhighlightLastError();
|
||||
|
||||
private:
|
||||
void wheelEvent ( QWheelEvent * event );
|
||||
Highlighter *highlighter;
|
||||
};
|
||||
|
|
71
src/func.cc
71
src/func.cc
|
@ -36,6 +36,10 @@
|
|||
#include "printutils.h"
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <boost/math/special_functions/fpclassify.hpp>
|
||||
using boost::math::isnan;
|
||||
using boost::math::isinf;
|
||||
|
||||
/*
|
||||
Random numbers
|
||||
|
||||
|
@ -598,6 +602,71 @@ Value builtin_parent_module(const Context *, const EvalContext *evalctx)
|
|||
return Value(Module::stack_element(s - 1 - n));
|
||||
}
|
||||
|
||||
Value builtin_norm(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
if (evalctx->numArgs() == 1 && evalctx->getArgValue(0).type() == Value::VECTOR) {
|
||||
double sum = 0;
|
||||
Value::VectorType v = evalctx->getArgValue(0).toVector();
|
||||
for (size_t i = 0; i < v.size(); i++)
|
||||
if (v[i].type() == Value::NUMBER)
|
||||
sum += pow(v[i].toDouble(),2);
|
||||
else {
|
||||
PRINT(" WARNING: Incorrect arguments to norm()");
|
||||
return Value();
|
||||
}
|
||||
return Value(sqrt(sum));
|
||||
}
|
||||
return Value();
|
||||
}
|
||||
|
||||
Value builtin_cross(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
if (evalctx->numArgs() != 2) {
|
||||
PRINT("WARNING: Invalid number of parameters for cross()");
|
||||
return Value();
|
||||
}
|
||||
|
||||
Value arg0 = evalctx->getArgValue(0);
|
||||
Value arg1 = evalctx->getArgValue(1);
|
||||
if ((arg0.type() != Value::VECTOR) || (arg1.type() != Value::VECTOR)) {
|
||||
PRINT("WARNING: Invalid type of parameters for cross()");
|
||||
return Value();
|
||||
}
|
||||
|
||||
Value::VectorType v0 = arg0.toVector();
|
||||
Value::VectorType v1 = arg1.toVector();
|
||||
if ((v0.size() != 3) || (v1.size() != 3)) {
|
||||
PRINT("WARNING: Invalid vector size of parameter for cross()");
|
||||
return Value();
|
||||
}
|
||||
for (unsigned int a = 0;a < 3;a++) {
|
||||
if ((v0[a].type() != Value::NUMBER) || (v1[a].type() != Value::NUMBER)) {
|
||||
PRINT("WARNING: Invalid value in parameter vector for cross()");
|
||||
return Value();
|
||||
}
|
||||
double d0 = v0[a].toDouble();
|
||||
double d1 = v1[a].toDouble();
|
||||
if (isnan(d0) || isnan(d1)) {
|
||||
PRINT("WARNING: Invalid value (NaN) in parameter vector for cross()");
|
||||
return Value();
|
||||
}
|
||||
if (isinf(d0) || isinf(d1)) {
|
||||
PRINT("WARNING: Invalid value (INF) in parameter vector for cross()");
|
||||
return Value();
|
||||
}
|
||||
}
|
||||
|
||||
double x = v0[1].toDouble() * v1[2].toDouble() - v0[2].toDouble() * v1[1].toDouble();
|
||||
double y = v0[2].toDouble() * v1[0].toDouble() - v0[0].toDouble() * v1[2].toDouble();
|
||||
double z = v0[0].toDouble() * v1[1].toDouble() - v0[1].toDouble() * v1[0].toDouble();
|
||||
|
||||
Value::VectorType result;
|
||||
result.push_back(Value(x));
|
||||
result.push_back(Value(y));
|
||||
result.push_back(Value(z));
|
||||
return Value(result);
|
||||
}
|
||||
|
||||
void register_builtin_functions()
|
||||
{
|
||||
Builtins::init("abs", new BuiltinFunction(&builtin_abs));
|
||||
|
@ -627,5 +696,7 @@ void register_builtin_functions()
|
|||
Builtins::init("search", new BuiltinFunction(&builtin_search));
|
||||
Builtins::init("version", new BuiltinFunction(&builtin_version));
|
||||
Builtins::init("version_num", new BuiltinFunction(&builtin_version_num));
|
||||
Builtins::init("norm", new BuiltinFunction(&builtin_norm));
|
||||
Builtins::init("cross", new BuiltinFunction(&builtin_cross));
|
||||
Builtins::init("parent_module", new BuiltinFunction(&builtin_parent_module));
|
||||
}
|
||||
|
|
|
@ -2,20 +2,24 @@
|
|||
#define HIGHLIGHTER_H_
|
||||
|
||||
#include <QSyntaxHighlighter>
|
||||
#include <QTextDocument>
|
||||
#include <QTextFormat>
|
||||
#include <QTextEdit>
|
||||
#include <QHash>
|
||||
|
||||
class Highlighter : public QSyntaxHighlighter
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum state_e {NORMAL=-1,QUOTE,COMMENT};
|
||||
QHash<QString, QTextCharFormat> tokenFormats;
|
||||
QTextCharFormat errorFormat;
|
||||
Highlighter(QTextDocument *parent);
|
||||
void highlightBlock(const QString &text);
|
||||
void assignFormatsToTokens(const QString &);
|
||||
void portable_rehighlightBlock( const QTextBlock &text );
|
||||
void highlightError(int error_pos);
|
||||
void unhighlightLastError();
|
||||
void assignFormatsToTokens(const QString &);
|
||||
private:
|
||||
QTextBlock lastErrorBlock;
|
||||
int errorPos;
|
||||
|
@ -23,7 +27,6 @@ private:
|
|||
QMap<QString,QStringList> tokentypes;
|
||||
QMap<QString,QTextCharFormat> typeformats;
|
||||
int lastDocumentPos();
|
||||
void portable_rehighlightBlock( const QTextBlock &text );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -210,7 +210,7 @@ Geometry *ImportNode::createGeometry() const
|
|||
bool binary = false;
|
||||
std::streampos file_size = f.tellg();
|
||||
f.seekg(80);
|
||||
if (!f.eof()) {
|
||||
if (f.good() && !f.eof()) {
|
||||
uint32_t facenum = 0;
|
||||
f.read((char *)&facenum, sizeof(uint32_t));
|
||||
#ifdef BOOST_BIG_ENDIAN
|
||||
|
@ -224,13 +224,12 @@ Geometry *ImportNode::createGeometry() const
|
|||
|
||||
char data[5];
|
||||
f.read(data, 5);
|
||||
if (!binary && !f.eof() && !memcmp(data, "solid", 5)) {
|
||||
if (!binary && !f.eof() && f.good() && !memcmp(data, "solid", 5)) {
|
||||
int i = 0;
|
||||
double vdata[3][3];
|
||||
std::string line;
|
||||
std::getline(f, line);
|
||||
while (!f.eof()) {
|
||||
|
||||
std::getline(f, line);
|
||||
boost::trim(line);
|
||||
if (boost::regex_search(line, ex_sfe)) {
|
||||
|
@ -261,7 +260,7 @@ Geometry *ImportNode::createGeometry() const
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (binary && !f.eof() && f.good())
|
||||
{
|
||||
f.ignore(80-5+4);
|
||||
while (1) {
|
||||
|
@ -288,7 +287,6 @@ Geometry *ImportNode::createGeometry() const
|
|||
else {
|
||||
file >> poly;
|
||||
file.close();
|
||||
|
||||
bool err = createPolySetFromPolyhedron(poly, *p);
|
||||
}
|
||||
#else
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
#include <QSettings>
|
||||
#include <QProgressDialog>
|
||||
#include <QMutexLocker>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
|
@ -101,6 +102,9 @@
|
|||
|
||||
#include "boosty.h"
|
||||
|
||||
// Keeps track of open window
|
||||
QSet<MainWindow*> *MainWindow::windows = NULL;
|
||||
|
||||
// Global application state
|
||||
unsigned int GuiLocker::gui_locked = 0;
|
||||
QString MainWindow::qexamplesdir;
|
||||
|
@ -154,9 +158,13 @@ settings_valueList(const QString &key, const QList<int> &defaultList = QList<int
|
|||
}
|
||||
|
||||
MainWindow::MainWindow(const QString &filename)
|
||||
: root_inst("group"), progresswidget(NULL)
|
||||
: root_inst("group"), tempFile(NULL), progresswidget(NULL)
|
||||
{
|
||||
setupUi(this);
|
||||
this->setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
if (!MainWindow::windows) MainWindow::windows = new QSet<MainWindow*>;
|
||||
MainWindow::windows->insert(this);
|
||||
|
||||
#ifdef ENABLE_CGAL
|
||||
this->cgalworker = new CGALWorker();
|
||||
|
@ -186,7 +194,8 @@ MainWindow::MainWindow(const QString &filename)
|
|||
fps = 0;
|
||||
fsteps = 1;
|
||||
|
||||
highlighter = new Highlighter(editor->document());
|
||||
connect(this, SIGNAL(highlightError(int)), editor, SLOT(highlightError(int)));
|
||||
connect(this, SIGNAL(unhighlightLastError()), editor, SLOT(unhighlightLastError()));
|
||||
editor->setTabStopWidth(30);
|
||||
editor->setLineWrapping(true); // Not designable
|
||||
|
||||
|
@ -471,6 +480,7 @@ MainWindow::~MainWindow()
|
|||
#ifdef ENABLE_OPENCSG
|
||||
delete this->opencsgRenderer;
|
||||
#endif
|
||||
MainWindow::windows->remove(this);
|
||||
}
|
||||
|
||||
void MainWindow::showProgress()
|
||||
|
@ -524,6 +534,7 @@ MainWindow::openFile(const QString &new_filename)
|
|||
#endif
|
||||
setFileName(actual_filename);
|
||||
editor->setPlainText("");
|
||||
this->last_compiled_doc = "";
|
||||
|
||||
fileChangedOnDisk(); // force cached autoReloadId to update
|
||||
refreshDocument();
|
||||
|
@ -665,6 +676,7 @@ void MainWindow::compile(bool reload, bool forcedone)
|
|||
|
||||
if (shouldcompiletoplevel) {
|
||||
console->clear();
|
||||
if (editor->isContentModified()) saveBackup();
|
||||
compileTopLevelDocument();
|
||||
didcompile = true;
|
||||
}
|
||||
|
@ -685,6 +697,16 @@ void MainWindow::compile(bool reload, bool forcedone)
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!reload && didcompile) {
|
||||
if (!animate_panel->isVisible()) {
|
||||
emit unhighlightLastError();
|
||||
if (!this->root_module) {
|
||||
emit highlightError( parser_error_pos );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
compileDone(didcompile | forcedone);
|
||||
}
|
||||
|
||||
|
@ -1013,6 +1035,45 @@ void MainWindow::actionOpenExample()
|
|||
}
|
||||
}
|
||||
|
||||
void MainWindow::writeBackup(QFile *file)
|
||||
{
|
||||
// see MainWindow::saveBackup()
|
||||
file->resize(0);
|
||||
QTextStream writer(file);
|
||||
writer.setCodec("UTF-8");
|
||||
writer << this->editor->toPlainText();
|
||||
|
||||
PRINTB("Saved backup file: %s", file->fileName().toLocal8Bit().constData());
|
||||
}
|
||||
|
||||
void MainWindow::saveBackup()
|
||||
{
|
||||
std::string path = PlatformUtils::backupPath();
|
||||
if ((!fs::exists(path)) && (!PlatformUtils::createBackupPath())) {
|
||||
PRINTB("WARNING: Cannot create backup path: %s", path);
|
||||
return;
|
||||
}
|
||||
|
||||
QString backupPath = QString::fromStdString(path);
|
||||
if (!backupPath.endsWith("/")) backupPath.append("/");
|
||||
|
||||
QString basename = "unsaved";
|
||||
if (!this->fileName.isEmpty()) {
|
||||
QFileInfo fileInfo = QFileInfo(this->fileName);
|
||||
basename = fileInfo.baseName();
|
||||
}
|
||||
|
||||
if (!this->tempFile) {
|
||||
this->tempFile = new QTemporaryFile(backupPath.append(basename + "-backup-XXXXXXXX.scad"));
|
||||
}
|
||||
|
||||
if ((!this->tempFile->isOpen()) && (! this->tempFile->open())) {
|
||||
PRINT("WARNING: Failed to create backup file");
|
||||
return;
|
||||
}
|
||||
return writeBackup(this->tempFile);
|
||||
}
|
||||
|
||||
void MainWindow::actionSave()
|
||||
{
|
||||
if (this->fileName.isEmpty()) {
|
||||
|
@ -1089,10 +1150,10 @@ void MainWindow::hideEditor()
|
|||
{
|
||||
QSettings settings;
|
||||
if (editActionHide->isChecked()) {
|
||||
editor->hide();
|
||||
editorPane->hide();
|
||||
settings.setValue("view/hideEditor",true);
|
||||
} else {
|
||||
editor->show();
|
||||
editorPane->show();
|
||||
settings.setValue("view/hideEditor",false);
|
||||
}
|
||||
}
|
||||
|
@ -1227,6 +1288,10 @@ void MainWindow::updateTemporalVariables()
|
|||
top_ctx.set_variable("$vpr", Value(vpr));
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if the current document is a file on disk and that file has new content.
|
||||
Returns false if a file on disk has disappeared or if we haven't yet saved.
|
||||
*/
|
||||
bool MainWindow::fileChangedOnDisk()
|
||||
{
|
||||
if (!this->fileName.isEmpty()) {
|
||||
|
@ -1267,15 +1332,6 @@ void MainWindow::compileTopLevelDocument()
|
|||
QFileInfo(this->fileName).absolutePath().toLocal8Bit(),
|
||||
false);
|
||||
|
||||
if (!animate_panel->isVisible()) {
|
||||
highlighter->unhighlightLastError();
|
||||
if (!this->root_module) {
|
||||
QTextCursor cursor = editor->textCursor();
|
||||
cursor.setPosition(parser_error_pos);
|
||||
editor->setTextCursor(cursor);
|
||||
highlighter->highlightError( parser_error_pos );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::checkAutoReload()
|
||||
|
@ -1405,6 +1461,7 @@ void MainWindow::actionRender()
|
|||
void MainWindow::cgalRender()
|
||||
{
|
||||
if (!this->root_module || !this->root_node) {
|
||||
compileEnded();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2014,6 +2071,10 @@ void MainWindow::closeEvent(QCloseEvent *event)
|
|||
settings.setValue("window/position", pos());
|
||||
settings_setValueList("window/splitter1sizes",splitter1->sizes());
|
||||
settings_setValueList("window/splitter2sizes",splitter2->sizes());
|
||||
if (this->tempFile) {
|
||||
delete this->tempFile;
|
||||
this->tempFile = NULL;
|
||||
}
|
||||
event->accept();
|
||||
} else {
|
||||
event->ignore();
|
||||
|
|
|
@ -263,45 +263,58 @@ bool FileModule::handleDependencies()
|
|||
if (this->is_handling_dependencies) return false;
|
||||
this->is_handling_dependencies = true;
|
||||
|
||||
bool changed = false;
|
||||
bool somethingchanged = false;
|
||||
std::vector<std::pair<std::string,std::string> > updates;
|
||||
|
||||
// If a lib in usedlibs was previously missing, we need to relocate it
|
||||
// by searching the applicable paths. We can identify a previously missing module
|
||||
// as it will have a relative path.
|
||||
|
||||
// Iterating manually since we want to modify the container while iterating
|
||||
FileModule::ModuleContainer::iterator iter = this->usedlibs.begin();
|
||||
while (iter != this->usedlibs.end()) {
|
||||
FileModule::ModuleContainer::iterator curr = iter++;
|
||||
BOOST_FOREACH(std::string filename, this->usedlibs) {
|
||||
|
||||
bool wasmissing = false;
|
||||
bool found = true;
|
||||
|
||||
// Get an absolute filename for the module
|
||||
std::string filename = *curr;
|
||||
if (!boosty::is_absolute(filename)) {
|
||||
wasmissing = true;
|
||||
fs::path fullpath = find_valid_path(this->path, filename);
|
||||
if (!fullpath.empty()) filename = boosty::stringy(fullpath);
|
||||
if (!fullpath.empty()) {
|
||||
updates.push_back(std::make_pair(filename, boosty::stringy(fullpath)));
|
||||
filename = boosty::stringy(fullpath);
|
||||
}
|
||||
else {
|
||||
found = false;
|
||||
}
|
||||
}
|
||||
|
||||
FileModule *oldmodule = ModuleCache::instance()->lookup(filename);
|
||||
FileModule *newmodule = ModuleCache::instance()->evaluate(filename);
|
||||
// Detect appearance but not removal of files
|
||||
if (newmodule && oldmodule != newmodule) {
|
||||
changed = true;
|
||||
if (found) {
|
||||
bool wascached = ModuleCache::instance()->isCached(filename);
|
||||
FileModule *oldmodule = ModuleCache::instance()->lookup(filename);
|
||||
FileModule *newmodule;
|
||||
bool changed = ModuleCache::instance()->evaluate(filename, newmodule);
|
||||
// Detect appearance but not removal of files, and keep old module
|
||||
// on compile errors (FIXME: Is this correct behavior?)
|
||||
if (changed) {
|
||||
#ifdef DEBUG
|
||||
PRINTB_NOCACHE(" %s: %p -> %p", filename % oldmodule % newmodule);
|
||||
PRINTB_NOCACHE(" %s: %p -> %p", filename % oldmodule % newmodule);
|
||||
#endif
|
||||
}
|
||||
if (!newmodule) {
|
||||
}
|
||||
somethingchanged |= changed;
|
||||
// Only print warning if we're not part of an automatic reload
|
||||
if (!oldmodule && !wasmissing) {
|
||||
if (!newmodule && !wascached && !wasmissing) {
|
||||
PRINTB_NOCACHE("WARNING: Failed to compile library '%s'.", filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Relative filenames which were located is reinserted as absolute filenames
|
||||
typedef std::pair<std::string,std::string> stringpair;
|
||||
BOOST_FOREACH(const stringpair &files, updates) {
|
||||
this->usedlibs.erase(files.first);
|
||||
this->usedlibs.insert(files.second);
|
||||
}
|
||||
this->is_handling_dependencies = false;
|
||||
return changed;
|
||||
return somethingchanged;
|
||||
}
|
||||
|
||||
AbstractNode *FileModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
|
||||
|
|
|
@ -546,12 +546,17 @@ int gui(vector<string> &inputFiles, const fs::path &original_path, int argc, cha
|
|||
BOOST_FOREACH(const string &infile, inputFiles) {
|
||||
new MainWindow(assemblePath(original_path, infile));
|
||||
}
|
||||
app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
|
||||
#else
|
||||
MainWindow *m = new MainWindow(assemblePath(original_path, inputFiles[0]));
|
||||
app.connect(m, SIGNAL(destroyed()), &app, SLOT(quit()));
|
||||
#endif
|
||||
return app.exec();
|
||||
app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
|
||||
int rc = app.exec();
|
||||
if (MainWindow::windows) {
|
||||
foreach (MainWindow *mainw, *MainWindow::windows) {
|
||||
delete mainw;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#else // OPENSCAD_QTGUI
|
||||
bool QtUseGUI() { return false; }
|
||||
|
|
|
@ -90,17 +90,15 @@ fs::path find_valid_path(const fs::path &sourcepath,
|
|||
|
||||
void parser_init(const std::string &applicationpath)
|
||||
{
|
||||
// Add paths from OPENSCADPATH before adding built-in paths
|
||||
// Add paths from OPENSCADPATH before adding built-in paths
|
||||
const char *openscadpaths = getenv("OPENSCADPATH");
|
||||
if (openscadpaths) {
|
||||
std::string paths(openscadpaths);
|
||||
typedef boost::split_iterator<std::string::iterator> string_split_iterator;
|
||||
for (string_split_iterator it =
|
||||
make_split_iterator(paths, first_finder(":", boost::is_iequal()));
|
||||
it != string_split_iterator();
|
||||
++it) {
|
||||
add_librarydir(boosty::absolute(fs::path(boost::copy_range<std::string>(*it))).string());
|
||||
}
|
||||
std::string sep = PlatformUtils::pathSeparatorChar();
|
||||
typedef boost::split_iterator<std::string::iterator> string_split_iterator;
|
||||
for (string_split_iterator it = boost::make_split_iterator(paths, boost::first_finder(sep, boost::is_iequal())); it != string_split_iterator(); ++it) {
|
||||
add_librarydir(boosty::absolute(fs::path(boost::copy_range<std::string>(*it))).string());
|
||||
}
|
||||
}
|
||||
|
||||
// This is the built-in user-writable library path
|
||||
|
|
|
@ -28,7 +28,16 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#define MAXCMDLEN 64000
|
||||
|
||||
// want to use system definitions instead like #include <system.h>
|
||||
#ifndef WIFEXITED
|
||||
#define WIFEXITED(S) (((S) & 0xff) == 0)
|
||||
#endif
|
||||
#ifndef WEXITSTATUS
|
||||
#define WEXITSTATUS(S) (((S) >> 8) & 0xff)
|
||||
#endif
|
||||
|
||||
#define MAXCMDLEN /*64000*/ 32768 /* MS Windows limit */
|
||||
#define BUFFSIZE 42
|
||||
|
||||
int main( int argc, char * argv[] )
|
||||
|
@ -36,57 +45,67 @@ int main( int argc, char * argv[] )
|
|||
FILE *cmd_stdout;
|
||||
char cmd[MAXCMDLEN];
|
||||
char buffer[BUFFSIZE];
|
||||
char *fgets_result;
|
||||
int eof = 0;
|
||||
int pclose_result;
|
||||
int i;
|
||||
const char * argchar;
|
||||
int result = 0;
|
||||
int quotify_arg = 0;
|
||||
unsigned n; // total number of characters in cmd
|
||||
static const char exe_str[] = "openscad.exe";
|
||||
static const char redirect_str[] = " 2>&1"; // capture stderr and stdout
|
||||
|
||||
strcat( cmd, "\0" );
|
||||
strcat( cmd, "openscad.exe" );
|
||||
memcpy(cmd, exe_str, (n = sizeof(exe_str)-1)); // without \0
|
||||
for ( i = 1 ; i < argc ; ++i ) {
|
||||
quotify_arg = 0;
|
||||
for ( argchar = argv[i]; *argchar!=0; argchar++ ) {
|
||||
if ((char)(*argchar)==' ') quotify_arg = 1;
|
||||
register char *s;
|
||||
/*bool*/ int quote;
|
||||
|
||||
cmd[n++] = ' ';
|
||||
// MS Windows special characters need quotation
|
||||
// See issues #440, #441 & #479
|
||||
quote = NULL != strpbrk((s = argv[i]), " \"&'<>^|\t");
|
||||
if (quote) cmd[n++] = '"';
|
||||
while (*s) { // copy & check
|
||||
// The following test is compomise between brevity, clarity and performance.
|
||||
// It could be boiled down to: if ('"' == s[strspn(s,"\\")])
|
||||
// or expanded to avoid repetitive passes of strspn() over same data.
|
||||
if ('"' == *s || ('\\' == *s && '"' == s[strspn(s,"\\")])) cmd[n++] = '\\';
|
||||
cmd[n++] = *s++;
|
||||
if (n >= MAXCMDLEN-sizeof(redirect_str)) {
|
||||
fprintf(stderr, "Command line length exceeds limit of %d\n", MAXCMDLEN);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
strcat( cmd, " " );
|
||||
if (quotify_arg) strcat( cmd, "\"");
|
||||
strcat( cmd, argv[i] );
|
||||
if (quotify_arg) strcat( cmd, "\"");
|
||||
if (quote) cmd[n++] = '"';
|
||||
}
|
||||
strcat( cmd, " 2>&1"); // capture stderr and stdout
|
||||
printf("openscad.com: running command: %s\n", cmd );
|
||||
memcpy(&cmd[n], redirect_str, sizeof(redirect_str)); // including \0
|
||||
|
||||
cmd_stdout = _popen( cmd, "rt" );
|
||||
if ( cmd_stdout == NULL ) {
|
||||
printf( "Error opening _popen for command: %s", cmd );
|
||||
perror( "Error message:" );
|
||||
fprintf(stderr, "Error opening _popen for command: %s", cmd );
|
||||
perror( "Error message" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
while ( !eof )
|
||||
{
|
||||
fgets_result = fgets( buffer, BUFFSIZE, cmd_stdout );
|
||||
if ( fgets_result == NULL ) {
|
||||
for(;;) {
|
||||
if (NULL == fgets(buffer, BUFFSIZE, cmd_stdout)) {
|
||||
if ( ferror( cmd_stdout ) ) {
|
||||
printf("Error reading from stdout of %s\n", cmd);
|
||||
fprintf(stderr, "Error reading from stdout of %s\n", cmd);
|
||||
result = 1;
|
||||
}
|
||||
if ( feof( cmd_stdout ) ) {
|
||||
eof = 1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
fprintf( stdout, "%s", buffer );
|
||||
fputs(buffer, stdout);
|
||||
}
|
||||
}
|
||||
|
||||
pclose_result = _pclose( cmd_stdout );
|
||||
if ( pclose_result < 0 ) {
|
||||
perror("Error while closing stdout for command:");
|
||||
// perror() applicable with return value of -1 only!
|
||||
// Avoid stupid "Error: No Error" message
|
||||
if (pclose_result == -1) {
|
||||
perror("Error while closing stdout for command");
|
||||
result = 1;
|
||||
} else if (!result) {
|
||||
result = WIFEXITED(pclose_result) ? WEXITSTATUS(pclose_result) : 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -124,3 +124,22 @@ o rm cascade*.scad
|
|||
o Verify that no rerendering was triggered (the 4 objects are still there)
|
||||
o ./cascade2.sh
|
||||
o Verify that everything reloads at once without flickering
|
||||
|
||||
Test 15: Correct handling of compile errors in auto-reloaded modules
|
||||
--------
|
||||
o Turn on Automatic Reload and Compile
|
||||
o Open mainusingerror.scad
|
||||
o Verify that you get:
|
||||
- Compiling library '.../error.scad'.
|
||||
- Parser error in line 3: syntax error
|
||||
- WARNING: Failed to compile library '.../error.scad'.
|
||||
- Main file should keep compiling
|
||||
o Verify that the above doesn't repeat
|
||||
|
||||
Test 16: Dependency tracking of underlying dependencies
|
||||
--------
|
||||
o Turn on Automatic Reload and Compile
|
||||
o Open mainsubsub.scad
|
||||
o Verify that you see a red cylinder
|
||||
o edit subdit/subsub.scad: Change color
|
||||
o Verify that color changes
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
use <subdir/sub.scad>
|
||||
sub();
|
|
@ -0,0 +1,3 @@
|
|||
//mainusingerror.scad
|
||||
echo(version());
|
||||
use <error.scad>
|
|
@ -1,7 +1,7 @@
|
|||
use <mymodule-lib.scad>
|
||||
|
||||
module mymodule() {
|
||||
sphere();
|
||||
sphere(5);
|
||||
}
|
||||
|
||||
mymodule();
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
module mymodule() {
|
||||
cylinder(center=true);
|
||||
cylinder(r=5, center=true);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
use <subsub.scad>
|
||||
|
||||
module sub() {
|
||||
subsub();
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
module subsub() {
|
||||
color("red") cylinder(r = 10, h = 5);
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
// openscad should exit normally.
|
||||
// it should not crash and/or freeze and/or gobble RAM
|
||||
import("../../stl/empty.stl");
|
||||
import("../../stl/empty2.stl");
|
||||
echo("empty stl test ok");
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
module donut() {
|
||||
rotate_extrude(convexity=2)
|
||||
translate([5,0,0])
|
||||
difference() {
|
||||
circle(r=2);
|
||||
circle(r=1);
|
||||
}
|
||||
}
|
||||
|
||||
difference()
|
||||
{
|
||||
donut();
|
||||
translate([-10,-10,0]) cube(10);
|
||||
}
|
|
@ -1,4 +1,8 @@
|
|||
// The inner cube won't render correctly in OpenCSG mode as long as this bug is present
|
||||
// Note: This causes a different bug in unstable:
|
||||
// If we render a preview first, the render() node will be cached as a PolySet. This will
|
||||
// cause the same problems as in issue495.scad. If we clear cache and render using CGAL,
|
||||
// it doesn't trigger the bug since we stay in CGAL all the time
|
||||
difference() {
|
||||
render(convexity=2) difference() {
|
||||
cube(20, center = true);
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
// Hollow cube.
|
||||
// STL export is wrong (inner cube is positive instead of negative)
|
||||
// This is fixed by applying and using the patch to CGAL containing
|
||||
// convert_all_inner_shells_to_polyhedron()
|
||||
difference() {
|
||||
cube(20, center = true);
|
||||
cube(10, center = true);
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
// In CGAL mode, there should be a cavity
|
||||
// The problem appears to be that we don't create a correct Nef Polyhedron from
|
||||
// the polyset, probably already being wrong when converting to a Polyhedron
|
||||
difference() {
|
||||
polyhedron(convexity=2, faces=[[2,1,0],[3,1,2],[4,0,1],[4,1,5],[4,2,0],[6,2,4],[6,3,2],[7,3,6],[5,1,3],[5,3,7],[6,4,5],[6,5,7],[9,10,8],[9,11,10],[8,12,9],[9,12,13],[10,12,8],[10,14,12],[11,14,10],[11,15,14],[9,13,11],[11,13,15],[12,14,13],[13,14,15]],
|
||||
points=[[-5,-5,-5],[-5,-5,5],[-5,5,-5],[-5,5,5],[5,-5,-5],[5,-5,5],[5,5,-5],[5,5,5],[-2.5,-2.5,-2.5],[-2.5,-2.5,2.5],[-2.5,2.5,-2.5],[-2.5,2.5,2.5],[2.5,-2.5,-2.5],[2.5,-2.5,2.5],[2.5,2.5,-2.5],[2.5,2.5,2.5]]);
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// >2 objects which don't all intersect should be empty
|
||||
intersection() {
|
||||
translate([0,0,0]) cube(5, center=true);
|
||||
translate([4,0,0]) cube(5, center=true);
|
||||
translate([8,00,]) cube(5, center=true);
|
||||
translate([12,0,0]) cube(5, center=true);
|
||||
}
|
||||
|
||||
// Subtracting something from empty intersection should be empty
|
||||
translate([0,-12,0]) difference() {
|
||||
intersection() {
|
||||
cube();
|
||||
translate([2,0,0]) cube();
|
||||
}
|
||||
cylinder(r=4, h=10, center=true);
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
echo(cross([2, 3, 4], [5, 6, 7]));
|
||||
echo(cross([2, 1, -3], [0, 4, 5]));
|
||||
echo(cross([2, 1, -3], cross([2, 3, 4], [5, 6, 7])));
|
||||
|
||||
echo(cross([2, 0/0, -3], [0, 4, 5]));
|
||||
echo(cross([2, 1/0, -3], [0, 4, 5]));
|
||||
echo(cross([2, -1/0, -3], [0, 4, 5]));
|
||||
|
||||
echo(cross(0));
|
||||
echo(cross(0, 1));
|
||||
echo(cross(0, "a"));
|
||||
echo(cross(0, 1, 3));
|
||||
echo(cross([0], [1]));
|
||||
echo(cross([1, 2, 3], [1, 2]));
|
||||
echo(cross([1, 2, 3], [1, 2, "a"]));
|
||||
echo(cross([1, 2, 3], [1, 2, [0]]));
|
||||
echo(cross([1, 2, 3], [1, 2, [1:2]]));
|
|
@ -0,0 +1,27 @@
|
|||
u=undef;
|
||||
|
||||
echo(norm([]));
|
||||
echo(norm([1]));
|
||||
echo(norm([1,2]));
|
||||
echo(norm([1,2,3]));
|
||||
echo(norm([1,2,3,4]));
|
||||
echo(norm());
|
||||
|
||||
echo(norm([1,2,0/0]));
|
||||
echo(norm([1,2,1/0]));
|
||||
echo(norm([1,2,-1/0]));
|
||||
|
||||
echo(norm(""));
|
||||
echo(norm("abcd"));
|
||||
echo(norm(true));
|
||||
echo(norm([1:4]));
|
||||
|
||||
echo(norm([1, 2, "a"]));
|
||||
echo(norm([1, 2, []]));
|
||||
echo(norm([1, 2, [1]]));
|
||||
echo(norm([1, 2, [1:3]]));
|
||||
echo(norm([[1,2,3,4],[1,2,3],[1,2],[1]]));
|
||||
|
||||
echo(norm(u));
|
||||
echo(norm(u, u));
|
||||
echo(norm(a, a));
|
|
@ -0,0 +1,4 @@
|
|||
// Used to test variable override with the -D parameter
|
||||
a = 1;
|
||||
b = 2;
|
||||
echo(a,b);
|
|
@ -14,14 +14,14 @@ special_module(23, $fn=5);
|
|||
echo("$children scope");
|
||||
module child_module_2() {
|
||||
echo("$children should be 4: ", $children);
|
||||
for(i=[0:$children-1]) child(i);
|
||||
for(i=[0:$children-1]) children(i);
|
||||
}
|
||||
|
||||
module child_module_1() {
|
||||
echo("$children should be 1: ", $children);
|
||||
child_module_2() {
|
||||
echo("$children should be 1: ", $children);
|
||||
child(0);
|
||||
children(0);
|
||||
echo("child_module_2 child 0");
|
||||
echo("child_module_2 child 1");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
solid OpenSCAD_Model
|
||||
endsolid OpenSCAD_Model
|
||||
|
|
@ -559,6 +559,8 @@ set(CORE_SOURCES
|
|||
../src/fileutils.cc
|
||||
../src/progress.cc
|
||||
../src/boost-utils.cc
|
||||
../src/PlatformUtils.cc
|
||||
../src/${PLATFORMUTILS_SOURCE}
|
||||
${FLEX_OpenSCADlexer_OUTPUTS}
|
||||
${BISON_OpenSCADparser_OUTPUTS})
|
||||
|
||||
|
@ -605,8 +607,6 @@ set(OFFSCREEN_SOURCES
|
|||
../src/ThrownTogetherRenderer.cc
|
||||
../src/renderer.cc
|
||||
../src/render.cc
|
||||
../src/PlatformUtils.cc
|
||||
../src/${PLATFORMUTILS_SOURCE}
|
||||
../src/OpenCSGRenderer.cc)
|
||||
|
||||
if(NULLGL)
|
||||
|
@ -626,7 +626,7 @@ endif()
|
|||
|
||||
add_library(tests-core STATIC ${CORE_SOURCES})
|
||||
target_link_libraries(tests-core ${OPENGL_LIBRARIES} ${GLIB2_LIBRARIES} )
|
||||
set(TESTS-CORE-LIBRARIES ${OPENGL_LIBRARIES} ${GLIB2_LIBRARIES} ${Boost_LIBRARIES} )
|
||||
set(TESTS-CORE-LIBRARIES ${OPENGL_LIBRARIES} ${GLIB2_LIBRARIES} ${Boost_LIBRARIES} ${COCOA_LIBRARY})
|
||||
|
||||
add_library(tests-common STATIC ${COMMON_SOURCES})
|
||||
target_link_libraries(tests-common tests-core)
|
||||
|
@ -672,7 +672,7 @@ target_link_libraries(csgtexttest tests-nocgal ${TESTS-NOCGAL-LIBRARIES})
|
|||
#
|
||||
add_executable(cgalcachetest cgalcachetest.cc)
|
||||
set_target_properties(cgalcachetest PROPERTIES COMPILE_FLAGS "-DENABLE_CGAL ${CGAL_CXX_FLAGS_INIT}")
|
||||
target_link_libraries(cgalcachetest tests-cgal ${TESTS-CGAL-LIBRARIES} ${CLIPPER_LIBRARY} ${GLEW_LIBRARY} ${COCOA_LIBRARY})
|
||||
target_link_libraries(cgalcachetest tests-cgal ${TESTS-CGAL-LIBRARIES} ${GLEW_LIBRARY})
|
||||
|
||||
#
|
||||
# openscad no-qt
|
||||
|
@ -847,7 +847,8 @@ list(APPEND ECHO_FILES ${FUNCTION_FILES}
|
|||
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/expression-shortcircuit-tests.scad
|
||||
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/parent_module-tests.scad
|
||||
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/children-tests.scad
|
||||
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/range-tests.scad)
|
||||
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/range-tests.scad
|
||||
${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/empty-stl.scad)
|
||||
|
||||
list(APPEND DUMPTEST_FILES ${FEATURES_FILES} ${EXAMPLE_FILES})
|
||||
list(APPEND DUMPTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/escape-test.scad
|
||||
|
@ -911,7 +912,9 @@ list(APPEND BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue495.scad
|
|||
${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue585.scad
|
||||
${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue591.scad
|
||||
${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue593.scad
|
||||
${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue612.scad)
|
||||
${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue612.scad
|
||||
${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue112.scad
|
||||
${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue666.scad)
|
||||
|
||||
list(APPEND OPENCSGTEST_FILES ${BUGS_FILES})
|
||||
list(APPEND CGALPNGTEST_FILES ${BUGS_FILES})
|
||||
|
@ -1023,7 +1026,18 @@ add_cmdline_test(openscad-nonascii EXE ${OPENSCAD_BINPATH} ARGS -o
|
|||
FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/sfære.scad)
|
||||
|
||||
|
||||
# Image output
|
||||
# Variable override (-D arg)
|
||||
|
||||
# FIXME - this breaks on older cmake that is very common 'in the wild' on linux
|
||||
# Override simple variable
|
||||
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_GREATER 2.8.10)
|
||||
add_cmdline_test(openscad-override EXE ${OPENSCAD_BINPATH}
|
||||
ARGS -D a=3$<SEMICOLON> -o
|
||||
SUFFIX echo
|
||||
FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/override.scad)
|
||||
endif()
|
||||
|
||||
# Image output parameters
|
||||
add_cmdline_test(openscad-imgsize EXE ${OPENSCAD_BINPATH}
|
||||
ARGS --imgsize 100,100 -o
|
||||
SUFFIX png
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.3 KiB |
|
@ -0,0 +1,27 @@
|
|||
ECHO: [-3, 6, -3]
|
||||
ECHO: [17, -10, 8]
|
||||
ECHO: [15, 15, 15]
|
||||
WARNING: Invalid value (NaN) in parameter vector for cross()
|
||||
ECHO: undef
|
||||
WARNING: Invalid value (INF) in parameter vector for cross()
|
||||
ECHO: undef
|
||||
WARNING: Invalid value (INF) in parameter vector for cross()
|
||||
ECHO: undef
|
||||
WARNING: Invalid number of parameters for cross()
|
||||
ECHO: undef
|
||||
WARNING: Invalid type of parameters for cross()
|
||||
ECHO: undef
|
||||
WARNING: Invalid type of parameters for cross()
|
||||
ECHO: undef
|
||||
WARNING: Invalid number of parameters for cross()
|
||||
ECHO: undef
|
||||
WARNING: Invalid vector size of parameter for cross()
|
||||
ECHO: undef
|
||||
WARNING: Invalid vector size of parameter for cross()
|
||||
ECHO: undef
|
||||
WARNING: Invalid value in parameter vector for cross()
|
||||
ECHO: undef
|
||||
WARNING: Invalid value in parameter vector for cross()
|
||||
ECHO: undef
|
||||
WARNING: Invalid value in parameter vector for cross()
|
||||
ECHO: undef
|
|
@ -0,0 +1 @@
|
|||
ECHO: "empty stl test ok"
|
|
@ -0,0 +1,26 @@
|
|||
ECHO: 0
|
||||
ECHO: 1
|
||||
ECHO: 2.2360679775
|
||||
ECHO: 3.74165738677
|
||||
ECHO: 5.47722557505
|
||||
ECHO: undef
|
||||
ECHO: nan
|
||||
ECHO: inf
|
||||
ECHO: inf
|
||||
ECHO: undef
|
||||
ECHO: undef
|
||||
ECHO: undef
|
||||
ECHO: undef
|
||||
WARNING: Incorrect arguments to norm()
|
||||
ECHO: undef
|
||||
WARNING: Incorrect arguments to norm()
|
||||
ECHO: undef
|
||||
WARNING: Incorrect arguments to norm()
|
||||
ECHO: undef
|
||||
WARNING: Incorrect arguments to norm()
|
||||
ECHO: undef
|
||||
WARNING: Incorrect arguments to norm()
|
||||
ECHO: undef
|
||||
ECHO: undef
|
||||
ECHO: undef
|
||||
ECHO: undef
|
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.3 KiB |
|
@ -0,0 +1 @@
|
|||
ECHO: 3, 2
|
Loading…
Reference in New Issue