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

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

		Author:	Charles
		Date:	10/4/2002

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

#ifndef __I3DExVertexPrimitive__
#define __I3DExVertexPrimitive__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "MCCompObj.h"
#include "InterfaceIDs.h"
#include "VMTypes.h"
#include "IMorphArea.h"
#include "IEdge.h"
#include <MCSMPCountedObject.h>
#include <MCCountedPtrArray.h>

struct I3DExVertex;
struct IPolygon;
struct IPolymesh;
struct VMDataStruct;
struct SVPStatus;
struct IMFTextPopupPart;
struct I3dExSkinable;
struct SReplicate;
struct I3DExModifier;
struct IWorkingBoxPlane;
struct FacetMesh;
struct UVSpaceInfo;
struct IShComponent;
class  TVertexSkinInfo;
class  TSegmentMesh;
class  TPointMesh;
class  TVertexPrimSkinInfo;
struct IMCFile;
class  TBBox2D;
class  TIndex2;


//****** Globally Unique Ids *************************************************

MCDEFINE_GUID_SAFELIB2(IID_I3DExVertexPrimitive, R_IID_I3DExVertexPrimitive);


//****************************************************************************
//  I3DExVertexPrimitive
//
//    Interface of the vertex primitive
//
//****************************************************************************


struct IVertexCallback
{
	virtual boolean WantsVertexPosition(EFacetMeshType& outMeshType) = 0;

	virtual void	SetVerticesCount(int32 count) = 0;
	
	virtual void	VertexPosition(const TVector3& position) = 0;
	virtual void	Vertex(I3DExVertex* vertex) = 0;
};

struct IPolygonCallback
{
	virtual void	SetPolygonCount(int32 count) = 0;
	virtual void	Polygon(IPolygon* polygon) = 0;
};


struct IMorphTargetUndoInfo : public IMCUnknown 
{
};


struct I3DExSkinningAlgorithm;
struct TWorkingBoxInfo;

/// \addtogroup ExternalInterface
///
/// \{

enum EMorphTargetStorageType
{
	eCompactMorphTarget=0,
	eModelingMorphTarget=1
};

//-- External Animation keyframing
#define		kPolymeshGroupParam			'PMSH'	// Polymesh group (TVMPolymesh::RegisterParams)
#define		kMorphAreaGroupParam		'MRPH'	// Morph Area group (TVMMorphArea::RegisterParams)


struct TModelerDataFlags
{
	TModelerDataFlags() :
			fBuildVertexMesh(true),fBuildEdgeMesh(true),
			fUsePolygonColor(true),fWithNormals(true),
			fBuildApproxBBox(false)
	{
	}

	uint32		fBuildVertexMesh:1;
	uint32		fBuildEdgeMesh:1;
	uint32		fUsePolygonColor:1;
	uint32		fWithNormals:1;
	uint32		fBuildApproxBBox:1;
};
struct TLevelOfDetailsData : public TMCSMPCountedObject
{
	TLevelOfDetailsData() {;}
	TLevelOfDetailsData(const TLevelOfDetailsData& other):fName(other.fName), fFilePath(other.fFilePath) {;}
	TLevelOfDetailsData& operator= (const TLevelOfDetailsData& other)
	{
		if (this != &other)
		{
			fName = other.fName;
			fFilePath = other.fFilePath;
		}
		return *this;
	}
	~TLevelOfDetailsData() {;} // Currently this class is not expected to be inheritible.
	TMCDynamicString fName;
	TMCDynamicString fFilePath;
};
struct ILevelOfDetailsManager
{
	struct ILevelOfDetailsDistanceSelection
	{
		int16 fLODIndex;
		real32 fDistance;
	};
	enum ELODSelectionCriterion
	{
		kFunctionalityLODSelectionCriterion,
		kDistanceLODSelectionCriterion
	};
    virtual int16 GetNbLOD() const = 0;
    virtual void AddLOD(TLevelOfDetailsData *lodToAdd, TMCCountedPtrArray<IPolymesh>& lodMesh) = 0;
    virtual void RemoveLOD(int16 lodIndex) = 0;
	/// Check if a LOD by the specified name is already in the list, for this test "Base" is in the list and is considered the name of the base mesh
	virtual boolean HasLODByName(const TMCString& queryName) = 0;
	virtual ELODSelectionCriterion GetLODSelectionCriterion()  const = 0;
	virtual void SetLODSelectionCriterion(ELODSelectionCriterion selectedCriterion) = 0;
	virtual const TMCString& GetLODName(int16 lodIndex) const = 0;
	virtual void SetLODName(int16 lodIndex, const TMCString& newName) = 0;
	virtual const TMCArray<int16>& GetLODDisplayPermutation() const = 0;
	virtual void SetLODDisplayPermutation(const TMCArray<int16>& newPermutation) = 0;
	virtual int16 GetRenderingLODIndex() const = 0;
	virtual void SetRenderingLODIndex(int16 newVal) = 0;
	virtual int16 GetViewportLODIndex() const = 0;
	virtual void SetViewportLODIndex(int16 newVal) = 0;
	virtual const TMCArray<ILevelOfDetailsDistanceSelection>& GetDistanceSelectionArray() const = 0;
	virtual void SetDistanceSelectionArray(const TMCArray<ILevelOfDetailsDistanceSelection>& newArray) = 0;
	// Get the appropriate LOD for the viewport according to the specified distance.
	virtual int16 GetLODIndex(real32 distance) const = 0;
	// Get the index of the specified LOD, if contained in the manager, otherwise kUnusedIndex
	virtual uint32 GetLODIndexForData(TLevelOfDetailsData *lodToSearch) const = 0;

};
/// <P>I3DExVertexPrimitive is the main interface to access a vertex primitive. 
/// It can be useful if you want to export directly a vertex primitive (this 
/// allow to access the polygons data without having to go through triangulation).</P>
///
/// <P>You can query this interface (using QueryInterface) to know if a given primitive
/// is a vertex primitive. If the primitive supports this interface it means that it
/// is a vertex primitive.</P>
///
struct I3DExVertexPrimitive: public IMCUnknown 
{

