MiniMap.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /*
  2. FinalSun/FinalAlert 2 Mission Editor
  3. Copyright (C) 1999-2024 Electronic Arts, Inc.
  4. Authored by Matthias Wagner
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <https://www.gnu.org/licenses/>.
  15. */
  16. // MiniMap.cpp: implementaion file
  17. //
  18. #include "stdafx.h"
  19. #include "finalsun.h"
  20. #include "MiniMap.h"
  21. #include "finalsundlg.h"
  22. #include "macros.h"
  23. #include "mapdata.h"
  24. #include "variables.h"
  25. #include "inlines.h"
  26. #ifdef _DEBUG
  27. #define new DEBUG_NEW
  28. #undef THIS_FILE
  29. static char THIS_FILE[] = __FILE__;
  30. #endif
  31. /////////////////////////////////////////////////////////////////////////////
  32. // CMiniMap
  33. IMPLEMENT_DYNCREATE(CMiniMap, CView)
  34. CMiniMap::CMiniMap(): m_scale(theApp.m_Options.fMiniMapScale)
  35. {
  36. }
  37. CMiniMap::~CMiniMap()
  38. {
  39. }
  40. BEGIN_MESSAGE_MAP(CMiniMap, CView)
  41. //{{AFX_MSG_MAP(CMiniMap)
  42. ON_WM_SYSCOMMAND()
  43. ON_WM_MOUSEMOVE()
  44. ON_WM_LBUTTONDOWN()
  45. //}}AFX_MSG_MAP
  46. ON_WM_SIZING()
  47. ON_WM_SETCURSOR()
  48. END_MESSAGE_MAP()
  49. /////////////////////////////////////////////////////////////////////////////
  50. // draw CMiniMap
  51. void CMiniMap::OnDraw(CDC* pDC)
  52. {
  53. BYTE* colors;
  54. BITMAPINFO biinfo;
  55. int pitch;
  56. DrawMinimap(&colors, biinfo, pitch);
  57. if(!colors) return;
  58. // set the bits
  59. //SetDIBitsToDevice(pDC->m_hDC, 0, 0, Map->GetWidth()*2, Map->GetHeight(),0,0,0, Map->GetHeight(), colors, &biinfo, DIB_RGB_COLORS);
  60. RECT r;
  61. GetClientRect(&r);
  62. StretchDIBits(pDC->m_hDC, 0, 0, r.right, r.bottom, 0, 0, Map->GetWidth() * 2, Map->GetHeight(), colors, &biinfo, DIB_RGB_COLORS, SRCCOPY);
  63. // now draw the current position
  64. CFinalSunDlg& dlg=*(CFinalSunDlg*)theApp.GetMainWnd();
  65. CIsoView& isoview=*dlg.m_view.m_isoview;
  66. RECT selRect;
  67. auto isoRect = isoview.GetScaledDisplayRect();
  68. int mapwidth=Map->GetWidth();
  69. int mapheight=Map->GetHeight();
  70. // Get iso view display rectangle
  71. RECT cr;
  72. isoview.GetClientRect(&cr);
  73. auto topLeft = Map->GetMiniMapPos(isoview.GetMapCoordinatesFromClientCoordinates(CPoint(0, 0), false, true));
  74. auto topRight = Map->GetMiniMapPos(isoview.GetMapCoordinatesFromClientCoordinates(CPoint(cr.right, 0), false, true));
  75. auto bottomLeft = Map->GetMiniMapPos(isoview.GetMapCoordinatesFromClientCoordinates(CPoint(0, cr.bottom), false, true));
  76. auto bottomRight = Map->GetMiniMapPos(isoview.GetMapCoordinatesFromClientCoordinates(CPoint(cr.right, cr.bottom), false, true));
  77. auto left = min(topLeft.x, topRight.x);
  78. auto top = min(topLeft.y, topRight.y);
  79. auto right = max(bottomLeft.x, bottomRight.x);
  80. auto bottom = max(bottomLeft.y, bottomRight.y);
  81. CPoint center(r.right / 2, r.bottom / 2);
  82. selRect.left = left * m_scale;
  83. selRect.top = top * m_scale;
  84. selRect.right = right * m_scale;
  85. selRect.bottom = bottom * m_scale;
  86. pDC->Draw3dRect(&selRect, RGB(200,0,0), RGB(120,0,0));
  87. }
  88. /////////////////////////////////////////////////////////////////////////////
  89. // diagnose CMiniMap
  90. #ifdef _DEBUG
  91. void CMiniMap::AssertValid() const
  92. {
  93. CView::AssertValid();
  94. }
  95. void CMiniMap::Dump(CDumpContext& dc) const
  96. {
  97. CView::Dump(dc);
  98. }
  99. #endif //_DEBUG
  100. /////////////////////////////////////////////////////////////////////////////
  101. // handlers
  102. BOOL CMiniMap::PreCreateWindow(CREATESTRUCT& cs)
  103. {
  104. // MW 07/17/2001: Style changed
  105. cs.style = WS_CAPTION | WS_OVERLAPPED | WS_SYSMENU;// | WS_CHILD;
  106. cs.cx=0;
  107. cs.cy=0;
  108. CFinalSunDlg& dlg=*(CFinalSunDlg*)theApp.GetMainWnd();
  109. //CIsoView& isoview=*dlg.m_view.m_isoview;
  110. RECT r;
  111. dlg.GetWindowRect(&r);
  112. cs.x=0;//r.right-250 ;
  113. cs.y=r.bottom-250;
  114. if(cs.y<0) cs.y=0;
  115. //cs.dwExStyle=WS_EX_TOOLWINDOW;
  116. //cs.dwExStyle=WS_EX_PALETTEWINDOW;
  117. // this here will cause an assert in debug mode, ignore it (window must be a child window)
  118. int res=CWnd::PreCreateWindow(cs);
  119. cs.style=WS_POPUPWINDOW | WS_CAPTION /*| WS_DLGFRAME */ | WS_THICKFRAME | WS_OVERLAPPED | DS_3DLOOK | WS_MINIMIZEBOX; //WS_CAPTION | WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX;
  120. return res;
  121. }
  122. void CMiniMap::UpdateView()
  123. {
  124. CRect r;
  125. GetWindowRect(r);
  126. if(Map->GetIsoSize()==0)
  127. {
  128. ShowWindow(SW_HIDE);
  129. }
  130. else
  131. {
  132. // calculate the needed width=height
  133. int axissizex=Map->GetWidth()*2;
  134. int axissizey=Map->GetHeight();
  135. SetIcon(theApp.m_pMainWnd->GetIcon(FALSE), FALSE);
  136. SetIcon(theApp.m_pMainWnd->GetIcon(TRUE), TRUE);
  137. SetWindowPos(&wndTopMost, r.left, r.top, axissizex * m_scale + 2 * (GetSystemMetrics(SM_CXFIXEDFRAME)), axissizey * m_scale + 2 * GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CYCAPTION), SWP_SHOWWINDOW);
  138. RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
  139. }
  140. }
  141. BOOL bMiniMapClosedByUser=FALSE;
  142. void CMiniMap::OnSysCommand(UINT nID, LPARAM lParam)
  143. {
  144. if(nID==SC_CLOSE)
  145. {
  146. bMiniMapClosedByUser=TRUE;
  147. ShowWindow(SW_HIDE);
  148. return;
  149. }
  150. CWnd::OnSysCommand(nID, lParam);
  151. }
  152. void CMiniMap::OnMouseMove(UINT nFlags, CPoint point)
  153. {
  154. if(nFlags==MK_LBUTTON)
  155. {
  156. int x,y;
  157. int xiso;
  158. int yiso;
  159. //y=Map->GetIsoSize()-(point.y - point.x+ /*(float)Map->GetIsoSize()/2.0f*/+1);
  160. //x=Map->GetIsoSize()-(point.x + point.y- /*(float)Map->GetIsoSize()/2.0f*/+1);
  161. //y-=Map->GetHeight();
  162. RECT cr;
  163. GetClientRect(&cr);
  164. float defaultXSize = (Map->GetWidth() * 2 * m_scale);
  165. float defaultYSize = (Map->GetHeight() * m_scale);
  166. float resizedXScale = cr.right / defaultXSize;
  167. float resizedYScale = cr.bottom / defaultYSize;
  168. CFinalSunDlg& dlg = *(CFinalSunDlg*)theApp.GetMainWnd();
  169. CIsoView& isoview = *dlg.m_view.m_isoview;
  170. auto viewScale = isoview.GetViewScale();
  171. auto viewOffset = isoview.GetViewOffset();
  172. x = (point.x / m_scale / resizedXScale) / 2 +Map->GetHeight() / 2;
  173. y = (point.y / m_scale / resizedYScale) + Map->GetWidth() / 2;
  174. RECT r = isoview.GetScaledDisplayRect();
  175. isoview.SetScroll((x-r.right/f_x/2)*f_x, (y-r.bottom/f_y/2)*f_y);
  176. isoview.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
  177. RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
  178. }
  179. }
  180. void CMiniMap::OnLButtonDown(UINT nFlags, CPoint point)
  181. {
  182. OnMouseMove(nFlags, point);
  183. }
  184. void CMiniMap::DrawMinimap(BYTE **lpData, BITMAPINFO &biinfo, int& Pitch)
  185. {
  186. Map->GetMinimap(lpData, &biinfo, &Pitch);
  187. // fix straw pixels
  188. auto* data = *lpData;
  189. if (data)
  190. {
  191. // fix bottom left and right top pixels in the bottom-up bitmap
  192. memcpy(&data[0], &data[sizeof(RGBTRIPLE)], sizeof(RGBTRIPLE));
  193. auto firstLine = (biinfo.bmiHeader.biHeight - 1) * Pitch;
  194. memcpy(&data[firstLine + (biinfo.bmiHeader.biWidth - 1) * sizeof(RGBTRIPLE)], &data[firstLine + (biinfo.bmiHeader.biWidth - 2) * sizeof(RGBTRIPLE)], sizeof(RGBTRIPLE));
  195. }
  196. }
  197. void CMiniMap::OnSizing(UINT fwSide, LPRECT pRect)
  198. {
  199. CView::OnSizing(fwSide, pRect);
  200. int axissizex = Map->GetWidth() * 2;
  201. int axissizey = Map->GetHeight();
  202. float ratio = float(axissizex) / float(axissizey);
  203. if (pRect)
  204. {
  205. int heightAdd = 2 * GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CYCAPTION);
  206. int widthAdd = 2 * GetSystemMetrics(SM_CXFIXEDFRAME);
  207. if (fwSide == WMSZ_LEFT || fwSide == WMSZ_TOPLEFT || fwSide == WMSZ_BOTTOMLEFT ||
  208. fwSide == WMSZ_RIGHT || fwSide == WMSZ_BOTTOMRIGHT)
  209. {
  210. pRect->bottom = pRect->top + (pRect->right - pRect->left - widthAdd) / ratio + heightAdd;
  211. }
  212. else
  213. {
  214. pRect->right = pRect->left + (pRect->bottom - pRect->top - heightAdd) * ratio + widthAdd;
  215. }
  216. }
  217. //width = axissizex* m_scale + 2 * (GetSystemMetrics(SM_CXFIXEDFRAME))
  218. m_scale = ((pRect->right - pRect->left) - 2 * GetSystemMetrics(SM_CXFIXEDFRAME)) / (float)axissizex;
  219. RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
  220. }
  221. BOOL CMiniMap::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  222. {
  223. if (!CView::OnSetCursor(pWnd, nHitTest, message))
  224. SetCursor(m_hArrowCursor);
  225. return TRUE;
  226. }