Skip to content

Commit

Permalink
Merge pull request #490 from Drewol/feat/save-font
Browse files Browse the repository at this point in the history
Add option to save nuklear font texture between BasicNuklearGui instances
  • Loading branch information
itszn authored Jun 25, 2021
2 parents 17331e9 + 164309d commit 98e3d12
Show file tree
Hide file tree
Showing 12 changed files with 248 additions and 95 deletions.
1 change: 1 addition & 0 deletions Main/include/Application.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ class Application
Map<String, CachedJacketImage*> m_jacketImages;
String m_lastMapPath;
Thread m_updateThread;
Thread m_fontBakeThread;
class Beatmap* m_currentMap = nullptr;
SkinHttp m_skinHttp;
SkinIR m_skinIR;
Expand Down
13 changes: 4 additions & 9 deletions Main/include/ChatOverlay.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,28 @@
#include "Application.hpp"
#include "Input.hpp"
#include "GameConfig.hpp"
#include "GuiUtils.hpp"

class MultiplayerScreen;

// TODO(itszn) inherit BasicNuklearGui to reduce duplciated code
class ChatOverlay: public IApplicationTickable
class ChatOverlay: public BasicNuklearGui
{
public:
ChatOverlay(MultiplayerScreen* m) : m_multi(m), m_nctx(), m_eventQueue() {};
ChatOverlay(MultiplayerScreen* m) : m_multi(m) {};
~ChatOverlay();

bool Init() override;
void Tick(float deltaTime) override;
void Render(float deltaTime) override;
void NKRender();

void UpdateNuklearInput(SDL_Event evt);
void SendChatMessage(const String& message);
void AddMessage(const String& message);
void AddMessage(const String& message, int r, int g, int b);
bool OnKeyPressedConsume(SDL_Scancode key);
void OpenChat();
void CloseChat();
void ShutdownNuklear();
void InitNuklearIfNeeded();
bool IsOpen() {
return m_isOpen;
}
Expand All @@ -43,11 +42,7 @@ class ChatOverlay: public IApplicationTickable
void m_drawWindow();
void m_drawChatAlert();

bool m_nuklearRunning = false;

MultiplayerScreen* m_multi = NULL;
struct nk_context* m_nctx = NULL;
std::queue<SDL_Event> m_eventQueue;

char m_chatDraft[512] = {0};
bool m_isOpen = false;
Expand Down
2 changes: 2 additions & 0 deletions Main/include/GameConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,8 @@ DefineEnum(GameConfigKeys,
SettingsLastTab,
TransferScoresOnChartUpdate,

KeepFontTexture,

CurrentProfileName,

// Gameplay options
Expand Down
15 changes: 14 additions & 1 deletion Main/include/GuiUtils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "ApplicationTickable.hpp"
#include "GameConfig.hpp"
#include "Input.hpp"
#include "Shared/Thread.hpp"

class BasicNuklearGui : public IApplicationTickable
{
Expand All @@ -17,6 +18,10 @@ class BasicNuklearGui : public IApplicationTickable
void InitNuklearIfNeeded();
virtual bool OnKeyPressedConsume(SDL_Scancode code) { return m_isOpen; };

static void StartFontInit();
static void BakeFontWithLock();
static void DestroyFont();

protected:
bool m_nuklearRunning = false;
struct nk_context* m_nctx = NULL;
Expand All @@ -29,8 +34,16 @@ class BasicNuklearGui : public IApplicationTickable
Mesh m_bgMesh;

private:
static Mutex s_mutex;
static nk_font_atlas* s_atlas;
static nk_font* s_font;
static GLuint s_fontTexture;
static bool s_hasFontTexture;
static int s_fontImageWidth;
static int s_fontImageHeight;
void InitNuklearFontAtlas();
void InitNuklearFontAtlasFallback(struct nk_font_atlas* atlas, float fontSize);
static void BakeFont();
static void InitNuklearFontAtlasFallback(struct nk_font_atlas* atlas, float fontSize);
};

class BasicWindow : public BasicNuklearGui
Expand Down
9 changes: 9 additions & 0 deletions Main/src/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <Graphics/ResourceManagers.hpp>
#include <Shared/Profiling.hpp>
#include "GameConfig.hpp"
#include "GuiUtils.hpp"
#include "Input.hpp"
#include "TransitionScreen.hpp"
#include "SkinConfig.hpp"
Expand Down Expand Up @@ -1012,6 +1013,11 @@ bool Application::m_Init()
g_transition = TransitionScreen::Create();
}

if (g_gameConfig.GetBool(GameConfigKeys::KeepFontTexture)) {
BasicNuklearGui::StartFontInit();
m_fontBakeThread = Thread(BasicNuklearGui::BakeFontWithLock);
}

///TODO: check if directory exists already?
Path::CreateDir(Path::Absolute("screenshots"));
Path::CreateDir(Path::Absolute("songs"));
Expand Down Expand Up @@ -1313,6 +1319,9 @@ void Application::m_Cleanup()
if (m_updateThread.joinable())
m_updateThread.join();

if (m_fontBakeThread.joinable())
m_fontBakeThread.join();

// Finally, save config
m_SaveConfig();
}
Expand Down
80 changes: 5 additions & 75 deletions Main/src/ChatOverlay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,11 @@ void ChatOverlay::UpdateNuklearInput(SDL_Event evt)
m_eventQueue.push(evt);
}

