/*=========================================================================
* 
* SECTlist.cpp :  Implementation of Editor Lists  
* 
*
* Version			1.0
* Creation date		
* Revision date
*
* Shaitan
*=======================================================================*/

#include "stdafx.h"
#include "acp_base.h"

#include "SECTint.hpp"

DeclareTemplateStatic(SECT_tdxHandleOfElementLstCollisionInteraction); 
DeclareTemplateStatic(SECT_tdxHandleOfElementLstActivityInteraction); 
DeclareTemplateStatic(SECT_tdxHandleOfElementLstGraphicInteraction); 
DeclareTemplateStatic(SECT_tdxHandleOfElementLstSoundInteraction); 
DeclareTemplateStatic(SCT_tdxHandleOfLstSoundEvent); 


//#################################################################################
// Graphic Element
//#################################################################################

/*===========================================================================
	Default Constructor
===========================================================================*/
SECT_GraphicElement::SECT_GraphicElement (SECT_tdxHandleOfElementLstGraphicInteraction hGraphicElement, Sector_Object *pOwnerSector)
	: CPA_EdMot<SECT_tdxHandleOfElementLstGraphicInteraction>(hGraphicElement),
	  SECT_ElementBase (pOwnerSector)
{
	HIE_tdxHandleToSuperObject		hSector;
	SECT_tdxHandleOfSectorObject	hSectObj;
	Sector_Object					*pSectObj;

	// set corresponding sector
	hSector = SECT_GetSectorInGraphicList(hGraphicElement);
	hSectObj = (SECT_tdxHandleOfSectorObject) HIE_fn_hGetSuperObjectObject(hSector);
	pSectObj = (Sector_Object *) pOwnerSector->GetSectorInterface()->GetBaseObject(hSectObj);
	m_pSector = pSectObj->GetSuperObject();
}

/*===========================================================================
	New Constructor
===========================================================================*/
SECT_GraphicElement::SECT_GraphicElement (CPA_SuperObject *pSector, Sector_Object *pOwnerSector)
	: SECT_ElementBase (pOwnerSector)
{
	SECT_tdxHandleOfElementLstGraphicInteraction	hGraphicElem;
	HIE_tdxHandleToSuperObject						hSupObj;

	// create engine element
	hGraphicElem = (SECT_tdxHandleOfElementLstGraphicInteraction) GetStruct();
	// associate it with engine sector
	hSupObj = (HIE_tdxHandleToSuperObject) pSector->GetStruct(); 
	SECT_fn_vSetSectorPointedElementLSTGraphicInt(hGraphicElem, hSupObj);
	// set engine struct
	SetStruct(hGraphicElem);
	// init level
	SetGraphicLevel(1, FALSE);
	// init level
	SetGraphicMode(C_SECT_ModeNormal, FALSE);
	// set corresponding sector
	m_pSector = pSector;
}

/*===========================================================================
	Destructor
===========================================================================*/
SECT_GraphicElement::~SECT_GraphicElement (void)
{

}


/*===========================================================================
	Graphic Level
===========================================================================*/
int	SECT_GraphicElement::GetGraphicLevel (void)
{
	// get engine level of detail
	return SCT_fn_wGetLODInGraphicList(GetStruct());
}

void SECT_GraphicElement::SetGraphicLevel (int iNewLevel, BOOL bNotify)
{
	// set engine level of detail
	SECT_fn_vSetLevelElementLSTGraphicInt(GetStruct(), iNewLevel);
	// save
	if ((m_pOwnerSector)&&(bNotify)&&(g_bCanSave))
		fn_vWriteSection();
}

/*===========================================================================
	Graphic Mode
===========================================================================*/
char SECT_GraphicElement::GetGraphicMode (void)
{
	// get engine graphic mode
	return SCT_fn_wGetModeInGraphicList(GetStruct());
}

void SECT_GraphicElement::SetGraphicMode (char cNewMode, BOOL bNotify)
{
	// set engine graphic mode
	SECT_fn_vSetModeElementLSTGraphicInt(GetStruct(), cNewMode);
	// update list order
	if (m_pOwnerSector)
	{
		// remove element from list and reinsert it at the right place
		if (m_pOwnerSector->fn_bRemoveSectorInList(this, E_Graphic))
			m_pOwnerSector->fn_bAddSectorInList(this, E_Graphic);
	}
	// save
	if ((m_pOwnerSector)&&(bNotify)&&(g_bCanSave))
		fn_vWriteSection();
}

//#################################################################################
// Collision Element
//#################################################################################

