/*=========================================================================
*
* EvtEditor.cpp :  Editor : Implementation file.
*
*
* Version			1.0
* Creation date
* Revision date
*
* Shaitan
*=======================================================================*/
#include "stdafx.h"

#include "itf/customid.h"
#ifdef ACTIVE_EDITOR
#include "acp_base.h"

#include <direct.h>

#include "geo.h"
#include "gli.h"
#include "tex.h"

#include "itf/CPAInter.hpp"

#include "itf/camdllb.hpp"
#include "itf/CPAProj.hpp"

#include "itf/CPAHieEd.hpp"
#include "itf/CPAMWorl.hpp"
#include "itf/DevMul3D.hpp"

#include "itf/CPAdlang.hpp"

#include "itf/StdDLLID.h"
#include "itf/cohemngr.hpp"

//SHATEMP
/*
#include "X:\cpa\tempgrp\GLI\PC\light_st.h"
#include "X:\cpa\tempgrp\GLI\PC\PvObj_st.h"
#include "X:\cpa\tempgrp\GLI\PC\InterfLL.h"
#include "X:\cpa\tempgrp\GLI\PC\linear.h"
*/

#include "X:\cpa\tempgrp\GLIGLOU\MULTIDRV\inc\light_st.h"
#include "X:\cpa\tempgrp\GLIGLOU\MULTIDRV\inc\PvObj_st.h"
#include "X:\cpa\tempgrp\GLIGLOU\MULTIDRV\inc\linear.h"


#include "x:\cpa\main\inc\_EditID.h"
#include "GAM/Input.h"

// --------------------------- popup ---------------------------------------
#define C_ui_CancelDrawingAction	12
#define C_ui_NormalDrawingAction	15
#define C_ui_GridedDrawingAction	16
#define C_ui_WiredDrawingAction		17
#define C_ui_ShowAxisAction         18
#define C_ui_ShowBoundingV          19
#define C_ui_ScaleAction			24
#define C_ui_ReScaleAction			25
#define C_ui_ComputeCentersAction	26

// --------------------------- submenu ---------------------------------------
#define C_ui_ComputeBV			31
#define C_ui_CoherenceMngr		32
#define C_ui_Option				33
#define C_ui_DeltaSelect		40
#define C_ui_FullSelect			41
#define C_ui_UnselectAll		42
#define C_ui_Textured			43
#define C_ui_Grided				44
#define C_ui_Wired				45
#define C_ui_World				46
#define C_ui_CollisionMap		61
#define C_ui_Visible			47
#define C_ui_Current			48
#define C_ui_NoBV				49
#define C_ui_SectorsBV			50
#define C_ui_ActorsBV			51
#define C_ui_ObjectsBV			52
#define C_ui_NoAxis				53
#define C_ui_DownRightAxis		54
#define C_ui_DownLeftAxis		55
#define C_ui_NoCenter			56
#define C_ui_MainCenters		57
#define C_ui_AllCenters			58
#define C_ui_BKColors			59
#define C_ui_SaveDisplay		60
// Begin Silviu Simen Select by sector and type
#define C_ui_SelectSectorType	61
// End Silviu Simen Select by sector and type

// --------------------------- colors ---------------------------------------
#define C_lc_SelectColor	E_lc_Red
#define C_lc_ChildColor		E_lc_Blue
#define C_lc_ParentColor	E_lc_Green
#define C_lc_BrotherColor	E_lc_Yellow
#define	C_lc_ShowColor		E_lc_Violet
#define C_lc_NoColor		E_lc_NoColor

#define C_lNbConst			0.1

#define C_szTipOfDayIniFile	"TipOfDay.ini"
#define C_szAstucesIniFile	"Astuces.ini"


//***********************************************
//*** DR (20/01/98) *****************************
extern HMODULE g_hWawModule;
//*** End DR ************************************
//***********************************************


//#################################################################################
// INITS
//#################################################################################

/*===========================================================================
	Constructor 
=========================================================================*/
CPA_Interface::CPA_Interface (void)
{
	CString csFileName;
	
	// init parameters
	m_p_oMultiDevice = NULL;
	m_p_oMainWorld = NULL;
	// init models
	m_pListAllModels = NULL;
	m_pCurrentModel = NULL;
	// init pyramid selection
	m_bSelectionFrameVisible=FALSE;
	m_bSelectionFrameCreating=FALSE;
	m_bPyramidDepthChanging=FALSE;

	//init object move parameters
	m_bLastMovePlaneRemembered = FALSE;
	m_bModeIsObjectMouseMove = FALSE;
	fn_vSetMouseMovePlane(E_mmp_Standard);

	MTH3D_M_vSetVectorElements(&m_stMouseXAxe, 1.0, 0.0, 0.0);
	MTH3D_M_vSetVectorElements(&m_stMouseYAxe, 0.0, 1.0, 0.0);
	MTH3D_M_vNullVector(&m_stLastMoveXAxe);
	MTH3D_M_vNullVector(&m_stLastMoveYAxe);

	m_dfZNearSelectionFrame=0.1;
	m_dfZFarSelectionFrame=20.0;

	// init editor
	m_p_oEditor = new CPA_HierarchyEditor();
	m_p_oEditor = NULL;
	// init specific interface
	m_oSpecificInterface.SetInterface(this);

	// for rename during loading
	m_bIsLoadingWorld = FALSE;
	m_lNbObjectsRenamed = 0;	
	// user preferences
	m_lNbAuthorized = 0;
	m_lNbProhibited = 0;
	m_lNbUsers = 0;
	// user prefix
	m_csUserPrefix.Empty();
	m_bUseUserPreferences = TRUE;
	// Language
	m_csCurrentLanguage.Empty();

	// Put on Ground
	m_bPyramidMode = FALSE;

	// Selection
	m_bDeltaSelect = FALSE;
	m_bFullSelect = FALSE;
	m_bIgnoreFlags = FALSE;
	m_bLockSelection = FALSE;
	m_bFixedDepth = FALSE;
	m_bRealTime = FALSE;
	m_fPyramidalDepth = 1.f;
	m_fCameraTargetDepth = 1.f;

	// display parameters
	m_iShowCenter = 0;
	m_bLoaded = FALSE;
	m_bScaleObject= FALSE;
	m_eBVMode = E_bv_None;

	// status bar info
	m_eStatusBarMode = E_sb_InstanceInfo;
	m_bDisplayDistance = FALSE;

	// mouse swap
	m_bAutomaticSwap = TRUE;
	m_bCursorInFirstScreen = TRUE;
	m_eForceSwap = eSwapRight;

	// tip of day
	m_bDisplayTipOfDay = TRUE;
}


/*===========================================================================
	Destructor 
=========================================================================*/
CPA_Interface::~CPA_Interface (void)
{
	// models
	while (!m_stListOfModelsByType.IsEmpty())
		delete m_stListOfModelsByType.RemoveHead();
}


/*===========================================================================
	Create
=========================================================================*/
void CPA_Interface::Create (void)
{
	// Bottom Frame Window
	m_pModelFrame = new CSplitFrame;
	m_pModelFrame->CreateBase("INSERT", 2, 3, m_p_oMainWorld);
    m_pModelFrame->m_iInitWidth = 0;
    m_pModelFrame->m_iInitHeight = 120;
    m_pModelFrame->mfn_vEnableCaption(FALSE);

	// init hierarchy editor
	m_p_oEditor->Create();

	// init select mode
	m_pComboSelectMode = (CComboBox *) GetFrameBase()->m_oGeneralDialogBar.GetDlgItem(CPA_IDCB_SELECTMODE);
	m_csSelectMode = "All Types";
	m_bLinkMode = FALSE;
	
	// init dialog select
	m_oDialogSelect.m_bDoDialog = FALSE;
	// init specific interface
	m_oSpecificInterface.fn_vSpecificInit();

	// init map state
	m_bInitialState = FALSE;
	// init camera mode
	m_bAutoTarget = FALSE;
	m_bAutoZoom = FALSE;

	// init selection & move
	m_bConsX = FALSE;
	m_bConsY = FALSE;
	m_bConsZ = FALSE;
	m_bPyramidMode = FALSE;

	// init camera move mode  
	m_bMoveCamera = FALSE; 

}

/*===========================================================================
	Init
=========================================================================*/
void CPA_Interface::Init (void)
{
	// Dialog Insert
	m_pDialogInsert = new CPA_DialogInsert;
	m_pDialogInsert->fn_vInitDialog(this, m_pModelFrame);
	m_pModelFrame->SetActiveView(m_pDialogInsert, TRUE);
	// Models
	if (!m_pListAllModels)
	{
		m_stListAllBitmaps.m_fn_vCreate(C_cVariableSize, 32, 32);
		m_pListAllModels = new EDT_ModelsByType("All Types", NULL, m_pDialogInsert, &m_stListAllBitmaps);
		fn_vInitListOfModelsByType(GetMainWorld()->GetListOfObjectDLLBase());
	}
}

/*===========================================================================
	Static Init
=========================================================================*/
void CPA_Interface::StaticInit (void)
{
	// init models
	SCR_fn_v_RdL0_RegisterCallback("Edit-ListOfModels", CallBackLoadModelList, SCR_CRC_c_RdL0_ForSection);
}

//#################################################################################
// GET FUNCTIONS
//#################################################################################

/*===========================================================================
*		Description:	Main Frame (for dialog bar & menus)
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
CPA_EditorBase	* CPA_Interface::GetEditor (void)
{ 
	return m_p_oEditor; 
}

/*===========================================================================
*		Description:	Main Frame (for dialog bar & menus)
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
FRMBaseMenu	* CPA_Interface::GetFrameBase (void)
{ 
	return GetMultiDevice()->GetParentFrame(); 
}

/*===========================================================================
*		Description:	Current World (for lists)
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
CPA_World * CPA_Interface::GetCurrentWorld (void)
{ 
	return GetMultiDevice3D()->GetWorld(); 
}


//#################################################################################
// SET FUNCTIONS
//#################################################################################

/*===========================================================================
*		Description:	set main world and update editor
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::SetMainWorld (CPA_MainWorld *p_oMainWorld)
{
	m_p_oMainWorld = p_oMainWorld;
	m_p_oEditor->SetMainWorld(m_p_oMainWorld);
}


/*===========================================================================
*		Description:	Set multidevice and dispatch message
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::SetMultiDevice	(DEV_MultiDevice *p_oMultiDevice)
{
	CPA_DLLBase *p_oDLL;
	POSITION	pos;

	// set new device
	if (m_p_oMultiDevice)
	{
		m_p_oMultiDevice->Disactivate();
	}

	m_p_oMultiDevice = p_oMultiDevice;
	p_oMultiDevice->Activate();


	if (m_p_oMultiDevice)
		m_p_oMultiDevice->SetInterface(this);

	// specific update
	m_oSpecificInterface.fn_vSpecificUpdate(TRUE);

	// tell hierarchy editor
	m_p_oEditor->fn_vOnChangeDevice();

	if (!m_p_oMainWorld)
		return;

	// tell all Object DLLs
	for (p_oDLL = m_p_oMainWorld->GetListOfObjectDLLBase()->GetHeadElement(pos); p_oDLL;
		 p_oDLL = m_p_oMainWorld->GetListOfObjectDLLBase()->GetNextElement(pos))
		p_oDLL->fn_vOnChangeDevice();

	// tell all Tool DLLs
	for (p_oDLL = m_p_oMainWorld->GetListOfToolDLLBase()->GetHeadElement(pos); p_oDLL;
		 p_oDLL = m_p_oMainWorld->GetListOfToolDLLBase()->GetNextElement(pos))
		p_oDLL->fn_vOnChangeDevice();
}

/*===========================================================================
*		Description:	dispatch message when world changes
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vChangeWorld (void)
{
	CPA_DLLBase *p_oDLL;
	POSITION	pos;

	// specific update
	m_oSpecificInterface.fn_vSpecificUpdate(TRUE);

	// tell hierarchy editor
	m_p_oEditor->fn_vOnChangeWorld();

	if (!m_p_oMainWorld)
		return;

	// tell all Object DLLs
	for (p_oDLL = m_p_oMainWorld->GetListOfObjectDLLBase()->GetHeadElement(pos); p_oDLL;
		 p_oDLL = m_p_oMainWorld->GetListOfObjectDLLBase()->GetNextElement(pos))
		p_oDLL->fn_vOnChangeWorld();

	// tell all Tool DLLs
	for (p_oDLL = m_p_oMainWorld->GetListOfToolDLLBase()->GetHeadElement(pos); p_oDLL;
		 p_oDLL = m_p_oMainWorld->GetListOfToolDLLBase()->GetNextElement(pos))
		p_oDLL->fn_vOnChangeWorld();
}

/*===========================================================================
*		Description:	dispatch message when root changes
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vChangeRoot (void)
{
	CPA_DLLBase			*p_oDLL;
	POSITION			pos;

	// specific update
	m_oSpecificInterface.fn_vSpecificUpdate(TRUE);

	// tell hierarchy editor
	m_p_oEditor->fn_vOnChangeRoot();

	if (!m_p_oMainWorld)
		return;

	// tell all Object DLLs
	for (p_oDLL = m_p_oMainWorld->GetListOfObjectDLLBase()->GetHeadElement(pos); p_oDLL;
		 p_oDLL = m_p_oMainWorld->GetListOfObjectDLLBase()->GetNextElement(pos))
		p_oDLL->fn_vOnChangeRoot();

	// tell all Tool DLLs
	for (p_oDLL = m_p_oMainWorld->GetListOfToolDLLBase()->GetHeadElement(pos); p_oDLL;
		 p_oDLL = m_p_oMainWorld->GetListOfToolDLLBase()->GetNextElement(pos))
		p_oDLL->fn_vOnChangeRoot();
}


/*===========================================================================
*		Description:	Before Editor
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                           Author:
*=========================================================================*/
void CPA_Interface::fn_vBeforeEditor (void)
{
	CString csFileName;
	
	/* Init sinus effect and global fog */
	GLI_vInitWaterplaneModule();
	GLI_cGlobalFogIsOn = 0;

	// init user parameters
	fn_vInitUserPrefix();
	GetSpecificInterface()->fn_vInitUserStatus();
	// init scripts
	csFileName = M_GetMainApp()->m_csEngineDataPath + "\\ModifLst.txt";
	SCR_fn_v_SvL1_SetModificationFileName((char*)(LPCSTR)csFileName);

	//init Language
	fn_vInitLanguage();

	//*********************************************
	//*** DR (20/01/98) : Init Watch Window  ******
	if( g_hWawModule != NULL )
		{
		void (*WawInitFunction)(void) = (void (__cdecl*)(void))GetProcAddress( g_hWawModule, "WAW_fn_vInitWatchWindow" );
		if( WawInitFunction != NULL ) WawInitFunction();
		else AfxMessageBox("Init function has not been found in DLL (WAW module)");
		}
	//*** End DR (20/01/98) ***********************
	//*********************************************
}

/*===========================================================================
*		Description:	InitLanguage
*		Creation date:
*		Author:			Xavier Billault
*---------------------------------------------------------------------------
*		Revision date:                           Author:
*=========================================================================*/
void CPA_Interface::fn_vInitLanguage(void)
{
	if (m_csCurrentLanguage.IsEmpty())
	{
		// user prefix
		if (m_bUseUserPreferences)
		{
			char	szLanguage[256];

			CString csFileName = M_GetMainApp()->m_csEditorDataPath + C_szInterfaceIniFile;
			GetPrivateProfileString ("User", "User Language", "", szLanguage, 255, (char*)(LPCSTR)csFileName);
			m_csCurrentLanguage = szLanguage;
		}
		
		// if no preference, use dialog
		if (m_csCurrentLanguage.IsEmpty())
		{
			CStringList	cslLangList;

			CStdioFile	cfFile;
			CString			csFile;

			csFile=M_GetMainApp()->m_csEditorDataPath + "\\Language.txt";

			if(cfFile.Open(csFile,CFile::modeRead))
			{
				CString	csLanguage;

				while(cfFile.ReadString(csLanguage))
					cslLangList.AddTail(csLanguage);

				cfFile.Close();
			}
			else
			{
				AfxMessageBox("Can't open "+csFile+"\nUse Default Language !!!");

				cslLangList.AddTail("English");
				cslLangList.AddTail("French");
			}

			CPA_DialogLanguage	LangBox(this,&cslLangList);
			if(LangBox.DoModal()==IDOK)
				m_csCurrentLanguage=LangBox.m_csLanguage;
			else
				m_csCurrentLanguage="Français";
		}
	}
}

/*===========================================================================
*		Description:	SaveLanguage
*		Creation date:
*		Author:			Xavier Billault
*---------------------------------------------------------------------------
*		Revision date:                           Author:
*=========================================================================*/
void CPA_Interface::fn_vSaveLanguage(CString csLanguage)
{
	CString	csFileName;
	BOOL	bRes;
	
	// preference file
	csFileName = M_GetMainApp()->m_csEditorDataPath + C_szInterfaceIniFile;
	// try to write preference
	bRes = WritePrivateProfileString ("User", "User Language", (char*)(LPCSTR) csLanguage, (char*)(LPCSTR)csFileName);
	// warning if problem
	if (!bRes)
		M_GetMainWnd()->UpdateStatus("Hierarchy Editor cannot save your preferences. CPAPref.ini may have a ReadOnly status ?", C_STATUSPANE_INFOS, C_STATUS_WARNING);
	else
		M_GetMainWnd()->UpdateStatus("Preferences saved", C_STATUSPANE_INFOS, C_STATUS_NORMAL);
}

/*===========================================================================
*		Description:	Before Editor
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                           Author:
*=========================================================================*/
void CPA_Interface::fn_vUpdateEditor (void)
{
	// for objects renamed during loading
	M_GetMainWnd()->UpdateStatus((char *) (LPCSTR) m_p_oEditor->GetLoadingMessage(), C_STATUSPANE_INFOS, m_p_oEditor->GetLoadingStatus());
	// update frame
	GetSpecificInterface()->fn_vSetFrameTitle();
}

/*===========================================================================
*		Description:	Update all dialogs
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                           Author:
*=========================================================================*/
void CPA_Interface::fn_vUpdateAll (tdeModeChange eMode)
{
	if ((!GetMultiDevice())||(!GetCurrentWorld()))
		return;
	
	// update frame and dialogbar
	switch (eMode)
	{
		case E_mc_JustDraw:
		case E_mc_UpdateSelection:
		case E_mc_UpdateDialog:
			break;

		case E_mc_UpdateAll:
			// update selection
			if (!fn_bIsSelectionValid())
				fn_vCancelCurrentSelection(FALSE);
			// update display mode
			GetSpecificInterface()->fn_vInitCurrentSector();

		default:
			break;
	}

	// call editor update
	m_p_oMainWorld->GetCurrentEditor()->fn_vUpdateEditor(eMode);

	// redraw the world
	fn_vUpdatePositions();
	GetMultiDevice()->DrawEditorObject();
}


/*===========================================================================
*		Description:	update global matrix
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                           Author:
*=========================================================================*/
void CPA_Interface::fn_vUpdatePositions (void)
{
	HIE_fn_vInvalidateAllGlobalMatrices();
	if (GetMultiDevice3D()->GetEngineWorld())
		HIE_fn_vRefreshHierarchy(GetMultiDevice3D()->GetEngineWorld());
}

/*===========================================================================
*		Description:	Check if current selection match the Select Mode
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                Author:
*=========================================================================*/
BOOL CPA_Interface::fn_bIsSelectionValid (void)
{
	// Mode "AllType" -> any selection is valid
	if (m_csSelectMode == "All Types")
		return TRUE;

	// find the current select type
	if (m_csSelectMode == GetTypeSelected())
		return TRUE;

	// selection is not valid
	return FALSE;
}


/*===========================================================================
*		Description:	Find the type of selected objects (multi-type -> 0)
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                Author:
*=========================================================================*/
CString CPA_Interface::GetTypeSelected (void)
{
	CPA_SuperObject *pElem;
	POSITION		pos;
	CString			csSelectType;

	csSelectType = "All Types";

	for (pElem = GetCurrentWorld()->GetListSelected()->GetHeadElement(pos); pElem;
		 pElem = GetCurrentWorld()->GetListSelected()->GetNextElement(pos))
	{
		// first time => init select type
		if (csSelectType == "All Types")
			csSelectType = pElem->GetRealTypeName();
		// next times => compare type name
		else if (csSelectType != pElem->GetRealTypeName())
			return ("All Types");
	}

	return csSelectType;
}

/*===========================================================================
*		Description:	Find the type of selected objects (multi-type -> 0)
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                Author:
*=========================================================================*/
void CPA_Interface::fn_vCancelAllModes (void)
{
	// reinit editor
	m_p_oEditor->fn_vCancelAllModes();
	// reinit dialogs
	m_oDialogSelect.m_bDoDialog = FALSE;
}

/*===========================================================================
*		Description:	set all drawing flags to normal
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                Author:
*=========================================================================*/
void CPA_Interface::fn_vCancelAllDrawingFlags (void)
{
	SetDrawingFlags(GetCurrentWorld()->GetRoot(), E_df_Normal);
}

//#################################################################################
// SELECT MODE
//#################################################################################

/*===========================================================================
*		Description:	Set the select mode and update drawing
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                Author:
*=========================================================================*/
void CPA_Interface::SetSelectMode (CString csSelectMode)
{
	m_csSelectMode = csSelectMode;
	fn_vChangeSelectMode(csSelectMode);
}

