/*=========================================================================
*
* 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 "EDTBase.Hpp"
#include "EDTSObj.hpp"
#include "EDTSpec.hpp"
#include "EDTTemp.hpp"
#include "EDTModif.hpp"
#include "EDTdEdit.hpp"
#include "EDTdUpdt.hpp"
#include "EDTdMove.hpp"
#include "EDTdFlag.hpp"
#include "EDTdSel.hpp"
//CPA2 Corneliu Babiuc 17-06-98
#include "EDTdVect.hpp"
//END CPA2 Corneliu Babiuc 17-06-98
#include "EDTParse.hpp"

#include "incCOL.h"


#include "incDPT.h"
#define D_PhysiCol_Define
#include "incGAM.h"
#include "incSPO.h"
#include "incPO.h"
#include "incIPO.h"
#undef  D_PhysiCol_Define

#include "x:\cpa\Main\inc\_editid.h"
#include "TUT.h"





#include "incGeo.h"

extern "C" __declspec(dllimport)  void GEO_vGetPointOfObject ( ACP_tdxHandleOfObject hObject ,
														  MTH3D_tdstVector *p_stPoint ,
														  ACP_tdxIndex xIndexOfPoint);



// infos
static CString g_csEDTName = "Hierarchy";
static CString g_csEDTAuthor = "Chantal Oury";
static CString g_csEDTVersion = "V 6.0.4   18/03/99";
static CString g_csEDTFrenchHelpFile = "Hierarchie.hlp";
static CString g_csEDTEnglishHelpFile = "";

BOOL g_bTipFirstTime = TRUE;

// macros
#define M_GetEngineRoot()	GetInterface()->GetMultiDevice3D()->GetEngineWorld()
#define M_GetEditorRoot()	GetInterface()->GetMultiDevice3D()->M_GetWorld()->GetRoot()

#define M_GetViewPort3d()   ((DEV_ViewPort3D *) GetInterface()->GetMultiDevice()->GetFocusDevice()->GetViewPort())
#define M_GetToolDLLs()		GetMainWorld()->GetToolDLLReceivingEvtEditorMsg()

#define M_ListConcerned		M_GetListAllDLLs()->m_stListConcerned
#define M_ListSelected		M_GetListAllDLLs()->m_stListSelected

// menu
#define C_ui_OrientInstanceAction	10
#define C_ui_CopyInstanceAction		11
#define C_ui_CopyObjectAction		12
#define C_ui_PasteSameAction		13
#define C_ui_PasteDefaultAction		14
#define C_ui_PutOnGroundAction		15

#define C_ui_DisplaySpecificAction	21
#define C_ui_EditorAction			22

#define C_ui_SaveStatusAction		30
#define C_ui_SavePrefixAction		31
#define C_ui_SavePermissions		32
#define C_ui_SaveInterdictions		33
#define C_ui_SaveDialogsAction		34
#define C_ui_ChangeOwner			42



// cursors
#define	C_hc_CurrentCursor		0
#define	C_hc_HierarchyCursor	1
#define	C_hc_PFatherCursor		2
#define	C_hc_PPositionCursor	3
#define	C_hc_ChoiceCursor		4
#define	C_hc_CopyAllCursor		5
#define	C_hc_CopyAloneCursor	6
#define	C_hc_SelectToCursor		7
#define	C_hc_MoveToCursor		8
#define	C_hc_OrientCursor		9
#define	C_hc_VOrientCursor		10

// increase value for translation and rotation step
const GLI_tdxValue	C_xTranslationStep	= (GLI_tdxValue) 0.02;
const GLI_tdxValue	C_xRotationStep		= (GLI_tdxValue) 0.1;

#define AXE_X 0
#define AXE_Y 1
#define AXE_Z 2

//--------------- keys ------------------------

// selection
#define KA_ID_MULTI					1
#define KA_ID_PYRAMID				2
#define KA_ID_MULTIPYRAMID			3
#define KA_ID_CHOICE				4

// copy / paste
#define KA_ID_ALONE					11
#define KA_ID_COPY					12
#define KA_ID_PASTESAME				13
#define KA_ID_PASTEDEFAULT			14
#define KA_ID_PASTEFATHER			15
#define KA_ID_PASTEPOS				16

// modifs
#define KA_ID_DEL					17
#define KA_ID_PARENT				18
#define KA_ID_SUPEROBJECTFLAGS		19

// teleportation
#define KA_ID_REGISTERSELECTION		21
#define KA_ID_MOVETO				22
// put on ground
#define KA_ID_PUTONGROUND			23
// orientation
#define KA_ID_ORIENTINSTANCE		24
#define KA_ID_ORIENTVERTICAL		25
//CPA2 Corneliu Babiuc (multiple teleportation) 07-07-98
#define KA_ID_ADDDELREGISTRATION	26
//END CPA2 Corneliu Babiuc (multiple teleportation) 07-07-98

// moves
#define KA_ID_ROTX					31
#define KA_ID_ROTY					32
#define KA_ID_ROTZ					33
#define KA_ID_LEFT					34
#define KA_ID_RIGHT					35
#define KA_ID_ON					36
#define KA_ID_BACK					37
#define KA_ID_UP					38
#define KA_ID_DOWN					39
#define KA_ID_ROTINVX				40
#define KA_ID_ROTINVY				41
#define KA_ID_ROTINVZ				42
#define KA_ID_INCROTATIONSTEP		43
#define KA_ID_DECROTATIONSTEP		44
#define KA_ID_INCTRANSLATIONSTEP	45
#define KA_ID_DECTRANSLATIONSTEP	46
#define KA_ID_XCONSTRAINT			47
#define KA_ID_YCONSTRAINT			48
#define KA_ID_ZCONSTRAINT			49
#define KA_ID_MOVEDEPTH				50
#define KA_ID_WARPOBJECTDEPTHMOVE	51
#define KA_ID_MOVEDOBJECT			52
#define KA_ID_ROTATEOBJECTXY		53
#define KA_ID_ROTATEOBJECTXZ		54

// current sector
#define KA_ID_SECTORSELECTION		61
#define KA_ID_SECTORWITHMOUSE		62

//CPA2 Corneliu Babiuc 14-06-98
// specific teleportation
#define KA_ID_MOVETOINSTANCE		63
#define KA_ID_MOVETOCAMERA			64
#define KA_ID_MOVECAMERATOINSTANCE	65
#define KA_ID_MOVECAMERACENTERED	66
#define KA_ID_CHOOSEVECTOR			67
//END CPA2 Corneliu Babiuc 17-06-98

// Begin Silviu Simen 18 August 1998 Cut/Paste Mechanism
#define KA_ID_CUT					68
// End Silviu Simen 18 August 1998 Cut/Paste Mechanism
// Begin Silviu Simen 01 september 1998 List of Objects in Sectors
#define KA_ID_SELECTSECTOR			69
// End Silviu Simen 01 september 1998 List of Objects in Sectors

// keyboard
static tdstKeyboardActionDef g_EDTKeyboardAction[] =
{
	// selection
	{ "multiple selection",				KA_ID_MULTI					},
	{ "pyramid selection",				KA_ID_PYRAMID				},
	{ "multi-pyramid selection",		KA_ID_MULTIPYRAMID			},
	{ "use Selection dialog",			KA_ID_CHOICE				},
	// copy / paste
	{ "Copy instance alone",			KA_ID_ALONE					},
	{ "copy instance with Branch",		KA_ID_COPY					},
// Begin Silviu Simen 18 August 1998 Cut/Paste Mechanism
	{ "cut instance",					KA_ID_CUT					},
// Begin Silviu Simen 18 August 1998 Cut/Paste Mechanism
	{ "paste at chosen position",		KA_ID_PASTEPOS				},
	{ "paste under Default parent",		KA_ID_PASTEDEFAULT			},
	{ "paste under Found parent",		KA_ID_PASTESAME				},
	{ "paste under same parent",		KA_ID_PASTEFATHER			},
	// delete
	{ "Delete selected instances",		KA_ID_DEL					},
	// hierarchy
	{ "Change super-object parent",		KA_ID_PARENT				},
	// SuperObject Flags
	{ "Edit super-object flags",		KA_ID_SUPEROBJECTFLAGS		},
	// move to
	{ "Register selection for move",	KA_ID_REGISTERSELECTION     },
//CPA2 Corneliu Babiuc (multiple teleportation) 07-07-98
	{ "add/delete Registration",		KA_ID_ADDDELREGISTRATION	},
//END CPA2 Corneliu Babiuc (multiple teleportation) 07-07-98
	{ "Teleport to new position",		KA_ID_MOVETO				},
//CPA2 Corneliu Babiuc 14-06-98
	// specific teleportation
	{ "Teleport to instance",			KA_ID_MOVETOINSTANCE		},
	{ "Teleport to camera",				KA_ID_MOVETOCAMERA			},
	{ "Teleport camera to instance",	KA_ID_MOVECAMERATOINSTANCE	},
	{ "Teleport camera centered on Rayman", KA_ID_MOVECAMERACENTERED},
	{ "Choose translation vector",		KA_ID_CHOOSEVECTOR			},
//END CPA2 Corneliu Babiuc 17-06-98
	// put on ground
	{ "put on Ground",					KA_ID_PUTONGROUND			},
	// orient
	{ "Orient to position",				KA_ID_ORIENTINSTANCE		},
	{ "orient keePing vertical",		KA_ID_ORIENTVERTICAL		},
	// rotations
	{ "rotate instance / X",			KA_ID_ROTX					},
	{ "rotate instance / Y",			KA_ID_ROTY					},
	{ "rotate instance / Z",			KA_ID_ROTZ					},
	// inverse rotations
	{ "inverse rotate instance / X",	KA_ID_ROTINVX				},
	{ "inverse rotate instance / Y",	KA_ID_ROTINVY				},
	{ "inverse rotate instance / Z",	KA_ID_ROTINVZ				},
	// translations
	{ "translate instance -> Left",		KA_ID_LEFT					},
	{ "translate instance -> Right",	KA_ID_RIGHT					},
	{ "translate instance -> On",		KA_ID_ON					},
	{ "translate instance -> Back",		KA_ID_BACK					},
	{ "translate instance -> Up",		KA_ID_UP					},
	{ "translate instance -> Down",		KA_ID_DOWN					},
	// T/R steps
	{ "increase rotation step",			KA_ID_INCROTATIONSTEP		},
	{ "decrease rotation step",			KA_ID_DECROTATIONSTEP		},
	{ "increase translation step",		KA_ID_INCTRANSLATIONSTEP	},
	{ "decrease translation step",		KA_ID_DECTRANSLATIONSTEP	},
	// constraints on axis
	{ "X constraint axis",				KA_ID_XCONSTRAINT			},
	{ "Y constraint axis",				KA_ID_YCONSTRAINT			},
	{ "Z constraint axis",				KA_ID_ZCONSTRAINT			},
    // scroll
	{ "move mouse in depth",			KA_ID_MOVEDEPTH				},
	{ "Warped move mouse in depth",		KA_ID_WARPOBJECTDEPTHMOVE	},
    { "camera follows instance",		KA_ID_MOVEDOBJECT			},    
	{ "mouse rotate Horizontal",		KA_ID_ROTATEOBJECTXY		},    
	{ "mouse rotate Vertical",			KA_ID_ROTATEOBJECTXZ		},
	// current sector
	{ "update current Sector",			KA_ID_SECTORSELECTION		}, 
	{ "Detect current sector",			KA_ID_SECTORWITHMOUSE		},
// Begin Silviu Simen 01 september 1998 List of Objects in Sectors
	{ "Select Sector",					KA_ID_SELECTSECTOR			},
// End Silviu Simen 01 september 1998 List of Objects in Sectors
 // end of list
	{ NULL, 0 }
};

tdstDLLIdentity g_stHierarchyIdentity;

#define M_xSgn(x) (x)
float sqr(float x);

//CPA2 Corneliu Babiuc 15-06-98
static EDT_SuperObject		* g_pReferenceInstance = NULL;
//END CPA2 Corneliu Babiuc 15-06-98

//#################################################################################
// CONSTRUCTOR
//#################################################################################
/*===========================================================================
	Constructor - init the lists from DLLs
=========================================================================*/
EDT_HierarchyEditor::EDT_HierarchyEditor (void)
{
	// ************************** private internal
	m_p_stDLLIdentity = &g_stHierarchyIdentity;
    
    // Does your DLL can output in main game view ?
	m_stBaseDLLDefinition.bCanOutputIn3DView = FALSE;

    // Does your DLL can be refresh by engine ?
	m_stBaseDLLDefinition.bCanBeRefreshedByEngine = TRUE;

	// init parameters
	m_pSpecificEditor = new EDT_SpecificEditor(this);

	SetMainWorld(NULL);
	SetCurrent(TRUE);

	// init infos
    SetEditorInfo(g_csEDTName, g_csEDTAuthor, g_csEDTVersion, g_csEDTFrenchHelpFile, g_csEDTEnglishHelpFile);

	// Init Mode
	m_eEditorMode = E_em_NoMode;
	m_bMultiSelectMode = FALSE;
	m_a_hCursors[C_hc_CurrentCursor] = NULL;

	// Init members
	m_stListToCopy.RemoveAll();
	// Init Move
	m_pMouseMove = NULL;
	m_pKeyMove   = NULL;
	m_eMouseMoveMode = E_mmm_NoMouseMove;
	m_bAvoidKeyRepeat = FALSE;
	// Init rotation and translation step
	m_xTranslationStep = (GLI_tdxValue) 0.02;
	m_xRotationStep = (GLI_tdxValue) 0.1;
	// Init orientation
	m_pOrientedObject = NULL;
	m_pOrientMove = NULL;
	m_bKeepOrientMode = FALSE;

	// Dialogs
	m_pDialogList = NULL;
	m_pDialogSelect = NULL;

	HINSTANCE hOldInst = AfxGetResourceHandle();
    AfxSetResourceHandle (GetDLLIdentity()->hModule);

	m_pDialogUpdate = new EDT_DialogUpdate();
	m_pDialogMove = new EDT_DialogMove();
	m_pDialogFlag = new EDT_DialogFlag();

	AfxSetResourceHandle(hOldInst);

	m_eModifCanceled = E_cm_NoCancel;
	m_csMessage.Empty();

	// Keys
	m_p_oDevKeyboard = new CPA_KeyActionConfiguration(C_szHierarchyIniFile, g_EDTKeyboardAction);
    m_p_oDevKeyboard->mfn_vSetObjectName("Hierarchy Editor");

    // Mouse moves
    m_bMovedObjectStaysOnScreen = FALSE;     
	m_bCanDisplayPopup = TRUE;
	m_bDoDialogSelect = FALSE;
	m_bDisableFirstMove = TRUE;

	// World
	m_bHasCurrentWorld = FALSE;

	// Super-Object Save
	m_csSOReferencePath.Empty();

	// modifications
	m_pListOfTempModifs = NULL;

	// teleportation
//CPA2 Corneliu Babiuc (multiple registration) 06-07-98
//	m_pRegisteredObject = NULL;
//	m_bIsASelection = FALSE;
//END CPA2 Corneliu Babiuc (multiple registration) 06-07-98
	// sector selection
	m_bSelectSector = FALSE;
	m_bSelectSectorWithMouse = FALSE;

// Begin Silviu Simen 18 August 1998 Cut/Paste Mechanism
	m_pRegisteredCuttedObject = NULL;
	m_bSpecialObject = FALSE;
// End Silviu Simen 18 August 1998 Cut/Paste Mechanism

}


/*===========================================================================
	Destructor
=========================================================================*/
EDT_HierarchyEditor::~EDT_HierarchyEditor()
{
	// Keys
	delete m_p_oDevKeyboard;
	m_p_oDevKeyboard = NULL;

	// copy / paste
	while (!m_stListToCopy.IsEmpty())
	{
		delete (m_stListToCopy.GetHead()->m_pChild);
		delete (m_stListToCopy.RemoveHead());
	}
}

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

BOOL EDT_HierarchyEditor::fn_bAcceptModifFlag	(CPA_SuperObject *pEdObj, unsigned long ulFlag)
{
	unsigned long ulType = HIE_fn_ulGetSuperObjectType(pEdObj->GetStruct());

	if (ulType != HIE_C_ulActor)
	{
		return TRUE;
	}
	else
	{
		if (ulFlag == HIE_C_Flag_ulNotHitByRayTrace || ulFlag == HIE_C_Flag_ulNoShadowOnMe)
			return FALSE;
	}
	return TRUE;
}





/*===========================================================================
	Init
=========================================================================*/
void EDT_HierarchyEditor::fn_vJustAfterRegistered (void)
{
	// modification list
    fn_vRegisterModificationsType (C_szSuperObjectTypeName, g_a_csTypeModifs, C_lNbTypeModifs);

	// scripts
	SCR_fn_v_RdL0_RegisterCallback("Edit-Modifications", EDT_HierarchyEditor::CallBackLoadListModif, SCR_CRC_c_RdL0_ForSection);
	SCR_fn_v_RdL0_RegisterCallback("Modif-SuperObject", EDT_SuperObject::CallBackLoadModif, SCR_CRC_c_RdL0_ForSection);
	// engine
	CPA_EdMot<HIE_tdxHandleToSuperObject>::Init(HIE_fn_hCreateSuperObject,HIE_fn_vCopySuperObject,HIE_fn_vDestroySuperObject);
}

/*===========================================================================
	Construct
=========================================================================*/
void EDT_HierarchyEditor::fn_vConstruct (void)
{
	CString	csFileName;
	char	szDimension[256];
	int		iDim;

	csFileName = M_GetMainApp()->m_csEditorDataPath + C_szHierarchyIniFile;

	// left frame width
	GetPrivateProfileString ("Preference", "Left Frame Width", "0", szDimension, 256, (char*)(LPCSTR)csFileName);
	iDim = atoi(szDimension);
	// Left Frame Window
	m_pLeftFrame = new CSplitFrame;
	m_pLeftFrame->CreateBase("LIST", 1, 2, GetMainWorld());
    m_pLeftFrame->m_iInitWidth = (iDim > 0) ? iDim : 180;
    m_pLeftFrame->m_iInitHeight = 0;
    m_pLeftFrame->mfn_vEnableCaption(FALSE);
    m_pLeftFrame->m_stWinBottom.cLinkSame = FRM_C_MoveRight;

	
	m_pLeftFrame->CreateSplitter(C_cVerticalSplitter,  3 );

	// DialogList dimension
	GetPrivateProfileString ("Preference", "DialogList Dimension", "0", szDimension, 256, (char*)(LPCSTR)csFileName);
	iDim = atoi(szDimension);
	// Dialog List
	m_pDialogList = new CPA_DialogList;
	m_pDialogList->fn_vInitDialog(this, m_pLeftFrame);
// FOR TUTORIAL
	TUT_M_vGetTutDll();

	TUT_M_vRegisterControl	(m_pDialogList->GetComboHandle(),	"EDT_DLIST_COMBO_CHOICE",	TUT_e_ComboBox);
	TUT_M_vRegisterControl	(m_pDialogList->GetListHandle(),	"EDT_DLIST_LIST_INSTANCES",	TUT_e_ListBox);
	TUT_M_vRegisterControl	(m_pDialogList->GetTreeHandle(),	"EDT_DLIST_TREE_HIERARCHY",	TUT_e_TreeCtrl);
// END TUTORIAL
	m_pLeftFrame->SetPaneView(0, m_pDialogList, "INSTANCES", (iDim > 0) ? iDim : 500);

	HINSTANCE hOldInst = AfxGetResourceHandle();
    AfxSetResourceHandle (GetDLLIdentity()->hModule);

	// DialogEdit dimension
	GetPrivateProfileString ("Preference", "DialogEdit Dimension", "0", szDimension, 256, (char*)(LPCSTR)csFileName);
	iDim = atoi(szDimension);
	// Dialog Edit
	m_pDialogEdit = new EDT_DialogEdit;
	m_pDialogEdit->fn_vInitDialog(this, m_pLeftFrame);
	m_pLeftFrame->SetPaneView(1, m_pDialogEdit, "EDIT", (iDim > 0) ? iDim : 404);

	// DialogSelect dimension
	GetPrivateProfileString ("Preference", "DialogSelect Dimension", "0", szDimension, 256, (char*)(LPCSTR)csFileName);
	iDim = atoi(szDimension);
	// Dialog Selectt
	m_pDialogSelect = new EDT_DialogSelect;
	m_pDialogSelect->fn_vInitDialog(this, m_pLeftFrame);
	m_pLeftFrame->SetPaneView(2, m_pDialogSelect, "SELECT", (iDim > 0) ? iDim : 250);
	AfxSetResourceHandle(hOldInst);
	m_pDialogSelect->m_edit = m_pDialogEdit;

	// Bottom Frame Height
	GetPrivateProfileString ("Preference", "Bottom Frame Height", "0", szDimension, 256, (char*)(LPCSTR)csFileName);
	iDim = atoi(szDimension);
	// Bottom Frame Window
	m_pBottomFrame = GetInterface()->GetModelFrame();
    m_pBottomFrame->m_iInitHeight = (iDim > 0) ? iDim : 120;
}

/*===========================================================================
	Create
=========================================================================*/
void EDT_HierarchyEditor::Create (void)
{
	CPA_HierarchyEditor::Create();

	// specific
	m_pSpecificEditor->fn_vSpecificInit();

	// cursors
	m_a_hCursors[C_hc_HierarchyCursor]	= LoadCursor(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDC_PARENTMODE));	
	m_a_hCursors[C_hc_PFatherCursor]	= LoadCursor(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDC_PASTEFATHER));	
	m_a_hCursors[C_hc_PPositionCursor]	= LoadCursor(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDC_PASTEPOS));		
	m_a_hCursors[C_hc_ChoiceCursor]		= LoadCursor(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDC_CHOICEMODE));	
	m_a_hCursors[C_hc_CopyAllCursor]	= LoadCursor(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDC_COPYALLMODE));		
	m_a_hCursors[C_hc_CopyAloneCursor]	= LoadCursor(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDC_COPYALONEMODE));
	m_a_hCursors[C_hc_MoveToCursor]		= LoadCursor(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDC_MOVETOMODE));	
	m_a_hCursors[C_hc_SelectToCursor]	= LoadCursor(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDC_MOVETOSELECT));
	m_a_hCursors[C_hc_OrientCursor]		= LoadCursor(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDC_ORIENTMODE));
	m_a_hCursors[C_hc_VOrientCursor]	= LoadCursor(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDC_VORIENTMODE));

	// icons for list
	m_oMainIconList.Create(16, 16, ILC_MASK, 0, 12);
	m_oMainIconList.Add(LoadIcon(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDI_UNKNOWN)));
	m_oMainIconList.Add(LoadIcon(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDI_SUPOBJ)));
	m_oMainIconList.Add(LoadIcon(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDI_ACTOR)));
	m_oMainIconList.Add(LoadIcon(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDI_CAMERA)));
	m_oMainIconList.Add(LoadIcon(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDI_GEOM)));
	m_oMainIconList.Add(LoadIcon(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDI_IPO)));
	m_oMainIconList.Add(LoadIcon(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDI_LIGHT)));
	m_oMainIconList.Add(LoadIcon(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDI_PHYSICAL)));
	m_oMainIconList.Add(LoadIcon(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDI_SECTOR)));
	m_oMainIconList.Add(LoadIcon(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDI_WAYPOINT)));
	m_oMainIconList.Add(LoadIcon(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDI_ZONE)));

	// icons for tree
	m_oTreeIconList.Create(16, 16, ILC_MASK, 0, 6);
	m_oTreeIconList.Add(LoadIcon(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDI_EDIT)));
	m_oTreeIconList.Add(LoadIcon(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDI_EDIT)));
	m_oTreeIconList.Add(LoadIcon(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDI_NOEDIT)));
	m_oTreeIconList.Add(LoadIcon(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDI_PEDIT)));
	m_oTreeIconList.Add(LoadIcon(GetDLLIdentity()->hModule, MAKEINTRESOURCE(EDT_IDI_PNOEDIT)));


}

//#################################################################################
//	FOCUS
//#################################################################################

/*===========================================================================
	Called just before engine loop
=========================================================================*/
void EDT_HierarchyEditor::fn_vBeforeEngine()
{
	CPA_Interface *pInterface = GetInterface();
	
// Begin Silviu Simen 18 August 1998 Cut/Paste Mechanism
	if (m_pRegisteredCuttedObject) 
	{
		if (m_bSpecialObject) 
		{
			EDT_SuperObject * m_pParent;

			m_pParent = m_pSpecificEditor->GetDefaultParentForPaste(m_pRegisteredCuttedObject);
			M_GetEditManager()->AskFor (new EDT_ModifInsert 
					(this, m_pRegisteredCuttedObject, m_pParent, NULL));
			m_pRegisteredCuttedObject=NULL;
			m_bSpecialObject = FALSE;

		};
	};
// End  Silviu Simen 18 August 1998 Cut/Paste Mechanism

	// disactivate all windows
	g_oFrameGest.mfn_vDisactivateWindow(m_pLeftFrame);
	g_oFrameGest.mfn_vDisactivateWindow(m_pBottomFrame);
	// save reference position
	m_pDialogUpdate->m_stRefMatrix = *(HIE_fn_hGetSuperObjectGlobalMatrix(M_GetEngineRoot()));
	// update menu
	GetMainWorld()->GetFRMBase()->fn_vUpdateCurrentEditor(NULL);
	// update state
	pInterface->SetInitialState(FALSE);
	m_csLoadingMessage = "Editor Ready";
	m_iLoadingStatus = C_STATUS_NORMAL;
	// enable fog
	GLI_vFogOn();
}


/*===========================================================================
	Update editor hierarchy after engine loop
=========================================================================*/
void EDT_HierarchyEditor::fn_vBeforeEditor()
{
	CPA_Interface	*pInterface = GetInterface();
	BOOL			bLoaded;
	
	// update menu
	GetMainWorld()->GetFRMBase()->fn_vUpdateCurrentEditor(GetMainWorld()->GetCurrentEditor());

	// editor map
	m_lNbUnknown = 0;
	bLoaded = fn_bLoadEditorMap();

	// Activate all Frame Windows
	if (fn_bIsCurrentEditor())
	{
		g_oFrameGest.mfn_vSetRefresh(FALSE);
		g_oFrameGest.mfn_vActivateWindow(m_pLeftFrame);
		g_oFrameGest.mfn_vActivateWindow(m_pBottomFrame);
		g_oFrameGest.mfn_vSetRefresh(TRUE);
	}

	if (!m_bHasCurrentWorld)
		return;

	// Update all views
	m_pBottomFrame->SetActiveView(pInterface->GetDialogInsert(), TRUE);
	m_pLeftFrame->SetActiveView(m_pDialogList, TRUE);

	// reinit hierarchy
	fn_vReinitEditorMap(!bLoaded);

	// update drawing
	if (bLoaded)
	{
		GetInterface()->fn_vLoadDisplayMode();
		GetInterface()->fn_vLoadOptions();
	}
	// disable fog
	GLI_vFogOff();

    GLI_vResetTableOfActiveLightsForChar( GLI_C_ActivateLight );
}


/*===========================================================================
		Save
=========================================================================*/
void fn_vSaveMatrix (FILE *pFile, GEO_tdxHandleToMatrix hMatrix)
{
	MTH3D_tdstVector		stVecI,stVecJ,stVecK;
	char					szText[MAX_PATH];

	// translation
	POS_fn_vGetTranslationVector(hMatrix,&stVecI);
	sprintf(szText, "\t Translation : ( %f, %f, %f )\n", 
		GLI_M_ValueToFloat(MTH3D_M_xGetXofVector(&stVecI)),
		GLI_M_ValueToFloat(MTH3D_M_xGetYofVector(&stVecI)),
		GLI_M_ValueToFloat(MTH3D_M_xGetZofVector(&stVecI)));
	fputs(szText, pFile);
	// rotation
	POS_fn_vGetRotationMatrix (hMatrix,&stVecI,&stVecJ,&stVecK);
	sprintf(szText, "\t Rotation    : ( %f, %f, %f, %f, %f, %f, %f, %f, %f )\n", 
		GLI_M_ValueToFloat(MTH3D_M_xGetXofVector(&stVecI)),
		GLI_M_ValueToFloat(MTH3D_M_xGetYofVector(&stVecI)),
		GLI_M_ValueToFloat(MTH3D_M_xGetZofVector(&stVecI)),
		GLI_M_ValueToFloat(MTH3D_M_xGetXofVector(&stVecJ)),
		GLI_M_ValueToFloat(MTH3D_M_xGetYofVector(&stVecJ)),
		GLI_M_ValueToFloat(MTH3D_M_xGetZofVector(&stVecJ)),
		GLI_M_ValueToFloat(MTH3D_M_xGetXofVector(&stVecK)),
		GLI_M_ValueToFloat(MTH3D_M_xGetYofVector(&stVecK)),
		GLI_M_ValueToFloat(MTH3D_M_xGetZofVector(&stVecK)));
	fputs(szText, pFile);
	// scale
	POS_fn_vGetScaleMatrix (hMatrix,&stVecI,&stVecJ,&stVecK);
	sprintf(szText, "\t Scale       : ( %f, %f, %f, %f, %f, %f, %f, %f, %f )\n", 
		GLI_M_ValueToFloat(MTH3D_M_xGetXofVector(&stVecI)),
		GLI_M_ValueToFloat(MTH3D_M_xGetYofVector(&stVecI)),
		GLI_M_ValueToFloat(MTH3D_M_xGetZofVector(&stVecI)),
		GLI_M_ValueToFloat(MTH3D_M_xGetXofVector(&stVecJ)),
		GLI_M_ValueToFloat(MTH3D_M_xGetYofVector(&stVecJ)),
		GLI_M_ValueToFloat(MTH3D_M_xGetZofVector(&stVecJ)),
		GLI_M_ValueToFloat(MTH3D_M_xGetXofVector(&stVecK)),
		GLI_M_ValueToFloat(MTH3D_M_xGetYofVector(&stVecK)),
		GLI_M_ValueToFloat(MTH3D_M_xGetZofVector(&stVecK)));
	fputs(szText, pFile);
}

