/AI_Patch/src/game/client/panelmetaclassmgr.cpp
C++ | 437 lines | 256 code | 73 blank | 108 comment | 38 complexity | b00bb5fc263498d5ee1b6195776a783d MD5 | raw file
Possible License(s): BSD-3-Clause
- //========= Copyright Valve Corporation, All rights reserved. ============//
- //
- // Purpose: A panel "metaclass" is a name given to a particular type of
- // panel with particular instance data. Such panels tend to be dynamically
- // added and removed from their parent panels.
- //
- // $Workfile: $
- // $NoKeywords: $
- //=============================================================================//
- #include "cbase.h"
- #include "panelmetaclassmgr.h"
- #include <KeyValues.h>
- #include <vgui_controls/Panel.h>
- #include "utldict.h"
- #include "filesystem.h"
- #include <KeyValues.h>
-
- // memdbgon must be the last include file in a .cpp file!!!
- #include "tier0/memdbgon.h"
-
- //-----------------------------------------------------------------------------
- // Helper KeyValue parsing methods
- //-----------------------------------------------------------------------------
- bool ParseRGBA( KeyValues *pValues, const char* pFieldName, int& r, int& g, int& b, int& a )
- {
- r = g = b = a = 255;
- const char *pColorString = pValues->GetString( pFieldName, "255 255 255 255" );
- if ( !pColorString || !pColorString[ 0 ] )
- return false;
-
- // Try and scan them in
- int scanned;
- scanned = sscanf( pColorString, "%i %i %i %i", &r, &g, &b, &a );
- if ( scanned != 4 )
- {
- Warning( "Couldn't scan four color values from %s\n", pColorString );
- return false;
- }
-
- return true;
- }
-
- bool ParseRGBA( KeyValues* pValues, const char* pFieldName, Color& c )
- {
- int r, g, b, a;
- if (!ParseRGBA( pValues, pFieldName, r, g, b, a ))
- return false;
-
- c.SetColor( r, g, b, a );
- return true;
- }
-
- //-----------------------------------------------------------------------------
- // FIXME: Why do we have vgui::KeyValues too!?!??! Bleah
- /*-----------------------------------------------------------------------------
- bool ParseRGBA( KeyValues *pValues, const char* pFieldName, int& r, int& g, int& b, int& a )
- {
- r = g = b = a = 255;
- const char *pColorString = pValues->GetString( pFieldName, "255 255 255 255" );
- if ( !pColorString || !pColorString[ 0 ] )
- return false;
-
- // Try and scan them in
- int scanned;
- scanned = sscanf( pColorString, "%i %i %i %i", &r, &g, &b, &a );
- if ( scanned != 4 )
- {
- Warning( "Couldn't scan four color values from %s\n", pColorString );
- return false;
- }
-
- return true;
- }
-
- bool ParseRGBA( KeyValues* pValues, const char* pFieldName, Color& c )
- {
- int r, g, b, a;
- if (!ParseRGBA( pValues, pFieldName, r, g, b, a ))
- return false;
-
- c.SetColor( r, g, b, a );
- return true;
- } */
-
-
- bool ParseCoord( KeyValues *pValues, const char* pFieldName, int& x, int& y )
- {
- x = y = 0;
- const char *pCoordString = pValues->GetString( pFieldName, "0 0" );
- if ( !pCoordString || !pCoordString[ 0 ] )
- return false;
-
- // Try and scan them in
- int scanned;
- scanned = sscanf( pCoordString, "%i %i", &x, &y );
- if ( scanned != 2 )
- {
- Warning( "Couldn't scan 2d coordinate values from %s\n", pCoordString );
- return false;
- }
-
- // coords are within 640x480 screen space
- x = ( x * ( ( float )ScreenWidth() / 640.0 ) );
- y = ( y * ( ( float )ScreenHeight() / 480.0 ) );
-
- return true;
- }
-
- bool ParseRect( KeyValues *pValues, const char* pFieldName, int& x, int& y, int& w, int& h )
- {
- x = y = w = h = 0;
- const char *pRectString = pValues->GetString( pFieldName, "0 0 0 0" );
- if ( !pRectString || !pRectString[ 0 ] )
- return false;
-
- // Try and scan them in
- int scanned;
- scanned = sscanf( pRectString, "%i %i %i %i", &x, &y, &w, &h );
- if ( scanned != 4 )
- {
- Warning( "Couldn't scan rectangle values from %s\n", pRectString );
- return false;
- }
-
- // coords are within 640x480 screen space
- x = ( x * ( ( float )ScreenWidth() / 640.0 ) );
- y = ( y * ( ( float )ScreenHeight() / 480.0 ) );
- w = ( w * ( ( float )ScreenWidth() / 640.0 ) );
- h = ( h * ( ( float )ScreenHeight() / 480.0 ) );
-
- return true;
- }
-
-
- //-----------------------------------------------------------------------------
- // Helper class to make meta class panels (for use in entities, so they autocleanup)
- //-----------------------------------------------------------------------------
- CPanelWrapper::CPanelWrapper() : m_pPanel(NULL)
- {
- }
-
- CPanelWrapper::~CPanelWrapper()
- {
- Deactivate();
- }
-
- void CPanelWrapper::Activate( char const* pMetaClassName, vgui::Panel *pParent, int sortorder, void *pVoidInitData )
- {
- if ( m_pPanel )
- {
- Deactivate();
- }
-
- m_pPanel = PanelMetaClassMgr()->CreatePanelMetaClass( pMetaClassName, sortorder, pVoidInitData, pParent );
- }
-
- void CPanelWrapper::Deactivate( void )
- {
- if ( m_pPanel )
- {
- PanelMetaClassMgr()->DestroyPanelMetaClass( m_pPanel );
- m_pPanel = NULL;
- }
- }
-
- vgui::Panel *CPanelWrapper::GetPanel( )
- {
- return m_pPanel;
- }
-
-
- //-----------------------------------------------------------------------------
- // Purpose: Singleton class responsible for managing metaclass panels
- //-----------------------------------------------------------------------------
- class CPanelMetaClassMgrImp : public IPanelMetaClassMgr
- {
- public:
- // constructor, destructor
- CPanelMetaClassMgrImp();
- virtual ~CPanelMetaClassMgrImp();
-
- // Members of IPanelMetaClassMgr
- virtual void LoadMetaClassDefinitionFile( const char* pLevelName );
- virtual void InstallPanelType( const char* pPanelName, IPanelFactory* pFactory );
- virtual vgui::Panel *CreatePanelMetaClass( const char* pMetaClassName,
- int sortorder, void *pInitData, vgui::Panel *pParent, const char *pChainName );
- virtual void DestroyPanelMetaClass( vgui::Panel *pPanel );
-
- private:
- struct MetaClassDict_t
- {
- unsigned short m_KeyValueIndex;
- unsigned short m_TypeIndex;
- KeyValues* m_pKeyValues;
- };
-
- // various parsing helper methods
- bool ParseSingleMetaClass( const char* pFileName, const char* pInstanceName,
- KeyValues* pMetaClass, int keyValueIndex );
- bool ParseMetaClassList( const char* pFileName, KeyValues* pKeyValues, int keyValueIndex );
-
- // No copy constructor
- CPanelMetaClassMgrImp( const CPanelMetaClassMgrImp & );
-
- // List of panel types...
- CUtlDict< IPanelFactory*, unsigned short > m_PanelTypeDict;
-
- // List of metaclass types
- CUtlDict< MetaClassDict_t, unsigned short > m_MetaClassDict;
-
- // Create key value accesor
- CUtlDict< KeyValues*, unsigned short > m_MetaClassKeyValues;
- };
-
-
- //-----------------------------------------------------------------------------
- // Returns the singleton panel metaclass mgr interface
- //-----------------------------------------------------------------------------
- IPanelMetaClassMgr* PanelMetaClassMgr()
- {
- // NOTE: the CPanelFactory implementation requires the local static here
- // even though it means an extra check every time PanelMetaClassMgr is accessed
- static CPanelMetaClassMgrImp s_MetaClassMgrImp;
- return &s_MetaClassMgrImp;
- }
-
-
- //-----------------------------------------------------------------------------
- // constructor, destructor
- //-----------------------------------------------------------------------------
- CPanelMetaClassMgrImp::CPanelMetaClassMgrImp() : m_PanelTypeDict( true, 0, 32 )
- {
- }
-
- CPanelMetaClassMgrImp::~CPanelMetaClassMgrImp()
- {
- }
-
-
- //-----------------------------------------------------------------------------
- // Call this to install a new panel type
- //-----------------------------------------------------------------------------
- void CPanelMetaClassMgrImp::InstallPanelType( const char* pPanelName, IPanelFactory* pFactory )
- {
- Assert( pPanelName && pFactory );
-
- // convert to lowercase
- int len = Q_strlen(pPanelName) + 1;
- char* pTemp = (char*)stackalloc( len );
- Q_strncpy( pTemp, pPanelName, len );
- Q_strnlwr( pTemp, len );
-
- m_PanelTypeDict.Insert( pTemp, pFactory );
-
- stackfree( pTemp );
- }
-
-
- //-----------------------------------------------------------------------------
- // Parse a single metaclass
- //-----------------------------------------------------------------------------
- bool CPanelMetaClassMgrImp::ParseSingleMetaClass( const char* pFileName,
- const char* pMetaClassName, KeyValues* pMetaClassValues, int keyValueIndex )
- {
- // Complain about duplicately defined metaclass names...
- if ( m_MetaClassDict.Find( pMetaClassName ) != m_MetaClassDict.InvalidIndex() )
- {
- Warning( "Meta class %s duplicately defined (file %s)\n", pMetaClassName, pFileName );
- return false;
- }
-
- // find the type...
- const char* pPanelType = pMetaClassValues->GetString( "type" );
- if (!pPanelType || !pPanelType[0])
- {
- Warning( "Unable to find type of meta class %s in file %s\n", pMetaClassName, pFileName );
- return false;
- }
-
- unsigned short i = m_PanelTypeDict.Find( pPanelType );
- if (i == m_PanelTypeDict.InvalidIndex())
- {
- Warning( "Type %s of meta class %s undefined!\n", pPanelType, pMetaClassName );
- stackfree(pLwrMetaClass);
- return false;
- }
-
- // Add it to the metaclass dictionary
- MetaClassDict_t element;
- element.m_TypeIndex = i;
- element.m_KeyValueIndex = keyValueIndex;
- element.m_pKeyValues = pMetaClassValues;
- m_MetaClassDict.Insert( pMetaClassName, element );
-
- return true;
- }
-
-
- //-----------------------------------------------------------------------------
- // Parse the metaclass list
- //-----------------------------------------------------------------------------
- bool CPanelMetaClassMgrImp::ParseMetaClassList( const char* pFileName,
- KeyValues* pKeyValues, int keyValueIdx )
- {
- // Iterate over all metaclasses...
- KeyValues* pIter = pKeyValues->GetFirstSubKey();
- while( pIter )
- {
- if (!ParseSingleMetaClass( pFileName, pIter->GetName(), pIter, keyValueIdx ))
- {
- // return false;
- Warning( "MetaClass missing for %s\n", pIter->GetName() );
- }
- pIter = pIter->GetNextKey();
- }
-
- return true;
- }
-
-
- //-----------------------------------------------------------------------------
- // Loads up a file containing metaclass definitions
- //-----------------------------------------------------------------------------
- void CPanelMetaClassMgrImp::LoadMetaClassDefinitionFile( const char *pFileName )
- {
- MEM_ALLOC_CREDIT();
-
- // Blat out previous metaclass definitions read in from this file...
- int i = m_MetaClassKeyValues.Find( pFileName );
- if (i != m_MetaClassKeyValues.InvalidIndex() )
- {
- // Blow away the previous keyvalues from that file
- unsigned short j = m_MetaClassDict.First();
- while ( j != m_MetaClassDict.InvalidIndex() )
- {
- unsigned short next = m_MetaClassDict.Next(j);
- if ( m_MetaClassDict[j].m_KeyValueIndex == i)
- {
- m_MetaClassDict.RemoveAt(j);
- }
-
- j = next;
- }
-
- m_MetaClassKeyValues[i]->deleteThis();
- m_MetaClassKeyValues.RemoveAt(i);
- }
-
- // Create a new keyvalues entry
- KeyValues* pKeyValues = new KeyValues(pFileName);
- int idx = m_MetaClassKeyValues.Insert( pFileName, pKeyValues );
-
- // Read in all metaclass definitions...
-
- // Load the file
- if ( !pKeyValues->LoadFromFile( filesystem, pFileName ) )
- {
- Warning( "Couldn't find metaclass definition file %s\n", pFileName );
- pKeyValues->deleteThis();
- m_MetaClassKeyValues.RemoveAt(idx);
- return;
- }
- else
- {
- // Go ahead and parse the data now
- if ( !ParseMetaClassList( pFileName, pKeyValues, idx ) )
- {
- Warning( "Detected one or more errors parsing %s\n", pFileName );
- }
- }
- }
-
-
- //-----------------------------------------------------------------------------
- // Performs key value chaining
- //-----------------------------------------------------------------------------
- static void KeyValueChainRecursive( KeyValues* pKeyValues, const char *pSectionName )
- {
- KeyValues* pSection = pKeyValues->FindKey( pSectionName );
-
- if (pSection)
- {
- pKeyValues->ChainKeyValue( pSection );
- }
-
- KeyValues* pIter = pKeyValues->GetFirstSubKey();
- while (pIter)
- {
- // Don't both setting up links on a keyvalue that has no children
- if (pIter->GetFirstSubKey())
- KeyValueChainRecursive( pIter, pSectionName );
-
- pIter = pIter->GetNextKey();
- }
- }
-
-
- //-----------------------------------------------------------------------------
- // Create, destroy panel...
- //-----------------------------------------------------------------------------
- vgui::Panel *CPanelMetaClassMgrImp::CreatePanelMetaClass( const char* pMetaClassName,
- int sortorder, void *pInitData, vgui::Panel *pParent, const char *pChainName )
- {
- // Search for the metaclass name
- int i = m_MetaClassDict.Find( pMetaClassName );
- if (i == m_MetaClassDict.InvalidIndex())
- return NULL;
-
- // Now that we've got the metaclass, we can figure out what kind of
- // panel to instantiate...
- MetaClassDict_t &metaClass = m_MetaClassDict[i];
- IPanelFactory* pFactory = m_PanelTypeDict[metaClass.m_TypeIndex];
-
- // Set up the key values for use in initialization
- if (pChainName)
- {
- KeyValueChainRecursive( metaClass.m_pKeyValues, pChainName );
- }
-
- // Create and initialize the panel
- vgui::Panel *pPanel = pFactory->Create( pMetaClassName, metaClass.m_pKeyValues, pInitData, pParent );
- if ( pPanel )
- {
- pPanel->SetZPos( sortorder );
- }
-
- return pPanel;
- }
-
- void CPanelMetaClassMgrImp::DestroyPanelMetaClass( vgui::Panel *pPanel )
- {
- // if ( pPanel )
- // pPanel->MarkForDeletion();
- delete pPanel;
- }
-
-