	// ****************************************************************************
	//								Hydrate
	// 
	/// Called by the modeler when it is hydrated.
	///
	virtual void MCCOMAPI Hydrate()=0;

	// ****************************************************************************
	//								Dehydrate
	// 
	/// Called by the modeler when it is dehydrated.
	///
	virtual void MCCOMAPI Dehydrate()=0;

	//	Vertex modeler interface methods

	// ****************************************************************************
	//								GetNbPolymeshes
	// 
	/// Returns the number of Polymeshes in the primitive.
	///
	virtual long MCCOMAPI GetNbPolymeshes()=0;

	// ****************************************************************************
	//								GetNbEdges
	// 
	/// Returns the total number of edges in the primitive.
	///
	virtual long MCCOMAPI GetNbEdges()=0;

	

	virtual long MCCOMAPI GetNbPolygons()=0;
	virtual void MCCOMAPI GetPolymesh(IPolymesh** polymesh, long index) =0;

	// ****************************************************************************
	//								GetBoundingBox
	// 
	/// Returns the bounding box of the vertex primitive. To get the 
	///	bounding box of the selection, set selection to true.
	///
	/// \param ignoreSkining	False: return invalid bbox if skinned.
	/// \param selection		Set to true to get the bounding box of the selection.
	/// \param bbox				The bounding box of the primitive that is returned.
	///
	virtual void MCCOMAPI GetBoundingBox(TBBox3D& bbox, boolean ignoreSkining, boolean selection=false) =0;

	virtual void MCCOMAPI GetUVBoundingBox(TBBox2D& bbox, boolean selection=false) =0;

	virtual long MCCOMAPI Pick(void** obj, long flags, FatRay& fatRay, TVector3& hitPosition) =0;
	virtual int32 MCCOMAPI PickUV(void** obj, TIndex2& index, const TVector2& position, real32 raySize) =0;
	virtual void MCCOMAPI DeleteSelectedEdges()=0;
	virtual void MCCOMAPI DeleteSelectedVertices(boolean useSymmetry)=0;
	virtual void MCCOMAPI DeleteSelectedPolygons(boolean useSymmetry)=0;

	// ****************************************************************************
	//								CreatePolyhedra
	// 
	/// Create a polyhedra based on one of this platonic polyhedron:
	///	tetrahedra (4 polygons), cube (6 polygons), octahedra (8 polygons),
	///	dodecahedra (12 polygons), icosahedron (20 polygons) and then subdived it
	///
	/// \param numPolygons	The number of polygons wanted ( this number might not be the number of polygons
	///						on the polyhedra: the polyhedra created will used the most suitable number for 
	///						the number of polygons wanted )
	///
	/// \param bbox			The bounding box countaning the polyhedra
	///
	/// \return	A pointer to the created polymesh
	///
	virtual IPolymesh* MCCOMAPI CreatePolyhedra(long numPolygons,TBBox3D* bbox) =0;							

	// ****************************************************************************
	//								CreateSphere
	// 
	/// Creates a sphere.
	///
	/// \param circumferenceCount	Number of edges arround the sphere.
	/// \param halfSectionCount		Number of section over and under the equador.
	/// \param bbox					The bounding box countaning the sphere.
	/// \param axis					Axis of the sphere.
	///
	/// \return	A pointer to the created polymesh
	///
	virtual IPolymesh* MCCOMAPI CreateSphere(int32 circumferenceCount, int32 halfSectionCount, TBBox3D* bbox, CoordAxes axis )=0;

	// ****************************************************************************
	//								CreateCone
	// 
	/// Creates a cone.
	///
	/// \param baseSegmentCount		Number of edges arround the base.
	///	\param heightSegmentCount	Number of section to the top.
	///	\param bbox					The bounding box countaning the polyhedra.
	///	\param axis					Axis of the cone.
	///
	/// \return A pointer on the created polymesh
	///
	virtual IPolymesh* MCCOMAPI CreateCone(int32 baseSegmentCount,int32 heightSegmentCount,TBBox3D* bbox,CoordAxes axis)=0;

	// ****************************************************************************
	//								CreateCylinder
	// 
	/// Creates a cylinder
	///
	/// \param numPolygons	Number of edges arround the base
	///	\param numSegments	Number of section to the top
	///	\param bbox			The bounding box countaning the polyhedra
	///	\param axis			Axis of the cylinder
	///
	/// \return	A pointer to the created polymesh
	///
	virtual IPolymesh* MCCOMAPI CreateCylinder(int32 numPolygons,int32 numSegments,TBBox3D* bbox,CoordAxes axis) =0;			

	// ****************************************************************************
	//								CreateCube
	// 
	/// Creates a cube.
	///
	/// \param bbox The bounding box countaning the cube.
	///	\param segmentation Tesselation by face.
	///
	/// \return	A pointer to the created polymesh.
	///
	virtual IPolymesh* MCCOMAPI CreateCube(TBBox3D* bbox, int32 segmentation) =0;				

	// ****************************************************************************
	//								CreateMesh
	// 
	/// Creates a mesh (grid).
	///
	/// \param numU: number of section along u axis
	///	\param numV: number of section along v axis
	///	\param uAxis: X,Y or Z
	///	\param vAxis: X,Y or Z
	///	\param du: length of 1 section along u
	///	\param dv: length of 1 section along v
	///	\param center
	///	\param crease
	///
	/// \return	A pointer to the created polymesh
	///
	virtual IPolymesh* MCCOMAPI CreateMesh(	long numU,long numV,CoordAxes uAxis,CoordAxes vAxis,
											real du,real dv,TVector3 &center, boolean crease=false) =0;							

	virtual IPolymesh* MCCOMAPI  CreateMesh2(long numU,long numV,const TVector3 &uAxis,const TVector3 &vAxis,
		real du,real dv,const TVector3 &center) =0;						

