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

/// This is the base class for anything which is an element of a list with a fixed order
/// and a transparency value assigned to each element. Examples of derived classes are
/// Mudbox's sculpt layers, paint layers, and viewport filters.
class MBDLL_DECL Layer : virtual public TreeNode
{
	DECLARE_CLASS;

public:
	/// Returns the current transparency of the layer.  0 is fully transparent, 1 is opaque.
	virtual float Transparency( void ) const;
	
	/// Sets the transparency of the layer.
	virtual void SetTransparency(
		float fTransparency		///< [in] Transparency value, between 0 and 1.  0 is fully transparent, 1 is opaque.
		);

	/// Returns a pointer to first child of this item, or NULL if this item has no children.
	virtual Layer *Children( void ) const;
	
	/// Returns a pointer to the next item with the same parent as this one.
	virtual Layer *Next( void ) const;
	
	/// Returns a pointer to the previous item with the same parent as this one.
	virtual Layer *Prev( void ) const;
	
	/// Returns a pointer to the object containing this layer.
	virtual class LayerContainer *Container( void ) const;
};

/// This class contains and manages a list of Layers.
class MBDLL_DECL LayerContainer : virtual public TreeNode
{
	DECLARE_CLASS;

public:
	/// Returns the number of layers in the container.
	virtual unsigned int LayerCount( void ) const;
	
	/// Returns a pointer to a contained layer, based on its index in the list
	virtual class Layer *Layer(
		unsigned int iLayerIndex	///< [in] index of the layer to return (0-based)
		) const;
		
	/// Returns the index of the specified layer in the container.  If the layer in not in the container, either -1 or a value equal to LayerCount() will be returned.
	virtual unsigned int LayerIndex(
		class Layer *pLayer			///< [in] A pointer to the layer whose index you want.
		) const;
	
	/// Removes a layer from the container.  The layer is not deleted.
	virtual void UnlinkLayer(
		class Layer *pLayer		///< [in] A pointer to the layer to be removed
		);
	
	/// Adds a new layer to the container.
	virtual void AddLayer(
		class Layer *pLayer		///< [in] A pointer to the layer to be added
		);
	
	/// Creates a new layer and returns a pointer to it.
	virtual class Layer *CreateLayer( void );
	
	/// Returns a pointer to the current (active) layer
	virtual class Layer *ActiveLayer( void ) const;
	
	/// Sets the current (active) layer
	virtual void SetActiveLayer(
		class Layer *pLayer		///< [in] A pointer to the layer to be made current
		);
		
	/// Moves the layer before or after the specified one in the list
	virtual void MoveLayer(
		class Layer *pLayer,	///< [in] A pointer to the layer to be moved
		class Layer *pWhere,	///< [in] A pointer to the destination
		bool bBefore			///< [in] If \b true, the layer is moved to immediately before the destination.  If \b false, it is moved to immediately after.
		);
	
	/// Makes this layer as a child of another one
	virtual void ReparentLayer(
		class Layer *pLayer,	///< [in] The layer to move
		class Layer *pParent	///< [in] Its new parent
		);
	
	/// Returns the base layer
	virtual class Layer *BaseLayer( void ) const;

	/// Reads/writes this object to/from a data stream
	virtual void Serialize(
		Stream &s		///< [in] the data stream
		);
};

/// \brief This class represents a Sculpt Layer.
///
/// A sculpt layer stores offsets (deltas) to the vertex positions of a mesh.  When the 
/// layer is visible, the offsets are added to the mesh (scaled according to the transparency
/// factor).  Sculpt layers also support Masking, where each vertex in the sculpt layer also has
/// a mask value, which it is multiplied by.  This allows the content of the layer to be attenuated
/// locally (using the mask) or globally (using the transparency value) with no loss of data.
///
/// Sculpt layers only keep offset information for those vertices that have actually changed.
/// For that reason, the index of a vertex within a sculpt layer is not the same as the index
/// of a vertex within the model.
///
/// See also SubdivisionLevel::AddLayer().
class MBDLL_DECL LayerMeshData : public TreeNode
{
	DECLARE_CLASS;
public:
	/// Set the name of the layer.
	virtual void SetName(
		const QString &sName		///< [in] the new layer name
		);

