/*****************************************************************************
 * $LastChangedDate: 2011-04-23 21:07:07 -0400 (Sat, 23 Apr 2011) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   ShaderFactory attaches a shader to a node.
 *//*
 * 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 SHADER_SHADER_FACTORY_HH
#define SHADER_SHADER_FACTORY_HH 1

#define GET_SHADER_FACTORY() (ShaderFactory::GetInstance())

#include <map>
#include "base/singleton.hh"
#include "graph/typedefs.hh"
namespace graph { class NodeSort; }
using namespace graph;
#include "shader/shader_name.hh"
#if ! DOXYGEN
namespace osg { class Shader; class Program; }
#endif

namespace shader {

/// @brief Stores individual vertex/fragment shaders.
struct ShaderProgram
{
    ShaderProgram( RefPtr<osg::Program> program,
                   RefPtr<osg::Shader> vertexShader,
                   RefPtr<osg::Shader> fragmentShader )
    : mProgram(program), mVertexShader(vertexShader), mFragmentShader(fragmentShader)
    { }
    RefPtr<osg::Program>    mProgram;
    RefPtr<osg::Shader>     mVertexShader;
    RefPtr<osg::Shader>     mFragmentShader;
};

////////////////////////////////////////////////////////////////////////////////
/// @brief ShaderFactory attaches a shader to a node.
///
/// Build pathnames to files container GLSL shader source code.
/// Naming convention:
/// ${shaderName}_vert.glsl
/// ${shaderName}_frag.glsl
///
/// Design notes:
/// Abstracts OSG to a degree, but assumes a scene-graph capable
/// of attaching a shader program to any kind of node.
///
class ShaderFactory
{
PREVENT_COPYING(ShaderFactory)
friend class graph::NodeSort;
private:
    ShaderFactory( void );
    ~ShaderFactory();

public:
                    DEFINE_GetInstance( ShaderFactory )  // Singleton
    void            AttachShader( const ShaderName& shaderName, RefPtr<Node> node );
    ShaderProgram   GetShader( const ShaderName& shaderName );
    void            Flush( void );

private:
    ShaderProgram   CreateShader( const ShaderName& shaderName );
    string          ExpandMacros( const string& shaderSrc );

private:
    typedef std::map<ShaderName,ShaderProgram> ShaderMap;
    CLASS_VAR ShaderFactory*    msInstance;
    const string                mShaderDir;     ///< directory with shader src code
    ShaderMap                   mShaderMap;     ///< map of shader programs
};

} // namespace shader

#endif // SHADER_SHADER_FACTORY_HH
