/*
------------------------------------------------------------------------------------------
HEADER FILE FOR WP:
WayPoint.h

Creation Date : January,1997
Author : Jacques (Annecy)
------------------------------------------------------------------------------------------
Modifications : 
January 16,1997    Alb     Many modification in all file to conform it with  3DOS

------------------------------------------------------------------------------------------
This file defines structures and functions used to manage waypoint and way
in the engine
------------------------------------------------------------------------------------------
Remark :
if _WAY_FirstLinkIsFirstWaypoint_ is defined, it is assumed that there is as much links as 
waypoints, first link describing how to go to the first waypoint, and so on
if it is not defined, it is assumed that there is one more waypoint than links. First link
describing how to go from the first WP to the second, and so on.
------------------------------------------------------------------------------------------
*/
/*
Invalidate one of the two following lines :
*/
//#define _WAY_FirstLinkIsFirstWaypoint_
 #undef _WAY_FirstLinkIsFirstWaypoint_ 

#if !defined(__WAYPOINT_TYPES__)
#define __WAYPOINT_TYPES__

#if !defined(ONLY_TYPES)
#define WAYPOINT_UNDEF
#define ONLY_TYPES
#endif /* !ONLY_TYPES */

/*
------------------------------------------------------------------------------------------
INCLUDE FILES :
------------------------------------------------------------------------------------------
*/
/*
Avoiding : 
error C2501: 'Do_not_use_extern_in_c_files' : missing decl-specifiers
*/
#ifdef extern
#undef extern
#endif 
#include "ACP_Base.h"
#include "Hie.h"
#include "mth.h"
#include "Macros.h"
#include "dynamic.h"
#include "Bezier.h"
#include "Circlway.h"

#if defined(WAYPOINT_UNDEF)
#undef ONLY_TYPES
#undef WAYPOINT_UNDEF
#endif /* !WAYPOINT_UNDEF */

/*
------------------------------------------------------------------------------------------
TYPE DEFINITION :
If enumerate :
 M_BeginDeclareEnumerate(<type>)
 M_EndDeclareEnumerate(<type>, <basic type>)
------------------------------------------------------------------------------------------
*/
/*
Structure defining WayPoint in the Game Engine :
*/
typedef struct tdst_WayPoint_
{
 /* vertex defining the position of the waypoint */
 MTH3D_tdstVector			m_stVertex;
 /* radius of the WP :*/
	MTH_tdxReal			m_xRadius;
 /* Handle on the superobject owner of the WP (if NULL, WP = static) */
 HIE_tdxHandleToSuperObject m_hSuperObject;
 /* following field is used to determine when the object should be free */
 unsigned char m_ucUsedCount;
} tdst_WayPoint;
/* defining the handle type :*/
typedef tdst_WayPoint*		ACP_tdxHandleOfWaypoint;

/* following type defines the type of the connection */
M_BeginDeclareEnumerate(ACP_tde_ucConnectionType_)
ACP_ConnType_ucStaticLine,
ACP_ConnType_ucDynamicLine,
ACP_ConnType_ucBezier,
ACP_ConnType_ucCircle,
ACP_ConnType_ucInvalid,
ACP_ConnType_ucNbrOfElement = ACP_ConnType_ucInvalid,
M_EndDeclareEnumerate(ACP_tde_ucConnectionType,unsigned char)

/* The following enum describes the dynamic type of a connection :*/
M_BeginDeclareEnumerate(ACP_tde_ucConnectionDynamicType_)
ACP_ConDynType_ucNone,
ACP_ConDynType_ucConstant,
ACP_ConDynType_ucLinear,
ACP_ConDynType_ucSinus,
ACP_ConDynType_ucInvalid,
ACP_ConDynType_ucNbrOfElement = ACP_ConDynType_ucInvalid
M_EndDeclareEnumerate(ACP_tde_ucConnectionDynamicType,unsigned char)

