//#################################################################################
//
// BASE CLASS OF YOUR DLL interface
//
//#################################################################################

#ifdef ACTIVE_EDITOR

#include "stdafx.h"
#include "ACP_Base.h"
#include "itf.h"
#include "gmt.h"
#include "incgam.h"
#include "dpt.h"
#include "ogd.h"
#include "scr.h"
#include "gli.h"
#include "po.h"
#include "_interf.hpp"
#include "DiaMeca.hpp"
#include "DiaSound.hpp"
#include "DiaCol.hpp"
#include "DiaView.hpp"
#include "DiaMain.hpp"
#include "DiaText.hpp"
#include "DiaList.hpp"
#include "MatList.hpp"
#include "GMatObj.hpp"
#include "VMatObj.hpp"
#include "MMatObj.hpp"
#include "CMatObj.hpp"
#include "TexObj.hpp"
#include "TextureDlg.h"
#include "TGMdef.hpp"
#include "x:\cpa\main\inc\_editid.h"

//Mircea Dunka 9.11.98
/* SHA_TEMP
#define __MSC__
#include <glide.h>
//end Mircea Dunka
*/

// infos
static CString g_csTGMName = "Material";
static CString g_csTGMAuthor = "Y. Le Tensorer & B. Germain";
static CString g_csTGMVersion = "V 2.0.3   01/04/98";
static CString g_csTGMFrenchHelpFile = "Materiau.hlp";
static CString g_csTGMEnglishHelpFile = "";

BOOL g_bTipFirstTime = TRUE;

tdstDLLIdentity g_stMaterialIdentity;
extern Material_Interface *gs_p_oMaterialInterface;

// the Keyboard configuration
#define KA_TGM_EDITPICKEDMATERIALMODE 1
#define KA_TGM_SPLITTARGETONDROPMODE  2
static tdstKeyboardActionDef gs_a_stAppKeys[] =
{
  {"Select material under cursor", KA_TGM_EDITPICKEDMATERIALMODE},
//CPA2 Corneliu Babiuc 27-05-98
//  {"Split target on drop", KA_TGM_SPLITTARGETONDROPMODE},
    {"Drop material", KA_TGM_SPLITTARGETONDROPMODE},
//END CPA2 Corneliu Babiuc 27-05-98
  {NULL, 0},
};

FILE *g_xLogFile = NULL;

static long gs_lNbPreviousMaterialsInLinkTable = 0;
static long gs_lNbPreviousGeomobjInLinkTable = 0;

#define C_uiSubMenuOpen	1
#define C_uiSubMenuSavePrefs 2
#define C_uiSubMenuDeactivateWarnings 3
#define C_uiSubMenuShowMaterial	4

//left splitter
#define C_wMainPaneId 0
#define C_wCollidePaneId 1
#define C_wMechanicsPaneId 2
#define C_wSoundPaneId 3
#define C_wVisualPaneId 4

//bottom splitter
#define C_wTexturePaneId 0
#define C_wListPaneId 1

//ANNECY Shaitan DisableFunctions (16/04/98) {
BOOL g_bMasterEditor = FALSE;
//ENDANNECY Shaitan DisableFunctions }

//================================================================================
// CONSTRUCTOR.
// You must put here all your DLL interface definitions.
//================================================================================
Material_Interface::Material_Interface(void)
{
	// ************************** private internal
	m_p_stDLLIdentity = &g_stMaterialIdentity;

	// Does your DLL can output in main game view ?
	m_stBaseDLLDefinition.bCanOutputIn3DView = TRUE;

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

    SetEditorInfo(g_csTGMName, g_csTGMAuthor, g_csTGMVersion, g_csTGMFrenchHelpFile, g_csTGMEnglishHelpFile);
	//m_bIsActivated = FALSE;
	//m_bIsSelected = FALSE;
	m_eRefreshListsMode = E_rlm_DoNothing;
	m_bModeIsMaterialSelect = FALSE;
	m_bModeIsIndexedTriangleSplit = FALSE;
	m_p_oLeftSplitFrame = NULL;
	m_p_oBottomSplitFrame = NULL;
	m_p_oMaterialListView = NULL;
	m_p_oMaterialView = NULL;
	m_p_oMaterialMeca = NULL;
	m_p_oMaterialMain = NULL;
	m_p_oTextureDialog = NULL;
	m_p_oWorldRoot = NULL;
	m_p_oTextureDlg = NULL;
	m_bEnteredEditorAtLeastOnce = FALSE;
	GMT_fn_vInvalidate(&m_hQueriedDefaultGameMaterial);
	m_bCanSaveModifs = TRUE;
	m_bTexturesLoaded = FALSE;
    m_p_oKeyConfiguration = NULL;
	m_eLoadWarningsActivation = E_am_Never;
	m_bDisplayMaterialUnderCursor = TRUE;

	m_oTextureList.m_fn_vCreate(
		C_cFixedSize, //all images will have the same size
		C_wTextureSize, //this width
		C_wTextureSize, //this height
		TRUE, //load only optimized textures
		TRUE //create small copies if necessary
	);

	g_xLogFile = fopen("TGM.log", "w");
	if ( g_xLogFile )
	{
		fprintf(g_xLogFile, "DLL compiled on " __DATE__ " " __TIME__ "\n");
		fflush(g_xLogFile);
	}

	//Mircea Dunka 12.11.1997
	m_bGetGlidePixel = FALSE;
	//end Mircea Dunka
}


Material_Interface::~Material_Interface(void)
{
	ASSERT(m_oHighlightList.IsEmpty());

	if ( m_p_oLeftSplitFrame )
		delete m_p_oLeftSplitFrame;

	if ( m_p_oBottomSplitFrame )
		delete m_p_oBottomSplitFrame;

	if ( m_p_oMaterialListView )
		delete m_p_oMaterialListView;

	if ( m_p_oMaterialView )
		delete m_p_oMaterialView;

	if ( m_p_oMaterialMeca )
		delete m_p_oMaterialMeca;

	if ( m_p_oMaterialMain )
		delete m_p_oMaterialMain;

	if ( m_p_oTextureDlg )
		delete m_p_oTextureDlg;

	if ( m_p_oKeyConfiguration )
	  delete m_p_oKeyConfiguration;
}

//**************************************************************************************
//Begin Mircea Dunka 31 Aug 1998 - DialogBar interface
void Material_Interface::fn_vDefineDlgBarBtnIcon (tde_DlgBarCategory wCategory, tds_DlgBarBtn *_pDlgBarBtn)
{
	if(wCategory == C_DlgBarCategoryEditor)
	{
		_pDlgBarBtn->hIcon = ::LoadIcon((HINSTANCE)(GetDLLIdentity()->hModule), MAKEINTRESOURCE(IDI_TGM_DLGBAR_ICON));
		CString oCst;
        oCst = "Material";
        if( (M_GetMainApp()) && (M_GetMainApp()->mp_oAppKeyboard) )
        {
            oCst += "  (";
            oCst += M_GetMainApp()->mp_oAppKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Activate Material Editor"));
			oCst += ")";
        }
		strcpy(_pDlgBarBtn->szToolTip, (char*)(LPCTSTR)oCst);
		_pDlgBarBtn->uID = (UINT)this;
	}
}
//end Mircea Dunka 31 Aug 1998

//================================================================================
//================================================================================
BOOL Material_Interface::fn_bDefineSubMenu(EDT_SubMenu *_p_oEDTSubMenu)
{
	if ( _p_oEDTSubMenu -> GetSubMenuType() == C_SubMenuEditor )
	{
		CString csEntry;
		csEntry = "Material";
		csEntry += "\t";
		csEntry += M_GetMainApp()->mp_oAppKeyboard->mfn_oConvertIniStringToKeyString((const CString*)&CString("Activate Material Editor"));;
		_p_oEDTSubMenu -> AddAnEntry( this, (char *)LPCTSTR(csEntry), C_uiSubMenuOpen, fn_bIsCurrentEditor());
		return TRUE;
	}
	else if ( _p_oEDTSubMenu->GetSubMenuType() == C_SubMenuSpecific ) //only sent to current editor
	{
		// submenu "Specific"
		CString csMenuString("Current Load Warnings: ");
		switch ( m_eLoadWarningsActivation )
		{
		case E_am_Never:
			csMenuString += C_szActivationModeNever;
			break;

		case  E_am_Once:
			csMenuString += C_szActivationModeOnce;
			break;

		case  E_am_Always:
			csMenuString += C_szActivationModeAlways;
			break;
		}
		_p_oEDTSubMenu->AddAnEntry(this, (char *) LPCTSTR(csMenuString), C_uiSubMenuDeactivateWarnings);
		_p_oEDTSubMenu->AddAnEntry(this, "Show Material under cursor", C_uiSubMenuShowMaterial, m_bDisplayMaterialUnderCursor);
		_p_oEDTSubMenu->AddASeparator();
		_p_oEDTSubMenu->AddAnEntry(this, "Save Dialogs Dimensions", C_uiSubMenuSavePrefs);
		return TRUE;
	}
	return FALSE;
}

//================================================================================
//================================================================================
void Material_Interface::_OnSubMenuCommand(EDT_SubMenu * /*_p_oEDTSubMenu*/,UINT uiMsgID)
{
	if( uiMsgID == C_uiSubMenuOpen )
	{
		if  (fn_bIsCurrentEditor())
		  GetMainWorld()-> fn_bCloseEditor ( this );
		else
		  GetMainWorld()-> fn_bActivateEditor (this, NULL );
		// envoie la commande onactivate...
		//M_GetMainWnd() -> MessageBox("MATERIAL","OPEN",MB_OK);
	}
	else if ( uiMsgID == C_uiSubMenuSavePrefs )
	{
		m_vSavePreferences();
	}
	else if ( uiMsgID == C_uiSubMenuDeactivateWarnings )
	{
		//swap the activation of the load warnings
		CString csOptionString;
		switch ( m_eLoadWarningsActivation )
		{
		case E_am_Never:
			m_eLoadWarningsActivation = E_am_Once;
			csOptionString = C_szActivationModeOnce;
			break;

		case  E_am_Once:
			m_eLoadWarningsActivation = E_am_Always;
			csOptionString = C_szActivationModeAlways;
			break;

		case  E_am_Always:
			m_eLoadWarningsActivation = E_am_Never;
			csOptionString = C_szActivationModeNever;
			break;
		}
		//get the config file name
		CString	csFileName = M_GetMainApp()->m_csEditorDataPath + "Tools\\Material\\Material.ini";
		char *p_szFileName = (char*)(LPCSTR)csFileName;
		//and update the corresponding entry
		WritePrivateProfileString(
			C_szPreferencesProfileSection, 
			C_szLoadWarningsActivationProfileString,	
			csOptionString, 
			p_szFileName
		);
		//flush file write queue
		WritePrivateProfileString (NULL, NULL, NULL, p_szFileName);
	}
	else if ( uiMsgID == C_uiSubMenuShowMaterial )
	{
		m_bDisplayMaterialUnderCursor = ! m_bDisplayMaterialUnderCursor;
	}
}

