Skip to content

Commit 517ffa5

Browse files
authored
Merge pull request #50 from morganchristiansson/gl2-backgrounds
OpenGL backgrounds (splash, menu, options) and cursor
2 parents 49ab5db + 1ba679b commit 517ffa5

14 files changed

Lines changed: 387 additions & 85 deletions

CGame.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "s25util/file_handle.h"
1414
#include <libsiedler2/ArchivItem_Ini.h>
1515
#include <libsiedler2/libsiedler2.h>
16+
#include <glad/glad.h>
1617
#include <boost/filesystem.hpp>
1718
#include <boost/nowide/cstdio.hpp>
1819
#include <boost/program_options.hpp>
@@ -43,6 +44,11 @@ CGame::CGame(Extent GameResolution_, bool fullscreen_)
4344

4445
CGame::~CGame()
4546
{
47+
if(glContext_)
48+
{
49+
SDL_GL_DeleteContext(glContext_);
50+
glContext_ = nullptr;
51+
}
4652
global::s2 = nullptr;
4753
}
4854

@@ -69,12 +75,15 @@ int CGame::Execute()
6975
return 0;
7076
}
7177

72-
void CGame::RenderPresent() const
78+
void CGame::RenderPresent()
7379
{
74-
SDL_UpdateTexture(displayTexture_.get(), nullptr, Surf_Display->pixels, Surf_Display->w * sizeof(Uint32));
75-
SDL_RenderClear(renderer_.get());
76-
SDL_RenderCopy(renderer_.get(), displayTexture_.get(), nullptr, nullptr);
77-
SDL_RenderPresent(renderer_.get());
80+
displayTexture_.upload(Surf_Display->pixels);
81+
displayTexture_.Draw(Rect(0, 0, GameResolution.x, GameResolution.y));
82+
83+
const auto& cursorImg = Cursor.clicked ? (Cursor.button.right ? cross_ : cursorClicked_) : cursor_;
84+
cursorImg.Draw(Cursor.pos);
85+
86+
SDL_GL_SwapWindow(window_.get());
7887
}
7988

8089
CMenu* CGame::RegisterMenu(std::unique_ptr<CMenu> Menu)

CGame.h

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "CIO/CFont.h"
99
#include "SdlSurface.h"
10+
#include "Texture.h"
1011
#include <boost/filesystem/path.hpp>
1112
#include <Point.h>
1213
#include <memory>
@@ -27,8 +28,8 @@ class CGame
2728
bool Running;
2829
bool showLoadScreen;
2930
SdlSurface Surf_Display;
30-
SdlTexture displayTexture_;
31-
SdlRenderer renderer_;
31+
Texture displayTexture_;
32+
SDL_GLContext glContext_ = nullptr;
3233
SdlWindow window_;
3334

3435
private:
@@ -43,7 +44,14 @@ class CGame
4344
CFont lastFps;
4445

4546
Uint32 lastFrameTime = 0;
46-
unsigned suppressResizeEvents_ = 0;
47+
Extent appliedResolution_ = Extent{0, 0}; ///< Last resolution we applied to the window/display
48+
bool appliedFullscreen_ = false; ///< Last fullscreen state we applied
49+
50+
// Textures for splash screen and cursor
51+
Texture splashBg_;
52+
Texture cursor_;
53+
Texture cursorClicked_;
54+
Texture cross_;
4755

4856
// structure for mouse cursor
4957
struct
@@ -67,9 +75,13 @@ class CGame
6775
std::unique_ptr<CMap> MapObj;
6876

6977
void SetAppIcon();
70-
void RecreateDisplayResources();
78+
void setGLViewport();
79+
bool CreateWindow();
7180

7281
public:
82+
// Apply current GameResolution and fullscreen settings to the window/display.
83+
void ApplyWindowChanges();
84+
7385
void LoadSettings();
7486
void SaveSettings() const;
7587

@@ -79,7 +91,6 @@ class CGame
7991
int Execute();
8092

8193
bool Init();
82-
bool ReCreateWindow();
8394
void UpdateDisplaySize(const Extent& newSize);
8495