	// ****************************************************************************
	//								CreateOval
	// 
	/// Creates an oval.
	///
	/// \param uAxis		X,Y or Z
	///	\param vAxis		X,Y or Z
	///	\param uSize		size along u axis
	///	\param vSize		size along v axis
	///	\param numSides		number of edges arround the oval
	///	\param center		center of the oval.
	///
	/// \return	A pointer to the created polymesh
	///
	virtual IPolymesh* MCCOMAPI  CreateOval(CoordAxes uAxis,CoordAxes vAxis,
											real uSize,real vSize, long numSides, TVector3 &center) =0;							

    // ****************************************************************************
	//								Triangulate
	// 
	/// Triangulate the selected polygons
	///
	virtual void MCCOMAPI Triangulate()=0;
    
	// ****************************************************************************
	//								Untriangulate
	// 
	///  Untriangulate the selected polygons
	///
	virtual void MCCOMAPI Untriangulate()=0;

	virtual void MCCOMAPI CreatePolymesh(IPolymesh** iPolymesh)=0;						
	virtual void MCCOMAPI SetSphereOfAttraction(SSOAData& data) =0;
	virtual void MCCOMAPI MoveSphereOfAttraction(TVector3 &center) =0;
	virtual void MCCOMAPI DoneSphereOfAttraction() =0;

	// ****************************************************************************
	//								DeleteAllPolymeshes
	// 
	/// Removes all the polymeshes from the primitive
	///
	/// \param clearShadingDomains True to remove all the shading domains
	///
	virtual void MCCOMAPI DeleteAllPolymeshes( boolean clearShadingDomains )=0;

	virtual void MCCOMAPI AddPolymesh(IPolymesh *polymesh) =0;			//	Does an AddRef
	virtual ErrorCode MCCOMAPI Extrude( EExtrudeMode mode ) =0;
	virtual ErrorCode MCCOMAPI Sweep() =0;
	virtual ErrorCode MCCOMAPI Loft()=0;
	virtual ErrorCode MCCOMAPI Organic()=0;
	virtual void MCCOMAPI CreaseEdges(boolean byAngle, real angle, boolean includeNonSelectedEdges)=0;
	virtual void MCCOMAPI SmoothEdges(boolean byAngle, real angle, boolean includeNonSelectedEdges)=0;
	
	virtual void MCCOMAPI InitMarquee() =0;
	// return true if the selection changed
	virtual boolean MCCOMAPI SetMarquee(TMCArray<RayPlane> &rayPlanes, long marqueeMode) =0;
	virtual boolean MCCOMAPI SetUVMarquee(const TBBox2D& rect, long marqueeMode) =0;
	virtual void MCCOMAPI EndMarquee() =0;
	
	virtual void MCCOMAPI ProjectToPlane(TVector3 &position,TVector3 &normal) =0;
	virtual void MCCOMAPI OffsetSelection(TVector3 &offset) =0;

	// ****************************************************************************
	//								SubdivideSelection
	// 
	/// Subdivide the current selection by first applying a triangulation,
	///	then building the midegdes vertices ( using the curvature of the surface to
	///	place them ) and finaly linking these new vertices.
	///
	virtual void MCCOMAPI SubdivideSelection() =0;
	
	// ****************************************************************************
	//								TesselateSelection
	// 
	/// Tesselates the current selection using the method passed in.
	///	NOTE: the tesselation doesn't use the curvature of the surface to build new 
	///	vertices (SubdivideSelection does).
	///
	/// \param mode	The mode of tesselation to be used.
	///
	virtual void MCCOMAPI TesselateSelection( const ETesselateMode mode ) =0;

	//
	virtual boolean MCCOMAPI CanPerform(long command) =0;

	// ****************************************************************************
	//								
	// 
	/// Returns the first vertex encountered having its flag 'special'
	///	set to true.
	///
	/// \return a pointer to the vertex
	///
	virtual I3DExVertex* MCCOMAPI SpecialVertex(  boolean displayedOne = true ) =0;

	// ****************************************************************************
	//								RemoveSpecialVertex
	// 
	/// Sets all the vertex flag 'special' to false
	///
	virtual void MCCOMAPI RemoveSpecialVertex(  boolean displayedOne = true ) =0;

	// ****************************************************************************
	//								ForAllVertices
	// 
	/// Call a callback on all vertices
	///
	virtual void MCCOMAPI ForAllVertices(IVertexCallback* callback) = 0;

	virtual boolean MCCOMAPI Weld(real tolerance, boolean alignOnly) =0;
	virtual void MCCOMAPI AddThickness(real thickness) =0;
	virtual void MCCOMAPI OffsetSurface(real distance) =0;
	//virtual void MCCOMAPI GetWorkingPolymeshes(long command,TMCPtrArray<IPolymesh> &originals,TMCPtrArray<IPolymesh> &results) =0; //	Remember to Release all object pointers placed in the lists

	// ****************************************************************************
	//								GetBestPlane
	// 
	/// Returns the plane that is closest to the current selection
	///
	/// \param ii			First vector of the plane
	/// \param jj			Second vector of the plane
	/// \param kk			Vector normal to the plane
	/// \param center		Point in the plane.
	///
	virtual boolean MCCOMAPI GetBestPlane(TVector3 &ii,TVector3 &jj,TVector3 &kk,TVector3 &center) =0;
	
	// ****************************************************************************
	//								SimpleExtrude
	// 
	/// Perform an extrusion of the current selection along their normal.
	///	Sets linkPolygons to true to keep all the adjacents polygons together.
	///
	/// \param distance		Distance of extrusion
	///	\param linkPolygons True if the polygons should be kept attached.
	///
	virtual ErrorCode MCCOMAPI SimpleExtrude(real distance, boolean linkPolygons) =0;

	// ****************************************************************************
	//								PrepareRevolution
	// 
	/// Should be called before using Revolution. Build the extra edges 
	///	usable as rotation axis and store the current selection state
	///
	/// \return	A pointer to the new polymesh countaining the new edges. It's up
	///			to the user to keep them or delete them after the rotation is done.
	///
	virtual IPolymesh* MCCOMAPI PrepareRevolution()=0;