/*===========================================================================
*		Description:	init combo for select mode
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vInitSelectMode	(void)
{
	EDT_ListByDLL	*pListDLL;
	EDT_ListByType	*pListType;
	POSITION		pos, pos1;
	int				iInd;

	// init the list
	m_pComboSelectMode->ResetContent();
	m_pComboSelectMode->AddString("All Types");

    // check lists by type to find the available DLLs
	for (pListDLL = GetCurrentWorld()->GetListOfListByDLL()->GetHeadElement(pos); pListDLL; 
		 pListDLL = GetCurrentWorld()->GetListOfListByDLL()->GetNextElement(pos))
	{
		for (pListType = pListDLL->m_stListOfListByType.GetHeadElement(pos1); pListType;
			 pListType = pListDLL->m_stListOfListByType.GetNextElement(pos1))
			m_pComboSelectMode->AddString(pListType->GetTypeName());
	}

	// set current selection
	iInd = m_pComboSelectMode->FindStringExact(-1, m_csSelectMode);
	m_pComboSelectMode->SetCurSel(iInd);

	// if necessary, update link mode
	if (m_bLinkMode)
		fn_vUpdateLink(m_csSelectMode);
}

/*===========================================================================
*		Description:	update link mode 
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vOnChangeLinkMode (void)
{
	char szCurrentMode[30];
	
	// if necessary, update drawing
	if (m_bLinkMode)
	{
		m_pComboSelectMode->GetLBText(m_pComboSelectMode->GetCurSel(), szCurrentMode);
		fn_vUpdateLink(szCurrentMode);
	}
	else
		m_pComboSelectMode->EnableWindow(TRUE);
}


/*===========================================================================
*		Description:	update select mode when selection changes in combo
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vOnChangeSelectMode (void)
{
	char szText[256];

	// update select mode
	m_pComboSelectMode->GetLBText(m_pComboSelectMode->GetCurSel(), szText);
	SetSelectMode(szText);
	// update drawing
	fn_vUpdateAll(E_mc_UpdateAll);
}

/*===========================================================================
*		Description:	update combo when select mode changes
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vChangeSelectMode (CString csSelectMode)
{
	EDT_ListByType *pListType;
	CString			csCurrentMode;
	int				iInd;
	
	// get the new select mode
	pListType = GetListWithTypeName(csSelectMode);
	if (pListType)
		csCurrentMode = csSelectMode;
	else
		csCurrentMode = "All Types";
	// set combo selection
	iInd = m_pComboSelectMode->FindStringExact(-1, csCurrentMode);
	m_pComboSelectMode->SetCurSel(iInd);
	// if necessary, update link
	if (m_bLinkMode)
		fn_vUpdateLink(csCurrentMode);
}


/*===========================================================================
*		Description:	init combo for select mode
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vUpdateLink	(CString csCurrentMode)
{
	CString			csNewMode;

	// only in link mode
	if (!m_bLinkMode)
		return;
	
	// editor
	m_p_oEditor->fn_vUpdateLink(csCurrentMode);

	// if necessary, update selectmode
	m_pComboSelectMode->GetLBText(m_pComboSelectMode->GetCurSel(), csNewMode);
	if (csNewMode != csCurrentMode)
	{
		// update mode
		SetSelectMode(csNewMode);
		// update all
		fn_vUpdateAll(E_mc_UpdateAll);
	}
}


//#################################################################################
// SELECTION
//#################################################################################

/*===========================================================================
*		Description:	Add a new object in the list of selection
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
void CPA_Interface::fn_vAddSelectedObject (CPA_SuperObject *pNewObj, BOOL bUpdateDisplay)
{
	CPA_List<CPA_SuperObject> stListRemoved;
	CPA_SuperObject			  *pElem;
	POSITION				  pos;

	// if the selection is locked, cancel
	if (GetLockSelection()) 
		return;

	// check if there is a world
	if (!GetCurrentWorld() || !GetCurrentWorld()->GetRoot())
		return;

	if (!pNewObj)
		return;

	// check all the elements in the list
	for (pElem = GetCurrentWorld()->GetListSelected()->GetHeadElement(pos); pElem;
		 pElem = GetCurrentWorld()->GetListSelected()->GetNextElement(pos))
	{
		// if this is a child of pNewObj, remove it from the list
		if (pElem->fn_bIsUnderObject(pNewObj))
			stListRemoved.AddTail(pElem);
	}
	// remove redondant elements
	for (pElem = stListRemoved.GetHeadElement(pos); pElem;
		 pElem = stListRemoved.GetNextElement(pos))
	{
		// remove it from the selected objects
		GetCurrentWorld()->fn_vUpdateSelectLists(pElem, E_lum_Delete, TRUE);
		// update color and tell DLLs
		fn_vSetLocalColor(pElem, E_lm_ShowNormal);
		fn_vSendMessageSelect(pElem, C_EDTUndo);
	}
	// add the new object in the list
	GetCurrentWorld()->fn_vUpdateSelectLists(pNewObj, E_lum_Insert, TRUE);
	fn_vSetLocalColor(pNewObj, E_lm_ShowSelected);

	// tell DLLs
	fn_vSendMessageSelect(pNewObj, C_EDTDo);

	// target & zoom
	if (GetCurrentWorld()->GetCountSelected() == 1)
	{
		if ((m_bAutoTarget) || (m_bAutoZoom))
			fn_vCenterOnObject(GetCurrentWorld()->GetSingleSelection(), m_bAutoZoom, m_bAutoTarget);
	}

	// update all
	if (bUpdateDisplay)
		fn_vUpdateAll(E_mc_UpdateSelection);
}

/*===========================================================================
*		Description:	Remove an object from the list of selection
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
void CPA_Interface::fn_vRemoveSelectedObject (CPA_SuperObject *pEdObj, BOOL bUpdateDisplay)
{
	POSITION		 pos;

	// if the selection is locked, cancel
	if (GetLockSelection()) 
		return;

	// check if there is a world
	if (!GetCurrentWorld() || !GetCurrentWorld()->GetRoot())
		return;

	// remove selected object from the list
	pos = GetCurrentWorld()->GetListSelected()->Find(pEdObj);
	if (pos)
	{
		GetCurrentWorld()->fn_vUpdateSelectLists(pEdObj, E_lum_Delete, TRUE);
		// update selection
		fn_vSetLocalColor(pEdObj, E_lm_ShowNormal);
		// tell DLLs
		fn_vSendMessageSelect(pEdObj, C_EDTUndo);
	}
	// update all
	if (bUpdateDisplay)
		fn_vUpdateAll(E_mc_UpdateSelection);
}


/*===========================================================================
*		Description:	Cancel current selection
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
void CPA_Interface::fn_vCancelCurrentSelection (BOOL bUpdateDisplay)
{
	EDT_ListByDLL	 *pListSelect;
	CPA_SuperObject  *pElem;
	POSITION		 pos;

	// if the selection is locked, cancel
	if (GetLockSelection()) 
		return;

	// check if there is a world
	if (!GetCurrentWorld() || !GetCurrentWorld()->GetRoot())
		return;

	// cancel engine selection
	fn_vSetLocalColor(GetCurrentWorld()->GetRoot(), E_lm_ShowNormal);
	// check all the elements in the list
	while (GetCurrentWorld()->GetListSelected()->GetCount() > 0)
	{
		pElem = GetCurrentWorld()->GetListSelected()->RemoveTail();
		// tell DLLs
		fn_vSendMessageSelect(pElem, C_EDTUndo);
	}
	// cancel Editor selection
	GetCurrentWorld()->GetListSelected()->RemoveAll();
	GetCurrentWorld()->GetListAllDLLs()->m_stListConcerned.RemoveAll();
	// cancel SelectByType
	for (pListSelect = GetCurrentWorld()->GetListOfListByDLL()->GetHeadElement(pos); pListSelect;
		 pListSelect = GetCurrentWorld()->GetListOfListByDLL()->GetNextElement(pos))
	{
		pListSelect->m_stListConcerned.RemoveAll();
		pListSelect->m_stListSelected.RemoveAll();
		pListSelect->m_stListProtectSelected.RemoveAll();
		pListSelect->m_stListProtectConcerned.RemoveAll();
	}
	// disable edit dialog
	if (bUpdateDisplay)
		fn_vUpdateAll(E_mc_UpdateSelection);
}


/*===========================================================================
*		Description:	Select object corresponding to the choice in the list
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL CPA_Interface::fn_bSelectObject (CPA_SuperObject *pSelectedObject, BOOL bCenter, BOOL bCheck)
{
	int	iInd = 0;
	
	// if the selection is locked, cancel
	if (GetLockSelection()) 
		return FALSE;

	// check if there is a world
	if (!GetCurrentWorld() || !GetCurrentWorld()->GetRoot())
		return FALSE;

	// cancel the current selection
	fn_vCancelCurrentSelection(FALSE);
	
	// find the object corresponding to the choice in the listbox
	if (!pSelectedObject)
		return FALSE;
	
	// ask for permission and select object
	if ((!bCheck)||(fn_bCanSelect(pSelectedObject) == C_Accept))
		fn_vAddSelectedObject(pSelectedObject, FALSE);
	else
		return FALSE;
	
	// if necessary, center and zoom object on the screen
	if (bCenter)
	{ 
		if (m_bAutoTarget)
			fn_vZoomOnObject(pSelectedObject);
		else
			fn_vCenterOnObject(pSelectedObject, TRUE, FALSE);
	}
	
	// redraw the world
	fn_vUpdateAll(E_mc_UpdateSelection);
	
	return TRUE;
}


/*===========================================================================
*		Description:	Check if chosen object can be selected in 3D view
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
tdeTypeAnswer CPA_Interface::fn_bCanSelect (CPA_SuperObject *pEdObj, ACP_tdxIndex xIndex, HIE_tdstPickInfo *pPicking)
{
	CPA_ObjectDLLBase	*p_oDLL, *p_oOwnerDLL;
	tdeTypeAnswer		eAnswer = C_Accept;
	tdeTypeAnswer		eOwnerAnswer = C_Accept;
	tdeTypeAnswer		eEditorAnswer = C_Accept;
	CPA_DLLBase			*pCurrentEditor;

	// No object => no selection
	if (!pEdObj)
		return C_Refuse;
	
	// selection must be valid
	if ((m_csSelectMode != "All Types")&&(pEdObj->GetRealTypeName() != m_csSelectMode))
		return C_Refuse;

	// non editable childs can't be selected
	if (pEdObj->fn_bIsEditProtected())
		return C_Refuse;

	// drawing flag
	if ((!fn_bIgnoreFlags())&&(pEdObj->GetDrawingFlag() != E_df_Normal)&&(pEdObj->GetDrawingFlag() != E_df_BoundingV)) 
		return C_Refuse;

	p_oDLL = pEdObj->GetObjectDLL();

	// ask current editor permission
	if (!m_p_oEditor->fn_bIsCurrentEditor())
	{
		pCurrentEditor = (CPA_DLLBase *)m_p_oMainWorld->GetCurrentEditor();
		eEditorAnswer = pCurrentEditor->fn_bAcceptSelect(pEdObj, xIndex, pPicking, C_AsCurrentEditor);
		if (eEditorAnswer == C_Refuse)
			return C_Refuse;
	}
	// ask world permission
	if (!GetCurrentWorld()->fn_bAcceptSelect(p_oDLL))
		return C_Refuse;
	// ask DLL permission
	if (p_oDLL)
	{
		eAnswer = p_oDLL->fn_bAcceptSelect(pEdObj, xIndex, pPicking, C_AsConcernedDLL);
		if (eAnswer == C_Refuse)
			return C_Refuse;
	}
	// if necessary, ask owner permission
	if (pEdObj->GetSuperObjectOwner())
	{
		p_oOwnerDLL = pEdObj->GetSuperObjectOwner()->GetObjectDLL();
		if (p_oOwnerDLL)
		{
			eOwnerAnswer = p_oOwnerDLL->fn_bAcceptSelect(pEdObj, xIndex, pPicking, C_AsChildOwner);
			if (eOwnerAnswer == C_Refuse)
				return C_Refuse;
		}
	}

	// accept or next ?
	if ((eAnswer == C_Accept)&&(eOwnerAnswer == C_Accept)&&(eEditorAnswer == C_Accept))
		return C_Accept;
	else
		return C_WantNext;
}


/*===========================================================================
*		Description:	update colors for dialog selection
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
void CPA_Interface::fn_vUpdateSelection (CPA_SuperObject *pSelectedObject, tdeSelectMode eMode)
{
	CPA_SuperObject *pElem;
	POSITION		pos;

	// there must be a valid world
	if ((!GetMultiDevice())||(!GetCurrentWorld()))
		return;

	// cancel current drawing
	fn_vSetLocalColor(GetCurrentWorld()->GetRoot(), E_lm_ShowNormal);
	// parent mode => draw dialog selection
	if (((eMode == E_sm_SelectParent)||(eMode == E_sm_SelectPFather))&&(pSelectedObject))
		fn_vSetLocalColor(pSelectedObject, E_lm_ShowParent);
	// draw current selection
	for (pElem = GetCurrentWorld()->GetListSelected()->GetHeadElement(pos); pElem;
		 pElem = GetCurrentWorld()->GetListSelected()->GetNextElement(pos))
		fn_vSetLocalColor(pElem, E_lm_ShowSelected);
	// select mode => draw new selection
	if ((eMode != E_sm_SelectParent)&&(eMode != E_sm_SelectPFather)&&(pSelectedObject))
		fn_vSetLocalColor(pSelectedObject, E_lm_ShowOnly);
	// update drawing
	fn_vUpdateAll(E_mc_JustDraw);
}

/*===========================================================================
*		Description:	set colors for selection
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
void CPA_Interface::fn_vSetLocalColor (CPA_SuperObject *pEdObj, tdeLightMode eMode)
{
	CPA_SuperObject	*pChild;
	tdeLocalColor	eCurrent;
	tdeLightMode	eChild;

	// find color and childs mode corresponding to current mode
	switch (eMode)
	{
		case E_lm_ShowSelected:
			eCurrent = C_lc_SelectColor;
			eChild = E_lm_ShowChild;
			break;
		case E_lm_ShowChild:
			eCurrent = C_lc_ChildColor;
			eChild = eMode;
			break;
		case E_lm_ShowParent:
			eCurrent = C_lc_ParentColor;
			eChild = E_lm_ShowBrother;
			break;
		case E_lm_ShowBrother:
			eCurrent = C_lc_BrotherColor;
			eChild = E_lm_ShowNormal;
			break;
		case E_lm_ShowOnly:
			eCurrent = C_lc_ShowColor;
			eChild = eMode;
			break;
		default:
			eCurrent = C_lc_NoColor;
			eChild = E_lm_ShowNormal;
			break;
	}

	// set current super-object color
	pEdObj->SetLocalColor(eCurrent);
	// set all childs colors
	for (pChild = pEdObj->GetSuperObjectFirstChild(); pChild;
		 pChild = pEdObj->GetSuperObjectNextChild(pChild))
	{
		// selected childs of parent have selection color
		if ((eMode == E_lm_ShowParent)&&(GetCurrentWorld()->GetListSelected()->Find(pChild)))
			fn_vSetLocalColor(pChild, E_lm_ShowSelected);
		// protected childs of super-object have the same color
		else if (pChild->GetSuperObjectOwner())
			fn_vSetLocalColor(pChild, eMode);
		// non protected childs have child color
		else
			fn_vSetLocalColor(pChild, eChild);
	}
}


//#################################################################################
// SELECTION (GET FUNCTIONS)
//#################################################################################

/*===========================================================================
*		Description:	Find the selected objects corresponding to the current DLL
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:             Author:
*=========================================================================*/
CPA_List<CPA_SuperObject> * CPA_Interface::GetSelectedObjects (CPA_ObjectDLLBase *p_oDLL)
{
	EDT_ListByDLL *pListSelect;
	POSITION		 pos;

	if ((!p_oDLL)||(!GetMultiDevice())||(!GetCurrentWorld()))
		return NULL;

	// search the lists to find the type
	for (pListSelect = GetCurrentWorld()->GetListOfListByDLL()->GetHeadElement(pos); pListSelect;
		 pListSelect = GetCurrentWorld()->GetListOfListByDLL()->GetNextElement(pos))
	{
		if (pListSelect->GetDLL() == p_oDLL)
			return (&pListSelect->m_stListSelected);
	}

	// SelectList was not found
	return NULL;
}


/*===========================================================================
*		Description:	Get objects of the good type in mouse selection
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
CPA_List<CPA_SuperObject> * CPA_Interface::GetMouseSelection (ACP_tdxIndex xIndex, HIE_tdstPickInfo *p_stObject, CString csTypeName)
{
	HIE_tdstPickInfo	*pPicking;
	CPA_SuperObject		*pFirstSelect;
	ACP_tdxIndex		xInd;

	// init list
	m_oDialogSelect.fn_vInitDialog();
	// find the selected objects corresponding to this mode
	for (xInd = xIndex, pPicking = p_stObject; xInd > 0; xInd--, pPicking++)
	{
		pFirstSelect = GetFirstSelection(E_sm_SelectByType, xInd, pPicking, csTypeName);
		if (pFirstSelect)
			fn_lFindSelectionInHierarchy(E_sm_SelectByType, pFirstSelect, csTypeName);
	}

	return &m_oDialogSelect.m_stHierarchy;
}

/*===========================================================================
*		Description:	Get objects of the good type in mouse selection
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
CPA_List<CPA_SuperObject> * CPA_Interface::GetMouseSelection (ACP_tdxIndex xIndex, HIE_tdstPickInfo *p_stObject, CString a_csValidTypes[], long lNbTypes)
{
	HIE_tdstPickInfo	*pPicking;
	CPA_SuperObject		*pFirstSelect;
	ACP_tdxIndex		xInd;
	long				lIndex;

	// init list
	m_oDialogSelect.fn_vInitDialog();
	// find the selected objects corresponding to this mode
	for (xInd = xIndex, pPicking = p_stObject; xInd > 0; xInd--, pPicking++)
	{
		pFirstSelect = GetFirstSelection(E_sm_SelectByType, xInd, pPicking, "All Types");
		// find selection for each type
		for (lIndex = 0; lIndex <lNbTypes; lIndex++)
			fn_lFindSelectionInHierarchy(E_sm_SelectByType, pFirstSelect, a_csValidTypes[lIndex]);
	}

	return &m_oDialogSelect.m_stHierarchy;
}

/*===========================================================================
*		Description:	Get objects of the good type in mouse selection
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
CPA_SuperObject * CPA_Interface::GetUserMouseSelection (ACP_tdxIndex xIndex, HIE_tdstPickInfo *p_stObject, CString csTypeName)
{
	CPA_SuperObject *pSelect;
	long			lNbSelect;

	// init dialog
	m_oDialogSelect.fn_vInitDialog();
	lNbSelect = 0;
	// find the selected objects corresponding to this mode
	if (xIndex)
	{
		lNbSelect = fn_lFindSelectionInDepth(E_sm_SelectByType, xIndex, p_stObject, csTypeName);
		if (lNbSelect == 1)
		{
			pSelect = m_oDialogSelect.m_stListSelect.FindElementFromIndex(0);
			lNbSelect = fn_lFindSelectionInHierarchy(E_sm_SelectByType, pSelect, csTypeName);
		}
	}

	// if there are several possibilities, do dialog
	if (lNbSelect > 1)
	{
		m_oDialogSelect.fn_vDoDialog(this, E_sm_SelectByType, csTypeName);
		return (m_oDialogSelect.m_pObjectToSelect);
	}
	// if there is only one choice, give it
	else if (lNbSelect == 1)
		return (m_oDialogSelect.m_stListSelect.FindElementFromIndex(0));
	// if there is no selection
	else
		return NULL;
}


/*===========================================================================
*		Description:	Get objects of the good type in mouse selection
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
CPA_SuperObject * CPA_Interface::GetUserMouseSelection (ACP_tdxIndex xIndex, HIE_tdstPickInfo *p_stObject, CString a_csValidTypes[], long lNbTypes)
{
	CPA_SuperObject *pSelect;
	long			lNbSelect;
	long			lIndex;

	// init dialog
	m_oDialogSelect.fn_vInitDialog();
	lNbSelect =0;
	// find the selected objects corresponding to this mode
	if (xIndex)
	{
		for (lIndex = 0; lIndex <lNbTypes; lIndex++)
			lNbSelect += fn_lFindSelectionInDepth(E_sm_SelectByType, xIndex, p_stObject, a_csValidTypes[lIndex]);
		if (lNbSelect == 1)
		{
			pSelect = m_oDialogSelect.m_stListSelect.FindElementFromIndex(0);
			lNbSelect = 0;
			for (lIndex = 0; lIndex <lNbTypes; lIndex++)
				lNbSelect += fn_lFindSelectionInHierarchy(E_sm_SelectByType, pSelect, a_csValidTypes[lIndex]);
		}
	}

	// if there are several possibilities, do dialog
	if (lNbSelect > 1)
	{
		m_oDialogSelect.fn_vDoDialog(this, E_sm_SelectByType, "", a_csValidTypes, lNbTypes);
		return (m_oDialogSelect.m_pObjectToSelect);
	}
	// if there is only one choice, give it
	else if (lNbSelect == 1)
		return (m_oDialogSelect.m_stListSelect.FindElementFromIndex(0));
	// if there is no selection
	else
		return NULL;
}


/*===========================================================================
*		Description:	Get selection from picking (depending on mode)
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
CPA_SuperObject * CPA_Interface::GetPickingSelection (tdeSelectMode eModeSelect, ACP_tdxIndex xIndex, HIE_tdstPickInfo *p_stObject, tdstMousePos *p_stPos, BOOL *bWillDoDialog, CPA_SuperObject *pPreviousSelection)
{
	HIE_tdstPickInfo	*pPicking;
	CPA_SuperObject		*pSelectedObject;
	DEV_ViewPort3D		*pViewPort;
	tdeTypeAnswer		eAnswer;
	ACP_tdxIndex		xRealInd;
	long				lNbSelect;
	int					iRange, iDelta, iPixel;
	int					iMaxRange, iMaxDelta, iMaxPixel;
	int					arDelta[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};

	// reinit dialog select & drawing
	m_oDialogSelect.fn_vInitDialog();
	*bWillDoDialog = FALSE;

	pViewPort = (DEV_ViewPort3D *) GetMultiDevice()->GetFocusDevice()->GetViewPort();
	iMaxRange = (m_bDeltaSelect) ? 5 : 1;
	iMaxDelta = (m_bDeltaSelect) ? 4 : 1;

	for (iRange = 1; iRange <= iMaxRange; iRange++)
	{
		p_stPos->stPos2D.xX -= 1;
		p_stPos->stPos2D.xY -= 1;

		for (iDelta = 0; iDelta < iMaxDelta; iDelta++)
		{
			iMaxPixel = (m_bDeltaSelect) ? 2 * iRange : 1;
			for (iPixel = 0; iPixel < iMaxPixel; iPixel++)
			{
				switch (eModeSelect)
				{
					case E_sm_SelectParent:
					case E_sm_SelectPFather:
						// find selected objects
						lNbSelect = fn_lFindSelectionInDepth(eModeSelect, xIndex, p_stObject);
						// select the object corresponding to the current mode
						if (lNbSelect == 1)
						{
							pSelectedObject = m_oDialogSelect.m_stListSelect.FindElementFromIndex(0);
							lNbSelect = fn_lFindSelectionInHierarchy(eModeSelect, pSelectedObject);
						}
						if (lNbSelect == 1)
							return pSelectedObject;
						else if (lNbSelect > 1)
						{
							m_oDialogSelect.m_bDoDialog = TRUE;
							*bWillDoDialog = TRUE;
						}
						break;
						
					case E_sm_SelectChoice:
						// find selected objects
						lNbSelect = fn_lFindSelectionInDepth(E_sm_SelectNormal, xIndex, p_stObject);
						if (lNbSelect)
						{
							*bWillDoDialog = TRUE;
							m_oDialogSelect.m_bDoDialog = TRUE;
						}
						break;

					case E_sm_SelectNormal:
						// init search
						eAnswer = C_WantNext;
						pPicking = p_stObject;
						xRealInd = 0;
						while ((eAnswer == C_WantNext)&&(xIndex>0))
						{
							// reinit dialog
							m_oDialogSelect.m_stListSelect.RemoveAll();
							m_oDialogSelect.m_pObjectToSelect = NULL;
							// find the new selection
							pSelectedObject = GetFirstSelection(E_sm_SelectNormal, xIndex, pPicking);
							if (pSelectedObject)
							{
								if ((pPreviousSelection)&&(pSelectedObject == pPreviousSelection))
									eAnswer = C_Accept;
								else
									eAnswer = fn_bCanSelect(pSelectedObject, xIndex, pPicking);
							}
							else
								eAnswer = C_WantNext;
							// next choice
							xIndex--;
							pPicking++;
							xRealInd++;
						}
						if (eAnswer == C_Accept)
						{
							// reinit mouse move (selected object is not always the first one)
							pViewPort->InitMouseMove (&p_stObject[xRealInd-1].stPickedObject.aDEF_stDataOfElement[0].stHit, &p_stPos->stPos2D);
							return pSelectedObject;
						}
						break;
				}

				if (m_bDeltaSelect && p_stObject)
				{
					p_stPos->stPos2D.xX += arDelta[iDelta][0];
					p_stPos->stPos2D.xY += arDelta[iDelta][1];
					xIndex = HIE_xIsSuperObjectPick(GLI_C_ModePickingFace, pViewPort->m_hDisplayDevice,
						pViewPort->m_hDisplayViewport, &p_stPos->stPos2D, GetMultiDevice3D()->GetEngineWorld(), p_stObject);
				}
			}
		}
	}
	return NULL;
}


/*===========================================================================
*		Description:	Getselection from dialog (depending on mode)
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
CPA_SuperObject * CPA_Interface::GetDialogSelection (tdeSelectMode eModeSelect)
{
	CPA_SuperObject *pSelected = NULL;
	CPA_SuperObject *pElem;
	tdeLightMode	eMode;
	POSITION		pos;
	
	// if necessary, display the Selection Dialog
	if (m_oDialogSelect.m_bDoDialog)
	{
		// cancel show mode
		fn_vSetLocalColor(GetCurrentWorld()->GetRoot(), E_lm_ShowNormal);
		// do modal dialog
		m_oDialogSelect.fn_vDoDialog(this, eModeSelect);
		// get parent
		pSelected = m_oDialogSelect.m_pObjectToSelect;
		// init redraw mode
		eMode = (eModeSelect == E_sm_SelectNormal) ? E_lm_ShowSelected : E_lm_ShowParent;
		// redraw selection
		fn_vSetLocalColor(GetCurrentWorld()->GetRoot(), E_lm_ShowNormal);
		for (pElem = GetCurrentWorld()->GetListSelected()->GetHeadElement(pos); pElem;
	 		 pElem = GetCurrentWorld()->GetListSelected()->GetNextElement(pos))
			fn_vSetLocalColor(pElem->GetSuperObjectFather(), eMode);
		// init return value
		if (eModeSelect == E_sm_SelectNormal)
			pSelected =  (fn_bCanSelect(pSelected) == C_Accept) ? pSelected : NULL;
		// reinit dialog
		m_oDialogSelect.fn_vInitDialog();
	}
	return pSelected;
}


/*===========================================================================
*		Description:	find the first object corresponding to the picking
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
CPA_SuperObject * CPA_Interface::GetFirstSelection (tdeSelectMode eSelect, ACP_tdxIndex xIndex, HIE_tdstPickInfo *p_stPickInfo, CString csTypeName)
{
	CPA_SuperObject *pCurChild = NULL;

	// there must be a world
	if ((!GetMultiDevice())||(!GetCurrentWorld()))
		return NULL;

	if (xIndex)
	{
		// find the child corresponding to p_tIndex
		pCurChild = GetEditorObject(p_stPickInfo[0].hSprObject);

		// no more selection
		while (pCurChild)
		{
			// For DLLs
			if ((eSelect == E_sm_SelectByType)&&(!csTypeName.IsEmpty()))
			{
				if (fn_bCanBeSelected(pCurChild, csTypeName, FALSE))
					return pCurChild;
			}
			// only non EditProtected child can be selected
			else if (!pCurChild->fn_bIsEditProtected())
			{
				if (!fn_bIgnoreFlags() &&
					(pCurChild->GetDrawingFlag() != E_df_BoundingV) &&
					(pCurChild->GetDrawingFlag() != E_df_Normal))
					return NULL;

				// Parent Mode
				if (eSelect == E_sm_SelectParent)
				{
					if (m_p_oEditor->fn_bCanBeParentForAll(pCurChild))
						return pCurChild;
				}
				// Paste Mode
				if (eSelect == E_sm_SelectPFather)
				{
					if (m_p_oEditor->fn_bCanPasteAllObjects(E_pm_PasteChoice, pCurChild))
						return pCurChild;
				}
				// Select Mode
				else if (eSelect == E_sm_SelectNormal)
				{
					// Type of the object must be valid
					if (fn_bCanSelect(pCurChild) == C_Accept)
						return pCurChild;
				}
			}
			// previous level of hierarchy
			pCurChild = pCurChild->GetSuperObjectFather();
		}
	}
	// selection
	return NULL;
}


/*===========================================================================
*		Description:	find all objects in depth corresponding to the picking
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
long CPA_Interface::fn_lFindSelectionInDepth (tdeSelectMode eSelect, ACP_tdxIndex xNbPicked, HIE_tdstPickInfo *p_stPickInfo, CString csTypeName)
{
	ACP_tdxIndex		xIndex;
	HIE_tdstPickInfo	*pPicking;
	CPA_SuperObject		*pCurSel;
	long				lNbPicked;

	// init parameters
	lNbPicked = 0;
	pPicking = p_stPickInfo;
	xIndex = xNbPicked;

	while (xIndex)
	{
		// get selected object
		pCurSel = GetFirstSelection(eSelect, xIndex, pPicking, csTypeName);
		// update dialog
		if ((pCurSel)&&(!m_oDialogSelect.m_stListSelect.Find(pCurSel)))
		{
			m_oDialogSelect.m_stListSelect.AddTail(pCurSel);
			lNbPicked++;
		}
		// next level of picking
		xIndex--;
		pPicking++;
	}
	return lNbPicked;
}


/*===========================================================================
*		Description:	find all objects in depth corresponding to the picking
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
long CPA_Interface::fn_lFindSelectionInHierarchy (tdeSelectMode eSelect, CPA_SuperObject *pFirstSelect, CString csTypeName)
{
	CPA_SuperObject		*pCurChild;
	long				lNbPicked;

	// init parameters
	pCurChild = pFirstSelect;
	lNbPicked = 0;

	// no more selection
	while (pCurChild)
	{
		// For DLLs
		if ((eSelect == E_sm_SelectByType)&&(!csTypeName.IsEmpty()))
		{
			if (fn_bCanBeSelected(pCurChild, csTypeName, FALSE))
			{
				m_oDialogSelect.m_stHierarchy.AddTail(pCurChild);
				lNbPicked++;
			}
		}
		// only non EditProtected child can be selected
		else if ( (!pCurChild->fn_bIsEditProtected())
				&&( fn_bIgnoreFlags()
				  ||(pCurChild->GetDrawingFlag() == E_df_BoundingV)
				  ||(pCurChild->GetDrawingFlag() == E_df_Normal)))
		{
			// Parent Mode
			if (eSelect == E_sm_SelectParent)
			{
				if (m_p_oEditor->fn_bCanBeParentForAll(pCurChild))
				{
					m_oDialogSelect.m_stHierarchy.AddTail(pCurChild);
					lNbPicked++;
				}
			}
			// Paste Mode
			if (eSelect == E_sm_SelectPFather)
			{
				if (m_p_oEditor->fn_bCanPasteAllObjects(E_pm_PasteChoice, pCurChild))
				{
					m_oDialogSelect.m_stHierarchy.AddTail(pCurChild);
					lNbPicked++;
				}
			}
			// Select Mode
			else if (eSelect == E_sm_SelectNormal)
			{
				// Type of the object must be valid
				if (fn_bCanSelect(pCurChild) == C_Accept)
				{
					m_oDialogSelect.m_stHierarchy.AddTail(pCurChild);
					lNbPicked++;
				}
			}
		}
		// previous level of hierarchy
		pCurChild = pCurChild->GetSuperObjectFather();
	}
	return lNbPicked;
}

/*===========================================================================
*		Description:	check if the new selected object has parents in
*						the list of selected objects
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
CPA_SuperObject * CPA_Interface::GetPreviousSelection (CPA_SuperObject *pEdObj)
{
	CPA_SuperObject *pElem;
	POSITION		pos;

	// check all the elements in the list
	for (pElem = GetCurrentWorld()->GetListSelected()->GetHeadElement(pos); pElem;
		 pElem = GetCurrentWorld()->GetListSelected()->GetNextElement(pos))
	{
		if (pEdObj->fn_bIsUnderObject(pElem))
			return pElem;
	}
	// object has no parent in the list
	return NULL;
}

//CPA2 Corneliu Babiuc (multiple registration) 02-07-98
//#################################################################################
// REGISTRATION FUNCTIONS
//#################################################################################

/*===========================================================================
*		Description:	check if the new registration object has parents in
*						the list of registered objects
*		Creation date:
*		Author:			Corneliu Babiuc
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
CPA_SuperObject * CPA_Interface::GetPreviousRegistration (CPA_SuperObject *pEdObj)
{
	CPA_SuperObject *pElem;
	POSITION		pos;

	// check all the elements in the list
	for (pElem = GetCurrentWorld()->GetListRegistered()->GetHeadElement(pos); pElem;
		 pElem = GetCurrentWorld()->GetListRegistered()->GetNextElement(pos))
	{
		if (pEdObj->fn_bIsUnderObject(pElem))
			return pElem;
	}
	// object has no parent in the list
	return NULL;
}

/*===========================================================================
*		Description:	Add an object in the list of registration
*		Creation date:
*		Author:			Corneliu Babiuc
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
void CPA_Interface::fn_vAddRegisteredObject	(CPA_SuperObject *pNewObj)
{
	CPA_List<CPA_SuperObject> stListRemoved;
	CPA_SuperObject			  *pElem;
	POSITION				  pos;

	if (!pNewObj)
		return;

	// check all the elements in the list
	for (pElem = GetCurrentWorld()->GetListRegistered()->GetHeadElement(pos); pElem;
		 pElem = GetCurrentWorld()->GetListRegistered()->GetNextElement(pos))
	{
		// if this is a child of pNewObj, remove it from the list
		if (pElem->fn_bIsUnderObject(pNewObj))
			stListRemoved.AddTail(pElem);
	}
	// remove redondant elements
	for (pElem = stListRemoved.GetHeadElement(pos); pElem;
		 pElem = stListRemoved.GetNextElement(pos))
	{
		// remove it from the selected objects
		GetCurrentWorld()->fn_vUpdateRegisterLists(pElem, E_lum_Delete, TRUE);
	}
	// add the new object in the list
	GetCurrentWorld()->fn_vUpdateRegisterLists(pNewObj, E_lum_Insert, TRUE);
}

/*===========================================================================
*		Description:	Remove an object from the list of registration
*		Creation date:
*		Author:			Corneliu Babiuc
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
void CPA_Interface::fn_vRemoveRegisteredObject	(CPA_SuperObject *pEdObj)
{
	POSITION		 pos;

	// check if there is a world
	if (!GetCurrentWorld() || !GetCurrentWorld()->GetRoot())
		return;

	// remove object from the list
	pos = GetCurrentWorld()->GetListRegistered()->Find(pEdObj);
	if (pos)
	{
		GetCurrentWorld()->fn_vUpdateRegisterLists(pEdObj, E_lum_Delete, TRUE);
	}
}

/*===========================================================================
*		Description:	Add a list of objects in the list of registration:
*                    if all objects are already registered, then they'll be 
*                    removed from the list, else unregistered objects are added
*		Creation date:
*		Author:			Corneliu Babiuc
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
void CPA_Interface::fn_vUpdateRegistrationFromSelection	(CPA_List<CPA_SuperObject> * p_lstSelection)
{
	CPA_SuperObject		*pElem;
	POSITION			pos;
	BOOL				bRemove = TRUE;

	for (pElem = p_lstSelection->GetHeadElement(pos);pElem;
		 pElem = p_lstSelection->GetNextElement(pos) )
	{
		//check if the object is allready registered
		if (!GetPreviousRegistration(pElem))
		{
			fn_vAddRegisteredObject(pElem);
			bRemove = FALSE;
		}
	}
	//if all objects are already registered then remove them from registration list
	if (bRemove)
		for (pElem = p_lstSelection->GetHeadElement(pos);pElem;
			 pElem = p_lstSelection->GetNextElement(pos) )
		{
			fn_vRemoveRegisteredObject(pElem);
		}
}

/*===========================================================================
*		Description:	Cancel current selection (clear the lists)
*		Creation date:
*		Author:			Corneliu Babiuc
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
void CPA_Interface::fn_vCancelCurrentRegistration()
{
	EDT_ListByDLL	 *pListSelect;
	CPA_SuperObject  *pElem;
	POSITION		 pos;

	// check if there is a world
	if (!GetCurrentWorld() || !GetCurrentWorld()->GetRoot())
		return;

	while (GetCurrentWorld()->GetListRegistered()->GetCount() > 0)
	{
		pElem = GetCurrentWorld()->GetListRegistered()->RemoveTail();
	}
	// cancel Editor selection
	GetCurrentWorld()->GetListRegistered()->RemoveAll();
	GetCurrentWorld()->GetRegisterListAllDLLs()->m_stListConcerned.RemoveAll();
	// cancel SelectByType
	for (pListSelect = GetCurrentWorld()->GetListOfRegisteredListByDLL()->GetHeadElement(pos); pListSelect;
		 pListSelect = GetCurrentWorld()->GetListOfRegisteredListByDLL()->GetNextElement(pos))
	{
		pListSelect->m_stListConcerned.RemoveAll();
		pListSelect->m_stListSelected.RemoveAll();
		pListSelect->m_stListProtectSelected.RemoveAll();
		pListSelect->m_stListProtectConcerned.RemoveAll();
	}
}
//END CPA2 Corneliu Babiuc (multiple registration) 02-07-98


//#################################################################################
// LISTS (GET FUNCTIONS)
//#################################################################################

/*===========================================================================
*		Description:	Return the list of all objects of the specified type
*						in the hierarchy
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:     Author: Shaitan
*=========================================================================*/
CPA_List<CPA_SuperObject> * CPA_Interface::GetObjectListByType (CString csTypeName, CPA_ObjectDLLBase *p_oDLL)
{
	EDT_ListByType	*pListType;
	EDT_ListByDLL	*pListDLL;
 	POSITION		pos;

	// there must be a world
	if ((!GetMultiDevice())||(!GetCurrentWorld()))
		return NULL;

	// look for the list only for the corresponding DLL
	if (p_oDLL)
	{
		pListDLL = GetCurrentWorld()->GetListFromObjectDLL(p_oDLL);
		if (!pListDLL)
			return NULL;
		pListType = pListDLL->GetListByType(csTypeName);
		if (pListType)
			return &pListType->m_stListObjects;
		else
			return NULL;
	}

	// all types
	if (csTypeName == "All Types")
		return &GetCurrentWorld()->GetListAllDLLs()->m_stListAllTypes.m_stListObjects;

	// find the corresponding list by type
	for (pListDLL = GetCurrentWorld()->GetListOfListByDLL()->GetHeadElement(pos); pListDLL;
		 pListDLL = GetCurrentWorld()->GetListOfListByDLL()->GetNextElement(pos))
	{
		// try to find the correspponding list by type
		pListType = pListDLL->GetListByType(csTypeName);
		if (pListType)
			return &pListType->m_stListObjects;
	}
	// list was not found
	return NULL;
}


