Skip to content

Commit

Permalink
war list settings
Browse files Browse the repository at this point in the history
  • Loading branch information
sjrc6 committed Dec 8, 2024
1 parent c75d6ef commit fd95899
Show file tree
Hide file tree
Showing 7 changed files with 290 additions and 21 deletions.
2 changes: 2 additions & 0 deletions src/engine/textrender.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ MAYBE_UNUSED static const char *FONT_ICON_FLAG_CHECKERED = "\xEF\x84\x9E";
MAYBE_UNUSED static const char *FONT_ICON_BAN = "\xEF\x81\x9E";
MAYBE_UNUSED static const char *FONT_ICON_CIRCLE_CHEVRON_DOWN = "\xEF\x84\xBA";
MAYBE_UNUSED static const char *FONT_ICON_KEY = "\xEF\x82\x84";
MAYBE_UNUSED static const char *FONT_ICON_USERS = "\xEF\x83\x80";
MAYBE_UNUSED static const char *FONT_ICON_COMMENT = "\xEF\x81\xB5";
MAYBE_UNUSED static const char *FONT_ICON_SQUARE_MINUS = "\xEF\x85\x86";
MAYBE_UNUSED static const char *FONT_ICON_SQUARE_PLUS = "\xEF\x83\xBE";
MAYBE_UNUSED static const char *FONT_ICON_SORT_UP = "\xEF\x83\x9E";
Expand Down
4 changes: 3 additions & 1 deletion src/game/client/components/menus.h
Original file line number Diff line number Diff line change
Expand Up @@ -849,8 +849,10 @@ class CMenus : public CComponent
// found in menus_tclient.cpp
void RenderSettingsTClient(CUIRect MainView);
void RenderSettingsProfiles(CUIRect MainView);
void RenderDevSkin(vec2 RenderPos, float Size, const char *pSkinName, const char *pBackupSkin, bool CustomColors, int FeetColor, int BodyColor, int Emote, bool Rainbow);
void RenderSettingsWarList(CUIRect MainView);

void RenderDevSkin(vec2 RenderPos, float Size, const char *pSkinName, const char *pBackupSkin, bool CustomColors, int FeetColor, int BodyColor, int Emote, bool Rainbow);
void RenderFontIcon(const CUIRect Rect, const char *pText, float Size, int Align);

ColorHSLA RenderHSLColorPicker(const CUIRect *pRect, unsigned int *pColor, bool Alpha);
bool RenderHslaScrollbars(CUIRect *pRect, unsigned int *pColor, bool Alpha, float DarkestLight);
Expand Down
227 changes: 226 additions & 1 deletion src/game/client/components/tclient/menus_tclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ static bool s_StartedTime = false;
const float LineSize = 20.0f;
const float ColorPickerLineSize = 25.0f;
const float HeadlineFontSize = 20.0f;
const float StandardFontSize = 14.0f;

const float HeadlineHeight = HeadlineFontSize + 0.0f;
const float Margin = 10.0f;
const float MarginSmall = 5.0f;
Expand Down Expand Up @@ -726,6 +728,11 @@ void CMenus::RenderSettingsTClient(CUIRect MainView)
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClResetBindWheelMouse, Localize("Reset position of mouse when opening bindwheel"), &g_Config.m_ClResetBindWheelMouse, &Button, LineSize);
}

if(s_CurCustomTab == TCLIENT_TAB_WARLIST)
{
RenderSettingsWarList(MainView);
}

if(s_CurCustomTab == TCLIENT_TAB_INFO)
{
MainView.HSplitTop(MarginSmall, nullptr, &MainView);
Expand Down Expand Up @@ -819,6 +826,215 @@ void CMenus::RenderSettingsTClient(CUIRect MainView)
}
}

