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


		MCColorRGBA.h

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

		Author:	Alec
		Date:	5/22/98

		Revision History

		when		who			what & why
		==========	==========	======================================================
		7/12/98		Alec		changed TMCColorRGBA32 back to use int32's, added unions
									to TMCColorRGBA to faciliate moving away from old code	
		6/4/98		Alec		ToRGBA/8 routines now also return the data passed in
		5/22/98		Alec		new today - classes for common color ops/math
		
*****************************************************************************************/

#ifndef ColorRGBA_H
#define ColorRGBA_H

#if CP_PRAGMA_ONCE
#pragma once
#endif

// This file contains the three color classes one floating pt class TMCColorRGBA,
// and two integer classes TMCColorRGBA8, and TMCColorRGBA32
//
// Note that we may want to distinguish between these color classes and pixel operations
// which should probably have their own class.  A convention is followed of naming the
// class TMCColorRGBA to indicate its components, followed by the size of the components
// if it is an integer color (8/16/32).  The intent is for these classes to have similar
// functionality where possible, and specialized functinality where possible.  The full use
// of color names is intended to help prevent accidental use of the wrong color component.
//
// Macros are provided in InlineColor.h to help deal with RGB vs. RGBA in the absence
// of a class for RGB.
//
// There are a wide variety of color spaces (notably CMYK) that we might want to add
// classes for.  We may also have to seperate operations into pre-mul vs. straight alpha.
// For example the interpolation routines are really only correct for constant and
// pre-mul alpha since alpha is linearly interpolated with all other components.  Where
// specialized color routines are necessary, check ColorMath.h.
//
// There are similar routines for TMCColorRGB and TMCColorRGBA16 available, but I have left
// these out until needed.

#include "MCBasicTypes.h"
#include "MCBasicDefines.h"
#include "MCOSConfig.h"
#include "MCColorRGB.h"
#include "MCAssert.h"

class TMCColorRGBA;



/// \addtogroup MCCore
/// \{

/// TMCColorRGBA8 is offscreen/system dependent, do not assume component ordering.
/// This 8 bit component integer color mimics the byte ordering of the native pixel format on the PC/MAC since we
/// often are working at the pixel level with this math.
///
/// <P> Other color classes are TMCColorRGB, TMCColorRGBA, TMCColorRGBA32</P>
class TMCColorRGBA8 : public TMCObject
{
	// no virtual functions to keep structure at 32 bits.
public:
		static const uint8 kMaxIntensity; // = 255; 	
		static const real  kInvMaxIntensity; //  = 1.0 / kMaxIntensity;
		
		static const TMCColorRGBA8 kBlackNoAlpha;
			// (0,0,0,0);
		static const TMCColorRGBA8 kBlackFullAlpha;
			// (0,0,0,kMaxIntensity);
		
		static const TMCColorRGBA8 kWhiteNoAlpha;
			// (kMaxIntensity,kMaxIntensity,kMaxIntensity,0);
		static const TMCColorRGBA8 kWhiteFullAlpha;
			// (kMaxIntensity,kMaxIntensity,kMaxIntensity,kMaxIntensity);
		
	public:		
		// constructors/setters
		inline TMCColorRGBA8				(void);
		inline TMCColorRGBA8				(const uint8 rr,const uint8 gg,const uint8 bb,const uint8 aa );

		inline TMCColorRGBA8				(uint32 c);
		inline TMCColorRGBA8				(const TMCColorRGB& color);
		inline TMCColorRGBA8				(const TMCColorRGBA& color);

		inline void Set						(const uint8 rr,const uint8 gg,const uint8 bb,const uint8 aa );
		
		// linear/bilinear interpolation, interpolants must be betwen 0 and 1
		// valid for constant alpha and pre-mul alpha interp
		void Interpolate					(const TMCColorRGBA8 from, const TMCColorRGBA8 to, const real interpolant); // must be between 0 and 1
		void Interpolate					(const TVector2& interpolants, // x [left/right], y [lower/upper]
											 const TMCColorRGBA8 lowerLeft,
											 const TMCColorRGBA8 lowerRight,
											 const TMCColorRGBA8 upperLeft,
											 const TMCColorRGBA8 upperRight);
		
