]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/model/animation.cxx
Merge branch 'next' of git.gitorious.org:fg/simgear into next
[simgear.git] / simgear / scene / model / animation.cxx
index e84866530a0eceba2a5e3c69580a87701a63b0f1..fa9b44e1021ab3390df18defad2d91a6e5408368 100644 (file)
@@ -22,6 +22,7 @@
 #include <osg/Geometry>
 #include <osg/LOD>
 #include <osg/Math>
+#include <osg/Object>
 #include <osg/PolygonMode>
 #include <osg/PolygonOffset>
 #include <osg/StateSet>
@@ -29,6 +30,7 @@
 #include <osg/TexMat>
 #include <osg/Texture2D>
 #include <osg/Transform>
+#include <osg/Uniform>
 #include <osgDB/ReadFile>
 #include <osgDB/Registry>
 #include <osgDB/Input>
@@ -43,6 +45,7 @@
 #include <simgear/scene/util/SGNodeMasks.hxx>
 #include <simgear/scene/util/SGSceneUserData.hxx>
 #include <simgear/scene/util/SGStateAttributeVisitor.hxx>
+#include <simgear/scene/util/StateAttributeFactory.hxx>
 
 #include "animation.hxx"
 #include "model.hxx"
 #include "SGScaleTransform.hxx"
 #include "SGInteractionAnimation.hxx"
 
+#include "ConditionNode.hxx"
+
 using OpenThreads::Mutex;
 using OpenThreads::ReentrantMutex;
 using OpenThreads::ScopedLock;
 
+using namespace simgear;
 \f
 ////////////////////////////////////////////////////////////////////////
 // Static utility functions.