//================================================================================
//================================================================================
void Material_Interface::m_vSetEditedMaterial(tdoEditorGameMaterial *_p_oMaterial)
{
	if ( /*_p_oMaterial &&*/ _p_oMaterial != m_p_oGetEditedMaterial() )
		m_p_oGetMaterialListView()->m_fn_vSelectMaterial(_p_oMaterial);
}

//================================================================================
//================================================================================
tdoEditorGameMaterial *Material_Interface::m_p_oGetEditedMaterial()
{
	long lSelectecIndex = m_p_oGetMaterialListView()->m_fn_lGetSelectedItem();
	return (tdoEditorGameMaterial *)
	((lSelectecIndex >= 0) ? m_p_oGetMaterialListView()->m_fn_lGetContent(lSelectecIndex) : NULL);
}

//================================================================================
//================================================================================
void Material_Interface::fn_vJustAfterRegistered(void)
{
	//----------------------------------------- declare the type name
	CString apszName[] =
	{
		C_szGameMaterialTypeName,
		C_szVisualMaterialTypeName,
		C_szMechanicsMaterialTypeName,
		C_szCollideMaterialTypeName,
		C_szTextureTypeName,
		C_szMaterialColName
	};
	fn_vRegisterObjectsType(apszName,6);

	/* scrpit register */
	m_p_oGetCollView()->m_fn_vInitLoad(); // collision names
	m_p_oGetMecaView()->m_fn_vInitLoad(); // mecanic default values
}

//================================================================================
//================================================================================
void Material_Interface::fn_vConstruct(void)
{
#ifndef __INACTIVE_INTERFACE__
	CString	csFileName = M_GetMainApp()->m_csEditorDataPath + "Tools\\Material\\Material.ini";
	char *p_szFileName = (char*)(LPCSTR)csFileName;
	char sz20ProfileDimension[20];

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

//ANNECY Shaitan DisableFunctions (16/04/98) {
	GetPrivateProfileString ("Status", "MasterEditor", "No", sz20ProfileDimension, 20, p_szFileName);
	g_bMasterEditor = !stricmp(sz20ProfileDimension,"Yes");
//ENDANNECY Shaitan DisableFunctions }

	m_p_oLeftSplitFrame = new CSplitFrame();
	m_p_oLeftSplitFrame->CreateBase( "Edition", 1, 2, M_GetMainWorld());
	m_p_oLeftSplitFrame->CreateSplitter(C_cVerticalSplitter, 5);

	// set Display Material Under cursor options
	GetPrivateProfileString(C_szPreferencesProfileSection, C_szDisplayMaterialUnderCursorProfileString, "TRUE", sz20ProfileDimension, 20, p_szFileName);
	m_bDisplayMaterialUnderCursor = !stricmp(sz20ProfileDimension,"TRUE");
	// create views into the 4 splitters
	GetPrivateProfileString(C_szPreferencesProfileSection, C_szVisualPaneHeightProfileString, C_szDefaultVisualPaneHeight, sz20ProfileDimension, 20, p_szFileName);
	m_p_oLeftSplitFrame->CreateView(C_wVisualPaneId, RUNTIME_CLASS(DiaView), "Visual", atoi(sz20ProfileDimension));
	GetPrivateProfileString(C_szPreferencesProfileSection, C_szMechanicsPaneHeightProfileString, C_szDefaultMechanicsPaneHeight, sz20ProfileDimension, 20, p_szFileName);
	m_p_oLeftSplitFrame->CreateView(C_wMechanicsPaneId, RUNTIME_CLASS(DiaMeca), "Mechanics", atoi(sz20ProfileDimension));
	GetPrivateProfileString(C_szPreferencesProfileSection, C_szSoundPaneHeightProfileString, C_szDefaultSoundPaneHeight, sz20ProfileDimension, 20, p_szFileName);
	m_p_oLeftSplitFrame->CreateView(C_wSoundPaneId, RUNTIME_CLASS(DiaSound), "Sound", atoi(sz20ProfileDimension));
	GetPrivateProfileString(C_szPreferencesProfileSection, C_szCollidePaneHeightProfileString, C_szDefaultCollidePaneHeight, sz20ProfileDimension, 20, p_szFileName);
	m_p_oLeftSplitFrame->CreateView(C_wCollidePaneId, RUNTIME_CLASS(DiaCol), "Collision", atoi(sz20ProfileDimension));
	GetPrivateProfileString(C_szPreferencesProfileSection, C_szMainPaneHeightProfileString, C_szDefaultMainPaneHeight, sz20ProfileDimension, 20, p_szFileName);
	m_p_oLeftSplitFrame->CreateView(C_wMainPaneId, RUNTIME_CLASS(DiaMain), "Main", atoi(sz20ProfileDimension));
	//set the width of the frame
	GetPrivateProfileString(C_szPreferencesProfileSection, C_szLeftPaneWidthProfileString, C_szDefaultLeftPaneWidth, sz20ProfileDimension, 20, p_szFileName);
	m_p_oLeftSplitFrame->m_iInitWidth = atoi(sz20ProfileDimension);
	//init other stuff
	m_p_oLeftSplitFrame->m_iInitHeight = 0;
	m_p_oLeftSplitFrame->mfn_vEnableCaption(FALSE);
	m_p_oLeftSplitFrame->m_stWinTop.cLinkSame = FRM_C_MoveRight;

	m_p_oBottomSplitFrame = new CSplitFrame();
	m_p_oBottomSplitFrame->CreateBase("Material List", 2, 3, M_GetMainWorld());
	m_p_oBottomSplitFrame->CreateSplitter(C_cHorizontalSplitter, 2);

	//create views into the 2 splitters
	//M_FRMAssociateView(m_p_oBottomSplitFrame, CMaterialListView);
	GetPrivateProfileString(C_szPreferencesProfileSection, C_szTexturePaneWidthProfileString, C_szDefaultTexturePaneWidth, sz20ProfileDimension, 20, p_szFileName);
	m_p_oBottomSplitFrame->CreateView(C_wTexturePaneId, RUNTIME_CLASS(DiaText), "Texture", atoi(sz20ProfileDimension));
	GetPrivateProfileString(C_szPreferencesProfileSection, C_szListPaneWidthProfileString, C_szDefaultListPaneWidth, sz20ProfileDimension, 20, p_szFileName);
	m_p_oBottomSplitFrame->CreateView(C_wListPaneId, RUNTIME_CLASS(CMaterialListView), "Materials", atoi(sz20ProfileDimension));
	//set the initial height of the pane
	m_p_oBottomSplitFrame->mfn_vEnableCaption(FALSE);
	GetPrivateProfileString(C_szPreferencesProfileSection, C_szMaterialListHeightProfileString, C_szDefaultMaterialListHeight, sz20ProfileDimension, 20, p_szFileName);
	m_p_oBottomSplitFrame->m_iInitHeight = atoi(sz20ProfileDimension);

	// gets pointers to the dialog boxes
	m_p_oMaterialMeca = (DiaMeca *) m_p_oLeftSplitFrame->m_fn_p_oGetPane(C_wMechanicsPaneId);
	m_p_oMaterialSound = (DiaSound *) m_p_oLeftSplitFrame->m_fn_p_oGetPane(C_wSoundPaneId);
	m_p_oMaterialCol = (DiaCol *) m_p_oLeftSplitFrame->m_fn_p_oGetPane(C_wCollidePaneId);
	m_p_oMaterialView = (DiaView *) m_p_oLeftSplitFrame->m_fn_p_oGetPane(C_wVisualPaneId);
	m_p_oMaterialMain = (DiaMain *) m_p_oLeftSplitFrame->m_fn_p_oGetPane(C_wMainPaneId);
	m_p_oMaterialListView = ((CMaterialListView *) m_p_oBottomSplitFrame->m_fn_p_oGetPane(C_wListPaneId))/*->m_p_oMaterialListView*/;
	m_p_oTextureDialog = (DiaText *) m_p_oBottomSplitFrame->m_fn_p_oGetPane(C_wTexturePaneId);

	//build the dialog to choose a texture, and share the bitmap list with the other view
	m_p_oTextureDlg = new CTextureDlg;
	m_p_oMaterialListView->m_fn_vSetBitmapList(&m_oTextureList);

	// Setup Keyboard Preferences
	m_p_oKeyConfiguration = new CPA_KeyActionConfiguration("Material\\Material.ini", gs_a_stAppKeys);
	m_p_oKeyConfiguration->mfn_vSetObjectName("Material Editor");

	//load the warning config preference
	GetPrivateProfileString(C_szPreferencesProfileSection, C_szLoadWarningsActivationProfileString, C_szDefaultLoadWarningsActivation, sz20ProfileDimension, 20, p_szFileName);
	if ( !strcmp(sz20ProfileDimension, C_szActivationModeNever) )
		m_eLoadWarningsActivation = E_am_Never;
	else if ( !strcmp(sz20ProfileDimension, C_szActivationModeOnce) )
		m_eLoadWarningsActivation = E_am_Once;
	else if ( !strcmp(sz20ProfileDimension, C_szActivationModeAlways) )
		m_eLoadWarningsActivation = E_am_Always;
	else
		m_eLoadWarningsActivation = E_am_InvalidMode;
	AfxSetResourceHandle( hOldInst );
#endif /* !__INACTIVE_INTERFACE__ */
}

//================================================================================
//================================================================================
void Material_Interface::fn_vOnActivateEditor(CPA_List<CPA_BaseObject> * /*pParams*/, BOOL /*bBackActivated*//*=FALSE*/)
{
	/*
	int iSwapBuf;
	iSwapBuf = g_oFrameGest.ma_iOrder[1][2];
	g_oFrameGest.ma_iOrder[1][2] = g_oFrameGest.ma_iOrder[2][3];
	g_oFrameGest.ma_iOrder[2][3] = iSwapBuf;
	*/
	if ( !m_bEnteredEditorAtLeastOnce )
	{
		m_bEnteredEditorAtLeastOnce = TRUE;
		if ( m_eRefreshListsMode != E_rlm_DoNothing )
			m_vDoRefreshLists(0, m_eRefreshListsMode, TRUE);

		CString csLevelName(fn_p_szGetLevelName());
		csLevelName += tdoEditorGameMaterial::m_csGetScriptExtension();
		short wIndex = ((CComboBox *) m_p_oGetMainView()->GetDlgItem(IDC_COMBO_FILE))->FindStringExact(CB_ERR, csLevelName);
		if ( wIndex != CB_ERR )
		{
			((CComboBox *) m_p_oGetMainView()->GetDlgItem(IDC_COMBO_FILE))->SetCurSel(wIndex);
			m_p_oGetMainView()->m_vReflectFileSelectionChange();
		}
	}
	//m_bIsSelected = TRUE;
	m_vShowEditor();

	// display Tip of the Day
	GetInterface()->fn_vDisplayTipOfDay("Materials", "TGM", g_bTipFirstTime);
	g_bTipFirstTime = FALSE;
}

