summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/func.cc24
-rw-r--r--src/module.cc5
-rw-r--r--src/module.h6
-rw-r--r--src/openscad.cc30
-rw-r--r--src/parsersettings.cc9
-rw-r--r--src/parsersettings.h2
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,
contact: Jan Huwald // Impressum