void CMenus::RenderSettingsWarList(CUIRect MainView)
{
CUIRect RightView, LeftView, Column1, Column2, Column3, Column4, Button, ButtonL, ButtonR, Label;

MainView.HSplitTop(MarginSmall, nullptr, &MainView);
MainView.VSplitMid(&LeftView, &RightView, MarginBetweenViews);
LeftView.VSplitLeft(MarginSmall, nullptr, &LeftView);
RightView.VSplitRight(MarginSmall, &RightView, nullptr);

// WAR LIST will have 4 columns
// [War entries] - [Entry Editing] - [Group Types] - [Recent Players]
// [Group Editing]

// putting this here so it can be updated by the entry list
static char s_aEntryName[MAX_NAME_LENGTH];
static char s_aEntryClan[MAX_CLAN_LENGTH];
static char s_aEntryReason[MAX_WARLIST_REASON_LENGTH];
static int s_IsClan = 1;
static int s_IsName = 0;

LeftView.VSplitMid(&Column1, &Column2, Margin);
RightView.VSplitMid(&Column3, &Column4, Margin);

// ======WAR ENTRIES======
Column1.HSplitTop(HeadlineHeight, &Label, &Column1);
Ui()->DoLabel(&Label, Localize("War Entries"), HeadlineFontSize, TEXTALIGN_ML);
Column1.HSplitTop(MarginSmall, nullptr, &Column1);
CUIRect EntriesSearch;

Column1.HSplitBottom(25.0f, &Column1, &EntriesSearch);
EntriesSearch.HSplitTop(MarginSmall, nullptr, &EntriesSearch);

static CWarEntry *pSelectedEntry = nullptr;
// Filter the list
static CLineInputBuffered<128> s_EntriesFilterInput;
std::vector<CWarEntry *> vpFilteredEntries;
for(size_t i = 0; i < GameClient()->m_WarList.m_WarEntries.size(); ++i)
{
CWarEntry *pEntry = &GameClient()->m_WarList.m_WarEntries[i];
bool Matches = false;
if(str_find_nocase(pEntry->m_aName, s_EntriesFilterInput.GetString()))
Matches = true;
if(str_find_nocase(pEntry->m_aClan, s_EntriesFilterInput.GetString()))
Matches = true;
if(str_find_nocase(pEntry->m_pWarType->m_aWarName, s_EntriesFilterInput.GetString()))
Matches = true;
if(Matches)
vpFilteredEntries.push_back(pEntry);
}

int SelectedOld = -1;
static CListBox s_EntriesListBox;
s_EntriesListBox.DoStart(35.0f, vpFilteredEntries.size(), 1, 2, SelectedOld, &Column1);

static std::vector<unsigned char> s_vItemIds;
static std::vector<CButtonContainer> s_vToolTipIds;
static std::vector<CButtonContainer> s_vDeleteButtons;

const int MaxEntries = GameClient()->m_WarList.m_WarEntries.size();
s_vItemIds.resize(MaxEntries);
s_vDeleteButtons.resize(MaxEntries);
s_vToolTipIds.resize(MaxEntries);

for(size_t i = 0; i < vpFilteredEntries.size(); i++)
{
CWarEntry *pEntry = vpFilteredEntries[i];

// idk why it wants this, it was complaining
if(!pEntry)
continue;

if(pSelectedEntry && pEntry == pSelectedEntry)
SelectedOld = i;

const CListboxItem Item = s_EntriesListBox.DoNextItem(&s_vItemIds[i], SelectedOld >= 0 && (size_t)SelectedOld == i);
if(!Item.m_Visible)
continue;

CUIRect EntryRect, DeleteButton, EntryTypeRect, WarType, ToolTip;
Item.m_Rect.Margin(0.0f, &EntryRect);
EntryRect.VSplitLeft(26.0f, &DeleteButton, &EntryRect);
DeleteButton.HMargin(7.5f, &DeleteButton);
DeleteButton.VSplitLeft(MarginSmall, nullptr, &DeleteButton);
DeleteButton.VSplitRight(MarginExtraSmall, &DeleteButton, nullptr);

if(DoButton_FontIcon(&s_vDeleteButtons[i], FONT_ICON_TRASH, 0, &DeleteButton, IGraphics::CORNER_ALL))
{
GameClient()->m_WarList.RemoveWarEntry(pEntry);
}
bool IsClan = false;
char aBuf[32];
if(str_comp(pEntry->m_aClan, "") != 0)
{
str_copy(aBuf, pEntry->m_aClan);
IsClan = true;
s_IsClan = 1;
s_IsName = 0;
}
else
{
str_copy(aBuf, pEntry->m_aName);
s_IsClan = 0;
s_IsName = 1;
}
EntryRect.VSplitLeft(35.0f, &EntryTypeRect, &EntryRect);

if(IsClan)
{
RenderFontIcon(EntryTypeRect, FONT_ICON_USERS, 18.0f, TEXTALIGN_MC);
}
else
{
// TODO: stop misusing this function
// TODO: render the real skin with skin remembering component (to be added)
RenderDevSkin(EntryTypeRect.Center(), 35.0f, "defualt", "default", false, 0, 0, 0, false);
}

if(str_comp(pEntry->m_aReason, "") != 0)
{
EntryRect.VSplitRight(20.0f, &EntryRect, &ToolTip);
RenderFontIcon(ToolTip, FONT_ICON_COMMENT, 18.0f, TEXTALIGN_MC);
GameClient()->m_Tooltips.DoToolTip(&s_vItemIds[i], &ToolTip, pEntry->m_aReason);
GameClient()->m_Tooltips.SetFadeTime(&s_vItemIds[i], 0.0f);
}

EntryRect.HMargin(MarginExtraSmall, &EntryRect);
EntryRect.HSplitMid(&EntryRect, &WarType, MarginSmall);

Ui()->DoLabel(&EntryRect, aBuf, StandardFontSize, TEXTALIGN_ML);
TextRender()->TextColor(pEntry->m_pWarType->m_Color);
Ui()->DoLabel(&WarType, pEntry->m_pWarType->m_aWarName, StandardFontSize, TEXTALIGN_ML);
TextRender()->TextColor(TextRender()->DefaultTextColor());
}
const int NewSelected = s_EntriesListBox.DoEnd();
if(SelectedOld != NewSelected)
{
pSelectedEntry = vpFilteredEntries[NewSelected];
str_copy(s_aEntryName, pSelectedEntry->m_aName);
str_copy(s_aEntryClan, pSelectedEntry->m_aClan);
str_copy(s_aEntryReason, pSelectedEntry->m_aReason);
}

Ui()->DoEditBox_Search(&s_EntriesFilterInput, &EntriesSearch, 14.0f, !Ui()->IsPopupOpen() && m_pClient->m_GameConsole.IsClosed());

// ======WAR ENTRY EDITING======

Column2.HSplitTop(HeadlineHeight, nullptr, &Column2);
Column2.HSplitTop(MarginSmall, nullptr, &Column2);
Column2.HSplitTop(HeadlineFontSize, &Button, &Column2);


Button.VSplitMid(&ButtonL, &ButtonR, MarginSmall);
static CLineInput s_NameInput;
s_NameInput.SetBuffer(s_aEntryName, sizeof(s_aEntryName));
s_NameInput.SetEmptyText("Name");
if(s_IsName)
Ui()->DoEditBox(&s_NameInput, &ButtonL, 12.0f);
else
{
ButtonL.Draw(ColorRGBA(1.0f, 1.0f, 1.0f, 0.25f), 15, 3.0f);
Ui()->ClipEnable(&ButtonL);
ButtonL.VMargin(2.0f, &ButtonL);
const STextBoundingBox BoundingBox = s_NameInput.Render(&ButtonL, 12.0f, TEXTALIGN_ML, false, -1.0f, 0.0f);
Ui()->ClipDisable();
}

static CLineInput s_ClanInput;
s_ClanInput.SetBuffer(s_aEntryClan, sizeof(s_aEntryClan));
s_ClanInput.SetEmptyText("Clan");
if(s_IsClan)
Ui()->DoEditBox(&s_ClanInput, &ButtonR, 12.0f);
else
{
ButtonR.Draw(ColorRGBA(1.0f, 1.0f, 1.0f, 0.25f), 15, 3.0f);
Ui()->ClipEnable(&ButtonR);
ButtonR.VMargin(2.0f, &ButtonR);
const STextBoundingBox BoundingBox = s_ClanInput.Render(&ButtonR, 12.0f, TEXTALIGN_ML, false, -1.0f, 0.0f);
Ui()->ClipDisable();

}
Column2.HSplitTop(MarginSmall, nullptr, &Column2);
Column2.HSplitTop(HeadlineFontSize, &Button, &Column2);
static CLineInput s_ReasonInput;
s_ReasonInput.SetBuffer(s_aEntryReason, sizeof(s_aEntryReason));
s_ReasonInput.SetEmptyText("Reason");
Ui()->DoEditBox(&s_ReasonInput, &Button, 12.0f);

Column2.HSplitTop(MarginSmall, nullptr, &Column2);
Column2.HSplitTop(LineSize, &Button, &Column2);
Button.VSplitMid(&ButtonL, &ButtonR, MarginSmall);
static unsigned char s_NameRadio, s_ClanRadio;
if(DoButton_CheckBox_Common(&s_NameRadio, "Name", s_IsName ? "X" : "", &ButtonL))
{
s_IsName = 1;
s_IsClan = 0;
}
if(DoButton_CheckBox_Common(&s_ClanRadio, "Clan", s_IsClan ? "X" : "", &ButtonR))
{
s_IsName = 0;
s_IsClan = 1;
}
if(!s_IsName)
str_copy(s_aEntryName, "");
if(!s_IsClan)
str_copy(s_aEntryClan, "");

static CButtonContainer s_AddButton, s_RemoveButton, s_OverrideButton;
}