/*===========================================================================
	Default Constructor
===========================================================================*/
SECT_CollisionElement::SECT_CollisionElement (SECT_tdxHandleOfElementLstCollisionInteraction hCollisionElement, Sector_Object *pOwnerSector)
	: CPA_EdMot<SECT_tdxHandleOfElementLstCollisionInteraction>(hCollisionElement),
	  SECT_ElementBase (pOwnerSector)
{
	SECT_tdxHandleOfSectorObject	hSectObj;
	HIE_tdxHandleToSuperObject		hSector;
	Sector_Object					*pSectObj;
	
	// set corresponding sector
	hSector = SECT_GetSectorInCollisionList(hCollisionElement);
	hSectObj = (SECT_tdxHandleOfSectorObject) HIE_fn_hGetSuperObjectObject(hSector);
	pSectObj = (Sector_Object *) pOwnerSector->GetSectorInterface()->GetBaseObject(hSectObj);
	m_pSector = pSectObj->GetSuperObject();
}

/*===========================================================================
	New Constructor
===========================================================================*/
SECT_CollisionElement::SECT_CollisionElement (CPA_SuperObject *pSector, Sector_Object *pOwnerSector)
	: SECT_ElementBase (pOwnerSector)
{
	SECT_tdxHandleOfElementLstCollisionInteraction	hCollisionElem;
	HIE_tdxHandleToSuperObject						hSupObj;
	
	// create engine element
	hCollisionElem = (SECT_tdxHandleOfElementLstCollisionInteraction) GetStruct();
	// associate it with engine sector
	hSupObj = (HIE_tdxHandleToSuperObject) pSector->GetStruct(); 
	SECT_fn_vSetSectorPointedElementLSTCollisionInt(hCollisionElem, hSupObj);
	// set engine struct
	SetStruct(hCollisionElem);
	// set corresponding sector
	m_pSector = pSector;
}

/*===========================================================================
	Destructor
===========================================================================*/
SECT_CollisionElement::~SECT_CollisionElement (void)
{

}

//#################################################################################
// Activity Element
//#################################################################################

/*===========================================================================
	Default Constructor
===========================================================================*/
SECT_ActivityElement::SECT_ActivityElement (SECT_tdxHandleOfElementLstActivityInteraction hActivityElement, Sector_Object *pOwnerSector)
	: CPA_EdMot<SECT_tdxHandleOfElementLstActivityInteraction>(hActivityElement),
	  SECT_ElementBase (pOwnerSector)
{
	SECT_tdxHandleOfSectorObject	hSectObj;
	HIE_tdxHandleToSuperObject		hSector;
	Sector_Object					*pSectObj;
	
	// set corresponding sector
	hSector = SECT_GetSectorInActivityList(hActivityElement);
	hSectObj = (SECT_tdxHandleOfSectorObject) HIE_fn_hGetSuperObjectObject(hSector);
	pSectObj = (Sector_Object *) pOwnerSector->GetSectorInterface()->GetBaseObject(hSectObj);
	m_pSector = pSectObj->GetSuperObject();
}

/*===========================================================================
	New Constructor
===========================================================================*/
SECT_ActivityElement::SECT_ActivityElement (CPA_SuperObject *pSector, Sector_Object *pOwnerSector)
	: SECT_ElementBase (pOwnerSector)
{
	SECT_tdxHandleOfElementLstActivityInteraction	hActivityElem;
	HIE_tdxHandleToSuperObject						hSupObj;
	
	// create engine element
	hActivityElem = (SECT_tdxHandleOfElementLstActivityInteraction) GetStruct();
	// associate it with engine sector
	hSupObj = (HIE_tdxHandleToSuperObject) pSector->GetStruct(); 
	SECT_fn_vSetSectorPointedElementLSTActivityInt(hActivityElem, hSupObj);
	// set engine struct
	SetStruct(hActivityElem);
	// set corresponding sector
	m_pSector = pSector;
}


/*===========================================================================
	Destructor
===========================================================================*/
SECT_ActivityElement::~SECT_ActivityElement (void)
{

}


//#################################################################################
// Sound Element
//#################################################################################

/*===========================================================================
	Default Constructor
===========================================================================*/
SECT_SoundElement::SECT_SoundElement (SECT_tdxHandleOfElementLstSoundInteraction hSoundElement, Sector_Object *pOwnerSector)
	: CPA_EdMot<SECT_tdxHandleOfElementLstSoundInteraction>(hSoundElement),
	  SECT_ElementBase (pOwnerSector)
{
	SECT_tdxHandleOfSectorObject	hSectObj;
	HIE_tdxHandleToSuperObject		hSector;
	Sector_Object					*pSectObj;
	
	// set corresponding sector
	hSector = SECT_GetSectorInSoundList(hSoundElement);
	hSectObj = (SECT_tdxHandleOfSectorObject) HIE_fn_hGetSuperObjectObject(hSector);
	pSectObj = (Sector_Object *) pOwnerSector->GetSectorInterface()->GetBaseObject(hSectObj);
	m_pSector = pSectObj->GetSuperObject();
}


