WndTerrainTilePalette.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. /* Copyright (c) 2002-2012 Croteam Ltd.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of version 2 of the GNU General Public License as published by
  4. the Free Software Foundation
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along
  10. with this program; if not, write to the Free Software Foundation, Inc.,
  11. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
  12. // WndTerrainTilePalette.cpp : implementation file
  13. //
  14. #include "stdafx.h"
  15. #include "WorldEditor.h"
  16. #include "WndTerrainTilePalette.h"
  17. #ifdef _DEBUG
  18. #undef new
  19. #define new DEBUG_NEW
  20. #undef THIS_FILE
  21. static char THIS_FILE[] = __FILE__;
  22. #endif
  23. #define PIX_TILE_WIDTH 64
  24. #define PIX_TILE_HEIGHT 64
  25. /////////////////////////////////////////////////////////////////////////////
  26. // CWndTerrainTilePalette
  27. CWndTerrainTilePalette::CWndTerrainTilePalette()
  28. {
  29. m_ptd=NULL;
  30. m_pDrawPort = NULL;
  31. m_pViewPort = NULL;
  32. m_iTimerID = -1;
  33. }
  34. CWndTerrainTilePalette::~CWndTerrainTilePalette()
  35. {
  36. // free allocated tile info structures
  37. for(INDEX i=0; i<m_dcTileInfo.Count(); i++)
  38. {
  39. delete &m_dcTileInfo[i];
  40. }
  41. m_dcTileInfo.Clear();
  42. if( m_pViewPort != NULL)
  43. {
  44. _pGfx->DestroyWindowCanvas( m_pViewPort);
  45. m_pViewPort = NULL;
  46. }
  47. }
  48. BEGIN_MESSAGE_MAP(CWndTerrainTilePalette, CWnd)
  49. //{{AFX_MSG_MAP(CWndTerrainTilePalette)
  50. ON_WM_PAINT()
  51. ON_WM_KILLFOCUS()
  52. ON_WM_LBUTTONDOWN()
  53. ON_WM_TIMER()
  54. ON_WM_LBUTTONUP()
  55. //}}AFX_MSG_MAP
  56. END_MESSAGE_MAP()
  57. /////////////////////////////////////////////////////////////////////////////
  58. // CWndTerrainTilePalette message handlers
  59. PIXaabbox2D CWndTerrainTilePalette::GetTileBBox( INDEX iTile)
  60. {
  61. PIXaabbox2D boxScr=PIXaabbox2D(
  62. PIX2D( (iTile%m_ctPaletteTilesH)*PIX_TILE_WIDTH+1,
  63. (iTile/m_ctPaletteTilesH)*PIX_TILE_HEIGHT+1),
  64. PIX2D( (iTile%m_ctPaletteTilesH+1)*PIX_TILE_WIDTH+1,
  65. (iTile/m_ctPaletteTilesH+1)*PIX_TILE_HEIGHT+1) );
  66. // return calculated box
  67. return boxScr;
  68. }
  69. void CWndTerrainTilePalette::OnPaint()
  70. {
  71. CTerrainLayer *ptlLayer=GetLayer();
  72. if(ptlLayer==NULL) return;
  73. {
  74. CPaintDC dc(this); // device context for painting
  75. }
  76. if( m_iTimerID == -1)
  77. {
  78. m_iTimerID = (int) SetTimer( 1, 10, NULL);
  79. }
  80. POINT ptMouse;
  81. GetCursorPos( &ptMouse);
  82. ScreenToClient( &ptMouse);
  83. // if there is a valid drawport, and the drawport can be locked
  84. if( (m_pDrawPort != NULL) && (m_pDrawPort->Lock()) )
  85. {
  86. CWorldEditorView *pWorldEditorView = theApp.GetActiveView();
  87. ASSERT( pWorldEditorView != NULL);
  88. // clear background
  89. m_pDrawPort->Fill( C_BLACK|CT_OPAQUE);
  90. // erase z-buffer
  91. m_pDrawPort->FillZBuffer(ZBUF_BACK);
  92. CTextureObject to;
  93. to.SetData(m_ptd);
  94. PIX pixTexW=m_ptd->GetPixWidth();
  95. PIX pixTexH=m_ptd->GetPixHeight();
  96. PIX pixTileSize=pixTexW/m_ctTilesPerRaw;
  97. PIX pixdpw=m_pDrawPort->GetWidth();
  98. PIX pixdph=m_pDrawPort->GetHeight();
  99. for(INDEX iTile=0; iTile<m_dcTileInfo.Count(); iTile++)
  100. {
  101. CTileInfo &ti=m_dcTileInfo[iTile];
  102. MEXaabbox2D boxTex=MEXaabbox2D(
  103. MEX2D(ti.ti_ix*pixTileSize, ti.ti_iy*pixTileSize),
  104. MEX2D((ti.ti_ix+1)*pixTileSize, (ti.ti_iy+1)*pixTileSize) );
  105. PIXaabbox2D boxScr=GetTileBBox(iTile);
  106. // draw tile
  107. FLOAT fU0=boxTex.Min()(1)/(FLOAT)pixTexW;
  108. FLOAT fV0=boxTex.Min()(2)/(FLOAT)pixTexH;
  109. FLOAT fU1=boxTex.Min()(1)/(FLOAT)pixTexW;
  110. FLOAT fV1=boxTex.Max()(2)/(FLOAT)pixTexH;
  111. FLOAT fU2=boxTex.Max()(1)/(FLOAT)pixTexW;
  112. FLOAT fV2=boxTex.Max()(2)/(FLOAT)pixTexH;
  113. FLOAT fU3=boxTex.Max()(1)/(FLOAT)pixTexW;
  114. FLOAT fV3=boxTex.Min()(2)/(FLOAT)pixTexH;
  115. FLOAT fI0=boxScr.Min()(1);
  116. FLOAT fJ0=boxScr.Min()(2);
  117. FLOAT fI1=boxScr.Min()(1);
  118. FLOAT fJ1=boxScr.Max()(2);
  119. FLOAT fI2=boxScr.Max()(1);
  120. FLOAT fJ2=boxScr.Max()(2);
  121. FLOAT fI3=boxScr.Max()(1);
  122. FLOAT fJ3=boxScr.Min()(2);
  123. if(ti.ti_bFlipX)
  124. {
  125. Swap(fI0,fI3);
  126. Swap(fJ0,fJ3);
  127. Swap(fI1,fI2);
  128. Swap(fJ1,fJ2);
  129. }
  130. if(ti.ti_bFlipY)
  131. {
  132. Swap(fI0,fI1);
  133. Swap(fJ0,fJ1);
  134. Swap(fI2,fI3);
  135. Swap(fJ2,fJ3);
  136. }
  137. if(ti.ti_bSwapXY)
  138. {
  139. Swap(fI1,fI3);
  140. Swap(fJ1,fJ3);
  141. }
  142. m_pDrawPort->InitTexture( &to);
  143. COLOR col=C_WHITE|CT_OPAQUE;
  144. m_pDrawPort->AddTexture(fI0, fJ0, fU0, fV0, col,
  145. fI1, fJ1, fU1, fV1, col,
  146. fI2, fJ2, fU2, fV2, col,
  147. fI3, fJ3, fU3, fV3, col);
  148. m_pDrawPort->FlushRenderingQueue();
  149. // draw border
  150. m_pDrawPort->DrawBorder( boxScr.Min()(1), boxScr.Min()(2), boxScr.Size()(1), boxScr.Size()(2), C_lGRAY|CT_OPAQUE);
  151. }
  152. m_pDrawPort->DrawBorder( 0,0, m_pDrawPort->GetWidth(),m_pDrawPort->GetHeight(), C_vlGRAY|CT_OPAQUE);
  153. // draw selected tile
  154. CTileInfo &ti=m_dcTileInfo[ptlLayer->tl_iSelectedTile];
  155. MEXaabbox2D boxTex=MEXaabbox2D(
  156. MEX2D(ti.ti_ix*pixTileSize, ti.ti_iy*pixTileSize),
  157. MEX2D((ti.ti_ix+1)*pixTileSize, (ti.ti_iy+1)*pixTileSize) );
  158. PIXaabbox2D boxScr=GetTileBBox(ptlLayer->tl_iSelectedTile);
  159. TIME tm=_pTimer->GetRealTimeTick();
  160. FLOAT fFactor=sin(tm*8)/2.0f+0.5f;
  161. COLOR colSelected=LerpColor(C_vlGRAY,C_RED,fFactor);
  162. m_pDrawPort->DrawBorder(boxScr.Min()(1), boxScr.Min()(2),
  163. boxScr.Size()(1), boxScr.Size()(2),
  164. colSelected|CT_OPAQUE);
  165. // draw tile under mouse
  166. PIXaabbox2D boxPoint( PIX2D( ptMouse.x, ptMouse.y), PIX2D(ptMouse.x, ptMouse.y));
  167. for( INDEX itum=0; itum<m_dcTileInfo.Count(); itum++)
  168. {
  169. CTileInfo &ti=m_dcTileInfo[itum];
  170. PIXaabbox2D boxScr=GetTileBBox(itum);
  171. if( (boxScr & boxPoint) == boxPoint)
  172. {
  173. INDEX iRot=((ULONG)(tm*25.0f))&7;
  174. ULONG ulLineType=0x0f0f0f0f<<iRot;
  175. m_pDrawPort->DrawBorder(boxScr.Min()(1), boxScr.Min()(2),
  176. boxScr.Size()(1), boxScr.Size()(2),
  177. C_BLUE|CT_OPAQUE, ulLineType);
  178. break;
  179. }
  180. }
  181. // unlock the drawport
  182. m_pDrawPort->Unlock();
  183. // if there is a valid viewport
  184. if (m_pViewPort!=NULL)
  185. {
  186. m_pViewPort->SwapBuffers();
  187. }
  188. }
  189. }
  190. BOOL CWndTerrainTilePalette::Initialize(PIX pixX, PIX pixY, CTextureData *ptd, BOOL bCenter/*=TRUE*/)
  191. {
  192. m_ptd=ptd;
  193. // obtain tile info array
  194. ObtainLayerTileInfo( &m_dcTileInfo, ptd, m_ctTilesPerRaw);
  195. INDEX ctTiles=m_dcTileInfo.Count();
  196. if(ctTiles==0) return FALSE;
  197. m_ctPaletteTilesH=sqrt((FLOAT)ctTiles);
  198. // calculate window's size
  199. CRect rectWindow;
  200. PIX pixWidth=PIX_TILE_WIDTH*m_ctPaletteTilesH;
  201. PIX pixHeight=((ctTiles-1)/m_ctPaletteTilesH+1)*PIX_TILE_HEIGHT;
  202. if(bCenter)
  203. {
  204. rectWindow.left = pixX-pixWidth/2;
  205. rectWindow.top = pixY-pixHeight/2;
  206. }
  207. else
  208. {
  209. rectWindow.left = pixX;
  210. rectWindow.top = pixY;
  211. }
  212. PIX pixScreenWidth = ::GetSystemMetrics(SM_CXSCREEN);
  213. PIX pixScreenHeight = ::GetSystemMetrics(SM_CYSCREEN);
  214. if( rectWindow.left+pixWidth>pixScreenWidth)
  215. {
  216. rectWindow.left=pixScreenWidth-pixWidth;
  217. }
  218. if( rectWindow.top+pixHeight>pixScreenHeight)
  219. {
  220. rectWindow.top=pixScreenHeight-pixHeight;
  221. }
  222. rectWindow.right = rectWindow.left + pixWidth+2;
  223. rectWindow.bottom = rectWindow.top + pixHeight+2;
  224. if( IsWindow(m_hWnd))
  225. {
  226. SetWindowPos( NULL, rectWindow.left, rectWindow.top,
  227. rectWindow.right-rectWindow.left, rectWindow.top-rectWindow.bottom,
  228. SWP_NOZORDER | SWP_NOACTIVATE);
  229. ShowWindow(SW_SHOW);
  230. }
  231. else
  232. {
  233. // create window
  234. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  235. BOOL bResult = CreateEx( WS_EX_TOOLWINDOW,
  236. NULL, L"Terrain tile palette", WS_CHILD|WS_POPUP|WS_VISIBLE,
  237. rectWindow.left, rectWindow.top, rectWindow.Width(), rectWindow.Height(),
  238. pMainFrame->m_hWnd, NULL, NULL);
  239. if( !bResult)
  240. {
  241. AfxMessageBox( L"Error: Failed to create terrain tile palette window!");
  242. return FALSE;
  243. }
  244. _pGfx->CreateWindowCanvas( m_hWnd, &m_pViewPort, &m_pDrawPort);
  245. }
  246. return TRUE;
  247. }
  248. void CWndTerrainTilePalette::OnKillFocus(CWnd* pNewWnd)
  249. {
  250. CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  251. if(pNewWnd!=pMainFrame->m_pwndToolTip && pNewWnd!=this)
  252. {
  253. DestroyWindow();
  254. DeleteTempMap();
  255. }
  256. }
  257. BOOL CWndTerrainTilePalette::PreTranslateMessage(MSG* pMsg)
  258. {
  259. if( pMsg->message==WM_KEYDOWN && pMsg->wParam==VK_ESCAPE)
  260. {
  261. DestroyWindow();
  262. DeleteTempMap();
  263. return TRUE;
  264. }
  265. return CWnd::PreTranslateMessage(pMsg);
  266. }
  267. void CWndTerrainTilePalette::OnLButtonDown(UINT nFlags, CPoint point)
  268. {
  269. }
  270. void CWndTerrainTilePalette::OnTimer(UINT nIDEvent)
  271. {
  272. POINT pt;
  273. GetCursorPos( &pt);
  274. CRect rectWnd;
  275. GetWindowRect(rectWnd);
  276. if(pt.x<rectWnd.left || pt.x>rectWnd.right ||
  277. pt.y<rectWnd.top || pt.y>rectWnd.bottom)
  278. {
  279. DestroyWindow();
  280. DeleteTempMap();
  281. return;
  282. }
  283. Invalidate(FALSE);
  284. CWnd::OnTimer(nIDEvent);
  285. }
  286. void CWndTerrainTilePalette::OnLButtonUp(UINT nFlags, CPoint point)
  287. {
  288. PIXaabbox2D boxPoint( PIX2D( point.x, point.y), PIX2D(point.x, point.y) );
  289. // for all tiles
  290. for( INDEX iTile=0; iTile<m_dcTileInfo.Count(); iTile++)
  291. {
  292. if( (GetTileBBox(iTile) & boxPoint) == boxPoint)
  293. {
  294. CTerrainLayer *ptlLayer=GetLayer();
  295. if(ptlLayer==NULL) return;
  296. if( ptlLayer->tl_ltType==LT_TILE)
  297. {
  298. ptlLayer->tl_iSelectedTile=iTile;
  299. }
  300. break;
  301. }
  302. }
  303. DestroyWindow();
  304. DeleteTempMap();
  305. }