mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-14 21:57:18 +08:00
Custom macro variables: two new keywords: 'exists' and 'default'
* 'default(var_name,value)' check if the variable exist and affect it the value if not. The variable can be boolean 'true' 'false', int '0' '12', double '1.0' '42.24' or string '"a string"'. * 'exists(var_name)' return true if present. Note that it create a dummy boolean variable. Note that if you're using the variable in a formula, it may crash even if guarded by a {if} as everything is interpreted (no lazy check). So be careful to add a 'default' so it get the right type and can the formula be interpreted (unless you just print it). Using 'default' doesn't change the return value of 'exists'.
This commit is contained in:
parent
8a0e9adcd4
commit
f1f60cd468
@ -305,6 +305,7 @@ public:
|
|||||||
enum FlagsConfigOption : uint32_t {
|
enum FlagsConfigOption : uint32_t {
|
||||||
FCO_PHONY = 1,
|
FCO_PHONY = 1,
|
||||||
FCO_EXTRUDER_ARRAY = 1 << 1,
|
FCO_EXTRUDER_ARRAY = 1 << 1,
|
||||||
|
FCO_PLACEHOLDER_TEMP = 1 << 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
ConfigOption() : flags(uint32_t(0)) {}
|
ConfigOption() : flags(uint32_t(0)) {}
|
||||||
|
@ -652,6 +652,8 @@ namespace client
|
|||||||
bool just_boolean_expression = false;
|
bool just_boolean_expression = false;
|
||||||
std::string error_message;
|
std::string error_message;
|
||||||
|
|
||||||
|
static std::map<t_config_option_key, std::unique_ptr<ConfigOption>> checked_vars;
|
||||||
|
|
||||||
// Table to translate symbol tag to a human readable error message.
|
// Table to translate symbol tag to a human readable error message.
|
||||||
static std::map<std::string, std::string> tag_to_error_message;
|
static std::map<std::string, std::string> tag_to_error_message;
|
||||||
|
|
||||||
@ -666,6 +668,11 @@ namespace client
|
|||||||
opt = config->option(opt_key);
|
opt = config->option(opt_key);
|
||||||
if (opt == nullptr && external_config != nullptr)
|
if (opt == nullptr && external_config != nullptr)
|
||||||
opt = external_config->option(opt_key);
|
opt = external_config->option(opt_key);
|
||||||
|
if (opt == nullptr) {
|
||||||
|
auto it = MyContext::checked_vars.find(opt_key);
|
||||||
|
if (it != MyContext::checked_vars.end())
|
||||||
|
opt = it->second.get();
|
||||||
|
}
|
||||||
return opt;
|
return opt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -825,13 +832,53 @@ namespace client
|
|||||||
boost::iterator_range<Iterator> &opt_key,
|
boost::iterator_range<Iterator> &opt_key,
|
||||||
OptWithPos<Iterator> &output)
|
OptWithPos<Iterator> &output)
|
||||||
{
|
{
|
||||||
const ConfigOption *opt = ctx->resolve_symbol(std::string(opt_key.begin(), opt_key.end()));
|
std::string str_key = std::string(opt_key.begin(), opt_key.end());
|
||||||
|
const ConfigOption *opt = ctx->resolve_symbol(str_key);
|
||||||
if (opt == nullptr)
|
if (opt == nullptr)
|
||||||
ctx->throw_exception("Not a variable name", opt_key);
|
ctx->throw_exception("Not a variable name", opt_key);
|
||||||
output.opt = opt;
|
output.opt = opt;
|
||||||
output.it_range = opt_key;
|
output.it_range = opt_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// function to check if a var exist & add a dummy var if not
|
||||||
|
template <typename Iterator>
|
||||||
|
static void check_variable(
|
||||||
|
const MyContext* ctx,
|
||||||
|
boost::iterator_range<Iterator>& opt_key,
|
||||||
|
Iterator& end_pos,
|
||||||
|
expr<Iterator>& out,
|
||||||
|
ConfigOption* default_val = nullptr)
|
||||||
|
{
|
||||||
|
t_config_option_key key = std::string(opt_key.begin(), opt_key.end());
|
||||||
|
const ConfigOption* opt = nullptr;
|
||||||
|
if (ctx->config_override != nullptr)
|
||||||
|
opt = ctx->config_override->option(key);
|
||||||
|
if (opt == nullptr)
|
||||||
|
opt = ctx->config->option(key);
|
||||||
|
if (opt == nullptr && ctx->external_config != nullptr)
|
||||||
|
opt = ctx->external_config->option(key);
|
||||||
|
if (opt == nullptr) {
|
||||||
|
std::unique_ptr<ConfigOption> ppt;
|
||||||
|
if(default_val == nullptr)
|
||||||
|
ppt = std::unique_ptr<ConfigOption>(new ConfigOptionBool(false));
|
||||||
|
else
|
||||||
|
ppt = std::unique_ptr<ConfigOption>(default_val);
|
||||||
|
// set flag to say "it's a var that isn't here, please ignore it"
|
||||||
|
ppt->flags |= ConfigOption::FCO_PLACEHOLDER_TEMP;
|
||||||
|
if (MyContext::checked_vars.find(key) != MyContext::checked_vars.end()) {
|
||||||
|
if (default_val != nullptr) {
|
||||||
|
// erase previous value
|
||||||
|
MyContext::checked_vars[key] = std::move(ppt);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// put the var
|
||||||
|
MyContext::checked_vars.emplace(std::move(key), std::move(ppt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//return
|
||||||
|
out = expr<Iterator>(opt != nullptr, out.it_range.begin(), end_pos);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Iterator>
|
template <typename Iterator>
|
||||||
static void scalar_variable_reference(
|
static void scalar_variable_reference(
|
||||||
const MyContext *ctx,
|
const MyContext *ctx,
|
||||||
@ -944,8 +991,11 @@ namespace client
|
|||||||
Iterator it_end,
|
Iterator it_end,
|
||||||
expr<Iterator> &output)
|
expr<Iterator> &output)
|
||||||
{
|
{
|
||||||
if (opt.opt->is_scalar())
|
if (opt.opt->is_scalar()) {
|
||||||
|
if (0 != (opt.opt->flags & ConfigOption::FCO_PLACEHOLDER_TEMP)) // fake var, from checked_vars
|
||||||
|
return scalar_variable_reference(ctx, opt, output);
|
||||||
ctx->throw_exception("Referencing a scalar variable when vector is expected", opt.it_range);
|
ctx->throw_exception("Referencing a scalar variable when vector is expected", opt.it_range);
|
||||||
|
}
|
||||||
const ConfigOptionVectorBase *vec = static_cast<const ConfigOptionVectorBase*>(opt.opt);
|
const ConfigOptionVectorBase *vec = static_cast<const ConfigOptionVectorBase*>(opt.opt);
|
||||||
if (vec->empty())
|
if (vec->empty())
|
||||||
ctx->throw_exception("Indexing an empty vector variable", opt.it_range);
|
ctx->throw_exception("Indexing an empty vector variable", opt.it_range);
|
||||||
@ -1064,6 +1114,7 @@ namespace client
|
|||||||
{ "variable_reference", "Expecting a variable reference."},
|
{ "variable_reference", "Expecting a variable reference."},
|
||||||
{ "regular_expression", "Expecting a regular expression."}
|
{ "regular_expression", "Expecting a regular expression."}
|
||||||
};
|
};
|
||||||
|
std::map<t_config_option_key, std::unique_ptr<ConfigOption>> MyContext::checked_vars = {};
|
||||||
|
|
||||||
// For debugging the boost::spirit parsers. Print out the string enclosed in it_range.
|
// For debugging the boost::spirit parsers. Print out the string enclosed in it_range.
|
||||||
template<typename Iterator>
|
template<typename Iterator>
|
||||||
@ -1324,6 +1375,15 @@ namespace client
|
|||||||
{ out = value.unary_not(out.it_range.begin()); }
|
{ out = value.unary_not(out.it_range.begin()); }
|
||||||
static void to_int(expr<Iterator> &value, expr<Iterator> &out)
|
static void to_int(expr<Iterator> &value, expr<Iterator> &out)
|
||||||
{ out = value.unary_integer(out.it_range.begin()); }
|
{ out = value.unary_integer(out.it_range.begin()); }
|
||||||
|
//function for default keyword
|
||||||
|
static void default_bool_(bool &value, const MyContext* ctx, boost::iterator_range<Iterator>& opt_key, Iterator& end_pos, expr<Iterator>& out)
|
||||||
|
{ MyContext::check_variable<Iterator>(ctx, opt_key, end_pos, out, new ConfigOptionBool(value)); }
|
||||||
|
static void default_int_(int &value, const MyContext* ctx, boost::iterator_range<Iterator>& opt_key, Iterator& end_pos, expr<Iterator>& out)
|
||||||
|
{ MyContext::check_variable<Iterator>(ctx, opt_key, end_pos, out, new ConfigOptionInt(value)); }
|
||||||
|
static void default_double_(double &value, const MyContext* ctx, boost::iterator_range<Iterator>& opt_key, Iterator& end_pos, expr<Iterator>& out)
|
||||||
|
{ MyContext::check_variable<Iterator>(ctx, opt_key, end_pos, out, new ConfigOptionFloat(value)); }
|
||||||
|
static void default_string_(boost::iterator_range<Iterator>& it_range, const MyContext* ctx, boost::iterator_range<Iterator>& opt_key, Iterator& end_pos, expr<Iterator>& out)
|
||||||
|
{ MyContext::check_variable<Iterator>(ctx, opt_key, end_pos, out, new ConfigOptionString(std::string(it_range.begin() + 1, it_range.end() - 1))); }
|
||||||
};
|
};
|
||||||
unary_expression = iter_pos[px::bind(&FactorActions::set_start_pos, _1, _val)] >> (
|
unary_expression = iter_pos[px::bind(&FactorActions::set_start_pos, _1, _val)] >> (
|
||||||
scalar_variable_reference(_r1) [ _val = _1 ]
|
scalar_variable_reference(_r1) [ _val = _1 ]
|
||||||
@ -1338,6 +1398,15 @@ namespace client
|
|||||||
| (kw["random"] > '(' > conditional_expression(_r1) [_val = _1] > ',' > conditional_expression(_r1) > ')')
|
| (kw["random"] > '(' > conditional_expression(_r1) [_val = _1] > ',' > conditional_expression(_r1) > ')')
|
||||||
[ px::bind(&MyContext::random<Iterator>, _r1, _val, _2) ]
|
[ px::bind(&MyContext::random<Iterator>, _r1, _val, _2) ]
|
||||||
| (kw["int"] > '(' > unary_expression(_r1) > ')') [ px::bind(&FactorActions::to_int, _1, _val) ]
|
| (kw["int"] > '(' > unary_expression(_r1) > ')') [ px::bind(&FactorActions::to_int, _1, _val) ]
|
||||||
|
| (kw["exists"] > '(' > identifier > ')' > iter_pos) [ px::bind(&MyContext::check_variable<Iterator>, _r1, _1, _2, _val, nullptr) ]
|
||||||
|
| (kw["default"] > '(' > identifier > ',' > strict_double > ')' > iter_pos)
|
||||||
|
[px::bind(&FactorActions::default_double_, _2, _r1, _1, _3, _val)]
|
||||||
|
| (kw["default"] > '(' > identifier > ',' > int_ > ')' > iter_pos)
|
||||||
|
[px::bind(&FactorActions::default_int_, _2, _r1, _1, _3, _val)]
|
||||||
|
| (kw["default"] > '(' > identifier > ',' > kw[bool_] > ')' > iter_pos)
|
||||||
|
[ px::bind(&FactorActions::default_bool_, _2, _r1, _1, _3, _val) ]
|
||||||
|
| (kw["default"] > '(' > identifier > ',' > raw[lexeme['"' > *((utf8char - char_('\\') - char_('"')) | ('\\' > char_)) > '"']] > ')' > iter_pos)
|
||||||
|
[px::bind(&FactorActions::default_string_, _2, _r1, _1, _3, _val)]
|
||||||
| (strict_double > iter_pos) [ px::bind(&FactorActions::double_, _1, _2, _val) ]
|
| (strict_double > iter_pos) [ px::bind(&FactorActions::double_, _1, _2, _val) ]
|
||||||
| (int_ > iter_pos) [ px::bind(&FactorActions::int_, _1, _2, _val) ]
|
| (int_ > iter_pos) [ px::bind(&FactorActions::int_, _1, _2, _val) ]
|
||||||
| (kw[bool_] > iter_pos) [ px::bind(&FactorActions::bool_, _1, _2, _val) ]
|
| (kw[bool_] > iter_pos) [ px::bind(&FactorActions::bool_, _1, _2, _val) ]
|
||||||
@ -1376,7 +1445,9 @@ namespace client
|
|||||||
("random")
|
("random")
|
||||||
("not")
|
("not")
|
||||||
("or")
|
("or")
|
||||||
("true");
|
("true")
|
||||||
|
("exists")
|
||||||
|
("default");
|
||||||
|
|
||||||
if (0) {
|
if (0) {
|
||||||
debug(start);
|
debug(start);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user