//
// A custom scene node used for displaying aligned billboards,
// i.e. ones that rotate around their own Y axis to face the
// camera, but which can have a direction.  These are useful for 
// (e.g.) trees, or beam effects.
//
// They can be rectangular, or trapezoidal.  You can also translate the texture
// co-ordinates to produce flowing textures.

#ifndef __C_ALIGNEDBILLBOARD_SCENE_NODE_H_INCLUDED__
#define __C_ALIGNEDBILLBOARD_SCENE_NODE_H_INCLUDED__ 1

#include "ISceneNode.h" // in Irrlicht/include
#include "S3DVertex.h"  // in Irrlicht/include

using namespace irr;

class CAlignedBillboardSceneNode : public scene::ISceneNode
{
public:
    //! How to face the billboard towards the camera
    typedef enum
    {
        //! The billboard is flat, and faces directly opposite the camera's view.
        FACE_OPPOSITE,

        //! The billboard is flat, and faces towards the camera, based on its center point.
        //! This is the default facing.
        FACE_TOWARDS_FROM_CENTER,

        //! Each end (start, end) of the billboard twists to face the camera from its
        //! individual position.  This is good for long beam-style billboards, but can
        //! lead to the billboard appearing twisted.
        FACE_TOWARDS_FROM_ENDS
    } TFaceCameraBy;

    //! constructor
    CAlignedBillboardSceneNode(scene::ISceneNode* parent,
            scene::ISceneManager* sceneManager,
            s32 id = -1,
            const core::dimension2d<f32>& size = core::dimension2d<f32>(10.0f, 10.0f),
            bool positionIsCenter = false,
            const core::vector3df& position = core::vector3df(0,0,0),
            const core::vector3df& alignment = core::vector3df(0,1,0),
            video::SColor shade_top = 0xFFFFFFFF,
            video::SColor shade_down = 0xFFFFFFFF);

    virtual ~CAlignedBillboardSceneNode();

    //! pre render event
    virtual void OnRegisterSceneNode();

    //! render
    virtual void render();

    //! returns the axis aligned bounding box of this node
    virtual const core::aabbox3d<f32>& getBoundingBox() const { return BBox; }

    //! Sets the alignment of the billboard.
    virtual void setAlignment(const core::vector3df & alignment);

    //! Returns the alignment of the billboard.
    virtual const core::vector3df getAlignment(void) { return Alignment; }

    //! An alternative way to specify the location and size of the billboard.
    //! You could use this for (e.g.) a "beam" effect.  It sets the position,
    //! alignment and height of the billboard, but does not change its width
    virtual void setStartAndEndPositions(const core::vector3df & startPosition,
                                         const core::vector3df & endPosition);

    //! sets the size of the billboard, making it rectangular
    virtual void setSize(const core::dimension2d<f32>& size);

    //! set the size of the billboard, making it (presumably) trapezoidal
    virtual void setSize(f32 bottomWidth, f32 topWidth, f32 height);

    //! gets the size of the billboard
    virtual f32 getBottomWidth() const { return BottomWidth; }

    //! gets the size of the billboard
    virtual f32 getTopWidth() const { return TopWidth; }

    //! gets the size of the billboard
    virtual f32 getHeight() const { return Height; }

    //! Set how the billboard faces the camera
    virtual void setFaceCameraBy(TFaceCameraBy faceCameraBy) { FaceCameraBy = faceCameraBy; }

    //! Reports how the billboard faces the camera
    virtual TFaceCameraBy getFaceCameraBy(void) const { return FaceCameraBy; }

    //! If true, the position of the billboard represents its centre
    //! If false (the default) the position represents the centre of the bottom edge
    virtual void setPositionIsCenter(bool positionIsCenter) { PositionIsCenter = positionIsCenter; }

    //! If true, the position of the billboard represents its centre
    //! If false (the default) the position represents the centre of the bottom edge
    virtual bool getPositionIsCenter(void) const { return PositionIsCenter; }

    //! Move the texture coordinates on the billboard.  This can be used for scrolling
    //! the texture along, e.g. creating a moving beam effect.
    //! \param translateBy: the amount to move the U and V texture coordinates on each vertex
    virtual void translateTextureCoordinates(const core::dimension2df & translateBy);

    //! Set the color of all vertices of the billboard
    //! \param overallColor: the color to set
    virtual void setColor(const video::SColor & overallColor);

    //! Set the color of the top and bottom vertices of the billboard
    //! \param topColor: the color to set the top vertices
    //! \param bottomColor: the color to set the bottom vertices
    virtual void setColor(const video::SColor & topColor, const video::SColor & bottomColor);

    //! Gets the color of the top and bottom vertices of the billboard
    //! \param[out] topColor: stores the color of the top vertices
    //! \param[out] bottomColor: stores the color of the bottom vertices
    virtual void getColor(video::SColor & topColor, video::SColor & bottomColor);

    virtual video::SMaterial& getMaterial(u32 i) { return Material; };

    //! returns amount of materials used by this scene node.
    virtual u32 getMaterialCount() { return 1; };

    //! Writes attributes of the scene node.
    virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0);

    //! Reads attributes of the scene node.
    virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);

    //! Returns type of the scene node
    virtual scene::ESCENE_NODE_TYPE getType() { return scene::ESNT_BILLBOARD; }

private:

    f32 BottomWidth;
    f32 TopWidth;
    f32 Height;
    core::aabbox3d<f32> BBox;
    video::SMaterial Material;

    video::S3DVertex vertices[4];
    u16 indices[6];

    core::vector3d<f32> Alignment;
    TFaceCameraBy FaceCameraBy;
    bool PositionIsCenter;
};


#endif // __C_ALIGNEDBILLBOARD_SCENE_NODE_H_INCLUDED__

