]> git.mxchange.org Git - simgear.git/blobdiff - simgear/structure/SGExpression.hxx
Allow Command-manager singleton to be deleted.
[simgear.git] / simgear / structure / SGExpression.hxx
index 05fc8336f9fd1f7b8c5e6b02b9dbf0c75757d331..2cfa3dc8909d629959816210282535f3be13f37c 100644 (file)
@@ -24,6 +24,9 @@
 
 #include <string>
 #include <vector>
+#include <functional>
+#include <set>
+#include <string>
 
 #include <simgear/props/condition.hxx>
 #include <simgear/props/props.hxx>
@@ -122,6 +125,9 @@ public:
   T getValue(const simgear::expression::Binding* binding = 0) const
   { T value; eval(value, binding); return value; }
 
+  double getDoubleValue(const simgear::expression::Binding* binding = 0) const
+  { T value; eval(value, binding); return value; }
+
   virtual bool isConst() const { return false; }
   virtual SGExpression* simplify();
   virtual simgear::expression::Type getType() const
@@ -132,6 +138,8 @@ public:
   {
     return simgear::expression::TypeTraits<T>::typeTag;
   }
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+  { }
 };
 
 /// Constant value expression
@@ -180,7 +188,9 @@ public:
     _expression = _expression->simplify();
     return SGExpression<T>::simplify();
   }
-
+  
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+    { _expression->collectDependentProperties(props); }  
 protected:
   SGUnaryExpression(SGExpression<T>* expression = 0)
   { setOperand(expression); }
