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

#ifndef GRAPH_GRAPH_HH
#define GRAPH_GRAPH_HH 1

#include "graph/graph_enablement.hh"
#include <osg/Switch>

namespace graph {

////////////////////////////////////////////////////////////////////////////////
/// @brief Graph class (per-object graph).
///
/// This can be thought of as ObjectGraph.
/// Graph defines the set of nodes of one individual Object.
///
/// Graph arrangement (OSG):
/// osg::Switch --> osg::Transform --> node
///
/// Graph and Object have their own separate Transform nodes.
/// Graph's Transform is used for orienting 3D models transparently
/// to an Object (Objects are attached to a Graph).
///
/// SUBTLE: Another transform node can be passed to the ctor as the root node.
/// Having two transform nodes is useful, since it allows setting
/// the correct orientation of a 3D model, which then is transformed
/// by the usual transform node.
///
/// Use AttachNode() [instead of addChild() with GetRootNode()/GetTransformNode()].
/// GetRootNode() must return the actual root node (this cannot be faked, if World::Attach()
/// were to attach its child then the root node would be outside the scene graph).
/// There is no separate Group node (it is really the Transform node),
/// but accomodates clients that only need a Group node.
///
class Graph : public Shared, private GraphEnablement
{
// Graph (ctor, dtor):
public:                             Graph( RefPtr<Node> node, const string& name = string() );
public:                             ~Graph();
public:  void                       SetName( const string& name );  // omitted GetName() for smallness

// Graph enablement:
public:  void                       Enable( const bool enable = true );  // enable rendering of Graph
public:  bool                       IfEnabled( void );

// Making graphs:
public:  CLASS_METHOD shptr<Graph>  MakeMinimalGraph( void );  // make a minimal-but-usable Graph

// Nodes:
public:  void                       AttachNode( RefPtr<Node> node );
public:  RefPtr<Node>               GetRootNode( void )      { CHECK_TYPESIG(this,TYPESIG_GRAPH); return mSwitchNode.get(); }
public:  RefPtr<TransformNode>      GetTransformNode( void ) { CHECK_TYPESIG(this,TYPESIG_GRAPH); return mTransformNode.get(); }
public:  RefPtr<osg::Group>         GetGroupNode( void )     { CHECK_TYPESIG(this,TYPESIG_GRAPH); return GetTransformNode().get(); }

// Graph (data members):
private: RefPtr<osg::Switch>    mSwitchNode;
private: RefPtr<TransformNode>  mTransformNode;     ///< outer-level transform node
private: RefPtr<osg::StateSet>  mStateSet;
public:  DECLARE_TYPESIG(TYPESIG_GRAPH)  // final member
};

} // namespace graph

#endif // GRAPH_GRAPH_HH
