/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 
 *
 * This library is open source and may be redistributed and/or modified under  
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 * 
 * This library 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 
 * OpenSceneGraph Public License for more details.
*/

#ifndef OSGSIM_OVERLAYNODE
#define OSGSIM_OVERLAYNODE 1

#include <osg/buffered_value>
#include <osg/CameraNode>
#include <osg/Texture2D>
#include <osg/TexGenNode>

#include <osgSim/Export>

namespace osgSim {

/** OverlayNode is for creating texture overlays on scenes, with the overlay texture being generated
  * by pre rendering an Overlay Subgraph to a texture, then projecting this resulting texture on the scene.*/
class OSGSIM_EXPORT OverlayNode : public osg::Group
{
    public :
        OverlayNode();

        OverlayNode(const OverlayNode& es, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
            
        META_Node(osgSim, OverlayNode);
        
        virtual void traverse(osg::NodeVisitor& nv);

        /** Set the overlay subgraph which will be rendered to texture.*/
        void setOverlaySubgraph(osg::Node* node);
        
        /** Get the overlay subgraph which will be rendered to texture.*/
        osg::Node* getOverlaySubgraph() { return _overlaySubgraph.get(); }

        /** Get the const overlay subgraph which will be render to texture.*/
        const osg::Node* getOverlaySubgraph() const { return _overlaySubgraph.get(); }
        

        /** Inform the OverlayNode that the overlay texture needs to be updated.*/
        void dirtyOverlayTexture();
        
        /** Set whether the OverlayNode should update the overlay texture on every frame.*/
        void setContinuousUpdate(bool update) { _continuousUpdate = update; }

        /** Get whether the OverlayNode should update the overlay texture on every frame.*/
        bool getContinuousUpdate() const { return _continuousUpdate; }


        /** Set the clear color to use when rendering the overlay subgraph.*/
        void setOverlayClearColor(const osg::Vec4& color);

        /** Get the clear color to use when rendering the overlay subgraph.*/
        const osg::Vec4& getOverlayClearColor() const;

        /** Set the TexEnv mode used to combine the overlay texture with the base color/texture of the OverlayNode's decorate subgraph.*/
        void setTexEnvMode(GLenum mode);
        
        /** Get the TexEnv mode used to combine the overlay texture with the base color/texture of the OverlayNode's decorate subgraph.*/
        GLenum getTexEnvMode() const { return _texEnvMode; }

        /** Set the texture unit that the texture should be assigned to.*/
        void setOverlayTextureUnit(unsigned int unit);

        /** Get the texture unit that the texture should be assigned to.*/
        unsigned int getOverlayTextureUnit() const { return _textureUnit; }
        
        /** Set the texture size hint. The size hint is used to request a texture of specified size.*/
        void setOverlayTextureSizeHint(unsigned int size);

        /** Get the texture size hint.*/
        unsigned int getOverlayTextureSizeHint() const { return _textureSizeHint; }
        

        /** Get the camera used to implement the render to texture of the overlay subgraph.*/
        osg::CameraNode* getCamera() { return _camera.get(); }

        /** Get the const camera used to implement the render to texture of the overlay subgraph.*/
        const osg::CameraNode* getCamera() const { return _camera.get(); }
        
    protected :

        virtual ~OverlayNode() {}
        
        void init();
        
        void updateMainSubgraphStateSet();

        typedef osg::buffered_value< int > TextureObjectValidList;
        
        mutable TextureObjectValidList _textureObjectValidList;

        osg::ref_ptr<osg::CameraNode>   _camera;
        
        // overlay subgraph is render to a texture
        osg::ref_ptr<osg::Node>         _overlaySubgraph;
        
        // texgen node to generate the tex coordinates for us
        osg::ref_ptr<osg::TexGenNode>   _texgenNode;
        
        // state set to decoate the main subgraph.
        osg::ref_ptr<osg::StateSet>     _mainSubgraphStateSet;
        
        // texture to render to, and to read from.
        GLenum                          _texEnvMode;
        unsigned int                    _textureUnit;
        unsigned int                    _textureSizeHint;
        osg::ref_ptr<osg::Texture2D>    _texture;

        bool                            _continuousUpdate;
        osg::Polytope                   _textureFrustum;
};

}

#endif
