diff --git a/CMakeLists.txt b/CMakeLists.txt index 44d156efa..973b2ffc7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1029,6 +1029,7 @@ set_glob(DATA GLOB_RECURSE "json;map;png;rules;ttf;txt;wv" datasrc ui/menuimages/play_game.png ui/menuimages/settings.png ui/no_skinpart.png + ui/sound_icons.png ui/themes/heavens.png ui/themes/heavens_day.map ui/themes/heavens_night.map @@ -1326,6 +1327,8 @@ if(CLIENT) components/motd.h components/nameplates.cpp components/nameplates.h + components/notifications.cpp + components/notifications.h components/particles.cpp components/particles.h components/players.cpp diff --git a/datasrc/content.py b/datasrc/content.py index 415fc043c..e06fc194b 100644 --- a/datasrc/content.py +++ b/datasrc/content.py @@ -241,6 +241,7 @@ image_fileicons = Image("fileicons", "ui/file_icons.png", 1) image_guibuttons = Image("guibuttons", "ui/gui_buttons.png", 1) image_guiicons = Image("guiicons", "ui/gui_icons.png", 1) image_menuicons = Image("menuicons", "ui/icons/menu.png", 1) +image_soundicons = Image("soundicons", "ui/sound_icons.png", 1) image_toolicons = Image("toolicons", "ui/icons/tools.png", 1) image_arrowicons = Image("arrowicons", "ui/icons/arrows.png", 1) image_friendicons = Image("friendicons", "ui/icons/friend.png", 1) @@ -264,6 +265,7 @@ container.images.Add(image_guibuttons) container.images.Add(image_guiicons) container.images.Add(Image("no_skinpart", "ui/no_skinpart.png")) container.images.Add(image_menuicons) +container.images.Add(image_soundicons) container.images.Add(image_toolicons) container.images.Add(image_arrowicons) container.images.Add(image_friendicons) @@ -295,6 +297,7 @@ set_guibuttons = SpriteSet("guibuttons", image_guibuttons, 12, 4) set_guiicons = SpriteSet("guiicons", image_guiicons, 8, 2) set_menuicons = SpriteSet("menuicons", image_menuicons, 4, 4) set_toolicons = SpriteSet("toolicons", image_toolicons, 4, 2) +set_soundicons = SpriteSet("guiicons", image_soundicons, 1, 2) set_arrowicons = SpriteSet("arrowicons", image_arrowicons, 4, 3) set_friendicons = SpriteSet("friendicons", image_friendicons, 2, 2) set_levelicons = SpriteSet("levelicons", image_levelicons, 4, 4) @@ -316,6 +319,7 @@ container.spritesets.Add(set_fileicons) container.spritesets.Add(set_guibuttons) container.spritesets.Add(set_guiicons) container.spritesets.Add(set_menuicons) +container.spritesets.Add(set_soundicons) container.spritesets.Add(set_toolicons) container.spritesets.Add(set_arrowicons) container.spritesets.Add(set_friendicons) @@ -484,6 +488,9 @@ container.sprites.Add(Sprite("menu_checkbox_hover", set_menuicons, 0,2,1,1)) container.sprites.Add(Sprite("menu_collapsed", set_menuicons, 1,0,1,1)) container.sprites.Add(Sprite("menu_expanded", set_menuicons, 1,1,1,1)) +container.sprites.Add(Sprite("soundicon_on", set_soundicons, 0,0,1,1)) +container.sprites.Add(Sprite("soundicon_mute", set_soundicons, 0,1,1,1)) + container.sprites.Add(Sprite("tool_up_a", set_toolicons, 0,0,1,1)) container.sprites.Add(Sprite("tool_up_b", set_toolicons, 0,1,1,1)) container.sprites.Add(Sprite("tool_down_a", set_toolicons, 1,0,1,1)) diff --git a/datasrc/ui/sound_icons.png b/datasrc/ui/sound_icons.png new file mode 100644 index 000000000..c5aa5affd Binary files /dev/null and b/datasrc/ui/sound_icons.png differ diff --git a/src/game/client/components/binds.cpp b/src/game/client/components/binds.cpp index 3ac20aba3..bac2f7e76 100644 --- a/src/game/client/components/binds.cpp +++ b/src/game/client/components/binds.cpp @@ -4,18 +4,18 @@ #include #include "binds.h" -const int CBinds::s_aDefaultBindKeys[] = { // only simple binds - KEY_F1, KEY_F2, KEY_TAB, 'u', KEY_F10, - 'a', 'd', - KEY_SPACE, KEY_MOUSE_1, KEY_MOUSE_2, KEY_LSHIFT, KEY_RSHIFT, KEY_RIGHT, KEY_LEFT, - '1', '2', '3', '4', '5', - KEY_MOUSE_WHEEL_UP, KEY_MOUSE_WHEEL_DOWN, - 't', 'y', 'x', - KEY_F3, KEY_F4, - 'r', +const int CBinds::s_aaDefaultBindKeys[][2] = { + {KEY_F1, 0}, {KEY_F2, 0}, {KEY_TAB, 0}, {'u', 0}, {KEY_F10, 0}, {'s', CBinds::MODIFIER_CTRL}, + {'a', 0}, {'d', 0}, + {KEY_SPACE, 0}, {KEY_MOUSE_1, 0}, {KEY_MOUSE_2, 0}, {KEY_LSHIFT, 0}, {KEY_RSHIFT, 0}, {KEY_RIGHT, 0}, {KEY_LEFT, 0}, + {'1', 0}, {'2', 0}, {'3', 0}, {'4', 0}, {'5', 0}, + {KEY_MOUSE_WHEEL_UP, 0}, {KEY_MOUSE_WHEEL_DOWN, 0}, + {'t', 0}, {'y', 0}, {'x', 0}, + {KEY_F3, 0}, {KEY_F4, 0}, + {'r', 0}, }; const char CBinds::s_aaDefaultBindValues[][32] = { - "toggle_local_console", "toggle_remote_console", "+scoreboard", "+show_chat", "screenshot", + "toggle_local_console", "toggle_remote_console", "+scoreboard", "+show_chat", "screenshot", "snd_toggle", "+left", "+right", "+jump", "+fire", "+hook", "+emote", "+spectate", "spectate_next", "spectate_previous", "+weapon1", "+weapon2", "+weapon3", "+weapon4", "+weapon5", @@ -188,10 +188,10 @@ void CBinds::SetDefaults() { // set default key bindings UnbindAll(); - const int count = sizeof(s_aDefaultBindKeys)/sizeof(int); + const int count = sizeof(s_aaDefaultBindKeys)/sizeof(int)/2; dbg_assert(count == sizeof(s_aaDefaultBindValues)/32, "the count of bind keys differs from that of bind values!"); for(int i = 0; i < count; i++) - Bind(s_aDefaultBindKeys[i], MODIFIER_NONE, s_aaDefaultBindValues[i]); + Bind(s_aaDefaultBindKeys[i][0], s_aaDefaultBindKeys[i][1], s_aaDefaultBindValues[i]); } void CBinds::OnConsoleInit() @@ -363,14 +363,14 @@ void CBinds::ConfigSaveCallback(IConfig *pConfig, void *pUserData) } } - // default binds can only be non-composed right now, so only check for that - for(unsigned j = 0; j < sizeof(s_aDefaultBindKeys)/sizeof(int); j++) + for(unsigned j = 0; j < sizeof(s_aaDefaultBindKeys)/sizeof(int)/2; j++) { - const int i = s_aDefaultBindKeys[j]; - if(pSelf->m_aaaKeyBindings[i][0][0] == 0) + const int Key = s_aaDefaultBindKeys[j][0]; + const int Modifier = s_aaDefaultBindKeys[j][1]; + if(pSelf->m_aaaKeyBindings[Key][Modifier][0] == 0) { // explicitly unbind keys that were unbound by the user - str_format(aBuffer, sizeof(aBuffer), "unbind %s ", pSelf->Input()->KeyName(i)); + str_format(aBuffer, sizeof(aBuffer), "unbind %s%s ", GetModifierName(Modifier), pSelf->Input()->KeyName(Key)); pConfig->WriteLine(aBuffer); } } diff --git a/src/game/client/components/binds.h b/src/game/client/components/binds.h index 5a38707b4..d1df5ba6b 100644 --- a/src/game/client/components/binds.h +++ b/src/game/client/components/binds.h @@ -53,7 +53,7 @@ public: private: char m_aaaKeyBindings[KEY_LAST][MODIFIER_COUNT][128]; - static const int s_aDefaultBindKeys[]; + static const int s_aaDefaultBindKeys[][2]; static const char s_aaDefaultBindValues[][32]; }; #endif diff --git a/src/game/client/components/menus_callback.cpp b/src/game/client/components/menus_callback.cpp index cc3ed285b..f70514f52 100644 --- a/src/game/client/components/menus_callback.cpp +++ b/src/game/client/components/menus_callback.cpp @@ -45,6 +45,7 @@ static CKeyInfo gs_aKeys[] = { "Respawn", "kill", 0, 0}, { "Ready", "ready_change", 0, 0}, { "Add demo marker", "add_demomarker", 0, 0}, + { "Toggle sounds", "snd_toggle", 0, 0}, }; /* This is for scripts/update_localization.py to work, don't remove! @@ -299,7 +300,7 @@ float CMenus::RenderSettingsControlsMisc(CUIRect View, void *pUser) } } - int NumOptions = 11; + int NumOptions = 12; int StartOption = 18; float ButtonHeight = 20.0f; float Spaceing = 2.0f; diff --git a/src/game/client/components/notifications.cpp b/src/game/client/components/notifications.cpp new file mode 100644 index 000000000..f9902cbb7 --- /dev/null +++ b/src/game/client/components/notifications.cpp @@ -0,0 +1,72 @@ +/* (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 +#include + +#include + +#include +#include + +#include "notifications.h" + +CNotifications::CNotifications() +{ + m_SoundToggleTime = 0.0f; +} + +void CNotifications::OnConsoleInit() +{ + IConsole* pConsole = Kernel()->RequestInterface(); + + pConsole->Register("snd_toggle", "", CFGFLAG_CLIENT, Con_SndToggle, this, "Toggle sounds on and off"); +} + +void CNotifications::Con_SndToggle(IConsole::IResult *pResult, void *pUserData) +{ + CNotifications *pSelf = (CNotifications *)pUserData; + + g_Config.m_SndEnable ^= 1; + pSelf->m_SoundToggleTime = pSelf->Client()->LocalTime(); +} + +void CNotifications::RenderSoundNotification() +{ + const float Height = 300.0f; + const float Width = Height*Graphics()->ScreenAspect(); + const float ItemHeight = 20.f; + const float ItemWidth = 20.f; + const float DisplayTime = 1.5f; // includes FadeTime + const float FadeTime = 0.6f; + const float RemainingDisplayTime = max(0.0f, m_SoundToggleTime + DisplayTime - Client()->LocalTime()); + + if(RemainingDisplayTime == 0.0f) + return; + + Graphics()->MapScreen(0.0f, 0.0f, Width, Height); + + CUIRect Area; + Area.x = (Width-ItemWidth)/2.f; + Area.y = (Height/5.f) - (ItemHeight/2.f); + Area.w = ItemWidth; + Area.h = ItemHeight; + + const float Fade = min(1.0f, RemainingDisplayTime / FadeTime); // 0.0 ≤ Fade ≤ 1.0 + + vec4 Color = (g_Config.m_SndEnable == 0) ? vec4(1.f/0xff*0xf9, 1.f/0xff*0x2b, 1.f/0xff*0x2b, 0.55f) : vec4(1.f/0xff*0x2b, 1.f/0xff*0xf9, 1.f/0xff*0x2b, 0.55f); + Color = mix(vec4(Color.r, Color.g, Color.b, 0.0f), Color, 0.8*Fade); + RenderTools()->DrawUIRect(&Area, Color, CUI::CORNER_ALL, 3.0f); + + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_SOUNDICONS].m_Id); + Graphics()->QuadsBegin(); + Graphics()->SetColor(1.0f*Fade, 1.0f*Fade, 1.0f*Fade, 1.0f*Fade); + RenderTools()->SelectSprite(g_Config.m_SndEnable ? SPRITE_SOUNDICON_ON : SPRITE_SOUNDICON_MUTE); + IGraphics::CQuadItem QuadItem(Area.x, Area.y, Area.w, Area.h); + Graphics()->QuadsDrawTL(&QuadItem, 1); + Graphics()->QuadsEnd(); +} + +void CNotifications::OnRender() +{ + RenderSoundNotification(); +} diff --git a/src/game/client/components/notifications.h b/src/game/client/components/notifications.h new file mode 100644 index 000000000..4ee0a7eff --- /dev/null +++ b/src/game/client/components/notifications.h @@ -0,0 +1,20 @@ +/* (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. */ +#ifndef GAME_CLIENT_COMPONENTS_NOTIFICATIONS_H +#define GAME_CLIENT_COMPONENTS_NOTIFICATIONS_H +#include + +class CNotifications : public CComponent +{ + float m_SoundToggleTime; + + void OnConsoleInit(); + void RenderSoundNotification(); + + static void Con_SndToggle(IConsole::IResult *pResult, void *pUserData); +public: + CNotifications(); + virtual void OnRender(); +}; + +#endif diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 4a873126e..09548e28c 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -41,6 +41,7 @@ #include "components/maplayers.h" #include "components/menus.h" #include "components/motd.h" +#include "components/notifications.h" #include "components/particles.h" #include "components/players.h" #include "components/nameplates.h" @@ -65,6 +66,7 @@ static CCountryFlags gs_CountryFlags; static CFlow gs_Flow; static CHud gs_Hud; static CDebugHud gs_DebugHud; +static CNotifications gs_Notifications; static CControls gs_Controls; static CEffects gs_Effects; static CScoreboard gs_Scoreboard; @@ -217,6 +219,7 @@ void CGameClient::OnConsoleInit() m_All.Add(m_pChat); m_All.Add(&gs_Broadcast); m_All.Add(&gs_DebugHud); + m_All.Add(&gs_Notifications); m_All.Add(&gs_Scoreboard); m_All.Add(m_pMotd); m_All.Add(m_pMenus);