Skip to content

Commit fb1d436

Browse files
committed
1 parent 1246b87 commit fb1d436

11 files changed

+246
-93
lines changed

Main/include/Application.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ class Application
136136
Map<String, CachedJacketImage*> m_jacketImages;
137137
String m_lastMapPath;
138138
Thread m_updateThread;
139+
Thread m_fontBakeThread;
139140
class Beatmap* m_currentMap = nullptr;
140141
SkinHttp m_skinHttp;
141142
SkinIR m_skinIR;

Main/include/ChatOverlay.hpp

+4-9
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,28 @@
44
#include "Application.hpp"
55
#include "Input.hpp"
66
#include "GameConfig.hpp"
7+
#include "GuiUtils.hpp"
78

89
class MultiplayerScreen;
910

1011
// TODO(itszn) inherit BasicNuklearGui to reduce duplciated code
11-
class ChatOverlay: public IApplicationTickable
12+
class ChatOverlay: public BasicNuklearGui
1213
{
1314
public:
14-
ChatOverlay(MultiplayerScreen* m) : m_multi(m), m_nctx(), m_eventQueue() {};
15+
ChatOverlay(MultiplayerScreen* m) : m_multi(m) {};
1516
~ChatOverlay();
1617

1718
bool Init() override;
1819
void Tick(float deltaTime) override;
1920
void Render(float deltaTime) override;
20-
void NKRender();
21+
2122
void UpdateNuklearInput(SDL_Event evt);
2223
void SendChatMessage(const String& message);
2324
void AddMessage(const String& message);
2425
void AddMessage(const String& message, int r, int g, int b);
2526
bool OnKeyPressedConsume(SDL_Scancode key);
2627
void OpenChat();
2728
void CloseChat();
28-
void ShutdownNuklear();
29-
void InitNuklearIfNeeded();
3029
bool IsOpen() {
3130
return m_isOpen;
3231
}
@@ -43,11 +42,7 @@ class ChatOverlay: public IApplicationTickable
4342
void m_drawWindow();
4443
void m_drawChatAlert();
4544

46-
bool m_nuklearRunning = false;
47-
4845
MultiplayerScreen* m_multi = NULL;
49-
struct nk_context* m_nctx = NULL;
50-
std::queue<SDL_Event> m_eventQueue;
5146

5247
char m_chatDraft[512] = {0};
5348
bool m_isOpen = false;

Main/include/GameConfig.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@ DefineEnum(GameConfigKeys,
181181
SettingsLastTab,
182182
TransferScoresOnChartUpdate,
183183

184+
KeepFontTexture,
185+
184186
CurrentProfileName,
185187

186188
// Gameplay options

Main/include/GuiUtils.hpp

+14-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "ApplicationTickable.hpp"
33
#include "GameConfig.hpp"
44
#include "Input.hpp"
5+
#include "Shared/Thread.hpp"
56

67
class BasicNuklearGui : public IApplicationTickable
78
{
@@ -17,6 +18,10 @@ class BasicNuklearGui : public IApplicationTickable
1718
void InitNuklearIfNeeded();
1819
virtual bool OnKeyPressedConsume(SDL_Scancode code) { return m_isOpen; };
1920

21+
static void StartFontInit();
22+
static void BakeFontWithLock();
23+
static void DestroyFont();
24+
2025
protected:
2126
bool m_nuklearRunning = false;
2227
struct nk_context* m_nctx = NULL;
@@ -29,8 +34,16 @@ class BasicNuklearGui : public IApplicationTickable
2934
Mesh m_bgMesh;
3035

3136
private:
37+
static Mutex s_mutex;
38+
static nk_font_atlas* s_atlas;
39+
static nk_font* s_font;
40+
static GLuint s_fontTexture;
41+
static bool s_hasFontTexture;
42+
static int s_fontImageWidth;
43+
static int s_fontImageHeight;
3244
void InitNuklearFontAtlas();
33-
void InitNuklearFontAtlasFallback(struct nk_font_atlas* atlas, float fontSize);
45+
static void BakeFont();
46+
static void InitNuklearFontAtlasFallback(struct nk_font_atlas* atlas, float fontSize);
3447
};
3548

3649
class BasicWindow : public BasicNuklearGui

Main/src/Application.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <Graphics/ResourceManagers.hpp>
1010
#include <Shared/Profiling.hpp>
1111
#include "GameConfig.hpp"
12+
#include "GuiUtils.hpp"
1213
#include "Input.hpp"
1314
#include "TransitionScreen.hpp"
1415
#include "SkinConfig.hpp"
@@ -1010,6 +1011,11 @@ bool Application::m_Init()
10101011
g_transition = TransitionScreen::Create();
10111012
}
10121013

1014+
if (g_gameConfig.GetBool(GameConfigKeys::KeepFontTexture)) {
1015+
BasicNuklearGui::StartFontInit();
1016+
m_fontBakeThread = Thread(BasicNuklearGui::BakeFontWithLock);
1017+
}
1018+
10131019
///TODO: check if directory exists already?
10141020
Path::CreateDir(Path::Absolute("screenshots"));
10151021
Path::CreateDir(Path::Absolute("songs"));
@@ -1311,6 +1317,9 @@ void Application::m_Cleanup()
13111317
if (m_updateThread.joinable())
13121318
m_updateThread.join();
13131319

1320+
if (m_fontBakeThread.joinable())
1321+
m_fontBakeThread.join();
1322+
13141323
// Finally, save config
13151324
m_SaveConfig();
13161325
}

