/****************************************************************************************************

		VMTypes.h
		Copyright: (c) 2001 Eovia Corp. All rights reserved.

		Author:	Charles
		Date:	10/4/2002

****************************************************************************************************/

#ifndef __VMTypes__
#define __VMTypes__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "MCArray.h"


struct IVPUniversalManipulator;


/// Error codes returned by the vertex modeler
enum ErrorCode
{
	kNoError=0,
	kBranchError=1,
	kOpenPolylineError=2,
	kTooManyPolygons=3,
	kPolygonExists=4,
	kDifferentPolymeshes=5,
	kDuplicateVertices=6,
	kObjectMissing=7,
	kNoLatheAxis=8,
	kUsesPolygon=9,
	kBadStartVertex=10,
	kAmbiguousPath=11,
	kNoPath=12,
	kExtrudingInteriorEdge=13,
	kBadCrossSection=14,
	kNotOnePolyline=15,
	kClosedPolylineError=16,
	kLathingEdgeWithPolygon=17,
	kNothingLoftable=18,
	kBadObjectToImport=19,
	kNoObject=20,
	kBooleanSubstractErr=21,
	kSweepObjectMissing=22,
	kCantBuild=23,
	kCantPerform=24,
	kAlignErr=25,
	kDispDel=26,
	kNotSelect=27
};


///	Coordinate axes
enum CoordAxes
{
	kXAxis=0,
	kYAxis=1,
	kZAxis=2
};

#define kAxisX	'XAXI'
#define kAxisY	'YAXI'
#define kAxisZ	'ZAXI'
#define kAxisCustom	'CAXI'

///////////////////////////////////////////////////////////
// Morphs

// Morph constant (to deprecate ?)
const int32 kNoMorphArea = -1;
const int32 kAllMorphArea = -2;
const int32 kNoMorphTarget = -1;
const int32 kAllMorphTarget = -2;

enum EMorphMode
{
	kMorphDisplayOnly		= 0, //the old "all morph" mode
	kMorphEditingAllowed	= 1, //Edition of morphs is allowed but not active
	kIsEditingMorph			= 2, //Some morphs are currently being edited.
};

struct TMorphID
{
	int32 fMorphAreaIndex;
	int32 fMorphTargetIndex;

	TMorphID(int32 inMorphAreaIndex, int32 inMorphTargetIndex)
	{
		MCAssert( (inMorphAreaIndex >= 0) && (inMorphTargetIndex >= 0) );
		fMorphAreaIndex		= inMorphAreaIndex;
		fMorphTargetIndex	= inMorphTargetIndex;
	}

	boolean operator != (const TMorphID& othr) const { return ((fMorphAreaIndex != othr.fMorphAreaIndex) || (fMorphTargetIndex != othr.fMorphTargetIndex)); }
	boolean operator == (const TMorphID& othr) const { return ((fMorphAreaIndex == othr.fMorphAreaIndex) && (fMorphTargetIndex == othr.fMorphTargetIndex)); }
};


class TMorphIDList
{
public:
	inline int32 GetMorphTargetIndex(int32 inMorphAreaIndex) const
	{
		const int32 idsCount= fMorphIDs.GetElemCount();
		for (int32 idNdx= 0; idNdx < idsCount; idNdx++)
		{
			const TMorphID& currID= fMorphIDs[idNdx];
			if (currID.fMorphAreaIndex == inMorphAreaIndex)
				return currID.fMorphTargetIndex;
		}
		return kNoMorphTarget;
	}

	inline void		SetElemSpace	(int32 inSpace)				{ fMorphIDs.SetElemSpace(inSpace); }
	inline void		AddElem			(const TMorphID& inMorpID)	{ fMorphIDs.AddElem(inMorpID); }
	inline void     RemoveElem      (int32 inSpace)             { fMorphIDs.RemoveElem(inSpace, 1); }
	inline void		EmptyList		()							{ fMorphIDs.ArrayFree(); }

	inline int32	GetElemCount	() const					{ return fMorphIDs.GetElemCount(); }

	inline const TMorphID&	operator[]	(int32 index) const		{ return fMorphIDs[index]; }

	inline boolean			operator == (const TMorphIDList& othr) const	{ return !((*this) != othr); }

	boolean operator != (const TMorphIDList& othr) const
	{
		const int32 othrCount = othr.GetElemCount();
		if (GetElemCount() == othrCount)
		{
			for (int32 morphNdx= 0; morphNdx < othrCount; morphNdx++)
			{
				if ( fMorphIDs[morphNdx] != othr[morphNdx] )
					return true;
			}
		}
		else
			return true;
		return false;
	}
protected:
	TMCArray<TMorphID> fMorphIDs;
};

///////////////////////////////////////////////////////////

enum BoxProjectionMode
{
	eCoverAll='CovA',
	eCoverFrontBack='CovF',
	eNoCover='CovN'
};

