
//**************************************************************************/
// 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 {
	
/// \brief Describes a material of a geometry including its surface colors, transparency and texture information.
///
/// The material class is responsible for the appearance of a surface when its rendered. Each mesh in Mudbox has an
/// associated material, and multiple meshes can use the same material instance.
///
/// When Mudbox renders the mesh, it first uses the associated material to prepare the opengl pipeline for the mesh
/// by calling the Material::Activate() function.
/// The material class is also used to determine the list of paintable textures over the surface. The functions
/// Material::TextureCount() and Material::Texture() are used for this purpose. For more details, see the TexturePool class.
///
/// You can derive from the Material class to create your own custom materials with texture channels that control
/// any parameters you wish. See the SDK examples.
///
/// How to access a specific texture value at a point on the surface:
///
/// 1.  Calculate the texture coordinate associated for the surface point. This can be done by 
///     calculating a linear conbination of the texture coordinates at the corners of the face based on the information
///     you have about where the point is inside the face.
///
/// 2.  Decide which texture are you interested in, by examining the list of textures in the corrseponding
///     material instance by calling the TextureCount() and Texture() functions. You can get the name
///     of a texture by calling the Texture::Name() function. This list is dynamic is because it can changed depending on the material
///     implementation. The default Mudbox material has a fixed list, but materials created
///     from custom cgfx files can have very different texture lists.
///
/// 3.  Since Mudbox supports layers for each texture, you next need to choose the layer you are interested in. To do this, 
///     cast the pointer obtained in step 2 to LayerContainer. Once you have a pointer to a
///     layercontainer instance, you can check the list of layers and their names. Finally you have to cast the 
///     layer to a TexturePool again.
///
/// 4.  Based on your interpolated texture coordinate, you have to select the proper tile in the TexturePool by calling 
///     TexturePool::Tile() function.  (If the UV space of an object goes beyond the range 0-1,
///     Mudbox uses multiple tiles to represent each layer
///		of a texture.) Pass in a bounding box representing the tile you are interested in.
///     For example, if the desired texture coordinate is 1.3, 3.4, then you would pass in a bounding box between ( 1, 3, 0 )
///     and ( 2, 4, 0 ).  (In texture space, the third coordinate is always 0.)  Once you get the tile, you would sample
///		the texel at 0.3, 0.4 within that tile. (See next step)
///
/// 5.  Once you got the texture, copy it to an Image object by calling the Texture::CopyTo() function. You can easily
///     access the color of the needed pixel by calling the Image::ColorAt() function. Note that copying
///     a texture to an image is a slow process, so if you want to sample multiple surface points, it is smart to
///     copy the textures only once, and cache it.
class MBDLL_DECL Material : virtual public TreeNode
{
	DECLARE_CLASS;

	/// This enum describes the usage of additional vertex data. When a direct value is 
	/// specified, the vertex data will be mapped to that channel. When a generic usage 
	/// is specified, the current material object will be asked. See Material::MapVertexData and
	/// VertexDataProvider.
	enum VertexDataUsage
	{
		/// \defgroup GenericValues Generic Values (these must be translated by the Material into a Direct value)
		///@{
		eVDUPosition, ///< Position of the vertex in object space
		eVDUNormal, ///< Normal of the vertex in object space
		eVDUTextureCoordinate, ///< Texture coordinate
		eVDUVertexColor, ///< Color of the vertex
		eVDUBoneIndices, ///< Indices for the vertex in four dimension. \see TransformationPalette
		eVDUBoneWeights, ///< Bone weights in three dimension. The weight of the last bone is calculated from the first three. \see TransformationPalette
		eVDUTangent, ///< Tangent vector in object space.
		eVDUBinormal, ///< Binormal vector in object space.
		///@}

