/*=============================================================================
 *
 *  Filename:			CPAFamil.hpp
 *  Version:            1.0
 *  Date:				30/12/96
 *  Author:             Marc Trabucato & Vincent Lhullier
 *
 *  Description:		definition of CPA_Family class (decendant of CPA_ReachableObject)
 *						that contains description of a family (name, anims, actions )
 *
 *===========================================================================*/
 
#ifndef __CPAFAMIL_HPP__
#define __CPAFAMIL_HPP__
 
#ifdef ACTIVE_EDITOR
 
#include "ACP_Base.h"
#include "ITF.h"
// Shaitan => optimisation lists in the level
#include "DPT.h"
// End Shaitan => optimisation lists in the level
#define D_ZdxStuff_StructureDefine
#define D_State_Define
#include "incGAM.h"
#undef D_ZdxStuff_StructureDefine
#undef D_State_Define
/*#include "GLI.h"*/
 
#include "TAC.h"
#include "TAN.h"
#include "TOT.h"
 
/****************************************/
#ifndef CPA_EXPORT
#if defined(CPA_WANTS_IMPORT)
#define CPA_EXPORT __declspec(dllimport)
#elif defined(CPA_WANTS_EXPORT)
#define CPA_EXPORT __declspec(dllexport)
#else
#define CPA_EXPORT
#endif
#endif
/****************************************/
 
/*=============================================================================
* Define : name of Family Type (for reachable constructor)
=============================================================================*/
#define C_szFamilyTypeName      "Family"
 
class CPA_Channel;
 
typedef struct
{
    CPA_Family	*p_oFamily;
    char		*szChannel;
    long		lIndexOfChannel;
	CPA_Channel *p_oChannel;
} tdstChannelInfoSearch;
 