/*===========================================================================
*		Description:	Return the sorted list of all objects of the specified
*						type in the hierarchy
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:     Author: Shaitan
*=========================================================================*/
CPA_BaseObjectList * CPA_Interface::GetSortedListByType (CString csTypeName, CPA_ObjectDLLBase *p_oDLL)
{
	EDT_ListByType	*pListType;
	EDT_ListByDLL	*pListDLL;
 	POSITION		pos;

	// there must be a world
	if ((!GetMultiDevice())||(!GetCurrentWorld()))
		return NULL;

	// look for the list only for the corresponding DLL
	if (p_oDLL)
	{
		pListDLL = GetCurrentWorld()->GetListFromObjectDLL(p_oDLL);
		if (!pListDLL)
			return NULL;
		pListType = pListDLL->GetListByType(csTypeName);
		if (pListType)
			return &pListType->m_stSortedList;
		else
			return NULL;
	}
	// all types
	if (csTypeName == "All Types")
		return &GetCurrentWorld()->GetListAllDLLs()->m_stListAllTypes.m_stSortedList;

	// find the corresponding list by type
	for (pListDLL = GetCurrentWorld()->GetListOfListByDLL()->GetHeadElement(pos); pListDLL;
		 pListDLL = GetCurrentWorld()->GetListOfListByDLL()->GetNextElement(pos))
	{
		// try to find the correspponding list by type
		pListType = pListDLL->GetListByType(csTypeName);
		if (pListType)
			return &pListType->m_stSortedList;
	}
	// list was not found
	return NULL;
}


/*===========================================================================
*		Description:	Return the list of all objects of the specified type
*						in the hierarchy
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:     Author: Shaitan
*=========================================================================*/
EDT_ListByType * CPA_Interface::GetListWithTypeName (CString oTypeName, CPA_ObjectDLLBase *p_oDLL)
{
	EDT_ListByType	*pListType;
	EDT_ListByDLL	*pListDLL;
 	POSITION		pos;

	// there must be a world
	if ((!GetMultiDevice())||(!GetCurrentWorld()))
		return NULL;

	// if DLL, return simply corresponding list
	if (p_oDLL)
	{
		pListDLL = GetCurrentWorld()->GetListFromObjectDLL(p_oDLL);
		if (pListDLL)
			return pListDLL->GetListByType(oTypeName);
		else
			return NULL;
	}

	// all types
	if (oTypeName == "All Types")
		return &GetCurrentWorld()->GetListAllDLLs()->m_stListAllTypes;

	// find the corresponding list by type
	for (pListDLL = GetCurrentWorld()->GetListOfListByDLL()->GetHeadElement(pos); pListDLL;
		 pListDLL = GetCurrentWorld()->GetListOfListByDLL()->GetNextElement(pos))
	{
		// try to find the correspponding list by type
		pListType = pListDLL->GetListByType(oTypeName);
		if (pListType)
			return pListType;
	}
	// list was not found
	return NULL;
}


/*===========================================================================
*		Description:	find the Editor Object corresponding to pSupObj.
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:     Author:
*=========================================================================*/
CPA_SuperObject * CPA_Interface::GetEditorObject (HIE_tdxHandleToSuperObject hSupObj)
{
	return m_p_oEditor->GetEditorObject(hSupObj);
}

/*===========================================================================
*		Description:	Find super-object from its type and name
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
CPA_SuperObject * CPA_Interface::GetSuperObject (CString csTypeName, CString csName)
{
	EDT_ListByType  *pListType;

	// find the corresponding list by type
	pListType = GetListWithTypeName(csTypeName);
	if (!pListType)
		return NULL;
	else
		return (pListType->GetObjectWithName(csName));
}


//#################################################################################
// MODELS
//#################################################################################

/*===========================================================================
*		Description:	Set the select mode and update drawing
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                Author:
*=========================================================================*/
void CPA_Interface::SetCurrentModel (EDT_Model *pModel)
{
	m_pCurrentModel = pModel;
	
	// if necessary, update editor
	m_p_oEditor->fn_vUpdateModel();
}

/*===========================================================================
*		Description:	find the list of models corresponding to the name
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
EDT_ModelsByType * CPA_Interface::GetModelsWithTypeName (CString csName)
{
	EDT_ModelsByType *pElem;
	POSITION		 pos;

	// list all types
	if (csName == "All Types")
		return m_pListAllModels;
	// list by type
	for (pElem = m_stListOfModelsByType.GetHeadElement(pos); pElem;
		 pElem = m_stListOfModelsByType.GetNextElement(pos))
	{
		if (pElem->GetTypeName() == csName)
			return pElem;
	}

	return NULL;
}

/*===========================================================================
*		Description:	create a new instance of the given model and type
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
CPA_SuperObject * CPA_Interface::GetNewInstance (CString csTypeName, CString csModel)
{
	EDT_ModelsByType *pListType;
	EDT_Model		 *pModel = NULL;

	// find the corresponding list by type
	pListType = GetModelsWithTypeName(csTypeName);
	if (pListType)
		pModel = pListType->GetModelWithName(csModel);
	if (pModel)
		return pModel->m_pObjectDLL->GetNewInstance(pModel->m_csTypeName, csModel, NULL);
	else
		return NULL;
}

/*===========================================================================
*		Description:	create and init the list of models by type
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vInitListOfModelsByType (CPA_List<CPA_ObjectDLLBase> *pListOfObjectDLLs)
{
	CPA_ObjectDLLBase *p_oDLL;
	POSITION		  pos;

	m_pListAllModels = new EDT_ModelsByType("All Types", NULL, m_pDialogInsert, &m_stListAllBitmaps);

	for (p_oDLL = pListOfObjectDLLs->GetHeadElement(pos); p_oDLL;
		 p_oDLL = pListOfObjectDLLs->GetNextElement(pos))
		p_oDLL->fn_vInitListsOfModels();
}


/*===========================================================================
*		Description:	create and init the lists of models
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL CPA_Interface::fn_bAddANewModelList (CString csListName, CPA_ObjectDLLBase *pObjectDLL)
{
	EDT_ModelsByType *pListModels;

	// find the corresponding list
	pListModels = GetModelsWithTypeName(csListName);
	// if necessary, create the new list
	if (!pListModels)
	{
		pListModels = new EDT_ModelsByType(csListName, pObjectDLL, m_pDialogInsert, &m_stListAllBitmaps);
		m_stListOfModelsByType.AddTail(pListModels);
		return TRUE;
	}
	// if already exists, do not change
	return FALSE;
}


/*===========================================================================
*		Description:	check if a list already exists
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL CPA_Interface::fn_bIsAlreadyLoaded (CString csListName)
{
	EDT_ModelsByType *pListModels;

	// find the corresponding list
	pListModels = GetModelsWithTypeName(csListName);
	return (pListModels != NULL);
}


/*===========================================================================
*		Description:	add a model to the corresponding list
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL CPA_Interface::fn_bAddANewModel (EDT_Model *pModel, CString csListName, CPA_ObjectDLLBase *pObjectDLL)
{
	EDT_ModelsByType *pListModels;

	// find the corresponding list
	pListModels = GetModelsWithTypeName(csListName);
	// if necessary, create the new list
	if (!pListModels)
	{
		pListModels = new EDT_ModelsByType(csListName, pObjectDLL, m_pDialogInsert, &m_stListAllBitmaps);
		m_stListOfModelsByType.AddTail(pListModels);
	}

	// already exists => do not change
	if (pListModels->GetModelWithName(pModel->m_csName))
		return FALSE;
	// update list of models by type
	pListModels->fn_vAddANewModel(pModel);
	// update list of all models
	if (!m_pListAllModels->GetModelWithName(pModel->m_csName))
		m_pListAllModels->fn_vAddANewModel(pModel);
	// tell owner DLL
	pModel->m_pObjectDLL->fn_vOnAddModelToList(pObjectDLL, csListName, pModel->m_csName, C_EDTDo);
	// tell current editor
	if (!pModel->m_pObjectDLL->fn_bIsCurrentEditor())
		GetMainWorld()->GetCurrentEditor()->fn_vOnAddModelToList(pObjectDLL, csListName, pModel->m_csName, C_EDTDo);

	return TRUE;
}

/*===========================================================================
*		Description:	remove a model from the corresponding list
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL CPA_Interface::fn_bRemoveAModel (CString csModelName, CString csListName)
{
	EDT_ModelsByType *pListModels;
	EDT_Model		 *pModel;

	// find the corresponding list
	pListModels = GetModelsWithTypeName(csListName);
	if (!pListModels)
		return FALSE;
	// find corresponding model
	pModel = pListModels->GetModelWithName(csModelName);
	if (!pModel)
		return FALSE;
	// ask owner DLL for permission
	if (!pModel->m_pObjectDLL->fn_bCanDeleteThisModel(csListName, pModel->m_csTypeName, pModel->m_csName))
		return FALSE;
	// Remove it from the list
	pListModels->fn_vRemoveAModel(pModel);
	// remove it from global list
	m_pListAllModels->fn_vRemoveAModel(pModel);
	// tell owner DLL
	pModel->m_pObjectDLL->fn_vOnAddModelToList(pListModels->GetDLL(), csListName, pModel->m_csName, C_EDTUndo);
	// tell current editor
	if (!pModel->m_pObjectDLL->fn_bIsCurrentEditor())
		GetMainWorld()->GetCurrentEditor()->fn_vOnAddModelToList(pListModels->GetDLL(), csListName, pModel->m_csName, C_EDTUndo);
	// destroy it
	if (pModel == m_pCurrentModel)
		SetCurrentModel(NULL);
	delete pModel;

	return TRUE;
}


/*===========================================================================
*		Description:	load a new list of models
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                           Author:
*=========================================================================*/
BOOL CPA_Interface::fn_bLoadModelList (CString csFileName, CString csListName, CPA_ObjectDLLBase *p_oDLL)
{
	SCR_tdst_Cxt_Values *p_stValues ;
	EDT_ModelsByType	*pNewModelList;
	char				szSectionName[SCR_CV_ui_Cfg_MaxLenName];

	// find if the list already exists
	pNewModelList = GetModelsWithTypeName(csListName);
	if (pNewModelList)
		return FALSE;

	// init scripts parameters
	SCRIPT_vRegisterPath((char *)(LPCSTR) M_GetMainApp()->m_csEditorDataPath);
	SCRIPT_vRegisterPath((char *)(LPCSTR) M_GetMainApp()->m_csEngineDataPath);

	SCR_M_RdL0_SetContextLong(1, 0,  (long) p_oDLL);
	
	// section name
	SCR_fn_v_RdL0_ComputeSectionName(szSectionName, (char *)(LPCSTR) csFileName, 
									 "Edit-ListOfModels", (char *)(LPCSTR) csListName);
	// load list from file
	p_stValues = SCR_fnp_st_RdL0_AnalyseSection(szSectionName, SCR_CDF_uw_Anl_Normal);
	if (p_stValues)
		pNewModelList = (EDT_ModelsByType *) p_stValues->a_ulValues[0];	
	// add it to the list
	if (pNewModelList)
		m_stListOfModelsByType.AddTail(pNewModelList);

	return (pNewModelList != NULL);
}

/*===========================================================================
*		Description:	save a list of models
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                           Author:
*=========================================================================*/
void CPA_Interface::fn_vSaveModelList (CString csFileName, CString csListName, CPA_ObjectDLLBase *p_oDLL, CPA_List<EDT_Model> *pListModels)
{
	SCR_tdst_Ntfy_Description	*pNotification;
	SCR_tde_Ntfy_Action			eAction;
	BOOL						bAlreadyExist;
	char						szSectionName[SCR_CV_ui_Cfg_MaxLenName];

	if ((!pListModels)||(!pListModels->GetCount()))
		return;

	// init section name
	SCR_fn_v_RdL0_ComputeSectionName(szSectionName, (char *)(LPCSTR) csFileName, "Edit-ListOfModels", (char *)(LPCSTR) csListName);
	// register modification
	bAlreadyExist = SCR_fn_c_RdL0_IsSectionExists(szSectionName);
	eAction = bAlreadyExist ? SCR_EA_Ntfy_AddSection : SCR_EA_Ntfy_RebuildSection;
	SCR_fn_v_SvL1_RegisterNotify(szSectionName, CallBackSaveModelList, (void *) pListModels, eAction);
	// update notification
	pNotification = SCR_fnp_st_SvL1_GetRegisterNotify(szSectionName);
	fn_v_SvL1_UpdateOneNotify(pNotification, eAction);
	// unregister notification
	SCR_fn_v_SvL1_DeleteRegisterNotify(szSectionName, SCR_CDR_c_RdL0_Match);
}

/*===========================================================================
*		Description:	call back for save
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                           Author:
*=========================================================================*/
void CPA_Interface::CallBackSaveModelList (SCR_tdst_File_Description *p_stFile, char *szSectionName, void *p_vData, SCR_tde_Ntfy_Action eAction)
{
	CPA_List<EDT_Model> *pListModels;
	CPA_ObjectDLLBase	*p_oDLL;
	EDT_Model			*pModel;
	POSITION			pos;
	char				szNewSectionName[SCR_CV_ui_Cfg_MaxLenName];
	char				szName[SCR_CV_ui_Cfg_MaxLenName];
	
	switch (eAction)
    {
		case SCR_EA_Ntfy_AddSection:
			// go to end of file (we need all file directive to load this section)
			SCR_fn_v_SvL1_ToEndSection(p_stFile);
			SCR_M_SvL0_SaveBlankLine (p_stFile);

		case SCR_EA_Ntfy_RebuildSection:
			// get parameters
			pListModels = (CPA_List<EDT_Model> *) p_vData;
			// save begin section
			SCR_fn_v_RdL0_SplitSectionName(szSectionName, NULL, szNewSectionName, szName);
			SCR_fn_v_RdL0_ComputeSectionName(szNewSectionName, NULL, "Edit-ListOfModels", szName);
			SCR_M_SvL0_SaveBeginSection(p_stFile, szNewSectionName, SCR_CC_C_Cfg_NoChar);
			// save DLL name
			pModel = pListModels->GetHeadElement(pos);
			p_oDLL = pModel->m_pObjectDLL;
			SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Normal, 1, (char *)(LPCSTR) p_oDLL->GetName());
			// save al models in list
			for (pModel = pListModels->GetHeadElement(pos); pModel; 
				 pModel = pListModels->GetNextElement(pos))
			{
				SCR_M_SvL0_SaveEntry(p_stFile, "AddModel", SCR_CC_C_Cfg_NoChar);
				SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Normal, 3, 
					(char *)(LPCSTR) pModel->m_csTypeName,
					(char *)(LPCSTR) pModel->m_csName,
					(char *)(LPCSTR) pModel->m_csBitmapName);
			}
			// end section
			SCR_M_SvL0_SaveEndSection (p_stFile, SCR_CC_C_Cfg_EOL);
			if (eAction == SCR_EA_Ntfy_AddSection)
				SCR_M_SvL0_SaveBlankLine (p_stFile);
			break;
	}
}

