diff --git a/src/libslic3r/PlaceholderParser.cpp b/src/libslic3r/PlaceholderParser.cpp index 8d4a88b144..4ad00927a7 100644 --- a/src/libslic3r/PlaceholderParser.cpp +++ b/src/libslic3r/PlaceholderParser.cpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #ifdef _MSC_VER #include // provides **_environ #else @@ -26,6 +26,7 @@ #endif #include +#include // Spirit v2.5 allows you to suppress automatic generation // of predefined terminals to speed up complation. With @@ -496,9 +497,22 @@ namespace client static void leq (expr &lhs, expr &rhs) { compare_op(lhs, rhs, '>', true ); } static void geq (expr &lhs, expr &rhs) { compare_op(lhs, rhs, '<', true ); } + // Random number generators + static int random_int(int min, int max) { + thread_local static std::mt19937 engine(std::random_device{}()); + thread_local static std::uniform_int_distribution dist; + return dist(engine, decltype(dist)::param_type{ min, max }); + } + static double random_double(double min, double max) { + thread_local static std::mt19937 engine(std::random_device{}()); + thread_local static std::uniform_real_distribution dist; + return dist(engine, decltype(dist)::param_type{ min, max }); + } + enum Function2ParamsType { FUNCTION_MIN, FUNCTION_MAX, + FUNCTION_RANDOM, }; // Store the result into param1. static void function_2params(expr ¶m1, expr ¶m2, Function2ParamsType fun) @@ -511,6 +525,7 @@ namespace client switch (fun) { case FUNCTION_MIN: d = std::min(param1.as_d(), param2.as_d()); break; case FUNCTION_MAX: d = std::max(param1.as_d(), param2.as_d()); break; + case FUNCTION_RANDOM: d = random_double(param1.as_d(), param2.as_d()); break; default: param1.throw_exception("Internal error: invalid function"); } param1.data.d = d; @@ -520,6 +535,7 @@ namespace client switch (fun) { case FUNCTION_MIN: i = std::min(param1.as_i(), param2.as_i()); break; case FUNCTION_MAX: i = std::max(param1.as_i(), param2.as_i()); break; + case FUNCTION_RANDOM: i = random_int(param1.as_i(), param2.as_i()); break; default: param1.throw_exception("Internal error: invalid function"); } param1.data.i = i; @@ -529,6 +545,7 @@ namespace client // Store the result into param1. static void min(expr ¶m1, expr ¶m2) { function_2params(param1, param2, FUNCTION_MIN); } static void max(expr ¶m1, expr ¶m2) { function_2params(param1, param2, FUNCTION_MAX); } + static void random(expr ¶m1, expr ¶m2) { function_2params(param1, param2, FUNCTION_RANDOM); } static void regex_op(expr &lhs, boost::iterator_range &rhs, char op) { @@ -1176,6 +1193,8 @@ namespace client [ px::bind(&expr::min, _val, _2) ] | (kw["max"] > '(' > conditional_expression(_r1) [_val = _1] > ',' > conditional_expression(_r1) > ')') [ px::bind(&expr::max, _val, _2) ] + | (kw["random"] > '(' > conditional_expression(_r1) [_val = _1] > ',' > conditional_expression(_r1) > ')') + [ px::bind(&expr::random, _val, _2) ] | (kw["int"] > '(' > unary_expression(_r1) > ')') [ px::bind(&FactorActions::to_int, _1, _val) ] | (strict_double > iter_pos) [ px::bind(&FactorActions::double_, _1, _2, _val) ] | (int_ > iter_pos) [ px::bind(&FactorActions::int_, _1, _2, _val) ] @@ -1212,6 +1231,7 @@ namespace client ("false") ("min") ("max") + ("random") ("not") ("or") ("true");