diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /app | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'app')
29 files changed, 4384 insertions, 0 deletions
diff --git a/app/legion/basemenu.cpp b/app/legion/basemenu.cpp new file mode 100644 index 0000000..1d8c9e9 --- /dev/null +++ b/app/legion/basemenu.cpp @@ -0,0 +1,95 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Base class menus should all inherit from +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#include "basemenu.h" +#include "menumanager.h" +#include <ctype.h> +#include "vgui/iinput.h" + + +//----------------------------------------------------------------------------- +// Constructor, destructor +//----------------------------------------------------------------------------- +CBaseMenu::CBaseMenu( vgui::Panel *pParent, const char *pPanelName ) : + BaseClass( pParent, pPanelName ) +{ + SetKeyBoardInputEnabled( true ); + SetMouseInputEnabled( true ); + SetSizeable( false ); + SetMoveable( false ); +} + +CBaseMenu::~CBaseMenu() +{ +} + + +void CBaseMenu::OnKeyCodeTyped( vgui::KeyCode code ) +{ + BaseClass::OnKeyCodeTyped( code ); + + bool shift = (vgui::input()->IsKeyDown(vgui::KEY_LSHIFT) || vgui::input()->IsKeyDown(vgui::KEY_RSHIFT)); + bool ctrl = (vgui::input()->IsKeyDown(vgui::KEY_LCONTROL) || vgui::input()->IsKeyDown(vgui::KEY_RCONTROL)); + bool alt = (vgui::input()->IsKeyDown(vgui::KEY_LALT) || vgui::input()->IsKeyDown(vgui::KEY_RALT)); + + if ( ctrl && shift && alt && code == vgui::KEY_B) + { + // enable build mode + ActivateBuildMode(); + } + +} + +//----------------------------------------------------------------------------- +// Commands +//----------------------------------------------------------------------------- +void CBaseMenu::OnCommand( const char *pCommand ) +{ + if ( !Q_stricmp( pCommand, "quit" ) ) + { + IGameManager::Stop(); + return; + } + + if ( !Q_stricmp( pCommand, "popmenu" ) ) + { + g_pMenuManager->PopMenu(); + return; + } + + if ( !Q_stricmp( pCommand, "popallmenus" ) ) + { + g_pMenuManager->PopAllMenus(); + return; + } + + if ( !Q_strnicmp( pCommand, "pushmenu ", 9 ) ) + { + const char *pMenuName = pCommand + 9; + while( isspace(*pMenuName) ) + { + ++pMenuName; + } + g_pMenuManager->PushMenu( pMenuName ); + return; + } + + if ( !Q_strnicmp( pCommand, "switchmenu ", 11 ) ) + { + const char *pMenuName = pCommand + 11; + while( isspace(*pMenuName) ) + { + ++pMenuName; + } + g_pMenuManager->SwitchToMenu( pMenuName ); + return; + } + + BaseClass::OnCommand( pCommand ); +} + diff --git a/app/legion/basemenu.h b/app/legion/basemenu.h new file mode 100644 index 0000000..5841852 --- /dev/null +++ b/app/legion/basemenu.h @@ -0,0 +1,39 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Base class menus should all inherit from +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#ifndef BASEMENU_H +#define BASEMENU_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "vgui_controls/frame.h" +#include "vgui/keycode.h" + + +//----------------------------------------------------------------------------- +// Constructor, destructor +//----------------------------------------------------------------------------- +class CBaseMenu : public vgui::Frame +{ + DECLARE_CLASS_SIMPLE( CBaseMenu, vgui::Frame ); + +public: + CBaseMenu( vgui::Panel *pParent, const char *pPanelName ); + virtual ~CBaseMenu(); + + // Commands + virtual void OnCommand( const char *pCommand ); + virtual void OnKeyCodeTyped( vgui::KeyCode code ); + +private: +}; + +#endif // BASEMENU_H + diff --git a/app/legion/gamemanager.cpp b/app/legion/gamemanager.cpp new file mode 100644 index 0000000..a7934db --- /dev/null +++ b/app/legion/gamemanager.cpp @@ -0,0 +1,342 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: List of game managers to update +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#include "gamemanager.h" +#include "tier0/icommandline.h" + +// FIXME: REMOVE (for Sleep) +#include <windows.h> + + +//----------------------------------------------------------------------------- +// globals +//----------------------------------------------------------------------------- +int IGameManager::m_nFrameNumber = 0; +bool IGameManager::m_bStopRequested = false; +bool IGameManager::m_bIsRunning = false; +bool IGameManager::m_bIsInitialized = false; +bool IGameManager::m_bLevelStartRequested = false; +bool IGameManager::m_bLevelShutdownRequested = false; +float IGameManager::m_flCurrentTime = 0.0f; +float IGameManager::m_flLastTime = 0.0f; +LevelState_t IGameManager::m_LevelState = NOT_IN_LEVEL; + +CUtlVector< IGameManager* > IGameManager::m_GameManagers; + + +//----------------------------------------------------------------------------- +// Adds a system to the list of systems to run +//----------------------------------------------------------------------------- +void IGameManager::Add( IGameManager* pSys ) +{ + Assert( !m_bIsRunning ); + m_GameManagers.AddToTail( pSys ); +} + + +//----------------------------------------------------------------------------- +// Removes a system from the list of systems to update +//----------------------------------------------------------------------------- +void IGameManager::Remove( IGameManager* pSys ) +{ + Assert( !m_bIsRunning ); + m_GameManagers.FindAndRemove( pSys ); +} + + +//----------------------------------------------------------------------------- +// Removes *all* systems from the list of systems to update +//----------------------------------------------------------------------------- +void IGameManager::RemoveAll( ) +{ + m_GameManagers.RemoveAll(); +} + + +//----------------------------------------------------------------------------- +// Invokes a method on all installed game systems in proper order +//----------------------------------------------------------------------------- +void IGameManager::InvokeMethod( GameManagerFunc_t f ) +{ + int i; + int nCount = m_GameManagers.Count(); + for ( i = 0; i < nCount; ++i ) + { + (m_GameManagers[i]->*f)(); + } +} + +void IGameManager::InvokeMethodReverseOrder( GameManagerFunc_t f ) +{ + int i; + int nCount = m_GameManagers.Count(); + for ( i = nCount; --i >= 0; ) + { + (m_GameManagers[i]->*f)(); + } +} + +bool IGameManager::InvokeMethod( GameManagerInitFunc_t f ) +{ + int i; + int nCount = m_GameManagers.Count(); + for ( i = 0; i < nCount; ++i ) + { + if ( !(m_GameManagers[i]->*f)() ) + return false; + } + return true; +} + +LevelRetVal_t IGameManager::InvokeLevelMethod( GameManagerLevelFunc_t f, bool bFirstCall ) +{ + LevelRetVal_t nRetVal = FINISHED; + int i; + int nCount = m_GameManagers.Count(); + for ( i = 0; i < nCount; ++i ) + { + LevelRetVal_t val = (m_GameManagers[i]->*f)( bFirstCall ); + if ( val == FAILED ) + return FAILED; + if ( val == MORE_WORK ) + { + nRetVal = MORE_WORK; + } + } + return nRetVal; +} + +LevelRetVal_t IGameManager::InvokeLevelMethodReverseOrder( GameManagerLevelFunc_t f, bool bFirstCall ) +{ + LevelRetVal_t nRetVal = FINISHED; + int i; + int nCount = m_GameManagers.Count(); + for ( i = 0; i < nCount; ++i ) + { + LevelRetVal_t val = ( m_GameManagers[i]->*f )( bFirstCall ); + if ( val == FAILED ) + { + nRetVal = FAILED; + } + if ( ( val == MORE_WORK ) && ( nRetVal != FAILED ) ) + { + nRetVal = MORE_WORK; + } + } + return nRetVal; +} + + +//----------------------------------------------------------------------------- +// Init, shutdown game system +//----------------------------------------------------------------------------- +bool IGameManager::InitAllManagers() +{ + m_nFrameNumber = 0; + if ( !InvokeMethod( &IGameManager::Init ) ) + return false; + + m_bIsInitialized = true; + return true; +} + +void IGameManager::ShutdownAllManagers() +{ + if ( m_bIsInitialized ) + { + InvokeMethodReverseOrder( &IGameManager::Shutdown ); + m_bIsInitialized = false; + } +} + + +//----------------------------------------------------------------------------- +// Updates the state machine related to loading levels +//----------------------------------------------------------------------------- +void IGameManager::UpdateLevelStateMachine() +{ + // Do we want to switch into the level shutdown state? + bool bFirstLevelShutdownFrame = false; + if ( m_bLevelShutdownRequested ) + { + if ( m_LevelState != LOADING_LEVEL ) + { + m_bLevelShutdownRequested = false; + } + if ( m_LevelState == IN_LEVEL ) + { + m_LevelState = SHUTTING_DOWN_LEVEL; + bFirstLevelShutdownFrame = true; + } + } + + // Perform level shutdown + if ( m_LevelState == SHUTTING_DOWN_LEVEL ) + { + LevelRetVal_t val = InvokeLevelMethodReverseOrder( &IGameManager::LevelShutdown, bFirstLevelShutdownFrame ); + if ( val != MORE_WORK ) + { + m_LevelState = NOT_IN_LEVEL; + } + } + + // Do we want to switch into the level startup state? + bool bFirstLevelStartFrame = false; + if ( m_bLevelStartRequested ) + { + if ( m_LevelState != SHUTTING_DOWN_LEVEL ) + { + m_bLevelStartRequested = false; + } + if ( m_LevelState == NOT_IN_LEVEL ) + { + m_LevelState = LOADING_LEVEL; + bFirstLevelStartFrame = true; + } + } + + // Perform level load + if ( m_LevelState == LOADING_LEVEL ) + { + LevelRetVal_t val = InvokeLevelMethod( &IGameManager::LevelInit, bFirstLevelStartFrame ); + if ( val == FAILED ) + { + m_LevelState = NOT_IN_LEVEL; + } + else if ( val == FINISHED ) + { + m_LevelState = IN_LEVEL; + } + } +} + + +//----------------------------------------------------------------------------- +// Runs the main loop. +//----------------------------------------------------------------------------- +void IGameManager::Start() +{ + Assert( !m_bIsRunning && m_bIsInitialized ); + + m_bIsRunning = true; + m_bStopRequested = false; + + // This option is useful when running the app twice on the same machine + // It makes the 2nd instance of the app run a lot faster + bool bPlayNice = ( CommandLine()->CheckParm( "-yieldcycles" ) != 0 ); + + float flStartTime = m_flCurrentTime = m_flLastTime = Plat_FloatTime(); + int nFramesSimulated = 0; + int nCount = m_GameManagers.Count(); + while ( !m_bStopRequested ) + { + UpdateLevelStateMachine(); + + m_flLastTime = m_flCurrentTime; + m_flCurrentTime = Plat_FloatTime(); + int nSimulationFramesNeeded = 1 + (int)( ( m_flCurrentTime - flStartTime ) / TICK_INTERVAL ); + while( nSimulationFramesNeeded > nFramesSimulated ) + { + for ( int i = 0; i < nCount; ++i ) + { + if ( m_GameManagers[i]->PerformsSimulation() ) + { + m_GameManagers[i]->Update(); + } + } + ++m_nFrameNumber; + ++nFramesSimulated; + } + + // Always do I/O related managers regardless of framerate + for ( int i = 0; i < nCount; ++i ) + { + if ( !m_GameManagers[i]->PerformsSimulation() ) + { + m_GameManagers[i]->Update(); + } + } + + if ( bPlayNice ) + { + Sleep( 1 ); + } + } + + m_bIsRunning = false; +} + + +//----------------------------------------------------------------------------- +// Stops the main loop at the next appropriate time +//----------------------------------------------------------------------------- +void IGameManager::Stop() +{ + if ( m_bIsRunning ) + { + m_bStopRequested = true; + } +} + + +//----------------------------------------------------------------------------- +// Returns the current frame number +//----------------------------------------------------------------------------- +int IGameManager::FrameNumber() +{ + return m_nFrameNumber; +} + +float IGameManager::CurrentSimulationTime() +{ + return m_nFrameNumber * TICK_INTERVAL; +} + +float IGameManager::SimulationDeltaTime() +{ + return TICK_INTERVAL; +} + + +//----------------------------------------------------------------------------- +// Used in rendering +//----------------------------------------------------------------------------- +float IGameManager::CurrentTime() +{ + return m_flCurrentTime; +} + +float IGameManager::DeltaTime() +{ + return m_flCurrentTime - m_flLastTime; +} + + +//----------------------------------------------------------------------------- +// Returns the current level state +//----------------------------------------------------------------------------- +LevelState_t IGameManager::GetLevelState() +{ + return m_LevelState; +} + + +//----------------------------------------------------------------------------- +// Start loading a level +//----------------------------------------------------------------------------- +void IGameManager::StartNewLevel() +{ + m_bLevelShutdownRequested = true; + m_bLevelStartRequested = true; +} + +void IGameManager::ShutdownLevel() +{ + m_bLevelShutdownRequested = true; +} + diff --git a/app/legion/gamemanager.h b/app/legion/gamemanager.h new file mode 100644 index 0000000..845d7d5 --- /dev/null +++ b/app/legion/gamemanager.h @@ -0,0 +1,160 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#ifndef GAMEMANAGER_H +#define GAMEMANAGER_H +#ifdef _WIN32 +#pragma once +#endif + +#include "tier1/utlvector.h" + + +//----------------------------------------------------------------------------- +// State we are in +//----------------------------------------------------------------------------- +enum LevelState_t +{ + NOT_IN_LEVEL = 0, + LOADING_LEVEL, + IN_LEVEL, + SHUTTING_DOWN_LEVEL, +}; + + +//----------------------------------------------------------------------------- +// State we are in +//----------------------------------------------------------------------------- +enum LevelRetVal_t +{ + FAILED = 0, + MORE_WORK, + FINISHED, +}; + + +//----------------------------------------------------------------------------- +// Tick interval +//----------------------------------------------------------------------------- +#define TICK_INTERVAL 0.015f + + +//----------------------------------------------------------------------------- +// Game managers are singleton objects in the game code responsible for various tasks +// The order in which the server systems appear in this list are the +// order in which they are initialized and updated. They are shut down in +// reverse order from which they are initialized. +//----------------------------------------------------------------------------- +abstract_class IGameManager +{ +public: + // GameManagers are expected to implement these methods. + virtual bool Init() = 0; + virtual LevelRetVal_t LevelInit( bool bFirstCall ) = 0; + virtual void Update( ) = 0; + virtual LevelRetVal_t LevelShutdown( bool bFirstCall ) = 0; + virtual void Shutdown() = 0; + + // Called during game save + virtual void OnSave() = 0; + + // Called during game restore + virtual void OnRestore() = 0; + + // This this game manager involved in I/O or simulation? + virtual bool PerformsSimulation() = 0; + + // Add, remove game managers + static void Add( IGameManager* pSys ); + static void Remove( IGameManager* pSys ); + static void RemoveAll( ); + + // Init, shutdown game managers + static bool InitAllManagers(); + static void ShutdownAllManagers(); + + // Start, stop running game managers + static void Start (); + static void Stop (); + static int FrameNumber(); + + // Used in simulation + static float CurrentSimulationTime(); + static float SimulationDeltaTime(); + + // Used in rendering + static float CurrentTime(); + static float DeltaTime(); + + // Start loading a level + static void StartNewLevel(); + static void ShutdownLevel(); + static LevelState_t GetLevelState(); + +protected: + // Updates the state machine related to loading levels + static void UpdateLevelStateMachine(); + + virtual ~IGameManager() {} + + typedef LevelRetVal_t (IGameManager::*GameManagerLevelFunc_t)( bool bFirstCall ); + typedef bool (IGameManager::*GameManagerInitFunc_t)(); + typedef void (IGameManager::*GameManagerFunc_t)(); + + // Used to invoke a method of all added game managers in order + static void InvokeMethod( GameManagerFunc_t f ); + static void InvokeMethodReverseOrder( GameManagerFunc_t f ); + static bool InvokeMethod( GameManagerInitFunc_t f ); + static LevelRetVal_t InvokeLevelMethod( GameManagerLevelFunc_t f, bool bFirstCall ); + static LevelRetVal_t InvokeLevelMethodReverseOrder( GameManagerLevelFunc_t f, bool bFirstCall ); + + static bool m_bLevelShutdownRequested; + static bool m_bLevelStartRequested; + static bool m_bStopRequested; + static CUtlVector< IGameManager* > m_GameManagers; + static bool m_bIsRunning; + static bool m_bIsInitialized; + static int m_nFrameNumber; + static float m_flCurrentTime; + static float m_flLastTime; + static LevelState_t m_LevelState; +}; + + +//----------------------------------------------------------------------------- +// Default decorator base-class for IGameManager +//----------------------------------------------------------------------------- +template< class BaseClass = IGameManager > +class CGameManager : public BaseClass +{ +public: + virtual ~CGameManager(); + + // GameManagers are expected to implement these methods. + // NOTE: If Init or LevelInit fail, they are expected to call + virtual bool Init() { return true; } + virtual LevelRetVal_t LevelInit( bool bFirstCall ) { return FINISHED; } + virtual void Update( ) {} + virtual LevelRetVal_t LevelShutdown( bool bFirstCall ) { return FINISHED; } + virtual void Shutdown() {} + virtual void OnSave() {} + virtual void OnRestore() {} + virtual bool PerformsSimulation() { return false; } +}; + + +//----------------------------------------------------------------------------- +// Automatically remove the game system if it gets deleted. +//----------------------------------------------------------------------------- +template< class BaseClass > +inline CGameManager< BaseClass >::~CGameManager() +{ + Remove( this ); +} + + +#endif // GAMEMANAGER_H diff --git a/app/legion/heightfield.cpp b/app/legion/heightfield.cpp new file mode 100644 index 0000000..9daf046 --- /dev/null +++ b/app/legion/heightfield.cpp @@ -0,0 +1,276 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Heightfield class +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#include "heightfield.h" +#include "materialsystem/imaterial.h" +#include "legion.h" +#include "materialsystem/imaterialsystem.h" +#include "materialsystem/imesh.h" +#include "tier2/tier2.h" +#include "tier2/utlstreambuffer.h" +#include "bitmap/bitmap.h" +#include "bitmap/psd.h" +#include "tier1/KeyValues.h" + + +//----------------------------------------------------------------------------- +// Utility macro +//----------------------------------------------------------------------------- +#define HEIGHT( _x, _y ) m_pHeightField[ ( (_y) << m_nPowX ) + (_x) ] +#define ROW( _y ) &m_pHeightField[ (_y) << m_nPowX ] + + +//----------------------------------------------------------------------------- +// Constructor, destructor +//----------------------------------------------------------------------------- +CHeightField::CHeightField( int nPowX, int nPowY, int nPowScale ) +{ + m_nPowX = nPowX; + m_nPowY = nPowY; + m_nPowScale = nPowScale; + m_nWidth = ( 1 << nPowX ); + m_nHeight = ( 1 << nPowY ); + m_nScale = ( 1 << nPowScale ); + m_flOOScale = 1.0f / m_nScale; + m_pHeightField = (float*)malloc( m_nWidth * m_nHeight * sizeof(float) ); + memset( m_pHeightField, 0, m_nWidth * m_nHeight * sizeof(float) ); + + KeyValues *pKeyValues = new KeyValues( "Wireframe" ); + pKeyValues->SetInt( "$nocull", 1 ); + m_Material.Init( "__Temp", pKeyValues ); +} + +CHeightField::~CHeightField() +{ + free( m_pHeightField ); +} + + +//----------------------------------------------------------------------------- +// Bilinearly filters a sample out of a bitmap at a particular (x,y) +// NOTE: x,y are not normalized and are expected to go in the range of (0->w-1, 0->h-1) +//----------------------------------------------------------------------------- +float BilerpBitmap( Bitmap_t &bitmap, float x, float y ) +{ + Assert( bitmap.m_ImageFormat == IMAGE_FORMAT_RGBA8888 ); + + float w = (float)bitmap.m_nWidth; + float h = (float)bitmap.m_nHeight; + + // Clamp to a valid range + x = clamp( x, 0, w - 1.0f ); + y = clamp( y, 0, h - 1.0f ); + + // pick bilerp coordinates + int i0 = (int)floor( x ); + int i1 = i0 + 1; + int j0 = (int)floor( y ); + int j1 = j0 + 1; + if ( i1 >= bitmap.m_nWidth ) + { + i1 = bitmap.m_nWidth - 1; + } + if ( j1 >= bitmap.m_nHeight ) + { + j1 = bitmap.m_nHeight - 1; + } + + float fx = x - i0; + float fy = y - j0; + + RGBA8888_t* pPixel00 = (RGBA8888_t*)bitmap.GetPixel( i0, j0 ); + RGBA8888_t* pPixel10 = (RGBA8888_t*)bitmap.GetPixel( i1, j0 ); + RGBA8888_t* pPixel01 = (RGBA8888_t*)bitmap.GetPixel( i0, j1 ); + RGBA8888_t* pPixel11 = (RGBA8888_t*)bitmap.GetPixel( i1, j1 ); + + float v00 = pPixel00->r / 255.0f; + float v10 = pPixel10->r / 255.0f; + float v01 = pPixel01->r / 255.0f; + float v11 = pPixel11->r / 255.0f; + + // do the bilerp + return (1-fx)*(1-fy)*v00 + fx*(1-fy)*v10 + (1-fx)*fy*v01 + fx*fy*v11; +} + + +//----------------------------------------------------------------------------- +// Loads the heightfield from a file +//----------------------------------------------------------------------------- +bool CHeightField::LoadHeightFromFile( const char *pFileName ) +{ + Bitmap_t bitmap; + CUtlStreamBuffer buf( pFileName, "GAME", CUtlBuffer::READ_ONLY ); + if ( IsPSDFile( buf ) ) + { + if ( !PSDReadFileRGBA8888( buf, bitmap ) ) + return false; + } + + // map from height field into map, ensuring corner pixel centers line up + // hfx -> mapx: 0 -> 0.5, hfw-1 -> mapw-0.5 + // x (mapw - 1)/(hfw - 1) + 0.5 + // mapx -> worldx: 0 -> 0, mapw -> worldw + float fx = (float)( bitmap.m_nWidth - 1) / (float)( m_nWidth - 1 ); + float fy = (float)( bitmap.m_nHeight - 1) / (float)( m_nHeight - 1 ); + + for( int i = 0; i < m_nHeight; ++i ) + { + float *pRow = ROW( i ); + for( int j = 0; j < m_nWidth; ++j, ++pRow ) + { + *pRow = 50.0f * BilerpBitmap( bitmap, i * fx, j * fy ); + } + } + return true; +} + + +//----------------------------------------------------------------------------- +// Returns the height at a particular point +//----------------------------------------------------------------------------- +float CHeightField::GetHeight( float x, float y ) +{ + x *= m_flOOScale; + y *= m_flOOScale; + + int gx = (int)floor( x ); + int gy = (int)floor( y ); + x -= gx; + y -= gy; + + // Check for out of range + if ( gx < -1 || gy < -1 || gx >= m_nWidth || gy >= m_nHeight ) + return 0.0f; + + float h00 = ( gx >= 0 && gy >= 0 ) ? HEIGHT(gx , gy ) : 0.0f; + float h01 = ( gx < (m_nWidth-1) && gy >= 0 ) ? HEIGHT(gx+1, gy ) : 0.0f; + float h10 = ( gx >= 0 && gy < (m_nHeight-1) ) ? HEIGHT(gx , gy+1) : 0.0f; + float h11 = ( gx<(m_nWidth-1) && gy<(m_nHeight-1) ) ? HEIGHT(gx+1, gy+1) : 0.0f; + + // This fixup accounts for the triangularization of the mesh + if (x > y) + { + h10 = h00 + h11 - h01; + } + else + { + h01 = h00 + h11 - h10; + } + + // Bilinear filter + float h0 = h00 + ( h01 - h00 ) * x; + float h1 = h10 + ( h11 - h10 ) * x; + float h = h0 + (h1-h0)*y; + + return h; +} + + +//----------------------------------------------------------------------------- +// Returns the height + slope at a particular point +//----------------------------------------------------------------------------- +float CHeightField::GetHeightAndSlope( float x, float y, float *dx, float *dy ) +{ + x *= m_flOOScale; + y *= m_flOOScale; + + int gx = (int)floor(x); + int gy = (int)floor(y); + x -= gx; + y -= gy; + + if ( gx < -1 || gy < -1 || gx >= m_nWidth || gy >= m_nHeight ) + { + *dx = 0; + *dy = 0; + return 0.0f; + } + + float h00 = ( gx >= 0 && gy >= 0 ) ? HEIGHT(gx , gy ) : 0.0f; + float h01 = ( gx < (m_nWidth-1) && gy >= 0 ) ? HEIGHT(gx+1, gy ) : 0.0f; + float h10 = ( gx >= 0 && gy < (m_nHeight-1) ) ? HEIGHT(gx , gy+1) : 0.0f; + float h11 = ( gx<(m_nWidth-1) && gy<(m_nHeight-1) ) ? HEIGHT(gx+1, gy+1) : 0.0f; + + if (x > y) + { + h10 = h00 + h11 - h01; + } + else + { + h01 = h00 + h11 - h10; + } + + *dx = ( h01 - h00 ) * m_flOOScale; + *dy = ( h10 - h00 ) * m_flOOScale; + + // Bilinear filter + float h0 = h00 + ( h01 - h00 ) * x; + float h1 = h10 + ( h11 - h10 ) * x; + float h = h0 + ( h1 - h0 )* y; + + return h; +} + + +//----------------------------------------------------------------------------- +// Draws the height field +//----------------------------------------------------------------------------- +void CHeightField::Draw( ) +{ + int nVertexCount = m_nWidth * m_nHeight; + int nIndexCount = 6 * ( m_nWidth - 1 ) * ( m_nHeight - 1 ); + + float flOOTexWidth = 1.0f / m_Material->GetMappingWidth(); + float flOOTexHeight = 1.0f / m_Material->GetMappingHeight(); + float iu = 0.5f * flOOTexWidth; + float iv = 1.0f - ( 0.5f * flOOTexHeight ); + float du = ( 1.0f - flOOTexWidth ) / ( m_nWidth - 1 ); + float dv = -( 1.0f - flOOTexHeight ) / ( m_nHeight - 1 ); + + CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); + pRenderContext->Bind( m_Material ); + IMesh *pMesh = pRenderContext->GetDynamicMesh( ); + + CMeshBuilder meshBuilder; + meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, nVertexCount, nIndexCount ); + + // Deal with vertices + float v = iv; + float y = 0.0f; + for ( int i = 0; i < m_nHeight; ++i, y += m_nScale, v += dv ) + { + float u = iu; + float x = 0.0f; + for ( int j = 0; j < m_nWidth; ++j, x += m_nScale, u += du ) + { + meshBuilder.Position3f( x, y, HEIGHT( j, i ) ); + meshBuilder.TexCoord2f( 0, u, v ); + meshBuilder.AdvanceVertex(); + } + } + + // Deal with indices + for ( int i = 0; i < (m_nHeight - 1); ++i ) + { + int nRow0 = m_nWidth * i; + int nRow1 = nRow0 + m_nWidth; + for ( int j = 0; j < (m_nWidth - 1); ++j ) + { + meshBuilder.FastIndex( nRow0+j ); + meshBuilder.FastIndex( nRow0+j+1 ); + meshBuilder.FastIndex( nRow1+j+1 ); + + meshBuilder.FastIndex( nRow0+j ); + meshBuilder.FastIndex( nRow1+j+1 ); + meshBuilder.FastIndex( nRow1+j ); + } + } + + meshBuilder.End(); + pMesh->Draw(); +} diff --git a/app/legion/heightfield.h b/app/legion/heightfield.h new file mode 100644 index 0000000..5267109 --- /dev/null +++ b/app/legion/heightfield.h @@ -0,0 +1,77 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Heightfield class +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#ifndef HEIGHTFIELD_H +#define HEIGHTFIELD_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "materialsystem/MaterialSystemUtil.h" + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CMeshBuilder; + + +//----------------------------------------------------------------------------- +// Definition of a heightfield +//----------------------------------------------------------------------------- +class CHeightField +{ +public: + CHeightField( int nPowX, int nPowY, int nPowScale ); + ~CHeightField(); + + // Loads the heights from a file + bool LoadHeightFromFile( const char *pFileName ); + + // Returns the max range of x, y + int GetWidth(); + int GetHeight(); + + // Returns the height of the field at a paticular (x,y) + float GetHeight( float x, float y ); + float GetHeightAndSlope( float x, float y, float *dx, float *dy ); + + // Draws the heightfield + void Draw( ); + +private: + int m_nPowX; + int m_nPowY; + int m_nWidth; + int m_nHeight; + int m_nScale; + int m_nPowScale; + float m_flOOScale; + float *m_pHeightField; + + CMaterialReference m_Material; + CTextureReference m_Texture; +}; + + +//----------------------------------------------------------------------------- +// Returns the max range of x, y (for use in GetHeight) +//----------------------------------------------------------------------------- +inline int CHeightField::GetWidth() +{ + return m_nWidth << m_nPowScale; +} + +inline int CHeightField::GetHeight() +{ + return m_nHeight << m_nPowScale; +} + + +#endif // HEIGHTFIELD_H diff --git a/app/legion/hostgamemenu.cpp b/app/legion/hostgamemenu.cpp new file mode 100644 index 0000000..858bbe8 --- /dev/null +++ b/app/legion/hostgamemenu.cpp @@ -0,0 +1,201 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: The menu that allows a player to start a game +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#include "menumanager.h" +#include "basemenu.h" +#include "vgui_controls/listpanel.h" +#include "vgui_controls/textentry.h" +#include "vgui_controls/Button.h" +#include "tier1/KeyValues.h" +#include "networkmanager.h" +#include "legion.h" +#include "inetworkmessagelistener.h" +#include "networkmessages.h" +#include "tier2/tier2.h" + + +//----------------------------------------------------------------------------- +// Constructor, destructor +//----------------------------------------------------------------------------- +class CHostGameMenu : public CBaseMenu, public INetworkMessageListener +{ + DECLARE_CLASS_SIMPLE( CHostGameMenu, CBaseMenu ); + +public: + CHostGameMenu( vgui::Panel *pParent, const char *pPanelName ); + virtual ~CHostGameMenu(); + + // Called when a particular network message occurs + virtual void OnNetworkMessage( NetworkMessageRoute_t route, INetworkMessage *pNetworkMessage ); + virtual void OnCommand( const char *pCommand ); + + MESSAGE_FUNC( OnTextNewLine, "TextNewLine" ); + +private: + vgui::ListPanel *m_pPlayerList; + vgui::TextEntry *m_pServerIP; + vgui::TextEntry *m_pServerName; + vgui::TextEntry *m_pChatLog; + vgui::TextEntry *m_pChatEntry; + vgui::TextEntry *m_pPlayerName; + vgui::Button *m_pStartGame; +}; + + +//----------------------------------------------------------------------------- +// Hooks the menu into the menu system +//----------------------------------------------------------------------------- +REGISTER_MENU( "HostGameMenu", CHostGameMenu ); + + +//----------------------------------------------------------------------------- +// Sort by player name +//----------------------------------------------------------------------------- +static int __cdecl PlayerNameSortFunc( vgui::ListPanel *pPanel, const vgui::ListPanelItem &item1, const vgui::ListPanelItem &item2 ) +{ + const char *string1 = item1.kv->GetString("player"); + const char *string2 = item2.kv->GetString("player"); + return stricmp( string1, string2 ); +} + + +//----------------------------------------------------------------------------- +// Constructor, destructor +//----------------------------------------------------------------------------- +CHostGameMenu::CHostGameMenu( vgui::Panel *pParent, const char *pPanelName ) : + BaseClass( pParent, pPanelName ) +{ + m_pPlayerList = new vgui::ListPanel( this, "PlayerList" ); + m_pPlayerList->AddColumnHeader( 0, "color", "Color", 52, 0 ); + m_pPlayerList->AddColumnHeader( 1, "player", "Player Name", 128, 0 ); + m_pPlayerList->SetSelectIndividualCells( false ); + m_pPlayerList->SetEmptyListText( "No Players" ); + m_pPlayerList->SetDragEnabled( false ); + m_pPlayerList->AddActionSignalTarget( this ); + m_pPlayerList->SetSortFunc( 0, PlayerNameSortFunc ); + m_pPlayerList->SetSortFunc( 1, PlayerNameSortFunc ); + m_pPlayerList->SetSortColumn( 1 ); + + m_pServerIP = new vgui::TextEntry( this, "ServerIP" ); + m_pServerName = new vgui::TextEntry( this, "ServerName" ); + + m_pPlayerName = new vgui::TextEntry( this, "PlayerName" ); + m_pPlayerName->SetMultiline( false ); + + m_pChatLog = new vgui::TextEntry( this, "ChatLog" ); + m_pChatLog->SetMultiline( true ); + m_pChatLog->SetVerticalScrollbar( true ); + + m_pChatEntry = new vgui::TextEntry( this, "ChatEntry" ); + m_pChatEntry->AddActionSignalTarget( this ); + m_pChatEntry->SetMultiline( false ); + m_pChatEntry->SendNewLine( true ); + + m_pStartGame = new vgui::Button( this, "StartGame", "Start Game", this ); + + LoadControlSettings( "resource/hostgamemenu.res", "GAME" ); + + m_pPlayerName->SetText( "Unnamed" ); + + if ( !g_pNetworkManager->HostGame() ) + { + m_pStartGame->SetEnabled( false ); + return; + } + + m_pServerIP->SetText( g_pNetworkSystem->GetLocalAddress() ); + m_pServerName->SetText( g_pNetworkSystem->GetLocalHostName() ); + + g_pNetworkManager->AddListener( NETWORK_MESSAGE_SERVER_TO_CLIENT, LEGION_NETMESSAGE_GROUP, CHAT_MESSAGE, this ); + g_pNetworkManager->AddListener( NETWORK_MESSAGE_CLIENT_TO_SERVER, LEGION_NETMESSAGE_GROUP, CHAT_MESSAGE, this ); +} + +CHostGameMenu::~CHostGameMenu() +{ + g_pNetworkManager->RemoveListener( NETWORK_MESSAGE_SERVER_TO_CLIENT, LEGION_NETMESSAGE_GROUP, CHAT_MESSAGE, this ); + g_pNetworkManager->RemoveListener( NETWORK_MESSAGE_CLIENT_TO_SERVER, LEGION_NETMESSAGE_GROUP, CHAT_MESSAGE, this ); +} + + +//----------------------------------------------------------------------------- +// Called when a particular network message occurs +//----------------------------------------------------------------------------- +void CHostGameMenu::OnNetworkMessage( NetworkMessageRoute_t route, INetworkMessage *pNetworkMessage ) +{ + if ( route == NETWORK_MESSAGE_SERVER_TO_CLIENT ) + { + CNetworkMessage_Chat *pChatMsg = static_cast<CNetworkMessage_Chat*>( pNetworkMessage ); + m_pChatLog->InsertString( pChatMsg->m_Message.Get() ); + m_pChatLog->InsertChar( '\n' ); + } + else + { + // If this message was received from an client, broadcast it to all other clients + g_pNetworkManager->BroadcastServerToClientMessage( pNetworkMessage ); + } +} + + +//----------------------------------------------------------------------------- +// Called when the enter key is hit in the chat entry window +//----------------------------------------------------------------------------- +void CHostGameMenu::OnTextNewLine() +{ + CNetworkMessage_Chat msg; + + int nLen = m_pChatEntry->GetTextLength(); + if ( nLen > 0 ) + { + char *pText = (char*)_alloca( (nLen+1) * sizeof(char) ); + m_pChatEntry->GetText( pText, nLen+1 ); + m_pChatEntry->SetText( "" ); + + int nLenName = m_pPlayerName->GetTextLength(); + char *pName = (char*)_alloca( (nLenName+8) * sizeof(char) ); + if ( nLenName == 0 ) + { + nLenName = 7; + Q_strcpy( pName, "unnamed" ); + } + else + { + m_pPlayerName->GetText( pName, nLenName+1 ); + } + + int nTotalLen = nLen + nLenName; + msg.m_Message.SetLength( nTotalLen + 3 ); + Q_snprintf( msg.m_Message.Get(), nTotalLen+3, "[%s] %s", pName, pText ); + + g_pNetworkManager->PostClientToServerMessage( &msg ); + } +} + + +//----------------------------------------------------------------------------- +// Called when the enter key is hit in the chat entry window +//----------------------------------------------------------------------------- +void CHostGameMenu::OnCommand( const char *pCommand ) +{ + if ( !Q_stricmp( pCommand, "CancelHostGame" ) ) + { + g_pNetworkManager->StopHostingGame(); + g_pMenuManager->PopMenu(); + return; + } + + if ( !Q_stricmp( pCommand, "StartGame" ) ) + { + IGameManager::StartNewLevel(); + g_pMenuManager->PopAllMenus(); + return; + } + + BaseClass::OnCommand( pCommand ); +} + + diff --git a/app/legion/inetworkmessagelistener.h b/app/legion/inetworkmessagelistener.h new file mode 100644 index 0000000..7aa27c3 --- /dev/null +++ b/app/legion/inetworkmessagelistener.h @@ -0,0 +1,47 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: The main manager of the networking code in the game +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#ifndef INETWORKMESSAGELISTENER_H +#define INETWORKMESSAGELISTENER_H + +#ifdef _WIN32 +#pragma once +#endif + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class INetworkMessage; + + +//----------------------------------------------------------------------------- +// Message route type +//----------------------------------------------------------------------------- +enum NetworkMessageRoute_t +{ + NETWORK_MESSAGE_SERVER_TO_CLIENT = 0, + NETWORK_MESSAGE_CLIENT_TO_SERVER, + + NETWORK_MESSAGE_ROUTE_COUNT, +}; + + +//----------------------------------------------------------------------------- +// Interface used to listen to network messages +//----------------------------------------------------------------------------- +abstract_class INetworkMessageListener +{ +public: + // Called when a particular network message occurs + virtual void OnNetworkMessage( NetworkMessageRoute_t route, INetworkMessage *pNetworkMessage ) = 0; +}; + + +#endif // INETWORKMESSAGELISTENER_H + diff --git a/app/legion/inputmanager.cpp b/app/legion/inputmanager.cpp new file mode 100644 index 0000000..716f7a0 --- /dev/null +++ b/app/legion/inputmanager.cpp @@ -0,0 +1,311 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: The main manager of the UI +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#include "inputmanager.h" +#include "legion.h" +#include "uimanager.h" +#include "inputsystem/iinputsystem.h" +#include "tier2/tier2.h" +#include "tier1/convar.h" + + +//----------------------------------------------------------------------------- +// Singleton accessor +//----------------------------------------------------------------------------- +static CInputManager s_InputManager; +extern CInputManager *g_pInputManager = &s_InputManager; + + +//----------------------------------------------------------------------------- +// Initialization +//----------------------------------------------------------------------------- +bool CInputManager::Init() +{ + // FIXME: Read keybindings from a file + m_KeyBindings.SetBinding( "w", "+forward" ); + m_KeyBindings.SetBinding( "s", "+back" ); + m_KeyBindings.SetBinding( "`", "toggleconsole" ); + m_ButtonUpToEngine.ClearAll(); + return true; +} + + +//----------------------------------------------------------------------------- +// Add a command into the command queue +//----------------------------------------------------------------------------- +void CInputManager::AddCommand( const char *pCommand ) +{ + m_CommandBuffer.AddText( pCommand ); +} + + +//----------------------------------------------------------------------------- +// FIXME! This is necessary only because of an artifact of how ConCommands used to work +//----------------------------------------------------------------------------- +static ConCommand *FindNamedCommand( char const *name ) +{ + // look through the command list for all matches + ConCommandBase const *cmd = (ConCommandBase const *)vgui::icvar()->GetCommands(); + while (cmd) + { + if (!Q_strcmp( name, cmd->GetName() ) ) + { + if ( cmd->IsCommand() ) + { + return ( ConCommand * )cmd; + } + } + cmd = cmd->GetNext(); + } + return NULL; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CInputManager::PrintConCommandBaseDescription( const ConCommandBase *pVar ) +{ + bool bMin, bMax; + float fMin, fMax; + const char *pStr; + + Assert( pVar ); + + Color clr; + clr.SetColor( 255, 100, 100, 255 ); + + if ( !pVar->IsCommand() ) + { + ConVar *var = ( ConVar * )pVar; + + bMin = var->GetMin( fMin ); + bMax = var->GetMax( fMax ); + + char const *value = NULL; + char tempVal[ 32 ]; + + if ( var->IsBitSet( FCVAR_NEVER_AS_STRING ) ) + { + value = tempVal; + + if ( fabs( (float)var->GetInt() - var->GetFloat() ) < 0.000001 ) + { + Q_snprintf( tempVal, sizeof( tempVal ), "%d", var->GetInt() ); + } + else + { + Q_snprintf( tempVal, sizeof( tempVal ), "%f", var->GetFloat() ); + } + } + else + { + value = var->GetString(); + } + + if ( value ) + { + Msg( "\"%s\" = \"%s\"", var->GetName(), value ); + + if ( Q_stricmp( value, var->GetDefault() ) ) + { + Msg( " ( def. \"%s\" )", var->GetDefault() ); + } + } + + if ( bMin ) + { + Msg( " min. %f", fMin ); + } + if ( bMax ) + { + Msg( " max. %f", fMax ); + } + + Msg( "\n" ); + } + else + { + ConCommand *var = ( ConCommand * )pVar; + + Msg( "\"%s\"\n", var->GetName() ); + } + +// PrintConCommandBaseFlags( pVar ); + + pStr = pVar->GetHelpText(); + if ( pStr && pStr[0] ) + { + Msg( " - %s\n", pStr ); + } +} + + +//----------------------------------------------------------------------------- +// Per-frame update +//----------------------------------------------------------------------------- +void CInputManager::ProcessCommands( ) +{ + m_CommandBuffer.BeginProcessingCommands( 1 ); + while ( m_CommandBuffer.DequeueNextCommand() ) + { + const CCommand& args = m_CommandBuffer.GetCommand(); + const ConCommandBase *pCommand = FindNamedCommand( args[ 0 ] ); + if ( pCommand && pCommand->IsCommand() ) + { + // FIXME: Um... yuck!?! + ConCommand *pConCommand = const_cast<ConCommand*>( static_cast<const ConCommand*>( pCommand ) ); + pConCommand->Dispatch( args ); + continue; + } + + ConVar *pConVar = g_pCVar->FindVar( args[0] ); + if ( !pConVar ) + continue; + + // perform a variable print or set + if ( args.ArgC() == 1 ) + { + PrintConCommandBaseDescription( pConVar ); + continue; + } + + // Note that we don't want the tokenized list, send down the entire string + // except for surrounding quotes + char remaining[1024]; + const char *pArgS = args.ArgS(); + int nLen = Q_strlen( pArgS ); + bool bIsQuoted = pArgS[0] == '\"'; + if ( !bIsQuoted ) + { + Q_strncpy( remaining, args.ArgS(), sizeof(remaining) ); + } + else + { + --nLen; + Q_strncpy( remaining, &pArgS[1], sizeof(remaining) ); + } + + // Now strip off any trailing spaces + char *p = remaining + nLen - 1; + while ( p >= remaining ) + { + if ( *p > ' ' ) + break; + + *p-- = 0; + } + + // Strip off ending quote + if ( bIsQuoted && p >= remaining ) + { + if ( *p == '\"' ) + { + *p = 0; + } + } + + if ( pConVar->IsBitSet( FCVAR_NEVER_AS_STRING ) ) + { + pConVar->SetValue( (float)atof( remaining ) ); + } + else + { + pConVar->SetValue( remaining ); + } + + } + m_CommandBuffer.EndProcessingCommands(); +} + + +//----------------------------------------------------------------------------- +// Per-frame update +//----------------------------------------------------------------------------- +void CInputManager::Update( ) +{ + char cmd[1024]; + + g_pInputSystem->PollInputState(); + int nEventCount = g_pInputSystem->GetEventCount(); + const InputEvent_t* pEvents = g_pInputSystem->GetEventData( ); + for ( int i = 0; i < nEventCount; ++i ) + { + if ( pEvents[i].m_nType == IE_Quit ) + { + IGameManager::Stop(); + break; + } + + bool bBypassVGui = false; + switch( pEvents[i].m_nType ) + { + case IE_AppActivated: + if ( pEvents[i].m_nData == 0 ) + { + m_ButtonUpToEngine.ClearAll(); + } + break; + + case IE_ButtonReleased: + { + // This logic is necessary to deal with switching back + forth + // between vgui + the engine. If we downclick in the engine, + // the engine must get the upclick. + ButtonCode_t code = (ButtonCode_t)pEvents[i].m_nData; + if ( m_ButtonUpToEngine[ code ] ) + { + m_ButtonUpToEngine.Clear( code ); + bBypassVGui = true; + } + } + break; + + default: + break; + } + + + if ( !bBypassVGui ) + { + if ( g_pUIManager->ProcessInputEvent( pEvents[i] ) ) + continue; + } + + // FIXME: Add game keybinding system here + bool bButtonDown = ( pEvents[i].m_nType == IE_ButtonPressed ); + bool bButtonUp = ( pEvents[i].m_nType == IE_ButtonReleased ); + if ( bButtonDown || bButtonUp ) + { + ButtonCode_t code = (ButtonCode_t)pEvents[i].m_nData; + if ( bButtonDown ) + { + m_ButtonUpToEngine.Set( code ); + } + const char *pBinding = m_KeyBindings.GetBindingForButton( code ); + if ( !pBinding ) + continue; + + if ( pBinding[0] != '+' ) + { + if ( bButtonDown ) + { + m_CommandBuffer.AddText( pBinding ); + } + continue; + } + + Q_snprintf( cmd, sizeof(cmd), "%c%s %i\n", bButtonUp ? '-' : '+', &pBinding[1], code ); + m_CommandBuffer.AddText( cmd ); + continue; + } + } + + ProcessCommands(); +} + diff --git a/app/legion/inputmanager.h b/app/legion/inputmanager.h new file mode 100644 index 0000000..82517df --- /dev/null +++ b/app/legion/inputmanager.h @@ -0,0 +1,55 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: The main manager of the input +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#ifndef INPUTMANAGER_H +#define INPUTMANAGER_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "gamemanager.h" +#include "tier2/keybindings.h" +#include "tier1/commandbuffer.h" +#include "bitvec.h" + + +//----------------------------------------------------------------------------- +// Input management +//----------------------------------------------------------------------------- +class CInputManager : public CGameManager<> +{ +public: + // Inherited from IGameManager + virtual bool Init(); + virtual void Update( ); + + // Add a command into the command queue + void AddCommand( const char *pCommand ); + +private: + // Per-frame update of commands + void ProcessCommands( ); + + // Purpose: + void PrintConCommandBaseDescription( const ConCommandBase *pVar ); + + CKeyBindings m_KeyBindings; + CBitVec<BUTTON_CODE_LAST> m_ButtonUpToEngine; + CCommandBuffer m_CommandBuffer; +}; + + +//----------------------------------------------------------------------------- +// Singleton accessor +//----------------------------------------------------------------------------- +extern CInputManager *g_pInputManager; + + +#endif // INPUTMANAGER_H + diff --git a/app/legion/joingamemenu.cpp b/app/legion/joingamemenu.cpp new file mode 100644 index 0000000..e3b1311 --- /dev/null +++ b/app/legion/joingamemenu.cpp @@ -0,0 +1,213 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Menu responsible for allowing players to join a game +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#include "menumanager.h" +#include "basemenu.h" +#include "vgui_controls/listpanel.h" +#include "vgui_controls/textentry.h" +#include "vgui_controls/button.h" +#include "networkmessages.h" +#include "networkmanager.h" +#include "tier1/KeyValues.h" + + +//----------------------------------------------------------------------------- +// Constructor, destructor +//----------------------------------------------------------------------------- +class CJoinGameMenu : public CBaseMenu, public INetworkMessageListener +{ + DECLARE_CLASS_SIMPLE( CJoinGameMenu, CBaseMenu ); + +public: + CJoinGameMenu( vgui::Panel *pParent, const char *pPanelName ); + virtual ~CJoinGameMenu(); + + // Called when a particular network message occurs + virtual void OnNetworkMessage( NetworkMessageRoute_t route, INetworkMessage *pNetworkMessage ); + virtual void OnCommand( const char *pCommand ); + + MESSAGE_FUNC( OnTextNewLine, "TextNewLine" ); + +private: + vgui::ListPanel *m_pPlayerList; + vgui::TextEntry *m_pChatLog; + vgui::TextEntry *m_pServerName; + vgui::TextEntry *m_pServerPort; + vgui::TextEntry *m_pChatEntry; + vgui::TextEntry *m_pPlayerName; + vgui::Button *m_pJoinGame; + bool m_bJoiningGame; +}; + + +//----------------------------------------------------------------------------- +// Hooks the menu into the menu manager +//----------------------------------------------------------------------------- +REGISTER_MENU( "JoinGameMenu", CJoinGameMenu ); + + +//----------------------------------------------------------------------------- +// Sort by player name +//----------------------------------------------------------------------------- +static int __cdecl PlayerNameSortFunc( vgui::ListPanel *pPanel, const vgui::ListPanelItem &item1, const vgui::ListPanelItem &item2 ) +{ + const char *string1 = item1.kv->GetString("player"); + const char *string2 = item2.kv->GetString("player"); + return stricmp( string1, string2 ); +} + + +//----------------------------------------------------------------------------- +// Constructor, destructor +//----------------------------------------------------------------------------- +CJoinGameMenu::CJoinGameMenu( vgui::Panel *pParent, const char *pPanelName ) : + BaseClass( pParent, pPanelName ) +{ + m_pPlayerList = new vgui::ListPanel( this, "PlayerList" ); + m_pPlayerList->AddColumnHeader( 0, "color", "Color", 52, 0 ); + m_pPlayerList->AddColumnHeader( 1, "player", "Player Name", 128, 0 ); + m_pPlayerList->SetSelectIndividualCells( false ); + m_pPlayerList->SetEmptyListText( "No Players" ); + m_pPlayerList->SetDragEnabled( false ); + m_pPlayerList->AddActionSignalTarget( this ); + m_pPlayerList->SetSortFunc( 0, PlayerNameSortFunc ); + m_pPlayerList->SetSortFunc( 1, PlayerNameSortFunc ); + m_pPlayerList->SetSortColumn( 1 ); + + m_pServerName = new vgui::TextEntry( this, "ServerName" ); + + m_pServerPort = new vgui::TextEntry( this, "ServerPort" ); + char pInitialPort[16]; + Q_snprintf( pInitialPort, sizeof(pInitialPort), "%d", NETWORKSYSTEM_DEFAULT_SERVER_PORT ); + m_pServerPort->SetText( pInitialPort ); + + m_pPlayerName = new vgui::TextEntry( this, "PlayerName" ); + m_pPlayerName->SetMultiline( false ); + + m_pChatLog = new vgui::TextEntry( this, "ChatLog" ); + m_pChatLog->SetMultiline( true ); + m_pChatLog->SetVerticalScrollbar( true ); + + m_pChatEntry = new vgui::TextEntry( this, "ChatEntry" ); + m_pChatEntry->AddActionSignalTarget( this ); + m_pChatEntry->SetMultiline( false ); + m_pChatEntry->SendNewLine( true ); + + m_pJoinGame = new vgui::Button( this, "JoinGame", "Join Game", this ); + + LoadControlSettings( "resource/joingamemenu.res", "GAME" ); + + m_pPlayerName->SetText( "Unnamed" ); + m_pChatEntry->SetEnabled( false ); + + if ( !g_pNetworkManager->StartClient() ) + { + m_pJoinGame->SetEnabled( false ); + return; + } + + g_pNetworkManager->AddListener( NETWORK_MESSAGE_SERVER_TO_CLIENT, LEGION_NETMESSAGE_GROUP, CHAT_MESSAGE, this ); +} + +CJoinGameMenu::~CJoinGameMenu() +{ + g_pNetworkManager->RemoveListener( NETWORK_MESSAGE_SERVER_TO_CLIENT, LEGION_NETMESSAGE_GROUP, CHAT_MESSAGE, this ); +} + + +//----------------------------------------------------------------------------- +// Called when a particular network message occurs +//----------------------------------------------------------------------------- +void CJoinGameMenu::OnNetworkMessage( NetworkMessageRoute_t route, INetworkMessage *pNetworkMessage ) +{ + CNetworkMessage_Chat *pChatMsg = static_cast<CNetworkMessage_Chat*>( pNetworkMessage ); + m_pChatLog->InsertString( pChatMsg->m_Message.Get() ); + m_pChatLog->InsertChar( '\n' ); +} + + +//----------------------------------------------------------------------------- +// Called when the enter key is hit in the chat entry window +//----------------------------------------------------------------------------- +void CJoinGameMenu::OnTextNewLine() +{ + CNetworkMessage_Chat msg; + + int nLen = m_pChatEntry->GetTextLength(); + if ( nLen > 0 ) + { + char *pText = (char*)_alloca( (nLen+1) * sizeof(char) ); + m_pChatEntry->GetText( pText, nLen+1 ); + m_pChatEntry->SetText( "" ); + + int nLenName = m_pPlayerName->GetTextLength(); + char *pName = (char*)_alloca( (nLenName+8) * sizeof(char) ); + if ( nLenName == 0 ) + { + nLenName = 7; + Q_strcpy( pName, "unnamed" ); + } + else + { + m_pPlayerName->GetText( pName, nLenName+1 ); + } + + int nTotalLen = nLen + nLenName; + msg.m_Message.SetLength( nTotalLen + 3 ); + Q_snprintf( msg.m_Message.Get(), nTotalLen+3, "[%s] %s", pName, pText ); + + g_pNetworkManager->PostClientToServerMessage( &msg ); + } +} + + +//----------------------------------------------------------------------------- +// Called when the enter key is hit in the chat entry window +//----------------------------------------------------------------------------- +void CJoinGameMenu::OnCommand( const char *pCommand ) +{ + if ( !Q_stricmp( pCommand, "Cancel" ) ) + { + g_pNetworkManager->ShutdownClient(); + g_pMenuManager->PopMenu(); + return; + } + + if ( !Q_stricmp( pCommand, "JoinGame" ) ) + { + if ( !m_bJoiningGame ) + { + g_pNetworkManager->DisconnectClientFromServer(); + m_pChatEntry->SetEnabled( false ); + m_pChatEntry->SetText( "" ); + m_bJoiningGame = true; + m_pJoinGame->SetText( "Join Game" ); + } + else + { + int nLen = m_pServerName->GetTextLength(); + char *pServer = (char*)_alloca( (nLen+1) * sizeof(char) ); + m_pServerName->GetText( pServer, nLen+1 ); + + char pPort[32]; + m_pServerPort->GetText( pPort, sizeof(pPort) ); + + if ( g_pNetworkManager->ConnectClientToServer( pServer, atoi( pPort ) ) ) + { + m_pChatEntry->SetEnabled( true ); + m_bJoiningGame = false; + m_pJoinGame->SetText( "Leave Game" ); + } + } + return; + } + + BaseClass::OnCommand( pCommand ); +} + + diff --git a/app/legion/legion.cpp b/app/legion/legion.cpp new file mode 100644 index 0000000..33a6c09 --- /dev/null +++ b/app/legion/legion.cpp @@ -0,0 +1,167 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// The copyright to the contents herein is the property of Valve, L.L.C. +// The contents may be used and/or copied only with the written permission of +// Valve, L.L.C., or in accordance with the terms and conditions stipulated in +// the agreement/contract under which the contents have been supplied. +// +// $Header: $ +// $NoKeywords: $ +// +// An RTS! +//============================================================================= + +#include "legion.h" +#include <windows.h> +#include "inputsystem/iinputsystem.h" +#include "networksystem/inetworksystem.h" +#include "filesystem.h" +#include "materialsystem/imaterialsystem.h" +#include "vgui/IVGui.h" +#include "vgui/ISurface.h" +#include "VGuiMatSurface/IMatSystemSurface.h" +#include "vgui_controls/controls.h" +#include "vgui/ILocalize.h" +#include "vgui_controls/AnimationController.h" +#include "gamemanager.h" +#include "menumanager.h" +#include "physicsmanager.h" +#include "rendermanager.h" +#include "uimanager.h" +#include "inputmanager.h" +#include "networkmanager.h" +#include "worldmanager.h" +#include "tier3/tier3.h" + + +//----------------------------------------------------------------------------- +// Purpose: Warning/Msg call back through this API +// Input : type - +// *pMsg - +// Output : SpewRetval_t +//----------------------------------------------------------------------------- +SpewRetval_t SpewFunc( SpewType_t type, char const *pMsg ) +{ + OutputDebugString( pMsg ); + if ( type == SPEW_ASSERT ) + { + DebuggerBreak(); + } + return SPEW_CONTINUE; +} + + +static CLegionApp s_LegionApp; +extern CLegionApp *g_pApp = &s_LegionApp; +DEFINE_WINDOWED_STEAM_APPLICATION_OBJECT_GLOBALVAR( CLegionApp, s_LegionApp ); + + +//----------------------------------------------------------------------------- +// Create all singleton systems +//----------------------------------------------------------------------------- +bool CLegionApp::Create() +{ + SpewOutputFunc( SpewFunc ); + + // FIXME: Put this into tier1librariesconnect + MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f, false ); + + if ( !BaseClass::Create() ) + return false; + + AppSystemInfo_t appSystems[] = + { + { "networksystem.dll", NETWORKSYSTEM_INTERFACE_VERSION }, + { "", "" } // Required to terminate the list + }; + + return AddSystems( appSystems ); +} + +bool CLegionApp::PreInit( ) +{ + if ( !BaseClass::PreInit() ) + return false; + + if ( !g_pInputSystem || !g_pFullFileSystem || !g_pNetworkSystem || !g_pMaterialSystem || !g_pVGui || !g_pVGuiSurface || !g_pMatSystemSurface ) + { + Warning( "Legion is missing a required interface!\n" ); + return false; + } + return true; +} + + +void CLegionApp::PostShutdown() +{ + BaseClass::PostShutdown(); +} + + +bool CLegionApp::RegisterConCommandBase( ConCommandBase *pCommand ) +{ + // Mark for easy removal + pCommand->AddFlags( FCVAR_CLIENTDLL ); + pCommand->SetNext( 0 ); + + // Link to variable list + g_pCVar->RegisterConCommandBase( pCommand ); + return true; +} + +void CLegionApp::UnregisterConCommandBase( ConCommandBase *pCommand ) +{ + // Unlink from variable list + g_pCVar->UnlinkVariable( pCommand ); +} + + +//----------------------------------------------------------------------------- +// main application +//----------------------------------------------------------------------------- +int CLegionApp::Main() +{ + if (!SetVideoMode()) + return 0; + + ConCommandBaseMgr::OneTimeInit( this ); + + g_pMaterialSystem->ModInit(); + + // World database + IGameManager::Add( g_pWorldManager ); + + // Output + IGameManager::Add( g_pRenderManager ); + + // Input + IGameManager::Add( g_pNetworkManager ); + IGameManager::Add( g_pInputManager ); + IGameManager::Add( g_pMenuManager ); + IGameManager::Add( g_pUIManager ); + + // Simulation + IGameManager::Add( g_pPhysicsManager ); + + // Init the game managers + if ( !IGameManager::InitAllManagers() ) + return 0; + + // First menu to start on + g_pMenuManager->PushMenu( "MainMenu" ); + + // This is the main game loop + IGameManager::Start(); + + // Shut down game systems + IGameManager::ShutdownAllManagers(); + + g_pMaterialSystem->ModShutdown(); + + g_pCVar->UnlinkVariables( FCVAR_CLIENTDLL ); + + return 1; +} + + + diff --git a/app/legion/legion.h b/app/legion/legion.h new file mode 100644 index 0000000..b998bfb --- /dev/null +++ b/app/legion/legion.h @@ -0,0 +1,64 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// The copyright to the contents herein is the property of Valve, L.L.C. +// The contents may be used and/or copied only with the written permission of +// Valve, L.L.C., or in accordance with the terms and conditions stipulated in +// the agreement/contract under which the contents have been supplied. +// +// $Header: $ +// $NoKeywords: $ +// +// An RTS! +//============================================================================= + +#ifndef LEGION_H +#define LEGION_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "appframework/vguimatsysapp.h" +#include "tier1/convar.h" + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CLegionApp; + + +//----------------------------------------------------------------------------- +// Singleton interfaces +//----------------------------------------------------------------------------- +extern CLegionApp *g_pApp; + + +//----------------------------------------------------------------------------- +// The application object +//----------------------------------------------------------------------------- +class CLegionApp : public CVguiMatSysApp, public IConCommandBaseAccessor +{ + typedef CVguiMatSysApp BaseClass; + +public: + // Methods of IApplication + virtual bool Create(); + virtual bool PreInit( ); + virtual int Main(); + virtual void PostShutdown( ); + virtual const char *GetAppName() { return "Legion"; } + + // Methods of IConCommandBaseAccessor + virtual bool RegisterConCommandBase( ConCommandBase *pCommand ); + virtual void UnregisterConCommandBase( ConCommandBase *pCommand ); + + // Promote to public + void AppPumpMessages() { BaseClass::AppPumpMessages(); } + +private: +}; + + +#endif // LEGION_H + + diff --git a/app/legion/legion.vcproj b/app/legion/legion.vcproj new file mode 100644 index 0000000..8570646 --- /dev/null +++ b/app/legion/legion.vcproj @@ -0,0 +1,289 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="7.10" + Name="legion" + ProjectGUID="{B0B64755-2419-4946-A726-881A1D884F65}" + Keyword="Win32Proj"> + <Platforms> + <Platform + Name="Win32"/> + </Platforms> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="Debug" + IntermediateDirectory="Debug" + ConfigurationType="1" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="..\..\public;..\..\public\tier1;..\..\common" + PreprocessorDefinitions="_WIN32;_DEBUG;_WINDOWS" + MinimalRebuild="TRUE" + ExceptionHandling="FALSE" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + ForceConformanceInForLoopScope="TRUE" + RuntimeTypeInfo="TRUE" + UsePrecompiledHeader="0" + ProgramDataBaseFileName="$(IntDir)/legion.pdb" + WarningLevel="4" + Detect64BitPortabilityProblems="TRUE" + DebugInformationFormat="4"/> + <Tool + Name="VCCustomBuildTool" + CommandLine="if exist ..\..\..\game\bin\legion.exe attrib -r ..\..\..\game\bin\legion.exe +copy "$(TargetPath)" ..\..\..\game\bin +if exist ..\..\..\game\bin\legion.pdb attrib -r ..\..\..\game\bin\legion.pdb +copy "$(TargetDir)"legion.pdb ..\..\..\game\bin +" + Outputs="..\..\..\game\bin\legion.exe;..\..\..\game\bin\legion.pdb"/> + <Tool + Name="VCLinkerTool" + IgnoreImportLibrary="TRUE" + OutputFile="$(OutDir)/legion.exe" + LinkIncremental="2" + SuppressStartupBanner="TRUE" + AdditionalLibraryDirectories="..\..\lib\public;..\..\lib\common" + IgnoreDefaultLibraryNames="libcmt.lib" + GenerateDebugInformation="TRUE" + ProgramDatabaseFile="$(OutDir)/legion.pdb" + SubSystem="2" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool"/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="Release" + IntermediateDirectory="Release" + ConfigurationType="1" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + GlobalOptimizations="TRUE" + InlineFunctionExpansion="2" + EnableIntrinsicFunctions="TRUE" + FavorSizeOrSpeed="1" + OptimizeForProcessor="3" + AdditionalIncludeDirectories="..\..\public;..\..\public\tier1;..\..\common" + PreprocessorDefinitions="_WIN32;NDEBUG;_WINDOWS" + ExceptionHandling="FALSE" + RuntimeLibrary="0" + ForceConformanceInForLoopScope="TRUE" + RuntimeTypeInfo="TRUE" + UsePrecompiledHeader="0" + ProgramDataBaseFileName="$(IntDir)/legion.pdb" + WarningLevel="4" + Detect64BitPortabilityProblems="TRUE" + DebugInformationFormat="3"/> + <Tool + Name="VCCustomBuildTool" + CommandLine="if exist ..\..\..\game\bin\legion.exe attrib -r ..\..\..\game\bin\legion.exe +copy "$(TargetPath)" ..\..\..\game\bin +if exist ..\..\..\game\bin\legion.pdb attrib -r ..\..\..\game\bin\legion.pdb +copy "$(TargetDir)"legion.pdb ..\..\..\game\bin +" + Outputs="..\..\..\game\bin\legion.exe;..\..\..\game\bin\legion.pdb"/> + <Tool + Name="VCLinkerTool" + IgnoreImportLibrary="TRUE" + OutputFile="$(OutDir)/legion.exe" + LinkIncremental="1" + SuppressStartupBanner="TRUE" + AdditionalLibraryDirectories="..\..\lib\public;..\..\lib\common" + IgnoreDefaultLibraryNames="libcmtd.lib" + GenerateDebugInformation="TRUE" + SubSystem="2" + OptimizeReferences="2" + EnableCOMDATFolding="2" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool"/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx" + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"> + <File + RelativePath=".\basemenu.cpp"> + </File> + <File + RelativePath=".\gamemanager.cpp"> + </File> + <File + RelativePath=".\heightfield.cpp"> + </File> + <File + RelativePath=".\hostgamemenu.cpp"> + </File> + <File + RelativePath=".\inputmanager.cpp"> + </File> + <File + RelativePath=".\joingamemenu.cpp"> + </File> + <File + RelativePath=".\legion.cpp"> + </File> + <File + RelativePath=".\mainmenu.cpp"> + </File> + <File + RelativePath="..\..\public\tier0\memoverride.cpp"> + </File> + <File + RelativePath=".\menumanager.cpp"> + </File> + <File + RelativePath=".\networkmanager.cpp"> + </File> + <File + RelativePath=".\networkmessages.cpp"> + </File> + <File + RelativePath=".\networkmessages.h"> + </File> + <File + RelativePath=".\physicsmanager.cpp"> + </File> + <File + RelativePath=".\rendermanager.cpp"> + </File> + <File + RelativePath=".\uimanager.cpp"> + </File> + <File + RelativePath=".\worldmanager.cpp"> + </File> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"> + <File + RelativePath=".\basemenu.h"> + </File> + <File + RelativePath=".\gamemanager.h"> + </File> + <File + RelativePath=".\heightfield.h"> + </File> + <File + RelativePath=".\inetworkmessagelistener.h"> + </File> + <File + RelativePath=".\inputmanager.h"> + </File> + <File + RelativePath=".\legion.h"> + </File> + <File + RelativePath=".\menumanager.h"> + </File> + <File + RelativePath=".\networkmanager.h"> + </File> + <File + RelativePath=".\physicsmanager.h"> + </File> + <File + RelativePath=".\rendermanager.h"> + </File> + <File + RelativePath=".\uimanager.h"> + </File> + <File + RelativePath=".\worldmanager.h"> + </File> + </Filter> + <Filter + Name="External Dependencies" + Filter=""> + <File + RelativePath="..\..\public\mathlib\math_base.h"> + </File> + <File + RelativePath="..\..\public\tier1\utlstack.h"> + </File> + <File + RelativePath="..\..\public\tier1\utlstring.h"> + </File> + </Filter> + <File + RelativePath="..\..\lib\public\appframework.lib"> + </File> + <File + RelativePath="..\..\lib\public\bitmap.lib"> + </File> + <File + RelativePath="..\..\lib\public\mathlib.lib"> + </File> + <File + RelativePath="..\..\lib\public\matsys_controls.lib"> + </File> + <File + RelativePath="..\..\lib\public\tier0.lib"> + </File> + <File + RelativePath="..\..\lib\public\tier1.lib"> + </File> + <File + RelativePath="..\..\lib\public\tier2.lib"> + </File> + <File + RelativePath="..\..\lib\public\tier3.lib"> + </File> + <File + RelativePath="..\..\lib\public\vgui_controls.lib"> + </File> + <File + RelativePath="..\..\lib\public\vstdlib.lib"> + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/app/legion/mainmenu.cpp b/app/legion/mainmenu.cpp new file mode 100644 index 0000000..b60b4d6 --- /dev/null +++ b/app/legion/mainmenu.cpp @@ -0,0 +1,46 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: List of game systems to update +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#include "menumanager.h" +#include "basemenu.h" + + +//----------------------------------------------------------------------------- +// Constructor, destructor +//----------------------------------------------------------------------------- +class CMainMenu : public CBaseMenu +{ + DECLARE_CLASS_SIMPLE( CMainMenu, CBaseMenu ); + +public: + CMainMenu( vgui::Panel *pParent, const char *pPanelName ); + virtual ~CMainMenu(); + +private: +}; + + +//----------------------------------------------------------------------------- +// Hooks the menu into the menu manager +//----------------------------------------------------------------------------- +REGISTER_MENU( "MainMenu", CMainMenu ); + + +//----------------------------------------------------------------------------- +// Constructor, destructor +//----------------------------------------------------------------------------- +CMainMenu::CMainMenu( vgui::Panel *pParent, const char *pPanelName ) : + BaseClass( pParent, pPanelName ) +{ + LoadControlSettings( "resource/mainmenu.res", "GAME" ); +} + +CMainMenu::~CMainMenu() +{ +} + diff --git a/app/legion/menumanager.cpp b/app/legion/menumanager.cpp new file mode 100644 index 0000000..9fdd438 --- /dev/null +++ b/app/legion/menumanager.cpp @@ -0,0 +1,195 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: The menu manager +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#include "menumanager.h" +#include "vgui_controls/panel.h" +#include "vgui_controls/frame.h" +#include "uimanager.h" + + +//----------------------------------------------------------------------------- +// Singleton +//----------------------------------------------------------------------------- +static CMenuManager s_MenuManager; +extern CMenuManager *g_pMenuManager = &s_MenuManager; + + +//----------------------------------------------------------------------------- +// Static members. +// NOTE: Do *not* set this to 0; it could cause us to lose some registered +// menus since that list is set up during construction +//----------------------------------------------------------------------------- +IMenuFactory *CMenuManager::m_pFirstFactory; + + +//----------------------------------------------------------------------------- +// Call to register methods which can construct menus w/ particular names +//----------------------------------------------------------------------------- +IMenuFactory *CMenuManager::RegisterMenu( IMenuFactory *pMenuFactory ) +{ + // NOTE: This method is expected to be called during global constructor + // time, so it must not require any global constructors to be called to work + IMenuFactory *pPrevFactory = m_pFirstFactory; + m_pFirstFactory = pMenuFactory; + return pPrevFactory; +} + + +//----------------------------------------------------------------------------- +// Init, shutdown +//----------------------------------------------------------------------------- +bool CMenuManager::Init() +{ + // Build a dictionary of all registered menus + IMenuFactory *pFactory; + for ( pFactory = m_pFirstFactory; pFactory; pFactory = pFactory->GetNextFactory() ) + { + m_MenuFactories.Insert( pFactory->GetMenuName(), pFactory ); + } + + m_bPopRequested = false; + m_bPopAllRequested = false; + m_pPushRequested = NULL; + + return true; +} + +void CMenuManager::Shutdown() +{ + CleanUpAllMenus(); +} + + +//----------------------------------------------------------------------------- +// Push, pop menus +//----------------------------------------------------------------------------- +void CMenuManager::PushMenu( const char *pMenuName ) +{ + AssertMsg( !m_pPushRequested, "Can't request to push two menus in a single frame!" ); + + MenuFactoryIndex_t i = m_MenuFactories.Find( pMenuName ); + if ( i == m_MenuFactories.InvalidIndex() ) + { + Warning( "Tried to push unknown menu %s\n", pMenuName ); + return; + } + m_pPushRequested = m_MenuFactories[i]; +} + +void CMenuManager::PopMenu( ) +{ + AssertMsg( !m_bPopRequested, "Can't request to pop two menus in a single frame!" ); + AssertMsg( !m_pPushRequested, "Can't request to pop after requesting to push a menu in a single frame!" ); + m_bPopRequested = true; +} + +void CMenuManager::PopAllMenus( ) +{ + AssertMsg( !m_pPushRequested, "Can't request to pop after requesting to push a menu in a single frame!" ); + m_bPopAllRequested = true; +} + + +//----------------------------------------------------------------------------- +// Request a menu to switch to +//----------------------------------------------------------------------------- +void CMenuManager::SwitchToMenu( const char *pMenuName ) +{ + AssertMsg( !m_bPopRequested, "Can't request to pop two menus in a single frame!" ); + AssertMsg( !m_pPushRequested, "Can't request to push two menus in a single frame!" ); + + MenuFactoryIndex_t i = m_MenuFactories.Find( pMenuName ); + if ( i == m_MenuFactories.InvalidIndex() ) + { + Warning( "Tried to switch to unknown menu %s\n", pMenuName ); + return; + } + m_bPopRequested = true; + m_pPushRequested = m_MenuFactories[i]; +} + + +//----------------------------------------------------------------------------- +// Returns the name of the topmost panel +//----------------------------------------------------------------------------- +const char *CMenuManager::GetTopmostPanelName() +{ + if ( !m_nActiveMenu.Count() ) + return NULL; + return m_nActiveMenu.Top()->GetName(); +} + + +//----------------------------------------------------------------------------- +// Request a menu to switch to +//----------------------------------------------------------------------------- +void CMenuManager::Update( ) +{ + if ( m_bPopAllRequested ) + { + CleanUpAllMenus(); + m_bPopAllRequested = false; + return; + } + + if ( m_bPopRequested ) + { + AssertMsg( m_nActiveMenu.Count(), "Tried to pop a menu when no menus are active" ); + vgui::Panel *pTop = m_nActiveMenu.Top(); + pTop->MarkForDeletion(); + m_nActiveMenu.Pop(); + + // Mark the new active menu as visible, attach it to hierarchy. + if ( m_nActiveMenu.Count() > 0 ) + { + vgui::Panel *pTop = m_nActiveMenu.Top(); + pTop->SetVisible( true ); + pTop->SetParent( g_pUIManager->GetRootPanel( UI_ROOT_MENU ) ); + } + else + { + g_pUIManager->EnablePanel( UI_ROOT_MENU, false ); + } + m_bPopRequested = false; + } + + if ( m_pPushRequested ) + { + // Mark the previous menu as not visible, detach it from hierarchy. + if ( m_nActiveMenu.Count() > 0 ) + { + vgui::Panel *pTop = m_nActiveMenu.Top(); + pTop->SetVisible( false ); + pTop->SetParent( (vgui::Panel*)NULL ); + } + else + { + g_pUIManager->EnablePanel( UI_ROOT_MENU, true ); + } + vgui::Panel *pMenu = m_pPushRequested->CreateMenu( g_pUIManager->GetRootPanel( UI_ROOT_MENU ) ); + m_nActiveMenu.Push( pMenu ); + static_cast<vgui::Frame*>( pMenu )->Activate(); + m_pPushRequested = NULL; + } +} + + +//----------------------------------------------------------------------------- +// Cleans up all menus +//----------------------------------------------------------------------------- +void CMenuManager::CleanUpAllMenus() +{ + while ( m_nActiveMenu.Count() ) + { + vgui::Panel *pTop = m_nActiveMenu.Top(); + pTop->MarkForDeletion(); + m_nActiveMenu.Pop(); + } + g_pUIManager->EnablePanel( UI_ROOT_MENU, false ); +} + diff --git a/app/legion/menumanager.h b/app/legion/menumanager.h new file mode 100644 index 0000000..e3096cd --- /dev/null +++ b/app/legion/menumanager.h @@ -0,0 +1,140 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: The manager that deals with menus +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#ifndef MENUMANAGER_H +#define MENUMANAGER_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "gamemanager.h" +#include "tier1/utldict.h" +#include "tier1/utlstack.h" + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +namespace vgui +{ + class Panel; +} + + +//----------------------------------------------------------------------------- +// Interface used to create menus +//----------------------------------------------------------------------------- +abstract_class IMenuFactory +{ +public: + // Returns the name of the menu it will create + virtual const char *GetMenuName() = 0; + + // Creates the menu + virtual vgui::Panel *CreateMenu( vgui::Panel *pParent ) = 0; + + // Used to build a list during construction + virtual IMenuFactory *GetNextFactory( ) = 0; + +protected: + virtual ~IMenuFactory() {} +}; + + +//----------------------------------------------------------------------------- +// Menu managemer +//----------------------------------------------------------------------------- +class CMenuManager : public CGameManager<> +{ +public: + typedef vgui::Panel* (*MenuFactory_t)( vgui::Panel *pParent ); + + // Inherited from IGameManager + virtual bool Init(); + virtual void Update( ); + virtual void Shutdown(); + + // Push, pop menus + void PushMenu( const char *pMenuName ); + void PopMenu( ); + void PopAllMenus( ); + + // Pop the top menu, push specified menu + void SwitchToMenu( const char *pMenuName ); + + // Returns the name of the topmost panel + const char *GetTopmostPanelName(); + + // Call to register methods which can construct menus w/ particular ids + // NOTE: This method is not expected to be called directly. Use the REGISTER_MENU macro instead + // It returns the previous head of the list of factories + static IMenuFactory* RegisterMenu( IMenuFactory *pMenuFactory ); + +private: + void CleanUpAllMenus(); + + typedef unsigned char MenuFactoryIndex_t; + CUtlDict< IMenuFactory *, MenuFactoryIndex_t > m_MenuFactories; + CUtlStack< vgui::Panel * > m_nActiveMenu; + bool m_bPopRequested; + bool m_bPopAllRequested; + IMenuFactory *m_pPushRequested; + static IMenuFactory *m_pFirstFactory; +}; + + +//----------------------------------------------------------------------------- +// Singleton accessor +//----------------------------------------------------------------------------- +extern CMenuManager *g_pMenuManager; + + +//----------------------------------------------------------------------------- +// Macro used to register menus with the menu manager +// For example, add the line REGISTER_MENU( "MainMenu", CMainMenu ); +// into the class defining the main menu +//----------------------------------------------------------------------------- +template < class T > +class CMenuFactory : public IMenuFactory +{ +public: + CMenuFactory( const char *pMenuName ) : m_pMenuName( pMenuName ) + { + m_pNextFactory = CMenuManager::RegisterMenu( this ); + } + + // Returns the name of the menu it will create + virtual const char *GetMenuName() + { + return m_pMenuName; + } + + // Creates the menu + virtual vgui::Panel *CreateMenu( vgui::Panel *pParent ) + { + return new T( pParent, m_pMenuName ); + } + + // Used to build a list during construction + virtual IMenuFactory *GetNextFactory( ) + { + return m_pNextFactory; + } + +private: + const char* m_pMenuName; + IMenuFactory *m_pNextFactory; +}; + +#define REGISTER_MENU( _name, _className ) \ + static CMenuFactory< _className > s_Factory ## _className( _name ) + + +#endif // MENUMANAGER_H + diff --git a/app/legion/networkmanager.cpp b/app/legion/networkmanager.cpp new file mode 100644 index 0000000..062e066 --- /dev/null +++ b/app/legion/networkmanager.cpp @@ -0,0 +1,393 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: The main manager of the networking code in the game +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#include "networkmanager.h" +#include "legion.h" +#include "networksystem/inetworkmessage.h" +#include "tier1/bitbuf.h" +#include "inetworkmessagelistener.h" +#include "tier0/icommandline.h" +#include "tier2/tier2.h" + + +//----------------------------------------------------------------------------- +// Singleton accessor +//----------------------------------------------------------------------------- +static CNetworkManager s_NetworkManager; +extern CNetworkManager *g_pNetworkManager = &s_NetworkManager; + + +//----------------------------------------------------------------------------- +// Static members. +// NOTE: Do *not* set this to 0; it could cause us to lose some registered +// menus since that list is set up during construction +//----------------------------------------------------------------------------- +INetworkMessageFactory *CNetworkManager::m_pFirstFactory; + + +//----------------------------------------------------------------------------- +// Call to register methods to register network messages +//----------------------------------------------------------------------------- +INetworkMessageFactory *CNetworkManager::RegisterNetworkMessage( INetworkMessageFactory *pNetworkMessageFactory ) +{ + // NOTE: This method is expected to be called during global constructor + // time, so it must not require any global constructors to be called to work + INetworkMessageFactory *pPrevFactory = m_pFirstFactory; + m_pFirstFactory = pNetworkMessageFactory; + return pPrevFactory; +} + + +//----------------------------------------------------------------------------- +// Init, shutdown +//----------------------------------------------------------------------------- +bool CNetworkManager::Init() +{ + m_bIsClient = m_bIsServer = false; + m_pClientToServerConnection = NULL; + + // Make a listener array for each message type + + // Register all network messages + INetworkMessageFactory *pFactory; + for ( pFactory = m_pFirstFactory; pFactory; pFactory = pFactory->GetNextFactory() ) + { + INetworkMessage *pNetworkMessage = pFactory->CreateNetworkMessage(); + g_pNetworkSystem->RegisterMessage( pNetworkMessage ); + } + + return true; +} + +void CNetworkManager::Shutdown() +{ + ShutdownClient(); + ShutdownServer(); +} + + +//----------------------------------------------------------------------------- +// Start a server up +//----------------------------------------------------------------------------- +bool CNetworkManager::StartServer( unsigned short nServerListenPort ) +{ + ShutdownServer( ); + if ( nServerListenPort == LEGION_DEFAULT_SERVER_PORT ) + { + nServerListenPort = CommandLine()->ParmValue( "-serverport", NETWORKSYSTEM_DEFAULT_SERVER_PORT ); + } + m_bIsServer = g_pNetworkSystem->StartServer( nServerListenPort ); + return m_bIsServer; +} + +void CNetworkManager::ShutdownServer( ) +{ + if ( m_bIsServer ) + { + g_pNetworkSystem->ShutdownServer( ); + m_bIsServer = false; + } +} + + +//----------------------------------------------------------------------------- +// Start a client up +//----------------------------------------------------------------------------- +bool CNetworkManager::StartClient( unsigned short nClientListenPort ) +{ + ShutdownClient( ); + + if ( nClientListenPort == LEGION_DEFAULT_CLIENT_PORT ) + { + nClientListenPort = CommandLine()->ParmValue( "-clientport", NETWORKSYSTEM_DEFAULT_CLIENT_PORT ); + } + + m_bIsClient = g_pNetworkSystem->StartClient( nClientListenPort ); + return m_bIsClient; +} + +void CNetworkManager::ShutdownClient( ) +{ + if ( m_bIsClient ) + { + DisconnectClientFromServer(); + g_pNetworkSystem->ShutdownClient( ); + m_bIsClient = false; + } +} + + +//----------------------------------------------------------------------------- +// Connects/disconnects the client to a server +//----------------------------------------------------------------------------- +bool CNetworkManager::ConnectClientToServer( const char *pServerName, unsigned short nServerListenPort ) +{ + DisconnectClientFromServer(); + if ( !IsClient() ) + return false; + + if ( nServerListenPort == LEGION_DEFAULT_SERVER_PORT ) + { + nServerListenPort = CommandLine()->ParmValue( "-serverport", NETWORKSYSTEM_DEFAULT_SERVER_PORT ); + } + m_pClientToServerConnection = g_pNetworkSystem->ConnectClientToServer( pServerName, nServerListenPort ); + return ( m_pClientToServerConnection != NULL ); +} + +void CNetworkManager::DisconnectClientFromServer( ) +{ + if ( m_pClientToServerConnection ) + { + g_pNetworkSystem->DisconnectClientFromServer( m_pClientToServerConnection ); + m_pClientToServerConnection = NULL; + } +} + + +//----------------------------------------------------------------------------- +// Start up a game where the local player is playing +//----------------------------------------------------------------------------- +bool CNetworkManager::HostGame() +{ + if ( !StartServer() ) + return false; + + if ( !StartClient() ) + { + ShutdownServer(); + return false; + } + + if ( !ConnectClientToServer( "localhost" ) ) + { + ShutdownClient(); + ShutdownServer(); + return false; + } + + return true; +} + +void CNetworkManager::StopHostingGame() +{ + ShutdownClient(); + ShutdownServer(); +} + + +//----------------------------------------------------------------------------- +// Are we a client?/Are we a server? (we can be both) +//----------------------------------------------------------------------------- +bool CNetworkManager::IsClient() +{ + return m_bIsClient; +} + +bool CNetworkManager::IsServer() +{ + return m_bIsServer; +} + + +//----------------------------------------------------------------------------- +// If we are a client, are we connected to the server? +//----------------------------------------------------------------------------- +bool CNetworkManager::IsClientConnected() +{ + return m_bIsClient && ( m_pClientToServerConnection != NULL ) && ( m_pClientToServerConnection->GetConnectionState() == CONNECTION_STATE_CONNECTED ); +} + + +//----------------------------------------------------------------------------- +// Post a network message to the server +//----------------------------------------------------------------------------- +void CNetworkManager::PostClientToServerMessage( INetworkMessage *pMessage ) +{ + if ( IsClientConnected() ) + { + m_pClientToServerConnection->AddNetMsg( pMessage ); + } +} + + +//----------------------------------------------------------------------------- +// Broadcast a network message to all clients +//----------------------------------------------------------------------------- +void CNetworkManager::BroadcastServerToClientMessage( INetworkMessage *pMessage ) +{ + if ( IsServer() ) + { + int nCount = m_ServerToClientConnection.Count(); + for ( int i = 0; i < nCount; ++i ) + { + m_ServerToClientConnection[i]->AddNetMsg( pMessage ); + } + } +} + + +//----------------------------------------------------------------------------- +// Add, remove network message listeners +//----------------------------------------------------------------------------- +void CNetworkManager::AddListener( NetworkMessageRoute_t route, int nGroup, int nType, INetworkMessageListener *pListener ) +{ + CUtlVector< CUtlVector< CUtlVector < INetworkMessageListener* > > > &listeners = m_Listeners[ route ]; + if ( listeners.Count() <= nGroup ) + { + listeners.AddMultipleToTail( nGroup - listeners.Count() + 1 ); + } + + if ( listeners[nGroup].Count() <= nType ) + { + listeners[nGroup].AddMultipleToTail( nType - listeners[nGroup].Count() + 1 ); + } + + Assert( listeners[nGroup][nType].Find( pListener ) < 0 ); + listeners[nGroup][nType].AddToTail( pListener ); +} + +void CNetworkManager::RemoveListener( NetworkMessageRoute_t route, int nGroup, int nType, INetworkMessageListener *pListener ) +{ + CUtlVector< CUtlVector< CUtlVector < INetworkMessageListener* > > > &listeners = m_Listeners[ route ]; + if ( listeners.Count() > nGroup ) + { + if( listeners[nGroup].Count() > nType ) + { + // Maintain order of listeners (not sure if it matters) + listeners[nGroup][nType].FindAndRemove( pListener ); + } + } +} + + +//----------------------------------------------------------------------------- +// Notifies listeners about a network message +//----------------------------------------------------------------------------- +void CNetworkManager::NotifyListeners( NetworkMessageRoute_t route, INetworkMessage *pMessage ) +{ + CUtlVector< CUtlVector< CUtlVector < INetworkMessageListener* > > > &listeners = m_Listeners[ route ]; + + // based on id, search for installed listeners + int nGroup = pMessage->GetGroup(); + if ( listeners.Count() > nGroup ) + { + int nType = pMessage->GetType(); + if ( listeners[nGroup].Count() > nType ) + { + CUtlVector< INetworkMessageListener* > &list = listeners[nGroup][nType]; + int nCount = list.Count(); + for ( int i = 0; i < nCount; ++i ) + { + list[i]->OnNetworkMessage( route, pMessage ); + } + } + } +} + + +//----------------------------------------------------------------------------- +// Process messages received by the client +//----------------------------------------------------------------------------- +void CNetworkManager::ProcessClientMessages() +{ + NetworkEvent_t *pEvent = g_pNetworkSystem->FirstNetworkEvent(); + for ( ; pEvent; pEvent = g_pNetworkSystem->NextNetworkEvent( ) ) + { + switch ( pEvent->m_nType ) + { + /* + case NETWORK_EVENT_CONNECTED: + { + NetworkConnectionEvent_t* pConnectEvent = static_cast<NetworkConnectionEvent_t*>( pEvent ); + m_pClientToServerConnection = pConnectEvent->m_pChannel; + } + break; + + case NETWORK_EVENT_DISCONNECTED: + { + NetworkDisconnectionEvent_t* pDisconnectEvent = static_cast<NetworkDisconnectionEvent_t*>( pEvent ); + Assert( m_pClientToServerConnection == pDisconnectEvent->m_pChannel ); + if ( m_pClientToServerConnection == pDisconnectEvent->m_pChannel ) + { + m_pClientToServerConnection = NULL; + } + } + break; + */ + + case NETWORK_EVENT_MESSAGE_RECEIVED: + { + NetworkMessageReceivedEvent_t* pPacketEvent = static_cast<NetworkMessageReceivedEvent_t*>( pEvent ); + NotifyListeners( NETWORK_MESSAGE_SERVER_TO_CLIENT, pPacketEvent->m_pNetworkMessage ); + } + break; + } + } +} + + +//----------------------------------------------------------------------------- +// Process messages received by the server +//----------------------------------------------------------------------------- +void CNetworkManager::ProcessServerMessages() +{ + NetworkEvent_t *pEvent = g_pNetworkSystem->FirstNetworkEvent(); + for ( ; pEvent; pEvent = g_pNetworkSystem->NextNetworkEvent( ) ) + { + switch ( pEvent->m_nType ) + { + case NETWORK_EVENT_CONNECTED: + { + NetworkConnectionEvent_t* pConnectEvent = static_cast<NetworkConnectionEvent_t*>( pEvent ); + m_ServerToClientConnection.AddToTail( pConnectEvent->m_pChannel ); + } + break; + + case NETWORK_EVENT_DISCONNECTED: + { + NetworkDisconnectionEvent_t* pDisconnectEvent = static_cast<NetworkDisconnectionEvent_t*>( pEvent ); + m_ServerToClientConnection.FindAndRemove( pDisconnectEvent->m_pChannel ); + } + break; + + case NETWORK_EVENT_MESSAGE_RECEIVED: + { + NetworkMessageReceivedEvent_t* pPacketEvent = static_cast<NetworkMessageReceivedEvent_t*>( pEvent ); + NotifyListeners( NETWORK_MESSAGE_CLIENT_TO_SERVER, pPacketEvent->m_pNetworkMessage ); + } + break; + } + } +} + + +//----------------------------------------------------------------------------- +// Per-frame update +//----------------------------------------------------------------------------- +void CNetworkManager::Update( ) +{ + if ( IsClient() ) + { + g_pNetworkSystem->ClientSendMessages(); + } + + if ( IsServer() ) + { + g_pNetworkSystem->ServerReceiveMessages(); + ProcessServerMessages(); + g_pNetworkSystem->ServerSendMessages(); + } + + if ( IsClient() ) + { + g_pNetworkSystem->ClientReceiveMessages(); + ProcessClientMessages(); + } +} + + diff --git a/app/legion/networkmanager.h b/app/legion/networkmanager.h new file mode 100644 index 0000000..7383587 --- /dev/null +++ b/app/legion/networkmanager.h @@ -0,0 +1,159 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: The main manager of the networking code in the game +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#ifndef NETWORKMANAGER_H +#define NETWORKMANAGER_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "gamemanager.h" +#include "networksystem/inetworksystem.h" +#include "inetworkmessagelistener.h" + + +//----------------------------------------------------------------------------- +// Default ports +//----------------------------------------------------------------------------- +enum +{ + LEGION_DEFAULT_SERVER_PORT = 0xFFFF, + LEGION_DEFAULT_CLIENT_PORT = 0xFFFF, +}; + + +//----------------------------------------------------------------------------- +// Interface used to create network messages +//----------------------------------------------------------------------------- +abstract_class INetworkMessageFactory +{ +public: + // Creates the menu + virtual INetworkMessage *CreateNetworkMessage( ) = 0; + + // Used to build a list during construction + virtual INetworkMessageFactory *GetNextFactory( ) = 0; + +protected: + virtual ~INetworkMessageFactory() {} +}; + + +//----------------------------------------------------------------------------- +// Network management system +//----------------------------------------------------------------------------- +class CNetworkManager : public CGameManager<> +{ +public: + // Inherited from IGameManager + virtual bool Init(); + virtual void Update( ); + virtual void Shutdown(); + + // Are we a client?/Are we a server? (we can be both) + bool IsClient(); + bool IsServer(); + + // If we are a client, are we connected to the server? + bool IsClientConnected(); + + // Start a server up + bool StartServer( unsigned short nServerListenPort = LEGION_DEFAULT_SERVER_PORT ); + void ShutdownServer( ); + + // Start a client up + bool StartClient( unsigned short nClientListenPort = LEGION_DEFAULT_CLIENT_PORT ); + void ShutdownClient( ); + + // Connects the client to a server + bool ConnectClientToServer( const char *pServerName, unsigned short nServerListenPort = LEGION_DEFAULT_SERVER_PORT ); + void DisconnectClientFromServer(); + + // Add, remove network message listeners + void AddListener( NetworkMessageRoute_t route, int nGroup, int nType, INetworkMessageListener *pListener ); + void RemoveListener( NetworkMessageRoute_t route, int nGroup, int nType, INetworkMessageListener *hListener ); + + // Post a network message to the server + void PostClientToServerMessage( INetworkMessage *pMessage ); + + // Broadcast a network message to all clients + void BroadcastServerToClientMessage( INetworkMessage *pMessage ); + + // Start up a game where the local player is playing + bool HostGame(); + void StopHostingGame(); + + // Call to register methods which can construct menus w/ particular ids + // NOTE: This method is not expected to be called directly. Use the REGISTER_NETWORK_MESSAGE macro instead + // It returns the previous head of the list of factories + static INetworkMessageFactory* RegisterNetworkMessage( INetworkMessageFactory *pMenuFactory ); + +private: + // Process messages received by the client + void ProcessClientMessages(); + + // Process messages received by the server + void ProcessServerMessages(); + + // Notifies listeners about a network message + void NotifyListeners( NetworkMessageRoute_t route, INetworkMessage *pMessage ); + + bool m_bIsClient; + bool m_bIsServer; + + INetChannel *m_pClientToServerConnection; + CUtlVector< INetChannel* > m_ServerToClientConnection; + CUtlVector< CUtlVector< CUtlVector < INetworkMessageListener* > > > m_Listeners[ NETWORK_MESSAGE_ROUTE_COUNT ]; + static INetworkMessageFactory* m_pFirstFactory; +}; + + +//----------------------------------------------------------------------------- +// Singleton accessor +//----------------------------------------------------------------------------- +extern CNetworkManager *g_pNetworkManager; + + +//----------------------------------------------------------------------------- +// Macro used to register menus with the menu system +// For example, add the line REGISTER_NETWORK_MESSAGE( CNetworkMessageChat ); +// into the file defining the chat message +//----------------------------------------------------------------------------- +template < class T > +class CNetworkMessageFactory : public INetworkMessageFactory +{ +public: + CNetworkMessageFactory( ) + { + m_pNextFactory = CNetworkManager::RegisterNetworkMessage( this ); + } + + // Creates the network message + virtual INetworkMessage *CreateNetworkMessage( ) + { + return new T; + } + + // Used to build a list during construction + virtual INetworkMessageFactory *GetNextFactory( ) + { + return m_pNextFactory; + } + +private: + INetworkMessage *m_pMessage; + INetworkMessageFactory *m_pNextFactory; +}; + +#define REGISTER_NETWORK_MESSAGE( _className ) \ + static CNetworkMessageFactory< _className > __s_Factory ## _className + + +#endif // NETWORKMANAGER_H + diff --git a/app/legion/networkmessages.cpp b/app/legion/networkmessages.cpp new file mode 100644 index 0000000..3b382a9 --- /dev/null +++ b/app/legion/networkmessages.cpp @@ -0,0 +1,51 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: A network message that sends chat messages +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#include "networkmessages.h" +#include "networkmanager.h" +#include "tier1/bitbuf.h" + + +//----------------------------------------------------------------------------- +// Chat network message +//----------------------------------------------------------------------------- +REGISTER_NETWORK_MESSAGE( CNetworkMessage_Chat ); + +CNetworkMessage_Chat::CNetworkMessage_Chat() +{ + SetReliable( false ); +} + +bool CNetworkMessage_Chat::WriteToBuffer( bf_write &buffer ) +{ + int nLen = m_Message.Length(); + buffer.WriteShort( nLen ); + if ( nLen ) + { + buffer.WriteBytes( m_Message.Get(), nLen ); + } + return !buffer.IsOverflowed(); +} + +bool CNetworkMessage_Chat::ReadFromBuffer( bf_read &buffer ) +{ + int nLen = buffer.ReadShort(); + if ( nLen ) + { + m_Message.SetLength( nLen + 1 ); + char *pDest = m_Message.Get(); + buffer.ReadBytes( pDest, nLen ); + pDest[ nLen ] = 0; + } + else + { + m_Message.Set( NULL ); + } + return !buffer.IsOverflowed(); +} + diff --git a/app/legion/networkmessages.h b/app/legion/networkmessages.h new file mode 100644 index 0000000..ea29773 --- /dev/null +++ b/app/legion/networkmessages.h @@ -0,0 +1,54 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: The main manager of the networking code in the game +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#ifndef NETWORKMESSAGES_H +#define NETWORKMESSAGES_H + +#ifdef _WIN32 +#pragma once +#endif + + +#include "networksystem/inetworkmessage.h" +#include "tier1/utlstring.h" + + +//----------------------------------------------------------------------------- +// Network message group +//----------------------------------------------------------------------------- +enum LegionNetworkGroups_t +{ + LEGION_NETMESSAGE_GROUP = NETWORKSYSTEM_FIRST_GROUP, +}; + + +//----------------------------------------------------------------------------- +// Network message types +//----------------------------------------------------------------------------- +enum LegionNetworkTypes_t +{ + CHAT_MESSAGE = 0, +}; + + +//----------------------------------------------------------------------------- +// Chat network message +//----------------------------------------------------------------------------- +class CNetworkMessage_Chat : public CNetworkMessage +{ +public: + CNetworkMessage_Chat(); + + DECLARE_BASE_MESSAGE( LEGION_NETMESSAGE_GROUP, CHAT_MESSAGE, "Chat Message" ) + + CUtlString m_Message; +}; + +#endif // NETWORKMESSAGES_H + + diff --git a/app/legion/physicsmanager.cpp b/app/legion/physicsmanager.cpp new file mode 100644 index 0000000..66a4650 --- /dev/null +++ b/app/legion/physicsmanager.cpp @@ -0,0 +1,29 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: The main manager of the physics +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#include "physicsmanager.h" +#include "legion.h" +#include "tier2/tier2.h" +#include "tier1/convar.h" + + + +//----------------------------------------------------------------------------- +// Singleton accessor +//----------------------------------------------------------------------------- +static CPhysicsManager s_PhysicsManager; +extern CPhysicsManager *g_pPhysicsManager = &s_PhysicsManager; + + +//----------------------------------------------------------------------------- +// Per-frame update +//----------------------------------------------------------------------------- +void CPhysicsManager::Update( ) +{ +} + diff --git a/app/legion/physicsmanager.h b/app/legion/physicsmanager.h new file mode 100644 index 0000000..10ea08f --- /dev/null +++ b/app/legion/physicsmanager.h @@ -0,0 +1,43 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: The main manager of the physics +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#ifndef PHYSICSMANAGER_H +#define PHYSICSMANAGER_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "gamemanager.h" +#include "tier2/keybindings.h" +#include "tier1/commandbuffer.h" +#include "bitvec.h" + + +//----------------------------------------------------------------------------- +// Input management +//----------------------------------------------------------------------------- +class CPhysicsManager : public CGameManager<> +{ +public: + // Inherited from IGameManager + virtual void Update( ); + virtual bool PerformsSimulation() { return true; } + +private: +}; + + +//----------------------------------------------------------------------------- +// Singleton accessor +//----------------------------------------------------------------------------- +extern CPhysicsManager *g_pPhysicsManager; + + +#endif // PHYSICSMANAGER_H + diff --git a/app/legion/rendermanager.cpp b/app/legion/rendermanager.cpp new file mode 100644 index 0000000..5d2e2a4 --- /dev/null +++ b/app/legion/rendermanager.cpp @@ -0,0 +1,255 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: The main manager of the rendering +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#include "rendermanager.h" +#include "legion.h" +#include "uimanager.h" +#include "worldmanager.h" +#include "materialsystem/imaterialsystem.h" +#include "tier2/tier2.h" + + +//----------------------------------------------------------------------------- +// Camera property +//----------------------------------------------------------------------------- +DEFINE_FIXEDSIZE_ALLOCATOR( CCameraProperty, 1, CMemoryPool::GROW_SLOW ); + + +CCameraProperty::CCameraProperty() +{ + m_Origin.Init(); + m_Angles.Init(); + m_Velocity.Init(); + m_AngVelocity.Init(); +} + +void CCameraProperty::GetForward( Vector *pForward ) +{ + AngleVectors( m_Angles, pForward ); +} + + +//----------------------------------------------------------------------------- +// Singleton accessor +//----------------------------------------------------------------------------- +static CRenderManager s_RenderManager; +extern CRenderManager *g_pRenderManager = &s_RenderManager; + + +//----------------------------------------------------------------------------- +// Game initialization +//----------------------------------------------------------------------------- +bool CRenderManager::Init() +{ + m_bRenderWorldFullscreen = true; + return true; +} + +void CRenderManager::Shutdown() +{ +} + + +//----------------------------------------------------------------------------- +// Level initialization +//----------------------------------------------------------------------------- +LevelRetVal_t CRenderManager::LevelInit( bool bFirstCall ) +{ + return FINISHED; +} + +LevelRetVal_t CRenderManager::LevelShutdown( bool bFirstCall ) +{ + return FINISHED; +} + + +//----------------------------------------------------------------------------- +// Property allocation +//----------------------------------------------------------------------------- +CCameraProperty *CRenderManager::CreateCameraProperty() +{ + return new CCameraProperty; +} + +void CRenderManager::DestroyCameraProperty( CCameraProperty *pProperty ) +{ + delete pProperty; +} + + +//----------------------------------------------------------------------------- +// Sets the rectangle to draw into +//----------------------------------------------------------------------------- +void CRenderManager::RenderWorldFullscreen() +{ + m_bRenderWorldFullscreen = true; +} + +void CRenderManager::RenderWorldInRect( int x, int y, int nWidth, int nHeight ) +{ + m_bRenderWorldFullscreen = false; + m_nRenderX = x; + m_nRenderY = y; + m_nRenderWidth = nWidth; + m_nRenderHeight = nHeight; +} + + +//----------------------------------------------------------------------------- +// Done completely client-side, want total smoothness, so simulate at render interval +//----------------------------------------------------------------------------- +void CRenderManager::UpdateLocalPlayerCamera() +{ + float dt = IGameManager::DeltaTime(); + CCameraProperty *pCamera = g_pWorldManager->GetLocalPlayer()->m_pCameraProperty; + VectorMA( pCamera->m_Origin, dt, pCamera->m_Velocity, pCamera->m_Origin ); + VectorMA( pCamera->m_Angles, dt, pCamera->m_AngVelocity, pCamera->m_Angles ); +} + + +//----------------------------------------------------------------------------- +// Per-frame update +//----------------------------------------------------------------------------- +void CRenderManager::Update( ) +{ + CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); + if ( GetLevelState() == NOT_IN_LEVEL ) + { + g_pMaterialSystem->BeginFrame( 0 ); + pRenderContext->ClearColor4ub( 76, 88, 68, 255 ); + pRenderContext->ClearBuffers( true, true ); + g_pUIManager->DrawUI(); + g_pMaterialSystem->EndFrame(); + g_pMaterialSystem->SwapBuffers(); + return; + } + + UpdateLocalPlayerCamera(); + + g_pMaterialSystem->BeginFrame( 0 ); + pRenderContext->ClearColor4ub( 0, 0, 0, 255 ); + pRenderContext->ClearBuffers( true, true ); + RenderWorld(); + g_pUIManager->DrawUI(); + g_pMaterialSystem->EndFrame(); + g_pMaterialSystem->SwapBuffers(); +} + + +//----------------------------------------------------------------------------- +// Sets up the camera +//----------------------------------------------------------------------------- +void CRenderManager::SetupCameraRenderState( ) +{ + CCameraProperty *pCamera = g_pWorldManager->GetLocalPlayer()->m_pCameraProperty; + + matrix3x4_t cameraToWorld; + AngleMatrix( pCamera->m_Angles, pCamera->m_Origin, cameraToWorld ); + + matrix3x4_t matRotate; + matrix3x4_t matRotateZ; + MatrixBuildRotationAboutAxis( Vector(0,0,1), -90, matRotateZ ); + MatrixMultiply( cameraToWorld, matRotateZ, matRotate ); + + matrix3x4_t matRotateX; + MatrixBuildRotationAboutAxis( Vector(1,0,0), 90, matRotateX ); + MatrixMultiply( matRotate, matRotateX, matRotate ); + + matrix3x4_t view; + MatrixInvert( matRotate, view ); + + CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); + pRenderContext->MatrixMode( MATERIAL_VIEW ); + pRenderContext->LoadMatrix( view ); +} + + +//----------------------------------------------------------------------------- +// Set up a projection matrix for a 90 degree fov +//----------------------------------------------------------------------------- + +// FIXME: Better control over Z range +#define ZNEAR 0.1f +#define ZFAR 10000.0f + +void CRenderManager::SetupProjectionMatrix( int nWidth, int nHeight, float flFOV ) +{ + VMatrix proj; + float flZNear = ZNEAR; + float flZFar = ZFAR; + float flApsectRatio = (nHeight != 0.0f) ? (float)nWidth / (float)nHeight : 100.0f; + + float halfWidth = tan( flFOV * M_PI / 360.0 ); + float halfHeight = halfWidth / flApsectRatio; + + memset( proj.Base(), 0, sizeof( proj ) ); + proj[0][0] = 1.0f / halfWidth; + proj[1][1] = 1.0f / halfHeight; + proj[2][2] = flZFar / ( flZNear - flZFar ); + proj[3][2] = -1.0f; + proj[2][3] = flZNear * flZFar / ( flZNear - flZFar ); + + CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); + pRenderContext->MatrixMode( MATERIAL_PROJECTION ); + pRenderContext->LoadMatrix( proj ); +} + + +//----------------------------------------------------------------------------- +// Set up a orthographic projection matrix +//----------------------------------------------------------------------------- +void CRenderManager::SetupOrthoMatrix( int nWidth, int nHeight ) +{ + CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); + pRenderContext->MatrixMode( MATERIAL_PROJECTION ); + pRenderContext->LoadIdentity(); + pRenderContext->Ortho( 0, 0, nWidth, nHeight, -1.0f, 1.0f ); +} + + +//----------------------------------------------------------------------------- +// Renders the world +//----------------------------------------------------------------------------- +void CRenderManager::RenderWorld() +{ + CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); + pRenderContext->MatrixMode( MATERIAL_PROJECTION ); + pRenderContext->PushMatrix(); + + pRenderContext->MatrixMode( MATERIAL_VIEW ); + pRenderContext->PushMatrix(); + + pRenderContext->MatrixMode( MATERIAL_MODEL ); + pRenderContext->PushMatrix(); + pRenderContext->LoadIdentity(); + + if ( m_bRenderWorldFullscreen ) + { + m_nRenderX = m_nRenderY = 0; + pRenderContext->GetRenderTargetDimensions( m_nRenderWidth, m_nRenderHeight ); + } + + pRenderContext->DepthRange( 0, 1 ); + pRenderContext->Viewport( m_nRenderX, m_nRenderY, m_nRenderWidth, m_nRenderHeight ); + + SetupProjectionMatrix( m_nRenderWidth, m_nRenderHeight, 90 ); + + SetupCameraRenderState(); + + g_pWorldManager->DrawWorld(); + + pRenderContext->MatrixMode( MATERIAL_PROJECTION ); + pRenderContext->PopMatrix(); + + pRenderContext->MatrixMode( MATERIAL_VIEW ); + pRenderContext->PopMatrix(); + + pRenderContext->MatrixMode( MATERIAL_MODEL ); + pRenderContext->PopMatrix(); +}
\ No newline at end of file diff --git a/app/legion/rendermanager.h b/app/legion/rendermanager.h new file mode 100644 index 0000000..555d7b8 --- /dev/null +++ b/app/legion/rendermanager.h @@ -0,0 +1,94 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: The main manager of rendering +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#ifndef RENDERMANAGER_H +#define RENDERMANAGER_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "gamemanager.h" +#include "tier1/mempool.h" +#include "mathlib/mathlib.h" + + +//----------------------------------------------------------------------------- +// Physics property for entities +//----------------------------------------------------------------------------- +class CCameraProperty +{ + DECLARE_FIXEDSIZE_ALLOCATOR( CCameraProperty ); + +public: + CCameraProperty(); + void GetForward( Vector *pForward ); + + // Array used for fixed-timestep simulation + Vector m_Origin; + QAngle m_Angles; + Vector m_Velocity; + QAngle m_AngVelocity; + +private: + friend class CRenderManager; +}; + + +//----------------------------------------------------------------------------- +// Rendering management +//----------------------------------------------------------------------------- +class CRenderManager : public CGameManager<> +{ +public: + // Inherited from IGameManager + virtual bool Init(); + virtual LevelRetVal_t LevelInit( bool bFirstCall ); + virtual void Update( ); + virtual LevelRetVal_t LevelShutdown( bool bFirstCall ); + virtual void Shutdown(); + + // Property allocation + CCameraProperty *CreateCameraProperty(); + void DestroyCameraProperty( CCameraProperty *pProperty ); + + void RenderWorldInRect( int x, int y, int nWidth, int nHeight ); + void RenderWorldFullscreen(); + +private: + // Set up a projection matrix for a 90 degree fov + void SetupProjectionMatrix( int nWidth, int nHeight, float flFOV ); + + // Set up a orthographic projection matrix + void SetupOrthoMatrix( int nWidth, int nHeight ); + + // Sets up the camera + void SetupCameraRenderState( ); + + // Draws the world + void RenderWorld(); + + // Done completely client-side, want total smoothness, so simulate at render interval + void UpdateLocalPlayerCamera(); + + bool m_bRenderWorldFullscreen; + int m_nRenderX; + int m_nRenderY; + int m_nRenderWidth; + int m_nRenderHeight; +}; + + +//----------------------------------------------------------------------------- +// Singleton accessor +//----------------------------------------------------------------------------- +extern CRenderManager *g_pRenderManager; + + +#endif // RENDERMANAGER_H + diff --git a/app/legion/uimanager.cpp b/app/legion/uimanager.cpp new file mode 100644 index 0000000..ef731f2 --- /dev/null +++ b/app/legion/uimanager.cpp @@ -0,0 +1,244 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: The main manager of the UI +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#include "uimanager.h" +#include "legion.h" +#include "appframework/vguimatsysapp.h" +#include "vgui/IVGui.h" +#include "vgui/ISurface.h" +#include "VGuiMatSurface/IMatSystemSurface.h" +#include "vgui_controls/controls.h" +#include "vgui/ILocalize.h" +#include "vgui_controls/EditablePanel.h" +#include "vgui_controls/AnimationController.h" +#include "filesystem.h" +#include "tier3/tier3.h" +#include "vgui_controls/consoledialog.h" +#include "inputmanager.h" + + +//----------------------------------------------------------------------------- +// Console dialog for use in legion +//----------------------------------------------------------------------------- +class CLegionConsoleDialog : public vgui::CConsoleDialog +{ + DECLARE_CLASS_SIMPLE( CLegionConsoleDialog, vgui::CConsoleDialog ); + +public: + CLegionConsoleDialog( vgui::Panel *pParent, const char *pName ); + virtual ~CLegionConsoleDialog(); + + virtual void OnClose(); + MESSAGE_FUNC_CHARPTR( OnCommandSubmitted, "CommandSubmitted", command ); +}; + + +CLegionConsoleDialog::CLegionConsoleDialog( vgui::Panel *pParent, const char *pName ) : BaseClass ( pParent, pName ) +{ + AddActionSignalTarget( this ); +} + +CLegionConsoleDialog::~CLegionConsoleDialog() +{ + g_pUIManager->HideConsole( ); +} + + +//----------------------------------------------------------------------------- +// A command was sent by the console +//----------------------------------------------------------------------------- +void CLegionConsoleDialog::OnCommandSubmitted( const char *pCommand ) +{ + g_pInputManager->AddCommand( pCommand ); +} + + +//----------------------------------------------------------------------------- +// Deals with close +//----------------------------------------------------------------------------- +void CLegionConsoleDialog::OnClose() +{ + g_pUIManager->HideConsole( ); +} + + + +//----------------------------------------------------------------------------- +// Singleton accessor +//----------------------------------------------------------------------------- +static CUIManager s_UIManager; +extern CUIManager *g_pUIManager = &s_UIManager; + + +static const char *s_pRootPanelNames[UI_ROOT_PANEL_COUNT] = +{ + "RootGamePanel", + "RootMenuPanel", + "RootToolsPanel", +}; + + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- +CUIManager::CUIManager() +{ +} + + +//----------------------------------------------------------------------------- +// Init, shutdown +//----------------------------------------------------------------------------- +bool CUIManager::Init() +{ + COMPILE_TIME_ASSERT( sizeof(s_pRootPanelNames) / sizeof(const char*) == UI_ROOT_PANEL_COUNT ); + + // load the base localization file + if (! vgui::scheme()->LoadSchemeFromFile("resource/legion.res", "Legion" ) ) + return false; + + vgui::filesystem()->AddSearchPath( "platform", "PLATFORM" ); + vgui::localize()->AddFile( vgui::filesystem(), "Resource/vgui_%language%.txt" ); + + // start vgui + g_pVGui->Start(); + + // Run a frame to get the embedded panel to be the right size + g_pVGui->RunFrame(); + + int w, h; + m_hEmbeddedPanel = g_pVGuiSurface->GetEmbeddedPanel(); + vgui::ipanel()->GetSize( m_hEmbeddedPanel, w, h ); + + // add our root panels + for ( int i = 0; i < UI_ROOT_PANEL_COUNT; ++i ) + { + m_pRootPanels[i] = new vgui::EditablePanel( NULL, s_pRootPanelNames[i] ); + m_pRootPanels[i]->SetParent( m_hEmbeddedPanel ); + m_pRootPanels[i]->SetZPos( i ); + m_pRootPanels[i]->SetBounds( 0, 0, w, h ); + m_pRootPanels[i]->SetPaintBorderEnabled( false ); + m_pRootPanels[i]->SetPaintBackgroundEnabled( false ); + m_pRootPanels[i]->SetPaintEnabled( false ); + m_pRootPanels[i]->SetKeyBoardInputEnabled( i != UI_ROOT_GAME ); + m_pRootPanels[i]->SetMouseInputEnabled( i != UI_ROOT_GAME ); + m_pRootPanels[i]->SetVisible( false ); + m_pRootPanels[i]->SetCursor( vgui::dc_crosshair ); + m_pRootPanels[i]->SetAutoResize( vgui::Panel::PIN_TOPLEFT, vgui::Panel::AUTORESIZE_DOWNANDRIGHT, 0, 0, 0, 0 ); + } + + m_hConsole = NULL; + + vgui::surface()->Invalidate( m_hEmbeddedPanel ); + return true; +} + +void CUIManager::Shutdown() +{ + g_pVGui->Stop(); +} + + +//----------------------------------------------------------------------------- +// Sets particular root panels to be visible +//----------------------------------------------------------------------------- +void CUIManager::EnablePanel( UIRootPanel_t id, bool bEnable ) +{ + m_pRootPanels[id]->SetVisible( bEnable ); +} + + +//----------------------------------------------------------------------------- +// Toggles the console +//----------------------------------------------------------------------------- +void CUIManager::ToggleConsole( const CCommand &args ) +{ + if ( !m_hConsole.Get() ) + { + m_hConsole = new CLegionConsoleDialog( m_pRootPanels[UI_ROOT_TOOLS], "Console" ); + + // set the console to taking up most of the right-half of the screen + int swide, stall; + vgui::surface()->GetScreenSize(swide, stall); + int offset = vgui::scheme()->GetProportionalScaledValue(16); + + m_hConsole->SetBounds( + swide / 2 - (offset * 4), + offset, + (swide / 2) + (offset * 3), + stall - (offset * 8)); + + m_hConsole->SetVisible( false ); + } + + bool bMakeVisible = !m_hConsole->IsVisible(); + EnablePanel( UI_ROOT_TOOLS, bMakeVisible ); + if ( bMakeVisible ) + { + m_hConsole->Activate(); + } + else + { + m_hConsole->Hide(); + } +} + + +//----------------------------------------------------------------------------- +// Hides the console +//----------------------------------------------------------------------------- +void CUIManager::HideConsole() +{ + EnablePanel( UI_ROOT_TOOLS, false ); + if ( m_hConsole.Get() ) + { + m_hConsole->SetVisible( false ); + } +} + + +//----------------------------------------------------------------------------- +// Per-frame update +//----------------------------------------------------------------------------- +void CUIManager::Update( ) +{ + vgui::GetAnimationController()->UpdateAnimations( IGameManager::CurrentTime() ); + g_pVGui->RunFrame(); + if ( !g_pVGui->IsRunning() ) + { + IGameManager::Stop(); + } +} + + +//----------------------------------------------------------------------------- +// Attempt to process an input event, return true if it sholdn't be chained to the rest of the game +//----------------------------------------------------------------------------- +bool CUIManager::ProcessInputEvent( const InputEvent_t& event ) +{ + return g_pMatSystemSurface->HandleInputEvent( event ); +} + + +//----------------------------------------------------------------------------- +// Draws the UI +//----------------------------------------------------------------------------- +void CUIManager::DrawUI() +{ + g_pVGuiSurface->PaintTraverseEx( m_hEmbeddedPanel, true ); +} + + +//----------------------------------------------------------------------------- +// Push, pop menus +//----------------------------------------------------------------------------- +vgui::Panel *CUIManager::GetRootPanel( UIRootPanel_t id ) +{ + return m_pRootPanels[id]; +} + diff --git a/app/legion/uimanager.h b/app/legion/uimanager.h new file mode 100644 index 0000000..290b0ae --- /dev/null +++ b/app/legion/uimanager.h @@ -0,0 +1,95 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: The main manager of the UI +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#ifndef UIMANAGER_H +#define UIMANAGER_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "gamemanager.h" +#include "vgui/vgui.h" +#include "tier1/convar.h" +#include "vgui_controls/panel.h" +#include "vgui_controls/phandle.h" + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +struct InputEvent_t; +class CLegionConsoleDialog; + +namespace vgui +{ + class Panel; +} + + +//----------------------------------------------------------------------------- +// Enum indicating the various main UI panels +// NOTE: The order in which they appear here is the order in which they will draw +//----------------------------------------------------------------------------- +enum UIRootPanel_t +{ + UI_ROOT_GAME = 0, + UI_ROOT_MENU, + UI_ROOT_TOOLS, + + UI_ROOT_PANEL_COUNT, +}; + + +//----------------------------------------------------------------------------- +// UI management +//----------------------------------------------------------------------------- +class CUIManager : public CGameManager<> +{ +public: + CUIManager(); + + // Inherited from IGameManager + virtual bool Init(); + virtual void Update( ); + virtual void Shutdown(); + + // Root panels + vgui::Panel *GetRootPanel( UIRootPanel_t id ); + + // Sets particular root panels to be visible + void EnablePanel( UIRootPanel_t id, bool bEnable ); + + // Attempt to process an input event, return true if it sholdn't be chained to the rest of the game + bool ProcessInputEvent( const InputEvent_t& event ); + + // Draws the UI + void DrawUI(); + + // Hides the console + void HideConsole(); + +private: + CON_COMMAND_MEMBER_F( CUIManager, "toggleconsole", ToggleConsole, "Toggle Console", 0 ); + + vgui::VPANEL m_hEmbeddedPanel; + vgui::Panel *m_pRootPanels[ UI_ROOT_PANEL_COUNT ]; + int m_nWindowWidth; + int m_nWindowHeight; + vgui::DHANDLE< CLegionConsoleDialog > m_hConsole; +}; + + +//----------------------------------------------------------------------------- +// Singleton accessor +//----------------------------------------------------------------------------- +extern CUIManager *g_pUIManager; + + +#endif // UIMANAGER_H + diff --git a/app/legion/worldmanager.cpp b/app/legion/worldmanager.cpp new file mode 100644 index 0000000..abd5d96 --- /dev/null +++ b/app/legion/worldmanager.cpp @@ -0,0 +1,166 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Contains all world state--the main game database +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#include "worldmanager.h" +#include "legion.h" +#include "heightfield.h" +#include "rendermanager.h" + +//----------------------------------------------------------------------------- +// Singleton accessor +//----------------------------------------------------------------------------- +static CWorldManager s_WorldManager; +extern CWorldManager *g_pWorldManager = &s_WorldManager; + + +//----------------------------------------------------------------------------- +// ConVars +//----------------------------------------------------------------------------- +static ConVar cam_forwardspeed( "cam_forwardspeed", "100", FCVAR_CHEAT, "Sets the camera forward speed" ); +static ConVar cam_backwardspeed( "cam_backwardspeed", "100", FCVAR_CHEAT, "Sets the camera backward speed" ); + + +//----------------------------------------------------------------------------- +// Constructor, destructor +//----------------------------------------------------------------------------- +CWorldManager::CWorldManager() +{ + m_pHeightField = NULL; +} + +CWorldManager::~CWorldManager() +{ + Assert( m_pHeightField == NULL ); +} + + +//----------------------------------------------------------------------------- +// Level init, shutdown +//----------------------------------------------------------------------------- +LevelRetVal_t CWorldManager::LevelInit( bool bFirstCall ) +{ + if ( !bFirstCall ) + return FINISHED; + + Assert( !m_pHeightField ); + m_pHeightField = new CHeightField( 6, 6, 4 ); + if ( !m_pHeightField->LoadHeightFromFile( "maps/testheight.psd" ) ) + return FAILED; + + CreateEntities(); + SetInitialLocalPlayerPosition(); + return FINISHED; +} + +LevelRetVal_t CWorldManager::LevelShutdown( bool bFirstCall ) +{ + if ( !bFirstCall ) + return FINISHED; + + DestroyEntities(); + + if ( m_pHeightField ) + { + delete m_pHeightField; + m_pHeightField = NULL; + } + return FINISHED; +} + + +//----------------------------------------------------------------------------- +// Create/ destroy entities +//----------------------------------------------------------------------------- +void CWorldManager::CreateEntities() +{ + m_PlayerEntity.m_pCameraProperty = g_pRenderManager->CreateCameraProperty(); +} + +void CWorldManager::DestroyEntities() +{ + g_pRenderManager->DestroyCameraProperty( m_PlayerEntity.m_pCameraProperty ); +} + + +//----------------------------------------------------------------------------- +// Gets the camera to world matrix +//----------------------------------------------------------------------------- +CPlayerEntity* CWorldManager::GetLocalPlayer() +{ + return &m_PlayerEntity; +} + + +//----------------------------------------------------------------------------- +// Sets the initial camera position +//----------------------------------------------------------------------------- +void CWorldManager::SetInitialLocalPlayerPosition() +{ + float flDistance = 1024.0; + Vector vecCameraDirection( 1.0f, 1.0f, -0.5f ); + VectorNormalize( vecCameraDirection ); + + VectorMA( Vector( 512, 512, 0 ), -flDistance, vecCameraDirection, m_PlayerEntity.m_pCameraProperty->m_Origin ); + + QAngle angles; + VectorAngles( vecCameraDirection, m_PlayerEntity.m_pCameraProperty->m_Angles ); + +} + + +//----------------------------------------------------------------------------- +// Draws the UI +//----------------------------------------------------------------------------- +void CWorldManager::DrawWorld() +{ + m_pHeightField->Draw( ); +} + + +//----------------------------------------------------------------------------- +// Commands +//----------------------------------------------------------------------------- +void CWorldManager::ForwardStart( const CCommand &args ) +{ + CCameraProperty *pCamera = m_PlayerEntity.m_pCameraProperty; + + Vector vecForward; + pCamera->GetForward( &vecForward ); + + VectorMA( pCamera->m_Velocity, cam_forwardspeed.GetFloat(), vecForward, pCamera->m_Velocity ); +} + +void CWorldManager::ForwardStop( const CCommand &args ) +{ + CCameraProperty *pCamera = m_PlayerEntity.m_pCameraProperty; + + Vector vecForward; + pCamera->GetForward( &vecForward ); + + VectorMA( pCamera->m_Velocity, -cam_forwardspeed.GetFloat(), vecForward, pCamera->m_Velocity ); +} + +void CWorldManager::BackwardStart( const CCommand &args ) +{ + CCameraProperty *pCamera = m_PlayerEntity.m_pCameraProperty; + + Vector vecForward; + pCamera->GetForward( &vecForward ); + + VectorMA( pCamera->m_Velocity, -cam_backwardspeed.GetFloat(), vecForward, pCamera->m_Velocity ); +} + +void CWorldManager::BackwardStop( const CCommand &args ) +{ + CCameraProperty *pCamera = m_PlayerEntity.m_pCameraProperty; + + Vector vecForward; + pCamera->GetForward( &vecForward ); + + VectorMA( pCamera->m_Velocity, cam_backwardspeed.GetFloat(), vecForward, pCamera->m_Velocity ); +}
\ No newline at end of file diff --git a/app/legion/worldmanager.h b/app/legion/worldmanager.h new file mode 100644 index 0000000..b1aa526 --- /dev/null +++ b/app/legion/worldmanager.h @@ -0,0 +1,84 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Contains all world state--the main game database +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#ifndef WORLDMANAGER_H +#define WORLDMANAGER_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "gamemanager.h" +#include "mathlib/mathlib.h" +#include "tier1/convar.h" + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CHeightField; +class CCameraProperty; + + +//----------------------------------------------------------------------------- +// Entity types +//----------------------------------------------------------------------------- +class CPlayerEntity +{ +public: + CCameraProperty *m_pCameraProperty; +}; + + +//----------------------------------------------------------------------------- +// World state +//----------------------------------------------------------------------------- +class CWorldManager : public CGameManager<> +{ +public: + CWorldManager(); + virtual ~CWorldManager(); + + // Inherited from IGameManager + virtual LevelRetVal_t LevelInit( bool bFirstCall ); +// virtual void Update( ); + virtual LevelRetVal_t LevelShutdown( bool bFirstCall ); + + // Draws the world + void DrawWorld(); + + // Gets the local player + CPlayerEntity *GetLocalPlayer(); + +private: + CON_COMMAND_MEMBER_F( CWorldManager, "+forward", ForwardStart, "Start forward movement", 0 ); + CON_COMMAND_MEMBER_F( CWorldManager, "-forward", ForwardStop, "Stop forward movement", 0 ); + CON_COMMAND_MEMBER_F( CWorldManager, "+back", BackwardStart, "Start backward movement", 0 ); + CON_COMMAND_MEMBER_F( CWorldManager, "-back", BackwardStop, "Stop backward movement", 0 ); + + // Creates, destroys entities + void CreateEntities(); + void DestroyEntities(); + + // Sets the initial camera position + void SetInitialLocalPlayerPosition(); + + CHeightField *m_pHeightField; + + CPlayerEntity m_PlayerEntity; +}; + + +//----------------------------------------------------------------------------- +// Singleton accessor +//----------------------------------------------------------------------------- +extern CWorldManager *g_pWorldManager; + + +#endif // WORLDMANAGER_H + |