/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield 
 * Copyright (C) 2003 3Dlabs Inc. Ltd.
 *
 * This application is open source and may be redistributed and/or modified   
 * freely and without restriction, both in commericial and non commericial
 * applications, as long as this copyright notice is maintained.
 * 
 * This application 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.
*/

/* file:	include/osgGL2/UniformValue
 * author:	Mike Weiblen 2003-12-28
 *
 * See http://www.3dlabs.com/opengl2/ for more information regarding
 * the OpenGL Shading Language.
*/

#ifndef OSGGL2_UNIFORMVALUE
#define OSGGL2_UNIFORMVALUE 1

#include <vector>
#include <typeinfo>

#include <osg/ref_ptr>
#include <osg/Vec2>
#include <osg/Vec3>
#include <osg/Vec4>
#include <osg/Referenced>

#include <osgGL2/Extensions>

namespace osgGL2 {

///////////////////////////////////////////////////////////////////////////
/** osgGL2::UniformValue is for internal use by osgGL2::ProgramObject.
  * UniformValue is an abstract class to encapsulate a new value for a glUniform.
  * osgGL2::ProgramObject.setUniform() constructs and sends a UniformValue
  * to all its PerContextProgramObjects (PCPOs) to set the value of a
  * glUniform.
  * The value contained in each UniformValue value is propagated to the
  * glProgramObjects during the next osgGL2::ProgramObject.apply().
  */

class OSGGL2_EXPORT UniformValue : public osg::Referenced
{
    public:
	virtual void apply( Extensions *ext, const GLhandleARB progObj ) const = 0;

        virtual int compare(const UniformValue& uv) const;

    protected:
	UniformValue( const char* uniformName ) : _name( uniformName ) {};
	virtual ~UniformValue() {};
	UniformValue();
	UniformValue(const UniformValue&);
	UniformValue& operator=(const UniformValue&);

	int getLocation( Extensions *ext, const GLhandleARB progObj ) const;

	std::string _name;
};

typedef std::vector< osg::ref_ptr<UniformValue> > UniformValueList;


///////////////////////////////////////////////////////////////////////////
/** UniformValueTemplate creates the concrete classes for each of the
  * uniform value types */

template<typename T>
class UniformValueTemplate: public UniformValue
{
    public:
	UniformValueTemplate( const char* uniformName, T value ) :
		UniformValue( uniformName ), _value( value ) {}

	virtual void apply( Extensions *ext, const GLhandleARB progObj ) const;

        virtual int compare(const UniformValue& uv) const 
        {
            if (this==&uv) return 0;
            const std::type_info* type_lhs = &typeid(*this);
            const std::type_info* type_rhs = &typeid(uv);
            if (type_lhs->before(*type_rhs)) return -1;
            if (*type_lhs != *type_rhs) return 1;
            const UniformValueTemplate& rhs = static_cast<const UniformValueTemplate&>(uv);

            if (_name<rhs._name) return -1;
            if (rhs._name<_name) return 1;

            if (_value<rhs._value) return -1;
            if (rhs._value<_value) return 1;

            return 0;
        }

    protected:
	UniformValueTemplate();
	const T _value;
};

typedef UniformValueTemplate<int>	UniformValue_int;
typedef UniformValueTemplate<float>	UniformValue_float;
typedef UniformValueTemplate<osg::Vec2>	UniformValue_Vec2;
typedef UniformValueTemplate<osg::Vec3>	UniformValue_Vec3;
typedef UniformValueTemplate<osg::Vec4>	UniformValue_Vec4;

}

#endif

/*EOF*/