Main/src/ChatOverlay.cpp

+5-74
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,11 @@ void ChatOverlay::UpdateNuklearInput(SDL_Event evt)
1717
m_eventQueue.push(evt);
1818
}
1919

20-
void ChatOverlay::ShutdownNuklear()
21-
{
22-
if (!m_nuklearRunning)
23-
return;
24-
25-
g_gameWindow->OnAnyEvent.RemoveAll(this);
26-
nk_sdl_shutdown();
27-
28-
m_nuklearRunning = false;
29-
}
30-
31-
3220
bool ChatOverlay::Init()
3321
{
34-
InitNuklearIfNeeded();
22+
m_backgroundFrame = false;
23+
24+
BasicNuklearGui::Init();
3525

3626
// Init the socket callbacks
3727
m_multi->GetTCP().SetTopicHandler("server.chat.received", this, &ChatOverlay::m_handleChatReceived);
@@ -40,62 +30,9 @@ bool ChatOverlay::Init()
4030
return true;
4131
}
4232

43-
void ChatOverlay::InitNuklearIfNeeded()
44-
{
45-
if (m_nuklearRunning) {
46-
return;
47-
}
48-
m_nctx = nk_sdl_init((SDL_Window*)g_gameWindow->Handle());
49-
50-
g_gameWindow->OnAnyEvent.Add(this, &ChatOverlay::UpdateNuklearInput);
51-
{
52-
struct nk_font_atlas *atlas;
53-
nk_sdl_font_stash_begin(&atlas);
54-
struct nk_font *fallback = nk_font_atlas_add_from_file(atlas, Path::Normalize( Path::Absolute("fonts/settings/NotoSans-Regular.ttf")).c_str(), 24, 0);
55-
56-
NK_STORAGE const nk_rune cjk_ranges[] = {
57-
0x0E3F, 0xFFFF,
58-
0
59-
};
60-
61-
struct nk_font_config cfg_cjk = nk_font_config(24);
62-
cfg_cjk.merge_mode = nk_true;
63-
cfg_cjk.range = cjk_ranges;
64-
65-
int maxSize;
66-
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
67-
Logf("System max texture size: %d", Logger::Severity::Info, maxSize);
68-
if (maxSize >= FULL_FONT_TEXTURE_HEIGHT && !g_gameConfig.GetBool(GameConfigKeys::LimitSettingsFont))
69-
{
70-
nk_font_atlas_add_from_file(atlas, Path::Normalize(Path::Absolute("fonts/settings/DroidSansFallback.ttf")).c_str(), 24, &cfg_cjk);
71-
}
72-
73-
usc_nk_sdl_font_stash_end();
74-
nk_font_atlas_cleanup(atlas);
75-
nk_style_set_font(m_nctx, &fallback->handle);
76-
}
77-
78-
m_nctx->style.text.color = nk_rgb(255, 255, 255);
79-
m_nctx->style.button.border_color = nk_rgb(0, 128, 255);
80-
m_nctx->style.button.padding = nk_vec2(5,5);
81-
m_nctx->style.button.rounding = 0;
82-
m_nctx->style.window.fixed_background = nk_style_item_color(nk_rgb(40, 40, 40));
83-
m_nctx->style.slider.bar_normal = nk_rgb(20, 20, 20);
84-
m_nctx->style.slider.bar_hover = nk_rgb(20, 20, 20);
85-
m_nctx->style.slider.bar_active = nk_rgb(20, 20, 20);
86-
87-
m_nuklearRunning = true;
88-
}
89-
9033
void ChatOverlay::Tick(float deltatime)
9134
{
92-
nk_input_begin(m_nctx);
93-
while (!m_eventQueue.empty())
94-
{
95-
nk_sdl_handle_event(&m_eventQueue.front());
96-
m_eventQueue.pop();
97-
}
98-
nk_input_end(m_nctx);
35+
BasicNuklearGui::Tick(deltatime);
9936

10037
if (m_isOpen && nk_window_find(m_nctx, "Multiplayer Chat") &&
10138
nk_window_is_closed(m_nctx, "Multiplayer Chat"))
@@ -104,11 +41,6 @@ void ChatOverlay::Tick(float deltatime)
10441
}
10542
}
10643

