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