]> git.mxchange.org Git - simgear.git/commitdiff
Modified Files:
authorfrohlich <frohlich>
Wed, 26 Dec 2007 19:12:04 +0000 (19:12 +0000)
committerfrohlich <frohlich>
Wed, 26 Dec 2007 19:12:04 +0000 (19:12 +0000)
animation.cxx animation.hxx: Make use of the expression stuff.
Factors out common code with other animations stuff in flightgear.

simgear/scene/model/animation.cxx
simgear/scene/model/animation.hxx

index 5966b5ab46670bdda52148b529e943bc57fb23e0..81040876016cc8d519c967b8d73b02ee3a7d8d7f 100644 (file)
@@ -110,36 +110,6 @@ set_translation (osg::Matrix &matrix, double position_m, const SGVec3d &axis)
   matrix(3, 2) = xyz[2];
 }
 
-/**
- * Modify property value by step and scroll settings in texture translations
- */
-static double
-apply_mods(double property, double step, double scroll, double bias)
-{
-
-  double modprop;
-  property += bias;
-  if(step > 0) {
-    double scrollval = 0.0;
-    if(scroll > 0) {
-      // calculate scroll amount (for odometer like movement)
-      double 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;
-  }
-  return modprop;
-
-}
-
 /**
  * Read an interpolation table from properties.
  */
@@ -152,202 +122,96 @@ read_interpolation_table(const SGPropertyNode* props)
   return new SGInterpTable(table_node);
 }
 
-////////////////////////////////////////////////////////////////////////
-// Utility value classes
-////////////////////////////////////////////////////////////////////////
-class SGScaleOffsetValue : public SGDoubleValue {
-public:
-  SGScaleOffsetValue(SGPropertyNode const* propertyNode) :
-    _propertyNode(propertyNode),
-    _scale(1),
-    _offset(0),
-    _min(-SGLimitsd::max()),
-    _max(SGLimitsd::max())
-  { }
-  void setScale(double scale)
-  { _scale = scale; }
-  void setOffset(double offset)
-  { _offset = offset; }
-  void setMin(double min)
-  { _min = min; }
-  void setMax(double max)
-  { _max = max; }
-
-  virtual double getValue() const
-  {
-    double value = _propertyNode ? _propertyNode->getDoubleValue() : 0;
-    return std::min(_max, std::max(_min, _offset + _scale*value));
-  }
-private:
-  SGSharedPtr<SGPropertyNode const> _propertyNode;
-  double _scale;
-  double _offset;
-  double _min;
-  double _max;
-};
+static std::string
+unit_string(const char* value, const char* unit)
+{
+  return std::string(value) + unit;
+}
 