//================================================================================
//================================================================================
void Material_Interface::fn_vOnCloseEditor(void)
{
	/*
	int iSwapBuf;
	iSwapBuf = g_oFrameGest.ma_iOrder[1][2];
	g_oFrameGest.ma_iOrder[1][2] = g_oFrameGest.ma_iOrder[2][3];
	g_oFrameGest.ma_iOrder[2][3] = iSwapBuf;
	*/
	//m_bIsSelected = FALSE;
	m_vHideEditor();
}

//================================================================================
//================================================================================
void Material_Interface::m_fn_vShowMaterialAll(tdoEditorGameMaterial *_p_oMaterial /*= NULL*/)
{
	tdoEditorGameMaterial *p_oMaterial = _p_oMaterial ? _p_oMaterial : m_p_oGetEditedMaterial();
	GMT_tdxHandleToGameMaterial hMaterial;

	if ( p_oMaterial )
	{
		m_vSetEditedMaterial(p_oMaterial);
		hMaterial = p_oMaterial->m_hGetEngineMaterial();
	}
	else
		GMT_fn_vInvalidate(&hMaterial);

	m_p_oGetVisualView()->m_fn_vShowMaterial(hMaterial);
	m_p_oGetMecaView()->m_fn_vShowMaterial(hMaterial);
	m_p_oGetSoundView()->m_fn_vShowMaterial(hMaterial);
	m_p_oGetCollView()->m_fn_vShowMaterial(hMaterial);
	m_p_oGetMainView()->m_fn_vShowMaterial(hMaterial);
	//do not call the texture view display method, because the visual material view has taken care of that
}

//================================================================================
//================================================================================
void Material_Interface::m_vShowEditor()
{
	//update links in the coherence manager
	m_vRefreshMaterialSuperObjectLinks();
	//make the listview display the materials currently used by the engine
	m_p_oGetMaterialListView()->m_vRefreshDisplayedMaterialList(
		m_p_oGetMaterialListView()->m_bAllMaterialsDisplayed()
	);
	//refresh lists if necessary (no action override)
	//m_vDoRefreshLists(0, E_rlm_DoNothing, !m_bTexturesLoaded);

	// activate the frames of the editor
	HWND WindowWithFocus = GetFocus ();

	if ( m_p_oLeftSplitFrame )
		g_oFrameGest.mfn_vActivateWindow(m_p_oLeftSplitFrame);

	if ( m_p_oBottomSplitFrame )
		g_oFrameGest.mfn_vActivateWindow(m_p_oBottomSplitFrame);

	SetFocus(WindowWithFocus);
}

//================================================================================
//================================================================================
void Material_Interface::m_vHideEditor()
{
	if ( m_p_oLeftSplitFrame != NULL )
		g_oFrameGest.mfn_vDisactivateWindow(m_p_oLeftSplitFrame);

	if ( m_p_oBottomSplitFrame != NULL )
		g_oFrameGest.mfn_vDisactivateWindow(m_p_oBottomSplitFrame);
}

//================================================================================
//================================================================================
void Material_Interface::fn_vBeforeEngine(void)
{
	if ( fn_bIsCurrentEditor() )
		m_vHideEditor();

	//copy the current value of each game material back in its initial value
/*
	CPA_BaseObjectList *p_oGameMaterialList = GetBaseObjectList(C_szGameMaterialTypeName);
	Position xPos = p_oGameMaterialList->GetHeadPosition();
	while ( xPos ) //for each game material
	{
		tdoEditorGameMaterial *p_oGameMaterial = (tdoEditorGameMaterial *) p_oGameMaterialList->GetNext(xPos);
		if ( p_oGameMaterial->fn_bIsAvailable() )
			GMT_fn_vSetGameMaterialInitialValues(p_oGameMaterial->m_hGetEngineMaterial());
	}
*/
}

//================================================================================
//================================================================================
void Material_Interface::fn_vBeforeEditor(void)
{
	//since the materials may change in the engine, restore the initial values
	CPA_BaseObjectList *p_oGameMaterialList = GetBaseObjectList(C_szGameMaterialTypeName);
	Position xPos = p_oGameMaterialList->GetHeadPosition();
/*	while ( xPos ) //for each game material
	{
		tdoEditorGameMaterial *p_oGameMaterial = (tdoEditorGameMaterial *) p_oGameMaterialList->GetNext(xPos);
		if ( p_oGameMaterial->fn_bIsAvailable() )
			GMT_fn_vReInitializeGameMaterial(p_oGameMaterial->m_hGetEngineMaterial());
	}
*/	//now we can show the editor if relevant
	if ( fn_bIsCurrentEditor() )
		m_vShowEditor();
}

//================================================================================
//called before the world is sent to the list, if we want to change anything
//================================================================================
/*virtual*/ void Material_Interface::fn_vBeforeDrawingWorld(GLD_tdstViewportAttributes *p1, GLI_tdxHandleToLight p2, DEV_ViewPort* p3)
{
	ASSERT(m_oHighlightList.IsEmpty());
	//get the list of game materials
	CPA_BaseObjectList *p_oGameMaterialList = GetBaseObjectList(C_szGameMaterialTypeName);
	Position xPos = p_oGameMaterialList->GetHeadPosition();
	while ( xPos ) //for each game material
	{
		tdoEditorGameMaterial *p_oGameMaterial = (tdoEditorGameMaterial *) p_oGameMaterialList->GetNext(xPos);
		if ( p_oGameMaterial->fn_bIsAvailable() )
		{
			//get its associated engine collide and mechanics materials
			GMT_tdxHandleToGameMaterial hGameMaterial = p_oGameMaterial->m_hGetEngineMaterial();
			DNM_tdxHandleToMecMatCharacteristics hMaterialMechanics = GMT_fn_hGetMechanicsMaterial(hGameMaterial);
			GMT_tdxHandleToCollideMaterial hMaterialCollide = GMT_fn_hGetCollideMaterial(hGameMaterial);
			//get the associated editor submaterials
			tdoEditorCollideMaterial *p_oCollideMaterial = (tdoEditorCollideMaterial *) m_p_oGetEditorObjectForEngine(hMaterialCollide);
			tdoEditorMechanicsMaterial *p_oMechanicsMaterial = (tdoEditorMechanicsMaterial *) m_p_oGetEditorObjectForEngine(hMaterialMechanics);
			//get their highlight color, if relevant
			short wDoHighlight = 0;
			GEO_tdstColor stMecaColor = { 0.0, 0.0, 0.0, 0.0 } , stCollideColor = { 0.0, 0.0, 0.0, 0.0 };
			if ( p_oCollideMaterial && p_oCollideMaterial->m_bGetHighlightColor(&stCollideColor) )
				wDoHighlight ++;
			if ( p_oMechanicsMaterial && p_oMechanicsMaterial->m_bGetHighlightColor(&stMecaColor) )
				wDoHighlight ++;
			//at least one is highlighted
			if ( wDoHighlight )
			{
				//create a highlight item
				tdstHighlightItem *p_stItem = new tdstHighlightItem;
				//remember for which game material
				p_stItem->hGameMaterial = hGameMaterial;
				//remember its original visual material
				p_stItem->hOriginalVisualMaterial = GMT_fn_hGetVisualMaterial(hGameMaterial);
				//build a new visual material for highlighting (its a copy)
				GLI_xDuplicateMaterial(&p_stItem->hHighlightVisualMaterial, p_stItem->hOriginalVisualMaterial);
				//compute the average highlight color
				stMecaColor.xR = (stMecaColor.xR + stCollideColor.xR) / wDoHighlight;
				stMecaColor.xG = (stMecaColor.xG + stCollideColor.xG) / wDoHighlight;
				stMecaColor.xB = (stMecaColor.xB + stCollideColor.xB) / wDoHighlight;
				//and set it in the highlight visual material for all colors, so that we see it...
				unsigned long xType;
				GLI_xGetMaterialType(p_stItem->hHighlightVisualMaterial, &xType);
				if ( xType & GLI_C_lIsTextured )
				{
					//make the engine not display the texture
					xType &= ~GLI_C_lIsTextured;
					xType &= ~GLI_C_lIsNotForceColorMaterial;
					//make the engine use the color attributes
					GLI_xSetMaterialType(p_stItem->hHighlightVisualMaterial, xType);
					//GLI_xSetMaterialTexture(p_stItem->hHighlightVisualMaterial, NULL);
				}
				GLI_xSetMaterialAmbientCoef(p_stItem->hHighlightVisualMaterial, &stMecaColor);
				GLI_xSetMaterialDiffuseCoef(p_stItem->hHighlightVisualMaterial, &stMecaColor);
				GLI_xSetMaterialSpecularCoef(p_stItem->hHighlightVisualMaterial, 1, &stMecaColor);
				//remove the texture so that we see it even better, especially for some faces whose aspect wont change if we dont...
				//give the temporary visual material to the game material
				GMT_fn_vSetVisualMaterial(p_stItem->hGameMaterial, p_stItem->hHighlightVisualMaterial);
				//then add it to the list, so that we can restore the visual material once the display is updated
				m_oHighlightList.AddTail(p_stItem);
			}
		}
	}
}
//================================================================================
//called after the list is sent to the viewport
//-> changes will not affect display, but we can add thing in the list if we want
//================================================================================
/*virtual*/ void Material_Interface::fn_vAddObjectsToDraw(GLD_tdstViewportAttributes *p1, GLI_tdxHandleToLight p2, DEV_ViewPort* p3)
{
	while ( !m_oHighlightList.IsEmpty() )
	{
		tdstHighlightItem *p_stItem = m_oHighlightList.RemoveHead();
		GMT_fn_vSetVisualMaterial(p_stItem->hGameMaterial, p_stItem->hOriginalVisualMaterial);
		GLI_xDeleteMaterial(p_stItem->hHighlightVisualMaterial);
		delete p_stItem;
	}
}

//================================================================================
//called after the list is displayed -> the screen has changed when we receive this
//================================================================================
/*virtual*/ void Material_Interface::fn_vAddObjectsToDraw2(GLD_tdstViewportAttributes *p1, GLI_tdxHandleToLight p2)
{
}

//================================================================================
//================================================================================
BOOL Material_Interface::fn_bDefinePopupMenu
(
	EDT_PopUpMenu *pPopup,
	CPA_List<CPA_SuperObject> * /*pSelection*/,
	BOOL bAsCurrentEditor
)
{
	if ( bAsCurrentEditor )
	{
		pPopup->AddAnEntry(this, "Exit Material editor", 0);
		tdoEditorGameMaterial *p_oCurrentMaterial = m_p_oGetEditedMaterial();
		if ( m_p_oGetCurrentFileObject() && p_oCurrentMaterial )
			pPopup->AddAnEntry(this, (char*)LPCTSTR(CString("Drop material '") + p_oCurrentMaterial->GetName() + "' under cursor"), 1);
		CPoint oScreenPos;
		GetCursorPos(&oScreenPos);
		m_vFindMaterialUnderCursor(oScreenPos, FALSE);
		if ( m_p_oMaterialUnderCursor )
			pPopup->AddAnEntry(this, (char*)LPCTSTR(CString("Edit material '") + m_p_oMaterialUnderCursor->GetName() + "'"), 2);
		
/* SHA_TEMP
		//Mircea Dunka 03.11.1998
		if(m_bGetGlidePixel)
			pPopup->AddAnEntry(this, "Stop Pixel Capture", 3);
		else
			pPopup->AddAnEntry(this, "Start Pixel Capture", 3);
		//end Mircea Dunka
*/
		return TRUE;
	}

	return FALSE;
}