void ChatOverlay::ShutdownNuklear()
{
if (!m_nuklearRunning)
return;

g_gameWindow->OnAnyEvent.RemoveAll(this);
nk_sdl_shutdown();

m_nuklearRunning = false;
}


bool ChatOverlay::Init()
{
InitNuklearIfNeeded();
m_backgroundFrame = false;

BasicNuklearGui::Init();

// Init the socket callbacks
m_multi->GetTCP().SetTopicHandler("server.chat.received", this, &ChatOverlay::m_handleChatReceived);
Expand All @@ -40,63 +30,9 @@ bool ChatOverlay::Init()
return true;
}

void ChatOverlay::InitNuklearIfNeeded()
{
if (m_nuklearRunning) {
return;
}
m_nctx = nk_sdl_init((SDL_Window*)g_gameWindow->Handle());

g_gameWindow->OnAnyEvent.Add(this, &ChatOverlay::UpdateNuklearInput);
{
struct nk_font_atlas *atlas;
nk_sdl_font_stash_begin(&atlas);
struct nk_font *fallback = nk_font_atlas_add_from_file(atlas, Path::Normalize( Path::Absolute("fonts/settings/NotoSans-Regular.ttf")).c_str(), 24, 0);

NK_STORAGE const nk_rune cjk_ranges[] = {
0x0E3F, 0xFFFF,
0
};

struct nk_font_config cfg_cjk = nk_font_config(24);
cfg_cjk.merge_mode = nk_true;
cfg_cjk.range = cjk_ranges;

int maxSize;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
Logf("System max texture size: %d", Logger::Severity::Info, maxSize);
if (maxSize >= FULL_FONT_TEXTURE_HEIGHT && !g_gameConfig.GetBool(GameConfigKeys::LimitSettingsFont))
{
nk_font_atlas_add_from_file(atlas, Path::Normalize(Path::Absolute("fonts/settings/DroidSansFallback.ttf")).c_str(), 24, &cfg_cjk);
}

usc_nk_sdl_font_stash_end();
nk_font_atlas_cleanup(atlas);

nk_style_set_font(m_nctx, &fallback->handle);
}

m_nctx->style.text.color = nk_rgb(255, 255, 255);
m_nctx->style.button.border_color = nk_rgb(0, 128, 255);
m_nctx->style.button.padding = nk_vec2(5,5);
m_nctx->style.button.rounding = 0;
m_nctx->style.window.fixed_background = nk_style_item_color(nk_rgb(40, 40, 40));
m_nctx->style.slider.bar_normal = nk_rgb(20, 20, 20);
m_nctx->style.slider.bar_hover = nk_rgb(20, 20, 20);
m_nctx->style.slider.bar_active = nk_rgb(20, 20, 20);

m_nuklearRunning = true;
}

void ChatOverlay::Tick(float deltatime)
{
nk_input_begin(m_nctx);
while (!m_eventQueue.empty())
{
nk_sdl_handle_event(&m_eventQueue.front());
m_eventQueue.pop();
}
nk_input_end(m_nctx);
BasicNuklearGui::Tick(deltatime);

if (m_isOpen && nk_window_find(m_nctx, "Multiplayer Chat") &&
nk_window_is_closed(m_nctx, "Multiplayer Chat"))
Expand All @@ -105,11 +41,6 @@ void ChatOverlay::Tick(float deltatime)
}
}

void ChatOverlay::NKRender()
{
nk_sdl_render(NK_ANTI_ALIASING_ON, MAX_VERTEX_MEMORY, MAX_ELEMENT_MEMORY);
}

void ChatOverlay::m_drawChatAlert()
{
// Don't add alert if we can't open chat
Expand Down Expand Up @@ -272,8 +203,7 @@ void ChatOverlay::Render(float deltatime)
m_drawChatAlert();
}

g_application->ForceRender();
NKRender();
BasicNuklearGui::Render(deltatime);
}

void ChatOverlay::CloseChat()
Expand Down
6 changes: 6 additions & 0 deletions Main/src/GameConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,12 @@ void GameConfig::InitDefaults()

Set(GameConfigKeys::CurrentProfileName, "Main");
Set(GameConfigKeys::UpdateChannel, "master");

#ifndef EMBEDDED
Set(GameConfigKeys::KeepFontTexture, true);
#else
Set(GameConfigKeys::KeepFontTexture, false);
#endif
}

void GameConfig::UpdateVersion()
Expand Down
91 changes: 82 additions & 9 deletions Main/src/GuiUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ void BasicNuklearGui::ShutdownNuklear()
return;

g_gameWindow->OnAnyEvent.RemoveAll(this);
nk_sdl_shutdown();
nk_sdl_shutdown_keep_font();

if (!g_gameConfig.GetBool(GameConfigKeys::KeepFontTexture)) {
glDeleteTextures(1, &s_fontTexture);
s_fontTexture = 0;
s_hasFontTexture = false;
}

