
//**************************************************************************/
// 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 {

class ViewPortFilter;

/// Holds all the information about the current viewport state, used by ViewPortFilter objects.
struct ViewPortState
{
	Texture *m_pColor;
	Texture *m_pDepth;
	Texture *m_pPosition;
	Texture *m_pNormal;
	Texture *m_pLinearDepth;
	Texture *m_pFaceNormal;
	bool m_bHDRNeeded;
};

/// \brief ViewPortFilters are post-processes that are applied to the rendered scene before display.
///
/// Mudbox first renders the meshes in the scene, then goes through its list of ViewPortFilters.
/// Any filters with visibility turned on are applied to the resulting image, yielding the new
/// image that is displayed.  This base class ViewPortFilter does nothing;  you must derive new
/// filters from it.
class MBDLL_DECL ViewPortFilter : public Layer
{
	DECLARE_CLASS;
public:

	/// The RequirementValue typedef is used to tell Mudbox what information needs to be
	/// calculated at render time so that this ViewPortFilter can work properly.  The
	/// elements in this list can be combined with a bitwise or (|) operator. This is
	/// used in the Requirements method.
	typedef int RequirementValue;
	enum
	{
		eNone = 0,
		eColor = 1,
		eHDR = 2,
		eDepth24 = 4,
//		ePosition16 = 8, // not implemented
		eNormal16 = 16,
		ePosition32 = 32,
//		eNormal32 = 64, // not implemented
		eNormalDepth16 = 128,
//		eNormalDepth32 = 256, // not implemented
		eLinearDepth = 512,
		eFaceNormal = 1024,
	};

	/// This is called after construction to initialize internal variables
	virtual void Initialize(void);

	/// \brief Returns a value that indicates what information is required by the ViewPortFilter.
	///
	/// When you create your own ViewPortFilter, you must override this method.
	/// Mudbox only calculates things like depth maps or normal maps when requested,
	/// so you must figure out what information is needed as input to your viewport
	/// filter, and have this function return the appropriate flags.
	virtual RequirementValue Requirement( void ) const;

	/// \brief Process the Mudbox view through the ViewPortFilter
	///
	/// This method does the actual work of filtering the viewport.
	/// Derived ViewPortFilters must override it. It takes the information
	/// provided in the ViewPortState that is passed in, and puts the resulting
	/// (filtered) image in the m_pColor texture of that object.
	/// This method must be overridden by derived classes.
	virtual void Process(
		ViewPortState &sState	///< [in|out] The textures used by this filter, and the result
		);

	/// This method is not used in ViewPortFilters.
	virtual float Transparency( void ) const;

	/// This method is not used in ViewPortFilters.
	virtual void SetTransparency(float fTransparency);

	/// This method is not used in ViewPortFilters.
	virtual Layer *Children( void ) const;

	/// This method is not used in ViewPortFilters.
	virtual Layer *Next( void ) const;

	/// This method is not used in ViewPortFilters.
	virtual Layer *Prev( void ) const;

	/// This method is not used in ViewPortFilters.
	virtual class LayerContainer *Container( void ) const;

	/// Turns the ViewPortFilter on and off.
	void SetVisible(
		bool bVisible  ///< [in] Set this \b true to make the filter visible, and \b false to hide it.
		);

	/// \brief This method locks any calibration the ViewPortFilter does
	///
	/// Some kinds of ViewPortFilters do a calibration step as part of the
	/// process.  For example, all the values produced may be normalized to
	/// the range of values currently displayed.  This can be a problem when
	/// you need to generate multiple images where the calibration must be
	/// the same (say, to make a large tiled image, or an animation).  Locking
	/// calibration tells the ViewPortFilter to leave its calibration values
	/// at the current level, rather than recalculating per-frame.
	///
	/// Derived ViewPortFilters probably do not need to override this method, but
	/// they should pay attention to the flag.  If you do need to override the
	/// method, ensure the derived method calls the base method so that the
	/// flag will be set properly.
	virtual void LockCalibration(
		bool bLock	///< [in] Set this \b true to lock calibration, and \b false to unlock it
		);

	/// Returns \b true if the ViewPortFilter calibration is locked
	bool CalibrationLocked(void);

	/// A pointer to the Viewport containing this ViewPortFilter
	class ViewPort *m_pViewPort;

protected:
	bool m_bCalibrationLocked;
};


