SGClipGroup.hxx
SGInteractionAnimation.hxx
SGMaterialAnimation.hxx
+ SGPickAnimation.hxx
SGOffsetTransform.hxx
SGReaderWriterXML.hxx
SGRotateTransform.hxx
SGClipGroup.cxx
SGInteractionAnimation.cxx
SGLightAnimation.cxx
+ SGPickAnimation.cxx
SGMaterialAnimation.cxx
SGOffsetTransform.cxx
SGReaderWriterXML.cxx
--- /dev/null
+/* -*-c++-*-
+ *
+ * Copyright (C) 2013 James Turner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+
+#include <simgear/scene/model/SGPickAnimation.hxx>
+
+#include <osg/Geode>
+#include <osg/PolygonOffset>
+#include <osg/PolygonMode>
+#include <osg/Material>
+
+#include <simgear/scene/material/EffectGeode.hxx>
+#include <simgear/scene/util/SGPickCallback.hxx>
+#include <simgear/scene/util/SGSceneUserData.hxx>
+#include <simgear/structure/SGBinding.hxx>
+#include <simgear/scene/util/StateAttributeFactory.hxx>
+
+using namespace simgear;
+
+using OpenThreads::Mutex;
+using OpenThreads::ScopedLock;
+
+ class SGPickAnimation::PickCallback : public SGPickCallback {
+ public:
+ PickCallback(const SGPropertyNode* configNode,
+ SGPropertyNode* modelRoot) :
+ _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));
+ }
+
+ const SGPropertyNode* upNode = configNode->getChild("mod-up");
+ if (!upNode)
+ return;
+ bindings = upNode->getChildren("binding");
+ for (unsigned int i = 0; i < bindings.size(); ++i) {
+ _bindingsUp.push_back(new SGBinding(bindings[i], modelRoot));
+ }
+ }
+ virtual bool buttonPressed(int button, const Info&)
+ {
+ 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 = -_repeatInterval; // anti-bobble: delay start of repeat
+ return true;
+ }
+ virtual void buttonReleased(void)
+ {
+ SGBindingList::const_iterator i;
+ for (i = _bindingsUp.begin(); i != _bindingsUp.end(); ++i)
+ (*i)->fire();
+ }
+ virtual void update(double dt)
+ {
+ if (!_repeatable)
+ return;
+
+ _repeatTime += dt;
+ while (_repeatInterval < _repeatTime) {
+ _repeatTime -= _repeatInterval;
+ SGBindingList::const_iterator i;
+ for (i = _bindingsDown.begin(); i != _bindingsDown.end(); ++i)
+ (*i)->fire();
+ }
+ }
+ private:
+ SGBindingList _bindingsDown;
+ SGBindingList _bindingsUp;
+ std::vector<int> _buttons;
+ bool _repeatable;
+ double _repeatInterval;
+ double _repeatTime;
+ };
+
+ class VncVisitor : public osg::NodeVisitor {
+ public:
+ VncVisitor(double x, double y, int mask) :
+ osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
+ _texX(x), _texY(y), _mask(mask), _done(false)
+ {
+ SG_LOG(SG_INPUT, SG_DEBUG, "VncVisitor constructor "
+ << x << "," << y << " mask " << mask);
+ }
+
+ virtual void apply(osg::Node &node)
+ {
+ // Some nodes have state sets attached
+ touchStateSet(node.getStateSet());
+ if (!_done)
+ traverse(node);
+ if (_done) return;
+ // See whether we are a geode worth exploring
+ osg::Geode *g = dynamic_cast<osg::Geode*>(&node);
+ if (!g) return;
+ // Go find all its drawables
+ int i = g->getNumDrawables();
+ while (--i >= 0) {
+ osg::Drawable *d = g->getDrawable(i);
+ if (d) touchDrawable(*d);
+ }
+ // Out of optimism, do the same for EffectGeode
+ simgear::EffectGeode *eg = dynamic_cast<simgear::EffectGeode*>(&node);
+ if (!eg) return;
+ for (simgear::EffectGeode::DrawablesIterator di = eg->drawablesBegin();
+ di != eg->drawablesEnd(); di++) {
+ touchDrawable(**di);
+ }
+ // Now see whether the EffectGeode has an Effect
+ simgear::Effect *e = eg->getEffect();
+ if (e) {
+ touchStateSet(e->getDefaultStateSet());
+ }
+ }
+
+ inline void touchDrawable(osg::Drawable &d)
+ {
+ osg::StateSet *ss = d.getStateSet();
+ touchStateSet(ss);
+ }
+
+ void touchStateSet(osg::StateSet *ss)
+ {
+ if (!ss) return;
+ osg::StateAttribute *sa = ss->getTextureAttribute(0,
+ osg::StateAttribute::TEXTURE);
+ if (!sa) return;
+ osg::Texture *t = sa->asTexture();
+ if (!t) return;
+ osg::Image *img = t->getImage(0);
+ if (!img) return;
+ if (!_done) {
+ int pixX = _texX * img->s();
+ int pixY = _texY * img->t();
+ _done = img->sendPointerEvent(pixX, pixY, _mask);
+ SG_LOG(SG_INPUT, SG_DEBUG, "VncVisitor image said " << _done
+ << " to coord " << pixX << "," << pixY);
+ }
+ }
+
+ inline bool wasSuccessful()
+ {
+ return _done;
+ }
+
+ private:
+ double _texX, _texY;
+ int _mask;
+ bool _done;
+ };
+
+
+ class SGPickAnimation::VncCallback : public SGPickCallback {
+ public:
+ VncCallback(const SGPropertyNode* configNode,
+ SGPropertyNode* modelRoot,
+ osg::Group *node)
+ : _node(node)
+ {
+ SG_LOG(SG_INPUT, SG_DEBUG, "Configuring VNC callback");
+ const char *cornernames[3] = {"top-left", "top-right", "bottom-left"};
+ SGVec3d *cornercoords[3] = {&_topLeft, &_toRight, &_toDown};
+ for (int c =0; c < 3; c++) {
+ const SGPropertyNode* cornerNode = configNode->getChild(cornernames[c]);
+ *cornercoords[c] = SGVec3d(
+ cornerNode->getDoubleValue("x"),
+ cornerNode->getDoubleValue("y"),
+ cornerNode->getDoubleValue("z"));
+ }
+ _toRight -= _topLeft;
+ _toDown -= _topLeft;
+ _squaredRight = dot(_toRight, _toRight);
+ _squaredDown = dot(_toDown, _toDown);
+ }
+
+ virtual bool buttonPressed(int button, const Info& info)
+ {
+ SGVec3d loc(info.local);
+ SG_LOG(SG_INPUT, SG_DEBUG, "VNC pressed " << button << ": " << loc);
+ loc -= _topLeft;
+ _x = dot(loc, _toRight) / _squaredRight;
+ _y = dot(loc, _toDown) / _squaredDown;
+ if (_x<0) _x = 0; else if (_x > 1) _x = 1;
+ if (_y<0) _y = 0; else if (_y > 1) _y = 1;
+ VncVisitor vv(_x, _y, 1 << button);
+ _node->accept(vv);
+ return vv.wasSuccessful();
+
+ }
+ virtual void buttonReleased(void)
+ {
+ SG_LOG(SG_INPUT, SG_DEBUG, "VNC release");
+ VncVisitor vv(_x, _y, 0);
+ _node->accept(vv);
+ }
+ virtual void update(double dt)
+ {
+ }
+ private:
+ double _x, _y;
+ osg::ref_ptr<osg::Group> _node;
+ SGVec3d _topLeft, _toRight, _toDown;
+ double _squaredRight, _squaredDown;
+ };
+
+ SGPickAnimation::SGPickAnimation(const SGPropertyNode* configNode,
+ SGPropertyNode* modelRoot) :
+ SGAnimation(configNode, modelRoot)
+ {
+ }
+
+ namespace
+ {
+ OpenThreads::Mutex colorModeUniformMutex;
+ osg::ref_ptr<osg::Uniform> colorModeUniform;
+ }
+
+ osg::Group*
+ SGPickAnimation::createAnimationGroup(osg::Group& parent)
+ {
+ osg::Group* commonGroup = new osg::Group;
+
+ // 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(simgear::PICK_BIT);
+ highlightGroup->addChild(commonGroup);
+ SGSceneUserData* ud;
+ ud = SGSceneUserData::getOrCreateSceneUserData(commonGroup);
+
+ // add actions that become macro and command invocations
+ std::vector<SGPropertyNode_ptr> actions;
+ actions = getConfig()->getChildren("action");
+ for (unsigned int i = 0; i < actions.size(); ++i)
+ ud->addPickCallback(new PickCallback(actions[i], getModelRoot()));
+ // Look for the VNC sessions that want raw mouse input
+ actions = getConfig()->getChildren("vncaction");
+ for (unsigned int i = 0; i < actions.size(); ++i)
+ ud->addPickCallback(new VncCallback(actions[i], getModelRoot(),
+ &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();
+ 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);
+ 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(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 | 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());
+ parent.addChild(highlightGroup);
+
+
+ return commonGroup;
+}
+
\ No newline at end of file
--- /dev/null
+/* -*-c++-*-
+ *
+ * Copyright (C) 2013 James Turner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SG_SCENE_PICK_ANIMATION_HXX
+#define SG_SCENE_PICK_ANIMATION_HXX
+
+#include <simgear/scene/model/animation.hxx>
+
+
+//////////////////////////////////////////////////////////////////////
+// Pick animation
+//////////////////////////////////////////////////////////////////////
+
+class SGPickAnimation : public SGAnimation {
+public:
+ SGPickAnimation(const SGPropertyNode* configNode,
+ SGPropertyNode* modelRoot);
+ virtual osg::Group* createAnimationGroup(osg::Group& parent);
+private:
+ class PickCallback;
+ class VncCallback;
+};
+
+#endif // of SG_SCENE_PICK_ANIMATION_HXX
+
#include <osg/LOD>
#include <osg/Math>
#include <osg/Object>
-#include <osg/PolygonMode>
-#include <osg/PolygonOffset>
#include <osg/StateSet>
#include <osg/Switch>
#include <osg/TexMat>
#include <simgear/math/interpolater.hxx>
#include <simgear/props/condition.hxx>
#include <simgear/props/props.hxx>
-#include <simgear/structure/SGBinding.hxx>
#include <simgear/scene/material/EffectGeode.hxx>
#include <simgear/scene/material/EffectCullVisitor.hxx>
#include <simgear/scene/util/DeletionManager.hxx>
#include "SGRotateTransform.hxx"
#include "SGScaleTransform.hxx"
#include "SGInteractionAnimation.hxx"
+#include "SGPickAnimation.hxx"
#include "ConditionNode.hxx"
updateCallback->appendTransform(rotation, value);
}
-
-////////////////////////////////////////////////////////////////////////
-// Implementation of SGPickAnimation
-////////////////////////////////////////////////////////////////////////
-
-class SGPickAnimation::PickCallback : public SGPickCallback {
-public:
- PickCallback(const SGPropertyNode* configNode,
- SGPropertyNode* modelRoot) :
- _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));
- }
-
- const SGPropertyNode* upNode = configNode->getChild("mod-up");
- if (!upNode)
- return;
- bindings = upNode->getChildren("binding");
- for (unsigned int i = 0; i < bindings.size(); ++i) {
- _bindingsUp.push_back(new SGBinding(bindings[i], modelRoot));
- }
- }
- virtual bool buttonPressed(int button, const Info&)
- {
- 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 = -_repeatInterval; // anti-bobble: delay start of repeat
- return true;
- }
- virtual void buttonReleased(void)
- {
- SGBindingList::const_iterator i;
- for (i = _bindingsUp.begin(); i != _bindingsUp.end(); ++i)
- (*i)->fire();
- }
- virtual void update(double dt)
- {
- if (!_repeatable)
- return;
-
- _repeatTime += dt;
- while (_repeatInterval < _repeatTime) {
- _repeatTime -= _repeatInterval;
- SGBindingList::const_iterator i;
- for (i = _bindingsDown.begin(); i != _bindingsDown.end(); ++i)
- (*i)->fire();
- }
- }
-private:
- SGBindingList _bindingsDown;
- SGBindingList _bindingsUp;
- std::vector<int> _buttons;
- bool _repeatable;
- double _repeatInterval;
- double _repeatTime;
-};
-
-class VncVisitor : public osg::NodeVisitor {
- public:
- VncVisitor(double x, double y, int mask) :
- osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
- _texX(x), _texY(y), _mask(mask), _done(false)
- {
- SG_LOG(SG_INPUT, SG_DEBUG, "VncVisitor constructor "
- << x << "," << y << " mask " << mask);
- }
-
- virtual void apply(osg::Node &node)
- {
- // Some nodes have state sets attached
- touchStateSet(node.getStateSet());
- if (!_done)
- traverse(node);
- if (_done) return;
- // See whether we are a geode worth exploring
- osg::Geode *g = dynamic_cast<osg::Geode*>(&node);
- if (!g) return;
- // Go find all its drawables
- int i = g->getNumDrawables();
- while (--i >= 0) {
- osg::Drawable *d = g->getDrawable(i);
- if (d) touchDrawable(*d);
- }
- // Out of optimism, do the same for EffectGeode
- simgear::EffectGeode *eg = dynamic_cast<simgear::EffectGeode*>(&node);
- if (!eg) return;
- for (simgear::EffectGeode::DrawablesIterator di = eg->drawablesBegin();
- di != eg->drawablesEnd(); di++) {
- touchDrawable(**di);
- }
- // Now see whether the EffectGeode has an Effect
- simgear::Effect *e = eg->getEffect();
- if (e) {
- touchStateSet(e->getDefaultStateSet());
- }
- }
-
- inline void touchDrawable(osg::Drawable &d)
- {
- osg::StateSet *ss = d.getStateSet();
- touchStateSet(ss);
- }
-
- void touchStateSet(osg::StateSet *ss)
- {
- if (!ss) return;
- osg::StateAttribute *sa = ss->getTextureAttribute(0,
- osg::StateAttribute::TEXTURE);
- if (!sa) return;
- osg::Texture *t = sa->asTexture();
- if (!t) return;
- osg::Image *img = t->getImage(0);
- if (!img) return;
- if (!_done) {
- int pixX = _texX * img->s();
- int pixY = _texY * img->t();
- _done = img->sendPointerEvent(pixX, pixY, _mask);
- SG_LOG(SG_INPUT, SG_DEBUG, "VncVisitor image said " << _done
- << " to coord " << pixX << "," << pixY);
- }
- }
-
- inline bool wasSuccessful()
- {
- return _done;
- }
-
- private:
- double _texX, _texY;
- int _mask;
- bool _done;
-};
-
-
-class SGPickAnimation::VncCallback : public SGPickCallback {
-public:
- VncCallback(const SGPropertyNode* configNode,
- SGPropertyNode* modelRoot,
- osg::Group *node)
- : _node(node)
- {
- SG_LOG(SG_INPUT, SG_DEBUG, "Configuring VNC callback");
- const char *cornernames[3] = {"top-left", "top-right", "bottom-left"};
- SGVec3d *cornercoords[3] = {&_topLeft, &_toRight, &_toDown};
- for (int c =0; c < 3; c++) {
- const SGPropertyNode* cornerNode = configNode->getChild(cornernames[c]);
- *cornercoords[c] = SGVec3d(
- cornerNode->getDoubleValue("x"),
- cornerNode->getDoubleValue("y"),
- cornerNode->getDoubleValue("z"));
- }
- _toRight -= _topLeft;
- _toDown -= _topLeft;
- _squaredRight = dot(_toRight, _toRight);
- _squaredDown = dot(_toDown, _toDown);
- }
-
- virtual bool buttonPressed(int button, const Info& info)
- {
- SGVec3d loc(info.local);
- SG_LOG(SG_INPUT, SG_DEBUG, "VNC pressed " << button << ": " << loc);
- loc -= _topLeft;
- _x = dot(loc, _toRight) / _squaredRight;
- _y = dot(loc, _toDown) / _squaredDown;
- if (_x<0) _x = 0; else if (_x > 1) _x = 1;
- if (_y<0) _y = 0; else if (_y > 1) _y = 1;
- VncVisitor vv(_x, _y, 1 << button);
- _node->accept(vv);
- return vv.wasSuccessful();
-
- }
- virtual void buttonReleased(void)
- {
- SG_LOG(SG_INPUT, SG_DEBUG, "VNC release");
- VncVisitor vv(_x, _y, 0);
- _node->accept(vv);
- }
- virtual void update(double dt)
- {
- }
-private:
- double _x, _y;
- osg::ref_ptr<osg::Group> _node;
- SGVec3d _topLeft, _toRight, _toDown;
- double _squaredRight, _squaredDown;
-};
-
-SGPickAnimation::SGPickAnimation(const SGPropertyNode* configNode,
- SGPropertyNode* modelRoot) :
- SGAnimation(configNode, modelRoot)
-{
-}
-
-namespace
-{
-Mutex colorModeUniformMutex;
-osg::ref_ptr<osg::Uniform> colorModeUniform;
-}
-
-osg::Group*
-SGPickAnimation::createAnimationGroup(osg::Group& parent)
-{
- osg::Group* commonGroup = new osg::Group;
-
- // 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(commonGroup);
-
- // add actions that become macro and command invocations
- std::vector<SGPropertyNode_ptr> actions;
- actions = getConfig()->getChildren("action");
- for (unsigned int i = 0; i < actions.size(); ++i)
- ud->addPickCallback(new PickCallback(actions[i], getModelRoot()));
- // Look for the VNC sessions that want raw mouse input
- actions = getConfig()->getChildren("vncaction");
- for (unsigned int i = 0; i < actions.size(); ++i)
- ud->addPickCallback(new VncCallback(actions[i], getModelRoot(),
- &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();
- 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);
- 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(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 | 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());
- parent.addChild(highlightGroup);
-
- return commonGroup;
-}
class UpdateCallback;
osg::ref_ptr<osg::Texture2D> _effect_texture;
};
-
-\f
-//////////////////////////////////////////////////////////////////////
-// Pick animation
-//////////////////////////////////////////////////////////////////////
-
-class SGPickAnimation : public SGAnimation {
-public:
- SGPickAnimation(const SGPropertyNode* configNode,
- SGPropertyNode* modelRoot);
- virtual osg::Group* createAnimationGroup(osg::Group& parent);
-private:
- class PickCallback;
- class VncCallback;
-};
-
\f
//////////////////////////////////////////////////////////////////////
// Light animation