#include <osgDB/FileNameUtils>
+#include <simgear/canvas/CanvasObjectPlacement.hxx>
#include <simgear/scene/material/EffectGeode.hxx>
#include <simgear/scene/util/RenderConstants.hxx>
#include <Main/globals.hxx>
-#include <Viewer/renderer.hxx>
#include <Scenery/scenery.hxx>
#include "od_gauge.hxx"
#include <cassert>
//------------------------------------------------------------------------------
-FGODGauge::FGODGauge():
- _size_x( -1 ),
- _size_y( -1 ),
- _view_width( -1 ),
- _view_height( -1 ),
- _use_image_coords( false ),
- _use_stencil( false ),
- _use_mipmapping( false ),
- _coverage_samples( 0 ),
- _color_samples( 0 ),
- rtAvailable( false )
+FGODGauge::FGODGauge()
{
-}
-
-//------------------------------------------------------------------------------
-FGODGauge::~FGODGauge()
-{
- if( camera.valid() )
- globals->get_renderer()->removeCamera(camera.get());
-}
-
-//------------------------------------------------------------------------------
-void FGODGauge::setSize(int size_x, int size_y)
-{
- _size_x = size_x;
- _size_y = size_y < 0 ? size_x : size_y;
-
- if( texture.valid() )
- texture->setTextureSize(_size_x, _size_x);
-}
-
-//----------------------------------------------------------------------------
-void FGODGauge::setViewSize(int width, int height)
-{
- _view_width = width;
- _view_height = height < 0 ? width : height;
-
- if( camera )
- updateCoordinateFrame();
-}
-
-//------------------------------------------------------------------------------
-void FGODGauge::useImageCoords(bool use)
-{
- if( use == _use_image_coords )
- return;
-
- _use_image_coords = use;
-
- if( texture )
- updateCoordinateFrame();
-}
-//------------------------------------------------------------------------------
-void FGODGauge::useStencil(bool use)
-{
- if( use == _use_stencil )
- return;
-
- _use_stencil = use;
-
- if( texture )
- updateStencil();
}
//------------------------------------------------------------------------------
-void FGODGauge::setSampling( bool mipmapping,
- int coverage_samples,
- int color_samples )
-{
- if( _use_mipmapping == mipmapping
- && _coverage_samples == coverage_samples
- && _color_samples == color_samples )
- return;
-
- _use_mipmapping = mipmapping;
-
- if( color_samples > coverage_samples )
- {
- SG_LOG
- (
- SG_GL,
- SG_WARN,
- "FGODGauge::setSampling: color_samples > coverage_samples not allowed!"
- );
- color_samples = coverage_samples;
- }
-
- _coverage_samples = coverage_samples;
- _color_samples = color_samples;
-
- updateSampling();
-}
-
-//------------------------------------------------------------------------------
-void FGODGauge::setRender(bool render)
-{
- // Only the far camera should trigger this texture to be rendered.
- camera->setNodeMask(render ? simgear::BACKGROUND_BIT : 0);
-}
-
-//------------------------------------------------------------------------------
-bool FGODGauge::serviceable(void)
-{
- return rtAvailable;
-}
-
-//------------------------------------------------------------------------------
-void FGODGauge::allocRT(osg::NodeCallback* camera_cull_callback)
-{
- camera = new osg::Camera;
- camera->setDataVariance(osg::Object::DYNAMIC);
- camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
- camera->setRenderOrder(osg::Camera::PRE_RENDER);
- camera->setClearColor(osg::Vec4(0.0f, 0.0f, 0.0f , 0.0f));
- camera->setClearStencil(0);
- camera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT,
- osg::Camera::FRAME_BUFFER );
-
- if( camera_cull_callback )
- camera->setCullCallback(camera_cull_callback);
-
- setRender(true);
- updateCoordinateFrame();
- updateStencil();
-
- osg::StateSet* stateSet = camera->getOrCreateStateSet();
- stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
- stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
- stateSet->setMode(GL_FOG, osg::StateAttribute::OFF);
- stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
- stateSet->setAttributeAndModes(new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK,
- osg::PolygonMode::FILL),
- osg::StateAttribute::ON);
- stateSet->setAttributeAndModes(new osg::AlphaFunc(osg::AlphaFunc::GREATER,
- 0.0f),
- osg::StateAttribute::ON);
- stateSet->setAttribute(new osg::ShadeModel(osg::ShadeModel::FLAT));
- stateSet->setAttributeAndModes(new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA,
- osg::BlendFunc::ONE_MINUS_SRC_ALPHA),
- osg::StateAttribute::ON);
- if( !texture )
- {
- texture = new osg::Texture2D;
- texture->setTextureSize(_size_x, _size_y);
- texture->setInternalFormat(GL_RGBA);
- }
-
- updateSampling();
-
- globals->get_renderer()->addCamera(camera.get(), false);
- rtAvailable = true;
-}
-
-//------------------------------------------------------------------------------
-void FGODGauge::updateCoordinateFrame()
-{
- assert( camera );
-
- if( _view_width < 0 )
- _view_width = _size_x;
- if( _view_height < 0 )
- _view_height = _size_y;
-
- camera->setViewport(0, 0, _size_x, _size_y);
-
- if( _use_image_coords )
- camera->setProjectionMatrix(
- osg::Matrix::ortho2D(0, _view_width, _view_height, 0)
- );
- else
- camera->setProjectionMatrix(
- osg::Matrix::ortho2D( -_view_width/2., _view_width/2.,
- -_view_height/2., _view_height/2. )
- );
-}
-
-//------------------------------------------------------------------------------
-void FGODGauge::updateStencil()
-{
- assert( camera );
-
- GLbitfield mask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
-
- if( _use_stencil)
- {
- camera->attach( osg::Camera::PACKED_DEPTH_STENCIL_BUFFER,
- GL_DEPTH_STENCIL_EXT );
- mask |= GL_STENCIL_BUFFER_BIT;
- }
- else
- {
- camera->detach(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER);
- }
-
- camera->setClearMask(mask);
-}
-
-//------------------------------------------------------------------------------
-void FGODGauge::updateSampling()
+FGODGauge::~FGODGauge()
{
- assert( camera );
- assert( texture );
- texture->setFilter(
- osg::Texture2D::MIN_FILTER,
- _use_mipmapping ? osg::Texture2D::LINEAR_MIPMAP_LINEAR
- : osg::Texture2D::LINEAR
- );
- camera->attach(
- osg::Camera::COLOR_BUFFER,
- texture.get(),
- 0, 0,
- _use_mipmapping,
- _coverage_samples,
- _color_samples
- );
}
/**
{
public:
+ typedef osg::ref_ptr<osg::Group> GroupPtr;
+ typedef osg::ref_ptr<osg::Material> MaterialPtr;
+
ReplaceStaticTextureVisitor( const char* name,
osg::Texture2D* new_texture ):
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
_tex_name( osgDB::getSimpleFileName(name) ),
- _new_texture(new_texture)
+ _new_texture(new_texture),
+ _cull_callback(0)
{}
- ReplaceStaticTextureVisitor( const SGPropertyNode* placement,
+ ReplaceStaticTextureVisitor( SGPropertyNode* placement,
osg::Texture2D* new_texture,
- osg::NodeCallback* cull_callback = 0 ):
+ osg::NodeCallback* cull_callback = 0,
+ const simgear::canvas::CanvasWeakPtr& canvas =
+ simgear::canvas::CanvasWeakPtr() ):
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
_tex_name( osgDB::getSimpleFileName(
placement->getStringValue("texture"))
),
_node_name( placement->getStringValue("node") ),
_parent_name( placement->getStringValue("parent") ),
+ _node(placement),
_new_texture(new_texture),
- _cull_callback(cull_callback)
+ _cull_callback(cull_callback),
+ _canvas(canvas)
{
if( _tex_name.empty()
&& _node_name.empty()
* Get a list of groups which have been inserted into the scene graph to
* replace the given texture
*/
- canvas::Placements& getPlacements()
+ simgear::canvas::Placements& getPlacements()
{
return _placements;
}
return;
osg::Group *parent = node.getParent(0);
- if( !_node_name.empty() && parent->getName() != _node_name )
+ if( !_node_name.empty() && getNodeName(*parent) != _node_name )
return;
if( !_parent_name.empty() )
// insert a new group between the geode an it's parent which overrides
// the texture
- osg::ref_ptr<osg::Group> group = new osg::Group;
+ GroupPtr group = new osg::Group;
group->setName("canvas texture group");
group->addChild(eg);
parent->removeChild(eg);
if( _cull_callback )
group->setCullCallback(_cull_callback);
- _placements.push_back(
- canvas::PlacementPtr(new ObjectPlacement(group))
- );
-
osg::StateSet* stateSet = group->getOrCreateStateSet();
stateSet->setTextureAttribute( unit, _new_texture,
osg::StateAttribute::OVERRIDE );
stateSet->setTextureMode( unit, GL_TEXTURE_2D,
osg::StateAttribute::ON );
+ _placements.push_back( simgear::canvas::PlacementPtr(
+ new simgear::canvas::ObjectPlacement(_node, group, _canvas)
+ ));
+
SG_LOG
(
SG_GL,
protected:
- class ObjectPlacement:
- public canvas::Placement
- {
- public:
- ObjectPlacement(osg::ref_ptr<osg::Group> group):
- _group(group)
- {}
-
- /**
- * Remove placement from the scene
- */
- virtual ~ObjectPlacement()
- {
- assert( _group->getNumChildren() == 1 );
- osg::Node *child = _group->getChild(0);
-
- if( _group->getNumParents() )
- {
- osg::Group *parent = _group->getParent(0);
- parent->addChild(child);
- parent->removeChild(_group);
- }
-
- _group->removeChild(child);
- }
-
- private:
- osg::ref_ptr<osg::Group> _group;
- };
-
std::string _tex_name, ///<! Name of texture to be replaced
_node_name, ///<! Only replace if node name matches
_parent_name; ///<! Only replace if any parent node matches
/// given name (all the tree upwards)
+
+ SGPropertyNode_ptr _node;
osg::Texture2D *_new_texture;
osg::NodeCallback *_cull_callback;
- canvas::Placements _placements;
+ simgear::canvas::CanvasWeakPtr _canvas;
+ simgear::canvas::Placements _placements;
+
+ const std::string& getNodeName(const osg::Node& node) const
+ {
+ if( !node.getName().empty() )
+ return node.getName();
+
+ // Special handling for pick animation which clears the name of the object
+ // and instead sets the name of a parent group with one or two groups
+ // attached (one for normal rendering and one for the picking highlight).
+ osg::Group const* parent = node.getParent(0);
+ if( parent->getName() == "pick render group" )
+ return parent->getParent(0)->getName();
+
+ return node.getName();
+ }
};
//------------------------------------------------------------------------------
-canvas::Placements FGODGauge::set_texture( const char* name,
- osg::Texture2D* new_texture )
+simgear::canvas::Placements
+FGODGauge::set_texture( osg::Node* branch,
+ const char * name,
+ osg::Texture2D* new_texture )
{
- osg::Group* root = globals->get_scenery()->get_aircraft_branch();
ReplaceStaticTextureVisitor visitor(name, new_texture);
- root->accept(visitor);
+ branch->accept(visitor);
return visitor.getPlacements();
}
//------------------------------------------------------------------------------
-canvas::Placements FGODGauge::set_texture( const SGPropertyNode* placement,
- osg::Texture2D* new_texture,
- osg::NodeCallback* cull_callback )
+simgear::canvas::Placements
+FGODGauge::set_aircraft_texture( const char* name,
+ osg::Texture2D* new_texture )
+{
+ return set_texture
+ (
+ globals->get_scenery()->get_aircraft_branch(),
+ name,
+ new_texture
+ );
+}
+
+//------------------------------------------------------------------------------
+simgear::canvas::Placements
+FGODGauge::set_texture( osg::Node* branch,
+ SGPropertyNode* placement,
+ osg::Texture2D* new_texture,
+ osg::NodeCallback* cull_callback,
+ const simgear::canvas::CanvasWeakPtr& canvas )
{
- osg::Group* root = globals->get_scenery()->get_aircraft_branch();
- ReplaceStaticTextureVisitor visitor(placement, new_texture, cull_callback);
- root->accept(visitor);
+ ReplaceStaticTextureVisitor visitor( placement,
+ new_texture,
+ cull_callback,
+ canvas );
+ branch->accept(visitor);
return visitor.getPlacements();
}
+
+//------------------------------------------------------------------------------
+simgear::canvas::Placements
+FGODGauge::set_aircraft_texture( SGPropertyNode* placement,
+ osg::Texture2D* new_texture,
+ osg::NodeCallback* cull_callback,
+ const simgear::canvas::CanvasWeakPtr& canvas )
+{
+ return set_texture
+ (
+ globals->get_scenery()->get_aircraft_branch(),
+ placement,
+ new_texture,
+ cull_callback,
+ canvas
+ );
+}