Skip to content

Commit

Permalink
custom fonts
Browse files Browse the repository at this point in the history
  • Loading branch information
sjrc6 committed Dec 25, 2024
1 parent d0de3c1 commit 16fe2e3
Show file tree
Hide file tree
Showing 19 changed files with 161 additions and 26 deletions.
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1829,6 +1829,12 @@ set(EXPECTED_DATA
skins7/x_ninja.json
skins7/xmas_hat.png
strong_weak.png
tclient/fonts/Cabin-Regular.ttf
tclient/fonts/GoogleSans-Regular.ttf
tclient/fonts/minecraft_font.ttf
tclient/fonts/Montserrat-Regular.ttf
tclient/fonts/Nunito-Black.ttf
tclient/fonts/Rubik-Regular.ttf
themes/auto.png
themes/autumn.png
themes/autumn_day.map
Expand Down
Binary file added data/tclient/fonts/Cabin-Regular.ttf
Binary file not shown.
Binary file added data/tclient/fonts/GoogleSans-Regular.ttf
Binary file not shown.
Binary file added data/tclient/fonts/Montserrat-Regular.ttf
Binary file not shown.
Binary file added data/tclient/fonts/Nunito-Black.ttf
Binary file not shown.
Binary file added data/tclient/fonts/Rubik-Regular.ttf
Binary file not shown.
Binary file added data/tclient/fonts/minecraft_font.ttf
Binary file not shown.
78 changes: 78 additions & 0 deletions src/engine/client/text.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,8 @@ class CGlyphMap
delete[] pTextureData;
}
}
// TClient
std::vector<FT_Face> *GetFaces() { return &m_vFtFaces; }

