/* -*-c++-*- */
/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
 * Copyright 2008-2010 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */
#ifndef OSGEARTH_SHADER_UTILS_H
#define OSGEARTH_SHADER_UTILS_H 1

#include <osgEarth/Common>
#include <osg/NodeCallback>
#include <osg/Uniform>

namespace osgEarth
{
    /**
     * A callback that will update the osgEarth lighting uniforms (based on the
     * FFP lighting state) if necessary.
     */
    class OSGEARTH_EXPORT UpdateLightingUniformsHelper
    {
    public:
        UpdateLightingUniformsHelper( bool useUpdateTraversal =false );
        ~UpdateLightingUniformsHelper();

        void cullTraverse( osg::Node* node, osg::NodeVisitor* nv );
        void updateTraverse( osg::Node* node );

    protected:
        int   _maxLights;
        bool* _lightEnabled;
        bool  _lightingEnabled;
        bool  _dirty;
        bool  _applied;
        bool  _useUpdateTrav;

        osg::ref_ptr<osg::Uniform> _lightingEnabledUniform;
        osg::ref_ptr<osg::Uniform> _lightEnabledUniform;
    };

    /**
     * Helper class for dealing with array uniforms. Array uniform naming works
     * differently on different drivers (ATI vs NVIDIA), so this class helps mitigate
     * those differences.
     */
    class OSGEARTH_EXPORT ArrayUniform : public osg::Referenced
    {
    public:
        ArrayUniform( osg::Uniform::Type type, const std::string& name, int size );

        /** creates an array uniform helper from an existing stateset */
        ArrayUniform( osg::StateSet* from, const std::string& name );

        void setElement( int index, int value );
        void setElement( int index, bool value );
        void setElement( int index, float value );

        void addTo( osg::StateSet* stateSet );
        void removeFrom( osg::StateSet* stateSet );

        bool isComplete() const { return _uniform.valid() && _uniformAlt.valid(); }
        int getNumElements() const { return isComplete() ? _uniform->getNumElements() : -1; }

    private:
        osg::ref_ptr<osg::Uniform> _uniform;
        osg::ref_ptr<osg::Uniform> _uniformAlt;
    };
}

#endif // OSGEARTH_SHADER_UTILS_H