		// find the min and max intensity
		inline uint8 GetMinOfRGB			(void) const;
		inline uint8 GetMaxOfRGB			(void) const;
										
		// these are operators on all the components
		inline boolean operator==			(const TMCColorRGBA8 rhs) const;
		inline boolean operator!=			(const TMCColorRGBA8 rhs) const;
		
		inline TMCColorRGBA8 operator+=		(const TMCColorRGBA8 rhs);
		inline TMCColorRGBA8 operator-=		(const TMCColorRGBA8 rhs);
		inline TMCColorRGBA8 operator*=		(const real s);
		inline TMCColorRGBA8 operator/=		(const real s);

		inline TMCColorRGBA8 operator+		(const TMCColorRGBA8 rhs) const;
		inline TMCColorRGBA8 operator-		(const TMCColorRGBA8 rhs) const;
		inline TMCColorRGBA8 operator*		(const real s) const;
		inline TMCColorRGBA8 operator/		(const real s) const;
		
		// conversion operations to the other colors
			   TMCColorRGBA& ToRGBA			(TMCColorRGBA& c) const;

		inline uint8 Intensity				() const;
	
		// returns the first component in the structure
		inline const uint8* GetAddrFirstComponent(void) const;
		inline uint8* GetAddrFirstComponent(void);

		inline uint8	operator [] (int32 i) const
		{
			MCAssert(i >= 0 && i < 4);
			return GetAddrFirstComponent()[i];
		}

		inline uint8&	operator [] (int32 i)
		{
			MCAssert(i >= 0 && i < 4);
			return GetAddrFirstComponent()[i];
		}

		enum EComponent
		{
			kRed	= 0,
			kGreen	= 1,
			kBlue	= 2,
			kAlpha	= 3
		};

		inline static int32	GetComponentIndex(EComponent index);
			
	public:	
		// for Windows (little-endian) the bytes are commonly stored as b,g,r,a
		// for Mac (big-endian) the bytes are stored a,r,g,b.  Note that neither
		// of these correspond to the RGBA ordering used in the class name/ctor.
		
#if MC_LITTLE_ENDIAN
		uint8	blue;
		uint8	green;
		uint8	red;
		uint8	alpha;
#elif MC_BIG_ENDIAN
		uint8	alpha;
		uint8	red;
		uint8	green;
		uint8	blue;
#else
		#error - unknown platform
#endif
};
/// \}


/// \addtogroup MCCore
/// \{	

/// <P> TMCColorRGBA32 is used for maximum precision when accumulating colors. 
/// (Primarily for sum-area table accumulation of 8-bit color components).
/// Unlike the 8-bit version, we have enough precision to do signed values </P>
///	
/// <P> Other color classes are TMCColorRGB, TMCColorRGBA, TMCColorRGBA8</P>
///
class TMCColorRGBA32 : public TMCObject
{	
	public:
		static const uint8 kMaxIntensity;
			// = 0x7FFFFFFFL;
		static const TMCColorRGBA32 kZero; 
			// ( 0,0,0,0 );
		
	public:
		// constructors/setters
		inline TMCColorRGBA32				(void);
		inline TMCColorRGBA32				(const int32 rr, const int32 gg, const int32 bb, const int32 aa);
		
		inline void Set						(const int32 rr, const int32 gg, const int32 bb, const int32 aa);
						
		// linear/bilinear interpolation, interpolants must be betwen 0 and 1
		// valid for constant alpha and pre-mul alpha interp
		void Interpolate					(const TMCColorRGBA32& from, const TMCColorRGBA32& to, const real interpolant );
		void Interpolate					(const TVector2& interpolants, // x [left/right], y [lower/upper]
											 const TMCColorRGBA32& lowerLeft,
											 const TMCColorRGBA32& lowerRight,
											 const TMCColorRGBA32& upperLeft,
											 const TMCColorRGBA32& upperRight);
		
