#include <osg/Geometry>
#include <osg/LOD>
#include <osg/Math>
+#include <osg/Object>
#include <osg/PolygonMode>
#include <osg/PolygonOffset>
#include <osg/StateSet>
#include <osg/TexMat>
#include <osg/Texture2D>
#include <osg/Transform>
+#include <osg/Uniform>
#include <osgDB/ReadFile>
#include <osgDB/Registry>
#include <osgDB/Input>
#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.
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", "");
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
// 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)
// 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;
}
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;
{
}
+namespace
+{
+Mutex colorModeUniformMutex;
+osg::ref_ptr<osg::Uniform> colorModeUniform;
+}
+
osg::Group*
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());