8596
void EventHandling(SDL_Event* Event);
@@ -88,7 +99,7 @@ class CGame
8899

89100
void Render();
90101

91-
void RenderPresent() const;
102+
void RenderPresent();
92103

93104
CMenu* RegisterMenu(std::unique_ptr<CMenu> Menu);
94105
bool UnregisterMenu(CMenu* Menu);

CGame_Event.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ void CGame::EventHandling(SDL_Event* Event)
6868
if(Event->key.keysym.mod & KMOD_ALT)
6969
{
7070
fullscreen = !fullscreen;
71+
ApplyWindowChanges();
7172
SaveSettings();
7273
}
7374
break;
@@ -388,12 +389,16 @@ void CGame::EventHandling(SDL_Event* Event)
388389
{
389390
if(Event->window.event == SDL_WINDOWEVENT_RESIZED)
390391
{
391-
if(suppressResizeEvents_ > 0)
392-
{
393-
suppressResizeEvents_--;
394-
break; // Skip stale event from our own window recreation
395-
}
396-
UpdateDisplaySize(Extent(Event->window.data1, Event->window.data2));
392+
// In fullscreen the compositor (e.g. Wayland) may report a size
393+
// different from the one we requested. We already applied the
394+
// resolution ourselves, so don't let the event override it.
395+
if(fullscreen)
396+
break;
397+
const Extent newSize(Event->window.data1, Event->window.data2);
398+
// Ignore events matching the resolution we already applied.
399+
if(newSize == appliedResolution_)
400+
break;
401+
UpdateDisplaySize(newSize);
397402
}
398403
break;
399404
}

CGame_Init.cpp

Lines changed: 112 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,49 +8,131 @@
88
#include "CIO/CMenu.h"
99
#include "CIO/CWindow.h"
1010
#include "CMap.h"
11-
#include "CSurface.h"
1211
#include "callbacks.h"
1312
#include "globals.h"
1413
#include "lua/GameDataLoader.h"
14+
#include <glad/glad.h>
1515
#include <iostream>
16-
#include <vector>
1716

18-
bool CGame::ReCreateWindow()
17+
bool CGame::CreateWindow()
1918
{
20-
suppressResizeEvents_ = 3;
21-
displayTexture_.reset();
22-
renderer_.reset();
23-
window_.reset();
19+
if(window_)
20+
return false;
21+
2422
window_.reset(SDL_CreateWindow("Return to the Roots Map editor [BETA]", SDL_WINDOWPOS_CENTERED,
2523
SDL_WINDOWPOS_CENTERED, GameResolution.x, GameResolution.y,
26-
fullscreen ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_RESIZABLE));
24+
SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE));
2725
if(!window_)
2826
return false;
29-
renderer_.reset(SDL_CreateRenderer(window_.get(), -1, 0));
30-
if(!renderer_)
27+
28+
glContext_ = SDL_GL_CreateContext(window_.get());
29+
if(!glContext_ || !gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress))
3130
return false;
32-
RecreateDisplayResources();
33-
if(!displayTexture_ || !Surf_Display)
31+
32+
glEnable(GL_TEXTURE_2D);
33+
glEnable(GL_BLEND);
34+
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
35+
glDisable(GL_DEPTH_TEST);
36+
glClearColor(0, 0, 0, 1);
37+
38+
SDL_ShowWindow(window_.get());
39+
40+
ApplyWindowChanges();
41+
if(!displayTexture_.isValid() || !Surf_Display)
3442
return false;
3543

3644
SetAppIcon();
45+
3746
return true;
3847
}
3948

