// OverviewWindow1.cpp : implementation file // #include "stdafx.h" #include "MW4GameEd.h" #include "OverviewWindow.h" #include "EditorChildWnd.h" #include "EditorWaypoint.h" #include "MainFrm.h" #include #include #include #include #include #include #include #include #include "DisplayWindow.h" #include #define __mbsrchr(s,c) (char*)_mbsrchr((const unsigned char*)(s),(c)) extern CMW4GameEdApp theApp; ///////////////////////////////////////////////////////////////////////////// // COverviewWindow IMPLEMENT_DYNCREATE(COverviewWindow, CEditorChildWnd) COverviewWindow::COverviewWindow() { CString title; CRect rect; CurrentVMode=VM_TEXTURE; title.LoadString(IDS_OVERVIEWWINDOWTITLE); rect.top = 2; rect.left = 650; rect.bottom = 202; rect.right = 850; ImgReady=false; BBufReady=false; mapWidth = 0; mapHeight = 0; Create(NULL,title, WS_CHILD | WS_CLIPSIBLINGS | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_VISIBLE,rect); } COverviewWindow::~COverviewWindow() { BackBuffer.DeleteObject(); } BEGIN_MESSAGE_MAP(COverviewWindow, CEditorChildWnd) //{{AFX_MSG_MAP(COverviewWindow) ON_WM_SIZE() ON_WM_PAINT() ON_WM_LBUTTONDOWN() ON_WM_MOUSEMOVE() ON_WM_RBUTTONDOWN() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // COverviewWindow message handlers int COverviewWindow::LoadImageFromMissionInstance(const char* missionFile) { char drive[_MAX_DRIVE],dir[_MAX_DIR],fname[_MAX_FNAME],ext[_MAX_EXT]; _splitpath(missionFile,drive,dir,fname,ext); NotationFile not(missionFile); const char* filename; Page *page = not.GetPage(fname); Check_Object(page); page->GetEntry("Map",&filename); char* p = __mbsrchr(filename,'\\'); *p = 0; sprintf(fname,"Content\\Textures\\%s\\*.*",filename); Directory* currentDir; currentDir = new Directory(fname,true); Register_Object(currentDir); int last = 0, blockX = 0, blockY = 0; do { p = currentDir->GetCurrentFolderName(); if (!p) break; currentDir->AdvanceCurrentFolder(); if (strlen(p) > 2) continue; strlwr(p); if (*p == 'a') blockX++; if (*p != last) { blockY++; last = *p; } } while (p); Unregister_Object(currentDir); delete currentDir; // OK, we're assuming the TGA is 24 bit so it had better be RGBMask mask=RGBMask(0xff0000,0x00ff00,0x0000ff); MapImage.CreateBlank(blockX * 256,blockY * 256,ITYPE_RGB,24,mask); currentDir = new Directory(fname,true); Register_Object(currentDir); char tmp[MAX_PATH]; strcpy(tmp,fname); p = __mbsrchr(tmp,'\\'); *p = 0; strcpy(dir,tmp); p = __mbsrchr(dir,'\\') + 1; strcpy(dir,p); int i = 0; CRect dst,src; src.left = 0; src.top = 0; src.right = 255; src.bottom = 255; do { p = currentDir->GetCurrentFolderName(); if (!p) break; currentDir->AdvanceCurrentFolder(); if (strlen(p) > 2) continue; CString noextfname,finalfname; noextfname.Format("%s\\%s\\%s_%s_0_0000",tmp,p,dir,p); finalfname=noextfname+".Png"; if(!gos_DoesFileExist((LPCSTR)finalfname)) finalfname=noextfname+".tga"; Image img((char *)(LPCSTR)finalfname); int x = MapImage.GetWidth() - 255 * (i % blockX + 1); int y = MapImage.GetHeight() - 255 * (i / blockX + 1); dst.left = x; dst.top = y; dst.right = x + 255; dst.bottom = y + 255; MapImage.Blt(img,dst,src); i++; } while (p); // MapImage.Rotate180(); // MapImage.MakeRGB24(); CString map_name; map_name=filename; map_name=map_name.Right(map_name.GetLength()-map_name.ReverseFind('\\')-1); CString tctpath,hfpath; tctpath.Format("Content\\Maps\\%s\\tctd.ini",map_name); if(gos_DoesFileExist((char *)(LPCSTR)tctpath)) { NotationFile hfinfo((char *)(LPCSTR)tctpath); page = hfinfo.GetPage((char *)(LPCSTR)map_name); Check_Object(page); const char *hfname; page->GetEntry("HeightField",&hfname); Point3D map_scale; page->GetEntry("DeltaX",&map_scale.x); page->GetEntry("DeltaY",&map_scale.y); page->GetEntry("DeltaZ",&map_scale.z); hfpath.Format("Content\\Maps\\%s\\%s",map_name,hfname); HField.Load((char *)(LPCSTR)hfpath); HField.MakeRGB24(); SlopeMap=HField; SlopeMap.ShowSlopeLimit(map_scale.x, map_scale.z, map_scale.y, 20.0f,ImgRGBColor(0,0,0),ImgRGBColor(255,255,255)); SlopeMap.MakeRGB24(); } else { PAUSE(("Tctd.ini Not Checked it for Map %s" ,(char *)(LPCSTR)map_name)); HField=MapImage; SlopeMap=HField; } ImgReady=true; BuildBackBuffer(); Unregister_Object(currentDir); delete currentDir; return (1); } void COverviewWindow::OnSize(UINT nType, int cx, int cy) { BuildBackBuffer(); /* static int last = 0; static int recursing = 0; int width,height; if (!recursing) { recursing = 1; if (cx != last) { width = cx + GetSystemMetrics(SM_CXSIZEFRAME) * 2; height = cx + GetSystemMetrics(SM_CXSIZEFRAME) + GetSystemMetrics(SM_CYCAPTION); last = cx; SetWindowPos(&wndTop,0,0,width,height,SWP_NOZORDER | SWP_NOMOVE); } else if (cy != last) { width = cy + GetSystemMetrics(SM_CXSIZEFRAME) * 2; height = cy + GetSystemMetrics(SM_CXSIZEFRAME) + GetSystemMetrics(SM_CYCAPTION); last = cy; SetWindowPos(&wndTop,0,0,width,height,SWP_NOZORDER | SWP_NOMOVE); } recursing = 0; } CMDIChildWnd::OnSize(nType, last, last);//cx, cy); */ } void COverviewWindow::OnPaint() { CPaintDC dc(this); //CEditorChildWnd::OnPaint(); DrawWindow(); // Do not call CEditorChildWnd::OnPaint() for painting messages } void COverviewWindow::PaintCameraPos(CDC* pDC) { if (Player::Instance) { LinearMatrix4D localToWorld; Point3D new_position; YawPitchRoll new_rotation; CRect r; GetClientRect(&r); localToWorld = Player::Instance->GetLocalToWorld(); new_position = localToWorld; new_rotation = localToWorld; CPoint end; CPen pen(PS_SOLID,1,RGB(255,0,0)), *oldPen; end.x = int(sin(new_rotation.yaw) * 10.0f); end.x += cameraClientCoords.x; end.y = int(cos(new_rotation.yaw) * 10.0f); end.y += cameraClientCoords.y; oldPen = pDC->SelectObject(&pen); pDC->MoveTo(Flip(cameraClientCoords)); pDC->LineTo(Flip(end)); cameraClientCoords.x = long(float(r.right) * float(new_position.x+mapWidth*0.5f) / float(mapWidth)); cameraClientCoords.y = long(float(r.bottom) * float(new_position.z+mapHeight*0.5f) / float(mapHeight)); r.left = cameraClientCoords.x - 2; r.right = cameraClientCoords.x + 2; r.top = cameraClientCoords.y - 2; r.bottom = cameraClientCoords.y + 2; CRect trect=Flip(r); pDC->Ellipse(&trect); pDC->SelectObject(oldPen); } } void COverviewWindow::PaintCircle(CDC* pDC, CPoint point, int extent, COLORREF clr, bool fill) { CRect r; CPen pen(PS_SOLID,1,clr), *oldPen; point=Flip(point); oldPen = pDC->SelectObject(&pen); r.left = point.x - int(extent * xScale); r.right = point.x + int(extent * xScale); r.top = point.y - int(extent * yScale); r.bottom = point.y + int(extent * yScale); if (fill) { CBrush brush(clr), *oldBrush; oldBrush = pDC->SelectObject(&brush); pDC->Ellipse(&r); pDC->SelectObject(oldBrush); } else { pDC->Ellipse(&r); } pDC->SelectObject(oldPen); } void COverviewWindow::PaintSquare(CDC* pDC, CPoint point, int extent, COLORREF clr) { CRect r; point=Flip(point); r.left = point.x - int(extent * xScale); r.right = point.x + int(extent * xScale); r.top = point.y - int(extent * yScale); r.bottom = point.y + int(extent * yScale); CPen pen(PS_SOLID,1,clr), *oldPen; CBrush brush(clr), *oldBrush; oldBrush = pDC->SelectObject(&brush); oldPen = pDC->SelectObject(&pen); pDC->Ellipse(&r); pDC->SelectObject(oldBrush); pDC->SelectObject(oldPen); } void COverviewWindow::PaintTriangle(CDC* pDC, CPoint point, int extent, COLORREF clr, bool fill) { CPoint points[4]; point=Flip(point); points[0].x = point.x; points[0].y = point.y - int(extent * yScale); points[1].x = point.x - int(extent * xScale); points[1].y = point.y + int(extent * yScale); points[2].x = point.x + int(extent * xScale); points[2].y = point.y + int(extent * yScale); points[3].x = point.x; points[3].y = point.y - int(extent * yScale); CPen pen(PS_SOLID,1,clr), *oldPen; CBrush brush(clr), *oldBrush; oldBrush = pDC->SelectObject(&brush); oldPen = pDC->SelectObject(&pen); pDC->Polygon(points,4); pDC->SelectObject(oldPen); // pDC->FloodFill(point.x,point.y,clr); pDC->SelectObject(oldBrush); } void COverviewWindow::PaintX(CDC* pDC, CPoint point, COLORREF clr) { CPen pen(PS_SOLID,1,clr), *oldPen; oldPen = pDC->SelectObject(&pen); point=Flip(point); pDC->MoveTo(point.x - 2,point.y - 2); pDC->LineTo(point.x + 2,point.y + 2); pDC->MoveTo(point.x + 2,point.y - 2); pDC->LineTo(point.x - 2,point.y + 2); pDC->SelectObject(oldPen); } void COverviewWindow::PaintPlus(CDC* pDC, CPoint point, COLORREF clr) { CPen pen(PS_SOLID,1,clr), *oldPen; oldPen = pDC->SelectObject(&pen); point=Flip(point); pDC->MoveTo(point.x - 2,point.y); pDC->LineTo(point.x + 2,point.y); pDC->MoveTo(point.x,point.y - 2); pDC->LineTo(point.x,point.y + 2); pDC->SelectObject(oldPen); } void COverviewWindow::OnLButtonDown(UINT nFlags, CPoint point) { if((theApp.m_editorState != CMW4GameEdApp::NoGameIdleState) && (Application::Instance->GetApplicationState() == ApplicationStateEngine::RunningGameState)) { // save the current camera rotation cameraRotation = Player::Instance->GetLocalToWorld(); SetCameraPos(point); } CEditorChildWnd::OnLButtonDown(nFlags, point); } void COverviewWindow::OnRButtonDown(UINT nFlags, CPoint point) { if((theApp.m_editorState != CMW4GameEdApp::NoGameIdleState) && (Application::Instance->GetApplicationState() == ApplicationStateEngine::RunningGameState)) { // save the current rotation so we don't lose pitch and roll cameraRotation = Player::Instance->GetLocalToWorld(); SetCameraRot(point); } CEditorChildWnd::OnRButtonDown(nFlags, point); } void COverviewWindow::OnMouseMove(UINT nFlags, CPoint point) { if((theApp.m_editorState != CMW4GameEdApp::NoGameIdleState) && (Application::Instance->GetApplicationState() == ApplicationStateEngine::RunningGameState)) { if (nFlags & MK_LBUTTON) { SetCameraPos(point); } if (nFlags & MK_RBUTTON) { SetCameraRot(point); } } CEditorChildWnd::OnMouseMove(nFlags, point); } void COverviewWindow::SetCameraPos() { Check_Object(Player::Instance); Check_Object(Player::Instance->playerInterface); Stuff::Point3D pos; pos = Player::Instance->GetLocalToParent(); CRect rect; GetClientRect(&rect); cameraClientCoords.x = int(pos.x * (float(rect.right) / float(mapWidth))); cameraClientCoords.y = int(pos.z * (float(rect.bottom) / float(mapHeight))); DrawWindow(); } void COverviewWindow::SetCameraPos(CPoint point) { Check_Object(Player::Instance); Check_Object(Player::Instance->playerInterface); point=Flip(point); cameraClientCoords = point; CRect r; float x,y; GetClientRect(&r); x = float(point.x) / r.right; y = float(point.y) / r.bottom; Stuff::LinearMatrix4D newPos = LinearMatrix4D::Identity; Stuff::Point3D pos; // rot.yaw = cameraRotation; // Old code just kept the yaw and not the pitch // Now we just keep the whole rotation. // // Stuff::YawPitchRoll rot = YawPitchRoll::Identity; Stuff::YawPitchRoll rot = cameraRotation; pos.x = mapWidth * x; pos.z = mapHeight * y; pos.x -= mapWidth * 0.5f; pos.z -= mapHeight * 0.5f; if (theApp.cameraFollowing == CAMERA_FOLLOW_NONE) { pos.y = theApp.cameraHeight; } else { Entity::CollisionMask collisionType = (theApp.cameraFollowing == CAMERA_FOLLOW_NONE) ? Entity::AlwaysCollidesMask : Entity::CanBeWalkedOnFlag; pos.y = theApp.displayWindow->GetMapPointVertical(pos.x,pos.z,collisionType) + theApp.cameraHeight; } newPos.BuildTranslation(pos); newPos.BuildRotation(rot); Player::Instance->SetNewLocalToParent(newPos); Player::Instance->SyncMatrices(true); ((CMainFrame*)theApp.m_pMainWnd)->SetGridLocation(); DrawWindow(); } void COverviewWindow::SetCameraRot() { Check_Object(Player::Instance); Check_Object(Player::Instance->playerInterface); Stuff::YawPitchRoll rot; rot = Player::Instance->GetLocalToParent(); // Switching over to using cameraRotation to store the whole rotation data // cameraRotation = rot.yaw - Pi; cameraRotation = rot; InvalidateCamera(); } void COverviewWindow::SetCameraRot(CPoint point) { Check_Object(Player::Instance); Check_Object(Player::Instance->playerInterface); point=Flip(point); CRect r; GetClientRect(&r); Stuff::LinearMatrix4D newRot = Player::Instance->GetLocalToParent(); Stuff::Point3D pos; Stuff::YawPitchRoll rot; pos = newRot; rot.pitch = 0; rot.roll = 0; float a,b; if (point.y > cameraClientCoords.y) { b = float(point.y - cameraClientCoords.y); if (point.x > cameraClientCoords.x) { a = float(point.x - cameraClientCoords.x); cameraRotation.yaw = float(Pi + atan(a / b)); } else { a = float(cameraClientCoords.x - point.x); cameraRotation.yaw = float(Pi - atan(a / b)); } } else { b = float(cameraClientCoords.y - point.y); if (point.x > cameraClientCoords.x) { if (b == 0.0f) { cameraRotation.yaw = 270 * Radians_Per_Degree; } else { a = float(point.x - cameraClientCoords.x); cameraRotation.yaw = float(Two_Pi - atan(a / b)); } } else { if (b == 0.0f) { cameraRotation.yaw = 90 * Radians_Per_Degree; } else { a = float(cameraClientCoords.x - point.x); cameraRotation.yaw = float(atan(a / b)); } } } cameraRotation.yaw -= Pi; // rot.yaw = cameraRotation; rot = cameraRotation; newRot.BuildTranslation(pos); newRot.BuildRotation(rot); Player::Instance->SetNewLocalToParent(newRot); Player::Instance->SyncMatrices(true); InvalidateCamera(); } void COverviewWindow::InvalidateCamera() { CRect r; r.top = cameraClientCoords.y - 11; r.left = cameraClientCoords.x - 11; r.right = cameraClientCoords.x + 11; r.bottom = cameraClientCoords.y + 11; DrawWindow(); } void COverviewWindow::UpdateCamera() { SetCameraPos(); SetCameraRot(); } void COverviewWindow::DrawWindow() { CDC *pDC=GetDC(); if(Application::Instance->GetApplicationState() == ApplicationStateEngine::RunningGameState && BBufReady ) { CRect destrect; GetClientRect(&destrect); CDC memDC; memDC.CreateCompatibleDC(pDC); memDC.SelectObject(BackBuffer); pDC->BitBlt(0,0,destrect.Width(),destrect.Height(),&memDC,0,0,SRCCOPY); Check_Object(Map::Instance); ChainIteratorOf iterator(&Map::Instance->childEntityChain); Entity* entity; xScale = (float)(destrect.right) * 1.0f / (float)(mapWidth); yScale = (float)(destrect.bottom) * 1.0f / (float)(mapHeight); while((entity = iterator.ReadAndNext()) != NULL) { Check_Object(entity); COLORREF color; Point3D point3d; CPoint point; point3d = entity->GetLocalToWorld(); point.x = (int)((point3d.x+mapWidth*0.5f) * xScale); point.y = (int)((point3d.z+mapHeight*0.5f) * yScale); if (entity->IsDerivedFrom(EditorLatticeNode::DefaultData)) { if (theApp.m_showLattice) { point=Flip(point); pDC->SetPixel(point.x,point.y,RGB(0,255,255)); pDC->SetPixel(point.x - 1,point.y,RGB(0,255,255)); pDC->SetPixel(point.x,point.y - 1,RGB(0,255,255)); pDC->SetPixel(point.x + 1,point.y,RGB(0,255,255)); pDC->SetPixel(point.x,point.y + 1,RGB(0,255,255)); } continue; } if (entity->IsDerivedFrom(EditorBoundaryNode::DefaultData)) { if (theApp.m_showBoundary) { EditorBoundaryNode* node, *start; start = Cast_Object(EditorBoundaryNode*,entity); node = start->nextnode; pDC->MoveTo(point.x,point.y); CPen pen(PS_DASH,0,RGB(255,0,0)), *oldPen; oldPen = pDC->SelectObject(&pen); while (node != start) { point3d = node->GetLocalToWorld(); CPoint pnt; pnt.x=int((point3d.x+mapWidth*0.5f) * xScale); pnt.y=int((point3d.z+mapHeight*0.5f) * yScale); pnt=Flip(pnt); pDC->LineTo(pnt); node = node->nextnode; } point3d = node->GetLocalToWorld(); CPoint pnt; pnt.x=int((point3d.x+mapWidth*0.5f) * xScale); pnt.y=int((point3d.z+mapHeight*0.5f) * yScale); pnt=Flip(pnt); pDC->LineTo(pnt); pDC->SelectObject(oldPen); } continue; } if (entity->IsDerivedFrom(EditorMovementPath::DefaultData)) { if (theApp.m_showPaths) { EditorMovementPath* path; EditorPathNode* node; path = Cast_Object(EditorMovementPath*,entity); ChainIteratorOf iterator(&path->pathNodes); switch (path->alignment) { default: case Entity::DefaultAlignment: color = RGB(128,128,128); break; case Entity::Player: color = RGB(0,255,255); break; case Entity::Enemy: color = RGB(255,0,0); break; case Entity::Team1: color = RGB(0,0,255); break; case Entity::Team2: color = RGB(255,255,0); break; case Entity::Team3: color = RGB(255,0,255); break; case Entity::Team4: color = RGB(0,255,0); break; } while ((node = iterator.ReadAndNext()) != NULL) { point3d = node->GetLocalToWorld(); point.x = int((point3d.x+mapWidth*0.5f) * xScale); point.y = int((point3d.z+mapHeight*0.5f) * yScale); PaintCircle(pDC,point,15,color); point=Flip(point); if (node->prevnode) { CPen pen(PS_SOLID,1,color), *oldPen; oldPen = pDC->SelectObject(&pen); pDC->MoveTo(point); point3d = node->prevnode->GetLocalToWorld(); point.x = int((point3d.x+mapWidth*0.5f)* xScale); point.y = int((point3d.z+mapHeight*0.5f) * yScale); point=Flip(point); pDC->LineTo(point); pDC->SelectObject(oldPen); } } } continue; } switch (entity->alignment) { default: case Entity::DefaultAlignment: color = RGB(128,128,128); break; case Entity::Player: color = RGB(0,255,255); break; case Entity::Enemy: color = RGB(255,0,0); break; case Entity::Team1: color = RGB(0,0,255); break; case Entity::Team2: color = RGB(255,255,0); break; case Entity::Team3: color = RGB(255,0,255); break; case Entity::Team4: color = RGB(0,255,0); break; } int extent = 5; // this is the radius of the object so we can scale our shapes to the window size ElementRenderer::Element* element; element = entity->GetElement(); if (element->IsBoundedBySphere()) { extent = int(element->GetWorldOBB().sphereRadius); } else if (element->IsBoundedByOBB()) { // handle OBB's when they come online. extent = 5; } if (entity->IsDerivedFrom(MechWarrior4::Mech::DefaultData)) { PaintTriangle(pDC,point,extent,color,true); } else if (entity->IsDerivedFrom(MechWarrior4::Vehicle::DefaultData)) { PaintTriangle(pDC,point,extent,color); } else if (entity->IsDerivedFrom(MechWarrior4::Building::DefaultData)) { PaintSquare(pDC,point,extent,color); } /* Objectives have no position else if (entity->IsDerivedFrom(EditorObjectiveMarker::DefaultData)) { EditorObjectiveMarker* marker; marker = Cast_Object(EditorObjectiveMarker*,entity); PaintCircle(pDC,point,color,marker->objective->m_Primary); } */ } PaintCameraPos(pDC); } else { CRect r; GetClientRect(&r); pDC->FillSolidRect(&r,RGB(0,0,0)); } ReleaseDC(pDC); } void COverviewWindow::BuildBackBuffer() { if(!ImgReady) return; CDC *pDC=GetDC(); BackBuffer.DeleteObject(); CRect rect; pDC->SetStretchBltMode(COLORONCOLOR); GetClientRect(&rect); BackBuffer.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height()); CDC memDC; memDC.CreateCompatibleDC(pDC); memDC.SelectObject(BackBuffer); Image *bimage=NULL; BITMAPINFO binf; switch(CurrentVMode) { case VM_TEXTURE: bimage=&MapImage; break; case VM_HFIELD: bimage=&HField; break; case VM_SLOPEMAP: bimage=&SlopeMap; break; default: STOP(("Invalid Mode")); } ZeroMemory(&binf,sizeof(binf)); binf.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); binf.bmiHeader.biWidth=bimage->GetWidth(); binf.bmiHeader.biHeight=-bimage->GetHeight(); binf.bmiHeader.biPlanes=1; binf.bmiHeader.biBitCount=(unsigned short)bimage->GetBpp(); binf.bmiHeader.biCompression=BI_RGB; Verify(binf.bmiHeader.biBitCount==24 || binf.bmiHeader.biBitCount==32); int res; res=StretchDIBits(memDC,0,0,rect.Width(),rect.Height(), 0,0,bimage->GetWidth(),bimage->GetHeight(), bimage->Lock(),&binf,DIB_RGB_COLORS,SRCCOPY); Verify(res!=0); bimage->UnLock(); ReleaseDC(pDC); BBufReady=true; } CPoint COverviewWindow::Flip(CPoint pnt) { CRect crect; GetClientRect(&crect); pnt.x=crect.Width()-pnt.x; pnt.y=crect.Height()-pnt.y; return pnt; } CRect COverviewWindow::Flip(CRect rct) { CRect crect; GetClientRect(&crect); rct.left=crect.Width()-rct.left; rct.right=crect.Width()-rct.right; rct.top=crect.Height()-rct.top; rct.bottom=crect.Height()-rct.bottom; return rct; }