You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
472 lines
11 KiB
472 lines
11 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: Implements an owner-draw combo box containing the names and thumbnail |
|
// images of textures. The textures are gotten from the global texture |
|
// manager object, and are filtered by texture format. |
|
// |
|
//============================================================================= |
|
|
|
#include "stdafx.h" |
|
#include "GameConfig.h" |
|
#include "IEditorTexture.h" |
|
#include "TextureBox.h" |
|
#include "TextureSystem.h" |
|
#include "hammer.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include <tier0/memdbgon.h> |
|
|
|
|
|
BEGIN_MESSAGE_MAP(CTextureBox, CComboBox) |
|
//{{AFX_MSG_MAP(CTextureBox) |
|
ON_WM_ERASEBKGND() |
|
ON_MESSAGE(CB_SELECTSTRING, OnSelectString) |
|
//}}AFX_MSG_MAP |
|
END_MESSAGE_MAP() |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CTextureBox::CTextureBox(void) |
|
{ |
|
bFirstMeasure = TRUE; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CTextureBox::~CTextureBox(void) |
|
{ |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : lpCompareItemStruct - |
|
// Output : int |
|
//----------------------------------------------------------------------------- |
|
int CTextureBox::CompareItem(LPCOMPAREITEMSTRUCT lpCompareItemStruct) |
|
{ |
|
return 0; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : lpDeleteItemStruct - |
|
//----------------------------------------------------------------------------- |
|
void CTextureBox::DeleteItem(LPDELETEITEMSTRUCT lpDeleteItemStruct) |
|
{ |
|
CComboBox::DeleteItem(lpDeleteItemStruct); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : lpDrawItemStruct - |
|
//----------------------------------------------------------------------------- |
|
void CTextureBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) |
|
{ |
|
// if(!pGD) |
|
// return; |
|
|
|
CDC dc; |
|
dc.Attach(lpDrawItemStruct->hDC); |
|
dc.SaveDC(); |
|
|
|
RECT& r = lpDrawItemStruct->rcItem; |
|
|
|
int iFontHeight = dc.GetTextExtent("J", 1).cy; |
|
|
|
if (lpDrawItemStruct->itemID != -1) |
|
{ |
|
IEditorTexture *pTex = (IEditorTexture *)GetItemDataPtr(lpDrawItemStruct->itemID); |
|
dc.SetROP2(R2_COPYPEN); |
|
CPalette *pOldPalette = NULL; |
|
|
|
if (pTex != NULL) |
|
{ |
|
pTex->Load(); |
|
|
|
pOldPalette = dc.SelectPalette(pTex->HasPalette() ? pTex->GetPalette() : g_pGameConfig->Palette, FALSE); |
|
dc.RealizePalette(); |
|
} |
|
|
|
COLORREF dwBackColor = RGB(255,255,255); |
|
COLORREF dwForeColor = RGB(0,0,0); |
|
|
|
if (lpDrawItemStruct->itemState & ODS_SELECTED) |
|
{ |
|
dwBackColor = GetSysColor(COLOR_HIGHLIGHT); |
|
dwForeColor = GetSysColor(COLOR_HIGHLIGHTTEXT); |
|
} |
|
|
|
// draw background |
|
CBrush brush; |
|
brush.CreateSolidBrush(dwBackColor); |
|
dc.FillRect(&r, &brush); |
|
|
|
if (pTex == NULL) |
|
{ |
|
// separator |
|
dc.SelectStockObject(BLACK_PEN); |
|
dc.MoveTo(r.left, r.top+5); |
|
dc.LineTo(r.right, r.top+5); |
|
} |
|
else |
|
{ |
|
char szName[MAX_PATH]; |
|
int iLen = pTex->GetShortName(szName); |
|
|
|
// when we get here, we are drawing a regular graphic. we |
|
// check the size of the rectangle - if it's > 32 (just |
|
// a nice number), we're drawing an item in the drop list. |
|
if ((r.bottom - r.top) > 32) |
|
{ |
|
DrawTexData_t DrawTexData; |
|
DrawTexData.nFlags = 0; |
|
|
|
// draw graphic |
|
CRect r2(r); |
|
r2.InflateRect(-4, -4); |
|
r2.right = r2.left + 64; |
|
pTex->Draw(&dc, r2, 0, 0, DrawTexData); |
|
|
|
// draw name |
|
dc.SetTextColor(dwForeColor); |
|
dc.SetBkMode(TRANSPARENT); |
|
dc.TextOut(r2.right + 4, r2.top + 4, szName, iLen); |
|
|
|
// draw size |
|
sprintf(szName, "%dx%d", pTex->GetWidth(), pTex->GetHeight()); |
|
dc.TextOut(r2.right + 4, r2.top + 4 + iFontHeight, szName, strlen(szName)); |
|
} |
|
// if it's < 32, we're drawing the item in the "closed" |
|
// combo box, so just draw the name of the texture |
|
else |
|
{ |
|
// just draw name - |
|
dc.SetTextColor(dwForeColor); |
|
dc.SetBkMode(TRANSPARENT); |
|
dc.TextOut(r.left + 4, r.top + 2, szName, iLen); |
|
} |
|
} |
|
|
|
if (pOldPalette) |
|
{ |
|
dc.SelectPalette(pOldPalette, FALSE); |
|
} |
|
} |
|
else if (lpDrawItemStruct->itemState & ODS_FOCUS) |
|
{ |
|
dc.DrawFocusRect(&r); |
|
} |
|
|
|
dc.RestoreDC(-1); |
|
dc.Detach(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Adds the given texture to the MRU for this texture list. |
|
// Input : pTex - Texture to add. If NULL, MRU is rebuilt from scratch. |
|
//----------------------------------------------------------------------------- |
|
void CTextureBox::AddMRU(IEditorTexture *pTex) |
|
{ |
|
if (pTex != NULL) |
|
{ |
|
// |
|
// Add the texture to the MRU set. |
|
// |
|
g_Textures.AddMRU(pTex); |
|
|
|
// |
|
// Update the list contents based on the new MRU set. |
|
// |
|
RebuildMRU(); |
|
|
|
// |
|
// Select the newly added texture, which should be at index 0. |
|
// |
|
SetCurSel(0); |
|
|
|
Invalidate(); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Rebuilds the MRU for this texture combo box. |
|
//----------------------------------------------------------------------------- |
|
void CTextureBox::RebuildMRU(void) |
|
{ |
|
SetRedraw(FALSE); |
|
|
|
int nCurSel = GetCurSel(); |
|
|
|
// |
|
// Delete current MRUs from list. |
|
// |
|
int nItems = GetCount(); |
|
int nDelimiterIndex = 0; |
|
while (nDelimiterIndex < nItems) |
|
{ |
|
// |
|
// The first item with a NULL item data pointer is the MRU delimiter. |
|
// |
|
if (GetItemDataPtr(nDelimiterIndex) == NULL) |
|
{ |
|
break; |
|
} |
|
|
|
nDelimiterIndex++; |
|
} |
|
|
|
// |
|
// If the MRU delimiter was found, delete everything before it. |
|
// |
|
if (nDelimiterIndex != nItems) |
|
{ |
|
do |
|
{ |
|
DeleteString(0); |
|
} while(nDelimiterIndex--); |
|
} |
|
|
|
// |
|
// Add each texture from the graphics MRU to this list's MRU. |
|
// |
|
int nStrCount = 0; |
|
int nMRUCount = g_Textures.MRUGetCount(); |
|
for (int nMRU = 0; nMRU < nMRUCount; nMRU++) |
|
{ |
|
IEditorTexture *pTex = g_Textures.MRUGet(nMRU); |
|
if (pTex != NULL) |
|
{ |
|
char szBuf[MAX_PATH]; |
|
pTex->GetShortName(szBuf); |
|
|
|
int nIndex = InsertString(nStrCount, szBuf); |
|
SetItemDataPtr(nIndex, pTex); |
|
nStrCount++; |
|
} |
|
} |
|
|
|
// |
|
// Add the MRU seperator to the list, unless the MRU was empty. |
|
// |
|
if (nStrCount > 0) |
|
{ |
|
int nIndex = InsertString(nStrCount, ""); |
|
SetItemDataPtr(nIndex, NULL); |
|
} |
|
|
|
// |
|
// Restore the original selection. |
|
// |
|
SetCurSel(nCurSel); |
|
SetRedraw(TRUE); |
|
Invalidate(); |
|
} |
|
|
|
|
|
void CTextureBox::NotifyNewMaterial( IEditorTexture *pTex ) |
|
{ |
|
char szStr[MAX_PATH]; |
|
pTex->GetShortName( szStr ); |
|
int iItem = AddString( szStr ); |
|
if ( iItem != CB_ERR ) |
|
{ |
|
SetItemDataPtr( iItem, (void *)pTex ); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : lpMeasureItemStruct - |
|
//----------------------------------------------------------------------------- |
|
void CTextureBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) |
|
{ |
|
lpMeasureItemStruct->itemWidth = 64; |
|
|
|
// |
|
// If the item data is NULL or points to an empty string, it's the separator. |
|
// |
|
char *pszText = (char *)lpMeasureItemStruct->itemData; |
|
|
|
if ((pszText == NULL) || (*pszText == '\0')) |
|
{ |
|
lpMeasureItemStruct->itemHeight = 9; |
|
} |
|
else |
|
{ |
|
lpMeasureItemStruct->itemHeight = 64 + 8; |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTextureBox::LoadGraphicList(void) |
|
{ |
|
if (g_pGameConfig->GetTextureFormat() == tfNone) |
|
{ |
|
return; |
|
} |
|
|
|
SetRedraw(FALSE); |
|
ResetContent(); |
|
InitStorage(g_Textures.GetActiveTextureCount() + 32, sizeof(PVOID)); |
|
|
|
// |
|
// Add the MRU textures to the list. |
|
// |
|
int nStrCount = 0; |
|
int nMRUCount = g_Textures.MRUGetCount(); |
|
for (int nMRU = 0; nMRU < nMRUCount; nMRU++) |
|
{ |
|
IEditorTexture *pTex = g_Textures.MRUGet(nMRU); |
|
if (pTex != NULL) |
|
{ |
|
char szStr[MAX_PATH]; |
|
pTex->GetShortName(szStr); |
|
AddString(szStr); |
|
SetItemDataPtr(nStrCount, (void *)pTex); |
|
nStrCount++; |
|
} |
|
} |
|
|
|
// |
|
// Add the MRU seperator to the list, unless the MRU was empty. |
|
// |
|
if (nStrCount > 0) |
|
{ |
|
AddString(""); |
|
SetItemDataPtr(nStrCount, NULL); |
|
nStrCount++; |
|
} |
|
|
|
// |
|
// Add the rest of the textures to the list. |
|
// |
|
int nIndex = 0; |
|
IEditorTexture *pTex = g_Textures.EnumActiveTextures(&nIndex, g_pGameConfig->GetTextureFormat()); |
|
while (pTex != NULL) |
|
{ |
|
char szStr[MAX_PATH]; |
|
pTex->GetShortName(szStr); |
|
int err = AddString(szStr); |
|
Assert( (err != CB_ERR) && (err != CB_ERRSPACE) ); |
|
SetItemDataPtr(nStrCount, (void *)pTex); |
|
nStrCount++; |
|
|
|
pTex = g_Textures.EnumActiveTextures(&nIndex, g_pGameConfig->GetTextureFormat()); |
|
} |
|
|
|
// |
|
// Hack: Select one that doesn't start with '+', '!', or '*', and doesn't have "door" in it. |
|
// |
|
SetCurSel(0); |
|
|
|
int nSel = GetCount(); |
|
for (int i = 0; i < nSel; i++) |
|
{ |
|
IEditorTexture *pTexSearch = (IEditorTexture *)GetItemDataPtr(i); |
|
if (pTexSearch != NULL) |
|
{ |
|
char szName[MAX_PATH]; |
|
pTexSearch->GetShortName(szName); |
|
|
|
if ((szName[0] != 0) && (szName[0] != '*') && (szName[0] != '+') && (szName[0] != '!') && (strstr(szName, "door") == NULL)) |
|
{ |
|
// this one is ok |
|
SetCurSel(i); |
|
break; |
|
} |
|
} |
|
} |
|
|
|
SetRedraw(TRUE); |
|
Invalidate(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : dwStyle - |
|
// rect - |
|
// pParentWnd - |
|
// nID - |
|
// Output : Returns TRUE on success, FALSE on failure. |
|
//----------------------------------------------------------------------------- |
|
BOOL CTextureBox::Create(DWORD dwStyle, const RECT &rect, CWnd *pParentWnd, UINT nID) |
|
{ |
|
static BOOL bInitClass = TRUE; |
|
static LPCTSTR pszTextureBoxClass = "TextureBox"; |
|
|
|
if(bInitClass) |
|
{ |
|
bInitClass = FALSE; |
|
|
|
// get default class provided by MFC |
|
WNDCLASS wndclass; |
|
GetClassInfo(AfxGetInstanceHandle(), _T("COMBOBOX"), &wndclass); |
|
wndclass.hbrBackground = NULL; |
|
wndclass.lpszClassName = pszTextureBoxClass; |
|
|
|
AfxRegisterClass(&wndclass); |
|
} |
|
|
|
return CWnd::Create(pszTextureBoxClass, NULL, dwStyle, rect, pParentWnd, nID); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : wParam - |
|
// lParam - |
|
// Output : LRESULT |
|
//----------------------------------------------------------------------------- |
|
LRESULT CTextureBox::OnSelectString(WPARAM wParam, LPARAM lParam) |
|
{ |
|
LPCTSTR pszSelect = LPCTSTR(lParam); |
|
int nCount = GetCount(); |
|
IEditorTexture *pTex; |
|
|
|
for(int i = wParam + 1; i < nCount; i++) |
|
{ |
|
pTex = (IEditorTexture *)GetItemDataPtr(i); |
|
if (pTex != NULL) |
|
{ |
|
char szName[MAX_PATH]; |
|
pTex->GetShortName(szName); |
|
if (!stricmp(szName, pszSelect)) |
|
{ |
|
SetCurSel(i); |
|
return i; |
|
} |
|
} |
|
} |
|
|
|
return LB_ERR; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : pDC - |
|
// Output : Returns TRUE on success, FALSE on failure. |
|
//----------------------------------------------------------------------------- |
|
BOOL CTextureBox::OnEraseBkgnd(CDC *pDC) |
|
{ |
|
CRect r; |
|
GetUpdateRect(r); |
|
pDC->SetROP2(R2_COPYPEN); |
|
FillRect(pDC->m_hDC, r, HBRUSH(GetStockObject(BLACK_BRUSH))); |
|
return TRUE; |
|
} |
|
|
|
|