/* defining a sampling rate type :*/
typedef unsigned char tduc_SamplingRate;
/*
Structure defining a Link in the Game Engine :
*/
typedef struct tdst_Link_
{ 
 /* Information depending on the type of the link :*/
	union
 {
  void *m_pvBuffer;/* to access the buffer without caring about the type */
  MTH3D_tdstVector *m_pstStaticVector;/* to access to the buffer for StaticLine type */
  tdstBezierObject *m_pstBezierObject;/* to access to the buffer for BezierObect type */
  //JT modify
  tdstCircleArcObject *m_pstCircleArcObject;/* to access to the buffer for ArcObject type */
 }; 

 /* Information depending on the dynamic type of the link :*/
 ACP_tdstDynaParam m_stConnDynTypeInfo;
 
 /* Defines the type of the link(linear,sinesuoidale,spline...) :*/
	ACP_tde_ucConnectionType m_eucConnectionType;
 /* defines the dynamic type (none, linear,sinus...)*/
 ACP_tde_ucConnectionDynamicType m_eucConnectionDynamicType;
 
 /* Current sample index :*/
 unsigned char m_ucCurrentSample;

 /* following member is used to determine when to erase the link :*/
 unsigned char m_ucUsedCount;
} tdst_Link;
/* defining the handle type :*/
typedef tdst_Link*			ACP_tdxHandleOfLink;

/*
typedef for the index :
*/
typedef unsigned char tducWPIndex;
/*
This structure defines the type of the waypoint :
*/
typedef struct tdst_Way_
{
 /* this field contains the speed the way is traveled through */
	/* MTH_tdxReal	m_tdxSpeed;  No more used since it is in the link, no?*/
 /* a dynamic array on handles on wp :*/
	ACP_tdxHandleOfWaypoint *m_d_hWayPoint;
 /* a dynamic array on handles on link :*/
	ACP_tdxHandleOfLink *m_d_hLink;
 /* The following member contains the size of the arrays */
	tducWPIndex m_ucSizeWay;
 /* contains an index on the array for the current wp :*/
	tducWPIndex m_ucCurrentWPIndex;
 /* following member is used to determine when to erase the way :*/
 unsigned char m_ucUsedCount;
} tdst_Way;
/* defining the handle type :*/
typedef tdst_Way*			ACP_tdxHandleOfWay;

// index : used in AI for Way in model
typedef unsigned char tduc_WayIndex;

#endif /* !__WAYPOINT_TYPES__ */

#if !defined(ONLY_TYPES)

#if !defined(__WAYPOINT_VARS__)
#define __WAYPOINT_VARS__

#undef EXTERN
#undef extern
#if !defined(WP_GLOBALS)
#define EXTERN extern
#else /* !GLOBALS */
#define EXTERN
#endif /* !GLOBALS */

/*
------------------------------------------------------------------------------------------
VARIABLE DECLARATION :

 <type> <variable name>
 #if defined(GLOBALS)
 = <initial values>
 #endif
 ;
------------------------------------------------------------------------------------------
*/


/*
------------------------------------------------------------------------------------------
MACROS-CONSTANT DECLARATION:
------------------------------------------------------------------------------------------
*/
/* define script section name :*/
#define C_SectionWayPointDescription "WayPoint"
#define C_SectionWayDescription "Way"

/* invalid handles :*/
#define ACP_C_InvalidWayPointHandle       ((ACP_tdxHandleOfWaypoint)NULL)
#define ACP_C_InvalidWayHandle            ((ACP_tdxHandleOfWay)NULL)
#define ACP_C_InvalidLinkHandle           ((ACP_tdxHandleOfLink)NULL)


#undef extern
#endif /* !__WAYPOINT_VARS__ */

#if !defined (__WAYPOINT_PROTOS__)
#define __WAYPOINT_PROTOS__

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/*
------------------------------------------------------------------------------------------
MACROS-FUNCTIONS DECLARATION:
------------------------------------------------------------------------------------------
*/
/* accessing to members of the structures :*/
#define M_xGetWPRadius(_hWP)\
 (((ACP_tdxHandleOfWaypoint)(_hWP))->m_xRadius)
#define M_hGetSuperObject(hWP)\
 (((ACP_tdxHandleOfWaypoint)(hWP))->m_hSuperObject)
#define M_stGetVertex(hWP)\
 (((ACP_tdxHandleOfWaypoint)(hWP))->m_stVertex)
// ANNECY AV {
//#define M_ucGetWPUsedCount(hWP)\
 (((ACP_tdxHandleOfWaypoint)(hWP))->m_ucUsedCount)
// END ANNECY AV }

#define M_eucGetLinkConnectionType(_hLink)\
 (((ACP_tdxHandleOfLink)(_hLink))->m_eucConnectionType)
#define M_pvGetLinkConnTypeInfo(_hLink)\
 (((ACP_tdxHandleOfLink)(_hLink))->m_pvBuffer)
#define M_stGetLinkConnTypeStaticVector(_hLink)\
  (((ACP_tdxHandleOfLink)(_hLink))->m_pstStaticVector)