107-
void ChatOverlay::NKRender()
108-
{
109-
nk_sdl_render(NK_ANTI_ALIASING_ON, MAX_VERTEX_MEMORY, MAX_ELEMENT_MEMORY);
110-
}
111-
11244
void ChatOverlay::m_drawChatAlert()
11345
{
11446
// Don't add alert if we can't open chat
@@ -271,8 +203,7 @@ void ChatOverlay::Render(float deltatime)
271203
m_drawChatAlert();
272204
}
273205

274-
g_application->ForceRender();
275-
NKRender();
206+
BasicNuklearGui::Render(deltatime);
276207
}
277208

278209
void ChatOverlay::CloseChat()

Main/src/GameConfig.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,12 @@ void GameConfig::InitDefaults()
233233

234234
Set(GameConfigKeys::CurrentProfileName, "Main");
235235
Set(GameConfigKeys::UpdateChannel, "master");
236+
237+
#ifndef EMBEDDED
238+
Set(GameConfigKeys::KeepFontTexture, true);
239+
#else
240+
Set(GameConfigKeys::KeepFontTexture, false);
241+
#endif
236242
}
237243

238244
void GameConfig::UpdateVersion()

Main/src/GuiUtils.cpp

+83-9
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,14 @@ void BasicNuklearGui::ShutdownNuklear()
2020
return;
2121

2222
g_gameWindow->OnAnyEvent.RemoveAll(this);
23-
nk_sdl_shutdown();
23+
nk_sdl_shutdown_keep_font();
24+
25+
if (!g_gameConfig.GetBool(GameConfigKeys::KeepFontTexture))
26+
{
27+
glDeleteTextures(1, &s_fontTexture);
28+
s_fontTexture = 0;
29+
s_hasFontTexture = false;
30+
}
2431

2532
m_nuklearRunning = false;
2633
}
@@ -69,26 +76,93 @@ static void ExtendFontAtlas(struct nk_font_atlas* atlas, const std::string_view&
6976
nk_font_atlas_add_from_file(atlas, fontPath.data(), pixelHeight, &cfg);
7077
}
7178

