diff --git a/src/MainWindow.h b/src/MainWindow.h index 79e20809..46a29969 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -54,11 +54,12 @@ public: std::vector > background_terms; CSGChain *background_chain; QString last_compiled_doc; + QString qexamplesdir; static const int maxRecentFiles = 10; QAction *actionRecentFile[maxRecentFiles]; - MainWindow(const QString &filename); + MainWindow(const QString &filename, const QString &examplesdir); ~MainWindow(); protected: diff --git a/src/PlatformUtils.cc b/src/PlatformUtils.cc index a64162c6..f731a9a3 100644 --- a/src/PlatformUtils.cc +++ b/src/PlatformUtils.cc @@ -40,11 +40,12 @@ std::string PlatformUtils::libraryPath() } #include "version_check.h" -#include "cgal.h" -#include #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) +#ifdef ENABLE_CGAL +#include "cgal.h" +#include #if defined(__GNUG__) #define GCC_INT_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 ) #if GCC_INT_VERSION > 40600 || defined(__clang__) @@ -52,6 +53,7 @@ std::string PlatformUtils::libraryPath() #define __openscad_info_demangle__ 1 #endif // GCC_INT_VERSION #endif // GNUG +#endif // ENABLE_CGAL std::string PlatformUtils::info() { @@ -79,6 +81,13 @@ std::string PlatformUtils::info() #define OPENCSG_VERSION_STRING "unknown, <1.3.2" #endif +#ifdef QT_VERSION + std::string qtVersion = qVersion(); +#else + std::string qtVersion = "Qt disabled"; +#endif + +#ifdef ENABLE_CGAL std::string cgal_3d_kernel = typeid(CGAL_Kernel3).name(); std::string cgal_2d_kernel = typeid(CGAL_Kernel2).name(); std::string cgal_2d_kernelEx = typeid(CGAL_ExactKernel2).name(); @@ -87,10 +96,15 @@ std::string PlatformUtils::info() cgal_3d_kernel = std::string( abi::__cxa_demangle( cgal_3d_kernel.c_str(), 0, 0, &status ) ); cgal_2d_kernel = std::string( abi::__cxa_demangle( cgal_2d_kernel.c_str(), 0, 0, &status ) ); cgal_2d_kernelEx = std::string( abi::__cxa_demangle( cgal_2d_kernelEx.c_str(), 0, 0, &status ) ); -#endif +#endif // demangle boost::replace_all( cgal_3d_kernel, "CGAL::", "" ); boost::replace_all( cgal_2d_kernel, "CGAL::", "" ); boost::replace_all( cgal_2d_kernelEx, "CGAL::", "" ); +#else // ENABLE_CGAL + std::string cgal_3d_kernel = ""; + std::string cgal_2d_kernel = ""; + std::string cgal_2d_kernelEx = ""; +#endif // ENABLE_CGAL s << "OpenSCAD Version: " << TOSTRING(OPENSCAD_VERSION) << "\nCompiler: " << compiler_info @@ -99,7 +113,7 @@ std::string PlatformUtils::info() << "\nEigen version: " << EIGEN_WORLD_VERSION << "." << EIGEN_MAJOR_VERSION << "." << EIGEN_MINOR_VERSION << "\nCGAL version, kernels: " << TOSTRING(CGAL_VERSION) << ", " << cgal_3d_kernel << ", " << cgal_2d_kernel << ", " << cgal_2d_kernelEx << "\nOpenCSG version: " << OPENCSG_VERSION_STRING - << "\nQt version: " << qVersion() + << "\nQt version: " << qtVersion << "\nMingW build: " << mingwstatus ; return s.str(); diff --git a/src/mainwin.cc b/src/mainwin.cc index fd1c5521..ea7da66e 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -27,7 +27,6 @@ #include "PolySetCache.h" #include "ModuleCache.h" #include "MainWindow.h" -#include "openscad.h" // examplesdir #include "parsersettings.h" #include "Preferences.h" #include "printutils.h" @@ -103,8 +102,6 @@ #include "boosty.h" -extern QString examplesdir; - // Global application state unsigned int GuiLocker::gui_locked = 0; @@ -156,7 +153,7 @@ settings_valueList(const QString &key, const QList &defaultList = QListqexamplesdir = examplesdir; this->openglbox = NULL; root_module = NULL; absolute_root_node = NULL; @@ -253,10 +251,9 @@ MainWindow::MainWindow(const QString &filename) this->menuOpenRecent->addAction(this->fileActionClearRecent); connect(this->fileActionClearRecent, SIGNAL(triggered()), this, SLOT(clearRecentFiles())); - - if (!examplesdir.isEmpty()) { + if (!qexamplesdir.isEmpty()) { bool found_example = false; - QStringList examples = QDir(examplesdir).entryList(QStringList("*.scad"), + QStringList examples = QDir(qexamplesdir).entryList(QStringList("*.scad"), QDir::Files | QDir::Readable, QDir::Name); foreach (const QString &ex, examples) { this->menuExamples->addAction(ex, this, SLOT(actionOpenExample())); @@ -985,7 +982,7 @@ void MainWindow::actionOpenExample() { QAction *action = qobject_cast(sender()); if (action) { - openFile(examplesdir + QDir::separator() + action->text()); + openFile(qexamplesdir + QDir::separator() + action->text()); } } diff --git a/src/openscad.cc b/src/openscad.cc index fb5ee448..a8e71b1b 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -25,7 +25,6 @@ */ #include "openscad.h" -#include "MainWindow.h" #include "node.h" #include "module.h" #include "modcontext.h" @@ -53,12 +52,9 @@ #include "CSGTermEvaluator.h" #include "CsgInfo.h" -#include -#include -#include #include -#ifdef Q_WS_MAC +#ifdef __APPLE__ #include "EventFilter.h" #include "AppleEvents.h" #ifdef OPENSCAD_DEPLOY @@ -79,6 +75,13 @@ namespace po = boost::program_options; namespace fs = boost::filesystem; +namespace Render { enum type { CGAL, OPENCSG, THROWNTOGETHER }; }; +std::string commandline_commands; +std::string currentdir; +using std::string; +using std::vector; +using boost::lexical_cast; +using boost::is_any_of; static void help(const char *progname) { @@ -119,15 +122,6 @@ static void info() exit(0); } -std::string commandline_commands; -std::string currentdir; -QString examplesdir; - -using std::string; -using std::vector; -using boost::lexical_cast; -using boost::is_any_of; - Camera get_camera( po::variables_map vm ) { Camera camera; @@ -182,6 +176,342 @@ Camera get_camera( po::variables_map vm ) return camera; } +int cmdline( const char* deps_output_file, const char* filename, Camera &camera, const char *output_file, fs::path original_path, Render::type renderer ) +{ + Tree tree; +#ifdef ENABLE_CGAL + CGALEvaluator cgalevaluator(tree); + PolySetCGALEvaluator psevaluator(cgalevaluator); +#endif + const char *stl_output_file = NULL; + const char *off_output_file = NULL; + const char *dxf_output_file = NULL; + const char *csg_output_file = NULL; + const char *png_output_file = NULL; + const char *ast_output_file = NULL; + const char *term_output_file = NULL; + bool null_output = false; + + std::string suffix = boosty::extension_str( output_file ); + boost::algorithm::to_lower( suffix ); + + if (suffix == ".stl") stl_output_file = output_file; + else if (suffix == ".off") off_output_file = output_file; + else if (suffix == ".dxf") dxf_output_file = output_file; + else if (suffix == ".csg") csg_output_file = output_file; + else if (suffix == ".png") png_output_file = output_file; + else if (suffix == ".ast") ast_output_file = output_file; + else if (suffix == ".term") term_output_file = output_file; + else if (strcmp(output_file, "null") == 0) null_output = true; + else { + fprintf(stderr, "Unknown suffix for output file %s\n", output_file); + return 1; + } + + // Top context - this context only holds builtins + ModuleContext top_ctx; + top_ctx.registerBuiltin(); +#if 0 && DEBUG + top_ctx.dump(NULL, NULL); +#endif + + FileModule *root_module; + ModuleInstantiation root_inst("group"); + AbstractNode *root_node; + AbstractNode *absolute_root_node; + CGAL_Nef_polyhedron root_N; + + handle_dep(filename); + + std::ifstream ifs(filename); + if (!ifs.is_open()) { + fprintf(stderr, "Can't open input file '%s'!\n", filename); + return 1; + } + std::string text((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); + text += "\n" + commandline_commands; + fs::path abspath = boosty::absolute(filename); + std::string parentpath = boosty::stringy(abspath.parent_path()); + root_module = parse(text.c_str(), parentpath.c_str(), false); + if (!root_module) { + fprintf(stderr, "Can't parse file '%s'!\n", filename); + return 1; + } + root_module->handleDependencies(); + + 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); + + // Do we have an explicit root node (! modifier)? + if (!(root_node = find_root_tag(absolute_root_node))) + root_node = absolute_root_node; + + tree.setRoot(root_node); + + if (csg_output_file) { + fs::current_path(original_path); + std::ofstream fstream(csg_output_file); + if (!fstream.is_open()) { + PRINTB("Can't open file \"%s\" for export", csg_output_file); + } + else { + fs::current_path(fparent); // Force exported filenames to be relative to document path + fstream << tree.getString(*root_node) << "\n"; + fstream.close(); + } + } + else if (ast_output_file) { + fs::current_path(original_path); + std::ofstream fstream(ast_output_file); + if (!fstream.is_open()) { + PRINTB("Can't open file \"%s\" for export", ast_output_file); + } + else { + fs::current_path(fparent); // Force exported filenames to be relative to document path + fstream << root_module->dump("", "") << "\n"; + fstream.close(); + } + } + else if (term_output_file) { + std::vector > highlight_terms; + std::vector > background_terms; + + CSGTermEvaluator csgRenderer(tree, &psevaluator); + shared_ptr root_raw_term = csgRenderer.evaluateCSGTerm(*root_node, highlight_terms, background_terms); + + fs::current_path(original_path); + std::ofstream fstream(term_output_file); + if (!fstream.is_open()) { + PRINTB("Can't open file \"%s\" for export", term_output_file); + } + else { + if (!root_raw_term) + fstream << "No top-level CSG object\n"; + else { + fstream << root_raw_term->dump() << "\n"; + } + fstream.close(); + } + } + else { +#ifdef ENABLE_CGAL + if ((null_output || png_output_file) && !(renderer==Render::CGAL)) { + // null output or OpenCSG png -> don't necessarily need CGALMesh evaluation + } else { + root_N = cgalevaluator.evaluateCGALMesh(*tree.root()); + } + + fs::current_path(original_path); + + if (deps_output_file) { + std::string deps_out( deps_output_file ); + std::string geom_out; + if ( stl_output_file ) geom_out = std::string(stl_output_file); + else if ( off_output_file ) geom_out = std::string(off_output_file); + else if ( dxf_output_file ) geom_out = std::string(dxf_output_file); + else if ( png_output_file ) geom_out = std::string(png_output_file); + else { + PRINTB("Output file:%s\n",output_file); + PRINT("Sorry, don't know how to write deps for that file type. Exiting\n"); + return 1; + } + int result = write_deps( deps_out, geom_out ); + if ( !result ) { + PRINT("error writing deps"); + return 1; + } + } + + if (stl_output_file) { + if (root_N.dim != 3) { + fprintf(stderr, "Current top level object is not a 3D object.\n"); + return 1; + } + if (!root_N.p3->is_simple()) { + fprintf(stderr, "Object isn't a valid 2-manifold! Modify your design.\n"); + return 1; + } + std::ofstream fstream(stl_output_file); + if (!fstream.is_open()) { + PRINTB("Can't open file \"%s\" for export", stl_output_file); + } + else { + export_stl(&root_N, fstream); + fstream.close(); + } + } + + if (off_output_file) { + if (root_N.dim != 3) { + fprintf(stderr, "Current top level object is not a 3D object.\n"); + return 1; + } + if (!root_N.p3->is_simple()) { + fprintf(stderr, "Object isn't a valid 2-manifold! Modify your design.\n"); + return 1; + } + std::ofstream fstream(off_output_file); + if (!fstream.is_open()) { + PRINTB("Can't open file \"%s\" for export", off_output_file); + } + else { + export_off(&root_N, fstream); + fstream.close(); + } + } + + if (dxf_output_file) { + if (root_N.dim != 2) { + fprintf(stderr, "Current top level object is not a 2D object.\n"); + return 1; + } + std::ofstream fstream(dxf_output_file); + if (!fstream.is_open()) { + PRINTB("Can't open file \"%s\" for export", dxf_output_file); + } + else { + export_dxf(&root_N, fstream); + fstream.close(); + } + } + + if (png_output_file) { + std::ofstream fstream(png_output_file,std::ios::out|std::ios::binary); + if (!fstream.is_open()) { + PRINTB("Can't open file \"%s\" for export", png_output_file); + } + else { + if (renderer==Render::CGAL) { + export_png_with_cgal(&root_N, camera, fstream); + } else if (renderer==Render::THROWNTOGETHER) { + export_png_with_throwntogether(tree, camera, fstream); + } else { + export_png_with_opencsg(tree, camera, fstream); + } + fstream.close(); + } + } +#else + fprintf(stderr, "OpenSCAD has been compiled without CGAL support!\n"); + return 1; +#endif + } + delete root_node; + return 0; +} + +#ifdef OPENSCAD_TESTING +#undef OPENSCAD_QTGUI +#else +#define OPENSCAD_QTGUI 1 +#endif + + +#ifdef OPENSCAD_QTGUI +#include "MainWindow.h" +#include +#include +#include + +bool QtUseGUI() +{ +#ifdef Q_WS_X11 + // see : + // On X11, the window system is initialized if GUIenabled is true. If GUIenabled + // is false, the application does not connect to the X server. On Windows and + // Macintosh, currently the window system is always initialized, regardless of the + // value of GUIenabled. This may change in future versions of Qt. + bool useGUI = getenv("DISPLAY") != 0; +#else + bool useGUI = true; +#endif + return useGUI; +} + +int gui(const char * filename,int argc, char ** argv) +{ + QApplication app(argc, argv, true); //useGUI); +#ifdef Q_WS_MAC + app.installEventFilter(new EventFilter(&app)); +#endif + // set up groups for QSettings + QCoreApplication::setOrganizationName("OpenSCAD"); + QCoreApplication::setOrganizationDomain("openscad.org"); + QCoreApplication::setApplicationName("OpenSCAD"); + QCoreApplication::setApplicationVersion(TOSTRING(OPENSCAD_VERSION)); + + QDir exdir(QApplication::instance()->applicationDirPath()); + QString qexamplesdir; +#ifdef Q_WS_MAC + exdir.cd("../Resources"); // Examples can be bundled + if (!exdir.exists("examples")) exdir.cd("../../.."); +#elif defined(Q_OS_UNIX) + if (exdir.cd("../share/openscad/examples")) { + qexamplesdir = exdir.path(); + } else + if (exdir.cd("../../share/openscad/examples")) { + qexamplesdir = exdir.path(); + } else + if (exdir.cd("../../examples")) { + qexamplesdir = exdir.path(); + } else +#endif + if (exdir.cd("examples")) { + qexamplesdir = exdir.path(); + } + + parser_init(QApplication::instance()->applicationDirPath().toLocal8Bit().constData()); + +#ifdef Q_WS_MAC + installAppleEventHandlers(); +#endif + +#if defined(OPENSCAD_DEPLOY) && defined(Q_WS_MAC) + AutoUpdater *updater = new SparkleAutoUpdater; + AutoUpdater::setUpdater(updater); + if (updater->automaticallyChecksForUpdates()) updater->checkForUpdates(); +#endif + + QString qfilename; + if (filename) qfilename = QString::fromLocal8Bit(boosty::stringy(boosty::absolute(filename)).c_str()); + +#if 0 /*** disabled by clifford wolf: adds rendering artefacts with OpenCSG ***/ + // turn on anti-aliasing + QGLFormat f; + f.setSampleBuffers(true); + f.setSamples(4); + QGLFormat::setDefaultFormat(f); +#endif +#ifdef ENABLE_MDI + new MainWindow(qfilename,qexamplesdir); + vector inputFiles; + if (vm.count("input-file")) { + inputFiles = vm["input-file"].as >(); + for (vector::const_iterator infile = inputFiles.begin()+1; infile != inputFiles.end(); infile++) { + new MainWindow(QString::fromLocal8Bit(boosty::stringy(original_path / *infile).c_str())); + } + } + app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit())); +#else + MainWindow *m = new MainWindow(qfilename,qexamplesdir); + app.connect(m, SIGNAL(destroyed()), &app, SLOT(quit())); +#endif + return app.exec(); +} +#else // OPENSCAD_QTGUI +bool QtUseGUI() { return false; } +int gui(const char * filename,int argc, char ** argv) +{ + fprintf(stderr,"Error: compiled without QT, but trying to run GUI\n"); + return 1; +} +#endif // OPENSCAD_QTGUI + int main(int argc, char **argv) { int rc = 0; @@ -193,28 +523,8 @@ int main(int argc, char **argv) #endif Builtins::instance()->initialize(); -#ifdef Q_WS_X11 - // see : - // On X11, the window system is initialized if GUIenabled is true. If GUIenabled - // is false, the application does not connect to the X server. On Windows and - // Macintosh, currently the window system is always initialized, regardless of the - // value of GUIenabled. This may change in future versions of Qt. - bool useGUI = getenv("DISPLAY") != 0; -#else - bool useGUI = true; -#endif - QApplication app(argc, argv, useGUI); -#ifdef Q_WS_MAC - app.installEventFilter(new EventFilter(&app)); -#endif fs::path original_path = fs::current_path(); - // set up groups for QSettings - QCoreApplication::setOrganizationName("OpenSCAD"); - QCoreApplication::setOrganizationDomain("openscad.org"); - QCoreApplication::setApplicationName("OpenSCAD"); - QCoreApplication::setApplicationVersion(TOSTRING(OPENSCAD_VERSION)); - const char *filename = NULL; const char *output_file = NULL; const char *deps_output_file = NULL; @@ -259,6 +569,13 @@ int main(int argc, char **argv) if (vm.count("version")) version(); if (vm.count("info")) info(); + Render::type renderer = Render::OPENCSG; + if (vm.count("render")) + renderer = Render::CGAL; + if (vm.count("preview")) + if (vm["preview"].as() == "throwntogether") + renderer = Render::THROWNTOGETHER; + if (vm.count("o")) { // FIXME: Allow for multiple output files? if (output_file) help(argv[0]); @@ -306,297 +623,23 @@ int main(int argc, char **argv) Camera camera = get_camera( vm ); - QDir exdir(QApplication::instance()->applicationDirPath()); -#ifdef Q_WS_MAC - exdir.cd("../Resources"); // Examples can be bundled - if (!exdir.exists("examples")) exdir.cd("../../.."); -#elif defined(Q_OS_UNIX) - if (exdir.cd("../share/openscad/examples")) { - examplesdir = exdir.path(); - } else - if (exdir.cd("../../share/openscad/examples")) { - examplesdir = exdir.path(); - } else - if (exdir.cd("../../examples")) { - examplesdir = exdir.path(); - } else -#endif - if (exdir.cd("examples")) { - examplesdir = exdir.path(); - } - - parser_init(QApplication::instance()->applicationDirPath().toLocal8Bit().constData()); - // Initialize global visitors NodeCache nodecache; NodeDumper dumper(nodecache); - Tree tree; -#ifdef ENABLE_CGAL - CGALEvaluator cgalevaluator(tree); - PolySetCGALEvaluator psevaluator(cgalevaluator); -#endif if (output_file) { - const char *stl_output_file = NULL; - const char *off_output_file = NULL; - const char *dxf_output_file = NULL; - const char *csg_output_file = NULL; - const char *png_output_file = NULL; - const char *ast_output_file = NULL; - const char *term_output_file = NULL; - bool null_output = false; - - QString suffix = QFileInfo(output_file).suffix().toLower(); - if (suffix == "stl") stl_output_file = output_file; - else if (suffix == "off") off_output_file = output_file; - else if (suffix == "dxf") dxf_output_file = output_file; - else if (suffix == "csg") csg_output_file = output_file; - else if (suffix == "png") png_output_file = output_file; - else if (suffix == "ast") ast_output_file = output_file; - else if (suffix == "term") term_output_file = output_file; - else if (strcmp(output_file, "null") == 0) null_output = true; - else { - fprintf(stderr, "Unknown suffix for output file %s\n", output_file); - exit(1); - } - if (!filename) help(argv[0]); - - // Top context - this context only holds builtins - ModuleContext top_ctx; - top_ctx.registerBuiltin(); -#if 0 && DEBUG - top_ctx.dump(NULL, NULL); -#endif - - FileModule *root_module; - ModuleInstantiation root_inst("group"); - AbstractNode *root_node; - AbstractNode *absolute_root_node; - CGAL_Nef_polyhedron root_N; - - handle_dep(filename); - - std::ifstream ifs(filename); - if (!ifs.is_open()) { - fprintf(stderr, "Can't open input file '%s'!\n", filename); - exit(1); - } - std::string text((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); - text += "\n" + commandline_commands; - fs::path abspath = boosty::absolute(filename); - std::string parentpath = boosty::stringy(abspath.parent_path()); - root_module = parse(text.c_str(), parentpath.c_str(), false); - if (!root_module) exit(1); - root_module->handleDependencies(); - - 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); - - // Do we have an explicit root node (! modifier)? - if (!(root_node = find_root_tag(absolute_root_node))) - root_node = absolute_root_node; - - tree.setRoot(root_node); - - if (csg_output_file) { - fs::current_path(original_path); - std::ofstream fstream(csg_output_file); - if (!fstream.is_open()) { - PRINTB("Can't open file \"%s\" for export", csg_output_file); - } - else { - fs::current_path(fparent); // Force exported filenames to be relative to document path - fstream << tree.getString(*root_node) << "\n"; - fstream.close(); - } - } - else if (ast_output_file) { - fs::current_path(original_path); - std::ofstream fstream(ast_output_file); - if (!fstream.is_open()) { - PRINTB("Can't open file \"%s\" for export", ast_output_file); - } - else { - fs::current_path(fparent); // Force exported filenames to be relative to document path - fstream << root_module->dump("", "") << "\n"; - fstream.close(); - } - } - else if (term_output_file) { - std::vector > highlight_terms; - std::vector > background_terms; - - CSGTermEvaluator csgrenderer(tree, &psevaluator); - shared_ptr root_raw_term = csgrenderer.evaluateCSGTerm(*root_node, highlight_terms, background_terms); - - fs::current_path(original_path); - std::ofstream fstream(term_output_file); - if (!fstream.is_open()) { - PRINTB("Can't open file \"%s\" for export", term_output_file); - } - else { - if (!root_raw_term) - fstream << "No top-level CSG object\n"; - else { - fstream << root_raw_term->dump() << "\n"; - } - fstream.close(); - } - } - else { -#ifdef ENABLE_CGAL - if ((null_output || png_output_file) && !vm.count("render")) { - // null output or OpenCSG png -> don't necessarily need CGALMesh evaluation - } else { - root_N = cgalevaluator.evaluateCGALMesh(*tree.root()); - } - - fs::current_path(original_path); - - if (deps_output_file) { - std::string deps_out( deps_output_file ); - std::string geom_out; - if ( stl_output_file ) geom_out = std::string(stl_output_file); - else if ( off_output_file ) geom_out = std::string(off_output_file); - else if ( dxf_output_file ) geom_out = std::string(dxf_output_file); - else if ( png_output_file ) geom_out = std::string(png_output_file); - else { - PRINTB("Output file:%s\n",output_file); - PRINT("Sorry, don't know how to write deps for that file type. Exiting\n"); - exit(1); - } - int result = write_deps( deps_out, geom_out ); - if ( !result ) { - PRINT("error writing deps"); - exit(1); - } - } - - if (stl_output_file) { - if (root_N.dim != 3) { - fprintf(stderr, "Current top level object is not a 3D object.\n"); - exit(1); - } - if (!root_N.p3->is_simple()) { - fprintf(stderr, "Object isn't a valid 2-manifold! Modify your design.\n"); - exit(1); - } - std::ofstream fstream(stl_output_file); - if (!fstream.is_open()) { - PRINTB("Can't open file \"%s\" for export", stl_output_file); - } - else { - export_stl(&root_N, fstream); - fstream.close(); - } - } - - if (off_output_file) { - if (root_N.dim != 3) { - fprintf(stderr, "Current top level object is not a 3D object.\n"); - exit(1); - } - if (!root_N.p3->is_simple()) { - fprintf(stderr, "Object isn't a valid 2-manifold! Modify your design.\n"); - exit(1); - } - std::ofstream fstream(off_output_file); - if (!fstream.is_open()) { - PRINTB("Can't open file \"%s\" for export", off_output_file); - } - else { - export_off(&root_N, fstream); - fstream.close(); - } - } - - if (dxf_output_file) { - if (root_N.dim != 2) { - fprintf(stderr, "Current top level object is not a 2D object.\n"); - exit(1); - } - std::ofstream fstream(dxf_output_file); - if (!fstream.is_open()) { - PRINTB("Can't open file \"%s\" for export", dxf_output_file); - } - else { - export_dxf(&root_N, fstream); - fstream.close(); - } - } - - if (png_output_file) { - std::ofstream fstream(png_output_file,std::ios::out|std::ios::binary); - if (!fstream.is_open()) { - PRINTB("Can't open file \"%s\" for export", png_output_file); - } - else { - if (vm.count("render")) { - export_png_with_cgal(&root_N, camera, fstream); - } else if (vm.count("preview") && vm["preview"].as() == "throwntogether" ) { - export_png_with_throwntogether(tree, camera, fstream); - } else { - export_png_with_opencsg(tree, camera, fstream); - } - fstream.close(); - } - } -#else - fprintf(stderr, "OpenSCAD has been compiled without CGAL support!\n"); - exit(1); -#endif - } - delete root_node; + rc = cmdline( deps_output_file, filename, camera, output_file, original_path, renderer ); } - else if (useGUI) + else if (QtUseGUI()) { -#ifdef Q_WS_MAC - installAppleEventHandlers(); -#endif - -#if defined(OPENSCAD_DEPLOY) && defined(Q_WS_MAC) - AutoUpdater *updater = new SparkleAutoUpdater; - AutoUpdater::setUpdater(updater); - if (updater->automaticallyChecksForUpdates()) updater->checkForUpdates(); -#endif - - QString qfilename; - if (filename) qfilename = QString::fromLocal8Bit(boosty::stringy(boosty::absolute(filename)).c_str()); - -#if 0 /*** disabled by clifford wolf: adds rendering artefacts with OpenCSG ***/ - // turn on anti-aliasing - QGLFormat f; - f.setSampleBuffers(true); - f.setSamples(4); - QGLFormat::setDefaultFormat(f); -#endif -#ifdef ENABLE_MDI - new MainWindow(qfilename); - vector inputFiles; - if (vm.count("input-file")) { - inputFiles = vm["input-file"].as >(); - for (vector::const_iterator infile = inputFiles.begin()+1; infile != inputFiles.end(); infile++) { - new MainWindow(QString::fromLocal8Bit(boosty::stringy(original_path / *infile).c_str())); - } - } - app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit())); -#else - MainWindow *m = new MainWindow(qfilename); - app.connect(m, SIGNAL(destroyed()), &app, SLOT(quit())); -#endif - rc = app.exec(); + rc = gui(filename,argc,argv); } else { fprintf(stderr, "Requested GUI mode but can't open display!\n"); - exit(1); + return 1; } Builtins::instance(true); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index babd0a08..67870b3a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -412,6 +412,25 @@ include_directories(../src) add_definitions(-DOPENSCAD_VERSION=test -DOPENSCAD_YEAR=2011 -DOPENSCAD_MONTH=10) add_definitions(-DOPENSCAD_TESTING) +# Platform specific settings + +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + message(STATUS "Offscreen OpenGL Context - using Apple CGL") + set(OFFSCREEN_CTX_SOURCE "OffscreenContextCGL.mm" CACHE TYPE STRING) + set(OFFSCREEN_IMGUTILS_SOURCE "imageutils-macosx.cc" CACHE TYPE STRING) + set(PLATFORMUTILS_SOURCE "PlatformUtils-mac.mm" CACHE TYPE STRING) +elseif(UNIX) + message(STATUS "Offscreen OpenGL Context - using Unix GLX") + set(OFFSCREEN_CTX_SOURCE "OffscreenContextGLX.cc" CACHE TYPE STRING) + set(OFFSCREEN_IMGUTILS_SOURCE "imageutils-lodepng.cc" CACHE TYPE STRING) + set(PLATFORMUTILS_SOURCE "PlatformUtils-posix.cc" CACHE TYPE STRING) +elseif(WIN32) + message(STATUS "Offscreen OpenGL Context - using Microsoft WGL") + set(OFFSCREEN_CTX_SOURCE "OffscreenContextWGL.cc" CACHE TYPE STRING) + set(OFFSCREEN_IMGUTILS_SOURCE "imageutils-lodepng.cc" CACHE TYPE STRING) + set(PLATFORMUTILS_SOURCE "PlatformUtils-win.cc" CACHE TYPE STRING) +endif() + set(CORE_SOURCES tests-common.cc ../src/parsersettings.cc @@ -440,6 +459,7 @@ set(CORE_SOURCES ../src/surface.cc ../src/control.cc ../src/render.cc + ../src/rendersettings.cc ../src/dxfdata.cc ../src/dxfdim.cc ../src/linearextrude.cc @@ -455,11 +475,11 @@ set(NOCGAL_SOURCES ../src/builtin.cc ../src/dxftess.cc ../src/import.cc - ../src/export.cc) + ../src/export.cc) set(CGAL_SOURCES ${NOCGAL_SOURCES} - ../src/CSGTermEvaluator.cc + ../src/CSGTermEvaluator.cc ../src/CGAL_Nef_polyhedron.cc ../src/cgalutils.cc ../src/CGALEvaluator.cc @@ -474,25 +494,15 @@ set(COMMON_SOURCES ../src/traverser.cc ../src/PolySetEvaluator.cc ../src/PolySetCache.cc + ../src/PlatformUtils.cc + ../src/${PLATFORMUTILS_SOURCE} + ../src/PlatformUtils.cc ../src/Tree.cc ../src/lodepng.cpp) # # Offscreen OpenGL context source code # -if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - message(STATUS "Offscreen OpenGL Context - using Apple CGL") - set(OFFSCREEN_CTX_SOURCE "OffscreenContextCGL.mm" CACHE TYPE STRING) - set(OFFSCREEN_IMGUTILS_SOURCE "imageutils-macosx.cc" CACHE TYPE STRING) -elseif(UNIX) - message(STATUS "Offscreen OpenGL Context - using Unix GLX") - set(OFFSCREEN_CTX_SOURCE "OffscreenContextGLX.cc" CACHE TYPE STRING) - set(OFFSCREEN_IMGUTILS_SOURCE "imageutils-lodepng.cc" CACHE TYPE STRING) -elseif(WIN32) - message(STATUS "Offscreen OpenGL Context - using Microsoft WGL") - set(OFFSCREEN_CTX_SOURCE "OffscreenContextWGL.cc" CACHE TYPE STRING) - set(OFFSCREEN_IMGUTILS_SOURCE "imageutils-lodepng.cc" CACHE TYPE STRING) -endif() set(OFFSCREEN_SOURCES ../src/GLView.cc @@ -501,7 +511,13 @@ set(OFFSCREEN_SOURCES ../src/${OFFSCREEN_IMGUTILS_SOURCE} ../src/imageutils.cc ../src/fbo.cc - ../src/system-gl.cc) + ../src/system-gl.cc + ../src/export_png.cc + ../src/CGALRenderer.cc + ../src/ThrownTogetherRenderer.cc + ../src/renderer.cc + ../src/render.cc + ../src/OpenCSGRenderer.cc) add_library(tests-core STATIC ${CORE_SOURCES}) target_link_libraries(tests-core ${OPENGL_LIBRARIES}) @@ -518,14 +534,14 @@ set(TESTS-CGAL-LIBRARIES ${CGAL_LIBRARY} ${CGAL_3RD_PARTY_LIBRARIES} ${GMP_LIBRA add_library(tests-nocgal STATIC ${NOCGAL_SOURCES}) target_link_libraries(tests-nocgal tests-common) add_library(tests-offscreen STATIC ${OFFSCREEN_SOURCES}) -# set_target_properties(tests-offscreen PROPERTIES COMPILE_FLAGS "-DENABLE_OPENCSG -DENABLE_CGAL ${CGAL_CXX_FLAGS_INIT}") +set_target_properties(tests-offscreen PROPERTIES COMPILE_FLAGS "-DENABLE_OPENCSG -DENABLE_CGAL ${CGAL_CXX_FLAGS_INIT}") set(TESTS-NOCGAL-LIBRARIES ${TESTS-CORE-LIBRARIES}) # # modulecachetest # add_executable(modulecachetest modulecachetest.cc) -target_link_libraries(modulecachetest tests-nocgal ${TESTS-NOCGAL-LIBRARIES}) +target_link_libraries(modulecachetest tests-nocgal ${TESTS-NOCGAL-LIBRARIES} ${Boost_LIBRARIES}) # # csgtexttest @@ -540,28 +556,41 @@ 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} ${GLEW_LIBRARY} ${COCOA_LIBRARY}) +# +# openscad no-qt +# +add_executable(openscad ../src/openscad.cc) +set_target_properties(openscad PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing -DEIGEN_DONT_ALIGN -DENABLE_CGAL -DENABLE_OPENCSG ${CGAL_CXX_FLAGS_INIT}") +target_link_libraries(openscad tests-offscreen tests-cgal tests-nocgal ${TESTS-CORE-LIBRARIES} ${TESTS-CGAL-LIBRARIES} ${GLEW_LIBRARY} ${Boost_LIBRARIES} ${OPENCSG_LIBRARY} ${COCOA_LIBRARY} ) + # # GUI binary tests # -if(APPLE) - set(GUI_BINPATH "${CMAKE_CURRENT_SOURCE_DIR}/../OpenSCAD.app/Contents/MacOS/OpenSCAD") -elseif (MINGW_CROSS_ENV_DIR) - set(GUI_BINPATH "${CMAKE_CURRENT_SOURCE_DIR}/../mingw32/release/openscad.exe") -elseif(WIN32) - set(GUI_BINPATH "${CMAKE_CURRENT_SOURCE_DIR}/../Release/openscad.exe") -else() - set(GUI_BINPATH "${CMAKE_CURRENT_SOURCE_DIR}/../openscad") -endif() +#if(APPLE) +# set(OPENSCAD_BINPATH "${CMAKE_CURRENT_SOURCE_DIR}/../OpenSCAD.app/Contents/MacOS/OpenSCAD") +#elseif (MINGW_CROSS_ENV_DIR) +# set(OPENSCAD_BINPATH "${CMAKE_CURRENT_SOURCE_DIR}/../mingw32/release/openscad.exe") +#elseif(WIN32) +# set(OPENSCAD_BINPATH "${CMAKE_CURRENT_SOURCE_DIR}/../Release/openscad.exe") +#else() +# set(OPENSCAD_BINPATH "${CMAKE_CURRENT_SOURCE_DIR}/../openscad") +#endif() -if(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/openscad") - set(GUI_BINPATH "${CMAKE_CURRENT_BINARY_DIR}/openscad") -endif() +#if(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/openscad") +# set(OPENSCAD_BINPATH "${CMAKE_CURRENT_BINARY_DIR}/openscad") +#endif() -if(EXISTS "${GUI_BINPATH}") - message(STATUS "Found OpenSCAD GUI binary: ${GUI_BINPATH}") +#if(EXISTS "${OPENSCAD_BINPATH}") +# message(STATUS "Found OpenSCAD binary: ${OPENSCAD_BINPATH}") +#else() +# message(STATUS "Couldn't find the OpenSCAD binary: ${OPENSCAD_BINPATH}") +# message(FATAL_ERROR "Please build the OpenSCAD binary and place it here: ${OPENSCAD_BINPATH}" ) +#endif() + +if(WIN32) + set(OPENSCAD_BINPATH "${CMAKE_CURRENT_BINARY_DIR}/openscad.exe") else() - message(STATUS "Couldn't find the OpenSCAD GUI binary: ${GUI_BINPATH}") - message(FATAL_ERROR "Please build the OpenSCAD GUI binary and place it here: ${GUI_BINPATH}" ) + set(OPENSCAD_BINPATH "${CMAKE_CURRENT_BINARY_DIR}/openscad") endif() # @@ -828,7 +857,7 @@ string(REPLACE __cmake_current_source_dir__ ${CMAKE_CURRENT_SOURCE_DIR} TMP ${TM string(REPLACE __python__ ${PYTHON_EXECUTABLE} TMP ${TMP}) string(REPLACE __header__ "Generated by cmake from ${CMAKE_CURRENT_SOURCE_DIR}/CTestCustom.template" TMP ${TMP}) string(REPLACE __cmake_system_name__ ${CMAKE_SYSTEM_NAME} TMP ${TMP}) -string(REPLACE __gui_binpath__ ${GUI_BINPATH} TMP ${TMP}) +string(REPLACE __openscad_binpath__ ${OPENSCAD_BINPATH} TMP ${TMP}) if (MINGW_CROSS_ENV_DIR) string(REPLACE __wine__ wine TMP ${TMP}) @@ -841,9 +870,9 @@ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake ${TMP}) # Add tests -add_cmdline_test(echotest EXE ${CMAKE_SOURCE_DIR}/echotest SUFFIX txt ARGS ${GUI_BINPATH} FILES ${ECHO_FILES}) -add_cmdline_test(dumptest EXE ${CMAKE_SOURCE_DIR}/dumptest SUFFIX csg ARGS ${GUI_BINPATH} FILES ${DUMPTEST_FILES}) -add_cmdline_test(moduledumptest EXE ${GUI_BINPATH} ARGS -o SUFFIX ast FILES +add_cmdline_test(echotest EXE ${CMAKE_SOURCE_DIR}/echotest SUFFIX txt ARGS ${OPENSCAD_BINPATH} FILES ${ECHO_FILES}) +add_cmdline_test(dumptest EXE ${CMAKE_SOURCE_DIR}/dumptest SUFFIX csg ARGS ${OPENSCAD_BINPATH} FILES ${DUMPTEST_FILES}) +add_cmdline_test(moduledumptest EXE ${OPENSCAD_BINPATH} ARGS -o SUFFIX ast FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/allmodules.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/allfunctions.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/allexpressions.scad) @@ -851,67 +880,67 @@ add_cmdline_test(csgtexttest SUFFIX txt FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/allexpressions.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/allfunctions.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/allmodules.scad) -add_cmdline_test(csgtermtest EXE ${GUI_BINPATH} ARGS -o SUFFIX term FILES +add_cmdline_test(csgtermtest EXE ${OPENSCAD_BINPATH} ARGS -o SUFFIX term FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/allexpressions.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/allfunctions.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/allmodules.scad) -add_cmdline_test(cgalpngtest EXE ${GUI_BINPATH} ARGS --render -o SUFFIX png FILES ${CGALPNGTEST_FILES}) -add_cmdline_test(opencsgtest EXE ${GUI_BINPATH} ARGS -o SUFFIX png FILES ${OPENCSGTEST_FILES}) -add_cmdline_test(throwntogethertest EXE ${GUI_BINPATH} ARGS --preview=throwntogether -o SUFFIX png FILES ${THROWNTOGETHERTEST_FILES}) +add_cmdline_test(cgalpngtest EXE ${OPENSCAD_BINPATH} ARGS --render -o SUFFIX png FILES ${CGALPNGTEST_FILES}) +add_cmdline_test(opencsgtest EXE ${OPENSCAD_BINPATH} ARGS -o SUFFIX png FILES ${OPENCSGTEST_FILES}) +add_cmdline_test(throwntogethertest EXE ${OPENSCAD_BINPATH} ARGS --preview=throwntogether -o SUFFIX png FILES ${THROWNTOGETHERTEST_FILES}) # FIXME: We don't actually need to compare the output of cgalstlsanitytest # with anything. It's self-contained and returns != 0 on error -add_cmdline_test(cgalstlsanitytest EXE ${CMAKE_SOURCE_DIR}/cgalstlsanitytest SUFFIX txt ARGS ${GUI_BINPATH} FILES ${CGALSTLSANITYTEST_FILES}) +add_cmdline_test(cgalstlsanitytest EXE ${CMAKE_SOURCE_DIR}/cgalstlsanitytest SUFFIX txt ARGS ${OPENSCAD_BINPATH} FILES ${CGALSTLSANITYTEST_FILES}) # Tests using the actual OpenSCAD binary # non-ASCII filenames -add_cmdline_test(openscad-nonascii EXE ${GUI_BINPATH} ARGS -o +add_cmdline_test(openscad-nonascii EXE ${OPENSCAD_BINPATH} ARGS -o SUFFIX csg FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/sfære.scad) # Image output -add_cmdline_test(openscad-imgsize EXE ${GUI_BINPATH} +add_cmdline_test(openscad-imgsize EXE ${OPENSCAD_BINPATH} ARGS --imgsize 100,100 -o SUFFIX png FILES ${CMAKE_SOURCE_DIR}/../examples/example001.scad) -add_cmdline_test(openscad-imgstretch EXE ${GUI_BINPATH} +add_cmdline_test(openscad-imgstretch EXE ${OPENSCAD_BINPATH} ARGS --imgsize 500,100 -o SUFFIX png FILES ${CMAKE_SOURCE_DIR}/../examples/example001.scad) -add_cmdline_test(openscad-imgstretch2 EXE ${GUI_BINPATH} +add_cmdline_test(openscad-imgstretch2 EXE ${OPENSCAD_BINPATH} ARGS --imgsize 100,500 -o SUFFIX png FILES ${CMAKE_SOURCE_DIR}/../examples/example001.scad) -add_cmdline_test(openscad-camdist EXE ${GUI_BINPATH} +add_cmdline_test(openscad-camdist EXE ${OPENSCAD_BINPATH} ARGS --imgsize=500,500 --camera=0,0,0,90,0,90,300 examples/example001.scad -o SUFFIX png FILES ${CMAKE_SOURCE_DIR}/../examples/example001.scad) -add_cmdline_test(openscad-camrot EXE ${GUI_BINPATH} +add_cmdline_test(openscad-camrot EXE ${OPENSCAD_BINPATH} ARGS --imgsize=500,500 --camera=0,0,0,440,337.5,315,300 examples/example001.scad -o SUFFIX png FILES ${CMAKE_SOURCE_DIR}/../examples/example001.scad) -add_cmdline_test(openscad-camtrans EXE ${GUI_BINPATH} +add_cmdline_test(openscad-camtrans EXE ${OPENSCAD_BINPATH} ARGS --imgsize=500,500 --camera=100,-20,-10,90,0,90,300 examples/example001.scad -o SUFFIX png FILES ${CMAKE_SOURCE_DIR}/../examples/example001.scad) -add_cmdline_test(openscad-camortho EXE ${GUI_BINPATH} +add_cmdline_test(openscad-camortho EXE ${OPENSCAD_BINPATH} ARGS --imgsize=500,500 --camera=100,-20,-10,90,0,90,300 examples/example001.scad --projection=o -o SUFFIX png FILES ${CMAKE_SOURCE_DIR}/../examples/example001.scad) -add_cmdline_test(openscad-cameye EXE ${GUI_BINPATH} +add_cmdline_test(openscad-cameye EXE ${OPENSCAD_BINPATH} ARGS --imgsize=500,500 --camera=60,40,30,0,0,0 examples/example001.scad -o SUFFIX png FILES ${CMAKE_SOURCE_DIR}/../examples/example001.scad) -add_cmdline_test(openscad-cameye2 EXE ${GUI_BINPATH} +add_cmdline_test(openscad-cameye2 EXE ${OPENSCAD_BINPATH} ARGS --imgsize=500,500 --camera=160,140,130,0,0,0 examples/example001.scad -o SUFFIX png FILES ${CMAKE_SOURCE_DIR}/../examples/example001.scad) -add_cmdline_test(openscad-cameyeortho EXE ${GUI_BINPATH} +add_cmdline_test(openscad-cameyeortho EXE ${OPENSCAD_BINPATH} ARGS --imgsize=500,500 --camera=160,140,130,0,0,0 examples/example001.scad --projection=o -o SUFFIX png FILES ${CMAKE_SOURCE_DIR}/../examples/example001.scad) -add_cmdline_test(openscad-camcenter EXE ${GUI_BINPATH} +add_cmdline_test(openscad-camcenter EXE ${OPENSCAD_BINPATH} ARGS --imgsize=500,500 --camera=60,40,30,20,10,30 -o SUFFIX png FILES ${CMAKE_SOURCE_DIR}/../examples/example001.scad) diff --git a/tests/CTestCustom.template b/tests/CTestCustom.template index b8d04ce8..1c930dd5 100644 --- a/tests/CTestCustom.template +++ b/tests/CTestCustom.template @@ -58,8 +58,8 @@ endif() # Part 1. Pretty Printing -message("running '__gui_binpath__ --info' to generate sysinfo.txt") -execute_process(COMMAND __wine__ __gui_binpath__ --info OUTPUT_FILE sysinfo.txt) +message("running '__openscad_binpath__ --info' to generate sysinfo.txt") +execute_process(COMMAND __wine__ __openscad_binpath__ --info OUTPUT_FILE sysinfo.txt) set(CTEST_CUSTOM_POST_TEST ${CTEST_CUSTOM_POST_TEST} "__cmake_current_binary_dir__/test_pretty_print") if ( ${debug_openscad_template} )