void EDT_HierarchyEditor::fn_vBeforeSaveAll (void)
{
// Begin Silviu Simen 18 August 1998 Cut/Paste Mechanism
	if (m_pRegisteredCuttedObject)
	{
		if (m_bSpecialObject) 
		{
			EDT_SuperObject * m_pParent;

			m_pParent = m_pSpecificEditor->GetDefaultParentForPaste(m_pRegisteredCuttedObject);
			M_GetEditManager()->AskFor (new EDT_ModifInsert 
					(this, m_pRegisteredCuttedObject, m_pParent, NULL));
			m_pRegisteredCuttedObject=NULL;
			m_bSpecialObject = FALSE;
		};
	};
// End  Silviu Simen 18 August 1998 Cut/Paste Mechanism
	return;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method : fn_vAfterSaveAll 
// Date   : 98-03
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description :
// Author      : Stegaru Cristian - CPA2
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Modification :
// Date         :
// By           :
//////////////////////////////////////////////////////////////////////////////////////////////////////
void EDT_HierarchyEditor::fn_vAfterSaveAll (void)
{
	char *szLevelsRelativePath = fn_szGetLevelsDataPath ();
	char *szClassesRelativePath = fn_szGetGraphicsClassesDataPath ();
	char *szBanksRelativePath = fn_szGetGraphicsBanksDataPath ();
	char *szMaterialRelativePath = fn_szGetGameMaterialDataPath ();
	char *szVisualRelativePath = fn_szGetVisualMaterialDataPath ();

	char szBaseRoot [_MAX_PATH];
	GetModuleFileName (NULL, szBaseRoot, _MAX_PATH);
	CString csBaseRoot (szBaseRoot);
	int iInx = csBaseRoot.ReverseFind ('\\');
	ASSERT (-1 != iInx);
	csBaseRoot = csBaseRoot.Left (iInx + 1);
	CString csRootClasses, csRootBanks, csRootLevels, csRootMaterials, csRootVisuals;
	csRootClasses = csBaseRoot + szClassesRelativePath + "\\";
	csRootBanks = csBaseRoot + szBanksRelativePath + "\\";
	csRootLevels = csBaseRoot + szLevelsRelativePath + "\\";
	csRootMaterials = csBaseRoot + szMaterialRelativePath + "\\";
	csRootVisuals = csBaseRoot + szVisualRelativePath + "\\";

	CParseSection parseSection;
	parseSection.AddRoot (csRootClasses);
	parseSection.AddRoot (csRootBanks);
	parseSection.AddRoot (csRootLevels);
	parseSection.AddRoot (csRootMaterials);
	parseSection.AddRoot (csRootVisuals);
	parseSection.AddRoot (csBaseRoot);
	
	EDT_SpecificEditor *pSpecificEditor = GetSpecificEditor ();
	ASSERT (pSpecificEditor);
	CString csStaticFileName = pSpecificEditor->GetStaticFileName ();
	int iPos = csStaticFileName.ReverseFind ('.');
	ASSERT (-1 != iPos);

	CString csInitialMDFFile = csStaticFileName.Left (iPos) + szModifExt;
	csInitialMDFFile = csRootLevels + csInitialMDFFile;
	CString csFinalMDFFile = csStaticFileName.Left (iPos) + szFinalModifExt;
	csFinalMDFFile = csRootLevels + csFinalMDFFile;

	{
		CWaitCursor wait;
		parseSection.ParseFile (csInitialMDFFile, csFinalMDFFile);
	}
}


//#################################################################################
// ENGINE
//#################################################################################

/*===========================================================================
		accept to run engine
=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bAcceptToRunEngine(void)
{
	return TRUE;
}

//#################################################################################
// END APPLI
//#################################################################################

/*===========================================================================
		accept to close
=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bAcceptToExit(void)
{
	return TRUE;
}

/*===========================================================================
		before closing
=========================================================================*/
void EDT_HierarchyEditor::fn_vJustBeforeClosing(void)
{
}


//#################################################################################
// KEYBOARD
//#################################################################################

/*===========================================================================
		KeyDown
=========================================================================*/
BOOL EDT_HierarchyEditor::_OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	if (!m_bHasCurrentWorld)
		return FALSE;

	unsigned short uwAction = m_p_oDevKeyboard->mfn_uwKeyToAction(nChar);
	switch (uwAction)
	{
// Begin Silviu Simen 01 september 1998 List of Objects in Sectors
		case KA_ID_SELECTSECTOR:
			fn_vSelectBySectorAndType();
			return TRUE;
// End Silviu Simen 01 september 1998 List of Objects in Sectors
		// memorise the selected object ( if there is one and only one ) 
		case KA_ID_REGISTERSELECTION :
//CPA2 Corneliu Babiuc (multiple registration) 03-07-98
		case KA_ID_ADDDELREGISTRATION :
			if (nRepCnt >1 ) return TRUE;
			// now allow to register a multiple selection
			if (M_GetWorld()->GetCountSelected() > 0)
			{
//					m_pRegisteredObject = (EDT_SuperObject *) M_GetWorld()->GetSingleSelection();
//					m_bIsASelection = TRUE;
				//if user doesn't press the SHIFT key, then cancel previous registration
				if (uwAction == KA_ID_REGISTERSELECTION)
					GetInterface()->fn_vCancelCurrentRegistration();
				//update registration list
				GetInterface()->fn_vUpdateRegistrationFromSelection(M_GetWorld()->GetListSelected());
				//set the cursor
				SetEditorMode(E_em_RegisterSelection);
				M_GetMainWnd()->UpdateStatus("Objects were registered ", C_STATUSPANE_INFOS, C_STATUS_NORMAL);
			}
//CPA2 Corneliu Babiuc TMS_0598 27-05-98
			//if no selection, clear the registered object
			else
//			if (M_GetWorld()->GetCountSelected() == 0)
			{
//					m_pRegisteredObject = NULL;
//					m_bIsASelection = FALSE;
				GetInterface()->fn_vCancelCurrentRegistration();
				SetEditorMode(E_em_ClearRegistration);
				M_GetMainWnd()->UpdateStatus("The registration list was cleared", C_STATUSPANE_INFOS, C_STATUS_NORMAL);
			}
//END CPA2 Corneliu Babiuc TMS_0598 27-05-98
//END CPA2 Corneliu Babiuc (multiple registration) 03-07-98
			return TRUE;

		// delete selected objects
		case KA_ID_DEL :
			if (M_GetWorld()->GetCountSelected())
			{
				if (fn_bCanDeleteAllObjects())
					M_GetEditManager()->AskFor (new EDT_ModifDelete
						(this, M_GetWorld()->GetListOfListByDLL(), GetInterface()->GetSelectMode()));
				else
					m_eModifCanceled = E_cm_CancelDelete;
				fn_vDisplayCancelMessage(m_eModifCanceled);
			}
			return TRUE;

		// move to mode
		case KA_ID_MOVETO:
			SetEditorMode(E_em_MoveToMode);
			return TRUE;

// Begin Silviu Simen 18 August 1998 Cut/Paste Mechanism
		case KA_ID_CUT:
			if (M_GetWorld()->GetCountSelected() == 1) 
			{
				if (m_pRegisteredCuttedObject) 
				{
					if (!m_bSpecialObject) 
					{
						if (IDYES == MessageBox(NULL,
								"  You have registered an instance : " + m_pRegisteredCuttedObject ->GetName() + "\n"
								"              Do you want to loose it ? \n\n"
								"      If you press YES, instance will be lost.\n"
								"If you press NO, the current selection will not be cut.\n"
								,"Unregister or Keep Instance",
								MB_YESNO | MB_ICONQUESTION ))
						{
							m_bSpecialObject = FALSE;

							m_pRegisteredCuttedObject = (EDT_SuperObject *) M_GetWorld()->GetSingleSelection();

							if (fn_bObjectIsSpecial()) 	
								m_bSpecialObject = TRUE;
							M_GetEditManager()->AskFor (new EDT_ModifDelete
									(this, M_GetWorld()->GetListOfListByDLL(), 
									GetInterface()->GetSelectMode(),TRUE,FALSE,TRUE,FALSE,m_bSpecialObject));
						}
					} 
					else 
					{
						MessageBox(NULL,
								"You have registered a special object: " + m_pRegisteredCuttedObject ->GetName() + "\n"
								"The current selection cannot be cut before reinserting this special object.",
								"Special Object Already Registered !",
								MB_OK|MB_ICONINFORMATION);

						m_csMessage = "A special object :" + m_pRegisteredCuttedObject -> GetName() + "is already registered";
					}
				}
				else 
				{
					m_bSpecialObject = FALSE;

					m_pRegisteredCuttedObject = (EDT_SuperObject *) M_GetWorld()->GetSingleSelection();

					if (fn_bObjectIsSpecial()) 	
						m_bSpecialObject = TRUE;
					M_GetEditManager()->AskFor (new EDT_ModifDelete
							(this, M_GetWorld()->GetListOfListByDLL(), 
							GetInterface()->GetSelectMode(),TRUE,FALSE,TRUE,FALSE,m_bSpecialObject));
				}
			}
			return TRUE;
// End Silviu Simen 18 August 1998 Cut/Paste Mechanism


//CPA2 Corneliu Babiuc 14-06-98
		// specific teleportation
		case KA_ID_MOVETOINSTANCE:
			SetEditorMode(E_em_MoveToInstance);
			return TRUE;

		case KA_ID_MOVETOCAMERA:
			// if there is an object selected or if there is an object registered
			if ( ( M_GetWorld()->GetCountSelected() == 1 || /*m_bIsASelection CPA2 Corneliu Babiuc (multiple registration)*/
				M_GetWorld()->GetCountRegistered() == 1) && nRepCnt ==1)
				fn_vMoveToCameraPosition();
			else 
				if (M_GetWorld()->GetCountSelected() > 1 ||/*CPA2 Corneliu Babiuc (multiple registration)*/
					M_GetWorld()->GetCountRegistered()>1 )
				{
					m_csMessage = "Editor could not teleport multiple selection to camera position";
					fn_vDisplayCancelMessage(m_eModifCanceled);
				}
			return TRUE;
		// teleport camera
		case KA_ID_MOVECAMERATOINSTANCE:
			SetEditorMode(E_em_MoveCameraToInstance);
			break;
		case KA_ID_MOVECAMERACENTERED:
			SetEditorMode(E_em_MoveCameraCentered);
			break;

		// choose translation vector
		case KA_ID_CHOOSEVECTOR:
			// if there is no selected object, do nothing
			if ( M_GetWorld()->GetCountSelected() > 0 )
			{
				if ( !fn_bCanTranslateAllObjects() )
				{
					m_csMessage = "Some objects connot be moved";
					fn_vDisplayCancelMessage(m_eModifCanceled);
					return TRUE;
				}
				EDT_DialogVector	dlg;
				MTH3D_tdstVector	stTranslation;
				// Invoke the dialog box
				if (dlg.DoModal() == IDOK)
				{
					// retrieve the dialog data
					MTH3D_M_vSetVectorElements(&stTranslation, dlg.m_xComponentX, dlg.m_xComponentY, dlg.m_xComponentZ);
					fn_vTranslateObjects(&stTranslation);
				}
			}
			return TRUE;
//END CPA2 Corneliu Babiuc 17-06-98

		// orient mode
		case KA_ID_ORIENTINSTANCE:
			if (fn_bCanOrientSelection())
			{
				SetEditorMode(E_em_OrientMode);
				m_bKeepOrientMode = TRUE;
			}
			return TRUE;

		case KA_ID_ORIENTVERTICAL:
			if (fn_bCanOrientSelection())
			{
				SetEditorMode(E_em_VOrientMode);
				m_bKeepOrientMode = TRUE;
			}
			return TRUE;

		// Copy Instance
		case KA_ID_ALONE :
// Begin Silviu Simen 18 August 1998 Cut/Paste Mechanism
			if (m_pRegisteredCuttedObject) 
			{
				if (! m_bSpecialObject) 
				{
					if (IDYES == MessageBox(NULL,
							"  You have registered an instance : " + m_pRegisteredCuttedObject ->GetName() + "\n"
							"              Do you want to loose it ? \n\n"
							"      If you press YES, instance will be lost.\n"
							"If you press NO, next Paste will apply to this instance.\n"
							,"Unregister or Keep Instance",
							MB_YESNO | MB_ICONQUESTION ))
						m_pRegisteredCuttedObject = NULL;
				} 
				else 
				{
					MessageBox(NULL,
							"You have registered an special object: " + m_pRegisteredCuttedObject ->GetName() + "\n"
							"Next Paste  will be applied to this object.",
							"Special Object Already Registered !",
							MB_OK|MB_ICONINFORMATION);
				}
			};
// End Silviu Simen 18 August 1998 Cut/Paste Mechanism

			if (M_GetWorld()->GetCountSelected() == 1)
				fn_vInitModifCopy(TRUE);
			return TRUE;
		// Copy Selection
		case KA_ID_COPY :
// Begin Silviu Simen 18 August 1998 Cut/Paste Mechanism
			if (m_pRegisteredCuttedObject) 
			{
				if (! m_bSpecialObject) 
				{
					if (IDYES == MessageBox(NULL,
							"  You have registered an instance : " + m_pRegisteredCuttedObject ->GetName() + "\n"
							"              Do you want to loose it ? \n\n"
							"      If you press YES, instance will be lost.\n"
							"If you press NO, next Paste will apply to this instance.\n"
							,"Unregister or Keep Instance",
							MB_YESNO | MB_ICONQUESTION ))
						m_pRegisteredCuttedObject = NULL;
				} 
				else 
				{
					MessageBox(NULL,
							"You have registered an special object: " + m_pRegisteredCuttedObject ->GetName() + "\n"
							"Next Paste  will be applied to this object.",
							"Special Object Already Registered !",
							MB_OK|MB_ICONINFORMATION);
				}
			};
// End Silviu Simen 18 August 1998 Cut/Paste Mechanism
			if (M_GetWorld()->GetCountSelected())
				fn_vInitModifCopy(FALSE);
			return TRUE;
		// Paste under same parent
		case KA_ID_PASTESAME :
			if (m_stListToCopy.GetCount())
				fn_vInitModifPaste (E_pm_PasteSame);
			return TRUE;
		// Paste under default parent
		case KA_ID_PASTEDEFAULT :
			if (m_stListToCopy.GetCount())
				fn_vInitModifPaste (E_pm_PasteDefault);
			return TRUE;
		// Paste under chosen father
		case KA_ID_PASTEFATHER :
			if (m_stListToCopy.GetCount() == 1)
				SetEditorMode(E_em_ParentMode);
			return TRUE;
		// Paste at chosen position
		case KA_ID_PASTEPOS :
// Begin Silviu Simen 18 August 1998 Cut/Paste Mechanism
			if (m_pRegisteredCuttedObject)
			{
				SetEditorMode(E_em_CutPasteMode);
			}
			else 
// End Silviu Simen 18 August 1998 Cut/Paste Mechanism
			if (m_stListToCopy.GetCount() == 1)
				SetEditorMode(E_em_PositionMode);
			return TRUE;

		// Init parent mode
		case KA_ID_PARENT :
			if (M_GetWorld()->GetCountSelected())
			{
				if (fn_bCanChangeAllParents())
					SetEditorMode(E_em_HierarchyMode);
				else
					m_eModifCanceled = E_cm_CancelParent;
				fn_vDisplayCancelMessage(m_eModifCanceled);
			}
			return TRUE;
		// Init selection mode
		case KA_ID_MULTI :
			if (fn_bCanEnterMultiMode())
			   m_bMultiSelectMode = TRUE;
			return TRUE;
		case KA_ID_PYRAMID :
			if (fn_bCanEnterMultiMode())
			   SetEditorMode(E_em_PyramidMode);
			return TRUE;
		case KA_ID_MULTIPYRAMID :
			if (fn_bCanEnterMultiMode())
			{
			   SetEditorMode(E_em_PyramidMode);
			   m_bMultiSelectMode = TRUE;
			}
			return TRUE;

		// move mode
		case KA_ID_WARPOBJECTDEPTHMOVE: //this one is specific only for object move
		case KA_ID_MOVEDEPTH:
			{
				if (!m_bAvoidKeyRepeat)
				{
					m_bAvoidKeyRepeat = TRUE;
					MTH3D_tdstVector XAxe, YAxe;
					MTH3D_M_vSetVectorElements(&XAxe, 1.0, 0.0, 0.0);
					MTH3D_M_vSetVectorElements(&YAxe, 0.0, 0.0, 1.0);
					GetInterface()->SetPlaneForMouseMove(&XAxe, &YAxe);
					//Selection Pyramid Begin
					GetInterface()->fn_vInitPyramidDepth(TRUE);
					GetInterface()->fn_vSetMouseMovePlane((uwAction == KA_ID_WARPOBJECTDEPTHMOVE) ? E_mmp_Warped : E_mmp_Standard);
					GetInterface()->SetPyramidDepthMode(TRUE);
				}
			}
			return TRUE;

		// mouse rotate object
		case KA_ID_ROTATEOBJECTXY:
			if ( m_eMouseMoveMode != E_mmm_MouseRotateXY)
			{
				if ( fn_bCanRotateAllObjects() && m_eMouseMoveMode )
					m_eMouseMoveMode = E_mmm_MouseRotateXY;
				else
					m_eModifCanceled = E_cm_CancelMove;
				fn_vDisplayCancelMessage(m_eModifCanceled);
			}
			return TRUE;
		case KA_ID_ROTATEOBJECTXZ:
			if ( m_eMouseMoveMode != E_mmm_MouseRotateXZ)
			{
				if ( fn_bCanRotateAllObjects() && m_eMouseMoveMode )
					m_eMouseMoveMode = E_mmm_MouseRotateXZ;
				else
					m_eModifCanceled = E_cm_CancelMove;
				fn_vDisplayCancelMessage(m_eModifCanceled);
			}
			return TRUE;

        // camera moves
		case KA_ID_MOVEDOBJECT:
            if (! m_bMovedObjectStaysOnScreen)
            {
                m_bMovedObjectStaysOnScreen = TRUE;
            }
            return TRUE;

		// rotations
		case KA_ID_ROTX :
			fn_vRotateObjects(AXE_X);
			return TRUE;
		case KA_ID_ROTY :
			fn_vRotateObjects(AXE_Y);
			return TRUE;
		case KA_ID_ROTZ :
			fn_vRotateObjects(AXE_Z);
			return TRUE;
//CPA2 Corneliu Babiuc 18-05-98
		//inverse rotation
		case KA_ID_ROTINVX :
			fn_vRotateObjects(AXE_X,1);
			return TRUE;
		case KA_ID_ROTINVY :
			fn_vRotateObjects(AXE_Y,1);
			return TRUE;
		case KA_ID_ROTINVZ :
			fn_vRotateObjects(AXE_Z,1);
			return TRUE;
		case KA_ID_INCROTATIONSTEP:
			fn_vSetRotationStep(C_xRotationStep + fn_xGetRotationStep());
			return TRUE;
		case KA_ID_DECROTATIONSTEP:
			fn_vSetRotationStep(fn_xGetRotationStep() - C_xRotationStep );
			return TRUE;
		case KA_ID_INCTRANSLATIONSTEP:
			fn_vSetTranslationStep(C_xTranslationStep + fn_xGetTranslationStep());
			return TRUE;
		case KA_ID_DECTRANSLATIONSTEP:
			fn_vSetTranslationStep(fn_xGetRotationStep() - C_xTranslationStep );
			return TRUE;
//END CPA2 Corneliu Babiuc 20-05-98

		// translations
		case KA_ID_LEFT :
			fn_vTranslateObjects(AXE_X, 1);
			return TRUE;
		case KA_ID_RIGHT :
			fn_vTranslateObjects(AXE_X, 0);
			return TRUE;
		case KA_ID_UP :
			fn_vTranslateObjects(AXE_Y, 1);
			return TRUE;
		case KA_ID_DOWN :
			fn_vTranslateObjects(AXE_Y, 0);
			return TRUE;
		case KA_ID_ON :
			fn_vTranslateObjects(AXE_Z, 1);
			return TRUE;
		case KA_ID_BACK :
			fn_vTranslateObjects(AXE_Z, 0);
			return TRUE;

		// selection choice
		case KA_ID_CHOICE :
			SetEditorMode(E_em_ChoiceMode);
			return TRUE;

		// current sector
		case KA_ID_SECTORSELECTION:
			m_bSelectSector = !m_bSelectSector;
			return TRUE;

		case KA_ID_SECTORWITHMOUSE:
			m_bSelectSectorWithMouse = TRUE;
			return TRUE;

//CPA2 Corneliu Babiuc 15-05-98
		// put on ground
		case KA_ID_PUTONGROUND:
			fn_vPutOnGround();
			return TRUE;

		//constraints on axis
		case KA_ID_XCONSTRAINT:
			GetInterface()->GetFrameBase()->m_oGeneralDialogBar.fn_vUpdateConstraints(CPA_MASK_CONSTRAINTX);
			return TRUE;
		case KA_ID_YCONSTRAINT:
			GetInterface()->GetFrameBase()->m_oGeneralDialogBar.fn_vUpdateConstraints(CPA_MASK_CONSTRAINTY);
			return TRUE;
		case KA_ID_ZCONSTRAINT:
			GetInterface()->GetFrameBase()->m_oGeneralDialogBar.fn_vUpdateConstraints(CPA_MASK_CONSTRAINTZ);
			return TRUE;
		// SuperObject Flags
		case KA_ID_SUPEROBJECTFLAGS:
			// get selected superobject
			//  the action will be performed if only one object is selected
			if ( M_GetWorld()->GetCountSelected() == 1 )
				fn_vDoDialogFlags( (EDT_SuperObject *) M_GetSingleSelection() );
			return TRUE;
//END CPA2 Corneliu Babiuc 21-05-98

		// not an editor key
		default :
			break;
	}

	if (m_bSelectSector)
	{
		tdeDisplayMode	mode;
		mode  = GetInterface()->GetSpecificInterface()->GetDisplayMode();
		if(mode == 	E_dm_DrawVisibleSectors || mode == E_dm_DrawOnlyCurrentSector)
		{
			DEV_ViewPort3D				*pCurViewport; 
			CPA_BaseObject				*p_oCamera;
			CPA_CameraCoords			oCoords;
			CPA_CameraDLLBase			*p_oCameraInterface;
			POS_tdstCompletePosition    stCameraMatrix;
			MTH3D_tdstVector			point;

			pCurViewport = (DEV_ViewPort3D *)GetInterface()->GetMultiDevice3D()->GetFocusDevice()->GetViewPort();
			p_oCamera = pCurViewport->GetCamera();
			p_oCameraInterface = pCurViewport->GetCameraInterface();
			POS_fn_vSetIdentityMatrix(&stCameraMatrix);
			p_oCameraInterface->GetMatrix(p_oCamera, &stCameraMatrix);
			point.xX = 0;
			point.xY = 0;
			point.xZ = 10;
			POS_fn_vMulMatrixVertex(&point, &stCameraMatrix, &point);

			CPA_SuperObject *sector = GetInterface()->GetSpecificInterface()->GetCurrentSectorFromPos(&point);
			if (sector) 
				GetInterface()->GetSpecificInterface()->SetCurrentSector	(sector);
		}
	}

	//key not processed
	return FALSE;
}


/*===========================================================================
		KeyUp
=========================================================================*/

BOOL EDT_HierarchyEditor::_OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	if (!m_bHasCurrentWorld)
		return FALSE;

	switch (m_p_oDevKeyboard->mfn_uwKeyToAction(nChar))
	{
		// create the Modif corresponding to the last move
		case KA_ID_RIGHT :
		case KA_ID_BACK :
		case KA_ID_DOWN :
		case KA_ID_LEFT :
		case KA_ID_ROTX :
		case KA_ID_ROTY :
		case KA_ID_ROTZ :
		case KA_ID_ON :
		case KA_ID_UP :
			if ((M_GetWorld()->GetCountSelected()) && (m_pKeyMove))
			{
				fn_bDoOrCancelMove(m_pKeyMove);
				m_pKeyMove = NULL;
			}
			return TRUE;

		// update selection mode
		case KA_ID_MULTI:
			m_bMultiSelectMode = FALSE;
			return TRUE;
		case KA_ID_PYRAMID:
			SetEditorMode(E_em_NoMode);
			return TRUE;
		case KA_ID_MULTIPYRAMID:
			m_bMultiSelectMode = FALSE;
			return TRUE;

		// update mode

// Begin Silviu Simen 18 August 1998 Cut/Paste Mechanism
		case KA_ID_CUT:
// End   Silviu Simen 18 August 1998 Cut/Paste Mechanism
		case KA_ID_CHOICE:
		case KA_ID_PARENT:
		case KA_ID_ALONE:
		case KA_ID_COPY:
		case KA_ID_PASTEFATHER:
		case KA_ID_PASTEPOS:
		case KA_ID_MOVETO:
//CPA2 Corneliu Babiuc 14-06-98
		case KA_ID_MOVETOINSTANCE:
		case KA_ID_MOVECAMERATOINSTANCE:
		case KA_ID_MOVECAMERACENTERED:
		case KA_ID_REGISTERSELECTION : //CPA2 Corneliu Babiuc (multiple registration) 07-06-98
//END CPA2 Corneliu Babiuc 17-06-98
			SetEditorMode(E_em_NoMode);
			return TRUE;

		case KA_ID_ORIENTINSTANCE:
			SetEditorMode(E_em_NoMode);
			m_bKeepOrientMode = FALSE;
			return TRUE;

		case KA_ID_ORIENTVERTICAL:
			SetEditorMode(E_em_NoMode);
			m_bKeepOrientMode = FALSE;
			return TRUE;

		case KA_ID_WARPOBJECTDEPTHMOVE:
			if ( GetInterface()->fn_eGetMouseMovePlane() == E_mmp_Warped )
				GetInterface()->fn_vSetMouseMovePlane(E_mmp_Standard);
			//fall through

		case KA_ID_MOVEDEPTH:
			m_bAvoidKeyRepeat = FALSE;
			// Now, mouse will move back into default plane (X,Y) (related to camera)
			//m_bMouseMoveInDepth = FALSE;
			MTH3D_tdstVector XAxe, YAxe;
			MTH3D_M_vSetVectorElements(&XAxe, 1.0, 0.0, 0.0);
			MTH3D_M_vSetVectorElements(&YAxe, 0.0, 1.0, 0.0);
			GetInterface()->SetPlaneForMouseMove(&XAxe, &YAxe);
			// Selection Pyramid
			GetInterface()->fn_vInitPyramidDepth(FALSE);
			//GetInterface()->m_vSetMouseMovePlane(E_mmp_None);
			//CPA_Ed_1 begin DCerbu
			GetInterface()->SetPyramidDepthMode(FALSE);
			//CPA_Ed_1 end DCerbu

			return TRUE;

		case KA_ID_MOVEDOBJECT:
			m_bMovedObjectStaysOnScreen = FALSE;
			return TRUE;

		case KA_ID_ROTATEOBJECTXY:
		case KA_ID_ROTATEOBJECTXZ:
			if ( m_eMouseMoveMode )
				m_eMouseMoveMode = E_mmm_MouseMove;
			else
				m_eMouseMoveMode = E_mmm_NoMouseMove;
			return TRUE;

		case KA_ID_SECTORWITHMOUSE:
			m_bSelectSectorWithMouse = FALSE;
			return TRUE;
		default :
			break;
	}


	//key not processed
	return FALSE;
}



//#################################################################################
// MOUSE
//#################################################################################

/*===========================================================================
		MouseMove
=========================================================================*/

BOOL EDT_HierarchyEditor::_OnMouseMove(UINT nFlags, tdstMousePos *p_stPos, MTH3D_tdstVector *p_stVector)
{
	CPA_ObjectDLLBase	*p_oDLL;
	MTH3D_tdstVector	stOrientPosition, stNewPos;
	EDT_SuperObject		*pSupObj;
	CPA_SuperObject		*pElem;
	tdstPosition		stPosition;
	POSITION			pos;
	BOOL				bRes = FALSE;
	float				fMoved, fRequest;
					


	if (!m_bHasCurrentWorld)
		return FALSE;

	if (m_bDisableFirstMove)
	{
		m_bDisableFirstMove = FALSE;
		return FALSE;
	}
	
	if (GetInterface()->fn_bDoSelectionPyramid(p_stPos))
		return TRUE;

	// orient mode
	if ((m_eEditorMode == E_em_OrientMode)||(m_eEditorMode == E_em_VOrientMode))
	{
		// check selection
		if (!m_pOrientedObject)
			return TRUE;
		// find position
		stPosition.stPos.stPos2D = p_stPos->stPos2D;
		if (!fn_bFindPickingPosition(&stPosition))
			return TRUE;

		// ask DLL for custom orientation
		p_oDLL = m_pOrientedObject->GetObjectDLL();
		if (p_oDLL)
			bRes = p_oDLL->fn_bOnOrientingObject(m_pOrientedObject, &stPosition);
		// get picking position
		if ((!bRes)&&(m_pOrientMove))
		{
			// get picking position
			stOrientPosition = stPosition.a_stPickInfo->stPickedObject.aDEF_stDataOfElement[0].stHit;
			// orient object
			if (m_eEditorMode == E_em_OrientMode)
				fn_vOrientToPosition(m_pOrientedObject, &stOrientPosition);
			else
				fn_vOrientWithVertical(m_pOrientedObject, &stOrientPosition);
		}
		return TRUE;
	}	
	
	// move the selected object
	if ((m_eMouseMoveMode)&&(p_stVector)&&(M_GetWorld()->GetCountSelected() > 0))
	{
		// first call : init the parameters and check permission
		if (!m_pMouseMove)
		{
			//remember the position of the mouse
			if ((fn_bMouseRotatesObjects() && fn_bCanRotateAllObjects())
			  ||(fn_bCanTranslateAllObjects()))
			{
				// tell Dlls
				fn_vSendMessageBeginMove();
				// create modif
				m_pMouseMove = new EDT_ModifMove(this, M_GetWorld()->GetListOfListByDLL(), GetInterface()->GetSelectMode());
			}
			else
			{
				m_eModifCanceled = E_cm_CancelMove;
				m_eMouseMoveMode = E_mmm_NoMouseMove;
				return FALSE;
			}
		}

		// move is a rotation
		if (fn_bMouseRotatesObjects())
		{
			POS_tdstCompletePosition stMatrix;

			POS_fn_vSetIdentityMatrix(&stMatrix);

			//get the corresponding 2d movement in the camera's plane
			GLI_tdst2DVertex     stDelta2D;
			p_stVector->xX = p_stPos->stPos3D.xX + p_stVector->xX * 10;
			p_stVector->xY = p_stPos->stPos3D.xY + p_stVector->xY * 10;
			p_stVector->xZ = p_stPos->stPos3D.xZ + p_stVector->xZ * 10;
			// get the position after the mouse move
			M_GetViewPort3d()->Convert3dTo2d(&stDelta2D, p_stVector);
			// now we can compute the difference with the old position
			stDelta2D.xX = (stDelta2D.xX - p_stPos->stPos2D.xX) / 10;
			stDelta2D.xY = (stDelta2D.xY - p_stPos->stPos2D.xY) / 10;

			// nullify the vector because the object won't move
			MTH3D_M_vNullVector(p_stVector);
			// update all objects in the list
			POS_fn_vSetIdentityMatrix(&stMatrix);
			if (abs((int) stDelta2D.xX) > abs((int) stDelta2D.xY))
				fn_vRotateX(&stMatrix, (float) (M_xSgn(stDelta2D.xX) * 0.1));
			else
			{
				if (m_eMouseMoveMode == E_mmm_MouseRotateXY)
					fn_vRotateY(&stMatrix, (float) (M_xSgn(stDelta2D.xY) * 0.1));
				else
					fn_vRotateZ(&stMatrix, (float) (M_xSgn(stDelta2D.xY) * 0.1));
			}

			// update all objects in the list
			for (pElem = M_GetWorld()->GetListSelected()->GetHeadElement(pos); pElem;
				 pElem = M_GetWorld()->GetListSelected()->GetNextElement(pos))
			{
				pSupObj = (EDT_SuperObject *) pElem;
				pSupObj->fn_vRotate(&stMatrix);
			}
			// tell DLLs
			fn_vSendMessageMoving();
		}
		
		// move is a translation
		else 
		{
			MTH3D_tdstVector stNewVector = *p_stVector;

			// lock selection
			if (GetInterface()->GetLockSelection())
			{
				MTH3D_tdstVector prj1, prj2;
				// get first selected object
				pElem = M_GetWorld()->GetListSelected()->GetHeadElement(pos);	
				if (pElem)
				{
					GetInterface()->fn_vGetScreenProjection(pElem, &prj1);
					((EDT_SuperObject *)pElem)->fn_vTranslate(p_stVector, TRUE);
					GetInterface()->fn_vGetScreenProjection(pElem, &prj2);
					
					fMoved = sqr(prj1.xX - prj2.xX) + sqr(prj1.xY - prj2.xY);
					fRequest = sqr(p_stPos->stPos2D.xX - m_stLBDownMousePos.stPos2D.xX) + sqr(p_stPos->stPos2D.xY - m_stLBDownMousePos.stPos2D.xY);
					
					MTH3D_M_vMulScalarVector(&stNewVector, -1, &stNewVector);
					((EDT_SuperObject *)pElem)->fn_vTranslate(&stNewVector, TRUE);
					MTH3D_M_vMulScalarVector(&stNewVector, -(float)sqrt((fRequest + 1e-4f)/(fMoved + 1e-4f)), &stNewVector);
				}
				m_stLBDownMousePos.stPos2D = p_stPos->stPos2D;
			}
			// update all objects in the list
			for (pElem = M_GetWorld()->GetListSelected()->GetHeadElement(pos); pElem;
				 pElem = M_GetWorld()->GetListSelected()->GetNextElement(pos))
			{
				pSupObj = (EDT_SuperObject *) pElem;

				CPA_Interface *pInterface = GetInterface();

				if(//one or two buttons was pressed
				   (//one pressed
				    (pInterface->fn_bConsX()) ||
					(pInterface->fn_bConsY()) ||
					(pInterface->fn_bConsZ())
					) &&
					!(//but not all tree
					(pInterface->fn_bConsX())&&
					(pInterface->fn_bConsY())&&
					(pInterface->fn_bConsZ())
					) &&
					//not valid when move with plane(Q or W keys)
					!(pInterface->GetPyramidDepthMode())

				   )
				{
					//the X button is not pressed
					if(!pInterface->fn_bConsX())
						stNewVector.xX=0;	

					//the Y button is not pressed
					if(!pInterface->fn_bConsY())
						stNewVector.xY=0;	
					
					//the Z button is not pressed
					if(!pInterface->fn_bConsZ())
						stNewVector.xZ=0;	
				}

				pSupObj->fn_vTranslate(&stNewVector, TRUE);	
			}
			// tell DLLs
			fn_vSendMessageMoving();
			M_GetViewPort3d()->AddtoMoveVector(&stNewVector);	
			POS_fn_vGetTranslationVector(HIE_fn_hGetSuperObjectMatrix(M_GetWorld()->GetSingleSelection()->GetStruct()), &stNewPos);
			M_GetViewPort3d()->SetPosition(&stNewPos);
			M_GetViewPort3d()->fn_vUpdateStatusBarMessage();	

			// In this mode, the object does not move on the screen : the camera moves
			if (m_bMovedObjectStaysOnScreen)
			{
				// So, we get the camera
				CPA_CameraDLLBase	*p_oCameraInterface = M_GetViewPort3d()->GetCameraInterface();
				CPA_BaseObject		*p_oCamera = M_GetViewPort3d()->GetCamera();
				CPA_CameraCoords	oCoords;

				oCoords.SetXYZ(p_stVector->xX,p_stVector->xY,p_stVector->xZ);
				oCoords.SetAxisSystem(WorldCoordinates);

				p_oCameraInterface->Translate(p_oCamera,&oCoords);
			}
		}
		return TRUE;
	}
	else
	{
		m_eMouseMoveMode = E_mmm_NoMouseMove;
		if (fn_bIsMoveToModeEnabled())
			return TRUE;
	}

	// mousemove not processed
	return FALSE;
}


/*===========================================================================
		Left Button Double-Click  -> Selection
=========================================================================*/
BOOL EDT_HierarchyEditor::_OnLButtonDblClk(UINT nFlags, tdstMousePos *p_stPos, ACP_tdxIndex xIndex, HIE_tdstPickInfo *p_stObject)
{
	CPA_SuperObject *pObjectToEdit;

	if (!m_bHasCurrentWorld)
		return FALSE;

	// if dblclk on selected object, call corresponding DLL
	pObjectToEdit = fn_pstIsMouseOnObject(xIndex, p_stObject);
	if ((pObjectToEdit)&&(pObjectToEdit->GetObjectDLL()))
	{
		m_stListToEdit.RemoveAll();
		m_stListToEdit.AddTail(pObjectToEdit);
		GetMainWorld()->fn_bActivateEditor(pObjectToEdit->GetObjectDLL(), &m_stListToEdit);
	}

	// update all
	GetInterface()->fn_vUpdateAll(E_mc_UpdateDialog);

	// processed
	return TRUE;
}