		/// \defgroup DirectValues Direct Values (these values will be used as the final channel for the data)
		///@{
		eVDUDirectTextureCoordinate0, ///< Indicatest the 0th texture coordinate channel.
		eVDUDirectTextureCoordinate1, ///< Indicatest the 1st texture coordinate channel.
		eVDUDirectTextureCoordinate2, ///< Indicatest the 2nd texture coordinate channel.
		eVDUDirectTextureCoordinate3, ///< Indicatest the 3rd texture coordinate channel.
		eVDUDirectTextureCoordinate4, ///< Indicatest the 4th texture coordinate channel.
		eVDUDirectTextureCoordinate5, ///< Indicatest the 5th texture coordinate channel.
		eVDUDirectTextureCoordinate6, ///< Indicatest the 6th texture coordinate channel.
		eVDUDirectTextureCoordinate7, ///< Indicatest the 7th texture coordinate channel.
		///@}

		eVDUNotUsed ///< Means that the data is not used by the material and can be skipped.
	};

protected:
	/// \brief Constructor.  Do not use it directly; Use CreateInstance() instead.
	///
	/// \code
	///		Material *myMaterial = CreateInstance<Material>();
	/// \endcode
	Material( void );  

public:
    ~Material();

	/// \brief Prepares the GPU to draw with this material
	///
	/// This method is called by Mudbox when the material is about to used for a mesh. It should return true if additional rendering
	/// steps are needed. The cColor parameter is only as suggestion, its up to the material class how it uses (or ignores) it.
	virtual bool Activate(
		const Mesh *pMesh,							///< [in] The mesh to be rendered
		const AxisAlignedBoundingBox &cUVArea,		///< [in] The UV tile of the mesh to be rendered (each tile is drawn separately)
		const Color &cColor = Color::white			///< [in] The suggested color for the tile
		);
	
	/// Sets the GPU back to its default state.
	virtual void Deactivate( void );

	/// \brief Returns the overall transparency of the surface. Range 0..1.  Not currently used.
	///
	/// It is up to the material implementation how it handles this overall transparency value.  It can ignore it, but then the 
	/// user wont be able to control the transparency of their objects in the scene. 0 means totally transparent
	/// while 1 means opaque. This is currently not used in mudbox (transparency is always 1) but it might be
	/// used in future versions.
	virtual float Transparency( void ) const;
	
	/// Sets the transparency of the surface. Range 0..1. Called by Mudbox when the user changes the transparency
	/// for an object.  Not currently used.
	virtual void SetTransparency(
		float fTransparency			///< [in] Ranges from 0 (transparent) to 1 (opaque)
		);

	/// \brief Returns \b true if textures should be visible on the rendered surface.
	///
	/// It is up to the material implementation how it handles this parameter.  It is provided in case 
	/// a user wants to turn off texturing in the scene. In that case SetTexturesVisible() is called with
	/// \b false as the parameter.
	///
	/// If textures are set to invisible, then the material implementation should use a
	/// fixed value for the different channels that were using textures.
	virtual bool TexturesVisible( void ) const;
	
	/// Sets if the textures should be visible on the surface.
	virtual void SetTexturesVisible(
		bool bVisible	///< [in] To make textures visible, set this to \b true.
		);

	/// \brief Returns true if the material implementation needs texture coordinates from the mesh.
	///
	/// If you are deriving a new material class, you need to have this method return true if your
	/// material needs texture coordinate information to draw itself properly.
	virtual bool IsTCNeeded( void ) const;
	
	/// \brief Returns true if the material implementation needs tangent and binormal data from the mesh.
	///
	/// If you are deriving a new material class, you need to have this method return true if your
	/// material needs tangent and binormal data to draw itself properly.
	virtual bool IsTNBNeeded( void ) const;

	/// Returns the number of textures associated with the material.
	virtual unsigned int TextureCount( void ) const;
	
	/// Returns a pointer to the specified texture.  Do not delete this pointer.
	virtual class TexturePool *Texture(
		unsigned int iTextureIndex		///< [in] Index of the texture to be returned
		) const;

