diff --git a/src/blupi.cxx b/src/blupi.cxx index e450b56..9ecdc61 100644 --- a/src/blupi.cxx +++ b/src/blupi.cxx @@ -779,8 +779,16 @@ DoInit (int argc, char * argv[], bool & exit) info.max_texture_height); } + // Create the event manager. + g_pEvent = new CEvent; + if (g_pEvent == nullptr) + { + InitFail ("New event"); + return EXIT_FAILURE; + } + // Create the main pixmap. - g_pPixmap = new CPixmap; + g_pPixmap = new CPixmap (g_pEvent); if (g_pPixmap == nullptr) { InitFail ("New pixmap"); @@ -994,27 +1002,18 @@ DoInit (int argc, char * argv[], bool & exit) g_pDecor->Create (g_pSound, g_pPixmap); g_pDecor->MapInitColors (); - // Create the event manager. - g_pEvent = new CEvent; - if (g_pEvent == nullptr) - { - InitFail ("New event"); - return EXIT_FAILURE; - } - const bool zoom = g_zoom; g_pEvent->Create (g_pPixmap, g_pDecor, g_pSound, g_pMovie); // Load all cursors - g_pPixmap->LoadCursors (g_zoom); + g_pPixmap->LoadCursors (); g_pPixmap->ChangeSprite (SPRITE_WAIT); g_updateThread = new std::thread (CheckForUpdates); - if (g_bFullScreen) - g_pEvent->SetFullScreen (true); - if (!g_bFullScreen && zoom != g_zoom) + if (zoom != g_zoom) g_pEvent->SetWindowSize (g_zoom); + g_pEvent->SetFullScreen (g_bFullScreen); g_pEvent->ChangePhase (EV_PHASE_INTRO1); g_bTermInit = true; diff --git a/src/def.h b/src/def.h index 52409ba..e988620 100644 --- a/src/def.h +++ b/src/def.h @@ -25,7 +25,9 @@ // clang-format off #define _INTRO true // true for init screen -#define SCRFACTOR 16 / 9 +#define SCRNUM 16 +#define SCRDEN 9 +#define SCRFACTOR SCRNUM / SCRDEN #define LXLOGIC 640 #define LYLOGIC 480 #define LXIMAGE (LYLOGIC * SCRFACTOR + (LYLOGIC * SCRFACTOR) % 2) // window size diff --git a/src/event.cxx b/src/event.cxx index 8a8a36b..510bfef 100644 --- a/src/event.cxx +++ b/src/event.cxx @@ -1697,6 +1697,12 @@ CEvent::~CEvent () WriteInfo (); // lit le fichier "info.blp" } +bool +CEvent::IsDemoPlaying () +{ + return this->m_bDemoPlay; +} + // Retourne la position de la souris. Point @@ -1717,14 +1723,6 @@ CEvent::GetMousePos () void CEvent::SetFullScreen (bool bFullScreen) { - int x, y; - SDL_GetMouseState (&x, &y); - x /= g_zoom; - y /= g_zoom; - - g_zoom = 1; - SDL_SetWindowSize (g_window, LXIMAGE, LYIMAGE); - g_bFullScreen = bFullScreen; int displayIndex = 0; @@ -1732,7 +1730,7 @@ CEvent::SetFullScreen (bool bFullScreen) displayIndex = SDL_GetWindowDisplayIndex (g_window); #endif /* _WIN32 */ - if (g_bFullScreen) + if (g_bFullScreen && g_zoom == 2) { int displays = SDL_GetNumVideoDisplays (); @@ -1750,7 +1748,10 @@ CEvent::SetFullScreen (bool bFullScreen) g_window, displayBounds[displayIndex].x, displayBounds[displayIndex].y); } - SDL_SetWindowFullscreen (g_window, bFullScreen ? SDL_WINDOW_FULLSCREEN : 0); + SDL_SetWindowFullscreen ( + g_window, bFullScreen ? (g_zoom == 1 ? SDL_WINDOW_FULLSCREEN_DESKTOP + : SDL_WINDOW_FULLSCREEN) + : 0); SDL_SetWindowBordered (g_window, bFullScreen ? SDL_FALSE : SDL_TRUE); SDL_SetWindowGrab (g_window, bFullScreen ? SDL_TRUE : SDL_FALSE); @@ -1759,17 +1760,14 @@ CEvent::SetFullScreen (bool bFullScreen) g_window, SDL_WINDOWPOS_CENTERED_DISPLAY (displayIndex), SDL_WINDOWPOS_CENTERED_DISPLAY (displayIndex)); - m_pPixmap->LoadCursors (g_zoom); + m_pPixmap->LoadCursors (); - /* Force this update before otherwise the coordinates retrieved with - * the Warp SDL function are corresponding to the previous size. - */ - CEvent::PushUserEvent (EV_UPDATE); - - auto coord = new SDL_Point; // Released by the event handler. - coord->x = x; - coord->y = y; - CEvent::PushUserEvent (EV_WARPMOUSE, coord); + if (g_bFullScreen) + { + Sint32 w, h; + SDL_GetWindowSize (g_window, &w, &h); + SDL_WarpMouseGlobal (w / 2, h / 2); + } } /** @@ -1810,6 +1808,9 @@ CEvent::SetWindowSize (Uint8 prevScale, Uint8 newScale) int x, y; SDL_GetMouseState (&x, &y); + if (g_bFullScreen && newScale == 2) + newScale = 1; + SDL_SetWindowSize (g_window, LXIMAGE * newScale, LYIMAGE * newScale); int displayIndex = SDL_GetWindowDisplayIndex (g_window); @@ -1817,7 +1818,10 @@ CEvent::SetWindowSize (Uint8 prevScale, Uint8 newScale) g_window, SDL_WINDOWPOS_CENTERED_DISPLAY (displayIndex), SDL_WINDOWPOS_CENTERED_DISPLAY (displayIndex)); - m_pPixmap->LoadCursors (newScale); + m_pPixmap->LoadCursors (); + + if (prevScale == newScale) + return; /* Force this update before otherwise the coordinates retrieved with * the Warp SDL function are corresponding to the previous size. @@ -2178,8 +2182,8 @@ CEvent::DrawButtons () SetEnable (EV_BUTTON3, !g_bFullScreen); SetEnable (EV_BUTTON4, g_bFullScreen); - SetEnable (EV_BUTTON5, !g_bFullScreen && g_zoom > 1); - SetEnable (EV_BUTTON6, !g_bFullScreen && g_zoom < 2); + SetEnable (EV_BUTTON5, g_zoom > 1); + SetEnable (EV_BUTTON6, g_zoom < 2); SetEnable (EV_BUTTON7, g_restoreMidi && mid && ogg); SetEnable (EV_BUTTON8, !g_restoreMidi && mid && ogg); @@ -4233,10 +4237,16 @@ CEvent::ChangeButtons (Sint32 message) SetLanguage (); break; case EV_BUTTON3: + { + auto zoom = g_zoom; + g_zoom = 1; SetFullScreen (true); + SetWindowSize (zoom, 1); break; + } case EV_BUTTON4: SetFullScreen (false); + SetWindowSize (g_zoom, g_zoom); break; case EV_BUTTON5: { @@ -4244,6 +4254,7 @@ CEvent::ChangeButtons (Sint32 message) if (g_zoom > 1) --g_zoom; SetWindowSize (scale, g_zoom); + SetFullScreen (g_bFullScreen); break; } case EV_BUTTON6: @@ -4252,6 +4263,7 @@ CEvent::ChangeButtons (Sint32 message) if (g_zoom < 2) ++g_zoom; SetWindowSize (scale, g_zoom); + SetFullScreen (g_bFullScreen); break; } case EV_BUTTON7: @@ -5282,7 +5294,8 @@ CEvent::DemoStep () pos.y = event.motion.y; } - SDL_WarpMouseInWindow (g_window, pos.x * g_zoom, pos.y * g_zoom); + this->m_pPixmap->FromGameToDisplay (pos.x, pos.y); + SDL_WarpMouseInWindow (g_window, pos.x, pos.y); } if (m_pDemoBuffer) @@ -5334,6 +5347,7 @@ CEvent::DemoRecEvent (const SDL_Event & event) demoEvent.button = event.button.button; demoEvent.x = event.button.x; demoEvent.y = event.button.y; + this->m_pPixmap->FromDisplayToGame (demoEvent.x, demoEvent.y); break; case SDL_MOUSEMOTION: @@ -5341,6 +5355,7 @@ CEvent::DemoRecEvent (const SDL_Event & event) demoEvent.time = m_demoTime; demoEvent.x = event.motion.x; demoEvent.y = event.motion.y; + this->m_pPixmap->FromDisplayToGame (demoEvent.x, demoEvent.y); break; default: diff --git a/src/event.h b/src/event.h index d327df5..1f4b1cd 100644 --- a/src/event.h +++ b/src/event.h @@ -94,6 +94,7 @@ public: CEvent (); ~CEvent (); + bool IsDemoPlaying (); Point GetMousePos (); void Create (CPixmap * pPixmap, CDecor * pDecor, CSound * pSound, CMovie * pMovie); diff --git a/src/menu.cxx b/src/menu.cxx index 19a242a..53c7191 100644 --- a/src/menu.cxx +++ b/src/menu.cxx @@ -185,7 +185,9 @@ CMenu::Create ( pos = m_pos; pos.x += DIMBUTTONX / 2; pos.y += DIMBUTTONY / 2; - SDL_WarpMouseInWindow (g_window, pos.x * g_zoom, pos.y * g_zoom); + + this->m_pPixmap->FromGameToDisplay (pos.x, pos.y); + SDL_WarpMouseInWindow (g_window, pos.x, pos.y); } m_selRank = Detect (pos); diff --git a/src/pixmap.cxx b/src/pixmap.cxx index bc23cc8..2bd2aa4 100644 --- a/src/pixmap.cxx +++ b/src/pixmap.cxx @@ -33,6 +33,7 @@ #include "blupi.h" #include "def.h" +#include "event.h" #include "misc.h" #include "pixmap.h" @@ -40,7 +41,7 @@ // Constructeur. -CPixmap::CPixmap () +CPixmap::CPixmap (CEvent * event) { Sint32 i; @@ -56,6 +57,8 @@ CPixmap::CPixmap () m_lpSDLCursors[i] = nullptr; m_lpCurrentCursor = nullptr; + this->mainTexture = nullptr; + this->event = event; } // Destructeur. @@ -83,6 +86,9 @@ CPixmap::~CPixmap () if (m_lpSDLBlupi) SDL_FreeSurface (m_lpSDLBlupi); + + if (this->mainTexture) + SDL_DestroyTexture (this->mainTexture); } // Cr�e l'objet DirectDraw principal. @@ -118,8 +124,25 @@ CPixmap::BltFast (Sint32 dstCh, size_t srcCh, Rect dstR, Rect srcR) if (dstCh < 0) { + + if (!this->mainTexture && g_bFullScreen && g_zoom == 1) + { + SDL_SetHint (SDL_HINT_RENDER_SCALE_QUALITY, "best"); + this->mainTexture = SDL_CreateTexture ( + g_renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, LXIMAGE, + LYIMAGE); + SDL_SetHint (SDL_HINT_RENDER_SCALE_QUALITY, "nearest"); + } + else if (this->mainTexture && !(g_bFullScreen && g_zoom == 1)) + { + SDL_DestroyTexture (this->mainTexture); + this->mainTexture = nullptr; + } + + SDL_SetRenderTarget (g_renderer, this->mainTexture); res = SDL_RenderCopy ( g_renderer, m_SDLTextureInfo[srcCh].texture, &srcRect, &dstRect); + SDL_SetRenderTarget (g_renderer, nullptr); } else { @@ -711,6 +734,10 @@ bool CPixmap::Display () { m_bBackDisplayed = true; + + if (this->mainTexture) + SDL_RenderCopy (g_renderer, this->mainTexture, nullptr, nullptr); + SDL_RenderPresent (g_renderer); return true; } @@ -881,7 +908,7 @@ CPixmap::GetCursorRect (MouseSprites sprite) } void -CPixmap::LoadCursors (Uint8 scale) +CPixmap::LoadCursors () { Uint32 rmask, gmask, bmask, amask; @@ -899,6 +926,8 @@ on the endianness (byte order) of the machine */ amask = 0xff000000; #endif + auto scale = this->GetDisplayScale (); + for (int i = SPRITE_BEGIN; i <= SPRITE_END; ++i) { MouseSprites sprite = static_cast (i); @@ -929,3 +958,58 @@ CPixmap::ChangeSprite (MouseSprites sprite) SDL_SetCursor (m_lpSDLCursors[sprite - 1]); m_lpCurrentCursor = m_lpSDLCursors[sprite - 1]; } + +double +CPixmap::GetDisplayScale () +{ + // SDL_DisplayMode displayMode; + // SDL_GetWindowDisplayMode (g_window, &displayMode); + Sint32 w, h; + SDL_GetWindowSize (g_window, &w, &h); + return static_cast (h / LYIMAGE); +} + +void +CPixmap::FromDisplayToGame (Sint32 & x, Sint32 & y) +{ + if (this->event->IsDemoPlaying ()) + return; + + SDL_DisplayMode displayMode; + SDL_GetWindowDisplayMode (g_window, &displayMode); + + if ( + static_cast (displayMode.w) / displayMode.h == + static_cast (SCRNUM) / SCRDEN) + return; + + double w = displayMode.w, h = displayMode.h; + double ratio = w * SCRDEN / SCRNUM; + + x = (x - (w - ratio) / 2) / (ratio / LXIMAGE); + y = y / (h / LYIMAGE); +} + +void +CPixmap::FromGameToDisplay (Sint32 & x, Sint32 & y) +{ + Sint32 w, h; + SDL_GetWindowSize (g_window, &w, &h); + + double factor = 1; + + if (!g_bFullScreen) + factor = g_zoom; + + x *= factor; + y *= factor; + + if (static_cast (w) / h == static_cast (SCRNUM) / SCRDEN) + return; + + double _w = w, _h = h; + double ratio = w * SCRDEN / SCRNUM; + + x = x * ratio / LXIMAGE + (_w - ratio) / 2; + y = y * _h / LYIMAGE; +} diff --git a/src/pixmap.h b/src/pixmap.h index 7a67047..0b315fa 100644 --- a/src/pixmap.h +++ b/src/pixmap.h @@ -47,6 +47,8 @@ struct TextureInfo { } }; +class CEvent; + class CPixmap { public: @@ -55,7 +57,7 @@ public: EXPAND, }; - CPixmap (); + CPixmap (CEvent * event); ~CPixmap (); bool Create (Point dim); @@ -88,9 +90,14 @@ public: void SetMouseSprite (MouseSprites sprite); void MouseShow (bool bShow); - void LoadCursors (Uint8 scale); + void LoadCursors (); void ChangeSprite (MouseSprites sprite); +public: + double GetDisplayScale (); + void FromDisplayToGame (Sint32 & x, Sint32 & y); + void FromGameToDisplay (Sint32 & x, Sint32 & y); + protected: Sint32 BltFast (Sint32 dstCh, size_t srcCh, Rect dstR, Rect srcR); Sint32 BltFast (Sint32 chDst, size_t channel, Point dst, Rect rcRect); @@ -111,8 +118,11 @@ protected: MouseSprites m_mouseSprite; bool m_bBackDisplayed; + CEvent * event; + SDL_Cursor * m_lpCurrentCursor; SDL_Cursor * m_lpSDLCursors[MAXCURSORS]; SDL_Surface * m_lpSDLBlupi; + SDL_Texture * mainTexture; std::unordered_map m_SDLTextureInfo; };