diff --git a/game/client/NextBot/C_NextBot.cpp b/game/client/NextBot/C_NextBot.cpp new file mode 100644 index 00000000..13d55012 --- /dev/null +++ b/game/client/NextBot/C_NextBot.cpp @@ -0,0 +1,245 @@ +// C_NextBot.cpp +// Client-side implementation of Next generation bot system +// Author: Michael Booth, April 2005 +//========= Copyright Valve Corporation, All rights reserved. ============// + +#include "cbase.h" +#include "C_NextBot.h" +#include "debugoverlay_shared.h" +#include +#include "viewrender.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#undef NextBot + +ConVar NextBotShadowDist( "nb_shadow_dist", "400" ); + +//----------------------------------------------------------------------------- +IMPLEMENT_CLIENTCLASS_DT( C_NextBotCombatCharacter, DT_NextBot, NextBotCombatCharacter ) +END_RECV_TABLE() + + +//----------------------------------------------------------------------------- +C_NextBotCombatCharacter::C_NextBotCombatCharacter() +{ + // Left4Dead have surfaces too steep for IK to work properly + m_EntClientFlags |= ENTCLIENTFLAG_DONTUSEIK; + + m_shadowType = SHADOWS_SIMPLE; + m_forcedShadowType = SHADOWS_NONE; + m_bForceShadowType = false; + + TheClientNextBots().Register( this ); +} + + +//----------------------------------------------------------------------------- +C_NextBotCombatCharacter::~C_NextBotCombatCharacter() +{ + TheClientNextBots().UnRegister( this ); +} + + +//----------------------------------------------------------------------------- +void C_NextBotCombatCharacter::Spawn( void ) +{ + BaseClass::Spawn(); +} + + +//----------------------------------------------------------------------------- +void C_NextBotCombatCharacter::UpdateClientSideAnimation() +{ + if (IsDormant()) + { + return; + } + + BaseClass::UpdateClientSideAnimation(); +} + + +//-------------------------------------------------------------------------------------------------------- +void C_NextBotCombatCharacter::UpdateShadowLOD( void ) +{ + ShadowType_t oldShadowType = m_shadowType; + + if ( m_bForceShadowType ) + { + m_shadowType = m_forcedShadowType; + } + else + { +#ifdef NEED_SPLITSCREEN_INTEGRATION + FOR_EACH_VALID_SPLITSCREEN_PLAYER( hh ) + { + C_BasePlayer *pl = C_BasePlayer::GetLocalPlayer(hh); + if ( pl ) + { + Vector delta = GetAbsOrigin() - C_BasePlayer::GetLocalPlayer(hh)->GetAbsOrigin(); +#else + { + if ( C_BasePlayer::GetLocalPlayer() ) + { + Vector delta = GetAbsOrigin() - C_BasePlayer::GetLocalPlayer()->GetAbsOrigin(); +#endif + if ( delta.IsLengthLessThan( NextBotShadowDist.GetFloat() ) ) + { + m_shadowType = SHADOWS_RENDER_TO_TEXTURE_DYNAMIC; + } + else + { + m_shadowType = SHADOWS_SIMPLE; + } + } + else + { + m_shadowType = SHADOWS_SIMPLE; + } + } + } + + if ( oldShadowType != m_shadowType ) + { + DestroyShadow(); + } +} + + +//-------------------------------------------------------------------------------------------------------- +ShadowType_t C_NextBotCombatCharacter::ShadowCastType( void ) +{ + if ( !IsVisible() ) + return SHADOWS_NONE; + + if ( m_shadowTimer.IsElapsed() ) + { + m_shadowTimer.Start( 0.15f ); + UpdateShadowLOD(); + } + + return m_shadowType; +} + + +//-------------------------------------------------------------------------------------------------------- +bool C_NextBotCombatCharacter::GetForcedShadowCastType( ShadowType_t* pForcedShadowType ) const +{ + if ( pForcedShadowType ) + { + *pForcedShadowType = m_forcedShadowType; + } + return m_bForceShadowType; +} + +//-------------------------------------------------------------------------------------------------------- +/** + * Singleton accessor. + * By returning a reference, we guarantee construction of the + * instance before its first use. + */ +C_NextBotManager &TheClientNextBots( void ) +{ + static C_NextBotManager manager; + return manager; +} + + +//-------------------------------------------------------------------------------------------------------- +C_NextBotManager::C_NextBotManager( void ) +{ +} + + +//-------------------------------------------------------------------------------------------------------- +C_NextBotManager::~C_NextBotManager() +{ +} + + +//-------------------------------------------------------------------------------------------------------- +void C_NextBotManager::Register( C_NextBotCombatCharacter *bot ) +{ + m_botList.AddToTail( bot ); +} + + +//-------------------------------------------------------------------------------------------------------- +void C_NextBotManager::UnRegister( C_NextBotCombatCharacter *bot ) +{ + m_botList.FindAndRemove( bot ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool C_NextBotManager::SetupInFrustumData( void ) +{ +#ifdef ENABLE_AFTER_INTEGRATION + // Done already this frame. + if ( IsInFrustumDataValid() ) + return true; + + // Can we use the view data yet? + if ( !FrustumCache()->IsValid() ) + return false; + + // Get the number of active bots. + int nBotCount = m_botList.Count(); + + // Reset. + for ( int iBot = 0; iBot < nBotCount; ++iBot ) + { + // Get the current bot. + C_NextBotCombatCharacter *pBot = m_botList[iBot]; + if ( !pBot ) + continue; + + pBot->InitFrustumData(); + } + + FOR_EACH_VALID_SPLITSCREEN_PLAYER( iSlot ) + { + ACTIVE_SPLITSCREEN_PLAYER_GUARD( iSlot ); + // Get the active local player. + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + if ( !pPlayer ) + continue; + + for ( int iBot = 0; iBot < nBotCount; ++iBot ) + { + // Get the current bot. + C_NextBotCombatCharacter *pBot = m_botList[iBot]; + if ( !pBot ) + continue; + + // Are we in the view frustum? + Vector vecMin, vecMax; + pBot->CollisionProp()->WorldSpaceAABB( &vecMin, &vecMax ); + bool bInFrustum = !FrustumCache()->m_Frustums[iSlot].CullBox( vecMin, vecMax ); + + if ( bInFrustum ) + { + Vector vecSegment; + VectorSubtract( pBot->GetAbsOrigin(), pPlayer->GetAbsOrigin(), vecSegment ); + float flDistance = vecSegment.LengthSqr(); + if ( flDistance < pBot->GetInFrustumDistanceSqr() ) + { + pBot->SetInFrustumDistanceSqr( flDistance ); + } + + pBot->SetInFrustum( true ); + } + } + } + + // Mark as setup this frame. + m_nInFrustumFrame = gpGlobals->framecount; +#endif + + return true; +} + +//-------------------------------------------------------------------------------------------------------- diff --git a/game/client/NextBot/C_NextBot.h b/game/client/NextBot/C_NextBot.h new file mode 100644 index 00000000..c26d7b9b --- /dev/null +++ b/game/client/NextBot/C_NextBot.h @@ -0,0 +1,134 @@ +// C_NextBot.h +// Next generation bot system +// Author: Michael Booth, April 2005 +//========= Copyright Valve Corporation, All rights reserved. ============// + +#ifndef _C_NEXT_BOT_H_ +#define _C_NEXT_BOT_H_ + +#include "c_ai_basenpc.h" + +//---------------------------------------------------------------------------------------------------------------- +/** +* The interface holding IBody information +*/ +class IBodyClient +{ +public: + enum ActivityType + { + MOTION_CONTROLLED_XY = 0x0001, // XY position and orientation of the bot is driven by the animation. + MOTION_CONTROLLED_Z = 0x0002, // Z position of the bot is driven by the animation. + ACTIVITY_UNINTERRUPTIBLE= 0x0004, // activity can't be changed until animation finishes + ACTIVITY_TRANSITORY = 0x0008, // a short animation that takes over from the underlying animation momentarily, resuming it upon completion + ENTINDEX_PLAYBACK_RATE = 0x0010, // played back at different rates based on entindex + }; +}; + + +//-------------------------------------------------------------------------------------------------------- +/** + * The client-side implementation of the NextBot + */ +class C_NextBotCombatCharacter : public C_BaseCombatCharacter +{ +public: + DECLARE_CLASS( C_NextBotCombatCharacter, C_BaseCombatCharacter ); + DECLARE_CLIENTCLASS(); + + C_NextBotCombatCharacter(); + virtual ~C_NextBotCombatCharacter(); + +public: + virtual void Spawn( void ); + virtual void UpdateClientSideAnimation( void ); + virtual ShadowType_t ShadowCastType( void ); + virtual bool IsNextBot() { return true; } + void ForceShadowCastType( bool bForce, ShadowType_t forcedShadowType = SHADOWS_NONE ) { m_bForceShadowType = bForce; m_forcedShadowType = forcedShadowType; } + bool GetForcedShadowCastType( ShadowType_t* pForcedShadowType ) const; + + // Local In View Data. + void InitFrustumData( void ) { m_bInFrustum = false; m_flFrustumDistanceSqr = FLT_MAX; m_nInFrustumFrame = gpGlobals->framecount; } + bool IsInFrustumValid( void ) { return ( m_nInFrustumFrame == gpGlobals->framecount ); } + void SetInFrustum( bool bInFrustum ) { m_bInFrustum = bInFrustum; } + bool IsInFrustum( void ) { return m_bInFrustum; } + void SetInFrustumDistanceSqr( float flDistance ) { m_flFrustumDistanceSqr = flDistance; } + float GetInFrustumDistanceSqr( void ) { return m_flFrustumDistanceSqr; } + +private: + ShadowType_t m_shadowType; // Are we LOD'd to simple shadows? + CountdownTimer m_shadowTimer; // Timer to throttle checks for shadow LOD + ShadowType_t m_forcedShadowType; + bool m_bForceShadowType; + void UpdateShadowLOD( void ); + + // Local In View Data. + int m_nInFrustumFrame; + bool m_bInFrustum; + float m_flFrustumDistanceSqr; + +private: + C_NextBotCombatCharacter( const C_NextBotCombatCharacter & ); // not defined, not accessible +}; + +//-------------------------------------------------------------------------------------------------------- +/** + * The C_NextBotManager manager + */ +class C_NextBotManager +{ +public: + C_NextBotManager( void ); + ~C_NextBotManager(); + + /** + * Execute functor for each NextBot in the system. + * If a functor returns false, stop iteration early + * and return false. + */ + template < typename Functor > + bool ForEachCombatCharacter( Functor &func ) + { + for( int i=0; i < m_botList.Count(); ++i ) + { + C_NextBotCombatCharacter *character = m_botList[i]; + if ( character->IsPlayer() ) + { + continue; + } + + if ( character->IsDormant() ) + { + continue; + } + + if ( !func( character ) ) + { + return false; + } + } + + return true; + } + + int GetActiveCount() { return m_botList.Count(); } + + bool SetupInFrustumData( void ); + bool IsInFrustumDataValid( void ) { return ( m_nInFrustumFrame == gpGlobals->framecount ); } + +private: + friend class C_NextBotCombatCharacter; + + void Register( C_NextBotCombatCharacter *bot ); + void UnRegister( C_NextBotCombatCharacter *bot ); + + CUtlVector< C_NextBotCombatCharacter * > m_botList; ///< list of all active NextBots + + int m_nInFrustumFrame; +}; + +// singleton accessor +extern C_NextBotManager &TheClientNextBots( void ); + + +#endif // _C_NEXT_BOT_H_ diff --git a/game/client/client_cstrike.vpc b/game/client/client_cstrike.vpc new file mode 100644 index 00000000..19429718 --- /dev/null +++ b/game/client/client_cstrike.vpc @@ -0,0 +1,275 @@ +//----------------------------------------------------------------------------- +// CLIENT_CSTRIKE.VPC +// +// Project Script +//----------------------------------------------------------------------------- + +$Macro SRCDIR "..\.." +$Macro GAMENAME "cstrike" + +$Include "$SRCDIR\game\client\client_base.vpc" + +$Configuration +{ + $Compiler + { + $AdditionalIncludeDirectories "$BASE;$SRCDIR\game\shared\cstrike\control,.\cstrike,.\cstrike\control,.\cstrike\VGUI,$SRCDIR\game\shared\cstrike" + $PreprocessorDefinitions "$BASE;CSTRIKE_DLL;NEXT_BOT" + } +} + +$Project "Client (CStrike)" +{ + $Folder "Replay" + { + $File "cstrike\cs_replay.cpp" + $File "cstrike\cs_replay.h" + } + + $Folder "Source Files" + { + -$File "$SRCDIR\game\shared\weapon_parse_default.cpp" + + $File "c_team_objectiveresource.cpp" + $File "c_team_objectiveresource.h" + $File "c_team_train_watcher.cpp" + $File "c_team_train_watcher.h" + $File "hud_base_account.cpp" + $File "hud_base_account.h" + $File "hud_voicestatus.cpp" + $File "hud_baseachievement_tracker.cpp" + $File "hud_baseachievement_tracker.h" + $File "$SRCDIR\game\client\hud_vote.h" + $File "$SRCDIR\game\client\hud_vote.cpp" + $File "$SRCDIR\game\shared\predicted_viewmodel.cpp" + $File "$SRCDIR\game\shared\predicted_viewmodel.h" + + $Folder "CounterStrike DLL" + { + $File "$SRCDIR\game\shared\cstrike\cs_achievement_constants.h" + $File "$SRCDIR\game\shared\cstrike\cs_achievementdefs.h" + $File "$SRCDIR\game\shared\cs_achievements_and_stats_interface.cpp" + $File "$SRCDIR\game\shared\cs_achievements_and_stats_interface.h" + $File "$SRCDIR\game\shared\cstrike\achievements_cs.cpp" + $File "$SRCDIR\game\shared\cstrike\achievements_cs.h" + $File "$SRCDIR\game\shared\cstrike\basecsgrenade_projectile.cpp" + $File "$SRCDIR\game\shared\cstrike\basecsgrenade_projectile.h" + $File "cstrike\buy_presets\buy_preset.cpp" + $File "cstrike\buy_presets\buy_preset_debug.cpp" + $File "cstrike\buy_presets\buy_preset_debug.h" + $File "cstrike\buy_presets\buy_preset_weapon_info.cpp" + $File "cstrike\buy_presets\buy_presets.cpp" + $File "cstrike\buy_presets\buy_presets.h" + $File "cstrike\c_cs_hostage.cpp" + $File "cstrike\c_cs_hostage.h" + $File "cstrike\c_cs_player.cpp" + $File "cstrike\c_cs_player.h" + $File "cstrike\c_cs_playerresource.cpp" + $File "cstrike\c_cs_playerresource.h" + $File "cstrike\c_cs_team.cpp" + $File "cstrike\c_cs_team.h" + $File "cstrike\c_csrootpanel.cpp" + $File "cstrike\c_csrootpanel.h" + $File "cstrike\c_plantedc4.cpp" + $File "cstrike\c_plantedc4.h" + $File "cstrike\c_te_radioicon.cpp" + $File "cstrike\c_te_shotgun_shot.cpp" + $File "cstrike\clientmode_csnormal.cpp" + $File "cstrike\clientmode_csnormal.h" + $File "$SRCDIR\game\shared\cstrike\cs_ammodef.cpp" + $File "$SRCDIR\game\shared\cstrike\cs_ammodef.h" + $File "$SRCDIR\game\shared\cstrike\cs_gamemovement.cpp" + $File "$SRCDIR\game\shared\cstrike\cs_gamerules.cpp" + $File "$SRCDIR\game\shared\cstrike\cs_gamerules.h" + $File "$SRCDIR\game\shared\cstrike\cs_gamestats_shared.cpp" + $File "$SRCDIR\game\shared\cstrike\cs_gamestats_shared.h" + $File "$SRCDIR\game\shared\steamworks_gamestats.cpp" + $File "$SRCDIR\game\shared\steamworks_gamestats.h" + $File "cstrike\cs_in_main.cpp" + $File "$SRCDIR\game\shared\cstrike\cs_player_shared.cpp" + $File "$SRCDIR\game\shared\cstrike\cs_playeranimstate.cpp" + $File "$SRCDIR\game\shared\cstrike\cs_playeranimstate.h" + $File "cstrike\cs_prediction.cpp" + $File "$SRCDIR\game\shared\cstrike\cs_shareddefs.cpp" + $File "cstrike\cs_client_gamestats.cpp" + $File "cstrike\cs_client_gamestats.h" + $File "$SRCDIR\game\shared\cstrike\cs_usermessages.cpp" + $File "cstrike\cs_view_scene.cpp" + $File "cstrike\cs_view_scene.h" + $File "$SRCDIR\game\shared\cstrike\cs_weapon_parse.cpp" + $File "$SRCDIR\game\shared\cstrike\cs_weapon_parse.h" + $File "cstrike\fx_cs_blood.cpp" + $File "cstrike\fx_cs_blood.h" + $File "cstrike\fx_cs_impacts.cpp" + $File "cstrike\fx_cs_knifeslash.cpp" + $File "cstrike\fx_cs_muzzleflash.cpp" + $File "$SRCDIR\game\shared\cstrike\fx_cs_shared.cpp" + $File "$SRCDIR\game\shared\cstrike\fx_cs_shared.h" + $File "cstrike\fx_cs_weaponfx.cpp" + $File "$SRCDIR\game\shared\cstrike\bot\shared_util.cpp" + $File "$SRCDIR\game\shared\cstrike\bot\shared_util.h" + $File "cstrike\vgui_rootpanel_cs.cpp" + + $Folder "HUD Elements" + { + $File "cstrike\cs_hud_ammo.cpp" + $File "cstrike\cs_hud_chat.cpp" + $File "cstrike\cs_hud_chat.h" + $File "cstrike\cs_hud_damageindicator.cpp" + $File "cstrike\cs_hud_freezepanel.cpp" + $File "cstrike\cs_hud_freezepanel.h" + $File "cstrike\cs_hud_playerhealth.cpp" + $File "cstrike\cs_hud_playerhealth.h" + $File "cstrike\cs_hud_health.cpp" + $File "cstrike\cs_hud_scope.cpp" + $File "cstrike\cs_hud_target_id.cpp" + $File "cstrike\cs_hud_weaponselection.cpp" + $File "cstrike\hud_account.cpp" + $File "cstrike\hud_armor.cpp" + $File "cstrike\hud_c4.cpp" + $File "cstrike\hud_deathnotice.cpp" + $File "cstrike\hud_defuser.cpp" + $File "cstrike\hud_flashbang.cpp" + $File "cstrike\hud_hostagerescue.cpp" + $File "cstrike\hud_progressbar.cpp" + $File "cstrike\hud_radar.cpp" + $File "cstrike\hud_radar.h" + $File "cstrike\hud_roundtimer.cpp" + $File "cstrike\hud_scenarioicon.cpp" + $File "cstrike\hud_shopping_cart.cpp" + $File "cstrike\cs_hud_achievement_announce.cpp" + $File "cstrike\cs_hud_achievement_announce.h" + $File "cstrike\cs_hud_achievement_tracker.cpp" + $File "cstrike\radio_status.cpp" + $File "cstrike\radio_status.h" + } + + $Folder "Weapon" + { + $File "$SRCDIR\game\shared\cstrike\weapon_ak47.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_aug.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_awp.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_basecsgrenade.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_basecsgrenade.h" + $File "$SRCDIR\game\shared\cstrike\weapon_c4.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_c4.h" + $File "$SRCDIR\game\shared\cstrike\weapon_csbase.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_csbase.h" + $File "$SRCDIR\game\shared\cstrike\weapon_csbasegun.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_csbasegun.h" + $File "$SRCDIR\game\shared\cstrike\weapon_deagle.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_elite.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_famas.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_fiveseven.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_flashbang.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_flashbang.h" + $File "$SRCDIR\game\shared\cstrike\weapon_g3sg1.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_galil.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_glock.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_hegrenade.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_hegrenade.h" + $File "$SRCDIR\game\shared\cstrike\weapon_knife.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_knife.h" + $File "$SRCDIR\game\shared\cstrike\weapon_m249.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_m3.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_m4a1.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_mac10.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_mp5navy.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_p228.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_p90.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_scout.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_sg550.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_sg552.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_smokegrenade.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_smokegrenade.h" + $File "$SRCDIR\game\shared\cstrike\weapon_tmp.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_ump45.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_usp.cpp" + $File "$SRCDIR\game\shared\cstrike\weapon_xm1014.cpp" + } + + $Folder "vgui" + { + $File "cstrike\VGUI\achievement_stats_summary.cpp" + $File "cstrike\VGUI\achievement_stats_summary.h" + $File "cstrike\VGUI\achievements_page.cpp" + $File "cstrike\VGUI\achievements_page.h" + $File "cstrike\VGUI\stats_summary.cpp" + $File "cstrike\VGUI\stats_summary.h" + $File "cstrike\VGUI\stat_card.cpp" + $File "cstrike\VGUI\stat_card.h" + $File "cstrike\VGUI\base_stats_page.cpp" + $File "cstrike\VGUI\base_stats_page.h" + $File "cstrike\VGUI\match_stats_page.cpp" + $File "cstrike\VGUI\match_stats_page.h" + $File "cstrike\VGUI\lifetime_stats_page.cpp" + $File "cstrike\VGUI\lifetime_stats_page.h" + $File "cstrike\VGUI\bordered_panel.cpp" + $File "cstrike\VGUI\bordered_panel.h" + $File "cstrike\VGUI\backgroundpanel.cpp" + $File "cstrike\VGUI\backgroundpanel.h" + $File "cstrike\VGUI\buymouseoverpanelbutton.h" + $File "cstrike\VGUI\buypreset_imageinfo.cpp" + $File "cstrike\VGUI\buypreset_listbox.cpp" + $File "cstrike\VGUI\buypreset_listbox.h" + $File "cstrike\VGUI\buypreset_panel.cpp" + $File "cstrike\VGUI\buypreset_weaponsetlabel.h" + $File "cstrike\VGUI\career_box.cpp" + $File "cstrike\VGUI\career_box.h" + $File "cstrike\VGUI\career_button.cpp" + $File "cstrike\VGUI\career_button.h" + $File "cstrike\VGUI\counterstrikeviewport.cpp" + $File "cstrike\VGUI\counterstrikeviewport.h" + $File "cstrike\VGUI\cstrikebuyequipmenu.cpp" + $File "cstrike\VGUI\cstrikebuyequipmenu.h" + $File "cstrike\VGUI\cstrikebuymenu.cpp" + $File "cstrike\VGUI\cstrikebuymenu.h" + $File "cstrike\VGUI\cstrikebuysubmenu.h" + $File "cstrike\VGUI\cstrikeclassmenu.cpp" + $File "cstrike\VGUI\cstrikeclassmenu.h" + $File "cstrike\VGUI\cstrikeclientscoreboard.cpp" + $File "cstrike\VGUI\cstrikeclientscoreboard.h" + $File "cstrike\VGUI\cstrikespectatorgui.cpp" + $File "cstrike\VGUI\cstrikespectatorgui.h" + $File "cstrike\VGUI\cstriketeammenu.cpp" + $File "cstrike\VGUI\cstriketeammenu.h" + $File "cstrike\VGUI\cstriketextwindow.cpp" + $File "cstrike\VGUI\cstriketextwindow.h" + $File "cstrike\vgui_c4panel.cpp" + $File "cstrike\vgui_viewc4panel.cpp" + $File "cstrike\VGUI\win_panel_round.cpp" + $File "cstrike\VGUI\win_panel_round.h" + } + + $Folder "NextBot" + { + $File "NextBot\C_NextBot.cpp" + $File "NextBot\C_NextBot.h" + } + } + + $Folder "game_controls" + { + $File "game_controls\buymenu.cpp" + $File "game_controls\buysubmenu.cpp" + $File "game_controls\classmenu.cpp" + } + } + + $Folder "Header Files" + { + + $Folder "game_controls header files" + { + $File "game_controls\buymenu.h" + $File "game_controls\buysubmenu.h" + $File "game_controls\classmenu.h" + } + } + + $Folder "Link Libraries" + { + $Lib vtf + } + +} diff --git a/game/client/cstrike/VGUI/achievement_stats_summary.cpp b/game/client/cstrike/VGUI/achievement_stats_summary.cpp new file mode 100644 index 00000000..81ef2983 --- /dev/null +++ b/game/client/cstrike/VGUI/achievement_stats_summary.cpp @@ -0,0 +1,120 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "cbase.h" +#include "achievement_stats_summary.h" +#include "achievements_page.h" +#include "lifetime_stats_page.h" +#include "match_stats_page.h" +#include "stats_summary.h" + +#include + +using namespace vgui; + +#include +#include "vgui/ISurface.h" + +#include "filesystem.h" +#include + +// memdbgon must be the last include file in a .cpp file!!! +#include + + +const int cDialogWidth = 900; + + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +CAchievementAndStatsSummary::CAchievementAndStatsSummary(vgui::Panel *parent) : BaseClass(parent, "AchievementAndStatsSummary") +{ + SetDeleteSelfOnClose(false); + //SetBounds(0, 0, 640, 384); + SetBounds(0, 0, 900, 780); + SetMinimumSize( 640, 780 ); + SetSizeable( false ); + + SetTitle("#GameUI_CreateAchievementsAndStats", true); + SetOKButtonText("#GameUI_Close"); + SetCancelButtonVisible(false); + + m_pStatsSummary = new CStatsSummary( this, "StatsSummary" ); + m_pAchievementsPage = new CAchievementsPage(this, "AchievementsPage"); + m_pLifetimeStatsPage = new CLifetimeStatsPage(this, "StatsPage"); + m_pMatchStatsPage = new CMatchStatsPage(this, "MatchStatsPage"); + + AddPage(m_pStatsSummary, "#GameUI_Stats_Summary"); + AddPage(m_pAchievementsPage, "#GameUI_Achievements_Tab"); + AddPage(m_pMatchStatsPage, "#GameUI_MatchStats"); + AddPage(m_pLifetimeStatsPage, "#GameUI_LifetimeStats"); +} + +//----------------------------------------------------------------------------- +// Purpose: Destructor +//----------------------------------------------------------------------------- +CAchievementAndStatsSummary::~CAchievementAndStatsSummary() +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CAchievementAndStatsSummary::ApplySchemeSettings( vgui::IScheme *pScheme ) +{ + BaseClass::ApplySchemeSettings( pScheme ); + + int screenWide, screenTall; + surface()->GetScreenSize( screenWide, screenTall ); + + // [smessick] Close the achievements dialog for a low resolution screen. + if ( screenWide < cAchievementsDialogMinWidth ) + { + OnOK( true ); + Close(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: runs the server when the OK button is pressed +//----------------------------------------------------------------------------- +bool CAchievementAndStatsSummary::OnOK(bool applyOnly) +{ + BaseClass::OnOK(applyOnly); + + return true; +} + +//---------------------------------------------------------- +// Purpose: Preserve our width to the one in the .res file +//---------------------------------------------------------- +void CAchievementAndStatsSummary::OnSizeChanged(int newWide, int newTall) +{ + // Lock the width, but allow height scaling + if ( newWide != cDialogWidth ) + { + SetSize( cDialogWidth, newTall ); + return; + } + + BaseClass::OnSizeChanged(newWide, newTall); +} + +//---------------------------------------------------------- +// Purpose: Processes when summary dialog is activated. +//---------------------------------------------------------- +void CAchievementAndStatsSummary::Activate() +{ + m_pStatsSummary->MakeReadyForUse(); + m_pStatsSummary->UpdateStatsData(); + m_pAchievementsPage->UpdateAchievementDialogInfo(); + m_pLifetimeStatsPage->UpdateStatsData(); + m_pMatchStatsPage->UpdateStatsData(); + + BaseClass::Activate(); +} diff --git a/game/client/cstrike/VGUI/achievement_stats_summary.h b/game/client/cstrike/VGUI/achievement_stats_summary.h new file mode 100644 index 00000000..c73b4d73 --- /dev/null +++ b/game/client/cstrike/VGUI/achievement_stats_summary.h @@ -0,0 +1,62 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef ACHIEVEMENTANDSTATSSUMMARY_H +#define ACHIEVEMENTANDSTATSSUMMARY_H +#ifdef _WIN32 +#pragma once +#endif + +#include + +class CAchievementsPage; +class CLifetimeStatsPage; +class CMatchStatsPage; +class StatCard; +class CStatsSummary; + +const int cAchievementsDialogMinWidth = 1024; // don't show this screen for lower resolutions + +//----------------------------------------------------------------------------- +// Purpose: dialog for displaying the achievements/stats summary +//----------------------------------------------------------------------------- +class CAchievementAndStatsSummary : public vgui::PropertyDialog +{ + DECLARE_CLASS_SIMPLE( CAchievementAndStatsSummary, vgui::PropertyDialog ); + +public: + CAchievementAndStatsSummary(vgui::Panel *parent); + ~CAchievementAndStatsSummary(); + + virtual void Activate(); + + void OnKeyCodePressed( vgui::KeyCode code ) + { + if ( code == KEY_XBUTTON_B ) + { + Close(); + } + else + { + BaseClass::OnKeyCodePressed(code); + } + } + +protected: + virtual bool OnOK(bool applyOnly); + virtual void OnSizeChanged( int newWide, int newTall ); + virtual void ApplySchemeSettings( vgui::IScheme *pScheme ); + +private: + CAchievementsPage* m_pAchievementsPage; + CLifetimeStatsPage* m_pLifetimeStatsPage; + CMatchStatsPage* m_pMatchStatsPage; + CStatsSummary* m_pStatsSummary; +}; + + +#endif // ACHIEVEMENTANDSTATSSUMMARY_H diff --git a/game/client/cstrike/VGUI/achievements_page.cpp b/game/client/cstrike/VGUI/achievements_page.cpp new file mode 100644 index 00000000..bc6036e3 --- /dev/null +++ b/game/client/cstrike/VGUI/achievements_page.cpp @@ -0,0 +1,1061 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Display a list of achievements for the current game +// +//=============================================================================// + +#include "cbase.h" +#include "achievements_page.h" +#include "vgui_controls/Button.h" +#include "vgui/ILocalize.h" +#include "ixboxsystem.h" +#include "iachievementmgr.h" +#include "filesystem.h" +#include "vgui_controls/ImagePanel.h" +#include "vgui_controls/ComboBox.h" +#include "vgui_controls/CheckButton.h" +#include "fmtstr.h" +#include "c_cs_playerresource.h" +#include "stat_card.h" +#include + +#include "../../../public/steam/steam_api.h" +#include "achievementmgr.h" +#include "../../../../public/vgui/IScheme.h" +#include "../vgui_controls/ScrollBar.h" +#include "achievements_cs.h" + +extern CAchievementMgr g_AchievementMgrCS; + +using namespace vgui; + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +KeyValues *g_pPreloadedCSAchievementPageItemLayout = NULL; +KeyValues *g_pPreloadedCSAchievementPageGroupLayout = NULL; + +// Shared helper functions so xbox and pc can share as much code as possible while coming from different bases. + +//----------------------------------------------------------------------------- +// Purpose: Sets the parameter pIconPanel to display the specified achievement's icon file. +//----------------------------------------------------------------------------- +bool CSLoadAchievementIconForPage( vgui::ImagePanel* pIconPanel, CCSBaseAchievement* pAchievement, const char *pszExt /*= NULL*/ ) +{ + char imagePath[_MAX_PATH]; + Q_strncpy( imagePath, "achievements\\", sizeof(imagePath) ); + Q_strncat( imagePath, pAchievement->GetName(), sizeof(imagePath), COPY_ALL_CHARACTERS ); + if ( pszExt ) + { + Q_strncat( imagePath, pszExt, sizeof(imagePath), COPY_ALL_CHARACTERS ); + } + Q_strncat( imagePath, ".vtf", sizeof(imagePath), COPY_ALL_CHARACTERS ); + + char checkFile[_MAX_PATH]; + Q_snprintf( checkFile, sizeof(checkFile), "materials\\vgui\\%s", imagePath ); + if ( !g_pFullFileSystem->FileExists( checkFile ) ) + { + Q_snprintf( imagePath, sizeof(imagePath), "hud\\icon_locked.vtf" ); + } + + pIconPanel->SetShouldScaleImage( true ); + pIconPanel->SetImage( imagePath ); + pIconPanel->SetVisible( true ); + + return pIconPanel->IsVisible(); +} + +//----------------------------------------------------------------------------- +// Purpose: Sets the parameter pIconPanel to display the specified achievement's icon file. +//----------------------------------------------------------------------------- +bool CSLoadIconForPage( vgui::ImagePanel* pIconPanel, const char* pFilename, const char *pszExt /*= NULL*/ ) +{ + char imagePath[_MAX_PATH]; + Q_strncpy( imagePath, "achievements\\", sizeof(imagePath) ); + Q_strncat( imagePath, pFilename, sizeof(imagePath), COPY_ALL_CHARACTERS ); + if ( pszExt ) + { + Q_strncat( imagePath, pszExt, sizeof(imagePath), COPY_ALL_CHARACTERS ); + } + Q_strncat( imagePath, ".vtf", sizeof(imagePath), COPY_ALL_CHARACTERS ); + + char checkFile[_MAX_PATH]; + Q_snprintf( checkFile, sizeof(checkFile), "materials\\vgui\\%s", imagePath ); + if ( !g_pFullFileSystem->FileExists( checkFile ) ) + { + Q_snprintf( imagePath, sizeof(imagePath), "hud\\icon_locked.vtf" ); + } + + pIconPanel->SetShouldScaleImage( true ); + pIconPanel->SetImage( imagePath ); + pIconPanel->SetVisible( true ); + + return pIconPanel->IsVisible(); +} + +//----------------------------------------------------------------------------- +// The bias is to ensure the percentage bar gets plenty orange before it reaches the text, +// as the white-on-grey is hard to read. +//----------------------------------------------------------------------------- +Color CSLerpColorsForPage ( Color cStart, Color cEnd, float flPercent ) +{ + float r = (float)((float)(cStart.r()) + (float)(cEnd.r() - cStart.r()) * Bias( flPercent, 0.75 ) ); + float g = (float)((float)(cStart.g()) + (float)(cEnd.g() - cStart.g()) * Bias( flPercent, 0.75 ) ); + float b = (float)((float)(cStart.b()) + (float)(cEnd.b() - cStart.b()) * Bias( flPercent, 0.75 ) ); + float a = (float)((float)(cStart.a()) + (float)(cEnd.a() - cStart.a()) * Bias( flPercent, 0.75 ) ); + return Color( r, g, b, a ); +} + +//----------------------------------------------------------------------------- +// Purpose: Shares common percentage bar calculations/color settings between xbox and pc. +// Not really intended for robustness or reuse across many panels. +// Input : pFrame - assumed to have certain child panels (see below) +// *pAchievement - source achievement to poll for progress. Non progress achievements will not show a percentage bar. +//----------------------------------------------------------------------------- +void CSUpdateProgressBarForPage( vgui::EditablePanel* pPanel, CCSBaseAchievement* pAchievement, Color clrProgressBar ) +{ + ///* + if ( pAchievement->GetGoal() > 1 ) + { + bool bShowProgress = true; + + // if this achievement gets saved with game and we're not in a level and have not achieved it, then we do not have any state + // for this achievement, don't show progress + if ( ( pAchievement->GetFlags() & ACH_SAVE_WITH_GAME ) && /*!GameUI().IsInLevel() &&*/ !pAchievement->IsAchieved() ) + { + bShowProgress = false; + } + + float flCompletion = 0.0f; + + // Once achieved, we can't rely on count. If they've completed the achievement just set to 100%. + int iCount = pAchievement->GetCount(); + if ( pAchievement->IsAchieved() ) + { + flCompletion = 1.0f; + iCount = pAchievement->GetGoal(); + } + else if ( bShowProgress ) + { + flCompletion = ( ((float)pAchievement->GetCount()) / ((float)pAchievement->GetGoal()) ); + // In rare cases count can exceed goal and not be achieved (switch local storage on X360, take saved game from different user on PC). + // These will self-correct with continued play, but if we're in that state don't show more than 100% achieved. + flCompletion = MIN( flCompletion, 1.0 ); + } + + char szPercentageText[ 256 ] = ""; + if ( bShowProgress ) + { + Q_snprintf( szPercentageText, 256, "%d/%d", iCount, pAchievement->GetGoal() ); + } + + pPanel->SetControlString( "PercentageText", szPercentageText ); + pPanel->SetControlVisible( "PercentageText", true ); + pPanel->SetControlVisible( "CompletionText", true ); + + vgui::ImagePanel *pPercentageBar = (vgui::ImagePanel*)pPanel->FindChildByName( "PercentageBar" ); + vgui::ImagePanel *pPercentageBarBkg = (vgui::ImagePanel*)pPanel->FindChildByName( "PercentageBarBackground" ); + + if ( pPercentageBar && pPercentageBarBkg ) + { + pPercentageBar->SetFillColor( clrProgressBar ); + pPercentageBar->SetWide( pPercentageBarBkg->GetWide() * flCompletion ); + + pPanel->SetControlVisible( "PercentageBarBackground", IsX360() ? bShowProgress : true ); + pPanel->SetControlVisible( "PercentageBar", true ); + } + } + //*/ +} + +// TODO: revisit this once other games are rebuilt using the updated IAchievement interface +bool CSGameSupportsAchievementTrackerForPage() +{ + const char *pGame = Q_UnqualifiedFileName( engine->GetGameDirectory() ); + return ( !Q_stricmp( pGame, "cstrike" ) ); +} + +////////////////////////////////////////////////////////////////////////// +// PC Implementation +////////////////////////////////////////////////////////////////////////// + + + +int AchivementSortPredicate( CCSBaseAchievement* const* pLeft, CCSBaseAchievement* const* pRight ) +{ + if ( (*pLeft)->IsAchieved() && !(*pRight)->IsAchieved() ) + return -1; + + if ( !(*pLeft)->IsAchieved() && (*pRight)->IsAchieved() ) + return 1; + + if ( (*pLeft)->GetAchievementID() < (*pRight)->GetAchievementID() ) + return -1; + + if ( (*pLeft)->GetAchievementID() > (*pRight)->GetAchievementID() ) + return 1; + + return 0; +} + + +//----------------------------------------------------------------------------- +// Purpose: creates child panels, passes down name to pick up any settings from res files. +//----------------------------------------------------------------------------- +CAchievementsPage::CAchievementsPage(vgui::Panel *parent, const char *name) : BaseClass(parent, "CSAchievementsDialog") +{ + m_iFixedWidth = 900; // Give this an initial value in order to set a proper size + SetBounds(0, 0, 900, 780); + SetMinimumSize( 256, 780 ); + + m_pStatCard = new StatCard(this, "ignored"); + + m_pAchievementsList = new vgui::PanelListPanel( this, "listpanel_achievements" ); + m_pAchievementsList->SetFirstColumnWidth( 0 ); + + m_pGroupsList = new vgui::PanelListPanel( this, "listpanel_groups" ); + m_pGroupsList->SetFirstColumnWidth( 0 ); + + m_pListBG = new vgui::ImagePanel( this, "listpanel_background" ); + + m_pPercentageBarBackground = SETUP_PANEL( new ImagePanel( this, "PercentageBarBackground" ) ); + m_pPercentageBar = SETUP_PANEL( new ImagePanel( this, "PercentageBar" ) ); + + ListenForGameEvent( "player_stats_updated" ); + ListenForGameEvent( "achievement_earned_local" ); + + // int that holds the highest number achievement id we've found + int iHighestAchievementIDSeen = -1; + int iNextGroupBoundary = 1000; + + Q_memset( m_AchievementGroups, 0, sizeof(m_AchievementGroups) ); + m_iNumAchievementGroups = 0; + + // Base groups + int iCount = g_AchievementMgrCS.GetAchievementCount(); + for ( int i = 0; i < iCount; ++i ) + { + CCSBaseAchievement* pAchievement = dynamic_cast(g_AchievementMgrCS.GetAchievementByIndex( i )); + + if ( !pAchievement ) + continue; + + int iAchievementID = pAchievement->GetAchievementID(); + + if ( iAchievementID > iHighestAchievementIDSeen ) + { + // if it's crossed the next group boundary, create a new group + if ( iAchievementID >= iNextGroupBoundary ) + { + int iNewGroupBoundary = iAchievementID; + CreateNewAchievementGroup( iNewGroupBoundary, iNewGroupBoundary+99 ); + + iNextGroupBoundary = iNewGroupBoundary + 100; + } + + iHighestAchievementIDSeen = iAchievementID; + } + } + + LoadControlSettings("resource/ui/CSAchievementsDialog.res"); + UpdateTotalProgressDisplay(); + CreateOrUpdateComboItems( true ); + + // Default display shows the first achievement group + UpdateAchievementList(1001, 1100); + + m_bStatsDirty = true; + m_bAchievementsDirty = true; +} + +CAchievementsPage::~CAchievementsPage() +{ + g_AchievementMgrCS.SaveGlobalStateIfDirty( false ); // check for saving here to store achievements we want pinned to HUD + + m_pAchievementsList->DeleteAllItems(); + delete m_pAchievementsList; + delete m_pPercentageBarBackground; + delete m_pPercentageBar; +} + +void CAchievementsPage::CreateNewAchievementGroup( int iMinRange, int iMaxRange ) +{ + m_AchievementGroups[m_iNumAchievementGroups].m_iMinRange = iMinRange; + m_AchievementGroups[m_iNumAchievementGroups].m_iMaxRange = iMaxRange; + m_iNumAchievementGroups++; +} + +//---------------------------------------------------------- +// Get the width we're going to lock at +//---------------------------------------------------------- +void CAchievementsPage::ApplySettings( KeyValues *pResourceData ) +{ + m_iFixedWidth = pResourceData->GetInt( "wide", 512 ); + + BaseClass::ApplySettings( pResourceData ); +} + +//---------------------------------------------------------- +// Preserve our width to the one in the .res file +//---------------------------------------------------------- +void CAchievementsPage::OnSizeChanged(int newWide, int newTall) +{ + // Lock the width, but allow height scaling + if ( newWide != m_iFixedWidth ) + { + SetSize( m_iFixedWidth, newTall ); + return; + } + + BaseClass::OnSizeChanged(newWide, newTall); +} + +//---------------------------------------------------------- +// Re-populate the achievement list with the selected group +//---------------------------------------------------------- +void CAchievementsPage::UpdateAchievementList(CAchievementsPageGroupPanel* groupPanel) +{ + if (!groupPanel) + return; + + UpdateAchievementList( groupPanel->GetFirstAchievementID(), groupPanel->GetLastAchievementID() ); + + vgui::IScheme *pGroupScheme = scheme()->GetIScheme( GetScheme() ); + + // Update active status for button display + for (int i = 0; i < m_pGroupsList->GetItemCount(); i++) + { + CAchievementsPageGroupPanel *pPanel = (CAchievementsPageGroupPanel*)m_pGroupsList->GetItemPanel(i); + if ( pPanel ) + { + if ( pPanel != groupPanel ) + { + pPanel->SetGroupActive( false ); + } + else + { + pPanel->SetGroupActive( true ); + } + + pPanel->UpdateAchievementInfo( pGroupScheme ); + } + } +} + +void CAchievementsPage::UpdateTotalProgressDisplay() +{ + // Set up total completion percentage bar + float flCompletion = 0.0f; + + int iCount = g_AchievementMgrCS.GetAchievementCount(); + int nUnlocked = 0; + + if ( iCount > 0 ) + { + for ( int i = 0; i < iCount; ++i ) + { + CCSBaseAchievement* pAchievement = dynamic_cast(g_AchievementMgrCS.GetAchievementByIndex( i )); + + if ( pAchievement && pAchievement->IsAchieved() ) + ++nUnlocked; + } + + flCompletion = (((float)nUnlocked) / ((float)g_AchievementMgrCS.GetAchievementCount())); + } + + char szPercentageText[64]; + V_sprintf_safe( szPercentageText, "%d / %d", + nUnlocked, g_AchievementMgrCS.GetAchievementCount() ); + + SetControlString( "PercentageText", szPercentageText ); + SetControlVisible( "PercentageText", true ); + SetControlVisible( "CompletionText", true ); + + vgui::IScheme *pScheme = scheme()->GetIScheme( GetScheme() ); + + Color clrHighlight = pScheme->GetColor( "NewGame.SelectionColor", Color(255, 255, 255, 255) ); + Color clrWhite(255, 255, 255, 255); + + Color cProgressBar = Color( static_cast( clrHighlight.r() ) * ( 1.0f - flCompletion ) + static_cast( clrWhite.r() ) * flCompletion, + static_cast( clrHighlight.g() ) * ( 1.0f - flCompletion ) + static_cast( clrWhite.g() ) * flCompletion, + static_cast( clrHighlight.b() ) * ( 1.0f - flCompletion ) + static_cast( clrWhite.b() ) * flCompletion, + static_cast( clrHighlight.a() ) * ( 1.0f - flCompletion ) + static_cast( clrWhite.a() ) * flCompletion ); + + m_pPercentageBar->SetFgColor( cProgressBar ); + m_pPercentageBar->SetWide( m_pPercentageBarBackground->GetWide() * flCompletion ); + + SetControlVisible( "PercentageBarBackground", true ); + SetControlVisible( "PercentageBar", true ); +} + +//---------------------------------------------------------- +// Re-populate the achievement list with the selected group +//---------------------------------------------------------- +void CAchievementsPage::UpdateAchievementList(int minID, int maxID) +{ + int iMinRange = minID; + int iMaxRange = maxID; + + int iCount = g_AchievementMgrCS.GetAchievementCount(); + + CUtlVector sortedAchivementList; + sortedAchivementList.EnsureCapacity(iCount); + + for ( int i = 0; i < iCount; ++i ) + { + CCSBaseAchievement* pAchievement = dynamic_cast(g_AchievementMgrCS.GetAchievementByIndex(i)); + + if ( !pAchievement ) + continue; + + int iAchievementID = pAchievement->GetAchievementID(); + + if ( iAchievementID < iMinRange || iAchievementID > iMaxRange ) + continue; + + // don't show hidden achievements if not achieved + if ( pAchievement->ShouldHideUntilAchieved() && !pAchievement->IsAchieved() ) + continue; + + sortedAchivementList.AddToTail(pAchievement); + } + + sortedAchivementList.Sort(AchivementSortPredicate); + + m_pAchievementsList->DeleteAllItems(); + + FOR_EACH_VEC(sortedAchivementList, i) + { + CCSBaseAchievement* pAchievement = sortedAchivementList[i]; + + CAchievementsPageItemPanel *pAchievementItemPanel = new CAchievementsPageItemPanel( m_pAchievementsList, "AchievementDialogItemPanel"); + pAchievementItemPanel->SetAchievementInfo(pAchievement); + + // force all our new panel to have the correct internal layout and size so that our parent container can layout properly + pAchievementItemPanel->InvalidateLayout(true, true); + + m_pAchievementsList->AddItem( NULL, pAchievementItemPanel ); + } + + m_pAchievementsList->MoveScrollBarToTop(); +} + +//----------------------------------------------------------------------------- +// Purpose: Loads settings from achievementsdialog.res in hl2/resource/ui/ +// Sets up progress bar displaying total achievement unlocking progress by the user. +//----------------------------------------------------------------------------- +void CAchievementsPage::ApplySchemeSettings( vgui::IScheme *pScheme ) +{ + BaseClass::ApplySchemeSettings( pScheme ); + + m_pGroupsList->SetBgColor(Color(86,86,86,255)); + + SetBgColor(Color(86,86,86,255)); + + // Set text color for percentage + Panel *pPanel; + pPanel = FindChildByName("PercentageText"); + if (pPanel) + { + pPanel->SetFgColor(Color(157, 194, 80, 255)); + } + + // Set text color for achievement earned label + pPanel = FindChildByName("AchievementsEarnedLabel"); + if (pPanel) + { + pPanel->SetFgColor(Color(157, 194, 80, 255)); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Each sub-panel gets its data updated +//----------------------------------------------------------------------------- +void CAchievementsPage::UpdateAchievementDialogInfo( void ) +{ + // Hide the group list scrollbar + if (m_pGroupsList->GetScrollbar()) + { + m_pGroupsList->GetScrollbar()->SetWide(0); + } + + int iCount = m_pAchievementsList->GetItemCount(); + vgui::IScheme *pScheme = scheme()->GetIScheme( GetScheme() ); + + int i; + for ( i = 0; i < iCount; i++ ) + { + CAchievementsPageItemPanel *pPanel = (CAchievementsPageItemPanel*)m_pAchievementsList->GetItemPanel(i); + if ( pPanel ) + { + pPanel->UpdateAchievementInfo( pScheme ); + } + } + + // Update all group panels + int iGroupCount = m_pGroupsList->GetItemCount(); + for ( i = 0; i < iGroupCount; i++ ) + { + CAchievementsPageGroupPanel *pPanel = (CAchievementsPageGroupPanel*)m_pGroupsList->GetItemPanel(i); + if ( pPanel ) + { + pPanel->UpdateAchievementInfo( pScheme ); + + if ( pPanel->IsGroupActive() ) + { + UpdateAchievementList( pPanel ); + } + } + } + + // update the groups and overall progress bar + CreateOrUpdateComboItems( false ); // update them with new achieved counts + + UpdateTotalProgressDisplay(); + + m_pStatCard->UpdateInfo(); + + m_bAchievementsDirty = false; + m_bStatsDirty = false; +} + +void CAchievementsPage::CreateOrUpdateComboItems( bool bCreate ) +{ + // Build up achievement group names + for ( int i=0;iFind( buf ); + + if ( !wzGroupName ) + { + wzGroupName = L"Need Title ( %s1 of %s2 )"; + } + + wchar_t wzGroupTitle[128]; + + if ( wzGroupName ) + { + // Determine number of achievements in the group which have been awarded + int numAwarded = 0; + int numTested = 0; + for (int j = m_AchievementGroups[i].m_iMinRange; j < m_AchievementGroups[i].m_iMaxRange; j++) + { + IAchievement* pCur = g_AchievementMgrCS.GetAchievementByID( j ); + + if ( !pCur ) + continue; + + numTested++; + + if ( pCur->IsAchieved() ) + { + numAwarded++; + } + } + + wchar_t wzNumUnlocked[8]; + V_snwprintf( wzNumUnlocked, ARRAYSIZE( wzNumUnlocked ), L"%d", numAwarded ); + + wchar_t wzNumAchievements[8]; + V_snwprintf( wzNumAchievements, ARRAYSIZE( wzNumAchievements ), L"%d", numTested ); + + g_pVGuiLocalize->ConstructString( wzGroupTitle, sizeof( wzGroupTitle ), wzGroupName, 0 ); + } + + KeyValues *pKV = new KeyValues( "grp" ); + pKV->SetInt( "minrange", m_AchievementGroups[i].m_iMinRange ); + pKV->SetInt( "maxrange", m_AchievementGroups[i].m_iMaxRange ); + + if ( bCreate ) + { + // Create an achievement group instance + CAchievementsPageGroupPanel *achievementGroupPanel = new CAchievementsPageGroupPanel( m_pGroupsList, this, "AchievementDialogGroupPanel", i ); + achievementGroupPanel->SetGroupInfo( wzGroupTitle, m_AchievementGroups[i].m_iMinRange, m_AchievementGroups[i].m_iMaxRange ); + + if (i == 0) + { + achievementGroupPanel->SetGroupActive(true); + } + else + { + achievementGroupPanel->SetGroupActive(false); + } + + m_pGroupsList->AddItem( NULL, achievementGroupPanel ); + } + } + + m_pStatCard->UpdateInfo(); +} + +//----------------------------------------------------------------------------- +// Purpose: creates child panels, passes down name to pick up any settings from res files. +//----------------------------------------------------------------------------- +CAchievementsPageItemPanel::CAchievementsPageItemPanel( vgui::PanelListPanel *parent, const char* name) : BaseClass( parent, name ) +{ + m_pParent = parent; + m_pSchemeSettings = NULL; + + m_pAchievementIcon = SETUP_PANEL(new vgui::ImagePanel( this, "AchievementIcon" )); + m_pAchievementNameLabel = new vgui::Label( this, "AchievementName", "name" ); + m_pAchievementDescLabel = new vgui::Label( this, "AchievementDesc", "desc" ); + m_pPercentageBar = SETUP_PANEL( new ImagePanel( this, "PercentageBar" ) ); + m_pPercentageText = new vgui::Label( this, "PercentageText", "" ); + m_pAwardDate = new vgui::Label( this, "AwardDate", "date" ); + m_pShowOnHUDButton = new vgui::CheckButton( this, "ShowOnHudToggle", "" ); + m_pShowOnHUDButton->SetMouseInputEnabled( true ); + m_pShowOnHUDButton->SetEnabled( true ); + m_pShowOnHUDButton->SetCheckButtonCheckable( true ); + m_pShowOnHUDButton->AddActionSignalTarget( this ); + + m_pHiddenHUDToggleButton = new CHiddenHUDToggleButton( this, "HiddenHUDToggle", "" ); + m_pHiddenHUDToggleButton->SetPaintBorderEnabled( false ); + + + SetMouseInputEnabled( true ); + parent->SetMouseInputEnabled( true ); +} + +CAchievementsPageItemPanel::~CAchievementsPageItemPanel() +{ + delete m_pAchievementIcon; + delete m_pAchievementNameLabel; + delete m_pAchievementDescLabel; + delete m_pPercentageBar; + delete m_pPercentageText; + delete m_pAwardDate; + delete m_pShowOnHUDButton; + delete m_pHiddenHUDToggleButton; +} + +void CAchievementsPageItemPanel::ToggleShowOnHUDButton() +{ + if (m_pShowOnHUDButton) + { + m_pShowOnHUDButton->SetSelected( !m_pShowOnHUDButton->IsSelected() ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Updates displayed achievement data. In applyschemesettings, and when gameui activates. +//----------------------------------------------------------------------------- +void CAchievementsPageItemPanel::UpdateAchievementInfo( vgui::IScheme* pScheme ) +{ + if ( m_pSourceAchievement && m_pSchemeSettings ) + { + //============================================================================= + // HPE_BEGIN: + // [dwenger] Get achievement name and description text from the localized file + //============================================================================= + + // Set name, description and unlocked state text + m_pAchievementNameLabel->SetText( ACHIEVEMENT_LOCALIZED_NAME( m_pSourceAchievement ) ); + m_pAchievementDescLabel->SetText( ACHIEVEMENT_LOCALIZED_DESC( m_pSourceAchievement ) ); + + //============================================================================= + // HPE_END + //============================================================================= + + // Setup icon + // get the vtfFilename from the path. + + // Display percentage completion for progressive achievements + // Set up total completion percentage bar. Goal > 1 means its a progress achievement. + CSUpdateProgressBarForPage( this, m_pSourceAchievement, m_clrProgressBar ); + + if ( m_pSourceAchievement->IsAchieved() ) + { + CSLoadAchievementIconForPage( m_pAchievementIcon, m_pSourceAchievement ); + + SetBgColor( pScheme->GetColor( "AchievementsLightGrey", Color(255, 0, 0, 255) ) ); + + m_pAchievementNameLabel->SetFgColor( pScheme->GetColor( "SteamLightGreen", Color(255, 255, 255, 255) ) ); + + Color fgColor = pScheme->GetColor( "Label.TextBrightColor", Color(255, 255, 255, 255) ); + m_pAchievementDescLabel->SetFgColor( fgColor ); + m_pPercentageText->SetFgColor( fgColor ); + m_pShowOnHUDButton->SetVisible( false ); + m_pShowOnHUDButton->SetSelected( false ); + m_pHiddenHUDToggleButton->SetVisible( false ); + m_pAwardDate->SetVisible( true ); + m_pAwardDate->SetFgColor( pScheme->GetColor( "SteamLightGreen", Color(255, 255, 255, 255) ) ); + + // Assign the award date text + int year, month, day, hour, minute, second; + if ( m_pSourceAchievement->GetAwardTime(year, month, day, hour, minute, second) ) + { + char dateBuffer[32] = ""; + Q_snprintf( dateBuffer, 32, "%4d-%02d-%02d", year, month, day ); + m_pAwardDate->SetText( dateBuffer ); + } + else + m_pAwardDate->SetText( "" ); + } + else + { + CSLoadAchievementIconForPage( m_pAchievementIcon, m_pSourceAchievement, "_bw" ); + + SetBgColor( pScheme->GetColor( "AchievementsDarkGrey", Color(255, 0, 0, 255) ) ); + + Color fgColor = pScheme->GetColor( "AchievementsInactiveFG", Color(255, 255, 255, 255) ); + m_pAchievementNameLabel->SetFgColor( fgColor ); + m_pAchievementDescLabel->SetFgColor( fgColor ); + m_pPercentageText->SetFgColor( fgColor ); + + if ( CSGameSupportsAchievementTrackerForPage() ) + { + m_pShowOnHUDButton->SetVisible( !m_pSourceAchievement->ShouldHideUntilAchieved() ); + m_pShowOnHUDButton->SetSelected( m_pSourceAchievement->ShouldShowOnHUD() ); + + m_pHiddenHUDToggleButton->SetVisible( !m_pSourceAchievement->ShouldHideUntilAchieved() ); + } + else + { + m_pShowOnHUDButton->SetVisible( false ); + m_pHiddenHUDToggleButton->SetVisible( false ); + } + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Makes a local copy of a pointer to the achievement entity stored on the client. +//----------------------------------------------------------------------------- +void CAchievementsPageItemPanel::SetAchievementInfo( CCSBaseAchievement* pAchievement ) +{ + if ( !pAchievement ) + { + Assert( 0 ); + return; + } + + m_pSourceAchievement = pAchievement; + m_iSourceAchievementIndex = pAchievement->GetAchievementID(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CAchievementsPageItemPanel::PreloadResourceFile( void ) +{ + const char *controlResourceName = "resource/ui/AchievementItem.res"; + + g_pPreloadedCSAchievementPageItemLayout = new KeyValues(controlResourceName); + g_pPreloadedCSAchievementPageItemLayout->LoadFromFile(g_pFullFileSystem, controlResourceName); + +/* + // precache all achievement icons + int iCount = g_AchievementMgrCS.GetAchievementCount(); + for ( int i = 0; i < iCount; ++i ) + { + CCSBaseAchievement* pAchievement = dynamic_cast(g_AchievementMgrCS.GetAchievementByIndex( i )); + char imagePath[_MAX_PATH]; + + Q_strncpy( imagePath, "achievements\\", sizeof(imagePath) ); + Q_strncat( imagePath, pAchievement->GetName(), sizeof(imagePath), COPY_ALL_CHARACTERS ); + Q_strncat( imagePath, "_bw", sizeof(imagePath), COPY_ALL_CHARACTERS ); + Q_strncat( imagePath, ".vtf", sizeof(imagePath), COPY_ALL_CHARACTERS ); + + scheme()->GetImage(imagePath, true); + + Q_strncpy( imagePath, "achievements\\", sizeof(imagePath) ); + Q_strncat( imagePath, pAchievement->GetName(), sizeof(imagePath), COPY_ALL_CHARACTERS ); + Q_strncat( imagePath, ".vtf", sizeof(imagePath), COPY_ALL_CHARACTERS ); + + scheme()->GetImage(imagePath, true); + } +*/ +} + +//----------------------------------------------------------------------------- +// Purpose: Loads settings from hl2/resource/ui/achievementitem.res +// Sets display info for this achievement item. +//----------------------------------------------------------------------------- +void CAchievementsPageItemPanel::ApplySchemeSettings( vgui::IScheme* pScheme ) +{ + if ( !g_pPreloadedCSAchievementPageItemLayout ) + { + PreloadResourceFile(); + } + + LoadControlSettings( "", NULL, g_pPreloadedCSAchievementPageItemLayout ); + + m_pSchemeSettings = pScheme; + + if ( !m_pSourceAchievement ) + { + return; + } + + BaseClass::ApplySchemeSettings( pScheme ); + + // m_pSchemeSettings must be set for this. + UpdateAchievementInfo( pScheme ); +} + +void CAchievementsPageItemPanel::OnCheckButtonChecked(Panel *panel) +{ + if ( CSGameSupportsAchievementTrackerForPage() && panel == m_pShowOnHUDButton && m_pSourceAchievement ) + { + m_pSourceAchievement->SetShowOnHUD( m_pShowOnHUDButton->IsSelected() ); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: creates child panels, passes down name to pick up any settings from res files. +//----------------------------------------------------------------------------- +CAchievementsPageGroupPanel::CAchievementsPageGroupPanel( vgui::PanelListPanel *parent, CAchievementsPage *owner, const char* name, int iListItemID ) : BaseClass( parent, name ) +{ + m_pParent = parent; + m_pOwner = owner; + m_pSchemeSettings = NULL; + + m_pGroupIcon = SETUP_PANEL(new vgui::ImagePanel( this, "GroupIcon" )); + m_pAchievementGroupLabel = new vgui::Label( this, "GroupName", "name" ); + m_pPercentageText = new vgui::Label( this, "GroupPercentageText", "1/1" ); + m_pPercentageBar = SETUP_PANEL( new ImagePanel( this, "GroupPercentageBar" ) ); + m_pGroupButton = new CGroupButton( this, "GroupButton", "" ); + m_pGroupButton->SetPos( 0, 0 ); + m_pGroupButton->SetZPos( 20 ); + m_pGroupButton->SetWide( 256 ); + m_pGroupButton->SetTall( 64 ); + SetMouseInputEnabled( true ); + parent->SetMouseInputEnabled( true ); + + m_bActiveButton = false; +} + +CAchievementsPageGroupPanel::~CAchievementsPageGroupPanel() +{ + delete m_pAchievementGroupLabel; + delete m_pPercentageBar; + delete m_pPercentageText; + delete m_pGroupIcon; +} + +//----------------------------------------------------------------------------- +// Purpose: Loads settings from hl2/resource/ui/achievementitem.res +// Sets display info for this achievement item. +//----------------------------------------------------------------------------- +void CAchievementsPageGroupPanel::ApplySchemeSettings( vgui::IScheme* pScheme ) +{ + if ( !g_pPreloadedCSAchievementPageGroupLayout ) + { + PreloadResourceFile(); + } + + LoadControlSettings( "", NULL, g_pPreloadedCSAchievementPageGroupLayout ); + + m_pSchemeSettings = pScheme; + + BaseClass::ApplySchemeSettings( pScheme ); + + // m_pSchemeSettings must be set for this. + UpdateAchievementInfo( pScheme ); +} + +//----------------------------------------------------------------------------- +// Purpose: Updates displayed achievement data. In ApplySchemeSettings(), and +// when gameui activates. +//----------------------------------------------------------------------------- +void CAchievementsPageGroupPanel::UpdateAchievementInfo( vgui::IScheme* pScheme ) +{ + if ( m_pSchemeSettings ) + { + int numAwarded = 0; + int numTested = 0; + + char buf[128]; + int achievementRangeStart = (m_iFirstAchievementID / 1000) * 1000; + Q_snprintf( buf, sizeof(buf), "#Achievement_Group_%d", achievementRangeStart ); + + wchar_t *wzGroupName = g_pVGuiLocalize->Find( buf ); + + if ( !wzGroupName ) + { + wzGroupName = L"Need Title ( %s1 of %s2 )"; + } + + wchar_t wzGroupTitle[128]; + + if ( wzGroupName ) + { + // Determine number of achievements in the group which have been awarded + for (int i = m_iFirstAchievementID; i < m_iLastAchievementID; i++) + { + IAchievement* pCur = g_AchievementMgrCS.GetAchievementByID( i ); + + if ( !pCur ) + continue; + + numTested++; + + if ( pCur->IsAchieved() ) + { + numAwarded++; + } + } + + wchar_t wzNumUnlocked[8]; + V_snwprintf( wzNumUnlocked, ARRAYSIZE( wzNumUnlocked ), L"%d", numAwarded ); + + wchar_t wzNumAchievements[8]; + V_snwprintf( wzNumAchievements,ARRAYSIZE( wzNumAchievements ), L"%d", numTested ); + + g_pVGuiLocalize->ConstructString( wzGroupTitle, sizeof( wzGroupTitle ), wzGroupName, 2, wzNumUnlocked, wzNumAchievements ); + } + + // Set group name text + m_pAchievementGroupLabel->SetText( wzGroupTitle );//m_pGroupName ); + m_pAchievementGroupLabel->SetFgColor(Color(157, 194, 80, 255)); + + char* buff[32]; + Q_snprintf( (char*)buff, 32, "%d / %d", numAwarded, numTested ); + m_pPercentageText->SetText( (const char*)buff ); + m_pPercentageText->SetFgColor(Color(157, 194, 80, 255)); + + if ( !m_bActiveButton ) + { + CSLoadIconForPage( m_pGroupIcon, "achievement-btn-up" ); + } + else + { + CSLoadIconForPage( m_pGroupIcon, "achievement-btn-select" ); + } + + // Update the percentage complete bar + vgui::ImagePanel *pPercentageBar = (vgui::ImagePanel*)FindChildByName( "GroupPercentageBar" ); + vgui::ImagePanel *pPercentageBarBkg = (vgui::ImagePanel*)FindChildByName( "GroupPercentageBarBackground" ); + + if ( pPercentageBar && pPercentageBarBkg ) + { + float flCompletion = (float)numAwarded / (float)numTested; + pPercentageBar->SetFillColor( Color(157, 194, 80, 255) ); + pPercentageBar->SetWide( pPercentageBarBkg->GetWide() * flCompletion ); + + SetControlVisible( "GroupPercentageBarBackground", true ); + SetControlVisible( "GroupPercentageBar", true ); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CAchievementsPageGroupPanel::PreloadResourceFile( void ) +{ + const char *controlResourceName = "resource/ui/AchievementGroup.res"; + + g_pPreloadedCSAchievementPageGroupLayout = new KeyValues(controlResourceName); + g_pPreloadedCSAchievementPageGroupLayout->LoadFromFile(g_pFullFileSystem, controlResourceName); + + +} + +//----------------------------------------------------------------------------- +// Purpose: Assigns a name and achievement id bounds for an achievement group. +//----------------------------------------------------------------------------- +void CAchievementsPageGroupPanel::SetGroupInfo( const wchar_t* name, int firstAchievementID, int lastAchievementID ) +{ + // Store away the group name + short _textLen = (short)wcslen(name) + 1; + m_pGroupName = new wchar_t[_textLen]; + Q_memcpy( m_pGroupName, name, _textLen * sizeof(wchar_t) ); + + // Store off the start & end achievement IDs + m_iFirstAchievementID = firstAchievementID; + m_iLastAchievementID = lastAchievementID; +} + +CGroupButton::CGroupButton( vgui::Panel *pParent, const char *pName, const char *pText ) : +BaseClass( pParent, pName, pText ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: Handle the case where the user presses an achievement group button. +//----------------------------------------------------------------------------- +void CGroupButton::DoClick( void ) +{ + // Process when a group button is hit + CAchievementsPageGroupPanel* pParent = static_cast(GetParent()); + + if (pParent) + { + CAchievementsPage* pAchievementsPage = static_cast(pParent->GetOwner()); + + if (pAchievementsPage) + { + // Update the list of group achievements + pAchievementsPage->UpdateAchievementList( pParent ); + } + } +} + +void CAchievementsPage::OnPageShow() +{ + m_pGroupsList->GetScrollbar()->SetWide(0); +} + +void CAchievementsPage::FireGameEvent( IGameEvent *event ) +{ + const char *type = event->GetName(); + + if ( 0 == Q_strcmp( type, "achievement_earned_local" ) ) + m_bAchievementsDirty = true; + + if ( 0 == Q_strcmp( type, "player_stats_updated" ) ) + m_bStatsDirty = true; +} + +void CAchievementsPage::OnThink() +{ + vgui::IScheme *pScheme = scheme()->GetIScheme( GetScheme() ); + + if ( m_bAchievementsDirty ) + { + UpdateAchievementDialogInfo(); + } + else if ( m_bStatsDirty ) + { + // Update progress for currently displayed achievements + int itemId = m_pAchievementsList->FirstItem(); + + while (itemId != m_pAchievementsList->InvalidItemID() ) + { + CAchievementsPageItemPanel *pAchievementItem = dynamic_cast(m_pAchievementsList->GetItemPanel(itemId)); + pAchievementItem->UpdateAchievementInfo(pScheme); + + itemId = m_pAchievementsList->NextItem(itemId); + } + m_bStatsDirty = false; + } +} + +CHiddenHUDToggleButton::CHiddenHUDToggleButton( vgui::Panel *pParent, const char *pName, const char *pText ) : +BaseClass( pParent, pName, pText ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: Handle the case where the user shift-clicks on an un-awarded achievement. +//----------------------------------------------------------------------------- +void CHiddenHUDToggleButton::DoClick( void ) +{ + if ( input()->IsKeyDown(KEY_LSHIFT) || input()->IsKeyDown(KEY_RSHIFT) ) + { + // Process when a group button is hit + CAchievementsPageItemPanel* pParent = static_cast(GetParent()); + + if (pParent) + { + pParent->ToggleShowOnHUDButton(); + } + } +} diff --git a/game/client/cstrike/VGUI/achievements_page.h b/game/client/cstrike/VGUI/achievements_page.h new file mode 100644 index 00000000..2066b1db --- /dev/null +++ b/game/client/cstrike/VGUI/achievements_page.h @@ -0,0 +1,218 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef CSACHIEVEMENTSPAGE_H +#define CSACHIEVEMENTSPAGE_H +#ifdef _WIN32 +#pragma once +#endif + +#include "vgui_controls/PanelListPanel.h" +#include "vgui_controls/Label.h" +#include "tier1/KeyValues.h" +#include "vgui_controls/PropertyPage.h" +#include "vgui_controls/Button.h" +#include "c_cs_player.h" +#include "vgui_avatarimage.h" +#include "GameEventListener.h" + +class CCSBaseAchievement; +class IScheme; +class CAchievementsPageGroupPanel; +class StatCard; + +#define ACHIEVED_ICON_PATH "hud/icon_check.vtf" +#define LOCK_ICON_PATH "hud/icon_locked.vtf" + +// Loads an achievement's icon into a specified image panel, or turns the panel off if no achievement icon was found. +bool CSLoadAchievementIconForPage( vgui::ImagePanel* pIconPanel, CCSBaseAchievement *pAchievement, const char *pszExt = NULL ); + +// Loads an achievement's icon into a specified image panel, or turns the panel off if no achievement icon was found. +bool CSLoadIconForPage( vgui::ImagePanel* pIconPanel, const char* pFilename, const char *pszExt = NULL ); + +// Updates a listed achievement item's progress bar. +void CSUpdateProgressBarForPage( vgui::EditablePanel* pPanel, CCSBaseAchievement *pAchievement, Color clrProgressBar ); + +//////////////////////////////////////////////////////////////////////////// +// PC version +////////////////////////////////////////////////////////////////////////// +class CAchievementsPage : public vgui::PropertyPage, public CGameEventListener +{ + DECLARE_CLASS_SIMPLE ( CAchievementsPage, vgui::PropertyPage ); + +public: + CAchievementsPage( vgui::Panel *parent, const char *name ); + ~CAchievementsPage(); + + virtual void ApplySchemeSettings( vgui::IScheme *pScheme ); + + void UpdateTotalProgressDisplay(); + virtual void UpdateAchievementDialogInfo( void ); + + virtual void OnPageShow(); + virtual void OnThink(); + + virtual void ApplySettings( KeyValues *pResourceData ); + virtual void OnSizeChanged( int newWide, int newTall ); + + virtual void FireGameEvent( IGameEvent *event ); + + void CreateNewAchievementGroup( int iMinRange, int iMaxRange ); + void CreateOrUpdateComboItems( bool bCreate ); + void UpdateAchievementList(CAchievementsPageGroupPanel* groupPanel); + void UpdateAchievementList(int minID, int maxID); + + vgui::PanelListPanel *m_pAchievementsList; + vgui::ImagePanel *m_pListBG; + + vgui::PanelListPanel *m_pGroupsList; + vgui::ImagePanel *m_pGroupListBG; + + vgui::ImagePanel *m_pPercentageBarBackground; + vgui::ImagePanel *m_pPercentageBar; + + StatCard* m_pStatCard; + + int m_iFixedWidth; + + bool m_bStatsDirty; + bool m_bAchievementsDirty; + + typedef struct + { + int m_iMinRange; + int m_iMaxRange; + } achievement_group_t; + + int m_iNumAchievementGroups; + + achievement_group_t m_AchievementGroups[15]; +}; + +class CHiddenHUDToggleButton : public vgui::Button +{ + DECLARE_CLASS_SIMPLE( CHiddenHUDToggleButton, vgui::Button ); + +public: + + CHiddenHUDToggleButton( vgui::Panel *pParent, const char *pName, const char *pText ); + + virtual void DoClick( void ); +}; + +////////////////////////////////////////////////////////////////////////// +// Individual item panel, displaying stats for one achievement +class CAchievementsPageItemPanel : public vgui::EditablePanel +{ + DECLARE_CLASS_SIMPLE( CAchievementsPageItemPanel, vgui::EditablePanel ); + +public: + CAchievementsPageItemPanel( vgui::PanelListPanel *parent, const char* name); + ~CAchievementsPageItemPanel(); + + void SetAchievementInfo ( CCSBaseAchievement* pAchievement ); + CCSBaseAchievement* GetAchievementInfo( void ) { return m_pSourceAchievement; } + void UpdateAchievementInfo( vgui::IScheme *pScheme ); + virtual void ApplySchemeSettings( vgui::IScheme *pScheme ); + + void ToggleShowOnHUDButton(); + + MESSAGE_FUNC_PTR( OnCheckButtonChecked, "CheckButtonChecked", panel ); + +private: + static void PreloadResourceFile(); + + CCSBaseAchievement* m_pSourceAchievement; + int m_iSourceAchievementIndex; + + vgui::PanelListPanel *m_pParent; + + vgui::Label *m_pAchievementNameLabel; + vgui::Label *m_pAchievementDescLabel; + vgui::Label *m_pPercentageText; + vgui::Label *m_pAwardDate; + + vgui::ImagePanel *m_pLockedIcon; + vgui::ImagePanel *m_pAchievementIcon; + + vgui::ImagePanel *m_pPercentageBarBackground; + vgui::ImagePanel *m_pPercentageBar; + + vgui::CheckButton *m_pShowOnHUDButton; + + vgui::IScheme *m_pSchemeSettings; + + CHiddenHUDToggleButton *m_pHiddenHUDToggleButton; + + CPanelAnimationVar( Color, m_clrProgressBar, "ProgressBarColor", "140 140 140 255" ); +}; + +class CGroupButton : public vgui::Button +{ + DECLARE_CLASS_SIMPLE( CGroupButton, vgui::Button ); + +public: + + CGroupButton( vgui::Panel *pParent, const char *pName, const char *pText ); + + virtual void DoClick( void ); +}; + +////////////////////////////////////////////////////////////////////////// +// Individual achievement group panel, displaying info for one achievement group +class CAchievementsPageGroupPanel : public vgui::EditablePanel +{ + DECLARE_CLASS_SIMPLE( CAchievementsPageGroupPanel, vgui::EditablePanel ); + +public: + CAchievementsPageGroupPanel( vgui::PanelListPanel *parent, CAchievementsPage *owner, const char* name, int iListItemID ); + ~CAchievementsPageGroupPanel(); + + void SetGroupInfo ( const wchar_t* name, int firstAchievementID, int lastAchievementID ); + void UpdateAchievementInfo( vgui::IScheme *pScheme ); + virtual void ApplySchemeSettings( vgui::IScheme *pScheme ); + + int GetFirstAchievementID() { return m_iFirstAchievementID; } + int GetLastAchievementID() { return m_iLastAchievementID; } + + vgui::PanelListPanel* GetParent() { return m_pParent; } + CAchievementsPage* GetOwner() { return m_pOwner; } + + void SetGroupActive(bool active) { m_bActiveButton = active; } + bool IsGroupActive() { return m_bActiveButton; } + +private: + void PreloadResourceFile( void ); + + vgui::PanelListPanel *m_pParent; + CAchievementsPage *m_pOwner; + + vgui::Label *m_pAchievementGroupLabel; + vgui::Label *m_pPercentageText; + + CGroupButton *m_pGroupButton; + + vgui::ImagePanel *m_pGroupIcon; + + vgui::ImagePanel *m_pPercentageBarBackground; + vgui::ImagePanel *m_pPercentageBar; + + vgui::IScheme *m_pSchemeSettings; + + bool m_bActiveButton; + + CPanelAnimationVar( Color, m_clrProgressBar, "ProgressBarColor", "140 140 140 255" ); + + int m_iFirstAchievementID; + int m_iLastAchievementID; + + wchar_t *m_pGroupName; +}; + + + +#endif // CSACHIEVEMENTSPAGE_H diff --git a/game/client/cstrike/VGUI/backgroundpanel.cpp b/game/client/cstrike/VGUI/backgroundpanel.cpp new file mode 100644 index 00000000..c875217e --- /dev/null +++ b/game/client/cstrike/VGUI/backgroundpanel.cpp @@ -0,0 +1,676 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "cbase.h" +#include "backgroundpanel.h" + +#include +#include +#include +#include +#include +#include "vgui_controls/BuildGroup.h" +#include "vgui_controls/BitmapImagePanel.h" + +using namespace vgui; + +#define DEBUG_WINDOW_RESIZING 0 +#define DEBUG_WINDOW_REPOSITIONING 0 + +//----------------------------------------------------------------------------- +const int NumSegments = 7; +static int coord[NumSegments+1] = { + 0, + 1, + 2, + 3, + 4, + 6, + 9, + 10 +}; + +//----------------------------------------------------------------------------- +void DrawRoundedBackground( Color bgColor, int wide, int tall ) +{ + int x1, x2, y1, y2; + surface()->DrawSetColor(bgColor); + surface()->DrawSetTextColor(bgColor); + + int i; + + // top-left corner -------------------------------------------------------- + int xDir = 1; + int yDir = -1; + int xIndex = 0; + int yIndex = NumSegments - 1; + int xMult = 1; + int yMult = 1; + int x = 0; + int y = 0; + for ( i=0; iDrawFilledRect( x1, y1, x2, y2 ); + + xIndex += xDir; + yIndex += yDir; + } + + // top-right corner ------------------------------------------------------- + xDir = 1; + yDir = -1; + xIndex = 0; + yIndex = NumSegments - 1; + x = wide; + y = 0; + xMult = -1; + yMult = 1; + for ( i=0; iDrawFilledRect( x1, y1, x2, y2 ); + xIndex += xDir; + yIndex += yDir; + } + + // bottom-right corner ---------------------------------------------------- + xDir = 1; + yDir = -1; + xIndex = 0; + yIndex = NumSegments - 1; + x = wide; + y = tall; + xMult = -1; + yMult = -1; + for ( i=0; iDrawFilledRect( x1, y1, x2, y2 ); + xIndex += xDir; + yIndex += yDir; + } + + // bottom-left corner ----------------------------------------------------- + xDir = 1; + yDir = -1; + xIndex = 0; + yIndex = NumSegments - 1; + x = 0; + y = tall; + xMult = 1; + yMult = -1; + for ( i=0; iDrawFilledRect( x1, y1, x2, y2 ); + xIndex += xDir; + yIndex += yDir; + } + + // paint between top left and bottom left --------------------------------- + x1 = 0; + x2 = coord[NumSegments]; + y1 = coord[NumSegments]; + y2 = tall - coord[NumSegments]; + surface()->DrawFilledRect( x1, y1, x2, y2 ); + + // paint between left and right ------------------------------------------- + x1 = coord[NumSegments]; + x2 = wide - coord[NumSegments]; + y1 = 0; + y2 = tall; + surface()->DrawFilledRect( x1, y1, x2, y2 ); + + // paint between top right and bottom right ------------------------------- + x1 = wide - coord[NumSegments]; + x2 = wide; + y1 = coord[NumSegments]; + y2 = tall - coord[NumSegments]; + surface()->DrawFilledRect( x1, y1, x2, y2 ); +} + +//----------------------------------------------------------------------------- +void DrawRoundedBorder( Color borderColor, int wide, int tall ) +{ + int x1, x2, y1, y2; + surface()->DrawSetColor(borderColor); + surface()->DrawSetTextColor(borderColor); + + int i; + + // top-left corner -------------------------------------------------------- + int xDir = 1; + int yDir = -1; + int xIndex = 0; + int yIndex = NumSegments - 1; + int xMult = 1; + int yMult = 1; + int x = 0; + int y = 0; + for ( i=0; iDrawFilledRect( x1, y1, x2, y2 ); + + xIndex += xDir; + yIndex += yDir; + } + + // top-right corner ------------------------------------------------------- + xDir = 1; + yDir = -1; + xIndex = 0; + yIndex = NumSegments - 1; + x = wide; + y = 0; + xMult = -1; + yMult = 1; + for ( i=0; iDrawFilledRect( x1, y1, x2, y2 ); + xIndex += xDir; + yIndex += yDir; + } + + // bottom-right corner ---------------------------------------------------- + xDir = 1; + yDir = -1; + xIndex = 0; + yIndex = NumSegments - 1; + x = wide; + y = tall; + xMult = -1; + yMult = -1; + for ( i=0; iDrawFilledRect( x1, y1, x2, y2 ); + xIndex += xDir; + yIndex += yDir; + } + + // bottom-left corner ----------------------------------------------------- + xDir = 1; + yDir = -1; + xIndex = 0; + yIndex = NumSegments - 1; + x = 0; + y = tall; + xMult = 1; + yMult = -1; + for ( i=0; iDrawFilledRect( x1, y1, x2, y2 ); + xIndex += xDir; + yIndex += yDir; + } + + // top -------------------------------------------------------------------- + x1 = coord[NumSegments]; + x2 = wide - coord[NumSegments]; + y1 = 0; + y2 = 1; + surface()->DrawFilledRect( x1, y1, x2, y2 ); + + // bottom ----------------------------------------------------------------- + x1 = coord[NumSegments]; + x2 = wide - coord[NumSegments]; + y1 = tall - 1; + y2 = tall; + surface()->DrawFilledRect( x1, y1, x2, y2 ); + + // left ------------------------------------------------------------------- + x1 = 0; + x2 = 1; + y1 = coord[NumSegments]; + y2 = tall - coord[NumSegments]; + surface()->DrawFilledRect( x1, y1, x2, y2 ); + + // right ------------------------------------------------------------------ + x1 = wide - 1; + x2 = wide; + y1 = coord[NumSegments]; + y2 = tall - coord[NumSegments]; + surface()->DrawFilledRect( x1, y1, x2, y2 ); +} + +//----------------------------------------------------------------------------- +class CaptionLabel : public Label +{ +public: + CaptionLabel(Panel *parent, const char *panelName, const char *text) : Label(parent, panelName, text) + { + } + + virtual void ApplySchemeSettings( vgui::IScheme *pScheme ) + { + Label::ApplySchemeSettings( pScheme ); + SetFont( pScheme->GetFont( "MenuTitle", IsProportional() ) ); + } +}; + +//----------------------------------------------------------------------------- +// Purpose: transform a normalized value into one that is scaled based the minimum +// of the horizontal and vertical ratios +//----------------------------------------------------------------------------- +static int GetAlternateProportionalValueFromNormal(int normalizedValue) +{ + int wide, tall; + GetHudSize( wide, tall ); + int proH, proW; + surface()->GetProportionalBase( proW, proH ); + double scaleH = (double)tall / (double)proH; + double scaleW = (double)wide / (double)proW; + double scale = (scaleW < scaleH) ? scaleW : scaleH; + + return (int)( normalizedValue * scale ); +} + +//----------------------------------------------------------------------------- +// Purpose: transform a standard scaled value into one that is scaled based the minimum +// of the horizontal and vertical ratios +//----------------------------------------------------------------------------- +int GetAlternateProportionalValueFromScaled( HScheme hScheme, int scaledValue) +{ + return GetAlternateProportionalValueFromNormal( scheme()->GetProportionalNormalizedValueEx( hScheme, scaledValue ) ); +} + +//----------------------------------------------------------------------------- +// Purpose: moves and resizes a single control +//----------------------------------------------------------------------------- +static void RepositionControl( Panel *pPanel ) +{ + int x, y, w, h; + pPanel->GetBounds(x, y, w, h); + +#if DEBUG_WINDOW_RESIZING + int x1, y1, w1, h1; + pPanel->GetBounds(x1, y1, w1, h1); + int x2, y2, w2, h2; + x2 = scheme()->GetProportionalNormalizedValueEx( pPanel->GetScheme(), x1 ); + y2 = scheme()->GetProportionalNormalizedValueEx( pPanel->GetScheme(), y1 ); + w2 = scheme()->GetProportionalNormalizedValueEx( pPanel->GetScheme(), w1 ); + h2 = scheme()->GetProportionalNormalizedValueEx( pPanel->GetScheme(), h1 ); +#endif + + x = GetAlternateProportionalValueFromScaled( pPanel->GetScheme(), x ); + y = GetAlternateProportionalValueFromScaled( pPanel->GetScheme(), y ); + w = GetAlternateProportionalValueFromScaled( pPanel->GetScheme(), w ); + h = GetAlternateProportionalValueFromScaled( pPanel->GetScheme(), h ); + + pPanel->SetBounds(x, y, w, h); + +#if DEBUG_WINDOW_RESIZING + DevMsg( "Resizing '%s' from (%d,%d) %dx%d to (%d,%d) %dx%d -- initially was (%d,%d) %dx%d\n", + pPanel->GetName(), x1, y1, w1, h1, x, y, w, h, x2, y2, w2, h2 ); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: Sets colors etc for background image panels +//----------------------------------------------------------------------------- +void ApplyBackgroundSchemeSettings( EditablePanel *pWindow, vgui::IScheme *pScheme ) +{ + Color bgColor = Color( 255, 255, 255, pScheme->GetColor( "BgColor", Color( 0, 0, 0, 0 ) )[3] ); + Color fgColor = pScheme->GetColor( "FgColor", Color( 0, 0, 0, 0 ) ); + + if ( !pWindow ) + return; + + CBitmapImagePanel *pBitmapPanel; + + // corners -------------------------------------------- + pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "TopLeftPanel" )); + if ( pBitmapPanel ) + { + pBitmapPanel->setImageColor( bgColor ); + } + pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "TopRightPanel" )); + if ( pBitmapPanel ) + { + pBitmapPanel->setImageColor( bgColor ); + } + pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "BottomLeftPanel" )); + if ( pBitmapPanel ) + { + pBitmapPanel->setImageColor( bgColor ); + } + pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "BottomRightPanel" )); + if ( pBitmapPanel ) + { + pBitmapPanel->setImageColor( bgColor ); + } + + // background ----------------------------------------- + pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "TopSolid" )); + if ( pBitmapPanel ) + { + pBitmapPanel->setImageColor( bgColor ); + } + pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "UpperMiddleSolid" )); + if ( pBitmapPanel ) + { + pBitmapPanel->setImageColor( bgColor ); + } + pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "LowerMiddleSolid" )); + if ( pBitmapPanel ) + { + pBitmapPanel->setImageColor( bgColor ); + } + pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "BottomSolid" )); + if ( pBitmapPanel ) + { + pBitmapPanel->setImageColor( bgColor ); + } + + // Logo ----------------------------------------------- + pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "ExclamationPanel" )); + if ( pBitmapPanel ) + { + pBitmapPanel->setImageColor( fgColor ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Re-aligns background image panels so they are touching. +//----------------------------------------------------------------------------- +static void FixupBackgroundPanels( EditablePanel *pWindow, int offsetX, int offsetY ) +{ + if ( !pWindow ) + return; + + int screenWide, screenTall; + pWindow->GetSize( screenWide, screenTall ); + + int inset = GetAlternateProportionalValueFromNormal( 20 ); + int cornerSize = GetAlternateProportionalValueFromNormal( 10 ); + + int titleHeight = GetAlternateProportionalValueFromNormal( 42 ); + int mainHeight = GetAlternateProportionalValueFromNormal( 376 ); + + int logoSize = titleHeight; + + int captionInset = GetAlternateProportionalValueFromNormal( 76 ); + + Panel *pPanel; + + // corners -------------------------------------------- + pPanel = pWindow->FindChildByName( "TopLeftPanel" ); + if ( pPanel ) + { + pPanel->SetZPos( -20 ); + pPanel->SetBounds( offsetX + inset, offsetY + inset, cornerSize, cornerSize ); + } + + pPanel = pWindow->FindChildByName( "TopRightPanel" ); + if ( pPanel ) + { + pPanel->SetZPos( -20 ); + pPanel->SetBounds( screenWide - offsetX - inset - cornerSize, offsetY + inset, cornerSize, cornerSize ); + } + + pPanel = pWindow->FindChildByName( "BottomLeftPanel" ); + if ( pPanel ) + { + pPanel->SetZPos( -20 ); + pPanel->SetBounds( offsetX + inset, screenTall - offsetY - inset - cornerSize, cornerSize, cornerSize ); + } + + pPanel = pWindow->FindChildByName( "BottomRightPanel" ); + if ( pPanel ) + { + pPanel->SetZPos( -20 ); + pPanel->SetBounds( screenWide - offsetX - inset - cornerSize, screenTall - offsetY - inset - cornerSize, cornerSize, cornerSize ); + } + + // background ----------------------------------------- + pPanel = pWindow->FindChildByName( "TopSolid" ); + if ( pPanel ) + { + pPanel->SetZPos( -20 ); + pPanel->SetBounds( offsetX + inset + cornerSize, offsetY + inset, screenWide - 2*offsetX - 2*inset - 2*cornerSize, cornerSize ); + } + + pPanel = pWindow->FindChildByName( "UpperMiddleSolid" ); + if ( pPanel ) + { + pPanel->SetZPos( -20 ); + pPanel->SetBounds( offsetX + inset, offsetY + inset + cornerSize, screenWide - 2*offsetX - 2*inset, titleHeight ); + } + + pPanel = pWindow->FindChildByName( "LowerMiddleSolid" ); + if ( pPanel ) + { + pPanel->SetZPos( -20 ); + pPanel->SetBounds( offsetX + inset + cornerSize, screenTall - offsetY - inset - cornerSize, screenWide - 2*offsetX - 2*inset - 2*cornerSize, cornerSize ); + } + + pPanel = pWindow->FindChildByName( "BottomSolid" ); + if ( pPanel ) + { + pPanel->SetZPos( -20 ); + pPanel->SetBounds( offsetX + inset, screenTall - offsetY - inset - cornerSize - mainHeight, screenWide - 2*offsetX - 2*inset, mainHeight ); + } + + // transparent border --------------------------------- + pPanel = pWindow->FindChildByName( "TopClear" ); + if ( pPanel ) + { + pPanel->SetZPos( -20 ); + pPanel->SetBounds( 0, 0, screenWide, offsetY + inset ); + } + + pPanel = pWindow->FindChildByName( "BottomClear" ); + if ( pPanel ) + { + pPanel->SetZPos( -20 ); + pPanel->SetBounds( 0, screenTall - offsetY - inset, screenWide, offsetY + inset ); + } + + pPanel = pWindow->FindChildByName( "LeftClear" ); + if ( pPanel ) + { + pPanel->SetZPos( -20 ); + pPanel->SetBounds( 0, offsetY + inset, offsetX + inset, screenTall - 2*offsetY - 2*inset ); + } + + pPanel = pWindow->FindChildByName( "RightClear" ); + if ( pPanel ) + { + pPanel->SetZPos( -20 ); + pPanel->SetBounds( screenWide - offsetX - inset, offsetY + inset, offsetX + inset, screenTall - 2*offsetY - 2*inset ); + } + + // Logo ----------------------------------------------- + int logoInset = (cornerSize + titleHeight - logoSize)/2; + pPanel = pWindow->FindChildByName( "ExclamationPanel" ); + if ( pPanel ) + { + pPanel->SetZPos( -19 ); // higher than the background + pPanel->SetBounds( offsetX + inset + logoInset, offsetY + inset + logoInset, logoSize, logoSize ); + } + + // Title caption -------------------------------------- + pPanel = dynamic_cast< Label * >(pWindow->FindChildByName( "CaptionLabel" )); + if ( pPanel ) + { + pPanel->SetZPos( -19 ); // higher than the background + pPanel->SetBounds( offsetX + captionInset/*inset + 2*logoInset + logoSize*/, offsetY + inset + logoInset, screenWide, logoSize ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Creates background image panels +//----------------------------------------------------------------------------- +void CreateBackground( EditablePanel *pWindow ) +{ + // corners -------------------------------------------- + new CBitmapImagePanel( pWindow, "TopLeftPanel", "gfx/vgui/round_corner_nw" ); + new CBitmapImagePanel( pWindow, "TopRightPanel", "gfx/vgui/round_corner_ne" ); + new CBitmapImagePanel( pWindow, "BottomLeftPanel", "gfx/vgui/round_corner_sw" ); + new CBitmapImagePanel( pWindow, "BottomRightPanel", "gfx/vgui/round_corner_se" ); + + // background ----------------------------------------- + new CBitmapImagePanel( pWindow, "TopSolid", "gfx/vgui/solid_background" ); + new CBitmapImagePanel( pWindow, "UpperMiddleSolid", "gfx/vgui/solid_background" ); + new CBitmapImagePanel( pWindow, "LowerMiddleSolid", "gfx/vgui/solid_background" ); + new CBitmapImagePanel( pWindow, "BottomSolid", "gfx/vgui/solid_background" ); + + // transparent border --------------------------------- + new CBitmapImagePanel( pWindow, "TopClear", "gfx/vgui/trans_background" ); + new CBitmapImagePanel( pWindow, "BottomClear", "gfx/vgui/trans_background" ); + new CBitmapImagePanel( pWindow, "LeftClear", "gfx/vgui/trans_background" ); + new CBitmapImagePanel( pWindow, "RightClear", "gfx/vgui/trans_background" ); + + // Logo ----------------------------------------------- + new CBitmapImagePanel( pWindow, "ExclamationPanel", "gfx/vgui/CS_logo" ); + + // Title caption -------------------------------------- + Panel *pPanel = dynamic_cast< Label * >(pWindow->FindChildByName( "CaptionLabel" )); + if ( !pPanel ) + new CaptionLabel( pWindow, "CaptionLabel", "" ); +} + +void ResizeWindowControls( EditablePanel *pWindow, int tall, int wide, int offsetX, int offsetY ) +{ + if (!pWindow || !pWindow->GetBuildGroup() || !pWindow->GetBuildGroup()->GetPanelList()) + return; + + CUtlVector *panelList = pWindow->GetBuildGroup()->GetPanelList(); + CUtlVector resizedPanels; + CUtlVector movedPanels; + + // Resize to account for 1.25 aspect ratio (1280x1024) screens + { + for ( int i = 0; i < panelList->Size(); ++i ) + { + PHandle handle = (*panelList)[i]; + + Panel *panel = handle.Get(); + + bool found = false; + for ( int j = 0; j < resizedPanels.Size(); ++j ) + { + if (panel == resizedPanels[j]) + found = true; + } + + if (!panel || found) + { + continue; + } + + resizedPanels.AddToTail( panel ); // don't move a panel more than once + + if ( panel != pWindow ) + { + RepositionControl( panel ); + } + } + } + + // and now re-center them. Woohoo! + for ( int i = 0; i < panelList->Size(); ++i ) + { + PHandle handle = (*panelList)[i]; + + Panel *panel = handle.Get(); + + bool found = false; + for ( int j = 0; j < movedPanels.Size(); ++j ) + { + if (panel == movedPanels[j]) + found = true; + } + + if (!panel || found) + { + continue; + } + + movedPanels.AddToTail( panel ); // don't move a panel more than once + + if ( panel != pWindow ) + { + int x, y; + + panel->GetPos( x, y ); + panel->SetPos( x + offsetX, y + offsetY ); + +#if DEBUG_WINDOW_REPOSITIONING + DevMsg( "Repositioning '%s' from (%d,%d) to (%d,%d) -- a distance of (%d,%d)\n", + panel->GetName(), x, y, x + offsetX, y + offsetY, offsetX, offsetY ); +#endif + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Resizes windows to fit completely on-screen (for 1280x1024), and +// centers them on the screen. Sub-controls are also resized and moved. +//----------------------------------------------------------------------------- +void LayoutBackgroundPanel( EditablePanel *pWindow ) +{ + if ( !pWindow ) + return; + + int screenW, screenH; + GetHudSize( screenW, screenH ); + + int wide, tall; + pWindow->GetSize( wide, tall ); + + int offsetX = 0; + int offsetY = 0; + + // Slide everything over to the center + pWindow->SetBounds( 0, 0, screenW, screenH ); + + if ( wide != screenW || tall != screenH ) + { + wide = GetAlternateProportionalValueFromScaled( pWindow->GetScheme(), wide); + tall = GetAlternateProportionalValueFromScaled( pWindow->GetScheme(), tall); + + offsetX = (screenW - wide)/2; + offsetY = (screenH - tall)/2; + + ResizeWindowControls( pWindow, tall, wide, offsetX, offsetY ); + } + + // now that the panels are moved/resized, look for some bg panels, and re-align them + FixupBackgroundPanels( pWindow, offsetX, offsetY ); +} + +//----------------------------------------------------------------------------- + diff --git a/game/client/cstrike/VGUI/backgroundpanel.h b/game/client/cstrike/VGUI/backgroundpanel.h new file mode 100644 index 00000000..5edf22e8 --- /dev/null +++ b/game/client/cstrike/VGUI/backgroundpanel.h @@ -0,0 +1,53 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef CSBACKGROUND_H +#define CSBACKGROUND_H + +#include +#include + +//----------------------------------------------------------------------------- +// Purpose: Creates background image panels +//----------------------------------------------------------------------------- +void CreateBackground( vgui::EditablePanel *pWindow ); + +//----------------------------------------------------------------------------- +// Purpose: Resizes windows to fit completely on-screen (for 1280x1024), and +// centers them on the screen. Sub-controls are also resized and moved. +//----------------------------------------------------------------------------- +void LayoutBackgroundPanel( vgui::EditablePanel *pWindow ); + +//----------------------------------------------------------------------------- +// Purpose: Sets colors etc for background image panels +//----------------------------------------------------------------------------- +void ApplyBackgroundSchemeSettings( vgui::EditablePanel *pWindow, vgui::IScheme *pScheme ); + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void ResizeWindowControls( vgui::EditablePanel *pWindow, int tall, int wide, int offsetX, int offsetY ); + +//----------------------------------------------------------------------------- +// Purpose: transform a standard scaled value into one that is scaled based the minimum +// of the horizontal and vertical ratios +//----------------------------------------------------------------------------- +int GetAlternateProportionalValueFromScaled( vgui::HScheme scheme, int scaledValue ); + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void DrawRoundedBackground( Color bgColor, int wide, int tall ); + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void DrawRoundedBorder( Color borderColor, int wide, int tall ); + +//----------------------------------------------------------------------------- + +#endif // CSBACKGROUND_H diff --git a/game/client/cstrike/VGUI/base_stats_page.cpp b/game/client/cstrike/VGUI/base_stats_page.cpp new file mode 100644 index 00000000..ab27865b --- /dev/null +++ b/game/client/cstrike/VGUI/base_stats_page.cpp @@ -0,0 +1,359 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// +//=============================================================================// + +#include "cbase.h" +#include "tier3/tier3.h" +#include "vgui/ILocalize.h" +#include "lifetime_stats_page.h" +#include +#include "cs_client_gamestats.h" +#include "filesystem.h" +#include "cs_weapon_parse.h" +#include "buy_presets/buy_presets.h" +#include "../vgui_controls/ScrollBar.h" +#include "stat_card.h" + +using namespace vgui; + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +KeyValues *g_pPreloadedCSBaseStatGroupLayout = NULL; + +//----------------------------------------------------------------------------- +// Purpose: creates child panels, passes down name to pick up any settings from res files. +//----------------------------------------------------------------------------- +CBaseStatsPage::CBaseStatsPage(vgui::Panel *parent, const char *name) : BaseClass(parent, "CSBaseStatsDialog") +{ + vgui::IScheme *pScheme = scheme()->GetIScheme( GetScheme() ); + + m_listItemFont = pScheme->GetFont( "StatsPageText", IsProportional() ); + + m_statsList = new SectionedListPanel( this, "StatsList" ); + m_statsList->SetClickable(false); + m_statsList->SetDrawHeaders(false); + + m_bottomBar = new ImagePanel(this, "BottomBar"); + + m_pGroupsList = new vgui::PanelListPanel( this, "listpanel_groups" ); + m_pGroupsList->SetFirstColumnWidth( 0 ); + + SetBounds(0, 0, 900, 780); + SetMinimumSize( 256, 780 ); + + SetBgColor(GetSchemeColor("ListPanel.BgColor", GetBgColor(), pScheme)); + + m_pStatCard = new StatCard(this, "ignored"); + + ListenForGameEvent( "player_stats_updated" ); + + m_bStatsDirty = true; +} + +CBaseStatsPage::~CBaseStatsPage() +{ + delete m_statsList; +} + + +void CBaseStatsPage::MoveToFront() +{ + UpdateStatsData(); + m_pStatCard->UpdateInfo(); +} + +void CBaseStatsPage::UpdateStatsData() +{ + // Hide the group list scrollbar + if (m_pGroupsList->GetScrollbar()) + { + m_pGroupsList->GetScrollbar()->SetWide(0); + } + + UpdateGroupPanels(); + RepopulateStats(); + + m_bStatsDirty = false; +} + +//----------------------------------------------------------------------------- +// Purpose: Loads settings from statsdialog.res in hl2/resource/ui/ +//----------------------------------------------------------------------------- +void CBaseStatsPage::ApplySchemeSettings( vgui::IScheme *pScheme ) +{ + BaseClass::ApplySchemeSettings( pScheme ); + LoadControlSettings("resource/ui/CSBaseStatsDialog.res"); + + m_statsList->SetClickable(false); + m_statsList->SetDrawHeaders(false); + + m_statsList->SetVerticalScrollbar(true); + + SetBgColor(Color(86,86,86,255)); + + //Remove any pre-existing sections and add then fresh (this can happen on a resolution change) + m_statsList->RemoveAllSections(); + + m_statsList->AddSection( 0, "Players"); + + m_statsList->SetFontSection(0, m_listItemFont); + + m_pGroupsList->SetBgColor(Color(86,86,86,255)); + m_statsList->SetBgColor(Color(52,52,52,255)); +} + +void CBaseStatsPage::SetActiveStatGroup (CBaseStatGroupPanel* groupPanel) +{ + for (int i = 0; i < m_pGroupsList->GetItemCount(); i++) + { + CBaseStatGroupPanel *pPanel = (CBaseStatGroupPanel*)m_pGroupsList->GetItemPanel(i); + if ( pPanel ) + { + if ( pPanel != groupPanel ) + { + pPanel->SetGroupActive( false ); + } + else + { + pPanel->SetGroupActive( true ); + } + } + } +} + +void CBaseStatsPage::UpdateGroupPanels() +{ + int iGroupCount = m_pGroupsList->GetItemCount(); + vgui::IScheme *pGroupScheme = scheme()->GetIScheme( GetScheme() ); + + for ( int i = 0; i < iGroupCount; i++ ) + { + CBaseStatGroupPanel *pPanel = (CBaseStatGroupPanel*)m_pGroupsList->GetItemPanel(i); + if ( pPanel ) + { + pPanel->Update( pGroupScheme ); + } + } +} + + + +void CBaseStatsPage::OnSizeChanged(int newWide, int newTall) +{ + BaseClass::OnSizeChanged(newWide, newTall); + + if (m_statsList) + { + int labelX, labelY, listX, listY, listWide, listTall; + m_statsList->GetBounds(listX, listY, listWide, listTall); + + if (m_bottomBar) + { + m_bottomBar->GetPos(labelX, labelY); + m_bottomBar->SetPos(labelX, listY + listTall); + } + } +} + +const wchar_t* CBaseStatsPage::TranslateWeaponKillIDToAlias( int statKillID ) +{ + CSWeaponID weaponIDIndex = WEAPON_MAX; + for ( int i = 0; WeaponName_StatId_Table[i].killStatId != CSSTAT_UNDEFINED; ++i ) + { + if( WeaponName_StatId_Table[i].killStatId == statKillID ) + { + weaponIDIndex = WeaponName_StatId_Table[i].weaponId; + break; + } + } + + if (weaponIDIndex == WEAPON_MAX) + { + return NULL; + } + else + { + return WeaponIDToDisplayName(weaponIDIndex); + } +} + +const wchar_t* CBaseStatsPage::LocalizeTagOrUseDefault( const char* tag, const wchar_t* def ) +{ + const wchar_t* result = g_pVGuiLocalize->Find( tag ); + + if ( !result ) + result = def ? def : L"\0"; + + return result; +} + +CBaseStatGroupPanel* CBaseStatsPage::AddGroup( const wchar_t* name, const char* title_tag, const wchar_t* def ) +{ + CBaseStatGroupPanel* newGroup = new CBaseStatGroupPanel( m_pGroupsList, this, "StatGroupPanel", 0 ); + newGroup->SetGroupInfo( name, LocalizeTagOrUseDefault( title_tag, def ) ); + newGroup->SetGroupActive( false ); + + m_pGroupsList->AddItem( NULL, newGroup ); + + return newGroup; +} + +void CBaseStatsPage::FireGameEvent( IGameEvent * event ) +{ + const char *type = event->GetName(); + + if ( 0 == Q_strcmp( type, "player_stats_updated" ) ) + m_bStatsDirty = true; +} + +void CBaseStatsPage::OnThink() +{ + if ( m_bStatsDirty ) + UpdateStatsData(); +} + +CBaseStatGroupPanel::CBaseStatGroupPanel( vgui::PanelListPanel *parent, CBaseStatsPage *owner, const char* name, int iListItemID ) : BaseClass( parent, name ) +{ + m_pParent = parent; + m_pOwner = owner; + m_pSchemeSettings = NULL; + + m_pGroupIcon = SETUP_PANEL(new vgui::ImagePanel( this, "GroupIcon" )); + m_pBaseStatGroupLabel = new vgui::Label( this, "GroupName", "name" ); + m_pGroupButton = new CBaseStatGroupButton(this, "GroupButton", "" ); + m_pGroupButton->SetPos( 0, 0 ); + m_pGroupButton->SetZPos( 20 ); + m_pGroupButton->SetWide( 256 ); + m_pGroupButton->SetTall( 64 ); + SetMouseInputEnabled( true ); + parent->SetMouseInputEnabled( true ); + + m_bActiveButton = false; +} + +CBaseStatGroupPanel::~CBaseStatGroupPanel() +{ + delete m_pBaseStatGroupLabel; + delete m_pGroupIcon; +} + + +//----------------------------------------------------------------------------- +// Purpose: Sets the parameter pIconPanel to display the specified achievement's icon file. +//----------------------------------------------------------------------------- +bool CBaseStatGroupPanel::LoadIcon( const char* pFilename) +{ + char imagePath[_MAX_PATH]; + Q_strncpy( imagePath, "achievements\\", sizeof(imagePath) ); + Q_strncat( imagePath, pFilename, sizeof(imagePath), COPY_ALL_CHARACTERS ); + Q_strncat( imagePath, ".vtf", sizeof(imagePath), COPY_ALL_CHARACTERS ); + + char checkFile[_MAX_PATH]; + Q_snprintf( checkFile, sizeof(checkFile), "materials\\vgui\\%s", imagePath ); + if ( !g_pFullFileSystem->FileExists( checkFile ) ) + { + Q_snprintf( imagePath, sizeof(imagePath), "hud\\icon_locked.vtf" ); + } + + m_pGroupIcon->SetShouldScaleImage( true ); + m_pGroupIcon->SetImage( imagePath ); + m_pGroupIcon->SetVisible( true ); + + return m_pGroupIcon->IsVisible(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Loads settings from hl2/resource/ui/achievementitem.res +// Sets display info for this achievement item. +//----------------------------------------------------------------------------- +void CBaseStatGroupPanel::ApplySchemeSettings( vgui::IScheme* pScheme ) +{ + if ( !g_pPreloadedCSBaseStatGroupLayout ) + { + PreloadResourceFile(); + } + + LoadControlSettings( "", NULL, g_pPreloadedCSBaseStatGroupLayout ); + + m_pSchemeSettings = pScheme; + + BaseClass::ApplySchemeSettings( pScheme ); +} + +void CBaseStatGroupPanel::Update( vgui::IScheme* pScheme ) +{ + if ( m_pSchemeSettings ) + { + + // Set group name text + m_pBaseStatGroupLabel->SetText( m_pGroupTitle ); + m_pBaseStatGroupLabel->SetFgColor(Color(157, 194, 80, 255)); + + if ( !m_bActiveButton ) + { + LoadIcon( "achievement-btn-up" ); + } + else + { + LoadIcon( "achievement-btn-select" ); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseStatGroupPanel::PreloadResourceFile( void ) +{ + const char *controlResourceName = "resource/ui/StatGroup.res"; + + g_pPreloadedCSBaseStatGroupLayout = new KeyValues(controlResourceName); + g_pPreloadedCSBaseStatGroupLayout->LoadFromFile(g_pFullFileSystem, controlResourceName); +} + + + +//----------------------------------------------------------------------------- +// Purpose: Assigns a name and achievement id bounds for an achievement group. +//----------------------------------------------------------------------------- +void CBaseStatGroupPanel::SetGroupInfo ( const wchar_t* name, const wchar_t* title) +{ + // Store away the group name + short _textLen = (short)wcslen(name) + 1; + m_pGroupName = new wchar_t[_textLen]; + Q_memcpy( m_pGroupName, name, _textLen * sizeof(wchar_t) ); + + _textLen = (short)wcslen(title) + 1; + m_pGroupTitle = new wchar_t[_textLen]; + Q_memcpy( m_pGroupTitle, title, _textLen * sizeof(wchar_t) ); +} + + +CBaseStatGroupButton::CBaseStatGroupButton( vgui::Panel *pParent, const char *pName, const char *pText ) : +BaseClass( pParent, pName, pText ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: Handle the case where the user presses an achievement group button. +//----------------------------------------------------------------------------- +void CBaseStatGroupButton::DoClick( void ) +{ + // Process when a group button is hit + CBaseStatGroupPanel* pParent = static_cast(GetParent()); + + if (pParent) + { + CBaseStatsPage* pBaseStatsPage = static_cast(pParent->GetOwner()); + + if (pBaseStatsPage) + { + pBaseStatsPage->SetActiveStatGroup( pParent ); + pBaseStatsPage->UpdateStatsData(); + } + } +} diff --git a/game/client/cstrike/VGUI/base_stats_page.h b/game/client/cstrike/VGUI/base_stats_page.h new file mode 100644 index 00000000..e22ec323 --- /dev/null +++ b/game/client/cstrike/VGUI/base_stats_page.h @@ -0,0 +1,135 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef CSBASESTATSPAGE_H +#define CSBASESTATSPAGE_H +#ifdef _WIN32 +#pragma once +#endif + +#include "vgui_controls/PanelListPanel.h" +#include "vgui_controls/Label.h" +#include "tier1/KeyValues.h" +#include "vgui_controls/PropertyPage.h" +#include "vgui_controls/Button.h" +#include "vgui_controls/ImagePanel.h" +#include "GameEventListener.h" + +struct PlayerStatData_t; +class IScheme; +class CBaseStatGroupPanel; +class StatCard; +struct StatsCollection_t; +struct RoundStatsDirectAverage_t; + +class CBaseStatsPage : public vgui::PropertyPage, public CGameEventListener +{ + DECLARE_CLASS_SIMPLE ( CBaseStatsPage, vgui::PropertyPage ); + +public: + CBaseStatsPage( vgui::Panel *parent, const char *name ); + + ~CBaseStatsPage(); + + virtual void ApplySchemeSettings( vgui::IScheme *pScheme ); + virtual void MoveToFront(); + virtual void OnSizeChanged(int wide, int tall); + virtual void OnThink(); + + void UpdateStatsData(); + void SetActiveStatGroup (CBaseStatGroupPanel* groupPanel); + + virtual void FireGameEvent( IGameEvent * event ); + +protected: + + void UpdateGroupPanels(); + CBaseStatGroupPanel* AddGroup( const wchar_t* name, const char* title_tag, const wchar_t* def = NULL ); + const wchar_t* TranslateWeaponKillIDToAlias( int statKillID ); + const wchar_t* LocalizeTagOrUseDefault( const char* tag, const wchar_t* def = NULL ); + + virtual void RepopulateStats() = 0; + + vgui::SectionedListPanel *m_statsList; + vgui::HFont m_listItemFont; + +private: + + vgui::PanelListPanel *m_pGroupsList; + vgui::ImagePanel* m_bottomBar; + StatCard* m_pStatCard; + bool m_bStatsDirty; +}; + + + + +class CBaseStatGroupButton : public vgui::Button +{ + DECLARE_CLASS_SIMPLE( CBaseStatGroupButton, vgui::Button ); + +public: + + CBaseStatGroupButton( vgui::Panel *pParent, const char *pName, const char *pText ); + + virtual void DoClick( void ); +}; + + + + + +class CBaseStatGroupPanel : public vgui::EditablePanel +{ + DECLARE_CLASS_SIMPLE( CBaseStatGroupPanel, vgui::EditablePanel ); + +public: + CBaseStatGroupPanel( vgui::PanelListPanel *parent, CBaseStatsPage *owner, const char* name, int iListItemID ); + ~CBaseStatGroupPanel(); + + void SetGroupInfo ( const wchar_t* name, const wchar_t* title); + + virtual void ApplySchemeSettings( vgui::IScheme *pScheme ); + + void Update( vgui::IScheme* pScheme ); + + vgui::PanelListPanel* GetParent() { return m_pParent; } + CBaseStatsPage* GetOwner() { return m_pOwner; } + + void SetGroupActive(bool active) { m_bActiveButton = active; } + bool IsGroupActive() { return m_bActiveButton; } + +protected: + + // Loads an icon into a specified image panel, or turns the panel off if no icon was found. + bool LoadIcon( const char* pFilename); + +private: + void PreloadResourceFile( void ); + + vgui::PanelListPanel *m_pParent; + CBaseStatsPage *m_pOwner; + + vgui::Label *m_pBaseStatGroupLabel; + + CBaseStatGroupButton *m_pGroupButton; + + vgui::ImagePanel *m_pGroupIcon; + + vgui::IScheme *m_pSchemeSettings; + + bool m_bActiveButton; + + wchar_t *m_pGroupName; + wchar_t *m_pGroupTitle; +}; + + + + + +#endif // CSBASESTATSPAGE_H diff --git a/game/client/cstrike/VGUI/bordered_panel.cpp b/game/client/cstrike/VGUI/bordered_panel.cpp new file mode 100644 index 00000000..cec1d702 --- /dev/null +++ b/game/client/cstrike/VGUI/bordered_panel.cpp @@ -0,0 +1,27 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +//------------------------------------------------------------- +// File: BorderedPanel.cpp +// Desc: +// Author: Peter Freese +// Date: 2009/05/20 +// Copyright: © 2009 Hidden Path Entertainment +//------------------------------------------------------------- + +#include "cbase.h" +#include "bordered_panel.h" +#include "backgroundpanel.h" // rounded border support + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +void BorderedPanel::PaintBackground() +{ + int wide, tall; + GetSize( wide, tall ); + + DrawRoundedBackground( GetBgColor(), wide, tall ); + DrawRoundedBorder( GetFgColor(), wide, tall ); +} + +DECLARE_BUILD_FACTORY( BorderedPanel ); + diff --git a/game/client/cstrike/VGUI/bordered_panel.h b/game/client/cstrike/VGUI/bordered_panel.h new file mode 100644 index 00000000..7279f10b --- /dev/null +++ b/game/client/cstrike/VGUI/bordered_panel.h @@ -0,0 +1,35 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +//------------------------------------------------------------- +// File: bordered_panel.h +// Desc: +// Author: Peter Freese +// Date: 2009/05/20 +// Copyright: © 2009 Hidden Path Entertainment +//------------------------------------------------------------- + +#ifndef INCLUDED_BorderedPanel +#define INCLUDED_BorderedPanel +#pragma once + +#include + +using namespace vgui; + +//----------------------------------------------------------------------------- +// Purpose: Editable panel with a forced rounded/outlined border +//----------------------------------------------------------------------------- +class BorderedPanel : public EditablePanel +{ +public: + DECLARE_CLASS_SIMPLE( BorderedPanel, EditablePanel ); + + BorderedPanel( Panel *parent, const char *name ) : + EditablePanel( parent, name ) + { + } + + void PaintBackground(); +}; + + +#endif // INCLUDED_BorderedPanel diff --git a/game/client/cstrike/VGUI/buymouseoverpanelbutton.h b/game/client/cstrike/VGUI/buymouseoverpanelbutton.h new file mode 100644 index 00000000..9e5abbf6 --- /dev/null +++ b/game/client/cstrike/VGUI/buymouseoverpanelbutton.h @@ -0,0 +1,397 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef BUYMOUSEOVERPANELBUTTON_H +#define BUYMOUSEOVERPANELBUTTON_H +#ifdef _WIN32 +#pragma once +#endif + +#include +#include +#include "mouseoverpanelbutton.h" +#include "hud.h" +#include "c_cs_player.h" +#include "cs_gamerules.h" +#include "cstrike/bot/shared_util.h" +#include +#include +#include + +using namespace vgui; + +//----------------------------------------------------------------------------- +// Purpose: Triggers a new panel when the mouse goes over the button +//----------------------------------------------------------------------------- +class BuyMouseOverPanelButton : public MouseOverPanelButton +{ +private: + typedef MouseOverPanelButton BaseClass; +public: + BuyMouseOverPanelButton(vgui::Panel *parent, const char *panelName, vgui::EditablePanel *panel) : + MouseOverPanelButton( parent, panelName, panel) + { + m_iPrice = 0; + m_iPreviousPrice = 0; + m_iASRestrict = 0; + m_iDEUseOnly = 0; + m_command = NULL; + m_bIsBargain = false; + + m_pBlackMarketPrice = NULL;//new EditablePanel( parent, "BlackMarket_Labels" ); + if ( m_pBlackMarketPrice ) + { + m_pBlackMarketPrice->LoadControlSettings( "Resource/UI/BlackMarket_Labels.res" ); + + int x,y,wide,tall; + GetClassPanel()->GetBounds( x, y, wide, tall ); + m_pBlackMarketPrice->SetBounds( x, y, wide, tall ); + int px, py; + GetClassPanel()->GetPinOffset( px, py ); + int rx, ry; + GetClassPanel()->GetResizeOffset( rx, ry ); + // Apply pin settings from template, too + m_pBlackMarketPrice->SetAutoResize( GetClassPanel()->GetPinCorner(), GetClassPanel()->GetAutoResize(), px, py, rx, ry ); + } + } + + virtual void ApplySettings( KeyValues *resourceData ) + { + BaseClass::ApplySettings( resourceData ); + + KeyValues *kv = resourceData->FindKey( "cost", false ); + if( kv ) // if this button has a cost defined for it + { + m_iPrice = kv->GetInt(); // save the price away + } + + kv = resourceData->FindKey( "as_restrict", false ); + if( kv ) // if this button has a map limitation for it + { + m_iASRestrict = kv->GetInt(); // save the as_restrict away + } + + kv = resourceData->FindKey( "de_useonly", false ); + if( kv ) // if this button has a map limitation for it + { + m_iDEUseOnly = kv->GetInt(); // save the de_useonly away + } + + if ( m_command ) + { + delete[] m_command; + m_command = NULL; + } + kv = resourceData->FindKey( "command", false ); + if ( kv ) + { + m_command = CloneString( kv->GetString() ); + } + + SetPriceState(); + SetMapTypeState(); + } + + int GetASRestrict() { return m_iASRestrict; } + + int GetDEUseOnly() { return m_iDEUseOnly; } + + virtual void PerformLayout() + { + BaseClass::PerformLayout(); + SetPriceState(); + SetMapTypeState(); + +#ifndef CS_SHIELD_ENABLED + if ( !Q_stricmp( GetName(), "shield" ) ) + { + SetVisible( false ); + SetEnabled( false ); + } +#endif + } + + virtual void ApplySchemeSettings( vgui::IScheme *pScheme ) + { + BaseClass::ApplySchemeSettings( pScheme ); + + m_avaliableColor = pScheme->GetColor( "Label.TextColor", Color( 0, 0, 0, 0 ) ); + m_unavailableColor = pScheme->GetColor( "Label.DisabledFgColor2", Color( 0, 0, 0, 0 ) ); + m_bargainColor = Color( 0, 255, 0, 192 ); + + SetPriceState(); + SetMapTypeState(); + } + + void SetPriceState() + { + if ( CSGameRules() && CSGameRules()->IsBlackMarket() ) + { + SetMarketState(); + } + else + { + if ( GetParent() ) + { + Panel *pPanel = dynamic_cast< Panel * >(GetParent()->FindChildByName( "MarketSticker" ) ); + + if ( pPanel ) + { + pPanel->SetVisible( false ); + } + } + + m_bIsBargain = false; + } + + C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer(); + + if ( m_iPrice && ( pPlayer && m_iPrice > pPlayer->GetAccount() ) ) + { + SetFgColor( m_unavailableColor ); + SetCommand( "buy_unavailable" ); + } + else + { + if ( m_bIsBargain == false ) + { + SetFgColor( m_avaliableColor ); + } + else + { + SetFgColor( m_bargainColor ); + } + + SetCommand( m_command ); + } + } + + void SetMarketState( void ) + { + Panel *pClassPanel = GetClassPanel(); + if ( pClassPanel ) + { + pClassPanel->SetVisible( false ); + } + + if ( m_pBlackMarketPrice ) + { + Label *pLabel = dynamic_cast< Label * >(m_pBlackMarketPrice->FindChildByName( "pricelabel" ) ); + + if ( pLabel ) + { + const int BufLen = 2048; + wchar_t wbuf[BufLen] = L""; + const wchar_t *formatStr = g_pVGuiLocalize->Find("#Cstrike_MarketPreviousPrice"); + + if ( !formatStr ) + formatStr = L"%s1"; + + char strPrice[16]; + wchar_t szPrice[64]; + Q_snprintf( strPrice, sizeof( strPrice ), "%d", m_iPreviousPrice ); + + g_pVGuiLocalize->ConvertANSIToUnicode( strPrice, szPrice, sizeof(szPrice)); + + g_pVGuiLocalize->ConstructString( wbuf, sizeof(wbuf), formatStr, 1, szPrice ); + pLabel->SetText( wbuf ); + pLabel->SetVisible( true ); + } + + pLabel = dynamic_cast< Label * >(m_pBlackMarketPrice->FindChildByName( "price" ) ); + + if ( pLabel ) + { + const int BufLen = 2048; + wchar_t wbuf[BufLen] = L""; + const wchar_t *formatStr = g_pVGuiLocalize->Find("#Cstrike_MarketCurrentPrice"); + + if ( !formatStr ) + formatStr = L"%s1"; + + char strPrice[16]; + wchar_t szPrice[64]; + Q_snprintf( strPrice, sizeof( strPrice ), "%d", m_iPrice ); + + g_pVGuiLocalize->ConvertANSIToUnicode( strPrice, szPrice, sizeof(szPrice)); + + g_pVGuiLocalize->ConstructString( wbuf, sizeof(wbuf), formatStr, 1, szPrice ); + pLabel->SetText( wbuf ); + pLabel->SetVisible( true ); + } + + pLabel = dynamic_cast< Label * >(m_pBlackMarketPrice->FindChildByName( "difference" ) ); + + if ( pLabel ) + { + const int BufLen = 2048; + wchar_t wbuf[BufLen] = L""; + const wchar_t *formatStr = g_pVGuiLocalize->Find("#Cstrike_MarketDeltaPrice"); + + if ( !formatStr ) + formatStr = L"%s1"; + + char strPrice[16]; + wchar_t szPrice[64]; + + int iDifference = m_iPreviousPrice - m_iPrice; + + if ( iDifference >= 0 ) + { + pLabel->SetFgColor( m_bargainColor ); + } + else + { + pLabel->SetFgColor( Color( 192, 28, 0, 255 ) ); + } + + Q_snprintf( strPrice, sizeof( strPrice ), "%d", abs( iDifference ) ); + + g_pVGuiLocalize->ConvertANSIToUnicode( strPrice, szPrice, sizeof(szPrice)); + + g_pVGuiLocalize->ConstructString( wbuf, sizeof(wbuf), formatStr, 1, szPrice ); + pLabel->SetText( wbuf ); + pLabel->SetVisible( true ); + } + + ImagePanel *pImage = dynamic_cast< ImagePanel * >(m_pBlackMarketPrice->FindChildByName( "classimage" ) ); + + if ( pImage ) + { + ImagePanel *pClassImage = dynamic_cast< ImagePanel * >(GetClassPanel()->FindChildByName( "classimage" ) ); + + if ( pClassImage ) + { + pImage->SetSize( pClassImage->GetWide(), pClassImage->GetTall() ); + pImage->SetImage( pClassImage->GetImage() ); + } + } + + if ( GetParent() ) + { + Panel *pPanel = dynamic_cast< Panel * >(GetParent()->FindChildByName( "MarketSticker" ) ); + + if ( pPanel ) + { + if ( m_bIsBargain ) + { + pPanel->SetVisible( true ); + } + else + { + pPanel->SetVisible( false ); + } + } + } + } + } + + void SetMapTypeState() + { + CCSGameRules *pRules = CSGameRules(); + + if ( pRules ) + { + if( pRules->IsVIPMap() ) + { + if ( m_iASRestrict ) + { + SetFgColor( m_unavailableColor ); + SetCommand( "buy_unavailable" ); + } + } + + if ( !pRules->IsBombDefuseMap() ) + { + if ( m_iDEUseOnly ) + { + SetFgColor( m_unavailableColor ); + SetCommand( "buy_unavailable" ); + } + } + } + } + + void SetBargainButton( bool state ) + { + m_bIsBargain = state; + } + + void SetCurrentPrice( int iPrice ) + { + m_iPrice = iPrice; + } + + void SetPreviousPrice( int iPrice ) + { + m_iPreviousPrice = iPrice; + } + + const char *GetBuyCommand( void ) + { + return m_command; + } + + virtual void ShowPage() + { + if ( g_lastPanel ) + { + for( int i = 0; i< g_lastPanel->GetParent()->GetChildCount(); i++ ) + { + MouseOverPanelButton *buyButton = dynamic_cast(g_lastPanel->GetParent()->GetChild(i)); + + if ( buyButton ) + { + buyButton->HidePage(); + } + } + } + + BaseClass::ShowPage(); + + if ( !Q_stricmp( m_command, "vguicancel" ) ) + return; + + if ( CSGameRules() && CSGameRules()->IsBlackMarket() ) + { + if ( m_pBlackMarketPrice && !m_pBlackMarketPrice->IsVisible() ) + { + m_pBlackMarketPrice->SetVisible( true ); + } + } + } + + virtual void HidePage() + { + BaseClass::HidePage(); + + if ( m_pBlackMarketPrice && m_pBlackMarketPrice->IsVisible() ) + { + m_pBlackMarketPrice->SetVisible( false ); + } + } + +private: + + int m_iPrice; + int m_iPreviousPrice; + int m_iASRestrict; + int m_iDEUseOnly; + bool m_bIsBargain; + + Color m_avaliableColor; + Color m_unavailableColor; + Color m_bargainColor; + + char *m_command; + +public: + vgui::EditablePanel *m_pBlackMarketPrice; +}; + + +#endif // BUYMOUSEOVERPANELBUTTON_H diff --git a/game/client/cstrike/VGUI/buypreset_imageinfo.cpp b/game/client/cstrike/VGUI/buypreset_imageinfo.cpp new file mode 100644 index 00000000..69f93cce --- /dev/null +++ b/game/client/cstrike/VGUI/buypreset_imageinfo.cpp @@ -0,0 +1,577 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#include "cbase.h" + +#include "weapon_csbase.h" +#include "cs_ammodef.h" + +#include +#include +#include +#include +#include +#include "vgui_controls/BuildGroup.h" +#include "vgui_controls/BitmapImagePanel.h" +#include "vgui_controls/TextEntry.h" +#include "vgui_controls/TextImage.h" +#include "vgui_controls/RichText.h" +#include "vgui_controls/QueryBox.h" +#include "career_box.h" +#include "buypreset_listbox.h" +#include "buypreset_weaponsetlabel.h" + +#include "cstrike/bot/shared_util.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +using namespace vgui; + +//-------------------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------------------- +WeaponImageInfo::WeaponImageInfo() +{ + m_needLayout = m_isCentered = false; + m_left = m_top = m_wide = m_tall = 0; + m_isPrimary = false; + memset( &m_weapon, 0, sizeof(ImageInfo) ); + memset( &m_ammo, 0, sizeof(ImageInfo) ); + m_weaponScale = m_ammoScale = 0; + m_pAmmoText = new TextImage( "" ); +} + +//-------------------------------------------------------------------------------------------------------------- +WeaponImageInfo::~WeaponImageInfo() +{ + delete m_pAmmoText; +} + +//-------------------------------------------------------------------------------------------------------------- +void WeaponImageInfo::ApplyTextSettings( vgui::IScheme *pScheme, bool isProportional ) +{ + Color color = pScheme->GetColor( "FgColor", Color( 0, 0, 0, 0 ) ); + + m_pAmmoText->SetColor( color ); + m_pAmmoText->SetFont( pScheme->GetFont( "Default", isProportional ) ); + m_pAmmoText->SetWrap( false ); +} + +//-------------------------------------------------------------------------------------------------------------- +void WeaponImageInfo::SetBounds( int left, int top, int wide, int tall ) +{ + m_left = left; + m_top = top; + m_wide = wide; + m_tall = tall; + m_needLayout = true; +} + +//-------------------------------------------------------------------------------------------------------------- +void WeaponImageInfo::SetCentered( bool isCentered ) +{ + m_isCentered = isCentered; + m_needLayout = true; +} + +//-------------------------------------------------------------------------------------------------------------- +void WeaponImageInfo::SetScaleAt1024( int weaponScale, int ammoScale ) +{ + m_weaponScale = weaponScale; + m_ammoScale = ammoScale; + m_needLayout = true; +} + +//-------------------------------------------------------------------------------------------------------------- +void WeaponImageInfo::SetWeapon( const BuyPresetWeapon *pWeapon, bool isPrimary, bool useCurrentAmmoType ) +{ + m_pAmmoText->SetText( L"" ); + m_weapon.image = NULL; + m_ammo.image = NULL; + m_isPrimary = isPrimary; + + if ( !pWeapon ) + return; + + wchar_t *multiplierString = g_pVGuiLocalize->Find("#Cstrike_BuyMenuPresetMultiplier"); + if ( !multiplierString ) + multiplierString = L""; + const int BufLen = 32; + wchar_t buf[BufLen]; + + if ( pWeapon->GetAmmoType() == AMMO_CLIPS ) + { + CSWeaponID weaponID = pWeapon->GetWeaponID(); + const CCSWeaponInfo *info = GetWeaponInfo( weaponID ); + int numClips = pWeapon->GetAmmoAmount(); + if ( info ) + { + int maxRounds = GetCSAmmoDef()->MaxCarry( info->iAmmoType ); + int buyClipSize = GetCSAmmoDef()->GetBuySize( info->iAmmoType ); + + int maxClips = (buyClipSize > 0) ? ceil(maxRounds/(float)buyClipSize) : 0; + numClips = MIN( numClips, maxClips ); + m_weapon.image = scheme()->GetImage( ImageFnameFromWeaponID( weaponID, m_isPrimary ), true ); + if ( numClips == 0 ) + { + m_ammo.image = NULL; + } + else if ( info->m_WeaponType == WEAPONTYPE_SHOTGUN ) + { + m_ammo.image = scheme()->GetImage( "gfx/vgui/shell", true ); + } + else if ( isPrimary ) + { + m_ammo.image = scheme()->GetImage( "gfx/vgui/bullet", true ); + } + else + { + m_ammo.image = scheme()->GetImage( "gfx/vgui/cartridge", true ); + } + + if ( numClips > 1 ) + { + g_pVGuiLocalize->ConstructString( buf, sizeof(buf), multiplierString, 1, NumAsWString( numClips ) ); + m_pAmmoText->SetText( buf ); + } + else + { + m_pAmmoText->SetText( L"" ); + } + } + else if ( numClips > 0 || !useCurrentAmmoType ) + { + if ( useCurrentAmmoType ) + { + CSWeaponID currentID = GetClientWeaponID( isPrimary ); + m_weapon.image = scheme()->GetImage( ImageFnameFromWeaponID( currentID, m_isPrimary ), true ); + info = GetWeaponInfo( currentID ); + if ( !info ) + { + m_weapon.image = NULL; + numClips = 0; + } + else if ( info->m_WeaponType == WEAPONTYPE_SHOTGUN ) + { + m_ammo.image = scheme()->GetImage( "gfx/vgui/shell", true ); + } + else if ( isPrimary ) + { + m_ammo.image = scheme()->GetImage( "gfx/vgui/bullet", true ); + } + else + { + m_ammo.image = scheme()->GetImage( "gfx/vgui/cartridge", true ); + } + } + else + { + m_weapon.image = scheme()->GetImage( ImageFnameFromWeaponID( weaponID, m_isPrimary ), true ); + if ( numClips == 0 ) + { + m_ammo.image = NULL; + } + else if ( isPrimary ) + { + m_ammo.image = scheme()->GetImage( "gfx/vgui/bullet", true ); + } + else + { + m_ammo.image = scheme()->GetImage( "gfx/vgui/cartridge", true ); + } + } + if ( numClips > 1 ) + { + g_pVGuiLocalize->ConstructString( buf, sizeof(buf), multiplierString, 1, NumAsWString( numClips ) ); + m_pAmmoText->SetText( buf ); + } + else + { + m_pAmmoText->SetText( L"" ); + } + } + } + m_needLayout = true; +} + +//-------------------------------------------------------------------------------------------------------------- +void WeaponImageInfo::Paint() +{ + if ( m_needLayout ) + PerformLayout(); + + m_weapon.Paint(); + m_ammo.Paint(); +} + +//-------------------------------------------------------------------------------------------------------------- +void WeaponImageInfo::PaintText() +{ + if ( m_needLayout ) + PerformLayout(); + + m_pAmmoText->Paint(); +} + +//-------------------------------------------------------------------------------------------------------------- +void WeaponImageInfo::PerformLayout() +{ + m_needLayout = false; + + m_weapon.FitInBounds( m_left, m_top, m_wide*0.8, m_tall, m_isCentered, m_weaponScale ); + int ammoX = MIN( m_wide*5/6, m_weapon.w ); + int ammoSize = m_tall * 9 / 16; + if ( !m_isPrimary ) + { + ammoSize = ammoSize * 25 / 40; + ammoX = MIN( m_wide*5/6, m_weapon.w*3/4 ); + } + if ( ammoX + ammoSize > m_wide ) + { + ammoX = m_wide - ammoSize; + } + m_ammo.FitInBounds( m_left + ammoX, m_top + m_tall - ammoSize, ammoSize, ammoSize, false, m_ammoScale ); + + int w, h; + m_pAmmoText->ResizeImageToContent(); + m_pAmmoText->GetSize( w, h ); + if ( m_isPrimary ) + { + if ( m_ammoScale < 75 ) + { + m_pAmmoText->SetPos( m_left + ammoX + ammoSize*1.25f - w, m_top + m_tall - h ); + } + else + { + m_pAmmoText->SetPos( m_left + ammoX + ammoSize - w, m_top + m_tall - h ); + } + } + else + { + m_pAmmoText->SetPos( m_left + ammoX + ammoSize, m_top + m_tall - h ); + } +} + +//-------------------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------------------- +WeaponLabel::WeaponLabel(Panel *parent, const char *panelName) : BaseClass( parent, panelName ) +{ + SetSize( 10, 10 ); + SetMouseInputEnabled( false ); +} + +//-------------------------------------------------------------------------------------------------------------- +WeaponLabel::~WeaponLabel() +{ +} + +//-------------------------------------------------------------------------------------------------------------- +void WeaponLabel::SetWeapon( const BuyPresetWeapon *pWeapon, bool isPrimary, bool showAmmo ) +{ + BuyPresetWeapon weapon(WEAPON_NONE); + if ( pWeapon ) + weapon = *pWeapon; + if ( !showAmmo ) + weapon.SetAmmoAmount( 0 ); + m_weapon.SetWeapon( &weapon, isPrimary, false ); +} + +//-------------------------------------------------------------------------------------------------------------- +void WeaponLabel::ApplySchemeSettings(IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings( pScheme ); + + m_weapon.ApplyTextSettings( pScheme, IsProportional() ); +} + +//-------------------------------------------------------------------------------------------------------------- +void WeaponLabel::PerformLayout() +{ + BaseClass::PerformLayout(); + + int wide, tall; + GetSize( wide, tall ); + m_weapon.SetBounds( 0, 0, wide, tall ); +} + +//-------------------------------------------------------------------------------------------------------------- +void WeaponLabel::Paint() +{ + BaseClass::Paint(); + + m_weapon.Paint(); + m_weapon.PaintText(); +} + +//-------------------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------------------- +ItemImageInfo::ItemImageInfo() +{ + m_needLayout = false; + m_left = m_top = m_wide = m_tall = 0; + m_count = 0; + memset( &m_image, 0, sizeof(ImageInfo) ); + m_pText = new TextImage( "" ); + + SetBounds( 0, 0, 100, 100 ); +} + +//-------------------------------------------------------------------------------------------------------------- +ItemImageInfo::~ItemImageInfo() +{ + delete m_pText; +} + +//-------------------------------------------------------------------------------------------------------------- +void ItemImageInfo::ApplyTextSettings( vgui::IScheme *pScheme, bool isProportional ) +{ + Color color = pScheme->GetColor( "Label.TextColor", Color( 0, 0, 0, 0 ) ); + + m_pText->SetColor( color ); + m_pText->SetFont( pScheme->GetFont( "Default", isProportional ) ); + m_pText->SetWrap( false ); +} + +//-------------------------------------------------------------------------------------------------------------- +void ItemImageInfo::SetBounds( int left, int top, int wide, int tall ) +{ + m_left = left; + m_top = top; + m_wide = wide; + m_tall = tall; + m_needLayout = true; +} + +//-------------------------------------------------------------------------------------------------------------- +void ItemImageInfo::SetItem( const char *imageFname, int count ) +{ + m_pText->SetText( L"" ); + m_count = count; + + if ( imageFname ) + m_image.image = scheme()->GetImage( imageFname, true ); + else + m_image.image = NULL; + + if ( count > 1 ) + { + wchar_t *multiplierString = g_pVGuiLocalize->Find("#Cstrike_BuyMenuPresetMultiplier"); + if ( !multiplierString ) + multiplierString = L""; + const int BufLen = 32; + wchar_t buf[BufLen]; + + g_pVGuiLocalize->ConstructString( buf, sizeof(buf), multiplierString, 1, NumAsWString( count ) ); + m_pText->SetText( buf ); + } + m_needLayout = true; +} + +//-------------------------------------------------------------------------------------------------------------- +void ItemImageInfo::Paint() +{ + if ( m_needLayout ) + PerformLayout(); + + if ( m_count ) + m_image.Paint(); +} + +//-------------------------------------------------------------------------------------------------------------- +void ItemImageInfo::PaintText() +{ + if ( m_needLayout ) + PerformLayout(); + + m_pText->Paint(); +} + +//-------------------------------------------------------------------------------------------------------------- +void ItemImageInfo::PerformLayout() +{ + m_needLayout = false; + + m_image.FitInBounds( m_left, m_top, m_wide, m_tall, false, 0 ); + + int w, h; + m_pText->ResizeImageToContent(); + m_pText->GetSize( w, h ); + m_pText->SetPos( m_left + m_image.w - w, m_top + m_tall - h ); +} + +//-------------------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------------------- +EquipmentLabel::EquipmentLabel(Panel *parent, const char *panelName, const char *imageFname) : BaseClass( parent, panelName ) +{ + SetSize( 10, 10 ); + m_item.SetItem( imageFname, 0 ); + SetMouseInputEnabled( false ); +} + +//-------------------------------------------------------------------------------------------------------------- +EquipmentLabel::~EquipmentLabel() +{ +} + +//-------------------------------------------------------------------------------------------------------------- +void EquipmentLabel::SetItem( const char *imageFname, int count ) +{ + m_item.SetItem( imageFname, count ); +} + +//-------------------------------------------------------------------------------------------------------------- +void EquipmentLabel::ApplySchemeSettings(IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings( pScheme ); + + m_item.ApplyTextSettings( pScheme, IsProportional() ); +} + +//-------------------------------------------------------------------------------------------------------------- +void EquipmentLabel::PerformLayout() +{ + BaseClass::PerformLayout(); + + int wide, tall; + GetSize( wide, tall ); + m_item.SetBounds( 0, 0, wide, tall ); +} + +//-------------------------------------------------------------------------------------------------------------- +void EquipmentLabel::Paint() +{ + BaseClass::Paint(); + + m_item.Paint(); + m_item.PaintText(); +} + + +//-------------------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------------------- +/// Helper function: draws a simple dashed line +void DrawDashedLine(int x0, int y0, int x1, int y1, int dashLen, int gapLen) +{ + // work out which way the line goes + if ((x1 - x0) > (y1 - y0)) + { + // x direction line + while (1) + { + if (x0 + dashLen > x1) + { + // draw partial + surface()->DrawFilledRect(x0, y0, x1, y1+1); + } + else + { + surface()->DrawFilledRect(x0, y0, x0 + dashLen, y1+1); + } + + x0 += dashLen; + + if (x0 + gapLen > x1) + break; + + x0 += gapLen; + } + } + else + { + // y direction + while (1) + { + if (y0 + dashLen > y1) + { + // draw partial + surface()->DrawFilledRect(x0, y0, x1+1, y1); + } + else + { + surface()->DrawFilledRect(x0, y0, x1+1, y0 + dashLen); + } + + y0 += dashLen; + + if (y0 + gapLen > y1) + break; + + y0 += gapLen; + } + } +} + +//-------------------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------------------- +void ImageInfo::Paint() +{ + if ( !image ) + return; + + image->SetSize( w, h ); + image->SetPos( x, y ); + image->Paint(); + image->SetSize( 0, 0 ); // restore image size to content size to not mess up other places that use the same image +} + +//-------------------------------------------------------------------------------------------------------------- +void ImageInfo::FitInBounds( int baseX, int baseY, int width, int height, bool center, int scaleAt1024, bool halfHeight ) +{ + if ( !image ) + { + x = y = w = h = 0; + return; + } + + image->GetContentSize(fullW, fullH); + + if ( scaleAt1024 ) + { + int screenW, screenH; + GetHudSize( screenW, screenH ); + + w = fullW * screenW / 1024 * scaleAt1024 / 100; + h = fullH * screenW / 1024 * scaleAt1024 / 100; + + if ( fullH > 64 && scaleAt1024 == 100 ) + { + w = w * 64 / fullH; + h = h * 64 / fullH; + } + + if ( h > height * 1.2 ) + scaleAt1024 = 0; + } + if ( !scaleAt1024 ) + { + w = fullW; + h = fullH; + + if ( h != height ) + { + w = (int) w * 1.0f * height / h; + h = height; + } + + if ( w > width ) + { + h = (int) h * 1.0f * width / w; + w = width; + } + } + + if ( center ) + { + x = baseX + (width - w)/2; + } + else + { + x = baseX; + } + y = baseY + (height - h)/2; +} + +//-------------------------------------------------------------------------------------------------------------- diff --git a/game/client/cstrike/VGUI/buypreset_listbox.cpp b/game/client/cstrike/VGUI/buypreset_listbox.cpp new file mode 100644 index 00000000..add8dd75 --- /dev/null +++ b/game/client/cstrike/VGUI/buypreset_listbox.cpp @@ -0,0 +1,406 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#include "cbase.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "buypreset_listbox.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include + +using namespace vgui; + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + + +//-------------------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------------------- +BuyPresetListBox::BuyPresetListBox( vgui::Panel *parent, char const *panelName ) : Panel( parent, panelName ) +{ + m_visibleIndex = 0; + m_lastSize = 0; + + SetBounds( 0, 0, 100, 100 ); + + m_vbar = new ScrollBar(this, "PanelListPanelVScroll", true); + m_vbar->SetBounds( 0, 0, 20, 20 ); + m_vbar->SetVisible(true); + m_vbar->AddActionSignalTarget( this ); + + m_pPanelEmbedded = new EditablePanel(this, "PanelListEmbedded"); + m_pPanelEmbedded->SetBounds(0, 0, 20, 20); + m_pPanelEmbedded->SetPaintBackgroundEnabled( false ); + m_pPanelEmbedded->SetPaintBorderEnabled(false); + + if( IsProportional() ) + { + int width, height; + int sw,sh; + surface()->GetProportionalBase( width, height ); + GetHudSize(sw, sh); + + // resize scrollbar, etc + m_iScrollbarSize = static_cast( static_cast( SCROLLBAR_SIZE )*( static_cast( sw )/ static_cast( width ))); + m_iDefaultHeight = static_cast( static_cast( DEFAULT_HEIGHT )*( static_cast( sw )/ static_cast( width ))); + m_iPanelBuffer = static_cast( static_cast( PANELBUFFER )*( static_cast( sw )/ static_cast( width ))); + } + else + { + m_iScrollbarSize = SCROLLBAR_SIZE; + m_iDefaultHeight = DEFAULT_HEIGHT; + m_iPanelBuffer = PANELBUFFER; + } +} + +//-------------------------------------------------------------------------------------------------------------- +BuyPresetListBox::~BuyPresetListBox() +{ + // free data from table + DeleteAllItems(); +} + +//-------------------------------------------------------------------------------------------------------------- +/** + * Passes commands up to the parent + */ +void BuyPresetListBox::OnCommand( const char *command ) +{ + GetParent()->OnCommand( command ); +} + +//-------------------------------------------------------------------------------------------------------------- +/** + * Scrolls the list according to the mouse wheel movement + */ +void BuyPresetListBox::OnMouseWheeled(int delta) +{ + int scale = 3; + if ( m_items.Count() ) + { + Panel *panel = m_items[0].panel; + if ( panel ) + { + scale = panel->GetTall() + m_iPanelBuffer; + } + } + int val = m_vbar->GetValue(); + val -= (delta * scale); + m_vbar->SetValue(val); +} + +//-------------------------------------------------------------------------------------------------------------- +/** + * Computes vertical pixels needed by listbox contents + */ +int BuyPresetListBox::computeVPixelsNeeded( void ) +{ + int pixels = 0; + + int i; + for ( i = 0; i < m_items.Count(); i++ ) + { + Panel *panel = m_items[i].panel; + if ( !panel ) + continue; + + int w, h; + panel->GetSize( w, h ); + + pixels += m_iPanelBuffer; // add in buffer. between items. + pixels += h; + } + + pixels += m_iPanelBuffer; // add in buffer below last item + + return pixels; +} + +//-------------------------------------------------------------------------------------------------------------- +/** + * Adds an item to the end of the listbox. UserData is assumed to be a pointer that can be freed by the listbox if non-NULL. + */ +int BuyPresetListBox::AddItem( vgui::Panel *panel, void * userData ) +{ + assert(panel); + + DataItem item = { panel, userData }; + + panel->SetParent( m_pPanelEmbedded ); + + m_items.AddToTail( item ); + + InvalidateLayout(); + return m_items.Count(); +} + +//-------------------------------------------------------------------------------------------------------------- +/** + * Exchanges two items in the listbox + */ +void BuyPresetListBox::SwapItems( int index1, int index2 ) +{ + if ( index1 < 0 || index2 < 0 || index1 >= m_items.Count() || index2 >= m_items.Count() ) + { + return; + } + + DataItem temp = m_items[index1]; + m_items[index1] = m_items[index2]; + m_items[index2] = temp; + + InvalidateLayout(); +} + +//-------------------------------------------------------------------------------------------------------------- +/** + * Returns the number of items in the listbox + */ +int BuyPresetListBox::GetItemCount( void ) const +{ + return m_items.Count(); +} + +//-------------------------------------------------------------------------------------------------------------- +/** + * Returns the panel in the given index, or NULL + */ +Panel * BuyPresetListBox::GetItemPanel(int index) const +{ + if ( index < 0 || index >= m_items.Count() ) + return NULL; + + return m_items[index].panel; +} + +//-------------------------------------------------------------------------------------------------------------- +/** + * Returns the userData in the given index, or NULL + */ +void * BuyPresetListBox::GetItemUserData(int index) +{ + if ( index < 0 || index >= m_items.Count() ) + { + return NULL; + } + + return m_items[index].userData; +} + +//-------------------------------------------------------------------------------------------------------------- +/** + * Sets the userData in the given index + */ +void BuyPresetListBox::SetItemUserData( int index, void * userData ) +{ + if ( index < 0 || index >= m_items.Count() ) + return; + + m_items[index].userData = userData; +} + +//-------------------------------------------------------------------------------------------------------------- +/** + * Removes an item from the table (changing the indices of all following items), deleting the panel and userData + */ +void BuyPresetListBox::RemoveItem(int index) +{ + if ( index < 0 || index >= m_items.Count() ) + return; + + DataItem item = m_items[index]; + if ( item.panel ) + { + item.panel->MarkForDeletion(); + } + if ( item.userData ) + { + delete item.userData; + } + + m_items.Remove( index ); + + InvalidateLayout(); +} + +//-------------------------------------------------------------------------------------------------------------- +/** + * clears the listbox, deleting all panels and userData + */ +void BuyPresetListBox::DeleteAllItems() +{ + while ( m_items.Count() ) + { + RemoveItem( 0 ); + } + + // move the scrollbar to the top of the list + m_vbar->SetValue(0); + InvalidateLayout(); +} + +//-------------------------------------------------------------------------------------------------------------- +/** + * Handles Count changes + */ +void BuyPresetListBox::OnSizeChanged(int wide, int tall) +{ + BaseClass::OnSizeChanged(wide, tall); + InvalidateLayout(); +} + +//-------------------------------------------------------------------------------------------------------------- +/** + * Positions listbox items, etc after internal changes + */ +void BuyPresetListBox::PerformLayout() +{ + int wide, tall; + GetSize( wide, tall ); + + int vpixels = computeVPixelsNeeded(); + + int visibleIndex = m_visibleIndex; + + //!! need to make it recalculate scroll positions + m_vbar->SetVisible(true); + m_vbar->SetEnabled(false); + m_vbar->SetRange( 0, (MAX( 0, vpixels - tall + m_iDefaultHeight )) ); + m_vbar->SetRangeWindow( m_iDefaultHeight ); + m_vbar->SetButtonPressedScrollValue( m_iDefaultHeight ); // standard height of labels/buttons etc. + m_vbar->SetPos(wide - m_iScrollbarSize, 1); + m_vbar->SetSize(m_iScrollbarSize, tall - 2); + + m_visibleIndex = visibleIndex; + + int top = MAX( 0, m_vbar->GetValue() ); + + m_pPanelEmbedded->SetPos( 1, -top ); + m_pPanelEmbedded->SetSize( wide-m_iScrollbarSize -2, vpixels ); + + // Now lay out the controls on the embedded panel + int y = 0; + int h = 0; + int totalh = 0; + + int i; + for ( i = 0; i < m_items.Count(); i++, y += h ) + { + // add in a little buffer between panels + y += m_iPanelBuffer; + DataItem item = m_items[i]; + + h = item.panel->GetTall(); + + totalh += h; + item.panel->SetBounds( 8, y, wide - m_iScrollbarSize - 8 - 8, h ); + item.panel->InvalidateLayout(); + } + + if ( m_visibleIndex >= 0 && m_visibleIndex < m_items.Count() ) + { + + int vpos = 0; + + int tempWide, tempTall; + GetSize( tempWide, tempTall ); + + int vtop, vbottom; + m_vbar->GetRange( vtop, vbottom ); + + int tempTop = MAX( 0, m_vbar->GetValue() ); // top pixel in the embedded panel + int bottom = tempTop + tempTall - 2; + + int itemTop, itemLeft, itemBottom, itemRight; + m_items[m_visibleIndex].panel->GetBounds( itemLeft, itemTop, itemRight, itemBottom ); + itemBottom += itemTop; + itemRight += itemLeft; + + if ( itemTop < tempTop ) + { + // item's top is too high + vpos -= ( tempTop - itemTop ); + + m_vbar->SetValue(vpos); + OnSliderMoved(vpos); + } + else if ( itemBottom > bottom ) + { + // item's bottom is too low + vpos += ( itemBottom - bottom ); + + m_vbar->SetValue(vpos); + OnSliderMoved(vpos); + } + } + + if ( m_lastSize == vpixels ) + { + m_visibleIndex = -1; + } + m_lastSize = vpixels; +} + +//-------------------------------------------------------------------------------------------------------------- +/** + * Try to ensure that the given index is visible + */ +void BuyPresetListBox::MakeItemVisible( int index ) +{ + m_visibleIndex = index; + m_lastSize = 0; +} + +//-------------------------------------------------------------------------------------------------------------- +/** + * Loads colors, fonts, etc + */ +void BuyPresetListBox::ApplySchemeSettings(IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings(pScheme); + + SetBgColor(GetSchemeColor("BuyPresetListBox.BgColor", GetBgColor(), pScheme)); + + SetBorder(pScheme->GetBorder("BrowserBorder")); + m_vbar->SetBorder(pScheme->GetBorder("BrowserBorder")); + + PerformLayout(); +} + + +//-------------------------------------------------------------------------------------------------------------- +/** + * Handles slider being dragged + */ +void BuyPresetListBox::OnSliderMoved( int position ) +{ + InvalidateLayout(); + Repaint(); +} + + +//-------------------------------------------------------------------------------------------------------------- +/** + * Moves slider to the top + */ +void BuyPresetListBox::MoveScrollBarToTop() +{ + m_vbar->SetValue(0); + OnSliderMoved(0); +} + diff --git a/game/client/cstrike/VGUI/buypreset_listbox.h b/game/client/cstrike/VGUI/buypreset_listbox.h new file mode 100644 index 00000000..68d6de69 --- /dev/null +++ b/game/client/cstrike/VGUI/buypreset_listbox.h @@ -0,0 +1,78 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#ifndef BUYPRESET_LISTBOX_H +#define BUYPRESET_LISTBOX_H +#ifdef _WIN32 +#pragma once +#endif + +#include +#include + +#include + +//-------------------------------------------------------------------------------------------------------------- +/** + * ListBox-style control with behavior needed by weapon lists for BuyPreset editing + */ +class BuyPresetListBox : public vgui::Panel +{ + DECLARE_CLASS_SIMPLE( BuyPresetListBox, vgui::Panel ); + +public: + BuyPresetListBox( vgui::Panel *parent, char const *panelName ); + ~BuyPresetListBox(); + + virtual int AddItem( vgui::Panel *panel, void * userData ); ///< Adds an item to the end of the listbox. UserData is assumed to be a pointer that can be freed by the listbox if non-NULL. + virtual int GetItemCount( void ) const; ///< Returns the number of items in the listbox + void SwapItems( int index1, int index2 ); ///< Exchanges two items in the listbox + void MakeItemVisible( int index ); ///< Try to ensure that the given index is visible + + vgui::Panel * GetItemPanel( int index ) const; ///< Returns the panel in the given index, or NULL + void * GetItemUserData( int index ); ///< Returns the userData in the given index, or NULL + void SetItemUserData( int index, void * userData ); ///< Sets the userData in the given index + + virtual void RemoveItem( int index ); ///< Removes an item from the table (changing the indices of all following items), deleting the panel and userData + virtual void DeleteAllItems(); ///< clears the listbox, deleting all panels and userData + + // overrides + virtual void OnSizeChanged(int wide, int tall); ////< Handles size changes + MESSAGE_FUNC_INT( OnSliderMoved, "ScrollBarSliderMoved", position ); ///< Handles slider being dragged + virtual void OnMouseWheeled(int delta); ///< Scrolls the list according to the mouse wheel movement + virtual void MoveScrollBarToTop(); ///< Moves slider to the top + +protected: + + virtual int computeVPixelsNeeded( void ); ///< Computes vertical pixels needed by listbox contents + + virtual void PerformLayout(); ///< Positions listbox items, etc after internal changes + virtual void ApplySchemeSettings( vgui::IScheme *pScheme ); ///< Loads colors, fonts, etc + + virtual void OnCommand( const char *command ); ///< Passes commands up to the parent + +private: + enum { SCROLLBAR_SIZE = 18, DEFAULT_HEIGHT = 24, PANELBUFFER = 5 }; + + typedef struct dataitem_s + { + vgui::Panel *panel; + void * userData; + } DataItem; + CUtlVector< DataItem > m_items; + + vgui::ScrollBar *m_vbar; + vgui::Panel *m_pPanelEmbedded; + + int m_iScrollbarSize; + int m_iDefaultHeight; + int m_iPanelBuffer; + + int m_visibleIndex; + int m_lastSize; +}; + +#endif // BUYPRESET_LISTBOX_H diff --git a/game/client/cstrike/VGUI/buypreset_panel.cpp b/game/client/cstrike/VGUI/buypreset_panel.cpp new file mode 100644 index 00000000..321984b4 --- /dev/null +++ b/game/client/cstrike/VGUI/buypreset_panel.cpp @@ -0,0 +1,447 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#include "cbase.h" + +#include "weapon_csbase.h" +#include "cs_ammodef.h" + +#include +#include +#include +#include +#include +#include "vgui_controls/BuildGroup.h" +#include "vgui_controls/BitmapImagePanel.h" +#include "vgui_controls/TextEntry.h" +#include "vgui_controls/TextImage.h" +#include "vgui_controls/RichText.h" +#include "vgui_controls/QueryBox.h" +#include "career_box.h" +#include "buypreset_listbox.h" +#include "buypreset_weaponsetlabel.h" +#include "backgroundpanel.h" + +#include "cstrike/bot/shared_util.h" + +using namespace vgui; + +const float horizTitleRatio = 18.0f/68.0f; + +//-------------------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------------------- +/* +class PresetNameTextEntry : public TextEntry +{ +public: + PresetNameTextEntry(Panel *parent, CBuyPresetEditMainMenu *menu, const char *name ) : TextEntry( parent, name ) + { + m_pMenu = menu; + } + + virtual void FireActionSignal() + { + TextEntry::FireActionSignal(); + if ( m_pMenu ) + { + m_pMenu->SetDirty(); + } + } + +private: + CBuyPresetEditMainMenu *m_pMenu; +}; +*/ + +//-------------------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------------------- +int GetScaledValue( HScheme hScheme, int unscaled ) +{ + int val = scheme()->GetProportionalScaledValueEx( hScheme, unscaled ); + return GetAlternateProportionalValueFromScaled( hScheme, val ); +} + +//-------------------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------------------- +class PresetBackgroundPanel : public vgui::Panel +{ + typedef vgui::Panel BaseClass; + +public: + PresetBackgroundPanel( vgui::Panel *parent, const char *panelName ) : BaseClass( parent, panelName ) + { + }; + + virtual void ApplySchemeSettings( vgui::IScheme *pScheme ) + { + BaseClass::ApplySchemeSettings( pScheme ); + SetBorder( pScheme->GetBorder("ButtonBorder") ); + m_lineColor = pScheme->GetColor( "Border.Bright", Color( 0, 0, 0, 0 ) ); + } + + virtual void ApplySettings( KeyValues *inResourceData ) + { + BaseClass::ApplySettings( inResourceData ); + + m_lines.RemoveAll(); + KeyValues *lines = inResourceData->FindKey( "lines", false ); + if ( lines ) + { + KeyValues *line = lines->GetFirstValue(); + while ( line ) + { + const char *str = line->GetString( NULL, "" ); + Vector4D p; + int numPoints = sscanf( str, "%f %f %f %f", &p[0], &p[1], &p[2], &p[3] ); + if ( numPoints == 4 ) + { + m_lines.AddToTail( p ); + } + line = line->GetNextValue(); + } + } + } + + virtual void PaintBackground( void ) + { + BaseClass::PaintBackground(); + + vgui::surface()->DrawSetColor( m_lineColor ); + vgui::surface()->DrawSetTextColor( m_lineColor ); + for ( int i=0; iDrawFilledRect( x1, y1, x2, y2 ); + } + } + + virtual void PerformLayout( void ) + { + m_scaledLines.RemoveAll(); + for ( int i=0; i m_lines; + CUtlVector< Vector4D > m_scaledLines; +}; + +//-------------------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------------------- +BuyPresetEditPanel::BuyPresetEditPanel( Panel *parent, const char *panelName, const char *resourceFilename, int fallbackIndex, bool editableName ) : BaseClass( parent, panelName ) +{ + SetProportional( parent->IsProportional() ); + if ( IsProportional() ) + { + m_baseWide = m_baseTall = scheme()->GetProportionalScaledValueEx( GetScheme(), 100 ); + } + else + { + m_baseWide = m_baseTall = 100; + } + SetSize( m_baseWide, m_baseTall ); + + m_fallbackIndex = fallbackIndex; + + m_pBgPanel = new PresetBackgroundPanel( this, "mainBackground" ); + + m_pTitleEntry = NULL; + m_pTitleLabel = NULL; + m_pCostLabel = NULL; + /* + m_pTitleEntry = new PresetNameTextEntry( this, dynamic_cast(parent), "titleEntry" ); + m_pTitleLabel = new Label( this, "title", "" ); + m_pCostLabel = new Label( this, "cost", "" ); + */ + + m_pPrimaryWeapon = new WeaponLabel( this, "primary" ); + m_pSecondaryWeapon = new WeaponLabel( this, "secondary" ); + + m_pHEGrenade = new EquipmentLabel( this, "hegrenade" ); + m_pSmokeGrenade = new EquipmentLabel( this, "smokegrenade" ); + m_pFlashbangs = new EquipmentLabel( this, "flashbang" ); + + m_pDefuser = new EquipmentLabel( this, "defuser" ); + m_pNightvision = new EquipmentLabel( this, "nightvision" ); + + m_pArmor = new EquipmentLabel( this, "armor" ); + + if ( resourceFilename ) + { + LoadControlSettings( resourceFilename ); + } + + int x, y, w, h; + m_pBgPanel->GetBounds( x, y, w, h ); + + m_baseWide = x + w; + m_baseTall = y + h; + SetSize( m_baseWide, m_baseTall ); +} + +//-------------------------------------------------------------------------------------------------------------- +BuyPresetEditPanel::~BuyPresetEditPanel() +{ +} + +//-------------------------------------------------------------------------------------------------------------- +void BuyPresetEditPanel::SetWeaponSet( const WeaponSet *pWeaponSet, bool current ) +{ + // set to empty state + Reset(); + + // now fill in items + if ( pWeaponSet ) + { + if ( m_pTitleLabel ) + { + m_pTitleLabel->SetText( SharedVarArgs( "#Cstrike_BuyPresetChoice%d", m_fallbackIndex ) ); + } + if ( m_pTitleEntry ) + { + m_pTitleEntry->SetText( SharedVarArgs( "#Cstrike_BuyPresetChoice%d", m_fallbackIndex ) ); + } + + if ( m_pCostLabel ) + { + const int BufLen = 256; + wchar_t wbuf[BufLen]; + g_pVGuiLocalize->ConstructString( wbuf, sizeof( wbuf ), + g_pVGuiLocalize->Find( "#Cstrike_BuyPresetPlainCost" ), + 1, NumAsWString( pWeaponSet->FullCost() ) ); + m_pCostLabel->SetText( wbuf ); + } + + m_pPrimaryWeapon->SetWeapon( &pWeaponSet->m_primaryWeapon, true, true ); + m_pSecondaryWeapon->SetWeapon( &pWeaponSet->m_secondaryWeapon, false, true ); + + if ( pWeaponSet->m_HEGrenade ) + m_pHEGrenade->SetItem( "gfx/vgui/hegrenade_square", 1 ); + if ( pWeaponSet->m_smokeGrenade ) + m_pSmokeGrenade->SetItem( "gfx/vgui/smokegrenade_square", 1 ); + if ( pWeaponSet->m_flashbangs ) + m_pFlashbangs->SetItem( "gfx/vgui/flashbang_square", pWeaponSet->m_flashbangs ); + + if ( pWeaponSet->m_defuser ) + m_pDefuser->SetItem( "gfx/vgui/defuser", 1 ); + if ( pWeaponSet->m_nightvision ) + m_pNightvision->SetItem( "gfx/vgui/nightvision", 1 ); + + if ( pWeaponSet->m_armor ) + { + if ( pWeaponSet->m_helmet ) + m_pArmor->SetItem( "gfx/vgui/kevlar_helmet", 1 ); + else + m_pArmor->SetItem( "gfx/vgui/kevlar", 1 ); + } + } +} + +//-------------------------------------------------------------------------------------------------------------- +void BuyPresetEditPanel::SetText( const wchar_t *text ) +{ + if ( !text ) + text = L""; + if ( m_pTitleLabel ) + { + m_pTitleLabel->SetText( text ); + } + if ( m_pTitleEntry ) + { + m_pTitleEntry->SetText( text ); + } + InvalidateLayout(); +} + +//-------------------------------------------------------------------------------------------------------------- +/** + * Handle command callbacks + */ +void BuyPresetEditPanel::OnCommand( const char *command ) +{ + if (stricmp(command, "close")) + { + PostActionSignal( new KeyValues("Command", "command", SharedVarArgs( "%s %d", command, m_fallbackIndex )) ); + } + + BaseClass::OnCommand(command); +} + +//-------------------------------------------------------------------------------------------------------------- +void BuyPresetEditPanel::ApplySchemeSettings(IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings(pScheme); + SetBgColor( Color( 0, 0, 0, 0 ) ); + + IBorder *pBorder = NULL; + + int i; + + for (i = 0; i < GetChildCount(); i++) + { + // perform auto-layout on the child panel + Panel *child = GetChild(i); + if (!child) + continue; + + if ( !stricmp( "button", child->GetClassName() ) ) + { + Button *pButton = dynamic_cast