Team Fortress 2 Source Code as on 22/4/2020
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.

483 lines
12 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "client_pch.h"
  8. #include <vgui/VGUI.h>
  9. #include <vgui_controls/Controls.h>
  10. #include "cl_demoaction.h"
  11. #include "cl_demoactionmanager.h"
  12. #include "cl_demouipanel.h"
  13. // memdbgon must be the last include file in a .cpp file!!!
  14. #include "tier0/memdbgon.h"
  15. using namespace vgui;
  16. //-----------------------------------------------------------------------------
  17. // Purpose:
  18. //-----------------------------------------------------------------------------
  19. class CDemoActionManager : public IDemoActionManager
  20. {
  21. public:
  22. CDemoActionManager();
  23. ~CDemoActionManager();
  24. // Public interface
  25. public:
  26. virtual void Init( void );
  27. virtual void Shutdown( void );
  28. virtual void StartPlaying( char const *demfilename );
  29. virtual void StopPlaying();
  30. virtual void Update( bool newframe, int demotick, float demotime );
  31. virtual void SaveToBuffer( CUtlBuffer& buf );
  32. virtual void SaveToFile( void );
  33. virtual char const *GetCurrentDemoFile( void );
  34. virtual int GetActionCount( void );
  35. virtual CBaseDemoAction *GetAction( int index );
  36. virtual void AddAction( CBaseDemoAction *action );
  37. virtual void RemoveAction( CBaseDemoAction *action );
  38. virtual bool IsDirty( void ) const;
  39. virtual void SetDirty( bool dirty );
  40. virtual void ReloadFromDisk( void );
  41. virtual void DispatchEvents();
  42. virtual void InsertFireEvent( CBaseDemoAction *action );
  43. virtual bool OverrideView( democmdinfo_t& info, int tick );
  44. private:
  45. void OnVDMLoaded( char const *demfilename );
  46. void ClearAll();
  47. CUtlVector< CBaseDemoAction * > m_ActionStack;
  48. CUtlVector< CBaseDemoAction * > m_PendingFireActionStack;
  49. int m_nPrevTick;
  50. float m_flPrevTime;
  51. bool m_bDirty;
  52. char m_szCurrentFile[ MAX_OSPATH ];
  53. long m_lFileTime;
  54. };
  55. static CDemoActionManager g_DemoActionManager;
  56. IDemoActionManager *demoaction = ( IDemoActionManager * )&g_DemoActionManager;
  57. //-----------------------------------------------------------------------------
  58. // Purpose:
  59. //-----------------------------------------------------------------------------
  60. CDemoActionManager::CDemoActionManager()
  61. {
  62. m_nPrevTick = 0;
  63. m_flPrevTime = 0.0f;
  64. m_szCurrentFile[ 0 ] = 0;
  65. m_bDirty = false;
  66. m_lFileTime = -1;
  67. }
  68. //-----------------------------------------------------------------------------
  69. // Purpose:
  70. //-----------------------------------------------------------------------------
  71. CDemoActionManager::~CDemoActionManager()
  72. {
  73. }
  74. //-----------------------------------------------------------------------------
  75. // Purpose:
  76. //-----------------------------------------------------------------------------
  77. void CDemoActionManager::Init( void )
  78. {
  79. }
  80. //-----------------------------------------------------------------------------
  81. // Purpose:
  82. //-----------------------------------------------------------------------------
  83. void CDemoActionManager::Shutdown( void )
  84. {
  85. StopPlaying();
  86. ClearAll();
  87. m_ActionStack.Purge();
  88. m_PendingFireActionStack.Purge();
  89. }
  90. //-----------------------------------------------------------------------------
  91. // Purpose: Reload without saving
  92. //-----------------------------------------------------------------------------
  93. void CDemoActionManager::ReloadFromDisk( void )
  94. {
  95. char metafile[ 512 ];
  96. Q_StripExtension( m_szCurrentFile, metafile, sizeof( metafile ) );
  97. Q_DefaultExtension( metafile, ".vdm", sizeof( metafile ) );
  98. ClearAll();
  99. //const char *buffer = NULL;
  100. //int sz = 0;
  101. //buffer = (const char *)COM_LoadFile( metafile, 5, &sz );
  102. // if ( buffer )
  103. // {
  104. m_lFileTime = g_pFileSystem->GetFileTime( metafile );
  105. KeyValues *kv = new KeyValues( metafile );
  106. Assert( kv );
  107. if ( kv )
  108. {
  109. if ( kv->LoadFromFile( g_pFullFileSystem, metafile ) )
  110. {
  111. // Iterate over all metaclasses...
  112. KeyValues* pIter = kv->GetFirstSubKey();
  113. while( pIter )
  114. {
  115. char factorytouse[ 512 ];
  116. Q_strncpy( factorytouse, pIter->GetName(), sizeof( factorytouse ) );
  117. // New format is to put numbers in here
  118. if ( atoi( factorytouse ) > 0 )
  119. {
  120. Q_strncpy( factorytouse, pIter->GetString( "factory", "" ), sizeof( factorytouse ) );
  121. }
  122. CBaseDemoAction *action = CBaseDemoAction::CreateDemoAction( CBaseDemoAction::TypeForName( factorytouse ) );
  123. if ( action )
  124. {
  125. if ( !action->Init( pIter ) )
  126. {
  127. delete action;
  128. }
  129. else
  130. {
  131. m_ActionStack.AddToTail( action );
  132. }
  133. }
  134. pIter = pIter->GetNextKey();
  135. }
  136. }
  137. else
  138. {
  139. SaveToFile();
  140. }
  141. }
  142. // }
  143. // else
  144. // {
  145. // This will save out an empty .vdm of the proper name
  146. // SaveToFile();
  147. // }
  148. OnVDMLoaded( m_szCurrentFile );
  149. m_bDirty = false;
  150. }
  151. //-----------------------------------------------------------------------------
  152. // Purpose:
  153. // Input : *demfilename -
  154. //-----------------------------------------------------------------------------
  155. void CDemoActionManager::StartPlaying( char const *demfilename )
  156. {
  157. Assert( demfilename );
  158. // Clear anything currently pending
  159. StopPlaying();
  160. bool changedfile = Q_strcasecmp( demfilename, m_szCurrentFile ) != 0;
  161. Q_strncpy( m_szCurrentFile, demfilename, sizeof( m_szCurrentFile ) );
  162. char metafile[ 512 ];
  163. Q_StripExtension( demfilename, metafile, sizeof( metafile ) );
  164. Q_DefaultExtension( metafile, ".vdm", sizeof( metafile ) );
  165. long filetime = g_pFileSystem->GetFileTime( metafile );
  166. // If didn't change file and the timestamps are the same, don't transition to new .vdm
  167. if ( !changedfile && ( m_lFileTime == filetime ) )
  168. {
  169. return;
  170. }
  171. if ( m_bDirty )
  172. {
  173. SaveToFile();
  174. }
  175. ReloadFromDisk();
  176. }
  177. //-----------------------------------------------------------------------------
  178. // Purpose:
  179. //-----------------------------------------------------------------------------
  180. void CDemoActionManager::ClearAll()
  181. {
  182. m_PendingFireActionStack.RemoveAll();
  183. while ( m_ActionStack.Count() > 0 )
  184. {
  185. CBaseDemoAction *a = m_ActionStack[ 0 ];
  186. delete a;
  187. m_ActionStack.Remove( 0 );
  188. }
  189. }
  190. //-----------------------------------------------------------------------------
  191. // Purpose:
  192. //-----------------------------------------------------------------------------
  193. void CDemoActionManager::StopPlaying()
  194. {
  195. int count = m_ActionStack.Count();
  196. for ( int i = 0; i < count; i++ )
  197. {
  198. CBaseDemoAction *a = m_ActionStack[ i ];
  199. a->Reset();
  200. }
  201. // Reset counters
  202. m_nPrevTick = 0;
  203. m_flPrevTime = 0.0f;
  204. m_PendingFireActionStack.RemoveAll();
  205. }
  206. //-----------------------------------------------------------------------------
  207. // Purpose:
  208. // Input : demoframe -
  209. // demotime -
  210. //-----------------------------------------------------------------------------
  211. void CDemoActionManager::Update( bool newframe, int demotick, float demotime )
  212. {
  213. // Nothing to do?
  214. int count = m_ActionStack.Count();
  215. if ( count <= 0 )
  216. return;
  217. // Setup timing context
  218. DemoActionTimingContext ctx;
  219. ctx.prevtick = m_nPrevTick;
  220. ctx.curtick = demotick;
  221. ctx.prevtime = m_flPrevTime;
  222. ctx.curtime = demotime;
  223. int i;
  224. for ( i = 0; i < count; i++ )
  225. {
  226. CBaseDemoAction *action = m_ActionStack[ i ];
  227. Assert( action );
  228. if ( !action )
  229. continue;
  230. action->Update( ctx );
  231. }
  232. m_nPrevTick = demotick;
  233. m_flPrevTime = demotime;
  234. }
  235. //-----------------------------------------------------------------------------
  236. // Purpose:
  237. // Input : buf -
  238. //-----------------------------------------------------------------------------
  239. void CDemoActionManager::SaveToBuffer( CUtlBuffer& buf )
  240. {
  241. buf.Printf( "demoactions\n" );
  242. buf.Printf( "{\n" );
  243. int count = m_ActionStack.Count();
  244. int i;
  245. for ( i = 0; i < count; i++ )
  246. {
  247. CBaseDemoAction *action = m_ActionStack[ i ];
  248. Assert( action );
  249. if ( !action )
  250. continue;
  251. action->SaveToBuffer( 1, i + 1, buf );
  252. }
  253. buf.Printf( "}\n" );
  254. }
  255. //-----------------------------------------------------------------------------
  256. // Purpose:
  257. // Input : *demfilename -
  258. //-----------------------------------------------------------------------------
  259. void CDemoActionManager::SaveToFile( void )
  260. {
  261. // Nothing loaded
  262. if ( m_szCurrentFile[ 0 ] == 0 )
  263. return;
  264. // It's not dirty
  265. if ( !m_bDirty )
  266. return;
  267. char metafile[ 512 ];
  268. Q_StripExtension( m_szCurrentFile, metafile, sizeof( metafile ) );
  269. Q_DefaultExtension( metafile, ".vdm", sizeof( metafile ) );
  270. // Save data
  271. CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
  272. SaveToBuffer( buf );
  273. // Write to file
  274. FileHandle_t fh;
  275. fh = g_pFileSystem->Open( metafile, "w" );
  276. if ( fh != FILESYSTEM_INVALID_HANDLE )
  277. {
  278. g_pFileSystem->Write( buf.Base(), buf.TellPut(), fh );
  279. g_pFileSystem->Close( fh );
  280. }
  281. m_bDirty = false;
  282. // Make sure filetime is up to date
  283. m_lFileTime = g_pFileSystem->GetFileTime( metafile );
  284. }
  285. //-----------------------------------------------------------------------------
  286. // Purpose:
  287. // Input : *demfilename -
  288. //-----------------------------------------------------------------------------
  289. void CDemoActionManager::OnVDMLoaded( char const *demfilename )
  290. {
  291. // Notify UI?
  292. if ( g_pDemoUI )
  293. {
  294. g_pDemoUI->OnVDMChanged();
  295. }
  296. if ( g_pDemoUI2 )
  297. {
  298. g_pDemoUI2->OnVDMChanged();
  299. }
  300. }
  301. char const *CDemoActionManager::GetCurrentDemoFile( void )
  302. {
  303. return m_szCurrentFile;
  304. }
  305. //-----------------------------------------------------------------------------
  306. // Purpose:
  307. // Output : int
  308. //-----------------------------------------------------------------------------
  309. int CDemoActionManager::GetActionCount( void )
  310. {
  311. int count = m_ActionStack.Count();
  312. return count;
  313. }
  314. //-----------------------------------------------------------------------------
  315. // Purpose:
  316. // Input : index -
  317. // Output : CBaseDemoAction
  318. //-----------------------------------------------------------------------------
  319. CBaseDemoAction *CDemoActionManager::GetAction( int index )
  320. {
  321. int count = m_ActionStack.Count();
  322. if ( index < 0 || index >= count )
  323. return NULL;
  324. return m_ActionStack[ index ];
  325. }
  326. //-----------------------------------------------------------------------------
  327. // Purpose:
  328. // Input : *action -
  329. //-----------------------------------------------------------------------------
  330. void CDemoActionManager::AddAction( CBaseDemoAction *action )
  331. {
  332. m_bDirty = true;
  333. Assert( action );
  334. m_ActionStack.AddToTail( action );
  335. }
  336. //-----------------------------------------------------------------------------
  337. // Purpose:
  338. // Input : *action -
  339. //-----------------------------------------------------------------------------
  340. void CDemoActionManager::RemoveAction( CBaseDemoAction *action )
  341. {
  342. Assert( action );
  343. m_bDirty = true;
  344. m_ActionStack.FindAndRemove( action );
  345. delete action;
  346. }
  347. //-----------------------------------------------------------------------------
  348. // Purpose:
  349. // Output : Returns true on success, false on failure.
  350. //-----------------------------------------------------------------------------
  351. bool CDemoActionManager::IsDirty( void ) const
  352. {
  353. return m_bDirty;
  354. }
  355. //-----------------------------------------------------------------------------
  356. // Purpose:
  357. // Input : dirty -
  358. //-----------------------------------------------------------------------------
  359. void CDemoActionManager::SetDirty( bool dirty )
  360. {
  361. m_bDirty = true;
  362. }
  363. //-----------------------------------------------------------------------------
  364. // Purpose:
  365. // Input : *action -
  366. //-----------------------------------------------------------------------------
  367. void CDemoActionManager::InsertFireEvent( CBaseDemoAction *action )
  368. {
  369. // BUGBUG: Sometimes this can get called multiple times for the same event before DispatchEvents() is called. Why?
  370. // If that gets fixed, remove this hack.
  371. if ( m_PendingFireActionStack.Find(action) >= 0 )
  372. return;
  373. m_PendingFireActionStack.AddToTail( action );
  374. }
  375. //-----------------------------------------------------------------------------
  376. // Purpose:
  377. //-----------------------------------------------------------------------------
  378. void CDemoActionManager::DispatchEvents()
  379. {
  380. int c = m_PendingFireActionStack.Count();
  381. int i;
  382. for ( i = 0; i < c; i++ )
  383. {
  384. CBaseDemoAction *action = m_PendingFireActionStack[ i ];
  385. Assert( action );
  386. action->FireAction();
  387. action->SetActionFired( true );
  388. }
  389. m_PendingFireActionStack.RemoveAll();
  390. }
  391. bool CDemoActionManager::OverrideView( democmdinfo_t& info, int tick )
  392. {
  393. // override view
  394. return false;
  395. }