]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/model/animation.cxx
pass SGReaderWriterXMLOptions to effects
[simgear.git] / simgear / scene / model / animation.cxx
index 1bb11bee4c08b0a63c10a081df4c2e0a1596f502..80c08be2bfc5b002f68728229b3644471df9b3b4 100644 (file)
 #include <osg/Texture2D>
 #include <osg/Transform>
 #include <osgDB/ReadFile>
+#include <osgDB/Registry>
+#include <osgDB/Input>
+#include <osgDB/ParameterOutput>
+
 
 #include <simgear/math/interpolater.hxx>
 #include <simgear/props/condition.hxx>
 #include "SGMaterialAnimation.hxx"
 #include "SGRotateTransform.hxx"
 #include "SGScaleTransform.hxx"
+#include "SGInteractionAnimation.hxx"
+
+using OpenThreads::Mutex;
+using OpenThreads::ReentrantMutex;
+using OpenThreads::ScopedLock;
 
 \f
 ////////////////////////////////////////////////////////////////////////
@@ -145,11 +154,11 @@ public:
   void setOffset(double offset)
   { _offset = offset; }
 
-  virtual void eval(double& value) const
+  virtual void eval(double& value, const simgear::expression::Binding* b) const
   {
     _offset.shuffle();
     _scale.shuffle();
-    value = _offset + _scale*getOperand()->getValue();
+    value = _offset + _scale*getOperand()->getValue(b);
   }
 
   virtual bool isConst() const { return false; }
@@ -342,7 +351,7 @@ struct DoDrawArraysVisitor : public osg::NodeVisitor {
         using namespace osg;
         using namespace std;
 
-        for (int i = 0; i < geode.getNumDrawables(); ++i)
+        for (int i = 0; i < (int)geode.getNumDrawables(); ++i)
             geode.getDrawable(i)->setUseDisplayList(false);
     }
 };