//================================================================================
//================================================================================
void Material_Interface::_OnPopUpMenuCommand(UINT _IDCmdMsg)
{
	switch ( _IDCmdMsg )
	{
	case 0: //exit material editor
		/*m_bIsSelected = !*/GetMainWorld()->fn_bCloseEditor(this);
	  break;

	case 1: //drop the current material on the object under the cursor when the popup menu was opened
		m_p_oGetMaterialListView()->m_vApplyCurrentMaterialToObjectUnderCursor((HIE_tdstPickInfo *) m_a_stPickInfo);
		break;

	case 2: //make the editor select the material under the cursor when the popup menu was opened
		m_bEditPickedMaterial((HIE_tdstPickInfo *) m_a_stPickInfo);
		break;
/* SHA_TEMP
	//Mircea Dunka 03.11.1998
	case 3:
		m_bGetGlidePixel = !m_bGetGlidePixel ;
		break;
	//end Mircea Dunka
*/
	default:
		break;
	}
}

//================================================================================
//================================================================================
BOOL Material_Interface::_OnKeyDown(UINT _nChar, UINT /*nRepCnt*/, UINT /*nFlags*/)
{
	if ( fn_bIsCurrentEditor() )
	{
		switch ( m_p_oKeyConfiguration->mfn_uwKeyToAction(_nChar) )
		{
		case KA_TGM_EDITPICKEDMATERIALMODE:
			if ( !m_bModeIsMaterialSelect )
			{
				m_bModeIsMaterialSelect = TRUE;
				fn_vGiveProgressInfo("pick an object to select its material", -1);
			}
			return TRUE;

		case KA_TGM_SPLITTARGETONDROPMODE:
			if ( !m_bModeIsIndexedTriangleSplit )
			{
				m_bModeIsIndexedTriangleSplit = TRUE;
				fn_vGiveProgressInfo("drop the dragged material on one face only", -1);
			}
			return TRUE;
		}
	}
	return FALSE;
}

//================================================================================
//================================================================================
BOOL Material_Interface::_OnKeyUp(UINT _nChar, UINT /*nRepCnt*/, UINT /*nFlags*/)
{
	if ( fn_bIsCurrentEditor() )
	{
		switch ( m_p_oKeyConfiguration->mfn_uwKeyToAction(_nChar) )
		{
		case KA_TGM_EDITPICKEDMATERIALMODE:
			m_bModeIsMaterialSelect = FALSE;
			fn_vGiveProgressInfo("", -1);
			return TRUE;

		case KA_TGM_SPLITTARGETONDROPMODE:
			m_bModeIsIndexedTriangleSplit = FALSE;
			fn_vGiveProgressInfo("", -1);
			return TRUE;
		}
	}
	return FALSE;
}

//================================================================================
//================================================================================
void Material_Interface::m_vFindMaterialUnderCursor(CPoint _oPoint, BOOL _bVerbose /*= FALSE*/)
{
	m_p_oMaterialUnderCursor = NULL;
	if ( xGetPickInfoUnderPoint(&m_a_stPickInfo, _oPoint) )
	{
		Geometry3D *p_oGeometry = (Geometry3D*) GetMainWorld()
		->fn_p_oFindObjectWithEngine(
			m_a_stPickInfo[0].hGeoObject,
			C_szGeometricObjectTypeName
		);
		if ( p_oGeometry && m_bDisplayMaterialUnderCursor )
		{
			ACP_tdxIndex xPickedElement = m_a_stPickInfo[0].stPickedObject.aDEF_stDataOfElement[0].xElements;
			m_p_oMaterialUnderCursor = (tdoEditorGameMaterial *) p_oGeometry->fn_p_oGetGameMaterial(xPickedElement, 0);
			if ( _bVerbose )
			{
				if ( m_p_oMaterialUnderCursor )
				{
					CString csMessageStart(m_bModeIsMaterialSelect ? "Edit material '" : "Material under cursor is '");
					csMessageStart += m_p_oMaterialUnderCursor->GetName()
					+ "' from file " + ((CPA_FileObject *) m_p_oMaterialUnderCursor->GetOwner())->GetReferencedName(this, C_szFileReferencedNameKey)
					+ " of object '" + p_oGeometry->GetName() + "'";
					fn_vGiveProgressInfo(csMessageStart, -1);
				}
				else
					fn_vGiveProgressInfo(CString("Object ") + p_oGeometry->GetName() + " has no associated material", -1, C_STATUS_WARNING);
			}
		}
		else if ( _bVerbose && m_bDisplayMaterialUnderCursor)
			fn_vGiveProgressInfo("there is no object under the cursor", -1, C_STATUS_WARNING);
		else
			fn_vGiveProgressInfo("", -1);
	}
}

//================================================================================
//================================================================================
BOOL Material_Interface::_OnMouseMove(UINT /*nFlags*/, tdstMousePos *p_stPos, MTH3D_tdstVector * /*p_stVect*/)
{
	if ( fn_bIsCurrentEditor() )
	{
		m_vFindMaterialUnderCursor(p_stPos->stPos, TRUE);
		//Mircea Dunka 5.11.1998
		if(m_bGetGlidePixel)
			m_vFindColorUnderCursor(p_stPos->stPos, TRUE);
		//end Mircea Dunka
	}

	return FALSE;
}

//Mircea Dunka 5.11.1998
//================================================================================
//================================================================================
void Material_Interface::m_vFindColorUnderCursor(CPoint _oPoint, BOOL _bVerbose)
{
/* SHA_TEMP
	HWND hWndUnder = ::WindowFromPoint(_oPoint);

	DEV_ViewPort3D *p_o3dViewPort = (DEV_ViewPort3D *) gs_p_oMaterialInterface->GetInterface()->GetMultiDevice3D()->GetFocusDevice()->GetViewPort();
	if ( hWndUnder == p_o3dViewPort->GetSafeHwnd() )
	{
		tdstMousePos       stMousePos;

		//in screen pixel coordinates
		stMousePos.stPos = _oPoint;
		//in viewport pixel coordinates
		::ScreenToClient(hWndUnder, &_oPoint);

		//correct for voodooo if necessary
		//CPoint oScreenPoint(stScreenPos);
		if (GLI_lWhatIsGLI() == GLI_C_VersionGlide)
			p_o3dViewPort->ClientToVoodoo(_oPoint);

		#define BYTESPERPIXEL 2

		FxU16 pix;
		GrLfbInfo_t info;
		FxU32* rptr;
		
		info.size = sizeof( GrLfbInfo_t );

		if(grLfbLock( GR_LFB_READ_ONLY, GR_BUFFER_FRONTBUFFER, GR_LFBWRITEMODE_565,
			GR_ORIGIN_UPPER_LEFT, FXFALSE, &info))
		{
			rptr = (FxU32*) info.lfbPtr;
			rptr += ((info.strideInBytes * _oPoint.y) + _oPoint.x * BYTESPERPIXEL)>>2;

			if(_oPoint.x%2) //see glidepgm.doc for this :)
				pix = (FxU16)(*rptr >> 16);
			else
				pix = (FxU16)(*rptr & 0xFFFF);
			
			m_p_oTextureDialog->m_nRPixelColor = (BYTE)((pix & 0xF800)>>8);
			m_p_oTextureDialog->m_nGPixelColor = (BYTE)((pix & 0x07E0)>>3);
			m_p_oTextureDialog->m_nBPixelColor = (BYTE)((pix & 0x001F)<<3);
			m_p_oTextureDialog->GetDlgItem(IDC_BUTTON_PIXELCOLOR) -> InvalidateRect(NULL);

			grLfbUnlock( GR_LFB_READ_ONLY, GR_BUFFER_FRONTBUFFER );
		}
	}
*/
	return;
}
//end Mircea Dunka

//================================================================================
//================================================================================
BOOL Material_Interface::m_bEditPickedMaterial(HIE_tdstPickInfo *_p_stPickInfo)
{
	if ( _p_stPickInfo )
	{
		tdoEditorGameMaterial *p_oMaterial;
		ACP_tdxIndex xPickedElement;

		Geometry3D *p_oGeometry = (Geometry3D*) GetMainWorld()
		->fn_p_oFindObjectWithEngine(
			_p_stPickInfo->hGeoObject,
			C_szGeometricObjectTypeName
		);
		if ( p_oGeometry )
		{
			//find the material used by the picked element of the object
			xPickedElement = _p_stPickInfo->stPickedObject.aDEF_stDataOfElement[0].xElements;
			p_oMaterial = (tdoEditorGameMaterial *) p_oGeometry->fn_p_oGetGameMaterial(xPickedElement, 0);
			if ( p_oMaterial )
			{
				//make the list display the materials of the file that contains the selected material
				m_p_oGetMainView()->m_vSelectFileOfMaterial(p_oMaterial);
				//make us display it
				m_fn_vShowMaterialAll(p_oMaterial);
			}
			else
				fn_vGiveProgressInfo(p_oGeometry->GetName() + " has no associated game material!", -1, C_STATUS_ERROR);
			//we handled the mouse event
			return TRUE;
		}
	}
	//we did not handle the mouse event
	return FALSE;
}

//================================================================================
//================================================================================
BOOL Material_Interface::_OnLButtonDown(UINT /*nFlags*/, tdstMousePos * /*p_stPos*/, ACP_tdxIndex /*xIndex*/, HIE_tdstPickInfo *p_stPickInfo)
{
	if ( fn_bIsCurrentEditor() && m_bModeIsMaterialSelect )
	{
		return m_bEditPickedMaterial(p_stPickInfo);
	}
	else
		return FALSE;
}

