bool C4GraphicsSystem::ToggleShowHelp() { Toggle(ShowHelp); // Turned off? Invalidate background. if (!ShowHelp) InvalidateBg(); return true; }
void C4GraphicsSystem::DrawFlashMessage() { if (!FlashMessageTime) return; if (!Application.isFullScreen) return; Application.DDraw->TextOut(FlashMessageText, Game.GraphicsResource.FontRegular, 1.0, Application.DDraw->lpBack, (FlashMessageX==-1) ? Config.Graphics.ResX/2 : FlashMessageX, (FlashMessageY==-1) ? Config.Graphics.ResY/2 : FlashMessageY, CStdDDraw::DEFAULT_MESSAGE_COLOR, (FlashMessageX==-1) ? ACenter : ALeft); FlashMessageTime--; // Flash message timed out: redraw background if (!FlashMessageTime) InvalidateBg(); }
void C4GraphicsSystem::DrawFlashMessage() { if (!FlashMessageTime) return; if (Application.isEditor) return; pDraw->TextOut(FlashMessageText, ::GraphicsResource.FontRegular, 1.0, FullScreen.pSurface, (FlashMessageX==-1) ? C4GUI::GetScreenWdt()/2 : FlashMessageX, (FlashMessageY==-1) ? C4GUI::GetScreenHgt()/2 : FlashMessageY, C4Draw::DEFAULT_MESSAGE_COLOR, (FlashMessageX==-1) ? ACenter : ALeft); FlashMessageTime--; // Flash message timed out: redraw background if (!FlashMessageTime) InvalidateBg(); }
void C4GraphicsSystem::FlashMessage(const char *szMessage) { // Store message SCopy(szMessage, FlashMessageText, C4MaxTitle); // Calculate message time FlashMessageTime = SLen(FlashMessageText) * 2; // Initial position FlashMessageX = -1; FlashMessageY = 10; // Upper board active: stay below upper board if (Config.Graphics.UpperBoard) FlashMessageY += C4UpperBoardHeight; // More than one viewport: try to stay below portraits etc. if (GetViewportCount() > 1) FlashMessageY += 64; // New flash message: redraw background (might be drawing one message on top of another) InvalidateBg(); }
void C4GraphicsSystem::Default() { MessageBoard.reset(new C4MessageBoard); InvalidateBg(); ShowVertices=false; ShowAction=false; ShowCommand=false; ShowEntrance=false; ShowPathfinder=false; ShowNetstatus=false; Show8BitSurface=0; ShowLights=false; ShowMenuInfo=false; ShowHelp=false; FlashMessageText[0]=0; FlashMessageTime=0; FlashMessageX=FlashMessageY=0; pLoaderScreen=NULL; }
void C4GraphicsSystem::Default() { UpperBoard.Default(); MessageBoard.Default(); FirstViewport=NULL; InvalidateBg(); ViewportArea.Default(); ShowVertices=FALSE; ShowAction=FALSE; ShowCommand=FALSE; ShowEntrance=FALSE; ShowPathfinder=FALSE; ShowNetstatus=FALSE; ShowSolidMask=FALSE; ShowHelp=FALSE; FlashMessageText[0]=0; FlashMessageTime=0; FlashMessageX=FlashMessageY=0; fSetPalette=FALSE; Video.Default(); for (int32_t iRamp=0; iRamp<3*C4MaxGammaRamps; iRamp+=3) { dwGamma[iRamp+0]=0; dwGamma[iRamp+1]=0x808080; dwGamma[iRamp+2]=0xffffff; } fSetGamma=FALSE; pLoaderScreen=NULL; }
BOOL C4GraphicsSystem::DoSaveScreenshot(bool fSaveAll, const char *szFilename) { // Fullscreen only if (!Application.isFullScreen) return FALSE; // back surface must be present if (!Application.DDraw->lpBack) return FALSE; // save landscape if (fSaveAll) { // get viewport to draw in C4Viewport *pVP=GetFirstViewport(); if (!pVP) return FALSE; // create image large enough to hold the landcape CPNGFile png; int32_t lWdt=GBackWdt,lHgt=GBackHgt; if (!png.Create(lWdt, lHgt, false)) return FALSE; // get backbuffer size int32_t bkWdt=Config.Graphics.ResX,bkHgt=Config.Graphics.ResY; if (!bkWdt || !bkHgt) return FALSE; // facet for blitting C4FacetEx bkFct; // mark background to be redrawn InvalidateBg(); // backup and clear sky parallaxity int32_t iParX=Game.Landscape.Sky.ParX; Game.Landscape.Sky.ParX=10; int32_t iParY=Game.Landscape.Sky.ParY; Game.Landscape.Sky.ParY=10; // temporarily change viewport player int32_t iVpPlr=pVP->Player; pVP->Player=NO_OWNER; // blit all tiles needed for (int32_t iY=0; iY<lHgt; iY+=bkHgt) for (int32_t iX=0; iX<lWdt; iX+=bkWdt) { // get max width/height int32_t bkWdt2=bkWdt,bkHgt2=bkHgt; if (iX+bkWdt2>lWdt) bkWdt2-=iX+bkWdt2-lWdt; if (iY+bkHgt2>lHgt) bkHgt2-=iY+bkHgt2-lHgt; // update facet bkFct.Set(Application.DDraw->lpBack, 0, 0, bkWdt2, bkHgt2, iX, iY); // draw there pVP->Draw(bkFct, false); // render Application.DDraw->PageFlip(); Application.DDraw->PageFlip(); // get output (locking primary!) if (Application.DDraw->lpBack->Lock()) { // transfer each pixel - slooow... for (int32_t iY2=0; iY2<bkHgt2; ++iY2) for (int32_t iX2=0; iX2<bkWdt2; ++iX2) png.SetPix(iX+iX2, iY+iY2, Application.DDraw->ApplyGammaTo(Application.DDraw->lpBack->GetPixDw(iX2, iY2, false))); // done; unlock Application.DDraw->lpBack->Unlock(); } } // restore viewport player pVP->Player=iVpPlr; // restore parallaxity Game.Landscape.Sky.ParX=iParX; Game.Landscape.Sky.ParY=iParY; // save! return png.Save(szFilename); } // Save primary surface return Application.DDraw->lpBack->SavePNG(szFilename, false, true, false); }
void C4GraphicsSystem::RecalculateViewports() { // Fullscreen only if (!Application.isFullScreen) return; // Sort viewports SortViewportsByPlayerControl(); // Viewport area int32_t iBorderTop = 0, iBorderBottom = 0; if (Config.Graphics.UpperBoard) iBorderTop = C4UpperBoardHeight; iBorderBottom = MessageBoard.Output.Hgt; ViewportArea.Set(Application.DDraw->lpBack,0,iBorderTop, Config.Graphics.ResX, Config.Graphics.ResY-iBorderTop-iBorderBottom); // Redraw flag InvalidateBg(); #ifdef _WIN32 // reset mouse clipping ClipCursor(NULL); #else // StdWindow handles this. #endif // reset GUI dlg pos if (Game.pGUI) Game.pGUI->SetPreferredDlgRect(C4Rect(ViewportArea.X, ViewportArea.Y, ViewportArea.Wdt, ViewportArea.Hgt)); // fullscreen background: First, cover all of screen BackgroundAreas.Clear(); BackgroundAreas.AddRect(C4Rect(ViewportArea.X, ViewportArea.Y, ViewportArea.Wdt, ViewportArea.Hgt)); // Viewports C4Viewport *cvp; int32_t iViews = 0; for (cvp=FirstViewport; cvp; cvp=cvp->Next) iViews++; if (!iViews) return; int32_t iViewsH = (int32_t) sqrt(float(iViews)); int32_t iViewsX = iViews / iViewsH; int32_t iViewsL = iViews % iViewsH; int32_t cViewH,cViewX,ciViewsX; int32_t cViewWdt,cViewHgt,cOffWdt,cOffHgt,cOffX,cOffY; cvp=FirstViewport; for (cViewH=0; cViewH<iViewsH; cViewH++) { ciViewsX = iViewsX; if (cViewH<iViewsL) ciViewsX++; for (cViewX=0; cViewX<ciViewsX; cViewX++) { cViewWdt = ViewportArea.Wdt/ciViewsX; cViewHgt = ViewportArea.Hgt/iViewsH; cOffX = ViewportArea.X; cOffY = ViewportArea.Y; cOffWdt=cOffHgt=0; int32_t ViewportScrollBorder = Application.isFullScreen ? C4ViewportScrollBorder : 0; if (ciViewsX*Min<int32_t>(cViewWdt, GBackWdt+2*ViewportScrollBorder)<ViewportArea.Wdt) cOffX=(ViewportArea.Wdt-ciViewsX*Min<int32_t>(cViewWdt, GBackWdt+2*ViewportScrollBorder))/2; if (iViewsH*Min<int32_t>(cViewHgt, GBackHgt+2*ViewportScrollBorder)<ViewportArea.Hgt) cOffY=(ViewportArea.Hgt-iViewsH*Min<int32_t>(cViewHgt, GBackHgt+2*ViewportScrollBorder))/2 + ViewportArea.Y; if (Config.Graphics.SplitscreenDividers) { if (cViewX<ciViewsX-1) cOffWdt=4; if (cViewH<iViewsH-1) cOffHgt=4; } int32_t coViewWdt=cViewWdt-cOffWdt; if (coViewWdt>GBackWdt+2*ViewportScrollBorder) { coViewWdt=GBackWdt+2*ViewportScrollBorder; } int32_t coViewHgt=cViewHgt-cOffHgt; if (coViewHgt>GBackHgt+2*ViewportScrollBorder) { coViewHgt=GBackHgt+2*ViewportScrollBorder; } C4Rect rcOut(cOffX+cViewX*cViewWdt, cOffY+cViewH*cViewHgt, coViewWdt, coViewHgt); cvp->SetOutputSize(rcOut.x,rcOut.y,rcOut.x,rcOut.y,rcOut.Wdt,rcOut.Hgt); cvp=cvp->Next; // clip down area avaiable for background drawing BackgroundAreas.ClipByRect(rcOut); } } }
bool C4GraphicsSystem::DoSaveScreenshot(bool fSaveAll, const char *szFilename, float fSaveAllZoom) { // Fullscreen only if (Application.isEditor) return false; // back surface must be present if (!FullScreen.pSurface) return false; // save landscape if (fSaveAll) { // Create full map screenshots at zoom 2x. Fractional zooms (like 1.7x) should work but might cause some trouble at screen borders. float zoom = fSaveAllZoom; // get viewport to draw in C4Viewport *pVP=::Viewports.GetFirstViewport(); if (!pVP) return false; // create image large enough to hold the landscape std::unique_ptr<CPNGFile> png(new CPNGFile()); int32_t lWdt = GBackWdt * zoom, lHgt = GBackHgt * zoom; if (!png->Create(lWdt, lHgt, false)) return false; // get backbuffer size int32_t bkWdt=C4GUI::GetScreenWdt(), bkHgt=C4GUI::GetScreenHgt(); if (!bkWdt || !bkHgt) return false; // facet for blitting C4TargetFacet bkFct; // mark background to be redrawn InvalidateBg(); // draw on one big viewport pVP->SetOutputSize(0,0,0,0, bkWdt, bkHgt); // backup and clear sky parallaxity int32_t iParX=::Landscape.Sky.ParX; ::Landscape.Sky.ParX=10; int32_t iParY=::Landscape.Sky.ParY; ::Landscape.Sky.ParY=10; // backup and clear viewport borders FLOAT_RECT vp_borders = { pVP->BorderLeft, pVP->BorderRight, pVP->BorderTop, pVP->BorderBottom }; pVP->BorderLeft = pVP->BorderRight = pVP->BorderTop = pVP->BorderBottom = 0.0f; // temporarily change viewport player int32_t iVpPlr=pVP->Player; pVP->Player=NO_OWNER; // blit all tiles needed for (int32_t iY=0; iY<lHgt; iY+=bkHgt) for (int32_t iX=0; iX<lWdt; iX+=bkWdt) { // get max width/height int32_t bkWdt2=bkWdt,bkHgt2=bkHgt; if (iX+bkWdt2>lWdt) bkWdt2-=iX+bkWdt2-lWdt; if (iY+bkHgt2>lHgt) bkHgt2-=iY+bkHgt2-lHgt; // update facet bkFct.Set(FullScreen.pSurface, 0, 0, ceil(float(bkWdt2)/zoom), ceil(float(bkHgt2)/zoom), iX/zoom, iY/zoom, zoom, 0, 0); // draw there pVP->Draw(bkFct, true, false); // render FullScreen.pSurface->PageFlip(); FullScreen.pSurface->PageFlip(); // get output (locking primary!) if (FullScreen.pSurface->Lock()) { // transfer each pixel - slooow... for (int32_t iY2 = 0; iY2 < bkHgt2; ++iY2) #ifndef USE_CONSOLE glReadPixels(0, FullScreen.pSurface->Hgt - iY2 - 1, bkWdt2, 1, GL_BGR, GL_UNSIGNED_BYTE, reinterpret_cast<BYTE *>(png->GetRow(iY + iY2)) + iX * 3); #else for (int32_t iX2=0; iX2<bkWdt2; ++iX2) png->SetPix(iX+iX2, iY+iY2, FullScreen.pSurface->GetPixDw(iX2, iY2, false)); #endif // done; unlock FullScreen.pSurface->Unlock(); // This can take a long time and we would like to pump messages // However, we're currently hogging the primary surface and horrible things might happen if we do that, including initiation of another screenshot // The only thing that can be safely run is music (sound could play but that would just make them out of sync of the game) ::Application.MusicSystem.Execute(true); } } // restore viewport player pVP->Player=iVpPlr; // restore viewport borders pVP->BorderLeft = vp_borders.left; pVP->BorderTop = vp_borders.top; pVP->BorderRight = vp_borders.right; pVP->BorderBottom = vp_borders.bottom; // restore parallaxity ::Landscape.Sky.ParX=iParX; ::Landscape.Sky.ParY=iParY; // restore viewport size ::Viewports.RecalculateViewports(); // save! CPNGFile::ScheduleSaving(png.release(), szFilename); return true; } // Save primary surface in background thread return FullScreen.pSurface->SavePNG(szFilename, false, false, true); }