@@ -200,6 +206,10 @@ SGExpressiond*
 read_value(const SGPropertyNode* configNode, SGPropertyNode* modelRoot,
            const char* unit, double defMin, double defMax)
 {
+  const SGPropertyNode * expression = configNode->getNode( "expression" );
+  if( expression != NULL )
+    return SGReadDoubleExpression( modelRoot, expression->getChild(0) );
+
   SGExpression<double>* value = 0;
 
   std::string inputPropertyName = configNode->getStringValue("property", "");
@@ -376,14 +386,24 @@ SGAnimation::SGAnimation(const SGPropertyNode* configNode,
 
 SGAnimation::~SGAnimation()
 {
-  if (_found)
-    return;
-
-  SG_LOG(SG_IO, SG_ALERT, "Could not find at least one of the following"
-         " objects for animation:\n");
-  std::list<std::string>::const_iterator i;
-  for (i = _objectNames.begin(); i != _objectNames.end(); ++i)
-    SG_LOG(SG_IO, SG_ALERT, *i << "\n");
+  if (!_found)
+  {
+      std::list<std::string>::const_iterator i;
+      string info;
+      for (i = _objectNames.begin(); i != _objectNames.end(); ++i)
+      {
+          if (!info.empty())
+              info.append(", ");
+          info.append("'");
+          info.append(*i);
+          info.append("'");
+      }
+      if (!info.empty())
+      {
+          SG_LOG(SG_IO, SG_ALERT, "Could not find at least one of the following"
+                  " objects for animation: " << info);
+      }
+  }
 }
 
 bool
@@ -1445,25 +1465,6 @@ SGRangeAnimation::createAnimationGroup(osg::Group& parent)
 // Implementation of a select animation
 ////////////////////////////////////////////////////////////////////////
 
-class SGSelectAnimation::UpdateCallback : public osg::NodeCallback {
-public:
-  UpdateCallback(const SGCondition* condition) :
-    _condition(condition)
-  {}
-  virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
-  {
-    osg::Switch* sw = static_cast<osg::Switch*>(node);
-    if (_condition->test())
-      sw->setAllChildrenOn();
-    else
-      sw->setAllChildrenOff();
-    traverse(node, nv);
-  }
-
-private:
-  SGSharedPtr<SGCondition const> _condition;
-};
-
 SGSelectAnimation::SGSelectAnimation(const SGPropertyNode* configNode,
                                      SGPropertyNode* modelRoot) :
   SGAnimation(configNode, modelRoot)
@@ -1479,12 +1480,13 @@ SGSelectAnimation::createAnimationGroup(osg::Group& parent)
   // when the animation installer returns
   if (!condition)
     return new osg::Group;
-
-  osg::Switch* sw = new osg::Switch;
-  sw->setName("select animation node");
-  sw->setUpdateCallback(new UpdateCallback(condition));
-  parent.addChild(sw);
-  return sw;
+  simgear::ConditionNode* cn = new simgear::ConditionNode;
+  cn->setName("select animation node");
+  cn->setCondition(condition.ptr());
+  osg::Group* grp = new osg::Group;
+  cn->addChild(grp);
+  parent.addChild(cn);
+  return grp;
 }
 
 
@@ -2098,7 +2100,7 @@ public:
   virtual bool buttonPressed(int button, const Info&)
   {
     bool found = false;
-    for( std::vector<int>::iterator it = _buttons.begin(); it != _buttons.end(); it++ ) {
+    for( std::vector<int>::iterator it = _buttons.begin(); it != _buttons.end(); ++it ) {
       if( *it == button ) {
         found = true;
         break;
@@ -2276,6 +2278,12 @@ SGPickAnimation::SGPickAnimation(const SGPropertyNode* configNode,
 {
 }
 
+namespace
+{
+Mutex colorModeUniformMutex;
+osg::ref_ptr<osg::Uniform> colorModeUniform;
+}
+
 osg::Group*
 SGPickAnimation::createAnimationGroup(osg::Group& parent)
 {
@@ -2306,28 +2314,52 @@ SGPickAnimation::createAnimationGroup(osg::Group& parent)
       &parent));
 
   // prepare a state set that paints the edges of this object yellow
+  // The material and texture attributes are set with
+  // OVERRIDE|PROTECTED in case there is a material animation on a
+  // higher node in the scene graph, which would have its material
+  // attribute set with OVERRIDE.
   osg::StateSet* stateSet = highlightGroup->getOrCreateStateSet();
-  stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE);
-
+  osg::Texture2D* white = StateAttributeFactory::instance()->getWhiteTexture();
+  stateSet->setTextureAttributeAndModes(0, white,
+                                        (osg::StateAttribute::ON
+                                         | osg::StateAttribute::OVERRIDE
+                                         | osg::StateAttribute::PROTECTED));
   osg::PolygonOffset* polygonOffset = new osg::PolygonOffset;
   polygonOffset->setFactor(-1);
   polygonOffset->setUnits(-1);
   stateSet->setAttribute(polygonOffset, osg::StateAttribute::OVERRIDE);
-  stateSet->setMode(GL_POLYGON_OFFSET_LINE, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
-
+  stateSet->setMode(GL_POLYGON_OFFSET_LINE,
+                    osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
   osg::PolygonMode* polygonMode = new osg::PolygonMode;
   polygonMode->setMode(osg::PolygonMode::FRONT_AND_BACK,
                        osg::PolygonMode::LINE);
   stateSet->setAttribute(polygonMode, osg::StateAttribute::OVERRIDE);
-  
   osg::Material* material = new osg::Material;
   material->setColorMode(osg::Material::OFF);
-  material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(1, 1, 0, 1));
-  material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(1, 1, 0, 1));
+  material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(0, 0, 0, 1));
+  // XXX Alpha < 1.0 in the diffuse material value is a signal to the
+  // default shader to take the alpha value from the material value
+  // and not the glColor. In many cases the pick animation geometry is
+  // transparent, so the outline would not be visible without this hack.
+  material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(0, 0, 0, .95));
   material->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4f(1, 1, 0, 1));
   material->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(0, 0, 0, 0));
-  stateSet->setAttribute(material, osg::StateAttribute::OVERRIDE);
-
+  stateSet->setAttribute(
+      material, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED);
+  // The default shader has a colorMode uniform that mimics the
+  // behavior of Material color mode.
+  osg::Uniform* cmUniform = 0;
+  {
+      ScopedLock<Mutex> lock(colorModeUniformMutex);
+      if (!colorModeUniform.valid()) {
+          colorModeUniform = new osg::Uniform(osg::Uniform::INT, "colorMode");
+          colorModeUniform->set(0); // MODE_OFF
+          colorModeUniform->setDataVariance(osg::Object::STATIC);
+      }
+      cmUniform = colorModeUniform.get();
+  }
+  stateSet->addUniform(cmUniform,
+                       osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
   // Only add normal geometry if configured
   if (getConfig()->getBoolValue("visible", true))
     parent.addChild(normalGroup.get());