/*=============================================================================
* class CPA_Family
=============================================================================*/
class CPA_Family : public CPA_SaveObject,
                   public CPA_EdMot<tdxHandleToFamilyList>
{
	/* variables*/
    protected:
        CPA_Action          *m_p_oInitialAction;
        CPA_BaseObject      *m_p_oZDxBoundingVolume;
        char                m_szBdVSectionName[SCR_CV_ui_Cfg_MaxLenName];
        BOOL                m_bIsABaseFamily;                       /* When TRUE, the family is a base family : one can copy its states and actions*/
	public:
        CPA_EdList<CPA_State,tdxHandleToState,LST2_M_StaticAnchorTo(tdxHandleToState)*>    m_oListOfStates;
        CPA_List<CPA_Action>            m_oListOfActions;           /* list of actions*/
// Shaitan => state list in the level
        CPA_List<CPA_Action>            m_oListOfUsedActions;       /* list of actions used in the loaded level */
// End Shaitan => state list in the level
// Shaitan => module list in the level
        CPA_List<CPA_BaseObject>        m_oListOfUsedPOs;			/* list of POs used in the loaded level */
        CPA_List<EditorObjectTable>     m_oListOfUsedObjectTables;  /* list of object tables used in the loaded level */
// End Shaitan => module list in the level
        CPA_List<CPA_Animation>         m_oListOfAnimations;        /* list of animations*/
        CPA_List<EditorObjectTable>     m_oListOfObjectTables;      /* list of object tables*/
        BOOL							m_bUsedByCurrentLevel;
        CList<CString,CString>			m_oListOfChannelsName;

// Shaitan => optimisation lists in the level
        BOOL							m_bMustUpdateStateList;		/* modification flag */
        BOOL							m_bMustUpdatePOList;		/* modification flag */
// End Shaitan => optimisation list in the level

	/* methods*/
	public:
		/* constructor*/
        CPA_Family(CPA_EditorBase *_p_oEditor, tdxHandleToFamilyList _hEngineFamily, char *_szFamilyName = NULL);
        ~CPA_Family();
 
        /* virtual methods overloaded*/
        /* CPA_BaseObject*/
        long        GetDataType             ( void )            { return 0; }
        void*       GetData                 ( void )            { return (void*)GetStruct(); }
        static void Init                    ( void );
		static void InitStatic				( CPA_MainWorld *_p_oMainWorld );
        void        mfn_vLoad               ( void );
        static void mfn_vCallBackSave       ( SCR_tdst_File_Description *_p_stFile, char *_p_szSectionName, void *_p_vData, SCR_tde_Ntfy_Action _eAction);
        static void mfn_vCallBackSaveEmptySection   ( SCR_tdst_File_Description *_p_stFile, char *_p_szSectionName, void *_p_vData, SCR_tde_Ntfy_Action _eAction);
        static SCR_tde_Anl_ReturnValue 
                    mfn_CallbackLoadBaseFamilySection ( SCR_tdst_File_Description *_p_stFile, char *_p_szName,
                                                        char *_ap_szParams[], SCR_tde_Anl_Action _eAction );
    /**/
    protected:
        void SetStruct						( tdxHandleToFamilyList _hFamily);
		void mfn_vFillChannelNamesList		( void );
        void mfn_vInitACZFile               ( void );
        void mfn_vFillTPLList               ( void );
    /**/
    public:
 
        /**/
        void       mfn_vSetInitialAction    ( CPA_Action *_p_oAction )  { m_p_oInitialAction = _p_oAction; }
        CPA_Action *mfn_p_oGetInitialAction ( void )                    { return m_p_oInitialAction; }
        /* add functions*/
        inline void mfn_vAddAnimation       ( CPA_Animation *_p_oAnimation );
        inline void mfn_vAddAction          ( CPA_Action *_p_oAction );
        inline void mfn_vAddState           ( CPA_State *_p_oState, BOOL _bModifyEngine = TRUE );
        inline void mfn_vAddObjectTable     ( EditorObjectTable *_p_oObjectTable);
 
        void mfn_vSetOnLevel            (BOOL _bOnLevel )                   { m_bUsedByCurrentLevel = _bOnLevel; }
 
        /* remove functions*/
        inline void mfn_vRemoveAction   ( CPA_Action *_p_oAction );
        inline void mfn_vRemoveState    ( CPA_State *_p_oState, BOOL _bModifyEngine = TRUE );
 
        /* get functions*/
        CPA_Animation       *mfn_p_oGetAnimation        ( const CString _csAnimName ) ;
        CPA_Action          *mfn_p_oGetAction           ( const CString _csActionName ) ;
        CPA_State           *mfn_p_oGetState            ( const CString _csStateName );
        EditorObjectTable   *mfn_p_oGetObjectTable      ( const CString _csObjectTableName );
        inline tdxHandleToState mfn_p_stGetEngineState  ( const CString _csStateName );
 
        /* test functions*/
        BOOL mfn_bIsAnimationOfFamily       ( CPA_Animation *_p_oAnimation )    { return ((BOOL)m_oListOfAnimations . Find ( _p_oAnimation )) ; }
        BOOL mfn_bIsActionOfFamily          ( CPA_Action *_p_oAction )          { return ((BOOL)m_oListOfActions . Find ( _p_oAction )) ; }
        BOOL mfn_bIsStateOfFamily           ( CPA_State *_p_oState )            { return ((BOOL)m_oListOfStates . Find ( _p_oState )) ; }
        BOOL mfn_bIsObjectTableOfFamily     ( EditorObjectTable *_p_oObjTbl )   { return ((BOOL)m_oListOfObjectTables . Find ( _p_oObjTbl )) ; }
        BOOL mfn_bIsLoadedOnCurrentLevel( void )                            { return m_bUsedByCurrentLevel; }
        BOOL mfn_bIsABaseFamily( void )                                     { return m_bIsABaseFamily;      }
 
        /* Bounding volume*/
        inline void    mfn_vSetBoundingVolume   ( CPA_BaseObject *_p_oZdx);
        CPA_BaseObject *mfn_p_oGetBoundingVolume( void )                           { return m_p_oZDxBoundingVolume; }

// Shaitan => optimisation lists in the level
        inline void mfn_vSetModifiedStateList	(void);
		inline void mfn_vSetModifiedPOList		(void);

		inline BOOL mfn_bMustUpdateStateList	(void);
		inline BOOL mfn_bMustUpdatePOList		(void);
// End Shaitan => optimisation list in the level

};
 
