/*****************************************************************************
 * $LastChangedDate: 2011-04-09 21:58:06 -0400 (Sat, 09 Apr 2011) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   SceneGraph class.
 *//*
 * LEGAL:   COPYRIGHT (C) 2009 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#ifndef GRAPH_SCENE_GRAPH_HH
#define GRAPH_SCENE_GRAPH_HH 1

#define GET_SCENE_GRAPH() (SceneGraph::GetInstance())

#include "base/singleton.hh"
using namespace base;
#include "gfx/rgba.hh"
using namespace gfx;
namespace object { class Object; }
namespace graph { class NodeSort; }
#include "graph/base_scene_graph.hh"
#include <osg/PolygonMode>

namespace graph {

////////////////////////////////////////////////////////////////////////////////
/// @brief SceneGraph class contains nodes.
/// @verbatim
///                     +------------+
///                     | root node  |
///                 +---+------------+--+
///                 |        |          |
///                 |        |          |
///          +--------+  +--------+  +--------+
///          | branch |  | branch |  | branch |
///          |  node  |  |  node  |  |  node  |
///          | default|  |  [1]   |  |  [2]   |
///          +--------+  +--------+  +--------+
/// @endverbatim
///
/// This arrangement circumvents OSG's rule of allowing child nodes
/// to override similar state of its parent which wouldn't be restored
/// after traversal crosses over to a sibling node.
///
/// Different ways to attach a node:
/// --------------------------------
/// AttachNode( RefPtr<Node> node );
/// Attach node under branch node having default state.
///
/// AttachNode( RefPtr<Node> node, const NodeSort& nodeSort );
/// Attach node under a branch node having state defined by NodeSort.
/// NodeSort defines typical graphical-state such as transparency.
/// SceneGraph creates and caches branch nodes mapped by NodeSort.
///
/// AttachBranchNode( RefPtr<GroupNode> branchNode );
/// For flexibility, allow client to externally create its own branch node
/// having special state.  Client would then attach geometry under it.
///
/// State-sorting responsibility:
/// -----------------------------
/// Nodes with a default graphical state can be attached to the root node.
/// If other graphical state is needed, the users of SceneGraph
/// are responsible for placing nodes sharing a graphical state
/// under a branch node which the user creates.
///
/// Implementation:
/// ---------------
/// SceneGraph is a singleton that provides the public interface.
/// SceneGraph _is_ a BaseSceneGraph and _has_ a ShadowSceneGraph.
/// Some base methods are overridden to fork operations to both.
///
/// Shadows:
/// --------
/// Though not obvious, shadows are supported.
/// Attach shadow casters using NodeSort(SHADOW_CASTER)
/// and shadow receivers using NodeSort(SHADOW_RECEIVER).
///
class SceneGraph : public BaseSceneGraph
{
PREVENT_COPYING(SceneGraph)
private:
                                SceneGraph( void );
    virtual                     ~SceneGraph();
    void                        ArrangeNodes( void );

// Public interface:
public:
                                DEFINE_GetInstance( SceneGraph )  // Singleton
    virtual void                AttachNode( RefPtr<Node> node, const NodeSort& nodeSort );
    void                        AttachNode( RefPtr<Node> node );  // specific
    virtual void                AttachObject( shptr<Object> object, const NodeSort& nodeSort );
    void                        AttachObject( shptr<Object> object );  // specific
    virtual void                DetachNode( RefPtr<Node> node );
    virtual void                DetachObject( shptr<Object> object );
    virtual bool                IfNodeAttached( Node& node );
    virtual bool                IfObjectAttached( shptr<Object> object );
    virtual void                Flush( void );

// Public interface (specific or special modes):
    void                        Optimize( void ); 
    void                        SetBackgroundColor( const RGBA color );
    void                        EnableWireframeMode( const bool enable );
    void                        ToggleWireframeMode( void );
    void                        SaveToFile( const string& filename, const bool useCompression );

// Data members:
private:
    CLASS_VAR SceneGraph*       msInstance;         ///< SceneGraph is a singleton
    RefPtr<osg::ClearNode>      mClearNode;         ///< to get root node, use BaseSceneGraph::GetRootNode()
    RefPtr<BaseSceneGraph>      mShadowSceneGraph;  ///< subgraph containing shadow casters/receivers (or is BaseSceneGraph if shadows disabled)
    bool                        mEnableWireframe;   ///< wireframe mode
    RefPtr<osg::PolygonMode>    mPolygonMode;       ///< for wireframe mode
};

} // namespace graph

#endif // GRAPH_SCENE_GRAPH_HH
