/****************************************************************************************************

		MCGradient.h
		Copyright: (c) 2001 Eovia Corp. All rights reserved.

		Author:	Julien
		Date:	10/11/2002

****************************************************************************************************/

#ifndef __MCGradient__
#define __MCGradient__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "MCClassArray.h"
#include "MCColorRGBAIndex.h"

/// \addtogroup MCCore
/// \{

/// A gradient contains an array of TMCColorRGBAIndex (color keys).
/// For a value beetween 0 and 1, it can return an interpolation beetween the 2 colors whose index framed the value.
/// It can be use as a pMap parameter and be animated.
/// kGradientParamType is its paramType value.
/// kGradientValueType is its valueType value.
///
class TMCGradient
{
public:
	inline TMCGradient	(void);
	inline TMCGradient	(boolean isEmpty);
	inline TMCGradient	(const TMCClassArray<TMCColorRGBAIndex>& colorArray);


	// ****************************************************************************
	//								GetColor
	// 
	/// Get a color in the gradient. Position must be beetween 0 and 1.
	/// 
	/// \param pos    the position asked
	/// \param color  the color to be filled
	/// 
	void		GetColor			(real32 pos, TMCColorRGBA& color ) const;
	
	// ****************************************************************************
	//								GetColorKeyCount
	// 
	/// \return the number of colorKeys
	///
	int32		GetColorKeyCount	() const {return fColorIndexArray.GetElemCount();}

	// ****************************************************************************
	//								GetColorKey
	// 
	/// Color keys accessor
	/// 
	/// \param elem      the index in the array
	/// \param colorKey  the TMCColorRGBAIndex to be returned
	/// 
	void		GetColorKey			(const int32 elem, TMCColorRGBAIndex& colorKey ) const {colorKey = fColorIndexArray[elem];}
	
	// ****************************************************************************
	//								FindColorKey
	// 
	///	Looks for a specific colorKey in the array of keys.
	///	If several are found in the tolerance (epsilon), the nearest one is choosen.
	///
	/// \param colorKey  the TMCColorRGBAIndex to be found in the array.
	/// \param epsilon   a tolerance.
	/// \return the position of the elem in array, -1 if not found.
	///
	int32		FindColorKey		(const TMCColorRGBAIndex& colorKey, const real32 epsilon) const;
	
	// ****************************************************************************
	//								FindColorKeyByIndex
	// 	
	///	Look for a colorKey with the same index in the array of keys.
	/// If several are found in the tolerance (epsilon), the nearest one is choosen.
	///	\param index    the index to be found.
	///	\param epsilon  a tolerance.
	/// \return the position of the colorKey in the array, or -1 if none is found.
	///
	int32		FindColorKeyByIndex	(const real32 index, const real32 epsilon ) const;

	// ****************************************************************************
	//								SetColorKeyColor
	// 
	/// Sets the color for a colorKey.
	/// \param elem   the position of the colorKey in the array.
	/// \param color  the new color for this colorKey.
	///
	void		SetColorKeyColor	(const int32 elem, TMCColorRGBA& color);

	// ****************************************************************************
	//								SetColorKeyIndex
	// 
	///	Set the index for a colorKey.
	/// \param elem   the position of the colorKey in the array.
	/// \param index  the new index for this colorKey.
	///
	void		SetColorKeyIndex	(const int32 elem, const real32 index);

	// ****************************************************************************
	//								AddColorKey
	// 
	/// Adds a new colorKey to the array of keys
	/// \param colorIndex the colorKey to be added
	/// \return the position in the array, or -1 if the colorKey couldn't be added.
	///
	int32		AddColorKey			( TMCColorRGBAIndex& colorIndex );

	// ****************************************************************************
	//								AddColorKey
	// 
	/// Adds a new colorKey to the array of keys
	/// 
	/// \param color the colorKey to be added
	/// \param index the index of the colorKey
	/// 
	int32		AddColorKey			( TMCColorRGBA& color, real32 index );