enum PlanarProjectionMode
{
	eNoSplit,
	eHorSplitByOrientation,
	eHorSplitByPosition,
	eVerSplitByOrientation,
	eVerSplitByPosition
};

#define kThickOffset 10
enum EExtrudeMode
{
	kNormal=0, // extrusion along the normal
	kParallelFaces,
	kConstantFaces,
	kConstantSection,
	kSweepExtrusion,
	kThickNormal=kThickOffset, // Same modes, but the adjacent polygons are extruded together
	kThickParallelFaces,
	kThickConstantFaces,
	kThickConstantSection,
	kThickSweepExtrusion,
	kUnknownExtrudeMode=0xFFFFFFFF
};

enum ETesselateMode
{
	eVertexToCenter=0,
	eMidedgeToCenter,
	eMidedgeToMidedge,
	eUnknownTesselateMode=0xFFFFFFFF
};

enum ESelectType
{
	eSelect=0,
	eNonSelect,
	eAll,
	eUnknownSelectType=0xFFFFFFFF
};

enum EPolyVerticesConstraints
{
	eNoConstraints=0,
	eNotPolygon,	///< non-polygon polyline
	ePolygon,		///< polygon polyline
	eConnected,		///< all the adjacent selected vertices ( its more a cloud of points than a polyline )
	eUnknownConstraint=0xFFFFFFFF
};

enum EFacetMeshType
{
	eWeightPaintingMeshNoUV,		///< for weight painting
	eWeightPaintingMeshWithUV,		///< for weight painting
	eModelingMeshNoUV,				///< for the modeling we do not need the uvs and need to hide hidden vertices. Get also the color per polygon
	eModelingMeshWithUV,
	eMorphNoUV,						///< mesh with the morph influence only
	eMorphWithUV,					///< mesh with the morph influence only
	eFinalNoUV,						///< mesh with the morph and the bone influence
	eFinalWithUV,					///< mesh with the morph and the bone influence
	eFullMesh,						///< For the scene preview
	eMeshWithoutSkinningNorMorph,	///< Mesh without any skinning nor morphs
	eUVEditingMode,
	eUnknownMeshType=0xFFFFFFFF
};

#define kModelMode			'Mdel'
#define kMorphMode			'Mrph'
#define kSkinMode			'Skin'
#define kUVEditMode         'UVed'


struct SSOAData : public TMCObject
{
	enum ESOAMode
	{
		kSpline,
		kLinear,
		kSpiky,
		kBumpy
	} fMode;

	enum ESOASelectionMode
	{
		kUnselected,
		kSelected
	} fSelectionMode;

	real		fRadius;
	TVector3	fCenter;
};


struct EdgeData : public TMCObject
{
	TVector3 vp1;
	TVector3 vp2;
	boolean isSelected;
};


struct RayPlane : public TMCObject
{
	TVector3 fOrigin;
	TVector3 fNormal;
};


struct FatRay : public TMCObject
{
	TVector3 fDirection;
	TVector3 fOrigin;
	TMCArray<RayPlane> fRayPlanes; // large zone arround the selection point
	TMCArray<RayPlane> fRayPlanesPrecise;	// smaller zone: if something is found in it, it's going to be prioritary
											// over others objects in the area.
};

/// Vertex primitive action
struct IVPAction: public IMCUnknown 
{
public:
	enum EVPActionKind
	{
		kVPATrackBall,
		kVPAResize,
		kVPAOffset,
		kVPAMoveSelection,
		kVPASelection,
		kVPACrease,
		kVPAGeneral,
		kVPAGeneralMove,
		kVPAExtrude,
		kVPAMorphTargetAddedRemoved,	// does not save and restore the offsets just the animated parameters
		kVPAUVModified,
		kVPAUVSelection,

		kInvalidVPActionKind = 0xFFFFFFFF
	};
	virtual void MCCOMAPI Do() =0;
	virtual void MCCOMAPI Undo() =0;
	virtual void MCCOMAPI Redo() =0;
	virtual ErrorCode MCCOMAPI BeginTracking(void* data) =0;
	virtual void MCCOMAPI ContinueTracking(void* data1, void* data2) =0;
	virtual void MCCOMAPI FinishTracking() =0;
	virtual void MCCOMAPI SetExtraData(void* data) {}

	// *************************************************************************
	// RestoreLastMeshCopy()
	// Same as Undo() except it does not store a copy of the current mesh 
	// but only restores the copy of the last saved mesh (from the last Undo())
	// *************************************************************************
	virtual void MCCOMAPI RestoreLastMeshCopy() = 0;

	// To know softsel/orientation....
	virtual void SetUniversalManipulator(IVPUniversalManipulator *um) = 0;

	// Symmetry
	virtual void MCCOMAPI SetSymmetryFlag(boolean useSymmetry, boolean keepSymmetry) = 0;
};



#endif
