diff --git a/client/CMT.cpp b/client/CMT.cpp index 083494a35..72947e7c3 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -74,14 +74,13 @@ int preferredDriverIndex = -1; SDL_Window * mainWindow = nullptr; SDL_Renderer * mainRenderer = nullptr; SDL_Texture * screenTexture = nullptr; + #endif // VCMI_SDL1 SDL_Surface *screen = nullptr, //main screen surface *screen2 = nullptr,//and hlp surface (used to store not-active interfaces layer) *screenBuf = screen; //points to screen (if only advmapint is present) or screen2 (else) - should be used when updating controls which are not regularly redrawed -static boost::thread *mainGUIThread; - std::queue events; boost::mutex eventsM; @@ -95,7 +94,7 @@ void processCommand(const std::string &message); static void setScreenRes(int w, int h, int bpp, bool fullscreen, bool resetVideo=true); void dispose(); void playIntro(); -static void listenForEvents(); +static void mainLoop(); //void requestChangingResolution(); void startGame(StartInfo * options, CConnection *serv = nullptr); void endGame(); @@ -458,8 +457,7 @@ int main(int argc, char** argv) if(!gNoGUI) { - mainGUIThread = new boost::thread(&CGuiHandler::run, &GH); - listenForEvents(); + mainLoop(); } else { @@ -822,7 +820,7 @@ static bool checkVideoMode(int monitorIndex, int w, int h, int& bpp, bool fullsc #ifndef VCMI_SDL1 static bool recreateWindow(int w, int h, int bpp, bool fullscreen) { - // VCMI will only work with 2, 3 or 4 bytes per pixel + // VCMI will only work with 2 or 4 bytes per pixel vstd::amax(bpp, 16); vstd::amin(bpp, 32); if(bpp>16) @@ -905,6 +903,8 @@ static bool recreateWindow(int w, int h, int bpp, bool fullscreen) logGlobal->infoStream() << "Created renderer " << info.name; SDL_RenderSetLogicalSize(mainRenderer, w, h); + + SDL_RenderSetViewport(mainRenderer, nullptr); @@ -1082,83 +1082,97 @@ static void fullScreenChanged() GH.totalRedraw(); } -static void listenForEvents() +static void handleEvent(SDL_Event & ev) +{ + if((ev.type==SDL_QUIT) ||(ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4 && (ev.key.keysym.mod & KMOD_ALT))) + { + handleQuit(); + return; + } + + #ifdef VCMI_SDL1 + //FIXME: this should work even in pregame + else if(LOCPLINT && ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4) + #else + else if(ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4) + #endif // VCMI_SDL1 + { + Settings full = settings.write["video"]["fullscreen"]; + full->Bool() = !full->Bool(); + return; + } + else if(ev.type == SDL_USEREVENT) + { + switch(ev.user.code) + { + case RETURN_TO_MAIN_MENU: + { + endGame(); + GH.curInt = CGPreGame::create();; + GH.defActionsDef = 63; + } + break; + case STOP_CLIENT: + client->endGame(false); + break; + case RESTART_GAME: + { + StartInfo si = *client->getStartInfo(true); + endGame(); + startGame(&si); + } + break; + case PREPARE_RESTART_CAMPAIGN: + { + auto si = reinterpret_cast(ev.user.data1); + endGame(); + startGame(si); + } + break; + case RETURN_TO_MENU_LOAD: + endGame(); + CGPreGame::create(); + GH.defActionsDef = 63; + CGP->update(); + CGP->menu->switchToTab(vstd::find_pos(CGP->menu->menuNameToEntry, "load")); + GH.curInt = CGP; + break; + case FULLSCREEN_TOGGLED: + fullScreenChanged(); + break; + default: + logGlobal->errorStream() << "Error: unknown user event. Code " << ev.user.code; + break; + } + + return; + } + { + boost::unique_lock lock(eventsM); + events.push(ev); + } + +} + + +static void mainLoop() { SettingsListener resChanged = settings.listen["video"]["fullscreen"]; resChanged([](const JsonNode &newState){ CGuiHandler::pushSDLEvent(SDL_USEREVENT, FULLSCREEN_TOGGLED); }); + GH.mainFPSmng->init(); + while(1) //main SDL events loop { SDL_Event ev; - int ret = SDL_WaitEvent(&ev); - if (ret == 0 || (ev.type==SDL_QUIT) || - (ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4 && (ev.key.keysym.mod & KMOD_ALT))) + while(1 == SDL_PollEvent(&ev)) { - handleQuit(); - continue; + handleEvent(ev); } - #ifdef VCMI_SDL1 - //FIXME: this should work even in pregame - else if(LOCPLINT && ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4) - #else - else if(ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4) - #endif // VCMI_SDL1 - { - Settings full = settings.write["video"]["fullscreen"]; - full->Bool() = !full->Bool(); - continue; - } - else if(ev.type == SDL_USEREVENT) - { - switch(ev.user.code) - { - case RETURN_TO_MAIN_MENU: - { - endGame(); - GH.curInt = CGPreGame::create();; - GH.defActionsDef = 63; - } - break; - case STOP_CLIENT: - client->endGame(false); - break; - case RESTART_GAME: - { - StartInfo si = *client->getStartInfo(true); - endGame(); - startGame(&si); - } - break; - case PREPARE_RESTART_CAMPAIGN: - { - auto si = reinterpret_cast(ev.user.data1); - endGame(); - startGame(si); - } - break; - case RETURN_TO_MENU_LOAD: - endGame(); - CGPreGame::create(); - GH.defActionsDef = 63; - CGP->update(); - CGP->menu->switchToTab(vstd::find_pos(CGP->menu->menuNameToEntry, "load")); - GH.curInt = CGP; - break; - case FULLSCREEN_TOGGLED: - fullScreenChanged(); - break; - default: - logGlobal->errorStream() << "Error: unknown user event. Code " << ev.user.code; - assert(0); - } + + GH.renderFrame(); - continue; - } - { - boost::unique_lock lock(eventsM); - events.push(ev); - } } } @@ -1208,15 +1222,16 @@ void handleQuit() { auto quitApplication = []() { - if(client) client->endGame(); + if(client) + endGame(); - if(mainGUIThread) - { - GH.terminate = true; - if(mainGUIThread->get_id() != boost::this_thread::get_id()) mainGUIThread->join(); - delete mainGUIThread; - mainGUIThread = nullptr; - } +// if(mainGUIThread) +// { +// GH.terminate = true; +// if(mainGUIThread->get_id() != boost::this_thread::get_id()) mainGUIThread->join(); +// delete mainGUIThread; +// mainGUIThread = nullptr; +// } delete console; console = nullptr; boost::this_thread::sleep(boost::posix_time::milliseconds(750)); diff --git a/client/gui/CGuiHandler.cpp b/client/gui/CGuiHandler.cpp index 07873bd9c..765ce7a72 100644 --- a/client/gui/CGuiHandler.cpp +++ b/client/gui/CGuiHandler.cpp @@ -410,43 +410,25 @@ void CGuiHandler::fakeMouseMove() handleMouseMotion(&evnt); } -void CGuiHandler::run() +void CGuiHandler::renderFrame() { - setThreadName("CGuiHandler::run"); - inGuiThread.reset(new bool(true)); - try - { - if(settings["video"]["fullscreen"].Bool()) - CCS->curh->centerCursor(); - - mainFPSmng->init(); // resets internal clock, needed for FPS manager - while(!terminate) - { - { - //boost::unique_lock lock(*CPlayerInterface::pim); - if(curInt) - curInt->update(); // calls a update and drawing process of the loaded game interface object at the moment + if(!terminate) + { + if(curInt) + curInt->update(); // calls a update and drawing process of the loaded game interface object at the moment #ifndef VCMI_SDL1 + if(0 != SDL_RenderCopy(mainRenderer, screenTexture, nullptr, nullptr)) + logGlobal->errorStream() << __FUNCTION__ << " SDL_RenderCopy " << SDL_GetError(); - SDL_SetRenderDrawColor(mainRenderer, 0, 0, 0, 0); - SDL_RenderClear(mainRenderer); - SDL_RenderCopy(mainRenderer, screenTexture, NULL, NULL); - - SDL_RenderPresent(mainRenderer); - + SDL_RenderPresent(mainRenderer); #endif - } - mainFPSmng->framerateDelay(); // holds a constant FPS - } - } - catch(const std::exception & e) - { - logGlobal->errorStream() << "Error: " << e.what(); - exit(EXIT_FAILURE); - } + + mainFPSmng->framerateDelay(); // holds a constant FPS + } } + CGuiHandler::CGuiHandler() :lastClick(-500, -500) { diff --git a/client/gui/CGuiHandler.h b/client/gui/CGuiHandler.h index 273df7176..8697f9d1a 100644 --- a/client/gui/CGuiHandler.h +++ b/client/gui/CGuiHandler.h @@ -80,7 +80,8 @@ public: CGuiHandler(); ~CGuiHandler(); - void run(); // holds the main loop for the whole program after initialization and manages the update/rendering system + + void renderFrame(); void totalRedraw(); //forces total redraw (using showAll), sets a flag, method gets called at the end of the rendering void simpleRedraw(); //update only top interface and draw background from buffer, sets a flag, method gets called at the end of the rendering diff --git a/client/gui/SDL_Extensions.cpp b/client/gui/SDL_Extensions.cpp index eaafbe61e..eb1e20ab4 100644 --- a/client/gui/SDL_Extensions.cpp +++ b/client/gui/SDL_Extensions.cpp @@ -14,6 +14,21 @@ const SDL_Color Colors::WHITE = { 255, 243, 222, 0 }; const SDL_Color Colors::METALLIC_GOLD = { 173, 142, 66, 0 }; const SDL_Color Colors::GREEN = { 0, 255, 0, 0 }; +#if (SDL_MAJOR_VERSION == 2) +void SDL_UpdateRect(SDL_Surface *surface, int x, int y, int w, int h) +{ + Rect rect(x,y,w,h); + if(0 !=SDL_UpdateTexture(screenTexture, &rect, surface->pixels, surface->pitch)) + logGlobal->errorStream() << __FUNCTION__ << "SDL_UpdateTexture " << SDL_GetError(); + + SDL_RenderClear(mainRenderer); + if(0 != SDL_RenderCopy(mainRenderer, screenTexture, NULL, NULL)) + logGlobal->errorStream() << __FUNCTION__ << "SDL_RenderCopy " << SDL_GetError(); + SDL_RenderPresent(mainRenderer); + +} +#endif // VCMI_SDL1 + SDL_Surface * CSDL_Ext::newSurface(int w, int h, SDL_Surface * mod) //creates new surface, with flags/format same as in surface given { SDL_Surface * ret = SDL_CreateRGBSurface(mod->flags,w,h,mod->format->BitsPerPixel,mod->format->Rmask,mod->format->Gmask,mod->format->Bmask,mod->format->Amask); @@ -490,12 +505,19 @@ Uint32 CSDL_Ext::colorToUint32(const SDL_Color * color) void CSDL_Ext::update(SDL_Surface * what) { -// #ifdef VCMI_SDL1 -// if(what) - SDL_UpdateRect(what, 0, 0, what->w, what->h); -// #else -// SDL_UpdateTexture(screenTexture, NULL, what->pixels, what->pitch); -// #endif + #ifdef VCMI_SDL1 + if(what) + SDL_UpdateRect(what, 0, 0, what->w, what->h); + #else + Rect rect(0,0,what->w,what->h); + if(!what) + return; + if(0 !=SDL_UpdateTexture(screenTexture, &rect, what->pixels, what->pitch)) + logGlobal->errorStream() << __FUNCTION__ << "SDL_UpdateTexture " << SDL_GetError(); + #endif // VCMI_SDL1 + + + } void CSDL_Ext::drawBorder(SDL_Surface * sur, int x, int y, int w, int h, const int3 &color) { diff --git a/client/gui/SDL_Extensions.h b/client/gui/SDL_Extensions.h index 210b9084f..b6ea251c4 100644 --- a/client/gui/SDL_Extensions.h +++ b/client/gui/SDL_Extensions.h @@ -52,17 +52,7 @@ inline void SDL_WarpMouse(int x, int y) SDL_WarpMouseInWindow(mainWindow,x,y); } -inline void SDL_UpdateRect(SDL_Surface *surface, int x, int y, int w, int h) -{ - Rect rect(x,y,w,h); - SDL_UpdateTexture(screenTexture, &rect, surface->pixels, surface->pitch); - - SDL_RenderClear(mainRenderer); - SDL_RenderCopy(mainRenderer, screenTexture, NULL, NULL); - - SDL_RenderPresent(mainRenderer); - -} +void SDL_UpdateRect(SDL_Surface *surface, int x, int y, int w, int h); #endif inline bool isCtrlKeyDown()