reman3/Rayman_X/cpa/tempgrp/TGM/Src/MatList.cpp

1102 lines
43 KiB
C++

/*=============================================================================
*
* Filename: MatList.cpp
* Version: 1.0
* Date: 06/11/96
* Author: V.L.
*
* Description: implementation of MaterialList view
*
*===========================================================================*/
#include "stdafx.h"
#include "Acp_base.h"
#include "itf.h"
#include "incgam.h"
#include "ogd.h"
#include "gmt.h"
#include "dpt.h"
#include "x:\cpa\main\inc\_editid.h"
#include "matres.h"
#include "_interf.hpp"
#include "MatList.hpp"
#include "GMatObj.hpp"
#include "VMatObj.hpp"
#include "TexObj.hpp"
#include "diaview.hpp"
#include "diacol.hpp"
#include "diameca.hpp"
#include "diamain.hpp"
#include "TGMdef.hpp"
//ROMTEAM WorldEditor (Cristi Petrescu 12/12/97)
#include "ozo.h"
//ENDROMTEAM WorldEditor (Cristi Petrescu)
extern Material_Interface *gs_p_oMaterialInterface;
//=============================================================================
// Constant for DragDrop type
//=============================================================================
#define C_uiMaterial 1996
//=============================================================================
//
// implementation off C3ListView class
//
//=============================================================================
IMPLEMENT_DYNCREATE(CMaterialListView, C3ListView)
//=============================================================================
// Description : Message map
//=============================================================================
BEGIN_MESSAGE_MAP(CMaterialListView, C3ListView)
//{{AFX_MSG_MAP(CMaterialListView)
ON_WM_CREATE()
ON_WM_LBUTTONDOWN()
ON_WM_KEYDOWN()
ON_WM_KEYUP()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//=============================================================================
// Description : constructor
//=============================================================================
CMaterialListView::CMaterialListView() : C3ListView()
{
m_fn_vSetDDTypeAndEditor( C_uiMaterial, "Material_Editor");
m_fn_vSetBox(C_cDisplayBitmapAndText, C_wListViewBTItemWidth, C_wListViewBTItemHeight);
m_fn_vSetBox(C_cDisplayBitmap, C_wListViewBItemWidth, C_wListViewBItemHeight);
m_fn_vSetBox(C_cDisplayText, C_wListViewTItemWidth, C_wListViewTItemHeight);
//m_fn_vDisableMenuItem(TLVM_lOrder);
m_oHatchBitmap.LoadBitmap(IDB_BITMAP_HATCHED);
m_oHatchBrush.CreatePatternBrush(&m_oHatchBitmap);
m_fn_vSetBitmapList(NULL);
m_wSpecialImage = TSL_cItemNotFound;
//which materials are to be displayed ?
CString csFileName = M_GetMainApp()->m_csEditorDataPath + "Tools\\Material\\Material.ini";
char *p_szFileName = (char*)(LPCSTR)csFileName;
char sz20ProfileDimension[20];
GetPrivateProfileString(C_szPreferencesProfileSection, C_szDisplayModeProfileString, C_szDefaultDisplayFilter, sz20ProfileDimension, 20, p_szFileName);
m_vSetMaterialDisplayFilter(strcmp(sz20ProfileDimension, C_szDisplayFilterDisabled) ? TRUE : FALSE);
}
//=============================================================================
// Description : destructor
//=============================================================================
CMaterialListView::~CMaterialListView()
{
}
//=============================================================================
// Description : Create view
//=============================================================================
int CMaterialListView::OnCreate( LPCREATESTRUCT _p_stCreateStruct )
{
if (C3ListView::OnCreate( _p_stCreateStruct ) == -1)
return -1;
m_cDisplayType = C_cDisplayBitmapAndText;
return 0;
}
//=============================================================================
// Description : on draw item
//=============================================================================
void CMaterialListView::m_fn_vOverriddenDrawItem( short wItem, CDC *pDC, RECT *rect)
{
tdoEditorGameMaterial *p_oEditorMaterial;
BOOL bSelected;
// get item data
p_oEditorMaterial = (tdoEditorGameMaterial *) m_fn_lGetContent( wItem, m_cCurrentOrder );
//if the item was not loaded by engine, select a gray background
CBrush *p_oOldBrush = NULL;
//CBrush oGrayBrush(HS_BDIAGONAL, RGB(200, 100, 70));
//CBrush oGrayBrush(CBitmap::FromHandle(m_hHatchBitmap))
if ( !p_oEditorMaterial->m_bIsReferenced() )
p_oOldBrush = pDC->SelectObject(&m_oHatchBrush);
//draw the item normally, with a special text for items with this image (in text only-mode)
m_fn_vDrawItem( wItem, pDC, rect, m_wSpecialImage);
//restore the original background
if ( p_oOldBrush )
pDC->SelectObject(p_oOldBrush);
// reinvert rectangle if item is selected
bSelected = m_fn_bIsItemSelected(wItem, m_cCurrentOrder);
if (bSelected)
pDC->InvertRect( rect );
if (bSelected)
pDC->InvertRect( rect );
}
//=============================================================================
// Description : on select item
//=============================================================================
void CMaterialListView::OnSelectItem(short wCase)
{
if ( wCase != TSL_cItemNotFound )
{
tdoEditorGameMaterial *p_oGameMaterial = (tdoEditorGameMaterial *) m_fn_lGetContent(wCase);
//if the editor material has no associated engine material yet
if ( p_oGameMaterial && !p_oGameMaterial->fn_bIsAvailable() )
{
//prevent object name prefixing, because all the objects that will be created now
//will get their names from existing sections
BOOL bPrevLoadingWorld = gs_p_oMaterialInterface->GetInterface()->fn_bIsLoadingWorld();
gs_p_oMaterialInterface->GetInterface()->SetLoadingWorld(TRUE);
//make the editor material analyze its associated section to load the engine material
p_oGameMaterial->m_vLoadAssociatedEngineMaterial();
//restore prefixing mode (for new objects that we could create)
gs_p_oMaterialInterface->GetInterface()->SetLoadingWorld(bPrevLoadingWorld);
int iImage = m_iGetTextureIndexForGameMaterial(p_oGameMaterial, TRUE);
//make the view update its display and show the correct texture
m_fn_vSetItemImage(wCase, (short) iImage);
m_fn_vRedrawSelectedItem(wCase);
//update the purge button status, in case all materials are now analyzed
gs_p_oMaterialInterface->m_p_oGetMainView()->m_vUpdatePurgeStatus();
}
}
C3ListView::OnSelectItem(wCase);
if ( wCase == TSL_cItemNotFound )
{
//m_fn_vRedrawSelectedItem();
m_fn_vUnselectItem();
gs_p_oMaterialInterface->m_fn_vShowMaterialAll();
//Invalidate();
return;
}
//show all parameters of the material
gs_p_oMaterialInterface->m_fn_vShowMaterialAll();
HWND hWnd = ((CWnd *) M_GetMainActiveViewport())->GetSafeHwnd();
DD_eAddReference(hWnd, m_oDDCase.fn_p_szGetEditorName(), m_oDDCase.fn_uiGetDataType(), FALSE);
}
//=============================================================================
// Description : change selected item image
// called by CMaterialDescDlg when visuel change
//=============================================================================
void CMaterialListView::m_fn_vChangeSelectedItemImage( int iImage )
{
m_fn_vSetItemImage( m_fn_lGetSelectedItem(), (short) iImage );
}
//=============================================================================
// Description : redraw selected item
// called by CMaterialDescDlg when visuel change
//=============================================================================
void CMaterialListView::m_fn_vRedrawSelectedItem(int iItem /*= -1*/)
{
if ( iItem == TSL_cItemNotFound )
iItem = m_fn_lGetSelectedItem(m_cCurrentOrder);
RECT rect;
m_fn_vGetCaseRect((short) iItem, &rect);
rect.top -= GetScrollPosition().y;
rect.bottom -= GetScrollPosition().y;
rect.left -= GetScrollPosition().x;
rect.right -= GetScrollPosition().x;
InvalidateRect( &rect );
}
//=============================================================================
// Description SelectMaterial in list to fit with the given one
//=============================================================================
void CMaterialListView::m_fn_vSelectMaterial(tdoEditorGameMaterial *_p_oGameMaterial)
{
int iPreviousSelectedItem = m_fn_lGetSelectedItem(m_cCurrentOrder);
int iNewSelectedItem = m_fn_iFindMaterial(_p_oGameMaterial);
if ( iNewSelectedItem == iPreviousSelectedItem )
return;
//select the new item, and redraw it
if ( iNewSelectedItem != TSL_cItemNotFound )
{
m_fn_vSetSelectedItem(iNewSelectedItem);
m_vScrollToMakeItemVisible((short) iNewSelectedItem);
m_fn_vRedrawSelectedItem(iNewSelectedItem);
}
else
m_fn_vUnselectItem();
//redraw the rectangle of the previously selected item too
if ( iPreviousSelectedItem != TSL_cItemNotFound )
m_fn_vRedrawSelectedItem(iPreviousSelectedItem);
}
//=============================================================================
// Description : Find Material item in list which correspond to the given engine material
// the index returned is the alphabetic index
//=============================================================================
int CMaterialListView::m_fn_iFindMaterial(tdoEditorGameMaterial *_p_oGameMaterial)
{
int iItem;
tdoEditorGameMaterial *p_oEditorMaterial;
for ( iItem = 0; iItem < m_fn_lGetCount(); iItem++)
{
p_oEditorMaterial = (tdoEditorGameMaterial *) m_fn_lGetContent(iItem);
if ((p_oEditorMaterial != NULL) && (p_oEditorMaterial == _p_oGameMaterial) )
return iItem;
}
return -1;
}
//=============================================================================
// try to make the object under the cursor use the currently selected material
//=============================================================================
void CMaterialListView::m_vApplyCurrentMaterialToObjectUnderCursor(HIE_tdstPickInfo *_p_stPickInfo)
{
M_p_oGetEditManager()->AskFor(new Material_ApplyMaterialModif(*_p_stPickInfo));
}
//=============================================================================
// handle function for OnLButtonDown
//=============================================================================
void CMaterialListView::OnLButtonDown(UINT nFlags, CPoint pt)
{
POINT stScreenPos;
C3ListView::OnLButtonDown( nFlags, pt);
GetCursorPos(&stScreenPos);
HIE_aDEF_stTabOfPickInfo a_stPickInfo;
if ( xGetPickInfoUnderPoint(&a_stPickInfo, stScreenPos) )
m_vApplyCurrentMaterialToObjectUnderCursor(a_stPickInfo);
}
//=============================================================================
//=============================================================================
Material_ApplyMaterialModif::Material_ApplyMaterialModif(
HIE_tdstPickInfo &_r_stPickInfo
)
: CPA_Modif(0, "Game material drop")
{
m_p_oMaterialListView = gs_p_oMaterialInterface->m_p_oGetMaterialListView();
m_p_oGeometry = (Geometry3D*)gs_p_oMaterialInterface->GetMainWorld()
->fn_p_oFindObjectWithEngine(
_r_stPickInfo.hGeoObject,
C_szGeometricObjectTypeName
);
if ( m_p_oGeometry )
{
m_xPickedElement = _r_stPickInfo.stPickedObject.aDEF_stDataOfElement[0].xElements;
//TODO: is xIndexOfFace valid for spheres , lines or points ?
m_xIndexInElement = _r_stPickInfo.stPickedObject.aDEF_stDataOfElement[0].xIndexOfFace;
m_p_oMaterialBeforeDo = (tdoEditorGameMaterial *)
m_p_oGeometry->fn_p_oGetGameMaterial(m_xPickedElement, m_xIndexInElement);
//ASSERT(m_p_oMaterialBeforeDo);
m_p_oMaterialAfterDo = (tdoEditorGameMaterial *) m_p_oMaterialListView
->m_fn_lGetContent(m_p_oMaterialListView->m_fn_lGetSelectedItem());
//ASSERT(m_p_oMaterialAfterDo);
m_bSwingFace = FALSE;
// ANNECY MT - 15/09/98 {
/*
//ask if we want to apply the material to all faces of the IT or to the picked face only
if ( m_p_oGeometry->fn_bIsIndexedTriangle(m_xPickedElement) )
m_bSwingFace = gs_p_oMaterialInterface->m_bSplitIndexedTriangle();
//m_bSwingFace = (AfxMessageBox("Apply the material to this face only", MB_YESNO) == IDYES);
*/
// END ANNECY MT }
//if materials do not belong to the same file, forbid material drop
CPA_FileObject *p_oCommonGMTFile = p_oGetFileObjectForReferencedPath(C_szFileNameForDefaultMaterial);
CPA_FileObject *p_oInitialFileObject = (CPA_FileObject *) (m_p_oMaterialBeforeDo ? m_p_oMaterialBeforeDo->GetOwner() : NULL);
CPA_FileObject *p_oFinalFileObject = (CPA_FileObject *) m_p_oMaterialAfterDo->GetOwner();
if //make sure the user wants to do this
(
(p_oInitialFileObject != p_oFinalFileObject) //if both materials do not come from the same file
&& (p_oInitialFileObject != p_oCommonGMTFile && p_oFinalFileObject != p_oCommonGMTFile) //and those files are not the common file
)
{
int iMixMaterials = AfxMessageBox(
"The material being replaced does not belong to the file of the material being dropped\n"
"In some cases, this might cause some levels to become interdependant\n"
"(the current level will need another level to be loaded)\n"
"Are you sure you want to do this ?",
MB_YESNO
);
//if not, output a status message, and prevent completion of the modif
if ( iMixMaterials != IDYES )
{
CString csMessage("You cannot drop a material from ");
csMessage += ((CPA_FileObject *) m_p_oMaterialAfterDo->GetOwner())->GetReferencedName(gs_p_oMaterialInterface, C_szFileReferencedNameKey);
fn_vGiveProgressInfo(csMessage + " on object '" + m_p_oGeometry->GetName() + "'", -1, C_STATUS_WARNING);
m_p_oGeometry = NULL;
}
}
}
}
//=============================================================================
//=============================================================================
BOOL Material_ApplyMaterialModif::Do()
{
if (!m_p_oMaterialAfterDo)
return FALSE;
return m_bDoIt(m_p_oMaterialBeforeDo, m_p_oMaterialAfterDo, TRUE);
}
//=============================================================================
//=============================================================================
BOOL Material_ApplyMaterialModif::Undo()
{
return m_bDoIt(m_p_oMaterialAfterDo, m_p_oMaterialBeforeDo, FALSE);
}
//=============================================================================
//=============================================================================
BOOL Material_ApplyMaterialModif::m_bDoIt(
tdoEditorGameMaterial *_p_oBefore,
tdoEditorGameMaterial *_p_oAfter,
BOOL _bSplitElement
)
{
//do nothing if both implied materials are identical
if ( _p_oBefore == _p_oAfter )
return FALSE;
//ROMTEAM WorldEditor (Cristi Petrescu 22/12/97)
// check for zone object
// workaround to find which type of zone (if any) is the father of the geometric object
CPA_EditorBase *poZoneEditor = gs_p_oMaterialInterface -> GetMainWorld () -> GetEditorByName ("Zone");
ASSERT (poZoneEditor);
// the zone type
long lEngineType = poZoneEditor -> OnQueryAction (gs_p_oMaterialInterface, C_uiQueryTypeOfZoneByGeometricObject, (long) m_p_oGeometry);
GMT_tdxHandleToGameMaterial hGameMaterial = m_p_oMaterialAfterDo -> m_hGetEngineMaterial ();
GMT_tdxHandleToCollideMaterial hCollideMaterial = GMT_fn_hGetCollideMaterial (hGameMaterial);
// the collision material type
if (hCollideMaterial != GMT_C_InvalidCollideMaterial)
{
if (lEngineType == -1)
{
// no zone
if (IDNO == MessageBox (NULL,
"The object is not a zone.\n"
"Are you sure you want to drop\n"
"a material with collision properties on it?\n",
"Material warning",
MB_ICONEXCLAMATION | MB_YESNO))
// infirmation ...
return FALSE;
}
else
{
// there is a collision material for this game material...
WORD m_uwTypeOfZone = GMT_fn_wGetTypeOfCollideMaterial (hCollideMaterial);
BOOL bWrongCollideMaterial = FALSE;
char szMessage[255];
char *szZone;
strcpy (szMessage, "The collide material is ");
switch (lEngineType)
{
case C_lZDM:
szZone = "ZDM";
break;
case C_lZDR:
szZone = "ZDR";
break;
case C_lZDE:
szZone = "ZDE";
break;
}
switch (m_uwTypeOfZone)
{
case 0:
if (lEngineType != C_lZDM)
{
strcat (szMessage, "ZDM");
bWrongCollideMaterial = TRUE;
}
break;
case 1:
if (lEngineType != C_lZDR)
{
strcat (szMessage, "ZDR");
bWrongCollideMaterial = TRUE;
}
break;
case 2:
if (lEngineType != C_lZDE)
{
strcat (szMessage, "ZDE");
bWrongCollideMaterial = TRUE;
}
break;
}
if (bWrongCollideMaterial)
{
strcat (szMessage, ", but the object is a ");
strcat (szMessage, szZone);
strcat (szMessage, " zone.");
M_GetMainWnd()->UpdateStatus(szMessage, C_STATUSPANE_INFOS, C_STATUS_ERROR);
return FALSE;
}
}
}
else
{
if (lEngineType != -1)
{
// dropping a material without collision props on a zone
if (IDNO == MessageBox (NULL,
"The object is a zone.\n"
"Are you sure you want to drop\n"
"a material with no collision properties on it?\n",
"Material warning",
MB_ICONEXCLAMATION | MB_YESNO))
// infirmation ...
return FALSE;
}
}
//ENDROMTEAM WorldEditor (Cristi Petrescu)
if ( m_p_oGeometry /*&& _p_oBefore && _p_oAfter*/ )
{
//if no element is created, the current material may become unrefenced, so remove a link
if ( _p_oBefore && (!m_bSwingFace || !_bSplitElement) )
g_oCoherenceManager.m_fn_vRemoveALink(m_p_oGeometry, _p_oBefore);
//in any case, the new material becomes referenced
if ( _p_oAfter )
g_oCoherenceManager.m_fn_vAddALink(m_p_oGeometry, _p_oAfter);
ACP_tdxIndex xMaterialedElement, xMaterialedIndexInElement;
// ANNECY MT - 15/09/98 {
/*
if ( m_bSwingFace ) //the user wants to move the IT face into a FMD before applying the material
{
if ( _bSplitElement ) //move the face from the IT to the FMD
{
m_p_oGeometry->fn_vMoveFaceToFaceDescriptors(m_xPickedElement, m_xIndexInElement, &m_xElementFMD, &m_xFaceFMD);
//GEO_fn_vMoveFaceToFaceDescriptors((ACP_tdxHandleOfObject) m_p_oGeometry->GetData(), m_xPickedElement, m_xIndexInElement, &m_xElementFMD, &m_xFaceFMD);
//we will apply the material to the face in the facemap descriptor
xMaterialedElement = m_xElementFMD;
xMaterialedIndexInElement = m_xFaceFMD;
}
else //move the face back from the FMD to the IT
{
m_p_oGeometry->fn_vMoveFaceDescriptorsToFace(m_xElementFMD, m_xFaceFMD, m_xPickedElement, m_xIndexInElement);
//GEO_fn_vMoveFaceDescriptorsToFace((ACP_tdxHandleOfObject) m_p_oGeometry->GetData(), m_xElementFMD, m_xFaceFMD, m_xPickedElement, m_xIndexInElement);
//we will apply the material to the indexed triangle element
xMaterialedElement = m_xPickedElement;
xMaterialedIndexInElement = m_xIndexInElement;
}
//GEO_vEndModifyObject2((ACP_tdxHandleOfObject) m_p_oGeometry->GetData());
//make the geometric object notify that those 2 elements are to be saved
m_p_oGeometry->fn_vNotifySaveElement(m_xPickedElement);
if ( m_xElementFMD != m_xPickedElement )
m_p_oGeometry->fn_vNotifySaveElement(m_xElementFMD);
}
else
*/
// END ANNECY MT }
{
xMaterialedElement = m_xPickedElement;
xMaterialedIndexInElement = m_xIndexInElement;
}
//set the new material for the triangles
m_p_oGeometry->fn_vSetGameMaterial(xMaterialedElement, xMaterialedIndexInElement, (CPA_BaseObject *) _p_oAfter);
//redraw the material list in case the aspect changed, because if the replaced material
//is no longer used and the list displays only used materials, it will disappear
m_p_oMaterialListView->m_vRefreshDisplayedMaterialList(m_p_oMaterialListView->m_bDisplayAll);
m_p_oMaterialListView->Invalidate();
//redraw the viewport contents to see the new material
gs_p_oMaterialInterface->GetInterface()->fn_vUpdateAll(E_mc_JustDraw);
//tell the object it has to be saved because the material changed. If we modified the
//faces, it is not necessary because the notification is already done
// ANNECY MT - 15/09/98 {
/*
if ( !m_bSwingFace )
*/
// END ANNECY MT }
m_p_oGeometry->fn_vNotifySaveElement(xMaterialedElement);
//
return TRUE;
}
return FALSE;
}
//=============================================================================
//change the bitmap associated to a game material item according to its unanimated texture
//=============================================================================
void CMaterialListView::m_vResetMaterialItemTexture(tdoEditorGameMaterial *_p_oGameMaterial)
{
//find the item for the game material in the material list
int iMaterialIndex = m_fn_iFindMaterial(_p_oGameMaterial);
//find the index of the bitmap corresponding to its unanimated texture
int iImageIndex = m_iGetTextureIndexForGameMaterial(_p_oGameMaterial, FALSE);
//change the item's image accordingly
m_fn_vSetItemImage(iMaterialIndex, iImageIndex);
//then redraw it
m_fn_vRedrawSelectedItem(iMaterialIndex);
}
//=============================================================================
// Description : returns the index of the bitmap that represents the current
// texture of the specified editor game material
//=============================================================================
int CMaterialListView::m_iGetTextureIndexForGameMaterial(
tdoEditorGameMaterial *_p_oGameMaterial,
BOOL _bLoadIfNotFound
)
{
GMT_tdxHandleToGameMaterial hGameMaterial = _p_oGameMaterial->m_hGetEngineMaterial();
int iImage;
if ( GMT_fn_b_ulIsValid(hGameMaterial) )
{
//get the visual material
ACP_tdxHandleOfMaterial hVisualMaterial = GMT_fn_hGetVisualMaterial(_p_oGameMaterial->m_hGetEngineMaterial());
tdoEditorVisualMaterial *p_oVisualMaterial = (tdoEditorVisualMaterial *) gs_p_oMaterialInterface->m_p_oGetEditorObjectForEngine(hVisualMaterial);
long lNbTextures = GLI_lGetMaterialNumberOfAnimatedTexture(hVisualMaterial);
//if we dont load the associated bitmaps, just go for the first texture of the list
if ( !lNbTextures )
{
iImage = m_fn_p_oGetBitmapList()->m_fn_iGetBitmapIndex(C_szNoBitmapName);
m_fn_p_oGetBitmapList()->m_fn_vSetBitmapLong(iImage, 0);
}
else
{
if ( !_bLoadIfNotFound && lNbTextures )
lNbTextures = 1;
for ( lNbTextures --; lNbTextures >= 0; lNbTextures -- ) //scan all textures in animation list
{
//get its texture, and the associated editor texture as well
float fDuration;
GLI_tdstTexture *p_stTexture;
GLI_vGetMaterialAnimatedTexture(hVisualMaterial, lNbTextures, &p_stTexture, &fDuration);
//find the bitmap used as texture
tdoEditorTexture *p_oEditorTexture = (tdoEditorTexture *) gs_p_oMaterialInterface->m_p_oGetEditorObjectForEngine(p_stTexture);
//SCR_tdst_Link_Value *p_stTextureEntry = SCR_fnp_st_Link_SearchValue(GLI_p_stGetLinkTableOfTexture(), (unsigned long) p_stTexture);
//char *pszTextureName = SCR_M_p_sz_Link_GetKey(p_stTextureEntry) + SCR_M_ul_Link_GetAdditionalLong(p_stTextureEntry, 1);
//normally the bitmap list references all bitmaps found in the texture directory...
iImage = m_fn_p_oGetBitmapList()->m_fn_iGetBitmapIndex((char *)LPCTSTR(p_oEditorTexture->m_csGetTextureName())/*pszTextureName*/);
if ( iImage == -1 ) //the bitmap is not yet loaded
{
if ( _bLoadIfNotFound ) //if we want to load it
{
//remember current directory
char szCurDir[_MAX_PATH];
long lCurDirLen = _MAX_PATH;
lCurDirLen = GetCurrentDirectory(lCurDirLen, szCurDir);
//change to the textures directory
if (!SetCurrentDirectory(fn_szGetTexturesDataPath()))
//return a failsafe bitmap index if an error occured
iImage = m_fn_p_oGetBitmapList()->m_fn_iGetBitmapIndex(C_szUnviewableBitmapName);
else
{
//load the bitmap in the bitmap list
tdoEditorVisualMaterial *p_oMaterial = (tdoEditorVisualMaterial *)
gs_p_oMaterialInterface->m_p_oGetEditorObjectForEngine(hVisualMaterial);
iImage = m_fn_p_oGetBitmapList()->m_fn_iAdd(p_oEditorTexture->m_csGetTextureName());
//and restore the previous directory
SetCurrentDirectory(szCurDir);
//if we could load the image, associate it to the texture
if ( iImage != -1 )
m_fn_p_oGetBitmapList()->m_fn_vSetBitmapLong(iImage, (long) p_stTexture);
else
//get the image corresponding to an unviewable texture
iImage = m_fn_p_oGetBitmapList()->m_fn_iGetBitmapIndex(C_szUnviewableBitmapName);
}
}
else
//load the image corresponding to an unviewable texture
iImage = m_fn_p_oGetBitmapList()->m_fn_iGetBitmapIndex(C_szUnviewableBitmapName);
}
else //the bitmap is already loaded: associate the texture to it
m_fn_p_oGetBitmapList()->m_fn_vSetBitmapLong(iImage, (long) p_stTexture);
} //for all textures in animated list
} //the material has a texture
}
else //the game material is not valid
iImage = m_fn_p_oGetBitmapList()->m_fn_iGetBitmapIndex(C_szUnviewableBitmapName);
return iImage;
}
//=============================================================================
//=============================================================================
void CMaterialListView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
gs_p_oMaterialInterface->_OnKeyDown(nChar, nRepCnt, nFlags);
}
//=============================================================================
//=============================================================================
void CMaterialListView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
gs_p_oMaterialInterface->_OnKeyUp(nChar, nRepCnt, nFlags);
}
//=============================================================================
// Description : update the image indexes for the listed game materials because
//the bitmaps were reloaded
//=============================================================================
void CMaterialListView::m_vBitmapListWasRefreshed(void)
{
for ( long lIndex = 0; lIndex < m_fn_lGetCount(); lIndex ++ )
{
//find the name of the texture for the game material
tdoEditorGameMaterial *p_oMaterial;
p_oMaterial = (tdoEditorGameMaterial *) m_fn_lGetContent(lIndex);
int iImage = m_iGetTextureIndexForGameMaterial(p_oMaterial, FALSE);
int iMaterialIndex = m_fn_iFindMaterial(p_oMaterial);
m_fn_vSetItemImage(iMaterialIndex, (short) iImage);
}
Invalidate();
}
//=============================================================================
//=============================================================================
void CMaterialListView::_OnCommand(short _wMenuId)
{
if ( _wMenuId == 9 )
m_vRefreshDisplayedMaterialList(!m_bDisplayAll);
else if ( _wMenuId == 10 )
m_vAnalyzeAllMaterials();
}
//=============================================================================
//=============================================================================
void CMaterialListView::_InitPopupMenu(CMenu &r_oMenu, short wFirstValue)
{
r_oMenu.AppendMenu(MF_SEPARATOR);
//make sure the id I want to use is available
ASSERT(9 >= wFirstValue);
r_oMenu.AppendMenu((m_bDisplayAll ? MF_CHECKED : MF_UNCHECKED) | MF_STRING, 9, "Display All");
if ( m_bDisplayAll )
r_oMenu.AppendMenu(MF_STRING, 10, "Analyze All");
}
//=============================================================================
//=============================================================================
void CMaterialListView::m_vAnalyzeAllMaterials()
{
BOOL bPrevLoadingWorld = gs_p_oMaterialInterface->GetInterface()->fn_bIsLoadingWorld();
//prevent object name prefixing, because all the objects that will be created now
//will get their names from existing sections
gs_p_oMaterialInterface->GetInterface()->SetLoadingWorld(TRUE);
long lCount, lNbMaterials = m_fn_lGetCount();
CString csStatusMessage;
csStatusMessage.Format("Analyzing %d materials", lNbMaterials);
for ( lCount = 0; lCount < lNbMaterials; lCount ++ )
{
tdoEditorGameMaterial *p_oGameMaterial = (tdoEditorGameMaterial *) m_fn_lGetContent(lCount);
fn_vGiveProgressInfo(csStatusMessage, (100 * lCount) / lNbMaterials);
if ( p_oGameMaterial && !p_oGameMaterial->fn_bIsAvailable() )
{
//make the editor material analyze its associated section to load the engine material
//but without uploading the texture to the graphic board
p_oGameMaterial->m_vLoadAssociatedEngineMaterial(FALSE);
int iImage = m_iGetTextureIndexForGameMaterial(p_oGameMaterial, TRUE);
//make the view update its display and show the correct texture
m_fn_vSetItemImage(lCount, (short) iImage);
m_fn_vRedrawSelectedItem(lCount);
}
}
fn_vGiveProgressInfo("", -1);
//restore prefixing mode (for new objects that we could create)
gs_p_oMaterialInterface->GetInterface()->SetLoadingWorld(bPrevLoadingWorld);
//now we can upload all textures to the board's vram
GLI_vEndofGeometricLoad();
//update the purge button status, in case all materials are now analyzed
gs_p_oMaterialInterface->m_p_oGetMainView()->m_vUpdatePurgeStatus();
//make the view redraw itself
}
//=============================================================================
//=============================================================================
void CMaterialListView::m_vRefreshDisplayedMaterialList(BOOL _bAllMaterials, BOOL _bKillAll /* = FALSE */)
{
if ( _bKillAll )
m_fn_bDeleteAllItems();
//update internal flag for menu
m_bDisplayAll = _bAllMaterials;
CPA_FileObject *p_oCurrentFileObject = gs_p_oMaterialInterface->m_p_oGetCurrentFileObject();
CPA_List<CPA_BaseObject> oListedMaterials;
if ( p_oCurrentFileObject )
gs_p_oMaterialInterface->GetMainWorld()->fn_lFindObjects(
&oListedMaterials,
"", // obj name
C_szGameMaterialTypeName, //type
p_oCurrentFileObject // owner
);
//find all editor material objects
long lCurMaterial = 0, lNbMaterials = oListedMaterials.GetCount();
POSITION xPos;
xPos = oListedMaterials.GetHeadPosition();
while ( xPos )
{
fn_vGiveProgressInfo("updating list of displayed materials", ((lCurMaterial ++) * 100) / lNbMaterials);
//extract the editor game material
tdoEditorGameMaterial *p_oGameMaterial = (tdoEditorGameMaterial *) oListedMaterials.GetNext(xPos);
if ( _bAllMaterials || p_oGameMaterial->m_bIsReferenced() )
{ //we want the material to be displayed
//find the material in the list
int iItem = m_fn_iFindMaterial(p_oGameMaterial);
if ( iItem == TSL_cItemNotFound )
{
//find an image to display for the material
int iImage = m_iGetTextureIndexForGameMaterial(p_oGameMaterial, TRUE);
//add the material to the list with the correct texture
int iAddedItem = m_fn_iAddItem(p_oGameMaterial->GetName(), (short) iImage, (long) p_oGameMaterial);
//m_fn_vSetItemImage(iAddedItem, iImage); ?
}
}
else if ( !_bKillAll) //we want the material not to be displayed, and all materials were not removed
{
//find the material in the list
int iItem = m_fn_iFindMaterial(p_oGameMaterial);
if ( iItem != TSL_cItemNotFound ) //if we found it, remove it from the list
{
//make the frames undisplay the material if we remove the selected material
if ( m_fn_lGetSelectedItem() == iItem )
{
m_fn_vUnselectItem();
gs_p_oMaterialInterface->m_fn_vShowMaterialAll();
}
m_fn_bDeleteItem(iItem);
}
}
}
fn_vGiveProgressInfo("", -1);
}
//=============================================================================
// Description : Create a new material
// template the given material or default material if parameter is null
//=============================================================================
void CMaterialListView::m_fn_vCreateNewMaterial(tdoEditorGameMaterial *_p_oTemplateMaterial, CString _csName)
{
Material_CreateOrCopyMaterialModif *p_oModif
= new Material_CreateOrCopyMaterialModif(_p_oTemplateMaterial, _csName);
M_p_oGetEditManager()->AskFor(p_oModif);
}
//=============================================================================
//=============================================================================
Material_CreateOrCopyMaterialModif::Material_CreateOrCopyMaterialModif
(
tdoEditorGameMaterial *_p_oTemplateMaterial,
CString _csName
)
: CPA_Modif(0, "")
{
m_p_oMaterialListView = gs_p_oMaterialInterface->m_p_oGetMaterialListView();
m_csNameToGive = _csName;
//create the engine material
m_hTemplateMaterial = GMT_fn_hCreateGameMaterial();
if ( _p_oTemplateMaterial )
{
SetName("Game material duplication");
//create a copy of the template material
GMT_fn_vCopyGameMaterial(m_hTemplateMaterial, _p_oTemplateMaterial->m_hGetEngineMaterial());
}
else
{
SetName("Game material creation");
//give the game material a visual material, which is the minimum
ACP_tdxHandleOfMaterial hVisualMaterial;
GLI_xCreateMaterial(&hVisualMaterial);
//now give it to the game material
GMT_fn_vSetVisualMaterial(m_hTemplateMaterial, hVisualMaterial);
//and create a set of initial values for future use
// GMT_fn_vSetGameMaterialInitialValues(m_hTemplateMaterial);
}
//if for redo/undo, I use a destroymodif to reuse the code...
m_p_oDestroyModif = NULL;
}
//=============================================================================
//=============================================================================
Material_CreateOrCopyMaterialModif::~Material_CreateOrCopyMaterialModif()
{
if ( m_p_oDestroyModif )
{
delete m_p_oDestroyModif;
m_p_oDestroyModif = NULL;
}
else
{
//if not even done once, the engine materials are not used, so we destroy them both
if ( !HasBeenDone() )
{
if ( GMT_fn_b_ulIsValid(m_hTemplateMaterial) )
{
//delete the visual material that was created especially for this template
ACP_tdxHandleOfMaterial hVisualMaterial = GMT_fn_hGetVisualMaterial(m_hTemplateMaterial);
GLI_xDeleteMaterial(hVisualMaterial);
//then delete the template itself
GMT_fn_vDestroyGameMaterial(m_hTemplateMaterial);
}
GMT_fn_vInvalidate(&m_hTemplateMaterial);
}
else
//if done once, the destroy modif exists, and we should not get here...
ASSERT(FALSE);
}
}
//=============================================================================
//=============================================================================
BOOL Material_CreateOrCopyMaterialModif::Do()
{
if ( m_p_oDestroyModif ) //this is hence a redo of creation -> an undo of destruction
return m_p_oDestroyModif->Undo();
else //no modif exists: this is the first do()
{
//create an editor material, containing a brand new engine material cloned from the template
//an editor visual material will be created automatically as well
//the new game material will be notified for save because its section does not exists
tdoEditorGameMaterial *p_oEditorGameMaterialAfterDo = new tdoEditorGameMaterial(
gs_p_oMaterialInterface->m_p_oGetCurrentFileObject(),
m_csNameToGive,
FALSE,
m_hTemplateMaterial
);
//remember the name that was actually given to the editor object
m_csNameToGive = p_oEditorGameMaterialAfterDo->GetName();
//retrieve the handle to the visual material and the associated editor object
ACP_tdxHandleOfMaterial hCreatedVisualMaterial = GMT_fn_hGetVisualMaterial(p_oEditorGameMaterialAfterDo->m_hGetEngineMaterial());
//get the handle to the bitmap for the material
GLI_tdstTexture *p_stTexture;
GLI_xGetMaterialTexture(hCreatedVisualMaterial, &p_stTexture);
//find the bitmap used as texture
int iImage;
if (p_stTexture == NULL)
iImage = m_p_oMaterialListView->m_fn_p_oGetBitmapList()->m_fn_iGetBitmapIndex(C_szNoBitmapName);
else
iImage = m_p_oMaterialListView->m_fn_p_oGetBitmapList()->m_fn_iGetBitmapIndexByLong((long) p_stTexture);
//add the editor material in the material list
long lIndexInListAfterDo = m_p_oMaterialListView->m_fn_iAddItem(
p_oEditorGameMaterialAfterDo->GetName(),
(short) iImage,
(long) p_oEditorGameMaterialAfterDo
);
m_p_oMaterialListView->m_fn_vSetItemImage(lIndexInListAfterDo, (short) iImage);
//make the list select this material and redraw itself
m_p_oMaterialListView->OnSelectItem((short) lIndexInListAfterDo);
m_p_oMaterialListView->m_vScrollToMakeItemVisible((short) lIndexInListAfterDo);
//create a destroy modif for future do/undo
m_p_oDestroyModif = new Material_DestroyMaterialModif(p_oEditorGameMaterialAfterDo);
return TRUE;
}
}
//=============================================================================
//=============================================================================
BOOL Material_CreateOrCopyMaterialModif::Undo()
{
ASSERT(m_p_oDestroyModif);
return m_p_oDestroyModif->Do(); //an undo of creation is a do of destruction
}
//=============================================================================
// Description : Delete selected material
// verify that material is unused
//=============================================================================
void CMaterialListView::m_fn_vDeleteMaterial(tdoEditorGameMaterial *_p_oMaterialToDelete)
{
//if the material has other fathers than its file (meaning there are geometric objects)
if ( _p_oMaterialToDelete->m_bIsReferenced() )
AfxMessageBox("Material used in scene, can't be deleted", MB_ICONSTOP | MB_OK );
else
{
//short wItemImageIndex = m_fn_wGetImage(iItem);
Material_DestroyMaterialModif *p_oModif = new Material_DestroyMaterialModif(_p_oMaterialToDelete);
M_p_oGetEditManager()->AskFor(p_oModif);
}
}
//=============================================================================
//=============================================================================
Material_DestroyMaterialModif::Material_DestroyMaterialModif(
tdoEditorGameMaterial *_p_oDeletedGameMaterial
)
: CPA_Modif(0, "Material deletion")
{
m_bMaterialWasInList = FALSE;
m_p_oMaterialListView = gs_p_oMaterialInterface->m_p_oGetMaterialListView();
//remember the editor game material
m_p_oDeletedGameMaterial = _p_oDeletedGameMaterial;
GMT_tdxHandleToGameMaterial hGameMaterial = m_p_oDeletedGameMaterial->m_hGetEngineMaterial();
//and the editor visual material as well
ACP_tdxHandleOfMaterial hVisualMaterial = GMT_fn_hGetVisualMaterial(hGameMaterial);
m_p_oDeletedVisualMaterial = (tdoEditorVisualMaterial *)
gs_p_oMaterialInterface->m_p_oGetEditorObjectForEngine(hVisualMaterial);
ASSERT(m_p_oDeletedVisualMaterial);
//prepare the do/undo of the associated collide material deletion
GMT_tdxHandleToCollideMaterial hMaterialCollide = GMT_fn_hGetCollideMaterial(hGameMaterial);
if ( hMaterialCollide != GMT_C_InvalidCollideMaterial )
m_p_oDeleteEngineCollideModif = new tdoDeleteEngineCollideModif(hGameMaterial, hMaterialCollide);
else
m_p_oDeleteEngineCollideModif = NULL;
//prepare the do/undo of the associated mechanics material deletion
DNM_tdxHandleToMecMatCharacteristics hMaterialMechanics = GMT_fn_hGetMechanicsMaterial(hGameMaterial);
if ( DNM_fn_bIsMatCharacteristicsValid(hMaterialMechanics) )
m_p_oDeleteEngineMechanicsModif = new tdoDeleteEngineMechanicsModif(hGameMaterial, hMaterialMechanics);
else
m_p_oDeleteEngineMechanicsModif = NULL;
}
//=============================================================================
//=============================================================================
Material_DestroyMaterialModif::~Material_DestroyMaterialModif()
{
//destroy the other modifs,
//they will take care of the fact that they have been done or not by themselves
if ( m_p_oDeleteEngineCollideModif )
delete m_p_oDeleteEngineCollideModif;
if ( m_p_oDeleteEngineMechanicsModif )
delete m_p_oDeleteEngineMechanicsModif;
//if the modif is not done or is undone, the objects are in use, so dont destroy them
if ( HasBeenDone() )
{
//tell the scripts we dont want to save the material
m_p_oDeletedGameMaterial->fn_vNotifyUnSave();
m_p_oDeletedVisualMaterial->fn_vNotifyUnSave();
//and destroy the objects
if ( m_p_oDeletedVisualMaterial )
{
//destroy the engine visual material
ACP_tdxHandleOfMaterial hVisualMaterial = m_p_oDeletedVisualMaterial->m_hGetEngineMaterial();
if ( hVisualMaterial )
GLI_xDeleteMaterial(hVisualMaterial);
//destroy the editor visual material
delete m_p_oDeletedVisualMaterial;
m_p_oDeletedVisualMaterial = NULL;
}
if ( m_p_oDeletedGameMaterial )
{
//destroy the engine game material
GMT_tdxHandleToGameMaterial hGameMaterial = m_p_oDeletedGameMaterial->m_hGetEngineMaterial();
if ( GMT_fn_b_ulIsValid(hGameMaterial) )
GMT_fn_vDestroyGameMaterial(hGameMaterial);
//destroy the editor game material
delete m_p_oDeletedGameMaterial;
m_p_oDeletedGameMaterial = NULL;
}
}
}
//=============================================================================
// do the material deletion
//=============================================================================
BOOL Material_DestroyMaterialModif::Do()
{
//disable the submaterials
BOOL bResult = TRUE;
if ( m_p_oDeleteEngineCollideModif )
bResult = m_p_oDeleteEngineCollideModif->Do();
if ( bResult && m_p_oDeleteEngineMechanicsModif )
bResult = m_p_oDeleteEngineMechanicsModif->Do();
//if this succeeded, remove the visual and game materials
if ( bResult )
{
//remove the links between the game material and its submaterial
g_oCoherenceManager.m_fn_vRemoveALink(m_p_oDeletedGameMaterial, m_p_oDeletedVisualMaterial);
//make the hierarchy believe the objects no longer exist
m_p_oDeletedVisualMaterial->fn_bUnValidate();
m_p_oDeletedGameMaterial->fn_bUnValidate();
//tell we dont want to save the game and visual materials
m_p_oDeletedGameMaterial->fn_vNotifyUnSave();
m_p_oDeletedVisualMaterial->fn_vNotifyUnSave();
//remove the material from the list of displayed materials, if relevant
int iItem = m_p_oMaterialListView->m_fn_iFindMaterial(m_p_oDeletedGameMaterial);
if ( iItem != TSL_cItemNotFound )
{
m_bMaterialWasInList = TRUE;
m_p_oMaterialListView->m_fn_bDeleteItem(iItem);
m_p_oMaterialListView->m_fn_vChangeDisplayType(m_p_oMaterialListView->m_cDisplayType);
}
gs_p_oMaterialInterface->m_fn_vShowMaterialAll();
}
return bResult;
}
//=============================================================================
// undo/redo the material deletion
//=============================================================================
BOOL Material_DestroyMaterialModif::Undo()
{
//reinsert the objects in the lists of the hierarchy editor
m_p_oDeletedGameMaterial->fn_bValidate();
m_p_oDeletedVisualMaterial->fn_bValidate();
//and tell the scripts the objects have to be saved
m_p_oDeletedGameMaterial->fn_vNotifyRestore();
m_p_oDeletedVisualMaterial->fn_vNotifyRestore();
//if the material was displayed before we removed it, make it visible again.
//note that if this material has no links, it might appear nonetheless in the view
//whereas the mode is to display only used materials...
if ( m_bMaterialWasInList )
{
//get the handle to the bitmap for the material
GLI_tdstTexture *p_stTexture;
GLI_xGetMaterialTexture(m_p_oDeletedVisualMaterial->m_hGetEngineMaterial(), &p_stTexture);
//find the bitmap used as texture
int iImage;
if (p_stTexture == NULL)
iImage = m_p_oMaterialListView->m_fn_p_oGetBitmapList()->m_fn_iGetBitmapIndex(C_szNoBitmapName);
else
iImage = m_p_oMaterialListView->m_fn_p_oGetBitmapList()->m_fn_iGetBitmapIndexByLong((long) p_stTexture);
//reinsert an item in the list
m_p_oMaterialListView->m_fn_iAddItem(
m_p_oDeletedGameMaterial->GetName(),
(short) iImage,
(long) m_p_oDeletedGameMaterial
);
}
//now reenable the submaterials
BOOL bResult = TRUE;
if ( m_p_oDeleteEngineMechanicsModif )
bResult = m_p_oDeleteEngineMechanicsModif->Undo();
if ( bResult && m_p_oDeleteEngineCollideModif )
bResult = m_p_oDeleteEngineCollideModif->Undo();
//and display the material we deleted
gs_p_oMaterialInterface->m_fn_vShowMaterialAll(m_p_oDeletedGameMaterial);
return TRUE;
}