// class CPA_WORLD

#include "stdafx.h"

#ifdef ACTIVE_EDITOR

#include "acp_base.h"
#include "itf/CPAWorld.hpp"
#include "itf/cpasobj.hpp"
#include "itf/devmul3d.hpp"
#include "itf/CPAMWorl.hpp"
#include "itf/CPAInter.hpp"
#include "itf/stddllid.h"


CPA_World::CPA_World(CPA_MainWorld *_p_oMainWorld, BOOL bTemporary)
{
	CPA_CameraDLLBase* p_oCamDLL;

    m_bIsTemporary = bTemporary;
	m_p_oSprObjRoot = NULL;
	m_p_oMultiDevice = NULL;
    fn_vInitListObjects(_p_oMainWorld->GetListOfObjectDLLBase());

	p_oCamDLL = (CPA_CameraDLLBase*) (_p_oMainWorld->GetObjectDLLWithName(C_szDLLCameraName));
	m_oCameraSlots.SetInterface(p_oCamDLL);
}

CPA_World::~CPA_World()
{
	while (!(m_lstListByDLL.IsEmpty()))
		delete m_lstListByDLL.RemoveHead();
//CPA2 Corneliu Babiuc (multiple teleportation) 3-03-98
	while (!(m_lstRegisterListByDLL.IsEmpty()))
		delete m_lstRegisterListByDLL.RemoveHead();
//END CPA2 Corneliu Babiuc (multiple teleportation) 3-03-98
}


CPA_Interface * CPA_World::GetInterface (void)
{
	return m_p_oMultiDevice->GetInterface();
}

/*===========================================================================
*		Description:	Init the lists 
*		Creation date:	
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:        Author:         
*=========================================================================*/
void CPA_World::fn_vCreateListFromHierarchy(CPA_List<CPA_ObjectDLLBase> *_p_oListOfObjectDLL)
{
    fn_vInitListObjects(_p_oListOfObjectDLL);
    fn_vInitListAllObjects(m_p_oSprObjRoot);
}

/*===========================================================================
*		Description:	Init the lists from Objects DLLs
*		Creation date:	
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		
*---------------------------------------------------------------------------
*		Revision date:        Author:         
*=========================================================================*/
void CPA_World::fn_vInitListObjects(CPA_List<CPA_ObjectDLLBase> *_p_oListOfObjectDLL)
{
	CPA_ObjectDLLBase	*p_oDLL;
	POSITION			pos;

	// RAZ
	m_lstListByDLL.RemoveAll();
	m_stListAllObjects.RemoveAll();
	m_stListAllDLLs.fn_vReinit();
//CPA2 Corneliu Babiuc (multiple registration)
	m_lstRegisterListByDLL.RemoveAll();
	m_stRegisterListAllDLLs.fn_vReinit();
//END CPA2 Corneliu Babiuc (multiple registration)

    // check all objects dlls to find the available types
    for (p_oDLL = _p_oListOfObjectDLL->GetHeadElement(pos); p_oDLL;
         p_oDLL = _p_oListOfObjectDLL->GetNextElement(pos))
    {
		// create the corresponding ListByType
		m_lstListByDLL.AddTail(new EDT_ListByDLL(p_oDLL));
//CPA2 Corneliu Babiuc (multiple registration)
		m_lstRegisterListByDLL.AddTail(new EDT_ListByDLL(p_oDLL));
//END CPA2 Corneliu Babiuc (multiple registration)
		p_oDLL->fn_vInitListByType(this);
    }
}


/*===========================================================================
*		Description:	create and init the lists of models
*		Creation date:	
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_World::fn_vAddANewListByType (char *szTypeName, CPA_ObjectDLLBase *pObjectDLL)
{
	EDT_ListByType	*pListType;
	EDT_ListByDLL	*pListDLL;
	
	// find the corresponding DLL list
	pListDLL = GetListFromObjectDLL(pObjectDLL);
	if (!pListDLL)
	{
		pListDLL= new EDT_ListByDLL(pObjectDLL);
		GetListOfListByDLL()->AddTail(pListDLL);
	}

	// create list by type
	pListType = pListDLL->GetListByType(szTypeName);
	if (!pListType)
	{
		pListType = new EDT_ListByType(pObjectDLL, szTypeName);
		pListDLL->m_stListOfListByType.AddTail(pListType);
	}
}


/*===========================================================================
*		Description:	Init the list of all objects in the hierarchy
*		Creation date:	
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		
*---------------------------------------------------------------------------
*		Revision date:        Author:         
*=========================================================================*/
void CPA_World::fn_vInitListAllObjects(CPA_SuperObject *_p_EdObj)
{
    CPA_SuperObject *p_EdChild;

    p_EdChild = _p_EdObj->GetSuperObjectFirstChild();
    while (p_EdChild)
	{
		// add the child to the list
        m_stListAllObjects.AddTail(p_EdChild);
		// next level of hierarchy
        fn_vInitListAllObjects(p_EdChild);
		// next brother
        p_EdChild = _p_EdObj->GetSuperObjectNextChild(p_EdChild);
	}
}

