dev.nlited.com

>>

Image.cpp

<<<< prev
next >>>>

2016-08-21 19:25:26 chip Page 1826 📢 PUBLIC

Image.cpp performs all the actual draw operations.



Image.cpp: /*************************************************************************/ /** Image.cpp: Manages the offscreen image, SwapChain method. **/ /** (C)2016 nlited systems, Chip Doran **/ /*************************************************************************/ #include <Windows.h> #include "Util.h" #include "MyD2D.h" #include "Sprite.h" #include "Globals.h" using namespace D2D1; //Direct2D version 1 #define SPRITE_MAX 8000 //Limit the number of sprites to create struct Bitmap_s BitmapList[]= { { BITMAP_ROCKET_PNG, L"PNG", L"PNG_ROCKET",2 }, { BITMAP_NONE } }; class Image { public: static Image *Ptr(HIMAGE hImg); static int Create(HIMAGE *phImg, HWND hWnd); int Destroy(void); int Resize(const RECT *pR); int SetAttract(HATTRACT hAttract); int Redraw(void); int Paint(void); int Begin(void); ID2D1RenderTarget *GetRender(void); int End(void); int AddSprite(struct Sprite_s *pSprite); //Data UINT32 Signature; private: Image(void); ~Image(void); int Create2(HWND hWnd); int DrawCreate(ID2D1HwndRenderTarget **pRender); int DrawCreateBitmaps(void); void ReleaseEverything(void); int DrawBackground(void); int DrawStatus(void); int DrawSprites(void); void DrawText(const D2D_RECT_F &rText, const WCHAR *Fmt, ...); //Data HWND hWnd; HATTRACT hAttract; bool IsBuilding; bool DoRedraw; bool DoReset; bool IsBitmapLoaded; RECT rImg; ID2D1BitmapRenderTarget *pImgRender; UINT RedrawCt; UINT SpriteCt; struct Sprite_s *Sprites[SPRITE_MAX]; D2D_COLOR_F TextClr; INT64 uSecTicks; //QueryPerformanceCounter() ticks per microsecond INT64 DrawTime; //Elapsed microseconds for previous Redraw() INT64 PaintTime; //Elapsed microseconds for previous Paint() UINT DrawAvg; //Rolling average of DrawTime UINT PaintAvg; //Rolling average of PaintTime UINT FramesPerSec; UINT FrameCt; UINT64 FrameCtEnd; WCHAR Text[200]; }; /*************************************************************************/ /** Public interface **/ /*************************************************************************/ int ImgCreate(HIMAGE *phImg, HWND hWnd) { if(IsBadPtr(phImg,sizeof(*phImg),BADPTR_WRITE)) return(ERR_BADPTR); if(!IsWindow(hWnd)) return(ERR_BADARG1); return(Image::Create(phImg,hWnd)); } int ImgDestroy(HIMAGE hImg) { Image *pImg= Image::Ptr(hImg); if(!pImg) return(ERR_BADHANDLE); return(pImg->Destroy()); } int ImgResize(HIMAGE hImg, const RECT *pR) { Image *pImg= Image::Ptr(hImg); if(!pImg) return(ERR_BADHANDLE); if(IsBadPtr(pR,sizeof(*pR),BADPTR_READ)) return(ERR_BADPTR); return(pImg->Resize(pR)); } int ImgSetAttract(HIMAGE hImg, HATTRACT hAttract) { Image *pImg= Image::Ptr(hImg); if(!pImg) return(ERR_BADHANDLE); return(pImg->SetAttract(hAttract)); } int ImgPaint(HIMAGE hImg) { Image *pImg= Image::Ptr(hImg); if(!pImg) return(ERR_BADHANDLE); return(pImg->Paint()); } int ImgBegin(HIMAGE hImg) { Image *pImg= Image::Ptr(hImg); if(!pImg) return(ERR_BADHANDLE); return(pImg->Begin()); } ID2D1RenderTarget *ImgGetRender(HIMAGE hImg) { Image *pImg= Image::Ptr(hImg); if(!pImg) return(0); return(pImg->GetRender()); } int ImgEnd(HIMAGE hImg) { Image *pImg= Image::Ptr(hImg); if(!pImg) return(ERR_BADHANDLE); return(pImg->End()); } int ImgAddSprite(HIMAGE hImg, struct Sprite_s *pSprite) { Image *pImg= Image::Ptr(hImg); if(!pImg) return(ERR_BADHANDLE); if(IsBadPtr(pSprite,sizeof(*pSprite),BADPTR_RW)) return(ERR_BADPTR); return(pImg->AddSprite(pSprite)); } /*************************************************************************/ /** Public internals **/ /*************************************************************************/ Image *Image::Ptr(HIMAGE hImg) { Image *pImg= (Image*)hImg; if(!hImg || IsBadPtr(pImg,sizeof(*pImg),BADPTR_RW) || pImg->Signature!=SIGNATURE_IMAGE) pImg= 0; return(pImg); } int Image::Create(HIMAGE *phImg, HWND hWnd) { int Err= ERR_OK; Image *pImg= new Image; if(!pImg) { Err= Error(ERR_NOMEM,__FUNCTION__": NoMem(%d)",sizeof(*pImg)); } else if(IsErr(Err= pImg->Create2(hWnd))) { delete pImg; } else { *phImg= (HIMAGE)pImg; } return(Err); } int Image::Destroy(void) { int Err= ERR_OK; delete this; return(Err); } int Image::Resize(const RECT *pR) { int Err= ERR_OK; rImg= *pR; ID2D1HwndRenderTarget *pRender= MyD2DRenderWnd(ghD2D,hWnd); if(pRender) pRender->Resize(SizeU(RWID(rImg),RHGT(rImg))); if(pImgRender) SafeRelease(pImgRender); DoRedraw= 1; return(Err); } int Image::SetAttract(HATTRACT hAttract) { this->hAttract= hAttract; return(ERR_OK); } int Image::Redraw(void) { int Err= ERR_OK; HRESULT WinErr; LARGE_INTEGER Start,End; D2D1_TAG Tag1,Tag2; ID2D1HwndRenderTarget *pRender= MyD2DRenderWnd(ghD2D,hWnd); if(IsBuilding) return(ERR_BUSY); if(!(pRender && pImgRender /*&& pImgBitmap*/)) return(ERR_NOINIT); RedrawCt++; FrameCt++; QueryPerformanceCounter(&Start); pImgRender->BeginDraw(); DrawBackground(); DrawSprites(); DrawStatus(); if(hAttract) AttractDraw(hAttract,(HIMAGE)this); WinErr= pImgRender->EndDraw(&Tag1,&Tag2); QueryPerformanceCounter(&End); DrawTime= (End.QuadPart-Start.QuadPart)/uSecTicks; if(!SUCCEEDED(WinErr)) { Warn(ERR_SYSCREATE,__FUNCTION__": Draw failed. [%d/%X:%d:%d]",WinErr,WinErr,Tag1,Tag2); if(WinErr==D2DERR_RECREATE_TARGET) DoReset= 1; } DoRedraw= 0; return(Err); } int Image::Paint(void) { int Err= ERR_OK; HRESULT WinErr; D2D1_TAG Tag1,Tag2; ID2D1HwndRenderTarget *pRender= MyD2DRenderWnd(ghD2D,hWnd); ID2D1Bitmap *pImage; LARGE_INTEGER Start,End; if(!FrameCtEnd) { FrameCtEnd= GetTickCount64()+10000; FrameCt= 0; } if(!(pRender && pImgRender) && IsErr(Err= DrawCreate(&pRender))) return(Err); if(DoRedraw) Redraw(); QueryPerformanceCounter(&Start); pRender->BeginDraw(); pImgRender->GetBitmap(&pImage); pRender->DrawBitmap(pImage); WinErr= pRender->EndDraw(&Tag1,&Tag2); QueryPerformanceCounter(&End); PaintTime= (End.QuadPart-Start.QuadPart)/uSecTicks; if(!SUCCEEDED(WinErr)) { Warn(ERR_SYSCREATE,__FUNCTION__": Draw failed. [%d/%X:%d:%d]",WinErr,WinErr,Tag1,Tag2); if(WinErr==D2DERR_RECREATE_TARGET) DoReset= 1; } if(GetTickCount64()>=FrameCtEnd) { FramesPerSec= FrameCt; FrameCt= 0; FrameCtEnd= GetTickCount64()+10000; } if(DoReset) { //EVERYTHING needs to be released and recreated. Warn(ERR_OK,__FUNCTION__": Resetting..."); ReleaseEverything(); DoReset= 0; } return(Err); } int Image::Begin(void) { int Err= ERR_OK; SpriteCt= 0; IsBuilding= 1; DoRedraw= 1; return(Err); } ID2D1RenderTarget *Image::GetRender(void) { return(pImgRender); } int Image::End(void) { int Err= ERR_OK; IsBuilding= 0; return(Err); } int Image::AddSprite(struct Sprite_s *pSprite) { int Err= ERR_OK; UINT n1; if(SpriteCt>=SPRITE_MAX) { Err= Warn(ERR_TOO_MANY,__FUNCTION__": Too many sprites! [%d]",SpriteCt); } else { if(pSprite->SpriteID==SPRITE_BITMAP) { for(n1=0;BitmapList[n1].BitmapID && BitmapList[n1].BitmapID!=pSprite->BitmapID;n1++); pSprite->pBitmap= &BitmapList[n1]; } //TODO: Sort by Z-Order Sprites[SpriteCt++]= pSprite; } return(Err); } /*************************************************************************/ /** Private internals **/ /*************************************************************************/ Image::Image(void) { LARGE_INTEGER Freq; memset(this,0,sizeof(*this)); Signature= SIGNATURE_IMAGE; TextClr= D2D1::ColorF(RGB(200,249,40),(FLOAT)0.85); QueryPerformanceFrequency(&Freq); uSecTicks= Freq.QuadPart/1000000; //Ticks per microsecond. srand(GetTickCount()); } Image::~Image(void) { Signature|= SIGNATURE_INVALID; ReleaseEverything(); } int Image::Create2(HWND hWnd) { int Err= ERR_OK; this->hWnd= hWnd; DoRedraw= 1; return(Err); } int Image::DrawCreate(ID2D1HwndRenderTarget **ppRender) { int Err= ERR_OK; HRESULT WinErr; ID2D1RenderTarget *pRender= 0; if(IsErr(Err= MyD2DCreateResourcesWnd(ghD2D,hWnd))) { Err= Error(Err,__FUNCTION__": Unable to create Direct2D resources."); } else if(!(pRender= MyD2DRenderWnd(ghD2D,hWnd))) { Err= Error(Err,__FUNCTION__": Unable to retrieve Renderer."); } else if(!pImgRender && !SUCCEEDED(WinErr= pRender->CreateCompatibleRenderTarget(0,0,0,D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE,&pImgRender))) { Err= Error(ERR_SYSCREATE,__FUNCTION__": Unable to create ImgRender. [%X]",WinErr); } else if(!IsBitmapLoaded && IsErr(Err= DrawCreateBitmaps())) { Err= Error(Err,__FUNCTION__": Unable to load bitmaps."); } else { IsBitmapLoaded= 1; DoReset= 0; } *ppRender= (ID2D1HwndRenderTarget*)pRender; return(Err); } int Image::DrawCreateBitmaps(void) { int Err= ERR_OK; UINT n1; for(n1=0;BitmapList[n1].BitmapID;n1++) { Err= MyD2DBitmapCreate(ghD2D,&BitmapList[n1]); } return(Err); } void Image::ReleaseEverything(void) { UINT n1; IsBitmapLoaded= 0; for(n1=0;BitmapList[n1].BitmapID;n1++) SafeRelease(BitmapList[n1].pBitmap); SafeRelease(pImgRender); MyD2DReleaseResources(ghD2D,hWnd); } /*************************************************************************/ /** Draw frame components **/ /*************************************************************************/ int Image::DrawBackground(void) { int Err= ERR_OK; D2D_COLOR_F FillClr(ColorF(RGB(40,10,20))); if(pImgRender) { pImgRender->Clear(FillClr); } return(Err); } int Image::DrawStatus(void) { int Err= ERR_OK; UINT ChrCt= 0; WCHAR Text[80]; D2D_RECT_F rText(RectF(20.0f,(FLOAT)(rImg.bottom-20),(FLOAT)(rImg.right-20),(FLOAT)rImg.bottom)); if(pImgRender) { DrawAvg+= (int)(DrawTime-DrawAvg)/100; PaintAvg+= (int)(PaintTime-PaintAvg)/100; pImgRender->SetTransform(Matrix3x2F::Identity()); ChrCt+= StrFormatW(Text+ChrCt,STRSIZE(Text)-ChrCt,L"%u.%01u FPS, ",FramesPerSec/10,FramesPerSec%10); ChrCt+= StrFormatW(Text+ChrCt,STRSIZE(Text)-ChrCt,L"%04u sprites, ",SpriteCt); ChrCt+= StrFormatW(Text+ChrCt,STRSIZE(Text)-ChrCt,L"Draw %2u.%03ums, ",DrawAvg/1000,DrawAvg%1000); ChrCt+= StrFormatW(Text+ChrCt,STRSIZE(Text)-ChrCt,L"Paint %2u.%03ums",PaintAvg/1000,PaintAvg%1000); DrawText(rText,L"Redraw %6d: %s",RedrawCt,Text); } return(Err); } /*************************************************************************/ /** Sprites **/ /*************************************************************************/ int Image::DrawSprites(void) { int Err= ERR_OK; UINT n1; if(pImgRender) { for(n1=0;n1<SpriteCt;n1++) { SpriteDrawImg(pImgRender,Sprites[n1]); } } return(Err); } /*************************************************************************/ /** Format and draw text. **/ /*************************************************************************/ void Image::DrawText(const D2D_RECT_F &rText, const WCHAR *Fmt, ...) { UINT ChrCt= 0; va_list ArgList; ID2D1SolidColorBrush *pBrush= 0; IDWriteTextFormat *pFormat= MyD2DTextFormat(ghD2D); if(pImgRender && pFormat) { va_start(ArgList,Fmt); ChrCt+= StrFormatVW(Text+ChrCt,STRSIZE(Text)-ChrCt,Fmt,ArgList); pImgRender->CreateSolidColorBrush(TextClr,&pBrush); pImgRender->DrawTextW(Text,ChrCt,pFormat,rText,pBrush); pBrush->Release(); va_end(ArgList); } }


WebV7 (C)2018 nlited | Rendered by tikope in 118.646ms | 18.226.187.232