diff options
29 files changed, 173 insertions, 27 deletions
@@ -38,6 +38,36 @@ <key>LSIsAppleDefaultForType</key> <true/> </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>stl</string> + </array> + <key>CFBundleTypeName</key> + <string>STL 3D file</string> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>off</string> + </array> + <key>CFBundleTypeName</key> + <string>OFF 3D file</string> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>dxf</string> + </array> + <key>CFBundleTypeName</key> + <string>DXF file</string> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + </dict> </array> <key>NSAppleScriptEnabled</key> <true/> diff --git a/openscad.pro b/openscad.pro index 81f5e6f..96a0a2a 100644 --- a/openscad.pro +++ b/openscad.pro @@ -227,6 +227,7 @@ HEADERS += src/typedefs.h \ src/handle_dep.h \ src/polyset.h \ src/printutils.h \ + src/fileutils.h \ src/value.h \ src/progress.h \ src/editor.h \ @@ -291,6 +292,7 @@ SOURCES += src/version_check.cc \ src/linearextrude.cc \ src/rotateextrude.cc \ src/printutils.cc \ + src/fileutils.cc \ src/progress.cc \ src/parsersettings.cc \ src/stl-utils.cc \ diff --git a/src/dxfdim.cc b/src/dxfdim.cc index 555ed49..66842d2 100644 --- a/src/dxfdim.cc +++ b/src/dxfdim.cc @@ -30,6 +30,7 @@ #include "dxfdata.h" #include "builtin.h" #include "printutils.h" +#include "fileutils.h" #include "evalcontext.h" #include "mathc99.h" @@ -54,7 +55,8 @@ Value builtin_dxf_dim(const Context *ctx, const EvalContext *evalctx) // See issue #217 for (size_t i = 0; i < evalctx->numArgs(); i++) { if (evalctx->getArgName(i) == "file") - filename = evalctx->getAbsolutePath(evalctx->getArgValue(i).toString()); + filename = lookup_file(evalctx->getArgValue(i).toString(), + evalctx->documentPath(), ctx->documentPath()); if (evalctx->getArgName(i) == "layer") layername = evalctx->getArgValue(i).toString(); if (evalctx->getArgName(i) == "origin") diff --git a/src/fileutils.cc b/src/fileutils.cc new file mode 100644 index 0000000..b844b4a --- /dev/null +++ b/src/fileutils.cc @@ -0,0 +1,35 @@ +#include "fileutils.h" +#include "printutils.h" + +#include <boost/filesystem.hpp> +namespace fs = boost::filesystem; +#include "boosty.h" + +/*! + Returns the absolute path to the given filename, unless it's empty. + If the file isn't found in the given path, the fallback path will be + used to be backwards compatible with <= 2013.01 (see issue #217). +*/ +std::string lookup_file(const std::string &filename, + const std::string &path, const std::string &fallbackpath) +{ + std::string resultfile; + if (!filename.empty() && !boosty::is_absolute(fs::path(filename))) { + fs::path absfile; + if (!path.empty()) absfile = boosty::absolute(fs::path(path) / filename); + fs::path absfile_fallback; + if (!fallbackpath.empty()) absfile_fallback = boosty::absolute(fs::path(fallbackpath) / filename); + + if (!fs::exists(absfile) && fs::exists(absfile_fallback)) { + resultfile = absfile_fallback.string(); + PRINTB("WARNING: Imported file (%s) found in document root instead of relative to the importing module. This behavior is deprecated", filename); + } + else { + resultfile = absfile.string(); + } + } + else { + resultfile = filename; + } + return resultfile; +} diff --git a/src/fileutils.h b/src/fileutils.h new file mode 100644 index 0000000..1f68cdb --- /dev/null +++ b/src/fileutils.h @@ -0,0 +1,9 @@ +#ifndef FILEUTILS_H_ +#define FILEUTILS_H_ + +#include <string> + +std::string lookup_file(const std::string &filename, + const std::string &path, const std::string &fallbackpath); + +#endif diff --git a/src/import.cc b/src/import.cc index bd8f830..bb44d70 100644 --- a/src/import.cc +++ b/src/import.cc @@ -33,6 +33,7 @@ #include "dxfdata.h" #include "dxftess.h" #include "printutils.h" +#include "fileutils.h" #include "handle_dep.h" // handle_dep() #ifdef ENABLE_CGAL @@ -97,7 +98,7 @@ AbstractNode *ImportModule::instantiate(const Context *ctx, const ModuleInstanti PRINT("DEPRECATED: filename= is deprecated. Please use file="); } } - std::string filename = inst->getAbsolutePath(v.isUndefined() ? "" : v.toString()); + std::string filename = lookup_file(v.isUndefined() ? "" : v.toString(), inst->path(), ctx->documentPath()); import_type_e actualtype = this->type; if (actualtype == TYPE_UNKNOWN) { std::string extraw = boosty::extension_str( fs::path(filename) ); diff --git a/src/linearextrude.cc b/src/linearextrude.cc index 4953781..bc678e6 100644 --- a/src/linearextrude.cc +++ b/src/linearextrude.cc @@ -29,6 +29,7 @@ #include "module.h" #include "evalcontext.h" #include "printutils.h" +#include "fileutils.h" #include "builtin.h" #include "PolySetEvaluator.h" #include "openscad.h" // get_fragments_from_r() @@ -74,7 +75,7 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI if (!file.isUndefined() && file.type() == Value::STRING) { PRINT("DEPRECATED: Support for reading files in linear_extrude will be removed in future releases. Use a child import() instead."); - node->filename = inst->getAbsolutePath(file.toString()); + node->filename = lookup_file(file.toString(), inst->path(), c.documentPath()); } // if height not given, and first argument is a number, diff --git a/src/mainwin.cc b/src/mainwin.cc index 027f72a..5f9d633 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -488,17 +488,25 @@ void MainWindow::requestOpenFile(const QString &) void MainWindow::openFile(const QString &new_filename) { + QString actual_filename = new_filename; #ifdef ENABLE_MDI if (!editor->toPlainText().isEmpty()) { - new MainWindow(new_filename); + QFileInfo fi(new_filename); + if (fi.suffix().toLower().contains(QRegExp("^(stl|off|dxf)$"))) { + actual_filename = QString(); + } + new MainWindow(actual_filename); clearCurrentOutput(); return; } #endif - setFileName(new_filename); + setFileName(actual_filename); refreshDocument(); updateRecentFiles(); + if (actual_filename.isEmpty()) { + this->editor->setPlainText(QString("import(\"%1\");\n").arg(new_filename)); + } } void diff --git a/src/module.cc b/src/module.cc index 9503f05..8b84c07 100644 --- a/src/module.cc +++ b/src/module.cc @@ -71,7 +71,10 @@ IfElseModuleInstantiation::~IfElseModuleInstantiation() /*! Returns the absolute path to the given filename, unless it's empty. - */ + + NB! This will actually search for the file, to be backwards compatible with <= 2013.01 + (see issue #217) +*/ std::string ModuleInstantiation::getAbsolutePath(const std::string &filename) const { if (!filename.empty() && !boosty::is_absolute(fs::path(filename))) { diff --git a/src/openscad.cc b/src/openscad.cc index 6a0d057..7c54762 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -359,7 +359,8 @@ int main(int argc, char **argv) fs::path fpath = boosty::absolute(fs::path(filename)); fs::path fparent = fpath.parent_path(); fs::current_path(fparent); - + top_ctx.setDocumentPath(fparent.string()); + AbstractNode::resetIndexCounter(); absolute_root_node = root_module->instantiate(&top_ctx, &root_inst, NULL); diff --git a/src/rotateextrude.cc b/src/rotateextrude.cc index 2f9a28b..e073a69 100644 --- a/src/rotateextrude.cc +++ b/src/rotateextrude.cc @@ -28,6 +28,7 @@ #include "module.h" #include "evalcontext.h" #include "printutils.h" +#include "fileutils.h" #include "builtin.h" #include "polyset.h" #include "visitor.h" @@ -70,7 +71,7 @@ AbstractNode *RotateExtrudeModule::instantiate(const Context *ctx, const ModuleI if (!file.isUndefined()) { PRINT("DEPRECATED: Support for reading files in rotate_extrude will be removed in future releases. Use a child import() instead."); - node->filename = inst->getAbsolutePath(file.toString()); + node->filename = lookup_file(file.toString(), inst->path(), c.documentPath()); } node->layername = layer.isUndefined() ? "" : layer.toString(); diff --git a/src/surface.cc b/src/surface.cc index b3246c1..46ddc07 100644 --- a/src/surface.cc +++ b/src/surface.cc @@ -30,6 +30,7 @@ #include "evalcontext.h" #include "builtin.h" #include "printutils.h" +#include "fileutils.h" #include "handle_dep.h" // handle_dep() #include "visitor.h" @@ -82,7 +83,7 @@ AbstractNode *SurfaceModule::instantiate(const Context *ctx, const ModuleInstant c.setVariables(args, evalctx); Value fileval = c.lookup_variable("file"); - node->filename = inst->getAbsolutePath(fileval.isUndefined() ? "" : fileval.toString()); + node->filename = lookup_file(fileval.isUndefined() ? "" : fileval.toString(), inst->path(), c.documentPath()); Value center = c.lookup_variable("center", true); if (center.type() == Value::BOOL) { diff --git a/testdata/scad/features/linear_extrude-tests.scad b/testdata/scad/features/linear_extrude-tests.scad index 67de8e6..67d892f 100644 --- a/testdata/scad/features/linear_extrude-tests.scad +++ b/testdata/scad/features/linear_extrude-tests.scad @@ -11,3 +11,5 @@ translate([31.5,2.5,0]) linear_extrude(height=10, twist=-45) polygon(points = [[ translate([0,20,0]) linear_extrude(height=20, twist=45, slices=2) square([10,10]); translate([19,20,0]) linear_extrude(height=20, twist=45, slices=10) square([10,10]); + +translate([-15,0,0]) linear_extrude(5) square([10,10]); diff --git a/testdata/scad/misc/localfiles_dir/localfiles-compatibility-test.scad b/testdata/scad/misc/localfiles_dir/localfiles-compatibility-test.scad new file mode 100644 index 0000000..d6b197c --- /dev/null +++ b/testdata/scad/misc/localfiles_dir/localfiles-compatibility-test.scad @@ -0,0 +1,3 @@ +use <localfiles_subdir/localfiles_submodule.scad> + +localfiles_submodule(); diff --git a/testdata/scad/misc/localfiles_dir/localfiles_subdir/localfiles_submodule.scad b/testdata/scad/misc/localfiles_dir/localfiles_subdir/localfiles_submodule.scad new file mode 100644 index 0000000..cab3499 --- /dev/null +++ b/testdata/scad/misc/localfiles_dir/localfiles_subdir/localfiles_submodule.scad @@ -0,0 +1,9 @@ +module localfiles_submodule() +{ + linear_extrude(h=100) import("localfile.dxf"); + translate([-250,0,0]) linear_extrude(file="localfile.dxf"); + translate([0,350,0]) rotate_extrude(file="localfile.dxf"); + translate([250,0,0]) scale([200,200,50]) surface("localfile.dat"); + + translate([0,-200,0]) sphere(r=dxf_dim(file="localfile.dxf", name="localfile")/2); +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 51abd06..964adc2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -429,6 +429,7 @@ set(CORE_SOURCES ../src/linearextrude.cc ../src/rotateextrude.cc ../src/printutils.cc + ../src/fileutils.cc ../src/progress.cc ../src/boost-utils.cc ${FLEX_OpenSCADlexer_OUTPUTS} @@ -762,13 +763,15 @@ list(APPEND DUMPTEST_FILES ${MINIMAL_FILES} ${FEATURES_FILES} ${EXAMPLE_FILES}) list(APPEND DUMPTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/escape-test.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/include-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/use-tests.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/localfiles-test.scad) + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/localfiles-test.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/localfiles_dir/localfiles-compatibility-test.scad) list(APPEND CGALPNGTEST_FILES ${FEATURES_FILES} ${SCAD_DXF_FILES} ${EXAMPLE_FILES}) list(APPEND CGALPNGTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/include-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/use-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/transform-nan-inf-tests.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/localfiles-test.scad) + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/localfiles-test.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/localfiles_dir/localfiles-compatibility-test.scad) list(APPEND OPENCSGTEST_FILES ${CGALPNGTEST_FILES}) list(APPEND OPENCSGTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/bbox-transform-bug.scad) diff --git a/tests/cgalpngtest.cc b/tests/cgalpngtest.cc index 81fc6b4..7b958de 100644 --- a/tests/cgalpngtest.cc +++ b/tests/cgalpngtest.cc @@ -113,9 +113,10 @@ int main(int argc, char **argv) exit(1); } - if (fs::path(filename).has_parent_path()) { - fs::current_path(fs::path(filename).parent_path()); - } + fs::path fpath = boosty::absolute(fs::path(filename)); + fs::path fparent = fpath.parent_path(); + fs::current_path(fparent); + top_ctx.setDocumentPath(fparent.string()); AbstractNode::resetIndexCounter(); AbstractNode *absolute_root_node = root_module->instantiate(&top_ctx, &root_inst); diff --git a/tests/csgtestcore.cc b/tests/csgtestcore.cc index 320b533..7b9dbab 100644 --- a/tests/csgtestcore.cc +++ b/tests/csgtestcore.cc @@ -148,9 +148,10 @@ int csgtestcore(int argc, char *argv[], test_type_e test_type) } if (!sysinfo_dump) { - if (fs::path(filename).has_parent_path()) { - fs::current_path(fs::path(filename).parent_path()); - } + fs::path fpath = boosty::absolute(fs::path(filename)); + fs::path fparent = fpath.parent_path(); + fs::current_path(fparent); + top_ctx.setDocumentPath(fparent.string()); } AbstractNode::resetIndexCounter(); diff --git a/tests/dumptest.cc b/tests/dumptest.cc index e4876fa..4477703 100644 --- a/tests/dumptest.cc +++ b/tests/dumptest.cc @@ -97,9 +97,10 @@ int main(int argc, char **argv) exit(1); } - if (fs::path(filename).has_parent_path()) { - fs::current_path(fs::path(filename).parent_path()); - } + fs::path fpath = boosty::absolute(fs::path(filename)); + fs::path fparent = fpath.parent_path(); + fs::current_path(fparent); + top_ctx.setDocumentPath(fparent.string()); AbstractNode::resetIndexCounter(); root_node = root_module->instantiate(&top_ctx, &root_inst); @@ -130,7 +131,7 @@ int main(int argc, char **argv) delete root_module; fs::current_path(original_path); - root_module = parsefile(outfilename); + root_module = parsefile(outfilename, fparent.string().c_str()); if (!root_module) { fprintf(stderr, "Error: Unable to read back dumped file\n"); exit(1); @@ -141,9 +142,7 @@ int main(int argc, char **argv) tree.setRoot(root_node); - if (fs::path(outfilename).has_parent_path()) { - fs::current_path(fs::path(outfilename).parent_path()); - } + fs::current_path(fparent); string readbackstr = dumptree(tree, *root_node); if (dumpstdstr != readbackstr) { diff --git a/tests/regression/cgalpngtest/linear_extrude-tests-expected.png b/tests/regression/cgalpngtest/linear_extrude-tests-expected.png Binary files differindex 1486743..7d3ea2c 100644 --- a/tests/regression/cgalpngtest/linear_extrude-tests-expected.png +++ b/tests/regression/cgalpngtest/linear_extrude-tests-expected.png diff --git a/tests/regression/cgalpngtest/localfiles-compatibility-test-expected.png b/tests/regression/cgalpngtest/localfiles-compatibility-test-expected.png Binary files differnew file mode 100644 index 0000000..d0cfd50 --- /dev/null +++ b/tests/regression/cgalpngtest/localfiles-compatibility-test-expected.png diff --git a/tests/regression/dumptest/linear_extrude-tests-expected.txt b/tests/regression/dumptest/linear_extrude-tests-expected.txt index cba1189..298b7e7 100644 --- a/tests/regression/dumptest/linear_extrude-tests-expected.txt +++ b/tests/regression/dumptest/linear_extrude-tests-expected.txt @@ -29,4 +29,9 @@ square(size = [10, 10], center = false); } } + multmatrix([[1, 0, 0, -15], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 5, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + square(size = [10, 10], center = false); + } + } diff --git a/tests/regression/dumptest/localfiles-compatibility-test-expected.txt b/tests/regression/dumptest/localfiles-compatibility-test-expected.txt new file mode 100644 index 0000000..8725061 --- /dev/null +++ b/tests/regression/dumptest/localfiles-compatibility-test-expected.txt @@ -0,0 +1,20 @@ + group() { + linear_extrude(height = 100, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + import(file = "localfile.dxf", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); + } + multmatrix([[1, 0, 0, -250], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(file = "localfile.dxf", layer = "", origin = [0, 0], scale = 1, height = 100, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 2); + } + multmatrix([[1, 0, 0, 0], [0, 1, 0, 350], [0, 0, 1, 0], [0, 0, 0, 1]]) { + rotate_extrude(file = "localfile.dxf", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); + } + multmatrix([[1, 0, 0, 250], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + multmatrix([[200, 0, 0, 0], [0, 200, 0, 0], [0, 0, 50, 0], [0, 0, 0, 1]]) { + surface(file = "localfile.dat", center = false); + } + } + multmatrix([[1, 0, 0, 0], [0, 1, 0, -200], [0, 0, 1, 0], [0, 0, 0, 1]]) { + sphere($fn = 0, $fa = 12, $fs = 2, r = 100); + } + } + diff --git a/tests/regression/opencsgtest/linear_extrude-tests-expected.png b/tests/regression/opencsgtest/linear_extrude-tests-expected.png Binary files differindex f31b22a..b929d09 100644 --- a/tests/regression/opencsgtest/linear_extrude-tests-expected.png +++ b/tests/regression/opencsgtest/linear_extrude-tests-expected.png diff --git a/tests/regression/opencsgtest/localfiles-compatibility-test-expected.png b/tests/regression/opencsgtest/localfiles-compatibility-test-expected.png Binary files differnew file mode 100644 index 0000000..f280efd --- /dev/null +++ b/tests/regression/opencsgtest/localfiles-compatibility-test-expected.png diff --git a/tests/regression/throwntogethertest/linear_extrude-tests-expected.png b/tests/regression/throwntogethertest/linear_extrude-tests-expected.png Binary files differindex b672783..fddeeb8 100644 --- a/tests/regression/throwntogethertest/linear_extrude-tests-expected.png +++ b/tests/regression/throwntogethertest/linear_extrude-tests-expected.png diff --git a/tests/regression/throwntogethertest/localfiles-compatibility-test-expected.png b/tests/regression/throwntogethertest/localfiles-compatibility-test-expected.png Binary files differnew file mode 100644 index 0000000..f280efd --- /dev/null +++ b/tests/regression/throwntogethertest/localfiles-compatibility-test-expected.png diff --git a/tests/tests-common.cc b/tests/tests-common.cc index ac85e37..3c66e1b 100644 --- a/tests/tests-common.cc +++ b/tests/tests-common.cc @@ -7,7 +7,12 @@ #include <sstream> #include <fstream> -FileModule *parsefile(const char *filename) +/*! + fakepath is used to force the parser to believe that the file is + read from this location, in order to ensure that filepaths are + eavluated relative to this path (for testing purposes). +*/ +FileModule *parsefile(const char *filename, const char *fakepath) { FileModule *root_module = NULL; @@ -19,7 +24,9 @@ FileModule *parsefile(const char *filename) else { std::string text((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>()); text += "\n" + commandline_commands; - std::string pathname = boosty::stringy(fs::path(filename).parent_path()); + std::string pathname; + if (fakepath) pathname = fakepath; + else pathname = boosty::stringy(fs::path(filename).parent_path()); root_module = parse(text.c_str(), pathname.c_str(), false); if (root_module) { root_module->handleDependencies(); diff --git a/tests/tests-common.h b/tests/tests-common.h index 3393884..e16bcda 100644 --- a/tests/tests-common.h +++ b/tests/tests-common.h @@ -1,6 +1,8 @@ #ifndef TESTS_COMMON_H_ #define TESTS_COMMON_H_ -class FileModule *parsefile(const char *filename); +#include <stdlib.h> + +class FileModule *parsefile(const char *filename, const char *fakepath = NULL); #endif |