/*===========================================================================
	New Constructor
===========================================================================*/
SECT_SoundElement::SECT_SoundElement (CPA_SuperObject *pSector, Sector_Object *pOwnerSector)
	: SECT_ElementBase (pOwnerSector)
{
	SECT_tdxHandleOfElementLstSoundInteraction	hSoundElem;
	HIE_tdxHandleToSuperObject					hSupObj;
	
	// create engine element
	hSoundElem = (SECT_tdxHandleOfElementLstSoundInteraction) GetStruct();
	// associate it with engine sector
	hSupObj = (HIE_tdxHandleToSuperObject) pSector->GetStruct(); 
	SECT_fn_vSetSectorPointedElementLSTSoundInt(hSoundElem, hSupObj);
	// set engine struct
	SetStruct(hSoundElem);
	// init level
	SetSoundLevel(1, FALSE);
	// set corresponding sector
	m_pSector = pSector;
}


/*===========================================================================
	Destructor
===========================================================================*/
SECT_SoundElement::~SECT_SoundElement (void)
{

}


/*===========================================================================
	Sound Level
===========================================================================*/
int	SECT_SoundElement::GetSoundLevel (void)
{
	// get engine volume
	return SCT_fn_lGetVolumeInSoundList(GetStruct());
}

void SECT_SoundElement::SetSoundLevel (int iNewLevel, BOOL bNotify)
{
	// set engine volume
	SCT_fn_vSetVolumeLSTSoundInt(GetStruct(), iNewLevel);
	
	// save
	if ((m_pOwnerSector)&&(bNotify)&&(g_bCanSave))
		fn_vWriteSection();
}

//#################################################################################
// SoundEvent Element
//#################################################################################

/*===========================================================================
	Default Constructor
===========================================================================*/
SECT_SndEvtEngineElem::SECT_SndEvtEngineElem (SCT_tdxHandleOfLstSoundEvent hSoundEventElement, Sector_Object *pOwnerSector)
	: CPA_EdMot<SCT_tdxHandleOfLstSoundEvent>(hSoundEventElement)
{
	SECT_tdxHandleOfSectorObject	hSectObj;
	HIE_tdxHandleToSuperObject		hSector;
	SND_tdxHandleToSoundEvent		hSoundEvent;
	Sector_Object					*pSectObj;
	
	// register owner
	m_pOwnerSector = pOwnerSector;
	// set corresponding sector
	hSector = SCT_fn_hGetSectorInSoundEventList(hSoundEventElement);
	if( hSector != NULL )
	{
		hSectObj = (SECT_tdxHandleOfSectorObject) HIE_fn_hGetSuperObjectObject(hSector);
		pSectObj = (Sector_Object *) pOwnerSector->GetSectorInterface()->GetBaseObject(hSectObj);
		m_pSector = pSectObj->GetSuperObject();
	}
	else
		m_pSector = NULL;
	// set corresponding sound event
	hSoundEvent = SCT_fn_uGetSoundEventInSoundEventList(hSoundEventElement);
	m_pSoundEvent = pOwnerSector->GetSectorInterface()->GetOrNullSoundEvent(hSoundEvent);
}

/*===========================================================================
	New Constructor
===========================================================================*/
SECT_SndEvtEngineElem::SECT_SndEvtEngineElem (CPA_SuperObject *pSector, SECT_SoundEvent *pSoundEvent, Sector_Object *pOwnerSector)
{
	SCT_tdxHandleOfLstSoundEvent	hSoundEventElem;
	HIE_tdxHandleToSuperObject		hSupObj;

	// register owner
	m_pOwnerSector = pOwnerSector;
	// create engine element
	hSoundEventElem = (SCT_tdxHandleOfLstSoundEvent) GetStruct();
	// associate it with engine sector
	hSupObj = (pSector) ? (HIE_tdxHandleToSuperObject) pSector->GetStruct() : NULL; 
	SCT_fn_vSetSectorPointedElementLSTSoundEvent(hSoundEventElem, hSupObj);
	// set engine sound event
	m_pSoundEvent = pSoundEvent;
	if (pSoundEvent)
		SCR_fnp_st_RdL0_AnalyseSection((char*)(LPCSTR) pSoundEvent->GetReferencedSectionName(), SCR_CDF_uw_Anl_Normal);;
	SCT_fn_vSetEventListElementLSTSoundEvent(hSoundEventElem, (m_pSoundEvent) ? (SND_tdxHandleToSoundEvent) m_pSoundEvent->GetData() : NULL);
	// set engine struct
	SetStruct(hSoundEventElem);
	// set corresponding sector
	m_pSector = pSector;
}