40-
void CGame::RecreateDisplayResources()
49+
void CGame::ApplyWindowChanges()
4150
{
42-
displayTexture_.reset();
43-
displayTexture_ = makeSdlTexture(renderer_, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, GameResolution.x,
44-
GameResolution.y);
45-
Surf_Display = makeRGBSurface(GameResolution.x, GameResolution.y, true);
51+
if(!window_)
52+
return;
53+
54+
if(fullscreen)
55+
{
56+
SDL_DisplayMode dm;
57+
SDL_zero(dm);
58+
dm.w = static_cast<int>(GameResolution.x);
59+
dm.h = static_cast<int>(GameResolution.y);
60+
dm.format = 0; // let SDL pick a supported format
61+
dm.refresh_rate = 0;
62+
if(SDL_SetWindowDisplayMode(window_.get(), &dm) != 0)
63+
{
64+
std::cerr << "SDL_SetWindowDisplayMode failed: " << SDL_GetError() << std::endl;
65+
return;
66+
}
67+
68+
const Uint32 flags = SDL_GetWindowFlags(window_.get());
69+
if(!(flags & SDL_WINDOW_FULLSCREEN))
70+
{
71+
if(SDL_SetWindowFullscreen(window_.get(), SDL_WINDOW_FULLSCREEN) != 0)
72+
{
73+
std::cerr << "SDL_SetWindowFullscreen failed: " << SDL_GetError() << std::endl;
74+
return;
75+
}
76+
} else if(GameResolution != appliedResolution_)
77+
{
78+
// Already fullscreen and the resolution changed. Toggle fullscreen off and
79+
// back on so SDL/Wayland actually applies the new display mode.
80+
if(SDL_SetWindowFullscreen(window_.get(), 0) != 0)
81+
{
82+
std::cerr << "SDL_SetWindowFullscreen(0) failed: " << SDL_GetError() << std::endl;
83+
return;
84+
}
85+
SDL_SetWindowSize(window_.get(), GameResolution.x, GameResolution.y);
86+
if(SDL_SetWindowFullscreen(window_.get(), SDL_WINDOW_FULLSCREEN) != 0)
87+
{
88+
std::cerr << "SDL_SetWindowFullscreen failed: " << SDL_GetError() << std::endl;
89+
return;
90+
}
91+
}
92+
} else
93+
{
94+
if(SDL_SetWindowFullscreen(window_.get(), 0) != 0)
95+
{
96+
std::cerr << "SDL_SetWindowFullscreen failed: " << SDL_GetError() << std::endl;
97+
return;
98+
}
99+
SDL_SetWindowSize(window_.get(), GameResolution.x, GameResolution.y);
100+
SDL_SetWindowPosition(window_.get(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
101+
}
102+
103+
UpdateDisplaySize(GameResolution);
104+
}
105+
106+
void CGame::setGLViewport()
107+
{
108+
if(!window_)
109+
return;
110+
int w = 0, h = 0;
111+
SDL_GL_GetDrawableSize(window_.get(), &w, &h);
112+
if(w == 0 || h == 0)
113+
return;
114+
glViewport(0, 0, w, h);
115+
glMatrixMode(GL_PROJECTION);
116+
glLoadIdentity();
117+
glOrtho(0, GameResolution.x, GameResolution.y, 0, -1, 1);
118+
glMatrixMode(GL_MODELVIEW);
119+
glLoadIdentity();
46120
}
47121

48122
void CGame::UpdateDisplaySize(const Extent& newSize)
49123
{
50124
GameResolution = newSize;
51-
RecreateDisplayResources();
125+
appliedResolution_ = GameResolution;
126+
appliedFullscreen_ = fullscreen;
127+
128+
Surf_Display = makeRGBSurface(GameResolution.x, GameResolution.y, true);
129+
displayTexture_.createEmpty(GameResolution);
130+
131+
setGLViewport();
52132
for(auto& menu : Menus)
133+
{
53134
menu->resetSurface();
135+
}
54136
for(auto& wnd : Windows)
55137
wnd->resetSurface();
56138
}
@@ -62,7 +144,7 @@ bool CGame::Init()
62144
SDL_ShowCursor(SDL_DISABLE);
63145

64146
std::cout << "Create Window...";
65-
if(!ReCreateWindow())
147+
if(!CreateWindow())
66148
{
67149
std::cout << "failure";
68150
return false;
@@ -94,10 +176,14 @@ bool CGame::Init()
94176
}
95177
}
96178

179+
// Create texture for splash background
180+
splashBg_.load(global::bmpArray[SPLASHSCREEN_LOADING_S2SCREEN].surface.get(), true);
181+
97182
// std::cout << "\nShow loading screen...";
98183
showLoadScreen = true;
99-
CSurface::DrawStretched(Surf_Display, global::bmpArray[SPLASHSCREEN_LOADING_S2SCREEN].surface);
100-
RenderPresent();
184+
glClear(GL_COLOR_BUFFER_BIT);
185+
splashBg_.Draw(Rect(0, 0, GameResolution.x, GameResolution.y));
186+
SDL_GL_SwapWindow(window_.get());
101187

102188
GameDataLoader gdLoader(global::worldDesc);
103189
if(!gdLoader.Load())
@@ -252,5 +338,10 @@ bool CGame::Init()
252338
// create the mainmenu
253339
callback::mainmenu(INITIALIZING_CALL);
254340

341+
// Create textures for cursor
342+
cursor_.load(global::bmpArray[CURSOR].surface.get());
343+
cursorClicked_.load(global::bmpArray[CURSOR_CLICKED].surface.get());
344+
cross_.load(global::bmpArray[CROSS].surface.get());
345+
255346
return true;
256347
}