	/// \brief Loads or unloads the specified uv tile for all textures in this material.
	///
	/// To reduce memory footprint, users may opt to unload some tiles of the texture maps
	/// they are working with.  This method is called by Mudbox to unload (remove from memory)
	/// or load (bring in from disk) those specific tiles.  When a texture tile is unloaded, the
	/// material should use an arbitrary constant value for the channel it represents.
	///
	/// You probably don't need to override this method in your own materials.
	virtual void SetTextureTileLive(
		const AxisAlignedBoundingBox &cUVArea,	///< [in] The UV bounds of the tile you want
		bool bLive								///< [in] Specify \b true to load the tile, \b false to unload it.
		);
	
	/// Returns \true if the specified uv tile is loaded into memory.
	virtual bool IsTextureTileLive(
		const AxisAlignedBoundingBox &cUVArea	///< [in] The UV bounds of the tile you are interested in
		);
	
	/// Returns the number of texture tiles associated with this material.
	virtual unsigned int TextureTileCount() const;
	
	/// Returns the uv area covered by the given tile.
	virtual AxisAlignedBoundingBox TextureTileArea(
		unsigned int iTileIndex		///< [in] The index of the tile of interest.
		) const;

	virtual void ActivateUVArea( const AxisAlignedBoundingBox & );

	/// This function is called to determine the mapping of vertex shader inputs for the material.
	/// The return value must be a direct value. The value eNotUsed should be returned if the data
	/// is not used by the shader.
	virtual VertexDataUsage MapVertexData( 
		VertexDataUsage eUsage ///< [in] The usage to be mapped. This is always a generic value. See VertexDataUsage.
		) const;
};


//-----------------------------------------------------------------------------
/// Represents a texture mixer
class MBDLL_DECL TextureMixer : public Node
{
	DECLARE_CLASS;

protected:
	/// \brief Constructor.  Do not use it directly; Use CreateInstance() instead.
	///
	/// \code
	///		TextureMixer *myTextureMixer = CreateInstance<TextureMixer>();
	/// \endcode
	TextureMixer( void );

public:
	/// Returns the number of the blending modes
	virtual unsigned int BlendModeCount( void ) const;
	
	/// Returns the display name of the specified blending mode
	virtual QString BlendModeName(
		int i		///< [in] Index of the blending mode
		) const;
	
	virtual void SetBlendMode( int iBlendMode ) ;

	/// Set number of layers to blend
	virtual void SetLayerCount(
		unsigned int iLayerCount	///< [in] Number of layers that should be blended in a mix operation.
		);
	
	/// Set mix the data for layer at iLayerIndex
	virtual void SetLayerData(
		unsigned int iLayerIndex,	///< [in] The index of the layer to be altered
		int iTextureID,				///< [in] The ID of the texture for this layer
		float fTransparency			///< [in] The transparency of the layer
		);
	
	/// Mix the layers setup with the SetLayerData method.
	virtual void Mix(
		class Texture *d,			///< [out] A pointer to an existing Texture. It will be overridden with the result of the mixing.
		unsigned int iWidth,		///< [in] The width of the texture to be mixed
		unsigned int iHeight,		///< [in] The height of the texture to be mixed
		enum Image::Format eFormat	///< [in] The image format desired for the result
		);

};

//-----------------------------------------------------------------------------
/// \brief This is a container class for simple textures.
///
/// In Mudbox, textures are confined to a 0 to 1 UV space.  If an object has texture coordinates that go
/// outside this 0-1 space, then multiple texture tiles are used to represent the texture, one tile per unit
/// region in texture space.  This class is a container for all the tiles that comprise a texture.
///
/// Mudbox also uses paint layers (where each layer would have the same number of tiles).  An instance of
/// the TexturePool class can therefore also be a LayerContainer.
/// In this case it is possible to cast a TexturePool pointer into a pointer to a LayerContainer instance,
/// and use the LayerContainer pointer to determine the number of layers and get them.  Each pointer to a layer object
/// can then be cast into a TexturePool object again, which then will be the physical paint layer. See
/// the Material class documentation for more details.
class MBDLL_DECL TexturePool : virtual public Node
{
	DECLARE_CLASS;

protected:
	/// \brief Constructor.  Do not use it directly; Use CreateInstance() instead.
	///
	/// \code
	///		TexturePool *myTexturePool = CreateInstance<TexturePool>();
	/// \endcode
	TexturePool( void );

public:

