source-engine/hammer/mapanimationdlg.cpp

333 lines
8.8 KiB
C++
Raw Normal View History

2020-04-23 00:56:21 +08:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <stdafx.h>
#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 <tier0/memdbgon.h>
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++)
{
CMapEntity *ent = dynamic_cast<CMapEntity*>( pSelection->Element( i ) );
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 )
{
ent = dynamic_cast<CMapEntity*>( selection.Element(pos) );
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();
}