#define M_stGetLinkConnTypeBezierObject(_hLink)\
  (((ACP_tdxHandleOfLink)(_hLink))->m_pstBezierObject)

#define M_eucGetLinkConnectionDynType(_hLink)\
 (((ACP_tdxHandleOfLink)(_hLink))->m_eucConnectionDynamicType)
#define M_stGetLinkConnDynTypeInfo(_hLink)\
	(((ACP_tdxHandleOfLink)(_hLink))->m_stConnDynTypeInfo)

#define M_ucGetLinkCurrentSample(_hLink)\
 (((ACP_tdxHandleOfLink)(_hLink))->m_ucCurrentSample)
// ANNECY AV {
//#define M_ucGetLinkUsedCount(_hLink)\
 (((ACP_tdxHandleOfLink)(_hLink))->m_ucUsedCount)
// END ANNECY AV }

#define M_dhGetWayWPHandleArray(_hWay)\
	(((ACP_tdxHandleOfWay)(_hWay))->m_d_hWayPoint)
#define M_dhGetWayLinkHandleArray(_hWay)\
	(((ACP_tdxHandleOfWay)(_hWay))->m_d_hLink)
#define M_ucGetWaySizeWay(_hWay)\
	(((ACP_tdxHandleOfWay)(_hWay))->m_ucSizeWay)
#define M_ucGetWayCurrentWPIndex(_hWay)\
	(((ACP_tdxHandleOfWay)(_hWay))->m_ucCurrentWPIndex)
// ANNECY AV {
//#define M_ucGetWayCurrentUsedCount(_hWay)\
 (((ACP_tdxHandleOfWay)(_hWay))->m_ucUsedCount)
// END ANNECY AV }

#define M_hGetWPAtPositionWay(_hWay,_ucIndex)\
 (M_dhGetWayWPHandleArray(_hWay)[(_ucIndex)])
#define M_hGetLinkAtPositionWay(_hWay,_ucIndex)\
 (M_dhGetWayLinkHandleArray(_hWay)[(_ucIndex)])

#define M_hGetWayCurrentWP(_hWay)\
 M_hGetWPAtPositionWay((_hWay),M_ucGetWayCurrentWPIndex(_hWay))
#define M_ucWayNbrOfWP(_hWay)\
 M_ucGetWaySizeWay(_hWay)

#ifdef _WAY_FirstLinkIsFirstWaypoint_
 #define M_hGetWayCurrentLink(_hWay)\
  M_hGetLinkAtPositionWay((_hWay),M_ucGetWayCurrentWPIndex(_hWay))
 #define M_ucWayNbrOfLink(_hWay)\
  M_ucGetWaySizeWay(_hWay)
#else /*_WAY_FirstLinkIsFirstWaypoint_*/
 #define M_hGetWayCurrentLink(_hWay)\
  M_hGetLinkAtPositionWay((_hWay),(unsigned char)(M_ucGetWayCurrentWPIndex(_hWay)-1))
 #define M_ucWayNbrOfLink(_hWay)\
  ((unsigned char)(M_ucGetWaySizeWay(_hWay)-1))
#endif /*_WAY_FirstLinkIsFirstWaypoint_*/

#define M_bWayIsLastWayPoint(_hWay,_ucPos)\
 (M_ucGetWaySizeWay(_hWay) == ((_ucPos)+1))
#define M_bWayIsFirstWayPoint(_hWay)\
 (M_ucGetWayCurrentWPIndex(_hWay)==0)

#define M_bIsValidDynTypeLink(_eucConnDynType)\
 (((_eucConnDynType)>=ACP_ConDynType_ucNone)&&((_eucConnDynType)<ACP_ConDynType_ucInvalid))

/*
------------------------------------------------------------------------------------------
FUNCTIONS DECLARATION:
------------------------------------------------------------------------------------------
*/

//------------------------------------ Waypoints
ACP_tdxHandleOfWaypoint fn_hConstructWaypoint(void);
void fn_vDestroyWaypoint (ACP_tdxHandleOfWaypoint /*_hWP*/);
ACP_tdxHandleOfWaypoint  fn_hDuplicateWaypoint (ACP_tdxHandleOfWaypoint /*_hWP*/);
void fn_vCopyWaypoint (ACP_tdxHandleOfWaypoint /*_hDestWP*/, ACP_tdxHandleOfWaypoint /*_hSrcWP*/);
void fn_vInvalidateWaypoint(ACP_tdxHandleOfWaypoint* /*_hWP*/);
ACP_tdxBool fn_bIsWaypointValid (ACP_tdxHandleOfWaypoint /*_hWP*/);
ACP_tdxHandleOfWaypoint fn_hAddRefWaypoint(ACP_tdxHandleOfWaypoint /*_hWP*/);
ACP_tdxHandleOfWaypoint fn_hReleaseWaypoint(ACP_tdxHandleOfWaypoint /*_hWP*/);