	enum RenderMode
	{
		renderModeConstantColor,
		renderModeTexture,
		renderModeVertexColor
	};

	enum Location
	{
		locationUnknown,
		locationGPU,
		locationCPU,
		locationDisk
	};

	/// Returns the name of the texturepool.
	virtual QString Name( void ) const;
	
	/// Sets the name of the texture pool.
	virtual void SetName(
		const QString &sName		///< [in] New texture pool name.  If the texture pool is a layer, this is the name of the layer seen in the UI.
		);
	
	/// Returns the render mode of the texture pool. 0=constant color, 1=texture, 2=vertex color
	virtual unsigned int RenderMode( void ) const;
	
	/// Sets the render mode for the texture pool.
	virtual void SetRenderMode( unsigned int iMode );
	
	/// Sets the location for the texture pool.
	virtual void SetLocation( unsigned int iLocation );
	
	/// Gets the location for the texture pool.
	virtual unsigned int Location( void );
	
	virtual TexturePool &operator =( TexturePool &cT );

	/// \brief Returns the number of tiles in a row.
	///
	/// The number of tiles in a TexturePool depends on the texture coordinates of the meshes which are using
	/// the pool. If the mesh has texture coordinates only within the 0-1 range, then only a single tile will be used,
	/// so this function will return 1. But for example when the U texture coordinate is in the range of 0-3 and V
	/// is in the range of 0-2, then six tiles will be used, this function will return 3 (since there are 3 tiles horizontally)
	virtual int Width( void ) const;
	
	/// Sets the number of tiles in a row.
	virtual void SetWidth( int iWidth );
	
	/// \brief Set the file name mask for the texture pool.
	/// 
	/// If there is more than a single tile used in the pool, then the file name will be extended with a string indicating 
	/// which tile it belongs to. The attached string has the format _uX_vY, where X is the horizontal, and Y is the vertical 
	/// coordinate of the tile. For example if the given filename is texture.jpg, then the name for the third tile in the first row
	/// will be texutre_u3_v1.jpg
	virtual void SetFileName(
		const QString &sFileName		///< [in] The base file name for the texture files in this pool
		);
	
	/// Returns the file name mask for the texture pool. The name may contain tile wildcards (%i, %x, %y).
	virtual const QString& FileName( void ) const;
	
	/// Saves the textures into files on the disk.
    /// If the file format is PSD and the material is not null, the uv mesh is drawn in a 
    /// layer above the image layer saved by this function.
	virtual void Save(
		const QString &sFileName = "",		///< [in] The file name to save
		const QString &sFormat = "",			///< [in] The file format in the form "bitDepth,dataType", i.e. "8,i" for 8bit/channel integer. 8,16,32 are valid for bitdepth and i and fp are valid for dataType.
        Material *m = NULL                  ///< [in] The material assciated with this texture pool. 
		);          
	
	/// \brief Sets the dirty status of the texture.
	///
	/// This function must be called after the texture content is changed
	virtual void SetDirty(
		bool bDirty		///< [in] Set to \b true to mark the texture dirty.
		);
	
	/// Gets the dirty status of the texture
	virtual bool IsDirty( void );
	
	/// Adds a point to the dirty region of this texture pool.
	virtual void AddToDirtyArea( 
		const Vector &cPoint	///< [in] the area of the texture pool to mark as dirty
	);

	/// Reload the pool from the files based on the current file name mask
	virtual void Reload( void );
	
	/// Sets a flag to say that the texturepool has been modified.
	virtual void SetContentChanged( void );
	
	/// Returns true if the texturepool has been modified since the last file save
	virtual bool IsContentChanged( void );

	/// Returns the number of created tiles so far. These tiles can overlap.
	virtual unsigned int TileCount( void ) const;
	
