diff --git a/game/sdl/display.cpp b/game/sdl/display.cpp index 277b60b..932a9de 100644 --- a/game/sdl/display.cpp +++ b/game/sdl/display.cpp @@ -31,11 +31,19 @@ Display::Display() m_pbmBack = NULL; m_pbmFront = NULL; m_pbmClip = NULL; - - m_gameDisplay = NULL; - m_gameSurfacePixels = NULL; - m_gameSurface = NULL; + + m_window = NULL; + m_renderer = NULL; + m_texture = NULL; + + m_gamePixels = NULL; + m_gamePixels32 = NULL; + memset(m_palette, 0, sizeof(m_palette)); + m_pitch32 = 0; m_pixelCount = 0; + + m_density = 0; + m_fShouldRender = false; } Display::~Display() @@ -46,24 +54,23 @@ Display::~Display() m_pbmFront = NULL; delete m_pbmClip; m_pbmClip = NULL; - - delete m_gameDisplay; - m_gameDisplay = NULL; - - m_pixelCount = 0; - m_gameSurfacePixels = NULL; - SDL_FreeSurface(m_gameSurface); - m_gameSurface = NULL; - SDL_DestroyWindow(window); - window = NULL; - SDL_DestroyTexture(texture); - texture = NULL; + + SDL_DestroyWindow(m_window); + m_window = NULL; + SDL_DestroyRenderer(m_renderer); + m_renderer = NULL; + SDL_DestroyTexture(m_texture); + m_texture = NULL; + + delete m_gamePixels; + m_gamePixels = NULL; + delete m_gamePixels32; + m_gamePixels32 = NULL; } bool Display::Init() { - Uint32 videoflags; - int cxScreen, cyScreen; + dword videoflags; /* Initialize SDL */ if (SDL_Init(SDL_INIT_VIDEO) < 0) { @@ -80,7 +87,7 @@ bool Display::Init() SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeRight LandscapeLeft"); #endif - // The host wants to process mouse and touch events separately + // Android wants to process mouse and touch events separately #if defined(__ANDROID__) SDL_SetHint(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1"); #endif @@ -88,27 +95,36 @@ bool Display::Init() // Get surface properties SurfaceProperties props; HostHelpers::GetSurfaceProperties(&props); - cxScreen = props.cxWidth; - cyScreen = props.cyHeight; + m_cx = props.cxWidth; + m_cy = props.cyHeight; m_density = props.density; // Create window - if ((window = SDL_CreateWindow("Hostile Takeover", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, cxScreen, cyScreen, videoflags)) == NULL) { - LOG() << "Couldn't create window: " << cxScreen << "x" << cyScreen << " \nError: " << SDL_GetError(); + if ((m_window = SDL_CreateWindow("Hostile Takeover", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_cx, m_cy, videoflags)) == NULL) { + LOG() << "Couldn't create window: " << m_cx << "x" << m_cy << " \nError: " << SDL_GetError(); return false; } - renderer = SDL_CreateRenderer(window, 0, SDL_RENDERER_TARGETTEXTURE); + // Create renderer + m_renderer = SDL_CreateRenderer(m_window, 0, SDL_RENDERER_TARGETTEXTURE); this->SetShouldRender(true); // Keep the screen size around - s_siz.cx = cxScreen; - s_siz.cy = cyScreen; + s_siz.cx = m_cx; + s_siz.cy = m_cy; - m_gameSurface = SDL_CreateRGBSurface(videoflags, cxScreen, cyScreen, 32, 0, 0, 0, 0); - m_pixelCount = cxScreen * cyScreen; - m_gameDisplay = (byte *)malloc(m_pixelCount); - m_gameSurfacePixels = (Uint32 *)m_gameSurface->pixels; + // Create texture + m_texture = SDL_CreateTexture(m_renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_TARGET, m_cx, m_cy); + + // Set pixel info + m_pixelCount = m_cx * m_cy; + m_gamePixels = (byte *)malloc(m_pixelCount); + m_gamePixels32 = (dword *)malloc(m_pixelCount * 4); + m_pitch32 = m_cx * sizeof(dword); + + // Keep the screen size around + s_siz.cx = m_cx; + s_siz.cy = m_cy; ModeInfo *pmode = m_amodeInfo; @@ -178,7 +194,7 @@ void Display::SetPalette(Palette *ppal) } for (int i = 0; i < cEntries; i++) { - m_32bppColors[i] = ((Uint8)aclr[i].r << 16) | ((Uint8)aclr[i].g << 8) | ((Uint8)aclr[i].b << 0); + m_palette[i] = ((Uint8)aclr[i].r << 16) | ((Uint8)aclr[i].g << 8) | ((Uint8)aclr[i].b << 0); } } @@ -217,7 +233,7 @@ bool Display::SetMode(int imode) if (pbmBack == NULL) return false; - DibBitmap *pbmFront = CreateDibBitmap(m_gameDisplay, pmode->cx, pmode->cy); + DibBitmap *pbmFront = CreateDibBitmap(m_gamePixels, pmode->cx, pmode->cy); if (pbmFront == NULL) { delete pbmBack; return NULL; @@ -269,38 +285,35 @@ void Display::FrameStart() { // surface->pixels can change every time the surface is locked. // TODO(darrinm): problem for, e.g. scrolling optimizations? - m_pbmFront->Init(m_gameDisplay, m_gameSurface->w, m_gameSurface->h); + m_pbmFront->Init(m_gamePixels, m_cx, m_cy); } void Display::FrameComplete(int cfrmm, UpdateMap **apupd, Rect *arc, bool fScrolled) { for (int i = 0; i < m_pixelCount; i++) { - m_gameSurfacePixels[i] = m_32bppColors[m_gameDisplay[i]]; + m_gamePixels32[i] = m_palette[m_gamePixels[i]]; } RenderGameSurface(); } void Display::RenderGameSurface() { - if (!m_fshouldRender) + if (!m_fShouldRender) return; - // Create the texture - texture = SDL_CreateTextureFromSurface(renderer, m_gameSurface); + // Update the texture + SDL_UpdateTexture(m_texture, NULL, m_gamePixels32, m_pitch32); - // Prepare the renderer - SDL_RenderClear(renderer); - SDL_RenderCopy(renderer, texture, NULL, NULL); + // Draw any sprites onto the texture + SDL_SetRenderTarget(m_renderer, m_texture); + s_psprm->DrawSprites(m_renderer, s_siz); + SDL_SetRenderTarget(m_renderer, NULL); - // Draw on any sprites - s_psprm->DrawSprites(renderer, s_siz); - - // Present the renderer - SDL_RenderPresent(renderer); - - // Free memory from the created texture - SDL_DestroyTexture(texture); + // Present the renderer to the screen + SDL_RenderClear(m_renderer); + SDL_RenderCopy(m_renderer, m_texture, NULL, NULL); + SDL_RenderPresent(m_renderer); } void Display::ResetScrollOffset() @@ -329,7 +342,7 @@ float Display::Density() { } void Display::SetShouldRender(bool fsr) { - m_fshouldRender = fsr; + m_fShouldRender = fsr; } } // namespace wi diff --git a/game/sdl/host.cpp b/game/sdl/host.cpp index d138063..29904b9 100644 --- a/game/sdl/host.cpp +++ b/game/sdl/host.cpp @@ -454,6 +454,11 @@ bool ProcessSdlEvent(base::Message *pmsg, Event *pevt) pevt->eType = appStopEvent; break; + case SDL_WINDOWEVENT: + gpmfrmm->DrawFrame(true); + gpdisp->RenderGameSurface(); + break; + default: return false; } diff --git a/game/sdl/htplatform.h b/game/sdl/htplatform.h index d896b1b..796dc7f 100644 --- a/game/sdl/htplatform.h +++ b/game/sdl/htplatform.h @@ -137,17 +137,18 @@ private: DibBitmap *m_pbmFront; DibBitmap *m_pbmClip; - SDL_Window *window; - SDL_Renderer *renderer; - SDL_Texture *texture; + SDL_Window *m_window; + SDL_Renderer *m_renderer; + SDL_Texture *m_texture; - byte *m_gameDisplay; - SDL_Surface *m_gameSurface; - Uint32 *m_gameSurfacePixels; - Uint32 m_32bppColors[256]; + byte *m_gamePixels; + Uint32 *m_gamePixels32; + Uint32 m_palette[256]; + int m_pitch32; int m_pixelCount; + float m_density; - bool m_fshouldRender; + bool m_fShouldRender; }; #define kfDtClearLine 1 diff --git a/game/sdl/sdlselectionsprite.cpp b/game/sdl/sdlselectionsprite.cpp index c62ab3d..dfa74c7 100644 --- a/game/sdl/sdlselectionsprite.cpp +++ b/game/sdl/sdlselectionsprite.cpp @@ -1,5 +1,8 @@ #include "game/sdl/sdlselectionsprite.h" +#define GRABBIE_SIZE 10 +#define GRABBIE_SIZE_HALF GRABBIE_SIZE/2 + namespace wi { SdlSelectionSprite::SdlSelectionSprite(SpriteManager *psprm) { @@ -41,27 +44,21 @@ void SdlSelectionSprite::Draw(void *pv, Size *psiz) { DPoint apt[4]; drc_.GetPoints(apt); - float density = gpdisp->Density(); - #define renderer (SDL_Renderer *)pv SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); for (int i = 0; i < ARRAYSIZE(apt); i++) { int next = i + 1 == ARRAYSIZE(apt) ? 0 : i + 1; - // x/y points for point a/b of the selection sprite line - int x1 = roundf(apt[i].y * density); - int y1 = roundf(apt[i].x * density); - int x2 = roundf(apt[next].y * density); - int y2 = roundf(apt[next].x * density); + // x/y are swapped + Point pt1 = {apt[i].y, apt[i].x}; + Point pt2 = {apt[next].y, apt[next].x}; // draw the selection sprite line - SDL_RenderDrawLine(renderer, x1, y1, x2, y2); - - int gs = 20; // grabbie size - int gsh = gs / 2; // grabbie size half + SDL_RenderDrawLine(renderer, pt1.x, pt1.y, pt2.x, pt2.y); // create and draw a grabbie rect - SDL_Rect rect = {x1 - gsh, y1 - gsh , gs, gs}; + SDL_Rect rect = {pt1.x - GRABBIE_SIZE_HALF, pt1.y - GRABBIE_SIZE_HALF, + GRABBIE_SIZE, GRABBIE_SIZE}; SDL_RenderFillRect(renderer, &rect); } diff --git a/game/sdl/sdlspritemgr.cpp b/game/sdl/sdlspritemgr.cpp index 29cf5c1..0a8e57d 100644 --- a/game/sdl/sdlspritemgr.cpp +++ b/game/sdl/sdlspritemgr.cpp @@ -8,6 +8,8 @@ SdlSpriteManager::SdlSpriteManager() { pcrit_ = new base::CriticalSection(); cpspr_ = 0; fSpriteDirty_ = false; + memset(&rcClip1_, 0, sizeof(rcClip1_)); + memset(&rcClip2_, 0, sizeof(rcClip2_)); } SdlSpriteManager::~SdlSpriteManager() { @@ -64,8 +66,28 @@ void SdlSpriteManager::DrawSprites(SDL_Renderer *renderer, Size siz) { } for (int i = 0; i < cpspr_; i++) { + // Draw clipped to rcClip1 + SDL_RenderSetClipRect(renderer, &rcClip1_); + apspr_[i]->Draw(renderer, &siz); + + // Draw clipped to rcClip2 + SDL_RenderSetClipRect(renderer, &rcClip2_); apspr_[i]->Draw(renderer, &siz); } + + SDL_RenderSetClipRect(renderer, NULL); +} + +void SdlSpriteManager::SetClipRects(wi::Rect *prc1, wi::Rect *prc2) { + rcClip1_.x = prc1->left; + rcClip1_.y = prc1->top; + rcClip1_.w = prc1->Width(); + rcClip1_.h = prc1->Height(); + + rcClip2_.x = prc2->left; + rcClip2_.y = prc2->top; + rcClip2_.w = prc2->Width(); + rcClip2_.h = prc2->Height(); } diff --git a/game/sdl/sdlspritemgr.h b/game/sdl/sdlspritemgr.h index 710a83b..6b71cb4 100644 --- a/game/sdl/sdlspritemgr.h +++ b/game/sdl/sdlspritemgr.h @@ -11,10 +11,7 @@ public: SdlSpriteManager(); ~SdlSpriteManager(); - virtual void SetClipRects(wi::Rect *prc1, wi::Rect *prc2) { - LOG() << "SdlSpriteManager::SetClipRects not implemented yet"; - return; - } + virtual void SetClipRects(wi::Rect *prc1, wi::Rect *prc2); virtual wi::AnimSprite *CreateAnimSprite() { LOG() << "SdlSpriteManager::CreateAnimSprite not implemented yet"; return NULL; @@ -32,6 +29,8 @@ private: int cpspr_; wi::Sprite *apspr_[16]; bool fSpriteDirty_; + SDL_Rect rcClip1_; + SDL_Rect rcClip2_; }; } // namespace wi