//================================================================================
//================================================================================
void Material_Interface::m_vRefreshMaterialSuperObjectLinks(void)
{
	CPA_BaseObjectList *p_oObjectList = GetMainWorld()->fn_p_oGetOriginalObjectList(C_szGameMaterialTypeName);
	if ( p_oObjectList )
	{
		Position xPos = p_oObjectList->GetHeadPosition();
		while ( xPos )
		{
			//first of all, remove all links where a game material is a child
			tdoEditorGameMaterial *p_oGameMaterial = (tdoEditorGameMaterial *) p_oObjectList->GetNext(xPos);
			g_oCoherenceManager.m_fn_vRemoveAllLinks(p_oGameMaterial, C_cLinkedAsChild);
			//but do not forget to reestablish the link with its father fileobject
			g_oCoherenceManager.m_fn_vAddALink(p_oGameMaterial->GetOwner(), p_oGameMaterial);
		}
	}

	//now find all geometric objects, and mark them as fathers of the correponding game materials
	p_oObjectList = GetMainWorld()->fn_p_oGetOriginalObjectList(C_szGeometricObjectTypeName);
	if ( p_oObjectList )
	{
		Position xPos;
		xPos = p_oObjectList->GetHeadPosition();
		while ( xPos )
		{
			Geometry3D *p_oFather = (Geometry3D *) p_oObjectList->GetNext(xPos);
			//if we did not create links for this object already
			GEO_tdstGeometricObject *p_stGeomObj = (GEO_tdstGeometricObject *) p_oFather->GetData();
			//for all elements in the object
			for (ACP_tdxIndex xElement = 0; xElement < p_stGeomObj->xNbElements; xElement ++)
			{
				//get the type of the element
				ACP_tdxIndex xElementType = p_stGeomObj->d_xListOfElementsTypes[xElement];
				switch ( xElementType )
				{
				//these have one material for all the indexed elements they contain
				case GEO_C_xElementIndexedTriangles:
				case GEO_C_xElementPoints:
					{
						//get the material
						CPA_BaseObject *p_oGameMaterial = p_oFather->fn_p_oGetGameMaterial(xElement);
						//if the link is not yet established, register the link
						if ( p_oGameMaterial )
							g_oCoherenceManager.m_fn_vAddALink(p_oFather, p_oGameMaterial);
					}
					break;

				//these have one material per indexed element
				case GEO_C_xElementLines:
				case GEO_C_xElementSpheres:
				case GEO_C_xElementAlignedBoxes:
				case GEO_C_xElementCones:
				case GEO_C_xElementFaceMapDescriptors:
					{
						ACP_tdxIndex xNbIndexedElements = p_oFather->fn_xGetNbIndexedElements(xElement);
						//loop through all indexed elements
						for( int iElementIndex = 0; iElementIndex < xNbIndexedElements; iElementIndex ++ )
						{
							//get the material
							CPA_BaseObject *p_oGameMaterial = p_oFather->fn_p_oGetGameMaterial(xElement, iElementIndex);
							//and register the link
							if ( p_oGameMaterial )
								g_oCoherenceManager.m_fn_vAddALink(p_oFather, p_oGameMaterial);
						}
					}
					break;

				//these are not defined yet
				case GEO_C_xElementSprites:
				case GEO_C_xElementTMeshes:
					{
						ACP_tdxIndex xNbIndexedElements = 0;
					}
					break;
				} /* act according to the element's type */
			} /* for each element of the object */
		} /* for each object in the list */
	} /* if there is a geometric object list */
}

//================================================================================
//================================================================================
/*virtual*/ BOOL Material_Interface::fn_bAcceptToSave()
{
	if ( !m_bCanSaveModifs )
		fn_vGiveProgressInfo("", -1, C_STATUS_ERROR);
	return m_bCanSaveModifs;
}

//================================================================================
//================================================================================
/*virtual*/ void Material_Interface::fn_vBeforeSaveAll(void)
{
	//get fileobjects that are marked for purge, notify all unreferenced texture sections for deletion
	CPA_List<CPA_FileObject> oFileList;
	m_p_oGetMainView()->m_vGetListOfFilesToPurge(&oFileList);
	POSITION xPos = oFileList.GetHeadPosition();
	while ( xPos )
	{
		CPA_FileObject *p_oFile = oFileList.GetNext(xPos);
		//for each gmt file, get the associated tex file
		CString csTextureFileName = p_oFile->GetReferencedName(this, C_szFileReferencedNameKey);
		csTextureFileName = csTextureFileName.Left(csTextureFileName.ReverseFind('.')) + tdoEditorTexture::m_csGetScriptExtension();
		p_oFile = p_oGetFileObjectForReferencedPath(csTextureFileName, C_szFileReferencedNameKey);
		//now get all texture objects of this file
    CPA_List<CPA_BaseObject> oFoundTextures;
    GetMainWorld()->fn_lFindObjects(
      &oFoundTextures,
      "", // obj name
      C_szTextureTypeName, //type
      p_oFile // owner
    );
		POSITION xTexPos = oFoundTextures.GetHeadPosition();
		while ( xTexPos )
		{
			tdoEditorTexture *p_oTexture = (tdoEditorTexture *) oFoundTextures.GetNext(xTexPos);
			//if the texture is not referenced by any visual material, notify that the section is to be deleted
			if ( !p_oTexture->m_bIsReferenced() )
				p_oTexture->fn_vNotifyUnSave();
		}
	}
}

//================================================================================
//================================================================================
/*virtual*/ void Material_Interface::fn_vAfterSaveAll(void)
{
  char *a_szMaterialTypes[] =
  {
    C_szCollideMaterialTypeName,
    C_szMechanicsMaterialTypeName,
    C_szVisualMaterialTypeName,
    C_szGameMaterialTypeName,
		C_szTextureTypeName
  };
  for (int i = 0;  i < sizeof(a_szMaterialTypes) / sizeof(char *); i ++ )
  {
    CPA_List<CPA_BaseObject> oFoundMaterials;

    GetMainWorld()->fn_lFindObjects(
      &oFoundMaterials,
      "", // obj name
      a_szMaterialTypes[i], //type
      NO_CRITERIA // owner
    );
    POSITION xPos = oFoundMaterials.GetHeadPosition();
    while ( xPos )
    {
      CPA_SaveObject *p_oMaterial = (CPA_SaveObject *) oFoundMaterials.GetNext(xPos);
      if ( !p_oMaterial->fn_bSectionExists() ) //if the object has no section
      {
				//destroy it (it will handle cohemngr links removal itself)
        delete p_oMaterial;
      }
    }
    //empty the list before we go for the next type
    oFoundMaterials.RemoveAll();
  }

	//update the highlight info in the init file
	m_vSaveHighlightInfo();
}

//================================================================================
//================================================================================
void Material_Interface::m_vLoadHighlightInfo()
{
	CString	csFileName = M_GetMainApp()->m_csEditorDataPath + "Tools\\Material\\Material.ini";
	char *p_szFileName = (char*)(LPCSTR)csFileName;
	CPA_BaseObjectList *p_oMaterialList;
	Position xPos;

	//for each mechanics material, read its highlight information, if relevant
	p_oMaterialList = GetBaseObjectList(C_szMechanicsMaterialTypeName);
	xPos = p_oMaterialList->GetHeadPosition();
	while ( xPos )
	{
		char sz40ColorString[40];
		tdoEditorMechanicsMaterial *p_oMechanicsMaterial = (tdoEditorMechanicsMaterial *) p_oMaterialList->GetNext(xPos);
		GetPrivateProfileString(C_szMechanicsHighlightProfileSection, p_oMechanicsMaterial->fn_p_szGetName(), "", sz40ColorString, 40, p_szFileName);
		if ( strlen(sz40ColorString) ) //the material has a highlight color
		{
			GEO_tdstColor stColor;
			float fR, fG, fB;
			sscanf(sz40ColorString, "%f,%f,%f", &fR, &fG, &fB);
			stColor.xR = (GEO_tdxColorValue) fR;
			stColor.xG = (GEO_tdxColorValue) fG;
			stColor.xB = (GEO_tdxColorValue) fB;
			p_oMechanicsMaterial->m_vEnableHighlight(TRUE);
			p_oMechanicsMaterial->m_vSetHighlightColor(stColor);
		}
	}

	//for each collide material, read its highlight information, if relevant
	p_oMaterialList = GetBaseObjectList(C_szCollideMaterialTypeName);
	xPos = p_oMaterialList->GetHeadPosition();
	while ( xPos )
	{
		char sz40ColorString[40];
		tdoEditorCollideMaterial *p_oCollideMaterial = (tdoEditorCollideMaterial *) p_oMaterialList->GetNext(xPos);
		GetPrivateProfileString(C_szCollideHighlightProfileSection, p_oCollideMaterial->fn_p_szGetName(), "", sz40ColorString, 40, p_szFileName);
		if ( strlen(sz40ColorString) ) //the material has a highlight color
		{
			GEO_tdstColor stColor;
			float fR, fG, fB;
			sscanf(sz40ColorString, "%f,%f,%f", &fR, &fG, &fB);
			stColor.xR = (GEO_tdxColorValue) fR;
			stColor.xG = (GEO_tdxColorValue) fG;
			stColor.xB = (GEO_tdxColorValue) fB;
			p_oCollideMaterial->m_vEnableHighlight(TRUE);
			p_oCollideMaterial->m_vSetHighlightColor(stColor);
		}
	}
}

//================================================================================
//================================================================================
void Material_Interface::m_vSaveHighlightInfo()
{
	CString	csFileName = M_GetMainApp()->m_csEditorDataPath + "Tools\\Material\\Material.ini";
	char *p_szFileName = (char*)(LPCSTR)csFileName;
	CPA_BaseObjectList *p_oMaterialList;
	Position xPos;

	//empty the sections
	WritePrivateProfileString(C_szCollideHighlightProfileSection, NULL,	NULL, p_szFileName);
	WritePrivateProfileString(C_szMechanicsHighlightProfileSection, NULL,	NULL, p_szFileName);

	//for each mechanics material, write its highlight information, if relevant
	p_oMaterialList = GetBaseObjectList(C_szMechanicsMaterialTypeName);
	xPos = p_oMaterialList->GetHeadPosition();
	while ( xPos )
	{
		GEO_tdstColor stColor;
		CString csColorString;
		char *pszColorString;
		tdoEditorMechanicsMaterial *p_oMechanicsMaterial = (tdoEditorMechanicsMaterial *) p_oMaterialList->GetNext(xPos);
		//if it has highlighting enabled
		if ( p_oMechanicsMaterial->m_bGetHighlightColor(&stColor) )
		{
			//format the highlight color information
			csColorString.Format("%f,%f,%f", (float) stColor.xR, (float) stColor.xG, (float) stColor.xB);
			pszColorString = (char *)LPCTSTR(csColorString);
		}
		else
			//else clear the highlight entry
			pszColorString = NULL;
		//update the entry in the section
		WritePrivateProfileString(C_szMechanicsHighlightProfileSection, p_oMechanicsMaterial->fn_p_szGetName(),	pszColorString, p_szFileName);
	}

	//for each collide material, write its highlight information, if relevant
	p_oMaterialList = GetBaseObjectList(C_szCollideMaterialTypeName);
	xPos = p_oMaterialList->GetHeadPosition();
	while ( xPos )
	{
		GEO_tdstColor stColor;
		CString csColorString;
		char *pszColorString;
		tdoEditorCollideMaterial *p_oCollideMaterial = (tdoEditorCollideMaterial *) p_oMaterialList->GetNext(xPos);
		//if it has highlighting enabled
		if ( p_oCollideMaterial->m_bGetHighlightColor(&stColor) )
		{
			//format the highlight color information
			csColorString.Format("%f,%f,%f", (float) stColor.xR, (float) stColor.xG, (float) stColor.xB);
			pszColorString = (char *)LPCTSTR(csColorString);
		}
		else
			//else clear the highlight entry
			pszColorString = NULL;
		//update the entry in the section
		WritePrivateProfileString(C_szCollideHighlightProfileSection, p_oCollideMaterial->fn_p_szGetName(),	pszColorString, p_szFileName);
	}

	// write on file
	WritePrivateProfileString (NULL, NULL, NULL, p_szFileName);
}

