
//**************************************************************************/
// Copyright (c) 2008 Autodesk, Inc.
// All rights reserved.
//
// Use of this software is subject to the terms of the Autodesk license
// agreement provided at the time of installation or download, or which
// otherwise accompanies this software in either electronic or hard copy form.
//
//**************************************************************************/
// DESCRIPTION:
// CREATED: October 2008
//**************************************************************************/

namespace mudbox {

/// Represents a light source in the scene.
class MBDLL_DECL Light : virtual public GroupNode
{
	DECLARE_CLASS;

protected:
	/// \brief Constructor.  Do not use this directly. Use CreateInstances() instead.
	///
	/// This is the typical way to create a Light:
	/// \code
	///		Light *myLight = CreateInstance<Light>();
	/// \endcode
	Light( void );

public:

	enum LightType
	{
		LIGHT_DIRECTIONAL=0,
		LIGHT_POINT,
		LIGHT_SPOT,
        LIGHT_IBL,
        LIGHT_NONE,
	};

	/// Returns the diffuse color value of the light.
	virtual Color Diffuse( void ) const;
	
	/// Sets the diffuse color value of the light.
	virtual void SetDiffuse(
		const Color &cDiffuse		///< [in] The new color
		);
	
	/// Returns the light intensity in range 0..1
	virtual float Intensity( void ) const;
	
	/// Sets the light intensity in range 0..1
	virtual void SetIntensity(
		float fIntensity		///< [in] The new intensity (0 is no light;  1 is full light)
		);
	
	/// Returns true if the light direction is locked to the camera direction.
	virtual bool IsLockedToCamera( void ) const;
	
    /// Set lock/unlock to camera
    virtual void SetLockedToCamera(
		bool bOnOrOff	///< [in] If \b true, the light will be locked to the camera so that it is always pointing in the same direction.
		);
	
	/// Renders the light manipulator or light geometry, if they are turned on.
	virtual bool Render( void );
	
	/// Returns a pointer to the light's manipulator, or NULL if no manipulator has been created.
	virtual Manipulator *GetManipulator();
	
	/// Checks and updates the shadow map (if shadowing is turned on).
	virtual void ValidateShadowMap();
	
	/// Returns the depth map associated with the light.
	virtual Texture *ShadowDepthMap();
	
	/// \brief Returns the shadow/depth map matrix associated with light.
	///
	/// This matrix is the 'view matrix' of the light.  It is used to render
	/// the scene from the light's perspective (and thus create a depth buffer),
	/// and to transform the main scene depth values into 'light space' so we can
	/// compare the main scene depth values to the light's scene depth values.
	/// This is used to create shadow maps for the light.
	virtual const Matrix &ShadowMatrix() const;
	
	/// Returns \b true if shadow castinging is enabled for this light.
	virtual bool CastShadow();
	
	/// \brief Returns the shadow bias for this light.
	///
	/// Bias does not have a fixed range, but generally lies between -1 & 1.
	/// It is used to offset the depth map either toward the light’s position
	/// or away from it.  This is used to correct any inaccuracies in the depth
	/// comparison caused by precision loss.  (Either when converting the pixel’s
	/// position to light space or in the depth map itself).  Similar to polygon offset in OpenGL.
	virtual float ShadowBias();
	
	/// \brief Returns the type of this light.
	///
	/// Possible return values are Light::LIGHT_DIRECTIONAL, Light::LIGHT_POINT, Light::LIGHT_SPOT, Light::LIGHT_IBL, or Light::LIGHT_NONE.
	virtual LightType Type();
	
	/// \brief Sets the light attenuation value.  Range is from 0-1.
	///
	/// This is called "Light Decay" in the UI.
	virtual void SetAttenuation(float);
	
	/// Returns the light attenuation value.  Range is from 0-1.
	///
	/// This is called "Light Decay" in the UI.
	virtual float Attenuation(void) const;
	
	/// \brief Returns the "locked to camera" matrix
	///
	/// This matrix represents the initial camera matrix (on start up or when the light
	/// is created) multiplied by the inverse of the current camera matrix and the 
	/// inverse of the current light matrix.  Effectively, it is the 'delta' between
	/// the camera position, and the position of a light that is locked to it.
	/// Use this to get the current world space location of a light relative to the camera.  
	virtual Matrix LockedToCameraMatrix() const;
	
    /// Returns the HDRI image associated with this light, if any.  Returns a NULL pointer if this is not an HDRI light.
    virtual Image *HDRImage() const;
	
	// \brief Returns the path to the associated HDRI image, if any.
	//
	// Returns a NULL pointer if this is not an HDRI light.  If a valid String pointer is returned, you should NOT delete it;
	// it is a pointer into the object data.
    virtual const QString *HDRImageFilename() const;
};

}; // end of namespace mudbox