	// ****************************************************************************
	//								Revolution
	// 
	/// Uses the selected polylines to build a new polymesh by rotating them
	///	nSteps time arround an axis defined by an edge countaining 2 non-displayed 
	///	special vertices.
	///	This method keep intact the original polylines
	///
	/// \param nSteps		Number of sections
	///	\param tolerance	Distance under which the points arround the axis are merged
	///						in 1 point on the axis
	///
	/// \return	A pointer to the newly created polymesh
	///
	virtual IPolymesh* MCCOMAPI Revolution(int32 nSteps, real32 tolerance)=0;

	virtual void MCCOMAPI DirectNormalsOutward()=0;

	virtual boolean MCCOMAPI IsNewPrimitive()=0;
	virtual void MCCOMAPI StorePMAP(const VMDataStruct& data) =0;
	virtual void MCCOMAPI GetPMAP(VMDataStruct& data) =0;

	// ****************************************************************************
	//								SetBackdropImage
	// 
	/// Set a backdrop image on a plane
	/// 
	/// \param filePath  the full path of the image file
	/// \param planeID   the id of the plane
	/// 
	virtual void MCCOMAPI SetBackdropImage(const TMCString& filePath, uint16 planeID) = 0;

	// ****************************************************************************
	//								ActivateBackdrop
	// 
	/// Enable or disable a backdrop image on a plane
	/// 
	/// \param active   true if enabling
	/// \param planeID  the id of the plane
	/// 
	virtual void MCCOMAPI ActivateBackdrop(boolean active, uint16 planeID) = 0;

	// ****************************************************************************
	//								GetBackdropImage
	// 
	/// Get the status of the backdrop image of a plane
	/// 
	/// \param filePath  return the full path of the image file
	/// \param active    return true if the backdrop is enabled
	/// \param planeID   the id of the plane
	/// 
	virtual void MCCOMAPI GetBackdropImage(TMCString& filePath, boolean& active, uint16 planeID) = 0;

	// ****************************************************************************
	//								GetWorkingBoxInfo
	// 
	/// Gets the parameters of the working box.
	/// When undefined, returns negative values.
	/// 
	virtual void MCCOMAPI GetWorkingBoxInfo(TWorkingBoxInfo& outInfo) const = 0;

	// ****************************************************************************
	//								SetWorkingBoxInfo
	// 
	/// Sets the parameters of the working box.
	/// 
	virtual void MCCOMAPI SetWorkingBoxInfo(const TWorkingBoxInfo& inInfo) = 0;

	
	virtual MCCOMErr	MCCOMAPI GetFacetMesh(uint32 lodindex, boolean faceted, EFacetMeshType meshType, FacetMesh** outMesh) = 0;
	virtual	MCCOMErr	MCCOMAPI GetFacetMesh2(uint32 lodindex, FacetMesh** outMesh, boolean renderingMesh, EFacetMeshType meshType) = 0;

	/// Get the Edges and Vertexes colors, as well as their position and index,
	/// and the BBox of the polymeshSet
	///
	virtual void		MCCOMAPI GetModelerData(TBBox3D&					bBox,
												TSegmentMesh&				segmentMesh, 
												TPointMesh&					pointMesh, 
												EFacetMeshType				meshType,
												const TModelerDataFlags&	modelerDataFlags) = 0;

	virtual void		MCCOMAPI UpdatePolygonColors( FacetMesh* facetMesh, boolean faceted, EFacetMeshType	meshType ) = 0;

	virtual boolean		MCCOMAPI HasRenderablePolygons()=0;
	virtual boolean		MCCOMAPI HasRenderableEdges()=0;
	virtual boolean		MCCOMAPI HasRenderableVertices()=0;

	virtual IPolygon*	MCCOMAPI GetPolygonFromFacetIndex(int16 lodindex,int32 index) =0;	//	Remember to Release this object
	virtual void		MCCOMAPI SetShowPolygons(boolean value) =0;
	virtual long		MCCOMAPI GetNbFacets()=0;
	virtual long		MCCOMAPI GetNbVertices()=0;
	virtual void		MCCOMAPI StartEdgeTransfer()=0;
	virtual long		MCCOMAPI EdgeTransfer(EdgeData edgeBuffer[], long bufferSize) =0;
	virtual void		MCCOMAPI ExtensionDataChanged()=0;
	virtual void		MCCOMAPI PreBoolean()=0;
	virtual IPolymesh*	MCCOMAPI CurrentScriptPolymesh()=0;		//	Remember to Release this object
	virtual void		MCCOMAPI DetachPolygons()=0;

	// ****************************************************************************
	//								ReversePolygonsNormals
	// 
	/// Flip the selected polygons and all the adjacents polygons ( to
	///	keep a smooth surface ).
	///
	virtual void		MCCOMAPI ReverseSelectionNormals()=0;

	virtual void		MCCOMAPI Decimate(real threshold, boolean decimateByValue, boolean distanceCriterion)=0;
	virtual void		MCCOMAPI Resize(TVector3& scale)=0;
	virtual void		MCCOMAPI SetSize(TVector3& scale)=0;
	virtual void		MCCOMAPI Rotate(real angle, CoordAxes axis)=0;
	virtual void		MCCOMAPI CenterAndResize(TVector3& offset, real& scaleFactor)=0;

	// ****************************************************************************
	//								SetHidden
	// 
	/// Hides or Reveals vertices.
	///	Possibility to hide the selected vertices 
	///	(selectType == eSelect), the non selected vertices (selectType == eNonSelect)
	///	or all the vertices (selectType == eAll).
	///	Possibility to reveal the hidden vertices in different state: all selected
	///	(selectType == eSelect), all non selected (selectType == eNonSlect), or untouched, as they
	///	currently are (selectType == eAll).
	///
	/// \param value		True to hide, false to reveal
	///	\param selectType	Selection option
	///
	virtual void		MCCOMAPI SetHidden(boolean value, ESelectType selectType)=0;

	virtual void		MCCOMAPI MakeVPAction(IVPAction::EVPActionKind kind, IVPAction** obj)=0;
	virtual void		MCCOMAPI SetSelection(boolean selected) =0;