/*===========================================================================
*		Description:	call back for load
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                           Author:
*=========================================================================*/
SCRIPT_tdeReturnValue CPA_Interface::CallBackLoadModelList	(SCR_tdst_File_Description *p_stFile, char *szSectionName, char *szParams[], SCR_tde_Anl_Action eAction)
{
	CPA_ObjectDLLBase	*p_oDLL;
	EDT_ModelsByType	*pNewListModels;
	CPA_Interface		*pInterface;
	EDT_Model			*pNewModel;

	switch (eAction)
	{
		// section => create
		case SCR_EA_Anl_BeginSection:
			// get parameters
			SCR_M_RdL0_GetContextLong(0, 0, CPA_ObjectDLLBase *,  p_oDLL);
			pInterface = p_oDLL->GetInterface();
			pNewListModels = NULL;
			// check DLL Name and create list
			if (!strcmp((char *) (LPCSTR) p_oDLL->GetName(), szParams[0]))
				pNewListModels = new EDT_ModelsByType(szSectionName, p_oDLL, pInterface->GetDialogInsert(), pInterface->GetBitmapList());
			// set result
			SCR_M_RdL0_SetSectionLong(0, 0, (long) pNewListModels);
			break;
		
		case SCR_EA_Anl_Entry:
			// load a new model
			if (strcmp(szSectionName,"AddModel") == 0)
			{
				// get list
				SCR_M_RdL0_GetSectionLong(0, 0, EDT_ModelsByType *,  pNewListModels);
				if (!pNewListModels)
					break;
				// get parameters
				p_oDLL = pNewListModels->GetDLL();
				pInterface = p_oDLL->GetInterface();
				// create and add model to the list
				pNewModel = new EDT_Model(p_oDLL, szParams[0], szParams[1], szParams[2], pInterface);
				pNewListModels->fn_vAddANewModel(pNewModel);
				// update list all models
				if (!pInterface->m_pListAllModels->GetModelWithName(pNewModel->m_csName))
					pInterface->m_pListAllModels->fn_vAddANewModel(pNewModel);
				// call DLL to create its model
				p_oDLL->fn_vOnLoadNewModel(pNewListModels->GetTypeName(), pNewModel);
				break;
			}
			break;

		case SCR_EA_Anl_EndSection:
			break;
	}
	return SCR_ERV_Anl_NormalReturn;
}



//#################################################################################
// HIERARCHY
//#################################################################################

/*===========================================================================
*		Description:	insert object in hierarchy, as last child of pParent
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:        Author: 
*=========================================================================*/
BOOL CPA_Interface::fn_bInsertObjectInHierarchy (CPA_SuperObject *pEdObj, CPA_SuperObject *pParent, BOOL bUseEditManager, BOOL bUpdateModif, BOOL bSelect, BOOL pBlock)
{
	return m_p_oEditor->fn_bInsertObjectInHierarchy (pEdObj, pParent, bUseEditManager, bUpdateModif, bSelect, pBlock);
}

/*===========================================================================
*		Description:	insert object in hierarchy, as next brother of pBrother
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:        Author: 
*=========================================================================*/
BOOL CPA_Interface::fn_bInsertAsPreviousBrother (CPA_SuperObject *pEdObj, CPA_SuperObject *pBrother, BOOL bUseEditManager, BOOL bUpdateModif, BOOL bSelect, BOOL pBlock)
{
	return m_p_oEditor->fn_bInsertAsPreviousBrother (pEdObj, pBrother, bUseEditManager, bUpdateModif, bSelect, pBlock);
}

/*===========================================================================
*		Description:	remove object from hierarchy
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:        Author: 
*=========================================================================*/
BOOL CPA_Interface::fn_bDeleteObjectInHierarchy (CPA_SuperObject *pEdObj, BOOL bUseEditManager, BOOL bUpdateModif, BOOL bDestroySuperObject, BOOL bSelect, BOOL pBlock)
{
	return m_p_oEditor->fn_bDeleteObjectInHierarchy (pEdObj, bUseEditManager, bUpdateModif, bDestroySuperObject, bSelect, pBlock);
}

/*===========================================================================
*		Description:	create new editor super-object from engine SO
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:        Author: 
*=========================================================================*/
CPA_SuperObject * CPA_Interface::GetNewSuperObject (HIE_tdxHandleToSuperObject hEngineSO, 
													tdeSaveStatus eStatus, tdeTypeSO eTypeSO, 
													CString csName, CString csEngineFileName)
{
	return m_p_oEditor->GetNewSuperObject(hEngineSO, eStatus, eTypeSO, csName, csEngineFileName);
}

/*===========================================================================
*		Description:	create new super-object
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:        Author: 
*=========================================================================*/
CPA_SuperObject * CPA_Interface::GetNewSuperObject (tdeSaveStatus eStatus, tdeTypeSO eTypeSO, 
													CString csName, CString csEngineFileName)
{
	return m_p_oEditor->GetNewSuperObject(eStatus, eTypeSO, csName, csEngineFileName);
}


/*===========================================================================
*		Description:	create a copy of pModel
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:        Author: 
*=========================================================================*/
CPA_SuperObject * CPA_Interface::GetCopyOfSuperObject	(CPA_SuperObject *pModel)
{
	return m_p_oEditor->GetCopyOfSuperObject(pModel);
}


/*===========================================================================
*		Description:	create new super-object
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:        Author: 
*=========================================================================*/
CPA_FileObject * CPA_Interface::GetFileObject (CString csFileName)
{
	return m_p_oEditor->GetFileObject(csFileName);
}

//#################################################################################
// PYRAMID
//#################################################################################

/*===========================================================================
*		Description:	init or cancel depth move for pyramid selection
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:        Author: 
*=========================================================================*/
void CPA_Interface::fn_vInitPyramidDepth (BOOL bInitMove)
{
	if (bInitMove)
	{
		if (m_bSelectionFrameCreating)
		{
			m_bPyramidDepthChanging = TRUE;
			GetCursorPos(&m_stMouseFixPoint);
		}
	}
	else
		if (m_bPyramidDepthChanging)
			m_bPyramidDepthChanging=FALSE;
}

/*===========================================================================
*		Description:	init selection pyramid
*		Creation date:
*		Author:			Yann Le Tensorer
*---------------------------------------------------------------------------
*		Revision date:        Author: Shaitan
*=========================================================================*/
void CPA_Interface::fn_vInitSelectionPyramid(tdstMousePos *p_stPos)
{
	DEV_ViewPort	*ViewPort;
	char			szMessage[256], szMode[20];

	m_stSelectionStartVertex.stPos2D.xX=p_stPos->stPos2D.xX;
	m_stSelectionVertexTopLeft.stPos2D.xX=p_stPos->stPos2D.xX;
	m_stSelectionVertexTopRight.stPos2D.xX=p_stPos->stPos2D.xX;
	m_stSelectionVertexBottomRight.stPos2D.xX=p_stPos->stPos2D.xX;
	m_stSelectionVertexBottomLeft.stPos2D.xX=p_stPos->stPos2D.xX;

	m_stSelectionStartVertex.stPos2D.xY=p_stPos->stPos2D.xY;
	m_stSelectionVertexTopLeft.stPos2D.xY=p_stPos->stPos2D.xY;
	m_stSelectionVertexTopRight.stPos2D.xY=p_stPos->stPos2D.xY;
	m_stSelectionVertexBottomRight.stPos2D.xY=p_stPos->stPos2D.xY;
	m_stSelectionVertexBottomLeft.stPos2D.xY=p_stPos->stPos2D.xY;

	m_bSelectionFrameVisible=FALSE;
	m_bSelectionFrameCreating=TRUE;
	m_bPyramidDepthChanging=FALSE;

	ViewPort =  (DEV_ViewPort3D *) GetMultiDevice()->GetFocusDevice()->GetViewPort();

	fn_vSetZCamera(	ViewPort->m_hDisplayDevice,ViewPort->m_hDisplayViewport,
								&m_stSelectionVertexBottomRight.stPos3D,
								&m_stSelectionVertexBottomRight.stPos3D,
								m_dfZNearSelectionFrame);
	fn_vSetZCamera(	ViewPort->m_hDisplayDevice,ViewPort->m_hDisplayViewport,
								&m_stSelectionVertexTopRight.stPos3D,
								&m_stSelectionVertexTopRight.stPos3D,
								m_dfZNearSelectionFrame);
	fn_vSetZCamera(	ViewPort->m_hDisplayDevice,ViewPort->m_hDisplayViewport,
								&m_stSelectionVertexTopLeft.stPos3D,
								&m_stSelectionVertexTopLeft.stPos3D,
								m_dfZNearSelectionFrame);
	fn_vSetZCamera(	ViewPort->m_hDisplayDevice,ViewPort->m_hDisplayViewport,
								&m_stSelectionVertexBottomLeft.stPos3D,
								&m_stSelectionVertexBottomLeft.stPos3D,
								m_dfZNearSelectionFrame);

	float saveZ = (float)m_dfZFarSelectionFrame;
	if (m_bFixedDepth) 
		m_dfZFarSelectionFrame = m_dfZNearSelectionFrame + GetPyramidalDepth();

	fn_vSetZCamera(	ViewPort->m_hDisplayDevice,ViewPort->m_hDisplayViewport,
								&m_stFarSelectionVertexBottomRight.stPos3D,
								&m_stFarSelectionVertexBottomRight.stPos3D,
								m_dfZFarSelectionFrame);
	fn_vSetZCamera(	ViewPort->m_hDisplayDevice,ViewPort->m_hDisplayViewport,
								&m_stFarSelectionVertexTopRight.stPos3D,
								&m_stFarSelectionVertexTopRight.stPos3D,
								m_dfZFarSelectionFrame);
	fn_vSetZCamera(	ViewPort->m_hDisplayDevice,ViewPort->m_hDisplayViewport,
								&m_stFarSelectionVertexTopLeft.stPos3D,
								&m_stFarSelectionVertexTopLeft.stPos3D,
								m_dfZFarSelectionFrame);
	fn_vSetZCamera(	ViewPort->m_hDisplayDevice,ViewPort->m_hDisplayViewport,
								&m_stFarSelectionVertexBottomLeft.stPos3D,
								&m_stFarSelectionVertexBottomLeft.stPos3D,
								m_dfZFarSelectionFrame);

	// message in status bar
	strcpy(szMode, m_bRealTime ? "REAL TIME" : "STATIC");
	if (m_bFixedDepth) 
		sprintf(szMessage, "Pyramid Selection : %s, FIXED depth : %3.2f m (choosed in options)", szMode, GetPyramidalDepth());
	else
		sprintf(szMessage, "Pyramid Selection : %s, FREE depth : %3.2f m (use 'W' to change the depth)", szMode, m_dfZFarSelectionFrame);
	
	M_GetMainWnd()->UpdateStatus(szMessage, C_STATUSPANE_INFOS, C_STATUS_NORMAL);

	m_dfZFarSelectionFrame = saveZ;
}


/*===========================================================================
*		Description:	Draw pyramid selection (OnMouseMove)
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:        Author: 
*=========================================================================*/
BOOL CPA_Interface::fn_bDoSelectionPyramid	(tdstMousePos *p_stPos)
{
	// if necessary, update pyramid depth
	if (m_bPyramidDepthChanging)
		fn_vChangePyramidDepth(p_stPos);

	// if pyramid enabled, draw pyramid
	if (m_bSelectionFrameCreating)
	{
		fn_vCreateSelectionFrame(p_stPos);
		fn_vUpdateAll(E_mc_JustDraw);
		return TRUE;
	}

	// no action
	return FALSE;
}


/*===========================================================================
*		Description:	Draw selection frame.
*		Creation date:
*		Author:			Yann Le Tensorer
*---------------------------------------------------------------------------
*		Revision date:        Author: Shaitan
*=========================================================================*/
void CPA_Interface::fn_vDrawSelectionFrame(GLD_tdstViewportAttributes *p1)
{

	POS_tdstCompletePosition stMatrix;
	MTH3D_tdstVector stTopRight, stTopLeft, stBottomRight, stBottomLeft;
	MTH3D_tdstVector stFarTopRight, stFarTopLeft, stFarBottomRight, stFarBottomLeft;

	POS_fn_vSetIdentityMatrix(&stMatrix);

	if (!m_bSelectionFrameVisible)
		return;

	if (g_p_stCurrentMatrix!=0)
	{
		GLI_xGetCameraMatrix(((GLI_tdstSpecificAttributesFor3D*)(p1->p_vSpecificToXD))->p_stCam,&stMatrix);
		GLI_xLoadMatrix(&stMatrix);

		stBottomRight = m_stSelectionVertexBottomRight.stPos3D;
		stBottomLeft = m_stSelectionVertexBottomLeft.stPos3D;
		stTopRight = m_stSelectionVertexTopRight.stPos3D;
		stTopLeft = m_stSelectionVertexTopLeft.stPos3D;

		stFarBottomRight = m_stFarSelectionVertexBottomRight.stPos3D;
		stFarBottomLeft = m_stFarSelectionVertexBottomLeft.stPos3D;
		stFarTopRight = m_stFarSelectionVertexTopRight.stPos3D;
		stFarTopLeft = m_stFarSelectionVertexTopLeft.stPos3D;

		GLI_xDraw3DLine16((GLD_tdstViewportAttributes_*)p1,&stFarTopLeft,&stFarTopRight,0xffffffff/*0xcccccccc*/);
		GLI_xDraw3DLine16((GLD_tdstViewportAttributes_*)p1,&stFarTopRight,&stFarBottomRight,0xffffffff/*0xcccccccc*/);
		GLI_xDraw3DLine16((GLD_tdstViewportAttributes_*)p1,&stFarBottomRight,&stFarBottomLeft,0xffffffff/*0xcccccccc*/);
		GLI_xDraw3DLine16((GLD_tdstViewportAttributes_*)p1,&stFarBottomLeft,&stFarTopLeft,0xffffffff/*0xcccccccc*/);

		GLI_xDraw3DLine16((GLD_tdstViewportAttributes_*)p1,&stTopLeft,&stFarTopLeft,0xffffffff/*0xcccccccc*/);
		GLI_xDraw3DLine16((GLD_tdstViewportAttributes_*)p1,&stTopRight,&stFarTopRight,0xffffffff/*0xcccccccc*/);
		GLI_xDraw3DLine16((GLD_tdstViewportAttributes_*)p1,&stBottomRight,&stFarBottomRight,0xffffffff/*0xcccccccc*/);
		GLI_xDraw3DLine16((GLD_tdstViewportAttributes_*)p1,&stBottomLeft,&stFarBottomLeft,0xffffffff/*0xcccccccc*/);

		GLI_xDraw3DLine16((GLD_tdstViewportAttributes_*)p1,&stTopLeft,&stTopRight,0xffffffff);
		GLI_xDraw3DLine16((GLD_tdstViewportAttributes_*)p1,&stTopRight,&stBottomRight,0xffffffff);
		GLI_xDraw3DLine16((GLD_tdstViewportAttributes_*)p1,&stBottomRight,&stBottomLeft,0xffffffff);
		GLI_xDraw3DLine16((GLD_tdstViewportAttributes_*)p1,&stBottomLeft,&stTopLeft,0xffffffff);

        GLI_xPopMatrix();
	}

}


/*===========================================================================
*		Description:	end pyramid selection mode
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:        Author: Yann Le Tensorer
*=========================================================================*/
void CPA_Interface::fn_vEndSelectionPyramid	(void)
{
	if (m_bSelectionFrameCreating||m_bPyramidDepthChanging)
	{
		if (!m_bRealTime) 
			fn_vSelectObjectsInPyramid();
		m_bSelectionFrameCreating = FALSE;
		m_bSelectionFrameVisible = FALSE;
		m_bPyramidDepthChanging = FALSE;
		fn_vUpdateAll(E_mc_UpdateDialog);
	}
}


/*######################################################################################
functions for object moving
######################################################################################*/

void CPA_Interface::fn_vEnterObjectMouseMoveMode() 
{ 
	m_bModeIsObjectMouseMove = TRUE; 
	m_bLastMovePlaneRemembered = FALSE;
	//m_vSetMouseMovePlane(E_mmp_Standard);
}

/*=========================================================================*/
/*=========================================================================*/
void CPA_Interface::fn_vLeaveObjectMouseMoveMode() 
{ 
	if ( m_bModeIsObjectMouseMove )
	{
		m_bModeIsObjectMouseMove = FALSE; 
		// redraw everything, 
		fn_vUpdateAll(E_mc_JustDraw);
	}
	m_bLastMovePlaneRemembered = FALSE;
	fn_vSetMouseMovePlane(E_mmp_Standard);
}

/*=========================================================================*/
/*=========================================================================*/
BOOL CPA_Interface::fn_bGetObjectMouseMoveMode() 
{ 
	return m_bModeIsObjectMouseMove; 
}

/*=========================================================================*/
/*=========================================================================*/
tdeMouseMovePlane CPA_Interface::fn_eGetMouseMovePlane() 
{ 
	return m_eMouseMovePlane; 
}

/*=========================================================================*/
/*=========================================================================*/
void CPA_Interface::fn_vSetMouseMovePlane(tdeMouseMovePlane _eMMP) 
{ 
	m_eMouseMovePlane = _eMMP; 
}

/*=========================================================================*/
/*=========================================================================*/
void CPA_Interface::SetPlaneForMouseMove(MTH3D_tdstVector *p_stX_Axe, MTH3D_tdstVector *p_stY_Axe)
{
	memcpy(&m_stMouseXAxe, p_stX_Axe, sizeof(m_stMouseXAxe));
	memcpy(&m_stMouseYAxe, p_stY_Axe, sizeof(m_stMouseYAxe));
}

/*=========================================================================*/
/*=========================================================================*/
void CPA_Interface::RememberLastMouseMovePlane(MTH3D_tdstVector *p_stX_Axe, MTH3D_tdstVector *p_stY_Axe)
{
	memcpy(&m_stLastMoveXAxe, p_stX_Axe, sizeof(m_stLastMoveXAxe));
	memcpy(&m_stLastMoveYAxe, p_stY_Axe, sizeof(m_stLastMoveYAxe));
	m_bLastMovePlaneRemembered = TRUE;
}

/*=========================================================================*/
/*=========================================================================*/
void CPA_Interface::SetMovePlaneCenter(MTH3D_tdstVector *p_stPosition) 
{ 
	memcpy(&m_stMouseMovePlaneCenter, p_stPosition, sizeof(m_stMouseMovePlaneCenter));
}

/*=========================================================================*/
/*=========================================================================*/
void CPA_Interface::GetPlaneForMouseMove(MTH3D_tdstVector *p_stX_Axe, MTH3D_tdstVector *p_stY_Axe)
{
	memcpy(p_stX_Axe, &m_stMouseXAxe, sizeof(m_stMouseXAxe));
	memcpy(p_stY_Axe, &m_stMouseYAxe, sizeof(m_stMouseYAxe));
}

/*=========================================================================*/
/*=========================================================================*/
void CPA_Interface::fn_vComputeSuperObjectsCenters(GLD_tdstViewportAttributes *p1)
{
//	GLI_tdstSpecificAttributesFor3D *p_st3DAtributes;
	CPA_List<CPA_SuperObject>		*p_oListOfObjects;
	MTH3D_tdstVector				stCamPos;
	CPA_SuperObject					*p_oObject;
	DEV_ViewPort3D					*pViewPort;
	POS_tdstCompletePosition		stMatrix, stRealMatrix;
	POSITION						xPos; 
	
	// init parameters
	p_oListOfObjects = GetCurrentWorld()->GetListAllObjects();
	xPos = p_oListOfObjects->GetHeadPosition();

//	p_st3DAtributes = (GLI_tdstSpecificAttributesFor3D*)(p1->p_vSpecificToXD);
//	GLI_xGetCameraMatrix(p_st3DAtributes->p_stCam, &stMatrix);

	// get camera parameters
	pViewPort = (DEV_ViewPort3D *) GetMultiDevice()->GetFocusDevice()->GetViewPort();
	GLI_xGetCameraMatrix(pViewPort->GetEngineCamera(), &stMatrix); 
	POS_fn_vInvertMatrix(&stRealMatrix,&stMatrix);
	POS_fn_vGetTranslationVector(&stRealMatrix, &stCamPos);

		// check all objects in the list
	while (xPos)
	{
		p_oObject = (CPA_SuperObject *) p_oListOfObjects->GetNext(xPos);

		if (GetShowcenter() && p_oObject->GetObject() && (GetShowcenter() & 1 || fn_bCanSelect(p_oObject) == C_Accept))
		{
			HIE_tdxHandleToSuperObject		hSuperObject;
			HIE_aDEF_stTabOfPickInfo		a_stPickInfo;
			GLI_tdstAligned2DVector			a2_st2DVertex;
			GLI_tdstAligned3DVector			a2_stVertex;
			GEO_tdxHandleToMatrix			hGlobalMatrix;
			MTH3D_tdstVector				stPosition;
			GLI_tdst2DVertex				stPos2D;
			ACP_tdxIndex					xNbPicked;
			BOOL							bFound = FALSE;

			// get superobject parameters
			hSuperObject = p_oObject->GetStruct();
			hGlobalMatrix = HIE_fn_hGetSuperObjectGlobalMatrix(hSuperObject);
			POS_fn_vGetTranslationVector(hGlobalMatrix, &stPosition);

			// get projection of center
			GLI_xSerialLinearOp(1, &stPosition, &a2_stVertex, &stMatrix);
			GLI_xSerialProjection(pViewPort->GetEngineCamera(), 1, &a2_stVertex, &a2_st2DVertex);
			stPos2D.xX = a2_st2DVertex.xX;
			stPos2D.xY = a2_st2DVertex.xY;

			// check if center is visible
			xNbPicked = HIE_xIsSuperObjectPick(GLI_C_ModePickingFace, pViewPort->m_hDisplayDevice, pViewPort->m_hDisplayViewport, 
												&stPos2D, GetMultiDevice3D()->GetEngineWorld(), a_stPickInfo);
			if (xNbPicked > 0)
			{
				MTH3D_tdstVector stHit, stDistHit, stDistObj;
				
				// check distance 
				stHit = a_stPickInfo[0].stPickedObject.aDEF_stDataOfElement[0].stHit;
				MTH3D_M_vSubVector(&stDistHit, &stCamPos, &stHit);
				MTH3D_M_vSubVector(&stDistObj, &stCamPos, &stPosition);
				if (MTH3D_M_xNormVector(&stDistHit) >= MTH3D_M_xNormVector(&stDistObj) - 0.15)
					bFound = TRUE;
				
				// check picking
				HIE_tdxHandleToSuperObject	hPicked = a_stPickInfo[0].hSprObject;
				while (hPicked && !bFound)
				{
					if (hPicked == hSuperObject)
						bFound = TRUE;
					else
						hPicked = HIE_fn_hGetSuperObjectFather(hPicked);
				}
			}

			// update super object flag
			p_oObject->SetCenterVisible(bFound);
		}
	}
}

/*=========================================================================*/
/*=========================================================================*/
void CPA_Interface::fn_vDrawSuperObjectsCenters(GLD_tdstViewportAttributes *p1)
{
	CPA_List<CPA_SuperObject> *p_oListOfObjects = GetCurrentWorld()->GetListAllObjects();
	POSITION xPos = p_oListOfObjects->GetHeadPosition();
	POS_tdstCompletePosition matrix;
	
	while ( xPos )
	{
		CPA_SuperObject	*p_oObject = (CPA_SuperObject *) p_oListOfObjects->GetNext(xPos);
		if (GetShowcenter() && p_oObject->GetObject() && p_oObject->fn_bIsCenterVisible() &&
			(GetShowcenter() & 1 || fn_bCanSelect(p_oObject) == C_Accept))
		{
			MTH3D_tdstVector p;
			GLI_tdstAligned2DVector a2_st2DVertex;
			GLI_tdstAligned3DVector a2_stVertex;
			GLI_tdstSpecificAttributesFor3D *p_st3DAtributes;

			HIE_tdxHandleToSuperObject hSuperObject = p_oObject->GetStruct();

			if(!m_bLoaded)
			{
				GLI_xCreateMaterial(&m_hCenterMaterial);
				GLI_xLoadTexture(&m_pTexBar, NULL, "center.bmp", 0, 0);
				if (m_pTexBar) 
					TEX_vSetTextureQualityLevel(m_pTexBar,(char)TEX_C_QHIGH); // eventuellement
				GLI_vEndofGeometricLoad(); 
				GLI_xSetMaterialTexture(m_hCenterMaterial,m_pTexBar);
				m_bLoaded = TRUE;
			}
			GEO_tdxHandleToMatrix hGlobalMatrix = HIE_fn_hGetSuperObjectGlobalMatrix(hSuperObject);
			POS_fn_vGetTranslationVector(hGlobalMatrix, &p);

			p_st3DAtributes = (GLI_tdstSpecificAttributesFor3D*)(p1->p_vSpecificToXD);
			GLI_xGetCameraMatrix(p_st3DAtributes->p_stCam, &matrix);
			GLI_xSerialLinearOp(1, &p, &a2_stVertex, &matrix);
			GLI_xSerialProjection(p_st3DAtributes->p_stCam, 1, &a2_stVertex, &a2_st2DVertex);
//			g_stCurLLInterface.p_fnSerialSnap2DVertices (&a2_st2DVertex, 1);

			float near1 = (float)p_st3DAtributes->p_stCam->xNear;
			p_st3DAtributes->p_stCam->xNear += 0.01f; 
			GLI_vDraw2DSprite(p1, a2_st2DVertex.xX-5, a2_st2DVertex.xX + 5, a2_st2DVertex.xY-5, a2_st2DVertex.xY + 5, m_hCenterMaterial);           
			p_st3DAtributes->p_stCam->xNear = near1; 
		}
	}
}

