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

#ifndef FX_SPRITE_HH
#define FX_SPRITE_HH 1

#include "gfx/rgba.hh"
using namespace gfx;

namespace fx {

////////////////////////////////////////////////////////////////////////////////
/// @brief Sprite class.
///
/// See Commodore 64 Programmer's Reference Guide.
///
/// This class is written with inlines to optimize ParticleSystem.
///
/// Note: Client should attach Sprites to a group node with appropriate OSG stateset.
/// For example, the client can bind a texture to a stateset then pass that to Sprite ctor.
/// Historically, Sprite used to alter its stateset (bind textures etc),
/// but that eroded the state-sorting of the scene-graph.
///
class Sprite : public Object
{
PREVENT_COPYING(Sprite)
typedef Object Parent;

public:
    /// @brief Sprite ctor args.
    ///
    struct Args
    {
        Args( const WorldVertex& position,
              const fp width,
              RefPtr<osg::StateSet> stateSet,
              const RGBA color )
        :   mPosition(position), mWidth(width), mStateSet(stateSet), mColor(color)
        {
        }

        const WorldVertex           mPosition;
        const fp                    mWidth;     ///< width of sprite's quad
        const RefPtr<osg::StateSet> mStateSet;  ///< can have a texture bound to it (etc)
        const RGBA                  mColor;
    };

    Sprite( const Args& args );
    ~Sprite();

    const string GetName( void )
    {
    CHECK_TYPESIG(this,TYPESIG_SPRITE);
        return string("Sprite");
    }

    virtual NodeSort GetNodeSort( void ) { return msSpriteNodeSort; }

    RGBA GetColor0( void )
    {
    CHECK_TYPESIG(this,TYPESIG_SPRITE);
        return mColor0;
    }

    void SetColor0( const RGBA rgba )
    {
    CHECK_TYPESIG(this,TYPESIG_SPRITE);
        // The only way to change color in OSG is to
        // re-attach color array to geometry.
        mColor0 = rgba;
        osg::Vec4Array* colors = new osg::Vec4Array( 1 );
        (*colors)[0] = RGBA2VEC4F( rgba );  // colors[0] = color (singular)
        mGeometry->setColorArray( colors );
      //mGeometry->setColorBinding( osg::Geometry::BIND_OVERALL );  // done by ctor
    }

    enum { ROTATE_ABS = false, ROTATE_REL = true };
    void RotateRoll( const Radian radian, const bool relative = true );

private:
    RefPtr<osg::Drawable>   MakeDrawable( const Args& args );

private:
    CLASS_CONST NodeSort    msSpriteNodeSort;
    RefPtr<osg::Geometry>   mGeometry;      ///< Geometry is also a Drawable
    RefPtr<osg::Vec3Array>  mVertexs;       ///< vertexs
    RGBA                    mColor0;        ///< uni-color
    const fp                mWidth;         ///< needed for roll (cloud support)
public:
    DECLARE_TYPESIG(TYPESIG_SPRITE)
};

} // namespace fx

#endif // FX_SPRITE_HH
