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

		I3DExFigurePrimitive.h
		Copyright: (c) 2005 Eovia Corp. All rights reserved.

		Author:	Jeremy
		Date:	3/7/2005

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

#ifndef __I3DExFigurePrimitive__
#define __I3DExFigurePrimitive__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "MCCompObj.h"
#include "InterfaceIDs.h"
#include "MCString.h"
#include "MCCountedPtrArray.h"
#include "MCArray.h"
#include "MCPoint.h"

struct IPolymesh;
struct IPolygon;
struct TOriginalMeshData;
struct I3DExVertex;
struct I3dExSkinable;
struct I3DExVertexPrimitive;

template <class T> class TMCCountedPtrArray;
template <class T> class TMCClassArray;

//****** Globally Unique Ids *************************************************
MCDEFINE_GUID_H(IID_I3DExFigurePrimitive);
MCDEFINE_GUID_H(IID_I3DExFigureActor);
MCDEFINE_GUID_H(IID_I3DExFigureActor0);



struct TActorInfo
{
	TMCDynamicString	fName;
	TMCDynamicString	fInternalName;
	boolean				fEnabled;

	int32				fParentIndex;

	boolean				fUseAlternateGeom;
	int32				fPolymeshIndex;
	int32				fAlternatePolymeshIndex;

	int32				fMorphAreaIndex;
	int32				fMetaMorphAreaIndex;
};

struct TSubdivisionData
{
	inline TSubdivisionData() : fType(0),fModelingLevel(0),fRenderingLevel(0),fSubdivisionUVMode(true) {}

	IDType		fType;
	int32		fModelingLevel;
	int32		fRenderingLevel;
	boolean		fSubdivisionUVMode;
};


//****************************************************************************
//  I3DExFigurePrimitive
//
//    Interface of the figure primitive
//
//****************************************************************************

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

struct I3DExFigureActor : public IMCUnknown
{
	// ****************************************************************************
	//								IsVisible
	//
	/// Returns the visibility of the actor.
	// 
	virtual boolean				MCCOMAPI IsVisible() = 0;

	// ****************************************************************************
	//								SetVisible
	//
	/// \param visible			Visibility of the actor.
	// 
	virtual void				MCCOMAPI SetVisible(boolean visible) = 0;

	// ****************************************************************************
	//								GetGeometryCount
	//
	/// Gets the number of geometries for this actor.
	//
	virtual int32				MCCOMAPI GetGeometryCount() = 0;

	// ****************************************************************************
	//								GetCurrentGeometry
	//
	/// Returns the current geometry index of the actor.
	//
	virtual int32				MCCOMAPI GetCurrentGeometry() = 0;

	// ****************************************************************************
	//								SetCurrentGeometry
	//
	/// Changes the current geometry of the actor.
	//
	virtual void				MCCOMAPI SetCurrentGeometry(int32 index) = 0;

	// ****************************************************************************
	//								GetGeometryName
	//
	/// Returns the name of one of the actor geometries.
	//
	virtual const TMCString&	MCCOMAPI GetGeometryName(int32 index) = 0;

	// ****************************************************************************
	//								AddGeometry
	//
	/// Adds a geometry to the actor. The polymesh should not be a polymesh of this
	/// vertex primitive.
	/// \param name			Name of the geometry.
	/// \param polymesh		Polymesh.
	//
	virtual void				MCCOMAPI AddGeometry(const TMCString& name, IPolymesh* polymesh) = 0;

	// ****************************************************************************
	//								GetGeometryVertices
	//
	/// Returns informations about one of the geometry.
	//
	virtual void				MCCOMAPI GetGeometryVertices(int32 geometryIndex, IPolymesh** polymesh, int32& outPolymeshIndex, TMCCountedPtrArray<I3DExVertex>& vertices) = 0;
	
	// ****************************************************************************
	//								WeldTo
	//
	/// Weld this actor to another one. Don't forget to call I3DExFigurePrimitive::PostActorWelding
	/// after welding all the actors together.
	//
	virtual void				MCCOMAPI WeldTo(I3DExFigureActor* actor) = 0;

	// ****************************************************************************
	//								CreateMorphArea
	//
	/// Returns the morph area for the actor. If it already exists, the morph area
	/// index is returned.
	//
	virtual int32				MCCOMAPI CreateMorphArea() = 0;

	/// Returns the morph area for the actor (does not create it).
	virtual int32				MCCOMAPI GetMorphAreaIndex	() const = 0;

	///Returns the index of the actor
	virtual int32				MCCOMAPI GetActorIndex		() const = 0;

	// ****************************************************************************
	//								Initialize
	//
	/// \param name				Actor's name.
	/// \param internalName		Actor's internal name.
	//
	virtual void				MCCOMAPI Initialize(const TMCString& name, const TMCString& internalName) = 0;

	// Those function should not be used
	virtual void				MCCOMAPI Convert_AddGeometry(const TMCString& name, int32 polymeshIndex) = 0;
	virtual void				MCCOMAPI Convert_Initialize(int32 morphAreaIndex, int32 currentGeometry) = 0;

	virtual const TMCString&	MCCOMAPI GetName			() const = 0;

	virtual void				MCCOMAPI SetJointIndex		(int32 jointIndex) = 0;

	virtual int32				MCCOMAPI GetJointIndex		() const = 0;

	// ****************************************************************************
	//								GetWeldedActors
	//
	/// Gets the actors welded on to the current actor
	/// \param actors			Returned list of actors.
	//
	virtual void				MCCOMAPI GetWeldedActors(TMCCountedPtrArray<I3DExFigureActor>& actors) = 0;