	/// Returns a pointer to a specified tile.  Do not delete this pointer.
	virtual class Texture *Tile(
		unsigned int iTileIndex		///< [in] Index of the tile to be returned
		);
	
	/// Returns a texture tile for a coordinate range. Attempts to create the texture if it does not yet exist.
	virtual class Texture *Tile(
		const AxisAlignedBoundingBox &cTCArea,	///< [in] The UV area that corresponds to the desired texture.
		bool bAlloc = true						///< [in] Set this to \b true to guarantee the returned Texture is loaded onto the GPU.
		);
	
	/// Returns the UV area associated with a tile.
	virtual AxisAlignedBoundingBox TileArea(
		unsigned int iTileIndex		///< [in] Index of the tile
		) const;
	
	/// Returns a mixed object for the pool
	virtual TextureMixer *Mixer( void ) const;
	
	/// Returns the blending mode of the pool
	virtual int BlendMode( void ) const;
	
	/// Sets the blending mode
	virtual void SetBlendMode(
		int iMode		///< [in] The index of the desired blending mode (see TextureMixer::BlendModeCount() and TextureMixer::BlendModeName() )
		);

	virtual void SetMaterial(
		Material* pMaterial	///< [in] Set the material associated with this TexturePool.
		);

    virtual Material *GetMaterial() const; /// return the material associated with this texture pool.
};

//-----------------------------------------------------------------------------
/// \brief Represents a texture tile inside a texture pool.
///
/// Textures are like images (see the Image class) in that they are a 2d array of pixel values. Like images, Textures
/// support many formats.  Textures can also be used internally as the target of OpenGL rendering
/// operations -- that is, Mudbox scenes can be rendered into Textures. Textures have
/// the ability to keep old versions of themselves around for undo/redo purposes.
class MBDLL_DECL Texture : virtual public Node
{
	DECLARE_CLASS;

protected:
	/// \brief Constructor.  Do not use it directly; Use CreateInstance() instead.
	///
	/// \code
	///		Texture *myTexture = CreateInstance<Texture>();
	/// \endcode
	Texture( void );

public:
	/// Create/allocate the content of the texture.
	virtual void Create(
		unsigned int iWidth,			///< [in] The width
		unsigned int iHeight,			///< [in] The height
		unsigned int iChannelCount,		///< [in] The number of channels (for example, RGBA would be 4)
		enum Image::Format eFormat,		///< [in] The image format (see the Image class for details)
		const Color &cColor				///< [in] The initial color that the texture should be set to
		);
	
	/// Create/allocate the content of the texture.
	virtual void Create(
		unsigned int iWidth,			///< [in] The width
		unsigned int iHeight,			///< [in] The height
		unsigned int iChannelCount,		///< [in] The number of channels (for example, RGBA would be 4)
		enum Image::Format eFormat		///< [in] The image format (see the Image class for details)
		);
	
	/// Create the texture from an image file.
	virtual bool CreateFromFile(
		const QString &sFileName		///< [in] The name of the image file to be read in
		);
	
	/// Copy the content of the texture into another one, using the current opengl pipeline settings.
	virtual void CopyTo(
		Texture &cTexture		///< [in] The texture to be copied to
		) const;

	/// Returns the width of the texture in pixels.
	virtual unsigned int Width( void ) const;
	
	/// Returns the height of the texture in pixels.
	virtual unsigned int Height( void ) const;
	
	/// Returns the bit depth of the texture (per channel)
	virtual unsigned int BitDepth( void ) const;
	
	/// Returns the format of the texture.
	virtual enum Image::Format Format( void ) const;

	/// \brief Binds the texture node.
	/// 
	/// This call makes the texture active, so that opengl operations will be able to use it. It calls
	/// glBindTexture() internally.
	virtual bool Activate( void ) const;
	
	/// UnBinds the texture node, but does not restore the previous active texture.
	/// The active opengl texture after this call is undefined.
	virtual bool Deactivate( void ) const;

	/// Returns the opengl name of the texture.
	virtual unsigned int OpenGLName( void ) const;