/*=========================================================================*/
/*=========================================================================*/
void CPA_Interface::fn_vGetScreenProjection(CPA_SuperObject *obj, MTH3D_tdstVector *prj)
{
	MTH3D_tdstVector p;
	GLI_tdstAligned2DVector a2_st2DVertex;
	GLI_tdstAligned3DVector a2_stVertex;
	GLI_tdstSpecificAttributesFor3D *p_st3DAtributes;
	GLD_tdstViewportAttributes ViewAttr;
	POS_tdstCompletePosition matrix;

	prj->xX = prj->xY = prj->xZ = 0;
	DEV_ViewPort3D *ViewPort =  (DEV_ViewPort3D *) GetMultiDevice()->GetFocusDevice()->GetViewPort();
	if ( !GLD_bGetViewportAttributes( ViewPort->m_hDisplayDevice,ViewPort->m_hDisplayViewport, &ViewAttr)) return;
	p_st3DAtributes = (GLI_tdstSpecificAttributesFor3D *)ViewAttr.p_vSpecificToXD;

	GEO_tdxHandleToMatrix hGlobalMatrix = HIE_fn_hGetSuperObjectMatrix(obj->GetStruct());
	POS_fn_vGetTranslationVector(hGlobalMatrix, &p);
	p_st3DAtributes = (GLI_tdstSpecificAttributesFor3D*)(ViewAttr.p_vSpecificToXD);
	GLI_xGetCameraMatrix(p_st3DAtributes->p_stCam, &matrix);
	GLI_xSerialLinearOp(1, &p, &a2_stVertex, &matrix);
	GLI_xSerialProjection(p_st3DAtributes->p_stCam, 1, &a2_stVertex, &a2_st2DVertex);
//	g_stCurLLInterface.p_fnSerialSnap2DVertices (&a2_st2DVertex, 1);
	
	prj->xX = a2_st2DVertex.xX;
	prj->xY = a2_st2DVertex.xY;
}

/*=========================================================================*/
/*=========================================================================*/
void CPA_Interface::fn_vDrawSuperObjectsAxis(GLD_tdstViewportAttributes *p1)
{
	
	CPA_List<CPA_SuperObject> *p_oListOfObjects = GetCurrentWorld()->GetListAllObjects();
	POSITION xPos = p_oListOfObjects->GetHeadPosition();

	while ( xPos )
	{
		CPA_SuperObject	*p_oObject = (CPA_SuperObject	*) p_oListOfObjects->GetNext(xPos);
		if ( p_oObject && p_oObject->fn_bIsAxisDrawn() )
		{
			HIE_tdxHandleToSuperObject hSuperObject = p_oObject->GetStruct();
			GEO_tdxHandleToMatrix hGlobalMatrix = HIE_fn_hGetSuperObjectGlobalMatrix(hSuperObject);
			//get the origin and axis of the superobject
			MTH3D_tdstVector stOrigin, stI, stJ, stK;
			POS_fn_vGetTranslationVector(hGlobalMatrix, &stOrigin);
			POS_fn_vGetRotationMatrix(hGlobalMatrix, &stI, &stJ, &stK);
			//now draw lines from the origin of the matrix to each vector:
			MTH3D_M_vAddVector(&stI, &stI, &stOrigin);
			MTH3D_M_vAddVector(&stJ, &stJ, &stOrigin);
			MTH3D_M_vAddVector(&stK, &stK, &stOrigin);
			GLI_xDraw3DLine16(
				(GLD_tdstViewportAttributes_*)p1,
				&stOrigin,
				&stI,
				0xff000000
			);
			GLI_xDraw3DLine16(
				(GLD_tdstViewportAttributes_*)p1,
				&stOrigin,
				&stJ,
				0x00ff0000
			);
			GLI_xDraw3DLine16(
				(GLD_tdstViewportAttributes_*)p1,
				&stOrigin,
				&stK,
				0x0000ff00
			);
		}
	}
}

/*=========================================================================*/
/*=========================================================================*/
void CPA_Interface::fn_vDrawMoveObjectFrame(GLD_tdstViewportAttributes *p1)
{
	if ( fn_bGetObjectMouseMoveMode() && m_bLastMovePlaneRemembered && m_stMouseYAxe.xZ )
	{
		POS_tdstCompletePosition stMatrix, stInvMatrix;

		POS_fn_vSetIdentityMatrix(&stMatrix);
		POS_fn_vSetIdentityMatrix(&stInvMatrix);

		//array of positions around a square numbered as follows:
		// 0--1--2
		// |		 |
		// 3  Q  4
		// |     |
		// 5--6--7

		MTH3D_tdstVector stVertexes[8]; 
		//linear combination of X and Y vectors to go from the center Q 
		//to an extermity of a line to draw
		#define C_fDist 1.0
		float aa_fXY[8][2] = 
		{ 
			{ -C_fDist,  C_fDist },
			{  0.0,      C_fDist },
			{  C_fDist,  C_fDist },
			{ -C_fDist,  0.0     },
			{  C_fDist,  0.0     },
			{ -C_fDist, -C_fDist },
			{  0.0,     -C_fDist },
			{  C_fDist, -C_fDist }
		};
		GEO_tdstColor ColBidon;

		ColBidon.xR=0.5;
		ColBidon.xG=0.5;
		ColBidon.xB=0.5;
		ColBidon.xA=0.5;

		GLI_xGetCameraMatrix(((GLI_tdstSpecificAttributesFor3D*)(p1->p_vSpecificToXD))->p_stCam,&stMatrix);
		GLI_xLoadMatrix(&stMatrix);
		GLI_vSetFog(100,100,200,&ColBidon);

		POS_fn_vInvertMatrix(&stInvMatrix , &stMatrix);

		for ( short wIndex = 0; wIndex < 8; wIndex ++ )		
		{
			//put the center of the plane in the vertex
			MTH3D_M_vCopyVector(&stVertexes[wIndex], &m_stMouseMovePlaneCenter);
			//convert the point into camera coordinates
			//POS_fn_vMulMatrixVertex(&stVertexes[wIndex], &stMatrix , &stVertexes[wIndex]);
			//compute the new position of the point after it moved away from the center
			MTH3D_tdstVector stTempVector;
			MTH3D_M_vCopyVector(&stTempVector, &m_stLastMoveXAxe);
			MTH3D_M_vMulScalarVector(&stTempVector, aa_fXY[wIndex][0], &stTempVector);
			MTH3D_M_vAddVector(&stVertexes[wIndex], &stVertexes[wIndex], &stTempVector);
			MTH3D_M_vCopyVector(&stTempVector, &m_stLastMoveYAxe);
			MTH3D_M_vMulScalarVector(&stTempVector, aa_fXY[wIndex][1], &stTempVector);
			MTH3D_M_vAddVector(&stVertexes[wIndex], &stVertexes[wIndex], &stTempVector);
			//convert the point back into world coordinates
			//POS_fn_vMulMatrixVertex(&stVertexes[wIndex], &stInvMatrix, &stVertexes[wIndex]);
		}
		//now draw all the lines we want: 0-2, 3-4, 5-7, 0-5, 1-6, 2-7
		short aa_wIndexes[6][2] =
		{
			{ 0, 2 },
			{ 3, 4 },
			{ 5, 7 },
			{ 0, 5 },
			{ 1, 6 },
			{ 2, 7 }
		};
		for (wIndex = 0; wIndex < 6; wIndex ++ )
		{
			GLI_xDraw3DLine16(
				(GLD_tdstViewportAttributes_*)p1,
				&stVertexes[aa_wIndexes[wIndex][0]],
				&stVertexes[aa_wIndexes[wIndex][1]],
				(wIndex == 1 || wIndex == 4) ? 0xeeeeeeee : 0x99999999 //crosshair is brighter than outer frame
			);
		}
		GLI_xPopMatrix();
	}
}


//#################################################################################
// MENU FUNCTIONS
//#################################################################################

/*===========================================================================
*		Description:	display popup menu
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
void CPA_Interface::fn_vDisplayPopupMenu (tdstMousePos *p_stCoords)
{
    CPA_SuperObject	  *pSelected;
	CPA_ToolDLLBase	  *pDLLTool;
	DEV_ViewPort3D	  *pCurViewport;
	EDT_ListByDLL	  *pSelect;
	CPA_DLLBase		  *p_oCameraInterface;
	EDT_SubMenu		  *p_oSubMenu;
	POSITION		  pos;
	CString			  csMenuDescString, csMenuAccelString;

	
	// get camera interface
	pCurViewport = (DEV_ViewPort3D *) GetMultiDevice()->GetFocusDevice()->GetViewPort();
	p_oCameraInterface = pCurViewport->GetCameraInterface();	
	
	// clear popupmenu
	m_oPopUpMenu.Clear();

	if (p_oCameraInterface->fn_bDefinePopupMenu(&m_oPopUpMenu, GetCurrentWorld()->GetListSelected(), FALSE))
		m_oPopUpMenu.AddASeparator();

	// drawing
	if (GetCurrentWorld()->GetCountSelected() == 1)
	{
		pSelected = GetCurrentWorld()->GetSingleSelection();
		// display
		p_oSubMenu = m_oPopUpMenu.fn_p_oGetNewSubMenu("Display");
//CPA2 Corneliu Babiuc 13-05-98
		//make the menu string
		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Normal Object"));
		csMenuDescString.Format("Normal\t%s", csMenuAccelString);
		p_oSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_NormalDrawingAction, (pSelected->GetDrawingFlag() == E_df_Normal), TRUE);
		
		//make the menu string
		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Grided Object"));
		csMenuDescString.Format("Grided\t%s", csMenuAccelString);
		p_oSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_GridedDrawingAction, (pSelected->GetDrawingFlag() == E_df_Grided), TRUE);
		
		//make the menu string
		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Wired Object"));
		csMenuDescString.Format("Wired\t%s", csMenuAccelString);
		p_oSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_WiredDrawingAction, (pSelected->GetDrawingFlag() == E_df_Wired), TRUE);
//END CPA2 Corneliu Babiuc 13-05-98
        m_oPopUpMenu.AddASubMenu(p_oSubMenu);
		// show
		p_oSubMenu = m_oPopUpMenu.fn_p_oGetNewSubMenu("Show");
//CPA2 Corneliu Babiuc 19-05-98
		//make the menu string
		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Show Object Axis"));
		csMenuDescString.Format("Show Axis\t%s", csMenuAccelString);
		p_oSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_ShowAxisAction, pSelected->fn_bIsAxisDrawn(), TRUE);

		p_oSubMenu->AddAnEntry(NULL, "Show Bounding Volume", C_ui_ShowBoundingV, (pSelected->GetDrawingFlag() == E_df_BoundingV), TRUE);
//END CPA2 Corneliu Babiuc 19-05-98
        m_oPopUpMenu.AddASubMenu(p_oSubMenu);

		m_oPopUpMenu.AddASeparator();
	}

	// Hierarchy Editor Entries
	if (m_p_oEditor->fn_bDefinePopupMenu(&m_oPopUpMenu, GetCurrentWorld()->GetListSelected(), TRUE))
		m_oPopUpMenu.AddASeparator();

	// ask current editor first
	if (!m_p_oEditor->fn_bIsCurrentEditor())
	{
		if (GetMainWorld()->GetCurrentEditor()->fn_bDefinePopupMenu(&m_oPopUpMenu, GetCurrentWorld()->GetListSelected(), TRUE))
			m_oPopUpMenu.AddASeparator();
	}

	// ask all object DLLs
	for (pSelect = GetCurrentWorld()->GetListOfListByDLL()->GetHeadElement(pos); pSelect;
		 pSelect = GetCurrentWorld()->GetListOfListByDLL()->GetNextElement(pos))
	{
		if (pSelect->GetDLL() != p_oCameraInterface)
		{
			if (pSelect->GetDLL()->fn_bDefinePopupMenu(&m_oPopUpMenu, &pSelect->m_stListSelected, FALSE))
				m_oPopUpMenu.AddASeparator();
		}
	}

	// ask all tool DLLs
	for (pDLLTool = GetMainWorld()->GetListOfToolDLLBase()->GetHeadElement(pos); pDLLTool;
		 pDLLTool = GetMainWorld()->GetListOfToolDLLBase()->GetNextElement(pos))
	{
		if (pDLLTool->fn_bDefinePopupMenu(&m_oPopUpMenu, GetCurrentWorld()->GetListSelected(), FALSE))
			m_oPopUpMenu.AddASeparator();
	}

	// then, build and draw the popupmenu.
	m_oPopUpMenu.Build();
	m_oPopUpMenu.Draw((DEV_ViewPort3D *) GetMultiDevice()->GetFocusDevice()->GetViewPort(),p_stCoords);
}


/*===========================================================================
*		Description:	display popup menu
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
void CPA_Interface::fn_vDisplayMenuCommand (UINT IDCmdMsg)
{
    CPA_SuperObject *pSelected;
	UINT			IDRealCmdMsg;
	CPA_EditorBase	*pOwner;	

	// get real ID
	if ((m_oPopUpMenu.fn_bFindCmdID(IDCmdMsg,&pOwner,&IDRealCmdMsg))&&(pOwner == NULL))
	{
		switch (IDRealCmdMsg)
		{
			// drawing
			case C_ui_NormalDrawingAction:
				pSelected = GetCurrentWorld()->GetSingleSelection();
				pSelected->SetDrawingFlag(E_df_Normal);
				fn_vUpdateAll(E_mc_JustDraw);
				return;
			case C_ui_GridedDrawingAction:
				pSelected = GetCurrentWorld()->GetSingleSelection();
				pSelected->SetDrawingFlag(E_df_Grided);
				fn_vUpdateAll(E_mc_JustDraw);
				return;
			case C_ui_WiredDrawingAction:
				pSelected = GetCurrentWorld()->GetSingleSelection();
				pSelected->SetDrawingFlag(E_df_Wired);
				fn_vUpdateAll(E_mc_JustDraw);
				return;

			case C_ui_ShowAxisAction:
				pSelected = GetCurrentWorld()->GetSingleSelection();
				pSelected->SetDrawnAxis(!pSelected->fn_bIsAxisDrawn());
				fn_vUpdateAll(E_mc_JustDraw);
				return;

			case C_ui_ShowBoundingV:
				pSelected = GetCurrentWorld()->GetSingleSelection();
				if (pSelected->GetDrawingFlag() == E_df_BoundingV)
					pSelected->SetDrawingFlag(E_df_Normal);
				else
					pSelected->SetDrawingFlag(E_df_BoundingV);
				fn_vUpdateAll(E_mc_JustDraw);
				return;

			default:
				break;
		}
	}
	// other entries
	m_oPopUpMenu._OnCommand(IDCmdMsg);
}

/*===========================================================================
*		Description:	define submenu
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
BOOL CPA_Interface::fn_bDefineSubMenu (EDT_SubMenu *p_oEDTSubMenu)
{
//CPA2 Corneliu Babiuc 07-05-98
	CString csMenuDescString, csMenuAccelString;
//END CPA2 Corneliu Babiuc 07-05-98

	if (p_oEDTSubMenu->GetSubMenuType() == C_SubMenuEdit)
    {
// Begin Silviu Simen Select by sector and type
		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Select by Sector"));
		csMenuDescString.Format("Select by Sector/Type\t%s", csMenuAccelString);
		p_oEDTSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_SelectSectorType, FALSE, TRUE);
// End Silviu Simen Select by sector and type
		// selection
		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Unselect all"));
		csMenuDescString.Format("Unselect all\t%s", csMenuAccelString);
		p_oEDTSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_UnselectAll, FALSE, TRUE);
//CPA2 Corneliu Babiuc 19-05-98
		// full selection
		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Full selection"));
		csMenuDescString.Format("Full selection\t%s", csMenuAccelString);
		p_oEDTSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_FullSelect, m_bFullSelect, TRUE);

		// delta selection
		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Delta selection"));
		csMenuDescString.Format("Delta selection\t%s", csMenuAccelString);
		p_oEDTSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_DeltaSelect, m_bDeltaSelect, TRUE);
//END CPA2 Corneliu Babiuc 19-05-98
	}

	if (p_oEDTSubMenu->GetSubMenuType() == C_SubMenuTool)
    {
		p_oEDTSubMenu->AddAnEntry(NULL, "Recompute All Bounding Volumes", C_ui_ComputeBV, FALSE, TRUE);
		p_oEDTSubMenu->AddAnEntry(NULL, "Coherence Manager", C_ui_CoherenceMngr, FALSE, TRUE);
		p_oEDTSubMenu->AddASeparator();
//CPA2 Corneliu Babiuc 07-05-98
		csMenuAccelString = M_GetMainApp()->mp_oAppKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Options"));
		csMenuDescString.Format("Options\t%s", csMenuAccelString);
		p_oEDTSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_Option, FALSE, TRUE);
//END CPA2 Corneliu Babiuc 07-05-98
		return TRUE;
	}

	if (p_oEDTSubMenu->GetSubMenuType() == C_SubMenu3DView)
    {
		CPA_CameraDLLBase		*p_oCameraInterface = ((DEV_ViewPort3D *) GetMultiDevice3D()->GetFocusDevice()->GetViewPort())->GetCameraInterface();
		tdeDisplayReferential	eDisplayModeAxis	= p_oCameraInterface ? p_oCameraInterface -> GetReferentialDisplayMode() : DisplayNone ;

        // appearance
		EDT_SubMenu *p_oSubMenu = p_oEDTSubMenu->fn_p_oGetNewSubMenu("Appearance");

		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Normal World"));
		csMenuDescString.Format("Normal\t%s", csMenuAccelString);
		p_oSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_Textured, fn_bWorldIsTextured(), TRUE);

		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Grided World"));
		csMenuDescString.Format("Grided\t%s", csMenuAccelString);
		p_oSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_Grided, fn_bWorldIsGrided(), TRUE);

		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Wired World"));
		csMenuDescString.Format("Wired\t%s", csMenuAccelString);
		p_oSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_Wired, fn_bWorldIsWired(), TRUE);

        p_oEDTSubMenu->AddASubMenu(p_oSubMenu);

		// display
		p_oSubMenu = p_oEDTSubMenu->fn_p_oGetNewSubMenu("Display");

		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("World Sectors"));
		csMenuDescString.Format("World Sectors\t%s", csMenuAccelString);
		p_oSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_World, (GetSpecificInterface()->GetDisplayMode() == E_dm_DrawWorld), TRUE);

		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Visible Sectors"));
		csMenuDescString.Format("Visible Sectors\t%s", csMenuAccelString);
		p_oSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_Visible, (GetSpecificInterface()->GetDisplayMode() == E_dm_DrawVisibleSectors), TRUE);

		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Current Sector"));
		csMenuDescString.Format("Current Sector\t%s", csMenuAccelString);
		p_oSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_Current, (GetSpecificInterface()->GetDisplayMode() == E_dm_DrawOnlyCurrentSector), TRUE);
		// collision map
		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Collision Map"));
		csMenuDescString.Format("Collision Map\t%s", csMenuAccelString);
		p_oSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_CollisionMap, (GetSpecificInterface()->GetDisplayMode() == E_dm_DrawCollisionMap), TRUE);
        p_oEDTSubMenu->AddASubMenu(p_oSubMenu);

		// bounding volume
		p_oSubMenu = p_oEDTSubMenu->fn_p_oGetNewSubMenu("Bounding Volume");

		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Sectors BV"));
		csMenuDescString.Format("Sectors\t%s", csMenuAccelString);
		p_oSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_SectorsBV, (m_eBVMode == E_bv_Sectors), TRUE);

		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Actors BV"));
		csMenuDescString.Format("Actors\t%s", csMenuAccelString);
		p_oSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_ActorsBV, (m_eBVMode == E_bv_Actors), TRUE);

		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Objects BV"));
		csMenuDescString.Format("Objects\t%s", csMenuAccelString);
		p_oSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_ObjectsBV, (m_eBVMode == E_bv_Objects), TRUE);
 
		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("No BV"));
		csMenuDescString.Format("None\t%s", csMenuAccelString);
		p_oSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_NoBV, (m_eBVMode == E_bv_None), TRUE);

		p_oEDTSubMenu->AddASubMenu(p_oSubMenu);

		// axis
		p_oSubMenu = p_oEDTSubMenu->fn_p_oGetNewSubMenu("Axis");

		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Show Axis Left"));
		csMenuDescString.Format("Down Left Corner\t%s", csMenuAccelString);
		p_oSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_DownLeftAxis, (eDisplayModeAxis==DisplayDownLeft), TRUE);

		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Show Axis Right"));
		csMenuDescString.Format("Down Right Corner\t%s", csMenuAccelString);
		p_oSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_DownRightAxis, (eDisplayModeAxis==DisplayDownRight), TRUE);

		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Show No Axis"));
		csMenuDescString.Format("None\t%s", csMenuAccelString);
		p_oSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_NoAxis, (eDisplayModeAxis==DisplayNone), TRUE);

        p_oEDTSubMenu->AddASubMenu(p_oSubMenu);

		// centers
		p_oSubMenu = p_oEDTSubMenu->fn_p_oGetNewSubMenu("Objects Center");

		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Show Main Centers"));
		csMenuDescString.Format("Instances\t%s", csMenuAccelString);
		p_oSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_MainCenters, (m_iShowCenter == 2), TRUE);

		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Show All Centers"));
		csMenuDescString.Format("Objects\t%s", csMenuAccelString);
		p_oSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_AllCenters, (m_iShowCenter == 1), TRUE);
  
		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Show No Center"));
		csMenuDescString.Format("None\t%s", csMenuAccelString);
		p_oSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_NoCenter, (m_iShowCenter == 0), TRUE);

		p_oEDTSubMenu->AddASubMenu(p_oSubMenu);

		// general entries
		p_oEDTSubMenu->AddASeparator();

		CPA_DLLBase *p_oSectorInterface = GetMainWorld()->GetObjectDLLWithName(C_szDLLSectorName);
		p_oSectorInterface->fn_bDefineSubMenu(p_oEDTSubMenu);

		if (!m_bScaleObject)
		{
			csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Scale Editor Objects"));
			csMenuDescString.Format("Scale pure editor objects\t%s", csMenuAccelString);
			p_oEDTSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString,  C_ui_ScaleAction );
		}
		else
		{
			csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Scale Editor Objects"));
			csMenuDescString.Format("Disable the scale\t%s", csMenuAccelString);
			p_oEDTSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString,  C_ui_ReScaleAction ); 
		}
		
		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Compute Centers"));
		csMenuDescString.Format("Compute Objects Centers\t%s", csMenuAccelString);
		p_oEDTSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_ComputeCentersAction, FALSE, TRUE);

		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Cancel all drawing flags"));
		csMenuDescString.Format("Cancel all drawing flags\t%s", csMenuAccelString);
		p_oEDTSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_CancelDrawingAction, FALSE, TRUE);

		// save
		p_oEDTSubMenu->AddASeparator();

		csMenuAccelString = M_GetMainApp()->mp_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Select Background Color"));
		csMenuDescString.Format("Select Background Color\t%s", csMenuAccelString);
		p_oEDTSubMenu->AddAnEntry(NULL, (char*)(LPCTSTR)csMenuDescString, C_ui_BKColors, FALSE, TRUE);

		p_oEDTSubMenu->AddAnEntry(NULL, "Save Display Mode", C_ui_SaveDisplay, FALSE, TRUE);
		return TRUE;
	}

	return FALSE;

}

/*===========================================================================
*		Description:	submenu command
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
void CPA_Interface::_OnSubMenuCommand (EDT_SubMenu *p_oEDTSubMenu,UINT uiMsgID)
{
	if (p_oEDTSubMenu->GetSubMenuType() == C_SubMenuEdit)
    {
		switch (uiMsgID)
		{
			// selection
			case C_ui_DeltaSelect:
				SetDeltaSelect(!m_bDeltaSelect);
				GetFrameBase()->m_oGeneralDialogBar.fn_vUpdateDeltaSelect(m_bDeltaSelect);
				return;
			case C_ui_FullSelect:
				SetFullSelect(!m_bFullSelect);
				fn_vUpdateAll(E_mc_UpdateDialog);
				GetFrameBase()->m_oGeneralDialogBar.fn_vUpdateFullSelect(m_bFullSelect);
				return;
			case C_ui_UnselectAll:
				fn_vCancelCurrentSelection();
				return;
// Begin Silviu Simen Select by sector and type
			case C_ui_SelectSectorType:
				SelectBySector();
				return;
// End Silviu Simen Select by sector and type
			default:
				return;
		}
	}

	if (p_oEDTSubMenu->GetSubMenuType() == C_SubMenuTool)
	{
		switch (uiMsgID)
		{
			case C_ui_ComputeBV:
				fn_vComputeAllBound();
				return;
			case C_ui_CoherenceMngr:
				g_oCoherenceManager.m_fn_vShowIncoherence();
				return;
			case C_ui_Option:
				m_oDialogOption.fn_vDoDialog(this);
				return;
			default:
				return;
		}
	}

	if (p_oEDTSubMenu->GetSubMenuType() == C_SubMenu3DView)
	{
		CPA_CameraDLLBase *p_oCameraInterface = ((DEV_ViewPort3D *) GetMultiDevice3D()->GetFocusDevice()->GetViewPort())->GetCameraInterface();

		switch (uiMsgID)
		{
			// appearance
			case C_ui_Textured:
				fn_vChangeWorldMask(GLI_C_lIsTextured, !fn_bWorldIsTextured());
				return;
			case C_ui_Grided:
				fn_vChangeWorldMask(GLI_C_lIsNotGrided, fn_bWorldIsGrided());
				return;
			case C_ui_Wired:
				fn_vChangeWorldMask(GLI_C_lIsNotWired, fn_bWorldIsWired());
				return;

			// display
			case C_ui_World:
				GetSpecificInterface()->fn_vOnChangeDisplayMode(E_dm_DrawWorld);
				return;
			case C_ui_Visible:
				GetSpecificInterface()->fn_vOnChangeDisplayMode(E_dm_DrawVisibleSectors);
				return;
			case C_ui_Current:
				GetSpecificInterface()->fn_vOnChangeDisplayMode(E_dm_DrawOnlyCurrentSector);
				return;

			case C_ui_CollisionMap:
				GetSpecificInterface()->fn_vOnChangeDisplayMode(E_dm_DrawCollisionMap);
				return;

			// bounding volumes
			case C_ui_NoBV:
				fn_vSetBVMode(E_bv_None);
				return;
			case C_ui_SectorsBV:
				fn_vSetBVMode(E_bv_Sectors);
				return;
			case C_ui_ActorsBV:
				fn_vSetBVMode(E_bv_Actors);
				return;
			case C_ui_ObjectsBV:
				fn_vSetBVMode(E_bv_Objects);
				return;

			// axis
			case C_ui_NoAxis:
				p_oCameraInterface -> SetReferentialDisplayMode( DisplayNone );
				return;
			case C_ui_DownRightAxis:
				p_oCameraInterface -> SetReferentialDisplayMode( DisplayDownRight );
				return;
			case C_ui_DownLeftAxis:
				p_oCameraInterface -> SetReferentialDisplayMode( DisplayDownLeft );
				return;

			// centers
			case C_ui_NoCenter:
				SetShowcenter(0);
				GetFrameBase()->m_oGeneralDialogBar.m_oDisplayToolbar.SetButton(IDCB_NORMAL);
				return;
			case C_ui_MainCenters:
				SetShowcenter(2);
				GetFrameBase()->m_oGeneralDialogBar.m_oDisplayToolbar.SetButton(IDCB_MAINCENTERS);
				return;
			case C_ui_AllCenters:
				SetShowcenter(1);
				GetFrameBase()->m_oGeneralDialogBar.m_oDisplayToolbar.SetButton(IDCB_ALLCENTERS);
				return;

			// background
			case C_ui_BKColors:	
			{
				CColorDialog	oColorDialog;
				COLORREF		stColor;

				// display color dialog
				if (oColorDialog.DoModal() == IDOK)
				{
					// get selected color
					stColor = oColorDialog.GetColor(); 
					// update controls
					GetMultiDevice()->SetBackgroundColor(stColor);
				}
				return;
			}

			case C_ui_SaveDisplay:
				fn_vSaveDisplayMode();
				return;
			
			// cancel drawing
			case C_ui_CancelDrawingAction:
				fn_vCancelAllDrawingFlags();
				fn_vUpdateAll(E_mc_JustDraw);
				return;

			// compute centers
			case C_ui_ComputeCentersAction:
				fn_vComputeSuperObjectsCenters(NULL);
				fn_vUpdateAll(E_mc_JustDraw);
				return;

			// scale pure editor objects
			case C_ui_ScaleAction:
				fn_vScale();
				fn_vUpdatePositions();
				fn_vScale();
				m_bScaleObject = TRUE;
				fn_vUpdateAll(E_mc_JustDraw);
				return;
			case C_ui_ReScaleAction:
				fn_vReScale();
				m_bScaleObject = FALSE;
				fn_vUpdateAll(E_mc_JustDraw);
				return;

			default:
				return;
		}
	}
}

//#################################################################################
// PROTECTED FUNCTIONS
//#################################################################################

/*===========================================================================
*		Description:	check if object can be selected
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
BOOL CPA_Interface::fn_bCanBeSelected (CPA_SuperObject *pEdObj, CString csTypeName, BOOL bCheckSelect)
{
	// type must be valid
	if ((csTypeName != "All Types") && (pEdObj->GetRealTypeName() != csTypeName) )
		return FALSE;

	// non editable childs can't be selected
	if ((pEdObj->fn_bIsEditProtected())||(!pEdObj->GetObjectDLL()))
		return FALSE;

	// drawing flag
	if (!fn_bIgnoreFlags() && (pEdObj->GetDrawingFlag() != E_df_Normal) && (pEdObj->GetDrawingFlag() != E_df_BoundingV)) 
		return FALSE;

	// is object already selected ?
	if ((bCheckSelect)&&(GetPreviousSelection(pEdObj)))
		return FALSE;

	// object can be selected
	return TRUE;
}


/*===========================================================================
*		Description:	dispatch message when selection changes
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vSendMessageSelect (CPA_SuperObject *pEdObj, tdeTypeModif eType)
{
	CPA_ToolDLLBase *pDLLTool;
	CPA_DLLBase		*pCurrentEditor;
	POSITION		pos;

	pCurrentEditor = (CPA_DLLBase *) m_p_oMainWorld->GetCurrentEditor();

	// current editor
	if (!m_p_oEditor->fn_bIsCurrentEditor())
		pCurrentEditor->fn_vOnSelect(pEdObj, eType, C_AsCurrentEditor);
	// Object DLL
	if (pEdObj->GetObjectDLL())
		pEdObj->GetObjectDLL()->fn_vOnSelect(pEdObj, eType, C_AsConcernedDLL);
	// owner DLL
	if (pEdObj->GetSuperObjectOwner())
		pEdObj->GetSuperObjectOwner()->GetObjectDLL()->fn_vOnSelect(pEdObj, eType, C_AsChildOwner);
	// Tool DLLs
	for (pDLLTool = m_p_oMainWorld->GetToolDLLReceivingEvtEditorMsg()->GetHeadElement(pos); pDLLTool;
		 pDLLTool = m_p_oMainWorld->GetToolDLLReceivingEvtEditorMsg()->GetNextElement(pos))
	{
		if (pDLLTool != pCurrentEditor)
			pDLLTool->fn_vOnSelect(pEdObj, eType, C_AsToolDLL);
	}
}



/*===========================================================================
*		Description:	change pyramid Depth (OnMouseMove)
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:        Author: Yann Le Tensorer
*=========================================================================*/
void CPA_Interface::fn_vChangePyramidDepth (tdstMousePos *p_stPos)
{
	DEV_ViewPort	*ViewPort;
	POINT			stTmpPoint;
	MSG				Message;
	char			szMessage[256], szMode[20];

	ViewPort =  (DEV_ViewPort3D *) GetMultiDevice()->GetFocusDevice()->GetViewPort();

	SetCursorPos(m_stMouseFixPoint.x ,m_stMouseFixPoint.y);

	// Delete the MouseMove message sent by SetCursorPos
	while (PeekMessage (& Message , NULL , WM_MOUSEMOVE , WM_MOUSEMOVE , PM_REMOVE)) ;

	// change z accordin to vertical mouse move
	stTmpPoint.x=MTH_M_xRealToLong(p_stPos->stPos.x/*2D.xX*/);
	stTmpPoint.y=MTH_M_xRealToLong(p_stPos->stPos.y/*2D.xY*/);
//	ViewPort->ClientToScreen(&stTmpPoint);
	stTmpPoint.x=stTmpPoint.x-m_stMouseFixPoint.x;
	stTmpPoint.y=stTmpPoint.y-m_stMouseFixPoint.y;
	m_dfZFarSelectionFrame=m_dfZFarSelectionFrame-(MTH_M_xLongToReal(stTmpPoint.y)/100.0);
	if (m_dfZFarSelectionFrame<=m_dfZNearSelectionFrame)
		m_dfZFarSelectionFrame=m_dfZNearSelectionFrame+0.1;

	// change mouse 2D coordinates to previous position
	stTmpPoint=m_stMouseFixPoint;
//	ViewPort->ScreenToClient(&stTmpPoint);
	p_stPos->stPos.x/*2D.xX*/= stTmpPoint.x;
	p_stPos->stPos.y/*2D.xY*/= stTmpPoint.y;

	// message in status bar
	strcpy(szMode, m_bRealTime ? "REAL TIME" : "STATIC");
	if (!m_bFixedDepth) 
		sprintf(szMessage, "Pyramid Selection : %s, FREE depth : %3.2f m (use 'W' to change the depth)", szMode, m_dfZFarSelectionFrame);
	
	M_GetMainWnd()->UpdateStatus(szMessage, C_STATUSPANE_INFOS, C_STATUS_NORMAL);

}