	// ****************************************************************************
	//								InvertSelection
	// 
	/// 
	///	Invert the selection status of the polygons, edges and vertices ( depending )
	///	of the selectionFlags
	/// 
	///	\param selectionFlag	kOFPolygon, kOFEdge, or kOFVertex.
	///
	virtual void		MCCOMAPI InvertSelection( int32 selectionFlag ) =0;

	virtual void		MCCOMAPI SetSelectionByName(boolean selected,int32 kind, int8* name) =0;
	
	// ****************************************************************************
	//								SetSelectionByShadingDomain
	// 
	/// Select/deselect polygons based on their shading domain ID.
	///
	/// \param id		The shading domain ID
	///	\param select	True: select, false: deselect
	///
	virtual void		MCCOMAPI SetSelectionByShadingDomain( int32 id, boolean select) =0;

	virtual void		MCCOMAPI GetNamesForKind(TMCArray<TMCString255>& nameList, int32 kind) =0;
	virtual void		MCCOMAPI SetNameOnSelection(const TMCString& name, int32 kind) = 0;

	virtual SVPStatus*	MCCOMAPI GetStatus() =0;
	virtual void		MCCOMAPI Flatten() =0;
	virtual void		MCCOMAPI Deform(I3DExModifier* deformer) =0;
	virtual MCCOMErr	MCCOMAPI DoImportFriend(I3DExVertexPrimitive* element, boolean select, int32 index, I3DShInstance *instance)=0;
	virtual MCCOMErr	MCCOMAPI DoExportFriend(I3DExVertexPrimitive* element, boolean select, int32 index, const TTransform3D& transform)=0;
	virtual MCCOMErr	MCCOMAPI DoImportAlien(IMCUnknown* element, real fidelity, boolean select, int32 index)=0;
	virtual IPolymesh* 	MCCOMAPI BooleanOperation(int32 opKind, int32 iDA, int32 iDB) =0;
	virtual void		MCCOMAPI ResetPolymeshMarkers() =0;
	virtual void		MCCOMAPI Flip(TVector3& origin, TVector3& normal) =0;
	virtual void		MCCOMAPI DuplicateWithSymmetry(TVector3& origin, TVector3& normal, real tolerance) =0;
	virtual void		MCCOMAPI DuplicateSelection() =0;
//	virtual boolean		MCCOMAPI CalcSmoothingIDs() =0;
	virtual ErrorCode	MCCOMAPI FillPolygons()=0;					/// acts on selected polylines
	virtual	void		MCCOMAPI TimeHasChanged()=0;
	virtual void		MCCOMAPI Replicate(SReplicate& data)=0;
	virtual void		MCCOMAPI PosCheck()=0;
	virtual void		MCCOMAPI Adjust()=0;

	/// Returns the skinable interface (supported by the vertex primitive)
	///
	virtual I3dExSkinable* MCCOMAPI GetSkinableInterface() = 0;

	// The following 3 calls must be made on the SAME selection:

	/// Copies the skining info of the selected vertices into the given array.
	///
	virtual void		MCCOMAPI GetSelectedSkinInfo(TMCClassArray<TVertexSkinInfo>& skinInfos) = 0;

	/// Copies the skining info from the given array into the selected vertices
	///
	virtual void		MCCOMAPI SetSelectedSkinInfo(TMCClassArray<TVertexSkinInfo>& skinInfos) = 0;

	/// Swaps the skining info between the given array and the selected vertices
	///
	virtual void		MCCOMAPI SwapSkinInfos		(TMCClassArray<TVertexSkinInfo>& skinInfos) = 0;

	// ****************************************************************************
	//								SetSelectionShadingDomainID
	// 
	/// Sets the current selection shading domain ID (== UVSpaceID) to 
	///	the passed ShadingDomainID. If no shading domain exist with this ID, 
	///	nothing is done.
	///
	/// \param ShadingDomainID : the ID of the shading domain
	///
	virtual void		MCCOMAPI SetSelectionShadingDomainID( uint32 ShadingDomainID ) = 0;

	// ****************************************************************************
	//								AddShadingDomain
	// 
	/// Adds a new shading domain to the list of shading domain of the
	///	primitive.
	///
	/// \param domainName	The name of the domain to be added
	///	\param clearFirst	Sets this flag to true to remove the existing shading domain
	///						before adding the new one.
	///
	/// \return	the ID of the new shading domain ( or of the already existing domain)
	///
	virtual int32		MCCOMAPI AddShadingDomain( TMCString& domainName, boolean clearFirst ) = 0;

	// ****************************************************************************
	//								RemoveShadingDomain
	// 
	/// Removes a shading domain from the list, and change the reference
	///	to this domain in the polygon into another one.
	///
	/// \param domainID		The domain to be removed.
	///	\param replaceBy	The new ID to be set on the polygon. If -1, the first avaible ID is used.
	///
	virtual void		MCCOMAPI RemoveShadingDomain( const int32 domainID, int32 replaceBy=-1 ) = 0;
	
	// ****************************************************************************
	//								GetShadingDomainInfos
	// 
	/// Return a reference on the shading domain list of this primitive.
	///
	/// \return	the reference
	///
	virtual TMCClassArray<UVSpaceInfo>& MCCOMAPI GetShadingDomainInfos()=0;


	// ****************************************************************************
	//								GetUVSpaceInfoByID
	// 
	/// Returns the uv space info with the same id than the given one, or null if not found
	/// 
	/// \param uvSpaceID  the id of the uv space to find
	/// 
	virtual const UVSpaceInfo*	MCCOMAPI	GetUVSpaceInfoByID	(uint32 uvSpaceID) = 0;