/*=============================================================================
* Macros to add an action, an anim or a transition anim to a family
=============================================================================*/
#define M_AddActionToFamily( p_oFamily , p_oAction )          p_oFamily -> mfn_vAddAction( p_oAction )
#define M_AddAnimationToFamily( p_oFamily , p_oAnimation )    p_oFamily -> mfn_vAddAnimation( p_oAnimation )
#define M_AddStateToFamily( p_oFamily , p_oState )            p_oFamily -> mfn_vAddState( p_oState )
#define M_AddObjectTableToFamily( p_oFamily, p_oObjectTable ) p_oFamily -> mfn_vAddObjectTable( p_oObjectTable )
 
 
/*=============================================================================
 * inline functions implementation
=============================================================================*/
 
/* ----------------------------------------------------------------------------*/
/* Description : add an animation to family*/
/* ----------------------------------------------------------------------------*/
inline void CPA_Family::mfn_vAddAnimation( CPA_Animation *_p_oAnimation )
{
    m_oListOfAnimations . AddTail( _p_oAnimation );
}
 
/* ----------------------------------------------------------------------------*/
/* Description : add an action to family*/
/* ----------------------------------------------------------------------------*/
inline void CPA_Family::mfn_vAddAction( CPA_Action *_p_oAction )
{
    ASSERT( !m_oListOfActions . Find ( _p_oAction ) );
    m_oListOfActions . AddTail( _p_oAction );
 
    if( m_p_oInitialAction == NULL )
    {
        m_p_oInitialAction = _p_oAction;
    }
}
 
/* ----------------------------------------------------------------------------*/
/* Description : add a state to family*/
/* ----------------------------------------------------------------------------*/
inline void CPA_Family::mfn_vAddState( CPA_State *_p_oState, BOOL _bModifyEngine /*=TRUE*/ )
{
    ASSERT( ! m_oListOfStates . Find ( _p_oState ) );
    m_oListOfStates . AddTail( _p_oState, _bModifyEngine );
}
 
/* ----------------------------------------------------------------------------*/
/* Description : add an objecttable to family*/
/* ----------------------------------------------------------------------------*/
inline void CPA_Family::mfn_vAddObjectTable(EditorObjectTable *_p_oObjectTable)
{
    ASSERT( !m_oListOfObjectTables . Find ( _p_oObjectTable ) );
    m_oListOfObjectTables . AddTail( _p_oObjectTable );
}
 
/* ----------------------------------------------------------------------------*/
/* Description : remove action from family*/
/* ----------------------------------------------------------------------------*/
inline void CPA_Family::mfn_vRemoveAction( CPA_Action *_p_oAction )
{
    POSITION stPos = m_oListOfActions . Find ( _p_oAction );
 
    if( stPos )
    {
        m_oListOfActions . RemoveAt ( stPos );
        if( ( m_p_oInitialAction == _p_oAction ) && ( m_oListOfActions . GetCount() > 0 ) )
        {
            m_p_oInitialAction = m_oListOfActions . GetHeadElement();
        }
    }
}
 
/* ----------------------------------------------------------------------------*/
/* Description : remove state from family (editor and engine)*/
/* ----------------------------------------------------------------------------*/
inline void CPA_Family::mfn_vRemoveState( CPA_State *_p_oState, BOOL _bModifyEngine /*=TRUE*/  )
{
    POSITION stPos = m_oListOfStates . Find ( _p_oState );
 
    if( stPos )
    {
        m_oListOfStates . RemoveAt ( stPos, _bModifyEngine );
    }
}
 