//================================================================================
//================================================================================
BOOL Material_Interface::m_bLoadWarningsAreEnabled()
{ 
	static BOOL s_bToldOnce = FALSE;
	switch ( m_eLoadWarningsActivation )
	{
	case E_am_Never: //no warning
		return FALSE;

	case E_am_Once: //warn only once
		if ( s_bToldOnce )
			return FALSE;
		else
		{
			s_bToldOnce = TRUE;
			return TRUE;
		}

	case E_am_Always: //always warn
		return TRUE;

	default: //this should not happen, but correct it anyway
		m_eLoadWarningsActivation = E_am_Always;
		return TRUE;
	}
}
//================================================================================
//================================================================================
const char *fn_pszBaseName0(const char *_pszName)
{
	char *pszBase = NULL;
	if ( _pszName )
		pszBase = (char *) max(strrchr(_pszName, '\\'), strrchr(_pszName, '/')) ;
	return pszBase ? pszBase + 1 : _pszName;
}


const char *fn_pszBaseName1(const char *_pszName)
{
	char *pszBase = (char *) max(strrchr(_pszName, '\\'), strrchr(_pszName, '/'));
	if ( pszBase )
	{
		char *pszPos = pszBase;
		char cSlash = *pszPos;
		*pszPos = '_';
		pszBase = (char *) fn_pszBaseName0(_pszName);
		*pszPos = cSlash;
	}
	else
		pszBase = (char *) _pszName;

	return pszBase;
}

void Material_Interface::m_vRefreshFileObjectList()
{
	//now we can rebuild all file objects	from the script's file list
	unsigned int uiFilePos = 0;
	SCR_tdst_File_Open *p_stFileEntry;
	SCR_M_DyAr_GetNextElement(
		SCR_tdst_File_Open,
		uiFilePos,
		p_stFileEntry,
		SCR_g_st_File_ArrayOpen
	);
	while ( p_stFileEntry )
	{
		BOOL bIsAGmtFile;
		const char *pszName = p_stFileEntry->stFile.a_szOpenFileName;
		const char *pszNameExtension = strrchr(pszName, '.');
		if
		( //if this is a game, visual material or texture file
			pszNameExtension
			&&
			(
				(bIsAGmtFile = !tdoEditorGameMaterial::m_csGetScriptExtension().CompareNoCase(pszNameExtension))
				|| !tdoEditorVisualMaterial::m_csGetScriptExtension().CompareNoCase(pszNameExtension)
				|| !tdoEditorTexture::m_csGetScriptExtension().CompareNoCase(pszNameExtension)
			)
		)
		{
			//make the interface create the file object
			CPA_FileObject *p_ofileObject = p_oGetFileObjectForCompletePath(pszName);
			//this is the name under which the section was referenced -> should be the short name
			p_ofileObject->fn_bSetReferencedName(this, C_szFileReferencedNameKey, p_stFileEntry->stFile.a_szFileName);
			//register the shortest name too, because this is the only part that can be used to check
			//that a gmt file has an equivalent vmt file...
			p_ofileObject->fn_bSetReferencedName(this, C_szFileMinimalNameKey, fn_pszBaseName0(pszName));
			//add the file to the list
			if ( bIsAGmtFile )
				m_p_oGetMainView()->m_vAddFile(p_ofileObject);
		}
		uiFilePos ++;
		SCR_M_DyAr_GetNextElement(
			SCR_tdst_File_Open,
			uiFilePos,
			p_stFileEntry,
			SCR_g_st_File_ArrayOpen
		);
	}

	CPA_BaseObjectList *p_oFileList = gs_p_oMaterialInterface->GetMainWorld()->fn_p_oGetOriginalObjectList(C_szFileTypeName);
	Position xPos = p_oFileList->GetHeadPosition();
	while ( xPos )
	{
		CString csFileName;
		CPA_FileObject *p_oGameMaterialFileObject = (CPA_FileObject *) p_oFileList->GetNext(xPos);
		csFileName = p_oGameMaterialFileObject->GetReferencedName(this, C_szFileMinimalNameKey); //get the minimal name
		short wFoundExtensionDot = (short) csFileName.ReverseFind('.');
		//if this is a game material file object
		if ( wFoundExtensionDot != -1 && !csFileName.Mid(wFoundExtensionDot).CompareNoCase(tdoEditorGameMaterial::m_csGetScriptExtension()) )
		{
			//replace the game material extension with the visual material extension in the string
			csFileName = csFileName.Left(wFoundExtensionDot) + tdoEditorVisualMaterial::m_csGetScriptExtension();
			//and make sure the associated vmt file object was created in the above loop
			CPA_FileObject *p_oVisualMaterialFileObject = p_oGetFileObjectForReferencedPath(csFileName, C_szFileMinimalNameKey);
			//check that for a game material file the corresponding visual material file exists, and link them together
			if ( !p_oVisualMaterialFileObject )
			{
				m_bCanSaveModifs = FALSE; //we dont want to save our modifs
				AfxMessageBox(
					p_oGameMaterialFileObject->GetName() + " has no equivalent " + csFileName + " in the game datae\n"
					"Because of this, the material editor forbids to save your modifications..."
				);
			}
			/*else
				g_oCoherenceManager.m_fn_vAddALink(p_oGameMaterialFileObject, p_oVisualMaterialFileObject);*/

			//for the texture file, create a file object if it is not done yet, because we might need it
			csFileName = csFileName.Left(wFoundExtensionDot) + tdoEditorTexture::m_csGetScriptExtension();
			CPA_FileObject *p_oTextureFileObject = p_oGetFileObjectForReferencedPath(csFileName, C_szFileMinimalNameKey);
			if ( !p_oTextureFileObject )
			{
				//build its complete name from the visual material's file name, because the texture files are with the vmt files
				CString csFullFileName = p_oVisualMaterialFileObject->GetCompleteName();
				short wFoundExtensionDot = (short) csFullFileName.ReverseFind('.');
				csFullFileName = csFullFileName.Left(wFoundExtensionDot) + tdoEditorTexture::m_csGetScriptExtension();
				//make the interface create the file object
				CPA_FileObject *p_oTextureFileObject = p_oGetFileObjectForCompletePath(csFullFileName);
				//now compute the referenced name
				csFullFileName = p_oVisualMaterialFileObject->GetReferencedName(this, C_szFileReferencedNameKey);
				wFoundExtensionDot = (short) csFullFileName.ReverseFind('.');
				csFullFileName = csFullFileName.Left(wFoundExtensionDot) + tdoEditorTexture::m_csGetScriptExtension();
				p_oTextureFileObject->fn_bSetReferencedName(this, C_szFileReferencedNameKey, csFullFileName);
				//register the shortest name too, because this is the only part that can be used to check
				//that a gmt file has an equivalent vmt file...
				p_oTextureFileObject->fn_bSetReferencedName(this, C_szFileMinimalNameKey, fn_pszBaseName0(LPCTSTR(csFullFileName)));
				//g_oCoherenceManager.m_fn_vAddALink(p_oGameMaterialFileObject, p_oTextureFileObject);
			}
		}
	}

	CString csFullFileName, csBaseName;
	CPA_FileObject *p_oFileObject;
	//since there are only one file for all mechanics and collide materials, create the file objects outside the loop
	csBaseName = CString("ED") + tdoEditorMechanicsMaterial::m_csGetScriptExtension();
	csFullFileName = CString(fn_szGetMechanicsMaterialDataPath()) + "\\" + csBaseName;
	p_oFileObject = p_oGetFileObjectForCompletePath(csFullFileName);
	p_oFileObject->fn_bSetReferencedName(this, C_szFileReferencedNameKey, csBaseName);
	p_oFileObject->fn_bSetReferencedName(this, C_szFileMinimalNameKey, csBaseName);

	csBaseName = CString("ED") + tdoEditorCollideMaterial::m_csGetScriptExtension();
	csFullFileName = CString(fn_szGetCollideMaterialDataPath()) + "\\" + csBaseName;
	p_oFileObject = p_oGetFileObjectForCompletePath(csFullFileName);
	p_oFileObject->fn_bSetReferencedName(this, C_szFileReferencedNameKey, csBaseName);
	p_oFileObject->fn_bSetReferencedName(this, C_szFileMinimalNameKey, csBaseName);
}

//================================================================================
// f**ing M$ templates dont work, so create our own system !
//================================================================================
#define D_tdoMaterialClass tdoEditorGameMaterial
#define D_tdxEngineMaterialHandle GMT_tdxHandleToGameMaterial
#include "templates.cxx"

#define D_tdoMaterialClass tdoEditorVisualMaterial
#include "templates.cxx"

#define D_tdoMaterialClass tdoEditorTexture
#define D_tdxEngineMaterialHandle GLI_tdstTexture *
#include "templates.cxx"

#define D_tdoMaterialClass tdoEditorCollideMaterial
#define D_tdxEngineMaterialHandle GMT_tdxHandleToCollideMaterial
#include "templates.cxx"

#define D_tdoMaterialClass tdoEditorMechanicsMaterial
#define D_tdxEngineMaterialHandle DNM_tdxHandleToMecMatCharacteristics
#include "templates.cxx"

