bugfix: Correctly handle else scopes, handle overrides inside assign scopes

master
Marius Kintel 2014-11-25 00:45:00 -05:00
parent d195d05008
commit 23c9dee265
15 changed files with 30 additions and 32 deletions

View File

@ -62,7 +62,7 @@ AbstractNode *CgaladvModule::instantiate(const Context *ctx, const ModuleInstant
Context c(ctx);
c.setVariables(args, evalctx);
evalctx->applyScope();
inst->scope.apply(*evalctx);
Value convexity, path, subdiv_type, level;

View File

@ -218,7 +218,7 @@ AbstractNode *ColorModule::instantiate(const Context *ctx, const ModuleInstantia
Context c(ctx);
c.setVariables(args, evalctx);
evalctx->applyScope();
inst->scope.apply(*evalctx);
Value v = c.lookup_variable("c");
if (v.type() == Value::VECTOR) {

View File

@ -167,10 +167,6 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
{
AbstractNode *node = NULL;
if (this->type != FOR && this->type != INT_FOR) {
evalctx->applyScope();
}
switch (this->type) {
case CHILD: {
printDeprecation("DEPRECATED: child() will be removed in future releases. Use children() instead.");
@ -285,11 +281,15 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
case ASSIGN: {
node = new AbstractNode(inst);
// We create a new context to avoid parameters from influencing each other
// -> parallel evaluation. This is to be backwards compatible.
Context c(evalctx);
for (size_t i = 0; i < evalctx->numArgs(); i++) {
if (!evalctx->getArgName(i).empty())
c.set_variable(evalctx->getArgName(i), evalctx->getArgValue(i));
}
// Let any local variables override the parameters
inst->scope.apply(c);
std::vector<AbstractNode *> instantiatednodes = inst->instantiateChildren(&c);
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
}
@ -309,10 +309,12 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
node = new AbstractNode(inst);
const IfElseModuleInstantiation *ifelse = dynamic_cast<const IfElseModuleInstantiation*>(inst);
if (evalctx->numArgs() > 0 && evalctx->getArgValue(0).toBool()) {
inst->scope.apply(*evalctx);
std::vector<AbstractNode *> instantiatednodes = ifelse->instantiateChildren(evalctx);
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
}
else {
ifelse->else_scope.apply(*evalctx);
std::vector<AbstractNode *> instantiatednodes = ifelse->instantiateElseChildren(evalctx);
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
}

View File

@ -43,7 +43,7 @@ public:
AbstractNode *CsgModule::instantiate(const Context*, const ModuleInstantiation *inst, EvalContext *evalctx) const
{
evalctx->applyScope();
inst->scope.apply(*evalctx);
CsgNode *node = new CsgNode(inst, type);
std::vector<AbstractNode *> instantiatednodes = inst->instantiateChildren(evalctx);
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());

View File

@ -37,22 +37,6 @@ ModuleInstantiation *EvalContext::getChild(size_t i) const
return this->scope ? this->scope->children[i] : NULL;
}
/*!
When instantiating a module which can take a scope as parameter (i.e. non-leaf nodes),
use this method to apply the local scope definitions to the evaluation context.
This will enable variables defined in local blocks.
NB! for loops are special as the local block may depend on variables evaluated by the
for loop parameters. The for loop code will handle this specially.
*/
void EvalContext::applyScope()
{
if (this->scope) {
BOOST_FOREACH(const Assignment &ass, this->scope->assignments) {
this->set_variable(ass.first, ass.second->evaluate(this));
}
}
}
#ifdef DEBUG
std::string EvalContext::dump(const AbstractModule *mod, const ModuleInstantiation *inst)
{

View File

@ -22,8 +22,6 @@ public:
size_t numChildren() const;
ModuleInstantiation *getChild(size_t i) const;
void applyScope();
#ifdef DEBUG
virtual std::string dump(const class AbstractModule *mod, const ModuleInstantiation *inst);
#endif

View File

@ -58,7 +58,7 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI
Context c(ctx);
c.setVariables(args, evalctx);
evalctx->applyScope();
inst->scope.apply(*evalctx);
node->fn = c.lookup_variable("$fn").toDouble();
node->fs = c.lookup_variable("$fs").toDouble();

View File

@ -54,3 +54,16 @@ std::vector<AbstractNode*> LocalScope::instantiateChildren(const Context *evalct
return childnodes;
}
/*!
When instantiating a module which can take a scope as parameter (i.e. non-leaf nodes),
use this method to apply the local scope definitions to the evaluation context.
This will enable variables defined in local blocks.
NB! for loops are special as the local block may depend on variables evaluated by the
for loop parameters. The for loop code will handle this specially.
*/
void LocalScope::apply(Context &ctx) const
{
BOOST_FOREACH(const Assignment &ass, this->assignments) {
ctx.set_variable(ass.first, ass.second->evaluate(&ctx));
}
}

View File

@ -13,6 +13,7 @@ public:
std::string dump(const std::string &indent) const;
std::vector<class AbstractNode*> instantiateChildren(const class Context *evalctx) const;
void addChild(ModuleInstantiation *ch);
void apply(Context &ctx) const;
AssignmentList assignments;
ModuleInstantiationList children;

View File

@ -195,7 +195,7 @@ AbstractNode *Module::instantiate(const Context *ctx, const ModuleInstantiation
// At this point we know that nobody will modify the dependencies of the local scope
// passed to this instance, so we can populate the context
evalctx->applyScope();
inst->scope.apply(*evalctx);
ModuleContext c(ctx, evalctx);
// set $children first since we might have variables depending on it

View File

@ -58,7 +58,7 @@ AbstractNode *OffsetModule::instantiate(const Context *ctx, const ModuleInstanti
Context c(ctx);
c.setVariables(args, evalctx);
evalctx->applyScope();
inst->scope.apply(*evalctx);
node->fn = c.lookup_variable("$fn").toDouble();
node->fs = c.lookup_variable("$fs").toDouble();

View File

@ -53,7 +53,7 @@ AbstractNode *ProjectionModule::instantiate(const Context *ctx, const ModuleInst
Context c(ctx);
c.setVariables(args, evalctx);
evalctx->applyScope();
inst->scope.apply(*evalctx);
Value convexity = c.lookup_variable("convexity", true);
Value cut = c.lookup_variable("cut", true);

View File

@ -50,7 +50,7 @@ AbstractNode *RenderModule::instantiate(const Context *ctx, const ModuleInstanti
Context c(ctx);
c.setVariables(args, evalctx);
evalctx->applyScope();
inst->scope.apply(*evalctx);
Value v = c.lookup_variable("convexity");
if (v.type() == Value::NUMBER)

View File

@ -56,7 +56,7 @@ AbstractNode *RotateExtrudeModule::instantiate(const Context *ctx, const ModuleI
Context c(ctx);
c.setVariables(args, evalctx);
evalctx->applyScope();
inst->scope.apply(*evalctx);
node->fn = c.lookup_variable("$fn").toDouble();
node->fs = c.lookup_variable("$fs").toDouble();

View File

@ -83,7 +83,7 @@ AbstractNode *TransformModule::instantiate(const Context *ctx, const ModuleInsta
Context c(ctx);
c.setVariables(args, evalctx);
evalctx->applyScope();
inst->scope.apply(*evalctx);
if (this->type == SCALE)
{