	// ****************************************************************************
	//								CreateMorphAreaOnSelection
	// 
	/// 
	///	Create a new morph area on the current selection and set the passed name 
	///	to it. If some vertices of the selection already had a morph area, the new 
	///	one erase the old one. If in this process, an older morph area can be deprived
	///	of any vertices and become useless. In that case, they're not removed but 
	///	their indexes are return so they can be easily removed later.
	/// 
	///	\param morphAreaName:	the name of the new area.
	/// \param removedAreas:	an array of the indexes of the area that aren't used anymore by any vertex
	///							after the new one has been set.
	///
	virtual void		MCCOMAPI CreateMorphAreaOnSelection( TMCString& morphAreaName, TMCArray<int32>& removedAreas )=0;

	// ****************************************************************************
	//								SetMorphAreaOnSelection
	// 
	/// 
	///			set a currently existing area on a selection of vertices. The comments
	///			for CreateMorphAreaOnSelection are also valid here.
	/// 
	///	\param morphAreaIndex: the index of the area.
	///
	///	\param removedAreas: an array of the indexes of the area that aren't used anymore by any vertex
	///						after the new one has been set.
	///
	virtual void		MCCOMAPI SetMorphAreaOnSelection( const int32 morphAreaIndex, TMCArray<int32>& removedAreas )=0;

	// ****************************************************************************
	//								CreateMetaMorphArea
	// 
	/// 
	///	creates a new meta morph area and returns the index of the new morph area (or -1 if an error occured).
	/// 
	///	\param morphAreaName:	the name of the new area.
	///	\param subAreas:		an array of the indexes of the sub areas linked to this new
	///							meta morph area.
	///
	virtual int32		MCCOMAPI CreateMetaMorphArea( const TMCString& morphAreaName, const TMCArray<int32>& subAreas )=0;

	// ****************************************************************************
	//								GetMorphAreaCount
	// 
	/// 
	///	Returns the number of morph area in the primitive. Some of these areas
	///	can be empty ( not used by any of the vertices of the primitive )
	///
	virtual int32		MCCOMAPI GetMorphAreaCount()=0;
	
	// ****************************************************************************
	//								GetMorphAreaNoAddRef
	// 
	/// 
	///	Returns a pointer to a Morph Area.
	/// 
	///	\param areaIndex: the index of the area
	///
	virtual IMorphArea*	MCCOMAPI GetMorphAreaNoAddRef( const int32 areaIndex )=0;
	
	// ****************************************************************************
	//								CreateMorphTarget
	// 
	/// 
	///	Creates a morph target in a specific morph area and set its name. All
	///	the vertices countain in the morph area have a default deformation
	///	set to a vector 0.
	/// 
	///	\param inMorphArea		The index of the area.
	///	\param morphTargetName  The name of the new target.
	///	\param inIndex			Where the new morph should be inserted in the list (-1 => at the end)
	///
	/// \return the index of the new morph target or -1 if the operation could not be performed.
	///
	virtual int32		MCCOMAPI CreateMorphTarget( const int32 inMorphArea, TMCString& morphTargetName, const int32 inIndex= -1)=0;
	
	// ****************************************************************************
	//								RemoveMorphTarget
	// 
	/// 
	///	Remove a morph target from a morph area. 
	///	<P><B>WARNING:</B> since we work with index ( and not with ID ), removing a 
	///	target from the array will shift all the indexes of the following targets.</P>
	/// 
	///	\param inMorphArea: the index of the area
	///	\param targetIndex: the index
	///
	/// \return True if the operation could be performed
	///
	virtual boolean		MCCOMAPI RemoveMorphTarget( const int32 inMorphArea, const int32 targetIndex )=0;
	
	// ****************************************************************************
	//								SetSelectionByMorphArea
	// 
	/// 
	///	Select or deselect all the vertices in an area
	/// 
	///	\param morphAreaIndex			the index of the area
	///	\param select					true to select, false to deselect
	///	\param addToCurrentSelection	set to true to keep the current selection unmodified
	///									(unless it's part of the morph area)
	///
	virtual void		MCCOMAPI SetSelectionByMorphArea( const int32 morphAreaIndex, const boolean select, const boolean addToCurrentSelection )=0;
	
	// ****************************************************************************
	//								RemoveMorphAreas
	// 
	/// 
	///	Remove a list of areas.
	///	<P><B>WARNING:</B> since we work with index ( and not with ID ), removing areas 
	///	from the array will shift all the indexes of the following areas</P>
	/// 
	///	\param removedAreaIndexes: the array of the area indexes to be removed
	///
	virtual void		MCCOMAPI RemoveMorphAreas( TMCArray<int32>& removedAreaIndexes )=0;
	
	///Gets the current morph mode
	virtual EMorphMode	MCCOMAPI GetMorphMode() const = 0;

	///Sets the current morph mode
	virtual void		MCCOMAPI SetMorphMode(EMorphMode inMorphMode) = 0;

	///Gets the list of morphs being edited (returns null when not in edit mode)
	virtual const TMorphIDList*	MCCOMAPI GetEditedMorphs() const = 0;

	///Sets the list of morphs being edited
	virtual void		MCCOMAPI SetEditedMorphs(const TMorphIDList& inEditedMorphs) = 0;

	// ****************************************************************************
	//								AddOffsetFromTarget
	// 
	/// Add the offsets of a specific target to another one. This can 
	///	be used to merge targets, or to copy the content of a target into
	///	another one.
	///
	/// \param inMorphArea		The id of the morph area concerned
	///	\param fromTarget		The target source
	///	\param toTarget			The destination target
	///	\param coeff			Multiply all the offset of the target source before copiing them into 
	///							the destination.
	///
	virtual void		MCCOMAPI AddOffsetFromTarget( const int32 inMorphArea, const int32 fromTarget, const int32 toTarget, const real32 coeff=1.0 )=0;

	// ****************************************************************************
	//								ImportMorphTarget
	// 
	/// Import a morph target form antoher vertex object.
	///
	/// \param inSource			The morph target datas.
	/// \param morphIDList		Contains the id of the morph area and the id of the morph target
	//
	/// \return True if the operation could be performed
	///
	virtual boolean		MCCOMAPI ImportMorphTarget( I3DExVertexPrimitive* inSource, const TMorphIDList* morphIDList )=0;