/*===========================================================================
		Left Button Down  -> depends on current Mode
=========================================================================*/
BOOL EDT_HierarchyEditor::_OnLButtonDown(UINT nFlags, tdstMousePos *p_stPos, ACP_tdxIndex xIndex, HIE_tdstPickInfo *p_stObject)
{
	GEO_tdxHandleToMatrix	hGlobalMatrix;
	CPA_ObjectDLLBase		*p_oDLL;
	EDT_SuperObject			*pSelectedObject;
	EDT_SuperObject			*pPreviousSelection=NULL;
	CPA_SuperObject			*pPrevSelected;
	MTH3D_tdstVector		stPosition;
	MTH3D_tdstVector		stOrientPosition;
	MTH3D_tdstVector		stDistance, stPos1, stPos2;
	MTH3D_tdstVector		stNormal, stVector;
	tdeSelectMode			eModeSelect;
	tdstPosition			stClickPosition;
	POSITION				pos;
	BOOL					bUpdate;
	BOOL					bRes = FALSE;


	if (!m_bHasCurrentWorld)
		return FALSE;

	if (m_bSelectSectorWithMouse)
	{
		tdeDisplayMode	mode;
		mode  = GetInterface()->GetSpecificInterface()->GetDisplayMode();
		if(mode == 	E_dm_DrawVisibleSectors || mode == E_dm_DrawOnlyCurrentSector && p_stObject)
		{
			CPA_SuperObject *sector = GetInterface()->GetSpecificInterface()->GetCurrentSectorFromPos(&p_stObject->stPickedObject.aDEF_stDataOfElement[0].stHit);
			if(sector) 
			{	
				GetInterface()->GetSpecificInterface()->SetCurrentSector(sector);
				CComboBox *cb = (CComboBox *)GetInterface()->GetFrameBase()->m_oGeneralDialogBar.GetDlgItem(CPA_IDCB_CURRENTSECTOR);
				cb->SelectString(-1, sector->GetObject()->GetName());
			}
		}
		return TRUE;
	}
	if (GetInterface()->GetLockSelection()) 
		m_stLBDownMousePos.stPos2D = p_stPos->stPos2D;

	// init flags
	m_bCanDisplayPopup = FALSE;
	m_bDisableFirstMove = TRUE;
	bUpdate = FALSE;

	// Select Parent (Hierarchy or Paste)
	if ((m_eEditorMode == E_em_HierarchyMode)||(m_eEditorMode == E_em_ParentMode))
	{
		eModeSelect = (m_eEditorMode == E_em_HierarchyMode) ? E_sm_SelectParent : E_sm_SelectPFather;
		// find selected objects
		pSelectedObject = (EDT_SuperObject *) GetInterface()->GetPickingSelection(eModeSelect, xIndex, p_stObject, p_stPos, &m_bDoDialogSelect);
		if (pSelectedObject)
		{
			// hierarchy mode => create modif parent
			if (m_eEditorMode == E_em_HierarchyMode)
			{
				M_GetEditManager()->AskFor (new EDT_ModifParent (this, 
														M_GetWorld()->GetListOfListByDLL(), 
														(EDT_SuperObject *) pSelectedObject, 
														GetInterface()->GetSelectMode()));
			}

			// father for paste => init modif paste
			else
				fn_vInitModifPaste(E_pm_PasteChoice, pSelectedObject);
		}
		else if (!m_bDoDialogSelect)
		{
			m_csMessage = "There is no valid parent under the mouse";
			m_eModifCanceled = E_cm_CancelParent;
		}
	}

	// position mode
	else if (m_eEditorMode == E_em_PositionMode)
	{
		if ((xIndex)&&(p_stObject))
		{
			// get new position and normal from picking
			stPosition = p_stObject[0].stPickedObject.aDEF_stDataOfElement[0].stHit;
			fn_vGetNormalFromPicking(p_stObject, &stNormal);
			// update it according to instance bounding volume
			pSelectedObject = (EDT_SuperObject *) m_stListToCopy.GetHeadElement()->m_pChild;
			fn_vGetPositionFromBoundingVolume(pSelectedObject, &stNormal, &stVector);
			MTH3D_M_vAddVector(&stPosition, &stPosition, &stVector);
			// paste instance at given position
			fn_vInitModifPaste(E_pm_PasteChoice, NULL, &stPosition);
		}
		else
			// warn user
			fn_vInitModifPaste(E_pm_PasteChoice, NULL, NULL);
	}
	
	// Pyramid Mode
	else if (fn_bIsPyramidModeEnabled())
		GetInterface()->fn_vInitSelectionPyramid(p_stPos);

	// Choice Mode
	else if (m_eEditorMode == E_em_ChoiceMode)
	{
		// if necessary, cancel current selection
		if (!m_bMultiSelectMode)
		{
			GetInterface()->fn_vCancelCurrentSelection(FALSE);
			bUpdate = TRUE;
		}
		// find selected objects
		GetInterface()->GetPickingSelection(E_sm_SelectChoice, xIndex, p_stObject, p_stPos, &m_bDoDialogSelect);
	}

	// Mode To Mode
	else if (m_eEditorMode == E_em_MoveToMode)
	{
//CPA2 Corneliu Babiuc (TMS_0598) 25-05-98
			// now allow to teleport multiple selection
/*
		if (M_GetWorld()->GetCountSelected() != 1)
		{
			// reinit selection
			GetInterface()->fn_vCancelCurrentSelection(FALSE);
			// find selected objects
			pSelectedObject = (EDT_SuperObject *) GetInterface()->GetPickingSelection(E_sm_SelectNormal, xIndex, p_stObject, p_stPos, &m_bDoDialogSelect);
			if (pSelectedObject)
			{
				GetInterface()->fn_vAddSelectedObject(pSelectedObject, FALSE);
				SetCurrentCursor(C_hc_MoveToCursor, FALSE);
			}
			bUpdate = TRUE;
		}
*/
//END CPA2 Corneliu Babiuc (TMS_0598) 25-05-98
	}
//CPA2 Corneliu Babiuc 15-06-98
	// specific teleportation
	else if (m_eEditorMode == E_em_MoveToInstance)
	{
		g_pReferenceInstance = (EDT_SuperObject *) GetInterface()->GetPickingSelection(E_sm_SelectNormal, xIndex, p_stObject, p_stPos, &m_bDoDialogSelect);
		// don't allow to teleport multiple selection 
		if (M_GetWorld()->GetCountSelected() != 1 && /*! m_bIsASelection CPA2 Corneliu Babiuc (multiple teleportation)*/M_GetWorld()->GetCountRegistered()==0)
		{
			// reinit selection
			GetInterface()->fn_vCancelCurrentSelection(FALSE);
			// find selected objects
			if (g_pReferenceInstance)
			{
				GetInterface()->fn_vAddSelectedObject(g_pReferenceInstance, FALSE);
				SetCurrentCursor(C_hc_MoveToCursor, FALSE);
			}
			bUpdate = TRUE;
		}
	}
	else if (m_eEditorMode == E_em_MoveCameraToInstance || m_eEditorMode == E_em_MoveCameraCentered)
	{
		g_pReferenceInstance = (EDT_SuperObject *) GetInterface()->GetPickingSelection(E_sm_SelectNormal, xIndex, p_stObject, p_stPos, &m_bDoDialogSelect);
	}
//END CPA2 Corneliu Babiuc 17-06-98
	
	// Orient Mode
	else if ((m_eEditorMode == E_em_OrientMode)||(m_eEditorMode == E_em_VOrientMode))
	{
		// RAZ move
		m_pOrientMove = NULL;
		m_pOrientedObject = NULL;

		if (M_GetWorld()->GetCountSelected() == 1)
		{
			if ((xIndex)&&(p_stObject))
			{
				m_pOrientedObject = (EDT_SuperObject *) M_GetWorld()->GetSingleSelection();
				// ask DLL for custom orientation
				p_oDLL = m_pOrientedObject->GetObjectDLL();
				if (p_oDLL)
				{
					// MAJ position
					stClickPosition.stPos.stPos2D = p_stPos->stPos2D;
					fn_bFindPickingPosition(&stClickPosition);
					// give info to DLL
					bRes = p_oDLL->fn_bOnClickOrientPosition(m_pOrientedObject, &stClickPosition);
				}
				// get picking position
				if (!bRes)
				{
					// get picking position
					stOrientPosition = p_stObject->stPickedObject.aDEF_stDataOfElement[0].stHit;
					// create modif
					m_pOrientMove = new EDT_ModifMove(this, M_GetWorld()->GetListOfListByDLL(), GetInterface()->GetSelectMode());
					// orient object
					if (m_eEditorMode == E_em_OrientMode)
						fn_vOrientToPosition(m_pOrientedObject, &stOrientPosition);
					else
						fn_vOrientWithVertical(m_pOrientedObject, &stOrientPosition);
				}
			}
			else
				m_csMessage = "Editor could not find a valid position";
		}
	}

	// Distance
	else if (GetInterface()->GetDisplayDistance())
	{
		// get first selected object;
		pPrevSelected = M_GetWorld()->GetListSelected()->GetHeadElement(pos);	
		if (pPrevSelected)
			M_GetViewPort3d()->SetSelectedInstance(pPrevSelected->GetObject() ? pPrevSelected->GetObject()->GetName() : pPrevSelected->GetName());
		else
			M_GetViewPort3d()->SetSelectedInstance("");
			// find new selected object
		pSelectedObject = (EDT_SuperObject *) GetInterface()->GetPickingSelection(E_sm_SelectNormal, xIndex, p_stObject, p_stPos, &m_bDoDialogSelect, pPreviousSelection);
		if (pSelectedObject)
			M_GetViewPort3d()->SetPickedInstance(pSelectedObject->GetObject() ? pSelectedObject->GetObject()->GetName() : pSelectedObject->GetName());
		else
			M_GetViewPort3d()->SetPickedInstance("");
	
		if (!pPrevSelected || !pSelectedObject) 
		{
			//now display the distance to static object
			if (pPrevSelected)
			{
				stClickPosition.stPos.stPos2D = p_stPos->stPos2D;
				if (fn_bFindPickingPosition(&stClickPosition))
				{
					M_GetViewPort3d()->SetPickedInstance("picking position");
					// get first position
					hGlobalMatrix = HIE_fn_hGetSuperObjectMatrix(pPrevSelected->GetStruct());
					POS_fn_vGetTranslationVector(hGlobalMatrix, &stPos1);
					// compute distance
					MTH3D_M_vSubVector(&stDistance, &(stClickPosition.stPos.stPos3D), &stPos1);
					M_GetViewPort3d()->SetDistanceVector(&stDistance);
				}
			}
			else
			{
				MTH3D_M_vSetVectorElements(&stDistance, 0.0f, 0.0f, 0.0f);
				M_GetViewPort3d()->SetDistanceVector(&stDistance);
			}
		}
		else
		{
			// get first position
			hGlobalMatrix = HIE_fn_hGetSuperObjectMatrix(pPrevSelected->GetStruct());
			POS_fn_vGetTranslationVector(hGlobalMatrix, &stPos1);
			// get second position
			hGlobalMatrix = HIE_fn_hGetSuperObjectMatrix(pSelectedObject->GetStruct());
			POS_fn_vGetTranslationVector(hGlobalMatrix, &stPos2);
			// compute distance
			MTH3D_M_vSubVector(&stDistance, &stPos2, &stPos1);
			M_GetViewPort3d()->SetDistanceVector(&stDistance);
		}
		M_GetViewPort3d()->fn_vUpdateStatusBarMessage();
	}
// Begin Silviu Simen 18 August 1998 Cut/Paste Mechanism
	else if (m_eEditorMode == E_em_CutPasteMode) {
		;
	}
// End Silviu Simen 18 August 1998 Cut/Paste Mechanism

	// Select Mode
	else
	{
		// get previous selection
		pPreviousSelection = (EDT_SuperObject *) fn_pstIsMouseOnObject(xIndex, p_stObject);
		// find selected objects
		pSelectedObject = (EDT_SuperObject *) GetInterface()->GetPickingSelection(E_sm_SelectNormal, xIndex, p_stObject, p_stPos, &m_bDoDialogSelect, pPreviousSelection);
		if (pSelectedObject)
		{
			M_GetViewPort3d()->SetSelectedInstance(pSelectedObject->GetObject() ? pSelectedObject->GetObject()->GetName() : pSelectedObject->GetName());
			MTH3D_M_vSetVectorElements(&stDistance, 0.0f, 0.0f, 0.0f);
			M_GetViewPort3d()->SetMoveVector(&stDistance);	
			POS_fn_vGetTranslationVector(HIE_fn_hGetSuperObjectMatrix(pSelectedObject->GetStruct()), &stDistance);
			M_GetViewPort3d()->SetPosition(&stDistance);
			M_GetViewPort3d()->fn_vUpdateStatusBarMessage();
		}
		else
		{
			M_GetViewPort3d()->SetSelectedInstance("");
			MTH3D_M_vSetVectorElements(&stDistance, 0.0f, 0.0f, 0.0f);
			M_GetViewPort3d()->SetMoveVector(&stDistance);	
			M_GetViewPort3d()->SetPosition(&stDistance);	
			M_GetViewPort3d()->fn_vUpdateStatusBarMessage();		
		}

		// mouse is not on a selected object
		if ((!m_bMultiSelectMode)&&((!pPreviousSelection)||(pPreviousSelection != pSelectedObject)))
		{
			GetInterface()->fn_vCancelCurrentSelection(FALSE);
			bUpdate = TRUE;
		}
		// select corresponding object
		if (pSelectedObject)
		{
			// normal selection => select if not
			if (!m_bMultiSelectMode)
			{
				if (pPreviousSelection != pSelectedObject)
				{
					GetInterface()->fn_vAddSelectedObject(pSelectedObject, FALSE);
					bUpdate = TRUE;
				}
			}
			// multiple selection
			else
			{
				// object already selected ?
				pPreviousSelection = (EDT_SuperObject *) GetInterface()->GetPreviousSelection(pSelectedObject);
				if (pPreviousSelection)
					GetInterface()->fn_vRemoveSelectedObject(pPreviousSelection, FALSE);
				if (pPreviousSelection != pSelectedObject)
					GetInterface()->fn_vAddSelectedObject(pSelectedObject, FALSE);
				bUpdate = TRUE;
			}
		}
		// init mousemove
		if (!m_eMouseMoveMode)
		{
			if (pSelectedObject || GetInterface()->GetLockSelection())
				m_eMouseMoveMode = E_mmm_MouseMove;
			else
				m_eMouseMoveMode = E_mmm_NoMouseMove;
		}
	}

	// update all
	if (bUpdate)
		GetInterface()->fn_vUpdateAll(E_mc_UpdateSelection);

	// stick objects
	if (GetDialogSelect()->fn_bIsSelecting())
		GetDialogSelect()->fn_vSetPoint(p_stPos, p_stObject);

	// key processed
	return TRUE;
}


/*===========================================================================
		Left Button Up  -> depends on current Mode
=========================================================================*/
BOOL EDT_HierarchyEditor::_OnLButtonUp(UINT nFlags, tdstMousePos *p_stPos)
{
	CPA_ObjectDLLBase	*p_oDLL;
	MTH3D_tdstVector	stDistance;
	EDT_SuperObject		*pSelected;
	tdeSelectMode		eModeSelect;
	tdstPosition		stPosition;
	BOOL				bRes = FALSE;

	if (!m_bHasCurrentWorld)
		return FALSE;

	// if necessary, display the Selection Dialog
	if (m_bDoDialogSelect)
	{
		// Parent Mode
		if ((m_eEditorMode == E_em_HierarchyMode)||(m_eEditorMode == E_em_ParentMode))
		{
			// do modal dialog
			eModeSelect = (m_eEditorMode == E_em_HierarchyMode) ? E_sm_SelectParent : E_sm_SelectPFather;
			// get parent
			pSelected = (EDT_SuperObject *) GetInterface()->GetDialogSelection(eModeSelect);
			if (pSelected)
			{
				// hierarchy mode => create modif parent
				if (m_eEditorMode == E_em_HierarchyMode)
				{
					M_GetEditManager()->AskFor (new EDT_ModifParent(this, 
													M_GetWorld()->GetListOfListByDLL(), 
													pSelected, 
													GetInterface()->GetSelectMode()));
				}
				// father for paste => init modif paste
				else
					fn_vInitModifPaste(E_pm_PasteChoice, pSelected);
			}
		}
		// choice mode
		else if (m_eEditorMode = E_em_ChoiceMode)
		{
			// get parent
			pSelected = (EDT_SuperObject *) GetInterface()->GetDialogSelection(E_sm_SelectNormal);
			// ask permission and set new selection
			if (pSelected)
				GetInterface()->fn_vAddSelectedObject(pSelected, FALSE);
		}
		// cancel mode
		SetEditorMode(E_em_NoMode);
		m_bMultiSelectMode = FALSE;
		// update drawing
		GetInterface()->fn_vUpdateAll(E_mc_UpdateDialog);
		M_GetViewPort3d()->SetFocus();
	}

// Begin Silviu Simen 18 August 1998 Cut/Paste Mechanism
	if (m_eEditorMode == E_em_CutPasteMode)
	{
		if (m_pRegisteredCuttedObject)
		{
			stPosition.stPos.stPos2D = p_stPos->stPos2D;
			if (!fn_bFindPickingPosition(&stPosition))
			{
				m_csMessage = "Editor could not find a valid position";
				fn_vDisplayCancelMessage(m_eModifCanceled);
			}
			else 
			{
				EDT_SuperObject  *pParent;


				pParent = m_pSpecificEditor->GetDefaultParentForPaste(m_pRegisteredCuttedObject);

				M_GetEditManager()->AskFor (new EDT_ModifInsert 
					(this, m_pRegisteredCuttedObject, pParent, &stPosition, 
					NULL, TRUE, TRUE, FALSE, TRUE,m_bSpecialObject));

				m_pRegisteredCuttedObject=NULL;
				m_bSpecialObject = FALSE;
				SetEditorMode(E_em_NoMode);
			}
		}
	}
	else 
// End Silviu Simen 18 August 1998 Cut/Paste Mechanism

	// Move To Mode
	if (m_eEditorMode == E_em_MoveToMode)
	{
		// if there is an object selected or if there is an object registered
		if ( (M_GetWorld()->GetCountSelected() /*== 1*/>0) || /*m_bIsASelection */M_GetWorld()->GetCountRegistered()) //CPA2 Corneliu Babiuc (TMS_0598) 25-05-98
			{
				stPosition.stPos.stPos2D = p_stPos->stPos2D;
				if (!fn_bFindPickingPosition(&stPosition))
				{
					m_csMessage = "Editor could not find a valid position";
					fn_vDisplayCancelMessage(m_eModifCanceled);
				}
				else
					fn_vMoveToNewPosition(&stPosition);
			}
	}
//CPA2 Corneliu Babiuc 15-06-98
	else if (m_eEditorMode == E_em_MoveToInstance)
	{
		// if there is an object selected or if there is an object registered
		if ( (M_GetWorld()->GetCountSelected() == 1) || /*m_bIsASelection*/M_GetWorld()->GetCountRegistered() ==1) //CPA2 Corneliu Babiuc (multiple registration) 06-07-98
		{
			if (!g_pReferenceInstance)
			{
				m_csMessage = "Editor could not find an instance";
				fn_vDisplayCancelMessage(m_eModifCanceled);
			}
			else
			{
				fn_vMoveToInstancePosition(g_pReferenceInstance);
			}
		}
		g_pReferenceInstance = NULL;
	}
	else if (m_eEditorMode == E_em_MoveCameraToInstance || m_eEditorMode == E_em_MoveCameraCentered) 
	{
		if (!g_pReferenceInstance)
		{
			m_csMessage = "Editor could not find an instance";
			fn_vDisplayCancelMessage(m_eModifCanceled);
		}
		else
		{
			if (m_eEditorMode == E_em_MoveCameraToInstance)
				fn_vMoveCameraOrientedToInstance(g_pReferenceInstance);
			else
			{
				// search for Rayman
				CPA_List<CPA_SuperObject> * p_lstInstancesList;
				CPA_SuperObject			  *pElem, * p_oRayman = NULL;
				//get the list of actors, and search for Rayman base object
				p_lstInstancesList = GetInterface()->GetObjectListByType(C_szActorInstanceTypeName);
				POSITION Pos;
				for( pElem = p_lstInstancesList->GetHeadElement(Pos);
					 pElem;
					 pElem = p_lstInstancesList->GetNextElement(Pos) )
				{
					//compare if the base object has name Rayman
					if (pElem->GetObject()->GetName() == "Rayman")
					{
						p_oRayman = pElem;
						break;
					}
				}
	
				if (!p_oRayman)
				{
					m_csMessage = "Editor could not find Rayman's instance";
					fn_vDisplayCancelMessage(m_eModifCanceled);
				}
				else
				{		
					fn_vMoveCameraToInstanceCenterOnInstance(g_pReferenceInstance, p_oRayman);
				}
			}
		}
		g_pReferenceInstance = NULL;
	}
//END CPA2 Corneliu Babiuc 17-06-98
	else
		fn_vDisplayCancelMessage(m_eModifCanceled);

	// Orient Mode
	if ((m_eEditorMode == E_em_OrientMode)||(m_eEditorMode == E_em_VOrientMode))
	{
		// check selection
		if (m_pOrientedObject)
		{
			// ask DLL for custom orientation
			p_oDLL = m_pOrientedObject->GetObjectDLL();
			if (p_oDLL)
			{
				// MAJ position
				stPosition.stPos.stPos2D = p_stPos->stPos2D;
				fn_bFindPickingPosition(&stPosition);
				// give info to DLL
				bRes = p_oDLL->fn_bOnEndOrientObject(m_pOrientedObject, &stPosition);
			}
			// do modif
			if ((m_pOrientMove)&&(!bRes))
				fn_bDoOrCancelMove(m_pOrientMove);
			else 
				fn_vDisplayCancelMessage(m_eModifCanceled);
			// if necessary, cancel mode
			if (!m_bKeepOrientMode)
				SetEditorMode(E_em_NoMode);
			// raz move
			m_pOrientMove = NULL;
			m_pOrientedObject = NULL;
		}
	}

	// if modif was canceled
	if (m_eModifCanceled != E_cm_NoCancel)
	{
		// cancel all modes
		SetEditorMode(E_em_NoMode);
		m_bMultiSelectMode = FALSE;
	}
	// If selected objects have moved
	else if ((M_GetWorld()->GetCountSelected()) && (m_pMouseMove))
	{
		fn_bDoOrCancelMove(m_pMouseMove);

		pSelected = (EDT_SuperObject *) M_GetWorld()->GetSingleSelection();
		if (pSelected)
		{
			M_GetViewPort3d()->SetSelectedInstance(pSelected->GetObject() ? pSelected->GetObject()->GetName() : pSelected->GetName());
			MTH3D_M_vSetVectorElements(&stDistance, 0.0f, 0.0f, 0.0f);
			M_GetViewPort3d()->SetMoveVector(&stDistance);	
			POS_fn_vGetTranslationVector(HIE_fn_hGetSuperObjectMatrix(pSelected->GetStruct()), &stDistance);
			M_GetViewPort3d()->SetPosition(&stDistance);
			M_GetViewPort3d()->fn_vUpdateStatusBarMessage();
		}
		else
		{
			M_GetViewPort3d()->SetSelectedInstance("");
			MTH3D_M_vSetVectorElements(&stDistance, 0.0f, 0.0f, 0.0f);
			M_GetViewPort3d()->SetMoveVector(&stDistance);	
			M_GetViewPort3d()->SetPosition(&stDistance);	
		}
		m_pMouseMove = NULL;
		m_eMouseMoveMode = E_mmm_NoMouseMove;
	}

	// Pyramid Selection
	GetInterface()->fn_vEndSelectionPyramid();

	m_bCanDisplayPopup = TRUE;
	m_bDoDialogSelect = FALSE;
	m_bDisableFirstMove = TRUE;
	return TRUE;
}


/*===========================================================================
		Right Button Down  -> popup menu
=========================================================================*/
BOOL EDT_HierarchyEditor::_OnRButtonDown(UINT nFlags, tdstMousePos *p_stCoords, ACP_tdxIndex xIndex, HIE_tdstPickInfo *p_stObject)
{
	if (!m_bHasCurrentWorld)
		return FALSE;
	// show the cursor, in case a dialog appear!
	if (!m_bCanDisplayPopup)
		return FALSE;

	// to select an object
	_OnLButtonDown(nFlags, p_stCoords, xIndex, p_stObject);
	_OnLButtonUp(nFlags, p_stCoords);

	// cancel mode (for popup)
	fn_vCancelAllModes();
	// display popup
	GetInterface()->fn_vDisplayPopupMenu(p_stCoords);

	// command processed
	return TRUE;
}


/*===========================================================================
		Right Button Doubleclick
=========================================================================*/
BOOL EDT_HierarchyEditor::_OnRButtonDblClk (UINT nFlags, tdstMousePos *p_stPos, ACP_tdxIndex xIndex, HIE_tdstPickInfo *p_stObject)
{
	return FALSE;
}

/*===========================================================================
		Right Button up
=========================================================================*/
BOOL EDT_HierarchyEditor::_OnRButtonUp(UINT nFlags, tdstMousePos *p_stPos)
{
	return FALSE;
}



//#################################################################################
// COMMANDS
//#################################################################################

/*===========================================================================
		on command
=========================================================================*/
BOOL EDT_HierarchyEditor::_OnCommand (UINT IDCmdMsg)
{
	// check if command comes from popupmenu
	if ((IDCmdMsg >= C_EDTPopUpMenuIDStart) &&
		(IDCmdMsg <= C_EDTPopUpMenuIDEnd))
	{
		// popupmenu command processed...
		GetInterface()->fn_vDisplayMenuCommand(IDCmdMsg);
		return TRUE;
	}

	return FALSE;
}


/*===========================================================================
		on update command
=========================================================================*/
BOOL EDT_HierarchyEditor::_OnUpdateCommandUI(UINT IDCmdMsg, CCmdUI *pCmdUI)
{
	return FALSE;
}


//#################################################################################
// DRAG & DROP
//#################################################################################

/*===========================================================================
*		Description:	get minimal box
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vGetMinMaxPointsOfInstance	(EDT_SuperObject *pEdObj, POS_tdxHandleToPosition hMatrix, MTH3D_tdstVector *p_stMinPoint, MTH3D_tdstVector *p_stMaxPoint,
/* CPA2 Corneliu Babiuc (TMS_0598) 13-06-98*/			BOOL bGlobal )
{
	HIE_tdxHandleToSuperObject	hSupObj;
    POS_tdstCompletePosition    stMatrix;
	ACP_tdxHandleOfObject		hPhysicalObject;
	MTH3D_tdstVector			stPoint;
	EDT_SuperObject				*pChild;
	ACP_tdxIndex				xNbPoints, xNumPoint;
	MTH_tdxReal					xTemp;

	POS_fn_vSetIdentityMatrix(&stMatrix);
	hSupObj = pEdObj->GetStruct();

	switch (HIE_fn_ulGetSuperObjectType(hSupObj))
	{
		// geometric object
		case HIE_C_ulEDT_Geometric:
			//Take the physical object
			hPhysicalObject = (ACP_tdxHandleOfObject) HIE_fn_hGetSuperObjectObject(hSupObj);
			break;

		// instanciated physical object
		case HIE_C_ulIPO:
		case HIE_C_ulIPO_Mirror:
			//Take the physical object
			GLI_vGetVisualSetLOD(PO_fn_hGetVisualSet(IPO_fn_hGetPhysicalObject((IPO_tdxHandleToInstanciatedPhysicalObject)HIE_fn_hGetSuperObjectObject(hSupObj))),
				0L,
				&xTemp,
				&hPhysicalObject);
			break;

		// physical object
		case HIE_C_ulPO:
			//Take the physical object
			GLI_vGetVisualSetLOD(PO_fn_hGetVisualSet((PO_tdxHandleToPhysicalObject)HIE_fn_hGetSuperObjectObject(hSupObj)),
				0L,
				&xTemp,
				&hPhysicalObject);
                break;
 
		default:
			hPhysicalObject = NULL;
			break;
	}

	// update min&max
	if (hPhysicalObject) 
	{
		// get number of points in the object
		xNbPoints = GEO_xGetGeometricObjectNumberOfPoints(hPhysicalObject);
		// check coordinates of each point 
		for (xNumPoint = 0; xNumPoint < xNbPoints; xNumPoint++)
		{
			// get point
			GEO_vGetPointOfObject(hPhysicalObject, &stPoint, xNumPoint);
			// update with matrix
			POS_fn_vMulMatrixVertex(&stPoint, hMatrix, &stPoint);
//CPA2 Corneliu Babiuc (TMS_0598) 13-06-98
			// transform in global coordinates if bGlobal is true
			if (bGlobal)
				POS_fn_vMulMatrixVertex(&stPoint, HIE_fn_hGetSuperObjectGlobalMatrix(pEdObj->GetStruct()), &stPoint);
//END CPA2 Corneliu Babiuc (TMS_0598) 13-06-98
			// check x coordinate
			if (stPoint.xX < p_stMinPoint->xX) p_stMinPoint->xX = stPoint.xX;
			if (stPoint.xX > p_stMaxPoint->xX) p_stMaxPoint->xX = stPoint.xX;
			// check y coordinate
			if (stPoint.xY < p_stMinPoint->xY) p_stMinPoint->xY = stPoint.xY;
			if (stPoint.xY > p_stMaxPoint->xY) p_stMaxPoint->xY = stPoint.xY;
			// check z coordinate
			if (stPoint.xZ < p_stMinPoint->xZ) p_stMinPoint->xZ = stPoint.xZ;
			if (stPoint.xZ > p_stMaxPoint->xZ) p_stMaxPoint->xZ = stPoint.xZ;
		}
	}

	// next level of hierarchy
	for (pChild = (EDT_SuperObject *) pEdObj->GetSuperObjectFirstChild(); pChild;
		 pChild = (EDT_SuperObject *) pEdObj->GetSuperObjectNextChild(pChild))
	{
		// compute global matrix
		POS_fn_vMulMatrixMatrix(&stMatrix, hMatrix, HIE_fn_hGetSuperObjectMatrix(pChild->GetStruct()));
		// compute min & max
		fn_vGetMinMaxPointsOfInstance(pChild, &stMatrix, p_stMinPoint, p_stMaxPoint,
		/*CPA2 Corneliu Babiuc (TMS_0598) 13-06-98*/ bGlobal);
	}

}

/*===========================================================================
*		Description:	get normal from picking infos
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vGetPositionFromBoundingVolume (EDT_SuperObject *pSupObj, MTH3D_tdstVector *pNormal, MTH3D_tdstVector *pVector)
{
    POS_tdstCompletePosition    stMatrix;
	MTH3D_tdstVector			stMinPoint, stMaxPoint;

	// compute min & max
	POS_fn_vSetIdentityMatrix(&stMatrix);
	stMinPoint.xX = stMinPoint.xY = stMinPoint.xZ = MTH_C_InfinitPlus;
	stMaxPoint.xX = stMaxPoint.xY = stMaxPoint.xZ = MTH_C_InfinitMinus;
	fn_vGetMinMaxPointsOfInstance(pSupObj, &stMatrix, &stMinPoint, &stMaxPoint);

	// check normal
	if (pNormal->xX > 0)
		pVector->xX = (stMinPoint.xX < 0) ? - stMinPoint.xX : 0;
	if (pNormal->xX < 0)
		pVector->xX = (stMaxPoint.xX > 0) ? - stMaxPoint.xX : 0;

	if (pNormal->xY > 0)
		pVector->xY = (stMinPoint.xY < 0) ? - stMinPoint.xY : 0;
	if (pNormal->xY < 0)
		pVector->xY = (stMaxPoint.xY > 0) ? - stMaxPoint.xY : 0;

	if (pNormal->xZ > 0)
		pVector->xZ = (stMinPoint.xZ < 0) ? - stMinPoint.xZ : 0;
	if (pNormal->xZ < 0)
		pVector->xZ = (stMaxPoint.xZ > 0) ? - stMaxPoint.xZ : 0;
}

/*===========================================================================
*		Description:	get normal from picking infos
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vGetNormalFromPicking (HIE_aDEF_stTabOfPickInfo a_stPickInfo, MTH3D_tdstVector *pNormal)
{
	IPO_tdxHandleToInstanciatedPhysicalObject	hInstanciated;
	PO_tdxHandleToPhysicalObject				hPhysical;
    GEO_tdstGeometricObject						*p_stObj;
	GLI_tdstDataOfElement						*p_stData;
	ACP_tdxHandleOfObject						hGeomObj;
	MTH_tdxReal									xVoidReal;

    // geometric object
	if ( HIE_fn_ulGetSuperObjectType(a_stPickInfo[0].hSprObject) == HIE_C_ulEDT_Geometric)
		p_stObj = (GEO_tdstGeometricObject *) HIE_fn_hGetSuperObjectObject(a_stPickInfo[0].hSprObject);

    // physical object
	if (HIE_fn_ulGetSuperObjectType(a_stPickInfo[0].hSprObject) & (HIE_C_ulPO | HIE_C_ulPO_Mirror))
    {
        hPhysical = (PO_tdxHandleToPhysicalObject) HIE_fn_hGetSuperObjectObject(a_stPickInfo[0].hSprObject);
		GLI_vGetVisualSetLOD(PO_fn_hGetVisualSet(hPhysical), 0, &xVoidReal, &hGeomObj);
        p_stObj = (GEO_tdstGeometricObject *) hGeomObj;
    }

    // instanciated physical object
	if (HIE_fn_ulGetSuperObjectType(a_stPickInfo[0].hSprObject) & (HIE_C_ulIPO | HIE_C_ulIPO_Mirror))
    {
        hInstanciated = (IPO_tdxHandleToInstanciatedPhysicalObject) HIE_fn_hGetSuperObjectObject(a_stPickInfo[0].hSprObject);
		hPhysical = IPO_fn_hGetPhysicalObject(hInstanciated);
		GLI_vGetVisualSetLOD(PO_fn_hGetVisualSet(hPhysical), 0, &xVoidReal, &hGeomObj);
        p_stObj = (GEO_tdstGeometricObject *) hGeomObj;
    }
    
	// get data
	p_stData = &(a_stPickInfo[0].stPickedObject.aDEF_stDataOfElement[0]);
	// get normal
	GEO_vGetNormalOfGeometricObjectElement(p_stObj, p_stData->xElements, p_stData->xIndexOfFace, pNormal);
} 

/*===========================================================================
		on drag drop end
=========================================================================*/
BOOL EDT_HierarchyEditor::_OnDragDropEnd(WPARAM wParam, LPARAM lParam)
{
	CPA_ObjectDLLBase			*p_oDLL;
	EDT_SuperObject				*pParent;
	EDT_SuperObject				*pNewInstance;
	MTH3D_tdstVector			stNormal, stVector;
	MTH3D_tdstVector			stSource, stResult;
	MTH3D_tdstVector			stTranslation;
	POS_tdstCompletePosition	*pParentMatrix, *pInstanceMatrix, *pGlobalMatrix;
	POS_tdstCompletePosition	stMatrix;
	tdeSaveStatus				eStatus;
	tdstPosition				stPosition;
	tdeTypeSO					eTypeInsert;
	DD_Object					*p_oDDObject;
	EDT_Model					*pModel;
	CPoint						point;

	POS_fn_vSetIdentityMatrix(&stMatrix);
	if (!m_bHasCurrentWorld)
		return FALSE;

	p_oDDObject = (DD_Object *) lParam;
	// check data type of dragged object
	if (p_oDDObject->fn_uiGetDataType() != C_ucModel)
		return FALSE;

	// there must be a current model
	pModel = GetInterface()->GetCurrentModel();
	if (!pModel)
		return FALSE;
	p_oDLL = pModel->m_pObjectDLL;

	// ask permission to the world
	if (!M_GetWorld()->fn_bAcceptModifInsert(p_oDLL))
	{
		m_csMessage = "Instances created by this DLL cannot be inserted in this world";
		fn_vDisplayCancelMessage(E_cm_CancelInsert);
		return FALSE;
	}

	// init stMousePos
	stPosition.stPos.stPos = p_oDDObject->m_stMousePos;
	// modif position for GLIDE
	M_GetViewPort3d()->ScreenToClient( &p_oDDObject->m_stMousePos);
    //if (GLI_lWhatIsGLI () == GLI_C_VersionGlide )
	if(1) //USE_DIRECTX: tjr entrer ici pour les deux modes
	{
		point = p_oDDObject->m_stMousePos;
		M_GetViewPort3d()->ClientToVoodoo(point);
        stPosition.stPos.stPos2D.xX = GLI_M_LongToValue(point.x);
	    stPosition.stPos.stPos2D.xY = GLI_M_LongToValue(point.y);
	}
	else
	{
        stPosition.stPos.stPos2D.xX = GLI_M_LongToValue(p_oDDObject->m_stMousePos.x);
        stPosition.stPos.stPos2D.xY = GLI_M_LongToValue(p_oDDObject->m_stMousePos.y);
	}

	// Get Type
	eTypeInsert = p_oDLL->GetTypeInstance(pModel->m_csTypeName, pModel->m_csName);
	eStatus = p_oDLL->GetStatusInstance(pModel->m_csTypeName, pModel->m_csName);
	// Get Parent for insertion
	pParent = GetParentForInsertion(p_oDLL, pModel->m_csTypeName, pModel->m_csName, &stPosition, eTypeInsert, eStatus);
	if (!pParent)
	{
		m_csMessage = "Editor could not find a valid parent for this model and position";
		fn_vDisplayCancelMessage(E_cm_CancelInsert);
		return FALSE;
	}

	// construct the new instance
	pNewInstance = (EDT_SuperObject *) p_oDLL->GetNewInstance(pModel->m_csTypeName, pModel->m_csName, pParent);
	if (!pNewInstance)
	{
		m_csMessage = "There is no instance to insert";
		fn_vDisplayCancelMessage(E_cm_CancelInsert);
		return FALSE;
	}

	// get position
	pParentMatrix = HIE_fn_hGetSuperObjectGlobalMatrix(pParent->GetStruct());
	pInstanceMatrix = HIE_fn_hGetSuperObjectMatrix(pNewInstance->GetStruct());
	pGlobalMatrix = HIE_fn_hGetSuperObjectGlobalMatrix(pNewInstance->GetStruct());
	// ask DLL
	if (!p_oDLL->fn_bChooseInsertPosition(pNewInstance, pParent, &stPosition))
	{
		// set global matrix orientation
		POS_fn_vMulMatrixMatrix(pGlobalMatrix, pParentMatrix, pInstanceMatrix);
		POS_fn_vNormalizeMatrix(pGlobalMatrix);
		// get real position
		fn_vGetNormalFromPicking(stPosition.a_stPickInfo, &stNormal);
		fn_vGetPositionFromBoundingVolume(pNewInstance, &stNormal, &stVector);
		MTH3D_M_vAddVector(&stPosition.stPos.stPos3D, &stPosition.stPos.stPos3D, &stVector);
		// correct position according to pParent's matrix
		POS_fn_vInvertMatrix(&stMatrix, pParentMatrix);
		POS_fn_vMulMatrixVertex(&stTranslation, &stMatrix, &stPosition.stPos.stPos3D); 
		POS_fn_vSetTranslationVector(pInstanceMatrix,&stTranslation);
		POS_fn_vSetTranslationVector(pGlobalMatrix,&stPosition.stPos.stPos3D);
	}
	else
	{
		// set absolute translation
		POS_fn_vGetTranslationVector(pInstanceMatrix, &stSource);
		POS_fn_vMulMatrixVertex(&stResult, pParentMatrix, &stSource);
		POS_fn_vSetTranslationVector(pGlobalMatrix, &stResult);
	}
	
	// insert object
	if (fn_bCanInsert(pNewInstance, pParent))
		M_GetEditManager()->AskFor (new EDT_ModifInsert (this, pNewInstance, pParent, &stPosition));
	else
	{
		m_eModifCanceled = E_cm_CancelInsert;
		pModel->m_pObjectDLL->fn_vOnCancelInsertion(pNewInstance);
	}

	fn_vDisplayCancelMessage(m_eModifCanceled);
	// cancel current mode
	if (m_eEditorMode == E_em_ChoiceMode)
		SetEditorMode(E_em_NoMode);
	// set focus to 3D View
	M_GetViewPort3d()->SetFocus();
	return TRUE;
}


