Matthias Urlichs 5 лет назад
Родитель
Сommit
329ad97a84
2 измененных файлов с 38 добавлено и 0 удалено
  1. 35 0
      src/libslic3r/PlaceholderParser.cpp
  2. 3 0
      t/custom_gcode.t

+ 35 - 0
src/libslic3r/PlaceholderParser.cpp

@@ -332,6 +332,21 @@ namespace client
             return expr();
         }
 
+        expr unary_integer(const Iterator start_pos) const
+        { 
+            switch (this->type) {
+            case TYPE_INT :
+                return expr<Iterator>(this->i(), start_pos, this->it_range.end());
+            case TYPE_DOUBLE:
+                return expr<Iterator>((int)(this->d()), start_pos, this->it_range.end()); 
+            default:
+                this->throw_exception("Cannot convert to integer.");
+            }
+            assert(false);
+            // Suppress compiler warnings.
+            return expr();
+        }
+
         expr unary_not(const Iterator start_pos) const
         { 
             switch (this->type) {
@@ -415,6 +430,22 @@ namespace client
             return *this;
         }
 
+        expr &operator%=(const expr &rhs)
+        {
+            this->throw_if_not_numeric("Cannot divide a non-numeric type.");
+            rhs.throw_if_not_numeric("Cannot divide with a non-numeric type.");
+            if ((this->type == TYPE_INT) ? (rhs.i() == 0) : (rhs.d() == 0.))
+                rhs.throw_exception("Division by zero");
+            if (this->type == TYPE_DOUBLE || rhs.type == TYPE_DOUBLE) {
+                double d = std::fmod(this->as_d(), rhs.as_d());
+                this->data.d = d;
+                this->type = TYPE_DOUBLE;
+            } else
+                this->data.i %= rhs.i();
+            this->it_range = boost::iterator_range<Iterator>(this->it_range.begin(), rhs.it_range.end());
+            return *this;
+        }
+
         static void to_string2(expr &self, std::string &out)
         {
             out = self.to_string();
@@ -1087,6 +1118,7 @@ namespace client
                 unary_expression(_r1)                       [_val  = _1]
                 >> *(   (lit('*') > unary_expression(_r1) ) [_val *= _1]
                     |   (lit('/') > unary_expression(_r1) ) [_val /= _1]
+                    |   (lit('%') > unary_expression(_r1) ) [_val %= _1]
                     );
             multiplicative_expression.name("multiplicative_expression");
 
@@ -1107,6 +1139,8 @@ namespace client
                         { out = value.unary_minus(out.it_range.begin()); }
                 static void not_(expr<Iterator> &value, expr<Iterator> &out)
                         { out = value.unary_not(out.it_range.begin()); }
+                static void to_int(expr<Iterator> &value, expr<Iterator> &out)
+                        { out = value.unary_integer(out.it_range.begin()); }
             };
             unary_expression = iter_pos[px::bind(&FactorActions::set_start_pos, _1, _val)] >> (
                     scalar_variable_reference(_r1)                  [ _val = _1 ]
@@ -1118,6 +1152,7 @@ namespace client
                                                                     [ px::bind(&expr<Iterator>::min, _val, _2) ]
                 |   (kw["max"] > '(' > conditional_expression(_r1) [_val = _1] > ',' > conditional_expression(_r1) > ')') 
                                                                     [ px::bind(&expr<Iterator>::max, _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) ]
                 |   (kw[bool_] > iter_pos)                          [ px::bind(&FactorActions::bool_,   _1, _2, _val) ]

+ 3 - 0
t/custom_gcode.t

@@ -67,6 +67,8 @@ use Slic3r::Test;
     is $parser->process('{2*3/6}'),   '1',   'math: 2*3/6';
     is $parser->process('{2*3/12}'),  '0',   'math: 2*3/12';
     ok abs($parser->process('{2.*3/12}') - 0.5) < 1e-7, 'math: 2.*3/12';
+    is $parser->process('{10%2.5}')   '0',   'math: 10 % 2.5';
+    is $parser->process('{11/2.5-1}') '1',   'math: 11 % 2.5';
     is $parser->process('{2*(3-12)}'), '-18', 'math: 2*(3-12)';
     is $parser->process('{2*foo*(3-12)}'), '0', 'math: 2*foo*(3-12)';
     is $parser->process('{2*bar*(3-12)}'), '-36', 'math: 2*bar*(3-12)';
@@ -75,6 +77,7 @@ use Slic3r::Test;
     is $parser->process('{max(12, 14)}'), '14', 'math: max(12, 14)';
     is $parser->process('{min(13.4, -1238.1)}'), '-1238.1', 'math: min(13.4, -1238.1)';
     is $parser->process('{max(13.4, -1238.1)}'), '13.4', 'math: max(13.4, -1238.1)';
+    is $parser->process('{int(13.4)}'), '13', 'math: int(13.4)';
 
     # Test the boolean expression parser.
     is $parser->evaluate_boolean_expression('12 == 12'), 1, 'boolean expression parser: 12 == 12';