@@ -397,6 +406,9 @@ SGAnimation::animate(osg::Node* node, const SGPropertyNode* configNode,
   } else if (type == "flash") {
     SGFlashAnimation animInst(configNode, modelRoot);
     animInst.apply(node);
+  } else if (type == "interaction") {
+    SGInteractionAnimation animInst(configNode, modelRoot);
+    animInst.apply(node);
   } else if (type == "material") {
     SGMaterialAnimation animInst(configNode, modelRoot, options);
     animInst.apply(node);
@@ -651,9 +663,20 @@ SGTranslateAnimation::SGTranslateAnimation(const SGPropertyNode* configNode,
   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 (configNode->hasValue("axis/x1-m")) {
+    SGVec3d v1, v2;
+    v1[0] = configNode->getDoubleValue("axis/x1-m", 0);
+    v1[1] = configNode->getDoubleValue("axis/y1-m", 0);
+    v1[2] = configNode->getDoubleValue("axis/z1-m", 0);
+    v2[0] = configNode->getDoubleValue("axis/x2-m", 0);
+    v2[1] = configNode->getDoubleValue("axis/y2-m", 0);
+    v2[2] = configNode->getDoubleValue("axis/z2-m", 0);
+    _axis = v2 - v1;
+  } else {
+    _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);
 }
@@ -931,12 +954,12 @@ SGScaleAnimation::createAnimationGroup(osg::Group& parent)
 
 namespace
 {
-OpenThreads::Mutex normalizeMutex;
+Mutex normalizeMutex;
 
 osg::StateSet* getNormalizeStateSet()
 {
     static osg::ref_ptr<osg::StateSet> normalizeStateSet;
-    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(normalizeMutex);
+    ScopedLock<Mutex> lock(normalizeMutex);
     if (!normalizeStateSet.valid()) {
         normalizeStateSet = new osg::StateSet;
         normalizeStateSet->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
@@ -952,6 +975,15 @@ osg::StateSet* getNormalizeStateSet()
 
 class SGDistScaleAnimation::Transform : public osg::Transform {
 public:
+  Transform() : _min_v(0.0), _max_v(0.0), _factor(0.0), _offset(0.0) {}
+  Transform(const Transform& rhs,
+            const osg::CopyOp& copyOp = osg::CopyOp::SHALLOW_COPY)
+    : osg::Transform(rhs, copyOp), _table(rhs._table), _center(rhs._center),
+      _min_v(rhs._min_v), _max_v(rhs._max_v), _factor(rhs._factor),
+      _offset(rhs._offset)
+  {
+  }
+  META_Node(simgear, SGDistScaleAnimation::Transform);
   Transform(const SGPropertyNode* configNode)
   {
     setName(configNode->getStringValue("name", "dist scale animation"));
@@ -999,13 +1031,23 @@ public:
     return true;
   }
 
+  static bool writeLocalData(const osg::Object& obj, osgDB::Output& fw)
+  {
+    const Transform& trans = static_cast<const Transform&>(obj);
+    fw.indent() << "center " << trans._center << "\n";
+    fw.indent() << "min_v " << trans._min_v << "\n";
+    fw.indent() << "max_v " << trans._max_v << "\n";
+    fw.indent() << "factor " << trans._factor << "\n";
+    fw.indent() << "offset " << trans._offset << "\n";
+    return true;
+  }
 private:
   double computeScaleFactor(osg::NodeVisitor* nv) const
   {
     if (!nv)
       return 1;
 
-    double scale_factor = (_center.osg() - nv->getEyePoint()).length();
+    double scale_factor = (toOsg(_center) - nv->getEyePoint()).length();
     if (_table == 0) {
       scale_factor = _factor * scale_factor + _offset;
     } else {
@@ -1042,6 +1084,17 @@ SGDistScaleAnimation::createAnimationGroup(osg::Group& parent)
   return transform;
 }
 
+namespace
+{
+  osgDB::RegisterDotOsgWrapperProxy distScaleAnimationTransformProxy
+  (
+   new SGDistScaleAnimation::Transform,
+   "SGDistScaleAnimation::Transform",
+   "Object Node Transform SGDistScaleAnimation::Transform Group",
+   0,
+   &SGDistScaleAnimation::Transform::writeLocalData
+   );
+}
 \f
 ////////////////////////////////////////////////////////////////////////
 // Implementation of flash animation
@@ -1049,6 +1102,19 @@ SGDistScaleAnimation::createAnimationGroup(osg::Group& parent)
 
 class SGFlashAnimation::Transform : public osg::Transform {
 public:
+  Transform() : _power(0.0), _factor(0.0), _offset(0.0), _min_v(0.0),
+                _max_v(0.0), _two_sides(false)
+  {}
+
+  Transform(const Transform& rhs,
+            const osg::CopyOp& copyOp = osg::CopyOp::SHALLOW_COPY)
+    : osg::Transform(rhs, copyOp), _center(rhs._center), _axis(rhs._axis),
+      _power(rhs._power), _factor(rhs._factor), _offset(rhs._offset),
+      _min_v(rhs._min_v), _max_v(rhs._max_v), _two_sides(rhs._two_sides)
+  {
+  }
+  META_Node(simgear, SGFlashAnimation::Transform);
+
   Transform(const SGPropertyNode* configNode)
   {
     setReferenceFrame(RELATIVE_RF);
@@ -1105,6 +1171,21 @@ public:
     return true;
   }
 
+  static bool writeLocalData(const osg::Object& obj, osgDB::Output& fw)
+  {
+    const Transform& trans = static_cast<const Transform&>(obj);
+    fw.indent() << "center " << trans._center[0] << " "
+                << trans._center[1] << " " << trans._center[2] << " " << "\n";
+    fw.indent() << "axis " << trans._axis[0] << " "
+                << trans._axis[1] << " " << trans._axis[2] << " " << "\n";
+    fw.indent() << "power " << trans._power << " \n";
+    fw.indent() << "min_v " << trans._min_v << "\n";
+    fw.indent() << "max_v " << trans._max_v << "\n";
+    fw.indent() << "factor " << trans._factor << "\n";
+    fw.indent() << "offset " << trans._offset << "\n";
+    fw.indent() << "twosides " << (trans._two_sides ? "true" : "false") << "\n";
+    return true;
+  }
 private:
   double computeScaleFactor(osg::NodeVisitor* nv) const
   {
@@ -1159,13 +1240,29 @@ SGFlashAnimation::createAnimationGroup(osg::Group& parent)
   return transform;
 }
 
+namespace
+{
+  osgDB::RegisterDotOsgWrapperProxy flashAnimationTransformProxy
+  (
+   new SGFlashAnimation::Transform,
+   "SGFlashAnimation::Transform",
+   "Object Node Transform SGFlashAnimation::Transform Group",
+   0,
+   &SGFlashAnimation::Transform::writeLocalData
+   );
+}
 \f
 ////////////////////////////////////////////////////////////////////////
-// Implementation of flash animation
+// Implementation of billboard animation
 ////////////////////////////////////////////////////////////////////////
 
 class SGBillboardAnimation::Transform : public osg::Transform {
 public:
+  Transform() : _spherical(true) {}
+  Transform(const Transform& rhs,
+            const osg::CopyOp& copyOp = osg::CopyOp::SHALLOW_COPY)
+    : osg::Transform(rhs, copyOp), _spherical(rhs._spherical) {}
+  META_Node(simgear, SGBillboardAnimation::Transform);
   Transform(const SGPropertyNode* configNode) :
     _spherical(configNode->getBoolValue("spherical", true))
   {
@@ -1202,7 +1299,13 @@ public:
     // Hmm, don't yet know how to get that back ...
     return false;
   }
+  static bool writeLocalData(const osg::Object& obj, osgDB::Output& fw)
+  {
+    const Transform& trans = static_cast<const Transform&>(obj);
 
+    fw.indent() << (trans._spherical ? "true" : "false") << "\n";
+    return true;
+  }
 private:
   bool _spherical;
 };
@@ -1222,6 +1325,17 @@ SGBillboardAnimation::createAnimationGroup(osg::Group& parent)
   return transform;
 }
 
+namespace
+{
+  osgDB::RegisterDotOsgWrapperProxy billboardAnimationTransformProxy
+  (
+   new SGBillboardAnimation::Transform,
+   "SGBillboardAnimation::Transform",
+   "Object Node Transform SGBillboardAnimation::Transform Group",
+   0,
+   &SGBillboardAnimation::Transform::writeLocalData
+   );
+}
 \f
 ////////////////////////////////////////////////////////////////////////
 // Implementation of a range animation
@@ -1387,13 +1501,12 @@ SGAlphaTestAnimation::SGAlphaTestAnimation(const SGPropertyNode* configNode,
 namespace
 {
 // Keep one copy of the most common alpha test its state set.
-OpenThreads::ReentrantMutex alphaTestMutex;
+ReentrantMutex alphaTestMutex;
 osg::ref_ptr<osg::AlphaFunc> standardAlphaFunc;
 osg::ref_ptr<osg::StateSet> alphaFuncStateSet;
 
 osg::AlphaFunc* makeAlphaFunc(float clamp)
 {
-    using namespace OpenThreads;
     ScopedLock<ReentrantMutex> lock(alphaTestMutex);
     if (osg::equivalent(clamp, 0.01f)) {
         if (standardAlphaFunc.valid())
@@ -1817,6 +1930,7 @@ SGTexTransformAnimation::createAnimationGroup(osg::Group& parent)
   osg::Group* group = new osg::Group;
   group->setName("texture transform group");
   osg::StateSet* stateSet = group->getOrCreateStateSet();
+  stateSet->setDataVariance(osg::Object::DYNAMIC);  
   osg::TexMat* texMat = new osg::TexMat;
   UpdateCallback* updateCallback = new UpdateCallback(getCondition());
   // interpret the configs ...
@@ -1957,12 +2071,16 @@ class SGPickAnimation::PickCallback : public SGPickCallback {
 public:
   PickCallback(const SGPropertyNode* configNode,
                SGPropertyNode* modelRoot) :
-    _button(configNode->getIntValue("button", -1)),
     _repeatable(configNode->getBoolValue("repeatable", false)),
     _repeatInterval(configNode->getDoubleValue("interval-sec", 0.1))
   {
     SG_LOG(SG_INPUT, SG_DEBUG, "Reading all bindings");
     std::vector<SGPropertyNode_ptr> bindings;
+
+    bindings = configNode->getChildren("button");
+    for (unsigned int i = 0; i < bindings.size(); ++i) {
+      _buttons.push_back( bindings[i]->getIntValue() );
+    }
     bindings = configNode->getChildren("binding");
     for (unsigned int i = 0; i < bindings.size(); ++i) {
       _bindingsDown.push_back(new SGBinding(bindings[i], modelRoot));
@@ -1978,12 +2096,19 @@ public:
   }
   virtual bool buttonPressed(int button, const Info&)
   {
-    if (0 <= _button && button != _button)
+    bool found = false;
+    for( std::vector<int>::iterator it = _buttons.begin(); it != _buttons.end(); it++ ) {
+      if( *it == button ) {
+        found = true;
+        break;
+      }
+    }
+    if (!found )
       return false;
     SGBindingList::const_iterator i;
     for (i = _bindingsDown.begin(); i != _bindingsDown.end(); ++i)
       (*i)->fire();
-    _repeatTime = 0;
+    _repeatTime = -_repeatInterval;    // anti-bobble: delay start of repeat
     return true;
   }
   virtual void buttonReleased(void)
@@ -2008,7 +2133,7 @@ public:
 private:
   SGBindingList _bindingsDown;
   SGBindingList _bindingsUp;
-  int _button;
+  std::vector<int> _buttons;
   bool _repeatable;
   double _repeatInterval;
   double _repeatTime;
@@ -2027,14 +2152,16 @@ SGPickAnimation::createAnimationGroup(osg::Group& parent)
 
   // Contains the normal geometry that is interactive
   osg::ref_ptr<osg::Group> normalGroup = new osg::Group;
+  normalGroup->setName("pick normal group");
   normalGroup->addChild(commonGroup);
 
   // Used to render the geometry with just yellow edges
   osg::Group* highlightGroup = new osg::Group;
+  highlightGroup->setName("pick highlight group");
   highlightGroup->setNodeMask(SG_NODEMASK_PICK_BIT);
   highlightGroup->addChild(commonGroup);
   SGSceneUserData* ud;
-  ud = SGSceneUserData::getOrCreateSceneUserData(highlightGroup);
+  ud = SGSceneUserData::getOrCreateSceneUserData(commonGroup);
   std::vector<SGPropertyNode_ptr> actions;
   actions = getConfig()->getChildren("action");
   for (unsigned int i = 0; i < actions.size(); ++i)