	// ****************************************************************************
	//								ExportMorphTarget
	// 
	/// Export a morph target to antoher vertex object.
	///
	/// \param outObject		The object.
	/// \param inMorphArea		The id of the morph area
	///	\param inTarget			The id of the morph target
	//
	/// \return True if the operation could be performed
	///
	virtual boolean		MCCOMAPI ExportMorphTarget( I3DExVertexPrimitive* outObject, const TMorphIDList* morphIDList)=0;
	
	// ****************************************************************************
	//								InvalidateMorphing
	// 
	/// 
	///	Invalidate the morph data
	///
	/// \param areaIndex:	Set to kAllMorphArea to invalidate all the areas,
	///						otherwise set to the area to be invalidate
	///
	virtual void		MCCOMAPI InvalidateMorphing( const int32 areaIndex )=0;


	// ****************************************************************************
	//								GetMorphTargetUndoInfo
	// 
	/// 
	///	Returns the current state of the morph target to use to undo an operation
	/// performed on that morph target
	///
	/// \param undoInfo		The info info that is returned.
	/// \param inMorphArea	The index of the morph area on which the operation is performed
	/// \param inTarget		The index of the morph target in the morph area
	///
	virtual void		MCCOMAPI GetMorphTargetUndoInfo(IMorphTargetUndoInfo** undoInfo,const int32 inMorphArea,const int32 inTargets)=0;

	// ****************************************************************************
	//								UndoMorphTargetChange
	// 
	/// 
	///	Undoes a change a morph target
	///
	/// \param undoInfo		The info info that is returned.
	///
	virtual void		MCCOMAPI UndoMorphTargetChange(IMorphTargetUndoInfo* iUndoInfo) = 0;

	// ****************************************************************************
	//								SetWorkingBoxPlane
	// 
	/// Give the active working box plane to the primitive. Some tool 
	///	need it ( extrusion )
	///
	/// \param WBPlane	The working box plane
	///
	virtual void		MCCOMAPI SetWorkingBoxPlane( IWorkingBoxPlane* WBPlane )=0;

	// ****************************************************************************
	//								SetSkinningAlgorithmComponent
	// 
	/// Sets the skinning algorithm to use on the vertex primitive
	///
	/// \param algorithm	The algorithm to use.
	///
	virtual void		MCCOMAPI SetSkinningAlgorithmComponent(IShComponent* algorithm) = 0;

	// ****************************************************************************
	//								GetSkinningAlgorithm
	// 
	/// Gets the skinning algorithm used on the vertex primitive.
	///
	virtual I3DExSkinningAlgorithm*		MCCOMAPI GetSkinningAlgorithm() = 0;

	// ****************************************************************************
	//								GetGlobalDeformerDefaultStrength
	// 
	/// Gets the default strength of an attached global deformer. This strength
	/// can be overriden on a morph area.
	///
	virtual real32		MCCOMAPI GetGlobalDeformerDefaultStrength(int32 deformerIndex) = 0;

	// ****************************************************************************
	//								SetGlobalDeformerDefaultStrength
	// 
	/// Sets the default strength of an attached global deformer.
	///
	virtual void		MCCOMAPI SetGlobalDeformerDefaultStrength(int32 deformerIndex, real32 strength) = 0;


	// ****************************************************************************
	//								GetMorphTargetStorageType
	// 
	/// Returns how the morph targets are currently stored in the primitive (Compact or modeling)
	/// The morph targets are in compact mode when the object is not being edited in the modeler.
	///
	virtual EMorphTargetStorageType MCCOMAPI GetMorphTargetStorageType() =0;

	// ****************************************************************************
	//								SetIsFigurePrimitive
	// 
	/// Sets whether a vertex primitive is actually a figure.
	///
	virtual void MCCOMAPI SetIsFigurePrimitive(boolean isFigurePrimitive)=0;

	// ****************************************************************************
	//								GetIsFigurePrimitive
	// 
	/// Returns true if a vertex primitive is actually a figure.
	///
	virtual boolean	MCCOMAPI GetIsFigurePrimitive() const =0;

	// ****************************************************************************
	//								RayHit
	// 
	/// Returns the intersection of a ray with the geometry in the modeler. The normal
	/// returned is the normal the last time than StoreNormalsRayHit() was called. If it was not
	/// called then it is the current normal to the mesh.
	///
	/// Note that the normal is always smoothed.
	///
	/// \Return True if there is an intersection, false otherwise.
	///
	/// \param origin			origin of the ray
	/// \param direction		direction of the ray
	/// \param position			origin of the ray
	/// \param normal			smoothed normal at the hit point
	/// \param polymeshIndex	index of the polymesh that is hit if any
	///
	virtual boolean MCCOMAPI RayHit(const TVector3& origin,const TVector3& direction,
									TVector3& position,TVector3& normal,int32& polymeshIndex)=0;

	// ****************************************************************************
	//								SymmetrizeSelection
	// 
	/// Symmetrize the selection on polymeshes that have the symmetrical modeleing
	/// enabled.
	///
	virtual void		MCCOMAPI SymmetrizeSelection() = 0;

	// ****************************************************************************
	//								ShouldApplySkinning
	// 
	/// Return Vertex Primitive Skin Info
	/// 
	/// \param recomputeSkinning   is set to true if the Skinning need recomputing
	///
	virtual TVertexPrimSkinInfo* MCCOMAPI ShouldApplySkinning(boolean& recomputeSkinning) = 0;

	// ****************************************************************************
	//								CheckWrapConflict
	// 
	/// Return true if PolymeshSet WrapAround have a conflict
	/// 
	virtual boolean MCCOMAPI CheckWrapConflict() = 0;
	
	// ****************************************************************************
	//								SkipWrapAlert
	// 
	/// Set polymeshset skip flag for WrapAround conflict alert to true
	/// 
	virtual void MCCOMAPI SkipWrapAlert() = 0;

	// ****************************************************************************
	//								SetUpdateFacetMeshColor
	// 
	/// Set polymeshset flag to enable or disable FacetMeshColor update
	/// 
	virtual void MCCOMAPI SetUpdateFacetMeshColor(boolean enable) = 0;

