From ba2cab60df2a512eba0dfb7eda597eb405abbce9 Mon Sep 17 00:00:00 2001 From: Roman Chistokhodov Date: Wed, 27 Oct 2021 04:35:11 +0300 Subject: [PATCH] Get VGUI back (optionally) (#194) * Get VGUI back (optionally) * Add some missing VGUI invocations * Update CMakeLists.txt to build with vgui for Windows * Move windows.h inclusions only to those places where it's really needed * Try fix mingw build * Update hud_spectator * Merge nekonomicon's vgui branch * Don't include vgui panel and app in cdll_int.cpp if vgui is real * Deduplicate scoreboard global variables * Add options to prefer non-vgui motd and scoreboard when vgui is enabled * Add vgui-dev as a submodule. Add building vith vgui to CI * Fix artifact uploading * Don't use global variable when not necessary * char* to const char* in CMenuHandler_StringCommand constructor * Fix 'format string is not a literal string' warnings * Fix 'always evaluate to true' warnings * Team Fortress classes to const char* * CreateCommandMenu accepts const char* * Fix printf formats. Turn some unsigned longs into unsigned ints since they use only 32 bits anyway * Explicit assignment result as condition * Prevent memory leak on menu reading * Localize button text * Create FileInputStream on stack avoiding the leak * Remove Servers Browser code * Arrow file names to const char* * Fix assignment to the wrong variable --- .github/workflows/.github.yml | 26 + .gitmodules | 3 + CMakeLists.txt | 4 +- cl_dll/CMakeLists.txt | 73 +- cl_dll/MOTD.cpp | 4 + cl_dll/ammo.cpp | 10 +- cl_dll/cdll_int.cpp | 29 +- cl_dll/death.cpp | 17 +- cl_dll/entity.cpp | 6 + cl_dll/hud.cpp | 234 ++- cl_dll/hud.h | 56 +- cl_dll/hud_redraw.cpp | 38 +- cl_dll/hud_servers.cpp | 1226 ------------ cl_dll/hud_servers.h | 40 - cl_dll/hud_spectator.cpp | 139 +- cl_dll/hud_spectator.h | 1 + cl_dll/in_camera.cpp | 16 + cl_dll/in_defs.h | 13 - cl_dll/input.cpp | 26 + cl_dll/input_mouse.h | 15 + cl_dll/input_xash3d.cpp | 2 + cl_dll/menu.cpp | 9 + cl_dll/saytext.cpp | 21 +- cl_dll/scoreboard.cpp | 21 +- cl_dll/text_message.cpp | 9 + cl_dll/vgui_ClassMenu.cpp | 436 ++++ cl_dll/vgui_ConsolePanel.cpp | 97 + cl_dll/vgui_ConsolePanel.h | 37 + cl_dll/vgui_ControlConfigPanel.cpp | 216 ++ cl_dll/vgui_ControlConfigPanel.h | 43 + cl_dll/vgui_CustomObjects.cpp | 551 ++++++ cl_dll/vgui_MOTDWindow.cpp | 151 ++ cl_dll/vgui_SchemeManager.cpp | 556 ++++++ cl_dll/vgui_SchemeManager.h | 50 + cl_dll/vgui_ScorePanel.cpp | 1147 +++++++++++ cl_dll/vgui_ScorePanel.h | 311 +++ cl_dll/vgui_SpectatorPanel.cpp | 420 ++++ cl_dll/vgui_SpectatorPanel.h | 111 ++ cl_dll/vgui_TeamFortressViewport.cpp | 2633 +++++++++++++++++++++++++ cl_dll/vgui_TeamFortressViewport.h | 1816 +++++++++++++++++ cl_dll/vgui_int.cpp | 127 ++ cl_dll/vgui_int.h | 21 + cl_dll/vgui_teammenu.cpp | 394 ++++ cl_dll/voice_status.cpp | 884 +++++++++ cl_dll/voice_status.h | 228 +++ common/winsani_in.h | 7 + common/winsani_out.h | 4 + game_shared/bitvec.h | 4 +- game_shared/vgui_checkbutton2.cpp | 116 +- game_shared/vgui_checkbutton2.h | 61 +- game_shared/vgui_defaultinputsignal.h | 19 +- game_shared/vgui_grid.cpp | 195 +- game_shared/vgui_grid.h | 24 +- game_shared/vgui_helpers.cpp | 49 +- game_shared/vgui_helpers.h | 66 +- game_shared/vgui_listbox.cpp | 107 +- game_shared/vgui_listbox.h | 69 +- game_shared/vgui_loadtga.cpp | 95 +- game_shared/vgui_loadtga.h | 10 +- game_shared/vgui_scrollbar2.cpp | 229 ++- game_shared/vgui_scrollbar2.h | 65 +- game_shared/vgui_slider2.cpp | 371 ++-- game_shared/vgui_slider2.h | 44 +- game_shared/voice_banmgr.cpp | 117 +- game_shared/voice_banmgr.h | 31 +- game_shared/voice_common.h | 6 +- game_shared/voice_gamemgr.cpp | 131 +- game_shared/voice_gamemgr.h | 54 +- game_shared/voice_status.cpp | 478 +++-- game_shared/voice_status.h | 161 +- game_shared/voice_vgui_tweakdlg.cpp | 213 +- game_shared/voice_vgui_tweakdlg.h | 7 +- vgui-dev | 1 + 73 files changed, 12239 insertions(+), 2762 deletions(-) create mode 100644 .gitmodules delete mode 100644 cl_dll/hud_servers.cpp delete mode 100644 cl_dll/hud_servers.h create mode 100644 cl_dll/vgui_ClassMenu.cpp create mode 100644 cl_dll/vgui_ConsolePanel.cpp create mode 100644 cl_dll/vgui_ConsolePanel.h create mode 100644 cl_dll/vgui_ControlConfigPanel.cpp create mode 100644 cl_dll/vgui_ControlConfigPanel.h create mode 100644 cl_dll/vgui_CustomObjects.cpp create mode 100644 cl_dll/vgui_MOTDWindow.cpp create mode 100644 cl_dll/vgui_SchemeManager.cpp create mode 100644 cl_dll/vgui_SchemeManager.h create mode 100644 cl_dll/vgui_ScorePanel.cpp create mode 100644 cl_dll/vgui_ScorePanel.h create mode 100644 cl_dll/vgui_SpectatorPanel.cpp create mode 100644 cl_dll/vgui_SpectatorPanel.h create mode 100644 cl_dll/vgui_TeamFortressViewport.cpp create mode 100644 cl_dll/vgui_TeamFortressViewport.h create mode 100644 cl_dll/vgui_int.cpp create mode 100644 cl_dll/vgui_int.h create mode 100644 cl_dll/vgui_teammenu.cpp create mode 100644 cl_dll/voice_status.cpp create mode 100644 cl_dll/voice_status.h create mode 100644 common/winsani_in.h create mode 100644 common/winsani_out.h create mode 160000 vgui-dev diff --git a/.github/workflows/.github.yml b/.github/workflows/.github.yml index 49264af4..34c449d1 100644 --- a/.github/workflows/.github.yml +++ b/.github/workflows/.github.yml @@ -23,6 +23,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v2 + with: + submodules: true - name: Checkout steam-runtime if: startsWith(matrix.os, 'ubuntu') @@ -58,6 +60,13 @@ jobs: schroot --chroot steamrt_scout_i386 -- cmake -B build -S . -DCMAKE_EXE_LINKER_FLAGS="-Wl,--no-undefined" -DGOLDSOURCE_SUPPORT=ON -DCMAKE_INSTALL_PREFIX="$PWD/dist" schroot --chroot steamrt_scout_i386 -- cmake --build build --target all schroot --chroot steamrt_scout_i386 -- cmake --build build --target install + - name: Build with goldsource input and vgui + if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.cc, 'gcc') + run: | + schroot --chroot steamrt_scout_i386 -- cmake -B build-vgui -S . -DCMAKE_EXE_LINKER_FLAGS="-Wl,--no-undefined" -DGOLDSOURCE_SUPPORT=ON -DUSE_VGUI=ON -DCMAKE_INSTALL_PREFIX="$PWD/dist-vgui" + cp vgui-dev/lib/vgui.so build-vgui/cl_dll + schroot --chroot steamrt_scout_i386 -- cmake --build build-vgui --target all + schroot --chroot steamrt_scout_i386 -- cmake --build build-vgui --target install - name: Build with mingw if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.cc, 'gcc') @@ -74,6 +83,11 @@ jobs: run: | cmake -G "Visual Studio 15 2017" -B build -DGOLDSOURCE_SUPPORT=ON -DCMAKE_INSTALL_PREFIX="dist" msbuild -verbosity:normal /property:Configuration=Release build/INSTALL.vcxproj + - name: Build with msvc and vgui + if: startsWith(matrix.os, 'windows') + run: | + cmake -G "Visual Studio 15 2017" -B build -DGOLDSOURCE_SUPPORT=ON -DUSE_VGUI=ON -DCMAKE_INSTALL_PREFIX="dist-vgui" + msbuild -verbosity:normal /property:Configuration=Release build/INSTALL.vcxproj - name: Extract branch name shell: bash @@ -89,10 +103,22 @@ jobs: with: name: hlsdk-${{ steps.extract_branch.outputs.branch }}-linux path: dist/${{ steps.extract_gamedir.outputs.gamedir }} + - name: Upload linux artifact with vgui + if: startsWith(matrix.os, 'ubuntu') && matrix.cc == 'gcc' + uses: actions/upload-artifact@v2 + with: + name: hlsdk-${{ steps.extract_branch.outputs.branch }}-linux-vgui + path: dist-vgui/${{ steps.extract_gamedir.outputs.gamedir }} - name: Upload windows artifact if: startsWith(matrix.os, 'windows') uses: actions/upload-artifact@v2 with: name: hlsdk-${{ steps.extract_branch.outputs.branch }}-windows path: dist/${{ steps.extract_gamedir.outputs.gamedir }} + - name: Upload windows artifact with vgui + if: startsWith(matrix.os, 'windows') + uses: actions/upload-artifact@v2 + with: + name: hlsdk-${{ steps.extract_branch.outputs.branch }}-windows-vgui + path: dist-vgui/${{ steps.extract_gamedir.outputs.gamedir }} diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..25dfc145 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "vgui-dev"] + path = vgui-dev + url = https://github.com/FWGS/vgui-dev diff --git a/CMakeLists.txt b/CMakeLists.txt index cc8fdd20..7321d4c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,8 +36,10 @@ project (HLSDK-XASH3D) #-------------- # USER DEFINES \ ################\ -option(USE_VGUI "Enable VGUI1. UNDONE" OFF) +option(USE_VGUI "Enable VGUI1." OFF) option(USE_VGUI2 "Enable VGUI2. UNDONE" OFF) +option(USE_NOVGUI_MOTD "Prefer non-VGUI MOTD when USE_VGUI is enabled" OFF) +option(USE_NOVGUI_SCOREBOARD "Prefer non-VGUI Scoreboard when USE_VGUI is enabled" OFF) option(USE_VOICEMGR "Enable VOICE MANAGER." OFF) option(BUILD_CLIENT "Build client dll" ON) option(BUILD_SERVER "Build server dll" ON) diff --git a/cl_dll/CMakeLists.txt b/cl_dll/CMakeLists.txt index 07d6b0d0..8e8e3fb2 100644 --- a/cl_dll/CMakeLists.txt +++ b/cl_dll/CMakeLists.txt @@ -50,6 +50,15 @@ if (GOLDSOURCE_SUPPORT) add_definitions(-DGOLDSOURCE_SUPPORT) endif() +if (USE_VGUI) + add_definitions(-DUSE_VGUI) + if (USE_NOVGUI_MOTD) + add_definitions(-DUSE_NOVGUI_MOTD) + endif() + if (USE_NOVGUI_SCOREBOARD) + add_definitions(-DUSE_NOVGUI_SCOREBOARD) + endif() +endif() set (CLDLL_SOURCES ../dlls/crossbow.cpp @@ -112,11 +121,52 @@ set (CLDLL_SOURCES train.cpp tri.cpp util.cpp - view.cpp - scoreboard.cpp - MOTD.cpp) + view.cpp) -include_directories (. hl/ ../dlls ../dlls/wpn_shared ../common ../engine ../pm_shared ../game_shared ../public ../utils/false_vgui/include) +if (USE_VGUI) + list(APPEND CLDLL_SOURCES + vgui_int.cpp + vgui_ClassMenu.cpp + vgui_ConsolePanel.cpp + vgui_ControlConfigPanel.cpp + vgui_CustomObjects.cpp + vgui_MOTDWindow.cpp + vgui_SchemeManager.cpp + vgui_ScorePanel.cpp + vgui_TeamFortressViewport.cpp + vgui_SpectatorPanel.cpp + vgui_teammenu.cpp + voice_status.cpp + ../game_shared/vgui_checkbutton2.cpp + ../game_shared/vgui_grid.cpp + ../game_shared/vgui_helpers.cpp + ../game_shared/vgui_listbox.cpp + ../game_shared/vgui_loadtga.cpp + ../game_shared/vgui_scrollbar2.cpp + ../game_shared/vgui_slider2.cpp + ../game_shared/voice_banmgr.cpp + ) + if (USE_NOVGUI_MOTD) + list(APPEND CLDLL_SOURCES MOTD.cpp) + endif() + if (USE_NOVGUI_SCOREBOARD) + list(APPEND CLDLL_SOURCES scoreboard.cpp) + endif() +else() + list(APPEND CLDLL_SOURCES + MOTD.cpp + scoreboard.cpp) +endif() + +include_directories (. hl/ ../dlls ../dlls/wpn_shared ../common ../engine ../pm_shared ../game_shared ../public) + +if (USE_VGUI) + SET(CMAKE_SKIP_RPATH TRUE) + link_directories(${CMAKE_SOURCE_DIR}/vgui-dev/lib) + include_directories(../vgui-dev/include) +else() + include_directories(../utils/false_vgui/include) +endif() if(USE_VOICEMGR) #set(CLDLL_SOURCES @@ -126,10 +176,25 @@ if(USE_VOICEMGR) endif() add_library (${CLDLL_LIBRARY} SHARED ${CLDLL_SOURCES}) + if (GOLDSOURCE_SUPPORT) target_link_libraries( ${CLDLL_LIBRARY} ${CMAKE_DL_LIBS} ) endif() +if (USE_VGUI) + if (WIN32) + add_library(vgui SHARED IMPORTED) + set_property(TARGET vgui PROPERTY IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/vgui-dev/lib/win32_vc6/vgui.dll") + set_property(TARGET vgui PROPERTY IMPORTED_IMPLIB "${CMAKE_SOURCE_DIR}/vgui-dev/lib/win32_vc6/vgui.lib") + target_link_libraries(${CLDLL_LIBRARY} vgui) + target_link_libraries(${CLDLL_LIBRARY} ws2_32) + elseif(APPLE) + target_link_libraries(${CLDLL_LIBRARY} "-Wl,--no-undefined -L${CMAKE_SOURCE_DIR}/vgui-dev/lib vgui.dylib") + else() + target_link_libraries(${CLDLL_LIBRARY} :vgui.so) + endif() +endif() + if(WIN32) target_link_libraries( ${CLDLL_LIBRARY} user32.lib ) if (GOLDSOURCE_SUPPORT) diff --git a/cl_dll/MOTD.cpp b/cl_dll/MOTD.cpp index e186134f..c48a9af1 100644 --- a/cl_dll/MOTD.cpp +++ b/cl_dll/MOTD.cpp @@ -26,13 +26,17 @@ #include #include +#if !USE_VGUI || USE_NOVGUI_MOTD DECLARE_MESSAGE( m_MOTD, MOTD ) +#endif int CHudMOTD::Init( void ) { gHUD.AddHudElem( this ); +#if !USE_VGUI || USE_NOVGUI_MOTD HOOK_MESSAGE( MOTD ); +#endif m_bShow = false; diff --git a/cl_dll/ammo.cpp b/cl_dll/ammo.cpp index 7be34e23..94952df7 100644 --- a/cl_dll/ammo.cpp +++ b/cl_dll/ammo.cpp @@ -27,6 +27,9 @@ #include #include "ammohistory.h" +#if USE_VGUI +#include "vgui_TeamFortressViewport.h" +#endif WEAPON *gpActiveSel; // NULL means off, 1 means just the menu bar, otherwise // this points to the active weapon menu item @@ -673,10 +676,11 @@ int CHudAmmo::MsgFunc_WeaponList( const char *pszName, int iSize, void *pbuf ) // Slot button pressed void CHudAmmo::SlotInput( int iSlot ) { +#if USE_VGUI // Let the Viewport use it first, for menus -// if( gViewPort && gViewPort->SlotInput( iSlot ) ) -// return; - + if( gViewPort && gViewPort->SlotInput( iSlot ) ) + return; +#endif gWR.SelectSlot(iSlot, FALSE, 1); } diff --git a/cl_dll/cdll_int.cpp b/cl_dll/cdll_int.cpp index d2be3eea..23da5ae7 100644 --- a/cl_dll/cdll_int.cpp +++ b/cl_dll/cdll_int.cpp @@ -23,11 +23,18 @@ #include "netadr.h" #include "parsemsg.h" +#if USE_VGUI +#include "vgui_int.h" +#include "vgui_TeamFortressViewport.h" +#endif + #if GOLDSOURCE_SUPPORT && (_WIN32 || __linux__ || __APPLE__) && (__i386 || _M_IX86) -#define USE_VGUI_FOR_GOLDSOURCE_SUPPORT 1 +#define USE_FAKE_VGUI !USE_VGUI +#if USE_FAKE_VGUI #include "VGUI_Panel.h" #include "VGUI_App.h" #endif +#endif extern "C" { @@ -38,6 +45,9 @@ extern "C" cl_enginefunc_t gEngfuncs; CHud gHUD; +#if USE_VGUI +TeamFortressViewport *gViewPort = NULL; +#endif mobile_engfuncs_t *gMobileEngfuncs = NULL; extern "C" int g_bhopcap; @@ -183,7 +193,7 @@ int *HUD_GetRect( void ) return extent; } -#if USE_VGUI_FOR_GOLDSOURCE_SUPPORT +#if USE_FAKE_VGUI class TeamFortressViewport : public vgui::Panel { public: @@ -238,7 +248,7 @@ so the HUD can reinitialize itself. int DLLEXPORT HUD_VidInit( void ) { gHUD.VidInit(); -#if USE_VGUI_FOR_GOLDSOURCE_SUPPORT +#if USE_FAKE_VGUI vgui::Panel* root=(vgui::Panel*)gEngfuncs.VGui_GetPanel(); if (root) { gEngfuncs.Con_Printf( "Root VGUI panel exists\n" ); @@ -256,6 +266,8 @@ int DLLEXPORT HUD_VidInit( void ) } else { gEngfuncs.Con_Printf( "Root VGUI panel does not exist\n" ); } +#elif USE_VGUI + VGui_Startup(); #endif return 1; } @@ -274,6 +286,9 @@ void DLLEXPORT HUD_Init( void ) { InitInput(); gHUD.Init(); +#if USE_VGUI + Scheme_Init(); +#endif gEngfuncs.pfnHookUserMsg( "Bhopcap", __MsgFunc_Bhopcap ); } @@ -337,7 +352,9 @@ Called by engine every frame that client .dll is loaded void DLLEXPORT HUD_Frame( double time ) { -#if USE_VGUI_FOR_GOLDSOURCE_SUPPORT +#if USE_VGUI + GetClientVoiceMgr()->Frame(time); +#elif USE_FAKE_VGUI if (!gViewPort) gEngfuncs.VGui_ViewportPaintBackground(HUD_GetRect()); #else @@ -355,7 +372,9 @@ Called when a player starts or stops talking. void DLLEXPORT HUD_VoiceStatus( int entindex, qboolean bTalking ) { - +#if USE_VGUI + GetClientVoiceMgr()->UpdateSpeakerStatus(entindex, bTalking); +#endif } /* diff --git a/cl_dll/death.cpp b/cl_dll/death.cpp index d2c41e38..1dbb0b39 100644 --- a/cl_dll/death.cpp +++ b/cl_dll/death.cpp @@ -23,6 +23,10 @@ #include #include +#if USE_VGUI +#include "vgui_TeamFortressViewport.h" +#endif + DECLARE_MESSAGE( m_DeathNotice, DeathMsg ) struct DeathNoticeItem { @@ -110,7 +114,9 @@ int CHudDeathNotice::Draw( float flTime ) // Only draw if the viewport will let me // vgui dropped out - //if( gViewPort && gViewPort->AllowedToPrintText() ) +#if USE_VGUI + if( gViewPort && gViewPort->AllowedToPrintText() ) +#endif { // Draw the death notice y = YRES( DEATHNOTICE_TOP ) + 2 + ( 20 * i ); //!!! @@ -168,6 +174,11 @@ int CHudDeathNotice::MsgFunc_DeathMsg( const char *pszName, int iSize, void *pbu strcpy( killedwith, "d_" ); strncat( killedwith, READ_STRING(), sizeof(killedwith) - strlen(killedwith) - 1 ); +#if USE_VGUI + if (gViewPort) + gViewPort->DeathMsg( killer, victim ); +#endif + gHUD.m_Spectator.DeathMessage( victim ); for( i = 0; i < MAX_DEATHNOTICES; i++ ) @@ -182,9 +193,7 @@ int CHudDeathNotice::MsgFunc_DeathMsg( const char *pszName, int iSize, void *pbu i = MAX_DEATHNOTICES - 1; } - //if(gViewPort) - // gViewPort->GetAllPlayersInfo(); - gHUD.m_Scoreboard.GetAllPlayersInfo(); + gHUD.GetAllPlayersInfo(); // Get the Killer's name const char *killer_name = ""; diff --git a/cl_dll/entity.cpp b/cl_dll/entity.cpp index e9b3d0f4..ba524f6a 100644 --- a/cl_dll/entity.cpp +++ b/cl_dll/entity.cpp @@ -7,6 +7,8 @@ // Client side entity management functions +#include + #include "hud.h" #include "cl_util.h" #include "const.h" @@ -526,6 +528,10 @@ void DLLEXPORT HUD_CreateEntities( void ) #endif // Add in any game specific objects Game_AddObjects(); + +#if USE_VGUI + GetClientVoiceMgr()->CreateEntities(); +#endif } /* diff --git a/cl_dll/hud.cpp b/cl_dll/hud.cpp index 9652770d..eae37b7a 100644 --- a/cl_dll/hud.cpp +++ b/cl_dll/hud.cpp @@ -23,11 +23,72 @@ #include #include #include "parsemsg.h" -#include "hud_servers.h" +#if USE_VGUI +#include "vgui_int.h" +#include "vgui_TeamFortressViewport.h" +#endif #include "demo.h" #include "demo_api.h" +hud_player_info_t g_PlayerInfoList[MAX_PLAYERS+1]; // player info from the engine +extra_player_info_t g_PlayerExtraInfo[MAX_PLAYERS+1]; // additional player info sent directly to the client dll +team_info_t g_TeamInfo[MAX_TEAMS + 1]; +int g_IsSpectator[MAX_PLAYERS+1]; +int g_iPlayerClass; +int g_iTeamNumber; +int g_iUser1 = 0; +int g_iUser2 = 0; +int g_iUser3 = 0; + +#if USE_VGUI +#include "vgui_ScorePanel.h" + +class CHLVoiceStatusHelper : public IVoiceStatusHelper +{ +public: + virtual void GetPlayerTextColor(int entindex, int color[3]) + { + color[0] = color[1] = color[2] = 255; + + if( entindex >= 0 && entindex < sizeof(g_PlayerExtraInfo)/sizeof(g_PlayerExtraInfo[0]) ) + { + int iTeam = g_PlayerExtraInfo[entindex].teamnumber; + + if ( iTeam < 0 ) + { + iTeam = 0; + } + + iTeam = iTeam % iNumberOfTeamColors; + + color[0] = iTeamColors[iTeam][0]; + color[1] = iTeamColors[iTeam][1]; + color[2] = iTeamColors[iTeam][2]; + } + } + + virtual void UpdateCursorState() + { + gViewPort->UpdateCursorState(); + } + + virtual int GetAckIconHeight() + { + return ScreenHeight - gHUD.m_iFontHeight*3 - 6; + } + + virtual bool CanShowSpeakerLabels() + { + if( gViewPort && gViewPort->m_pScoreBoard ) + return !gViewPort->m_pScoreBoard->isVisible(); + else + return false; + } +}; +static CHLVoiceStatusHelper g_VoiceStatusHelper; +#endif + cvar_t *hud_textmode; float g_hud_text_color[3]; @@ -81,73 +142,182 @@ int __MsgFunc_GameMode( const char *pszName, int iSize, void *pbuf ) // TFFree Command Menu void __CmdFunc_OpenCommandMenu( void ) { +#if USE_VGUI + if ( gViewPort ) + { + gViewPort->ShowCommandMenu( gViewPort->m_StandardMenu ); + } +#endif } // TFC "special" command void __CmdFunc_InputPlayerSpecial( void ) { +#if USE_VGUI + if ( gViewPort ) + { + gViewPort->InputPlayerSpecial(); + } +#endif } void __CmdFunc_CloseCommandMenu( void ) { +#if USE_VGUI + if ( gViewPort ) + { + gViewPort->InputSignalHideCommandMenu(); + } +#endif } void __CmdFunc_ForceCloseCommandMenu( void ) { -} - -void __CmdFunc_ToggleServerBrowser( void ) -{ +#if USE_VGUI + if ( gViewPort ) + { + gViewPort->HideCommandMenu(); + } +#endif } // TFFree Command Menu Message Handlers int __MsgFunc_ValClass( const char *pszName, int iSize, void *pbuf ) { +#if USE_VGUI + if (gViewPort) + return gViewPort->MsgFunc_ValClass( pszName, iSize, pbuf ); +#endif return 0; } int __MsgFunc_TeamNames( const char *pszName, int iSize, void *pbuf ) { +#if USE_VGUI + if (gViewPort) + return gViewPort->MsgFunc_TeamNames( pszName, iSize, pbuf ); +#endif return 0; } int __MsgFunc_Feign( const char *pszName, int iSize, void *pbuf ) { +#if USE_VGUI + if (gViewPort) + return gViewPort->MsgFunc_Feign( pszName, iSize, pbuf ); +#endif return 0; } int __MsgFunc_Detpack( const char *pszName, int iSize, void *pbuf ) { +#if USE_VGUI + if (gViewPort) + return gViewPort->MsgFunc_Detpack( pszName, iSize, pbuf ); +#endif return 0; } int __MsgFunc_VGUIMenu( const char *pszName, int iSize, void *pbuf ) { +#if USE_VGUI + if (gViewPort) + return gViewPort->MsgFunc_VGUIMenu( pszName, iSize, pbuf ); +#endif return 0; } +#if USE_VGUI && !USE_NOVGUI_MOTD +int __MsgFunc_MOTD(const char *pszName, int iSize, void *pbuf) +{ + if (gViewPort) + return gViewPort->MsgFunc_MOTD( pszName, iSize, pbuf ); + return 0; +} +#endif + int __MsgFunc_BuildSt( const char *pszName, int iSize, void *pbuf ) { +#if USE_VGUI + if (gViewPort) + return gViewPort->MsgFunc_BuildSt( pszName, iSize, pbuf ); +#endif return 0; } int __MsgFunc_RandomPC( const char *pszName, int iSize, void *pbuf ) { +#if USE_VGUI + if (gViewPort) + return gViewPort->MsgFunc_RandomPC( pszName, iSize, pbuf ); +#endif return 0; } int __MsgFunc_ServerName( const char *pszName, int iSize, void *pbuf ) { +#if USE_VGUI + if (gViewPort) + return gViewPort->MsgFunc_ServerName( pszName, iSize, pbuf ); +#endif return 0; } +#if USE_VGUI && !USE_NOVGUI_SCOREBOARD +int __MsgFunc_ScoreInfo(const char *pszName, int iSize, void *pbuf) +{ + if (gViewPort) + return gViewPort->MsgFunc_ScoreInfo( pszName, iSize, pbuf ); + return 0; +} + +int __MsgFunc_TeamScore(const char *pszName, int iSize, void *pbuf) +{ + if (gViewPort) + return gViewPort->MsgFunc_TeamScore( pszName, iSize, pbuf ); + return 0; +} + +int __MsgFunc_TeamInfo(const char *pszName, int iSize, void *pbuf) +{ + if (gViewPort) + return gViewPort->MsgFunc_TeamInfo( pszName, iSize, pbuf ); + return 0; +} +#endif + int __MsgFunc_Spectator( const char *pszName, int iSize, void *pbuf ) { +#if USE_VGUI + if (gViewPort) + return gViewPort->MsgFunc_Spectator( pszName, iSize, pbuf ); +#endif return 0; } +#if USE_VGUI +int __MsgFunc_SpecFade(const char *pszName, int iSize, void *pbuf) +{ + if (gViewPort) + return gViewPort->MsgFunc_SpecFade( pszName, iSize, pbuf ); + return 0; +} + +int __MsgFunc_ResetFade(const char *pszName, int iSize, void *pbuf) +{ + if (gViewPort) + return gViewPort->MsgFunc_ResetFade( pszName, iSize, pbuf ); + return 0; + +} +#endif + int __MsgFunc_AllowSpec( const char *pszName, int iSize, void *pbuf ) { +#if USE_VGUI + if (gViewPort) + return gViewPort->MsgFunc_AllowSpec( pszName, iSize, pbuf ); +#endif return 0; } @@ -167,7 +337,6 @@ void CHud::Init( void ) HOOK_COMMAND( "-commandmenu", CloseCommandMenu ); HOOK_COMMAND( "ForceCloseCommandMenu", ForceCloseCommandMenu ); HOOK_COMMAND( "special", InputPlayerSpecial ); - HOOK_COMMAND( "togglebrowser", ToggleServerBrowser ); HOOK_MESSAGE( ValClass ); HOOK_MESSAGE( TeamNames ); @@ -177,9 +346,24 @@ void CHud::Init( void ) HOOK_MESSAGE( RandomPC ); HOOK_MESSAGE( ServerName ); +#if USE_VGUI && !USE_NOVGUI_MOTD + HOOK_MESSAGE( MOTD ); +#endif + +#if USE_VGUI && !USE_NOVGUI_SCOREBOARD + HOOK_MESSAGE( ScoreInfo ); + HOOK_MESSAGE( TeamScore ); + HOOK_MESSAGE( TeamInfo ); +#endif + HOOK_MESSAGE( Spectator ); HOOK_MESSAGE( AllowSpec ); +#if USE_VGUI + HOOK_MESSAGE( SpecFade ); + HOOK_MESSAGE( ResetFade ); +#endif + // VGUI Menus HOOK_MESSAGE( VGUIMenu ); @@ -230,11 +414,19 @@ void CHud::Init( void ) m_AmmoSecondary.Init(); m_TextMessage.Init(); m_StatusIcons.Init(); +#if USE_VGUI + GetClientVoiceMgr()->Init(&g_VoiceStatusHelper, (vgui::Panel**)&gViewPort); +#endif + +#if !USE_VGUI || USE_NOVGUI_MOTD m_MOTD.Init(); +#endif +#if !USE_VGUI || USE_NOVGUI_SCOREBOARD m_Scoreboard.Init(); +#endif m_Menu.Init(); - + MsgFunc_ResetHUD( 0, 0, NULL ); } @@ -411,8 +603,15 @@ void CHud::VidInit( void ) m_AmmoSecondary.VidInit(); m_TextMessage.VidInit(); m_StatusIcons.VidInit(); - m_Scoreboard.VidInit(); +#if USE_VGUI + GetClientVoiceMgr()->VidInit(); +#endif +#if !USE_VGUI || USE_NOVGUI_MOTD m_MOTD.VidInit(); +#endif +#if !USE_VGUI || USE_NOVGUI_SCOREBOARD + m_Scoreboard.VidInit(); +#endif } int CHud::MsgFunc_Logo( const char *pszName, int iSize, void *pbuf ) @@ -588,3 +787,22 @@ float CHud::GetSensitivity( void ) { return m_flMouseSensitivity; } + +void CHud::GetAllPlayersInfo() +{ + for( int i = 1; i < MAX_PLAYERS; i++ ) + { + GetPlayerInfo( i, &g_PlayerInfoList[i] ); + + if( g_PlayerInfoList[i].thisplayer ) + { +#if USE_VGUI + if(gViewPort) + gViewPort->m_pScoreBoard->m_iPlayerNum = i; +#endif +#if !USE_VGUI || USE_NOVGUI_SCOREBOARD + m_Scoreboard.m_iPlayerNum = i; // !!!HACK: this should be initialized elsewhere... maybe gotten from the engine +#endif + } + } +} diff --git a/cl_dll/hud.h b/cl_dll/hud.h index 7c5eee0e..69c6646f 100644 --- a/cl_dll/hud.h +++ b/cl_dll/hud.h @@ -63,6 +63,9 @@ typedef struct cvar_s cvar_t; #define MAX_MOTD_LENGTH 1536 +#define MAX_SERVERNAME_LENGTH 64 +#define MAX_TEAMNAME_SIZE 32 + // //----------------------------------------------------- // @@ -89,6 +92,9 @@ struct HUDLIST // //----------------------------------------------------- +#if USE_VGUI +#include "voice_status.h" // base voice handling class +#endif #include "hud_spectator.h" // @@ -196,11 +202,7 @@ private: int m_iPos; }; -// -//----------------------------------------------------- -// -// REMOVED: Vgui has replaced this. -// +#if !USE_VGUI || USE_NOVGUI_MOTD class CHudMOTD : public CHudBase { public: @@ -222,7 +224,9 @@ protected: int m_iLines; int m_iMaxLength; }; +#endif +#if !USE_VGUI || USE_NOVGUI_SCOREBOARD class CHudScoreboard : public CHudBase { public: @@ -249,6 +253,7 @@ public: void GetAllPlayersInfo( void ); }; +#endif // //----------------------------------------------------- @@ -283,41 +288,6 @@ protected: float *m_pflNameColors[MAX_STATUSBAR_LINES]; }; -// -//----------------------------------------------------- -// -// REMOVED: Vgui has replaced this. -// -/* -class CHudScoreboard : public CHudBase -{ -public: - int Init( void ); - void InitHUDData( void ); - int VidInit( void ); - int Draw( float flTime ); - int DrawPlayers( int xoffset, float listslot, int nameoffset = 0, char *team = NULL ); // returns the ypos where it finishes drawing - void UserCmd_ShowScores( void ); - void UserCmd_HideScores( void ); - int MsgFunc_ScoreInfo( const char *pszName, int iSize, void *pbuf ); - int MsgFunc_TeamInfo( const char *pszName, int iSize, void *pbuf ); - int MsgFunc_TeamScore( const char *pszName, int iSize, void *pbuf ); - void DeathMsg( int killer, int victim ); - - int m_iNumTeams; - - int m_iLastKilledBy; - int m_fLastKillTime; - int m_iPlayerNum; - int m_iShowscoresHeld; - - void GetAllPlayersInfo( void ); - -private: - struct cvar_s *cl_showpacketloss; -}; -*/ - struct extra_player_info_t { short frags; @@ -633,8 +603,12 @@ public: CHudAmmoSecondary m_AmmoSecondary; CHudTextMessage m_TextMessage; CHudStatusIcons m_StatusIcons; +#if !USE_VGUI || USE_NOVGUI_SCOREBOARD CHudScoreboard m_Scoreboard; +#endif +#if !USE_VGUI || USE_NOVGUI_MOTD CHudMOTD m_MOTD; +#endif void Init( void ); void VidInit( void ); @@ -670,6 +644,8 @@ public: void AddHudElem( CHudBase *p ); float GetSensitivity(); + + void GetAllPlayersInfo( void ); }; extern CHud gHUD; diff --git a/cl_dll/hud_redraw.cpp b/cl_dll/hud_redraw.cpp index 579c0897..300c228f 100644 --- a/cl_dll/hud_redraw.cpp +++ b/cl_dll/hud_redraw.cpp @@ -21,6 +21,10 @@ #include "cl_util.h" //#include "triangleapi.h" +#if USE_VGUI +#include "vgui_TeamFortressViewport.h" +#endif + #define MAX_LOGO_FRAMES 56 int grgLogoFrame[MAX_LOGO_FRAMES] = @@ -39,6 +43,11 @@ extern cvar_t *sensitivity; // Think void CHud::Think( void ) { +#if USE_VGUI + m_scrinfo.iSize = sizeof(m_scrinfo); + GetScreenInfo(&m_scrinfo); +#endif + int newfov; HUDLIST *pList = m_pHudList; @@ -94,13 +103,40 @@ int CHud::Redraw( float flTime, int intermission ) if( m_flTimeDelta < 0 ) m_flTimeDelta = 0; +#if USE_VGUI + // Bring up the scoreboard during intermission + if (gViewPort) + { + if( m_iIntermission && !intermission ) + { + // Have to do this here so the scoreboard goes away + m_iIntermission = intermission; + gViewPort->HideCommandMenu(); + gViewPort->HideScoreBoard(); + gViewPort->UpdateSpectatorPanel(); + } + else if( !m_iIntermission && intermission ) + { + m_iIntermission = intermission; + gViewPort->HideCommandMenu(); + gViewPort->HideVGUIMenu(); +#if !USE_NOVGUI_SCOREBOARD + gViewPort->ShowScoreBoard(); +#endif + gViewPort->UpdateSpectatorPanel(); + // Take a screenshot if the client's got the cvar set + if( CVAR_GET_FLOAT( "hud_takesshots" ) != 0 ) + m_flShotTime = flTime + 1.0; // Take a screenshot in a second + } + } +#else if( !m_iIntermission && intermission ) { // Take a screenshot if the client's got the cvar set if( CVAR_GET_FLOAT( "hud_takesshots" ) != 0 ) m_flShotTime = flTime + 1.0f; // Take a screenshot in a second } - +#endif if( m_flShotTime && m_flShotTime < flTime ) { gEngfuncs.pfnClientCmd( "snapshot\n" ); diff --git a/cl_dll/hud_servers.cpp b/cl_dll/hud_servers.cpp deleted file mode 100644 index fa6d5585..00000000 --- a/cl_dll/hud_servers.cpp +++ /dev/null @@ -1,1226 +0,0 @@ -//========= Copyright (c) 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -// hud_servers.cpp -#include "hud.h" -#include "cl_util.h" -#include "hud_servers_priv.h" -#include "hud_servers.h" -#include "net_api.h" -#include -#include - -static int context_id; - -// Default master server address in case we can't read any from woncomm.lst file -#define VALVE_MASTER_ADDRESS "half-life.east.won.net" -#define PORT_MASTER 27010 -#define PORT_SERVER 27015 - -// File where we really should look for master servers -#define MASTER_PARSE_FILE "woncomm.lst" - -#define MAX_QUERIES 20 - -#define NET_API gEngfuncs.pNetAPI - -static CHudServers *g_pServers = NULL; - -/* -=================== -ListResponse - -Callback from engine -=================== -*/ -void NET_CALLBACK ListResponse( struct net_response_s *response ) -{ - if( g_pServers ) - { - g_pServers->ListResponse( response ); - } -} - -/* -=================== -ServerResponse - -Callback from engine -=================== -*/ -void NET_CALLBACK ServerResponse( struct net_response_s *response ) -{ - if( g_pServers ) - { - g_pServers->ServerResponse( response ); - } -} - -/* -=================== -PingResponse - -Callback from engine -=================== -*/ -void NET_CALLBACK PingResponse( struct net_response_s *response ) -{ - if( g_pServers ) - { - g_pServers->PingResponse( response ); - } -} - -/* -=================== -RulesResponse - -Callback from engine -=================== -*/ -void NET_CALLBACK RulesResponse( struct net_response_s *response ) -{ - if( g_pServers ) - { - g_pServers->RulesResponse( response ); - } -} - -/* -=================== -PlayersResponse - -Callback from engine -=================== -*/ -void NET_CALLBACK PlayersResponse( struct net_response_s *response ) -{ - if( g_pServers ) - { - g_pServers->PlayersResponse( response ); - } -} - -/* -=================== -ListResponse - -=================== -*/ -void CHudServers::ListResponse( struct net_response_s *response ) -{ - request_t *list; - request_t *p; - int c = 0; - - if( !( response->error == NET_SUCCESS ) ) - return; - - if( response->type != NETAPI_REQUEST_SERVERLIST ) - return; - - if( response->response ) - { - list = ( request_t * ) response->response; - while ( list ) - { - c++; - - //if( c < 40 ) - { - // Copy from parsed stuff - p = new request_t; - p->context = -1; - p->remote_address = list->remote_address; - p->next = m_pServerList; - m_pServerList = p; - } - - // Move on - list = list->next; - } - } - - gEngfuncs.Con_Printf( "got list\n" ); - - m_nQuerying = 1; - m_nActiveQueries = 0; -} - -/* -=================== -ServerResponse - -=================== -*/ -void CHudServers::ServerResponse( struct net_response_s *response ) -{ - char *szresponse; - request_t *p; - server_t *browser; - int len; - char sz[32]; - - // Remove from active list - p = FindRequest( response->context, m_pActiveList ); - if( p ) - { - RemoveServerFromList( &m_pActiveList, p ); - m_nActiveQueries--; - } - - if( response->error != NET_SUCCESS ) - return; - - switch ( response->type ) - { - case NETAPI_REQUEST_DETAILS: - if( response->response ) - { - szresponse = (char *)response->response; - len = strlen( szresponse ) + 100 + 1; - sprintf( sz, "%i", (int)( 1000.0 * response->ping ) ); - - browser = new server_t; - browser->remote_address = response->remote_address; - browser->info = new char[len]; - browser->ping = (int)( 1000.0 * response->ping ); - strcpy( browser->info, szresponse ); - - NET_API->SetValueForKey( browser->info, "address", gEngfuncs.pNetAPI->AdrToString( &response->remote_address ), len ); - NET_API->SetValueForKey( browser->info, "ping", sz, len ); - - AddServer( &m_pServers, browser ); - } - break; - default: - break; - } -} - -/* -=================== -PingResponse - -=================== -*/ -void CHudServers::PingResponse( struct net_response_s *response ) -{ - char sz[32]; - - if( response->error != NET_SUCCESS ) - return; - - switch( response->type ) - { - case NETAPI_REQUEST_PING: - sprintf( sz, "%.2f", 1000.0 * response->ping ); - - gEngfuncs.Con_Printf( "ping == %s\n", sz ); - break; - default: - break; - } -} - -/* -=================== -RulesResponse - -=================== -*/ -void CHudServers::RulesResponse( struct net_response_s *response ) -{ - char *szresponse; - - if( response->error != NET_SUCCESS ) - return; - - switch( response->type ) - { - case NETAPI_REQUEST_RULES: - if( response->response ) - { - szresponse = (char *)response->response; - - gEngfuncs.Con_Printf( "rules %s\n", szresponse ); - } - break; - default: - break; - } -} - -/* -=================== -PlayersResponse - -=================== -*/ -void CHudServers::PlayersResponse( struct net_response_s *response ) -{ - char *szresponse; - - if( response->error != NET_SUCCESS ) - return; - - switch( response->type ) - { - case NETAPI_REQUEST_PLAYERS: - if( response->response ) - { - szresponse = (char *)response->response; - - gEngfuncs.Con_Printf( "players %s\n", szresponse ); - } - break; - default: - break; - } -} - -/* -=================== -CompareServers - -Return 1 if p1 is "less than" p2, 0 otherwise -=================== -*/ -int CHudServers::CompareServers( server_t *p1, server_t *p2 ) -{ - const char *n1, *n2; - - if( p1->ping < p2->ping ) - return 1; - - if( p1->ping == p2->ping ) - { - // Pings equal, sort by second key: hostname - if( p1->info && p2->info ) - { - n1 = NET_API->ValueForKey( p1->info, "hostname" ); - n2 = NET_API->ValueForKey( p2->info, "hostname" ); - - if( n1 && n2 ) - { - if( stricmp( n1, n2 ) < 0 ) - return 1; - } - } - } - - return 0; -} - -/* -=================== -AddServer - -=================== -*/ -void CHudServers::AddServer( server_t **ppList, server_t *p ) -{ - server_t *list; - - if( !ppList || ! p ) - return; - - m_nServerCount++; - - // What sort key? Ping? - list = *ppList; - - // Head of list? - if( !list ) - { - p->next = NULL; - *ppList = p; - return; - } - - // Put on head of list - if( CompareServers( p, list ) ) - { - p->next = *ppList; - *ppList = p; - } - else - { - while( list->next ) - { - // Insert before list next - if( CompareServers( p, list->next ) ) - { - p->next = list->next->next; - list->next = p; - return; - } - - list = list->next; - } - - // Just add at end - p->next = NULL; - list->next = p; - } -} - -/* -=================== -Think - -=================== -*/ -void CHudServers::Think( double time ) -{ - m_fElapsed += time; - - if( !m_nRequesting ) - return; - - if( !m_nQuerying ) - return; - - QueryThink(); - - if( ServerListSize() > 0 ) - return; - - m_dStarted = 0.0; - m_nRequesting = 0; - m_nDone = 0; - m_nQuerying = 0; - m_nActiveQueries = 0; -} - -/* -=================== -QueryThink - -=================== -*/ -void CHudServers::QueryThink( void ) -{ - request_t *p; - - if( !m_nRequesting || m_nDone ) - return; - - if( !m_nQuerying ) - return; - - if( m_nActiveQueries > MAX_QUERIES ) - return; - - // Nothing left - if( !m_pServerList ) - return; - - while( 1 ) - { - p = m_pServerList; - - // No more in list? - if( !p ) - break; - - // Move to next - m_pServerList = m_pServerList->next; - - // Setup context_id - p->context = context_id; - - // Start up query on this one - NET_API->SendRequest( context_id++, NETAPI_REQUEST_DETAILS, 0, 2.0, &p->remote_address, ::ServerResponse ); - - // Increment active list - m_nActiveQueries++; - - // Add to active list - p->next = m_pActiveList; - m_pActiveList = p; - - // Too many active? - if( m_nActiveQueries > MAX_QUERIES ) - break; - } -} - -/* -================== -ServerListSize - -# of servers in active query and in pending to be queried lists -================== -*/ -int CHudServers::ServerListSize( void ) -{ - int c = 0; - request_t *p; - - p = m_pServerList; - while( p ) - { - c++; - p = p->next; - } - - p = m_pActiveList; - while( p ) - { - c++; - p = p->next; - } - - return c; -} - -/* -=================== -FindRequest - -Look up a request by context id -=================== -*/ -CHudServers::request_t *CHudServers::FindRequest( int context, request_t *pList ) -{ - request_t *p; - p = pList; - while( p ) - { - if( context == p->context ) - return p; - - p = p->next; - } - return NULL; -} - -/* -=================== -RemoveServerFromList - -Remote, but don't delete, item from *ppList -=================== -*/ -void CHudServers::RemoveServerFromList( request_t **ppList, request_t *item ) -{ - request_t *p, *n; - request_t *newlist = NULL; - - if( !ppList ) - return; - - p = *ppList; - while( p ) - { - n = p->next; - if( p != item ) - { - p->next = newlist; - newlist = p; - } - p = n; - } - *ppList = newlist; -} - -/* -=================== -ClearRequestList - -=================== -*/ -void CHudServers::ClearRequestList( request_t **ppList ) -{ - request_t *p, *n; - - if( !ppList ) - return; - - p = *ppList; - while( p ) - { - n = p->next; - delete p; - p = n; - } - *ppList = NULL; -} - -/* -=================== -ClearServerList - -=================== -*/ -void CHudServers::ClearServerList( server_t **ppList ) -{ - server_t *p, *n; - - if( !ppList ) - return; - - p = *ppList; - while( p ) - { - n = p->next; - delete[] p->info; - delete p; - p = n; - } - *ppList = NULL; -} - -int CompareField( CHudServers::server_t *p1, CHudServers::server_t *p2, const char *fieldname, int iSortOrder ) -{ - const char *sz1, *sz2; - float fv1, fv2; - - sz1 = NET_API->ValueForKey( p1->info, fieldname ); - sz2 = NET_API->ValueForKey( p2->info, fieldname ); - - fv1 = atof( sz1 ); - fv2 = atof( sz2 ); - - if( fv1 && fv2 ) - { - if( fv1 > fv2 ) - return iSortOrder; - else if( fv1 < fv2 ) - return -iSortOrder; - else - return 0; - } - - // String compare - return stricmp( sz1, sz2 ); -} - -int CALLBACK ServerListCompareFunc( CHudServers::server_t *p1, CHudServers::server_t *p2, const char *fieldname ) -{ - if(!p1 || !p2) // No meaningful comparison - return 0; - - int iSortOrder = 1; - - int retval = 0; - - retval = CompareField( p1, p2, fieldname, iSortOrder ); - - return retval; -} - -static char g_fieldname[256]; -int __cdecl FnServerCompare( const void *elem1, const void *elem2 ) -{ - CHudServers::server_t *list1, *list2; - - list1 = *(CHudServers::server_t **)elem1; - list2 = *(CHudServers::server_t **)elem2; - - return ServerListCompareFunc( list1, list2, g_fieldname ); -} - -void CHudServers::SortServers( const char *fieldname ) -{ - server_t *p; - // Create a list - if( !m_pServers ) - return; - - strcpy( g_fieldname, fieldname ); - - int i; - int c = 0; - - p = m_pServers; - while( p ) - { - c++; - p = p->next; - } - - server_t **pSortArray; - - pSortArray = new server_t *[c]; - memset( pSortArray, 0, c * sizeof(server_t*) ); - - // Now copy the list into the pSortArray: - p = m_pServers; - i = 0; - while( p ) - { - pSortArray[i++] = p; - p = p->next; - } - - // Now do that actual sorting. - size_t nCount = c; - size_t nSize = sizeof(server_t*); - - qsort( - pSortArray, - (size_t)nCount, - (size_t)nSize, - FnServerCompare - ); - - // Now rebuild the list. - m_pServers = pSortArray[0]; - for( i = 0; i < c - 1; i++ ) - { - pSortArray[i]->next = pSortArray[i + 1]; - } - pSortArray[c - 1]->next = NULL; - - // Clean Up. - delete[] pSortArray; -} - -/* -=================== -GetServer - -Return particular server -=================== -*/ -CHudServers::server_t *CHudServers::GetServer( int server ) -{ - int c = 0; - server_t *p; - - p = m_pServers; - while( p ) - { - if( c == server ) - return p; - - c++; - p = p->next; - } - return NULL; -} - -/* -=================== -GetServerInfo - -Return info ( key/value ) string for particular server -=================== -*/ -char *CHudServers::GetServerInfo( int server ) -{ - server_t *p = GetServer( server ); - if( p ) - { - return p->info; - } - return NULL; -} - -/* -=================== -CancelRequest - -Kill all pending requests in engine -=================== -*/ -void CHudServers::CancelRequest( void ) -{ - m_nRequesting = 0; - m_nQuerying = 0; - m_nDone = 1; - - NET_API->CancelAllRequests(); -} - -/* -================== -LoadMasterAddresses - -Loads the master server addresses from file and into the passed in array -================== -*/ -int CHudServers::LoadMasterAddresses( int maxservers, int *count, netadr_t *padr ) -{ - int i; - char szMaster[256]; - char szMasterFile[256]; - char *pbuffer = NULL; - char *pstart = NULL ; - netadr_t adr; - char szAdr[64]; - int nPort; - int nCount = 0; - bool bIgnore; - int nDefaultPort; - - // Assume default master and master file - strcpy( szMaster, VALVE_MASTER_ADDRESS ); // IP:PORT string - strcpy( szMasterFile, MASTER_PARSE_FILE ); - - // See if there is a command line override - i = gEngfuncs.CheckParm( "-comm", &pstart ); - if( i && pstart ) - { - strcpy( szMasterFile, pstart ); - } - - // Read them in from proper file - pbuffer = (char *)gEngfuncs.COM_LoadFile( szMasterFile, 5, NULL ); // Use malloc - if( !pbuffer ) - { - goto finish_master; - } - - pstart = pbuffer; - - while( nCount < maxservers ) - { - pstart = gEngfuncs.COM_ParseFile( pstart, m_szToken ); - - if( strlen( m_szToken ) <= 0) - break; - - bIgnore = true; - - if( !stricmp( m_szToken, "Master" ) ) - { - nDefaultPort = PORT_MASTER; - bIgnore = FALSE; - } - - // Now parse all addresses between { } - pstart = gEngfuncs.COM_ParseFile( pstart, m_szToken ); - if( strlen( m_szToken ) <= 0 ) - break; - - if( stricmp( m_szToken, "{" ) ) - break; - - // Parse addresses until we get to "}" - while( nCount < maxservers ) - { - char base[256]; - - // Now parse all addresses between { } - pstart = gEngfuncs.COM_ParseFile( pstart, m_szToken ); - - if( strlen( m_szToken ) <= 0 ) - break; - - if( !stricmp ( m_szToken, "}" ) ) - break; - - sprintf( base, "%s", m_szToken ); - - pstart = gEngfuncs.COM_ParseFile( pstart, m_szToken ); - - if( strlen( m_szToken ) <= 0 ) - break; - - if( stricmp( m_szToken, ":" ) ) - break; - - pstart = gEngfuncs.COM_ParseFile( pstart, m_szToken ); - - if( strlen( m_szToken ) <= 0 ) - break; - - nPort = atoi( m_szToken ); - if( !nPort ) - nPort = nDefaultPort; - - sprintf( szAdr, "%s:%i", base, nPort ); - - // Can we resolve it any better - if( !NET_API->StringToAdr( szAdr, &adr ) ) - bIgnore = true; - - if( !bIgnore ) - { - padr[nCount++] = adr; - } - } - } -finish_master: - if( !nCount ) - { - sprintf( szMaster, VALVE_MASTER_ADDRESS ); // IP:PORT string - - // Convert to netadr_t - if( NET_API->StringToAdr( szMaster, &adr ) ) - { - padr[nCount++] = adr; - } - } - - *count = nCount; - - if( pbuffer ) - { - gEngfuncs.COM_FreeFile( pbuffer ); - } - - return ( nCount > 0 ) ? 1 : 0; -} - -/* -=================== -RequestList - -Request list of game servers from master -=================== -*/ -void CHudServers::RequestList( void ) -{ - m_nRequesting = 1; - m_nDone = 0; - m_dStarted = m_fElapsed; - - int count = 0; - netadr_t adr; - - if( !LoadMasterAddresses( 1, &count, &adr ) ) - { - gEngfuncs.Con_DPrintf( "SendRequest: Unable to read master server addresses\n" ); - return; - } - - ClearRequestList( &m_pActiveList ); - ClearRequestList( &m_pServerList ); - ClearServerList( &m_pServers ); - - m_nServerCount = 0; - - // Make sure networking system has started. - NET_API->InitNetworking(); - - // Kill off left overs if any - NET_API->CancelAllRequests(); - - // Request Server List from master - NET_API->SendRequest( context_id++, NETAPI_REQUEST_SERVERLIST, 0, 5.0, &adr, ::ListResponse ); -} - -void CHudServers::RequestBroadcastList( int clearpending ) -{ - m_nRequesting = 1; - m_nDone = 0; - m_dStarted = m_fElapsed; - - netadr_t adr = {0}; - - if( clearpending ) - { - ClearRequestList( &m_pActiveList ); - ClearRequestList( &m_pServerList ); - ClearServerList( &m_pServers ); - - m_nServerCount = 0; - } - - // Make sure to byte swap server if necessary ( using "host" to "net" conversion - adr.port = htons( PORT_SERVER ); - - // Make sure networking system has started. - NET_API->InitNetworking(); - - if( clearpending ) - { - // Kill off left overs if any - NET_API->CancelAllRequests(); - } - - adr.type = NA_BROADCAST; - - // Request Servers from LAN via IP - NET_API->SendRequest( context_id++, NETAPI_REQUEST_DETAILS, FNETAPI_MULTIPLE_RESPONSE, 5.0, &adr, ::ServerResponse ); - - adr.type = NA_BROADCAST_IPX; - - // Request Servers from LAN via IPX ( if supported ) - NET_API->SendRequest( context_id++, NETAPI_REQUEST_DETAILS, FNETAPI_MULTIPLE_RESPONSE, 5.0, &adr, ::ServerResponse ); -} - -void CHudServers::ServerPing( int server ) -{ - server_t *p; - - p = GetServer( server ); - if( !p ) - return; - - // Make sure networking system has started. - NET_API->InitNetworking(); - - // Request Server List from master - NET_API->SendRequest( context_id++, NETAPI_REQUEST_PING, 0, 5.0, &p->remote_address, ::PingResponse ); -} - -void CHudServers::ServerRules( int server ) -{ - server_t *p; - - p = GetServer( server ); - if( !p ) - return; - - // Make sure networking system has started. - NET_API->InitNetworking(); - - // Request Server List from master - NET_API->SendRequest( context_id++, NETAPI_REQUEST_RULES, 0, 5.0, &p->remote_address, ::RulesResponse ); -} - -void CHudServers::ServerPlayers( int server ) -{ - server_t *p; - - p = GetServer( server ); - if( !p ) - return; - - // Make sure networking system has started. - NET_API->InitNetworking(); - - // Request Server List from master - NET_API->SendRequest( context_id++, NETAPI_REQUEST_PLAYERS, 0, 5.0, &p->remote_address, ::PlayersResponse ); -} - -int CHudServers::isQuerying() -{ - return m_nRequesting ? 1 : 0; -} - -/* -=================== -GetServerCount - -Return number of servers in browser list -=================== -*/ -int CHudServers::GetServerCount( void ) -{ - return m_nServerCount; -} - -/* -=================== -CHudServers - -=================== -*/ -CHudServers::CHudServers( void ) -{ - m_nRequesting = 0; - m_dStarted = 0.0; - m_nDone = 0; - m_pServerList = NULL; - m_pServers = NULL; - m_pActiveList = NULL; - m_nQuerying = 0; - m_nActiveQueries = 0; - - m_fElapsed = 0.0; - - m_pPingRequest = NULL; - m_pRulesRequest = NULL; - m_pPlayersRequest = NULL; -} - -/* -=================== -~CHudServers - -=================== -*/ -CHudServers::~CHudServers( void ) -{ - ClearRequestList( &m_pActiveList ); - ClearRequestList( &m_pServerList ); - ClearServerList( &m_pServers ); - - m_nServerCount = 0; - - if( m_pPingRequest ) - { - delete m_pPingRequest; - m_pPingRequest = NULL; - } - - if( m_pRulesRequest ) - { - delete m_pRulesRequest; - m_pRulesRequest = NULL; - } - - if( m_pPlayersRequest ) - { - delete m_pPlayersRequest; - m_pPlayersRequest = NULL; - } -} - -/////////////////////////////// -// -// PUBLIC APIs -// -/////////////////////////////// - -/* -=================== -ServersGetCount - -=================== -*/ -int ServersGetCount( void ) -{ - if( g_pServers ) - { - return g_pServers->GetServerCount(); - } - return 0; -} - -int ServersIsQuerying( void ) -{ - if( g_pServers ) - { - return g_pServers->isQuerying(); - } - return 0; -} - -/* -=================== -ServersGetInfo - -=================== -*/ -const char *ServersGetInfo( int server ) -{ - if( g_pServers ) - { - return g_pServers->GetServerInfo( server ); - } - - return NULL; -} - -void SortServers( const char *fieldname ) -{ - if( g_pServers ) - { - g_pServers->SortServers( fieldname ); - } -} - -/* -=================== -ServersShutdown - -=================== -*/ -void ServersShutdown( void ) -{ - if( g_pServers ) - { - delete g_pServers; - g_pServers = NULL; - } -} - -/* -=================== -ServersInit - -=================== -*/ -void ServersInit( void ) -{ - // Kill any previous instance - ServersShutdown(); - - g_pServers = new CHudServers(); -} - -/* -=================== -ServersThink - -=================== -*/ -void ServersThink( double time ) -{ - if( g_pServers ) - { - g_pServers->Think( time ); - } -} - -/* -=================== -ServersCancel - -=================== -*/ -void ServersCancel( void ) -{ - if( g_pServers ) - { - g_pServers->CancelRequest(); - } -} - -// Requests -/* -=================== -ServersList - -=================== -*/ -void ServersList( void ) -{ - if( g_pServers ) - { - g_pServers->RequestList(); - } -} - -void BroadcastServersList( int clearpending ) -{ - if( g_pServers ) - { - g_pServers->RequestBroadcastList( clearpending ); - } -} - -void ServerPing( int server ) -{ - if( g_pServers ) - { - g_pServers->ServerPing( server ); - } -} - -void ServerRules( int server ) -{ - if( g_pServers ) - { - g_pServers->ServerRules( server ); - } -} - -void ServerPlayers( int server ) -{ - if( g_pServers ) - { - g_pServers->ServerPlayers( server ); - } -} diff --git a/cl_dll/hud_servers.h b/cl_dll/hud_servers.h deleted file mode 100644 index 5e886560..00000000 --- a/cl_dll/hud_servers.h +++ /dev/null @@ -1,40 +0,0 @@ -//========= Copyright (c) 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#if !defined( HUD_SERVERSH ) -#define HUD_SERVERSH -#pragma once - -#define NET_CALLBACK /* */ - -// Dispatchers -void NET_CALLBACK ListResponse( struct net_response_s *response ); -void NET_CALLBACK ServerResponse( struct net_response_s *response ); -void NET_CALLBACK PingResponse( struct net_response_s *response ); -void NET_CALLBACK RulesResponse( struct net_response_s *response ); -void NET_CALLBACK PlayersResponse( struct net_response_s *response ); - -void ServersInit( void ); -void ServersShutdown( void ); -void ServersThink( double time ); -void ServersCancel( void ); - -// Get list and get server info from each -void ServersList( void ); - -// Query for IP / IPX LAN servers -void BroadcastServersList( int clearpending ); - -void ServerPing( int server ); -void ServerRules( int server ); -void ServerPlayers( int server ); - -int ServersGetCount( void ); -const char *ServersGetInfo( int server ); -int ServersIsQuerying( void ); -void SortServers( const char *fieldname ); -#endif // HUD_SERVERSH diff --git a/cl_dll/hud_spectator.cpp b/cl_dll/hud_spectator.cpp index 7cb8e1fe..bfd8112b 100644 --- a/cl_dll/hud_spectator.cpp +++ b/cl_dll/hud_spectator.cpp @@ -9,6 +9,10 @@ #include "cl_util.h" #include "cl_entity.h" #include "triangleapi.h" +#if USE_VGUI +#include "vgui_TeamFortressViewport.h" +#include "vgui_SpectatorPanel.h" +#endif #include "hltv.h" #include "pm_shared.h" @@ -76,8 +80,16 @@ void SpectatorSpray( void ) gEngfuncs.pfnServerCmd( string ); } } + void SpectatorHelp( void ) { +#if USE_VGUI + if( gViewPort ) + { + gViewPort->ShowVGUIMenu( MENU_SPECHELP ); + } + else +#endif { char *text = CHudTextMessage::BufferedLocaliseTextString( "#Spec_Help_Text" ); @@ -100,10 +112,33 @@ void SpectatorMenu( void ) gEngfuncs.Con_Printf( "usage: spec_menu <0|1>\n" ); return; } + +#if USE_VGUI + gViewPort->m_pSpectatorPanel->ShowMenu( atoi( gEngfuncs.Cmd_Argv( 1 ) ) != 0 ); +#endif } void ToggleScores( void ) { +#if USE_VGUI && !USE_NOVGUI_SCOREBOARD + if( gViewPort ) + { + if( gViewPort->IsScoreBoardVisible() ) + { + gViewPort->HideScoreBoard(); + } + else + { + gViewPort->ShowScoreBoard(); + } + } +#else + if (gHUD.m_Scoreboard.m_iShowscoresHeld) { + gHUD.m_Scoreboard.UserCmd_HideScores(); + } else { + gHUD.m_Scoreboard.UserCmd_ShowScores(); + } +#endif } //----------------------------------------------------------------------------- @@ -392,8 +427,7 @@ int CHudSpectator::Draw( float flTime ) return 1; // make sure we have player info - //gViewPort->GetAllPlayersInfo(); - gHUD.m_Scoreboard.GetAllPlayersInfo(); + gHUD.GetAllPlayersInfo(); // loop through all the players and draw additional infos to their sprites on the map for( int i = 0; i < MAX_PLAYERS; i++ ) @@ -529,9 +563,16 @@ void CHudSpectator::DirectorMessage( int iSize, void *pbuf ) READ_LONG(); // total number of spectator slots m_iSpectatorNumber = READ_LONG(); // total number of spectator READ_WORD(); // total number of relay proxies +#if USE_VGUI + gViewPort->UpdateSpectatorPanel(); +#endif break; case DRC_CMD_BANNER: // gEngfuncs.Con_DPrintf( "GUI: Banner %s\n",READ_STRING() ); // name of banner tga eg gfx/temp/7454562234563475.tga +#if USE_VGUI + gViewPort->m_pSpectatorPanel->m_TopBanner->LoadImage( READ_STRING() ); + gViewPort->UpdateSpectatorPanel(); +#endif break; case DRC_CMD_FADE: break; @@ -573,8 +614,7 @@ void CHudSpectator::FindNextPlayer( bool bReverse ) int iDir = bReverse ? -1 : 1; // make sure we have player info - //gViewPort->GetAllPlayersInfo(); - gHUD.m_Scoreboard.GetAllPlayersInfo(); + gHUD.GetAllPlayersInfo(); do { @@ -611,6 +651,68 @@ void CHudSpectator::FindNextPlayer( bool bReverse ) VectorCopy( pEnt->angles, vJumpAngles ); } iJumpSpectator = 1; +#if USE_VGUI + gViewPort->MsgFunc_ResetFade( NULL, 0, NULL ); +#endif +} + +void CHudSpectator::FindPlayer(const char *name) +{ + // MOD AUTHORS: Modify the logic of this function if you want to restrict the observer to watching + // only a subset of the players. e.g. Make it check the target's team. + + // if we are NOT in HLTV mode, spectator targets are set on server + if ( !gEngfuncs.IsSpectateOnly() ) + { + char cmdstring[32]; + // forward command to server + sprintf(cmdstring,"follow %s",name); + gEngfuncs.pfnServerCmd(cmdstring); + return; + } + + g_iUser2 = 0; + + // make sure we have player info + gHUD.GetAllPlayersInfo(); + + cl_entity_t * pEnt = NULL; + + for (int i = 1; i < MAX_PLAYERS; i++ ) + { + + pEnt = gEngfuncs.GetEntityByIndex( i ); + + if ( !IsActivePlayer( pEnt ) ) + continue; + + if(!stricmp(g_PlayerInfoList[pEnt->index].name,name)) + { + g_iUser2 = i; + break; + } + + } + + // Did we find a target? + if ( !g_iUser2 ) + { + gEngfuncs.Con_DPrintf( "No observer targets.\n" ); + // take save camera position + VectorCopy(m_cameraOrigin, vJumpOrigin); + VectorCopy(m_cameraAngles, vJumpAngles); + } + else + { + // use new entity position for roaming + VectorCopy ( pEnt->origin, vJumpOrigin ); + VectorCopy ( pEnt->angles, vJumpAngles ); + } + + iJumpSpectator = 1; +#if USE_VGUI + gViewPort->MsgFunc_ResetFade( NULL, 0, NULL ); +#endif } void CHudSpectator::HandleButtonsDown( int ButtonPressed ) @@ -622,6 +724,11 @@ void CHudSpectator::HandleButtonsDown( int ButtonPressed ) // gEngfuncs.Con_Printf( " HandleButtons:%i\n", ButtonPressed ); +#if USE_VGUI + if( !gViewPort ) + return; +#endif + //Not in intermission. if( gHUD.m_iIntermission ) return; @@ -637,8 +744,10 @@ void CHudSpectator::HandleButtonsDown( int ButtonPressed ) return; // enable spectator screen - //if( ButtonPressed & IN_DUCK ) - // gViewPort->m_pSpectatorPanel->ShowMenu( !gViewPort->m_pSpectatorPanel->m_menuVisible ); +#if USE_VGUI + if( ButtonPressed & IN_DUCK ) + gViewPort->m_pSpectatorPanel->ShowMenu( !gViewPort->m_pSpectatorPanel->m_menuVisible ); +#endif // 'Use' changes inset window mode if( ButtonPressed & IN_USE ) @@ -705,6 +814,14 @@ void CHudSpectator::HandleButtonsDown( int ButtonPressed ) void CHudSpectator::HandleButtonsUp( int ButtonPressed ) { +#if USE_VGUI + if( !gViewPort ) + return; + + if( !gViewPort->m_pSpectatorPanel->isVisible() ) + return; // dont do anything if not in spectator mode +#endif + if( ButtonPressed & ( IN_FORWARD | IN_BACK ) ) m_zoomDelta = 0.0f; @@ -800,12 +917,19 @@ void CHudSpectator::SetModes( int iNewMainMode, int iNewInsetMode ) SetCrosshair( 0, m_crosshairRect, 0, 0, 0 ); } +#if USE_VGUI + gViewPort->MsgFunc_ResetFade( NULL, 0, NULL ); +#endif + char string[128]; sprintf( string, "#Spec_Mode%d", g_iUser1 ); sprintf( string, "%c%s", HUD_PRINTCENTER, CHudTextMessage::BufferedLocaliseTextString( string ) ); gHUD.m_TextMessage.MsgFunc_TextMsg( NULL, strlen( string ) + 1, string ); } +#if USE_VGUI + gViewPort->UpdateSpectatorPanel(); +#endif } bool CHudSpectator::IsActivePlayer( cl_entity_t *ent ) @@ -1454,6 +1578,9 @@ void CHudSpectator::CheckSettings() m_pip->value = INSET_OFF; // draw small border around inset view, adjust upper black bar +#if USE_VGUI + gViewPort->m_pSpectatorPanel->EnableInsetView( m_pip->value != INSET_OFF ); +#endif } int CHudSpectator::ToggleInset( bool allowOff ) diff --git a/cl_dll/hud_spectator.h b/cl_dll/hud_spectator.h index d7187d49..800928e0 100644 --- a/cl_dll/hud_spectator.h +++ b/cl_dll/hud_spectator.h @@ -73,6 +73,7 @@ public: void HandleButtonsDown( int ButtonPressed ); void HandleButtonsUp( int ButtonPressed ); void FindNextPlayer( bool bReverse ); + void FindPlayer(const char *name); void DirectorMessage( int iSize, void *pbuf ); void SetSpectatorStartPosition(); int Init(); diff --git a/cl_dll/in_camera.cpp b/cl_dll/in_camera.cpp index 881f0c3c..ac68be5e 100644 --- a/cl_dll/in_camera.cpp +++ b/cl_dll/in_camera.cpp @@ -15,6 +15,22 @@ #include "camera.h" #include "in_defs.h" +#if _WIN32 +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#define WIN32_EXTRA_LEAN +#define HSPRITE WINDOWS_HSPRITE +#include +#undef HSPRITE +#else +typedef struct point_s +{ + int x; + int y; +} POINT; +#define GetCursorPos(x) +#define SetCursorPos(x,y) +#endif + float CL_KeyState( kbutton_t *key ); extern "C" diff --git a/cl_dll/in_defs.h b/cl_dll/in_defs.h index 7221c356..0b6cca8b 100644 --- a/cl_dll/in_defs.h +++ b/cl_dll/in_defs.h @@ -16,17 +16,4 @@ // fall over #define ROLL 2 -#if _WIN32 -#define HSPRITE HSPRITE_win32 -#include -#undef HSPRITE -#else -typedef struct point_s -{ - int x; - int y; -} POINT; -#define GetCursorPos(x) -#define SetCursorPos(x,y) -#endif #endif diff --git a/cl_dll/input.cpp b/cl_dll/input.cpp index 76659a94..d0267f9b 100644 --- a/cl_dll/input.cpp +++ b/cl_dll/input.cpp @@ -28,6 +28,10 @@ extern "C" #include #include +#if USE_VGUI +#include "vgui_TeamFortressViewport.h" +#endif + extern "C" { struct kbutton_s DLLEXPORT *KB_Find( const char *name ); @@ -645,13 +649,27 @@ void IN_Impulse( void ) void IN_ScoreDown( void ) { KeyDown( &in_score ); +#if USE_VGUI && !USE_NOVGUI_SCOREBOARD + if ( gViewPort ) + { + gViewPort->ShowScoreBoard(); + } +#else gHUD.m_Scoreboard.UserCmd_ShowScores(); +#endif } void IN_ScoreUp( void ) { KeyUp( &in_score ); +#if USE_VGUI && !USE_NOVGUI_SCOREBOARD + if ( gViewPort ) + { + gViewPort->HideScoreBoard(); + } +#else gHUD.m_Scoreboard.UserCmd_HideScores(); +#endif } void IN_MLookUp( void ) @@ -849,6 +867,12 @@ void DLLEXPORT CL_CreateMove( float frametime, struct usercmd_s *cmd, int active // cmd->buttons = CL_ButtonBits( 1 ); +#if USE_VGUI + // If they're in a modal dialog, ignore the attack button. + if(GetClientVoiceMgr()->IsInSquelchMode()) + cmd->buttons &= ~IN_ATTACK; +#endif + // Using joystick? if( in_joystick->value ) { @@ -903,9 +927,11 @@ int CL_ButtonBits( int bResetState ) if( in_attack.state & 3 ) { +#if !USE_VGUI || USE_NOVGUI_MOTD if( gHUD.m_MOTD.m_bShow ) gHUD.m_MOTD.Reset(); else +#endif bits |= IN_ATTACK; } diff --git a/cl_dll/input_mouse.h b/cl_dll/input_mouse.h index f8e2c631..0ecd8147 100644 --- a/cl_dll/input_mouse.h +++ b/cl_dll/input_mouse.h @@ -47,6 +47,21 @@ protected: // No need for goldsource input support on the platforms that are not supported by GoldSource. #if GOLDSOURCE_SUPPORT && (_WIN32 || __linux__ || __APPLE__) && (__i386 || _M_IX86) #define SUPPORT_GOLDSOURCE_INPUT 1 + +#if _WIN32 +#define HSPRITE WINDOWS_HSPRITE +#include +#undef HSPRITE +#else +typedef struct point_s +{ + int x; + int y; +} POINT; +#define GetCursorPos(x) +#define SetCursorPos(x,y) +#endif + class GoldSourceInput : public AbstractInput { public: diff --git a/cl_dll/input_xash3d.cpp b/cl_dll/input_xash3d.cpp index 2be1ffb3..ba5b14fd 100644 --- a/cl_dll/input_xash3d.cpp +++ b/cl_dll/input_xash3d.cpp @@ -187,9 +187,11 @@ void FWGSInput::IN_Move( float frametime, usercmd_t *cmd ) viewangles[YAW] -= ac_sidemove * 5; ac_sidemove = 0; } +#if !USE_VGUI || USE_NOVGUI_MOTD if( gHUD.m_MOTD.m_bShow ) gHUD.m_MOTD.scroll += rel_pitch; else +#endif viewangles[PITCH] += rel_pitch; if( viewangles[PITCH] > cl_pitchdown->value ) diff --git a/cl_dll/menu.cpp b/cl_dll/menu.cpp index fc24b917..e9166979 100644 --- a/cl_dll/menu.cpp +++ b/cl_dll/menu.cpp @@ -24,6 +24,10 @@ #include #include +#if USE_VGUI +#include "vgui_TeamFortressViewport.h" +#endif + #define MAX_MENU_STRING 512 char g_szMenuString[MAX_MENU_STRING]; char g_szPrelocalisedMenuString[MAX_MENU_STRING]; @@ -78,6 +82,11 @@ int CHudMenu::Draw( float flTime ) } // don't draw the menu if the scoreboard is being shown +#if USE_VGUI + if( gViewPort && gViewPort->IsScoreBoardVisible() ) + return 1; +#endif + // draw the menu, along the left-hand side of the screen // count the number of newlines int nlc = 0; diff --git a/cl_dll/saytext.cpp b/cl_dll/saytext.cpp index bf8eca80..d7a7dd98 100644 --- a/cl_dll/saytext.cpp +++ b/cl_dll/saytext.cpp @@ -25,6 +25,10 @@ #include #include +#if USE_VGUI +#include "vgui_TeamFortressViewport.h" +#endif + extern float *GetClientColor( int clientIndex ); #define MAX_LINES 5 @@ -95,6 +99,12 @@ int CHudSayText::Draw( float flTime ) { int y = Y_START; +#if USE_VGUI + if( ( gViewPort && gViewPort->AllowedToPrintText() == FALSE ) || !m_HUD_saytext->value ) + return 1; +#endif + + // make sure the scrolltime is within reasonable bounds, to guard against the clock being reset flScrollTime = Q_min( flScrollTime, flTime + m_HUD_saytext_time->value ); @@ -156,9 +166,18 @@ int CHudSayText::MsgFunc_SayText( const char *pszName, int iSize, void *pbuf ) void CHudSayText::SayTextPrint( const char *pszBuf, int iBufSize, int clientIndex ) { - int i; +#if USE_VGUI + if( gViewPort && gViewPort->AllowedToPrintText() == FALSE ) + { + // Print it straight to the console + ConsolePrint( pszBuf ); + return; + } +#else ConsolePrint( pszBuf ); +#endif + int i; // find an empty string slot for( i = 0; i < MAX_LINES; i++ ) { diff --git a/cl_dll/scoreboard.cpp b/cl_dll/scoreboard.cpp index b5b2ae31..2b8d7d20 100644 --- a/cl_dll/scoreboard.cpp +++ b/cl_dll/scoreboard.cpp @@ -28,23 +28,20 @@ cvar_t *cl_scoreboard_bg; cvar_t *cl_showpacketloss; -hud_player_info_t g_PlayerInfoList[MAX_PLAYERS + 1]; // player info from the engine -extra_player_info_t g_PlayerExtraInfo[MAX_PLAYERS + 1]; // additional player info sent directly to the client dll -team_info_t g_TeamInfo[MAX_TEAMS + 1]; -int g_iUser1; -int g_iUser2; -int g_iUser3; -int g_iTeamNumber; -int g_iPlayerClass; -//#include "vgui_TeamFortressViewport.h" + +#if USE_VGUI +#include "vgui_TeamFortressViewport.h" +#endif DECLARE_COMMAND( m_Scoreboard, ShowScores ) DECLARE_COMMAND( m_Scoreboard, HideScores ) +#if !USE_VGUI || USE_NOVGUI_SCOREBOARD DECLARE_MESSAGE( m_Scoreboard, ScoreInfo ) DECLARE_MESSAGE( m_Scoreboard, TeamInfo ) DECLARE_MESSAGE( m_Scoreboard, TeamScore ) +#endif int CHudScoreboard::Init( void ) { @@ -54,9 +51,11 @@ int CHudScoreboard::Init( void ) // HOOK_COMMAND( "+showscores", ShowScores ); // HOOK_COMMAND( "-showscores", HideScores ); +#if !USE_VGUI || USE_NOVGUI_SCOREBOARD HOOK_MESSAGE( ScoreInfo ); HOOK_MESSAGE( TeamScore ); HOOK_MESSAGE( TeamInfo ); +#endif InitHUDData(); @@ -502,7 +501,9 @@ int CHudScoreboard::MsgFunc_ScoreInfo( const char *pszName, int iSize, void *pbu g_PlayerExtraInfo[cl].playerclass = playerclass; g_PlayerExtraInfo[cl].teamnumber = teamnumber; - //gViewPort->UpdateOnPlayerInfo(); +#if USE_VGUI + gViewPort->UpdateOnPlayerInfo(); +#endif } return 1; diff --git a/cl_dll/text_message.cpp b/cl_dll/text_message.cpp index daeacf3f..9f1a55ad 100644 --- a/cl_dll/text_message.cpp +++ b/cl_dll/text_message.cpp @@ -26,6 +26,10 @@ #include #include "parsemsg.h" +#if USE_VGUI +#include "vgui_TeamFortressViewport.h" +#endif + DECLARE_MESSAGE( m_TextMessage, TextMsg ) int CHudTextMessage::Init( void ) @@ -178,6 +182,11 @@ int CHudTextMessage::MsgFunc_TextMsg( const char *pszName, int iSize, void *pbuf char *psz = szBuf[5]; +#if USE_VGUI + if( gViewPort && gViewPort->AllowedToPrintText() == FALSE ) + return 1; +#endif + switch( msg_dest ) { case HUD_PRINTCENTER: diff --git a/cl_dll/vgui_ClassMenu.cpp b/cl_dll/vgui_ClassMenu.cpp new file mode 100644 index 00000000..568ed98c --- /dev/null +++ b/cl_dll/vgui_ClassMenu.cpp @@ -0,0 +1,436 @@ +//=========== (C) Copyright 1996-2002 Valve, L.L.C. All rights reserved. =========== +// +// The copyright to the contents herein is the property of Valve, L.L.C. +// The contents may be used and/or copied only with the written permission of +// Valve, L.L.C., or in accordance with the terms and conditions stipulated in +// the agreement/contract under which the contents have been supplied. +// +// Purpose: TFC Class Menu +// +// $Workfile: $ +// $Date: $ +// +//----------------------------------------------------------------------------- +// $Log: $ +// +// $NoKeywords: $ +//============================================================================= + +#include "VGUI_Font.h" +#include + +#include "hud.h" +#include "cl_util.h" +#include "camera.h" +#include "kbutton.h" +#include "cvardef.h" +#include "usercmd.h" +#include "const.h" +#include "camera.h" +#include "in_defs.h" +#include "parsemsg.h" + +#include "vgui_int.h" +#include "vgui_TeamFortressViewport.h" + +// Class Menu Dimensions +#define CLASSMENU_TITLE_X XRES(40) +#define CLASSMENU_TITLE_Y YRES(32) +#define CLASSMENU_TOPLEFT_BUTTON_X XRES(40) +#define CLASSMENU_TOPLEFT_BUTTON_Y YRES(80) +#define CLASSMENU_BUTTON_SIZE_X XRES(124) +#define CLASSMENU_BUTTON_SIZE_Y YRES(24) +#define CLASSMENU_BUTTON_SPACER_Y YRES(8) +#define CLASSMENU_WINDOW_X XRES(176) +#define CLASSMENU_WINDOW_Y YRES(80) +#define CLASSMENU_WINDOW_SIZE_X XRES(424) +#define CLASSMENU_WINDOW_SIZE_Y YRES(312) +#define CLASSMENU_WINDOW_TEXT_X XRES(150) +#define CLASSMENU_WINDOW_TEXT_Y YRES(80) +#define CLASSMENU_WINDOW_NAME_X XRES(150) +#define CLASSMENU_WINDOW_NAME_Y YRES(8) +#define CLASSMENU_WINDOW_PLAYERS_Y YRES(42) + +// Creation +CClassMenuPanel::CClassMenuPanel( int iTrans, int iRemoveMe, int x, int y, int wide, int tall ) : CMenuPanel( iTrans, iRemoveMe, x, y, wide, tall ) +{ + // don't show class graphics at below 640x480 resolution + bool bShowClassGraphic = true; + if( ScreenWidth < 640 ) + { + bShowClassGraphic = false; + } + + memset( m_pClassImages, 0, sizeof(m_pClassImages) ); + + // Get the scheme used for the Titles + CSchemeManager *pSchemes = gViewPort->GetSchemeManager(); + + // schemes + SchemeHandle_t hTitleScheme = pSchemes->getSchemeHandle( "Title Font" ); + SchemeHandle_t hClassWindowText = pSchemes->getSchemeHandle( "Briefing Text" ); + + // color schemes + int r, g, b, a; + + // Create the title + Label *pLabel = new Label( "", CLASSMENU_TITLE_X, CLASSMENU_TITLE_Y ); + pLabel->setParent( this ); + pLabel->setFont( pSchemes->getFont( hTitleScheme ) ); + pSchemes->getFgColor( hTitleScheme, r, g, b, a ); + pLabel->setFgColor( r, g, b, a ); + pSchemes->getBgColor( hTitleScheme, r, g, b, a ); + pLabel->setBgColor( r, g, b, a ); + pLabel->setContentAlignment( vgui::Label::a_west ); + pLabel->setText(gHUD.m_TextMessage.BufferedLocaliseTextString( "#Title_SelectYourClass" ) ); + + // Create the Scroll panel + m_pScrollPanel = new CTFScrollPanel( CLASSMENU_WINDOW_X, CLASSMENU_WINDOW_Y, CLASSMENU_WINDOW_SIZE_X, CLASSMENU_WINDOW_SIZE_Y ); + m_pScrollPanel->setParent( this ); + //force the scrollbars on, so after the validate clientClip will be smaller + m_pScrollPanel->setScrollBarAutoVisible( false, false ); + m_pScrollPanel->setScrollBarVisible( true, true ); + m_pScrollPanel->setBorder( new LineBorder( Color( 255 * 0.7, 170 * 0.7, 0, 0 ) ) ); + m_pScrollPanel->validate(); + + int clientWide=m_pScrollPanel->getClient()->getWide(); + + //turn scrollpanel back into auto show scrollbar mode and validate + m_pScrollPanel->setScrollBarAutoVisible( false, true ); + m_pScrollPanel->setScrollBarVisible( false, false ); + m_pScrollPanel->validate(); + + // Create the Class buttons +#ifdef _TFC + for( int i = 0; i <= PC_RANDOM; i++ ) + { + char sz[256]; + int iYPos = CLASSMENU_TOPLEFT_BUTTON_Y + ( ( CLASSMENU_BUTTON_SIZE_Y + CLASSMENU_BUTTON_SPACER_Y ) * i ); + + ActionSignal *pASignal = new CMenuHandler_StringCommandClassSelect( sTFClassSelection[i], true ); + + // Class button + sprintf( sz, "%s", CHudTextMessage::BufferedLocaliseTextString( sLocalisedClasses[i] ) ); + m_pButtons[i] = new ClassButton( i, sz, CLASSMENU_TOPLEFT_BUTTON_X, iYPos, CLASSMENU_BUTTON_SIZE_X, CLASSMENU_BUTTON_SIZE_Y, true ); + + // RandomPC uses '0' + if( i >= 1 && i <= 9 ) + { + sprintf( sz, "%d", i ); + } + else + { + strcpy( sz, "0" ); + } + m_pButtons[i]->setBoundKey( sz[0] ); + m_pButtons[i]->setContentAlignment( vgui::Label::a_west ); + m_pButtons[i]->addActionSignal( pASignal ); + m_pButtons[i]->addInputSignal( new CHandler_MenuButtonOver(this, i) ); + m_pButtons[i]->setParent( this ); + + // Create the Class Info Window + // m_pClassInfoPanel[i] = new CTransparentPanel( 255, CLASSMENU_WINDOW_X, CLASSMENU_WINDOW_Y, CLASSMENU_WINDOW_SIZE_X, CLASSMENU_WINDOW_SIZE_Y ); + m_pClassInfoPanel[i] = new CTransparentPanel( 255, 0, 0, clientWide, CLASSMENU_WINDOW_SIZE_Y ); + m_pClassInfoPanel[i]->setParent( m_pScrollPanel->getClient() ); + // m_pClassInfoPanel[i]->setVisible( false ); + + // don't show class pic in lower resolutions + int textOffs = XRES( 8 ); + + if( bShowClassGraphic ) + { + textOffs = CLASSMENU_WINDOW_NAME_X; + } + + // Create the Class Name Label + sprintf( sz, "#Title_%s", sTFClassSelection[i] ); + char *localName=CHudTextMessage::BufferedLocaliseTextString( sz ); + Label *pNameLabel = new Label( "", textOffs, CLASSMENU_WINDOW_NAME_Y ); + pNameLabel->setFont( pSchemes->getFont( hTitleScheme ) ); + pNameLabel->setParent( m_pClassInfoPanel[i] ); + pSchemes->getFgColor( hTitleScheme, r, g, b, a ); + pNameLabel->setFgColor( r, g, b, a ); + pSchemes->getBgColor( hTitleScheme, r, g, b, a ); + pNameLabel->setBgColor( r, g, b, a ); + pNameLabel->setContentAlignment( vgui::Label::a_west ); + // pNameLabel->setBorder( new LineBorder() ); + pNameLabel->setText( "%s", localName); + + // Create the Class Image + if( bShowClassGraphic ) + { + for( int team = 0; team < 2; team++ ) + { + if( team == 1 ) + { + sprintf( sz, "%sred", sTFClassSelection[i] ); + } + else + { + sprintf( sz, "%sblue", sTFClassSelection[i] ); + } + + m_pClassImages[team][i] = new CImageLabel( sz, 0, 0, CLASSMENU_WINDOW_TEXT_X, CLASSMENU_WINDOW_TEXT_Y ); + + CImageLabel *pLabel = m_pClassImages[team][i]; + pLabel->setParent( m_pClassInfoPanel[i] ); + // pLabel->setBorder( new LineBorder() ); + + if( team != 1 ) + { + pLabel->setVisible( false ); + } + + // Reposition it based upon it's size + int xOut, yOut; + pNameLabel->getTextSize( xOut, yOut ); + pLabel->setPos( ( CLASSMENU_WINDOW_TEXT_X - pLabel->getWide() ) / 2, yOut / 2 ); + } + } + + // Create the Player count string + gHUD.m_TextMessage.LocaliseTextString( "#Title_CurrentlyOnYourTeam", m_sPlayersOnTeamString, STRLENMAX_PLAYERSONTEAM ); + m_pPlayers[i] = new Label( "", textOffs, CLASSMENU_WINDOW_PLAYERS_Y ); + m_pPlayers[i]->setParent( m_pClassInfoPanel[i] ); + m_pPlayers[i]->setBgColor( 0, 0, 0, 255 ); + m_pPlayers[i]->setContentAlignment( vgui::Label::a_west ); + m_pPlayers[i]->setFont( pSchemes->getFont( hClassWindowText ) ); + + // Open up the Class Briefing File + sprintf(sz, "classes/short_%s.txt", sTFClassSelection[i]); + char *cText = "Class Description not available."; + char *pfile = (char *)gEngfuncs.COM_LoadFile( sz, 5, NULL ); + if( pfile ) + { + cText = pfile; + } + + // Create the Text info window + TextPanel *pTextWindow = new TextPanel( cText, textOffs, CLASSMENU_WINDOW_TEXT_Y, ( CLASSMENU_WINDOW_SIZE_X - textOffs ) - 5, CLASSMENU_WINDOW_SIZE_Y - CLASSMENU_WINDOW_TEXT_Y ); + pTextWindow->setParent( m_pClassInfoPanel[i] ); + pTextWindow->setFont( pSchemes->getFont( hClassWindowText ) ); + pSchemes->getFgColor( hClassWindowText, r, g, b, a ); + pTextWindow->setFgColor( r, g, b, a ); + pSchemes->getBgColor( hClassWindowText, r, g, b, a ); + pTextWindow->setBgColor( r, g, b, a ); + + // Resize the Info panel to fit it all + int wide,tall; + pTextWindow->getTextImage()->getTextSizeWrapped( wide, tall ); + pTextWindow->setSize( wide, tall ); + + int xx, yy; + pTextWindow->getPos( xx, yy ); + int maxX = xx + wide; + int maxY = yy + tall; + + //check to see if the image goes lower than the text + //just use the red teams [0] images + if( m_pClassImages[0][i] != null ) + { + m_pClassImages[0][i]->getPos( xx, yy ); + if( ( yy + m_pClassImages[0][i]->getTall() ) > maxY ) + { + maxY = yy + m_pClassImages[0][i]->getTall(); + } + } + + m_pClassInfoPanel[i]->setSize( maxX , maxY ); + if( pfile ) + gEngfuncs.COM_FreeFile( pfile ); + // m_pClassInfoPanel[i]->setBorder( new LineBorder() ); + } +#endif + // Create the Cancel button + m_pCancelButton = new CommandButton( gHUD.m_TextMessage.BufferedLocaliseTextString( "#Menu_Cancel" ), CLASSMENU_TOPLEFT_BUTTON_X, 0, CLASSMENU_BUTTON_SIZE_X, CLASSMENU_BUTTON_SIZE_Y ); + m_pCancelButton->setParent( this ); + m_pCancelButton->addActionSignal( new CMenuHandler_TextWindow( HIDE_TEXTWINDOW ) ); + + m_iCurrentInfo = 0; +} + +// Update +void CClassMenuPanel::Update() +{ + // Don't allow the player to join a team if they're not in a team + if( !g_iTeamNumber ) + return; + + int iYPos = CLASSMENU_TOPLEFT_BUTTON_Y; + + // Cycle through the rest of the buttons +#ifdef _TFC + for( int i = 0; i <= PC_RANDOM; i++ ) + { + bool bCivilian = ( gViewPort->GetValidClasses( g_iTeamNumber ) == -1 ); + + if( bCivilian ) + { + // If this team can only be civilians, only the civilian button's visible + if( i == 0 ) + { + m_pButtons[0]->setVisible( true ); + SetActiveInfo( 0 ); + iYPos += CLASSMENU_BUTTON_SIZE_Y + CLASSMENU_BUTTON_SPACER_Y; + } + else + { + m_pButtons[i]->setVisible( false ); + } + } + else + { + if( m_pButtons[i]->IsNotValid() || i == 0 ) + { + m_pButtons[i]->setVisible( false ); + } + else + { + m_pButtons[i]->setVisible( true ); + m_pButtons[i]->setPos( CLASSMENU_TOPLEFT_BUTTON_X, iYPos ); + iYPos += CLASSMENU_BUTTON_SIZE_Y + CLASSMENU_BUTTON_SPACER_Y; + + // Start with the first option up + if( !m_iCurrentInfo ) + SetActiveInfo( i ); + } + } + + // Now count the number of teammembers of this class + int iTotal = 0; + for( int j = 1; j < MAX_PLAYERS; j++ ) + { + if( g_PlayerInfoList[j].name == 0 ) + continue; // empty player slot, skip + if( g_PlayerExtraInfo[j].teamname[0] == 0 ) + continue; // skip over players who are not in a team + if( g_PlayerInfoList[j].thisplayer ) + continue; // skip this player + if( g_PlayerExtraInfo[j].teamnumber != g_iTeamNumber ) + continue; // skip over players in other teams + + // If this team is forced to be civilians, just count the number of teammates + if( g_PlayerExtraInfo[j].playerclass != i && !bCivilian ) + continue; + + iTotal++; + } + + char sz[256]; + sprintf( sz, m_sPlayersOnTeamString, iTotal ); + m_pPlayers[i]->setText( "%s", sz ); + + // Set the text color to the teamcolor + m_pPlayers[i]->setFgColor( iTeamColors[g_iTeamNumber % iNumberOfTeamColors][0], + iTeamColors[g_iTeamNumber % iNumberOfTeamColors][1], + iTeamColors[g_iTeamNumber % iNumberOfTeamColors][2], + 0 ); + + // set the graphic to be the team pick + for( int team = 0; team < MAX_TEAMS; team++ ) + { + // unset all the other images + if( m_pClassImages[team][i] ) + { + m_pClassImages[team][i]->setVisible( false ); + } + + // set the current team image + if( m_pClassImages[g_iTeamNumber - 1][i] != 0 ) + { + m_pClassImages[g_iTeamNumber - 1][i]->setVisible( true ); + } + else if( m_pClassImages[0][i] ) + { + m_pClassImages[0][i]->setVisible( true ); + } + } + } +#endif + + // If the player already has a class, make the cancel button visible + if( g_iPlayerClass ) + { + m_pCancelButton->setPos( CLASSMENU_TOPLEFT_BUTTON_X, iYPos ); + m_pCancelButton->setVisible( true ); + } + else + { + m_pCancelButton->setVisible( false ); + } +} + +//====================================== +// Key inputs for the Class Menu +bool CClassMenuPanel::SlotInput( int iSlot ) +{ + if( ( iSlot < 0 ) || ( iSlot > 9 ) ) + return false; + + if( !m_pButtons[iSlot] ) + return false; + + // Is the button pushable? (0 is special case) + if( iSlot == 0 ) + { + // Selects Civilian and RandomPC + if( gViewPort->GetValidClasses( g_iTeamNumber ) == -1 ) + { + m_pButtons[0]->fireActionSignal(); + return true; + } + + // Select RandomPC + iSlot = 10; + } + + if( !( m_pButtons[iSlot]->IsNotValid() ) ) + { + m_pButtons[iSlot]->fireActionSignal(); + return true; + } + + return false; +} + +//====================================== +// Update the Class menu before opening it +void CClassMenuPanel::Open( void ) +{ + Update(); + CMenuPanel::Open(); +} + +//----------------------------------------------------------------------------- +// Purpose: Called each time a new level is started. +//----------------------------------------------------------------------------- +void CClassMenuPanel::Initialize( void ) +{ + setVisible( false ); + m_pScrollPanel->setScrollValue( 0, 0 ); +} + +//====================================== +// Mouse is over a class button, bring up the class info +void CClassMenuPanel::SetActiveInfo( int iInput ) +{ + // Remove all the Info panels and bring up the specified one +#ifdef _TFC + for( int i = 0; i <= PC_RANDOM; i++ ) + { + m_pButtons[i]->setArmed( false ); + m_pClassInfoPanel[i]->setVisible( false ); + } + + if( iInput > PC_RANDOM || iInput < 0 ) +#endif + iInput = 0; + + m_pButtons[iInput]->setArmed( true ); + m_pClassInfoPanel[iInput]->setVisible( true ); + m_iCurrentInfo = iInput; + + m_pScrollPanel->setScrollValue( 0, 0 ); + m_pScrollPanel->validate(); +} + diff --git a/cl_dll/vgui_ConsolePanel.cpp b/cl_dll/vgui_ConsolePanel.cpp new file mode 100644 index 00000000..ca33636a --- /dev/null +++ b/cl_dll/vgui_ConsolePanel.cpp @@ -0,0 +1,97 @@ +//========= Copyright (c) 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "vgui_ConsolePanel.h" +#include "hud.h" +#include +#include +#include +#include +#include + +using namespace vgui; + +namespace +{ + +class Handler : public ActionSignal +{ +private: + + ConsolePanel *_consolePanel; + +public: + + Handler( ConsolePanel *consolePanel ) + { + _consolePanel = consolePanel; + } + +public: + + virtual void actionPerformed( Panel *panel ) + { + _consolePanel->doExecCommand(); + } +}; + +} + +ConsolePanel::ConsolePanel( int x, int y, int wide, int tall ) : Panel( x, y, wide, tall ) +{ + setBorder( new EtchedBorder() ); + + _textGrid = new TextGrid( 80, 21, 5, 5, 200, 100 ); + _textGrid->setBorder( new LoweredBorder() ); + _textGrid->setParent( this ); + + _textEntry=new TextEntry( "", 5, 5, 200, 20 ); + _textEntry->setParent( this ); + _textEntry->addActionSignal( new Handler( this ) ); +} + +int ConsolePanel::print( const char *text ) +{ + return _textGrid->printf( "%s", text ); +} + +int ConsolePanel::vprintf( const char *format, va_list argList ) +{ + return _textGrid->vprintf( format, argList ); +} + +int ConsolePanel::printf( const char* format, ... ) +{ + va_list argList; + va_start( argList, format ); + int ret = vprintf( format, argList ); + va_end( argList ); + return ret; +} + +void ConsolePanel::doExecCommand() +{ + char buf[2048]; + _textEntry->getText( 0, buf, sizeof buf ); + _textEntry->setText( null, 0 ); + gEngfuncs.pfnClientCmd( buf ); +} + +void ConsolePanel::setSize( int wide, int tall ) +{ + Panel::setSize( wide, tall ); + + getPaintSize( wide, tall ); + + _textGrid->setBounds( 5, 5, wide - 10, tall - 35 ); + _textEntry->setBounds( 5, tall - 25, wide - 10, 20 ); +} + + + + + diff --git a/cl_dll/vgui_ConsolePanel.h b/cl_dll/vgui_ConsolePanel.h new file mode 100644 index 00000000..cc255a73 --- /dev/null +++ b/cl_dll/vgui_ConsolePanel.h @@ -0,0 +1,37 @@ +//========= Copyright (c) 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef CONSOLEPANEL_H +#define CONSOLEPANEL_H + +#include +#include + +namespace vgui +{ + class TextGrid; + class TextEntry; +} + +class ConsolePanel : public vgui::Panel +{ +private: + vgui::TextGrid *_textGrid; + vgui::TextEntry *_textEntry; +public: + ConsolePanel( int x, int y, int wide, int tall ); +public: + virtual void setSize( int wide, int tall ); + virtual int print( const char *text ); + virtual int vprintf( const char *format, va_list argList ); + virtual int printf( const char *format, ... ); + virtual void doExecCommand(); +}; + + + +#endif diff --git a/cl_dll/vgui_ControlConfigPanel.cpp b/cl_dll/vgui_ControlConfigPanel.cpp new file mode 100644 index 00000000..dbef1a3f --- /dev/null +++ b/cl_dll/vgui_ControlConfigPanel.cpp @@ -0,0 +1,216 @@ +//========= Copyright (c) 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include +#include "vgui_ControlConfigPanel.h" +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace vgui; + +namespace +{ +class FooTablePanel : public TablePanel +{ +private: + Label *_label; + TextEntry *_textEntry; + ControlConfigPanel *_controlConfigPanel; +public: + FooTablePanel( ControlConfigPanel *controlConfigPanel, int x, int y, int wide, int tall, int columnCount ) : TablePanel( x, y, wide, tall, columnCount ) + { + _controlConfigPanel = controlConfigPanel; + _label = new Label( "You are a dumb monkey", 0, 0, 100, 20 ); + _label->setBgColor( Scheme::sc_primary3 ); + _label->setFgColor( Scheme::sc_primary1 ); + _label->setFont( Scheme::sf_primary3 ); + + _textEntry=new TextEntry( "", 0, 0, 100, 20 ); + // _textEntry->setFont( Scheme::sf_primary3 ); + } +public: + virtual int getRowCount() + { + return _controlConfigPanel->GetCVarCount(); + } + + virtual int getCellTall( int row ) + { + return 12; + } + + virtual Panel *getCellRenderer( int column, int row,bool columnSelected, bool rowSelected, bool cellSelected ) + { + char cvar[128], desc[128], bind[128], bindAlt[128]; + _controlConfigPanel->GetCVar( row, cvar, 128, desc, 128 ); + + if( cellSelected ) + { + _label->setBgColor( Scheme::sc_primary1 ); + _label->setFgColor( Scheme::sc_primary3 ); + } + else if( rowSelected ) + { + _label->setBgColor( Scheme::sc_primary2 ); + _label->setFgColor( Scheme::sc_primary1 ); + } + else + { + _label->setBgColor( Scheme::sc_primary3 ); + _label->setFgColor( Scheme::sc_primary1 ); + } + + switch( column ) + { + case 0: + { + _label->setText( desc ); + _label->setContentAlignment( Label::a_west ); + break; + } + case 1: + { + _controlConfigPanel->GetCVarBind( cvar, bind, 128, bindAlt, 128 ); + _label->setText( bind ); + _label->setContentAlignment( Label::a_center ); + break; + } + case 2: + { + _controlConfigPanel->GetCVarBind( cvar, bind, 128, bindAlt, 128 ); + _label->setText( bindAlt ); + _label->setContentAlignment( Label::a_center ); + break; + } + default: + { + _label->setText( "" ); + break; + } + } + + return _label; + } + virtual Panel *startCellEditing( int column, int row ) + { + _textEntry->setText( "Goat", strlen( "Goat" ) ); + _textEntry->requestFocus(); + return _textEntry; + } +}; +} + +ControlConfigPanel::ControlConfigPanel( int x, int y, int wide, int tall ) : Panel( x, y, wide, tall ) +{ + setPaintBorderEnabled( false ); + setPaintBackgroundEnabled( false ); + setPaintEnabled( false ); + + _actionLabel = new Label( "Action" ); + _actionLabel->setBgColor( Scheme::sc_primary3 ); + _actionLabel->setFgColor( Scheme::sc_primary3 ); + + _keyButtonLabel = new Label( "Key / Button" ); + _keyButtonLabel->setBgColor( Scheme::sc_primary3 ); + _keyButtonLabel->setFgColor( Scheme::sc_primary3 ); + + _alternateLabel = new Label( "Alternate" ); + _alternateLabel->setBgColor( Scheme::sc_primary3 ); + _alternateLabel->setFgColor( Scheme::sc_primary3 ); + + _headerPanel=new HeaderPanel( 0, 0, wide, 20 ); + _headerPanel->setParent( this ); + + _headerPanel->addSectionPanel( _actionLabel ); + _headerPanel->addSectionPanel( _keyButtonLabel ); + _headerPanel->addSectionPanel( _alternateLabel ); + + _headerPanel->setSliderPos( 0, wide / 2 ); + _headerPanel->setSliderPos( 1, ( wide / 2 ) + ( wide / 4 ) ); + _headerPanel->setSliderPos( 2, wide ); + + _scrollPanel=new ScrollPanel( 0, 20, wide, tall - 20 ); + _scrollPanel->setParent( this ); + _scrollPanel->setPaintBorderEnabled( false ); + _scrollPanel->setPaintBackgroundEnabled( false ); + _scrollPanel->setPaintEnabled( false ); + _scrollPanel->getClient()->setPaintBorderEnabled( false ); + _scrollPanel->getClient()->setPaintBackgroundEnabled( false ); + _scrollPanel->getClient()->setPaintEnabled( false ); + _scrollPanel->setScrollBarVisible( false, true ); + + _tablePanel = new FooTablePanel( this, 0, 0, _scrollPanel->getClient()->getWide(), 800, 3 ); + _tablePanel->setParent( _scrollPanel->getClient() ); + _tablePanel->setHeaderPanel( _headerPanel ); + _tablePanel->setBgColor( Color( 200, 0, 0, 255 ) ); + _tablePanel->setFgColor( Color( Scheme::sc_primary2 ) ); + _tablePanel->setGridVisible( true, true ); + _tablePanel->setGridSize( 1, 1 ); +} + +void ControlConfigPanel::AddCVar( const char *cvar, const char *desc ) +{ + _cvarDar.addElement( vgui_strdup( cvar ) ); + _descDar.addElement( vgui_strdup( desc ) ); +} + +int ControlConfigPanel::GetCVarCount() +{ + return _cvarDar.getCount(); +} + +void ControlConfigPanel::GetCVar( int index, char *cvar, int cvarLen, char *desc, int descLen ) +{ + vgui_strcpy( cvar, cvarLen, _cvarDar[index] ); + vgui_strcpy( desc, descLen, _descDar[index] ); +} + +void ControlConfigPanel::AddCVarFromInputStream( InputStream *is ) +{ + if( is == null ) + { + return; + } + + DataInputStream dis( is ); + + bool success; + + while( 1 ) + { + char buf[256], cvar[128], desc[128]; + + dis.readLine( buf, 256, success ); + + if( !success ) + { + break; + } + + if( sscanf( buf, "\"%[^\"]\" \"%[^\"]\"", cvar, desc ) == 2 ) + { + AddCVar( cvar, desc ); + } + } +} + +void ControlConfigPanel::GetCVarBind( const char *cvar, char *bind, int bindLen, char *bindAlt, int bindAltLen ) +{ + sprintf( bind,"%s : Bind", cvar ); + sprintf( bindAlt,"%s : BindAlt", cvar ); +} + +void ControlConfigPanel::SetCVarBind( const char *cvar, const char *bind, const char *bindAlt ) +{ +} + diff --git a/cl_dll/vgui_ControlConfigPanel.h b/cl_dll/vgui_ControlConfigPanel.h new file mode 100644 index 00000000..963adb14 --- /dev/null +++ b/cl_dll/vgui_ControlConfigPanel.h @@ -0,0 +1,43 @@ +//========= Copyright (c) 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef CONTROLCONFIGPANEL_H +#define CONTROLCONFIGPANEL_H + +#include +#include + +namespace vgui +{ + class HeaderPanel; + class TablePanel; + class ScrollPanel; + class InputStream; + class Label; +} + +class ControlConfigPanel : public vgui::Panel +{ +private: + vgui::HeaderPanel *_headerPanel; + vgui::TablePanel *_tablePanel; + vgui::ScrollPanel *_scrollPanel; + vgui::Dar _cvarDar; + vgui::Dar _descDar; + vgui::Label *_actionLabel; + vgui::Label *_keyButtonLabel; + vgui::Label *_alternateLabel; +public: + ControlConfigPanel( int x, int y, int wide, int tall ); + void AddCVar( const char *cvar, const char *desc ); + void AddCVarFromInputStream( vgui::InputStream *is ); + int GetCVarCount(); + void GetCVar( int index, char *cvar, int cvarLen, char *desc, int descLen ); + void GetCVarBind( const char *cvar, char *bind, int bindLen, char *bindAlt, int bindAltLen ); + void SetCVarBind( const char *cvar, const char *bind, const char *bindAlt ); +}; +#endif diff --git a/cl_dll/vgui_CustomObjects.cpp b/cl_dll/vgui_CustomObjects.cpp new file mode 100644 index 00000000..920956a3 --- /dev/null +++ b/cl_dll/vgui_CustomObjects.cpp @@ -0,0 +1,551 @@ +//=========== (C) Copyright 1996-2002 Valve, L.L.C. All rights reserved. =========== +// +// The copyright to the contents herein is the property of Valve, L.L.C. +// The contents may be used and/or copied only with the written permission of +// Valve, L.L.C., or in accordance with the terms and conditions stipulated in +// the agreement/contract under which the contents have been supplied. +// +// Purpose: Contains implementation of various VGUI-derived objects +// +// $Workfile: $ +// $Date: $ +// +//----------------------------------------------------------------------------- +// $Log: $ +// +// $NoKeywords: $ +//============================================================================= + +#include "VGUI_Font.h" + +#include "hud.h" +#include "cl_util.h" +#include "camera.h" +#include "kbutton.h" +#include "cvardef.h" +#include "usercmd.h" +#include "const.h" +#include "camera.h" +#include "in_defs.h" +#include "parsemsg.h" + +#include "vgui_int.h" +#include "vgui_TeamFortressViewport.h" +#include "vgui_loadtga.h" + +// Arrow filenames +const char *sArrowFilenames[] = +{ + "arrowup", + "arrowdn", + "arrowlt", + "arrowrt", +}; + +// Get the name of TGA file, without a gamedir +char *GetTGANameForRes( const char *pszName ) +{ + int i; + char sz[256]; + static char gd[256]; + + if( ScreenWidth < 640 ) + i = 320; + else + i = 640; + + sprintf( sz, pszName, i ); + sprintf( gd, "gfx/vgui/%s.tga", sz ); + return gd; +} + +//----------------------------------------------------------------------------- +// Purpose: Loads a .tga file and returns a pointer to the VGUI tga object +//----------------------------------------------------------------------------- +BitmapTGA *LoadTGAForRes( const char* pImageName ) +{ + BitmapTGA *pTGA; + char sz[256]; + + sprintf( sz, "%%d_%s", pImageName ); + pTGA = vgui_LoadTGA( GetTGANameForRes( sz ) ); + + return pTGA; +} + +//=========================================================== +// All TFC Hud buttons are derived from this one. +CommandButton::CommandButton( const char *text, int x, int y, int wide, int tall, bool bNoHighlight ) : Button( "", x, y, wide, tall ) +{ + m_iPlayerClass = 0; + m_bNoHighlight = bNoHighlight; + m_bFlat = false; + Init(); + setText( text ); +} + +CommandButton::CommandButton( int iPlayerClass, const char *text, int x, int y, int wide, int tall, bool bFlat ) : Button( "", x, y, wide, tall ) +{ + m_iPlayerClass = iPlayerClass; + m_bNoHighlight = false; + m_bFlat = bFlat; + Init(); + setText( text ); +} + +CommandButton::CommandButton( const char *text, int x, int y, int wide, int tall, bool bNoHighlight, bool bFlat ) : Button( "", x, y, wide, tall ) +{ + m_iPlayerClass = 0; + m_bFlat = bFlat; + m_bNoHighlight = bNoHighlight; + Init(); + setText( text ); +} + +void CommandButton::Init( void ) +{ + m_pSubMenu = NULL; + m_pSubLabel = NULL; + m_pParentMenu = NULL; + + // Set text color to orange + setFgColor( Scheme::sc_primary1 ); + + // left align + setContentAlignment( vgui::Label::a_west ); + + // Add the Highlight signal + if( !m_bNoHighlight ) + addInputSignal( new CHandler_CommandButtonHighlight( this ) ); + + // not bound to any button yet + m_cBoundKey = 0; +} + +//----------------------------------------------------------------------------- +// Purpose: Prepends the button text with the current bound key +// if no bound key, then a clear space ' ' instead +//----------------------------------------------------------------------------- +void CommandButton::RecalculateText( void ) +{ + char szBuf[128]; + + if( m_cBoundKey != 0 ) + { + if( m_cBoundKey == (char)255 ) + { + strcpy( szBuf, m_sMainText ); + } + else + { + sprintf( szBuf, " %c %s", m_cBoundKey, m_sMainText ); + } + szBuf[MAX_BUTTON_SIZE-1] = 0; + } + else + { + // just draw a space if no key bound + sprintf( szBuf, " %s", m_sMainText ); + szBuf[MAX_BUTTON_SIZE - 1] = 0; + } + + Button::setText( szBuf ); +} + +void CommandButton::setText( const char *text ) +{ + strncpy( m_sMainText, text, MAX_BUTTON_SIZE ); + m_sMainText[MAX_BUTTON_SIZE - 1] = 0; + + RecalculateText(); +} + +void CommandButton::setBoundKey( char boundKey ) +{ + m_cBoundKey = boundKey; + RecalculateText(); +} + +char CommandButton::getBoundKey( void ) +{ + return m_cBoundKey; +} + +void CommandButton::AddSubMenu( CCommandMenu *pNewMenu ) +{ + m_pSubMenu = pNewMenu; + + // Prevent this button from being pushed + setMouseClickEnabled( MOUSE_LEFT, false ); +} + +void CommandButton::UpdateSubMenus( int iAdjustment ) +{ + if( m_pSubMenu ) + m_pSubMenu->RecalculatePositions( iAdjustment ); +} + +void CommandButton::paint() +{ + // Make the sub label paint the same as the button + if( m_pSubLabel ) + { + if( isSelected() ) + m_pSubLabel->PushDown(); + else + m_pSubLabel->PushUp(); + } + + // draw armed button text in white + if( isArmed() ) + { + setFgColor( Scheme::sc_secondary2 ); + } + else + { + setFgColor( Scheme::sc_primary1 ); + } + + Button::paint(); +} + +void CommandButton::paintBackground() +{ + if( m_bFlat ) + { + if( isArmed() ) + { + // Orange Border + drawSetColor( Scheme::sc_secondary1 ); + drawOutlinedRect( 0, 0, _size[0], _size[1] ); + } + } + else + { + if( isArmed() ) + { + // Orange highlight background + drawSetColor( Scheme::sc_primary2 ); + drawFilledRect( 0, 0, _size[0], _size[1] ); + } + + // Orange Border + drawSetColor( Scheme::sc_secondary1 ); + drawOutlinedRect( 0, 0, _size[0], _size[1] ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Highlights the current button, and all it's parent menus +//----------------------------------------------------------------------------- +void CommandButton::cursorEntered( void ) +{ + // unarm all the other buttons in this menu + CCommandMenu *containingMenu = getParentMenu(); + if( containingMenu ) + { + containingMenu->ClearButtonsOfArmedState(); + + // make all our higher buttons armed + CCommandMenu *pCParent = containingMenu->GetParentMenu(); + if( pCParent ) + { + CommandButton *pParentButton = pCParent->FindButtonWithSubmenu( containingMenu ); + + pParentButton->cursorEntered(); + } + } + + // arm ourselves + setArmed( true ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CommandButton::cursorExited( void ) +{ + // only clear ourselves if we have do not have a containing menu + // only stay armed if we have a sub menu + // the buttons only unarm themselves when another button is armed instead + if( !getParentMenu() || !GetSubMenu() ) + { + setArmed( false ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Returns the command menu that the button is part of, if any +// Output : CCommandMenu * +//----------------------------------------------------------------------------- +CCommandMenu *CommandButton::getParentMenu( void ) +{ + return m_pParentMenu; +} + +//----------------------------------------------------------------------------- +// Purpose: Sets the menu that contains this button +// Input : *pParentMenu - +//----------------------------------------------------------------------------- +void CommandButton::setParentMenu( CCommandMenu *pParentMenu ) +{ + m_pParentMenu = pParentMenu; +} + +//=========================================================== +int ClassButton::IsNotValid() +{ + // If this is the main ChangeClass button, remove it if the player's only able to be civilians + if( m_iPlayerClass == -1 ) + { + if( gViewPort->GetValidClasses( g_iTeamNumber ) == -1 ) + return true; + + return false; + } + + // Is it an illegal class? +#ifdef _TFC + if( ( gViewPort->GetValidClasses( 0 ) & sTFValidClassInts[m_iPlayerClass] ) || ( gViewPort->GetValidClasses( g_iTeamNumber ) & sTFValidClassInts[m_iPlayerClass] ) ) + return true; +#endif + + // Only check current class if they've got autokill on + bool bAutoKill = CVAR_GET_FLOAT( "hud_classautokill" ) != 0; + if( bAutoKill ) + { + // Is it the player's current class? + if ( +#ifdef _TFC + (gViewPort->IsRandomPC() && m_iPlayerClass == PC_RANDOM) || +#endif + (!gViewPort->IsRandomPC() && (m_iPlayerClass == g_iPlayerClass)) ) + return true; + } + + return false; +} + +//=========================================================== +// Button with Class image beneath it +CImageLabel::CImageLabel( const char *pImageName,int x,int y ) : Label( "", x, y ) +{ + setContentFitted( true ); + m_pTGA = LoadTGAForRes( pImageName ); + setImage( m_pTGA ); +} + +CImageLabel::CImageLabel( const char *pImageName, int x, int y, int wide, int tall ) : Label( "", x, y, wide, tall ) +{ + setContentFitted( true ); + m_pTGA = LoadTGAForRes( pImageName ); + setImage( m_pTGA ); +} + +//=========================================================== +// Image size +int CImageLabel::getImageWide( void ) +{ + if( m_pTGA ) + { + int iXSize, iYSize; + + m_pTGA->getSize( iXSize, iYSize ); + + return iXSize; + } + else + { + return 1; + } +} + +int CImageLabel::getImageTall( void ) +{ + if( m_pTGA ) + { + int iXSize, iYSize; + + m_pTGA->getSize( iXSize, iYSize ); + + return iYSize; + } + else + { + return 1; + } +} + +void CImageLabel::LoadImage( const char *pImageName ) +{ + if( m_pTGA ) + delete m_pTGA; + + // Load the Image + m_pTGA = LoadTGAForRes( pImageName ); + + if( m_pTGA == NULL ) + { + // we didn't find a matching image file for this resolution + // try to load file resolution independent + char sz[256]; + + sprintf( sz, "%s/%s", gEngfuncs.pfnGetGameDirectory(), pImageName ); + FileInputStream fis( sz, false ); + m_pTGA = new BitmapTGA( &fis, true ); + fis.close(); + } + + if( m_pTGA == NULL ) + return; // unable to load image + + int w,t; + + m_pTGA->getSize( w, t ); + + setSize( XRES ( w ),YRES ( t) ); + setImage( m_pTGA ); +} + +//=========================================================== +// Various overloaded paint functions for Custom VGUI objects +void CCommandMenu::paintBackground() +{ + // Transparent black background + + if( m_iSpectCmdMenu ) + drawSetColor( 0, 0, 0, 64 ); + else + drawSetColor( Scheme::sc_primary3 ); + + drawFilledRect( 0, 0, _size[0], _size[1] ); +} + +//================================================================================= +// CUSTOM SCROLLPANEL +//================================================================================= +CTFScrollButton::CTFScrollButton( int iArrow, const char *text, int x, int y, int wide, int tall ) : CommandButton( text, x, y, wide, tall ) +{ + // Set text color to orange + setFgColor( Scheme::sc_primary1 ); + + // Load in the arrow + m_pTGA = LoadTGAForRes( sArrowFilenames[iArrow] ); + setImage( m_pTGA ); + + // Highlight signal + InputSignal *pISignal = new CHandler_CommandButtonHighlight( this ); + addInputSignal( pISignal ); +} + +void CTFScrollButton::paint( void ) +{ + if( !m_pTGA ) + return; + + // draw armed button text in white + if( isArmed() ) + { + m_pTGA->setColor( Color( 255, 255, 255, 0 ) ); + } + else + { + m_pTGA->setColor( Color( 255, 255, 255, 128 ) ); + } + + m_pTGA->doPaint( this ); +} + +void CTFScrollButton::paintBackground( void ) +{ +/* + if( isArmed() ) + { + // Orange highlight background + drawSetColor( Scheme::sc_primary2 ); + drawFilledRect( 0, 0, _size[0], _size[1] ); + } + + // Orange Border + drawSetColor( Scheme::sc_secondary1 ); + drawOutlinedRect( 0, 0, _size[0] - 1, _size[1] ); +*/ +} + +void CTFSlider::paintBackground( void ) +{ + int wide, tall, nobx, noby; + + getPaintSize( wide, tall ); + getNobPos( nobx, noby ); + + // Border + drawSetColor( Scheme::sc_secondary1 ); + drawOutlinedRect( 0, 0, wide, tall ); + + if( isVertical() ) + { + // Nob Fill + drawSetColor( Scheme::sc_primary2 ); + drawFilledRect( 0, nobx, wide, noby ); + + // Nob Outline + drawSetColor( Scheme::sc_primary1 ); + drawOutlinedRect( 0, nobx, wide, noby ); + } + else + { + // Nob Fill + drawSetColor( Scheme::sc_primary2 ); + drawFilledRect( nobx, 0, noby, tall ); + + // Nob Outline + drawSetColor( Scheme::sc_primary1 ); + drawOutlinedRect( nobx, 0, noby, tall ); + } +} + +CTFScrollPanel::CTFScrollPanel( int x, int y, int wide, int tall ) : ScrollPanel( x, y, wide, tall ) +{ + ScrollBar *pScrollBar = getVerticalScrollBar(); + pScrollBar->setButton( new CTFScrollButton( ARROW_UP, "", 0, 0, 16, 16 ), 0 ); + pScrollBar->setButton( new CTFScrollButton( ARROW_DOWN, "", 0, 0, 16, 16 ), 1 ); + pScrollBar->setSlider( new CTFSlider( 0, wide - 1, wide, ( tall - ( wide * 2 ) ) + 2, true ) ); + pScrollBar->setPaintBorderEnabled( false ); + pScrollBar->setPaintBackgroundEnabled( false ); + pScrollBar->setPaintEnabled( false ); + + pScrollBar = getHorizontalScrollBar(); + pScrollBar->setButton( new CTFScrollButton( ARROW_LEFT, "", 0, 0, 16, 16 ), 0 ); + pScrollBar->setButton( new CTFScrollButton( ARROW_RIGHT, "", 0, 0, 16, 16 ), 1 ); + pScrollBar->setSlider( new CTFSlider( tall, 0, wide - ( tall * 2 ), tall, false ) ); + pScrollBar->setPaintBorderEnabled( false ); + pScrollBar->setPaintBackgroundEnabled( false ); + pScrollBar->setPaintEnabled( false ); +} + +//================================================================================= +// CUSTOM HANDLERS +//================================================================================= +void CHandler_MenuButtonOver::cursorEntered(Panel *panel) +{ + if( gViewPort && m_pMenuPanel ) + { + m_pMenuPanel->SetActiveInfo( m_iButton ); + } +} + +void CMenuHandler_StringCommandClassSelect::actionPerformed( Panel *panel ) +{ + CMenuHandler_StringCommand::actionPerformed( panel ); + + // THIS IS NOW BEING DONE ON THE TFC SERVER TO AVOID KILLING SOMEONE THEN + // HAVE THE SERVER SAY "SORRY...YOU CAN'T BE THAT CLASS". + +#if !defined _TFC + bool bAutoKill = CVAR_GET_FLOAT( "hud_classautokill" ) != 0; + if( bAutoKill && g_iPlayerClass != 0 ) + gEngfuncs.pfnClientCmd( "kill" ); +#endif +} + diff --git a/cl_dll/vgui_MOTDWindow.cpp b/cl_dll/vgui_MOTDWindow.cpp new file mode 100644 index 00000000..d5715b92 --- /dev/null +++ b/cl_dll/vgui_MOTDWindow.cpp @@ -0,0 +1,151 @@ +//=========== (C) Copyright 1996-2002 Valve, L.L.C. All rights reserved. =========== +// +// The copyright to the contents herein is the property of Valve, L.L.C. +// The contents may be used and/or copied only with the written permission of +// Valve, L.L.C., or in accordance with the terms and conditions stipulated in +// the agreement/contract under which the contents have been supplied. +// +// Purpose: +// +// $Workfile: $ +// $Date: $ +// +//----------------------------------------------------------------------------- +// $Log: $ +// +// $NoKeywords: $ +//============================================================================= + +#include "VGUI_Font.h" +#include "VGUI_ScrollPanel.h" +#include "VGUI_TextImage.h" + +#include + +#include "hud.h" +#include "cl_util.h" +#include "camera.h" +#include "kbutton.h" +#include "const.h" + +#include "vgui_int.h" +#include "vgui_TeamFortressViewport.h" + +#define MOTD_TITLE_X XRES(16) +#define MOTD_TITLE_Y YRES(16) + +#define MOTD_WINDOW_X XRES(112) +#define MOTD_WINDOW_Y YRES(80) +#define MOTD_WINDOW_SIZE_X XRES(424) +#define MOTD_WINDOW_SIZE_Y YRES(312) + +//----------------------------------------------------------------------------- +// Purpose: Displays the MOTD and basic server information +//----------------------------------------------------------------------------- +class CMessageWindowPanel : public CMenuPanel +{ +public: + CMessageWindowPanel( const char *szMOTD, const char *szTitle, int iShadeFullScreen, int iRemoveMe, int x, int y, int wide, int tall ); + +private: + CTransparentPanel *m_pBackgroundPanel; +}; + +//----------------------------------------------------------------------------- +// Purpose: Creates a new CMessageWindowPanel +// Output : CMenuPanel - interface to the panel +//----------------------------------------------------------------------------- +CMenuPanel *CMessageWindowPanel_Create( const char *szMOTD, const char *szTitle, int iShadeFullscreen, int iRemoveMe, int x, int y, int wide, int tall ) +{ + return new CMessageWindowPanel( szMOTD, szTitle, iShadeFullscreen, iRemoveMe, x, y, wide, tall ); +} + +//----------------------------------------------------------------------------- +// Purpose: Constructs a message panel +//----------------------------------------------------------------------------- +CMessageWindowPanel::CMessageWindowPanel( const char *szMOTD, const char *szTitle, int iShadeFullscreen, int iRemoveMe, int x, int y, int wide, int tall ) : CMenuPanel( iShadeFullscreen ? 100 : 255, iRemoveMe, x, y, wide, tall ) +{ + // Get the scheme used for the Titles + CSchemeManager *pSchemes = gViewPort->GetSchemeManager(); + + // schemes + SchemeHandle_t hTitleScheme = pSchemes->getSchemeHandle( "Title Font" ); + SchemeHandle_t hMOTDText = pSchemes->getSchemeHandle( "Briefing Text" ); + + // color schemes + int r, g, b, a; + + // Create the window + m_pBackgroundPanel = new CTransparentPanel( iShadeFullscreen ? 255 : 100, MOTD_WINDOW_X, MOTD_WINDOW_Y, MOTD_WINDOW_SIZE_X, MOTD_WINDOW_SIZE_Y ); + m_pBackgroundPanel->setParent( this ); + m_pBackgroundPanel->setBorder( new LineBorder( Color( 255 * 0.7, 170 * 0.7, 0, 0 ) ) ); + m_pBackgroundPanel->setVisible( true ); + + int iXSize,iYSize,iXPos,iYPos; + m_pBackgroundPanel->getPos( iXPos, iYPos ); + m_pBackgroundPanel->getSize( iXSize, iYSize ); + + // Create the title + Label *pLabel = new Label( "", iXPos + MOTD_TITLE_X, iYPos + MOTD_TITLE_Y ); + pLabel->setParent( this ); + pLabel->setFont( pSchemes->getFont( hTitleScheme ) ); + pLabel->setFont( Scheme::sf_primary1 ); + + pSchemes->getFgColor( hTitleScheme, r, g, b, a ); + pLabel->setFgColor( r, g, b, a ); + pLabel->setFgColor( Scheme::sc_primary1 ); + pSchemes->getBgColor( hTitleScheme, r, g, b, a ); + pLabel->setBgColor( r, g, b, a ); + pLabel->setContentAlignment( vgui::Label::a_west ); + pLabel->setText( "%s", szTitle); + + // Create the Scroll panel + ScrollPanel *pScrollPanel = new CTFScrollPanel( iXPos + XRES( 16 ), iYPos + MOTD_TITLE_Y * 2 + YRES( 16 ), iXSize - XRES( 32 ), iYSize - ( YRES( 48 ) + BUTTON_SIZE_Y * 2 ) ); + pScrollPanel->setParent( this ); + + // force the scrollbars on so clientClip will take them in account after the validate + pScrollPanel->setScrollBarAutoVisible( false, false ); + pScrollPanel->setScrollBarVisible( true, true ); + pScrollPanel->validate(); + + // Create the text panel + TextPanel *pText = new TextPanel( "", 0, 0, 64, 64 ); + pText->setParent( pScrollPanel->getClient() ); + + // get the font and colors from the scheme + pText->setFont( pSchemes->getFont( hMOTDText ) ); + pSchemes->getFgColor( hMOTDText, r, g, b, a ); + pText->setFgColor( r, g, b, a ); + pSchemes->getBgColor( hMOTDText, r, g, b, a ); + pText->setBgColor( r, g, b, a ); + pText->setText( szMOTD ); + + // Get the total size of the MOTD text and resize the text panel + int iScrollSizeX, iScrollSizeY; + + // First, set the size so that the client's wdith is correct at least because the + // width is critical for getting the "wrapped" size right. + // You'll see a horizontal scroll bar if there is a single word that won't wrap in the + // specified width. + pText->getTextImage()->setSize( pScrollPanel->getClientClip()->getWide(), pScrollPanel->getClientClip()->getTall() ); + pText->getTextImage()->getTextSizeWrapped( iScrollSizeX, iScrollSizeY ); + + // Now resize the textpanel to fit the scrolled size + pText->setSize( iScrollSizeX, iScrollSizeY ); + + //turn the scrollbars back into automode + pScrollPanel->setScrollBarAutoVisible( true, true ); + pScrollPanel->setScrollBarVisible( false, false ); + + pScrollPanel->validate(); + + CommandButton *pButton = new CommandButton( CHudTextMessage::BufferedLocaliseTextString( "#Menu_OK" ), iXPos + XRES( 16 ), iYPos + iYSize - YRES( 16 ) - BUTTON_SIZE_Y, CMENU_SIZE_X, BUTTON_SIZE_Y ); + pButton->addActionSignal( new CMenuHandler_TextWindow( HIDE_TEXTWINDOW ) ); + pButton->setParent( this ); +} + + + + + + diff --git a/cl_dll/vgui_SchemeManager.cpp b/cl_dll/vgui_SchemeManager.cpp new file mode 100644 index 00000000..dddd268c --- /dev/null +++ b/cl_dll/vgui_SchemeManager.cpp @@ -0,0 +1,556 @@ +//=========== (C) Copyright 1996-2002 Valve, L.L.C. All rights reserved. =========== +// +// The copyright to the contents herein is the property of Valve, L.L.C. +// The contents may be used and/or copied only with the written permission of +// Valve, L.L.C., or in accordance with the terms and conditions stipulated in +// the agreement/contract under which the contents have been supplied. +// +// Purpose: +// +// $Workfile: $ +// $Date: $ +// +//----------------------------------------------------------------------------- +// $Log: $ +// +// $NoKeywords: $ +//============================================================================= + +#include "hud.h" +#include "vgui_SchemeManager.h" +#include "cvardef.h" + +#include + + +cvar_t *g_CV_BitmapFonts; + + +void Scheme_Init() +{ + g_CV_BitmapFonts = gEngfuncs.pfnRegisterVariable("bitmapfonts", "1", 0); +} + + + +//----------------------------------------------------------------------------- +// Purpose: Scheme managers data container +//----------------------------------------------------------------------------- +class CSchemeManager::CScheme +{ +public: + enum { + SCHEME_NAME_LENGTH = 32, + FONT_NAME_LENGTH = 48, + FONT_FILENAME_LENGTH = 64, + }; + + // name + char schemeName[SCHEME_NAME_LENGTH]; + + // font + char fontName[FONT_NAME_LENGTH]; + + int fontSize; + int fontWeight; + + vgui::Font *font; + int ownFontPointer; // true if the font is ours to delete + + // scheme + byte fgColor[4]; + byte bgColor[4]; + byte armedFgColor[4]; + byte armedBgColor[4]; + byte mousedownFgColor[4]; + byte mousedownBgColor[4]; + byte borderColor[4]; + + // construction/destruction + CScheme(); + ~CScheme(); +}; + +CSchemeManager::CScheme::CScheme() +{ + schemeName[0] = 0; + fontName[0] = 0; + fontSize = 0; + fontWeight = 0; + font = NULL; + ownFontPointer = false; +} + +CSchemeManager::CScheme::~CScheme() +{ + // only delete our font pointer if we own it + if ( ownFontPointer ) + { + delete font; + } +} + +//----------------------------------------------------------------------------- +// Purpose: resolution information +// !! needs to be shared out +//----------------------------------------------------------------------------- +static int g_ResArray[] = +{ + 320, + 400, + 512, + 640, + 800, + 1024, + 1152, + 1280, + 1600 +}; +static int g_NumReses = sizeof(g_ResArray) / sizeof(int); + +static byte *LoadFileByResolution( const char *filePrefix, int xRes, const char *filePostfix ) +{ + // find our resolution in the res array + int resNum = g_NumReses - 1; + while ( g_ResArray[resNum] > xRes ) + { + resNum--; + + if ( resNum < 0 ) + return NULL; + } + + // try open the file + byte *pFile = NULL; + while ( 1 ) + { + + // try load + char fname[256]; + sprintf( fname, "%s%d%s", filePrefix, g_ResArray[resNum], filePostfix ); + pFile = gEngfuncs.COM_LoadFile( fname, 5, NULL ); + + if ( pFile ) + break; + + if ( resNum == 0 ) + return NULL; + + resNum--; + }; + + return pFile; +} + +static void ParseRGBAFromString( byte colorArray[4], const char *colorVector ) +{ + int r, g, b, a; + sscanf( colorVector, "%d %d %d %d", &r, &g, &b, &a ); + colorArray[0] = r; + colorArray[1] = g; + colorArray[2] = b; + colorArray[3] = a; +} + +//----------------------------------------------------------------------------- +// Purpose: initializes the scheme manager +// loading the scheme files for the current resolution +// Input : xRes - +// yRes - dimensions of output window +//----------------------------------------------------------------------------- +CSchemeManager::CSchemeManager( int xRes, int yRes ) +{ + // basic setup + m_pSchemeList = NULL; + m_iNumSchemes = 0; + + // find the closest matching scheme file to our resolution + char token[1024]; + char *pFile = (char*)LoadFileByResolution( "", xRes, "_textscheme.txt" ); + m_xRes = xRes; + + char *pFileStart = pFile; + + byte *pFontData; + int fontFileLength; + char fontFilename[512]; + + // + // Read the scheme descriptions from the text file, into a temporary array + // format is simply: + // = + // + // a of "SchemeName" signals a new scheme is being described + // + + const static int numTmpSchemes = 64; + static CScheme tmpSchemes[numTmpSchemes]; + memset( tmpSchemes, 0, sizeof(tmpSchemes) ); + int currentScheme = -1; + CScheme *pScheme = NULL; + + if ( !pFile ) + { + gEngfuncs.Con_DPrintf( "Unable to find *_textscheme.txt\n"); + goto buildDefaultFont; + } + + // record what has been entered so we can create defaults from the different values + bool hasFgColor, hasBgColor, hasArmedFgColor, hasArmedBgColor, hasMouseDownFgColor, hasMouseDownBgColor; + + pFile = gEngfuncs.COM_ParseFile( pFile, token ); + while ( strlen(token) > 0 && (currentScheme < numTmpSchemes) ) + { + // get the paramName name + static const int tokenSize = 64; + char paramName[tokenSize], paramValue[tokenSize]; + + strncpy( paramName, token, tokenSize ); + paramName[tokenSize-1] = 0; // ensure null termination + + // get the '=' character + pFile = gEngfuncs.COM_ParseFile( pFile, token ); + if ( stricmp( token, "=" ) ) + { + if ( currentScheme < 0 ) + { + gEngfuncs.Con_Printf( "error parsing font scheme text file at file start - expected '=', found '%s''\n", token ); + } + else + { + gEngfuncs.Con_Printf( "error parsing font scheme text file at scheme '%s' - expected '=', found '%s''\n", tmpSchemes[currentScheme].schemeName, token ); + } + break; + } + + // get paramValue + pFile = gEngfuncs.COM_ParseFile( pFile, token ); + strncpy( paramValue, token, tokenSize ); + paramValue[tokenSize-1] = 0; // ensure null termination + + // is this a new scheme? + if ( !stricmp(paramName, "SchemeName") ) + { + // setup the defaults for the current scheme + if ( pScheme ) + { + // foreground color defaults (normal -> armed -> mouse down) + if ( !hasFgColor ) + { + pScheme->fgColor[0] = pScheme->fgColor[1] = pScheme->fgColor[2] = pScheme->fgColor[3] = 255; + } + if ( !hasArmedFgColor ) + { + memcpy( pScheme->armedFgColor, pScheme->fgColor, sizeof(pScheme->armedFgColor) ); + } + if ( !hasMouseDownFgColor ) + { + memcpy( pScheme->mousedownFgColor, pScheme->armedFgColor, sizeof(pScheme->mousedownFgColor) ); + } + + // background color (normal -> armed -> mouse down) + if ( !hasBgColor ) + { + pScheme->bgColor[0] = pScheme->bgColor[1] = pScheme->bgColor[2] = pScheme->bgColor[3] = 0; + } + if ( !hasArmedBgColor ) + { + memcpy( pScheme->armedBgColor, pScheme->bgColor, sizeof(pScheme->armedBgColor) ); + } + if ( !hasMouseDownBgColor ) + { + memcpy( pScheme->mousedownBgColor, pScheme->armedBgColor, sizeof(pScheme->mousedownBgColor) ); + } + + // font size + if ( !pScheme->fontSize ) + { + pScheme->fontSize = 17; + } + if ( !pScheme->fontName[0] ) + { + strcpy( pScheme->fontName, "Arial" ); + } + } + + // create the new scheme + currentScheme++; + pScheme = &tmpSchemes[currentScheme]; + hasFgColor = hasBgColor = hasArmedFgColor = hasArmedBgColor = hasMouseDownFgColor = hasMouseDownBgColor = false; + + strncpy( pScheme->schemeName, paramValue, CScheme::SCHEME_NAME_LENGTH ); + pScheme->schemeName[CScheme::SCHEME_NAME_LENGTH-1] = '\0'; // ensure null termination of string + } + + if ( !pScheme ) + { + gEngfuncs.Con_Printf( "font scheme text file MUST start with a 'SchemeName'\n"); + break; + } + + // pull the data out into the scheme + if ( !stricmp(paramName, "FontName") ) + { + strncpy( pScheme->fontName, paramValue, CScheme::FONT_NAME_LENGTH ); + pScheme->fontName[CScheme::FONT_NAME_LENGTH-1] = 0; + } + else if ( !stricmp(paramName, "FontSize") ) + { + pScheme->fontSize = atoi( paramValue ); + } + else if ( !stricmp(paramName, "FontWeight") ) + { + pScheme->fontWeight = atoi( paramValue ); + } + else if ( !stricmp(paramName, "FgColor") ) + { + ParseRGBAFromString( pScheme->fgColor, paramValue ); + hasFgColor = true; + } + else if ( !stricmp(paramName, "BgColor") ) + { + ParseRGBAFromString( pScheme->bgColor, paramValue ); + hasBgColor = true; + } + else if ( !stricmp(paramName, "FgColorArmed") ) + { + ParseRGBAFromString( pScheme->armedFgColor, paramValue ); + hasArmedFgColor = true; + } + else if ( !stricmp(paramName, "BgColorArmed") ) + { + ParseRGBAFromString( pScheme->armedBgColor, paramValue ); + hasArmedBgColor = true; + } + else if ( !stricmp(paramName, "FgColorMousedown") ) + { + ParseRGBAFromString( pScheme->mousedownFgColor, paramValue ); + hasMouseDownFgColor = true; + } + else if ( !stricmp(paramName, "BgColorMousedown") ) + { + ParseRGBAFromString( pScheme->mousedownBgColor, paramValue ); + hasMouseDownBgColor = true; + } + else if ( !stricmp(paramName, "BorderColor") ) + { + ParseRGBAFromString( pScheme->borderColor, paramValue ); + hasMouseDownBgColor = true; + } + + // get the new token last, so we now if the loop needs to be continued or not + pFile = gEngfuncs.COM_ParseFile( pFile, token ); + } + + // free the file + gEngfuncs.COM_FreeFile( pFileStart ); + + +buildDefaultFont: + + // make sure we have at least 1 valid font + if ( currentScheme < 0 ) + { + currentScheme = 0; + strcpy( tmpSchemes[0].schemeName, "Default Scheme" ); + strcpy( tmpSchemes[0].fontName, "Arial" ); + tmpSchemes[0].fontSize = 0; + tmpSchemes[0].fgColor[0] = tmpSchemes[0].fgColor[1] = tmpSchemes[0].fgColor[2] = tmpSchemes[0].fgColor[3] = 255; + tmpSchemes[0].armedFgColor[0] = tmpSchemes[0].armedFgColor[1] = tmpSchemes[0].armedFgColor[2] = tmpSchemes[0].armedFgColor[3] = 255; + tmpSchemes[0].mousedownFgColor[0] = tmpSchemes[0].mousedownFgColor[1] = tmpSchemes[0].mousedownFgColor[2] = tmpSchemes[0].mousedownFgColor[3] = 255; + } + + // we have the full list of schemes in the tmpSchemes array + // now allocate the correct sized list + m_iNumSchemes = currentScheme + 1; // 0-based index + m_pSchemeList = new CScheme[ m_iNumSchemes ]; + + // copy in the data + memcpy( m_pSchemeList, tmpSchemes, sizeof(CScheme) * m_iNumSchemes ); + + // create the fonts + for ( int i = 0; i < m_iNumSchemes; i++ ) + { + m_pSchemeList[i].font = NULL; + + // see if the current font values exist in a previously loaded font + for ( int j = 0; j < i; j++ ) + { + // check if the font name, size, and weight are the same + if ( !stricmp(m_pSchemeList[i].fontName, m_pSchemeList[j].fontName) + && m_pSchemeList[i].fontSize == m_pSchemeList[j].fontSize + && m_pSchemeList[i].fontWeight == m_pSchemeList[j].fontWeight ) + { + // copy the pointer, but mark i as not owning it + m_pSchemeList[i].font = m_pSchemeList[j].font; + m_pSchemeList[i].ownFontPointer = false; + } + } + + // if we haven't found the font already, load it ourselves + if ( !m_pSchemeList[i].font ) + { + fontFileLength = -1; + pFontData = NULL; + + if(g_CV_BitmapFonts && g_CV_BitmapFonts->value) + { + int fontRes = 640; + if ( m_xRes >= 1600 ) + fontRes = 1600; + else if ( m_xRes >= 1280 ) + fontRes = 1280; + else if ( m_xRes >= 1152 ) + fontRes = 1152; + else if ( m_xRes >= 1024 ) + fontRes = 1024; + else if ( m_xRes >= 800 ) + fontRes = 800; + + sprintf(fontFilename, "gfx\\vgui\\fonts\\%d_%s.tga", fontRes, m_pSchemeList[i].schemeName); + pFontData = gEngfuncs.COM_LoadFile( fontFilename, 5, &fontFileLength ); + if(!pFontData) + gEngfuncs.Con_Printf("Missing bitmap font: %s\n", fontFilename); + } + + m_pSchemeList[i].font = new vgui::Font( + m_pSchemeList[i].fontName, + pFontData, + fontFileLength, + m_pSchemeList[i].fontSize, + 0, + 0, + m_pSchemeList[i].fontWeight, + false, + false, + false, + false); + + m_pSchemeList[i].ownFontPointer = true; + } + + // fix up alpha values; VGUI uses 1-A (A=0 being solid, A=255 transparent) + m_pSchemeList[i].fgColor[3] = 255 - m_pSchemeList[i].fgColor[3]; + m_pSchemeList[i].bgColor[3] = 255 - m_pSchemeList[i].bgColor[3]; + m_pSchemeList[i].armedFgColor[3] = 255 - m_pSchemeList[i].armedFgColor[3]; + m_pSchemeList[i].armedBgColor[3] = 255 - m_pSchemeList[i].armedBgColor[3]; + m_pSchemeList[i].mousedownFgColor[3] = 255 - m_pSchemeList[i].mousedownFgColor[3]; + m_pSchemeList[i].mousedownBgColor[3] = 255 - m_pSchemeList[i].mousedownBgColor[3]; + } +} + +//----------------------------------------------------------------------------- +// Purpose: frees all the memory used by the scheme manager +//----------------------------------------------------------------------------- +CSchemeManager::~CSchemeManager() +{ + delete [] m_pSchemeList; + m_iNumSchemes = 0; +} + +//----------------------------------------------------------------------------- +// Purpose: Finds a scheme in the list, by name +// Input : char *schemeName - string name of the scheme +// Output : SchemeHandle_t handle to the scheme +//----------------------------------------------------------------------------- +SchemeHandle_t CSchemeManager::getSchemeHandle( const char *schemeName ) +{ + // iterate through the list + for ( int i = 0; i < m_iNumSchemes; i++ ) + { + if ( !stricmp(schemeName, m_pSchemeList[i].schemeName) ) + return i; + } + + return 0; +} + +//----------------------------------------------------------------------------- +// Purpose: always returns a valid scheme handle +// Input : schemeHandle - +// Output : CScheme +//----------------------------------------------------------------------------- +CSchemeManager::CScheme *CSchemeManager::getSafeScheme( SchemeHandle_t schemeHandle ) +{ + if ( schemeHandle < m_iNumSchemes ) + return m_pSchemeList + schemeHandle; + + return m_pSchemeList; +} + + +//----------------------------------------------------------------------------- +// Purpose: Returns the schemes pointer to a font +// Input : schemeHandle - +// Output : vgui::Font +//----------------------------------------------------------------------------- +vgui::Font *CSchemeManager::getFont( SchemeHandle_t schemeHandle ) +{ + return getSafeScheme( schemeHandle )->font; +} + +void CSchemeManager::getFgColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a ) +{ + CScheme *pScheme = getSafeScheme( schemeHandle ); + r = pScheme->fgColor[0]; + g = pScheme->fgColor[1]; + b = pScheme->fgColor[2]; + a = pScheme->fgColor[3]; +} + +void CSchemeManager::getBgColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a ) +{ + CScheme *pScheme = getSafeScheme( schemeHandle ); + r = pScheme->bgColor[0]; + g = pScheme->bgColor[1]; + b = pScheme->bgColor[2]; + a = pScheme->bgColor[3]; +} + +void CSchemeManager::getFgArmedColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a ) +{ + CScheme *pScheme = getSafeScheme( schemeHandle ); + r = pScheme->armedFgColor[0]; + g = pScheme->armedFgColor[1]; + b = pScheme->armedFgColor[2]; + a = pScheme->armedFgColor[3]; +} + +void CSchemeManager::getBgArmedColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a ) +{ + CScheme *pScheme = getSafeScheme( schemeHandle ); + r = pScheme->armedBgColor[0]; + g = pScheme->armedBgColor[1]; + b = pScheme->armedBgColor[2]; + a = pScheme->armedBgColor[3]; +} + +void CSchemeManager::getFgMousedownColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a ) +{ + CScheme *pScheme = getSafeScheme( schemeHandle ); + r = pScheme->mousedownFgColor[0]; + g = pScheme->mousedownFgColor[1]; + b = pScheme->mousedownFgColor[2]; + a = pScheme->mousedownFgColor[3]; +} + +void CSchemeManager::getBgMousedownColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a ) +{ + CScheme *pScheme = getSafeScheme( schemeHandle ); + r = pScheme->mousedownBgColor[0]; + g = pScheme->mousedownBgColor[1]; + b = pScheme->mousedownBgColor[2]; + a = pScheme->mousedownBgColor[3]; +} + +void CSchemeManager::getBorderColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a ) +{ + CScheme *pScheme = getSafeScheme( schemeHandle ); + r = pScheme->borderColor[0]; + g = pScheme->borderColor[1]; + b = pScheme->borderColor[2]; + a = pScheme->borderColor[3]; +} + + + diff --git a/cl_dll/vgui_SchemeManager.h b/cl_dll/vgui_SchemeManager.h new file mode 100644 index 00000000..acde6c4b --- /dev/null +++ b/cl_dll/vgui_SchemeManager.h @@ -0,0 +1,50 @@ +//========= Copyright (c) 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include + +// handle to an individual scheme +typedef int SchemeHandle_t; + +// Register console variables, etc.. +void Scheme_Init(); + +//----------------------------------------------------------------------------- +// Purpose: Handles the loading of text scheme description from disk +// supports different font/color/size schemes at different resolutions +//----------------------------------------------------------------------------- +class CSchemeManager +{ +public: + // initialization + CSchemeManager( int xRes, int yRes ); + virtual ~CSchemeManager(); + + // scheme handling + SchemeHandle_t getSchemeHandle( const char *schemeName ); + + // getting info from schemes + vgui::Font *getFont( SchemeHandle_t schemeHandle ); + void getFgColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a ); + void getBgColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a ); + void getFgArmedColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a ); + void getBgArmedColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a ); + void getFgMousedownColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a ); + void getBgMousedownColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a ); + void getBorderColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a ); + +private: + class CScheme; + CScheme *m_pSchemeList; + int m_iNumSchemes; + + // Resolution we were initted at. + int m_xRes; + + CScheme *getSafeScheme( SchemeHandle_t schemeHandle ); +}; + diff --git a/cl_dll/vgui_ScorePanel.cpp b/cl_dll/vgui_ScorePanel.cpp new file mode 100644 index 00000000..d71685ef --- /dev/null +++ b/cl_dll/vgui_ScorePanel.cpp @@ -0,0 +1,1147 @@ +//=========== (C) Copyright 1996-2002 Valve, L.L.C. All rights reserved. =========== +// +// The copyright to the contents herein is the property of Valve, L.L.C. +// The contents may be used and/or copied only with the written permission of +// Valve, L.L.C., or in accordance with the terms and conditions stipulated in +// the agreement/contract under which the contents have been supplied. +// +// Purpose: VGUI scoreboard +// +// $Workfile: $ +// $Date: $ +// +//----------------------------------------------------------------------------- +// $Log: $ +// +// $NoKeywords: $ +//============================================================================= + + +#include + +#include "hud.h" +#include "cl_util.h" +#include "const.h" +#include "entity_state.h" +#include "cl_entity.h" +#include "vgui_TeamFortressViewport.h" +#include "vgui_ScorePanel.h" +#include "vgui_helpers.h" +#include "vgui_loadtga.h" +#include "voice_status.h" +#include "vgui_SpectatorPanel.h" + +int HUD_IsGame( const char *game ); +int EV_TFC_IsAllyTeam( int iTeam1, int iTeam2 ); + +// Scoreboard dimensions +#define SBOARD_TITLE_SIZE_Y YRES(22) + +#define X_BORDER XRES(4) + +// Column sizes +class SBColumnInfo +{ +public: + const char *m_pTitle; // If null, ignore, if starts with #, it's localized, otherwise use the string directly. + int m_Width; // Based on 640 width. Scaled to fit other resolutions. + Label::Alignment m_Alignment; +}; + +// grid size is marked out for 640x480 screen + +SBColumnInfo g_ColumnInfo[NUM_COLUMNS] = +{ + {NULL, 24, Label::a_east}, // tracker column + {NULL, 140, Label::a_east}, // name + {NULL, 56, Label::a_east}, // class + {"#SCORE", 40, Label::a_east}, + {"#DEATHS", 46, Label::a_east}, + {"#LATENCY", 46, Label::a_east}, + {"#VOICE", 40, Label::a_east}, + {NULL, 2, Label::a_east}, // blank column to take up the slack +}; + + +#define TEAM_NO 0 +#define TEAM_YES 1 +#define TEAM_SPECTATORS 2 +#define TEAM_BLANK 3 + + +//----------------------------------------------------------------------------- +// ScorePanel::HitTestPanel. +//----------------------------------------------------------------------------- + +void ScorePanel::HitTestPanel::internalMousePressed( MouseCode code ) +{ + for( int i = 0; i < _inputSignalDar.getCount(); i++ ) + { + _inputSignalDar[i]->mousePressed( code, this ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Create the ScoreBoard panel +//----------------------------------------------------------------------------- +ScorePanel::ScorePanel( int x, int y, int wide, int tall ) : Panel( x, y, wide, tall ) +{ + CSchemeManager *pSchemes = gViewPort->GetSchemeManager(); + SchemeHandle_t hTitleScheme = pSchemes->getSchemeHandle( "Scoreboard Title Text" ); + SchemeHandle_t hSmallScheme = pSchemes->getSchemeHandle( "Scoreboard Small Text" ); + Font *tfont = pSchemes->getFont( hTitleScheme ); + Font *smallfont = pSchemes->getFont( hSmallScheme ); + + setBgColor( 0, 0, 0, 96 ); + m_pCurrentHighlightLabel = NULL; + m_iHighlightRow = -1; + + //m_pTrackerIcon = vgui_LoadTGANoInvertAlpha("gfx/vgui/640_scoreboardtracker.tga"); + + // Initialize the top title. + m_TitleLabel.setFont( tfont ); + m_TitleLabel.setText( "" ); + m_TitleLabel.setBgColor( 0, 0, 0, 255 ); + m_TitleLabel.setFgColor( Scheme::sc_primary1 ); + m_TitleLabel.setContentAlignment( vgui::Label::a_west ); + + LineBorder *border = new LineBorder( Color( 60, 60, 60, 128 ) ); + setBorder( border ); + setPaintBorderEnabled( true ); + + int xpos = g_ColumnInfo[0].m_Width + 3; + if( ScreenWidth >= 640 ) + { + // only expand column size for res greater than 640 + xpos = XRES( xpos ); + } + m_TitleLabel.setBounds( xpos, 4, wide, SBOARD_TITLE_SIZE_Y ); + m_TitleLabel.setContentFitted( false ); + m_TitleLabel.setParent( this ); + + // Setup the header (labels like "name", "class", etc..). + m_HeaderGrid.SetDimensions( NUM_COLUMNS, 1 ); + m_HeaderGrid.SetSpacing( 0, 0 ); + + for( int i = 0; i < NUM_COLUMNS; i++ ) + { + if( g_ColumnInfo[i].m_pTitle && g_ColumnInfo[i].m_pTitle[0] == '#' ) + m_HeaderLabels[i].setText( CHudTextMessage::BufferedLocaliseTextString( g_ColumnInfo[i].m_pTitle ) ); + else if( g_ColumnInfo[i].m_pTitle ) + m_HeaderLabels[i].setText( g_ColumnInfo[i].m_pTitle ); + + int xwide = g_ColumnInfo[i].m_Width; + if( ScreenWidth >= 640 ) + { + xwide = XRES( xwide ); + } + else if( ScreenWidth == 400 ) + { + // hack to make 400x300 resolution scoreboard fit + if( i == 1 ) + { + // reduces size of player name cell + xwide -= 28; + } + else if( i == 0 ) + { + // tracker icon cell + xwide -= 8; + } + } + + m_HeaderGrid.SetColumnWidth( i, xwide ); + m_HeaderGrid.SetEntry( i, 0, &m_HeaderLabels[i] ); + + m_HeaderLabels[i].setBgColor( 0, 0, 0, 255 ); + m_HeaderLabels[i].setFgColor( Scheme::sc_primary1 ); + m_HeaderLabels[i].setFont( smallfont ); + m_HeaderLabels[i].setContentAlignment( g_ColumnInfo[i].m_Alignment ); + + int yres = 12; + if( ScreenHeight >= 480 ) + { + yres = YRES( yres ); + } + m_HeaderLabels[i].setSize( 50, yres ); + } + + // Set the width of the last column to be the remaining space. + int ex, ey, ew, eh; + + m_HeaderGrid.GetEntryBox( NUM_COLUMNS - 2, 0, ex, ey, ew, eh ); + m_HeaderGrid.SetColumnWidth( NUM_COLUMNS - 1, ( wide - X_BORDER ) - ( ex + ew ) ); + + m_HeaderGrid.AutoSetRowHeights(); + m_HeaderGrid.setBounds( X_BORDER, SBOARD_TITLE_SIZE_Y, wide - X_BORDER * 2, m_HeaderGrid.GetRowHeight( 0 ) ); + m_HeaderGrid.setParent( this ); + m_HeaderGrid.setBgColor( 0, 0, 0, 255 ); + + // Now setup the listbox with the actual player data in it. + int headerX, headerY, headerWidth, headerHeight; + + m_HeaderGrid.getBounds( headerX, headerY, headerWidth, headerHeight ); + m_PlayerList.setBounds( headerX, headerY+headerHeight, headerWidth, tall - headerY - headerHeight - 6 ); + m_PlayerList.setBgColor( 0, 0, 0, 255 ); + m_PlayerList.setParent( this ); + + for( int row=0; row < NUM_ROWS; row++ ) + { + CGrid *pGridRow = &m_PlayerGrids[row]; + + pGridRow->SetDimensions( NUM_COLUMNS, 1 ); + + for( int col = 0; col < NUM_COLUMNS; col++ ) + { + m_PlayerEntries[col][row].setContentFitted( false ); + m_PlayerEntries[col][row].setRow( row ); + m_PlayerEntries[col][row].addInputSignal( this ); + pGridRow->SetEntry(col, 0, &m_PlayerEntries[col][row]); + } + + pGridRow->setBgColor( 0, 0, 0, 255 ); + pGridRow->SetSpacing( 0, 0 ); + pGridRow->CopyColumnWidths( &m_HeaderGrid ); + pGridRow->AutoSetRowHeights(); + pGridRow->setSize( PanelWidth( pGridRow ), pGridRow->CalcDrawHeight() ); + pGridRow->RepositionContents(); + + m_PlayerList.AddItem( pGridRow ); + } + + // Add the hit test panel. It is invisible and traps mouse clicks so we can go into squelch mode. + m_HitTestPanel.setBgColor( 0, 0, 0, 255 ); + m_HitTestPanel.setParent( this ); + m_HitTestPanel.setBounds( 0, 0, wide, tall ); + m_HitTestPanel.addInputSignal( this ); + + m_pCloseButton = new CommandButton( "x", wide - XRES( 12 + 4 ), YRES( 2 ), XRES( 12 ) , YRES( 12 ) ); + m_pCloseButton->setParent( this ); + m_pCloseButton->addActionSignal( new CMenuHandler_StringCommandWatch( "-showscores", true ) ); + m_pCloseButton->setBgColor( 0, 0, 0, 255 ); + m_pCloseButton->setFgColor( 255, 255, 255, 0 ); + m_pCloseButton->setFont( tfont ); + m_pCloseButton->setBoundKey( (char)255 ); + m_pCloseButton->setContentAlignment( Label::a_center ); + + Initialize(); +} + +//----------------------------------------------------------------------------- +// Purpose: Called each time a new level is started. +//----------------------------------------------------------------------------- +void ScorePanel::Initialize( void ) +{ + // Clear out scoreboard data + m_iLastKilledBy = 0; + m_fLastKillTime = 0; + m_iPlayerNum = 0; + m_iNumTeams = 0; + memset( g_PlayerExtraInfo, 0, sizeof g_PlayerExtraInfo ); + memset( g_TeamInfo, 0, sizeof g_TeamInfo ); +} + +bool HACK_GetPlayerUniqueID( int iPlayer, char playerID[16] ) +{ + return !!gEngfuncs.GetPlayerUniqueID( iPlayer, playerID ); // TODO remove after testing +} + +//----------------------------------------------------------------------------- +// Purpose: Recalculate the internal scoreboard data +//----------------------------------------------------------------------------- +void ScorePanel::Update() +{ + int i; + + // Set the title + if( gViewPort->m_szServerName[0] != '\0' ) + { + char sz[MAX_SERVERNAME_LENGTH + 16]; + + sprintf( sz, "%s", gViewPort->m_szServerName ); + m_TitleLabel.setText( sz ); + } + + m_iRows = 0; + gViewPort->GetAllPlayersInfo(); + + // Clear out sorts + for (i = 0; i < NUM_ROWS; i++) + { + m_iSortedRows[i] = 0; + m_iIsATeam[i] = TEAM_NO; + } + for (i = 0; i < MAX_PLAYERS; i++) + { + m_bHasBeenSorted[i] = false; + } + + // If it's not teamplay, sort all the players. Otherwise, sort the teams. + if( !gHUD.m_Teamplay ) + SortPlayers( 0, NULL ); + else + SortTeams(); + + // set scrollbar range + m_PlayerList.SetScrollRange(m_iRows); + + FillGrid(); + + if( gViewPort->m_pSpectatorPanel->m_menuVisible ) + { + m_pCloseButton->setVisible ( true ); + } + else + { + m_pCloseButton->setVisible ( false ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Sort all the teams +//----------------------------------------------------------------------------- +void ScorePanel::SortTeams() +{ + // clear out team scores + int i; + for ( i = 1; i <= m_iNumTeams; i++ ) + { + if( !g_TeamInfo[i].scores_overriden ) + g_TeamInfo[i].frags = g_TeamInfo[i].deaths = 0; + g_TeamInfo[i].ping = g_TeamInfo[i].packetloss = 0; + } + + // recalc the team scores, then draw them + for( i = 1; i < MAX_PLAYERS; i++ ) + { + if( g_PlayerInfoList[i].name == 0 ) + continue; // empty player slot, skip + + if( g_PlayerExtraInfo[i].teamname[0] == 0 ) + continue; // skip over players who are not in a team + + // find what team this player is in + int j; + for ( j = 1; j <= m_iNumTeams; j++ ) + { + if( !stricmp( g_PlayerExtraInfo[i].teamname, g_TeamInfo[j].name ) ) + break; + } + if( j > m_iNumTeams ) // player is not in a team, skip to the next guy + continue; + + if( !g_TeamInfo[j].scores_overriden ) + { + g_TeamInfo[j].frags += g_PlayerExtraInfo[i].frags; + g_TeamInfo[j].deaths += g_PlayerExtraInfo[i].deaths; + } + + g_TeamInfo[j].ping += g_PlayerInfoList[i].ping; + g_TeamInfo[j].packetloss += g_PlayerInfoList[i].packetloss; + + if( g_PlayerInfoList[i].thisplayer ) + g_TeamInfo[j].ownteam = TRUE; + else + g_TeamInfo[j].ownteam = FALSE; + + // Set the team's number (used for team colors) + g_TeamInfo[j].teamnumber = g_PlayerExtraInfo[i].teamnumber; + } + + // find team ping/packetloss averages + for( i = 1; i <= m_iNumTeams; i++ ) + { + g_TeamInfo[i].already_drawn = FALSE; + + if( g_TeamInfo[i].players > 0 ) + { + g_TeamInfo[i].ping /= g_TeamInfo[i].players; // use the average ping of all the players in the team as the teams ping + g_TeamInfo[i].packetloss /= g_TeamInfo[i].players; // use the average ping of all the players in the team as the teams ping + } + } + + // Draw the teams + while( 1 ) + { + int highest_frags = -99999; int lowest_deaths = 99999; + int best_team = 0; + + for( i = 1; i <= m_iNumTeams; i++ ) + { + if( g_TeamInfo[i].players < 1 ) + continue; + + if( !g_TeamInfo[i].already_drawn && g_TeamInfo[i].frags >= highest_frags ) + { + if( g_TeamInfo[i].frags > highest_frags || g_TeamInfo[i].deaths < lowest_deaths ) + { + best_team = i; + lowest_deaths = g_TeamInfo[i].deaths; + highest_frags = g_TeamInfo[i].frags; + } + } + } + + // draw the best team on the scoreboard + if( !best_team ) + break; + + // Put this team in the sorted list + m_iSortedRows[m_iRows] = best_team; + m_iIsATeam[m_iRows] = TEAM_YES; + g_TeamInfo[best_team].already_drawn = TRUE; // set the already_drawn to be TRUE, so this team won't get sorted again + m_iRows++; + + // Now sort all the players on this team + SortPlayers( 0, g_TeamInfo[best_team].name ); + } + + // Add all the players who aren't in a team yet into spectators + SortPlayers( TEAM_SPECTATORS, NULL ); +} + +//----------------------------------------------------------------------------- +// Purpose: Sort a list of players +//----------------------------------------------------------------------------- +void ScorePanel::SortPlayers( int iTeam, char *team ) +{ + bool bCreatedTeam = false; + + // draw the players, in order, and restricted to team if set + while ( 1 ) + { + // Find the top ranking player + int highest_frags = -99999; int lowest_deaths = 99999; + int best_player; + best_player = 0; + + for ( int i = 1; i < MAX_PLAYERS; i++ ) + { + if ( m_bHasBeenSorted[i] == false && g_PlayerInfoList[i].name && g_PlayerExtraInfo[i].frags >= highest_frags ) + { + cl_entity_t *ent = gEngfuncs.GetEntityByIndex( i ); + + if ( ent && !(team && stricmp(g_PlayerExtraInfo[i].teamname, team)) ) + { + extra_player_info_t *pl_info = &g_PlayerExtraInfo[i]; + if ( pl_info->frags > highest_frags || pl_info->deaths < lowest_deaths ) + { + best_player = i; + lowest_deaths = pl_info->deaths; + highest_frags = pl_info->frags; + } + } + } + } + + if ( !best_player ) + break; + + // If we haven't created the Team yet, do it first + if (!bCreatedTeam && iTeam) + { + m_iIsATeam[ m_iRows ] = iTeam; + m_iRows++; + + bCreatedTeam = true; + } + + // Put this player in the sorted list + m_iSortedRows[ m_iRows ] = best_player; + m_bHasBeenSorted[ best_player ] = true; + m_iRows++; + } + + if (team) + { + m_iIsATeam[m_iRows++] = TEAM_BLANK; + } +} + +//----------------------------------------------------------------------------- +// Purpose: Recalculate the existing teams in the match +//----------------------------------------------------------------------------- +void ScorePanel::RebuildTeams() +{ + // clear out player counts from teams + int i; + for ( i = 1; i <= m_iNumTeams; i++ ) + { + g_TeamInfo[i].players = 0; + } + + // rebuild the team list + gViewPort->GetAllPlayersInfo(); + m_iNumTeams = 0; + for ( i = 1; i < MAX_PLAYERS; i++ ) + { + if ( g_PlayerInfoList[i].name == NULL ) + continue; + + if ( g_PlayerExtraInfo[i].teamname[0] == 0 ) + continue; // skip over players who are not in a team + + // is this player in an existing team? + int j; + for ( j = 1; j <= m_iNumTeams; j++ ) + { + if ( g_TeamInfo[j].name[0] == '\0' ) + break; + + if ( !stricmp( g_PlayerExtraInfo[i].teamname, g_TeamInfo[j].name ) ) + break; + } + + if ( j > m_iNumTeams ) + { // they aren't in a listed team, so make a new one + // search through for an empty team slot + for ( j = 1; j <= m_iNumTeams; j++ ) + { + if ( g_TeamInfo[j].name[0] == '\0' ) + break; + } + m_iNumTeams = Q_max( j, m_iNumTeams ); + + strncpy( g_TeamInfo[j].name, g_PlayerExtraInfo[i].teamname, MAX_TEAM_NAME ); + g_TeamInfo[j].players = 0; + } + + g_TeamInfo[j].players++; + } + + // clear out any empty teams + for ( i = 1; i <= m_iNumTeams; i++ ) + { + if ( g_TeamInfo[i].players < 1 ) + memset( &g_TeamInfo[i], 0, sizeof(team_info_t) ); + } + + // Update the scoreboard + Update(); +} + + +void ScorePanel::FillGrid() +{ + CSchemeManager *pSchemes = gViewPort->GetSchemeManager(); + SchemeHandle_t hScheme = pSchemes->getSchemeHandle("Scoreboard Text"); + SchemeHandle_t hTitleScheme = pSchemes->getSchemeHandle("Scoreboard Title Text"); + SchemeHandle_t hSmallScheme = pSchemes->getSchemeHandle("Scoreboard Small Text"); + + Font *sfont = pSchemes->getFont(hScheme); + Font *tfont = pSchemes->getFont(hTitleScheme); + Font *smallfont = pSchemes->getFont(hSmallScheme); + + // update highlight position + int x, y; + getApp()->getCursorPos(x, y); + cursorMoved(x, y, this); + + // remove highlight row if we're not in squelch mode + if (!GetClientVoiceMgr()->IsInSquelchMode()) + { + m_iHighlightRow = -1; + } + + bool bNextRowIsGap = false; + int row; + for(row=0; row < NUM_ROWS; row++) + { + CGrid *pGridRow = &m_PlayerGrids[row]; + pGridRow->SetRowUnderline(0, false, 0, 0, 0, 0, 0); + + if(row >= m_iRows) + { + for(int col=0; col < NUM_COLUMNS; col++) + m_PlayerEntries[col][row].setVisible(false); + + continue; + } + + bool bRowIsGap = false; + if (bNextRowIsGap) + { + bNextRowIsGap = false; + bRowIsGap = true; + } + + for(int col=0; col < NUM_COLUMNS; col++) + { + CLabelHeader *pLabel = &m_PlayerEntries[col][row]; + + pLabel->setVisible(true); + pLabel->setText2(""); + pLabel->setImage(NULL); + pLabel->setFont(sfont); + pLabel->setTextOffset(0, 0); + + int rowheight = 13; + if (ScreenHeight > 480) + { + rowheight = YRES(rowheight); + } + else + { + // more tweaking, make sure icons fit at low res + rowheight = 15; + } + pLabel->setSize(pLabel->getWide(), rowheight); + pLabel->setBgColor(0, 0, 0, 255); + + char sz[128]; + hud_player_info_t *pl_info = NULL; + team_info_t *team_info = NULL; + + if (m_iIsATeam[row] == TEAM_BLANK) + { + pLabel->setText(" "); + continue; + } + else if ( m_iIsATeam[row] == TEAM_YES ) + { + // Get the team's data + team_info = &g_TeamInfo[ m_iSortedRows[row] ]; + + // team color text for team names + pLabel->setFgColor( iTeamColors[team_info->teamnumber % iNumberOfTeamColors][0], + iTeamColors[team_info->teamnumber % iNumberOfTeamColors][1], + iTeamColors[team_info->teamnumber % iNumberOfTeamColors][2], + 0 ); + + // different height for team header rows + rowheight = 20; + if (ScreenHeight >= 480) + { + rowheight = YRES(rowheight); + } + pLabel->setSize(pLabel->getWide(), rowheight); + pLabel->setFont(tfont); + + pGridRow->SetRowUnderline( 0, + true, + YRES(3), + iTeamColors[team_info->teamnumber % iNumberOfTeamColors][0], + iTeamColors[team_info->teamnumber % iNumberOfTeamColors][1], + iTeamColors[team_info->teamnumber % iNumberOfTeamColors][2], + 0 ); + } + else if ( m_iIsATeam[row] == TEAM_SPECTATORS ) + { + // grey text for spectators + pLabel->setFgColor(100, 100, 100, 0); + + // different height for team header rows + rowheight = 20; + if (ScreenHeight >= 480) + { + rowheight = YRES(rowheight); + } + pLabel->setSize(pLabel->getWide(), rowheight); + pLabel->setFont(tfont); + + pGridRow->SetRowUnderline(0, true, YRES(3), 100, 100, 100, 0); + } + else + { + // team color text for player names + pLabel->setFgColor( iTeamColors[ g_PlayerExtraInfo[ m_iSortedRows[row] ].teamnumber % iNumberOfTeamColors ][0], + iTeamColors[ g_PlayerExtraInfo[ m_iSortedRows[row] ].teamnumber % iNumberOfTeamColors ][1], + iTeamColors[ g_PlayerExtraInfo[ m_iSortedRows[row] ].teamnumber % iNumberOfTeamColors ][2], + 0 ); + + // Get the player's data + pl_info = &g_PlayerInfoList[ m_iSortedRows[row] ]; + + // Set background color + if ( pl_info->thisplayer ) // if it is their name, draw it a different color + { + // Highlight this player + pLabel->setFgColor(Scheme::sc_white); + pLabel->setBgColor( iTeamColors[ g_PlayerExtraInfo[ m_iSortedRows[row] ].teamnumber % iNumberOfTeamColors ][0], + iTeamColors[ g_PlayerExtraInfo[ m_iSortedRows[row] ].teamnumber % iNumberOfTeamColors ][1], + iTeamColors[ g_PlayerExtraInfo[ m_iSortedRows[row] ].teamnumber % iNumberOfTeamColors ][2], + 196 ); + } + else if ( m_iSortedRows[row] == m_iLastKilledBy && m_fLastKillTime && m_fLastKillTime > gHUD.m_flTime ) + { + // Killer's name + pLabel->setBgColor( 255,0,0, 255 - ((float)15 * (float)(m_fLastKillTime - gHUD.m_flTime)) ); + } + } + + // Align + if (col == COLUMN_NAME || col == COLUMN_CLASS) + { + pLabel->setContentAlignment( vgui::Label::a_west ); + } + else if (col == COLUMN_TRACKER) + { + pLabel->setContentAlignment( vgui::Label::a_center ); + } + else + { + pLabel->setContentAlignment( vgui::Label::a_east ); + } + + // Fill out with the correct data + strcpy(sz, ""); + if ( m_iIsATeam[row] ) + { + char sz2[128]; + + switch (col) + { + case COLUMN_NAME: + if ( m_iIsATeam[row] == TEAM_SPECTATORS ) + { + sprintf( sz2, "%s", CHudTextMessage::BufferedLocaliseTextString( "#Spectators" ) ); + } + else + { + sprintf( sz2, "%s", gViewPort->GetTeamName(team_info->teamnumber) ); + } + + strcpy(sz, sz2); + + // Append the number of players + if ( m_iIsATeam[row] == TEAM_YES ) + { + if (team_info->players == 1) + { + sprintf(sz2, "(%d %s)", team_info->players, CHudTextMessage::BufferedLocaliseTextString( "#Player" ) ); + } + else + { + sprintf(sz2, "(%d %s)", team_info->players, CHudTextMessage::BufferedLocaliseTextString( "#Player_plural" ) ); + } + + pLabel->setText2(sz2); + pLabel->setFont2(smallfont); + } + break; + case COLUMN_VOICE: + break; + case COLUMN_CLASS: + break; + case COLUMN_KILLS: + if ( m_iIsATeam[row] == TEAM_YES ) + sprintf(sz, "%d", team_info->frags ); + break; + case COLUMN_DEATHS: + if ( m_iIsATeam[row] == TEAM_YES ) + sprintf(sz, "%d", team_info->deaths ); + break; + case COLUMN_LATENCY: + if ( m_iIsATeam[row] == TEAM_YES ) + sprintf(sz, "%d", team_info->ping ); + break; + default: + break; + } + } + else + { + bool bShowClass = false; + + switch (col) + { + case COLUMN_NAME: + /* + if (g_pTrackerUser) + { + int playerSlot = m_iSortedRows[row]; + int trackerID = gEngfuncs.GetTrackerIDForPlayer(playerSlot); + const char *trackerName = g_pTrackerUser->GetUserName(trackerID); + if (trackerName && *trackerName) + { + sprintf(sz, " (%s)", trackerName); + pLabel->setText2(sz); + } + } + */ + sprintf(sz, "%s ", pl_info->name); + break; + case COLUMN_VOICE: + sz[0] = 0; + // in HLTV mode allow spectator to turn on/off commentator voice + //if (!pl_info->thisplayer || gEngfuncs.IsSpectateOnly() ) + //{ + GetClientVoiceMgr()->UpdateSpeakerImage(pLabel, m_iSortedRows[row]); + //} + break; + case COLUMN_CLASS: + // No class for other team's members (unless allied or spectator) + if ( gViewPort && EV_TFC_IsAllyTeam( g_iTeamNumber, g_PlayerExtraInfo[ m_iSortedRows[row] ].teamnumber ) ) + bShowClass = true; + // Don't show classes if this client hasnt picked a team yet + if ( g_iTeamNumber == 0 ) + bShowClass = false; +#ifdef _TFC + // in TFC show all classes in spectator mode + if ( g_iUser1 ) + bShowClass = true; +#endif + + if (bShowClass) + { + // Only print Civilian if this team are all civilians + bool bNoClass = false; + if ( g_PlayerExtraInfo[ m_iSortedRows[row] ].playerclass == 0 ) + { + if ( gViewPort->GetValidClasses( g_PlayerExtraInfo[ m_iSortedRows[row] ].teamnumber ) != -1 ) + bNoClass = true; + } + + if (bNoClass) + sz[0] = '\0'; + else + sprintf( sz, "%s", CHudTextMessage::BufferedLocaliseTextString( sLocalisedClasses[ g_PlayerExtraInfo[ m_iSortedRows[row] ].playerclass ] ) ); + } + else + { + sz[0] = '\0'; + } + break; + + case COLUMN_TRACKER: + /* + if (g_pTrackerUser) + { + int playerSlot = m_iSortedRows[row]; + int trackerID = gEngfuncs.GetTrackerIDForPlayer(playerSlot); + + if (g_pTrackerUser->IsFriend(trackerID) && trackerID != g_pTrackerUser->GetTrackerID()) + { + pLabel->setImage(m_pTrackerIcon); + pLabel->setFgColorAsImageColor(false); + m_pTrackerIcon->setColor(Color(255, 255, 255, 0)); + } + } + */ + break; + +#ifdef _TFC + case COLUMN_KILLS: + if (g_PlayerExtraInfo[ m_iSortedRows[row] ].teamnumber) + sprintf(sz, "%d", g_PlayerExtraInfo[ m_iSortedRows[row] ].frags ); + break; + case COLUMN_DEATHS: + if (g_PlayerExtraInfo[ m_iSortedRows[row] ].teamnumber) + sprintf(sz, "%d", g_PlayerExtraInfo[ m_iSortedRows[row] ].deaths ); + break; + case COLUMN_LATENCY: + if (g_PlayerExtraInfo[ m_iSortedRows[row] ].teamnumber) + sprintf(sz, "%d", g_PlayerInfoList[ m_iSortedRows[row] ].ping ); + break; +#else + case COLUMN_KILLS: + sprintf(sz, "%d", g_PlayerExtraInfo[ m_iSortedRows[row] ].frags ); + break; + case COLUMN_DEATHS: + sprintf(sz, "%d", g_PlayerExtraInfo[ m_iSortedRows[row] ].deaths ); + break; + case COLUMN_LATENCY: + sprintf(sz, "%d", g_PlayerInfoList[ m_iSortedRows[row] ].ping ); + break; +#endif + default: + break; + } + } + + pLabel->setText(sz); + } + } + + for(row=0; row < NUM_ROWS; row++) + { + CGrid *pGridRow = &m_PlayerGrids[row]; + + pGridRow->AutoSetRowHeights(); + pGridRow->setSize(PanelWidth(pGridRow), pGridRow->CalcDrawHeight()); + pGridRow->RepositionContents(); + } + + // hack, for the thing to resize + m_PlayerList.getSize(x, y); + m_PlayerList.setSize(x, y); +} + + +//----------------------------------------------------------------------------- +// Purpose: Setup highlights for player names in scoreboard +//----------------------------------------------------------------------------- +void ScorePanel::DeathMsg( int killer, int victim ) +{ + // if we were the one killed, or the world killed us, set the scoreboard to indicate suicide + if ( victim == m_iPlayerNum || killer == 0 ) + { + m_iLastKilledBy = killer ? killer : m_iPlayerNum; + m_fLastKillTime = gHUD.m_flTime + 10; // display who we were killed by for 10 seconds + + if ( killer == m_iPlayerNum ) + m_iLastKilledBy = m_iPlayerNum; + } +} + + +void ScorePanel::Open( void ) +{ + RebuildTeams(); + setVisible(true); + m_HitTestPanel.setVisible(true); +} + + +void ScorePanel::mousePressed(MouseCode code, Panel* panel) +{ + if(gHUD.m_iIntermission) + return; + + if (!GetClientVoiceMgr()->IsInSquelchMode()) + { + GetClientVoiceMgr()->StartSquelchMode(); + m_HitTestPanel.setVisible(false); + } + else if (m_iHighlightRow >= 0) + { + // mouse has been pressed, toggle mute state + int iPlayer = m_iSortedRows[m_iHighlightRow]; + if (iPlayer > 0) + { + // print text message + hud_player_info_t *pl_info = &g_PlayerInfoList[iPlayer]; + + if (pl_info && pl_info->name && pl_info->name[0]) + { + char string[256]; + if (GetClientVoiceMgr()->IsPlayerBlocked(iPlayer)) + { + char string1[1024]; + + // remove mute + GetClientVoiceMgr()->SetPlayerBlockedState(iPlayer, false); + + sprintf( string1, CHudTextMessage::BufferedLocaliseTextString( "#Unmuted" ), pl_info->name ); + sprintf( string, "%c** %s\n", HUD_PRINTTALK, string1 ); + + gHUD.m_TextMessage.MsgFunc_TextMsg(NULL, strlen(string)+1, string ); + } + else + { + char string1[1024]; + char string2[1024]; + + // mute the player + GetClientVoiceMgr()->SetPlayerBlockedState(iPlayer, true); + + sprintf( string1, CHudTextMessage::BufferedLocaliseTextString( "#Muted" ), pl_info->name ); + sprintf( string2, "%s", CHudTextMessage::BufferedLocaliseTextString( "#No_longer_hear_that_player" ) ); + sprintf( string, "%c** %s %s\n", HUD_PRINTTALK, string1, string2 ); + + gHUD.m_TextMessage.MsgFunc_TextMsg(NULL, strlen(string)+1, string ); + } + } + } + } +} + +void ScorePanel::cursorMoved(int x, int y, Panel *panel) +{ + if (GetClientVoiceMgr()->IsInSquelchMode()) + { + // look for which cell the mouse is currently over + for (int i = 0; i < NUM_ROWS; i++) + { + int row, col; + if (m_PlayerGrids[i].getCellAtPoint(x, y, row, col)) + { + MouseOverCell(i, col); + return; + } + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Handles mouse movement over a cell +// Input : row - +// col - +//----------------------------------------------------------------------------- +void ScorePanel::MouseOverCell(int row, int col) +{ + CLabelHeader *label = &m_PlayerEntries[col][row]; + + // clear the previously highlighted label + if (m_pCurrentHighlightLabel != label) + { + m_pCurrentHighlightLabel = NULL; + m_iHighlightRow = -1; + } + if (!label) + return; + + // don't act on teams + if (m_iIsATeam[row] != TEAM_NO) + return; + + // don't act on disconnected players or ourselves + hud_player_info_t *pl_info = &g_PlayerInfoList[ m_iSortedRows[row] ]; + if (!pl_info->name || !pl_info->name[0]) + return; + + if (pl_info->thisplayer && !gEngfuncs.IsSpectateOnly() ) + return; + + // setup the new highlight + m_pCurrentHighlightLabel = label; + m_iHighlightRow = row; +} + +//----------------------------------------------------------------------------- +// Purpose: Label paint functions - take into account current highligh status +//----------------------------------------------------------------------------- +void CLabelHeader::paintBackground() +{ + Color oldBg; + getBgColor(oldBg); + + if (gViewPort->GetScoreBoard()->m_iHighlightRow == _row) + { + setBgColor(134, 91, 19, 0); + } + + Panel::paintBackground(); + + setBgColor(oldBg); +} + + +//----------------------------------------------------------------------------- +// Purpose: Label paint functions - take into account current highligh status +//----------------------------------------------------------------------------- +void CLabelHeader::paint() +{ + Color oldFg; + getFgColor(oldFg); + + if (gViewPort->GetScoreBoard()->m_iHighlightRow == _row) + { + setFgColor(255, 255, 255, 0); + } + + // draw text + int x, y, iwide, itall; + getTextSize(iwide, itall); + calcAlignment(iwide, itall, x, y); + _dualImage->setPos(x, y); + + int x1, y1; + _dualImage->GetImage(1)->getPos(x1, y1); + _dualImage->GetImage(1)->setPos(_gap, y1); + + _dualImage->doPaint(this); + + // get size of the panel and the image + if (_image) + { + Color imgColor; + getFgColor( imgColor ); + if( _useFgColorAsImageColor ) + { + _image->setColor( imgColor ); + } + + _image->getSize(iwide, itall); + calcAlignment(iwide, itall, x, y); + _image->setPos(x, y); + _image->doPaint(this); + } + + setFgColor(oldFg[0], oldFg[1], oldFg[2], oldFg[3]); +} + + +void CLabelHeader::calcAlignment(int iwide, int itall, int &x, int &y) +{ + // calculate alignment ourselves, since vgui is so broken + int wide, tall; + getSize(wide, tall); + + x = 0, y = 0; + + // align left/right + switch (_contentAlignment) + { + // left + case Label::a_northwest: + case Label::a_west: + case Label::a_southwest: + { + x = 0; + break; + } + + // center + case Label::a_north: + case Label::a_center: + case Label::a_south: + { + x = (wide - iwide) / 2; + break; + } + + // right + case Label::a_northeast: + case Label::a_east: + case Label::a_southeast: + { + x = wide - iwide; + break; + } + } + + // top/down + switch (_contentAlignment) + { + // top + case Label::a_northwest: + case Label::a_north: + case Label::a_northeast: + { + y = 0; + break; + } + + // center + case Label::a_west: + case Label::a_center: + case Label::a_east: + { + y = (tall - itall) / 2; + break; + } + + // south + case Label::a_southwest: + case Label::a_south: + case Label::a_southeast: + { + y = tall - itall; + break; + } + } + +// don't clip to Y +// if (y < 0) +// { +// y = 0; +// } + if (x < 0) + { + x = 0; + } + + x += _offset[0]; + y += _offset[1]; +} diff --git a/cl_dll/vgui_ScorePanel.h b/cl_dll/vgui_ScorePanel.h new file mode 100644 index 00000000..b17770a4 --- /dev/null +++ b/cl_dll/vgui_ScorePanel.h @@ -0,0 +1,311 @@ +//========= Copyright (c) 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef SCOREPANEL_H +#define SCOREPANEL_H + +#include +#include +#include +#include +#include +#include +#include "../game_shared/vgui_listbox.h" +#include "cl_util.h" + +#include + +#define MAX_SCORES 10 +#define MAX_SCOREBOARD_TEAMS 5 + +// Scoreboard cells +#define COLUMN_TRACKER 0 +#define COLUMN_NAME 1 +#define COLUMN_CLASS 2 +#define COLUMN_KILLS 3 +#define COLUMN_DEATHS 4 +#define COLUMN_LATENCY 5 +#define COLUMN_VOICE 6 +#define COLUMN_BLANK 7 +#define NUM_COLUMNS 8 +#define NUM_ROWS (MAX_PLAYERS + (MAX_SCOREBOARD_TEAMS * 2)) + +using namespace vgui; + +class CTextImage2 : public Image +{ +public: + CTextImage2() + { + _image[0] = new TextImage(""); + _image[1] = new TextImage(""); + } + + ~CTextImage2() + { + delete _image[0]; + delete _image[1]; + } + + TextImage *GetImage(int image) + { + return _image[image]; + } + + void getSize(int &wide, int &tall) + { + int w1, w2, t1, t2; + _image[0]->getTextSize(w1, t1); + _image[1]->getTextSize(w2, t2); + + wide = w1 + w2; + tall = Q_max(t1, t2); + setSize(wide, tall); + } + + void doPaint(Panel *panel) + { + _image[0]->doPaint(panel); + _image[1]->doPaint(panel); + } + + void setPos(int x, int y) + { + _image[0]->setPos(x, y); + + int swide, stall; + _image[0]->getSize(swide, stall); + + int wide, tall; + _image[1]->getSize(wide, tall); + _image[1]->setPos(x + wide, y + (stall * 0.9) - tall); + } + + void setColor(Color color) + { + _image[0]->setColor(color); + } + + void setColor2(Color color) + { + _image[1]->setColor(color); + } + +private: + TextImage *_image[2]; + +}; + +//----------------------------------------------------------------------------- +// Purpose: Custom label for cells in the Scoreboard's Table Header +//----------------------------------------------------------------------------- +class CLabelHeader : public Label +{ +public: + CLabelHeader() : Label("") + { + _dualImage = new CTextImage2(); + _dualImage->setColor2(Color(255, 170, 0, 0)); + _row = -2; + _useFgColorAsImageColor = true; + _offset[0] = 0; + _offset[1] = 0; + } + + ~CLabelHeader() + { + delete _dualImage; + } + + void setRow(int row) + { + _row = row; + } + + void setFgColorAsImageColor(bool state) + { + _useFgColorAsImageColor = state; + } + + virtual void setText(int textBufferLen, const char* text) + { + _dualImage->GetImage(0)->setText(text); + + // calculate the text size + Font *font = _dualImage->GetImage(0)->getFont(); + _gap = 0; + for (const char *ch = text; *ch != 0; ch++) + { + int a, b, c; + font->getCharABCwide(*ch, a, b, c); + _gap += (a + b + c); + } + + _gap += XRES(5); + } + + virtual void setText(const char* text) + { + // strip any non-alnum characters from the end + char buf[512]; + strcpy(buf, text); + + int len = strlen(buf); + while (len && isspace(buf[--len])) + { + buf[len] = 0; + } + + CLabelHeader::setText(0, buf); + } + + void setText2(const char *text) + { + _dualImage->GetImage(1)->setText(text); + } + + void getTextSize(int &wide, int &tall) + { + _dualImage->getSize(wide, tall); + } + + void setFgColor(int r,int g,int b,int a) + { + Label::setFgColor(r,g,b,a); + Color color(r,g,b,a); + _dualImage->setColor(color); + _dualImage->setColor2(color); + repaint(); + } + + void setFgColor(Scheme::SchemeColor sc) + { + int r, g, b, a; + Label::setFgColor(sc); + Label::getFgColor( r, g, b, a ); + + // Call the r,g,b,a version so it sets the color in the dualImage.. + setFgColor( r, g, b, a ); + } + + void setFont(Font *font) + { + _dualImage->GetImage(0)->setFont(font); + } + + void setFont2(Font *font) + { + _dualImage->GetImage(1)->setFont(font); + } + + // this adjust the absolute position of the text after alignment is calculated + void setTextOffset(int x, int y) + { + _offset[0] = x; + _offset[1] = y; + } + + void paint(); + void paintBackground(); + void calcAlignment(int iwide, int itall, int &x, int &y); + +private: + CTextImage2 *_dualImage; + int _row; + int _gap; + int _offset[2]; + bool _useFgColorAsImageColor; +}; + +class ScoreTablePanel; + +#include "../game_shared/vgui_grid.h" +#include "../game_shared/vgui_defaultinputsignal.h" + +//----------------------------------------------------------------------------- +// Purpose: Scoreboard back panel +//----------------------------------------------------------------------------- +class ScorePanel : public Panel, public vgui::CDefaultInputSignal +{ +private: + // Default panel implementation doesn't forward mouse messages when there is no cursor and we need them. + class HitTestPanel : public Panel + { + public: + virtual void internalMousePressed(MouseCode code); + }; + + +private: + + Label m_TitleLabel; + + // Here is how these controls are arranged hierarchically. + // m_HeaderGrid + // m_HeaderLabels + + // m_PlayerGridScroll + // m_PlayerGrid + // m_PlayerEntries + + CGrid m_HeaderGrid; + CLabelHeader m_HeaderLabels[NUM_COLUMNS]; // Labels above the + CLabelHeader *m_pCurrentHighlightLabel; + int m_iHighlightRow; + + vgui::CListBox m_PlayerList; + CGrid m_PlayerGrids[NUM_ROWS]; // The grid with player and team info. + CLabelHeader m_PlayerEntries[NUM_COLUMNS][NUM_ROWS]; // Labels for the grid entries. + + ScorePanel::HitTestPanel m_HitTestPanel; + CommandButton *m_pCloseButton; + CLabelHeader* GetPlayerEntry(int x, int y) {return &m_PlayerEntries[x][y];} + +public: + + int m_iNumTeams; + int m_iPlayerNum; + int m_iShowscoresHeld; + + int m_iRows; + int m_iSortedRows[NUM_ROWS]; + int m_iIsATeam[NUM_ROWS]; + bool m_bHasBeenSorted[MAX_PLAYERS]; + int m_iLastKilledBy; + int m_fLastKillTime; + + +public: + + ScorePanel(int x,int y,int wide,int tall); + + void Update( void ); + + void SortTeams( void ); + void SortPlayers( int iTeam, char *team ); + void RebuildTeams( void ); + + void FillGrid(); + + void DeathMsg( int killer, int victim ); + + void Initialize( void ); + + void Open( void ); + + void MouseOverCell(int row, int col); + +// InputSignal overrides. +public: + + virtual void mousePressed(MouseCode code, Panel* panel); + virtual void cursorMoved(int x, int y, Panel *panel); + + friend class CLabelHeader; +}; + +#endif diff --git a/cl_dll/vgui_SpectatorPanel.cpp b/cl_dll/vgui_SpectatorPanel.cpp new file mode 100644 index 00000000..4b2b897c --- /dev/null +++ b/cl_dll/vgui_SpectatorPanel.cpp @@ -0,0 +1,420 @@ +//========= Copyright � 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +// vgui_SpectatorPanel.cpp: implementation of the SpectatorPanel class. +// +////////////////////////////////////////////////////////////////////// + +#include "hud.h" +#include "cl_util.h" +#include "const.h" +#include "entity_state.h" +#include "cl_entity.h" +#include "pm_shared.h" +#include "vgui_TeamFortressViewport.h" +#include "vgui_SpectatorPanel.h" +#include "vgui_ScorePanel.h" + +//#include "Exports.h" + +/* +========================== +HUD_ChatInputPosition + +Sets the location of the input for chat text +========================== +*/ + +void DLLEXPORT HUD_ChatInputPosition( int *x, int *y ) +{ +// RecClChatInputPosition( x, y ); + + if ( g_iUser1 != 0 || gEngfuncs.IsSpectateOnly() ) + { + if ( gHUD.m_Spectator.m_pip->value == INSET_OFF ) + { + *y = YRES( PANEL_HEIGHT ); + } + else + { + *y = YRES( gHUD.m_Spectator.m_OverviewData.insetWindowHeight + 5 ); + } + } +} + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +SpectatorPanel::SpectatorPanel( int x, int y, int wide, int tall ) : Panel( x, y, wide, tall ) +{ +} + +SpectatorPanel::~SpectatorPanel() +{ +} + +void SpectatorPanel::ActionSignal( int cmd ) +{ + switch( cmd ) + { + case SPECTATOR_PANEL_CMD_NONE : break; + + case SPECTATOR_PANEL_CMD_OPTIONS : gViewPort->ShowCommandMenu( gViewPort->m_SpectatorOptionsMenu ); + break; + + case SPECTATOR_PANEL_CMD_NEXTPLAYER : gHUD.m_Spectator.FindNextPlayer(true); + break; + + case SPECTATOR_PANEL_CMD_PREVPLAYER : gHUD.m_Spectator.FindNextPlayer(false); + break; + + case SPECTATOR_PANEL_CMD_PLAYERS : gViewPort->ShowCommandMenu( gViewPort->m_PlayerMenu ); + break; + + case SPECTATOR_PANEL_CMD_HIDEMENU : ShowMenu(false); + break; + + case SPECTATOR_PANEL_CMD_CAMERA : gViewPort->ShowCommandMenu( gViewPort->m_SpectatorCameraMenu ); + break; + + case SPECTATOR_PANEL_CMD_TOGGLE_INSET : gHUD.m_Spectator.SetModes( -1, + gHUD.m_Spectator.ToggleInset(false) ); + break; + + + default : gEngfuncs.Con_DPrintf("Unknown SpectatorPanel ActionSingal %i.\n",cmd); break; + } +} + +void SpectatorPanel::Initialize() +{ + int x, y, wide, tall; + + getBounds( x, y, wide, tall ); + + CSchemeManager *pSchemes = gViewPort->GetSchemeManager(); + + SchemeHandle_t hSmallScheme = pSchemes->getSchemeHandle( "Team Info Text" ); + + m_TopBorder = new CTransparentPanel( 64, 0, 0, ScreenWidth, YRES( PANEL_HEIGHT ) ); + m_TopBorder->setParent( this ); + + m_BottomBorder = new CTransparentPanel( 64, 0, ScreenHeight - YRES( 32 ), ScreenWidth, YRES( PANEL_HEIGHT ) ); + m_BottomBorder->setParent( this ); + + setPaintBackgroundEnabled( false ); + + m_ExtraInfo = new Label( "Extra Info", 0, 0, wide, YRES( PANEL_HEIGHT ) ); + m_ExtraInfo->setParent( m_TopBorder ); + m_ExtraInfo->setFont( pSchemes->getFont( hSmallScheme ) ); + + m_ExtraInfo->setPaintBackgroundEnabled( false ); + m_ExtraInfo->setFgColor( 143, 143, 54, 0 ); + m_ExtraInfo->setContentAlignment( vgui::Label::a_west ); + + m_TimerImage = new CImageLabel( "timer", 0, 0, 14, 14 ); + m_TimerImage->setParent( m_TopBorder ); + + m_TopBanner = new CImageLabel( "banner", 0, 0, XRES( BANNER_WIDTH ), YRES( BANNER_HEIGHT ) ); + m_TopBanner->setParent( this ); + + m_CurrentTime = new Label( "00:00", 0, 0, wide, YRES( PANEL_HEIGHT ) ); + m_CurrentTime->setParent( m_TopBorder ); + m_CurrentTime->setFont( pSchemes->getFont( hSmallScheme ) ); + m_CurrentTime->setPaintBackgroundEnabled( false ); + m_CurrentTime->setFgColor( 143, 143, 54, 0 ); + m_CurrentTime->setContentAlignment( vgui::Label::a_west ); + + m_Separator = new Panel( 0, 0, XRES( 64 ), YRES( 96 ) ); + m_Separator->setParent( m_TopBorder ); + m_Separator->setFgColor( 59, 58, 34, 48 ); + m_Separator->setBgColor( 59, 58, 34, 48 ); + + for( int j = 0; j < TEAM_NUMBER; j++ ) + { + m_TeamScores[j] = new Label( " ", 0, 0, wide, YRES( PANEL_HEIGHT ) ); + m_TeamScores[j]->setParent( m_TopBorder ); + m_TeamScores[j]->setFont( pSchemes->getFont( hSmallScheme ) ); + m_TeamScores[j]->setPaintBackgroundEnabled( false ); + m_TeamScores[j]->setFgColor( 143, 143, 54, 0 ); + m_TeamScores[j]->setContentAlignment( vgui::Label::a_west ); + m_TeamScores[j]->setVisible( false ); + } + + // Initialize command buttons. +// m_OptionButton = new ColorButton( CHudTextMessage::BufferedLocaliseTextString( "#SPECT_OPTIONS" ), XRES(15), YRES(6), XRES(OPTIONS_BUTTON_X), YRES(20), false, false ); + m_OptionButton = new DropDownButton( CHudTextMessage::BufferedLocaliseTextString( "#SPECT_OPTIONS" ), XRES(15), YRES(6), XRES(OPTIONS_BUTTON_X), YRES(20), false, false ); + m_OptionButton->setParent( m_BottomBorder ); + m_OptionButton->setContentAlignment( vgui::Label::a_center ); + m_OptionButton->setBoundKey( (char)255 ); // special no bound to avoid leading spaces in name + m_OptionButton->addActionSignal( new CSpectatorHandler_Command( this, SPECTATOR_PANEL_CMD_OPTIONS ) ); + m_OptionButton->setUnArmedBorderColor( 59, 58, 34, 48 ); + m_OptionButton->setArmedBorderColor( 194, 202, 54, 0 ); + m_OptionButton->setUnArmedColor( 143, 143, 54, 0 ); + m_OptionButton->setArmedColor( 194, 202, 54, 0 ); + + m_CamButton = new DropDownButton( CHudTextMessage::BufferedLocaliseTextString( "#CAM_OPTIONS" ), ScreenWidth - ( XRES ( CAMOPTIONS_BUTTON_X ) + 15 ), YRES(6), XRES ( CAMOPTIONS_BUTTON_X ), YRES(20), false, false ); + m_CamButton->setParent( m_BottomBorder ); + m_CamButton->setContentAlignment( vgui::Label::a_center ); + m_CamButton->setBoundKey( (char)255 ); // special no bound to avoid leading spaces in name + m_CamButton->addActionSignal( new CSpectatorHandler_Command( this, SPECTATOR_PANEL_CMD_CAMERA ) ); + m_CamButton->setUnArmedBorderColor( 59, 58, 34, 48 ); + m_CamButton->setArmedBorderColor( 194, 202, 54, 0 ); + m_CamButton->setUnArmedColor( 143, 143, 54, 0 ); + m_CamButton->setArmedColor( 194, 202, 54, 0 ); + +// m_PrevPlayerButton= new ColorButton("<", XRES( 15 + OPTIONS_BUTTON_X + 15 ), YRES(6), XRES(24), YRES(20), false, false ); + m_PrevPlayerButton= new CImageButton("arrowleft", XRES( 15 + OPTIONS_BUTTON_X + 15 ), YRES(6), XRES(24), YRES(20), false, false ); + m_PrevPlayerButton->setParent( m_BottomBorder ); + m_PrevPlayerButton->setContentAlignment( vgui::Label::a_center ); + m_PrevPlayerButton->setBoundKey( (char)255 ); // special no bound to avoid leading spaces in name + m_PrevPlayerButton->addActionSignal( new CSpectatorHandler_Command( this, SPECTATOR_PANEL_CMD_PREVPLAYER ) ); + m_PrevPlayerButton->setUnArmedBorderColor( 59, 58, 34, 48 ); + m_PrevPlayerButton->setArmedBorderColor( 194, 202, 54, 0 ); + m_PrevPlayerButton->setUnArmedColor( 143, 143, 54, 0 ); + m_PrevPlayerButton->setArmedColor( 194, 202, 54, 0 ); + +// m_NextPlayerButton= new ColorButton(">", (ScreenWidth - (XRES ( CAMOPTIONS_BUTTON_X ) + 15)) - XRES ( 24 + 15 ), YRES(6), XRES(24), YRES(20),false, false ); + m_NextPlayerButton= new CImageButton("arrowright", (ScreenWidth - (XRES ( CAMOPTIONS_BUTTON_X ) + 15)) - XRES ( 24 + 15 ), YRES(6), XRES(24), YRES(20),false, false ); + m_NextPlayerButton->setParent( m_BottomBorder ); + m_NextPlayerButton->setContentAlignment( vgui::Label::a_center ); + m_NextPlayerButton->setBoundKey( (char)255 ); // special no bound to avoid leading spaces in name + m_NextPlayerButton->addActionSignal( new CSpectatorHandler_Command( this, SPECTATOR_PANEL_CMD_NEXTPLAYER ) ); + m_NextPlayerButton->setUnArmedBorderColor( 59, 58, 34, 48 ); + m_NextPlayerButton->setArmedBorderColor( 194, 202, 54, 0 ); + m_NextPlayerButton->setUnArmedColor( 143, 143, 54, 0 ); + m_NextPlayerButton->setArmedColor( 194, 202, 54, 0 ); + + // Initialize the bottom title. + float flLabelSize = ( ( ScreenWidth - ( XRES ( CAMOPTIONS_BUTTON_X ) + 15 ) ) - XRES( 24 + 15 ) ) - XRES( ( 15 + OPTIONS_BUTTON_X + 15 ) + 38 ); + + m_BottomMainButton = new DropDownButton("Spectator Bottom", + XRES( ( 15 + OPTIONS_BUTTON_X + 15 ) + 31 ), YRES(6), flLabelSize, YRES(20), + false, false ); + + m_BottomMainButton->setParent(m_BottomBorder); + m_BottomMainButton->setPaintBackgroundEnabled(false); + m_BottomMainButton->setFgColor( Scheme::sc_primary1 ); + m_BottomMainButton->setContentAlignment( vgui::Label::a_center ); + m_BottomMainButton->setBorder( new LineBorder( Color( 59, 58, 34, 48 ) ) ); + m_BottomMainButton->setBoundKey( (char)255 ); // special no bound to avoid leading spaces in name + m_BottomMainButton->addActionSignal( new CSpectatorHandler_Command(this,SPECTATOR_PANEL_CMD_PLAYERS) ); + m_BottomMainButton->setUnArmedBorderColor ( 59, 58, 34, 48 ); + m_BottomMainButton->setArmedBorderColor ( 194, 202, 54, 0 ); + m_BottomMainButton->setUnArmedColor ( 143, 143, 54, 0 ); + m_BottomMainButton->setArmedColor ( 194, 202, 54, 0 ); + + + m_BottomMainLabel = new Label("Spectator Bottom", + XRES( ( 15 + OPTIONS_BUTTON_X + 15 ) + 31 ), YRES(6), flLabelSize, YRES(20)); + + m_BottomMainLabel->setParent( m_BottomBorder ); + m_BottomMainLabel->setPaintBackgroundEnabled( false ); + m_BottomMainLabel->setFgColor( Scheme::sc_primary1 ); + m_BottomMainLabel->setContentAlignment( vgui::Label::a_center ); + m_BottomMainLabel->setBorder( NULL ); + m_BottomMainLabel->setVisible(false); + + m_InsetViewButton = new ColorButton( "", XRES( 2 ), YRES( 2 ), XRES( 240 ), YRES( 180 ), false, false ); + m_InsetViewButton->setParent( this ); + m_InsetViewButton->setBoundKey( (char)255 ); + m_InsetViewButton->addActionSignal( new CSpectatorHandler_Command( this, SPECTATOR_PANEL_CMD_TOGGLE_INSET ) ); + m_InsetViewButton->setUnArmedBorderColor( 59, 58, 34, 48 ); + m_InsetViewButton->setArmedBorderColor( 194, 202, 54, 0 ); + m_InsetViewButton->setUnArmedColor( 143, 143, 54, 0 ); + m_InsetViewButton->setArmedColor( 194, 202, 54, 0 ); + + m_menuVisible = false; + m_insetVisible = false; + // m_HideButton->setVisible( false ); + m_CamButton->setVisible( false ); + m_OptionButton->setVisible( false ); + m_NextPlayerButton->setVisible( false ); + m_PrevPlayerButton->setVisible( false ); + m_TopBanner->setVisible( false ); + m_ExtraInfo->setVisible( false ); + m_Separator->setVisible( false ); + m_TimerImage->setVisible( false ); +} + +void SpectatorPanel::ShowMenu( bool isVisible ) +{ +// m_HideButton->setVisible(isVisible); m_HideButton->setArmed( false ); + m_OptionButton->setVisible(isVisible); m_OptionButton->setArmed( false ); + m_CamButton->setVisible(isVisible); m_CamButton->setArmed( false ); + m_NextPlayerButton->setVisible(isVisible); m_NextPlayerButton->setArmed( false ); + m_PrevPlayerButton->setVisible(isVisible); m_PrevPlayerButton->setArmed( false ); + + if( !isVisible ) + { + int iLabelSizeX, iLabelSizeY; + m_BottomMainLabel->setVisible(true); + m_BottomMainButton->setVisible(false); + + m_BottomMainLabel->getSize( iLabelSizeX, iLabelSizeY ); + m_BottomMainLabel->setPos( ( ScreenWidth / 2 ) - ( iLabelSizeX / 2 ), YRES( 6 ) ); + } + else + { + m_BottomMainButton->setPos( XRES( ( 15 + OPTIONS_BUTTON_X + 15 ) + 31 ), YRES(6) ); + m_BottomMainLabel->setVisible(false); + m_BottomMainButton->setVisible(true); + } + + if( !isVisible ) + { + gViewPort->HideCommandMenu(); + + // if switching from visible menu to invisible menu, show help text + if( m_menuVisible && this->isVisible() ) + { + char string[64]; + + _snprintf( string, sizeof(string) - 1, "%c%s", HUD_PRINTCENTER, CHudTextMessage::BufferedLocaliseTextString( "#Spec_Duck" ) ); + string[sizeof(string) - 1] = '\0'; + + gHUD.m_TextMessage.MsgFunc_TextMsg( NULL, strlen( string ) + 1, string ); + } + } + + m_menuVisible = isVisible; + + gViewPort->UpdateCursorState(); +} + +const char *GetSpectatorLabel( int iMode ) +{ + switch( iMode ) + { + case OBS_CHASE_LOCKED: + return "#OBS_CHASE_LOCKED"; + + case OBS_CHASE_FREE: + return "#OBS_CHASE_FREE"; + + case OBS_ROAMING: + return "#OBS_ROAMING"; + + case OBS_IN_EYE: + return "#OBS_IN_EYE"; + + case OBS_MAP_FREE: + return "#OBS_MAP_FREE"; + + case OBS_MAP_CHASE: + return "#OBS_MAP_CHASE"; + + case OBS_NONE: + default: + return "#OBS_NONE"; + } + + return ""; +} + +void SpectatorPanel::EnableInsetView(bool isEnabled) +{ + int x = gHUD.m_Spectator.m_OverviewData.insetWindowX; + int y = gHUD.m_Spectator.m_OverviewData.insetWindowY; + int wide = gHUD.m_Spectator.m_OverviewData.insetWindowWidth; + int tall = gHUD.m_Spectator.m_OverviewData.insetWindowHeight; + int offset = x + wide + 2; + + if( isEnabled ) + { + // short black bar to see full inset + m_TopBorder->setBounds( XRES( offset ), 0, XRES(640 - offset ), YRES( PANEL_HEIGHT ) ); + + if( gEngfuncs.IsSpectateOnly() ) + { + m_TopBanner->setVisible( true ); + m_TopBanner->setPos( XRES( offset ), 0 ); + } + else + m_TopBanner->setVisible( false ); + + m_InsetViewButton->setBounds( XRES( x -1 ), YRES( y ), + XRES( wide +2), YRES( tall ) ); + m_InsetViewButton->setVisible( true ); + } + else + { + // full black bar, no inset border + // show banner only in real HLTV mode + if( gEngfuncs.IsSpectateOnly() ) + { + m_TopBanner->setVisible( true ); + m_TopBanner->setPos( 0, 0 ); + } + else + m_TopBanner->setVisible( false ); + + m_TopBorder->setBounds( 0, 0, ScreenWidth, YRES( PANEL_HEIGHT ) ); + + m_InsetViewButton->setVisible( false ); + } + + m_insetVisible = isEnabled; + + Update(); + + m_CamButton->setText( CHudTextMessage::BufferedLocaliseTextString( GetSpectatorLabel( g_iUser1 ) ) ); +} + +void SpectatorPanel::Update() +{ + int iTextWidth, iTextHeight; + int iTimeHeight, iTimeWidth; + int offset, j; + + if( m_insetVisible ) + offset = gHUD.m_Spectator.m_OverviewData.insetWindowX + gHUD.m_Spectator.m_OverviewData.insetWindowWidth + 2; + else + offset = 0; + + bool visible = gHUD.m_Spectator.m_drawstatus->value != 0; + + m_ExtraInfo->setVisible( visible ); + m_TimerImage->setVisible( visible ); + m_CurrentTime->setVisible( visible ); + m_Separator->setVisible( visible ); + + for( j = 0; j < TEAM_NUMBER; j++ ) + m_TeamScores[j]->setVisible( visible ); + + if( !visible ) + return; + + m_ExtraInfo->getTextSize( iTextWidth, iTextHeight ); + m_CurrentTime->getTextSize( iTimeWidth, iTimeHeight ); + + iTimeWidth += XRES ( SEPERATOR_WIDTH*2 + 1 ); // +timer icon + iTimeWidth += ( SEPERATOR_WIDTH-(iTimeWidth%SEPERATOR_WIDTH) ); + + if( iTimeWidth > iTextWidth ) + iTextWidth = iTimeWidth; + + int xPos = ScreenWidth - ( iTextWidth + XRES ( SEPERATOR_WIDTH + offset ) ); + + m_ExtraInfo->setBounds( xPos, YRES( SEPERATOR_HEIGHT ), iTextWidth, iTextHeight ); + + m_TimerImage->setBounds( xPos, YRES( SEPERATOR_HEIGHT ) + iTextHeight , XRES(SEPERATOR_WIDTH*2 + 1), YRES(SEPERATOR_HEIGHT + 1) ); + + m_CurrentTime->setBounds( xPos + XRES ( SEPERATOR_WIDTH*2 + 1 ), YRES( SEPERATOR_HEIGHT ) + iTextHeight , iTimeWidth, iTimeHeight ); + + m_Separator->setPos( ScreenWidth - ( iTextWidth + XRES ( 2*SEPERATOR_WIDTH+SEPERATOR_WIDTH/2+offset ) ) , YRES( 5 ) ); + m_Separator->setSize( XRES( 1 ), PANEL_HEIGHT - 10 ); + + for( j = 0; j < TEAM_NUMBER; j++ ) + { + int iwidth, iheight; + + m_TeamScores[j]->getTextSize( iwidth, iheight ); + m_TeamScores[j]->setBounds( ScreenWidth - ( iTextWidth + XRES ( 2*SEPERATOR_WIDTH+2*SEPERATOR_WIDTH/2+offset ) + iwidth ), YRES( SEPERATOR_HEIGHT ) + ( iheight * j ), iwidth, iheight ); + } +} diff --git a/cl_dll/vgui_SpectatorPanel.h b/cl_dll/vgui_SpectatorPanel.h new file mode 100644 index 00000000..5312e963 --- /dev/null +++ b/cl_dll/vgui_SpectatorPanel.h @@ -0,0 +1,111 @@ +//========= Copyright (c) 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +// vgui_SpectatorPanel.h: interface for the SpectatorPanel class. +// +////////////////////////////////////////////////////////////////////// + +#ifndef SPECTATORPANEL_H +#define SPECTATORPANEL_H + +#include +#include +#include + +using namespace vgui; + +#define SPECTATOR_PANEL_CMD_NONE 0 + +#define SPECTATOR_PANEL_CMD_OPTIONS 1 +#define SPECTATOR_PANEL_CMD_PREVPLAYER 2 +#define SPECTATOR_PANEL_CMD_NEXTPLAYER 3 +#define SPECTATOR_PANEL_CMD_HIDEMENU 4 +#define SPECTATOR_PANEL_CMD_TOGGLE_INSET 5 +#define SPECTATOR_PANEL_CMD_CAMERA 6 +#define SPECTATOR_PANEL_CMD_PLAYERS 7 + +// spectator panel sizes +#define PANEL_HEIGHT 64 + +#define BANNER_WIDTH 256 +#define BANNER_HEIGHT 64 + +#define OPTIONS_BUTTON_X 96 +#define CAMOPTIONS_BUTTON_X 200 + + +#define SEPERATOR_WIDTH 15 +#define SEPERATOR_HEIGHT 15 + + +#define TEAM_NUMBER 2 + +class SpectatorPanel : public Panel //, public vgui::CDefaultInputSignal +{ + +public: + SpectatorPanel( int x, int y, int wide, int tall ); + virtual ~SpectatorPanel(); + + void ActionSignal( int cmd ); + + // InputSignal overrides. +public: + void Initialize(); + void Update(); + + void EnableInsetView( bool isEnabled ); + void ShowMenu( bool isVisible ); + + DropDownButton * m_OptionButton; + // CommandButton *m_HideButton; + //ColorButton * m_PrevPlayerButton; + //ColorButton * m_NextPlayerButton; + CImageButton * m_PrevPlayerButton; + CImageButton * m_NextPlayerButton; + DropDownButton * m_CamButton; + + CTransparentPanel *m_TopBorder; + CTransparentPanel *m_BottomBorder; + + ColorButton *m_InsetViewButton; + + DropDownButton *m_BottomMainButton; + CImageLabel *m_TimerImage; + Label *m_BottomMainLabel; + Label *m_CurrentTime; + Label *m_ExtraInfo; + Panel *m_Separator; + + Label *m_TeamScores[TEAM_NUMBER]; + + CImageLabel *m_TopBanner; + + bool m_menuVisible; + bool m_insetVisible; +}; + +class CSpectatorHandler_Command : public ActionSignal +{ + +private: + SpectatorPanel *m_pFather; + int m_cmd; + +public: + CSpectatorHandler_Command( SpectatorPanel *panel, int cmd ) + { + m_pFather = panel; + m_cmd = cmd; + } + + virtual void actionPerformed( Panel *panel ) + { + m_pFather->ActionSignal( m_cmd ); + } +}; +#endif // !defined SPECTATORPANEL_H diff --git a/cl_dll/vgui_TeamFortressViewport.cpp b/cl_dll/vgui_TeamFortressViewport.cpp new file mode 100644 index 00000000..e1d5e58d --- /dev/null +++ b/cl_dll/vgui_TeamFortressViewport.cpp @@ -0,0 +1,2633 @@ +//=========== (C) Copyright 1996-2002 Valve, L.L.C. All rights reserved. =========== +// +// The copyright to the contents herein is the property of Valve, L.L.C. +// The contents may be used and/or copied only with the written permission of +// Valve, L.L.C., or in accordance with the terms and conditions stipulated in +// the agreement/contract under which the contents have been supplied. +// +// Purpose: Client DLL VGUI Viewport +// +// $Workfile: $ +// $Date: $ +// +//----------------------------------------------------------------------------- +// $Log: $ +// +// $NoKeywords: $ +//============================================================================= +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hud.h" +#include "cl_util.h" +#include "camera.h" +#include "kbutton.h" +#include "cvardef.h" +#include "usercmd.h" +#include "const.h" +#include "camera.h" +#include "in_defs.h" +#include "parsemsg.h" +#include "pm_shared.h" +#include "keydefs.h" +#include "demo.h" +#include "demo_api.h" + +#include "vgui_int.h" +#include "vgui_TeamFortressViewport.h" +#include "vgui_ScorePanel.h" +#include "vgui_SpectatorPanel.h" + +#include "shake.h" +#include "screenfade.h" + +void IN_SetVisibleMouse(bool visible); +class CCommandMenu; + +// Scoreboard positions +#define SBOARD_INDENT_X XRES( 104 ) +#define SBOARD_INDENT_Y YRES( 40 ) + +// low-res scoreboard indents +#define SBOARD_INDENT_X_512 30 +#define SBOARD_INDENT_Y_512 30 + +#define SBOARD_INDENT_X_400 0 +#define SBOARD_INDENT_Y_400 20 + +void IN_ResetMouse( void ); +extern CMenuPanel *CMessageWindowPanel_Create( const char *szMOTD, const char *szTitle, int iShadeFullscreen, int iRemoveMe, int x, int y, int wide, int tall ); +extern float *GetClientColor( int clientIndex ); + +using namespace vgui; + +// Team Colors +int iNumberOfTeamColors = 5; +int iTeamColors[5][3] = +{ + { 255, 170, 0 }, // HL orange (default) + { 125, 165, 210 }, // Blue + { 200, 90, 70 }, // Red + { 225, 205, 45 }, // Yellow + { 145, 215, 140 }, // Green +}; + +// Used for Class specific buttons +const char *sTFClasses[] = +{ + "", + "SCOUT", + "SNIPER", + "SOLDIER", + "DEMOMAN", + "MEDIC", + "HWGUY", + "PYRO", + "SPY", + "ENGINEER", + "CIVILIAN", +}; + +const char *sLocalisedClasses[] = +{ + "#Civilian", + "#Scout", + "#Sniper", + "#Soldier", + "#Demoman", + "#Medic", + "#HWGuy", + "#Pyro", + "#Spy", + "#Engineer", + "#Random", + "#Civilian", +}; + +const char *sTFClassSelection[] = +{ + "civilian", + "scout", + "sniper", + "soldier", + "demoman", + "medic", + "hwguy", + "pyro", + "spy", + "engineer", + "randompc", + "civilian", +}; + +#ifdef _TFC +int iBuildingCosts[] = +{ + BUILD_COST_DISPENSER, + BUILD_COST_SENTRYGUN, + BUILD_COST_TELEPORTER +}; + +// This maps class numbers to the Invalid Class bit. +// This is needed for backwards compatability in maps that were finished before +// all the classes were in TF. Hence the wacky sequence. +int sTFValidClassInts[] = +{ + 0, + TF_ILL_SCOUT, + TF_ILL_SNIPER, + TF_ILL_SOLDIER, + TF_ILL_DEMOMAN, + TF_ILL_MEDIC, + TF_ILL_HVYWEP, + TF_ILL_PYRO, + TF_ILL_SPY, + TF_ILL_ENGINEER, + TF_ILL_RANDOMPC, +}; +#endif + +// Get the name of TGA file, based on GameDir +char *GetVGUITGAName( const char *pszName ) +{ + int i; + char sz[256]; + static char gd[256]; + const char *gamedir; + + if( ScreenWidth < 640 ) + i = 320; + else + i = 640; + + sprintf( sz, pszName, i ); + + gamedir = gEngfuncs.pfnGetGameDirectory(); + sprintf( gd, "%s/gfx/vgui/%s.tga", gamedir, sz ); + + return gd; +} + +//================================================================ +// COMMAND MENU +//================================================================ +void CCommandMenu::AddButton( CommandButton *pButton ) +{ + if( m_iButtons >= MAX_BUTTONS ) + return; + + m_aButtons[m_iButtons] = pButton; + m_iButtons++; + pButton->setParent( this ); + pButton->setFont( Scheme::sf_primary3 ); + + // give the button a default key binding + if( m_iButtons < 10 ) + { + pButton->setBoundKey( m_iButtons + '0' ); + } + else if( m_iButtons == 10 ) + { + pButton->setBoundKey( '0' ); + } +} + +void CCommandMenu::RemoveAllButtons(void) +{ + /* + for(int i=0;iIsNotValid() ) + { + if( m_aButtons[i]->getBoundKey() == keyNum ) + { + // hit the button + if( m_aButtons[i]->GetSubMenu() ) + { + // open the sub menu + gViewPort->SetCurrentCommandMenu( m_aButtons[i]->GetSubMenu() ); + return false; + } + else + { + // run the bound command + m_aButtons[i]->fireActionSignal(); + return true; + } + } + } + } + + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: clears the current menus buttons of any armed (highlighted) +// state, and all their sub buttons +//----------------------------------------------------------------------------- +void CCommandMenu::ClearButtonsOfArmedState( void ) +{ + for( int i = 0; i < GetNumButtons(); i++ ) + { + m_aButtons[i]->setArmed( false ); + + if( m_aButtons[i]->GetSubMenu() ) + { + m_aButtons[i]->GetSubMenu()->ClearButtonsOfArmedState(); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pSubMenu - +// Output : CommandButton +//----------------------------------------------------------------------------- +CommandButton *CCommandMenu::FindButtonWithSubmenu( CCommandMenu *pSubMenu ) +{ + for( int i = 0; i < GetNumButtons(); i++ ) + { + if( m_aButtons[i]->GetSubMenu() == pSubMenu ) + return m_aButtons[i]; + } + + return NULL; +} + +// Recalculate the visible buttons +bool CCommandMenu::RecalculateVisibles( int iYOffset, bool bHideAll ) +{ + int i, iCurrentY = 0; + int iVisibleButtons = 0; + + // Cycle through all the buttons in this menu, and see which will be visible + for( i = 0; i < m_iButtons; i++ ) + { + int iClass = m_aButtons[i]->GetPlayerClass(); + + if( ( iClass && iClass != g_iPlayerClass ) || ( m_aButtons[i]->IsNotValid() ) || bHideAll ) + { + m_aButtons[i]->setVisible( false ); + if( m_aButtons[i]->GetSubMenu() != NULL ) + { + (m_aButtons[i]->GetSubMenu())->RecalculateVisibles( 0, true ); + } + } + else + { + // If it's got a submenu, force it to check visibilities + if( m_aButtons[i]->GetSubMenu() != NULL ) + { + if( !( m_aButtons[i]->GetSubMenu() )->RecalculateVisibles( 0, false ) ) + { + // The submenu had no visible buttons, so don't display this button + m_aButtons[i]->setVisible( false ); + continue; + } + } + + m_aButtons[i]->setVisible( true ); + iVisibleButtons++; + } + } + + // Set Size + setSize( _size[0], ( iVisibleButtons * ( m_flButtonSizeY - 1 ) ) + 1 ); + + if( iYOffset ) + { + m_iYOffset = iYOffset; + } + + for( i = 0; i < m_iButtons; i++ ) + { + if( m_aButtons[i]->isVisible() ) + { + if( m_aButtons[i]->GetSubMenu() != NULL ) + ( m_aButtons[i]->GetSubMenu() )->RecalculateVisibles( iCurrentY + m_iYOffset, false ); + + // Make sure it's at the right Y position + // m_aButtons[i]->getPos( iXPos, iYPos ); + if( m_iDirection ) + { + m_aButtons[i]->setPos( 0, ( iVisibleButtons - 1 ) * ( m_flButtonSizeY - 1 ) - iCurrentY ); + } + else + { + m_aButtons[i]->setPos( 0, iCurrentY ); + } + + iCurrentY += ( m_flButtonSizeY - 1 ); + } + } + + return iVisibleButtons ? true : false; +} + +// Make sure all submenus can fit on the screen +void CCommandMenu::RecalculatePositions( int iYOffset ) +{ + int iTop; + int iAdjust = 0; + + m_iYOffset+= iYOffset; + + if( m_iDirection ) + iTop = ScreenHeight - ( m_iYOffset + _size[1] ); + else + iTop = m_iYOffset; + + if( iTop < 0 ) + iTop = 0; + + // Calculate if this is going to fit onscreen, and shuffle it up if it won't + int iBottom = iTop + _size[1]; + + if( iBottom > ScreenHeight ) + { + // Move in increments of button sizes + while( iAdjust < ( iBottom - ScreenHeight ) ) + { + iAdjust += m_flButtonSizeY - 1; + } + + iTop -= iAdjust; + + // Make sure it doesn't move off the top of the screen (the menu's too big to fit it all) + if( iTop < 0 ) + { + iAdjust -= ( 0 - iTop ); + iTop = 0; + } + } + + setPos( _pos[0], iTop ); + + // We need to force all menus below this one to update their positions now, because they + // might have submenus riding off buttons in this menu that have just shifted. + for( int i = 0; i < m_iButtons; i++ ) + m_aButtons[i]->UpdateSubMenus( iAdjust ); +} + +// Make this menu and all menus above it in the chain visible +void CCommandMenu::MakeVisible( CCommandMenu *pChildMenu ) +{ +/* + // Push down the button leading to the child menu + for( int i = 0; i < m_iButtons; i++ ) + { + if( ( pChildMenu != NULL ) && ( m_aButtons[i]->GetSubMenu() == pChildMenu ) ) + { + m_aButtons[i]->setArmed( true ); + } + else + { + m_aButtons[i]->setArmed( false ); + } + } +*/ + + setVisible( true ); + if( m_pParentMenu ) + m_pParentMenu->MakeVisible( this ); +} + +//================================================================ +// CreateSubMenu +CCommandMenu *TeamFortressViewport::CreateSubMenu( CommandButton *pButton, CCommandMenu *pParentMenu, int iYOffset, int iXOffset ) +{ + int iXPos = 0; + int iYPos = 0; + int iWide = CMENU_SIZE_X; + int iTall = 0; + int iDirection = 0; + + if( pParentMenu ) + { + iXPos = m_pCurrentCommandMenu->GetXOffset() + ( CMENU_SIZE_X - 1 ) + iXOffset; + iYPos = m_pCurrentCommandMenu->GetYOffset() + iYOffset; + iDirection = pParentMenu->GetDirection(); + } + + CCommandMenu *pMenu = new CCommandMenu( pParentMenu, iDirection, iXPos, iYPos, iWide, iTall ); + pMenu->setParent( this ); + pButton->AddSubMenu( pMenu ); + pButton->setFont( Scheme::sf_primary3 ); + pMenu->m_flButtonSizeY = m_pCurrentCommandMenu->m_flButtonSizeY; + + // Create the Submenu-open signal + InputSignal *pISignal = new CMenuHandler_PopupSubMenuInput( pButton, pMenu ); + pButton->addInputSignal( pISignal ); + + // Put a > to show it's a submenu + CImageLabel *pLabel = new CImageLabel( "arrow", CMENU_SIZE_X - SUBMENU_SIZE_X, SUBMENU_SIZE_Y ); + pLabel->setParent( pButton ); + pLabel->addInputSignal( pISignal ); + + // Reposition + pLabel->getPos( iXPos, iYPos ); + pLabel->setPos( CMENU_SIZE_X - pLabel->getImageWide(), ( BUTTON_SIZE_Y - pLabel->getImageTall() ) / 2 ); + + // Create the mouse off signal for the Label too + if( !pButton->m_bNoHighlight ) + pLabel->addInputSignal( new CHandler_CommandButtonHighlight( pButton ) ); + + return pMenu; +} + +//----------------------------------------------------------------------------- +// Purpose: Makes sure the memory allocated for TeamFortressViewport is nulled out +// Input : stAllocateBlock - +// Output : void * +//----------------------------------------------------------------------------- +void *TeamFortressViewport::operator new( size_t stAllocateBlock ) +{ +// void *mem = Panel::operator new( stAllocateBlock ); + void *mem = ::operator new( stAllocateBlock ); + memset( mem, 0, stAllocateBlock ); + return mem; +} + +//----------------------------------------------------------------------------- +// Purpose: InputSignal handler for the main viewport +//----------------------------------------------------------------------------- +class CViewPortInputHandler : public InputSignal +{ +public: + bool bPressed; + + CViewPortInputHandler() + { + } + + virtual void cursorMoved( int x, int y, Panel *panel ) {} + virtual void cursorEntered( Panel *panel ) {} + virtual void cursorExited( Panel *panel ) {} + virtual void mousePressed( MouseCode code, Panel *panel ) + { + if( code != MOUSE_LEFT ) + { + // send a message to close the command menu + // this needs to be a message, since a direct call screws the timing + gEngfuncs.pfnClientCmd( "ForceCloseCommandMenu\n" ); + } + } + + virtual void mouseReleased( MouseCode code, Panel *panel ) + { + } + + virtual void mouseDoublePressed( MouseCode code, Panel *panel ) {} + virtual void mouseWheeled( int delta, Panel *panel ) {} + virtual void keyPressed( KeyCode code, Panel *panel ) {} + virtual void keyTyped( KeyCode code, Panel *panel ) {} + virtual void keyReleased( KeyCode code, Panel *panel ) {} + virtual void keyFocusTicked( Panel *panel ) {} +}; + +//================================================================ +TeamFortressViewport::TeamFortressViewport( int x, int y, int wide, int tall ) : Panel( x, y, wide, tall ), m_SchemeManager( wide, tall ) +{ + gViewPort = this; + m_iInitialized = false; + m_pTeamMenu = NULL; + m_pClassMenu = NULL; + m_pScoreBoard = NULL; + m_pSpectatorPanel = NULL; + m_pCurrentMenu = NULL; + m_pCurrentCommandMenu = NULL; + + Initialize(); + addInputSignal( new CViewPortInputHandler ); + + int r, g, b, a; + + Scheme* pScheme = App::getInstance()->getScheme(); + + // primary text color + // Get the colors + //!! two different types of scheme here, need to integrate + SchemeHandle_t hPrimaryScheme = m_SchemeManager.getSchemeHandle( "Primary Button Text" ); + { + // font + pScheme->setFont( Scheme::sf_primary1, m_SchemeManager.getFont( hPrimaryScheme ) ); + + // text color + m_SchemeManager.getFgColor( hPrimaryScheme, r, g, b, a ); + pScheme->setColor( Scheme::sc_primary1, r, g, b, a ); // sc_primary1 is non-transparent orange + + // background color (transparent black) + m_SchemeManager.getBgColor( hPrimaryScheme, r, g, b, a ); + pScheme->setColor( Scheme::sc_primary3, r, g, b, a ); + + // armed foreground color + m_SchemeManager.getFgArmedColor( hPrimaryScheme, r, g, b, a ); + pScheme->setColor( Scheme::sc_secondary2, r, g, b, a ); + + // armed background color + m_SchemeManager.getBgArmedColor( hPrimaryScheme, r, g, b, a ); + pScheme->setColor( Scheme::sc_primary2, r, g, b, a ); + + //!! need to get this color from scheme file + // used for orange borders around buttons + m_SchemeManager.getBorderColor( hPrimaryScheme, r, g, b, a ); + // pScheme->setColor( Scheme::sc_secondary1, r, g, b, a ); + pScheme->setColor( Scheme::sc_secondary1, 255 * 0.7, 170 * 0.7, 0, 0); + } + + // Change the second primary font (used in the scoreboard) + SchemeHandle_t hScoreboardScheme = m_SchemeManager.getSchemeHandle( "Scoreboard Text" ); + { + pScheme->setFont( Scheme::sf_primary2, m_SchemeManager.getFont( hScoreboardScheme ) ); + } + + // Change the third primary font (used in command menu) + SchemeHandle_t hCommandMenuScheme = m_SchemeManager.getSchemeHandle( "CommandMenu Text" ); + { + pScheme->setFont( Scheme::sf_primary3, m_SchemeManager.getFont( hCommandMenuScheme ) ); + } + + App::getInstance()->setScheme( pScheme ); + + // VGUI MENUS + CreateTeamMenu(); + CreateClassMenu(); + CreateSpectatorMenu(); + CreateScoreBoard(); + // Init command menus + m_iNumMenus = 0; + m_iCurrentTeamNumber = m_iUser1 = m_iUser2 = m_iUser3 = 0; + + m_StandardMenu = CreateCommandMenu( "commandmenu.txt", 0, CMENU_TOP, false, CMENU_SIZE_X, BUTTON_SIZE_Y, 0 ); + m_SpectatorOptionsMenu = CreateCommandMenu("spectatormenu.txt", 1, PANEL_HEIGHT, true, CMENU_SIZE_X, BUTTON_SIZE_Y / 2, 0 ); // above bottom bar, flat design + m_SpectatorCameraMenu = CreateCommandMenu("spectcammenu.txt", 1, PANEL_HEIGHT, true, XRES( 200 ), BUTTON_SIZE_Y / 2, ScreenWidth - ( XRES ( 200 ) + 15 ) ); // above bottom bar, flat design + + m_PlayerMenu = m_iNumMenus; + m_iNumMenus++; + + float flLabelSize = ( (ScreenWidth - (XRES ( CAMOPTIONS_BUTTON_X ) + 15)) - XRES ( 24 + 15 ) ) - XRES( (15 + OPTIONS_BUTTON_X + 15) + 38 ); + + m_pCommandMenus[m_PlayerMenu] = new CCommandMenu(NULL, 1, + XRES( ( 15 + OPTIONS_BUTTON_X + 15 ) + 31 ),PANEL_HEIGHT, flLabelSize,300); + m_pCommandMenus[m_PlayerMenu]->setParent(this); + m_pCommandMenus[m_PlayerMenu]->setVisible(false); + m_pCommandMenus[m_PlayerMenu]->m_flButtonSizeY = BUTTON_SIZE_Y /2; + m_pCommandMenus[m_PlayerMenu]->m_iSpectCmdMenu = 1; + + UpdatePlayerMenu(m_PlayerMenu); +} + +//----------------------------------------------------------------------------- +// Purpose: Called everytime a new level is started. Viewport clears out it's data. +//----------------------------------------------------------------------------- +void TeamFortressViewport::Initialize( void ) +{ + // Force each menu to Initialize + if( m_pTeamMenu ) + { + m_pTeamMenu->Initialize(); + } + if( m_pClassMenu ) + { + m_pClassMenu->Initialize(); + } + if( m_pScoreBoard ) + { + m_pScoreBoard->Initialize(); + HideScoreBoard(); + } + if( m_pSpectatorPanel ) + { + // Spectator menu doesn't need initializing + m_pSpectatorPanel->setVisible( false ); + } + + // Make sure all menus are hidden + HideVGUIMenu(); + HideCommandMenu(); + + // Clear out some data + m_iGotAllMOTD = true; + m_iRandomPC = false; + m_flScoreBoardLastUpdated = 0; + m_flSpectatorPanelLastUpdated = 0; + + // reset player info + g_iPlayerClass = 0; + g_iTeamNumber = 0; + + m_sMapName[0] = '\0'; + m_szServerName[0] = '\0'; + for( int i = 0; i < 5; i++ ) + { + m_iValidClasses[i] = 0; + m_sTeamNames[i][0] = '\0'; + } + + App::getInstance()->setCursorOveride( App::getInstance()->getScheme()->getCursor(Scheme::scu_none) ); +} + +class CException; +//----------------------------------------------------------------------------- +// Purpose: Read the Command Menu structure from the txt file and create the menu. +// Returns Index of menu in m_pCommandMenus +//----------------------------------------------------------------------------- +int TeamFortressViewport::CreateCommandMenu( const char *menuFile, int direction, int yOffset, bool flatDesign, float flButtonSizeX, float flButtonSizeY, int xOffset ) +{ + // COMMAND MENU + // Create the root of this new Command Menu + int newIndex = m_iNumMenus; + + m_pCommandMenus[newIndex] = new CCommandMenu( NULL, direction, xOffset, yOffset, flButtonSizeX, 300 ); // This will be resized once we know how many items are in it + m_pCommandMenus[newIndex]->setParent( this ); + m_pCommandMenus[newIndex]->setVisible( false ); + m_pCommandMenus[newIndex]->m_flButtonSizeY = flButtonSizeY; + m_pCommandMenus[newIndex]->m_iSpectCmdMenu = direction; + + m_iNumMenus++; + + // Read Command Menu from the txt file + char token[1024]; + char *pFileStart = (char*)gEngfuncs.COM_LoadFile( menuFile, 5, NULL ); + if( !pFileStart ) + { + gEngfuncs.Con_DPrintf( "Unable to open %s\n", menuFile); + SetCurrentCommandMenu( NULL ); + return newIndex; + } + +#ifdef _WIN32 + try + { +#endif + // First, read in the localisation strings + + // Detpack strings + gHUD.m_TextMessage.LocaliseTextString( "#DetpackSet_For5Seconds", m_sDetpackStrings[0], MAX_BUTTON_SIZE ); + gHUD.m_TextMessage.LocaliseTextString( "#DetpackSet_For20Seconds", m_sDetpackStrings[1], MAX_BUTTON_SIZE ); + gHUD.m_TextMessage.LocaliseTextString( "#DetpackSet_For50Seconds", m_sDetpackStrings[2], MAX_BUTTON_SIZE ); + + // Now start parsing the menu structure + m_pCurrentCommandMenu = m_pCommandMenus[newIndex]; + char szLastButtonText[32] = "file start"; + char* pfile = gEngfuncs.COM_ParseFile( pFileStart, token ); + while( ( strlen ( token ) > 0 ) && ( m_iNumMenus < MAX_MENUS ) ) + { + // Keep looping until we hit the end of this menu + while( token[0] != '}' && ( strlen( token ) > 0 ) ) + { + char cText[32] = ""; + char cBoundKey[32] = ""; + char cCustom[32] = ""; + static const int cCommandLength = 128; + char cCommand[cCommandLength] = ""; + char szMap[MAX_MAPNAME] = ""; + int iPlayerClass = 0; + int iCustom = false; + int iTeamOnly = -1; + int iToggle = 0; + int iButtonY; + bool bGetExtraToken = true; + CommandButton *pButton = NULL; + + // We should never be here without a Command Menu + if( !m_pCurrentCommandMenu ) + { + gEngfuncs.Con_Printf( "Error in %s file after '%s'.\n", menuFile, szLastButtonText ); + gEngfuncs.COM_FreeFile( pFileStart ); // Vit_amiN: prevent the memory leak + m_iInitialized = false; + + return newIndex; + } + + // token should already be the bound key, or the custom name + strncpy( cCustom, token, sizeof(cCustom) - 1 ); + cCustom[sizeof(cCustom) - 1] = '\0'; + + // See if it's a custom button + if( !strcmp( cCustom, "CUSTOM" ) ) + { + iCustom = true; + + // Get the next token + pfile = gEngfuncs.COM_ParseFile( pfile, token ); + } + // See if it's a map + else if( !strcmp( cCustom, "MAP" ) ) + { + // Get the mapname + pfile = gEngfuncs.COM_ParseFile( pfile, token ); + strncpy( szMap, token, MAX_MAPNAME ); + szMap[MAX_MAPNAME - 1] = '\0'; + + // Get the next token + pfile = gEngfuncs.COM_ParseFile( pfile, token ); + } + else if( !strncmp( cCustom, "TEAM", 4 ) ) // TEAM1, TEAM2, TEAM3, TEAM4 + { + // make it a team only button + iTeamOnly = atoi( cCustom + 4 ); + + // Get the next token + pfile = gEngfuncs.COM_ParseFile( pfile, token ); + } + else if( !strncmp( cCustom, "TOGGLE", 6 ) ) + { + iToggle = true; + + // Get the next token + pfile = gEngfuncs.COM_ParseFile( pfile, token ); + } + else + { + // See if it's a Class +#ifdef _TFC + for( int i = 1; i <= PC_ENGINEER; i++ ) + { + if( !strcmp( token, sTFClasses[i] ) ) + { + // Save it off + iPlayerClass = i; + + // Get the button text + pfile = gEngfuncs.COM_ParseFile( pfile, token ); + break; + } + } +#endif + } + + // Get the button bound key + strncpy( cBoundKey, token, 31 ); + cBoundKey[31] = '\0'; + + // Get the button text + pfile = gEngfuncs.COM_ParseFile( pfile, token ); + strncpy( cText, CHudTextMessage::BufferedLocaliseTextString( token ), 31 ); // Vit_amiN: localize button text + cText[31] = '\0'; + + // save off the last button text we've come across (for error reporting) + strcpy( szLastButtonText, cText ); + + // Get the button command + pfile = gEngfuncs.COM_ParseFile( pfile, token ); + strncpy( cCommand, token, cCommandLength - 1 ); + cCommand[cCommandLength - 1] = '\0'; + + iButtonY = ( BUTTON_SIZE_Y - 1 ) * m_pCurrentCommandMenu->GetNumButtons(); + + // Custom button handling + if( iCustom ) + { + pButton = CreateCustomButton( cText, cCommand, iButtonY ); + + // Get the next token to see if we're a menu + pfile = gEngfuncs.COM_ParseFile( pfile, token ); + + if( token[0] == '{' ) + { + strcpy( cCommand, token ); + } + else + { + bGetExtraToken = false; + } + } + else if( szMap[0] != '\0' ) + { + // create a map button + pButton = new MapButton( szMap, cText, xOffset, iButtonY, flButtonSizeX, flButtonSizeY ); + } + else if( iTeamOnly != -1 ) + { + // button that only shows up if the player is on team iTeamOnly + pButton = new TeamOnlyCommandButton( iTeamOnly, cText, xOffset, iButtonY, flButtonSizeX, flButtonSizeY, flatDesign ); + } + else if( iToggle && direction == 0 ) + { + pButton = new ToggleCommandButton( cCommand, cText, xOffset, iButtonY, flButtonSizeX, flButtonSizeY, flatDesign ); + } + else if( direction == 1 ) + { + if( iToggle ) + pButton = new SpectToggleButton( cCommand, cText, xOffset, iButtonY, flButtonSizeX, flButtonSizeY, flatDesign ); + else + pButton = new SpectButton( iPlayerClass, cText, xOffset, iButtonY, flButtonSizeX, flButtonSizeY ); + } + else + { + // normal button + pButton = new CommandButton( iPlayerClass, cText, xOffset, iButtonY, flButtonSizeX, flButtonSizeY, flatDesign ); + } + + // add the button into the command menu + if( pButton ) + { + m_pCurrentCommandMenu->AddButton( pButton ); + pButton->setBoundKey( cBoundKey[0] ); + pButton->setParentMenu( m_pCurrentCommandMenu ); + + // Override font in CommandMenu + pButton->setFont( Scheme::sf_primary3 ); + } + + // Find out if it's a submenu or a button we're dealing with + if( cCommand[0] == '{' ) + { + if( m_iNumMenus >= MAX_MENUS ) + { + gEngfuncs.Con_Printf( "Too many menus in %s past '%s'\n", menuFile, szLastButtonText ); + } + else + { + // Create the menu + m_pCommandMenus[m_iNumMenus] = CreateSubMenu( pButton, m_pCurrentCommandMenu, iButtonY ); + m_pCurrentCommandMenu = m_pCommandMenus[m_iNumMenus]; + m_iNumMenus++; + } + } + else if( !iCustom ) + { + // Create the button and attach it to the current menu + if( iToggle ) + pButton->addActionSignal( new CMenuHandler_ToggleCvar( cCommand ) ); + else + pButton->addActionSignal( new CMenuHandler_StringCommand( cCommand ) ); + + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput( pButton, m_pCurrentCommandMenu ) ); + } + + // Get the next token + if( bGetExtraToken ) + { + pfile = gEngfuncs.COM_ParseFile( pfile, token ); + } + } + + // Move back up a menu + m_pCurrentCommandMenu = m_pCurrentCommandMenu->GetParentMenu(); + + pfile = gEngfuncs.COM_ParseFile( pfile, token ); + } +#ifdef _WIN32 + } + catch( CException *e ) + { + e; + //e->Delete(); + e = NULL; + gEngfuncs.COM_FreeFile( pFileStart ); // Vit_amiN: prevent the memory leak + m_iInitialized = false; + return newIndex; + } +#endif + + SetCurrentMenu( NULL ); + SetCurrentCommandMenu( NULL ); + gEngfuncs.COM_FreeFile( pFileStart ); + + m_iInitialized = true; + + return newIndex; +} + +//----------------------------------------------------------------------------- +// Purpose: Creates all the class choices under a spy's disguise menus, and +// maps a command to them +// Output : CCommandMenu +//----------------------------------------------------------------------------- +CCommandMenu *TeamFortressViewport::CreateDisguiseSubmenu( CommandButton *pButton, CCommandMenu *pParentMenu, const char *commandText, int iYOffset, int iXOffset ) +{ + // create the submenu, under which the class choices will be listed + CCommandMenu *pMenu = CreateSubMenu( pButton, pParentMenu, iYOffset, iXOffset ); + m_pCommandMenus[m_iNumMenus] = pMenu; + m_iNumMenus++; + + // create the class choice buttons +#ifdef _TFC + for( int i = PC_SCOUT; i <= PC_ENGINEER; i++ ) + { + CommandButton *pDisguiseButton = new CommandButton( CHudTextMessage::BufferedLocaliseTextString( sLocalisedClasses[i] ), 0, BUTTON_SIZE_Y, CMENU_SIZE_X, BUTTON_SIZE_Y ); + + char sz[256]; + + sprintf( sz, "%s %d", commandText, i ); + pDisguiseButton->addActionSignal( new CMenuHandler_StringCommand( sz ) ); + + pMenu->AddButton( pDisguiseButton ); + } +#endif + + return pMenu; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pButtonText - +// *pButtonName - +// Output : CommandButton +//----------------------------------------------------------------------------- +CommandButton *TeamFortressViewport::CreateCustomButton( char *pButtonText, char *pButtonName, int iYOffset ) +{ + CommandButton *pButton = NULL; + CCommandMenu *pMenu = NULL; + + // ChangeTeam + if( !strcmp( pButtonName, "!CHANGETEAM" ) ) + { + // ChangeTeam Submenu + pButton = new CommandButton( pButtonText, 0, BUTTON_SIZE_Y * 2, CMENU_SIZE_X, BUTTON_SIZE_Y ); + + // Create the submenu + pMenu = CreateSubMenu(pButton, m_pCurrentCommandMenu, iYOffset ); + m_pCommandMenus[m_iNumMenus] = pMenu; + m_iNumMenus++; + + // ChangeTeam buttons + for( int i = 0; i < 4; i++ ) + { + char sz[256]; + + sprintf( sz, "jointeam %d", i + 1 ); + m_pTeamButtons[i] = new TeamButton( i + 1, "teamname", 0, BUTTON_SIZE_Y, CMENU_SIZE_X, BUTTON_SIZE_Y ); + m_pTeamButtons[i]->addActionSignal( new CMenuHandler_StringCommandWatch( sz ) ); + pMenu->AddButton( m_pTeamButtons[i] ); + } + + // Auto Assign button + m_pTeamButtons[4] = new TeamButton( 5, gHUD.m_TextMessage.BufferedLocaliseTextString( "#Team_AutoAssign" ), 0, BUTTON_SIZE_Y, CMENU_SIZE_X, BUTTON_SIZE_Y ); + m_pTeamButtons[4]->addActionSignal( new CMenuHandler_StringCommand( "jointeam 5" ) ); + pMenu->AddButton( m_pTeamButtons[4] ); + + // Spectate button + m_pTeamButtons[5] = new SpectateButton( CHudTextMessage::BufferedLocaliseTextString( "#Menu_Spectate" ), 0, BUTTON_SIZE_Y, CMENU_SIZE_X, BUTTON_SIZE_Y, false ); + m_pTeamButtons[5]->addActionSignal( new CMenuHandler_StringCommand( "spectate" ) ); + pMenu->AddButton( m_pTeamButtons[5] ); + } + // ChangeClass + else if( !strcmp( pButtonName, "!CHANGECLASS" ) ) + { + // Create the Change class menu + pButton = new ClassButton( -1, pButtonText, 0, BUTTON_SIZE_Y, CMENU_SIZE_X, BUTTON_SIZE_Y, false ); + + // ChangeClass Submenu + pMenu = CreateSubMenu( pButton, m_pCurrentCommandMenu, iYOffset ); + m_pCommandMenus[m_iNumMenus] = pMenu; + m_iNumMenus++; + +#ifdef _TFC + for( int i = PC_SCOUT; i <= PC_RANDOM; i++ ) + { + char sz[256]; + + // ChangeClass buttons + CHudTextMessage::LocaliseTextString( sLocalisedClasses[i], sz, 256 ); + ClassButton *pClassButton = new ClassButton( i, sz, 0, BUTTON_SIZE_Y, CMENU_SIZE_X, BUTTON_SIZE_Y, false ); + + sprintf( sz, "%s", sTFClassSelection[i] ); + pClassButton->addActionSignal( new CMenuHandler_StringCommandClassSelect( sz ) ); + pMenu->AddButton( pClassButton ); + } +#endif + } +#ifdef _TFC + // Map Briefing + else if( !strcmp( pButtonName, "!MAPBRIEFING" ) ) + { + pButton = new CommandButton( pButtonText, 0, BUTTON_SIZE_Y * m_pCurrentCommandMenu->GetNumButtons(), CMENU_SIZE_X, BUTTON_SIZE_Y ); + pButton->addActionSignal( new CMenuHandler_TextWindow( MENU_MAPBRIEFING ) ); + + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput( pButton, m_pCurrentCommandMenu ) ); + } + // Class Descriptions + else if( !strcmp( pButtonName, "!CLASSDESC" ) ) + { + pButton = new ClassButton( 0, pButtonText, 0, BUTTON_SIZE_Y * m_pCurrentCommandMenu->GetNumButtons(), CMENU_SIZE_X, BUTTON_SIZE_Y, false ); + pButton->addActionSignal( new CMenuHandler_TextWindow( MENU_CLASSHELP ) ); + + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput( pButton, m_pCurrentCommandMenu ) ); + } + else if( !strcmp( pButtonName, "!SERVERINFO" ) ) + { + pButton = new ClassButton( 0, pButtonText, 0, BUTTON_SIZE_Y * m_pCurrentCommandMenu->GetNumButtons(), CMENU_SIZE_X, BUTTON_SIZE_Y, false ); + pButton->addActionSignal( new CMenuHandler_TextWindow( MENU_INTRO ) ); + + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput( pButton, m_pCurrentCommandMenu ) ); + } + // Spy abilities + else if( !strcmp( pButtonName, "!SPY" ) ) + { + pButton = new DisguiseButton( 0, pButtonText, 0, BUTTON_SIZE_Y, CMENU_SIZE_X, BUTTON_SIZE_Y ); + } + // Feign + else if( !strcmp( pButtonName, "!FEIGN" ) ) + { + pButton = new FeignButton( FALSE, pButtonText, 0, BUTTON_SIZE_Y, CMENU_SIZE_X, BUTTON_SIZE_Y ); + pButton->addActionSignal( new CMenuHandler_StringCommand( "feign" ) ); + + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput( pButton, m_pCurrentCommandMenu ) ); + } + // Feign Silently + else if( !strcmp( pButtonName, "!FEIGNSILENT" ) ) + { + pButton = new FeignButton( FALSE, pButtonText, 0, BUTTON_SIZE_Y, CMENU_SIZE_X, BUTTON_SIZE_Y ); + pButton->addActionSignal( new CMenuHandler_StringCommand( "sfeign" ) ); + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput( pButton, m_pCurrentCommandMenu ) ); + } + // Stop Feigning + else if( !strcmp( pButtonName, "!FEIGNSTOP" ) ) + { + pButton = new FeignButton( TRUE, pButtonText, 0, BUTTON_SIZE_Y, CMENU_SIZE_X, BUTTON_SIZE_Y ); + pButton->addActionSignal( new CMenuHandler_StringCommand( "feign" ) ); + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput( pButton, m_pCurrentCommandMenu ) ); + } + // Disguise + else if( !strcmp( pButtonName, "!DISGUISEENEMY" ) ) + { + // Create the disguise enemy button, which active only if there are 2 teams + pButton = new DisguiseButton(DISGUISE_TEAM2, pButtonText, 0, BUTTON_SIZE_Y, CMENU_SIZE_X, BUTTON_SIZE_Y); + CreateDisguiseSubmenu( pButton, m_pCurrentCommandMenu, "disguise_enemy", iYOffset); + } + else if( !strcmp( pButtonName, "!DISGUISEFRIENDLY" ) ) + { + // Create the disguise friendly button, which active only if there are 1 or 2 teams + pButton = new DisguiseButton( DISGUISE_TEAM1 | DISGUISE_TEAM2, pButtonText, 0, BUTTON_SIZE_Y, CMENU_SIZE_X, BUTTON_SIZE_Y ); + CreateDisguiseSubmenu( pButton, m_pCurrentCommandMenu, "disguise_friendly", iYOffset ); + } + else if( !strcmp( pButtonName, "!DISGUISE" ) ) + { + // Create the Disguise button + pButton = new DisguiseButton( DISGUISE_TEAM3 | DISGUISE_TEAM4, pButtonText, 0, BUTTON_SIZE_Y, CMENU_SIZE_X, BUTTON_SIZE_Y ); + CCommandMenu *pDisguiseMenu = CreateSubMenu( pButton, m_pCurrentCommandMenu, iYOffset ); + m_pCommandMenus[m_iNumMenus] = pDisguiseMenu; + m_iNumMenus++; + + // Disguise Enemy submenu buttons + for( int i = 1; i <= 4; i++ ) + { + // only show the 4th disguise button if we have 4 teams + m_pDisguiseButtons[i] = new DisguiseButton( ( ( i < 4 ) ? DISGUISE_TEAM3 : 0) | DISGUISE_TEAM4, "Disguise", 0, BUTTON_SIZE_Y, CMENU_SIZE_X, BUTTON_SIZE_Y ); + + pDisguiseMenu->AddButton( m_pDisguiseButtons[i] ); + m_pDisguiseButtons[i]->setParentMenu( pDisguiseMenu ); + + char sz[256]; + + sprintf( sz, "disguise %d", i ); + CreateDisguiseSubmenu( m_pDisguiseButtons[i], pDisguiseMenu, sz, iYOffset, CMENU_SIZE_X - 1 ); + } + } + // Start setting a Detpack + else if( !strcmp( pButtonName, "!DETPACKSTART" ) ) + { + // Detpack Submenu + pButton = new DetpackButton( 2, pButtonText, 0, BUTTON_SIZE_Y * 2, CMENU_SIZE_X, BUTTON_SIZE_Y ); + + // Create the submenu + pMenu = CreateSubMenu( pButton, m_pCurrentCommandMenu, iYOffset ); + m_pCommandMenus[m_iNumMenus] = pMenu; + m_iNumMenus++; + + // Set detpack buttons + CommandButton *pDetButton; + pDetButton = new CommandButton( m_sDetpackStrings[0], 0, BUTTON_SIZE_Y, CMENU_SIZE_X, BUTTON_SIZE_Y ); + pDetButton->addActionSignal( new CMenuHandler_StringCommand( "detstart 5" ) ); + pMenu->AddButton( pDetButton ); + pDetButton = new CommandButton( m_sDetpackStrings[1], 0, BUTTON_SIZE_Y, CMENU_SIZE_X, BUTTON_SIZE_Y ); + pDetButton->addActionSignal( new CMenuHandler_StringCommand( "detstart 20" ) ); + pMenu->AddButton( pDetButton ); + pDetButton = new CommandButton( m_sDetpackStrings[2], 0, BUTTON_SIZE_Y, CMENU_SIZE_X, BUTTON_SIZE_Y ); + pDetButton->addActionSignal( new CMenuHandler_StringCommand( "detstart 50" ) ); + pMenu->AddButton( pDetButton ); + } + // Stop setting a Detpack + else if( !strcmp( pButtonName, "!DETPACKSTOP" ) ) + { + pButton = new DetpackButton( 1, pButtonText, 0, BUTTON_SIZE_Y, CMENU_SIZE_X, BUTTON_SIZE_Y ); + pButton->addActionSignal( new CMenuHandler_StringCommand( "detstop" ) ); + + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput( pButton, m_pCurrentCommandMenu ) ); + } + // Engineer building + else if( !strcmp( pButtonName, "!BUILD" ) ) + { + // only appears if the player is an engineer, and either they have built something or have enough metal to build + pButton = new BuildButton( BUILDSTATE_BASE, 0, pButtonText, 0, BUTTON_SIZE_Y * 2, CMENU_SIZE_X, BUTTON_SIZE_Y ); + } + else if( !strcmp( pButtonName, "!BUILDSENTRY" ) ) + { + pButton = new BuildButton( BUILDSTATE_CANBUILD, BuildButton::SENTRYGUN, pButtonText, 0, BUTTON_SIZE_Y * 2, CMENU_SIZE_X, BUTTON_SIZE_Y ); + pButton->addActionSignal( new CMenuHandler_StringCommand( "build 2" ) ); + + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput( pButton, m_pCurrentCommandMenu ) ); + } + else if( !strcmp( pButtonName, "!BUILDDISPENSER" ) ) + { + pButton = new BuildButton( BUILDSTATE_CANBUILD, BuildButton::DISPENSER, pButtonText, 0, BUTTON_SIZE_Y * 2, CMENU_SIZE_X, BUTTON_SIZE_Y ); + pButton->addActionSignal( new CMenuHandler_StringCommand( "build 1" ) ); + + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput( pButton, m_pCurrentCommandMenu ) ); + } + else if( !strcmp( pButtonName, "!ROTATESENTRY180" ) ) + { + pButton = new BuildButton( BUILDSTATE_HASBUILDING, BuildButton::SENTRYGUN, pButtonText, 0, BUTTON_SIZE_Y * 2, CMENU_SIZE_X, BUTTON_SIZE_Y ); + pButton->addActionSignal( new CMenuHandler_StringCommand( "rotatesentry180" ) ); + + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput( pButton, m_pCurrentCommandMenu ) ); + } + else if( !strcmp( pButtonName, "!ROTATESENTRY" ) ) + { + pButton = new BuildButton( BUILDSTATE_HASBUILDING, BuildButton::SENTRYGUN, pButtonText, 0, BUTTON_SIZE_Y * 2, CMENU_SIZE_X, BUTTON_SIZE_Y ); + pButton->addActionSignal( new CMenuHandler_StringCommand( "rotatesentry" ) ); + + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput(pButton, m_pCurrentCommandMenu) ); + } + else if( !strcmp( pButtonName, "!DISMANTLEDISPENSER" ) ) + { + pButton = new BuildButton( BUILDSTATE_HASBUILDING, BuildButton::DISPENSER, pButtonText, 0, BUTTON_SIZE_Y * 2, CMENU_SIZE_X, BUTTON_SIZE_Y ); + pButton->addActionSignal( new CMenuHandler_StringCommand( "dismantle 1" ) ); + + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput( pButton, m_pCurrentCommandMenu ) ); + } + else if( !strcmp( pButtonName, "!DISMANTLESENTRY" ) ) + { + pButton = new BuildButton( BUILDSTATE_HASBUILDING, BuildButton::SENTRYGUN, pButtonText, 0, BUTTON_SIZE_Y * 2, CMENU_SIZE_X, BUTTON_SIZE_Y ); + pButton->addActionSignal( new CMenuHandler_StringCommand( "dismantle 2" ) ); + + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput( pButton, m_pCurrentCommandMenu ) ); + } + else if( !strcmp( pButtonName, "!DETONATEDISPENSER" ) ) + { + pButton = new BuildButton( BUILDSTATE_HASBUILDING, BuildButton::DISPENSER, pButtonText, 0, BUTTON_SIZE_Y * 2, CMENU_SIZE_X, BUTTON_SIZE_Y ); + pButton->addActionSignal( new CMenuHandler_StringCommand( "detdispenser" ) ); + + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput( pButton, m_pCurrentCommandMenu ) ); + } + else if( !strcmp( pButtonName, "!DETONATESENTRY" ) ) + { + pButton = new BuildButton( BUILDSTATE_HASBUILDING, BuildButton::SENTRYGUN, pButtonText, 0, BUTTON_SIZE_Y * 2, CMENU_SIZE_X, BUTTON_SIZE_Y ); + pButton->addActionSignal( new CMenuHandler_StringCommand( "detsentry" ) ); + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput(pButton, m_pCurrentCommandMenu) ); + } + else if ( !strcmp( pButtonName, "!BUILDENTRYTELEPORTER" ) ) + { + pButton = new BuildButton( BUILDSTATE_CANBUILD, BuildButton::ENTRY_TELEPORTER, pButtonText, 0, BUTTON_SIZE_Y * 2, CMENU_SIZE_X, BUTTON_SIZE_Y); + pButton->addActionSignal(new CMenuHandler_StringCommand("build 4")); + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput(pButton, m_pCurrentCommandMenu) ); + } + else if ( !strcmp( pButtonName, "!DISMANTLEENTRYTELEPORTER" ) ) + { + pButton = new BuildButton( BUILDSTATE_HASBUILDING, BuildButton::ENTRY_TELEPORTER, pButtonText, 0, BUTTON_SIZE_Y * 2, CMENU_SIZE_X, BUTTON_SIZE_Y); + pButton->addActionSignal(new CMenuHandler_StringCommand("dismantle 4")); + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput(pButton, m_pCurrentCommandMenu) ); + } + else if ( !strcmp( pButtonName, "!DETONATEENTRYTELEPORTER" ) ) + { + pButton = new BuildButton( BUILDSTATE_HASBUILDING, BuildButton::ENTRY_TELEPORTER, pButtonText, 0, BUTTON_SIZE_Y * 2, CMENU_SIZE_X, BUTTON_SIZE_Y); + pButton->addActionSignal(new CMenuHandler_StringCommand("detentryteleporter")); + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput(pButton, m_pCurrentCommandMenu) ); + } + else if ( !strcmp( pButtonName, "!BUILDEXITTELEPORTER" ) ) + { + pButton = new BuildButton( BUILDSTATE_CANBUILD, BuildButton::EXIT_TELEPORTER, pButtonText, 0, BUTTON_SIZE_Y * 2, CMENU_SIZE_X, BUTTON_SIZE_Y); + pButton->addActionSignal(new CMenuHandler_StringCommand("build 5")); + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput(pButton, m_pCurrentCommandMenu) ); + } + else if ( !strcmp( pButtonName, "!DISMANTLEEXITTELEPORTER" ) ) + { + pButton = new BuildButton( BUILDSTATE_HASBUILDING, BuildButton::EXIT_TELEPORTER, pButtonText, 0, BUTTON_SIZE_Y * 2, CMENU_SIZE_X, BUTTON_SIZE_Y); + pButton->addActionSignal(new CMenuHandler_StringCommand("dismantle 5")); + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput(pButton, m_pCurrentCommandMenu) ); + } + else if ( !strcmp( pButtonName, "!DETONATEEXITTELEPORTER" ) ) + { + pButton = new BuildButton( BUILDSTATE_HASBUILDING, BuildButton::EXIT_TELEPORTER, pButtonText, 0, BUTTON_SIZE_Y * 2, CMENU_SIZE_X, BUTTON_SIZE_Y); + pButton->addActionSignal(new CMenuHandler_StringCommand("detexitteleporter")); + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput( pButton, m_pCurrentCommandMenu ) ); + } + // Stop building + else if( !strcmp( pButtonName, "!BUILDSTOP" ) ) + { + pButton = new BuildButton( BUILDSTATE_BUILDING, 0, pButtonText, 0, BUTTON_SIZE_Y * 2, CMENU_SIZE_X, BUTTON_SIZE_Y ); + pButton->addActionSignal( new CMenuHandler_StringCommand( "build" ) ); + + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput( pButton, m_pCurrentCommandMenu ) ); + } +#endif + + return pButton; +} + +//======================================================================= +void TeamFortressViewport::ShowCommandMenu( int menuIndex ) +{ + if( !m_iInitialized ) + return; + + // Already have a menu open. + if( m_pCurrentMenu ) + return; + + // is the command menu open? + if( m_pCurrentCommandMenu == m_pCommandMenus[menuIndex] ) + { + HideCommandMenu(); + return; + } + + // Not visible while in intermission + if( gHUD.m_iIntermission ) + return; + + // Recalculate visible menus + UpdateCommandMenu( menuIndex ); + HideVGUIMenu(); + + SetCurrentCommandMenu( m_pCommandMenus[menuIndex] ); + m_flMenuOpenTime = gHUD.m_flTime; + UpdateCursorState(); + + // get command menu parameters + for( int i = 2; i < gEngfuncs.Cmd_Argc(); i++ ) + { + const char *param = gEngfuncs.Cmd_Argv( i - 1 ); + if( param ) + { + if( m_pCurrentCommandMenu->KeyInput(param[0]) ) + { + // kill the menu open time, since the key input is final + HideCommandMenu(); + } + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Handles the key input of "-commandmenu" +// Input : +//----------------------------------------------------------------------------- +void TeamFortressViewport::InputSignalHideCommandMenu() +{ + if( !m_iInitialized ) + return; + + // if they've just tapped the command menu key, leave it open + if( (m_flMenuOpenTime + 0.3 ) > gHUD.m_flTime ) + return; + + HideCommandMenu(); +} + +//----------------------------------------------------------------------------- +// Purpose: Hides the command menu +//----------------------------------------------------------------------------- +void TeamFortressViewport::HideCommandMenu() +{ + if( !m_iInitialized ) + return; + + if( m_pCommandMenus[m_StandardMenu] ) + { + m_pCommandMenus[m_StandardMenu]->ClearButtonsOfArmedState(); + } + + if( m_pCommandMenus[m_SpectatorOptionsMenu] ) + { + m_pCommandMenus[m_SpectatorOptionsMenu]->ClearButtonsOfArmedState(); + } + + if( m_pCommandMenus[m_SpectatorCameraMenu] ) + { + m_pCommandMenus[m_SpectatorCameraMenu]->ClearButtonsOfArmedState(); + } + + if ( m_pCommandMenus[m_PlayerMenu] ) + { + m_pCommandMenus[m_PlayerMenu]->ClearButtonsOfArmedState(); + } + + + m_flMenuOpenTime = 0.0f; + SetCurrentCommandMenu( NULL ); + UpdateCursorState(); +} + +//----------------------------------------------------------------------------- +// Purpose: Bring up the scoreboard +//----------------------------------------------------------------------------- +void TeamFortressViewport::ShowScoreBoard( void ) +{ + if( m_pScoreBoard ) + { + // No Scoreboard in single-player + if( gEngfuncs.GetMaxClients() > 1 ) + { + m_pScoreBoard->Open(); + UpdateCursorState(); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Returns true if the scoreboard is up +//----------------------------------------------------------------------------- +bool TeamFortressViewport::IsScoreBoardVisible( void ) +{ + if( m_pScoreBoard ) + return m_pScoreBoard->isVisible(); + + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: Hide the scoreboard +//----------------------------------------------------------------------------- +void TeamFortressViewport::HideScoreBoard( void ) +{ + // Prevent removal of scoreboard during intermission + if( gHUD.m_iIntermission ) + return; + + if( m_pScoreBoard ) + { + m_pScoreBoard->setVisible( false ); + + GetClientVoiceMgr()->StopSquelchMode(); + + UpdateCursorState(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Activate's the player special ability +// called when the player hits their "special" key +//----------------------------------------------------------------------------- +void TeamFortressViewport::InputPlayerSpecial( void ) +{ + if( !m_iInitialized ) + return; + +#ifdef _TFC + if( g_iPlayerClass == PC_ENGINEER || g_iPlayerClass == PC_SPY ) + { + ShowCommandMenu( gViewPort->m_StandardMenu ); + + if( m_pCurrentCommandMenu ) + { + m_pCurrentCommandMenu->KeyInput( '7' ); + } + } + else +#endif + { + // if it's any other class, just send the command down to the server + ClientCmd( "_special" ); + } +} + +// Set the submenu of the Command Menu +void TeamFortressViewport::SetCurrentCommandMenu( CCommandMenu *pNewMenu ) +{ + for( int i = 0; i < m_iNumMenus; i++ ) + m_pCommandMenus[i]->setVisible( false ); + + m_pCurrentCommandMenu = pNewMenu; + + if( m_pCurrentCommandMenu ) + m_pCurrentCommandMenu->MakeVisible( NULL ); +} + +void TeamFortressViewport::UpdateCommandMenu( int menuIndex ) +{ + // if its the player menu update the player list + if(menuIndex==m_PlayerMenu) + { + m_pCommandMenus[m_PlayerMenu]->RemoveAllButtons(); + UpdatePlayerMenu(m_PlayerMenu); + } + + m_pCommandMenus[menuIndex]->RecalculateVisibles( 0, false ); + m_pCommandMenus[menuIndex]->RecalculatePositions( 0 ); +} + +void TeamFortressViewport::UpdatePlayerMenu(int menuIndex) +{ + + cl_entity_t * pEnt = NULL; + float flLabelSize = ( (ScreenWidth - (XRES ( CAMOPTIONS_BUTTON_X ) + 15)) - XRES ( 24 + 15 ) ) - XRES( (15 + OPTIONS_BUTTON_X + 15) + 38 ); + gViewPort->GetAllPlayersInfo(); + + + for (int i = 1; i < MAX_PLAYERS; i++ ) + { + //if ( g_PlayerInfoList[i].name == NULL ) + // continue; // empty player slot, skip + + pEnt = gEngfuncs.GetEntityByIndex( i ); + + if ( !gHUD.m_Spectator.IsActivePlayer( pEnt ) ) + continue; + + //if ( g_PlayerExtraInfo[i].teamname[0] == 0 ) + // continue; // skip over players who are not in a team + + SpectButton *pButton = new SpectButton(1 , g_PlayerInfoList[pEnt->index].name , + XRES( ( 15 + OPTIONS_BUTTON_X + 15 ) + 31 ),PANEL_HEIGHT+(i-1)*CMENU_SIZE_X, flLabelSize, BUTTON_SIZE_Y /2 ); + + pButton->setBoundKey( (char)255 ); + pButton->setContentAlignment( vgui::Label::a_center ); + m_pCommandMenus[menuIndex]->AddButton( pButton ); + pButton->setParentMenu( m_pCommandMenus[menuIndex] ); + + // Override font in CommandMenu + pButton->setFont( Scheme::sf_primary3 ); + + pButton->addActionSignal(new CMenuHandler_SpectateFollow( g_PlayerInfoList[pEnt->index].name)); + // Create an input signal that'll popup the current menu + pButton->addInputSignal( new CMenuHandler_PopupSubMenuInput(pButton, m_pCommandMenus[menuIndex]) ); + + } + +} + + + +void COM_FileBase( const char *in, char *out ); + +void TeamFortressViewport::UpdateSpectatorPanel() +{ + m_iUser1 = g_iUser1; + m_iUser2 = g_iUser2; + m_iUser3 = g_iUser3; + + if( !m_pSpectatorPanel ) + return; + + if( g_iUser1 && gHUD.m_pCvarDraw->value && !gHUD.m_iIntermission ) // don't draw in dev_overview mode + { + char bottomText[128]; + char helpString2[128]; + char tempString[128]; + char *name; + char *pBottomText = NULL; + int player = 0; + + // check if spectator combinations are still valid + gHUD.m_Spectator.CheckSettings(); + + if( !m_pSpectatorPanel->isVisible() ) + { + m_pSpectatorPanel->setVisible( true ); // show spectator panel, but + m_pSpectatorPanel->ShowMenu( false ); // dsiable all menus/buttons + + _snprintf( tempString, sizeof(tempString) - 1, "%c%s", HUD_PRINTCENTER, CHudTextMessage::BufferedLocaliseTextString( "#Spec_Duck" ) ); + tempString[sizeof(tempString) - 1] = '\0'; + + gHUD.m_TextMessage.MsgFunc_TextMsg( NULL, strlen( tempString ) + 1, tempString ); + } + + sprintf(bottomText,"#Spec_Mode%d", g_iUser1 ); + sprintf(helpString2,"#Spec_Mode%d", g_iUser1 ); + + if( gEngfuncs.IsSpectateOnly() ) + strcat( helpString2, " - HLTV" ); + + // check if we're locked onto a target, show the player's name + if( ( g_iUser2 > 0 ) && ( g_iUser2 <= gEngfuncs.GetMaxClients() ) && ( g_iUser1 != OBS_ROAMING ) ) + { + player = g_iUser2; + } + + // special case in free map and inset off, don't show names + if( ( g_iUser1 == OBS_MAP_FREE ) && !gHUD.m_Spectator.m_pip->value ) + name = NULL; + else + name = g_PlayerInfoList[player].name; + + // create player & health string + if( player && name ) + { + strncpy( bottomText, name, sizeof(bottomText) ); + bottomText[ sizeof(bottomText) - 1 ] = 0; + pBottomText = bottomText; + } + else + { + pBottomText = CHudTextMessage::BufferedLocaliseTextString( bottomText ); + } + + // in first person mode colorize player names + if( ( g_iUser1 == OBS_IN_EYE ) && player ) + { + float *color = GetClientColor( player ); + int r = color[0]*255; + int g = color[1]*255; + int b = color[2]*255; + + // set team color, a bit transparent + m_pSpectatorPanel->m_BottomMainLabel->setFgColor( r, g, b, 0 ); + } + else + { // restore GUI color + m_pSpectatorPanel->m_BottomMainLabel->setFgColor( 143, 143, 54, 0 ); + } + + // add sting auto if we are in auto directed mode + if( gHUD.m_Spectator.m_autoDirector->value ) + { + char tempString[128]; + + sprintf( tempString, "#Spec_Auto %s", helpString2 ); + strcpy( helpString2, tempString ); + } + + m_pSpectatorPanel->m_BottomMainLabel->setText( "%s", pBottomText ); + m_pSpectatorPanel->m_BottomMainButton->setText( pBottomText ); + + + // update extra info field + char szText[64]; + + if( gEngfuncs.IsSpectateOnly() ) + { + // in HLTV mode show number of spectators + _snprintf( szText, sizeof(szText) - 1, "%s: %d", CHudTextMessage::BufferedLocaliseTextString( "#Spectators" ), gHUD.m_Spectator.m_iSpectatorNumber ); + } + else + { + // otherwise show map name + char szMapName[64]; + + COM_FileBase( gEngfuncs.pfnGetLevelName(), szMapName ); + + _snprintf( szText, sizeof(szText) - 1, "%s: %s",CHudTextMessage::BufferedLocaliseTextString( "#Spec_Map" ), szMapName ); + } + + szText[sizeof(szText) - 1] = '\0'; + + m_pSpectatorPanel->m_ExtraInfo->setText( szText ); + + /* + int timer = (int)( gHUD.m_roundTimer.m_flTimeEnd - gHUD.m_flTime ); + + if( timer < 0 ) + timer = 0; + + _snprintf( szText, 63, "%d:%02d\n", ( timer / 60 ), ( timer % 60 ) ); + + szText[63] = 0; + + m_pSpectatorPanel->m_CurrentTime->setText( szText ); */ + + // update spectator panel + gViewPort->m_pSpectatorPanel->Update(); + } + else + { + if( m_pSpectatorPanel->isVisible() ) + { + m_pSpectatorPanel->setVisible( false ); + m_pSpectatorPanel->ShowMenu( false ); // dsiable all menus/buttons + } + } + + m_flSpectatorPanelLastUpdated = gHUD.m_flTime + 1.0; // update every second +} + +//====================================================================== +void TeamFortressViewport::CreateScoreBoard( void ) +{ + int xdent = SBOARD_INDENT_X, ydent = SBOARD_INDENT_Y; + if( ScreenWidth == 512 ) + { + xdent = SBOARD_INDENT_X_512; + ydent = SBOARD_INDENT_Y_512; + } + else if( ScreenWidth == 400 ) + { + xdent = SBOARD_INDENT_X_400; + ydent = SBOARD_INDENT_Y_400; + } + + m_pScoreBoard = new ScorePanel( xdent, ydent, ScreenWidth - ( xdent * 2 ), ScreenHeight - ( ydent * 2 ) ); + m_pScoreBoard->setParent( this ); + m_pScoreBoard->setVisible( false ); +} + +//====================================================================== +// Set the VGUI Menu +void TeamFortressViewport::SetCurrentMenu( CMenuPanel *pMenu ) +{ + m_pCurrentMenu = pMenu; + if( m_pCurrentMenu ) + { + // Don't open menus in demo playback + if( gEngfuncs.pDemoAPI->IsPlayingback() ) + return; + + m_pCurrentMenu->Open(); + } + else + { + gEngfuncs.pfnClientCmd( "closemenus;" ); + } +} + +//================================================================ +// Text Window +CMenuPanel *TeamFortressViewport::CreateTextWindow( int iTextToShow ) +{ + char sz[256]; + char *cText; + char *pfile = NULL; + static const int MAX_TITLE_LENGTH = 64; + char cTitle[MAX_TITLE_LENGTH]; + + if( iTextToShow == SHOW_MOTD ) + { + if( !m_szServerName[0] ) + strcpy( cTitle, "Half-Life" ); + else + { + strncpy( cTitle, m_szServerName, MAX_TITLE_LENGTH - 1 ); + cTitle[MAX_TITLE_LENGTH - 1] = '\0'; + } + + cText = m_szMOTD; + } + else if( iTextToShow == SHOW_MAPBRIEFING ) + { + // Get the current mapname, and open it's map briefing text + if( m_sMapName[0] ) + { + strcpy( sz, "maps/"); + strcat( sz, m_sMapName ); + strcat( sz, ".txt" ); + } + else + { + const char *level = gEngfuncs.pfnGetLevelName(); + if( !level ) + return NULL; + + strcpy( sz, level ); + char *ch = strchr( sz, '.' ); + *ch = '\0'; + strcat( sz, ".txt" ); + + // pull out the map name + strcpy( m_sMapName, level ); + ch = strchr( m_sMapName, '.' ); + if( ch ) + { + *ch = 0; + } + + ch = strchr( m_sMapName, '/' ); + if( ch ) + { + // move the string back over the '/' + memmove( m_sMapName, ch + 1, strlen( ch ) + 1 ); + } + } + + pfile = (char*)gEngfuncs.COM_LoadFile( sz, 5, NULL ); + + if( !pfile ) + return NULL; + + cText = pfile; + + strncpy( cTitle, m_sMapName, MAX_TITLE_LENGTH ); + cTitle[MAX_TITLE_LENGTH - 1] = 0; + } +#ifdef _TFC + else if( iTextToShow == SHOW_CLASSDESC ) + { + switch( g_iPlayerClass ) + { + case PC_SCOUT: cText = CHudTextMessage::BufferedLocaliseTextString( "#Help_scout" ); + CHudTextMessage::LocaliseTextString( "#Title_scout", cTitle, MAX_TITLE_LENGTH ); break; + case PC_SNIPER: cText = CHudTextMessage::BufferedLocaliseTextString( "#Help_sniper" ); + CHudTextMessage::LocaliseTextString( "#Title_sniper", cTitle, MAX_TITLE_LENGTH ); break; + case PC_SOLDIER: cText = CHudTextMessage::BufferedLocaliseTextString( "#Help_soldier" ); + CHudTextMessage::LocaliseTextString( "#Title_soldier", cTitle, MAX_TITLE_LENGTH ); break; + case PC_DEMOMAN: cText = CHudTextMessage::BufferedLocaliseTextString( "#Help_demoman" ); + CHudTextMessage::LocaliseTextString( "#Title_demoman", cTitle, MAX_TITLE_LENGTH ); break; + case PC_MEDIC: cText = CHudTextMessage::BufferedLocaliseTextString( "#Help_medic" ); + CHudTextMessage::LocaliseTextString( "#Title_medic", cTitle, MAX_TITLE_LENGTH ); break; + case PC_HVYWEAP: cText = CHudTextMessage::BufferedLocaliseTextString( "#Help_hwguy" ); + CHudTextMessage::LocaliseTextString( "#Title_hwguy", cTitle, MAX_TITLE_LENGTH ); break; + case PC_PYRO: cText = CHudTextMessage::BufferedLocaliseTextString( "#Help_pyro" ); + CHudTextMessage::LocaliseTextString( "#Title_pyro", cTitle, MAX_TITLE_LENGTH ); break; + case PC_SPY: cText = CHudTextMessage::BufferedLocaliseTextString( "#Help_spy" ); + CHudTextMessage::LocaliseTextString( "#Title_spy", cTitle, MAX_TITLE_LENGTH ); break; + case PC_ENGINEER: cText = CHudTextMessage::BufferedLocaliseTextString( "#Help_engineer" ); + CHudTextMessage::LocaliseTextString( "#Title_engineer", cTitle, MAX_TITLE_LENGTH ); break; + case PC_CIVILIAN: cText = CHudTextMessage::BufferedLocaliseTextString( "#Help_civilian" ); + CHudTextMessage::LocaliseTextString( "#Title_civilian", cTitle, MAX_TITLE_LENGTH ); break; + default: + return NULL; + } + + if( g_iPlayerClass == PC_CIVILIAN ) + { + strcpy(sz, "classes/long_civilian.txt"); + } + else + { + sprintf( sz, "classes/long_%s.txt", sTFClassSelection[g_iPlayerClass] ); + } + + char *pfile = (char*)gEngfuncs.COM_LoadFile( sz, 5, NULL ); + if( pfile ) + { + cText = pfile; + } + } +#endif + else if( iTextToShow == SHOW_SPECHELP ) + { + CHudTextMessage::LocaliseTextString( "#Spec_Help_Title", cTitle, MAX_TITLE_LENGTH ); + cTitle[MAX_TITLE_LENGTH - 1] = 0; + + char *pfile = CHudTextMessage::BufferedLocaliseTextString( "#Spec_Help_Text" ); + if( pfile ) + { + cText = pfile; + } + } + + // if we're in the game (ie. have selected a class), flag the menu to be only grayed in the dialog box, instead of full screen + CMenuPanel *pMOTDPanel = CMessageWindowPanel_Create( cText, cTitle, g_iPlayerClass == PC_UNDEFINED, false, 0, 0, ScreenWidth, ScreenHeight ); + pMOTDPanel->setParent( this ); + + if( pfile ) + gEngfuncs.COM_FreeFile( pfile ); + + return pMOTDPanel; +} + +//================================================================ +// VGUI Menus +void TeamFortressViewport::ShowVGUIMenu( int iMenu ) +{ + CMenuPanel *pNewMenu = NULL; + + // Don't open menus in demo playback + if( gEngfuncs.pDemoAPI->IsPlayingback() ) + return; + + // Don't open any menus except the MOTD during intermission + // MOTD needs to be accepted because it's sent down to the client + // after map change, before intermission's turned off + if( gHUD.m_iIntermission && iMenu != MENU_INTRO ) + return; + + // Don't create one if it's already in the list + if( m_pCurrentMenu ) + { + CMenuPanel *pMenu = m_pCurrentMenu; + while( pMenu != NULL ) + { + if( pMenu->GetMenuID() == iMenu ) + return; + + pMenu = pMenu->GetNextMenu(); + } + } + + switch( iMenu ) + { + case MENU_TEAM: + pNewMenu = ShowTeamMenu(); + break; + + // Map Briefing removed now that it appears in the team menu + case MENU_MAPBRIEFING: + pNewMenu = CreateTextWindow( SHOW_MAPBRIEFING ); + break; + + case MENU_INTRO: + pNewMenu = CreateTextWindow( SHOW_MOTD ); + break; + + case MENU_CLASSHELP: + pNewMenu = CreateTextWindow( SHOW_CLASSDESC ); + break; + + case MENU_SPECHELP: + pNewMenu = CreateTextWindow( SHOW_SPECHELP ); + break; + case MENU_CLASS: + pNewMenu = ShowClassMenu(); + break; + + default: + break; + } + + if( !pNewMenu ) + return; + + // Close the Command Menu if it's open + HideCommandMenu(); + + pNewMenu->SetMenuID( iMenu ); + pNewMenu->SetActive( true ); + pNewMenu->setParent( this ); + + // See if another menu is visible, and if so, cache this one for display once the other one's finished + if( m_pCurrentMenu ) + { + if( m_pCurrentMenu->GetMenuID() == MENU_CLASS && iMenu == MENU_TEAM ) + { + CMenuPanel *temp = m_pCurrentMenu; + m_pCurrentMenu->Close(); + m_pCurrentMenu = pNewMenu; + m_pCurrentMenu->SetNextMenu( temp ); + m_pCurrentMenu->Open(); + UpdateCursorState(); + } + else + { + m_pCurrentMenu->SetNextMenu( pNewMenu ); + } + } + else + { + m_pCurrentMenu = pNewMenu; + m_pCurrentMenu->Open(); + UpdateCursorState(); + } +} + +// Removes all VGUI Menu's onscreen +void TeamFortressViewport::HideVGUIMenu() +{ + while( m_pCurrentMenu ) + { + HideTopMenu(); + } +} + +// Remove the top VGUI menu, and bring up the next one +void TeamFortressViewport::HideTopMenu() +{ + if( m_pCurrentMenu ) + { + // Close the top one + m_pCurrentMenu->Close(); + + // Bring up the next one + gViewPort->SetCurrentMenu( m_pCurrentMenu->GetNextMenu() ); + } + + UpdateCursorState(); +} + +// Return TRUE if the HUD's allowed to print text messages +bool TeamFortressViewport::AllowedToPrintText( void ) +{ + // Prevent text messages when fullscreen menus are up + if( m_pCurrentMenu && g_iPlayerClass == 0 ) + { + int iId = m_pCurrentMenu->GetMenuID(); + if( iId == MENU_TEAM || iId == MENU_CLASS || iId == MENU_INTRO || iId == MENU_CLASSHELP ) + return FALSE; + } + + return TRUE; +} + +//====================================================================================== +// TEAM MENU +//====================================================================================== +// Bring up the Team selection Menu +CMenuPanel* TeamFortressViewport::ShowTeamMenu() +{ + // Don't open menus in demo playback + if( gEngfuncs.pDemoAPI->IsPlayingback() ) + return NULL; + + m_pTeamMenu->Reset(); + return m_pTeamMenu; +} + +void TeamFortressViewport::CreateTeamMenu() +{ + // Create the panel + m_pTeamMenu = new CTeamMenuPanel( 100, false, 0, 0, ScreenWidth, ScreenHeight ); + m_pTeamMenu->setParent( this ); + m_pTeamMenu->setVisible( false ); +} + +//====================================================================================== +// CLASS MENU +//====================================================================================== +// Bring up the Class selection Menu +CMenuPanel* TeamFortressViewport::ShowClassMenu() +{ + // Don't open menus in demo playback + if( gEngfuncs.pDemoAPI->IsPlayingback() ) + return NULL; + + m_pClassMenu->Reset(); + return m_pClassMenu; +} + +void TeamFortressViewport::CreateClassMenu() +{ + // Create the panel + m_pClassMenu = new CClassMenuPanel( 100, false, 0, 0, ScreenWidth, ScreenHeight ); + m_pClassMenu->setParent( this ); + m_pClassMenu->setVisible( false ); +} + +//====================================================================================== +//====================================================================================== +// SPECTATOR MENU +//====================================================================================== +// Spectator "Menu" explaining the Spectator buttons +void TeamFortressViewport::CreateSpectatorMenu() +{ + // Create the Panel + m_pSpectatorPanel = new SpectatorPanel( 0, 0, ScreenWidth, ScreenHeight ); + m_pSpectatorPanel->setParent( this ); + m_pSpectatorPanel->setVisible( false ); + m_pSpectatorPanel->Initialize(); +} + +//====================================================================================== +// UPDATE HUD SECTIONS +//====================================================================================== +// We've got an update on player info +// Recalculate any menus that use it. +void TeamFortressViewport::UpdateOnPlayerInfo() +{ + if( m_pTeamMenu ) + m_pTeamMenu->Update(); + + if( m_pClassMenu ) + m_pClassMenu->Update(); + + if( m_pScoreBoard ) + m_pScoreBoard->Update(); +} + +void TeamFortressViewport::UpdateCursorState() +{ + // Need cursor if any VGUI window is up + if( m_pSpectatorPanel->m_menuVisible || m_pCurrentMenu || m_pTeamMenu->isVisible() || GetClientVoiceMgr()->IsInSquelchMode() ) + { + IN_SetVisibleMouse(true); + App::getInstance()->setCursorOveride( App::getInstance()->getScheme()->getCursor(Scheme::scu_arrow) ); + return; + } + else if( m_pCurrentCommandMenu ) + { + // commandmenu doesn't have cursor if hud_capturemouse is turned off + if( gHUD.m_pCvarStealMouse->value != 0.0f ) + { + IN_SetVisibleMouse(true); + App::getInstance()->setCursorOveride( App::getInstance()->getScheme()->getCursor(Scheme::scu_arrow) ); + return; + } + } + + App::getInstance()->setCursorOveride( App::getInstance()->getScheme()->getCursor(Scheme::scu_none) ); + IN_SetVisibleMouse(false); + + // Don't reset mouse in demo playback + if( !gEngfuncs.pDemoAPI->IsPlayingback() ) + { + IN_ResetMouse(); + } +} + +void TeamFortressViewport::UpdateHighlights() +{ + if( m_pCurrentCommandMenu ) + m_pCurrentCommandMenu->MakeVisible( NULL ); +} + +void TeamFortressViewport::GetAllPlayersInfo( void ) +{ + for( int i = 1; i < MAX_PLAYERS; i++ ) + { + GetPlayerInfo( i, &g_PlayerInfoList[i] ); + + if( g_PlayerInfoList[i].thisplayer ) + m_pScoreBoard->m_iPlayerNum = i; // !!!HACK: this should be initialized elsewhere... maybe gotten from the engine + } +} + +void TeamFortressViewport::paintBackground() +{ + int wide, tall; + getParent()->getSize( wide, tall ); + setSize( wide, tall ); + if( m_pScoreBoard ) + { + int x, y; + getApp()->getCursorPos( x, y ); + m_pScoreBoard->cursorMoved( x, y, m_pScoreBoard ); + } + + // See if the command menu is visible and needs recalculating due to some external change + if( g_iTeamNumber != m_iCurrentTeamNumber ) + { + UpdateCommandMenu( m_StandardMenu ); + + if( m_pClassMenu ) + { + m_pClassMenu->Update(); + } + + m_iCurrentTeamNumber = g_iTeamNumber; + } + + if( g_iPlayerClass != m_iCurrentPlayerClass ) + { + UpdateCommandMenu( m_StandardMenu ); + + m_iCurrentPlayerClass = g_iPlayerClass; + } + + // See if the Spectator Menu needs to be update + if( ( g_iUser1 != m_iUser1 || g_iUser2 != m_iUser2 ) || + ( m_flSpectatorPanelLastUpdated < gHUD.m_flTime ) ) + { + UpdateSpectatorPanel(); + } + + // Update the Scoreboard, if it's visible + if( m_pScoreBoard->isVisible() && ( m_flScoreBoardLastUpdated < gHUD.m_flTime ) ) + { + m_pScoreBoard->Update(); + m_flScoreBoardLastUpdated = gHUD.m_flTime + 0.5; + } + + int extents[4]; + + getAbsExtents( extents[0], extents[1], extents[2], extents[3] ); + + VGui_ViewportPaintBackground( extents ); +} + +//================================================================ +// Input Handler for Drag N Drop panels +void CDragNDropHandler::cursorMoved( int x, int y, Panel *panel ) +{ + if( m_bDragging ) + { + App::getInstance()->getCursorPos( x, y ); + m_pPanel->setPos( m_iaDragOrgPos[0] + ( x - m_iaDragStart[0] ), m_iaDragOrgPos[1] + ( y - m_iaDragStart[1] ) ); + + if( m_pPanel->getParent() != null ) + { + m_pPanel->getParent()->repaint(); + } + } +} + +void CDragNDropHandler::mousePressed( MouseCode code, Panel *panel ) +{ + int x, y; + App::getInstance()->getCursorPos( x, y ); + m_bDragging = true; + m_iaDragStart[0] = x; + m_iaDragStart[1] = y; + m_pPanel->getPos( m_iaDragOrgPos[0], m_iaDragOrgPos[1] ); + App::getInstance()->setMouseCapture( panel ); + + m_pPanel->setDragged( m_bDragging ); + m_pPanel->requestFocus(); +} + +void CDragNDropHandler::mouseReleased( MouseCode code, Panel *panel ) +{ + m_bDragging = false; + m_pPanel->setDragged( m_bDragging ); + App::getInstance()->setMouseCapture( null ); +} + +//================================================================ +// Number Key Input +bool TeamFortressViewport::SlotInput( int iSlot ) +{ + // If there's a menu up, give it the input + if( m_pCurrentMenu ) + return m_pCurrentMenu->SlotInput( iSlot ); + + return FALSE; +} + +// Direct Key Input +int TeamFortressViewport::KeyInput( int down, int keynum, const char *pszCurrentBinding ) +{ + // Enter gets out of Spectator Mode by bringing up the Team Menu + if( m_iUser1 && gEngfuncs.Con_IsVisible() == false ) + { + if( down && ( keynum == K_ENTER || keynum == K_KP_ENTER ) ) + ShowVGUIMenu( MENU_TEAM ); + } + + // Open Text Window? + if( m_pCurrentMenu && gEngfuncs.Con_IsVisible() == false ) + { + int iMenuID = m_pCurrentMenu->GetMenuID(); + + // Get number keys as Input for Team/Class menus + if( iMenuID == MENU_TEAM || iMenuID == MENU_CLASS ) + { + // Escape gets you out of Team/Class menus if the Cancel button is visible + if( keynum == K_ESCAPE ) + { + if( ( iMenuID == MENU_TEAM && g_iTeamNumber ) || ( iMenuID == MENU_CLASS && g_iPlayerClass ) ) + { + HideTopMenu(); + return 0; + } + } + + for( int i = '0'; i <= '9'; i++ ) + { + if( down && ( keynum == i ) ) + { + SlotInput( i - '0' ); + return 0; + } + } + } + + // Grab enter keys to close TextWindows + if( down && ( keynum == K_ENTER || keynum == K_KP_ENTER || keynum == K_SPACE || keynum == K_ESCAPE ) ) + { + if( iMenuID == MENU_MAPBRIEFING || iMenuID == MENU_INTRO || iMenuID == MENU_CLASSHELP ) + { + HideTopMenu(); + return 0; + } + } + + // Grab jump key on Team Menu as autoassign + if( pszCurrentBinding && down && !strcmp( pszCurrentBinding, "+jump" ) ) + { + if( iMenuID == MENU_TEAM ) + { + m_pTeamMenu->SlotInput( 5 ); + return 0; + } + } + + } + + // if we're in a command menu, try hit one of it's buttons + if( down && m_pCurrentCommandMenu ) + { + // Escape hides the command menu + if( keynum == K_ESCAPE ) + { + HideCommandMenu(); + return 0; + } + + // only trap the number keys + if( keynum >= '0' && keynum <= '9' ) + { + if( m_pCurrentCommandMenu->KeyInput( keynum ) ) + { + // a final command has been issued, so close the command menu + HideCommandMenu(); + } + + return 0; + } + } + + return 1; +} + +//================================================================ +// Message Handlers +int TeamFortressViewport::MsgFunc_ValClass( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + + for( int i = 0; i < 5; i++ ) + m_iValidClasses[i] = READ_SHORT(); + + // Force the menu to update + UpdateCommandMenu( m_StandardMenu ); + + return 1; +} + +int TeamFortressViewport::MsgFunc_TeamNames( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + + m_iNumberOfTeams = READ_BYTE(); + + for( int i = 0; i < m_iNumberOfTeams; i++ ) + { + int teamNum = i + 1; + + gHUD.m_TextMessage.LocaliseTextString( READ_STRING(), m_sTeamNames[teamNum], MAX_TEAMNAME_SIZE ); + + // Set the team name buttons + if( m_pTeamButtons[i] ) + m_pTeamButtons[i]->setText( m_sTeamNames[teamNum] ); + + // range check this value...m_pDisguiseButtons[5]; + if( teamNum < 5 ) + { + // Set the disguise buttons + if( m_pDisguiseButtons[teamNum] ) + m_pDisguiseButtons[teamNum]->setText( m_sTeamNames[teamNum] ); + } + } + + // Update the Team Menu + if( m_pTeamMenu ) + m_pTeamMenu->Update(); + + return 1; +} + +int TeamFortressViewport::MsgFunc_Feign( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + + m_iIsFeigning = READ_BYTE(); + + // Force the menu to update + UpdateCommandMenu( m_StandardMenu ); + + return 1; +} + +int TeamFortressViewport::MsgFunc_Detpack( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + + m_iIsSettingDetpack = READ_BYTE(); + + // Force the menu to update + UpdateCommandMenu( m_StandardMenu ); + + return 1; +} + +int TeamFortressViewport::MsgFunc_VGUIMenu( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + + int iMenu = READ_BYTE(); + + // Map briefing includes the name of the map (because it's sent down before the client knows what map it is) + if( iMenu == MENU_MAPBRIEFING ) + { + strncpy( m_sMapName, READ_STRING(), sizeof(m_sMapName) - 1 ); + m_sMapName[sizeof(m_sMapName) - 1] = '\0'; + } + + // Bring up the menu6 + ShowVGUIMenu( iMenu ); + + return 1; +} + +int TeamFortressViewport::MsgFunc_MOTD( const char *pszName, int iSize, void *pbuf ) +{ + if( m_iGotAllMOTD ) + m_szMOTD[0] = 0; + + BEGIN_READ( pbuf, iSize ); + + m_iGotAllMOTD = READ_BYTE(); + + int roomInArray = sizeof(m_szMOTD) - strlen( m_szMOTD ) - 1; + + strncat( m_szMOTD, READ_STRING(), roomInArray >= 0 ? roomInArray : 0 ); + m_szMOTD[sizeof(m_szMOTD) - 1] = '\0'; + + // don't show MOTD for HLTV spectators + if( m_iGotAllMOTD && !gEngfuncs.IsSpectateOnly() ) + { + ShowVGUIMenu( MENU_INTRO ); + } + + return 1; +} + +int TeamFortressViewport::MsgFunc_BuildSt( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + + m_iBuildState = READ_SHORT(); + + // Force the menu to update + UpdateCommandMenu( m_StandardMenu ); + + return 1; +} + +int TeamFortressViewport::MsgFunc_RandomPC( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + + m_iRandomPC = READ_BYTE(); + + return 1; +} + +int TeamFortressViewport::MsgFunc_ServerName( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + + strncpy( m_szServerName, READ_STRING(), sizeof(m_szServerName) ); + m_szServerName[sizeof(m_szServerName) - 1] = 0; + + return 1; +} + +int TeamFortressViewport::MsgFunc_ScoreInfo( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + short cl = READ_BYTE(); + short frags = READ_SHORT(); + short deaths = READ_SHORT(); + short playerclass = READ_SHORT(); + short teamnumber = READ_SHORT(); + + if( cl > 0 && cl <= MAX_PLAYERS ) + { + g_PlayerExtraInfo[cl].frags = frags; + g_PlayerExtraInfo[cl].deaths = deaths; + g_PlayerExtraInfo[cl].playerclass = playerclass; + g_PlayerExtraInfo[cl].teamnumber = teamnumber; + + //Dont go bellow 0! + if( g_PlayerExtraInfo[cl].teamnumber < 0 ) + g_PlayerExtraInfo[cl].teamnumber = 0; + + UpdateOnPlayerInfo(); + } + + return 1; +} + +// Message handler for TeamScore message +// accepts three values: +// string: team name +// short: teams kills +// short: teams deaths +// if this message is never received, then scores will simply be the combined totals of the players. +int TeamFortressViewport::MsgFunc_TeamScore( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + char *TeamName = READ_STRING(); + + int i; + // find the team matching the name + for( i = 1; i <= m_pScoreBoard->m_iNumTeams; i++ ) + { + if( !stricmp( TeamName, g_TeamInfo[i].name ) ) + break; + } + + if( i > m_pScoreBoard->m_iNumTeams ) + return 1; + + // use this new score data instead of combined player scoresw + g_TeamInfo[i].scores_overriden = TRUE; + g_TeamInfo[i].frags = READ_SHORT(); + g_TeamInfo[i].deaths = READ_SHORT(); + + return 1; +} + +// Message handler for TeamInfo message +// accepts two values: +// byte: client number +// string: client team name +int TeamFortressViewport::MsgFunc_TeamInfo( const char *pszName, int iSize, void *pbuf ) +{ + if( !m_pScoreBoard ) + return 1; + + BEGIN_READ( pbuf, iSize ); + short cl = READ_BYTE(); + + if( cl > 0 && cl <= MAX_PLAYERS ) + { + // set the players team + strncpy( g_PlayerExtraInfo[cl].teamname, READ_STRING(), MAX_TEAM_NAME - 1 ); + g_PlayerExtraInfo[cl].teamname[MAX_TEAM_NAME - 1] = '\0'; + } + + // rebuild the list of teams + m_pScoreBoard->RebuildTeams(); + + return 1; +} + +void TeamFortressViewport::DeathMsg( int killer, int victim ) +{ + m_pScoreBoard->DeathMsg( killer, victim ); +} + +int TeamFortressViewport::MsgFunc_Spectator( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + + short cl = READ_BYTE(); + if( cl > 0 && cl <= MAX_PLAYERS ) + { + g_IsSpectator[cl] = READ_BYTE(); + } + + return 1; +} + +int TeamFortressViewport::MsgFunc_AllowSpec( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + + m_iAllowSpectators = READ_BYTE(); + + // Force the menu to update + UpdateCommandMenu( m_StandardMenu ); + + // If the team menu is up, update it too + if( m_pTeamMenu ) + m_pTeamMenu->Update(); + + return 1; +} + +#if defined( _TFC ) +const Vector& GetTeamColor( int team_no ); +extern globalvars_t *gpGlobals; +#endif + +// used to reset the player's screen immediately +int TeamFortressViewport::MsgFunc_ResetFade( const char *pszName, int iSize, void *pbuf ) +{ +#if defined( _TFC ) + if ( !gpGlobals ) + return 0; + + screenfade_t sf; + gEngfuncs.pfnGetScreenFade( &sf ); + + sf.fader = 0; + sf.fadeg = 0; + sf.fadeb = 0; + sf.fadealpha = 0; + + sf.fadeEnd = 0.1; + sf.fadeReset = 0.0; + sf.fadeSpeed = 0.0; + + sf.fadeFlags = FFADE_IN; + + sf.fadeReset += gpGlobals->time; + sf.fadeEnd += sf.fadeReset; + + gEngfuncs.pfnSetScreenFade( &sf ); +#endif + + return 1; +} + +// used to fade a player's screen out/in when they're spectating someone who is teleported +int TeamFortressViewport::MsgFunc_SpecFade( const char *pszName, int iSize, void *pbuf ) +{ +#if defined( _TFC ) + BEGIN_READ( pbuf, iSize ); + + int iIndex = READ_BYTE(); + + // we're in first-person spectator mode (...not first-person in the PIP) + if ( g_iUser1 == OBS_IN_EYE ) + { + // this is the person we're watching + if ( g_iUser2 == iIndex ) + { + int iFade = READ_BYTE(); + int iTeam = READ_BYTE(); + float flTime = ( (float)READ_SHORT() / 100.0 ); + int iAlpha = READ_BYTE(); + + Vector team = GetTeamColor( iTeam ); + + screenfade_t sf; + gEngfuncs.pfnGetScreenFade( &sf ); + + sf.fader = team[0]; + sf.fadeg = team[1]; + sf.fadeb = team[2]; + sf.fadealpha = iAlpha; + + sf.fadeEnd = flTime; + sf.fadeReset = 0.0; + sf.fadeSpeed = 0.0; + + if ( iFade == BUILD_TELEPORTER_FADE_OUT ) + { + sf.fadeFlags = FFADE_OUT; + sf.fadeReset = flTime; + + if ( sf.fadeEnd ) + sf.fadeSpeed = -(float)sf.fadealpha / sf.fadeEnd; + + sf.fadeTotalEnd = sf.fadeEnd += gpGlobals->time; + sf.fadeReset += sf.fadeEnd; + } + else + { + sf.fadeFlags = FFADE_IN; + + if ( sf.fadeEnd ) + sf.fadeSpeed = (float)sf.fadealpha / sf.fadeEnd; + + sf.fadeReset += gpGlobals->time; + sf.fadeEnd += sf.fadeReset; + } + + gEngfuncs.pfnSetScreenFade( &sf ); + } + } +#endif + + return 1; +} diff --git a/cl_dll/vgui_TeamFortressViewport.h b/cl_dll/vgui_TeamFortressViewport.h new file mode 100644 index 00000000..39c6b26f --- /dev/null +++ b/cl_dll/vgui_TeamFortressViewport.h @@ -0,0 +1,1816 @@ +//========= Copyright (c) 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef TEAMFORTRESSVIEWPORT_H +#define TEAMFORTRESSVIEWPORT_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// custom scheme handling +#include "vgui_SchemeManager.h" + +#define TF_DEFS_ONLY +#ifdef _TFC +#include "../tfc/tf_defs.h" +#else +#define PC_LASTCLASS 10 +#define PC_UNDEFINED 0 +#define MENU_DEFAULT 1 +#define MENU_TEAM 2 +#define MENU_CLASS 3 +#define MENU_MAPBRIEFING 4 +#define MENU_INTRO 5 +#define MENU_CLASSHELP 6 +#define MENU_CLASSHELP2 7 +#define MENU_REPEATHELP 8 +#define MENU_SPECHELP 9 +#endif +using namespace vgui; + +class Cursor; +class ScorePanel; +class SpectatorPanel; +class CCommandMenu; +class CommandLabel; +class CommandButton; +class BuildButton; +class ClassButton; +class CMenuPanel; +class DragNDropPanel; +class CTransparentPanel; +class CClassMenuPanel; +class CTeamMenuPanel; +class TeamFortressViewport; + +char *GetVGUITGAName( const char *pszName ); +BitmapTGA *LoadTGAForRes( const char* pImageName ); +void ScaleColors( int &r, int &g, int &b, int a ); +extern const char *sTFClassSelection[]; +extern int sTFValidClassInts[]; +extern const char *sLocalisedClasses[]; +extern int iTeamColors[5][3]; +extern int iNumberOfTeamColors; +extern TeamFortressViewport *gViewPort; + + +// Command Menu positions +#define MAX_MENUS 80 +#define MAX_BUTTONS 100 + +#define BUTTON_SIZE_Y YRES(30) +#define CMENU_SIZE_X XRES(160) + +#define SUBMENU_SIZE_X (CMENU_SIZE_X / 8) +#define SUBMENU_SIZE_Y (BUTTON_SIZE_Y / 6) + +#define CMENU_TOP (BUTTON_SIZE_Y * 4) + +//#define MAX_TEAMNAME_SIZE 64 +#define MAX_BUTTON_SIZE 32 + +// Map Briefing Window +#define MAPBRIEF_INDENT 30 + +// Team Menu +#define TMENU_INDENT_X (30 * ((float)ScreenHeight / 640)) +#define TMENU_HEADER 100 +#define TMENU_SIZE_X (ScreenWidth - (TMENU_INDENT_X * 2)) +#define TMENU_SIZE_Y (TMENU_HEADER + BUTTON_SIZE_Y * 7) +#define TMENU_PLAYER_INDENT (((float)TMENU_SIZE_X / 3) * 2) +#define TMENU_INDENT_Y (((float)ScreenHeight - TMENU_SIZE_Y) / 2) + +// Class Menu +#define CLMENU_INDENT_X (30 * ((float)ScreenHeight / 640)) +#define CLMENU_HEADER 100 +#define CLMENU_SIZE_X (ScreenWidth - (CLMENU_INDENT_X * 2)) +#define CLMENU_SIZE_Y (CLMENU_HEADER + BUTTON_SIZE_Y * 11) +#define CLMENU_PLAYER_INDENT (((float)CLMENU_SIZE_X / 3) * 2) +#define CLMENU_INDENT_Y (((float)ScreenHeight - CLMENU_SIZE_Y) / 2) + +// Arrows +enum +{ + ARROW_UP, + ARROW_DOWN, + ARROW_LEFT, + ARROW_RIGHT, +}; + +//============================================================================== +// VIEWPORT PIECES +//============================================================ +// Wrapper for an Image Label without a background +class CImageLabel : public Label +{ +public: + BitmapTGA *m_pTGA; + + void LoadImage(const char * pImageName); + CImageLabel( const char* pImageName,int x,int y ); + CImageLabel( const char* pImageName,int x,int y,int wide,int tall ); + + virtual int getImageTall(); + virtual int getImageWide(); + + virtual void paintBackground() + { + // Do nothing, so the background's left transparent. + } +}; + +// Command Label +// Overridden label so we can darken it when submenus open +class CommandLabel : public Label +{ +private: + int m_iState; + +public: + CommandLabel( const char *text, int x, int y, int wide, int tall ) : Label( text, x, y, wide, tall ) + { + m_iState = false; + } + + void PushUp() + { + m_iState = false; + repaint(); + } + + void PushDown() + { + m_iState = true; + repaint(); + } +}; + +//============================================================ +// Command Buttons +class CommandButton : public Button +{ +private: + int m_iPlayerClass; + bool m_bFlat; + + // Submenus under this button + CCommandMenu *m_pSubMenu; + CCommandMenu *m_pParentMenu; + CommandLabel *m_pSubLabel; + + char m_sMainText[MAX_BUTTON_SIZE]; + char m_cBoundKey; + + SchemeHandle_t m_hTextScheme; + + void RecalculateText( void ); + +public: + bool m_bNoHighlight; + + CommandButton(const char* text,int x,int y,int wide,int tall, bool bNoHighlight, bool bFlat); + // Constructors + CommandButton( const char* text,int x,int y,int wide,int tall, bool bNoHighlight = false); + CommandButton( int iPlayerClass, const char* text,int x,int y,int wide,int tall, bool bFlat ); + + void Init( void ); + + // Menu Handling + void AddSubMenu( CCommandMenu *pNewMenu ); + void AddSubLabel( CommandLabel *pSubLabel ) + { + m_pSubLabel = pSubLabel; + } + + virtual int IsNotValid( void ) + { + return false; + } + + void UpdateSubMenus( int iAdjustment ); + int GetPlayerClass() { return m_iPlayerClass; }; + CCommandMenu *GetSubMenu() { return m_pSubMenu; }; + + CCommandMenu *getParentMenu( void ); + void setParentMenu( CCommandMenu *pParentMenu ); + + // Overloaded vgui functions + virtual void paint(); + virtual void setText( const char *text ); + virtual void paintBackground(); + + void cursorEntered( void ); + void cursorExited( void ); + + void setBoundKey( char boundKey ); + char getBoundKey( void ); +}; + +class ColorButton : public CommandButton +{ +private: + + Color *ArmedColor; + Color *UnArmedColor; + + Color *ArmedBorderColor; + Color *UnArmedBorderColor; + +public: + ColorButton( const char *text, int x, int y, int wide, int tall, bool bNoHighlight, bool bFlat ) : + CommandButton( text, x, y, wide, tall, bNoHighlight, bFlat ) + { + ArmedColor = NULL; + UnArmedColor = NULL; + ArmedBorderColor = NULL; + UnArmedBorderColor = NULL; + } + + virtual void paintBackground() + { + int r, g, b, a; + Color bgcolor; + + if( isArmed() ) + { + // Highlight background + /* getBgColor( bgcolor ); + bgcolor.getColor( r, g, b, a ); + drawSetColor( r, g, b, a ); + drawFilledRect( 0, 0, _size[0], _size[1] );*/ + + if( ArmedBorderColor ) + { + ArmedBorderColor->getColor( r, g, b, a ); + drawSetColor( r, g, b, a ); + drawOutlinedRect( 0, 0, _size[0], _size[1]); + } + } + else + { + if( UnArmedBorderColor ) + { + UnArmedBorderColor->getColor( r, g, b, a ); + drawSetColor( r, g, b, a ); + drawOutlinedRect( 0, 0, _size[0], _size[1]); + } + } + } + + void paint() + { + int r, g, b, a; + if( isArmed() ) + { + if( ArmedColor ) + { + ArmedColor->getColor( r, g, b, a ); + setFgColor( r, g, b, a ); + } + else + setFgColor( Scheme::sc_secondary2 ); + } + else + { + if( UnArmedColor ) + { + UnArmedColor->getColor( r, g, b, a ); + setFgColor( r, g, b, a ); + } + else + setFgColor( Scheme::sc_primary1 ); + } + + Button::paint(); + } + + void setArmedColor( int r, int g, int b, int a ) + { + ArmedColor = new Color( r, g, b, a ); + } + + void setUnArmedColor( int r, int g, int b, int a ) + { + UnArmedColor = new Color( r, g, b, a ); + } + + void setArmedBorderColor( int r, int g, int b, int a ) + { + ArmedBorderColor = new Color( r, g, b, a ); + } + + void setUnArmedBorderColor( int r, int g, int b, int a ) + { + UnArmedBorderColor = new Color( r, g, b, a ); + } +}; + +class SpectButton : public CommandButton +{ +private: + +public: + SpectButton( int iPlayerClass, const char *text, int x, int y, int wide, int tall ) : + CommandButton( text, x, y, wide, tall, false ) + { + Init(); + + setText( text ); + } + + virtual void paintBackground() + { + if( isArmed() ) + { + drawSetColor( 143,143, 54, 125 ); + drawFilledRect( 5, 0, _size[0] - 5, _size[1] ); + } + } + + virtual void paint() + { + + if( isArmed() ) + { + setFgColor( 194, 202, 54, 0 ); + } + else + { + setFgColor( 143, 143, 54, 15 ); + } + + Button::paint(); + } +}; + +//============================================================ +// Command Menus +class CCommandMenu : public Panel +{ +private: + CCommandMenu *m_pParentMenu; + int m_iXOffset; + int m_iYOffset; + + // Buttons in this menu + CommandButton *m_aButtons[ MAX_BUTTONS ]; + int m_iButtons; + + // opens menu from top to bottom (0 = default), or from bottom to top (1)? + int m_iDirection; +public: + CCommandMenu( CCommandMenu *pParentMenu, int x, int y, int wide, int tall ) : Panel( x, y, wide, tall ) + { + m_pParentMenu = pParentMenu; + m_iXOffset = x; + m_iYOffset = y; + m_iButtons = 0; + m_iDirection = 0; + } + + CCommandMenu( CCommandMenu *pParentMenu, int direction, int x, int y, int wide, int tall ) : Panel( x, y, wide, tall ) + { + m_pParentMenu = pParentMenu; + m_iXOffset = x; + m_iYOffset = y; + m_iButtons = 0; + m_iDirection = direction; + } + + float m_flButtonSizeY; + int m_iSpectCmdMenu; + void AddButton( CommandButton *pButton ); + bool RecalculateVisibles( int iNewYPos, bool bHideAll ); + void RecalculatePositions( int iYOffset ); + void MakeVisible( CCommandMenu *pChildMenu ); + + CCommandMenu *GetParentMenu() { return m_pParentMenu; }; + int GetXOffset() { return m_iXOffset; }; + int GetYOffset() { return m_iYOffset; }; + int GetDirection() { return m_iDirection; }; + int GetNumButtons() { return m_iButtons; }; + CommandButton *FindButtonWithSubmenu( CCommandMenu *pSubMenu ); + + void ClearButtonsOfArmedState( void ); + + void RemoveAllButtons(void); + + + bool KeyInput( int keyNum ); + + virtual void paintBackground(); +}; + +//============================================================================== +// Command menu root button (drop down box style) + +class DropDownButton : public ColorButton +{ +private: + CImageLabel *m_pOpenButton; + +public: + + DropDownButton( const char* text,int x,int y,int wide,int tall, bool bNoHighlight, bool bFlat ) : + ColorButton( text, x, y, wide, tall, bNoHighlight, bFlat ) + { + // Put a > to show it's a submenu + m_pOpenButton = new CImageLabel( "arrowup", XRES( CMENU_SIZE_X-2 ) , YRES( BUTTON_SIZE_Y-2 ) ); + m_pOpenButton->setParent(this); + + int textwide, texttall; + getSize( textwide, texttall); + + // Reposition + m_pOpenButton->setPos( textwide-(m_pOpenButton->getImageWide()+6), -2 /*(tall - m_pOpenButton->getImageTall()*2) / 2*/ ); + m_pOpenButton->setVisible(true); + + } + + virtual void setVisible(bool state) + { + m_pOpenButton->setVisible(state); + ColorButton::setVisible(state); + } + + +}; + +//============================================================================== +// Button with image instead of text + +class CImageButton : public ColorButton +{ +private: + CImageLabel *m_pOpenButton; + +public: + + CImageButton( const char* text,int x,int y,int wide,int tall, bool bNoHighlight, bool bFlat ) : + ColorButton( " ", x, y, wide, tall, bNoHighlight, bFlat ) + { + m_pOpenButton = new CImageLabel( text,1,1,wide-2 , tall-2 ); + m_pOpenButton->setParent(this); + + // Reposition + // m_pOpenButton->setPos( x+1,y+1 ); + // m_pOpenButton->setSize(wide-2,tall-2); + + m_pOpenButton->setVisible(true); + } + + virtual void setVisible(bool state) + { + m_pOpenButton->setVisible(state); + ColorButton::setVisible(state); + } + + +}; + +//============================================================================== +class TeamFortressViewport : public Panel +{ +private: + vgui::Cursor* _cursorNone; + vgui::Cursor* _cursorArrow; + + int m_iInitialized; + + CCommandMenu *m_pCommandMenus[MAX_MENUS]; + CCommandMenu *m_pCurrentCommandMenu; + float m_flMenuOpenTime; + float m_flScoreBoardLastUpdated; + float m_flSpectatorPanelLastUpdated; + int m_iNumMenus; + int m_iCurrentTeamNumber; + int m_iCurrentPlayerClass; + int m_iUser1; + int m_iUser2; + int m_iUser3; + + // VGUI Menus + void CreateTeamMenu( void ); + CMenuPanel* ShowTeamMenu( void ); + void CreateClassMenu( void ); + CMenuPanel* ShowClassMenu( void ); + void CreateSpectatorMenu( void ); + + // Scheme handler + CSchemeManager m_SchemeManager; + + // MOTD + int m_iGotAllMOTD; + char m_szMOTD[ MAX_MOTD_LENGTH ]; + + // Command Menu Team buttons + CommandButton *m_pTeamButtons[6]; + CommandButton *m_pDisguiseButtons[5]; + BuildButton *m_pBuildButtons[3]; + BuildButton *m_pBuildActiveButtons[3]; + + int m_iAllowSpectators; + + // Data for specific sections of the Command Menu + int m_iValidClasses[5]; + int m_iIsFeigning; + int m_iIsSettingDetpack; + int m_iNumberOfTeams; + int m_iBuildState; + int m_iRandomPC; + char m_sTeamNames[5][MAX_TEAMNAME_SIZE]; + + // Localisation strings + char m_sDetpackStrings[3][MAX_BUTTON_SIZE]; + + char m_sMapName[64]; + + // helper function to update the player menu entries + void UpdatePlayerMenu(int menuIndex); + +public: + TeamFortressViewport(int x,int y,int wide,int tall); + void Initialize( void ); + + int CreateCommandMenu( const char * menuFile, int direction, int yOffset, bool flatDesign, float flButtonSizeX, float flButtonSizeY, int xOffset ); + void CreateScoreBoard( void ); + CommandButton * CreateCustomButton( char *pButtonText, char * pButtonName, int iYOffset ); + CCommandMenu * CreateDisguiseSubmenu( CommandButton *pButton, CCommandMenu *pParentMenu, const char *commandText, int iYOffset, int iXOffset = 0 ); + + void UpdateCursorState( void ); + void UpdateCommandMenu(int menuIndex); + void UpdateOnPlayerInfo( void ); + void UpdateHighlights( void ); + void UpdateSpectatorPanel( void ); + + int KeyInput( int down, int keynum, const char *pszCurrentBinding ); + void InputPlayerSpecial( void ); + void GetAllPlayersInfo( void ); + void DeathMsg( int killer, int victim ); + + void ShowCommandMenu(int menuIndex); + void InputSignalHideCommandMenu( void ); + void HideCommandMenu( void ); + void SetCurrentCommandMenu( CCommandMenu *pNewMenu ); + void SetCurrentMenu( CMenuPanel *pMenu ); + + void ShowScoreBoard( void ); + void HideScoreBoard( void ); + bool IsScoreBoardVisible( void ); + + bool AllowedToPrintText( void ); + + void ShowVGUIMenu( int iMenu ); + void HideVGUIMenu( void ); + void HideTopMenu( void ); + + CMenuPanel* CreateTextWindow( int iTextToShow ); + + CCommandMenu *CreateSubMenu( CommandButton *pButton, CCommandMenu *pParentMenu, int iYOffset, int iXOffset = 0 ); + + // Data Handlers + int GetValidClasses(int iTeam) { return m_iValidClasses[iTeam]; }; + int GetNumberOfTeams() { return m_iNumberOfTeams; }; + int GetIsFeigning() { return m_iIsFeigning; }; + int GetIsSettingDetpack() { return m_iIsSettingDetpack; }; + int GetBuildState() { return m_iBuildState; }; + int IsRandomPC() { return m_iRandomPC; }; + char *GetTeamName( int iTeam ) { return m_sTeamNames[iTeam]; }; + int GetAllowSpectators() { return m_iAllowSpectators; }; + + // Message Handlers + int MsgFunc_ValClass(const char *pszName, int iSize, void *pbuf ); + int MsgFunc_TeamNames(const char *pszName, int iSize, void *pbuf ); + int MsgFunc_Feign(const char *pszName, int iSize, void *pbuf ); + int MsgFunc_Detpack(const char *pszName, int iSize, void *pbuf ); + int MsgFunc_VGUIMenu(const char *pszName, int iSize, void *pbuf ); + int MsgFunc_MOTD( const char *pszName, int iSize, void *pbuf ); + int MsgFunc_BuildSt( const char *pszName, int iSize, void *pbuf ); + int MsgFunc_RandomPC( const char *pszName, int iSize, void *pbuf ); + int MsgFunc_ServerName( const char *pszName, int iSize, void *pbuf ); + int MsgFunc_ScoreInfo( const char *pszName, int iSize, void *pbuf ); + int MsgFunc_TeamScore( const char *pszName, int iSize, void *pbuf ); + int MsgFunc_TeamInfo( const char *pszName, int iSize, void *pbuf ); + int MsgFunc_Spectator( const char *pszName, int iSize, void *pbuf ); + int MsgFunc_AllowSpec( const char *pszName, int iSize, void *pbuf ); + int MsgFunc_SpecFade( const char *pszName, int iSize, void *pbuf ); + int MsgFunc_ResetFade( const char *pszName, int iSize, void *pbuf ); + + // Input + bool SlotInput( int iSlot ); + + virtual void paintBackground(); + + CSchemeManager *GetSchemeManager( void ) { return &m_SchemeManager; } + ScorePanel *GetScoreBoard( void ) { return m_pScoreBoard; } + + void *operator new( size_t stAllocateBlock ); + +public: + // VGUI Menus + CMenuPanel *m_pCurrentMenu; + CTeamMenuPanel *m_pTeamMenu; + int m_StandardMenu; // indexs in m_pCommandMenus + int m_SpectatorOptionsMenu; + int m_SpectatorCameraMenu; + int m_PlayerMenu; // a list of current player + CClassMenuPanel *m_pClassMenu; + ScorePanel *m_pScoreBoard; + SpectatorPanel *m_pSpectatorPanel; + char m_szServerName[ MAX_SERVERNAME_LENGTH ]; +}; + +//============================================================ +// Command Menu Button Handlers +#define MAX_COMMAND_SIZE 256 + +class CMenuHandler_StringCommand : public ActionSignal +{ +protected: + char m_pszCommand[MAX_COMMAND_SIZE]; + int m_iCloseVGUIMenu; +public: + CMenuHandler_StringCommand( const char *pszCommand ) + { + strncpy( m_pszCommand, pszCommand, MAX_COMMAND_SIZE - 1 ); + m_pszCommand[MAX_COMMAND_SIZE - 1] = '\0'; + m_iCloseVGUIMenu = false; + } + + CMenuHandler_StringCommand( const char *pszCommand, int iClose ) + { + strncpy( m_pszCommand, pszCommand, MAX_COMMAND_SIZE - 1 ); + m_pszCommand[MAX_COMMAND_SIZE - 1] = '\0'; + m_iCloseVGUIMenu = true; + } + + virtual void actionPerformed(Panel *panel) + { + gEngfuncs.pfnClientCmd( m_pszCommand ); + + if( m_iCloseVGUIMenu ) + gViewPort->HideTopMenu(); + else + gViewPort->HideCommandMenu(); + } +}; + +// This works the same as CMenuHandler_StringCommand, except it watches the string command +// for specific commands, and modifies client vars based upon them. +class CMenuHandler_StringCommandWatch : public CMenuHandler_StringCommand +{ +private: +public: + CMenuHandler_StringCommandWatch( const char *pszCommand ) : CMenuHandler_StringCommand( pszCommand ) + { + } + + CMenuHandler_StringCommandWatch( const char *pszCommand, int iClose ) : CMenuHandler_StringCommand( pszCommand, iClose ) + { + } + + virtual void actionPerformed( Panel *panel ) + { + CMenuHandler_StringCommand::actionPerformed( panel ); + + // Try to guess the player's new team (it'll be corrected if it's wrong) + if( !strcmp( m_pszCommand, "jointeam 1" ) ) + g_iTeamNumber = 1; + else if( !strcmp( m_pszCommand, "jointeam 2" ) ) + g_iTeamNumber = 2; + else if( !strcmp( m_pszCommand, "jointeam 3" ) ) + g_iTeamNumber = 3; + else if( !strcmp( m_pszCommand, "jointeam 4" ) ) + g_iTeamNumber = 4; + } +}; + +// Used instead of CMenuHandler_StringCommand for Class Selection buttons. +// Checks the state of hud_classautokill and kills the player if set +class CMenuHandler_StringCommandClassSelect : public CMenuHandler_StringCommand +{ +private: +public: + CMenuHandler_StringCommandClassSelect( char *pszCommand ) : CMenuHandler_StringCommand( pszCommand ) + { + } + + CMenuHandler_StringCommandClassSelect( char *pszCommand, int iClose ) : CMenuHandler_StringCommand( pszCommand, iClose ) + { + } + + virtual void actionPerformed( Panel *panel ); +}; + +class CMenuHandler_PopupSubMenuInput : public InputSignal +{ +private: + CCommandMenu *m_pSubMenu; + Button *m_pButton; +public: + CMenuHandler_PopupSubMenuInput( Button *pButton, CCommandMenu *pSubMenu ) + { + m_pSubMenu = pSubMenu; + m_pButton = pButton; + } + + virtual void cursorMoved( int x, int y, Panel *panel ) + { + // gViewPort->SetCurrentCommandMenu( m_pSubMenu ); + } + + virtual void cursorEntered( Panel *panel ) + { + gViewPort->SetCurrentCommandMenu( m_pSubMenu ); + + if( m_pButton ) + m_pButton->setArmed( true ); + }; + virtual void cursorExited(Panel* Panel) {}; + virtual void mousePressed(MouseCode code,Panel* panel) {}; + virtual void mouseDoublePressed(MouseCode code,Panel* panel) {}; + virtual void mouseReleased(MouseCode code,Panel* panel) {}; + virtual void mouseWheeled(int delta,Panel* panel) {}; + virtual void keyPressed(KeyCode code,Panel* panel) {}; + virtual void keyTyped(KeyCode code,Panel* panel) {}; + virtual void keyReleased(KeyCode code,Panel* panel) {}; + virtual void keyFocusTicked(Panel* panel) {}; +}; + +class CMenuHandler_LabelInput : public InputSignal +{ +private: + ActionSignal *m_pActionSignal; +public: + CMenuHandler_LabelInput( ActionSignal *pSignal ) + { + m_pActionSignal = pSignal; + } + + virtual void mousePressed( MouseCode code, Panel *panel ) + { + m_pActionSignal->actionPerformed( panel ); + } + + virtual void mouseReleased( MouseCode code, Panel *panel ) {}; + virtual void cursorEntered( Panel *panel ) {}; + virtual void cursorExited( Panel *Panel ) {}; + virtual void cursorMoved( int x, int y, Panel *panel ) {}; + virtual void mouseDoublePressed( MouseCode code, Panel *panel ) {}; + virtual void mouseWheeled( int delta, Panel *panel ) {}; + virtual void keyPressed( KeyCode code, Panel *panel ) {}; + virtual void keyTyped( KeyCode code, Panel *panel ) {}; + virtual void keyReleased( KeyCode code, Panel *panel ) {}; + virtual void keyFocusTicked( Panel *panel ) {}; +}; + +#define HIDE_TEXTWINDOW 0 +#define SHOW_MAPBRIEFING 1 +#define SHOW_CLASSDESC 2 +#define SHOW_MOTD 3 +#define SHOW_SPECHELP 4 + +class CMenuHandler_TextWindow : public ActionSignal +{ +private: + int m_iState; + +public: + CMenuHandler_TextWindow( int iState ) + { + m_iState = iState; + } + + virtual void actionPerformed( Panel *panel ) + { + if( m_iState == HIDE_TEXTWINDOW ) + { + gViewPort->HideTopMenu(); + } + else + { + gViewPort->HideCommandMenu(); + gViewPort->ShowVGUIMenu( m_iState ); + } + } +}; + +class CMenuHandler_ToggleCvar : public ActionSignal +{ +private: + struct cvar_s *m_cvar; + +public: + CMenuHandler_ToggleCvar( char *cvarname ) + { + m_cvar = gEngfuncs.pfnGetCvarPointer( cvarname ); + } + + virtual void actionPerformed( Panel *panel ) + { + if( m_cvar->value ) + m_cvar->value = 0.0f; + else + m_cvar->value = 1.0f; + + // hide the menu + gViewPort->HideCommandMenu(); + + gViewPort->UpdateSpectatorPanel(); + } +}; + + + +class CMenuHandler_SpectateFollow : public ActionSignal +{ +protected: + char m_szplayer[MAX_COMMAND_SIZE]; +public: + CMenuHandler_SpectateFollow( char *player ) + { + strncpy( m_szplayer, player, MAX_COMMAND_SIZE); + m_szplayer[MAX_COMMAND_SIZE-1] = '\0'; + } + + virtual void actionPerformed(Panel* panel) + { + gHUD.m_Spectator.FindPlayer(m_szplayer); + gViewPort->HideCommandMenu(); + } +}; + + + +class CDragNDropHandler : public InputSignal +{ +private: + DragNDropPanel *m_pPanel; + bool m_bDragging; + int m_iaDragOrgPos[2]; + int m_iaDragStart[2]; + +public: + CDragNDropHandler( DragNDropPanel *pPanel ) + { + m_pPanel = pPanel; + m_bDragging = false; + } + + void cursorMoved( int x, int y, Panel *panel ); + void mousePressed( MouseCode code, Panel *panel ); + void mouseReleased( MouseCode code, Panel *panel ); + + void mouseDoublePressed( MouseCode code, Panel *panel ) {}; + void cursorEntered( Panel *panel ) {}; + void cursorExited( Panel *panel ) {}; + void mouseWheeled( int delta, Panel *panel ) {}; + void keyPressed( KeyCode code, Panel *panel ) {}; + void keyTyped( KeyCode code, Panel *panel ) {}; + void keyReleased( KeyCode code, Panel *panel ) {}; + void keyFocusTicked( Panel *panel ) {}; +}; + +class CHandler_MenuButtonOver : public InputSignal +{ +private: + int m_iButton; + CMenuPanel *m_pMenuPanel; +public: + CHandler_MenuButtonOver( CMenuPanel *pPanel, int iButton ) + { + m_iButton = iButton; + m_pMenuPanel = pPanel; + } + + void cursorEntered( Panel *panel ); + + void cursorMoved( int x, int y, Panel *panel ) {}; + void mousePressed( MouseCode code, Panel *panel ) {}; + void mouseReleased( MouseCode code, Panel *panel ) {}; + void mouseDoublePressed( MouseCode code, Panel *panel ) {}; + void cursorExited( Panel *panel) {}; + void mouseWheeled( int delta, Panel *panel ) {}; + void keyPressed( KeyCode code, Panel *panel ) {}; + void keyTyped( KeyCode code, Panel *panel ) {}; + void keyReleased( KeyCode code, Panel *panel ) {}; + void keyFocusTicked( Panel *panel ) {}; +}; + +class CHandler_ButtonHighlight : public InputSignal +{ +private: + Button *m_pButton; +public: + CHandler_ButtonHighlight( Button *pButton ) + { + m_pButton = pButton; + } + + virtual void cursorEntered( Panel *panel ) + { + m_pButton->setArmed( true ); + }; + + virtual void cursorExited( Panel *Panel ) + { + m_pButton->setArmed( false ); + }; + + virtual void mousePressed( MouseCode code, Panel *panel ) {}; + virtual void mouseReleased( MouseCode code, Panel *panel ) {}; + virtual void cursorMoved( int x, int y, Panel *panel ) {}; + virtual void mouseDoublePressed( MouseCode code, Panel *panel ) {}; + virtual void mouseWheeled( int delta, Panel *panel ) {}; + virtual void keyPressed( KeyCode code, Panel *panel ) {}; + virtual void keyTyped( KeyCode code, Panel *panel ) {}; + virtual void keyReleased( KeyCode code, Panel *panel ) {}; + virtual void keyFocusTicked( Panel *panel ) {}; +}; + +//----------------------------------------------------------------------------- +// Purpose: Special handler for highlighting of command menu buttons +//----------------------------------------------------------------------------- +class CHandler_CommandButtonHighlight : public CHandler_ButtonHighlight +{ +private: + CommandButton *m_pCommandButton; +public: + CHandler_CommandButtonHighlight( CommandButton *pButton ) : CHandler_ButtonHighlight( pButton ) + { + m_pCommandButton = pButton; + } + + virtual void cursorEntered( Panel *panel ) + { + m_pCommandButton->cursorEntered(); + } + + virtual void cursorExited( Panel *panel ) + { + m_pCommandButton->cursorExited(); + } +}; + + +//================================================================ +// Overidden Command Buttons for special visibilities +class ClassButton : public CommandButton +{ +protected: + int m_iPlayerClass; + +public: + ClassButton( int iClass, const char *text, int x, int y, int wide, int tall, bool bNoHighlight ) : CommandButton( text, x, y, wide, tall, bNoHighlight ) + { + m_iPlayerClass = iClass; + } + + virtual int IsNotValid(); +}; + +class TeamButton : public CommandButton +{ +private: + int m_iTeamNumber; +public: + TeamButton( int iTeam, const char *text, int x, int y, int wide, int tall ) : CommandButton( text, x, y, wide, tall ) + { + m_iTeamNumber = iTeam; + } + + virtual int IsNotValid() + { + int iTeams = gViewPort->GetNumberOfTeams(); + + // Never valid if there's only 1 team + if( iTeams == 1 ) + return true; + + // Auto Team's always visible + if( m_iTeamNumber == 5 ) + return false; + + if( iTeams >= m_iTeamNumber && m_iTeamNumber != g_iTeamNumber ) + return false; + + return true; + } +}; + +class FeignButton : public CommandButton +{ +private: + int m_iFeignState; +public: + FeignButton( int iState, const char *text, int x, int y, int wide, int tall ) : CommandButton( text, x, y, wide, tall ) + { + m_iFeignState = iState; + } + + virtual int IsNotValid() + { + // Only visible for spies +#ifdef _TFC + if( g_iPlayerClass != PC_SPY ) + return true; +#endif + + if( m_iFeignState == gViewPort->GetIsFeigning() ) + return false; + + return true; + } +}; + +class SpectateButton : public CommandButton +{ +public: + SpectateButton( const char *text, int x, int y, int wide, int tall, bool bNoHighlight ) : CommandButton( text, x, y, wide, tall, bNoHighlight ) + { + } + + virtual int IsNotValid() + { + // Only visible if the server allows it + if( gViewPort->GetAllowSpectators() != 0 ) + return false; + + return true; + } +}; + +#define DISGUISE_TEAM1 (1<<0) +#define DISGUISE_TEAM2 (1<<1) +#define DISGUISE_TEAM3 (1<<2) +#define DISGUISE_TEAM4 (1<<3) + +class DisguiseButton : public CommandButton +{ +private: + int m_iValidTeamsBits; + int m_iThisTeam; +public: + DisguiseButton( int iValidTeamNumsBits, const char *text, int x, int y, int wide, int tall ) : CommandButton( text, x, y, wide, tall, false ) + { + m_iValidTeamsBits = iValidTeamNumsBits; + } + + virtual int IsNotValid() + { +#ifdef _TFC + // Only visible for spies + if( g_iPlayerClass != PC_SPY ) + return true; +#endif + + // if it's not tied to a specific team, then always show (for spies) + if( !m_iValidTeamsBits ) + return false; + + // if we're tied to a team make sure we can change to that team + int iTmp = 1 << ( gViewPort->GetNumberOfTeams() - 1 ); + if( m_iValidTeamsBits & iTmp ) + return false; + + return true; + } +}; + +class DetpackButton : public CommandButton +{ +private: + int m_iDetpackState; +public: + DetpackButton( int iState, const char *text, int x, int y, int wide, int tall ) : CommandButton( text, x, y, wide, tall ) + { + m_iDetpackState = iState; + } + + virtual int IsNotValid() + { +#ifdef _TFC + // Only visible for demomen + if( g_iPlayerClass != PC_DEMOMAN ) + return true; +#endif + + if( m_iDetpackState == gViewPort->GetIsSettingDetpack() ) + return false; + + return true; + } +}; + +extern int iBuildingCosts[]; +#define BUILDSTATE_HASBUILDING (1<<0) // Data is building ID (1 = Dispenser, 2 = Sentry, 3 = Entry Teleporter, 4 = Exit Teleporter) +#define BUILDSTATE_BUILDING (1<<1) +#define BUILDSTATE_BASE (1<<2) +#define BUILDSTATE_CANBUILD (1<<3) // Data is building ID (1 = Dispenser, 2 = Sentry, 3 = Entry Teleporter, 4 = Exit Teleporter) + +class BuildButton : public CommandButton +{ +private: + int m_iBuildState; + int m_iBuildData; + +public: + enum Buildings + { + DISPENSER = 0, + SENTRYGUN = 1, + ENTRY_TELEPORTER = 2, + EXIT_TELEPORTER = 3 + }; + + BuildButton( int iState, int iData, const char *text, int x, int y, int wide, int tall ) : CommandButton( text, x, y, wide, tall ) + { + m_iBuildState = iState; + m_iBuildData = iData; + } + + virtual int IsNotValid() + { +#ifdef _TFC + // Only visible for engineers + if( g_iPlayerClass != PC_ENGINEER ) + return true; + + // If this isn't set, it's only active when they're not building + if( m_iBuildState & BUILDSTATE_BUILDING ) + { + // Make sure the player's building + if( !( gViewPort->GetBuildState() & BS_BUILDING ) ) + return true; + } + else + { + // Make sure the player's not building + if( gViewPort->GetBuildState() & BS_BUILDING ) + return true; + } + + if( m_iBuildState & BUILDSTATE_BASE ) + { + // Only appear if we've got enough metal to build something, or something already built + if ( gViewPort->GetBuildState() & (BS_HAS_SENTRYGUN | BS_HAS_DISPENSER | BS_CANB_SENTRYGUN | BS_CANB_DISPENSER | BS_HAS_ENTRY_TELEPORTER | BS_HAS_EXIT_TELEPORTER | BS_CANB_ENTRY_TELEPORTER | BS_CANB_EXIT_TELEPORTER) ) + return false; + + return true; + } + + // Must have a building + if( m_iBuildState & BUILDSTATE_HASBUILDING ) + { + if( m_iBuildData == BuildButton::DISPENSER && !( gViewPort->GetBuildState() & BS_HAS_DISPENSER ) ) + return true; + + if( m_iBuildData == BuildButton::SENTRYGUN && !( gViewPort->GetBuildState() & BS_HAS_SENTRYGUN ) ) + return true; + if ( m_iBuildData == BuildButton::ENTRY_TELEPORTER && !(gViewPort->GetBuildState() & BS_HAS_ENTRY_TELEPORTER) ) + return true; + if ( m_iBuildData == BuildButton::EXIT_TELEPORTER && !(gViewPort->GetBuildState() & BS_HAS_EXIT_TELEPORTER) ) + return true; + } + + // Can build something + if( m_iBuildState & BUILDSTATE_CANBUILD ) + { + // Make sure they've got the ammo and don't have one already + if( m_iBuildData == BuildButton::DISPENSER && ( gViewPort->GetBuildState() & BS_CANB_DISPENSER ) ) + return false; + if( m_iBuildData == BuildButton::SENTRYGUN && ( gViewPort->GetBuildState() & BS_CANB_SENTRYGUN ) ) + return false; + if ( m_iBuildData == BuildButton::ENTRY_TELEPORTER && (gViewPort->GetBuildState() & BS_CANB_ENTRY_TELEPORTER) ) + return false; + if ( m_iBuildData == BuildButton::EXIT_TELEPORTER && (gViewPort->GetBuildState() & BS_CANB_EXIT_TELEPORTER) ) + return false; + + return true; + } +#endif + return false; + } +}; + +#define MAX_MAPNAME 256 + +class MapButton : public CommandButton +{ +private: + char m_szMapName[MAX_MAPNAME]; + +public: + MapButton( const char *pMapName, const char *text, int x, int y, int wide, int tall ) : CommandButton( text, x, y, wide, tall ) + { + sprintf( m_szMapName, "maps/%s.bsp", pMapName ); + } + + virtual int IsNotValid() + { + const char *level = gEngfuncs.pfnGetLevelName(); + if( !level ) + return true; + + // Does it match the current map name? + if( strcmp( m_szMapName, level ) ) + return true; + + return false; + } +}; + +//----------------------------------------------------------------------------- +// Purpose: CommandButton which is only displayed if the player is on team X +//----------------------------------------------------------------------------- +class TeamOnlyCommandButton : public CommandButton +{ +private: + int m_iTeamNum; + +public: + TeamOnlyCommandButton( int iTeamNum, const char *text, int x, int y, int wide, int tall, bool flat ) : + CommandButton( text, x, y, wide, tall, false, flat ), m_iTeamNum( iTeamNum ) {} + + virtual int IsNotValid() + { + if( g_iTeamNumber != m_iTeamNum ) + return true; + + return CommandButton::IsNotValid(); + } +}; + +//----------------------------------------------------------------------------- +// Purpose: CommandButton which is only displayed if the player is on team X +//----------------------------------------------------------------------------- +class ToggleCommandButton : public CommandButton, public InputSignal +{ +private: + struct cvar_s *m_cvar; + CImageLabel *pLabelOn; + CImageLabel *pLabelOff; + +public: + ToggleCommandButton( const char *cvarname, const char *text, int x, int y, int wide, int tall, bool flat ) : + CommandButton( text, x, y, wide, tall, false, flat ) + { + m_cvar = gEngfuncs.pfnGetCvarPointer( cvarname ); + + // Put a > to show it's a submenu + pLabelOn = new CImageLabel( "checked", 0, 0 ); + pLabelOn->setParent(this); + pLabelOn->addInputSignal(this); + + pLabelOff = new CImageLabel( "unchecked", 0, 0 ); + pLabelOff->setParent(this); + pLabelOff->setEnabled(true); + pLabelOff->addInputSignal(this); + + int textwide, texttall; + getTextSize( textwide, texttall ); + + // Reposition + pLabelOn->setPos( textwide, ( tall - pLabelOn->getTall() ) / 2 ); + + pLabelOff->setPos( textwide, ( tall - pLabelOff->getTall() ) / 2 ); + + // Set text color to orange + setFgColor( Scheme::sc_primary1 ); + } + + virtual void cursorEntered( Panel *panel ) + { + CommandButton::cursorEntered(); + } + + virtual void cursorExited( Panel *panel ) + { + CommandButton::cursorExited(); + } + + virtual void mousePressed( MouseCode code, Panel *panel ) + { + doClick(); + }; + + virtual void cursorMoved( int x, int y, Panel *panel ) {}; + + virtual void mouseDoublePressed( MouseCode code, Panel *panel) {}; + virtual void mouseReleased( MouseCode code, Panel *panel ) {}; + virtual void mouseWheeled( int delta, Panel *panel ) {}; + virtual void keyPressed( KeyCode code, Panel *panel ) {}; + virtual void keyTyped( KeyCode code, Panel *panel ) {}; + virtual void keyReleased( KeyCode code, Panel *panel ) {}; + virtual void keyFocusTicked( Panel *panel) {}; + + virtual void paint( void ) + { + if( !m_cvar ) + { + pLabelOff->setVisible( false ); + pLabelOn->setVisible( false ); + } + else if( m_cvar->value ) + { + pLabelOff->setVisible( false ); + pLabelOn->setVisible( true ); + } + else + { + pLabelOff->setVisible( true ); + pLabelOn->setVisible( false ); + } + + CommandButton::paint(); + } +}; +class SpectToggleButton : public CommandButton, public InputSignal +{ +private: + struct cvar_s *m_cvar; + CImageLabel *pLabelOn; + +public: + SpectToggleButton( const char *cvarname, const char *text, int x, int y, int wide, int tall, bool flat ) : + CommandButton( text, x, y, wide, tall, false, flat ) + { + m_cvar = gEngfuncs.pfnGetCvarPointer( cvarname ); + + // Put a > to show it's a submenu + pLabelOn = new CImageLabel( "checked", 0, 0 ); + pLabelOn->setParent( this ); + pLabelOn->addInputSignal( this ); + + int textwide, texttall; + getTextSize( textwide, texttall ); + + // Reposition + pLabelOn->setPos( textwide, ( tall - pLabelOn->getTall() ) / 2 ); + } + + virtual void cursorEntered( Panel *panel ) + { + CommandButton::cursorEntered(); + } + + virtual void cursorExited( Panel *panel ) + { + CommandButton::cursorExited(); + } + + virtual void mousePressed( MouseCode code, Panel *panel ) + { + doClick(); + }; + + virtual void cursorMoved( int x, int y, Panel *panel ) {}; + + virtual void mouseDoublePressed( MouseCode code, Panel *panel ) {}; + virtual void mouseReleased( MouseCode code, Panel *panel ) {}; + virtual void mouseWheeled( int delta, Panel *panel ) {}; + virtual void keyPressed( KeyCode code, Panel *panel ) {}; + virtual void keyTyped( KeyCode code, Panel *panel ) {}; + virtual void keyReleased( KeyCode code, Panel *panel ) {}; + virtual void keyFocusTicked( Panel *panel ) {}; + + virtual void paintBackground() + { + if( isArmed() ) + { + drawSetColor( 143, 143, 54, 125 ); + drawFilledRect( 5, 0, _size[0] - 5, _size[1] ); + } + } + + virtual void paint( void ) + { + if( isArmed() ) + { + setFgColor( 194, 202, 54, 0 ); + } + else + { + setFgColor( 143, 143, 54, 15 ); + } + + if( !m_cvar ) + { + pLabelOn->setVisible( false ); + } + else if( m_cvar->value ) + { + pLabelOn->setVisible( true ); + } + else + { + pLabelOn->setVisible( false ); + } + + Button::paint(); + } +}; + +/* +class SpectToggleButton : public ToggleCommandButton +{ +private: + struct cvar_s *m_cvar; + CImageLabel *pLabelOn; + CImageLabel *pLabelOff; + +public: + SpectToggleButton( const char *cvarname, const char *text, int x, int y, int wide, int tall, bool flat ) : + ToggleCommandButton( cvarname, text, x, y, wide, tall, flat, TRUE ) + { + m_cvar = gEngfuncs.pfnGetCvarPointer( cvarname ); + + // Put a > to show it's a submenu + pLabelOn = new CImageLabel( "checked", 0, 0 ); + pLabelOn->setParent( this ); + pLabelOn->addInputSignal( this ); + + pLabelOff = new CImageLabel( "unchecked", 0, 0 ); + pLabelOff->setParent( this ); + pLabelOff->setEnabled( true ); + pLabelOff->addInputSignal( this ); + + int textwide, texttall; + getTextSize( textwide, texttall ); + + // Reposition + pLabelOn->setPos( textwide, ( tall - pLabelOn->getTall() ) / 2 ); + + pLabelOff->setPos( textwide, ( tall - pLabelOff->getTall() ) / 2 ); + + // Set text color to orange + setFgColor( Scheme::sc_primary1 ); + } + + virtual void paintBackground() + { + if( isArmed() ) + { + drawSetColor( 143,143, 54, 125 ); + drawFilledRect( 5, 0, _size[0] - 5,_size[1] ); + } + } + + virtual void paint() + { + + if( isArmed() ) + { + setFgColor( 194, 202, 54, 0 ); + } + else + { + setFgColor( 143, 143, 54, 15 ); + } + + if( !m_cvar ) + { + pLabelOff->setVisible( false ); + pLabelOn->setVisible( false ); + } + else if( m_cvar->value ) + { + pLabelOff->setVisible( false ); + pLabelOn->setVisible( true ); + } + else + { + pLabelOff->setVisible( true ); + pLabelOn->setVisible( false ); + } + + Button::paint(); + } +}; +*/ + +//============================================================ +// Panel that can be dragged around +class DragNDropPanel : public Panel +{ +private: + bool m_bBeingDragged; + LineBorder *m_pBorder; +public: + DragNDropPanel( int x, int y, int wide, int tall ) : Panel( x, y, wide, tall ) + { + m_bBeingDragged = false; + + // Create the Drag Handler + addInputSignal( new CDragNDropHandler( this ) ); + + // Create the border (for dragging) + m_pBorder = new LineBorder(); + } + + virtual void setDragged( bool bState ) + { + m_bBeingDragged = bState; + + if( m_bBeingDragged ) + setBorder( m_pBorder ); + else + setBorder( NULL ); + } +}; + +//================================================================ +// Panel that draws itself with a transparent black background +class CTransparentPanel : public Panel +{ +private: + int m_iTransparency; +public: + CTransparentPanel( int iTrans, int x, int y, int wide, int tall ) : Panel( x, y, wide, tall ) + { + m_iTransparency = iTrans; + } + + virtual void paintBackground() + { + if( m_iTransparency ) + { + // Transparent black background + drawSetColor( 0, 0, 0, m_iTransparency ); + drawFilledRect( 0, 0, _size[0], _size[1] ); + } + } +}; + +//================================================================ +// Menu Panel that supports buffering of menus +class CMenuPanel : public CTransparentPanel +{ +private: + CMenuPanel *m_pNextMenu; + int m_iMenuID; + int m_iRemoveMe; + int m_iIsActive; + float m_flOpenTime; +public: + CMenuPanel( int iRemoveMe, int x, int y, int wide, int tall ) : CTransparentPanel( 100, x, y, wide, tall ) + { + Reset(); + m_iRemoveMe = iRemoveMe; + } + + CMenuPanel( int iTrans, int iRemoveMe, int x, int y, int wide, int tall ) : CTransparentPanel( iTrans, x, y, wide, tall ) + { + Reset(); + m_iRemoveMe = iRemoveMe; + } + + virtual void Reset( void ) + { + m_pNextMenu = NULL; + m_iIsActive = false; + m_flOpenTime = 0; + } + + void SetNextMenu( CMenuPanel *pNextPanel ) + { + if( m_pNextMenu ) + m_pNextMenu->SetNextMenu( pNextPanel ); + else + m_pNextMenu = pNextPanel; + } + + void SetMenuID( int iID ) + { + m_iMenuID = iID; + } + + void SetActive( int iState ) + { + m_iIsActive = iState; + } + + virtual void Open( void ) + { + setVisible( true ); + + // Note the open time, so we can delay input for a bit + m_flOpenTime = gHUD.m_flTime; + } + + virtual void Close( void ) + { + setVisible( false ); + m_iIsActive = false; + + if ( m_iRemoveMe ) + gViewPort->removeChild( this ); + + // This MenuPanel has now been deleted. Don't append code here. + } + + int ShouldBeRemoved() { return m_iRemoveMe; }; + CMenuPanel* GetNextMenu() { return m_pNextMenu; }; + int GetMenuID() { return m_iMenuID; }; + int IsActive() { return m_iIsActive; }; + float GetOpenTime() { return m_flOpenTime; }; + + // Numeric input + virtual bool SlotInput( int iSlot ) { return false; }; + virtual void SetActiveInfo( int iInput ) {}; +}; + +//================================================================ +// Custom drawn scroll bars +class CTFScrollButton : public CommandButton +{ +private: + BitmapTGA *m_pTGA; + +public: + CTFScrollButton( int iArrow, const char *text, int x, int y, int wide, int tall ); + + virtual void paint( void ); + virtual void paintBackground( void ); +}; + +// Custom drawn slider bar +class CTFSlider : public Slider +{ +public: + CTFSlider( int x, int y, int wide, int tall, bool vertical ) : Slider( x, y, wide, tall, vertical ) + { + }; + + virtual void paintBackground( void ); +}; + +// Custom drawn scrollpanel +class CTFScrollPanel : public ScrollPanel +{ +public: + CTFScrollPanel(int x,int y,int wide,int tall); +}; + +//================================================================ +// Menu Panels that take key input +//============================================================ +class CClassMenuPanel : public CMenuPanel +{ +private: + CTransparentPanel *m_pClassInfoPanel[PC_LASTCLASS]; + Label *m_pPlayers[PC_LASTCLASS]; + ClassButton *m_pButtons[PC_LASTCLASS]; + CommandButton *m_pCancelButton; + ScrollPanel *m_pScrollPanel; + + CImageLabel *m_pClassImages[MAX_TEAMS][PC_LASTCLASS]; + + int m_iCurrentInfo; + + enum { STRLENMAX_PLAYERSONTEAM = 128 }; + char m_sPlayersOnTeamString[STRLENMAX_PLAYERSONTEAM]; + +public: + CClassMenuPanel( int iTrans, int iRemoveMe, int x, int y, int wide, int tall ); + + virtual bool SlotInput( int iSlot ); + virtual void Open( void ); + virtual void Update( void ); + virtual void SetActiveInfo( int iInput ); + virtual void Initialize( void ); + + virtual void Reset( void ) + { + CMenuPanel::Reset(); + m_iCurrentInfo = 0; + } +}; + +class CTeamMenuPanel : public CMenuPanel +{ +public: + ScrollPanel *m_pScrollPanel; + CTransparentPanel *m_pTeamWindow; + Label *m_pMapTitle; + TextPanel *m_pBriefing; + TextPanel *m_pTeamInfoPanel[6]; + CommandButton *m_pButtons[6]; + bool m_bUpdatedMapName; + CommandButton *m_pCancelButton; + CommandButton *m_pSpectateButton; + + int m_iCurrentInfo; + +public: + CTeamMenuPanel( int iTrans, int iRemoveMe, int x, int y, int wide, int tall ); + + virtual bool SlotInput( int iSlot ); + virtual void Open( void ); + virtual void Update( void ); + virtual void SetActiveInfo( int iInput ); + virtual void paintBackground( void ); + + virtual void Initialize( void ); + + virtual void Reset( void ) + { + CMenuPanel::Reset(); + m_iCurrentInfo = 0; + } +}; + +//========================================================= +// Specific Menus to handle old HUD sections +class CHealthPanel : public DragNDropPanel +{ +private: + BitmapTGA *m_pHealthTGA; + Label *m_pHealthLabel; +public: + CHealthPanel( int x, int y, int wide, int tall ) : DragNDropPanel( x, y, wide, tall ) + { + // Load the Health icon + FileInputStream *fis = new FileInputStream( GetVGUITGAName( "%d_hud_health" ), false ); + m_pHealthTGA = new BitmapTGA( fis, true ); + fis->close(); + + // Create the Health Label + int iXSize, iYSize; + m_pHealthTGA->getSize( iXSize, iYSize ); + m_pHealthLabel = new Label( "", 0, 0, iXSize, iYSize ); + m_pHealthLabel->setImage( m_pHealthTGA ); + m_pHealthLabel->setParent( this ); + + // Set panel dimension + // Shouldn't be needed once Billy's fized setImage not recalculating the size + // setSize( iXSize + 100, gHUD.m_iFontHeight + 10 ); + // m_pHealthLabel->setPos( 10, ( getTall() - iYSize ) / 2 ); + } + + virtual void paintBackground() + { + } + + void paint() + { + // Get the paint color + int r,g,b,a; + // Has health changed? Flash the health # + if( gHUD.m_Health.m_fFade ) + { + gHUD.m_Health.m_fFade -= ( gHUD.m_flTimeDelta * 20 ); + if( gHUD.m_Health.m_fFade <= 0 ) + { + a = MIN_ALPHA; + gHUD.m_Health.m_fFade = 0; + } + + // Fade the health number back to dim + a = MIN_ALPHA + ( gHUD.m_Health.m_fFade / FADE_TIME ) * 128; + } + else + a = MIN_ALPHA; + + gHUD.m_Health.GetPainColor( r, g, b ); + ScaleColors(r, g, b, a ); + + // If health is getting low, make it bright red + if( gHUD.m_Health.m_iHealth <= 15 ) + a = 255; + + int iXSize, iYSize, iXPos, iYPos; + m_pHealthTGA->getSize( iXSize, iYSize ); + m_pHealthTGA->getPos( iXPos, iYPos ); + + // Paint the player's health + int x = gHUD.DrawHudNumber( iXPos + iXSize + 5, iYPos + 5, DHN_3DIGITS | DHN_DRAWZERO, gHUD.m_Health.m_iHealth, r, g, b ); + + // Draw the vertical line + int HealthWidth = gHUD.GetSpriteRect( gHUD.m_HUD_number_0 ).right - gHUD.GetSpriteRect( gHUD.m_HUD_number_0 ).left; + x += HealthWidth / 2; + FillRGBA( x, iYPos + 5, HealthWidth / 10, gHUD.m_iFontHeight, 255, 160, 0, a ); + } +}; +#endif diff --git a/cl_dll/vgui_int.cpp b/cl_dll/vgui_int.cpp new file mode 100644 index 00000000..2a4272d8 --- /dev/null +++ b/cl_dll/vgui_int.cpp @@ -0,0 +1,127 @@ +//========= Copyright (c) 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "vgui_int.h" +#include +#include +#include +#include +#include +#include +#include +#include "hud.h" +#include "cl_util.h" +#include "camera.h" +#include "kbutton.h" +#include "cvardef.h" +#include "usercmd.h" +#include "const.h" +#include "camera.h" +#include "in_defs.h" +#include "vgui_TeamFortressViewport.h" +#include "vgui_ControlConfigPanel.h" + +namespace +{ + +class TexturePanel : public Panel, public ActionSignal +{ +private: + int _bindIndex; + TextEntry *_textEntry; +public: + TexturePanel() : Panel( 0, 0, 256, 276 ) + { + _bindIndex = 2700; + _textEntry = new TextEntry( "2700", 0, 0, 128, 20 ); + _textEntry->setParent( this ); + _textEntry->addActionSignal( this ); + } + + virtual bool isWithin( int x, int y ) + { + return _textEntry->isWithin( x, y ); + } + + virtual void actionPerformed( Panel *panel ) + { + char buf[256]; + + _textEntry->getText( 0, buf, 256 ); + sscanf( buf, "%d", &_bindIndex); + } +protected: + virtual void paintBackground() + { + Panel::paintBackground(); + + int wide, tall; + + getPaintSize( wide, tall ); + + drawSetColor( 0, 0, 255, 0 ); + drawSetTexture( _bindIndex ); + drawTexturedRect( 0, 19, 257, 257 ); + } +}; + +} + +using namespace vgui; + +void VGui_ViewportPaintBackground( int extents[4] ) +{ + gEngfuncs.VGui_ViewportPaintBackground( extents ); +} + +void* VGui_GetPanel() +{ + return (Panel*)gEngfuncs.VGui_GetPanel(); +} + +void VGui_Startup() +{ + Panel *root = (Panel*)VGui_GetPanel(); + root->setBgColor( 128, 128, 0, 0 ); + // root->setNonPainted( false ); + // root->setBorder( new LineBorder() ); + root->setLayout( new BorderLayout( 0 ) ); + + // root->getSurfaceBase()->setEmulatedCursorVisible( true ); + + if( gViewPort != NULL ) + { +// root->removeChild( gViewPort ); + + // free the memory +// delete gViewPort; +// gViewPort = NULL; + + gViewPort->Initialize(); + } + else + { + gViewPort = new TeamFortressViewport( 0, 0, root->getWide(), root->getTall() ); + gViewPort->setParent( root ); + } + + /* + TexturePanel *texturePanel = new TexturePanel(); + texturePanel->setParent( gViewPort ); + */ +} + +void VGui_Shutdown() +{ + delete gViewPort; + gViewPort = NULL; +} + + + + + diff --git a/cl_dll/vgui_int.h b/cl_dll/vgui_int.h new file mode 100644 index 00000000..6510853e --- /dev/null +++ b/cl_dll/vgui_int.h @@ -0,0 +1,21 @@ +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef VGUI_INT_H +#define VGUI_INT_H + +extern "C" +{ +void VGui_Startup(); +void VGui_Shutdown(); + +//Only safe to call from inside subclass of Panel::paintBackground +void VGui_ViewportPaintBackground(int extents[4]); +} + + +#endif \ No newline at end of file diff --git a/cl_dll/vgui_teammenu.cpp b/cl_dll/vgui_teammenu.cpp new file mode 100644 index 00000000..bc7b22e6 --- /dev/null +++ b/cl_dll/vgui_teammenu.cpp @@ -0,0 +1,394 @@ +//=========== (C) Copyright 1996-2002 Valve, L.L.C. All rights reserved. =========== +// +// The copyright to the contents herein is the property of Valve, L.L.C. +// The contents may be used and/or copied only with the written permission of +// Valve, L.L.C., or in accordance with the terms and conditions stipulated in +// the agreement/contract under which the contents have been supplied. +// +// Purpose: TFC Team Menu +// +// $Workfile: $ +// $Date: $ +// +//----------------------------------------------------------------------------- +// $Log: $ +// +// $NoKeywords: $ +//============================================================================= + +#include "vgui_int.h" +#include "VGUI_Font.h" +#include "VGUI_ScrollPanel.h" +#include "VGUI_TextImage.h" + +#include "hud.h" +#include "cl_util.h" +#include "vgui_TeamFortressViewport.h" + +// Team Menu Dimensions +#define TEAMMENU_TITLE_X XRES(40) +#define TEAMMENU_TITLE_Y YRES(32) +#define TEAMMENU_TOPLEFT_BUTTON_X XRES(40) +#define TEAMMENU_TOPLEFT_BUTTON_Y YRES(80) +#define TEAMMENU_BUTTON_SIZE_X XRES(124) +#define TEAMMENU_BUTTON_SIZE_Y YRES(24) +#define TEAMMENU_BUTTON_SPACER_Y YRES(8) +#define TEAMMENU_WINDOW_X XRES(176) +#define TEAMMENU_WINDOW_Y YRES(80) +#define TEAMMENU_WINDOW_SIZE_X XRES(424) +#define TEAMMENU_WINDOW_SIZE_Y YRES(312) +#define TEAMMENU_WINDOW_TITLE_X XRES(16) +#define TEAMMENU_WINDOW_TITLE_Y YRES(16) +#define TEAMMENU_WINDOW_TEXT_X XRES(16) +#define TEAMMENU_WINDOW_TEXT_Y YRES(48) +#define TEAMMENU_WINDOW_TEXT_SIZE_Y YRES(178) +#define TEAMMENU_WINDOW_INFO_X XRES(16) +#define TEAMMENU_WINDOW_INFO_Y YRES(234) + +// Creation +CTeamMenuPanel::CTeamMenuPanel( int iTrans, int iRemoveMe, int x, int y, int wide, int tall ) : CMenuPanel( iTrans, iRemoveMe, x, y, wide, tall ) +{ + // Get the scheme used for the Titles + CSchemeManager *pSchemes = gViewPort->GetSchemeManager(); + + // schemes + SchemeHandle_t hTitleScheme = pSchemes->getSchemeHandle( "Title Font" ); + SchemeHandle_t hTeamWindowText = pSchemes->getSchemeHandle( "Briefing Text" ); + SchemeHandle_t hTeamInfoText = pSchemes->getSchemeHandle( "Team Info Text" ); + + // get the Font used for the Titles + Font *pTitleFont = pSchemes->getFont( hTitleScheme ); + int r, g, b, a; + + // Create the title + Label *pLabel = new Label( "", TEAMMENU_TITLE_X, TEAMMENU_TITLE_Y ); + pLabel->setParent( this ); + pLabel->setFont( pTitleFont ); + pSchemes->getFgColor( hTitleScheme, r, g, b, a ); + pLabel->setFgColor( r, g, b, a ); + pSchemes->getBgColor( hTitleScheme, r, g, b, a ); + pLabel->setBgColor( r, g, b, a ); + pLabel->setContentAlignment( vgui::Label::a_west ); + pLabel->setText( "%s", gHUD.m_TextMessage.BufferedLocaliseTextString("#Title_SelectYourTeam")); + + // Create the Info Window + m_pTeamWindow = new CTransparentPanel( 255, TEAMMENU_WINDOW_X, TEAMMENU_WINDOW_Y, TEAMMENU_WINDOW_SIZE_X, TEAMMENU_WINDOW_SIZE_Y ); + m_pTeamWindow->setParent( this ); + m_pTeamWindow->setBorder( new LineBorder( Color( 255 * 0.7, 170 * 0.7 ,0 ,0 ) ) ); + + // Create the Map Name Label + m_pMapTitle = new Label( "", TEAMMENU_WINDOW_TITLE_X, TEAMMENU_WINDOW_TITLE_Y ); + m_pMapTitle->setFont( pTitleFont ); + m_pMapTitle->setParent( m_pTeamWindow ); + pSchemes->getFgColor( hTitleScheme, r, g, b, a ); + m_pMapTitle->setFgColor( r, g, b, a ); + pSchemes->getBgColor( hTitleScheme, r, g, b, a ); + m_pMapTitle->setBgColor( r, g, b, a ); + m_pMapTitle->setContentAlignment( vgui::Label::a_west ); + + // Create the Scroll panel + m_pScrollPanel = new CTFScrollPanel( TEAMMENU_WINDOW_TEXT_X, TEAMMENU_WINDOW_TEXT_Y, TEAMMENU_WINDOW_SIZE_X - ( TEAMMENU_WINDOW_TEXT_X * 2 ), TEAMMENU_WINDOW_TEXT_SIZE_Y ); + m_pScrollPanel->setParent( m_pTeamWindow ); + m_pScrollPanel->setScrollBarVisible( false, false ); + + // Create the Map Briefing panel + m_pBriefing = new TextPanel("", 0, 0, TEAMMENU_WINDOW_SIZE_X - TEAMMENU_WINDOW_TEXT_X, TEAMMENU_WINDOW_TEXT_SIZE_Y ); + m_pBriefing->setParent( m_pScrollPanel->getClient() ); + m_pBriefing->setFont( pSchemes->getFont( hTeamWindowText ) ); + pSchemes->getFgColor( hTeamWindowText, r, g, b, a ); + m_pBriefing->setFgColor( r, g, b, a ); + pSchemes->getBgColor( hTeamWindowText, r, g, b, a ); + m_pBriefing->setBgColor( r, g, b, a ); + + m_pBriefing->setText( gHUD.m_TextMessage.BufferedLocaliseTextString( "#Map_Description_not_available" ) ); + + // Team Menu buttons + for( int i = 1; i <= 5; i++ ) + { + char sz[256]; + + int iYPos = TEAMMENU_TOPLEFT_BUTTON_Y + ( ( TEAMMENU_BUTTON_SIZE_Y + TEAMMENU_BUTTON_SPACER_Y ) * i ); + + // Team button + m_pButtons[i] = new CommandButton( "", TEAMMENU_TOPLEFT_BUTTON_X, iYPos, TEAMMENU_BUTTON_SIZE_X, TEAMMENU_BUTTON_SIZE_Y, true ); + m_pButtons[i]->setParent( this ); + m_pButtons[i]->setContentAlignment( vgui::Label::a_west ); + m_pButtons[i]->setVisible( false ); + + // AutoAssign button uses special case + if( i == 5 ) + { + m_pButtons[5]->setBoundKey( '5' ); + m_pButtons[5]->setText( gHUD.m_TextMessage.BufferedLocaliseTextString( "#Team_AutoAssign" ) ); + m_pButtons[5]->setVisible( true ); + } + + // Create the Signals + sprintf( sz, "jointeam %d", i ); + m_pButtons[i]->addActionSignal( new CMenuHandler_StringCommandWatch( sz, true ) ); + m_pButtons[i]->addInputSignal( new CHandler_MenuButtonOver( this, i ) ); + + // Create the Team Info panel + m_pTeamInfoPanel[i] = new TextPanel( "", TEAMMENU_WINDOW_INFO_X, TEAMMENU_WINDOW_INFO_Y, TEAMMENU_WINDOW_SIZE_X - TEAMMENU_WINDOW_INFO_X, TEAMMENU_WINDOW_SIZE_X - TEAMMENU_WINDOW_INFO_Y ); + m_pTeamInfoPanel[i]->setParent( m_pTeamWindow ); + m_pTeamInfoPanel[i]->setFont( pSchemes->getFont( hTeamInfoText ) ); + m_pTeamInfoPanel[i]->setFgColor( iTeamColors[i % iNumberOfTeamColors][0], + iTeamColors[i % iNumberOfTeamColors][1], + iTeamColors[i % iNumberOfTeamColors][2], + 0 ); + m_pTeamInfoPanel[i]->setBgColor( 0, 0, 0, 255 ); + } + + // Create the Cancel button + m_pCancelButton = new CommandButton( CHudTextMessage::BufferedLocaliseTextString( "#Menu_Cancel" ), TEAMMENU_TOPLEFT_BUTTON_X, 0, TEAMMENU_BUTTON_SIZE_X, TEAMMENU_BUTTON_SIZE_Y ); + m_pCancelButton->setParent( this ); + m_pCancelButton->addActionSignal( new CMenuHandler_TextWindow( HIDE_TEXTWINDOW ) ); + + // Create the Spectate button + m_pSpectateButton = new SpectateButton( CHudTextMessage::BufferedLocaliseTextString( "#Menu_Spectate" ), TEAMMENU_TOPLEFT_BUTTON_X, 0, TEAMMENU_BUTTON_SIZE_X, TEAMMENU_BUTTON_SIZE_Y, true ); + m_pSpectateButton->setParent( this ); + m_pSpectateButton->addActionSignal( new CMenuHandler_StringCommand( "spectate", true ) ); + m_pSpectateButton->setBoundKey( '6' ); + m_pSpectateButton->addInputSignal( new CHandler_MenuButtonOver( this, 6 ) ); + + Initialize(); +} + +//----------------------------------------------------------------------------- +// Purpose: Called each time a new level is started. +//----------------------------------------------------------------------------- +void CTeamMenuPanel::Initialize( void ) +{ + m_bUpdatedMapName = false; + m_iCurrentInfo = 0; + m_pScrollPanel->setScrollValue( 0, 0 ); +} + +//----------------------------------------------------------------------------- +// Purpose: Called everytime the Team Menu is displayed +//----------------------------------------------------------------------------- +void CTeamMenuPanel::Update( void ) +{ + int iYPos = TEAMMENU_TOPLEFT_BUTTON_Y; + + // Set the team buttons + for( int i = 1; i <= 4; i++ ) + { + if( m_pButtons[i] ) + { + if( i <= gViewPort->GetNumberOfTeams() ) + { + m_pButtons[i]->setText( gViewPort->GetTeamName( i ) ); + + // bound key replacement + char sz[32]; + sprintf( sz, "%d", i ); + m_pButtons[i]->setBoundKey( sz[0] ); + + m_pButtons[i]->setVisible( true ); + m_pButtons[i]->setPos( TEAMMENU_TOPLEFT_BUTTON_X, iYPos ); + iYPos += TEAMMENU_BUTTON_SIZE_Y + TEAMMENU_BUTTON_SPACER_Y; + + // Start with the first option up + if( !m_iCurrentInfo ) + SetActiveInfo( i ); + + char szPlayerList[( MAX_PLAYER_NAME_LENGTH + 3 ) * 31]; // name + ", " + strcpy(szPlayerList, "\n"); + // Update the Team Info + // Now count the number of teammembers of this class + int iTotal = 0; + for( int j = 1; j < MAX_PLAYERS; j++ ) + { + if( g_PlayerInfoList[j].name == NULL ) + continue; // empty player slot, skip + if( g_PlayerInfoList[j].thisplayer ) + continue; // skip this player + if( g_PlayerExtraInfo[j].teamnumber != i ) + continue; // skip over players in other teams + + iTotal++; + if( iTotal > 1 ) + strncat( szPlayerList, ", ", sizeof(szPlayerList) - strlen( szPlayerList ) - 1 ); + strncat( szPlayerList, g_PlayerInfoList[j].name, sizeof(szPlayerList) - strlen( szPlayerList ) - 1 ); + szPlayerList[sizeof(szPlayerList) - 1] = '\0'; + } + + if( iTotal > 0 ) + { + // Set the text of the info Panel + char szText[( ( MAX_PLAYER_NAME_LENGTH + 3 ) * 31 ) + 256]; + if( iTotal == 1 ) + sprintf( szText, "%s: %d Player (%d points)", gViewPort->GetTeamName( i ), iTotal, g_TeamInfo[i].frags ); + else + sprintf( szText, "%s: %d Players (%d points)", gViewPort->GetTeamName( i ), iTotal, g_TeamInfo[i].frags ); + strncat( szText, szPlayerList, sizeof(szText) - strlen( szText ) - 1 ); + szText[sizeof(szText) - 1] = '\0'; + + m_pTeamInfoPanel[i]->setText( szText ); + } + else + { + m_pTeamInfoPanel[i]->setText( "" ); + } + } + else + { + // Hide the button (may be visible from previous maps) + m_pButtons[i]->setVisible( false ); + } + } + } + + // Move the AutoAssign button into place + m_pButtons[5]->setPos( TEAMMENU_TOPLEFT_BUTTON_X, iYPos ); + iYPos += TEAMMENU_BUTTON_SIZE_Y + TEAMMENU_BUTTON_SPACER_Y; + + // Spectate button + if( m_pSpectateButton->IsNotValid() ) + { + m_pSpectateButton->setVisible( false ); + } + else + { + m_pSpectateButton->setPos( TEAMMENU_TOPLEFT_BUTTON_X, iYPos ); + m_pSpectateButton->setVisible( true ); + iYPos += TEAMMENU_BUTTON_SIZE_Y + TEAMMENU_BUTTON_SPACER_Y; + } + + // If the player is already in a team, make the cancel button visible + if( g_iTeamNumber ) + { + m_pCancelButton->setPos( TEAMMENU_TOPLEFT_BUTTON_X, iYPos ); + iYPos += TEAMMENU_BUTTON_SIZE_Y + TEAMMENU_BUTTON_SPACER_Y; + m_pCancelButton->setVisible( true ); + } + else + { + m_pCancelButton->setVisible( false ); + } + + // Set the Map Title + if( !m_bUpdatedMapName ) + { + const char *level = gEngfuncs.pfnGetLevelName(); + if( level && level[0] ) + { + char sz[256]; + char szTitle[256]; + char *ch; + + // Update the level name + strcpy( sz, level ); + ch = strchr( sz, '/' ); + if( !ch ) + ch = strchr( sz, '\\' ); + strcpy( szTitle, ch + 1 ); + ch = strchr( szTitle, '.' ); + *ch = '\0'; + m_pMapTitle->setText( "%s", szTitle ); + *ch = '.'; + + // Update the map briefing + strcpy( sz, level ); + ch = strchr( sz, '.' ); + *ch = '\0'; + strcat( sz, ".txt" ); + char *pfile = (char*)gEngfuncs.COM_LoadFile( sz, 5, NULL ); + if( pfile ) + { + m_pBriefing->setText( pfile ); + + // Get the total size of the Briefing text and resize the text panel + int iXSize, iYSize; + m_pBriefing->getTextImage()->getTextSize( iXSize, iYSize ); + m_pBriefing->setSize( iXSize, iYSize ); + gEngfuncs.COM_FreeFile( pfile ); + } + + m_bUpdatedMapName = true; + } + } + + m_pScrollPanel->validate(); +} + +//===================================== +// Key inputs +bool CTeamMenuPanel::SlotInput( int iSlot ) +{ + // Check for AutoAssign + if( iSlot == 5 ) + { + m_pButtons[5]->fireActionSignal(); + return true; + } + + // Spectate + if( iSlot == 6 ) + { + m_pSpectateButton->fireActionSignal(); + return true; + } + + // Otherwise, see if a particular team is selectable + if( ( iSlot < 1 ) || ( iSlot > gViewPort->GetNumberOfTeams() ) ) + return false; + + if( !m_pButtons[iSlot] ) + return false; + + // Is the button pushable? + if( m_pButtons[iSlot]->isVisible() ) + { + m_pButtons[iSlot]->fireActionSignal(); + return true; + } + + return false; +} + +//====================================== +// Update the Team menu before opening it +void CTeamMenuPanel::Open( void ) +{ + Update(); + CMenuPanel::Open(); +} + +void CTeamMenuPanel::paintBackground() +{ + // make sure we get the map briefing up + if( !m_bUpdatedMapName ) + Update(); + + CMenuPanel::paintBackground(); +} + +//====================================== +// Mouse is over a team button, bring up the class info +void CTeamMenuPanel::SetActiveInfo( int iInput ) +{ + // Remove all the Info panels and bring up the specified one + m_pSpectateButton->setArmed( false ); + for( int i = 1; i <= 5; i++ ) + { + m_pButtons[i]->setArmed( false ); + m_pTeamInfoPanel[i]->setVisible( false ); + } + + // 6 is Spectate + if( iInput == 6 ) + { + m_pSpectateButton->setArmed( true ); + } + else + { + m_pButtons[iInput]->setArmed( true ); + m_pTeamInfoPanel[iInput]->setVisible( true ); + } + + m_iCurrentInfo = iInput; + + m_pScrollPanel->validate(); +} diff --git a/cl_dll/voice_status.cpp b/cl_dll/voice_status.cpp new file mode 100644 index 00000000..53cd9d5f --- /dev/null +++ b/cl_dll/voice_status.cpp @@ -0,0 +1,884 @@ +//========= Copyright � 1996-2001, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +// There are hud.h's coming out of the woodwork so this ensures that we get the right one. +#if defined(THREEWAVE) || defined(DMC_BUILD) + #include "../dmc/cl_dll/hud.h" +#elif defined(CSTRIKE) + #include "../cstrike/cl_dll/hud.h" +#elif defined(DOD) + #include "../dod/cl_dll/hud.h" +#else + #include "hud.h" +#endif + +#include "cl_util.h" +#include +#include +#include +#include "parsemsg.h" +#include "demo.h" +#include "demo_api.h" +#include "voice_status.h" +#include "r_efx.h" +#include "entity_types.h" +#include "VGUI_ActionSignal.h" +#include "VGUI_Scheme.h" +#include "VGUI_TextImage.h" +#include "vgui_loadtga.h" +#include "vgui_helpers.h" +#include "VGUI_MouseCode.h" + + + +using namespace vgui; + + +extern int cam_thirdperson; + + +#define VOICE_MODEL_INTERVAL 0.3 +#define SCOREBOARD_BLINK_FREQUENCY 0.3 // How often to blink the scoreboard icons. +#define SQUELCHOSCILLATE_PER_SECOND 2.0f + + +extern BitmapTGA *LoadTGA( const char* pImageName ); + + + +// ---------------------------------------------------------------------- // +// The voice manager for the client. +// ---------------------------------------------------------------------- // +CVoiceStatus g_VoiceStatus; + +CVoiceStatus* GetClientVoiceMgr() +{ + return &g_VoiceStatus; +} + + + +// ---------------------------------------------------------------------- // +// CVoiceStatus. +// ---------------------------------------------------------------------- // + +static CVoiceStatus *g_pInternalVoiceStatus = NULL; + +int __MsgFunc_VoiceMask(const char *pszName, int iSize, void *pbuf) +{ + if(g_pInternalVoiceStatus) + g_pInternalVoiceStatus->HandleVoiceMaskMsg(iSize, pbuf); + + return 1; +} + +int __MsgFunc_ReqState(const char *pszName, int iSize, void *pbuf) +{ + if(g_pInternalVoiceStatus) + g_pInternalVoiceStatus->HandleReqStateMsg(iSize, pbuf); + + return 1; +} + + +int g_BannedPlayerPrintCount; +void ForEachBannedPlayer(char id[16]) +{ + char str[256]; + sprintf(str, "Ban %d: %2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x\n", + g_BannedPlayerPrintCount++, + id[0], id[1], id[2], id[3], + id[4], id[5], id[6], id[7], + id[8], id[9], id[10], id[11], + id[12], id[13], id[14], id[15] + ); +#ifdef _WIN32 + strupr(str); +#endif + gEngfuncs.pfnConsolePrint(str); +} + + +void ShowBannedCallback() +{ + if(g_pInternalVoiceStatus) + { + g_BannedPlayerPrintCount = 0; + gEngfuncs.pfnConsolePrint("------- BANNED PLAYERS -------\n"); + g_pInternalVoiceStatus->m_BanMgr.ForEachBannedPlayer(ForEachBannedPlayer); + gEngfuncs.pfnConsolePrint("------------------------------\n"); + } +} + + +// ---------------------------------------------------------------------- // +// CVoiceStatus. +// ---------------------------------------------------------------------- // + +CVoiceStatus::CVoiceStatus() +{ + m_bBanMgrInitialized = false; + m_LastUpdateServerState = 0; + + m_pSpeakerLabelIcon = NULL; + m_pScoreboardNeverSpoken = NULL; + m_pScoreboardNotSpeaking = NULL; + m_pScoreboardSpeaking = NULL; + m_pScoreboardSpeaking2 = NULL; + m_pScoreboardSquelch = NULL; + m_pScoreboardBanned = NULL; + + m_pLocalBitmap = NULL; + m_pAckBitmap = NULL; + + m_bTalking = m_bServerAcked = false; + + memset(m_pBanButtons, 0, sizeof(m_pBanButtons)); + + m_pParentPanel = NULL; + + m_bServerModEnable = -1; + + m_pchGameDir = NULL; +} + + +CVoiceStatus::~CVoiceStatus() +{ + g_pInternalVoiceStatus = NULL; + + for(int i=0; i < MAX_VOICE_SPEAKERS; i++) + { + delete m_Labels[i].m_pLabel; + m_Labels[i].m_pLabel = NULL; + + delete m_Labels[i].m_pIcon; + m_Labels[i].m_pIcon = NULL; + + delete m_Labels[i].m_pBackground; + m_Labels[i].m_pBackground = NULL; + } + + delete m_pLocalLabel; + m_pLocalLabel = NULL; + + FreeBitmaps(); + + if(m_pchGameDir) + { + if(m_bBanMgrInitialized) + { + m_BanMgr.SaveState(m_pchGameDir); + } + + free(m_pchGameDir); + } +} + + +int CVoiceStatus::Init( + IVoiceStatusHelper *pHelper, + Panel **pParentPanel) +{ + // Setup the voice_modenable cvar. + gEngfuncs.pfnRegisterVariable("voice_modenable", "1", FCVAR_ARCHIVE); + + gEngfuncs.pfnRegisterVariable("voice_clientdebug", "0", 0); + + gEngfuncs.pfnAddCommand("voice_showbanned", ShowBannedCallback); + + if(gEngfuncs.pfnGetGameDirectory()) + { + m_BanMgr.Init(gEngfuncs.pfnGetGameDirectory()); + m_bBanMgrInitialized = true; + } + + assert(!g_pInternalVoiceStatus); + g_pInternalVoiceStatus = this; + + m_BlinkTimer = 0; + m_VoiceHeadModel = 0; + memset(m_Labels, 0, sizeof(m_Labels)); + + for(int i=0; i < MAX_VOICE_SPEAKERS; i++) + { + CVoiceLabel *pLabel = &m_Labels[i]; + + pLabel->m_pBackground = new Label(""); + + if((pLabel->m_pLabel = new Label("")) != 0) + { + pLabel->m_pLabel->setVisible( true ); + pLabel->m_pLabel->setFont( Scheme::sf_primary2 ); + pLabel->m_pLabel->setTextAlignment( Label::a_east ); + pLabel->m_pLabel->setContentAlignment( Label::a_east ); + pLabel->m_pLabel->setParent( pLabel->m_pBackground ); + } + + if( (pLabel->m_pIcon = new ImagePanel( NULL )) != 0 ) + { + pLabel->m_pIcon->setVisible( true ); + pLabel->m_pIcon->setParent( pLabel->m_pBackground ); + } + + pLabel->m_clientindex = -1; + } + + m_pLocalLabel = new ImagePanel(NULL); + + m_bInSquelchMode = false; + + m_pHelper = pHelper; + m_pParentPanel = pParentPanel; + gHUD.AddHudElem(this); + m_iFlags = HUD_ACTIVE; + HOOK_MESSAGE(VoiceMask); + HOOK_MESSAGE(ReqState); + + // Cache the game directory for use when we shut down + const char *pchGameDirT = gEngfuncs.pfnGetGameDirectory(); + m_pchGameDir = (char *)malloc(strlen(pchGameDirT) + 1); + strcpy(m_pchGameDir, pchGameDirT); + + return 1; +} + + +int CVoiceStatus::VidInit() +{ + FreeBitmaps(); + + + if( (m_pLocalBitmap = vgui_LoadTGA("gfx/vgui/icntlk_pl.tga")) != 0 ) + { + m_pLocalBitmap->setColor(Color(255,255,255,135)); + } + + if( (m_pAckBitmap = vgui_LoadTGA("gfx/vgui/icntlk_sv.tga")) != 0 ) + { + m_pAckBitmap->setColor(Color(255,255,255,135)); // Give just a tiny bit of translucency so software draws correctly. + } + + m_pLocalLabel->setImage( m_pLocalBitmap ); + m_pLocalLabel->setVisible( false ); + + + if( (m_pSpeakerLabelIcon = vgui_LoadTGANoInvertAlpha("gfx/vgui/speaker4.tga" )) != 0 ) + m_pSpeakerLabelIcon->setColor( Color(255,255,255,1) ); // Give just a tiny bit of translucency so software draws correctly. + + if ((m_pScoreboardNeverSpoken = vgui_LoadTGANoInvertAlpha("gfx/vgui/640_speaker1.tga")) != 0) + m_pScoreboardNeverSpoken->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. + + if((m_pScoreboardNotSpeaking = vgui_LoadTGANoInvertAlpha("gfx/vgui/640_speaker2.tga")) != 0) + m_pScoreboardNotSpeaking->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. + + if((m_pScoreboardSpeaking = vgui_LoadTGANoInvertAlpha("gfx/vgui/640_speaker3.tga")) != 0) + m_pScoreboardSpeaking->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. + + if((m_pScoreboardSpeaking2 = vgui_LoadTGANoInvertAlpha("gfx/vgui/640_speaker4.tga")) != 0) + m_pScoreboardSpeaking2->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. + + if((m_pScoreboardSquelch = vgui_LoadTGA("gfx/vgui/icntlk_squelch.tga")) != 0) + m_pScoreboardSquelch->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. + + if((m_pScoreboardBanned = vgui_LoadTGA("gfx/vgui/640_voiceblocked.tga")) != 0) + m_pScoreboardBanned->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. + + // Figure out the voice head model height. + m_VoiceHeadModelHeight = 45; + char *pFile = (char *)gEngfuncs.COM_LoadFile("scripts/voicemodel.txt", 5, NULL); + if(pFile) + { + char token[4096]; + gEngfuncs.COM_ParseFile(pFile, token); + if(token[0] >= '0' && token[0] <= '9') + { + m_VoiceHeadModelHeight = (float)atof(token); + } + + gEngfuncs.COM_FreeFile(pFile); + } + + m_VoiceHeadModel = gEngfuncs.pfnSPR_Load("sprites/voiceicon.spr"); + return TRUE; +} + + +void CVoiceStatus::Frame(double frametime) +{ + // check server banned players once per second + if(gEngfuncs.GetClientTime() - m_LastUpdateServerState > 1) + { + UpdateServerState(false); + } + + m_BlinkTimer += frametime; + + // Update speaker labels. + if( m_pHelper->CanShowSpeakerLabels() ) + { + for( int i=0; i < MAX_VOICE_SPEAKERS; i++ ) + m_Labels[i].m_pBackground->setVisible( m_Labels[i].m_clientindex != -1 ); + } + else + { + for( int i=0; i < MAX_VOICE_SPEAKERS; i++ ) + m_Labels[i].m_pBackground->setVisible( false ); + } + + for(int i=0; i < VOICE_MAX_PLAYERS; i++) + UpdateBanButton(i); +} + + +void CVoiceStatus::CreateEntities() +{ + if(!m_VoiceHeadModel) + return; + + cl_entity_t *localPlayer = gEngfuncs.GetLocalPlayer(); + + int iOutModel = 0; + for(int i=0; i < VOICE_MAX_PLAYERS; i++) + { + if(!m_VoicePlayers[i]) + continue; + + cl_entity_s *pClient = gEngfuncs.GetEntityByIndex(i+1); + + // Don't show an icon if the player is not in our PVS. + if(!pClient || pClient->curstate.messagenum < localPlayer->curstate.messagenum) + continue; + + // Don't show an icon for dead or spectating players (ie: invisible entities). + if(pClient->curstate.effects & EF_NODRAW) + continue; + + // Don't show an icon for the local player unless we're in thirdperson mode. + if(pClient == localPlayer && !cam_thirdperson) + continue; + + cl_entity_s *pEnt = &m_VoiceHeadModels[iOutModel]; + ++iOutModel; + + memset(pEnt, 0, sizeof(*pEnt)); + + pEnt->curstate.rendermode = kRenderTransAdd; + pEnt->curstate.renderamt = 255; + pEnt->baseline.renderamt = 255; + pEnt->curstate.renderfx = kRenderFxNoDissipation; + pEnt->curstate.framerate = 1; + pEnt->curstate.frame = 0; + pEnt->model = (struct model_s*)gEngfuncs.GetSpritePointer(m_VoiceHeadModel); + pEnt->angles[0] = pEnt->angles[1] = pEnt->angles[2] = 0; + pEnt->curstate.scale = 0.5f; + + pEnt->origin[0] = pEnt->origin[1] = 0; + pEnt->origin[2] = 45; + + VectorAdd(pEnt->origin, pClient->origin, pEnt->origin); + + // Tell the engine. + gEngfuncs.CL_CreateVisibleEntity(ET_NORMAL, pEnt); + } +} + + +void CVoiceStatus::UpdateSpeakerStatus( int entindex, qboolean bTalking ) +{ + cvar_t *pVoiceLoopback = NULL; + + if ( !m_pParentPanel || !*m_pParentPanel ) + { + return; + } + + if ( gEngfuncs.pfnGetCvarFloat( "voice_clientdebug" ) ) + { + char msg[256]; + _snprintf( msg, sizeof( msg ), "CVoiceStatus::UpdateSpeakerStatus: ent %d talking = %d\n", entindex, bTalking ); + gEngfuncs.pfnConsolePrint( msg ); + } + + int iLocalPlayerIndex = gEngfuncs.GetLocalPlayer()->index; + + // Is it the local player talking? + if ( entindex == -1 ) + { + m_bTalking = !!bTalking; + if( bTalking ) + { + // Enable voice for them automatically if they try to talk. + gEngfuncs.pfnClientCmd( "voice_modenable 1" ); + } + + // now set the player index to the correct index for the local player + // this will allow us to have the local player's icon flash in the scoreboard + entindex = iLocalPlayerIndex; + + pVoiceLoopback = gEngfuncs.pfnGetCvarPointer( "voice_loopback" ); + } + else if ( entindex == -2 ) + { + m_bServerAcked = !!bTalking; + } + + if ( entindex >= 0 && entindex <= VOICE_MAX_PLAYERS ) + { + int iClient = entindex - 1; + if ( iClient < 0 ) + { + return; + } + + CVoiceLabel *pLabel = FindVoiceLabel( iClient ); + if ( bTalking ) + { + m_VoicePlayers[iClient] = true; + m_VoiceEnabledPlayers[iClient] = true; + + // If we don't have a label for this guy yet, then create one. + if ( !pLabel ) + { + // if this isn't the local player (unless they have voice_loopback on) + if ( ( entindex != iLocalPlayerIndex ) || ( pVoiceLoopback && pVoiceLoopback->value ) ) + { + if ( (pLabel = GetFreeVoiceLabel()) != 0 ) + { + // Get the name from the engine. + hud_player_info_t info; + memset( &info, 0, sizeof( info ) ); + gEngfuncs.pfnGetPlayerInfo( entindex, &info ); + + char paddedName[512]; + _snprintf( paddedName, sizeof( paddedName ), "%s ", info.name ); + + int color[3]; + m_pHelper->GetPlayerTextColor( entindex, color ); + + if ( pLabel->m_pBackground ) + { + pLabel->m_pBackground->setBgColor( color[0], color[1], color[2], 135 ); + pLabel->m_pBackground->setParent( *m_pParentPanel ); + pLabel->m_pBackground->setVisible( m_pHelper->CanShowSpeakerLabels() ); + } + + if ( pLabel->m_pLabel ) + { + pLabel->m_pLabel->setFgColor( 255, 255, 255, 0 ); + pLabel->m_pLabel->setBgColor( 0, 0, 0, 255 ); + pLabel->m_pLabel->setText( "%s", paddedName ); + } + + pLabel->m_clientindex = iClient; + } + } + } + } + else + { + m_VoicePlayers[iClient] = false; + + // If we have a label for this guy, kill it. + if ( pLabel ) + { + pLabel->m_pBackground->setVisible( false ); + pLabel->m_clientindex = -1; + } + } + } + + RepositionLabels(); +} + + +void CVoiceStatus::UpdateServerState(bool bForce) +{ + // Can't do anything when we're not in a level. + char const *pLevelName = gEngfuncs.pfnGetLevelName(); + if( pLevelName[0] == 0 ) + { + if( gEngfuncs.pfnGetCvarFloat("voice_clientdebug") ) + { + gEngfuncs.pfnConsolePrint( "CVoiceStatus::UpdateServerState: pLevelName[0]==0\n" ); + } + + return; + } + + int bCVarModEnable = !!gEngfuncs.pfnGetCvarFloat("voice_modenable"); + if(bForce || m_bServerModEnable != bCVarModEnable) + { + m_bServerModEnable = bCVarModEnable; + + char str[256]; + _snprintf(str, sizeof(str), "VModEnable %d", m_bServerModEnable); + ServerCmd(str); + + if(gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + { + char msg[256]; + sprintf(msg, "CVoiceStatus::UpdateServerState: Sending '%s'\n", str); + gEngfuncs.pfnConsolePrint(msg); + } + } + + char str[2048]; + sprintf(str, "vban"); + bool bChange = false; + + for(unsigned long dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++) + { + unsigned int serverBanMask = 0; + unsigned int banMask = 0; + for(unsigned int i=0; i < 32; i++) + { + char playerID[16]; + if(!gEngfuncs.GetPlayerUniqueID(i+1, playerID)) + continue; + + if(m_BanMgr.GetPlayerBan(playerID)) + banMask |= 1 << i; + + if(m_ServerBannedPlayers[dw*32 + i]) + serverBanMask |= 1 << i; + } + + if(serverBanMask != banMask) + bChange = true; + + // Ok, the server needs to be updated. + char numStr[512]; + sprintf(numStr, " %x", banMask); + strcat(str, numStr); + } + + if(bChange || bForce) + { + if(gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + { + char msg[256]; + sprintf(msg, "CVoiceStatus::UpdateServerState: Sending '%s'\n", str); + gEngfuncs.pfnConsolePrint(msg); + } + + gEngfuncs.pfnServerCmdUnreliable(str); // Tell the server.. + } + else + { + if (gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + { + gEngfuncs.pfnConsolePrint( "CVoiceStatus::UpdateServerState: no change\n" ); + } + } + + m_LastUpdateServerState = gEngfuncs.GetClientTime(); +} + +void CVoiceStatus::UpdateSpeakerImage(Label *pLabel, int iPlayer) +{ + m_pBanButtons[iPlayer-1] = pLabel; + UpdateBanButton(iPlayer-1); +} + +void CVoiceStatus::UpdateBanButton(int iClient) +{ + Label *pPanel = m_pBanButtons[iClient]; + + if (!pPanel) + return; + + char playerID[16]; + extern bool HACK_GetPlayerUniqueID( int iPlayer, char playerID[16] ); + if(!HACK_GetPlayerUniqueID(iClient+1, playerID)) + return; + + // Figure out if it's blinking or not. + bool bBlink = fmod(m_BlinkTimer, SCOREBOARD_BLINK_FREQUENCY*2) < SCOREBOARD_BLINK_FREQUENCY; + bool bTalking = !!m_VoicePlayers[iClient]; + bool bBanned = m_BanMgr.GetPlayerBan(playerID); + bool bNeverSpoken = !m_VoiceEnabledPlayers[iClient]; + + // Get the appropriate image to display on the panel. + if (bBanned) + { + pPanel->setImage(m_pScoreboardBanned); + } + else if (bTalking) + { + if (bBlink) + { + pPanel->setImage(m_pScoreboardSpeaking2); + } + else + { + pPanel->setImage(m_pScoreboardSpeaking); + } + pPanel->setFgColor(255, 170, 0, 1); + } + else if (bNeverSpoken) + { + pPanel->setImage(m_pScoreboardNeverSpoken); + pPanel->setFgColor(100, 100, 100, 1); + } + else + { + pPanel->setImage(m_pScoreboardNotSpeaking); + } +} + + +void CVoiceStatus::HandleVoiceMaskMsg(int iSize, void *pbuf) +{ + BEGIN_READ( pbuf, iSize ); + + unsigned int dw; + for(dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++) + { + m_AudiblePlayers.SetDWord(dw, (unsigned long)READ_LONG()); + m_ServerBannedPlayers.SetDWord(dw, (unsigned long)READ_LONG()); + + if(gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + { + char str[256]; + gEngfuncs.pfnConsolePrint("CVoiceStatus::HandleVoiceMaskMsg\n"); + + sprintf(str, " - m_AudiblePlayers[%d] = %lu\n", dw, m_AudiblePlayers.GetDWord(dw)); + gEngfuncs.pfnConsolePrint(str); + + sprintf(str, " - m_ServerBannedPlayers[%d] = %lu\n", dw, m_ServerBannedPlayers.GetDWord(dw)); + gEngfuncs.pfnConsolePrint(str); + } + } + + m_bServerModEnable = READ_BYTE(); +} + +void CVoiceStatus::HandleReqStateMsg(int iSize, void *pbuf) +{ + if(gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + { + gEngfuncs.pfnConsolePrint("CVoiceStatus::HandleReqStateMsg\n"); + } + + UpdateServerState(true); +} + +void CVoiceStatus::StartSquelchMode() +{ + if(m_bInSquelchMode) + return; + + m_bInSquelchMode = true; + m_pHelper->UpdateCursorState(); +} + +void CVoiceStatus::StopSquelchMode() +{ + m_bInSquelchMode = false; + m_pHelper->UpdateCursorState(); +} + +bool CVoiceStatus::IsInSquelchMode() +{ + return m_bInSquelchMode; +} + +CVoiceLabel* CVoiceStatus::FindVoiceLabel(int clientindex) +{ + for(int i=0; i < MAX_VOICE_SPEAKERS; i++) + { + if(m_Labels[i].m_clientindex == clientindex) + return &m_Labels[i]; + } + + return NULL; +} + + +CVoiceLabel* CVoiceStatus::GetFreeVoiceLabel() +{ + return FindVoiceLabel(-1); +} + + +void CVoiceStatus::RepositionLabels() +{ + // find starting position to draw from, along right-hand side of screen + int y = ScreenHeight / 2; + + int iconWide = 8, iconTall = 8; + if( m_pSpeakerLabelIcon ) + { + m_pSpeakerLabelIcon->getSize( iconWide, iconTall ); + } + + // Reposition active labels. + for(int i = 0; i < MAX_VOICE_SPEAKERS; i++) + { + CVoiceLabel *pLabel = &m_Labels[i]; + + if( pLabel->m_clientindex == -1 || !pLabel->m_pLabel ) + { + if( pLabel->m_pBackground ) + pLabel->m_pBackground->setVisible( false ); + + continue; + } + + int textWide, textTall; + pLabel->m_pLabel->getContentSize( textWide, textTall ); + + // Don't let it stretch too far across their screen. + if( textWide > (ScreenWidth*2)/3 ) + textWide = (ScreenWidth*2)/3; + + // Setup the background label to fit everything in. + int border = 2; + int bgWide = textWide + iconWide + border*3; + int bgTall = Q_max( textTall, iconTall ) + border*2; + pLabel->m_pBackground->setBounds( ScreenWidth - bgWide - 8, y, bgWide, bgTall ); + + // Put the text at the left. + pLabel->m_pLabel->setBounds( border, (bgTall - textTall) / 2, textWide, textTall ); + + // Put the icon at the right. + int iconLeft = border + textWide + border; + int iconTop = (bgTall - iconTall) / 2; + if( pLabel->m_pIcon ) + { + pLabel->m_pIcon->setImage( m_pSpeakerLabelIcon ); + pLabel->m_pIcon->setBounds( iconLeft, iconTop, iconWide, iconTall ); + } + + y += bgTall + 2; + } + + if( m_pLocalBitmap && m_pAckBitmap && m_pLocalLabel && (m_bTalking || m_bServerAcked) ) + { + m_pLocalLabel->setParent(*m_pParentPanel); + m_pLocalLabel->setVisible( true ); + + if( m_bServerAcked && !!gEngfuncs.pfnGetCvarFloat("voice_clientdebug") ) + m_pLocalLabel->setImage( m_pAckBitmap ); + else + m_pLocalLabel->setImage( m_pLocalBitmap ); + + int sizeX, sizeY; + m_pLocalBitmap->getSize(sizeX, sizeY); + + int local_xPos = ScreenWidth - sizeX - 10; + int local_yPos = m_pHelper->GetAckIconHeight() - sizeY; + + m_pLocalLabel->setPos( local_xPos, local_yPos ); + } + else + { + m_pLocalLabel->setVisible( false ); + } +} + + +void CVoiceStatus::FreeBitmaps() +{ + // Delete all the images we have loaded. + delete m_pLocalBitmap; + m_pLocalBitmap = NULL; + + delete m_pAckBitmap; + m_pAckBitmap = NULL; + + delete m_pSpeakerLabelIcon; + m_pSpeakerLabelIcon = NULL; + + delete m_pScoreboardNeverSpoken; + m_pScoreboardNeverSpoken = NULL; + + delete m_pScoreboardNotSpeaking; + m_pScoreboardNotSpeaking = NULL; + + delete m_pScoreboardSpeaking; + m_pScoreboardSpeaking = NULL; + + delete m_pScoreboardSpeaking2; + m_pScoreboardSpeaking2 = NULL; + + delete m_pScoreboardSquelch; + m_pScoreboardSquelch = NULL; + + delete m_pScoreboardBanned; + m_pScoreboardBanned = NULL; + + // Clear references to the images in panels. + for(int i=0; i < VOICE_MAX_PLAYERS; i++) + { + if (m_pBanButtons[i]) + { + m_pBanButtons[i]->setImage(NULL); + } + } + + if(m_pLocalLabel) + m_pLocalLabel->setImage(NULL); +} + +//----------------------------------------------------------------------------- +// Purpose: returns true if the target client has been banned +// Input : playerID - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CVoiceStatus::IsPlayerBlocked(int iPlayer) +{ + char playerID[16]; + if (!gEngfuncs.GetPlayerUniqueID(iPlayer, playerID)) + return false; + + return m_BanMgr.GetPlayerBan(playerID); +} + +//----------------------------------------------------------------------------- +// Purpose: returns true if the player can't hear the other client due to game rules (eg. the other team) +// Input : playerID - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CVoiceStatus::IsPlayerAudible(int iPlayer) +{ + return !!m_AudiblePlayers[iPlayer-1]; +} + +//----------------------------------------------------------------------------- +// Purpose: blocks/unblocks the target client from being heard +// Input : playerID - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +void CVoiceStatus::SetPlayerBlockedState(int iPlayer, bool blocked) +{ + if (gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + { + gEngfuncs.pfnConsolePrint( "CVoiceStatus::SetPlayerBlockedState part 1\n" ); + } + + char playerID[16]; + if (!gEngfuncs.GetPlayerUniqueID(iPlayer, playerID)) + return; + + if (gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + { + gEngfuncs.pfnConsolePrint( "CVoiceStatus::SetPlayerBlockedState part 2\n" ); + } + + // Squelch or (try to) unsquelch this player. + if (gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + { + char str[256]; + sprintf(str, "CVoiceStatus::SetPlayerBlockedState: setting player %d ban to %d\n", iPlayer, !m_BanMgr.GetPlayerBan(playerID)); + gEngfuncs.pfnConsolePrint(str); + } + + m_BanMgr.SetPlayerBan( playerID, blocked ); + UpdateServerState(false); +} diff --git a/cl_dll/voice_status.h b/cl_dll/voice_status.h new file mode 100644 index 00000000..48f00db2 --- /dev/null +++ b/cl_dll/voice_status.h @@ -0,0 +1,228 @@ +//========= Copyright (c) 1996-2001, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef VOICE_STATUS_H +#define VOICE_STATUS_H +#pragma once + + +#include "VGUI_Label.h" +#include "VGUI_LineBorder.h" +#include "VGUI_ImagePanel.h" +#include "VGUI_BitmapTGA.h" +#include "VGUI_InputSignal.h" +#include "VGUI_Button.h" +#include "voice_common.h" +#include "cl_entity.h" +#include "voice_banmgr.h" +#include "vgui_checkbutton2.h" +#include "vgui_defaultinputsignal.h" + + +class CVoiceStatus; + + +class CVoiceLabel +{ +public: + vgui::Label *m_pLabel; + vgui::Label *m_pBackground; + vgui::ImagePanel *m_pIcon; // Voice icon next to player name. + int m_clientindex; // Client index of the speaker. -1 if this label isn't being used. +}; + + +// This is provided by each mod to access data that may not be the same across mods. +class IVoiceStatusHelper +{ +public: + virtual ~IVoiceStatusHelper() {} + + // Get RGB color for voice status text about this player. + virtual void GetPlayerTextColor(int entindex, int color[3]) = 0; + + // Force it to update the cursor state. + virtual void UpdateCursorState() = 0; + + // Return the height above the bottom that the voice ack icons should be drawn at. + virtual int GetAckIconHeight() = 0; + + // Return true if the voice manager is allowed to show speaker labels + // (mods usually return false when the scoreboard is up). + virtual bool CanShowSpeakerLabels() = 0; +}; + +//----------------------------------------------------------------------------- +// Purpose: Holds a color for the shared image +//----------------------------------------------------------------------------- +class VoiceImagePanel : public vgui::ImagePanel +{ + virtual void paintBackground() + { + if (_image!=null) + { + vgui::Color col; + getFgColor(col); + _image->setColor(col); + _image->doPaint(this); + } + } +}; + + +class CVoiceStatus : public CHudBase, public vgui::CDefaultInputSignal +{ +public: + CVoiceStatus(); + virtual ~CVoiceStatus(); + +// CHudBase overrides. +public: + + // Initialize the cl_dll's voice manager. + virtual int Init( + IVoiceStatusHelper *m_pHelper, + vgui::Panel **pParentPanel); + + // ackPosition is the bottom position of where CVoiceStatus will draw the voice acknowledgement labels. + virtual int VidInit(); + + +public: + + // Call from HUD_Frame each frame. + void Frame(double frametime); + + // Called when a player starts or stops talking. + // entindex is -1 to represent the local client talking (before the data comes back from the server). + // When the server acknowledges that the local client is talking, then entindex will be gEngfuncs.GetLocalPlayer(). + // entindex is -2 to represent the local client's voice being acked by the server. + void UpdateSpeakerStatus(int entindex, qboolean bTalking); + + // sets the correct image in the label for the player + void UpdateSpeakerImage(vgui::Label *pLabel, int iPlayer); + + // Call from the HUD_CreateEntities function so it can add sprites above player heads. + void CreateEntities(); + + // Called when the server registers a change to who this client can hear. + void HandleVoiceMaskMsg(int iSize, void *pbuf); + + // The server sends this message initially to tell the client to send their state. + void HandleReqStateMsg(int iSize, void *pbuf); + + +// Squelch mode functions. +public: + + // When you enter squelch mode, pass in + void StartSquelchMode(); + void StopSquelchMode(); + bool IsInSquelchMode(); + + // returns true if the target client has been banned + // playerIndex is of range 1..maxplayers + bool IsPlayerBlocked(int iPlayerIndex); + + // returns false if the player can't hear the other client due to game rules (eg. the other team) + bool IsPlayerAudible(int iPlayerIndex); + + // blocks the target client from being heard + void SetPlayerBlockedState(int iPlayerIndex, bool blocked); + +public: + + CVoiceLabel* FindVoiceLabel(int clientindex); // Find a CVoiceLabel representing the specified speaker. + // Returns NULL if none. + // entindex can be -1 if you want a currently-unused voice label. + CVoiceLabel* GetFreeVoiceLabel(); // Get an unused voice label. Returns NULL if none. + + void RepositionLabels(); + + void FreeBitmaps(); + + void UpdateServerState(bool bForce); + + // Update the button artwork to reflect the client's current state. + void UpdateBanButton(int iClient); + + +public: + + enum {MAX_VOICE_SPEAKERS=7}; + + float m_LastUpdateServerState; // Last time we called this function. + int m_bServerModEnable; // What we've sent to the server about our "voice_modenable" cvar. + + vgui::Panel **m_pParentPanel; + CPlayerBitVec m_VoicePlayers; // Who is currently talking. Indexed by client index. + + // This is the gamerules-defined list of players that you can hear. It is based on what teams people are on + // and is totally separate from the ban list. Indexed by client index. + CPlayerBitVec m_AudiblePlayers; + + // Players who have spoken at least once in the game so far + CPlayerBitVec m_VoiceEnabledPlayers; + + // This is who the server THINKS we have banned (it can become incorrect when a new player arrives on the server). + // It is checked periodically, and the server is told to squelch or unsquelch the appropriate players. + CPlayerBitVec m_ServerBannedPlayers; + + cl_entity_s m_VoiceHeadModels[VOICE_MAX_PLAYERS]; // These aren't necessarily in the order of players. They are just + // a place for it to put data in during CreateEntities. + + IVoiceStatusHelper *m_pHelper; // Each mod provides an implementation of this. + + + // Scoreboard icons. + double m_BlinkTimer; // Blink scoreboard icons.. + vgui::BitmapTGA *m_pScoreboardNeverSpoken; + vgui::BitmapTGA *m_pScoreboardNotSpeaking; + vgui::BitmapTGA *m_pScoreboardSpeaking; + vgui::BitmapTGA *m_pScoreboardSpeaking2; + vgui::BitmapTGA *m_pScoreboardSquelch; + vgui::BitmapTGA *m_pScoreboardBanned; + + vgui::Label *m_pBanButtons[VOICE_MAX_PLAYERS]; // scoreboard buttons. + + // Squelch mode stuff. + bool m_bInSquelchMode; + + HSPRITE m_VoiceHeadModel; // Voice head model (goes above players who are speaking). + float m_VoiceHeadModelHeight; // Height above their head to place the model. + + vgui::Image *m_pSpeakerLabelIcon; // Icon next to speaker labels. + + // Lower-right icons telling when the local player is talking.. + vgui::BitmapTGA *m_pLocalBitmap; // Represents the local client talking. + vgui::BitmapTGA *m_pAckBitmap; // Represents the server ack'ing the client talking. + vgui::ImagePanel *m_pLocalLabel; // Represents the local client talking. + + bool m_bTalking; // Set to true when the client thinks it's talking. + bool m_bServerAcked; // Set to true when the server knows the client is talking. + +public: + + CVoiceBanMgr m_BanMgr; // Tracks which users we have squelched and don't want to hear. + +public: + + bool m_bBanMgrInitialized; + + // Labels telling who is speaking. + CVoiceLabel m_Labels[MAX_VOICE_SPEAKERS]; + + // Cache the game directory for use when we shut down + char * m_pchGameDir; +}; + + +// Get the (global) voice manager. +CVoiceStatus* GetClientVoiceMgr(); + + +#endif // VOICE_STATUS_H diff --git a/common/winsani_in.h b/common/winsani_in.h new file mode 100644 index 00000000..d8c85271 --- /dev/null +++ b/common/winsani_in.h @@ -0,0 +1,7 @@ +#if _MSC_VER >= 1500 // MSVC++ 9.0 (Visual Studio 2008) +#pragma push_macro("ARRAYSIZE") +#ifdef ARRAYSIZE +#undef ARRAYSIZE +#endif +#define HSPRITE WINDOWS_HSPRITE +#endif diff --git a/common/winsani_out.h b/common/winsani_out.h new file mode 100644 index 00000000..27269500 --- /dev/null +++ b/common/winsani_out.h @@ -0,0 +1,4 @@ +#if _MSC_VER >= 1500 // MSVC++ 9.0 (Visual Studio 2008) +#undef HSPRITE +#pragma pop_macro("ARRAYSIZE") +#endif diff --git a/game_shared/bitvec.h b/game_shared/bitvec.h index bb6d8fb7..d77796fb 100644 --- a/game_shared/bitvec.h +++ b/game_shared/bitvec.h @@ -1,10 +1,9 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +//========= Copyright � 1996-2002, Valve LLC, All rights reserved. ============ // // Purpose: // // $NoKeywords: $ //============================================================================= -#pragma once #if !defined(BITVEC_H) #define BITVEC_H @@ -155,3 +154,4 @@ inline void CBitVec::SetDWord( int i, unsigned long val ) m_DWords[i] = val; } #endif // BITVEC_H + diff --git a/game_shared/vgui_checkbutton2.cpp b/game_shared/vgui_checkbutton2.cpp index b998a41d..bb67f31a 100644 --- a/game_shared/vgui_checkbutton2.cpp +++ b/game_shared/vgui_checkbutton2.cpp @@ -10,57 +10,50 @@ #include "vgui_checkbutton2.h" #include "vgui_loadtga.h" - #define EXTRA_X 5 - using namespace vgui; - - CCheckButton2::CCheckButton2() : - m_Label(""), - m_pChecked(NULL), - m_pUnchecked(NULL), - m_pHandler(NULL), - m_CheckboxPanel(NULL) + m_Label( "" ), + m_pChecked( NULL ), + m_pUnchecked( NULL ), + m_pHandler( NULL ), + m_CheckboxPanel( NULL ) { m_bOwnImages = false; m_bChecked = false; m_pChecked = m_pUnchecked = NULL; m_bCheckboxLeft = true; - m_Label.setParent(this); - m_Label.setFgColor(255,255,255,0); - m_Label.setBgColor(0,0,0,255); // background is not drawn and foreground is white - m_Label.addInputSignal(this); + m_Label.setParent( this ); + m_Label.setFgColor( 255, 255, 255, 0 ); + m_Label.setBgColor( 0, 0, 0, 255 ); // background is not drawn and foreground is white + m_Label.addInputSignal( this ); - m_CheckboxPanel.setParent(this); - m_CheckboxPanel.addInputSignal(this); + m_CheckboxPanel.setParent( this ); + m_CheckboxPanel.addInputSignal( this ); - setPaintBackgroundEnabled(false); + setPaintBackgroundEnabled( false ); } - CCheckButton2::~CCheckButton2() { DeleteImages(); } - -void CCheckButton2::SetImages(char const *pChecked, char const *pUnchecked) +void CCheckButton2::SetImages( char const *pChecked, char const *pUnchecked ) { DeleteImages(); - - m_pChecked = vgui_LoadTGA(pChecked); - m_pUnchecked = vgui_LoadTGA(pUnchecked); + + m_pChecked = vgui_LoadTGA( pChecked ); + m_pUnchecked = vgui_LoadTGA( pUnchecked ); m_bOwnImages = true; SetupControls(); } - -void CCheckButton2::SetImages(Image *pChecked, Image *pUnchecked) +void CCheckButton2::SetImages( Image *pChecked, Image *pUnchecked ) { DeleteImages(); @@ -71,10 +64,9 @@ void CCheckButton2::SetImages(Image *pChecked, Image *pUnchecked) SetupControls(); } - void CCheckButton2::DeleteImages() { - if(m_bOwnImages) + if( m_bOwnImages ) { delete m_pChecked; delete m_pUnchecked; @@ -87,71 +79,62 @@ void CCheckButton2::DeleteImages() SetupControls(); } - -void CCheckButton2::SetCheckboxLeft(bool bLeftAlign) +void CCheckButton2::SetCheckboxLeft( bool bLeftAlign ) { m_bCheckboxLeft = bLeftAlign; SetupControls(); } - bool CCheckButton2::GetCheckboxLeft() { return m_bCheckboxLeft; } - -void CCheckButton2::SetText(char const *pText, ...) +void CCheckButton2::SetText( char const *pText, ... ) { char str[512]; - - va_list marker; - va_start(marker, pText); - _vsnprintf(str, sizeof(str), pText, marker); - va_end(marker); - m_Label.setText(str); + va_list marker; + va_start( marker, pText ); + _vsnprintf( str, sizeof( str ), pText, marker ); + va_end( marker ); + + m_Label.setText( str ); SetupControls(); } - -void CCheckButton2::SetTextColor(int r, int g, int b, int a) +void CCheckButton2::SetTextColor( int r, int g, int b, int a ) { - m_Label.setFgColor(r, g, b, a); + m_Label.setFgColor( r, g, b, a ); repaint(); } - -void CCheckButton2::SetHandler(ICheckButton2Handler *pHandler) +void CCheckButton2::SetHandler( ICheckButton2Handler *pHandler ) { m_pHandler = pHandler; } - bool CCheckButton2::IsChecked() { return m_bChecked; } - -void CCheckButton2::SetChecked(bool bChecked) +void CCheckButton2::SetChecked( bool bChecked ) { m_bChecked = bChecked; SetupControls(); } - -void CCheckButton2::internalMousePressed(MouseCode code) +void CCheckButton2::internalMousePressed( MouseCode code ) { m_bChecked = !m_bChecked; - if(m_pHandler) - m_pHandler->StateChanged(this); + if( m_pHandler ) + m_pHandler->StateChanged( this ); SetupControls(); } - void CCheckButton2::SetupControls() { // Initialize the checkbutton bitmap. @@ -161,37 +144,28 @@ void CCheckButton2::SetupControls() int controlSizes[2][2]; controlSizes[0][0] = controlSizes[0][1] = 0; - if(pBitmap) - pBitmap->getSize(controlSizes[0][0], controlSizes[0][1]); - - m_CheckboxPanel.setImage(pBitmap); - m_CheckboxPanel.setSize(controlSizes[0][0], controlSizes[0][1]); + if( pBitmap ) + pBitmap->getSize( controlSizes[0][0], controlSizes[0][1] ); + + m_CheckboxPanel.setImage( pBitmap ); + m_CheckboxPanel.setSize( controlSizes[0][0], controlSizes[0][1] ); - // Get the label's size. - m_Label.getSize(controlSizes[1][0], controlSizes[1][1]); - m_Label.setContentAlignment(Label::a_west); - + m_Label.getSize( controlSizes[1][0], controlSizes[1][1] ); + m_Label.setContentAlignment( Label::a_west ); // Position the controls. int iLeftControl = !m_bCheckboxLeft; int iBiggestY = controlSizes[0][1] > controlSizes[1][0] ? 0 : 1; - controls[iLeftControl]->setPos(0, (controlSizes[iBiggestY][1] - controlSizes[iLeftControl][1]) / 2); - controls[!iLeftControl]->setPos(controlSizes[iLeftControl][0] + EXTRA_X, (controlSizes[iBiggestY][1] - controlSizes[!iLeftControl][1]) / 2); + controls[iLeftControl]->setPos( 0, ( controlSizes[iBiggestY][1] - controlSizes[iLeftControl][1] ) / 2 ); + controls[!iLeftControl]->setPos( controlSizes[iLeftControl][0] + EXTRA_X, ( controlSizes[iBiggestY][1] - controlSizes[!iLeftControl][1]) / 2 ); - // Fit this control to the sizes of the subcontrols. - setSize(controlSizes[0][0] + controlSizes[1][0] + EXTRA_X, (controlSizes[0][1] > controlSizes[1][1]) ? controlSizes[0][1] : controlSizes[1][1]); + setSize(controlSizes[0][0] + controlSizes[1][0] + EXTRA_X, ( controlSizes[0][1] > controlSizes[1][1]) ? controlSizes[0][1] : controlSizes[1][1] ); repaint(); } - -void CCheckButton2::mousePressed(MouseCode code, Panel *panel) +void CCheckButton2::mousePressed( MouseCode code, Panel *panel ) { - internalMousePressed(code); + internalMousePressed( code ); } - - - - - diff --git a/game_shared/vgui_checkbutton2.h b/game_shared/vgui_checkbutton2.h index 7267abe2..d04fc182 100644 --- a/game_shared/vgui_checkbutton2.h +++ b/game_shared/vgui_checkbutton2.h @@ -1,32 +1,29 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +//========= Copyright � 1996-2002, Valve LLC, All rights reserved. ============ // // Purpose: // // $NoKeywords: $ //============================================================================= -#pragma once -#if !defined(VGUI_CHECKBUTTON2_H) + +#ifndef VGUI_CHECKBUTTON2_H #define VGUI_CHECKBUTTON2_H +#ifdef _WIN32 +#pragma once +#endif -#include "vgui_label.h" -#include "vgui_imagepanel.h" +#include "VGUI_Label.h" +#include "VGUI_ImagePanel.h" #include "vgui_defaultinputsignal.h" - namespace vgui { - - class CCheckButton2; - - class ICheckButton2Handler { public: - virtual void StateChanged(CCheckButton2 *pButton) = 0; + virtual void StateChanged( CCheckButton2 *pButton ) = 0; }; - // VGUI checkbox class. // - Provides access to the checkbox images. // - Provides an easy callback mechanism for state changes. @@ -34,47 +31,37 @@ public: class CCheckButton2 : public Panel, public CDefaultInputSignal { public: + CCheckButton2(); + ~CCheckButton2(); - CCheckButton2(); - ~CCheckButton2(); - // Initialize the button with these. - void SetImages(char const *pChecked, char const *pUnchecked); - void SetImages(Image *pChecked, Image *pUnchecked); // If you use this, the button will never delete the images. + void SetImages( char const *pChecked, char const *pUnchecked ); + void SetImages( Image *pChecked, Image *pUnchecked ); // If you use this, the button will never delete the images. void DeleteImages(); // The checkbox can be to the left or the right of the text (default is left). - void SetCheckboxLeft(bool bLeftAlign); + void SetCheckboxLeft( bool bLeftAlign ); bool GetCheckboxLeft(); - + // Set the label text. - void SetText(char const *pText, ...); - void SetTextColor(int r, int g, int b, int a); + void SetText( char const *pText, ... ); + void SetTextColor( int r, int g, int b, int a ); // You can register for change notification here. - void SetHandler(ICheckButton2Handler *pHandler); - + void SetHandler( ICheckButton2Handler *pHandler ); + // Get/set the check state. bool IsChecked(); - void SetChecked(bool bChecked); - - + void SetChecked( bool bChecked ); // Panel overrides. -public: - - virtual void internalMousePressed(MouseCode code); - + virtual void internalMousePressed( MouseCode code ); protected: - void SetupControls(); - // InputSignal overrides. -protected: - virtual void mousePressed(MouseCode code,Panel* panel); - + virtual void mousePressed( MouseCode code, Panel *panel ); public: ICheckButton2Handler *m_pHandler; @@ -89,9 +76,5 @@ public: bool m_bChecked; }; - - } - - #endif // VGUI_CHECKBUTTON2_H diff --git a/game_shared/vgui_defaultinputsignal.h b/game_shared/vgui_defaultinputsignal.h index 25d89d70..cd55b76c 100644 --- a/game_shared/vgui_defaultinputsignal.h +++ b/game_shared/vgui_defaultinputsignal.h @@ -1,14 +1,17 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +//========= Copyright � 1996-2002, Valve LLC, All rights reserved. ============ // // Purpose: // // $NoKeywords: $ //============================================================================= -#pragma once -#if !defined(VGUI_DEFAULTINPUTSIGNAL_H) -#define VGUI_DEFAULTINPUTSIGNAL_H -#include "vgui_inputsignal.h" +#ifndef VGUI_DEFAULTINPUTSIGNAL_H +#define VGUI_DEFAULTINPUTSIGNAL_H +#ifdef _WIN32 +#pragma once +#endif + +#include "VGUI_InputSignal.h" namespace vgui { @@ -16,8 +19,8 @@ namespace vgui class CDefaultInputSignal : public vgui::InputSignal { public: - virtual void cursorMoved(int x,int y,Panel* panel) {} - virtual void cursorEntered(Panel* panel) {} + virtual void cursorMoved( int x, int y, Panel *panel ) {} + virtual void cursorEntered( Panel *panel ) {} virtual void cursorExited(Panel* panel) {} virtual void mousePressed(MouseCode code,Panel* panel) {} virtual void mouseDoublePressed(MouseCode code,Panel* panel) {} @@ -29,4 +32,6 @@ namespace vgui virtual void keyFocusTicked(Panel* panel) {} }; } + + #endif // VGUI_DEFAULTINPUTSIGNAL_H diff --git a/game_shared/vgui_grid.cpp b/game_shared/vgui_grid.cpp index 5a1af15e..f94e1cef 100644 --- a/game_shared/vgui_grid.cpp +++ b/game_shared/vgui_grid.cpp @@ -8,10 +8,8 @@ #include #include "vgui_grid.h" - using namespace vgui; - #define AssertCheck(expr, msg) \ if(!(expr))\ {\ @@ -19,12 +17,9 @@ using namespace vgui; return 0;\ } - - // ------------------------------------------------------------------------------ // // CGrid::CGridEntry. // ------------------------------------------------------------------------------ // - CGrid::CGridEntry::CGridEntry() { m_pPanel = NULL; @@ -35,47 +30,42 @@ CGrid::CGridEntry::~CGridEntry() { } - // ------------------------------------------------------------------------------ // // CGrid. // ------------------------------------------------------------------------------ // - CGrid::CGrid() { Clear(); } - CGrid::~CGrid() { Term(); } - -bool CGrid::SetDimensions(int xCols, int yRows) +bool CGrid::SetDimensions( int xCols, int yRows ) { Term(); m_GridEntries = new CGridEntry[xCols * yRows]; - m_Widths = new int[xCols*2 + yRows*2]; + m_Widths = new int[xCols * 2 + yRows * 2]; m_Heights = m_Widths + xCols; m_ColOffsets = m_Heights + yRows; m_RowOffsets = m_ColOffsets + xCols; - if(!m_GridEntries || !m_Widths) + if( !m_GridEntries || !m_Widths ) { Term(); return false; } - memset(m_Widths, 0, sizeof(int) * (xCols*2 + yRows*2)); + memset( m_Widths, 0, sizeof(int) * ( xCols * 2 + yRows * 2 ) ); m_xCols = xCols; m_yRows = yRows; return true; } - void CGrid::Term() { delete [] m_GridEntries; @@ -83,180 +73,164 @@ void CGrid::Term() Clear(); } - -Panel* CGrid::GetEntry(int x, int y) +Panel *CGrid::GetEntry( int x, int y ) { - return GridEntry(x, y)->m_pPanel; + return GridEntry( x, y )->m_pPanel; } - -bool CGrid::SetEntry(int x, int y, Panel *pPanel) +bool CGrid::SetEntry( int x, int y, Panel *pPanel ) { - CGridEntry *pEntry = GridEntry(x, y); - if(!pEntry) + CGridEntry *pEntry = GridEntry( x, y ); + if( !pEntry ) return false; - if(pEntry->m_pPanel) - pEntry->m_pPanel->setParent(NULL); + if( pEntry->m_pPanel ) + pEntry->m_pPanel->setParent( NULL ); pEntry->m_pPanel = pPanel; - if(pPanel) - pPanel->setParent(this); + if( pPanel ) + pPanel->setParent( this ); m_bDirty = true; return true; } - int CGrid::GetXSpacing() { return m_xSpacing; } - int CGrid::GetYSpacing() { return m_ySpacing; } - -void CGrid::SetSpacing(int xSpacing, int ySpacing) +void CGrid::SetSpacing( int xSpacing, int ySpacing ) { - if(xSpacing != m_xSpacing) + if( xSpacing != m_xSpacing ) { m_xSpacing = xSpacing; - CalcColOffsets(0); + CalcColOffsets( 0 ); m_bDirty = true; } - if(ySpacing != m_ySpacing) + if( ySpacing != m_ySpacing ) { m_ySpacing = ySpacing; - CalcRowOffsets(0); + CalcRowOffsets( 0 ); m_bDirty = true; } } - bool CGrid::SetColumnWidth(int iColumn, int width) { - AssertCheck(iColumn >= 0 && iColumn < m_xCols, "CGrid::SetColumnWidth : invalid location specified"); + AssertCheck( iColumn >= 0 && iColumn < m_xCols, "CGrid::SetColumnWidth : invalid location specified" ); m_Widths[iColumn] = width; - CalcColOffsets(iColumn+1); + CalcColOffsets( iColumn + 1 ); m_bDirty = true; return true; } - -bool CGrid::SetRowHeight(int iRow, int height) +bool CGrid::SetRowHeight( int iRow, int height ) { - AssertCheck(iRow >= 0 && iRow < m_yRows, "CGrid::SetColumnWidth : invalid location specified"); + AssertCheck( iRow >= 0 && iRow < m_yRows, "CGrid::SetColumnWidth : invalid location specified" ); m_Heights[iRow] = height; - CalcRowOffsets(iRow+1); + CalcRowOffsets( iRow + 1 ); m_bDirty = true; return true; } - -int CGrid::GetColumnWidth(int iColumn) +int CGrid::GetColumnWidth( int iColumn ) { - AssertCheck(iColumn >= 0 && iColumn < m_xCols, "CGrid::GetColumnWidth: invalid location specified"); + AssertCheck( iColumn >= 0 && iColumn < m_xCols, "CGrid::GetColumnWidth: invalid location specified" ); return m_Widths[iColumn]; } - -int CGrid::GetRowHeight(int iRow) +int CGrid::GetRowHeight( int iRow ) { - AssertCheck(iRow >= 0 && iRow < m_yRows, "CGrid::GetRowHeight: invalid location specified"); + AssertCheck( iRow >= 0 && iRow < m_yRows, "CGrid::GetRowHeight: invalid location specified" ); return m_Heights[iRow]; } - -int CGrid::CalcFitColumnWidth(int iColumn) +int CGrid::CalcFitColumnWidth( int iColumn ) { - AssertCheck(iColumn >= 0 && iColumn < m_xCols, "CGrid::CalcFitColumnWidth: invalid location specified"); + AssertCheck( iColumn >= 0 && iColumn < m_xCols, "CGrid::CalcFitColumnWidth: invalid location specified" ); int maxSize = 0; - for(int i=0; i < m_yRows; i++) + for( int i = 0; i < m_yRows; i++ ) { - Panel *pPanel = GridEntry(iColumn, i)->m_pPanel; - if(!pPanel) + Panel *pPanel = GridEntry( iColumn, i )->m_pPanel; + if( !pPanel ) continue; int w, h; - pPanel->getSize(w,h); - if(w > maxSize) + pPanel->getSize( w, h ); + if( w > maxSize ) maxSize = w; } return maxSize; } - -int CGrid::CalcFitRowHeight(int iRow) +int CGrid::CalcFitRowHeight( int iRow ) { - AssertCheck(iRow >= 0 && iRow < m_yRows, "CGrid::CalcFitRowHeight: invalid location specified"); + AssertCheck( iRow >= 0 && iRow < m_yRows, "CGrid::CalcFitRowHeight: invalid location specified" ); int maxSize = 0; - for(int i=0; i < m_xCols; i++) + for( int i = 0; i < m_xCols; i++ ) { - Panel *pPanel = GridEntry(i, iRow)->m_pPanel; - if(!pPanel) + Panel *pPanel = GridEntry( i, iRow )->m_pPanel; + if( !pPanel ) continue; int w, h; - pPanel->getSize(w,h); - if(h > maxSize) + pPanel->getSize( w, h ); + if( h > maxSize ) maxSize = h; } return maxSize; } - void CGrid::AutoSetRowHeights() { - for(int i=0; i < m_yRows; i++) - SetRowHeight(i, CalcFitRowHeight(i)); + for( int i = 0; i < m_yRows; i++ ) + SetRowHeight( i, CalcFitRowHeight( i ) ); } - -bool CGrid::GetEntryBox( - int col, int row, int &x, int &y, int &w, int &h) +bool CGrid::GetEntryBox( int col, int row, int &x, int &y, int &w, int &h ) { - AssertCheck(col >= 0 && col < m_xCols && row >= 0 && row < m_yRows, "CGrid::GetEntryBox: invalid location specified"); + AssertCheck( col >= 0 && col < m_xCols && row >= 0 && row < m_yRows, "CGrid::GetEntryBox: invalid location specified" ); x = m_ColOffsets[col]; w = m_Widths[col]; y = m_RowOffsets[row]; h = m_Heights[row]; - return true; + return true; } - -bool CGrid::CopyColumnWidths(CGrid *pOther) +bool CGrid::CopyColumnWidths( CGrid *pOther ) { - if(!pOther || pOther->m_xCols != m_xCols) + if( !pOther || pOther->m_xCols != m_xCols ) return false; - for(int i=0; i < m_xCols; i++) + for( int i = 0; i < m_xCols; i++ ) m_Widths[i] = pOther->m_Widths[i]; - CalcColOffsets(0); + CalcColOffsets( 0 ); m_bDirty = true; return true; } - void CGrid::RepositionContents() { - for(int x=0; x < m_xCols; x++) + for( int x = 0; x < m_xCols; x++ ) { - for(int y=0; y < m_yRows; y++) + for( int y=0; y < m_yRows; y++ ) { - Panel *pPanel = GridEntry(x,y)->m_pPanel; - if(!pPanel) + Panel *pPanel = GridEntry( x, y )->m_pPanel; + if( !pPanel ) continue; pPanel->setBounds( @@ -270,12 +244,11 @@ void CGrid::RepositionContents() m_bDirty = false; } - int CGrid::CalcDrawHeight() { - if(m_yRows > 0) + if( m_yRows > 0 ) { - return m_RowOffsets[m_yRows-1] + m_Heights[m_yRows - 1] + m_ySpacing; + return m_RowOffsets[m_yRows - 1] + m_Heights[m_yRows - 1] + m_ySpacing; } else { @@ -283,25 +256,24 @@ int CGrid::CalcDrawHeight() } } - void CGrid::paint() { - if(m_bDirty) + if( m_bDirty ) RepositionContents(); Panel::paint(); // walk the grid looking for underlined rows int x = 0, y = 0; - for (int row = 0; row < m_yRows; row++) + for( int row = 0; row < m_yRows; row++ ) { - CGridEntry *cell = GridEntry(0, row); + CGridEntry *cell = GridEntry( 0, row ); y += cell->m_pPanel->getTall() + m_ySpacing; - if (cell->m_bUnderline) + if( cell->m_bUnderline ) { - drawSetColor(cell->m_UnderlineColor[0], cell->m_UnderlineColor[1], cell->m_UnderlineColor[2], cell->m_UnderlineColor[3]); - drawFilledRect(0, y - (cell->m_iUnderlineOffset + 1), getWide(), y - cell->m_iUnderlineOffset); + drawSetColor( cell->m_UnderlineColor[0], cell->m_UnderlineColor[1], cell->m_UnderlineColor[2], cell->m_UnderlineColor[3] ); + drawFilledRect( 0, y - (cell->m_iUnderlineOffset + 1 ), getWide(), y - cell->m_iUnderlineOffset ); } } } @@ -314,11 +286,11 @@ void CGrid::paintBackground() //----------------------------------------------------------------------------- // Purpose: sets underline color for a particular row //----------------------------------------------------------------------------- -void CGrid::SetRowUnderline(int row, bool enabled, int offset, int r, int g, int b, int a) +void CGrid::SetRowUnderline( int row, bool enabled, int offset, int r, int g, int b, int a ) { - CGridEntry *cell = GridEntry(0, row); + CGridEntry *cell = GridEntry( 0, row ); cell->m_bUnderline = enabled; - if (enabled) + if( enabled ) { cell->m_iUnderlineOffset = offset; cell->m_UnderlineColor[0] = r; @@ -337,53 +309,51 @@ void CGrid::Clear() m_bDirty = false; } - CGrid::CGridEntry* CGrid::GridEntry(int x, int y) { - AssertCheck(x >= 0 && x < m_xCols && y >= 0 && y < m_yRows, "CGrid::GridEntry: invalid location specified"); - return &m_GridEntries[y*m_xCols + x]; + AssertCheck( x >= 0 && x < m_xCols && y >= 0 && y < m_yRows, "CGrid::GridEntry: invalid location specified" ); + return &m_GridEntries[y * m_xCols + x]; } - -void CGrid::CalcColOffsets(int iStart) +void CGrid::CalcColOffsets( int iStart ) { int cur = m_xSpacing; - if(iStart != 0) - cur += m_ColOffsets[iStart-1] + m_Widths[iStart-1]; + if( iStart != 0 ) + cur += m_ColOffsets[iStart - 1] + m_Widths[iStart - 1]; - for(int i=iStart; i < m_xCols; i++) + for( int i = iStart; i < m_xCols; i++ ) { m_ColOffsets[i] = cur; cur += m_Widths[i] + m_xSpacing; } } - -void CGrid::CalcRowOffsets(int iStart) +void CGrid::CalcRowOffsets( int iStart ) { int cur = m_ySpacing; - if(iStart != 0) - cur += m_RowOffsets[iStart-1]; + if( iStart != 0 ) + cur += m_RowOffsets[iStart - 1]; - for(int i=iStart; i < m_yRows; i++) + for( int i = iStart; i < m_yRows; i++ ) { m_RowOffsets[i] = cur; cur += m_Heights[i] + m_ySpacing; } } -bool CGrid::getCellAtPoint(int worldX, int worldY, int &row, int &col) +bool CGrid::getCellAtPoint( int worldX, int worldY, int &row, int &col ) { row = -1; col = -1; - for(int x=0; x < m_xCols; x++) + + for( int x = 0; x < m_xCols; x++ ) { - for(int y=0; y < m_yRows; y++) + for( int y = 0; y < m_yRows; y++ ) { - Panel *pPanel = GridEntry(x,y)->m_pPanel; - if (!pPanel) + Panel *pPanel = GridEntry( x, y )->m_pPanel; + if( !pPanel ) continue; - if (pPanel->isWithin(worldX, worldY)) + if( pPanel->isWithin( worldX, worldY ) ) { col = x; row = y; @@ -395,4 +365,3 @@ bool CGrid::getCellAtPoint(int worldX, int worldY, int &row, int &col) return false; } - diff --git a/game_shared/vgui_grid.h b/game_shared/vgui_grid.h index 739834e5..0e45ac4a 100644 --- a/game_shared/vgui_grid.h +++ b/game_shared/vgui_grid.h @@ -5,22 +5,20 @@ // $NoKeywords: $ //============================================================================= #pragma once -#if !defined(VGUI_GRID_H) +#ifndef VGUI_GRID_H #define VGUI_GRID_H -#include "vgui_panel.h" - +#include "VGUI_Panel.h" namespace vgui { - // The grid control simply manages a grid of panels. You can adjust column sizes and spacings and // configure and fill the panels however you want. // To use this control, call SetDimensions, SetSpacing and fill the controls. class CGrid : public Panel { public: - CGrid(); + CGrid(); virtual ~CGrid(); bool SetDimensions(int xCols, int yRows); // Set how many columns and rows in the grid. @@ -66,8 +64,6 @@ public: bool getCellAtPoint(int worldX, int worldY, int &row, int &col); // Panel overrides. -public: - virtual void paint(); virtual void paintBackground(); @@ -76,8 +72,8 @@ protected: class CGridEntry { public: - CGridEntry(); - ~CGridEntry(); + CGridEntry(); + ~CGridEntry(); Panel *m_pPanel; @@ -92,9 +88,6 @@ protected: void CalcColOffsets(int iStart); void CalcRowOffsets(int iStart); - -protected: - bool m_bDirty; // Set when controls will need to be repositioned. int m_xCols; @@ -108,9 +101,8 @@ protected: int *m_ColOffsets; int *m_RowOffsets; - CGridEntry *m_GridEntries; - -}; - + CGridEntry *m_GridEntries; }; +} #endif // VGUI_GRID_H + diff --git a/game_shared/vgui_helpers.cpp b/game_shared/vgui_helpers.cpp index c2694759..79c4e378 100644 --- a/game_shared/vgui_helpers.cpp +++ b/game_shared/vgui_helpers.cpp @@ -7,37 +7,36 @@ #include "vgui_helpers.h" - using namespace vgui; - -void AlignPanel(Panel *pChild, Panel *pParent, int alignment) +void AlignPanel( Panel *pChild, Panel *pParent, int alignment ) { int w, h, cw, ch; - pParent->getSize(w, h); - pChild->getSize(cw, ch); - int xCenter = (w - cw) / 2; - int yCenter = (h - ch) / 2; + pParent->getSize( w, h ); + pChild->getSize( cw, ch ); - if(alignment == Label::a_west) - pChild->setPos(0, yCenter); - else if(alignment == Label::a_northwest) - pChild->setPos(0,0); - else if(alignment == Label::a_north) - pChild->setPos(xCenter, 0); - else if(alignment == Label::a_northeast) - pChild->setPos(w - cw, 0); - else if(alignment == Label::a_east) - pChild->setPos(w - cw, yCenter); - else if(alignment == Label::a_southeast) - pChild->setPos(w - cw, h - ch); - else if(alignment == Label::a_south) - pChild->setPos(xCenter, h - ch); - else if(alignment == Label::a_southwest) - pChild->setPos(0, h - ch); - else if(alignment == Label::a_center) - pChild->setPos(xCenter, yCenter); + int xCenter = ( w - cw ) / 2; + int yCenter = ( h - ch ) / 2; + + if( alignment == Label::a_west ) + pChild->setPos( 0, yCenter ); + else if( alignment == Label::a_northwest ) + pChild->setPos( 0, 0 ); + else if( alignment == Label::a_north ) + pChild->setPos( xCenter, 0 ); + else if( alignment == Label::a_northeast ) + pChild->setPos( w - cw, 0 ); + else if( alignment == Label::a_east ) + pChild->setPos( w - cw, yCenter ); + else if( alignment == Label::a_southeast ) + pChild->setPos( w - cw, h - ch ); + else if( alignment == Label::a_south ) + pChild->setPos( xCenter, h - ch ); + else if( alignment == Label::a_southwest ) + pChild->setPos( 0, h - ch ); + else if( alignment == Label::a_center ) + pChild->setPos( xCenter, yCenter ); } diff --git a/game_shared/vgui_helpers.h b/game_shared/vgui_helpers.h index fb150eb5..91c24343 100644 --- a/game_shared/vgui_helpers.h +++ b/game_shared/vgui_helpers.h @@ -5,22 +5,68 @@ // $NoKeywords: $ //============================================================================= #pragma once -#if !defined(VGUI_HELPERS_H) +#ifndef VGUI_HELPERS_H #define VGUI_HELPERS_H +#include "VGUI_Panel.h" +#include "VGUI_Label.h" -#include "vgui_panel.h" -#include "vgui_label.h" +inline int PanelTop( vgui::Panel *pPanel ) +{ + int x, y, w, h; + pPanel->getBounds( x, y, w, h ); -inline int PanelTop(vgui::Panel *pPanel) {int x,y,w,h; pPanel->getBounds(x,y,w,h); return y;} -inline int PanelLeft(vgui::Panel *pPanel) {int x,y,w,h; pPanel->getBounds(x,y,w,h); return x;} -inline int PanelRight(vgui::Panel *pPanel) {int x,y,w,h; pPanel->getBounds(x,y,w,h); return x+w;} -inline int PanelBottom(vgui::Panel *pPanel) {int x,y,w,h; pPanel->getBounds(x,y,w,h); return y+h;} -inline int PanelWidth(vgui::Panel *pPanel) {int x,y,w,h; pPanel->getBounds(x,y,w,h); return w;} -inline int PanelHeight(vgui::Panel *pPanel) {int x,y,w,h; pPanel->getBounds(x,y,w,h); return h;} + return y; +} + +inline int PanelLeft( vgui::Panel *pPanel ) +{ + int x, y, w, h; + + pPanel->getBounds( x, y, w, h ); + + return x; +} + +inline int PanelRight( vgui::Panel *pPanel ) +{ + int x, y, w, h; + + pPanel->getBounds( x, y, w, h ); + + return x + w; +} + +inline int PanelBottom( vgui::Panel *pPanel ) +{ + int x, y, w, h; + + pPanel->getBounds( x, y, w, h ); + + return y + h; +} + +inline int PanelWidth( vgui::Panel *pPanel ) +{ + int x, y, w, h; + + pPanel->getBounds( x, y, w, h ); + + return w; +} + +inline int PanelHeight( vgui::Panel *pPanel ) +{ + int x, y, w, h; + + pPanel->getBounds( x, y, w, h ); + + return h; +} // Places child at the requested position inside pParent. iAlignment is from Label::Alignment. -void AlignPanel(vgui::Panel *pChild, vgui::Panel *pParent, int alignment); +void AlignPanel( vgui::Panel *pChild, vgui::Panel *pParent, int alignment ); + #endif // VGUI_HELPERS_H diff --git a/game_shared/vgui_listbox.cpp b/game_shared/vgui_listbox.cpp index 6986d909..77b7689b 100644 --- a/game_shared/vgui_listbox.cpp +++ b/game_shared/vgui_listbox.cpp @@ -7,28 +7,25 @@ #include "vgui_listbox.h" - - using namespace vgui; - -CListBox::CListBox() : Panel(0, 0, 0, 0), - m_ItemsPanel(0,0,0,0), - m_ScrollBar(0, 0, 0, 0, true), - m_Slider(0, 0, 10, 40, true) +CListBox::CListBox() : Panel( 0, 0, 0, 0 ), + m_ItemsPanel( 0, 0, 0, 0 ), + m_ScrollBar( 0, 0, 0, 0, true ), + m_Slider( 0, 0, 10, 40, true ) { m_Signal.m_pListBox = this; - m_ItemsPanel.setParent(this); - m_ItemsPanel.setBgColor(0,0,0,255); - - m_Slider.setRangeWindow(50); - m_Slider.setRangeWindowEnabled(true); + m_ItemsPanel.setParent( this ); + m_ItemsPanel.setBgColor( 0, 0, 0, 255 ); - m_ScrollBar.setParent(this); - m_ScrollBar.addIntChangeSignal(&m_Signal); - m_ScrollBar.setSlider(&m_Slider); - m_ScrollBar.setButtonPressedScrollValue(1); + m_Slider.setRangeWindow( 50 ); + m_Slider.setRangeWindowEnabled( true ); + + m_ScrollBar.setParent( this ); + m_ScrollBar.addIntChangeSignal( &m_Signal ); + m_ScrollBar.setSlider( &m_Slider ); + m_ScrollBar.setButtonPressedScrollValue( 1 ); m_Items.m_pNext = m_Items.m_pPrev = &m_Items; m_ItemOffset = 0; @@ -51,40 +48,42 @@ void CListBox::Term() // Free the LBItems. LBItem *pNext; - for(LBItem *pItem=m_Items.m_pNext; pItem != &m_Items; pItem=pNext) + + for( LBItem *pItem =m_Items.m_pNext; pItem != &m_Items; pItem = pNext ) { - pItem->m_pPanel->setParent(NULL); // detach the panel from us + pItem->m_pPanel->setParent( NULL ); // detach the panel from us pNext = pItem->m_pNext; delete pItem; } m_Items.m_pPrev = m_Items.m_pNext = &m_Items; } -void CListBox::AddItem(Panel* panel) +void CListBox::AddItem( Panel *panel ) { // Add the item. LBItem *pItem = new LBItem; - if(!pItem) + if( !pItem ) return; pItem->m_pPanel = panel; - pItem->m_pPanel->setParent(&m_ItemsPanel); + pItem->m_pPanel->setParent( &m_ItemsPanel ); pItem->m_pPrev = m_Items.m_pPrev; pItem->m_pNext = &m_Items; pItem->m_pNext->m_pPrev = pItem->m_pPrev->m_pNext = pItem; - m_ScrollBar.setRange(0, GetScrollMax()); - m_Slider.setRangeWindow(50); - m_Slider.setRangeWindowEnabled(true); + m_ScrollBar.setRange( 0, GetScrollMax() ); + m_Slider.setRangeWindow( 50 ); + m_Slider.setRangeWindowEnabled( true ); InternalLayout(); } int CListBox::GetNumItems() { - int count=0; - for(LBItem *pItem=m_Items.m_pNext; pItem != &m_Items; pItem=pItem->m_pNext) + int count = 0; + + for( LBItem *pItem = m_Items.m_pNext; pItem != &m_Items; pItem = pItem->m_pNext ) ++count; return count; @@ -93,7 +92,9 @@ int CListBox::GetNumItems() int CListBox::GetItemWidth() { int wide, tall; - m_ItemsPanel.getSize(wide, tall); + + m_ItemsPanel.getSize( wide, tall ); + return wide; } @@ -102,29 +103,29 @@ int CListBox::GetScrollPos() return m_ItemOffset; } -void CListBox::SetScrollPos(int pos) +void CListBox::SetScrollPos( int pos ) { int maxItems = GetScrollMax(); - if(maxItems < 0) + if( maxItems < 0 ) return; - m_ItemOffset = (pos < 0) ? 0 : ((pos > maxItems) ? maxItems : pos); + m_ItemOffset = ( pos < 0 ) ? 0 : ( ( pos > maxItems ) ? maxItems : pos ); InternalLayout(); } -void CListBox::setPos(int x, int y) +void CListBox::setPos( int x, int y ) { - Panel::setPos(x, y); + Panel::setPos( x, y ); InternalLayout(); } -void CListBox::setSize(int wide,int tall) +void CListBox::setSize( int wide, int tall ) { - Panel::setSize(wide,tall); + Panel::setSize( wide, tall ); InternalLayout(); } -void CListBox::setPixelScroll(int value) +void CListBox::setPixelScroll( int value ) { m_ItemOffset = m_ScrollBar.getValue(); InternalLayout(); @@ -133,11 +134,11 @@ void CListBox::setPixelScroll(int value) void CListBox::InternalLayout() { int x, y, wide, tall; - getBounds(x, y, wide, tall); + getBounds( x, y, wide, tall ); // Reposition the main panel and the scrollbar. - m_ItemsPanel.setBounds(0, 0, wide-15, tall); - m_ScrollBar.setBounds(wide-15, 0, 15, tall); + m_ItemsPanel.setBounds( 0, 0, wide - 15, tall ); + m_ScrollBar.setBounds( wide - 15, 0, 15, tall ); bool bNeedScrollbar = false; @@ -145,31 +146,32 @@ void CListBox::InternalLayout() int curItem = 0; int curY = 0; int maxItem = GetScrollMax(); - for(LBItem *pItem=m_Items.m_pNext; pItem != &m_Items; pItem=pItem->m_pNext) + for( LBItem *pItem = m_Items.m_pNext; pItem != &m_Items; pItem = pItem->m_pNext ) { - if(curItem < m_ItemOffset) + if( curItem < m_ItemOffset ) { - pItem->m_pPanel->setVisible(false); + pItem->m_pPanel->setVisible( false ); bNeedScrollbar = true; } - else if (curItem >= maxItem) + else if( curItem >= maxItem ) { // item is past the end of the items we care about - pItem->m_pPanel->setVisible(false); + pItem->m_pPanel->setVisible( false ); } else { - pItem->m_pPanel->setVisible(true); + pItem->m_pPanel->setVisible( true ); int itemWidth, itemHeight; - pItem->m_pPanel->getSize(itemWidth, itemHeight); + + pItem->m_pPanel->getSize( itemWidth, itemHeight ); // Don't change the item's height but change its width to fit the listbox. - pItem->m_pPanel->setBounds(0, curY, wide, itemHeight); + pItem->m_pPanel->setBounds( 0, curY, wide, itemHeight ); curY += itemHeight; - if (curY > tall) + if( curY > tall ) { bNeedScrollbar = true; } @@ -178,7 +180,7 @@ void CListBox::InternalLayout() ++curItem; } - m_ScrollBar.setVisible(bNeedScrollbar); + m_ScrollBar.setVisible( bNeedScrollbar ); repaint(); } @@ -187,16 +189,16 @@ void CListBox::paintBackground() { } -void CListBox::SetScrollRange(int maxScroll) +void CListBox::SetScrollRange( int maxScroll ) { m_iScrollMax = maxScroll; - m_ScrollBar.setRange(0, maxScroll); + m_ScrollBar.setRange( 0, maxScroll ); InternalLayout(); } -int CListBox::GetScrollMax() +int CListBox::GetScrollMax() { - if (m_iScrollMax < 0) + if( m_iScrollMax < 0 ) { return GetNumItems() - 1; } @@ -204,4 +206,3 @@ int CListBox::GetScrollMax() return m_iScrollMax; } - diff --git a/game_shared/vgui_listbox.h b/game_shared/vgui_listbox.h index 9b245b4c..a97c780d 100644 --- a/game_shared/vgui_listbox.h +++ b/game_shared/vgui_listbox.h @@ -5,19 +5,17 @@ // $NoKeywords: $ //============================================================================= #pragma once -#if !defined(VOICE_LISTBOX_H) +#ifndef VOICE_LISTBOX_H #define VOICE_LISTBOX_H #include "VGUI_Panel.h" #include "VGUI_IntChangeSignal.h" -#include "VGUI_Slider2.h" -#include "VGUI_ScrollBar2.h" - +#include "vgui_slider2.h" +#include "vgui_scrollbar2.h" namespace vgui { - // Listbox class used by voice code. Based off of vgui's list panel but with some modifications: // - This listbox clips its child items to its rectangle. // - You can access things like the scrollbar and find out the item width. @@ -27,45 +25,39 @@ namespace vgui class CListBox : public Panel { public: - - CListBox(); - ~CListBox(); + CListBox(); + ~CListBox(); - void Init(); - void Term(); + void Init(); + void Term(); // Add an item to the listbox. This automatically sets the item's parent to the listbox // and resizes the item's width to fit within the listbox. - void AddItem(Panel *pPanel); + void AddItem( Panel *pPanel ); // Get the number of items currently in the listbox. - int GetNumItems(); + int GetNumItems(); // Get the width that listbox items will be set to (this changes if you resize the listbox). - int GetItemWidth(); + int GetItemWidth(); // Get/set the scrollbar position (position says which element is at the top of the listbox). - int GetScrollPos(); - void SetScrollPos(int pos); + int GetScrollPos(); + void SetScrollPos( int pos ); // sets the last item the listbox should scroll to // scroll to GetNumItems() if not set - void SetScrollRange(int maxScroll); + void SetScrollRange( int maxScroll ); // returns the maximum value the scrollbar can scroll to - int GetScrollMax(); + int GetScrollMax(); -// vgui overrides. -public: - - virtual void setPos(int x, int y); - virtual void setSize(int wide,int tall); - virtual void setPixelScroll(int value); + // vgui overrides. + virtual void setPos( int x, int y ); + virtual void setSize( int wide, int tall ); + virtual void setPixelScroll( int value ); virtual void paintBackground(); - - protected: - class LBItem { public: @@ -76,34 +68,29 @@ protected: class ListBoxSignal : public IntChangeSignal { public: - void intChanged(int value,Panel* panel) + void intChanged( int value, Panel *panel ) { - m_pListBox->setPixelScroll(-value); + m_pListBox->setPixelScroll( -value ); } vgui::CListBox *m_pListBox; }; - -protected: - - void InternalLayout(); - - -protected: + void InternalLayout(); // All the items.. - LBItem m_Items; + LBItem m_Items; - Panel m_ItemsPanel; + Panel m_ItemsPanel; - int m_ItemOffset; // where we're scrolled to - Slider2 m_Slider; - ScrollBar2 m_ScrollBar; + int m_ItemOffset; // where we're scrolled to + Slider2 m_Slider; + ScrollBar2 m_ScrollBar; ListBoxSignal m_Signal; - int m_iScrollMax; + int m_iScrollMax; }; } #endif // VOICE_LISTBOX_H + diff --git a/game_shared/vgui_loadtga.cpp b/game_shared/vgui_loadtga.cpp index 5c0d9189..bfd8ee7a 100644 --- a/game_shared/vgui_loadtga.cpp +++ b/game_shared/vgui_loadtga.cpp @@ -7,10 +7,9 @@ #include "../cl_dll/wrect.h" #include "../cl_dll/cl_dll.h" -#include "vgui.h" +#include "VGUI.h" #include "vgui_loadtga.h" -#include "vgui_inputstream.h" - +#include "VGUI_InputStream.h" // ---------------------------------------------------------------------- // // Helper class for loading tga files. @@ -18,76 +17,96 @@ class MemoryInputStream : public vgui::InputStream { public: - MemoryInputStream() - { - m_pData = NULL; - m_DataLen = m_ReadPos = 0; - } - - virtual void seekStart(bool& success) {m_ReadPos=0; success=true;} - virtual void seekRelative(int count,bool& success) {m_ReadPos+=count; success=true;} - virtual void seekEnd(bool& success) {m_ReadPos=m_DataLen; success=true;} - virtual int getAvailable(bool& success) {success=false; return 0;} // This is what vgui does for files... - - virtual uchar readUChar(bool& success) + MemoryInputStream() { - if(m_ReadPos>=0 && m_ReadPos= 0 && m_ReadPos < m_DataLen ) { - success=true; + success = true; uchar ret = m_pData[m_ReadPos]; ++m_ReadPos; return ret; } else { - success=false; + success = false; return 0; } } - virtual void readUChar(uchar* buf,int count,bool& success) + virtual void readUChar( uchar *buf, int count, bool &success ) { - for(int i=0; i < count; i++) - buf[i] = readUChar(success); + for( int i = 0; i < count; i++) + buf[i] = readUChar( success ); } - virtual void close(bool& success) + virtual void close( bool &success) { m_pData = NULL; m_DataLen = m_ReadPos = 0; } - uchar *m_pData; - int m_DataLen; - int m_ReadPos; + uchar *m_pData; + int m_DataLen; + int m_ReadPos; }; -vgui::BitmapTGA* vgui_LoadTGA(char const *pFilename) +vgui::BitmapTGA *vgui_LoadTGA( char const *pFilename ) { MemoryInputStream stream; - stream.m_pData = gEngfuncs.COM_LoadFile((char*)pFilename, 5, &stream.m_DataLen); - if(!stream.m_pData) + stream.m_pData = gEngfuncs.COM_LoadFile( (char*)pFilename, 5, &stream.m_DataLen ); + if( !stream.m_pData ) return NULL; stream.m_ReadPos = 0; - vgui::BitmapTGA *pRet = new vgui::BitmapTGA(&stream, true); - gEngfuncs.COM_FreeFile(stream.m_pData); - + vgui::BitmapTGA *pRet = new vgui::BitmapTGA( &stream, true ); + gEngfuncs.COM_FreeFile( stream.m_pData ); + return pRet; } -vgui::BitmapTGA* vgui_LoadTGANoInvertAlpha(char const *pFilename) +vgui::BitmapTGA *vgui_LoadTGANoInvertAlpha( char const *pFilename ) { MemoryInputStream stream; - - stream.m_pData = gEngfuncs.COM_LoadFile((char*)pFilename, 5, &stream.m_DataLen); - if(!stream.m_pData) + + stream.m_pData = gEngfuncs.COM_LoadFile( (char*)pFilename, 5, &stream.m_DataLen ); + if( !stream.m_pData ) return NULL; - + stream.m_ReadPos = 0; - vgui::BitmapTGA *pRet = new vgui::BitmapTGA(&stream, false); - gEngfuncs.COM_FreeFile(stream.m_pData); + vgui::BitmapTGA *pRet = new vgui::BitmapTGA( &stream, false ); + gEngfuncs.COM_FreeFile( stream.m_pData ); return pRet; } diff --git a/game_shared/vgui_loadtga.h b/game_shared/vgui_loadtga.h index ea0ecac2..26505b18 100644 --- a/game_shared/vgui_loadtga.h +++ b/game_shared/vgui_loadtga.h @@ -5,12 +5,12 @@ // $NoKeywords: $ //============================================================================= #pragma once -#if !defined(VGUI_LOADTGA_H) +#ifndef VGUI_LOADTGA_H #define VGUI_LOADTGA_H -#include "vgui_bitmaptga.h" +#include "VGUI_BitmapTGA.h" - -vgui::BitmapTGA* vgui_LoadTGA(char const *pFilename); -vgui::BitmapTGA* vgui_LoadTGANoInvertAlpha(char const *pFilename); +vgui::BitmapTGA *vgui_LoadTGA( char const *pFilename ); +vgui::BitmapTGA *vgui_LoadTGANoInvertAlpha( char const *pFilename ); #endif // VGUI_LOADTGA_H + diff --git a/game_shared/vgui_scrollbar2.cpp b/game_shared/vgui_scrollbar2.cpp index 3f3194bc..805bb191 100644 --- a/game_shared/vgui_scrollbar2.cpp +++ b/game_shared/vgui_scrollbar2.cpp @@ -1,58 +1,56 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +//========= Copyright � 1996-2002, Valve LLC, All rights reserved. ============ // // Purpose: // // $NoKeywords: $ //============================================================================= - -#include "VGUI_ScrollBar2.h" -#include "VGUI_Slider2.h" +#include "vgui_scrollbar2.h" +#include "vgui_slider2.h" #include "vgui_loadtga.h" -#include -#include -#include -#include +#include +#include +#include +#include using namespace vgui; - namespace { class FooDefaultScrollBarIntChangeSignal : public IntChangeSignal { public: - FooDefaultScrollBarIntChangeSignal(ScrollBar2* scrollBar) + FooDefaultScrollBarIntChangeSignal( ScrollBar2 *scrollBar ) { - _scrollBar=scrollBar; + _scrollBar = scrollBar; } - virtual void intChanged(int value,Panel* panel) + + virtual void intChanged( int value, Panel *panel ) { _scrollBar->fireIntChangeSignal(); } protected: - ScrollBar2* _scrollBar; + ScrollBar2 *_scrollBar; }; class FooDefaultButtonSignal : public ActionSignal { public: - ScrollBar2* _scrollBar; - int _buttonIndex; -public: - FooDefaultButtonSignal(ScrollBar2* scrollBar,int buttonIndex) + ScrollBar2 *_scrollBar; + int _buttonIndex; + + FooDefaultButtonSignal( ScrollBar2 *scrollBar, int buttonIndex ) { - _scrollBar=scrollBar; - _buttonIndex=buttonIndex; + _scrollBar = scrollBar; + _buttonIndex = buttonIndex; } -public: - virtual void actionPerformed(Panel* panel) + + virtual void actionPerformed( Panel *panel ) { - _scrollBar->doButtonPressed(_buttonIndex); + _scrollBar->doButtonPressed( _buttonIndex ); } }; - } //----------------------------------------------------------------------------- @@ -65,32 +63,29 @@ private: LineBorder m_Border; public: - ScrollBarButton(const char *filename, int x, int y, int wide, int tall) : m_Border(Color(60, 60, 60, 0)), Button("", x, y, wide, tall) + ScrollBarButton( const char *filename, int x, int y, int wide, int tall ) : m_Border( Color( 60, 60, 60, 0 ) ), Button( "", x, y, wide, tall ) { - Image *image = vgui_LoadTGA(filename); - if (image) + Image *image = vgui_LoadTGA( filename ); + if( image ) { - image->setColor(Color(140, 140, 140, 0)); - setImage(image); + image->setColor( Color( 140, 140, 140, 0 ) ); + setImage( image ); } - setBorder(&m_Border); + setBorder( &m_Border ); } virtual void paintBackground() { - int wide,tall; - getPaintSize(wide,tall); + int wide, tall; + getPaintSize( wide, tall ); // fill the background - drawSetColor(0, 0, 0, 0); - drawFilledRect(0, 0, wide, tall); + drawSetColor( 0, 0, 0, 0 ); + drawFilledRect( 0, 0, wide, tall ); } }; - - - //----------------------------------------------------------------------------- // Purpose: Constructor // Input : x - @@ -99,68 +94,68 @@ public: // tall - // vertical - //----------------------------------------------------------------------------- -ScrollBar2::ScrollBar2(int x,int y,int wide,int tall,bool vertical) : Panel(x,y,wide,tall) +ScrollBar2::ScrollBar2( int x, int y, int wide, int tall, bool vertical ) : Panel( x, y, wide, tall ) { - _slider=null; - _button[0]=null; - _button[1]=null; + _slider = null; + _button[0] = null; + _button[1] = null; - if(vertical) + if( vertical ) { - setSlider(new Slider2(0,wide-1,wide,(tall-(wide*2))+2,true)); - setButton(new ScrollBarButton("gfx/vgui/arrowup.tga",0,0,wide,wide),0); - setButton(new ScrollBarButton("gfx/vgui/arrowdown.tga",0,tall-wide,wide,wide),1); + setSlider( new Slider2( 0, wide - 1, wide, ( tall - ( wide * 2 ) ) + 2, true ) ); + setButton( new ScrollBarButton( "gfx/vgui/arrowup.tga", 0, 0, wide, wide ), 0 ); + setButton( new ScrollBarButton( "gfx/vgui/arrowdown.tga", 0, tall - wide, wide, wide ), 1 ); } else { // untested code - setSlider(new Slider2(tall,0,wide-(tall*2),tall,false)); - setButton(new ScrollBarButton("gfx/vgui/320_arrowlt.tga",0,0,tall+1,tall+1),0); - setButton(new ScrollBarButton("gfx/vgui/320_arrowrt.tga",wide-tall,0,tall+1,tall+1),1); + setSlider( new Slider2( tall, 0, wide - ( tall * 2 ), tall, false ) ); + setButton( new ScrollBarButton( "gfx/vgui/320_arrowlt.tga", 0, 0, tall + 1, tall + 1 ), 0 ); + setButton( new ScrollBarButton( "gfx/vgui/320_arrowrt.tga", wide - tall, 0, tall + 1, tall + 1 ) , 1 ); } - setPaintBorderEnabled(true); - setPaintBackgroundEnabled(true); - setPaintEnabled(true); - setButtonPressedScrollValue(15); + setPaintBorderEnabled( true ); + setPaintBackgroundEnabled( true ); + setPaintEnabled( true ); + setButtonPressedScrollValue( 15 ); validate(); - } +} -void ScrollBar2::setSize(int wide,int tall) +void ScrollBar2::setSize( int wide, int tall ) { - Panel::setSize(wide,tall); + Panel::setSize( wide, tall ); - if(_slider==null) + if( _slider == null ) { return; } - if(_button[0]==null) + if( _button[0] == null ) { return; } - if(_button[1]==null) + if( _button[1] == null ) { return; } - getPaintSize(wide,tall); + getPaintSize( wide, tall ); - if(_slider->isVertical()) + if( _slider->isVertical() ) { - _slider->setBounds(0,wide,wide,tall-(wide*2)); - //_slider->setBounds(0,0,wide,tall); - _button[0]->setBounds(0,0,wide,wide); - _button[1]->setBounds(0,tall-wide,wide,wide); + _slider->setBounds( 0, wide, wide, tall - ( wide * 2 ) ); + // _slider->setBounds( 0, 0, wide, tall ); + _button[0]->setBounds( 0, 0, wide, wide ); + _button[1]->setBounds( 0, tall - wide, wide, wide ); } else { - _slider->setBounds(tall,0,wide-(tall*2),tall); - //_slider->setBounds(0,0,wide,tall); - _button[0]->setBounds(0,0,tall,tall); - _button[1]->setBounds((wide-tall),0,tall,tall); + _slider->setBounds( tall, 0, wide - ( tall * 2 ), tall ); + // _slider->setBounds( 0, 0, wide, tall ); + _button[0]->setBounds( 0, 0, tall, tall ); + _button[1]->setBounds( ( wide - tall ), 0, tall, tall); } } @@ -168,9 +163,9 @@ void ScrollBar2::performLayout() { } -void ScrollBar2::setValue(int value) +void ScrollBar2::setValue( int value ) { - _slider->setValue(value); + _slider->setValue( value ); } int ScrollBar2::getValue() @@ -178,22 +173,22 @@ int ScrollBar2::getValue() return _slider->getValue(); } -void ScrollBar2::addIntChangeSignal(IntChangeSignal* s) +void ScrollBar2::addIntChangeSignal( IntChangeSignal *s ) { - _intChangeSignalDar.putElement(s); - _slider->addIntChangeSignal(new FooDefaultScrollBarIntChangeSignal(this)); + _intChangeSignalDar.putElement( s ); + _slider->addIntChangeSignal( new FooDefaultScrollBarIntChangeSignal( this ) ); } -void ScrollBar2::setRange(int min,int max) +void ScrollBar2::setRange( int min, int max ) { - _slider->setRange(min,max); + _slider->setRange( min, max ); } void ScrollBar2::fireIntChangeSignal() { - for(int i=0;i<_intChangeSignalDar.getCount();i++) + for( int i = 0; i < _intChangeSignalDar.getCount(); i++ ) { - _intChangeSignalDar[i]->intChanged(_slider->getValue(),this); + _intChangeSignalDar[i]->intChanged( _slider->getValue(), this ); } } @@ -207,39 +202,41 @@ bool ScrollBar2::hasFullRange() return _slider->hasFullRange(); } -//LEAK: new and old slider will leak -void ScrollBar2::setButton(Button* button,int index) +// LEAK: new and old slider will leak +void ScrollBar2::setButton( Button *button, int index ) { - if(_button[index]!=null) + if( _button[index] != null ) { - removeChild(_button[index]); + removeChild( _button[index] ); } - _button[index]=button; - addChild(_button[index]); - _button[index]->addActionSignal(new FooDefaultButtonSignal(this,index)); + _button[index] = button; + addChild( _button[index] ); + + _button[index]->addActionSignal( new FooDefaultButtonSignal( this, index ) ); validate(); - //_button[index]->setVisible(false); + // _button[index]->setVisible( false ); } -Button* ScrollBar2::getButton(int index) +Button *ScrollBar2::getButton( int index ) { return _button[index]; } -//LEAK: new and old slider will leak -void ScrollBar2::setSlider(Slider2 *slider) +// LEAK: new and old slider will leak +void ScrollBar2::setSlider( Slider2 *slider ) { - if(_slider!=null) + if( _slider != null ) { - removeChild(_slider); + removeChild( _slider ); } - _slider=slider; - addChild(_slider); - _slider->addIntChangeSignal(new FooDefaultScrollBarIntChangeSignal(this)); + _slider = slider; + addChild( _slider ); + + _slider->addIntChangeSignal( new FooDefaultScrollBarIntChangeSignal( this ) ); validate(); } @@ -249,62 +246,62 @@ Slider2 *ScrollBar2::getSlider() return _slider; } -void ScrollBar2::doButtonPressed(int buttonIndex) +void ScrollBar2::doButtonPressed( int buttonIndex ) { - if(buttonIndex==0) + if( buttonIndex == 0 ) { - _slider->setValue(_slider->getValue()-_buttonPressedScrollValue); + _slider->setValue( _slider->getValue() - _buttonPressedScrollValue ); } else { - _slider->setValue(_slider->getValue()+_buttonPressedScrollValue); + _slider->setValue( _slider->getValue() + _buttonPressedScrollValue ); } - } -void ScrollBar2::setButtonPressedScrollValue(int value) +void ScrollBar2::setButtonPressedScrollValue( int value ) { - _buttonPressedScrollValue=value; + _buttonPressedScrollValue = value; } -void ScrollBar2::setRangeWindow(int rangeWindow) +void ScrollBar2::setRangeWindow( int rangeWindow ) { - _slider->setRangeWindow(rangeWindow); + _slider->setRangeWindow( rangeWindow ); } -void ScrollBar2::setRangeWindowEnabled(bool state) +void ScrollBar2::setRangeWindowEnabled( bool state ) { - _slider->setRangeWindowEnabled(state); + _slider->setRangeWindowEnabled( state ); } void ScrollBar2::validate() { - if(_slider!=null) + if( _slider != null ) { - int buttonOffset=0; + int buttonOffset = 0; - for(int i=0;i<2;i++) + for( int i = 0; i < 2; i++ ) { - if(_button[i]!=null) + if( _button[i] != null ) { - if(_button[i]->isVisible()) + if( _button[i]->isVisible() ) { - if(_slider->isVertical()) - { - buttonOffset+=_button[i]->getTall(); + if( _slider->isVertical() ) + { + buttonOffset += _button[i]->getTall(); } else { - buttonOffset+=_button[i]->getWide(); + buttonOffset += _button[i]->getWide(); } } } } - _slider->setButtonOffset(buttonOffset); + _slider->setButtonOffset( buttonOffset ); } - int wide,tall; - getSize(wide,tall); - setSize(wide,tall); + int wide, tall; + + getSize( wide, tall ); + setSize( wide, tall ); } diff --git a/game_shared/vgui_scrollbar2.h b/game_shared/vgui_scrollbar2.h index 16fe8a46..71cd965b 100644 --- a/game_shared/vgui_scrollbar2.h +++ b/game_shared/vgui_scrollbar2.h @@ -5,16 +5,15 @@ // $NoKeywords: $ //============================================================================= #pragma once -#if !defined(VGUI_SCROLLBAR2_H) +#ifndef VGUI_SCROLLBAR2_H #define VGUI_SCROLLBAR2_H -#include -#include -#include +#include +#include +#include namespace vgui { - class IntChangeSignal; class Button; class Slider2; @@ -25,34 +24,34 @@ class Slider2; class VGUIAPI ScrollBar2 : public Panel { public: - ScrollBar2(int x,int y,int wide,int tall,bool vertical); -public: - virtual void setValue(int value); - virtual int getValue(); - virtual void addIntChangeSignal(IntChangeSignal* s); - virtual void setRange(int min,int max); - virtual void setRangeWindow(int rangeWindow); - virtual void setRangeWindowEnabled(bool state); - virtual void setSize(int wide,int tall); - virtual bool isVertical(); - virtual bool hasFullRange(); - virtual void setButton(Button *button,int index); - virtual Button* getButton(int index); - virtual void setSlider(Slider2 *slider); - virtual Slider2 *getSlider(); - virtual void doButtonPressed(int buttonIndex); - virtual void setButtonPressedScrollValue(int value); - virtual void validate(); -public: //bullshit public - virtual void fireIntChangeSignal(); -protected: - virtual void performLayout(); -protected: - Button* _button[2]; - Slider2 *_slider; - Dar _intChangeSignalDar; - int _buttonPressedScrollValue; -}; + ScrollBar2( int x, int y, int wide, int tall, bool vertical ); + virtual void setValue( int value ); + virtual int getValue(); + virtual void addIntChangeSignal( IntChangeSignal *s ); + virtual void setRange(int min, int max ); + virtual void setRangeWindow( int rangeWindow ); + virtual void setRangeWindowEnabled( bool state ); + virtual void setSize( int wide, int tall ); + virtual bool isVertical(); + virtual bool hasFullRange(); + virtual void setButton( Button *button,int index ); + virtual Button *getButton( int index ); + virtual void setSlider( Slider2 *slider ); + virtual Slider2 *getSlider(); + virtual void doButtonPressed( int buttonIndex ); + virtual void setButtonPressedScrollValue( int value ); + virtual void validate(); + // bullshit public + virtual void fireIntChangeSignal(); +protected: + virtual void performLayout(); + + Button *_button[2]; + Slider2 *_slider; + Dar _intChangeSignalDar; + int _buttonPressedScrollValue; +}; } #endif // VGUI_SCROLLBAR2_H + diff --git a/game_shared/vgui_slider2.cpp b/game_shared/vgui_slider2.cpp index 801f5c00..d7e2c564 100644 --- a/game_shared/vgui_slider2.cpp +++ b/game_shared/vgui_slider2.cpp @@ -5,12 +5,12 @@ // $NoKeywords: $ //============================================================================= -#include "VGUI_Slider2.h" +#include "vgui_slider2.h" -#include -#include -#include -#include +#include +#include +#include +#include using namespace vgui; @@ -18,54 +18,57 @@ namespace { class FooDefaultSliderSignal : public InputSignal { -private: - Slider2* _slider; + Slider2 *_slider; public: - FooDefaultSliderSignal(Slider2* slider) + FooDefaultSliderSignal( Slider2 *slider ) { - _slider=slider; + _slider = slider; } -public: - void cursorMoved(int x,int y,Panel* panel) + + void cursorMoved( int x, int y, Panel *panel ) { - _slider->privateCursorMoved(x,y,panel); + _slider->privateCursorMoved( x, y, panel ); } - void cursorEntered(Panel* panel){} - void cursorExited(Panel* panel){} - void mouseDoublePressed(MouseCode code,Panel* panel){} - void mousePressed(MouseCode code,Panel* panel) + + void cursorEntered( Panel *panel ) {} + void cursorExited( Panel *panel ) {} + void mouseDoublePressed( MouseCode code, Panel *panel ) {} + + void mousePressed( MouseCode code, Panel *panel ) { - _slider->privateMousePressed(code,panel); + _slider->privateMousePressed( code, panel ); } - void mouseReleased(MouseCode code,Panel* panel) + + void mouseReleased( MouseCode code, Panel *panel ) { - _slider->privateMouseReleased(code,panel); + _slider->privateMouseReleased( code, panel ); } - void mouseWheeled(int delta,Panel* panel){} - void keyPressed(KeyCode code,Panel* panel){} - void keyTyped(KeyCode code,Panel* panel){} - void keyReleased(KeyCode code,Panel* panel){} - void keyFocusTicked(Panel* panel){} + + void mouseWheeled( int delta, Panel *panel ) {} + void keyPressed( KeyCode code, Panel *panel ) {} + void keyTyped( KeyCode code, Panel *panel ) {} + void keyReleased( KeyCode code, Panel *panel ) {} + void keyFocusTicked( Panel *panel ) {} }; } -Slider2::Slider2(int x,int y,int wide,int tall,bool vertical) : Panel(x,y,wide,tall) +Slider2::Slider2( int x, int y, int wide, int tall, bool vertical ) : Panel( x, y, wide, tall ) { - _vertical=vertical; - _dragging=false; - _value=0; - _range[0]=0; - _range[1]=299; - _rangeWindow=0; - _rangeWindowEnabled=false; - _buttonOffset=0; + _vertical = vertical; + _dragging = false; + _value = 0; + _range[0] = 0; + _range[1] = 299; + _rangeWindow = 0; + _rangeWindowEnabled = false; + _buttonOffset = 0; recomputeNobPosFromValue(); - addInputSignal(new FooDefaultSliderSignal(this)); + addInputSignal( new FooDefaultSliderSignal( this ) ); } -void Slider2::setSize(int wide,int tall) +void Slider2::setSize( int wide, int tall ) { - Panel::setSize(wide,tall); + Panel::setSize( wide, tall ); recomputeNobPosFromValue(); } @@ -74,24 +77,24 @@ bool Slider2::isVertical() return _vertical; } -void Slider2::setValue(int value) +void Slider2::setValue( int value ) { - int oldValue=_value; + int oldValue = _value; - if(value<_range[0]) + if( value < _range[0] ) { - value=_range[0]; + value = _range[0]; } - if(value>_range[1]) + if( value > _range[1] ) { value=_range[1]; } - _value=value; + _value = value; recomputeNobPosFromValue(); - if(_value!=oldValue) + if( _value != oldValue ) { fireIntChangeSignal(); } @@ -104,48 +107,48 @@ int Slider2::getValue() void Slider2::recomputeNobPosFromValue() { - int wide,tall; + int wide, tall; - getPaintSize(wide,tall); + getPaintSize( wide, tall ); - float fwide=(float)wide; - float ftall=(float)tall; - float frange=(float)(_range[1]-_range[0]); - float fvalue=(float)(_value-_range[0]); - float fper=fvalue/frange; - float frangewindow=(float)(_rangeWindow); + float fwide = (float)wide; + float ftall = (float)tall; + float frange = (float)(_range[1] - _range[0]); + float fvalue = (float)(_value - _range[0]); + float fper = fvalue / frange; + float frangewindow = (float)_rangeWindow; - if(frangewindow<0) + if( frangewindow < 0 ) { - frangewindow=0; + frangewindow = 0; } - if(!_rangeWindowEnabled) + if( !_rangeWindowEnabled ) { - frangewindow=frange; + frangewindow = frange; } - if ( frangewindow > 0 ) + if( frangewindow > 0 ) { - if(_vertical) + if( _vertical ) { float fnobsize=frangewindow; float freepixels = ftall - fnobsize; float firstpixel = freepixels * fper; - _nobPos[0]=(int)( firstpixel ); - _nobPos[1]=(int)( firstpixel + fnobsize ); + _nobPos[0] = (int)( firstpixel ); + _nobPos[1] = (int)( firstpixel + fnobsize ); - if(_nobPos[1]>tall) + if( _nobPos[1] > tall ) { - _nobPos[0]=tall-((int)fnobsize); - _nobPos[1]=tall; + _nobPos[0] = tall - ((int)fnobsize); + _nobPos[1] = tall; } } else { - float fnobsize=frangewindow; + float fnobsize = frangewindow; float freepixels = fwide - fnobsize; float firstpixel = freepixels * fper; @@ -153,10 +156,10 @@ void Slider2::recomputeNobPosFromValue() _nobPos[0]=(int)( firstpixel ); _nobPos[1]=(int)( firstpixel + fnobsize ); - if(_nobPos[1]>wide) + if( _nobPos[1] > wide ) { - _nobPos[0]=wide-((int)fnobsize); - _nobPos[1]=wide; + _nobPos[0] = wide - ((int)fnobsize); + _nobPos[1] = wide; } } } @@ -167,40 +170,41 @@ void Slider2::recomputeNobPosFromValue() void Slider2::recomputeValueFromNobPos() { int wide,tall; - getPaintSize(wide,tall); - float fwide=(float)wide; - float ftall=(float)tall; - float frange=(float)(_range[1]-_range[0]); - float fvalue=(float)(_value-_range[0]); - float fnob=(float)_nobPos[0]; - float frangewindow=(float)(_rangeWindow); + getPaintSize( wide, tall ); - if(frangewindow<0) + float fwide = (float)wide; + float ftall = (float)tall; + float frange = (float)(_range[1] - _range[0]); + float fvalue = (float)(_value - _range[0]); + float fnob = (float)_nobPos[0]; + float frangewindow = (float)(_rangeWindow); + + if( frangewindow < 0 ) { - frangewindow=0; + frangewindow = 0; } - if(!_rangeWindowEnabled) + if( !_rangeWindowEnabled ) { - frangewindow=frange; + frangewindow = frange; } - if ( frangewindow > 0 ) + if( frangewindow > 0 ) { - if(_vertical) + if( _vertical ) { - float fnobsize=frangewindow; - fvalue=frange*(fnob/(ftall-fnobsize)); + float fnobsize = frangewindow; + fvalue = frange * ( fnob / ( ftall - fnobsize ) ); } else { - float fnobsize=frangewindow; - fvalue=frange*(fnob/(fwide-fnobsize)); + float fnobsize = frangewindow; + fvalue = frange * ( fnob / ( fwide - fnobsize ) ); } } // Take care of rounding issues. - _value=(int)(fvalue+_range[0]+0.5); + _value = (int)( fvalue+_range[0] + 0.5 ); // Clamp final result _value = ( _value < _range[1] ) ? _value : _range[1]; @@ -208,27 +212,28 @@ void Slider2::recomputeValueFromNobPos() bool Slider2::hasFullRange() { - int wide,tall; - getPaintSize(wide,tall); + int wide, tall; - float fwide=(float)wide; - float ftall=(float)tall; - float frange=(float)(_range[1]-_range[0]); - float frangewindow=(float)(_rangeWindow); + getPaintSize( wide, tall ); - if(frangewindow<0) + float fwide = (float)wide; + float ftall = (float)tall; + float frange = (float)( _range[1] - _range[0] ); + float frangewindow = (float)( _rangeWindow ); + + if( frangewindow < 0 ) { - frangewindow=0; + frangewindow = 0; } - if(!_rangeWindowEnabled) + if( !_rangeWindowEnabled ) { - frangewindow=frange; + frangewindow = frange; } - if ( frangewindow > 0 ) + if( frangewindow > 0 ) { - if(_vertical) + if( _vertical ) { if( frangewindow <= ( ftall + _buttonOffset ) ) { @@ -247,126 +252,125 @@ bool Slider2::hasFullRange() return false; } -void Slider2::addIntChangeSignal(IntChangeSignal* s) +void Slider2::addIntChangeSignal( IntChangeSignal *s ) { _intChangeSignalDar.putElement(s); } void Slider2::fireIntChangeSignal() { - for(int i=0;i<_intChangeSignalDar.getCount();i++) + for( int i = 0; i < _intChangeSignalDar.getCount(); i++ ) { - _intChangeSignalDar[i]->intChanged(getValue(),this); + _intChangeSignalDar[i]->intChanged( getValue(), this ); } } void Slider2::paintBackground() { - int wide,tall; - getPaintSize(wide,tall); + int wide, tall; + getPaintSize( wide, tall ); - if (_vertical) + if( _vertical ) { // background behind slider - drawSetColor(40, 40, 40, 0); - drawFilledRect(0, 0, wide, tall); + drawSetColor( 40, 40, 40, 0 ); + drawFilledRect( 0, 0, wide, tall ); // slider front - drawSetColor(0, 0, 0, 0); - drawFilledRect(0,_nobPos[0],wide,_nobPos[1]); + drawSetColor( 0, 0, 0, 0 ); + drawFilledRect( 0, _nobPos[0], wide, _nobPos[1] ); // slider border - drawSetColor(60, 60, 60, 0); - drawFilledRect(0,_nobPos[0],wide,_nobPos[0]+1); // top - drawFilledRect(0,_nobPos[1],wide,_nobPos[1]+1); // bottom - drawFilledRect(0,_nobPos[0]+1,1,_nobPos[1]); // left - drawFilledRect(wide-1,_nobPos[0]+1,wide,_nobPos[1]); // right + drawSetColor( 60, 60, 60, 0 ); + drawFilledRect( 0, _nobPos[0], wide, _nobPos[0] + 1 ); // top + drawFilledRect( 0, _nobPos[1], wide, _nobPos[1] + 1 ); // bottom + drawFilledRect( 0, _nobPos[0] + 1, 1, _nobPos[1] ); // left + drawFilledRect( wide - 1, _nobPos[0] + 1, wide, _nobPos[1] ); // right } else { //!! doesn't work + drawSetColor( Scheme::sc_secondary3 ); + drawFilledRect( 0, 0, wide, tall ); - drawSetColor(Scheme::sc_secondary3); - drawFilledRect(0,0,wide,tall); + drawSetColor( Scheme::sc_black ); + drawOutlinedRect( 0, 0, wide, tall ); - drawSetColor(Scheme::sc_black); - drawOutlinedRect(0,0,wide,tall); - - drawSetColor(Scheme::sc_primary2); - drawFilledRect(_nobPos[0],0,_nobPos[1],tall); + drawSetColor( Scheme::sc_primary2 ); + drawFilledRect( _nobPos[0], 0, _nobPos[1], tall ); - drawSetColor(Scheme::sc_black); - drawOutlinedRect(_nobPos[0],0,_nobPos[1],tall); + drawSetColor( Scheme::sc_black ); + drawOutlinedRect( _nobPos[0], 0, _nobPos[1], tall ); } } -void Slider2::setRange(int min,int max) +void Slider2::setRange( int min, int max ) { - if(maxmax) + if( min > max ) { - min=max; + min = max; } - _range[0]=min; - _range[1]=max; + _range[0] = min; + _range[1] = max; } -void Slider2::getRange(int& min,int& max) +void Slider2::getRange( int &min, int &max ) { - min=_range[0]; - max=_range[1]; + min = _range[0]; + max = _range[1]; } -void Slider2::privateCursorMoved(int x,int y,Panel* panel) +void Slider2::privateCursorMoved( int x, int y, Panel *panel ) { - if(!_dragging) + if( !_dragging ) { return; } - getApp()->getCursorPos(x,y); - screenToLocal(x,y); + getApp()->getCursorPos( x, y ); + screenToLocal( x, y ); - int wide,tall; - getPaintSize(wide,tall); + int wide, tall; + getPaintSize( wide, tall); - if(_vertical) + if( _vertical ) { - _nobPos[0]=_nobDragStartPos[0]+(y-_dragStartPos[1]); - _nobPos[1]=_nobDragStartPos[1]+(y-_dragStartPos[1]); + _nobPos[0] = _nobDragStartPos[0] + ( y - _dragStartPos[1] ); + _nobPos[1] = _nobDragStartPos[1] + ( y - _dragStartPos[1] ); - if(_nobPos[1]>tall) + if( _nobPos[1] > tall ) { - _nobPos[0]=tall-(_nobPos[1]-_nobPos[0]); - _nobPos[1]=tall; + _nobPos[0] = tall - ( _nobPos[1] - _nobPos[0] ); + _nobPos[1] = tall; } - - if(_nobPos[0]<0) + + if( _nobPos[0] < 0 ) { - _nobPos[1]=_nobPos[1]-_nobPos[0]; - _nobPos[0]=0; + _nobPos[1] = _nobPos[1] - _nobPos[0]; + _nobPos[0] = 0; } } else { - _nobPos[0]=_nobDragStartPos[0]+(x-_dragStartPos[0]); - _nobPos[1]=_nobDragStartPos[1]+(x-_dragStartPos[0]); + _nobPos[0] = _nobDragStartPos[0] + ( x - _dragStartPos[0] ); + _nobPos[1] = _nobDragStartPos[1] + ( x - _dragStartPos[0] ); - if(_nobPos[1]>wide) + if( _nobPos[1] > wide ) { - _nobPos[0]=wide-(_nobPos[1]-_nobPos[0]); - _nobPos[1]=wide; + _nobPos[0] = wide - ( _nobPos[1] - _nobPos[0] ); + _nobPos[1] = wide; } - - if(_nobPos[0]<0) + + if( _nobPos[0] < 0 ) { - _nobPos[1]=_nobPos[1]-_nobPos[0]; - _nobPos[0]=0; + _nobPos[1] = _nobPos[1] - _nobPos[0]; + _nobPos[0] = 0; } } @@ -375,62 +379,61 @@ void Slider2::privateCursorMoved(int x,int y,Panel* panel) fireIntChangeSignal(); } -void Slider2::privateMousePressed(MouseCode code,Panel* panel) +void Slider2::privateMousePressed( MouseCode code, Panel *panel ) { int x,y; - getApp()->getCursorPos(x,y); - screenToLocal(x,y); + getApp()->getCursorPos( x, y ); + screenToLocal( x, y ); - if(_vertical) + if( _vertical ) { - if((y>=_nobPos[0])&&(y<_nobPos[1])) + if( ( y >= _nobPos[0] ) && ( y < _nobPos[1] ) ) { - _dragging=true; - getApp()->setMouseCapture(this); - _nobDragStartPos[0]=_nobPos[0]; - _nobDragStartPos[1]=_nobPos[1]; - _dragStartPos[0]=x; - _dragStartPos[1]=y; + _dragging = true; + getApp()->setMouseCapture( this ); + _nobDragStartPos[0] = _nobPos[0]; + _nobDragStartPos[1] = _nobPos[1]; + _dragStartPos[0] = x; + _dragStartPos[1] = y; } } else { - if((x>=_nobPos[0])&&(x<_nobPos[1])) + if( ( x >= _nobPos[0] ) && ( x < _nobPos[1] ) ) { - _dragging=true; - getApp()->setMouseCapture(this); - _nobDragStartPos[0]=_nobPos[0]; - _nobDragStartPos[1]=_nobPos[1]; - _dragStartPos[0]=x; - _dragStartPos[1]=y; + _dragging = true; + getApp()->setMouseCapture( this ); + _nobDragStartPos[0] = _nobPos[0]; + _nobDragStartPos[1] = _nobPos[1]; + _dragStartPos[0] = x; + _dragStartPos[1] = y; } } - } -void Slider2::privateMouseReleased(MouseCode code,Panel* panel) +void Slider2::privateMouseReleased( MouseCode code, Panel *panel ) { - _dragging=false; - getApp()->setMouseCapture(null); + _dragging = false; + getApp()->setMouseCapture( null ); } -void Slider2::getNobPos(int& min, int& max) +void Slider2::getNobPos( int &min, int &max ) { - min=_nobPos[0]; - max=_nobPos[1]; + min = _nobPos[0]; + max = _nobPos[1]; } -void Slider2::setRangeWindow(int rangeWindow) +void Slider2::setRangeWindow( int rangeWindow ) { _rangeWindow=rangeWindow; } -void Slider2::setRangeWindowEnabled(bool state) +void Slider2::setRangeWindowEnabled( bool state ) { _rangeWindowEnabled=state; } -void Slider2::setButtonOffset(int buttonOffset) +void Slider2::setButtonOffset( int buttonOffset ) { _buttonOffset=buttonOffset; -} \ No newline at end of file +} diff --git a/game_shared/vgui_slider2.h b/game_shared/vgui_slider2.h index e421bba5..9f9388c8 100644 --- a/game_shared/vgui_slider2.h +++ b/game_shared/vgui_slider2.h @@ -5,22 +5,20 @@ // $NoKeywords: $ //============================================================================= #pragma once -#if !defined(VGUI_SLIDER2_H) +#ifndef VGUI_SLIDER2_H #define VGUI_SLIDER2_H -#include -#include -#include +#include +#include +#include namespace vgui { - enum MouseCode; class IntChangeSignal; class VGUIAPI Slider2 : public Panel { -private: bool _vertical; bool _dragging; int _nobPos[2]; @@ -33,31 +31,31 @@ private: bool _rangeWindowEnabled; int _buttonOffset; public: - Slider2(int x,int y,int wide,int tall,bool vertical); -public: - virtual void setValue(int value); + Slider2( int x, int y, int wide, int tall, bool vertical ); + + virtual void setValue( int value ); virtual int getValue(); virtual bool isVertical(); - virtual void addIntChangeSignal(IntChangeSignal* s); - virtual void setRange(int min,int max); - virtual void getRange(int& min,int& max); - virtual void setRangeWindow(int rangeWindow); - virtual void setRangeWindowEnabled(bool state); - virtual void setSize(int wide,int tall); - virtual void getNobPos(int& min, int& max); + virtual void addIntChangeSignal( IntChangeSignal *s ); + virtual void setRange( int min, int max ); + virtual void getRange( int &min, int &max ); + virtual void setRangeWindow( int rangeWindow ); + virtual void setRangeWindowEnabled( bool state ); + virtual void setSize( int wide, int tall ); + virtual void getNobPos( int &min, int &max ); virtual bool hasFullRange(); - virtual void setButtonOffset(int buttonOffset); + virtual void setButtonOffset( int buttonOffset ); private: virtual void recomputeNobPosFromValue(); virtual void recomputeValueFromNobPos(); -public: //bullshit public - virtual void privateCursorMoved(int x,int y,Panel* panel); - virtual void privateMousePressed(MouseCode code,Panel* panel); - virtual void privateMouseReleased(MouseCode code,Panel* panel); +public: // bullshit public + virtual void privateCursorMoved( int x, int y, Panel *panel ); + virtual void privateMousePressed( MouseCode code, Panel *panel ); + virtual void privateMouseReleased( MouseCode code, Panel *panel ); protected: - virtual void fireIntChangeSignal(); + virtual void fireIntChangeSignal(); virtual void paintBackground(); }; - } + #endif // VGUI_SLIDER2_H diff --git a/game_shared/voice_banmgr.cpp b/game_shared/voice_banmgr.cpp index 915e854f..f8241bf3 100644 --- a/game_shared/voice_banmgr.cpp +++ b/game_shared/voice_banmgr.cpp @@ -9,79 +9,73 @@ #include #include "voice_banmgr.h" - #define BANMGR_FILEVERSION 1 char const *g_pBanMgrFilename = "voice_ban.dt"; - - // Hash a player ID to a byte. -unsigned char HashPlayerID(char const playerID[16]) +unsigned char HashPlayerID( char const playerID[16] ) { unsigned char curHash = 0; - for(int i=0; i < 16; i++) + for( int i = 0; i < 16; i++ ) curHash += (unsigned char)playerID[i]; return curHash; } - - CVoiceBanMgr::CVoiceBanMgr() { Clear(); } - CVoiceBanMgr::~CVoiceBanMgr() { Term(); } - -bool CVoiceBanMgr::Init(char const *pGameDir) +bool CVoiceBanMgr::Init( char const *pGameDir ) { Term(); char filename[512]; - _snprintf(filename, sizeof(filename), "%s/%s", pGameDir, g_pBanMgrFilename); + sprintf( filename, "%s/%s", pGameDir, g_pBanMgrFilename ); // Load in the squelch file. - FILE *fp = fopen(filename, "rb"); - if(fp) + FILE *fp = fopen( filename, "rb" ); + if( fp ) { int version; - fread(&version, 1, sizeof(version), fp); - if(version == BANMGR_FILEVERSION) + fread( &version, 1, sizeof(version), fp ); + if( version == BANMGR_FILEVERSION ) { - fseek(fp, 0, SEEK_END); - int nIDs = (ftell(fp) - sizeof(version)) / 16; - fseek(fp, sizeof(version), SEEK_SET); + fseek( fp, 0, SEEK_END ); + int nIDs = ( ftell( fp ) - sizeof(version) ) / 16; + fseek( fp, sizeof(version), SEEK_SET ); - for(int i=0; i < nIDs; i++) + for( int i = 0; i < nIDs; i++ ) { char playerID[16]; - fread(playerID, 1, 16, fp); - AddBannedPlayer(playerID); - } + + fread( playerID, 1, 16, fp ); + AddBannedPlayer( playerID ); + } } - fclose(fp); + fclose( fp ); } return true; } - void CVoiceBanMgr::Term() { // Free all the player structures. - for(int i=0; i < 256; i++) + for( int i = 0; i < 256; i++ ) { BannedPlayer *pListHead = &m_PlayerHash[i]; BannedPlayer *pNext; - for(BannedPlayer *pCur=pListHead->m_pNext; pCur != pListHead; pCur=pNext) + + for( BannedPlayer *pCur=pListHead->m_pNext; pCur != pListHead; pCur = pNext ) { pNext = pCur->m_pNext; delete pCur; @@ -91,53 +85,51 @@ void CVoiceBanMgr::Term() Clear(); } - void CVoiceBanMgr::SaveState(char const *pGameDir) { // Save the file out. char filename[512]; - _snprintf(filename, sizeof(filename), "%s/%s", pGameDir, g_pBanMgrFilename); - FILE *fp = fopen(filename, "wb"); - if(fp) + sprintf( filename, "%s/%s", pGameDir, g_pBanMgrFilename ); + + FILE *fp = fopen( filename, "wb" ); + if( fp ) { int version = BANMGR_FILEVERSION; - fwrite(&version, 1, sizeof(version), fp); + fwrite( &version, 1, sizeof(version), fp ); - for(int i=0; i < 256; i++) + for( int i = 0; i < 256; i++ ) { BannedPlayer *pListHead = &m_PlayerHash[i]; - for(BannedPlayer *pCur=pListHead->m_pNext; pCur != pListHead; pCur=pCur->m_pNext) + for( BannedPlayer *pCur = pListHead->m_pNext; pCur != pListHead; pCur = pCur->m_pNext ) { - fwrite(pCur->m_PlayerID, 1, 16, fp); + fwrite( pCur->m_PlayerID, 1, 16, fp ); } } - fclose(fp); + fclose( fp ); } } - -bool CVoiceBanMgr::GetPlayerBan(char const playerID[16]) +bool CVoiceBanMgr::GetPlayerBan( char const playerID[16] ) { - return !!InternalFindPlayerSquelch(playerID); + return !!InternalFindPlayerSquelch( playerID ); } - -void CVoiceBanMgr::SetPlayerBan(char const playerID[16], bool bSquelch) +void CVoiceBanMgr::SetPlayerBan( char const playerID[16], bool bSquelch ) { - if(bSquelch) + if( bSquelch ) { // Is this guy already squelched? - if(GetPlayerBan(playerID)) + if( GetPlayerBan( playerID ) ) return; - - AddBannedPlayer(playerID); + + AddBannedPlayer( playerID ); } else { - BannedPlayer *pPlayer = InternalFindPlayerSquelch(playerID); - if(pPlayer) + BannedPlayer *pPlayer = InternalFindPlayerSquelch( playerID ); + if( pPlayer ) { pPlayer->m_pPrev->m_pNext = pPlayer->m_pNext; pPlayer->m_pNext->m_pPrev = pPlayer->m_pPrev; @@ -146,52 +138,51 @@ void CVoiceBanMgr::SetPlayerBan(char const playerID[16], bool bSquelch) } } - -void CVoiceBanMgr::ForEachBannedPlayer(void (*callback)(char id[16])) +void CVoiceBanMgr::ForEachBannedPlayer(void (*callback)( char id[16] ) ) { - for(int i=0; i < 256; i++) + for( int i = 0; i < 256; i++ ) { - for(BannedPlayer *pCur=m_PlayerHash[i].m_pNext; pCur != &m_PlayerHash[i]; pCur=pCur->m_pNext) + for( BannedPlayer *pCur = m_PlayerHash[i].m_pNext; pCur != &m_PlayerHash[i]; pCur = pCur->m_pNext ) { - callback(pCur->m_PlayerID); + callback( pCur->m_PlayerID ); } } } - void CVoiceBanMgr::Clear() { // Tie off the hash table entries. - for(int i=0; i < 256; i++) + for( int i = 0; i < 256; i++ ) m_PlayerHash[i].m_pNext = m_PlayerHash[i].m_pPrev = &m_PlayerHash[i]; } - -CVoiceBanMgr::BannedPlayer* CVoiceBanMgr::InternalFindPlayerSquelch(char const playerID[16]) +CVoiceBanMgr::BannedPlayer *CVoiceBanMgr::InternalFindPlayerSquelch( char const playerID[16] ) { - int index = HashPlayerID(playerID); + int index = HashPlayerID( playerID ); + BannedPlayer *pListHead = &m_PlayerHash[index]; - for(BannedPlayer *pCur=pListHead->m_pNext; pCur != pListHead; pCur=pCur->m_pNext) + for( BannedPlayer *pCur = pListHead->m_pNext; pCur != pListHead; pCur=pCur->m_pNext ) { - if(memcmp(playerID, pCur->m_PlayerID, 16) == 0) + if( memcmp( playerID, pCur->m_PlayerID, 16 ) == 0 ) return pCur; } return NULL; } - -CVoiceBanMgr::BannedPlayer* CVoiceBanMgr::AddBannedPlayer(char const playerID[16]) +CVoiceBanMgr::BannedPlayer* CVoiceBanMgr::AddBannedPlayer( char const playerID[16] ) { BannedPlayer *pNew = new BannedPlayer; - if(!pNew) + if( !pNew ) return NULL; - int index = HashPlayerID(playerID); - memcpy(pNew->m_PlayerID, playerID, 16); + int index = HashPlayerID( playerID ); + + memcpy( pNew->m_PlayerID, playerID, 16 ); pNew->m_pNext = &m_PlayerHash[index]; pNew->m_pPrev = m_PlayerHash[index].m_pPrev; pNew->m_pPrev->m_pNext = pNew->m_pNext->m_pPrev = pNew; + return pNew; } diff --git a/game_shared/voice_banmgr.h b/game_shared/voice_banmgr.h index 4c4f7b63..64c0c2bb 100644 --- a/game_shared/voice_banmgr.h +++ b/game_shared/voice_banmgr.h @@ -5,47 +5,42 @@ // $NoKeywords: $ //============================================================================= #pragma once -#if !defined(VOICE_BANMGR_H) +#ifndef VOICE_BANMGR_H #define VOICE_BANMGR_H // This class manages the (persistent) list of squelched players. class CVoiceBanMgr { public: - - CVoiceBanMgr(); - ~CVoiceBanMgr(); + CVoiceBanMgr(); + ~CVoiceBanMgr(); // Init loads the list of squelched players from disk. - bool Init(char const *pGameDir); + bool Init( char const *pGameDir ); void Term(); // Saves the state into voice_squelch.dt. - void SaveState(char const *pGameDir); + void SaveState( char const *pGameDir ); - bool GetPlayerBan(char const playerID[16]); - void SetPlayerBan(char const playerID[16], bool bSquelch); + bool GetPlayerBan( char const playerID[16] ); + void SetPlayerBan( char const playerID[16], bool bSquelch ); // Call your callback for each banned player. - void ForEachBannedPlayer(void (*callback)(char id[16])); - + void ForEachBannedPlayer( void (*callback)( char id[16] ) ); protected: - class BannedPlayer { public: - char m_PlayerID[16]; + char m_PlayerID[16]; BannedPlayer *m_pPrev, *m_pNext; }; - void Clear(); - BannedPlayer* InternalFindPlayerSquelch(char const playerID[16]); - BannedPlayer* AddBannedPlayer(char const playerID[16]); - - -protected: + void Clear(); + BannedPlayer *InternalFindPlayerSquelch( char const playerID[16] ); + BannedPlayer *AddBannedPlayer( char const playerID[16] ); BannedPlayer m_PlayerHash[256]; }; #endif // VOICE_BANMGR_H + diff --git a/game_shared/voice_common.h b/game_shared/voice_common.h index 58225955..c32011a3 100644 --- a/game_shared/voice_common.h +++ b/game_shared/voice_common.h @@ -5,14 +5,14 @@ // $NoKeywords: $ //============================================================================= #pragma once -#if !defined(VOICE_COMMON_H) +#ifndef VOICE_COMMON_H #define VOICE_COMMON_H #include "bitvec.h" - #define VOICE_MAX_PLAYERS 32 // (todo: this should just be set to MAX_CLIENTS). -#define VOICE_MAX_PLAYERS_DW ((VOICE_MAX_PLAYERS / 32) + !!(VOICE_MAX_PLAYERS & 31)) +#define VOICE_MAX_PLAYERS_DW ((VOICE_MAX_PLAYERS / 32) + !!(VOICE_MAX_PLAYERS & 31)) typedef CBitVec CPlayerBitVec; #endif // VOICE_COMMON_H + diff --git a/game_shared/voice_gamemgr.cpp b/game_shared/voice_gamemgr.cpp index 403d4320..086c715c 100644 --- a/game_shared/voice_gamemgr.cpp +++ b/game_shared/voice_gamemgr.cpp @@ -1,10 +1,11 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +//========= Copyright (c) 1996-2002, Valve LLC, All rights reserved. ============ // -// Purpose: +// Purpose: // // $NoKeywords: $ //============================================================================= +#include "archtypes.h" // DAL #include "voice_gamemgr.h" #include #include @@ -13,8 +14,11 @@ #include "cbase.h" #include "player.h" + + #define UPDATE_INTERVAL 0.3 + // These are stored off as CVoiceGameMgr is created and deleted. CPlayerBitVec g_PlayerModEnable; // Set to 1 for each player if the player wants to use voice in this mod. // (If it's zero, then the server reports that the game rules are saying the @@ -32,24 +36,25 @@ cvar_t voice_serverdebug = {"voice_serverdebug", "0"}; // Set game rules to allow all clients to talk to each other. // Muted players still can't talk to each other. -cvar_t sv_alltalk = {"sv_alltalk", "0"}; +cvar_t sv_alltalk = {"sv_alltalk", "0", FCVAR_SERVER}; // ------------------------------------------------------------------------ // // Static helpers. // ------------------------------------------------------------------------ // + // Find a player with a case-insensitive name search. -static CBasePlayer* FindPlayerByName( const char *pTestName ) +static CBasePlayer* FindPlayerByName(const char *pTestName) { - for( int i = 1; i <= gpGlobals->maxClients; i++ ) + for(int i=1; i <= gpGlobals->maxClients; i++) { - edict_t *pEdict = g_engfuncs.pfnPEntityOfEntIndex( i ); - if( pEdict ) + edict_t *pEdict = g_engfuncs.pfnPEntityOfEntIndex(i); + if(pEdict) { - CBaseEntity *pEnt = CBaseEntity::Instance( pEdict ); - if( pEnt && pEnt->IsPlayer() ) - { - const char *pNetName = STRING( pEnt->pev->netname ); - if( stricmp( pNetName, pTestName ) == 0 ) + CBaseEntity *pEnt = CBaseEntity::Instance(pEdict); + if(pEnt && pEnt->IsPlayer()) + { + const char *pNetName = STRING(pEnt->pev->netname); + if(stricmp(pNetName, pTestName) == 0) { return (CBasePlayer*)pEnt; } @@ -75,30 +80,37 @@ static void VoiceServerDebug( char const *pFmt, ... ) ALERT( at_console, "%s", msg ); } + + // ------------------------------------------------------------------------ // // CVoiceGameMgr. // ------------------------------------------------------------------------ // + CVoiceGameMgr::CVoiceGameMgr() { m_UpdateInterval = 0; m_nMaxPlayers = 0; } + CVoiceGameMgr::~CVoiceGameMgr() { } -bool CVoiceGameMgr::Init( IVoiceGameMgrHelper *pHelper, int maxClients ) + +bool CVoiceGameMgr::Init( + IVoiceGameMgrHelper *pHelper, + int maxClients) { m_pHelper = pHelper; m_nMaxPlayers = VOICE_MAX_PLAYERS < maxClients ? VOICE_MAX_PLAYERS : maxClients; - g_engfuncs.pfnPrecacheModel( "sprites/voiceicon.spr" ); + g_engfuncs.pfnPrecacheModel("sprites/voiceicon.spr"); - m_msgPlayerVoiceMask = REG_USER_MSG( "VoiceMask", VOICE_MAX_PLAYERS_DW * 4 * 2 ); + m_msgPlayerVoiceMask = REG_USER_MSG( "VoiceMask", VOICE_MAX_PLAYERS_DW*4 * 2 ); m_msgRequestState = REG_USER_MSG( "ReqState", 0 ); // register voice_serverdebug if it hasn't been registered already - if( !CVAR_GET_POINTER( "voice_serverdebug" ) ) + if ( !CVAR_GET_POINTER( "voice_serverdebug" ) ) CVAR_REGISTER( &voice_serverdebug ); if( !CVAR_GET_POINTER( "sv_alltalk" ) ) @@ -107,70 +119,73 @@ bool CVoiceGameMgr::Init( IVoiceGameMgrHelper *pHelper, int maxClients ) return true; } -void CVoiceGameMgr::SetHelper( IVoiceGameMgrHelper *pHelper ) + +void CVoiceGameMgr::SetHelper(IVoiceGameMgrHelper *pHelper) { m_pHelper = pHelper; } -void CVoiceGameMgr::Update( double frametime ) + +void CVoiceGameMgr::Update(double frametime) { // Only update periodically. m_UpdateInterval += frametime; - if( m_UpdateInterval < UPDATE_INTERVAL ) + if(m_UpdateInterval < UPDATE_INTERVAL) return; UpdateMasks(); } -void CVoiceGameMgr::ClientConnected( edict_t *pEdict ) + +void CVoiceGameMgr::ClientConnected(edict_t *pEdict) { - int index = ENTINDEX( pEdict ) - 1; + int index = ENTINDEX(pEdict) - 1; // Clear out everything we use for deltas on this guy. g_bWantModEnable[index] = true; - g_SentGameRulesMasks[index].Init( 0 ); - g_SentBanMasks[index].Init( 0 ); + g_SentGameRulesMasks[index].Init(0); + g_SentBanMasks[index].Init(0); } // Called to determine if the Receiver has muted (blocked) the Sender // Returns true if the receiver has blocked the sender -bool CVoiceGameMgr::PlayerHasBlockedPlayer( CBasePlayer *pReceiver, CBasePlayer *pSender ) +bool CVoiceGameMgr::PlayerHasBlockedPlayer(CBasePlayer *pReceiver, CBasePlayer *pSender) { int iReceiverIndex, iSenderIndex; - if( !pReceiver || !pSender ) + if ( !pReceiver || !pSender ) return false; iReceiverIndex = pReceiver->entindex() - 1; - iSenderIndex = pSender->entindex() - 1; + iSenderIndex = pSender->entindex() - 1; - if( iReceiverIndex < 0 || iReceiverIndex >= m_nMaxPlayers || iSenderIndex < 0 || iSenderIndex >= m_nMaxPlayers ) + if ( iReceiverIndex < 0 || iReceiverIndex >= m_nMaxPlayers || iSenderIndex < 0 || iSenderIndex >= m_nMaxPlayers ) return false; return ( g_BanMasks[iReceiverIndex][iSenderIndex] ? true : false ); } -bool CVoiceGameMgr::ClientCommand( CBasePlayer *pPlayer, const char *cmd ) +bool CVoiceGameMgr::ClientCommand(CBasePlayer *pPlayer, const char *cmd) { int playerClientIndex = pPlayer->entindex() - 1; - if( playerClientIndex < 0 || playerClientIndex >= m_nMaxPlayers ) + if(playerClientIndex < 0 || playerClientIndex >= m_nMaxPlayers) { VoiceServerDebug( "CVoiceGameMgr::ClientCommand: cmd %s from invalid client (%d)\n", cmd, playerClientIndex ); return true; } - bool bBan = stricmp( cmd, "vban" ) == 0; - if( bBan && CMD_ARGC() >= 2 ) + bool bBan = stricmp(cmd, "vban") == 0; + if(bBan && CMD_ARGC() >= 2) { - for( int i = 1; i < CMD_ARGC(); i++ ) + for(int i=1; i < CMD_ARGC(); i++) { - unsigned long mask = 0; - sscanf( CMD_ARGV(i), "%lx", &mask ); + uint32 mask = 0; + sscanf(CMD_ARGV(i), "%x", &mask); - if( i <= VOICE_MAX_PLAYERS_DW ) + if(i <= VOICE_MAX_PLAYERS_DW) { VoiceServerDebug( "CVoiceGameMgr::ClientCommand: vban (0x%x) from %d\n", mask, playerClientIndex ); - g_BanMasks[playerClientIndex].SetDWord( i - 1, mask ); + g_BanMasks[playerClientIndex].SetDWord(i-1, mask); } else { @@ -179,15 +194,15 @@ bool CVoiceGameMgr::ClientCommand( CBasePlayer *pPlayer, const char *cmd ) } // Force it to update the masks now. - //UpdateMasks(); + // UpdateMasks(); return true; } - else if( stricmp( cmd, "VModEnable" ) == 0 && CMD_ARGC() >= 2 ) + else if(stricmp(cmd, "VModEnable") == 0 && CMD_ARGC() >= 2) { - VoiceServerDebug( "CVoiceGameMgr::ClientCommand: VModEnable (%d)\n", !!atoi( CMD_ARGV( 1 ) ) ); - g_PlayerModEnable[playerClientIndex] = !!atoi( CMD_ARGV( 1 ) ); + VoiceServerDebug( "CVoiceGameMgr::ClientCommand: VModEnable (%d)\n", !!atoi(CMD_ARGV(1)) ); + g_PlayerModEnable[playerClientIndex] = !!atoi(CMD_ARGV(1)); g_bWantModEnable[playerClientIndex] = false; - //UpdateMasks(); + // UpdateMasks(); return true; } else @@ -196,22 +211,23 @@ bool CVoiceGameMgr::ClientCommand( CBasePlayer *pPlayer, const char *cmd ) } } + void CVoiceGameMgr::UpdateMasks() { m_UpdateInterval = 0; - bool bAllTalk = !!g_engfuncs.pfnCVarGetFloat( "sv_alltalk" ); + bool bAllTalk = !!(sv_alltalk.value); - for( int iClient = 0; iClient < m_nMaxPlayers; iClient++ ) + for(int iClient=0; iClient < m_nMaxPlayers; iClient++) { - CBaseEntity *pEnt = UTIL_PlayerByIndex( iClient + 1 ); - if( !pEnt || !pEnt->IsPlayer() ) + CBaseEntity *pEnt = UTIL_PlayerByIndex(iClient+1); + if(!pEnt || !pEnt->IsPlayer()) continue; // Request the state of their "VModEnable" cvar. - if( g_bWantModEnable[iClient] ) + if(g_bWantModEnable[iClient]) { - MESSAGE_BEGIN( MSG_ONE, m_msgRequestState, NULL, pEnt->pev ); + MESSAGE_BEGIN(MSG_ONE, m_msgRequestState, NULL, pEnt->pev); MESSAGE_END(); } @@ -221,10 +237,10 @@ void CVoiceGameMgr::UpdateMasks() if( g_PlayerModEnable[iClient] ) { // Build a mask of who they can hear based on the game rules. - for( int iOtherClient = 0; iOtherClient < m_nMaxPlayers; iOtherClient++ ) + for(int iOtherClient=0; iOtherClient < m_nMaxPlayers; iOtherClient++) { - pEnt = UTIL_PlayerByIndex( iOtherClient + 1 ); - if( pEnt && pEnt->IsPlayer() && ( bAllTalk || m_pHelper->CanPlayerHearPlayer( pPlayer, (CBasePlayer*)pEnt ) ) ) + CBaseEntity *pEnt = UTIL_PlayerByIndex(iOtherClient+1); + if(pEnt && (bAllTalk || m_pHelper->CanPlayerHearPlayer(pPlayer, (CBasePlayer*)pEnt)) ) { gameRulesMask[iOtherClient] = true; } @@ -232,26 +248,27 @@ void CVoiceGameMgr::UpdateMasks() } // If this is different from what the client has, send an update. - if( gameRulesMask != g_SentGameRulesMasks[iClient] || g_BanMasks[iClient] != g_SentBanMasks[iClient] ) + if(gameRulesMask != g_SentGameRulesMasks[iClient] || + g_BanMasks[iClient] != g_SentBanMasks[iClient]) { g_SentGameRulesMasks[iClient] = gameRulesMask; g_SentBanMasks[iClient] = g_BanMasks[iClient]; - MESSAGE_BEGIN( MSG_ONE, m_msgPlayerVoiceMask, NULL, pPlayer->pev ); + MESSAGE_BEGIN(MSG_ONE, m_msgPlayerVoiceMask, NULL, pPlayer->pev); int dw; - for( dw = 0; dw < VOICE_MAX_PLAYERS_DW; dw++ ) + for(dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++) { - WRITE_LONG( gameRulesMask.GetDWord( dw ) ); - WRITE_LONG( g_BanMasks[iClient].GetDWord( dw ) ); + WRITE_LONG(gameRulesMask.GetDWord(dw)); + WRITE_LONG(g_BanMasks[iClient].GetDWord(dw)); } MESSAGE_END(); } // Tell the engine. - for( int iOtherClient = 0; iOtherClient < m_nMaxPlayers; iOtherClient++ ) + for(int iOtherClient=0; iOtherClient < m_nMaxPlayers; iOtherClient++) { bool bCanHear = gameRulesMask[iOtherClient] && !g_BanMasks[iClient][iOtherClient]; - g_engfuncs.pfnVoice_SetClientListening( iClient + 1, iOtherClient + 1, bCanHear ); + g_engfuncs.pfnVoice_SetClientListening(iClient+1, iOtherClient+1, bCanHear); } } } diff --git a/game_shared/voice_gamemgr.h b/game_shared/voice_gamemgr.h index f6e9d92c..cdbb8815 100644 --- a/game_shared/voice_gamemgr.h +++ b/game_shared/voice_gamemgr.h @@ -1,66 +1,80 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +//========= Copyright � 1996-2002, Valve LLC, All rights reserved. ============ // // Purpose: // // $NoKeywords: $ //============================================================================= #pragma once -#if !defined(VOICE_GAMEMGR_H) +#ifndef VOICE_GAMEMGR_H #define VOICE_GAMEMGR_H +#ifdef _WIN32 +#endif + + #include "voice_common.h" + class CGameRules; class CBasePlayer; + class IVoiceGameMgrHelper { public: - virtual ~IVoiceGameMgrHelper() {} + virtual ~IVoiceGameMgrHelper() {} // Called each frame to determine which players are allowed to hear each other. This overrides // whatever squelch settings players have. - virtual bool CanPlayerHearPlayer( CBasePlayer *pListener, CBasePlayer *pTalker ) = 0; + virtual bool CanPlayerHearPlayer(CBasePlayer *pListener, CBasePlayer *pTalker) = 0; }; + // CVoiceGameMgr manages which clients can hear which other clients. class CVoiceGameMgr { public: - CVoiceGameMgr(); - virtual ~CVoiceGameMgr(); + CVoiceGameMgr(); + virtual ~CVoiceGameMgr(); + + bool Init( + IVoiceGameMgrHelper *m_pHelper, + int maxClients + ); - bool Init( IVoiceGameMgrHelper *m_pHelper, int maxClients ); - - void SetHelper( IVoiceGameMgrHelper *pHelper ); + void SetHelper(IVoiceGameMgrHelper *pHelper); // Updates which players can hear which other players. // If gameplay mode is DM, then only players within the PVS can hear each other. // If gameplay mode is teamplay, then only players on the same team can hear each other. // Player masks are always applied. - void Update( double frametime ); + void Update(double frametime); // Called when a new client connects (unsquelches its entity for everyone). - void ClientConnected( struct edict_s *pEdict ); + void ClientConnected(struct edict_s *pEdict); // Called on ClientCommand. Checks for the squelch and unsquelch commands. // Returns true if it handled the command. - bool ClientCommand( CBasePlayer *pPlayer, const char *cmd ); + bool ClientCommand(CBasePlayer *pPlayer, const char *cmd); // Called to determine if the Receiver has muted (blocked) the Sender // Returns true if the receiver has blocked the sender - bool PlayerHasBlockedPlayer( CBasePlayer *pReceiver, CBasePlayer *pSender ); + bool PlayerHasBlockedPlayer(CBasePlayer *pReceiver, CBasePlayer *pSender); + private: + // Force it to update the client masks. - void UpdateMasks(); + void UpdateMasks(); -private: - int m_msgPlayerVoiceMask; - int m_msgRequestState; - IVoiceGameMgrHelper *m_pHelper; - int m_nMaxPlayers; - double m_UpdateInterval; // How long since the last update. + int m_msgPlayerVoiceMask; + int m_msgRequestState; + + IVoiceGameMgrHelper *m_pHelper; + int m_nMaxPlayers; + double m_UpdateInterval; // How long since the last update. }; + + #endif // VOICE_GAMEMGR_H diff --git a/game_shared/voice_status.cpp b/game_shared/voice_status.cpp index 57bc0f16..cbc81e81 100644 --- a/game_shared/voice_status.cpp +++ b/game_shared/voice_status.cpp @@ -6,34 +6,16 @@ //============================================================================= // There are hud.h's coming out of the woodwork so this ensures that we get the right one. -#if defined( DMC_BUILD ) - #include "../dmc/cl_dll/hud.h" - #include "../dmc/cl_dll/cl_util.h" -#elif defined( RICOCHET_BUILD ) - #include "../ricochet/cl_dll/hud.h" - #include "../ricochet/cl_dll/cl_util.h" -#else - #include "../cl_dll/hud.h" - #include "../cl_dll/cl_util.h" -#endif +#include "../cl_dll/hud.h" +#include "../cl_dll/cl_util.h" #include #include #include -#if defined( DMC_BUILD ) - #include "../dmc/cl_dll/parsemsg.h" - #include "../dmc/cl_dll/hud_servers.h" - #include "../dmc/cl_dll/demo.h" -#elif defined( RICOCHET_BUILD ) - #include "../ricochet/cl_dll/parsemsg.h" - #include "../ricochet/cl_dll/hud_servers.h" - #include "../ricochet/cl_dll/demo.h" -#else - #include "../cl_dll/parsemsg.h" - #include "../cl_dll/hud_servers.h" - #include "../cl_dll/demo.h" -#endif +#include "../cl_dll/parsemsg.h" +#include "../cl_dll/hud_servers.h" +#include "../cl_dll/demo.h" #include "demo_api.h" #include "voice_status.h" @@ -46,23 +28,16 @@ #include "vgui_helpers.h" #include "vgui_mousecode.h" - - using namespace vgui; - extern int cam_thirdperson; - #define VOICE_MODEL_INTERVAL 0.3 #define SCOREBOARD_BLINK_FREQUENCY 0.3 // How often to blink the scoreboard icons. #define SQUELCHOSCILLATE_PER_SECOND 2.0f - extern BitmapTGA *LoadTGA( const char* pImageName ); - - // ---------------------------------------------------------------------- // // The voice manager for the client. // ---------------------------------------------------------------------- // @@ -73,63 +48,60 @@ CVoiceStatus* GetClientVoiceMgr() return &g_VoiceStatus; } - - // ---------------------------------------------------------------------- // // CVoiceStatus. // ---------------------------------------------------------------------- // - static CVoiceStatus *g_pInternalVoiceStatus = NULL; -int __MsgFunc_VoiceMask(const char *pszName, int iSize, void *pbuf) +int __MsgFunc_VoiceMask( const char *pszName, int iSize, void *pbuf ) { - if(g_pInternalVoiceStatus) - g_pInternalVoiceStatus->HandleVoiceMaskMsg(iSize, pbuf); + if( g_pInternalVoiceStatus ) + g_pInternalVoiceStatus->HandleVoiceMaskMsg( iSize, pbuf ); return 1; } -int __MsgFunc_ReqState(const char *pszName, int iSize, void *pbuf) +int __MsgFunc_ReqState( const char *pszName, int iSize, void *pbuf ) { - if(g_pInternalVoiceStatus) - g_pInternalVoiceStatus->HandleReqStateMsg(iSize, pbuf); + if( g_pInternalVoiceStatus ) + g_pInternalVoiceStatus->HandleReqStateMsg( iSize, pbuf ); return 1; } - int g_BannedPlayerPrintCount; -void ForEachBannedPlayer(char id[16]) + +void ForEachBannedPlayer( char id[16] ) { char str[256]; - sprintf(str, "Ban %d: %2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x\n", + + sprintf( str, "Ban %d: %2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x\n", g_BannedPlayerPrintCount++, id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], id[8], id[9], id[10], id[11], id[12], id[13], id[14], id[15] ); - strupr(str); + + strupr( str ); + gEngfuncs.pfnConsolePrint(str); } - void ShowBannedCallback() { - if(g_pInternalVoiceStatus) + if( g_pInternalVoiceStatus ) { g_BannedPlayerPrintCount = 0; gEngfuncs.pfnConsolePrint("------- BANNED PLAYERS -------\n"); - g_pInternalVoiceStatus->m_BanMgr.ForEachBannedPlayer(ForEachBannedPlayer); + g_pInternalVoiceStatus->m_BanMgr.ForEachBannedPlayer( ForEachBannedPlayer ); gEngfuncs.pfnConsolePrint("------------------------------\n"); } } - // ---------------------------------------------------------------------- // // CVoiceStatus. // ---------------------------------------------------------------------- // - CVoiceStatus::CVoiceStatus() { m_bBanMgrInitialized = false; @@ -142,84 +114,80 @@ CVoiceStatus::CVoiceStatus() m_pScoreboardSpeaking2 = NULL; m_pScoreboardSquelch = NULL; m_pScoreboardBanned = NULL; - + m_pLocalBitmap = NULL; m_pAckBitmap = NULL; m_bTalking = m_bServerAcked = false; - memset(m_pBanButtons, 0, sizeof(m_pBanButtons)); + memset( m_pBanButtons, 0, sizeof(m_pBanButtons) ); m_bServerModEnable = -1; m_pchGameDir = NULL; } - CVoiceStatus::~CVoiceStatus() { g_pInternalVoiceStatus = NULL; - - for(int i=0; i < MAX_VOICE_SPEAKERS; i++) + + for( int i = 0; i < MAX_VOICE_SPEAKERS; i++ ) { delete m_Labels[i].m_pLabel; m_Labels[i].m_pLabel = NULL; delete m_Labels[i].m_pIcon; m_Labels[i].m_pIcon = NULL; - + delete m_Labels[i].m_pBackground; m_Labels[i].m_pBackground = NULL; - } + } delete m_pLocalLabel; m_pLocalLabel = NULL; FreeBitmaps(); - if(m_pchGameDir) + if( m_pchGameDir ) { - if(m_bBanMgrInitialized) + if( m_bBanMgrInitialized ) { - m_BanMgr.SaveState(m_pchGameDir); + m_BanMgr.SaveState( m_pchGameDir ); } - free(m_pchGameDir); + free( m_pchGameDir ); } } - -int CVoiceStatus::Init( - IVoiceStatusHelper *pHelper, - Panel **pParentPanel) +int CVoiceStatus::Init( IVoiceStatusHelper *pHelper, Panel **pParentPanel ) { // Setup the voice_modenable cvar. - gEngfuncs.pfnRegisterVariable("voice_modenable", "1", FCVAR_ARCHIVE); + gEngfuncs.pfnRegisterVariable( "voice_modenable", "1", FCVAR_ARCHIVE ); - gEngfuncs.pfnRegisterVariable("voice_clientdebug", "0", 0); + gEngfuncs.pfnRegisterVariable( "voice_clientdebug", "0", 0 ); - gEngfuncs.pfnAddCommand("voice_showbanned", ShowBannedCallback); + gEngfuncs.pfnAddCommand( "voice_showbanned", ShowBannedCallback ); - if(gEngfuncs.pfnGetGameDirectory()) + if( gEngfuncs.pfnGetGameDirectory() ) { - m_BanMgr.Init(gEngfuncs.pfnGetGameDirectory()); + m_BanMgr.Init( gEngfuncs.pfnGetGameDirectory() ); m_bBanMgrInitialized = true; } - assert(!g_pInternalVoiceStatus); + assert( !g_pInternalVoiceStatus ); g_pInternalVoiceStatus = this; m_BlinkTimer = 0; m_VoiceHeadModel = NULL; - memset(m_Labels, 0, sizeof(m_Labels)); - - for(int i=0; i < MAX_VOICE_SPEAKERS; i++) + memset( m_Labels, 0, sizeof(m_Labels) ); + + for( int i = 0; i < MAX_VOICE_SPEAKERS; i++ ) { CVoiceLabel *pLabel = &m_Labels[i]; - pLabel->m_pBackground = new Label(""); + pLabel->m_pBackground = new Label( "" ); - if(pLabel->m_pLabel = new Label("")) + if( pLabel->m_pLabel = new Label( "" ) ) { pLabel->m_pLabel->setVisible( true ); pLabel->m_pLabel->setFont( Scheme::sf_primary2 ); @@ -237,92 +205,90 @@ int CVoiceStatus::Init( pLabel->m_clientindex = -1; } - m_pLocalLabel = new ImagePanel(NULL); + m_pLocalLabel = new ImagePanel( NULL ); m_bInSquelchMode = false; m_pHelper = pHelper; m_pParentPanel = pParentPanel; - gHUD.AddHudElem(this); + gHUD.AddHudElem( this ); m_iFlags = HUD_ACTIVE; - HOOK_MESSAGE(VoiceMask); - HOOK_MESSAGE(ReqState); + HOOK_MESSAGE( VoiceMask ); + HOOK_MESSAGE( ReqState ); // Cache the game directory for use when we shut down const char *pchGameDirT = gEngfuncs.pfnGetGameDirectory(); - m_pchGameDir = (char *)malloc(strlen(pchGameDirT) + 1); - strcpy(m_pchGameDir, pchGameDirT); + m_pchGameDir = (char *)malloc( strlen( pchGameDirT ) + 1 ); + strcpy( m_pchGameDir, pchGameDirT ); return 1; } - int CVoiceStatus::VidInit() { FreeBitmaps(); - - if( m_pLocalBitmap = vgui_LoadTGA("gfx/vgui/icntlk_pl.tga") ) + if( m_pLocalBitmap = vgui_LoadTGA( "gfx/vgui/icntlk_pl.tga" ) ) { - m_pLocalBitmap->setColor(Color(255,255,255,135)); + m_pLocalBitmap->setColor( Color( 255, 255, 255, 135 ) ); } - if( m_pAckBitmap = vgui_LoadTGA("gfx/vgui/icntlk_sv.tga") ) + if( m_pAckBitmap = vgui_LoadTGA( "gfx/vgui/icntlk_sv.tga" ) ) { - m_pAckBitmap->setColor(Color(255,255,255,135)); // Give just a tiny bit of translucency so software draws correctly. + m_pAckBitmap->setColor( Color( 255, 255, 255, 135 ) ); // Give just a tiny bit of translucency so software draws correctly. } m_pLocalLabel->setImage( m_pLocalBitmap ); m_pLocalLabel->setVisible( false ); + if( m_pSpeakerLabelIcon = vgui_LoadTGANoInvertAlpha( "gfx/vgui/speaker4.tga" ) ) + m_pSpeakerLabelIcon->setColor( Color( 255, 255, 255, 1 ) ); // Give just a tiny bit of translucency so software draws correctly. - if( m_pSpeakerLabelIcon = vgui_LoadTGANoInvertAlpha("gfx/vgui/speaker4.tga" ) ) - m_pSpeakerLabelIcon->setColor( Color(255,255,255,1) ); // Give just a tiny bit of translucency so software draws correctly. + if( m_pScoreboardNeverSpoken = vgui_LoadTGANoInvertAlpha( "gfx/vgui/640_speaker1.tga" ) ) + m_pScoreboardNeverSpoken->setColor( Color( 255, 255, 255, 1 ) ); // Give just a tiny bit of translucency so software draws correctly. - if (m_pScoreboardNeverSpoken = vgui_LoadTGANoInvertAlpha("gfx/vgui/640_speaker1.tga")) - m_pScoreboardNeverSpoken->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. + if( m_pScoreboardNotSpeaking = vgui_LoadTGANoInvertAlpha( "gfx/vgui/640_speaker2.tga" ) ) + m_pScoreboardNotSpeaking->setColor( Color( 255, 255, 255, 1 ) ); // Give just a tiny bit of translucency so software draws correctly. - if(m_pScoreboardNotSpeaking = vgui_LoadTGANoInvertAlpha("gfx/vgui/640_speaker2.tga")) - m_pScoreboardNotSpeaking->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. - - if(m_pScoreboardSpeaking = vgui_LoadTGANoInvertAlpha("gfx/vgui/640_speaker3.tga")) - m_pScoreboardSpeaking->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. - - if(m_pScoreboardSpeaking2 = vgui_LoadTGANoInvertAlpha("gfx/vgui/640_speaker4.tga")) - m_pScoreboardSpeaking2->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. - - if(m_pScoreboardSquelch = vgui_LoadTGA("gfx/vgui/icntlk_squelch.tga")) - m_pScoreboardSquelch->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. + if( m_pScoreboardSpeaking = vgui_LoadTGANoInvertAlpha( "gfx/vgui/640_speaker3.tga" ) ) + m_pScoreboardSpeaking->setColor( Color( 255, 255, 255, 1 ) ); // Give just a tiny bit of translucency so software draws correctly. - if(m_pScoreboardBanned = vgui_LoadTGA("gfx/vgui/640_voiceblocked.tga")) - m_pScoreboardBanned->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. + if( m_pScoreboardSpeaking2 = vgui_LoadTGANoInvertAlpha( "gfx/vgui/640_speaker4.tga" ) ) + m_pScoreboardSpeaking2->setColor( Color( 255, 255, 255, 1 ) ); // Give just a tiny bit of translucency so software draws correctly. + + if( m_pScoreboardSquelch = vgui_LoadTGA( "gfx/vgui/icntlk_squelch.tga" ) ) + m_pScoreboardSquelch->setColor( Color( 255, 255, 255, 1 ) ); // Give just a tiny bit of translucency so software draws correctly. + + if( m_pScoreboardBanned = vgui_LoadTGA( "gfx/vgui/640_voiceblocked.tga" ) ) + m_pScoreboardBanned->setColor( Color( 255, 255, 255, 1 ) ); // Give just a tiny bit of translucency so software draws correctly. // Figure out the voice head model height. m_VoiceHeadModelHeight = 45; - char *pFile = (char *)gEngfuncs.COM_LoadFile("scripts/voicemodel.txt", 5, NULL); - if(pFile) + char *pFile = (char *)gEngfuncs.COM_LoadFile( "scripts/voicemodel.txt", 5, NULL ); + if( pFile ) { char token[4096]; - gEngfuncs.COM_ParseFile(pFile, token); - if(token[0] >= '0' && token[0] <= '9') + + gEngfuncs.COM_ParseFile( pFile, token ); + if( token[0] >= '0' && token[0] <= '9' ) { - m_VoiceHeadModelHeight = (float)atof(token); + m_VoiceHeadModelHeight = (float)atof( token ); } - gEngfuncs.COM_FreeFile(pFile); + gEngfuncs.COM_FreeFile( pFile ); } - m_VoiceHeadModel = gEngfuncs.pfnSPR_Load("sprites/voiceicon.spr"); + m_VoiceHeadModel = gEngfuncs.pfnSPR_Load( "sprites/voiceicon.spr" ); + return TRUE; } - -void CVoiceStatus::Frame(double frametime) +void CVoiceStatus::Frame( double frametime ) { // check server banned players once per second - if(gEngfuncs.GetClientTime() - m_LastUpdateServerState > 1) + if( gEngfuncs.GetClientTime() - m_LastUpdateServerState > 1 ) { - UpdateServerState(false); + UpdateServerState( false ); } m_BlinkTimer += frametime; @@ -330,51 +296,50 @@ void CVoiceStatus::Frame(double frametime) // Update speaker labels. if( m_pHelper->CanShowSpeakerLabels() ) { - for( int i=0; i < MAX_VOICE_SPEAKERS; i++ ) + for( int i = 0; i < MAX_VOICE_SPEAKERS; i++ ) m_Labels[i].m_pBackground->setVisible( m_Labels[i].m_clientindex != -1 ); } else { - for( int i=0; i < MAX_VOICE_SPEAKERS; i++ ) + for( int i = 0; i < MAX_VOICE_SPEAKERS; i++ ) m_Labels[i].m_pBackground->setVisible( false ); } - for(int i=0; i < VOICE_MAX_PLAYERS; i++) + for( int i = 0; i < VOICE_MAX_PLAYERS; i++ ) UpdateBanButton(i); } - void CVoiceStatus::CreateEntities() { - if(!m_VoiceHeadModel) + if( !m_VoiceHeadModel ) return; cl_entity_t *localPlayer = gEngfuncs.GetLocalPlayer(); int iOutModel = 0; - for(int i=0; i < VOICE_MAX_PLAYERS; i++) + for( int i = 0; i < VOICE_MAX_PLAYERS; i++ ) { - if(!m_VoicePlayers[i]) + if( !m_VoicePlayers[i] ) continue; - - cl_entity_s *pClient = gEngfuncs.GetEntityByIndex(i+1); - + + cl_entity_s *pClient = gEngfuncs.GetEntityByIndex( i + 1 ); + // Don't show an icon if the player is not in our PVS. - if(!pClient || pClient->curstate.messagenum < localPlayer->curstate.messagenum) + if( !pClient || pClient->curstate.messagenum < localPlayer->curstate.messagenum ) continue; // Don't show an icon for dead or spectating players (ie: invisible entities). - if(pClient->curstate.effects & EF_NODRAW) + if( pClient->curstate.effects & EF_NODRAW ) continue; // Don't show an icon for the local player unless we're in thirdperson mode. - if(pClient == localPlayer && !cam_thirdperson) + if( pClient == localPlayer && !cam_thirdperson ) continue; cl_entity_s *pEnt = &m_VoiceHeadModels[iOutModel]; ++iOutModel; - memset(pEnt, 0, sizeof(*pEnt)); + memset( pEnt, 0, sizeof(*pEnt) ); pEnt->curstate.rendermode = kRenderTransAdd; pEnt->curstate.renderamt = 255; @@ -382,30 +347,30 @@ void CVoiceStatus::CreateEntities() pEnt->curstate.renderfx = kRenderFxNoDissipation; pEnt->curstate.framerate = 1; pEnt->curstate.frame = 0; - pEnt->model = (struct model_s*)gEngfuncs.GetSpritePointer(m_VoiceHeadModel); + pEnt->model = (struct model_s*)gEngfuncs.GetSpritePointer( m_VoiceHeadModel ); pEnt->angles[0] = pEnt->angles[1] = pEnt->angles[2] = 0; pEnt->curstate.scale = 0.5f; - + pEnt->origin[0] = pEnt->origin[1] = 0; pEnt->origin[2] = 45; - VectorAdd(pEnt->origin, pClient->origin, pEnt->origin); + VectorAdd( pEnt->origin, pClient->origin, pEnt->origin ); // Tell the engine. - gEngfuncs.CL_CreateVisibleEntity(ET_NORMAL, pEnt); + gEngfuncs.CL_CreateVisibleEntity( ET_NORMAL, pEnt ); } } - -void CVoiceStatus::UpdateSpeakerStatus(int entindex, qboolean bTalking) +void CVoiceStatus::UpdateSpeakerStatus( int entindex, qboolean bTalking ) { - if(!*m_pParentPanel) + if( !*m_pParentPanel ) return; if( gEngfuncs.pfnGetCvarFloat("voice_clientdebug") ) { char msg[256]; - _snprintf( msg, sizeof(msg), "CVoiceStatus::UpdateSpeakerStatus: ent %d talking = %d\n", entindex, bTalking ); + + sprintf( msg, "CVoiceStatus::UpdateSpeakerStatus: ent %d talking = %d\n", entindex, bTalking ); gEngfuncs.pfnConsolePrint( msg ); } @@ -423,30 +388,30 @@ void CVoiceStatus::UpdateSpeakerStatus(int entindex, qboolean bTalking) { m_bServerAcked = !!bTalking; } - else if(entindex >= 0 && entindex <= VOICE_MAX_PLAYERS) + else if( entindex >= 0 && entindex <= VOICE_MAX_PLAYERS ) { int iClient = entindex - 1; - if(iClient < 0) + if( iClient < 0 ) return; - CVoiceLabel *pLabel = FindVoiceLabel(iClient); - if(bTalking) + CVoiceLabel *pLabel = FindVoiceLabel( iClient ); + if( bTalking ) { m_VoicePlayers[iClient] = true; m_VoiceEnabledPlayers[iClient] = true; // If we don't have a label for this guy yet, then create one. - if(!pLabel) + if( !pLabel ) { - if(pLabel = GetFreeVoiceLabel()) + if( pLabel = GetFreeVoiceLabel() ) { // Get the name from the engine. - hud_player_info_t info; - memset(&info, 0, sizeof(info)); - GetPlayerInfo(entindex, &info); + hud_player_info_t info = {0}; + + GetPlayerInfo( entindex, &info ); char paddedName[512]; - _snprintf(paddedName, sizeof(paddedName), "%s ", info.name); + sprintf( paddedName, "%s ", info.name ); int color[3]; m_pHelper->GetPlayerTextColor( entindex, color ); @@ -474,9 +439,9 @@ void CVoiceStatus::UpdateSpeakerStatus(int entindex, qboolean bTalking) m_VoicePlayers[iClient] = false; // If we have a label for this guy, kill it. - if(pLabel) + if( pLabel ) { - pLabel->m_pBackground->setVisible(false); + pLabel->m_pBackground->setVisible( false ); pLabel->m_clientindex = -1; } } @@ -485,14 +450,13 @@ void CVoiceStatus::UpdateSpeakerStatus(int entindex, qboolean bTalking) RepositionLabels(); } - -void CVoiceStatus::UpdateServerState(bool bForce) +void CVoiceStatus::UpdateServerState( bool bForce ) { // Can't do anything when we're not in a level. char const *pLevelName = gEngfuncs.pfnGetLevelName(); if( pLevelName[0] == 0 ) { - if( gEngfuncs.pfnGetCvarFloat("voice_clientdebug") ) + if( gEngfuncs.pfnGetCvarFloat( "voice_clientdebug" ) ) { gEngfuncs.pfnConsolePrint( "CVoiceStatus::UpdateServerState: pLevelName[0]==0\n" ); } @@ -500,167 +464,177 @@ void CVoiceStatus::UpdateServerState(bool bForce) return; } - int bCVarModEnable = !!gEngfuncs.pfnGetCvarFloat("voice_modenable"); - if(bForce || m_bServerModEnable != bCVarModEnable) + int bCVarModEnable = !!gEngfuncs.pfnGetCvarFloat( "voice_modenable" ); + if( bForce || m_bServerModEnable != bCVarModEnable ) { m_bServerModEnable = bCVarModEnable; char str[256]; - _snprintf(str, sizeof(str), "VModEnable %d", m_bServerModEnable); - ServerCmd(str); - if(gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + sprintf( str, "VModEnable %d", m_bServerModEnable ); + ServerCmd( str ); + + if( gEngfuncs.pfnGetCvarFloat( "voice_clientdebug" ) ) { char msg[256]; - sprintf(msg, "CVoiceStatus::UpdateServerState: Sending '%s'\n", str); - gEngfuncs.pfnConsolePrint(msg); + + sprintf( msg, "CVoiceStatus::UpdateServerState: Sending '%s'\n", str ); + gEngfuncs.pfnConsolePrint( msg ); } } - char str[2048]; - sprintf(str, "vban"); + char str[2048] = "vban"; + bool bChange = false; - for(unsigned long dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++) + for( unsigned long dw = 0; dw < VOICE_MAX_PLAYERS_DW; dw++ ) { unsigned long serverBanMask = 0; unsigned long banMask = 0; - for(unsigned long i=0; i < 32; i++) + + for( unsigned long i = 0; i < 32; i++ ) { char playerID[16]; - if(!gEngfuncs.GetPlayerUniqueID(i+1, playerID)) + + if( !gEngfuncs.GetPlayerUniqueID( i + 1, playerID ) ) continue; - if(m_BanMgr.GetPlayerBan(playerID)) + if( m_BanMgr.GetPlayerBan( playerID ) ) banMask |= 1 << i; - if(m_ServerBannedPlayers[dw*32 + i]) + if( m_ServerBannedPlayers[dw * 32 + i] ) serverBanMask |= 1 << i; } - if(serverBanMask != banMask) + if( serverBanMask != banMask ) bChange = true; // Ok, the server needs to be updated. char numStr[512]; + sprintf(numStr, " %x", banMask); + strcat(str, numStr); } - if(bChange || bForce) + if( bChange || bForce ) { - if(gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + if( gEngfuncs.pfnGetCvarFloat( "voice_clientdebug" ) ) { char msg[256]; - sprintf(msg, "CVoiceStatus::UpdateServerState: Sending '%s'\n", str); - gEngfuncs.pfnConsolePrint(msg); + + sprintf( msg, "CVoiceStatus::UpdateServerState: Sending '%s'\n", str ); + + gEngfuncs.pfnConsolePrint( msg ); } - gEngfuncs.pfnServerCmdUnreliable(str); // Tell the server.. + gEngfuncs.pfnServerCmdUnreliable( str ); // Tell the server.. } else { - if (gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + if( gEngfuncs.pfnGetCvarFloat( "voice_clientdebug" ) ) { gEngfuncs.pfnConsolePrint( "CVoiceStatus::UpdateServerState: no change\n" ); } } - + m_LastUpdateServerState = gEngfuncs.GetClientTime(); } -void CVoiceStatus::UpdateSpeakerImage(Label *pLabel, int iPlayer) +void CVoiceStatus::UpdateSpeakerImage( Label *pLabel, int iPlayer ) { - m_pBanButtons[iPlayer-1] = pLabel; - UpdateBanButton(iPlayer-1); + m_pBanButtons[iPlayer - 1] = pLabel; + UpdateBanButton(iPlayer - 1); } -void CVoiceStatus::UpdateBanButton(int iClient) +void CVoiceStatus::UpdateBanButton( int iClient ) { Label *pPanel = m_pBanButtons[iClient]; - if (!pPanel) + if( !pPanel ) return; char playerID[16]; extern bool HACK_GetPlayerUniqueID( int iPlayer, char playerID[16] ); - if(!HACK_GetPlayerUniqueID(iClient+1, playerID)) + + if( !HACK_GetPlayerUniqueID( iClient + 1, playerID ) ) return; // Figure out if it's blinking or not. - bool bBlink = fmod(m_BlinkTimer, SCOREBOARD_BLINK_FREQUENCY*2) < SCOREBOARD_BLINK_FREQUENCY; + bool bBlink = fmod( m_BlinkTimer, SCOREBOARD_BLINK_FREQUENCY * 2 ) < SCOREBOARD_BLINK_FREQUENCY; bool bTalking = !!m_VoicePlayers[iClient]; - bool bBanned = m_BanMgr.GetPlayerBan(playerID); + bool bBanned = m_BanMgr.GetPlayerBan( playerID ); bool bNeverSpoken = !m_VoiceEnabledPlayers[iClient]; // Get the appropriate image to display on the panel. - if (bBanned) + if( bBanned ) { - pPanel->setImage(m_pScoreboardBanned); + pPanel->setImage( m_pScoreboardBanned ); } - else if (bTalking) + else if( bTalking ) { - if (bBlink) + if( bBlink ) { - pPanel->setImage(m_pScoreboardSpeaking2); + pPanel->setImage( m_pScoreboardSpeaking2 ); } else { - pPanel->setImage(m_pScoreboardSpeaking); + pPanel->setImage( m_pScoreboardSpeaking ); } - pPanel->setFgColor(255, 170, 0, 1); + + pPanel->setFgColor( 255, 170, 0, 1 ); } - else if (bNeverSpoken) + else if( bNeverSpoken ) { - pPanel->setImage(m_pScoreboardNeverSpoken); - pPanel->setFgColor(100, 100, 100, 1); + pPanel->setImage( m_pScoreboardNeverSpoken ); + pPanel->setFgColor( 100, 100, 100, 1 ); } else { - pPanel->setImage(m_pScoreboardNotSpeaking); + pPanel->setImage( m_pScoreboardNotSpeaking ); } } - -void CVoiceStatus::HandleVoiceMaskMsg(int iSize, void *pbuf) +void CVoiceStatus::HandleVoiceMaskMsg( int iSize, void *pbuf ) { BEGIN_READ( pbuf, iSize ); unsigned long dw; - for(dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++) - { - m_AudiblePlayers.SetDWord(dw, (unsigned long)READ_LONG()); - m_ServerBannedPlayers.SetDWord(dw, (unsigned long)READ_LONG()); - if(gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + for( dw = 0; dw < VOICE_MAX_PLAYERS_DW; dw++ ) + { + m_AudiblePlayers.SetDWord( dw, (unsigned long)READ_LONG() ); + m_ServerBannedPlayers.SetDWord( dw, (unsigned long)READ_LONG() ); + + if( gEngfuncs.pfnGetCvarFloat( "voice_clientdebug" ) ) { char str[256]; - gEngfuncs.pfnConsolePrint("CVoiceStatus::HandleVoiceMaskMsg\n"); - - sprintf(str, " - m_AudiblePlayers[%d] = %lu\n", dw, m_AudiblePlayers.GetDWord(dw)); - gEngfuncs.pfnConsolePrint(str); - - sprintf(str, " - m_ServerBannedPlayers[%d] = %lu\n", dw, m_ServerBannedPlayers.GetDWord(dw)); - gEngfuncs.pfnConsolePrint(str); + gEngfuncs.pfnConsolePrint( "CVoiceStatus::HandleVoiceMaskMsg\n" ); + + sprintf( str, " - m_AudiblePlayers[%d] = %lu\n", dw, m_AudiblePlayers.GetDWord( dw ) ); + gEngfuncs.pfnConsolePrint( str ); + + sprintf( str, " - m_ServerBannedPlayers[%d] = %lu\n", dw, m_ServerBannedPlayers.GetDWord( dw ) ); + gEngfuncs.pfnConsolePrint( str ); } } m_bServerModEnable = READ_BYTE(); } -void CVoiceStatus::HandleReqStateMsg(int iSize, void *pbuf) +void CVoiceStatus::HandleReqStateMsg( int iSize, void *pbuf ) { - if(gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + if( gEngfuncs.pfnGetCvarFloat( "voice_clientdebug" ) ) { - gEngfuncs.pfnConsolePrint("CVoiceStatus::HandleReqStateMsg\n"); + gEngfuncs.pfnConsolePrint( "CVoiceStatus::HandleReqStateMsg\n" ); } - UpdateServerState(true); + UpdateServerState( true ); } void CVoiceStatus::StartSquelchMode() { - if(m_bInSquelchMode) + if( m_bInSquelchMode ) return; m_bInSquelchMode = true; @@ -678,37 +652,35 @@ bool CVoiceStatus::IsInSquelchMode() return m_bInSquelchMode; } -CVoiceLabel* CVoiceStatus::FindVoiceLabel(int clientindex) +CVoiceLabel *CVoiceStatus::FindVoiceLabel( int clientindex ) { - for(int i=0; i < MAX_VOICE_SPEAKERS; i++) + for( int i = 0; i < MAX_VOICE_SPEAKERS; i++ ) { - if(m_Labels[i].m_clientindex == clientindex) + if( m_Labels[i].m_clientindex == clientindex ) return &m_Labels[i]; } return NULL; } - -CVoiceLabel* CVoiceStatus::GetFreeVoiceLabel() +CVoiceLabel *CVoiceStatus::GetFreeVoiceLabel() { - return FindVoiceLabel(-1); + return FindVoiceLabel( -1 ); } - void CVoiceStatus::RepositionLabels() { // find starting position to draw from, along right-hand side of screen int y = ScreenHeight / 2; - + int iconWide = 8, iconTall = 8; if( m_pSpeakerLabelIcon ) { m_pSpeakerLabelIcon->getSize( iconWide, iconTall ); } - + // Reposition active labels. - for(int i = 0; i < MAX_VOICE_SPEAKERS; i++) + for( int i = 0; i < MAX_VOICE_SPEAKERS; i++ ) { CVoiceLabel *pLabel = &m_Labels[i]; @@ -721,24 +693,25 @@ void CVoiceStatus::RepositionLabels() } int textWide, textTall; + pLabel->m_pLabel->getContentSize( textWide, textTall ); // Don't let it stretch too far across their screen. - if( textWide > (ScreenWidth*2)/3 ) - textWide = (ScreenWidth*2)/3; + if( textWide > ( ScreenWidth * 2 ) / 3 ) + textWide = ( ScreenWidth * 2 ) / 3; // Setup the background label to fit everything in. int border = 2; - int bgWide = textWide + iconWide + border*3; - int bgTall = max( textTall, iconTall ) + border*2; + int bgWide = textWide + iconWide + border * 3; + int bgTall = max( textTall, iconTall ) + border * 2; pLabel->m_pBackground->setBounds( ScreenWidth - bgWide - 8, y, bgWide, bgTall ); // Put the text at the left. - pLabel->m_pLabel->setBounds( border, (bgTall - textTall) / 2, textWide, textTall ); + pLabel->m_pLabel->setBounds( border, ( bgTall - textTall ) / 2, textWide, textTall ); // Put the icon at the right. int iconLeft = border + textWide + border; - int iconTop = (bgTall - iconTall) / 2; + int iconTop = ( bgTall - iconTall ) / 2; if( pLabel->m_pIcon ) { pLabel->m_pIcon->setImage( m_pSpeakerLabelIcon ); @@ -748,22 +721,23 @@ void CVoiceStatus::RepositionLabels() y += bgTall + 2; } - if( m_pLocalBitmap && m_pAckBitmap && m_pLocalLabel && (m_bTalking || m_bServerAcked) ) + if( m_pLocalBitmap && m_pAckBitmap && m_pLocalLabel && ( m_bTalking || m_bServerAcked ) ) { - m_pLocalLabel->setParent(*m_pParentPanel); + m_pLocalLabel->setParent( *m_pParentPanel ); m_pLocalLabel->setVisible( true ); - if( m_bServerAcked && !!gEngfuncs.pfnGetCvarFloat("voice_clientdebug") ) + if( m_bServerAcked && !!gEngfuncs.pfnGetCvarFloat( "voice_clientdebug" ) ) m_pLocalLabel->setImage( m_pAckBitmap ); else m_pLocalLabel->setImage( m_pLocalBitmap ); int sizeX, sizeY; - m_pLocalBitmap->getSize(sizeX, sizeY); + + m_pLocalBitmap->getSize( sizeX, sizeY ); int local_xPos = ScreenWidth - sizeX - 10; int local_yPos = m_pHelper->GetAckIconHeight() - sizeY; - + m_pLocalLabel->setPos( local_xPos, local_yPos ); } else @@ -772,7 +746,6 @@ void CVoiceStatus::RepositionLabels() } } - void CVoiceStatus::FreeBitmaps() { // Delete all the images we have loaded. @@ -804,16 +777,16 @@ void CVoiceStatus::FreeBitmaps() m_pScoreboardBanned = NULL; // Clear references to the images in panels. - for(int i=0; i < VOICE_MAX_PLAYERS; i++) + for( int i = 0; i < VOICE_MAX_PLAYERS; i++ ) { - if (m_pBanButtons[i]) + if( m_pBanButtons[i] ) { - m_pBanButtons[i]->setImage(NULL); + m_pBanButtons[i]->setImage( NULL ); } } - if(m_pLocalLabel) - m_pLocalLabel->setImage(NULL); + if( m_pLocalLabel ) + m_pLocalLabel->setImage( NULL ); } //----------------------------------------------------------------------------- @@ -821,13 +794,14 @@ void CVoiceStatus::FreeBitmaps() // Input : playerID - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- -bool CVoiceStatus::IsPlayerBlocked(int iPlayer) +bool CVoiceStatus::IsPlayerBlocked( int iPlayer ) { char playerID[16]; - if (!gEngfuncs.GetPlayerUniqueID(iPlayer, playerID)) + + if( !gEngfuncs.GetPlayerUniqueID( iPlayer, playerID ) ) return false; - return m_BanMgr.GetPlayerBan(playerID); + return m_BanMgr.GetPlayerBan( playerID ); } //----------------------------------------------------------------------------- @@ -835,9 +809,9 @@ bool CVoiceStatus::IsPlayerBlocked(int iPlayer) // Input : playerID - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- -bool CVoiceStatus::IsPlayerAudible(int iPlayer) +bool CVoiceStatus::IsPlayerAudible( int iPlayer ) { - return !!m_AudiblePlayers[iPlayer-1]; + return !!m_AudiblePlayers[iPlayer - 1]; } //----------------------------------------------------------------------------- @@ -845,30 +819,32 @@ bool CVoiceStatus::IsPlayerAudible(int iPlayer) // Input : playerID - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- -void CVoiceStatus::SetPlayerBlockedState(int iPlayer, bool blocked) +void CVoiceStatus::SetPlayerBlockedState( int iPlayer, bool blocked ) { - if (gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + if( gEngfuncs.pfnGetCvarFloat( "voice_clientdebug" ) ) { gEngfuncs.pfnConsolePrint( "CVoiceStatus::SetPlayerBlockedState part 1\n" ); } char playerID[16]; - if (!gEngfuncs.GetPlayerUniqueID(iPlayer, playerID)) + + if( !gEngfuncs.GetPlayerUniqueID( iPlayer, playerID ) ) return; - if (gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + if( gEngfuncs.pfnGetCvarFloat( "voice_clientdebug" ) ) { gEngfuncs.pfnConsolePrint( "CVoiceStatus::SetPlayerBlockedState part 2\n" ); } // Squelch or (try to) unsquelch this player. - if (gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + if( gEngfuncs.pfnGetCvarFloat( "voice_clientdebug" ) ) { char str[256]; - sprintf(str, "CVoiceStatus::SetPlayerBlockedState: setting player %d ban to %d\n", iPlayer, !m_BanMgr.GetPlayerBan(playerID)); - gEngfuncs.pfnConsolePrint(str); + + sprintf( str, "CVoiceStatus::SetPlayerBlockedState: setting player %d ban to %d\n", iPlayer, !m_BanMgr.GetPlayerBan( playerID ) ); + gEngfuncs.pfnConsolePrint( str ); } m_BanMgr.SetPlayerBan( playerID, blocked ); - UpdateServerState(false); + UpdateServerState( false ); } diff --git a/game_shared/voice_status.h b/game_shared/voice_status.h index efc5e5c5..22bd864c 100644 --- a/game_shared/voice_status.h +++ b/game_shared/voice_status.h @@ -1,10 +1,9 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +//========= Copyright (c) 1996-2002, Valve LLC, All rights reserved. ============ // // Purpose: // // $NoKeywords: $ //============================================================================= -#pragma once #if !defined(VOICE_STATUS_H) #define VOICE_STATUS_H @@ -20,17 +19,15 @@ #include "vgui_checkbutton2.h" #include "vgui_defaultinputsignal.h" - class CVoiceStatus; - class CVoiceLabel { public: - vgui::Label *m_pLabel; - vgui::Label *m_pBackground; + vgui::Label *m_pLabel; + vgui::Label *m_pBackground; vgui::ImagePanel *m_pIcon; // Voice icon next to player name. - int m_clientindex; // Client index of the speaker. -1 if this label isn't being used. + int m_clientindex; // Client index of the speaker. -1 if this label isn't being used. }; @@ -38,7 +35,7 @@ public: class IVoiceStatusHelper { public: - virtual ~IVoiceStatusHelper() {} + virtual ~IVoiceStatusHelper() {} // Get RGB color for voice status text about this player. virtual void GetPlayerTextColor(int entindex, int color[3]) = 0; @@ -47,7 +44,7 @@ public: virtual void UpdateCursorState() = 0; // Return the height above the bottom that the voice ack icons should be drawn at. - virtual int GetAckIconHeight() = 0; + virtual int GetAckIconHeight() = 0; // Return true if the voice manager is allowed to show speaker labels // (mods usually return false when the scoreboard is up). @@ -61,164 +58,148 @@ class VoiceImagePanel : public vgui::ImagePanel { virtual void paintBackground() { - if (_image!=null) + if( _image != null ) { vgui::Color col; - getFgColor(col); - _image->setColor(col); - _image->doPaint(this); + getFgColor( col ); + _image->setColor( col ); + _image->doPaint( this ); } } }; - class CVoiceStatus : public CHudBase, public vgui::CDefaultInputSignal { public: - CVoiceStatus(); + CVoiceStatus(); virtual ~CVoiceStatus(); -// CHudBase overrides. -public: + // CHudBase overrides. // Initialize the cl_dll's voice manager. - virtual int Init( - IVoiceStatusHelper *m_pHelper, - vgui::Panel **pParentPanel); - + virtual int Init( IVoiceStatusHelper *m_pHelper, vgui::Panel **pParentPanel ); + // ackPosition is the bottom position of where CVoiceStatus will draw the voice acknowledgement labels. - virtual int VidInit(); - - -public: + virtual int VidInit(); // Call from HUD_Frame each frame. - void Frame(double frametime); + void Frame( double frametime ); // Called when a player starts or stops talking. // entindex is -1 to represent the local client talking (before the data comes back from the server). // When the server acknowledges that the local client is talking, then entindex will be gEngfuncs.GetLocalPlayer(). // entindex is -2 to represent the local client's voice being acked by the server. - void UpdateSpeakerStatus(int entindex, qboolean bTalking); + void UpdateSpeakerStatus( int entindex, qboolean bTalking ); // sets the correct image in the label for the player - void UpdateSpeakerImage(vgui::Label *pLabel, int iPlayer); + void UpdateSpeakerImage( vgui::Label *pLabel, int iPlayer ); // Call from the HUD_CreateEntities function so it can add sprites above player heads. - void CreateEntities(); + void CreateEntities(); // Called when the server registers a change to who this client can hear. - void HandleVoiceMaskMsg(int iSize, void *pbuf); + void HandleVoiceMaskMsg( int iSize, void *pbuf ); // The server sends this message initially to tell the client to send their state. - void HandleReqStateMsg(int iSize, void *pbuf); + void HandleReqStateMsg( int iSize, void *pbuf ); - -// Squelch mode functions. -public: + // Squelch mode functions. // When you enter squelch mode, pass in - void StartSquelchMode(); - void StopSquelchMode(); - bool IsInSquelchMode(); + void StartSquelchMode(); + void StopSquelchMode(); + bool IsInSquelchMode(); // returns true if the target client has been banned // playerIndex is of range 1..maxplayers - bool IsPlayerBlocked(int iPlayerIndex); + bool IsPlayerBlocked( int iPlayerIndex ); // returns false if the player can't hear the other client due to game rules (eg. the other team) - bool IsPlayerAudible(int iPlayerIndex); + bool IsPlayerAudible( int iPlayerIndex ); // blocks the target client from being heard - void SetPlayerBlockedState(int iPlayerIndex, bool blocked); + void SetPlayerBlockedState( int iPlayerIndex, bool blocked ); -public: - - CVoiceLabel* FindVoiceLabel(int clientindex); // Find a CVoiceLabel representing the specified speaker. + CVoiceLabel *FindVoiceLabel( int clientindex ); // Find a CVoiceLabel representing the specified speaker. // Returns NULL if none. // entindex can be -1 if you want a currently-unused voice label. - CVoiceLabel* GetFreeVoiceLabel(); // Get an unused voice label. Returns NULL if none. + CVoiceLabel *GetFreeVoiceLabel(); // Get an unused voice label. Returns NULL if none. void RepositionLabels(); void FreeBitmaps(); - void UpdateServerState(bool bForce); + void UpdateServerState( bool bForce ); // Update the button artwork to reflect the client's current state. - void UpdateBanButton(int iClient); + void UpdateBanButton( int iClient ); + enum + { + MAX_VOICE_SPEAKERS = 7 + }; -public: + float m_LastUpdateServerState; // Last time we called this function. + int m_bServerModEnable; // What we've sent to the server about our "voice_modenable" cvar. - enum {MAX_VOICE_SPEAKERS=7}; - - float m_LastUpdateServerState; // Last time we called this function. - int m_bServerModEnable; // What we've sent to the server about our "voice_modenable" cvar. - - vgui::Panel **m_pParentPanel; - CPlayerBitVec m_VoicePlayers; // Who is currently talking. Indexed by client index. + vgui::Panel **m_pParentPanel; + CPlayerBitVec m_VoicePlayers; // Who is currently talking. Indexed by client index. // This is the gamerules-defined list of players that you can hear. It is based on what teams people are on // and is totally separate from the ban list. Indexed by client index. - CPlayerBitVec m_AudiblePlayers; + CPlayerBitVec m_AudiblePlayers; // Players who have spoken at least once in the game so far - CPlayerBitVec m_VoiceEnabledPlayers; + CPlayerBitVec m_VoiceEnabledPlayers; // This is who the server THINKS we have banned (it can become incorrect when a new player arrives on the server). // It is checked periodically, and the server is told to squelch or unsquelch the appropriate players. - CPlayerBitVec m_ServerBannedPlayers; + CPlayerBitVec m_ServerBannedPlayers; - cl_entity_s m_VoiceHeadModels[VOICE_MAX_PLAYERS]; // These aren't necessarily in the order of players. They are just - // a place for it to put data in during CreateEntities. + cl_entity_s m_VoiceHeadModels[VOICE_MAX_PLAYERS]; // These aren't necessarily in the order of players. They are just + // a place for it to put data in during CreateEntities. - IVoiceStatusHelper *m_pHelper; // Each mod provides an implementation of this. + IVoiceStatusHelper *m_pHelper; // Each mod provides an implementation of this. - // Scoreboard icons. - double m_BlinkTimer; // Blink scoreboard icons.. - vgui::BitmapTGA *m_pScoreboardNeverSpoken; - vgui::BitmapTGA *m_pScoreboardNotSpeaking; - vgui::BitmapTGA *m_pScoreboardSpeaking; - vgui::BitmapTGA *m_pScoreboardSpeaking2; - vgui::BitmapTGA *m_pScoreboardSquelch; - vgui::BitmapTGA *m_pScoreboardBanned; - - vgui::Label *m_pBanButtons[VOICE_MAX_PLAYERS]; // scoreboard buttons. + double m_BlinkTimer; // Blink scoreboard icons.. + vgui::BitmapTGA *m_pScoreboardNeverSpoken; + vgui::BitmapTGA *m_pScoreboardNotSpeaking; + vgui::BitmapTGA *m_pScoreboardSpeaking; + vgui::BitmapTGA *m_pScoreboardSpeaking2; + vgui::BitmapTGA *m_pScoreboardSquelch; + vgui::BitmapTGA *m_pScoreboardBanned; + + vgui::Label *m_pBanButtons[VOICE_MAX_PLAYERS]; // scoreboard buttons. // Squelch mode stuff. - bool m_bInSquelchMode; - - HSPRITE m_VoiceHeadModel; // Voice head model (goes above players who are speaking). - float m_VoiceHeadModelHeight; // Height above their head to place the model. + bool m_bInSquelchMode; - vgui::Image *m_pSpeakerLabelIcon; // Icon next to speaker labels. + HSPRITE m_VoiceHeadModel; // Voice head model (goes above players who are speaking). + float m_VoiceHeadModelHeight; // Height above their head to place the model. + + vgui::Image *m_pSpeakerLabelIcon; // Icon next to speaker labels. // Lower-right icons telling when the local player is talking.. - vgui::BitmapTGA *m_pLocalBitmap; // Represents the local client talking. - vgui::BitmapTGA *m_pAckBitmap; // Represents the server ack'ing the client talking. - vgui::ImagePanel *m_pLocalLabel; // Represents the local client talking. + vgui::BitmapTGA *m_pLocalBitmap; // Represents the local client talking. + vgui::BitmapTGA *m_pAckBitmap; // Represents the server ack'ing the client talking. + vgui::ImagePanel *m_pLocalLabel; // Represents the local client talking. - bool m_bTalking; // Set to true when the client thinks it's talking. - bool m_bServerAcked; // Set to true when the server knows the client is talking. + bool m_bTalking; // Set to true when the client thinks it's talking. + bool m_bServerAcked; // Set to true when the server knows the client is talking. -public: - - CVoiceBanMgr m_BanMgr; // Tracks which users we have squelched and don't want to hear. + CVoiceBanMgr m_BanMgr; // Tracks which users we have squelched and don't want to hear. -public: - - bool m_bBanMgrInitialized; + bool m_bBanMgrInitialized; // Labels telling who is speaking. - CVoiceLabel m_Labels[MAX_VOICE_SPEAKERS]; + CVoiceLabel m_Labels[MAX_VOICE_SPEAKERS]; // Cache the game directory for use when we shut down - char * m_pchGameDir; + char *m_pchGameDir; }; - -// Get the (global) voice manager. +// Get the (global) voice manager. CVoiceStatus* GetClientVoiceMgr(); #endif // VOICE_STATUS_H + diff --git a/game_shared/voice_vgui_tweakdlg.cpp b/game_shared/voice_vgui_tweakdlg.cpp index 07f02ad7..ea61f509 100644 --- a/game_shared/voice_vgui_tweakdlg.cpp +++ b/game_shared/voice_vgui_tweakdlg.cpp @@ -9,7 +9,6 @@ #include "../cl_dll/cl_util.h" #include "../cl_dll/vgui_teamfortressviewport.h" - #include "vgui_actionsignal.h" #include "voice_vgui_tweakdlg.h" #include "voice_vgui_tweakdlg.h" @@ -21,20 +20,18 @@ #include "vgui_checkbutton2.h" #include "vgui_helpers.h" - -#define ITEM_BORDER 40 // Border between text and scrollbars on left and right. +#define ITEM_BORDER 40 // Border between text and scrollbars on left and right. #define VOICETWEAK_TRANSPARENCY 150 - class TweakScroller { public: - TweakScroller(); - void Init(Panel *pParent, char *pText, int yPos); + TweakScroller(); + void Init( Panel *pParent, char *pText, int yPos ); // Get/set value. Values are 0-1. float GetValue(); - void SetValue(float val); + void SetValue( float val ); public: Label m_Label; @@ -46,48 +43,36 @@ public: class CVoiceVGUITweakDlg : public CMenuPanel, public ICheckButton2Handler { typedef CMenuPanel BaseClass; - public: - CVoiceVGUITweakDlg(); - ~CVoiceVGUITweakDlg(); + CVoiceVGUITweakDlg(); + ~CVoiceVGUITweakDlg(); -// CMenuPanel overrides. -public: + // CMenuPanel overrides. virtual void Open(); virtual void Close(); - -// ICheckButton2Handler overrides. -public: - + // ICheckButton2Handler overrides. virtual void StateChanged(CCheckButton2 *pButton); - - -// Panel overrides. -public: + // Panel overrides. virtual void paintBackground(); - private: + int m_DlgWidth; + int m_DlgHeight; - int m_DlgWidth; - int m_DlgHeight; + Label m_Label; - Label m_Label; - - IVoiceTweak *m_pVoiceTweak; // Engine voice tweak API. + IVoiceTweak *m_pVoiceTweak; // Engine voice tweak API. - TweakScroller m_MicVolume; - TweakScroller m_SpeakerVolume; + TweakScroller m_MicVolume; + TweakScroller m_SpeakerVolume; - CCheckButton2 m_VoiceModEnable; - - Button m_Button_OK; + CCheckButton2 m_VoiceModEnable; + + Button m_Button_OK; }; - - bool g_bTweakDlgOpen = false; bool IsTweakDlgOpen() @@ -95,107 +80,97 @@ bool IsTweakDlgOpen() return g_bTweakDlgOpen; } - - // ------------------------------------------------------------------------ // // Global functions. // ------------------------------------------------------------------------ // - static CVoiceVGUITweakDlg g_VoiceTweakDlg; -CMenuPanel* GetVoiceTweakDlg() + +CMenuPanel *GetVoiceTweakDlg() { return &g_VoiceTweakDlg; } - class CVoiceTweakOKButton : public ActionSignal { public: - virtual void actionPerformed(Panel *pPanel) + virtual void actionPerformed( Panel *pPanel ) { gViewPort->HideVGUIMenu(); } }; + CVoiceTweakOKButton g_OKButtonSignal; - - // ------------------------------------------------------------------------ // // TweakScroller // ------------------------------------------------------------------------ // - TweakScroller::TweakScroller() : - m_Label(""), - m_Scroll(0,0,0,0,false), - m_Slider(0,0,10,10,false) + m_Label( "" ), + m_Scroll( 0, 0, 0, 0, false ), + m_Slider( 0, 0, 10, 10, false ) { } - -void TweakScroller::Init(Panel *pParent, char *pText, int yPos) +void TweakScroller::Init( Panel *pParent, char *pText, int yPos ) { int parentWidth, parentHeight; - pParent->getSize(parentWidth, parentHeight); + + pParent->getSize( parentWidth, parentHeight ); // Setup the volume scroll bar. - m_Label.setParent(pParent); - m_Label.setFont(Scheme::sf_primary1); - m_Label.setContentAlignment(vgui::Label::a_northwest); - m_Label.setBgColor(0, 0, 0, 255); - m_Label.setFgColor(255,255,255,0); - m_Label.setPos(ITEM_BORDER, yPos); - m_Label.setSize(parentWidth/2-ITEM_BORDER, 20); - m_Label.setText(pText); - m_Label.setVisible(true); + m_Label.setParent( pParent ); + m_Label.setFont( Scheme::sf_primary1 ); + m_Label.setContentAlignment( vgui::Label::a_northwest ); + m_Label.setBgColor( 0, 0, 0, 255 ); + m_Label.setFgColor( 255, 255, 255, 0 ); + m_Label.setPos( ITEM_BORDER, yPos ); + m_Label.setSize( parentWidth / 2 - ITEM_BORDER, 20 ); + m_Label.setText( pText ); + m_Label.setVisible( true ); - m_Slider.setRangeWindow(10); - m_Slider.setRangeWindowEnabled(true); - - m_Scroll.setPos(parentWidth/2+ITEM_BORDER, yPos); - m_Scroll.setSize(parentWidth/2-ITEM_BORDER*2, 20); - m_Scroll.setSlider(&m_Slider); - m_Scroll.setParent(pParent); - m_Scroll.setRange(0, 100); - m_Scroll.setFgColor(255,255,255,0); - m_Scroll.setBgColor(255,255,255,0); + m_Slider.setRangeWindow( 10 ); + m_Slider.setRangeWindowEnabled( true ); + + m_Scroll.setPos( parentWidth / 2 + ITEM_BORDER, yPos ); + m_Scroll.setSize( parentWidth / 2 - ITEM_BORDER * 2, 20 ); + m_Scroll.setSlider( &m_Slider ); + m_Scroll.setParent( pParent ); + m_Scroll.setRange( 0, 100 ); + m_Scroll.setFgColor( 255, 255, 255, 0 ); + m_Scroll.setBgColor( 255, 255, 255, 0 ); } - float TweakScroller::GetValue() { return m_Scroll.getValue() / 100.0f; } - -void TweakScroller::SetValue(float val) +void TweakScroller::SetValue( float val ) { - m_Scroll.setValue((int)(val * 100.0f)); + m_Scroll.setValue( (int)( val * 100.0f ) ); } - // ------------------------------------------------------------------------ // // CVoiceVGUITweakDlg implementation. // ------------------------------------------------------------------------ // CVoiceVGUITweakDlg::CVoiceVGUITweakDlg() - : CMenuPanel(VOICETWEAK_TRANSPARENCY, false, 0, 0, 0, 0), - m_Button_OK("",0,0), - m_Label("") + : CMenuPanel( VOICETWEAK_TRANSPARENCY, false, 0, 0, 0, 0 ), + m_Button_OK( "", 0, 0 ), + m_Label( "" ) { m_pVoiceTweak = NULL; - m_Button_OK.addActionSignal(&g_OKButtonSignal); - m_Label.setBgColor(255,255,255,200); + m_Button_OK.addActionSignal( &g_OKButtonSignal ); + m_Label.setBgColor( 255, 255, 255, 200 ); } - CVoiceVGUITweakDlg::~CVoiceVGUITweakDlg() { } - void CVoiceVGUITweakDlg::Open() { - if(g_bTweakDlgOpen) + if( g_bTweakDlgOpen ) return; g_bTweakDlgOpen = true; @@ -209,46 +184,48 @@ void CVoiceVGUITweakDlg::Open() m_pVoiceTweak->StartVoiceTweakMode(); // Set our size. - setPos((ScreenWidth - m_DlgWidth) / 2, (ScreenHeight - m_DlgHeight) / 2); - setSize(m_DlgWidth, m_DlgHeight); + setPos( ( ScreenWidth - m_DlgWidth ) / 2, ( ScreenHeight - m_DlgHeight ) / 2 ); + setSize( m_DlgWidth, m_DlgHeight ); int curY = ITEM_BORDER; - m_MicVolume.Init(this, gHUD.m_TextMessage.BufferedLocaliseTextString("#Mic_Volume"), curY); - m_MicVolume.SetValue(m_pVoiceTweak->GetControlFloat(MicrophoneVolume)); - curY = PanelBottom(&m_MicVolume.m_Label); + m_MicVolume.Init( this, gHUD.m_TextMessage.BufferedLocaliseTextString( "#Mic_Volume" ), curY ); + m_MicVolume.SetValue( m_pVoiceTweak->GetControlFloat( MicrophoneVolume ) ); + curY = PanelBottom( &m_MicVolume.m_Label ); - m_SpeakerVolume.Init(this, gHUD.m_TextMessage.BufferedLocaliseTextString("#Speaker_Volume"), curY); - m_SpeakerVolume.SetValue(m_pVoiceTweak->GetControlFloat(OtherSpeakerScale)); - curY = PanelBottom(&m_SpeakerVolume.m_Label); + m_SpeakerVolume.Init( this, gHUD.m_TextMessage.BufferedLocaliseTextString( "#Speaker_Volume" ), curY ); + m_SpeakerVolume.SetValue( m_pVoiceTweak->GetControlFloat( OtherSpeakerScale ) ); + curY = PanelBottom( &m_SpeakerVolume.m_Label ); - m_VoiceModEnable.setParent(this); - m_VoiceModEnable.SetImages("gfx/vgui/checked.tga", "gfx/vgui/unchecked.tga"); - m_VoiceModEnable.SetText("Enable Voice In This Mod"); - m_VoiceModEnable.setPos(ITEM_BORDER, curY); - m_VoiceModEnable.SetCheckboxLeft(false); - m_VoiceModEnable.SetChecked(!!gEngfuncs.pfnGetCvarFloat("voice_modenable")); - m_VoiceModEnable.SetHandler(this); + m_VoiceModEnable.setParent( this ); + m_VoiceModEnable.SetImages( "gfx/vgui/checked.tga", "gfx/vgui/unchecked.tga" ); + m_VoiceModEnable.SetText( "Enable Voice In This Mod" ); + m_VoiceModEnable.setPos( ITEM_BORDER, curY ); + m_VoiceModEnable.SetCheckboxLeft( false ); + m_VoiceModEnable.SetChecked( !!gEngfuncs.pfnGetCvarFloat( "voice_modenable" ) ); + m_VoiceModEnable.SetHandler( this ); // Setup the OK button. int buttonWidth, buttonHeight; - m_Button_OK.setText(gHUD.m_TextMessage.BufferedLocaliseTextString("#Menu_OK")); - m_Button_OK.getSize(buttonWidth, buttonHeight); - m_Button_OK.setPos((m_DlgWidth - buttonWidth) / 2, m_DlgHeight - buttonHeight - 3); - m_Button_OK.setParent(this); + + m_Button_OK.setText( gHUD.m_TextMessage.BufferedLocaliseTextString( "#Menu_OK" ) ); + m_Button_OK.getSize( buttonWidth, buttonHeight ); + m_Button_OK.setPos(( m_DlgWidth - buttonWidth ) / 2, m_DlgHeight - buttonHeight - 3 ); + m_Button_OK.setParent( this ); // Put the label on the top. - m_Label.setBgColor(0, 0, 0, 255); - m_Label.setFgColor(255,255,255,0); - m_Label.setText(gHUD.m_TextMessage.BufferedLocaliseTextString("#Voice_Properties")); + m_Label.setBgColor( 0, 0, 0, 255 ); + m_Label.setFgColor( 255, 255, 255, 0 ); + m_Label.setText( gHUD.m_TextMessage.BufferedLocaliseTextString( "#Voice_Properties" ) ); + int labelWidth, labelHeight; - m_Label.getSize(labelWidth, labelHeight); - m_Label.setPos((m_DlgWidth - labelWidth) / 2, 5); - m_Label.setParent(this); + + m_Label.getSize( labelWidth, labelHeight ); + m_Label.setPos( ( m_DlgWidth - labelWidth ) / 2, 5 ); + m_Label.setParent( this ); BaseClass::Open(); } - void CVoiceVGUITweakDlg::Close() { m_pVoiceTweak->EndVoiceTweakMode(); @@ -257,33 +234,33 @@ void CVoiceVGUITweakDlg::Close() BaseClass::Close(); } - void CVoiceVGUITweakDlg::paintBackground() { BaseClass::paintBackground(); // Draw our border. - int w,h; - getSize(w,h); + int w, h; - drawSetColor(128,128,128,1); - drawOutlinedRect(0, 0, w, h); + getSize( w, h ); + + drawSetColor( 128, 128, 128, 1 ); + drawOutlinedRect( 0, 0, w, h ); float volume = m_MicVolume.GetValue(); - m_pVoiceTweak->SetControlFloat(MicrophoneVolume, volume); + m_pVoiceTweak->SetControlFloat( MicrophoneVolume, volume ); - m_pVoiceTweak->SetControlFloat(OtherSpeakerScale, m_SpeakerVolume.GetValue()); + m_pVoiceTweak->SetControlFloat( OtherSpeakerScale, m_SpeakerVolume.GetValue() ); } -void CVoiceVGUITweakDlg::StateChanged(CCheckButton2 *pButton) +void CVoiceVGUITweakDlg::StateChanged( CCheckButton2 *pButton ) { - if(pButton == &m_VoiceModEnable) + if( pButton == &m_VoiceModEnable ) { - if(pButton->IsChecked()) - gEngfuncs.pfnClientCmd("voice_modenable 1"); + if( pButton->IsChecked() ) + gEngfuncs.pfnClientCmd( "voice_modenable 1" ); else - gEngfuncs.pfnClientCmd("voice_modenable 0"); + gEngfuncs.pfnClientCmd( "voice_modenable 0" ); } } diff --git a/game_shared/voice_vgui_tweakdlg.h b/game_shared/voice_vgui_tweakdlg.h index 960a8d85..21af03ae 100644 --- a/game_shared/voice_vgui_tweakdlg.h +++ b/game_shared/voice_vgui_tweakdlg.h @@ -5,17 +5,16 @@ // $NoKeywords: $ //============================================================================= #pragma once -#if !defined(VOICE_VGUI_TWEAKDLG_H) +#ifndef VOICE_VGUI_TWEAKDLG_H #define VOICE_VGUI_TWEAKDLG_H class CMenuPanel; - // Returns true if the tweak dialog is currently up. bool IsTweakDlgOpen(); // Returns a global instance of the tweak dialog. -CMenuPanel* GetVoiceTweakDlg(); - +CMenuPanel *GetVoiceTweakDlg(); #endif // VOICE_VGUI_TWEAKDLG_H + diff --git a/vgui-dev b/vgui-dev new file mode 160000 index 00000000..93573075 --- /dev/null +++ b/vgui-dev @@ -0,0 +1 @@ +Subproject commit 93573075afe885618ea15831e72d44bdacd65bfb