262 changes: 151 additions & 111 deletions src/engine/server/server.cpp

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions src/engine/server/server.h
Expand Up @@ -109,6 +109,7 @@ class CServer : public IServer
public:
class IGameServer *GameServer() { return m_pGameServer; }
class CConfig *Config() { return m_pConfig; }
const CConfig *Config() const { return m_pConfig; }
class IConsole *Console() { return m_pConsole; }
class IStorage *Storage() { return m_pStorage; }
class IEngineAntibot *Antibot() { return m_pAntibot; }
Expand Down Expand Up @@ -150,7 +151,6 @@ class CServer : public IServer

// connection state info
int m_State;
bool m_SupportsMapSha256;
int m_Latency;
int m_SnapRate;

Expand Down Expand Up @@ -226,14 +226,12 @@ class CServer : public IServer

int m_RunServer;

int m_MapReload;
bool m_MapReload;
bool m_ReloadedWhenEmpty;
int m_RconClientID;
int m_RconAuthLevel;
int m_PrintCBIndex;

int64_t m_Lastheartbeat;
//static NETADDR4 master_server;
char m_aShutdownReason[128];

enum
{
Expand Down Expand Up @@ -363,7 +361,8 @@ class CServer : public IServer

void PumpNetwork(bool PacketWaiting);

char *GetMapName() const;
virtual void ChangeMap(const char *pMap);
const char *GetMapName() const;
int LoadMap(const char *pMapName);

void SaveDemo(int ClientID, float Time);
Expand Down Expand Up @@ -412,6 +411,7 @@ class CServer : public IServer
static void ConchainRconPasswordChange(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainRconModPasswordChange(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainRconHelperPasswordChange(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainMapUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);

#if defined(CONF_FAMILY_UNIX)
static void ConchainConnLoggingServerChange(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
Expand Down
6 changes: 6 additions & 0 deletions src/engine/server/sql_string_helpers.cpp
Expand Up @@ -42,6 +42,12 @@ int sqlstr::EscapeLike(char *pDst, const char *pSrc, int DstSize)

void sqlstr::AgoTimeToString(int AgoTime, char *pAgoString, int Size)
{
if(AgoTime <= 0)
{
str_copy(pAgoString, "moments", Size);
return;
}

char aBuf[20];
int aTimes[7] =
{
Expand Down
11 changes: 7 additions & 4 deletions src/engine/shared/config_variables.h
Expand Up @@ -12,6 +12,7 @@ MACRO_CONFIG_INT(PlayerCountry, player_country, -1, -1, 1000, CFGFLAG_SAVE | CFG
MACRO_CONFIG_STR(Password, password, 32, "", CFGFLAG_CLIENT | CFGFLAG_SERVER | CFGFLAG_NONTEEHISTORIC, "Password to the server")
MACRO_CONFIG_STR(Logfile, logfile, 128, "", CFGFLAG_SAVE | CFGFLAG_CLIENT | CFGFLAG_SERVER, "Filename to log all output to")
MACRO_CONFIG_INT(ConsoleOutputLevel, console_output_level, 0, 0, 2, CFGFLAG_CLIENT | CFGFLAG_SERVER, "Adjusts the amount of information in the console")
MACRO_CONFIG_INT(ConsoleEnableColors, console_enable_colors, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SERVER, "Enable colors in console output")
MACRO_CONFIG_INT(Events, events, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT | CFGFLAG_SERVER, "Enable triggering of events, (eye emotes on some holidays in server, christmas skins in client).")

MACRO_CONFIG_STR(SteamName, steam_name, 16, "", CFGFLAG_SAVE | CFGFLAG_CLIENT, "Last seen name of the Steam profile")
Expand Down Expand Up @@ -51,7 +52,6 @@ MACRO_CONFIG_INT(BrFilterFriends, br_filter_friends, 0, 0, 1, CFGFLAG_SAVE | CFG
MACRO_CONFIG_INT(BrFilterCountry, br_filter_country, 0, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Filter out servers with non-matching player country")
MACRO_CONFIG_INT(BrFilterCountryIndex, br_filter_country_index, -1, -1, 999, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Player country to filter by in the server browser")
MACRO_CONFIG_INT(BrFilterPw, br_filter_pw, 0, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Filter out password protected servers in browser")
MACRO_CONFIG_INT(BrFilterPing, br_filter_ping, 999, 0, 999, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Ping to filter by in the server browser")
MACRO_CONFIG_STR(BrFilterGametype, br_filter_gametype, 128, "", CFGFLAG_SAVE | CFGFLAG_CLIENT, "Game types to filter")
MACRO_CONFIG_INT(BrFilterGametypeStrict, br_filter_gametype_strict, 0, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Strict gametype filter")
MACRO_CONFIG_INT(BrFilterConnectingPlayers, br_filter_connecting_players, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Filter connecting players")
Expand Down Expand Up @@ -120,7 +120,9 @@ MACRO_CONFIG_INT(GfxRefreshRate, gfx_refresh_rate, 0, 0, 10000, CFGFLAG_SAVE | C
MACRO_CONFIG_INT(GfxFinish, gfx_finish, 0, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "")
MACRO_CONFIG_INT(GfxBackgroundRender, gfx_backgroundrender, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Render graphics when window is in background")
MACRO_CONFIG_INT(GfxTextOverlay, gfx_text_overlay, 10, 1, 100, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Stop rendering textoverlay in editor or with entities: high value = less details = more speed")
#if !defined(CONF_PLATFORM_MACOS)
MACRO_CONFIG_INT(GfxAsyncRenderOld, gfx_asyncrender_old, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Do rendering async from the the update")
#endif
MACRO_CONFIG_INT(GfxTuneOverlay, gfx_tune_overlay, 20, 1, 100, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Stop rendering text overlay in tuning zone in editor: high value = less details = more speed")
MACRO_CONFIG_INT(GfxQuadAsTriangle, gfx_quad_as_triangle, 0, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Render quads as triangles (fixes quad coloring on some GPUs)")

Expand Down Expand Up @@ -233,8 +235,8 @@ MACRO_CONFIG_STR(SvSqlServerName, sv_sql_servername, 5, "UNK", CFGFLAG_SERVER, "
MACRO_CONFIG_INT(SvSaveGames, sv_savegames, 1, 0, 1, CFGFLAG_SERVER, "Enables savegames (/save and /load)")
MACRO_CONFIG_INT(SvSaveSwapGamesDelay, sv_saveswapgames_delay, 30, 0, 10000, CFGFLAG_SERVER, "Delay in seconds for loading a savegame or before swapping")
MACRO_CONFIG_INT(SvSaveSwapGamesPenalty, sv_saveswapgames_penalty, 60, 0, 10000, CFGFLAG_SERVER, "Penalty in seconds for saving or swapping position")
MACRO_CONFIG_INT(SvSwapTimeout, sv_swap_timeout, 30, 0, 10000, CFGFLAG_SERVER, "Timeout in seconds before option to swap expires")
MACRO_CONFIG_INT(SvSwap, sv_swap, 0, 0, 1, CFGFLAG_SERVER, "Enable /swap")
MACRO_CONFIG_INT(SvSwapTimeout, sv_swap_timeout, 180, 0, 10000, CFGFLAG_SERVER, "Timeout in seconds before option to swap expires")
MACRO_CONFIG_INT(SvSwap, sv_swap, 1, 0, 1, CFGFLAG_SERVER, "Enable /swap")
MACRO_CONFIG_INT(SvUseSQL, sv_use_sql, 0, 0, 1, CFGFLAG_SERVER, "Enables MySQL backend instead of SQLite backend (sv_sqlite_file is still used as fallback write server when no MySQL server is reachable)")
MACRO_CONFIG_INT(SvSqlQueriesDelay, sv_sql_queries_delay, 1, 0, 20, CFGFLAG_SERVER, "Delay in seconds between SQL queries of a single player")
MACRO_CONFIG_STR(SvSqliteFile, sv_sqlite_file, 64, "ddnet-server.sqlite", CFGFLAG_SERVER, "File to store ranks in case sv_use_sql is turned off or used as backup sql server")
Expand Down Expand Up @@ -307,6 +309,7 @@ MACRO_CONFIG_INT(ClZoomBackgroundLayers, cl_zoom_background_layers, 0, 0, 1, CFG
MACRO_CONFIG_COL(ClBackgroundColor, cl_background_color, 128, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Background color") //0 0 128
MACRO_CONFIG_COL(ClBackgroundEntitiesColor, cl_background_entities_color, 128, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Background (entities) color") //0 0 128
MACRO_CONFIG_STR(ClBackgroundEntities, cl_background_entities, 100, "", CFGFLAG_CLIENT | CFGFLAG_SAVE, "Background (entities)")
MACRO_CONFIG_STR(ClRunOnJoin, cl_run_on_join, 100, "", CFGFLAG_CLIENT | CFGFLAG_SAVE, "Command to run when joining a server")

// menu background map
MACRO_CONFIG_STR(ClMenuMap, cl_menu_map, 100, "auto", CFGFLAG_CLIENT | CFGFLAG_SAVE, "Background map in the menu")
Expand Down Expand Up @@ -375,7 +378,7 @@ MACRO_CONFIG_INT(ClChatTeamColors, cl_chat_teamcolors, 0, 0, 1, CFGFLAG_CLIENT |
MACRO_CONFIG_INT(ClChatReset, cl_chat_reset, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Reset chat when pressing escape")
MACRO_CONFIG_INT(ClChatOld, cl_chat_old, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Old chat style: No tee, no background");

MACRO_CONFIG_INT(ClShowDirection, cl_show_direction, 1, 0, 2, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Show tee direction")
MACRO_CONFIG_INT(ClShowDirection, cl_show_direction, 1, 0, 2, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Show key presses (1 = other players', 2 = also your own)")
MACRO_CONFIG_INT(ClHttpMapDownload, cl_http_map_download, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Try fast HTTP map download first")
MACRO_CONFIG_INT(ClOldGunPosition, cl_old_gun_position, 0, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Tees hold gun a bit higher like in TW 0.6.1 and older")
MACRO_CONFIG_INT(ClConfirmDisconnectTime, cl_confirm_disconnect_time, 20, -1, 1440, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Confirmation popup before disconnecting after game time (in minutes, -1 to turn off, 0 to always turn on)")
Expand Down
15 changes: 9 additions & 6 deletions src/engine/shared/console.cpp
Expand Up @@ -315,11 +315,14 @@ char *CConsole::Format(char *pBuf, int Size, const char *pFrom, const char *pStr

void CConsole::Print(int Level, const char *pFrom, const char *pStr, ColorRGBA PrintColor)
{
// if the color is pure white, use default terminal color
if(mem_comp(&PrintColor, &gs_ConsoleDefaultColor, sizeof(ColorRGBA)) == 0)
set_console_msg_color(NULL);
else
set_console_msg_color(&PrintColor);
if(g_Config.m_ConsoleEnableColors)
{
// if the color is pure white, use default terminal color
if(mem_comp(&PrintColor, &gs_ConsoleDefaultColor, sizeof(ColorRGBA)) == 0)
set_console_msg_color(NULL);
else
set_console_msg_color(&PrintColor);
}
dbg_msg(pFrom, "%s", pStr);
set_console_msg_color(NULL);
char aBuf[1024];
Expand Down Expand Up @@ -588,7 +591,7 @@ void CConsole::ExecuteFile(const char *pFilename, int ClientID, bool LogFailure,
m_pFirstExec = &ThisFile;

// exec the file
IOHANDLE File = m_pStorage->OpenFile(pFilename, IOFLAG_READ, StorageType);
IOHANDLE File = m_pStorage->OpenFile(pFilename, IOFLAG_READ | IOFLAG_SKIP_BOM, StorageType);

char aBuf[128];
if(File)
Expand Down
2 changes: 2 additions & 0 deletions src/engine/shared/console.h
Expand Up @@ -194,6 +194,8 @@ class CConsole : public IConsole
CCommand *FindCommand(const char *pName, int FlagMask);

public:
CConfig *Config() { return m_pConfig; }

CConsole(int FlagMask);
~CConsole();

Expand Down
2 changes: 1 addition & 1 deletion src/engine/shared/masterserver.cpp
Expand Up @@ -149,7 +149,7 @@ class CMasterServer : public IEngineMasterServer
return -1;

// try to open file
IOHANDLE File = m_pStorage->OpenFile("masters.cfg", IOFLAG_READ, IStorage::TYPE_SAVE);
IOHANDLE File = m_pStorage->OpenFile("masters.cfg", IOFLAG_READ | IOFLAG_SKIP_BOM, IStorage::TYPE_SAVE);
if(!File)
return -1;

Expand Down
2 changes: 1 addition & 1 deletion src/engine/shared/network_conn.cpp
Expand Up @@ -294,7 +294,7 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr, SECURITY_
if(pPacket->m_DataSize > 1)
{
// make sure to sanitize the error string form the other party
str_utf8_copy(aStr, (char *)&pPacket->m_aChunkData[1], minimum(pPacket->m_DataSize, (int)sizeof(aStr)));
str_copy(aStr, (char *)&pPacket->m_aChunkData[1], minimum(pPacket->m_DataSize, (int)sizeof(aStr)));
str_sanitize_cc(aStr);
}

Expand Down
4 changes: 2 additions & 2 deletions src/engine/shared/storage.cpp
Expand Up @@ -92,7 +92,7 @@ class CStorage : public IStorage
void LoadPaths(const char *pArgv0)
{
// check current directory
IOHANDLE File = io_open("storage.cfg", IOFLAG_READ);
IOHANDLE File = io_open("storage.cfg", IOFLAG_READ | IOFLAG_SKIP_BOM);
if(!File)
{
// check usable path in argv[0]
Expand All @@ -105,7 +105,7 @@ class CStorage : public IStorage
char aBuffer[IO_MAX_PATH_LENGTH];
str_copy(aBuffer, pArgv0, Pos + 1);
str_append(aBuffer, "/storage.cfg", sizeof(aBuffer));
File = io_open(aBuffer, IOFLAG_READ);
File = io_open(aBuffer, IOFLAG_READ | IOFLAG_SKIP_BOM);
}

if(Pos >= IO_MAX_PATH_LENGTH || !File)
Expand Down
3 changes: 2 additions & 1 deletion src/engine/shared/uuid_manager.cpp
Expand Up @@ -101,7 +101,8 @@ static int GetID(int Index)

void CUuidManager::RegisterName(int ID, const char *pName)
{
dbg_assert(GetIndex(ID) == m_aNames.size(), "names must be registered with increasing ID");
int Index = GetIndex(ID);
dbg_assert(Index == m_aNames.size(), "names must be registered with increasing ID");
CName Name;
Name.m_pName = pName;
Name.m_Uuid = CalculateUuid(pName);
Expand Down
17 changes: 15 additions & 2 deletions src/game/client/components/binds.cpp
Expand Up @@ -92,6 +92,9 @@ int CBinds::GetModifierMask(IInput *i)
Mask |= i->KeyIsPressed(KEY_LCTRL) << CBinds::MODIFIER_CTRL;
Mask |= i->KeyIsPressed(KEY_RCTRL) << CBinds::MODIFIER_CTRL;
Mask |= i->KeyIsPressed(KEY_LALT) << CBinds::MODIFIER_ALT;
Mask |= i->KeyIsPressed(KEY_RALT) << CBinds::MODIFIER_ALT;
Mask |= i->KeyIsPressed(KEY_LGUI) << CBinds::MODIFIER_GUI;
Mask |= i->KeyIsPressed(KEY_RGUI) << CBinds::MODIFIER_GUI;
if(!Mask)
return 1 << CBinds::MODIFIER_NONE;

Expand All @@ -109,7 +112,11 @@ int CBinds::GetModifierMaskOfKey(int Key)
case KEY_RCTRL:
return 1 << CBinds::MODIFIER_CTRL;
case KEY_LALT:
case KEY_RALT:
return 1 << CBinds::MODIFIER_ALT;
case KEY_LGUI:
case KEY_RGUI:
return 1 << CBinds::MODIFIER_GUI;
default:
return 0;
}
Expand All @@ -124,7 +131,9 @@ bool CBinds::ModifierMatchesKey(int Modifier, int Key)
case MODIFIER_CTRL:
return Key == KEY_LCTRL || Key == KEY_RCTRL;
case MODIFIER_ALT:
return Key == KEY_LALT;
return Key == KEY_LALT || Key == KEY_RALT;
case MODIFIER_GUI:
return Key == KEY_LGUI || Key == KEY_RGUI;
case MODIFIER_NONE:
default:
return false;
Expand Down Expand Up @@ -159,7 +168,7 @@ bool CBinds::OnInput(IInput::CEvent e)
if(m_aapKeyBindings[0][e.m_Key] && !ret)
{
// When ctrl+shift are pressed (ctrl+shift binds and also the hard-coded ctrl+shift+d, ctrl+shift+g, ctrl+shift+e), ignore other +xxx binds
if(e.m_Flags & IInput::FLAG_PRESS && Mask != ((1 << MODIFIER_CTRL) | (1 << MODIFIER_SHIFT)))
if(e.m_Flags & IInput::FLAG_PRESS && Mask != ((1 << MODIFIER_CTRL) | (1 << MODIFIER_SHIFT)) && Mask != ((1 << MODIFIER_GUI) | (1 << MODIFIER_SHIFT)))
Console()->ExecuteLineStroked(1, m_aapKeyBindings[0][e.m_Key]);
if(e.m_Flags & IInput::FLAG_RELEASE)
Console()->ExecuteLineStroked(0, m_aapKeyBindings[0][e.m_Key]);
Expand Down Expand Up @@ -394,6 +403,8 @@ int CBinds::GetBindSlot(const char *pBindString, int *Mod)
*Mod |= (1 << MODIFIER_CTRL);
else if(!str_comp(aMod, "alt"))
*Mod |= (1 << MODIFIER_ALT);
else if(!str_comp(aMod, "gui"))
*Mod |= (1 << MODIFIER_GUI);
else
return 0;

Expand All @@ -415,6 +426,8 @@ const char *CBinds::GetModifierName(int Modifier)
return "ctrl";
case MODIFIER_ALT:
return "alt";
case MODIFIER_GUI:
return "gui";
case MODIFIER_NONE:
default:
return "";
Expand Down
1 change: 1 addition & 0 deletions src/game/client/components/binds.h
Expand Up @@ -38,6 +38,7 @@ class CBinds : public CComponent
MODIFIER_SHIFT,
MODIFIER_CTRL,
MODIFIER_ALT,
MODIFIER_GUI,
MODIFIER_COUNT,
MODIFIER_COMBINATION_COUNT = 1 << MODIFIER_COUNT
};
Expand Down
12 changes: 6 additions & 6 deletions src/game/client/components/chat.cpp
Expand Up @@ -178,7 +178,7 @@ bool CChat::OnInput(IInput::CEvent Event)
if(m_Mode == MODE_NONE)
return false;

if(Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyPress(KEY_V))
if(Input()->ModifierIsPressed() && Input()->KeyPress(KEY_V))
{
const char *Text = Input()->GetClipboardText();
if(Text)
Expand All @@ -192,25 +192,25 @@ bool CChat::OnInput(IInput::CEvent Event)
if(Text[i] == '\n')
{
int max = minimum(i - Begin + 1, (int)sizeof(aLine));
str_utf8_copy(aLine, Text + Begin, max);
str_copy(aLine, Text + Begin, max);
Begin = i + 1;
SayChat(aLine);
while(Text[i] == '\n')
i++;
}
}
int max = minimum(i - Begin + 1, (int)sizeof(aLine));
str_utf8_copy(aLine, Text + Begin, max);
m_Input.Add(aLine);
str_copy(aLine, Text + Begin, max);
m_Input.Append(aLine);
}
}

if(Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyPress(KEY_C))
if(Input()->ModifierIsPressed() && Input()->KeyPress(KEY_C))
{
Input()->SetClipboardText(m_Input.GetString());
}

if(Input()->KeyIsPressed(KEY_LCTRL)) // jump to spaces and special ASCII characters
if(Input()->ModifierIsPressed()) // jump to spaces and special ASCII characters
{
int SearchDirection = 0;
if(Input()->KeyPress(KEY_LEFT) || Input()->KeyPress(KEY_BACKSPACE))
Expand Down
22 changes: 11 additions & 11 deletions src/game/client/components/console.cpp
Expand Up @@ -115,7 +115,7 @@ void CGameConsole::CInstance::OnInput(IInput::CEvent Event)
{
bool Handled = false;

if(m_pGameConsole->Input()->KeyIsPressed(KEY_LCTRL)) // jump to spaces and special ASCII characters
if(m_pGameConsole->Input()->ModifierIsPressed()) // jump to spaces and special ASCII characters
{
int SearchDirection = 0;
if(m_pGameConsole->Input()->KeyPress(KEY_LEFT) || m_pGameConsole->Input()->KeyPress(KEY_BACKSPACE))
Expand Down Expand Up @@ -176,7 +176,7 @@ void CGameConsole::CInstance::OnInput(IInput::CEvent Event)
m_Input.SetCursorOffset(FoundAt);
}
}
if(m_pGameConsole->Input()->KeyIsPressed(KEY_LCTRL) && m_pGameConsole->Input()->KeyPress(KEY_V))
if(m_pGameConsole->Input()->ModifierIsPressed() && m_pGameConsole->Input()->KeyPress(KEY_V))
{
const char *Text = m_pGameConsole->Input()->GetClipboardText();
if(Text)
Expand All @@ -200,28 +200,28 @@ void CGameConsole::CInstance::OnInput(IInput::CEvent Event)
}
int max = minimum(i - Begin + 1, (int)sizeof(aLine));
str_copy(aLine, Text + Begin, max);
m_Input.Add(aLine);
m_Input.Append(aLine);
}
}
else if(m_pGameConsole->Input()->KeyIsPressed(KEY_LCTRL) && m_pGameConsole->Input()->KeyPress(KEY_C))
else if(m_pGameConsole->Input()->ModifierIsPressed() && m_pGameConsole->Input()->KeyPress(KEY_C))
{
m_pGameConsole->Input()->SetClipboardText(m_Input.GetString());
}
else if(m_pGameConsole->Input()->KeyIsPressed(KEY_LCTRL) && m_pGameConsole->Input()->KeyPress(KEY_A))
else if(m_pGameConsole->Input()->ModifierIsPressed() && m_pGameConsole->Input()->KeyPress(KEY_A))
{
m_Input.SetCursorOffset(0);
}
else if(m_pGameConsole->Input()->KeyIsPressed(KEY_LCTRL) && m_pGameConsole->Input()->KeyPress(KEY_E))
else if(m_pGameConsole->Input()->ModifierIsPressed() && m_pGameConsole->Input()->KeyPress(KEY_E))
{
m_Input.SetCursorOffset(m_Input.GetLength());
}
else if(m_pGameConsole->Input()->KeyIsPressed(KEY_LCTRL) && m_pGameConsole->Input()->KeyPress(KEY_U))
else if(m_pGameConsole->Input()->ModifierIsPressed() && m_pGameConsole->Input()->KeyPress(KEY_U))
{
m_Input.DeleteUntilCursor();
m_Input.SetRange("", 0, m_Input.GetCursorOffset());
}
else if(m_pGameConsole->Input()->KeyIsPressed(KEY_LCTRL) && m_pGameConsole->Input()->KeyPress(KEY_K))
else if(m_pGameConsole->Input()->ModifierIsPressed() && m_pGameConsole->Input()->KeyPress(KEY_K))
{
m_Input.DeleteFromCursor();
m_Input.SetRange("", m_Input.GetCursorOffset(), m_Input.GetLength());
}

if(Event.m_Flags & IInput::FLAG_PRESS)
Expand Down Expand Up @@ -681,7 +681,7 @@ void CGameConsole::OnRender()
float LineOffset = 1.0f;

bool WantsSelectionCopy = false;
if(Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyPress(KEY_C))
if(Input()->ModifierIsPressed() && Input()->KeyPress(KEY_C))
WantsSelectionCopy = true;
std::string SelectionString;

Expand Down
2 changes: 1 addition & 1 deletion src/game/client/components/countryflags.cpp
Expand Up @@ -16,7 +16,7 @@

void CCountryFlags::LoadCountryflagsIndexfile()
{
IOHANDLE File = Storage()->OpenFile("countryflags/index.txt", IOFLAG_READ, IStorage::TYPE_ALL);
IOHANDLE File = Storage()->OpenFile("countryflags/index.txt", IOFLAG_READ | IOFLAG_SKIP_BOM, IStorage::TYPE_ALL);
if(!File)
{
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "countryflags", "couldn't open index file");
Expand Down
3 changes: 1 addition & 2 deletions src/game/client/components/hud.cpp
Expand Up @@ -127,8 +127,7 @@ void CHud::RenderGameTimer()

str_time(Time * 100, TIME_DAYS, aBuf, sizeof(aBuf));
float FontSize = 10.0f;
float w;
w = TextRender()->TextWidth(0, 12,
float w = TextRender()->TextWidth(0, FontSize,
Time >= 3600 * 24 ? "00d 00:00:00" : Time >= 3600 ? "00:00:00" : "00:00",
-1, -1.0f);
// last 60 sec red, last 10 sec blink
Expand Down
28 changes: 16 additions & 12 deletions src/game/client/components/items.cpp
Expand Up @@ -325,9 +325,10 @@ void CItems::OnRender()
CProjectileData Data = pProj->GetData();
RenderProjectile(&Data, pProj->ID());
}
for(auto *pLaser = (CLaser *)GameClient()->m_PredictedWorld.FindFirst(CGameWorld::ENTTYPE_LASER); pLaser; pLaser = (CLaser *)pLaser->NextEntity())
for(CEntity *pEnt = GameClient()->m_PredictedWorld.FindFirst(CGameWorld::ENTTYPE_LASER); pEnt; pEnt = pEnt->NextEntity())
{
if(pLaser->GetOwner() < 0 || (pLaser->GetOwner() >= 0 && !GameClient()->m_aClients[pLaser->GetOwner()].m_IsPredictedLocal))
auto *const pLaser = dynamic_cast<CLaser *>(pEnt);
if(!pLaser || pLaser->GetOwner() < 0 || !GameClient()->m_aClients[pLaser->GetOwner()].m_IsPredictedLocal)
continue;
CNetObj_Laser Data;
pLaser->FillInfo(&Data);
Expand Down Expand Up @@ -376,17 +377,20 @@ void CItems::OnRender()
{
if(auto *pProj = (CProjectile *)GameClient()->m_GameWorld.FindMatch(Item.m_ID, Item.m_Type, pData))
{
bool IsOtherTeam = m_pClient->IsOtherTeam(pProj->GetOwner());
if(pProj->m_LastRenderTick <= 0 && (pProj->m_Type != WEAPON_SHOTGUN || (!pProj->m_Freeze && !pProj->m_Explosive)) // skip ddrace shotgun bullets
&& (pProj->m_Type == WEAPON_SHOTGUN || fabs(length(pProj->m_Direction) - 1.f) < 0.02) // workaround to skip grenades on ball mod
&& (pProj->GetOwner() < 0 || !GameClient()->m_aClients[pProj->GetOwner()].m_IsPredictedLocal || IsOtherTeam) // skip locally predicted projectiles
&& !Client()->SnapFindItem(IClient::SNAP_PREV, Item.m_Type, Item.m_ID))
if(pProj->GetOwner() >= 0)
{
ReconstructSmokeTrail(&Data, pProj->m_DestroyTick);
bool IsOtherTeam = m_pClient->IsOtherTeam(pProj->GetOwner());
if(pProj->m_LastRenderTick <= 0 && (pProj->m_Type != WEAPON_SHOTGUN || (!pProj->m_Freeze && !pProj->m_Explosive)) // skip ddrace shotgun bullets
&& (pProj->m_Type == WEAPON_SHOTGUN || fabs(length(pProj->m_Direction) - 1.f) < 0.02) // workaround to skip grenades on ball mod
&& (pProj->GetOwner() < 0 || !GameClient()->m_aClients[pProj->GetOwner()].m_IsPredictedLocal || IsOtherTeam) // skip locally predicted projectiles
&& !Client()->SnapFindItem(IClient::SNAP_PREV, Item.m_Type, Item.m_ID))
{
ReconstructSmokeTrail(&Data, pProj->m_DestroyTick);
}
pProj->m_LastRenderTick = Client()->GameTick(g_Config.m_ClDummy);
if(!IsOtherTeam)
continue;
}
pProj->m_LastRenderTick = Client()->GameTick(g_Config.m_ClDummy);
if(!IsOtherTeam)
continue;
}
}
if(Inactive && (Data.m_Explosive ? BlinkingProjEx : BlinkingProj))
Expand All @@ -411,7 +415,7 @@ void CItems::OnRender()
{
if(UsePredicted)
{
auto *pLaser = (CLaser *)GameClient()->m_GameWorld.FindMatch(Item.m_ID, Item.m_Type, pData);
auto *pLaser = dynamic_cast<CLaser *>(GameClient()->m_GameWorld.FindMatch(Item.m_ID, Item.m_Type, pData));
if(pLaser && pLaser->GetOwner() >= 0 && GameClient()->m_aClients[pLaser->GetOwner()].m_IsPredictedLocal)
continue;
}
Expand Down
2 changes: 1 addition & 1 deletion src/game/client/components/maplayers.cpp
Expand Up @@ -1650,7 +1650,7 @@ void CMapLayers::OnRender()
Render = true;
}

if(Render && pLayer->m_Type == LAYERTYPE_TILES && Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyIsPressed(KEY_LSHIFT) && Input()->KeyPress(KEY_KP_0))
if(Render && pLayer->m_Type == LAYERTYPE_TILES && Input()->ModifierIsPressed() && (Input()->KeyIsPressed(KEY_LSHIFT) || Input()->KeyIsPressed(KEY_RSHIFT)) && Input()->KeyPress(KEY_KP_0))
{
CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer;
CTile *pTiles = (CTile *)m_pLayers->Map()->GetData(pTMap->m_Data);
Expand Down
238 changes: 27 additions & 211 deletions src/game/client/components/menus.cpp
Expand Up @@ -60,7 +60,6 @@ bool CMenus::ms_ValueSelectorTextMode;

float CMenus::ms_ButtonHeight = 25.0f;
float CMenus::ms_ListheaderHeight = 17.0f;
float CMenus::ms_FontmodHeight = 0.8f;

IInput::CEvent CMenus::m_aInputEvents[MAX_INPUTEVENTS];
int CMenus::m_NumInputEvents;
Expand All @@ -79,7 +78,6 @@ CMenus::CMenus()
m_MenuActive = true;
m_ShowStart = true;
m_UseMouseButtons = true;
m_MouseSlow = false;

m_EscapePressed = false;
m_EnterPressed = false;
Expand Down Expand Up @@ -119,15 +117,6 @@ CMenus::CMenus()
}
}

float CMenus::ButtonColorMul(const void *pID)
{
if(UI()->ActiveItem() == pID)
return ButtonColorMulActive();
else if(UI()->HotItem() == pID)
return ButtonColorMulHot();
return ButtonColorMulDefault();
}

int CMenus::DoButton_Icon(int ImageId, int SpriteId, const CUIRect *pRect)
{
int x = pRect->x;
Expand Down Expand Up @@ -199,7 +188,7 @@ int CMenus::DoButton_Menu(const void *pID, const char *pText, int Checked, const
}

if(!MouseInsideColorPicker)
Color.a *= ButtonColorMul(pID);
Color.a *= UI()->ButtonColorMul(pID);
RenderTools()->DrawUIRect(pRect, Color, Corners, r);

if(pImageName)
Expand All @@ -224,7 +213,7 @@ int CMenus::DoButton_Menu(const void *pID, const char *pText, int Checked, const

Text.HMargin(pRect->h >= 20.0f ? 2.0f : 1.0f, &Text);
Text.HMargin((Text.h * FontFactor) / 2.0f, &Text);
UI()->DoLabel(&Text, pText, Text.h * ms_FontmodHeight, 0, -1, AlignVertically);
UI()->DoLabel(&Text, pText, Text.h * CUI::ms_FontmodHeight, 0, -1, AlignVertically);

if(MouseInsideColorPicker)
return 0;
Expand All @@ -234,10 +223,10 @@ int CMenus::DoButton_Menu(const void *pID, const char *pText, int Checked, const

void CMenus::DoButton_KeySelect(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
{
RenderTools()->DrawUIRect(pRect, ColorRGBA(1, 1, 1, 0.5f * ButtonColorMul(pID)), CUI::CORNER_ALL, 5.0f);
RenderTools()->DrawUIRect(pRect, ColorRGBA(1, 1, 1, 0.5f * UI()->ButtonColorMul(pID)), CUI::CORNER_ALL, 5.0f);
CUIRect Temp;
pRect->HMargin(1.0f, &Temp);
UI()->DoLabel(&Temp, pText, Temp.h * ms_FontmodHeight, 0);
UI()->DoLabel(&Temp, pText, Temp.h * CUI::ms_FontmodHeight, 0);
}

int CMenus::DoButton_MenuTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Corners, SUIAnimator *pAnimator, const ColorRGBA *pDefaultColor, const ColorRGBA *pActiveColor, const ColorRGBA *pHoverColor, float EdgeRounding, int AlignVertically)
Expand Down Expand Up @@ -316,7 +305,7 @@ int CMenus::DoButton_MenuTab(const void *pID, const char *pText, int Checked, co
}

Rect.HMargin(2.0f, &Temp);
UI()->DoLabel(&Temp, pText, Temp.h * ms_FontmodHeight, 0, -1, AlignVertically);
UI()->DoLabel(&Temp, pText, Temp.h * CUI::ms_FontmodHeight, 0, -1, AlignVertically);

return UI()->DoButtonLogic(pID, pText, Checked, pRect);
}
Expand All @@ -329,7 +318,7 @@ int CMenus::DoButton_GridHeader(const void *pID, const char *pText, int Checked,
RenderTools()->DrawUIRect(pRect, ColorRGBA(1, 1, 1, 0.5f), CUI::CORNER_T, 5.0f);
CUIRect t;
pRect->VSplitLeft(5.0f, 0, &t);
UI()->DoLabel(&t, pText, pRect->h * ms_FontmodHeight, -1);
UI()->DoLabel(&t, pText, pRect->h * CUI::ms_FontmodHeight, -1);
return UI()->DoButtonLogic(pID, pText, Checked, pRect);
}

Expand All @@ -343,20 +332,20 @@ int CMenus::DoButton_CheckBox_Common(const void *pID, const char *pText, const c
t.VSplitLeft(5.0f, 0, &t);

c.Margin(2.0f, &c);
RenderTools()->DrawUIRect(&c, ColorRGBA(1, 1, 1, 0.25f * ButtonColorMul(pID)), CUI::CORNER_ALL, 3.0f);
RenderTools()->DrawUIRect(&c, ColorRGBA(1, 1, 1, 0.25f * UI()->ButtonColorMul(pID)), CUI::CORNER_ALL, 3.0f);

bool CheckAble = *pBoxText == 'X';
if(CheckAble)
{
TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_OVERSIZE | ETextRenderFlags::TEXT_RENDER_FLAG_NO_PIXEL_ALIGMENT);
TextRender()->SetCurFont(TextRender()->GetFont(TEXT_FONT_ICON_FONT));
UI()->DoLabel(&c, "\xEE\x97\x8D", c.h * ms_FontmodHeight, 0, -1, 0);
UI()->DoLabel(&c, "\xEE\x97\x8D", c.h * CUI::ms_FontmodHeight, 0, -1, 0);
TextRender()->SetCurFont(NULL);
}
else
UI()->DoLabel(&c, pBoxText, c.h * ms_FontmodHeight, 0, -1, 0);
UI()->DoLabel(&c, pBoxText, c.h * CUI::ms_FontmodHeight, 0, -1, 0);
TextRender()->SetRenderFlags(0);
UI()->DoLabel(&t, pText, c.h * ms_FontmodHeight, -1);
UI()->DoLabel(&t, pText, c.h * CUI::ms_FontmodHeight, -1);

return UI()->DoButtonLogic(pID, pText, 0, pRect);
}
Expand Down Expand Up @@ -519,7 +508,7 @@ int CMenus::DoValueSelector(void *pID, CUIRect *pRect, const char *pLabel, bool
if(ms_ValueSelectorTextMode && s_LastTextpID == pID)
{
static float s_NumberBoxID = 0;
DoEditBox(&s_NumberBoxID, pRect, s_NumStr, sizeof(s_NumStr), 10.0f, &s_NumberBoxID, false, CUI::CORNER_ALL);
UIEx()->DoEditBox(&s_NumberBoxID, pRect, s_NumStr, sizeof(s_NumStr), 10.0f, &s_NumberBoxID, false, CUI::CORNER_ALL);

UI()->SetActiveItem(&s_NumberBoxID);

Expand Down Expand Up @@ -606,169 +595,6 @@ int CMenus::DoValueSelector(void *pID, CUIRect *pRect, const char *pLabel, bool
return Current;
}

int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *Offset, bool Hidden, int Corners, const char *pEmptyText)
{
return m_UIEx.DoEditBox(pID, pRect, pStr, StrSize, FontSize, Offset, Hidden, Corners, pEmptyText);
}

int CMenus::DoClearableEditBox(void *pID, void *pClearID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *Offset, bool Hidden, int Corners, const char *pEmptyText)
{
bool ReturnValue = false;
CUIRect EditBox;
CUIRect ClearButton;
pRect->VSplitRight(15.0f, &EditBox, &ClearButton);
if(DoEditBox(pID, &EditBox, pStr, StrSize, FontSize, Offset, Hidden, Corners & ~CUI::CORNER_R, pEmptyText))
{
ReturnValue = true;
}

TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_PIXEL_ALIGMENT);
RenderTools()->DrawUIRect(&ClearButton, ColorRGBA(1, 1, 1, 0.33f * ButtonColorMul(pClearID)), Corners & ~CUI::CORNER_L, 3.0f);
UI()->DoLabel(&ClearButton, "Ă—", ClearButton.h * ms_FontmodHeight, 0, -1, 0);
TextRender()->SetRenderFlags(0);
if(UI()->DoButtonLogic(pClearID, "Ă—", 0, &ClearButton))
{
pStr[0] = 0;
UI()->SetActiveItem(pID);
ReturnValue = true;
}
return ReturnValue;
}

float CMenus::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current)
{
CUIRect Handle;
static float OffsetY;
pRect->HSplitTop(33, &Handle, 0);

Current = clamp(Current, 0.0f, 1.0f);
Handle.y = pRect->y + (pRect->h - Handle.h) * Current;

// logic
float ReturnValue = Current;
int Inside = UI()->MouseInside(&Handle);

if(UI()->ActiveItem() == pID)
{
if(!UI()->MouseButton(0))
UI()->SetActiveItem(0);

if(Input()->KeyIsPressed(KEY_LSHIFT) || Input()->KeyIsPressed(KEY_RSHIFT))
m_MouseSlow = true;

float Min = pRect->y;
float Max = pRect->h - Handle.h;
float Cur = UI()->MouseY() - OffsetY;
ReturnValue = (Cur - Min) / Max;
if(ReturnValue < 0.0f)
ReturnValue = 0.0f;
if(ReturnValue > 1.0f)
ReturnValue = 1.0f;
}
else if(UI()->HotItem() == pID)
{
if(UI()->MouseButton(0))
{
UI()->SetActiveItem(pID);
OffsetY = UI()->MouseY() - Handle.y;
}
}

if(Inside)
UI()->SetHotItem(pID);

// render
RenderTools()->DrawUIRect(pRect, ColorRGBA(0, 0, 0, 0.25f), CUI::CORNER_ALL, 5.0f);

float ColorSlider = 0;

if(UI()->ActiveItem() == pID)
ColorSlider = 1.0f;
else if(UI()->HotItem() == pID)
ColorSlider = 0.9f;
else
ColorSlider = 0.75f;

RenderTools()->DrawUIRect(&Handle, ColorRGBA(ColorSlider, ColorSlider, ColorSlider, 0.75f), CUI::CORNER_ALL, 5.0f);

return ReturnValue;
}

float CMenus::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current, bool ColorPickerSlider, ColorRGBA *pColorInner)
{
CUIRect Handle;
static float OffsetX;
pRect->VSplitLeft(ColorPickerSlider ? 8 : 33, &Handle, 0);

Handle.x += (pRect->w - Handle.w) * Current;

// logic
float ReturnValue = Current;
int Inside = UI()->MouseInside(&Handle);

if(UI()->ActiveItem() == pID)
{
if(!UI()->MouseButton(0))
UI()->SetActiveItem(0);

if(Input()->KeyIsPressed(KEY_LSHIFT) || Input()->KeyIsPressed(KEY_RSHIFT))
m_MouseSlow = true;

float Min = pRect->x;
float Max = pRect->w - Handle.w;
float Cur = UI()->MouseX() - OffsetX;
ReturnValue = (Cur - Min) / Max;
if(ReturnValue < 0.0f)
ReturnValue = 0.0f;
if(ReturnValue > 1.0f)
ReturnValue = 1.0f;
}
else if(UI()->HotItem() == pID)
{
if(UI()->MouseButton(0))
{
UI()->SetActiveItem(pID);
OffsetX = UI()->MouseX() - Handle.x;
}
}

if(Inside)
UI()->SetHotItem(pID);

// render
if(!ColorPickerSlider)
{
CUIRect Rail;
pRect->HMargin(5.0f, &Rail);
RenderTools()->DrawUIRect(&Rail, ColorRGBA(1, 1, 1, 0.25f), 0, 0.0f);

CUIRect Slider = Handle;
Slider.h = Rail.y - Slider.y;
RenderTools()->DrawUIRect(&Slider, ColorRGBA(1, 1, 1, 0.25f), CUI::CORNER_T, 2.5f);
Slider.y = Rail.y + Rail.h;
RenderTools()->DrawUIRect(&Slider, ColorRGBA(1, 1, 1, 0.25f), CUI::CORNER_B, 2.5f);

Slider = Handle;
Slider.Margin(5.0f, &Slider);
RenderTools()->DrawUIRect(&Slider, ColorRGBA(1, 1, 1, 0.25f * ButtonColorMul(pID)), CUI::CORNER_ALL, 2.5f);
}
else
{
CUIRect Slider = Handle;
float MarginW = 4.0f;
float MarginH = 9.0f;
Slider.x -= MarginW / 2;
Slider.y -= MarginH / 2;
Slider.w += MarginW;
Slider.h += MarginH;
RenderTools()->DrawUIRect(&Slider, ColorRGBA(0.15f, 0.15f, 0.15f, 1.0f), CUI::CORNER_ALL, 5.0f);
Slider.Margin(2, &Slider);
RenderTools()->DrawUIRect(&Slider, *pColorInner, CUI::CORNER_ALL, 3.0f);
}

return ReturnValue;
}

int CMenus::DoKeyReader(void *pID, const CUIRect *pRect, int Key, int Modifier, int *NewModifier)
{
// process
Expand Down Expand Up @@ -1186,7 +1012,7 @@ void CMenus::OnInit()
if(g_Config.m_ClSkipStartMenu)
m_ShowStart = false;

m_UIEx.Init(UI(), Kernel(), RenderTools(), m_aInputEvents, &m_NumInputEvents);
UIEx()->Init(UI(), Kernel(), RenderTools(), m_aInputEvents, &m_NumInputEvents);

m_RefreshButton.Init(UI(), -1);
m_ConnectButton.Init(UI(), -1);
Expand Down Expand Up @@ -1452,8 +1278,7 @@ int CMenus::Render()

CUIRect Screen = *UI()->Screen();
UI()->MapScreen();

m_MouseSlow = false;
UIEx()->ResetMouseSlow();

static int s_Frame = 0;
if(s_Frame == 0)
Expand Down Expand Up @@ -1898,8 +1723,8 @@ int CMenus::Render()
TextBox.VSplitLeft(20.0f, 0, &TextBox);
TextBox.VSplitRight(60.0f, &TextBox, 0);
UI()->DoLabel(&Label, Localize("Password"), 18.0f, -1);
static float Offset = 0.0f;
DoEditBox(&g_Config.m_Password, &TextBox, g_Config.m_Password, sizeof(g_Config.m_Password), 12.0f, &Offset, true);
static float s_Offset = 0.0f;
UIEx()->DoEditBox(&g_Config.m_Password, &TextBox, g_Config.m_Password, sizeof(g_Config.m_Password), 12.0f, &s_Offset, true);
}
else if(m_Popup == POPUP_CONNECTING)
{
Expand Down Expand Up @@ -2129,8 +1954,8 @@ int CMenus::Render()
TextBox.VSplitLeft(20.0f, 0, &TextBox);
TextBox.VSplitRight(60.0f, &TextBox, 0);
UI()->DoLabel(&Label, Localize("New name:"), 18.0f, -1);
static float Offset = 0.0f;
DoEditBox(&Offset, &TextBox, m_aCurrentDemoFile, sizeof(m_aCurrentDemoFile), 12.0f, &Offset);
static float s_Offset = 0.0f;
UIEx()->DoEditBox(&s_Offset, &TextBox, m_aCurrentDemoFile, sizeof(m_aCurrentDemoFile), 12.0f, &s_Offset);
}
#if defined(CONF_VIDEORECORDER)
else if(m_Popup == POPUP_RENDER_DEMO)
Expand Down Expand Up @@ -2253,8 +2078,8 @@ int CMenus::Render()
TextBox.VSplitLeft(20.0f, 0, &TextBox);
TextBox.VSplitRight(60.0f, &TextBox, 0);
UI()->DoLabel(&Label, Localize("Video name:"), 18.0f, -1);
static float Offset = 0.0f;
DoEditBox(&Offset, &TextBox, m_aCurrentDemoFile, sizeof(m_aCurrentDemoFile), 12.0f, &Offset);
static float s_Offset = 0.0f;
UIEx()->DoEditBox(&s_Offset, &TextBox, m_aCurrentDemoFile, sizeof(m_aCurrentDemoFile), 12.0f, &s_Offset);
}
else if(m_Popup == POPUP_REPLACE_VIDEO)
{
Expand Down Expand Up @@ -2360,8 +2185,8 @@ int CMenus::Render()
TextBox.VSplitLeft(20.0f, 0, &TextBox);
TextBox.VSplitRight(60.0f, &TextBox, 0);
UI()->DoLabel(&Label, Localize("Nickname"), 16.0f, -1);
static float Offset = 0.0f;
DoEditBox(&g_Config.m_PlayerName, &TextBox, g_Config.m_PlayerName, sizeof(g_Config.m_PlayerName), 12.0f, &Offset, false, CUI::CORNER_ALL, Client()->PlayerName());
static float s_Offset = 0.0f;
UIEx()->DoEditBox(&g_Config.m_PlayerName, &TextBox, g_Config.m_PlayerName, sizeof(g_Config.m_PlayerName), 12.0f, &s_Offset, false, CUI::CORNER_ALL, Client()->PlayerName());
}
else if(m_Popup == POPUP_POINTS)
{
Expand Down Expand Up @@ -2500,7 +2325,7 @@ void CMenus::RenderThemeSelection(CUIRect MainView, bool Header)
else // generic
str_format(aName, sizeof(aName), "%s", Theme.m_Name.cstr());

UI()->DoLabel(&Item.m_Rect, aName, 16 * ms_FontmodHeight, -1);
UI()->DoLabel(&Item.m_Rect, aName, 16 * CUI::ms_FontmodHeight, -1);
}

bool ItemActive = false;
Expand Down Expand Up @@ -2555,19 +2380,10 @@ bool CMenus::OnMouseMove(float x, float y)
if(!m_MenuActive)
return false;

UI()->ConvertMouseMove(&x, &y);
if(m_MouseSlow)
{
m_MousePos.x += x * 0.05f;
m_MousePos.y += y * 0.05f;
}
else
{
m_MousePos.x += x;
m_MousePos.y += y;
}
m_MousePos.x = clamp(m_MousePos.x, 0.f, (float)Graphics()->WindowWidth());
m_MousePos.y = clamp(m_MousePos.y, 0.f, (float)Graphics()->WindowHeight());
UIEx()->ConvertMouseMove(&x, &y);

m_MousePos.x = clamp(m_MousePos.x + x, 0.f, (float)Graphics()->WindowWidth());
m_MousePos.y = clamp(m_MousePos.y + y, 0.f, (float)Graphics()->WindowHeight());

return true;
}
Expand Down Expand Up @@ -2797,7 +2613,7 @@ void CMenus::RenderBackground()
bool CMenus::CheckHotKey(int Key) const
{
return m_Popup == POPUP_NONE &&
!Input()->KeyIsPressed(KEY_LSHIFT) && !Input()->KeyIsPressed(KEY_RSHIFT) && !Input()->KeyIsPressed(KEY_LCTRL) && !Input()->KeyIsPressed(KEY_RCTRL) && !Input()->KeyIsPressed(KEY_LALT) && // no modifier
!Input()->KeyIsPressed(KEY_LSHIFT) && !Input()->KeyIsPressed(KEY_RSHIFT) && !Input()->ModifierIsPressed() && // no modifier
Input()->KeyIsPressed(Key) && m_pClient->m_GameConsole.IsClosed();
}

Expand Down
37 changes: 5 additions & 32 deletions src/game/client/components/menus.h
Expand Up @@ -75,10 +75,7 @@ class CMenus : public CComponent

CUIEx m_UIEx;

float ButtonColorMulActive() { return 0.5f; }
float ButtonColorMulHot() { return 1.5f; }
float ButtonColorMulDefault() { return 1.0f; }
float ButtonColorMul(const void *pID);
CUIEx *UIEx() { return &m_UIEx; }

int DoButton_DemoPlayer(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
int DoButton_Sprite(const void *pID, int ImageID, int SpriteID, int Checked, const CUIRect *pRect, int Corners);
Expand All @@ -92,32 +89,13 @@ class CMenus : public CComponent
int DoButton_CheckBox_Number(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
ColorHSLA DoLine_ColorPicker(int *pResetID, const float LineSize, const float WantedPickerPosition, const float LabelSize, const float BottomMargin, CUIRect *pMainRect, const char *pText, unsigned int *pColorValue, const ColorRGBA DefaultColor, bool CheckBoxSpacing = true, bool UseCheckBox = false, int *pCheckBoxValue = NULL);
void DoLaserPreview(const CUIRect *pRect, const ColorHSLA OutlineColor, const ColorHSLA InnerColor);
/*static void ui_draw_menu_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra);
static void ui_draw_keyselect_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra);
static void ui_draw_menu_tab_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra);
static void ui_draw_settings_tab_button(const void *id, const char *text, int checked, const CUIRect *r, const void *extra);
*/
int DoValueSelector(void *pID, CUIRect *pRect, const char *pLabel, bool UseScroll, int Current, int Min, int Max, int Step, float Scale, bool IsHex, float Round, ColorRGBA *Color);
int DoButton_Icon(int ImageId, int SpriteId, const CUIRect *pRect);
int DoButton_GridHeader(const void *pID, const char *pText, int Checked, const CUIRect *pRect);

//static void ui_draw_browse_icon(int what, const CUIRect *r);
//static void ui_draw_grid_header(const void *id, const char *text, int checked, const CUIRect *r, const void *extra);

/*static void ui_draw_checkbox_common(const void *id, const char *text, const char *boxtext, const CUIRect *r, const void *extra);
static void ui_draw_checkbox(const void *id, const char *text, int checked, const CUIRect *r, const void *extra);
static void ui_draw_checkbox_number(const void *id, const char *text, int checked, const CUIRect *r, const void *extra);
*/
int DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *Offset, bool Hidden = false, int Corners = CUI::CORNER_ALL, const char *pEmptyText = "");
int DoClearableEditBox(void *pID, void *pClearID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *Offset, bool Hidden = false, int Corners = CUI::CORNER_ALL, const char *pEmptyText = "");
//static int ui_do_edit_box(void *id, const CUIRect *rect, char *str, unsigned str_size, float font_size, bool hidden=false);

float DoScrollbarV(const void *pID, const CUIRect *pRect, float Current);
float DoScrollbarH(const void *pID, const CUIRect *pRect, float Current, bool ColorPickerSlider = false, ColorRGBA *pColorInner = NULL);
void DoButton_KeySelect(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
int DoKeyReader(void *pID, const CUIRect *pRect, int Key, int Modifier, int *NewModifier);

//static int ui_do_key_reader(void *id, const CUIRect *rect, int key);
void UiDoGetButtons(int Start, int Stop, CUIRect View, CUIRect ScopeView);

void RenderColorPicker();
Expand Down Expand Up @@ -168,11 +146,11 @@ class CMenus : public CComponent
{
Color.a = RealColor.a;
if(i == 0)
Color.a *= ButtonColorMulActive();
Color.a *= UI()->ButtonColorMulActive();
else if(i == 1)
Color.a *= ButtonColorMulHot();
Color.a *= UI()->ButtonColorMulHot();
else if(i == 2)
Color.a *= ButtonColorMulDefault();
Color.a *= UI()->ButtonColorMulDefault();
Graphics()->SetColor(Color);

CUIElement::SUIElementRect &NewRect = *UIElement.Get(i);
Expand All @@ -187,7 +165,7 @@ class CMenus : public CComponent
if(pText == NULL)
pText = GetTextLambda();
NewRect.m_Text = pText;
UI()->DoLabel(NewRect, &Text, pText, Text.h * ms_FontmodHeight, 0, -1, AlignVertically);
UI()->DoLabel(NewRect, &Text, pText, Text.h * CUI::ms_FontmodHeight, 0, -1, AlignVertically);
}
}
Graphics()->SetColor(1, 1, 1, 1);
Expand Down Expand Up @@ -224,9 +202,6 @@ class CMenus : public CComponent

int UiLogicGetCurrentClickedItem();

//static void demolist_listdir_callback(const char *name, int is_dir, void *user);
//static void demolist_list_callback(const CUIRect *rect, int index, void *user);

// menus_settings_assets.cpp
public:
struct SCustomItem
Expand Down Expand Up @@ -287,7 +262,6 @@ class CMenus : public CComponent
bool m_MenuActive;
bool m_UseMouseButtons;
vec2 m_MousePos;
bool m_MouseSlow;

char m_aNextServer[256];

Expand Down Expand Up @@ -330,7 +304,6 @@ class CMenus : public CComponent
static float ms_ButtonHeight;
static float ms_ListheaderHeight;
static float ms_ListitemAdditionalHeight;
static float ms_FontmodHeight;

// for settings
bool m_NeedRestartGeneral;
Expand Down
54 changes: 17 additions & 37 deletions src/game/client/components/menus_browser.cpp
Expand Up @@ -171,7 +171,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
RenderTools()->DrawUIRect(&View, ColorRGBA(0, 0, 0, 0.15f), 0, 0);

CUIRect Scroll;
View.VSplitRight(10, &View, &Scroll);
View.VSplitRight(20.0f, &View, &Scroll);

int NumServers = ServerBrowser()->NumSortedServers();

Expand All @@ -188,10 +188,9 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
UI()->DoLabelScaled(&MsgBox, Localize("No servers match your filter criteria"), 16.0f, 0);
}

static int s_ScrollBar = 0;
static float s_ScrollValue = 0;

s_ScrollValue = DoScrollbarV(&s_ScrollBar, &Scroll, s_ScrollValue);
s_ScrollValue = UIEx()->DoScrollbarV(&s_ScrollValue, &Scroll, s_ScrollValue);

if(Input()->KeyPress(KEY_TAB) && m_pClient->m_GameConsole.IsClosed())
{
Expand Down Expand Up @@ -529,11 +528,11 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
QuickSearch.VSplitLeft(SearchExcludeAddrStrMax, 0, &QuickSearch);
QuickSearch.VSplitLeft(5.0f, 0, &QuickSearch);

static float Offset = 0.0f;
if(Input()->KeyPress(KEY_F) && (Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL)))
if(Input()->KeyPress(KEY_F) && Input()->ModifierIsPressed())
UI()->SetActiveItem(&g_Config.m_BrFilterString);
static int s_ClearButton = 0;
if(DoClearableEditBox(&g_Config.m_BrFilterString, &s_ClearButton, &QuickSearch, g_Config.m_BrFilterString, sizeof(g_Config.m_BrFilterString), 12.0f, &Offset, false, CUI::CORNER_ALL))
static float s_Offset = 0.0f;
if(UIEx()->DoClearableEditBox(&g_Config.m_BrFilterString, &s_ClearButton, &QuickSearch, g_Config.m_BrFilterString, sizeof(g_Config.m_BrFilterString), 12.0f, &s_Offset, false, CUI::CORNER_ALL))
Client()->ServerBrowserUpdate();
}

Expand All @@ -554,10 +553,10 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
QuickExclude.VSplitLeft(5.0f, 0, &QuickExclude);

static int s_ClearButton = 0;
static float Offset = 0.0f;
if(Input()->KeyPress(KEY_X) && (Input()->KeyPress(KEY_LSHIFT) || Input()->KeyPress(KEY_RSHIFT)) && (Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL)))
static float s_Offset = 0.0f;
if(Input()->KeyPress(KEY_X) && (Input()->KeyIsPressed(KEY_LSHIFT) || Input()->KeyIsPressed(KEY_RSHIFT)) && Input()->ModifierIsPressed())
UI()->SetActiveItem(&g_Config.m_BrExcludeString);
if(DoClearableEditBox(&g_Config.m_BrExcludeString, &s_ClearButton, &QuickExclude, g_Config.m_BrExcludeString, sizeof(g_Config.m_BrExcludeString), 12.0f, &Offset, false, CUI::CORNER_ALL))
if(UIEx()->DoClearableEditBox(&g_Config.m_BrExcludeString, &s_ClearButton, &QuickExclude, g_Config.m_BrExcludeString, sizeof(g_Config.m_BrExcludeString), 12.0f, &s_Offset, false, CUI::CORNER_ALL))
Client()->ServerBrowserUpdate();
}

Expand Down Expand Up @@ -590,8 +589,8 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
UI()->DoLabelScaled(&ServerAddr, Localize("Server address:"), 14.0f, -1);
ServerAddr.VSplitLeft(SearchExcludeAddrStrMax + 5.0f + ExcludeSearchIconMax + 5.0f, NULL, &ServerAddr);
static int s_ClearButton = 0;
static float Offset = 0.0f;
DoClearableEditBox(&g_Config.m_UiServerAddress, &s_ClearButton, &ServerAddr, g_Config.m_UiServerAddress, sizeof(g_Config.m_UiServerAddress), 12.0f, &Offset);
static float s_Offset = 0.0f;
UIEx()->DoClearableEditBox(&g_Config.m_UiServerAddress, &s_ClearButton, &ServerAddr, g_Config.m_UiServerAddress, sizeof(g_Config.m_UiServerAddress), 12.0f, &s_Offset);

// button area
ButtonArea = ConnectButtons;
Expand All @@ -612,7 +611,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
return m_aLocalStringHelper;
};

if(DoButtonMenu(m_RefreshButton, &s_RefreshButton, Func, 0, &ButtonRefresh, true, false, CUI::CORNER_ALL) || Input()->KeyPress(KEY_F5) || (Input()->KeyPress(KEY_R) && (Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL))))
if(DoButtonMenu(m_RefreshButton, &s_RefreshButton, Func, 0, &ButtonRefresh, true, false, CUI::CORNER_ALL) || Input()->KeyPress(KEY_F5) || (Input()->KeyPress(KEY_R) && Input()->ModifierIsPressed()))
{
if(g_Config.m_UiPage == PAGE_INTERNET)
ServerBrowser()->Refresh(IServerBrowser::TYPE_INTERNET);
Expand Down Expand Up @@ -705,35 +704,17 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
UI()->DoLabelScaled(&Button, Localize("Game types:"), FontSize, -1);
Button.VSplitRight(60.0f, 0, &Button);
ServerFilter.HSplitTop(3.0f, 0, &ServerFilter);
static float Offset = 0.0f;
if(DoEditBox(&g_Config.m_BrFilterGametype, &Button, g_Config.m_BrFilterGametype, sizeof(g_Config.m_BrFilterGametype), FontSize, &Offset))
static float s_OffsetGametype = 0.0f;
if(UIEx()->DoEditBox(&g_Config.m_BrFilterGametype, &Button, g_Config.m_BrFilterGametype, sizeof(g_Config.m_BrFilterGametype), FontSize, &s_OffsetGametype))
Client()->ServerBrowserUpdate();

{
ServerFilter.HSplitTop(19.0f, &Button, &ServerFilter);
CUIRect EditBox;
Button.VSplitRight(60.0f, &Button, &EditBox);

UI()->DoLabelScaled(&Button, Localize("Maximum ping:"), FontSize, -1);

char aBuf[5] = "";
if(g_Config.m_BrFilterPing != 0)
str_format(aBuf, sizeof(aBuf), "%d", g_Config.m_BrFilterPing);
static float Offset = 0.0f;
if(DoEditBox(&g_Config.m_BrFilterPing, &EditBox, aBuf, sizeof(aBuf), FontSize, &Offset))
{
g_Config.m_BrFilterPing = clamp(str_toint(aBuf), 0, 999);
Client()->ServerBrowserUpdate();
}
}

// server address
ServerFilter.HSplitTop(3.0f, 0, &ServerFilter);
ServerFilter.HSplitTop(19.0f, &Button, &ServerFilter);
UI()->DoLabelScaled(&Button, Localize("Server address:"), FontSize, -1);
Button.VSplitRight(60.0f, 0, &Button);
static float OffsetAddr = 0.0f;
if(DoEditBox(&g_Config.m_BrFilterServerAddress, &Button, g_Config.m_BrFilterServerAddress, sizeof(g_Config.m_BrFilterServerAddress), FontSize, &OffsetAddr))
static float s_OffsetAddr = 0.0f;
if(UIEx()->DoEditBox(&g_Config.m_BrFilterServerAddress, &Button, g_Config.m_BrFilterServerAddress, sizeof(g_Config.m_BrFilterServerAddress), FontSize, &s_OffsetAddr))
Client()->ServerBrowserUpdate();

// player country
Expand Down Expand Up @@ -1021,7 +1002,6 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
g_Config.m_BrFilterCountry = 0;
g_Config.m_BrFilterCountryIndex = -1;
g_Config.m_BrFilterPw = 0;
g_Config.m_BrFilterPing = 999;
g_Config.m_BrFilterGametype[0] = 0;
g_Config.m_BrFilterGametypeStrict = 0;
g_Config.m_BrFilterConnectingPlayers = 1;
Expand Down Expand Up @@ -1367,7 +1347,7 @@ void CMenus::RenderServerbrowserFriends(CUIRect View)
Button.VSplitLeft(80.0f, 0, &Button);
static char s_aName[MAX_NAME_LENGTH] = {0};
static float s_OffsetName = 0.0f;
DoEditBox(&s_aName, &Button, s_aName, sizeof(s_aName), FontSize + 2, &s_OffsetName);
UIEx()->DoEditBox(&s_aName, &Button, s_aName, sizeof(s_aName), FontSize + 2, &s_OffsetName);

ServerFriends.HSplitTop(3.0f, 0, &ServerFriends);
ServerFriends.HSplitTop(19.0f, &Button, &ServerFriends);
Expand All @@ -1376,7 +1356,7 @@ void CMenus::RenderServerbrowserFriends(CUIRect View)
Button.VSplitLeft(80.0f, 0, &Button);
static char s_aClan[MAX_CLAN_LENGTH] = {0};
static float s_OffsetClan = 0.0f;
DoEditBox(&s_aClan, &Button, s_aClan, sizeof(s_aClan), FontSize + 2, &s_OffsetClan);
UIEx()->DoEditBox(&s_aClan, &Button, s_aClan, sizeof(s_aClan), FontSize + 2, &s_OffsetClan);

ServerFriends.HSplitTop(3.0f, 0, &ServerFriends);
ServerFriends.HSplitTop(20.0f, &Button, &ServerFriends);
Expand Down
27 changes: 11 additions & 16 deletions src/game/client/components/menus_demo.cpp
Expand Up @@ -26,14 +26,14 @@

int CMenus::DoButton_DemoPlayer(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
{
RenderTools()->DrawUIRect(pRect, ColorRGBA(1, 1, 1, (Checked ? 0.10f : 0.5f) * ButtonColorMul(pID)), CUI::CORNER_ALL, 5.0f);
RenderTools()->DrawUIRect(pRect, ColorRGBA(1, 1, 1, (Checked ? 0.10f : 0.5f) * UI()->ButtonColorMul(pID)), CUI::CORNER_ALL, 5.0f);
UI()->DoLabel(pRect, pText, 14.0f, 0);
return UI()->DoButtonLogic(pID, pText, Checked, pRect);
}

int CMenus::DoButton_Sprite(const void *pID, int ImageID, int SpriteID, int Checked, const CUIRect *pRect, int Corners)
{
RenderTools()->DrawUIRect(pRect, ColorRGBA(1.0f, 1.0f, 1.0f, (Checked ? 0.10f : 0.5f) * ButtonColorMul(pID)), Corners, 5.0f);
RenderTools()->DrawUIRect(pRect, ColorRGBA(1.0f, 1.0f, 1.0f, (Checked ? 0.10f : 0.5f) * UI()->ButtonColorMul(pID)), Corners, 5.0f);
Graphics()->TextureSet(g_pData->m_aImages[ImageID].m_Id);
Graphics()->QuadsBegin();
if(!Checked)
Expand Down Expand Up @@ -158,8 +158,8 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
TextBox.VSplitLeft(20.0f, 0, &TextBox);
TextBox.VSplitRight(60.0f, &TextBox, 0);
UI()->DoLabel(&Label, Localize("New name:"), 18.0f, -1);
static float Offset = 0.0f;
if(DoEditBox(&Offset, &TextBox, m_aCurrentDemoFile, sizeof(m_aCurrentDemoFile), 12.0f, &Offset))
static float s_Offset = 0.0f;
if(UIEx()->DoEditBox(&s_Offset, &TextBox, m_aCurrentDemoFile, sizeof(m_aCurrentDemoFile), 12.0f, &s_Offset))
{
m_aDemoPlayerPopupHint[0] = '\0';
}
Expand Down Expand Up @@ -527,7 +527,7 @@ void CMenus::UiDoListboxStart(const void *pID, const CUIRect *pRect, float RowHe
RenderTools()->DrawUIRect(&View, ColorRGBA(0, 0, 0, 0.15f), CUI::CORNER_ALL, 5.0f);
}

View.VSplitRight(10, &View, &Scroll);
View.VSplitRight(20.0f, &View, &Scroll);

// setup the variables
gs_ListBoxOriginalView = View;
Expand Down Expand Up @@ -563,7 +563,7 @@ void CMenus::UiDoListboxStart(const void *pID, const CUIRect *pRect, float RowHe
if(Num == 0)
gs_ListBoxScrollValue = 0;
else
gs_ListBoxScrollValue = clamp(DoScrollbarV(pID, &Scroll, gs_ListBoxScrollValue), 0.0f, 1.0f);
gs_ListBoxScrollValue = UIEx()->DoScrollbarV(pID, &Scroll, gs_ListBoxScrollValue);

// the list
gs_ListBoxView = gs_ListBoxOriginalView;
Expand Down Expand Up @@ -1069,13 +1069,10 @@ void CMenus::RenderDemoList(CUIRect MainView)

// scrollbar
CUIRect Scroll;
ListBox.VSplitRight(15, &ListBox, &Scroll);
ListBox.VSplitRight(20.0f, &ListBox, &Scroll);

static int s_ScrollBar = 0;
static float s_ScrollValue = 0;

Scroll.HMargin(5.0f, &Scroll);
s_ScrollValue = DoScrollbarV(&s_ScrollBar, &Scroll, s_ScrollValue);
s_ScrollValue = UIEx()->DoScrollbarV(&s_ScrollValue, &Scroll, s_ScrollValue);

int PreviousIndex = m_DemolistSelectedIndex;
HandleListInputs(ListBox, s_ScrollValue, 3.0f, &m_ScrollOffset, s_aCols[0].m_Rect.h, m_DemolistSelectedIndex, m_lDemos.size());
Expand Down Expand Up @@ -1205,7 +1202,7 @@ void CMenus::RenderDemoList(CUIRect MainView)
}

static int s_RefreshButton = 0;
if(DoButton_Menu(&s_RefreshButton, Localize("Refresh"), 0, &RefreshRect) || Input()->KeyPress(KEY_F5) || (Input()->KeyPress(KEY_R) && (Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL))))
if(DoButton_Menu(&s_RefreshButton, Localize("Refresh"), 0, &RefreshRect) || Input()->KeyPress(KEY_F5) || (Input()->KeyPress(KEY_R) && Input()->ModifierIsPressed()))
{
DemolistPopulate();
DemolistOnUpdate(false);
Expand Down Expand Up @@ -1257,13 +1254,11 @@ void CMenus::RenderDemoList(CUIRect MainView)
if(DoButton_Menu(&s_DirectoryButtonID, Localize("Demos directory"), 0, &DirectoryButton))
{
char aBuf[IO_MAX_PATH_LENGTH];
char aBufFull[IO_MAX_PATH_LENGTH + 7];
Storage()->GetCompletePath(IStorage::TYPE_SAVE, "demos", aBuf, sizeof(aBuf));
Storage()->CreateFolder("demos", IStorage::TYPE_SAVE);
str_format(aBufFull, sizeof(aBufFull), "file://%s", aBuf);
if(!open_link(aBufFull))
if(!open_file(aBuf))
{
dbg_msg("menus", "couldn't open link");
dbg_msg("menus", "couldn't open file");
}
}

Expand Down
28 changes: 11 additions & 17 deletions src/game/client/components/menus_ingame.cpp
Expand Up @@ -683,17 +683,13 @@ void CMenus::RenderServerControl(CUIRect MainView)
QuickSearch.VSplitLeft(wSearch, 0, &QuickSearch);
QuickSearch.VSplitLeft(5.0f, 0, &QuickSearch);
static int s_ClearButton = 0;
static float Offset = 0.0f;
//static char aFilterString[25];
if(m_ControlPageOpening || (Input()->KeyPress(KEY_F) && (Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL))))
static float s_Offset = 0.0f;
if(m_ControlPageOpening || (Input()->KeyPress(KEY_F) && Input()->ModifierIsPressed()))
{
UI()->SetActiveItem(&m_aFilterString);
m_ControlPageOpening = false;
}
if(DoClearableEditBox(&m_aFilterString, &s_ClearButton, &QuickSearch, m_aFilterString, sizeof(m_aFilterString), 14.0f, &Offset, false, CUI::CORNER_ALL, Localize("Search")))
{
// TODO: Implement here
}
UIEx()->DoClearableEditBox(&m_aFilterString, &s_ClearButton, &QuickSearch, m_aFilterString, sizeof(m_aFilterString), 14.0f, &s_Offset, false, CUI::CORNER_ALL, Localize("Search"));
}

Bottom.VSplitRight(120.0f, &Bottom, &Button);
Expand Down Expand Up @@ -738,9 +734,9 @@ void CMenus::RenderServerControl(CUIRect MainView)
float w = TextRender()->TextWidth(0, 14.0f, pLabel, -1, -1.0f);
Reason.VSplitLeft(w + 10.0f, 0, &Reason);
static float s_Offset = 0.0f;
if(Input()->KeyPress(KEY_R) && (Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL)))
if(Input()->KeyPress(KEY_R) && Input()->ModifierIsPressed())
UI()->SetActiveItem(&m_aCallvoteReason);
DoEditBox(&m_aCallvoteReason, &Reason, m_aCallvoteReason, sizeof(m_aCallvoteReason), 14.0f, &s_Offset, false, CUI::CORNER_ALL);
UIEx()->DoEditBox(&m_aCallvoteReason, &Reason, m_aCallvoteReason, sizeof(m_aCallvoteReason), 14.0f, &s_Offset, false, CUI::CORNER_ALL);

// extended features (only available when authed in rcon)
if(Client()->RconAuthed())
Expand Down Expand Up @@ -811,11 +807,11 @@ void CMenus::RenderServerControl(CUIRect MainView)
Bottom.VSplitLeft(5.0f, 0, &Bottom);
Bottom.VSplitLeft(250.0f, &Button, &Bottom);
static float s_OffsetDesc = 0.0f;
DoEditBox(&s_aVoteDescription, &Button, s_aVoteDescription, sizeof(s_aVoteDescription), 14.0f, &s_OffsetDesc, false, CUI::CORNER_ALL);
UIEx()->DoEditBox(&s_aVoteDescription, &Button, s_aVoteDescription, sizeof(s_aVoteDescription), 14.0f, &s_OffsetDesc, false, CUI::CORNER_ALL);

Bottom.VMargin(20.0f, &Button);
static float s_OffsetCmd = 0.0f;
DoEditBox(&s_aVoteCommand, &Button, s_aVoteCommand, sizeof(s_aVoteCommand), 14.0f, &s_OffsetCmd, false, CUI::CORNER_ALL);
UIEx()->DoEditBox(&s_aVoteCommand, &Button, s_aVoteCommand, sizeof(s_aVoteCommand), 14.0f, &s_OffsetCmd, false, CUI::CORNER_ALL);
}
}
}
Expand Down Expand Up @@ -1033,15 +1029,13 @@ void CMenus::RenderGhost(CUIRect MainView)
RenderTools()->DrawUIRect(&View, ColorRGBA(0, 0, 0, 0.15f), 0, 0);

CUIRect Scroll;
View.VSplitRight(10, &View, &Scroll);
View.VSplitRight(20.0f, &View, &Scroll);

int NumGhosts = m_lGhosts.size();
static int s_ScrollBar = 0;
static float s_ScrollValue = 0;
static int s_SelectedIndex = 0;

s_ScrollValue = DoScrollbarV(&s_ScrollBar, &Scroll, s_ScrollValue);
s_ScrollValue = UIEx()->DoScrollbarV(&s_ScrollValue, &Scroll, s_ScrollValue);

int NumGhosts = m_lGhosts.size();
static int s_SelectedIndex = 0;
HandleListInputs(View, s_ScrollValue, 1.0f, nullptr, s_aCols[0].m_Rect.h, s_SelectedIndex, NumGhosts);

// set clipping
Expand Down
174 changes: 95 additions & 79 deletions src/game/client/components/menus_settings.cpp

Large diffs are not rendered by default.

11 changes: 5 additions & 6 deletions src/game/client/components/menus_settings_assets.cpp
Expand Up @@ -520,10 +520,10 @@ void CMenus::RenderSettingsCustom(CUIRect MainView)
QuickSearch.VSplitLeft(5.0f, 0, &QuickSearch);
QuickSearch.VSplitLeft(QuickSearch.w - 15.0f, &QuickSearch, &QuickSearchClearButton);
static int s_ClearButton = 0;
static float Offset = 0.0f;
if(Input()->KeyPress(KEY_F) && (Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL)))
static float s_Offset = 0.0f;
if(Input()->KeyPress(KEY_F) && Input()->ModifierIsPressed())
UI()->SetActiveItem(&s_aFilterString[s_CurCustomTab]);
if(DoClearableEditBox(&s_aFilterString[s_CurCustomTab], &s_ClearButton, &QuickSearch, s_aFilterString[s_CurCustomTab], sizeof(s_aFilterString[0]), 14.0f, &Offset, false, CUI::CORNER_ALL, Localize("Search")))
if(UIEx()->DoClearableEditBox(&s_aFilterString[s_CurCustomTab], &s_ClearButton, &QuickSearch, s_aFilterString[s_CurCustomTab], sizeof(s_aFilterString[0]), 14.0f, &s_Offset, false, CUI::CORNER_ALL, Localize("Search")))
s_InitCustomList[s_CurCustomTab] = true;
}

Expand All @@ -547,10 +547,9 @@ void CMenus::RenderSettingsCustom(CUIRect MainView)
Storage()->GetCompletePath(IStorage::TYPE_SAVE, aBufFull, aBuf, sizeof(aBuf));
Storage()->CreateFolder("assets", IStorage::TYPE_SAVE);
Storage()->CreateFolder(aBufFull, IStorage::TYPE_SAVE);
str_format(aBufFull, sizeof(aBufFull), "file://%s", aBuf);
if(!open_link(aBufFull))
if(!open_file(aBuf))
{
dbg_msg("menus", "couldn't open link");
dbg_msg("menus", "couldn't open file");
}
}

Expand Down
45 changes: 22 additions & 23 deletions src/game/client/components/players.cpp
Expand Up @@ -542,34 +542,33 @@ void CPlayers::RenderPlayer(

Graphics()->SetColor(1.0f, 1.0f, 1.0f, Alpha);
Graphics()->QuadsSetRotation(0);
int ShowDirection = g_Config.m_ClShowDirection;
#if defined(CONF_VIDEORECORDER)
if((((!IVideo::Current() && (g_Config.m_ClShowDirection >= 1)) || (IVideo::Current() && g_Config.m_ClVideoShowDirection)) && ClientID >= 0) || DemoPlayer()->IsPlaying())
#else
if((g_Config.m_ClShowDirection >= 1 && ClientID >= 0) || DemoPlayer()->IsPlaying())
if(IVideo::Current())
ShowDirection = g_Config.m_ClVideoShowDirection;
#endif
vec2 ShowDirectionPos(Position.x - 11.0f, Position.y - 70.f);
if((Local && ShowDirection == 2) || (!Local && ShowDirection >= 1))
{
if((Local && g_Config.m_ClShowDirection == 2) || (!Local && g_Config.m_ClShowDirection >= 1))
if(Player.m_Direction == -1)
{
if(Player.m_Direction == -1)
{
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_ARROW].m_Id);
Graphics()->QuadsSetRotation(pi);
Graphics()->RenderQuadContainerAsSprite(m_DirectionQuadContainerIndex, 0, Position.x - 30.f, Position.y - 70.f);
}
else if(Player.m_Direction == 1)
{
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_ARROW].m_Id);
Graphics()->RenderQuadContainerAsSprite(m_DirectionQuadContainerIndex, 0, Position.x + 30.f, Position.y - 70.f);
}
if(Player.m_Jumped & 1)
{
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_ARROW].m_Id);
Graphics()->QuadsSetRotation(pi * 3 / 2);
Graphics()->RenderQuadContainerAsSprite(m_DirectionQuadContainerIndex, 0, Position.x, Position.y - 70.f);
}
Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
Graphics()->QuadsSetRotation(0);
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_ARROW].m_Id);
Graphics()->QuadsSetRotation(pi);
Graphics()->RenderQuadContainerAsSprite(m_DirectionQuadContainerIndex, 0, ShowDirectionPos.x - 30.f, ShowDirectionPos.y);
}
else if(Player.m_Direction == 1)
{
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_ARROW].m_Id);
Graphics()->RenderQuadContainerAsSprite(m_DirectionQuadContainerIndex, 0, ShowDirectionPos.x + 30.f, ShowDirectionPos.y);
}
if(Player.m_Jumped & 1)
{
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_ARROW].m_Id);
Graphics()->QuadsSetRotation(pi * 3 / 2);
Graphics()->RenderQuadContainerAsSprite(m_DirectionQuadContainerIndex, 0, ShowDirectionPos.x, ShowDirectionPos.y);
}
Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
Graphics()->QuadsSetRotation(0);
}

if(OtherTeam || ClientID < 0)
Expand Down
2 changes: 1 addition & 1 deletion src/game/client/components/scoreboard.cpp
Expand Up @@ -206,7 +206,7 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch
pTitle = Localize("Game over");
else
{
str_utf8_copy(aBuf, Client()->GetCurrentMap(), sizeof(aBuf));
str_copy(aBuf, Client()->GetCurrentMap(), sizeof(aBuf));
while(TextRender()->TextWidth(0, TitleFontsize, aBuf, -1, -1.0f) > TitleWidth)
aBuf[str_length(aBuf) - 1] = '\0';
if(str_comp(aBuf, Client()->GetCurrentMap()))
Expand Down
6 changes: 3 additions & 3 deletions src/game/client/gameclient.cpp
Expand Up @@ -219,7 +219,7 @@ void CGameClient::OnInit()
m_pGraphics->AddWindowResizeListener(OnWindowResizeCB, this);

// propagate pointers
m_UI.SetGraphics(Graphics(), TextRender());
m_UI.Init(Graphics(), TextRender());

m_RenderTools.Init(Graphics(), UI(), this);

Expand Down Expand Up @@ -735,7 +735,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker, bool IsDummy)

if(MsgId == NETMSGTYPE_SV_READYTOENTER)
{
Client()->EnterGame();
Client()->EnterGame(IsDummy ? !g_Config.m_ClDummy : g_Config.m_ClDummy);
}
else if(MsgId == NETMSGTYPE_SV_EMOTICON)
{
Expand Down Expand Up @@ -1408,7 +1408,7 @@ void CGameClient::OnNewSnapshot()
else if(Item.m_Type == NETOBJTYPE_SWITCHSTATE)
{
const CNetObj_SwitchState *pSwitchStateData = (const CNetObj_SwitchState *)pData;
int Team = Item.m_ID;
int Team = clamp(Item.m_ID, 0, MAX_CLIENTS - 1);

int NumSwitchers = clamp(pSwitchStateData->m_NumSwitchers, 0, 255);
if(!Collision()->m_pSwitchers || NumSwitchers != Collision()->m_NumSwitchers)
Expand Down
91 changes: 48 additions & 43 deletions src/game/client/lineinput.cpp
@@ -1,5 +1,9 @@
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
/* If you are missing that file, acquire a complete release at teeworlds.com. */
#include <base/math.h>
#include <base/system.h>
#include <base/tl/base.h>

#include "lineinput.h"
#include <engine/keys.h>

Expand All @@ -10,23 +14,47 @@ CLineInput::CLineInput()

void CLineInput::Clear()
{
mem_zero(m_aStr, sizeof(m_aStr));
m_Len = 0;
m_CursorPos = 0;
m_NumChars = 0;
Set("");
}

void CLineInput::Set(const char *pString)
{
str_copy(m_aStr, pString, sizeof(m_aStr));
m_Len = str_length(m_aStr);
str_utf8_stats(m_aStr, MAX_SIZE, MAX_CHARS, &m_Len, &m_NumChars);
m_CursorPos = m_Len;
m_NumChars = 0;
int Offset = 0;
while(pString[Offset])
}

void CLineInput::SetRange(const char *pString, int Begin, int End)
{
if(Begin > End)
swap(Begin, End);
Begin = clamp(Begin, 0, m_Len);
End = clamp(End, 0, m_Len);

int RemovedCharSize, RemovedCharCount;
str_utf8_stats(m_aStr + Begin, End - Begin + 1, MAX_CHARS, &RemovedCharSize, &RemovedCharCount);

int AddedCharSize, AddedCharCount;
str_utf8_stats(pString, MAX_SIZE - m_Len + RemovedCharSize, MAX_CHARS - m_NumChars + RemovedCharCount, &AddedCharSize, &AddedCharCount);

if(RemovedCharSize || AddedCharSize)
{
Offset = str_utf8_forward(pString, Offset);
++m_NumChars;
if(AddedCharSize < RemovedCharSize)
{
if(AddedCharSize)
mem_copy(m_aStr + Begin, pString, AddedCharSize);
mem_move(m_aStr + Begin + AddedCharSize, m_aStr + Begin + RemovedCharSize, m_Len - Begin - AddedCharSize);
}
else if(AddedCharSize > RemovedCharSize)
mem_move(m_aStr + End + AddedCharSize - RemovedCharSize, m_aStr + End, m_Len - End);

if(AddedCharSize >= RemovedCharSize)
mem_copy(m_aStr + Begin, pString, AddedCharSize);

m_CursorPos = End - RemovedCharSize + AddedCharSize;
m_Len += AddedCharSize - RemovedCharSize;
m_NumChars += AddedCharCount - RemovedCharCount;
m_aStr[m_Len] = '\0';
}
}

Expand All @@ -46,13 +74,14 @@ void CLineInput::Editing(const char *pString, int Cursor)
m_FakeCursorPos = m_CursorPos + Cursor + 1;
}

void CLineInput::Add(const char *pString)
void CLineInput::Insert(const char *pString, int Begin)
{
if((int)sizeof(m_aStr) - m_Len <= str_length(pString))
return;
str_copy(m_aStr + m_Len, pString, sizeof(m_aStr) - m_Len);
m_Len = str_length(m_aStr);
m_CursorPos = m_Len;
SetRange(pString, Begin, Begin);
}

void CLineInput::Append(const char *pString)
{
Insert(pString, m_Len);
}

static bool IsNotAWordChar(signed char c)
Expand All @@ -75,15 +104,7 @@ int32_t CLineInput::Manipulate(IInput::CEvent Event, char *pStr, int StrMaxSize,
// gather string stats
int CharCount = 0;
int CharSize = 0;
while(Event.m_aText[CharSize])
{
int NewCharSize = str_utf8_forward(Event.m_aText, CharSize);
if(NewCharSize != CharSize)
{
++CharCount;
CharSize = NewCharSize;
}
}
str_utf8_stats(Event.m_aText, MAX_SIZE, MAX_CHARS, &CharSize, &CharCount);

// add new string
if(CharCount)
Expand Down Expand Up @@ -133,7 +154,7 @@ int32_t CLineInput::Manipulate(IInput::CEvent Event, char *pStr, int StrMaxSize,
}
else if(Key == KEY_LEFT)
{
if(ModifierKey == KEY_LCTRL)
if(ModifierKey == KEY_LCTRL || ModifierKey == KEY_RCTRL || ModifierKey == KEY_LGUI || ModifierKey == KEY_RGUI)
{
bool MovedCursor = false;
int OldCursorPos = CursorPos;
Expand All @@ -160,7 +181,7 @@ int32_t CLineInput::Manipulate(IInput::CEvent Event, char *pStr, int StrMaxSize,
}
else if(Key == KEY_RIGHT)
{
if(ModifierKey == KEY_LCTRL)
if(ModifierKey == KEY_LCTRL || ModifierKey == KEY_RCTRL || ModifierKey == KEY_LGUI || ModifierKey == KEY_RGUI)
{
bool WasNonWordChar = IsNotAWordChar(pStr[CursorPos]);
while((!WasNonWordChar && !IsNotAWordChar(pStr[CursorPos])) || (WasNonWordChar && IsNotAWordChar(pStr[CursorPos])))
Expand Down Expand Up @@ -197,22 +218,6 @@ int32_t CLineInput::Manipulate(IInput::CEvent Event, char *pStr, int StrMaxSize,
return Changes;
}

void CLineInput::DeleteUntilCursor()
{
char aBuf[MAX_SIZE];
str_copy(aBuf, &m_aStr[m_CursorPos], sizeof(aBuf));
Set(aBuf);
SetCursorOffset(0);
}

void CLineInput::DeleteFromCursor()
{
char aBuf[MAX_SIZE];
str_copy(aBuf, m_aStr, sizeof(aBuf));
aBuf[m_CursorPos] = '\0';
Set(aBuf);
}

void CLineInput::ProcessInput(IInput::CEvent e)
{
Manipulate(e, m_aStr, MAX_SIZE, MAX_CHARS, &m_Len, &m_CursorPos, &m_NumChars, 0, 0);
Expand Down
13 changes: 3 additions & 10 deletions src/game/client/lineinput.h
Expand Up @@ -40,25 +40,18 @@ class CLineInput
};
static int32_t Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int StrMaxChars, int *pStrLenPtr, int *pCursorPosPtr, int *pNumCharsPtr, int32_t ModifyFlags, int ModifierKey);

class CCallback
{
public:
virtual ~CCallback() {}
virtual bool Event(IInput::CEvent e) = 0;
};

CLineInput();
void Clear();
void ProcessInput(IInput::CEvent e);
void Editing(const char *pString, int Cursor);
void Set(const char *pString);
void Add(const char *pString);
void SetRange(const char *pString, int Begin, int End);
void Insert(const char *pString, int Begin);
void Append(const char *pString);
const char *GetString(bool Editing = false) const { return Editing ? m_DisplayStr : m_aStr; }
int GetLength(bool Editing = false) const { return Editing ? m_FakeLen : m_Len; }
int GetCursorOffset(bool Editing = false) const { return Editing ? m_FakeCursorPos : m_CursorPos; }
void SetCursorOffset(int Offset) { m_CursorPos = Offset > m_Len ? m_Len : Offset < 0 ? 0 : Offset; }
void DeleteUntilCursor();
void DeleteFromCursor();
};

#endif
24 changes: 12 additions & 12 deletions src/game/client/prediction/entities/character.cpp
Expand Up @@ -704,62 +704,62 @@ void CCharacter::HandleTiles(int Index)
}

// handle switch tiles
if(Collision()->IsSwitch(MapIndex) == TILE_FREEZE && Team() != TEAM_SUPER)
if(Collision()->GetSwitchType(MapIndex) == TILE_FREEZE && Team() != TEAM_SUPER)
{
if(Collision()->GetSwitchNumber(MapIndex) == 0 || Collision()->m_pSwitchers[Collision()->GetSwitchNumber(MapIndex)].m_Status[Team()])
Freeze(Collision()->GetSwitchDelay(MapIndex));
}
else if(Collision()->IsSwitch(MapIndex) == TILE_DFREEZE && Team() != TEAM_SUPER)
else if(Collision()->GetSwitchType(MapIndex) == TILE_DFREEZE && Team() != TEAM_SUPER)
{
if(Collision()->GetSwitchNumber(MapIndex) == 0 || Collision()->m_pSwitchers[Collision()->GetSwitchNumber(MapIndex)].m_Status[Team()])
m_DeepFreeze = true;
}
else if(Collision()->IsSwitch(MapIndex) == TILE_DUNFREEZE && Team() != TEAM_SUPER)
else if(Collision()->GetSwitchType(MapIndex) == TILE_DUNFREEZE && Team() != TEAM_SUPER)
{
if(Collision()->GetSwitchNumber(MapIndex) == 0 || Collision()->m_pSwitchers[Collision()->GetSwitchNumber(MapIndex)].m_Status[Team()])
m_DeepFreeze = false;
}
else if(Collision()->IsSwitch(MapIndex) == TILE_HIT_ENABLE && m_Hit & DISABLE_HIT_HAMMER && Collision()->GetSwitchDelay(MapIndex) == WEAPON_HAMMER)
else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_ENABLE && m_Hit & DISABLE_HIT_HAMMER && Collision()->GetSwitchDelay(MapIndex) == WEAPON_HAMMER)
{
m_Hit &= ~DISABLE_HIT_HAMMER;
m_Core.m_NoHammerHit = false;
}
else if(Collision()->IsSwitch(MapIndex) == TILE_HIT_DISABLE && !(m_Hit & DISABLE_HIT_HAMMER) && Collision()->GetSwitchDelay(MapIndex) == WEAPON_HAMMER)
else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_DISABLE && !(m_Hit & DISABLE_HIT_HAMMER) && Collision()->GetSwitchDelay(MapIndex) == WEAPON_HAMMER)
{
m_Hit |= DISABLE_HIT_HAMMER;
m_Core.m_NoHammerHit = true;
}
else if(Collision()->IsSwitch(MapIndex) == TILE_HIT_ENABLE && m_Hit & DISABLE_HIT_SHOTGUN && Collision()->GetSwitchDelay(MapIndex) == WEAPON_SHOTGUN)
else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_ENABLE && m_Hit & DISABLE_HIT_SHOTGUN && Collision()->GetSwitchDelay(MapIndex) == WEAPON_SHOTGUN)
{
m_Hit &= ~DISABLE_HIT_SHOTGUN;
m_Core.m_NoShotgunHit = false;
}
else if(Collision()->IsSwitch(MapIndex) == TILE_HIT_DISABLE && !(m_Hit & DISABLE_HIT_SHOTGUN) && Collision()->GetSwitchDelay(MapIndex) == WEAPON_SHOTGUN)
else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_DISABLE && !(m_Hit & DISABLE_HIT_SHOTGUN) && Collision()->GetSwitchDelay(MapIndex) == WEAPON_SHOTGUN)
{
m_Hit |= DISABLE_HIT_SHOTGUN;
m_Core.m_NoShotgunHit = true;
}
else if(Collision()->IsSwitch(MapIndex) == TILE_HIT_ENABLE && m_Hit & DISABLE_HIT_GRENADE && Collision()->GetSwitchDelay(MapIndex) == WEAPON_GRENADE)
else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_ENABLE && m_Hit & DISABLE_HIT_GRENADE && Collision()->GetSwitchDelay(MapIndex) == WEAPON_GRENADE)
{
m_Hit &= ~DISABLE_HIT_GRENADE;
m_Core.m_NoGrenadeHit = false;
}
else if(Collision()->IsSwitch(MapIndex) == TILE_HIT_DISABLE && !(m_Hit & DISABLE_HIT_GRENADE) && Collision()->GetSwitchDelay(MapIndex) == WEAPON_GRENADE)
else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_DISABLE && !(m_Hit & DISABLE_HIT_GRENADE) && Collision()->GetSwitchDelay(MapIndex) == WEAPON_GRENADE)
{
m_Hit |= DISABLE_HIT_GRENADE;
m_Core.m_NoGrenadeHit = true;
}
else if(Collision()->IsSwitch(MapIndex) == TILE_HIT_ENABLE && m_Hit & DISABLE_HIT_LASER && Collision()->GetSwitchDelay(MapIndex) == WEAPON_LASER)
else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_ENABLE && m_Hit & DISABLE_HIT_LASER && Collision()->GetSwitchDelay(MapIndex) == WEAPON_LASER)
{
m_Hit &= ~DISABLE_HIT_LASER;
m_Core.m_NoLaserHit = false;
}
else if(Collision()->IsSwitch(MapIndex) == TILE_HIT_DISABLE && !(m_Hit & DISABLE_HIT_LASER) && Collision()->GetSwitchDelay(MapIndex) == WEAPON_LASER)
else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_DISABLE && !(m_Hit & DISABLE_HIT_LASER) && Collision()->GetSwitchDelay(MapIndex) == WEAPON_LASER)
{
m_Hit |= DISABLE_HIT_LASER;
m_Core.m_NoLaserHit = true;
}
else if(Collision()->IsSwitch(MapIndex) == TILE_JUMP)
else if(Collision()->GetSwitchType(MapIndex) == TILE_JUMP)
{
int newJumps = Collision()->GetSwitchDelay(MapIndex);
if(newJumps != m_Core.m_Jumps)
Expand Down
7 changes: 4 additions & 3 deletions src/game/client/prediction/gameworld.cpp
Expand Up @@ -446,14 +446,15 @@ void CGameWorld::NetObjAdd(int ObjID, int ObjType, const void *pObjData, const C
{
CLaser NetLaser = CLaser(this, ObjID, (CNetObj_Laser *)pObjData);
CLaser *pMatching = 0;
if(CLaser *pLaser = (CLaser *)GetEntity(ObjID, ENTTYPE_LASER))
if(CLaser *pLaser = dynamic_cast<CLaser *>(GetEntity(ObjID, ENTTYPE_LASER)))
if(NetLaser.Match(pLaser))
pMatching = pLaser;
if(!pMatching)
{
for(CLaser *pLaser = (CLaser *)FindFirst(CGameWorld::ENTTYPE_LASER); pLaser; pLaser = (CLaser *)pLaser->TypeNext())
for(CEntity *pEnt = FindFirst(CGameWorld::ENTTYPE_LASER); pEnt; pEnt = pEnt->TypeNext())
{
if(pLaser->m_ID == -1 && NetLaser.Match(pLaser))
auto *const pLaser = dynamic_cast<CLaser *>(pEnt);
if(pLaser && pLaser->m_ID == -1 && NetLaser.Match(pLaser))
{
pMatching = pLaser;
pMatching->m_ID = ObjID;
Expand Down
2 changes: 1 addition & 1 deletion src/game/client/projectile_data.cpp
Expand Up @@ -49,7 +49,7 @@ CProjectileData ExtractProjectileInfoDDNet(const CNetObj_DDNetProjectile *pProj,

Result.m_ExtraInfo = true;
Result.m_Owner = pProj->m_Data & 255;
if(pProj->m_Data & PROJECTILEFLAG_NO_OWNER)
if(pProj->m_Data & PROJECTILEFLAG_NO_OWNER || Result.m_Owner < 0 || Result.m_Owner >= MAX_CLIENTS)
{
Result.m_Owner = -1;
}
Expand Down
34 changes: 27 additions & 7 deletions src/game/client/ui.cpp
Expand Up @@ -42,12 +42,20 @@ void CUIElement::SUIElementRect::Reset()
UI
*********************************************************/

float CUI::ms_FontmodHeight = 0.8f;

void CUI::Init(class IGraphics *pGraphics, class ITextRender *pTextRender)
{
m_pGraphics = pGraphics;
m_pTextRender = pTextRender;
}

CUI::CUI()
{
m_pHotItem = 0;
m_pActiveItem = 0;
m_pLastActiveItem = 0;
m_pBecommingHotItem = 0;
m_pBecomingHotItem = 0;

m_MouseX = 0;
m_MouseY = 0;
Expand Down Expand Up @@ -128,18 +136,16 @@ int CUI::Update(float Mx, float My, float Mwx, float Mwy, int Buttons)
m_MouseWorldY = Mwy;
m_LastMouseButtons = m_MouseButtons;
m_MouseButtons = Buttons;
m_pHotItem = m_pBecommingHotItem;
m_pHotItem = m_pBecomingHotItem;
if(m_pActiveItem)
m_pHotItem = m_pActiveItem;
m_pBecommingHotItem = 0;
m_pBecomingHotItem = 0;
return 0;
}

int CUI::MouseInside(const CUIRect *r) const
bool CUI::MouseInside(const CUIRect *pRect) const
{
if(m_MouseX >= r->x && m_MouseX < r->x + r->w && m_MouseY >= r->y && m_MouseY < r->y + r->h)
return 1;
return 0;
return pRect->Inside(m_MouseX, m_MouseY);
}

void CUI::ConvertMouseMove(float *x, float *y) const
Expand All @@ -149,6 +155,15 @@ void CUI::ConvertMouseMove(float *x, float *y) const
*y = *y * Fac;
}

float CUI::ButtonColorMul(const void *pID)
{
if(ActiveItem() == pID)
return ButtonColorMulActive();
else if(HotItem() == pID)
return ButtonColorMulHot();
return ButtonColorMulDefault();
}

CUIRect *CUI::Screen()
{
float Aspect = Graphics()->ScreenAspect();
Expand Down Expand Up @@ -367,6 +382,11 @@ void CUIRect::HMargin(float Cut, CUIRect *pOtherRect) const
pOtherRect->h = r.h - 2 * Cut;
}

bool CUIRect::Inside(float x, float y) const
{
return x >= this->x && x < this->x + this->w && y >= this->y && y < this->y + this->h;
}

int CUI::DoButtonLogic(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
{
return DoButtonLogic(pID, Checked, pRect);
Expand Down
23 changes: 14 additions & 9 deletions src/game/client/ui.h
Expand Up @@ -100,6 +100,8 @@ class CUIRect
* @param pOtherRect The CUIRect to place inside *this* CUIRect
*/
void HMargin(float Cut, CUIRect *pOtherRect) const;

bool Inside(float x, float y) const;
};

struct SUIAnimator
Expand Down Expand Up @@ -180,7 +182,7 @@ class CUI
const void *m_pHotItem;
const void *m_pActiveItem;
const void *m_pLastActiveItem;
const void *m_pBecommingHotItem;
const void *m_pBecomingHotItem;
float m_MouseX, m_MouseY; // in gui space
float m_MouseDeltaX, m_MouseDeltaY; // in gui space
float m_MouseWorldX, m_MouseWorldY; // in world space
Expand All @@ -195,12 +197,10 @@ class CUI
std::vector<CUIElement *> m_UIElements;

public:
static float ms_FontmodHeight;

// TODO: Refactor: Fill this in
void SetGraphics(class IGraphics *pGraphics, class ITextRender *pTextRender)
{
m_pGraphics = pGraphics;
m_pTextRender = pTextRender;
}
void Init(class IGraphics *pGraphics, class ITextRender *pTextRender);
class IGraphics *Graphics() const { return m_pGraphics; }
class ITextRender *TextRender() const { return m_pTextRender; }

Expand Down Expand Up @@ -243,7 +243,7 @@ class CUI
int MouseButtonClicked(int Index) const { return MouseButton(Index) && !((m_LastMouseButtons >> Index) & 1); }
int MouseButtonReleased(int Index) const { return ((m_LastMouseButtons >> Index) & 1) && !MouseButton(Index); }

void SetHotItem(const void *pID) { m_pBecommingHotItem = pID; }
void SetHotItem(const void *pID) { m_pBecomingHotItem = pID; }
void SetActiveItem(const void *pID)
{
m_pActiveItem = pID;
Expand All @@ -252,13 +252,18 @@ class CUI
}
void ClearLastActiveItem() { m_pLastActiveItem = 0; }
const void *HotItem() const { return m_pHotItem; }
const void *NextHotItem() const { return m_pBecommingHotItem; }
const void *NextHotItem() const { return m_pBecomingHotItem; }
const void *ActiveItem() const { return m_pActiveItem; }
const void *LastActiveItem() const { return m_pLastActiveItem; }

int MouseInside(const CUIRect *pRect) const;
bool MouseInside(const CUIRect *pRect) const;
void ConvertMouseMove(float *x, float *y) const;

float ButtonColorMulActive() { return 0.5f; }
float ButtonColorMulHot() { return 1.5f; }
float ButtonColorMulDefault() { return 1.0f; }
float ButtonColorMul(const void *pID);

CUIRect *Screen();
void MapScreen();
float PixelSize();
Expand Down
238 changes: 219 additions & 19 deletions src/game/client/ui_ex.cpp
Expand Up @@ -13,9 +13,9 @@

#include <limits>

CUIEx::CUIEx(CUI *pUI, IKernel *pKernel, CRenderTools *pRenderTools, IInput::CEvent *pInputEventsArray, int *pInputEventCount)
CUIEx::CUIEx()
{
Init(pUI, pKernel, pRenderTools, pInputEventsArray, pInputEventCount);
m_MouseSlow = false;
}

void CUIEx::Init(CUI *pUI, IKernel *pKernel, CRenderTools *pRenderTools, IInput::CEvent *pInputEventsArray, int *pInputEventCount)
Expand All @@ -31,7 +31,188 @@ void CUIEx::Init(CUI *pUI, IKernel *pKernel, CRenderTools *pRenderTools, IInput:
m_pTextRender = Kernel()->RequestInterface<ITextRender>();
}

int CUIEx::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *Offset, bool Hidden, int Corners, const char *pEmptyText)
void CUIEx::ConvertMouseMove(float *pX, float *pY) const
{
UI()->ConvertMouseMove(pX, pY);

if(m_MouseSlow)
{
const float SlowMouseFactor = 0.05f;
*pX *= SlowMouseFactor;
*pY *= SlowMouseFactor;
}
}

float CUIEx::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current)
{
Current = clamp(Current, 0.0f, 1.0f);

// layout
CUIRect Rail;
pRect->Margin(5.0f, &Rail);

CUIRect Handle;
Rail.HSplitTop(clamp(33.0f, Rail.w, Rail.h / 3.0f), &Handle, 0);
Handle.y = Rail.y + (Rail.h - Handle.h) * Current;

// logic
static float s_OffsetY;
const bool InsideRail = UI()->MouseInside(&Rail);
const bool InsideHandle = UI()->MouseInside(&Handle);
bool Grabbed = false; // whether to apply the offset

if(UI()->ActiveItem() == pID)
{
if(UI()->MouseButton(0))
{
Grabbed = true;
if(Input()->KeyIsPressed(KEY_LSHIFT) || Input()->KeyIsPressed(KEY_RSHIFT))
m_MouseSlow = true;
}
else
{
UI()->SetActiveItem(0);
}
}
else if(UI()->HotItem() == pID)
{
if(UI()->MouseButton(0))
{
UI()->SetActiveItem(pID);
s_OffsetY = UI()->MouseY() - Handle.y;
Grabbed = true;
}
}
else if(UI()->MouseButtonClicked(0) && !InsideHandle && InsideRail)
{
UI()->SetActiveItem(pID);
s_OffsetY = Handle.h / 2.0f;
Grabbed = true;
}

if(InsideHandle)
{
UI()->SetHotItem(pID);
}

float ReturnValue = Current;
if(Grabbed)
{
const float Min = Rail.y;
const float Max = Rail.h - Handle.h;
const float Cur = UI()->MouseY() - s_OffsetY;
ReturnValue = clamp((Cur - Min) / Max, 0.0f, 1.0f);
}

// render
RenderTools()->DrawUIRect(&Rail, ColorRGBA(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, Rail.w / 2.0f);

float ColorSlider;
if(UI()->ActiveItem() == pID)
ColorSlider = 0.9f;
else if(UI()->HotItem() == pID)
ColorSlider = 1.0f;
else
ColorSlider = 0.8f;

RenderTools()->DrawUIRect(&Handle, ColorRGBA(ColorSlider, ColorSlider, ColorSlider, 1.0f), CUI::CORNER_ALL, Handle.w / 2.0f);

return ReturnValue;
}

float CUIEx::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current, const ColorRGBA *pColorInner)
{
Current = clamp(Current, 0.0f, 1.0f);

// layout
CUIRect Rail;
if(pColorInner)
Rail = *pRect;
else
pRect->HMargin(5.0f, &Rail);

CUIRect Handle;
Rail.VSplitLeft(pColorInner ? 8.0f : clamp(33.0f, Rail.h, Rail.w / 3.0f), &Handle, 0);
Handle.x += (Rail.w - Handle.w) * Current;

// logic
static float s_OffsetX;
const bool InsideRail = UI()->MouseInside(&Rail);
const bool InsideHandle = UI()->MouseInside(&Handle);
bool Grabbed = false; // whether to apply the offset

if(UI()->ActiveItem() == pID)
{
if(UI()->MouseButton(0))
{
Grabbed = true;
if(Input()->KeyIsPressed(KEY_LSHIFT) || Input()->KeyIsPressed(KEY_RSHIFT))
m_MouseSlow = true;
}
else
{
UI()->SetActiveItem(0);
}
}
else if(UI()->HotItem() == pID)
{
if(UI()->MouseButton(0))
{
UI()->SetActiveItem(pID);
s_OffsetX = UI()->MouseX() - Handle.x;
Grabbed = true;
}
}
else if(UI()->MouseButtonClicked(0) && !InsideHandle && InsideRail)
{
UI()->SetActiveItem(pID);
s_OffsetX = Handle.w / 2.0f;
Grabbed = true;
}

if(InsideHandle)
{
UI()->SetHotItem(pID);
}

float ReturnValue = Current;
if(Grabbed)
{
const float Min = Rail.x;
const float Max = Rail.w - Handle.w;
const float Cur = UI()->MouseX() - s_OffsetX;
ReturnValue = clamp((Cur - Min) / Max, 0.0f, 1.0f);
}

// render
if(pColorInner)
{
CUIRect Slider;
Handle.VMargin(-2.0f, &Slider);
Slider.HMargin(-3.0f, &Slider);
RenderTools()->DrawUIRect(&Slider, ColorRGBA(0.15f, 0.15f, 0.15f, 1.0f), CUI::CORNER_ALL, 5.0f);
Slider.Margin(2.0f, &Slider);
RenderTools()->DrawUIRect(&Slider, *pColorInner, CUI::CORNER_ALL, 3.0f);
}
else
{
RenderTools()->DrawUIRect(&Rail, ColorRGBA(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, Rail.h / 2.0f);

float ColorSlider;
if(UI()->ActiveItem() == pID)
ColorSlider = 0.9f;
else if(UI()->HotItem() == pID)
ColorSlider = 1.0f;
else
ColorSlider = 0.8f;

RenderTools()->DrawUIRect(&Handle, ColorRGBA(ColorSlider, ColorSlider, ColorSlider, 1.0f), CUI::CORNER_ALL, Handle.h / 2.0f);
}

return ReturnValue;
}

bool CUIEx::DoEditBox(const void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *pOffset, bool Hidden, int Corners, const char *pEmptyText)
{
int Inside = UI()->MouseInside(pRect);
bool ReturnValue = false;
Expand All @@ -54,9 +235,9 @@ int CUIEx::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSi
m_CurCursor = minimum(str_length(pStr), m_CurCursor);

bool IsShiftPressed = Input()->KeyIsPressed(KEY_LSHIFT) || Input()->KeyIsPressed(KEY_RSHIFT);
bool IsCtrlPressed = Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL);
bool IsModPressed = Input()->ModifierIsPressed();

if(!IsShiftPressed && IsCtrlPressed && Input()->KeyPress(KEY_V))
if(!IsShiftPressed && IsModPressed && Input()->KeyPress(KEY_V))
{
const char *pText = Input()->GetClipboardText();
if(pText)
Expand Down Expand Up @@ -113,7 +294,7 @@ int CUIEx::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSi
}
}

if(!IsShiftPressed && IsCtrlPressed && (Input()->KeyPress(KEY_C) || Input()->KeyPress(KEY_X)))
if(!IsShiftPressed && IsModPressed && (Input()->KeyPress(KEY_C) || Input()->KeyPress(KEY_X)))
{
if(m_HasSelection)
{
Expand Down Expand Up @@ -141,7 +322,7 @@ int CUIEx::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSi
Input()->SetClipboardText(pStr);
}

if(!IsShiftPressed && IsCtrlPressed && Input()->KeyPress(KEY_A))
if(!IsShiftPressed && IsModPressed && Input()->KeyPress(KEY_A))
{
m_CurSelStart = 0;
int StrLen = str_length(pStr);
Expand All @@ -150,7 +331,7 @@ int CUIEx::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSi
m_CurCursor = StrLen;
}

if(!IsShiftPressed && IsCtrlPressed && Input()->KeyPress(KEY_U))
if(!IsShiftPressed && IsModPressed && Input()->KeyPress(KEY_U))
{
pStr[0] = '\0';
m_CurCursor = 0;
Expand All @@ -159,11 +340,10 @@ int CUIEx::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSi

for(int i = 0; i < *m_pInputEventCount; i++)
{
int32_t ManipulateChanges = 0;
int LastCursor = m_CurCursor;
int Len = str_length(pStr);
int NumChars = Len;
ManipulateChanges = CLineInput::Manipulate(m_pInputEventsArray[i], pStr, StrSize, StrSize, &Len, &m_CurCursor, &NumChars, m_HasSelection ? CLineInput::LINE_INPUT_MODIFY_DONT_DELETE : 0, IsCtrlPressed ? KEY_LCTRL : 0);
int Len, NumChars;
str_utf8_stats(pStr, StrSize, StrSize, &Len, &NumChars);
int32_t ManipulateChanges = CLineInput::Manipulate(m_pInputEventsArray[i], pStr, StrSize, StrSize, &Len, &m_CurCursor, &NumChars, m_HasSelection ? CLineInput::LINE_INPUT_MODIFY_DONT_DELETE : 0, IsModPressed ? KEY_LCTRL : 0);
ReturnValue |= (ManipulateChanges & (CLineInput::LINE_INPUT_CHANGE_STRING | CLineInput::LINE_INPUT_CHANGE_CHARACTERS_DELETE)) != 0;

// if cursor changed, reset selection
Expand Down Expand Up @@ -344,26 +524,26 @@ int CUIEx::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSi
if(UI()->LastActiveItem() == pID && !JustGotActive && (UpdateOffset || *m_pInputEventCount))
{
float w = TextRender()->TextWidth(0, FontSize, pDisplayStr, DispCursorPos, std::numeric_limits<float>::max());
if(w - *Offset > Textbox.w)
if(w - *pOffset > Textbox.w)
{
// move to the left
float wt = TextRender()->TextWidth(0, FontSize, pDisplayStr, -1, std::numeric_limits<float>::max());
do
{
*Offset += minimum(wt - *Offset - Textbox.w, Textbox.w / 3);
} while(w - *Offset > Textbox.w + 0.0001f);
*pOffset += minimum(wt - *pOffset - Textbox.w, Textbox.w / 3);
} while(w - *pOffset > Textbox.w + 0.0001f);
}
else if(w - *Offset < 0.0f)
else if(w - *pOffset < 0.0f)
{
// move to the right
do
{
*Offset = maximum(0.0f, *Offset - Textbox.w / 3);
} while(w - *Offset < -0.0001f);
*pOffset = maximum(0.0f, *pOffset - Textbox.w / 3);
} while(w - *pOffset < -0.0001f);
}
}
UI()->ClipEnable(pRect);
Textbox.x -= *Offset;
Textbox.x -= *pOffset;

CTextCursor SelCursor;
TextRender()->SetCursor(&SelCursor, 0, 0, 16, 0);
Expand Down Expand Up @@ -437,3 +617,23 @@ int CUIEx::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSi

return ReturnValue;
}

bool CUIEx::DoClearableEditBox(const void *pID, const void *pClearID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *pOffset, bool Hidden, int Corners, const char *pEmptyText)
{
CUIRect EditBox;
CUIRect ClearButton;
pRect->VSplitRight(15.0f, &EditBox, &ClearButton);
bool ReturnValue = DoEditBox(pID, &EditBox, pStr, StrSize, FontSize, pOffset, Hidden, Corners & ~CUI::CORNER_R, pEmptyText);

TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_PIXEL_ALIGMENT);
RenderTools()->DrawUIRect(&ClearButton, ColorRGBA(1, 1, 1, 0.33f * UI()->ButtonColorMul(pClearID)), Corners & ~CUI::CORNER_L, 3.0f);
UI()->DoLabel(&ClearButton, "Ă—", ClearButton.h * CUI::ms_FontmodHeight, 0, -1, 0);
TextRender()->SetRenderFlags(0);
if(UI()->DoButtonLogic(pClearID, "Ă—", 0, &ClearButton))
{
pStr[0] = 0;
UI()->SetActiveItem(pID);
ReturnValue = true;
}
return ReturnValue;
}
27 changes: 17 additions & 10 deletions src/game/client/ui_ex.h
Expand Up @@ -32,27 +32,34 @@ class CUIEx
int m_MousePressY = 0;
int m_MouseCurX = 0;
int m_MouseCurY = 0;
bool m_MouseSlow;
int m_CurSelStart = 0;
int m_CurSelEnd = 0;
void *m_pSelItem = nullptr;
const void *m_pSelItem = NULL;

int m_CurCursor = 0;

protected:
CUI *UI() { return m_pUI; }
IInput *Input() { return m_pInput; }
ITextRender *TextRender() { return m_pTextRender; }
IKernel *Kernel() { return m_pKernel; }
IGraphics *Graphics() { return m_pGraphics; }
CRenderTools *RenderTools() { return m_pRenderTools; }
CUI *UI() const { return m_pUI; }
IInput *Input() const { return m_pInput; }
ITextRender *TextRender() const { return m_pTextRender; }
IKernel *Kernel() const { return m_pKernel; }
IGraphics *Graphics() const { return m_pGraphics; }
CRenderTools *RenderTools() const { return m_pRenderTools; }

public:
CUIEx(CUI *pUI, IKernel *pKernel, CRenderTools *pRenderTools, IInput::CEvent *pInputEventsArray, int *pInputEventCount);
CUIEx() {}
CUIEx();

void Init(CUI *pUI, IKernel *pKernel, CRenderTools *pRenderTools, IInput::CEvent *pInputEventsArray, int *pInputEventCount);

int DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *Offset, bool Hidden = false, int Corners = CUI::CORNER_ALL, const char *pEmptyText = "");
void ConvertMouseMove(float *pX, float *pY) const;
void ResetMouseSlow() { m_MouseSlow = false; }

float DoScrollbarV(const void *pID, const CUIRect *pRect, float Current);
float DoScrollbarH(const void *pID, const CUIRect *pRect, float Current, const ColorRGBA *pColorInner = NULL);

bool DoEditBox(const void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *pOffset, bool Hidden = false, int Corners = CUI::CORNER_ALL, const char *pEmptyText = "");
bool DoClearableEditBox(const void *pID, const void *pClearID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *pOffset, bool Hidden = false, int Corners = CUI::CORNER_ALL, const char *pEmptyText = "");
};

#endif
2 changes: 1 addition & 1 deletion src/game/collision.cpp
Expand Up @@ -754,7 +754,7 @@ void CCollision::GetSpeedup(int Index, vec2 *Dir, int *Force, int *MaxSpeed) con
*MaxSpeed = m_pSpeedup[Index].m_MaxSpeed;
}

int CCollision::IsSwitch(int Index) const
int CCollision::GetSwitchType(int Index) const
{
if(Index < 0 || !m_pSwitch)
return 0;
Expand Down
2 changes: 1 addition & 1 deletion src/game/collision.h
Expand Up @@ -92,7 +92,7 @@ class CCollision
int IsSpeedup(int Index) const;
int IsTune(int Index) const;
void GetSpeedup(int Index, vec2 *Dir, int *Force, int *MaxSpeed) const;
int IsSwitch(int Index) const;
int GetSwitchType(int Index) const;
int GetSwitchNumber(int Index) const;
int GetSwitchDelay(int Index) const;

Expand Down
7 changes: 4 additions & 3 deletions src/game/ddracecommands.h
Expand Up @@ -48,9 +48,10 @@ CONSOLE_COMMAND("vote_mute", "v[id] i[seconds]", CFGFLAG_SERVER, ConVoteMute, th
CONSOLE_COMMAND("vote_unmute", "v[id]", CFGFLAG_SERVER, ConVoteUnmute, this, "Give back v's right to vote.")
CONSOLE_COMMAND("vote_mutes", "", CFGFLAG_SERVER, ConVoteMutes, this, "List the current active vote mutes.")
CONSOLE_COMMAND("mute", "", CFGFLAG_SERVER, ConMute, this, "")
CONSOLE_COMMAND("muteid", "v[id] i[seconds] ?r[reason]", CFGFLAG_SERVER, ConMuteID, this, "")
CONSOLE_COMMAND("muteip", "s[ip] i[seconds] ?r[reason]", CFGFLAG_SERVER, ConMuteIP, this, "")
CONSOLE_COMMAND("unmute", "v[id]", CFGFLAG_SERVER, ConUnmute, this, "")
CONSOLE_COMMAND("muteid", "v[id] i[seconds] ?r[reason]", CFGFLAG_SERVER, ConMuteID, this, "Mute player with id")
CONSOLE_COMMAND("muteip", "s[ip] i[seconds] ?r[reason]", CFGFLAG_SERVER, ConMuteIP, this, "Mute player with IP address")
CONSOLE_COMMAND("unmute", "i[muteid]", CFGFLAG_SERVER, ConUnmute, this, "Unmute mute with number from \"mutes\"")
CONSOLE_COMMAND("unmuteid", "v[id]", CFGFLAG_SERVER, ConUnmuteID, this, "Unmute player with id")
CONSOLE_COMMAND("mutes", "", CFGFLAG_SERVER, ConMutes, this, "")
CONSOLE_COMMAND("moderate", "", CFGFLAG_SERVER, ConModerate, this, "Enables/disables active moderator mode for the player")
CONSOLE_COMMAND("vote_no", "", CFGFLAG_SERVER, ConVoteNo, this, "Same as \"vote no\"")
Expand Down
2 changes: 1 addition & 1 deletion src/game/editor/auto_map.cpp
Expand Up @@ -47,7 +47,7 @@ void CAutoMapper::Load(const char *pTileName)
{
char aPath[256];
str_format(aPath, sizeof(aPath), "editor/%s.rules", pTileName);
IOHANDLE RulesFile = m_pEditor->Storage()->OpenFile(aPath, IOFLAG_READ, IStorage::TYPE_ALL);
IOHANDLE RulesFile = m_pEditor->Storage()->OpenFile(aPath, IOFLAG_READ | IOFLAG_SKIP_BOM, IStorage::TYPE_ALL);
if(!RulesFile)
return;

Expand Down