@@ -192,11 +202,11 @@ private:
 template<typename T>
 class SGBinaryExpression : public SGExpression<T> {
 public:
-  const SGExpression<T>* getOperand(unsigned i) const
+  const SGExpression<T>* getOperand(size_t i) const
   { return _expressions[i]; }
-  SGExpression<T>* getOperand(unsigned i)
+  SGExpression<T>* getOperand(size_t i)
   { return _expressions[i]; }
-  void setOperand(unsigned i, SGExpression<T>* expression)
+  void setOperand(size_t i, SGExpression<T>* expression)
   {
     if (!expression)
       expression = new SGConstExpression<T>(T());
@@ -214,6 +224,12 @@ public:
     return SGExpression<T>::simplify();
   }
 
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+  {
+    _expressions[0]->collectDependentProperties(props);
+    _expressions[1]->collectDependentProperties(props); 
+  } 
+  
 protected:
   SGBinaryExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
   { setOperand(0, expr0); setOperand(1, expr1); }
@@ -225,16 +241,16 @@ private:
 template<typename T>
 class SGNaryExpression : public SGExpression<T> {
 public:
-  unsigned getNumOperands() const
+  size_t getNumOperands() const
   { return _expressions.size(); }
-  const SGExpression<T>* getOperand(unsigned i) const
+  const SGExpression<T>* getOperand(size_t i) const
   { return _expressions[i]; }
-  SGExpression<T>* getOperand(unsigned i)
+  SGExpression<T>* getOperand(size_t i)
   { return _expressions[i]; }
-  unsigned addOperand(SGExpression<T>* expression)
+  size_t addOperand(SGExpression<T>* expression)
   {
     if (!expression)
-      return ~unsigned(0);
+      return ~size_t(0);
     _expressions.push_back(expression);
     return _expressions.size() - 1;
   }
@@ -250,18 +266,23 @@ public:
 
   virtual bool isConst() const
   {
-    for (unsigned i = 0; i < _expressions.size(); ++i)
+    for (size_t i = 0; i < _expressions.size(); ++i)
       if (!_expressions[i]->isConst())
         return false;
     return true;
   }
   virtual SGExpression<T>* simplify()
   {
-    for (unsigned i = 0; i < _expressions.size(); ++i)
+    for (size_t i = 0; i < _expressions.size(); ++i)
       _expressions[i] = _expressions[i]->simplify();
     return SGExpression<T>::simplify();
   }
 
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+  {
+    for (size_t i = 0; i < _expressions.size(); ++i)
+      _expressions[i]->collectDependentProperties(props);
+  } 
 protected:
   SGNaryExpression()
   { }
@@ -284,6 +305,9 @@ public:
   { _prop = prop; }
   virtual void eval(T& value, const simgear::expression::Binding*) const
   { doEval(value); }
+  
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+    { props.insert(_prop.get()); }
 private:
   void doEval(float& value) const
   { if (_prop) value = _prop->getFloatValue(); }
@@ -319,7 +343,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = acos(SGMisc<T>::clip(getOperand()->getValue(b), -1, 1)); }
+  { value = acos((double)SGMisc<T>::clip(getOperand()->getValue(b), -1, 1)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -332,7 +356,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = asin(SGMisc<T>::clip(getOperand()->getValue(b), -1, 1)); }
+  { value = asin((double)SGMisc<T>::clip(getOperand()->getValue(b), -1, 1)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -345,7 +369,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = atan(getOperand()->getValue(b)); }
+  { value = atan(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -358,7 +382,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = ceil(getOperand()->getValue(b)); }
+  { value = ceil(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -371,7 +395,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = cos(getOperand()->getValue(b)); }
+  { value = cos(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -384,7 +408,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = cosh(getOperand()->getValue(b)); }
+  { value = cosh(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -397,7 +421,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = exp(getOperand()->getValue(b)); }
+  { value = exp(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -410,7 +434,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = floor(getOperand()->getValue(b)); }
+  { value = floor(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -423,7 +447,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = log(getOperand()->getValue(b)); }
+  { value = log(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -436,7 +460,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = log10(getOperand()->getValue(b)); }
+  { value = log10(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -449,7 +473,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = sin(getOperand()->getValue(b)); }
+  { value = sin(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -462,7 +486,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = sinh(getOperand()->getValue(b)); }
+  { value = sinh(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -488,7 +512,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = sqrt(getOperand()->getValue(b)); }
+  { value = sqrt(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -501,7 +525,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = tan(getOperand()->getValue(b)); }
+  { value = tan(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -514,7 +538,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = tanh(getOperand()->getValue(b)); }
+  { value = tanh(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -662,24 +686,16 @@ public:
 private:
   T apply_mods(T property) const
   {
-    T modprop;
-    if (_step > 0) {
-      T scrollval = 0;
-      if(_scroll > 0) {
-        // calculate scroll amount (for odometer like movement)
-        T remainder  =  _step - fmod(fabs(property), _step);
-        if (remainder < _scroll) {
-          scrollval = (_scroll - remainder) / _scroll * _step;
-        }
-      }
-      // apply stepping of input value
-      if(property > 0)
-        modprop = ((floor(property/_step) * _step) + scrollval);
-      else
-        modprop = ((ceil(property/_step) * _step) + scrollval);
-    } else {
-      modprop = property;
-    }
+    if( _step <= SGLimits<T>::min() ) return property;
+
+    // apply stepping of input value
+    T modprop = floor(property/_step)*_step;
+
+    // calculate scroll amount (for odometer like movement)
+    T remainder = property <= SGLimits<T>::min() ? -fmod(property,_step) : (_step - fmod(property,_step));
+    if( remainder > SGLimits<T>::min() && remainder < _scroll )
+      modprop += (_scroll - remainder) / _scroll * _step;
+
     return modprop;
   }
 
@@ -717,6 +733,12 @@ public:
       return getOperand()->simplify();
     return SGUnaryExpression<T>::simplify();
   }
+  
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+  {
+    SGUnaryExpression<T>::collectDependentProperties(props);
+    _enable->collectDependentProperties(props);
+  }
 
   using SGUnaryExpression<T>::getOperand;
 private:
@@ -731,7 +753,7 @@ public:
     : SGBinaryExpression<T>(expr0, expr1)
   { }
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = atan2(getOperand(0)->getValue(b), getOperand(1)->getValue(b)); }
+  { value = atan2(getOperand(0)->getDoubleValue(b), getOperand(1)->getDoubleValue(b)); }
   using SGBinaryExpression<T>::getOperand;
 };
 
@@ -771,7 +793,7 @@ public:
     : SGBinaryExpression<T>(expr0, expr1)
   { }
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = pow(getOperand(0)->getValue(b), getOperand(1)->getValue(b)); }
+  { value = pow(getOperand(0)->getDoubleValue(b), getOperand(1)->getDoubleValue(b)); }
   using SGBinaryExpression<T>::getOperand;
 };
 
@@ -786,14 +808,33 @@ public:
   virtual void eval(T& value, const simgear::expression::Binding* b) const
   {
     value = T(0);
-    unsigned sz = SGNaryExpression<T>::getNumOperands();
-    for (unsigned i = 0; i < sz; ++i)
+    size_t sz = SGNaryExpression<T>::getNumOperands();
+    for (size_t i = 0; i < sz; ++i)
       value += getOperand(i)->getValue(b);
   }
   using SGNaryExpression<T>::getValue;
   using SGNaryExpression<T>::getOperand;
 };
 
+template<typename T>
+class SGDifferenceExpression : public SGNaryExpression<T> {
+public:
+  SGDifferenceExpression()
+  { }
+  SGDifferenceExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
+    : SGNaryExpression<T>(expr0, expr1)
+  { }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  {
+    value = getOperand(0)->getValue(b);
+    size_t sz = SGNaryExpression<T>::getNumOperands();
+    for (size_t i = 1; i < sz; ++i)
+      value -= getOperand(i)->getValue(b);
+  }
+  using SGNaryExpression<T>::getValue;
+  using SGNaryExpression<T>::getOperand;
+};
+
 template<typename T>
 class SGProductExpression : public SGNaryExpression<T> {
 public:
@@ -805,8 +846,8 @@ public:
   virtual void eval(T& value, const simgear::expression::Binding* b) const
   {
     value = T(1);
-    unsigned sz = SGNaryExpression<T>::getNumOperands();
-    for (unsigned i = 0; i < sz; ++i)
+    size_t sz = SGNaryExpression<T>::getNumOperands();
+    for (size_t i = 0; i < sz; ++i)
       value *= getOperand(i)->getValue(b);
   }
   using SGNaryExpression<T>::getValue;
@@ -823,12 +864,12 @@ public:
   { }
   virtual void eval(T& value, const simgear::expression::Binding* b) const
   {
-    unsigned sz = SGNaryExpression<T>::getNumOperands();
+    size_t sz = SGNaryExpression<T>::getNumOperands();
     if (sz < 1)
       return;
     
     value = getOperand(0)->getValue(b);
-    for (unsigned i = 1; i < sz; ++i)
+    for (size_t i = 1; i < sz; ++i)
       value = SGMisc<T>::min(value, getOperand(i)->getValue(b));
   }
   using SGNaryExpression<T>::getOperand;
@@ -844,12 +885,12 @@ public:
   { }
   virtual void eval(T& value, const simgear::expression::Binding* b) const
   {
-    unsigned sz = SGNaryExpression<T>::getNumOperands();
+    size_t sz = SGNaryExpression<T>::getNumOperands();
     if (sz < 1)
       return;
     
     value = getOperand(0)->getValue(b);
-    for (unsigned i = 1; i < sz; ++i)
+    for (size_t i = 1; i < sz; ++i)
       value = SGMisc<T>::max(value, getOperand(i)->getValue(b));
   }
   using SGNaryExpression<T>::getOperand;
@@ -860,6 +901,11 @@ typedef SGExpression<float> SGExpressionf;
 typedef SGExpression<double> SGExpressiond;
 typedef SGExpression<bool> SGExpressionb;
 
+typedef SGSharedPtr<SGExpressioni> SGExpressioni_ref;
+typedef SGSharedPtr<SGExpressionf> SGExpressionf_ref;
+typedef SGSharedPtr<SGExpressiond> SGExpressiond_ref;
+typedef SGSharedPtr<SGExpressionb> SGExpressionb_ref;
+
 /**
  * Global function to make an expression out of properties.
 
@@ -904,7 +950,7 @@ namespace simgear
   {
   struct ParseError : public sg_exception
   {
-      ParseError(const string& message = std::string())
+      ParseError(const std::string& message = std::string())
           : sg_exception(message) {}
   };
     
@@ -968,8 +1014,8 @@ namespace simgear
   class BindingLayout
   {
   public:
-      int addBinding(const std::string& name, expression::Type type);
-      bool findBinding(const string& name, VariableBinding& result) const;
+      size_t addBinding(const std::string& name, expression::Type type);
+      bool findBinding(const std::string& name, VariableBinding& result) const;
       std::vector<VariableBinding> bindings;
   };
 
@@ -986,7 +1032,7 @@ namespace simgear
           ParserMap& map = getParserMap();
           ParserMap::iterator itr = map.find(exp->getName());
           if (itr == map.end())
-              throw ParseError(string("unknown expression ") + exp->getName());
+              throw ParseError(std::string("unknown expression ") + exp->getName());
           exp_parser parser = itr->second;
           return (*parser)(exp, this);
       }
@@ -1061,16 +1107,16 @@ namespace simgear
   class GeneralNaryExpression : public ::SGExpression<T> {
   public:
     typedef OpType operand_type;
-    unsigned getNumOperands() const
+    size_t getNumOperands() const
     { return _expressions.size(); }
-    const ::SGExpression<OpType>* getOperand(unsigned i) const
+    const ::SGExpression<OpType>* getOperand(size_t i) const
     { return _expressions[i]; }
-    ::SGExpression<OpType>* getOperand(unsigned i)
+    ::SGExpression<OpType>* getOperand(size_t i)
     { return _expressions[i]; }
-    unsigned addOperand(::SGExpression<OpType>* expression)
+    size_t addOperand(::SGExpression<OpType>* expression)
     {
       if (!expression)
-        return ~unsigned(0);
+        return ~size_t(0);
       _expressions.push_back(expression);
       return _expressions.size() - 1;
     }
@@ -1086,14 +1132,14 @@ namespace simgear
     
     virtual bool isConst() const
     {
-      for (unsigned i = 0; i < _expressions.size(); ++i)
+      for (size_t i = 0; i < _expressions.size(); ++i)
         if (!_expressions[i]->isConst())
           return false;
       return true;
     }
     virtual ::SGExpression<T>* simplify()
     {
-      for (unsigned i = 0; i < _expressions.size(); ++i)
+      for (size_t i = 0; i < _expressions.size(); ++i)
         _expressions[i] = _expressions[i]->simplify();
       return SGExpression<T>::simplify();
     }
@@ -1130,7 +1176,7 @@ namespace simgear
     }
     virtual void eval(bool& value, const simgear::expression::Binding* b) const
     {
-      unsigned sz = this->getNumOperands();
+      size_t sz = this->getNumOperands();
       if (sz != 2)
         return;
       value = _pred(this->getOperand(0)->getValue(b),
@@ -1234,7 +1280,7 @@ namespace simgear
     ConvertExpression() {}
     ConvertExpression(::SGExpression<OpType>* expr0)
     {
-      addOperand(expr0);
+      this->addOperand(expr0);
     }
     virtual void eval(T& value, const simgear::expression::Binding* b) const
     {