PageRenderTime 54ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/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
  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: A panel "metaclass" is a name given to a particular type of
  4. // panel with particular instance data. Such panels tend to be dynamically
  5. // added and removed from their parent panels.
  6. //
  7. // $Workfile: $
  8. // $NoKeywords: $
  9. //=============================================================================//
  10. #include "cbase.h"
  11. #include "panelmetaclassmgr.h"
  12. #include <KeyValues.h>
  13. #include <vgui_controls/Panel.h>
  14. #include "utldict.h"
  15. #include "filesystem.h"
  16. #include <KeyValues.h>
  17. // memdbgon must be the last include file in a .cpp file!!!
  18. #include "tier0/memdbgon.h"
  19. //-----------------------------------------------------------------------------
  20. // Helper KeyValue parsing methods
  21. //-----------------------------------------------------------------------------
  22. bool ParseRGBA( KeyValues *pValues, const char* pFieldName, int& r, int& g, int& b, int& a )
  23. {
  24. r = g = b = a = 255;
  25. const char *pColorString = pValues->GetString( pFieldName, "255 255 255 255" );
  26. if ( !pColorString || !pColorString[ 0 ] )
  27. return false;
  28. // Try and scan them in
  29. int scanned;
  30. scanned = sscanf( pColorString, "%i %i %i %i", &r, &g, &b, &a );
  31. if ( scanned != 4 )
  32. {
  33. Warning( "Couldn't scan four color values from %s\n", pColorString );
  34. return false;
  35. }
  36. return true;
  37. }
  38. bool ParseRGBA( KeyValues* pValues, const char* pFieldName, Color& c )
  39. {
  40. int r, g, b, a;
  41. if (!ParseRGBA( pValues, pFieldName, r, g, b, a ))
  42. return false;
  43. c.SetColor( r, g, b, a );
  44. return true;
  45. }
  46. //-----------------------------------------------------------------------------
  47. // FIXME: Why do we have vgui::KeyValues too!?!??! Bleah
  48. /*-----------------------------------------------------------------------------
  49. bool ParseRGBA( KeyValues *pValues, const char* pFieldName, int& r, int& g, int& b, int& a )
  50. {
  51. r = g = b = a = 255;
  52. const char *pColorString = pValues->GetString( pFieldName, "255 255 255 255" );
  53. if ( !pColorString || !pColorString[ 0 ] )
  54. return false;
  55. // Try and scan them in
  56. int scanned;
  57. scanned = sscanf( pColorString, "%i %i %i %i", &r, &g, &b, &a );
  58. if ( scanned != 4 )
  59. {
  60. Warning( "Couldn't scan four color values from %s\n", pColorString );
  61. return false;
  62. }
  63. return true;
  64. }
  65. bool ParseRGBA( KeyValues* pValues, const char* pFieldName, Color& c )
  66. {
  67. int r, g, b, a;
  68. if (!ParseRGBA( pValues, pFieldName, r, g, b, a ))
  69. return false;
  70. c.SetColor( r, g, b, a );
  71. return true;
  72. } */
  73. bool ParseCoord( KeyValues *pValues, const char* pFieldName, int& x, int& y )
  74. {
  75. x = y = 0;
  76. const char *pCoordString = pValues->GetString( pFieldName, "0 0" );
  77. if ( !pCoordString || !pCoordString[ 0 ] )
  78. return false;
  79. // Try and scan them in
  80. int scanned;
  81. scanned = sscanf( pCoordString, "%i %i", &x, &y );
  82. if ( scanned != 2 )
  83. {
  84. Warning( "Couldn't scan 2d coordinate values from %s\n", pCoordString );
  85. return false;
  86. }
  87. // coords are within 640x480 screen space
  88. x = ( x * ( ( float )ScreenWidth() / 640.0 ) );
  89. y = ( y * ( ( float )ScreenHeight() / 480.0 ) );
  90. return true;
  91. }
  92. bool ParseRect( KeyValues *pValues, const char* pFieldName, int& x, int& y, int& w, int& h )
  93. {
  94. x = y = w = h = 0;
  95. const char *pRectString = pValues->GetString( pFieldName, "0 0 0 0" );
  96. if ( !pRectString || !pRectString[ 0 ] )
  97. return false;
  98. // Try and scan them in
  99. int scanned;
  100. scanned = sscanf( pRectString, "%i %i %i %i", &x, &y, &w, &h );
  101. if ( scanned != 4 )
  102. {
  103. Warning( "Couldn't scan rectangle values from %s\n", pRectString );
  104. return false;
  105. }
  106. // coords are within 640x480 screen space
  107. x = ( x * ( ( float )ScreenWidth() / 640.0 ) );
  108. y = ( y * ( ( float )ScreenHeight() / 480.0 ) );
  109. w = ( w * ( ( float )ScreenWidth() / 640.0 ) );
  110. h = ( h * ( ( float )ScreenHeight() / 480.0 ) );
  111. return true;
  112. }
  113. //-----------------------------------------------------------------------------
  114. // Helper class to make meta class panels (for use in entities, so they autocleanup)
  115. //-----------------------------------------------------------------------------
  116. CPanelWrapper::CPanelWrapper() : m_pPanel(NULL)
  117. {
  118. }
  119. CPanelWrapper::~CPanelWrapper()
  120. {
  121. Deactivate();
  122. }
  123. void CPanelWrapper::Activate( char const* pMetaClassName, vgui::Panel *pParent, int sortorder, void *pVoidInitData )
  124. {
  125. if ( m_pPanel )
  126. {
  127. Deactivate();
  128. }
  129. m_pPanel = PanelMetaClassMgr()->CreatePanelMetaClass( pMetaClassName, sortorder, pVoidInitData, pParent );
  130. }
  131. void CPanelWrapper::Deactivate( void )
  132. {
  133. if ( m_pPanel )
  134. {
  135. PanelMetaClassMgr()->DestroyPanelMetaClass( m_pPanel );
  136. m_pPanel = NULL;
  137. }
  138. }
  139. vgui::Panel *CPanelWrapper::GetPanel( )
  140. {
  141. return m_pPanel;
  142. }
  143. //-----------------------------------------------------------------------------
  144. // Purpose: Singleton class responsible for managing metaclass panels
  145. //-----------------------------------------------------------------------------
  146. class CPanelMetaClassMgrImp : public IPanelMetaClassMgr
  147. {
  148. public:
  149. // constructor, destructor
  150. CPanelMetaClassMgrImp();
  151. virtual ~CPanelMetaClassMgrImp();
  152. // Members of IPanelMetaClassMgr
  153. virtual void LoadMetaClassDefinitionFile( const char* pLevelName );
  154. virtual void InstallPanelType( const char* pPanelName, IPanelFactory* pFactory );
  155. virtual vgui::Panel *CreatePanelMetaClass( const char* pMetaClassName,
  156. int sortorder, void *pInitData, vgui::Panel *pParent, const char *pChainName );
  157. virtual void DestroyPanelMetaClass( vgui::Panel *pPanel );
  158. private:
  159. struct MetaClassDict_t
  160. {
  161. unsigned short m_KeyValueIndex;
  162. unsigned short m_TypeIndex;
  163. KeyValues* m_pKeyValues;
  164. };
  165. // various parsing helper methods
  166. bool ParseSingleMetaClass( const char* pFileName, const char* pInstanceName,
  167. KeyValues* pMetaClass, int keyValueIndex );
  168. bool ParseMetaClassList( const char* pFileName, KeyValues* pKeyValues, int keyValueIndex );
  169. // No copy constructor
  170. CPanelMetaClassMgrImp( const CPanelMetaClassMgrImp & );
  171. // List of panel types...
  172. CUtlDict< IPanelFactory*, unsigned short > m_PanelTypeDict;
  173. // List of metaclass types
  174. CUtlDict< MetaClassDict_t, unsigned short > m_MetaClassDict;
  175. // Create key value accesor
  176. CUtlDict< KeyValues*, unsigned short > m_MetaClassKeyValues;
  177. };
  178. //-----------------------------------------------------------------------------
  179. // Returns the singleton panel metaclass mgr interface
  180. //-----------------------------------------------------------------------------
  181. IPanelMetaClassMgr* PanelMetaClassMgr()
  182. {
  183. // NOTE: the CPanelFactory implementation requires the local static here
  184. // even though it means an extra check every time PanelMetaClassMgr is accessed
  185. static CPanelMetaClassMgrImp s_MetaClassMgrImp;
  186. return &s_MetaClassMgrImp;
  187. }
  188. //-----------------------------------------------------------------------------
  189. // constructor, destructor
  190. //-----------------------------------------------------------------------------
  191. CPanelMetaClassMgrImp::CPanelMetaClassMgrImp() : m_PanelTypeDict( true, 0, 32 )
  192. {
  193. }
  194. CPanelMetaClassMgrImp::~CPanelMetaClassMgrImp()
  195. {
  196. }
  197. //-----------------------------------------------------------------------------
  198. // Call this to install a new panel type
  199. //-----------------------------------------------------------------------------
  200. void CPanelMetaClassMgrImp::InstallPanelType( const char* pPanelName, IPanelFactory* pFactory )
  201. {
  202. Assert( pPanelName && pFactory );
  203. // convert to lowercase
  204. int len = Q_strlen(pPanelName) + 1;
  205. char* pTemp = (char*)stackalloc( len );
  206. Q_strncpy( pTemp, pPanelName, len );
  207. Q_strnlwr( pTemp, len );
  208. m_PanelTypeDict.Insert( pTemp, pFactory );
  209. stackfree( pTemp );
  210. }
  211. //-----------------------------------------------------------------------------
  212. // Parse a single metaclass
  213. //-----------------------------------------------------------------------------
  214. bool CPanelMetaClassMgrImp::ParseSingleMetaClass( const char* pFileName,
  215. const char* pMetaClassName, KeyValues* pMetaClassValues, int keyValueIndex )
  216. {
  217. // Complain about duplicately defined metaclass names...
  218. if ( m_MetaClassDict.Find( pMetaClassName ) != m_MetaClassDict.InvalidIndex() )
  219. {
  220. Warning( "Meta class %s duplicately defined (file %s)\n", pMetaClassName, pFileName );
  221. return false;
  222. }
  223. // find the type...
  224. const char* pPanelType = pMetaClassValues->GetString( "type" );
  225. if (!pPanelType || !pPanelType[0])
  226. {
  227. Warning( "Unable to find type of meta class %s in file %s\n", pMetaClassName, pFileName );
  228. return false;
  229. }
  230. unsigned short i = m_PanelTypeDict.Find( pPanelType );
  231. if (i == m_PanelTypeDict.InvalidIndex())
  232. {
  233. Warning( "Type %s of meta class %s undefined!\n", pPanelType, pMetaClassName );
  234. stackfree(pLwrMetaClass);
  235. return false;
  236. }
  237. // Add it to the metaclass dictionary
  238. MetaClassDict_t element;
  239. element.m_TypeIndex = i;
  240. element.m_KeyValueIndex = keyValueIndex;
  241. element.m_pKeyValues = pMetaClassValues;
  242. m_MetaClassDict.Insert( pMetaClassName, element );
  243. return true;
  244. }
  245. //-----------------------------------------------------------------------------
  246. // Parse the metaclass list
  247. //-----------------------------------------------------------------------------
  248. bool CPanelMetaClassMgrImp::ParseMetaClassList( const char* pFileName,
  249. KeyValues* pKeyValues, int keyValueIdx )
  250. {
  251. // Iterate over all metaclasses...
  252. KeyValues* pIter = pKeyValues->GetFirstSubKey();
  253. while( pIter )
  254. {
  255. if (!ParseSingleMetaClass( pFileName, pIter->GetName(), pIter, keyValueIdx ))
  256. {
  257. // return false;
  258. Warning( "MetaClass missing for %s\n", pIter->GetName() );
  259. }
  260. pIter = pIter->GetNextKey();
  261. }
  262. return true;
  263. }
  264. //-----------------------------------------------------------------------------
  265. // Loads up a file containing metaclass definitions
  266. //-----------------------------------------------------------------------------
  267. void CPanelMetaClassMgrImp::LoadMetaClassDefinitionFile( const char *pFileName )
  268. {
  269. MEM_ALLOC_CREDIT();
  270. // Blat out previous metaclass definitions read in from this file...
  271. int i = m_MetaClassKeyValues.Find( pFileName );
  272. if (i != m_MetaClassKeyValues.InvalidIndex() )
  273. {
  274. // Blow away the previous keyvalues from that file
  275. unsigned short j = m_MetaClassDict.First();
  276. while ( j != m_MetaClassDict.InvalidIndex() )
  277. {
  278. unsigned short next = m_MetaClassDict.Next(j);
  279. if ( m_MetaClassDict[j].m_KeyValueIndex == i)
  280. {
  281. m_MetaClassDict.RemoveAt(j);
  282. }
  283. j = next;
  284. }
  285. m_MetaClassKeyValues[i]->deleteThis();
  286. m_MetaClassKeyValues.RemoveAt(i);
  287. }
  288. // Create a new keyvalues entry
  289. KeyValues* pKeyValues = new KeyValues(pFileName);
  290. int idx = m_MetaClassKeyValues.Insert( pFileName, pKeyValues );
  291. // Read in all metaclass definitions...
  292. // Load the file
  293. if ( !pKeyValues->LoadFromFile( filesystem, pFileName ) )
  294. {
  295. Warning( "Couldn't find metaclass definition file %s\n", pFileName );
  296. pKeyValues->deleteThis();
  297. m_MetaClassKeyValues.RemoveAt(idx);
  298. return;
  299. }
  300. else
  301. {
  302. // Go ahead and parse the data now
  303. if ( !ParseMetaClassList( pFileName, pKeyValues, idx ) )
  304. {
  305. Warning( "Detected one or more errors parsing %s\n", pFileName );
  306. }
  307. }
  308. }
  309. //-----------------------------------------------------------------------------
  310. // Performs key value chaining
  311. //-----------------------------------------------------------------------------
  312. static void KeyValueChainRecursive( KeyValues* pKeyValues, const char *pSectionName )
  313. {
  314. KeyValues* pSection = pKeyValues->FindKey( pSectionName );
  315. if (pSection)
  316. {
  317. pKeyValues->ChainKeyValue( pSection );
  318. }
  319. KeyValues* pIter = pKeyValues->GetFirstSubKey();
  320. while (pIter)
  321. {
  322. // Don't both setting up links on a keyvalue that has no children
  323. if (pIter->GetFirstSubKey())
  324. KeyValueChainRecursive( pIter, pSectionName );
  325. pIter = pIter->GetNextKey();
  326. }
  327. }
  328. //-----------------------------------------------------------------------------
  329. // Create, destroy panel...
  330. //-----------------------------------------------------------------------------
  331. vgui::Panel *CPanelMetaClassMgrImp::CreatePanelMetaClass( const char* pMetaClassName,
  332. int sortorder, void *pInitData, vgui::Panel *pParent, const char *pChainName )
  333. {
  334. // Search for the metaclass name
  335. int i = m_MetaClassDict.Find( pMetaClassName );
  336. if (i == m_MetaClassDict.InvalidIndex())
  337. return NULL;
  338. // Now that we've got the metaclass, we can figure out what kind of
  339. // panel to instantiate...
  340. MetaClassDict_t &metaClass = m_MetaClassDict[i];
  341. IPanelFactory* pFactory = m_PanelTypeDict[metaClass.m_TypeIndex];
  342. // Set up the key values for use in initialization
  343. if (pChainName)
  344. {
  345. KeyValueChainRecursive( metaClass.m_pKeyValues, pChainName );
  346. }
  347. // Create and initialize the panel
  348. vgui::Panel *pPanel = pFactory->Create( pMetaClassName, metaClass.m_pKeyValues, pInitData, pParent );
  349. if ( pPanel )
  350. {
  351. pPanel->SetZPos( sortorder );
  352. }
  353. return pPanel;
  354. }
  355. void CPanelMetaClassMgrImp::DestroyPanelMetaClass( vgui::Panel *pPanel )
  356. {
  357. // if ( pPanel )
  358. // pPanel->MarkForDeletion();
  359. delete pPanel;
  360. }