/*===========================================================================
		on drag drop Move
=========================================================================*/
BOOL EDT_HierarchyEditor::_OnDragDropMove(WPARAM wParam, LPARAM lParam)
{
	return FALSE;
}

/*===========================================================================
		on drag drop GainFocus
=========================================================================*/
BOOL EDT_HierarchyEditor::_OnDragDropGainFocus(WPARAM wParam, LPARAM lParam)
{
 	// give it to current DLL
	return FALSE;
}

/*===========================================================================
		on drag drop LooseFocus
=========================================================================*/
BOOL EDT_HierarchyEditor::_OnDragDropLooseFocus(WPARAM wParam, LPARAM lParam)
{
	return FALSE;
}


//#################################################################################
// ADD OBJECTS TO DRAW
//#################################################################################

/*===========================================================================
		add objects 1
=========================================================================*/
void EDT_HierarchyEditor::fn_vAddObjectsToDraw(GLD_tdstViewportAttributes *p1, GLI_tdxHandleToLight p2, DEV_ViewPort* p3)
{
	GetInterface()->fn_vDrawSelectionFrame(p1);
	GetInterface()->fn_vDrawMoveObjectFrame(p1);
	GetInterface()->fn_vDrawSuperObjectsAxis(p1);
}

/*===========================================================================
		add objects 2
=========================================================================*/
void EDT_HierarchyEditor::fn_vAddObjectsToDraw2 (GLD_tdstViewportAttributes *p1, GLI_tdxHandleToLight p2)
{

}


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

/*===========================================================================
*		Description:	find the Editor Object corresponding to pSupObj.
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:     Author:
*=========================================================================*/
CPA_SuperObject * EDT_HierarchyEditor::GetEditorObject (HIE_tdxHandleToSuperObject hSupObj)
{
	CPA_SuperObject *pElem;
	POSITION	pos = NULL;

	return (CPA_SuperObject *) GetBaseObject(hSupObj, "", NO_CRITERIA, E_rc_AllObjects);

	// test the structure
	for (pElem = M_GetWorld()->GetListAllObjects()->GetHeadElement(pos); pElem;
		 pElem = M_GetWorld()->GetListAllObjects()->GetNextElement(pos))
	{
		if (pElem->GetStruct() == hSupObj)
			return pElem;
	}

	// check also hierarchy (during rebuild)
	for (pElem = m_stListHierarchy.GetHeadElement(pos); pElem;
		 pElem = m_stListHierarchy.GetNextElement(pos))
	{
		if (pElem->GetStruct() == hSupObj)
			return pElem;
	}

	// object was not found
	return NULL;
}

/*===========================================================================
*		Description:	Create new Editor Super-object from engine SO
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
CPA_SuperObject * EDT_HierarchyEditor::GetNewSuperObject (HIE_tdxHandleToSuperObject hEngineSO, 
														  tdeSaveStatus eStatus, tdeTypeSO eTypeSO, 
														  CString csName , CString csEngineFileName)
{
	EDT_SuperObject *pSupObj;

	pSupObj = new EDT_SuperObject(this, hEngineSO, eStatus, eTypeSO, csName, csEngineFileName);

	return pSupObj;
}

/*===========================================================================
*		Description:	Create new Editor Super-object
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
CPA_SuperObject * EDT_HierarchyEditor::GetNewSuperObject (tdeSaveStatus eStatus, tdeTypeSO eTypeSO,
														  CString csName, CString csEngineFileName)
{
	EDT_SuperObject *pSupObj;

	pSupObj = new EDT_SuperObject(this, eStatus, eTypeSO, csName, csEngineFileName);

	return pSupObj;
}
/*===========================================================================
*		Description:	Create copy of super-object
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
CPA_SuperObject * EDT_HierarchyEditor::GetCopyOfSuperObject	(CPA_SuperObject *pModel)
{
	EDT_SuperObject *pSupObj;
	EDT_SuperObject *pMyModel;

	pMyModel = (EDT_SuperObject *) pModel;

	pSupObj = new EDT_SuperObject(*pMyModel);

	return pSupObj;
}

/*===========================================================================
*		Description:	Create a copy of a descriptor (instance alone or hierarchy tree)
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
EDT_SuperObject * EDT_HierarchyEditor::GetACopy(EDT_SuperObject *pDesc, BOOL bInstanceAlone, BOOL bFirstCopy)
{
	EDT_SuperObject		 *pNewEdObj, *pNewOwner;
	EDT_SuperObject		 *pEdChild, *pNewChild;
	POSITION			 pos;

	// New object to insert
	pNewEdObj = (EDT_SuperObject *) GetCopyOfSuperObject(pDesc);
	pNewEdObj->MyObjectIsAlsoACopy(pDesc);
	if (bFirstCopy)
		pNewEdObj->SetNameForCopy(pDesc);
	else
		pNewEdObj->SetNameForPaste(pDesc);


	pNewEdObj->mfn_vSetInitialSPOName (pDesc->mfn_csGetInitialSPOName ());
	// next level of the hierarchy
	pEdChild = (EDT_SuperObject *) pDesc->GetSuperObjectFirstChild();
	while (pEdChild)
	{
		// instance alone : copy only protected childs
		if ((!bInstanceAlone)||(pEdChild->GetSuperObjectOwner()))
		{
			// create the new child
			pNewOwner =  (pEdChild->GetSuperObjectOwner() == pDesc) ? pNewEdObj : NULL;
			pNewChild = GetRecursiveCopy(pEdChild, pNewOwner, bInstanceAlone, bFirstCopy);
			// update the list of childs
			pos = pNewEdObj->Find(pNewChild, NULL);
			if (!pos)
				pNewChild->fn_vInsertUnderParent(pNewEdObj);
		}
		pEdChild = (EDT_SuperObject *) pDesc->GetSuperObjectNextChild(pEdChild);
	}


	// new Editable Object
	return pNewEdObj;
}


/*===========================================================================
*		Description:	Create a a copy of a hierarchy tree
*						(recursive function)
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
EDT_SuperObject * EDT_HierarchyEditor::GetRecursiveCopy(EDT_SuperObject *pDesc, EDT_SuperObject *pOwner, BOOL bInstanceAlone, BOOL bFirstCopy)
{
	EDT_SuperObject		 *pNewEdObj, *pNewOwner;
	EDT_SuperObject		 *pEdChild, *pNewChild;
	POSITION			 pos;

	// protected objet
	if (pDesc->GetSuperObjectOwner())
	{
		pNewEdObj = (EDT_SuperObject *) pDesc->GetSuperObjectOwner()->GetObjectDLL()->GetCopyOfProtectedChild(pDesc, pOwner);
		pNewEdObj->SetSuperObjectOwner(pOwner);
	}
	else
	{
		pNewEdObj = (EDT_SuperObject *) GetCopyOfSuperObject(pDesc);
		pNewEdObj->MyObjectIsAlsoACopy(pDesc);
	}

	// set new name
	if (bFirstCopy)
		pNewEdObj->SetNameForCopy(pDesc);

	// next level of the hierarchy
	pEdChild = (EDT_SuperObject *) pDesc->GetSuperObjectFirstChild();
	while (pEdChild)
	{
		// instance alone : copy only protected childs
		if ((!bInstanceAlone)||(pEdChild->GetSuperObjectOwner()))
		{
			// get owner
			if (pEdChild->GetSuperObjectOwner())
			{
				CPA_SuperObject *pNewOwn = (pEdChild->GetSuperObjectOwner()== pDesc) ? pNewEdObj : pNewEdObj->GetSuperObjectOwner();
				pNewOwner = (EDT_SuperObject *) pNewOwn;
			}
			else
				pNewOwner = NULL;
			// create the new child
			pNewChild = GetRecursiveCopy(pEdChild, pNewOwner, bInstanceAlone, bFirstCopy);
			// update the list of childs
			pos = pNewEdObj->Find(pNewChild, NULL);
			if (!pos)
				pNewChild->fn_vInsertUnderParent(pNewEdObj);
		}
		// next brother
		pEdChild = (EDT_SuperObject *) pDesc->GetSuperObjectNextChild(pEdChild);
	}


	// new Editable Object
	return pNewEdObj;
}


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

/*===========================================================================
*		Description:	Set cursor
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                Author:
*=========================================================================*/
void EDT_HierarchyEditor::SetCurrentCursor (int iNumCursor, BOOL bSaveCurrentCursor)
{
	HCURSOR hCurrentCursor;
	// set new cursor
	hCurrentCursor = (HCURSOR) SetClassLong 
			(M_GetViewPort3d()->m_hWnd, GCL_HCURSOR, (LONG) m_a_hCursors[iNumCursor]);
	SetCursor(m_a_hCursors[iNumCursor]);

	// if necessary, register current one
	if (bSaveCurrentCursor)
	{
		if ((iNumCursor != C_hc_CurrentCursor)&&(m_a_hCursors[C_hc_CurrentCursor] != hCurrentCursor))
			m_a_hCursors[C_hc_CurrentCursor] = hCurrentCursor;
	}
}

/*===========================================================================
*		Description:	Set editor mode and update cursor
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                Author:
*=========================================================================*/
void EDT_HierarchyEditor::SetEditorMode (tdeEditorMode eNewMode)
{
	CPA_Interface	*pInterface = GetInterface();
	CPA_SuperObject *pElem;
	POSITION		pos;
	
	// same mode => no change
	if (m_eEditorMode == eNewMode)
		return;

	// set normal cursor 
	if (m_a_hCursors[C_hc_CurrentCursor])
		SetCurrentCursor(C_hc_CurrentCursor);
	// cancel parent mode => reinit drawing
	if (m_eEditorMode == E_em_HierarchyMode)
	{
		// reinit engine selection
		pInterface->fn_vSetLocalColor(M_GetWorld()->GetRoot(), E_lm_ShowNormal);
		for (pElem = M_GetWorld()->GetListSelected()->GetHeadElement(pos); pElem;
			 pElem = M_GetWorld()->GetListSelected()->GetNextElement(pos))
			pInterface->fn_vSetLocalColor(pElem, E_lm_ShowSelected);
	}
	
	// update cursor and multiselect
	switch (eNewMode)
	{
		case E_em_HierarchyMode:
			SetCurrentCursor(C_hc_HierarchyCursor);
			for (pElem = M_GetWorld()->GetListSelected()->GetHeadElement(pos); pElem;
				 pElem = M_GetWorld()->GetListSelected()->GetNextElement(pos))
				pInterface->fn_vSetLocalColor(pElem->GetSuperObjectFather(), E_lm_ShowParent);
			m_bMultiSelectMode = FALSE;
			break;
		case E_em_ChoiceMode:
			SetCurrentCursor(C_hc_ChoiceCursor);
			break;
		case E_em_ParentMode:
			SetCurrentCursor(C_hc_PFatherCursor);
			m_bMultiSelectMode = FALSE;
			break;
		case E_em_PositionMode:
			SetCurrentCursor(C_hc_PPositionCursor);
			break;
		case E_em_CopyAllMode:
			SetCurrentCursor(C_hc_CopyAllCursor);
			break;
		case E_em_CopyAloneMode:
			SetCurrentCursor(C_hc_CopyAloneCursor);
			break;
// Begin Silviu Simen 18 August 1998 Cut/Paste Mechanism
		case E_em_CutPasteMode:
			SetCurrentCursor(C_hc_MoveToCursor);
			break;
// End Silviu Simen 18 August 1998 Cut/Paste Mechanism
//CPA2 Corneliu Babiuc (multiple registration) 07-07-98
		case E_em_RegisterSelection:
			SetCurrentCursor(C_hc_CopyAllCursor);
			break;
		case E_em_ClearRegistration:
			SetCurrentCursor(C_hc_CopyAloneCursor);
			break;
//END CPA2 Corneliu Babiuc (multiple registration) 07-07-98
		case E_em_MoveToMode:
//CPA2 Corneliu Babiuc (TMS_0598) 25-05-98
			// now allow to teleport multiple selection
//			if ((M_GetWorld()->GetCountSelected() == 1) || m_bIsASelection)
			if ((M_GetWorld()->GetCountSelected() >= 1) || /*m_bIsASelection CPA2 Corneliu Babiuc (multiple registration)*/
				M_GetWorld()->GetCountRegistered())
//END CPA2 Corneliu Babiuc (TMS_0598) 25-05-98
				SetCurrentCursor(C_hc_MoveToCursor);
			else
				SetCurrentCursor(C_hc_SelectToCursor);
			break;
//CPA2 Corneliu Babiuc 14-06-98
		case E_em_MoveToInstance:
			if ((M_GetWorld()->GetCountSelected() == 1) || /*m_bIsASelection CPA2 Corneliu Babiuc (multiple registration)*/
				M_GetWorld()->GetCountRegistered() == 1)
				SetCurrentCursor(C_hc_MoveToCursor);
			else
				SetCurrentCursor(C_hc_SelectToCursor);
			break;
		case E_em_MoveCameraToInstance:
		case E_em_MoveCameraCentered:
			SetCurrentCursor(C_hc_MoveToCursor);
			break;
//END CPA2 Corneliu Babiuc 15-06-98

		case E_em_OrientMode:
			if (M_GetWorld()->GetCountSelected() == 1)
				SetCurrentCursor(C_hc_OrientCursor);
			break;
		case E_em_VOrientMode:
			if (M_GetWorld()->GetCountSelected() == 1)
				SetCurrentCursor(C_hc_VOrientCursor);
			break;
	}
	// set new mode
	m_eEditorMode = eNewMode;
	// update drawing
	pInterface->fn_vUpdateAll(E_mc_JustDraw);
}


//#################################################################################
// REINIT
//#################################################################################

/*===========================================================================
*		Description:	Update Editor and dispatch message when Device changes
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vOnChangeDevice (void)
{

	// check if there is a world
	m_bHasCurrentWorld = ((GetInterface()->GetMultiDevice())&&(M_GetWorld()));

	// update dialogs
	if (m_bHasCurrentWorld && m_pDialogList)
	{
		m_pDialogList->fn_vInitAllLists();
		GetInterface()->fn_vUpdateAll(E_mc_UpdateAll);
	}
}


/*===========================================================================
*		Description:	Update Editor and dispatch message when World changes
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vOnChangeWorld (void)
{
	// check if there is a world
	m_bHasCurrentWorld = ((GetInterface()->GetMultiDevice())&&(M_GetWorld()));

	// update all dialogs
	if (m_bHasCurrentWorld && m_pDialogList)
	{
		m_pDialogList->fn_vInitAllLists();
		GetInterface()->fn_vUpdateAll(E_mc_UpdateAll);
	}
}


/*===========================================================================
*		Description:	Update Editor and dispatch message when Root changes
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vOnChangeRoot (void)
{
	// check if there is a world
	m_bHasCurrentWorld = ((GetInterface()->GetMultiDevice())&&(M_GetWorld()));

	// update all dialogs
	if (m_bHasCurrentWorld && m_pDialogList)
	{
		m_pDialogList->fn_vInitAllLists();
		if (!GetInterface()->fn_bIsLoadingWorld())
			GetInterface()->fn_vUpdateAll(E_mc_UpdateAll);
	}
}

//#################################################################################
// PERMISSIONS
//#################################################################################

/*===========================================================================
*		Description:	check if all selected objects can be moved
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bCanTranslateAllObjects (tdeList eList)
{
//	CPA_SuperObject *pSupObj;
	EDT_ListByDLL	*pListSelect;
	POSITION		pos;

//CPA2 Corneliu Babiuc (multiple registration) 3-07-98
	CPA_List<EDT_ListByDLL> *pListByDLL; 
		switch (eList)
		{
		case E_lst_SelectedList:
			pListSelect = M_GetWorld()->GetListAllDLLs();
			pListByDLL = M_GetWorld()->GetListOfListByDLL();
			break;
		case E_lst_RegisteredList:
			pListSelect = M_GetWorld()->GetRegisterListAllDLLs();
			pListByDLL = M_GetWorld()->GetListOfRegisteredListByDLL();
			break;
		default:
			ASSERT (0);
		}
//END CPA2 Corneliu Babiuc (multiple registration) 3-07-98

	// check current editor for permission
	if (!fn_bIsCurrentEditor())
	{
		pListSelect = M_GetWorld()->GetListAllDLLs();
		if (pListSelect->m_stListSelected.GetCount())
		{
			if (!M_GetCurrentEditor()->fn_bAcceptModifTranslate(&pListSelect->m_stListSelected, C_AsCurrentEditor))
			{
				m_csMessage = "Current Editor does not allow you to translate these objects";
				return FALSE;
			}
		}
	}
	// check all the DLLs for permission
//CPA2 Corneliu Babiuc (multiple registration) 03-07-98
//	for (pListSelect = M_GetWorld()->GetListOfListByDLL()->GetHeadElement(pos); pListSelect;
//		 pListSelect = M_GetWorld()->GetListOfListByDLL()->GetNextElement(pos))
	for (pListSelect = pListByDLL->GetHeadElement(pos); pListSelect;
		 pListSelect = pListByDLL->GetNextElement(pos))
//END CPA2 Corneliu Babiuc (multiple registration) 03-07-98
	{
		// if there are selected objects of this type
		if (pListSelect->m_stListSelected.GetCount())
		{
			// ask World permission
			if (!M_GetWorld()->fn_bAcceptModifTranslate(pListSelect->GetDLL()))
			{
				m_csMessage.Format("Objects of DLL %s cannot be translated in this world.", pListSelect->GetDLL()->GetName());
				return FALSE;
			}
			// ask the DLL for permission
			if (!pListSelect->GetDLL()->fn_bAcceptModifTranslate(&pListSelect->m_stListSelected, C_AsConcernedDLL))
			{
				m_csMessage.Format("DLL %s does not allow you to translate its objects.", pListSelect->GetDLL()->GetName());
				return FALSE;
			}
		}
		// if necessary, ask owner permission
		if (pListSelect->m_stListProtectSelected.GetCount())
		{
			// ask the DLL for permission
			if (!pListSelect->GetDLL()->fn_bAcceptModifTranslate(&pListSelect->m_stListProtectSelected, C_AsChildOwner))
			{
				m_csMessage = "Some protected objets cannot be translated";
				return FALSE;
			}
		}
	}
	// objects can be moved
	return TRUE;
}


/*===========================================================================
*		Description:	check if all selected objects can be moved
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bCanRotateAllObjects (void)
{
	CPA_SuperObject	*pSupObj;
	EDT_ListByDLL	*pListSelect;
	POSITION		pos;

	// check super-objects flags
	for (pSupObj = M_GetWorld()->GetListSelected()->GetHeadElement(pos); pSupObj;
		 pSupObj = M_GetWorld()->GetListSelected()->GetNextElement(pos))
	{
		if (HIE_fn_SO_bHasNoTransformationMatrix(pSupObj->GetStruct()))
		{
			m_csMessage = "Some super-objects have no transformation matrix";
			return FALSE;
		}
	}

	
	// check current editor for permission
	if (!fn_bIsCurrentEditor())
	{
		pListSelect = M_GetWorld()->GetListAllDLLs();
		if (pListSelect->m_stListSelected.GetCount())
		{
			if (!M_GetCurrentEditor()->fn_bAcceptModifRotate(&pListSelect->m_stListSelected, C_AsCurrentEditor))
			{
				m_csMessage = "Current Editor does not allow you to rotate these objects";
				return FALSE;
			}
		}
	}
	for (pListSelect = M_GetWorld()->GetListOfListByDLL()->GetHeadElement(pos); pListSelect;
		 pListSelect = M_GetWorld()->GetListOfListByDLL()->GetNextElement(pos))
	{
		// if there are selected objects of this type
		if (pListSelect->m_stListSelected.GetCount())
		{
			// ask World permission
			if (!M_GetWorld()->fn_bAcceptModifRotate(pListSelect->GetDLL()))
			{
				m_csMessage.Format("Objects of DLL %s cannot be rotated in this world.", pListSelect->GetDLL()->GetName());
				return FALSE;
			}
			// ask the DLL for permission
			if (!pListSelect->GetDLL()->fn_bAcceptModifRotate(&pListSelect->m_stListSelected, C_AsConcernedDLL))
			{
				m_csMessage.Format("DLL %s does not allow you to rotate its objects.", pListSelect->GetDLL()->GetName());
				return FALSE;
			}
		}
		// if necessary, ask owner
		if (pListSelect->m_stListProtectSelected.GetCount())
		{
			// ask the DLL for permission
			if (!pListSelect->GetDLL()->fn_bAcceptModifRotate(&pListSelect->m_stListProtectSelected, C_AsChildOwner))
			{
				m_csMessage = "Some protected objets cannot be rotated";
				return FALSE;
			}
		}
	}

	// objects can be moved
	return TRUE;
}


/*===========================================================================
*		Description:	check if all selected objects can be deleted
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bCanDeleteAllObjects (void)
{
	CPA_SuperObject	*pEdObj;
	EDT_ListByDLL	*pListSelect;
	POSITION		pos;

	// ask for interface permission
	pListSelect = M_GetWorld()->GetListAllDLLs();
	for (pEdObj = pListSelect->m_stListConcerned.GetHeadElement(pos); pEdObj;
		 pEdObj = pListSelect->m_stListConcerned.GetNextElement(pos))
	{
		if (!GetInterface()->fn_bCanModifyObject(pEdObj))
		{
			m_csMessage = "You cannot modify objects created by this designer";
			return FALSE;
		}
	}

	
	// check current editor for permission
	if (!fn_bIsCurrentEditor())
	{
		pListSelect = M_GetWorld()->GetListAllDLLs();
		if (pListSelect->m_stListConcerned.GetCount())
		{
			if (!M_GetCurrentEditor()->fn_bAcceptModifDelete(&pListSelect->m_stListConcerned, C_AsCurrentEditor))
			{
				m_csMessage = "Current Editor does not allow you to delete these objects";
				return FALSE;
			}
		}
	}
	// check all the DLLs for permission
	for (pListSelect = M_GetWorld()->GetListOfListByDLL()->GetHeadElement(pos); pListSelect;
		 pListSelect = M_GetWorld()->GetListOfListByDLL()->GetNextElement(pos))
	{
		// if there are selected objects of this type
		if (pListSelect->m_stListConcerned.GetCount())
		{
			// ask World permission
			if (!M_GetWorld()->fn_bAcceptModifDelete(pListSelect->GetDLL()))
			{
				m_csMessage.Format("Objects of DLL %s cannot be deleted in this world.", pListSelect->GetDLL()->GetName());
				return FALSE;
			}
			// ask the DLL for permission
			if (!pListSelect->GetDLL()->fn_bAcceptModifDelete(&pListSelect->m_stListConcerned, C_AsConcernedDLL))
			{
				m_csMessage.Format("DLL %s does not allow you to delete its objects.", pListSelect->GetDLL()->GetName());
				return FALSE;
			}
		}
		// if necessary, ask owner
		if (pListSelect->m_stListProtectSelected.GetCount())
		{
			// ask the DLL for permission
			if (!pListSelect->GetDLL()->fn_bAcceptModifDelete(&pListSelect->m_stListProtectSelected, C_AsChildOwner))
			{
				m_csMessage = "Some protected objets cannot be deleted";
				return FALSE;
			}
		}
	}
	// objects can be moved
	return TRUE;
}

/*===========================================================================
*		Description:	check if all selected objects can change parent
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bCanChangeAllParents (void)
{
	EDT_ListByDLL	*pListSelect;
	POSITION		pos;

	// check permissions
	if (!fn_bCanChangeSelectedObjects())
		return FALSE;
	
	// check current editor for permission
	if (!fn_bIsCurrentEditor())
	{
		pListSelect = M_GetWorld()->GetListAllDLLs();
		if (pListSelect->m_stListSelected.GetCount())
		{
			if (!M_GetCurrentEditor()->fn_bAcceptModifParent(&pListSelect->m_stListSelected, C_AsCurrentEditor))
			{
				m_csMessage = "Current Editor does not allow you to change these objects' parent";
				return FALSE;
			}
		}
	}
	// check all the DLLs for permission
	for (pListSelect = M_GetWorld()->GetListOfListByDLL()->GetHeadElement(pos); pListSelect;
		 pListSelect = M_GetWorld()->GetListOfListByDLL()->GetNextElement(pos))
	{
		// if there are selected objects of this type
		if (pListSelect->m_stListSelected.GetCount())
		{
			// ask World permission
			if (!M_GetWorld()->fn_bAcceptModifParent(pListSelect->GetDLL()))
			{
				m_csMessage.Format("Parents of the objects of DLL %s cannot be changed in this world.", pListSelect->GetDLL()->GetName());
				return FALSE;
			}
			// ask the DLL for permission
			if (!pListSelect->GetDLL()->fn_bAcceptModifParent(&pListSelect->m_stListSelected, C_AsConcernedDLL))
			{
				m_csMessage.Format("DLL %s does not allow you to change its objects' parent.", pListSelect->GetDLL()->GetName());
				return FALSE;
			}
		}
		// if necessary, ask owner
		if (pListSelect->m_stListProtectSelected.GetCount())
		{
			// ask the DLL for permission
			if (!pListSelect->GetDLL()->fn_bAcceptModifParent(&pListSelect->m_stListProtectSelected, C_AsChildOwner))
			{
				m_csMessage = "Some protected objets cannot change their parent";
				return FALSE;
			}
		}
	}
	// objects can be moved
	return TRUE;
}

/*===========================================================================
*		Description:	check if all selected objects can be copied
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bCanCopyAllObjects (void)
{
	EDT_ListByDLL  *pListSelect;
	POSITION		  pos;

	// check current editor for permission
	if (!fn_bIsCurrentEditor())
	{
		pListSelect = M_GetWorld()->GetListAllDLLs();
		if (pListSelect->m_stListConcerned.GetCount())
		{
			if (!M_GetCurrentEditor()->fn_bAcceptModifCopy(&pListSelect->m_stListConcerned, C_AsCurrentEditor))
			{
				m_csMessage = "Current Editor does not allow you to copy these objects";
				return FALSE;
			}
		}
	}
	// check all the DLLs for permission
	for (pListSelect = M_GetWorld()->GetListOfListByDLL()->GetHeadElement(pos); pListSelect;
		 pListSelect = M_GetWorld()->GetListOfListByDLL()->GetNextElement(pos))
	{
		// if there are selected objects of this type
		if (pListSelect->m_stListConcerned.GetCount())
		{
			// ask World permission
			if (!M_GetWorld()->fn_bAcceptModifCopy(pListSelect->GetDLL()))
			{
				m_csMessage.Format("Objects of DLL %s cannot be copied in this world.", pListSelect->GetDLL()->GetName());
				return FALSE;
			}

			// ask the DLL for permission
			if (!pListSelect->GetDLL()->fn_bAcceptModifCopy(&pListSelect->m_stListConcerned, C_AsConcernedDLL))
			{
				m_csMessage.Format("DLL %s does not allow you to copy its objects.", pListSelect->GetDLL()->GetName());
				return FALSE;
			}
		}
		// if necessary, ask owner
		if (pListSelect->m_stListProtectSelected.GetCount())
		{
			// ask the DLL for permission
			if (!pListSelect->GetDLL()->fn_bAcceptModifCopy(&pListSelect->m_stListProtectSelected, C_AsChildOwner))
			{
				m_csMessage = "Some protected objets cannot be copied";
				return FALSE;
			}
		}
	}
	// objects can be moved
	return TRUE;
}


/*===========================================================================
*		Description:	check if parent is coherent
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bCanBeParent (CPA_SuperObject *pParent, tdstPosition *p_stPosition, tdeTypeSO eTypeSO, tdeSaveStatus eStatus)
{
	CPA_SuperObject *pSector;

	// check type
	switch (eTypeSO)
	{
		case C_Protected:
			return TRUE;

		case C_Dynamic:
			return (pParent == GetInterface()->GetSpecificInterface()->GetDynamicRoot());

		case C_Static:
			pSector = GetInterface()->GetSpecificInterface()->GetCurrentSectorFromPos(&p_stPosition->stPos.stPos3D);

			if (pParent->GetTypeSO() != C_Static)
				return FALSE;
			if (GetInterface()->GetSpecificInterface()->GetSuperObjectCurrentSector(pParent) != pSector)
				return FALSE;
			if (!GetSpecificEditor()->fn_bCheckSaveStatus(eStatus, (EDT_SuperObject *)pParent))
				return FALSE;

			return TRUE;
	}
	return FALSE;
}

/*===========================================================================
*		Description:	check if pEdObj is accepted as parent for all
*						selected objects
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bCanBeParentForAll (CPA_SuperObject *pNewParent)
{
	CPA_SuperObject *pElem;
	EDT_SuperObject	*pSupObj;
	EDT_SuperObject  *pParent;
	POSITION		pos;

	pParent = (EDT_SuperObject *) pNewParent;
	
	// check specific editor
	if (!m_pSpecificEditor->fn_bCanBeParent(pParent, M_GetWorld()->GetListSelected()))
		return FALSE;
	
	// check all the elements in the list
	for (pElem = M_GetWorld()->GetListSelected()->GetHeadElement(pos); pElem;
		 pElem = M_GetWorld()->GetListSelected()->GetNextElement(pos))
	{
		pSupObj = (EDT_SuperObject *) pElem;
		
		// hierarchy links must be coherent
		if (pParent->fn_bIsUnderObject(pSupObj))
			return FALSE;
		// hierarchy links must be valid
		if ((!pSupObj->fn_bAcceptAsParent(pParent))||(!pParent->fn_bAcceptAsChild(pSupObj)))
			return FALSE;
	}
	// object can be parent
	return TRUE;
}


/*===========================================================================
*		Description:	check if we can enter multi select mode
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bCanEnterMultiMode (void)
{
	// parent selection => no multiselect
	if ((m_eEditorMode == E_em_HierarchyMode)||(m_eEditorMode == E_em_ParentMode))
		return FALSE;

	// check current editor permission
	if ((!fn_bIsCurrentEditor())&&(!M_GetCurrentEditor()->fn_bAcceptMultiSelect()))
		return FALSE;

	// check world permission
	if (!M_GetWorld()->fn_bAcceptMultiSelect())
		return FALSE;

	// no objection
	return TRUE;
}




//#################################################################################
// INSERTION
//#################################################################################

/*===========================================================================
*		Description:	find parent for insertion
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                           Author:
*=========================================================================*/
EDT_SuperObject * EDT_HierarchyEditor::GetParentForInsertion (CPA_ObjectDLLBase *p_oDLL, CString csTypeName, CString csModelName, tdstPosition *p_stPosition, tdeTypeSO eTypeInsert, tdeSaveStatus eStatus)
{
	EDT_SuperObject				*pParent = NULL;
	MTH3D_tdstVector			stNormal;
	BOOL						bRes;

	bRes = fn_bFindPickingPosition(p_stPosition);
	
	// Ask DLL for a parent
	pParent = (EDT_SuperObject *) p_oDLL->GetParentForInsertion(csTypeName, csModelName, p_stPosition);

	// if necessary, try to find default parent
	if (!pParent)
	{
		if (!bRes)
			return NULL;
		// move position to guarantee it is in a sector
		fn_vGetNormalFromPicking(p_stPosition->a_stPickInfo, &stNormal);
		MTH3D_M_vMulScalarVector(&stNormal, (float)0.1, &stNormal);
		MTH3D_M_vAddVector(&p_stPosition->stPos.stPos3D, &p_stPosition->stPos.stPos3D, &stNormal);
		// get corresponding default parent
		pParent = (EDT_SuperObject *) GetInterface()->GetSpecificInterface()->GetDefaultParentFromPos(p_stPosition, eTypeInsert, eStatus);
		// reinit position
		MTH3D_M_vMulScalarVector(&stNormal, (float)-1.0, &stNormal);
		MTH3D_M_vAddVector(&p_stPosition->stPos.stPos3D, &p_stPosition->stPos.stPos3D, &stNormal);
	}
	return pParent;
}