void CPA_World::InitWorldForDrawing()
{
	ASSERT(m_p_oSprObjRoot != NULL);

	// compute new world spherebox
//	GLI_xComputeSuperObjectSphereBox(m_p_oSprObjRoot->GetStruct());
}


void CPA_World::fn_vSetRoot(CPA_SuperObject *_p_SprObj)
{
	// if there is a multidevice, then clear old engine struct
	if (m_p_oMultiDevice)
		m_p_oMultiDevice->SetEngineWorld(NULL);

	m_p_oSprObjRoot = _p_SprObj;

	if (m_p_oSprObjRoot)
	{
		InitWorldForDrawing();
		fn_vReinitListObjects();
		fn_vFillListObjects(m_p_oSprObjRoot);
		fn_vReinitSortedList();
		if (m_p_oMultiDevice)
		{
			m_p_oMultiDevice->SetEngineWorld(m_p_oSprObjRoot->GetStruct());
			if (m_p_oMultiDevice->GetInterface())
				m_p_oMultiDevice->GetInterface()->fn_vChangeRoot();
		}
	}
}

/*===========================================================================
*		Description:	RAZ of all lists
*		Creation date:	
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		test the type of the object
*---------------------------------------------------------------------------
*		Revision date:				 Author:         
*=========================================================================*/
void CPA_World::fn_vReinitListObjects(void)
{
    EDT_ListByDLL	*pListDLL;
	POSITION		pos;

	// Reinit the list of all objects
	m_stListAllDLLs.fn_vReinit();
	m_stListAllObjects.RemoveAll();

	// Reinit the lists by Types
    for (pListDLL = m_lstListByDLL.GetHeadElement(pos); pListDLL;
         pListDLL = m_lstListByDLL.GetNextElement(pos))
        pListDLL->fn_vReinit();
}

/*===========================================================================
*		Description:	RAZ of all lists
*		Creation date:	
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		test the type of the object
*---------------------------------------------------------------------------
*		Revision date:				 Author:         
*=========================================================================*/
void CPA_World::fn_vReinitSortedList(void)
{
    EDT_ListByDLL	*pListDLL;
	POSITION		pos;

	// Reinit the list of all objects
	m_stListAllDLLs.fn_vUpdateSortedList();

	// Reinit the lists by Types
    for (pListDLL = m_lstListByDLL.GetHeadElement(pos); pListDLL;
         pListDLL = m_lstListByDLL.GetNextElement(pos))
        pListDLL->fn_vUpdateSortedList();
}

/*===========================================================================
*		Description:	fill the list from the current hierarchy
*		Creation date:	
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		test the type of the object
*---------------------------------------------------------------------------
*		Revision date:				 Author:         
*=========================================================================*/
void CPA_World::fn_vFillListObjects(CPA_SuperObject *pEdObj)
{
	CPA_SuperObject	*pChild;
	EDT_ListByDLL  *pListDLL;

	// Find objects which type belongs to the Editor
	if ((pEdObj->GetObjectType() != HIE_C_ulSuperObject)&&(!pEdObj->fn_bIsEditProtected()))
	{
		// update the corresponding list
		pListDLL = GetListFromObject(pEdObj);
		pListDLL->fn_vUpdateListObject(pEdObj, E_lum_Insert);
				
		// Update the lists by Type
		m_stListAllDLLs.fn_vUpdateListObject(pEdObj, E_lum_Insert);
	}
	// Fill the list of all objects
	m_stListAllObjects.AddTail(pEdObj);

	// Next level of hierarchy
	pChild = pEdObj->GetSuperObjectFirstChild();
	while (pChild)
	{
		fn_vFillListObjects(pChild);
		pChild = pEdObj->GetSuperObjectNextChild(pChild);
	}
}