/*===========================================================================
	Destructor
===========================================================================*/
SECT_SndEvtEngineElem::~SECT_SndEvtEngineElem (void)
{

}


/*===========================================================================
	Sound Event Reference
===========================================================================*/
CString SECT_SndEvtEngineElem::GetSoundEventReference (void)
{				
	return GetSoundEvent()->GetReferencedSectionName();
}

/*===========================================================================
	Init Sound Event
===========================================================================*/
void SECT_SndEvtEngineElem::fn_vInitSoundEvent (void)
{
	SND_tdxHandleToSoundEvent	hSoundEvent;

	// already initialised => no change
	if (m_pSoundEvent)
		return;

	// set corresponding sound event
 	hSoundEvent = SCT_fn_uGetSoundEventInSoundEventList(GetStruct());
	m_pSoundEvent = m_pOwnerSector->GetSectorInterface()->GetOrNullSoundEvent(hSoundEvent);
}

//#################################################################################
// Sound Event Element
//#################################################################################

/*===========================================================================
	Constructor
===========================================================================*/
SECT_SoundEventElement::SECT_SoundEventElement (CPA_SuperObject *pSector, Sector_Object *pOwnerSector)
	: SECT_ElementBase (pOwnerSector)
{
	// set corresponding sector
	m_pSector = pSector;
	// init list of sound events
	m_oSoundEventList.RemoveAll();
}

/*===========================================================================
	Destructor
===========================================================================*/
SECT_SoundEventElement::~SECT_SoundEventElement (void)
{

}

/*===========================================================================
	Add Sound Event
===========================================================================*/
void SECT_SoundEventElement::fn_vAddSoundEvent (SECT_SndEvtEngineElem *pSndEvtElem, BOOL bNotify)
{
	m_oSoundEventList.AddTail(pSndEvtElem);
	// if necessary, register modif
	if (bNotify)
		fn_vWriteSection();
}

/*===========================================================================
	Remove Sound Event
===========================================================================*/
void SECT_SoundEventElement::fn_vRemoveSoundEvent (SECT_SndEvtEngineElem *pSndEvtElem, BOOL bNotify)
{
	POSITION pos;
	
	pos = m_oSoundEventList.Find(pSndEvtElem, NULL);
	if (pos)
		m_oSoundEventList.RemoveAt(pos);
	// if necessary, register modif
	if (bNotify)
		fn_vWriteSection();
}

/*===========================================================================
	Remove All Sound Events
===========================================================================*/
void SECT_SoundEventElement::fn_vRemoveAllSoundEvents (BOOL bNotify)
{
	m_oSoundEventList.RemoveAll();
	// if necessary, register modif
	if (bNotify)
		fn_vWriteSection();
}

/*===========================================================================
	Copy Sound Events
===========================================================================*/
void SECT_SoundEventElement::fn_vCopyMissingSoundEvents	(SECT_SoundEventElement *pModel, BOOL bNotify)
{
	SECT_SndEvtEngineElem	*pElem, *pNewElem;
	POSITION				pos;
	
	// for all sound event in model list
	for (pElem = pModel->GetSndEvtList()->GetHeadElement(pos); pElem; 
		 pElem = pModel->GetSndEvtList()->GetNextElement(pos))
	{
		// look for same sound event
		pNewElem = GetElementWithSoundEvent(pElem->GetSoundEvent());
		if (!pNewElem)
		{
			// create element and add it
			pNewElem = new SECT_SndEvtEngineElem(m_pSector, pElem->GetSoundEvent(), GetOwnerSector());
			fn_vAddSoundEvent(pNewElem, FALSE);
		}
	}
	// if necessary, register modif
	if (bNotify)
		fn_vWriteSection();
}

/*===========================================================================
	Find Sound Event
===========================================================================*/
SECT_SndEvtEngineElem * SECT_SoundEventElement::GetElementWithSoundEvent (SECT_SoundEvent *pSoundEvent)
{
	SECT_SndEvtEngineElem	*pElem;
	POSITION				pos;
	
	for (pElem = m_oSoundEventList.GetHeadElement(pos); pElem; 
		 pElem = m_oSoundEventList.GetNextElement(pos))
	{
		if (pElem->GetSoundEvent() == pSoundEvent)
			return pElem;
	}

	return NULL;
}

//#################################################################################
// Graphic List
//#################################################################################