/*===========================================================================
*		Description:	check if all selected objects can be deleted
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bCanDelete (EDT_SuperObject *pEdObj)
{
	CPA_List<CPA_SuperObject> stListDelete;

	// there must be a world !
	if ((!m_bHasCurrentWorld)||(!M_GetWorld()->GetRoot()))
		return FALSE;

	// object must be in the hierarchy
	if (!pEdObj->fn_bIsUnderObject(M_GetWorld()->GetRoot()))
		return FALSE;

	// ask for interface permission
	if (!GetInterface()->fn_bCanModifyObject(pEdObj))
		return FALSE;

	// ask DLLs for permission
	stListDelete.RemoveAll();
	stListDelete.AddTail(pEdObj);

	// ask World
	if (!M_GetWorld()->fn_bAcceptModifDelete(pEdObj->GetObjectDLL()))
		return FALSE;
	// ask current editor
	if (!fn_bIsCurrentEditor())
	{
		if (!M_GetCurrentEditor()->fn_bAcceptModifDelete(&stListDelete, C_AsCurrentEditor))
			return FALSE;
	}
	// ask concerned DLL
	if (pEdObj->GetObjectDLL())
	{
		if (!pEdObj->GetObjectDLL()->fn_bAcceptModifDelete(&stListDelete, C_AsConcernedDLL))
			return FALSE;
	}
	// if necessary, ask owner
	if (pEdObj->GetSuperObjectOwner())
	{
		if (!pEdObj->GetSuperObjectOwner()->GetObjectDLL()->fn_bAcceptModifDelete(&stListDelete, C_AsChildOwner))
			return FALSE;
	}

	// no objection
	return TRUE;
}

/*===========================================================================
*		Description:	check if object can be inserted in hierarchy
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bCanInsert (EDT_SuperObject *pEdObj, EDT_SuperObject *pParent)
{
	// there must be a world !
	if ((!m_bHasCurrentWorld)||(!M_GetWorld()->GetRoot()))
		return FALSE;

	// check the hierarchy
	if ((pParent->fn_bIsUnderObject(pEdObj))||(pEdObj->fn_bIsUnderObject(M_GetWorld()->GetRoot()))
	  ||(!pParent->fn_bIsUnderObject(M_GetWorld()->GetRoot())))
	{
		m_csMessage = "Hierarchy links are not coherent";
		return FALSE;
	}

	// ask specific editor
	if (!m_pSpecificEditor->fn_bCanBeParent(pParent, pEdObj))
	{
		m_csMessage = "Parent is not valid";
		return FALSE;
	}
	// parent must be valid
	if ((!pEdObj->fn_bAcceptAsParent(pParent))
	  ||(!pParent->fn_bAcceptAsChild(pEdObj)))
	{
		m_csMessage = "Parent is not valid";
		return FALSE;
	}

	// ask World
	if (!M_GetWorld()->fn_bAcceptModifInsert(pEdObj->GetObjectDLL()))
	{
		m_csMessage = "Instances of DLL " + pEdObj->GetObjectDLL()->GetName() + " cannot be inserted in this world";
		return FALSE;
	}
	// ask current editor
	if (!fn_bIsCurrentEditor())
	{
		if (!M_GetCurrentEditor()->fn_bAcceptModifInsert(pEdObj, pParent, C_AsCurrentEditor))
		{
			m_csMessage = "Current Editor does not accept this insertion";
			return FALSE;
		}
	}
	// ask concerned DLL
	if (pEdObj->GetObjectDLL())
	{
		if (!pEdObj->GetObjectDLL()->fn_bAcceptModifInsert(pEdObj, pParent, C_AsConcernedDLL))
		{
			m_csMessage = "DLL " + pEdObj->GetObjectDLL()->GetName() + " does not accept this insertion";
			return FALSE;
		}
	}
	// if necessary, ask owner
	if (pEdObj->GetSuperObjectOwner())
	{
		if (!pEdObj->GetSuperObjectOwner()->GetObjectDLL()->fn_bAcceptModifInsert(pEdObj, pParent, C_AsChildOwner))
		{
			m_csMessage = "Owner of the new protected instance does not accept this insertion.";
			return FALSE;
		}
	}

	// no objection
	return TRUE;
}

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

/*===========================================================================
*		Description:	insert object in the hierarchy and update all lists
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bInsertObjectInHierarchy (CPA_SuperObject *pEdObj, CPA_SuperObject *pParent, 
											  BOOL bUseEditManager, BOOL bUpdateDrawing, BOOL bSelect, BOOL pBlock)

{
	EDT_SuperObject *pNewSO;
	EDT_SuperObject *pNewParent;
	EDT_ModifInsert *pModifInsert;

	pNewSO = (EDT_SuperObject *) pEdObj;
	pNewParent = (EDT_SuperObject *) pParent;
	
	// check if parent is valid
	if (!fn_bCanInsert(pNewSO, pNewParent))
		return FALSE;

	// create modif
	pModifInsert = new EDT_ModifInsert 
		(this, pNewSO, pNewParent, NULL, NULL, bUpdateDrawing, bSelect, pBlock);
	
	// insert object in hierarchy
	if (bUseEditManager)
		M_GetEditManager()->AskFor(pModifInsert);
	else
	{
		pModifInsert->Do();
		delete pModifInsert;
	}

	return TRUE;
}

/*===========================================================================
*		Description:	insert object in the hierarchy and update all lists
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bInsertAsPreviousBrother (CPA_SuperObject *pEdObj, CPA_SuperObject *pBrother, 
											  BOOL bUseEditManager, BOOL bUpdateDrawing, BOOL bSelect, BOOL pBlock)
{
	EDT_SuperObject *pParent, *pNewSO, *pNewBrother;
	EDT_ModifInsert	*pModifInsert;

	pNewBrother = (EDT_SuperObject *) pBrother;
	pNewSO = (EDT_SuperObject *) pEdObj;
	
	// check if parent is valid
	pParent = (EDT_SuperObject *) pNewBrother->GetSuperObjectFather();
	if ((!pParent)||(!fn_bCanInsert(pNewSO, pParent)))
	  return FALSE;

	// create modif
	pModifInsert = new EDT_ModifInsert 
		(this, pNewSO, pParent, NULL, pNewBrother, bUpdateDrawing, bSelect, pBlock);
	
	// insert object in hierarchy
	if (bUseEditManager)
		M_GetEditManager()->AskFor(pModifInsert);
	else
	{
		pModifInsert->Do();
		delete pModifInsert;
	}

	return TRUE;
}

/*===========================================================================
*		Description:	delete object in the hierarchy and update all lists
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bDeleteObjectInHierarchy (CPA_SuperObject *pEdObj, BOOL bUseEditManager, 
													   BOOL bUpdateDrawing, BOOL bDestroySuperObject, BOOL bSelect, BOOL pBlock)
{
	EDT_SuperObject *pOldSO;
	EDT_ModifDelete *pModifDelete;
	
	pOldSO = (EDT_SuperObject *) pEdObj;
	// check permissions
	if (!fn_bCanDelete(pOldSO))
		return FALSE;

	// create modif
	pModifDelete = new EDT_ModifDelete (this, pOldSO, GetInterface()->GetSelectMode(), 
										bUpdateDrawing, bDestroySuperObject, bSelect, pBlock);
	// insert object in hierarchy
	if (bUseEditManager)
		M_GetEditManager()->AskFor(pModifDelete);
	else
	{
		pModifDelete->Do();
		delete pModifDelete;
	}

	return TRUE;
}


//#################################################################################
// MOVES
//#################################################################################

/*===========================================================================
*		Description:	Find if the Mouse is on selected object
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:         Author:
*=========================================================================*/
CPA_SuperObject * EDT_HierarchyEditor::fn_pstIsMouseOnObject (ACP_tdxIndex xIndex, HIE_tdstPickInfo *p_stObject)
{
	CPA_SuperObject		*pCurChild, *pElem;
	ACP_tdxIndex		xInd = 0;
	POSITION			pos;

	// if there's no selection
	if (!M_GetWorld()->GetCountSelected())
		return NULL;

	while (xInd < xIndex)
	{
		// find the child corresponding to p_tIndex
		pCurChild = GetEditorObject(p_stObject[xInd++].hSprObject);
		if ( !pCurChild )
		{
			ASSERT(FALSE); //this should not occur, but continue anyway if you choose to ignore
			return NULL;
		}

		// find the corresponding list
		for (pElem = M_GetWorld()->GetListSelected()->GetHeadElement(pos); pElem;
			 pElem = M_GetWorld()->GetListSelected()->GetNextElement(pos))
		{
			if (pCurChild->fn_bIsUnderObject(pElem))
				return pElem;
		}
	}
	return NULL;
}


/*===========================================================================
*		Description:	Rotate object around selected axis
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                 Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vRotateObjects (int iAxe, int iDirection )
{
	CPA_SuperObject		*pElem;
	EDT_SuperObject		*pSupObj;
	POS_tdstCompletePosition	stMatrix;
	GLI_tdxValue		xAngle;
	POSITION			pos;

	POS_fn_vSetIdentityMatrix(&stMatrix);

	// First call : init the move or check permissions
	if (!m_pKeyMove)
	{
		if (fn_bCanRotateAllObjects())
		{
			// create modif
			m_pKeyMove = new EDT_ModifMove(this, M_GetWorld()->GetListOfListByDLL(), GetInterface()->GetSelectMode());
			// tell DLLs
			fn_vSendMessageBeginMove();
		}
		else
		{
			fn_vDisplayCancelMessage(E_cm_CancelMove);
			return;
		}
	}

	// Rotation matrix
	xAngle = (iDirection) ? -m_xRotationStep : m_xRotationStep;
	POS_fn_vSetIdentityMatrix(&stMatrix);
	// Rotation around selected axis
	if (iAxe == AXE_X)
		fn_vRotateX(&stMatrix, xAngle);
	else if (iAxe == AXE_Y)
		fn_vRotateY(&stMatrix, xAngle);
	else if (iAxe == AXE_Z)
		fn_vRotateZ(&stMatrix, xAngle);

	// update all objects in the list
	for (pElem = M_GetWorld()->GetListSelected()->GetHeadElement(pos); pElem;
		 pElem = M_GetWorld()->GetListSelected()->GetNextElement(pos))
	{
		pSupObj = (EDT_SuperObject *) pElem;
		pSupObj->fn_vRotate(&stMatrix);
	}
	// Tell Dlls
	fn_vSendMessageMoving();
	// Redraw the world
    GetInterface()->fn_vUpdateAll(E_mc_JustDraw);
	m_pDialogEdit->fn_vUpdateRotation();
}


/*==========================================================================
*		Description:	Translate the object
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                                                                                          Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vTranslateObjects (int iAxe, int iDirection)
{
	MTH3D_tdstVector	stVector;
	CPA_SuperObject		*pElem;
	EDT_SuperObject		*pSupObj;
	DEV_ViewPort3D		*pCurViewport;
	POS_tdstCompletePosition	stMatrix,stTempMatrix;
	GLI_tdxValue		xVal;
	POSITION			pos;

	POS_fn_vSetIdentityMatrix(&stMatrix);
	POS_fn_vSetIdentityMatrix(&stTempMatrix);

	// First call : init the move
	if (!m_pKeyMove)
	{
		if (fn_bCanTranslateAllObjects())
		{
			// create modif
			m_pKeyMove = new EDT_ModifMove(this, M_GetWorld()->GetListOfListByDLL(), GetInterface()->GetSelectMode());
			// tell dlls
			fn_vSendMessageBeginMove();
		}
		else
		{
			fn_vDisplayCancelMessage(E_cm_CancelMove);
			return;
		}
	}

	// translation vector
	xVal = (iDirection) ? m_xTranslationStep : -m_xTranslationStep;
	MTH3D_M_vNullVector(&stVector);
	// Translation on OBJECT's axis
	if (m_bMultiSelectMode)
	{
		// select axis
		if (iAxe == AXE_X)
		{
			MTH3D_M_vSetXofVector(&stVector, xVal);
		}
		else if (iAxe == AXE_Y)
		{
			MTH3D_M_vSetZofVector(&stVector, xVal);
		}
		else if (iAxe == AXE_Z)
		{
			MTH3D_M_vSetYofVector(&stVector, -xVal);
		}
		// update all objects in the list
		for (pElem = M_GetWorld()->GetListSelected()->GetHeadElement(pos); pElem;
			 pElem = M_GetWorld()->GetListSelected()->GetNextElement(pos))
		{
			pSupObj = (EDT_SuperObject *) pElem;
			pSupObj->fn_vTranslate(&stVector, FALSE);
		}
	}
	// Translation on CAMERA's axis
	else
	{
		// select axis
		if (iAxe == AXE_X)
		{
			MTH3D_M_vSetXofVector(&stVector, xVal);
		}
		else if (iAxe == AXE_Y)
		{
			MTH3D_M_vSetYofVector(&stVector, xVal);
		}
		else if (iAxe == AXE_Z)
		{
			MTH3D_M_vSetZofVector(&stVector, xVal);
		}
		// update vector according to camera position
		pCurViewport = M_GetViewPort3d();
		GLI_xGetCameraMatrix(pCurViewport->GetEngineCamera(),&stTempMatrix);
		POS_fn_vInvertMatrix(&stMatrix,&stTempMatrix);
		
		MTH3D_tdstVector stVect;

		MTH3D_M_vNullVector(&stVect);
		POS_fn_vSetTranslationVector(&stMatrix,&stVect);
		
		POS_fn_vMulMatrixVertex(&stVector, &stMatrix, &stVector);
		for (pElem = M_GetWorld()->GetListSelected()->GetHeadElement(pos); pElem;
			 pElem = M_GetWorld()->GetListSelected()->GetNextElement(pos))
		{
			pSupObj = (EDT_SuperObject *) pElem;
			pSupObj->fn_vTranslate(&stVector, TRUE);
		}
	}

	// tell DLLs
	fn_vSendMessageMoving();
	// redraw the world
	GetInterface()->fn_vUpdateAll(E_mc_JustDraw);
}




/*==========================================================================
*		Description:	check if move is available, and do or cancel it
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                                                                                          Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bDoOrCancelMove (EDT_ModifMove *pModifMove)
{
	BOOL bRes = TRUE;
	long lNbBreaks;

	// check if objects can be modified
	if (!fn_bCanChangeSelectedObjects())
	{
		m_csMessage = "You cannot modify objects created by this designer";
		m_eModifCanceled = E_cm_CancelMove;
		bRes = FALSE;
	}
	// check if move is available
	lNbBreaks = m_pSpecificEditor->fn_lCanMoveObjects(M_GetWorld()->GetListSelected());
	// move is not available
	if (lNbBreaks == -1)
	{
		m_csMessage = "Some Objects are out of all sectors";
		m_eModifCanceled = E_cm_CancelMove;
		bRes = FALSE;
	}
	// broken links => dialog 
	if (lNbBreaks > 0)
	{
		bRes = m_pDialogMove->fn_bDoDialog(this);
		M_GetViewPort3d()->SetFocus();
	}

	fn_vDisplayCancelMessage(m_eModifCanceled);

	// if move is avalaible, do modif
	if (bRes)
	{
		pModifMove->fn_vInitListModif(&m_stListOfModifParent);
		M_GetEditManager()->AskFor(pModifMove);
	}
	// cancel the move
	else
		pModifMove->Cancel();

	return bRes;
}


//#################################################################################
// MESSAGES
//#################################################################################

/*===========================================================================
*		Description:	dispatch message when moving
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vSendMessageMoving (void)
{
	CPA_ToolDLLBase		*pDLLTool;
	EDT_ListByDLL		*pListSelect;
	POSITION			pos;

	// Tell current editor
	if ((!fn_bIsCurrentEditor())&&(M_ListConcerned.GetCount()))
		M_GetCurrentEditor()->fn_vOnMoving(&M_ListSelected, &M_ListConcerned, C_AsCurrentEditor);
	 // Tell all concerned DLLs
	for (pListSelect = M_GetWorld()->GetListOfListByDLL()->GetHeadElement(pos); pListSelect;
		 pListSelect = M_GetWorld()->GetListOfListByDLL()->GetNextElement(pos))
	{
		// if there are selected objects of this type
		if (pListSelect->m_stListConcerned.GetCount())
			pListSelect->GetDLL()->fn_vOnMoving(&pListSelect->m_stListSelected, &pListSelect->m_stListConcerned, C_AsConcernedDLL);
	}
	 // Tell all owner DLLs
	for (pListSelect = M_GetWorld()->GetListOfListByDLL()->GetHeadElement(pos); pListSelect;
		 pListSelect = M_GetWorld()->GetListOfListByDLL()->GetNextElement(pos))
	{
		// if there are selected objects of this type
		if (pListSelect->m_stListProtectConcerned.GetCount())
			pListSelect->GetDLL()->fn_vOnMoving(&pListSelect->m_stListProtectSelected, &pListSelect->m_stListProtectConcerned, C_AsChildOwner);
	}
	// Tool DLLs
	for (pDLLTool = M_GetToolDLLs()->GetHeadElement(pos); pDLLTool;
		 pDLLTool = M_GetToolDLLs()->GetNextElement(pos))
	{
		// if there are selected objects of this type
		if ((M_ListConcerned.GetCount())&&(pDLLTool != M_GetCurrentEditor()))
			pDLLTool->fn_vOnMoving(&M_ListSelected, &M_ListConcerned, C_AsToolDLL);
	}
}


/*===========================================================================
*		Description:	dispatch message when begin move
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vSendMessageBeginMove (void)
{
	CPA_ToolDLLBase		*pDLLTool;
	EDT_ListByDLL		*pListSelect;
	POSITION			pos;

	// tell current editor
	if ((!fn_bIsCurrentEditor())&&(M_ListConcerned.GetCount()))
		M_GetCurrentEditor()->fn_vOnBeginMove(&M_ListSelected, &M_ListConcerned, C_AsCurrentEditor);
	// tell concerned DLLs
	for (pListSelect = M_GetWorld()->GetListOfListByDLL()->GetHeadElement(pos); pListSelect;
		 pListSelect = M_GetWorld()->GetListOfListByDLL()->GetNextElement(pos))
	{
		// if there are selected objects of this type
		if (pListSelect->m_stListConcerned.GetCount())
			pListSelect->GetDLL()->fn_vOnBeginMove(&pListSelect->m_stListSelected, &pListSelect->m_stListConcerned, C_AsConcernedDLL);
	}
	// tell owner DLLs
	for (pListSelect = M_GetWorld()->GetListOfListByDLL()->GetHeadElement(pos); pListSelect;
		 pListSelect = M_GetWorld()->GetListOfListByDLL()->GetNextElement(pos))
	{
		// if there are selected objects of this type
		if (pListSelect->m_stListProtectConcerned.GetCount())
			pListSelect->GetDLL()->fn_vOnBeginMove(&pListSelect->m_stListProtectSelected, &pListSelect->m_stListProtectConcerned, C_AsChildOwner);
	}
	// Tool DLLs
	for (pDLLTool = M_GetToolDLLs()->GetHeadElement(pos); pDLLTool;
		 pDLLTool = M_GetToolDLLs()->GetNextElement(pos))
	{
		// if there are selected objects of this type
		if ((M_ListConcerned.GetCount())&&(pDLLTool != M_GetCurrentEditor()))
			pDLLTool->fn_vOnBeginMove(&M_ListSelected, &M_ListConcerned, C_AsToolDLL);
	}
}


/*===========================================================================
*		Description:	dispatch message when level changes
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vSendMessageChangeLevel (void)
{
	CPA_DLLBase		*pDLL;
	POSITION			pos;

	// tell object DLLs
	for (pDLL = GetMainWorld()->GetListOfObjectDLLBase()->GetHeadElement(pos); pDLL;
		 pDLL = GetMainWorld()->GetListOfObjectDLLBase()->GetNextElement(pos))
	{
		pDLL->fn_vLevelChanges();
	}
	// tell object DLLs
	for (pDLL = GetMainWorld()->GetListOfToolDLLBase()->GetHeadElement(pos); pDLL;
		 pDLL = GetMainWorld()->GetListOfToolDLLBase()->GetNextElement(pos))
	{
		pDLL->fn_vLevelChanges();
	}
}

/*===========================================================================
*		Description:	dispatch message when level has changed
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vSendMessageLevelChanged (void)
{
	CPA_DLLBase		*pDLL;
	POSITION			pos;

	// tell object DLLs
	for (pDLL = GetMainWorld()->GetListOfObjectDLLBase()->GetHeadElement(pos); pDLL;
		 pDLL = GetMainWorld()->GetListOfObjectDLLBase()->GetNextElement(pos))
	{
		pDLL->fn_vLevelHasChanged();
	}
	// tell object DLLs
	for (pDLL = GetMainWorld()->GetListOfToolDLLBase()->GetHeadElement(pos); pDLL;
		 pDLL = GetMainWorld()->GetListOfToolDLLBase()->GetNextElement(pos))
	{
		pDLL->fn_vLevelHasChanged();
	}
}



//#################################################################################
// EDITOR
//#################################################################################

//===========================================================================
//===========================================================================
BOOL EDT_HierarchyEditor::fn_bHasGainedFocus (void)
{
	GetInterface()->fn_vUpdateAll(E_mc_UpdateAll);

	// display Tip of the Day
	GetInterface()->fn_vDisplayTipOfDay("Hierarchy", "EDT", g_bTipFirstTime);
	g_bTipFirstTime = FALSE;

	return TRUE;
}

//===========================================================================
//===========================================================================
void EDT_HierarchyEditor::fn_vOnActivateEditor (CPA_List<CPA_BaseObject> *pParams, BOOL bBackActivated)
{
	CPA_BaseObject *pElem;
	CPA_SuperObject		*pEdObj;
	POSITION			pos;
	
	// if there is a list, select corresponding super-objects
	if (pParams)
	{
		// cancel current selection
		GetInterface()->fn_vCancelCurrentSelection(FALSE);
		// select parameters
		for (pElem = pParams->GetHeadElement(pos); pElem;
			 pElem = pParams->GetNextElement(pos))
		{
			// check if this is a super-object
			if (pElem->GetType() == C_szSuperObjectTypeName)
			{
				// if possible, select it
				pEdObj = (CPA_SuperObject *) pElem;
				if (GetInterface()->fn_bCanSelect(pEdObj) == C_Accept)
					GetInterface()->fn_vAddSelectedObject(pEdObj, FALSE);
			}
		}
	}
	// restore and update dialogs
	fn_vRestoreDialogs();
}
	
//===========================================================================
//===========================================================================
void EDT_HierarchyEditor::fn_vOnCloseEditor (void)
{
	fn_vCancelAllModes();
}


/*===========================================================================
*		Description:	cancel all modes when changing editor
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                           Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vCancelAllModes (void)
{
	// Init Mode
	m_bMultiSelectMode= FALSE;
	SetEditorMode(E_em_NoMode);
	// Init Move
	m_pOrientMove = NULL;
	m_pOrientedObject = NULL;
	m_pMouseMove = NULL;
	m_pKeyMove   = NULL;
	m_eMouseMoveMode = E_mmm_NoMouseMove;
}


/*===========================================================================
*		Description:	restore all dialogs when changing editor
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                           Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vRestoreDialogs (void)
{
	// activate editor frames
	g_oFrameGest.mfn_vActivateWindow(m_pLeftFrame);
	g_oFrameGest.mfn_vActivateWindow(m_pBottomFrame);
	// update dialogs
	GetInterface()->fn_vUpdateAll(E_mc_UpdateAll);
}

//#################################################################################
// DIALOG LIST
//#################################################################################


/*===========================================================================
*		Description:	Give all the list to the dialog
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::GetListsForDialog (CPA_DialogList *pDialog)
{
	EDT_ListByType	*pListType;
	EDT_ListByDLL	*pListDLL;
	POSITION		pos, pos1;

	if (!m_bHasCurrentWorld)
		return;

	// Hierarchy
	if (M_GetWorld()->GetRoot())
		pDialog->fn_vAddANewTree("Hierarchy", M_GetWorld()->GetRoot(), &m_oMainIconList, &m_oTreeIconList);
	// List All Types
	pDialog->fn_vAddANewList("All Types", GetInterface()->GetSortedListByType("All Types"), 
							 &m_oMainIconList, &m_oTreeIconList,
							 E_lo_Alpha, TRUE, C_lDrawState | C_lDrawIcon | C_lDrawName, TRUE);
	// Current Model
	pDialog->fn_vAddANewList("Current Model", GetInterface()->GetSortedListByType("All Types"), 
							 &m_oMainIconList, &m_oTreeIconList, E_lo_Alpha, TRUE, 
							 C_lDrawState | C_lDrawName, TRUE);
	// ListByType
	for (pListDLL = M_GetWorld()->GetListOfListByDLL()->GetHeadElement(pos); pListDLL;
		 pListDLL = M_GetWorld()->GetListOfListByDLL()->GetNextElement(pos))
	{
		for (pListType = pListDLL->m_stListOfListByType.GetHeadElement(pos1); pListType;
			 pListType = pListDLL->m_stListOfListByType.GetNextElement(pos1))
			pDialog->fn_vAddANewList(pListType->GetTypeName(), &pListType->m_stSortedList, 
									 &m_oMainIconList, &m_oTreeIconList, E_lo_Alpha, TRUE, 
									 C_lDrawState | C_lDrawName, TRUE);
	}

// Begin Silviu Simen september 1998 List of Objects in Sectors
	// initialize the lists
	fn_vBuildListOfSectors();

	CPA_List<CPA_SuperObject>* poList = GetInterface()->GetObjectListByType	(C_szSectorTypeName);
	CPA_SuperObject * pSector;

	ASSERT (poList);
	for (pSector = poList->GetHeadElement(pos); pSector; 
		 pSector = poList->GetNextElement(pos)) 
	{
		pDialog->fn_vAddANewList(pSector->GetName(), M_GetMainWorld()->m_stListObjectsInSectors.GetListOfSector(pSector),
								 &m_oMainIconList, &m_oTreeIconList, E_lo_Alpha, TRUE,
								 C_lDrawState | C_lDrawIcon | C_lDrawName, TRUE);
	}
// End Silviu Simen 01 september 1998 List of Objects in Sectors

}


/*===========================================================================
*		Description:	Give the list by default
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vInitDefaultParameters (CPA_DialogList *pDialog)
{
	pDialog->SetDefaultTypeName("Hierarchy");
	pDialog->SetDefaultTestName("No Test");
	pDialog->SetDefaultButtonState(FALSE);
}


/*===========================================================================
*		Description:	Get info for list element
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
CString EDT_HierarchyEditor::GetInfoForListItem (CPA_DialogList *pDialog, CString csListName, CPA_BaseObject *pObject)
{
	return "";
}

/*===========================================================================
*		Description:	Get icon for list element
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
int	EDT_HierarchyEditor::GetIconForListItem (CPA_DialogList *pDialog, CString csListName, CPA_BaseObject *pObject)
{
	EDT_SuperObject *pSupObj;
	
	if (fn_bIsHierarchyTree(csListName))
		return 0;
	
	pSupObj = (EDT_SuperObject *) pObject;

	return GetNumIconFromObjectType(pSupObj->GetRealTypeName());
}

/*===========================================================================
*		Description:	Get icon for list element
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
int	EDT_HierarchyEditor::GetStateForListItem (CPA_DialogList *pDialog, CString csListName, CPA_BaseObject *pObject)
{
	EDT_SuperObject *pSupObj;
	
	// find good icon
	pSupObj = (EDT_SuperObject *) pObject;
	// check state
	return ( (GetInterface()->fn_bCanSelect(pSupObj) == C_Accept) ? 1 : 2);
}

/*===========================================================================
*		Description:	Get brother for tree element
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
CPA_BaseObject * EDT_HierarchyEditor::GetTreeNodeNextChild (CPA_DialogList *pDialog, CString csListName, CPA_BaseObject *pParent, CPA_BaseObject *pCurrentChild) 
{ 
	EDT_SuperObject *pSupObj, *pChild;
	
	pSupObj = (EDT_SuperObject *) pParent;
	pChild = (EDT_SuperObject *) pCurrentChild;
	
	if (pChild)
		return pSupObj->GetSuperObjectNextChild(pChild);
	else
		return pSupObj->GetSuperObjectFirstChild();
}

/*===========================================================================
*		Description:	Get icon for tree element
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
int	EDT_HierarchyEditor::GetIconForTreeItem	(CPA_DialogList *pDialog, CString csListName, CPA_BaseObject *pObject) 
{ 
	EDT_SuperObject *pSupObj;
	
	if (!fn_bIsHierarchyTree(csListName))
		return 0;
	
	pSupObj = (EDT_SuperObject *) pObject;

	return GetNumIconFromObjectType(pSupObj->GetRealTypeName());
}

	
/*===========================================================================
*		Description:	Get icon for tree element
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
int	EDT_HierarchyEditor::GetStateForTreeItem	(CPA_DialogList *pDialog, CString csListName, CPA_BaseObject *pObject) 
{ 
	EDT_SuperObject *pSupObj;
	
	// find good icon
	pSupObj = (EDT_SuperObject *) pObject;
	// check state
	if (!pSupObj->GetSuperObjectOwner())
		return ( (GetInterface()->fn_bCanSelect(pSupObj) == C_Accept) ? 1 : 2);
	else
		return ( (GetInterface()->fn_bCanSelect(pSupObj) == C_Accept) ? 3 : 4);
}



/*===========================================================================
*		Description:	Find icon corresponding to object's type
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
int EDT_HierarchyEditor::GetNumIconFromObjectType (CString csType)
{
	// get icon
	if (csType == C_szSuperObjectTypeName)
		return 1;
	if (csType == C_szActorInstanceTypeName)
		return 2;
	if (csType == C_szCameraObjectTypeName)
		return 3;
	if (csType == C_szGeometricObjectTypeName)
		return 4;
	if (csType == C_szInstanciatedPhysicalObjectTypeName)
		return 5;
	if (csType == C_szLightTypeName)
		return 6;
	if (csType == C_szPhysicalObjectTypeName)
		return 7;
	if (csType == C_szSectorTypeName)
		return 8;
	if (csType == C_szWayPointTypeName)
		return 9;
	if ((csType == C_szZddName) ||
		(csType == C_szZdmName) ||
		(csType == C_szZdeName) ||
		(csType == C_szZdrName))
		return 10;

	// unknown
	return 0;
}

/*===========================================================================
*		Description:	Give the selection to the dialog
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
CPA_BaseObject * EDT_HierarchyEditor::GetDialogSelection (CPA_DialogList *pDialog, CString csTypeName, tdeListDrawMode eDrawMode)
{
	if (!m_bHasCurrentWorld)
		return NULL;

	if (M_GetWorld()->GetCountSelected() == 1)
		return M_GetWorld()->GetSingleSelection();
	else
		return NULL;
}


/*===========================================================================
*		Description:	Update Editor when list changes
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bOnSelChangeComboList (CPA_DialogList *pDialog, CString csTypeName)
{
	CPA_Interface	*pInterface = GetInterface();

	// link => update select mode
	if (pInterface->GetLinkMode())
	{
		// hierarchy => all types
		if (fn_bIsHierarchyTree(csTypeName))
			pInterface->SetSelectMode("All Types");
		// current model => corresponding type or all types
		else if (csTypeName == "CurrentModel")
		{
			// update select mode
			if (pInterface->GetCurrentModel())
				pInterface->SetSelectMode(GetInterface()->GetCurrentModel()->m_csName);
			else
				pInterface->SetSelectMode("All Types");
		}
		// link => same type
		else
			pInterface->SetSelectMode(csTypeName);
	}
	// dialog default handling
	return FALSE;
}


/*===========================================================================
*		Description:	Update Editor when selection changes
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bOnSelChangeListObjects (CPA_DialogList *pDialog, CString csTypeName, CPA_BaseObject *pSelectedObject, BOOL bUnselect)
{
	if (!bUnselect)
		return (!GetInterface()->fn_bSelectObject((CPA_SuperObject *)pSelectedObject, FALSE));
	else
	{
		GetInterface()->fn_vRemoveSelectedObject((CPA_SuperObject *)pSelectedObject);
		return FALSE;
	}
}

/*----------------------------------------
----------------------------------------*/
BOOL EDT_HierarchyEditor::fn_bOnDblClkListObjects (CPA_DialogList *pDialog, CString csTypeName, CPA_BaseObject *pSelectedObject)
{
	return (!GetInterface()->fn_bSelectObject((CPA_SuperObject *)pSelectedObject, TRUE));
}

/*----------------------------------------
----------------------------------------*/
BOOL EDT_HierarchyEditor::fn_bOnSelChangeHierarchyTree (CPA_DialogList *pDialog, CString csTypeName, CPA_BaseObject *pSelectedObject, CPA_BaseObject *pSelectedParent)
{
	return (!GetInterface()->fn_bSelectObject((CPA_SuperObject *)pSelectedObject, FALSE));
}

/*----------------------------------------
----------------------------------------*/
BOOL EDT_HierarchyEditor::fn_bOnDblClkHierarchyTree (CPA_DialogList *pDialog, CString csTypeName, CPA_BaseObject *pSelectedObject, CPA_BaseObject *pSelectedParent)
{
	return (!GetInterface()->fn_bSelectObject((CPA_SuperObject *)pSelectedObject, TRUE));
}


/*===========================================================================
*		Description:	Key Down in cpa_dialoglist
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bOnKeyDownInDialog (CPA_DialogList *pDialog, CString csTypeName, tdeListDrawMode eDraw, 
										CPA_BaseObject *pSelectedObject, UINT nChar, UINT nRepCnt, UINT nFlags)
{
	EDT_SuperObject *pSupObj;
	CPA_SuperObject *pEdObj;
	
	switch (m_p_oDevKeyboard->mfn_uwKeyToAction(nChar))
	{
		// delete selected object
		case KA_ID_DEL :
			if (pSelectedObject)
			{
				pEdObj = (CPA_SuperObject *) pSelectedObject;
				pSupObj = (EDT_SuperObject *) pEdObj;
				// if allowed, delete it
				if (fn_bCanDelete(pSupObj))
					M_GetEditManager()->AskFor(new EDT_ModifDelete (this, pSupObj, GetInterface()->GetSelectMode()));
					else
					m_eModifCanceled = E_cm_CancelDelete;
				fn_vDisplayCancelMessage(m_eModifCanceled);
			}
			return TRUE;
	}

	return FALSE;
}

/*===========================================================================
*		Description:	Key Up in cpa_dialoglist
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bOnKeyUpInDialog (CPA_DialogList *pDialog, CString csTypeName, tdeListDrawMode eDraw,
									  CPA_BaseObject *pSelectedObject, UINT nChar, UINT nRepCnt, UINT nFlags)
{
	return FALSE;
}

/*===========================================================================
*		Description:	Drag and Drop in Hierarchy Tree
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bCanDragItemInHierarchyTree	(CPA_DialogList *pDialog, CString csTypeName, CPA_BaseObject *pObjectToDrag)
{
	CPA_SuperObject *pSupObj = (CPA_SuperObject *) pObjectToDrag;
	
	if (fn_bCanChangeAllParents())
	{
		GetInterface()->fn_vSetLocalColor(pSupObj->GetSuperObjectFather(), E_lm_ShowParent);
		GetInterface()->fn_vUpdateAll(E_mc_JustDraw);
		return TRUE;
	}
	else
		return FALSE;
}

/*===========================================================================
*		Description:	Add Camera entries to popup
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bAddEntriesToTreePopup (CPA_DialogList *pDialog, CString csListName, CMenu *pMenu, UINT uiCustomEntriesStart)
{
	DEV_ViewPort3D	  *pCurViewport;
	CPA_DLLBase		  *p_oCameraInterface;

	// get camera interface
	pCurViewport = M_GetViewPort3d();
	p_oCameraInterface = pCurViewport->GetCameraInterface();	
	
	return p_oCameraInterface->fn_bAddEntriesToTreePopup(pDialog, csListName, pMenu, uiCustomEntriesStart);
}

/*===========================================================================
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bAddEntriesToListPopup (CPA_DialogList *pDialog, CString csListName, CMenu *pMenu, UINT uiCustomEntriesStart)
{
	DEV_ViewPort3D	  *pCurViewport;
	CPA_DLLBase		  *p_oCameraInterface;

	// get camera interface
	pCurViewport = M_GetViewPort3d();
	p_oCameraInterface = pCurViewport->GetCameraInterface();	
	
	return p_oCameraInterface->fn_bAddEntriesToListPopup(pDialog, csListName, pMenu, uiCustomEntriesStart);
}

/*===========================================================================
*=========================================================================*/
void EDT_HierarchyEditor::fn_vOnCommandInTreePopup (CPA_DialogList *pDialog, CString csListName, UINT uiCustomEntry)
{
	DEV_ViewPort3D	  *pCurViewport;
	CPA_DLLBase		  *p_oCameraInterface;

	// get camera interface
	pCurViewport = M_GetViewPort3d();
	p_oCameraInterface = pCurViewport->GetCameraInterface();	
	
	p_oCameraInterface->fn_vOnCommandInTreePopup(pDialog, csListName, uiCustomEntry);
}

/*===========================================================================
*=========================================================================*/
void EDT_HierarchyEditor::fn_vOnCommandInListPopup (CPA_DialogList *pDialog, CString csListName, UINT uiCustomEntry)
{
	DEV_ViewPort3D	  *pCurViewport;
	CPA_DLLBase		  *p_oCameraInterface;

	// get camera interface
	pCurViewport = M_GetViewPort3d();
	p_oCameraInterface = pCurViewport->GetCameraInterface();	
	
	p_oCameraInterface->fn_vOnCommandInListPopup(pDialog, csListName, uiCustomEntry);
}

/*----------------------------------------
----------------------------------------*/
BOOL EDT_HierarchyEditor::fn_bCanDropItemInHierarchyTree	(CPA_DialogList *pDialog, CString csTypeName, CPA_BaseObject *pObjectToDrop, CPA_BaseObject *pTarget)
{
	return fn_bCanBeParentForAll((CPA_SuperObject *) pTarget);
}

/*----------------------------------------
----------------------------------------*/
BOOL EDT_HierarchyEditor::fn_bOnDragDropInHierarchyTree	(CPA_DialogList *pDialog, CString csTypeName, CPA_BaseObject *pObject, CPA_BaseObject *pTarget)
{
	CPA_SuperObject *pSupObj;
	
	pSupObj = (CPA_SuperObject *) pTarget;
	
	// create modif
	M_GetEditManager()->AskFor (new EDT_ModifParent
		(this, M_GetWorld()->GetListOfListByDLL(), (EDT_SuperObject *) pSupObj, GetInterface()->GetSelectMode()));
	// default handling
	return FALSE;
}