// set
void fn_vSetRadiusWaypoint (ACP_tdxHandleOfWaypoint /*_hWP*/, MTH_tdxReal /*_xRadius*/);
void fn_vSetVertexWaypoint (ACP_tdxHandleOfWaypoint /*_hWP*/, MTH3D_tdstVector* /*_stVertex*/);
void fn_vSetSuperObjetWaypoint (ACP_tdxHandleOfWaypoint /*_hWP*/, HIE_tdxHandleToSuperObject /*_hSuperObject*/);
// get
void	fn_vGetRadiusWaypoint (ACP_tdxHandleOfWaypoint /*_hWP*/, MTH_tdxReal* /*_pstRadius*/);
void	fn_vGetVertexWaypoint (ACP_tdxHandleOfWaypoint /*_hWP*/, MTH3D_tdstVector* /*_pstVertex*/);
HIE_tdxHandleToSuperObject	fn_pGetSuperObjetWaypoint (ACP_tdxHandleOfWaypoint /*_hWP*/);

// load
SCRIPT_tdeReturnValue fn_eScriptCallBackLoadWaypoint(FILE * /*p_fFile*/, char * /*szAction*/, char ** /*szParams[]*/, SCRIPT_tdeAction /*cType*/);

ACP_tdxHandleOfWaypoint fn_hGetHWPLoaded(char * /*_szFileName*/, char* /*_p_szWPName*/);

// tools

void fn_vComputeLocationWaypoint ( ACP_tdxHandleOfWaypoint /*_hWP*/, MTH3D_tdstVector* /*_pstVertex*/);

//----------------------------------- Link
ACP_tdxHandleOfLink fn_hConstructLink (void);
void fn_vDestroyLink (ACP_tdxHandleOfLink /*_hLink*/);

//JT modify -> .c change
ACP_tdxHandleOfLink  fn_hDuplicateLink (ACP_tdxHandleOfLink /*_hLink*/);

//JT modify -> new function
void fn_vCopyLink (ACP_tdxHandleOfLink /*_hDestLink*/, ACP_tdxHandleOfLink /*_hSrcLink*/);

void fn_vInvalidateLink (ACP_tdxHandleOfLink* /*_hLink*/);
ACP_tdxBool fn_bIsLinkValid (ACP_tdxHandleOfLink /*_hLink*/);
ACP_tdxHandleOfLink fn_hAddRefLink(ACP_tdxHandleOfLink /*_hWP*/);
ACP_tdxHandleOfLink fn_hReleaseLink(ACP_tdxHandleOfLink /*_hWP*/);

void fn_vAllocLink	(ACP_tdxHandleOfLink /*_hLink*/,ACP_tde_ucConnectionType /*_eucConnType*/,ACP_tde_ucConnectionDynamicType /*_eucConnDynType*/);
void fn_vFreeLink	(ACP_tdxHandleOfLink);

ACP_tde_ucConnectionType fn_eucGetConTypeLink(ACP_tdxHandleOfLink /*_hLink*/);
ACP_tde_ucConnectionDynamicType fn_eucGetConDynTypeLink(ACP_tdxHandleOfLink /*_hLink*/);
void *fn_pvGetLinkConTypeInfo(ACP_tdxHandleOfLink /*_hLink*/);

//JT modify -> create new
void fn_vSetLinkConTypeInfo(ACP_tdxHandleOfLink /*_hLink*/, void* /*_pLinkConTypeInfo*/);

ACP_tdstDynaParam  *fn_pvGetLinkConDynTypeInfo(ACP_tdxHandleOfLink /*_hLink*/);
void fn_vSetConTypeLink(ACP_tdxHandleOfLink /*_hLink*/,ACP_tde_ucConnectionType /*_eucType*/);

void fn_vSetConDynTypeLink(ACP_tdxHandleOfLink /*_hLink*/,ACP_tde_ucConnectionDynamicType /*eucType*/);
void fn_vBuildLinkFromszParams(ACP_tdxHandleOfLink /*hLink*/, char ** /*szParams*/,ACP_tdxHandleOfWaypoint /*_hWayPointBefore*/, ACP_tdxHandleOfWaypoint /*_hWayPointAfter*/ );

