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.

937 lines
21 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "stdafx.h"
  7. #pragma warning(push, 1)
  8. #pragma warning(disable:4701 4702 4530)
  9. #include <fstream>
  10. #pragma warning(pop)
  11. #include "hammer.h"
  12. #include "TextureWindow.h"
  13. #include "TextureBrowser.h"
  14. #include "CustomMessages.h"
  15. #include "IEditorTexture.h"
  16. #include "GameConfig.h"
  17. #include "GlobalFunctions.h"
  18. #include "TextureSystem.h"
  19. #include "materialsystem/imaterial.h"
  20. #include "materialsystem/imaterialsystem.h"
  21. // memdbgon must be the last include file in a .cpp file!!!
  22. #include <tier0/memdbgon.h>
  23. const DWORD NO_FILE_FILTER = 0xFFFFFFF0L;
  24. const int iPadding = 4;
  25. const int iTexNameFontHeight = 7;
  26. const int iTexIconHeight = 12;
  27. BEGIN_MESSAGE_MAP(CTextureWindow, CWnd)
  28. //{{AFX_MSG_MAP(CTextureWindow)
  29. ON_WM_PAINT()
  30. ON_WM_SIZE()
  31. ON_WM_HSCROLL()
  32. ON_WM_VSCROLL()
  33. ON_WM_LBUTTONDOWN()
  34. ON_WM_LBUTTONDBLCLK()
  35. ON_WM_KEYDOWN()
  36. ON_WM_MOUSEWHEEL()
  37. ON_WM_CHAR()
  38. //}}AFX_MSG_MAP
  39. END_MESSAGE_MAP()
  40. //-----------------------------------------------------------------------------
  41. // Purpose: Constructor. Initializes data members.
  42. //-----------------------------------------------------------------------------
  43. CTextureWindow::CTextureWindow(void)
  44. {
  45. bFirstPaint = TRUE;
  46. m_szFilter[0] = '\0';
  47. m_nFilters = 0;
  48. m_szKeywords[0] = '\0';
  49. m_nKeywords = 0;
  50. m_pSpecificList = NULL;
  51. szCurTexture[0] = '\0';
  52. m_eTextureFormat = g_pGameConfig->GetTextureFormat();
  53. m_bEnableUpdate = true;
  54. m_nTypeFilter = ~0;
  55. m_bShowErrors = true;
  56. }
  57. //-----------------------------------------------------------------------------
  58. // Purpose: Destructor.
  59. //-----------------------------------------------------------------------------
  60. CTextureWindow::~CTextureWindow(void)
  61. {
  62. }
  63. //-----------------------------------------------------------------------------
  64. // Purpose:
  65. // Input : *pParentWnd -
  66. // rect -
  67. //-----------------------------------------------------------------------------
  68. void CTextureWindow::Create(CWnd *pParentWnd, RECT& rect)
  69. {
  70. static CString TextureWndClassName;
  71. iDisplaySize = 64;
  72. if(TextureWndClassName.IsEmpty())
  73. {
  74. // create class
  75. TextureWndClassName = AfxRegisterWndClass(CS_DBLCLKS | CS_HREDRAW |
  76. CS_VREDRAW, LoadCursor(NULL, IDC_ARROW),
  77. (HBRUSH) GetStockObject(BLACK_BRUSH),
  78. AfxGetApp()->LoadIcon(IDI_TEXTUREWINDOW));
  79. }
  80. CWnd::Create(TextureWndClassName, "TextureBrowserWindow",
  81. SS_SUNKEN | WS_TABSTOP | WS_CHILD | WS_VSCROLL | WS_HSCROLL,
  82. rect, pParentWnd, IDC_TEXTUREWINDOW);
  83. UpdateScrollSizes();
  84. // create font
  85. if(!TexFont.m_hObject)
  86. TexFont.CreatePointFont(iTexNameFontHeight * 10, "Courier New");
  87. CDC *pDC = GetDC();
  88. pDC->SelectObject(&TexFont);
  89. pDC->GetCharWidth('A', 'A', &iTexNameCharWidth);
  90. ReleaseDC(pDC);
  91. }
  92. //-----------------------------------------------------------------------------
  93. // Purpose:
  94. // Input : bEnable -
  95. //-----------------------------------------------------------------------------
  96. void CTextureWindow::EnableUpdate(bool bEnable)
  97. {
  98. m_bEnableUpdate = bEnable;
  99. }
  100. //-----------------------------------------------------------------------------
  101. // Purpose: Searches for all of the keywords in an array of keywords within
  102. // a given search string, case-insensitive.
  103. // Input : pszSearch - String to search for keywords within.
  104. // pszKeyword - Array of pointers to keywords.
  105. // nKeywords - Number of keywords in the array.
  106. // Output : Returns true if all keywords were found, false otherwise.
  107. //-----------------------------------------------------------------------------
  108. bool CTextureWindow::MatchKeywords(const char *pszSearch, char **pszKeyword, int nKeywords)
  109. {
  110. if (nKeywords != 0)
  111. {
  112. for (int i = 0; i < nKeywords; i++)
  113. {
  114. if (Q_stristr(pszSearch, pszKeyword[i]) == NULL)
  115. {
  116. return(false);
  117. }
  118. }
  119. }
  120. return(true);
  121. }
  122. //-----------------------------------------------------------------------------
  123. // Changes type filter bits
  124. //-----------------------------------------------------------------------------
  125. void CTextureWindow::SetTypeFilter( int filter, bool enable )
  126. {
  127. if (enable)
  128. m_nTypeFilter |= filter;
  129. else
  130. m_nTypeFilter &= ~filter;
  131. if (m_bEnableUpdate)
  132. {
  133. UpdateScrollSizes();
  134. SelectTexture(szCurTexture, false);
  135. if (IsWindow(m_hWnd))
  136. {
  137. Invalidate();
  138. UpdateWindow();
  139. }
  140. }
  141. }
  142. //-----------------------------------------------------------------------------
  143. // Purpose:
  144. // Input : *pTE -
  145. // bStart -
  146. // Output : Returns TRUE on success, FALSE on failure.
  147. //-----------------------------------------------------------------------------
  148. BOOL CTextureWindow::EnumTexturePositions(TWENUMPOS *pTE, BOOL bStart)
  149. {
  150. RECT &texrect = pTE->texrect;
  151. if (bStart)
  152. {
  153. pTE->cur_x = iPadding;
  154. pTE->cur_y = iPadding;
  155. pTE->largest_y = 0;
  156. pTE->iTexIndex = 0;
  157. if (IsWindow(m_hWnd))
  158. {
  159. GetClientRect(&pTE->clientrect);
  160. }
  161. SetRect(&texrect, 0, 0, 0, 0);
  162. }
  163. bool bFound = false;
  164. do
  165. {
  166. pTE->pTex = g_Textures.EnumActiveTextures(&pTE->iTexIndex, m_eTextureFormat);
  167. if (pTE->pTex == NULL)
  168. continue;
  169. bFound = false;
  170. // If we are iterating a specific list of textures, make sure it is in the list.
  171. // dvs: inefficient, the specific list should control the loop, not act as a filter
  172. if (m_pSpecificList != NULL)
  173. {
  174. int nIndex = m_pSpecificList->Find(pTE->pTex);
  175. if (nIndex == -1)
  176. continue;
  177. pTE->nUsageCount = m_pSpecificList->Element(nIndex).nUsageCount;
  178. }
  179. // Filter by texture name.
  180. char szTemp[MAX_PATH];
  181. pTE->pTex->GetShortName(szTemp);
  182. if (MatchKeywords(szTemp, m_Filters, m_nFilters))
  183. {
  184. //
  185. // Filter by keywords.
  186. //
  187. // NOTE: Try not to access the material here when finding the position
  188. // because it causes the materials to be cached (slow!!)
  189. if (m_nKeywords)
  190. {
  191. pTE->pTex->GetKeywords(szTemp);
  192. if (MatchKeywords(szTemp, m_Keyword, m_nKeywords))
  193. {
  194. bFound = true;
  195. }
  196. }
  197. else
  198. {
  199. bFound = true;
  200. }
  201. }
  202. // Filter based on opacity, etc.
  203. // NOTE: Try not to access the material here when finding the position
  204. // because it causes the materials to be cached (slow!!)
  205. if (bFound && ((m_nTypeFilter & TYPEFILTER_ALL) != TYPEFILTER_ALL))
  206. {
  207. IMaterial* pMaterial = pTE->pTex->GetMaterial();
  208. if (pMaterial)
  209. {
  210. bFound = false;
  211. if ( pMaterial->GetMaterialVarFlag( MATERIAL_VAR_SELFILLUM ) )
  212. {
  213. if (m_nTypeFilter & TYPEFILTER_SELFILLUM)
  214. bFound = true;
  215. }
  216. if ( pMaterial->GetMaterialVarFlag( MATERIAL_VAR_BASEALPHAENVMAPMASK ) )
  217. {
  218. if (m_nTypeFilter & TYPEFILTER_ENVMASK)
  219. bFound = true;
  220. }
  221. if ( pMaterial->GetMaterialVarFlag( MATERIAL_VAR_TRANSLUCENT ) )
  222. {
  223. if (m_nTypeFilter & TYPEFILTER_TRANSLUCENT)
  224. bFound = true;
  225. }
  226. else
  227. {
  228. if (m_nTypeFilter & TYPEFILTER_OPAQUE)
  229. bFound = true;
  230. }
  231. }
  232. }
  233. // Blow off zero-size materials, but only if they've been loaded...
  234. // Otherwise we have to cache everything which will take forever...
  235. if ( bFound && pTE->pTex->IsLoaded() )
  236. {
  237. if ((pTE->pTex->GetWidth() == 0) || (pTE->pTex->GetHeight() == 0))
  238. {
  239. bFound = false;
  240. }
  241. }
  242. } while ((pTE->pTex != NULL) && (!bFound));
  243. if ((!bFound) || (pTE->pTex == NULL))
  244. {
  245. return(FALSE);
  246. }
  247. doresize:
  248. SetRect( &texrect, pTE->cur_x, pTE->cur_y,
  249. pTE->cur_x + iDisplaySize,
  250. pTE->cur_y + iDisplaySize );
  251. // if we've got one texture on this row already, and this one goes out of
  252. // the client area, jump to the next row. we want to have at least one texture on
  253. // each row, or we will sit in an infinite loop.
  254. if(pTE->cur_x > iPadding && texrect.right > pTE->clientrect.right)
  255. {
  256. pTE->cur_x = iPadding;
  257. pTE->cur_y = pTE->largest_y + iPadding;
  258. goto doresize;
  259. }
  260. texrect.bottom += (8 + iTexNameFontHeight + iTexIconHeight);
  261. if(texrect.bottom > pTE->largest_y)
  262. pTE->largest_y = texrect.bottom;
  263. // update cur_x
  264. pTE->cur_x = texrect.right + iPadding;
  265. return TRUE;
  266. }
  267. //-----------------------------------------------------------------------------
  268. // Purpose: Sets the dimensions of each texture within the texture window.
  269. // Input : iSize - 32 to display as 32 x 32 textures.
  270. // 64 to display as 64 x 64 textures.
  271. // 128 to display as 128 x 128 textures.
  272. // 512 to display as 512 x 512 textures
  273. //-----------------------------------------------------------------------------
  274. void CTextureWindow::SetDisplaySize(int iSize)
  275. {
  276. iDisplaySize = iSize;
  277. UpdateScrollSizes();
  278. SelectTexture(szCurTexture, FALSE);
  279. RedrawWindow();
  280. }
  281. //-----------------------------------------------------------------------------
  282. // Purpose: Sets the name filter that is used to filter the texture window contents.
  283. // Input : pszFilter - Space, comma, or semicolon delimited names to filter against.
  284. //-----------------------------------------------------------------------------
  285. void CTextureWindow::SetNameFilter(LPCTSTR pszFilter)
  286. {
  287. if (m_bEnableUpdate)
  288. {
  289. // kill highlight
  290. HighlightCurTexture();
  291. }
  292. // set filter
  293. strcpy(m_szFilter, pszFilter);
  294. strupr(m_szFilter);
  295. // delimit the filter
  296. m_nFilters = 0;
  297. char *p = strtok(m_szFilter, " ,;");
  298. while (p != NULL)
  299. {
  300. m_Filters[m_nFilters++] = p;
  301. p = strtok(NULL, " ,;");
  302. }
  303. if (m_bEnableUpdate)
  304. {
  305. UpdateScrollSizes();
  306. SelectTexture(szCurTexture, false);
  307. if (IsWindow(m_hWnd))
  308. {
  309. Invalidate();
  310. UpdateWindow();
  311. }
  312. }
  313. }
  314. //-----------------------------------------------------------------------------
  315. // Purpose: Sets the keywords that are used to filter the texture window contents.
  316. // Input : pszFilter - Space, comma, or semicolon delimited keywords to filter against.
  317. //-----------------------------------------------------------------------------
  318. void CTextureWindow::SetKeywords(LPCTSTR pszKeywords)
  319. {
  320. if (m_bEnableUpdate)
  321. {
  322. // kill highlight
  323. HighlightCurTexture();
  324. }
  325. // set keyword filter
  326. strcpy(m_szKeywords, pszKeywords);
  327. strupr(m_szKeywords);
  328. // delimit the filter
  329. m_nKeywords = 0;
  330. char *p = strtok(m_szKeywords, " ,;");
  331. while (p != NULL)
  332. {
  333. m_Keyword[m_nKeywords++] = p;
  334. p = strtok(NULL, " ,;");
  335. }
  336. if (m_bEnableUpdate)
  337. {
  338. UpdateScrollSizes();
  339. SelectTexture(szCurTexture, false);
  340. if (IsWindow(m_hWnd))
  341. {
  342. Invalidate();
  343. UpdateWindow();
  344. }
  345. }
  346. }
  347. //-----------------------------------------------------------------------------
  348. // Purpose:
  349. //-----------------------------------------------------------------------------
  350. void CTextureWindow::UpdateScrollSizes(void)
  351. {
  352. TWENUMPOS TE;
  353. total_x = total_y = 0;
  354. if(EnumTexturePositions(&TE, TRUE))
  355. do {
  356. if(TE.texrect.right > total_x)
  357. total_x = TE.texrect.right;
  358. if(TE.texrect.bottom > total_y)
  359. total_y = TE.texrect.bottom;
  360. } while(EnumTexturePositions(&TE));
  361. // update total_x and total_y
  362. total_x += iPadding;
  363. total_y += iPadding;
  364. SCROLLINFO si;
  365. si.cbSize = sizeof(SCROLLINFO);
  366. si.fMask = SIF_ALL;
  367. si.nMin = 0;
  368. si.nPos = 0;
  369. si.nMax = total_x;
  370. si.nPage = TE.clientrect.right;
  371. SetScrollInfo(SB_HORZ, &si, TRUE);
  372. si.nMax = total_y;
  373. si.nPage = TE.clientrect.bottom;
  374. SetScrollInfo(SB_VERT, &si, TRUE);
  375. char szbuf[100];
  376. sprintf(szbuf, "Size = %d %d\n", total_y, TE.clientrect.bottom);
  377. TRACE0(szbuf);
  378. }
  379. //-----------------------------------------------------------------------------
  380. // Purpose:
  381. //-----------------------------------------------------------------------------
  382. void CTextureWindow::OnPaint(void)
  383. {
  384. CPaintDC dc(this); // device context for painting
  385. // setup font
  386. dc.SelectObject(&TexFont);
  387. dc.SetTextColor(RGB(255, 255, 255));
  388. //dc.SetBkColor(RGB(0,0,0));
  389. dc.SetBkMode(TRANSPARENT);
  390. CRect clientrect;
  391. GetClientRect(clientrect);
  392. dc.SetWindowOrg(GetScrollPos(SB_HORZ), GetScrollPos(SB_VERT));
  393. TWENUMPOS TE;
  394. BOOL bNotDone = EnumTexturePositions(&TE, TRUE);
  395. BOOL bFoundHighlight = FALSE;
  396. rectHighlight.left = -1;
  397. BOOL bFirst = TRUE;
  398. char szDrawTexture[128];
  399. char szFirstDrawnTexture[128];
  400. while (bNotDone)
  401. {
  402. TE.pTex->GetShortName(szDrawTexture);
  403. if (!strcmpi(szCurTexture, szDrawTexture))
  404. {
  405. rectHighlight = TE.texrect;
  406. rectHighlight.InflateRect(2, 4);
  407. bFoundHighlight = TRUE;
  408. }
  409. if (dc.RectVisible(&TE.texrect))
  410. {
  411. // ensure loaded
  412. TE.pTex->Load();
  413. CPalette *pOld = dc.SelectPalette(TE.pTex->HasPalette() ? TE.pTex->GetPalette() : g_pGameConfig->Palette, FALSE);
  414. dc.RealizePalette();
  415. int flags = drawCaption | drawIcons;
  416. if (m_bShowErrors)
  417. flags |= drawErrors;
  418. DrawTexData_t DrawTexData;
  419. DrawTexData.nFlags = flags | (m_pSpecificList ? drawUsageCount : 0);
  420. DrawTexData.nUsageCount = TE.nUsageCount;
  421. TE.pTex->Draw(&dc, TE.texrect, iTexNameFontHeight, iTexIconHeight, DrawTexData);
  422. dc.SelectPalette(pOld, FALSE);
  423. }
  424. //
  425. // Save the name of the first drawn texture in case we need to highlight it.
  426. //
  427. if (bFirst)
  428. {
  429. bFirst = FALSE;
  430. strcpy(szFirstDrawnTexture, szDrawTexture);
  431. }
  432. // next texture & position
  433. bNotDone = EnumTexturePositions(&TE);
  434. }
  435. if(bFoundHighlight)
  436. {
  437. HighlightCurTexture(&dc);
  438. }
  439. else
  440. {
  441. // select first texture
  442. SelectTexture(szFirstDrawnTexture);
  443. }
  444. }
  445. //-----------------------------------------------------------------------------
  446. // Purpose:
  447. // Input : nType -
  448. // cx -
  449. // cy -
  450. //-----------------------------------------------------------------------------
  451. void CTextureWindow::OnSize(UINT nType, int cx, int cy)
  452. {
  453. CWnd::OnSize(nType, cx, cy);
  454. UpdateScrollSizes();
  455. }
  456. //-----------------------------------------------------------------------------
  457. // Purpose:
  458. // Input : nSBCode -
  459. // nPos -
  460. // pScrollBar -
  461. //-----------------------------------------------------------------------------
  462. void CTextureWindow::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
  463. {
  464. int iPos = int(nPos);
  465. SCROLLINFO si;
  466. GetScrollInfo(SB_HORZ, &si);
  467. int iCurPos = GetScrollPos(SB_HORZ);
  468. int iLimit = GetScrollLimit(SB_HORZ);
  469. switch(nSBCode)
  470. {
  471. case SB_LINELEFT:
  472. iPos = -int(si.nPage / 4);
  473. break;
  474. case SB_LINERIGHT:
  475. iPos = int(si.nPage / 4);
  476. break;
  477. case SB_PAGELEFT:
  478. iPos = -int(si.nPage / 2);
  479. break;
  480. case SB_PAGERIGHT:
  481. iPos = int(si.nPage / 2);
  482. break;
  483. case SB_THUMBTRACK:
  484. case SB_THUMBPOSITION:
  485. iPos -= iCurPos;
  486. break;
  487. }
  488. if(iCurPos + iPos < 0)
  489. iPos = -iCurPos;
  490. if(iCurPos + iPos > iLimit)
  491. iPos = iLimit - iCurPos;
  492. if(iPos)
  493. {
  494. SetScrollPos(SB_HORZ, iCurPos + iPos);
  495. ScrollWindow(-iPos, 0);
  496. UpdateWindow();
  497. }
  498. CWnd::OnHScroll(nSBCode, nPos, pScrollBar);
  499. }
  500. //-----------------------------------------------------------------------------
  501. // Purpose:
  502. // Input : nSBCode -
  503. // nPos -
  504. // pScrollBar -
  505. //-----------------------------------------------------------------------------
  506. void CTextureWindow::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
  507. {
  508. SCROLLINFO si;
  509. GetScrollInfo(SB_VERT, &si);
  510. int iCurPos = GetScrollPos(SB_VERT);
  511. int iLimit = GetScrollLimit(SB_VERT);
  512. int iPos = int(si.nPos);
  513. switch(nSBCode)
  514. {
  515. case SB_LINEUP:
  516. iPos = -int(si.nPage / 4);
  517. break;
  518. case SB_LINEDOWN:
  519. iPos = int(si.nPage / 4);
  520. break;
  521. case SB_PAGEUP:
  522. iPos = -int(si.nPage / 2);
  523. break;
  524. case SB_PAGEDOWN:
  525. iPos = int(si.nPage / 2);
  526. break;
  527. case SB_THUMBTRACK:
  528. case SB_THUMBPOSITION:
  529. iPos = si.nTrackPos - iCurPos;
  530. break;
  531. case SB_ENDSCROLL:
  532. iPos = 0;
  533. break;
  534. }
  535. if(iCurPos + iPos < 0)
  536. iPos = -iCurPos;
  537. if(iCurPos + iPos > iLimit)
  538. iPos = iLimit - iCurPos;
  539. if(iPos)
  540. {
  541. SetScrollPos(SB_VERT, iCurPos + iPos);
  542. ScrollWindow(0, -iPos);
  543. UpdateWindow();
  544. }
  545. CWnd::OnVScroll(nSBCode, nPos, pScrollBar);
  546. }
  547. //-----------------------------------------------------------------------------
  548. // Purpose:
  549. // Input : *pDC -
  550. //-----------------------------------------------------------------------------
  551. void CTextureWindow::HighlightCurTexture(CDC *pDC)
  552. {
  553. CDC dc;
  554. BOOL bMadeDC = FALSE;
  555. // nothing to draw
  556. if(rectHighlight.left < 0)
  557. return;
  558. if(!pDC)
  559. {
  560. dc.Attach(::GetDC(m_hWnd));
  561. dc.SetWindowOrg(GetScrollPos(SB_HORZ), GetScrollPos(SB_VERT));
  562. bMadeDC = TRUE;
  563. pDC = &dc;
  564. }
  565. pDC->SelectStockObject(WHITE_PEN);
  566. pDC->SelectStockObject(NULL_BRUSH);
  567. pDC->SetROP2(R2_XORPEN);
  568. pDC->Rectangle(rectHighlight);
  569. if(bMadeDC)
  570. ::ReleaseDC(m_hWnd, dc.Detach());
  571. }
  572. //-----------------------------------------------------------------------------
  573. // Purpose: Selects a given texture by name, scrolling the window if necessary
  574. // to make the selected texture visible.
  575. // Input : pszTexture - Texture to select.
  576. //-----------------------------------------------------------------------------
  577. void CTextureWindow::SelectTexture(LPCTSTR pszTexture, BOOL bAllowRedraw)
  578. {
  579. TWENUMPOS TE;
  580. BOOL bNotDone = EnumTexturePositions(&TE, TRUE);
  581. int iTextureIndex = 0;
  582. IEditorTexture *pTex = g_Textures.FindActiveTexture(pszTexture);
  583. CRect r(100, 100, 500, 500);
  584. if (IsWindow(m_hWnd))
  585. {
  586. GetClientRect(r);
  587. }
  588. int iClientHeight = r.Height();
  589. if (pTex == NULL)
  590. {
  591. return;
  592. }
  593. while (bNotDone)
  594. {
  595. if (pTex == TE.pTex)
  596. {
  597. // found it - make sure it's visible
  598. if (IsWindow(m_hWnd))
  599. {
  600. int iScrollPos = GetScrollPos(SB_VERT);
  601. if (iScrollPos + iClientHeight < TE.texrect.top || TE.texrect.bottom < iScrollPos)
  602. {
  603. SetScrollPos(SB_VERT, TE.texrect.top);
  604. ScrollWindow(0, iScrollPos - TE.texrect.top);
  605. if (bAllowRedraw)
  606. {
  607. RedrawWindow();
  608. }
  609. }
  610. // first remove current highlight
  611. HighlightCurTexture();
  612. }
  613. pTex->GetShortName(szCurTexture);
  614. // highlight new texture
  615. if (IsWindow(m_hWnd))
  616. {
  617. rectHighlight = CRect(&TE.texrect);
  618. rectHighlight.InflateRect(2, 4);
  619. HighlightCurTexture();
  620. }
  621. GetParent()->PostMessage(TWN_SELCHANGED);
  622. return;
  623. }
  624. // next texture & position
  625. bNotDone = EnumTexturePositions(&TE);
  626. ++iTextureIndex;
  627. }
  628. }
  629. //-----------------------------------------------------------------------------
  630. // Purpose:
  631. // Input : nFlags -
  632. // point -
  633. //-----------------------------------------------------------------------------
  634. void CTextureWindow::OnLButtonDown(UINT nFlags, CPoint point)
  635. {
  636. // find clicked texture
  637. TWENUMPOS TE;
  638. BOOL bNotDone = EnumTexturePositions(&TE, TRUE);
  639. int iTextureIndex = 0;
  640. int iHorzPos = GetScrollPos(SB_HORZ);
  641. int iVertPos = GetScrollPos(SB_VERT);
  642. char szNewTexture[128];
  643. point += CPoint(iHorzPos, iVertPos);
  644. while (bNotDone)
  645. {
  646. if (PtInRect(&TE.texrect, point))
  647. {
  648. TE.pTex->GetShortName(szNewTexture);
  649. break;
  650. }
  651. // next texture & position
  652. bNotDone = EnumTexturePositions(&TE);
  653. ++iTextureIndex;
  654. }
  655. if(!bNotDone)
  656. {
  657. // no texture was hit
  658. return;
  659. }
  660. // first remove current highlight
  661. HighlightCurTexture();
  662. // highlight new texture
  663. strcpy(szCurTexture, szNewTexture);
  664. rectHighlight = CRect(&TE.texrect);
  665. rectHighlight.InflateRect(2, 4);
  666. HighlightCurTexture();
  667. // tell parent we changed selection
  668. GetParent()->PostMessage(TWN_SELCHANGED);
  669. SetFocus();
  670. CWnd::OnLButtonDown(nFlags, point);
  671. }
  672. //-----------------------------------------------------------------------------
  673. // Purpose: Notifies our parent window of a double-click event.
  674. // Input : nFlags -
  675. // point -
  676. //-----------------------------------------------------------------------------
  677. void CTextureWindow::OnLButtonDblClk(UINT nFlags, CPoint point)
  678. {
  679. GetParent()->PostMessage(TWN_LBUTTONDBLCLK);
  680. CWnd::OnLButtonDblClk(nFlags, point);
  681. }
  682. //-----------------------------------------------------------------------------
  683. // Purpose:
  684. // Input : nChar -
  685. // nRepCnt -
  686. // nFlags -
  687. //-----------------------------------------------------------------------------
  688. void CTextureWindow::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  689. {
  690. CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
  691. }
  692. //-----------------------------------------------------------------------------
  693. // Purpose:
  694. // Input : nFlags -
  695. // zDelta -
  696. // point -
  697. // Output : Returns TRUE on success, FALSE on failure.
  698. //-----------------------------------------------------------------------------
  699. BOOL CTextureWindow::OnMouseWheel(UINT nFlags, short zDelta, CPoint point)
  700. {
  701. int nScrollCode;
  702. if (zDelta > 0)
  703. {
  704. nScrollCode = SB_LINEUP;
  705. }
  706. else
  707. {
  708. nScrollCode = SB_LINEDOWN;
  709. }
  710. SCROLLINFO si;
  711. GetScrollInfo(SB_VERT, &si);
  712. int iCurPos = GetScrollPos(SB_VERT);
  713. int iLimit = GetScrollLimit(SB_VERT);
  714. int iPos = int(si.nPos);
  715. switch (nScrollCode)
  716. {
  717. case SB_LINEUP:
  718. {
  719. iPos = -(int)si.nPage / 4;
  720. break;
  721. }
  722. case SB_LINEDOWN:
  723. {
  724. iPos = si.nPage / 4;
  725. break;
  726. }
  727. }
  728. if (iCurPos + iPos < 0)
  729. {
  730. iPos = -iCurPos;
  731. }
  732. if (iCurPos + iPos > iLimit)
  733. {
  734. iPos = iLimit - iCurPos;
  735. }
  736. if (iPos)
  737. {
  738. SetScrollPos(SB_VERT, iCurPos + iPos);
  739. ScrollWindow(0, -iPos);
  740. UpdateWindow();
  741. }
  742. return(TRUE);
  743. }
  744. //-----------------------------------------------------------------------------
  745. // Purpose:
  746. // Input : nChar -
  747. // nRepCnt -
  748. // nFlags -
  749. //-----------------------------------------------------------------------------
  750. void CTextureWindow::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
  751. {
  752. CWnd::OnChar(nChar, nRepCnt, nFlags);
  753. }
  754. //-----------------------------------------------------------------------------
  755. // Purpose: Sets the contents of the texture window to a specific list of textures.
  756. // Input : pList - Textures with which to populate the texture window.
  757. //-----------------------------------------------------------------------------
  758. void CTextureWindow::SetSpecificList(TextureWindowTexList *pList)
  759. {
  760. m_pSpecificList = pList;
  761. if (m_hWnd != NULL)
  762. {
  763. UpdateScrollSizes();
  764. SelectTexture(szCurTexture, FALSE);
  765. RedrawWindow();
  766. }
  767. }
  768. //-----------------------------------------------------------------------------
  769. // Purpose:
  770. // Input : eTextureFormat -
  771. //-----------------------------------------------------------------------------
  772. void CTextureWindow::SetTextureFormat(TEXTUREFORMAT eTextureFormat)
  773. {
  774. m_eTextureFormat = eTextureFormat;
  775. }