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.

332 lines
8.8 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include <stdafx.h>
  8. #include "GlobalFunctions.h"
  9. #include "History.h"
  10. #include "MainFrm.h"
  11. #include "MapAnimator.h"
  12. #include "MapAnimationDlg.h"
  13. #include "MapClass.h"
  14. #include "MapDoc.h"
  15. #include "MapEntity.h"
  16. #include "MapWorld.h"
  17. #include "hammer.h"
  18. #include "Selection.h"
  19. // memdbgon must be the last include file in a .cpp file!!!
  20. #include <tier0/memdbgon.h>
  21. BEGIN_MESSAGE_MAP( CMapAnimationDlg, CHammerBar )
  22. //{{AFX_MSG_MAP( CMapAnimationDlg )
  23. ON_WM_HSCROLL()
  24. ON_BN_CLICKED(IDC_ANIMATIONPLAY, OnPlay)
  25. ON_BN_CLICKED(IDC_ANIMATIONCREATEKEYFRAME, OnCreateKeyFrame)
  26. ON_UPDATE_COMMAND_UI(IDC_ANIMATIONPLAY, UpdateControl)
  27. ON_UPDATE_COMMAND_UI(IDC_ANIMATIONCREATEKEYFRAME, UpdateControl)
  28. //}}AFX_MSG_MAP
  29. END_MESSAGE_MAP()
  30. //-----------------------------------------------------------------------------
  31. // Purpose: CMapAnimationDlg contructor
  32. //-----------------------------------------------------------------------------
  33. CMapAnimationDlg::CMapAnimationDlg()
  34. {
  35. m_flAnimationDuration = 5.0f;
  36. m_flAnimationStart = 0.0f;
  37. m_flAnimTime = 0.0f;
  38. m_bPlaying = false;
  39. }
  40. static const int ANIMSLIDER_NUMTICS = 100;
  41. //-----------------------------------------------------------------------------
  42. //-----------------------------------------------------------------------------
  43. bool CMapAnimationDlg::Create( CWnd *pParentWnd )
  44. {
  45. //
  46. // create a modeless dialog toolbar
  47. //
  48. if( !( CHammerBar::Create( pParentWnd, IDD, CBRS_RIGHT, IDCB_ANIMATIONBAR ) ) )
  49. {
  50. return false;
  51. }
  52. // to remain consistant with the other toolbars in the editor
  53. SetWindowText( _T( "Animation" ) );
  54. // set dialog bar style
  55. SetBarStyle( GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_FIXED );
  56. // enable docking
  57. EnableDocking( CBRS_ALIGN_ANY );
  58. //
  59. // initialize the dialog items
  60. //
  61. InitTimeSlider();
  62. m_Play.SubclassDlgItem( IDC_ANIMATIONPLAY, this );
  63. // show the dialog
  64. ShowWindow( SW_SHOW );
  65. m_bEnabled = false;
  66. // created successfully
  67. return true;
  68. }
  69. //-----------------------------------------------------------------------------
  70. // Purpose: Called every frame, used to update animation time
  71. //-----------------------------------------------------------------------------
  72. void CMapAnimationDlg::RunFrame( void )
  73. {
  74. if ( m_bPlaying )
  75. {
  76. AdvanceAnimationTime();
  77. }
  78. }
  79. //-----------------------------------------------------------------------------
  80. //-----------------------------------------------------------------------------
  81. void CMapAnimationDlg::InitTimeSlider( void )
  82. {
  83. m_TimeSlider.SubclassDlgItem( IDC_TIMESLIDER, this );
  84. m_TimeSlider.SetRange( 0, ANIMSLIDER_NUMTICS );
  85. m_TimeSlider.SetTicFreq( ANIMSLIDER_NUMTICS / 4 );
  86. m_TimeSlider.SetPos( 0 );
  87. m_TimeSlider.EnableWindow( false );
  88. }
  89. //-----------------------------------------------------------------------------
  90. // Purpose: Sets Enable/Disable state for any controls
  91. // Input : *pCmdUI -
  92. //-----------------------------------------------------------------------------
  93. void CMapAnimationDlg::UpdateControl( CCmdUI *pCmdUI )
  94. {
  95. CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
  96. if ( !pDoc || !m_bEnabled )
  97. {
  98. pCmdUI->Enable( false );
  99. return;
  100. }
  101. else
  102. {
  103. pCmdUI->Enable( true );
  104. }
  105. }
  106. //-----------------------------------------------------------------------------
  107. // Purpose: Communicates to the doc the current animation time
  108. // Input : time -
  109. //-----------------------------------------------------------------------------
  110. void CMapAnimationDlg::UpdateAnimationTime( void )
  111. {
  112. CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
  113. if( !pDoc )
  114. {
  115. return;
  116. }
  117. pDoc->SetAnimationTime( m_flAnimTime );
  118. }
  119. //-----------------------------------------------------------------------------
  120. //-----------------------------------------------------------------------------
  121. void CMapAnimationDlg::OnHScroll( UINT nSBCode, UINT nPos, CScrollBar *pScrollBar )
  122. {
  123. // get the new time from the slider bar
  124. m_flAnimTime = ((float)m_TimeSlider.GetPos() / ANIMSLIDER_NUMTICS) * m_flAnimationDuration;
  125. // stop any playback
  126. PausePlayback();
  127. UpdateAnimationTime();
  128. CHammerBar::OnHScroll( nSBCode, nPos, pScrollBar );
  129. }
  130. //-----------------------------------------------------------------------------
  131. // Purpose: Moves the animation time forward with real time
  132. //-----------------------------------------------------------------------------
  133. void CMapAnimationDlg::OnPlay( void )
  134. {
  135. CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
  136. if ( !pDoc )
  137. {
  138. return;
  139. }
  140. // if we're not playing, start
  141. if ( !m_bPlaying )
  142. {
  143. m_flAnimationStart = pDoc->GetTime() - m_flAnimTime;
  144. m_bPlaying = true;
  145. // change the animation text
  146. SetDlgItemText( IDC_ANIMATIONPLAY, "Stop" );
  147. UpdateAnimationTime();
  148. }
  149. else
  150. {
  151. PausePlayback();
  152. }
  153. }
  154. //-----------------------------------------------------------------------------
  155. // Purpose: pauses the animation playback at the current time
  156. //-----------------------------------------------------------------------------
  157. void CMapAnimationDlg::PausePlayback( void )
  158. {
  159. m_bPlaying = false;
  160. SetDlgItemText( IDC_ANIMATIONPLAY, "Play" );
  161. }
  162. //-----------------------------------------------------------------------------
  163. // Purpose: Creates a new keyframe in the cycle at the current time in the animation
  164. //-----------------------------------------------------------------------------
  165. void CMapAnimationDlg::OnCreateKeyFrame( void )
  166. {
  167. // stop any playback
  168. PausePlayback();
  169. GetHistory()->MarkUndoPosition( NULL, "New Keyframe" );
  170. // get the animating object
  171. CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
  172. const CMapObjectList *pSelection = pDoc->GetSelection()->GetList();
  173. for (int i = 0; i < pSelection->Count(); i++)
  174. {
  175. CMapEntity *ent = dynamic_cast<CMapEntity*>( pSelection->Element( i ) );
  176. if ( ent && ent->IsAnimationController() )
  177. {
  178. // tell the animating object to create a new keyframe
  179. CMapAnimator *anim = ent->GetChildOfType( (CMapAnimator*)NULL );
  180. if ( anim )
  181. {
  182. CMapEntity *pNewEntity = anim->CreateNewKeyFrame( m_flAnimTime );
  183. CMapDoc::GetActiveMapDoc()->AddObjectToWorld( pNewEntity );
  184. GetHistory()->KeepNew( pNewEntity );
  185. // change the selection and then update the view
  186. CMapDoc::GetActiveMapDoc()->SelectObject(pNewEntity, scClear|scSaveChanges );
  187. break;
  188. }
  189. }
  190. }
  191. ResetTimeSlider();
  192. }
  193. //-----------------------------------------------------------------------------
  194. // Purpose: moves the current animation time forward, if currently playing
  195. //-----------------------------------------------------------------------------
  196. void CMapAnimationDlg::AdvanceAnimationTime( void )
  197. {
  198. if ( !m_bPlaying )
  199. return;
  200. CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
  201. if ( !pDoc )
  202. {
  203. return;
  204. }
  205. // make sure the animation is long enough to play
  206. if ( m_flAnimationDuration <= 0.01 )
  207. {
  208. ResetTimeSlider();
  209. return;
  210. }
  211. // calculate the new position along the time slider
  212. m_flAnimTime = pDoc->GetTime() - m_flAnimationStart;
  213. // check to see if we've hit the end of the animation
  214. if ( m_flAnimTime >= m_flAnimationDuration )
  215. {
  216. ResetTimeSlider();
  217. return;
  218. }
  219. // set the new animtion time
  220. m_TimeSlider.SetPos( (m_flAnimTime / m_flAnimationDuration) * ANIMSLIDER_NUMTICS );
  221. UpdateAnimationTime();
  222. }
  223. //-----------------------------------------------------------------------------
  224. // Purpose: Resets the slider bar and all times
  225. //-----------------------------------------------------------------------------
  226. void CMapAnimationDlg::ResetTimeSlider( void )
  227. {
  228. PausePlayback();
  229. m_flAnimTime = 0.0f;
  230. m_flAnimationStart = 0.0f;
  231. m_TimeSlider.SetPos( 0 );
  232. UpdateAnimationTime();
  233. }
  234. //-----------------------------------------------------------------------------
  235. // Purpose: Called whenever the selection changes, so the slider bar can update
  236. // with the selected keyframe info
  237. // Input : &selection -
  238. //-----------------------------------------------------------------------------
  239. void CMapAnimationDlg::SelectionChanged( CMapObjectList &selection )
  240. {
  241. // reset the slider
  242. ResetTimeSlider();
  243. m_bEnabled = false;
  244. // loop through the selection looking for potential animating objects
  245. CMapEntity *ent = NULL;
  246. FOR_EACH_OBJ( selection, pos )
  247. {
  248. ent = dynamic_cast<CMapEntity*>( selection.Element(pos) );
  249. if ( ent )
  250. {
  251. if ( ent->IsAnimationController() && ent->GetChildOfType((CMapAnimator*)NULL) )
  252. {
  253. m_bEnabled = true;
  254. break;
  255. }
  256. }
  257. }
  258. // find out our enabled state
  259. if ( !m_bEnabled )
  260. {
  261. m_TimeSlider.EnableWindow( false );
  262. return;
  263. }
  264. m_TimeSlider.EnableWindow( true );
  265. // set up the slider from the selection
  266. CMapAnimator *anim = ent->GetChildOfType( (CMapAnimator*)NULL );
  267. Assert( anim != NULL );
  268. m_flAnimationDuration = anim->GetRemainingTime();
  269. }