		// these are operators on all the components
		inline boolean operator==			(const TMCColorRGBA32& rhs) const;
		inline boolean operator!=			(const TMCColorRGBA32& rhs) const;
		
		inline TMCColorRGBA32& operator+=	(const TMCColorRGBA32& rhs);
		inline TMCColorRGBA32& operator-=	(const TMCColorRGBA32& rhs);
		inline TMCColorRGBA32& operator*=	(const real s);
		inline TMCColorRGBA32& operator/=	(const real s);
		
		inline TMCColorRGBA32 operator+		(const TMCColorRGBA32& rhs) const;
		inline TMCColorRGBA32 operator-		(const TMCColorRGBA32& rhs) const;
		inline TMCColorRGBA32 operator*		(const real s) const;
		inline TMCColorRGBA32 operator/		(const real s) const;
		
		// we use this operator to accumulate TMCColorRGBA8 values
		inline void			  operator+=	(const TMCColorRGBA8& rhs);

		// returns the first component in the structure
		inline const int32* GetAddrFirstComponent(void) const;
		
	public:	
		int32	red;
		int32	green;
		int32	blue;
		int32	alpha;
};

/// \}

/// \addtogroup MCCore
/// \{

/// TMCColorRGBA adds an alpha component to TMCColorRGB <BR>
/// <P> Other color classes are TMCColorRGBA32, TMCColorRGBA8</P>
///
class TMCColorRGBA : public TMCColorRGB
{
	// This is the floating point color used for most calculations since it 
	// can do interpolation without converting int-to-float. 
	
	public:
		static const real kMaxIntensity;			// = 1;
		static const real kInvMaxIntensity;			//  = 1.0 / kMaxIntensity;
				
		static const TMCColorRGBA kBlackNoAlpha; 	//(0,0,0,0);
		static const TMCColorRGBA kBlackFullAlpha; 	// (0,0,0,kMaxIntensity);
		
		static const TMCColorRGBA kWhiteNoAlpha;	// (kMaxIntensity,kMaxIntensity,kMaxIntensity,0);
		static const TMCColorRGBA kWhiteFullAlpha;	// (kMaxIntensity,kMaxIntensity,kMaxIntensity,kMaxIntensity);
		
	public:
		// constructors/setters
		inline TMCColorRGBA				(void);

		// we should not have a default value for the alpha, this cause too many alpha value to be set to 1 by mistake (Charles)
		inline TMCColorRGBA				(const TMCColorRGB& rgb, real a);

		inline TMCColorRGBA				(const real rr, const real gg, const real bb, const real aa);
				
		inline void Set					(const real rr, const real gg, const real bb, const real aa);
		
		boolean IsEqual					(const TMCColorRGBA& rhs, const real epsilon = 0.0) const;		
		
		// magnitudes
		inline real GetMagnitude		(void) const;
		inline real GetMagnitudeSquared	(void) const;
		
		// find the min and max intensity
		inline real GetMinOfRGB			(void) const;
		inline real GetMaxOfRGB			(void) const;
		
		// see if the color falls in between [0, 1]	- mainly for debug		
		boolean		IsClamped			(void) const;
		
		// clamp the color value to between [0, 1]
		void		Clamp				(void);
		
		// linear/bilinear interpolation, interpolants must be betwen 0 and 1
		// valid for constant alpha and pre-mul alpha interp
		void		Interpolate			(const TMCColorRGBA& from, const TMCColorRGBA& to, const real interpolant);
		void		Interpolate			(const TVector2& interpolants, // x [left/right], y [lower/upper]
										 const TMCColorRGBA& lowerLeft,
										 const TMCColorRGBA& lowerRight,
										 const TMCColorRGBA& upperLeft,
										 const TMCColorRGBA& upperRight);
		