	virtual const TMCString&	MCCOMAPI GetInternalName	() const = 0;
};

    

/// <P>I3DExFigurePrimitive is the interface to functions specific to figure primitives.
/// Figure primitives are a subclass of vertex primitives, and as such always implement
/// the I3DExVertexPrimitive interface as well.</P>
///
struct I3DExFigurePrimitive: public IMCUnknown 
{
	enum EMeshType
	{
		kMultiplePolymeshes,
		kUniquePolymesh,
	};

	// ****************************************************************************
	//								WeldPolymesh (Old function, deprecated)
	//
	/// \param inPolymesh1        First group
	/// \param inPolymesh2        Second group
	//
	/// \return False if the two polymeshes seem to be oriented differently, True otherwise.
	// 
	virtual boolean	 MCCOMAPI	WeldPolymeshs(IPolymesh* inFirstPolymesh, IPolymesh* inSecondPolymesh) =0;

	// ****************************************************************************
	//								SetActorInfos (Old function, deprecated)
	//
	/// \param inActorInfos       Actor infos
	// 
	virtual void	 MCCOMAPI	SetActorInfos(const TMCClassArray<TActorInfo>& inActorInfos) =0;

	// ****************************************************************************
	//								GetActorInfos (Old function, deprecated)
	//
	/// \param inActorInfos       Actor infos
	// 
	virtual const TMCClassArray<TActorInfo>&	 MCCOMAPI	GetActorInfos() const =0;

	// ****************************************************************************
	//								SetMeshMode
	//
	/// \param mode			Mesh mode
	//
	virtual void				MCCOMAPI SetMeshMode(EMeshType mode) = 0;

	// ****************************************************************************
	//								SetMeshMode
	//
	virtual EMeshType			MCCOMAPI GetMeshMode() = 0;

	// ****************************************************************************
	//								GetActorCount
	//
	virtual int32				MCCOMAPI GetActorCount() = 0;

	// ****************************************************************************
	//								AddActor
	//
	/// Add an actor and returns its index in the figure primitive.
	//
	virtual int32				MCCOMAPI AddActor() = 0;

	// ****************************************************************************
	//								GetActor
	//
	/// Gets an actor.
	//
	virtual I3DExFigureActor*	MCCOMAPI GetActor(int32 index) = 0;

	// ****************************************************************************
	//								PostActorWelding
	//
	/// Must be called after welding the actor (\see I3DExFigureActor::WeldTo)
	//
	virtual void				MCCOMAPI PostActorWelding() = 0;

	// ****************************************************************************
	//								BeginActorSetCurrentGeometry
	//
	/// Can be called before calling multiple SetCurrentGeometry() the actors (\see I3DExFigureActor::SetCurrentGeometry())
	//
	virtual void				MCCOMAPI BeginActorSetCurrentGeometry() = 0;

	// ****************************************************************************
	//								EndActorSetCurrentGeometry
	//
	/// Can be called after calling multiple SetCurrentGeometry() the actors (\see I3DExFigureActor::SetCurrentGeometry())
	//
	virtual void				MCCOMAPI EndActorSetCurrentGeometry() = 0;

	// ****************************************************************************
	//								ValidateGeometriesCaches
	//
	/// Validates the geometry caches on all actors. It will speed up the calls to
	/// I3DExFigureActor::GetGeometryVertices().
	//
	virtual void				MCCOMAPI ValidateGeometriesCaches() = 0;

	// ****************************************************************************
	//								FreeGeometriesCaches
	//
	/// Free the caches.
	//
	virtual void				MCCOMAPI FreeGeometriesCaches() = 0;

	// ****************************************************************************
	//								IsConforming (Old function, deprecated)
	//
	virtual boolean	 MCCOMAPI	IsConforming() =0;

	// ****************************************************************************
	//								SetConforming (Old function, deprecated)
	//
	virtual void	 MCCOMAPI	SetConforming(boolean enable) =0;

	// ****************************************************************************
	//								GetSubdivisionData
	//
	// Returns the parameters of the subdivision surfaces
	//
	virtual const TSubdivisionData&	 MCCOMAPI	GetSubdivisionData() = 0;

	// ****************************************************************************
	//								SetSubdivisionData
	//
	// Sets the parameters of the subdivision surfaces
	//
	virtual void	 MCCOMAPI	SetSubdivisionData(const TSubdivisionData& subdivisionData) = 0;

	//returns the I3dExSkinable interface of the figure primitive
	virtual I3dExSkinable*			MCCOMAPI GetThisSkinable		() = 0;

	//returns the I3DExVertexPrimitive of the figure primitive
	virtual I3DExVertexPrimitive*	MCCOMAPI GetThisVertexPrimitive	() = 0;

	///Returns data to rebuild the original geometry/topology of the actors
	virtual void	MCCOMAPI GetActorsOriginalMeshData (TMCClassArray<TOriginalMeshData>& outData) = 0;
};


struct TOriginalMeshData : public TMCObject
{
	TMCDynamicString				fActorName;
	int32							fMorphAreaIndex;
	TMCCountedPtrArray<I3DExVertex>	fOriginalVertices;  //some vertices can be null
	TMCArray<TMCPoint>				fMergedVertices;	//the actor index and original vertex index to which it was merged
	TMCCountedPtrArray<IPolygon>	fPolygons;
};

/// \}



#endif
