Team Fortress 2 Source Code as on 22/4/2020
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

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Implements an owner-draw combo box containing the names and thumbnail
  4. // images of textures. The textures are gotten from the global texture
  5. // manager object, and are filtered by texture format.
  6. //
  7. //=============================================================================
  8. #include "stdafx.h"
  9. #include "GameConfig.h"
  10. #include "IEditorTexture.h"
  11. #include "TextureBox.h"
  12. #include "TextureSystem.h"
  13. #include "hammer.h"
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include <tier0/memdbgon.h>
  16. BEGIN_MESSAGE_MAP(CTextureBox, CComboBox)
  17. //{{AFX_MSG_MAP(CTextureBox)
  18. ON_WM_ERASEBKGND()
  19. ON_MESSAGE(CB_SELECTSTRING, OnSelectString)
  20. //}}AFX_MSG_MAP
  21. END_MESSAGE_MAP()
  22. //-----------------------------------------------------------------------------
  23. // Purpose:
  24. //-----------------------------------------------------------------------------
  25. CTextureBox::CTextureBox(void)
  26. {
  27. bFirstMeasure = TRUE;
  28. }
  29. //-----------------------------------------------------------------------------
  30. // Purpose:
  31. //-----------------------------------------------------------------------------
  32. CTextureBox::~CTextureBox(void)
  33. {
  34. }
  35. //-----------------------------------------------------------------------------
  36. // Purpose:
  37. // Input : lpCompareItemStruct -
  38. // Output : int
  39. //-----------------------------------------------------------------------------
  40. int CTextureBox::CompareItem(LPCOMPAREITEMSTRUCT lpCompareItemStruct)
  41. {
  42. return 0;
  43. }
  44. //-----------------------------------------------------------------------------
  45. // Purpose:
  46. // Input : lpDeleteItemStruct -
  47. //-----------------------------------------------------------------------------
  48. void CTextureBox::DeleteItem(LPDELETEITEMSTRUCT lpDeleteItemStruct)
  49. {
  50. CComboBox::DeleteItem(lpDeleteItemStruct);
  51. }
  52. //-----------------------------------------------------------------------------
  53. // Purpose:
  54. // Input : lpDrawItemStruct -
  55. //-----------------------------------------------------------------------------
  56. void CTextureBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
  57. {
  58. // if(!pGD)
  59. // return;
  60. CDC dc;
  61. dc.Attach(lpDrawItemStruct->hDC);
  62. dc.SaveDC();
  63. RECT& r = lpDrawItemStruct->rcItem;
  64. int iFontHeight = dc.GetTextExtent("J", 1).cy;
  65. if (lpDrawItemStruct->itemID != -1)
  66. {
  67. IEditorTexture *pTex = (IEditorTexture *)GetItemDataPtr(lpDrawItemStruct->itemID);
  68. dc.SetROP2(R2_COPYPEN);
  69. CPalette *pOldPalette = NULL;
  70. if (pTex != NULL)
  71. {
  72. pTex->Load();
  73. pOldPalette = dc.SelectPalette(pTex->HasPalette() ? pTex->GetPalette() : g_pGameConfig->Palette, FALSE);
  74. dc.RealizePalette();
  75. }
  76. COLORREF dwBackColor = RGB(255,255,255);
  77. COLORREF dwForeColor = RGB(0,0,0);
  78. if (lpDrawItemStruct->itemState & ODS_SELECTED)
  79. {
  80. dwBackColor = GetSysColor(COLOR_HIGHLIGHT);
  81. dwForeColor = GetSysColor(COLOR_HIGHLIGHTTEXT);
  82. }
  83. // draw background
  84. CBrush brush;
  85. brush.CreateSolidBrush(dwBackColor);
  86. dc.FillRect(&r, &brush);
  87. if (pTex == NULL)
  88. {
  89. // separator
  90. dc.SelectStockObject(BLACK_PEN);
  91. dc.MoveTo(r.left, r.top+5);
  92. dc.LineTo(r.right, r.top+5);
  93. }
  94. else
  95. {
  96. char szName[MAX_PATH];
  97. int iLen = pTex->GetShortName(szName);
  98. // when we get here, we are drawing a regular graphic. we
  99. // check the size of the rectangle - if it's > 32 (just
  100. // a nice number), we're drawing an item in the drop list.
  101. if ((r.bottom - r.top) > 32)
  102. {
  103. DrawTexData_t DrawTexData;
  104. DrawTexData.nFlags = 0;
  105. // draw graphic
  106. CRect r2(r);
  107. r2.InflateRect(-4, -4);
  108. r2.right = r2.left + 64;
  109. pTex->Draw(&dc, r2, 0, 0, DrawTexData);
  110. // draw name
  111. dc.SetTextColor(dwForeColor);
  112. dc.SetBkMode(TRANSPARENT);
  113. dc.TextOut(r2.right + 4, r2.top + 4, szName, iLen);
  114. // draw size
  115. sprintf(szName, "%dx%d", pTex->GetWidth(), pTex->GetHeight());
  116. dc.TextOut(r2.right + 4, r2.top + 4 + iFontHeight, szName, strlen(szName));
  117. }
  118. // if it's < 32, we're drawing the item in the "closed"
  119. // combo box, so just draw the name of the texture
  120. else
  121. {
  122. // just draw name -
  123. dc.SetTextColor(dwForeColor);
  124. dc.SetBkMode(TRANSPARENT);
  125. dc.TextOut(r.left + 4, r.top + 2, szName, iLen);
  126. }
  127. }
  128. if (pOldPalette)
  129. {
  130. dc.SelectPalette(pOldPalette, FALSE);
  131. }
  132. }
  133. else if (lpDrawItemStruct->itemState & ODS_FOCUS)
  134. {
  135. dc.DrawFocusRect(&r);
  136. }
  137. dc.RestoreDC(-1);
  138. dc.Detach();
  139. }
  140. //-----------------------------------------------------------------------------
  141. // Purpose: Adds the given texture to the MRU for this texture list.
  142. // Input : pTex - Texture to add. If NULL, MRU is rebuilt from scratch.
  143. //-----------------------------------------------------------------------------
  144. void CTextureBox::AddMRU(IEditorTexture *pTex)
  145. {
  146. if (pTex != NULL)
  147. {
  148. //
  149. // Add the texture to the MRU set.
  150. //
  151. g_Textures.AddMRU(pTex);
  152. //
  153. // Update the list contents based on the new MRU set.
  154. //
  155. RebuildMRU();
  156. //
  157. // Select the newly added texture, which should be at index 0.
  158. //
  159. SetCurSel(0);
  160. Invalidate();
  161. }
  162. }
  163. //-----------------------------------------------------------------------------
  164. // Purpose: Rebuilds the MRU for this texture combo box.
  165. //-----------------------------------------------------------------------------
  166. void CTextureBox::RebuildMRU(void)
  167. {
  168. SetRedraw(FALSE);
  169. int nCurSel = GetCurSel();
  170. //
  171. // Delete current MRUs from list.
  172. //
  173. int nItems = GetCount();
  174. int nDelimiterIndex = 0;
  175. while (nDelimiterIndex < nItems)
  176. {
  177. //
  178. // The first item with a NULL item data pointer is the MRU delimiter.
  179. //
  180. if (GetItemDataPtr(nDelimiterIndex) == NULL)
  181. {
  182. break;
  183. }
  184. nDelimiterIndex++;
  185. }
  186. //
  187. // If the MRU delimiter was found, delete everything before it.
  188. //
  189. if (nDelimiterIndex != nItems)
  190. {
  191. do
  192. {
  193. DeleteString(0);
  194. } while(nDelimiterIndex--);
  195. }
  196. //
  197. // Add each texture from the graphics MRU to this list's MRU.
  198. //
  199. int nStrCount = 0;
  200. int nMRUCount = g_Textures.MRUGetCount();
  201. for (int nMRU = 0; nMRU < nMRUCount; nMRU++)
  202. {
  203. IEditorTexture *pTex = g_Textures.MRUGet(nMRU);
  204. if (pTex != NULL)
  205. {
  206. char szBuf[MAX_PATH];
  207. pTex->GetShortName(szBuf);
  208. int nIndex = InsertString(nStrCount, szBuf);
  209. SetItemDataPtr(nIndex, pTex);
  210. nStrCount++;
  211. }
  212. }
  213. //
  214. // Add the MRU seperator to the list, unless the MRU was empty.
  215. //
  216. if (nStrCount > 0)
  217. {
  218. int nIndex = InsertString(nStrCount, "");
  219. SetItemDataPtr(nIndex, NULL);
  220. }
  221. //
  222. // Restore the original selection.
  223. //
  224. SetCurSel(nCurSel);
  225. SetRedraw(TRUE);
  226. Invalidate();
  227. }
  228. void CTextureBox::NotifyNewMaterial( IEditorTexture *pTex )
  229. {
  230. char szStr[MAX_PATH];
  231. pTex->GetShortName( szStr );
  232. int iItem = AddString( szStr );
  233. if ( iItem != CB_ERR )
  234. {
  235. SetItemDataPtr( iItem, (void *)pTex );
  236. }
  237. }
  238. //-----------------------------------------------------------------------------
  239. // Purpose:
  240. // Input : lpMeasureItemStruct -
  241. //-----------------------------------------------------------------------------
  242. void CTextureBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
  243. {
  244. lpMeasureItemStruct->itemWidth = 64;
  245. //
  246. // If the item data is NULL or points to an empty string, it's the separator.
  247. //
  248. char *pszText = (char *)lpMeasureItemStruct->itemData;
  249. if ((pszText == NULL) || (*pszText == '\0'))
  250. {
  251. lpMeasureItemStruct->itemHeight = 9;
  252. }
  253. else
  254. {
  255. lpMeasureItemStruct->itemHeight = 64 + 8;
  256. }
  257. }
  258. //-----------------------------------------------------------------------------
  259. // Purpose:
  260. //-----------------------------------------------------------------------------
  261. void CTextureBox::LoadGraphicList(void)
  262. {
  263. if (g_pGameConfig->GetTextureFormat() == tfNone)
  264. {
  265. return;
  266. }
  267. SetRedraw(FALSE);
  268. ResetContent();
  269. InitStorage(g_Textures.GetActiveTextureCount() + 32, sizeof(PVOID));
  270. //
  271. // Add the MRU textures to the list.
  272. //
  273. int nStrCount = 0;
  274. int nMRUCount = g_Textures.MRUGetCount();
  275. for (int nMRU = 0; nMRU < nMRUCount; nMRU++)
  276. {
  277. IEditorTexture *pTex = g_Textures.MRUGet(nMRU);
  278. if (pTex != NULL)
  279. {
  280. char szStr[MAX_PATH];
  281. pTex->GetShortName(szStr);
  282. AddString(szStr);
  283. SetItemDataPtr(nStrCount, (void *)pTex);
  284. nStrCount++;
  285. }
  286. }
  287. //
  288. // Add the MRU seperator to the list, unless the MRU was empty.
  289. //
  290. if (nStrCount > 0)
  291. {
  292. AddString("");
  293. SetItemDataPtr(nStrCount, NULL);
  294. nStrCount++;
  295. }
  296. //
  297. // Add the rest of the textures to the list.
  298. //
  299. int nIndex = 0;
  300. IEditorTexture *pTex = g_Textures.EnumActiveTextures(&nIndex, g_pGameConfig->GetTextureFormat());
  301. while (pTex != NULL)
  302. {
  303. char szStr[MAX_PATH];
  304. pTex->GetShortName(szStr);
  305. int err = AddString(szStr);
  306. Assert( (err != CB_ERR) && (err != CB_ERRSPACE) );
  307. SetItemDataPtr(nStrCount, (void *)pTex);
  308. nStrCount++;
  309. pTex = g_Textures.EnumActiveTextures(&nIndex, g_pGameConfig->GetTextureFormat());
  310. }
  311. //
  312. // Hack: Select one that doesn't start with '+', '!', or '*', and doesn't have "door" in it.
  313. //
  314. SetCurSel(0);
  315. int nSel = GetCount();
  316. for (int i = 0; i < nSel; i++)
  317. {
  318. IEditorTexture *pTexSearch = (IEditorTexture *)GetItemDataPtr(i);
  319. if (pTexSearch != NULL)
  320. {
  321. char szName[MAX_PATH];
  322. pTexSearch->GetShortName(szName);
  323. if ((szName[0] != 0) && (szName[0] != '*') && (szName[0] != '+') && (szName[0] != '!') && (strstr(szName, "door") == NULL))
  324. {
  325. // this one is ok
  326. SetCurSel(i);
  327. break;
  328. }
  329. }
  330. }
  331. SetRedraw(TRUE);
  332. Invalidate();
  333. }
  334. //-----------------------------------------------------------------------------
  335. // Purpose:
  336. // Input : dwStyle -
  337. // rect -
  338. // pParentWnd -
  339. // nID -
  340. // Output : Returns TRUE on success, FALSE on failure.
  341. //-----------------------------------------------------------------------------
  342. BOOL CTextureBox::Create(DWORD dwStyle, const RECT &rect, CWnd *pParentWnd, UINT nID)
  343. {
  344. static BOOL bInitClass = TRUE;
  345. static LPCTSTR pszTextureBoxClass = "TextureBox";
  346. if(bInitClass)
  347. {
  348. bInitClass = FALSE;
  349. // get default class provided by MFC
  350. WNDCLASS wndclass;
  351. GetClassInfo(AfxGetInstanceHandle(), _T("COMBOBOX"), &wndclass);
  352. wndclass.hbrBackground = NULL;
  353. wndclass.lpszClassName = pszTextureBoxClass;
  354. AfxRegisterClass(&wndclass);
  355. }
  356. return CWnd::Create(pszTextureBoxClass, NULL, dwStyle, rect, pParentWnd, nID);
  357. }
  358. //-----------------------------------------------------------------------------
  359. // Purpose:
  360. // Input : wParam -
  361. // lParam -
  362. // Output : LRESULT
  363. //-----------------------------------------------------------------------------
  364. LRESULT CTextureBox::OnSelectString(WPARAM wParam, LPARAM lParam)
  365. {
  366. LPCTSTR pszSelect = LPCTSTR(lParam);
  367. int nCount = GetCount();
  368. IEditorTexture *pTex;
  369. for(int i = wParam + 1; i < nCount; i++)
  370. {
  371. pTex = (IEditorTexture *)GetItemDataPtr(i);
  372. if (pTex != NULL)
  373. {
  374. char szName[MAX_PATH];
  375. pTex->GetShortName(szName);
  376. if (!stricmp(szName, pszSelect))
  377. {
  378. SetCurSel(i);
  379. return i;
  380. }
  381. }
  382. }
  383. return LB_ERR;
  384. }
  385. //-----------------------------------------------------------------------------
  386. // Purpose:
  387. // Input : pDC -
  388. // Output : Returns TRUE on success, FALSE on failure.
  389. //-----------------------------------------------------------------------------
  390. BOOL CTextureBox::OnEraseBkgnd(CDC *pDC)
  391. {
  392. CRect r;
  393. GetUpdateRect(r);
  394. pDC->SetROP2(R2_COPYPEN);
  395. FillRect(pDC->m_hDC, r, HBRUSH(GetStockObject(BLACK_BRUSH)));
  396. return TRUE;
  397. }