/* ----------------------------------------------------------------------------*/
/* Description : return engine state of given name*/
/* ----------------------------------------------------------------------------*/
inline tdxHandleToState CPA_Family::mfn_p_stGetEngineState( CString _csStateName )
{
    tdxHandleToState hState;
    int iIndex;
 
    LST2_M_StaticForEachElementOf( & GetStruct() -> hForStateArray, hState, iIndex)
    {
        if( !_csStateName.CompareNoCase(hState -> szStateName) )
            return hState;
    }
    return NULL;
}
 
/* ----------------------------------------------------------------------------*/
/* Description : update Bounding Volume*/
/* ----------------------------------------------------------------------------*/
inline void CPA_Family::mfn_vSetBoundingVolume( CPA_BaseObject *_p_oZdx)
{
    GEO_tdxHandleToBoundingSphere	hFamilyBoundingSphere;
 
	m_p_oZDxBoundingVolume		= _p_oZdx;
 
	hFamilyBoundingSphere = fn_vGetBoundingVolumeOfFamily(GetStruct());
 
    if( m_p_oZDxBoundingVolume )
	{
        fn_vSetGeometricSphereOfFamily(GetStruct(),(ACP_tdxHandleOfObject)m_p_oZDxBoundingVolume->GetData());
		GEO_fn_vUpdateBoundingSphere((ACP_tdxHandleOfObject)m_p_oZDxBoundingVolume->GetData(), hFamilyBoundingSphere);
	}
    else
        fn_vSetGeometricSphereOfFamily(GetStruct(),(ACP_tdxHandleOfObject)NULL);
 
    fn_vNotifySave();
}
 
// Shaitan => optimisation lists in the level
/*-----------------------------------------------------------------------------
 *  Description : set modification flags
 *---------------------------------------------------------------------------*/
inline void CPA_Family::mfn_vSetModifiedStateList (void)
{
	m_bMustUpdateStateList = TRUE;
	m_bMustUpdatePOList = TRUE;
}
/*-----------------------------------------------------------------------------
 *  Description : set modification flags
 *---------------------------------------------------------------------------*/
inline void CPA_Family::mfn_vSetModifiedPOList (void)
{
	m_bMustUpdatePOList = TRUE;
}

/*-----------------------------------------------------------------------------
 *  Description : test modification flag
 *---------------------------------------------------------------------------*/
inline BOOL CPA_Family::mfn_bMustUpdateStateList (void)
{
    char szSectionName[SCR_CV_ui_Cfg_MaxLenName];

	// if flag is not set, no need to go further
	if (!m_bMustUpdateStateList)
		return FALSE;

	// check if the family is optimized
	sprintf(szSectionName,"%s\\%s\\Families\\%s\\%s.stl^%s",
		fn_szGetLevelsDataPath(),
		fn_p_szGetLevelName(),
		GetName(),
		GetName(),
		C_SectionCreateListOfState);
	return (SCR_fn_c_RdL0_IsSectionExists(szSectionName));
}

/*-----------------------------------------------------------------------------
 *  Description : test modification flag
 *---------------------------------------------------------------------------*/
inline BOOL CPA_Family::mfn_bMustUpdatePOList (void)
{
    char szSectionName[SCR_CV_ui_Cfg_MaxLenName];

	// if flag is not set, no need to go further
	if (!m_bMustUpdatePOList)
		return FALSE;

	// check if the family is optimized
	sprintf(szSectionName,"%s\\%s\\Families\\%s\\%s.otl^%s",
		fn_szGetLevelsDataPath(),
		fn_p_szGetLevelName(),
		GetName(),
		GetName(),
		C_SectionCreateListOfPOs);
	return (SCR_fn_c_RdL0_IsSectionExists(szSectionName));
}
// End Shaitan => optimisation list in the level

#endif /* ACTIVE_EDITOR*/
 
#endif /* __CPAFAMIL_HPP__*/