/*===========================================================================
	Add Graphic Element
===========================================================================*/
BOOL SECT_GraphicList::fn_bAddAnElement	(SECT_ElementBase *pNewElem, BOOL bUpdateEngine)
{
	if (!pNewElem->GetSector())
		return FALSE;
	
	// try to add element in list base
	if (!SECT_ListBase::fn_bAddAnElement(pNewElem, bUpdateEngine))
		return FALSE;
	
	// no element -> simply add in the list
	if (!GetCount())
		AddTail((SECT_GraphicElement *)pNewElem, bUpdateEngine);
	// else find position according to mode and priority
	else
	{
		SECT_ElementBase	*pCurElem; 
		Sector_Object		*pNewSector;
		Sector_Object		*pCurSector;
		POSITION			pos, curPos; 
		BOOL				bFound; 
		char				cNewMode; 
		char				cCurMode; 
		char				cNewPriority; 
		char				cCurPriority; 

		// init parameters
		pNewSector = (Sector_Object *)pNewElem->GetSector()->GetObject();
		cNewPriority = pNewSector->GetPriority();
		cNewMode = ((SECT_GraphicElement *)pNewElem)->GetGraphicMode();
		// init position
		pos = GetHeadPosition();
		bFound = FALSE;

		// check list to find position
		while (pos && !bFound)
		{
			// save current position
			curPos = pos;
			// get current element
			pCurElem = GetNext(pos);
			// test mode
			cCurMode = ((SECT_GraphicElement *)pCurElem)->GetGraphicMode();
			if (cCurMode > cNewMode)
			{
				InsertBefore(curPos, (SECT_GraphicElement *)pNewElem, bUpdateEngine);
				bFound = TRUE;
			}
			else if (cCurMode == cNewMode)
			{
				pCurSector = (Sector_Object *)pCurElem->GetSector()->GetObject();
				cCurPriority = pCurSector->GetPriority();
				// test priority
				if (cNewPriority > cCurPriority)
				{
					InsertBefore(curPos, (SECT_GraphicElement *)pNewElem, bUpdateEngine);
					bFound = TRUE;
				}
			}
		}
		if (!bFound)
			AddTail((SECT_GraphicElement *)pNewElem, bUpdateEngine);
	}

	return TRUE;
}


/*===========================================================================
	Remove Graphic Element
===========================================================================*/
void SECT_GraphicList::fn_vRemoveAnElement (SECT_ElementBase *pOldElem, BOOL bUpdateEngine)
{
	POSITION pos;
	
	// add element to the list
	pos = Find((SECT_GraphicElement *) pOldElem, NULL);
	if (pos)
		RemoveAt(pos, bUpdateEngine);
	// update sorted list
	SECT_ListBase::fn_vRemoveAnElement(pOldElem, bUpdateEngine);
}

/*===========================================================================
	Remove Graphic Element
===========================================================================*/
void SECT_GraphicList::fn_vRemoveAllElements (BOOL bUpdateEngine)
{
	SECT_ElementBase *pElem;
	
	// remove childs
	while (GetCount())
	{
		// remove child
		pElem = (SECT_ElementBase *) RemoveHead(bUpdateEngine);
		// warn coherence manager
		g_oCoherenceManager.m_fn_vRemoveALink(pElem->GetOwnerSector(), pElem->GetSector());
	}
}

/*===========================================================================
	Get Element
===========================================================================*/
SECT_ElementBase * SECT_GraphicList::GetHeadElementBase (POSITION& rPosition)
{
	return GetHeadElement(rPosition);
}

SECT_ElementBase * SECT_GraphicList::GetNextElementBase (POSITION& rPosition)
{
	return GetNextElement(rPosition);
}


//#################################################################################
// Collision List
//#################################################################################

/*===========================================================================
	Add Collision Element
===========================================================================*/
BOOL SECT_CollisionList::fn_bAddAnElement	(SECT_ElementBase *pNewElem, BOOL bUpdateEngine)
{
	if (!pNewElem->GetSector())
		return FALSE;
	
	// try to add element in list base
	if (!SECT_ListBase::fn_bAddAnElement(pNewElem, bUpdateEngine))
		return FALSE;
	
	// no element -> simply add in the list
	if (!GetCount())
		AddTail((SECT_CollisionElement *)pNewElem, bUpdateEngine);
	// else find position according to priority
	else
	{
		SECT_ElementBase	*pCurElem; 
		Sector_Object		*pNewSector;
		Sector_Object		*pCurSector;
		POSITION			pos, curPos; 
		BOOL				bFound; 
		char				cNewPriority; 
		char				cCurPriority; 

		// init parameters
		pNewSector = (Sector_Object *)pNewElem->GetSector()->GetObject();
		cNewPriority = pNewSector->GetPriority();
		// init position
		pos = GetHeadPosition();
		bFound = FALSE;

		// check list to find position
		while (pos && !bFound)
		{
			// save current position
			curPos = pos;
			// get current element
			pCurElem = GetNext(pos);
			pCurSector = (Sector_Object *)pCurElem->GetSector()->GetObject();
			cCurPriority = pCurSector->GetPriority();
			// test priority
			if (cNewPriority > cCurPriority)
			{
				InsertBefore(curPos, (SECT_CollisionElement *)pNewElem, bUpdateEngine);
				bFound = TRUE;
			}
		}
		if (!bFound)
			AddTail((SECT_CollisionElement *)pNewElem, bUpdateEngine);
	}

	return TRUE;
}