//================================================================================
//================================================================================
void Material_Interface::m_vDoRefreshLists(
	long _lStartInLinkTable /*= 0*/,
	tdeRefreshListsMode _eOverrideMode /*= E_rlm_DoNothing*/,
	BOOL _bLoadTextures /*= TRUE*/
)
{
	g_oBaseFrame.mfnv_UpdateTitle("Prepare materials");

	//override the mode if specified
	if ( _eOverrideMode != E_rlm_DoNothing )
		m_eRefreshListsMode = _eOverrideMode;

	if ( m_eRefreshListsMode != E_rlm_DoNothing )
	{
		//get the root of the world
		//m_p_oWorldRoot = M_GetWorld()->GetRoot();

		if ( m_eRefreshListsMode == E_rlm_DestroyAndRebuild )
		{
			//rescan the game material linktable from the beginning if the materials were destroyed
			_lStartInLinkTable = 0;
			//start by destroying all file objects:
			CPA_List<CPA_BaseObject> oFileObjectList;
			GetMainWorld()->fn_lFindObjects(
				&oFileObjectList,
				"", C_szFileTypeName,
				NO_CRITERIA /* owner */
			);
			POSITION xPos = oFileObjectList.GetHeadPosition();
			while ( xPos )
			{
				CPA_FileObject *p_oFileObject = (CPA_FileObject *) oFileObjectList.GetNext(xPos);
				const char *pszFileName = p_oFileObject->fn_p_szGetName();
				const char *pszNameExtension = strrchr(pszFileName, '.');
				if
				( //if this is a material related file
					pszNameExtension
					&&
					(
						!tdoEditorGameMaterial::m_csGetScriptExtension().CompareNoCase(pszNameExtension)
						|| !tdoEditorVisualMaterial::m_csGetScriptExtension().CompareNoCase(pszNameExtension)
						|| !tdoEditorMechanicsMaterial::m_csGetScriptExtension().CompareNoCase(pszNameExtension)
						|| !tdoEditorCollideMaterial::m_csGetScriptExtension().CompareNoCase(pszNameExtension)
						|| !tdoEditorTexture::m_csGetScriptExtension().CompareNoCase(pszNameExtension)
					)
				)
				{
					//remove the file from the list
					m_p_oGetMainView()->m_vRemoveFile(p_oFileObject);
					//remove all coherence mamanger links for this file
	        g_oCoherenceManager.m_fn_vRemoveAllLinks(p_oFileObject, C_cLinkedAsChildAndFather);
					//and destroy the file
					delete p_oFileObject;
				}
			}

			//empty the current list of editor materials, but without destroying
			//their associated materials, since the handles are not valid, because Level Has Changed!!!
			//this is fine, since the editor objects' destructors dont care about the associated engine materials
			vKillMaterialList((tdoEditorGameMaterial *) NULL, NULL);
			vKillMaterialList((tdoEditorVisualMaterial *) NULL, NULL);
			vKillMaterialList((tdoEditorTexture *) NULL, NULL);
			vKillMaterialList((tdoEditorMechanicsMaterial *) NULL, m_p_oMaterialMeca->m_p_oMaterialCombo);
			vKillMaterialList((tdoEditorCollideMaterial *) NULL, m_p_oMaterialCol->m_p_oMaterialCombo);
		}

		//prevent object name prefixing, because all the objects that will be created now
		//will get their names from existing sections
		BOOL bPrevLoadingWorld = GetInterface()->fn_bIsLoadingWorld();
		GetInterface()->SetLoadingWorld(TRUE);
		m_vRefreshFileObjectList();
		vRefreshMaterialList(0, (tdoEditorTexture *) NULL, FALSE, NULL);
		vRefreshMaterialList(_lStartInLinkTable, (tdoEditorGameMaterial *) NULL, FALSE, NULL);
		//second args tells that the sections were analyzed with the full name instead of the referenced name
		vRefreshMaterialList(0, (tdoEditorMechanicsMaterial *) NULL, TRUE, m_p_oMaterialMeca->m_p_oMaterialCombo);
		vRefreshMaterialList(0, (tdoEditorCollideMaterial *) NULL, FALSE, m_p_oMaterialCol->m_p_oMaterialCombo);
		//restore prefixing mode (for new objects that we could create)
		GetInterface()->SetLoadingWorld(bPrevLoadingWorld);

		//no refresh is necessary now
		m_eRefreshListsMode = E_rlm_DoNothing;

		fn_vGiveProgressInfo("", -1);
	}

	if ( _bLoadTextures )
	{
		m_p_oTextureDlg->m_fn_vRefreshTextureList(TRUE, TRUE);
		m_bTexturesLoaded = TRUE;
	}
}

//================================================================================
//================================================================================
void Material_Interface::fn_vLevelHasChanged(void)
{

    // Christophe modifications 08/12/98 {
    CString	csFileName = M_GetMainApp()->m_csEditorDataPath + "Tools\\Material\\Material.ini";
	char *p_szFileName = (char*)(LPCSTR)csFileName,
          sz255GMTFileName[255],
          sz8FileToLoadSection[8],
          sz3FileNumber[3];
    unsigned char FileNumber = 1;
    do
    {
        strcpy(sz8FileToLoadSection, "File");
        strcat(sz8FileToLoadSection, itoa(FileNumber++, sz3FileNumber, 10) );
        GetPrivateProfileString("Preload", sz8FileToLoadSection, "", sz255GMTFileName, 255, p_szFileName);
        if(sz255GMTFileName[0])
        {
            SCR_fnp_st_RdL0_AnalyseSection(sz255GMTFileName, SCR_CDF_uw_Anl_Normal);
        }
    } while(sz255GMTFileName[0]);
    // } End Christophe modifications

 	//we want to rescan all linktables from the beginning
	gs_lNbPreviousMaterialsInLinkTable = 0;
	gs_lNbPreviousGeomobjInLinkTable = 0;
  //all existent editor materials must be destroyed before the new ones are linked to the engine materials
	m_vDoRefreshLists(0, E_rlm_DestroyAndRebuild, TRUE/*FALSE*/);
	//read the highlight information from the ini file.
	m_vLoadHighlightInfo();
}

//================================================================================
//================================================================================
CString Material_Interface::m_csGetIdPartOfSectionName(CString _csSectionName)
{
	char szId[SCR_CV_ui_Cfg_MaxLenName];
	SCR_fn_v_RdL0_SplitSectionName((char *)LPCTSTR(_csSectionName), NULL, NULL, szId);
	return szId;
}

//================================================================================
//================================================================================
CString Material_Interface::m_csGetActionPartOfSectionName(CString _csSectionName)
{
	char szAction[SCR_CV_ui_Cfg_MaxLenName];
	SCR_fn_v_RdL0_SplitSectionName((char *)LPCTSTR(_csSectionName), NULL, szAction, NULL);
	return szAction;
}

//================================================================================
//================================================================================
CString Material_Interface::m_csGetFilePartOfSectionName(CString _csSectionName)
{
	char szFile[SCR_CV_ui_Cfg_MaxLenName];
	SCR_fn_v_RdL0_SplitSectionName((char *)LPCTSTR(_csSectionName), szFile, NULL, NULL);
	return szFile;
}

//================================================================================
//================================================================================
CPA_SaveObject *Material_Interface::m_p_oGetEditorObjectForEngine(ACP_tdxHandleOfMaterial _hVisualMaterial)
{
	if ( _hVisualMaterial )
		return (CPA_SaveObject *) GetBaseObject(_hVisualMaterial, C_szVisualMaterialTypeName);
	else
		return NULL;
}

//================================================================================
//================================================================================
CPA_SaveObject *Material_Interface::m_p_oGetEditorObjectForEngine(DNM_tdxHandleToMecMatCharacteristics _hMechanicsMaterial)
{
	if ( DNM_fn_bIsMatCharacteristicsValid(_hMechanicsMaterial) )
		return (CPA_SaveObject *) GetBaseObject(_hMechanicsMaterial, C_szMechanicsMaterialTypeName);
	else
		return NULL;
}

//================================================================================
//================================================================================
CPA_SaveObject *Material_Interface::m_p_oGetEditorObjectForEngine(GMT_tdxHandleToCollideMaterial _hCollideMaterial)
{
	if ( _hCollideMaterial != GMT_C_InvalidCollideMaterial )
		return (CPA_SaveObject *) GetBaseObject(_hCollideMaterial, C_szCollideMaterialTypeName);
	else
		return NULL;
}

//================================================================================
//================================================================================
CPA_SaveObject *Material_Interface::m_p_oGetEditorObjectForEngine(GMT_tdxHandleToGameMaterial _hGameMaterial)
{
	if ( GMT_fn_b_ulIsValid(_hGameMaterial) )
		return (CPA_SaveObject *) GetBaseObject(_hGameMaterial, C_szGameMaterialTypeName);
	else
		return NULL;
}

//================================================================================
//================================================================================
CPA_SaveObject *Material_Interface::m_p_oGetEditorObjectForEngine(GLI_tdstTexture *_hTexture)
{
	if ( _hTexture )
		return (CPA_SaveObject *) GetBaseObject(_hTexture, C_szTextureTypeName);
	else
		return NULL;
}

//================================================================================
//================================================================================
CPA_FileObject *Material_Interface::m_p_oGetCurrentFileObject()
{
	return m_p_oGetMainView()->m_p_oGetCurrentFileObject();
}

//================================================================================
//================================================================================
/*virtual*/ BOOL Material_Interface::fn_bLoadBaseObject	(CPA_BaseObject *p_oObject)
{
	if ( p_oObject && p_oObject->fn_bIsOfType(C_szGameMaterialTypeName) )
	{
		((tdoEditorGameMaterial *) p_oObject)->m_vLoadAssociatedEngineMaterial();
		return TRUE;
	}
	return FALSE;
}

//================================================================================
//================================================================================
long Material_Interface::OnQueryAction(CPA_EditorBase* /*p_oSender*/, WPARAM wParam, LPARAM /*lParam*/)
{
  switch( wParam )
  {
  case C_cCreateNewGameMaterial:
		//the update is not necessary unless the world is known
		if ( m_bEnteredEditorAtLeastOnce && m_p_oGetWorldSuperObject() )
		{
			long lNewNbMaterialInLinkTable = SCR_M_st_Link_GetDynamicArray(tdoEditorGameMaterial::m_p_stGetAssociatedLinkTable()).uiNumValues;
			long lNewNbGeomobjInLinkTable = SCR_M_st_Link_GetDynamicArray(GLI_p_stGetLinkTableOfGeometric()).uiNumValues;
			if
			(
				gs_lNbPreviousMaterialsInLinkTable != lNewNbMaterialInLinkTable
				|| gs_lNbPreviousGeomobjInLinkTable != lNewNbGeomobjInLinkTable
			)
			{
				//update the lists, but do not delete existent editor materials, and do not load textures
				m_vDoRefreshLists(gs_lNbPreviousMaterialsInLinkTable, E_rlm_UpdateWithoutDestruction, TRUE);
				//remember the number of materials in the linktable
				gs_lNbPreviousMaterialsInLinkTable = lNewNbMaterialInLinkTable;
				gs_lNbPreviousGeomobjInLinkTable = lNewNbGeomobjInLinkTable;
			}
		}
		else
			m_eRefreshListsMode = E_rlm_UpdateWithoutDestruction;
    break;

  case C_cGetDefaultGameMaterial:
		if ( !GMT_fn_b_ulIsValid(m_hQueriedDefaultGameMaterial) )
		{
			/*//find the material with the default name found in the file containing common materials
			tdoEditorGameMaterial *p_oMaterial = (tdoEditorGameMaterial *) GetMainWorld()->fn_p_oFindObject(
				C_szNameOfDefaultMaterial,
				C_szGameMaterialTypeName,
				p_oGetFileObjectForReferencedPath(C_szFileNameForDefaultMaterial)
			);
			if ( p_oMaterial )
				m_hQueriedDefaultGameMaterial = p_oMaterial->m_hGetEngineMaterial();
			else*/
			{
        char szDefaultGMTFile[256];
        char szDefaultGMTName[256];

        strcpy(szDefaultGMTFile, fn_szGetGameMaterialDataPath() );
        strcat(szDefaultGMTFile, "\\" );
        strcat(szDefaultGMTFile, C_szFileNameForDefaultMaterial );
        SCR_fn_v_RdL0_ComputeSectionName( szDefaultGMTName, szDefaultGMTFile,C_szGameMaterialTypeName ,C_szNameOfDefaultMaterial); 
				//if we did not create the editor materials yet, find an engine material with the default name in the link table
				SCR_tdst_Link_Table *p_stGameLinkTable = GMT_fn_p_stGetLinkTable();
        SCR_tdst_Link_Value *p_stEntry = SCR_fnp_st_Link_SearchKey (p_stGameLinkTable , szDefaultGMTName);

				//if we found it, return it, else return the first material we got
				if ( p_stEntry )
					m_hQueriedDefaultGameMaterial = (GMT_tdxHandleToGameMaterial) SCR_M_ul_Link_GetValue(p_stEntry);
				else
        {
          unsigned int uiPos = 0;
          SCR_tdst_Link_Value *p_stFirstEntry;
		      SCR_M_DyAr_GetNextElement( SCR_tdst_Link_Value, uiPos, p_stFirstEntry, p_stGameLinkTable->stLinkArray );

          if ( p_stFirstEntry )
					  m_hQueriedDefaultGameMaterial = (GMT_tdxHandleToGameMaterial) SCR_M_ul_Link_GetValue(p_stFirstEntry);
				  else
					  GMT_fn_vInvalidate(&m_hQueriedDefaultGameMaterial);
        }
			}
		}
		return (long) m_hQueriedDefaultGameMaterial;
  }
  return NULL;
}