		// color accumulation is used so often and we want to take advantage of fmul-add
		// this is equiv to  *this += rhs * scalar, no clamping is done
		inline void AccumRGBA			(const TMCColorRGBA& rhs, const real scalar );  
		inline void AccumRGB			(const TMCColorRGBA& rhs, // alpha ignored
										 const real scalar ); 

		inline void Add					(const TMCColorRGB& rhs);
				
		// these are operators on all the components
		inline boolean		 operator==	(const TMCColorRGBA& rhs) const;
		inline boolean		 operator!=	(const TMCColorRGBA& rhs) const;
		
		inline TMCColorRGBA& operator=  (const int32 i)		{ MCAssert(i==0); R=i;G=i;B=i;A=1; return *this; }
		inline TMCColorRGBA& operator=	(const TMCColorRGB& c) { *((TMCColorRGB*)this)=c; return *this;}
		inline TMCColorRGBA& operator+= (const TMCColorRGBA& rhs);
		inline TMCColorRGBA& operator+= (const TMCColorRGB& rhs);
		inline TMCColorRGBA& operator-= (const TMCColorRGBA& rhs);
		inline TMCColorRGBA& operator*= (const real s);
		inline TMCColorRGBA& operator/= (const real s);
	
		inline TMCColorRGBA  operator+	(const TMCColorRGBA& rhs) const;
		inline TMCColorRGBA  operator-	(const TMCColorRGBA& rhs) const;
		inline TMCColorRGBA  operator*	(const real s) const;
		inline TMCColorRGBA  operator/	(const real s) const;
		
		// dot, term-by-term product
		inline real			 operator*	(const TMCColorRGBA& rhs) const;
		inline TMCColorRGBA  operator%	(const TMCColorRGBA& rhs) const;
		
		// conversion operations to the other colors
		TMCColorRGBA8& ToRGBA8			(TMCColorRGBA8& c) const;
		TMCColorRGBA8& ToRGBA8Unclamped	(TMCColorRGBA8& c) const;
		
		// returns the address of first component in the structure
		inline const real* GetAddrFirstComponent(void) const;
		inline real		operator[] (int32 index) const;
		inline real&	operator[] (int32 index);
		
	public:
		// in order to facilitate a simpler move away from old colors
		// do not use R,G,B,A in new code (use the full names)
		union { real alpha;	real A; };
};
/// \}

// inline implementation --------------------------------------------

inline TMCColorRGBA8::TMCColorRGBA8(void)
	{ }

inline TMCColorRGBA8::TMCColorRGBA8(const uint8 rr,	const uint8 gg,	const uint8 bb,	const uint8 aa )
	: red( rr ), green( gg ), blue( bb ), alpha( aa )
	{ }

inline TMCColorRGBA8::TMCColorRGBA8(const TMCColorRGB &color)
{
	ASSIGN_CAST( red,	color.red*255  );
	ASSIGN_CAST( green, color.green*255);
	ASSIGN_CAST( blue,	color.blue*255 );
	alpha	= 0;
}

inline TMCColorRGBA8::TMCColorRGBA8(const TMCColorRGBA &color)
{
	red		= (int8)(color.red*255);
	green	= (int8)(color.green*255);
	blue	= (int8)(color.blue*255);
	alpha	= (int8)(color.alpha*255);
}

inline TMCColorRGBA8::TMCColorRGBA8(uint32 c) 
{
	*((uint32*)this)=c;
}

inline void TMCColorRGBA8::Set(const uint8 rr, const uint8 gg, const uint8 bb, const uint8 aa )
	{ red = rr; green = gg; blue = bb; alpha = aa; }



inline uint8 TMCColorRGBA8::GetMinOfRGB( void ) const
	{ uint8 min = ( red < green ); return ( min < blue ) ? min : blue; }

inline uint8 TMCColorRGBA8::GetMaxOfRGB( void ) const
	{ uint8 min = ( red > green ); return ( min > blue ) ? min : blue; }