	// ****************************************************************************
	//								AddColorKey
	// 
	/// Adds a new colorKey to the array of keys
	/// 
	/// \param red    the red part of the colorKey to be added
	/// \param green  the green part of the colorKey to be added
	/// \param blue   the blue part of the colorKey to be added
	/// \param alpha  the alpha part of the colorKey to be added
	/// \param index  the index of the colorKey
	/// 
	int32		AddColorKey			( real32 red, real32 green, real32 blue, real32 alpha, real32 index );

	// ****************************************************************************
	//								RemoveColorKey
	// 
	/// Removes a colorKey from the array of keys.	
	/// \param elem  the position of the colorKey in the array.
	/// \return false if out of range
	///
	boolean		RemoveColorKey		( const int32 elem );

	// ****************************************************************************
	//								IsEqual
	// 
	/// Equality test beetween this gradient and another one
	/// \param grad    the other gradient
	/// \param epsilon a tolerance value
	/// \return true if equal ( same number of colorKey, and each colorKey with same color and same index )
	///
	boolean		IsEqual				(const TMCGradient& grad, const real32 epsilon=0.0f) const;
	
	// ****************************************************************************
	//								Interpolate
	// 
	///	Linear interpolation: set this gradient to a value beetween the from and to gradients
	/// \param from         first gradient.
	/// \param to           second gradient.
	/// \param interpolant  interpolation value (should be beetween 0 and 1).
	void		Interpolate			(const TMCGradient& from, const TMCGradient& to, const real32 interpolant);
	
	// ****************************************************************************
	//								Interpolate
	// 
	/// Bilinear interpolation: set this gradient to a value beetween the 4 gradients
	/// \param interpolants  interpolation values ( x [left/right], y [lower/upper])
	/// \param lowerLeft, lowerRight, upperLeft, upperRight: the 4 gradients
	///
	void		Interpolate			(const TVector2& interpolants,
									 const TMCGradient& lowerLeft,
									 const TMCGradient& lowerRight,
									 const TMCGradient& upperLeft,
									 const TMCGradient& upperRight);

	// ****************************************************************************
	//								operator==
	// 
	/// \see IsEqual()
	///
	inline boolean		operator==	(const TMCGradient& rhs) const;
	
	// ****************************************************************************
	//								operator!=
	// 
	/// \see !IsEqual()
	///
	inline boolean		operator!=	(const TMCGradient& rhs) const;
	
	// ****************************************************************************
	//								operator=
	//
	inline TMCGradient&	operator=	(const TMCGradient& grad);

	// ****************************************************************************
	//								operator=
	// 
	// -Description:
	// used for gradient keyframes
	//
	// -Parameters:
	//
	// -Returns:
	//
	inline TMCGradient&	operator=	(const int32 i) { MCAssert(i==0); return *this; }

protected:
	TMCClassArray<TMCColorRGBAIndex> fColorIndexArray;
	
};

/// \}

inline TMCGradient::TMCGradient(void)
	{
	// Default constructor build an empty gradient for key framing
	}

inline TMCGradient::TMCGradient(boolean isEmpty)
	{
		if(!isEmpty)
		{
			fColorIndexArray.AddElem( TMCColorRGBAIndex(.0f,.0f,.6f,1,.0f) );
			fColorIndexArray.AddElem( TMCColorRGBAIndex(.4f,1.f,1.f,1,1.f) );
		}
	}

inline TMCGradient::TMCGradient(const TMCClassArray<TMCColorRGBAIndex>& colorArray)
	: fColorIndexArray(colorArray)
	{ }

inline boolean TMCGradient::operator== (const TMCGradient& rhs) const 
	{ return IsEqual( rhs ); }

inline boolean TMCGradient::operator!= (const TMCGradient& rhs) const 
	{ return !IsEqual( rhs ); }

inline TMCGradient &TMCGradient::operator= (const TMCGradient &rhs)
{
	fColorIndexArray.ArrayFree();
	const int32 numColors = rhs.fColorIndexArray.GetElemCount();

	for( int32 i=0 ; i<numColors ; i++ )
	{
		TMCColorRGBAIndex colorI;
		rhs.fColorIndexArray.GetElem(i, colorI);
		fColorIndexArray.AddElem(colorI);
	}	

	return *this;
}







#endif