/*===========================================================================
*		Description:	Update Button Test
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bOnButtonTest (CPA_DialogList *pDialog, CString csCurrentType, tdeListDrawMode eMode)
{
	CPA_Interface *pInterface = GetInterface();

	// current model => nothing
	if (csCurrentType == "Current Model")
		return FALSE;

	// otherwise => change link mode
	pInterface->SetLinkMode(!pInterface->GetLinkMode());
	fn_vSetANewTest(pDialog, csCurrentType);
	// update interface
	if (pInterface->GetLinkMode())
		fn_bOnSelChangeComboList(NULL, csCurrentType);
	else
		pInterface->fn_vOnChangeLinkMode();

	return FALSE;
}



/*===========================================================================
*		Description:	Test function
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bTestFunction (CString csCurrentType, CString csTestName, CPA_BaseObject *pElem)
{
	CPA_SuperObject		*pEdObj;

	// current model =>  only instances of the model
	if ((csTestName.Left(7)) == "Model =")
	{
		pEdObj = (CPA_SuperObject *)pElem;
		if ((GetInterface()->GetCurrentModel())&&(pEdObj->GetModelName() == GetInterface()->GetCurrentModel()->m_csName))
			return TRUE;
		else
			return FALSE;
	}

	// other => no test
	return TRUE;
}


/*===========================================================================
*		Description:	set the test corresponding to the current list
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vSetANewTest (CPA_DialogList *pDialog, CString csCurrentType)
{
	CString				csNewTest;
	BOOL				bCustomTest = FALSE;

	// Current Model => set corresponding name and test
	if (csCurrentType == "Current Model")
	{
		if (GetInterface()->GetCurrentModel())
			csNewTest.Format("Model = %s", GetInterface()->GetCurrentModel()->m_csName);
		else
			csNewTest = "Model = NULL";
		pDialog->fn_vInitButtonTest(csNewTest, FALSE, TRUE);
		return;
	}

	// Otherwise set link test
	else
	{
		if (GetInterface()->GetLinkMode())
			pDialog->fn_vInitButtonTest("Linked Selection", TRUE, FALSE);
		else
			pDialog->fn_vInitButtonTest("Free Selection", TRUE, FALSE);
		return; 
	}
}


/*===========================================================================
*		Description:	Test if dialog list is a hierarchy tree
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bIsHierarchyTree (CString oCurrentType)
{
	// global hierarchy
	if (oCurrentType == "Hierarchy")
		return TRUE;
	// static hierarchy
	if (oCurrentType == "Static")
		return TRUE;
	// dynamic hierarchy
	if (oCurrentType == "Dynamic")
		return TRUE;

	// not a hierarchy
	return FALSE;
}

/*===========================================================================
*		Description:	Test if dialog list is a hierarchy tree
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vUpdateDialogList (CString csMode)
{
	if (!m_pDialogList)
		return;
	
	// update current model
	if (csMode.IsEmpty())
	{
		if (m_pDialogList->GetCurrentType() == "Current Model")
		{
			fn_vSetANewTest(m_pDialogList, "Current Model");
			m_pDialogList->fn_vUpdateSelection(E_lrm_ReinitList);
			GetInterface()->fn_vUpdateLink("Current Model");
		}
	}

	else if (m_pDialogList->GetCurrentType() != csMode)
	{
		m_pDialogList->SetCurrentType(csMode);
		fn_vSetANewTest(m_pDialogList, csMode);
	}
}


//#################################################################################
// REBUILD HIERARCHY
//#################################################################################

/*===========================================================================
*		Description:	Load editor infos corresponding to engine current map
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:     Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bLoadEditorMap (void)
{
	HIE_tdxHandleToSuperObject	hRoot;
	CPA_SuperObject				*pRoot;
	CPA_Interface				*pInterface = GetInterface();
	CString						csLevels;
	BOOL						bMustLoad;

	// check if load is necessary
	bMustLoad = ((!M_GetEditorRoot()) || (M_GetEditorRoot()->GetStruct() != M_GetEngineRoot()));
	
	// init parameters
	if (bMustLoad)	
	{
		// init Super-Object Path
		csLevels = fn_szGetLevelsDataPath();
		m_csSOReferencePath = csLevels + "\\";
		//GetReferencePath("Super-Object Reference Path");
		// for rename during loading
		pInterface->SetLoadingWorld(TRUE);
		pInterface->SetNbObjectsRenamed(0);
		// update frame
		g_oBaseFrame.mfnv_UpdateTitle("Loading Editor datas...");
		// send message
		fn_vSendMessageChangeLevel();
		// update list
		m_pDialogList->fn_vInitAllLists();
		// update modifs
		if (m_pListOfTempModifs)
		{
			delete m_pListOfTempModifs;
			m_pListOfTempModifs = NULL;
		}
		// load editor world
		hRoot = M_GetEngineRoot();
		pRoot = m_pSpecificEditor->fn_pInitEditorMap(hRoot);
		M_GetWorld()->fn_vSetRoot(pRoot);
		// send message
		fn_vSendMessageLevelChanged();
		pInterface->SetLoadingWorld(FALSE);
		// for objects renamed during loading
		if (pInterface->GetNbObjectsRenamed() > 0)
		{
			m_csLoadingMessage.Format("%ld object(s) were renamed : your changes will not be saved", GetInterface()->GetNbObjectsRenamed());
			m_iLoadingStatus = C_STATUS_ERROR;
			g_oNameManager.fn_vWriteNameConflicts();
		}
		else if (m_lNbUnknown)
		{
			m_csLoadingMessage.Format("%ld object(s) were created by default", m_lNbUnknown);
			m_iLoadingStatus = C_STATUS_WARNING;
		}
		else
		{
			m_csLoadingMessage = "Editor Hierarchy Updated";
			m_iLoadingStatus = C_STATUS_NORMAL;
		}
	}
	// update frame
	pInterface->GetSpecificInterface()->fn_vSetFrameTitle();
	return (bMustLoad);
}


/*===========================================================================
*		Description:	Build Editor Hierarchy from Engine Hierarchy.
*						(recursive function)
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:     Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vReinitEditorMap (BOOL bReinitLoad)
{
	CPA_Interface	*pInterface = GetInterface();

	// if this is a reinitialisation, raz.
	if (bReinitLoad)
	{
		m_lNbUnknown = 0;
		// Update the Hierarchy
		M_GetMainWnd()->UpdateStatus("Updating Editor Hierarchy", C_STATUSPANE_INFOS, C_STATUS_NORMAL);
		fn_vBuildEditorHierarchy(M_GetEditorRoot(), M_GetEngineRoot());
		fn_vDoDialogUpdate();
		// Reinit the lists
		M_GetWorld()->fn_vReinitListObjects();
		M_GetWorld()->fn_vFillListObjects(M_GetEditorRoot());
		M_GetWorld()->fn_vReinitSortedList();
		// initialize the lists
		//fn_vBuildListOfSectors();
	}
	m_stListHierarchy.RemoveAll();

	// update specific editor
	pInterface->GetSpecificInterface()->fn_vSpecificUpdate();
	pInterface->GetSpecificInterface()->fn_vInitCurrentSector();
	// update lights
	M_GetMainApp()->fn_vUpdateDynamicLights();

	// update all dialogs
	pInterface->GetDialogInsert()->fn_vInitComboType();
	m_pDialogList->fn_vReinitDialog();
	m_pDialogEdit->fn_vUpdateDialog();
	m_pDialogSelect->fn_vUpdateDialog();

	// dialog bar
	pInterface->fn_vInitSelectMode();

	// Update the drawing (hierarchy changed !)
	pInterface->fn_vSetLocalColor(M_GetWorld()->GetRoot(), E_lm_ShowNormal);
	pInterface->fn_vUpdateAll(E_mc_UpdateDialog);
	// update frame
	M_GetMainWnd()->UpdateStatus((char*)(LPCSTR)m_csLoadingMessage, C_STATUSPANE_INFOS, m_iLoadingStatus);
	if (pInterface->GetNbObjectsRenamed() > 0)
		MessageBox (AfxGetMainWnd()->m_hWnd, "Objects were renamed during loading : \nyour changes in all editors cannot be saved", "PROBLEM !", MB_OK|MB_ICONEXCLAMATION);
	// set focus to 3D View
	M_GetMainDevice()->SetFocusDevice(0);	

}

// Begin Silviu Simen 01 september 1998 List of Objects in Sectors

void EDT_HierarchyEditor::fn_vBuildListOfSectors(void) 
{
	if (GetInterface()->GetSpecificInterface()->fn_bHasValidWorld(FALSE))
	{
		M_GetMainWorld()->m_stListObjectsInSectors.fn_vCleanAllListsOfSectors();
		fn_vDoBuildListOfSectors(M_GetEditorRoot(), M_GetEngineRoot());

	}
}

void EDT_HierarchyEditor::fn_vDoBuildListOfSectors(CPA_SuperObject *pEdObj, HIE_tdxHandleToSuperObject hSupObj)
{
	HIE_tdxHandleToSuperObject	hChild;
	HIE_tdxHandleToSuperObject	hBrother;
	CPA_SuperObject				*pEdChild;
	// CString objectType;
	unsigned long				ulType;

	MTH3D_tdstVector	stObjectPosition;
	CPA_SuperObject *	pSector;

	if (!pEdObj)
		return;

	// save the childs of current SuperObject
	hChild = HIE_fn_hGetSuperObjectFirstChild(hSupObj);
	while (hChild)
	{
		pEdChild = GetEditorObject(hChild);
		stObjectPosition = HIE_fn_hGetSuperObjectMatrix(pEdChild->GetStruct())->stTranslationVector;
		pSector = GetInterface()->GetSpecificInterface()->GetCurrentSectorFromPos(&stObjectPosition);

		// objectType = pEdChild ->GetType();
		ulType = HIE_fn_ulGetSuperObjectType(pEdChild->GetStruct());
		switch (ulType) 
		{
			case HIE_C_ulSuperObject :
			case HIE_C_ulSector:
				break;
			default:
				M_GetMainWorld()->m_stListObjectsInSectors.AddElement(pEdChild, pSector);
		}
		hBrother = HIE_fn_hGetSuperObjectNextBrother(hChild);
		fn_vDoBuildListOfSectors(pEdChild, hChild);
		hChild = hBrother;
	}
}
// End Silviu Simen 01 september 1998 List of Objects in Sectors



/*===========================================================================
*		Description:	Build Editor Hierarchy from Engine Hierarchy.
*						(recursive function)
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:     Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vBuildEditorHierarchy (CPA_SuperObject *pEdObj, HIE_tdxHandleToSuperObject hSupObj)
{
	HIE_tdxHandleToSuperObject	hChild;
	HIE_tdxHandleToSuperObject	hBrother;
	CPA_ObjectDLLBase			*p_oDLL;
	CPA_SuperObject				*pEdChild;
//	POSITION					pos;
	CString						csName;

	if (!pEdObj)
		return;

	// save the childs of current SuperObject
	hChild = HIE_fn_hGetSuperObjectFirstChild(hSupObj);
	// isolate current Object to avoid interferences
	pEdObj->RemoveAllChilds(FALSE);
	// construct the child's level
	while (hChild)
	{
		// find the corresponding Editable Object
		pEdChild = GetEditorObject(hChild);
		// new object => create editor instance
		if (!pEdChild)
		{
			// try to find super object in link-table
			pEdChild = GetSuperObjectFromLinkTable(hChild, (EDT_SuperObject *)pEdObj);
			// find super-objet type
			p_oDLL = GetMainWorld()->GetObjectDLLWithType(HIE_fn_ulGetSuperObjectType(hChild));
			if (p_oDLL)
			{
				if (pEdChild)
					p_oDLL->fn_vBuildNewEditorInstance(pEdChild, hChild);
				else
					pEdChild = p_oDLL->GetNewEditorInstance(hChild);
			}
			// no DLL can build it => default SO
			if (!pEdChild)
			{
				csName.Format("SO_Unknown%ld", m_lNbUnknown++);
				pEdChild = GetNewSuperObject(hChild, E_ss_NoSave, C_NoType, csName, "");
			}
			// init hierarchy parameters
			m_pSpecificEditor->fn_vInitTypeSO((EDT_SuperObject *) pEdChild, (EDT_SuperObject *) pEdObj);
		}
		// object already present => update
		else
		{
			p_oDLL = pEdChild->GetObjectDLL();
			if ((p_oDLL)&&(!pEdChild->GetSuperObjectOwner()))
				p_oDLL->fn_vUpdateEditorInstance(pEdChild, hChild);
		}
		// update lists (for protected childs)
		fn_vUpdateHierarchyList(pEdChild);
		// Editor Object MUST exist
		ASSERT(pEdChild);
		// save the next brother
		hBrother = HIE_fn_hGetSuperObjectNextBrother(hChild);
		// next level of the hierarchy
		fn_vBuildEditorHierarchy(pEdChild, hChild);
		// add the Editor Object in the hierarchy
		pEdChild->SetList(NULL, FALSE);
		pEdObj->AddANewChild(pEdChild, FALSE);
		// next Child
		hChild = hBrother;
	}
}


/*===========================================================================
*		Description:	destroy editor super object
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:     Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vUpdateHierarchyList (CPA_SuperObject *pEdObj)
{
}

/*===========================================================================
*		Description:	destroy editor super object
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:     Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vDestroySuperObject (CPA_SuperObject *pEdObj, BOOL bDestroyEngineStruct, BOOL bUpdateLists)
{
	EDT_ListByDLL *pListDLL;
	
	if (!pEdObj)
		return;

	// temporary => when engine struct is no more valid 
	if (!bDestroyEngineStruct)
		((EDT_SuperObject *) pEdObj)->SetEngineStruct(HIE_fn_hCreateSuperObject());

	// update sorted lists
	if (bUpdateLists)
	{
		// update corresponding list
		pListDLL = M_GetWorld()->GetListFromObject(pEdObj);
		if (pListDLL)
			pListDLL->fn_vUpdateListObject(pEdObj, E_lum_Delete);
		// update list all DLLs
		M_GetWorld()->GetListAllDLLs()->fn_vUpdateListObject(pEdObj, E_lum_Delete);
	}

	// delete super object
	delete pEdObj;
}


//#################################################################################
// DIALOGS
//#################################################################################

/*===========================================================================
*		Description:	Update all dialogs
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                           Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vUpdateEditor (tdeModeChange eMode)
{
	if (!m_bHasCurrentWorld)
		return;

	switch (eMode)
	{
		case E_mc_JustDraw:
			break;

		case E_mc_UpdateSelection:
			// update dialog list
			m_pDialogList->fn_vUpdateSelection(E_lrm_ChangeSelection);
			// update edit dialog
			m_pDialogEdit->fn_vUpdateDialog();
			m_pDialogSelect->fn_vUpdateDialog();
			break;

		case E_mc_UpdateAll:
		case E_mc_UpdateDialog:
			// update dialog list
			fn_vSetANewTest(m_pDialogList, m_pDialogList->GetCurrentType());
			m_pDialogList->fn_vUpdateSelection(E_lrm_ReinitList);
			// update edit dialog
			m_pDialogEdit->fn_vUpdateDialog();
			m_pDialogSelect->fn_vUpdateDialog();
			break;

		default:
			break;
	}
}


/*===========================================================================
*		Description:	Check if Editable Objects have been destroyed, and
*						ask user for confirmation
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:     Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vDoDialogUpdate (void)
{
}

/*===========================================================================
*		Description:	update link between dialoglist and select mode
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:     Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vUpdateLink (CString csCurrentMode)
{
	EDT_ListByType	*pListType = NULL;
	CComboBox		*pCombo;
	EDT_Model		*pModel;
	CString			csCurrentType;
	int				iInd;
	
	// get parameters
	csCurrentType = m_pDialogList->GetCurrentType();
	pCombo = GetInterface()->GetComboSelectMode();
	pModel = GetInterface()->GetCurrentModel();
	// hierarchy => all types
	if (fn_bIsHierarchyTree(csCurrentType))
	{
		iInd = pCombo->FindStringExact(-1, "All Types");
		pCombo->SetCurSel(iInd);
		pCombo->EnableWindow(FALSE);
	}
	// current model => corresponding type or all types
	else if (csCurrentType == "Current Model")
	{
		if (pModel)
			pListType = GetInterface()->GetListWithTypeName(pModel->m_csTypeName);
		if (pListType)
			iInd = pCombo->FindStringExact(-1, pListType->GetTypeName());
		else
			iInd = pCombo->FindStringExact(-1, "All Types");
		pCombo->SetCurSel(iInd);
		pCombo->EnableWindow(FALSE);
	}
	// link => same type
	else 
	{
		if (csCurrentType != csCurrentMode)
			fn_vUpdateDialogList(csCurrentMode);
		pCombo->EnableWindow(TRUE);
	}
}

/*===========================================================================
*		Description:	update dialoglist when current model changes
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:     Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vUpdateModel (void)
{
	fn_vUpdateDialogList("");
}

//#################################################################################
// COPY / PASTE
//#################################################################################

/*===========================================================================
*		Description:	Init modif for copy
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:        Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vInitModifCopy (BOOL bInstanceAlone)
{
	if (fn_bCanCopyAllObjects())
	{
		SetEditorMode((bInstanceAlone) ? E_em_CopyAloneMode : E_em_CopyAllMode);
		fn_vInitListToCopy(M_GetWorld()->GetListSelected(), bInstanceAlone);
		m_lNbCopy = 0;
	}
	else
		m_eModifCanceled = E_cm_CancelCopy;
	fn_vDisplayCancelMessage(m_eModifCanceled);
}


/*===========================================================================
*		Description:	Init modif for paste
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:        Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vInitModifPaste (tdePasteMode eMode, EDT_SuperObject *pNewParent, MTH3D_tdstVector *pNewPosition)
{
	if (fn_bCanPasteAllObjects(eMode, pNewParent, pNewPosition))
		M_GetEditManager()->AskFor(new EDT_ModifPaste
			(this, &m_stListToCopy, GetInterface()->GetSelectMode(), ++m_lNbCopy));
	else
	{
		m_eModifCanceled = E_cm_CancelPaste;
		fn_vCancelAllModes();
	}
	fn_vDisplayCancelMessage(m_eModifCanceled);
}

/*===========================================================================
*		Description:	Init the lists of objects to copy
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:        Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vInitListToCopy (CPA_List<CPA_SuperObject> *pListObjects, BOOL bInstanceAlone)
{
	CPA_SuperObject *pElem;
	EDT_SuperObject *pNewElem;
	POSITION		pos;

	// reinit the list
	while (!m_stListToCopy.IsEmpty())
		delete (m_stListToCopy.RemoveHead());
	// fill the list with selected objects
	for (pElem = pListObjects->GetHeadElement(pos); pElem;
		 pElem = pListObjects->GetNextElement(pos))
	{
		// create new elem
		pNewElem = GetACopy((EDT_SuperObject *)pElem, bInstanceAlone, TRUE);
		//CPA2 Stegaru Cristian 98-03
		ASSERT (pNewElem);
		pNewElem->mfn_vSetInitialSPOName (((EDT_SuperObject *)pElem)->GetName ());
		//End CPA2 Stegaru Cristian 98-03
		// notify unsave (not in hierarchy)
		UnSaveAllElement(pNewElem);
		pNewElem->fn_vUpdateValidity(FALSE);
		m_stListToCopy.AddTail(new EDT_SaveParents(pNewElem, (EDT_SuperObject *) pElem->GetSuperObjectFather(), NULL));
	}
}

/*===========================================================================
*		Description:	Init the lists of objects to copy
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:        Author:
*=========================================================================*/
void EDT_HierarchyEditor::UnSaveAllElement (EDT_SuperObject *pSupObj)
{
	CPA_SuperObject *pChild;
	CPA_BaseObject	*pObject;

	// unsave superobject
	pSupObj->fn_vNotifyUnSave();

	// if necessary, unsave object
	pObject = pSupObj->GetObject();
	if ((pObject)&&(pObject->fn_bCanBeSaved()))
		((CPA_SaveObject *)pObject)->fn_vNotifyUnSave();

	// unsave all childs
	for (pChild = pSupObj->GetSuperObjectFirstChild(); pChild;
		 pChild = pSupObj->GetSuperObjectNextChild(pChild))
		UnSaveAllElement((EDT_SuperObject *)pChild);
}


/*===========================================================================
*		Description:	Init parents for paste.
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:        Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bInitParentAndPos (tdePasteMode eMode, EDT_SuperObject *pNewParent, MTH3D_tdstVector *pNewPosition)
{
	EDT_SuperObject		*pEdObj;
	EDT_SaveParents		*pElem;
	DEV_ViewPort3D		*pCurViewport;
	MTH3D_tdstVector	stRefVector;
	MTH3D_tdstVector	stTranslation;
	POS_tdstCompletePosition	stRefMatrix,stCamMatrix;
	POS_tdstCompletePosition	*pRefMatrix;
	POSITION			pos;
	
	MTH3D_tdstVector		stVect;
	POS_tdxHandleToPosition	hMatrix;

	POS_fn_vSetIdentityMatrix(&stRefMatrix);
	POS_fn_vSetIdentityMatrix(&stCamMatrix);
	// init vector for position
	pCurViewport = M_GetViewPort3d();
	MTH3D_M_vSetVectorElements(&stRefVector, (GLI_tdxValue)0.02, (GLI_tdxValue)0.02, (GLI_tdxValue)0.0);
	// correct it according to camera
	GLI_xGetCameraMatrix(pCurViewport->GetEngineCamera(),&stCamMatrix);
	POS_fn_vInvertMatrix(&stRefMatrix,&stCamMatrix);
	MTH3D_M_vNullVector(&stVect);
	POS_fn_vSetTranslationVector(&stRefMatrix,&stVect);
	POS_fn_vMulMatrixVertex(&stRefVector, &stRefMatrix, &stRefVector); 
		
	// check all objects in the list
	for (pElem = m_stListToCopy.GetHeadElement(pos); pElem;
		 pElem = m_stListToCopy.GetNextElement(pos))
	{
		// init parameters
		pEdObj = (EDT_SuperObject *) pElem->m_pChild;
		// init global position
		hMatrix = HIE_fn_hGetSuperObjectGlobalMatrix(pEdObj->GetStruct());
		POS_fn_vGetTranslationVector(hMatrix,&stTranslation);
		MTH3D_M_vAddVector(&stTranslation, &stTranslation, &stRefVector);
		POS_fn_vSetTranslationVector(hMatrix,&stTranslation);
		// default parent 
		if (eMode == E_pm_PasteDefault)
			pNewParent = m_pSpecificEditor->GetDefaultParentForPaste(pEdObj);
		// same parent
		else if (eMode == E_pm_PasteSame)
		{
			pNewParent = (EDT_SuperObject *) pElem->m_pInitialParent;
			// if parent was removed from hierarchy, get default one
			if (!pNewParent->fn_bIsUnderObject(M_GetWorld()->GetRoot()))
				pNewParent = m_pSpecificEditor->GetDefaultParentForPaste(pEdObj);
		}
		// chosen parent
		else if ((eMode == E_pm_PasteChoice)&&(pNewParent))
		{
			// paste close to parent
			pRefMatrix = HIE_fn_hGetSuperObjectGlobalMatrix(pNewParent->GetStruct());
			POS_fn_vGetTranslationVector(pRefMatrix,&stVect);
			MTH3D_M_vAddVector(&stTranslation, &stVect, &stRefVector);
			POS_fn_vSetTranslationVector(hMatrix,&stTranslation);
		}
		// chosen position
		else if ((eMode == E_pm_PasteChoice)&&(pNewPosition))
		{
			// init position
			MTH3D_M_vCopyVector(&stTranslation, pNewPosition);
			POS_fn_vSetTranslationVector(hMatrix,&stTranslation);
			// get corresponding default parent
			pNewParent = m_pSpecificEditor->GetDefaultParentForPaste(pEdObj);
		}
		// there must be a parent
		if ((!pNewParent)||(pNewParent->fn_bIsUnderObject(pEdObj)))
			return FALSE;
		// ask specific editor
		if (!m_pSpecificEditor->fn_bCanBeParent(pNewParent, pEdObj))
			return FALSE;
		// parent must be valid
		if ((!pEdObj->fn_bAcceptAsParent(pNewParent))||(!pNewParent->fn_bAcceptAsChild(pEdObj)))
			return FALSE;
		// init parent
		pElem->m_pFinalParent = pNewParent;
	}

	// all parents were found
	return TRUE;
}


/*===========================================================================
*		Description:	check permission for paste.
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:        Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bCanPasteAllObjects (tdePasteMode eMode, CPA_SuperObject *pNewParent, MTH3D_tdstVector *pNewPosition)
{
	// check parents
	if (!fn_bInitParentAndPos(eMode, (EDT_SuperObject *)pNewParent, pNewPosition))
	{
		m_csMessage = "There is no valid parent to paste these objects";
		return FALSE;
	}
	// check permissions with DLLs ??
	return TRUE;
}



//**************************************************************************************
//Begin Mircea Dunka 31 Aug 1998 - DialogBar interface
void EDT_HierarchyEditor::fn_vDefineDlgBarBtnIcon (tde_DlgBarCategory wCategory, tds_DlgBarBtn *_pDlgBarBtn)
{
	if(wCategory == C_DlgBarCategoryEditor)
	{
		_pDlgBarBtn->hIcon = ::LoadIcon((HINSTANCE)(GetDLLIdentity()->hModule), MAKEINTRESOURCE(IDI_EDT_DLGBAR_ICON));

        CString oCst;
		oCst = "Hierarchy";
        if( (M_GetMainApp()) && (M_GetMainApp()->mp_oAppKeyboard) )
        {
            oCst += "  (";
			oCst += M_GetMainApp()->mp_oAppKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Activate Hierarchy Editor"));
			oCst += ")";
        }
		strcpy(_pDlgBarBtn->szToolTip, (char*)(LPCTSTR)oCst);
		_pDlgBarBtn->uID = (UINT)this;
	}
}
//end Mircea Dunka 31 Aug 1998

//#################################################################################
// SUBMENUS AND POPUPMENUS
//#################################################################################

/*===========================================================================
*		Description:	add entries to given submenu.
*		Creation date:
*		Author:			Marc Trabucato
*---------------------------------------------------------------------------
*		Revision date:       Author: Shaitan
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bDefineSubMenu(EDT_SubMenu *p_oEDTSubMenu)
{
	CString		oCst;
	BOOL		bEnable;
	
	// submenu "Edit"
	if (p_oEDTSubMenu->GetSubMenuType() == C_SubMenuEdit)
    {
		// Full selection
		p_oEDTSubMenu->AddASeparator();
		// copy instance
//CPA2 Corneliu Babiuc 13-05-98
//		oCst = "Copy Instance Alone";
		oCst = "Copy instance alone";
		oCst += "\t";
//		oCst += m_p_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Copy Instance Alone"));
		oCst += m_p_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Copy instance alone"));
//END CPA2 Corneliu Babiuc 13-05-98
		bEnable = ((M_GetWorld()->GetCountSelected() == 1)&&(fn_bCanCopyAllObjects()));
		p_oEDTSubMenu->AddAnEntry(this, (char*)(LPCTSTR)oCst, C_ui_CopyInstanceAction, FALSE, bEnable);
        // copy selection
//CPA2 Corneliu Babiuc 13-05-98
//		oCst = "Copy selected Objects";
		oCst = "Copy instance with Branch";
		oCst += "\t";
//		oCst += m_p_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Copy selected Objects"));
		oCst += m_p_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("copy instance with Branch"));
//END CPA2 Corneliu Babiuc 13-05-98
		bEnable = ((M_GetWorld()->GetCountSelected() > 0)&&(fn_bCanCopyAllObjects()));
		p_oEDTSubMenu->AddAnEntry(this, (char*)(LPCTSTR)oCst, C_ui_CopyObjectAction, FALSE, bEnable);
        // paste (same parent)
		oCst = "Paste under Same parent";
		oCst += "\t";
		oCst += m_p_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("paste under same parent"));
		bEnable = (m_stListToCopy.GetCount() && fn_bCanPasteAllObjects(E_pm_PasteSame));
		p_oEDTSubMenu->AddAnEntry(this, (char*)(LPCTSTR)oCst, C_ui_PasteSameAction, FALSE, bEnable);
        // paste (default parent)
		oCst = "Paste under Default parent";
		oCst += "\t";
		oCst += m_p_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("paste under Default parent"));
		bEnable = (m_stListToCopy.GetCount() && fn_bCanPasteAllObjects(E_pm_PasteDefault));
		p_oEDTSubMenu->AddAnEntry(this, (char*)(LPCTSTR)oCst, C_ui_PasteDefaultAction, FALSE, bEnable);		
		// RAZ message
		m_csMessage.Empty();
		// message processed
        return TRUE;
	}

	// submenu "Editor"
	else if (p_oEDTSubMenu->GetSubMenuType() == C_SubMenuEditor)
    {
        // build text
		oCst = "Hierarchy";
		oCst += "\t";
		oCst += M_GetMainApp()->mp_oAppKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Activate Hierarchy Editor"));
		// open or close editor
		p_oEDTSubMenu->AddAnEntry(this, (char*)(LPCTSTR)oCst, C_ui_EditorAction, fn_bIsCurrentEditor(), !fn_bIsCurrentEditor());
		return TRUE;
	}
	
	// submenu "Preference"
	else if (p_oEDTSubMenu->GetSubMenuType() == C_SubMenuPreference)
    {
   		// preferences
		p_oEDTSubMenu->AddAnEntry(this, "User Mode (Next Session)", C_ui_SaveStatusAction, FALSE, TRUE);
		p_oEDTSubMenu->AddAnEntry(this, "Save User Identity", C_ui_SavePrefixAction, FALSE, TRUE);
		p_oEDTSubMenu->AddAnEntry(this, "Save Authorized Modifs", C_ui_SavePermissions, FALSE, TRUE);
		p_oEDTSubMenu->AddAnEntry(this, "Save Prohibited Modifs", C_ui_SaveInterdictions, FALSE, TRUE);
		p_oEDTSubMenu->AddAnEntry(this, "Save Dialogs Dimensions", C_ui_SaveDialogsAction, FALSE, TRUE);
		return TRUE;
	}
	
	// no entry
	return FALSE;
}

/*===========================================================================
*		Description:	execute action according submenu entry.
*		Creation date:
*		Author:			Marc Trabucato
*---------------------------------------------------------------------------
*		Revision date:       Author: Shaitan
*=========================================================================*/
void EDT_HierarchyEditor::_OnSubMenuCommand(EDT_SubMenu *p_oEDTSubMenu, UINT uiMsgID)
{
    // Submenu "Edit"
	if (p_oEDTSubMenu->GetSubMenuType() == C_SubMenuEdit)
    {
        switch (uiMsgID)
        {
			// copy instance alone
            case C_ui_CopyInstanceAction:
 				fn_vInitListToCopy(M_GetWorld()->GetListSelected(), TRUE);
				m_lNbCopy = 0;
               break;
            // copy objects and all childs
            case C_ui_CopyObjectAction:
  				fn_vInitListToCopy(M_GetWorld()->GetListSelected(), FALSE);
				m_lNbCopy = 0;
              break;
 
			// paste under same parent
            case C_ui_PasteSameAction:
 				fn_vInitModifPaste (E_pm_PasteSame);
               break;
            // paste under default parent
            case C_ui_PasteDefaultAction:
 				fn_vInitModifPaste (E_pm_PasteDefault);
              break;
       }
		// specific action
		if ((uiMsgID >= C_ui_DisplaySpecificAction)
		  &&(uiMsgID < C_ui_DisplaySpecificAction + (unsigned int) m_lNbSpecificActions))
			m_pSpecificEditor->fn_vOnSubmenuCommand(uiMsgID - C_ui_DisplaySpecificAction);
    }
	 
	// SubMenu "Editor"
	else if (p_oEDTSubMenu->GetSubMenuType() == C_SubMenuEditor)
    {
		// if possible, activate hierarchy editor
		if ((uiMsgID == C_ui_EditorAction)&&(!fn_bIsCurrentEditor()))
			GetMainWorld()->fn_bActivateEditor(this, NULL);
	}

	// SubMenu "Preferences"
	else if (p_oEDTSubMenu->GetSubMenuType() == C_SubMenuPreference)
    {
        switch (uiMsgID)
        {
			// preference => status 
            case C_ui_SaveStatusAction:
				GetInterface()->GetSpecificInterface()->GetDialogStatus()->fn_vDoDialog(GetInterface()->GetSpecificInterface(), FALSE);
                break;
			// preference => prefix 
            case C_ui_SavePrefixAction:
				GetInterface()->fn_vSaveUserPrefix(GetInterface()->GetUserPrefix().Left(3));
                break;
			// preference => prefix 
            case C_ui_SavePermissions:
				GetInterface()->fn_vSaveAuthorizations();
                break;
			// preference => prefix 
            case C_ui_SaveInterdictions:
				GetInterface()->fn_vSaveProhibitions();
                break;
			// preference => dialogs 
            case C_ui_SaveDialogsAction:
				fn_vSaveDialogsPreferences();
                break;

		}
	}
}


/*===========================================================================
*		Description:	add entries to popupmenu.
*		Creation date:
*		Author:			Marc Trabucato
*---------------------------------------------------------------------------
*		Revision date:       Author: Shaitan
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bDefinePopupMenu(EDT_PopUpMenu *p_oPopup, CPA_List<CPA_SuperObject> *pSelection, BOOL bAsCurrentEditor)
{
	EDT_SubMenu	*p_oSubMenu;
	CString		csText;
	BOOL		bResult = FALSE;

	p_oSubMenu = p_oPopup->fn_p_oGetNewSubMenu("Edit Super-Object");

	if (fn_bIsCurrentEditor())
	{
		// edit flags
		if (M_GetWorld()->GetCountSelected() == 1)
		{
			if (M_GetSingleSelection()->GetSuperObjectOwner())
			{
				p_oSubMenu->AddAnEntry(this, "Unprotect Child", C_ui_ChangeOwner, FALSE, TRUE);
				bResult = TRUE;
			}
			else if (M_GetSingleSelection()->GetSuperObjectFather()->GetObjectDLL())
			{
				p_oSubMenu->AddAnEntry(this, "Protect Child", C_ui_ChangeOwner, FALSE, TRUE);
				bResult = TRUE;
			}
		}
	}


	// orient instance
	if (fn_bCanOrientSelection())
	{
		p_oSubMenu->AddAnEntry(this, "Orient Instance", C_ui_OrientInstanceAction, FALSE, TRUE);
        bResult = TRUE;
	}
	if (M_GetWorld()->GetCountSelected() == 1)
	{
//CPA2 Corneliu Babiuc 18-05-98
		csText = "Put on Ground";
		csText += "\t";
		csText += m_p_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("put on Ground"));

//		p_oSubMenu->AddAnEntry(this, "Put On Ground", C_ui_PutOnGroundAction);
		p_oSubMenu->AddAnEntry(this, (char*)(LPCTSTR)csText, C_ui_PutOnGroundAction);
//END CPA2 Corneliu Babiuc 18-05-98
		bResult = TRUE;
	}

	// copy instance
	if ((M_GetWorld()->GetCountSelected() == 1)&&(fn_bCanCopyAllObjects()))
	{
//CPA2 Corneliu Babiuc 13-05-98
		csText = "Copy instance alone";
		csText += "\t";
		csText += m_p_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Copy instance alone"));

//		p_oSubMenu->AddAnEntry(this, "Copy Instance Alone", C_ui_CopyInstanceAction, FALSE, TRUE);
		p_oSubMenu->AddAnEntry(this, (char*)(LPCTSTR)csText, C_ui_CopyInstanceAction, FALSE, TRUE);
//END CPA2 Corneliu Babiuc 13-05-98
        bResult = TRUE;
	}
	// copy object
	if ((M_GetWorld()->GetCountSelected() > 0)&&(fn_bCanCopyAllObjects()))
	{
//CPA2 Corneliu Babiuc 13-05-98
		csText = "Copy instance with Branch";
		csText += "\t";
		csText += m_p_oDevKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("copy instance with Branch"));

//		p_oSubMenu->AddAnEntry(this, "Copy selected Objects", C_ui_CopyObjectAction, FALSE, TRUE);
		p_oSubMenu->AddAnEntry(this, (char*)(LPCTSTR)csText, C_ui_CopyObjectAction, FALSE, TRUE);
//END CPA2 Corneliu Babiuc 13-05-98
        bResult = TRUE;
	}
	m_csMessage.Empty();

	if (bResult)
		p_oPopup->AddASubMenu(p_oSubMenu);

	// entries ?
    return bResult;
}

/*===========================================================================
*		Description:	execute action according popupmenu entry.
*		Creation date:
*		Author:			Marc Trabucato
*---------------------------------------------------------------------------
*		Revision date:       Author: Shaitan
*=========================================================================*/
void EDT_HierarchyEditor::_OnPopUpMenuCommand(UINT _IDCmdMsg)
{
	CPA_SuperObject *pSelected;

	switch (_IDCmdMsg)
	{
		// orient instance
		case C_ui_OrientInstanceAction:
			// change mode
			SetEditorMode(E_em_OrientMode);
			break;
		// copy instance
		case C_ui_CopyInstanceAction:
			fn_vInitListToCopy(M_GetWorld()->GetListSelected(), TRUE);
			m_lNbCopy = 0;
			break;
		// copy selection
		case C_ui_CopyObjectAction:
			fn_vInitListToCopy(M_GetWorld()->GetListSelected(), FALSE);
			m_lNbCopy = 0;
			break;

		// Put on Ground
		case C_ui_PutOnGroundAction:
			fn_vPutOnGround();
 			return;

		case C_ui_ChangeOwner:
			pSelected = M_GetWorld()->GetSingleSelection();
			// update owner
			if (pSelected->GetSuperObjectOwner())
				pSelected->SetSuperObjectOwner(NULL);
			else
				pSelected->SetSuperObjectOwner(pSelected->GetSuperObjectFather());
			// update editor
			GetInterface()->fn_vUpdateAll(E_mc_UpdateDialog);
	}
}