//CPA2 Corneliu Babiuc (multiple registration) 02-07-98
/*===========================================================================
*		Description:	Find the list by type corresponding to the object 
*						(the list it must belong to).
*		Creation date:	
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		test the type of the object
*---------------------------------------------------------------------------
*		Revision date:				 Author:         
*       02-07-98					Corneliu Babiuc (pass the list as parameter)
*=========================================================================*/
EDT_ListByDLL * CPA_World::GetListFromObject (CPA_List<EDT_ListByDLL> *p_lstListByDLL, CPA_SuperObject *pEdObj)
{
	EDT_ListByDLL	*pListDLL = NULL;
	POSITION		pos;
	
	// protected childs can't be selected
	if (!pEdObj)
		return NULL;
	
/*	for (pListDLL = m_lstListByDLL.GetHeadElement(pos); pListDLL; 
		 pListDLL = m_lstListByDLL.GetNextElement(pos)) */
	for (pListDLL = p_lstListByDLL->GetHeadElement(pos); pListDLL; 
		 pListDLL = p_lstListByDLL->GetNextElement(pos)) 
//END CPA2 Corneliu Babiuc (multiple registration) 02-07-98
	{
		if (pEdObj->GetObjectDLL() == pListDLL->GetDLL())
			return pListDLL;
	}

	return NULL;
}

//CPA2 Corneliu Babiuc (multiple registration) 02-07-98
/*===========================================================================
*		Description:	Find the lists corresponding to the type of object 
*		Creation date:	
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		test the type of the object
*---------------------------------------------------------------------------
*		Revision date:				 Author:         
*       02-07-98					Corneliu Babiuc (pass the list as parameter)
*=========================================================================*/
EDT_ListByDLL * CPA_World::GetListFromObjectDLL (CPA_List<EDT_ListByDLL> *p_lstListByDLL, CPA_ObjectDLLBase *p_oDLL)
{
	EDT_ListByDLL	*pListDLL = NULL;
	POSITION		pos;
	
/*	for (pListDLL = m_lstListByDLL.GetHeadElement(pos); pListDLL; 
		 pListDLL = m_lstListByDLL.GetNextElement(pos)) */
	for (pListDLL = p_lstListByDLL->GetHeadElement(pos); pListDLL; 
		 pListDLL = p_lstListByDLL->GetNextElement(pos)) 
//END CPA2 Corneliu Babiuc (multiple registration) 02-07-98
	{
		if (p_oDLL == pListDLL->GetDLL())
			return pListDLL;
	}

	return NULL;
}


/*===========================================================================
*		Description:	Update the lists when an object is deleted or inserted
*						in the hierarchy (recursive function)
*		Creation date:	
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		
*---------------------------------------------------------------------------
*		Revision date:             Author:         
*=========================================================================*/
void CPA_World::fn_vUpdateListObjects (CPA_SuperObject *pEdObj, tdeListUpdateMode eType, BOOL bUpdateObject)
{
	CPA_SuperObject		*pChild;
	EDT_ListByDLL		*pListDLL;
	POSITION			pos;

	pListDLL = GetListFromObject(pEdObj);

	// if the type is handled by the Editor
	if (pListDLL)
		pListDLL->fn_vUpdateListObject(pEdObj, eType);
	m_stListAllDLLs.fn_vUpdateListObject(pEdObj, eType);

	// update other lists
	if ((eType == E_lum_Insert)||(eType == E_lum_ReInsert))
		m_stListAllObjects.AddTail(pEdObj);
	else if (eType == E_lum_Delete)
	{
		// update the list of all objects
		pos = m_stListAllObjects.Find(pEdObj, NULL);
		if (pos)
			m_stListAllObjects.RemoveAt(pos);
		// update selection
		fn_vUpdateSelectLists(pEdObj, E_lum_Delete, TRUE);
	}
	// next level of the hierarchy
	pChild = pEdObj->GetSuperObjectFirstChild();
	while (pChild)
	{
		fn_vUpdateListObjects(pChild, eType, bUpdateObject);
		pChild = pEdObj->GetSuperObjectNextChild(pChild);
	}
}