	/// Sets the texture as a render target.  Subsequent renderings will render into that texture.
	virtual bool SetAsRenderTarget( void );
	
	/// Restore previous render target.
	virtual bool RestoreRenderTarget( void );

    virtual abool *getFilteringPref();

	/// Create the texture content from an image.
	virtual void CopyFrom(
		Image *pImage		///< [in] the Image to copy the texture from
		);

    /// Replace the texture with the content from an image
    virtual void ReplaceWith(
		Image *pImage		///< [in] the Image to copy the texture from
        );
	
	/// Copy the texture or a region thereof to an image. If region == 0, it copies the entire texture
	virtual void CopyTo(
		Image *pImage,					///< [in] A pointer to the image target
		bool tiled = true,				///< [in] Set to \b true if this is a tiled image
		const ImgTile *region = 0,		///< [in] Specifies a region to copy (see the ImgTile class)
		ImageDescriptor::MemoryChannelOrder eOrder = ImageDescriptor::orderRGBA		///< [in] Specify what order you want the color channels stored
		);

	/// Sets the location for the texture pool.
	virtual void SetLocation( 
		unsigned int iLocation		///< [in] Location can be one of TexturePool::locationGPU, TexturePool::locationCPU, or TexturePool::locationDisk
		);
	
	/// \brief Gets the location for the texture pool.
	///
	/// Possible values are TexturePool::locationUnknown, TexturePool::locationGPU, TexturePool::locationCPU, or TexturePool::locationDisk
	virtual unsigned int Location( void );

	/// Return the memory usage of all texture instances of the class in bytes.
	virtual int64 TotalMemoryUsage( void ) const;

	/// For internal use only
	virtual void SetLive(
		bool bLive
		);
	
	/// For internal use only
	virtual bool IsLive( void ) const;

    /// \name Undo Mechanism
    /// These methods provide a multi-level undo and redo system for textures.
    //@{

        /// \brief Caches a copy of the current texture.  Returns \b true if successful. 
        ///
	    /// This is part of a Texture's built-in undo mechanism.  Effectively, the current
	    /// version of the texture becomes the previous version, and a fresh copy is now
	    /// the current version.  Any 'next' versions are purged.
        virtual bool NewVersion();                                      

        /// \brief Makes the previous version of the texture current.  Returns \b true if successful.
	    ///
 	    /// This is part of a Texture's built-in undo mechanism.  The current
	    /// version of the texture becomes the next version, and the previous version becomes
	    /// the current version.
        virtual bool PrevVersion();

        /// \brief Makes the 'next' version of the texture current.  Returns \b true if successful.
	    ///
 	    /// This is part of a Texture's built-in undo mechanism.  The current
	    /// version of the texture becomes the previous version, and the next version becomes
	    /// the current version.
        virtual bool NextVersion();

        /// Returns the number of versions of this texture. Returns 1 for unversioned textures.
        virtual int  NumVersions();

        /// \brief Merges the oldest two versions of this texture. Returns \b true if successful.
	    ///
	    /// This is used to limit the number of items on the undo queue.
        virtual bool MergeOldestVersions();

        /// \brief Purges any versions of this texture after the current one (i.e. all "next" versions). Returns \b true if successful.
	    ///
	    /// Creating a new version will implicitly purge newer versions, but if
        /// another operation takes place that puts a new item on the undo queue,
        /// this should be called to purge newer versions of this texture.
        virtual bool PurgeNewerVersions();

        /// Purges all but the current version of this Texture. Used to flush the undo queue. Returns \b true if successful.
        virtual bool PurgeAllButCurrentVersion();

        /// \brief Notifies the texture that you are about to start making undoable changes to it (such as a brush stroke). Returns \b true if successful.
	    ///
	    /// This method calls NewVersion() internally.
        virtual bool BeginUndoableOperation();

        /// Notifies the texture that you have finished making undoable changes to it (such as a brush stroke). Returns \b true if successful.
        virtual bool EndUndoableOperation();

    //@}