inline uint8 TMCColorRGBA8::Intensity() const
{
	int32 intensity = int32(0.3f * red + 0.6f * green + 0.1f * blue);

	if (intensity>255) intensity=255;

	return intensity;
}

		
inline boolean TMCColorRGBA8::operator== (const TMCColorRGBA8 rhs) const 
	{ return *(uint32*)this == *(uint32*)&rhs; }

inline boolean TMCColorRGBA8::operator!= (const TMCColorRGBA8 rhs) const 
	{ return *(uint32*)this != *(uint32*)&rhs; }



inline TMCColorRGBA8 TMCColorRGBA8::operator+= (const TMCColorRGBA8 rhs)
 { { (*this).red += (rhs).red; (*this).green += (rhs).green; (*this).blue += (rhs).blue; (*this).alpha += (rhs).alpha; }; return *this; }

inline TMCColorRGBA8 TMCColorRGBA8::operator-= (const TMCColorRGBA8 rhs)
 { { (*this).red -= (rhs).red; (*this).green -= (rhs).green; (*this).blue -= (rhs).blue; (*this).alpha -= (rhs).alpha; }; return *this; }

inline TMCColorRGBA8 TMCColorRGBA8::operator*= (const real s)
{  
	ASSIGN_CAST( red,   red*s);
	ASSIGN_CAST( green, green*s);
	ASSIGN_CAST( blue,  blue*s);
	ASSIGN_CAST( alpha, alpha*s);
	return *this; 
}

inline TMCColorRGBA8 TMCColorRGBA8::operator/= (const real s)
{
	ASSIGN_CAST(red,   red/s);
	ASSIGN_CAST(green, green/s);
	ASSIGN_CAST(blue,  blue/s);
	ASSIGN_CAST(alpha, alpha/s);
	return *this; 
}


inline TMCColorRGBA8 TMCColorRGBA8::operator+ (const TMCColorRGBA8 rhs) const
 { return TMCColorRGBA8( *this ) += rhs; }

inline TMCColorRGBA8 TMCColorRGBA8::operator- (const TMCColorRGBA8 rhs) const
 { return TMCColorRGBA8( *this ) -= rhs; }

inline TMCColorRGBA8 TMCColorRGBA8::operator* (const real s) const
 { return TMCColorRGBA8( *this ) *= s; }

inline TMCColorRGBA8 TMCColorRGBA8::operator/ (const real s) const
 { return TMCColorRGBA8( *this ) /= s; }

#if MC_LITTLE_ENDIAN
	const uint8* TMCColorRGBA8::GetAddrFirstComponent(void) const
		{ return &blue; }
#elif MC_BIG_ENDIAN
	const uint8* TMCColorRGBA8::GetAddrFirstComponent(void) const
		{ return &alpha; }
#else
 		#error - unknown platform
#endif

#if MC_LITTLE_ENDIAN
	uint8* TMCColorRGBA8::GetAddrFirstComponent(void)
		{ return &blue; }
#elif MC_BIG_ENDIAN
	uint8* TMCColorRGBA8::GetAddrFirstComponent(void)
		{ return &alpha; }
#else
 		#error - unknown platform
#endif

inline int32 TMCColorRGBA8::GetComponentIndex(EComponent index)
{
	MCAssert(index >=0 && index < 4);
#if MC_LITTLE_ENDIAN
	switch (index)
	{
	case kRed:		return 2;
	case kGreen:	return 1;
	case kBlue:		return 0;
	case kAlpha:	return 3;
	}
#elif MC_BIG_ENDIAN
	switch (index)
	{
	case kRed:		return 1;
	case kGreen:	return 2;
	case kBlue:		return 3;
	case kAlpha:	return 0;
	}
#else
	#error - unknown platform
#endif
	return 0;
}

// --------------------------------------------

inline TMCColorRGBA32::TMCColorRGBA32(void)
	{ }