/*===========================================================================
*		Description:	create selection frame (OnMouseMove)
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:        Author: Yann Le Tensorer
*=========================================================================*/
void CPA_Interface::fn_vCreateSelectionFrame (tdstMousePos *p_stPos)
{
	DEV_ViewPort	*ViewPort;

	ViewPort =  (DEV_ViewPort3D *) GetMultiDevice()->GetFocusDevice()->GetViewPort();

	if (p_stPos->stPos2D.xX<=m_stSelectionStartVertex.stPos2D.xX && p_stPos->stPos2D.xY<=m_stSelectionStartVertex.stPos2D.xY)
	{/*		^
			 \
			  \ */
		m_stSelectionVertexTopLeft.stPos2D.xX=p_stPos->stPos2D.xX;
		m_stSelectionVertexTopLeft.stPos2D.xY=p_stPos->stPos2D.xY;
		m_stSelectionVertexBottomRight.stPos2D.xX=m_stSelectionStartVertex.stPos2D.xX;
		m_stSelectionVertexBottomRight.stPos2D.xY=m_stSelectionStartVertex.stPos2D.xY;
	}

	else
	if (p_stPos->stPos2D.xX<=m_stSelectionStartVertex.stPos2D.xX && p_stPos->stPos2D.xY>=m_stSelectionStartVertex.stPos2D.xY)
	{//		  /
	//		 /
	//		^
		m_stSelectionVertexTopLeft.stPos2D.xX=p_stPos->stPos2D.xX;
		m_stSelectionVertexTopLeft.stPos2D.xY=m_stSelectionStartVertex.stPos2D.xY;
		m_stSelectionVertexBottomRight.stPos2D.xX=m_stSelectionStartVertex.stPos2D.xX;
		m_stSelectionVertexBottomRight.stPos2D.xY=p_stPos->stPos2D.xY;
	}

	else
	if (p_stPos->stPos2D.xX>=m_stSelectionStartVertex.stPos2D.xX && p_stPos->stPos2D.xY>=m_stSelectionStartVertex.stPos2D.xY)
	{//		\
	//		 \
	//		  ^
		m_stSelectionVertexBottomRight=*p_stPos;
		m_stSelectionVertexTopLeft=m_stSelectionStartVertex;
	}

	else
	if (p_stPos->stPos2D.xX>=m_stSelectionStartVertex.stPos2D.xX && p_stPos->stPos2D.xY<=m_stSelectionStartVertex.stPos2D.xY)
	{//		  ^
	//		 /
	//		/
		m_stSelectionVertexTopLeft.stPos2D.xX=m_stSelectionStartVertex.stPos2D.xX;
		m_stSelectionVertexTopLeft.stPos2D.xY=p_stPos->stPos2D.xY;
		m_stSelectionVertexBottomRight.stPos2D.xX=p_stPos->stPos2D.xX;
		m_stSelectionVertexBottomRight.stPos2D.xY=m_stSelectionStartVertex.stPos2D.xY;
	}

	m_stSelectionVertexTopRight.stPos2D.xX=m_stSelectionVertexBottomRight.stPos2D.xX;
	m_stSelectionVertexTopRight.stPos2D.xY=m_stSelectionVertexTopLeft.stPos2D.xY;
	m_stSelectionVertexBottomLeft.stPos2D.xX=m_stSelectionVertexTopLeft.stPos2D.xX;
	m_stSelectionVertexBottomLeft.stPos2D.xY=m_stSelectionVertexBottomRight.stPos2D.xY;

	PIC_vMouse3DScreen(ViewPort->m_hDisplayDevice,ViewPort->m_hDisplayViewport,&m_stSelectionVertexBottomRight.stPos2D,&m_stSelectionVertexBottomRight.stPos3D);
	PIC_vMouse3DScreen(ViewPort->m_hDisplayDevice,ViewPort->m_hDisplayViewport,&m_stSelectionVertexBottomLeft.stPos2D,&m_stSelectionVertexBottomLeft.stPos3D);
	PIC_vMouse3DScreen(ViewPort->m_hDisplayDevice,ViewPort->m_hDisplayViewport,&m_stSelectionVertexTopRight.stPos2D,&m_stSelectionVertexTopRight.stPos3D);
	PIC_vMouse3DScreen(ViewPort->m_hDisplayDevice,ViewPort->m_hDisplayViewport,&m_stSelectionVertexTopLeft.stPos2D,&m_stSelectionVertexTopLeft.stPos3D);

	m_stFarSelectionVertexBottomRight=m_stSelectionVertexBottomRight;
	m_stFarSelectionVertexBottomLeft=m_stSelectionVertexBottomLeft;
	m_stFarSelectionVertexTopRight=m_stSelectionVertexTopRight;
	m_stFarSelectionVertexTopLeft=m_stSelectionVertexTopLeft;

	float saveZ = (float)m_dfZFarSelectionFrame;
	if (m_bFixedDepth) 
		m_dfZFarSelectionFrame = m_dfZNearSelectionFrame + GetPyramidalDepth();

	fn_vSetZCamera(	ViewPort->m_hDisplayDevice,ViewPort->m_hDisplayViewport,
							&m_stFarSelectionVertexBottomRight.stPos3D,
							&m_stFarSelectionVertexBottomRight.stPos3D,
							m_dfZFarSelectionFrame);
	fn_vSetZCamera(	ViewPort->m_hDisplayDevice,ViewPort->m_hDisplayViewport,
							&m_stFarSelectionVertexTopRight.stPos3D,
							&m_stFarSelectionVertexTopRight.stPos3D,
							m_dfZFarSelectionFrame);
	fn_vSetZCamera(	ViewPort->m_hDisplayDevice,ViewPort->m_hDisplayViewport,
							&m_stFarSelectionVertexTopLeft.stPos3D,
							&m_stFarSelectionVertexTopLeft.stPos3D,
							m_dfZFarSelectionFrame);
	fn_vSetZCamera(	ViewPort->m_hDisplayDevice,ViewPort->m_hDisplayViewport,
							&m_stFarSelectionVertexBottomLeft.stPos3D,
							&m_stFarSelectionVertexBottomLeft.stPos3D,
							m_dfZFarSelectionFrame);

	m_dfZFarSelectionFrame = saveZ;

	// Calculate normals
	fn_vCalculateSelectionPyramidNormals();

	// select objects
	if(m_bRealTime)
		fn_vSelectObjectsInPyramid();

	// pyramid is visible only if volume > 0
	if (
		(m_stSelectionVertexTopLeft.stPos2D.xX!=m_stSelectionVertexBottomRight.stPos2D.xX) &&
		(m_stSelectionVertexTopLeft.stPos2D.xY!=m_stSelectionVertexBottomRight.stPos2D.xY)
	   )
		 m_bSelectionFrameVisible=TRUE;
	else
		m_bSelectionFrameVisible=FALSE;
}


/*===========================================================================
*		Description:	calculate all normals (6 faces).
*		Creation date:
*		Author:			Yann Le Tensorer
*---------------------------------------------------------------------------
*		Revision date:        Author:
*=========================================================================*/
void CPA_Interface::fn_vCalculateSelectionPyramidNormals()
{
	MTH3D_tdstVector		Vect1;
	MTH3D_tdstVector		Vect2;

	MTH3D_M_vSubVector( &Vect1,&m_stSelectionVertexTopRight.stPos3D ,&m_stSelectionVertexTopLeft.stPos3D );
	MTH3D_M_vSubVector( &Vect2,&m_stFarSelectionVertexTopLeft.stPos3D ,&m_stSelectionVertexTopLeft.stPos3D );
	MTH3D_M_vCrossProductVector(&m_stNormaleTop,&Vect1,&Vect2);

	MTH3D_M_vSubVector( &Vect1,&m_stFarSelectionVertexBottomRight.stPos3D ,&m_stFarSelectionVertexBottomLeft.stPos3D );
	MTH3D_M_vSubVector( &Vect2,&m_stSelectionVertexBottomLeft.stPos3D ,&m_stFarSelectionVertexBottomLeft.stPos3D );
	MTH3D_M_vCrossProductVector(&m_stNormaleBottom,&Vect1,&Vect2);

	MTH3D_M_vSubVector( &Vect1,&m_stSelectionVertexBottomRight.stPos3D ,&m_stSelectionVertexTopRight.stPos3D );
	MTH3D_M_vSubVector( &Vect2,&m_stFarSelectionVertexTopRight.stPos3D ,&m_stSelectionVertexTopRight.stPos3D );
	MTH3D_M_vCrossProductVector(&m_stNormaleRight,&Vect1,&Vect2);

	MTH3D_M_vSubVector( &Vect1,&m_stFarSelectionVertexBottomLeft.stPos3D ,&m_stFarSelectionVertexTopLeft.stPos3D );
	MTH3D_M_vSubVector( &Vect2,&m_stSelectionVertexTopLeft.stPos3D ,&m_stFarSelectionVertexTopLeft.stPos3D );
	MTH3D_M_vCrossProductVector(&m_stNormaleLeft,&Vect1,&Vect2);

	MTH3D_M_vSubVector( &Vect1,&m_stSelectionVertexBottomLeft.stPos3D ,&m_stSelectionVertexTopLeft.stPos3D );
	MTH3D_M_vSubVector( &Vect2,&m_stSelectionVertexTopRight.stPos3D ,&m_stSelectionVertexTopLeft.stPos3D );
	MTH3D_M_vCrossProductVector(&m_stNormaleNear,&Vect1,&Vect2);

	MTH3D_M_vSubVector( &Vect1,&m_stFarSelectionVertexBottomRight.stPos3D ,&m_stFarSelectionVertexTopRight.stPos3D );
	MTH3D_M_vSubVector( &Vect2,&m_stFarSelectionVertexTopLeft.stPos3D ,&m_stFarSelectionVertexTopRight.stPos3D );
	MTH3D_M_vCrossProductVector(&m_stNormaleFar,&Vect1,&Vect2);
}


/*===========================================================================
*		Description:	check if vertex is in selection pyramid.
*		Creation date:
*		Author:			Yann Le Tensorer
*---------------------------------------------------------------------------
*		Revision date:        Author:
*=========================================================================*/
BOOL CPA_Interface::fn_bIsVertexInSelectionPyramid(MTH3D_tdstVector *p_stSrcVertex)
{
	MTH3D_tdstVector	vect1;
	double				ProdScal;

	MTH3D_M_vSubVector(&vect1,&m_stFarSelectionVertexTopLeft.stPos3D,p_stSrcVertex);
	ProdScal=MTH3D_M_xDotProductVector(&vect1,&m_stNormaleFar);
	if (ProdScal<=0) return FALSE;
	ProdScal=MTH3D_M_xDotProductVector(&vect1,&m_stNormaleLeft);
	if (ProdScal<=0) return FALSE;
	ProdScal=MTH3D_M_xDotProductVector(&vect1,&m_stNormaleTop);
	if (ProdScal<=0) return FALSE;

	MTH3D_M_vSubVector(&vect1,&m_stSelectionVertexBottomRight.stPos3D,p_stSrcVertex);
	ProdScal=MTH3D_M_xDotProductVector(&vect1,&m_stNormaleBottom);
	if (ProdScal<=0) return FALSE;
	ProdScal=MTH3D_M_xDotProductVector(&vect1,&m_stNormaleRight);
	if (ProdScal<=0) return FALSE;
	ProdScal=MTH3D_M_xDotProductVector(&vect1,&m_stNormaleNear);
	if (ProdScal<=0) return FALSE;

	return TRUE;
}


/*===========================================================================
*		Description:	Change z : world coordinate -> camera coordinate, 
*						keep x & y on screen.
*		Creation date:
*		Author:			Yann Le Tensorer
*---------------------------------------------------------------------------
*		Revision date:        Author:
*=========================================================================*/
void CPA_Interface::fn_vSetZCamera(GLD_tdhDevice hDev,
								GLD_tdhViewport hVp,
								MTH3D_tdstVector *p_stSrcVertex,
								MTH3D_tdstVector *p_stDstVertex,
								double z)
{
	GLI_tdstSpecificAttributesFor3D *p_stSpecAttrib3D;
	GLD_tdstViewportAttributes      stViewAttrib;
	struct GLI_tdstCamera_			*p_stCam;
	POS_tdstCompletePosition		stMatrix, stInvMatrix ;
	MTH3D_tdstVector				stTmpVertex;
	double							z1;

	POS_fn_vSetIdentityMatrix(&stMatrix);
	POS_fn_vSetIdentityMatrix(&stInvMatrix);

	if ( !GLD_bGetViewportAttributes( hDev, hVp, &stViewAttrib ) )
		return;
	p_stSpecAttrib3D = (GLI_tdstSpecificAttributesFor3D *)stViewAttrib.p_vSpecificToXD;
	p_stCam = p_stSpecAttrib3D->p_stCam;


	// camera coordinates
	GLI_xGetCameraMatrix ( p_stCam , &stMatrix );
	POS_fn_vMulMatrixVertex( &stTmpVertex , &stMatrix , p_stSrcVertex );

	// z1 = initial Z (camera coords.)
	z1=stTmpVertex.xZ;
	// z = new Z (camera coords.)
	stTmpVertex.xZ=(float) z;
	// calculate x&y (same projection on screen)
	stTmpVertex.xX=(float) (z*stTmpVertex.xX/z1);
	stTmpVertex.xY=(float) (z*stTmpVertex.xY/z1);

	// World coordinates
	POS_fn_vInvertMatrix ( &stInvMatrix , &stMatrix );
	POS_fn_vMulMatrixVertex( p_stDstVertex , &stInvMatrix , &stTmpVertex );
}




/*===========================================================================
*		Description:	Select object in pyramid.
*		Creation date:
*		Author:			Yann Le Tensorer
*---------------------------------------------------------------------------
*		Revision date:        Author: Shaitan
*=========================================================================*/
void CPA_Interface::fn_vSelectObjectsInPyramid()
{
	GEO_tdxHandleToMatrix	h_stObjectGlobalMatrix;
	MTH3D_tdstVector		stPosObject;
	CPA_SuperObject			*pElem;
	CPA_SuperObject			*pPreviousSelection;
	POSITION				pos = NULL;

	// single selection : cancel current one
	if (!m_p_oEditor->fn_bIsMultiSelectModeEnabled())
		fn_vCancelCurrentSelection(FALSE);

	// select all objects in pyramid
	for (pElem = GetCurrentWorld()->GetListAllObjects()->GetHeadElement(pos); pElem;
		 pElem = GetCurrentWorld()->GetListAllObjects()->GetNextElement(pos))
	{
	    h_stObjectGlobalMatrix = HIE_fn_hGetSuperObjectGlobalMatrix(pElem->GetStruct());
		POS_fn_vGetTranslationVector(h_stObjectGlobalMatrix,&stPosObject);
		if (fn_bIsVertexInSelectionPyramid(&stPosObject))
		{
			if (fn_bCanSelect(pElem) == C_Accept)
			{
				// object already selected ?
				pPreviousSelection = GetPreviousSelection(pElem);
				if (!pPreviousSelection)
					fn_vAddSelectedObject(pElem, FALSE);
			}
		}
	}
	fn_vUpdateAll(E_mc_UpdateSelection);
}

/*===========================================================================
*		Description:	set all drawing flags
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                Author:
*=========================================================================*/
void CPA_Interface::SetDrawingFlags (CPA_SuperObject *pEdObj, tdeDrawingFlag eNewFlag)
{
	CPA_SuperObject *pChild;

	// set flag
	pEdObj->CPA_SuperObjectBase::SetDrawingFlag(eNewFlag);
	// next level (recursive function)
	for (pChild = pEdObj->GetSuperObjectFirstChild(); pChild;
		pChild = pEdObj->GetSuperObjectNextChild(pChild))
		SetDrawingFlags(pChild, eNewFlag);
}

/*===========================================================================
*		Description:	center object
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                Author:
*=========================================================================*/
void CPA_Interface::fn_vCenterOnObject (CPA_SuperObject *pTarget, BOOL bZoom, BOOL bKeepTargeted)
{
	DEV_ViewPort3D		*pCurViewport;
	CPA_CameraDLLBase	*p_oCameraInterface;
	CPA_BaseObject		*p_oCamera;
	BOOL				bWasNotTargeted;

	// get camera 
	pCurViewport = (DEV_ViewPort3D *) GetMultiDevice()->GetFocusDevice()->GetViewPort();
	p_oCameraInterface = pCurViewport->GetCameraInterface();
    if (! p_oCameraInterface)  return;
	p_oCamera = pCurViewport->GetCamera();
    if (! p_oCamera)  return;
	
	bWasNotTargeted = (p_oCameraInterface->GetTargetType(p_oCamera) == tNone);

	// target on super-object
	p_oCameraInterface->SetTargetSuperObject(p_oCamera,pTarget);
	p_oCameraInterface->SetTargetType(p_oCamera,tSuperObject);
	p_oCameraInterface->Update(p_oCamera);
	// zoom
	if (bZoom)
	{
		p_oCameraInterface->ZoomOnTarget(p_oCamera, pTarget);
		p_oCameraInterface->Update(p_oCamera);
	}
	// reinit camera mode
	if ((!bKeepTargeted)&&(bWasNotTargeted)) 
	{
		p_oCameraInterface->SetTargetType(p_oCamera,tNone);
		p_oCameraInterface->Update(p_oCamera);
	}

}