// ----------------------------------------------------------------------------
// Save Preferences
// ----------------------------------------------------------------------------
void Material_Interface::m_vSavePreferences(void)
{
	CString	csFileName = M_GetMainApp()->m_csEditorDataPath + "Tools\\Material\\Material.ini";
	char *p_szFileName = (char*)(LPCSTR)csFileName;
	CString	csDimension;

	// Open MODE
	WritePrivateProfileString(
		C_szPreferencesProfileSection, C_szDisplayModeProfileString,
		m_p_oGetMaterialListView()->m_bAllMaterialsDisplayed() ? "All" : "Used" , p_szFileName
	);

	// Display Materiau under cursor mode
	WritePrivateProfileString( C_szPreferencesProfileSection, C_szDisplayMaterialUnderCursorProfileString, 
		m_bDisplayMaterialUnderCursor ? "TRUE" : "FALSE", p_szFileName
	);

	//////////////////
	//  PANEL SIZES //
	//////////////////

	//left pane width
	csDimension.Format("%ld", m_p_oLeftSplitFrame->m_oCurPos.right - m_p_oLeftSplitFrame->m_oCurPos.left);
	WritePrivateProfileString(
		C_szPreferencesProfileSection, C_szLeftPaneWidthProfileString,
		(char*)(LPCSTR)csDimension, p_szFileName
	);

	//visual view height
	csDimension.Format("%ld", m_p_oLeftSplitFrame->GetPaneSize(C_wVisualPaneId));
	WritePrivateProfileString(
		C_szPreferencesProfileSection, C_szVisualPaneHeightProfileString,
		(char*)(LPCSTR)csDimension, p_szFileName
	);
	//mechanics view height
	csDimension.Format("%ld", m_p_oLeftSplitFrame->GetPaneSize(C_wMechanicsPaneId));
	WritePrivateProfileString(
		C_szPreferencesProfileSection, C_szMechanicsPaneHeightProfileString,
		(char*)(LPCSTR)csDimension, p_szFileName
	);
	//collide view height
	csDimension.Format("%ld", m_p_oLeftSplitFrame->GetPaneSize(C_wCollidePaneId));
	WritePrivateProfileString(
		C_szPreferencesProfileSection, C_szCollidePaneHeightProfileString,
		(char*)(LPCSTR)csDimension, p_szFileName
	);
	//sound view height
	csDimension.Format("%ld", m_p_oLeftSplitFrame->GetPaneSize(C_wSoundPaneId));
	WritePrivateProfileString(
		C_szPreferencesProfileSection, C_szSoundPaneHeightProfileString,
		(char*)(LPCSTR)csDimension, p_szFileName
	);

	//sound view height
	csDimension.Format("%ld", m_p_oLeftSplitFrame->GetPaneSize(C_wMainPaneId));
	WritePrivateProfileString(
		C_szPreferencesProfileSection, C_szMainPaneHeightProfileString,
		(char*)(LPCSTR)csDimension, p_szFileName
	);

	//texture view width
	csDimension.Format("%ld", m_p_oBottomSplitFrame->GetPaneSize(C_wTexturePaneId));
	WritePrivateProfileString(
		C_szPreferencesProfileSection, C_szTexturePaneWidthProfileString,
		(char*)(LPCSTR)csDimension, p_szFileName
	);

	//list pane width
	csDimension.Format("%ld", m_p_oBottomSplitFrame->GetPaneSize(C_wListPaneId));
	WritePrivateProfileString(
		C_szPreferencesProfileSection, C_szListPaneWidthProfileString,
		(char*)(LPCSTR)csDimension, p_szFileName
	);

	//bottom splitter frame height
	csDimension.Format("%ld", m_p_oBottomSplitFrame->m_oCurPos.bottom - m_p_oBottomSplitFrame->m_oCurPos.top);
	WritePrivateProfileString(
		C_szPreferencesProfileSection, C_szMaterialListHeightProfileString,
		(char*)(LPCSTR)csDimension, p_szFileName
	);

	// write on file
	WritePrivateProfileString (NULL , NULL, NULL, p_szFileName);
}

//================================================================================
//================================================================================
/*virtual*/ BOOL Material_Interface::fn_bOnInvalidateLink(CPA_BaseObject * /*pOwner*/, CPA_BaseObject * /*pReferencedObject*/, BOOL /*bDestroyed*/)
{
	AfxMessageBox("uh oh...");
	return FALSE;
}

//================================================================================
//================================================================================
/*virtual*/ void Material_Interface::fn_vOnRestoreLink(CPA_BaseObject * /*pOwner*/, CPA_BaseObject * /*pReferencedObject*/)
{
	AfxMessageBox("uh oh...");
}

//================================================================================
//================================================================================
/*virtual*/ void Material_Interface::fn_vOnModifyChild(CPA_BaseObject *pOwner, CPA_BaseObject * /*pReferencedObject*/, unsigned long /*_ulData*/)
{
	AfxMessageBox("uh oh...");
}

//================================================================================
//================================================================================
ACP_tdxIndex xGetPickInfoUnderPoint(HIE_aDEF_stTabOfPickInfo *_p_xRetrievedPickInfo, CPoint _oScreenCursor)
{
	ACP_tdxIndex xNbPicked = 0;
	HWND hWndUnder = ::WindowFromPoint(_oScreenCursor);

	DEV_ViewPort3D *p_o3dViewPort = (DEV_ViewPort3D *) gs_p_oMaterialInterface->GetInterface()->GetMultiDevice3D()->GetFocusDevice()->GetViewPort();
	if ( hWndUnder == p_o3dViewPort->GetSafeHwnd() )
	{
		HIE_tdxHandleToSuperObject hEngineSupObject;
		tdstMousePos       stMousePos;

		//in screen pixel coordinates
		stMousePos.stPos = _oScreenCursor;
		//in viewport pixel coordinates
		::ScreenToClient(hWndUnder, &_oScreenCursor);

		//correct for voodooo if necessary
		//CPoint oScreenPoint(stScreenPos);
		if (GLI_lWhatIsGLI() == GLI_C_VersionGlide)
		 p_o3dViewPort->ClientToVoodoo(_oScreenCursor);

		stMousePos.stPos2D.xX = GLI_M_LongToValue(_oScreenCursor.x);
		stMousePos.stPos2D.xY = GLI_M_LongToValue(_oScreenCursor.y);

		xNbPicked = 0;
		//try to pick an object
		hEngineSupObject = gs_p_oMaterialInterface->m_p_oGetWorldSuperObject()->GetStruct();
		//Must be changed but how?

		if ( hEngineSupObject == NULL )
			return 0;

		//fill the supplied pickinfo array with what we find under the cursor
		xNbPicked = HIE_xIsSuperObjectPick(GLI_C_ModePickingFace,
			p_o3dViewPort->m_hDisplayDevice,
			p_o3dViewPort->m_hDisplayViewport,
			&stMousePos.stPos2D, hEngineSupObject, (HIE_tdstPickInfo *) _p_xRetrievedPickInfo
		);
	}
	return xNbPicked;
}

//================================================================================
//================================================================================
CPA_FileObject *p_oGetFileObjectForCompletePath(CString _csPath)
{
	return gs_p_oMaterialInterface->GetInterface()->GetFileObject(_csPath);
}

//================================================================================
//================================================================================
CPA_FileObject *p_oGetFileObjectForReferencedPath(CString _csPath, CString _csKey /*= C_szFileReferencedNameKey*/)
{
	BOOL bTestAgainstCompleteName = _csKey.IsEmpty();
	CPA_BaseObjectList *p_oFileList = gs_p_oMaterialInterface->GetMainWorld()->fn_p_oGetOriginalObjectList(C_szFileTypeName);
	Position xPos = p_oFileList->GetHeadPosition();
	while ( xPos )
	{
		CPA_FileObject *p_oFileObject = (CPA_FileObject *) p_oFileList->GetNext(xPos);
		if ( bTestAgainstCompleteName ) 
		{
			if ( !p_oFileObject->GetCompleteName().CompareNoCase(_csPath) )
				return p_oFileObject;
		}
		else
		{
			if ( !p_oFileObject->GetReferencedName(gs_p_oMaterialInterface, _csKey).CompareNoCase(_csPath) )
				return p_oFileObject;
		}
	}
	return NULL;
}

//================================================================================
//================================================================================
// Only displays message in the status bar if 'cPercentage = -1'
void fn_vGiveProgressInfo(CString csMessage, long lTruePercentage, short _wHighLight /*= C_STATUS_NORMAL*/)
{
	long lScaledPercentage = lTruePercentage;
	static long s_lLastPercentage = 98765432; //some value that is unlikely to be passed
	CString csTrueMessage;
	if ( lScaledPercentage < 0 )
		csTrueMessage = csMessage;
	else if ( lScaledPercentage >= 0 )
	{
		if ( lScaledPercentage > 100 )
			lScaledPercentage = 100;

		lScaledPercentage /= 2;
		if ( lScaledPercentage != s_lLastPercentage )
		{
			csTrueMessage.Format(
				"%s %.*s%.*s", LPCTSTR(csMessage),
				lScaledPercentage,       "ƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒ",
				50 - lScaledPercentage,  "--------------------------------------------------"
			);
		}
	}

	//display only if the window is available and the percentage changed
	if ( lScaledPercentage != s_lLastPercentage )
	{
		FRMBaseMenu *p_oWnd = (FRMBaseMenu *) g_oFrameGest.ma_p_oOccupyArray[2][2];
		if ( !p_oWnd )
			p_oWnd = M_GetMainWnd();
		if ( p_oWnd )
			p_oWnd->UpdateStatus(
				(char *)LPCTSTR(csTrueMessage),
				C_STATUSPANE_INFOS,
				_wHighLight
			);
		s_lLastPercentage = (lScaledPercentage < 0) ? 98765432 : lScaledPercentage;
	}
}

#endif //ACTIVE_EDITOR