inline TMCColorRGBA32::TMCColorRGBA32(const int32 rr, const int32 gg, const int32 bb, const int32 aa )
	: red( rr ), green( gg ), blue( bb ), alpha( aa )
	{ }

inline void TMCColorRGBA32::Set(const int32 rr,	const int32 gg,	const int32 bb,	const int32 aa )
	{ red = rr; green = gg; blue = bb; alpha = aa; }



inline boolean TMCColorRGBA32::operator== (const TMCColorRGBA32& rhs) const

	{ return ((red == rhs.red) && (green == rhs.green) && (blue == rhs.blue) && (alpha == rhs.alpha)); }

inline boolean TMCColorRGBA32::operator!= (const TMCColorRGBA32& rhs) const 
	{ return (!(*this == rhs)); }



inline TMCColorRGBA32& TMCColorRGBA32::operator+= (const TMCColorRGBA32& rhs)
 { { (*this).red += (rhs).red; (*this).green += (rhs).green; (*this).blue += (rhs).blue; (*this).alpha += (rhs).alpha; }; return *this; }

inline TMCColorRGBA32& TMCColorRGBA32::operator-= (const TMCColorRGBA32& rhs)
 { { (*this).red -= (rhs).red; (*this).green -= (rhs).green; (*this).blue -= (rhs).blue; (*this).alpha -= (rhs).alpha; }; return *this; }

inline TMCColorRGBA32& TMCColorRGBA32::operator*= (const real s)
{  
	ASSIGN_CAST(red,   red*s);
	ASSIGN_CAST(green, green*s);
	ASSIGN_CAST(blue,  blue*s);
	ASSIGN_CAST(alpha, alpha*s);
	return *this; 
}

inline TMCColorRGBA32& TMCColorRGBA32::operator/= (const real s)
{ 
	ASSIGN_CAST(red,   red/s);
	ASSIGN_CAST(green, green/s);
	ASSIGN_CAST(blue,  blue/s);
	ASSIGN_CAST(alpha, alpha/s);
	return *this; 
}


// we use this operator to accumulate TMCColorRGBA8 values
inline void TMCColorRGBA32::operator += ( const TMCColorRGBA8& rhs )
 { { (*this).red += (rhs).red; (*this).green += (rhs).green; (*this).blue += (rhs).blue; (*this).alpha += (rhs).alpha; }; }
		


inline TMCColorRGBA32 TMCColorRGBA32::operator+ (const TMCColorRGBA32& rhs) const
	{ return TMCColorRGBA32( *this ) += rhs; }

inline TMCColorRGBA32 TMCColorRGBA32::operator- (const TMCColorRGBA32& rhs) const
	{ return TMCColorRGBA32( *this ) -= rhs; }

inline TMCColorRGBA32 TMCColorRGBA32::operator* (const real s) const
	{ return TMCColorRGBA32( *this ) *= s; }

inline TMCColorRGBA32 TMCColorRGBA32::operator/ (const real s) const
	{ return TMCColorRGBA32( *this ) /= s; }


const int32* TMCColorRGBA32::GetAddrFirstComponent(void) const
	{ return &red; }

// --------------------------------------------

inline TMCColorRGBA::TMCColorRGBA(void)
	{ }

inline TMCColorRGBA::TMCColorRGBA(const TMCColorRGB& rgb, real a)
	: TMCColorRGB(rgb), alpha(a)
	{ }

inline TMCColorRGBA::TMCColorRGBA(const real rr,const real gg,const real bb,const real aa )
	: TMCColorRGB(rr,gg,bb), alpha( aa )
	{ }

inline void TMCColorRGBA::Set(const real rr, const real gg, const real bb, const real aa )
	{ red = rr; green = gg; blue = bb; alpha = aa; }

inline real TMCColorRGBA::GetMagnitude(void) const
	{ return RealSqrt( GetMagnitudeSquared() ); }

inline real TMCColorRGBA::GetMagnitudeSquared(void) const
	{ return red * red + green * green + blue * blue + alpha * alpha; }
		
