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

#if defined(JAMBUILD)
#include <Mudbox/mudbox.h>
#else
#include "../../include/Mudbox/mudbox.h"
#endif

using namespace mudbox;

// This structure holds info for a single vertex.
struct VertexInfo
{
	VertexInfo( void ) {};
	VertexInfo( unsigned int iGlobalVertexIndex, unsigned int iVertexIndex, const Vector &vDisp, float fMask, unsigned int iFaceIndex, unsigned int iCornerIndex ) 
	{ 
		m_iGlobalVertexIndex = iGlobalVertexIndex;
		m_iVertexIndex = iVertexIndex; 
		m_vDisplacement = vDisp; 
		m_fMask = fMask; 
		m_iCount = 1;
		m_iFaceIndex = iFaceIndex;
		m_iCornerIndex = iCornerIndex;
	};
	int operator -( const VertexInfo &v ) const { return m_iGlobalVertexIndex-v.m_iGlobalVertexIndex; };
	void Refine( const Vector &vDisplacement, float fMask )
	{
		m_vDisplacement = (m_iCount*m_vDisplacement+vDisplacement)/(m_iCount+1);
		m_fMask = (m_iCount*m_fMask+fMask)/(m_iCount+1);
		m_iCount++;
	};

	unsigned int m_iVertexIndex;
	unsigned int m_iGlobalVertexIndex;
	unsigned int m_iFaceIndex;
	unsigned int m_iCornerIndex;
	float m_fMask;
	Vector m_vDisplacement;
	int m_iCount;
};

struct Tile
{
	unsigned int m_iIndex;
	bool m_bZero;
};

// This is the main class for the plugin.
class DisplaceOperation : public TreeNode
{
	DECLARE_CLASS;

	enum Space
	{
		spaceNormal,
		spaceTangent,
		spaceObject,
		spaceWorld
	};

	// This function is used to convert masked filenames to final ones, replacing the %x %y %i variables with proper values.
	QString GetFileName( const QString &sMask, unsigned int iTile, unsigned int iUPos, unsigned int iVPos ) const;
	// This function is the oposite, converts a real filename to a masked one.
	QString FilterFileName( const QString &sFileName ) const;

public:
	DisplaceOperation( void );

	void Do( void );
	// Main function, called when the operation must be performed.
	void Execute( void );

	// Called by Mudbox when an event occurs with an attribute
	void OnNodeEvent( const Attribute &, NodeEventType eType );
	// Makes it possible to store/restore the data in this object.
	void Serialize( Stream &cStream );
	// This will be called when the plugin is loaded into memory.
	static void Initializer( void );

	// Pointer to the target object.
	aptr<Geometry> m_pObject;
	// Level of subdivision the object.
	aint m_iSubdivisionLevel;
	// True if texture coordinates should be smoothed. This helps preventing seams on the displaced model.
	abool m_bSmoothTC;
	// This is only a feedback attribute to the user.
	aint m_iFinalFaceCount;
	// Space of the displacement map.  By default the displacement map is treated as a regular scalar displacement map.
	aenum m_eMapSpace;

	// Filename mask for the displacement map.
	afilename m_sDisplacementFileMask;
	// Lower value for the displacement range.
	mutable Vector m_vDisplacementMin;
	// Upper value for the displacement range.
	mutable Vector m_vDisplacementMax;
	// Channel to be used in the displacement image.
	aenum m_iDisplacementChannel;
	// Filename mask for the mask image.
	afilename m_sMaskFileMask;
	// Channel to be used in the mask image.
	aenum m_iMaskChannel;

	// Number of tiles in a row.
	aint m_iUDim;
	// Index of the tile on the upper left corner.
	aint m_iFirstTileIndex;
	// String describes which tiles should be processed
	astring m_sTileRange;

	// Push button to execute the operation.
	aevent m_eExecute;
	// Push button to delete the operation
	aevent m_eDelete;

	astring m_sNextCommand;

	// List of tiles to be processed
	unsigned int m_iVDim;
	Store<Tile> m_aTiles;

	bool m_bFloatMap;
	int m_iBaseU, m_iBaseV;
	mutable float m_fGain;
};