		/// Set the texture filtering on this texture
		virtual void SetFiltered( 
			bool bFiltered ///< [in] true to turn filtering on, false to turn filtering off.
			);

		/// Set to true to automatically convert 32 bit floating point textures to 16 bit floating point textures
		/// on the gpu.
		virtual void SetConvert32To16bitFloat( 
			bool bConvert ///< [in] true to convert, false to leave 32 bit float textures as is.
			);

protected:
    ImgTile   m_DirtyTile;

public:

    /// \name Dirty Tile Methods
    /// The dirty tile methods are used by the undo mechanism
    /// so that it only has to save those portions of the 
    /// texture that has been modified.
    
    //@{

        /// Resets the dirty region to be empty
        void ResetDirtyTile() 
        {
            m_DirtyTile = ImgTile(0, 0, 0, 0);       
        }

        /// \brief Notifies the texture that part of it has changed.
	    ///
	    /// Call this when you are modifying a texture, to indicate what part has changed.
        virtual void AddToDirtyTile(
		    int x,	///< [in] The X coordinate of the changed pixel
		    int y	///< [in] The Y coordinate of the changed pixel
		    )
        {
            m_DirtyTile.ExpandToInclude(x, y);
        }

        /// \brief Notifies the texture that part of it has changed.
	    ///
	    /// This is used by the undo mechanism so that it only has to save those
        /// portions of the image that have been modified.  Call this when
	    /// you are modifying a texture.
        virtual void AddToDirtyTile(
		    const ImgTile &t ///< [in] The X coordinate of the changed pixel
		    )
        {
            m_DirtyTile.ExpandToInclude(t.x, t.y);
            m_DirtyTile.ExpandToInclude(t.x+t.nx, t.y+t.ny);
        }

        /// Returns the dirty rectangle of the texture.
        const ImgTile &DirtyTile() const { return m_DirtyTile; }

    //@}
};


//-----------------------------------------------------------------------------
/// \brief RenderTarget is an abstraction of an OpenGL renderbuffer object.
///
/// You can attach multiple textures to the different 'slots' of this RenderTarget,
/// to do multi-target rendering.  Textures attached to slot0, slot1, slot2 and slot3
/// will all get the color;  A Texture attached to slotDepth would get the zbuffer.
class MBDLL_DECL RenderTarget : public Node
{
	DECLARE_CLASS;

	enum Slot
	{
		eSlotColor0 = 0,
		eSlotColor1,
		eSlotColor2,
		eSlotColor3,
		eSlotDepth,
		eSlotCount		// placeholder for last position - not a type of slot
	};

public:
	/// Paints the given texture into the rendertarget, stretching or shrinking it to fill the available space.
	virtual void DrawTexture( 
		const class Texture *pTexture
		);
	
	/// Attaches a texture to the RenderTarget. The texture must have exactly the same size as the target.
	virtual bool Attach(
		mudbox::Texture *pTexture,		///< [in] The texture to be attached to the RenderTarget
		Slot eSlot = eSlotColor0		///< [in] The slot to attach it to
		);
	
	/// Detaches a texture from a slot in the rendertarget.
	virtual void Detach(
		Slot eSlot = eSlotColor0		///< [in] The slot to detach a texture from
		);
	
	/// Returns the attached texture at a given slot.
	virtual mudbox::Texture *Texture(
		Slot eSlot = eSlotColor0	///< [in] The id for the slot being queried
		) const;
	
	/// Returns the width of the rendertarget in pixels.
	virtual unsigned int Width( void ) const;
	
	/// Returns the height of the rendertarget in pixels.
	virtual unsigned int Height( void ) const;
	
	/// Sets the size of the rendertarget in pixels.
	virtual void SetSize(
		unsigned int iWidth,
		unsigned int iHeight
		);

	/// Makes this rendertarget active, but saves the previous one.
	virtual void Activate( void );
	
	/// Restores the previous rendertarget.
	virtual void Restore( void );

	/// \internal Set Multisample tag. To be removed.
	virtual void SetMultisampling( bool bMultisampling );
};

}; // end of namespace mudbox