/*===========================================================================
*		Description:	Update select lists when an object is selected or 
*						un-selected
*		Creation date:	
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		
*---------------------------------------------------------------------------
*		Revision date:             Author:         
*=========================================================================*/
void CPA_World::fn_vUpdateSelectLists (CPA_SuperObject *pEdObj, tdeListUpdateMode eType, BOOL bIsSelected)
{
	CPA_SuperObject	 *pChild;
	EDT_ListByDLL	 *pListSelect;

	// update list select
	pListSelect = GetListFromObject(pEdObj);
	if (pListSelect)
		pListSelect->fn_vUpdateListSelect(pEdObj, eType, bIsSelected);
	// update list all types
	m_stListAllDLLs.fn_vUpdateListSelect(pEdObj, eType, bIsSelected);
	
	// if necessary, update lists for the owner
	if (pEdObj->GetSuperObjectOwner())
	{
		pListSelect = GetListFromObject(pEdObj->GetSuperObjectOwner());
		if (pListSelect)
			pListSelect->fn_vUpdateListProtect(pEdObj, eType, bIsSelected);
	}

	// next level of the hierarchy
	pChild = pEdObj->GetSuperObjectFirstChild();
	while (pChild)
	{
		fn_vUpdateSelectLists(pChild, eType, FALSE);
		pChild = pEdObj->GetSuperObjectNextChild(pChild);
	}
}


//CPA2 Corneliu Babiuc (multiple registration) 02-07-98
/*===========================================================================
*		Description:	Update registration lists when an object is added or 
						removed from registration
*		Creation date:	
*		Author:			Corneliu Babiuc
*---------------------------------------------------------------------------
*		
*---------------------------------------------------------------------------
*		Revision date:             Author:         
*=========================================================================*/
void CPA_World::fn_vUpdateRegisterLists (CPA_SuperObject *pEdObj, tdeListUpdateMode eType, BOOL bIsSelected)
{
	CPA_SuperObject	 *pChild;
	EDT_ListByDLL	 *pListSelect;

	// update list select
	pListSelect = GetListFromObject(&m_lstRegisterListByDLL, pEdObj);
	if (pListSelect)
		pListSelect->fn_vUpdateListSelect(pEdObj, eType, bIsSelected);
	// update list all types
	m_stRegisterListAllDLLs.fn_vUpdateListSelect(pEdObj, eType, bIsSelected);
	
	// if necessary, update lists for the owner
	if (pEdObj->GetSuperObjectOwner())
	{
		pListSelect = GetListFromObject(&m_lstRegisterListByDLL, pEdObj->GetSuperObjectOwner());
		if (pListSelect)
			pListSelect->fn_vUpdateListProtect(pEdObj, eType, bIsSelected);
	}

	// next level of the hierarchy
	pChild = pEdObj->GetSuperObjectFirstChild();
	while (pChild)
	{
		fn_vUpdateRegisterLists(pChild, eType, FALSE);
		pChild = pEdObj->GetSuperObjectNextChild(pChild);
	}
}
//END CPA2 Corneliu Babiuc (multiple registration) 02-07-98

/*===========================================================================
*		Description:	insert super-object in a new world without updating object
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_World::fn_vInsertSuperObjectInNewWorld (CPA_SuperObject *pEdObj, CPA_SuperObject *pParent, BOOL bUpdateDrawing)
{
	// insert object in hierarchy
	pEdObj->Isolate();
	pParent->AddTail(pEdObj);
	// update the corresponding list
	fn_vUpdateListObjects(pEdObj, E_lum_Insert, FALSE);
	// update validity
	pEdObj->fn_vUpdateValidity(TRUE);
	// update absolute position
	if ((m_p_oMultiDevice)&&(m_p_oMultiDevice->GetInterface()))
	{
		if (bUpdateDrawing)
			m_p_oMultiDevice->GetInterface()->fn_vUpdateAll(E_mc_UpdateAll);
	}
}

/*===========================================================================
*		Description:	delete super-object in new world without updating object
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_World::fn_vDeleteSuperObjectInNewWorld (CPA_SuperObject *pEdObj, BOOL bUpdateDrawing)
{
	// remove object from hierarchy
	pEdObj->Isolate();
	// update all the lists
	fn_vUpdateListObjects(pEdObj, E_lum_Delete, FALSE);
	// update validity
	pEdObj->fn_vUpdateValidity(FALSE);
	// update absolute position
	if ((m_p_oMultiDevice)&&(m_p_oMultiDevice->GetInterface()))
	{
		if (bUpdateDrawing)
			m_p_oMultiDevice->GetInterface()->fn_vUpdateAll(E_mc_UpdateAll);
	}
}

#endif //ACTIVE_EDITOR