	// ****************************************************************************
	//								SetShowUVUnfoldInfoDifferentColor
	// 
	/// Set polymeshset flag to enable or disable seam and pinning points dissplay in a different color
	/// 
	virtual void MCCOMAPI SetShowUVUnfoldInfoDifferentColor(boolean enable) = 0;
    
	virtual  real32 MCCOMAPI GetScalingFactor() const = 0;

	// ****************************************************************************
	//								IsHydrated
	// 
	/// Returns true of the vertex primitive is hydrated.
	/// 
	virtual boolean		MCCOMAPI IsHydrated() const = 0;

	/// Invalidates the mesh (eg when the weights have changed
	virtual void		MCCOMAPI SetSkinningValid	(boolean valid) = 0;

	// ****************************************************************************
	//								UnfoldUV
	// 
	/// Returns a mesh matching the geometry of the input mesh, with UV calculated
    /// according to seams and pinning points.
	///
    /// \param meshToUnfold The mesh that should be unfold. This mesh must be part
    ///    Vertex primitive. If the result of the function is not NULL, the input
    ///    mesh is no longer valid.
    /// \param projectionAxis The projection axis (0 - X, 1 - Y, 2 - Z)
    /// \param uvPinningAxis  The UV axis used for pinning (0 - U, 1 - V)
	///
	/// \Return If succesfull, the mesh with unfolded UV, otherwise NULL;
	///
    virtual IPolymesh* MCCOMAPI  UnfoldUV(IPolymesh* meshToUnfold,
                                          int32 projectionAxis,
                                          int32 uvPinningAxis) = 0;
    
    virtual ILevelOfDetailsManager* MCCOMAPI GetLODManager() const = 0;
};

/// \}


//	Object flags
const uint32 kOFNothing			=		0;
const uint32 kOFVertex			=		0x0001;
const uint32 kOFEdge			=		0x0002;
const uint32 kOFPolygon			=		0x0004;
const uint32 kOFDrawingPlane	=		0x0008;
const uint32 kOFBBox			=		0x0010;
const uint32 kOFEverything		=		kOFVertex|kOFEdge|kOFPolygon;
const uint32 kOFUseShieldPolygon=		0x0020;



struct SVPStatus : public TMCObject
{
	int32						fNumTotalPolymeshes;
	int32						fNumSelectedPolymeshes;
	int32						fNumPartiallySelectedPolymeshes;
	TMCCountedPtr<IPolymesh>	fFirstSelectedPolymesh;
	TMCCountedPtr<IPolymesh>	fSecondSelectedPolymesh;
	TMCCountedPtr<IPolymesh>	fFirstPolymeshWithSelection;
	TMCCountedPtr<IPolymesh>	fSecondPolymeshWithSelection;

	int32						fNumTotalPolygons;
	int32						fNumSelectedPolygons;
	TMCCountedPtr<IPolygon>		fFirstSelectedPolygon;
	TMCCountedPtr<IPolygon>		fSecondSelectedPolygon;

	int32						fNumTotalEdges;
	int32						fNumSelectedEdges;
	TMCCountedPtr<IEdge>		fFirstSelectedEdge;
	TMCCountedPtr<IEdge>		fSecondSelectedEdge;

	int32						fNumTotalVertices;
	int32						fNumSelectedVertices;
	TMCCountedPtr<I3DExVertex>		fFirstSelectedVertex;
	TMCCountedPtr<I3DExVertex>		fSecondSelectedVertex;

	boolean						fSomethingSelected;
	boolean						fSomethingDeselected;
	boolean						fCanReveal;
	boolean						fCanHide;
	boolean						fCanWeld;
	boolean						fCanFlatten;
	boolean						fCanFill;
	boolean						fCanEmpty;
	boolean						fCanAdjust;
	boolean						fCanOrganic;
	boolean						fCanBooleanSubtract;
	boolean						fCanUnlink;
	int32						fShadingDomain; // -1 if the selection has several shading domain
	int32						fMorphAreaCount;
};


struct SReplicate : public TMCObject
{
	enum EReplicateKind
	{
		kRepLinear,
		kRepGrid,
		kRepCircle
	} fMode;

	TVector3	fUOffset;
	TVector3	fVOffset;
	int32		fNumU;
	int32		fNumV;
	real		fArcAngle;
	real		fRadius;
	int32		fAxis;
	boolean		fRotateCopies;
};


struct TWorkingBoxInfo
{
	real32 fGridSize;
	real32 fGridSpacing;
	int32  fLineSpacing;

	TWorkingBoxInfo()
	{
		fGridSize	= -1.0f;
		fGridSpacing= -1.0f;
		fLineSpacing= -1;
	}
};


const int32 kUnionOperation			= 0;
const int32 kIntersectionOperation	= 1;
const int32 kSubtractionOperation	= 2;

const int32 kUnionOperation2		= 3;
const int32 kIntersectionOperation2	= 4;
const int32 kSubtractionOperation2	= 5;

//	Codes for menu commands
const long kExtrudeCommand			= 0;
const int32 kSweepCommand			= 1;
const int32 kLoftCommand			= 2;
const int32 kLatheCommand			= 3;
const int32 kEmptyPolygonCommand	= 5;
const int32 kFillPolygonCommand		= 6;
const int32 kAddThicknessCommand	= 7;
const int32 kOffsetSurfaceCommand	= 8;
const int32 kGenericCommand			= 9;
const int32 kSimpleExtrudeCommand	= 10;
const int32 kMenuLatheCommand		= 11;
const int32 kOrganicCommand			= 12;
const int32 kNumCommands			= 13;


//	select by name kinds
const int32 kSelectPolymeshByName	= 'PlmN';
const int32 kSelectVertexByName		= 'VtxN';
const int32 kSelectPolygonByName	= 'PlgN';
const int32 kSelectEdgeByName		= 'EdgN';

//	Marquee selection modes
const int32 kMarqueeSelect			= 0;
const int32 kMarqueeSwap			= 1;
const int32 kMarqueeDeselect		= 2;


#endif