CGame_Render.cpp

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "CMap.h"
1111
#include "CSurface.h"
1212
#include "globals.h"
13+
#include <glad/glad.h>
1314
#ifdef _WIN32
1415
# include "s25editResource.h"
1516
# ifndef WIN32_LEAN_AND_MEAN
@@ -38,18 +39,14 @@ void CGame::SetAppIcon()
3839

3940
void CGame::Render()
4041
{
41-
suppressResizeEvents_ = 0;
42-
if(Extent(Surf_Display->w, Surf_Display->h) != GameResolution
43-
|| fullscreen != ((SDL_GetWindowFlags(window_.get()) & SDL_WINDOW_FULLSCREEN) != 0))
44-
{
45-
ReCreateWindow();
46-
}
42+
glClear(GL_COLOR_BUFFER_BIT);
43+
SDL_FillRect(Surf_Display.get(), nullptr, SDL_MapRGBA(Surf_Display->format, 0, 0, 0, 0));
4744

4845
// if the S2 loading screen is shown, render only this until user clicks a mouse button
4946
if(showLoadScreen)
5047
{
51-
CSurface::DrawStretched(Surf_Display, global::bmpArray[SPLASHSCREEN_LOADING_S2SCREEN].surface);
52-
RenderPresent();
48+
splashBg_.Draw(Rect(0, 0, GameResolution.x, GameResolution.y));
49+
SDL_GL_SwapWindow(window_.get());
5350
return;
5451
}
5552

@@ -103,16 +100,6 @@ void CGame::Render()
103100
}
104101
}
105102

106-
// render mouse cursor
107-
if(Cursor.clicked)
108-
{
109-
if(Cursor.button.right)
110-
CSurface::Draw(Surf_Display, global::bmpArray[CROSS].surface, Cursor.pos);
111-
else
112-
CSurface::Draw(Surf_Display, global::bmpArray[CURSOR_CLICKED].surface, Cursor.pos);
113-
} else
114-
CSurface::Draw(Surf_Display, global::bmpArray[CURSOR].surface, Cursor.pos);
115-
116103
#ifdef _ADMINMODE
117104
FrameCounter++;
118105
#endif

CIO/CFile.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ bool CFile::read_bbm(FILE* fp)
291291
CHECK_READ(libendian::read(&(color.r), 1, fp));
292292
CHECK_READ(libendian::read(&(color.g), 1, fp));
293293
CHECK_READ(libendian::read(&(color.b), 1, fp));
294+
color.a = 255;
294295
}
295296

296297
palArray++;
@@ -1250,6 +1251,7 @@ bool CFile::read_bob05(FILE* fp)
12501251
CHECK_READ(libendian::read(&(color.r), 1, fp));
12511252
CHECK_READ(libendian::read(&(color.g), 1, fp));
12521253
CHECK_READ(libendian::read(&(color.b), 1, fp));
1254+
color.a = 255;
12531255
}
12541256

12551257
palArray++;

0 commit comments

Comments
 (0)