/*===========================================================================
*		Description:	center object
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                Author:
*=========================================================================*/
void CPA_Interface::fn_vZoomOnObject (CPA_SuperObject *pTarget)
{
	DEV_ViewPort3D		*pCurViewport;
	CPA_CameraDLLBase	*p_oCameraInterface;
	CPA_BaseObject		*p_oCamera;

	// get camera 
	pCurViewport = (DEV_ViewPort3D *) GetMultiDevice()->GetFocusDevice()->GetViewPort();
	p_oCameraInterface = pCurViewport->GetCameraInterface();
    if (! p_oCameraInterface)  return;
	p_oCamera = pCurViewport->GetCamera();
    if (! p_oCamera)  return;
	
	// zoom
	p_oCameraInterface->ZoomOnTarget(p_oCamera, pTarget);
	p_oCameraInterface->Update(p_oCamera);
}

/*===========================================================================
*		Description:	set auto target
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                Author:
*=========================================================================*/
void CPA_Interface::SetAutoTarget (BOOL bAutoTarget)
{
	DEV_ViewPort3D		*pCurViewport;
	CPA_CameraDLLBase	*p_oCameraInterface;
	CPA_BaseObject		*p_oCamera;

	// get camera 
	pCurViewport = (DEV_ViewPort3D *) GetMultiDevice()->GetFocusDevice()->GetViewPort();
	p_oCameraInterface = pCurViewport->GetCameraInterface();
	p_oCamera = pCurViewport->GetCamera();
    if (!p_oCameraInterface || ! p_oCamera)  
		return;
	
	if (m_bAutoTarget != bAutoTarget)
	{
		// update flag
		m_bAutoTarget = bAutoTarget;
		// update camera
		if (m_bAutoTarget)
		{
			// save previous mode
			m_ePreviousMode = p_oCameraInterface->GetTargetType(p_oCamera);
			// if necessary , target selection
			if (GetCurrentWorld()->GetCountSelected() == 1)
				fn_vCenterOnObject(GetCurrentWorld()->GetSingleSelection(), FALSE, TRUE);
		}
		else
		{
			p_oCameraInterface->SetTargetType(p_oCamera,m_ePreviousMode);
			p_oCameraInterface->Update(p_oCamera);
		}
		// update dialogbar
		GetFrameBase()->m_oGeneralDialogBar.fn_vUpdateAutoTarget(m_bAutoTarget);
	}
}


/*===========================================================================
*		Description:	set auto zoom
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                Author:
*=========================================================================*/
void CPA_Interface::SetAutoZoom (BOOL bAutoZoom)
{
	DEV_ViewPort3D		*pCurViewport;
	CPA_CameraDLLBase	*p_oCameraInterface;
	CPA_BaseObject		*p_oCamera;

	// get camera 
	pCurViewport = (DEV_ViewPort3D *) GetMultiDevice()->GetFocusDevice()->GetViewPort();
	p_oCameraInterface = pCurViewport->GetCameraInterface();
	p_oCamera = pCurViewport->GetCamera();
    if (!p_oCameraInterface || ! p_oCamera)  
		return;
	
	if (m_bAutoZoom != bAutoZoom)
	{
		// update flag
		m_bAutoZoom = bAutoZoom;
		// update camera
		if (m_bAutoZoom && (GetCurrentWorld()->GetCountSelected() == 1))
			fn_vCenterOnObject(GetCurrentWorld()->GetSingleSelection(), TRUE, FALSE);
		// update dialogbar
		GetFrameBase()->m_oGeneralDialogBar.fn_vUpdateAutoZoom(m_bAutoZoom);
	}
}

/*===========================================================================
*		Description:	set constrain for X axes
*		Creation date:
*		Author:			DCerbu
*---------------------------------------------------------------------------
*		Revision date:                Author:
*=========================================================================*/
void CPA_Interface::SetConsX (BOOL bCons)
{

	m_bConsX=bCons;
}
/*===========================================================================
*		Description:	set constrain for Y axes
*		Creation date:
*		Author:			DCerbu
*---------------------------------------------------------------------------
*		Revision date:                Author:
*=========================================================================*/
void CPA_Interface::SetConsY (BOOL bCons)
{
	m_bConsY=bCons;
}
/*===========================================================================
*		Description:	set constrain for Z axes
*		Creation date:
*		Author:			DCerbu
*---------------------------------------------------------------------------
*		Revision date:                Author:
*=========================================================================*/
void CPA_Interface::SetConsZ (BOOL bCons)
{
	m_bConsZ=bCons;
}

//#################################################################################
// USER PREFIX
//#################################################################################
/*===========================================================================
*		Description:	get prefixed name for unicity
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                Author:
*=========================================================================*/
CString CPA_Interface::GetPrefixedName (const CString csName)
{
	CString csPrefix, csPrefixedName;
	
	// get current prefix
	csPrefix = csName.Left(4);
	
	// if necessary, add prefix
	csPrefixedName = (csPrefix == m_csUserPrefix) ? csName : m_csUserPrefix + csName;

	return csPrefixedName;
}

/*===========================================================================
*		Description:	check prefix for permissions
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                Author:
*=========================================================================*/
BOOL CPA_Interface::fn_bCanModifyObject (CPA_BaseObject *pObject)
{
	CString csPrefix;
	long	lIndex;


	// get object prefix
	csPrefix = pObject->GetName().Left(4);

	// can modify user objects
	if (csPrefix == m_csUserPrefix)
		return TRUE;

	lIndex = GetPrefixIndex(csPrefix.Left(3));
	csPrefix = (lIndex != -1) ? csPrefix.Left(3) : "";

	// can modify objects with authorized prefix
	if (fn_bIsAuthorized(csPrefix))
		return TRUE;

	// never modify objects with forbidden prefix
	if (fn_bIsProhibited(csPrefix))
		return FALSE;

	// else must ask for permission
	return m_oDialogPermission.fn_bDoDialog(this, pObject, lIndex);
}

/*===========================================================================
*		Description:	init user prefix
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vInitUserPrefix (void)
{
	CString	csFileName, csUserPrefix;
	char	szUserPrefix[256];
	BOOL	bUserList;

	// load list of available users
	bUserList = fn_bLoadListOfUsers();

	// try to read preference
	if (m_csUserPrefix.IsEmpty())
	{
		// user prefix
		if (m_bUseUserPreferences)
		{
			csFileName = M_GetMainApp()->m_csEditorDataPath + C_szInterfaceIniFile;
			GetPrivateProfileString ("User", "User Prefix", "", szUserPrefix, 5, (char*)(LPCSTR)csFileName);
			csUserPrefix = szUserPrefix;
		}
		
		// if no preference, use dialog
		if (csUserPrefix.IsEmpty())
		{
			if (!bUserList)
				csUserPrefix = "DS1";
			else
				csUserPrefix = GetUserFromUsersFile();
		}
		
		// set user prefix
		if (csUserPrefix.GetLength() > 3)
			csUserPrefix = csUserPrefix.Left(3);
		else while (csUserPrefix.GetLength() < 3)
			csUserPrefix += "_";

		m_csUserPrefix = csUserPrefix + "_";

		if (m_bUseUserPreferences)
		{
			// read permissions
			fn_vLoadAuthorizations();
			// read interdictions
			fn_vLoadProhibitions();
		}
	}

}

/*===========================================================================
*		Description:	load list of avalable users and prefix
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                Author:
*=========================================================================*/
BOOL CPA_Interface::fn_bLoadListOfUsers (void)
{
	CString		csFileName, csUser;
	FILE		*pFile;
	char		szUser[256];
	int			iPos;
	
	m_lNbUsers = 0;
	
	csFileName = M_GetMainApp()->m_csEditorDataPath + "\\UserList.txt";
	
	// open file
	pFile = fopen((char*)(LPCTSTR)csFileName, "rt");
	if (!pFile)
	{
		AfxMessageBox("Unable to open EDT_DATA\\UserList.txt",MB_ICONEXCLAMATION | MB_OK);
		return FALSE;
	}

	// get all user names and prefix
	while (fgets(szUser, 256, pFile) != NULL)
	{
		csUser = szUser;
		iPos = csUser.Find(" = ");
		m_a_csUserNames[m_lNbUsers] = csUser.Left(iPos);
		m_a_csUserPrefix[m_lNbUsers] = csUser.Mid(iPos+3,3);
		m_lNbUsers++;
	}

	return TRUE;
}

/*===========================================================================
*		Description:	ask user to get prefix
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                Author:
*=========================================================================*/
CString CPA_Interface::GetUserFromUsersFile (void)
{
	long lIndex;
	
	// ask user for his name
	lIndex = m_oDialogPrefix.fn_lDoDialog(this, m_a_csUserNames, m_lNbUsers);
	// register corresponding prefix
	return (m_a_csUserPrefix[lIndex]);
}


/*===========================================================================
*		Description:	get index from prefix
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
long CPA_Interface::GetPrefixIndex (CString csUserPrefix)
{
	long lIndex;
	
	// check prefix list
	for (lIndex = 0; lIndex < m_lNbUsers; lIndex++)
	{
		if (m_a_csUserPrefix[lIndex] == csUserPrefix)
			return lIndex;
	}

	// prefix was not found
	return -1;
}

/*===========================================================================
*		Description:	add authorisation for given prefix
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vAddAuthorization (CString csPrefix)
{
	if (!fn_bIsAuthorized(csPrefix))
		m_a_csAuthorized[m_lNbAuthorized++] = csPrefix;
}

/*===========================================================================
*		Description:	check if given prefix is authorized
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL CPA_Interface::fn_bIsAuthorized (CString csPrefix)
{
	long lIndex;
	
	for (lIndex = 0; lIndex < m_lNbAuthorized; lIndex++)
	{
		if (m_a_csAuthorized[lIndex] == csPrefix)
			return TRUE;
	}

	return FALSE;
}


/*===========================================================================
*		Description:	add authorisation for given prefix
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vAddProhibition (CString csPrefix)
{
	if (!fn_bIsProhibited(csPrefix))
		m_a_csProhibited[m_lNbProhibited++] = csPrefix;
}

/*===========================================================================
*		Description:	check if given prefix is authorized
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL CPA_Interface::fn_bIsProhibited (CString csPrefix)
{
	long lIndex;
	
	for (lIndex = 0; lIndex < m_lNbProhibited; lIndex++)
	{
		if (m_a_csProhibited[lIndex] == csPrefix)
			return TRUE;
	}

	return FALSE;
}

/*===========================================================================
*		Description:	save user preference
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vSaveUserPrefix (CString csUserPrefix)
{
	CString	csFileName;
	BOOL	bRes;
	
	// preference file
	csFileName = M_GetMainApp()->m_csEditorDataPath + C_szInterfaceIniFile;
	// try to write preference
	bRes = WritePrivateProfileString ("User", "User Prefix", (char*)(LPCSTR) csUserPrefix, (char*)(LPCSTR)csFileName);
	// warning if problem
	if (!bRes)
		M_GetMainWnd()->UpdateStatus("Hierarchy Editor cannot save your preferences. CPAPref.ini may have a ReadOnly status ?", C_STATUSPANE_INFOS, C_STATUS_WARNING);
	else
		M_GetMainWnd()->UpdateStatus("Preferences saved", C_STATUSPANE_INFOS, C_STATUS_NORMAL);
}

/*===========================================================================
*		Description:	save user preference
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vSaveAuthorizations (void)
{
	CString	csFileName;
	BOOL	bRes;
	long	lIndex;
	char	szText[30];
	
	// preference file
	csFileName = M_GetMainApp()->m_csEditorDataPath + C_szInterfaceIniFile;
	// try to write nb authorizations
	sprintf(szText, "%ld", m_lNbAuthorized);
	bRes = WritePrivateProfileString ("Permissions", "Nb Authorized", szText, (char*)(LPCSTR)csFileName);
	// write each authorization
	for (lIndex = 0; lIndex < m_lNbAuthorized; lIndex++)
	{
		sprintf(szText, "Authorized%ld", lIndex);
		WritePrivateProfileString ("Permissions", szText, (char*)(LPCSTR) m_a_csAuthorized[lIndex], (char*)(LPCSTR)csFileName);
	}
	// warning if problem
	if (!bRes)
		M_GetMainWnd()->UpdateStatus("Hierarchy Editor cannot save your preferences. CPAPref.ini may have a ReadOnly status ?", C_STATUSPANE_INFOS, C_STATUS_WARNING);
	else
		M_GetMainWnd()->UpdateStatus("Preferences saved", C_STATUSPANE_INFOS, C_STATUS_NORMAL);
}

/*===========================================================================
*		Description:	save user preference
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vSaveProhibitions (void)
{
	CString	csFileName;
	BOOL	bRes;
	long	lIndex;
	char	szText[30];
	
	// preference file
	csFileName = M_GetMainApp()->m_csEditorDataPath + C_szInterfaceIniFile;
	// try to write nb authorizations
	sprintf(szText, "%ld", m_lNbProhibited);
	bRes = WritePrivateProfileString ("Interdictions", "Nb Prohibited", szText, (char*)(LPCSTR)csFileName);
	// write each authorization
	for (lIndex = 0; lIndex < m_lNbProhibited; lIndex++)
	{
		sprintf(szText, "Prohibited%ld", lIndex);
		WritePrivateProfileString ("Interdictions", szText, (char*)(LPCSTR) m_a_csProhibited[lIndex], (char*)(LPCSTR)csFileName);
	}
	// warning if problem
	if (!bRes)
		M_GetMainWnd()->UpdateStatus("Hierarchy Editor cannot save your preferences. CPAPref.ini may have a ReadOnly status ?", C_STATUSPANE_INFOS, C_STATUS_WARNING);
	else
		M_GetMainWnd()->UpdateStatus("Preferences saved", C_STATUSPANE_INFOS, C_STATUS_NORMAL);
}

/*===========================================================================
*		Description:	load user preference
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vLoadAuthorizations (void)
{
	CString	csFileName;
	long	lIndex;
	char	szText[30];
	char	szEntry[30];
	
	// preference file
	csFileName = M_GetMainApp()->m_csEditorDataPath + C_szInterfaceIniFile;
	// try to write nb authorizations
	GetPrivateProfileString ("Permissions", "Nb Authorized", "", szText, 30, (char*)(LPCSTR)csFileName);
	if (strcmp(szText, ""))
		sscanf(szText, "%ld", &m_lNbAuthorized);
	else
		m_lNbProhibited = 0;
	// write each authorization
	for (lIndex = 0; lIndex < m_lNbAuthorized; lIndex++)
	{
		sprintf(szEntry, "Authorized%ld", lIndex);
		GetPrivateProfileString ("Permissions", szEntry, "", szText, 30, (char*)(LPCSTR)csFileName);
		m_a_csAuthorized[lIndex] = szText; 
	}
}

/*===========================================================================
*		Description:	load user preference
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vLoadProhibitions (void)
{
	CString	csFileName;
	long	lIndex;
	char	szText[30];
	char	szEntry[30];
	
	// preference file
	csFileName = M_GetMainApp()->m_csEditorDataPath + C_szInterfaceIniFile;
	// try to write nb authorizations
	GetPrivateProfileString ("Interdictions", "Nb Prohibited", "", szText, 30, (char*)(LPCSTR)csFileName);
	if (strcmp(szText, ""))
		sscanf(szText, "%ld", &m_lNbProhibited);
	else
		m_lNbProhibited = 0;
	// write each authorization
	for (lIndex = 0; lIndex < m_lNbProhibited; lIndex++)
	{
		sprintf(szEntry, "Prohibited%ld", lIndex);
		GetPrivateProfileString ("Interdictions", szEntry, "", szText, 30, (char*)(LPCSTR)csFileName);
		m_a_csProhibited[lIndex] = szText; 
	}
}

/*===========================================================================
*		Description:	Translation of the CPA_SuperObject
*		Creation date:	oct 20 -1997
*		Author:			DCerbu
*---------------------------------------------------------------------------
*		Revision date:                Author:
*=========================================================================*/
void CPA_Interface::fn_vTranslate (CPA_SuperObject *pSelected,MTH3D_tdstVector *p_stVector, BOOL bAbsolute)
{
	POS_tdstCompletePosition	stMatrix,*p_stMatrix;
	MTH3D_tdstVector	stVector,stTemp;

	POS_fn_vSetIdentityMatrix(&stMatrix);
	// translation on OBJECT axis
	if (!bAbsolute)
	{
		// update vector according to the rotation matrix of the object
		stMatrix = *(HIE_fn_hGetSuperObjectMatrix(pSelected->GetStruct()));
		MTH3D_M_vNullVector(&stVector);
		POS_fn_vSetTranslationVector(&stMatrix, &stVector);
		POS_fn_vMulMatrixVertex(&stVector, &stMatrix, p_stVector);
	}
	// Translation on CAMERA's axis
	else
	{
		// update vector according to object's position
		POS_fn_vInvertMatrix(&stMatrix,HIE_fn_hGetSuperObjectGlobalMatrix(HIE_fn_hGetSuperObjectFather(pSelected->GetStruct())));
		MTH3D_M_vNullVector(&stVector);
		POS_fn_vSetTranslationVector(&stMatrix, &stVector);
		POS_fn_vMulMatrixVertex(&stVector, &stMatrix, p_stVector);
	}

	// update the translation vector of the object
	p_stMatrix = HIE_fn_hGetSuperObjectMatrix(pSelected->GetStruct());
	POS_fn_vGetTranslationVector(p_stMatrix, &stTemp);
	MTH3D_M_vAddVector(&stTemp, &stTemp, &stVector);
	POS_fn_vSetTranslationVector(p_stMatrix, &stTemp);
//	POS_fn_vNormalizeMatrix(p_stMatrix);
}

/*===========================================================================
*		Description:	scale all pure editor objects
*		Creation date:	03-09-98
*		Author:			ionut grozea
*---------------------------------------------------------------------------
*	Revision date:                Author:
*=========================================================================*/
void CPA_Interface::fn_vScale ()
{
	CPA_List<CPA_SuperObject>	*poListWayPoint;
	CPA_List<CPA_SuperObject>	*poListLights;
	CPA_ObjectDLLBase			*poObjectDLL;
	CPA_SuperObject				*poSuperObject;
	CPA_SuperObject				*poGraphicSupObj;
	POSITION					xSuperObjectPos;


	//for lights
	poListLights = GetObjectListByType ("Light");
	poObjectDLL = GetMainWorld()->GetObjectDLLWithName(C_szDLLLightName);

	// loop on the light super object
	for (poSuperObject = poListLights->GetHeadElement(xSuperObjectPos); poSuperObject; 
		 poSuperObject = poListLights->GetNextElement(xSuperObjectPos))
	{
		MTH3D_tdstVector	stVectI,stVectJ,stVectK;
		MTH3D_tdstVector	stScale;
		POS_tdstCompletePosition	stMatrix, stTempCMatrix ,stCMatrix;
		DEV_ViewPort3D		*pCurViewport;
		double				dist;
		
		// init vectors
		MTH3D_M_vNullVector(&stVectI);
		MTH3D_M_vNullVector(&stVectJ);
		MTH3D_M_vNullVector(&stVectK);

		// get graphic object
		poGraphicSupObj = poObjectDLL->GetVisualSuperObject(poSuperObject);
		if (poGraphicSupObj)
		{
			//the new matrix
			POS_fn_vSetIdentityMatrix(&stMatrix);
			POS_fn_vSetIdentityMatrix(&stCMatrix);
			POS_fn_vSetIdentityMatrix(&stTempCMatrix);

			stMatrix = *(HIE_fn_hGetSuperObjectGlobalMatrix(poGraphicSupObj->GetStruct()));
			pCurViewport = (DEV_ViewPort3D *) GetMultiDevice()->GetFocusDevice()->GetViewPort();
			GLI_xGetCameraMatrix(pCurViewport->GetEngineCamera(),&stTempCMatrix);
			POS_fn_vInvertMatrix(&stCMatrix,&stTempCMatrix);
			dist = sqrt((stMatrix.stTranslationVector.xX-stCMatrix.stTranslationVector.xX)*(stMatrix.stTranslationVector.xX-stCMatrix.stTranslationVector.xX)
				+
				(stMatrix.stTranslationVector.xY-stCMatrix.stTranslationVector.xY)*(stMatrix.stTranslationVector.xY-stCMatrix.stTranslationVector.xY)
				+
				(stMatrix.stTranslationVector.xZ-stCMatrix.stTranslationVector.xZ)*(stMatrix.stTranslationVector.xZ-stCMatrix.stTranslationVector.xZ)
				);
 			stScale.xX =(float)  (1+dist*C_lNbConst);
			stScale.xY = (float)(1+dist*C_lNbConst);
			stScale.xZ = (float)(1+dist*C_lNbConst);
			MTH3D_M_vSetXofVector(&stVectI, MTH3D_M_xGetXofVector(&stScale));
			MTH3D_M_vSetYofVector(&stVectJ, MTH3D_M_xGetYofVector(&stScale));
			MTH3D_M_vSetZofVector(&stVectK, MTH3D_M_xGetZofVector(&stScale));

			POS_fn_vSetScaleMatrix(HIE_fn_hGetSuperObjectMatrix(poGraphicSupObj->GetStruct()),&stVectI,&stVectJ,&stVectK);
		}
	}


	//for waypoint
	poListWayPoint = GetObjectListByType ("Waypoint");
	poObjectDLL = GetMainWorld()->GetObjectDLLWithName(C_szDLLWayPointName);
	
	// loop on the waypoint super object
	for (poSuperObject = poListWayPoint->GetHeadElement(xSuperObjectPos); poSuperObject; 
		 poSuperObject = poListWayPoint->GetNextElement(xSuperObjectPos))
	{
		MTH3D_tdstVector	stVectI={0.f,0.f,0.f}, stVectJ={0.f,0.f,0.f},stVectK={0.f,0.f,0.f};
		MTH3D_tdstVector	stScale={0.f,0.f,0.f};
		POS_tdstCompletePosition	stMatrix, stTempCMatrix ,stCMatrix;
		DEV_ViewPort3D		*pCurViewport;
		double  dist;
		
		// init vectors
		MTH3D_M_vNullVector(&stVectI);
		MTH3D_M_vNullVector(&stVectJ);
		MTH3D_M_vNullVector(&stVectK);

		// get graphic object
		poGraphicSupObj = poObjectDLL->GetVisualSuperObject(poSuperObject);
		if (poGraphicSupObj)
		{
			//the new matrix
			POS_fn_vSetIdentityMatrix(&stMatrix);
			POS_fn_vSetIdentityMatrix(&stCMatrix);
			POS_fn_vSetIdentityMatrix(&stTempCMatrix);
			stMatrix = *(HIE_fn_hGetSuperObjectGlobalMatrix(poGraphicSupObj->GetStruct()));
			pCurViewport = (DEV_ViewPort3D *) GetMultiDevice()->GetFocusDevice()->GetViewPort();
			GLI_xGetCameraMatrix(pCurViewport->GetEngineCamera(),&stTempCMatrix);
			stCMatrix = stTempCMatrix;
			POS_fn_vInvertMatrix(&stCMatrix,&stTempCMatrix);
			dist = sqrt((stMatrix.stTranslationVector.xX-stCMatrix.stTranslationVector.xX)*(stMatrix.stTranslationVector.xX-stCMatrix.stTranslationVector.xX)
				+
				(stMatrix.stTranslationVector.xY-stCMatrix.stTranslationVector.xY)*(stMatrix.stTranslationVector.xY-stCMatrix.stTranslationVector.xY)
				+
				(stMatrix.stTranslationVector.xZ-stCMatrix.stTranslationVector.xZ)*(stMatrix.stTranslationVector.xZ-stCMatrix.stTranslationVector.xZ)
				);
 			stScale.xX = (float)(1+dist*C_lNbConst);
			stScale.xY = (float)(1+dist*C_lNbConst);
			stScale.xZ = (float)(1+dist*C_lNbConst);
			MTH3D_M_vSetXofVector(&stVectI, MTH3D_M_xGetXofVector(&stScale));
			MTH3D_M_vSetYofVector(&stVectJ, MTH3D_M_xGetYofVector(&stScale));
			MTH3D_M_vSetZofVector(&stVectK, MTH3D_M_xGetZofVector(&stScale));

			POS_fn_vSetScaleMatrix(HIE_fn_hGetSuperObjectMatrix(poGraphicSupObj->GetStruct()),&stVectI,&stVectJ,&stVectK);
		}
	}
}


/*===========================================================================
*		Description:	rescale all pure editor objects
*		Creation date:	03-09-98
*		Author:			ionut grozea
*---------------------------------------------------------------------------
*	Revision date:                Author:
*=========================================================================*/
void CPA_Interface::fn_vReScale ()
{
	CPA_List<CPA_SuperObject>	*poListWayPoint;
	CPA_List<CPA_SuperObject>	*poListLights;
	CPA_ObjectDLLBase			*poObjectDLL;
	CPA_SuperObject				*poSuperObject;
	CPA_SuperObject				*poGraphicSupObj;
	POSITION					xSuperObjectPos;


	//for lights
	poListLights = GetObjectListByType ("Light");
	poObjectDLL = GetMainWorld()->GetObjectDLLWithName(C_szDLLLightName);
	
	// loop on the light super object
	for (poSuperObject = poListLights->GetHeadElement(xSuperObjectPos); poSuperObject; 
		 poSuperObject = poListLights->GetNextElement(xSuperObjectPos))
	{
		// get graphic object
		poGraphicSupObj = poObjectDLL->GetVisualSuperObject(poSuperObject);
		if (poGraphicSupObj)
		{
			POS_fn_vResetScaleMatrix(HIE_fn_hGetSuperObjectMatrix(poGraphicSupObj->GetStruct()));
		}
	}
 
	//for WayPoint
	poListWayPoint = GetObjectListByType ("Waypoint");
	poObjectDLL = GetMainWorld()->GetObjectDLLWithName(C_szDLLWayPointName);
	
	// loop on the WayPoint super object
	for (poSuperObject = poListWayPoint->GetHeadElement(xSuperObjectPos); poSuperObject; 
		 poSuperObject=poListWayPoint->GetNextElement(xSuperObjectPos))
	{
		// get graphic object
		poGraphicSupObj = poObjectDLL->GetVisualSuperObject(poSuperObject);
		if (poGraphicSupObj)
		{
			POS_fn_vResetScaleMatrix(HIE_fn_hGetSuperObjectMatrix(poGraphicSupObj->GetStruct()));
		}
	}
 
	fn_vUpdateAll(E_mc_UpdateAll);

}