-class SGPersScaleOffsetValue : public SGDoubleValue {
+class SGPersonalityScaleOffsetExpression : public SGUnaryExpression<double> {
 public:
-  SGPersScaleOffsetValue(SGPropertyNode const* propertyNode,
-                         SGPropertyNode const* config,
-                         const char* scalename, const char* offsetname,
-                         double defScale = 1, double defOffset = 0) :
-    _propertyNode(propertyNode),
-    _scale(config, scalename, defScale),
-    _offset(config, offsetname, defOffset),
-    _min(-SGLimitsd::max()),
-    _max(SGLimitsd::max())
+  SGPersonalityScaleOffsetExpression(SGExpression<double>* expr,
+                                     SGPropertyNode const* config,
+                                     const std::string& scalename,
+                                     const std::string& offsetname,
+                                     double defScale = 1,
+                                     double defOffset = 0) :
+    SGUnaryExpression<double>(expr),
+    _scale(config, scalename.c_str(), defScale),
+    _offset(config, offsetname.c_str(), defOffset)
   { }
   void setScale(double scale)
   { _scale = scale; }
   void setOffset(double offset)
   { _offset = offset; }
-  void setMin(double min)
-  { _min = min; }
-  void setMax(double max)
-  { _max = max; }
 
-  virtual double getValue() const
+  virtual void eval(double& value) const
   {
     _offset.shuffle();
     _scale.shuffle();
-    double value = _propertyNode ? _propertyNode->getDoubleValue() : 0;
-    return SGMiscd::clip(_offset + _scale*value, _min, _max);
+    value = _offset + _scale*getOperand()->getValue();
   }
-private:
-  SGSharedPtr<SGPropertyNode const> _propertyNode;
-  mutable SGPersonalityParameter<double> _scale;
-  mutable SGPersonalityParameter<double> _offset;
-  double _min;
-  double _max;
-};
 
-class SGInterpTableValue : public SGDoubleValue {
-public:
-  SGInterpTableValue(SGPropertyNode const* propertyNode,
-                     SGInterpTable const* interpTable) :
-    _propertyNode(propertyNode),
-    _interpTable(interpTable)
-  { }
-  virtual double getValue() const
-  { return _interpTable->interpolate(_propertyNode ? _propertyNode->getDoubleValue() : 0); }
-private:
-  SGSharedPtr<SGPropertyNode const> _propertyNode;
-  SGSharedPtr<SGInterpTable const> _interpTable;
-};
+  virtual bool isConst() const { return false; }
 
-class SGTexScaleOffsetValue : public SGDoubleValue {
-public:
-  SGTexScaleOffsetValue(const SGPropertyNode* propertyNode) :
-    _propertyNode(propertyNode),
-    _scale(1),
-    _offset(0),
-    _step(0),
-    _scroll(0),
-    _bias(0),
-    _min(-SGLimitsd::max()),
-    _max(SGLimitsd::max())
-  { }
-  void setScale(double scale)
-  { _scale = scale; }
-  void setOffset(double offset)
-  { _offset = offset; }
-  void setStep(double step)
-  { _step = step; }
-  void setScroll(double scroll)
-  { _scroll = scroll; }
-  void setBias(double bias)
-  { _bias = bias; }
-  void setMin(double min)
-  { _min = min; }
-  void setMax(double max)
-  { _max = max; }
-
-  virtual double getValue() const
-  {
-    double value = _propertyNode ? _propertyNode->getDoubleValue() : 0;
-    value = apply_mods(value, _step, _scroll, _bias);
-    return SGMiscd::clip(_scale*(_offset + value), _min, _max);
-  }
 private:
-  SGSharedPtr<const SGPropertyNode> _propertyNode;
-  double _scale;
-  double _offset;
-  double _step;
-  double _scroll;
-  double _bias;
-  double _min;
-  double _max;
+  mutable SGPersonalityParameter<double> _scale;
+  mutable SGPersonalityParameter<double> _offset;
 };
 
-class SGTexTableValue : public SGDoubleValue {
-public:
-  SGTexTableValue(const SGPropertyNode* propertyNode,
-                  const SGInterpTable* interpTable) :
-    _propertyNode(propertyNode),
-    _interpTable(interpTable)
-  { }
-  void setStep(double step)
-  { _step = step; }
-  void setScroll(double scroll)
-  { _scroll = scroll; }
-  void setBias(double bias)
-  { _bias = bias; }
-  virtual double getValue() const
-  {
-    double value = _propertyNode ? _propertyNode->getDoubleValue() : 0;
-    value = apply_mods(value, _step, _scroll, _bias);
-    return _interpTable->interpolate(value);
-  }
-private:
-  SGSharedPtr<SGPropertyNode const> _propertyNode;
-  SGSharedPtr<SGInterpTable const> _interpTable;
-  double _step;
-  double _scroll;
-  double _bias;
-};
 
-static std::string
-unit_string(const char* value, const char* unit)
+static SGExpressiond*
+read_factor_offset(const SGPropertyNode* configNode, SGExpressiond* expr,
+                   const std::string& factor, const std::string& offset)
 {
-  return std::string(value) + unit;
+  double factorValue = configNode->getDoubleValue(factor, 1);
+  if (factorValue != 1)
+    expr = new SGScaleExpression<double>(expr, factorValue);
+  double offsetValue = configNode->getDoubleValue(offset, 0);
+  if (offsetValue != 0)
+    expr = new SGBiasExpression<double>(expr, offsetValue);
+  return expr;
 }
 
-static SGDoubleValue*
+static SGExpressiond*
 read_value(const SGPropertyNode* configNode, SGPropertyNode* modelRoot,
            const char* unit, double defMin, double defMax)
 {
-  std::string inputPropertyName;
-  inputPropertyName = configNode->getStringValue("property", "");
-  if (!inputPropertyName.empty()) {
+  SGExpression<double>* value = 0;
+
+  std::string inputPropertyName = configNode->getStringValue("property", "");
+  if (inputPropertyName.empty()) {
+    std::string spos = unit_string("starting-position", unit);
+    double initPos = configNode->getDoubleValue(spos, 0);
+    value = new SGConstExpression<double>(initPos);
+  } else {
     SGPropertyNode* inputProperty;
-    inputProperty = modelRoot->getNode(inputPropertyName.c_str(), true);
-    SGInterpTable* interpTable = read_interpolation_table(configNode);
-    if (interpTable) {
-      SGInterpTableValue* value;
-      value = new SGInterpTableValue(inputProperty, interpTable);
-      return value;
+    inputProperty = modelRoot->getNode(inputPropertyName, true);
+    value = new SGPropertyExpression<double>(inputProperty);
+  }
+
+  SGInterpTable* interpTable = read_interpolation_table(configNode);
+  if (interpTable) {
+    return new SGInterpTableExpression<double>(value, interpTable);
+  } else {
+    std::string offset = unit_string("offset", unit);
+    std::string min = unit_string("min", unit);
+    std::string max = unit_string("max", unit);
+    
+    if (configNode->getBoolValue("use-personality", false)) {
+      value = new SGPersonalityScaleOffsetExpression(value, configNode,
+                                                     "factor", offset);
     } else {
-      std::string offset = unit_string("offset", unit);
-      std::string min = unit_string("min", unit);
-      std::string max = unit_string("max", unit);
-
-      if (configNode->getBoolValue("use-personality", false)) {
-        SGPersScaleOffsetValue* value;
-        value = new SGPersScaleOffsetValue(inputProperty, configNode,
-                                           "factor", offset.c_str());
-        value->setMin(configNode->getDoubleValue(min.c_str(), defMin));
-        value->setMax(configNode->getDoubleValue(max.c_str(), defMax));
-        return value;
-      } else {
-        SGScaleOffsetValue* value = new SGScaleOffsetValue(inputProperty);
-        value->setScale(configNode->getDoubleValue("factor", 1));
-        value->setOffset(configNode->getDoubleValue(offset.c_str(), 0));
-        value->setMin(configNode->getDoubleValue(min.c_str(), defMin));
-        value->setMax(configNode->getDoubleValue(max.c_str(), defMax));
-        return value;
-      }
+      value = read_factor_offset(configNode, value, "factor", offset);
     }
+    
+    double minClip = configNode->getDoubleValue(min, defMin);
+    double maxClip = configNode->getDoubleValue(max, defMax);
+    if (minClip > SGMiscd::min(SGLimitsd::min(), -SGLimitsd::max()) ||
+        maxClip < SGLimitsd::max())
+      value = new SGClipExpression<double>(value, minClip, maxClip);
+    
+    return value;
   }
   return 0;
 }
@@ -742,7 +606,7 @@ SGGroupAnimation::createAnimationGroup(osg::Group& parent)
 class SGTranslateAnimation::UpdateCallback : public osg::NodeCallback {
 public:
   UpdateCallback(SGCondition const* condition,
-                 SGDoubleValue const* animationValue) :
+                 SGExpressiond const* animationValue) :
     _condition(condition),
     _animationValue(animationValue)
   { }
@@ -757,7 +621,7 @@ public:
   }
 public:
   SGSharedPtr<SGCondition const> _condition;
-  SGSharedPtr<SGDoubleValue const> _animationValue;
+  SGSharedPtr<SGExpressiond const> _animationValue;
 };
 
 SGTranslateAnimation::SGTranslateAnimation(const SGPropertyNode* configNode,
@@ -765,17 +629,20 @@ SGTranslateAnimation::SGTranslateAnimation(const SGPropertyNode* configNode,
   SGAnimation(configNode, modelRoot)
 {
   _condition = getCondition();
-  _animationValue = read_value(configNode, modelRoot, "-m",
-                               -SGLimitsd::max(), SGLimitsd::max());
+  SGSharedPtr<SGExpressiond> value;
+  value = read_value(configNode, modelRoot, "-m",
+                     -SGLimitsd::max(), SGLimitsd::max());
+  _animationValue = value->simplify();
+  if (_animationValue)
+    _initialValue = _animationValue->getValue();
+  else
+    _initialValue = 0;
+
   _axis[0] = configNode->getDoubleValue("axis/x", 0);
   _axis[1] = configNode->getDoubleValue("axis/y", 0);
   _axis[2] = configNode->getDoubleValue("axis/z", 0);
   if (8*SGLimitsd::min() < norm(_axis))
     _axis = normalize(_axis);
-
-  _initialValue = configNode->getDoubleValue("starting-position-m", 0);
-  _initialValue *= configNode->getDoubleValue("factor", 1);
-  _initialValue += configNode->getDoubleValue("offset-m", 0);
 }
 
 osg::Group*
@@ -783,7 +650,7 @@ SGTranslateAnimation::createAnimationGroup(osg::Group& parent)
 {
   SGTranslateTransform* transform = new SGTranslateTransform;
   transform->setName("translate animation");
-  if (_animationValue) {
+  if (_animationValue && !_animationValue->isConst()) {
     UpdateCallback* uc = new UpdateCallback(_condition, _animationValue);
     transform->setUpdateCallback(uc);
   }
@@ -801,7 +668,7 @@ SGTranslateAnimation::createAnimationGroup(osg::Group& parent)
 class SGRotateAnimation::UpdateCallback : public osg::NodeCallback {
 public:
   UpdateCallback(SGCondition const* condition,
-                 SGDoubleValue const* animationValue) :
+                 SGExpressiond const* animationValue) :
     _condition(condition),
     _animationValue(animationValue)
   { }
@@ -816,13 +683,13 @@ public:
   }
 public:
   SGSharedPtr<SGCondition const> _condition;
-  SGSharedPtr<SGDoubleValue const> _animationValue;
+  SGSharedPtr<SGExpressiond const> _animationValue;
 };
 
 class SGRotateAnimation::SpinUpdateCallback : public osg::NodeCallback {
 public:
   SpinUpdateCallback(SGCondition const* condition,
-                     SGDoubleValue const* animationValue) :
+                     SGExpressiond const* animationValue) :
     _condition(condition),
     _animationValue(animationValue),
     _lastTime(-1)
@@ -848,22 +715,26 @@ public:
   }
 public:
   SGSharedPtr<SGCondition const> _condition;
-  SGSharedPtr<SGDoubleValue const> _animationValue;
+  SGSharedPtr<SGExpressiond const> _animationValue;
   double _lastTime;
 };
 
-SGRotateAnimation::SGRotateAnimation(const SGPropertyNode* configNode, SGPropertyNode* modelRoot) :
+SGRotateAnimation::SGRotateAnimation(const SGPropertyNode* configNode,
+                                     SGPropertyNode* modelRoot) :
   SGAnimation(configNode, modelRoot)
 {
   std::string type = configNode->getStringValue("type", "");
   _isSpin = (type == "spin");
 
   _condition = getCondition();
-  _animationValue = read_value(configNode, modelRoot, "-deg",
-                               -SGLimitsd::max(), SGLimitsd::max());
-  _initialValue = configNode->getDoubleValue("starting-position-deg", 0);
-  _initialValue *= configNode->getDoubleValue("factor", 1);
-  _initialValue += configNode->getDoubleValue("offset-deg", 0);
+  SGSharedPtr<SGExpressiond> value;
+  value = read_value(configNode, modelRoot, "-deg",
+                     -SGLimitsd::max(), SGLimitsd::max());
+  _animationValue = value->simplify();
+  if (_animationValue)
+    _initialValue = _animationValue->getValue();
+  else
+    _initialValue = 0;
 
   _center = SGVec3d::zeros();
   if (configNode->hasValue("axis/x1-m")) {
@@ -898,7 +769,7 @@ SGRotateAnimation::createAnimationGroup(osg::Group& parent)
     SpinUpdateCallback* uc;
     uc = new SpinUpdateCallback(_condition, _animationValue);
     transform->setUpdateCallback(uc);
-  } else if (_animationValue) {
+  } else if (_animationValue || !_animationValue->isConst()) {
     UpdateCallback* uc = new UpdateCallback(_condition, _animationValue);
     transform->setUpdateCallback(uc);
   }
@@ -917,7 +788,7 @@ SGRotateAnimation::createAnimationGroup(osg::Group& parent)
 class SGScaleAnimation::UpdateCallback : public osg::NodeCallback {
 public:
   UpdateCallback(const SGCondition* condition,
-                 SGSharedPtr<const SGDoubleValue> animationValue[3]) :
+                 SGSharedPtr<const SGExpressiond> animationValue[3]) :
     _condition(condition)
   {
     _animationValue[0] = animationValue[0];
@@ -938,7 +809,7 @@ public:
   }
 public:
   SGSharedPtr<SGCondition const> _condition;
-  SGSharedPtr<SGDoubleValue const> _animationValue[3];
+  SGSharedPtr<SGExpressiond const> _animationValue[3];
 };
 
 SGScaleAnimation::SGScaleAnimation(const SGPropertyNode* configNode,
@@ -951,58 +822,69 @@ SGScaleAnimation::SGScaleAnimation(const SGPropertyNode* configNode,
   double offset = configNode->getDoubleValue("offset", 0);
   double factor = configNode->getDoubleValue("factor", 1);
 
+  SGSharedPtr<SGExpressiond> inPropExpr;
+
   std::string inputPropertyName;
   inputPropertyName = configNode->getStringValue("property", "");
-  SGPropertyNode* inputProperty = 0;
-  if (!inputPropertyName.empty()) {
-    inputProperty = modelRoot->getNode(inputPropertyName.c_str(), true);
+  if (inputPropertyName.empty()) {
+    inPropExpr = new SGConstExpression<double>(0);
+  } else {
+    SGPropertyNode* inputProperty;
+    inputProperty = modelRoot->getNode(inputPropertyName, true);
+    inPropExpr = new SGPropertyExpression<double>(inputProperty);
   }
+
   SGInterpTable* interpTable = read_interpolation_table(configNode);
   if (interpTable) {
-    SGInterpTableValue* value;
-    value = new SGInterpTableValue(inputProperty, interpTable);
-    _animationValue[0] = value;
-    _animationValue[1] = value;
-    _animationValue[2] = value;
+    SGSharedPtr<SGExpressiond> value;
+    value = new SGInterpTableExpression<double>(inPropExpr, interpTable);
+    _animationValue[0] = value->simplify();
+    _animationValue[1] = value->simplify();
+    _animationValue[2] = value->simplify();
   } else if (configNode->getBoolValue("use-personality", false)) {
-    SGPersScaleOffsetValue* value;
-    value = new SGPersScaleOffsetValue(inputProperty, configNode,
-                                        "x-factor", "x-offset",
-                                        factor, offset);
-    value->setMin(configNode->getDoubleValue("x-min", 0));
-    value->setMax(configNode->getDoubleValue("x-max", SGLimitsd::max()));
-    _animationValue[0] = value;
-    value = new SGPersScaleOffsetValue(inputProperty, configNode,
-                                        "y-factor", "y-offset",
-                                        factor, offset);
-    value->setMin(configNode->getDoubleValue("y-min", 0));
-    value->setMax(configNode->getDoubleValue("y-max", SGLimitsd::max()));
-    _animationValue[1] = value;
-    value = new SGPersScaleOffsetValue(inputProperty, configNode,
-                                        "z-factor", "z-offset",
-                                        factor, offset);
-    value->setMin(configNode->getDoubleValue("z-min", 0));
-    value->setMax(configNode->getDoubleValue("z-max", SGLimitsd::max()));
-    _animationValue[2] = value;
+    SGSharedPtr<SGExpressiond> value;
+    value = new SGPersonalityScaleOffsetExpression(inPropExpr, configNode,
+                                                   "x-factor", "x-offset",
+                                                   factor, offset);
+    double minClip = configNode->getDoubleValue("x-min", 0);
+    double maxClip = configNode->getDoubleValue("x-max", SGLimitsd::max());
+    value = new SGClipExpression<double>(value, minClip, maxClip);
+    _animationValue[0] = value->simplify();
+    
+    value = new SGPersonalityScaleOffsetExpression(inPropExpr, configNode,
+                                                   "y-factor", "y-offset",
+                                                   factor, offset);
+    minClip = configNode->getDoubleValue("y-min", 0);
+    maxClip = configNode->getDoubleValue("y-max", SGLimitsd::max());
+    value = new SGClipExpression<double>(value, minClip, maxClip);
+    _animationValue[1] = value->simplify();
+    
+    value = new SGPersonalityScaleOffsetExpression(inPropExpr, configNode,
+                                                   "z-factor", "z-offset",
+                                                   factor, offset);
+    minClip = configNode->getDoubleValue("z-min", 0);
+    maxClip = configNode->getDoubleValue("z-max", SGLimitsd::max());
+    value = new SGClipExpression<double>(value, minClip, maxClip);
+    _animationValue[2] = value->simplify();
   } else {
-    SGScaleOffsetValue* value = new SGScaleOffsetValue(inputProperty);
-    value->setScale(configNode->getDoubleValue("x-factor", factor));
-    value->setOffset(configNode->getDoubleValue("x-offset", offset));
-    value->setMin(configNode->getDoubleValue("x-min", 0));
-    value->setMax(configNode->getDoubleValue("x-max", SGLimitsd::max()));
-    _animationValue[0] = value;
-    value = new SGScaleOffsetValue(inputProperty);
-    value->setScale(configNode->getDoubleValue("y-factor", factor));
-    value->setOffset(configNode->getDoubleValue("y-offset", offset));
-    value->setMin(configNode->getDoubleValue("y-min", 0));
-    value->setMax(configNode->getDoubleValue("y-max", SGLimitsd::max()));
-    _animationValue[1] = value;
-    value = new SGScaleOffsetValue(inputProperty);
-    value->setScale(configNode->getDoubleValue("z-factor", factor));
-    value->setOffset(configNode->getDoubleValue("z-offset", offset));
-    value->setMin(configNode->getDoubleValue("z-min", 0));
-    value->setMax(configNode->getDoubleValue("z-max", SGLimitsd::max()));
-    _animationValue[2] = value;
+    SGSharedPtr<SGExpressiond> value;
+    value = read_factor_offset(configNode, inPropExpr, "x-factor", "x-offset");
+    double minClip = configNode->getDoubleValue("x-min", 0);
+    double maxClip = configNode->getDoubleValue("x-max", SGLimitsd::max());
+    value = new SGClipExpression<double>(value, minClip, maxClip);
+    _animationValue[0] = value->simplify();
+
+    value = read_factor_offset(configNode, inPropExpr, "y-factor", "y-offset");
+    minClip = configNode->getDoubleValue("y-min", 0);
+    maxClip = configNode->getDoubleValue("y-max", SGLimitsd::max());
+    value = new SGClipExpression<double>(value, minClip, maxClip);
+    _animationValue[1] = value->simplify();
+
+    value = read_factor_offset(configNode, inPropExpr, "z-factor", "z-offset");
+    minClip = configNode->getDoubleValue("z-min", 0);
+    maxClip = configNode->getDoubleValue("z-max", SGLimitsd::max());
+    value = new SGClipExpression<double>(value, minClip, maxClip);
+    _animationValue[2] = value->simplify();
   }
   _initialValue[0] = configNode->getDoubleValue("x-starting-scale", 1);
   _initialValue[0] *= configNode->getDoubleValue("x-factor", factor);
@@ -1335,8 +1217,8 @@ SGBillboardAnimation::createAnimationGroup(osg::Group& parent)
 class SGRangeAnimation::UpdateCallback : public osg::NodeCallback {
 public:
   UpdateCallback(const SGCondition* condition,
-                 const SGDoubleValue* minAnimationValue,
-                 const SGDoubleValue* maxAnimationValue,
+                 const SGExpressiond* minAnimationValue,
+                 const SGExpressiond* maxAnimationValue,
                  double minValue, double maxValue) :
     _condition(condition),
     _minAnimationValue(minAnimationValue),
@@ -1367,8 +1249,8 @@ public:
 
 private:
   SGSharedPtr<const SGCondition> _condition;
-  SGSharedPtr<const SGDoubleValue> _minAnimationValue;
-  SGSharedPtr<const SGDoubleValue> _maxAnimationValue;
+  SGSharedPtr<const SGExpressiond> _minAnimationValue;
+  SGSharedPtr<const SGExpressiond> _maxAnimationValue;
   double _minStaticValue;
   double _maxStaticValue;
 };
@@ -1383,18 +1265,23 @@ SGRangeAnimation::SGRangeAnimation(const SGPropertyNode* configNode,
   inputPropertyName = configNode->getStringValue("min-property", "");
   if (!inputPropertyName.empty()) {
     SGPropertyNode* inputProperty;
-    inputProperty = modelRoot->getNode(inputPropertyName.c_str(), true);
-    SGScaleOffsetValue* value = new SGScaleOffsetValue(inputProperty);
-    value->setScale(configNode->getDoubleValue("min-factor", 1));
-    _minAnimationValue = value;
+    inputProperty = modelRoot->getNode(inputPropertyName, true);
+    SGSharedPtr<SGExpressiond> value;
+    value = new SGPropertyExpression<double>(inputProperty);
+
+    value = read_factor_offset(configNode, value, "min-factor", "min-offset");
+    _minAnimationValue = value->simplify();
   }
   inputPropertyName = configNode->getStringValue("max-property", "");
   if (!inputPropertyName.empty()) {
     SGPropertyNode* inputProperty;
     inputProperty = modelRoot->getNode(inputPropertyName.c_str(), true);
-    SGScaleOffsetValue* value = new SGScaleOffsetValue(inputProperty);
-    value->setScale(configNode->getDoubleValue("max-factor", 1));
-    _maxAnimationValue = value;
+
+    SGSharedPtr<SGExpressiond> value;
+    value = new SGPropertyExpression<double>(inputProperty);
+
+    value = read_factor_offset(configNode, value, "max-factor", "max-offset");
+    _maxAnimationValue = value->simplify();
   }
 
   _initialValue[0] = configNode->getDoubleValue("min-m", 0);
@@ -1610,7 +1497,7 @@ private:
 
 class SGBlendAnimation::UpdateCallback : public osg::NodeCallback {
 public:
-  UpdateCallback(const SGPropertyNode* configNode, const SGDoubleValue* v) :
+  UpdateCallback(const SGPropertyNode* configNode, const SGExpressiond* v) :
     _prev_value(-1),
     _animationValue(v)
   { }
@@ -1626,7 +1513,7 @@ public:
   }
 public:
   double _prev_value;
-  SGSharedPtr<SGDoubleValue const> _animationValue;
+  SGSharedPtr<SGExpressiond const> _animationValue;
 };
 
 
@@ -1889,7 +1776,7 @@ public:
     for (i = _transforms.begin(); i != _transforms.end(); ++i)
       i->transform->transform(texMat->getMatrix());
   }
-  void appendTransform(Transform* transform, SGDoubleValue* value)
+  void appendTransform(Transform* transform, SGExpressiond* value)
   {
     Entry entry = { transform, value };
     transform->transform(_matrix);
@@ -1899,7 +1786,7 @@ public:
 private:
   struct Entry {
     SGSharedPtr<Transform> transform;
-    SGSharedPtr<const SGDoubleValue> value;
+    SGSharedPtr<const SGExpressiond> value;
   };
   typedef std::vector<Entry> TransformList;
   TransformList _transforms;
@@ -1956,29 +1843,38 @@ SGTexTransformAnimation::appendTexTranslate(const SGPropertyNode* config,
                                             UpdateCallback* updateCallback)
 {
   std::string propertyName = config->getStringValue("property", "/null");
-  SGPropertyNode* inputNode;
-  inputNode = getModelRoot()->getNode(propertyName.c_str(), true);
+  SGSharedPtr<SGExpressiond> value;
+  if (getModelRoot()->hasChild(propertyName))
+    value = new SGPropertyExpression<double>(getModelRoot()->getNode(propertyName));
+  else
+    value = new SGConstExpression<double>(0);
 
-  SGDoubleValue* animationValue;
+  SGSharedPtr<SGExpressiond> animationValue;
   SGInterpTable* table = read_interpolation_table(config);
   if (table) {
-    SGTexTableValue* value;
-    value = new SGTexTableValue(inputNode, table);
-    value->setStep(config->getDoubleValue("step", 0));
-    value->setScroll(config->getDoubleValue("scroll", 0));
-    value->setBias(config->getDoubleValue("bias", 0));
-    animationValue = value;
+    value = new SGInterpTableExpression<double>(value, table);
+    double biasValue = config->getDoubleValue("bias", 0);
+    if (biasValue != 0)
+      value = new SGBiasExpression<double>(value, biasValue);
+    value = new SGStepExpression<double>(value,
+                                         config->getDoubleValue("step", 0),
+                                         config->getDoubleValue("scroll", 0));
+    animationValue = value->simplify();
   } else {
-    SGTexScaleOffsetValue* value;
-    value = new SGTexScaleOffsetValue(inputNode);
-    value->setScale(config->getDoubleValue("factor", 1));
-    value->setOffset(config->getDoubleValue("offset", 0));
-    value->setStep(config->getDoubleValue("step", 0));
-    value->setScroll(config->getDoubleValue("scroll", 0));
-    value->setBias(config->getDoubleValue("bias", 0));
-    value->setMin(config->getDoubleValue("min", -SGLimitsd::max()));
-    value->setMax(config->getDoubleValue("max", SGLimitsd::max()));
-    animationValue = value;
+    double biasValue = config->getDoubleValue("bias", 0);
+    if (biasValue != 0)
+      value = new SGBiasExpression<double>(value, biasValue);
+    value = new SGStepExpression<double>(value,
+                                         config->getDoubleValue("step", 0),
+                                         config->getDoubleValue("scroll", 0));
+    value = read_factor_offset(config, value, "factor", "offset");
+
+    if (config->hasChild("min") || config->hasChild("max")) {
+      double minClip = config->getDoubleValue("min", -SGLimitsd::max());
+      double maxClip = config->getDoubleValue("max", SGLimitsd::max());
+      value = new SGClipExpression<double>(value, minClip, maxClip);
+    }
+    animationValue = value->simplify();
   }
   SGVec3d axis(config->getDoubleValue("axis/x", 0),
                config->getDoubleValue("axis/y", 0),
@@ -1994,29 +1890,38 @@ SGTexTransformAnimation::appendTexRotate(const SGPropertyNode* config,
                                          UpdateCallback* updateCallback)
 {
   std::string propertyName = config->getStringValue("property", "/null");
-  SGPropertyNode* inputNode;
-  inputNode = getModelRoot()->getNode(propertyName.c_str(), true);
+  SGSharedPtr<SGExpressiond> value;
+  if (getModelRoot()->hasChild(propertyName))
+    value = new SGPropertyExpression<double>(getModelRoot()->getNode(propertyName));
+  else
+    value = new SGConstExpression<double>(0);
 
-  SGDoubleValue* animationValue;
+  SGSharedPtr<SGExpressiond> animationValue;
   SGInterpTable* table = read_interpolation_table(config);
   if (table) {
-    SGTexTableValue* value;
-    value = new SGTexTableValue(inputNode, table);
-    value->setStep(config->getDoubleValue("step", 0));
-    value->setScroll(config->getDoubleValue("scroll", 0));
-    value->setBias(config->getDoubleValue("bias", 0));
-    animationValue = value;
+    value = new SGInterpTableExpression<double>(value, table);
+    double biasValue = config->getDoubleValue("bias", 0);
+    if (biasValue != 0)
+      value = new SGBiasExpression<double>(value, biasValue);
+    value = new SGStepExpression<double>(value,
+                                         config->getDoubleValue("step", 0),
+                                         config->getDoubleValue("scroll", 0));
+    animationValue = value->simplify();
   } else {
-    SGTexScaleOffsetValue* value;
-    value = new SGTexScaleOffsetValue(inputNode);
-    value->setScale(config->getDoubleValue("factor", 1));
-    value->setOffset(config->getDoubleValue("offset-deg", 0));
-    value->setStep(config->getDoubleValue("step", 0));
-    value->setScroll(config->getDoubleValue("scroll", 0));
-    value->setBias(config->getDoubleValue("bias", 0));
-    value->setMin(config->getDoubleValue("min-deg", -SGLimitsd::max()));
-    value->setMax(config->getDoubleValue("max-deg", SGLimitsd::max()));
-    animationValue = value;
+    double biasValue = config->getDoubleValue("bias", 0);
+    if (biasValue != 0)
+      value = new SGBiasExpression<double>(value, biasValue);
+    value = new SGStepExpression<double>(value,
+                                         config->getDoubleValue("step", 0),
+                                         config->getDoubleValue("scroll", 0));
+    value = read_factor_offset(config, value, "factor", "offset-deg");
+
+    if (config->hasChild("min-deg") || config->hasChild("max-deg")) {
+      double minClip = config->getDoubleValue("min-deg", -SGLimitsd::max());
+      double maxClip = config->getDoubleValue("max-deg", SGLimitsd::max());
+      value = new SGClipExpression<double>(value, minClip, maxClip);
+    }
+    animationValue = value->simplify();
   }
   SGVec3d axis(config->getDoubleValue("axis/x", 0),
                config->getDoubleValue("axis/y", 0),
index 61901e9bcfc0b5496c5358f6968861b1f546656b..70ef67263addced098b1a6d5a985b23348081a3b 100644 (file)
 # error This library requires C++
 #endif
 
-#include <vector>
-#include <map>
-
-#include <osg/Vec3>
-#include <osg/Vec4>
-
 #include <osg/ref_ptr>
-#include <osg/AlphaFunc>
 #include <osg/Group>
-#include <osg/Material>
 #include <osg/Node>
-#include <osg/NodeCallback>
 #include <osg/NodeVisitor>
-#include <osg/StateSet>
 #include <osg/Texture2D>
-#include <osg/TexMat>
-
 #include <osgDB/ReaderWriter>
-#include <simgear/props/props.hxx>
-#include <simgear/misc/sg_path.hxx>
 
-#include <simgear/math/interpolater.hxx>
-#include <simgear/scene/model/persparam.hxx>
 #include <simgear/scene/util/SGNodeMasks.hxx>
-
-
-SG_USING_STD(vector);
-SG_USING_STD(map);
-
-// Don't pull in the headers, since we don't need them here.
-class SGInterpTable;
-class SGCondition;
+#include <simgear/props/props.hxx>
+#include <simgear/props/condition.hxx>
+#include <simgear/structure/SGExpression.hxx>
 
 // Has anyone done anything *really* stupid, like making min and max macros?
 #ifdef min
@@ -52,18 +31,6 @@ class SGCondition;
 #undef max
 #endif
 
-
-\f
-//////////////////////////////////////////////////////////////////////
-// Helper classes, FIXME: factor out
-//////////////////////////////////////////////////////////////////////
-
-class SGDoubleValue : public SGReferenced {
-public:
-  virtual ~SGDoubleValue() {}
-  virtual double getValue() const = 0;
-};
-
 \f
 //////////////////////////////////////////////////////////////////////
 // Base class for animation installers
@@ -150,7 +117,7 @@ public:
 private:
   class UpdateCallback;
   SGSharedPtr<const SGCondition> _condition;
-  SGSharedPtr<const SGDoubleValue> _animationValue;
+  SGSharedPtr<const SGExpressiond> _animationValue;
   SGVec3d _axis;
   double _initialValue;
 };
@@ -169,7 +136,7 @@ private:
   class UpdateCallback;
   class SpinUpdateCallback;
   SGSharedPtr<const SGCondition> _condition;
-  SGSharedPtr<const SGDoubleValue> _animationValue;
+  SGSharedPtr<const SGExpressiond> _animationValue;
   SGVec3d _axis;
   SGVec3d _center;
   double _initialValue;
@@ -189,7 +156,7 @@ public:
 private:
   class UpdateCallback;
   SGSharedPtr<const SGCondition> _condition;
-  SGSharedPtr<const SGDoubleValue> _animationValue[3];
+  SGSharedPtr<const SGExpressiond> _animationValue[3];
   SGVec3d _initialValue;
   SGVec3d _center;
 };
@@ -249,8 +216,8 @@ public:
 private:
   class UpdateCallback;
   SGSharedPtr<const SGCondition> _condition;
-  SGSharedPtr<const SGDoubleValue> _minAnimationValue;
-  SGSharedPtr<const SGDoubleValue> _maxAnimationValue;
+  SGSharedPtr<const SGExpressiond> _minAnimationValue;
+  SGSharedPtr<const SGExpressiond> _maxAnimationValue;
   SGVec2d _initialValue;
 };
 
@@ -294,7 +261,7 @@ public:
 private:
   class BlendVisitor;
   class UpdateCallback;
-  SGSharedPtr<SGDoubleValue> _animationValue;
+  SGSharedPtr<SGExpressiond> _animationValue;
 };
 
 \f