void CMenus::RenderSettingsProfiles(CUIRect MainView)
{
CUIRect Label, LabelMid, Section, LabelRight;
Expand Down Expand Up @@ -1253,7 +1469,7 @@ void CMenus::RenderDevSkin(vec2 RenderPos, float Size, const char *pSkinName, co
SkinInfo.m_ColorBody = ColorRGBA(1.0f, 1.0f, 1.0f);
SkinInfo.m_ColorFeet = ColorRGBA(1.0f, 1.0f, 1.0f);
}
if (Rainbow)
if(Rainbow)
{
ColorRGBA Col = color_cast<ColorRGBA>(ColorHSLA(DefTick, 1.0f, 0.5f));
SkinInfo.m_ColorBody = Col;
Expand All @@ -1266,3 +1482,12 @@ void CMenus::RenderDevSkin(vec2 RenderPos, float Size, const char *pSkinName, co
vec2 TeeRenderPos(RenderPos.x, RenderPos.y + OffsetToMid.y);
RenderTools()->RenderTee(pIdleState, &SkinInfo, Emote, vec2(1.0f, 0.0f), TeeRenderPos);
}

void CMenus::RenderFontIcon(const CUIRect Rect, const char *pText, float Size, int Align)
{
TextRender()->SetFontPreset(EFontPreset::ICON_FONT);
TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING);
Ui()->DoLabel(&Rect, pText, Size, Align);
TextRender()->SetRenderFlags(0);
TextRender()->SetFontPreset(EFontPreset::DEFAULT_FONT);
}
43 changes: 30 additions & 13 deletions src/game/client/components/tclient/warlist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ void CWarList::UpsertWarType(int Index, const char *pType, ColorRGBA Color)

if(Index >= 0 && Index < static_cast<int>(m_WarTypes.size()))
{
str_copy(m_WarTypes[Index].m_aWarType, pType);
m_WarTypes[Index].m_Color = Color;
str_copy(m_WarTypes[Index]->m_aWarName, pType);
m_WarTypes[Index]->m_Color = Color;
}
else
{
Expand All @@ -130,6 +130,12 @@ void CWarList::UpsertWarType(int Index, const char *pType, ColorRGBA Color)
void CWarList::AddWarEntry(const char *pName, const char *pClan, const char *pReason, const char *pType)
{
CWarType *WarType = FindWarType(pType);

if(WarType == &m_WarTypeNone)
{
AddWarType(pType, ColorRGBA(0, 0, 1, 1));
WarType = FindWarType(pType);
}
CWarEntry Entry(WarType);
str_copy(Entry.m_aReason, pReason);

Expand All @@ -145,13 +151,13 @@ void CWarList::AddWarEntry(const char *pName, const char *pClan, const char *pRe

void CWarList::AddWarType(const char *pType, ColorRGBA Color)
{
if(str_comp(pType, "none"))
if(str_comp(pType, "none") == 0)
return;

CWarType *Type = FindWarType(pType);
if(*Type == m_WarTypeNone)
if(Type == &m_WarTypeNone)
{
CWarType NewType(pType, Color);
CWarType *NewType = new CWarType(pType, Color);
m_WarTypes.push_back(NewType);
}
else
Expand All @@ -169,20 +175,30 @@ void CWarList::RemoveWarEntry(const char *pName, const char *pClan, const char *
m_WarEntries.erase(it);
}


void CWarList::RemoveWarEntry(CWarEntry *Entry)
{
auto it = std::find_if(m_WarEntries.begin(), m_WarEntries.end(),
[Entry](const CWarEntry &WarEntry) {return &WarEntry == Entry;});
if(it != m_WarEntries.end())
m_WarEntries.erase(it);
}
void CWarList::RemoveWarType(const char *pType)
{
CWarType Type(pType);
auto it = std::find(m_WarTypes.begin(), m_WarTypes.end(), Type);

auto it = std::find_if(m_WarTypes.begin(), m_WarTypes.end(),
[&Type](CWarType *warTypePtr) { return *warTypePtr == Type; });
if(it != m_WarTypes.end())
{
// Don't remove default war types
if(!it->m_Removable)
if(!(*it)->m_Removable)
return;

// Find all war entries and set them to None if they are using this type
for(CWarEntry &Entry : m_WarEntries)
{
if(*Entry.m_pWarType == *it)
if(*Entry.m_pWarType == **it)
{
Entry.m_pWarType = &m_WarTypeNone;
}
Expand All @@ -194,9 +210,10 @@ void CWarList::RemoveWarType(const char *pType)
CWarType *CWarList::FindWarType(const char *pType)
{
CWarType Type(pType);
auto it = std::find(m_WarTypes.begin(), m_WarTypes.end(), Type);
auto it = std::find_if(m_WarTypes.begin(), m_WarTypes.end(),
[&Type](CWarType *warTypePtr) {return *warTypePtr == Type;});
if(it != m_WarTypes.end())
return &(*it);
return *it;
else
return &m_WarTypeNone;
}
Expand Down Expand Up @@ -292,14 +309,14 @@ void CWarList::ConfigSaveCallback(IConfigManager *pConfigManager, void *pUserDat
char aBuf[1024];
for(int i = 0; i < static_cast<int>(pThis->m_WarTypes.size()); i++)
{
CWarType &WarType = pThis->m_WarTypes[i];
CWarType &WarType = *pThis->m_WarTypes[i];

// Imported wartypes don't get saved
if(WarType.m_Imported)
continue;

char aEscapeType[MAX_WARLIST_TYPE_LENGTH * 2];
EscapeParam(aEscapeType, WarType.m_aWarType, sizeof(aEscapeType));
EscapeParam(aEscapeType, WarType.m_aWarName, sizeof(aEscapeType));
ColorHSLA Color = color_cast<ColorHSLA>(WarType.m_Color);

str_format(aBuf, sizeof(aBuf), "update_war_type %d \"%s\" %d", i, aEscapeType, Color.Pack(false));
Expand All @@ -315,7 +332,7 @@ void CWarList::ConfigSaveCallback(IConfigManager *pConfigManager, void *pUserDat
char aEscapeName[MAX_NAME_LENGTH * 2];
char aEscapeClan[MAX_CLAN_LENGTH * 2];
char aEscapeReason[MAX_WARLIST_REASON_LENGTH * 2];
EscapeParam(aEscapeType, Entry.m_pWarType->m_aWarType, sizeof(aEscapeType));
EscapeParam(aEscapeType, Entry.m_pWarType->m_aWarName, sizeof(aEscapeType));
EscapeParam(aEscapeName, Entry.m_aName, sizeof(aEscapeName));
EscapeParam(aEscapeClan, Entry.m_aClan, sizeof(aEscapeClan));
EscapeParam(aEscapeReason, Entry.m_aReason, sizeof(aEscapeReason));
Expand Down
Loading

0 comments on commit fd95899

Please sign in to comment.