/// Represents the 3D viewport where Mudbox renders the scene
class MBDLL_DECL ViewPort : public LayerContainer
{
	DECLARE_CLASS;

public:
	/// Returns the number of ViewPortFilters associated with this ViewPort
	virtual unsigned int FilterCount( void ) const;

	/// Returns a pointer to a ViewPortFilter associated with this ViewPort
	virtual ViewPortFilter *Filter(
		unsigned int iIndex	///< [in] index of the ViewPortFilter to be returned
		) const;

	/// Associates a ViewPortFilter with this ViewPort
	virtual void AddFilter(
		ViewPortFilter *pFilter	///< [in] a pointer to the ViewPortFilter to be added
		);

	/// Removes a ViewPortFilter that was associated with this ViewPort.  The filter is not deleted.
	virtual void RemoveFilter(
		unsigned int iIndex	///< [in] index of the ViewPortFilter to be removed
		);

	/// Locks/unlocks the calibration of all viewport filters associated with this ViewPort. (See ViewPortFilter::LockCalibration())
	void LockFilterCalibration(
		bool bLocked ///< [in] Set this \b true to lock calibration, and \b false to unlock it
		);

	/// \brief Saves a snapshot of the current viewport to the given image file name.
	///
	/// The file type will be determined by the extension of the file name (eg .png,
	/// .bmp, .tif).
	///
	/// See also Kernel()->RenderScene() for a more flexible method.
	virtual void SaveScreenshot(
		const QString &sFileName	///< [in] Name of the image file where the screenshot should be saved
		) const;

	/// Returns the width of the ViewPort in pixels
	virtual int Width( void );

	/// Returns the height of the ViewPort in pixels
	virtual int Height( void );

    /// Returns the current image plane
    class ImagePlaneInterface *ActiveImagePlane();

	/// Returns the current cursor horizontal position inside the viewport in the 0-1 range
	virtual float CursorXPosition( void ) const;

	/// Returns the current cursor vertical position inside the viewport in the 0-1 range
	virtual float CursorYPosition( void ) const;

	/// Returns the surface point which is under the cursor
	const SurfacePoint *CursorSurfacePoint( void ) const;

	/// This is the same as FilterCount()
	unsigned int LayerCount( void ) const;

	/// This is the same as Filter()
	class Layer *Layer(
		unsigned int iLayerIndex	///< [in] index of the layer (filter) to be returned
		) const;

	/// This is the same as RemoveFilter()
	void UnlinkLayer(
		class Layer *pLayer	///< [in] index of the layer (filter) to be removed
		);

	/// Returns a new ViewPortFilter
	class Layer *CreateLayer( void );

	/// This is the same as AddFilter()
	void AddLayer(
		class Layer *pLayer	///< [in] a pointer to the layer (filter) to be added
		);

	/// Returns a pointer to the active layer (filter).  That is, the one last clicked on by the user
	class Layer *ActiveLayer( void ) const;

	/// Set a layer (filter) to be the active one
	void SetActiveLayer(
		class Layer *pLayer	///< [in] a pointer to the layer (filter) to be made active
		);

	/// Returns the combined requirements of all visible ViewPortFilters associated with this ViewPort
	ViewPortFilter::RequirementValue ViewPortFilterRequirements( void ) const;

	/// This type controls the behaviour of the Redraw function, used as a parameter there.
	enum RedrawType
	{
		eFull, /// Schedule a full redraw of the 3d viewport later, ViewPort::Redraw returns immediately when this parameter is used.
		eArea, /// Schedule a redraw of the 3d viewport for the specified area only, ViewPort::Redraw returns immediately when this parameter is used.
		eOverlayOnly /// Redraws the overlay part of the viewport right away. The 3d content is not redrawn.
	};

	/// \brief Calling this function will redraw the viewport.
	void Redraw( 
		RedrawType eType = eFull, ///< [in] This parameter determined what should be affected by the function. See ViewPort::RedrawType for mode details.
		float fXStart = 0, ///< [in] Left side of the area which has to be refreshed in the 0-1 intervall. Ignored if eType != eArea.
		float fYStart = 0, ///< [in] Top side of the area which has to be refreshed in the 0-1 intervall. Ignored if eType != eArea.
		float fXEnd = 0, ///< [in] Right side of the area which has to be refreshed in the 0-1 intervall. Ignored if eType != eArea.
		float fYEnd = 0 ///< [in] Upper side of the area which has to be refreshed in the 0-1 intervall. Ignored if eType != eArea.
		);
	/// Returns the viewport state structure
	virtual struct ViewPortState ViewPortState( void );
};

}; // end of namespace mudbox