	/// Gets the name of the layer.
	virtual QString Name( void ) const;
	
	/// Gets the visibility of the layer.
	virtual bool Visible() const;

	/// Sets the visibility of the layer.
	virtual void SetVisible( bool bVisible );

	/// Sets the transparency of the layer.
	virtual void SetTransparency(
		float fTransparency		///< [in] Transparency value, between 0 and 1.  0 is fully transparent, 1 is opaque.
		);

	/// Returns the current transparency of the layer.  0 is fully transparent, 1 is opaque.
	virtual float Transparency( void ) const;

	/// \brief Returns the index of a vertex in a sculpt layer.
	///
	/// Vertices in a sculpt layer do not have the same index as vertices in a mesh.  This method
	/// takes a mesh vertex index and finds the corresponding sculpt layer vertex index.
	///
	/// \b Note: This is a slow function, so return values should be cached if the index will be used 
	/// multiple times to modify/get vertex data.
	virtual unsigned int VertexIndex (
		unsigned int iVertexIndex,  ///< [in] Index of the vertex inside the mesh.
		bool bCreate = true		///< [in] Create the index if it doesn't exist
		);
	
	/// \brief Set the number of vertices in the layer.
	///
	/// The number of vertices in a sculpt layer may be smaller than the number of vertices
	/// in a model level, because the sculpt layer only keeps information on vertices that
	/// have changed.
	virtual void SetVertexCount(
		unsigned int iVertexCount	///< [in] The desired number of vertices for the layer
		);
	
	/// Returns the number of vertex deltas in this layer.
	/// See SetVertexCount()
	virtual unsigned int VertexCount() const;

	/// Returns the mesh's vertex index for the corresponding layer vertex index.
	/// See SetVertexCount()
	virtual unsigned int MeshVertexIndex( 
		unsigned int iLayerVertexIndex  ///< [in] The index inside the layer. Valid range is 0 to VertexCount() - 1
		) const;

	/// Set the mask value belonging to a vertex in the layer.
	virtual void SetVertexData( 
		unsigned int iVertexLayerIndex, ///< [in] Index of the vertex inside the layer. See VertexIndex().
		unsigned int iGlobalVertexIndex, ///< [in] Index of the vertex inside the mesh.
		float fMask  ///< [in] New mask value for the vertex, which must be between 0 and 1.  0 means no mask;  1 is completely masked.
		);
		
	/// Set the delta position stored for a vertex in the layer.
	virtual Vector SetVertexDelta( 
		unsigned int iVertexLayerIndex, ///< [in] Index of the vertex inside the layer. See VertexIndex().
		unsigned int iLocalVertexIndex, ///< [in] Index of the vertex inside the mesh.
		const Vector &vDelta, ///< [in] New delta vector for the vertex. This vector will be added to the world space position of the vertex when the layer becomes visible.
		bool bUpdate = true ///< [in] True to automatically update the mesh's corresponding vertex positions, false to only update the sculpt layer's delta.
	);
		
	/// Returns the mask of a vertex in the layer.
	virtual float VertexMask(
		unsigned int iVertexLayerIndex ///< [in] Index of the vertex inside the layer. See VertexIndex().
		);
		
	/// Returns the current delta value associated to a vertex.
	virtual Vector VertexDelta(
		unsigned int iVertexLayerIndex ///< [in] Index of the vertex inside the layer. See VertexIndex().
		);

	/// After creating new vertex deltas (by calling VertexIndex with bCreate set to true) call this
	/// method to commit the changes into the layer. This method can be called once, after all vertex data 
	/// has been set for the operation.
	/// Returns true on success, false otherwise.
	virtual bool FinishChanges();
};

}; // end of namespace mudbox