/*===========================================================================
	Remove Collision Element
===========================================================================*/
void SECT_CollisionList::fn_vRemoveAnElement (SECT_ElementBase *pOldElem, BOOL bUpdateEngine)
{
	POSITION pos;
	
	// add element to the list
	pos = Find((SECT_CollisionElement *) pOldElem, NULL);
	if (pos)
		RemoveAt(pos, bUpdateEngine);
	// update sorted list
	SECT_ListBase::fn_vRemoveAnElement(pOldElem, bUpdateEngine);
}

/*===========================================================================
	Remove Collision Element
===========================================================================*/
void SECT_CollisionList::fn_vRemoveAllElements (BOOL bUpdateEngine)
{
	SECT_ElementBase *pElem;
	
	// remove childs
	while (GetCount())
	{
		// remove child
		pElem = (SECT_ElementBase *) RemoveHead(bUpdateEngine);
		// warn coherence manager
		g_oCoherenceManager.m_fn_vRemoveALink(pElem->GetOwnerSector(), pElem->GetSector());
	}
}

/*===========================================================================
	Get Element
===========================================================================*/
SECT_ElementBase * SECT_CollisionList::GetHeadElementBase (POSITION& rPosition)
{
	return GetHeadElement(rPosition);
}

SECT_ElementBase * SECT_CollisionList::GetNextElementBase (POSITION& rPosition)
{
	return GetNextElement(rPosition);
}


//#################################################################################
// Activity List
//#################################################################################

/*===========================================================================
	Add Activity Element
===========================================================================*/
BOOL SECT_ActivityList::fn_bAddAnElement (SECT_ElementBase *pNewElem, BOOL bUpdateEngine)
{
	if (!pNewElem->GetSector())
		return FALSE;
	
	// try to add element in list base
	if (!SECT_ListBase::fn_bAddAnElement(pNewElem, bUpdateEngine))
		return FALSE;
	
	// no element -> simply add in the list
	if (!GetCount())
		AddTail((SECT_ActivityElement *)pNewElem, bUpdateEngine);
	// else find position according to priority
	else
	{
		SECT_ElementBase	*pCurElem; 
		Sector_Object		*pNewSector;
		Sector_Object		*pCurSector;
		POSITION			pos, curPos; 
		BOOL				bFound; 
		char				cNewPriority; 
		char				cCurPriority; 

		// init parameters
		pNewSector = (Sector_Object *)pNewElem->GetSector()->GetObject();
		cNewPriority = pNewSector->GetPriority();
		// init position
		pos = GetHeadPosition();
		bFound = FALSE;

		// check list to find position
		while (pos && !bFound)
		{
			// save current position
			curPos = pos;
			// get current element
			pCurElem = GetNext(pos);
			pCurSector = (Sector_Object *)pCurElem->GetSector()->GetObject();
			cCurPriority = pCurSector->GetPriority();
			// test priority
			if (cNewPriority > cCurPriority)
			{
				InsertBefore(curPos, (SECT_ActivityElement *)pNewElem, bUpdateEngine);
				bFound = TRUE;
			}
		}
		if (!bFound)
			AddTail((SECT_ActivityElement *)pNewElem, bUpdateEngine);
	}

	return TRUE;
}


/*===========================================================================
	Remove Activity Element
===========================================================================*/
void SECT_ActivityList::fn_vRemoveAnElement (SECT_ElementBase *pOldElem, BOOL bUpdateEngine)
{
	POSITION pos;
	
	// add element to the list
	pos = Find((SECT_ActivityElement *) pOldElem, NULL);
	if (pos)
		RemoveAt(pos, bUpdateEngine);
	// update sorted list
	SECT_ListBase::fn_vRemoveAnElement(pOldElem, bUpdateEngine);
}


/*===========================================================================
	Remove Activity Element
===========================================================================*/
void SECT_ActivityList::fn_vRemoveAllElements (BOOL bUpdateEngine)
{
	SECT_ElementBase *pElem;
	
	// remove childs
	while (GetCount())
	{
		// remove child
		pElem = (SECT_ElementBase *) RemoveHead(bUpdateEngine);
		// warn coherence manager
		g_oCoherenceManager.m_fn_vRemoveALink(pElem->GetOwnerSector(), pElem->GetSector());
	}
}

