diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/func.cc | 24 | ||||
-rw-r--r-- | src/module.cc | 5 | ||||
-rw-r--r-- | src/module.h | 6 | ||||
-rw-r--r-- | src/openscad.cc | 30 | ||||
-rw-r--r-- | src/parsersettings.cc | 9 | ||||
-rw-r--r-- | src/parsersettings.h | 2 |
6 files changed, 62 insertions, 14 deletions
diff --git a/src/func.cc b/src/func.cc index 20f487a..865a2b4 100644 --- a/src/func.cc +++ b/src/func.cc @@ -528,6 +528,29 @@ Value builtin_version_num(const Context *ctx, const EvalContext *evalctx) return Value(y * 10000 + m * 100 + d); } +Value builtin_parent_module(const Context *, const EvalContext *evalctx) +{ + int n; + double d; + int s = Module::stack_size(); + if (evalctx->numArgs() == 0) + d=1; // parent module + else if (evalctx->numArgs() == 1 && evalctx->getArgValue(0).type() == Value::NUMBER) + evalctx->getArgValue(0).getDouble(d); + else + return Value(); + n=trunc(d); + if (n < 0) { + PRINTB("WARNING: Negative parent module index (%d) not allowed", n); + return Value(); + } + if (n >= s) { + PRINTB("WARNING: Parent module index (%d) greater than the number of modules on the stack", n); + return Value(); + } + return Value(Module::stack_element(s - 1 - n)); +} + void register_builtin_functions() { Builtins::init("abs", new BuiltinFunction(&builtin_abs)); @@ -556,4 +579,5 @@ 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("parent_module", new BuiltinFunction(&builtin_parent_module)); } diff --git a/src/module.cc b/src/module.cc index f66c8ef..1f4059e 100644 --- a/src/module.cc +++ b/src/module.cc @@ -153,6 +153,8 @@ std::vector<AbstractNode*> IfElseModuleInstantiation::instantiateElseChildren(co return this->else_scope.instantiateChildren(evalctx); } +std::deque<std::string> Module::module_stack; + Module::~Module() { } @@ -182,6 +184,8 @@ AbstractNode *Module::instantiate(const Context *ctx, const ModuleInstantiation ModuleContext c(ctx, evalctx); // set $children first since we might have variables depending on it c.set_variable("$children", Value(double(inst->scope.children.size()))); + module_stack.push_back(inst->name()); + c.set_variable("$parent_modules", Value(double(module_stack.size()))); c.initializeModule(*this); // FIXME: Set document path to the path of the module #if 0 && DEBUG @@ -191,6 +195,7 @@ AbstractNode *Module::instantiate(const Context *ctx, const ModuleInstantiation AbstractNode *node = new AbstractNode(inst); std::vector<AbstractNode *> instantiatednodes = this->scope.instantiateChildren(&c); node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); + module_stack.pop_back(); return node; } diff --git a/src/module.h b/src/module.h index b5c58af..8414706 100644 --- a/src/module.h +++ b/src/module.h @@ -4,6 +4,7 @@ #include <string> #include <vector> #include <list> +#include <deque> #include <boost/unordered_map.hpp> #include <boost/unordered_set.hpp> #include <time.h> @@ -73,10 +74,15 @@ public: virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx = NULL) const; virtual std::string dump(const std::string &indent, const std::string &name) const; + static const std::string& stack_element(int n) { return module_stack[n]; }; + static int stack_size() { return module_stack.size(); }; AssignmentList definition_arguments; LocalScope scope; + +private: + static std::deque<std::string> module_stack; }; // FIXME: A FileModule doesn't have definition arguments, so we shouldn't really diff --git a/src/openscad.cc b/src/openscad.cc index f4f4014..e5eb69f 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -190,9 +190,9 @@ Camera get_camera( po::variables_map vm ) return camera; } -int cmdline(const char *deps_output_file, const std::string &filename, Camera &camera, const char *output_file, const fs::path &original_path, Render::type renderer, char ** argv ) +int cmdline(const std::string &application_path, const char *deps_output_file, const std::string &filename, Camera &camera, const char *output_file, const fs::path &original_path, Render::type renderer, char ** argv ) { - parser_init(boosty::stringy(boost::filesystem::path( argv[0] ).parent_path())); + parser_init(application_path, false); Tree tree; #ifdef ENABLE_CGAL CGALEvaluator cgalevaluator(tree); @@ -454,7 +454,7 @@ bool QtUseGUI() return useGUI; } -int gui(vector<string> &inputFiles, const fs::path &original_path, int argc, char ** argv) +int gui(const std::string &application_path, vector<string> &inputFiles, const fs::path &original_path, int argc, char ** argv) { QApplication app(argc, argv, true); //useGUI); #ifdef Q_WS_MAC @@ -465,7 +465,7 @@ int gui(vector<string> &inputFiles, const fs::path &original_path, int argc, cha QCoreApplication::setOrganizationDomain("openscad.org"); QCoreApplication::setApplicationName("OpenSCAD"); QCoreApplication::setApplicationVersion(TOSTRING(OPENSCAD_VERSION)); - + QDir exdir(QApplication::instance()->applicationDirPath()); QString qexamplesdir; #ifdef Q_WS_MAC @@ -486,8 +486,7 @@ int gui(vector<string> &inputFiles, const fs::path &original_path, int argc, cha qexamplesdir = exdir.path(); } MainWindow::setExamplesDir(qexamplesdir); - - parser_init(QApplication::instance()->applicationDirPath().toLocal8Bit().constData()); + parser_init(application_path, true); #ifdef Q_WS_MAC installAppleEventHandlers(); @@ -520,7 +519,7 @@ int gui(vector<string> &inputFiles, const fs::path &original_path, int argc, cha } #else // OPENSCAD_QTGUI bool QtUseGUI() { return false; } -int gui(const vector<string> &inputFiles, const fs::path &original_path, int argc, char ** argv) +int gui(const std::string &application_path, const vector<string> &inputFiles, const fs::path &original_path, int argc, char ** argv) { fprintf(stderr,"Error: compiled without QT, but trying to run GUI\n"); return 1; @@ -641,12 +640,23 @@ int main(int argc, char **argv) NodeCache nodecache; NodeDumper dumper(nodecache); - if (output_file) { + bool cmdlinemode = false; + if (output_file) { // cmd-line mode + cmdlinemode = true; if (!inputFiles.size()) help(argv[0]); - rc = cmdline(deps_output_file, inputFiles[0], camera, output_file, original_path, renderer, argv); + } + const std::string application_path = +#ifdef OPENSCAD_QTGUI + QApplication::instance()->applicationDirPath().toLocal8Bit().constData(); +#else + boosty::stringy(boosty::absolute(boost::filesystem::path(argv[0]).parent_path())); +#endif + + if (cmdlinemode) { + rc = cmdline(application_path, deps_output_file, inputFiles[0], camera, output_file, original_path, renderer, argv); } else if (QtUseGUI()) { - rc = gui(inputFiles, original_path, argc, argv); + rc = gui(application_path, inputFiles, original_path, argc, argv); } else { fprintf(stderr, "Requested GUI mode but can't open display!\n"); diff --git a/src/parsersettings.cc b/src/parsersettings.cc index 63a7713..de1ff98 100644 --- a/src/parsersettings.cc +++ b/src/parsersettings.cc @@ -88,7 +88,7 @@ fs::path find_valid_path(const fs::path &sourcepath, return fs::path(); } -void parser_init(const std::string &applicationpath) +void parser_init(const std::string &applicationpath, bool isgui) { // Add paths from OPENSCADPATH before adding built-in paths const char *openscadpaths = getenv("OPENSCADPATH"); @@ -116,8 +116,11 @@ void parser_init(const std::string &applicationpath) fs::path libdir(applicationpath); fs::path tmpdir; #ifdef __APPLE__ - libdir /= "../Resources"; // Libraries can be bundled - if (!is_directory(libdir / "libraries")) libdir /= "../../.."; + // Libraries can be bundled on Mac. If not, fall back to development layout + if (isgui) { + libdir /= "../Resources"; + if (!is_directory(libdir / "libraries")) libdir /= "../../.."; + } #elif !defined(WIN32) if (is_directory(tmpdir = libdir / "../share/openscad/libraries")) { librarydir = boosty::stringy(tmpdir); diff --git a/src/parsersettings.h b/src/parsersettings.h index 52172b6..2aef85b 100644 --- a/src/parsersettings.h +++ b/src/parsersettings.h @@ -6,7 +6,7 @@ extern int parser_error_pos; -void parser_init(const std::string &applicationpath); +void parser_init(const std::string &applicationpath, bool isgui); void add_librarydir(const std::string &libdir); fs::path search_libs(const fs::path &localpath); fs::path find_valid_path(const fs::path &sourcepath, |