/*===========================================================================
*		Description:	save user preference
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vSaveDisplayMode (void)
{
	CPA_CameraDLLBase		*p_oCameraInterface = ((DEV_ViewPort3D *) GetMultiDevice3D()->GetFocusDevice()->GetViewPort())->GetCameraInterface();
	tdeDisplayReferential	eDisplayModeAxis	= p_oCameraInterface ? p_oCameraInterface -> GetReferentialDisplayMode() : DisplayNone ;
	CString					csFileName, csEntry;
	BOOL					bRes;
	char					cRed, cGreen, cBlue;
	
	// preference file
	csFileName = M_GetMainApp()->m_csEditorDataPath + C_szInterfaceIniFile;
	// try to write preference
	//
	// Appearance
	bRes  = WritePrivateProfileString ("Drawing", "Appearance - Textured", fn_bWorldIsTextured() ? "TRUE" : "FALSE", (char*)(LPCSTR)csFileName);
	bRes &= WritePrivateProfileString ("Drawing", "Appearance - Grided",   fn_bWorldIsGrided()   ? "TRUE" : "FALSE", (char*)(LPCSTR)csFileName);
	bRes &= WritePrivateProfileString ("Drawing", "Appearance - Wired",	   fn_bWorldIsWired()    ? "TRUE" : "FALSE", (char*)(LPCSTR)csFileName);
	// 
	// Display
	switch (m_oSpecificInterface.GetDisplayMode())
	{
	case E_dm_DrawWorld:				csEntry = "World";			break;
	case E_dm_DrawCollisionMap:			csEntry = "Collision Map";	break;
	case E_dm_DrawVisibleSectors:		csEntry = "Visible";		break;
	case E_dm_DrawOnlyCurrentSector:	csEntry = "Current";		break;
	}
	bRes &= WritePrivateProfileString ("Drawing", "Display Mode", (char*)(LPCSTR) csEntry, (char*)(LPCSTR)csFileName);
	//
	// Bounding Volume
	switch( m_eBVMode )
	{
	case E_bv_None:						csEntry = "None";			break;
	case E_bv_Sectors:					csEntry = "Sectors";		break;
	case E_bv_Actors:					csEntry = "Actors";			break;
	case E_bv_Objects:					csEntry = "Objects";		break;
	}
	bRes &= WritePrivateProfileString ("Drawing", "Bounding Volume", (char*)(LPCSTR) csEntry, (char*)(LPCSTR)csFileName);
	//
	// Axis
	switch( eDisplayModeAxis )
	{
	case DisplayNone:					csEntry = "None";				break;
	case DisplayDownRight:				csEntry = "Down Right Corner";	break;
	case DisplayDownLeft:				csEntry = "Down Left Corner";	break;
	}
	bRes &= WritePrivateProfileString ("Drawing", "Axis", (char*)(LPCSTR) csEntry, (char*)(LPCSTR)csFileName);
	//
	// Objects Center
	switch( m_iShowCenter )
	{
	case 0:								csEntry = "None";				break;
	case 1:								csEntry = "Objects";			break;
	case 2:								csEntry = "Instances";			break;
	}
	bRes &= WritePrivateProfileString ("Drawing", "Objects Center", (char*)(LPCSTR) csEntry, (char*)(LPCSTR)csFileName);
	//
	// Background color
	GetMultiDevice() -> GetBackgroundColor( &cRed, &cGreen, &cBlue );
	csEntry . Format( "%d,%d,%d", cRed, cGreen, cBlue );
	bRes &= WritePrivateProfileString ("Drawing", "Background Color", (char*)(LPCSTR) csEntry, (char*)(LPCSTR)csFileName);
	//
	// warning if problem
	if (!bRes)
		M_GetMainWnd()->UpdateStatus("Hierarchy Editor cannot save your preferences. CPAPref.ini may have a ReadOnly status ?", C_STATUSPANE_INFOS, C_STATUS_WARNING);
	else
		M_GetMainWnd()->UpdateStatus("Preferences saved", C_STATUSPANE_INFOS, C_STATUS_NORMAL);
}


/*===========================================================================
*		Description:	load user preference
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/

char	cRed, cGreen, cBlue; //chbani Moved from functin to Global because c plante dans sscanf 
							// je ne sais pas prq?
			
void CPA_Interface::fn_vLoadDisplayMode (void)
{
	CString					csFileName;
	char					szText[30];
	CPA_CameraDLLBase		*p_oCameraInterface = (CPA_CameraDLLBase*)GetMainWorld() -> GetObjectDLLWithName( C_szDLLCameraName );
	

	// preference file
	csFileName = M_GetMainApp()->m_csEditorDataPath + C_szInterfaceIniFile;
	// try to read preferences
	//
	// Appearance
	GetPrivateProfileString ("Drawing", "Appearance - Textured", "TRUE", szText, 30, (char*)(LPCSTR)csFileName);
	fn_vChangeWorldMask(GLI_C_lIsTextured, !stricmp( szText, "TRUE" ) );
	GetPrivateProfileString ("Drawing", "Appearance - Grided", "FALSE", szText, 30, (char*)(LPCSTR)csFileName);
	fn_vChangeWorldMask(GLI_C_lIsNotGrided, stricmp( szText, "TRUE" ) );
	GetPrivateProfileString ("Drawing", "Appearance - Wired", "FALSE", szText, 30, (char*)(LPCSTR)csFileName);
	fn_vChangeWorldMask(GLI_C_lIsNotWired, stricmp( szText, "TRUE" ) );
	//
	// Display 
	GetPrivateProfileString ("Drawing", "Display Mode", "World", szText, 30, (char*)(LPCSTR)csFileName);
	if ( !stricmp( szText, "World" ) )
		m_oSpecificInterface.SetDisplayMode(E_dm_DrawWorld);
	else if ( !stricmp( szText, "Collision Map" ) )
		m_oSpecificInterface.SetDisplayMode(E_dm_DrawCollisionMap);
	else if ( !stricmp( szText, "Visible" ) )
		m_oSpecificInterface.SetDisplayMode(E_dm_DrawVisibleSectors);
	else if ( !stricmp( szText, "Current" ) )
		m_oSpecificInterface.SetDisplayMode(E_dm_DrawOnlyCurrentSector);
	//
	// Bounding Volume
	GetPrivateProfileString ("Drawing", "Bounding Volume", "None", szText, 30, (char*)(LPCSTR)csFileName);
	if( !stricmp( szText, "None" ) )			fn_vSetBVMode( E_bv_None );
	else if( !stricmp( szText, "Sectors" ) )	fn_vSetBVMode( E_bv_Sectors );
	else if( !stricmp( szText, "Actors" ) )		fn_vSetBVMode( E_bv_Actors );
	else if( !stricmp( szText, "Objects" ) )	fn_vSetBVMode( E_bv_Objects );
	//
	// Axis
	if( p_oCameraInterface )
	{
		GetPrivateProfileString ("Drawing", "Axis", "None", szText, 30, (char*)(LPCSTR)csFileName);
		if( !stricmp( szText, "None" ) )					p_oCameraInterface -> SetReferentialDisplayMode( DisplayNone );
		else if( !stricmp( szText, "Down Right Corner" ) )	p_oCameraInterface -> SetReferentialDisplayMode( DisplayDownRight );
		else if( !stricmp( szText, "Down Left Corner" ) )	p_oCameraInterface -> SetReferentialDisplayMode( DisplayDownLeft );
	}


	//
	// Object Center
	GetPrivateProfileString ("Drawing", "Objects Center", "None", szText, 30, (char*)(LPCSTR)csFileName);
	if( !stricmp( szText, "None" ) )
	{
		SetShowcenter( 0 );
		GetFrameBase()->m_oGeneralDialogBar.m_oDisplayToolbar.SetButton(IDCB_NORMAL);
	}
	else if( !stricmp( szText, "Objects" ) )
	{
		SetShowcenter( 1 );
		GetFrameBase()->m_oGeneralDialogBar.m_oDisplayToolbar.SetButton(IDCB_ALLCENTERS);
	}
	else if( !stricmp( szText, "Instances" ) )
	{
		SetShowcenter( 2 );
		GetFrameBase()->m_oGeneralDialogBar.m_oDisplayToolbar.SetButton(IDCB_MAINCENTERS);
	}

	//
	// Background color
	GetPrivateProfileString ("Drawing", "Background Color", "", szText, 30, (char*)(LPCSTR)csFileName);
	if( strlen( szText ) )
	{
		sscanf( szText, "%d,%d,%d", &cRed, &cGreen, &cBlue );
		GetMultiDevice() -> SetBackgroundColor( cRed, cGreen, cBlue );
	}


}

/*===========================================================================
*		Description:	save options
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vSaveOptions (void)
{
	CString	csFileName, csText;
	BOOL	bRes;
	
	// preference file
	csFileName = M_GetMainApp()->m_csEditorDataPath + C_szInterfaceIniFile;

	// write general options
	csText = g_oCoherenceManager.m_fn_bIsCoherenceManagerDialogAutomatic() ? "TRUE" : "FALSE";
	bRes  = WritePrivateProfileString ("Options", "Automatic Coherence", (char*)(LPCSTR)csText, (char*)(LPCSTR)csFileName);

	csText = M_GetMainApp()->m_bAutoReinitTheMap ? "TRUE" : "FALSE";
	bRes &= WritePrivateProfileString ("Options", "Reinit the Map", (char*)(LPCSTR)csText, (char*)(LPCSTR)csFileName);

	csText = fn_bIsScaleActive() ? "TRUE" : "FALSE";
	bRes &= WritePrivateProfileString ("Options", "Scale editor object", (char*)(LPCSTR)csText, (char*)(LPCSTR)csFileName);

	// write pyramid depth
	csText.Format("%8.4f", GetPyramidalDepth());
	bRes &= WritePrivateProfileString ("Options", "Pyramid Depth", (char*)(LPCSTR)csText, (char*)(LPCSTR)csFileName);

	// write target depth
	csText.Format("%8.4f", GetCameraTargetDepth());
	bRes &= WritePrivateProfileString ("Options", "Target Depth", (char*)(LPCSTR)csText, (char*)(LPCSTR)csFileName);

	//CPA2 Gabi Dumitrascu 98/07/09
	//write automatic swap
	csText = fn_bGetAutomaticSwap () ? "TRUE" : "FALSE";
	bRes &= WritePrivateProfileString ("Options", "Automatic swap", (char*)(LPCSTR)csText, (char*)(LPCSTR)csFileName);

	//write swap mode
	switch (m_eForceSwap)
	{
		case eSwapBoth	: csText = "BOTH";  break;
		case eSwapLeft	: csText = "LEFT";  break;
		case eSwapRight : csText = "RIGHT"; break;
	}
	bRes &= WritePrivateProfileString ("Options", "Swap mode", (char*)(LPCSTR)csText, (char*)(LPCSTR)csFileName);
//End CPA2 Gabi Dumitrascu 98/07/09
}
	
/*===========================================================================
*		Description:	load options
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vLoadOptions (void)
{
	CString	csFileName;
	char	szText[30];
	
	// preference file
	csFileName = M_GetMainApp()->m_csEditorDataPath + C_szInterfaceIniFile;

	// read general options
	GetPrivateProfileString ("Options", "Automatic Coherence", "FALSE", szText, 30, (char*)(LPCSTR)csFileName);
	g_oCoherenceManager.m_fn_vSetAutomaticCoherenceManagerDialog(!stricmp(szText, "TRUE"));

	GetPrivateProfileString ("Options", "Reinit the Map", "FALSE", szText, 30, (char*)(LPCSTR)csFileName);
	M_GetMainApp()->m_bAutoReinitTheMap = !stricmp(szText, "TRUE");

	GetPrivateProfileString ("Options", "Scale editor object", "FALSE", szText, 30, (char*)(LPCSTR)csFileName);
	fn_bSetScaleActive(!stricmp(szText, "TRUE"));

	// read pyramidal depth
	GetPrivateProfileString ("Options", "Pyramid Depth", "FALSE", szText, 30, (char*)(LPCSTR)csFileName);
	SetPyramidalDepth((float) atof(szText));
	// read target depth
	GetPrivateProfileString ("Options", "Target Depth", "FALSE", szText, 30, (char*)(LPCSTR)csFileName);
	SetCameraTargetDepth((float) atof(szText));

	//CPA2 Gabi Dumitrascu 98/07/09
	GetPrivateProfileString ("Options", "Automatic swap", "TRUE", szText, 30, (char*)(LPCSTR)csFileName);
	BOOL bAutomaticSwap = (stricmp(szText, "TRUE") == 0);
	fn_bSetAutomaticSwap (bAutomaticSwap);

	GetPrivateProfileString ("Options", "Swap mode", "Right", szText, 30, (char*)(LPCSTR)csFileName);
	if (stricmp(szText, "Right") == 0) m_eForceSwap = eSwapRight;
	if (stricmp(szText, "Left")  == 0) m_eForceSwap = eSwapLeft;
	if (stricmp(szText, "Both")  == 0) m_eForceSwap = eSwapBoth;
	//End CPA2 Gabi Dumitrascu 98/07/09
}

/*===========================================================================
*		Description:	check world draw mask
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL CPA_Interface::fn_bWorldIsGrided (void)
{
	HIE_tdxHandleToSuperObject	hSup; 
	long						lMask; 

	hSup = GetCurrentWorld()->GetRoot()->GetStruct();
	lMask = HIE_fn_lGetSuperObjectDrawMask(hSup);

	return !(lMask & GLI_C_lIsNotGrided);
}

BOOL CPA_Interface::fn_bWorldIsWired (void)
{
	HIE_tdxHandleToSuperObject	hSup; 
	long						lMask; 

	hSup = GetCurrentWorld()->GetRoot()->GetStruct();
	lMask = HIE_fn_lGetSuperObjectDrawMask(hSup);

	return !(lMask & GLI_C_lIsNotWired);
}

BOOL CPA_Interface::fn_bWorldIsTextured	(void)
{
	HIE_tdxHandleToSuperObject	hSup; 
	long						lMask; 

	hSup = GetCurrentWorld()->GetRoot()->GetStruct();
	lMask = HIE_fn_lGetSuperObjectDrawMask(hSup);

	return (lMask & GLI_C_lIsTextured);
}

/*===========================================================================
*		Description:	change world draw mask
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vChangeWorldMask	(long lOption, BOOL bAdd)
{
	HIE_tdxHandleToSuperObject	hSup; 
	long						lMask; 

	hSup = GetCurrentWorld()->GetRoot()->GetStruct();
	lMask = HIE_fn_lGetSuperObjectDrawMask(hSup);

	// update mask
	lMask = (bAdd) ? (lMask | lOption) : (lMask & ~lOption);
	HIE_fn_vSetSuperObjectDrawMask(hSup,lMask);

	// update Toolbar
	GetFrameBase()->m_oGeneralDialogBar.fn_vUpdateAppearance(lMask);
	
	// update view
	fn_vUpdateAll(E_mc_JustDraw);
}

/*===========================================================================
*		Description:	compute bounding volume
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vComputeBoundRecurs(CPA_SuperObject *pFather)
{
	HIE_tdxHandleToSuperObject	hSprObj;
	ACP_tdxHandleOfObject		hBoundingVolume;
	CPA_ObjectDLLBase			*p_oDLL;
	CPA_SuperObject				*pObject;
	
	// TEMP => for actors
	hSprObj = (HIE_tdxHandleToSuperObject) pFather->GetStruct();
	if (HIE_fn_ulGetSuperObjectType(hSprObj) == HIE_C_ulActor)
	{
		p_oDLL = pFather->GetObjectDLL();
		hBoundingVolume = p_oDLL->fn_hGetBoundingVolume(pFather->GetObject());
		if (hBoundingVolume != NULL)
			HIE_fn_vSetSuperObjectBoundingVolume(hSprObj, hBoundingVolume);
		else
			HIE_fn_vComputeAllBoundingVolumes(hSprObj);
	}

	// compute BV for childs
	pObject = pFather->GetSuperObjectFirstChild();

	if(!pObject)
	{
		if(pFather->GetObjectDLL())
			pFather->GetObjectDLL()->fn_vComputeBoundingVolume(pFather->GetObject());
		return;
	}
	
	while(pObject)
	{
		fn_vComputeBoundRecurs(pObject);
		pObject = pFather->GetSuperObjectNextChild(pObject);
	}
}

/*===========================================================================
*		Description:	compute bounding volume
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vComputeAllBound(void)
{
	HIE_tdxHandleToSuperObject	hStaticWorld;
	HIE_tdxHandleToSuperObject	hDynamicWorld;
	CPA_BaseObjectList			*pList;
	CPA_ObjectDLLBase			*pDLL;
	CPA_BaseObject				*pObject;
	Position   					xPos;

	// compute BV of all physical objects
	pList = m_p_oMainWorld->fn_p_oGetOriginalObjectList(C_szPhysicalObjectTypeName);
	pDLL = m_p_oMainWorld->GetObjectDLLWithName(C_szDLLPhysicalObjectName);
	xPos = pList->GetHeadPosition();
	while(xPos)
	{
		pObject = pList->GetNext(xPos);
		pDLL->fn_vComputeBoundingVolume(pObject);
	}

	// compute BV of all objects by calling the corresponding DLLs
	fn_vComputeBoundRecurs(GetCurrentWorld()->GetRoot());

	// Second pass : compute BV of super-objects
	hDynamicWorld = HIE_fn_hGetSuperObjectFirstChild(GetMultiDevice3D()->GetEngineWorld());
	hStaticWorld = HIE_fn_hGetSuperObjectNextBrother(hDynamicWorld);
	
	// compute BV of static world
	HIE_fn_vComputeBoundingVolumeOfSuperObjectBranch(hStaticWorld);

	fn_vUpdatePositions();

	// Refresh
	fn_vUpdateAll(E_mc_JustDraw);
	M_GetMainWnd()->UpdateStatus("Bounding volumes computed", C_STATUSPANE_INFOS, C_STATUS_NORMAL);
}


/*===========================================================================
*		Description:	center mode
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::SetShowcenter (int iShow)
{ 
    // Display center of instance during Game ?
    if (iShow==2)
    {
        g_ucDisplayCenters = 1;
    }
    else
    {
        g_ucDisplayCenters = 0;
    }
	m_iShowCenter = iShow; 
	GetFrameBase()->m_oGeneralDialogBar.fn_vUpdateCenterMode(iShow);
	if (m_iShowCenter)
		fn_vComputeSuperObjectsCenters(NULL);
}



/*===========================================================================
*		Description:	set bounding volumes mode
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vSetBVMode (tdeBVMode eMode)
{
	CPA_SuperObject *pStaticRoot, *pDynamicRoot;
	CPA_SuperObject *pSector, *pActor;

	switch (eMode)
	{
		case E_bv_None:
			fn_vSetDisplayBV(FALSE, GetCurrentWorld()->GetRoot(), TRUE);
			break;

		case E_bv_Sectors:
			// cancel previous mode
			fn_vSetDisplayBV(FALSE, GetCurrentWorld()->GetRoot(), TRUE);
			pStaticRoot = GetSpecificInterface()->GetStaticRoot();
			// update sectors
			for (pSector = pStaticRoot->GetSuperObjectFirstChild(); pSector;
				 pSector = pStaticRoot->GetSuperObjectNextChild(pSector))
				fn_vSetDisplayBV(TRUE, pSector, FALSE);
			break;

		case E_bv_Actors:
			// cancel previous mode
			fn_vSetDisplayBV(FALSE, GetCurrentWorld()->GetRoot(), TRUE);
			pDynamicRoot = GetSpecificInterface()->GetDynamicRoot();
			// update sectors
			for (pActor = pDynamicRoot->GetSuperObjectFirstChild(); pActor;
				 pActor = pDynamicRoot->GetSuperObjectNextChild(pActor))
				fn_vSetDisplayBV(TRUE, pActor, FALSE);
			break;

		case E_bv_Objects:
			// cancel previous mode
			fn_vSetDisplayBV(TRUE, GetCurrentWorld()->GetRoot(), TRUE);
			pStaticRoot = GetSpecificInterface()->GetStaticRoot();
			// update sectors
			for (pSector = pStaticRoot->GetSuperObjectFirstChild(); pSector;
				 pSector = pStaticRoot->GetSuperObjectNextChild(pSector))
				fn_vSetDisplayBV(FALSE, pSector, FALSE);
			pDynamicRoot = GetSpecificInterface()->GetDynamicRoot();
			// update sectors
			for (pActor = pDynamicRoot->GetSuperObjectFirstChild(); pActor;
				 pActor = pDynamicRoot->GetSuperObjectNextChild(pActor))
				fn_vSetDisplayBV(FALSE, pActor, FALSE);
			break;
	}
	// update mode
	m_eBVMode = eMode;
	GetFrameBase()->m_oGeneralDialogBar.fn_vUpdateBVMode((int)eMode);
}

/*===========================================================================
*		Description:	display bounding volumes 
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vSetDisplayBV (BOOL bDisplayBV, CPA_SuperObject *pSupObj, BOOL bRecursive)
{
	CPA_SuperObject	*pChild;

	// update SO flag
	pSupObj->fn_vDisplayBV(bDisplayBV);

	// if necessary, update childs
	if (bRecursive)
	{
		for (pChild = pSupObj->GetSuperObjectFirstChild(); pChild;
			 pChild = pSupObj->GetSuperObjectNextChild(pChild))
			fn_vSetDisplayBV(bDisplayBV, pChild, TRUE);
	}
}


/*===========================================================================
*		Description:	display option dialog 
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vDoDialogOptions (void)
{
	m_oDialogOption.fn_vDoDialog(this);
}


/*===========================================================================
*		Description:	display TipOfDay dialog 
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void CPA_Interface::fn_vDisplayTipOfDay (CString csEditor, CString csTag, BOOL bFirstTime)
{
	CString csFileName;
	char	szTip[10];
	char	szCurrentTip[10];
	long	lCurrentTip = 0;

	//kwn : Desactivate Tip Of Day
	return;


	// Tip of the Day
	if (csEditor == "Interface" && csTag == "ITF")
	{
		bFirstTime = m_bDisplayTipOfDay;
		m_bDisplayTipOfDay = FALSE;
	}

	// get INI file
	if (m_csCurrentLanguage == "Francais" || m_csCurrentLanguage == "French")
		csFileName = M_GetMainApp()->m_csEditorDataPath + C_szAstucesIniFile;
	else
		csFileName = M_GetMainApp()->m_csEditorDataPath + C_szTipOfDayIniFile;

	// check if tip must be displayed
	if (!bFirstTime)
	{
		char	szMode[10];
		char	szCurrentMode[10];

		// get corresponding mode
		sprintf(szMode, "%s_Mode", csTag);
		GetPrivateProfileString ("TipOfDay", szMode, "Always", szCurrentMode, 256, (char*)(LPCSTR)csFileName);
		// test mode
		if (!strcmp(szCurrentMode, "FirstOnly"))
			return;
	}

	// get current tip
	sprintf(szTip, "%s_nTip", csTag);
	GetPrivateProfileString ("TipOfDay", szTip, "0", szCurrentTip, 10, (char*)(LPCSTR)csFileName);
	lCurrentTip = atol(szCurrentTip);
	// if there is a tip to display
	if (lCurrentTip > 0)
	{
		char	szCurrentText[255];

		sprintf(szCurrentTip, "%s%ld", csTag, lCurrentTip);
		GetPrivateProfileString (szCurrentTip, "L1", "", szCurrentText, 256, (char*)(LPCSTR)csFileName);
		// check if there is a text
		if (strlen(szCurrentText) > 0)
		{	
			HINSTANCE hOldInst = AfxGetResourceHandle();
			HINSTANCE hNewInst = AfxGetInstanceHandle();
			AfxSetResourceHandle(hNewInst);

			m_oDialogTip.fn_vDoDialog(csEditor, csTag, csFileName, lCurrentTip);
		
			AfxSetResourceHandle(hOldInst);
		}
	}
}

///////////////////////////////////////////////////////////////////////////////
// Begin Silviu Simen Select by sector
///////////////////////////////////////////////////////////////////////////////
void CPA_Interface::SelectBySector (void)
{
	CPA_HierarchyEditor *p_oHierarchy;
	p_oHierarchy = GetEvtEditor();
	ASSERT (p_oHierarchy);
	p_oHierarchy ->fn_vSelectBySectorAndType();
	fn_vUpdateAll(E_mc_UpdateSelection);
	//fn_vUpdateAll(E_mc_UpdateAll);
}
///////////////////////////////////////////////////////////////////////////////
// End Silviu Simen Select by sector
/////////////////////////////////////////////////////////////////////////////

#endif ACTIVE_EDITOR