FT_Face DefaultFace() const
{
Expand Down Expand Up @@ -959,6 +961,10 @@ class CTextRender : public IEngineTextRender

std::chrono::nanoseconds m_CursorRenderTime;

// TClient
std::vector<std::string> m_CustomFontFaces;
std::vector<std::string> m_DefaultFontFaces;

int GetFreeTextContainerIndex()
{
if(m_FirstFreeTextContainerIndex == -1)
Expand Down Expand Up @@ -1153,6 +1159,76 @@ class CTextRender : public IEngineTextRender
m_pGraphics = nullptr;
m_pStorage = nullptr;
}
// TClient
static int LaziestFileCallback(const char *pFilename, int IsDir, int StorageType, void *pUser)
{
std::vector<std::string> *pVector = static_cast<std::vector<std::string>*>(pUser);
if(IsDir)
return 0;
pVector->push_back(std::string(pFilename));
return 0;
}

// TClient
void CheckDefaultFaces()
{
for(const auto &CurrentFace : *m_pGlyphMap->GetFaces())
m_DefaultFontFaces.push_back(std::string(CurrentFace->family_name));
}
// TClient
void UpdateCustomFontList()
{
std::vector<std::string> m_AllFaces;
for(const auto &CurrentFace : *m_pGlyphMap->GetFaces())
m_AllFaces.push_back(std::string(CurrentFace->family_name));

m_CustomFontFaces.clear();
m_CustomFontFaces.push_back(std::string("DejaVu Sans"));
for(const auto &face : m_AllFaces)
if(std::find(m_DefaultFontFaces.begin(), m_DefaultFontFaces.end(), face) == m_DefaultFontFaces.end())
m_CustomFontFaces.push_back(face);
}
// TClient
void LoadCustomFonts()
{
CheckDefaultFaces();
std::vector<std::string> vCustomFonts;
Storage()->ListDirectory(IStorage::TYPE_ALL, "tclient/fonts", LaziestFileCallback, &vCustomFonts);
std::sort(vCustomFonts.begin(), vCustomFonts.end());
for(std::string sFile : vCustomFonts)
{
char aFontName[IO_MAX_PATH_LENGTH];
str_format(aFontName, sizeof(aFontName), "tclient/fonts/%s", sFile.c_str());
void *pFontData;
unsigned FontDataSize;
if(Storage()->ReadFile(aFontName, IStorage::TYPE_ALL, &pFontData, &FontDataSize))
{
if(LoadFontCollection(aFontName, static_cast<FT_Byte *>(pFontData), (FT_Long)FontDataSize))
{
m_vpFontData.push_back(pFontData);
}
else
{
free(pFontData);
}
}
else
{
log_error("textrender", "Failed to open/read font file '%s'", aFontName);
}
}
UpdateCustomFontList();
}
// TClient
std::vector<std::string> *GetCustomFaces() override
{
return &m_CustomFontFaces;
}
// TClient
void SetCustomFace(const char *pFace) override
{
m_pGlyphMap->SetDefaultFaceByName(pFace);
}

bool LoadFonts() override
{
Expand Down Expand Up @@ -1239,6 +1315,8 @@ class CTextRender : public IEngineTextRender
log_error("textrender", "Font index malformed: 'default' must be a string");
Success = false;
}
// TClient
LoadCustomFonts();

// extract language variant family names
const json_value &Variants = (*pJsonData)["language variants"];
Expand Down
3 changes: 2 additions & 1 deletion src/engine/shared/tater_variables.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@ MACRO_CONFIG_COL(ClStatusBarTextColor, tc_statusbar_text_color, 4278190335, CFGF
MACRO_CONFIG_COL(ClStatusBarAlpha, tc_statusbar_alpha, 75, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Status bar background alpha")
MACRO_CONFIG_COL(ClStatusBarTextAlpha, tc_statusbar_text_alpha, 100, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Status bar text alpha")


// Font
MACRO_CONFIG_STR(ClCustomFont, tc_custom_font, 255, "Dejavu Sans", CFGFLAG_CLIENT | CFGFLAG_SAVE, "Custom font face")



Expand Down
3 changes: 3 additions & 0 deletions src/engine/textrender.h
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,9 @@ class ITextRender : public IInterface
virtual void MoveCursor(CTextCursor *pCursor, float x, float y) const = 0;
virtual void SetCursorPosition(CTextCursor *pCursor, float x, float y) const = 0;

virtual std::vector<std::string> *GetCustomFaces() = 0; // TClient
virtual void SetCustomFace(const char *pFace) = 0; // TClient

virtual bool LoadFonts() = 0;
virtual void SetFontPreset(EFontPreset FontPreset) = 0;
virtual void SetFontLanguageVariant(const char *pLanguageFile) = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/game/client/components/controls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ int CControls::SnapInput(int *pData)
else
m_aInputData[g_Config.m_ClDummy].m_PlayerFlags = PLAYERFLAG_PLAYING;

if(m_pClient->m_Scoreboard.Active() || g_Config.m_ClPingNameCircle)
if(m_pClient->m_Scoreboard.Active() || g_Config.m_ClPingNameCircle || GameClient()->m_StatusBar.m_PingActive)
m_aInputData[g_Config.m_ClDummy].m_PlayerFlags |= PLAYERFLAG_SCOREBOARD;

if(Client()->ServerCapAnyPlayerFlag() && m_pClient->m_Controls.m_aShowHookColl[g_Config.m_ClDummy])
Expand Down
44 changes: 33 additions & 11 deletions src/game/client/components/tclient/menus_tclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ int CMenus::DoButtonLineSize_Menu(CButtonContainer *pButtonContainer, const char
return 0;

return Ui()->DoButtonLogic(pButtonContainer, Checked, pRect);

}

void CMenus::RenderSettingsTClient(CUIRect MainView)
Expand Down Expand Up @@ -194,7 +193,8 @@ void CMenus::RenderSettingsTClient(CUIRect MainView)
for(int Tab = 0; Tab < NUMBER_OF_TCLIENT_TABS; ++Tab)
{
TabBar.VSplitLeft(TabWidth, &Button, &TabBar);
const int Corners = Tab == 0 ? IGraphics::CORNER_L : Tab == NUMBER_OF_TCLIENT_TABS - 1 ? IGraphics::CORNER_R : IGraphics::CORNER_NONE;
const int Corners = Tab == 0 ? IGraphics::CORNER_L : Tab == NUMBER_OF_TCLIENT_TABS - 1 ? IGraphics::CORNER_R :
IGraphics::CORNER_NONE;
if(DoButton_MenuTab(&s_aPageTabs[Tab], apTabNames[Tab], s_CurCustomTab == Tab, &Button, Corners, nullptr, nullptr, nullptr, nullptr, 4.0f))
s_CurCustomTab = Tab;
}
Expand Down Expand Up @@ -266,6 +266,35 @@ void CMenus::RenderSettingsTClient(CUIRect MainView)
s_WhiteFeet.SetEmptyText("x_ninja");
Ui()->DoEditBox(&s_WhiteFeet, &FeetBox, EditBoxFontSize);
}
Column.HSplitTop(MarginSmall, nullptr, &Column);

static std::vector<const char *> s_FontDropDownNames = {};
static CUi::SDropDownState s_FontDropDownState;
static CScrollRegion s_FontDropDownScrollRegion;
s_FontDropDownState.m_SelectionPopupContext.m_pScrollRegion = &s_FontDropDownScrollRegion;
s_FontDropDownState.m_SelectionPopupContext.m_SpecialFontRenderMode = true;
int FontSelectedOld = -1;
for(size_t i = 0; i < TextRender()->GetCustomFaces()->size(); ++i)
{
if(s_FontDropDownNames.size() != TextRender()->GetCustomFaces()->size())
s_FontDropDownNames.push_back(TextRender()->GetCustomFaces()->at(i).c_str());

if(str_find_nocase(g_Config.m_ClCustomFont, TextRender()->GetCustomFaces()->at(i).c_str()))
FontSelectedOld = i;
}

CUIRect FontDropDownRect;
Column.HSplitTop(LineSize, &FontDropDownRect, &Column);
FontDropDownRect.VSplitLeft(100.0f, &Label, &FontDropDownRect);
Ui()->DoLabel(&Label, Localize("Custom Font: "), FontSize, TEXTALIGN_ML);
const int FontSelectedNew = Ui()->DoDropDown(&FontDropDownRect, FontSelectedOld, s_FontDropDownNames.data(), s_FontDropDownNames.size(), s_FontDropDownState);
if(FontSelectedOld != FontSelectedNew)
{
str_copy(g_Config.m_ClCustomFont, s_FontDropDownNames[FontSelectedNew]);
FontSelectedOld = FontSelectedNew;
TextRender()->SetCustomFace(g_Config.m_ClCustomFont);
}

Column.HSplitTop(MarginExtraSmall, nullptr, &Column);

s_SectionBoxes.back().h = Column.y - s_SectionBoxes.back().y;
Expand Down Expand Up @@ -573,8 +602,8 @@ void CMenus::RenderSettingsTClient(CUIRect MainView)
Ui()->DoScrollbarOption(&g_Config.m_ClRainbowSpeed, &g_Config.m_ClRainbowSpeed, &Button, Localize("Rainbow speed"), 0, 5000, &CUi::ms_LogarithmicScrollbarScale, 0, "%");
Column.HSplitTop(MarginExtraSmall, nullptr, &Column);
s_SectionBoxes.back().h = Column.y - s_SectionBoxes.back().y;

Column.HSplitTop(MarginSmall, nullptr, &Column);

// ***** END OF PAGE 1 SETTINGS ***** //
RightView = Column;

Expand All @@ -599,8 +628,7 @@ void CMenus::RenderSettingsTClient(CUIRect MainView)
Ui()->DoLabel(&Label, Localize("Kaomoji"), HeadlineFontSize, TEXTALIGN_ML);
Column.HSplitTop(MarginSmall, nullptr, &Column);

auto DoBindchat = [&](CLineInput &LineInput, const char *pLabel, const char *pName, const char *pCommand)
{
auto DoBindchat = [&](CLineInput &LineInput, const char *pLabel, const char *pName, const char *pCommand) {
Column.HSplitTop(LineSize, &Button, &Column);
char *BindCommand;
int BindIndex = GameClient()->m_Bindchat.GetBindNoDefault(pCommand);
Expand Down Expand Up @@ -645,7 +673,6 @@ void CMenus::RenderSettingsTClient(CUIRect MainView)
Ui()->DoLabel(&Label, Localize("Warlist"), HeadlineFontSize, TEXTALIGN_ML);
Column.HSplitTop(MarginSmall, nullptr, &Column);


static CLineInput s_Warlist1, s_Warlist2, s_Warlist3, s_Warlist4, s_Warlist5, s_Warlist6, s_Warlist7, s_Warlist8;
char aBuf[128];
char aGroup1Name[MAX_WARLIST_TYPE_LENGTH]; // enemy by default
Expand Down Expand Up @@ -676,7 +703,6 @@ void CMenus::RenderSettingsTClient(CUIRect MainView)
Column.HSplitTop(MarginSmall, nullptr, &Column);
str_format(aBuf, sizeof(aBuf), "Remove %s clan:", aGroup2Name);
DoBindchat(s_Warlist8, aBuf, ".delteamclan", "remove_war_clan_index 2");

}

if(s_CurCustomTab == TCLIENT_TAB_BINDWHEEL)
Expand Down Expand Up @@ -917,7 +943,6 @@ void CMenus::RenderSettingsWarList(CUIRect MainView)
static CWarEntry *pSelectedEntry = nullptr;
static CWarType *pSelectedType = GameClient()->m_WarList.m_WarTypes[0];


// Filter the list
static CLineInputBuffered<128> s_EntriesFilterInput;
std::vector<CWarEntry *> vpFilteredEntries;
Expand Down Expand Up @@ -1135,7 +1160,6 @@ void CMenus::RenderSettingsWarList(CUIRect MainView)
TextRender()->TextColor(TextRender()->DefaultTextColor());
}


Column2.HSplitBottom(150.0f, nullptr, &Column2);

Column2.HSplitTop(HeadlineHeight, &Label, &Column2);
Expand All @@ -1148,7 +1172,6 @@ void CMenus::RenderSettingsWarList(CUIRect MainView)
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClWarListScoreboard, Localize("Colors in scoreboard"), &g_Config.m_ClWarListScoreboard, &Column2, LineSize);
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClWarListShowClan, Localize("Show clan if war"), &g_Config.m_ClWarListShowClan, &Column2, LineSize);


// ======WAR TYPE EDITING======

Column3.HSplitTop(HeadlineHeight, &Label, &Column3);
Expand Down Expand Up @@ -1398,7 +1421,6 @@ void CMenus::RenderSettingsInfo(CUIRect MainView)
Client()->ViewFile(aBuf);
}