inline real TMCColorRGBA::GetMinOfRGB(void) const
	{ real min = ( red < green ); return ( min < blue ) ? min : blue; }

inline real TMCColorRGBA::GetMaxOfRGB( void ) const
	{ real min = ( red > green ); return ( min > blue ) ? min : blue; }



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

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


		
inline TMCColorRGBA& TMCColorRGBA::operator+= (const TMCColorRGBA& rhs)
 { { (*this).red += (rhs).red; (*this).green += (rhs).green; (*this).blue += (rhs).blue; (*this).alpha += (rhs).alpha; }; return *this; }

inline TMCColorRGBA& TMCColorRGBA::operator+= (const TMCColorRGB& rhs)
{
	red += rhs.red; green += rhs.green; blue += rhs.blue; return *this;
}

inline TMCColorRGBA& TMCColorRGBA::operator-= (const TMCColorRGBA& rhs)
 { { (*this).red -= (rhs).red; (*this).green -= (rhs).green; (*this).blue -= (rhs).blue; (*this).alpha -= (rhs).alpha; }; return *this; }

inline TMCColorRGBA& TMCColorRGBA::operator*= (const real s)
 { { (*this).red *= (s); (*this).green *= (s); (*this).blue *= (s); (*this).alpha *= (s); }; return *this; }

inline TMCColorRGBA& TMCColorRGBA::operator/= (const real s)
 { { (*this).red /= (s); (*this).green /= (s); (*this).blue /= (s); (*this).alpha /= (s); }; return *this; }




inline TMCColorRGBA TMCColorRGBA::operator+ (const TMCColorRGBA& rhs) const
	{ return TMCColorRGBA(*this) += rhs; }
inline TMCColorRGBA TMCColorRGBA::operator- (const TMCColorRGBA& rhs) const
	{ return TMCColorRGBA(*this) -= rhs; }
inline TMCColorRGBA TMCColorRGBA::operator* (const real s) const
	{ return TMCColorRGBA(*this) *= s; }
inline TMCColorRGBA TMCColorRGBA::operator/ (const real s) const
	{ return TMCColorRGBA(*this) /= s; }

inline real TMCColorRGBA::operator*	(const TMCColorRGBA& rhs) const
	{ return red * rhs.red + green * rhs.green + blue * rhs.blue + alpha * rhs.alpha; }

inline TMCColorRGBA TMCColorRGBA::operator% (const TMCColorRGBA& rhs) const
	{ return TMCColorRGBA( red * rhs.red, green * rhs.green, blue * rhs.blue, alpha * rhs.alpha ); }
		
inline void TMCColorRGBA::AccumRGBA(const TMCColorRGBA& rhs, const real scalar )
 { { (*this).red += (rhs).red * scalar; (*this).green += (rhs).green * scalar; (*this).blue += (rhs).blue * scalar; (*this).alpha += (rhs).alpha * scalar; }; }

inline void TMCColorRGBA::Add(const TMCColorRGB& rhs)
{
 { (*this).red += (rhs).red; (*this).green += (rhs).green; (*this).blue += (rhs).blue; };
}


inline void TMCColorRGBA::AccumRGB(const TMCColorRGBA& rhs, const real scalar )
 { { (*this).red += (rhs).red * (scalar); (*this).green += (rhs).green * (scalar); (*this).blue += (rhs).blue * (scalar); }; }

					


const real* TMCColorRGBA::GetAddrFirstComponent( void ) const 
	{ return &red; }


real TMCColorRGBA::operator[](int32 index) const
{
	MCAssert(index >= 0 && index < 4);
	return GetAddrFirstComponent()[index];
}

real& TMCColorRGBA::operator[](int32 index)
{
	MCAssert(index >= 0 && index < 4);
	return (&red)[index];
}

inline TMCColorRGB &TMCColorRGB::operator= (class TMCColorRGBA &c)
{
	red=c.red;
	green=c.green;
	blue=c.blue;

	return *this;
}


#endif