/*===========================================================================
	Get Element
===========================================================================*/
SECT_ElementBase * SECT_ActivityList::GetHeadElementBase (POSITION& rPosition)
{
	return GetHeadElement(rPosition);
}

SECT_ElementBase * SECT_ActivityList::GetNextElementBase (POSITION& rPosition)
{
	return GetNextElement(rPosition);
}


//#################################################################################
// Sound List
//#################################################################################

/*===========================================================================
	Add Sound Element
===========================================================================*/
BOOL SECT_SoundList::fn_bAddAnElement (SECT_ElementBase *pNewElem, BOOL bUpdateEngine)
{
	if (!pNewElem->GetSector())
		return FALSE;
	
	// try to add element in list base
	if (!SECT_ListBase::fn_bAddAnElement(pNewElem, bUpdateEngine))
		return FALSE;
	
	// no element -> simply add in the list
	if (!GetCount())
		AddTail((SECT_SoundElement *)pNewElem, bUpdateEngine);
	// else find position according to priority
	else
	{
		SECT_ElementBase	*pCurElem; 
		Sector_Object		*pNewSector;
		Sector_Object		*pCurSector;
		POSITION			pos, curPos; 
		BOOL				bFound; 
		char				cNewPriority; 
		char				cCurPriority; 

		// init parameters
		pNewSector = (Sector_Object *)pNewElem->GetSector()->GetObject();
		cNewPriority = pNewSector->GetPriority();
		// init position
		pos = GetHeadPosition();
		bFound = FALSE;

		// check list to find position
		while (pos && !bFound)
		{
			// save current position
			curPos = pos;
			// get current element
			pCurElem = GetNext(pos);
			pCurSector = (Sector_Object *)pCurElem->GetSector()->GetObject();
			cCurPriority = pCurSector->GetPriority();
			// test priority
			if (cNewPriority > cCurPriority)
			{
				InsertBefore(curPos, (SECT_SoundElement *)pNewElem, bUpdateEngine);
				bFound = TRUE;
			}
		}
		if (!bFound)
			AddTail((SECT_SoundElement *)pNewElem, bUpdateEngine);
	}

	return TRUE;
}


/*===========================================================================
	Remove Sound Element
===========================================================================*/
void SECT_SoundList::fn_vRemoveAnElement (SECT_ElementBase *pOldElem, BOOL bUpdateEngine)
{
	POSITION pos;
	
	// add element to the list
	pos = Find((SECT_SoundElement *) pOldElem, NULL);
	if (pos)
		RemoveAt(pos, bUpdateEngine);
	// update sorted list
	SECT_ListBase::fn_vRemoveAnElement(pOldElem, bUpdateEngine);
}

/*===========================================================================
	Remove Sound Element
===========================================================================*/
void SECT_SoundList::fn_vRemoveAllElements (BOOL bUpdateEngine)
{
	SECT_ElementBase *pElem;
	
	// remove childs
	while (GetCount())
	{
		// remove child
		pElem = (SECT_ElementBase *) RemoveHead(bUpdateEngine);
		// warn coherence manager
		g_oCoherenceManager.m_fn_vRemoveALink(pElem->GetOwnerSector(), pElem->GetSector());
	}
}


/*===========================================================================
	Get Element
===========================================================================*/
SECT_ElementBase * SECT_SoundList::GetHeadElementBase (POSITION& rPosition)
{
	return GetHeadElement(rPosition);
}

SECT_ElementBase * SECT_SoundList::GetNextElementBase (POSITION& rPosition)
{
	return GetNextElement(rPosition);
}


//#################################################################################
// SoundEvent List
//#################################################################################

/*===========================================================================
	Add SoundEventElement
===========================================================================*/
BOOL SECT_SoundEventList::fn_bAddAnElement (CPA_SuperObject *pSector, SECT_SoundEvent *pSoundEvent)
{
	SECT_SoundEventElement	*pElement;
	SECT_SndEvtEngineElem	*pSndEvElem;

	// get or create correponding element
	pElement = (SECT_SoundEventElement *) GetElementWithSector(pSector);
	if (!pElement)
	{
		pElement = new SECT_SoundEventElement(pSector, m_pOwnerSector);
		m_oElementList.AddTail(pElement);
	}
	// get sound event element
	pSndEvElem = pElement->GetElementWithSoundEvent(pSoundEvent);
	if (pSndEvElem)
		return FALSE;

	// add new sound event
	pSndEvElem = new SECT_SndEvtEngineElem(pSector, pSoundEvent, pElement->GetOwnerSector());
	// add sound event to element
	pElement->fn_vAddSoundEvent(pSndEvElem);
	// add element to the list
	AddTail(pSndEvElem);
	return TRUE;
}