m_nuklearRunning = false;
}
Expand Down Expand Up @@ -70,26 +76,93 @@ static void ExtendFontAtlas(struct nk_font_atlas* atlas, const std::string_view&
nk_font_atlas_add_from_file(atlas, fontPath.data(), pixelHeight, &cfg);
}

void BasicNuklearGui::InitNuklearFontAtlas()
Mutex BasicNuklearGui::s_mutex;
nk_font_atlas* BasicNuklearGui::s_atlas = nullptr;
nk_font* BasicNuklearGui::s_font = nullptr;
GLuint BasicNuklearGui::s_fontTexture = 0;
bool BasicNuklearGui::s_hasFontTexture = false;

void BasicNuklearGui::StartFontInit()
{
// This font should cover latin and cyrillic fonts.
const String defaultFontPath = Path::Normalize(Path::Absolute("fonts/settings/NotoSans-Regular.ttf"));
const float fontSize = 24.f;

struct nk_font_atlas* atlas;
nk_sdl_font_stash_begin(&atlas);
s_atlas = new nk_font_atlas();
nk_atlas_font_stash_begin(s_atlas);

struct nk_font* font = nk_font_atlas_add_from_file(atlas, defaultFontPath.data(), fontSize, 0);
struct nk_font* font = nk_font_atlas_add_from_file(s_atlas, defaultFontPath.data(), fontSize, 0);

if (!g_gameConfig.GetBool(GameConfigKeys::LimitSettingsFont))
{
InitNuklearFontAtlasFallback(atlas, fontSize);
InitNuklearFontAtlasFallback(s_atlas, fontSize);
}
s_font = font;
}

int BasicNuklearGui::s_fontImageWidth = 0;
int BasicNuklearGui::s_fontImageHeight = 0;

void BasicNuklearGui::BakeFontWithLock()
{
BasicNuklearGui::s_mutex.lock();
BakeFont();
BasicNuklearGui::s_mutex.unlock();
}

void BasicNuklearGui::BakeFont()
{
if (s_atlas->pixel || s_hasFontTexture)
return;
usc_nk_bake_atlas(s_atlas, s_fontImageWidth, s_fontImageHeight);
}

usc_nk_sdl_font_stash_end();
nk_font_atlas_cleanup(atlas);
void BasicNuklearGui::DestroyFont()
{
if (s_hasFontTexture)
{
glDeleteTextures(1, &s_fontTexture);
s_hasFontTexture = false;
}
if (s_atlas)
{
nk_font_atlas_clear(s_atlas);
delete s_atlas;
s_atlas = nullptr;
s_font = nullptr;
}
}

void BasicNuklearGui::InitNuklearFontAtlas()
{
BasicNuklearGui::s_mutex.lock();
if (s_atlas == nullptr)
{
StartFontInit();
}

assert(s_atlas);
if (!s_hasFontTexture && s_atlas->pixel == nullptr)
{
// Our thread didn't work
Log("Baking nuklear font on main thread", Logger::Severity::Warning);
BakeFont();
}

if (!s_hasFontTexture)
{
// Also assigns the atlas to the current sdl
s_fontTexture = usc_nk_sdl_generate_texture(s_atlas, s_atlas->pixel, s_fontImageWidth, s_fontImageHeight);
s_hasFontTexture = true;
}
else
{
usc_nk_sdl_use_atlas(s_atlas, s_fontTexture);
}
BasicNuklearGui::s_mutex.unlock();

nk_style_set_font(m_nctx, &font->handle);
assert(s_font);
nk_style_set_font(m_nctx, &s_font->handle);
}

void BasicNuklearGui::InitNuklearFontAtlasFallback(struct nk_font_atlas* atlas, float fontSize)
Expand Down
4 changes: 3 additions & 1 deletion Main/src/MultiplayerScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1211,7 +1211,9 @@ void MultiplayerScreen::m_OnButtonPressed(Input::Button buttonCode)
if (g_gameConfig.GetEnum<Enum_InputDevice>(GameConfigKeys::ButtonInputDevice) == InputDevice::Keyboard)
{
// In this case we want them to hit escape so we don't exit on text inputs
break;
int backScancode = g_gameConfig.GetInt(GameConfigKeys::Key_Back);
if (backScancode != SDL_SCANCODE_ESCAPE)
break;
}
// Otherwise fall though
[[fallthrough]];
Expand Down
1 change: 1 addition & 0 deletions Main/src/SettingsScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,7 @@ class SettingsPage_System : public SettingsPage
SelectionSetting(GameConfigKeys::AntiAliasing, m_aaModes, "Anti-aliasing (requires restart):");
SetApply(ToggleSetting(GameConfigKeys::VSync, "VSync"));
SetApply(ToggleSetting(GameConfigKeys::ShowFps, "Show FPS"));
SetApply(ToggleSetting(GameConfigKeys::KeepFontTexture, "Save font texture (settings load faster but uses more memory)"));

SectionHeader("Update");

Expand Down
Loading

0 comments on commit 98e3d12

Please sign in to comment.