Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

196 lines
5.8 KiB

5 years ago
//========= 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 );
}