/*===========================================================================
	Add SoundEventElement
===========================================================================*/
BOOL SECT_SoundEventList::fn_bRemoveAnElement (CPA_SuperObject *pSector, SECT_SoundEvent *pSoundEvent)
{
	SECT_SoundEventElement	*pElement;
	SECT_SndEvtEngineElem	*pSndEvElem;
	POSITION				pos;
	
	// get or create correponding element
	pElement = (SECT_SoundEventElement *) GetElementWithSector(pSector);
	if (!pElement)
		return FALSE;

	// get sound event element
	pSndEvElem = pElement->GetElementWithSoundEvent(pSoundEvent);
	if (!pSndEvElem)
		return FALSE;

	// remove sound event from element
	pElement->fn_vRemoveSoundEvent(pSndEvElem);
	// remove element from the list
	pos = Find(pSndEvElem, NULL);
	if (pos)
		RemoveAt(pos);

	return TRUE;
}

/*===========================================================================
	Add SoundEvent Engine Element
===========================================================================*/
BOOL SECT_SoundEventList::fn_bAddAnElement (SECT_SndEvtEngineElem *pEngineElem)
{
	SECT_SoundEventElement	*pElement;
	CPA_SuperObject			*pSector;

	// get corresponding parameters
	pSector = pEngineElem->GetSector();
	// get or create correponding element
	pElement = (SECT_SoundEventElement *) GetElementWithSector(pSector);
	if (!pElement)
	{
		pElement = new SECT_SoundEventElement(pSector, m_pOwnerSector);
		m_oElementList.AddTail(pElement);
	}
	// add sound event to element
	pElement->fn_vAddSoundEvent(pEngineElem, FALSE);
	// add element to the list
	AddTail(pEngineElem, FALSE);

	return TRUE;
}

/*===========================================================================
	Add SoundEvent Element
===========================================================================*/
BOOL SECT_SoundEventList::fn_bAddAnElement	(SECT_ElementBase *pNewElem, BOOL bUpdateEngine)
{
	SECT_SndEvtEngineElem	*pEngineElem;
	SECT_SoundEventElement		*pElement;
	POSITION					pos;
	
	// try to add element in list base
	if (!SECT_ListBase::fn_bAddAnElement(pNewElem, bUpdateEngine))
		return FALSE;
	
	// add element to the list
	pElement = (SECT_SoundEventElement *) pNewElem;
	m_oElementList.AddTail(pElement);
	// update engine list
	for (pEngineElem = pElement->GetSndEvtList()->GetHeadElement(pos); pEngineElem;
		 pEngineElem = pElement->GetSndEvtList()->GetNextElement(pos))
		AddTail(pEngineElem, bUpdateEngine);

	return TRUE;
}


/*===========================================================================
	Remove SoundEvent Element
===========================================================================*/
void SECT_SoundEventList::fn_vRemoveAnElement (SECT_ElementBase *pOldElem, BOOL bUpdateEngine)
{
	SECT_SoundEventElement	*pElement;
	SECT_SndEvtEngineElem	*pEngineElem;
	POSITION				pos, pos1;
	
	// remove element from the list
	pElement = (SECT_SoundEventElement *) pOldElem;
	pos = m_oElementList.Find(pElement, NULL);
	if (pos)
		m_oElementList.RemoveAt(pos);
	// if necessary, update engine
	for (pEngineElem = pElement->GetSndEvtList()->GetHeadElement(pos); pEngineElem;
		 pEngineElem = pElement->GetSndEvtList()->GetNextElement(pos))
	{
		pos1 = Find(pEngineElem, NULL);
		if (pos1)
			RemoveAt(pos1, bUpdateEngine);
	}

	// update sorted list
	SECT_ListBase::fn_vRemoveAnElement(pOldElem, bUpdateEngine);
}

/*===========================================================================
	Remove SoundEvent Element
===========================================================================*/
void SECT_SoundEventList::fn_vRemoveAllElements (BOOL bUpdateEngine)
{
	SECT_ElementBase *pElem;
	
	// remove elements
	while (m_oElementList.GetCount())
	{
		// remove child
		pElem = (SECT_ElementBase *) m_oElementList.RemoveHead();
		// warn coherence manager
		g_oCoherenceManager.m_fn_vRemoveALink(pElem->GetOwnerSector(), pElem->GetSector());
	}
	// remove engine elements
	while (GetCount())
		RemoveHead(bUpdateEngine);
}


/*===========================================================================
	Get Element
===========================================================================*/
SECT_ElementBase * SECT_SoundEventList::GetHeadElementBase (POSITION& rPosition)
{
	return m_oElementList.GetHeadElement(rPosition);
}

SECT_ElementBase * SECT_SoundEventList::GetNextElementBase (POSITION& rPosition)
{
	return m_oElementList.GetNextElement(rPosition);
}