//#################################################################################
// MESSAGE
//#################################################################################
/*===========================================================================
*		Description:	Display a message when a modif is canceled
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vDisplayCancelMessage (tdeCancelMode eModif)
{
	CString csMessage;

	// switch modif type to find the reight message
	switch (eModif)
	{
		case E_cm_CancelInsert:
			csMessage = "Instance could not be inserted in hierarchy";
			break;
		case E_cm_CancelParent :
			csMessage = "Hierarchy links cannot be changed";
			break;
		case E_cm_CancelCopy :
			csMessage = "Selected Objects cannot be copied";
			break;
		case E_cm_CancelPaste :
			csMessage = "Selected Objects cannot be paste";
			break;
		case E_cm_CancelDelete :
			csMessage = "Selected Objects cannot be removed from Hierarchy";
			break;
		case E_cm_CancelMove :
			csMessage = "Selected Objects cannot be moved";
			break;
		default:
			csMessage = "";
	}

	// if there is an explanation, display it
	if (!m_csMessage.IsEmpty())
	{
		csMessage += " : ";
		csMessage += m_csMessage;
	}
	else if (m_eModifCanceled != E_cm_NoCancel)
		csMessage += ".";

	// display message box
	M_GetMainWnd()->UpdateStatus((char*)(LPCSTR)csMessage, C_STATUSPANE_INFOS, C_STATUS_ERROR);

	// RAZ Message
	m_csMessage.Empty();
	m_eModifCanceled = E_cm_NoCancel;
}


//#################################################################################
// PREFERENCES
//#################################################################################
/*===========================================================================
*		Description:	get dialogs dimensions and save in .ini file
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:     Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vSaveDialogsPreferences (void)
{
	CString	csFileName;
	CString	csDimension;
	BOOL	bRes = TRUE;
	
	csFileName = M_GetMainApp()->m_csEditorDataPath + C_szHierarchyIniFile;
	// left frame width
	csDimension.Format("%ld", m_pLeftFrame->m_oCurPos.right - m_pLeftFrame->m_oCurPos.left);
	bRes &= WritePrivateProfileString ("Preference", "Left Frame Width", (char*)(LPCSTR)csDimension, (char*)(LPCSTR)csFileName);
	// dialogs dimensions
	csDimension.Format("%ld", m_pLeftFrame->GetPaneSize(0));
	bRes &= WritePrivateProfileString ("Preference", "DialogList Dimension", (char*)(LPCSTR)csDimension, (char*)(LPCSTR)csFileName);
	csDimension.Format("%ld", m_pLeftFrame->GetPaneSize(1));
	bRes &= WritePrivateProfileString ("Preference", "DialogEdit Dimension", (char*)(LPCSTR)csDimension, (char*)(LPCSTR)csFileName);
	// bottom frame width
	csDimension.Format("%ld", m_pBottomFrame->m_oCurPos.bottom - m_pBottomFrame->m_oCurPos.top);
	bRes &= WritePrivateProfileString ("Preference", "Bottom Frame Height", (char*)(LPCSTR)csDimension, (char*)(LPCSTR)csFileName);

	// if necessary, display error message
	if (!bRes)
		M_GetMainWnd()->UpdateStatus("Hierarchy Editor cannot save your preferences. EDTKeys.ini may have a ReadOnly status ?", C_STATUSPANE_INFOS, C_STATUS_WARNING);
	else
		M_GetMainWnd()->UpdateStatus("Preferences saved", C_STATUSPANE_INFOS, C_STATUS_NORMAL);
}

//#################################################################################
// SECTION
//#################################################################################
/*===========================================================================
*		Description:	retrieve or create super-objet coresponding to section name
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:     Author:
*=========================================================================*/
EDT_SuperObject * EDT_HierarchyEditor::GetOrLoadSuperObject (CString csSectionName)
{
	HIE_tdxHandleToSuperObject	hSupObj;
	SCR_tdst_Link_Value			*pLinkValue;
	SCR_tdst_Cxt_Values			*p_stValues ;
	CPA_ObjectDLLBase			*p_oDLL;
	EDT_SuperObject				*pSupObj = NULL;
	tdeSaveStatus				eSaveStatus;
	CString						csName, csEngineFileName;
	char						szActionName[SCR_CV_ui_Cfg_MaxLenName];
	char						szFileName[SCR_CV_ui_Cfg_MaxLenName];
	char						szName[SCR_CV_ui_Cfg_MaxLenName];
	
	// get value from coresponding link-table
	pLinkValue = SCR_fnp_st_Link_SearchKey(HIE_fn_p_stGetSuperObjectLinkTable(), (char*)(LPCSTR) csSectionName);
	SCR_fn_v_RdL0_SplitSectionName((char*)(LPCSTR) csSectionName, szFileName, szActionName, szName);
	csName = szName;
	csEngineFileName = szFileName;

	// key in link table => engine super-object already exists
	if ((pLinkValue)&&(SCR_M_e_Link_GetState(pLinkValue) == SCR_ELS_Link_Initialized))
		hSupObj = (HIE_tdxHandleToSuperObject) SCR_M_ul_Link_GetValue(pLinkValue);
	// else load engine super-object
	else
	{
		p_stValues = SCR_fnp_st_RdL0_AnalyseSection((char*)(LPCSTR) csSectionName, SCR_CDF_uw_Anl_Normal);
		if (p_stValues)
			hSupObj = (HIE_tdxHandleToSuperObject) p_stValues->a_ulValues[0];
	}
	
	// get or create corresponding super-object
	pSupObj = (EDT_SuperObject *) GetEditorObject(hSupObj);
	// new object => create editor instance
	if (!pSupObj)
	{
		// create super-objet
		eSaveStatus = (m_pSpecificEditor->fn_bIsValidType(C_Static)) ? E_ss_Responsible : E_ss_Modify;
		pSupObj = (EDT_SuperObject *) GetNewSuperObject(hSupObj, eSaveStatus, C_Static, csName, csEngineFileName);

		// if necessary, ask DLL to initialise its objet
		p_oDLL = GetMainWorld()->GetObjectDLLWithType(HIE_fn_ulGetSuperObjectType(hSupObj));
		if (p_oDLL)
			p_oDLL->fn_vBuildNewEditorInstance(pSupObj, hSupObj);
	}
	return pSupObj;

}

/*===========================================================================
*		Description:	check if engine struct is in link table, and find corresponding section
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:     Author:
*=========================================================================*/
EDT_SuperObject * EDT_HierarchyEditor::GetSuperObjectFromLinkTable (HIE_tdxHandleToSuperObject hEngineSO, EDT_SuperObject *pParent)
{
	EDT_SuperObject *pEdObj;
	tdeSaveStatus	eSaveStatus;
	tdeTypeSO		eTypeSO;
	CString			csSectionName;
	char			szFileName[SCR_CV_ui_Cfg_MaxLenName];
	char			szActionName[SCR_CV_ui_Cfg_MaxLenName];
	char			szName[SCR_CV_ui_Cfg_MaxLenName];

	// try to find super-object in link table
	csSectionName = GetEngineSectionName(hEngineSO);
	if (csSectionName.IsEmpty())
		return NULL;

	// get parameters and create super-object
	SCR_fn_v_RdL0_SplitSectionName((char*)(LPCSTR) csSectionName, szFileName, szActionName, szName);
	eTypeSO = (pParent) ? pParent->GetTypeSO() : C_Static;
	eSaveStatus = (m_pSpecificEditor->fn_bIsValidType(eTypeSO)) ? E_ss_Responsible : E_ss_Modify;
	// init type from hierarchy position
	pEdObj = (EDT_SuperObject *) GetNewSuperObject(hEngineSO, eSaveStatus, eTypeSO, szName, szFileName);

	return pEdObj;
}


/*===========================================================================
*		Description:	check if engine struct is in link table, and find corresponding section
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:     Author:
*=========================================================================*/
CString EDT_HierarchyEditor::GetEngineSectionName (HIE_tdxHandleToSuperObject hEngineSO)
{
	SCR_tdst_Link_Value	*pLinkValue;
	CString				csSectionName, csCompleteName;
	int					iPos;

	// init name
	csSectionName.Empty();

	// search link table for engine struct
	pLinkValue = SCR_fnp_st_Link_SearchValue(HIE_fn_p_stGetSuperObjectLinkTable(), (unsigned long) hEngineSO);
	if ((pLinkValue)&&(SCR_M_e_Link_GetState(pLinkValue) == SCR_ELS_Link_Initialized))
		csCompleteName = SCR_M_p_sz_Link_GetKey(pLinkValue);	
	// compute minimal file name
	// temp
	iPos = csCompleteName.Find(m_csSOReferencePath);
	if (iPos != -1)
		csSectionName = csCompleteName.Mid(m_csSOReferencePath.GetLength());
	else
		csSectionName = csCompleteName;
	return csSectionName;
}


//#################################################################################
// MODIFICATIONS
//#################################################################################

/*===========================================================================
*		Description:	add a modif to global list for super-objects
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vAddTemporaryModif (EDT_SuperObject *pSupObj)
{
	EDT_TempModif *pTempSO;

	// check if super-object is temporary
	pTempSO = pSupObj->GetTemporaryModif();
	if (!pTempSO)
		return;
	
	// if no list, create it
	if (!m_pListOfTempModifs)
		m_pListOfTempModifs = new EDT_TempList(this, FALSE);
	
	// add temporary modif to the list
	m_pListOfTempModifs->fn_vAddTemporaryModif(pTempSO);
}
	
/*===========================================================================
*		Description:	remove a modif from global list for super-objects
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vRemoveTemporaryModif (EDT_SuperObject *pSupObj)
{
	EDT_TempModif *pTempSO;

	// check if super-object is temporary
	pTempSO = pSupObj->GetTemporaryModif();
	if ((!pTempSO)||(!m_pListOfTempModifs))
		return;
	
	// remove temporary modif from the list
	m_pListOfTempModifs->fn_vRemoveTemporaryModif(pTempSO);
}

/*===========================================================================
*		Description:	remove a modif from global list for super-objects
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vChangeTemporaryModif (EDT_SuperObject *pSupObj)
{
	EDT_TempModif *pTempSO;

	// check if super-object is temporary
	pTempSO = pSupObj->GetTemporaryModif();
	if ((!pTempSO)||(!m_pListOfTempModifs))
		return;
	
	// remove temporary modif from the list
	m_pListOfTempModifs->fn_vChangeTemporaryModif(pTempSO);
}

/*===========================================================================
*		Description:	get section name correspinding to list of modifications
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
CString EDT_HierarchyEditor::GetTempListSectionName (void)
{
	return GetSpecificEditor()->GetModifSectionName();
}

//#################################################################################
// TEMPORARY MODIFICATIONS
//#################################################################################
/*===========================================================================
	Load list of modifications
=========================================================================*/
SCR_tde_Anl_ReturnValue EDT_HierarchyEditor::CallBackLoadListModif (SCR_tdst_File_Description *p_fFile, char *szSectionName, char *szParams[], SCR_tde_Anl_Action eAction)
{
	SCR_tdst_Cxt_Values *p_stValues ;
	EDT_SuperObject		*pSupObj;
	EDT_TempModif		*pTempSO;
	EDT_TempList		*pTempList;
	EDT_HierarchyEditor			*pEditor;
	char				szSupObjName[SCR_CV_ui_Cfg_MaxLenName];
	char				szFileName[SCR_CV_ui_Cfg_MaxLenName];
	CString				csOrigFileName;
	char				szModifObjName[SCR_CV_ui_Cfg_MaxLenName];
	char				szModifSectionName[SCR_CV_ui_Cfg_MaxLenName];
	
	switch (eAction)
	{
		case SCR_EA_Anl_BeginSection:
			// get corresponding super-object
			SCR_M_RdL0_GetContextLong(0, 0, EDT_HierarchyEditor *,  pEditor);
			pTempList = new EDT_TempList(pEditor, TRUE);
			pEditor->SetListOfTempModifs(pTempList);
			// create modification
			SCR_M_RdL0_SetSectionLong(0, 0, (long) pTempList);
			break;

		case SCR_EA_Anl_Entry:
			// load each modif
			if (strcmp(szSectionName, "Modification") == 0)
			{
				SCR_M_RdL0_GetSectionLong(0, 0, EDT_TempList *,  pTempList);
				pEditor = pTempList->GetEditor();
				
				// get corresponding super-object
				SCR_fn_v_RdL0_SplitSectionName(szParams[1], szFileName, szSectionName, szSupObjName);
				BOOL bUseTheSameFile = (1 == strlen (szFileName) && '*' == szFileName [0]);
				if (bUseTheSameFile)
					strcpy (szFileName, SCR_M_RdL0_GetFileNameR(0));
				SCR_fn_v_RdL0_ComputeSectionName(szSectionName, szFileName, "SuperObject", szSupObjName);
				pSupObj = pEditor->GetOrLoadSuperObject(szSectionName);
				ASSERT (pSupObj);
				// load corresponding temporary modif
				SCR_M_RdL0_SetContextLong(1, 0, (long) pSupObj);
				//get the modif section name
				csOrigFileName = szFileName;
				SCR_fn_v_RdL0_SplitSectionName(szParams[2], szFileName, szSectionName, szModifObjName);
				BOOL bUseTheMDFFile = (1 == strlen (szFileName) && '*' == szFileName [0]);
				if (bUseTheMDFFile)
				{
					int iPos = csOrigFileName.ReverseFind ('.');
					ASSERT (-1 != iPos);
					csOrigFileName = csOrigFileName.Left (iPos) + szModifExt;
				}
				else
					csOrigFileName = szFileName;

				SCR_fn_v_RdL0_ComputeSectionName(szModifSectionName, (char*)(LPCSTR)csOrigFileName, szSectionName, szModifObjName);
				pSupObj->mfn_vSetTempModifSectionName (szModifSectionName);
				p_stValues = SCR_fnp_st_RdL0_AnalyseSection(szParams[2], SCR_CDF_uw_Anl_Normal);
				if (p_stValues)
					pTempSO = (EDT_TempModif *) p_stValues->a_ulValues[0];

				// check coherence
				ASSERT (pSupObj == pTempSO->GetOriginalSO());
				//load the original super object name
				pTempSO->mfn_vSetOriginalSOName (szParams[0]);
				// update superobject
				pSupObj->SetTemporaryModif(pTempSO);

				// add modif to the list
				pTempList->fn_vAddTemporaryModif(pTempSO, FALSE);
			}

		case SCR_EA_Anl_EndSection:
			break;
	}
	return SCR_ERV_Anl_NormalReturn;
}

//#################################################################################
// POSITION
//#################################################################################
/*===========================================================================
*		Description:	get position from picking
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bFindPickingPosition (tdstPosition *p_stPosition)
{
	HIE_tdxHandleToSuperObject	hSupObj;
	HIE_aDEF_stTabOfPickInfo	a_stPickInfo;
	CPA_SuperObject				*pParent = NULL;
	DEV_ViewPort3D				*pCurViewport;
	ACP_tdxIndex				xNbPicked, xInd;

	// init parameters
	pCurViewport = M_GetViewPort3d();
	hSupObj = M_GetEngineRoot();
	xNbPicked = 0;

	// try to pick an object
	if (hSupObj != NULL)
	{
		// picking
		xNbPicked = HIE_xIsSuperObjectPick(GLI_C_ModePickingFace, pCurViewport->m_hDisplayDevice,
			pCurViewport->m_hDisplayViewport, &p_stPosition->stPos.stPos2D, hSupObj, a_stPickInfo);
	}

	// update picking info
	p_stPosition->xIndex = xNbPicked;    

	// if there is no picking, insertion is canceled
	if (xNbPicked == 0)
		return FALSE;

	// MAJ position
	p_stPosition->stPos.stPos3D = (a_stPickInfo[0].stPickedObject.aDEF_stDataOfElement[0].stHit);
	for (xInd = 0; xInd < xNbPicked; xInd++)
		p_stPosition->a_stPickInfo[xInd] = a_stPickInfo[xInd];

	return TRUE;
}

/*===========================================================================
*		Description:	get position from picking
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vMoveToNewPosition (tdstPosition *p_stPosition)
{
	EDT_SuperObject		*pParent, *pObjectToMove;
	MTH3D_tdstVector	stTranslation;
	MTH3D_tdstVector	stNormal, stVector;
	POS_tdstCompletePosition	*pParentMatrix, *pObjectMatrix, *pGlobalMatrix;
	POS_tdstCompletePosition	stMatrix;
	EDT_ModifMove		*pMouseMove;
	
	POS_fn_vSetIdentityMatrix(&stMatrix);
//CPA2 Corneliu Babiuc (multiple registration) 06-07-98
	CPA_List<EDT_ListByDLL>		* pObjectsListByDLL;
	CPA_List<CPA_SuperObject>	* pSOList;
	long x;

	if (x=M_GetWorld()->GetCountRegistered() )
	{				
		if ( !fn_bCanTranslateAllObjects(E_lst_RegisteredList) )
		{
			fn_vDisplayCancelMessage(E_cm_CancelMove);
			return;
		}
		pObjectsListByDLL = M_GetWorld()->GetListOfRegisteredListByDLL();
		pSOList = M_GetWorld()->GetListRegistered();
	}
	else 
	{
		if ( !fn_bCanTranslateAllObjects(E_lst_SelectedList) )
		{
			fn_vDisplayCancelMessage(E_cm_CancelMove);
			return;
		}
		pObjectsListByDLL = M_GetWorld()->GetListOfListByDLL();
		pSOList = M_GetWorld()->GetListSelected();
	}
//END CPA2 Corneliu Babiuc (multiple registration) 06-07-98

	// init mousemove
//CPA2 Corneliu Babiuc (teleport bug) 24-06-98
//	pMouseMove = new EDT_ModifMove(this, M_GetWorld()->GetListOfListByDLL(), GetInterface()->GetSelectMode());
//CPA2 Corneliu Babiuc (teleport bug) 24-06-98

	// init parameters
//CPA2 Corneliu Babiuc (TMS_0598) 25-05-98
//CPA2 Corneliu Babiuc (multiple registration) 06-07-98
/*	// if there is a registration then uses it
	if ( m_bIsASelection )
	{
//		pObjectToMove = (EDT_SuperObject *) M_GetWorld()->GetSingleSelection();
//	else
		pObjectToMove = m_pRegisteredObject; 
//END CPA2 Corneliu Babiuc (TMS_0598) 25-05-98
//CPA2 Corneliu Babiuc (teleport bug) 24-06-98
		// construct a list containing a single element: the registered object
		CPA_List<EDT_ListByDLL> lstSingleList;
		fn_vAddObjectRecursiveToList((CPA_SuperObject*)pObjectToMove, &lstSingleList, TRUE);
		pMouseMove = new EDT_ModifMove(this, &lstSingleList, GetInterface()->GetSelectMode());
//END CPA2 Corneliu Babiuc (teleport bug) 24-06-98
		pParent = (EDT_SuperObject *) pObjectToMove->GetSuperObjectFather();
		// init position
		fn_vGetNormalFromPicking(p_stPosition->a_stPickInfo, &stNormal);
		fn_vGetPositionFromBoundingVolume(pObjectToMove, &stNormal, &stVector);
		MTH3D_M_vAddVector(&p_stPosition->stPos.stPos3D, &p_stPosition->stPos.stPos3D, &stVector);
		// get position
		pParentMatrix = HIE_fn_hGetSuperObjectGlobalMatrix(pParent->GetStruct());
		pObjectMatrix = HIE_fn_hGetSuperObjectMatrix(pObjectToMove->GetStruct());
		pGlobalMatrix = HIE_fn_hGetSuperObjectGlobalMatrix(pObjectToMove->GetStruct());
		// correct position according to pParent's matrix
		POS_fn_vInvertMatrix(&stMatrix, pParentMatrix);
		POS_fn_vMulMatrixVertex(&stTranslation, &stMatrix, &p_stPosition->stPos.stPos3D); 
		POS_fn_vSetTranslationVector(pObjectMatrix,&stTranslation);
		POS_fn_vSetTranslationVector(pGlobalMatrix,&p_stPosition->stPos.stPos3D);
		// update global matrices
		GetInterface()->fn_vUpdatePositions();
//CPA2 Corneliu Babiuc (TMS_0598) 25-05-98
	}
	else // move selected objects
	{
*/
//CPA2 Corneliu Babiuc (multiple registration) 06-07-98
//CPA2 Corneliu Babiuc (teleport bug) 24-06-98
		// init mousemove
		pMouseMove = new EDT_ModifMove(this, /*M_GetWorld()->GetListOfListByDLL()*/pObjectsListByDLL, GetInterface()->GetSelectMode());
//CPA2 Corneliu Babiuc (teleport bug) 24-06-98
		// for each selected object
		POSITION stPos;
		long lIndex = 1;
		for( pObjectToMove = (EDT_SuperObject *) /*M_GetWorld()->GetListSelected()*/pSOList->GetHeadElement(stPos);
			 pObjectToMove;
			 pObjectToMove = (EDT_SuperObject *) /*M_GetWorld()->GetListSelected()*/pSOList->GetNextElement(stPos), lIndex++ )
		{
			
			MTH3D_tdstVector stNewPosition;
			pParent = (EDT_SuperObject *) pObjectToMove->GetSuperObjectFather();

			MTH3D_M_vCopyVector(&stNewPosition, &p_stPosition->stPos.stPos3D);
			// init position
			fn_vGetNormalFromPicking(p_stPosition->a_stPickInfo, &stNormal);
			fn_vGetPositionFromBoundingVolume(pObjectToMove, &stNormal, &stVector);
			// now the moving position is the new position added with vector for object BV
			MTH3D_M_vAddVector(&stNewPosition, &stNewPosition, &stVector);
			// get position
			pParentMatrix = HIE_fn_hGetSuperObjectGlobalMatrix(pParent->GetStruct());
			pObjectMatrix = HIE_fn_hGetSuperObjectMatrix(pObjectToMove->GetStruct());
			pGlobalMatrix = HIE_fn_hGetSuperObjectGlobalMatrix(pObjectToMove->GetStruct());
			// correct position according to pParent's matrix
			POS_fn_vInvertMatrix(&stMatrix, pParentMatrix);
			POS_fn_vMulMatrixVertex(&stTranslation, &stMatrix, &stNewPosition); 
			POS_fn_vSetTranslationVector(pObjectMatrix,&stTranslation);
			POS_fn_vSetTranslationVector(pGlobalMatrix,&stNewPosition);
			// update global matrices
			GetInterface()->fn_vUpdatePositions(); 

			//move object to avoid collision
			fn_vMoveObjectFromMultipleSelection(pObjectToMove, (CPA_List<EDT_SuperObject> *)M_GetWorld()->GetListSelected(), lIndex, &p_stPosition->stPos.stPos3D, &stNormal);
		} // for all selected objects
//	}  
//CPA2 Corneliu Babiuc (TMS_0598) 25-05-98
	// ask for move
	fn_bDoOrCancelMove(pMouseMove);
}

//CPA2 Corneliu Babiuc (specific teleportation) 15-06-98
//////////////////////////////////////////////////////////////////////////////////////////
// Method : EDT_HierarchyEditor::fn_vMoveToInstancePosition
// Date   : 15-06-1998
//////////////////////////////////////////////////////////////////////////////////////////
// Description : 
//   It telports the selected object to the position of a reference instance
// Parameters:
//  pReferenceInstance	 - reference instance where object has to be teleported
//////////////////////////////////////////////////////////////////////////////////////////
// Author      : Corneliu Babiuc
// Modification:
//////////////////////////////////////////////////////////////////////////////////////////
void EDT_HierarchyEditor::fn_vMoveToInstancePosition(EDT_SuperObject * pReferenceInstance)
{
	EDT_SuperObject		*pParent, *pObjectToMove;
	MTH3D_tdstVector	stTranslation, stGlobalTranslation;
	MTH3D_tdstVector	stVectI, stVectJ, stVectK;
	POS_tdstCompletePosition	*pParentMatrix, *pObjectMatrix, *pGlobalMatrix;
	POS_tdstCompletePosition	stMatrix, stRotationMatrix;
	EDT_ModifMove		*pMouseMove;
	
//CPA2 Corneliu Babiuc (multiple registration) 06-07-98
	if (M_GetWorld()->GetCountRegistered() )
	{				
		if ( !fn_bCanTranslateAllObjects(E_lst_RegisteredList) )
		{
			fn_vDisplayCancelMessage(E_cm_CancelMove);
			return;
		}
		pObjectToMove = (EDT_SuperObject *)M_GetWorld()->GetSingleRegistration();
	}
	else 
	{
		if ( !fn_bCanTranslateAllObjects(E_lst_SelectedList) )
		{
			fn_vDisplayCancelMessage(E_cm_CancelMove);
			return;
		}
		pObjectToMove = (EDT_SuperObject *)M_GetWorld()->GetSingleSelection();
	}
//END CPA2 Corneliu Babiuc (multiple registration) 06-07-98

//CPA2 Corneliu Babiuc (teleport bug) 25-06-98
	// construct a list containing a single element: the registered object
	CPA_List<EDT_ListByDLL> lstSingleList;
	fn_vAddObjectRecursiveToList((CPA_SuperObject*)pObjectToMove, &lstSingleList, TRUE);
	pMouseMove = new EDT_ModifMove(this, &lstSingleList, GetInterface()->GetSelectMode());
//END CPA2 Corneliu Babiuc (teleport bug) 25-06-98
	// now move the object
	POS_fn_vGetTranslationVector(HIE_fn_hGetSuperObjectGlobalMatrix(pReferenceInstance->GetStruct()),&stGlobalTranslation);
	pParent = (EDT_SuperObject *) pObjectToMove->GetSuperObjectFather();
	// get position
	pParentMatrix = HIE_fn_hGetSuperObjectGlobalMatrix(pParent->GetStruct());
	pObjectMatrix = HIE_fn_hGetSuperObjectMatrix(pObjectToMove->GetStruct());
	pGlobalMatrix = HIE_fn_hGetSuperObjectGlobalMatrix(pObjectToMove->GetStruct());
	// correct position according to pParent's matrix
	POS_fn_vSetIdentityMatrix(&stMatrix);
	POS_fn_vInvertMatrix(&stMatrix, pParentMatrix);
	POS_fn_vMulMatrixVertex(&stTranslation, &stMatrix, &stGlobalTranslation); 
	POS_fn_vSetTranslationVector(pObjectMatrix,&stTranslation);
	POS_fn_vSetTranslationVector(pGlobalMatrix,&stGlobalTranslation);
	// rotate object
	POS_fn_vGetRotationMatrix(HIE_fn_hGetSuperObjectGlobalMatrix(pReferenceInstance->GetStruct()),&stVectI,&stVectJ,&stVectK);
	//set the global rotation matrix
	POS_fn_vSetRotationMatrix(pGlobalMatrix,&stVectI,&stVectJ,&stVectK);
	//set local rotation matrix
	POS_fn_vSetIdentityMatrix(&stRotationMatrix);
	POS_fn_vSetRotationMatrix(&stRotationMatrix,&stVectI,&stVectJ,&stVectK);
	POS_fn_vMulMatrixMatrix(&stRotationMatrix, &stMatrix, &stRotationMatrix);
	POS_fn_vGetRotationMatrix(&stRotationMatrix,&stVectI,&stVectJ,&stVectK);
	POS_fn_vSetRotationMatrix(pObjectMatrix,&stVectI,&stVectJ,&stVectK);
	POS_fn_vNormalizeMatrix(pObjectMatrix);
	// update global matrices 
	GetInterface()->fn_vUpdatePositions(); 
	// ask for move
	fn_bDoOrCancelMove(pMouseMove);
}

//////////////////////////////////////////////////////////////////////////////////////////
// Method : EDT_HierarchyEditor::fn_vMoveToCameraPosition
// Date   : 15-06-1998
//////////////////////////////////////////////////////////////////////////////////////////
// Description : 
//   It telports the registered or selected object to the position of editor camera
// Parameters:
//////////////////////////////////////////////////////////////////////////////////////////
// Author      : Corneliu Babiuc
// Modification:
//////////////////////////////////////////////////////////////////////////////////////////

void EDT_HierarchyEditor::fn_vMoveToCameraPosition()
{
	POS_tdstCompletePosition	stMatrix, stCameraMatrix;
	POS_tdstCompletePosition	*pObjectMatrix, *pGlobalMatrix, *pParentMatrix;
	EDT_ModifMove		*pMouseMove;
	EDT_SuperObject		*pObjectToMove, *pParent;
	MTH3D_tdstVector	stTranslation, stGlobalTranslation;
	MTH3D_tdstVector	stVectI, stVectJ, stVectK;
	
//CPA2 Corneliu Babiuc (multiple registration) 06-07-98
	if (M_GetWorld()->GetCountRegistered() )
	{				
		if ( !fn_bCanTranslateAllObjects(E_lst_RegisteredList) )
		{
			fn_vDisplayCancelMessage(E_cm_CancelMove);
			return;
		}
		pObjectToMove = (EDT_SuperObject *)M_GetWorld()->GetSingleRegistration();
	}
	else 
	{
		if ( !fn_bCanTranslateAllObjects(E_lst_SelectedList) )
		{
			fn_vDisplayCancelMessage(E_cm_CancelMove);
			return;
		}
		pObjectToMove = (EDT_SuperObject *)M_GetWorld()->GetSingleSelection();
	}
//END CPA2 Corneliu Babiuc (multiple registration) 06-07-98

	// init mousemove
//CPA2 Corneliu Babiuc (teleport bug) 25-06-98
	// construct a list containing a single element: the registered object
	CPA_List<EDT_ListByDLL> lstSingleList;
	fn_vAddObjectRecursiveToList((CPA_SuperObject*)pObjectToMove, &lstSingleList, TRUE);
	pMouseMove = new EDT_ModifMove(this, &lstSingleList, GetInterface()->GetSelectMode());
//END CPA2 Corneliu Babiuc (teleport bug) 25-06-98
	
	DEV_ViewPort3D		*pCurViewport;
	CPA_BaseObject		*p_oCamera;

	pCurViewport = (DEV_ViewPort3D *)GetInterface()->GetMultiDevice3D()->GetFocusDevice()->GetViewPort();
	p_oCamera = pCurViewport->GetCamera();
	POS_fn_vSetIdentityMatrix(&stCameraMatrix);
	pCurViewport->GetCameraInterface()->GetMatrix(p_oCamera, &stCameraMatrix);
	POS_fn_vGetTranslationVector(&stCameraMatrix, &stGlobalTranslation);

	// now move the object to the editor camera position
	pParent = (EDT_SuperObject *) pObjectToMove->GetSuperObjectFather();
	// get position
	pParentMatrix = HIE_fn_hGetSuperObjectGlobalMatrix(pParent->GetStruct());
	pObjectMatrix = HIE_fn_hGetSuperObjectMatrix(pObjectToMove->GetStruct());
	pGlobalMatrix = HIE_fn_hGetSuperObjectGlobalMatrix(pObjectToMove->GetStruct());
	// correct position according to pParent's matrix
	POS_fn_vSetIdentityMatrix(&stMatrix);
	POS_fn_vInvertMatrix(&stMatrix, pParentMatrix);
	POS_fn_vMulMatrixVertex(&stTranslation, &stMatrix, &stGlobalTranslation); 
	POS_fn_vSetTranslationVector(pObjectMatrix,&stTranslation);
	POS_fn_vSetTranslationVector(pGlobalMatrix,&stGlobalTranslation);
	// rotate object
	POS_fn_vGetRotationMatrix(&stCameraMatrix,&stVectI,&stVectJ,&stVectK);
	//set the global rotation matrix
	POS_fn_vSetRotationMatrix(pGlobalMatrix,&stVectI,&stVectK,&stVectJ);
	//set the local rotation matrix
	POS_fn_vSetIdentityMatrix(&stCameraMatrix);
	POS_fn_vSetRotationMatrix(&stCameraMatrix,&stVectI,&stVectJ,&stVectK);
	POS_fn_vMulMatrixMatrix(&stCameraMatrix, &stMatrix, &stCameraMatrix);
	POS_fn_vGetRotationMatrix(&stCameraMatrix,&stVectI,&stVectK,&stVectJ);
	POS_fn_vSetRotationMatrix(pObjectMatrix,&stVectI,&stVectJ,&stVectK);
	POS_fn_vNormalizeMatrix(pObjectMatrix);
	// update global matrices
	GetInterface()->fn_vUpdatePositions();
	// ask for move
	fn_bDoOrCancelMove(pMouseMove);
}

//////////////////////////////////////////////////////////////////////////////////////////
// Method : EDT_HierarchyEditor::fn_vMoveCameraOrientedToInstance
// Date   : 18-06-1998
//////////////////////////////////////////////////////////////////////////////////////////
// Description : 
//   It moves the editor camera to have the same position and orientation as a reference 
//   instance. Set the camera translation and rotation according to reference instance
// Parameters:
//   p_oReference    - reference instance
//////////////////////////////////////////////////////////////////////////////////////////
// Author      : Corneliu Babiuc
// Modification:
//////////////////////////////////////////////////////////////////////////////////////////
void EDT_HierarchyEditor::fn_vMoveCameraOrientedToInstance(EDT_SuperObject * p_oReference)
{
	POS_tdstCompletePosition	*pGlobalPosition, stCameraMatrix;
	MTH3D_tdstVector	stTranslation, stVectI, stVectJ, stVectK;
	DEV_ViewPort3D		*pCurViewport;
	CPA_BaseObject		*p_oCamera;

	ASSERT(p_oReference);
	// get the reference object translation vector
	pGlobalPosition = HIE_fn_hGetSuperObjectGlobalMatrix(p_oReference->GetStruct());
	POS_fn_vGetTranslationVector(pGlobalPosition, &stTranslation);
	// set position
	pCurViewport = (DEV_ViewPort3D *)GetInterface()->GetMultiDevice3D()->GetFocusDevice()->GetViewPort();
	p_oCamera = pCurViewport->GetCamera();
	POS_fn_vSetIdentityMatrix(&stCameraMatrix);
	pCurViewport->GetCameraInterface()->GetMatrix(p_oCamera, &stCameraMatrix);
	POS_fn_vSetTranslationVector(&stCameraMatrix, &stTranslation);
	// set the rotation matrix of camera
	POS_fn_vGetRotationMatrix(pGlobalPosition,&stVectI,&stVectJ,&stVectK);
	//set the global rotation matrix
	MTH3D_M_vNegVector(&stVectJ, &stVectJ);
	POS_fn_vSetRotationMatrix(&stCameraMatrix,&stVectI,&stVectK,&stVectJ);
	pCurViewport->GetCameraInterface()->SetMatrix(p_oCamera, &stCameraMatrix);
}

