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;
|
|
}
|
|
|