//-------------------------------- Way
ACP_tdxHandleOfWay fn_hConstructWay (void);
void fn_vDestroyWay (ACP_tdxHandleOfWay /*_hWay*/);
ACP_tdxHandleOfWay  fn_hDuplicateWay (ACP_tdxHandleOfWay /*_hWay*/);
void fn_vCopyWay (ACP_tdxHandleOfWay /*_hWayDst*/, ACP_tdxHandleOfWay /*_hWaySrc*/);
void fn_vInvalidateWay(ACP_tdxHandleOfWay* /*_hWay*/);
ACP_tdxBool fn_bIsWayValid (ACP_tdxHandleOfWay /*_hWay*/);
void fn_vInitWay (ACP_tdxHandleOfWay /*__hWay*/);
ACP_tdxHandleOfWay fn_hAddRefWay(ACP_tdxHandleOfWay /*_hWay*/);
ACP_tdxHandleOfWay fn_hReleaseWay(ACP_tdxHandleOfWay /*_hWay*/);

// manipulate
void fn_vAllocWay		(ACP_tdxHandleOfWay /*_hWay*/, tducWPIndex/*_ucSizeWay*/);
void fn_vFreeWay		(ACP_tdxHandleOfWay /*_hWay*/);
void fn_vReallocWay		(ACP_tdxHandleOfWay /*_hWay*/, tducWPIndex/*_ucNewSizeWay*/);

//JT modify
void fn_vInsertWayPoint		(ACP_tdxHandleOfWay /*_hWay*/, ACP_tdxHandleOfWaypoint /*_hWP*/, ACP_tdxHandleOfLink /*_hLinkBefore*/, ACP_tdxHandleOfLink /*_hLinkAfter*/,  tducWPIndex /*_ucPosWP*/);
//JT modify
void fn_vDeleteWayPoint		(ACP_tdxHandleOfWay /*hWay*/, tducWPIndex /*_ucPosWP*/, ACP_tdxHandleOfLink /*_hNewLink*/);

// set
void fn_vSetCurrentWPWay(ACP_tdxHandleOfWay,tducWPIndex);

// get
tducWPIndex fn_ucGetSizeWay (ACP_tdxHandleOfWay /*hWay*/);
ACP_tdxHandleOfWaypoint fn_hGetWayPoint	(ACP_tdxHandleOfWay /*hWay*/, tducWPIndex /*_ucPos*/);
ACP_tdxHandleOfLink fn_hGetLink		(ACP_tdxHandleOfWay /*hWay*/, tducWPIndex /*ucPos*/);

tducWPIndex fn_ucPositionWayPoint	(ACP_tdxHandleOfWay /*hWay*/, ACP_tdxHandleOfWaypoint /*hWP*/);
ACP_tdxHandleOfWaypoint fn_hNextWayPoint(ACP_tdxHandleOfWay /*hWay*/);
ACP_tdxHandleOfWaypoint fn_hPrevWayPoint		(ACP_tdxHandleOfWay /*hWay*/);
ACP_tdxHandleOfWaypoint fn_hCurrentWayPoint	(ACP_tdxHandleOfWay /*hWay*/);

// load
SCRIPT_tdeReturnValue fn_eScriptCallBackLoadWay(FILE * /*p_fFile*/, char * /*szAction*/, char * /*szParams*/[], SCRIPT_tdeAction /*cType*/);

/* Tools :*/
/* function called when action FollowWay is initialised :*/
void fnv_InitWayBeforeFollowing(HIE_tdxHandleToSuperObject /*_p_SuperObjPerso*/,ACP_tdxHandleOfWay /*_hWay*/);
/* function called when the specific vertex has been reached */
unsigned char fn_ucCurrentVertexReachedWhileFollowingWay(HIE_tdxHandleToSuperObject /*_p_SuperObjPerso*/,ACP_tdxHandleOfWay /* _hWay */);
/* function called to get the speed : */
MTH_tdxReal fn_tdxGetSpeedWay(HIE_tdxHandleToSuperObject /*_p_SuperObjPerso*/,ACP_tdxHandleOfWay /*_hWay*/);
/* function called to get the vertex to reach */
void fn_vGetNextPointWay(HIE_tdxHandleToSuperObject /*_p_SuperobjPerso*/,ACP_tdxHandleOfWay /*_hWay*/,MTH3D_tdstVector* /*_stVertex*/,MTH_tdxReal* /*_p_stMinDist*/);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* !__WAYPOINT_PROTOS__ */

#endif /* !ONLY_TYPES */