//////////////////////////////////////////////////////////////////////////////////////////
// Method : EDT_HierarchyEditor::fn_vMoveCameraToInstanceCenterOnInstance
// Date   : 18-06-1998
//////////////////////////////////////////////////////////////////////////////////////////
// Description : 
//   It moves the editor camera to have the same position as a reference instance and 
//  centered to another instance. Set the camera translation and rotation according to reference instance
// Parameters:
//   p_oReference       - reference instance
//   p_oCenterObject    - instance where camera should to be centered 
//////////////////////////////////////////////////////////////////////////////////////////
// Author      : Corneliu Babiuc
// Modification:
//////////////////////////////////////////////////////////////////////////////////////////
void EDT_HierarchyEditor::fn_vMoveCameraToInstanceCenterOnInstance(EDT_SuperObject * p_oReference, CPA_SuperObject * p_oCenterObject)
{
	POS_tdstCompletePosition	*pGlobalPosition;
	MTH3D_tdstVector	stTranslation;
	CPA_CameraCoords	oPosition;
	DEV_ViewPort3D		*pCurViewport;
	CPA_BaseObject		*p_oCamera;
	CPA_CameraDLLBase   *p_CameraInterface;

	// check if the instance is Rayman:
	if ( p_oReference == p_oCenterObject )
	{
		m_csMessage = "Cannot move and center camera to Rayman's position";
		fn_vDisplayCancelMessage(m_eModifCanceled);
		return;
	}
	ASSERT(p_oReference);
	ASSERT(p_oCenterObject);
	// get the reference object translation vector
	pGlobalPosition = HIE_fn_hGetSuperObjectGlobalMatrix(p_oReference->GetStruct());
	POS_fn_vGetTranslationVector(pGlobalPosition, &stTranslation);
	oPosition.SetCoords(&stTranslation);
	oPosition.SetAxisSystem(WorldCoordinates);
	// set position
	pCurViewport = (DEV_ViewPort3D *)GetInterface()->GetMultiDevice3D()->GetFocusDevice()->GetViewPort();
	p_oCamera = pCurViewport->GetCamera();
	p_CameraInterface = pCurViewport->GetCameraInterface();
	p_CameraInterface->SetPosition(p_oCamera, &oPosition);
	// center on instance
	p_CameraInterface->SetTargetSuperObject(p_oCamera, p_oCenterObject);
	p_CameraInterface->SetTargetType(p_oCamera, tSuperObject);
	p_CameraInterface->Update(p_oCamera);
	p_CameraInterface->SetTargetType(p_oCamera, tNone);
	GetInterface()->fn_vUpdateAll(E_mc_JustDraw);
}

//////////////////////////////////////////////////////////////////////////////////////////
// Method : EDT_HierarchyEditor::fn_vTranslateObjects
// Date   : 15-06-1998
//////////////////////////////////////////////////////////////////////////////////////////
// Description : 
//   It translates all selected objects with a specified translation vector
// Parameters:
//   pTranslation      - translation vector
//////////////////////////////////////////////////////////////////////////////////////////
// Author      : Corneliu Babiuc
// Modification:
//////////////////////////////////////////////////////////////////////////////////////////

void EDT_HierarchyEditor::fn_vTranslateObjects(MTH3D_tdstVector * pTranslation)
{
	EDT_SuperObject * pSupObj;
	POSITION		pos;
	EDT_ModifMove	*pObjectsMove;
	
	// create modif
	pObjectsMove = new EDT_ModifMove(this, M_GetWorld()->GetListOfListByDLL(), GetInterface()->GetSelectMode());

	// apply translation vector
	for (pSupObj = (EDT_SuperObject *) M_GetWorld()->GetListSelected()->GetHeadElement(pos); pSupObj;
		 pSupObj = (EDT_SuperObject *) M_GetWorld()->GetListSelected()->GetNextElement(pos))
	{
		pSupObj->fn_vTranslate(pTranslation, TRUE);
	}
	// ask for move
	fn_bDoOrCancelMove(pObjectsMove);
}
//END CPA2 Corneliu Babiuc (specific teleportation) 19-06-98

//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method :fn_vMoveToNewPosition (MTH3D_tdstVector* p_stPosition)
// Date  : 98-01-28
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description : this function is called in the PutOnGround function in order to implement Undo/Redo
// functionality
// Author      : Gabi Dumitrascu - CPA2
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Modification :
// Date         :
// By           :
//////////////////////////////////////////////////////////////////////////////////////////////////////
void EDT_HierarchyEditor::fn_vMoveToNewPosition (MTH3D_tdstVector* p_stPosition)
{
	EDT_SuperObject		*pParent, *pObjectToMove;
	MTH3D_tdstVector	stTranslation;
	POS_tdstCompletePosition	*pParentMatrix, *pObjectMatrix, *pGlobalMatrix;
	POS_tdstCompletePosition	stMatrix;
	EDT_ModifMove		*pMouseMove;
	
	POS_fn_vSetIdentityMatrix(&stMatrix);
	if (!fn_bCanTranslateAllObjects())
	{				
		fn_vDisplayCancelMessage(E_cm_CancelMove);
		return;
	}

	// init mousemove
	pMouseMove = new EDT_ModifMove(this, M_GetWorld()->GetListOfListByDLL(), GetInterface()->GetSelectMode());

	// init parameters
	pObjectToMove = (EDT_SuperObject *) M_GetWorld()->GetSingleSelection();
	pParent = (EDT_SuperObject *) pObjectToMove->GetSuperObjectFather();
	// get position
	pParentMatrix = HIE_fn_hGetSuperObjectGlobalMatrix(pParent->GetStruct());
	pObjectMatrix = HIE_fn_hGetSuperObjectMatrix(pObjectToMove->GetStruct());
	pGlobalMatrix = HIE_fn_hGetSuperObjectGlobalMatrix(pObjectToMove->GetStruct());
	// correct position according to pParent's matrix
	POS_fn_vInvertMatrix(&stMatrix, pParentMatrix);
	POS_fn_vMulMatrixVertex(&stTranslation, &stMatrix, p_stPosition); 
	POS_fn_vSetTranslationVector(pObjectMatrix,&stTranslation);
	POS_fn_vSetTranslationVector(pGlobalMatrix,p_stPosition);
	// update global matrices
	GetInterface()->fn_vUpdatePositions();
	// ask for move
	fn_bDoOrCancelMove(pMouseMove);
}


/*===========================================================================
*		Description:	get position from picking
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vApplyGravityToInstance (EDT_SuperObject *pSupObj, MTH3D_tdstVector *p_stMove, MTH3D_tdstVector *p_stVertical)
{
	HIE_aDEF_stTabOfPickInfo	a_stPickInfo;
    POS_tdxHandleToPosition		hMatrix, hLocal, hParent;
	MTH3D_tdstVector			stRealPosition, stTempPosition;
	MTH3D_tdstVector			stRealLocal, stTempLocal;
	MTH3D_tdstVector			stPosition, stDest;
	MTH3D_tdstVector			stNormal, stVector;
	MTH3D_tdstVector			stLocalVector, stLocalMove;
	ACP_tdxIndex				xNbPicked;

	// register superobject position
	hMatrix = HIE_fn_hGetSuperObjectGlobalMatrix(pSupObj->GetStruct());
	POS_fn_vGetTranslationVector(hMatrix, &stRealPosition);
	hLocal = HIE_fn_hGetSuperObjectMatrix(pSupObj->GetStruct());
	POS_fn_vGetTranslationVector(hLocal, &stRealLocal);
	// get new position
	MTH3D_M_vAddVector(&stPosition, &stRealPosition, p_stMove);
	MTH3D_M_vAddVector(&stDest, &stPosition, p_stVertical);
	// set it at temporary position to avoid picking
	MTH3D_M_vMulScalarVector(&stNormal, (float) -1.2, p_stVertical);
	fn_vGetPositionFromBoundingVolume(pSupObj, &stNormal, &stVector);
	MTH3D_M_vAddVector(&stTempPosition, &stPosition, &stVector);
	POS_fn_vSetTranslationVector(hMatrix, &stTempPosition);
	// same operation for local matrix
	hParent = HIE_fn_hGetSuperObjectGlobalMatrix(pSupObj->GetSuperObjectFather()->GetStruct());
	POS_fn_vMulMatrixVertex(&stLocalMove, hParent, p_stMove);
	POS_fn_vMulMatrixVertex(&stLocalVector, hParent, &stVector);
	MTH3D_M_vAddVector(&stTempLocal, &stRealLocal, &stLocalMove);
	MTH3D_M_vAddVector(&stTempLocal, &stTempLocal, &stLocalVector);
	POS_fn_vSetTranslationVector(hLocal, &stTempLocal);
	// get picking info
	xNbPicked = HIE_bIntersectSemiAxeWithSuperObject(GLI_C_ModePickingFace, &stPosition, &stDest,  
													 p_stVertical, M_GetEngineRoot(), a_stPickInfo);
	if (xNbPicked > 0)
	{
		// get real final position
		fn_vGetNormalFromPicking(a_stPickInfo, &stNormal);
		fn_vGetPositionFromBoundingVolume(pSupObj, &stNormal, &stVector);
		stDest = a_stPickInfo[0].stPickedObject.aDEF_stDataOfElement[0].stHit;
		MTH3D_M_vAddVector(&stDest, &stDest, &stVector);
		// update move
		MTH3D_M_vSubVector(&stDest, &stDest, &stPosition);
		MTH3D_M_vAddVector(p_stMove, p_stMove, &stDest);
	}
	// set at real position
	POS_fn_vSetTranslationVector(hMatrix, &stRealPosition);
	POS_fn_vSetTranslationVector(hLocal, &stRealLocal);
}



/*===========================================================================
*		Description:	test if parent can be changed
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bCanChangeSelectedObjects (void)
{
	CPA_SuperObject *pElem;
	POSITION		pos;
	
	// check all the elements in the list
	for (pElem = M_GetWorld()->GetListSelected()->GetHeadElement(pos); pElem;
		 pElem = M_GetWorld()->GetListSelected()->GetNextElement(pos))
	{
		if (!GetInterface()->fn_bCanModifyObject(pElem))
			return FALSE;
	}

	return TRUE;
}



//#################################################################################
// MOVES
//#################################################################################
/*===========================================================================
*		Description:	rotate matrix
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vRotateX (POS_tdstCompletePosition *p_stMatrix, GLI_tdxValue xXAngle)
{
	MTH3D_tdstVector	stVectI,stVectJ,stVectK;

	POS_fn_vGetRotationMatrix(p_stMatrix,&stVectI,&stVectJ,&stVectK);
	
	MTH3D_M_vSetYofVector(&stVectJ,GLI_M_Cos(xXAngle)) ;
	MTH3D_M_vSetZofVector(&stVectJ,GLI_M_Sin(xXAngle)) ;
	MTH3D_M_vSetYofVector(&stVectK,GLI_M_Neg(GLI_M_Sin(xXAngle))) ;
	MTH3D_M_vSetZofVector(&stVectK,GLI_M_Cos(xXAngle)) ;

	POS_fn_vSetRotationMatrix(p_stMatrix,&stVectI,&stVectJ,&stVectK);
}

//===========================================================================
//===========================================================================

void EDT_HierarchyEditor::fn_vRotateY (POS_tdstCompletePosition *p_stMatrix, GLI_tdxValue xYAngle)
{
	MTH3D_tdstVector	stVectI,stVectJ,stVectK;

	POS_fn_vGetRotationMatrix(p_stMatrix,&stVectI,&stVectJ,&stVectK);
	
	MTH3D_M_vSetXofVector(&stVectI,GLI_M_Cos(xYAngle)) ;
	MTH3D_M_vSetZofVector(&stVectI,GLI_M_Sin(xYAngle)) ;
	MTH3D_M_vSetXofVector(&stVectK,GLI_M_Neg(GLI_M_Sin(xYAngle))) ;
	MTH3D_M_vSetZofVector(&stVectK,GLI_M_Cos(xYAngle)) ;

	POS_fn_vSetRotationMatrix(p_stMatrix,&stVectI,&stVectJ,&stVectK);
}

//===========================================================================
//===========================================================================

void EDT_HierarchyEditor::fn_vRotateZ (POS_tdstCompletePosition *p_stMatrix, GLI_tdxValue xZAngle)
{
	MTH3D_tdstVector	stVectI,stVectJ,stVectK;

	POS_fn_vGetRotationMatrix(p_stMatrix,&stVectI,&stVectJ,&stVectK);
	
	MTH3D_M_vSetXofVector(&stVectI,GLI_M_Cos(xZAngle));
	MTH3D_M_vSetYofVector(&stVectI,GLI_M_Sin(xZAngle));
	MTH3D_M_vSetXofVector(&stVectJ,GLI_M_Neg(GLI_M_Sin(xZAngle)));
	MTH3D_M_vSetYofVector(&stVectJ,GLI_M_Cos(xZAngle));

	POS_fn_vSetRotationMatrix(p_stMatrix,&stVectI,&stVectJ,&stVectK);
}



//#################################################################################
// ORIENT
//#################################################################################
/*===========================================================================
*		Description:	check if object can be oriented
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
BOOL EDT_HierarchyEditor::fn_bCanOrientSelection (void)
{
	EDT_SuperObject *pEdObj;
	EDT_ListByDLL	*pListSelect;
	POSITION		pos;

	// only one instance
	if (M_GetWorld()->GetCountSelected() != 1)
		return FALSE;
	
	// ask dll
	pEdObj = (EDT_SuperObject *) M_GetWorld()->GetSingleSelection();
	if (pEdObj->GetObjectDLL() && !pEdObj->GetObjectDLL()->fn_bAcceptOrientInstance(pEdObj))
	{
		m_csMessage = "This object cannot be oriented";
		return FALSE;
	}
	
	// check current editor for permission
	if (!fn_bIsCurrentEditor())
	{
		pListSelect = M_GetWorld()->GetListAllDLLs();
		if (pListSelect->m_stListSelected.GetCount())
		{
			if (!M_GetCurrentEditor()->fn_bAcceptModifRotate(&pListSelect->m_stListSelected, C_AsCurrentEditor))
			{
				m_csMessage = "Current Editor does not allow you to rotate these objects";
				return FALSE;
			}
		}
	}
	for (pListSelect = M_GetWorld()->GetListOfListByDLL()->GetHeadElement(pos); pListSelect;
		 pListSelect = M_GetWorld()->GetListOfListByDLL()->GetNextElement(pos))
	{
		// if there are selected objects of this type
		if (pListSelect->m_stListSelected.GetCount())
		{
			// ask World permission
			if (!M_GetWorld()->fn_bAcceptModifRotate(pListSelect->GetDLL()))
			{
				m_csMessage.Format("Objects of DLL %s cannot be rotated in this world.", pListSelect->GetDLL()->GetName());
				return FALSE;
			}
			// ask the DLL for permission
			if (!pListSelect->GetDLL()->fn_bAcceptModifRotate(&pListSelect->m_stListSelected, C_AsConcernedDLL))
			{
				m_csMessage.Format("DLL %s does not allow you to rotate its objects.", pListSelect->GetDLL()->GetName());
				return FALSE;
			}
		}
		// if necessary, ask owner
		if (pListSelect->m_stListProtectSelected.GetCount())
		{
			// ask the DLL for permission
			if (!pListSelect->GetDLL()->fn_bAcceptModifRotate(&pListSelect->m_stListProtectSelected, C_AsChildOwner))
			{
				m_csMessage = "Some protected objets cannot be rotated";
				return FALSE;
			}
		}
	}

	// objects can be moved
	return TRUE;

}

/*===========================================================================
*		Description:	orient object to picking position
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vOrientToPosition (EDT_SuperObject *pEdObj, MTH3D_tdstVector *pOrientPosition)
{
	GEO_tdxHandleToMatrix	hGlobalMatrix;
	GEO_tdxHandleToMatrix	hInstanceMatrix;
	GEO_tdxHandleToMatrix	hParentMatrix;
	MTH3D_tdstVector		stGlobalPosition;
	MTH3D_tdstVector		stVectI, stVectJ, stVectK;
	CPA_SuperObject			*pParent;
	MTH_tdxReal				xX, xY,xZ;

	
	// get parameters
	pParent = pEdObj->GetSuperObjectFather();
	hInstanceMatrix = HIE_fn_hGetSuperObjectMatrix(pEdObj->GetStruct());
	hGlobalMatrix = HIE_fn_hGetSuperObjectGlobalMatrix (pEdObj->GetStruct());
	POS_fn_vGetTranslationVector (hGlobalMatrix, &stGlobalPosition);
	// get X vector
	MTH3D_M_vSubVector(&stVectI, pOrientPosition, &stGlobalPosition);
	MTH3D_M_vNormalizeVector(&stVectI, &stVectI);
	// get Y vector
	xX = MTH3D_M_xGetXofVector(&stVectI);
	xY = MTH3D_M_xGetYofVector(&stVectI);
	xZ = MTH3D_M_xGetZofVector(&stVectI);
	if ((xX != 0)||(xY != 0))
	{ 
		MTH3D_M_vSetVectorElements(&stVectJ, -xY, xX, 0.0); 
	}
	else 
	{ 
		MTH3D_M_vSetVectorElements(&stVectJ, 0.0, -xZ, xY); 
	} 
	MTH3D_M_vNormalizeVector(&stVectJ, &stVectJ);
	// get Z vector
	MTH3D_M_vCrossProductVector(&stVectK, &stVectI, &stVectJ);

	// calculate the new rotation matrix
	POS_fn_vSetRotationMatrix(hGlobalMatrix, &stVectJ, &stVectI, &stVectK);
	// set local matrix orientation
	hParentMatrix = GEO_fn_hCreateMatrix();
	POS_fn_vInvertMatrix(hParentMatrix, HIE_fn_hGetSuperObjectGlobalMatrix(pParent->GetStruct()));
	POS_fn_vMulMatrixMatrix(hInstanceMatrix, hParentMatrix, hGlobalMatrix);
	POS_fn_vNormalizeMatrix(hInstanceMatrix);
	// update drawing
	GetInterface()->fn_vUpdatePositions();
	GetInterface()->fn_vUpdateAll(E_mc_JustDraw);
}



/*===========================================================================
*		Description:	orient object to picking position, keeping axis orientation
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vOrientWithSelectedAxis (EDT_SuperObject *pEdObj, MTH3D_tdstVector *pOrientPosition, MTH3D_tdstVector *pAxis)
{
	GEO_tdxHandleToMatrix	hGlobalMatrix;
	MTH3D_tdstVector		stGlobalPosition, stVector, stFullAxis;
	MTH_tdxReal				xCoeff;

	// get superobject position
	hGlobalMatrix = HIE_fn_hGetSuperObjectGlobalMatrix(pEdObj->GetStruct());
	POS_fn_vGetTranslationVector(hGlobalMatrix, &stGlobalPosition);
	// changement de l'orientation
	MTH3D_M_vSubVector(&stVector, pOrientPosition, &stGlobalPosition);
	xCoeff = MTH3D_M_xDotProductVector(&stVector, pAxis);
	MTH3D_M_vMulScalarVector(&stFullAxis, xCoeff, pAxis);
	MTH3D_M_vSubVector(&stVector, &stVector, &stFullAxis);
	MTH3D_M_vAddVector(pOrientPosition, &stGlobalPosition, &stVector);

	// orient instance
	fn_vOrientToPosition(pEdObj, pOrientPosition);	
}

void EDT_HierarchyEditor::fn_vOrientWithVertical (EDT_SuperObject *pEdObj, MTH3D_tdstVector *pOrientPosition)
{
	MTH3D_tdstVector stAxis;

	MTH3D_M_vSetVectorElements(&stAxis, 0.f, 0.f, 1.f);
	fn_vOrientWithSelectedAxis(pEdObj, pOrientPosition, &stAxis);
}

/*===========================================================================
*		Description:	dialog to update super-object flags
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:       Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vDoDialogFlags (EDT_SuperObject *pSuperObject)
{
	HINSTANCE hOldInst = AfxGetResourceHandle();

	AfxSetResourceHandle (GetDLLIdentity()->hModule);

	m_pDialogFlag->fn_vDoDialog(this, pSuperObject);

	AfxSetResourceHandle(hOldInst);
}

/*===========================================================================
*		Description:	put on ground effect
*		Creation date:	19/03/98
*		Author:			Shaitan
*---------------------------------------------------------------------------
*	Revision date:                Author:
*=========================================================================*/
void EDT_HierarchyEditor::fn_vPutOnGround (void)
{
	HIE_aDEF_stTabOfPickInfo	a_stPickInfo;
	MTH3D_tdstVector			stInitialPosition;
	MTH3D_tdstVector			stFinalPosition;
	MTH3D_tdstVector			stVertical;
	CPA_SuperObject				*pSelected;
	CPA_SuperObject				*pGround = NULL;
	ACP_tdxIndex				xNbPicked, xIndex;
	BOOL						bFirstPicking;

	
	// get object to move
	pSelected = M_GetWorld()->GetSingleSelection(); 
	if (!pSelected)
		return;

	// init vertical & picking parameters
	MTH3D_M_vSetVectorElements(&stVertical, 0.0, 0.0, -20.0);
	xNbPicked = HIE_C_DepthPickingObjects;
	bFirstPicking = TRUE;

	// if there are too many object between instance and ground, we may need several picking
	while (!pGround && (xNbPicked >= HIE_C_DepthPickingObjects))
	{
		// get initial position
		if (bFirstPicking)
			POS_fn_vGetTranslationVector(HIE_fn_hGetSuperObjectMatrix(pSelected->GetStruct()), &stInitialPosition);
		else
			stInitialPosition = a_stPickInfo[xNbPicked-1].stPickedObject.aDEF_stDataOfElement[0].stHit;
		// reinit parameters
		MTH3D_M_vAddVector(&stFinalPosition, &stInitialPosition, &stVertical);
		xIndex = 0;
		// perform another picking
		xNbPicked = HIE_bIntersectSemiAxeWithSuperObject(GLI_C_ModePickingFace, &stInitialPosition, &stFinalPosition,  
														 &stVertical, M_GetEngineRoot(), a_stPickInfo);
		while ((xIndex < xNbPicked) && (pGround == NULL))
		{
			// check type (want only IPO)
			if (HIE_fn_ulGetSuperObjectType(a_stPickInfo[xIndex].hSprObject) & (HIE_C_ulIPO | HIE_C_ulIPO_Mirror))
				pGround = GetInterface()->GetEditorObject(a_stPickInfo[xIndex].hSprObject);
			else
				xIndex++;
		}
		bFirstPicking = FALSE;
	}

	// if no ground was found, cannot put on ground !
	if (!pGround)
	{
		M_GetMainWnd()->UpdateStatus("There is no ground under this instance", C_STATUSPANE_INFOS, C_STATUS_ERROR);
		return;
	}

	// move object to its new position
	stFinalPosition = a_stPickInfo[xIndex].stPickedObject.aDEF_stDataOfElement[0].stHit;
	fn_vMoveToNewPosition(&stFinalPosition);
	
	GetInterface()->fn_vUpdateAll(E_mc_UpdateAll);
}

//CPA2 Corneliu Babiuc (TMS_0598) 26-05-98
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method : EDT_HierarchyEditor::fn_vMoveObjectFromMultipleSelection
// Date   : 26-05-1998
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description : 
//   Used by teleport function, to position an object in case of multiple selection in order to 
//   avoid objects collision. It is done calculating the bounding parallel box of already 
//   teleported objects and then move the current object to avoid collision
// Parameters:
//  pSuperObject	 - object which has to be repositioned
//  p_oList		     - list of already moved objects (unused now, maybe in future, who knows?)
//  lIndex           - the number of current object in the p_oList
//  pSelectedPoint   - teleportation point
//  pNormal          - normal from picking
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Author      : Corneliu Babiuc
// Modification:
//////////////////////////////////////////////////////////////////////////////////////////////////////
void EDT_HierarchyEditor::fn_vMoveObjectFromMultipleSelection (
							EDT_SuperObject * pSuperObject,
							CPA_List<EDT_SuperObject> * p_oList,
							long lIndex,
							MTH3D_tdstVector * pSelectedPoint,
							MTH3D_tdstVector * pNormal)
{
	POS_tdstCompletePosition    stMatrix;
	MTH3D_tdstVector			stTranslation, stTemp;
	GLI_tdxValue				xNormFactor;
	MTH3D_tdstVector			stMinPoint, stMaxPoint;
	MTH3D_tdstVector			stGlobalCenter, stCenter;
	// these two vectors contain the minimal and maximal vertices of 
	// the parallel box that covers all the others parallel boxes
	static MTH3D_tdstVector		stGlobalMinPoint, stGlobalMaxPoint;
	
	//we consider the object size being the parallel box having min and max 
	//point of object as vertices
	
	// if the object is not the first in the list we'll just translate it tanget 
	// to the plan perpendicular to the normal
	if ( lIndex > 1 )
	{
		// compute min & max in global coordinates
		POS_fn_vSetIdentityMatrix(&stMatrix);
		stMinPoint.xX = stMinPoint.xY = stMinPoint.xZ = MTH_C_InfinitPlus;
		stMaxPoint.xX = stMaxPoint.xY = stMaxPoint.xZ = MTH_C_InfinitMinus;
		fn_vGetMinMaxPointsOfInstance(pSuperObject, &stMatrix, &stMinPoint, &stMaxPoint, TRUE);
		//get the centers of the global and current box 
		MTH3D_M_vAddVector(&stCenter, &stMinPoint, &stMaxPoint);
		MTH3D_M_vMulScalarVector(&stCenter, (GLI_tdxValue)0.5, &stCenter);
		MTH3D_M_vAddVector(&stGlobalCenter, &stGlobalMinPoint, &stGlobalMaxPoint);
		MTH3D_M_vMulScalarVector(&stGlobalCenter, (GLI_tdxValue)0.5, &stGlobalCenter);

		MTH3D_M_vSubVector(&stTranslation, &stGlobalCenter, pSelectedPoint);
		// we'll project this vector on the plane perpendicular to the normal
		MTH3D_M_vMulScalarVector(&stTemp, MTH3D_M_xDotProductVector( pNormal, &stTranslation), pNormal);
		MTH3D_M_vSubVector(&stTranslation, &stTemp, &stTranslation);
		// now we have to move the object, on the stTranslation direction
		// as it doesn't intersect the global parallel box

		//compute the vector between two centers
		MTH3D_M_vSubVector(&stTemp, &stCenter, &stGlobalCenter);
		// we'll choose the minimal deplacement
		if (GLI_M_Abs(stTranslation.xX) >= GLI_M_Abs(stTranslation.xY) &&
			GLI_M_Abs(stTranslation.xX) >= GLI_M_Abs(stTranslation.xZ) )
		{
			xNormFactor = (GLI_M_Sgn(stTranslation.xX)*((stGlobalMaxPoint.xX - stGlobalMinPoint.xX) + 
							(stMaxPoint.xX - stMinPoint.xX))/2 - stTemp.xX)/stTranslation.xX;
		}
		else
		{
			if (GLI_M_Abs(stTranslation.xY) > GLI_M_Abs(stTranslation.xX) &&
				GLI_M_Abs(stTranslation.xY) >= GLI_M_Abs(stTranslation.xZ) )
			{
				xNormFactor = (GLI_M_Sgn(stTranslation.xY)*((stGlobalMaxPoint.xY - stGlobalMinPoint.xY) +
							(stMaxPoint.xY - stMinPoint.xY))/2 - stTemp.xY)/stTranslation.xY;
			}
			else
			{
				xNormFactor = (GLI_M_Sgn(stTranslation.xZ)*((stGlobalMaxPoint.xZ - stGlobalMinPoint.xZ) +
							(stMaxPoint.xZ - stMinPoint.xZ))/2 - stTemp.xZ)/stTranslation.xZ;
			}
		}
		// we assure the distance between the two boxes to avoid collision
		MTH3D_M_vMulScalarVector(&stTranslation, xNormFactor, &stTranslation);
		// update global matrices
		GetInterface()->fn_vUpdatePositions();
	}
	// recompute min & max in global coordinates
	POS_fn_vSetIdentityMatrix(&stMatrix);
	stMinPoint.xX = stMinPoint.xY = stMinPoint.xZ = MTH_C_InfinitPlus;
	stMaxPoint.xX = stMaxPoint.xY = stMaxPoint.xZ = MTH_C_InfinitMinus;
	fn_vGetMinMaxPointsOfInstance(pSuperObject, &stMatrix, &stMinPoint, &stMaxPoint, TRUE);

	if ( lIndex == 1 )
	{
		//just initialize the points
		MTH3D_M_vCopyVector(&stGlobalMinPoint, &stMinPoint);
		MTH3D_M_vCopyVector(&stGlobalMaxPoint, &stMaxPoint);
	}
	else
	{
		stGlobalMinPoint.xX = (stGlobalMinPoint.xX < stMinPoint.xX) ? stGlobalMinPoint.xX : stMinPoint.xX;
		stGlobalMinPoint.xY = (stGlobalMinPoint.xY < stMinPoint.xY) ? stGlobalMinPoint.xY : stMinPoint.xY;
		stGlobalMinPoint.xZ = (stGlobalMinPoint.xZ < stMinPoint.xZ) ? stGlobalMinPoint.xZ : stMinPoint.xZ;
		stGlobalMaxPoint.xX = (stGlobalMaxPoint.xX > stMaxPoint.xX) ? stGlobalMaxPoint.xX : stMaxPoint.xX;
		stGlobalMaxPoint.xY = (stGlobalMaxPoint.xY > stMaxPoint.xY) ? stGlobalMaxPoint.xY : stMaxPoint.xY;
		stGlobalMaxPoint.xZ = (stGlobalMaxPoint.xZ > stMaxPoint.xZ) ? stGlobalMaxPoint.xZ : stMaxPoint.xZ;
	}

}
//END CPA2 Corneliu Babiuc (TMS_0598) 13-05-98

//CPA2 Corneliu Babiuc (teleportation bug) 24-06-98
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method : EDT_HierarchyEditor::fn_vAddObjectRecursiveToList
// Date   : 26-05-1998
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description : 
//    It appends an object and all its children to a list 
// Parameters:
//  pSuperObject	 - object has to be appended
//  p_lstListByDLL   - list 
//  bSelected        - add or not the object to selected list
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Author      : Corneliu Babiuc
// Modification:
//////////////////////////////////////////////////////////////////////////////////////////////////////

void EDT_HierarchyEditor::fn_vAddObjectRecursiveToList(CPA_SuperObject * pSuperObject, CPA_List<EDT_ListByDLL> * p_lstListByDLL, BOOL bSelected)
{
	EDT_ListByDLL	*pObjectList = NULL, *pListDLL;
	POSITION		pos;

	ASSERT(pSuperObject);
	//find the corresponding DLL for the object
	for (pListDLL = p_lstListByDLL->GetHeadElement(pos); pListDLL; 
		 pListDLL = p_lstListByDLL->GetNextElement(pos))
	{
		if (pSuperObject->GetObjectDLL() == pListDLL->GetDLL())
		{
			pObjectList = pListDLL;
			break;
		}
	}
	// if the object DLL list wasn't found then add a new element
	if (!pObjectList)
	{
		// create the corresponding ListByType
		p_lstListByDLL->AddTail(new EDT_ListByDLL(pSuperObject->GetObjectDLL()));
		pObjectList = p_lstListByDLL->GetTail();
	}
	// add the object
	pObjectList->fn_vUpdateListSelect(pSuperObject, E_lum_Insert, bSelected);
	// next level of the hierarchy
	CPA_SuperObject * pChild = pSuperObject->GetSuperObjectFirstChild();
	while (pChild)
	{
		fn_vAddObjectRecursiveToList(pChild, p_lstListByDLL, FALSE);
		pChild = pSuperObject->GetSuperObjectNextChild(pChild);
	}
}
//END CPA2 Corneliu Babiuc (teleportation bug) 24-06-98


// Begin Silviu Simen 18 August 1998 Cut/Paste Mechanism
BOOL EDT_HierarchyEditor::fn_bObjectIsSpecial() 
{
	// this code assumes that object is selected
	EDT_ListByDLL	*pListSelect;
	POSITION		pos;

	for (pListSelect = M_GetWorld()->GetListOfListByDLL()->GetHeadElement(pos); pListSelect;
		 pListSelect = M_GetWorld()->GetListOfListByDLL()->GetNextElement(pos))
	{
		// if there are selected objects of this type
		if (pListSelect->m_stListConcerned.GetCount())
		{
			// ask the DLL for permission
			if (!pListSelect->GetDLL()->fn_bAcceptModifCut(&pListSelect->m_stListConcerned, C_AsConcernedDLL))
			{
				m_csMessage.Format("%s is a Special Object and must be reinserted in Hierarchy", m_pRegisteredCuttedObject->GetName());
				return TRUE;
			}
		}
	}

	// object is not special
	return FALSE;
}
// End Silviu Simen 18 August 1998 Cut/Paste Mechanism

// Begin Silviu Simen september 1998 Select By Sector and Type
void EDT_HierarchyEditor::fn_vSelectBySectorAndType(void) 
{
	HINSTANCE hOldInst = AfxGetResourceHandle();
    AfxSetResourceHandle (GetDLLIdentity()->hModule);

	EDT_DialogSelectType oDialogBox(GetInterface());

	// do not allow selection outside Hierarchy Editor
/*
	if (GetInterface()->GetEvtEditor() != M_GetCurrentEditor()) 
	{
		M_GetMainWnd()->UpdateStatus("Not in Hierarchy Editor", C_STATUSPANE_INFOS, C_STATUS_NORMAL);
		return ;
	}
*/
	
	oDialogBox.DoModal();
	if (oDialogBox.m_bWasOK) 
	{
		fn_vDoSelectBySectorAndType(oDialogBox.m_csSelSector, oDialogBox.m_ulSelType);
	}

    AfxSetResourceHandle (hOldInst);
}

void EDT_HierarchyEditor::fn_vDoSelectBySectorAndType (CString csSector, unsigned long ulType) 
{
	Position pos;
	CPA_BaseObjectList	*pList;
	CPA_BaseObject		*pBaseObj;
	CPA_SuperObject		*pSObj;
	unsigned long		ulObjType ;
	char				szMessage[100];
	int					iNumberSelected;

	iNumberSelected = 0;
	M_GetWorld()->GetListSelected()->RemoveAll();
	pList = M_GetMainWorld()->m_stListObjectsInSectors.GetListOfSectorByName(csSector);
	

	// set multi select mode 
	m_bMultiSelectMode = TRUE;
	for (pBaseObj = pList->GetHeadElement(pos); pBaseObj;
		 pBaseObj = pList->GetNextElement(pos))
	{
		// check type
		pSObj = (CPA_SuperObject *) pBaseObj;
		ulObjType = HIE_fn_ulGetSuperObjectType(pSObj->GetStruct());

		if ((pSObj->GetType() == C_szSuperObjectTypeName) && (ulObjType == ulType)) 
		{
			// if possible, select it
			if (GetInterface()->fn_bCanSelect(pSObj) == C_Accept)
			{
				GetInterface()->fn_vAddSelectedObject(pSObj, FALSE);
				++ iNumberSelected;
			}
		}
	}
	// unset multi select mode 
	m_bMultiSelectMode = FALSE;

	// update status bar
	M_GetViewPort3d()->fn_vUpdateStatusBarMessage();
	sprintf(szMessage,"Selected %d objects",iNumberSelected);
	if (iNumberSelected)
		M_GetMainWnd()->UpdateStatus(szMessage, C_STATUSPANE_INFOS, C_STATUS_NORMAL);
	else 
		M_GetMainWnd()->UpdateStatus("No object selected", C_STATUSPANE_INFOS, C_STATUS_NORMAL);

	//	make the update of the selection
	GetInterface()->fn_vUpdateAll(E_mc_UpdateSelection);

	M_GetViewPort3d()->SetFocus();
}
// End Silviu Simen september 1998 Select By Sector and Type

#endif // ACTIVE_EDITOR
