//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #include #include "GlobalFunctions.h" #include "History.h" #include "MainFrm.h" #include "MapAnimator.h" #include "MapAnimationDlg.h" #include "MapClass.h" #include "MapDoc.h" #include "MapEntity.h" #include "MapWorld.h" #include "hammer.h" #include "Selection.h" // memdbgon must be the last include file in a .cpp file!!! #include BEGIN_MESSAGE_MAP( CMapAnimationDlg, CHammerBar ) //{{AFX_MSG_MAP( CMapAnimationDlg ) ON_WM_HSCROLL() ON_BN_CLICKED(IDC_ANIMATIONPLAY, OnPlay) ON_BN_CLICKED(IDC_ANIMATIONCREATEKEYFRAME, OnCreateKeyFrame) ON_UPDATE_COMMAND_UI(IDC_ANIMATIONPLAY, UpdateControl) ON_UPDATE_COMMAND_UI(IDC_ANIMATIONCREATEKEYFRAME, UpdateControl) //}}AFX_MSG_MAP END_MESSAGE_MAP() //----------------------------------------------------------------------------- // Purpose: CMapAnimationDlg contructor //----------------------------------------------------------------------------- CMapAnimationDlg::CMapAnimationDlg() { m_flAnimationDuration = 5.0f; m_flAnimationStart = 0.0f; m_flAnimTime = 0.0f; m_bPlaying = false; } static const int ANIMSLIDER_NUMTICS = 100; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- bool CMapAnimationDlg::Create( CWnd *pParentWnd ) { // // create a modeless dialog toolbar // if( !( CHammerBar::Create( pParentWnd, IDD, CBRS_RIGHT, IDCB_ANIMATIONBAR ) ) ) { return false; } // to remain consistant with the other toolbars in the editor SetWindowText( _T( "Animation" ) ); // set dialog bar style SetBarStyle( GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_FIXED ); // enable docking EnableDocking( CBRS_ALIGN_ANY ); // // initialize the dialog items // InitTimeSlider(); m_Play.SubclassDlgItem( IDC_ANIMATIONPLAY, this ); // show the dialog ShowWindow( SW_SHOW ); m_bEnabled = false; // created successfully return true; } //----------------------------------------------------------------------------- // Purpose: Called every frame, used to update animation time //----------------------------------------------------------------------------- void CMapAnimationDlg::RunFrame( void ) { if ( m_bPlaying ) { AdvanceAnimationTime(); } } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void CMapAnimationDlg::InitTimeSlider( void ) { m_TimeSlider.SubclassDlgItem( IDC_TIMESLIDER, this ); m_TimeSlider.SetRange( 0, ANIMSLIDER_NUMTICS ); m_TimeSlider.SetTicFreq( ANIMSLIDER_NUMTICS / 4 ); m_TimeSlider.SetPos( 0 ); m_TimeSlider.EnableWindow( false ); } //----------------------------------------------------------------------------- // Purpose: Sets Enable/Disable state for any controls // Input : *pCmdUI - //----------------------------------------------------------------------------- void CMapAnimationDlg::UpdateControl( CCmdUI *pCmdUI ) { CMapDoc *pDoc = CMapDoc::GetActiveMapDoc(); if ( !pDoc || !m_bEnabled ) { pCmdUI->Enable( false ); return; } else { pCmdUI->Enable( true ); } } //----------------------------------------------------------------------------- // Purpose: Communicates to the doc the current animation time // Input : time - //----------------------------------------------------------------------------- void CMapAnimationDlg::UpdateAnimationTime( void ) { CMapDoc *pDoc = CMapDoc::GetActiveMapDoc(); if( !pDoc ) { return; } pDoc->SetAnimationTime( m_flAnimTime ); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void CMapAnimationDlg::OnHScroll( UINT nSBCode, UINT nPos, CScrollBar *pScrollBar ) { // get the new time from the slider bar m_flAnimTime = ((float)m_TimeSlider.GetPos() / ANIMSLIDER_NUMTICS) * m_flAnimationDuration; // stop any playback PausePlayback(); UpdateAnimationTime(); CHammerBar::OnHScroll( nSBCode, nPos, pScrollBar ); } //----------------------------------------------------------------------------- // Purpose: Moves the animation time forward with real time //----------------------------------------------------------------------------- void CMapAnimationDlg::OnPlay( void ) { CMapDoc *pDoc = CMapDoc::GetActiveMapDoc(); if ( !pDoc ) { return; } // if we're not playing, start if ( !m_bPlaying ) { m_flAnimationStart = pDoc->GetTime() - m_flAnimTime; m_bPlaying = true; // change the animation text SetDlgItemText( IDC_ANIMATIONPLAY, "Stop" ); UpdateAnimationTime(); } else { PausePlayback(); } } //----------------------------------------------------------------------------- // Purpose: pauses the animation playback at the current time //----------------------------------------------------------------------------- void CMapAnimationDlg::PausePlayback( void ) { m_bPlaying = false; SetDlgItemText( IDC_ANIMATIONPLAY, "Play" ); } //----------------------------------------------------------------------------- // Purpose: Creates a new keyframe in the cycle at the current time in the animation //----------------------------------------------------------------------------- void CMapAnimationDlg::OnCreateKeyFrame( void ) { // stop any playback PausePlayback(); GetHistory()->MarkUndoPosition( NULL, "New Keyframe" ); // get the animating object CMapDoc *pDoc = CMapDoc::GetActiveMapDoc(); const CMapObjectList *pSelection = pDoc->GetSelection()->GetList(); for (int i = 0; i < pSelection->Count(); i++) { CMapClass *pMapClass = (CUtlReference< CMapClass >)pSelection->Element( i ); CMapEntity *ent = dynamic_cast( pMapClass ); if ( ent && ent->IsAnimationController() ) { // tell the animating object to create a new keyframe CMapAnimator *anim = ent->GetChildOfType( (CMapAnimator*)NULL ); if ( anim ) { CMapEntity *pNewEntity = anim->CreateNewKeyFrame( m_flAnimTime ); CMapDoc::GetActiveMapDoc()->AddObjectToWorld( pNewEntity ); GetHistory()->KeepNew( pNewEntity ); // change the selection and then update the view CMapDoc::GetActiveMapDoc()->SelectObject(pNewEntity, scClear|scSaveChanges ); break; } } } ResetTimeSlider(); } //----------------------------------------------------------------------------- // Purpose: moves the current animation time forward, if currently playing //----------------------------------------------------------------------------- void CMapAnimationDlg::AdvanceAnimationTime( void ) { if ( !m_bPlaying ) return; CMapDoc *pDoc = CMapDoc::GetActiveMapDoc(); if ( !pDoc ) { return; } // make sure the animation is long enough to play if ( m_flAnimationDuration <= 0.01 ) { ResetTimeSlider(); return; } // calculate the new position along the time slider m_flAnimTime = pDoc->GetTime() - m_flAnimationStart; // check to see if we've hit the end of the animation if ( m_flAnimTime >= m_flAnimationDuration ) { ResetTimeSlider(); return; } // set the new animtion time m_TimeSlider.SetPos( (m_flAnimTime / m_flAnimationDuration) * ANIMSLIDER_NUMTICS ); UpdateAnimationTime(); } //----------------------------------------------------------------------------- // Purpose: Resets the slider bar and all times //----------------------------------------------------------------------------- void CMapAnimationDlg::ResetTimeSlider( void ) { PausePlayback(); m_flAnimTime = 0.0f; m_flAnimationStart = 0.0f; m_TimeSlider.SetPos( 0 ); UpdateAnimationTime(); } //----------------------------------------------------------------------------- // Purpose: Called whenever the selection changes, so the slider bar can update // with the selected keyframe info // Input : &selection - //----------------------------------------------------------------------------- void CMapAnimationDlg::SelectionChanged( CMapObjectList &selection ) { // reset the slider ResetTimeSlider(); m_bEnabled = false; // loop through the selection looking for potential animating objects CMapEntity *ent = NULL; FOR_EACH_OBJ( selection, pos ) { CMapClass *pMapClass = (CUtlReference< CMapClass >)selection.Element(pos); ent = dynamic_cast( pMapClass ); if ( ent ) { if ( ent->IsAnimationController() && ent->GetChildOfType((CMapAnimator*)NULL) ) { m_bEnabled = true; break; } } } // find out our enabled state if ( !m_bEnabled ) { m_TimeSlider.EnableWindow( false ); return; } m_TimeSlider.EnableWindow( true ); // set up the slider from the selection CMapAnimator *anim = ent->GetChildOfType( (CMapAnimator*)NULL ); Assert( anim != NULL ); m_flAnimationDuration = anim->GetRemainingTime(); }