72-
void BasicNuklearGui::InitNuklearFontAtlas()
79+
Mutex BasicNuklearGui::s_mutex;
80+
nk_font_atlas* BasicNuklearGui::s_atlas = nullptr;
81+
nk_font* BasicNuklearGui::s_font = nullptr;
82+
GLuint BasicNuklearGui::s_fontTexture = 0;
83+
bool BasicNuklearGui::s_hasFontTexture = false;
84+
85+
void BasicNuklearGui::StartFontInit()
7386
{
7487
// This font should cover latin and cyrillic fonts.
7588
const String defaultFontPath = Path::Normalize(Path::Absolute("fonts/settings/NotoSans-Regular.ttf"));
7689
const float fontSize = 24.f;
7790

78-
struct nk_font_atlas* atlas;
79-
nk_sdl_font_stash_begin(&atlas);
91+
s_atlas = new nk_font_atlas();
92+
nk_atlas_font_stash_begin(s_atlas);
8093

81-
struct nk_font* font = nk_font_atlas_add_from_file(atlas, defaultFontPath.data(), fontSize, 0);
94+
struct nk_font* font = nk_font_atlas_add_from_file(s_atlas, defaultFontPath.data(), fontSize, 0);
8295

8396
if (!g_gameConfig.GetBool(GameConfigKeys::LimitSettingsFont))
8497
{
85-
InitNuklearFontAtlasFallback(atlas, fontSize);
98+
InitNuklearFontAtlasFallback(s_atlas, fontSize);
8699
}
100+
s_font = font;
101+
}
102+
103+
int BasicNuklearGui::s_fontImageWidth = 0;
104+
int BasicNuklearGui::s_fontImageHeight = 0;
105+
106+
void BasicNuklearGui::BakeFontWithLock()
107+
{
108+
BasicNuklearGui::s_mutex.lock();
109+
BakeFont();
110+
BasicNuklearGui::s_mutex.unlock();
111+
}
112+
113+
void BasicNuklearGui::BakeFont()
114+
{
115+
if (s_atlas->pixel || s_hasFontTexture)
116+
return;
117+
usc_nk_bake_atlas(s_atlas, s_fontImageWidth, s_fontImageHeight);
118+
}
87119

88-
usc_nk_sdl_font_stash_end();
89-
nk_font_atlas_cleanup(atlas);
120+
void BasicNuklearGui::DestroyFont()
121+
{
122+
if (s_hasFontTexture)
123+
{
124+
glDeleteTextures(1, &s_fontTexture);
125+
s_hasFontTexture = false;
126+
}
127+
if (s_atlas)
128+
{
129+
nk_font_atlas_clear(s_atlas);
130+
delete s_atlas;
131+
s_atlas = nullptr;
132+
s_font = nullptr;
133+
}
134+
}
135+
136+
void BasicNuklearGui::InitNuklearFontAtlas()
137+
{
138+
BasicNuklearGui::s_mutex.lock();
139+
if (s_atlas == nullptr)
140+
{
141+
StartFontInit();
142+
}
143+
144+
assert(s_atlas);
145+
if (!s_hasFontTexture && s_atlas->pixel == nullptr)
146+
{
147+
// Our thread didn't work
148+
Log("Baking nuklear font on main thread", Logger::Severity::Warning);
149+
BakeFont();
150+
}
151+
152+
if (!s_hasFontTexture)
153+
{
154+
// Also assigns the atlas to the current sdl
155+
s_fontTexture = usc_nk_sdl_generate_texture(s_atlas, s_atlas->pixel, s_fontImageWidth, s_fontImageHeight);
156+
s_hasFontTexture = true;
157+
}
158+
else
159+
{
160+
usc_nk_sdl_use_atlas(s_atlas, s_fontTexture);
161+
}
162+
BasicNuklearGui::s_mutex.unlock();
90163

91-
nk_style_set_font(m_nctx, &font->handle);
164+
assert(s_font);
165+
nk_style_set_font(m_nctx, &s_font->handle);
92166
}
93167

94168
void BasicNuklearGui::InitNuklearFontAtlasFallback(struct nk_font_atlas* atlas, float fontSize)

Main/src/SettingsScreen.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,7 @@ class SettingsPage_System : public SettingsPage
714714
SelectionSetting(GameConfigKeys::AntiAliasing, m_aaModes, "Anti-aliasing (requires restart):");
715715
SetApply(ToggleSetting(GameConfigKeys::VSync, "VSync"));
716716
SetApply(ToggleSetting(GameConfigKeys::ShowFps, "Show FPS"));
717+
SetApply(ToggleSetting(GameConfigKeys::KeepFontTexture, "Save font texture (settings load faster but uses more memory)"));
717718

718719
SectionHeader("Update");
719720

0 commit comments

Comments
 (0)