// =======RIGHT VIEW========

RightView.HSplitTop(HeadlineHeight, &Label, &RightView);
Expand Down
21 changes: 15 additions & 6 deletions src/game/client/components/tclient/statusbar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ float CStatusBar::AngleWidth()
}
void CStatusBar::AngleRender()
{
CNetObj_Character *pCharacter = &m_pClient->m_Snap.m_aCharacters[m_pClient->m_Snap.m_LocalClientId].m_Cur;
CNetObj_Character *pCharacter = &m_pClient->m_Snap.m_aCharacters[m_PlayerId].m_Cur;
float Angle = 0.0f;
if(m_pClient->m_Snap.m_aCharacters[m_pClient->m_Snap.m_LocalClientId].m_HasExtendedDisplayInfo)
if(m_pClient->m_Snap.m_aCharacters[m_PlayerId].m_HasExtendedDisplayInfo)
{
CNetObj_DDNetCharacter *pExtendedData = &m_pClient->m_Snap.m_aCharacters[m_pClient->m_Snap.m_LocalClientId].m_ExtendedData;
CNetObj_DDNetCharacter *pExtendedData = &m_pClient->m_Snap.m_aCharacters[m_PlayerId].m_ExtendedData;
Angle = atan2f(pExtendedData->m_TargetY, pExtendedData->m_TargetX);
}
else
Expand All @@ -69,17 +69,18 @@ void CStatusBar::AngleRender()

float CStatusBar::PingWidth()
{
if(!m_pClient->m_Snap.m_apPlayerInfos[m_pClient->m_Snap.m_LocalClientId])
if(!m_pClient->m_Snap.m_apPlayerInfos[m_PlayerId])
return 0.0f;

return TextRender()->TextWidth(m_FontSize, "0000");
}
void CStatusBar::PingRender() {

const CNetObj_PlayerInfo *pInfo = m_pClient->m_Snap.m_apPlayerInfos[m_pClient->m_Snap.m_LocalClientId];
const CNetObj_PlayerInfo *pInfo = m_pClient->m_Snap.m_apPlayerInfos[m_PlayerId];
char aBuf[32];
str_format(aBuf, sizeof(aBuf), "%d", GameClient()->Client()->NetClient()->GetLatency());
str_format(aBuf, sizeof(aBuf), "%d", pInfo->m_Latency);
TextRender()->Text(m_CursorX, m_CursorY, m_FontSize, aBuf);
m_PingActive = true;
}

float CStatusBar::PredictionWidth()
Expand Down Expand Up @@ -150,11 +151,19 @@ float CStatusBar::LabelWidth(const char *pLabel) { return 0.0f; }

void CStatusBar::OnRender()
{
m_PingActive = false;

if(Client()->State() != IClient::STATE_ONLINE && Client()->State() != IClient::STATE_DEMOPLAYBACK)
return;

if(!g_Config.m_ClStatusBar || !m_pClient->m_Snap.m_pGameInfoObj)
return;

m_PlayerId = m_pClient->m_Snap.m_LocalClientId;
if(m_pClient->m_Snap.m_SpecInfo.m_Active)
m_PlayerId = m_pClient->m_Snap.m_SpecInfo.m_SpectatorId;


UpdateStatusBarSize();

Graphics()->MapScreen(0.0f, 0.0f, m_Width, m_Height);
Expand Down
3 changes: 2 additions & 1 deletion src/game/client/components/tclient/statusbar.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,9 @@ class CStatusBar : public CComponent

void UpdateStatusBarSize();


bool m_PingActive = false;
float m_FrameTimeAverage = 0.0f;
int m_PlayerId = 0;
// float Width();
// void Render();
// float Width();
Expand Down
5 changes: 5 additions & 0 deletions src/game/client/components/tclient/tater.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ void CTater::ConchainRandomColor(IConsole::IResult *pResult, void *pUserData, IC
pThis->m_pClient->SendInfo(false);
}

void CTater::OnInit()
{
TextRender()->SetCustomFace(g_Config.m_ClCustomFont);
}

void CTater::OnConsoleInit()
{
Console()->Register("tc_random_player", "s[type]", CFGFLAG_CLIENT, ConRandomTee, this, "Randomize player color (0 = all, 1 = body, 2 = feet, 3 = skin, 4 = flag) example: 0011 = randomize skin and flag [number is position] ");
Expand Down
1 change: 1 addition & 0 deletions src/game/client/components/tclient/tater.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class CTater : public CComponent
public:
CTater();
virtual int Sizeof() const override { return sizeof(*this); }
virtual void OnInit() override;

virtual void OnConsoleInit() override;
};
Expand Down
12 changes: 6 additions & 6 deletions src/game/client/gameclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2548,17 +2548,17 @@ void CGameClient::OnPredict()
}
CNetObj_PlayerInput *pInputData = m_PredictedWorld.GetCharacterById(m_Snap.m_LocalClientId)->LatestInput();
CNetObj_PlayerInput *pDummyInputData = !pPredDummyChar ? 0 : m_PredictedWorld.GetCharacterById(m_PredictedDummyId)->LatestInput();
bool DummyFirst = pInputData && pDummyInputData && pSmoothDummyChar->GetCid() < pSmoothLocalChar->GetCid();
if(DummyFirst)
bool DummyFirst = pSmoothLocalChar && pSmoothDummyChar && pSmoothDummyChar->GetCid() < pSmoothLocalChar->GetCid();
if(DummyFirst && pSmoothDummyChar)
pSmoothDummyChar->OnDirectInput(pDummyInputData);
if(pInputData)
if(pInputData && pSmoothLocalChar)
pSmoothLocalChar->OnDirectInput(pInputData);
if(pDummyInputData && !DummyFirst)
if(pDummyInputData && !DummyFirst && pSmoothDummyChar)
pSmoothDummyChar->OnDirectInput(pDummyInputData);
m_PredSmoothingWorld.m_GameTick++;
if(pInputData)
if(pInputData && pSmoothLocalChar)
pSmoothLocalChar->OnPredictedInput(pInputData);
if(pDummyInputData)
if(pDummyInputData && pSmoothDummyChar)
pSmoothDummyChar->OnPredictedInput(pDummyInputData);
m_PredSmoothingWorld.Tick();

Expand Down
Loading

0 comments on commit 16fe2e3

Please sign in to comment.